diff options
Diffstat (limited to '')
171 files changed, 16548 insertions, 2850 deletions
diff --git a/.github/workflows/make.yml b/.github/workflows/make.yml index 8ea03b7..0d551be 100644 --- a/.github/workflows/make.yml +++ b/.github/workflows/make.yml @@ -11,7 +11,7 @@ jobs: steps: - uses: actions/checkout@v2 - - run: make -C project distrib + - run: SYSTEM=mac make -C project flags distrib - name: Upload distribution uses: actions/upload-artifact@v2 with: diff --git a/project/Makefile b/project/Makefile index cc94e65..691c762 100644 --- a/project/Makefile +++ b/project/Makefile @@ -17,7 +17,7 @@ ## This file is part of the SZS project. ## ## Visit https://szs.wiimm.de/ for project details and sources. ## ## ## -## Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> ## +## Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> ## ## ## ##################################################################### @@ -57,7 +57,7 @@ WPATT_LONG = Wiimms PAT Tool WSTRT_SHORT = wstrt WSTRT_LONG = Wiimms StaticR Tool -VERSION_NUM = 2.26a +VERSION_NUM = 2.27a BETA_VERSION = 0 # 0:off -1:"beta" >0:"beta#" @@ -146,7 +146,7 @@ DEFINES1 += -DUIOPT_INDEX_SIZE=310 # define max number of options (default 0x100 CFLAGS += -std=gnu99 -fomit-frame-pointer -fno-strict-aliasing -funroll-loops CFLAGS += -Wall -Wno-parentheses -Wno-unused-function -CFLAGS += -Wno-deprecated-declarations +CFLAGS += -Wno-deprecated-declarations -Wno-gnu-variable-sized-type-not-at-end CFLAGS += -O3 -Isrc -I$(UI) -I. DEPFLAGS += -MMD @@ -154,7 +154,7 @@ DEPFLAGS += -MMD #--- system depedent flags & libs ifeq ($(SYSTEM),mac) - CFLAGS += -I/usr/local/include + CFLAGS += -I/usr/local/include -Wno-typedef-redefinition endif ifeq ($(SYSTEM_LINUX),1) @@ -169,14 +169,11 @@ ifeq ($(SYSTEM),cygwin) LDFLAGS += -static-libgcc endif -#ifeq ($(HAVE_PCRE),1) -#ifeq ($(STATIC),1) -# LIBS += $(PCRE_A) -#else -# LIBS += -lpcre -#endif -# DEFINES1 += -DHAVE_PCRE=1 -#endif +ifeq ($(shell expr $(GCC_VERSION) '>=' 7.0 ),1) +ifneq ($(SYSTEM),mac) + CFLAGS += -Wno-format-truncation +endif +endif ifeq ($(HAVE_SHA),1) ifeq ($(SYSTEM_LINUX),1) @@ -421,6 +418,7 @@ default_rule: all ############################################################################### # local definitions +-include ./dclib/Makefile.rules -include makefiles-local/Makefile.local.$(SYSTEM) -include Makefile.user @@ -596,15 +594,6 @@ c++ clean++: do_clean+ st # #-------------------------- -.PHONY: dclib -dclib: - @echo "DCLIB_MYSQL=$(DCLIB_MYSQL)" - @echo "DCLIB_FLAGS=$(DCLIB_FLAGS)" - @echo "DCLIB_O=$(DCLIB_O)" - -# -#-------------------------- - .PHONY : debug debug: @printf "$(LOGFORMAT)" enable debug "-> define -DDEBUG" @@ -746,29 +735,30 @@ doc+: doc info .PHONY : flags flags: - @echo "" - @echo "SYSTEM: |$(SYSTEM)|$(SYSTEM2)|" - @echo "" - @echo "DEFINES: $(DEFINES)" - @echo "" - @echo "CFLAGS: $(CFLAGS)" - @echo "" - @echo "LDFLAGS: $(LDFLAGS)" - @echo "" - @echo "OPT_STATIC: $(OPT_STATIC)" - @echo "" - @echo "LIBS: $(LIBS)" - @echo "" - @echo "C_OBJECTS: $(C_OBJECTS)" - @echo "" - @echo "UI_FILES: $(UI_FILES)" - @echo "" - @echo "ALL_TOOLS: $(ALL_TOOLS)" - @echo "" - @echo "WRAPPER_TOOLS: $(WRAPPER_TOOLS)" - @echo "" - @echo "ALL_TOOLS_X: $(ALL_TOOLS_X)" - @echo "" + @echo "" + @echo "SYSTEM: |$(SYSTEM)|$(SYSTEM2)|" + @echo "GCC: |$(GCC_VERSION)|" + @echo "" + @echo "DEFINES: $(DEFINES)" + @echo "" + @echo "CFLAGS: $(CFLAGS)" + @echo "" + @echo "LDFLAGS: $(LDFLAGS)" + @echo "" + @echo "OPT_STATIC: $(OPT_STATIC)" + @echo "" + @echo "LIBS: $(LIBS)" + @echo "" + @echo "C_OBJECTS: $(C_OBJECTS)" + @echo "" + @echo "UI_FILES: $(UI_FILES)" + @echo "" + @echo "ALL_TOOLS: $(ALL_TOOLS)" + @echo "" + @echo "WRAPPER_TOOLS: $(WRAPPER_TOOLS)" + @echo "" + @echo "ALL_TOOLS_X: $(ALL_TOOLS_X)" + @echo "" # #-------------------------- diff --git a/project/dclib/Makefile.inc b/project/dclib/Makefile.inc index d386594..45fc2a5 100644 --- a/project/dclib/Makefile.inc +++ b/project/dclib/Makefile.inc @@ -1,18 +1,46 @@ + ########################################################################### + # # + # _____ ____ # + # | __ \ / __ \ _ _ _____ # + # | | \ \ / / \_\ | | | | _ \ # + # | | \ \| | | | | | |_| | # + # | | | || | | | | | ___/ # + # | | / /| | __ | | | | _ \ # + # | |__/ / \ \__/ / | |___| | |_| | # + # |_____/ \____/ |_____|_|_____/ # + # # + # Wiimms source code library # + # # + ########################################################################### + #------------------------------------------------------------------------------ # standard object files -DCLIB_O = dclib-basics.o dclib-cli.o dclib-color.o dclib-numeric.o \ - dclib-file.o dclib-option.o dclib-regex.o \ - dclib-utf8.o dclib-shift-jis.o \ - dclib-vector.o dclib-tables.o dclib-ui.o \ - dclib-xdump.o dclib-debug.o -DCLIB_O1 := lib-dol.o lib-bmg.o lib-mkw.o -DCLIB_O2 := lib-wiimmfi.o lib-gamespy.o lib-natneg.o +DCLIB_O := dclib-basics.o dclib-cli.o dclib-color.o dclib-numeric.o \ + dclib-file.o dclib-option.o dclib-regex.o \ + dclib-utf8.o dclib-shift-jis.o \ + dclib-vector.o dclib-tables.o dclib-ui.o \ + dclib-xdump.o dclib-debug.o + +DCLIB_O_MKW := lib-dol.o lib-bmg.o lib-mkw.o + +DCLIB_O_WIIMMFI := lib-wiimmfi.o lib-gamespy.o lib-natneg.o + +# legacy +DCLIB_O1 := $(DCLIB_O_MKW) +DCLIB_O2 := $(DCLIB_O_WIIMMFI) DCLIB_PRIVATE := dclib-terminal* dclib-command* lib-wiimmfi* lib-gamespy* lib-natneg* #------------------------------------------------------------------------------ +# if DCLIB_THREADS not set: disable it + +ifeq ($(origin DCLIB_THREAD), undefined) + DCLIB_THREAD := 0 +endif + +#------------------------------------------------------------------------------ # if DCLIB_MYSQL not set: enable it if file 'mysql.h' is found ifeq ($(origin DCLIB_MYSQL), undefined) @@ -43,8 +71,13 @@ endif #------------------------------------------------------------------------------ # add libraries and guardian macros +ifeq ($(DCLIB_THREAD),1) + DCLIB_O += dclib-thread.o + DCLIB_FLAGS += -DDCLIB_THREAD=1 +endif + ifeq ($(DCLIB_NETWORK),1) - DCLIB_O += dclib-network.o + DCLIB_O += dclib-network.o dclib-punycode.o DCLIB_FLAGS += -DDCLIB_NETWORK=1 else DCLIB_MYSQL := 0 diff --git a/project/dclib/dclib-basics.c b/project/dclib/dclib-basics.c index fdea8fc..964b5d2 100644 --- a/project/dclib/dclib-basics.c +++ b/project/dclib/dclib-basics.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -39,6 +39,7 @@ #include <time.h> #include <stdio.h> #include <stddef.h> +#include <signal.h> #include <errno.h> #include <sys/time.h> #include <fcntl.h> @@ -118,6 +119,14 @@ const char ThinLine300_3[901] = // 300 * '─' (U+2500) + NULL "──────────────────────────────────────────────────" "──────────────────────────────────────────────────"; +const char DoubleLine300_3[901] = // 300 * '═' (U+2550) + NULL + "══════════════════════════════════════════════════" + "══════════════════════════════════════════════════" + "══════════════════════════════════════════════════" + "══════════════════════════════════════════════════" + "══════════════════════════════════════════════════" + "══════════════════════════════════════════════════"; + /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -301,9 +310,9 @@ int GetProgramPath #ifdef __APPLE__ //--- read apple path of executable - + extern int _NSGetExecutablePath( char* buf, uint32_t * bufsize ); - + uint32_t size = sizeof(path); if (!_NSGetExecutablePath(path,&size)) { @@ -312,7 +321,7 @@ int GetProgramPath return StringCopyS(buf,buf_size,path) - buf; } -#else // !__APPLE__ +#else // !__APPLE__ //--- read files of /proc/... @@ -332,7 +341,7 @@ int GetProgramPath return StringCopyS(buf,buf_size,path) - buf; } -#endif // !__APPLE__ +#endif // !__APPLE__ //--- analyze argv0 @@ -433,8 +442,8 @@ char * StringCopyEM ( char * buf, ccp buf_end, ccp src, size_t max_copy ) // RESULT: end of copied string pointing to NULL // 'src' may be a NULL pointer. - ASSERT(buf); - ASSERT(buf<buf_end); + DASSERT(buf); + DASSERT(buf<buf_end); buf_end--; if ( max_copy >= 0 && buf + max_copy < buf_end ) buf_end = buf + max_copy; @@ -536,6 +545,54 @@ char * StringCat3A ( ccp src1, ccp src2, ccp src3 ) /////////////////////////////////////////////////////////////////////////////// +ccp StringCenterE +( + char * buf, // result buffer; if NULL, circ-buf is used + ccp buf_end, // end of 'buf', NULL if buf==NULL + ccp src, // source string + int width // wanted width +) +{ + if (!src) + src = ""; + int n2 = strlen(src); + if ( n2 >= width ) + { + if (!buf) + return CopyCircBuf(src,n2+1); + + StringCopyEM(buf,buf_end,src,n2); + return buf; + } + + n2 = width - n2; + int n1 = n2/2; + n2 -= n1; + + if (!buf) + { + buf = GetCircBuf(width+1); + buf_end = buf + width; + } + else + buf_end--; + + char *dest = buf; + while ( n1-- > 0 && dest < buf_end ) + *dest++ = ' '; + + while ( *src && dest < buf_end ) + *dest++ = *src++; + + while ( n2-- > 0 && dest < buf_end ) + *dest++ = ' '; + + *dest = 0; + return buf; +}; + +/////////////////////////////////////////////////////////////////////////////// + char * StringLowerE ( char * buf, ccp buf_end, ccp src ) { // RESULT: end of copied string pointing to NULL @@ -658,6 +715,166 @@ char * MemUpperS ( char * buf, size_t buf_size, mem_t src ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// Signals & Sleep /////////////// +/////////////////////////////////////////////////////////////////////////////// + +volatile int SIGINT_level = 0; +volatile int SIGHUP_level = 0; +volatile int SIGALRM_level = 0; +volatile int SIGCHLD_level = 0; +volatile int SIGPIPE_level = 0; +volatile int SIGUSR1_level = 0; +volatile int SIGUSR2_level = 0; + +// no timout for SIGPIPE +u_sec_t SIGINT_sec = 0; +u_sec_t SIGHUP_sec = 0; +u_sec_t SIGALRM_sec = 0; +u_sec_t SIGCHLD_sec = 0; +u_sec_t SIGUSR1_sec = 0; +u_sec_t SIGUSR2_sec = 0; + +int SIGINT_level_max = 3; +bool ignore_SIGINT = false; +bool ignore_SIGHUP = false; + +int redirect_signal_pid = 0; +LogFile_t log_signal_file = {0}; + +/////////////////////////////////////////////////////////////////////////////// + +static void inc_sig_handler ( volatile int *level, volatile uint *sec ) +{ + DASSERT(level); + DASSERT(sec); + + const uint now = GetTimeSec(false); + + if ( now - *sec > 30 ) + *level = 0; + *sec = now; + (*level)++; +} + +/////////////////////////////////////////////////////////////////////////////// + +static void sig_handler ( int signum ) +{ + fflush(stdout); + static bool had_sigpipe = false; + + if (redirect_signal_pid) + { + kill(redirect_signal_pid,signum); + return; + } + + switch(signum) + { + case SIGINT: + if (ignore_SIGINT) + break; + // fall through + + case SIGTERM: + inc_sig_handler(&SIGINT_level,&SIGINT_sec); + ccp signame = signum == SIGINT ? "INT" : "TERM"; + if ( SIGINT_level > 1 ) + PrintLogFile(&log_signal_file,"#SIGNAL %s: level set to %d/%d\n", + signame, SIGINT_level, SIGINT_level_max ); + if ( SIGINT_level >= SIGINT_level_max ) + { + PrintLogFile(&log_signal_file,"#SIGNAL %s: TERMINATE IMMEDIATELY!\n",signame); + exit(0); + } + break; + + case SIGHUP: + if (!ignore_SIGHUP) + { + inc_sig_handler(&SIGHUP_level,&SIGHUP_sec); + PrintLogFile(&log_signal_file,"#SIGNAL HUP: level set to %d\n",SIGHUP_level); + } + break; + + case SIGCHLD: + SIGCHLD_level++; + PrintLogFile(&log_signal_file,"#SIGNAL CHLD: level set to %d\n",SIGCHLD_level); + break; + + case SIGALRM: + inc_sig_handler(&SIGALRM_level,&SIGALRM_sec); + PrintLogFile(&log_signal_file,"#SIGNAL ALRM: level set to %d\n",SIGALRM_level); + break; + + case SIGUSR1: + inc_sig_handler(&SIGUSR1_level,&SIGUSR1_sec); + PrintLogFile(&log_signal_file,"#SIGNAL USR1: level set to %d\n",SIGUSR1_level); + break; + + case SIGUSR2: + inc_sig_handler(&SIGUSR2_level,&SIGUSR2_sec); + PrintLogFile(&log_signal_file,"#SIGNAL USR2: level set to %d\n",SIGUSR2_level); + break; + + case SIGPIPE: + SIGPIPE_level++; + if (!had_sigpipe) + { + PrintLogFile(&log_signal_file,"#SIGNAL SIGPIPE: %d\n",SIGPIPE_level); + had_sigpipe = true; + } + if ( SIGPIPE_level >= 5 ) + { + PrintLogFile(&log_signal_file,"#SIGNAL SIGPIPE: TERMINATE IMMEDIATELY!\n"); + exit(0); + } + break; + + default: + PrintLogFile(&log_signal_file,"#SIGNAL: %d\n",signum); + } + fflush(stderr); +} + +/////////////////////////////////////////////////////////////////////////////// + +void SetupSignalHandler ( int max_sigint_level, FILE *log_file ) +{ + SIGINT_level_max = max_sigint_level; + if (log_file) + { + log_signal_file.log = log_file; + log_signal_file.flush = true; + } + + static const int sigtab[] = { SIGTERM, SIGINT, SIGHUP, SIGALRM, SIGPIPE, -1 }; + int i; + for ( i = 0; sigtab[i] >= 0; i++ ) + { + struct sigaction sa; + memset(&sa,0,sizeof(sa)); + sa.sa_handler = &sig_handler; + sigaction(sigtab[i],&sa,0); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +int SleepNSec ( s_nsec_t nsec ) +{ + if ( nsec > 0 ) + { + struct timespec ts; + ts.tv_sec = nsec / NSEC_PER_SEC; + ts.tv_nsec = nsec % NSEC_PER_SEC; + return nanosleep(&ts,0); + } + return 0; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// PathCat*() /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -1165,6 +1382,67 @@ uint CountEqual ( cvp m1, cvp m2, uint size ) /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// +char * SkipEscapes ( ccp str ) +{ + if (str) + { + while ( *str == '\e' ) + { + str++; + if ( *str == '[' ) + str++; + while ( *str > 0 && *str < 0x40 ) + str++; + if (*str) + str++; + } + } + return (char*)str; +} + +//----------------------------------------------------------------------------- + +char * SkipEscapesE ( ccp str, ccp end ) +{ + if (str) + { + if (!end) + return SkipEscapes(str); + + while ( str < end && *str == '\e' ) + { + str++; + if ( str < end && *str == '[' ) + str++; + while ( str < end && *str > 0 && *str < 0x40 ) + str++; + if ( str < end ) + str++; + } + } + return (char*)str; +} + +//----------------------------------------------------------------------------- + +char * SkipEscapesS ( ccp str, int size ) +{ + return size < 0 ? SkipEscapes(str) : SkipEscapesE(str,str+strlen(str)); +} + +//----------------------------------------------------------------------------- + +mem_t SkipEscapesM ( mem_t mem ) +{ + mem_t res; + res.ptr = SkipEscapesE(mem.ptr,mem.ptr+mem.len); + res.len = mem.ptr + mem.len - res.ptr; + return res; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + int ReplaceToBuf ( // returns -1 on error (buf to small) or the length of the resulting string. @@ -1576,8 +1854,8 @@ char * PrintID /////////////// circ buf /////////////// /////////////////////////////////////////////////////////////////////////////// -static char circ_buf[CIRC_BUF_SIZE]; -static char *circ_ptr = circ_buf; +static __thread char circ_buf[CIRC_BUF_SIZE]; +static __thread char *circ_ptr = 0; /////////////////////////////////////////////////////////////////////////////// @@ -1597,6 +1875,8 @@ char * GetCircBuf // ==> ERROR0(ERR_OUT_OF_MEMORY) ) { + if (!circ_ptr) + circ_ptr = circ_buf; DASSERT( circ_ptr >= circ_buf && circ_ptr <= circ_buf + sizeof(circ_buf) ); buf_size = buf_size + 3 & ~3; @@ -1725,6 +2005,8 @@ void ReleaseCircBuf uint release_size // number of bytes to give back from end ) { + if (!circ_ptr) + circ_ptr = circ_buf; DASSERT( circ_ptr >= circ_buf && circ_ptr <= circ_buf + sizeof(circ_buf) ); if ( end_buf == circ_ptr @@ -1738,6 +2020,94 @@ void ReleaseCircBuf // /////////////////////////////////////////////////////////////////////////////// +/////////////// PrintMode_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void SetupPrintMode ( PrintMode_t * pm ) +{ + DASSERT(pm); + + //-- stdout + + if (!pm->fout) + { + pm->fout = stdout; + pm->cout = colout; + } + if (!pm->cout) + pm->cout = GetColorSet0(); + + + //-- stderr + + //if (!pm->ferr) pm->ferr = stderr; + if (!pm->cerr) + pm->cerr = GetColorSet0(); + + + //-- stdlog + + if (pm->flog) + { + if (!pm->clog) + pm->clog = GetColorSet0(); + } + else if (pm->ferr) + { + pm->flog = pm->ferr; + pm->clog = pm->cerr; + } + else + { + pm->flog = pm->fout; + pm->clog = pm->cout; + } + + + //-- misc + + if (!pm->prefix) pm->prefix = EmptyString; + if (!pm->eol) pm->eol = "\n"; + + pm->indent = NormalizeIndent(pm->indent); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// get line by list /////////////// +/////////////////////////////////////////////////////////////////////////////// + +ccp GetLineByListHelper ( const int *list, ccp beg, ccp mid, ccp end, ccp line ) +{ + DASSERT(list); + DASSERT(beg); + DASSERT(mid); + DASSERT(end); + DASSERT(line); + + char buf[CIRC_BUF_MAX_ALLOC+20]; + char *endbuf = buf + CIRC_BUF_MAX_ALLOC; + char *dest = buf; + + for (;;) + { + int wd = *list++; + if ( wd < 0 ) + break; + + dest = StringCopyE(dest,endbuf,beg); + beg = mid; + while ( wd-- > 0 ) + dest = StringCopyE(dest,endbuf,line); + } + + dest = StringCopyE(dest,endbuf,end); + *dest++ = 0; + return dest <= endbuf ? CopyCircBuf(buf,dest-buf) : EmptyString; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// struct FastBuf_t /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -2343,6 +2713,473 @@ int ScanSplitArg // /////////////////////////////////////////////////////////////////////////////// +/////////////// PointerList_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void ResetPointerMgr ( PointerList_t *pl ) +{ + if (pl) + { + FREE(pl->list); + InitializePointerMgr(pl,pl->grow); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void AddToPointerMgr ( PointerList_t *pl, const void *info ) +{ + DASSERT(pl); + if (!info) + return; + + // no duplicates! + for ( int i = 0; i < pl->used; i++ ) + if ( pl->list[i] == info ) + return; + + if ( pl->used == pl->size ) + { + if ( pl->grow < 10 ) + pl->grow = 10; + pl->size += pl->size/2 + pl->grow; + pl->list = REALLOC ( pl->list, (pl->size+1) * sizeof(*pl->list) ); + } + DASSERT( pl->used < pl->size ); + void **dest = pl->list + pl->used++; + *dest++ = (void*)info; + *dest = 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +void AddListToPointerMgr ( PointerList_t *pl, const void **list, int n_elem ) +{ + if (list) + { + if ( n_elem < 0 ) + while (*list) + AddToPointerMgr(pl,*list++); + else + while( --n_elem >= 0 ) + AddToPointerMgr(pl,*list++); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void ** DupPointerMgr ( PointerList_t *pl, bool reset ) +{ + DASSERT(pl); + void **dest = MEMDUP( pl->list, (pl->used+1) * sizeof(*dest) ); + if (reset) + ResetPointerMgr(pl); + return dest; +} + +/////////////////////////////////////////////////////////////////////////////// + +void ** ReplacePointerMgr + ( PointerList_t *pl, bool reset, const PointerList_t **old_list ) +{ + FREE(old_list); + return DupPointerMgr(pl,reset); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// ArgManager_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void ResetArgManager ( ArgManager_t *am ) +{ + static char *null_list[] = {0}; + + if (am) + { + if (am->size) + { + uint i; + for ( i = 0; i < am->argc; i++ ) + FreeString(am->argv[i]); + if ( am->argv != null_list ) + FREE(am->argv); + } + + const typeof(am->force_case) force_case = am->force_case; + memset(am,0,sizeof(*am)); + am->force_case = force_case; + am->argv = null_list; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void SetupArgManager + ( ArgManager_t *am, LowerUpper_t force_case, int argc, char ** argv, bool clone ) +{ + DASSERT(am); + memset(am,0,sizeof(*am)); + am->force_case = force_case; + if (clone) + CloneArgManager(am,argc,argv); + else + AttachArgManager(am,argc,argv); +} + +/////////////////////////////////////////////////////////////////////////////// + +void AttachArgManager ( ArgManager_t *am, int argc, char ** argv ) +{ + DASSERT(am); + ResetArgManager(am); + am->argc = argc; + am->argv = argv; +} + +/////////////////////////////////////////////////////////////////////////////// + +void CloneArgManager ( ArgManager_t *am, int argc, char ** argv ) +{ + DASSERT(am); + AttachArgManager(am,argc,argv); + PrepareEditArgManager(am,0); +} + +/////////////////////////////////////////////////////////////////////////////// + +void CopyArgManager ( ArgManager_t *dest, const ArgManager_t *src ) +{ + DASSERT(dest); + if (!src) + ResetArgManager(dest); + else if( dest != src ) + AttachArgManager(dest,src->argc,src->argv); +} + +/////////////////////////////////////////////////////////////////////////////// + +void MoveArgManager ( ArgManager_t *dest, ArgManager_t *src ) +{ + DASSERT(dest); + ResetArgManager(dest); + if (src) + { + dest->argv = src->argv; + dest->argc = src->argc; + dest->size = src->size; + memset(src,0,sizeof(*src)); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void PrepareEditArgManager ( ArgManager_t *am, int needed_space ) +{ + DASSERT(am); + + uint new_size = am->argc; + if ( needed_space > 0 ) + new_size += needed_space; + new_size = GetGoodAllocSize2(new_size+(new_size>>4)+10,sizeof(*am->argv)); + PRINT("PrepareEditArgManager(,%d) n=%d, size: %d -> %d\n", + needed_space, am->argc, am->size, new_size ); + + if (am->size) + am->argv = REALLOC(am->argv,sizeof(*am->argv)*new_size); + else + { + char **old = am->argv; + am->argv = MALLOC(sizeof(*am->argv)*new_size); + + uint i; + for ( i = 0; i < am->argc; i++ ) + am->argv[i] = old[i] ? STRDUP(old[i]) : 0; + } + am->size = new_size - 1; + DASSERT( am->argc <= am->size ); + am->argv[am->argc] = 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +uint AppendArgManager ( ArgManager_t *am, ccp arg1, ccp arg2, bool move_arg ) +{ + DASSERT(am); + PRINT("AppendArgManager(,%s,%s,%d)\n",arg1,arg2,move_arg); + return InsertArgManager(am,am->argc,arg1,arg2,move_arg); +} + +/////////////////////////////////////////////////////////////////////////////// + +static char ** insert_arg_manager + ( ArgManager_t *am, char **dest, ccp p_arg, bool move_arg ) +{ + DASSERT(am); + if (p_arg) + { + char *arg = (char*)p_arg; + if (!move_arg) + arg = STRDUP(arg); + + if ( am->force_case == LOUP_LOWER || am->force_case == LOUP_UPPER ) + { + ccp end = arg + strlen(arg) + 1; + if (am->force_case == LOUP_LOWER) + StringLowerE(arg,end,arg); + else + StringUpperE(arg,end,arg); + } + *dest++ = arg; + } + return dest; +} + +//----------------------------------------------------------------------------- + +uint InsertArgManager + ( ArgManager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg ) +{ + PRINT("InsertArgManager(,%d,%s,%s,%d)\n",pos,arg1,arg2,move_arg); + + pos = CheckIndex1(am->argc,pos); + const int n = (arg1!=0) + (arg2!=0); + if (n) + { + PrepareEditArgManager(am,n); + DASSERT( pos>=0 && pos <= am->argc ); + char **dest = am->argv + pos; + if ( pos < am->argc ) + memmove( dest+n, dest, (u8*)(am->argv+am->argc) - (u8*)dest ); + + dest = insert_arg_manager(am,dest,arg1,move_arg); + dest = insert_arg_manager(am,dest,arg2,move_arg); + + am->argc += n; + am->argv[am->argc] = 0; + } + return pos+n; +} + +/////////////////////////////////////////////////////////////////////////////// + +uint ReplaceArgManager + ( ArgManager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg ) +{ + PRINT("ReplaceArgManager(,%d,%s,%s,%d)\n",pos,arg1,arg2,move_arg); + + pos = CheckIndex1(am->argc,pos); + const int n = (arg1!=0) + (arg2!=0); + if (n) + { + PrepareEditArgManager(am,n); + DASSERT( pos>=0 && pos <= am->argc ); + char **dest = am->argv + pos; + if (arg1) + { + if ( pos++ < am->argc ) + FreeString(*dest); + *dest++ = move_arg ? (char*)arg1 : STRDUP(arg1); + } + if (arg2) + { + if ( pos++ < am->argc ) + FreeString(*dest); + *dest++ = move_arg ? (char*)arg2 : STRDUP(arg2); + } + if ( pos > am->argc ) + { + am->argc = pos; + am->argv[am->argc] = 0; + } + } + return pos; +} + +/////////////////////////////////////////////////////////////////////////////// + +uint RemoveArgManager ( ArgManager_t *am, int pos, int count ) +{ + DASSERT(am); + + #if HAVE_PRINT + const int oldpos = pos; + #endif + const int n = CheckIndexC(am->argc,&pos,count); + PRINT("RemoveArgManager(,%d,%d) : remove n=%d: %d..%d\n", + oldpos, count, n, pos, pos+n ); + + DASSERT( pos >= 0 && pos <= am->argc ); + DASSERT( n >= 0 && pos+n <= am->argc ); + + if ( n > 0 ) + { + PrepareEditArgManager(am,0); + char **dest = am->argv + pos; + + uint i; + for ( i = 0; i <n; i++ ) + FreeString(dest[i]); + am->argc -= n; + memmove( dest, dest+n, (u8*)(am->argv+am->argc) - (u8*)dest ); + am->argv[am->argc] = 0; + } + return pos; +} + +/////////////////////////////////////////////////////////////////////////////// + +uint ScanSimpleArgManager ( ArgManager_t *am, ccp src ) +{ + uint count = 0; + if (src) + { + for(;;) + { + while ( *src == ' ' || *src == '\t' ) + src++; + if (!*src) + break; + + ccp start = src; + while ( *src && *src != ' ' && *src != '\t' ) + src++; + + ccp arg = MEMDUP(start,src-start); + AppendArgManager(am,arg,0,true); + } + } + return count; +} + +/////////////////////////////////////////////////////////////////////////////// + +uint ScanQuotedArgManager ( ArgManager_t *am, ccp src, bool is_utf8 ) +{ + uint count = 0; + if (src) + { + char buf[10000], *bufend = buf + sizeof(buf) - 2; + + for(;;) + { + while ( *src == ' ' || *src == '\t' ) + src++; + if (!*src) + break; + + char *dest = buf; + while ( dest < bufend ) + { + if ( *src == '\'' || *src == '\"' ) + { + uint scanned; + dest += ScanEscapedString(dest,bufend-dest,src,-1,is_utf8,-1,&scanned); + src += scanned; + } + else + { + while ( dest < bufend && *src && *src != ' ' && *src != '\t' + && *src != '\'' && *src != '\"' ) + { + if ( *src == '\\' && src[1] ) + src++; + *dest++ = *src++; + } + } + if ( !*src || *src == ' ' || *src == '\t' ) + break; + } + ccp arg = MEMDUP(buf,dest-buf); + AppendArgManager(am,arg,0,true); + } + } + return count; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool CheckFilterArgManager ( const ArgManager_t *filter, ccp name ) +{ + if ( !name || !*name ) + return false; + + if (!filter->argc) + return true; + + char buf[200]; + if ( filter->force_case == LOUP_LOWER ) + { + StringLowerS(buf,sizeof(buf),name); + name = buf; + } + else if ( filter->force_case == LOUP_UPPER ) + { + StringUpperS(buf,sizeof(buf),name); + name = buf; + } + + bool fallback_status = true; + for ( int i = 0; i < filter->argc; i++ ) + { + ccp arg = filter->argv[i]; + const bool status = *arg != '/'; + if (status) + fallback_status = false; + else + arg++; + + const uint len = strlen(arg); + if ( *arg == '=' ) + { + if ( !strcmp(arg+1,name) ) + return status; + } + else if ( *arg == '^' ) + { + if ( len > 1 && !strncmp(arg+1,name,len-1) ) + return status; + } + else + if ( len && strstr(name,arg) ) + return status; + } + + return fallback_status; +} + +/////////////////////////////////////////////////////////////////////////////// + +void DumpArgManager ( FILE *f, int indent, const ArgManager_t *am, ccp title ) +{ + if ( !f || !am ) + return; + + indent = NormalizeIndent(indent); + if (title) + fprintf(f,"%*s" "ArgManager[%s]: N=%d", + indent,"", title, am->argc ); + else + fprintf(f,"%*s" "ArgManager: N=%d", indent,"", am->argc ); + + if (am->size) + fprintf(f,"/%u\n",am->size); + else + fputc('\n',f); + + if (am->argc) + { + char buf[10]; + int fw = snprintf(buf,sizeof(buf),"%u",am->argc-1)+2; + + uint i; + for ( i = 0; i < am->argc; i++ ) + fprintf(f,"%*s%*u: |%s|\n", indent,"", fw,i, am->argv[i] ); + } +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// struct mem_t /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -2487,16 +3324,80 @@ mem_t MemCat3A ( const mem_t m1, const mem_t m2, const mem_t m3 ) return res; } +/////////////////////////////////////////////////////////////////////////////// +// UTF8 support + +mem_t MidMem8 ( const mem_t src, int begin, int count ) +{ + if ( !src.ptr || !src.len ) + return src; + + ccp src_end = src.ptr + src.len; + const int u8len = ScanUTF8LengthE(src.ptr,src_end); + begin = CheckIndex1(u8len,begin); + if ( count < 0 ) + { + count = -count; + begin -= count; + if ( begin < 0 ) + { + count += begin; + begin = 0; + } + } + + mem_t res; + res.ptr = SkipUTF8CharE(src.ptr,src_end,begin); + const int max = u8len - begin; + res.len = SkipUTF8CharE( res.ptr, src_end, count < max ? count : max ) - res.ptr; + return res; +} + +/////////////////////////////////////////////////////////////////////////////// + +mem_t ExtractMem8 ( const mem_t src, int begin, int end ) +{ + if ( !src.ptr || !src.len ) + return src; + + ccp src_end = src.ptr + src.len; + const int u8len = ScanUTF8LengthE(src.ptr,src_end); + const int count = CheckIndex2(u8len,&begin,&end); + + mem_t res; + res.ptr = SkipUTF8CharE( src.ptr, src_end, begin ); + res.len = SkipUTF8CharE( res.ptr, src_end, count ) - res.ptr; + return res; +} + +/////////////////////////////////////////////////////////////////////////////// + +mem_t ExtractEndMem8 ( const mem_t src, int begin, int end ) +{ + if ( !src.ptr || !src.len ) + return src; + + ccp src_end = src.ptr + src.len; + const int u8len = ScanUTF8LengthE(src.ptr,src_end); + const int count = CheckIndex2End(u8len,&begin,&end); + + mem_t res; + res.ptr = SkipUTF8CharE( src.ptr, src_end, begin ); + res.len = SkipUTF8CharE( res.ptr, src_end, count ) - res.ptr; + return res; +} + // /////////////////////////////////////////////////////////////////////////////// /////////////// struct exmem_t /////////////// +/////////////////////////////////////////////////////////////////////////////// exmem_t EmptyExMem = {{EmptyString,0},0,false,false,false,false}; exmem_t NullExMem = {{0,0},0,false,false,false,false}; /////////////////////////////////////////////////////////////////////////////// -void FreeExMem ( const exmem_t *em ) +void ResetExMem ( const exmem_t *em ) { if (em) { @@ -2508,6 +3409,23 @@ void FreeExMem ( const exmem_t *em ) /////////////////////////////////////////////////////////////////////////////// +void FreeExMem ( const exmem_t *em ) +{ + if (em) + { + if (em->is_alloced) + { + exmem_t *em2 = (exmem_t*)em; + FreeString(em2->data.ptr); + em2->data.ptr = 0; + em2->data.len = 0; + em2->is_alloced = false; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + void FreeExMemCM ( const exmem_t *em, CopyMode_t copy_mode ) { if ( em && copy_mode == CPM_MOVE ) @@ -2604,7 +3522,41 @@ void AssignExMem ( exmem_t *dest, const exmem_t *source, CopyMode_t copy_mode ) /////////////////////////////////////////////////////////////////////////////// -exmem_t CopyExMemS ( ccp string, int slen, CopyMode_t copy_mode ) +void AssignExMemS ( exmem_t *dest, cvp source, int slen, CopyMode_t copy_mode ) +{ + if (dest) + { + ccp free_str = dest->is_alloced ? dest->data.ptr : 0; + const bool dest_key_alloced = dest->is_key_alloced; + memset(dest,0,sizeof(*dest)); + dest->is_key_alloced = dest_key_alloced; + + if (source) + { + dest->data.len = slen < 0 ? strlen(source) : slen; + switch (copy_mode) + { + case CPM_COPY: + dest->data.ptr = MEMDUP(source,dest->data.len); + dest->is_alloced = true; + break; + + case CPM_MOVE: + dest->is_alloced = true; + // fall through + case CPM_LINK: + dest->data.ptr = source; + break; + } + } + FreeString(free_str); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +#if 0 // [[obsolete]] since 2021-11 +exmem_t CopyExMemS ( cvp string, int slen, CopyMode_t copy_mode ) { exmem_t em = {{0}}; @@ -2630,6 +3582,7 @@ exmem_t CopyExMemS ( ccp string, int slen, CopyMode_t copy_mode ) return em; } +#endif /////////////////////////////////////////////////////////////////////////////// @@ -5038,10 +5991,10 @@ int ScanKeywordOffOn const KeywordTab_t KeyTab_OFF_AUTO_ON[] = { { OFFON_OFF, "OFF", "-1", 0 }, - { OFFON_OFF, "DISABLED", 0, 0 }, + { OFFON_OFF, "DISABLED", "NO", 0 }, { OFFON_AUTO, "AUTO", "0", 0 }, { OFFON_ON, "ON", "1", 0 }, - { OFFON_ON, "ENABLED", 0, 0 }, + { OFFON_ON, "ENABLED", "YES", 0 }, { OFFON_FORCE, "FORCE", "2", 0 }, { 0,0,0,0 } }; @@ -6589,16 +7542,42 @@ exmem_key_t * AppendEML ( exmem_list_t * eml, ccp key, CopyMode_t cm_key, /////////////////////////////////////////////////////////////////////////////// -bool RemoveEML ( exmem_list_t * eml, ccp key ) +bool RemoveByIndexEML ( exmem_list_t * eml, int index ) +{ + if ( index < 0 ) + index += eml->used; + if ( index >= 0 && index < eml->used ) + { + DASSERT( eml->used > 0 ); + eml->used--; + exmem_key_t * dest = eml->list + index; + if (dest->data.is_key_alloced) + FreeString(dest->key); + FreeExMem(&dest->data); + if (eml->used) + memmove(dest,dest+1,(eml->used-index)*sizeof(*dest)); + else + eml->is_unsorted = false; + return true; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool RemoveByKeyEML ( exmem_list_t * eml, ccp key ) { bool found; - uint idx = FindHelperEML(eml,key,&found); + const uint index = FindHelperEML(eml,key,&found); + #if 1 + return found && RemoveByIndexEML(eml,index); + #else // [[obsolete]] 2021-11 if (found) { DASSERT(eml->used); eml->used--; - DASSERT( idx <= eml->used ); - exmem_key_t * dest = eml->list + idx; + DASSERT( index <= eml->used ); + exmem_key_t * dest = eml->list + index; if (dest->data.is_key_alloced) FreeString(dest->key); FreeExMem(&dest->data); @@ -6608,6 +7587,7 @@ bool RemoveEML ( exmem_list_t * eml, ccp key ) eml->is_unsorted = false; } return found; + #endif } /////////////////////////////////////////////////////////////////////////////// @@ -6849,6 +7829,560 @@ void AddStandardSymbolsEML ( exmem_list_t * eml, bool overwrite ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// MultiColumn /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void ResetMultiColumn ( MultiColumn_t *mc ) +{ + if (mc) + { + ResetEML(&mc->list); + memset(mc,0,sizeof(*mc)); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +exmem_key_t * PutLineMC + ( MultiColumn_t *mc, uint opt, ccp key, ccp value, CopyMode_t cm_value ) +{ + DASSERT(mc); + DASSERT(key); + DASSERT(value); + + exmem_t data = ExMemByString(value); + exmem_key_t *res = AppendEML( &mc->list, key, CPM_LINK, &data, cm_value ); + res->data.attrib = opt; + return res; +} + +/////////////////////////////////////////////////////////////////////////////// + +exmem_key_t * PrintLineMC + ( MultiColumn_t *mc, uint opt, ccp key, ccp format, ... ) +{ + char buf[1000]; + va_list arg; + va_start(arg,format); + vsnprintf(buf,sizeof(buf),format,arg); + va_end(arg); + return PutLineMC(mc,opt,key,buf,CPM_COPY); +} + +/////////////////////////////////////////////////////////////////////////////// +// [[mc_len_t]] + +typedef struct mc_len_t +{ + int key; // key length + int val; // val length +} +mc_len_t; + +//----------------------------------------------------------------------------- +// [[mc_param_t]] + +#define MULTI_COLUMN_MAX_COLS 100 + +typedef struct mc_param_t +{ + FILE *f; // output file + const ColorSet_t + *colset; // color set for the frame + int debug; // debug level: 0..2 + + int frame_mode; // 0:ASCII, 1:single line, 2:double line + ccp prefix; // line prefix + int prefix_fw; // field width of 'prefix' + int indent; // indention excluding prefix + ccp sep; // separator for frame_mode 0 and 1 + int sep_fw; // field width of 'sep' + ccp eol; // end-of-line string + int fw; // total field width + + ccp head_key; // header string for key column + int head_key_fw; // field width of 'head_key' + ccp head_val; // header string for value column + int head_val_fw; // field width of 'head_val' + + int row_size; // additional size for a row + int col_size; // additional size for a column + + int n_rows; // number of rows + int n_cols; // number of columns + + mc_len_t *len_list; // list of estimatest lengths + mc_len_t fw_col[MULTI_COLUMN_MAX_COLS]; + // field width for each column +} +mc_param_t; + +//----------------------------------------------------------------------------- + +static void mc_print_sep ( const mc_param_t *p ) +{ + fprintf(p->f,"%s%*s",p->prefix,p->indent,""); + + const mc_len_t *fw = p->fw_col; + for ( int col = 0; col < p->n_cols; col++, fw++ ) + { + if (col) + fputs("-+-",p->f); + fprintf(p->f,"%.*s",fw->key+fw->val+p->sep_fw,Minus300); + } + fputs(p->eol,p->f); +} + +//----------------------------------------------------------------------------- + +static void mc_print_line1 ( const mc_param_t *p, ccp template ) +{ + fprintf(p->f,"%s%*s%s%.3s", + p->prefix, p->indent,"", + p->colset->heading, template ); + + const mc_len_t *fw = p->fw_col; + for ( int col = 0; col < p->n_cols; col++, fw++ ) + { + if (col) + fprintf(p->f,"%.3s",template+3); + fprintf(p->f,"%.*s", 3*(fw->key+fw->val+p->sep_fw+2), ThinLine300_3 ); + } + + fprintf(p->f,"%.3s%s%s",template+6,p->colset->reset,p->eol); +} + +//----------------------------------------------------------------------------- + +static void mc_print_line2 ( const mc_param_t *p, ccp template ) +{ + fprintf(p->f,"%s%*s%s%.3s", + p->prefix, p->indent,"", + p->colset->heading, template ); + + const mc_len_t *fw = p->fw_col; + for ( int col = 0; col < p->n_cols; col++, fw++ ) + { + if (col) + fprintf(p->f,"%.3s",template+6); + fprintf(p->f,"%.*s%.3s%.*s", + 3*(fw->key+2), DoubleLine300_3, + template+3, + 3*(fw->val+2), DoubleLine300_3 ); + } + + fprintf(p->f,"%.3s%s%s",template+9,p->colset->reset,p->eol); +} + +//----------------------------------------------------------------------------- + +int PrintMultiColumn ( const MultiColumn_t *mc ) +{ + const u_usec_t start_time = GetTimerUSec(); + if ( !mc || !mc->list.used ) + return -1; + + + //--- setup + + mc_param_t p = {0}; + p.f = mc->f ? mc->f : stdout; + p.colset = mc->colset ? mc->colset : GetColorSet0(); + p.debug = mc->debug; + p.indent = NormalizeIndent(mc->indent); + + p.prefix = mc->prefix; + if (p.prefix) + p.prefix_fw = ScanEUTF8Length(p.prefix); + else + { + p.prefix = EmptyString; + p.prefix_fw = 0; + } + + p.sep = mc->sep ? mc->sep : " "; + p.sep_fw = ScanEUTF8Length(p.sep); + p.eol = mc->eol ? mc->eol : "\n"; + p.fw = !mc->fw ? 79 : mc->fw > 10 ? mc->fw : 10; + + if ( mc->print_header ) + { + p.head_key = mc->head_key ? mc->head_key : "Name"; + p.head_key_fw = strlene8(p.head_key); + + p.head_val = mc->head_val ? mc->head_val : "Value"; + p.head_val_fw = strlene8(p.head_val); + } + else + { + p.head_key = p.head_val = EmptyString; + // p.head_key_fw = p.head_val_fw = 0; // initial value + } + + switch (mc->frame_mode) + { + case 0: + p.frame_mode = 0; + p.row_size = -3; + p.col_size = 3 + p.sep_fw; + break; + + case 1: + p.frame_mode = 1; + p.row_size = 1; + p.col_size = 3 + p.sep_fw; + break; + + default: + p.frame_mode = 2; + p.row_size = 1; + p.col_size = 6; + break; + } + + if ( p.debug > 1 ) + fprintf(p.f, + "#> debug=%d, pre=%s, indent=%d, eol=%s, fw=%d," + " print[Fhf]=%d%d%d, min_rows=%d, max_cols=%d%s", + p.debug, QuoteStringS(p.prefix,0,CHMD__MODERN), + p.indent, QuoteStringS(p.eol,0,CHMD__MODERN), p.fw, + p.frame_mode, mc->print_header, mc->print_footer, + mc->min_rows, mc->max_cols, p.eol ); + + + //--- find min width + + p.len_list = MALLOC( mc->list.used * sizeof(*p.len_list) ); + mc_len_t *len_ptr = p.len_list; + + int min_fw = INT_MAX; + const exmem_key_t *list_end = mc->list.list + mc->list.used; + for ( const exmem_key_t *ptr = mc->list.list; ptr < list_end; ptr++ ) + { + len_ptr->key = strlene8(ptr->key); + len_ptr->val = strlene8(ptr->data.data.ptr); + const int len = len_ptr->key + len_ptr->val; + if ( min_fw > len ) + min_fw = len; + len_ptr++; + } + min_fw += p.col_size; + + const int avail_chars = p.fw - p.prefix_fw - p.indent - p.row_size; + int max_cols = ( avail_chars + p.col_size - 1 ) / min_fw; + if ( max_cols > MULTI_COLUMN_MAX_COLS ) + max_cols = MULTI_COLUMN_MAX_COLS; + + const int min_rows = mc->min_rows > 1 ? mc->min_rows : 1; + const int temp = ( mc->list.used + min_rows - 1 ) / min_rows + 1; + if ( temp > 0 && max_cols > temp ) + max_cols = temp; + + if ( p.debug > 1 ) + fprintf(p.f, + "#> src-lines=%d, min-fw=%d, min-rows=%d, max-cols=%d/%d%s", + mc->list.used, min_fw, + min_rows, max_cols, MULTI_COLUMN_MAX_COLS, p.eol ); + + + //--- evaluate number of columns + + for ( p.n_cols = max_cols; p.n_cols > 0; p.n_cols-- ) + { + memset(p.fw_col,0,sizeof(p.fw_col)); + mc_len_t len = { p.head_key_fw, p.head_val_fw }; + + p.n_rows = ( mc->list.used - 1 ) / p.n_cols + 1; + p.n_cols = ( mc->list.used - 1 ) / p.n_rows + 1; + if ( p.debug > 1 ) + fprintf(p.f, "#> … try %2u columns and %3u rows, %3u cells total%s", + p.n_cols, p.n_rows, p.n_cols*p.n_rows, p.eol ); + + int idx, row, col, total_fw = 0; + len_ptr = p.len_list; + for ( idx = row = col = 0; idx < mc->list.used; idx++, len_ptr++ ) + { + if ( len.key < len_ptr->key ) + len.key = len_ptr->key; + if ( len.val < len_ptr->val ) + len.val = len_ptr->val; + + if ( ++row >= p.n_rows ) + { + total_fw += len.key + len.val + p.col_size; + if ( total_fw > avail_chars ) + break; + p.fw_col[col] = len; + + len.key = p.head_key_fw; + len.val = p.head_val_fw; + row = 0; + col++; + } + } + if ( col < p.n_cols ) + { + p.fw_col[col] = len; + total_fw += len.key + len.val + p.col_size; + } + if ( total_fw <= avail_chars ) + break; + } + + if ( p.n_cols < 1 ) + { + p.n_rows = mc->list.used; + p.n_cols = 1; + } + + if ( p.debug > 1 ) + { + fprintf(p.f,"#> cols=%d, rows=%d, fw", p.n_cols, p.n_rows ); + int total = 0; + const mc_len_t *fw = p.fw_col; + for ( int col = 0; col < p.n_cols; col++, fw++ ) + { + fprintf( p.f, "%c%u+%u", col ? ',' : '=', fw->key, fw->val ); + total += fw->key + fw->val + p.col_size; + } + fprintf(p.f," = %d/%d%s",total,avail_chars,p.eol); + } + + //--- print columns + + const u_usec_t output_time = GetTimerUSec(); + + uint out_lines = p.n_rows; + //---------------------- + if ( p.frame_mode >= 2 ) + //---------------------- + { + mc_print_line2(&p,"╔╤╦╗"); + out_lines++; + + if (mc->print_header) + { + fprintf(p.f,"%s%*s%s║%s",p.prefix,p.indent,"",p.colset->heading,p.colset->reset); + const mc_len_t *fw = p.fw_col; + for ( int col = 0; col < p.n_cols; col++, fw++ ) + fprintf(p.f," %s %s│%s %s %s║%s", + AlignEUTF8ToCircBuf(p.head_key,-fw->key,fw->key), + p.colset->heading, p.colset->reset, + AlignEUTF8ToCircBuf(p.head_val,-fw->val,fw->val), + p.colset->heading, p.colset->reset ); + fputs(p.eol,p.f); + + mc_print_line2(&p,"╠╪╬╣"); + out_lines += 2; + } + + for ( int row = 0; row < p.n_rows; row++ ) + { + fprintf(p.f,"%s%*s%s║%s",p.prefix,p.indent,"",p.colset->heading,p.colset->reset); + const exmem_key_t *ptr = mc->list.list + row; + const mc_len_t *fw = p.fw_col; + for ( int col = 0; col < p.n_cols; col++, ptr += p.n_rows, fw++ ) + { + if ( ptr < list_end ) + { + fprintf(p.f," %s %s│%s ", + AlignEUTF8ToCircBuf(ptr->key,-fw->key,fw->key), + p.colset->heading, p.colset->reset ); + + if ( ptr->data.attrib > 1 ) + { + const int fw_attrib = ptr->data.attrib < fw->val ? ptr->data.attrib : fw->val; + const int fw_val = p.len_list[ptr-mc->list.list].val; + if ( fw_attrib <= fw_val ) + goto std2; + fprintf(p.f,"%s%*s %s║%s", + AlignEUTF8ToCircBuf(ptr->data.data.ptr,fw_attrib,fw_attrib), + fw_attrib - fw->val, "", + p.colset->heading, p.colset->reset ); + } + else + { + std2:; + const int fw_val = ptr->data.attrib ? -fw->val : fw->val; + fprintf(p.f,"%s %s║%s", + AlignEUTF8ToCircBuf(ptr->data.data.ptr,fw_val,fw->val), + p.colset->heading, p.colset->reset ); + } + } + else + fprintf(p.f," %*s %s│%s %*s %s║%s", + fw->key, "", p.colset->heading, p.colset->reset, + fw->val, "", p.colset->heading, p.colset->reset ); + } + fputs(p.eol,p.f); + } + + mc_print_line2(&p,"╚╧╩╝"); + out_lines++; + } + //--------------------------- + else if ( p.frame_mode >= 1 ) + //--------------------------- + { + mc_print_line1(&p,"┌┬┐"); + out_lines++; + + if (mc->print_header) + { + fprintf(p.f,"%s%*s%s│%s",p.prefix,p.indent,"",p.colset->heading,p.colset->reset); + const mc_len_t *fw = p.fw_col; + for ( int col = 0; col < p.n_cols; col++, fw++ ) + fprintf(p.f," %s%s%s %s│%s", + AlignEUTF8ToCircBuf(p.head_key,-fw->key,fw->key), + p.sep, + AlignEUTF8ToCircBuf(p.head_val,-fw->val,fw->val), + p.colset->heading, p.colset->reset ); + + fputs(p.eol,p.f); + + mc_print_line1(&p,"├┼┤"); + out_lines += 2; + } + + for ( int row = 0; row < p.n_rows; row++ ) + { + fprintf(p.f,"%s%*s%s│%s",p.prefix,p.indent,"",p.colset->heading,p.colset->reset); + const exmem_key_t *ptr = mc->list.list + row; + const mc_len_t *fw = p.fw_col; + for ( int col = 0; col < p.n_cols; col++, ptr += p.n_rows, fw++ ) + { + if ( ptr < list_end ) + { + fprintf(p.f," %s%s", + AlignEUTF8ToCircBuf(ptr->key,-fw->key,fw->key), + p.sep ); + + if ( ptr->data.attrib > 1 ) + { + const int fw_attrib = ptr->data.attrib < fw->val ? ptr->data.attrib : fw->val; + const int fw_val = p.len_list[ptr-mc->list.list].val; + if ( fw_attrib <= fw_val ) + goto std1; + fprintf(p.f,"%s%*s %s│%s", + AlignEUTF8ToCircBuf(ptr->data.data.ptr,fw_attrib,fw_attrib), + fw_attrib - fw->val, "", + p.colset->heading, p.colset->reset ); + } + else + { + std1:; + const int fw_val = ptr->data.attrib ? -fw->val : fw->val; + fprintf(p.f,"%s %s│%s", + AlignEUTF8ToCircBuf(ptr->data.data.ptr,fw_val,fw->val), + p.colset->heading, p.colset->reset ); + } + } + else + fprintf(p.f," %*s %s│%s", + fw->key + fw->val + p.sep_fw, "", + p.colset->heading, p.colset->reset ); + } + fputs(p.eol,p.f); + } + + mc_print_line1(&p,"└┴┘"); + out_lines++; + } + //------------------- + else // !p.frame_mode + //------------------- + { + if (mc->print_header) + { + mc_print_sep(&p); + + fprintf(p.f,"%s%*s",p.prefix,p.indent,""); + const mc_len_t *fw = p.fw_col; + for ( int col = 0; col < p.n_cols; col++, fw++ ) + { + if (col) + fputs(" | ",p.f); + fprintf(p.f,"%s%s%s", + AlignEUTF8ToCircBuf(p.head_key,-fw->key,fw->key), + p.sep, + AlignEUTF8ToCircBuf(p.head_val,-fw->val,fw->val) ); + } + fputs(p.eol,p.f); + out_lines += 2; + } + + if ( mc->print_header || mc->print_footer ) + { + mc_print_sep(&p); + out_lines++; + } + + for ( int row = 0; row < p.n_rows; row++ ) + { + fprintf(p.f,"%s%*s",p.prefix,p.indent,""); + const exmem_key_t *ptr = mc->list.list + row; + const mc_len_t *fw = p.fw_col; + for ( int col = 0; col < p.n_cols; col++, ptr += p.n_rows, fw++ ) + { + if (col) + fputs(" | ",p.f); + if ( ptr < list_end ) + { + fprintf(p.f,"%s%s", + AlignEUTF8ToCircBuf(ptr->key,-fw->key,fw->key), + p.sep ); + + + if ( ptr->data.attrib > 1 ) + { + const int fw_attrib = ptr->data.attrib < fw->val ? ptr->data.attrib : fw->val; + const int fw_val = p.len_list[ptr-mc->list.list].val; + if ( fw_attrib <= fw_val ) + goto std0; + fprintf(p.f,"%s%*s", + AlignEUTF8ToCircBuf(ptr->data.data.ptr,fw_attrib,fw_attrib), + fw_attrib - fw->val, "" ); + } + else + { + std0:; + const int fw_val = ptr->data.attrib ? -fw->val : fw->val; + fputs(AlignEUTF8ToCircBuf(ptr->data.data.ptr,fw_val,fw->val),p.f); + } + } + } + fputs(p.eol,p.f); + } + + if (mc->print_footer) + { + mc_print_sep(&p); + out_lines++; + } + } + //--------------------- + // end-if !p.frame_mode + //--------------------- + + + //--- terminate + + if ( p.debug > 0 ) + { + const u_usec_t now = GetTimerUSec(); + fprintf(p.f,"#> setup in %llu us, %u ouput lines in %llu us, total %llu us%s", + output_time - start_time, + out_lines, now - output_time, + now - start_time, + p.eol ); + } + + FREE(p.len_list); + return out_lines; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// Memory Maps /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -8638,6 +10172,84 @@ int opt_new = 0; /////////////////////////////////////////////////////////////////////////////// +ccp GetIpModeName ( IpMode_t ipm ) +{ + switch (ipm) + { + case IPV4_ONLY: return "IPv4 only"; + case IPV6_ONLY: return "IPv6 only"; + case IPV4_FIRST: return "IPv4 first"; + case IPV6_FIRST: return "IPv6 first"; + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +ipv4_t GetIP4Mask ( int bits ) +{ + return bits > 0 && bits < 32 + ? htonl( 0xffffffffu << (32-bits) ) + : bits ? 0xffffffffu : 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +ipv6_t GetIP6Mask ( int bits ) +{ + ipv6_t ip6; + memset(&ip6,~0,sizeof(ip6)); + if ( bits >= 0 && bits < 128 ) + { + int idx = bits/32; + bits -= idx*32; + const u32 mask = htonl( bits ? 0xffffffffu << (32-bits) : 0 ); + ip6.v32[idx++] &= mask; + while ( idx < 4 ) + ip6.v32[idx++] = 0; + } + return ip6; +} + +/////////////////////////////////////////////////////////////////////////////// + +int GetBitsByMask4 ( ipv4_t ip4_nbo ) +{ + const int res = FindHighest0BitBE(&ip4_nbo,4); + return 31-res; +} + +/////////////////////////////////////////////////////////////////////////////// + +int GetBitsByMask6 ( ipv6_t ip6_nbo ) +{ + const int res = FindHighest0BitBE(&ip6_nbo,16); + return 127-res; +} + +/////////////////////////////////////////////////////////////////////////////// + +int GetBitsBySA ( sockaddr_t *sa, int return_on_error ) +{ + if (sa) + { + if ( sa->sa_family == AF_INET ) + { + sockaddr_in4_t *sa4 = (sockaddr_in4_t*)sa; + return GetBitsByMask4(sa4->sin_addr.s_addr); + } + + if ( sa->sa_family == AF_INET6 ) + { + sockaddr_in6_t *sa6 = (sockaddr_in6_t*)sa; + return GetBitsByMask6(*(ipv6_t*)&sa6->sin6_addr); + } + } + return return_on_error; +} + +/////////////////////////////////////////////////////////////////////////////// + uint CreateUniqueIdN ( int range ) { static uint unique_id = 1; diff --git a/project/dclib/dclib-basics.h b/project/dclib/dclib-basics.h index 95e47bb..47827c7 100644 --- a/project/dclib/dclib-basics.h +++ b/project/dclib/dclib-basics.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -39,6 +39,7 @@ #include <sys/types.h> #include <arpa/inet.h> +#include <sys/un.h> #include <limits.h> #include <stdlib.h> #include <stdio.h> @@ -65,8 +66,13 @@ #define SIZEOFRANGE(type,a,b) \ ( offsetof(type,b) + sizeof(((type*)0)->b) - offsetof(type,a) ) -#define PTR_DISTANCE(a,b) ( (u8*)(a) - (u8*)(b) ) -#define PTR_DISTANCE_INT(a,b) ( (int)( (u8*)(a) - (u8*)(b) )) +#define END_OF_VAR(v) ((void*)( (char*)(v) + sizeof(v) )) + +#define PTR_DISTANCE(a,b) ( (char*)(a) - (char*)(b) ) +#define PTR_DISTANCE_INT(a,b) ( (int)( (char*)(a) - (char*)(b) )) + +#define GET_INT_SIGN(type) ({ typeof(type) a=-1; a>0 ? 1 : -1; }) +#define GET_INT_TYPE(type) ((int)sizeof(type)*GET_INT_SIGN(type)) // /////////////////////////////////////////////////////////////////////////////// @@ -79,9 +85,16 @@ #else #define HAVE_CLOCK_GETTIME 0 #endif - + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// external types /////////////// /////////////////////////////////////////////////////////////////////////////// +typedef struct ColorSet_t ColorSet_t; +typedef struct RestoreState_t RestoreState_t; +typedef struct LogFile_t LogFile_t; + // /////////////////////////////////////////////////////////////////////////////// /////////////// bits /////////////// @@ -141,6 +154,7 @@ static inline uint Count1Bits64 ( u64 data ) } /////////////////////////////////////////////////////////////////////////////// +// return -1 if bit not found int FindLowest0BitBE ( cvp addr, uint size ); int FindLowest1BitBE ( cvp addr, uint size ); @@ -788,6 +802,20 @@ mem_t BehindMem ( const mem_t src, ccp ref ); //----------------------------------------------------------------------------- +// UTF8 support + +mem_t MidMem8 ( const mem_t src, int begin, int count ); +mem_t ExtractMem8 ( const mem_t src, int begin, int end ); +mem_t ExtractEndMem8 ( const mem_t src, int begin, int end ); + +static mem_t LeftMem8 ( const mem_t src, int count ) + { return ExtractMem8(src,0,count); } + +static mem_t RightMem8 ( const mem_t src, int count ) + { return ExtractEndMem8(src,-count,0); } + +//----------------------------------------------------------------------------- + // Alloc dest buffer and terminate with 0. // If m*.len < 0, then use strlen(). @@ -800,7 +828,7 @@ int CmpMem ( const mem_t s1, const mem_t s2 ); int StrCmpMem ( const mem_t mem, ccp str ); bool LeftStrCmpMemEQ ( const mem_t mem, ccp str ); -// free a string if str is not NULL|EmptyString|MinusString +// free a string if str is !NULL | !EmptyString | !MinusString | !IsCircBuf() void FreeString ( ccp str ); static inline void FreeMem ( mem_t *mem ) @@ -886,24 +914,39 @@ static inline exmem_t ExMemByStringE ( ccp str, ccp end ) return em; } -static inline exmem_t ExMemByS ( ccp str, int len ) +static inline exmem_t ExMemByS ( cvp str, int len ) { exmem_t em = { .data={ str, len }, .is_original=true }; return em; } -static inline exmem_t ExMemByE ( ccp str, ccp end ) +static inline exmem_t ExMemByE ( cvp str, cvp end ) { - exmem_t em = { .data={ str, end-str }, .is_original=true }; + exmem_t em = { .data={ str, (u8*)end-(u8*)str }, .is_original=true }; + return em; +} + +static inline exmem_t ExMemCalloc ( int size ) +{ + char *data = CALLOC(size,1); + exmem_t em = { .data={ data, size }, .is_original=true, .is_alloced=true }; + return em; +} + +static inline exmem_t ExMemDup ( cvp src, int size ) +{ + char *data = MEMDUP(src,size); + exmem_t em = { .data={ data, size+1 }, .is_original=true, .is_alloced=true }; return em; } //----------------------------------------------------------------------------- // interface -// 'em' maybe modified ignoring 'const' -void FreeExMem ( const exmem_t *em ); -void FreeExMemCM ( const exmem_t *em, CopyMode_t copy_mode ); // free if CPM_MOVE +// 'em' can be modified ignoring 'const' +void ResetExMem ( const exmem_t *em ); +void FreeExMem ( const exmem_t *em ); +void FreeExMemCM ( const exmem_t *em, CopyMode_t copy_mode ); // free on CPM_MOVE exmem_t AllocExMemS ( @@ -917,13 +960,17 @@ exmem_t AllocExMemS static inline exmem_t AllocExMemM ( mem_t src, bool try_circ, mem_t orig ) { return AllocExMemS(src.ptr,src.len,try_circ,orig.ptr,orig.len); } -void AssignExMem ( exmem_t *dest, const exmem_t *source, CopyMode_t copy_mode ); +void AssignExMem ( exmem_t *dest, const exmem_t *source, CopyMode_t copy_mode ); +void AssignExMemS ( exmem_t *dest, cvp source, int slen, CopyMode_t copy_mode ); + static inline exmem_t CopyExMem ( const exmem_t *source, CopyMode_t copy_mode ) { exmem_t em = {{0}}; AssignExMem(&em,source,copy_mode); return em; } -exmem_t CopyExMemS ( ccp string, int slen, CopyMode_t copy_mode ); +static inline exmem_t CopyExMemS ( cvp source, int slen, CopyMode_t copy_mode ) + { exmem_t em = {{0}}; AssignExMemS(&em,source,slen,copy_mode); return em; } + static inline exmem_t CopyExMemM ( const mem_t source, CopyMode_t copy_mode ) - { return CopyExMemS(source.ptr,source.len,copy_mode); } + { exmem_t em = {{0}}; AssignExMemS(&em,source.ptr,source.len,copy_mode); return em; } ccp PrintExMem ( const exmem_t * em ); // print to circ-buf @@ -1176,6 +1223,39 @@ uint PurgeCircBuf ( CircBuf_t *cb ); // /////////////////////////////////////////////////////////////////////////////// +/////////////// PrintMode_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[PrintMode_t]] + +typedef struct PrintMode_t +{ + FILE *fout; // NULL (stdout) or output file + const ColorSet_t + *cout; // NULL (no colors) or color set for 'fout' + + FILE *ferr; // NULL or error file + const ColorSet_t + *cerr; // NULL (no colors) or color set for 'ferr' + + FILE *flog; // if NULL: use 'ferr' or 'fout' as fallback + const ColorSet_t + *clog; // NULL (no colors) or color set for 'flog' + // if 'flog' is copied, use related 'col*' + + ccp prefix; // NULL (no prefix) or line prefix + ccp eol; // NULL (LF) or end-of-line string + int indent; // indention after prefix + int debug; // debug level (ignored if <=0) + + int mode; // user defined print mode + bool compact; // TRUE: print compact (e.g. no empty lines for readability) +} +PrintMode_t; + +void SetupPrintMode ( PrintMode_t * pm ); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// split strings /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -1280,6 +1360,7 @@ extern const char Slash200[201]; // 200 * '/' + NULL // UTF-8 => 3 bytes per char extern const char ThinLine300_3[901]; // 300 * '─' (U+2500) + NULL +extern const char DoubleLine300_3[901]; // 300 * '═' (U+2550) + NULL //----------------------------------------------------------------------------- @@ -1336,9 +1417,14 @@ char * StringCat3E ( char * buf, ccp buf_end, ccp src1, ccp src2, ccp src3 ); char * StringCat2A ( ccp src1, ccp src2 ); char * StringCat3A ( ccp src1, ccp src2, ccp src3 ); -static inline char * StringCopySMem ( char * buf, size_t bufsize, mem_t mem ) +// center string +ccp StringCenterE ( char * buf, ccp buf_end, ccp src, int width ); +static inline ccp StringCenterS ( char *buf, size_t bufsize, ccp src, int width ) + { return StringCenterE(buf,buf+bufsize,src,width); } + +static inline char * StringCopySMem ( char *buf, size_t bufsize, mem_t mem ) { return StringCopySM(buf,bufsize,mem.ptr,mem.len); } -static inline char * StringCopyEMem ( char * buf, ccp buf_end, mem_t mem ) +static inline char * StringCopyEMem ( char *buf, ccp buf_end, mem_t mem ) { return StringCopyEM(buf,buf_end,mem.ptr,mem.len); } char * StringLowerS ( char * buf, size_t bufsize, ccp src ); @@ -1357,6 +1443,12 @@ int StrNumCmp ( ccp a, ccp b ); // count the number of equal bytes and return a value of 0 to SIZE uint CountEqual ( cvp m1, cvp m2, uint size ); +// skip ESC & well known escape sequences (until noc-escape) +char * SkipEscapes ( ccp str ); +char * SkipEscapesE ( ccp str, ccp end ); +char * SkipEscapesS ( ccp str, int size ); +mem_t SkipEscapesM ( mem_t mem ); + // Concatenate path + path, return pointer to buf // Return pointer to buf or path1|path2|buf or alloced string char *PathCatBufPP ( char *buf, size_t bufsize, ccp path1, ccp path2 ); @@ -1495,12 +1587,14 @@ char * PrintID /////////////// circ buf /////////////// /////////////////////////////////////////////////////////////////////////////// -#define CIRC_BUF_MAX_ALLOC 0x0400 // request limit -#define CIRC_BUF_SIZE 0x4000 // internal buffer size +#define CIRC_BUF_MAX_ALLOC 0x0400 // request limit +#define CIRC_BUF_SIZE 0x4000 // internal buffer size // returns true if 'ptr' points into circ buffer => ignored by FreeString() bool IsCircBuf ( cvp ptr ); +//----------------------------------------------------------------------------- + char * GetCircBuf ( // Never returns NULL, but always ALIGN(4) @@ -1510,6 +1604,21 @@ char * GetCircBuf // ==> ERROR0(ERR_OUT_OF_MEMORY) ); +static inline wchar_t * GetCircBufW +( + // Never returns NULL, but always ALIGN(4) + + u32 buf_size // wanted buffer size (wchar elements), + // caller must add 1 for NULL-term + // if final buf_size > CIRC_BUF_MAX_ALLOC: + // ==> ERROR0(ERR_OUT_OF_MEMORY) +) +{ + return (wchar_t*)GetCircBuf(buf_size*sizeof(wchar_t)); +} + +//----------------------------------------------------------------------------- + char * CopyCircBuf ( // Never returns NULL, but always ALIGN(4) @@ -1563,6 +1672,28 @@ void ReleaseCircBuf // /////////////////////////////////////////////////////////////////////////////// +/////////////// get line by list /////////////// +/////////////////////////////////////////////////////////////////////////////// + +ccp GetLineByListHelper ( const int *list, ccp beg, ccp mid, ccp end, ccp line ); + +static inline ccp GetTopLineByList ( const int *list ) +{ + return GetLineByListHelper(list,"┌","┬","┐","─"); +} + +static inline ccp GetMidLineByList ( int *list ) +{ + return GetLineByListHelper(list,"├","┼","┤","─"); +} + +static inline ccp GetBottomLineByList ( int *list ) +{ + return GetLineByListHelper(list,"└","┴","┘","─"); +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// struct IntMode_t /////////////// /////////////////////////////////////////////////////////////////////////////// // [[IntMode_t]] @@ -1631,6 +1762,75 @@ ccp GetIntModeName ( IntMode_t mode ); // /////////////////////////////////////////////////////////////////////////////// +/////////////// lt/eq/gt /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[compare_operator_t]] + +typedef enum compare_operator_t +{ + COP_LT = 1, + COP_EQ = 2, + COP_GT = 4, + + COP_NE = COP_LT | COP_GT, + COP_LE = COP_LT | COP_EQ, + COP_GE = COP_GT | COP_EQ, + + COP_FALSE = 0, + COP_TRUE = COP_LT | COP_EQ | COP_GT, +} +__attribute__ ((packed)) compare_operator_t; + +//----------------------------------------------------------------------------- + +char * ScanCompareOp ( compare_operator_t *dest_op, ccp arg ); +ccp GetCompareOpName ( compare_operator_t op ); + +static inline compare_operator_t NegateCompareOp ( compare_operator_t op ) + { return op ^ COP_TRUE; } + +bool CompareByOpStat ( int stat, compare_operator_t op ); +bool CompareByOpINT ( int a, compare_operator_t op, int b ); +bool CompareByOpUINT ( uint a, compare_operator_t op, uint b ); +bool CompareByOpI64 ( s64 a, compare_operator_t op, s64 b ); +bool CompareByOpU64 ( u64 a, compare_operator_t op, u64 b ); +bool CompareByOpFLT ( float a, compare_operator_t op, float b ); +bool CompareByOpDBL ( double a, compare_operator_t op, double b ); + +static inline bool CompareByOpS ( ccp a, compare_operator_t op, ccp b ) + { return CompareByOpStat(strcmp(a,b),op); } + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// LOWER/AUTO/UPPER /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[LowerUpper_t]] + +typedef enum LowerUpper_t +{ + LOUP_ERROR = -99, + LOUP_LOWER = -1, + LOUP_AUTO = 0, + LOUP_UPPER = 1, +} +LowerUpper_t; + +extern const KeywordTab_t KeyTab_LOWER_AUTO_UPPER[]; + +int ScanKeywordLowerAutoUpper +( + // returns one of LOUP_* + + ccp arg, // argument to scan + int on_empty, // return this value on empty + uint max_num, // >0: additionally accept+return number <= max_num + ccp object // NULL (silent) or object for error messages +); + +ccp GetKeywordLowerAutoUpper ( LowerUpper_t value ); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// struct FastBuf_t /////////////// /////////////////////////////////////////////////////////////////////////////// // [[FastBuf_t]] @@ -1682,6 +1882,7 @@ ccp GetFastBufStatus ( const FastBuf_t *fb ); int ReserveSpaceFastBuf ( FastBuf_t *fb, uint size ); char * GetSpaceFastBuf ( FastBuf_t *fb, uint size ); +// if size<0: use strlen(source) instead uint InsertFastBuf ( FastBuf_t *fb, int index, cvp source, int size ); char * AppendFastBuf ( FastBuf_t *fb, cvp source, int size ); char * WriteFastBuf ( FastBuf_t *fb, uint offset, cvp source, int size ); @@ -1833,39 +2034,152 @@ int ScanSplitArg // /////////////////////////////////////////////////////////////////////////////// -/////////////// arg_manager_t /////////////// +/////////////// PointerList_t /////////////// /////////////////////////////////////////////////////////////////////////////// -// [[arg_manager_t]] +// [[PointerList_t]] -typedef struct arg_manager_t +typedef struct PointerList_t { - char **argv; // list of strings - int argc; // number of used elements in 'argv' - uint size; // >0: 'argv' is alloced to store # elements - // last NULL element is not counted here + void **list; // 0 terminated list, 1 longer than size + uint used; // num of used elements of 'list' + uint size; // num of alloced elements of 'list' + int grow; // list grows by 1.5*size + grow (at least by 10) } -arg_manager_t; +PointerList_t; //----------------------------------------------------------------------------- -void ResetArgManager ( arg_manager_t *am ); -void SetupArgManager ( arg_manager_t *am, int argc, char ** argv, bool clone ); -void AttachArgManager ( arg_manager_t *am, int argc, char ** argv ); -void CloneArgManager ( arg_manager_t *am, int argc, char ** argv ); +static inline void InitializePointerMgr ( PointerList_t *pl, int grow ) + { DASSERT(pl); memset(pl,0,sizeof(*pl)); pl->grow = grow; } + +void ResetPointerMgr ( PointerList_t *pl ); + +// if n_elem<0: add until NULL pointer +void AddToPointerMgr ( PointerList_t *pl, const void *info ); +void AddListToPointerMgr ( PointerList_t *pl, const void **list, int n_elem ); + +// reset==true: call ResetPointerMgr() after duplicating +void ** DupPointerMgr ( PointerList_t *pl, bool reset ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// ArgManager_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[ArgManager_t]] + +typedef struct ArgManager_t +{ + LowerUpper_t force_case; // change case? + char **argv; // list of strings + int argc; // number of used elements in 'argv' + uint size; // >0: 'argv' is alloced to store # elements + // last NULL element is not counted here +} +ArgManager_t; + +//----------------------------------------------------------------------------- -void AddSpaceArgManager ( arg_manager_t *am, int needed_space ); +void ResetArgManager ( ArgManager_t *am ); +void SetupArgManager ( ArgManager_t *am, LowerUpper_t force_case, + int argc, char ** argv, bool clone ); +void AttachArgManager ( ArgManager_t *am, int argc, char ** argv ); +void CloneArgManager ( ArgManager_t *am, int argc, char ** argv ); -void CopyArgManager ( arg_manager_t *dest, const arg_manager_t *src ); -void MoveArgManager ( arg_manager_t *dest, arg_manager_t *src ); +void AddSpaceArgManager ( ArgManager_t *am, int needed_space ); -void PrepareEditArgManager ( arg_manager_t *am, int needed_space ); +void CopyArgManager ( ArgManager_t *dest, const ArgManager_t *src ); +void MoveArgManager ( ArgManager_t *dest, ArgManager_t *src ); -uint AppendArgManager ( arg_manager_t *am, ccp arg1, ccp arg2, bool move_arg ); -uint InsertArgManager ( arg_manager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg ); -uint ReplaceArgManager( arg_manager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg ); -uint RemoveArgManager ( arg_manager_t *am, int pos, int count ); +void PrepareEditArgManager ( ArgManager_t *am, int needed_space ); -void DumpArgManager ( FILE *f, int indent, const arg_manager_t *am, ccp title ); +// return the pos behind last insert arguments +uint AppendArgManager ( ArgManager_t *am, ccp arg1, ccp arg2, bool move_arg ); +uint InsertArgManager ( ArgManager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg ); +uint ReplaceArgManager( ArgManager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg ); + +// return the pos at removed argument +uint RemoveArgManager ( ArgManager_t *am, int pos, int count ); + +uint ScanSimpleArgManager ( ArgManager_t *am, ccp src ); +uint ScanQuotedArgManager ( ArgManager_t *am, ccp src, bool is_utf8 ); + +// NULL if for both params accepted +bool CheckFilterArgManager ( const ArgManager_t *filter, ccp name ); + +void DumpArgManager ( FILE *f, int indent, const ArgManager_t *am, ccp title ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// sizeof_info_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[sizeof_info_t]] + +#define SIZEOF_INFO_TITLE(t) { -1, t }, +#define SIZEOF_INFO_ENTRY(e) { sizeof(e), #e }, +#define SIZEOF_INFO_SEP() { -2, 0 }, +#define SIZEOF_INFO_TERM() { -9, 0 }, + +typedef struct sizeof_info_t +{ + int size; + ccp name; +} +__attribute__ ((packed)) sizeof_info_t; + +//----------------------------------------------------------------------------- + +// basic lists +extern const sizeof_info_t sizeof_info_linux[]; // C and Linux types +extern const sizeof_info_t sizeof_info_dclib[]; // dcLib types + +// default list of lists for GCMD_Sizeof(), terminated by 0 +extern const sizeof_info_t *sizeof_info_default[]; +extern PointerList_t SizeofInfoMgr; + +static inline void AddDefaultToSizeofInfoMgr(void) + { AddListToPointerMgr(&SizeofInfoMgr,(cvpp)sizeof_info_default,-1); } + +static inline void AddInfoToSizeofInfoMgr ( const sizeof_info_t *info ) + { AddToPointerMgr(&SizeofInfoMgr,info); } + +static inline void AddListToSizeofInfoMgr ( const sizeof_info_t **list ) + { AddListToPointerMgr(&SizeofInfoMgr,(cvpp)list,-1); } + +static inline const sizeof_info_t ** GetSizeofInfoMgrList(void) + { return SizeofInfoMgr.used ? (const sizeof_info_t**)SizeofInfoMgr.list : 0; } + +/////////////////////////////////////////////////////////////////////////////// +// [[sizeof_info_order_t]] + +typedef enum sizeof_info_order_t +{ + SIZEOF_ORDER_NONE, // don't sort output, but print categories + SIZEOF_ORDER_NAME, // Sort the output by name (case-insensitive) + // and suppress output of categories. + SIZEOF_ORDER_SIZE, // Sort the output by size and suppress output of categories. +} +sizeof_info_order_t; + +//----------------------------------------------------------------------------- + +void ListSizeofInfo +( + const PrintMode_t *p_pm, // NULL or print mode + const sizeof_info_t **si_list, // list of list of entries + ArgManager_t *p_filter, // NULL or filter arguments, LOUP_LOWER recommended + sizeof_info_order_t order // kind of order +); + +static inline void ListSizeofInfoMgr +( + const PrintMode_t *p_pm, // NULL or print mode + PointerList_t *mgr, // valid PointerList_t + ArgManager_t *p_filter, // NULL or filter arguments, LOUP_LOWER recommended + sizeof_info_order_t order // kind of order +) +{ + ListSizeofInfo(p_pm,(const sizeof_info_t**)mgr->list,p_filter,order); +} // /////////////////////////////////////////////////////////////////////////////// @@ -2369,7 +2683,7 @@ extern ccp TableDecode64default, TableEncode64default; uint GetEscapedSize ( - // returns the needed buffer size for PrintEscapedString() + // returns the needed buffer size for PrintEscapedString() ccp source, // NULL or string to print int src_len, // length of string. if -1, str is null terminated @@ -2465,7 +2779,7 @@ uint EncodeBase64 // returns the number of scanned bytes of 'source' char *buf, // valid destination buffer - uint buf_size, // size of 'buf', >= 4 + uint buf_size, // size of 'buf' >= 4 const void *source, // NULL or data to encode int source_len, // length of 'source'; if <0: use strlen(source) const char encode64[64+1], // encoding table; if NULL: use TableEncode64default @@ -2496,7 +2810,7 @@ uint EncodeBase64ml // ml: multi line // returns the number of scanned bytes of 'source' char *buf, // valid destination buffer - uint buf_size, // size of 'buf', >= 4 + uint buf_size, // size of 'buf' >= 4 const void *source, // NULL or data to encode int source_len, // length of 'source'; if <0: use strlen(source) const char encode64[64+1], // encoding table; if NULL: use TableEncode64default @@ -2644,7 +2958,7 @@ uint EncodeByMode // returns the number of valid bytes in 'buf'. Result is NULL-terminated. char *buf, // valid destination buffer - uint buf_size, // size of 'buf', >= 4 + uint buf_size, // size of 'buf' >= 4 ccp source, // string to encode int slen, // length of string. if -1, str is null terminated EncodeMode_t emode // encoding mode @@ -2751,6 +3065,45 @@ static char * QuoteBashCircS ( ccp src, cvp if_null, CharMode_t cm ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// struct Escape_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[EscapeStat_t]] + +typedef enum EscapeStat_t +{ + ESCST_NONE, // nothing scanned (data incomplete) + ESCST_CHAR, // single char scanned (char behind '\e') + ESCST_FE, // FE scanned (single byte) + ESCST_SS2, // SS2 scanned ('N' + single byte), code := second char + ESCST_SS3, // SS3 scanned ('O' + single byte) , code := second char + ESCST_CSI, // 'Control Sequence Introduce' based string scanned, code := final char + ESCST_OSC, // 'Operating System Command' based string scanned + + ESCST__N +} +EscapeStat_t; + +extern const char ecape_stat_name[ESCST__N+1][5]; + +/////////////////////////////////////////////////////////////////////////////// +// [[Escape_t]] + +typedef struct Escape_t +{ + EscapeStat_t status; // one of EscapeStat_t + int scanned_len; // number of scanned chars + u32 code; // depends on 'status', see enum EscapeStat_t + mem_t esc; // if status==2: pointer+len to escape string; else (0,0) +} +Escape_t; + +//----------------------------------------------------------------------------- + +// returns esc->status +EscapeStat_t CheckEscape ( Escape_t *esc, cvp source, cvp end, bool check_esc ); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// scan keywords /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -2977,35 +3330,6 @@ ccp GetKeywordOffAutoOn ( OffOn_t value ); // /////////////////////////////////////////////////////////////////////////////// -/////////////// LOWER/AUTO/UPPER /////////////// -/////////////////////////////////////////////////////////////////////////////// -// [[LowerUpper_t]] - -typedef enum LowerUpper_t -{ - LOUP_ERROR = -99, - LOUP_LOWER = -1, - LOUP_AUTO = 0, - LOUP_UPPER = 1, -} -LowerUpper_t; - -extern const KeywordTab_t KeyTab_LOWER_AUTO_UPPER[]; - -int ScanKeywordLowerAutoUpper -( - // returns one of LOUP_* - - ccp arg, // argument to scan - int on_empty, // return this value on empty - uint max_num, // >0: additionally accept+return number <= max_num - ccp object // NULL (silent) or object for error messages -); - -ccp GetKeywordLowerAutoUpper ( LowerUpper_t value ); - -// -/////////////////////////////////////////////////////////////////////////////// /////////////// scan command lists /////////////// /////////////////////////////////////////////////////////////////////////////// // @@ -3280,14 +3604,15 @@ unsigned long long int str2ull ( const char *nptr, char **endptr, int base ); typedef enum sizeform_mode_t { DC_SFORM_ALIGN = 0x01, // aligned output - DC_SFORM_NARROW = 0x02, // suppress space between number and unit - DC_SFORM_UNIT1 = 0x04, // limit unit to 1 character (space for bytes) - DC_SFORM_INC = 0x08, // increment to next factor if no fraction is lost - DC_SFORM_PLUS = 0x10, // on signed output: print PLUS sign for values >0 - DC_SFORM_DASH = 0x20, // on NULL: print only a dash (minus sign) + DC_SFORM_CENTER = 0x02, // aligned and centered output + DC_SFORM_NARROW = 0x04, // suppress space between number and unit + DC_SFORM_UNIT1 = 0x08, // limit unit to 1 character (space for bytes) + DC_SFORM_INC = 0x10, // increment to next factor if no fraction is lost + DC_SFORM_PLUS = 0x20, // on signed output: print PLUS sign for values >0 + DC_SFORM_DASH = 0x40, // on NULL: print only a dash (minus sign) - DC_SFORM__MASK = 0x3f, // mask of above - DC_SFORM__AUTO = 0x40, // hint for some functions to decide by themself + DC_SFORM__MASK = 0x7f, // mask of above + DC_SFORM__AUTO = 0x80, // hint for some functions to decide by themself DC_SFORM_TINY = DC_SFORM_NARROW | DC_SFORM_UNIT1, } @@ -3302,6 +3627,13 @@ double RoundD7bytes ( double d ); /////////////////////////////////////////////////////////////////////////////// +// Parameters: +// char *buf, // result buffer +// // NULL: use a local circulary static buffer +// size_t buf_size, // size of 'buf', ignored if buf==NULL +// * num, // number to print +// sizeform_mode_t mode // any of DC_SFORM_ALIGN, DC_SFORM_DASH[not *D*()] + char * PrintNumberU4 ( char *buf, size_t buf_size, u64 num, sizeform_mode_t mode ); char * PrintNumberU5 ( char *buf, size_t buf_size, u64 num, sizeform_mode_t mode ); char * PrintNumberU6 ( char *buf, size_t buf_size, u64 num, sizeform_mode_t mode ); @@ -3315,13 +3647,6 @@ char * PrintNumberD5 ( char *buf, size_t buf_size, double num, sizeform_mode_t m char * PrintNumberD6 ( char *buf, size_t buf_size, double num, sizeform_mode_t mode ); char * PrintNumberD7 ( char *buf, size_t buf_size, double num, sizeform_mode_t mode ); -// Parameters: -// char *buf, // result buffer -// // NULL: use a local circulary static buffer -// size_t buf_size, // size of 'buf', ignored if buf==NULL -// * num, // number to print -// sizeform_mode_t mode // any of DC_SFORM_ALIGN, DC_SFORM_DASH[not *D*()] - /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // [[size_mode_t]] @@ -3475,6 +3800,24 @@ u64 GetSizeU64 ( ccp src, char **end, int force_base ); double GetSizeD ( ccp src, char **end, int force_base ); //----------------------------------------------------------------------------- +// [[range_opt_t]] + +typedef enum range_opt_t +{ + RAOPT_COLON = 0x01, // allow ':' as from/to separator + RAOPT_MINUS = 0x02, // allow '-' as from/to separator + RAOPT_HASH = 0x04, // allow '#' as from/size separator + RAOPT_COMMA = 0x08, // allow ',' as from/size separator + RAOPT_NEG = 0x10, // accept negative numbers as index relative to max_value + RAOPT_ASSUME_0 = 0x20, // allow ':-#,' as first char and assume 0 as first value + RAOPT_F_FORCE = 0x40, // flag to avoid value 0 as default alias + RAOPT__ALL = 0x7f, // all possible bits + + RAOPT__DEFAULT = RAOPT_COLON | RAOPT_HASH, +} +range_opt_t; + +//----------------------------------------------------------------------------- char * ScanSizeRange ( @@ -3487,7 +3830,8 @@ char * ScanSizeRange u64 default_factor, // use this factor if number hasn't one u64 default_factor_add, // use this factor for summands int force_base, // if 1000|1024: force multiple of this - double max_value // >0: max value for open ranges + double max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT ); char * ScanSizeRangeU32 @@ -3501,7 +3845,23 @@ char * ScanSizeRangeU32 u64 default_factor, // use this factor if number hasn't one u64 default_factor_add, // use this factor for summands int force_base, // if 1000|1024: force multiple of this - u32 max_value // >0: max value for open ranges + u32 max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT +); + +char * ScanSizeRangeS32 +( + int *stat, // if not NULL: store result + // 0:none, 1:single, 2:range + s32 *num1, // not NULL: store 'from' result + s32 *num2, // not NULL: store 'to' result + + ccp source, // source text + u64 default_factor, // use this factor if number hasn't one + u64 default_factor_add, // use this factor for summands + int force_base, // if 1000|1024: force multiple of this + s32 max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT ); char * ScanSizeRangeU64 @@ -3515,7 +3875,23 @@ char * ScanSizeRangeU64 u64 default_factor, // use this factor if number hasn't one u64 default_factor_add, // use this factor for summands int force_base, // if 1000|1024: force multiple of this - u64 max_value // >0: max value for open ranges + u64 max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT +); + +char * ScanSizeRangeS64 +( + int *stat, // if not NULL: store result + // 0:none, 1:single, 2:range + s64 *num1, // not NULL: store 'from' result + s64 *num2, // not NULL: store 'to' result + + ccp source, // source text + u64 default_factor, // use this factor if number hasn't one + u64 default_factor_add, // use this factor for summands + int force_base, // if 1000|1024: force multiple of this + s64 max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT ); //----------------------------------------------------------------------------- @@ -3531,7 +3907,8 @@ char * ScanSizeRangeList u64 default_factor, // use this factor if number hasn't one u64 default_factor_add, // use this factor for summands int force_base, // if 1000|1024: force multiple of this - double max_value // >0: max value for open ranges + double max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT ); char * ScanSizeRangeListU32 @@ -3545,7 +3922,8 @@ char * ScanSizeRangeListU32 u32 default_factor, // use this factor if number hasn't one u32 default_factor_add, // use this factor for summands int force_base, // if 1000|1024: force multiple of this - u32 max_value // >0: max value for open ranges + u32 max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT ); char * ScanSizeRangeListU64 @@ -3559,7 +3937,8 @@ char * ScanSizeRangeListU64 u64 default_factor, // use this factor if number hasn't one u64 default_factor_add, // use this factor for summands int force_base, // if 1000|1024: force multiple of this - u64 max_value // >0: max value for open ranges + u64 max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT ); //----------------------------------------------------------------------------- @@ -3610,78 +3989,49 @@ enumError ScanSizeOptU32 // /////////////////////////////////////////////////////////////////////////////// -/////////////// Scan Duration /////////////// -/////////////////////////////////////////////////////////////////////////////// -// [[ScanDuration_t]] - -typedef enum ScanDuration_t -{ - SDUMD_SKIP_BLANKS = 0x01, // skip leading blanks - SDUMD_ALLOW_COLON = 0x02, // allow 'H:M' and 'H:M:S' - SDUMD_ALLOW_DIV = 0x04, // allow fraction 'n/d' as number - - SDUMD_ALLOW_LIST = 0x10, // allow lists like '9h12m' - SDUMD_ALLOW_SPACE_SEP = 0x20, // lists: allow spaces as list separator - SDUMD_ALLOW_PLUS_SEP = 0x40, // lists: allow '+' as list separator - SDUMD_ALLOW_MINUS_SEP = 0x80, // lists: allow '-' as list separator - - SDUMD_M_ALL = 0xf7, -} -ScanDuration_t; - -//----------------------------------------------------------------------------- - -char * ScanDuration -( - double *num, // not NULL: store result - ccp source, // source text - double default_factor, // default factor if no SI unit found - ScanDuration_t mode -); - -double GetDurationFactor ( char ch ); - -char * ScanSIFactor -( - // returns end of scanned string - - double *num, // not NULL: store result - ccp source, // source text - double default_factor // return this if no factor found -); - -// -/////////////////////////////////////////////////////////////////////////////// /////////////// time & timer /////////////// /////////////////////////////////////////////////////////////////////////////// //--- conversion factors -#define SEC_PER_MIN 60 -#define SEC_PER_HOUR 3600 -#define SEC_PER_DAY 86400 -#define SEC_PER_WEEK 604800 +#define SEC_PER_MIN 60 +#define SEC_PER_HOUR 3600 +#define SEC_PER_DAY 86400 +#define SEC_PER_WEEK 604800 +#define SEC_PER_MONTH 2629746 // 365.2425 * SEC_PER_DAY / 12 +#define SEC_PER_QUARTER 7889238 // 365.2425 * SEC_PER_DAY / 4 +#define SEC_PER_YEAR 31556952 // 365.2425 * SEC_PER_DAY -#define MSEC_PER_SEC 1000ull -#define MSEC_PER_MIN (60*MSEC_PER_SEC) -#define MSEC_PER_HOUR (3600*MSEC_PER_SEC) -#define MSEC_PER_DAY (SEC_PER_DAY*MSEC_PER_SEC) -#define MSEC_PER_WEEK (SEC_PER_WEEK*MSEC_PER_SEC) +#define MSEC_PER_SEC 1000ll +#define MSEC_PER_MIN (MSEC_PER_SEC*SEC_PER_MIN) +#define MSEC_PER_HOUR (MSEC_PER_SEC*SEC_PER_HOUR) +#define MSEC_PER_DAY (MSEC_PER_SEC*SEC_PER_DAY) +#define MSEC_PER_WEEK (MSEC_PER_SEC*SEC_PER_WEEK) +#define MSEC_PER_MONTH (MSEC_PER_SEC*SEC_PER_MONTH) +#define MSEC_PER_QUARTER (MSEC_PER_SEC*SEC_PER_QUARTER) +#define MSEC_PER_YEAR (MSEC_PER_SEC*SEC_PER_YEAR) -#define USEC_PER_MSEC 1000ull -#define USEC_PER_SEC 1000000ull -#define USEC_PER_MIN (60*USEC_PER_SEC) -#define USEC_PER_HOUR (3600*USEC_PER_SEC) -#define USEC_PER_DAY (SEC_PER_DAY*USEC_PER_SEC) -#define USEC_PER_WEEK (SEC_PER_WEEK*USEC_PER_SEC) +#define USEC_PER_MSEC 1000ll +#define USEC_PER_SEC 1000000ll +#define USEC_PER_MIN (USEC_PER_SEC*SEC_PER_MIN) +#define USEC_PER_HOUR (USEC_PER_SEC*SEC_PER_HOUR) +#define USEC_PER_DAY (USEC_PER_SEC*SEC_PER_DAY) +#define USEC_PER_WEEK (USEC_PER_SEC*SEC_PER_WEEK) +#define USEC_PER_MONTH (USEC_PER_SEC*SEC_PER_MONTH) +#define USEC_PER_QUARTER (USEC_PER_SEC*SEC_PER_QUARTER) +#define USEC_PER_YEAR (USEC_PER_SEC*SEC_PER_YEAR) + +#define NSEC_PER_USEC 1000ll +#define NSEC_PER_MSEC 1000000ll +#define NSEC_PER_SEC 1000000000ll +#define NSEC_PER_MIN (NSEC_PER_SEC*SEC_PER_MIN) +#define NSEC_PER_HOUR (NSEC_PER_SEC*SEC_PER_HOUR) +#define NSEC_PER_DAY (NSEC_PER_SEC*SEC_PER_DAY) +#define NSEC_PER_WEEK (NSEC_PER_SEC*SEC_PER_WEEK) +#define NSEC_PER_MONTH (NSEC_PER_SEC*SEC_PER_MONTH) +#define NSEC_PER_QUARTER (NSEC_PER_SEC*SEC_PER_QUARTER) +#define NSEC_PER_YEAR (NSEC_PER_SEC*SEC_PER_YEAR) -#define NSEC_PER_USEC 1000ull -#define NSEC_PER_MSEC 1000000ull -#define NSEC_PER_SEC 1000000000ull -#define NSEC_PER_MIN (60*NSEC_PER_SEC) -#define NSEC_PER_HOUR (3600*NSEC_PER_SEC) -#define NSEC_PER_DAY (SEC_PER_DAY*NSEC_PER_SEC) -#define NSEC_PER_WEEK (SEC_PER_WEEK*NSEC_PER_SEC) //--- time types @@ -3694,6 +4044,19 @@ typedef s64 s_usec_t; // signed type to store time as microseconds typedef u64 u_nsec_t; // unsigned type to store time as nanoseconds typedef s64 s_nsec_t; // signed type to store time as nanoseconds + +//--- max values time types + +#define S_SEC_MAX S32_MAX +#define U_SEC_MAX U32_MAX +#define S_MSEC_MAX S64_MAX +#define U_MSEC_MAX U64_MAX +#define S_USEC_MAX S64_MAX +#define U_USEC_MAX U64_MAX +#define S_NSEC_MAX S64_MAX +#define U_NSEC_MAX U64_MAX + +//----------------------------------------------------------------------------- // [[DayTime_t]] typedef struct DayTime_t { @@ -3716,6 +4079,14 @@ extern int timezone_adjust_isdst; /////////////////////////////////////////////////////////////////////////////// +extern ccp micro_second_char; // default = "u" + +static inline void SetMicroSecondChar ( bool use_micro ) + { micro_second_char = use_micro ? "µ" : "u"; } + + +/////////////////////////////////////////////////////////////////////////////// + void SetupTimezone ( bool force ); int GetTimezoneAdjust ( time_t tim ); @@ -3727,17 +4098,55 @@ u_msec_t GetTimeMSec ( bool localtime ); u_usec_t GetTimeUSec ( bool localtime ); u_nsec_t GetTimeNSec ( bool localtime ); +struct timespec GetClockTimer(void); +u_sec_t GetTimerSec(void); u_msec_t GetTimerMSec(void); u_usec_t GetTimerUSec(void); u_nsec_t GetTimerNSec(void); -static inline u64 double2msec ( double d ) { return d>0.0 ? (u64)trunc( 1e3*d+0.5 ) : 0; } -static inline u64 double2usec ( double d ) { return d>0.0 ? (u64)trunc( 1e6*d+0.5 ) : 0; } -static inline u64 double2nsec ( double d ) { return d>0.0 ? (u64)trunc( 1e9*d+0.5 ) : 0; } +//----------------------------------------------------------------------------- + +static inline u_sec_t Time2TimerSec ( u_sec_t tim, bool localtime ) + { return tim - GetTimeSec(localtime) + GetTimerSec(); } + +static inline u_msec_t Time2TimerMSec ( u_msec_t tim, bool localtime ) + { return tim - GetTimeMSec(localtime) + GetTimerMSec(); } + +static inline u_usec_t Time2TimerUSec ( u_usec_t tim, bool localtime ) + { return tim - GetTimeUSec(localtime) + GetTimerUSec(); } -static inline double msec2double ( u64 num ) { return num * 1e-3; } -static inline double usec2double ( u64 num ) { return num * 1e-6; } -static inline double nsec2double ( u64 num ) { return num * 1e-9; } +static inline u_nsec_t Time2TimerNSec ( u_nsec_t tim, bool localtime ) + { return tim - GetTimeNSec(localtime) + GetTimerNSec(); } + + +static inline u_sec_t Timer2TimeSec ( u_sec_t tim, bool localtime ) + { return tim - GetTimerSec() + GetTimeSec(localtime); } + +static inline u_msec_t Timer2TimeMSec ( u_msec_t tim, bool localtime ) + { return tim - GetTimerMSec() + GetTimeMSec(localtime); } + +static inline u_usec_t Timer2TimeUSec ( u_usec_t tim, bool localtime ) + { return tim - GetTimerUSec() + GetTimeUSec(localtime); } + +static inline u_nsec_t Timer2TimeNSec ( u_nsec_t tim, bool localtime ) + { return tim - GetTimerNSec() + GetTimeNSec(localtime); } + +//----------------------------------------------------------------------------- + +static inline u_sec_t double2sec ( double d ) { return d>0.0 ? (u_msec_t)trunc( d+0.5 ) : 0; } +static inline u_msec_t double2msec ( double d ) { return d>0.0 ? (u_msec_t)trunc( 1e3*d+0.5 ) : 0; } +static inline u_usec_t double2usec ( double d ) { return d>0.0 ? (u_usec_t)trunc( 1e6*d+0.5 ) : 0; } +static inline u_nsec_t double2nsec ( double d ) { return d>0.0 ? (u_nsec_t)trunc( 1e9*d+0.5 ) : 0; } + +static inline s_sec_t double2ssec ( double d ) { return (s_sec_t) floor( d+0.5 ); } +static inline s_msec_t double2smsec ( double d ) { return (s_msec_t) floor( 1e3*d+0.5 ); } +static inline s_usec_t double2susec ( double d ) { return (s_usec_t) floor( 1e6*d+0.5 ); } +static inline s_nsec_t double2snsec ( double d ) { return (s_nsec_t) floor( 1e9*d+0.5 ); } + +static inline double sec2double ( s_sec_t num ) { return num; } +static inline double msec2double ( s_msec_t num ) { return num * 1e-3; } +static inline double usec2double ( s_usec_t num ) { return num * 1e-6; } +static inline double nsec2double ( s_nsec_t num ) { return num * 1e-9; } //--- another epoch: Monday, 2001-01-01 @@ -3747,13 +4156,57 @@ static inline double nsec2double ( u64 num ) { return num * 1e-9; } #define EPOCH_2001_NSEC (EPOCH_2001_SEC*NSEC_PER_SEC) /////////////////////////////////////////////////////////////////////////////// +// [[CurrentTime_t]] + +typedef struct CurrentTime_t +{ + u_sec_t sec; + u_msec_t msec; + u_usec_t usec; +} +CurrentTime_t; + +//----------------------------------------------------------------------------- + +CurrentTime_t GetCurrentTime ( bool localtime ); + +extern CurrentTime_t current_time; +static inline void UpdateCurrentTime(void) + { current_time = GetCurrentTime(false); } + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +// PrintRefTime*() return temporary buffer by GetCircBuf(), field width 10 +// Formats: +// ±10h: " %k:%M:%S" +// ±12d: " %e. %k:%M" +// *: "%F" + +ccp PrintRefTime +( + + u_sec_t tim, // seconds since epoch; 0 is replaced by time() + u_sec_t *ref_tim // NULL or ref_tim; if *ref_tim==0: write current time + // it is used to select format +); + +ccp PrintRefTimeUTC +( + + u_sec_t tim, // seconds since epoch; 0 is replaced by time() + u_sec_t *ref_tim // NULL or ref_tim; if *ref_tim==0: write current time + // it is used to select format +); + +//----------------------------------------------------------------------------- ccp PrintTimeByFormat ( // returns temporary buffer by GetCircBuf(); ccp format, // format string for strftime() - time_t tim // seconds since epoch; 0 is replaced by time() + u_sec_t tim // seconds since epoch; 0 is replaced by time() ); ccp PrintTimeByFormatUTC @@ -3761,7 +4214,7 @@ ccp PrintTimeByFormatUTC // returns temporary buffer by GetCircBuf(); ccp format, // format string for strftime() - time_t tim // seconds since epoch; 0 is replaced by time() + u_sec_t tim // seconds since epoch; 0 is replaced by time() ); //----------------------------------------------------------------------------- @@ -3786,6 +4239,24 @@ ccp PrintNSecByFormatUTC uint nsec // nanosecond of second ); +ccp PrintNTimeByFormat +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + u_nsec_t ntime +); + +ccp PrintNTimeByFormatUTC +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + u_nsec_t ntime +); + //----------------------------------------------------------------------------- static inline ccp PrintUSecByFormat @@ -3814,6 +4285,70 @@ static inline ccp PrintUSecByFormatUTC return PrintNSecByFormatUTC(format,tim,usec*NSEC_PER_USEC); } +ccp PrintUTimeByFormat +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + u_usec_t utime +); + +ccp PrintUTimeByFormatUTC +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + u_usec_t utime +); + +//----------------------------------------------------------------------------- + +static inline ccp PrintMSecByFormat +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + time_t tim, // seconds since epoch + uint msec // millisecond of second +) +{ + return PrintNSecByFormat(format,tim,msec*NSEC_PER_MSEC); +} + +static inline ccp PrintMSecByFormatUTC +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + time_t tim, // seconds since epoch + uint msec // millisecond of second +) +{ + return PrintNSecByFormatUTC(format,tim,msec*NSEC_PER_MSEC); +} + +ccp PrintMTimeByFormat +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + u_msec_t mtime +); + +ccp PrintMTimeByFormatUTC +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + u_msec_t mtime +); + //----------------------------------------------------------------------------- ccp PrintTimevalByFormat @@ -3926,7 +4461,7 @@ ccp PrintTimer3 // helper function u64 sec, // seconds to print int usec, // 0...999999: usec fraction, // otherwise suppress ms/us output - bool aligned // true: print aligned 3 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH ); static inline ccp PrintTimerSec3 @@ -3935,10 +4470,10 @@ static inline ccp PrintTimerSec3 // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL u_sec_t sec, // seconds to print - bool aligned // true: print aligned 3 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH ) { - return PrintTimer3(buf,buf_size,sec,-1,aligned); + return PrintTimer3(buf,buf_size,sec,-1,mode); } static inline ccp PrintTimerMSec3 @@ -3947,10 +4482,10 @@ static inline ccp PrintTimerMSec3 // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL u_msec_t msec, // microseconds to print - bool aligned // true: print aligned 3 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH ) { - return PrintTimer3(buf,buf_size,msec/1000,msec%1000*1000,aligned); + return PrintTimer3(buf,buf_size,msec/1000,msec%1000*1000,mode); } static inline ccp PrintTimerUSec3 @@ -3959,10 +4494,10 @@ static inline ccp PrintTimerUSec3 // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL u_usec_t usec, // microseconds to print - bool aligned // true: print aligned 3 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH ) { - return PrintTimer3(buf,buf_size,usec/1000000,usec%1000000,aligned); + return PrintTimer3(buf,buf_size,usec/1000000,usec%1000000,mode); } //----------------------------------------------------------------------------- @@ -3975,7 +4510,7 @@ ccp PrintTimer4 // helper function u64 sec, // seconds to print int usec, // 0...999999: usec fraction, // otherwise suppress ms/us output - bool aligned // true: print aligned 4 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH ); static inline ccp PrintTimerSec4 @@ -3984,10 +4519,10 @@ static inline ccp PrintTimerSec4 // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL u_sec_t sec, // seconds to print - bool aligned // true: print aligned 4 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH ) { - return PrintTimer4(buf,buf_size,sec,-1,aligned); + return PrintTimer4(buf,buf_size,sec,-1,mode); } static inline ccp PrintTimerMSec4 @@ -3996,10 +4531,10 @@ static inline ccp PrintTimerMSec4 // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL u_msec_t msec, // microseconds to print - bool aligned // true: print aligned 4 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH ) { - return PrintTimer4(buf,buf_size,msec/1000,msec%1000*1000,aligned); + return PrintTimer4(buf,buf_size,msec/MSEC_PER_SEC,msec%MSEC_PER_SEC*USEC_PER_SEC,mode); } static inline ccp PrintTimerUSec4 @@ -4008,23 +4543,36 @@ static inline ccp PrintTimerUSec4 // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL u_usec_t usec, // microseconds to print - bool aligned // true: print aligned 4 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH +) +{ + return PrintTimer4(buf,buf_size,usec/USEC_PER_SEC,usec%USEC_PER_SEC,mode); +} + +static inline ccp PrintTimerNSec4 +( + char * buf, // result buffer (>4 bytes) + // If NULL, a local circulary static buffer is used + size_t buf_size, // size of 'buf', ignored if buf==NULL + u_nsec_t nsec, // nanoseconds to print + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH ) { - return PrintTimer4(buf,buf_size,usec/1000000,usec%1000000,aligned); + const u_usec_t usec = nsec / NSEC_PER_USEC; + return PrintTimer4(buf,buf_size,usec/USEC_PER_SEC,usec%USEC_PER_SEC,mode); } //----------------------------------------------------------------------------- -ccp PrintTimer6 // helper function +ccp PrintTimer6N // helper function ( char * buf, // result buffer (>6 bytes) // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL u64 sec, // seconds to print - int usec, // 0...999999: usec fraction, - // otherwise suppress ms/us output - bool aligned // true: print aligned 6 character output + int nsec, // 0...999999999: nsec fraction, + // otherwise suppress ms/us/ns output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_CENTER | DC_SFORM_DASH ); static inline ccp PrintTimerSec6 @@ -4033,10 +4581,10 @@ static inline ccp PrintTimerSec6 // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL u_sec_t sec, // seconds to print - bool aligned // true: print aligned 6 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_CENTER | DC_SFORM_DASH ) { - return PrintTimer6(buf,buf_size,sec,-1,aligned); + return PrintTimer6N(buf,buf_size,sec,-1,mode); } static inline ccp PrintTimerMSec6 @@ -4045,10 +4593,11 @@ static inline ccp PrintTimerMSec6 // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL u_msec_t msec, // microseconds to print - bool aligned // true: print aligned 6 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_CENTER | DC_SFORM_DASH ) { - return PrintTimer6(buf,buf_size,msec/1000,msec%1000*1000,aligned); + return PrintTimer6N( buf, buf_size, + msec/MSEC_PER_SEC, msec%MSEC_PER_SEC*NSEC_PER_MSEC, mode ); } static inline ccp PrintTimerUSec6 @@ -4057,10 +4606,24 @@ static inline ccp PrintTimerUSec6 // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL u_usec_t usec, // microseconds to print - bool aligned // true: print aligned 6 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_CENTER | DC_SFORM_DASH +) +{ + return PrintTimer6N( buf, buf_size, + usec/USEC_PER_SEC, usec%USEC_PER_SEC*NSEC_PER_USEC, mode ); +} + +static inline ccp PrintTimerNSec6 +( + char * buf, // result buffer (>6 bytes) + // If NULL, a local circulary static buffer is used + size_t buf_size, // size of 'buf', ignored if buf==NULL + u_nsec_t nsec, // nanoseconds to print + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_CENTER | DC_SFORM_DASH ) { - return PrintTimer6(buf,buf_size,usec/1000000,usec%1000000,aligned); + return PrintTimer6N( buf, buf_size, + nsec/NSEC_PER_SEC, nsec%NSEC_PER_SEC, mode ); } //----------------------------------------------------------------------------- @@ -4071,19 +4634,31 @@ ccp PrintTimerUSec4s // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL s_usec_t usec, // microseconds to print - sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH ); +static inline ccp PrintTimerNSec4s +( + char * buf, // result buffer (>4 bytes) + // If NULL, a local circulary static buffer is used + size_t buf_size, // size of 'buf', ignored if buf==NULL + s_nsec_t nsec, // nanoseconds to print + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH +) +{ + return PrintTimerUSec4s(buf,buf_size,nsec/NSEC_PER_USEC,mode); +} + static inline ccp PrintTimerMSec4s ( char * buf, // result buffer (>4 bytes) // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL s_msec_t msec, // milliseconds to print - sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH ) { - return PrintTimerUSec4s(buf,buf_size,1000*msec,mode); + return PrintTimerUSec4s(buf,buf_size,msec*USEC_PER_MSEC,mode); } static inline ccp PrintTimerSec4s @@ -4092,7 +4667,7 @@ static inline ccp PrintTimerSec4s // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL int sec, // seconds to print - sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH ) { return PrintTimerUSec4s(buf,buf_size,1000000ll*sec,mode); @@ -4100,13 +4675,22 @@ static inline ccp PrintTimerSec4s //----------------------------------------------------------------------------- +ccp PrintTimerNSec7s +( + char * buf, // result buffer (>7 bytes) + // If NULL, a local circulary static buffer is used + size_t buf_size, // size of 'buf', ignored if buf==NULL + s_nsec_t nsec, // nanoseconds to print + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH +); + ccp PrintTimerUSec7s ( char * buf, // result buffer (>7 bytes) // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL s_usec_t usec, // microseconds to print - sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH ); static inline ccp PrintTimerMSec7s @@ -4115,7 +4699,7 @@ static inline ccp PrintTimerMSec7s // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL s_msec_t msec, // milliseconds to print - sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH ) { return PrintTimerUSec7s(buf,buf_size,1000*msec,mode); @@ -4127,12 +4711,169 @@ static inline ccp PrintTimerSec7s // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL int sec, // seconds to print - sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH ) { return PrintTimerUSec7s(buf,buf_size,1000000ll*sec,mode); } +//----------------------------------------------------------------------------- + +ccp PrintAge3Sec +( + u_sec_t now, // NULL or current time by GetTimeSec(false) + u_sec_t time // time to print +); + +ccp PrintAge4Sec +( + u_sec_t now, // NULL or current time by GetTimeSec(false) + u_sec_t time // time to print +); + +ccp PrintAge6Sec +( + u_sec_t now, // NULL or current time by GetTimeSec(false) + u_sec_t time // time to print +); + +ccp PrintAge7Sec +( + u_sec_t now, // NULL or current time by GetTimeSec(false) + u_sec_t time // time to print +); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// Scan Duration /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[ScanDuration_t]] + +typedef enum ScanDuration_t +{ + SDUMD_SKIP_BLANKS = 0x01, // skip leading blanks + SDUMD_ALLOW_COLON = 0x02, // allow 'H:M' and 'H:M:S' + SDUMD_ALLOW_DIV = 0x04, // allow fraction 'n/d' as number + SDUMD_ALLOW_CAPITALS = 0x08, // allow upper case letters + + SDUMD_ALLOW_LIST = 0x10, // allow lists like '9h12m' + SDUMD_ALLOW_SPACE_SEP = 0x20, // lists: allow spaces as list separator + SDUMD_ALLOW_PLUS_SEP = 0x40, // lists: allow '+' as list separator + SDUMD_ALLOW_MINUS_SEP = 0x80, // lists: allow '-' as list separator + + SDUMD_M_DEFAULT = 0xf7, + SDUMD_M_ALL = 0xff, +} +ScanDuration_t; + +//----------------------------------------------------------------------------- + +char * ScanDuration +( + // Returns a pointer to the the first not used character. + // On error, it is 'source' and '*seconds' is set to 0.0. + + double *seconds, // not NULL: store result (number of seconds) + ccp source, // source text + double default_factor, // default factor if no SI unit found + ScanDuration_t mode // flags +); + +double GetDurationFactor ( char ch ); + +char * ScanSIFactor +( + // returns end of scanned string + + double *num, // not NULL: store result + ccp source, // source text + double default_factor // return this if no factor found +); + +//----------------------------------------------------------------------------- + +// simple interfaces to ScanDuration(), SDUMD_M_DEFAULT is used as mode +double str2duration ( ccp src, char **endptr, double default_factor ); + + +static inline u_sec_t str2sec ( ccp src, char **endptr ) + { return double2sec(str2duration(src,endptr,1.0)); } + +static inline u_msec_t str2msec ( ccp src, char **endptr ) + { return double2msec(str2duration(src,endptr,1.0)); } + +static inline u_usec_t str2usec ( ccp src, char **endptr ) + { return double2usec(str2duration(src,endptr,1.0)); } + +static inline u_nsec_t str2nsec ( ccp src, char **endptr ) + { return double2nsec(str2duration(src,endptr,1.0)); } + + +static inline s_sec_t str2ssec ( ccp src, char **endptr ) + { return double2ssec(str2duration(src,endptr,1.0)); } + +static inline s_msec_t str2smsec ( ccp src, char **endptr ) + { return double2smsec(str2duration(src,endptr,1.0)); } + +static inline s_usec_t str2susec ( ccp src, char **endptr ) + { return double2susec(str2duration(src,endptr,1.0)); } + +static inline s_nsec_t str2snsec ( ccp src, char **endptr ) + { return double2snsec(str2duration(src,endptr,1.0)); } + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// Signals & Sleep /////////////// +/////////////////////////////////////////////////////////////////////////////// + +extern volatile int SIGINT_level; +extern volatile int SIGHUP_level; +extern volatile int SIGALRM_level; +extern volatile int SIGCHLD_level; +extern volatile int SIGPIPE_level; +extern volatile int SIGUSR1_level; +extern volatile int SIGUSR2_level; + +// no timout for SIGPIPE +extern u_sec_t SIGINT_sec; +extern u_sec_t SIGHUP_sec; +extern u_sec_t SIGALRM_sec; +extern u_sec_t SIGCHLD_sec; +extern u_sec_t SIGUSR1_sec; +extern u_sec_t SIGUSR2_sec; + +extern int SIGINT_level_max; +extern bool ignore_SIGINT; +extern bool ignore_SIGHUP; + +extern int redirect_signal_pid; +extern LogFile_t log_signal_file; + + +extern volatile int SIGINT_level; +extern volatile int SIGHUP_level; +extern volatile int SIGALRM_level; +extern volatile int SIGPIPE_level; + +extern int SIGINT_level_max; +extern bool ignore_SIGINT; +extern bool ignore_SIGHUP; + +void SetupSignalHandler ( int max_sigint_level, FILE *log_file ); + +//----------------------------------------------------------------------------- + +int SleepNSec ( s_nsec_t nsec ); + +static inline int SleepUSec ( s_usec_t usec ) + { return SleepNSec( usec * NSEC_PER_USEC ); } + +static inline int SleepMSec ( s_msec_t msec ) + { return SleepNSec( msec * NSEC_PER_MSEC ); } + +static inline int SleepSec ( s_sec_t sec ) + { return SleepNSec( sec * NSEC_PER_SEC ); } + // /////////////////////////////////////////////////////////////////////////////// /////////////// scan date & time /////////////// @@ -4362,13 +5103,383 @@ static inline ccp year2text // /////////////////////////////////////////////////////////////////////////////// +/////////////// usage counter /////////////// +/////////////////////////////////////////////////////////////////////////////// + +#if IS_DEVELOP + #define TEST_USAGE_COUNT 0 + #define USAGE_COUNT_ENABLED 0 +#else + #define TEST_USAGE_COUNT 0 + #define USAGE_COUNT_ENABLED 0 +#endif + +#if TEST_USAGE_COUNT + #define USAGE_COUNT_ENTRIES 11 // number of entries +#else + #define USAGE_COUNT_ENTRIES 30 // number of entries +#endif + +#define USAGE_COUNT_FIRST_ADD 8 // first entry where values wil be added +#define USAGE_COUNT_NEXT_MIN(v) (15*(v)/8) + +//----------------------------------------------------------------------------- +// [[UsageParam_t]] + +typedef struct UsageParam_t +{ + uint used; // number of used entries + bool enabled; // TRUE: statistics are enabled + bool is_active; // TRUE: counter is active (set by framework) + + //--- not saved/restored + + bool dirty; // TRUE: record needs an update @ 'update_nsec' + u_nsec_t update_nsec; // next update, based on GetTimerNSec() + u_nsec_t force_update_nsec; // force next update, based on GetTimerNSec() +} +UsageParam_t; + +//----------------------------------------------------------------------------- +// [[UsageCountEntry_t]] + +typedef struct UsageCountEntry_t +{ + u64 count; // counter + u_nsec_t elapsed_nsec; // elapsed time, by GetTimerNSec() + u_sec_t time_sec; // time of record, by GetTimeSec(false) + float top1s; // = 100.0*(utime+stime)/elapsed for 1s + float top5s; // = 100.0*(utime+stime)/elapsed for 5s +} +__attribute__ ((packed)) UsageCountEntry_t; + +//----------------------------------------------------------------------------- +// [[UsageCount_t]] + +typedef struct UsageCount_t +{ + UsageParam_t par; // base parameters + UsageCountEntry_t ref; // reference with absolute values + #if TEST_USAGE_COUNT + UsageCountEntry_t entry[USAGE_COUNT_ENTRIES+1]; // list of entries with delta values + #else + UsageCountEntry_t entry[USAGE_COUNT_ENTRIES]; // list of entries with delta values + #endif +} +UsageCount_t; + +//----------------------------------------------------------------------------- + +extern int usage_count_enabled; + +void EnableUsageCount(void); +static inline void DisableUsageCount(void) { usage_count_enabled--; } + +//----------------------------------------------------------------------------- + +// n_rec<0: clear from end, n_rec>=0: clear from index +void ClearUsageCount ( UsageCount_t *uc, int count ); + +// NOW_NSEC: 0 or GetTimerNSec(), but not GetTime*() +void UpdateUsageCount ( UsageCount_t *uc, u_nsec_t now_nsec ); +void UpdateUsageCountIncrement ( UsageCount_t *uc ); +void UpdateUsageCountAdd ( UsageCount_t *uc, int add ); +static inline void UsageCountIncrement ( UsageCount_t *uc ) + { UpdateUsageCountAdd(uc,1); } + +// stat about last 'nsec' nanoseconds +UsageCountEntry_t GetUsageCount ( const UsageCount_t *uc, s_nsec_t nsec ); + +void AddUsageCountEntry ( UsageCountEntry_t *dest, const UsageCountEntry_t *add ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// wait counter /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[UsageDurationEntry_t]] + +typedef struct UsageDurationEntry_t +{ + u_nsec_t elapsed_nsec; // elapsed time, by GetTimerNSec() + u_nsec_t total_nsec; // total waiting time + u_nsec_t top_nsec; // top waiting time + u64 count; // number of events + u_sec_t time_sec; // time of record, by GetTimeSec(false) + float top_cnt_1s; // top number of counts in 1 sec + float top_cnt_5s; // top number of counts in 5 sec +} +__attribute__ ((packed)) UsageDurationEntry_t; + +//----------------------------------------------------------------------------- +// [[UsageDuration_t]] + +typedef struct UsageDuration_t +{ + UsageParam_t par; // base parameters + UsageDurationEntry_t ref; // reference with absolute values + #if TEST_USAGE_COUNT + UsageDurationEntry_t entry[USAGE_COUNT_ENTRIES+1]; // list of entries with delta values + #else + UsageDurationEntry_t entry[USAGE_COUNT_ENTRIES]; // list of entries with delta values + #endif +} +UsageDuration_t; + +//----------------------------------------------------------------------------- + +// n_rec<0: clear from end, n_rec>=0: clear from index +void ClearUsageDuration ( UsageDuration_t *ud, int count ); + +// NOW_NSEC: 0 or GetTimerNSec(), but not GetTime*() +void UpdateUsageDuration ( UsageDuration_t *ud, u_nsec_t now_nsec ); +void UpdateUsageDurationAdd ( UsageDuration_t *ud, int add, u_nsec_t wait_nsec, u_nsec_t top_nsec ); +void UpdateUsageDurationIncrement ( UsageDuration_t *ud, u_nsec_t wait_nsec ); +void UsageDurationIncrement ( UsageDuration_t *ud, u_nsec_t wait_nsec ); + +// stat about last 'nsec' nanoseconds +UsageDurationEntry_t GetUsageDuration ( const UsageDuration_t *ud, s_nsec_t nsec ); + +void AddUsageDurationEntry ( UsageDurationEntry_t *dest, const UsageDurationEntry_t *add ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// usage counter mgr /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[ListUsageFunc]] + +typedef struct UsageCtrl_t UsageCtrl_t; + +enum +{ + LUC_PM_STANDARD, // standard view + LUC_PM_RAW, // raw values, not supported by ListUsageCount() + LUC_PM_SUMMARY, // summary + LUC_PM__USER // base value for user defined modes +}; + +typedef void (*ListUsageFunc) +( + PrintMode_t *pm, // valid print mode + const UsageCtrl_t *uci, // valid object to list + int print_mode, // see LUC_PM_* + s_nsec_t limit_nsec // >0: limit output until # is reached +); + +//----------------------------------------------------------------------------- + +typedef void (*UpdateUsageFunc) +( + const UsageCtrl_t *uci, // valid object to update + u_nsec_t now_usec // NULL or current time by GetTimerNSec() +); + +//----------------------------------------------------------------------------- +// [[UsageCtrl_t]] + +typedef struct UsageCtrl_t +{ + UsageParam_t *par; // higher prioritiy than uc->par and ud->par + UsageCount_t *uc; // not NULL for usage counters + UsageDuration_t *ud; // not NULL for wait counters + + UpdateUsageFunc update_func; // not NULL: Call this function to update + ListUsageFunc list_func; // not NULL: Call this function to list + + ccp title; // NULL or title + ccp key1; // first key, upper case + ccp key2; // NULL or second key, upper case + + ccp srt_load; // NULL or prefix vor SRT reading to allow prefix changes + ccp srt_prefix; // NULL prefix or SRT reading + writing + // If NULL: don't save/restore + // 'srt_load' is scanned before 'srt_prefix' + + float *color_val; // 6 values for mark,info,gint,warn,err,bad + // if NULL then use system list + u_nsec_t *color_dur; // 6 values for mark,info,gint,warn,err,bad + // if NULL then use system list +} +UsageCtrl_t; + +//----------------------------------------------------------------------------- + +extern PointerList_t usage_count_mgr; + +// NOW_NSEC: 0 or GetTimerNSec(), but not GetTime*() +u_nsec_t MaintainUsageByMgr ( u_nsec_t now_nsec ); +void UpdateByUCI ( const UsageCtrl_t *uci, u_nsec_t now_nsec ); +void UpdateUsageByMgr ( u_nsec_t now_nsec ); +void AddToUsageMgr ( const UsageCtrl_t *uci ); + +void ListUsageCount +( + PrintMode_t *p_pm, // NULL or print mode + const UsageCtrl_t *uci, // NULL or object to list + int print_mode, // see LUC_PM_* + s_nsec_t limit_nsec // >0: limit output until # is reached +); + +void ListUsageDuration +( + PrintMode_t *p_pm, // NULL or print mode + const UsageCtrl_t *uci, // NULL or object to list + int print_mode, // see LUC_PM_* + s_nsec_t limit_nsec // >0: limit output until # is reached +); + +static inline UsageParam_t * GetUsageParam ( const UsageCtrl_t *uci ) + { DASSERT(uci); return uci->par ? uci->par : uci->uc ? &uci->uc->par : uci->ud ? &uci->ud->par : 0; } + +static inline char GetUsageTypeChar ( const UsageCtrl_t *uci ) + { return !uci ? '-' : uci->uc ? 'C' : uci->ud ? 'D' : uci->par ? 'x' : '?'; } + +void SaveCurrentStateByUsageCountMgr ( FILE *f, uint fw_name ); +void RestoreStateByUsageCountMgr ( RestoreState_t *rs ); + +/////////////////////////////////////////////////////////////////////////////// +// [[IntervalInfo_t]] + +typedef struct IntervalInfo_t +{ + u_nsec_t nsec; + u_usec_t usec; + ccp name; +} +IntervalInfo_t; + +extern const IntervalInfo_t interval_info[]; + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// cpu usage /////////////// +/////////////////////////////////////////////////////////////////////////////// + +#if TEST_USAGE_COUNT + #define CPU_USAGE_ENTRIES 11 // number of entries +#else + #define CPU_USAGE_ENTRIES 30 // number of entries +#endif + +#if IS_DEVELOP + #define CPU_USAGE_ENABLED 0 // initial value for cpu_usage.par.enabled +#else + #define CPU_USAGE_ENABLED 0 // initial value for cpu_usage.par.enabled +#endif + +#define CPU_USAGE_FIRST_ADD 8 // first entry where values wil be added +#define CPU_USAGE_NEXT_MIN(v) (15*(v)/8) + +//----------------------------------------------------------------------------- +// [[CpuUsageEntry_t]] + +typedef struct CpuUsageEntry_t +{ + u_usec_t elapsed_usec; // elapsed time, by GetTimerUSec() + u_usec_t utime_usec; // user CPU time used + u_usec_t stime_usec; // system CPU time used + u_sec_t time_sec; // time of record, by GetTimeUSec(false) + float top1s; // = 100.0*(utime+stime)/elapsed for 1s + float top5s; // = 100.0*(utime+stime)/elapsed for 5s + u32 n_wait; // number of waits (poll() or select()) + float topw1s; // top number of waits in 1 sec + float topw5s; // top number of waits in 5 sec +} +__attribute__ ((packed)) CpuUsageEntry_t; + +//----------------------------------------------------------------------------- +// [[CpuUsage_t]] + +typedef struct CpuUsage_t +{ + UsageParam_t par; // base parameters + CpuUsageEntry_t ref; // reference with absolute values + #if TEST_USAGE_COUNT + CpuUsageEntry_t entry[CPU_USAGE_ENTRIES+1]; // list of entries with delta values + #else + CpuUsageEntry_t entry[CPU_USAGE_ENTRIES]; // list of entries with delta values + #endif +} +CpuUsage_t; + +//----------------------------------------------------------------------------- + +extern CpuUsage_t cpu_usage; +extern const UsageCtrl_t cpu_usage_ctrl; + +void UpdateCpuUsage(void); +void UpdateCpuUsageByUCI ( const UsageCtrl_t *, u_nsec_t ); // both params ignored +void UpdateCpuUsageIncrement(void); + +void ListCpuUsage +( + PrintMode_t *p_pm, // NULL or print mode + const UsageCtrl_t *uci, // ignored! + int print_mode, // see LUC_PM_* + s_nsec_t limit_nsec // >0: limit output until # is reached +); + +// stat about last 'usec' microseconds +CpuUsageEntry_t GetCpuUsage ( s_usec_t usec ); +uint GetCpuUsagePercent ( s_usec_t usec ); + +void AddCpuEntry ( CpuUsageEntry_t *dest, const CpuUsageEntry_t *add ); + +static inline uint GetCpuEntryPercent ( const CpuUsageEntry_t *entry ) +{ + DASSERT(entry); + return entry->elapsed_usec + ? 100 * ( entry->utime_usec + entry->stime_usec + entry->elapsed_usec/200 ) + / entry->elapsed_usec + : 0; +} + +static inline double GetCpuEntryRatio ( const CpuUsageEntry_t *entry ) +{ + DASSERT(entry); + return entry->elapsed_usec + ? (double)(entry->utime_usec + entry->stime_usec ) / entry->elapsed_usec + : 0.0; +} + +//----------------------------------------------------------------------------- + +// get percent, returns previuis valus if delay is <10ms +double get_rusage_percent (void); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// sockaddr support /////////////// /////////////////////////////////////////////////////////////////////////////// -// [[sockaddr_t]] [[sockaddr_in_t]] [[sockaddr_un_t]] [[sockaddr_info_t]] +// [[sockaddr_in46_t]] + +typedef struct sockaddr_in46_t +{ + union + { + sa_family_t family; // is first member of each sockaddr_* structure + sockaddr_in4_t in4; + sockaddr_in6_t in6; + }; +} +sockaddr_in46_t; + +//----------------------------------------------------------------------------- +// [[sockaddr_dclib_t]] + +typedef struct sockaddr_dclib_t +{ + union + { + sa_family_t family; // is first member of each sockaddr_* structure + sockaddr_in4_t in4; + sockaddr_in6_t in6; + sockaddr_un_t un; + }; +} +sockaddr_dclib_t; -typedef struct sockaddr sockaddr_t; -typedef struct sockaddr_in sockaddr_in_t; -typedef struct sockaddr_un sockaddr_un_t; +//----------------------------------------------------------------------------- +// [[sockaddr_info_t]] typedef struct sockaddr_info_t { @@ -4377,7 +5488,7 @@ typedef struct sockaddr_info_t } sockaddr_info_t; -//----------------------------------------------------------------------------- +/////////////////////////////////////////////////////////////////////////////// // [[doxygen]] static inline sockaddr_info_t CreateSockaddrInfo ( cvp sa, uint size ) @@ -4402,24 +5513,95 @@ static inline void SetupSockaddrInfo ( sockaddr_info_t *sai, cvp sa, uint size ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// ScanIP4 /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[ipv4_class_t]] + +typedef enum ipv4_class_t +{ + CIP4_ERROR = -1, // error + CIP4_INVALID = 0, // not an IPv4 + CIP4_NUMERIC, // 32 bit number only + CIP4_ABBREV, // abbreviated IPv4 (trailing point) + CIP4_CLASS_A, // IPv4 in class-A notation + CIP4_CLASS_B, // IPv4 in class-B notation + CIP4_CLASS_C, // IPv4 in class-C notation +} +ipv4_class_t; + +//----------------------------------------------------------------------------- + +ipv4_class_t ScanIP4 +( + ipv4_t *ret_ip4, // not NULL: return numeric IPv4 here + ccp addr, // address to analyze + int addr_len // length of addr; if <0: use strlen(addr) +); + +//----------------------------------------------------------------------------- + +char * NormalizeIP4 +( + // Return a pointer to dest if valid IPv4, + // Otherwise return 0 and buf is not modifieid. + + char *buf, // result buffer, can be 'addr' + // if NULL: use a local circulary static buffer + size_t buf_size, // size of 'buf', ignored if buf==NULL + bool c_notation, // TRUE: force lass-C notation (a.b.c.d) + + ccp addr, // address to analyze + int addr_len // length of addr; if <0: use strlen(addr) +); + +//----------------------------------------------------------------------------- + +static inline ipv4_class_t CheckIP4 +( + ccp addr, // address to analyze + int addr_len // length of addr; if <0: use strlen(addr) +) +{ + return ScanIP4(0,addr,addr_len); +} + +//----------------------------------------------------------------------------- + +int dclib_aton ( ccp addr, struct in_addr *inp ); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// PrintIP4*() /////////////// /////////////////////////////////////////////////////////////////////////////// +#define FW_IPV4_N 10 // 4294967295 #define FW_IPV4_A 12 // 255.16777215 #define FW_IPV4_B 13 // 255.255.65535 #define FW_IPV4_C 15 // 255.255.255.255 #define FW_IPV4_PORT 5 // 65535 +#define FW_IPV4_N_PORT (FW_IPV4_N+1+FW_IPV4_PORT) #define FW_IPV4_A_PORT (FW_IPV4_A+1+FW_IPV4_PORT) #define FW_IPV4_B_PORT (FW_IPV4_B+1+FW_IPV4_PORT) #define FW_IPV4_C_PORT (FW_IPV4_C+1+FW_IPV4_PORT) //----------------------------------------------------------------------------- +char * PrintIP4N +( + // print as unsigned number (CIP4_NUMERIC) + + char *buf, // result buffer + // NULL: use a local circulary static buffer + size_t buf_size, // size of 'buf', ignored if buf==NULL + u32 ip4, // IP4 to print + s32 port // 0..0xffff: add ':port' +); + char * PrintIP4A ( - // print in A-notation + // print in A-notation (CIP4_CLASS_A) char *buf, // result buffer // NULL: use a local circulary static buffer @@ -4430,7 +5612,7 @@ char * PrintIP4A char * PrintIP4B ( - // print in A-notation + // print in B-notation (CIP4_CLASS_B) char *buf, // result buffer // NULL: use a local circulary static buffer @@ -4480,6 +5662,20 @@ char * PrintAlignedIP4 ); //----------------------------------------------------------------------------- +// print by enum ipv4_class_t + +char * PrintIP4ByMode +( + char *buf, // result buffer + // NULL: use a local circulary static buffer + size_t buf_size, // size of 'buf', ignored if buf==NULL + u32 ip4, // IP4 to print + ipv4_class_t mode, // CIP4_NUMERIC | CIP4_CLASS_A | CIP4_CLASS_B: + // force numeric or class-A/B output; otherwise class-C output + s32 port // 0..0xffff: add ':port' +); + +//----------------------------------------------------------------------------- struct sockaddr_in; static inline char * PrintIP4sa @@ -4491,9 +5687,10 @@ static inline char * PrintIP4sa const struct sockaddr_in *sa // socket address ) { - DASSERT(sa); - return PrintIP4(buf,buf_size, - ntohl(sa->sin_addr.s_addr), ntohs(sa->sin_port) ); + return sa + ? PrintIP4(buf,buf_size, + ntohl(sa->sin_addr.s_addr), ntohs(sa->sin_port) ) + : "-"; } static inline char * PrintRightIP4sa @@ -4790,7 +5987,8 @@ exmem_key_t * AppendEML ( exmem_list_t * eml, ccp key, CopyMode_t cm_key, const exmem_t *data, CopyMode_t cm_data ); // Return true if item found and removed -bool RemoveEML ( exmem_list_t * eml, ccp key ); +bool RemoveByIndexEML ( exmem_list_t * eml, int index ); +bool RemoveByKeyEML ( exmem_list_t * eml, ccp key ); // find first pattern that matches @@ -4808,6 +6006,55 @@ void AddStandardSymbolsEML ( exmem_list_t * eml, bool overwrite ); // /////////////////////////////////////////////////////////////////////////////// +/////////////// MultiColumn /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[MultiColumn_t]] + +typedef struct MultiColumn_t +{ + FILE *f; // NULL or output file + const ColorSet_t + *colset; // NULL or color set for the frame + ccp prefix; // NULL or line prefix + int indent; // indention after prefix + ccp sep; // NULL or separator for frame_mode 0 and 1 + ccp eol; // NULL or end-of-line string + + int fw; // max field width + int min_rows; // minimal number of rows before MC + int max_cols; // >0: maximal number columns + + int frame_mode; // 0:ASCII, 1:single line, 2:double line + bool print_header; // TRUE: print column header + bool print_footer; // TRUE: print footer line + + ccp head_key; // NULL or name of key column, default="Name" + ccp head_val; // NULL or name of value column, default="Value" + + int debug; // >0: print basic debug info + // >1: be verbose + + exmem_list_t list; // list of parameters to print +} +MultiColumn_t; + +//----------------------------------------------------------------------------- + +void ResetMultiColumn ( MultiColumn_t *mc ); + +// return the number of printed lines including header and footer, or -1 on error +int PrintMultiColumn ( const MultiColumn_t *mc ); + +// Wrapper for short definition lines +// opt == 0 align right value +// opt >= 1 align left and try field width of # for value + +exmem_key_t * PutLineMC ( MultiColumn_t *mc, uint opt, ccp key, ccp value, CopyMode_t cm_value ); +exmem_key_t * PrintLineMC ( MultiColumn_t *mc, uint opt, ccp key, ccp format, ... ) + __attribute__ ((__format__(__printf__,4,5))); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// Memory Map /////////////// /////////////////////////////////////////////////////////////////////////////// // [[MemMapItem_t]] @@ -5122,6 +6369,7 @@ uint DropDataBuf /////////////////////////////////////////////////////////////////////////////// /////////////// ResizeElement_t, ResizeHelper_t /////////////// /////////////////////////////////////////////////////////////////////////////// +// [[ResizeElement_t]] typedef struct ResizeElement_t { @@ -5131,6 +6379,7 @@ typedef struct ResizeElement_t ResizeElement_t; //----------------------------------------------------------------------------- +// [[ResizeHelper_t]] typedef struct ResizeHelper_t { @@ -5393,6 +6642,11 @@ typedef enum SaveRestoreType_t SRT_DEF_ARRAY, // define/end an array of structs + SRT_MODE__BEGIN, //--- begin of modes + SRT_MODE_ASSIGN, // load option: assign numeric values (default) + SRT_MODE_ADD, // load option: add numeric values + SRT_MODE__END, //--- end of modes + SRT__IS_LIST, //----- from here: print lists; also used as separator SRT_STRING_FIELD, // var is StringField_t @@ -5411,10 +6665,18 @@ typedef struct SaveRestoreTab_t uint offset; // offset of variable uint size; // sizeof( var or string ) ccp name; // name in configuration file - s16 n_elem; // >0: is array with N elements - // <0: is array with -N elements, use last SRT_COUNT - u8 type; // SaveRestoreType_t - u8 emode; // EncodeMode_t + + union + { + struct + { + s16 n_elem; // >0: is array with N elements + // <0: is array with -N elements, use last SRT_COUNT + u8 type; // SaveRestoreType_t + u8 emode; // EncodeMode_t + }; + //struct SaveRestoreTab_t *ref; + }; } __attribute__ ((packed)) SaveRestoreTab_t; @@ -5424,7 +6686,8 @@ __attribute__ ((packed)) SaveRestoreTab_t; // #undef SRT_NAME // #define SRT_NAME name_of_the_struct -#define DEF_SRT_VAR(v,ne,n,t,e) {offsetof(SRT_NAME,v),sizeof(((SRT_NAME*)0)->v),n,ne,t,e} +#define DEF_SRT_VAR(v,ne,n,t,e) {offsetof(SRT_NAME,v),sizeof(((SRT_NAME*)0)->v),n, \ + .n_elem=ne,.type=t,.emode=e} #define DEF_SRT_BOOL(v,n) DEF_SRT_VAR(v,1,n,SRT_BOOL,0) #define DEF_SRT_UINT(v,n) DEF_SRT_VAR(v,1,n,SRT_UINT,0) @@ -5458,7 +6721,7 @@ __attribute__ ((packed)) SaveRestoreTab_t; #define DEF_SRT_ARRAY(v,n,t,e) \ {offsetof(SRT_NAME,v), sizeof(((SRT_NAME*)0)->v[0]), n, \ - sizeof(((SRT_NAME*)0)->v)/sizeof(*((SRT_NAME*)0)->v), t, e } + .n_elem=sizeof(((SRT_NAME*)0)->v)/sizeof(*((SRT_NAME*)0)->v), .type=t, .emode=e } #define DEF_SRT_BOOL_A(v,n) DEF_SRT_ARRAY(v,n,SRT_BOOL,0) #define DEF_SRT_UINT_A(v,n) DEF_SRT_ARRAY(v,n,SRT_UINT,0) @@ -5475,7 +6738,7 @@ __attribute__ ((packed)) SaveRestoreTab_t; #define DEF_SRT_ARRAY_C(v,n,t,e) \ {offsetof(SRT_NAME,v), sizeof(((SRT_NAME*)0)->v[0]), n, \ - -(s16)(sizeof(((SRT_NAME*)0)->v)/sizeof(*((SRT_NAME*)0)->v)), t, e } + .n_elem=-(s16)(sizeof(((SRT_NAME*)0)->v)/sizeof(*((SRT_NAME*)0)->v)), .type=t, .emode=e } #define DEF_SRT_BOOL_AC(v,n) DEF_SRT_ARRAY_C(v,n,SRT_BOOL,0) #define DEF_SRT_UINT_AC(v,n) DEF_SRT_ARRAY_C(v,n,SRT_UINT,0) @@ -5492,29 +6755,34 @@ __attribute__ ((packed)) SaveRestoreTab_t; #define DEF_SRT_ARRAY_FL(f,l) \ {offsetof(SRT_NAME,f), sizeof(((SRT_NAME*)0)->f), 0, \ - (offsetof(SRT_NAME,l)-offsetof(SRT_NAME,f))/sizeof(((SRT_NAME*)0)->f)+1, \ - SRT_DEF_ARRAY, 0 } + .n_elem=(offsetof(SRT_NAME,l)-offsetof(SRT_NAME,f))/sizeof(((SRT_NAME*)0)->f)+1, \ + .type=SRT_DEF_ARRAY } #define DEF_SRT_ARRAY_FLC(f,l) \ {offsetof(SRT_NAME,f), sizeof(((SRT_NAME*)0)->f), 0, \ - -(s16)((offsetof(SRT_NAME,l)-offsetof(SRT_NAME,f)) \ - /sizeof(((SRT_NAME*)0)->f)+1), SRT_DEF_ARRAY, 0 } + .n_elem=-(s16)((offsetof(SRT_NAME,l)-offsetof(SRT_NAME,f)) \ + /sizeof(((SRT_NAME*)0)->f)+1), .type=SRT_DEF_ARRAY } #define DEF_SRT_ARRAY_N(v,ne) DEF_SRT_VAR(v[0],ne,0,SRT_DEF_ARRAY,0) #define DEF_SRT_ARRAY_A(v) DEF_SRT_ARRAY(v,0,SRT_DEF_ARRAY,0) #define DEF_SRT_ARRAY_AC(v) DEF_SRT_ARRAY_C(v,0,SRT_DEF_ARRAY,0) -#define DEF_SRT_ARRAY_END() {0,0,0,0,SRT_DEF_ARRAY,0} +#define DEF_SRT_ARRAY_END() {0,0,0,.type=SRT_DEF_ARRAY} //--- global array of structs -#define DEF_SRT_ARRAY_GN(ne) {0,sizeof(SRT_NAME),0,ne,SRT_DEF_ARRAY,0} -#define DEF_SRT_ARRAY_GA(v) {0,sizeof(*v),0,sizeof(v)/sizeof(*v),SRT_DEF_ARRAY,0} +#define DEF_SRT_ARRAY_GN(ne) {0,sizeof(SRT_NAME),0,.n_elem=ne,.type=SRT_DEF_ARRAY} +#define DEF_SRT_ARRAY_GA(v) {0,sizeof(*v),0,.n_elem=sizeof(v)/sizeof(*v),.type=SRT_DEF_ARRAY} + +//--- modes + +#define DEF_SRT_MODE_ASSIGN() {0,0,0,.type=SRT_MODE_ASSIGN} +#define DEF_SRT_MODE_ADD() {0,0,0,.type=SRT_MODE_ADD} //--- special -#define DEF_SRT_SEPARATOR() {0,0,0,0,SRT__IS_LIST,0} -#define DEF_SRT_COMMENT(c) {0,0,c,0,SRT__IS_LIST,0} -#define DEF_SRT_TERM() {0,0,0,0,SRT__TERM,0} +#define DEF_SRT_SEPARATOR() {0,0,0,.type=SRT__IS_LIST} +#define DEF_SRT_COMMENT(c) {0,0,c,.type=SRT__IS_LIST} +#define DEF_SRT_TERM() {0,0,0,.type=SRT__TERM} /////////////////////////////////////////////////////////////////////////////// @@ -5549,6 +6817,13 @@ void RestoreStateByTable ccp prefix // NULL or prefix for names ); +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +extern const SaveRestoreTab_t SRT_UsageCount[]; +extern const SaveRestoreTab_t SRT_UsageDuration[]; +extern const SaveRestoreTab_t SRT_CpuUsage[]; + // /////////////////////////////////////////////////////////////////////////////// /////////////// GrowBuffer_t /////////////// @@ -5811,11 +7086,13 @@ extern int opt_new; // default 0 float double2float ( double d ); // reduce precision uint CreateUniqueIdN ( int range ); -static inline uint CreateUniqueId() { return CreateUniqueIdN(1); } -static inline uint CreateUniqueIdNBO() { return htonl(CreateUniqueIdN(1)); } +static inline uint CreateUniqueId(void) { return CreateUniqueIdN(1); } +static inline uint CreateUniqueIdNBO(void) { return htonl(CreateUniqueIdN(1)); } void Sha1Hex2Bin ( sha1_hash_t bin, ccp src, ccp end ); void Sha1Bin2Hex ( sha1_hex_t hex, cvp bin ); + +// return CircBuf() ccp GetSha1Hex ( cvp bin ); /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/dclib-cli.c b/project/dclib/dclib-cli.c index c4a3015..c4a5664 100644 --- a/project/dclib/dclib-cli.c +++ b/project/dclib/dclib-cli.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -41,248 +41,6 @@ // /////////////////////////////////////////////////////////////////////////////// -/////////////// arg_manager_t /////////////// -/////////////////////////////////////////////////////////////////////////////// - -void ResetArgManager ( arg_manager_t *am ) -{ - static char *null_list[] = {0}; - - if (am) - { - if (am->size) - { - uint i; - for ( i = 0; i < am->argc; i++ ) - FreeString(am->argv[i]); - if ( am->argv != null_list ) - FREE(am->argv); - } - memset(am,0,sizeof(*am)); - - am->argv = null_list; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -void SetupArgManager ( arg_manager_t *am, int argc, char ** argv, bool clone ) -{ - DASSERT(am); - memset(am,0,sizeof(*am)); - if (clone) - CloneArgManager(am,argc,argv); - else - AttachArgManager(am,argc,argv); -} - -/////////////////////////////////////////////////////////////////////////////// - -void AttachArgManager ( arg_manager_t *am, int argc, char ** argv ) -{ - DASSERT(am); - ResetArgManager(am); - am->argc = argc; - am->argv = argv; -} - -/////////////////////////////////////////////////////////////////////////////// - -void CloneArgManager ( arg_manager_t *am, int argc, char ** argv ) -{ - DASSERT(am); - AttachArgManager(am,argc,argv); - PrepareEditArgManager(am,0); -} - -/////////////////////////////////////////////////////////////////////////////// - -void CopyArgManager ( arg_manager_t *dest, const arg_manager_t *src ) -{ - DASSERT(dest); - if (!src) - ResetArgManager(dest); - else if( dest != src ) - AttachArgManager(dest,src->argc,src->argv); -} - -/////////////////////////////////////////////////////////////////////////////// - -void MoveArgManager ( arg_manager_t *dest, arg_manager_t *src ) -{ - DASSERT(dest); - ResetArgManager(dest); - if (src) - { - dest->argv = src->argv; - dest->argc = src->argc; - dest->size = src->size; - memset(src,0,sizeof(*src)); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -void PrepareEditArgManager ( arg_manager_t *am, int needed_space ) -{ - DASSERT(am); - - uint new_size = am->argc; - if ( needed_space > 0 ) - new_size += needed_space; - new_size = GetGoodAllocSize2(new_size+(new_size>>4)+10,sizeof(*am->argv)); - PRINT("PrepareEditArgManager(,%d) n=%d, size: %d -> %d\n", - needed_space, am->argc, am->size, new_size ); - - if (am->size) - am->argv = REALLOC(am->argv,sizeof(*am->argv)*new_size); - else - { - char **old = am->argv; - am->argv = MALLOC(sizeof(*am->argv)*new_size); - - uint i; - for ( i = 0; i < am->argc; i++ ) - am->argv[i] = old[i] ? STRDUP(old[i]) : 0; - } - am->size = new_size - 1; - DASSERT( am->argc <= am->size ); - am->argv[am->argc] = 0; -} - -/////////////////////////////////////////////////////////////////////////////// - -uint AppendArgManager ( arg_manager_t *am, ccp arg1, ccp arg2, bool move_arg ) -{ - DASSERT(am); - PRINT("AppendArgManager(,%s,%s,%d)\n",arg1,arg2,move_arg); - return InsertArgManager(am,am->argc,arg1,arg2,move_arg); -} - -/////////////////////////////////////////////////////////////////////////////// - -uint InsertArgManager - ( arg_manager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg ) -{ - PRINT("InsertArgManager(,%d,%s,%s,%d)\n",pos,arg1,arg2,move_arg); - - pos = CheckIndex1(am->argc,pos); - const int n = (arg1!=0) + (arg2!=0); - if (n) - { - PrepareEditArgManager(am,n); - DASSERT( pos>0 && pos <= am->argc ); - char **dest = am->argv + pos; - if ( pos < am->argc ) - memmove( dest+n, dest, (u8*)(am->argv+am->argc) - (u8*)dest ); - if (arg1) - *dest++ = move_arg ? (char*)arg1 : STRDUP(arg1); - if (arg2) - *dest++ = move_arg ? (char*)arg2 : STRDUP(arg2); - am->argc += n; - am->argv[am->argc] = 0; - } - return pos+n; -} - -/////////////////////////////////////////////////////////////////////////////// - -uint ReplaceArgManager - ( arg_manager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg ) -{ - PRINT("ReplaceArgManager(,%d,%s,%s,%d)\n",pos,arg1,arg2,move_arg); - - pos = CheckIndex1(am->argc,pos); - const int n = (arg1!=0) + (arg2!=0); - if (n) - { - PrepareEditArgManager(am,n); - DASSERT( pos>0 && pos <= am->argc ); - char **dest = am->argv + pos; - if (arg1) - { - if ( pos++ < am->argc ) - FreeString(*dest); - *dest++ = move_arg ? (char*)arg1 : STRDUP(arg1); - } - if (arg2) - { - if ( pos++ < am->argc ) - FreeString(*dest); - *dest++ = move_arg ? (char*)arg2 : STRDUP(arg2); - } - if ( pos > am->argc ) - { - am->argc = pos; - am->argv[am->argc] = 0; - } - } - return pos; -} - -/////////////////////////////////////////////////////////////////////////////// - -uint RemoveArgManager ( arg_manager_t *am, int pos, int count ) -{ - DASSERT(am); - - #if HAVE_PRINT - const int oldpos = pos; - #endif - const int n = CheckIndexC(am->argc,&pos,count); - PRINT("RemoveArgManager(,%d,%d) : remove n=%d: %d..%d\n", - oldpos, count, n, pos, pos+n ); - - DASSERT( pos >= 0 && pos <= am->argc ); - DASSERT( n >= 0 && pos+n <= am->argc ); - - if ( n > 0 ) - { - PrepareEditArgManager(am,0); - char **dest = am->argv + pos; - - uint i; - for ( i = 0; i <n; i++ ) - FreeString(dest[i]); - am->argc -= n; - memmove( dest, dest+n, (u8*)(am->argv+am->argc) - (u8*)dest ); - am->argv[am->argc] = 0; - } - return pos; -} - -/////////////////////////////////////////////////////////////////////////////// - -void DumpArgManager ( FILE *f, int indent, const arg_manager_t *am, ccp title ) -{ - if ( !f || !am ) - return; - - indent = NormalizeIndent(indent); - if (title) - fprintf(f,"%*s" "ArgManager[%s]: N=%d", - indent,"", title, am->argc ); - else - fprintf(f,"%*s" "ArgManager: N=%d", indent,"", am->argc ); - - if (am->size) - fprintf(f,"/%u\n",am->size); - else - fputc('\n',f); - - if (am->argc) - { - char buf[10]; - int fw = snprintf(buf,sizeof(buf),"%u",am->argc-1)+2; - - uint i; - for ( i = 0; i < am->argc; i++ ) - fprintf(f,"%*s%*u: |%s|\n", indent,"", fw,i, am->argv[i] ); - } -} - -// -/////////////////////////////////////////////////////////////////////////////// /////////////// global commands /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/dclib-color.c b/project/dclib/dclib-color.c index ef0ca01..eaff47a 100644 --- a/project/dclib/dclib-color.c +++ b/project/dclib/dclib-color.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -380,7 +380,7 @@ uint PutColoredLines int cont_indent = -1; uint n_lines = 0, n_space = 0; uint column = 0; - //ccp col_begin = ""; + ccp next_col = 0; enum { GB_NONE, GB_SIGN, GB_COMMA, GB_SPACE } gb_mode = GB_NONE; @@ -476,7 +476,8 @@ uint PutColoredLines if (*col) { - cur.dest = StringCopyE(cur.dest,buf+sizeof(buf),col); + //cur.dest = StringCopyE(cur.dest,buf+sizeof(buf),col); + next_col = col; if ( *text == '}' ) cur.col_active = col; else @@ -602,6 +603,12 @@ uint PutColoredLines while ( n_space > 0 ) *cur.dest++ = ' ', n_space--; + if (next_col) + { + cur.dest = StringCopyE(cur.dest,buf+sizeof(buf),next_col); + next_col = 0; + } + cur.dest = PrintUTF8Char(cur.dest,code); if ( cur.dest > buf_end ) goto new_line; // should never happen! @@ -821,7 +828,8 @@ static void PrintColorInfo ( FILE *f, color_info_t *ci ) enumError Command_TESTCOLORS ( int argc, char ** argv ) { #if HAVE_PRINT - GetColorByName(colout,"blue"); + // to force an order-check + GetColorOffsetByName("blue"); #endif printf("TEST COLORS: %u arguments:\n",argc); @@ -1093,7 +1101,6 @@ term_size_t GetTermSize ( int default_width, int default_height ) else { ts = GetTermSizeFD(STDOUT_FILENO,default_width,default_height); - if ( opt_width > 0 ) ts.width = opt_width; else if ( opt_max_width > 0 && ts.width > opt_max_width ) @@ -1253,6 +1260,45 @@ void EnableAutoTermSize() /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// +good_term_width_t good_term_width = +{ + .min_width = 40, + .def_width = 100, + .max_width = 120, + .good_width = 120 +}; + +/////////////////////////////////////////////////////////////////////////////// + +int GetGoodTermWidth ( good_term_width_t *gtw, bool force ) +{ + if (!gtw) + gtw = &good_term_width; + + if ( force || !gtw->setup_done ) + { + gtw->setup_done = true; + int good_width = opt_width; + if (!good_width) + { + good_width = GetTermWidth(gtw->def_width,gtw->min_width); + const int max = opt_max_width ? opt_max_width : gtw->max_width; + if ( good_width > max ) + good_width = max; + } + + if ( good_width < gtw->min_width ) + good_width = gtw->min_width; + + gtw->good_width = good_width; + } + return gtw->good_width; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + ccp TermCursorUp = TERM_CURSOR_UP; // move cursor up ccp TermCursorDown = TERM_CURSOR_DOWN; // move cursor down ccp TermCursorRight = TERM_CURSOR_RIGHT; // move cursor right @@ -1275,6 +1321,7 @@ ccp TermSetWrap = TERM_SET_WRAP; // enabled line wrapping ccp TermResetWrap = TERM_RESET_WRAP; // disable line wrapping ccp TermTextModeBeg = TERM_TEXT_MODE_BEG; // begin of text mode sequence +ccp TermTextModeBeg0 = TERM_TEXT_MODE_BEG; // begin of text mode sequence with reset ccp TermTextModeEnd = TERM_TEXT_MODE_END; // end of text mode sequence ccp TermTextModeReset = TERM_TEXT_MODE_RESET; // reset text mode @@ -1382,7 +1429,7 @@ const int Color18Index[18+1] = // 18 elements + -1 as terminator static char * GetColorCircBuf ( uint len ) { - static char circ_buf[1024]; + static char circ_buf[2048]; static char *circ_ptr = circ_buf; DASSERT( circ_ptr >= circ_buf && circ_ptr <= circ_buf + sizeof(circ_buf) ); @@ -2622,7 +2669,7 @@ ccp GetTextMode //--- output char buf[100], *end = buf + sizeof(buf); - char *dest = StringCopyE(buf,end,TermTextModeBeg); + char *dest = StringCopyE(buf,end,TermTextModeBeg0); const uint bg = (uint)bg_index < TCI__IGNORE ? color_index[bg_index] : ~0; @@ -3028,7 +3075,7 @@ ccp GetTextMode //--- output char buf[100], *end = buf + sizeof(buf); - char *dest = StringCopyE(buf,end,TermTextModeBeg); + char *dest = StringCopyE(buf,end,TermTextModeBeg0); ccp sep = ""; if ( (uint)font_index < TCI__IGNORE ) @@ -3063,6 +3110,129 @@ ccp GetTextMode // /////////////////////////////////////////////////////////////////////////////// +/////////////// color ids /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[color_helper_tab_t]] + +const TermColorId_t color8id = { .col = +{ + 0x00, // TCE_GREY0, + 0x00, // TCE_GREY1, + 0x10, // TCE_GREY2, + 0x10, // TCE_GREY3, + 0x10, // TCE_GREY4, + 0x07, // TCE_GREY5, + 0x07, // TCE_GREY6, + 0x07, // TCE_GREY7, + 0x17, // TCE_GREY8, + 0x17, // TCE_GREY9, + + 0x01, // TCE_RED_MAGENTA, + 0x01, // TCE_RED, + 0x01, // TCE_RED_ORANGE, + 0x01, // TCE_ORANGE_RED, + 0x01, // TCE_ORANGE, + 0x03, // TCE_ORANGE_YELLOW, + 0x03, // TCE_YELLOW_ORANGE, + 0x03, // TCE_YELLOW, + 0x03, // TCE_YELLOW_GREEN, + 0x02, // TCE_GREEN_YELLOW, + 0x02, // TCE_GREEN, + 0x02, // TCE_GREEN_CYAN, + 0x06, // TCE_CYAN_GREEN, + 0x06, // TCE_CYAN, + 0x06, // TCE_CYAN_BLUE, + 0x04, // TCE_BLUE_CYAN, + 0x04, // TCE_BLUE, + 0x04, // TCE_BLUE_MAGENTA, + 0x05, // TCE_MAGENTA_BLUE, + 0x05, // TCE_MAGENTA, + 0x05, // TCE_MAGENTA_RED, + + 0x11, // TCE_B_RED_MAGENTA, + 0x11, // TCE_B_RED, + 0x11, // TCE_B_RED_ORANGE, + 0x11, // TCE_B_ORANGE_RED, + 0x11, // TCE_B_ORANGE, + 0x13, // TCE_B_ORANGE_YELLOW, + 0x13, // TCE_B_YELLOW_ORANGE, + 0x13, // TCE_B_YELLOW, + 0x13, // TCE_B_YELLOW_GREEN, + 0x12, // TCE_B_GREEN_YELLOW, + 0x12, // TCE_B_GREEN, + 0x12, // TCE_B_GREEN_CYAN, + 0x16, // TCE_B_CYAN_GREEN, + 0x16, // TCE_B_CYAN, + 0x16, // TCE_B_CYAN_BLUE, + 0x14, // TCE_B_BLUE_CYAN, + 0x14, // TCE_B_BLUE, + 0x14, // TCE_B_BLUE_MAGENTA, + 0x15, // TCE_B_MAGENTA_BLUE, + 0x15, // TCE_B_MAGENTA, + 0x15, // TCE_B_MAGENTA_RED, +}}; + +// values for 38;5;x or 48;5;x +const TermColorId_t color256id = { .col = +{ + 232, // TCE_GREY0, + 235, // TCE_GREY1, + 237, // TCE_GREY2, + 240, // TCE_GREY3, + 242, // TCE_GREY4, + 245, // TCE_GREY5, + 247, // TCE_GREY6, + 250, // TCE_GREY7, + 252, // TCE_GREY8, + 255, // TCE_GREY9, + + 161, // TCE_RED_MAGENTA, + 160, // TCE_RED, + 166, // TCE_RED_ORANGE, + 166, // TCE_ORANGE_RED, + 172, // TCE_ORANGE, + 136, // TCE_ORANGE_YELLOW, + 136, // TCE_YELLOW_ORANGE, + 142, // TCE_YELLOW, + 106, // TCE_YELLOW_GREEN, + 70, // TCE_GREEN_YELLOW, + 34, // TCE_GREEN, + 35, // TCE_GREEN_CYAN, + 36, // TCE_CYAN_GREEN, + 37, // TCE_CYAN, + 32, // TCE_CYAN_BLUE, + 27, // TCE_BLUE_CYAN, + 21, // TCE_BLUE, + 92, // TCE_BLUE_MAGENTA, + 128, // TCE_MAGENTA_BLUE, + 164, // TCE_MAGENTA, + 162, // TCE_MAGENTA_RED, + + 198, // TCE_B_RED_MAGENTA, + 196, // TCE_B_RED, + 202, // TCE_B_RED_ORANGE, + 202, // TCE_B_ORANGE_RED, + 208, // TCE_B_ORANGE, + 214, // TCE_B_ORANGE_YELLOW, + 220, // TCE_B_YELLOW_ORANGE, + 226, // TCE_B_YELLOW, + 154, // TCE_B_YELLOW_GREEN, + 118, // TCE_B_GREEN_YELLOW, + 46, // TCE_B_GREEN, + 49, // TCE_B_GREEN_CYAN, + 50, // TCE_B_CYAN_GREEN, + 51, // TCE_B_CYAN, + 75, // TCE_B_CYAN_BLUE, + 111, // TCE_B_BLUE_CYAN, + 105, // TCE_B_BLUE, + 141, // TCE_B_BLUE_MAGENTA, + 177, // TCE_B_MAGENTA_BLUE, + 207, // TCE_B_MAGENTA, + 205, // TCE_B_MAGENTA_RED, +}}; + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// color tables /////////////// /////////////////////////////////////////////////////////////////////////////// // [[color_helper_tab_t]] @@ -3120,6 +3290,8 @@ static const color_helper_tab_t ch_tab_color[] = static const color_helper_tab_t ch_tab_bcolor[] = { + // [[new-color]] + SEP1 JOB1(b_red_magenta) JOB1(b_red) @@ -3150,6 +3322,8 @@ _Static_assert( N_COLORSET_GREY == 10, "wrong N_COLORSET_GREY" ); static const color_helper_tab_t ch_tab_grey[] = { + // [[new-color]] + SEP1 JOB1(black) JOB1(b_black) @@ -3173,8 +3347,10 @@ static const color_helper_tab_t ch_tab_grey[] = //----------------------------------------------------------------------------- -static const color_helper_tab_t ch_tab_name[] = +static const color_helper_tab_t ch_tab_name1[] = { + // [[new-color]] + SEP1 JOB1(setup) @@ -3186,12 +3362,15 @@ static const color_helper_tab_t ch_tab_name[] = JOB1(close) JOB1(file) JOB1(job) + JOB1(debug) + JOB1(log) + JOB1(mark) JOB1(info) JOB1(hint) JOB1(warn) - JOB1(debug) - JOB1(log) + JOB1(err) + JOB1(bad) JOB1(name) JOB1(op) @@ -3202,14 +3381,119 @@ static const color_helper_tab_t ch_tab_name[] = JOB1(fail) JOB1(fail2) JOB1(fatal) + + JOB1(select) + JOB1(differ) + JOB1(stat_line) + JOB1(warn_line) + JOB1(proc_line) + + JOB0 +}; + +//----------------------------------------------------------------------------- +_Static_assert( N_COLORSET_HL_LINE == 4, "wrong N_COLORSET_HL_LINE" ); +_Static_assert( N_COLORSET_ORDER == 9, "wrong N_COLORSET_ORDER" ); + +static const color_helper_tab_t ch_tab_name2[] = +{ + // [[new-color]] + + SEP1 + + JOB2(hl_line0,hl_line[0],0) + JOB2(hl_line1,hl_line[1],0) + JOB2(hl_line2,hl_line[2],0) + JOB2(hl_line3,hl_line[3],0) + JOB2(order0,order[0],0) + JOB2(order1,order[1],0) + JOB2(order2,order[2],0) + JOB2(order3,order[3],0) + JOB2(order4,order[4],0) + JOB2(order5,order[5],0) + JOB2(order6,order[6],0) + JOB2(order7,order[7],0) + JOB2(order8,order[8],0) + JOB1(cite) + JOB1(status) + JOB1(highlight) + JOB2(hl,highlight,1) + JOB1(hide) + + JOB1(heading) + JOB2(head,heading,1) + JOB1(caption) + JOB1(section) + JOB1(syntax) + JOB1(cmd) + JOB1(option) + JOB2(opt,option,1) + JOB1(param) + JOB2(par,param,1) + + JOB1(off) + JOB1(on) + + JOB0 +}; + +//----------------------------------------------------------------------------- +_Static_assert( N_COLORSET_HL_LINE == 4, "wrong N_COLORSET_HL_LINE" ); +_Static_assert( N_COLORSET_ORDER == 9, "wrong N_COLORSET_ORDER" ); + +static const color_helper_tab_t ch_tab_name[] = +{ + // [[new-color]] + + SEP1 + + JOB1(setup) + JOB1(run) + JOB1(abort) + JOB1(finish) + JOB1(script) + JOB1(open) + JOB1(close) + JOB1(file) + JOB1(job) + JOB1(debug) + JOB1(log) + JOB1(mark) + JOB1(info) + JOB1(hint) + JOB1(warn) + JOB1(err) JOB1(bad) + JOB1(name) + JOB1(op) + JOB1(value) + JOB2(val,value,1) + JOB1(success) + JOB1(error) + JOB1(fail) + JOB1(fail2) + JOB1(fatal) + JOB1(select) JOB1(differ) JOB1(stat_line) JOB1(warn_line) JOB1(proc_line) + JOB2(hl_line0,hl_line[0],0) + JOB2(hl_line1,hl_line[1],0) + JOB2(hl_line2,hl_line[2],0) + JOB2(hl_line3,hl_line[3],0) + JOB2(order0,order[0],0) + JOB2(order1,order[1],0) + JOB2(order2,order[2],0) + JOB2(order3,order[3],0) + JOB2(order4,order[4],0) + JOB2(order5,order[5],0) + JOB2(order6,order[6],0) + JOB2(order7,order[7],0) + JOB2(order8,order[8],0) JOB1(cite) JOB1(status) JOB1(highlight) @@ -3293,11 +3577,14 @@ const ColorSet_t * GetColorSet8() col.close = STRDUP(GetTextMode(1,TTM_COL_CLOSE)); col.file = STRDUP(GetTextMode(1,TTM_COL_FILE)); col.job = STRDUP(GetTextMode(1,TTM_COL_JOB)); + col.debug = STRDUP(GetTextMode(1,TTM_COL_DEBUG)); + col.log = STRDUP(GetTextMode(1,TTM_COL_LOG)); + col.mark = STRDUP(GetTextMode(1,TTM_COL_MARK)); col.info = STRDUP(GetTextMode(1,TTM_COL_INFO)); col.hint = STRDUP(GetTextMode(1,TTM_COL_HINT)); col.warn = STRDUP(GetTextMode(1,TTM_COL_WARN)); - col.debug = STRDUP(GetTextMode(1,TTM_COL_DEBUG)); - col.log = STRDUP(GetTextMode(1,TTM_COL_LOG)); + col.err = STRDUP(GetTextMode(1,TTM_COL_ERR)); + col.bad = STRDUP(GetTextMode(1,TTM_COL_BAD)); col.name = STRDUP(GetTextMode(1,TTM_COL_NAME)); col.op = STRDUP(GetTextMode(1,TTM_COL_OP)); col.value = STRDUP(GetTextMode(1,TTM_COL_VALUE)); @@ -3306,8 +3593,6 @@ const ColorSet_t * GetColorSet8() col.fail = STRDUP(GetTextMode(1,TTM_COL_FAIL)); col.fail2 = STRDUP(GetTextMode(1,TTM_COL_FAIL2)); col.fatal = STRDUP(GetTextMode(1,TTM_COL_FATAL)); - col.mark = STRDUP(GetTextMode(1,TTM_COL_MARK)); - col.bad = STRDUP(GetTextMode(1,TTM_COL_BAD)); col.select = STRDUP(GetTextMode(1,TTM_COL_SELECT)); col.differ = STRDUP(GetTextMode(1,TTM_COL_DIFFER)); col.stat_line = STRDUP(GetTextMode(1,TTM_COL_STAT_LINE)); @@ -3327,6 +3612,25 @@ const ColorSet_t * GetColorSet8() col.on = STRDUP(GetTextMode(1,TTM_COL_ON)); col.off = STRDUP(GetTextMode(1,TTM_COL_OFF)); + _Static_assert( N_COLORSET_HL_LINE == 4, "wrong N_COLORSET_HL_LINE" ); + + col.hl_line[0] = STRDUP(GetTextMode(1,TTM_COL_HL_LINE0)); + col.hl_line[1] = STRDUP(GetTextMode(1,TTM_COL_HL_LINE1)); + col.hl_line[2] = STRDUP(GetTextMode(1,TTM_COL_HL_LINE2)); + col.hl_line[3] = STRDUP(GetTextMode(1,TTM_COL_HL_LINE3)); + + _Static_assert( N_COLORSET_ORDER == 9, "wrong N_COLORSET_ORDER" ); + + col.order[0] = STRDUP(GetTextMode(1,TTM_COL_ORDER0)); + col.order[1] = STRDUP(GetTextMode(1,TTM_COL_ORDER1)); + col.order[2] = STRDUP(GetTextMode(1,TTM_COL_ORDER2)); + col.order[3] = STRDUP(GetTextMode(1,TTM_COL_ORDER3)); + col.order[4] = STRDUP(GetTextMode(1,TTM_COL_ORDER4)); + col.order[5] = STRDUP(GetTextMode(1,TTM_COL_ORDER5)); + col.order[6] = STRDUP(GetTextMode(1,TTM_COL_ORDER6)); + col.order[7] = STRDUP(GetTextMode(1,TTM_COL_ORDER7)); + col.order[8] = STRDUP(GetTextMode(1,TTM_COL_ORDER8)); + _Static_assert( N_COLORSET_GREY == 10, "wrong N_COLORSET_GREY" ); col.grey[0] = @@ -3348,8 +3652,8 @@ const ColorSet_t * GetColorSet8() col.red = col.red_orange = col.orange_red = - col.orange = - col.orange_yellow = STRDUP(GetTextMode(1,TTM_NO_BOLD|TTM_RED)); + col.orange = STRDUP(GetTextMode(1,TTM_NO_BOLD|TTM_RED)); + col.orange_yellow = col.yellow_orange = col.yellow = col.yellow_green = STRDUP(GetTextMode(1,TTM_NO_BOLD|TTM_YELLOW)); @@ -3370,8 +3674,8 @@ const ColorSet_t * GetColorSet8() col.b_red = col.b_red_orange = col.b_orange_red = - col.b_orange = - col.b_orange_yellow = STRDUP(GetTextMode(1,TTM_BOLD|TTM_RED)); + col.b_orange = STRDUP(GetTextMode(1,TTM_BOLD|TTM_RED)); + col.b_orange_yellow = col.b_yellow_orange = col.b_yellow = col.b_yellow_green = STRDUP(GetTextMode(1,TTM_BOLD|TTM_YELLOW)); @@ -3416,33 +3720,55 @@ const ColorSet_t * GetColorSet256() //--- special settings - col.setup = "\e[38;5;86;40m"; - col.run = "\e[38;5;229;40m"; - col.abort = "\e[38;5;198;40m"; - col.finish = "\e[38;5;154;40m"; - col.script = "\e[0;30;48;5;219m"; - col.open = "\e[38;5;225;40m"; - col.close = "\e[38;5;219;40m"; - col.heading = "\e[38;5;111;40m"; - col.info = "\e[38;5;49;40m"; - col.hint = "\e[38;5;220;40m"; - col.warn = "\e[38;5;208;40m"; - col.debug = "\e[38;5;210;40m"; - col.error = "\e[38;5;255;48;5;130m"; - col.fail = "\e[38;5;251;48;5;88m"; - col.fail2 = "\e[38;5;255;48;5;88m"; - col.fatal = "\e[38;5;255;48;5;129m"; - col.differ = "\e[38;5;226;48;5;19m"; - col.stat_line = "\e[38;5;231;48;5;19m"; - col.warn_line = "\e[38;5;215;48;5;19m"; - col.hide = "\e[38;5;245;40m"; + col.setup = "\e[0;38;5;86m"; + col.run = "\e[0;38;5;229m"; + col.abort = "\e[0;38;5;198m"; + col.finish = "\e[0;38;5;154m"; + col.script = "\e[0;0;30;48;5;219m"; + col.open = "\e[0;38;5;225m"; + col.close = "\e[0;38;5;219m"; + col.file = "\e[0;38;5;223m"; + col.heading = "\e[0;38;5;111m"; + col.cmd = "\e[0;38;5;123m"; + col.info = "\e[0;38;5;49m"; + col.hint = "\e[0;38;5;220m"; + col.warn = "\e[0;38;5;208m"; + col.err = "\e[0;38;5;198m"; + col.debug = "\e[0;38;5;210m"; + col.error = "\e[0;38;5;255;48;5;130m"; + col.fail = "\e[0;38;5;251;48;5;88m"; + col.fail2 = "\e[0;38;5;255;48;5;88m"; + col.fatal = "\e[0;38;5;255;48;5;129m"; + col.differ = "\e[0;38;5;226;48;5;18m"; + col.stat_line = "\e[0;38;5;231;48;5;18m"; + col.warn_line = "\e[0;38;5;214;48;5;18m"; + col.hide = "\e[0;38;5;245m"; + + _Static_assert( N_COLORSET_HL_LINE == 4, "wrong N_COLORSET_HL_LINE" ); + + col.hl_line[0] = "\e[0;38;5;145m"; + col.hl_line[1] = "\e[0;38;5;159m"; + col.hl_line[2] = "\e[0;38;5;157m"; + col.hl_line[3] = "\e[0;38;5;217m"; + + _Static_assert( N_COLORSET_ORDER == 9, "wrong N_COLORSET_ORDER" ); + + //col.order[0] = + col.order[1] = "\e[0;38;5;39m"; + //col.order[2] = + //col.order[3] = + //col.order[4] = + col.order[5] = "\e[0;38;5;214m"; + col.order[6] = "\e[0;38;5;197m"; + col.order[7] = "\e[0;38;5;213m"; + col.order[8] = "\e[0;38;5;141m"; //--- special settings: color names // dark: // ./mkw-ana testcol 400-420 420-330 330-030 030-033 033-005 005-404 404-400 - // ./mkw-ana testcol 400 410 420 320 330 230 030 032 033 024 005 204 404 402 400 + // ./mkw-ana testcol 401 400 410 420 320 330 230 130 030 031 032 033 024 015 005 204 304 404 402 401 col.red_magenta = "\e[38;5;161m"; col.red = "\e[38;5;160m"; @@ -3468,7 +3794,7 @@ const ColorSet_t * GetColorSet256() // bold: // ./mkw-ana testcol 500-520 520-550 550-050 050-055 055-225 225-515 515-500 - // ./mkw-ana testcol 500 510 520 530 550 350 050 053 055 135 225 425 515 512 500 + // ./mkw-ana testcol 502 500 510 520 530 540 550 350 250 050 053 054 055 135 235 225 325 425 515 513 502 col.b_red_magenta = "\e[38;5;198m"; col.b_red = "\e[38;5;196m"; @@ -3494,15 +3820,15 @@ const ColorSet_t * GetColorSet256() _Static_assert( N_COLORSET_GREY == 10, "wrong N_COLORSET_GREY" ); col.grey[0] = "\e[38;5;232m"; - col.grey[1] = "\e[38;5;235m"; //x + col.grey[1] = "\e[38;5;235m"; col.grey[2] = "\e[38;5;237m"; - col.grey[3] = "\e[38;5;240m"; //x + col.grey[3] = "\e[38;5;240m"; col.grey[4] = "\e[38;5;242m"; - col.grey[5] = "\e[38;5;245m"; //x + col.grey[5] = "\e[38;5;245m"; col.grey[6] = "\e[38;5;247m"; - col.grey[7] = "\e[38;5;250m"; //x + col.grey[7] = "\e[38;5;250m"; col.grey[8] = "\e[38;5;252m"; - col.grey[9] = "\e[38;5;255m"; //x + col.grey[9] = "\e[38;5;255m"; TermColorIndex_t font, bg; for ( font = 0; font < TCI__N_FONT; font++ ) @@ -3512,22 +3838,6 @@ const ColorSet_t * GetColorSet256() } return &col; - -//---------- old definitions ---------- -// -// col.differ = STRDUP(GetColorMode(COLMD_256_COLORS, -// TCI_YELLOW, TCI_BLUE, GCM_ALT|GCM_SHORT )); -// col.stat_line = STRDUP(GetColorMode(COLMD_256_COLORS, -// TCI_WHITE, TCI_BLUE, GCM_ALT|GCM_SHORT )); -// col.warn_line = STRDUP(GetColorMode(COLMD_256_COLORS, -// TCI_ORANGE, TCI_BLUE, GCM_ALT|GCM_SHORT )); -// -// col.orange = STRDUP(GetColorMode(COLMD_256_COLORS, -// TCI_ORANGE, TCI__IGNORE, GCM_ALT|GCM_SHORT )); -// col.b_orange = STRDUP(GetColorMode(COLMD_256_COLORS, -// TCI_B_ORANGE, TCI__IGNORE, GCM_ALT|GCM_SHORT )); -// -//------------------------------------- } /////////////////////////////////////////////////////////////////////////////// @@ -3629,7 +3939,7 @@ bool SetupColorSet ( ColorSet_t *cs, FILE *f ) /////////////////////////////////////////////////////////////////////////////// -ccp GetColorByName ( const ColorSet_t *colset, ccp name ) +int GetColorOffsetByName ( ccp name ) { struct cdef_t { @@ -3642,9 +3952,14 @@ ccp GetColorByName ( const ColorSet_t *colset, ccp name ) #define DEF1(n) { offsetof(ColorSet_t,n), #n }, #define DEF2(t,n) { offsetof(ColorSet_t,n), #t }, + _Static_assert( N_COLORSET_HL_LINE == 4, "wrong N_COLORSET_HL_LINE" ); + _Static_assert( N_COLORSET_ORDER == 9, "wrong N_COLORSET_ORDER" ); + _Static_assert( N_COLORSET_GREY == 10, "wrong N_COLORSET_GREY" ); + static const struct cdef_t tab[] = { - // [[new-color]] + // [[new-color]] order by name + DEF1(abort) DEF1(b_black) DEF1(b_blue) @@ -3683,6 +3998,7 @@ ccp GetColorByName ( const ColorSet_t *colset, ccp name ) DEF1(cyan_green) DEF1(debug) DEF1(differ) + DEF1(err) DEF1(error) DEF1(fail) DEF1(fail2) @@ -3718,6 +4034,10 @@ ccp GetColorByName ( const ColorSet_t *colset, ccp name ) DEF1(highlight) DEF1(hint) DEF2(hl,highlight) + DEF2(hl_line0,hl_line[0]) + DEF2(hl_line1,hl_line[1]) + DEF2(hl_line2,hl_line[2]) + DEF2(hl_line3,hl_line[3]) DEF1(info) DEF1(job) DEF1(log) @@ -3735,6 +4055,15 @@ ccp GetColorByName ( const ColorSet_t *colset, ccp name ) DEF1(orange) DEF1(orange_red) DEF1(orange_yellow) + DEF2(order0,order[0]) + DEF2(order1,order[1]) + DEF2(order2,order[2]) + DEF2(order3,order[3]) + DEF2(order4,order[4]) + DEF2(order5,order[5]) + DEF2(order6,order[6]) + DEF2(order7,order[7]) + DEF2(order8,order[8]) DEF2(par,param) DEF1(param) DEF1(proc_line) @@ -3776,7 +4105,7 @@ ccp GetColorByName ( const ColorSet_t *colset, ccp name ) if ( i > 0 && strcmp(cd[-1].name,cd->name) >= 0 ) { err_count++; - PRINT("WRONG COL ORDER: %s > %s\n", cd[-1].name, cd->name); + PRINT("\e[1;35mWRONG COL ORDER: %s > %s \e[0m\n", cd[-1].name, cd->name); } } @@ -3791,7 +4120,7 @@ ccp GetColorByName ( const ColorSet_t *colset, ccp name ) //--- search the name - if ( colset && name ) + if (name) { int beg = 0; int end = sizeof(tab)/sizeof(*tab) - 1; @@ -3804,13 +4133,73 @@ ccp GetColorByName ( const ColorSet_t *colset, ccp name ) else if ( stat > 0 ) beg = idx + 1; else - return *(ccp*)((u8*)colset+tab[idx].delta); + return tab[idx].delta; } } + return -1; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp GetColorByName ( const ColorSet_t *colset, ccp name ) +{ + if ( colset && name ) + { + const int offset = GetColorOffsetByName(name); + if ( offset > 0 ) + return GetColorByValidOffset(colset,offset); + } return EmptyString; } /////////////////////////////////////////////////////////////////////////////// + +ccp GetColorByOffsetOrName ( const ColorSet_t *colset, int * offset, ccp name ) +{ + if (!offset) + return GetColorByName(colset,name); + + if (!*offset) + *offset = GetColorOffsetByName(name); + return *offset > 0 ? GetColorByValidOffset(colset,*offset) : EmptyString; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +void ResetLineColor ( const ColorSet_t *colset ) +{ + ColorSet_t *cs = (ColorSet_t*)colset; + cs->line_begin = + cs->line_end = EmptyString; + cs->line_reset = cs->reset; +} + +//----------------------------------------------------------------------------- + +void SetLineColor ( const ColorSet_t *colset, int level ) +{ + _Static_assert( N_COLORSET_HL_LINE == 4, "wrong N_COLORSET_HL_LINE" ); + + ColorSet_t *cs = (ColorSet_t*)colset; + if ( level <= 0 ) + { + cs->line_begin = EmptyString; + cs->line_reset = cs->reset; + cs->line_end = EmptyString; + } + else + { + cs->line_begin = + cs->line_reset = cs->hl_line[ level < N_COLORSET_HL_LINE ? level : N_COLORSET_HL_LINE-1 ]; + cs->line_end = cs->reset; + } +} + +_Static_assert( N_COLORSET_ORDER == 9, "wrong N_COLORSET_ORDER" ); +// [[col-order]] + +/////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // [[color_helper_t]] @@ -3942,8 +4331,12 @@ void PrintColorSetHelper2 if ( ch->select & COLSEL_GREY ) print_by_helper_tab(ch,ch_tab_grey); - if ( ch->select & COLSEL_NAME ) + if ( (ch->select & COLSEL_NAME) == COLSEL_NAME ) print_by_helper_tab(ch,ch_tab_name); + else if ( ch->select & COLSEL_NAME1 ) + print_by_helper_tab(ch,ch_tab_name1); + else if ( ch->select & COLSEL_NAME2 ) + print_by_helper_tab(ch,ch_tab_name2); if ( ch->multi_assign > 1 ) { @@ -4041,9 +4434,9 @@ static void PrintColorSetSH PrintEscapedString(buf,sizeof(buf),col_string,-1,CHMD_ESC,0,0); if (memcmp(buf,"\\x1B",4)) - fprintf(f,"COL_%s=$'%s'\n",name,buf); + fprintf(f," COL_%s=$'%s'\n",name,buf); else - fprintf(f,"COL_%s='\\033%s'\n",name,buf+4); + fprintf(f," COL_%s='\\033%s'\n",name,buf+4); } } @@ -4100,12 +4493,12 @@ void PrintColorSet case 1: if (!cs) cs = GetColorSet(COLMD_ON); - PrintColorSetHelper(f,indent,cs,PrintColorSetSH,select,0); PrintEscapedString(buf,sizeof(buf),cs->reset,-1,CHMD_ESC,0,0); if (memcmp(buf,"\\x1B",4)) - fprintf(f,"COL0=$'%s'\n",buf); + fprintf(f," COL0=$'%s'\n",buf); else - fprintf(f,"COL0=$'\\033%s'\n",buf+4); + fprintf(f," COL0=$'\\033%s'\n",buf+4); + PrintColorSetHelper(f,indent,cs,PrintColorSetSH,select,0); break; case 2: @@ -4134,16 +4527,16 @@ void SetupColorView ( ColorView_t *cv ) cv->f = stdout; cv->indent = NormalizeIndent(cv->indent); -#ifdef DCLIB_TERMINAL + #ifdef DCLIB_TERMINAL cv->col_mode = cv->colset ? cv->colset->col_mode : NormalizeColorMode(cv->col_mode, cv->term ? cv->term->colors : 8 ); -#else + #else cv->col_mode = cv->colset ? cv->colset->col_mode : NormalizeColorMode(cv->col_mode,8); -#endif + #endif if (!cv->colset) cv->colset = GetColorSet(cv->col_mode); @@ -4429,11 +4822,17 @@ static void ViewColors256_helper #endif else { - const int mode = cv->mode & 1 ? 48 : 38; + int mode; + if ( cv->mode & 1 ) + { + mode = 48; + fputs("\e[38;5;0m",cv->f); + } + else + mode = 38; - uint i; - for ( i = beg; i < end; i += step ) - fprintf(cv->f,"\e[%u;5;%um %03u ",mode,i,i); + for ( uint i = beg; i < end; i += step ) + fprintf(cv->f,"\e[%u;5;%um %03u ",mode,i,i); fputs("\e[0m",cv->f); } } @@ -4527,6 +4926,7 @@ static void ViewColorsPredef_helper DASSERT(tab); const ColorSet_t *col = cv->colset; + const int indent = cv->indent + 15; // 15 is max name width for ( ; tab->name; tab++ ) { @@ -4538,10 +4938,10 @@ static void ViewColorsPredef_helper ccp val = *(ccp*)((u8*)col+tab->offset); if (*val) fprintf(cv->f,"%*s %s %-15s %s \\e%s\n", - cv->indent, tab->name, val, tab->name, col->reset, val+1 ); + indent, tab->name, val, tab->name, col->reset, val+1 ); else fprintf(cv->f,"%*s %s %-15s %s\n", - cv->indent, tab->name, val, tab->name, col->reset ); + indent, tab->name, val, tab->name, col->reset ); } else if (cv->allow_sep) { @@ -4566,16 +4966,18 @@ void ViewColorsPredef ( ColorView_t *cv, ColorSelect_t colsel ) colsel = COLSEL_M_MODE; cv->print_alt = ( colsel & COLSEL_F_ALT ) != 0; - cv->indent += 15; // 15 is max name width - fprintf(cv->f, "%s\n%*sPredefined%s color names for mode %s:\n\n", cv->colset->reset, cv->indent, "", - ( colsel & COLSEL_M_MODE ) == COLSEL_NAME ? " semantic" : "", + colsel & COLSEL_NAME ? " semantic" : "", GetColorModeName(cv->col_mode,0) ); - if ( colsel & COLSEL_NAME ) + if ( (colsel & COLSEL_NAME) == COLSEL_NAME ) ViewColorsPredef_helper(cv,ch_tab_name); + else if ( colsel & COLSEL_NAME1 ) + ViewColorsPredef_helper(cv,ch_tab_name1); + else if ( colsel & COLSEL_NAME2 ) + ViewColorsPredef_helper(cv,ch_tab_name2); if ( colsel & COLSEL_COLOR ) ViewColorsPredef_helper(cv,ch_tab_color); @@ -4585,8 +4987,27 @@ void ViewColorsPredef ( ColorView_t *cv, ColorSelect_t colsel ) if ( colsel & COLSEL_GREY ) ViewColorsPredef_helper(cv,ch_tab_grey); +} - cv->indent -= 15; +//----------------------------------------------------------------------------- + +void ViewColorsPage ( ColorView_t *cv, uint page ) +{ + const typeof(cv->mode) saved_mode = cv->mode; + switch(page) + { + case 0: ViewColorsAttrib8(cv); ViewColorsCombi8(cv); break; + case 1: ViewColors18(cv); break; + case 2: ViewColorsDC(cv,false); break; + case 3: ViewColorsDC(cv,true); break; + case 4: cv->mode=0; ViewColors256(cv); break; + case 5: cv->mode=1; ViewColors256(cv); break; + case 6: ViewColorsPredef(cv,COLSEL_GREY); break; + case 7: ViewColorsPredef(cv,COLSEL_M_COLOR); break; + case 8: ViewColorsPredef(cv,COLSEL_NAME1|COLSEL_F_ALT); break; + case 9: ViewColorsPredef(cv,COLSEL_NAME2|COLSEL_F_ALT); break; + } + cv->mode = saved_mode; } // diff --git a/project/dclib/dclib-color.h b/project/dclib/dclib-color.h index 9b19bbf..e36a9fe 100644 --- a/project/dclib/dclib-color.h +++ b/project/dclib/dclib-color.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -47,11 +47,7 @@ /////////////////////////////////////////////////////////////////////////////// #ifndef SUPPORT_36_COLORS - #if NEW_FEATURES - #define SUPPORT_36_COLORS 1 - #else - #define SUPPORT_36_COLORS 0 - #endif + #define SUPPORT_36_COLORS 1 #endif //----------------------------------------------------------------------------- @@ -106,6 +102,10 @@ ColorMode_t GetPrevColorMode ( ColorMode_t col_mode ); /////////////// terminal & colors /////////////// /////////////////////////////////////////////////////////////////////////////// +#define N_COLORSET_GREY 10 +#define N_COLORSET_HL_LINE 4 +#define N_COLORSET_ORDER 9 + extern int termios_valid; // valid if >0 void ResetTermios(void); @@ -153,7 +153,25 @@ extern uint auto_term_size_dirty; // >0: SIGWINCH received, auto_term_size is di bool GetAutoTermSize(void); // return true if changed void EnableAutoTermSize(void); -//----------------------------------------------------------------------------- +/////////////////////////////////////////////////////////////////////////////// +// [[good_term_width_t]] + +typedef struct good_term_width_t +{ + int def_width; + int min_width; + int max_width; + int good_width; + bool setup_done; +} +good_term_width_t; + +extern good_term_width_t good_term_width; + +// If !gtw: Use good_term_width +int GetGoodTermWidth ( good_term_width_t *gtw, bool recalc ); + +/////////////////////////////////////////////////////////////////////////////// //----- some basic terminal codes @@ -179,6 +197,7 @@ void EnableAutoTermSize(void); #define TERM_RESET_WRAP "\e[?7l" // disable line wrapping #define TERM_TEXT_MODE_BEG "\e[" // begin of text mode sequence +#define TERM_TEXT_MODE_BEG0 "\e[0;" // begin of text mode sequence with reset #define TERM_TEXT_MODE_END "m" // end of text mode sequence #define TERM_TEXT_MODE_RESET "\e[m" // reset text mode @@ -206,6 +225,7 @@ extern ccp TermSetWrap; // enabled line wrapping extern ccp TermResetWrap; // disable line wrapping extern ccp TermTextModeBeg; // begin of text mode sequence +extern ccp TermTextModeBeg0; // begin of text mode sequence with reset extern ccp TermTextModeEnd; // end of text mode sequence extern ccp TermTextModeReset; // reset text mode @@ -276,53 +296,69 @@ typedef enum TermTextMode_t //--- these Colors are also used to setup 'ColorSet_t' // [[new-color]] - TTM_COL_SETUP = TTM_BOLD | TTM_BLUE | TTM_BG_BLACK, - TTM_COL_RUN = TTM_BOLD | TTM_WHITE | TTM_BG_BLACK, - TTM_COL_ABORT = TTM_BOLD | TTM_MAGENTA | TTM_BG_BLACK, - TTM_COL_FINISH = TTM_BOLD | TTM_CYAN | TTM_BG_BLACK, - TTM_COL_SCRIPT = TTM_NO_BOLD | TTM_BLACK | TTM_BG_WHITE, - TTM_COL_OPEN = TTM_NO_BOLD | TTM_RED | TTM_BG_BLACK, - TTM_COL_CLOSE = TTM_NO_BOLD | TTM_RED | TTM_BG_BLACK, - TTM_COL_FILE = TTM_NO_BOLD | TTM_YELLOW | TTM_BG_BLACK, - TTM_COL_JOB = TTM_BOLD | TTM_BLUE | TTM_BG_BLACK, + TTM_COL_SETUP = TTM_RESET | TTM_BOLD | TTM_BLUE, + TTM_COL_RUN = TTM_RESET | TTM_BOLD | TTM_WHITE, + TTM_COL_ABORT = TTM_RESET | TTM_BOLD | TTM_MAGENTA, + TTM_COL_FINISH = TTM_RESET | TTM_BOLD | TTM_CYAN, + TTM_COL_SCRIPT = TTM_RESET | TTM_NO_BOLD | TTM_BLACK | TTM_BG_WHITE, + TTM_COL_OPEN = TTM_RESET | TTM_NO_BOLD | TTM_RED, + TTM_COL_CLOSE = TTM_RESET | TTM_NO_BOLD | TTM_RED, + TTM_COL_FILE = TTM_RESET | TTM_NO_BOLD | TTM_YELLOW, + TTM_COL_JOB = TTM_RESET | TTM_BOLD | TTM_BLUE, + TTM_COL_DEBUG = TTM_RESET | TTM_BOLD | TTM_RED, + TTM_COL_LOG = TTM_RESET | TTM_BOLD | TTM_WHITE | TTM_BG_BLUE, + + TTM_COL_MARK = TTM_RESET | TTM_BOLD | TTM_WHITE, + TTM_COL_INFO = TTM_RESET | TTM_BOLD | TTM_CYAN, + TTM_COL_HINT = TTM_RESET | TTM_BOLD | TTM_YELLOW, + TTM_COL_WARN = TTM_RESET | TTM_BOLD | TTM_RED, + TTM_COL_ERR = TTM_RESET | TTM_BOLD | TTM_MAGENTA, + TTM_COL_BAD = TTM_RESET | TTM_BOLD | TTM_MAGENTA, + + TTM_COL_NAME = TTM_RESET | TTM_NO_BOLD | TTM_CYAN, + TTM_COL_OP = TTM_RESET | TTM_BOLD | TTM_WHITE, + TTM_COL_VALUE = TTM_RESET | TTM_NO_BOLD | TTM_GREEN, + TTM_COL_SUCCESS = TTM_RESET | TTM_BOLD | TTM_GREEN, + TTM_COL_ERROR = TTM_RESET | TTM_NO_BOLD | TTM_BLACK | TTM_BG_YELLOW, + TTM_COL_FAIL = TTM_RESET | TTM_NO_BOLD | TTM_WHITE | TTM_BG_RED, + TTM_COL_FAIL2 = TTM_RESET | TTM_BOLD | TTM_WHITE | TTM_BG_RED, + TTM_COL_FATAL = TTM_RESET | TTM_BOLD | TTM_WHITE | TTM_BG_MAGENTA, - TTM_COL_INFO = TTM_BOLD | TTM_CYAN | TTM_BG_BLACK, - TTM_COL_HINT = TTM_BOLD | TTM_YELLOW | TTM_BG_BLACK, - TTM_COL_WARN = TTM_BOLD | TTM_RED | TTM_BG_BLACK, - TTM_COL_DEBUG = TTM_BOLD | TTM_RED | TTM_BG_BLACK, - TTM_COL_LOG = TTM_BOLD | TTM_WHITE | TTM_BG_BLUE, + TTM_COL_SELECT = TTM_RESET | TTM_NO_BOLD | TTM_YELLOW, + TTM_COL_DIFFER = TTM_RESET | TTM_BOLD | TTM_YELLOW | TTM_BG_BLUE, + TTM_COL_HL_LINE0 = TTM_RESET | TTM_NO_BOLD | TTM_WHITE, + TTM_COL_HL_LINE1 = TTM_RESET | TTM_BOLD | TTM_CYAN, + TTM_COL_HL_LINE2 = TTM_RESET | TTM_BOLD | TTM_GREEN, + TTM_COL_HL_LINE3 = TTM_RESET | TTM_BOLD | TTM_MAGENTA, - TTM_COL_NAME = TTM_NO_BOLD | TTM_CYAN | TTM_BG_BLACK, - TTM_COL_OP = TTM_BOLD | TTM_WHITE | TTM_BG_BLACK, - TTM_COL_VALUE = TTM_NO_BOLD | TTM_GREEN | TTM_BG_BLACK, - TTM_COL_SUCCESS = TTM_BOLD | TTM_GREEN | TTM_BG_BLACK, - TTM_COL_ERROR = TTM_NO_BOLD | TTM_BLACK | TTM_BG_YELLOW, - TTM_COL_FAIL = TTM_NO_BOLD | TTM_WHITE | TTM_BG_RED, - TTM_COL_FAIL2 = TTM_BOLD | TTM_WHITE | TTM_BG_RED, - TTM_COL_FATAL = TTM_BOLD | TTM_WHITE | TTM_BG_MAGENTA, - TTM_COL_MARK = TTM_BOLD | TTM_WHITE | TTM_BG_BLACK, - TTM_COL_BAD = TTM_BOLD | TTM_MAGENTA | TTM_BG_BLACK, + TTM_COL_ORDER0 = TTM_RESET | TTM_NO_BOLD | TTM_WHITE, + TTM_COL_ORDER1 = TTM_RESET | TTM_BOLD | TTM_BLUE, + TTM_COL_ORDER2 = TTM_RESET | TTM_BOLD | TTM_CYAN, + TTM_COL_ORDER3 = TTM_RESET | TTM_BOLD | TTM_GREEN, + TTM_COL_ORDER4 = TTM_RESET | TTM_BOLD | TTM_YELLOW, + TTM_COL_ORDER5 = TTM_RESET | TTM_BOLD | TTM_RED, + TTM_COL_ORDER6 = TTM_RESET | TTM_BOLD | TTM_MAGENTA, + TTM_COL_ORDER7 = TTM_RESET | TTM_BOLD | TTM_WHITE, + TTM_COL_ORDER8 = TTM_RESET | TTM_BOLD | TTM_WHITE, - TTM_COL_SELECT = TTM_NO_BOLD | TTM_YELLOW | TTM_BG_BLACK, - TTM_COL_DIFFER = TTM_BOLD | TTM_YELLOW | TTM_BG_BLUE, - TTM_COL_STAT_LINE = TTM_BOLD | TTM_WHITE | TTM_BG_BLUE, - TTM_COL_WARN_LINE = TTM_BOLD | TTM_RED | TTM_BG_BLUE, - TTM_COL_PROC_LINE = TTM_BOLD | TTM_WHITE | TTM_BG_MAGENTA, - TTM_COL_CITE = TTM_NO_BOLD | TTM_GREEN | TTM_BG_BLACK, - TTM_COL_STATUS = TTM_BOLD | TTM_GREEN | TTM_BG_BLACK, - TTM_COL_HIGHLIGHT = TTM_BOLD | TTM_YELLOW | TTM_BG_BLACK, - TTM_COL_HIDE = TTM_BOLD | TTM_BLACK | TTM_BG_BLACK, + TTM_COL_STAT_LINE = TTM_RESET | TTM_BOLD | TTM_WHITE | TTM_BG_BLUE, + TTM_COL_WARN_LINE = TTM_RESET | TTM_BOLD | TTM_RED | TTM_BG_BLUE, + TTM_COL_PROC_LINE = TTM_RESET | TTM_BOLD | TTM_WHITE | TTM_BG_MAGENTA, + TTM_COL_CITE = TTM_RESET | TTM_NO_BOLD | TTM_GREEN, + TTM_COL_STATUS = TTM_RESET | TTM_BOLD | TTM_GREEN, + TTM_COL_HIGHLIGHT = TTM_RESET | TTM_BOLD | TTM_YELLOW, + TTM_COL_HIDE = TTM_RESET | TTM_BOLD | TTM_BLACK, - TTM_COL_HEADING = TTM_BOLD | TTM_BLUE | TTM_BG_BLACK, - TTM_COL_CAPTION = TTM_BOLD | TTM_CYAN | TTM_BG_BLACK, - TTM_COL_SECTION = TTM_BOLD | TTM_GREEN | TTM_BG_BLACK, - TTM_COL_SYNTAX = TTM_BOLD | TTM_WHITE | TTM_BG_BLACK, - TTM_COL_CMD = TTM_NO_BOLD | TTM_CYAN | TTM_BG_BLACK, - TTM_COL_OPTION = TTM_NO_BOLD | TTM_GREEN | TTM_BG_BLACK, - TTM_COL_PARAM = TTM_NO_BOLD | TTM_YELLOW | TTM_BG_BLACK, + TTM_COL_HEADING = TTM_RESET | TTM_BOLD | TTM_BLUE, + TTM_COL_CAPTION = TTM_RESET | TTM_BOLD | TTM_CYAN, + TTM_COL_SECTION = TTM_RESET | TTM_BOLD | TTM_GREEN, + TTM_COL_SYNTAX = TTM_RESET | TTM_BOLD | TTM_WHITE, + TTM_COL_CMD = TTM_RESET | TTM_NO_BOLD | TTM_CYAN, + TTM_COL_OPTION = TTM_RESET | TTM_NO_BOLD | TTM_GREEN, + TTM_COL_PARAM = TTM_RESET | TTM_NO_BOLD | TTM_YELLOW, - TTM_COL_ON = TTM_BOLD | TTM_GREEN | TTM_BG_BLACK, - TTM_COL_OFF = TTM_BOLD | TTM_RED | TTM_BG_BLACK, + TTM_COL_ON = TTM_RESET | TTM_BOLD | TTM_GREEN, + TTM_COL_OFF = TTM_RESET | TTM_BOLD | TTM_RED, } TermTextMode_t; @@ -386,7 +422,7 @@ typedef enum TermColorIndex_t TCI__N = TCI__IGNORE, // number of supported colors TCI__N_FONT = TCI_B_RED, // number of recommended font colors TCI__N_BG = TCI__N, // number of recommended background colors - TCI__N_GREY = TCI_RED, // number of gray tones + TCI__N_GREY = TCI_RED, // number of gray tones #else // !SUPPORT_36_COLORS @@ -418,7 +454,7 @@ typedef enum TermColorIndex_t TCI__N = TCI__IGNORE, // number of supported colors TCI__N_FONT = TCI_B_RED, // number of recommended font colors TCI__N_BG = TCI__N, // number of recommended background colors - TCI__N_GREY = TCI_RED, // number of gray tones + TCI__N_GREY = TCI_RED, // number of gray tones #endif // !SUPPORT_36_COLORS } @@ -433,9 +469,108 @@ TermColorIndex_t; extern const int Color18Index[18+1]; // 18 elements + -1 as terminator //----------------------------------------------------------------------------- -// [[ColorSet_t]] +// [[TermColorIndexEx_t]] + +typedef enum TermColorIndexEx_t +{ + TCE_GREY0, + TCE_GREY1, + TCE_GREY2, + TCE_GREY3, + TCE_GREY4, + TCE_GREY5, + TCE_GREY6, + TCE_GREY7, + TCE_GREY8, + TCE_GREY9, + + TCE_RED_MAGENTA, + TCE_RED, + TCE_RED_ORANGE, + TCE_ORANGE_RED, + TCE_ORANGE, + TCE_ORANGE_YELLOW, + TCE_YELLOW_ORANGE, + TCE_YELLOW, + TCE_YELLOW_GREEN, + TCE_GREEN_YELLOW, + TCE_GREEN, + TCE_GREEN_CYAN, + TCE_CYAN_GREEN, + TCE_CYAN, + TCE_CYAN_BLUE, + TCE_BLUE_CYAN, + TCE_BLUE, + TCE_BLUE_MAGENTA, + TCE_MAGENTA_BLUE, + TCE_MAGENTA, + TCE_MAGENTA_RED, + + TCE_B_RED_MAGENTA, + TCE_B_RED, + TCE_B_RED_ORANGE, + TCE_B_ORANGE_RED, + TCE_B_ORANGE, + TCE_B_ORANGE_YELLOW, + TCE_B_YELLOW_ORANGE, + TCE_B_YELLOW, + TCE_B_YELLOW_GREEN, + TCE_B_GREEN_YELLOW, + TCE_B_GREEN, + TCE_B_GREEN_CYAN, + TCE_B_CYAN_GREEN, + TCE_B_CYAN, + TCE_B_CYAN_BLUE, + TCE_B_BLUE_CYAN, + TCE_B_BLUE, + TCE_B_BLUE_MAGENTA, + TCE_B_MAGENTA_BLUE, + TCE_B_MAGENTA, + TCE_B_MAGENTA_RED, + + TCE__N, -#define N_COLORSET_GREY 10 + TCE_BLACK = TCE_GREY0, + TCE_WHITE = TCE_GREY9, +} +TermColorIndexEx_t; + +//----------------------------------------------------------------------------- +// [[TermColorWarn_t]] + +typedef enum TermColorWarn_t +{ + TCW_MARK, + TCW_INFO, + TCW_HINT, + TCW_WARN, + TCW_ERR, + TCW_BAD, + TCW__N, +} +TermColorWarn_t; + +//----------------------------------------------------------------------------- +// [[TermColorId_t]] + +typedef struct TermColorId_t +{ + union + { + u8 col[TCE__N]; + u8 gray[N_COLORSET_GREY]; + }; +} +TermColorId_t; + +// values 0x00-0x07 for standard, 0x10-0x17 for bold +extern const TermColorId_t color8id; + +// values for 38;5;x or 48;5;x +extern const TermColorId_t color256id; + +//----------------------------------------------------------------------------- +// [[ColorSet_t]] typedef struct ColorSet_t { @@ -445,12 +580,14 @@ typedef struct ColorSet_t u8 colorize; u16 n_colors; + //--- some strings for formatted output if colors active ccp space; // pointer to 'EmptyString' or to 'Space200'; ccp tab; // pointer to 'EmptyString' or to 'TAB20'; ccp lf; // pointer to 'EmptyString' or to 'LF20'; + //--- data, always begins with 'reset' // [[new-color]] @@ -465,13 +602,23 @@ typedef struct ColorSet_t ccp close; ccp file; ccp job; - - ccp info; - ccp hint; - ccp warn; ccp debug; ccp log; + union + { + ccp warn_level[TCW__N]; + struct + { + ccp mark; + ccp info; + ccp hint; + ccp warn; + ccp err; + ccp bad; + }; + }; + ccp name; ccp op; ccp value; @@ -480,9 +627,9 @@ typedef struct ColorSet_t ccp fail; ccp fail2; ccp fatal; - ccp mark; - ccp bad; + ccp hl_line[N_COLORSET_HL_LINE]; + ccp order[N_COLORSET_ORDER]; ccp select; ccp differ; ccp stat_line; @@ -556,6 +703,13 @@ typedef struct ColorSet_t ccp b_magenta_red; ccp matrix[TCI__N_FONT][TCI__N_BG]; + + + //--- line support (mutable) + + ccp line_begin; // use this at beginning of line + ccp line_reset; // use this in line to reset line color + ccp line_end; // use this at end of line } ColorSet_t; @@ -564,18 +718,20 @@ ColorSet_t; typedef enum ColorSelect_t { - COLSEL_COLOR = 0x01, - COLSEL_B_COLOR = 0x02, - COLSEL_GREY = 0x04, - COLSEL_NAME = 0x08, + COLSEL_COLOR = 0x01, // standard colors + COLSEL_B_COLOR = 0x02, // bold colors + COLSEL_GREY = 0x04, // grey scale + + COLSEL_NAME1 = 0x08, // semantic color names, part 1 + COLSEL_NAME2 = 0x10, // semantic color names, part 2 + COLSEL_NAME = 0x18, // semantic color names, both parts - COLSEL_F_ALT = 0x10, + COLSEL_F_ALT = 0x20, COLSEL_M_COLOR = COLSEL_COLOR|COLSEL_B_COLOR, COLSEL_M_NONAME = COLSEL_COLOR|COLSEL_B_COLOR|COLSEL_GREY, COLSEL_M_MODE = 0x0f, COLSEL_M_ALL = 0x1f, - } ColorSelect_t; @@ -631,7 +787,22 @@ const ColorSet_t * GetColorSetAuto ( bool force_on ); const ColorSet_t * GetFileColorSet ( FILE *f ); bool SetupColorSet ( ColorSet_t *cc, FILE *f ); +int GetColorOffsetByName ( ccp name ); // returns -1 if not found + +// returns EmptyString[] if not found ccp GetColorByName ( const ColorSet_t *colset, ccp name ); +ccp GetColorByOffsetOrName ( const ColorSet_t *colset, int * offset, ccp name ); + +extern const char EmptyString[]; +static inline ccp GetColorByOffset ( const ColorSet_t *colset, int offset ) + { return offset > 0 ? *(ccp*)((u8*)colset+offset) : EmptyString; } + +static inline ccp GetColorByValidOffset ( const ColorSet_t *colset, int offset ) + { return *(ccp*)((u8*)colset+offset); } + +// both will change line_col & line_reset +void ResetLineColor ( const ColorSet_t *colset ); +void SetLineColor ( const ColorSet_t *colset, int level ); void PrintColorSet ( @@ -713,6 +884,9 @@ void ViewColorsDC ( ColorView_t *cv, bool optimized ); void ViewColors256 ( ColorView_t *cv ); void ViewColorsPredef ( ColorView_t *cv, ColorSelect_t select ); +#define VIEW_COLOR_PAGES 10 +void ViewColorsPage ( ColorView_t *cv, uint page ); + /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // legacy functions (deprecated) ==> wrapper for ViewColors*() diff --git a/project/dclib/dclib-debug.c b/project/dclib/dclib-debug.c index 7017608..6e23f6e 100644 --- a/project/dclib/dclib-debug.c +++ b/project/dclib/dclib-debug.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -495,8 +495,13 @@ enumError PrintErrorArg ( ccp func, ccp file, unsigned int line, } #if defined(EXTENDED_ERRORS) && EXTENDED_ERRORS > 1 + #ifdef SVN_NEXT + fprintf(stdwrn,"%s -> %s/%s?annotate=%d#l%d\n", + prefix, URI_VIEWVC, file, SVN_NEXT, line ); + #elif defined(REVISION_NEXT) fprintf(stdwrn,"%s -> %s/%s?annotate=%d#l%d\n", prefix, URI_VIEWVC, file, REVISION_NEXT, line ); + #endif #endif fputs(prefix,stdwrn); @@ -674,14 +679,10 @@ void HexDiff ( FILE * f, int indent, u64 addr, int addr_fw, int row_len, /////////////// trace functions /////////////// /////////////////////////////////////////////////////////////////////////////// -u_msec_t GetTimerMSec(); - -/////////////////////////////////////////////////////////////////////////////// - static void trace_helper ( int print_stderr, ccp format, va_list arg ) { static uint last_day = 0; - DayTime_t dt = GetDayTime(true); + DayTime_t dt = GetDayTime(false); if (!TRACE_FILE) { @@ -713,7 +714,7 @@ static void trace_helper ( int print_stderr, ccp format, va_list arg ) if ( last_day != dt.day ) { SetupTimezone(true); - dt = GetDayTime(true); + dt = GetDayTime(false); last_day = dt.day; snprintf(pre,sizeof(pre), "\n#DAY: %s, pid=%d\n%02u:%02u:%02u.%03u ", diff --git a/project/dclib/dclib-debug.h b/project/dclib/dclib-debug.h index 5851141..b8aefc8 100644 --- a/project/dclib/dclib-debug.h +++ b/project/dclib/dclib-debug.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -171,6 +171,20 @@ void HexDiff ( FILE * f, int indent, u64 addr, int addr_fw, int row_len, void HexDiff16 ( FILE * f, int indent, u64 addr, const void * data1, size_t count1, const void * data2, size_t count2 ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// debug helpers /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[PrintDebugFunc] + +typedef int (*PrintDebugFunc) +( + ccp format, // format string + ... // parameters for 'format' +) +__attribute__ ((__format__(__printf__,1,2))); + // /////////////////////////////////////////////////////////////////////////////// /////////////// DEBUG and TRACING /////////////// @@ -415,6 +429,12 @@ void WAIT_ARG_FUNC ( ccp format, va_list arg ); #undef PRINT_SIZEOF1 #undef BINGO1 +#undef PRINTD +#undef PRINT_IFD +#undef PRINT_SIZEOFD +#undef BINGOD +#undef HAVE_PRINTD + #undef xBINGO #undef HAVE_PRINT #undef PRINT_TIME @@ -437,27 +457,41 @@ void WAIT_ARG_FUNC ( ccp format, va_list arg ); #if defined(DEBUG) && defined(TEST) #define HAVE_PRINT 1 - #define PRINT PRINT1 #define PRINT_IF PRINT_IF1 #define PRINT_SIZEOF PRINT_SIZEOF1 #define BINGO BINGO_FUNC(__FUNCTION__,__LINE__,__FILE__) - void PRINT_TIME ( time_t time, ccp title ); #else #define HAVE_PRINT HAVE_TRACE - #define PRINT TRACE #define PRINT_IF TRACE_IF #define PRINT_SIZEOF TRACE_SIZEOF #define BINGO TRACELINE - #define PRINT_TIME(...) #endif +#if IS_DEVELOP + + #define HAVE_PRINTD 1 + #define PRINTD PRINT1 + #define PRINT_IFD PRINT_IF1 + #define PRINT_SIZEOFD PRINT_SIZEOF1 + #define BINGOD BINGO_FUNC(__FUNCTION__,__LINE__,__FILE__) + +#else + + #define HAVE_PRINTD 0 + #define PRINTD(...) + #define PRINT_IFD(cond,...) + #define PRINT_SIZEOFD(t) + #define BINGOD + +#endif + #define xBINGO BINGO_FUNC(__FUNCTION__,__LINE__,__FILE__) #define xTRACELINE TRACE_FUNC("%s() line #%d @ %s\n",__FUNCTION__,__LINE__,__FILE__) diff --git a/project/dclib/dclib-file.c b/project/dclib/dclib-file.c index f58ace1..aae70a3 100644 --- a/project/dclib/dclib-file.c +++ b/project/dclib/dclib-file.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -96,6 +96,317 @@ bool EnableSingleCharInput() // /////////////////////////////////////////////////////////////////////////////// +/////////////// log helpers /////////////// +/////////////////////////////////////////////////////////////////////////////// + +LogFile_t GlobalLogFile = {0}; + +/////////////////////////////////////////////////////////////////////////////// + +FILE * TryOpenFile ( FILE *f, ccp fname, ccp mode ) +{ + if ( f == TRY_OPEN_FILE ) + f = fopen(fname,mode); + else if (f) + { + rewind(f); + fflush(f); + } + return f; +} + +/////////////////////////////////////////////////////////////////////////////// + +int GetLogTimestamp ( char *buf, uint buf_size, TimestampMode_t ts_mode ) +{ + DASSERT(buf); + DASSERT(buf_size>2); + + uint len; + if ( ts_mode >= TSM_USEC ) + { + const u64 usec = GetTimeUSec(false); + const uint sec = usec/1000000 % SEC_PER_DAY; + len = snprintf(buf,buf_size, + "%02u:%02u:%02u.%06llu ", + sec / 3600, + sec / 60 % 60, + sec % 60, + usec % 1000000 ); + } + else if ( ts_mode >= TSM_MSEC ) + { + const u64 msec = GetTimeMSec(false); + const uint sec = msec/USEC_PER_MSEC % SEC_PER_DAY; + len = snprintf(buf,buf_size, + "%02u:%02u:%02u.%03llu ", + sec / 3600, + sec / 60 % 60, + sec % 60, + msec % 1000 ); + } + else if ( ts_mode >= TSM_SEC ) + { + const uint sec = GetTimeSec(false) % SEC_PER_DAY; + len = snprintf(buf,buf_size, + "%02u:%02u:%02u ", + sec / 3600, + sec / 60 % 60, + sec % 60 ); + } + else + { + *buf = 0; + len = 0; + } + + if ( len >= buf_size ) + { + len = buf_size - 1; + buf[len] = 0; + } + return len; +} + +/////////////////////////////////////////////////////////////////////////////// + +int PrintLogTimestamp ( LogFile_t *lf ) +{ + DASSERT(lf); + DASSERT(lf->log); + + int stat = 0; + if ( lf && lf->log ) + { + char buf[50]; + stat = GetLogTimestamp(buf,sizeof(buf),lf->ts_mode); + if ( stat > 0 ) + fwrite(buf,stat,1,lf->log); + } + return stat; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +int PutLogFile ( LogFile_t *lf, ccp text, int text_len ) +{ + if (!lf) + lf = &GlobalLogFile; + + if ( !lf->log || !text ) + return 0; + + //--- collect data first to have a single print + + char buf[2000]; + char *dest = buf + GetLogTimestamp( buf, sizeof(buf), lf->ts_mode ); + dest = StringCopyEMem( dest, buf+sizeof(buf), lf->tag ); + dest = StringCopyEM( dest, buf+sizeof(buf), text, + text_len < 0 ? strlen(text) : text_len ); + + const int len = dest - buf; + fwrite(buf,len,1,lf->log); + if (lf->flush) + fflush(lf->log); + if ( lf->log == stdout ) + stdout_seq_count++; + return len; +} + +/////////////////////////////////////////////////////////////////////////////// + +int PrintArgLogFile ( LogFile_t *lf, ccp format, va_list arg ) +{ + int stat = 0; + if (format) + { + char buf[2000]; + int len = vsnprintf(buf,sizeof(buf),format,arg); + if ( len >= 0 ) + { + if ( len >= sizeof(buf)-1 ) + { + len = sizeof(buf)-1; + buf[sizeof(buf)-1] = 0; + } + stat = PutLogFile(lf,buf,len); + } + } + return stat; +} + +/////////////////////////////////////////////////////////////////////////////// + +int PrintLogFile ( LogFile_t *lf, ccp format, ... ) +{ + va_list arg; + va_start(arg,format); + const int stat = PrintArgLogFile(lf,format,arg); + va_end(arg); + return stat; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// search tool /////////////// +/////////////////////////////////////////////////////////////////////////////// + +exmem_t SearchToolByPATH ( ccp tool ) +{ + exmem_t dest = {}; + if ( tool && *tool ) + { + char fname[PATH_MAX]; + if (strchr(tool,'/')) + { + struct stat st; + if ( !stat(tool,&st) && st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH) ) + AssignExMemS(&dest,tool,-1,CPM_COPY); + } + else + { + ccp path = getenv("PATH"); + for(;;) + { + while ( *path == ':' ) + path++; + ccp start = path; + while ( *path && *path != ':' ) + path++; + const int len = path - start; + if (!len) + break; + + const int flen = snprintf(fname,sizeof(fname),"%.*s/%s",len,start,tool); + struct stat st; + if ( !stat(fname,&st) && st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH) ) + { + AssignExMemS(&dest,fname,flen,CPM_COPY); + break; + } + } + } + } + return dest; +} + +/////////////////////////////////////////////////////////////////////////////// + +exmem_t SearchToolByList ( ccp * list, int max ) +{ + exmem_t dest = {}; + + if (list) + { + if ( max < 0 ) + { + max = 0; + for ( ccp *ptr = list; *ptr; ptr++ ) + max++; + } + + while ( max-- > 0 ) + { + ccp arg = *list++; + if (arg) + { + if ( *arg == '>' ) + { + ccp env = getenv(arg+1); + if ( env && *env ) + { + AssignExMemS(&dest,env,-1,CPM_LINK); + break; + } + } + else + { + dest = SearchToolByPATH(arg); + if (dest.data.len) + break; + } + } + } + } + return dest; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// pipe to pager /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static FILE *pager_file = 0; + +/////////////////////////////////////////////////////////////////////////////// + +FILE * OpenPipeToPager() +{ + static bool done = false; + + if (!done) + { + done = true; + + static ccp search_tab[] = + { + ">DC_PAGER", + ">DC_PAGER1", + ">DC_PAGER2", + ">PAGER", + "less", + "more", + 0 + }; + + exmem_t pager = SearchToolByList(search_tab,-1); + if (pager.data.ptr) + pager_file = popen(pager.data.ptr,"we"); + FreeExMem(&pager); + } + + return pager_file; +} + +/////////////////////////////////////////////////////////////////////////////// + +void ClosePagerFile() +{ + if (pager_file) + { + pclose(pager_file); + pager_file = 0; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +bool StdoutToPager() +{ + FILE *f = OpenPipeToPager(); + if (f) + { + fflush(stdout); + stdout = f; + return true; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +void CloseStdoutToPager() +{ + if ( pager_file && pager_file == stdout ) + { + ClosePagerFile(); + stdout = 0; + } +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// enum FileMode_t /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -3246,6 +3557,69 @@ uint NumberedFilename return index; } +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +static char * GetBlockDeviceHolderHelper + ( char *buf, char *endbuf, ccp name, ccp sep, int *level ) +{ + DASSERT(buf); + DASSERT(endbuf); + DASSERT(level); + + char path[200]; + snprintf(path,sizeof(path),"/sys/class/block/%s/holders",name); + if (IsDirectory(path,0)) + { + DIR *fdir = opendir(path); + if (fdir) + { + for(;;) + { + struct dirent *dent = readdir(fdir); + if (!dent) + break; + if ( dent->d_name[0] != '.' ) + { + buf = GetBlockDeviceHolderHelper(buf,endbuf,dent->d_name,sep,level); + (*level)++; + break; + } + } + closedir(fdir); + } + } + + return StringCat2E(buf,endbuf,sep,name); +} + +//----------------------------------------------------------------------------- + +ccp GetBlockDeviceHolder ( ccp name, ccp sep, int *ret_level ) +{ + static ParamField_t db = { .free_data = true }; + + bool old_found; + ParamFieldItem_t *item = FindInsertParamField(&db,name,false,0,&old_found); + DASSERT(item) + if (!old_found) + { + int level = 0; + char buf[1000]; + ccp end = GetBlockDeviceHolderHelper(buf,buf+sizeof(buf)-strlen(sep)-1,name,sep,&level); + ccp beg = buf + strlen(sep); + if ( beg < end ) + { + item->num = level; + item->data = MEMDUP(beg,end-beg+1); + } + } + + if (ret_level) + *ret_level = item->num; + return item->data; +} + // /////////////////////////////////////////////////////////////////////////////// /////////////// normalize filenames /////////////// @@ -3305,13 +3679,13 @@ char * NormalizeFileName if ( isalnum(ch) || ( is_utf8 ? ch >= 0x80 - : ch == 0xe4 // ä - || ch == 0xf6 // ö - || ch == 0xfc // ü - || ch == 0xdf // ß - || ch == 0xc4 // Ä - || ch == 0xd6 // Ö - || ch == 0xdc // Ü + : ch == 0xe4 // ä + || ch == 0xf6 // ö + || ch == 0xfc // ü + || ch == 0xdf // ß + || ch == 0xc4 // Ä + || ch == 0xd6 // Ö + || ch == 0xdc // Ü ) || strchr("_+-=%'\"$%&#,.!()[]{}<>",ch) ) @@ -3439,7 +3813,7 @@ uint NormalizeFilenameCygwin } else dest = buf; - #else // + #else // *dest++ = '/'; src += 2; if (*src) @@ -3623,7 +3997,7 @@ static int add_search // returns 0 if !stop_if_found, 2 if added+found, 1 if added, 0 else search_file_list_t *sfl, // valid data - ccp config_fname, // default filename (without path) of config file + ccp config_fname, // default filename (without path) of config file ccp *list, // NULL or list of filenames int n_list, // num of 'list' elements, -1:null terminated list ccp prefix, // prefix for relative filenames @@ -3659,7 +4033,7 @@ static int add_search search_file_t *sf = AppendSearchFile( sfl, res.data.ptr, res.is_alloced ? CPM_MOVE : CPM_COPY, config_fname ); if (sf) - { + { sf->hint |= hint; if ( sf->itype == INTY_REG && stop_if_found > 0 ) return 2; @@ -3755,6 +4129,7 @@ void ClearFDList ( FDList_t *fdl ) fdl->now_usec = GetTimeUSec(false); fdl->timeout_usec = M1(fdl->timeout_usec); + fdl->timeout_nsec = M1(fdl->timeout_nsec); } /////////////////////////////////////////////////////////////////////////////// @@ -3815,10 +4190,11 @@ uint AddFDList FDList_t *fdl, // valid socket list int sock, // socket to add - uint events // bit field: POLLIN|POLLOUT|POLLERR + uint events // bit field: POLLIN|POLLPRI|POLLOUT|POLLRDHUP|... ) { - if ( sock == -1 || !(events&(POLLIN|POLLOUT|POLLERR)) ) + events &= ~(POLLERR|POLLHUP|POLLNVAL); // only result! + if ( sock == -1 || !events ) return ~0; fdl->n_sock++; @@ -3840,7 +4216,7 @@ uint AddFDList FD_SET(sock,&fdl->readfds); if ( events & POLLOUT ) FD_SET(sock,&fdl->writefds); - if ( events & POLLERR ) + if ( events & POLLPRI ) FD_SET(sock,&fdl->exceptfds); return ~0; } @@ -3849,7 +4225,7 @@ uint AddFDList uint GetEventFDList ( - // returns bit field: POLLIN|POLLOUT|POLLERR + // returns bit field: POLLIN|POLLOUT|POLLERR|... FDList_t *fdl, // valid socket list int sock, // socket to look for @@ -3879,13 +4255,53 @@ uint GetEventFDList if (FD_ISSET(sock,&fdl->writefds)) revents |= POLLOUT; if (FD_ISSET(sock,&fdl->exceptfds)) - revents |= POLLERR; + revents |= POLLPRI; return revents; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// +static s_usec_t prepare_wait_fdl ( FDList_t *fdl ) +{ + DASSERT(fdl); + const s_usec_t now_usec = GetTimeUSec(false); + + if (fdl->timeout_nsec) + { + const u_usec_t wait_until + = ( (s_usec_t)fdl->timeout_nsec - (s_usec_t)GetTimerNSec() ) + / NSEC_PER_USEC + now_usec + 1; + if ( !fdl->timeout_usec || fdl->timeout_usec > wait_until ) + fdl->timeout_usec = wait_until; + } + + if ( fdl->min_wait_usec && fdl->timeout_usec ) + { + const u_usec_t wait_until = now_usec + fdl->min_wait_usec; + if ( fdl->timeout_usec < wait_until ) + fdl->timeout_usec = wait_until; + } + + return now_usec; +} + +//----------------------------------------------------------------------------- + +static void finish_wait_fdl ( FDList_t *fdl, u_usec_t start_usec ) +{ + DASSERT(fdl); + UpdateCurrentTime(); + fdl->now_usec = current_time.usec; + fdl->last_wait_usec = fdl->now_usec - start_usec; + fdl->wait_usec += fdl->last_wait_usec; + fdl->wait_count++; + + UpdateCpuUsageIncrement(); +} + +/////////////////////////////////////////////////////////////////////////////// + int WaitFDList ( FDList_t *fdl // valid socket list @@ -3893,49 +4309,75 @@ int WaitFDList { DASSERT(fdl); - int stat; - u64 now_usec = GetTimeUSec(false); + const s_usec_t now_usec = prepare_wait_fdl(fdl); + int stat; if (fdl->use_poll) { int timeout; - if ( fdl->timeout_usec > now_usec ) + if ( !fdl->timeout_usec ) + timeout = -1; + else if ( fdl->timeout_usec > now_usec ) { - u64 delta = ( fdl->timeout_usec - now_usec ) / 1000; - timeout = delta > 0x7fffffffull ? -1 : delta; + u_msec_t delta = ( fdl->timeout_usec - now_usec ) / USEC_PER_MSEC; + timeout = delta < 0x7fffffff ? delta : 0x7fffffff; + if (!timeout) + timeout = 1; } else timeout = 0; + if (fdl->debug_file) + { + fprintf(fdl->debug_file,"POLL: timeout=%d\n",timeout); + fflush(fdl->debug_file); + } stat = poll( fdl->poll_list, fdl->poll_used, timeout ); } else { struct timeval tv, *ptv = &tv; - if ( fdl->timeout_usec > now_usec ) + if ( !fdl->timeout_usec ) + ptv = NULL; + else if ( fdl->timeout_usec > now_usec ) { - const u64 delta = fdl->timeout_usec - now_usec; - if ( delta > 1000000ull * 0x7fffffffull ) - ptv = NULL; + const u_usec_t delta = fdl->timeout_usec - now_usec; + if ( delta > USEC_PER_YEAR ) + { + tv.tv_sec = SEC_PER_YEAR; + tv.tv_usec = 0; + } + else if ( delta > USEC_PER_MSEC ) + { + tv.tv_sec = delta / USEC_PER_SEC; + tv.tv_usec = delta % USEC_PER_SEC; + } else { - tv.tv_sec = delta / 1000000; - tv.tv_usec = delta % 1000000; + tv.tv_sec = 0; + tv.tv_usec = USEC_PER_MSEC; } } else tv.tv_sec = tv.tv_usec = 0; -//DEL fprintf(stderr,"#SELECT %lld: ptv=%d: %lu.%06lu\n", -//DEL fdl->timeout_usec-now_usec, ptv!=0, tv.tv_sec, tv.tv_usec ); + if (fdl->debug_file) + { + if (ptv) + fprintf(fdl->debug_file,"# SELECT: usec=%lld, Δnow=%lld, timeout=%llu.%06llu\n", + fdl->timeout_usec, fdl->timeout_usec - now_usec, + (u64)ptv->tv_sec, (u64)ptv->tv_usec ); + else + fprintf(fdl->debug_file,"# SELECT: usec=%lld, Δnow=%lld, timeout=NULL\n", + fdl->timeout_usec, fdl->timeout_usec - now_usec ); + fflush(fdl->debug_file); + } + stat = select( fdl->max_fd+1, &fdl->readfds, &fdl->writefds, &fdl->exceptfds, ptv ); } - fdl->now_usec = GetTimeUSec(false); - fdl->cur_usec = fdl->now_usec - now_usec; - fdl->wait_usec += fdl->cur_usec; - fdl->wait_count++; + finish_wait_fdl(fdl,now_usec); return stat; } @@ -3943,7 +4385,7 @@ int WaitFDList int PWaitFDList ( - FDList_t *fdl, // valid socket list + FDList_t *fdl, // valid socket list const sigset_t *sigmask // NULL or signal mask ) { @@ -3963,18 +4405,24 @@ int PWaitFDList } #endif + const u_usec_t now_usec = prepare_wait_fdl(fdl); + struct timespec ts, *pts = &ts; - u64 now_usec = GetTimeUSec(false); if ( fdl->timeout_usec > now_usec ) { const u64 delta = fdl->timeout_usec - now_usec; if ( delta > 1000000ull * 0x7fffffffull ) pts = NULL; - else + else if ( delta > USEC_PER_MSEC ) { ts.tv_sec = delta / 1000000; ts.tv_nsec = delta % 1000000 * 1000; } + else + { + ts.tv_sec = 0; + ts.tv_nsec = NSEC_PER_MSEC; + } } else ts.tv_sec = ts.tv_nsec = 0; @@ -3989,10 +4437,7 @@ int PWaitFDList &fdl->exceptfds, pts, sigmask ); #endif - fdl->now_usec = GetTimeUSec(false); - fdl->cur_usec = fdl->now_usec - now_usec; - fdl->wait_usec += fdl->cur_usec; - fdl->wait_count++; + finish_wait_fdl(fdl,now_usec); return stat; } @@ -5391,6 +5836,8 @@ void RestoreStateByTable uint aelem_count = 0; uint aelem_offset = 0; + bool mode_add = false; + for ( ; srt->type != SRT__TERM; srt++ ) { if ( srt->type == SRT_DEF_ARRAY ) @@ -5407,6 +5854,16 @@ void RestoreStateByTable continue; } + if ( srt->type >= SRT_MODE__BEGIN && srt->type <= SRT_MODE__END ) + { + switch (srt->type) + { + case SRT_MODE_ASSIGN: mode_add = false; break; + case SRT_MODE_ADD: mode_add = true; break; + } + continue; + } + if ( srt->type == SRT__IS_LIST || !srt->name ) continue; @@ -5456,13 +5913,22 @@ void RestoreStateByTable if ( !i && srt->type == SRT_COUNT && num <= UINT_MAX ) last_count = num; - switch(srt->size) - { - case 1: *(u8*) val = num; break; - case 2: *(u16*)val = num; break; - case 4: *(u32*)val = num; break; - case 8: *(u64*)val = num; break; - } + if (mode_add) + switch(srt->size) + { + case 1: *(u8*) val += num; break; + case 2: *(u16*)val += num; break; + case 4: *(u32*)val += num; break; + case 8: *(u64*)val += num; break; + } + else + switch(srt->size) + { + case 1: *(u8*) val = num; break; + case 2: *(u16*)val = num; break; + case 4: *(u32*)val = num; break; + case 8: *(u64*)val = num; break; + } if ( ++i == n_elem ) break; val += elem_off; @@ -5485,13 +5951,22 @@ void RestoreStateByTable while (*src) { s64 num = str2ll(src,&src,10); - switch(srt->size) - { - case 1: *(s8*) val = num; break; - case 2: *(s16*)val = num; break; - case 4: *(s32*)val = num; break; - case 8: *(s64*)val = num; break; - } + if (mode_add) + switch(srt->size) + { + case 1: *(s8*) val += num; break; + case 2: *(s16*)val += num; break; + case 4: *(s32*)val += num; break; + case 8: *(s64*)val += num; break; + } + else + switch(srt->size) + { + case 1: *(s8*) val = num; break; + case 2: *(s16*)val = num; break; + case 4: *(s32*)val = num; break; + case 8: *(s64*)val = num; break; + } if ( ++i == n_elem ) break; val += elem_off; @@ -5514,12 +5989,25 @@ void RestoreStateByTable uint i = 0; while (*src) { - if ( srt->size == sizeof(float) ) - *(float*)val = strtof(src,&src); - else if ( srt->size == sizeof(double) ) - *(double*)val = strtod(src,&src); - else if ( srt->size == sizeof(long double) ) - *(long double*)val = strtold(src,&src); + if (mode_add) + { + if ( srt->size == sizeof(float) ) + *(float*)val += strtof(src,&src); + else if ( srt->size == sizeof(double) ) + *(double*)val += strtod(src,&src); + else if ( srt->size == sizeof(long double) ) + *(long double*)val += strtold(src,&src); + } + else + { + if ( srt->size == sizeof(float) ) + *(float*)val = strtof(src,&src); + else if ( srt->size == sizeof(double) ) + *(double*)val = strtod(src,&src); + else if ( srt->size == sizeof(long double) ) + *(long double*)val = strtold(src,&src); + } + if ( ++i == n_elem ) break; val += elem_off; @@ -6378,6 +6866,192 @@ int PrintScriptVars // /////////////////////////////////////////////////////////////////////////////// +/////////////// CpuStatus_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +CpuStatus_t GetCpuStatus ( CpuStatus_t * prev_cpuinfo ) +{ + //--- retrieve static data + + static int n_cpu = -1; + static int clock_ticks = 100; + + char buf[1000]; + + if ( n_cpu < 0 ) + { + n_cpu = 0; + FILE *f = fopen("/proc/cpuinfo","r"); + if (f) + { + while (fgets(buf,sizeof(buf),f)) + if ( !memcmp(buf,"processor",9) && buf[9] <= ' ' ) + n_cpu++; + fclose(f); + } + + clock_ticks = sysconf(_SC_CLK_TCK); + if ( clock_ticks <= 0 ) + clock_ticks = 100; + } + + + //--- retrieve cpu data + + CpuStatus_t current = + { + .valid = true, + .nsec = GetTimerNSec(), + .n_cpu = n_cpu, + .clock_ticks = clock_ticks + }; + + + // man 5 proc | oo +/proc/loadavg + FILE *f_load = fopen("/proc/loadavg","r"); + if (f_load) + { + if (fgets(buf,sizeof(buf),f_load)) + { + char *ptr = buf; + current.loadavg_1m = strtod(ptr,&ptr); + current.loadavg_5m = strtod(ptr,&ptr); + current.loadavg_15m = strtod(ptr,&ptr); + + current.running_proc = strtol(ptr,&ptr,10); + current.total_proc = strtol(ptr+1,&ptr,10); + } + fclose(f_load); + } + + + // man 5 proc | oo +/proc/stat + FILE * f_stat = fopen("/proc/stat","r"); + if (f_stat) + { + while (fgets(buf,sizeof(buf),f_stat)) + if ( !memcmp(buf,"cpu ",4) ) + { + char *ptr = buf; + current.user = strtol(ptr+4,&ptr,10) * 10000 / clock_ticks; + current.nice = strtol(ptr,&ptr,10) * 10000 / clock_ticks; + current.system = strtol(ptr,&ptr,10) * 10000 / clock_ticks; + current.idle = strtol(ptr,&ptr,10) * 10000 / clock_ticks; + break; + } + fclose(f_stat); + } + + if (!prev_cpuinfo) + return current; + + + //--- get delta for result + + if (!prev_cpuinfo->valid) + *prev_cpuinfo = current; + + CpuStatus_t res = current; + res.nsec -= prev_cpuinfo->nsec; + res.user -= prev_cpuinfo->user; + res.nice -= prev_cpuinfo->nice; + res.system -= prev_cpuinfo->system; + res.idle -= prev_cpuinfo->idle; + + *prev_cpuinfo = current; + return res; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintCpuStatus ( const CpuStatus_t * cpuinfo ) +{ + if ( !cpuinfo || !cpuinfo->valid ) + return "INVALID"; + + return PrintCircBuf( + "ticks=%d, cpus=%d, times=%lld+%lld+%lld+%lld=%lld, avg=%4.2f,%4.2f,%4.2f %u/%u, nsec=%llu", + cpuinfo->clock_ticks, + cpuinfo->n_cpu, + cpuinfo->user, cpuinfo->nice, cpuinfo->system, cpuinfo->idle, + cpuinfo->user + cpuinfo->nice + cpuinfo->system + cpuinfo->idle, + cpuinfo->loadavg[0], cpuinfo->loadavg[1], cpuinfo->loadavg[2], + cpuinfo->running_proc, cpuinfo->total_proc, + cpuinfo->nsec ); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// MemoryStatus_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +MemoryStatus_t GetMemoryStatus(void) +{ + MemoryStatus_t mem = {0}; + + FILE *f = fopen("/proc/meminfo","r"); + if (f) + { + char buf[200]; + int count = 5; // abort, if all 5 params scanned + + while ( count > 0 && fgets(buf,sizeof(buf),f) ) + { + ccp colon = strchr(buf,':'); + if (colon) + { + u64 num = strtoul(colon+1,0,10) * 1024; + switch (colon-buf) + { + case 6: + if (!memcmp(buf,"Cached",6)) { count--; mem.cached = num; break; } + break; + + case 7: + if (!memcmp(buf,"MemFree",7)) { count--; mem.free = num; break; } + if (!memcmp(buf,"Buffers",7)) { count--; mem.buffers = num; break; } + break; + + case 8: + if (!memcmp(buf,"MemTotal",8)) { count--; mem.total = num; break; } + break; + + case 12: + if (!memcmp(buf,"MemAvailable",12)) { count--; mem.avail = num; break; } + break; + } + } + } + fclose(f); + mem.used = mem.total - mem.free - mem.buffers - mem.cached; + } + return mem; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintMemoryStatus ( const MemoryStatus_t * ms ) +{ + MemoryStatus_t temp; + if (!ms) + { + temp = GetMemoryStatus(); + ms = &temp; + } + + const sizeform_mode_t mode = DC_SFORM_NARROW; + return PrintCircBuf( + "tot=%s, free=%s, avail=%s, used=%s, buf=%s, cache=%s\n", + PrintNumberU7(0,0,ms->total,mode), + PrintNumberU7(0,0,ms->free,mode), + PrintNumberU7(0,0,ms->avail,mode), + PrintNumberU7(0,0,ms->used,mode), + PrintNumberU7(0,0,ms->buffers,mode), + PrintNumberU7(0,0,ms->cached,mode) ); +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// END /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/dclib-file.h b/project/dclib/dclib-file.h index 041929d..f9dd2fc 100644 --- a/project/dclib/dclib-file.h +++ b/project/dclib/dclib-file.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -44,6 +44,63 @@ // /////////////////////////////////////////////////////////////////////////////// +/////////////// log helpers /////////////// +/////////////////////////////////////////////////////////////////////////////// + +#define TRY_OPEN_FILE ((FILE*)1) +#define SETUP_TRY_OPEN_FILE(f,fname,mode) \ + static FILE *f = TRY_OPEN_FILE; f = TryOpenFile(f,fname,mode) + +FILE * TryOpenFile ( FILE *f, ccp fname, ccp mode ); + +//----------------------------------------------------------------------------- +// [[TimestampMode_t] + +typedef enum TimestampMode_t +{ + TSM_OFF, // no timestamp + TSM_SEC, // timstamp HH:MM:SS + TSM_MSEC, // timstamp HH:MM:SS.123 + TSM_USEC, // timstamp HH:MM:SS.123456 +} +TimestampMode_t; + +//----------------------------------------------------------------------------- +// [[LogFile_t] + +typedef struct LogFile_t +{ + FILE *log; // NULL or log file + mem_t tag; // A string to print before message + TimestampMode_t ts_mode; // How to print the timestamp + bool flush; // TRUE: fflush() for each log +} +LogFile_t; + +//----------------------------------------------------------------------------- + +extern LogFile_t GlobalLogFile; + +int GetLogTimestamp ( char *buf, uint buf_size, TimestampMode_t ts_mode ); +int PrintLogTimestamp ( LogFile_t *lf ); + +int PutLogFile ( LogFile_t *lf, ccp text, int text_len ); +int PrintArgLogFile ( LogFile_t *lf, ccp format, va_list arg ); +int PrintLogFile ( LogFile_t *lf, ccp format, ... ) + __attribute__ ((__format__(__printf__,2,3))); + +//----------------------------------------------------------------------------- + +exmem_t SearchToolByPATH ( ccp tool ); +exmem_t SearchToolByList ( ccp * list, int max ); // max<0: NULL is list terminator + +FILE * OpenPipeToPager(); +void ClosePagerFile(); +bool StdoutToPager(); +void CloseStdoutToPager(); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// enum FileMode_t /////////////// /////////////////////////////////////////////////////////////////////////////// // [[FileMode_t]] @@ -750,7 +807,6 @@ typedef struct TraceLog_t ccp fname; // name of file to open FILE *log; // NULL or open log file int level; // log level, don't log if <0 - } TraceLog_t; @@ -892,6 +948,7 @@ int ExistDirectory bool IsSameFilename ( ccp fn1, ccp fn2 ); /////////////////////////////////////////////////////////////////////////////// +// [[FindConfigFile_t]] typedef enum FindConfigFile_t { @@ -1008,11 +1065,17 @@ uint NumberedFilename #endif +/////////////////////////////////////////////////////////////////////////////// + +// return a string of the internal cache +// if ret_level: store level here. +ccp GetBlockDeviceHolder ( ccp name, ccp sep, int *ret_level ); + // /////////////////////////////////////////////////////////////////////////////// /////////////// normalize filenames /////////////// /////////////////////////////////////////////////////////////////////////////// -// [[trailing_slash]] +// [[trailing_slash]] typedef enum trailing_slash { @@ -1180,8 +1243,11 @@ typedef struct FDList_t { bool use_poll; // false: use select(), true: use poll() - u64 now_usec; // set on Clear() and Wait(), result of GetTimeUSec(false) - u64 timeout_usec; // next timeout, based on GetTimeUSec(false) + u_usec_t now_usec; // set on Clear() and Wait(), result of GetTimeUSec(false) + u_usec_t timeout_usec; // next timeout, based on GetTimeUSec(false) (TIME!) + u_nsec_t timeout_nsec; // next timeout, based on GetTimerNSec() (TIMER!) + u_usec_t min_wait_usec; // if >0: minimal waiting time (increment 'timeout_usec') + //--- select() params @@ -1198,11 +1264,12 @@ typedef struct FDList_t //--- statistics + FILE *debug_file; // not NULL: print debug line each select() and poll() uint n_sock; // current number of registered sockets // equals poll_used if poll is used uint wait_count; // total number of waits - u64 wait_usec; // total wait time in usec - u64 cur_usec; // current wait time in usec + u_usec_t wait_usec; // total wait time in usec + u_usec_t last_wait_usec; // last wait time in usec } FDList_t; @@ -1222,14 +1289,14 @@ uint AddFDList ( // returns the pool-index if available, ~0 otherwise - FDList_t *fdl, // valid socket list - int sock, // socket to add - uint events // bit field: POLLIN|POLLOUT|POLLERR + FDList_t *fdl, // valid socket list + int sock, // socket to add + uint events // bit field: POLLIN|POLLPRI|POLLOUT|POLLRDHUP|... ); uint GetEventFDList ( - // returns bit field: POLLIN|POLLOUT|POLLERR + // returns bit field: POLLIN|POLLOUT|POLLERR|... FDList_t *fdl, // valid socket list int sock, // socket to look for @@ -1506,7 +1573,7 @@ typedef struct PrintScript_t ccp var_name; // NULL or variable name for result ccp var_prefix; // NULL or prefix for member names int var_size; // if > 0: print size of var name (some 'fform' only) - int eq_tabstop; // if > 0: indent '=' to set tabstop (some 'fform' only) + int eq_tabstop; // if > 0: indent '=' to set tabstop (some 'fform' only) LowerUpper_t force_case; // change case of var names if not LOUP_AUTO bool create_array; // true: create ar arrays bool auto_quote; // true: detect quotes and use EscapeString() @@ -1552,6 +1619,75 @@ __attribute__ ((__format__(__printf__,3,4))); // /////////////////////////////////////////////////////////////////////////////// +/////////////// CpuStatus_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[CpuStatus_t]] + +typedef struct CpuStatus_t +{ + bool valid; // TRUE: data valid (setup done) + u_nsec_t nsec; // GetTimerNSec() + int clock_ticks; // number of clock ticks per second + int n_cpu; // total number of cpus + + // all times in 1e4 ticks per second (in 0.01%) + u64 user; // time spent in user mode. + u64 nice; // time spent in user mode with low priority. + u64 system; // time spent in system mode. + u64 idle; // time spent in the idle task. + + int running_proc; // currently runnable processes + int total_proc; // currently total processes + + union + { + struct + { + double loadavg_1m; // load average last minute + double loadavg_5m; // load average last 5 minutes + double loadavg_15m; // load average last 12 minutes + }; + + double loadavg[3]; // load average as array + }; +} +CpuStatus_t; + +//----------------------------------------------------------------------------- + +// prev_cpuinfo == NULL: get absolute values +// prev_cpuinfo != NULL: update 'prev_cpuinfo' and get delta +CpuStatus_t GetCpuStatus ( CpuStatus_t * prev_cpuinfo ); + +ccp PrintCpuStatus ( const CpuStatus_t * cpuinfo ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// MemoryStatus_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[MemoryStatus_t]] + +typedef struct MemoryStatus_t +{ + // man 5 proc | oo +//proc/meminfo + + u64 total; // Total usable RAM. + u64 free; // The sum of LowFree + HighFree. + u64 avail; // An estimate of available memory for starting new applications. + u64 buffers; // Relatively temporary storage. + u64 cached; // In-memory cache for files read from the disk. + + u64 used; // = total - free - buffers - cached; +} +MemoryStatus_t; + +//----------------------------------------------------------------------------- + +MemoryStatus_t GetMemoryStatus(void); +ccp PrintMemoryStatus ( const MemoryStatus_t * ms ); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// E N D /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/dclib-gen-ui.h b/project/dclib/dclib-gen-ui.h index 81314fa..ed97cd4 100644 --- a/project/dclib/dclib-gen-ui.h +++ b/project/dclib/dclib-gen-ui.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * diff --git a/project/dclib/dclib-gen-ui.inc b/project/dclib/dclib-gen-ui.inc index 4cbc594..0ac5694 100644 --- a/project/dclib/dclib-gen-ui.inc +++ b/project/dclib/dclib-gen-ui.inc @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * diff --git a/project/dclib/dclib-mysql.c b/project/dclib/dclib-mysql.c index a378c7d..e83838a 100644 --- a/project/dclib/dclib-mysql.c +++ b/project/dclib/dclib-mysql.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -35,16 +35,126 @@ #define _GNU_SOURCE 1 #include <string.h> +#include <stddef.h> #include <mysql/mysql.h> #include <mysql/errmsg.h> #include "dclib-mysql.h" +#include "dclib-file.h" #include "dclib-network.h" // http://dev.mysql.com/doc/refman/5.1/en/c-api-functions.html // /////////////////////////////////////////////////////////////////////////////// +/////////////// global vars /////////////// +/////////////////////////////////////////////////////////////////////////////// + +UsageDuration_t mysql_query_usage = { .par.used = 0, .par.enabled = true }; + +const UsageCtrl_t mysql_query_usage_ctrl = +{ + .par = &mysql_query_usage.par, + .ud = &mysql_query_usage, + .title = "Database queries", + .key1 = "DB", + .key2 = "MYSQL", + .srt_prefix = "my-q-", +}; + +/////////////////////////////////////////////////////////////////////////////// + +const SaveRestoreTab_t SRT_Mysql[] = +{ + #undef SRT_NAME + #define SRT_NAME MySql_t + + DEF_SRT_COMMENT("mysql stats"), + DEF_SRT_SEPARATOR(), + + DEF_SRT_MODE_ADD(), + DEF_SRT_UINT( total_connect_count, "mystat-connect" ), + DEF_SRT_UINT( total_query_count, "mystat-query-c" ), + DEF_SRT_UINT( total_query_size, "mystat-query-s" ), + DEF_SRT_UINT( total_result_count, "mystat-result" ), + DEF_SRT_UINT( total_row_count, "mystat-row" ), + DEF_SRT_UINT( total_field_count, "mystat-field-c" ), + DEF_SRT_UINT( total_field_size, "mystat-field-s" ), + + DEF_SRT_SEPARATOR(), + DEF_SRT_TERM() +}; + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// watch long queries /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static ccp wq_fname = 0; // NULL or opened file +static LogFile_t wq_log = {0}; // log data +static bool wq_failed = false; // true, if fopen() faild => don't try again + +static u_nsec_t wq_nsec = M1(wq_nsec); // >0: log queries that need ≥# nsec +static uint wq_size = M1(wq_size); // >0: log queries with ≥# bytes + +/////////////////////////////////////////////////////////////////////////////// + +void SetupQueryLogMYSQL +( + ccp fname, // filename of log file, openend with mode "a" + ccp tag, // identification of the tool for shared log files + u_nsec_t nsec, // >0: log queries that need e# nsec + uint size // >0: log queries that are longer e# bytes +) +{ + CloseQueryLogMYSQL(); + + wq_fname = fname; + wq_failed = false; + wq_nsec = nsec ? nsec : M1(wq_nsec); + wq_size = size ? size : M1(wq_size); + + wq_log.tag = MemByString0(tag); + wq_log.ts_mode = TSM_MSEC; + wq_log.flush = true; +} + +/////////////////////////////////////////////////////////////////////////////// + +void CloseQueryLogMYSQL() +{ + if (wq_log.log) + { + fclose(wq_log.log); + wq_log.log = 0; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +LogFile_t * OpenQueryLogMYSQL() +{ + if (!wq_log.log) + { + if ( wq_failed || !wq_fname || !*wq_fname ) + { + wq_failed = true; + return 0; + } + + wq_log.log = fopen(wq_fname,"ab"); + if (!wq_log.log) + { + wq_failed = true; + return 0; + } + } + + return &wq_log; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// struct MySql_t /////////////// /////////////////////////////////////////////////////////////////////////////// // management @@ -71,6 +181,8 @@ void InitializeMYSQL ( MySql_t *my ) my->auto_reconnect = true; my->prefix = EmptyString; InitializeStatusMYSQL(&my->status); + + AddToUsageMgr(&mysql_query_usage_ctrl); } /////////////////////////////////////////////////////////////////////////////// @@ -266,6 +378,52 @@ static enumError CheckOpenMYSQL ( MySql_t *my, uint loglevel ) /////////////////////////////////////////////////////////////////////////////// // queries +static void update_query_duration + ( MySql_t *my, u_nsec_t start_time, ccp query, uint qlen ) +{ + DASSERT(my); + const u_usec_t dur_nsec = GetTimerNSec() - start_time; + my->last_duration_usec = dur_nsec / NSEC_PER_USEC; + if ( my->max_duration_usec < my->last_duration_usec ) + my->max_duration_usec = my->last_duration_usec; + my->total_duration_usec += my->last_duration_usec; + + UpdateUsageDurationIncrement(&mysql_query_usage,dur_nsec); + + if ( dur_nsec >= wq_nsec || qlen >= wq_size ) + { + LogFile_t *lf = OpenQueryLogMYSQL(); + if (lf) + { + char buf[2000], *dest = buf; + bool have_space = false; + while ( *query && dest < buf+sizeof(buf)-2 ) + { + const uchar ch = *query++; + if ( ch > ' ' ) + { + if (have_space) + { + have_space = false; + *dest++ = ' '; + } + *dest++ = ch; + } + else if ( dest > buf ) + have_space = true; + } + *dest = 0; + + PrintLogFile(lf,"%5u %s : %s\n", + qlen, + PrintTimerNSec6(0,0,dur_nsec,DC_SFORM_ALIGN|DC_SFORM_DASH), + buf ); + } + } +} + +//----------------------------------------------------------------------------- + enumError DoQueryMYSQL ( MySql_t *my, // valid struct @@ -277,7 +435,7 @@ enumError DoQueryMYSQL DASSERT(my); DASSERT(query); - const u64 start_time = GetTimeUSec(false); + const u_nsec_t start_time = GetTimerNSec(); enumError err = CheckOpenMYSQL(my,loglevel); if (err) @@ -319,10 +477,7 @@ enumError DoQueryMYSQL ERROR0(ERR_DATABASE,"%s (#%d)\n", my->status.message, my->status.status ); - my->last_duration_usec = GetTimeUSec(false) - start_time; - if ( my->max_duration_usec < my->last_duration_usec ) - my->max_duration_usec = my->last_duration_usec; - my->total_duration_usec += my->last_duration_usec; + update_query_duration(my,start_time,query,query_length); return ERR_DATABASE; } } @@ -332,11 +487,7 @@ enumError DoQueryMYSQL my->field_count = mysql_field_count(my->mysql); ClearStatusMYSQL(&my->status); - - my->last_duration_usec = GetTimeUSec(false) - start_time; - if ( my->max_duration_usec < my->last_duration_usec ) - my->max_duration_usec = my->last_duration_usec; - my->total_duration_usec += my->last_duration_usec; + update_query_duration(my,start_time,query,query_length); return ERR_OK; } @@ -591,6 +742,7 @@ s64 FetchIntMYSQL ( MySql_t *my, // valid struct LogLevelMYSQL loglevel, // log level for mysql errors and queries + bool allow_trail, // allow additional chars behind number s64 return_default // return this value on non existent result ) { @@ -602,7 +754,7 @@ s64 FetchIntMYSQL char *end; const s64 val = strtoll(res.ptr,&end,10); FreeMemMYSQL(my,res); - return end == res.ptr + res.len ? val : return_default; + return allow_trail || end == res.ptr + res.len ? val : return_default; } /////////////////////////////////////////////////////////////////////////////// @@ -611,6 +763,7 @@ u64 FetchUIntMYSQL ( MySql_t *my, // valid struct LogLevelMYSQL loglevel, // log level for mysql errors and queries + bool allow_trail, // allow additional chars behind number u64 return_default // return this value on non existent result ) { @@ -622,7 +775,7 @@ u64 FetchUIntMYSQL char *end; const u64 val = strtoull(res.ptr,&end,10); FreeMemMYSQL(my,res); - return end == res.ptr + res.len ? val : return_default; + return allow_trail || end == res.ptr + res.len ? val : return_default; } // @@ -686,6 +839,7 @@ s64 PrintFetchIntMYSQL ( MySql_t *my, // valid struct LogLevelMYSQL loglevel, // log level for mysql errors and queries + bool allow_trail, // allow additional chars behind number s64 return_default, // return this value on non existent result ccp format, // format string for vsnprintf() ... // parameters for 'format' @@ -705,7 +859,7 @@ s64 PrintFetchIntMYSQL char *end; const s64 val = strtoll(res.ptr,&end,10); FreeMemMYSQL(my,res); - return end == res.ptr + res.len ? val : return_default; + return allow_trail || end == res.ptr + res.len ? val : return_default; } /////////////////////////////////////////////////////////////////////////////// @@ -714,6 +868,7 @@ u64 PrintFetchUIntMYSQL ( MySql_t *my, // valid struct LogLevelMYSQL loglevel, // log level for mysql errors and queries + bool allow_trail, // allow additional chars behind number u64 return_default, // return this value on non existent result ccp format, // format string for vsnprintf() ... // parameters for 'format' @@ -733,7 +888,7 @@ u64 PrintFetchUIntMYSQL char *end; const u64 val = strtoull(res.ptr,&end,10); FreeMemMYSQL(my,res); - return end == res.ptr + res.len ? val : return_default; + return allow_trail || end == res.ptr + res.len ? val : return_default; } // @@ -865,7 +1020,7 @@ int CountTablesMYSQL mem_t db = EscapeStringMYSQL(my, database && *database ? database : my->database ); mem_t tab = EscapeStringMYSQL(my, table && *table ? table : "%" ); - stat = PrintFetchIntMYSQL(my,MYLL_QUERY_ON_ERROR,-1, + stat = PrintFetchIntMYSQL(my,MYLL_QUERY_ON_ERROR,false,-1, "SELECT COUNT(DISTINCT TABLE_NAME) FROM information_schema.COLUMNS\n" "WHERE TABLE_SCHEMA = \"%s\" && TABLE_NAME like \"%s\"\n", db.ptr, tab.ptr ); @@ -894,7 +1049,7 @@ int CountColumnsMYSQL if ( column && *column ) { mem_t col = EscapeStringMYSQL(my,column); - stat = PrintFetchIntMYSQL(my,MYLL_QUERY_ON_ERROR,-1, + stat = PrintFetchIntMYSQL(my,MYLL_QUERY_ON_ERROR,false,-1, "SELECT COUNT(*) FROM information_schema.COLUMNS\n" "WHERE TABLE_SCHEMA = \"%s\" && TABLE_NAME like \"%s\"" " && COLUMN_NAME = \"%s\"\n", @@ -903,7 +1058,7 @@ int CountColumnsMYSQL } else { - stat = PrintFetchIntMYSQL(my,MYLL_QUERY_ON_ERROR,-1, + stat = PrintFetchIntMYSQL(my,MYLL_QUERY_ON_ERROR,false,-1, "SELECT COUNT(*) FROM information_schema.COLUMNS\n" "WHERE TABLE_SCHEMA = \"%s\" && TABLE_NAME like \"%s\"\n", db.ptr, tab.ptr ); diff --git a/project/dclib/dclib-mysql.h b/project/dclib/dclib-mysql.h index c251fda..8ae7e2c 100644 --- a/project/dclib/dclib-mysql.h +++ b/project/dclib/dclib-mysql.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -66,6 +66,22 @@ LogLevelMYSQL; // /////////////////////////////////////////////////////////////////////////////// +/////////////// watch long queries /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void SetupQueryLogMYSQL +( + ccp fname, // filename of log file, openend with mode "a" + ccp tag, // identification of the tool for shared log files + u_nsec_t nsec, // >0: log queries that need ≥# nsec + uint size // >0: log queries that are longer ≥# bytes +); + +void CloseQueryLogMYSQL(void); +struct LogFile_t * OpenQueryLogMYSQL(void); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// struct MySqlStatus_t /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -142,7 +158,7 @@ typedef struct MySql_t //--- statistics - uint total_connect_count; // total number of connections (usualy 1) + uint total_connect_count; // total number of connections (usually 1) uint total_query_count; // total number of queries u64 total_query_size; // total size of all queries uint total_result_count; // total number of fetched results @@ -158,6 +174,8 @@ typedef struct MySql_t } MySql_t; +extern const SaveRestoreTab_t SRT_Mysql[]; + // /////////////////////////////////////////////////////////////////////////////// /////////////// interface for MySql_t /////////////// @@ -264,6 +282,7 @@ s64 FetchIntMYSQL ( MySql_t *my, // valid struct LogLevelMYSQL loglevel, // log level for mysql errors and queries + bool allow_trail, // allow additional chars behind number s64 return_default // return this value on non existent result ); @@ -271,6 +290,7 @@ u64 FetchUIntMYSQL ( MySql_t *my, // valid struct LogLevelMYSQL loglevel, // log level for mysql errors and queries + bool allow_trail, // allow additional chars behind number u64 return_default // return this value on non existent result ); @@ -302,21 +322,23 @@ s64 PrintFetchIntMYSQL ( MySql_t *my, // valid struct LogLevelMYSQL loglevel, // log level for mysql errors and queries + bool allow_trail, // allow additional chars behind number s64 return_default, // return this value on non existent result ccp format, // format string for vsnprintf() ... // parameters for 'format' ) -__attribute__ ((__format__(__printf__,4,5))); +__attribute__ ((__format__(__printf__,5,6))); u64 PrintFetchUIntMYSQL ( MySql_t *my, // valid struct LogLevelMYSQL loglevel, // log level for mysql errors and queries + bool allow_trail, // allow additional chars behind number u64 return_default, // return this value on non existent result ccp format, // format string for vsnprintf() ... // parameters for 'format' ) -__attribute__ ((__format__(__printf__,4,5))); +__attribute__ ((__format__(__printf__,5,6))); //----------------------------------------------------------------------------- // fetch single row @@ -535,6 +557,10 @@ MySqlServerStats_t * Max2MySqlServerStats const MySqlServerStats_t *src // NULL or source ); +/////////////////////////////////////////////////////////////////////////////// + +extern UsageDuration_t mysql_query_usage; + // /////////////////////////////////////////////////////////////////////////////// /////////////// E N D /////////////// diff --git a/project/dclib/dclib-network-linux.c b/project/dclib/dclib-network-linux.c index 9116588..dc6c32b 100644 --- a/project/dclib/dclib-network-linux.c +++ b/project/dclib/dclib-network-linux.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -148,7 +148,7 @@ ssize_t SendUDPv4 struct in_pktinfo *pki = (struct in_pktinfo*) CMSG_DATA(cp); pki->ipi_ifindex = 0; pki->ipi_spec_dst.s_addr = src_addr; - + return sendmsg(sock,&msg,flags); } diff --git a/project/dclib/dclib-network-linux.h b/project/dclib/dclib-network-linux.h index 9366191..1760bde 100644 --- a/project/dclib/dclib-network-linux.h +++ b/project/dclib/dclib-network-linux.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * diff --git a/project/dclib/dclib-network.c b/project/dclib/dclib-network.c index 6e1e542..76390e3 100644 --- a/project/dclib/dclib-network.c +++ b/project/dclib/dclib-network.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -47,8 +47,11 @@ #include <sys/socket.h> #include <sys/un.h> #include <netinet/in.h> +#include <stddef.h> +#include <ifaddrs.h> #include "dclib-network.h" +#include "dclib-punycode.h" /////////////////////////////////////////////////////////////////////////////// @@ -239,6 +242,1431 @@ bool ResolveHostMem // /////////////////////////////////////////////////////////////////////////////// +/////////////// enum PrintModeIP_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +PrintModeIP_t ScanPrintModeIP ( PrintModeIP_t base, ccp arg ) +{ + if (arg) + { + bool neg = false; + while (*arg) + { + PrintModeIP_t val = 0; + PrintModeIP_t mask = 0; + switch(*arg++) + { + case '-': neg = !neg; break; + + case 'n': val = PMIP_NEVER; mask = PMIP_M_BITS; break; + case 'r': val = PMIP_RELEVANT; mask = PMIP_M_BITS; break; + case 'i': val = PMIP_IF_SET; mask = PMIP_M_BITS; break; + case 'a': val = PMIP_ALWAYS; mask = PMIP_M_BITS; break; + + case 'p': val = PMIP_PORT; break; + case 's': val = PMIP_SERVICE; break; + case 'm': val = PMIP_MASK; break; + case 'b': val = PMIP_BRACKETS; break; + case 'f': val = PMIP_FULL_IPV6; break; + + case '0': val = PMIP_0DOTS; mask = PMIP_M_DOTS; break; + case '1': val = PMIP_1DOT; mask = PMIP_M_DOTS; break; + case '2': val = PMIP_2DOTS; mask = PMIP_M_DOTS; break; + case '3': val = PMIP_3DOTS; mask = PMIP_M_DOTS; break; + } + + if (mask) // ignore 'neg' + { + base = base & ~mask | val; + neg = false; + } + else if (val) + { + if (neg) + base &= ~val; + else + base |= val; + neg = false; + } + } + } + + return base; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintPrintModeIP ( PrintModeIP_t val, bool align ) +{ + char buf[20], *dest = buf; + + DASSERT( PMIP_M_BITS == 3 ); + *dest++ = "nria"[ val & PMIP_M_BITS ]; + + if ( val & PMIP_PORT ) *dest++ = 'p'; else if (align) *dest++ = '-'; + if ( val & PMIP_SERVICE ) *dest++ = 's'; else if (align) *dest++ = '-'; + if ( val & PMIP_MASK ) *dest++ = 'm'; else if (align) *dest++ = '-'; + if ( val & PMIP_BRACKETS ) *dest++ = 'b'; else if (align) *dest++ = '-'; + if ( val & PMIP_FULL_IPV6 ) *dest++ = 'f'; else if (align) *dest++ = '-'; + + if ( val & PMIP_0DOTS ) + *dest++ = '0'; + else if ( val & PMIP_1DOT ) + *dest++ = '1'; + else if ( val & PMIP_2DOTS ) + *dest++ = '2'; + else if (align) + *dest++ = '3'; + + DASSERT( dest < buf+sizeof(buf) ); + return CopyCircBuf0(buf,dest-buf); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// enum IPClass_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +ccp GetIPClassColor ( const ColorSet_t *colset, IPClass_t ipc ) +{ + if ( !colset || !colset->colorize ) + return ""; + + switch (ipc) + { + case IPCL_INVALID: return colset->b_red; + case IPCL_LOOPBACK: return colset->b_cyan; + case IPCL_LOCAL: return colset->b_green; + case IPCL_STANDARD: return colset->reset; + case IPCL_SPECIAL: return colset->b_yellow; + default: return colset->b_magenta; + } +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct SplitIP_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +bool SplitIP ( SplitIP_t *sip, ccp addr ) +{ + DASSERT(sip); + memset(sip,0,sizeof(*sip)); + if (!addr) + return false; + + while ( isblank((int)*addr) ) + addr++; + + int bits = -1; + ccp slash = strchr(addr,'/'); + if (slash) + { + if (strchr(slash,'.')) + { + // is there a netmask? + struct in_addr inp; + if (inet_aton(slash+1,&inp)) + { + const int bits2 = Count1Bits32(inp.s_addr); + const ipv4_t mask = GetIP4Mask(bits2); + if ( mask == inp.s_addr ) + bits = bits2; + } + } + + if ( bits < 0 ) + { + const int val = strtol(slash+1,0,10); + if ( val >= 0 && val <= 128 ) + bits = val; + } + } + + ccp have_port = 0; + if ( *addr == '[' ) + { + ccp close = strchr(++addr,']'); + if (!close) + return false; + + StringCopySM(sip->name,sizeof(sip->name),addr,close-addr); + if ( close[1] == ':' ) + have_port = close+2; + } + else + { + char *end_name = slash + ? StringCopySM(sip->name,sizeof(sip->name),addr,slash-addr) + : StringCopyS(sip->name,sizeof(sip->name),addr); + + if ( end_name > sip->name && end_name[-1] == '.' ) + { + // remove trailing point if not a valid IPv4 (domains only) + if ( CheckIP4(sip->name,end_name-sip->name) <= CIP4_INVALID ) + *--end_name = 0; + } + + ccp point = strchr(sip->name,'.'); + if (point) + { + char *colon = strchr(point,':'); + if (colon) + { + *colon++ = 0; + have_port = colon; + } + } + } + + if (!*sip->name) + return false; + + if (have_port) + { + if ( *have_port >= '0' && *have_port <= '9' ) + { + const uint port = strtol(have_port,0,10); + if ( port <= 0xffff ) + sip->port = port; + } + else + { + char serv[100]; + if (slash) + { + StringCopySM(serv,sizeof(serv),have_port,slash-have_port); + have_port = serv; + } + + struct servent result_buf; + struct servent *result = 0; + char buf[1000]; + if ( !getservbyname_r(have_port,0,&result_buf,buf,sizeof(buf),&result) && result ) + sip->port = ntohs(result->s_port); + } + } + + sip->bits = bits; + return true; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct NamesIP_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +struct ip_names_list_t +{ + int offset; + char name[8]; +}; + +//----------------------------------------------------------------------------- + +#undef RECORD +#define RECORD(v) { offsetof(NamesIP_t,v), #v }, + +static const struct ip_names_list_t ip_names_list[] = +{ + RECORD(binaddr) + RECORD(ipvers) + RECORD(addr1) + RECORD(addr2) + RECORD(bits) + RECORD(mask1) + RECORD(mask2) + {-1,""} +}; + +#undef RECORD + +#undef GET_NAME_IP_PTR +#define GET_NAME_IP_PTR(nip,offset) ((ccp*)( (char*)(nip)+offset )) + +/////////////////////////////////////////////////////////////////////////////// + +void SetupNamesIP ( NamesIP_t *dest, const NamesIP_t *src ) +{ + if (!dest) + return; + + if (src) + { + for ( const struct ip_names_list_t *in = ip_names_list; in->offset >= 0; in++ ) + { + ccp *s = GET_NAME_IP_PTR(src,in->offset); + ccp *d = GET_NAME_IP_PTR(dest,in->offset); + *d = *s && **s ? *s : in->name; + } + } + else + { + for ( const struct ip_names_list_t *in = ip_names_list; in->offset >= 0; in++ ) + { + ccp *d = GET_NAME_IP_PTR(dest,in->offset); + *d = in->name; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void SetupNamesByListIP ( NamesIP_t *dest, const exmem_list_t *src ) +{ + if (!dest) + return; + + // [[2do]] ??? qqq +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintNamesIP ( const NamesIP_t *nip ) +{ + return nip + ? PrintCircBuf("ba=%s, iv=%s, a1=%s, a2=%s, b=%s, m1=%s, m2=%s\n", + nip->binaddr, nip->ipvers, nip->addr1, nip->addr2, + nip->bits, nip->mask1, nip->mask2 ) + : 0; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct BinIP_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +BinIP_t GetIPMask ( const BinIP_t *src ) +{ + BinIP_t res = {0}; + if (src) + { + if ( src->ipvers == 4 ) + res.ip4 = GetIP4Mask(src->bits); + else if ( src->ipvers == 6 ) + res.ip6 = GetIP6Mask(src->bits); + else + goto abort; + + res.ipvers = src->ipvers; + res.bits = src->bits; + } + + abort: + return res; +} + +/////////////////////////////////////////////////////////////////////////////// + +void ApplyIPMask ( BinIP_t *bip ) +{ + if (bip) + { + BinIP_t mask = GetIPMask(bip); + bip->ip6_64[0] &= mask.ip6_64[0]; + bip->ip6_64[1] &= mask.ip6_64[1]; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +IPClass_t GetIPClassBIP ( const BinIP_t * bip ) +{ + struct ip4_tab + { + ipv4_t addr; + ipv4_t mask; + IPClass_t ipc; + }; + + static const struct ip4_tab ip4_tab[] = + { + { 0x00000000, 0xffffffff, IPCL_INVALID }, // 0.0.0.0 + { 0x7f000000, 0xff000000, IPCL_LOOPBACK }, // 127.0.0.0/8 + { 0x0a000000, 0xff000000, IPCL_LOCAL }, // 10.0.0.0/8 + { 0xac100000, 0xfff00000, IPCL_LOCAL }, // 172.16.0.0/12 + { 0xc0a80000, 0xffff0000, IPCL_LOCAL }, // 192.168.0.0/16 + { 0xa9fe0000, 0xffff0000, IPCL_LOCAL }, // 169.254.0.0/16 + { 0xe0000000, 0xe0000000, IPCL_SPECIAL }, // 224.0.0.0/3 + { 0,0,IPCL__N }, + }; + + struct ip6_tab + { + IPClass_t ipc; + ccp name; + ipv6_t addr; + ipv6_t mask; + }; + + static struct ip6_tab ip6_tab[] = + { + { IPCL_INVALID, "::" }, + { IPCL_LOOPBACK, "::1" }, + { IPCL_LOCAL, "fe80::/10" }, + { IPCL_SPECIAL, "f00::/8" }, + { 0,0 }, + }; + + if (bip) + { + if ( bip->ipvers == 4 ) + { + const ipv4_t addr = ntohl(bip->ip4); + for ( const struct ip4_tab *ptr = ip4_tab; ptr->ipc < IPCL__N; ptr++ ) + if ( ( addr & ptr->mask ) == ptr->addr ) + return ptr->ipc; + return IPCL_STANDARD; + } + else if ( bip->ipvers == 6 ) + { + ipv6_t addr; + memcpy(&addr,bip->ip6_64,sizeof(addr)); + PRINT0("> %016llx.%016llx\n",ntoh64(addr.v64[0]),ntoh64(addr.v64[1])); + + static bool init_done = false; + if (!init_done) + { + init_done = true; + ManageIP_t mip = {{0}}; + for ( struct ip6_tab *ptr = ip6_tab; ptr->name; ptr++ ) + { + ScanMIP(&mip,ptr->name); + memcpy(&ptr->addr,mip.bin.ip6_64,sizeof(ptr->addr)); + ptr->mask = GetIP6Mask(mip.bin.bits); + } + ResetMIP(&mip); + } + + for ( struct ip6_tab *ptr = ip6_tab; ptr->name; ptr++ ) + { + PRINT0(" %016llx.%016llx / %016llx.%016llx : %s\n", + ntoh64(ptr->addr.v64[0]), ntoh64(ptr->addr.v64[1]), + ntoh64(ptr->mask.v64[0]), ntoh64(ptr->mask.v64[1]), + ptr->name ); + + if ( ( addr.v64[0] & ptr->mask.v64[0] ) == ptr->addr.v64[0] + && ( addr.v64[1] & ptr->mask.v64[1] ) == ptr->addr.v64[1] ) + { + return ptr->ipc; + } + } + return IPCL_STANDARD; + } + } + + return IPCL_INVALID; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintBIP ( const BinIP_t * bip ) +{ + ccp res; + int bitlen = 32; + char buf[INET6_ADDRSTRLEN+1]; + + switch ( bip ? bip->ipvers : 0 ) + { + case 4: + res = inet_ntop(AF_INET,&bip->ip4,buf,sizeof(buf)); + break; + + case 6: + res = inet_ntop(AF_INET6,bip->ip6_32,buf,sizeof(buf)); + bitlen = 128; + break; + + default: + res = 0; + break; + } + + if (!res) + return 0; + + return bip->bits < bitlen + ? PrintCircBuf("%s/%u",res,bip->bits) + : CopyCircBuf(res,strlen(res)+1); +} + +/////////////////////////////////////////////////////////////////////////////// + +bool IsSameBIP ( const BinIP_t *a1, const BinIP_t *a2, uint use_mask ) +{ + if ( a1 && a2 && a1->ipvers == a2->ipvers ) + { + int bits; + switch ( use_mask & 3 ) + { + case 1: bits = a1->bits; break; + case 2: bits = a2->bits; break; + case 3: bits = a1->bits < a2->bits ? a1->bits : a2->bits; break; + default: bits = 128; break; + } + + if ( a1->ipvers == 4 ) + { + ipv4_t mask = GetIP4Mask(bits); + return ( a1->ip4 & mask ) == ( a2->ip4 & mask ); + } + else if ( a1->ipvers == 6 ) + { + ipv6_t mask = GetIP6Mask(bits); + return !( ( a1->ip6.v64[0] ^ a2->ip6.v64[0] ) & mask.v64[0] ) + && !( ( a1->ip6.v64[1] ^ a2->ip6.v64[1] ) & mask.v64[1] ); + } + } + return false; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct BinIPList_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void ResetBIL ( BinIPList_t *bil ) +{ + if (bil) + { + ClearBIL(bil); + FREE(bil->list); + InitializeBIL(bil); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void ClearBIL ( BinIPList_t *bil ) +{ + if (bil) + { + BinIPItem_t *it = bil->list; + for ( int i = 0; i < bil->used; i++, it++ ) + { + FreeString(it->name); + it->name = 0; + } + bil->used = 0; + } +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +void SetSizeBIL ( BinIPList_t *bil, int size ) +{ + DASSERT(bil); + if ( size < 0 ) + size = 0; + + if ( bil->used > size ) + { + for ( int i = size; i < bil->used; i++ ) + { + BinIPItem_t *it = bil->list + i; + FreeString(it->name); + } + bil->used = size; + } + + if ( bil->size != size ) + { + bil->size = size; + bil->list = REALLOC( bil->list, size * sizeof(*bil->list) ); + } + + DASSERT( !bil->size || bil->list ); + DASSERT( bil->used <= bil->size ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void SetMinSizeBIL ( BinIPList_t *bil, int min_size ) +{ + DASSERT(bil); + if ( min_size > bil->size ) + { + const int good_size = bil->size / 8 + 10; + if ( min_size < good_size ) + min_size = good_size; + SetSizeBIL(bil,min_size); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +BinIPItem_t * CreateItemBIL ( BinIPList_t *bil, int n_item ) +{ + DASSERT(bil); + if ( n_item < 0 ) + n_item = 0; + + SetMinSizeBIL(bil,bil->used+n_item); + BinIPItem_t *res = bil->list + bil->used; + if ( n_item > 0 ) + memset( res, 0, n_item * sizeof(*res) ); + bil->used += n_item; + + DASSERT( !bil->size || bil->list ); + DASSERT( bil->used <= bil->size ); + return res; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +#if 0 + +BinIPItem_t * InsertBIL ( BinIPList_t *bil, int index, ccp key, CopyMode_t copy_mode ) +{ + DASSERT(bil); + // ??? + return 0; +} + +#endif +/////////////////////////////////////////////////////////////////////////////// +#if 0 + +BinIPItem_t * InsertByKeyBIL ( BinIPList_t *bil, ccp key, CopyMode_t copy_mode ) +{ + DASSERT(bil); + // ??? + return 0; +} + +#endif +/////////////////////////////////////////////////////////////////////////////// +#if 0 + +int FindIndexBIL ( const BinIPList_t *bil, ccp key ) +{ + DASSERT(bil); + // ??? + return 0; +} + +#endif +/////////////////////////////////////////////////////////////////////////////// + +BinIPIterate_t FindAddressBIL ( const BinIPList_t *bil, BinIP_t *addr, uint use_mask ) +{ + BinIPIterate_t iter; + if ( bil && bil->used && addr && addr->ipvers ) + { + iter.valid = true; + iter.bil = bil; + iter.cur = bil->list - 1; + iter.addr = *addr; + iter.use_mask = use_mask; + FindNextAddressBIL(&iter); + } + else + memset(&iter,0,sizeof(iter)); + return iter; +} + +//----------------------------------------------------------------------------- + +void FindNextAddressBIL ( BinIPIterate_t *iter ) +{ + if ( iter && iter->valid && iter->bil && iter->cur ) + { + for ( uint idx = iter->cur + 1 - iter->bil->list; idx < iter->bil->used; idx++ ) + { + BinIPItem_t *it = iter->bil->list + idx; + if (IsSameBIP(&it->bip,&iter->addr,iter->use_mask)) + { + iter->cur = it; + return; + } + } + } + + iter->valid = false; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +BinIP_t GetBIPBySA ( sockaddr_t *addr, sockaddr_t *mask ) +{ + BinIP_t res = {0}; + if (addr) + { + if ( addr->sa_family == AF_INET ) + { + res.ipvers = 4; + res.bits = GetBitsBySA(mask,32); + res.ip4 = ((sockaddr_in4_t*)addr)->sin_addr.s_addr; + } + else if ( addr->sa_family == AF_INET6 ) + { + res.ipvers = 6; + res.bits = GetBitsBySA(mask,128); + memcpy(&res.ip6,&((sockaddr_in6_t*)addr)->sin6_addr,sizeof(res.ip6)); + } + } + return res; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +uint ScanInterfaceAddresses ( BinIPList_t *bil, bool init_bil ) +{ + DASSERT(bil); + if (init_bil) + InitializeBIL(bil); + else + ClearBIL(bil); + + struct ifaddrs *ifaddr; + if (getifaddrs(&ifaddr)) + return -1; + + for ( const struct ifaddrs *ifa = ifaddr; ifa; ifa = ifa->ifa_next ) + { + BinIP_t temp = GetBIPBySA(ifa->ifa_addr,ifa->ifa_netmask); + if (temp.ipvers) + { + BinIPItem_t *it = CreateItemBIL(bil,1); + it->name = STRDUP(ifa->ifa_name); + it->bip = temp; + } + } + freeifaddrs(ifaddr); + + return bil->used; +} + +/////////////////////////////////////////////////////////////////////////////// + +const BinIPList_t * GetInterfaceAddressList ( bool update ) +{ + static BinIPList_t *list = 0; + + if ( !list || update ) + { + bool init = !list; + if (init) + list = MALLOC(sizeof(*list)); + ScanInterfaceAddresses(list,init); + } + return list; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool IsLocalBIL ( BinIP_t *addr, uint use_mask ) +{ + const BinIPList_t *ial = GetInterfaceAddressList(false); + BinIPIterate_t iter = FindAddressBIL(ial,addr,use_mask); + return iter.valid; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct ManageIP_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void ResetMIP ( ManageIP_t *mip ) +{ + if (mip) + { + FreeString(mip->name); + FreeString(mip->decoded_name); + memset(mip,0,sizeof(*mip)); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void ClearNameMIP ( ManageIP_t *mip ) +{ + if (mip) + { + FreeString(mip->name); + FreeString(mip->decoded_name); + mip->name = mip->decoded_name = 0; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +ManageIP_t GetCopyMIP ( const ManageIP_t *mip ) +{ + ManageIP_t res; + if (mip) + { + memcpy(&res,mip,sizeof(res)); + if (res.name) + res.name = STRDUP(res.name); + if (res.decoded_name) + res.decoded_name = STRDUP(res.decoded_name); + } + else + memset(&res,0,sizeof(res)); + + return res; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool AssignMIP ( ManageIP_t *dest, const ManageIP_t *src ) +{ + if (dest) + { + ClearNameMIP(dest); + *dest = GetCopyMIP(src); + return dest->bin.ipvers != 0; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool AssignBinMIP ( ManageIP_t *mip, cvp bin, int bits ) +{ + DASSERT(mip); + ResetMIP(mip); + if (!bin) + return false; + + const BinIP_t *bip = bin; + if ( bip->ipvers == 4 ) + mip->relevant_bits = 32; + else if ( bip->ipvers == 6 ) + mip->relevant_bits = 128; + else + return false; + + memcpy(&mip->bin,bin,sizeof(mip->bin)); + if ( bits >= 0 ) + { + mip->have_bits = true; + mip->bin.bits = bits < mip->relevant_bits ? bits : mip->relevant_bits; + } + + if ( mip->bin.bits < mip->relevant_bits ) + mip->have_bits = true; + else + mip->bin.bits = mip->relevant_bits; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool AssignSockaddrMIP ( ManageIP_t *mip, cvp sockaddr, u16 port, int bits ) +{ + DASSERT(mip); + ResetMIP(mip); + if (!sockaddr) + return false; + + const sockaddr_in46_t *sa = sockaddr; + if ( sa->family == AF_INET ) + { + mip->bin.ipvers = 4; + mip->bin.bits = 32; + mip->bin.ip4 = sa->in4.sin_addr.s_addr; + mip->port = ntohs(sa->in4.sin_port); + } + else if ( sa->family == AF_INET6 ) + { + mip->bin.ipvers = 6; + mip->bin.bits = 128; + memcpy(mip->bin.ip6_8,sa->in6.sin6_addr.s6_addr,sizeof(mip->bin.ip6_8)); + mip->port = ntohs(sa->in6.sin6_port); + } + + mip->relevant_bits = mip->bin.bits; + if ( bits >= 0 ) + { + mip->have_bits = true; + if ( mip->bin.bits > bits ) + mip->bin.bits = bits; + } + + if ( !mip->port ) + mip->port = port; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool ScanMIP ( ManageIP_t *mip, ccp addr ) +{ + DASSERT(mip); + ResetMIP(mip); + + SplitIP_t sip; + if (!SplitIP(&sip,addr)) + return false; + + if (strchr(sip.name,':')) + { + if ( inet_pton(AF_INET6,sip.name,mip->bin.ip6_32) != 1 ) + return false; + mip->bin.ipvers = 6; + mip->relevant_bits = 128; + } + else + { + struct in_addr inp; + if (!dclib_aton(sip.name,&inp)) + return false; + + mip->bin.ipvers = 4; + mip->bin.ip4 = inp.s_addr; + mip->relevant_bits = 32; + } + + mip->bin.bits = mip->relevant_bits; + if ( sip.bits >= 0 ) + { + mip->have_bits = true; + if ( sip.bits < mip->relevant_bits ) + mip->bin.bits = sip.bits; + } + + mip->port = sip.port; + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +ManageIP_t GetSockNameMIP ( int sock ) +{ + ManageIP_t mip = {{0}}; + sockaddr_in46_t sa; + socklen_t sa_len = sizeof(sa); + if (!getsockname(sock,(sockaddr_t*)&sa,&sa_len)) + AssignSockaddrMIP(&mip,&sa,0,-1); + return mip; +} + +/////////////////////////////////////////////////////////////////////////////// + +ManageIP_t GetPeerNameMIP ( int sock ) +{ + ManageIP_t mip = {{0}}; + sockaddr_in46_t sa; + socklen_t sa_len = sizeof(sa); + if (!getpeername(sock,(sockaddr_t*)&sa,&sa_len)) + AssignSockaddrMIP(&mip,&sa,0,-1); + return mip; +} + +/////////////////////////////////////////////////////////////////////////////// + +ManageIP_t GetAddrInfoMIP ( ccp addr, int protocol, IpMode_t ipm ) +{ + ManageIP_t mip = {{0}}; + + SplitIP_t sip; + if (SplitIP(&sip,addr)) + { + struct addrinfo hints + = { .ai_family = AF_UNSPEC, + .ai_protocol = protocol < 0 ? IPPROTO_TCP : protocol }; + struct addrinfo *result; + if (!getaddrinfo(sip.name,0,&hints,&result)) + { + struct addrinfo *ip4 = 0, *ip6 = 0; + for ( struct addrinfo *rp = result; rp; rp = rp->ai_next) + { + if ( !ip4 && rp->ai_family == AF_INET ) + ip4 = rp; + else if ( !ip6 && rp->ai_family == AF_INET6 ) + ip6 = rp; + } + + switch (ipm) + { + case IPV4_ONLY: break; // nothing to do + case IPV6_ONLY: ip4 = ip6; break; + case IPV4_FIRST: if (!ip4) ip4 = ip6; break; + case IPV6_FIRST: if (ip6) ip4 = ip6; break; + } + + if (ip4) + AssignSockaddrMIP(&mip,ip4->ai_addr,sip.port,sip.bits); + + freeaddrinfo(result); + } + } + + return mip; +} + +/////////////////////////////////////////////////////////////////////////////// + +sockaddr_in46_t GetSockaddrMIP ( const ManageIP_t *mip ) +{ + DASSERT(mip); + sockaddr_in46_t sa = { .family = 0 }; + + if ( mip->bin.ipvers == 4 ) + { + sa.in4.sin_family = AF_INET; + sa.in4.sin_addr.s_addr = mip->bin.ip4; + sa.in4.sin_port = htons(mip->port); + } + else if ( mip->bin.ipvers == 6 ) + { + sa.in6.sin6_family = AF_INET6; + sa.in6.sin6_port = htons(mip->port); + memcpy(sa.in6.sin6_addr.s6_addr,mip->bin.ip6_8,sizeof(sa.in6.sin6_addr)); + } + + return sa; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp GetNameInfoMIP ( ManageIP_t *mip ) +{ + DASSERT(mip); + if ( !mip->name && mip->bin.ipvers ) + { + char host1[NI_MAXHOST+20], host2[NI_MAXHOST+20]; + sockaddr_in46_t sa = GetSockaddrMIP(mip); + + if (!getnameinfo( (sockaddr_t*)&sa,sizeof(sa), host1,sizeof(host1), 0,0, 0 )) + { + mip->name = STRDUP(host1); + + FreeString(mip->decoded_name); + const uint stat = Domain2UTF8(host2,sizeof(host2),host1,-1); + mip->decoded_name = stat && *host2 && strcmp(host1,host2) ? STRDUP(host2) : 0; + } + } + return mip->name; +} + +/////////////////////////////////////////////////////////////////////////////// + +void ApplyMaskMIP ( ManageIP_t *mip, int bits ) +{ + DASSERT(mip); + if ( bits >= 0 && bits < mip->bin.bits ) + mip->bin.bits = bits; + ApplyIPMask(&mip->bin); +} + +/////////////////////////////////////////////////////////////////////////////// + +void MaskPrefixMIP ( ManageIP_t *mip ) +{ + DASSERT(mip); + if ( mip->bin.ipvers == 4 || mip->bin.ip6_64[0] != 0ull ) + ApplyMaskMIP(mip,64); +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintAddrMIP ( const ManageIP_t *mip, PrintModeIP_t pmode ) +{ + DASSERT(mip); + + ccp res; + char buf[INET6_ADDRSTRLEN+1]; + + switch (mip->bin.ipvers) + { + case 4: + res = buf; + if ( pmode & PMIP_0DOTS ) + snprintf(buf,sizeof(buf),"%u",ntohl(mip->bin.ip4)); + else if ( pmode & PMIP_1DOT ) + snprintf(buf,sizeof(buf), "%u.%u", + mip->bin.ip4x.v8[0], ntohl(mip->bin.ip4)&0xffffff ); + else if ( pmode & PMIP_2DOTS ) + snprintf(buf,sizeof(buf), "%u.%u.%u", + mip->bin.ip4x.v8[0], mip->bin.ip4x.v8[1], ntohs(mip->bin.ip4x.v16[1]) ); + else + snprintf(buf,sizeof(buf), "%u.%u.%u.%u", + mip->bin.ip4x.v8[0], mip->bin.ip4x.v8[1], + mip->bin.ip4x.v8[2], mip->bin.ip4x.v8[3] ); + break; + + case 6: + if ( pmode & PMIP_FULL_IPV6 ) + { + snprintf(buf,sizeof(buf), "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", + ntohs(mip->bin.ip6.v16[0]), + ntohs(mip->bin.ip6.v16[1]), + ntohs(mip->bin.ip6.v16[2]), + ntohs(mip->bin.ip6.v16[3]), + ntohs(mip->bin.ip6.v16[4]), + ntohs(mip->bin.ip6.v16[5]), + ntohs(mip->bin.ip6.v16[6]), + ntohs(mip->bin.ip6.v16[7]) ); + res = buf; + } + else + res = inet_ntop(AF_INET6,mip->bin.ip6_32,buf,sizeof(buf)); + break; + + default: + res = 0; + } + + if (!res) + return 0; + + char port[100]; + *port = 0; + if ( mip->port && pmode & (PMIP_SERVICE|PMIP_PORT) ) + { + if ( pmode & PMIP_SERVICE ) + { + struct servent result_buf; + struct servent *result; + char buf[1000]; + const int stat = getservbyport_r(htons(mip->port),0,&result_buf,buf,sizeof(buf),&result); + if ( !stat && result ) + snprintf(port,sizeof(port),":%s",result_buf.s_name); + } + + if (!*port) + snprintf(port,sizeof(port),":%u",mip->port); + pmode |= PMIP_BRACKETS; + } + + char bits[20]; + if (PrintBitsMIP(mip,pmode)) + { + if ( mip->bin.ipvers == 4 && pmode & PMIP_MASK ) + { + ipv4x_t mask; + mask.ip4 = GetIP4Mask(mip->bin.bits); + snprintf(bits,sizeof(bits),"/%d.%d.%d.%d", + mask.v8[0], mask.v8[1], mask.v8[2], mask.v8[3] ); + } + else + snprintf(bits,sizeof(bits),"/%u",mip->bin.bits); + } + else + *bits = 0; + + return pmode & PMIP_BRACKETS && mip->bin.ipvers == 6 + ? PrintCircBuf("[%s]%s%s",res,port,bits) + : PrintCircBuf("%s%s%s",res,port,bits); +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintVersAddrMIP ( const ManageIP_t *mip, PrintModeIP_t pmode ) +{ + DASSERT(mip); + ccp res = PrintAddrMIP(mip,pmode); + return res ? PrintCircBuf("IPv%u %s",mip->bin.ipvers,res) : 0; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +ccp GetSqlSetAddrMIP ( const ManageIP_t *mip, const NamesIP_t *names ) +{ + if (!mip) + return 0; + + NamesIP_t nip; + SetupNamesIP(&nip,names); + + if ( mip->bin.ipvers == 4 ) + { + const ipv4_t mask = GetIP4Mask(mip->bin.bits); + return PrintCircBuf("%s=4,%s=0,%s=0x%08x", + nip.ipvers, nip.addr1, + nip.addr2, ntohl( mip->bin.ip4 & mask )); + } + else if ( mip->bin.ipvers == 6 ) + { + const ipv6_t mask = GetIP6Mask(mip->bin.bits); + return PrintCircBuf("%s=6,%s=0x%llx,%s=0x%llx", + nip.ipvers, + nip.addr1, ntoh64( mip->bin.ip6_64[0] & mask.v64[0] ), + nip.addr2, ntoh64( mip->bin.ip6_64[1] & mask.v64[1] )); + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp GetSqlSetMaskMIP ( const ManageIP_t *mip, const NamesIP_t *names ) +{ + if (!mip) + return 0; + + NamesIP_t nip; + SetupNamesIP(&nip,names); + + if ( mip->bin.ipvers == 4 ) + { + const ipv4_t mask = GetIP4Mask(mip->bin.bits); + return PrintCircBuf("%s=4,%s=0,%s=0x%08x,%s=0,%s=0x%08x", + nip.ipvers, nip.addr1, + nip.addr2, ntohl( mip->bin.ip4 & mask ), + nip.mask1, nip.mask2, ntohl(mask)); + } + else if ( mip->bin.ipvers == 6 ) + { + const ipv6_t mask = GetIP6Mask(mip->bin.bits); + return PrintCircBuf("%s=6,%s=0x%llx,%s=0x%llx,%s=0x%llx,%s=0x%llx", + nip.ipvers, + nip.addr1, ntoh64( mip->bin.ip6_64[0] & mask.v64[0] ), + nip.addr2, ntoh64( mip->bin.ip6_64[1] & mask.v64[1] ), + nip.mask1, ntoh64(mask.v64[0]), + nip.mask2, ntoh64(mask.v64[1]) ); + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp GetSqlSetBinMIP ( const ManageIP_t *mip, const NamesIP_t *names ) +{ + if (!mip) + return 0; + + NamesIP_t nip; + SetupNamesIP(&nip,names); + + return PrintCircBuf("%s=unhex('%02x%02x%016llx%016llx')", + nip.binaddr, mip->bin.ipvers, mip->bin.bits, + ntoh64(mip->bin.ip6_64[0]), ntoh64(mip->bin.ip6_64[0]) ); +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp GetSqlCondAddrMIP ( const ManageIP_t *mip, const NamesIP_t *names ) +{ + if (!mip) + return 0; + + NamesIP_t nip; + SetupNamesIP(&nip,names); + + if ( mip->bin.ipvers == 4 ) + return PrintCircBuf("%s=4 && %s=0x%08x", + nip.ipvers, nip.addr2, ntohl(mip->bin.ip4) ); + else if ( mip->bin.ipvers == 6 ) + return PrintCircBuf("%s=6 && %s=0x%llx && %s=0x%llx", + nip.ipvers, + nip.addr1, ntoh64(mip->bin.ip6_64[0]), + nip.addr2, ntoh64(mip->bin.ip6_64[1]) ); + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp GetSqlCondMaskMIP ( const ManageIP_t *mip, const NamesIP_t *names ) +{ + if (!mip) + return 0; + + NamesIP_t nip; + SetupNamesIP(&nip,names); + + if ( mip->bin.ipvers == 4 ) + return PrintCircBuf("%s=4 && %s=(%s&0x%08x)", + nip.ipvers, + nip.addr2, nip.mask2, ntohl(mip->bin.ip4) ); + else if ( mip->bin.ipvers == 6 ) + return PrintCircBuf("%s=6 && %s=(%s&0x%llx) && %s=(%s&0x%llx)", + nip.ipvers, + nip.addr1, nip.mask1, ntoh64(mip->bin.ip6_64[0]), + nip.addr2, nip.mask2, ntoh64(mip->bin.ip6_64[1]) ); + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp GetSqlCondBinMaskMIP ( const ManageIP_t *mip, const NamesIP_t *names ) +{ + if (!mip) + return 0; + + NamesIP_t nip; + SetupNamesIP(&nip,names); + + if ( mip->bin.ipvers == 4 ) + return PrintCircBuf("compare_binaddr(%s,4,0,0x%08x,%s,%s)", + nip.binaddr, ntohl(mip->bin.ip4), + nip.mask1, nip.mask2 ); + else if ( mip->bin.ipvers == 6 ) + return PrintCircBuf("compare_binaddr(%s,6,0x%llx,0x%llx,%s,%s)", + nip.binaddr, + ntoh64(mip->bin.ip6_64[0]), ntoh64(mip->bin.ip6_64[1]), + nip.mask1, nip.mask2 ); + + return 0; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct ResolveIP_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void ResetRIP ( ResolveIP_t *rip ) +{ + if (rip) + { + ResetMIP(&rip->mip4); + ResetMIP(&rip->mip6); + memset(rip,0,sizeof(*rip)); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void ClearNamesRIP ( ResolveIP_t *rip ) +{ + if (rip) + { + ClearNameMIP(&rip->mip4); + ClearNameMIP(&rip->mip6); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +int SetupListRIP ( ResolveIP_t *rip ) +{ + DASSERT(rip); + memset(rip->mip_list,0,sizeof(rip->mip_list)); + + ManageIP_t **mp = rip->mip_list; + switch (rip->ip_mode) + { + case IPV6_FIRST: + if (rip->mip6.bin.ipvers) + *mp++ = &rip->mip6; + // fall though + case IPV4_ONLY: + if (rip->mip4.bin.ipvers) + *mp++ = &rip->mip4; + break; + + case IPV4_FIRST: + if (rip->mip4.bin.ipvers) + *mp++ = &rip->mip4; + // fall though + case IPV6_ONLY: + if (rip->mip6.bin.ipvers) + *mp++ = &rip->mip6; + break; + } + + return mp - rip->mip_list; +} + +/////////////////////////////////////////////////////////////////////////////// + +ResolveIP_t GetCopyRIP ( const ResolveIP_t *rip ) +{ + ResolveIP_t res; + if (rip) + { + res.ip_mode = rip->ip_mode; + res.mip4 = GetCopyMIP(&rip->mip4); + res.mip6 = GetCopyMIP(&rip->mip6); + SetupListRIP(&res); + } + else + memset(&res,0,sizeof(res)); + + return res; +} + +/////////////////////////////////////////////////////////////////////////////// + +void AssignRIP ( ResolveIP_t *dest, const ResolveIP_t *src ) +{ + if (dest) + { + ClearNamesRIP(dest); + *dest = GetCopyRIP(src); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +int ScanRIP +( + // return 0..2 = number of records + + ResolveIP_t *rip, // valid data, ResetRIP() + ccp addr, // address to scan + int protocol, // protocol to use: 0=all, -1=default (IPPROTO_TCP at the moment) + IpMode_t ip_mode, // IPv4 and/or IPV6, order of 'mip_list' + bool get_names // true: call GetNameInfoMIP() +) +{ + DASSERT(rip); + ResetRIP(rip); + + SplitIP_t sip; + if (!SplitIP(&sip,addr)) + return 0; + NormalizeNameSIP(&sip); + + rip->ip_mode = ip_mode; + + struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }; + struct addrinfo *result; + char aname[300]; + Domain2ASCII(aname,sizeof(aname),sip.name,-1); + if (!getaddrinfo(aname,0,&hints,&result)) + { + struct addrinfo *ip4 = 0, *ip6 = 0; + for ( struct addrinfo *rp = result; rp; rp = rp->ai_next) + { + if ( !ip4 && rp->ai_family == AF_INET ) + ip4 = rp; + else if ( !ip6 && rp->ai_family == AF_INET6 ) + ip6 = rp; + } + + if (ip4) + AssignSockaddrMIP(&rip->mip4,ip4->ai_addr,sip.port,sip.bits); + + if (ip6) + AssignSockaddrMIP(&rip->mip6,ip6->ai_addr,sip.port,sip.bits); + + if (get_names) + { + GetNameInfoMIP(&rip->mip4); + GetNameInfoMIP(&rip->mip6); + } + + freeaddrinfo(result); + } + + return SetupListRIP(rip); +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +#if 0 + +void DumpRIP ( FILE *f, int indent, const ResolveIP_t *rip ) +{ + if ( !f || !rip ) + return; + indent = NormalizeIndent(indent); +} + +#endif +// +/////////////////////////////////////////////////////////////////////////////// /////////////// struct AllowIP4_t /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -262,6 +1690,9 @@ const KeywordTab_t AllowIP4KeyTable[] = { ALLOW_MODE_LOG, "LOG", 0, 0 }, { ALLOW_MODE_VERBOSE, "VERBOSE", 0, 0 }, + { ALLOW_RELEASE, "RELEASE", 0, 0 }, + { ALLOW_DEBUG, "DEBUG", 0, 0 }, + { ALLOW_MODE_NOT, "NOT", 0, 0 }, { ALLOW_MODE_SET, "SET", 0, ALLOW_MODE__OP }, { ALLOW_MODE_AND, "AND", 0, ALLOW_MODE__OP }, @@ -382,6 +1813,13 @@ enumError ScanLineAllowIP4 if ( res & ALLOW_MODE_NOT ) res = res ^ ALLOW_MODE__MASK; + #if defined(DEBUG) && DEBUG > 0 || defined(IS_DEVELOP) && IS_DEVELOP > 0 + if ( res & ALLOW_RELEASE ) + return ERR_OK; + #else + if ( res & ALLOW_DEBUG ) + return ERR_OK; + #endif //--- add item @@ -3120,12 +4558,15 @@ void OnCloseStream PRINT("CLOSE: %d\n",ts->sock); if (ts->OnClose) ts->OnClose(ts,now_usec); + if ( ts->sock != -1 ) { + // if not closed by OnClose() shutdown(ts->sock,SHUT_RDWR); close(ts->sock); ts->sock = -1; } + if ( !ts->protect && ts->handler ) ts->handler->need_maintenance |= 1; @@ -3312,7 +4753,7 @@ void CheckTimeoutTCP ( TCPHandler_t *th ) /////////////////////////////////////////////////////////////////////////////// -bool MaintenanceTCP ( TCPHandler_t *th ) +bool MaintainTCP ( TCPHandler_t *th ) { DASSERT(th); @@ -3338,7 +4779,7 @@ bool MaintenanceTCP ( TCPHandler_t *th ) void ManageSocketsTCP ( - // call CheckSocketsTCP(), CheckTimeoutTCP(), MaintenanceTCP() + // call CheckSocketsTCP(), CheckTimeoutTCP(), MaintainTCP() TCPHandler_t *th, // valid TCP handler FDList_t *fdl, // valid socket list @@ -3351,7 +4792,7 @@ void ManageSocketsTCP CheckTimeoutTCP(th); if (th->need_maintenance) - MaintenanceTCP(th); + MaintainTCP(th); } /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/dclib-network.h b/project/dclib/dclib-network.h index 1f89690..41f371f 100644 --- a/project/dclib/dclib-network.h +++ b/project/dclib/dclib-network.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -40,6 +40,8 @@ #include "dclib-basics.h" #include "dclib-file.h" +#include <stddef.h> + // /////////////////////////////////////////////////////////////////////////////// /////////////// definitions /////////////// @@ -108,29 +110,401 @@ bool ResolveHostMem // /////////////////////////////////////////////////////////////////////////////// +/////////////// enum PrintModeIP_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[PrintModeIP_t]] + +typedef enum PrintModeIP_t +{ + // characters for ScanPrintModeIP(): nria + PMIP_NEVER = 0x000, ///< '/Bits' unterdrücken. + PMIP_RELEVANT = 0x001, ///< '/Bits' nur falls relevant. + PMIP_IF_SET = 0x002, ///< '/Bits' nur falls gesetzt. + PMIP_ALWAYS = 0x003, ///< '/Bits' immer ausgeben. + PMIP_M_BITS = 0x003, ///< Maske für Bit-Modi. + + // characters for ScanPrintModeIP(): psmb + PMIP_PORT = 0x004, ///< Flag: Print port if >0. + PMIP_SERVICE = 0x008, ///< Flag: Print service instead of port number. + PMIP_MASK = 0x010, ///< Flag: Print netmask instead of bits for IPv4. + PMIP_BRACKETS = 0x020, ///< Flag: Print bracktes if [IPv6]. + + // characters for ScanPrintModeIP(): f + PMIP_FULL_IPV6 = 0x100, ///< Print IPv6 without short numbers. + + // characters for ScanPrintModeIP(): 0123 + PMIP_0DOTS = 0x200, ///< Print IPv4 as single number (highest priority). + PMIP_1DOT = 0x400, ///< Print IPv4 as "1.2" (A-Class notation). + PMIP_2DOTS = 0x800, ///< Print IPv4 as "1.2.3" (B-Class notation). + PMIP_3DOTS = 0, ///< Print IPv4 as "1.2.3.4" (C-Class notation, default). + PMIP_M_DOTS = 0xc00 ///< Maske für Dot-Modi. +} +PrintModeIP_t; + +PrintModeIP_t ScanPrintModeIP ( PrintModeIP_t base, ccp arg ); +ccp PrintPrintModeIP ( PrintModeIP_t val, bool align ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// enum IPClass_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[IPClass_t]] + +typedef enum IPClass_t +{ + IPCL_INVALID, // 0.0.0.0 :: + IPCL_LOOPBACK, // 127.0/8 ::1 + IPCL_LOCAL, // 10.0/8 172.16/12 192.168/16 169.254/16 fe80::/10 + IPCL_STANDARD, // * * + IPCL_SPECIAL, // 224.0.0.0/3 f00::/8 + IPCL__N, +} +IPClass_t; + +//----------------------------------------------------------------------------- + +ccp GetIPClassColor ( const ColorSet_t *colset, IPClass_t ipc ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct SplitIP_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[SplitIP_t]] + +typedef struct SplitIP_t +{ + int bits; + u16 port; + char name[260]; +} +SplitIP_t; + +//----------------------------------------------------------------------------- + +bool SplitIP ( SplitIP_t *sip, ccp addr ); + +static inline void NormalizeNameSIP ( SplitIP_t *sip ) + { DASSERT(sip); NormalizeIP4(sip->name,sizeof(sip->name),true,sip->name,-1); } + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct NamesIP_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[NamesIP_t]] + +typedef struct NamesIP_t +{ + ccp binaddr; + ccp ipvers; + ccp addr1; + ccp addr2; + ccp bits; + ccp mask1; + ccp mask2; +} +NamesIP_t; + +//----------------------------------------------------------------------------- + +// reset if src==NULL +void SetupNamesIP ( NamesIP_t *dest, const NamesIP_t *src ); +void SetupNamesByListIP ( NamesIP_t *dest, const exmem_list_t *src ); + +ccp PrintNamesIP ( const NamesIP_t *nip ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct BinIP_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +enum +{ + IP_SIZE_ADDR = 39, ///< Maximale Zeichenlänge einer Adresse ohne Maske. + IP_SIZE_ADDR_MASK = 43, ///< Maximale Zeichenlänge einer Adresse mit Maske. + IP_SIZE_PREFIX = 22, ///< Maximale Zeichenlänge einer Adresse, die mit MaskPrefixMIP() gekürzt wurde. + IP_SIZE_ADDR_BIN = 22, ///< Size für eine binäre IP (ohne Maske). + + IP_SIZE_BINIP_C = 20, ///< Size für binäres Tupel (padding,ipvers,bits,addr). + IP_SIZE_BINIP = 18, ///< Size für binäres Tupel (ipvers,bits,addr). + IP_OFFSET_BINIP = 2, ///< Offset für DB-Transfer. +}; + +/////////////////////////////////////////////////////////////////////////////// +// [[BinIP_t]] + +typedef struct BinIP_t +{ + u16 user_id; // any id defined by user + u8 ipvers; // 0:invalid, 4:IPv4, 6:IPv6 + u8 bits; // number of 1-bits in netmask + + union // different views of ip address + { + u8 ip6_8[16]; + u16 ip6_16[8]; + u32 ip6_32[4]; + u64 ip6_64[2]; + ipv6_t ip6; + + struct + { + ipv4_t ip4_padding[3]; + ipv4_t ip4; + }; + + struct + { + ipv4_t ip4x_padding[3]; + ipv4x_t ip4x; + }; + }; +} +__attribute__ ((packed)) BinIP_t; + +_Static_assert( offsetof(BinIP_t,ipvers) == IP_OFFSET_BINIP, "wrong order of BinIP_t members" ); +_Static_assert( sizeof(BinIP_t) == IP_SIZE_BINIP_C, "wrong size of BinIP_t" ); + +//----------------------------------------------------------------------------- + +static inline u8 * GetCorePtrBIP ( const BinIP_t *src ) { return (u8*)&src->ipvers; } +static inline uint GetCoreSizeBIP ( const BinIP_t *src ) { return IP_SIZE_BINIP; } + +BinIP_t GetIPMask ( const BinIP_t *src ); +void ApplyIPMask ( BinIP_t *bip ); + +IPClass_t GetIPClassBIP ( const BinIP_t * bip ); +static inline ccp GetColorBIP( const ColorSet_t *colset, const BinIP_t * bip ) + { return GetIPClassColor(colset,GetIPClassBIP(bip)); } + +ccp PrintBIP ( const BinIP_t * bip ); + +// returns false, if !a1 || !a2 || invalid || differ_after_mask +// use_mask: bit 0 == 1 : use mask of a1; bit 1 == 2 : use mask of a2 +bool IsSameBIP ( const BinIP_t *a1, const BinIP_t *a2, uint use_mask ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct BinIPList_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[BinIPItem_t]] + +typedef struct BinIPItem_t +{ + ccp name; // optional name, alloced + BinIP_t bip; // IP data +} +BinIPItem_t; + +/////////////////////////////////////////////////////////////////////////////// +// [[BinIPList_t]] + +typedef struct BinIPList_t +{ + BinIPItem_t *list; // list of elements + uint used; // number of used elements in 'list' + uint size; // number of allocated elements in 'list' +} +BinIPList_t; + +/////////////////////////////////////////////////////////////////////////////// +// [[BinIPIterate_t]] + +typedef struct BinIPIterate_t +{ + bool valid; // iterator is valid + const BinIPList_t *bil; // list data + const BinIPItem_t *cur; // current element + + BinIP_t addr; // address to serch + uint use_mask; // flags for IsSameBIP() +} +BinIPIterate_t; + +/////////////////////////////////////////////////////////////////////////////// + +static inline void InitializeBIL ( BinIPList_t *bil ) + { DASSERT(bil); memset(bil,0,sizeof(*bil)); } + +void ResetBIL ( BinIPList_t *bil ); +void ClearBIL ( BinIPList_t *bil ); + +void SetSizeBIL ( BinIPList_t *bil, int size ); +void SetMinSizeBIL ( BinIPList_t *bil, int min_size ); +BinIPItem_t * CreateItemBIL ( BinIPList_t *bil, int n_item ); + +#if 0 // not implemented +BinIPItem_t * InsertBIL ( BinIPList_t *bil, int index, ccp key, CopyMode_t copy_mode ); +BinIPItem_t * InsertByKeyBIL ( BinIPList_t *bil, ccp key, CopyMode_t copy_mode ); +static inline BinIPItem_t * Append ( BinIPList_t *bil, int index, ccp key, CopyMode_t copy_mode ) + { return InsertBIL(bil,INT_MAX,key,copy_mode); } + +int FindIndexBIL ( const BinIPList_t *bil, ccp key ); +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// bits for use_mask: +// bit 0 == 1 : use mask of BinIPList_t::items +// bit 1 == 2 : use mask of addr + +BinIPIterate_t FindAddressBIL ( const BinIPList_t *bil, BinIP_t *addr, uint use_mask ); +void FindNextAddressBIL ( BinIPIterate_t *iter ); + +uint ScanInterfaceAddresses ( BinIPList_t *bil, bool init_bil ); +const BinIPList_t * GetInterfaceAddressList ( bool update ); + +bool IsLocalBIL ( BinIP_t *addr, uint use_mask ); +static inline bool IsLocalAddress ( BinIP_t *addr ) { return IsLocalBIL(addr,2); } +static inline bool IsLocalNetwork ( BinIP_t *addr ) { return IsLocalBIL(addr,3); } + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct ManageIP_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[ManageIP_t]] + +typedef struct ManageIP_t +{ + BinIP_t bin; // binary data + u16 port; // 0: not specified + bool have_bits; // true: bits were specified on input + u8 relevant_bits; // number of relevant bits + ccp name; // NULL or getnameinfo(), alloced + ccp decoded_name; // NULL or punycode-decoded 'name' if differ, alloced +} +ManageIP_t; + +/////////////////////////////////////////////////////////////////////////////// + +static inline bool IsIPv4MIP ( const ManageIP_t *mip ) + { return mip && mip->bin.ipvers == 4; } + +static inline bool IsIPv6MIP ( const ManageIP_t *mip ) + { return mip && mip->bin.ipvers == 6; } + +//----------------------------------------------------------------------------- +// if bits==-1: ignore parameter + +void ResetMIP ( ManageIP_t *mip ); // mip can be NULL +void ClearNameMIP ( ManageIP_t *mip ); // mip can be NULL + +bool AssignMIP ( ManageIP_t *dest, const ManageIP_t *src ); +bool AssignBinMIP ( ManageIP_t *mip, cvp bin, int bits ); +bool AssignSockaddrMIP ( ManageIP_t *mip, cvp sockaddr, u16 port, int bits ); + +bool ScanMIP ( ManageIP_t *mip, ccp addr ); + +ManageIP_t GetCopyMIP ( const ManageIP_t *mip ); +ManageIP_t GetSockNameMIP ( int sock ); +ManageIP_t GetPeerNameMIP ( int sock ); + +// protocol: protocol to use: 0=all, -1=default (IPPROTO_TCP at the moment) +ManageIP_t GetAddrInfoMIP ( ccp addr, int protocol, IpMode_t ipm ); + +sockaddr_in46_t GetSockaddrMIP ( const ManageIP_t *mip ); +ccp GetNameInfoMIP ( ManageIP_t *mip ); + +void ApplyMaskMIP ( ManageIP_t *mip, int bits ); +void MaskPrefixMIP ( ManageIP_t *mip ); // includes ApplyMaskMIP() + +//----------------------------------------------------------------------------- + +static inline bool PrintBitsMIP ( const ManageIP_t *mip, PrintModeIP_t pmode ) +{ + DASSERT(mip); + pmode &= PMIP_M_BITS; + return pmode > PMIP_NEVER + && ( mip->bin.bits < mip->relevant_bits + || pmode == PMIP_IF_SET && mip->have_bits + || pmode >= PMIP_ALWAYS + ); +} + +ccp PrintAddrMIP ( const ManageIP_t *mip, PrintModeIP_t pmode ); +ccp PrintVersAddrMIP ( const ManageIP_t *mip, PrintModeIP_t pmode ); + +static inline IPClass_t GetIPClassMIP ( const ManageIP_t * mip ) + { DASSERT(mip); return GetIPClassBIP(&mip->bin); } + +//----------------------------------------------------------------------------- + +ccp GetSqlSetAddrMIP ( const ManageIP_t *mip, const NamesIP_t *names ); +ccp GetSqlSetMaskMIP ( const ManageIP_t *mip, const NamesIP_t *names ); +ccp GetSqlSetBinMIP ( const ManageIP_t *mip, const NamesIP_t *names ); + +ccp GetSqlCondAddrMIP ( const ManageIP_t *mip, const NamesIP_t *names ); +ccp GetSqlCondMaskMIP ( const ManageIP_t *mip, const NamesIP_t *names ); +ccp GetSqlCondBinMaskMIP ( const ManageIP_t *mip, const NamesIP_t *names ); + +static inline ccp GetSqlCondBinAddrMIP ( const ManageIP_t *mip, const NamesIP_t *names ) + { return GetSqlSetBinMIP(mip,names); } + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct ResolveIP_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[ResolveIP_t]] + +typedef struct ResolveIP_t +{ + IpMode_t ip_mode; // used mode + ManageIP_t mip4; // resolved IPv4 + ManageIP_t mip6; // resolved IPv6 + ManageIP_t *mip_list[3]; // ordered and 0-termiated list of valid 'mip*' +} +ResolveIP_t; + +//----------------------------------------------------------------------------- + +void ResetRIP ( ResolveIP_t *rip ); // rip can be NULL +void ClearNamesRIP ( ResolveIP_t *rip ); // rip can be NULL + +ResolveIP_t GetCopyRIP ( const ResolveIP_t *rip ); +void AssignRIP ( ResolveIP_t *dest, const ResolveIP_t *src ); + +int ScanRIP +( + // return 0..2 = number of records + + ResolveIP_t *rip, // valid data, ResetRIP() + ccp addr, // address to scan + int protocol, // protocol to use: 0=all, -1=default (IPPROTO_TCP at the moment) + IpMode_t ip_mode, // IPv4 and/or IPV6, order of 'mip_list' + bool get_names // true: call GetNameInfoMIP() +); + +// not implemented yet +// void DumpRIP ( FILE *f, int indent, const ResolveIP_t *rip ); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// struct AllowIP4_t /////////////// /////////////////////////////////////////////////////////////////////////////// // standard values #define ALLOW_MODE_DENY 0 // access denied -#define ALLOW_MODE_ALLOW 0x001 // access allowed -#define ALLOW_MODE_AKEY 0x002 // access allowed by access key +#define ALLOW_MODE_ALLOW 0x0001 // access allowed +#define ALLOW_MODE_AKEY 0x0002 // access allowed by access key // locations -#define ALLOW_MODE_EXTERN 0x004 // keyword 'EXTERN' set -#define ALLOW_MODE_LAN 0x008 // keyword 'LAN' set -#define ALLOW_MODE_LOCAL 0x010 // keyword 'LOCAL' set +#define ALLOW_MODE_EXTERN 0x0004 // keyword 'EXTERN' set +#define ALLOW_MODE_LAN 0x0008 // keyword 'LAN' set +#define ALLOW_MODE_LOCAL 0x0010 // keyword 'LOCAL' set // users -#define ALLOW_MODE_PUBLIC 0x020 // keyword 'PUBLIC' set -#define ALLOW_MODE_USER 0x040 // keyword 'USER' set -#define ALLOW_MODE_MOD 0x080 // keyword 'MOD' or 'MODERATOR' set -#define ALLOW_MODE_ADMIN 0x100 // keyword 'ADMIN' or 'ADMINISTRATOR' set -#define ALLOW_MODE_DEVELOP 0x200 // keyword 'DEVELOP' or 'DEVELOPER' set +#define ALLOW_MODE_PUBLIC 0x0020 // keyword 'PUBLIC' set +#define ALLOW_MODE_USER 0x0040 // keyword 'USER' set +#define ALLOW_MODE_MOD 0x0080 // keyword 'MOD' or 'MODERATOR' set +#define ALLOW_MODE_ADMIN 0x0100 // keyword 'ADMIN' or 'ADMINISTRATOR' set +#define ALLOW_MODE_DEVELOP 0x0200 // keyword 'DEVELOP' or 'DEVELOPER' set // logging -#define ALLOW_MODE_LOG 0x400 // keyword 'LOG' set -#define ALLOW_MODE_VERBOSE 0x800 // keyword 'VERBOSE' set +#define ALLOW_MODE_LOG 0x0400 // keyword 'LOG' set +#define ALLOW_MODE_VERBOSE 0x0800 // keyword 'VERBOSE' set + +// context +#define ALLOW_RELEASE 0x1000 // accept this record if neither DEBUG nor IS_DEVELOP is set +#define ALLOW_DEBUG 0x2000 // accept this record if DEBUG or IS_DEVELOP is set // special processing values #define ALLOW_MODE_NOT 0x1000000000000000ull // negate bits @@ -685,7 +1059,7 @@ ccp PrintTransferStatsSQL // NULL: use a local circulary static buffer size_t buf_size, // size of 'buf', ignored if buf==NULL const TransferStats_t *ts, // valid source - ccp prefix // not NULL: prefix memebr names + ccp prefix // not NULL: prefix member names ); //----------------------------------------------------------------------------- @@ -1085,7 +1459,7 @@ typedef struct TCPHandler_t TCPHandlerFunc OnAcceptStream; // not NULL: called before accpeting a connection TCPCreateFunc OnCreateStream; // not NULL: called to create // and initialize a stream object - TCPStreamFunc OnAddedStream; // not NULL: called after the stream + TCPStreamFunc OnAddedStream; // not NULL: called after the stream // is created and added TCPStreamFunc OnDestroyStream; // not NULL: called by ResetTCPStream() @@ -1282,11 +1656,11 @@ void CheckSocketsTCP ); void CheckTimeoutTCP ( TCPHandler_t *th ); -bool MaintenanceTCP ( TCPHandler_t *th ); +bool MaintainTCP ( TCPHandler_t *th ); void ManageSocketsTCP ( - // call CheckSocketsTCP(), CheckTimeoutTCP(), MaintenanceTCP() + // call CheckSocketsTCP(), CheckTimeoutTCP(), MaintainTCP() TCPHandler_t *th, // valid TCP handler FDList_t *fdl, // valid socket list @@ -1294,7 +1668,7 @@ void ManageSocketsTCP ); /////////////////////////////////////////////////////////////////////////////// -// special case: send single data packtes +// special case: send single data packets TCPStream_t * SendSingleUnixTCP ( diff --git a/project/dclib/dclib-numeric.c b/project/dclib/dclib-numeric.c index 50fd266..0b21975 100644 --- a/project/dclib/dclib-numeric.c +++ b/project/dclib/dclib-numeric.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -36,10 +36,12 @@ #include <string.h> #include <unistd.h> +#include <stddef.h> #include <time.h> #include <stdio.h> #include <errno.h> #include <sys/time.h> +#include <sys/resource.h> #include <fcntl.h> #include "dclib-basics.h" @@ -966,6 +968,213 @@ int CheckIndexCEnd ( int max, int * p_begin, int count ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// lt/eq/gt /////////////// +/////////////////////////////////////////////////////////////////////////////// + +char * ScanCompareOp ( compare_operator_t *dest_op, ccp arg ) +{ + compare_operator_t op = COP_FALSE; + ccp ptr = arg; + if (ptr) + { + while ( *ptr > 0 && *ptr <= ' ' ) + ptr++; + + if ( (uchar)ptr[0] == 0xe2 && (uchar)ptr[1] == 0x89 ) + { + switch ((uchar)ptr[2]) + { + case 0xa0: op = COP_NE; ptr += 3; break; // UTF8 ≠ + case 0xa4: op = COP_LE; ptr += 3; break; // UTF8 ≤ + case 0xa5: op = COP_GE; ptr += 3; break; // UTF8 ≥ + } + } + else if ( *ptr == '!' ) + { + if ( *++ptr == '=' ) + { + op = COP_NE; + ptr++; + } + } + else + switch (*ptr) + { + case '=': + op = COP_EQ; + if ( *++ptr == '=' ) + ptr++; + break; + + case '<': + op = COP_LT; + switch (*++ptr) + { + case '=': + op = COP_LE; + ptr++; + break; + case '>': + op = COP_NE; + ptr++; + break; + } + break; + + case '>': + op = COP_GT; + if ( *++ptr == '=' ) + { + op = COP_GE; + ptr++; + } + break; + } + } + + if (dest_op) + *dest_op = op; + return op == COP_FALSE ? (char*)arg : (char*)ptr; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp GetCompareOpName ( compare_operator_t op ) +{ + switch (op) + { + case COP_EQ: return "=="; + case COP_LT: return "<"; + case COP_GT: return ">"; + case COP_NE: return "!="; + case COP_LE: return "<="; + case COP_GE: return ">="; + case COP_TRUE: return "*"; + default: return "%"; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +bool CompareByOpStat ( int stat, compare_operator_t op ) +{ + switch (op) + { + case COP_EQ: return stat == 0; + case COP_LT: return stat < 0; + case COP_GT: return stat > 0; + case COP_NE: return stat != 0; + case COP_LE: return stat <= 0; + case COP_GE: return stat >= 0; + case COP_TRUE: return true; + default: return false; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +bool CompareByOpINT ( int a, compare_operator_t op, int b ) +{ + switch (op) + { + case COP_EQ: return a == b; + case COP_LT: return a < b; + case COP_GT: return a > b; + case COP_NE: return a != b; + case COP_LE: return a <= b; + case COP_GE: return a >= b; + case COP_TRUE: return true; + default: return false; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +bool CompareByOpUINT ( uint a, compare_operator_t op, uint b ) +{ + switch (op) + { + case COP_EQ: return a == b; + case COP_LT: return a < b; + case COP_GT: return a > b; + case COP_NE: return a != b; + case COP_LE: return a <= b; + case COP_GE: return a >= b; + case COP_TRUE: return true; + default: return false; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +bool CompareByOpI64 ( s64 a, compare_operator_t op, s64 b ) +{ + switch (op) + { + case COP_EQ: return a == b; + case COP_LT: return a < b; + case COP_GT: return a > b; + case COP_NE: return a != b; + case COP_LE: return a <= b; + case COP_GE: return a >= b; + case COP_TRUE: return true; + default: return false; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +bool CompareByOpU64 ( u64 a, compare_operator_t op, u64 b ) +{ + switch (op) + { + case COP_EQ: return a == b; + case COP_LT: return a < b; + case COP_GT: return a > b; + case COP_NE: return a != b; + case COP_LE: return a <= b; + case COP_GE: return a >= b; + case COP_TRUE: return true; + default: return false; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +bool CompareByOpFLT ( float a, compare_operator_t op, float b ) +{ + switch (op) + { + case COP_EQ: return a == b; + case COP_LT: return a < b; + case COP_GT: return a > b; + case COP_NE: return a != b; + case COP_LE: return a <= b; + case COP_GE: return a >= b; + case COP_TRUE: return true; + default: return false; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +bool CompareByOpDBL ( double a, compare_operator_t op, double b ) +{ + switch (op) + { + case COP_EQ: return a == b; + case COP_LT: return a < b; + case COP_GT: return a > b; + case COP_NE: return a != b; + case COP_LE: return a <= b; + case COP_GE: return a >= b; + case COP_TRUE: return true; + default: return false; + } +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// encoding/decoding /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -990,7 +1199,7 @@ ccp GetEncodingName ( EncodeMode_t em ) uint GetEscapedSize ( - // returns the needed buffer size for PrintEscapedString() + // returns the needed buffer size for PrintEscapedString() ccp source, // NULL or string to print int src_len, // length of string. if -1, str is null terminated @@ -1435,7 +1644,7 @@ uint EncodeBase64 // returns the number of scanned bytes of 'source' char *buf, // valid destination buffer - uint buf_size, // size of 'buf', >= 4 + uint buf_size, // size of 'buf' >= 4 const void *source, // NULL or data to encode int source_len, // length of 'source'; if <0: use strlen(source) const char encode64[64+1], // encoding table; if NULL: use TableEncode64default @@ -1564,7 +1773,7 @@ uint EncodeBase64ml // ml: multi line // returns the number of scanned bytes of 'source' char *buf, // valid destination buffer - uint buf_size, // size of 'buf', >= 4 + uint buf_size, // size of 'buf' >= 4 const void *source, // NULL or data to encode int source_len, // length of 'source'; if <0: use strlen(source) const char encode64[64+1], // encoding table; if NULL: use TableEncode64default @@ -1985,7 +2194,7 @@ uint EncodeByMode // returns the number of valid bytes in 'buf'. Result is NULL-terminated. char *buf, // valid destination buffer - uint buf_size, // size of 'buf', >= 4 + uint buf_size, // size of 'buf' >= 4 ccp source, // string to encode int slen, // length of string. if -1, str is null terminated EncodeMode_t emode // encoding mode @@ -2172,7 +2381,7 @@ char * EscapeString buf[0] = '$'; buf[1] = buf[len+2] = quote_char; buf[len+3] = 0; - + } else if ( quote_mode == 2 ) { @@ -2190,9 +2399,132 @@ char * EscapeString // /////////////////////////////////////////////////////////////////////////////// +/////////////// struct Escape_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// https://en.wikipedia.org/wiki/ANSI_escape_code + +const char ecape_stat_name[ESCST__N+1][5] = +{ + "-", // ESCST_NONE + "CHAR", // ESCST_CHAR + "FE", // ESCST_FE + "SS2", // ESCST_SS2 + "SS3", // ESCST_SS3 + "CSI", // ESCST_CSI + "OSC", // ESCST_OSC + "", // ESCST__N +}; + +/////////////////////////////////////////////////////////////////////////////// + +EscapeStat_t CheckEscape ( Escape_t *esc, cvp source, cvp end, bool check_esc ) +{ + DASSERT(esc); + memset(esc,0,sizeof(*esc)); + if (!source) + return 0; + + ccp src = source; + if (!end) + end = src + strlen(src); + if ( src >= (ccp)end ) + return 0; + + ccp beg = src; + if (check_esc) + { + if ( *src != '\e' ) + { + esc->status = ESCST_CHAR; + esc->code = *src++; + goto term; + } + + src++; + if ( src >= (ccp)end ) + return 0; + } + esc->code = *src++; + + int term_wd = 0; + switch (esc->code) + { + case 'N': //--- SS2: Single Shift 2 --- + if ( src < (ccp)end ) + { + esc->status = ESCST_SS2; + esc->code = *src++; + } + break; + + case 'O': //--- SS3: Single Shift 3 --- + if ( src < (ccp)end ) + { + esc->status = ESCST_SS3; + esc->code = *src++; + } + break; + + case '[': //--- CSI --- + while ( src < (ccp)end && *src >= 0x30 && *src <= 0x3f ) + src++; + while ( src < (ccp)end && *src >= 0x20 && *src <= 0x2f ) + src++; + if ( src < (ccp)end && *src >= 0x40 && *src <= 0x7e ) + { + esc->status = ESCST_CSI; + esc->code = *src++; + } + break; + + + case ']': //--- OSC --- + // terminate by ST (ESC \ == 0x9c) or BEL (7) + for ( ; src < (ccp)end; src++ ) + { + if ( *src == 7 || (u8)*src == 0x9c ) + { + src++; + term_wd = 1; + esc->status = ESCST_OSC; + break; + } + if ( src+1 < (ccp)end && src[0] == '\e' && src[1] == '\\' ) + { + src += 2; + term_wd = 2; + esc->status = ESCST_OSC; + break; + } + } + break; + + default: //--- single char --- + esc->status = ESCST_CHAR; + break; + } + + term:; + if ( esc->status != ESCST_NONE ) + { + esc->scanned_len = src - (ccp)source; + if ( esc->status > ESCST_CHAR ) + { + esc->esc.ptr = beg; + esc->esc.len = src - beg - term_wd; + } + } + + return esc->status; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// time /////////////// /////////////////////////////////////////////////////////////////////////////// +ccp micro_second_char = "u"; + s64 timezone_adjust_sec = -1; s64 timezone_adjust_usec = -1; s64 timezone_adjust_nsec = -1; @@ -2285,6 +2617,24 @@ struct timespec GetClockTime ( bool localtime ) return ts; } +//----------------------------------------------------------------------------- + +struct timespec GetClockTimer(void) +{ + struct timespec ts; + + #if HAVE_CLOCK_GETTIME + if (!clock_gettime(CLOCK_MONOTONIC,&ts)) + return ts; + #endif + + // fall back + struct timeval tval = GetTimeOfDay(false); + ts.tv_sec = tval.tv_sec; + ts.tv_nsec = tval.tv_usec * NSEC_PER_USEC; + return ts; +} + /////////////////////////////////////////////////////////////////////////////// DayTime_t GetDayTime ( bool localtime ) @@ -2346,50 +2696,114 @@ u_nsec_t GetTimeNSec ( bool localtime ) return (u_nsec_t)(ts.tv_sec) * NSEC_PER_SEC + ts.tv_nsec; } +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +CurrentTime_t current_time = {0}; + +CurrentTime_t GetCurrentTime ( bool localtime ) +{ + struct timeval tval = GetTimeOfDay(localtime); + + CurrentTime_t ct; + ct.sec = tval.tv_sec; + ct.usec = tval.tv_sec * USEC_PER_SEC + tval.tv_usec; + ct.msec = ct.usec / 1000; + return ct; +} + // /////////////////////////////////////////////////////////////////////////////// /////////////// timer /////////////// /////////////////////////////////////////////////////////////////////////////// -static time_t time_base = 0; +u_sec_t GetTimerSec() +{ + struct timespec ts = GetClockTimer(); + return ts.tv_sec; +} /////////////////////////////////////////////////////////////////////////////// u_msec_t GetTimerMSec() { - struct timeval tv; - gettimeofday(&tv,NULL); - if (!time_base) - time_base = tv.tv_sec; - - return (u_msec_t)( tv.tv_sec - time_base ) * MSEC_PER_SEC - + tv.tv_usec/USEC_PER_MSEC; + struct timespec ts = GetClockTimer(); + return ts.tv_sec * MSEC_PER_SEC + ts.tv_nsec / NSEC_PER_MSEC; } /////////////////////////////////////////////////////////////////////////////// u_usec_t GetTimerUSec() { - struct timeval tv; - gettimeofday(&tv,NULL); - if (!time_base) - time_base = tv.tv_sec; + struct timespec ts = GetClockTimer(); + return ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC; +} - return (u_usec_t)( tv.tv_sec - time_base ) * USEC_PER_SEC + tv.tv_usec; +/////////////////////////////////////////////////////////////////////////////// + +u_nsec_t GetTimerNSec() +{ + struct timespec ts = GetClockTimer(); + return ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec; } /////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintRefTime +( -u_usec_t GetTimerNSec() + u_sec_t tim, // seconds since epoch; 0 is replaced by time() + u_sec_t *ref_tim // NULL or ref_tim; if *ref_tim==0: write current time + // it is used to select format +) { - struct timespec ts = GetClockTime(false); - if (!time_base) - time_base = ts.tv_sec; + u_sec_t ref; + if (!ref_tim) + ref = GetTimeSec(false); + else + { + if (!*ref_tim) + *ref_tim = GetTimeSec(false); + ref = *ref_tim; + } - return (u_usec_t)( ts.tv_sec - time_base ) * NSEC_PER_SEC + ts.tv_nsec; + ccp format = tim >= ref - 10*SEC_PER_HOUR && tim <= ref + 10*SEC_PER_HOUR + ? " %k:%M:%S" + : tim >= ref - 12*SEC_PER_DAY && tim <= ref + 10*SEC_PER_DAY + ? " %e. %k:%M" + : "%F"; + return PrintTimeByFormat(format,tim); +} + +//----------------------------------------------------------------------------- + +ccp PrintRefTimeUTC +( + + u_sec_t tim, // seconds since epoch; 0 is replaced by time() + u_sec_t *ref_tim // NULL or ref_tim; if *ref_tim==0: write current time + // it is used to select format +) +{ + u_sec_t ref; + if (!ref_tim) + ref = GetTimeSec(false); + else + { + if (!*ref_tim) + *ref_tim = GetTimeSec(false); + ref = *ref_tim; + } + + ccp format = tim >= ref - 10*SEC_PER_HOUR && tim <= ref + 10*SEC_PER_HOUR + ? " %k:%M:%S" + : tim >= ref - 12*SEC_PER_DAY && tim <= ref + 10*SEC_PER_DAY + ? " %e. %k:%M" + : "%F"; + return PrintTimeByFormatUTC(format,tim); } -/////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// ccp PrintTimeByFormat @@ -2397,14 +2811,12 @@ ccp PrintTimeByFormat // returns temporary buffer by GetCircBuf(); ccp format, // format string for strftime() - time_t tim // seconds since epoch; 0 is replaced by time() + u_sec_t tim // seconds since epoch; 0 is replaced by time() ) { - if (!tim) - tim = time(0); - char buf[100]; - struct tm *tm = localtime(&tim); + const time_t reftime = tim ? tim : time(0); + struct tm *tm = localtime(&reftime); const uint len = strftime(buf,sizeof(buf),format,tm); return CopyCircBuf(buf,len+1); } @@ -2416,14 +2828,12 @@ ccp PrintTimeByFormatUTC // returns temporary buffer by GetCircBuf(); ccp format, // format string for strftime() - time_t tim // seconds since epoch; 0 is replaced by time() + u_sec_t tim // seconds since epoch; 0 is replaced by time() ) { - if (!tim) - tim = time(0); - char buf[100]; - struct tm *tm = gmtime(&tim); + const time_t reftime = tim ? tim : time(0); + struct tm *tm = gmtime(&reftime); const uint len = strftime(buf,sizeof(buf),format,tm); return CopyCircBuf(buf,len+1); } @@ -2484,6 +2894,90 @@ ccp PrintNSecByFormatUTC return CopyCircBuf(buf,len+1); } +//----------------------------------------------------------------------------- + +ccp PrintNTimeByFormat +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + u_nsec_t ntime +) +{ + return PrintNSecByFormat(format,ntime/NSEC_PER_SEC,ntime%NSEC_PER_SEC); +} + +//----------------------------------------------------------------------------- + +ccp PrintNTimeByFormatUTC +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + u_nsec_t ntime +) +{ + return PrintNSecByFormatUTC(format,ntime/NSEC_PER_SEC,ntime%NSEC_PER_SEC); +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintUTimeByFormat +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + u_usec_t utime +) +{ + return PrintNSecByFormat(format,utime/USEC_PER_SEC,utime%USEC_PER_SEC*NSEC_PER_USEC); +} + +//----------------------------------------------------------------------------- + +ccp PrintUTimeByFormatUTC +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + u_usec_t utime +) +{ + return PrintNSecByFormatUTC(format,utime/USEC_PER_SEC,utime%USEC_PER_SEC*NSEC_PER_USEC); +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintMTimeByFormat +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + u_msec_t mtime +) +{ + return PrintNSecByFormat(format,mtime/MSEC_PER_SEC,mtime%MSEC_PER_SEC*NSEC_PER_MSEC); +} + +//----------------------------------------------------------------------------- + +ccp PrintMTimeByFormatUTC +( + // returns temporary buffer by GetCircBuf(); + + ccp format, // format string for strftime() + // 1-9 '@' in row replaced by digits of 'usec' + u_msec_t mtime +) +{ + return PrintNSecByFormatUTC(format,mtime/MSEC_PER_SEC,mtime%MSEC_PER_SEC*NSEC_PER_MSEC); +} + /////////////////////////////////////////////////////////////////////////////// ccp PrintTimevalByFormat @@ -2811,13 +3305,16 @@ ccp PrintTimer3 u64 sec, // seconds to print int usec, // 0...999999: usec fraction, // otherwise suppress ms/us output - bool aligned // true: print aligned 3 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH ) { if (!buf) buf = GetCircBuf( buf_size = 4 ); + const bool aligned = mode & DC_SFORM_ALIGN; - if ( !sec && usec >= 0 && usec <= 999999 ) + if ( !sec && !usec && mode & DC_SFORM_DASH ) + StringCopyS(buf,buf_size," -"); + else if ( !sec && usec >= 0 && usec <= 999999 ) { if (!usec) StringCopyS(buf,buf_size,aligned?" 0":"0"); @@ -2868,13 +3365,16 @@ ccp PrintTimer4 u64 sec, // seconds to print int usec, // 0...999999: usec fraction, // otherwise suppress ms/us output - bool aligned // true: print aligned 4 character output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH ) { if (!buf) buf = GetCircBuf( buf_size = 5 ); + const bool aligned = mode & DC_SFORM_ALIGN; - if ( sec < 10 && usec >= 0 && usec <= 999999 ) + if ( !sec && !usec && mode & DC_SFORM_DASH ) + StringCopyS(buf,buf_size," -"); + else if ( sec < 10 && usec >= 0 && usec <= 999999 ) { if (sec) snprintf(buf,buf_size,"%llu.%us",sec,usec/100000); @@ -2915,38 +3415,53 @@ ccp PrintTimer4 /////////////////////////////////////////////////////////////////////////////// -// [[nsec]] -> PrintTimer6U(), PrintTimer6N() - -ccp PrintTimer6 +ccp PrintTimer6N ( char * buf, // result buffer (>6 bytes) // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL u64 sec, // seconds to print - int usec, // 0...999999: usec fraction, - // otherwise suppress ms/us output - bool aligned // true: print aligned 6 character output + int nsec, // 0...999999999: nsec fraction, + // otherwise suppress ms/us/ns output + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_CENTER | DC_SFORM_DASH ) { + if ( mode & DC_SFORM_CENTER ) + { + char buf2[20]; + PrintTimer6N(buf2,sizeof(buf2),sec,nsec,mode&~(DC_SFORM_CENTER|DC_SFORM_ALIGN)); + return StringCenterS(buf,buf_size,buf2,6); + } + + char temp[20]; if (!buf) - buf = GetCircBuf( buf_size = 7 ); + { + buf = temp; + buf_size = sizeof(temp); + } - if (aligned) + const bool nsec_valid = nsec >= 0 && nsec <= 999999999; + + if ( mode & DC_SFORM_ALIGN ) { - if ( sec < 10 && usec >= 0 && usec <= 999999 ) + if ( !sec && !nsec && mode & DC_SFORM_DASH ) + StringCopyS(buf,buf_size," -"); + else if ( sec < 10 && nsec_valid ) { - usec += 1000000 * sec; - if (!usec) + u_nsec_t sum = sec *NSEC_PER_SEC + nsec; + if (!sum) StringCopyS(buf,buf_size," 0"); - else if ( usec < 10000 ) - snprintf(buf,buf_size,"%4uus",usec); + else if ( sum < 10000 ) + snprintf(buf,buf_size,"%4lluns",sum); + else if ( sum < 10000000 ) + snprintf(buf,buf_size,"%4lluus",sum/1000); else - snprintf(buf,buf_size,"%4ums",usec/1000); + snprintf(buf,buf_size,"%4llums",sum/1000000); } else if ( sec < 100 ) { - if ( usec >= 0 && usec <= 999999 ) - snprintf(buf,buf_size,"%2llu.%02us",sec,usec/10000); + if (nsec_valid ) + snprintf(buf,buf_size,"%2llu.%02us",sec,nsec/10000000); else snprintf(buf,buf_size,"%5llus",sec); } @@ -2975,21 +3490,25 @@ ccp PrintTimer6 } else { - if ( sec < 10 ) + if ( !sec && !nsec && mode & DC_SFORM_DASH ) + StringCopyS(buf,buf_size,"-"); + else if ( sec < 10 && nsec_valid ) { - usec += 1000000 * sec; - if (!usec) + u_nsec_t sum = sec *NSEC_PER_SEC + nsec; + if (!sum) StringCopyS(buf,buf_size,"0"); - else if ( usec < 10000 ) - snprintf(buf,buf_size,"%uus",usec); + else if ( sum < 10000 ) + snprintf(buf,buf_size,"%lluns",sum); + else if ( sum < 10000000 ) + snprintf(buf,buf_size,"%lluus",sum/1000); else - snprintf(buf,buf_size,"%ums",usec/1000); + snprintf(buf,buf_size,"%llums",sum/1000000); } else if ( sec < 100 ) { - if ( usec >= 0 && usec <= 999999 ) + if ( nsec_valid ) { - const uint val2 = usec/10000; + const uint val2 = nsec/10000000; if (val2) snprintf(buf,buf_size,"%llu.%02us",sec,val2); else @@ -3052,7 +3571,7 @@ ccp PrintTimer6 } } - return buf; + return buf == temp ? CopyCircBuf0(buf,strlen(buf)) : buf; } /////////////////////////////////////////////////////////////////////////////// @@ -3065,14 +3584,19 @@ ccp PrintTimerUSec4s // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL s_usec_t usec, // microseconds to print - sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH ) { if ( !buf || buf_size < 2 ) buf = GetCircBuf( buf_size = 5 ); if (!usec) - StringCopyS(buf,buf_size, mode & DC_SFORM_ALIGN ? " 0" : "0" ); + { + if ( mode & DC_SFORM_DASH ) + StringCopyS(buf,buf_size, mode & DC_SFORM_ALIGN ? " -" : "-" ); + else + StringCopyS(buf,buf_size, mode & DC_SFORM_ALIGN ? " 0" : "0" ); + } else { char sign; @@ -3084,7 +3608,7 @@ ccp PrintTimerUSec4s else sign = mode & DC_SFORM_PLUS ? '+' : ' '; - PrintTimerUSec3(buf+1,buf_size-1,usec,mode&DC_SFORM_ALIGN); + PrintTimerUSec3(buf+1,buf_size-1,usec,mode&~DC_SFORM_PLUS); *buf = ' '; char *ptr = buf+1; @@ -3097,22 +3621,25 @@ ccp PrintTimerUSec4s /////////////////////////////////////////////////////////////////////////////// -// [[nsec]] -> PrintTimer7Us(), PrintTimer7Ns() - ccp PrintTimerUSec7s ( char * buf, // result buffer (>7 bytes) // If NULL, a local circulary static buffer is used size_t buf_size, // size of 'buf', ignored if buf==NULL s_usec_t usec, // microseconds to print - sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH ) { if ( !buf || buf_size < 2 ) buf = GetCircBuf( buf_size = 8 ); if (!usec) - StringCopyS(buf,buf_size, mode & DC_SFORM_ALIGN ? " 0" : "0" ); + { + if ( mode & DC_SFORM_DASH ) + StringCopyS(buf,buf_size, mode & DC_SFORM_ALIGN ? " -" : "-" ); + else + StringCopyS(buf,buf_size, mode & DC_SFORM_ALIGN ? " 0" : "0" ); + } else { char sign; @@ -3135,6 +3662,123 @@ ccp PrintTimerUSec7s return buf; } +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintTimerNSec7s +( + char * buf, // result buffer (>7 bytes) + // If NULL, a local circulary static buffer is used + size_t buf_size, // size of 'buf', ignored if buf==NULL + s_nsec_t nsec, // nansoseconds to print + sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH +) +{ + if ( !buf || buf_size < 2 ) + buf = GetCircBuf( buf_size = 8 ); + + if (!nsec) + { + if ( mode & DC_SFORM_DASH ) + StringCopyS(buf,buf_size, mode & DC_SFORM_ALIGN ? " -" : "-" ); + else + StringCopyS(buf,buf_size, mode & DC_SFORM_ALIGN ? " 0" : "0" ); + } + else + { + char sign; + if ( nsec < 0 ) + { + nsec = -nsec; + sign = '-'; + } + else + sign = mode & DC_SFORM_PLUS ? '+' : ' '; + + PrintTimerNSec6(buf+1,buf_size-1, nsec, mode & DC_SFORM_ALIGN ); + *buf = ' '; + + char *ptr = buf+1; + while ( *ptr == ' ' ) + ptr++; + ptr[-1] = sign; + } + return buf; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintAge3Sec +( + u_sec_t now, // NULL or current time by GetTimeSec(false) + u_sec_t time // time to print +) +{ + if (!time) + return " -"; + + if (!now) + now = GetTimeSec(false); + + now -= time; + return now < 0 ? " +" : PrintTimer3(0,0,now,-1,DC_SFORM_ALIGN); +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintAge4Sec +( + u_sec_t now, // NULL or current time by GetTimeSec(false) + u_sec_t time // time to print +) +{ + if (!time) + return " -"; + + if (!now) + now = GetTimeSec(false); + + now -= time; + return now < 0 + ? PrintTimerSec4s(0,0,now,DC_SFORM_ALIGN) + : PrintTimer4(0,0,now,-1,DC_SFORM_ALIGN); +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintAge6Sec +( + u_sec_t now, // NULL or current time by GetTimeSec(false) + u_sec_t time // time to print +) +{ + if (!time) + return " -"; + + if (!now) + now = GetTimeSec(false); + + now -= time; + return now < 0 ? " +" : PrintTimerSec6(0,0,now,DC_SFORM_ALIGN); +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintAge7Sec +( + u_sec_t now, // NULL or current time by GetTimeSec(false) + u_sec_t time // time to print +) +{ + if (!time) + return " -"; + + if (!now) + now = GetTimeSec(false); + + return PrintTimerSec7s(0,0,now-time,DC_SFORM_ALIGN); +} + // /////////////////////////////////////////////////////////////////////////////// /////////////// scan date & time /////////////// @@ -3211,7 +3855,7 @@ char * ScanIntervalUSec { struct timespec ts; char *res = ScanIntervalTS(&ts,source); - + if (res_usec) *res_usec = ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC; return res; @@ -3227,7 +3871,7 @@ char * ScanIntervalNSec { struct timespec ts; char *res = ScanIntervalTS(&ts,source); - + if (res_nsec) *res_nsec = ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec; return res; @@ -3657,6 +4301,1821 @@ time_t year2time ( int year ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// usage counter /////////////// +/////////////////////////////////////////////////////////////////////////////// + +int usage_count_enabled = 0; + +void EnableUsageCount() +{ + usage_count_enabled++; + UpdateUsageByMgr(0); +} + +/////////////////////////////////////////////////////////////////////////////// + +const SaveRestoreTab_t SRT_UsageCount[] = +{ + #undef SRT_NAME + #define SRT_NAME UsageCount_t + + DEF_SRT_UINT( par.enabled, "enabled" ), + DEF_SRT_UINT( par.used, "used" ), + DEF_SRT_ARRAY_A(entry), + DEF_SRT_UINT( entry[0].count, "count" ), + DEF_SRT_UINT( entry[0].elapsed_nsec, "elapsed" ), + DEF_SRT_UINT( entry[0].time_sec, "time" ), + DEF_SRT_FLOAT( entry[0].top1s, "top1s" ), + DEF_SRT_FLOAT( entry[0].top5s, "top5s" ), + DEF_SRT_ARRAY_END(), + + DEF_SRT_SEPARATOR(), + DEF_SRT_TERM() +}; + +/////////////////////////////////////////////////////////////////////////////// + +void ClearUsageCount ( UsageCount_t *uc, int count ) +{ + if (!uc) + return; + + uint index = CheckIndex1(uc->par.used,count); + if ( index >= uc->par.used - 1 ) + return; + + uc->par.used = index; + if (!index) + { + const bool enabled = uc->par.enabled; + memset( uc, 0, sizeof(*uc) ); + uc->par.enabled = enabled; + } + else + { + UsageCountEntry_t *e = uc->entry + index; + memset( e, 0, PTR_DISTANCE((u8*)uc->entry+sizeof(uc->entry),e) ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// [[UpdateUsageCount]] + +void UpdateUsageCount ( UsageCount_t *uc, u_nsec_t timer_nsec ) +{ + if (!uc) + return; + + if ( !uc->par.enabled || usage_count_enabled <= 0 ) + { + uc->ref.elapsed_nsec = 0; + uc->ref.count = 0; + uc->par.dirty = false; + return; + } + + if ( !uc->par.is_active ) + { + if ( !uc->par.used && !uc->ref.count ) + return; + uc->par.is_active = true; + } + + UsageCountEntry_t cur = {0}; + cur.elapsed_nsec = timer_nsec ? timer_nsec : GetTimerNSec(); + + uc->par.update_nsec = uc->ref.elapsed_nsec + NSEC_PER_SEC; + if ( cur.elapsed_nsec >= uc->par.update_nsec ) + { + // needed for the case that USAGE_COUNT_ENTRIES was reduced after restart! + if ( uc->par.used > USAGE_COUNT_ENTRIES ) + uc->par.used = USAGE_COUNT_ENTRIES; + + cur.time_sec = GetTimeSec(false); + + if (uc->ref.elapsed_nsec) + { + //--- find index and move data + + int index; + if ( uc->par.used < USAGE_COUNT_FIRST_ADD ) + index = uc->par.used + 1; + else + { + u_nsec_t min = USAGE_COUNT_NEXT_MIN(NSEC_PER_SEC); + for ( index = USAGE_COUNT_FIRST_ADD; + index < uc->par.used; + index++, min = USAGE_COUNT_NEXT_MIN(min) + ) + { + UsageCountEntry_t *e = uc->entry + index; + if ( e->elapsed_nsec < min ) + { + AddUsageCountEntry(e,e-1); + index--; + break; + } + } + if ( ++index > USAGE_COUNT_ENTRIES ) + index = USAGE_COUNT_ENTRIES; + } + + if ( index > 1 ) + memmove( uc->entry+1, uc->entry, (index-1) * sizeof(*uc->entry) ); + + if ( uc->par.used < index ) + uc->par.used = index; + + + //--- update first entry + + UsageCountEntry_t *e = uc->entry; + *e = uc->ref; + e->elapsed_nsec = cur.elapsed_nsec - e->elapsed_nsec; + + + //--- update top value (1s) + + if (e->elapsed_nsec) + e->top1s = (double)( NSEC_PER_SEC * e->count ) / e->elapsed_nsec; + + + //--- update top value (5s) + + u_nsec_t elapsed5 = 0, count5 = 0; + UsageCountEntry_t *e5 = uc->entry; + for ( int i = 0; i < uc->par.used && elapsed5 < 5*NSEC_PER_SEC; i++, e5++ ) + { + elapsed5 += e5->elapsed_nsec; + count5 += e5->count; + } + + if (elapsed5) + { + if ( count5 == e->count ) + elapsed5 = 5*NSEC_PER_SEC; + e->top5s = (double)( NSEC_PER_SEC * count5 ) / elapsed5; + } + } + + uc->ref = cur; + uc->par.update_nsec = uc->ref.elapsed_nsec + NSEC_PER_SEC; + } + + uc->par.force_update_nsec = uc->ref.elapsed_nsec + NSEC_PER_MIN; + uc->par.dirty = uc->ref.count > 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +void UpdateUsageCountIncrement ( UsageCount_t *uc ) +{ + DASSERT(uc); + uc->par.is_active = true; + UpdateUsageCount(uc,0); + if ( usage_count_enabled > 0 ) + { + uc->ref.count++; + uc->par.dirty = true; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void UpdateUsageCountAdd ( UsageCount_t *uc, int add ) +{ + DASSERT(uc); + if ( add > 0 ) + { + uc->par.is_active = true; + UpdateUsageCount(uc,0); + if ( usage_count_enabled > 0 ) + { + uc->ref.count += add; + uc->par.dirty = true; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void AddUsageCountEntry ( UsageCountEntry_t *dest, const UsageCountEntry_t *add ) +{ + DASSERT(dest); + DASSERT(add); + dest->count += add->count; + dest->elapsed_nsec += add->elapsed_nsec; + + if ( !dest->time_sec || dest->time_sec > add->time_sec ) + dest->time_sec = add->time_sec; + + if ( dest->top1s < add->top1s ) + dest->top1s = add->top1s; + if ( dest->top5s < add->top5s ) + dest->top5s = add->top5s; +} + +/////////////////////////////////////////////////////////////////////////////// + +UsageCountEntry_t GetUsageCount ( const UsageCount_t *uc, s_nsec_t nsec ) +{ + DASSERT(uc); + UsageCountEntry_t res = {0}; + const UsageCountEntry_t *e = uc->entry; + for ( int i = 0; i < uc->par.used && nsec > 0; i++, e++ ) + { + nsec -= e->elapsed_nsec; + AddUsageCountEntry(&res,e); + } + return res; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +PointerList_t usage_count_mgr = { .used = 0, .grow = 10 }; + +/////////////////////////////////////////////////////////////////////////////// + +u_nsec_t MaintainUsageByMgr ( u_nsec_t now_nsec ) +{ + // returns delta time to next maintenance based on GetTimerNSec() + + if (!now_nsec) + now_nsec = GetTimerNSec(); + u_nsec_t next_nsec = now_nsec + NSEC_PER_MIN; + + for ( int i = 0; i < usage_count_mgr.used; i++ ) + { + const UsageCtrl_t *uci = usage_count_mgr.list[i]; + if (!uci) + continue; + + const UsageParam_t *par = GetUsageParam(uci); + if (par) + { + if ( par->dirty && par->update_nsec && par->update_nsec <= now_nsec + || par->force_update_nsec && par->force_update_nsec <= now_nsec ) + { + UpdateByUCI(uci,now_nsec); + } + if ( par->dirty && par->update_nsec && next_nsec > par->update_nsec ) + next_nsec = par->update_nsec; + } + } + + return next_nsec; +} + +/////////////////////////////////////////////////////////////////////////////// + +void UpdateByUCI ( const UsageCtrl_t *uci, u_nsec_t now_nsec ) +{ + if (uci) + { + if (uci->update_func) + uci->update_func(uci,now_nsec); + else if (uci->uc) + UpdateUsageCount(uci->uc,now_nsec); + else if (uci->ud) + UpdateUsageDuration(uci->ud,now_nsec); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void UpdateUsageByMgr ( u_nsec_t timer_nsec ) +{ + if (!timer_nsec) + timer_nsec = GetTimerNSec(); + for ( int i = 0; i < usage_count_mgr.used; i++ ) + { + const UsageCtrl_t *uci = usage_count_mgr.list[i]; + if (uci) + { + if (uci->uc) + UpdateUsageCount(uci->uc,timer_nsec); + else if (uci->ud) + UpdateUsageDuration(uci->ud,timer_nsec); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +#if 0 + static int sort_usage_count ( const UsageCtrl_t *a, const UsageCtrl_t *b ) + { + DASSERT( a && b ); + return strcmp(a->key1,b->key1); + } +#endif + +//----------------------------------------------------------------------------- + +void AddToUsageMgr ( const UsageCtrl_t *uci ) +{ + if ( !uci || !uci->key1 ) + return; + + // no duplicates! + for ( int i = 0; i < usage_count_mgr.used; i++ ) + { + const UsageCtrl_t *uci2 = usage_count_mgr.list[i]; + if ( uci2 && ( uci2->uc && uci2->uc == uci->uc || uci2->ud && uci2->ud == uci->ud )) + return; + } + + AddToPointerMgr(&usage_count_mgr,uci); + + #if 0 + qsort( usage_count_mgr.list, usage_count_mgr.used, + sizeof(*usage_count_mgr.list), (qsort_func)sort_usage_count ); + #endif +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +void SaveCurrentStateByUsageCountMgr ( FILE *f, uint fw_name ) +{ + DASSERT(f); + const u_nsec_t timer_nsec = GetTimerNSec(); + void **ucip = usage_count_mgr.list; + for ( int i = 0; i < usage_count_mgr.used; i++, ucip++ ) + { + UsageCtrl_t *uci = *ucip; + if (uci) + { + UpdateUsageCount(uci->uc,timer_nsec); + if (uci->srt_prefix) + { + if (uci->uc) + SaveCurrentStateByTable(f,uci->uc,SRT_UsageCount,uci->srt_prefix,fw_name); + else if (uci->ud) + SaveCurrentStateByTable(f,uci->ud,SRT_UsageDuration,uci->srt_prefix,fw_name); + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void RestoreStateByUsageCountMgr ( RestoreState_t *rs ) +{ + DASSERT(rs); + void **ucip = usage_count_mgr.list; + for ( int i = 0; i < usage_count_mgr.used; i++, ucip++ ) + { + UsageCtrl_t *uci = *ucip; + if (uci) + { + if (uci->uc) + { + UsageCount_t *uc = uci->uc; + if (uci->srt_load) + RestoreStateByTable(rs,uc,SRT_UsageCount,uci->srt_load); + if (uci->srt_prefix) + RestoreStateByTable(rs,uc,SRT_UsageCount,uci->srt_prefix); + + // needed for the case that USAGE_COUNT_ENTRIES was reduced after restart! + if ( uc->par.used > USAGE_COUNT_ENTRIES ) + uc->par.used = USAGE_COUNT_ENTRIES; + } + else if (uci->ud) + { + UsageDuration_t *ud = uci->ud; + if (uci->srt_load) + RestoreStateByTable(rs,ud,SRT_UsageDuration,uci->srt_load); + if (uci->srt_prefix) + RestoreStateByTable(rs,ud,SRT_UsageDuration,uci->srt_prefix); + + // needed for the case that USAGE_COUNT_ENTRIES was reduced after restart! + if ( ud->par.used > USAGE_COUNT_ENTRIES ) + ud->par.used = USAGE_COUNT_ENTRIES; + } + } + } +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// wait counter /////////////// +/////////////////////////////////////////////////////////////////////////////// + +const SaveRestoreTab_t SRT_UsageDuration[] = +{ + #undef SRT_NAME + #define SRT_NAME UsageDuration_t + + DEF_SRT_UINT( par.enabled, "enabled" ), + DEF_SRT_UINT( par.used, "used" ), + DEF_SRT_ARRAY_A(entry), + DEF_SRT_UINT( entry[0].elapsed_nsec, "elapsed" ), + DEF_SRT_UINT( entry[0].total_nsec, "total" ), + DEF_SRT_UINT( entry[0].top_nsec, "top" ), + DEF_SRT_UINT( entry[0].count, "count" ), + DEF_SRT_UINT( entry[0].time_sec, "time" ), + DEF_SRT_FLOAT( entry[0].top_cnt_1s, "top-c1" ), + DEF_SRT_FLOAT( entry[0].top_cnt_5s, "top-c5" ), + DEF_SRT_ARRAY_END(), + + DEF_SRT_SEPARATOR(), + DEF_SRT_TERM() +}; + +/////////////////////////////////////////////////////////////////////////////// + +// n_rec<0: clear from end, n_rec>=0: clear from index +void ClearUsageDuration ( UsageDuration_t *ud, int count ) +{ + if (!ud) + return; + + uint index = CheckIndex1(ud->par.used,count); + if ( index >= ud->par.used - 1 ) + return; + + ud->par.used = index; + if (!index) + { + const bool enabled = ud->par.enabled; + memset( ud, 0, sizeof(*ud) ); + ud->par.enabled = enabled; + } + else + { + UsageDurationEntry_t *e = ud->entry + index; + memset( e, 0, PTR_DISTANCE((u8*)ud->entry+sizeof(ud->entry),e) ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// [[UpdateUsageDuration]] + +// TIMER_NSEC: 0 or GetTimerNSec(), but not GetTime*() +void UpdateUsageDuration ( UsageDuration_t *ud, u_nsec_t timer_nsec ) +{ + if (!ud) + return; + + if ( !ud->par.enabled || usage_count_enabled <= 0 ) + { + ud->ref.elapsed_nsec = 0; + ud->ref.count = 0; + ud->par.dirty = false; + return; + } + + if ( !ud->par.is_active ) + { + if ( !ud->par.used && !ud->ref.count ) + return; + ud->par.is_active = true; + } + + UsageDurationEntry_t cur = {0}; + cur.elapsed_nsec = timer_nsec ? timer_nsec : GetTimerNSec(); + + ud->par.update_nsec = ud->ref.elapsed_nsec + NSEC_PER_SEC; + if ( cur.elapsed_nsec >= ud->par.update_nsec ) + { + // needed for the case that USAGE_COUNT_ENTRIES was reduced after restart! + if ( ud->par.used > USAGE_COUNT_ENTRIES ) + ud->par.used = USAGE_COUNT_ENTRIES; + + cur.time_sec = GetTimeSec(false); + + if (ud->ref.elapsed_nsec) + { + //--- find index and move data + + int index; + if ( ud->par.used < USAGE_COUNT_FIRST_ADD ) + index = ud->par.used + 1; + else + { + u_nsec_t min = USAGE_COUNT_NEXT_MIN(NSEC_PER_SEC); + for ( index = USAGE_COUNT_FIRST_ADD; + index < ud->par.used; + index++, min = USAGE_COUNT_NEXT_MIN(min) + ) + { + UsageDurationEntry_t *e = ud->entry + index; + if ( e->elapsed_nsec < min ) + { + AddUsageDurationEntry(e,e-1); + index--; + break; + } + } + if ( ++index > USAGE_COUNT_ENTRIES ) + index = USAGE_COUNT_ENTRIES; + } + + if ( index > 1 ) + memmove( ud->entry+1, ud->entry, (index-1) * sizeof(*ud->entry) ); + + if ( ud->par.used < index ) + ud->par.used = index; + + + //--- update first entry + + UsageDurationEntry_t *e = ud->entry; + *e = ud->ref; + e->elapsed_nsec = cur.elapsed_nsec - e->elapsed_nsec; + + + //--- update top value (1s) + + if (e->elapsed_nsec) + e->top_cnt_1s = (double)( NSEC_PER_SEC * e->count ) / e->elapsed_nsec; + + + //--- update top value (5s) + + u_nsec_t elapsed5 = 0, count5 = 0; + UsageDurationEntry_t *e5 = ud->entry; + for ( int i = 0; i < ud->par.used && elapsed5 < 5*NSEC_PER_SEC; i++, e5++ ) + { + elapsed5 += e5->elapsed_nsec; + count5 += e5->count; + } + + if (elapsed5) + { + if ( count5 == e->count ) + elapsed5 = 5*NSEC_PER_SEC; + e->top_cnt_5s = (double)( NSEC_PER_SEC * count5 ) / elapsed5; + } + } + + ud->ref = cur; + ud->par.update_nsec = ud->ref.elapsed_nsec + NSEC_PER_SEC; + } + + ud->par.force_update_nsec = ud->ref.elapsed_nsec + NSEC_PER_MIN; + ud->par.dirty = ud->ref.count > 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +void UpdateUsageDurationAdd + ( UsageDuration_t *ud, int add, u_nsec_t wait_nsec, u_nsec_t top_nsec ) +{ + DASSERT(ud); + ud->par.is_active = true; + UpdateUsageDuration(ud,0); + + if ( add > 0 && usage_count_enabled > 0 ) + { + ud->par.dirty = true; + ud->ref.count += add; + ud->ref.total_nsec += wait_nsec; + if ( ud->ref.top_nsec < top_nsec ) + ud->ref.top_nsec = top_nsec; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void UpdateUsageDurationIncrement ( UsageDuration_t *ud, u_nsec_t wait_nsec ) +{ + DASSERT(ud); + ud->par.is_active = true; + UpdateUsageDuration(ud,0); + if ( usage_count_enabled > 0 ) + { + ud->par.dirty = true; + ud->ref.count++; + ud->ref.total_nsec += wait_nsec; + if ( ud->ref.top_nsec < wait_nsec ) + ud->ref.top_nsec = wait_nsec; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void UsageDurationIncrement ( UsageDuration_t *ud, u_nsec_t wait_nsec ) +{ + DASSERT(ud); + ud->par.is_active = true; + if ( usage_count_enabled > 0 ) + { + ud->par.dirty = true; + ud->ref.count++; + ud->ref.total_nsec += wait_nsec; + if ( ud->ref.top_nsec < wait_nsec ) + ud->ref.top_nsec = wait_nsec; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +UsageDurationEntry_t GetUsageDuration ( const UsageDuration_t *ud, s_nsec_t nsec ) +{ + DASSERT(ud); + UsageDurationEntry_t res = {0}; + const UsageDurationEntry_t *e = ud->entry; + for ( int i = 0; i < ud->par.used && nsec > 0; i++, e++ ) + { + nsec -= e->elapsed_nsec; + AddUsageDurationEntry(&res,e); + } + return res; +} + +/////////////////////////////////////////////////////////////////////////////// + +void AddUsageDurationEntry ( UsageDurationEntry_t *dest, const UsageDurationEntry_t *add ) +{ + DASSERT(dest); + DASSERT(add); + dest->count += add->count; + dest->elapsed_nsec += add->elapsed_nsec; + dest->total_nsec += add->total_nsec; + + if ( !dest->time_sec || dest->time_sec > add->time_sec ) + dest->time_sec = add->time_sec; + + if ( dest->top_nsec < add->top_nsec ) + dest->top_nsec = add->top_nsec; + + if ( dest->top_cnt_1s < add->top_cnt_1s ) + dest->top_cnt_1s = add->top_cnt_1s; + if ( dest->top_cnt_5s < add->top_cnt_5s ) + dest->top_cnt_5s = add->top_cnt_5s; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// list usage count/wait /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static ccp print_usage_count_val ( double val, const float *color_val ) +{ + if ( val <= 0 ) + return " -"; + + static const float color_val0[] = { 100, 200, 300, 500, 1000, 2000 }; + if (!color_val) + color_val = color_val0; + + if ( val > color_val[0] || val >= 9999.9994 ) + { + ccp col = val < color_val[2] + ? ( val < color_val[1] ? colout->mark : colout->info ) + : val < color_val[4] + ? ( val < color_val[3] ? colout->hint : colout->warn ) + : ( val < color_val[5] ? colout->err : colout->bad ); + + return val < 9999.9994 + ? PrintCircBuf("%s%8.3f%s",col,val,colout->reset) + : val < 999999.94 + ? PrintCircBuf("%s%8.1f%s",col,val,colout->reset) + : PrintCircBuf("%s%8.0f%s",col,val,colout->reset); + } + + char *res = PrintCircBuf("%8.3f",val); + if ( val < 1.0 && res[3] == '0' ) + res[3] = ' '; + return res; +} + +//----------------------------------------------------------------------------- + +static ccp print_usage_count + ( u32 n_wait, u_nsec_t elapsed_nsec, const float *color_val ) +{ + return elapsed_nsec + ? print_usage_count_val( (double)( NSEC_PER_SEC * n_wait ) / elapsed_nsec, color_val ) + : " ×"; +} + +//----------------------------------------------------------------------------- + +static ccp print_usage_dur_val ( u_nsec_t dur, const u_nsec_t *color_dur ) +{ + if (!dur) + return " -"; + + ccp res = PrintTimerNSec6(0,0,dur,DC_SFORM_ALIGN); + + static const u_nsec_t color_dur0[] = + { + 10 * NSEC_PER_MSEC, // mark + 50 * NSEC_PER_MSEC, // info + 200 * NSEC_PER_MSEC, // hint + NSEC_PER_SEC, // warn + 8 * NSEC_PER_SEC, // err + NSEC_PER_MIN, // bad + }; + if (!color_dur) + color_dur = color_dur0; + + if ( dur > color_dur[0] ) + { + ccp col = dur < color_dur[2] + ? ( dur < color_dur[1] ? colout->mark : colout->info ) + : dur < color_dur[4] + ? ( dur < color_dur[3] ? colout->hint : colout->warn ) + : ( dur < color_dur[5] ? colout->err : colout->bad ); + + return PrintCircBuf("%s%s%s",col,res,colout->reset); + } + + return res; +} + +//----------------------------------------------------------------------------- + +static ccp print_usage_dur + ( u_nsec_t total, u64 count, const u_nsec_t *color_dur ) +{ + return count + ? print_usage_dur_val( total/count, color_dur ) + : " -"; +} + +// +/////////////////////////////////////////////////////////////////////////////// + +void ListUsageCount +( + PrintMode_t *p_pm, // NULL or print mode + const UsageCtrl_t *uci, // NULL or object to list + int print_mode, // see LUC_PM_* + s_nsec_t limit_nsec // >0: limit output until # is reached +) +{ + if (!uci) + return; + + if (uci->list_func) + { + uci->list_func(p_pm,uci,print_mode,limit_nsec); + return; + } + + if (!uci->uc) + { + if (uci->ud) + ListUsageDuration(p_pm,uci,print_mode,limit_nsec); + return; + } + + //--- setup + + PrintMode_t pm = {0}; + if (p_pm) + pm = *p_pm; + SetupPrintMode(&pm); + + if ( limit_nsec <= 0 ) + limit_nsec = S_NSEC_MAX; + + UsageCount_t *uc = uci->uc; + fprintf(pm.fout,"%s%s%*s %s%s (%u record%s%s%s)%s%s", + pm.compact ? "" : pm.eol, pm.prefix, pm.indent, "", + pm.cout->caption, uci->title, + uc->par.used, uc->par.used == 1 ? "" : "s", + usage_count_enabled > 0 ? "" : ", global disabled", + uc->par.enabled ? "" : ", disabled", + pm.cout->reset, pm.eol ); + + if (!uc->par.used) + return; + + + //--- print table + + UsageCountEntry_t sum = {0}; + u_sec_t reftime = 0; + u_nsec_t min = USAGE_COUNT_NEXT_MIN(NSEC_PER_SEC); + + if ( print_mode == LUC_PM_SUMMARY ) + { + fprintf(pm.fout, + "%s%*s%s╔════════╦════════╤═════════╤══════════╦═══════════╤═══════════╗%s" + "%s%*s%s║ range ║ period │ counter │ count/s ║ top~1s /s │ top~5s /s ║%s" + "%s%*s%s╠════════╬════════╪═════════╪══════════╬═══════════╪═══════════╣%s%s" + ,pm.prefix ,pm.indent,"" ,colout->heading ,pm.eol + ,pm.prefix ,pm.indent,"" ,colout->heading ,pm.eol + ,pm.prefix ,pm.indent,"" ,colout->heading ,colout->reset ,pm.eol + ); + + const IntervalInfo_t *interval = interval_info; + const UsageCountEntry_t *e = uc->entry; + for ( int i = 0; i < uc->par.used; i++, e++ ) + { + AddUsageCountEntry(&sum,e); + bool is_last = false; + const bool is_limit = sum.elapsed_nsec >= limit_nsec; + if ( sum.elapsed_nsec < interval->nsec ) + { + is_last = i+1 == uc->par.used; + if ( !is_last && !is_limit ) + continue; + } + + ccp name; + if ( is_last || sum.elapsed_nsec < interval->nsec ) + name = "*"; + else + { + while ( sum.elapsed_nsec > interval->nsec ) + interval++; + name = interval[-1].name; + } + + fprintf(pm.fout, + "%s%*s%s║%s %-6.6s %s║%s %s %s│%s %s %s│%s %s %s║%s" + ,pm.prefix ,pm.indent,"" + ,colout->heading, colout->reset + ,name + ,colout->heading, colout->reset + ,PrintTimerNSec6(0,0,sum.elapsed_nsec,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,PrintNumberU7(0,0,sum.count,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,print_usage_count(sum.count,sum.elapsed_nsec,uci->color_val) + ,colout->heading, colout->reset + ); + + fprintf(pm.fout, + " %s %s│%s %s %s║%s" + ,print_usage_count_val(sum.top1s,uci->color_val) + ,colout->heading, colout->reset + ,print_usage_count_val(sum.top5s,uci->color_val) + ,colout->heading, colout->reset + ); + + if (pm.debug) + fprintf(pm.flog," %2u%s",i,pm.eol); + else + fputs(pm.eol,pm.fout); + + if ( is_limit || !interval->name ) + break; + } + + fprintf(pm.fout, + "%s ╚════════╩════════╧═════════╧══════════╩═══════════╧═══════════╝%s%s" + ,colout->heading ,colout->reset ,pm.eol ); + } + else + { + fprintf(pm.fout, + "%s%*s%s╔═══════════╦═════════════════════════════╦══════════╦══════════╦═════════════════════════════╗%s" + "%s%*s%s║ ║ Single Record ║ top 1s ║ top 5s ║ Summed Values ║%s" + "%s%*s%s║ real time ║ period │ counter │ count/s ║ count/s ║ count/s ║ period │ counter │ count/s ║%s" + "%s%*s%s╠═══════════╬════════╪═════════╪══════════╬══════════╬══════════╬════════╪═════════╪══════════╣%s%s" + ,pm.prefix ,pm.indent,"" ,colout->heading ,pm.eol + ,pm.prefix ,pm.indent,"" ,colout->heading ,pm.eol + ,pm.prefix ,pm.indent,"" ,colout->heading ,pm.eol + ,pm.prefix ,pm.indent,"" ,colout->heading ,colout->reset ,pm.eol + ); + + const IntervalInfo_t *interval = interval_info+1; + const UsageCountEntry_t *e = uc->entry; + #if TEST_USAGE_COUNT + for ( int i = 0; i <= uc->par.used && sum.elapsed_nsec < limit_nsec; i++, e++ ) + #else + for ( int i = 0; i < uc->par.used && sum.elapsed_nsec < limit_nsec; i++, e++ ) + #endif + { + AddUsageCountEntry(&sum,e); + if ( i > 0 && ( sum.elapsed_nsec >= interval->nsec || i == USAGE_COUNT_FIRST_ADD )) + { + fprintf(pm.fout, + "%s ╟───────────╫────────┼─────────┼──────────╫" + "──────────╫──────────╫" + "────────┼─────────┼──────────╢%s%s", + colout->heading, colout->reset, pm.eol ); + while ( sum.elapsed_nsec >= interval->nsec ) + interval++; + } + + fprintf(pm.fout, + "%s%*s%s║%s%s %s║%s %s %s│%s %s %s│%s %s %s║%s" + ,pm.prefix ,pm.indent,"" + ,colout->heading, colout->reset + ,PrintRefTime(e->time_sec,&reftime) + ,colout->heading, colout->reset + ,PrintTimerNSec6(0,0,e->elapsed_nsec,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,PrintNumberU7(0,0,e->count,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,print_usage_count(e->count,e->elapsed_nsec,uci->color_val) + ,colout->heading, colout->reset + ); + + fprintf(pm.fout, + " %s %s║%s %s %s║%s" + ,print_usage_count_val(e->top1s,uci->color_val) + ,colout->heading, colout->reset + ,print_usage_count_val(e->top5s,uci->color_val) + ,colout->heading, colout->reset + ); + + fprintf(pm.fout, + " %s %s│%s %s %s│%s %s %s║%s" + ,PrintTimerNSec6(0,0,sum.elapsed_nsec,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,PrintNumberU7(0,0,sum.count,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,print_usage_count(sum.count,sum.elapsed_nsec,uci->color_val) + ,colout->heading, colout->reset + ); + + if (pm.debug) + { + if ( pm.debug >= 2 && i >= USAGE_COUNT_FIRST_ADD ) + { + fprintf(pm.flog," %2u %s %s%4llu%%%s %s%5llu%%%s%s", + i, + PrintTimerNSec6(0,0,min,DC_SFORM_ALIGN|DC_SFORM_DASH), + e->elapsed_nsec < min ? "" + : e->elapsed_nsec < min*2 ? colout->hint : colout->warn, + 100 * e->elapsed_nsec / min, colout->reset, + sum.elapsed_nsec < min ? colout->info : "", + 100 * sum.elapsed_nsec / min, colout->reset, pm.eol ); + min = USAGE_COUNT_NEXT_MIN(min); + } + else + fprintf(pm.flog," %2u%s",i,pm.eol); + } + else + fputs(pm.eol,pm.fout); + } + + fprintf(pm.fout, + "%s ╚═══════════╩════════╧═════════╧══════════╩" + "══════════╩══════════╩" + "════════╧═════════╧══════════╝%s%s" + ,colout->heading ,colout->reset ,pm.eol ); + } +} + +// +/////////////////////////////////////////////////////////////////////////////// + +void ListUsageDuration +( + PrintMode_t *p_pm, // NULL or print mode + const UsageCtrl_t *uci, // NULL or object to list + int print_mode, // see LUC_PM_* + s_nsec_t limit_nsec // >0: limit output until # is reached +) +{ + if (!uci) + return; + + if (uci->list_func) + { + uci->list_func(p_pm,uci,print_mode,limit_nsec); + return; + } + + if (!uci->ud) + { + if (uci->uc) + ListUsageCount(p_pm,uci,print_mode,limit_nsec); + return; + } + + //--- setup + + PrintMode_t pm = {0}; + if (p_pm) + pm = *p_pm; + SetupPrintMode(&pm); + + if ( limit_nsec <= 0 ) + limit_nsec = S_NSEC_MAX; + + UsageDuration_t *ud = uci->ud; + fprintf(pm.fout,"%s%s%*s %s%s (%u record%s%s%s)%s%s", + pm.compact ? "" : pm.eol, pm.prefix, pm.indent, "", + pm.cout->caption, uci->title, + ud->par.used, ud->par.used == 1 ? "" : "s", + usage_count_enabled > 0 ? "" : ", global disabled", + ud->par.enabled ? "" : ", disabled", + pm.cout->reset, pm.eol ); + + if (!ud->par.used) + return; + + + //--- print table + + UsageDurationEntry_t sum = {0}; + u_sec_t reftime = 0; + u_nsec_t min = USAGE_COUNT_NEXT_MIN(NSEC_PER_SEC); + + if ( print_mode == LUC_PM_SUMMARY ) + { + printf( + "%s ╔════════╦═════════════════════════════════════╦═════════╤═════════╤════════╗%s" + "%s ║ ║ Summed Record ║ top 1s │ top 5s │ top ║%s" + "%s ║ range ║ period │ counter │ count/s │ Ø time ║ count/s │ count/s │ time ║%s" + "%s ╠════════╬════════╪═════════╪═════════╪════════╬═════════╪═════════╪════════╣%s%s" + ,colout->heading, pm.eol + ,colout->heading, pm.eol + ,colout->heading, pm.eol + ,colout->heading ,colout->reset, pm.eol + ); + + const IntervalInfo_t *interval = interval_info; + const UsageDurationEntry_t *e = ud->entry; + for ( int i = 0; i < ud->par.used; i++, e++ ) + { + AddUsageDurationEntry(&sum,e); + bool is_last = false; + const bool is_limit = sum.elapsed_nsec >= limit_nsec; + if ( sum.elapsed_nsec < interval->nsec ) + { + is_last = i+1 == ud->par.used; + if ( !is_last && !is_limit ) + continue; + } + + ccp name; + if ( is_last || sum.elapsed_nsec < interval->nsec ) + name = "*"; + else + { + while ( sum.elapsed_nsec > interval->nsec ) + interval++; + name = interval[-1].name; + } + + if ( i > 0 && ( sum.elapsed_nsec >= interval->nsec || i == USAGE_COUNT_FIRST_ADD )) + { + fprintf(pm.fout, + "%s ╟───────────╫────────┼─────────┼─────────┼────────╫" + "─────────┼────────╫─────────┼────────╫" + "────────┼─────────┼─────────┼────────╢%s%s", + colout->heading, colout->reset, pm.eol ); + while ( sum.elapsed_nsec >= interval->nsec ) + interval++; + } + + fprintf(pm.fout, + "%s%*s%s║%s %-6.6s %s║%s %s %s│%s %s %s│%s%s %s│%s %s %s║%s" + ,pm.prefix ,pm.indent,"" + ,colout->heading, colout->reset + ,name + ,colout->heading, colout->reset + ,PrintTimerNSec6(0,0,sum.elapsed_nsec,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,PrintNumberU7(0,0,sum.count,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,print_usage_count(sum.count,sum.elapsed_nsec,uci->color_val) + ,colout->heading, colout->reset + ,print_usage_dur(sum.total_nsec,sum.count,uci->color_dur) + ,colout->heading, colout->reset + ); + + fprintf(pm.fout, + "%s %s│%s%s %s│%s %s %s║%s" + ,print_usage_count_val(sum.top_cnt_1s,uci->color_val) + ,colout->heading, colout->reset + ,print_usage_count_val(sum.top_cnt_5s,uci->color_val) + ,colout->heading, colout->reset + ,print_usage_dur_val(sum.top_nsec,uci->color_dur) + ,colout->heading, colout->reset + ); + + if (pm.debug) + fprintf(pm.flog," %2u%s",i,pm.eol); + else + fputs(pm.eol,pm.fout); + + if ( is_limit || !interval->name ) + break; + } + + fprintf(pm.fout, + "%s ╚════════╩════════╧═════════╧═════════╧════════╩" + "═════════╧═════════╧════════╝%s%s" + ,colout->heading ,colout->reset ,pm.eol ); + } + else + { + printf( + "%s ╔═══════════╦═════════════════════════════════════╦═════════╤═════════╤════════╦═════════════════════════════════════╗%s" + "%s ║ ║ Single Record ║ top 1s │ top 5s │ top ║ Summed Values ║%s" + "%s ║ real time ║ period │ counter │ count/s │ Ø time ║ count/s │ count/s │ time ║ period │ counter │ count/s │ Ø time ║%s" + "%s ╠═══════════╬════════╪═════════╪═════════╪════════╬═════════╪═════════╪════════╬════════╪═════════╪═════════╪════════╣%s%s" + ,colout->heading, pm.eol + ,colout->heading, pm.eol + ,colout->heading, pm.eol + ,colout->heading ,colout->reset, pm.eol + ); + + const IntervalInfo_t *interval = interval_info+1; + const UsageDurationEntry_t *e = ud->entry; + #if TEST_USAGE_COUNT + for ( int i = 0; i <= ud->par.used && sum.elapsed_nsec < limit_nsec; i++, e++ ) + #else + for ( int i = 0; i < ud->par.used && sum.elapsed_nsec < limit_nsec; i++, e++ ) + #endif + { + AddUsageDurationEntry(&sum,e); + if ( i > 0 && ( sum.elapsed_nsec >= interval->nsec || i == USAGE_COUNT_FIRST_ADD )) + { + fprintf(pm.fout, + "%s ╟───────────╫────────┼─────────┼─────────┼────────╫" + "─────────┼─────────┼────────╫" + "────────┼─────────┼─────────┼────────╢%s%s", + colout->heading, colout->reset, pm.eol ); + while ( sum.elapsed_nsec >= interval->nsec ) + interval++; + } + + fprintf(pm.fout, + "%s%*s%s║%s%s %s║%s %s %s│%s %s %s│%s%s %s│%s %s %s║%s" + ,pm.prefix ,pm.indent,"" + ,colout->heading, colout->reset + ,PrintRefTime(e->time_sec,&reftime) + ,colout->heading, colout->reset + ,PrintTimerNSec6(0,0,e->elapsed_nsec,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,PrintNumberU7(0,0,e->count,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,print_usage_count(e->count,e->elapsed_nsec,uci->color_val) + ,colout->heading, colout->reset + ,print_usage_dur(e->total_nsec,e->count,uci->color_dur) + ,colout->heading, colout->reset + ); + + fprintf(pm.fout, + "%s %s│%s%s %s│%s %s %s║%s" + ,print_usage_count_val(e->top_cnt_1s,uci->color_val) + ,colout->heading, colout->reset + ,print_usage_count_val(e->top_cnt_5s,uci->color_val) + ,colout->heading, colout->reset + ,print_usage_dur_val(e->top_nsec,uci->color_dur) + ,colout->heading, colout->reset + ); + + fprintf(pm.fout, + " %s %s│%s %s %s│%s%s %s│%s %s %s║%s" + ,PrintTimerNSec6(0,0,sum.elapsed_nsec,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,PrintNumberU7(0,0,sum.count,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,print_usage_count(sum.count,sum.elapsed_nsec,uci->color_val) + ,colout->heading, colout->reset + ,print_usage_dur(sum.total_nsec,sum.count,uci->color_dur) + ,colout->heading, colout->reset + ); + + if (pm.debug) + { + if ( pm.debug >= 2 && i >= USAGE_COUNT_FIRST_ADD ) + { + fprintf(pm.flog," %2u %s %s%4llu%%%s %s%5llu%%%s%s", + i, + PrintTimerNSec6(0,0,min,DC_SFORM_ALIGN|DC_SFORM_DASH), + e->elapsed_nsec < min ? "" + : e->elapsed_nsec < min*2 ? colout->hint : colout->warn, + 100 * e->elapsed_nsec / min, colout->reset, + sum.elapsed_nsec < min ? colout->info : "", + 100 * sum.elapsed_nsec / min, colout->reset, pm.eol ); + min = USAGE_COUNT_NEXT_MIN(min); + } + else + fprintf(pm.flog," %2u%s",i,pm.eol); + } + else + fputs(pm.eol,pm.fout); + } + + fprintf(pm.fout, + "%s ╚═══════════╩════════╧═════════╧═════════╧════════╩" + "═════════╧═════════╧════════╩" + "════════╧═════════╧═════════╧════════╝%s%s" + ,colout->heading ,colout->reset ,pm.eol ); + } +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// cpu usage /////////////// +/////////////////////////////////////////////////////////////////////////////// + +CpuUsage_t cpu_usage = { .par.used=0, .par.enabled = CPU_USAGE_ENABLED }; + +const UsageCtrl_t cpu_usage_ctrl = +{ + .par = &cpu_usage.par, + .update_func = UpdateCpuUsageByUCI, + .list_func = ListCpuUsage, + .title = "CPU usage (extern)", + .key1 = "CPU", +}; + +/////////////////////////////////////////////////////////////////////////////// + +static ccp print_cpu_percent ( double val ) +{ + if (!val) + return " -"; + + //static const double collist[] = { 40, 60, 80, 95 }; + static const double collist[] = { 25, 50, 75, 95 }; + + if ( val >= collist[0] ) + { + ccp col = val < collist[2] + ? ( val < collist[1] ? colout->info : colout->hint ) + : ( val < collist[3] ? colout->warn : colout->err ); + return PrintCircBuf("%s%6.2f%s", col, val, colout->reset ); + } + + char *res = PrintCircBuf("%6.2f",val); + if ( val < 1.0 && res[2] == '0' ) + res[2] = ' '; + return res; +} + +//----------------------------------------------------------------------------- + +static ccp print_cpu_seconds ( u_usec_t val ) +{ + return !val + ? " -" + : val < USEC_PER_SEC + ? PrintCircBuf("%8llu",val) + : val < 10*USEC_PER_SEC + ? PrintCircBuf("%llu.%06llu",val/USEC_PER_SEC,val%USEC_PER_SEC) + : PrintCircBuf("%4llu.%03llu",val/USEC_PER_SEC,val%USEC_PER_SEC/1000); +} + +//----------------------------------------------------------------------------- + +static ccp print_cpu_wait_val ( double val ) +{ + static const double collist[] = { 100, 150, 200, 250, 300, 350 }; + if ( val > collist[0] ) + { + if ( val >= 999.0 ) + return PrintCircBuf(" %s%6.0f%s",colout->fatal,val,colout->reset); + + ccp col = val < collist[2] + ? ( val < collist[1] ? colout->mark : colout->info ) + : val < collist[4] + ? ( val < collist[3] ? colout->hint : colout->warn ) + : ( val < collist[5] ? colout->err : colout->bad ); + + return PrintCircBuf("%s%7.2f%s",col,val,colout->reset); + } + + if ( val <= 0 ) + return " -"; + + char * res = PrintCircBuf("%7.2f",val); + if ( val < 1.0 && res[3] == '0' ) + res[3] = ' '; + return res; +} + +//----------------------------------------------------------------------------- + +static ccp print_cpu_wait ( u32 n_wait, u_usec_t elapsed_usec ) +{ + return elapsed_usec + ? print_cpu_wait_val( (double)( USEC_PER_SEC * n_wait ) / elapsed_usec ) + : " ×"; +} + +//----------------------------------------------------------------------------- + +static void print_cpu_debug + ( int idx, u_usec_t *min, u_usec_t elapsed1, u_usec_t elapsed2 ) +{ + DASSERT(min); + + if ( idx >= CPU_USAGE_FIRST_ADD && *min ) + { + printf(" %2u %s %s%4llu%%%s %s%4llu%%%s\n", + idx, + PrintTimerUSec6(0,0,*min,DC_SFORM_ALIGN|DC_SFORM_DASH), + elapsed1 < *min ? "" : elapsed1 < *min*2 ? colout->hint : colout->warn, + 100 * elapsed1 / *min, colout->reset, + elapsed2 < *min ? colout->info : "", 100 * elapsed2 / *min, colout->reset ); + *min = CPU_USAGE_NEXT_MIN(*min); + } + else + printf(" %2u\n",idx); +} + +/////////////////////////////////////////////////////////////////////////////// + +void ListCpuUsage +( + PrintMode_t *p_pm, // NULL or print mode + const UsageCtrl_t *uci, // ignored! + int print_mode, // see LUC_PM_* + s_nsec_t limit_nsec // >0: limit output until # is reached +) +{ + //--- setup + + PrintMode_t pm = {0}; + if (p_pm) + pm = *p_pm; + SetupPrintMode(&pm); + + const u_usec_t limit_usec = limit_nsec > 0 ? limit_nsec/NSEC_PER_USEC : S_USEC_MAX; + + + //--- print header + + const ccp empty_line = pm.compact ? "" : "\n"; + printf("%s%s CPU Usage (%u record%s%s)%s\n", + empty_line, colout->caption, + cpu_usage.par.used, cpu_usage.par.used == 1 ? "" : "s", + cpu_usage.par.enabled ? "" : ", disabled", colout->reset ); + + if (!cpu_usage.par.used) + return; + + + //--- print table + + CpuUsageEntry_t sum = {0}; + u_sec_t reftime = 0; + u_usec_t min = CPU_USAGE_NEXT_MIN(USEC_PER_SEC); + + if ( print_mode == LUC_PM_SUMMARY ) + { + printf( + "%s ╔════════╦═════════════════════════════════════════╦════════════════╦════════════════╗\n" + "%s ║ ║ Summed Values ║ top 1s ║ top 5s ║\n" + "%s ║ range ║ period │ user%% │system%%│total%% │ wait/s ║total%% │ wait/s ║total%% │ wait/s ║\n" + "%s ╠════════╬════════╪═══════╪═══════╪═══════╪════════╬═══════╪════════╬═══════╪════════╣%s\n" + ,colout->heading + ,colout->heading + ,colout->heading + ,colout->heading ,colout->reset + ); + + const IntervalInfo_t *interval = interval_info; + const CpuUsageEntry_t *e = cpu_usage.entry; + for ( int i = 0; i < cpu_usage.par.used; i++, e++ ) + { + AddCpuEntry(&sum,e); + bool is_last = false; + const bool is_limit = sum.elapsed_usec >= limit_usec; + if ( sum.elapsed_usec < interval->usec ) + { + is_last = i+1 == cpu_usage.par.used; + if ( !is_last && !is_limit ) + continue; + } + + ccp name; + if ( is_last || sum.elapsed_usec < interval->usec ) + name = "*"; + else + { + while ( sum.elapsed_usec > interval->usec ) + interval++; + name = interval[-1].name; + } + + const double elapsed = 100.0 / sum.elapsed_usec; + printf(" %s║%s %-6.6s %s║%s %s %s│%s%s %s│%s%s %s│%s%s %s│%s%s %s║%s" + ,colout->heading, colout->reset + ,name + ,colout->heading, colout->reset + ,PrintTimerUSec6(0,0,sum.elapsed_usec,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,print_cpu_percent(sum.utime_usec * elapsed) + ,colout->heading, colout->reset + ,print_cpu_percent(sum.stime_usec * elapsed) + ,colout->heading, colout->reset + ,print_cpu_percent(( sum.utime_usec + sum.stime_usec) * elapsed) + ,colout->heading, colout->reset + ,print_cpu_wait(sum.n_wait,sum.elapsed_usec) + ,colout->heading, colout->reset + ); + + printf("%s %s│%s%s %s║%s%s %s│%s%s %s║%s" + ,print_cpu_percent(sum.top1s) + ,colout->heading, colout->reset + ,print_cpu_wait_val(sum.topw1s) + ,colout->heading, colout->reset + ,print_cpu_percent(sum.top5s) + ,colout->heading, colout->reset + ,print_cpu_wait_val(sum.topw5s) + ,colout->heading, colout->reset + ); + + if (pm.debug) + fprintf(pm.flog," %2u%s",i,pm.eol); + else + fputs(pm.eol,pm.fout); + + if ( is_limit || !interval->name ) + break; + } + printf( + "%s ╚════════╩════════╧═══════╧═══════╧═══════╧════════╩" + "═══════╧════════╩═══════╧════════╝%s%s%s", + colout->heading ,colout->reset, pm.eol, empty_line ); + } + else if ( print_mode == LUC_PM_RAW ) + { + printf( + "%s ╔═══════════╦══════════════════════════════════════════════════╦══════════════════════════════════════════════════╗\n" + "%s ║ ║ Single Record (µs) ║ Summed Values (µs) ║\n" + "%s ║ real time ║ period │ user │ system │ total │ wait/s ║ period │ user │ system │ total │ wait/s ║\n" + "%s ╠═══════════╬════════╪══════════╪══════════╪══════════╪════════╬════════╪══════════╪══════════╪══════════╪════════╣%s\n" + ,colout->heading + ,colout->heading + ,colout->heading + ,colout->heading ,colout->reset + ); + + const IntervalInfo_t *interval = interval_info+1; + for ( int i = 0; i < cpu_usage.par.used && sum.elapsed_usec < limit_usec; i++ ) + { + const CpuUsageEntry_t *e = cpu_usage.entry+i; + AddCpuEntry(&sum,e); + if ( i > 0 && ( sum.elapsed_usec >= interval->usec || i == CPU_USAGE_FIRST_ADD )) + { + printf( + "%s ╟───────────╫────────┼──────────┼──────────┼──────────┼────────╫" + "────────┼──────────┼──────────┼──────────┼────────╢%s\n", + colout->heading, colout->reset ); + while ( sum.elapsed_usec >= interval->usec ) + interval++; + } + + printf(" %s║%s%s %s║%s %s %s│%s %s %s│%s %s %s│%s %s %s│%s%s %s║%s" + ,colout->heading, colout->reset + ,PrintRefTime(e->time_sec,&reftime) + ,colout->heading, colout->reset + ,PrintTimerUSec6(0,0,e->elapsed_usec,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,print_cpu_seconds(e->utime_usec) + ,colout->heading, colout->reset + ,print_cpu_seconds(e->stime_usec) + ,colout->heading, colout->reset + ,print_cpu_seconds( e->utime_usec + e->stime_usec ) + ,colout->heading, colout->reset + ,print_cpu_wait(e->n_wait,e->elapsed_usec) + ,colout->heading, colout->reset + ); + + printf(" %s %s│%s %s %s│%s %s %s│%s %s %s│%s%s %s║%s" + ,PrintTimerUSec6(0,0,sum.elapsed_usec,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,print_cpu_seconds(sum.utime_usec) + ,colout->heading, colout->reset + ,print_cpu_seconds(sum.stime_usec) + ,colout->heading, colout->reset + ,print_cpu_seconds( sum.utime_usec + sum.stime_usec ) + ,colout->heading, colout->reset + ,print_cpu_wait(sum.n_wait,sum.elapsed_usec) + ,colout->heading, colout->reset + ); + + if (pm.debug) + print_cpu_debug(i,&min,e->elapsed_usec,sum.elapsed_usec); + else + putchar('\n'); + } + + printf( + "%s ╚═══════════╩════════╧══════════╧══════════╧══════════╧════════╩" + "════════╧══════════╧══════════╧══════════╧════════╝%s\n%s", + colout->heading, colout->reset, empty_line ); + } + else + { + printf( + "%s ╔═══════════╦═════════════════════════════════════════╦════════════════╦════════════════╦═════════════════════════════════════════╗\n" + "%s ║ ║ Single Record ║ top 1s ║ top 5s ║ Summed Values ║\n" + "%s ║ real time ║ period │ user%% │system%%│total%% │ wait/s ║total%% │ wait/s ║total%% │ wait/s ║ period │ user%% │system%%│total%% │ wait/s ║\n" + "%s ╠═══════════╬════════╪═══════╪═══════╪═══════╪════════╬═══════╪════════╬═══════╪════════╬════════╪═══════╪═══════╪═══════╪════════╣%s\n" + ,colout->heading + ,colout->heading + ,colout->heading + ,colout->heading ,colout->reset + ); + + const IntervalInfo_t *interval = interval_info+1; + #if TEST_USAGE_COUNT + for ( int i = 0; i <= cpu_usage.par.used && sum.elapsed_usec < limit_usec; i++ ) + #else + for ( int i = 0; i < cpu_usage.par.used && sum.elapsed_usec < limit_usec; i++ ) + #endif + { + const CpuUsageEntry_t *e = cpu_usage.entry+i; + AddCpuEntry(&sum,e); + if ( i > 0 && ( sum.elapsed_usec >= interval->usec || i == CPU_USAGE_FIRST_ADD )) + { + printf( + "%s ╟───────────╫────────┼───────┼───────┼───────┼────────╫" + "───────┼────────╫───────┼────────╫" + "────────┼───────┼───────┼───────┼────────╢%s\n", + colout->heading, colout->reset ); + while ( sum.elapsed_usec >= interval->usec ) + interval++; + } + + double elapsed = 100.0 / e->elapsed_usec; + printf(" %s║%s%s %s║%s %s %s│%s%s %s│%s%s %s│%s%s %s│%s%s %s║%s" + ,colout->heading, colout->reset + ,PrintRefTime(e->time_sec,&reftime) + ,colout->heading, colout->reset + ,PrintTimerUSec6(0,0,e->elapsed_usec,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,print_cpu_percent(e->utime_usec * elapsed) + ,colout->heading, colout->reset + ,print_cpu_percent(e->stime_usec * elapsed) + ,colout->heading, colout->reset + ,print_cpu_percent(( e->utime_usec + e->stime_usec) * elapsed) + ,colout->heading, colout->reset + ,print_cpu_wait(e->n_wait,e->elapsed_usec) + ,colout->heading, colout->reset + ); + + printf("%s %s│%s%s %s║%s%s %s│%s%s %s║%s" + ,print_cpu_percent(e->top1s) + ,colout->heading, colout->reset + ,print_cpu_wait_val(e->topw1s) + ,colout->heading, colout->reset + ,print_cpu_percent(e->top5s) + ,colout->heading, colout->reset + ,print_cpu_wait_val(e->topw5s) + ,colout->heading, colout->reset + ); + + elapsed = 100.0 / sum.elapsed_usec; + printf(" %s %s│%s%s %s│%s%s %s│%s%s %s│%s%s %s║%s" + ,PrintTimerUSec6(0,0,sum.elapsed_usec,DC_SFORM_ALIGN|DC_SFORM_DASH) + ,colout->heading, colout->reset + ,print_cpu_percent(sum.utime_usec * elapsed) + ,colout->heading, colout->reset + ,print_cpu_percent(sum.stime_usec * elapsed) + ,colout->heading, colout->reset + ,print_cpu_percent(( sum.utime_usec + sum.stime_usec) * elapsed) + ,colout->heading, colout->reset + ,print_cpu_wait(sum.n_wait,sum.elapsed_usec) + ,colout->heading, colout->reset + ); + + if (pm.debug) + print_cpu_debug(i,&min,e->elapsed_usec,sum.elapsed_usec); + else + putchar('\n'); + } + + printf( + "%s ╚═══════════╩════════╧═══════╧═══════╧═══════╧════════╩" + "═══════╧════════╩═══════╧════════╩" + "════════╧═══════╧═══════╧═══════╧════════╝%s%s", + colout->heading, colout->reset, empty_line ); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +const SaveRestoreTab_t SRT_CpuUsage[] = +{ + #undef SRT_NAME + #define SRT_NAME CpuUsage_t + + DEF_SRT_COMMENT("cpu_usage"), + DEF_SRT_SEPARATOR(), + + DEF_SRT_INT( par.enabled, "cpu-enabled" ), + DEF_SRT_UINT( par.used, "cpu-used" ), + DEF_SRT_ARRAY_A(entry), + DEF_SRT_UINT( entry[0].elapsed_usec, "cpu-elapsed" ), + DEF_SRT_UINT( entry[0].utime_usec, "cpu-utime" ), + DEF_SRT_UINT( entry[0].stime_usec, "cpu-stime" ), + DEF_SRT_UINT( entry[0].time_sec, "cpu-rtime" ), + DEF_SRT_FLOAT( entry[0].top1s, "cpu-top1s" ), + DEF_SRT_FLOAT( entry[0].top5s, "cpu-top5s" ), + DEF_SRT_UINT( entry[0].n_wait, "cpu-nwait" ), + DEF_SRT_FLOAT( entry[0].topw1s, "cpu-topw1s" ), + DEF_SRT_FLOAT( entry[0].topw5s, "cpu-topw5s" ), + DEF_SRT_ARRAY_END(), + + DEF_SRT_SEPARATOR(), + DEF_SRT_TERM() +}; + +//----------------------------------------------------------------------------- +// [[UpdateCpuUsage]] + +void UpdateCpuUsageByUCI ( const UsageCtrl_t *uci, u_nsec_t now_nsec ) +{ + UpdateCpuUsage(); +} + +//----------------------------------------------------------------------------- + +void UpdateCpuUsage() +{ + if (!cpu_usage.par.enabled) + { + cpu_usage.ref.elapsed_usec = 0; + cpu_usage.ref.n_wait = 0; + return; + } + cpu_usage.par.is_active = true; + + CpuUsageEntry_t cur = {0}; + cur.elapsed_usec = GetTimerUSec(); + + if ( cur.elapsed_usec >= cpu_usage.ref.elapsed_usec + USEC_PER_SEC ) + { + // needed for the case that CPU_USAGE_ENTRIES was reduced after restart! + if ( cpu_usage.par.used > CPU_USAGE_ENTRIES ) + cpu_usage.par.used = CPU_USAGE_ENTRIES; + + struct rusage ru; + if (!getrusage(RUSAGE_SELF,&ru)) + { + cur.time_sec = GetTimeSec(false); + cur.utime_usec = ru.ru_utime.tv_sec * USEC_PER_SEC + ru.ru_utime.tv_usec; + cur.stime_usec = ru.ru_stime.tv_sec * USEC_PER_SEC + ru.ru_stime.tv_usec; + + if (cpu_usage.ref.elapsed_usec) + { + //--- find index and move data + + int index; + if ( cpu_usage.par.used < CPU_USAGE_FIRST_ADD ) + index = cpu_usage.par.used + 1; + else + { + u_usec_t min = CPU_USAGE_NEXT_MIN(USEC_PER_SEC); + for ( index = CPU_USAGE_FIRST_ADD; + index < cpu_usage.par.used; + index++, min = CPU_USAGE_NEXT_MIN(min) + ) + { + CpuUsageEntry_t *e = cpu_usage.entry + index; + if ( e->elapsed_usec < min ) + { + AddCpuEntry(e,e-1); + index--; + break; + } + } + if ( ++index > CPU_USAGE_ENTRIES ) + index = CPU_USAGE_ENTRIES; + } + + if ( index > 1 ) + memmove( cpu_usage.entry+1, cpu_usage.entry, + (index-1) * sizeof(*cpu_usage.entry) ); + + if ( cpu_usage.par.used < index ) + cpu_usage.par.used = index; + + + //--- update first entry + + CpuUsageEntry_t *e = cpu_usage.entry; + *e = cpu_usage.ref; + e->elapsed_usec = cur.elapsed_usec - cpu_usage.ref.elapsed_usec; + e->utime_usec = cur.utime_usec - cpu_usage.ref.utime_usec; + e->stime_usec = cur.stime_usec - cpu_usage.ref.stime_usec; + + + //--- update top values (1s) + + if (e->elapsed_usec) + { + e->top1s = 100.0 * ( e->utime_usec + e->stime_usec ) / e->elapsed_usec; + e->topw1s = (double)( USEC_PER_SEC * e->n_wait ) / e->elapsed_usec; + } + + + //--- update top values (5s) + + u_usec_t elapsed5 = 0, total5 = 0, wait5 = 0; + CpuUsageEntry_t *e5 = cpu_usage.entry; + for ( int i = 0; i < cpu_usage.par.used && elapsed5 < 5*USEC_PER_SEC; i++, e5++ ) + { + elapsed5 += e5->elapsed_usec; + total5 += e5->utime_usec + e5->stime_usec; + wait5 += e5->n_wait; + } + + if (elapsed5) + { + if ( wait5 == e->n_wait && total5 == e->utime_usec + e->stime_usec ) + elapsed5 = 5*NSEC_PER_SEC; + e->top5s = 100.0 * total5 / elapsed5; + e->topw5s = (double)( USEC_PER_SEC * wait5 ) / elapsed5; + } + } + + cpu_usage.ref = cur; + } + } +} + +//----------------------------------------------------------------------------- + +void UpdateCpuUsageIncrement() +{ + UpdateCpuUsage(); + cpu_usage.ref.n_wait++; +} + +//----------------------------------------------------------------------------- + +void AddCpuEntry ( CpuUsageEntry_t *dest, const CpuUsageEntry_t *add ) +{ + DASSERT(dest); + DASSERT(add); + dest->elapsed_usec += add->elapsed_usec; + dest->utime_usec += add->utime_usec; + dest->stime_usec += add->stime_usec; + dest->n_wait += add->n_wait; + + if ( !dest->time_sec || dest->time_sec > add->time_sec ) + dest->time_sec = add->time_sec; + + if ( dest->top1s < add->top1s ) + dest->top1s = add->top1s; + if ( dest->top5s < add->top5s ) + dest->top5s = add->top5s; + + if ( dest->topw1s < add->topw1s ) + dest->topw1s = add->topw1s; + if ( dest->topw5s < add->topw5s ) + dest->topw5s = add->topw5s; +} + +//----------------------------------------------------------------------------- + +CpuUsageEntry_t GetCpuUsage ( s_usec_t usec ) +{ + CpuUsageEntry_t res = {0}; + for ( int i = 0; i < cpu_usage.par.used && usec > 0; i++ ) + { + const CpuUsageEntry_t *e = cpu_usage.entry + i; + usec -= e->elapsed_usec; + AddCpuEntry(&res,e); + } + return res; +} + +//----------------------------------------------------------------------------- + +uint GetCpuUsagePercent ( s_usec_t usec ) +{ + CpuUsageEntry_t e = GetCpuUsage(usec); + return GetCpuEntryPercent(&e); +} + +/////////////////////////////////////////////////////////////////////////////// + +double get_rusage_percent (void) +{ + static u_nsec_t prev_time = 0; + static u_usec_t prev_rusage = 0; + static double prev_percent = 0.0; + + const u_nsec_t cur_time = GetTimerNSec(); + if ( cur_time < prev_time + 10*NSEC_PER_MSEC ) + return prev_percent; + + u_usec_t cur_rusage = prev_rusage; + struct rusage ru; + if (!getrusage(RUSAGE_SELF,&ru)) + { + cur_rusage = ru.ru_utime.tv_sec * USEC_PER_SEC + ru.ru_utime.tv_usec + + ru.ru_stime.tv_sec * USEC_PER_SEC + ru.ru_stime.tv_usec; + } + + double percent = 0.0; + if ( prev_time && cur_time > prev_time ) + percent = (double)( 100 * NSEC_PER_USEC * ( cur_rusage - prev_rusage )) + / ( cur_time - prev_time ); + + prev_time = cur_time; + prev_rusage = cur_rusage; + + return prev_percent = percent; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// urandom support /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -3718,7 +6177,7 @@ const u32 RANDOM32_C_ADD = 2 * 197731421; // 2 Primzahlen const u32 RANDOM32_COUNT_BASE = 4294967; // Primzahl == ~UINT_MAX32/1000; static int random32_a_index = -1; // Index in die a-Tabelle -static u32 random32_count = 1; // Abwärts-Zähler bis zum Wechsel von a,c +static u32 random32_count = 1; // Abwärts-Zähler bis zum Wechsel von a,c static u32 random32_a, random32_c, random32_X; // Die letzten Werte @@ -3750,7 +6209,7 @@ u32 MyRandom ( u32 max ) if (!--random32_count) { - // Neue Berechnung von random32_a und random32_c fällig + // Neue Berechnung von random32_a und random32_c fällig if ( random32_a_index < 0 ) { @@ -4295,8 +6754,23 @@ char * ScanS32 while ( *src > 0 && *src <= ' ' ) src++; } + #if 0 // 0b and 0d can be hex numbers => so this doeasn't work + uint base = default_base; + if ( src[0] == '0' ) + { + switch(tolower((int)src[1])) + { + case 'x': base = 16; break; + case 'd': base = 10; src+=2; break; + case 'o': base = 8; src+=2; break; + case 'b': base = 2; src+=2; break; + } + } + #else const uint base = src[0] == '0' && ( src[1] == 'x' || src[1] == 'X' ) ? 16 : default_base; + #endif + char *end; const s32 num = strtoul( src, &end, base ); if ( (ccp)end > src ) @@ -5734,14 +8208,27 @@ char * ScanSizeRange u64 default_factor, // use this factor if number hasn't one u64 default_factor_add, // use this factor for summands int force_base, // if 1000|1024: force multiple of this - double max_value // >0: max value for open ranges + double max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT ) { + if (!opt) + opt = RAOPT__DEFAULT; + int count = 0; - double d1, d2; + double d1 = 0, d2; + + bool have_d1 = false; + if ( opt & RAOPT_ASSUME_0 ) + { + have_d1 = *source == ':' && opt & RAOPT_COLON + || *source == '#' && opt & RAOPT_HASH + || *source == ',' && opt & RAOPT_COMMA; + } - char *end = ScanSize(&d1,source,default_factor,default_factor_add,force_base); - if ( end == source ) + char *end = have_d1 ? (char*)source + : ScanSize(&d1,source,default_factor,default_factor_add,force_base); + if ( !have_d1 && end == source ) { d1 = d2 = 0.0; count = 0; @@ -5750,13 +8237,33 @@ char * ScanSizeRange { count++; d2 = d1; - if ( *end == '#' || *end == ':' ) + + const bool have_range = *end == ':' && opt & RAOPT_COLON + || *end == '-' && opt & RAOPT_MINUS; + const bool have_size = *end == '#' && opt & RAOPT_HASH + || *end == ',' && opt & RAOPT_COMMA; + + if ( have_range || have_size ) { + if ( d1 < 0 && max_value > 0 && opt & RAOPT_NEG ) + { + d1 += max_value; + if ( d1 < 0 ) + d1 = 0; + } + source = end; end = ScanSize(&d2,source+1,default_factor,default_factor_add,force_base); + if ( have_range && d2 < 0 && max_value > 0 && opt & RAOPT_NEG ) + { + d2 += max_value; + if ( d2 < 0 ) + d2 = 0; + } + if ( end == source+1 ) { - if ( *source == ':' && max_value > 0.0 ) + if ( have_range && max_value > 0.0 ) { count++; d2 = max_value; @@ -5772,11 +8279,14 @@ char * ScanSizeRange else { count++; - if ( *source == '#' ) + if ( have_size ) d2 += d1-1; } if ( d2 < d1 ) + { + count = 0; d2 = d1; + } } } @@ -5802,16 +8312,21 @@ char * ScanSizeRangeU32 u64 default_factor, // use this factor if number hasn't one u64 default_factor_add, // use this factor for summands int force_base, // if 1000|1024: force multiple of this - u32 max_value // >0: max value for open ranges + u32 max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT ) { double d1, d2; char * end = ScanSizeRange(stat,&d1,&d2,source, default_factor,default_factor_add,force_base, - max_value>0 ? max_value : U32_MAX ); + max_value>0 ? max_value : U32_MAX, opt ); if ( d1 < 0 || d1 > U32_MAX || d2 < 0 || d2 > U32_MAX ) + { end = (char*)source; + if (stat) + *stat = 0; + } else { if (num1) @@ -5826,6 +8341,46 @@ char * ScanSizeRangeU32 /////////////////////////////////////////////////////////////////////////////// +char * ScanSizeRangeS32 +( + int *stat, // if not NULL: store result + // 0:none, 1:single, 2:range + s32 *num1, // not NULL: store 'from' result + s32 *num2, // not NULL: store 'to' result + + ccp source, // source text + u64 default_factor, // use this factor if number hasn't one + u64 default_factor_add, // use this factor for summands + int force_base, // if 1000|1024: force multiple of this + s32 max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT +) +{ + double d1, d2; + char * end = ScanSizeRange(stat,&d1,&d2,source, + default_factor,default_factor_add,force_base, + max_value>0 ? max_value : S32_MAX, opt ); + + if ( d1 < S32_MIN || d1 > S32_MAX || d2 < S32_MIN || d2 > U32_MAX ) + { + end = (char*)source; + if (stat) + *stat = 0; + } + else + { + if (num1) + *num1 = (s32)d1; + if (num2) + *num2 = (s32)d2; + } + + return end; + +} + +/////////////////////////////////////////////////////////////////////////////// + char * ScanSizeRangeU64 ( int *stat, // if not NULL: store result @@ -5837,16 +8392,21 @@ char * ScanSizeRangeU64 u64 default_factor, // use this factor if number hasn't one u64 default_factor_add, // use this factor for summands int force_base, // if 1000|1024: force multiple of this - u64 max_value // >0: max value for open ranges + u64 max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT ) { double d1, d2; char * end = ScanSizeRange(stat,&d1,&d2,source, default_factor,default_factor_add,force_base, - max_value>0 ? max_value : U64_MAX ); + max_value>0 ? max_value : U64_MAX, opt ); if ( d1 < 0 || d1 > U64_MAX || d2 < 0 || d2 > U64_MAX ) + { end = (char*)source; + if (stat) + *stat = 0; + } else { if (num1) @@ -5860,6 +8420,46 @@ char * ScanSizeRangeU64 } /////////////////////////////////////////////////////////////////////////////// + +char * ScanSizeRangeS64 +( + int *stat, // if not NULL: store result + // 0:none, 1:single, 2:range + s64 *num1, // not NULL: store 'from' result + s64 *num2, // not NULL: store 'to' result + + ccp source, // source text + u64 default_factor, // use this factor if number hasn't one + u64 default_factor_add, // use this factor for summands + int force_base, // if 1000|1024: force multiple of this + s64 max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT +) +{ + double d1, d2; + char * end = ScanSizeRange(stat,&d1,&d2,source, + default_factor,default_factor_add,force_base, + max_value>0 ? max_value : S64_MAX, opt ); + + if ( d1 < S64_MIN || d1 > S64_MAX || d2 < S64_MIN || d2 > U64_MAX ) + { + end = (char*)source; + if (stat) + *stat = 0; + } + else + { + if (num1) + *num1 = (s64)d1; + if (num2) + *num2 = (s64)d2; + } + + return end; + +} + +/////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// char * ScanSizeRangeList @@ -5873,7 +8473,8 @@ char * ScanSizeRangeList u64 default_factor, // use this factor if number hasn't one u64 default_factor_add, // use this factor for summands int force_base, // if 1000|1024: force multiple of this - double max_value // >0: max value for open ranges + double max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT ) { DASSERT(num); @@ -5888,7 +8489,8 @@ char * ScanSizeRangeList int stat; ptr = ScanSizeRange( &stat, num, num+1, ptr, - default_factor, default_factor_add, force_base, max_value ); + default_factor, default_factor_add, + force_base, max_value, opt ); if (!stat) break; num += 2; @@ -5929,7 +8531,8 @@ char * ScanSizeRangeListU32 u32 default_factor, // use this factor if number hasn't one u32 default_factor_add, // use this factor for summands int force_base, // if 1000|1024: force multiple of this - u32 max_value // >0: max value for open ranges + u32 max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT ) { DASSERT(num); @@ -5940,7 +8543,7 @@ char * ScanSizeRangeListU32 char *end = ScanSizeRangeList( n_range, d, max_range, source, default_factor, default_factor_add, - force_base, max_value ); + force_base, max_value, opt ); uint i; for ( i = 0; i < 2*max_range; i++ ) @@ -5964,7 +8567,8 @@ char * ScanSizeRangeListU64 u64 default_factor, // use this factor if number hasn't one u64 default_factor_add, // use this factor for summands int force_base, // if 1000|1024: force multiple of this - u64 max_value // >0: max value for open ranges + u64 max_value, // >0: max value for open ranges + range_opt_t opt // options, if 0 then use RAOPT__DEFAULT ) { DASSERT(num); @@ -5975,7 +8579,7 @@ char * ScanSizeRangeListU64 char *end = ScanSizeRangeList( n_range, d, max_range, source, default_factor, default_factor_add, - force_base, max_value ); + force_base, max_value, opt ); uint i; for ( i = 0; i < 2*max_range; i++ ) @@ -6021,7 +8625,7 @@ enumError ScanSizeOpt err = ERR_SYNTAX; if (print_err) ERROR0(ERR_SYNTAX, - "Illegal number for option --%s: %s\n", + "Invalid number for option --%s: %s\n", opt_name, source ); } else if ( min > 0 && d < min ) @@ -6219,6 +8823,7 @@ char * ScanSIFactor ) { DASSERT(source); + double i = 0.0; switch (*(uchar*)source++) { case 'y': default_factor = 1e-24; break; @@ -6227,26 +8832,27 @@ char * ScanSIFactor case 'f': default_factor = 1e-15; break; case 'p': default_factor = 1e-12; break; case 'n': default_factor = 1e-9; break; - case 0xb5: // µ as ANSI + case 0xb5: // µ as ASCII case 'u': default_factor = 1e-6; break; case 'm': default_factor = 1e-3; break; case 'c': default_factor = 1e-2; break; case 'd': default_factor = 1e-1; break; case 'h': default_factor = 1e2; break; - case 'k': default_factor = 1e3; break; - case 'M': default_factor = 1e6; break; - case 'G': default_factor = 1e9; break; - case 'T': default_factor = 1e12; break; - case 'P': default_factor = 1e15; break; - case 'E': default_factor = 1e18; break; - case 'Z': default_factor = 1e21; break; - case 'Y': default_factor = 1e24; break; + case 'k': + case 'K': default_factor = 1e3; i = 1024.0; break; + case 'M': default_factor = 1e6; i = 1048576.0; break; + case 'G': default_factor = 1e9; i = 1073741824.0; break; + case 'T': default_factor = 1e12; i = 1099511627776.0; break; + case 'P': default_factor = 1e15; i = 1125899906842624.0; break; + case 'E': default_factor = 1e18; i = 1152921504606846976.0; break; + case 'Z': default_factor = 1e21; i = 1180591620717411303424.0; break; + case 'Y': default_factor = 1e24; i = 1208925819614629174706176.0; break; case 0xc2: if ( (uchar)*source == 0xb5 ) { - // µ as UTF-8 + // µ as UTF-8 source++; default_factor = 1e-6; break; @@ -6258,6 +8864,13 @@ char * ScanSIFactor default: source--; } + + if ( *source == 'i' && i ) + { + source++; + default_factor = i; + } + if (num) *num = default_factor; return (char*)source; @@ -6270,13 +8883,13 @@ double GetDurationFactor ( char ch ) switch (ch) { case 's': return 1.0; break; - case 'm': return 60.0; break; - case 'h': return 3600.0; break; + case 'm': return SEC_PER_MIN; break; + case 'h': return SEC_PER_HOUR; break; case 't': - case 'd': return 86400.0; break; - case 'w': return 7*86400.0; break; + case 'd': return SEC_PER_DAY; break; + case 'w': return SEC_PER_WEEK; break; case 'j': - case 'y': return 365*86400.0; break; + case 'y': return SEC_PER_YEAR; break; default: return 0.0; } } @@ -6285,7 +8898,10 @@ double GetDurationFactor ( char ch ) char * ScanDuration ( - double *num, // not NULL: store result + // Returns a pointer to the the first not used character. + // On error, it is 'source' and '*seconds' is set to 0.0. + + double *seconds, // not NULL: store result (number of seconds) ccp source, // source text double default_factor, // default factor if no SI unit found ScanDuration_t mode @@ -6293,8 +8909,9 @@ char * ScanDuration { if (!source) return 0; + ccp src, done; + done = src = source; - ccp src = source; if ( mode & SDUMD_SKIP_BLANKS ) while ( *src == ' ' || *src == '\t' ) src++; @@ -6318,7 +8935,7 @@ char * ScanDuration } else sum += val; - src = end; + done = src = end; valid = true; if ( mode & SDUMD_ALLOW_SPACE_SEP ) @@ -6333,9 +8950,9 @@ char * ScanDuration } mode |= SDUMD_SKIP_BLANKS; } - if (num) - *num = sum; - return (char*)( valid ? src : source ); + if (seconds) + *seconds = sum; + return (char*)( valid ? done : source ); } @@ -6379,8 +8996,11 @@ char * ScanDuration double si_factor; end = ScanSIFactor(&si_factor,src,1.0); + char factor = *end; + if ( mode & SDUMD_ALLOW_CAPITALS ) + factor = tolower((int)factor); + double unit = GetDurationFactor(factor); - double unit = GetDurationFactor(*end); if (unit) { val *= unit * si_factor; @@ -6388,7 +9008,10 @@ char * ScanDuration } else { - unit = GetDurationFactor(*src); + char factor = *src; + if ( mode & SDUMD_ALLOW_CAPITALS ) + factor = tolower((int)factor); + unit = GetDurationFactor(factor); if (unit) { val *= unit; @@ -6401,24 +9024,199 @@ char * ScanDuration } } } - if (num) - *num = val; + if (seconds) + *seconds = val; return (char*)src; } - if (num) - *num = 0.0; + if (seconds) + *seconds = 0.0; return (char*)source; } +/////////////////////////////////////////////////////////////////////////////// + +double str2duration ( ccp src, char **endptr, double default_factor ) +{ + double dur = 0.0; + char *end = ScanDuration(&dur,src,default_factor,SDUMD_M_DEFAULT); + if (endptr) + *endptr = end; + return dur; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// ScanIP4 /////////////// +/////////////////////////////////////////////////////////////////////////////// + +ipv4_class_t ScanIP4 +( + ipv4_t *ret_ip4, // not NULL: return numeric IPv4 here + ccp addr, // address to analyze + int addr_len // length of addr; if <0: use strlen(addr) +) +{ + //--- param check + + if (!addr) + { + error: + if (ret_ip4) + *ret_ip4 = 0; + return CIP4_ERROR; + } + + if ( addr_len < 0 ) + addr_len = strlen(addr); + + ccp addr_end = addr + addr_len; + + + //--- skip leading blanks + + while ( addr < addr_end && isblank((int)*addr) ) + addr++; + + + //--- scan input + + int count = 0; + bool trailing_pt = false; + uint num[4] = {0,0,0,0}; + while ( addr < addr_end ) + { + if ( *addr < '0' || *addr > '9' ) + break; + + addr = ScanNumber ( num+count++, addr, addr_end, *addr == '0' ? 8 : 10, 3 ); + if ( count == 4 || *addr != '.' ) + { + trailing_pt = false; + break; + } + addr++; + trailing_pt = true; + } + + //printf("N=%u .=%u [%u,%u,%u,%u] addr=%s\n",count,trailing_pt,num[0],num[1],num[2],num[3],addr); + + if ( !count || addr < addr_end ) + goto error; + + + //--- calculate IPv4 based on class-X + + ipv4_class_t res = CIP4_INVALID; + u32 ipv4 = 0; + + switch ( trailing_pt ? 4 : count ) + { + case 1: + ipv4 = num[0]; + res = CIP4_NUMERIC; + break; + + case 2: + if ( num[0] <= 0xff && num[1] <= 0xffffff ) + { + ipv4 = num[0] << 24 | num[1]; + res = CIP4_CLASS_A; + } + break; + + case 3: + if ( num[0] <= 0xff && num[1] <= 0xff && num[2] <= 0xffff ) + { + ipv4 = num[0] << 24 | num[1] << 16 | num[2]; + res = CIP4_CLASS_B; + } + break; + + case 4: + if ( num[0] <= 0xff && num[1] <= 0xff && num[2] <= 0xff && num[3] <= 0xff ) + { + ipv4 = num[0] << 24 | num[1] << 16 | num[2] << 8 | num[3]; + res = CIP4_CLASS_C; + } + break; + } + + + //--- return status + + if (ret_ip4) + *ret_ip4 = ipv4; + + return res; +} + +/////////////////////////////////////////////////////////////////////////////// + +char * NormalizeIP4 +( + // Return a pointer to dest if valid IPv4, + // Otherwise return 0 and buf is not modifieid. + + char *buf, // result buffer, can be 'addr' + // if NULL: use a local circulary static buffer + size_t buf_size, // size of 'buf', ignored if buf==NULL + bool c_notation, // TRUE: force lass-C notation (a.b.c.d) + + ccp addr, // address to analyze + int addr_len // length of addr; if <0: use strlen(addr) +) +{ + ipv4_t ip4; + ipv4_class_t stat = ScanIP4(&ip4,addr,-1); + if ( stat <= CIP4_INVALID ) + return 0; + + return PrintIP4ByMode( buf, buf_size, ip4, c_notation ? CIP4_CLASS_C : stat, -1 ); +} + +/////////////////////////////////////////////////////////////////////////////// + +int dclib_aton ( ccp addr, struct in_addr *inp ) +{ + ipv4_t ip4; + ipv4_class_t stat = ScanIP4(&ip4,addr,-1); + if (inp) + inp->s_addr = htonl(ip4); + return stat > CIP4_INVALID; +} + // /////////////////////////////////////////////////////////////////////////////// /////////////// PrintIP4*() /////////////// /////////////////////////////////////////////////////////////////////////////// +char * PrintIP4N +( + // print as unsigned number (CIP4_NUMERIC) + + char *buf, // result buffer + // NULL: use a local circulary static buffer + size_t buf_size, // size of 'buf', ignored if buf==NULL + u32 ip4, // IP4 to print + s32 port // 0..0xffff: add ':port' +) +{ + if (!buf) + buf = GetCircBuf( buf_size = FW_IPV4_A_PORT+1 ); + + if ( port >= 0 && port <= 0xffff ) + snprintf(buf,buf_size,"%u:%u", ip4, port ); + else + snprintf(buf,buf_size,"%u",ip4); + return buf; +} + +/////////////////////////////////////////////////////////////////////////////// + char * PrintIP4A ( - // print in A-notation + // print in A-notation (CIP4_CLASS_A) char *buf, // result buffer // NULL: use a local circulary static buffer @@ -6446,7 +9244,7 @@ char * PrintIP4A char * PrintIP4B ( - // print in A-notation + // print in B-notation (CIP4_CLASS_B) char *buf, // result buffer // NULL: use a local circulary static buffer @@ -6599,6 +9397,28 @@ char * PrintAlignedIP4 return buf; } +/////////////////////////////////////////////////////////////////////////////// + +char * PrintIP4ByMode +( + char *buf, // result buffer + // NULL: use a local circulary static buffer + size_t buf_size, // size of 'buf', ignored if buf==NULL + u32 ip4, // IP4 to print + ipv4_class_t mode, // CIP4_NUMERIC | CIP4_CLASS_A | CIP4_CLASS_B: + // force numeric or class-A/B output; otherwise class-C output + s32 port // 0..0xffff: add ':port' +) +{ + switch (mode) + { + case CIP4_NUMERIC: return PrintIP4N(buf,buf_size,ip4,port); + case CIP4_CLASS_A: return PrintIP4A(buf,buf_size,ip4,port); + case CIP4_CLASS_B: return PrintIP4B(buf,buf_size,ip4,port); + default: return PrintIP4 (buf,buf_size,ip4,port); + } +} + // /////////////////////////////////////////////////////////////////////////////// /////////////// CRC16 /////////////// @@ -6735,6 +9555,132 @@ char * ScanNiceID4 ( int * res, ccp arg ) return (char*)arg; }; +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintNiceID5 ( uint id ) +{ + if (!id) + return "-----"; + + char *buf = GetCircBuf(6); + DASSERT(buf); + + buf[0] = 'A' + id / 26000 % 26; + buf[1] = 'A' + id / 1000 % 26; + buf[2] = '0' + id / 100 % 10; + buf[3] = '0' + id / 10 % 10; + buf[4] = '0' + id % 10; + buf[5] = 0; + + return buf; +} + +/////////////////////////////////////////////////////////////////////////////// + +char * ScanNiceID5 ( int * res, ccp arg ) +{ + DASSERT(res); + *res = -1; + + if (!arg) + return 0; + + char ch = tolower((int)arg[0]); + if ( ch >= 'a' && ch <= 'z' ) + { + int num = ch - 'a'; + ch = tolower((int)arg[1]); + if ( ch >= 'a' && ch <= 'z' ) + { + num = 26 * num + ch - 'a'; + ch = arg[2]; + if ( ch >= '0' && ch <= '9' ) + { + num = 10 * num + ch - '0'; + ch = arg[3]; + if ( ch >= '0' && ch <= '9' ) + { + num = 10 * num + ch - '0'; + ch = arg[4]; + if ( ch >= '0' && ch <= '9' ) + { + *res = 10 * num + ch - '0'; + return (char*)arg+5; + } + } + } + } + } + return (char*)arg; +}; + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintNiceID6 ( uint id ) +{ + if (!id) + return "------"; + + char *buf = GetCircBuf(7); + DASSERT(buf); + + buf[0] = 'A' + id / 676000 % 26; + buf[1] = 'A' + id / 26000 % 26; + buf[2] = 'A' + id / 1000 % 26; + buf[3] = '0' + id / 100 % 10; + buf[4] = '0' + id / 10 % 10; + buf[5] = '0' + id % 10; + buf[6] = 0; + + return buf; +} + +/////////////////////////////////////////////////////////////////////////////// + +char * ScanNiceID6 ( int * res, ccp arg ) +{ + DASSERT(res); + *res = -1; + + if (!arg) + return 0; + + char ch = tolower((int)arg[0]); + if ( ch >= 'a' && ch <= 'z' ) + { + int num = ch - 'a'; + ch = tolower((int)arg[1]); + if ( ch >= 'a' && ch <= 'z' ) + { + num = 26 * num + ch - 'a'; + ch = tolower((int)arg[2]); + if ( ch >= 'a' && ch <= 'z' ) + { + num = 26 * num + ch - 'a'; + ch = arg[3]; + if ( ch >= '0' && ch <= '9' ) + { + num = 10 * num + ch - '0'; + ch = arg[4]; + if ( ch >= '0' && ch <= '9' ) + { + num = 10 * num + ch - '0'; + ch = arg[5]; + if ( ch >= '0' && ch <= '9' ) + { + *res = 10 * num + ch - '0'; + return (char*)arg+6; + } + } + } + } + } + } + return (char*)arg; +}; + // /////////////////////////////////////////////////////////////////////////////// /////////////// END /////////////// diff --git a/project/dclib/dclib-numeric.h b/project/dclib/dclib-numeric.h index dc4ccef..5ab36ef 100644 --- a/project/dclib/dclib-numeric.h +++ b/project/dclib/dclib-numeric.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -819,7 +819,7 @@ static inline s64 double2int64 ( double d ) { return (s64) trunc (d+0.5); } /////////////////////////////////////////////////////////////////////////////// -// all values are multiple of 26*26*100 = 67600 = 0x10810 +// all values are multiple of 26*26*100 = 67600 = 0x00010810 #define GOOD_MAX_NICE4_5 67600 // 1 * 67600 #define GOOD_MAX_NICE4_6 946400 // 14 * 67600 #define GOOD_MAX_NICE4_7 9937200 // 147 * 67600 @@ -830,6 +830,28 @@ static inline s64 double2int64 ( double d ) { return (s64) trunc (d+0.5); } ccp PrintNiceID4 ( uint nice_gid ); char * ScanNiceID4 ( int * res, ccp arg ); +/////////////////////////////////////////////////////////////////////////////// + +// all values are multiple of 26*26*1000 = 676000 = 0x000a50a0 +#define GOOD_MAX_NICE5_6 676000 // 1 * 676000 +#define GOOD_MAX_NICE5_7 9464000 // 14 * 676000 +#define GOOD_MAX_NICE5_8 99372000 // 147 * 676000 +#define GOOD_MAX_NICE5_9 999804000 // 1479 * 676000 +#define GOOD_MAX_NICE5 4294628000 // 6353 * 676000 = 0xfffad2a0 = -339296 + +ccp PrintNiceID5 ( uint nice_gid ); +char * ScanNiceID5 ( int * res, ccp arg ); + +/////////////////////////////////////////////////////////////////////////////// + +// all values are multiple of 26*26*26*1000 = 17576000 = 0x010c3040 +#define GOOD_MAX_NICE6_8 87880000 // 5 * 17576000 +#define GOOD_MAX_NICE6_9 984256000 // 56 * 17576000 +#define GOOD_MAX_NICE6 4288544000 // 244 * 17576000 = 0xff9dfd00 = -6423296 + +ccp PrintNiceID6 ( uint nice_gid ); +char * ScanNiceID6 ( int * res, ccp arg ); + // /////////////////////////////////////////////////////////////////////////////// /////////////// E N D /////////////// diff --git a/project/dclib/dclib-option.c b/project/dclib/dclib-option.c index 6af1589..fdcce94 100644 --- a/project/dclib/dclib-option.c +++ b/project/dclib/dclib-option.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -113,10 +113,10 @@ void AddGenericOpt { go->sopt_id[ch] = gp->id; *sopt_ptr++ = ch; - if ( gp->arg ) + if ( gp->arg == 1 || gp->arg == 2 ) { *sopt_ptr++ = ':'; - if ( gp->arg > 1 ) + if ( gp->arg == 2 ) *sopt_ptr++ = ':'; } } @@ -142,7 +142,7 @@ void AddGenericOpt struct option *opt = go->lopt + go->lopt_used++; opt->name = StrDupMemPool(&go->str_pool,name_buf); - opt->has_arg = gp->arg; + opt->has_arg = gp->arg < 2 ? gp->arg : 2; opt->flag = 0; opt->val = gp->id; @@ -446,7 +446,7 @@ GetGParam_t GetGParamDBL ( const GParam_t *par, double *return_val ) /////////////////////////////////////////////////////////////////////////////// -GetGParam_t GetGParamSTR ( const GParam_t *par, ccp *return_val ) +GetGParam_t GetGParamCCP ( const GParam_t *par, ccp *return_val ) { DASSERT( !par || par->vtype == GetGParamValueType(par->ptype) ); if ( par && par->vtype == GPT_STR ) @@ -573,13 +573,15 @@ ccp PrintGParam ( const GParam_t *par ) const GenericOptParm_t StandardGOptions[] = { - { GOPT_O_TEST_OPT, 0, "_opt" }, + { GOPT_O_TEST_OPT, 0, "@opt" }, { GOPT_O_HELP, 0, "h|help" }, { GOPT_O_CLEAR, 0, "c|clear" }, { GOPT_O_PAGER, 0, "p|pager" }, + { GOPT_O_WIDTH, 1, "w|width" }, { GOPT_O_QUIT, 0, "Q|quit" }, { GOPT_O_QUIET, 0, "q|quiet" }, - { GOPT_O_VERBOSE, 0, "v|verbose" }, + { GOPT_O_VERBOSE, 3, "v|verbose" }, + { GOPT_O_DEBUG, 3, "D|d|debug" }, {0,0,0} }; @@ -660,7 +662,7 @@ enumError ScanGOptionsHelper //--- check options - InitializeGOptions(gopt); + InitializeGOptions(gopt,gopt->max_width); int err = 0, test_opt = 0; enumError stat = ERR_OK; @@ -876,7 +878,7 @@ enumError ScanGOptionsHelper case GOPT_IDX_DURATION: par->ptype = GOPT_IDX_DURATION; - ScanDuration(&par->d,optarg,1,SDUMD_M_ALL); break; + ScanDuration(&par->d,optarg,1,SDUMD_M_DEFAULT); break; break; case GOPT_IDX_STRING: @@ -923,8 +925,28 @@ enumError ScanGOptionsHelper case GOPT_O_QUIET: gopt->verbose = gopt->verbose > -1 ? -1 : gopt->verbose - 1; break; + case GOPT_O_VERBOSE: - gopt->verbose = gopt->verbose < 0 ? 0 : gopt->verbose + 1; + if (optarg) + gopt->verbose = str2l(optarg,0,10); + else + gopt->verbose = gopt->verbose < 0 ? 0 : gopt->verbose + 1; + break; + + case GOPT_O_DEBUG: + if (optarg) + gopt->debug = str2l(optarg,0,10); + else + gopt->debug++; + break; + + case GOPT_O_WIDTH: + { + char *end; + int num = str2l(optarg,&end,10); + if ( num > 0 && !*end ) + gopt->width = num < 40 ? 40 : num <= gopt->max_width ? num : gopt->max_width; + } break; case GOPT_O_HELP: gopt->help++; scan_opt |= SGO_PAGER; break; @@ -954,10 +976,15 @@ enumError ScanGOptionsHelper if (test_opt) { - printf("\nOPTIONS [N=%u/%u]: %s\n",go->lopt_used,go->lopt_size,go->sopt); - const struct option *opt; - for ( opt = go->lopt; opt->name; opt++ ) - printf(" %04x %u %s\n", opt->val, opt->has_arg, opt->name ); + printf("\n## %sShort options:%s %s\n## %sLong options (%u/%u):%s\n", + colout->caption, colout->reset, go->sopt, + colout->caption, go->lopt_used, go->lopt_size, colout->reset ); + + for ( const struct option *opt = go->lopt; opt->name; opt++ ) + printf("## %6x %c %s\n", opt->val, + opt->has_arg ? '0'+opt->has_arg : '-', + opt->name ); + putchar('\n'); } char **dest = argv + optind; @@ -1001,7 +1028,7 @@ enumError ScanGOptionsHelper abort: ResetGenericOpt(go); if (stat) - InitializeGOptions(gopt); + InitializeGOptions(gopt,gopt->max_width); return stat; } diff --git a/project/dclib/dclib-option.h b/project/dclib/dclib-option.h index f16dd7b..98fdb9c 100644 --- a/project/dclib/dclib-option.h +++ b/project/dclib/dclib-option.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -46,8 +46,13 @@ struct TCPStream_t; typedef struct GenericOptParm_t { - u32 id; // id of the option, - u8 arg; // 0:no arg, 1:arg, 2:optional arg + u32 id; // id of the option + + u8 arg; // 0: no arguments + // 1: always argument, + // 2: optional argument + // 3: short-opt: no arg / long-opt: optional arg + ccp name; // pipe separated option names } GenericOptParm_t; @@ -85,7 +90,7 @@ void AddGenericOpt ( GenericOpt_t *go, // data structure const GenericOptParm_t *gp, // list to add, list end on name==NULL - bool rm_minus // remove '-' on options for alternatives + bool rm_minus // remove '-' of options for alternatives ); // @@ -100,7 +105,7 @@ typedef enum GOPT_t GOPT_RESERVED_END = 0x02000000, // end of reserved range GOPT_M_INDEX = 0x000000ff, // mask to get the index - GOPT_N_PARAM = 25, // max used index+1 = num of params + GOPT_N_PARAM = 60, // max used index+1 = num of params GOPT_M_VALUE = 0x0003ff00, // mask for GOPT_T_PLUS|GOPT_T_MINUS GOPT_S_VALUE = 8, // value is shifted by this num GOPT_M_TYPE = 0x00fc0000, // mask to isolate option type @@ -108,7 +113,7 @@ typedef enum GOPT_t GOPT_S_TYPE = 18, // type is shifted by this num - //--- parameters by index + //--- parameters by index (sn=signed num, un=unsigned num) GOPT_IDX_NULL = 0, // type undefined @@ -174,15 +179,17 @@ typedef enum GOPT_t //--- named options GOPT_O__BEGIN = 0x100, - GOPT_O_TEST_OPT, // test: print all defined options + GOPT_O_TEST_OPT, // test: print all defined options: --@opt GOPT_O_HELP, // force help GOPT_O_CLEAR, // clear screen -> ScanGOptionsHelperTN() GOPT_O_PAGER, // activate pager -> ScanGOptionsHelperTN() + GOPT_O_WIDTH, // limit terminal width -> ScanGOptionsHelperTN() GOPT_O_QUIT, // quit if command done -> ScanGOptionsHelperTN() GOPT_O_QUIET, // be quiet - GOPT_O_VERBOSE, // be verbose + GOPT_O_VERBOSE, // be verbose, or set by --verbose=# + GOPT_O_DEBUG, // increment debug level, or set by --debug=# GOPT_O__CONTINUE // continue with this value on more options } @@ -239,7 +246,7 @@ GParam_t; typedef enum GetGParam_t { - GGP_NONE, // no param set or param unusable, 'return_val' untouched + GGP_NONE = 0, // no param set or param unusable, 'return_val' is untouched GGP_CONVERT, // param set, but converted (different numeric type) GGP_SIGN, // param returned, but sign maybe converted GGP_OK // original or extended param returned @@ -253,7 +260,7 @@ GetGParam_t GetGParamUINT ( const GParam_t *par, uint *return_val ); GetGParam_t GetGParamS64 ( const GParam_t *par, s64 *return_val ); GetGParam_t GetGParamU64 ( const GParam_t *par, u64 *return_val ); GetGParam_t GetGParamDBL ( const GParam_t *par, double *return_val ); -GetGParam_t GetGParamSTR ( const GParam_t *par, ccp *return_val ); +GetGParam_t GetGParamCCP ( const GParam_t *par, ccp *return_val ); GetGParam_t GetGParamBIT ( const GParam_t *par, u32 *return_val, u32 *return_mask ); ccp PrintGParam ( const GParam_t *par ); @@ -276,10 +283,13 @@ typedef struct GOptions_t int help; // number of GOPT_O_HELP int clear; // number of GOPT_O_CLEAR - int pager; // number of GOPT_O_PAGER, - int quit; // number of GOPT_O_QUIT, - int verbose; // combi of GOPT_O_QUIET & GOPT_O_VERBOSE, + int pager; // number of GOPT_O_PAGER + int quit; // number of GOPT_O_QUIT + int debug; // number of GOPT_O_DEBUG + int verbose; // combi of GOPT_O_QUIET & GOPT_O_VERBOSE + int max_width; // max terminal width + int width; // terminal width //--- generic parameter support @@ -289,10 +299,14 @@ GOptions_t; //----------------------------------------------------------------------------- -static inline void InitializeGOptions ( GOptions_t *go ) +#define GOOD_INFO_MAX_WIDTH 120 + +static inline void InitializeGOptions ( GOptions_t *go, int max_width ) { DASSERT(go); memset(go,0,sizeof(*go)); + go->max_width = max_width; + go->width = max_width < GOOD_INFO_MAX_WIDTH ? max_width : GOOD_INFO_MAX_WIDTH; } static inline const GParam_t * GetGParam ( const GOptions_t *go, uint par_index ) diff --git a/project/dclib/dclib-regex.c b/project/dclib/dclib-regex.c index 5d3d0aa..f879566 100644 --- a/project/dclib/dclib-regex.c +++ b/project/dclib/dclib-regex.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -164,7 +164,7 @@ enumError ScanRegex ( Regex_t *re, bool init_re, ccp regex ) enumError err = ERR_OK; for(;;) { - while ( isspace(*regex) || *regex == ';' ) + while ( isspace((int)*regex) || *regex == ';' ) regex++; if (!*regex) break; diff --git a/project/dclib/dclib-regex.h b/project/dclib/dclib-regex.h index 0a31998..d314b63 100644 --- a/project/dclib/dclib-regex.h +++ b/project/dclib/dclib-regex.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * diff --git a/project/dclib/dclib-shift-jis.c b/project/dclib/dclib-shift-jis.c index fd7d692..affb167 100644 --- a/project/dclib/dclib-shift-jis.c +++ b/project/dclib/dclib-shift-jis.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * diff --git a/project/dclib/dclib-system.h b/project/dclib/dclib-system.h index 6829cb3..7da6e82 100644 --- a/project/dclib/dclib-system.h +++ b/project/dclib/dclib-system.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * diff --git a/project/dclib/dclib-tables.c b/project/dclib/dclib-tables.c index 508d1c0..629e805 100644 --- a/project/dclib/dclib-tables.c +++ b/project/dclib/dclib-tables.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -34,16 +34,34 @@ #define _GNU_SOURCE 1 -//#include <string.h> -//#include <unistd.h> -//#include <time.h> -//#include <stdio.h> -//#include <errno.h> -//#include <sys/time.h> +#include <time.h> +#include <utime.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/time.h> #include "dclib-basics.h" -//#include "dclib-debug.h" -//#include "dclib-utf8.h" +#include "dclib-utf8.h" +#include "dclib-file.h" +#include "dclib-option.h" +#include "dclib-network.h" +#include "dclib-regex.h" +#include "dclib-xdump.h" +#include "dclib-ui.h" + +#ifdef DCLIB_MYSQL + #include "dclib-mysql.h" +#endif + +#if DCLIB_TERMINAL + #include "dclib-terminal.h" +#endif + +#if DCLIB_THREAD + #include "dclib-thread.h" +#endif // /////////////////////////////////////////////////////////////////////////////// @@ -264,7 +282,7 @@ const u16 TableCP1252_80[0x20] = { 0x20ac, 0,0x201a,0x0192, 0x201e,0x2026,0x2020,0x2021, // 80..87 0x02c6,0x2030,0x0160,0x2039, 0x0152, 0,0x017d, 0, // 88..8f - 0,0x2018,0x2019,0x201c, 0x201d,0x2022,0x2013,0x2014, // 90..97 + 0,0x2018,0x2019,0x201c, 0x201d,0x2022,0x2013,0x2014, // 90..97 0x02dc,0x2122,0x0161,0x203a, 0x0153, 0,0x017e,0x0178, // 98..9f }; @@ -412,6 +430,472 @@ const u8 TableAlphabet64[48] = // /////////////////////////////////////////////////////////////////////////////// +/////////////// sizeof_info_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +const sizeof_info_t sizeof_info_linux[] = +{ + SIZEOF_INFO_TITLE("Basic C types") + SIZEOF_INFO_ENTRY(char) + SIZEOF_INFO_ENTRY(wchar_t) + SIZEOF_INFO_ENTRY(short) + SIZEOF_INFO_ENTRY(int) + SIZEOF_INFO_ENTRY(long) + SIZEOF_INFO_ENTRY(long long) + SIZEOF_INFO_ENTRY(float) + SIZEOF_INFO_ENTRY(double) + SIZEOF_INFO_ENTRY(long double) + SIZEOF_INFO_ENTRY(void*) + + SIZEOF_INFO_TITLE("Linux C types") + SIZEOF_INFO_ENTRY(size_t) + SIZEOF_INFO_ENTRY(time_t) + SIZEOF_INFO_ENTRY(struct timeval) + SIZEOF_INFO_ENTRY(struct timespec) + SIZEOF_INFO_ENTRY(struct tm) + SIZEOF_INFO_ENTRY(struct timezone) + SIZEOF_INFO_ENTRY(struct utimbuf) + SIZEOF_INFO_ENTRY(struct stat) + SIZEOF_INFO_ENTRY(fd_set) + + SIZEOF_INFO_TERM() +}; + +/////////////////////////////////////////////////////////////////////////////// + +const sizeof_info_t sizeof_info_dclib[] = +{ + SIZEOF_INFO_TITLE("dcLib basic types") + SIZEOF_INFO_ENTRY(bool) + SIZEOF_INFO_ENTRY(u8) + SIZEOF_INFO_ENTRY(u16) + SIZEOF_INFO_ENTRY(u32) + SIZEOF_INFO_ENTRY(u64) + SIZEOF_INFO_ENTRY(mem_t) + SIZEOF_INFO_ENTRY(exmem_t) + + SIZEOF_INFO_TITLE("dcLib time & timer") + SIZEOF_INFO_ENTRY(u_sec_t) + SIZEOF_INFO_ENTRY(u_msec_t) + SIZEOF_INFO_ENTRY(u_usec_t) + SIZEOF_INFO_ENTRY(u_nsec_t) + SIZEOF_INFO_ENTRY(DayTime_t) + SIZEOF_INFO_ENTRY(CurrentTime_t) + + SIZEOF_INFO_TITLE("dcLib numeric & strings") + SIZEOF_INFO_ENTRY(float3) + SIZEOF_INFO_ENTRY(float3List_t) + SIZEOF_INFO_ENTRY(double3) + SIZEOF_INFO_ENTRY(double3List_t) + SIZEOF_INFO_ENTRY(float34) + SIZEOF_INFO_ENTRY(double34) + SIZEOF_INFO_ENTRY(MatrixD_t) + SIZEOF_INFO_ENTRY(RegexReplace_t) + SIZEOF_INFO_ENTRY(RegexElem_t) + SIZEOF_INFO_ENTRY(Regex_t) + SIZEOF_INFO_ENTRY(dcUnicodeTripel) + SIZEOF_INFO_ENTRY(Escape_t) + + SIZEOF_INFO_TITLE("dcLib buffers") + SIZEOF_INFO_ENTRY(sha1_hash_t) + SIZEOF_INFO_ENTRY(sha1_hex_t) + SIZEOF_INFO_ENTRY(sha1_id_t) + SIZEOF_INFO_ENTRY(uuid_text_t) + SIZEOF_INFO_ENTRY(CircBuf_t) + SIZEOF_INFO_ENTRY(FastBuf_t) + SIZEOF_INFO_ENTRY(ContainerData_t) + SIZEOF_INFO_ENTRY(Container_t) + SIZEOF_INFO_ENTRY(DataBuf_t) + SIZEOF_INFO_ENTRY(GrowBuffer_t) + + SIZEOF_INFO_TITLE("dcLib lists") + SIZEOF_INFO_ENTRY(mem_list_t) + SIZEOF_INFO_ENTRY(exmem_key_t) + SIZEOF_INFO_ENTRY(exmem_list_t) + SIZEOF_INFO_ENTRY(sizeof_info_t) + SIZEOF_INFO_ENTRY(PointerList_t) + SIZEOF_INFO_ENTRY(KeywordTab_t) + SIZEOF_INFO_ENTRY(StringField_t) + SIZEOF_INFO_ENTRY(ParamFieldItem_t) + SIZEOF_INFO_ENTRY(ParamField_t) + SIZEOF_INFO_ENTRY(SplitArg_t) + SIZEOF_INFO_ENTRY(ArgManager_t) + SIZEOF_INFO_ENTRY(CommandList_t) + SIZEOF_INFO_ENTRY(MemMapItem_t) + SIZEOF_INFO_ENTRY(MemMap_t) + SIZEOF_INFO_ENTRY(DynData_t) + SIZEOF_INFO_ENTRY(DynDataList_t) + SIZEOF_INFO_ENTRY(MemPoolChunk_t) + SIZEOF_INFO_ENTRY(MemPool_t) + SIZEOF_INFO_ENTRY(GenericOptParm_t) + SIZEOF_INFO_ENTRY(GenericOpt_t) + SIZEOF_INFO_ENTRY(GParam_t) + SIZEOF_INFO_ENTRY(GOptions_t) + SIZEOF_INFO_ENTRY(InfoOption_t) + SIZEOF_INFO_ENTRY(InfoCommand_t) + SIZEOF_INFO_ENTRY(InfoUI_t) + + SIZEOF_INFO_TITLE("dcLib file") + SIZEOF_INFO_ENTRY(LogFile_t) + SIZEOF_INFO_ENTRY(FileAttrib_t) + SIZEOF_INFO_ENTRY(File_t) + SIZEOF_INFO_ENTRY(MemFile_t) + SIZEOF_INFO_ENTRY(TraceLog_t) + #ifndef __APPLE__ + SIZEOF_INFO_ENTRY(LineBuffer_t) + #endif + SIZEOF_INFO_ENTRY(search_file_t) + SIZEOF_INFO_ENTRY(search_file_list_t) + SIZEOF_INFO_ENTRY(CatchOutput_t) + SIZEOF_INFO_ENTRY(SectionInfo_t) + SIZEOF_INFO_ENTRY(stat_file_count_t) + SIZEOF_INFO_ENTRY(PrintScript_t) + SIZEOF_INFO_ENTRY(RestoreState_t) + SIZEOF_INFO_ENTRY(RestoreStateTab_t) + SIZEOF_INFO_ENTRY(SaveRestoreType_t) + SIZEOF_INFO_ENTRY(SaveRestoreTab_t) + #ifdef DCLIB_MYSQL + SIZEOF_INFO_ENTRY(MySqlStatus_t) + SIZEOF_INFO_ENTRY(MySqlResult_t) + SIZEOF_INFO_ENTRY(MySql_t) + SIZEOF_INFO_ENTRY(MySqlServerStats_t) + #endif + + SIZEOF_INFO_TITLE("dcLib network") + SIZEOF_INFO_ENTRY(ipv4_t) + SIZEOF_INFO_ENTRY(ipv4x_t) + SIZEOF_INFO_ENTRY(ipv6_t) + SIZEOF_INFO_ENTRY(sockaddr_t) + SIZEOF_INFO_ENTRY(sockaddr_in4_t) + SIZEOF_INFO_ENTRY(sockaddr_in6_t) + SIZEOF_INFO_ENTRY(sockaddr_in46_t) + SIZEOF_INFO_ENTRY(sockaddr_un_t) + SIZEOF_INFO_ENTRY(sockaddr_dclib_t) + SIZEOF_INFO_ENTRY(sockaddr_info_t) + SIZEOF_INFO_ENTRY(socket_info_t) + SIZEOF_INFO_ENTRY(FDList_t) + SIZEOF_INFO_ENTRY(SplitIP_t) + SIZEOF_INFO_ENTRY(NamesIP_t) + SIZEOF_INFO_ENTRY(BinIP_t) + SIZEOF_INFO_ENTRY(BinIPItem_t) + SIZEOF_INFO_ENTRY(BinIPList_t) + SIZEOF_INFO_ENTRY(BinIPIterate_t) + SIZEOF_INFO_ENTRY(ManageIP_t) + SIZEOF_INFO_ENTRY(ResolveIP_t) + SIZEOF_INFO_ENTRY(NetworkHost_t) + SIZEOF_INFO_ENTRY(AllowIP4Item_t) + SIZEOF_INFO_ENTRY(AllowIP4_t) + SIZEOF_INFO_ENTRY(ether_head_t) + SIZEOF_INFO_ENTRY(ether_head_vlan_t) + SIZEOF_INFO_ENTRY(arp_head_t) + SIZEOF_INFO_ENTRY(ip4_head_t) + SIZEOF_INFO_ENTRY(udp_head_t) + SIZEOF_INFO_ENTRY(udp_packet_t) + SIZEOF_INFO_ENTRY(tcp_head_t) + SIZEOF_INFO_ENTRY(TransferStats_t) + SIZEOF_INFO_ENTRY(Socket_t) + SIZEOF_INFO_ENTRY(TCPStream_t) + SIZEOF_INFO_ENTRY(TCPHandler_t) + SIZEOF_INFO_ENTRY(CommandTCPInfo_t) + #if defined(SYSTEM_LINUX) || defined(__CYGWIN__) + SIZEOF_INFO_ENTRY(RouteIP4_t) + #endif + + #if DCLIB_TERMINAL + SIZEOF_INFO_TITLE("dcLib terminal & colors") + #else + SIZEOF_INFO_TITLE("dcLib colors") + #endif + SIZEOF_INFO_ENTRY(term_size_t) + SIZEOF_INFO_ENTRY(good_term_width_t) + SIZEOF_INFO_ENTRY(TermColorId_t) + SIZEOF_INFO_ENTRY(ColorSet_t) + SIZEOF_INFO_ENTRY(ColorView_t) + SIZEOF_INFO_ENTRY(SavedStdFiles_t) + #if DCLIB_TERMINAL + SIZEOF_INFO_ENTRY(History_t) + SIZEOF_INFO_ENTRY(TelnetRepeat_t) + SIZEOF_INFO_ENTRY(TelnetParam_t) + SIZEOF_INFO_ENTRY(TelnetTCPInfo_t) + SIZEOF_INFO_ENTRY(TelnetClient_t) + SIZEOF_INFO_ENTRY(TerminalKey_t) + SIZEOF_INFO_ENTRY(TerminalInfo_t) + SIZEOF_INFO_ENTRY(TerminalNameList_t) + SIZEOF_INFO_ENTRY(Keyboard_t) + #endif + + #if DCLIB_THREAD + SIZEOF_INFO_TITLE("dcLib threads") + SIZEOF_INFO_ENTRY(WatchdogThread_t) + #endif + + SIZEOF_INFO_TITLE("dcLib statistics") + SIZEOF_INFO_ENTRY(UsageParam_t) + SIZEOF_INFO_ENTRY(UsageCountEntry_t) + SIZEOF_INFO_ENTRY(UsageCount_t) + SIZEOF_INFO_ENTRY(UsageDurationEntry_t) + SIZEOF_INFO_ENTRY(UsageDuration_t) + SIZEOF_INFO_ENTRY(CpuUsageEntry_t) + SIZEOF_INFO_ENTRY(CpuUsage_t) + SIZEOF_INFO_ENTRY(UsageCtrl_t) + SIZEOF_INFO_ENTRY(usage_count_mgr) + SIZEOF_INFO_ENTRY(CpuStatus_t) + SIZEOF_INFO_ENTRY(MemoryStatus_t) + + SIZEOF_INFO_TITLE("dcLib misc") + SIZEOF_INFO_ENTRY(ProgInfo_t) + SIZEOF_INFO_ENTRY(IntervalInfo_t) + SIZEOF_INFO_ENTRY(MultiColumn_t) + SIZEOF_INFO_ENTRY(ScanAddr_t) + SIZEOF_INFO_ENTRY(ResizeElement_t) + SIZEOF_INFO_ENTRY(ResizeHelper_t) + SIZEOF_INFO_ENTRY(XDump_t) + + SIZEOF_INFO_TERM() +}; + +/////////////////////////////////////////////////////////////////////////////// + +const sizeof_info_t *sizeof_info_default[] = +{ + sizeof_info_linux, + sizeof_info_dclib, + 0 +}; + +PointerList_t SizeofInfoMgr = {0}; + +/////////////////////////////////////////////////////////////////////////////// + +static int compare_sizeof_size + ( const sizeof_info_t *a, const sizeof_info_t *b ) +{ + DASSERT( a && b ); + const int stat = a->size - b->size; + return stat ? stat : strcasecmp(a->name,b->name); +} + +//----------------------------------------------------------------------------- + +static int compare_sizeof_name + ( const sizeof_info_t *a, const sizeof_info_t *b ) +{ + DASSERT( a && b ); + return strcasecmp(a->name,b->name); +} + +/////////////////////////////////////////////////////////////////////////////// + +void ListSizeofInfo +( + const PrintMode_t *p_pm, // NULL or print mode + const sizeof_info_t **si_list, // list of list of entries + ArgManager_t *p_filter, // NULL or filter arguments, LOUP_LOWER recommended + sizeof_info_order_t order // kind of order +) +{ + if ( !si_list || !*si_list ) + return; + + + //--- setup + + PrintMode_t pm = {0}; + if (p_pm) + pm = *p_pm; + SetupPrintMode(&pm); + + if (!si_list) + { + si_list = GetSizeofInfoMgrList(); + if (!si_list) + si_list = sizeof_info_default; + } + + int n_tabs = 0, n_records = 0, n_elem = 0, n_cat = 0, str_size = 0;; + for ( const sizeof_info_t **si_ptr = si_list; *si_ptr; si_ptr++ ) + { + n_tabs++; + for ( const sizeof_info_t *si = *si_ptr; si->size != -9; si++ ) + { + n_records++; + if ( si->size >= 0 ) + n_elem++; + else if ( si->size == -1 ) + n_cat++; + if (si->name) + str_size += strlen(si->name) + 1; + } + } + + if ( pm.debug > 0 ) + fprintf(pm.flog,"\n%s> %u source list%s with %u record%s, %u categorie%s" + " and %u element%s, %zu bytes total%s%s", + pm.clog->info, + n_tabs, n_tabs == 1 ? "" : "s", + n_records, n_records == 1 ? "" : "s", + n_cat, n_cat == 1 ? "" : "s", + n_elem, n_elem == 1 ? "" : "s", + (n_records+n_tabs) * sizeof(sizeof_info_t) + str_size, + pm.clog->reset, pm.eol ); + + ArgManager_t my_filter = {0}, *filter = &my_filter; + + if (p_filter) + { + if ( p_filter->force_case == LOUP_LOWER ) + filter = p_filter; + else + { + for ( int i = 0; i < p_filter->argc; i++ ) + AppendArgManager(&my_filter,p_filter->argv[i],0,false); + + for ( int i = 0; i < my_filter.argc; i++ ) + { + char *arg = my_filter.argv[i]; + StringLowerS(arg,strlen(arg)+1,arg); + } + } + } + + sizeof_info_t *list = 0, *list_end = 0; + if (order) + list_end = list = MALLOC( n_elem * sizeof(*list) ); + + + //--- get field widths + + int max_size = 0; + for ( const sizeof_info_t **si_ptr = si_list; *si_ptr; si_ptr++ ) + { + for ( const sizeof_info_t *si = *si_ptr; si->size != -9; si++ ) + { + if ( max_size < si->size && CheckFilterArgManager(filter,si->name) ) + max_size = si->size; + } + } + + char buf[100]; + const int fw_hex = snprintf(buf,sizeof(buf),"%#x",max_size); + const int fw_dec = snprintf(buf,sizeof(buf),"%u",max_size); + + + //--- print or collect + + ccp head = 0; + int n_head = 0, n_sizeof = 0; + + for ( const sizeof_info_t **si_ptr = si_list; *si_ptr; si_ptr++ ) + { + for ( const sizeof_info_t *si = *si_ptr; si->size != -9; si++ ) + { + if ( si->size >= 0 ) + { + if (CheckFilterArgManager(filter,si->name)) + { + n_sizeof++; + if (order) + *list_end++ = *si; + else + { + if (head) + { + n_head++; + fprintf(pm.fout,"\n%s%s%s\n",pm.cout->caption,head,pm.cout->reset); + head = 0; + } + fprintf(pm.fout," %#*x = %*u : %s\n", + fw_hex, si->size, fw_dec, si->size, si->name ); + } + } + } + else if ( si->size == -1 ) + head = si->name; + else if ( si->size == -2 ) + putchar('\n'); + } + } + + + //--- print ordered list + + if (order) + { + putchar('\n'); + if ( n_sizeof > 1 ) + { + if ( order == SIZEOF_ORDER_NAME ) + qsort(list,n_sizeof,sizeof(*list),(qsort_func)compare_sizeof_name); + else + qsort(list,n_sizeof,sizeof(*list),(qsort_func)compare_sizeof_size); + } + + ccp prev = ""; + for ( const sizeof_info_t *ptr = list; ptr < list_end; ptr++ ) + { + if (!strcmp(prev,ptr->name)) + fprintf(pm.fout,"%s %#*x = %*u : %s%s\n", + pm.cout->warn, fw_hex, ptr->size, + fw_dec, ptr->size, ptr->name, pm.cout->reset ); + else + { + fprintf(pm.fout," %#*x = %*u : %s\n", + fw_hex, ptr->size, fw_dec, ptr->size, ptr->name ); + prev = ptr->name; + } + } + } + + + //--- terminate + + ResetArgManager(&my_filter); + + if ( pm.debug > 0 ) + { + putchar('\n'); + if (!n_sizeof) + fprintf(pm.flog,"%s> No elements printed.%s\n",pm.cout->info,pm.cout->reset); + else + { + fputs(pm.cout->info,stdout); + fputs("> ",stdout); + if (n_head) + fprintf(pm.flog,"%u head line%s and ", n_head, n_head == 1 ? "" : "s" ); + + if ( n_sizeof < n_elem ) + fprintf(pm.flog,"%u of %u elements printed.%s\n", + n_sizeof, n_elem, pm.cout->reset ); + else + fprintf(pm.flog,"%u element%s printed.%s\n", + n_sizeof, n_sizeof == 1 ? "" : "s", + pm.cout->reset ); + } + } + + putchar('\n'); + FREE(list); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// misc /////////////// +/////////////////////////////////////////////////////////////////////////////// + +const IntervalInfo_t interval_info[] = +{ + { NSEC_PER_SEC, USEC_PER_SEC, "Second" }, + { NSEC_PER_MIN, USEC_PER_MIN, "Minute" }, + { NSEC_PER_HOUR, USEC_PER_HOUR, "Hour" }, + { NSEC_PER_DAY, USEC_PER_DAY, "Day" }, + { NSEC_PER_WEEK, USEC_PER_WEEK, "Week" }, + { NSEC_PER_MONTH, USEC_PER_MONTH, "Month" }, + { NSEC_PER_YEAR, USEC_PER_YEAR, "Year" }, + { M1(u_nsec_t), M1(u_usec_t), "*" }, +}; + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// END /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/dclib-types.h b/project/dclib/dclib-types.h index 41ffbf9..7818bc0 100644 --- a/project/dclib/dclib-types.h +++ b/project/dclib/dclib-types.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -41,6 +41,7 @@ #include <limits.h> #include <stdlib.h> #include <stdio.h> +#include <stdint.h> #include <ctype.h> #ifndef WIN_DCLIB @@ -122,7 +123,7 @@ __attribute__ ((packed)) dcEndian_t; #define PiB (1024ull*1024*1024*1024*1024) #define EiB (1024ull*1024*1024*1024*1024*1024) -// specal '-1' support +// special '-1' support #define M1(a) ( (typeof(a))~0 ) #define IS_M1(a) ( (a) == (typeof(a))~0 ) @@ -340,38 +341,44 @@ typedef float float32; // float as 32 bit binary data, endian is file dependent /////////////////////////////////////////////////////////////////////////////// -#define U8_MIN (0) -#define U8_MAX (0xff) -#define S8_MIN (-0x80) -#define S8_MAX (0x7f) +#define U8_MIN (0u) +#define U8_MAX UINT8_MAX +#define S8_MIN INT8_MIN +#define S8_MAX INT8_MAX -#define U16_MIN (0) -#define U16_MAX (0xffff) -#define S16_MIN (-0x8000) -#define S16_MAX (0x7fff) +#define U16_MIN (0u) +#define U16_MAX UINT16_MAX +#define S16_MIN INT16_MIN +#define S16_MAX INT16_MAX -#define U32_MIN (0u) -#define U32_MAX (0xffffffffu) -#define S32_MIN (-0x80000000) -#define S32_MAX (0x7fffffff) +#define U32_MIN (0u) +#define U32_MAX UINT32_MAX +#define S32_MIN INT32_MIN +#define S32_MAX INT32_MAX -#define U64_MIN (0ull) -#define U64_MAX (0xffffffffffffffffull) -#define S64_MIN (-0x8000000000000000ll) -#define S64_MAX (0x7fffffffffffffffll) +#define U64_MIN (0ull) +#define U64_MAX UINT64_MAX +#define S64_MIN INT64_MIN +#define S64_MAX INT64_MAX /////////////////////////////////////////////////////////////////////////////// #ifndef DCLIB_BASIC_TYPES #define DCLIB_BASIC_TYPES 1 - typedef unsigned char uchar; - typedef unsigned int uint; - typedef unsigned long ulong; - typedef const void * cvp; - typedef const char * ccp; - typedef const uchar * cucp; + typedef unsigned char uchar; + typedef unsigned int uint; + typedef unsigned long ulong; + typedef const void * cvp; + typedef const void ** cvpp; + typedef const char * ccp; + typedef const char ** ccpp; + typedef const uchar * cucp; + typedef const uchar ** cucpp; #endif +struct mem_t; +typedef struct mem_t mem_t; + // [[sha1_hash_t]] [[sha1_hex_t]] [[sha1_id_t]] typedef u8 sha1_hash_t[20]; typedef char sha1_hex_t[41]; // 40 chars + NULL @@ -386,6 +393,84 @@ typedef int (*qsort_r_func)( const void *, const void *, void * ); // /////////////////////////////////////////////////////////////////////////////// +/////////////// sockaddr + IPv* support /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[sockaddr_t]] [[sockaddr_in_t]] +// [[sockaddr_in4_t]] [[sockaddr_in6_t]] [[sockaddr_un_t]] + +typedef struct sockaddr sockaddr_t; +typedef struct sockaddr_in sockaddr_in_t; +typedef struct sockaddr_in sockaddr_in4_t; +typedef struct sockaddr_in6 sockaddr_in6_t; +typedef struct sockaddr_un sockaddr_un_t; + +typedef struct sockaddr_in46_t sockaddr_in46_t; +typedef struct sockaddr_dclib_t sockaddr_dclib_t; + +/////////////////////////////////////////////////////////////////////////////// +// [[ipv4_t]] [[ipv4x_t]] [[ipv6_t]] + +typedef u32 ipv4_t; + +typedef struct ipv4x_t +{ + union + { + u8 v8[4]; + u16 v16[2]; + ipv4_t ip4; + }; +} +__attribute__ ((packed)) ipv4x_t; + +typedef struct ipv6_t +{ + union + { + u8 v8[16]; + u16 v16[8]; + u32 v32[4]; + u64 v64[2]; + }; +} +__attribute__ ((packed)) ipv6_t; + +//----------------------------------------------------------------------------- +// [[IpMode_t]] + +typedef enum IpMode_t +{ + // flags + IPVF_IPV6 = 1, // IPv6 only/first, otherwise IPv4 + IPVF_BOTH = 2, // try both variants (IPv4+IPv6) + + IPV4_ONLY = 0, // resolve only a IPv4 address + IPV6_ONLY = IPVF_IPV6, // resolve only a IPv6 address + IPV4_FIRST = IPVF_BOTH, // resolve a IPv4 first, and a IPv6 as fallback + IPV6_FIRST = IPVF_BOTH|IPVF_IPV6, // resolve a IPv6 first, and a IPv4 as fallback +} +IpMode_t; + +ccp GetIpModeName ( IpMode_t ipm ); + +//----------------------------------------------------------------------------- + +ipv4_t GetIP4Mask ( int bits ); +ipv6_t GetIP6Mask ( int bits ); + +int GetBitsByMask4 ( ipv4_t ip4_nbo ); +int GetBitsByMask6 ( ipv6_t ip6_nbo ); +int GetBitsBySA ( sockaddr_t *sa, int return_on_error ); + +static inline int GetBitsByIN ( sockaddr_in_t *sa, int return_on_error ) + { return GetBitsBySA((sockaddr_t*)sa,return_on_error); } +static inline int GetBitsByIN4 ( sockaddr_in4_t *sa, int return_on_error ) + { return GetBitsBySA((sockaddr_t*)sa,return_on_error); } +static inline int GetBitsByIN6 ( sockaddr_in6_t *sa, int return_on_error ) + { return GetBitsBySA((sockaddr_t*)sa,return_on_error); } + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// some structs /////////////// /////////////////////////////////////////////////////////////////////////////// // [[KeywordTab_t]] diff --git a/project/dclib/dclib-ui.c b/project/dclib/dclib-ui.c index ab75d67..b477d74 100644 --- a/project/dclib/dclib-ui.c +++ b/project/dclib/dclib-ui.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -256,6 +256,19 @@ enumError CheckEnvOptions ( ccp varname, check_opt_func func ) TRACE("env[%s] = %s\n",varname,env); + #if 1 // [[new]] with ArgManager_t + + ArgManager_t am = {0}; + AppendArgManager(&am,ProgInfo.progname,0,false); + ScanQuotedArgManager(&am,env,true); + #ifdef DEBUG + for ( int i = 0; i < am.argc; i++ ) + printf(" [%02u] |%s|\n",i,am.argv[i]); + #endif + enumError stat = func(am.argc,am.argv,true); + + #else // [[old]] + const int envlen = strlen(env); char * buf = MALLOC(envlen+1); char * dest = buf; @@ -274,7 +287,7 @@ enumError CheckEnvOptions ( ccp varname, check_opt_func func ) while ( *(u8*)src > ' ' ) *dest++ = *src++; *dest++ = 0; - ASSERT( dest <= buf+envlen+1 ); + DASSERT( dest <= buf+envlen+1 ); } TRACE("argc = %d\n",argc); @@ -290,18 +303,19 @@ enumError CheckEnvOptions ( ccp varname, check_opt_func func ) while (*dest) dest++; dest++; - ASSERT( dest <= buf+envlen+1 ); + DASSERT( dest <= buf+envlen+1 ); } enumError stat = func(argc,argv,true); + + #endif + + // don't free() because of possible pointers into argv[] + if (stat) fprintf(stderr, "Error while scanning the environment variable '%s'\n",varname); - // don't free() because it's possible that there are pointers to arguments - //FREE(argv); - //FREE(buf); - return stat; } @@ -580,7 +594,8 @@ static void print_help_options GetTextMode(colmode,TTM_RESET) ); } - const int fw = GetTermWidth(80,40) - 1; +// const int fw = GetTermWidth(80,40) - 1; + const int fw = GetGoodTermWidth(0,false) - 1; const InfoOption_t *io_beg = iu->opt_info + beg_index; const InfoOption_t *io_end = iu->opt_info + end_index; @@ -704,7 +719,8 @@ void PrintHelpCommands } fprintf(f,"\n%*s%sCommands:%s\n\n", indent,"", col_head, col_reset ); - const int fw = GetTermWidth(80,40) - 1; +// const int fw = GetTermWidth(80,40) - 1; + const int fw = GetGoodTermWidth(0,false) - 1; int fw1 = 0, fw2 = 0; const InfoCommand_t * ic; @@ -836,7 +852,8 @@ void PrintHelpCmd cmd = 0; const InfoCommand_t * ic = iu->cmd_info + cmd; - const int fw = GetTermWidth(80,40) - 1; +// const int fw = GetTermWidth(80,40) - 1; + const int fw = GetGoodTermWidth(0,false) - 1; uint col_len; ccp col_head, col_reset; diff --git a/project/dclib/dclib-ui.h b/project/dclib/dclib-ui.h index 42171d9..cc7f327 100644 --- a/project/dclib/dclib-ui.h +++ b/project/dclib/dclib-ui.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * diff --git a/project/dclib/dclib-utf8.c b/project/dclib/dclib-utf8.c index 29a7f81..1ad06ce 100644 --- a/project/dclib/dclib-utf8.c +++ b/project/dclib/dclib-utf8.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -108,7 +108,7 @@ int GetUTF8CharLength ( u32 code ) char * NextUTF8Char ( ccp ptr ) { - // go to next next UTF8 character + // goto next UTF8 character switch (CheckUTF8Mode(*ptr)) { @@ -144,7 +144,7 @@ char * NextUTF8Char ( ccp ptr ) char * NextUTF8CharE( ccp ptr, ccp end ) { - // go to next next UTF8 character + // goto next UTF8 character if ( ptr >= end ) return (char*)end; @@ -181,6 +181,20 @@ char * NextUTF8CharE( ccp ptr, ccp end ) /////////////////////////////////////////////////////////////////////////////// +char * NextEUTF8Char ( ccp ptr ) +{ + return NextUTF8Char(SkipEscapes(ptr)); +} + +//----------------------------------------------------------------------------- + +char * NextEUTF8CharE ( ccp ptr, ccp end ) +{ + return NextUTF8CharE(SkipEscapesE(ptr,end),end); +} + +/////////////////////////////////////////////////////////////////////////////// + char * PrevUTF8Char ( ccp str ) { // go to the previous UTC character @@ -265,6 +279,82 @@ char * PrevUTF8CharB ( ccp str, ccp begin ) /////////////////////////////////////////////////////////////////////////////// +char * SkipUTF8Char ( ccp str, int skip ) +{ + if (str) + { + if ( skip < 0 ) + skip += ScanUTF8Length(str); + while ( skip-- > 0 ) + { + ccp next = NextUTF8Char(str); + if ( str == next ) + break; + str = next; + } + } + return (char*)str; +} + +//----------------------------------------------------------------------------- + +char * SkipUTF8CharE ( ccp str, ccp end, int skip ) +{ + if (str) + { + if ( skip < 0 ) + skip += ScanUTF8LengthE(str,end); + while ( skip-- > 0 ) + { + ccp next = NextUTF8CharE(str,end); + if ( str == next ) + break; + str = next; + } + } + return (char*)str; +} + +//----------------------------------------------------------------------------- + +char * SkipEUTF8Char ( ccp str, int skip ) +{ + if (str) + { + if ( skip < 0 ) + skip += ScanEUTF8Length(str); + while ( skip-- > 0 ) + { + ccp next = NextEUTF8Char(str); + if ( str == next ) + break; + str = next; + } + } + return (char*)str; +} + +//----------------------------------------------------------------------------- + +char * SkipEUTF8CharE ( ccp str, ccp end, int skip ) +{ + if (str) + { + if ( skip < 0 ) + skip += ScanEUTF8LengthE(str,end); + while ( skip-- > 0 ) + { + ccp next = NextEUTF8CharE(str,end); + if ( str == next ) + break; + str = next; + } + } + return (char*)str; +} + +/////////////////////////////////////////////////////////////////////////////// + u32 GetUTF8Char ( ccp str ) { // fast scan of a UTF8 char -> ignore errors in continuation bytes @@ -698,12 +788,57 @@ u32 ScanUTF8AnsiCharE ( ccp * p_str, ccp end ) /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -int ScanUTF8Length ( ccp str, ccp end ) +int ScanUTF8Length ( ccp str ) { int count = 0; - ccp ptr = str; - if (end) + if (str) + { + ccp ptr = str; + for(;;) + { + const char ch = *ptr++; + if (!ch) + break; + switch (CheckUTF8Mode(ch)) + { + case DC_UTF8_2CHAR: + if ( CheckUTF8Mode(*ptr) == DC_UTF8_CONT_ANY ) + ptr++; + break; + + case DC_UTF8_3CHAR: + if ( CheckUTF8Mode(ptr[0]) == DC_UTF8_CONT_ANY + && CheckUTF8Mode(ptr[1]) == DC_UTF8_CONT_ANY ) + ptr += 2; + break; + + case DC_UTF8_4CHAR: + if ( CheckUTF8Mode(ptr[0]) == DC_UTF8_CONT_ANY + && CheckUTF8Mode(ptr[1]) == DC_UTF8_CONT_ANY + && CheckUTF8Mode(ptr[2]) == DC_UTF8_CONT_ANY ) + ptr += 3; + break; + + default: + break; + } + count++; + } + } + return count; +} + +//----------------------------------------------------------------------------- + +int ScanUTF8LengthE ( ccp str, ccp end ) +{ + if (!end) + return ScanUTF8Length(str); + + int count = 0; + if (str) { + ccp ptr = str; while ( ptr < end ) { const char ch = *ptr++; @@ -733,13 +868,78 @@ int ScanUTF8Length ( ccp str, ccp end ) count++; } } - else + return count; +} + +//----------------------------------------------------------------------------- + +int ScanEUTF8Length ( ccp str ) +{ + int count = 0; + if (str) { + ccp ptr = str; for(;;) { const char ch = *ptr++; if (!ch) break; + + if ( ch == '\e' ) + { + ptr = SkipEscapes(ptr-1); + continue; + } + + switch (CheckUTF8Mode(ch)) + { + case DC_UTF8_2CHAR: + if ( CheckUTF8Mode(*ptr) == DC_UTF8_CONT_ANY ) + ptr++; + break; + + case DC_UTF8_3CHAR: + if ( CheckUTF8Mode(ptr[0]) == DC_UTF8_CONT_ANY + && CheckUTF8Mode(ptr[1]) == DC_UTF8_CONT_ANY ) + ptr += 2; + break; + + case DC_UTF8_4CHAR: + if ( CheckUTF8Mode(ptr[0]) == DC_UTF8_CONT_ANY + && CheckUTF8Mode(ptr[1]) == DC_UTF8_CONT_ANY + && CheckUTF8Mode(ptr[2]) == DC_UTF8_CONT_ANY ) + ptr += 3; + break; + + default: + break; + } + count++; + } + } + return count; +} + +//----------------------------------------------------------------------------- + +int ScanEUTF8LengthE ( ccp str, ccp end ) +{ + if (!end) + return ScanEUTF8Length(str); + + int count = 0; + if (str) + { + ccp ptr = str; + while ( ptr < end ) + { + const char ch = *ptr++; + if ( ch == '\e' ) + { + ptr = SkipEscapesE(ptr-1,end); + continue; + } + switch (CheckUTF8Mode(ch)) { case DC_UTF8_2CHAR: @@ -775,7 +975,7 @@ int ScanUTF8Length ( ccp str, ccp end ) int CalcUTF8PrintFW ( ccp str, ccp end, uint wanted_fw ) { const uint bytecount = end ? end - str : strlen(str); - const uint utf8len = ScanUTF8Length(str,end); + const uint utf8len = ScanUTF8LengthE(str,end); return utf8len < wanted_fw ? wanted_fw - utf8len + bytecount : bytecount; @@ -853,6 +1053,74 @@ char * PrintUTF8CharToCircBuf ( u32 code ) return buf; } +/////////////////////////////////////////////////////////////////////////////// + +ccp AlignUTF8ToCircBuf ( ccp str, int fw, int prec ) +{ + uint len = ScanUTF8Length(str); + if ( prec >= 0 && len > prec ) + len = prec; + + const int align_left = fw < 0; + if ( align_left) + fw = -fw; + if ( fw < len ) + fw = len; + int spaces = fw - len; + + ccp end = SkipUTF8Char(str,len); + const int copy_len = end - str; + + char *buf = GetCircBuf(copy_len+spaces+1); + DASSERT(buf); + if (align_left) + { + memcpy(buf,str,copy_len); + memset(buf+copy_len,' ',spaces); + } + else + { + memset(buf,' ',spaces); + memcpy(buf+spaces,str,copy_len); + } + buf[copy_len+spaces] = 0; + return buf; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp AlignEUTF8ToCircBuf ( ccp str, int fw, int prec ) +{ + uint len = ScanEUTF8Length(str); + if ( prec >= 0 && len > prec ) + len = prec; + + const int align_left = fw < 0; + if ( align_left) + fw = -fw; + if ( fw < len ) + fw = len; + int spaces = fw - len; + + ccp end = SkipEUTF8Char(str,len); + const int copy_len = end - str; + + char *buf = GetCircBuf(copy_len+spaces+1); + DASSERT(buf); + if (align_left) + { + memcpy(buf,str,copy_len); + memset(buf+copy_len,' ',spaces); + } + else + { + memset(buf,' ',spaces); + memcpy(buf+spaces,str,copy_len); + } + buf[copy_len+spaces] = 0; + return buf; +} + // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/dclib-utf8.h b/project/dclib/dclib-utf8.h index adea8dc..c4d9380 100644 --- a/project/dclib/dclib-utf8.h +++ b/project/dclib/dclib-utf8.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -89,24 +89,56 @@ static inline dcUTF8Mode CheckUTF8Mode ( unsigned char ch ) { return (dcUTF8Mode)TableUTF8Mode[ch]; } int GetUTF8CharLength ( u32 code ); -char * NextUTF8Char ( ccp str ); +char * NextUTF8Char ( ccp str ); char * NextUTF8CharE ( ccp str, ccp end ); -char * PrevUTF8Char ( ccp str ); +char * PrevUTF8Char ( ccp str ); char * PrevUTF8CharB ( ccp str, ccp begin ); -u32 GetUTF8Char ( ccp str ); -u32 ScanUTF8Char ( ccp * str ); -u32 ScanUTF8CharE ( ccp * str, ccp end ); -u32 ScanUTF8CharInc ( ccp * str ); -u32 ScanUTF8CharIncE ( ccp * str, ccp end ); -u32 GetUTF8AnsiChar ( ccp str ); -u32 ScanUTF8AnsiChar ( ccp * str ); +char * SkipUTF8Char ( ccp str, int skip ); +char * SkipUTF8CharE ( ccp str, ccp end, int skip ); + +u32 GetUTF8Char ( ccp str ); +u32 ScanUTF8Char ( ccp * str ); +u32 ScanUTF8CharE ( ccp * str, ccp end ); +u32 ScanUTF8CharInc ( ccp * str ); +u32 ScanUTF8CharIncE ( ccp * str, ccp end ); +u32 GetUTF8AnsiChar ( ccp str ); +u32 ScanUTF8AnsiChar ( ccp * str ); u32 ScanUTF8AnsiCharE ( ccp * str, ccp end ); -int ScanUTF8Length ( ccp str, ccp end ); -int CalcUTF8PrintFW ( ccp str, ccp end, uint wanted_fw ); +int ScanUTF8Length ( ccp str ); +int ScanUTF8LengthE ( ccp str, ccp end ); +int CalcUTF8PrintFW ( ccp str, ccp end, uint wanted_fw ); char * PrintUTF8Char ( char * buf, u32 code ); char * PrintUTF8CharToCircBuf ( u32 code ); +ccp AlignUTF8ToCircBuf ( ccp str, int fw, int prec ); + +/////////////////////////////////////////////////////////////////////////////// +// special variants, that ignore known escape seqeuences + +char * NextEUTF8Char ( ccp str ); +char * NextEUTF8CharE ( ccp str, ccp end ); +char * SkipEUTF8Char ( ccp str, int skip ); +char * SkipEUTF8CharE ( ccp str, ccp end, int skip ); +int ScanEUTF8Length ( ccp str ); +int ScanEUTF8LengthE ( ccp str, ccp end ); + +ccp AlignEUTF8ToCircBuf ( ccp str, int fw, int prec ); + +/////////////////////////////////////////////////////////////////////////////// + +static inline int strlen8 ( ccp str ) + { return ScanUTF8Length(str); } + +static inline int strlen8e ( ccp str, ccp end ) + { return ScanUTF8LengthE(str,end); } + +static inline int strlene8 ( ccp str ) + { return ScanEUTF8Length(str); } + +static inline int strlene8e ( ccp str, ccp end ) + { return ScanEUTF8LengthE(str,end); } + /////////////////////////////////////////////////////////////////////////////// typedef struct dcUnicodeTripel diff --git a/project/dclib/dclib-vector.c b/project/dclib/dclib-vector.c index 233e7ef..af18888 100644 --- a/project/dclib/dclib-vector.c +++ b/project/dclib/dclib-vector.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * diff --git a/project/dclib/dclib-xdump.c b/project/dclib/dclib-xdump.c index df2f7f9..f4175b0 100644 --- a/project/dclib/dclib-xdump.c +++ b/project/dclib/dclib-xdump.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * diff --git a/project/dclib/dclib-xdump.h b/project/dclib/dclib-xdump.h index 06f602b..0cf9938 100644 --- a/project/dclib/dclib-xdump.h +++ b/project/dclib/dclib-xdump.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * diff --git a/project/dclib/lib-bmg.c b/project/dclib/lib-bmg.c index c1d24ce..0540243 100644 --- a/project/dclib/lib-bmg.c +++ b/project/dclib/lib-bmg.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -500,7 +500,7 @@ uint PrintString16BMG xd.indent = 2; xd.assumed_size = mem.len; XDiff( &xd, buf,dest-buf,true, mem.ptr,mem.len,true, 5,false ); - } + } ResetFastBuf(&fb.b); #endif @@ -542,7 +542,7 @@ uint PrintFastBuf16BMG char buf[1300]; char *dest = buf; - char *dest_term = dest + sizeof(buf) - 1; + char *dest_term = dest + sizeof(buf) - 1; char *dest_end = dest_term - 270; // escape sequence with 256 bytes possible char *last_u = 0; @@ -6442,6 +6442,36 @@ void DumpCtBMG ( FILE *f, int indent, ct_bmg_t *ctb ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// sizeof_info_t: bmg /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[sizeof_info_bmg]] + +const sizeof_info_t sizeof_info_bmg[] = +{ + SIZEOF_INFO_TITLE("BMG") + SIZEOF_INFO_ENTRY(bmg_range_t) + SIZEOF_INFO_ENTRY(bmg_section_t) + SIZEOF_INFO_ENTRY(bmg_header_t) + SIZEOF_INFO_ENTRY(bmg_inf_item_t) + SIZEOF_INFO_ENTRY(bmg_inf_t) + SIZEOF_INFO_ENTRY(bmg_dat_t) + SIZEOF_INFO_ENTRY(bmg_mid_t) + SIZEOF_INFO_ENTRY(bmg_flw_t) + SIZEOF_INFO_ENTRY(bmg_fli_t) + SIZEOF_INFO_ENTRY(bmg_sect_info_t) + SIZEOF_INFO_ENTRY(bmg_sect_list_t) + SIZEOF_INFO_ENTRY(bmg_raw_section_t) + SIZEOF_INFO_ENTRY(bmg_item_t) + SIZEOF_INFO_ENTRY(bmg_t) + SIZEOF_INFO_ENTRY(bmg_create_t) + SIZEOF_INFO_ENTRY(bmg_scan_mid_t) + SIZEOF_INFO_ENTRY(ct_bmg_t) + + SIZEOF_INFO_TERM() +}; + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// E N D /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/lib-bmg.h b/project/dclib/lib-bmg.h index 46cccac..98d3d9e 100644 --- a/project/dclib/lib-bmg.h +++ b/project/dclib/lib-bmg.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -70,7 +70,6 @@ typedef u16 bmg_slot_t; // type of slot typedef struct bmg_t bmg_t; - // /////////////////////////////////////////////////////////////////////////////// /////////////// MKW specific consts /////////////// @@ -259,6 +258,8 @@ extern u8 bmg_def_attrib[BMG_ATTRIB_SIZE]; // 2: string param extern const KeywordTab_t PatchKeysBMG[]; +extern const sizeof_info_t sizeof_info_bmg[]; + // /////////////////////////////////////////////////////////////////////////////// /////////////// CT/LE support /////////////// @@ -920,7 +921,7 @@ typedef struct bmg_create_t bmg_t *bmg; // current bmg const endian_func_t // endian functions, never NULL *endian; // init by bmg->endian, overridden by opt_bmg_endian - + FastBuf_t inf; // INF1 data FastBuf_t dat; // DAT1 data diff --git a/project/dclib/lib-dol.c b/project/dclib/lib-dol.c index d671193..94b73bb 100644 --- a/project/dclib/lib-dol.c +++ b/project/dclib/lib-dol.c @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -1201,5 +1201,26 @@ void ResetWCH ( wch_control_t * wc ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// sizeof_info_t: dol /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[sizeof_info_dol]] + +const sizeof_info_t sizeof_info_dol[] = +{ + SIZEOF_INFO_TITLE("DOL") + SIZEOF_INFO_ENTRY(dol_header_t) + SIZEOF_INFO_ENTRY(dol_sect_info_t) + SIZEOF_INFO_ENTRY(dol_sect_select_t) + SIZEOF_INFO_ENTRY(dol_sect_addr_t) + SIZEOF_INFO_ENTRY(gch_header_t) + SIZEOF_INFO_ENTRY(wch_segment_t) + SIZEOF_INFO_ENTRY(wch_header_t) + SIZEOF_INFO_ENTRY(wch_control_t) + + SIZEOF_INFO_TERM() +}; + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// E N D /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/lib-dol.h b/project/dclib/lib-dol.h index 0f03e25..c1d8b7b 100644 --- a/project/dclib/lib-dol.h +++ b/project/dclib/lib-dol.h @@ -14,16 +14,16 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * - * This program is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * This program is distributed in the hope that it will be useful, * + * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -123,7 +123,7 @@ typedef struct dol_sect_addr_t { //--- source info u32 addr; // address of data - u32 size; // size of data + u32 size; // size of data //--- search info int section; // section index, <0: invalid @@ -149,6 +149,8 @@ static inline ccp GetDolSectionName ( uint section ) return section < DOL_NN_SECTIONS ? dol_section_name[section] : 0; } +extern const sizeof_info_t sizeof_info_dol[]; + /////////////////////////////////////////////////////////////////////////////// bool GetDolSectionInfo diff --git a/project/dclib/lib-mkw.c b/project/dclib/lib-mkw.c index bbfb316..538e24b 100644 --- a/project/dclib/lib-mkw.c +++ b/project/dclib/lib-mkw.c @@ -15,7 +15,7 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -38,6 +38,8 @@ #include "lib-mkw.h" #include "dclib-numeric.h" +#include "lib-mkw-def.c" + // /////////////////////////////////////////////////////////////////////////////// /////////////// assigned points: tables /////////////// @@ -973,7 +975,7 @@ int GetVrDiffByTab ( int diff ) // diff = VR(winner) - VR(loser) const s16 search = diff; int i = 0, j = sizeof(vr_diff_tab) / sizeof(*vr_diff_tab) - 1; - + while ( i < j ) { const int k = (i+j)/2; @@ -1103,5 +1105,246 @@ ccp GetMkwMusicName3 ( int mid ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// engines /////////////// +/////////////////////////////////////////////////////////////////////////////// + +const char mkw_engine_info[MKW_ENGINE__N+1][7] = +{ + "50cc", + "100cc", + "150cc", + "mirror", + "200cc", + "?", +}; + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// slots, drivers and vehicles /////////////// +/////////////////////////////////////////////////////////////////////////////// + +ccp GetSlotHex ( u8 slot ) +{ + if (IsMkwSlotValid(slot)) + { + char *dest = GetCircBuf(2); + dest[0] = LoDigits[slot]; + dest[1] = 0; + return dest; + } + return "-"; +} + +//----------------------------------------------------------------------------- + +ccp GetSlotNum ( u8 slot ) +{ + if (IsMkwSlotValid(slot)) + return PrintCircBuf("%2u",slot); + return " -"; +} + +/////////////////////////////////////////////////////////////////////////////// + +const mkw_driver_t mkw_driver_attrib[MKW_N_DRIVER+1] = +{ + { 1, 0, "Mari", "Mari", "Mario", "Mario" }, // M0 #0 + { 0, 0, "B.Pe", "B.Pe", "Baby Peach", "Baby Peach" }, // S2 + { 2, 0, "Walu", "Walu", "Waluigi", "Waluigi" }, // L1 + { 2, 0, "Bows", "Bows", "Bowser", "Bowser" }, // L3 + + { 0, 0, "B.Da", "B.Da", "Baby Daisy", "Baby Daisy" }, // S3 #4 + { 0, 0, "DBon", "KnTr", "Dry Bones", "Knochentrocken" }, // S7 + { 0, 0, "B.Ma", "B.Ma", "Baby Mario", "Baby Mario" }, // S0 + { 1, 0, "Luig", "Luig", "Luigi", "Luigi" }, // M1 + + { 0, 0, "Toad", "Toad", "Toad", "Toad" }, // S4 #8 + { 2, 0, "Donk", "Donk", "Donkey Kong", "Donkey Kong" }, // L2 + { 1, 0, "Yosh", "Yosh", "Yoshi", "Yoshi" }, // M4 + { 2, 0, "Wari", "Wari", "Wario", "Wario" }, // L0 + + { 0, 0, "B.Lu", "B.Lu", "Baby Luigi", "Baby Luigi" }, // S1 #12 + { 0, 0, "Tdte", "Tdte", "Toadette", "Toadette" }, // S5 + { 0, 0, "Koop", "Koop", "Koopa Troopa", "Koopa" }, // S6 + { 1, 0, "Dais", "Dais", "Daisy", "Daisy" }, // M3 + + { 1, 0, "Peac", "Peac", "Peach", "Peach" }, // M2 #16 + { 1, 0, "Bird", "Bird", "Birdo", "Birdo" }, // M5 + { 1, 0, "DidK", "DidK", "Diddy Kong", "Diddy Kong" }, // M6 + { 2, 0, "KBoo", "BuHu", "King Boo", "König Buu Huu" }, // L4 + + { 1, 0, "B.Jr", "B.Jr", "Bowser Jr.", "Bowser Jr." }, // M7 #20 + { 2, 0, "DBow", "KnBo", "Dry Bowser", "Knochen-Bowser" }, // L7 + { 2, 0, "Funk", "Funk", "Funky Kong", "Funky Kong" }, // L6 + { 2, 0, "Rosa", "Rosa", "Rosalina", "Rosalina" }, // L5 + + { 0, 1, "MAsm", "MAkm", "Mii A (small,male)", "Mii A (klein,männ)" }, // S8 #24 + { 0, 1, "MAsf", "MAkw", "Mii A (small,female)", "Mii A (klein,weib)" }, // S9 + { 0, 2, "MBsm", "MBkm", "Mii B (small,male)", "Mii B (klein,männ)" }, // S10 + { 0, 2, "MBsf", "MBkw", "Mii B (small,female)", "Mii B (klein,weib)" }, // S11 + { 0, 3, "MCsm", "MCkm", "Mii C (small,male)", "Mii C (klein,männ)" }, // 0x11c + { 0, 3, "MCsf", "MCkw", "Mii C (small,female)", "Mii C (klein,weib)" }, // 0x11d + + { 1, 1, "MAmm", "MAmm", "Mii A (medium,male)", "Mii A (mittel,männ)" },// M8 #30 + { 1, 1, "MAmf", "MAmw", "Mii A (medium,female)","Mii A (mittel,weib)" },// M9 + { 1, 2, "MBmm", "MBmm", "Mii B (medium,male)", "Mii B (mittel,männ)" },// M10 + { 1, 2, "MBmf", "MBmw", "Mii B (medium,female)","Mii B (mittel,weib)" },// M11 + { 1, 3, "MCmm", "MCmm", "Mii C (medium,male)", "Mii C (mittel,männ)" },// 0x122 + { 1, 3, "MCmf", "MCmw", "Mii C (medium,female)","Mii C (mittel,weib)" },// 0x123 + + { 2, 1, "MAlm", "MAgm", "Mii A (large,male)", "Mii A (groß,männ)" }, // L8 #36 + { 2, 1, "MAlf", "MAgw", "Mii A (large,female)", "Mii A (groß,weib)" }, // L9 + { 2, 2, "MBlm", "MBgm", "Mii B (large,male)", "Mii B (groß,männ)" }, // L10 + { 2, 2, "MBlf", "MBgw", "Mii B (large,female)", "Mii B (groß,weib)" }, // L11 + { 2, 3, "MClm", "MCgm", "Mii C (large,male)", "Mii C (groß,männ)" }, // 0x128 + { 2, 3, "MClf", "MCgw", "Mii C (large,female)", "Mii C (groß,weib)" }, // 0x129 + + {0,0,"","",0,0} // TERM #42 +}; + +//----------------------------------------------------------------------------- + +ccp GetDriverNum ( u8 driver ) +{ + switch (driver) + { + case 48: return " ?"; + case 254: return " ."; + case 255: return " -"; + } + + return PrintCircBuf("%3u",driver); +} + +//----------------------------------------------------------------------------- + +ccp GetDriverName4 ( u8 driver ) +{ + if ( driver < MKW_N_DRIVER ) + { + ccp res = mkw_driver_attrib[driver].id_en; + if (*res) + return res; + } + + switch (driver) + { + case 48: return " ?? "; + case 254: return " .. "; + case 255: return " -- "; + } + + return PrintCircBuf("%3u.",driver); +} + +/////////////////////////////////////////////////////////////////////////////// + +const mkw_vehicle_t mkw_vehicle_attrib[MKW_N_VEHICLE+1] = +{ + { 0,0,1, "Ka-S", "MinK", "Standard Kart S", "Mini-Kart" }, // SK0 #0 + { 1,0,1, "Ka-M", "MedK", "Standard Kart M", "Medi-Kart" }, // MK0 + { 2,0,1, "Ka-L", "MaxK", "Standard Kart L", "Maxi-Kart" }, // LK0 + { 0,0,0, "Boos", "Baby", "Booster Seat", "Baby-Booster" }, // SK1 + { 1,0,0, "Drag", "Nost", "Classic Dragster","Nostalgia 1" }, // MK1 + { 2,0,0, "OffR", "OffR", "Offroader", "Offroader" }, // LK1 + + { 0,0,0, "Mini", "MinB", "Mini Beast", "Minibiest" }, // SK2 #6 + { 1,0,0, "Wing", "Wind", "Wild Wing", "Windschnitte" }, // MK2 + { 2,0,0, "Flam", "Feue", "Flame Flyer", "Feuerschleuder" }, // LK2 + { 0,0,0, "Chep", "BobC", "Cheep Charger", "Bob-Cheep" }, // SK3 + { 1,0,0, "Bloo", "Bloo", "Super Blooper", "Blooper-Bolide" }, // MK3 + { 2,0,0, "Pira", "PPir", "Piranha Prowler", "Pistenpiranha" }, // LK3 + + { 0,0,0, "Tita", "Monz", "Tiny Titan", "Monztruck" }, // SK4 #12 + { 1,0,0, "Dayt", "Cabr", "Daytripper", "Cabriosa" }, // MK4 + { 2,0,0, "JetS", "Ster", "Jetsetter", "Sterngleiter" }, // LK4 + { 0,0,0, "Falc", "Falc", "Blue Falcon", "Blue Falcon" }, // SK5 + { 1,0,0, "Spri", "Glor", "Sprinter", "Glory" }, // MK5 + { 2,0,0, "Hony", "Turb", "Honeycoupe", "Turbetto" }, // LK5 + + { 0,1,1, "Bi-S", "MinB", "Standard Bike S", "Mini-Bike" }, // SB0 #18 + { 1,1,1, "Bi-M", "MedB", "Standard Bike M", "Medi-Bike" }, // MB0 + { 2,1,1, "Bi-L", "MaxB", "Standard Bike L", "Maxi-Bike" }, // LB0 + { 0,2,0, "Bull", "Wili", "Bullet Bike", "Willi-Bike" }, // SB1 + { 1,2,0, "Mach", "Mach", "Mach Bike", "Mach-Bike" }, // MB1 + { 2,2,0, "Flam", "BowB", "Flame Runner", "Bowser-Bike" }, // LB1 + + { 0,1,0, "BitB", "Blit", "Bit Bike", "Blitzer" }, // SB2 #24 + { 1,1,0, "Suga", "Bonb", "Sugarscoot", "Bonbon-Bike" }, // MB2 + { 2,1,0, "WarB", "WarB", "Wario Bike", "Wario-Bike" }, // LB2 + { 0,2,0, "Quac", "Quak", "Quacker", "Quakquak" }, // SB3 + { 1,1,0, "ZipZ", "Rapi", "Zip Zip", "Rapido" }, // MB3 + { 2,1,0, "Shoo", "Schn", "Shooting Star", "Schnuppe" }, // LB3 + + { 0,2,0, "MKru", "Kame", "Magikruiser", "Kameknaller" }, // SB4 #30 + { 1,2,0, "Snea", "Pist", "Sneakster", "Pistensturm" }, // MB4 + { 2,2,0, "Spea", "Torp", "Spear", "Torped" }, // LB4 + { 0,2,0, "JetB", "JetA", "Jet Bubble", "Jet-A" }, // SB5 + { 1,2,0, "Dolp", "Flip", "Dolphin Dasher", "Flippster" }, // MB5 + { 2,1,0, "Phan", "Phan", "Phantom", "Phantom" }, // LB5 + + {0,0,0,"","",0,0} // TERM #36 +}; + +//----------------------------------------------------------------------------- + +ccp GetVehicleNum ( u8 vehicle ) +{ + switch (vehicle) + { + case 36: return " ?"; + case 254: return " ."; + case 255: return " -"; + } + + return PrintCircBuf("%3u",vehicle); +} + +//----------------------------------------------------------------------------- + +ccp GetVehicleName4 ( u8 vehicle ) +{ + if ( vehicle < MKW_N_VEHICLE ) + return mkw_vehicle_attrib[vehicle].id_en; + + switch (vehicle) + { + case 36: return " ?? "; + case 254: return " .. "; + case 255: return " -- "; + } + + return PrintCircBuf("%3u.",vehicle); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// sizeof_info_t: mkw /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[sizeof_info_mkw]] + +const sizeof_info_t sizeof_info_mkw[] = +{ + SIZEOF_INFO_TITLE("Mario Kart Wii") + + SIZEOF_INFO_ENTRY(mkw_std_pbits1_t) + SIZEOF_INFO_ENTRY(mkw_std_pbits2_t) + SIZEOF_INFO_ENTRY(mkw_ex_pbits1_t) + SIZEOF_INFO_ENTRY(mkw_ex_pbits2_t) + SIZEOF_INFO_ENTRY(mkw_pbits1_t) + SIZEOF_INFO_ENTRY(mkw_pbits2_t) + SIZEOF_INFO_ENTRY(MkwPointInfo_t) + SIZEOF_INFO_ENTRY(mkw_engine_t) + SIZEOF_INFO_ENTRY(mkw_engine_info) + SIZEOF_INFO_ENTRY(mkw_driver_t) + SIZEOF_INFO_ENTRY(mkw_driver_attrib) + SIZEOF_INFO_ENTRY(mkw_vehicle_t) + SIZEOF_INFO_ENTRY(mkw_vehicle_attrib) + + SIZEOF_INFO_TERM() +}; + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// END /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/lib-mkw.h b/project/dclib/lib-mkw.h index 16f7f86..f0df9b5 100644 --- a/project/dclib/lib-mkw.h +++ b/project/dclib/lib-mkw.h @@ -15,7 +15,7 @@ * * *************************************************************************** * * - * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -37,11 +37,11 @@ #define SZS_LIB_MKWII_H 1 #define _GNU_SOURCE 1 -#include "dclib-basics.h" +#include "lib-mkw-def.h" // /////////////////////////////////////////////////////////////////////////////// -/////////////// CTW definitions / ////////////// +/////////////// CTW definitions /////////////// /////////////////////////////////////////////////////////////////////////////// #define CTW_MAX_TRACK_ID 999999 @@ -51,6 +51,10 @@ /////////////// base definitions /////////////// /////////////////////////////////////////////////////////////////////////////// +extern const sizeof_info_t sizeof_info_mkw[]; + +/////////////////////////////////////////////////////////////////////////////// + enum mkw_consts_t // some constants { //--- num of players @@ -119,10 +123,10 @@ static inline bool IsMkwCustom ( uint tid ) #endif // unsigned types, that can hold 1 or 2 bits for each player -typedef u16 mkw_std_pbits1_t; // 12 bits needed -typedef u32 mkw_std_pbits2_t; // 24 bits needed -typedef u32 mkw_ex_pbits1_t; // 24 bits needed -typedef u64 mkw_ex_pbits2_t; // 48 bits needed +typedef u16 mkw_std_pbits1_t; // 12 bits needed +typedef u32 mkw_std_pbits2_t; // 24 bits needed +typedef u32 mkw_ex_pbits1_t; // 24 bits needed +typedef u64 mkw_ex_pbits2_t; // 48 bits needed #if SUPPORT_24P typedef u32 mkw_pbits1_t; @@ -138,6 +142,8 @@ typedef u64 mkw_ex_pbits2_t; // 48 bits needed #define MKW_EX_MAX_PLAYER2 ( MKW_EX_MAX_PLAYER * MKW_EX_MAX_PLAYER ) #define MKW_MAX_PLAYER2 ( MKW_MAX_PLAYER * MKW_MAX_PLAYER ) +#define MAX_ROOM_MEMBERS MKW_MAX_PLAYER + // /////////////////////////////////////////////////////////////////////////////// /////////////// assigned points for versus and rooms /////////////// @@ -156,7 +162,7 @@ typedef u64 mkw_ex_pbits2_t; // 48 bits needed typedef enum MkwPointID { //--- tables - MPI_UNKNOWN, // no table assigend + MPI_UNKNOWN, // no table assigned MPI_NINTENDO, // original table MPI_LINEAR, // 4 linear tables @@ -198,7 +204,7 @@ MkwPointInfo_t; //----------------------------------------------------------------------------- -const MkwPointInfo_t MkwPointInfo[MPI__N+1]; +extern const MkwPointInfo_t MkwPointInfo[MPI__N+1]; // [[24P--]] all tables @@ -301,6 +307,90 @@ ccp GetMkwMusicName3 ( int mid ); // /////////////////////////////////////////////////////////////////////////////// +/////////////// engines /////////////// +/////////////////////////////////////////////////////////////////////////////// + +typedef enum mkw_engine_t +{ + MKW_ENGINE_50CC, + MKW_ENGINE_100CC, + MKW_ENGINE_150CC, + MKW_ENGINE_MIRROR, + MKW_ENGINE_200CC, + MKW_ENGINE__N +} +__attribute__ ((packed)) mkw_engine_t; + +extern const char mkw_engine_info[MKW_ENGINE__N+1][7]; + +static inline ccp GetMkwEngineInfo ( mkw_engine_t engine ) +{ + return (uint)engine < MKW_ENGINE__N ? mkw_engine_info[engine] : "?"; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// slots, drivers and vehicles /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[mkw_driver_t]] + +typedef struct mkw_driver_t +{ + u8 weight; // 0:small, 1:medium, 2:large + u8 is_mii; // 0:no Mii, 1:A, 2:B, 3:B + char id_en[5]; + char id_de[5]; + ccp name_en; + ccp name_de; +} +mkw_driver_t; + +#define MKW_N_DRIVER 42 +extern const mkw_driver_t mkw_driver_attrib[MKW_N_DRIVER+1]; + +//----------------------------------------------------------------------------- +// [[mkw_vehicle_t]] + +typedef struct mkw_vehicle_t +{ + u8 weight; // 0:small, 1:medium, 2:large + u8 is_bike; // 0:kart, 1:out-bike, 2:in-bike + u8 battle; // 0:not used in battle, 1:used in battle + char id_en[5]; + char id_de[5]; + ccp name_en; + ccp name_de; +} +mkw_vehicle_t; + +#define MKW_N_VEHICLE 36 +extern const mkw_vehicle_t mkw_vehicle_attrib[MKW_N_VEHICLE+1]; + +//----------------------------------------------------------------------------- + +static inline bool IsMkwSlotValid ( uint slot ) + { return slot < MAX_ROOM_MEMBERS; } + +static inline int GetDriverInt ( u8 driver ) + { return driver >= 254 ? (int)driver - 256 : driver; } + +static inline int GetVehicleInt ( u8 vehicle ) + { return vehicle >= 254 ? (int)vehicle - 256 : vehicle; } + +//----------------------------------------------------------------------------- + +// for optimization: `colset´ is always valid and never NULL! + +ccp GetSlotHex ( u8 slot ); +ccp GetSlotNum ( u8 slot ); +ccp GetDriverNum ( u8 driver ); +ccp GetVehicleNum ( u8 vehicle ); + +ccp GetDriverName4 ( u8 driver ); +ccp GetVehicleName4 ( u8 vehicle ); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// END /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/revision.sh b/project/revision.sh index d1a0788..d47a779 100644 --- a/project/revision.sh +++ b/project/revision.sh @@ -1 +1 @@ -revision=8462 +revision=8529 diff --git a/project/setup.sh b/project/setup.sh index edbc893..92525a5 100644 --- a/project/setup.sh +++ b/project/setup.sh @@ -51,11 +51,17 @@ fi && grep -qw posix_fallocate /usr/include/fcntl.h \ && defines="$defines -DHAVE_POSIX_FALLOCATE=1" -#gcc $xflags system.c -o system.tmp && ./system.tmp >Makefile.setup +#-------------------------------------------------- + +GCC_VERSION="$( gcc --version | head -n1 | sed 's/([^)]*)//'|awk '{print $2}' )" +[[ $GCC_VERSION > 7 ]] && xflags+=" -fdiagnostics-color=always" + gcc $xflags -E -DPRINT_SYSTEM_SETTINGS system.c \ | awk -F= '/^result_/ {printf("%s := %s\n",substr($1,8),gensub(/"/,"","g",$2))}' \ > Makefile.setup +#-------------------------------------------------- + SYSTEM=$(awk '$1=="SYSTEM" {print $3}' Makefile.setup) #echo "SYSTEM=|$SYSTEM|" >&2 @@ -163,7 +169,7 @@ fi #-------------------------------------------------- -cat <<- ---EOT--- >>Makefile.setup +cat <<- __EOT__ >> Makefile.setup REVISION := $revision REVISION_NUM := $revision_num @@ -173,6 +179,7 @@ cat <<- ---EOT--- >>Makefile.setup TIME := ${tim[2]} YEAR := ${tim[3]} + GCC_VERSION := $GCC_VERSION FORCE_M32 := $force_m32 HAVE_MD5 := $have_md5 HAVE_SHA := $have_sha @@ -197,5 +204,5 @@ cat <<- ---EOT--- >>Makefile.setup HAVE_WORK_SRC := $HAVE_WORK_SRC HAVE_XSRC := $HAVE_XSRC - ---EOT--- + __EOT__ diff --git a/project/src/addr_port.inc b/project/src/addr_port.inc index a6b78b3..d949d79 100644 --- a/project/src/addr_port.inc +++ b/project/src/addr_port.inc @@ -3,130 +3,77 @@ static addr_port_version_t addr_port_version = { .magic = "PORT-DB", .db_version = 1, - .revision = 8458, - .timestamp = 1620190598, - .n_records = 2050 + .revision = 8516, + .timestamp = 1647001915, + .n_records = 1685 }; -static const addr_port_t addr_port_0[2050] = +static const addr_port_t addr_port_0[1685] = { {{ 0x80000000, 0x80000000, 0x80000000, 0x80000000 }, 0x8040|0, 0x8040|0 }, // HEAD - {{ 0x80008040, 0x800d2ce8, 0x800d2ca8, 0x800d2de8 }, 0xc|2, 0xc|2 }, // T1 - {{ 0x80008054, 0x8001f964, 0x800203e8, 0x8002052c }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80008090, 0x80008050, 0x80008024, 0x8000812c }, 0x10|2, 0x10|2 }, // T1 - {{ 0x800080ac, 0x8000806c, 0x80008024, 0x8000812c }, 0x10|2, 0x10|2 }, // T1 - {{ 0x800080c8, 0x80008088, 0x80008024, 0x8000812c }, 0x10|2, 0x10|2 }, // T1 {{ 0x80008114, 0x800080d4, 0x80008070, 0x80008188 }, 0xbc|2, 0xbc|2 }, // T1 {{ 0x800081e0, 0x800081a0, 0x8000813c, 0x80008250 }, 0x8|3, 0x8|3 }, // T1 - {{ 0x80008218, 0x800081d8, 0x80008174, 0x80060894 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80008220, 0x800081e0, 0x8000817c, 0x800082a4 }, 0x68|2, 0x68|2 }, // T1 {{ 0x8000829c, 0x8000825c, 0x800081f8, 0x8000841c }, 0x8f8|2, 0x8f8|2 }, // T1 - {{ 0x80008ba0, 0x80008b60, 0x80008afc, 0x800498a8 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80008bfc, 0x80008bbc, 0x80008b58, 0x80008d4c }, 0x7f4|2, 0x7f4|2 }, // T1 - {{ 0x800093f8, 0x800093b8, 0x80009354, 0x800d6970 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80009404, 0x800093c4, 0x80009360, 0x80020dac }, 0x4|3, 0x4|3 }, // T1 {{ 0x80009408, 0x800093c8, 0x80009364, 0x8000954c }, 0x24|2, 0x24|2 }, // T1 - {{ 0x8000942c, 0x800093ec, 0x80009388, 0x800d07c0 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80009440, 0x80009400, 0x8000939c, 0x800d4228 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80009458, 0x80009418, 0x800093b4, 0x80009560 }, 0x18b4|0, 0x18ec|1 }, // T1 {{ 0x8000ad44, 0x8000ad04, 0x8000aca0, 0x8000ae4c }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8000ad48, 0x8000ad08, 0x8000aca4, 0x8000ae40 }, 0x4|3, 0x4|3 }, // T1 {{ 0x8000ad4c, 0x8000ad0c, 0x8000aca8, 0x8000ae64 }, 0x8|3, 0x8|3 }, // T1 {{ 0x8000ad58, 0x8000ad18, 0x8000acb4, 0x8000ae50 }, 0x4|3, 0x4|3 }, // T1 {{ 0x8000ad5c, 0x8000ad1c, 0x8000acb8, 0x8000ae74 }, 0x8|3, 0x8|3 }, // T1 {{ 0x8000ad64, 0x8000ad24, 0x8000acc0, 0x8000ae5c }, 0x8|3, 0x8|3 }, // T1 {{ 0x8000ad6c, 0x8000ad2c, 0x8000acc8, 0x8000ae84 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8000ad70, 0x8000ad30, 0x8000accc, 0x8000ae68 }, 0x24|2, 0x24|2 }, // T1 - {{ 0x8000ad94, 0x8000ad54, 0x8000acf0, 0x800d2f2c }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8000ad98, 0x8000ad58, 0x8000acf4, 0x8000ae90 }, 0xc|2, 0xc|2 }, // T1 + {{ 0x8000ad70, 0x8000ad30, 0x8000accc, 0x8000ae68 }, 0x34|2, 0x34|2 }, // T1 {{ 0x8000ada4, 0x8000ad64, 0x8000ad00, 0x8000aebc }, 0x14|2, 0x14|2 }, // T1 {{ 0x8000adc0, 0x8000ad8c, 0x8000ad1c, 0x8000aed8 }, 0x14|2, 0x14|2 }, // T1 - {{ 0x8000ade0, 0x800519d8, 0x80051998, 0x80051ad8 }, 0x4|3, 0x4|3 }, // T1 {{ 0x8000adf8, 0x8000adbc, 0x8000ad4c, 0x8000af08 }, 0xa0|2, 0xa0|2 }, // T1 - {{ 0x8000aeb4, 0x80023810, 0x800237d0, 0x80023910 }, 0x8|3, 0x8|3 }, // T1 - {{ 0x8000aedc, 0x8002380c, 0x800237cc, 0x8002390c }, 0xc|2, 0xc|2 }, // T1 {{ 0x8000af20, 0x8000ae80, 0x8000ae44, 0x8000afcc }, 0x6e4|2, 0x6e4|2 }, // T1 {{ 0x8000b654, 0x8000b5b4, 0x8000b578, 0x8000b6bc }, 0x4c|2, 0x4c|2 }, // T1 - {{ 0x8000b6b0, 0x80098048, 0x8000b5d4, 0x8000b718 }, 0x4|3, 0x4|3 }, // T1 {{ 0x8000b6b4, 0x80021048, 0x8000b5d8, 0x8000b71c }, 0xac0|0, 0xac0|0 }, // T1 {{ 0x8000c174, 0x8000b614, 0x8000c098, 0x8000c1dc }, 0x1021c|0, 0x10248|1 }, // T1 - {{ 0x8001c3bc, 0x8001b85c, 0x8001c2e0, 0x8001c424 }, 0x68|2, 0x94|3 }, // T1 + {{ 0x8001c3bc, 0x8001b85c, 0x8001c2e0, 0x8001c424 }, 0x68|2, 0x68|2 }, // T1 {{ 0x8001c450, 0x8001b8f0, 0x8001c374, 0x8001c4b8 }, 0x5750|0, 0x5750|0 }, // T1 - {{ 0x80021ba8, 0x80021b08, 0x800b2638, 0x800b2778 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80021bac, 0x80021b0c, 0x80021acc, 0x800b277c }, 0x4|3, 0x4|3 }, // T1 {{ 0x80021bb0, 0x80021b10, 0x80021ad0, 0x80021c10 }, 0x1e508|0, 0x1e530|1 }, // T1 - {{ 0x800400e0, 0x80040040, 0x80040000, 0x80040140 }, 0x2a10|2, 0x2a38|3 }, // T1 - {{ 0x80042b18, 0x80042a78, 0x80042a38, 0x80042b78 }, 0x75400|2, 0x75400|2 }, // T1 - {{ 0x800b7f18, 0x800b42d8, 0x800b4298, 0x800b43d8 }, 0x1318|2, 0x1318|2 }, // T1 - {{ 0x800b9230, 0x800b9190, 0x800b9150, 0x800b9290 }, 0x6d0c|2, 0x6d0c|2 }, // T1 - {{ 0x800bff3c, 0x800bfe9c, 0x800bfe5c, 0x8012e598 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x800bff40, 0x800bfea0, 0x800bfe60, 0x800bffa0 }, 0x2a4f0|0, 0x2a4f0|0 }, // T1 - {{ 0x800ea474, 0x800ea3d4, 0x800ea394, 0x800ea4ec }, 0xa74|2, 0xa74|2 }, // T1 - {{ 0x800eaee8, 0x800eae48, 0x800eae08, 0x800ed580 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x800eaeec, 0x800eae4c, 0x800eae0c, 0x800eaf64 }, 0x4f5a4|0, 0x4f634|1 }, // T1 - {{ 0x8013a520, 0x8013a480, 0x8013a440, 0x8013a598 }, 0x228|2, 0x2b8|3 }, // T1 + {{ 0x800400e0, 0x80040040, 0x80040000, 0x80040140 }, 0x2a10|2, 0x2a10|2 }, // T1 + {{ 0x80042b18, 0x80042a78, 0x80042a38, 0x80042b78 }, 0x75400|0, 0x76718|1 }, // T1 + {{ 0x800b9230, 0x800b9190, 0x800b9150, 0x800b9290 }, 0x31200|0, 0x31200|0 }, // T1 + {{ 0x800ea474, 0x800ea3d4, 0x800ea394, 0x800ea4ec }, 0x5001c|0, 0x500ac|1 }, // T1 + {{ 0x8013a520, 0x8013a480, 0x8013a440, 0x8013a598 }, 0x228|2, 0x228|2 }, // T1 {{ 0x8013a7d8, 0x8013a738, 0x8013a6f8, 0x8013a850 }, 0x29b10|0, 0x29b10|0 }, // T1 - {{ 0x80164300, 0x80164260, 0x80164220, 0x801646a4 }, 0xc|2, 0xc|2 }, // T1 {{ 0x8016430c, 0x8016426c, 0x8016422c, 0x801643a8 }, 0x103dc|0, 0x103dc|0 }, // T1 {{ 0x801746f8, 0x80174658, 0x80174618, 0x80174834 }, 0x54c|2, 0x54c|2 }, // T1 - {{ 0x80174c44, 0x80174ba4, 0x80174b64, 0x80186884 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80174c4c, 0x80174bac, 0x80174b6c, 0x80174da0 }, 0x29c|2, 0x29c|2 }, // T1 {{ 0x80174ef0, 0x80174e50, 0x80174e10, 0x80175178 }, 0xa74|2, 0xa74|2 }, // T1 - {{ 0x80175970, 0x801758d0, 0x80175890, 0x800e4bd4 }, 0x8|3, 0x8|3 }, // T1 - {{ 0x80175978, 0x801758d8, 0x80175898, 0x80175bf0 }, 0x11c0|2, 0x11c0|2 }, // T1 - {{ 0x80176b38, 0x80176a98, 0x80176a58, 0x800fc840 }, 0x1c|2, 0x1c|2 }, // T1 - {{ 0x80176b54, 0x80176ab4, 0x80176a74, 0x80176dcc }, 0x64|2, 0x64|2 }, // T1 - {{ 0x80176bc8, 0x80176b28, 0x80176ae8, 0x80176e4c }, 0xb0|2, 0xb0|2 }, // T1 - {{ 0x80176c78, 0x80176bd8, 0x80176b98, 0x802435f0 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80176c7c, 0x80176bdc, 0x80176b9c, 0x80176f00 }, 0x18|2, 0x18|2 }, // T1 - {{ 0x80176ca8, 0x80176c08, 0x80176bc8, 0x80176f38 }, 0xb0|2, 0xb0|2 }, // T1 - {{ 0x80176d58, 0x80176cb8, 0x80176c78, 0x802435f0 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80176d5c, 0x80176cbc, 0x80176c7c, 0x80176fec }, 0x764|2, 0x764|2 }, // T1 + {{ 0x80175978, 0x801758d8, 0x80175898, 0x80175bf0 }, 0x1240|2, 0x1240|2 }, // T1 + {{ 0x80176bc8, 0x80176b28, 0x80176ae8, 0x80176e4c }, 0xcc|2, 0xcc|2 }, // T1 + {{ 0x80176ca8, 0x80176c08, 0x80176bc8, 0x80176f38 }, 0x818|2, 0x818|2 }, // T1 {{ 0x801774dc, 0x8017743c, 0x801773fc, 0x80177c54 }, 0xc|2, 0xc|2 }, // T1 {{ 0x80177504, 0x80177464, 0x80177424, 0x8017776c }, 0x10|2, 0x10|2 }, // T1 - {{ 0x80177570, 0x801774d0, 0x80177490, 0x80113380 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80177578, 0x801774d8, 0x80177498, 0x8017f594 }, 0x8|3, 0x8|3 }, // T1 {{ 0x801775a0, 0x80177500, 0x801774c0, 0x8017b1a8 }, 0xc|2, 0xc|2 }, // T1 - {{ 0x801775c4, 0x80177524, 0x801774e4, 0x8017af68 }, 0x2c|2, 0x2c|2 }, // T1 - {{ 0x80177614, 0x80177574, 0x80177534, 0x80112700 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80177618, 0x80177578, 0x80177538, 0x8017afbc }, 0x38|2, 0x38|2 }, // T1 - {{ 0x80177650, 0x801775b0, 0x80177570, 0x8021d674 }, 0x8|3, 0x8|3 }, // T1 - {{ 0x80177658, 0x801775b8, 0x80177578, 0x8017affc }, 0x74|2, 0x74|2 }, // T1 + {{ 0x801775c4, 0x80177524, 0x801774e4, 0x8017af68 }, 0x2c|2, 0x54|3 }, // T1 + {{ 0x80177618, 0x80177578, 0x80177538, 0x8017afbc }, 0xb4|2, 0xb4|2 }, // T1 {{ 0x80177708, 0x80177668, 0x80177628, 0x8017f594 }, 0x8|3, 0x8|3 }, // T1 - {{ 0x80177750, 0x801776b0, 0x80177670, 0x801bafac }, 0x8|3, 0x8|3 }, // T1 {{ 0x80177760, 0x801776c0, 0x80177680, 0x8017f9a4 }, 0x18|2, 0x18|2 }, // T1 {{ 0x80177788, 0x801776e8, 0x801776a8, 0x80177ab4 }, 0x28|2, 0x28|2 }, // T1 - {{ 0x801777bc, 0x8017771c, 0x801776dc, 0x80177aec }, 0x8|3, 0x8|3 }, // T1 - {{ 0x801777c4, 0x80177724, 0x801776e4, 0x800fcaec }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801777cc, 0x8017772c, 0x801776ec, 0x80177afc }, 0x54|2, 0x54|2 }, // T1 + {{ 0x801777bc, 0x8017771c, 0x801776dc, 0x80177aec }, 0x64|2, 0x64|2 }, // T1 {{ 0x80177828, 0x80177788, 0x80177748, 0x80177b54 }, 0xc|2, 0xc|2 }, // T1 {{ 0x80177834, 0x80177794, 0x80177754, 0x80177b68 }, 0x90|2, 0x90|2 }, // T1 {{ 0x80177904, 0x80177864, 0x80177824, 0x80177c90 }, 0x3c|2, 0x3c|2 }, // T1 - {{ 0x80177954, 0x801778b4, 0x80177874, 0x801ad274 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80177958, 0x801778b8, 0x80177878, 0x80177ce0 }, 0x3c|2, 0x3c|2 }, // T1 - {{ 0x801779a0, 0x80177900, 0x801778c0, 0x801ad270 }, 0x8|3, 0x8|3 }, // T1 {{ 0x801779a8, 0x80177908, 0x801778c8, 0x80177d2c }, 0x64|2, 0x64|2 }, // T1 - {{ 0x80177a14, 0x80177974, 0x80177934, 0x801ad274 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80177a18, 0x80177978, 0x80177938, 0x80177d98 }, 0xe0|2, 0xe0|2 }, // T1 - {{ 0x80177b20, 0x80177a80, 0x80177a40, 0x801ad274 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80177b24, 0x80177a84, 0x80177a44, 0x80177ea0 }, 0xf8|2, 0xf8|2 }, // T1 - {{ 0x80177c1c, 0x80177b7c, 0x80177b3c, 0x800a0ec4 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80177c20, 0x80177b80, 0x80177b40, 0x80177f9c }, 0x2c|2, 0x2c|2 }, // T1 - {{ 0x80177c74, 0x80177bd4, 0x80177b94, 0x801ad274 }, 0x4|3, 0x4|3 }, // T1 + {{ 0x80177b24, 0x80177a84, 0x80177a44, 0x80177ea0 }, 0x128|2, 0x128|2 }, // T1 {{ 0x80177c78, 0x80177bd8, 0x80177b98, 0x80177ff0 }, 0x134|2, 0x134|2 }, // T1 - {{ 0x80177db8, 0x80177d18, 0x80177cd8, 0x801ad274 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80177dbc, 0x80177d1c, 0x80177cdc, 0x80178130 }, 0xe0|2, 0xe0|2 }, // T1 {{ 0x80177ea8, 0x80177e08, 0x80177dc8, 0x80178218 }, 0x1c|2, 0x1c|2 }, // T1 {{ 0x80177ed4, 0x80177e34, 0x80177df4, 0x80178240 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80177eec, 0x80177e4c, 0x80177e0c, 0x8017825c }, 0x64|2, 0x64|2 }, // T1 {{ 0x80177f60, 0x80177ec0, 0x80177e80, 0x80178810 }, 0x60|2, 0x60|2 }, // T1 - {{ 0x80177fe0, 0x80177f40, 0x80177f00, 0x800f5b88 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80177ff8, 0x80177f58, 0x80177f18, 0x801782e0 }, 0x28|2, 0x28|2 }, // T1 - {{ 0x80178020, 0x80177f80, 0x80177f40, 0x801ad270 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80178028, 0x80177f88, 0x80177f48, 0x8017830c }, 0x22c|2, 0x22c|2 }, // T1 - {{ 0x80178260, 0x801781c0, 0x80178180, 0x801ad138 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80178274, 0x801781d4, 0x80178194, 0x80178550 }, 0x40|2, 0x40|2 }, // T1 - {{ 0x801782c0, 0x80178220, 0x801781e0, 0x801ad138 }, 0x4|3, 0x4|3 }, // T1 {{ 0x801782d0, 0x80178230, 0x801781f0, 0x8017854c }, 0x8|3, 0x8|3 }, // T1 {{ 0x801782d8, 0x80178238, 0x801781f8, 0x801785ac }, 0x158|2, 0x158|2 }, // T1 {{ 0x80178454, 0x801783b4, 0x80178374, 0x8017a304 }, 0x4|3, 0x4|3 }, // T1 @@ -134,47 +81,21 @@ static const addr_port_t addr_port_0[2050] = {{ 0x801784b4, 0x80178414, 0x801783d4, 0x801787c0 }, 0x8|3, 0x8|3 }, // T1 {{ 0x801784c0, 0x80178420, 0x801783e0, 0x801787c8 }, 0x30|2, 0x30|2 }, // T1 {{ 0x801784f0, 0x80178450, 0x80178410, 0x801787fc }, 0x8|3, 0x8|3 }, // T1 - {{ 0x80178514, 0x80178474, 0x80178434, 0x801788a4 }, 0x2b0|2, 0x2b0|2 }, // T1 - {{ 0x801787c4, 0x80178724, 0x801786e4, 0x800f3954 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801787c8, 0x80178728, 0x801786e8, 0x80178b58 }, 0x14|2, 0x14|2 }, // T1 - {{ 0x801787dc, 0x8017873c, 0x801786fc, 0x80186414 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801787e0, 0x80178740, 0x80178700, 0x80178b70 }, 0x48|2, 0x48|2 }, // T1 - {{ 0x80178828, 0x80178788, 0x80178748, 0x80186414 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017882c, 0x8017878c, 0x8017874c, 0x80178bbc }, 0x360|2, 0x360|2 }, // T1 - {{ 0x80178b8c, 0x80178aec, 0x80178aac, 0x8009b0bc }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80178b90, 0x80178af0, 0x80178ab0, 0x80178f20 }, 0x730|2, 0x730|2 }, // T1 - {{ 0x8017931c, 0x8017927c, 0x8017923c, 0x80238b80 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80179320, 0x80179280, 0x80179240, 0x80238b9c }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80179328, 0x80179288, 0x80179248, 0x801e6a08 }, 0x4|3, 0x4|3 }, // T1 + {{ 0x80178514, 0x80178474, 0x80178434, 0x801788a4 }, 0xdac|2, 0xdac|2 }, // T1 {{ 0x8017932c, 0x8017928c, 0x8017924c, 0x801796ec }, 0x4|3, 0x4|3 }, // T1 {{ 0x80179330, 0x80179290, 0x80179250, 0x80179518 }, 0x10|2, 0x10|2 }, // T1 - {{ 0x80179340, 0x801792a0, 0x80179260, 0x8016d520 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80179378, 0x801792d8, 0x80179298, 0x80238b80 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80179384, 0x801792e4, 0x801792a4, 0x80179660 }, 0x240|2, 0x240|2 }, // T1 - {{ 0x801795c4, 0x80179524, 0x801794e4, 0x80221dd4 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801795c8, 0x80179528, 0x801794e8, 0x801798a4 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801795cc, 0x8017952c, 0x801794ec, 0x802222fc }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801795d0, 0x80179530, 0x801794f0, 0x801798ac }, 0x14|2, 0x14|2 }, // T1 - {{ 0x801795e4, 0x80179544, 0x80179504, 0x80102bd8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801795e8, 0x80179548, 0x80179508, 0x801798c4 }, 0x584|2, 0x584|2 }, // T1 + {{ 0x80179384, 0x801792e4, 0x801792a4, 0x80179660 }, 0x7e8|2, 0x7e8|2 }, // T1 {{ 0x80179b6c, 0x80179acc, 0x80179a8c, 0x80179e44 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80179b70, 0x80179ad0, 0x80179a90, 0x80179e4c }, 0xd4|2, 0xd4|2 }, // T1 - {{ 0x80179c44, 0x80179ba4, 0x80179b64, 0x8009ab24 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80179c48, 0x80179ba8, 0x80179b68, 0x80179f24 }, 0x2fc|2, 0x2fc|2 }, // T1 - {{ 0x80179f44, 0x80179ea4, 0x80179e64, 0x8009ab24 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80179f48, 0x80179ea8, 0x80179e68, 0x8017a224 }, 0x4c|2, 0x4c|2 }, // T1 + {{ 0x80179b70, 0x80179ad0, 0x80179a90, 0x80179e4c }, 0x424|2, 0x424|2 }, // T1 {{ 0x80179f94, 0x80179ef4, 0x80179eb4, 0x8017a1ec }, 0x24|2, 0x24|2 }, // T1 {{ 0x80179fb8, 0x80179f18, 0x80179ed8, 0x80179e14 }, 0x4|3, 0x4|3 }, // T1 {{ 0x80179fbc, 0x80179f1c, 0x80179edc, 0x8017a2a4 }, 0x30|2, 0x30|2 }, // T1 {{ 0x80179fec, 0x80179f4c, 0x80179f0c, 0x801799bc }, 0x4|3, 0x4|3 }, // T1 - {{ 0x80179ff0, 0x80179f50, 0x80179f10, 0x8017a2d8 }, 0x18|2, 0x18|2 }, // T1 - {{ 0x8017a008, 0x80179f68, 0x80179f28, 0x80085c7c }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017a00c, 0x80179f6c, 0x80179f2c, 0x8017a2f4 }, 0x20|2, 0x20|2 }, // T1 + {{ 0x80179ff0, 0x80179f50, 0x80179f10, 0x8017a2d8 }, 0x3c|2, 0x3c|2 }, // T1 {{ 0x8017a02c, 0x80179f8c, 0x80179f4c, 0x801799bc }, 0x4|3, 0x4|3 }, // T1 {{ 0x8017a030, 0x80179f90, 0x80179f50, 0x8017a318 }, 0x48|2, 0x48|2 }, // T1 {{ 0x8017a078, 0x80179fd8, 0x80179f98, 0x801799bc }, 0x4|3, 0x4|3 }, // T1 {{ 0x8017a07c, 0x80179fdc, 0x80179f9c, 0x8017a364 }, 0x8|3, 0x8|3 }, // T1 - {{ 0x8017a0bc, 0x8017a01c, 0x80179fdc, 0x80128c34 }, 0x4|3, 0x4|3 }, // T1 {{ 0x8017a0c0, 0x8017a020, 0x80179fe0, 0x8017a3b0 }, 0x214|2, 0x214|2 }, // T1 {{ 0x8017a2d4, 0x8017a234, 0x8017a1f4, 0x8017987c }, 0x8|3, 0x8|3 }, // T1 {{ 0x8017a2dc, 0x8017a23c, 0x8017a1fc, 0x8017a5cc }, 0x18|2, 0x18|2 }, // T1 @@ -186,122 +107,40 @@ static const addr_port_t addr_port_0[2050] = {{ 0x8017a658, 0x8017a5b8, 0x8017a578, 0x801799bc }, 0x4|3, 0x4|3 }, // T1 {{ 0x8017a65c, 0x8017a5bc, 0x8017a57c, 0x8017a94c }, 0x50|2, 0x50|2 }, // T1 {{ 0x8017a6ac, 0x8017a60c, 0x8017a5cc, 0x801799bc }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017a6b0, 0x8017a610, 0x8017a5d0, 0x8017a9a0 }, 0xb4|2, 0xb4|2 }, // T1 - {{ 0x8017a764, 0x8017a6c4, 0x8017a684, 0x8012bef0 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017a768, 0x8017a6c8, 0x8017a688, 0x8017aa58 }, 0xc|2, 0xc|2 }, // T1 - {{ 0x8017a774, 0x8017a6d4, 0x8017a694, 0x80102bd8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017a778, 0x8017a6d8, 0x8017a698, 0x8017aa68 }, 0x5c|2, 0x5c|2 }, // T1 - {{ 0x8017a7d4, 0x8017a734, 0x8017a6f4, 0x80102bd8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017a7d8, 0x8017a738, 0x8017a6f8, 0x8017aac8 }, 0x58|2, 0x58|2 }, // T1 - {{ 0x8017a830, 0x8017a790, 0x8017a750, 0x80102bd8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017a834, 0x8017a794, 0x8017a754, 0x8017ab24 }, 0x12c|2, 0x12c|2 }, // T1 + {{ 0x8017a6b0, 0x8017a610, 0x8017a5d0, 0x8017a9a0 }, 0x2b0|2, 0x2b0|2 }, // T1 {{ 0x8017a960, 0x8017a8c0, 0x8017a880, 0x8017aa18 }, 0x4|3, 0x4|3 }, // T1 {{ 0x8017a964, 0x8017a8c4, 0x8017a884, 0x8017ac54 }, 0x14|2, 0x14|2 }, // T1 {{ 0x8017a97c, 0x8017a8dc, 0x8017a89c, 0x8017aa34 }, 0x18|2, 0x18|2 }, // T1 - {{ 0x8017a994, 0x8017a8f4, 0x8017a8b4, 0x8017ac84 }, 0x298|2, 0x298|2 }, // T1 - {{ 0x8017ac2c, 0x8017ab8c, 0x8017ab4c, 0x8021ee90 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017ac30, 0x8017ab90, 0x8017ab50, 0x8017af20 }, 0xc|2, 0xc|2 }, // T1 - {{ 0x8017ac44, 0x8017aba4, 0x8017ab64, 0x801cc084 }, 0x8|3, 0x8|3 }, // T1 + {{ 0x8017a994, 0x8017a8f4, 0x8017a8b4, 0x8017ac84 }, 0x2a8|2, 0x2a8|2 }, // T1 {{ 0x8017ac4c, 0x8017abac, 0x8017ab6c, 0x8017b094 }, 0x34c|2, 0x34c|2 }, // T1 {{ 0x8017afa4, 0x8017af04, 0x8017aec4, 0x8017b3f4 }, 0x390|2, 0x390|2 }, // T1 - {{ 0x8017b338, 0x8017b298, 0x8017b258, 0x8017b790 }, 0x10a0|2, 0x10a0|2 }, // T1 - {{ 0x8017c3d8, 0x8017c338, 0x8017c2f8, 0x800a2668 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017c3dc, 0x8017c33c, 0x8017c2fc, 0x8017c834 }, 0x1a0|2, 0x1a0|2 }, // T1 - {{ 0x8017c57c, 0x8017c4dc, 0x8017c49c, 0x80102bd8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017c580, 0x8017c4e0, 0x8017c4a0, 0x8017c9d8 }, 0x5c|2, 0x5c|2 }, // T1 - {{ 0x8017c5dc, 0x8017c53c, 0x8017c4fc, 0x80102bd8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017c5e0, 0x8017c540, 0x8017c500, 0x8017ca38 }, 0x58|2, 0x58|2 }, // T1 - {{ 0x8017c638, 0x8017c598, 0x8017c558, 0x80102bd8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017c63c, 0x8017c59c, 0x8017c55c, 0x8017ca94 }, 0x14c|2, 0x14c|2 }, // T1 + {{ 0x8017b338, 0x8017b298, 0x8017b258, 0x8017b790 }, 0x1450|2, 0x1450|2 }, // T1 {{ 0x8017c788, 0x8017c6e8, 0x8017c6a8, 0x8017c910 }, 0x8|3, 0x8|3 }, // T1 - {{ 0x8017c790, 0x8017c6f0, 0x8017c6b0, 0x8017cbe8 }, 0xb8|2, 0xb8|2 }, // T1 - {{ 0x8017c848, 0x8017c7a8, 0x8017c768, 0x80102bd8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017c84c, 0x8017c7ac, 0x8017c76c, 0x8017cca4 }, 0x5c|2, 0x5c|2 }, // T1 - {{ 0x8017c8a8, 0x8017c808, 0x8017c7c8, 0x80102bd8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017c8ac, 0x8017c80c, 0x8017c7cc, 0x8017cd04 }, 0x58|2, 0x58|2 }, // T1 - {{ 0x8017c904, 0x8017c864, 0x8017c824, 0x80102bd8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017c908, 0x8017c868, 0x8017c828, 0x8017cd60 }, 0x14c|2, 0x14c|2 }, // T1 + {{ 0x8017c790, 0x8017c6f0, 0x8017c6b0, 0x8017cbe8 }, 0x2c4|2, 0x2c4|2 }, // T1 {{ 0x8017ca54, 0x8017c9b4, 0x8017c974, 0x8017c910 }, 0x8|3, 0x8|3 }, // T1 - {{ 0x8017ca5c, 0x8017c9bc, 0x8017c97c, 0x8017ceb4 }, 0x750|2, 0x750|2 }, // T1 - {{ 0x8017d1ac, 0x8017d10c, 0x8017d0cc, 0x801f5920 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017d1b0, 0x8017d110, 0x8017d0d0, 0x8017d608 }, 0x1c|2, 0x1c|2 }, // T1 - {{ 0x8017d1cc, 0x8017d12c, 0x8017d0ec, 0x801fa410 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017d1d0, 0x8017d130, 0x8017d0f0, 0x8009844c }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017d1d4, 0x8017d134, 0x8017d0f4, 0x8017d62c }, 0xa58|2, 0xa58|2 }, // T1 - {{ 0x8017dc2c, 0x8017db8c, 0x8017db4c, 0x80089d3c }, 0x8|3, 0x8|3 }, // T1 - {{ 0x8017dc34, 0x8017db94, 0x8017db54, 0x8017e08c }, 0x4a4|2, 0x4a4|2 }, // T1 - {{ 0x8017e0d8, 0x8017e038, 0x8017dff8, 0x800f3a18 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017e0dc, 0x8017e03c, 0x8017dffc, 0x8017e534 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017e0e0, 0x8017e040, 0x8017e000, 0x80102bd8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017e0e4, 0x8017e044, 0x8017e004, 0x8017e53c }, 0xe8|2, 0xe8|2 }, // T1 - {{ 0x8017e1cc, 0x8017e12c, 0x8017e0ec, 0x80186414 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017e1d0, 0x8017e130, 0x8017e0f0, 0x8017e628 }, 0x4c|2, 0x4c|2 }, // T1 - {{ 0x8017e21c, 0x8017e17c, 0x8017e13c, 0x80186414 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017e220, 0x8017e180, 0x8017e140, 0x8017e678 }, 0x80|2, 0x80|2 }, // T1 - {{ 0x8017e2a0, 0x8017e200, 0x8017e1c0, 0x80186414 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017e2a4, 0x8017e204, 0x8017e1c4, 0x8017e6fc }, 0x100|2, 0x100|2 }, // T1 - {{ 0x8017e3a4, 0x8017e304, 0x8017e2c4, 0x80102bd8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017e3a8, 0x8017e308, 0x8017e2c8, 0x8017e800 }, 0x140|2, 0x140|2 }, // T1 - {{ 0x8017e4e8, 0x8017e448, 0x8017e408, 0x80186414 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017e4ec, 0x8017e44c, 0x8017e40c, 0x8017e944 }, 0x80|2, 0x80|2 }, // T1 - {{ 0x8017e56c, 0x8017e4cc, 0x8017e48c, 0x80186414 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017e570, 0x8017e4d0, 0x8017e490, 0x8017e9c8 }, 0x650|2, 0x650|2 }, // T1 - {{ 0x8017ebc0, 0x8017eb20, 0x8017eae0, 0x801a4be8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017ebc4, 0x8017eb24, 0x8017eae4, 0x8017f01c }, 0xec|2, 0xec|2 }, // T1 + {{ 0x8017ca5c, 0x8017c9bc, 0x8017c97c, 0x8017ceb4 }, 0x2254|2, 0x2254|2 }, // T1 {{ 0x8017ecb4, 0x8017ec14, 0x8017ebd4, 0x8017eff4 }, 0x8|3, 0x8|3 }, // T1 - {{ 0x8017ece8, 0x8017ec48, 0x8017ec08, 0x8017f190 }, 0x33c|2, 0x33c|2 }, // T1 - {{ 0x8017f05c, 0x8017efbc, 0x8017ef7c, 0x801fade4 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017f068, 0x8017efc8, 0x8017ef88, 0x8017f510 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017f06c, 0x8017efcc, 0x8017ef8c, 0x80096e38 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017f080, 0x8017efe0, 0x8017efa0, 0x8013cd50 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017f084, 0x8017efe4, 0x8017efa4, 0x8017f52c }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017f0a4, 0x8017f004, 0x8017efc4, 0x80096e38 }, 0x4|3, 0x4|3 }, // T1 + {{ 0x8017ece8, 0x8017ec48, 0x8017ec08, 0x8017f190 }, 0x33c|2, 0x380|3 }, // T1 + {{ 0x8017f068, 0x8017efc8, 0x8017ef88, 0x8017f510 }, 0x20|2, 0x64|3 }, // T1 {{ 0x8017f0cc, 0x8017f02c, 0x8017efec, 0x8017f574 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017f0e8, 0x8017f048, 0x8017f008, 0x8017f5ac }, 0x150|2, 0x150|2 }, // T1 - {{ 0x8017f238, 0x8017f198, 0x8017f158, 0x8008f338 }, 0x8|3, 0x8|3 }, // T1 - {{ 0x8017f240, 0x8017f1a0, 0x8017f160, 0x8017f704 }, 0xe0|2, 0xe0|2 }, // T1 - {{ 0x8017f320, 0x8017f280, 0x8017f240, 0x802420dc }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017f324, 0x8017f284, 0x8017f244, 0x8017f7e8 }, 0x64|2, 0x64|2 }, // T1 - {{ 0x8017f388, 0x8017f2e8, 0x8017f2a8, 0x802421f4 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8017f38c, 0x8017f2ec, 0x8017f2ac, 0x8017f850 }, 0xac|2, 0xac|2 }, // T1 + {{ 0x8017f0e8, 0x8017f048, 0x8017f008, 0x8017f5ac }, 0x350|2, 0x350|2 }, // T1 {{ 0x8017f438, 0x8017f398, 0x8017f358, 0x8017f830 }, 0x8|3, 0x8|3 }, // T1 {{ 0x8017f440, 0x8017f3a0, 0x8017f360, 0x8017f904 }, 0x64|2, 0x64|2 }, // T1 - {{ 0x8017f4ac, 0x8017f40c, 0x8017f3cc, 0x8014a090 }, 0xc|2, 0xc|2 }, // T1 {{ 0x8017f4b8, 0x8017f418, 0x8017f3d8, 0x801778fc }, 0x1b4|2, 0x1b4|2 }, // T1 - {{ 0x8017f670, 0x8017f5d0, 0x8017f590, 0x8017f9cc }, 0x20acc|0, 0x20acc|0 }, // T1 - {{ 0x801a013c, 0x801e7330, 0x801e72f0, 0x801e772c }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801a0140, 0x801a00a0, 0x801a0060, 0x801a049c }, 0x56a4|0, 0x56a4|0 }, // T1 - {{ 0x801a57e4, 0x80242a08, 0x801a5704, 0x801a5b40 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801a57e8, 0x801a5748, 0x801a5708, 0x801a5b44 }, 0x1cc|2, 0x1cc|2 }, // T1 - {{ 0x801a59e0, 0x802070d4, 0x801a5900, 0x801a5d3c }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801a59e8, 0x801a5948, 0x801a5908, 0x801a5d44 }, 0x368|2, 0x368|2 }, // T1 - {{ 0x801a5d7c, 0x802070d4, 0x801a5c9c, 0x801a60d8 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801a5d84, 0x801a5ce4, 0x801a5ca4, 0x801a60e0 }, 0x3bc|2, 0x3bc|2 }, // T1 - {{ 0x801a6164, 0x802070d4, 0x801a6084, 0x801a64c0 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801a616c, 0x801a60cc, 0x801a608c, 0x801a64c8 }, 0x264|2, 0x264|2 }, // T1 - {{ 0x801a63fc, 0x802070d4, 0x801a631c, 0x801a6758 }, 0x4|3, 0x4|3 }, // T1 + {{ 0x8017f670, 0x8017f5d0, 0x8017f590, 0x8017f9cc }, 0x26344|0, 0x26378|1 }, // T1 + {{ 0x801a59e8, 0x801a5948, 0x801a5908, 0x801a5d44 }, 0x368|2, 0x39c|3 }, // T1 + {{ 0x801a5d84, 0x801a5ce4, 0x801a5ca4, 0x801a60e0 }, 0x3bc|2, 0x3e8|3 }, // T1 + {{ 0x801a616c, 0x801a60cc, 0x801a608c, 0x801a64c8 }, 0x264|2, 0x298|3 }, // T1 {{ 0x801a6404, 0x801a6364, 0x801a6324, 0x801a6760 }, 0x104|2, 0x104|2 }, // T1 - {{ 0x801a6534, 0x802070d4, 0x801a6454, 0x801a6890 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801a653c, 0x801a649c, 0x801a645c, 0x801a6898 }, 0x4534|0, 0x4534|0 }, // T1 - {{ 0x801aaa70, 0x801aa2d8, 0x801aa990, 0x801aa6d4 }, 0xc|2, 0xc|2 }, // T1 - {{ 0x801aaa94, 0x8014149c, 0x801aa9b4, 0x801415b4 }, 0xc|2, 0xc|2 }, // T1 - {{ 0x801aaaa4, 0x801aaa04, 0x801aa9c4, 0x801aae00 }, 0x72b8|0, 0x72b8|0 }, // T1 - {{ 0x801b1d5c, 0x801b1dd4, 0x801b1c7c, 0x801b21d0 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801b1d60, 0x801b1c48, 0x801b1c80, 0x801b2044 }, 0xc|2, 0xc|2 }, // T1 - {{ 0x801b1d6c, 0x801b1ccc, 0x801b1c8c, 0x801b20c8 }, 0x8d94|0, 0x8d94|0 }, // T1 + {{ 0x801a653c, 0x801a649c, 0x801a645c, 0x801a6898 }, 0x4534|0, 0x4568|1 }, // T1 + {{ 0x801aaaa4, 0x801aaa04, 0x801aa9c4, 0x801aae00 }, 0x1005c|0, 0x1005c|0 }, // T1 {{ 0x801bab00, 0x801aa9e0, 0x801baa20, 0x801aaddc }, 0x8|3, 0x8|3 }, // T1 {{ 0x801bab08, 0x801baa68, 0x801baa28, 0x801bae64 }, 0x4|0, 0x4|0 }, // T1 {{ 0x801bab0c, 0x801aa9ec, 0x801baa2c, 0x801aade8 }, 0x14|2, 0x14|2 }, // T1 - {{ 0x801bab20, 0x801baa80, 0x801baa40, 0x801bae7c }, 0x11468|0, 0x11468|0 }, // T1 - {{ 0x801cbf88, 0x80233680, 0x80233924, 0x80233d78 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x801cbf8c, 0x801cbeec, 0x801cbeac, 0x801cc2e8 }, 0x1c464|0, 0x1c464|0 }, // T1 + {{ 0x801bab20, 0x801baa80, 0x801baa40, 0x801bae7c }, 0x2d8d0|0, 0x2d8d0|0 }, // T1 {{ 0x801e83f8, 0x801e8358, 0x801e8318, 0x801e8820 }, 0x27904|0, 0x27904|0 }, // T1 - {{ 0x8020fd14, 0x8020fc74, 0x8020fc34, 0x8023eab8 }, 0x4|3, 0x4|3 }, // T1 {{ 0x8020fd18, 0x8020fc78, 0x8020fc38, 0x80210138 }, 0x50|2, 0x50|2 }, // T1 - {{ 0x8020fdbc, 0x8020fd1c, 0x8020fcdc, 0x8011bc98 }, 0x4|3, 0x4|3 }, // T1 - {{ 0x8020fde4, 0x8020fd44, 0x8020fd04, 0x80238838 }, 0xc|2, 0xc|2 }, // T1 {{ 0x8020fe10, 0x8020fd70, 0x8020fd30, 0x80210198 }, 0x264|2, 0x264|2 }, // T1 - {{ 0x80210074, 0x8020ffd4, 0x8020ff94, 0x801565d8 }, 0x18|2, 0x18|2 }, // T1 {{ 0x802100a0, 0x80210000, 0x8020ffc0, 0x80210414 }, 0x15e6c|0, 0x15e6c|0 }, // T1 {{ 0x80225f14, 0x80243f18, 0x80225e34, 0x80226288 }, 0x2dc|2, 0x2dc|2 }, // T1 {{ 0x802261f8, 0x80225e74, 0x80226118, 0x8022656c }, 0x1a0d0|0, 0x1a0d0|0 }, // T1 @@ -317,9 +156,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80245580, 0x80245258, 0x80244fd0, 0x80245460 }, 0x4|3, 0x4|3 }, // D4 {{ 0x802456b4, 0x8024539c, 0x80245064, 0x80245504 }, 0x2d0|0, 0x2d0|0 }, // D4 {{ 0x80245a18, 0x80245700, 0x802453c8, 0x802457f8 }, 0x57c|0, 0x57c|0 }, // D4 - {{ 0x80246028, 0x80245d10, 0x802459d8, 0x80245e00 }, 0x6dc4|0, 0x6dc4|0 }, // D4 - {{ 0x8024cdec, 0x8024cad4, 0x8024c79c, 0x80248ce0 }, 0x4|3, 0x4|3 }, // D4 - {{ 0x8024cdf0, 0x8024cad8, 0x8024c7a0, 0x8024cbc8 }, 0x5994|0, 0x5994|0 }, // D4 + {{ 0x80246028, 0x80245d10, 0x802459d8, 0x80245e00 }, 0xc75c|0, 0xc75c|0 }, // D4 {{ 0x8025278c, 0x80252474, 0x8025213c, 0x8025255c }, 0x32c|0, 0x32c|0 }, // D4 {{ 0x80252ab8, 0x802527a0, 0x80252468, 0x80252890 }, 0x498c|0, 0x498c|0 }, // D4 {{ 0x80257480, 0x80257160, 0x80256e20, 0x80257240 }, 0x1104|0, 0x1104|0 }, // D4 @@ -342,7 +179,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80274d5c, 0x80270a1c, 0x802746fc, 0x80262270 }, 0x4|3, 0x4|3 }, // D5 {{ 0x80274d60, 0x80270a20, 0x80274700, 0x80262b40 }, 0x50c4|0, 0x50c4|0 }, // D5 {{ 0x80279e28, 0x80275ae8, 0x802797c8, 0x80267cdc }, 0x5c|2, 0x5c|2 }, // D5 - {{ 0x80279e8c, 0x80275b4c, 0x8027982c, 0x80268a8c }, 0xc|2, 0xc|2 }, // D5 {{ 0x80279ea0, 0x80275b60, 0x80279840, 0x80267d50 }, 0x25e0|0, 0x31e0|1 }, // D5 {{ 0x8027d080, 0x80278d40, 0x8027ca20, 0x8026af30 }, 0x284|0, 0x420|1 }, // D5 {{ 0x8027d4a0, 0x80279160, 0x8027ce40, 0x8026b350 }, 0x13ac|0, 0x13ac|0 }, // D5 @@ -356,7 +192,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x8028a8f8, 0x802865b8, 0x8028a298, 0x802788ec }, 0x4c|2, 0x4c|2 }, // D5 {{ 0x8028a944, 0x80286604, 0x8028a2e4, 0x80278824 }, 0x4|3, 0x4|3 }, // D5 {{ 0x8028a950, 0x80286610, 0x8028a2f0, 0x80278940 }, 0x458|2, 0x458|2 }, // D5 - {{ 0x8028ada8, 0x80286a68, 0x8028a748, 0x80290568 }, 0x14|2, 0x14|2 }, // D5 {{ 0x8028adbc, 0x80286a7c, 0x8028a75c, 0x8027624c }, 0x4|3, 0x4|3 }, // D5 {{ 0x8028adcc, 0x80286a8c, 0x8028a76c, 0x80275f34 }, 0x4|3, 0x4|3 }, // D5 {{ 0x8028add0, 0x80286a90, 0x8028a770, 0x80278dc0 }, 0x12c8|2, 0x1338|3 }, // D5 @@ -366,9 +201,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x8028fc70, 0x8028fc70, 0x8028f610, 0x8027dc70 }, 0x4|3, 0x4|3 }, // D5 {{ 0x8028fc74, 0x8028b934, 0x8028f614, 0x8027dc74 }, 0xd074|2, 0xd098|3 }, // D5 {{ 0x8029cd0c, 0x802989cc, 0x8029c6ac, 0x8028ad0c }, 0x1f4|2, 0x1f4|2 }, // D5 - {{ 0x8029cf04, 0x80298bc4, 0x8029c8a4, 0x8028af0c }, 0x48|2, 0x48|2 }, // D5 - {{ 0x8029cf54, 0x80298c38, 0x8029c918, 0x8028af5c }, 0x4|3, 0x4|3 }, // D5 - {{ 0x8029cf68, 0x80298c28, 0x8029c908, 0x8028af70 }, 0x571c|0, 0x571c|0 }, // D5 + {{ 0x8029cf04, 0x80298bc4, 0x8029c8a4, 0x8028af0c }, 0x5780|0, 0x5780|0 }, // D5 {{ 0x802a2694, 0x8029e354, 0x802a2034, 0x80290694 }, 0x8e0|2, 0x8e0|2 }, // D5 {{ 0x802a2f78, 0x8029ea50, 0x802a2918, 0x80290f78 }, 0x10|2, 0x10|2 }, // D5 {{ 0x802a2f88, 0x8029fcd8, 0x802a2928, 0x80290f88 }, 0x4|3, 0x4|3 }, // D5 @@ -382,12 +215,9 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80350580, 0x8034c200, 0x8034ff00, 0x8033e580 }, 0x20|0, 0x34680|1 }, // BSS {{ 0x80384c00, 0x80380880, 0x80384580, 0x80372c00 }, 0xcdc|0, 0xcdc|0 }, // D6 {{ 0x803858e0, 0x80381560, 0x80385260, 0x803738e8 }, 0x6bc|0, 0x6bc|0 }, // D6 - {{ 0x80385fbc, 0x80381b64, 0x8038593c, 0x80373eec }, 0x4|3, 0x4|3 }, // D6 {{ 0x80385fc0, 0x80381c40, 0x80385940, 0x80373fe0 }, 0x44|0, 0x44|0 }, // BSS {{ 0x8038601c, 0x80381c84, 0x8038599c, 0x8037403c }, 0x8|3, 0x8|3 }, // BSS - {{ 0x80386044, 0x8033f2ac, 0x803859c4, 0x80374064 }, 0x2c|2, 0x2c|2 }, // BSS - {{ 0x803860b0, 0x80381d30, 0x80385a30, 0x803740d0 }, 0x24|2, 0x24|2 }, // BSS - {{ 0x80386124, 0x80381da4, 0x80385aa4, 0x8037252c }, 0x4|3, 0x4|3 }, // BSS + {{ 0x803860b0, 0x80381d30, 0x80385a30, 0x803740d0 }, 0x24|2, 0x78|3 }, // BSS {{ 0x80386128, 0x80381da8, 0x80385aa8, 0x80374148 }, 0x10|2, 0x10|2 }, // BSS {{ 0x8038613c, 0x80382444, 0x80385abc, 0x803747e4 }, 0x4|3, 0x4|3 }, // BSS {{ 0x80386160, 0x80381de0, 0x80385ae0, 0x80374180 }, 0x34|2, 0x58|3 }, // BSS @@ -416,9 +246,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x803868a0, 0x80382520, 0x80386220, 0x803748c0 }, 0x20|2, 0x84|3 }, // BSS {{ 0x80386924, 0x803825a4, 0x803862a4, 0x80374944 }, 0x24|2, 0x6c|3 }, // BSS {{ 0x80386990, 0x80382610, 0x80386310, 0x803749b0 }, 0x4|2, 0x44|3 }, // BSS - {{ 0x803869d4, 0x80382654, 0x80386354, 0x803749f4 }, 0x8|3, 0x8|3 }, // BSS - {{ 0x803869e0, 0x80352a94, 0x80386360, 0x80374a00 }, 0x4|3, 0x4|3 }, // BSS - {{ 0x803869e4, 0x80382664, 0x80386364, 0x80374a04 }, 0x20|2, 0x80|3 }, // BSS + {{ 0x803869d4, 0x80382654, 0x80386354, 0x803749f4 }, 0x30|2, 0x90|3 }, // BSS {{ 0x80386a64, 0x803826e4, 0x803863e4, 0x80374a84 }, 0xf0|2, 0xf0|2 }, // BSS {{ 0x80386b58, 0x803827e8, 0x803864d8, 0x80374b88 }, 0x1c|2, 0x1c|2 }, // BSS {{ 0x80386bac, 0x8038282c, 0x8038652c, 0x80374bcc }, 0x1c|2, 0x64|3 }, // BSS @@ -427,20 +255,15 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80386c5c, 0x803828dc, 0x803865dc, 0x80374c7c }, 0x20|2, 0x20|2 }, // BSS {{ 0x80386c80, 0x803823e8, 0x803860e8, 0x80374ca0 }, 0x8|3, 0x8|3 }, // BSS {{ 0x80386ca8, 0x80382928, 0x80386628, 0x80374cc8 }, 0x8|2, 0xa4|3 }, // BSS - {{ 0x80386d4c, 0x803829cc, 0x803866cc, 0x80374d6c }, 0x128|2, 0x128|2 }, // BSS - {{ 0x80386e80, 0x80382b00, 0x80386800, 0x80348428 }, 0x4|3, 0x4|3 }, // BSS + {{ 0x80386d4c, 0x803829cc, 0x803866cc, 0x80374d6c }, 0x128|2, 0x140|3 }, // BSS {{ 0x80386e8c, 0x80382b0c, 0x8038680c, 0x80374eac }, 0x18|2, 0x50|3 }, // BSS {{ 0x80386edc, 0x80382b5c, 0x8038685c, 0x80374efc }, 0x4c|2, 0x4c|2 }, // BSS {{ 0x80386f44, 0x80382bbc, 0x803868c4, 0x80374f64 }, 0x34|2, 0x34|2 }, // BSS {{ 0x80386fa0, 0x80382c20, 0x80386920, 0x80374fc8 }, 0x24|2, 0x24|2 }, // D7 - {{ 0x80386fcc, 0x80382c4c, 0x8038694c, 0x80375e84 }, 0x4|3, 0x4|3 }, // D7 {{ 0x80386fdc, 0x80382c5c, 0x8038695c, 0x8037500c }, 0x1b54|0, 0x1b54|0 }, // D7 {{ 0x80388b34, 0x803847b4, 0x803884b4, 0x80376b54 }, 0x1c4|0, 0x1c4|0 }, // D7 {{ 0x80388cf8, 0x80384970, 0x80388678, 0x80376d18 }, 0x3c0|0, 0x3c0|0 }, // D7 {{ 0x803890b8, 0x80384d90, 0x80388a38, 0x803770d8 }, 0x14|2, 0x14|2 }, // D7 - {{ 0x803890d8, 0x80383338, 0x80388a58, 0x803770f8 }, 0xc|2, 0xc|2 }, // D7 - {{ 0x803890e4, 0x80384d2c, 0x80388a64, 0x80377104 }, 0x44|2, 0x44|2 }, // D7 - {{ 0x80389130, 0x80383260, 0x80388ab0, 0x80377150 }, 0x4|3, 0x4|3 }, // D7 {{ 0x8038913c, 0x80384dbc, 0x80388abc, 0x8037715c }, 0x30|2, 0x30|2 }, // D7 {{ 0x8038916c, 0x802d2190, 0x802d5e90, 0x802c4510 }, 0xc|2, 0xc|2 }, // BSS {{ 0x80389178, 0x802a3094, 0x802a6d94, 0x80295414 }, 0x4|3, 0x4|3 }, // BSS @@ -450,20 +273,14 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80510a88, 0x8054f704, 0x80510408, 0x804feaa8 }, 0xe8|2, 0xe8|2 }, // REL1 {{ 0x80510b70, 0x8050c6fc, 0x805104f0, 0x804feb90 }, 0xccb4|0, 0xccb4|0 }, // REL1 {{ 0x8051d824, 0x805193b0, 0x8051d1a4, 0x8050b848 }, 0xca70|0, 0xca70|0 }, // REL1 - {{ 0x8052a294, 0x80525e20, 0x80529c14, 0x805183b0 }, 0xa4|2, 0xa4|2 }, // REL1 - {{ 0x8052a338, 0x80525ec4, 0x80529cb8, 0x80518390 }, 0x2f54|2, 0x2f54|2 }, // REL1 + {{ 0x8052a338, 0x80525ec4, 0x80529cb8, 0x80518390 }, 0x2f5c|0, 0x2f5c|0 }, // REL1 {{ 0x8052d294, 0x8054f7fc, 0x8052cc14, 0x8051b2ec }, 0x6b8|2, 0x6b8|2 }, // REL1 {{ 0x8052d94c, 0x805c4d48, 0x8052d2cc, 0x8051b9a4 }, 0x14|2, 0x14|2 }, // REL1 {{ 0x8052d968, 0x80528e20, 0x8052d2e8, 0x8051b9c0 }, 0x4890|0, 0x4890|0 }, // REL1 {{ 0x805321f8, 0x8052d6b0, 0x80531b78, 0x805b6a04 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x805321fc, 0x8052d6b4, 0x80531b7c, 0x80520254 }, 0x2540|0, 0x2540|0 }, // REL1 - {{ 0x8053473c, 0x8058b90c, 0x80591ab0, 0x80580188 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80534740, 0x8052fbf8, 0x805340c0, 0x80522798 }, 0x922c|0, 0x922c|0 }, // REL1 + {{ 0x805321fc, 0x8052d6b4, 0x80531b7c, 0x80520254 }, 0xb770|0, 0xb770|0 }, // REL1 {{ 0x8053d978, 0x8054fed0, 0x8053d2f8, 0x8052b9d0 }, 0x934|2, 0x934|2 }, // REL1 - {{ 0x8053e2dc, 0x805830ac, 0x8053dc5c, 0x8052c334 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x8053e36c, 0x80538e30, 0x8053dcec, 0x8052c3c4 }, 0x1a44|0, 0x1a44|0 }, // REL1 - {{ 0x8053fdb0, 0x8053a874, 0x805ef568, 0x8052de08 }, 0x8|3, 0x8|3 }, // REL1 - {{ 0x8053fdb8, 0x8053a87c, 0x8053f738, 0x8052de10 }, 0xfd6c|0, 0xfd6c|0 }, // REL1 + {{ 0x8053e36c, 0x80538e30, 0x8053dcec, 0x8052c3c4 }, 0x117b8|0, 0x117b8|0 }, // REL1 {{ 0x8054fb28, 0x805508c4, 0x8054f4a8, 0x8053db80 }, 0xa0c|0, 0xa0c|0 }, // REL1 {{ 0x80550544, 0x8054a5ec, 0x8054fec4, 0x8053e59c }, 0x3240|2, 0x3240|2 }, // REL1 {{ 0x80553784, 0x805512e0, 0x80553104, 0x805417dc }, 0xa4|2, 0xa4|2 }, // REL1 @@ -471,18 +288,15 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80553850, 0x8054d830, 0x805531d0, 0x805418a8 }, 0x1ed0|0, 0x1ed0|0 }, // REL1 {{ 0x8055572c, 0x805513ac, 0x805550ac, 0x80543784 }, 0x153f0|0, 0x153f0|0 }, // REL1 {{ 0x8056ab68, 0x805ae0e4, 0x8056a4e8, 0x80558bc0 }, 0xab8|2, 0xab8|2 }, // REL1 - {{ 0x8056b620, 0x80652b60, 0x8056afa0, 0x80559678 }, 0xc|2, 0xc|2 }, // REL1 {{ 0x8056b62c, 0x805d3b9c, 0x8056afac, 0x80559684 }, 0xc|2, 0xc|2 }, // REL1 {{ 0x8056b638, 0x805667e8, 0x8056afb8, 0x80559690 }, 0x89a4|0, 0x89a4|0 }, // REL1 {{ 0x8057402c, 0x805aebb4, 0x805739ac, 0x80562084 }, 0x1858|2, 0x1858|2 }, // REL1 - {{ 0x80575890, 0x80583f3c, 0x80575210, 0x805638e8 }, 0x10|2, 0x10|2 }, // REL1 {{ 0x805758d4, 0x805b041c, 0x80575254, 0x8056392c }, 0x158|2, 0x158|2 }, // REL1 {{ 0x80575a30, 0x8056f1cc, 0x805753b0, 0x80563a88 }, 0xe4e0|0, 0xe4e0|0 }, // REL1 {{ 0x80583f1c, 0x8057d6f8, 0x8058389c, 0x80571f74 }, 0x17604|0, 0x17604|0 }, // REL1 {{ 0x8059b590, 0x805b0578, 0x8059af10, 0x805895e8 }, 0x34f8|0, 0x34f8|0 }, // REL1 {{ 0x8059ea98, 0x80594d74, 0x8059e418, 0x8058caf0 }, 0x1a98|2, 0x1a98|2 }, // REL1 {{ 0x805a054c, 0x805b3a88, 0x8059fecc, 0x8058e5a4 }, 0x3c|2, 0x3c|2 }, // REL1 - {{ 0x805a05d0, 0x80588c78, 0x8059ff50, 0x8058e628 }, 0x40|2, 0x40|2 }, // REL1 {{ 0x805a068c, 0x805b3ac8, 0x805a000c, 0x8058e6e4 }, 0xde0|2, 0xde0|2 }, // REL1 {{ 0x805a147c, 0x805a0d1c, 0x805a0dfc, 0x8058f4d4 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x805a1484, 0x805b48b0, 0x805a0e04, 0x8058f4dc }, 0x38c|2, 0x38c|2 }, // REL1 @@ -497,48 +311,33 @@ static const addr_port_t addr_port_0[2050] = {{ 0x805b92f8, 0x805a3800, 0x805b8c78, 0x805a7350 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x805b9300, 0x8061f7f4, 0x805b8c80, 0x805a7358 }, 0x1820|2, 0x1820|2 }, // REL1 {{ 0x805bab28, 0x805ef59c, 0x805ba4a8, 0x805a8b80 }, 0xc|2, 0xc|2 }, // REL1 - {{ 0x805bab34, 0x805ca844, 0x805ba4b4, 0x805a8b8c }, 0x8|3, 0x8|3 }, // REL1 {{ 0x805bab40, 0x805b4f80, 0x805ba4c0, 0x805a8b98 }, 0x750|2, 0x750|2 }, // REL1 {{ 0x805bb2b4, 0x80621030, 0x805bac34, 0x805a930c }, 0x200c|0, 0x200c|0 }, // REL1 {{ 0x805bd2d4, 0x805b695c, 0x805bcc54, 0x805ab32c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805bd2e0, 0x80623050, 0x805bcc60, 0x805ab338 }, 0xb4|2, 0xb4|2 }, // REL1 - {{ 0x805bd394, 0x805b56f0, 0x805bcd14, 0x805ab3ec }, 0x1268|2, 0x1268|2 }, // REL1 - {{ 0x805be5fc, 0x805d9524, 0x805bdf7c, 0x805ac654 }, 0x4|3, 0x4|3 }, // REL1 + {{ 0x805bd394, 0x805b56f0, 0x805bcd14, 0x805ab3ec }, 0x1268|0, 0x1268|0 }, // REL1 {{ 0x805be600, 0x805b6968, 0x805bdf80, 0x805ac658 }, 0x58|2, 0x58|2 }, // REL1 - {{ 0x805be658, 0x8058be40, 0x805bdfd8, 0x805ac6b0 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805be65c, 0x806284dc, 0x805bdfdc, 0x805ac6b4 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805be660, 0x80623100, 0x805bdfe0, 0x805ac6b8 }, 0x180|2, 0x180|2 }, // REL1 {{ 0x805be83c, 0x80623284, 0x805be1bc, 0x805ac894 }, 0x514|2, 0x514|2 }, // REL1 {{ 0x805bed6c, 0x806237a8, 0x805be6ec, 0x805acdc4 }, 0x548|2, 0x548|2 }, // REL1 {{ 0x805bf2b8, 0x80617818, 0x805bec38, 0x805ad310 }, 0x20|2, 0x20|2 }, // REL1 {{ 0x805bf2dc, 0x80623d14, 0x805bec5c, 0x805ad334 }, 0x8c|2, 0x8c|2 }, // REL1 - {{ 0x805bf368, 0x80609184, 0x805bece8, 0x805ad3c0 }, 0x5c|2, 0x5c|2 }, // REL1 {{ 0x805bf3c4, 0x805b69c8, 0x805bed44, 0x805ad41c }, 0xa3c|2, 0xa3c|2 }, // REL1 {{ 0x805bfe14, 0x805b7424, 0x805bf794, 0x805ade6c }, 0x29c|2, 0x29c|2 }, // REL1 {{ 0x805c00b0, 0x805b7718, 0x805bfa30, 0x805ae108 }, 0x808|2, 0x808|2 }, // REL1 {{ 0x805c08d4, 0x805b7f3c, 0x805c0254, 0x805ae938 }, 0x124c|2, 0x124c|2 }, // REL1 - {{ 0x805c1b24, 0x8062144c, 0x805c14a4, 0x805afb88 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x805c1b34, 0x805b91a0, 0x805c14b4, 0x805afb98 }, 0x1aa4|2, 0x1aa4|2 }, // REL1 - {{ 0x805c35e8, 0x8061c6b4, 0x805c2f68, 0x805b164c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x805c35ec, 0x805ca844, 0x805c2f6c, 0x805b1650 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x805c35f4, 0x80623e04, 0x805c2f74, 0x805b1658 }, 0x57c|2, 0x57c|2 }, // REL1 - {{ 0x805c3b78, 0x80609198, 0x805c34f8, 0x805b1bdc }, 0x1c|2, 0x1c|2 }, // REL1 {{ 0x805c3bc8, 0x805bac60, 0x805c3548, 0x805b1c2c }, 0xb74|0, 0xb74|0 }, // REL1 {{ 0x805c4744, 0x8063be90, 0x805c40c4, 0x805b27a8 }, 0x1c|2, 0x1c|2 }, // REL1 {{ 0x805c4760, 0x806243d4, 0x805c40e0, 0x805b27c4 }, 0xff0|2, 0xff0|2 }, // REL1 {{ 0x805c5764, 0x8061e8a0, 0x805c50e4, 0x805b37c8 }, 0x34|2, 0x34|2 }, // REL1 {{ 0x805c5798, 0x805bb7e8, 0x805c5118, 0x805b37fc }, 0x55d0|2, 0x55d0|2 }, // REL1 - {{ 0x805cad68, 0x805e27f8, 0x805ca6e8, 0x805b8dcc }, 0x3c|2, 0x3c|2 }, // REL1 - {{ 0x805cada4, 0x806091b4, 0x805ca724, 0x805b8e08 }, 0x30|2, 0x30|2 }, // REL1 {{ 0x805cadd4, 0x8062541c, 0x805ca754, 0x805b8e38 }, 0x12b8|2, 0x12b8|2 }, // REL1 {{ 0x805cc098, 0x805a7444, 0x805b1cec, 0x805a03c4 }, 0x18|2, 0x18|2 }, // REL1 - {{ 0x805cc0c0, 0x80576b5c, 0x8057cd40, 0x8056b418 }, 0xc|2, 0xc|2 }, // REL1 {{ 0x805cc0d8, 0x80626700, 0x805cba38, 0x805ba11c }, 0x14|2, 0x14|2 }, // REL1 - {{ 0x805cc0f8, 0x8058e09c, 0x80594240, 0x80582918 }, 0xc|2, 0xc|2 }, // REL1 - {{ 0x805cc14c, 0x8058e09c, 0x80594240, 0x80582918 }, 0xc|2, 0xc|2 }, // REL1 - {{ 0x805cc184, 0x8053f5dc, 0x80544498, 0x80532b70 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805cc194, 0x8060aa04, 0x8063b490, 0x8062a13c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x805cc198, 0x805b6468, 0x805bda8c, 0x805ac164 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805cc1b4, 0x80626758, 0x805cba90, 0x805ba174 }, 0x4c|2, 0x4c|2 }, // REL1 {{ 0x805cc204, 0x806267a8, 0x805cbae0, 0x805ba1b0 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x805cc20c, 0x806267b0, 0x805cbae8, 0x805ba1cc }, 0x173c|2, 0x173c|2 }, // REL1 @@ -555,17 +354,13 @@ static const addr_port_t addr_port_0[2050] = {{ 0x805cf824, 0x805c2d04, 0x805cf100, 0x80605650 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x805cf82c, 0x805c2d0c, 0x805cf108, 0x805bd788 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x805cf840, 0x805c2d20, 0x805cf11c, 0x805bd7d4 }, 0x28|2, 0x28|2 }, // REL1 - {{ 0x805cf878, 0x805c2d58, 0x805cf154, 0x805bd9fc }, 0x854|2, 0x854|2 }, // REL1 - {{ 0x805d00cc, 0x805c35ac, 0x805cf9a8, 0x8069e478 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x805d00d4, 0x805c35b4, 0x805cf9b0, 0x805be258 }, 0xe8|2, 0xe8|2 }, // REL1 + {{ 0x805cf878, 0x805c2d58, 0x805cf154, 0x805bd9fc }, 0x944|2, 0x944|2 }, // REL1 {{ 0x805d01c4, 0x805c36a4, 0x805cfaa0, 0x805be34c }, 0x1084|2, 0x1084|2 }, // REL1 - {{ 0x805d124c, 0x805c472c, 0x805d0b28, 0x805d39dc }, 0x8|3, 0x8|3 }, // REL1 {{ 0x805d1258, 0x805c4738, 0x805d0b34, 0x805bf3f4 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805d125c, 0x805c473c, 0x805d0b38, 0x805bf3ec }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805d1260, 0x805c4740, 0x805d0b3c, 0x805bf3fc }, 0x604|2, 0x604|2 }, // REL1 {{ 0x805d1874, 0x8064c778, 0x805d1150, 0x805bfa10 }, 0x10|2, 0x10|2 }, // REL1 {{ 0x805d1884, 0x80627eec, 0x805d1160, 0x805bfa20 }, 0x5c0|2, 0x5c0|2 }, // REL1 - {{ 0x805d1e74, 0x8058be44, 0x805d1750, 0x805c0010 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805d1e80, 0x805c4d64, 0x805d175c, 0x805c001c }, 0x60f0|0, 0x60f0|0 }, // REL1 {{ 0x805d7f70, 0x806284e4, 0x805d784c, 0x805c610c }, 0x4058|0, 0x4058|0 }, // REL1 {{ 0x805dc024, 0x8062c540, 0x805db900, 0x805ca1c0 }, 0x27f8|0, 0x27f8|0 }, // REL1 @@ -578,10 +373,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x805ea774, 0x8061f7e8, 0x805ea050, 0x805d8910 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805ea778, 0x80631a50, 0x805ea054, 0x805d8914 }, 0x435c|2, 0x435c|2 }, // REL1 {{ 0x805eeb38, 0x80635e10, 0x805ee414, 0x805dcf58 }, 0x1c|2, 0x1c|2 }, // REL1 - {{ 0x805eeb58, 0x8052d930, 0x805ee434, 0x805dcf78 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805eeb64, 0x805d4090, 0x805ee440, 0x805dcf84 }, 0x41b0|0, 0x41b0|0 }, // REL1 - {{ 0x805f2d14, 0x8063fc3c, 0x805f25f0, 0x805e1134 }, 0x8|3, 0x8|3 }, // REL1 - {{ 0x805f2d1c, 0x8060d52c, 0x805f25f8, 0x805e113c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805f2d20, 0x80635e3c, 0x805f25fc, 0x805e1140 }, 0x4a24|2, 0x4a24|2 }, // REL1 {{ 0x805f7744, 0x80639348, 0x805f5b08, 0x805e464c }, 0x18|2, 0x18|2 }, // REL1 {{ 0x805f775c, 0x8063934c, 0x805f5b0c, 0x805e4650 }, 0x14|2, 0x14|2 }, // REL1 @@ -589,24 +381,15 @@ static const addr_port_t addr_port_0[2050] = {{ 0x805f7784, 0x8063934c, 0x805f5b0c, 0x805e4650 }, 0x14|2, 0x14|2 }, // REL1 {{ 0x805f7798, 0x8063a8b4, 0x805f7074, 0x805e5bb8 }, 0x1388|2, 0x1388|2 }, // REL1 {{ 0x805f8b24, 0x806e4bd4, 0x805f8400, 0x805e6f44 }, 0xc|2, 0xc|2 }, // REL1 - {{ 0x805f8b30, 0x805d824c, 0x805f840c, 0x805e6f50 }, 0x180c|2, 0x180c|2 }, // REL1 - {{ 0x805fa33c, 0x805d9a58, 0x805f97bc, 0x805e8300 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x805fa340, 0x805d9a5c, 0x805f9c1c, 0x805e8760 }, 0x1270|2, 0x1270|2 }, // REL1 - {{ 0x805fb5b0, 0x8061aa1c, 0x805fae8c, 0x805e99d0 }, 0x4|3, 0x4|3 }, // REL1 + {{ 0x805f8b30, 0x805d824c, 0x805f840c, 0x805e6f50 }, 0x2a80|0, 0x2a80|0 }, // REL1 {{ 0x805fb5b8, 0x8063bc4c, 0x805fae94, 0x805e99d8 }, 0x244|2, 0x244|2 }, // REL1 - {{ 0x805fb80c, 0x8058c0d4, 0x805fb0e8, 0x805e9c2c }, 0x8|3, 0x8|3 }, // REL1 {{ 0x805fb814, 0x805aebac, 0x805fb0f0, 0x805e9c34 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805fb81c, 0x805dacd4, 0x805fb0f8, 0x805e9c3c }, 0x1cf4|2, 0x1cf4|2 }, // REL1 {{ 0x805fd514, 0x8063beb0, 0x805fcdf0, 0x805eb934 }, 0x241c|2, 0x241c|2 }, // REL1 {{ 0x805ff930, 0x8063e2cc, 0x805bf164, 0x805edd50 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x805ff934, 0x8063e2d0, 0x806b27bc, 0x805edd54 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x805ff958, 0x8063e2f4, 0x8062f5a8, 0x805edd78 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805ff970, 0x8063e30c, 0x805ff230, 0x805edd90 }, 0x2d4|2, 0x2d4|2 }, // REL1 - {{ 0x805ffc4c, 0x8063e5e8, 0x805da18c, 0x805ee06c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x805ffc64, 0x8063e600, 0x805ff51c, 0x805ee084 }, 0xf0|2, 0xf0|2 }, // REL1 {{ 0x805ffd64, 0x8063e700, 0x805ff51c, 0x805ee184 }, 0x658|2, 0x658|2 }, // REL1 - {{ 0x806003c8, 0x8063ed64, 0x8053cbc8, 0x805ee7e8 }, 0x8|3, 0x8|3 }, // REL1 - {{ 0x806003d0, 0x8063ed6c, 0x8065415c, 0x805ee7f0 }, 0xc|2, 0xc|2 }, // REL1 {{ 0x806003fc, 0x8063ed98, 0x805dee38, 0x805ee81c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8060045c, 0x8063edf8, 0x805ff94c, 0x805ee87c }, 0x2c|2, 0x2c|2 }, // REL1 {{ 0x80600488, 0x8063ee24, 0x805ffc30, 0x805ee8a8 }, 0x174|2, 0x174|2 }, // REL1 @@ -619,59 +402,35 @@ static const addr_port_t addr_port_0[2050] = {{ 0x806012ac, 0x805dc9cc, 0x80600a20, 0x805ef6cc }, 0x7a48|0, 0x7a48|0 }, // REL1 {{ 0x80608d10, 0x805e443c, 0x80608484, 0x805f7130 }, 0x1a18|0, 0x1a18|0 }, // REL1 {{ 0x8060a728, 0x8063fc48, 0x80609e9c, 0x805f8b48 }, 0x70ac|2, 0x70ac|2 }, // REL1 - {{ 0x806117d4, 0x80609154, 0x80610f48, 0x805ffbf4 }, 0x8c|2, 0x8c|2 }, // REL1 {{ 0x80611860, 0x805e5e4c, 0x80610fd4, 0x805ffc80 }, 0x4fdc|0, 0x4fdc|0 }, // REL1 {{ 0x8061683c, 0x80646d84, 0x80615fb0, 0x80604c5c }, 0x45f4|2, 0x45f4|2 }, // REL1 {{ 0x8061ae60, 0x806dc7dc, 0x8061a5d4, 0x80609280 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8061ae68, 0x805eae2c, 0x8061a5dc, 0x80609288 }, 0x3a24|2, 0x3a24|2 }, // REL1 - {{ 0x8061e88c, 0x8061c8bc, 0x8061e000, 0x8060ccac }, 0x8|3, 0x8|3 }, // REL1 {{ 0x8061e894, 0x8064b3b0, 0x8061e008, 0x8060ccb4 }, 0xe00|2, 0xe00|2 }, // REL1 {{ 0x8061f694, 0x8061e898, 0x8061ee08, 0x8060dab4 }, 0x3c|2, 0x3c|2 }, // REL1 - {{ 0x8061f6d0, 0x80617bcc, 0x8061ee44, 0x8060daf0 }, 0x10|2, 0x10|2 }, // REL1 - {{ 0x8061f6e0, 0x805ee854, 0x8061ee54, 0x8060db00 }, 0x15e4|2, 0x15e4|2 }, // REL1 - {{ 0x80620cc4, 0x8069cdec, 0x806a08e0, 0x8068f61c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80620cc8, 0x805efe3c, 0x8062043c, 0x8060f0e8 }, 0x64|2, 0x64|2 }, // REL1 - {{ 0x80620d44, 0x805c1d74, 0x805ce170, 0x805bc854 }, 0x4|3, 0x4|3 }, // REL1 + {{ 0x8061f6e0, 0x805ee854, 0x8061ee54, 0x8060db00 }, 0x164c|2, 0x164c|2 }, // REL1 {{ 0x80620d7c, 0x805efec8, 0x806204c8, 0x8060f174 }, 0x141c8|0, 0x141c8|0 }, // REL1 {{ 0x80634f44, 0x806040ac, 0x80634690, 0x8062333c }, 0x2544|2, 0x2544|2 }, // REL1 - {{ 0x80637488, 0x805e0d14, 0x80636bd4, 0x80625880 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x80637490, 0x806066a0, 0x80636bdc, 0x80625888 }, 0x7c|2, 0x7c|2 }, // REL1 {{ 0x80637510, 0x8064c200, 0x80636c5c, 0x80625908 }, 0x4dc|2, 0x4dc|2 }, // REL1 - {{ 0x80637a04, 0x8064c6f4, 0x80592240, 0x80580918 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80637a18, 0x8064c708, 0x80701fa4, 0x806f0ce0 }, 0x8|3, 0x8|3 }, // REL1 - {{ 0x80637a30, 0x805c5a8c, 0x805d2484, 0x805c0d44 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x80637a80, 0x8064c748, 0x8063716c, 0x80625e18 }, 0x40|2, 0x40|2 }, // REL1 {{ 0x80637ac0, 0x80606720, 0x806371ac, 0x80625e58 }, 0x4218|0, 0x4218|0 }, // REL1 - {{ 0x8063bcdc, 0x806d56d0, 0x806e5d80, 0x806d4abc }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x8063bce0, 0x805e2e38, 0x80606e8c, 0x805f5b38 }, 0x14|2, 0x14|2 }, // REL1 - {{ 0x8063bcf4, 0x806d56e8, 0x806e5d98, 0x806d4ad4 }, 0x18|2, 0x18|2 }, // REL1 + {{ 0x8063bcdc, 0x806d56d0, 0x806e5d80, 0x806d4abc }, 0x30|2, 0x30|2 }, // REL1 {{ 0x8063bd18, 0x805ece08, 0x8061c5b8, 0x8060b264 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x8063bd48, 0x80724cb8, 0x8072b510, 0x8071a24c }, 0x8|3, 0x8|3 }, // REL1 - {{ 0x8063bd50, 0x8070599c, 0x8070b9ac, 0x806fa6e8 }, 0x8|3, 0x8|3 }, // REL1 - {{ 0x8063bd6c, 0x80655050, 0x80658b44, 0x806477f0 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x8063bd98, 0x80655050, 0x80658b44, 0x806477f0 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8063bda8, 0x8060a9c8, 0x8063b454, 0x8062a100 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x8063bdc0, 0x807059a0, 0x8070b9b0, 0x806fa6ec }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x8063bdd8, 0x8060a9bc, 0x8063b448, 0x8062a0f4 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x8063be04, 0x80655050, 0x80658b44, 0x806477f0 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x8063be10, 0x8055be04, 0x8055fb04, 0x8054e1dc }, 0x4|3, 0x4|3 }, // REL1 + {{ 0x8063bdd8, 0x8060a9bc, 0x8063b448, 0x8062a0f4 }, 0x4|2, 0x3c|3 }, // REL1 {{ 0x8063be14, 0x8060a9f8, 0x8063b484, 0x8062a130 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x8063be1c, 0x806d0118, 0x806e0434, 0x806cf170 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x8063be2c, 0x8060aa0c, 0x8063b498, 0x8062a144 }, 0x952c|0, 0x952c|0 }, // REL1 - {{ 0x80645360, 0x80609168, 0x806449cc, 0x80633678 }, 0x80|2, 0x80|2 }, // REL1 {{ 0x806453e0, 0x8064c788, 0x80644a4c, 0x806336f8 }, 0x13d0|0, 0x13d0|0 }, // REL1 {{ 0x806467bc, 0x80631130, 0x80645e28, 0x80634ad4 }, 0x8|3, 0x8|3 }, // REL1 - {{ 0x806467c4, 0x8061c8b8, 0x80645e30, 0x80634adc }, 0x4|3, 0x4|3 }, // REL1 {{ 0x806467c8, 0x80613fb8, 0x80645e34, 0x80634ae0 }, 0x3c0c|2, 0x3c0c|2 }, // REL1 {{ 0x8064a3d4, 0x8063be94, 0x80649a40, 0x806386ec }, 0x14|2, 0x14|2 }, // REL1 {{ 0x8064a3e8, 0x80725270, 0x80649a54, 0x80638700 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8064a3ec, 0x8064db74, 0x80649a58, 0x80638704 }, 0xac0|0, 0xac0|0 }, // REL1 {{ 0x8064aec8, 0x8061e8bc, 0x8064a534, 0x806391e0 }, 0x18|2, 0x18|2 }, // REL1 - {{ 0x8064aee0, 0x80617bcc, 0x8064a54c, 0x806391f8 }, 0x3b1c|0, 0x3b1c|0 }, // REL1 - {{ 0x8064e9fc, 0x8061b6e8, 0x8064e068, 0x80582134 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x8064ea00, 0x8061b6ec, 0x8064e06c, 0x8063cd18 }, 0xbac|0, 0xbac|0 }, // REL1 - {{ 0x8064f5ac, 0x8061c298, 0x8064ec18, 0x805c003c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x8064f5b0, 0x8061c29c, 0x8064ec1c, 0x8063d8c8 }, 0x25fc|0, 0x25fc|0 }, // REL1 + {{ 0x8064aee0, 0x80617bcc, 0x8064a54c, 0x806391f8 }, 0x6ccc|0, 0x6ccc|0 }, // REL1 {{ 0x80651bb4, 0x806253d8, 0x80651220, 0x8063fecc }, 0x1c|2, 0x1c|2 }, // REL1 {{ 0x80651bd0, 0x8064e650, 0x8065123c, 0x8063fee8 }, 0x6f0|2, 0x6f0|2 }, // REL1 {{ 0x806522c0, 0x805bf784, 0x8065192c, 0x806405d8 }, 0x14|2, 0x14|2 }, // REL1 @@ -686,14 +445,11 @@ static const addr_port_t addr_port_0[2050] = {{ 0x8065fa4c, 0x80657ad0, 0x8065f0b8, 0x8064dd64 }, 0x3f4|2, 0x3f4|2 }, // REL1 {{ 0x8065fe40, 0x80657f04, 0x8065f4ac, 0x8064e158 }, 0x292c|0, 0x292c|0 }, // REL1 {{ 0x8066276c, 0x8071413c, 0x80661dd8, 0x80650a84 }, 0x8|3, 0x8|3 }, // REL1 - {{ 0x80662774, 0x80660690, 0x80661de0, 0x80650a8c }, 0xa04|2, 0xa04|2 }, // REL1 + {{ 0x80662774, 0x80660690, 0x80661de0, 0x80650a8c }, 0xa04|0, 0xa04|0 }, // REL1 {{ 0x80663178, 0x8065a820, 0x806627e4, 0x80651490 }, 0x2334|0, 0x2334|0 }, // REL1 - {{ 0x806654ac, 0x8065ca9c, 0x80664b18, 0x806537c4 }, 0x78|2, 0x78|2 }, // REL1 {{ 0x8066552c, 0x8067317c, 0x80664b98, 0x80653844 }, 0x2cb8|2, 0x2cb8|2 }, // REL1 {{ 0x806681e4, 0x80675e34, 0x80667850, 0x805af934 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x806681e8, 0x80675e38, 0x80667854, 0x80656500 }, 0x8|3, 0x8|3 }, // REL1 - {{ 0x80668274, 0x80675ec4, 0x806678e0, 0x8065ee28 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80668310, 0x80675f60, 0x8066797c, 0x8063e918 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x8066832c, 0x80675f7c, 0x80667998, 0x80656678 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x80668330, 0x80675f80, 0x8066799c, 0x80656688 }, 0x4dc|2, 0x4dc|2 }, // REL1 {{ 0x80668810, 0x806610ac, 0x80667e7c, 0x80656b68 }, 0xcc40|0, 0xcc40|0 }, // REL1 @@ -736,12 +492,9 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80675f1c, 0x8066e7b8, 0x80675588, 0x8066427c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x80675f20, 0x8066e7bc, 0x8067558c, 0x80664260 }, 0xc|2, 0xc|2 }, // REL1 {{ 0x80675f2c, 0x8066e7c8, 0x80675598, 0x8066428c }, 0x12c0|2, 0x12c0|2 }, // REL1 - {{ 0x806771ec, 0x8066fa88, 0x80676858, 0x806482a8 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x806771f4, 0x8066fa90, 0x80676860, 0x8066559c }, 0x1e2c|2, 0x1e2c|2 }, // REL1 {{ 0x80679068, 0x80676460, 0x806786d4, 0x80667410 }, 0x300|2, 0x300|2 }, // REL1 {{ 0x80679380, 0x80671908, 0x806789ec, 0x80667728 }, 0x186c|2, 0x186c|2 }, // REL1 - {{ 0x8067abf0, 0x805812fc, 0x8067a25c, 0x80668f98 }, 0xc|2, 0xc|2 }, // REL1 - {{ 0x8067abfc, 0x805ca84c, 0x8067a268, 0x80668fa4 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8067ac00, 0x80676778, 0x8067a26c, 0x80668fa8 }, 0x8bb8|2, 0x8bb8|2 }, // REL1 {{ 0x806837b8, 0x8067e554, 0x80682048, 0x80670d84 }, 0xddc|2, 0xddc|2 }, // REL1 {{ 0x80684594, 0x8067e554, 0x80682048, 0x80670d84 }, 0x8cc|2, 0x8cc|2 }, // REL1 @@ -770,7 +523,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x806ce5f4, 0x806e9f70, 0x806ef0b4, 0x806bc99c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x806ce5f8, 0x806e9f74, 0x806cdc64, 0x806bc9a0 }, 0x21c|2, 0x21c|2 }, // REL1 {{ 0x806ce814, 0x806ede54, 0x806cde80, 0x806bcbbc }, 0x8|3, 0x8|3 }, // REL1 - {{ 0x806ce81c, 0x806b327c, 0x806cde88, 0x806bcbc4 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x806ce820, 0x806c2294, 0x806cde8c, 0x806bcbc8 }, 0xccc|2, 0xccc|2 }, // REL1 {{ 0x806cf4ec, 0x807774ac, 0x806ceb58, 0x806bd894 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x806cf4f0, 0x806c2f64, 0x806ceb5c, 0x806bd898 }, 0x258|2, 0x258|2 }, // REL1 @@ -782,30 +534,10 @@ static const addr_port_t addr_port_0[2050] = {{ 0x806d08bc, 0x80777d3c, 0x806cff28, 0x806bec64 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x806d08c0, 0x806ea7a0, 0x806cff2c, 0x806bec68 }, 0x2020|2, 0x2020|2 }, // REL1 {{ 0x806d28fc, 0x806c1e14, 0x806d1f68, 0x806c0ca4 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x806d2900, 0x807c3790, 0x806d1f6c, 0x806c0ca8 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x806d2908, 0x806c3d38, 0x806d1f74, 0x806c0cb0 }, 0x84|2, 0x84|2 }, // REL1 - {{ 0x806d298c, 0x80658b30, 0x806600d8, 0x8064ed84 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x806d2990, 0x806c3dc0, 0x806d1ffc, 0x806c0d38 }, 0x32c8|2, 0x32c8|2 }, // REL1 + {{ 0x806d2908, 0x806c3d38, 0x806d1f74, 0x806c0cb0 }, 0x3350|2, 0x3350|2 }, // REL1 {{ 0x806d5c58, 0x806ec7cc, 0x806d52c4, 0x806c4000 }, 0x26c|2, 0x26c|2 }, // REL1 - {{ 0x806d5ed4, 0x806c7094, 0x806d5540, 0x806c427c }, 0x934|2, 0x934|2 }, // REL1 - {{ 0x806d6808, 0x805f7c90, 0x80628290, 0x80616f3c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x806d680c, 0x806c79cc, 0x806d5e78, 0x806c4bb4 }, 0x20|2, 0x20|2 }, // REL1 - {{ 0x806d682c, 0x805f7c90, 0x80628290, 0x80616f3c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x806d6830, 0x806c79f0, 0x806d5e9c, 0x806c4bd8 }, 0x20|2, 0x20|2 }, // REL1 - {{ 0x806d6850, 0x805f7c90, 0x80628290, 0x80616f3c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x806d6854, 0x806c7a14, 0x806d5ec0, 0x806c4bfc }, 0x192c|2, 0x192c|2 }, // REL1 - {{ 0x806d8180, 0x806f6748, 0x806fad1c, 0x806e9a58 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x806d8184, 0x806c9344, 0x806d77f0, 0x806c652c }, 0xac4|2, 0xac4|2 }, // REL1 - {{ 0x806d8c48, 0x806ccbc8, 0x806db8e4, 0x806ca620 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x806d8c4c, 0x806c9e0c, 0x806d82b8, 0x806c6ff4 }, 0xa0|2, 0xa0|2 }, // REL1 - {{ 0x806d8cec, 0x806f6748, 0x806fad1c, 0x806e9a58 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x806d8cf0, 0x806c9eb0, 0x806d835c, 0x806c7098 }, 0xf24|2, 0xf24|2 }, // REL1 - {{ 0x806d9c14, 0x806f6748, 0x806fad1c, 0x806e9a58 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x806d9c18, 0x806cadd8, 0x806d9284, 0x806c7fc0 }, 0xd0|2, 0xd0|2 }, // REL1 - {{ 0x806d9ce8, 0x806f6748, 0x806fad1c, 0x806e9a58 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x806d9cec, 0x806caeac, 0x806d9358, 0x806c8094 }, 0xbc8|2, 0xbc8|2 }, // REL1 + {{ 0x806d5ed4, 0x806c7094, 0x806d5540, 0x806c427c }, 0x49e0|2, 0x49e0|2 }, // REL1 {{ 0x806da8b4, 0x806d850c, 0x806d9f20, 0x806c8c5c }, 0x54|2, 0x54|2 }, // REL1 - {{ 0x806da908, 0x806cdc1c, 0x806d9f74, 0x806c8cb0 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x806da910, 0x806e4d54, 0x806d9f7c, 0x806c8cb8 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x806da914, 0x806eca58, 0x806d9f80, 0x806c8cbc }, 0x85c|2, 0x85c|2 }, // REL1 {{ 0x806db174, 0x806d5b28, 0x806da7e0, 0x806c951c }, 0xc|2, 0xc|2 }, // REL1 @@ -820,7 +552,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x806e3a78, 0x806e6580, 0x806e30e4, 0x806d1e20 }, 0x10|2, 0x10|2 }, // REL1 {{ 0x806e3a8c, 0x806ee8c8, 0x806e30f8, 0x806d1e34 }, 0x348|2, 0x348|2 }, // REL1 {{ 0x806e3e20, 0x806d2ddc, 0x806e348c, 0x806d21c8 }, 0x5784|2, 0x5784|2 }, // REL1 - {{ 0x806e95a4, 0x806cdc1c, 0x806e8c10, 0x806d794c }, 0x8|3, 0x8|3 }, // REL1 {{ 0x806e95b0, 0x806eec5c, 0x806e8c1c, 0x806d7958 }, 0x31f8|2, 0x31f8|2 }, // REL1 {{ 0x806ec7a8, 0x806e6574, 0x806ebe14, 0x806dab50 }, 0x14|2, 0x14|2 }, // REL1 {{ 0x806ec7bc, 0x806d8560, 0x806ebe28, 0x806dab64 }, 0xd70|2, 0xd70|2 }, // REL1 @@ -831,7 +562,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x806f77c0, 0x80713a74, 0x806f6e2c, 0x806e5b68 }, 0x260|2, 0x260|2 }, // REL1 {{ 0x806f7a20, 0x80713f0c, 0x806f708c, 0x806e5dc8 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x806f7a3c, 0x806f5428, 0x806f70a8, 0x806e5de4 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x806f7a40, 0x806f5768, 0x806f70ac, 0x806e5de8 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x806f7a74, 0x806d8a30, 0x806f70e0, 0x806e5e1c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x806f7a90, 0x80713cf0, 0x806f70fc, 0x806e5e38 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x806f7a98, 0x80713acc, 0x806f7104, 0x806e5e40 }, 0xc|2, 0xc|2 }, // REL1 @@ -848,7 +578,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x8070019c, 0x8070ff18, 0x806ff808, 0x806ee544 }, 0x64|2, 0x64|2 }, // REL1 {{ 0x8070022c, 0x806dc7f4, 0x806ff898, 0x806ee5d4 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x80700230, 0x80715c44, 0x806ff89c, 0x806ee5d8 }, 0x23c|2, 0x23c|2 }, // REL1 - {{ 0x8070046c, 0x806f9ac8, 0x806ffad8, 0x806ee814 }, 0xe300|2, 0xe300|2 }, // REL1 + {{ 0x8070046c, 0x806f9ac8, 0x806ffad8, 0x806ee814 }, 0xe300|0, 0xe300|0 }, // REL1 {{ 0x8070e7b8, 0x80715e88, 0x8070de24, 0x806fcb60 }, 0x10ec|2, 0x10ec|2 }, // REL1 {{ 0x8070f8b8, 0x80707e14, 0x8070ef24, 0x806fdc60 }, 0x80f0|0, 0x80f0|0 }, // REL1 {{ 0x807179c4, 0x8070ffac, 0x80717030, 0x80705d6c }, 0x46c|2, 0x46c|2 }, // REL1 @@ -860,7 +590,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80726570, 0x8073c5d8, 0x80725bdc, 0x80714918 }, 0x1c8c|2, 0x1c8c|2 }, // REL1 {{ 0x80728218, 0x8073e270, 0x80727884, 0x807165c0 }, 0x398|2, 0x398|2 }, // REL1 {{ 0x807285b4, 0x80745450, 0x80727c20, 0x8071695c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x807285c4, 0x80721178, 0x80727c30, 0x8071696c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x807285c8, 0x8073e61c, 0x80727c34, 0x80716970 }, 0xd54|2, 0xd54|2 }, // REL1 {{ 0x8072931c, 0x808227a8, 0x80728988, 0x807176c4 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8072932c, 0x80724754, 0x80728998, 0x807176d4 }, 0x8|3, 0x8|3 }, // REL1 @@ -874,20 +603,15 @@ static const addr_port_t addr_port_0[2050] = {{ 0x8072dfcc, 0x8073f390, 0x8072d638, 0x8071c374 }, 0x1f78|2, 0x1f78|2 }, // REL1 {{ 0x8072ff5c, 0x807276cc, 0x8072f5c8, 0x8071e304 }, 0x10|2, 0x10|2 }, // REL1 {{ 0x8072ff74, 0x80741320, 0x8072f5e0, 0x8071e31c }, 0x1fc|2, 0x1fc|2 }, // REL1 - {{ 0x80730178, 0x8071dd74, 0x8072f7e4, 0x8071e520 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8073017c, 0x807f8418, 0x8072f7e8, 0x8071e524 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x80730184, 0x80726dd4, 0x8072f7f0, 0x8071e52c }, 0x8e0|2, 0x8e0|2 }, // REL1 - {{ 0x80730a68, 0x80721168, 0x807300d4, 0x8071ee10 }, 0x14|2, 0x14|2 }, // REL1 - {{ 0x80730a7c, 0x8073385c, 0x807300e8, 0x8071ee24 }, 0xb8|2, 0xb8|2 }, // REL1 {{ 0x80730b34, 0x80741538, 0x807301a0, 0x8071eedc }, 0xe08|2, 0xe08|2 }, // REL1 - {{ 0x80731944, 0x807e78e0, 0x80730fb0, 0x8071fcec }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8073194c, 0x80727794, 0x80730fb8, 0x8071fcf4 }, 0x3fe0|2, 0x3fe0|2 }, // REL1 {{ 0x80735934, 0x80742350, 0x80734fa0, 0x80723cdc }, 0x33b8|2, 0x33b8|2 }, // REL1 {{ 0x80738cec, 0x80741328, 0x80738358, 0x80727094 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x80738da4, 0x8072b77c, 0x80738410, 0x8072714c }, 0x37a4|2, 0x37a4|2 }, // REL1 {{ 0x8073c548, 0x807457d0, 0x8073bbb4, 0x8072a8f0 }, 0x2898|2, 0x2898|2 }, // REL1 - {{ 0x8073edec, 0x8072ef20, 0x8073e458, 0x8072d194 }, 0x3d8c|2, 0x3d8c|2 }, // REL1 - {{ 0x80742b78, 0x80732cac, 0x807421e4, 0x80730f18 }, 0x4|3, 0x4|3 }, // REL1 + {{ 0x8073edec, 0x8072ef20, 0x8073e458, 0x8072d194 }, 0x3d8c|0, 0x3d8c|0 }, // REL1 {{ 0x80742b88, 0x80732cbc, 0x807421f4, 0x807289f8 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x80742b94, 0x80732cc8, 0x80742200, 0x80730f54 }, 0x28c|2, 0x28c|2 }, // REL1 {{ 0x80742e20, 0x80732f54, 0x8074248c, 0x807311cc }, 0x4|3, 0x4|3 }, // REL1 @@ -898,7 +622,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80743140, 0x80733274, 0x807427ac, 0x80731500 }, 0x10|2, 0x10|2 }, // REL1 {{ 0x80743150, 0x80733284, 0x807427bc, 0x807314d4 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x80743154, 0x80733288, 0x807427c0, 0x80731514 }, 0x9310|0, 0x9310|0 }, // REL1 - {{ 0x8074c4a4, 0x80769350, 0x8074bb10, 0x8073a864 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8074c4a8, 0x8076ceac, 0x8074bb14, 0x8073a868 }, 0x10e4|0, 0x10e4|0 }, // REL1 {{ 0x8074d5b8, 0x80748078, 0x8074cc24, 0x8073b978 }, 0x440c|2, 0x440c|2 }, // REL1 {{ 0x807519c4, 0x80759e3c, 0x80751030, 0x8073fd84 }, 0x4|3, 0x4|3 }, // REL1 @@ -907,7 +630,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80753f68, 0x8075c35c, 0x807535d4, 0x80742328 }, 0x198|2, 0x198|2 }, // REL1 {{ 0x80754100, 0x8074c484, 0x8075376c, 0x807424c0 }, 0x4ab4|2, 0x4ab4|2 }, // REL1 {{ 0x80758bc4, 0x807cacf4, 0x80758230, 0x80746f84 }, 0x14|2, 0x14|2 }, // REL1 - {{ 0x80758bd8, 0x80683998, 0x80758244, 0x80746f98 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x80758bdc, 0x807706f8, 0x80758248, 0x80746f9c }, 0x4f48|2, 0x4f48|2 }, // REL1 {{ 0x8075db24, 0x80750f48, 0x8075d190, 0x8074bee4 }, 0xc0c|2, 0xc0c|2 }, // REL1 {{ 0x8075e730, 0x8077d4f0, 0x8075dd9c, 0x8074caf0 }, 0x10|2, 0x10|2 }, // REL1 @@ -918,14 +640,11 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80765bc4, 0x8075c428, 0x80765230, 0x80753f84 }, 0xc0|2, 0xc0|2 }, // REL1 {{ 0x80765c90, 0x807759c4, 0x807652fc, 0x80754050 }, 0x1bb8|2, 0x1bb8|2 }, // REL1 {{ 0x80767848, 0x8067c250, 0x80766eb4, 0x80755c08 }, 0x54|2, 0x54|2 }, // REL1 - {{ 0x807678f0, 0x80758d44, 0x80766f5c, 0x80755cb0 }, 0x140c|2, 0x140c|2 }, // REL1 - {{ 0x80768cfc, 0x80816614, 0x80768368, 0x807570bc }, 0x8|3, 0x8|3 }, // REL1 - {{ 0x80768d04, 0x8075a158, 0x80768370, 0x807570c4 }, 0x8|3, 0x8|3 }, // REL1 + {{ 0x807678f0, 0x80758d44, 0x80766f5c, 0x80755cb0 }, 0x141c|2, 0x141c|2 }, // REL1 {{ 0x80768d0c, 0x8077e048, 0x80768378, 0x807570cc }, 0x8|3, 0x8|3 }, // REL1 {{ 0x80768d14, 0x8077db5c, 0x80768380, 0x807570d4 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x80768d1c, 0x80777624, 0x80768388, 0x807570dc }, 0x648|2, 0x648|2 }, // REL1 {{ 0x80769364, 0x8076687c, 0x807689d0, 0x80757724 }, 0x14|2, 0x14|2 }, // REL1 - {{ 0x80769398, 0x80817a94, 0x80768a04, 0x80757758 }, 0x3c|2, 0x3c|2 }, // REL1 {{ 0x807693d4, 0x80777674, 0x80768a40, 0x80757794 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x807693d8, 0x80777ca0, 0x80768a44, 0x80757798 }, 0x1a8|2, 0x1a8|2 }, // REL1 {{ 0x80769580, 0x806e87e8, 0x80768bec, 0x80757940 }, 0x14|2, 0x14|2 }, // REL1 @@ -933,48 +652,26 @@ static const addr_port_t addr_port_0[2050] = {{ 0x807695f0, 0x807768c8, 0x80768c5c, 0x807579b0 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x807695f4, 0x806e6550, 0x80768c60, 0x807579b4 }, 0x18|2, 0x18|2 }, // REL1 {{ 0x8076960c, 0x80777e68, 0x80768c78, 0x807579cc }, 0x3228|2, 0x3228|2 }, // REL1 - {{ 0x8076c854, 0x80688548, 0x8076bec0, 0x8075ac14 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8076c858, 0x8075a170, 0x8076bec4, 0x8075ac18 }, 0x2378|2, 0x2378|2 }, // REL1 {{ 0x8076ebd0, 0x8077b0a8, 0x8076e23c, 0x8075cf90 }, 0x708|0, 0x708|0 }, // REL1 {{ 0x8076f2d8, 0x8075c4f0, 0x8076e944, 0x8075d698 }, 0x3374|2, 0x3374|2 }, // REL1 {{ 0x8077264c, 0x80760058, 0x80771cb8, 0x80760a0c }, 0x6c|2, 0x6c|2 }, // REL1 {{ 0x80772700, 0x8077b7b4, 0x80771d6c, 0x80760ac0 }, 0x1510|2, 0x1510|2 }, // REL1 {{ 0x80773c10, 0x8075f8d0, 0x8077327c, 0x80761fd0 }, 0x764|2, 0x764|2 }, // REL1 - {{ 0x8077437c, 0x80850320, 0x807739e8, 0x8076273c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x80774388, 0x80764540, 0x807739f4, 0x80762748 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x80774390, 0x80849284, 0x807739fc, 0x80762750 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x80774398, 0x80764550, 0x80773a04, 0x80762758 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x8077439c, 0x80760108, 0x80773a08, 0x8076275c }, 0x1b34|0, 0x1b34|0 }, // REL1 - {{ 0x80775ed0, 0x8083c2a0, 0x8077553c, 0x80764290 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80775ed4, 0x80761c40, 0x80775540, 0x80764294 }, 0x119c|2, 0x119c|2 }, // REL1 - {{ 0x80777070, 0x8068b160, 0x8068ec54, 0x8067d990 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80777074, 0x80762de0, 0x807766e0, 0x80765434 }, 0xbbc|2, 0xbbc|2 }, // REL1 - {{ 0x80777c30, 0x8073ad90, 0x8074a2c8, 0x8073901c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80777c34, 0x807639a0, 0x807772a0, 0x80765ff4 }, 0x14|2, 0x14|2 }, // REL1 - {{ 0x80777c48, 0x8073ad90, 0x8074a2c8, 0x8073901c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80777c4c, 0x807639b8, 0x807772b8, 0x8076600c }, 0x18|2, 0x18|2 }, // REL1 - {{ 0x80777c64, 0x8073ad90, 0x8074a2c8, 0x8073901c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80777c68, 0x807639d4, 0x807772d4, 0x80766028 }, 0x1e8|2, 0x1e8|2 }, // REL1 - {{ 0x80777e50, 0x8073ad90, 0x8074a2c8, 0x8073901c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80777e54, 0x80763bc0, 0x807774c0, 0x80766214 }, 0x40c|2, 0x40c|2 }, // REL1 - {{ 0x80778260, 0x8073ad90, 0x8074a2c8, 0x8073901c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80778264, 0x80763fd0, 0x807778d0, 0x80766624 }, 0x14|2, 0x14|2 }, // REL1 - {{ 0x80778278, 0x8073ad90, 0x8074a2c8, 0x8073901c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x8077827c, 0x80763fe8, 0x807778e8, 0x8076663c }, 0x18|2, 0x18|2 }, // REL1 - {{ 0x80778294, 0x8073ad90, 0x8074a2c8, 0x8073901c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80778298, 0x80764004, 0x80777904, 0x80766658 }, 0x54c|2, 0x54c|2 }, // REL1 + {{ 0x8077439c, 0x80760108, 0x80773a08, 0x8076275c }, 0x4448|0, 0x4448|0 }, // REL1 {{ 0x807787e4, 0x8076e214, 0x80777e50, 0x80766ba4 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x807787ec, 0x8077cd0c, 0x80777e58, 0x80766bac }, 0x7f4|2, 0x7f4|2 }, // REL1 {{ 0x80779018, 0x80776838, 0x80778684, 0x807673d8 }, 0x10|2, 0x10|2 }, // REL1 {{ 0x80779028, 0x80764558, 0x80778694, 0x807673e8 }, 0x3df4|2, 0x3df4|2 }, // REL1 - {{ 0x8077ce1c, 0x8070f9d0, 0x8077c488, 0x8076b1dc }, 0x28|2, 0x28|2 }, // REL1 {{ 0x8077ce84, 0x8077d508, 0x8077c4f0, 0x8076b244 }, 0xfe0|2, 0xfe0|2 }, // REL1 {{ 0x8077de64, 0x8076e160, 0x8077d4d0, 0x8076c224 }, 0xa0|2, 0xa0|2 }, // REL1 {{ 0x8077df18, 0x8075a168, 0x8077d584, 0x8076c2d8 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x8077df20, 0x807683f4, 0x8077d58c, 0x8076c2e0 }, 0x4a84|0, 0x4a84|0 }, // REL1 {{ 0x807829d8, 0x8077e5a8, 0x80782044, 0x80770d98 }, 0x27b8|0, 0x27b8|0 }, // REL1 {{ 0x80785190, 0x80780df8, 0x80784894, 0x807735e8 }, 0x140|0, 0x140|0 }, // REL1 - {{ 0x807852d0, 0x80780ea0, 0x8078493c, 0x80773690 }, 0x2aac|2, 0x2aac|2 }, // REL1 {{ 0x80787d7c, 0x806f93a0, 0x807873e8, 0x8077613c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x80787d80, 0x807d0318, 0x807873ec, 0x80776140 }, 0x4bc4|2, 0x4bc4|2 }, // REL1 {{ 0x8078c95c, 0x80783950, 0x8078bfc8, 0x8077ad1c }, 0x19150|0, 0x19150|0 }, // REL1 @@ -982,43 +679,32 @@ static const addr_port_t addr_port_0[2050] = {{ 0x807a5be0, 0x8079cbd4, 0x807a524c, 0x80793fa0 }, 0x2558|0, 0x2558|0 }, // REL1 {{ 0x807a8138, 0x807d4ef8, 0x807a77a4, 0x807964f8 }, 0x1b88|0, 0x1b88|0 }, // REL1 {{ 0x807a9cc0, 0x8079f12c, 0x807a932c, 0x80798080 }, 0xe4|2, 0xe4|2 }, // REL1 - {{ 0x807a9dac, 0x807d6a58, 0x807a9418, 0x8079816c }, 0x10c|2, 0x10c|2 }, // REL1 {{ 0x807a9eb8, 0x8079f210, 0x807a9524, 0x80798278 }, 0x5178|0, 0x5178|0 }, // REL1 - {{ 0x807af0ec, 0x8079c9c0, 0x807ae758, 0x8079d4ac }, 0x28|2, 0x28|2 }, // REL1 - {{ 0x807af114, 0x807a4184, 0x807ae780, 0x8079d4d4 }, 0x14|2, 0x14|2 }, // REL1 {{ 0x807af12c, 0x807d4ee4, 0x807ae798, 0x8079d4ec }, 0xc|2, 0xc|2 }, // REL1 - {{ 0x807af138, 0x807a9098, 0x807ae7a4, 0x8079d4f8 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x807af13c, 0x807d6b90, 0x807ae7a8, 0x8079d4fc }, 0x3d90|0, 0x3d90|0 }, // REL1 - {{ 0x807b2ee8, 0x8077f8d4, 0x807b2554, 0x807a12a8 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x807b2ef4, 0x807a4494, 0x807b2560, 0x807a12b4 }, 0x26854|0, 0x26854|0 }, // REL1 {{ 0x807d976c, 0x807da94c, 0x807d8dd8, 0x807c7b2c }, 0x404|2, 0x404|2 }, // REL1 {{ 0x807d9b80, 0x807cacf4, 0x807d91ec, 0x807c7f40 }, 0xa28|2, 0xa28|2 }, // REL1 {{ 0x807da5ac, 0x8084b558, 0x807d9c18, 0x807c896c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x807da5c0, 0x807dad78, 0x807d9c2c, 0x807c8980 }, 0x16ac|2, 0x16ac|2 }, // REL1 - {{ 0x807dbc6c, 0x8079a9b8, 0x807db2d8, 0x807ca02c }, 0x4c|2, 0x4c|2 }, // REL1 {{ 0x807dbcc8, 0x807cba20, 0x807db334, 0x807ca088 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x807dbccc, 0x807cb734, 0x807db338, 0x807ca08c }, 0xbf0|2, 0xbf0|2 }, // REL1 {{ 0x807dc8c8, 0x807dc484, 0x807dbf34, 0x807cac88 }, 0x68|2, 0x68|2 }, // REL1 {{ 0x807dc94c, 0x807cc32c, 0x807dbfb8, 0x807cad0c }, 0x3fe8|2, 0x3fe8|2 }, // REL1 {{ 0x807e0938, 0x8083c6ec, 0x807dffa4, 0x807cecf8 }, 0x1bc4|2, 0x1bc4|2 }, // REL1 {{ 0x807e24fc, 0x807df55c, 0x807e1b68, 0x807d08bc }, 0x70|2, 0x70|2 }, // REL1 - {{ 0x807e2594, 0x807ebee0, 0x807e1c00, 0x807d0954 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x807e259c, 0x807dc50c, 0x807e1c08, 0x807d095c }, 0x3028|0, 0x3028|0 }, // REL1 - {{ 0x807e55c4, 0x8083f8ac, 0x807e4c30, 0x807d3984 }, 0x30|2, 0x30|2 }, // REL1 {{ 0x807e55f4, 0x8083e2b8, 0x807e4c60, 0x807d39b4 }, 0x60|2, 0x60|2 }, // REL1 {{ 0x807e5654, 0x807df5e4, 0x807e4cc0, 0x807d3a14 }, 0xd5c|0, 0xd5c|0 }, // REL1 {{ 0x807e63b0, 0x8083cfd8, 0x807e5a1c, 0x807d4770 }, 0x20|2, 0x20|2 }, // REL1 - {{ 0x807e63fc, 0x807de374, 0x807e5a68, 0x807d47bc }, 0x8|3, 0x8|3 }, // REL1 {{ 0x807e6404, 0x8083c6ec, 0x807e5a70, 0x807d47c4 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x807e6408, 0x8083e330, 0x807e5a74, 0x807d47c8 }, 0x3838|0, 0x3838|0 }, // REL1 {{ 0x807e9c40, 0x807e0394, 0x807e92ac, 0x807d8000 }, 0x4154|0, 0x4154|0 }, // REL1 {{ 0x807edd94, 0x80841b68, 0x807ed400, 0x807dc154 }, 0x468|2, 0x468|2 }, // REL1 - {{ 0x807ee248, 0x80841b64, 0x807ed8b4, 0x807dc608 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x807ee24c, 0x807e44e8, 0x807ed8b8, 0x807dc60c }, 0x1b4|2, 0x1b4|2 }, // REL1 {{ 0x807ee430, 0x80841fcc, 0x807eda9c, 0x807dc7f0 }, 0x5b0|2, 0x5b0|2 }, // REL1 {{ 0x807ee9e0, 0x807e46d0, 0x807ee04c, 0x807dcda0 }, 0x1004|0, 0x1004|0 }, // REL1 {{ 0x807ef9e4, 0x808425c0, 0x807ef050, 0x807ddda4 }, 0x2fc|2, 0x2fc|2 }, // REL1 - {{ 0x807efd00, 0x807e09b8, 0x807ef36c, 0x807de0c0 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x807efd04, 0x807e56dc, 0x807ef370, 0x807de0c4 }, 0x79d4|0, 0x79d4|0 }, // REL1 {{ 0x807f76e0, 0x808428dc, 0x807f6d4c, 0x807e5aa0 }, 0x464|2, 0x464|2 }, // REL1 {{ 0x807f7bbc, 0x807ed0bc, 0x807f7228, 0x807e5f7c }, 0xd4c|2, 0xd4c|2 }, // REL1 @@ -1026,7 +712,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x807f9274, 0x807ede84, 0x807f88e0, 0x807e7634 }, 0xc0|0, 0xc0|0 }, // REL1 {{ 0x807f9334, 0x80747b60, 0x807f89a0, 0x807e76f4 }, 0xc|2, 0xc|2 }, // REL1 {{ 0x807f9384, 0x808436ac, 0x807f89f0, 0x807e7744 }, 0x1d4|2, 0x1d4|2 }, // REL1 - {{ 0x807f9568, 0x80734848, 0x807f8bd4, 0x807e7928 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x807f9580, 0x808438a0, 0x807f8bec, 0x807e7940 }, 0x15ac|2, 0x15ac|2 }, // REL1 {{ 0x807fab3c, 0x80800e0c, 0x807fa1a8, 0x807e8efc }, 0xc|2, 0xc|2 }, // REL1 {{ 0x807fab48, 0x807edf88, 0x807fa1b4, 0x807e8f08 }, 0x3fd0|2, 0x3fd0|2 }, // REL1 @@ -1042,64 +727,47 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80813b88, 0x807f873c, 0x808131f4, 0x80801f48 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x80813b8c, 0x807edf50, 0x808131f8, 0x80801f4c }, 0x38|2, 0x38|2 }, // REL1 {{ 0x80813bc4, 0x80800e18, 0x80813230, 0x80801f84 }, 0xa6a8|0, 0xa6a8|0 }, // REL1 - {{ 0x8081e270, 0x8072fc98, 0x8081d8dc, 0x8080c630 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8081e278, 0x8072c704, 0x8081d8e4, 0x8080c638 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x8081e280, 0x8084b060, 0x8081d8ec, 0x8080c640 }, 0xd68|2, 0xd68|2 }, // REL1 {{ 0x8081efec, 0x8080b4d8, 0x8081e658, 0x8080d3ac }, 0xf4fc|0, 0xf4fc|0 }, // REL1 - {{ 0x8082e4e8, 0x80814a44, 0x8082db54, 0x8081c8a8 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x8082e4f0, 0x80750e38, 0x8082db5c, 0x8081c8b0 }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x8082e4f4, 0x80814a50, 0x8082db60, 0x8081c8b4 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8082e52c, 0x80762de4, 0x8082db98, 0x8081c8ec }, 0x14|2, 0x14|2 }, // REL1 {{ 0x8082e540, 0x8084bdcc, 0x8082dbac, 0x8081c900 }, 0x2ec|2, 0x2ec|2 }, // REL1 - {{ 0x8082e834, 0x8077b798, 0x8082dea0, 0x8081cbf4 }, 0x14|2, 0x14|2 }, // REL1 {{ 0x8082e850, 0x8081aa28, 0x8082debc, 0x8081cc10 }, 0xb6c|2, 0xb6c|2 }, // REL1 - {{ 0x8082f3bc, 0x80878070, 0x8082ea28, 0x8081d77c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8082f404, 0x8084c0dc, 0x8082ea70, 0x8081d7c4 }, 0x4090|2, 0x4090|2 }, // REL1 {{ 0x80833494, 0x8081b594, 0x80832b00, 0x80821854 }, 0x63c|0, 0x63c|0 }, // REL1 {{ 0x80833af0, 0x8076e4c8, 0x8083315c, 0x80821eb0 }, 0xc|2, 0xc|2 }, // REL1 {{ 0x80833afc, 0x8081bc04, 0x80833168, 0x80821ebc }, 0x430c|2, 0x430c|2 }, // REL1 {{ 0x80837e08, 0x8081ff0c, 0x80837470, 0x808261c8 }, 0x4|0, 0x4|0 }, // REL1 {{ 0x80837e0c, 0x8081ff14, 0x80837478, 0x808261cc }, 0xfb4|2, 0xfb4|2 }, // REL1 - {{ 0x80838e5c, 0x808501b4, 0x808384c8, 0x8082721c }, 0x21f8|2, 0x21f8|2 }, // REL1 + {{ 0x80838e5c, 0x808501b4, 0x808384c8, 0x8082721c }, 0x21f8|0, 0x21f8|0 }, // REL1 {{ 0x8083b054, 0x808540f4, 0x8083a6c0, 0x80829414 }, 0xc|2, 0xc|2 }, // REL1 {{ 0x8083b060, 0x80857c34, 0x8083a6cc, 0x80829420 }, 0xc|2, 0xc|2 }, // REL1 {{ 0x8083b06c, 0x80820ef4, 0x8083a6d8, 0x8082942c }, 0x19ac|2, 0x19ac|2 }, // REL1 {{ 0x8083ca18, 0x80833630, 0x8083c084, 0x8082add8 }, 0x94|2, 0x94|2 }, // REL1 - {{ 0x8083caac, 0x8082da30, 0x8083c118, 0x8082ae6c }, 0x94|2, 0x94|2 }, // REL1 {{ 0x8083cb40, 0x80852420, 0x8083c1ac, 0x8082af00 }, 0x86c|0, 0x86c|0 }, // REL1 - {{ 0x8083d408, 0x807e46ec, 0x8083ca74, 0x8082b7c8 }, 0x1c|2, 0x1c|2 }, // REL1 {{ 0x8083d424, 0x808229c4, 0x8083ca90, 0x8082b7e4 }, 0x4e60|0, 0x4e60|0 }, // REL1 - {{ 0x808422a0, 0x80851378, 0x8084190c, 0x80830660 }, 0x10|2, 0x10|2 }, // REL1 - {{ 0x808422b0, 0x80852c7c, 0x8084191c, 0x80830670 }, 0x2474|2, 0x2474|2 }, // REL1 {{ 0x80844728, 0x80827850, 0x80843d94, 0x80832ae8 }, 0x6274|0, 0x6274|0 }, // REL1 {{ 0x8084a99c, 0x80855180, 0x8084a008, 0x80838d5c }, 0x26b0|2, 0x26b0|2 }, // REL1 - {{ 0x8084d04c, 0x8082f754, 0x8084c6b8, 0x8083b40c }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8084d050, 0x80820ec8, 0x8084c6bc, 0x8083b410 }, 0x28|2, 0x28|2 }, // REL1 {{ 0x8084d0d4, 0x8082dac0, 0x8084c740, 0x8083b494 }, 0x4bf4|0, 0x4bf4|0 }, // REL1 {{ 0x80851cc8, 0x80854c00, 0x80851334, 0x80840088 }, 0x8|3, 0x8|3 }, // REL1 {{ 0x80851cd0, 0x80857858, 0x8085133c, 0x80840090 }, 0xe00|2, 0xe00|2 }, // REL1 {{ 0x80852ad0, 0x80821824, 0x8085213c, 0x80840e90 }, 0x138|2, 0x138|2 }, // REL1 {{ 0x80852c08, 0x808326c0, 0x80852274, 0x80840fc8 }, 0x1004|2, 0x1004|2 }, // REL1 - {{ 0x80853c0c, 0x8082da30, 0x80853278, 0x80841fcc }, 0x94|2, 0x94|2 }, // REL1 {{ 0x80853ca0, 0x808587f0, 0x8085330c, 0x80842060 }, 0x14c8|2, 0x14c8|2 }, // REL1 {{ 0x808551e4, 0x80833754, 0x80854850, 0x808435a4 }, 0x71a8|0, 0x71a8|0 }, // REL1 {{ 0x8085c3c4, 0x80859d34, 0x8085ba30, 0x8084a784 }, 0x22a0|2, 0x22a0|2 }, // REL1 {{ 0x8085e664, 0x808436a0, 0x8085dcd0, 0x8084ca24 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x8085e66c, 0x8083a948, 0x8085dcd8, 0x8084ca2c }, 0xa30|2, 0xa30|2 }, // REL1 {{ 0x8085f09c, 0x8085bfd4, 0x8085e708, 0x8084d45c }, 0xe24|2, 0xe24|2 }, // REL1 - {{ 0x8085fec0, 0x8082e5c4, 0x8085f52c, 0x8084e280 }, 0x68|2, 0x68|2 }, // REL1 {{ 0x8085ffcc, 0x8083b380, 0x8085f638, 0x8084e38c }, 0xf54|0, 0xf54|0 }, // REL1 {{ 0x80860f28, 0x8085cf08, 0x80860594, 0x8084f2e8 }, 0x1ee8|2, 0x1ee8|2 }, // REL1 - {{ 0x80862e14, 0x8083c2d0, 0x80862480, 0x808511d4 }, 0x40c|2, 0x40c|2 }, // REL1 - {{ 0x8086322c, 0x8085edfc, 0x80862898, 0x808515ec }, 0x1c64|2, 0x1c64|2 }, // REL1 - {{ 0x80864e90, 0x80860a60, 0x808644fc, 0x80794d0c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x80864e94, 0x80860a64, 0x80864500, 0x80853254 }, 0x25c|2, 0x25c|2 }, // REL1 + {{ 0x8086322c, 0x8085edfc, 0x80862898, 0x808515ec }, 0x1ec4|2, 0x1ec4|2 }, // REL1 {{ 0x808650f0, 0x8077cc20, 0x8086475c, 0x808534b0 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x808650f4, 0x80860cc4, 0x80864760, 0x808534b4 }, 0xdd4|2, 0xdd4|2 }, // REL1 {{ 0x80865ec8, 0x80853420, 0x80865534, 0x80854288 }, 0x8|3, 0x8|3 }, // REL1 - {{ 0x80865ed0, 0x80861aa0, 0x8086553c, 0x80854290 }, 0x6fc|2, 0x6fc|2 }, // REL1 - {{ 0x808665cc, 0x8086219c, 0x80865c38, 0x80794d0c }, 0x4|3, 0x4|3 }, // REL1 - {{ 0x808665d0, 0x808621a0, 0x80865c3c, 0x80854990 }, 0xaa8|2, 0xaa8|2 }, // REL1 + {{ 0x80865ed0, 0x80861aa0, 0x8086553c, 0x80854290 }, 0x11a8|2, 0x11a8|2 }, // REL1 {{ 0x80867084, 0x80864d30, 0x808666f0, 0x80855444 }, 0x650|2, 0x650|2 }, // REL1 {{ 0x808676e0, 0x80862c5c, 0x80866d4c, 0x80855aa0 }, 0x20d0|2, 0x20d0|2 }, // REL1 {{ 0x808697b8, 0x8086e680, 0x80868e24, 0x80857b78 }, 0x4|3, 0x4|3 }, // REL1 @@ -1110,7 +778,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x8086c958, 0x80866b00, 0x8086bfc4, 0x8085ad18 }, 0xb0|2, 0xb0|2 }, // REL1 {{ 0x8086ca30, 0x80878da8, 0x8086c09c, 0x8085adf0 }, 0x624c|2, 0x624c|2 }, // REL1 {{ 0x80872c94, 0x80865e14, 0x80872300, 0x80861054 }, 0xcec|2, 0xcec|2 }, // REL1 - {{ 0x80873990, 0x8082d8c0, 0x80872ffc, 0x80861d50 }, 0x4|3, 0x4|3 }, // REL1 {{ 0x80873998, 0x80866bd0, 0x80873004, 0x80861d58 }, 0x1aac|2, 0x1aac|2 }, // REL1 {{ 0x80875450, 0x808686f8, 0x80874abc, 0x80863810 }, 0x804|2, 0x804|2 }, // REL1 {{ 0x80875c54, 0x80877578, 0x8086a744, 0x80859498 }, 0x108|0, 0x108|0 }, // REL1 @@ -1122,9 +789,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x8088f8d0, 0x8088b478, 0x8088ef30, 0x8087dc90 }, 0x32c|0, 0x32c|0 }, // REL4 {{ 0x8088fbfc, 0x8088b7a4, 0x8088f25c, 0x8087e004 }, 0x1c4|0, 0x1c4|0 }, // REL4 {{ 0x8088fdf4, 0x8088b990, 0x8088f440, 0x8087e1f0 }, 0x4|3, 0x4|3 }, // REL4 - {{ 0x8088fe00, 0x8088b9a0, 0x8088f450, 0x8087e200 }, 0x160|2, 0x160|2 }, // REL4 - {{ 0x8088ff60, 0x8088bb00, 0x8088f5b0, 0x8087ff60 }, 0x4|3, 0x4|3 }, // REL4 - {{ 0x8088ff64, 0x8088bb04, 0x8088f5b4, 0x8087e364 }, 0x2c|2, 0x2c|2 }, // REL4 + {{ 0x8088fe00, 0x8088b9a0, 0x8088f450, 0x8087e200 }, 0x190|2, 0x190|2 }, // REL4 {{ 0x8088ff98, 0x8088cc90, 0x8088f5e8, 0x8087e398 }, 0x8|3, 0x8|3 }, // REL4 {{ 0x8088ffa8, 0x8088bb38, 0x8088f5f8, 0x8087e3a8 }, 0x88|0, 0x88|0 }, // REL4 {{ 0x80890030, 0x8088f9c0, 0x80894908, 0x808836c8 }, 0x310|0, 0x310|0 }, // REL4 @@ -1138,7 +803,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80891634, 0x8088e07c, 0x80890c84, 0x8087fa3c }, 0x84|2, 0x84|2 }, // REL4 {{ 0x808916bc, 0x8088d1ec, 0x80890d0c, 0x8087fac4 }, 0xec|2, 0xec|2 }, // REL4 {{ 0x808917ac, 0x8088e104, 0x80890dfc, 0x8087fbb4 }, 0x44|2, 0x44|2 }, // REL4 - {{ 0x808917f4, 0x8088d2dc, 0x80890e44, 0x8087fbfc }, 0x7ac|2, 0x7ac|2 }, // REL4 + {{ 0x808917f4, 0x8088d2dc, 0x80890e44, 0x8087fbfc }, 0x7ac|0, 0x7ac|0 }, // REL4 {{ 0x80891fa8, 0x8088e150, 0x808915f8, 0x808803b0 }, 0x44|2, 0x44|2 }, // REL4 {{ 0x80891ff8, 0x8088da90, 0x80891648, 0x80880400 }, 0x28|2, 0x28|2 }, // REL4 {{ 0x80892024, 0x8088e19c, 0x80891674, 0x8088042c }, 0x1d8|2, 0x1d8|2 }, // REL4 @@ -1163,8 +828,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80894240, 0x8088f158, 0x80893890, 0x80882650 }, 0x59c|2, 0x59c|2 }, // REL4 {{ 0x808947e0, 0x808934b0, 0x80893e30, 0x80882bf0 }, 0x7f8|2, 0x7f8|2 }, // REL4 {{ 0x80894ff0, 0x8088f6f8, 0x80894640, 0x80883400 }, 0x5c8|0, 0x5c8|0 }, // REL4 - {{ 0x808955b8, 0x80894c14, 0x80894c08, 0x808839c8 }, 0xc|2, 0xc|2 }, // REL4 - {{ 0x808955cc, 0x8088fccc, 0x80894c1c, 0x808839dc }, 0x28|2, 0x28|2 }, // REL4 {{ 0x808955f4, 0x80893cc4, 0x80894c44, 0x80883a04 }, 0x68c|2, 0x68c|2 }, // REL4 {{ 0x80895c9c, 0x8088fcf4, 0x808952ec, 0x808845c4 }, 0xe0|2, 0xe0|2 }, // REL4 {{ 0x80895d84, 0x8089436c, 0x808953d4, 0x808846ac }, 0x3bc|2, 0x3bc|2 }, // REL4 @@ -1181,21 +844,16 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80897cbc, 0x80890f14, 0x8089730c, 0x808865e4 }, 0x468|2, 0x468|2 }, // REL4 {{ 0x80898124, 0x8089516c, 0x80897774, 0x80886a4c }, 0x28|2, 0x7c|3 }, // REL4 {{ 0x808981a0, 0x808951e8, 0x808977f0, 0x80886ac8 }, 0x14|2, 0x14|2 }, // REL4 - {{ 0x808981c8, 0x80895210, 0x8088edcc, 0x8088410c }, 0x8|3, 0x8|3 }, // REL4 - {{ 0x8089822c, 0x8089526c, 0x8088edcc, 0x8087db2c }, 0x14|2, 0x14|2 }, // REL4 {{ 0x80898244, 0x8089528c, 0x80897874, 0x80886b4c }, 0x2c|2, 0x2c|2 }, // REL4 {{ 0x80898270, 0x808952b8, 0x8089779c, 0x80886a74 }, 0x30|2, 0x30|2 }, // REL4 - {{ 0x80898344, 0x8089538c, 0x8088edd4, 0x8087db34 }, 0x4|3, 0x4|3 }, // REL4 {{ 0x80898368, 0x808953b0, 0x80897874, 0x80886b4c }, 0x2c|2, 0x2c|2 }, // REL4 {{ 0x80898394, 0x808953dc, 0x8089779c, 0x80886a74 }, 0x30|2, 0x30|2 }, // REL4 {{ 0x808983e8, 0x808951e8, 0x808977f0, 0x80886ac8 }, 0x14|2, 0x14|2 }, // REL4 - {{ 0x80898410, 0x80895210, 0x8088edcc, 0x8088410c }, 0x8|3, 0x8|3 }, // REL4 {{ 0x80898484, 0x80895284, 0x8089786c, 0x80886b44 }, 0x8|3, 0x8|3 }, // REL4 {{ 0x808985a8, 0x80895284, 0x8089786c, 0x80886b44 }, 0x8|3, 0x8|3 }, // REL4 {{ 0x808985b0, 0x808953b0, 0x80897874, 0x80886b4c }, 0x2c|2, 0x2c|2 }, // REL4 {{ 0x808985dc, 0x808953dc, 0x8089779c, 0x80886a74 }, 0x30|2, 0x54|3 }, // REL4 {{ 0x80898630, 0x80895430, 0x808977f0, 0x80886ac8 }, 0x14|2, 0x14|2 }, // REL4 - {{ 0x80898658, 0x80895458, 0x8088edcc, 0x8088410c }, 0x8|3, 0x8|3 }, // REL4 {{ 0x808986cc, 0x808954cc, 0x8089786c, 0x80886b44 }, 0x34|2, 0x34|2 }, // REL4 {{ 0x80898704, 0x8089137c, 0x808978a4, 0x80886b7c }, 0x314|2, 0x314|2 }, // REL4 {{ 0x80898a20, 0x80893190, 0x808932e8, 0x808820a8 }, 0x4|3, 0x4|3 }, // REL4 @@ -1207,7 +865,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x80899638, 0x80891f08, 0x80898798, 0x80887a70 }, 0x1e0|2, 0x1e0|2 }, // REL4 {{ 0x80899820, 0x80895870, 0x80898980, 0x80887c58 }, 0x154|2, 0x154|2 }, // REL4 {{ 0x80899978, 0x8088f1a4, 0x80898ad8, 0x80887db0 }, 0x4|3, 0x4|3 }, // REL4 - {{ 0x8089997c, 0x808920ec, 0x80898adc, 0x80887db4 }, 0x574|2, 0x574|2 }, // REL4 + {{ 0x8089997c, 0x808920ec, 0x80898adc, 0x80887db4 }, 0x574|0, 0x574|0 }, // REL4 {{ 0x80899ef8, 0x808959d0, 0x80899058, 0x80888330 }, 0xdc|2, 0xdc|2 }, // REL4 {{ 0x80899fd8, 0x80892668, 0x80899138, 0x80888410 }, 0x1a0|2, 0x1a0|2 }, // REL4 {{ 0x8089a180, 0x80895ab0, 0x808992e0, 0x808885b8 }, 0x124|2, 0x124|2 }, // REL4 @@ -1220,8 +878,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x8089ab5c, 0x80896164, 0x80899cbc, 0x80888f4c }, 0x10|2, 0x10|2 }, // REL4 {{ 0x8089ab74, 0x8089617c, 0x80899cd4, 0x80888fb4 }, 0xb0|0, 0xb0|0 }, // REL4 {{ 0x8089ac24, 0x8089622c, 0x80899d84, 0x8088965c }, 0x4|3, 0x4|3 }, // REL4 - {{ 0x8089ac2c, 0x80896234, 0x80899d8c, 0x80889018 }, 0x14|2, 0x14|2 }, // REL4 - {{ 0x8089acc8, 0x808962d0, 0x80899e28, 0x80888b38 }, 0x8|3, 0x8|3 }, // REL4 {{ 0x8089ad30, 0x80896338, 0x80899e90, 0x808891d4 }, 0x18|2, 0x18|2 }, // REL4 {{ 0x8089ad78, 0x80896380, 0x80899ed8, 0x808891fc }, 0x4|3, 0x4|3 }, // REL4 {{ 0x8089ad84, 0x8089638c, 0x80899ee4, 0x808891a4 }, 0x1c|2, 0x1c|2 }, // REL4 @@ -1231,11 +887,9 @@ static const addr_port_t addr_port_0[2050] = {{ 0x8089aec0, 0x80897070, 0x8089a020, 0x80889320 }, 0x1c|2, 0x1c|2 }, // REL4 {{ 0x8089aee0, 0x808964c8, 0x8089a040, 0x80889340 }, 0x878|2, 0x878|2 }, // REL4 {{ 0x8089b760, 0x80897090, 0x8089a8c0, 0x80889bc0 }, 0x3ca4|2, 0x3ca4|2 }, // REL4 - {{ 0x8089f404, 0x808adf7c, 0x8089e564, 0x8088d864 }, 0x4|3, 0x4|3 }, // REL4 {{ 0x8089f408, 0x8089bb68, 0x8089e568, 0x8088d868 }, 0x98|2, 0x98|2 }, // REL4 {{ 0x8089f4a4, 0x8089ad34, 0x8089e604, 0x8088d904 }, 0xfc|2, 0xfc|2 }, // REL4 {{ 0x8089f5a0, 0x8089bc08, 0x8089e700, 0x8088da00 }, 0x1a0|2, 0x1a0|2 }, // REL4 - {{ 0x8089f740, 0x808a49a0, 0x8089e8a0, 0x8088dba0 }, 0x10|2, 0x10|2 }, // REL4 {{ 0x8089f758, 0x8089ae30, 0x8089e8b8, 0x8088dbb8 }, 0x5c|2, 0x5c|2 }, // REL4 {{ 0x8089f7b4, 0x8089bdbc, 0x8089e914, 0x8088dc14 }, 0x1c4|2, 0x1c4|2 }, // REL4 {{ 0x8089f984, 0x8089bf84, 0x8089eae4, 0x8088dde4 }, 0x5c|2, 0x5c|2 }, // REL4 @@ -1256,9 +910,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808a0070, 0x8089c210, 0x8089f1d0, 0x8088e4d0 }, 0x1c|2, 0x1c|2 }, // REL4 {{ 0x808a0098, 0x8089b2f8, 0x8089f1f8, 0x8088e4f8 }, 0x38|2, 0x38|2 }, // REL4 {{ 0x808a00d0, 0x8089b330, 0x8089f230, 0x808900d0 }, 0x4|3, 0x4|3 }, // REL4 - {{ 0x808a00d4, 0x8089b334, 0x8089f234, 0x8088e534 }, 0x4|3, 0x4|3 }, // REL4 - {{ 0x808a00d8, 0x808a00d8, 0x808a00d8, 0x808900d8 }, 0x4|3, 0x4|3 }, // REL4 - {{ 0x808a00dc, 0x8089b33c, 0x8089f23c, 0x8088e53c }, 0x220|2, 0x220|2 }, // REL4 + {{ 0x808a00d4, 0x8089b334, 0x8089f234, 0x8088e534 }, 0x228|2, 0x228|2 }, // REL4 {{ 0x808a02fc, 0x8089f078, 0x8089f45c, 0x8088e75c }, 0x40|2, 0x40|2 }, // REL4 {{ 0x808a0340, 0x8089c238, 0x8089f4a0, 0x8088e7a0 }, 0x34|2, 0x34|2 }, // REL4 {{ 0x808a0378, 0x8089b5a0, 0x8089f4d8, 0x8088e7d8 }, 0xe4|2, 0xe4|2 }, // REL4 @@ -1279,7 +931,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808a1d38, 0x8089d930, 0x808a0e98, 0x80890198 }, 0x14|2, 0x3c|3 }, // REL4 {{ 0x808a1d74, 0x8089d96c, 0x808a0ed4, 0x808901d4 }, 0xc|2, 0xc|2 }, // REL4 {{ 0x808a1d80, 0x8089d378, 0x808a0ee0, 0x808901e0 }, 0x274|2, 0x274|2 }, // REL4 - {{ 0x808a1ff4, 0x8089c8ac, 0x808a1154, 0x80890454 }, 0x8|3, 0x8|3 }, // REL4 {{ 0x808a1ffc, 0x8089d5ec, 0x808a115c, 0x8089045c }, 0x8|3, 0x8|3 }, // REL4 {{ 0x808a2050, 0x8089d980, 0x808a11b0, 0x808904b0 }, 0x368|2, 0x368|2 }, // REL4 {{ 0x808a23c0, 0x8089e3f8, 0x808a1520, 0x80890820 }, 0x17c|2, 0x17c|2 }, // REL4 @@ -1296,9 +947,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808a2ce8, 0x8089e2a0, 0x808a1e48, 0x80891148 }, 0x8|3, 0x8|3 }, // REL4 {{ 0x808a2cf8, 0x8089f6c0, 0x808a1e58, 0x80891158 }, 0x1e0|2, 0x1e0|2 }, // REL4 {{ 0x808a2edc, 0x8089e624, 0x808a203c, 0x8089133c }, 0x3f8|2, 0x3f8|2 }, // REL4 - {{ 0x808a32d4, 0x808a2d34, 0x808a2434, 0x80891734 }, 0x4|3, 0x4|3 }, // REL4 - {{ 0x808a32d8, 0x8089f8a8, 0x808a2438, 0x80891738 }, 0xfc|2, 0xfc|2 }, // REL4 - {{ 0x808a33e0, 0x8089ea20, 0x808a2540, 0x80891840 }, 0x1d4|2, 0x1d4|2 }, // REL4 {{ 0x808a35b4, 0x8089f9ac, 0x808a2714, 0x80891a14 }, 0x248|2, 0x248|2 }, // REL4 {{ 0x808a37fc, 0x8089ebf4, 0x808a295c, 0x80891c5c }, 0x64|2, 0x64|2 }, // REL4 {{ 0x808a3860, 0x808a0020, 0x808a29c0, 0x80891cc0 }, 0x4|3, 0x4|3 }, // REL4 @@ -1427,9 +1075,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808b5104, 0x808b0114, 0x808b4264, 0x808a357c }, 0x10|2, 0x10|2 }, // REL5 {{ 0x808b5118, 0x808b09e0, 0x808b4278, 0x808a3590 }, 0x5ac|2, 0x5ac|2 }, // REL5 {{ 0x808b5704, 0x808b292c, 0x808b4864, 0x808a3b7c }, 0x94|2, 0x94|2 }, // REL5 - {{ 0x808b5798, 0x808b1770, 0x808b48f8, 0x808a3c10 }, 0x8|3, 0x8|3 }, // REL5 {{ 0x808b57a0, 0x808b215c, 0x808b4900, 0x808a3c18 }, 0x48|2, 0x48|2 }, // REL5 - {{ 0x808b5818, 0x808b177c, 0x808b4978, 0x808a3c90 }, 0x70|2, 0x70|2 }, // REL5 {{ 0x808b5888, 0x808b0fc8, 0x808b49e8, 0x808a3d00 }, 0xe80|0, 0xf10|1 }, // REL5 {{ 0x808b6798, 0x808b1ed8, 0x808b58f8, 0x808a4c10 }, 0x4|2, 0x48|3 }, // REL5 {{ 0x808b67e0, 0x808b1f20, 0x808b5940, 0x808a4c58 }, 0x4|3, 0x4|3 }, // REL5 @@ -1472,7 +1118,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808b77c8, 0x808b2e08, 0x808b6928, 0x808a5c40 }, 0x8|3, 0x8|3 }, // REL5 {{ 0x808b77d0, 0x808ba3a8, 0x808b6930, 0x808a5c48 }, 0x4c|2, 0xac|3 }, // REL5 {{ 0x808b787c, 0x808ba454, 0x808b69dc, 0x808a5cf4 }, 0x1c|2, 0x1c|2 }, // REL5 - {{ 0x808b78e8, 0x808b1990, 0x808b6a48, 0x808a5d60 }, 0x18|2, 0x18|2 }, // REL5 {{ 0x808b7904, 0x808b50ac, 0x808b6a64, 0x808a5d7c }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808b7910, 0x808b2ef0, 0x808b6a70, 0x808a5d88 }, 0x78|2, 0x78|2 }, // REL5 {{ 0x808b7988, 0x808b2f68, 0x808b6ae8, 0x808a6cb8 }, 0x4|3, 0x4|3 }, // REL5 @@ -1594,9 +1239,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808bb194, 0x808bb84c, 0x808ba2e4, 0x808a9604 }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808bb198, 0x808bbb58, 0x808ba2e8, 0x808a9608 }, 0x28c|2, 0x28c|2 }, // REL5 {{ 0x808bb428, 0x808c4948, 0x808ba578, 0x808a9898 }, 0x4|3, 0x4|3 }, // REL5 - {{ 0x808bb42c, 0x808ae5c4, 0x808ba57c, 0x808a989c }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808bb430, 0x808bbdf0, 0x808ba580, 0x808a98a0 }, 0x4|3, 0x4|3 }, // REL5 - {{ 0x808bb434, 0x808ae5cc, 0x808ba584, 0x808a98a4 }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808bb43c, 0x808b50b4, 0x808ba58c, 0x808a98ac }, 0x248|2, 0x270|3 }, // REL5 {{ 0x808bb6ac, 0x808b5324, 0x808ba7fc, 0x808a9b1c }, 0x4|2, 0x7c|3 }, // REL5 {{ 0x808bb728, 0x808b53a0, 0x808ba878, 0x808a9b98 }, 0x1c|2, 0x1c|2 }, // REL5 @@ -1646,12 +1289,11 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808bfd0c, 0x808bc0f4, 0x808bee5c, 0x808ae17c }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808bfd10, 0x808b9ff0, 0x808bee60, 0x808ae180 }, 0x60|2, 0x60|2 }, // REL5 {{ 0x808bfd70, 0x808bc158, 0x808beec0, 0x808ae1e0 }, 0x4|3, 0x4|3 }, // REL5 - {{ 0x808bfd74, 0x808b19dc, 0x808beec4, 0x808ae1e4 }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808bfd78, 0x808b96c8, 0x808beec8, 0x808ae1e8 }, 0xd4|2, 0xd4|2 }, // REL5 {{ 0x808bfe4c, 0x808bfe4c, 0x808bef9c, 0x808ae2bc }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808bfe50, 0x808b97a0, 0x808befa0, 0x808ae2c0 }, 0x78|2, 0x78|2 }, // REL5 {{ 0x808bfec8, 0x808bfec8, 0x808bf018, 0x808ae338 }, 0x4|3, 0x4|3 }, // REL5 - {{ 0x808bfecc, 0x808b981c, 0x808bf01c, 0x808ae33c }, 0x250|2, 0x250|2 }, // REL5 + {{ 0x808bfecc, 0x808b981c, 0x808bf01c, 0x808ae33c }, 0x250|0, 0x250|0 }, // REL5 {{ 0x808c011c, 0x808b9a6c, 0x808bf26c, 0x808b011c }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808c0120, 0x808b9a70, 0x808bf270, 0x808ae590 }, 0x7c|2, 0x7c|2 }, // REL5 {{ 0x808c019c, 0x808c019c, 0x808c019c, 0x808b019c }, 0x4|3, 0x4|3 }, // REL5 @@ -1742,7 +1384,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808c5834, 0x808bf424, 0x808c4984, 0x808b3ccc }, 0x408|2, 0x408|2 }, // REL5 {{ 0x808c5c74, 0x808c275c, 0x808c4dc4, 0x808b410c }, 0x14|2, 0x14|2 }, // REL5 {{ 0x808c5c8c, 0x808d870c, 0x808c4ddc, 0x808b4124 }, 0xa4|2, 0xa4|2 }, // REL5 - {{ 0x808c5d30, 0x808b1d88, 0x808c4e80, 0x808b41c8 }, 0x3c|2, 0x3c|2 }, // REL5 {{ 0x808c5d70, 0x808bf868, 0x808c4ec0, 0x808b4208 }, 0x1a4|2, 0x1a4|2 }, // REL5 {{ 0x808c5f14, 0x808c0c84, 0x808c5064, 0x808b43ac }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808c5f18, 0x808bfa10, 0x808c5068, 0x808b43b0 }, 0x4|3, 0x4|3 }, // REL5 @@ -1764,9 +1405,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808c6f6c, 0x808c0f5c, 0x808c60bc, 0x808b5404 }, 0xb0|2, 0xb0|2 }, // REL5 {{ 0x808c7050, 0x808c0460, 0x808c61a0, 0x808b54e8 }, 0x49c|2, 0x49c|2 }, // REL5 {{ 0x808c7524, 0x808c2f3c, 0x808c6674, 0x808b59bc }, 0x140|2, 0x140|2 }, // REL5 - {{ 0x808c7664, 0x808c0934, 0x808c67b4, 0x808b5afc }, 0x168|2, 0x168|2 }, // REL5 - {{ 0x808c77d0, 0x808c6054, 0x808c6920, 0x808b5c68 }, 0x4|3, 0x4|3 }, // REL5 - {{ 0x808c77d4, 0x808c0aa4, 0x808c6924, 0x808b5c6c }, 0x4|3, 0x4|3 }, // REL5 + {{ 0x808c7664, 0x808c0934, 0x808c67b4, 0x808b5afc }, 0x174|2, 0x174|2 }, // REL5 {{ 0x808c77d8, 0x808c3080, 0x808c6928, 0x808b5c70 }, 0x1c|2, 0x1c|2 }, // REL5 {{ 0x808c77f4, 0x808c32c0, 0x808c6944, 0x808b5c8c }, 0x3c|2, 0x3c|2 }, // REL5 {{ 0x808c7830, 0x808c4530, 0x808c6980, 0x808b5cc8 }, 0x30|2, 0x30|2 }, // REL5 @@ -1804,7 +1443,6 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808caf84, 0x808c08fc, 0x808ca0d4, 0x808b941c }, 0x34|2, 0x34|2 }, // REL5 {{ 0x808cafb8, 0x808c5cb0, 0x808ca108, 0x808b9450 }, 0x80|2, 0x80|2 }, // REL5 {{ 0x808cb040, 0x808c7368, 0x808ca190, 0x808b94d8 }, 0x188|2, 0x188|2 }, // REL5 - {{ 0x808cb1c8, 0x808b1778, 0x808ca318, 0x808b9660 }, 0x74|2, 0x74|2 }, // REL5 {{ 0x808cb240, 0x808c5d38, 0x808ca390, 0x808b96d8 }, 0xa44|0, 0xa44|0 }, // REL5 {{ 0x808cbcc0, 0x808cab10, 0x808cae10, 0x808ba158 }, 0x4c|0, 0x4c|0 }, // REL5 {{ 0x808cbd54, 0x808c7564, 0x808caea4, 0x808ba1ec }, 0x154|2, 0x154|2 }, // REL5 @@ -1823,12 +1461,10 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808cdab0, 0x808c85d0, 0x808ccc00, 0x808bbf48 }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808cdab4, 0x808c8d2c, 0x808ccc04, 0x808bbf4c }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808cdab8, 0x808cb880, 0x808ccc08, 0x808bbf50 }, 0x570|2, 0x570|2 }, // REL5 - {{ 0x808ce12c, 0x808c60d4, 0x808cd27c, 0x808bc5c4 }, 0x10|2, 0x10|2 }, // REL5 {{ 0x808ce140, 0x808c85f0, 0x808cd290, 0x808bc5d8 }, 0x33c|2, 0x33c|2 }, // REL5 {{ 0x808ce480, 0x808c9dc0, 0x808cd5d0, 0x808bc918 }, 0xc4|2, 0xc4|2 }, // REL5 {{ 0x808ce568, 0x808cbf08, 0x808cd6b8, 0x808bca00 }, 0x5c0|2, 0x5c0|2 }, // REL5 {{ 0x808ceb28, 0x808af1dc, 0x808cdc78, 0x808bcfc0 }, 0x18|2, 0x18|2 }, // REL5 - {{ 0x808ceb48, 0x808b0fc8, 0x808cdc98, 0x808bcfe0 }, 0x8|3, 0x8|3 }, // REL5 {{ 0x808ceb50, 0x808cc4f0, 0x808cdca0, 0x808bcfe8 }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808ceb54, 0x808c8d2c, 0x808cdca4, 0x808bcfec }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808ceb58, 0x808c8a00, 0x808cdca8, 0x808bcff0 }, 0x648|2, 0x648|2 }, // REL5 @@ -1912,10 +1548,8 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808d3234, 0x808ce92c, 0x808d2384, 0x808c16cc }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808d323c, 0x808d4cec, 0x808d238c, 0x808c16d4 }, 0x518|2, 0x518|2 }, // REL5 {{ 0x808d3764, 0x808ce934, 0x808d28b4, 0x808c1bfc }, 0x33c|2, 0x384|3 }, // REL5 - {{ 0x808d3ae8, 0x808cecb8, 0x808d2c38, 0x808c1f80 }, 0x4|3, 0x4|3 }, // REL5 - {{ 0x808d3b48, 0x808cef88, 0x808d2c98, 0x808c1fe0 }, 0x40|2, 0x40|2 }, // REL5 + {{ 0x808d3ae8, 0x808cecb8, 0x808d2c38, 0x808c1f80 }, 0x4|2, 0xa0|3 }, // REL5 {{ 0x808d3b88, 0x808ced58, 0x808d2cd8, 0x808c2020 }, 0x4|3, 0x4|3 }, // REL5 - {{ 0x808d3b8c, 0x808cefcc, 0x808d2cdc, 0x808c2024 }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808d3bd8, 0x808d5248, 0x808d2d28, 0x808c2070 }, 0x4|3, 0x4|3 }, // REL5 {{ 0x808d3c18, 0x808ceda8, 0x808d2d68, 0x808c20b0 }, 0x28|2, 0x28|2 }, // REL5 {{ 0x808d3c74, 0x808cec64, 0x808d2dc4, 0x808c210c }, 0x4|3, 0x4|3 }, // REL5 @@ -2046,7 +1680,7 @@ static const addr_port_t addr_port_0[2050] = {{ 0x808dbe84, 0x808d7d4c, 0x808dafd4, 0x808ca31c }, 0x6c4|2, 0x6c4|2 }, // REL5 {{ 0x808dc580, 0x808bda70, 0x808db6d0, 0x808caa18 }, 0x34|2, 0x34|2 }, // REL5 {{ 0x808dc5b4, 0x808d772c, 0x808db704, 0x808caa4c }, 0x598|2, 0x598|2 }, // REL5 - {{ 0x808dcbd4, 0x808d847c, 0x808dbd24, 0x808cb06c }, 0x388|2, 0x800|3 }, // REL5 + {{ 0x808dcbd4, 0x808d847c, 0x808dbd24, 0x808cb06c }, 0x388|2, 0x388|2 }, // REL5 {{ 0x808dd3d4, 0x808d8c7c, 0x808dc524, 0x808cb86c }, 0x4c|0, 0x4c|0 }, // RELX {{ 0x809bd6e8, 0x809b8f28, 0x809bc748, 0x809abd28 }, 0x4|0, 0x40|1 }, // MEM1 {{ 0x809bd728, 0x809b8f68, 0x809bc788, 0x809abd68 }, 0x24|0, 0x24|0 }, // MEM1 @@ -2055,10 +1689,11 @@ static const addr_port_t addr_port_0[2050] = {{ 0x809c20d8, 0x809bd918, 0x809c1138, 0x809b0718 }, 0x4|0, 0x4|0 }, // MEM1 {{ 0x809c20f8, 0x809bd950, 0x809c1158, 0x809b0738 }, 0x4|0, 0x4|0 }, // MEM1 {{ 0x809c2100, 0x809bd930, 0x809c1160, 0x809b0740 }, 0x4|0, 0x4|0 }, // MEM1 + {{ 0x809c2108, 0x809bd958, 0x809c1168, 0x809b0748 }, 0x4|0, 0x4|0 }, // MEM1 {{ 0x809c3618, 0x809bee20, 0x809c2678, 0x809b1c58 }, 0x4|0, 0x4|0 }, // MEM1 {{ 0x809c38b8, 0x809bf0b0, 0x809c2918, 0x809b13f8 }, 0x4|0, 0x4|0 }, // MEM1 {{ 0x809c38bc, 0x809bf0b4, 0x809c291c, 0x809b1efc }, 0x8|0, 0x8|0 }, // MEM1 {{ 0x80ae9544, 0x80ae4d84, 0x80ae85a4, 0x80ad7b84 }, 0x4|0, 0x4|0 }, // MEM1 {{ 0xcd000000, 0xcd000000, 0xcd000000, 0xcd000000 }, 0x8000|0, 0x8000|0 }, // GPU -}; // 2050 records +}; // 1685 records diff --git a/project/src/analyze.c b/project/src/analyze.c index 7809a7a..8472a42 100644 --- a/project/src/analyze.c +++ b/project/src/analyze.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/crypt.h b/project/src/crypt.h index d252aab..a3862ed 100644 --- a/project/src/crypt.h +++ b/project/src/crypt.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/crypto/ssl-asm.S b/project/src/crypto/ssl-asm.S index 84963d4..8bc103c 100644 --- a/project/src/crypto/ssl-asm.S +++ b/project/src/crypto/ssl-asm.S @@ -16,7 +16,7 @@ * This file is part of the WIT project. * * Visit http://wit.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/crypto/ssl-asm.h b/project/src/crypto/ssl-asm.h index 1219e16..5259338 100644 --- a/project/src/crypto/ssl-asm.h +++ b/project/src/crypto/ssl-asm.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/db-ctcode.c b/project/src/db-ctcode.c index 4001a9f..983603c 100644 --- a/project/src/db-ctcode.c +++ b/project/src/db-ctcode.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/db-ctcode.h b/project/src/db-ctcode.h index 5d1f8ac..f9e03bc 100644 --- a/project/src/db-ctcode.h +++ b/project/src/db-ctcode.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/db-object.c b/project/src/db-object.c index 2e61e59..57c084b 100644 --- a/project/src/db-object.c +++ b/project/src/db-object.c @@ -61,28 +61,28 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = /* 0x000 */ { 0,0,0,0,0,0, {-1,-1,-1},0, {0,0,0,0,0,0,0,0} }, /* 0x001 */ - { "airblock", "Object not used in regular tracks. Used in competitions as \"invisible wall\" above barriers (so you can't fly/jump over them). They are boxes of 200x200x200 units with a pivot in the bottom face.", + { "airblock", "Object not used in regular tracks. Used in tournaments as an \"invisible wall\" above barriers so you cannot fly/jump over them. They are boxes of 200x200x200 units with a pivot in the bottom face.", OBF_OBJFLOW | OBF_SOLID, obj_charact_s, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x002 */ - { "Psea", "The sea on GCN Peach Beach; for details see Object/Psea.", + { "Psea", "The sea on <small>GCN</small> Peach Beach; for details see Object/Psea.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, {116,-1,-1}, "Psea(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x003 */ - { "lensFX", "Generates a lens flare object when looking at the sun; it's also highly recommended to place this object near or coincident to `sun'.", + { "lensFX", "Generates a lens flare object when looking at the sun; it is also highly recommended to place this object near or coincident to `sun'.", OBF_OBJECT | OBF_NO_FILE | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK | OBF_M_ARENA, obj_charact_ta, &settings_format_uuuu, &settings_format_uuuu, {203,-1,-1}, "lensFX", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x004 */ - { "venice_nami", "The rising and dropping sea on Delfino Pier. This object goes through five stages before it ends at its final height given in setting 2. Stages 1, 3 and 5 are active until a target height is reached, stages 2 and 4 are active for a given time period. The object has an ongoing additional cyclus of rising and dropping between -80 and 80 added to its current height. All target heights are relative to the placement height, the rising speed is in units per frame.", + { "venice_nami", "The rising and dropping sea on Delfino Pier. It requires `pocha' if the player can interact with it, or else the game will freeze upon respawning. This object goes through five stages before it ends at its final height given in setting 2. Stages 1, 3 and 5 are active until a target height is reached, stages 2 and 4 are active for a given time period. The object has an ongoing additional cyclus of rising and dropping between -80 and 80 added to its current height. All target heights are relative to the placement height, the rising speed is in units per frame.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_ARENA, obj_charact_a, &settings_format_uuuu, &settings_format_uuuu, @@ -96,21 +96,21 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Rising speed in even stages", 0 }}, /* 0x005 */ - { "sound_river", "Generates a river sound effect, the range where the sound comes from is controlled by the route, so makes use of it. Only works on slots 3.2, 4.2, 5.2 and 7.3.", + { "sound_river", "Generates a river sound effect. The range where the sound comes from is controlled by the route, so make use of it. Only works on slots 3.2, 4.2, 5.2, and 7.3.", OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x006 */ - { "sound_water_fall", "Generates a waterfall sound effect, the range where the sound comes from is controlled by the route, so makes use of it. Only works on slots 3.2, 4.2, 5.2 and 7.3.", + { "sound_water_fall", "Generates a waterfall sound effect. The range where the sound comes from is controlled by the route, so make use of it. Only works on slots 3.2, 4.2 and 7.3.", OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x007 */ - { "pocha", "Generates a water splash effect when a player touches KCL flag 0x10 with variants 1 (water) or 3 (icy water that also needs the `0x17|Ice' object). Also works for KCL flag 0x1A with variant 2, but cannot be triggered again until the player respawns. Only Y coordinate is used.", + { "pocha", "Generates a water splash effect when a player touches KCL flag 0x10 with variants 1 (water) or 3 (icy water that also needs the `0x17|ice' object). Also works for KCL flag 0x1A with variant 2, but cannot be triggered again until the player respawns. Only the Y coordinate is used.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK | OBF_M_ARENA, obj_charact_ta, &settings_format_uuuu, &settings_format_uuuu, @@ -118,70 +118,70 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = { "Group Y KCL Index", 0, 0, 0, 0, 0, 0, 0 }}, /* 0x008 */ - { "sound_lake", "Generates a lake sound effect, the range where the sound comes from is controlled by the route, so makes use of it. Only works on slot 8.2.", + { "sound_lake", "Generates a lake sound effect. The range where the sound comes from is controlled by the route, so make use of it. Only works on slots 2.2, 3.1, 5.1, and 8.2.", OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x009 */ - { "sound_big_fall", "Generates a louder waterfall sound effect, the range where the sound comes from is controlled by the route, so makes use of it. Only works on slots 3.2 and 7.3.", + { "sound_big_fall", "Generates a louder waterfall sound effect. The range where the sound comes from is controlled by the route, so make use of it. Only works on slots 3.2, 4.2 and 7.3.", OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x00a */ - { "sound_sea", "Generates a sea sound effect, the range where the sound comes from is controlled by the route, so makes use of it.", + { "sound_sea", "Generates a sea sound effect. The range where the sound comes from is controlled by the route, so make use of it. Only works on slots 5.1 and 6.3.", OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x00b */ - { "sound_fountain", "Generates a fountain sound effect, the range where the sound comes from is controlled by the route, so makes use of it. Only works on slots 2.2 and 3.1.", + { "sound_fountain", "Generates a fountain sound effect. The range where the sound comes from is controlled by the route, so make use of it. Only works on slots 2.2, 3.1, 5.1, and 8.2.", OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x00c */ - { "sound_volcano", "Generates a volcano sound effect, the range where the sound comes from is controlled by the route, so makes use of it.", + { "sound_volcano", "Generates a volcano sound effect. The range where the sound comes from is controlled by the route, so make use of it. Only works on slot 8.3.", OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x00d */ - { "sound_audience", "Generates an audience sound effect, the range where the sound comes from is controlled by the route, so makes use of it. Works on slots 1.1, 1.4, 2.3, 3.1 and 5.4; slot 3.1 doesn't feature slot-based audience ambience.", + { "sound_audience", "Generates an audience sound effect. The range where the sound comes from is controlled by the route, so make use of it. Works on slots 1.1, 1.4, 2.3, 3.1, and 5.4; slot 3.1 does not feature slot-based audience ambience.", OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x00e */ - { "sound_big_river", "Generates a louder river sound effect, the range where the sound comes from is controlled by the route, so makes use of it. Only works on slot 5.2.", + { "sound_big_river", "Generates a louder river sound effect. The range where the sound comes from is controlled by the route, so make use of it. Only works on slots 3.2, 4.2, 5.2, and 7.3.", OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x00f */ - { "sound_sand_fall", "Object not used in any track. Generates a sand fall sound effect, the range where the sound comes from is controlled by the route. This object must have a route.", + { "sound_sand_fall", "Object not used in any track. Generates a sand fall sound effect. The range where the sound comes from is controlled by the route. This object must have a route.", OBF_OBJFLOW, obj_charact, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x010 */ - { "sound_lift", "Generates a lift sound effect, the range where the sound comes from is controlled by the route, so makes use of it. Route Setting 1 is always 1 in all Nintendo tracks.", + { "sound_lift", "Generates a lift sound effect. The range where the sound comes from is controlled by the route, so make use of it. Route Setting 1 is always 1 in all Nintendo tracks.", OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x011 */ - { "pochaYogan", "Generates a lava splash effect when a player touches KCL flag 0x10 with variant 2. Only Y coordinate is used.", + { "pochaYogan", "Generates a lava splash effect when a player touches KCL flag 0x10 with variant 2. Only the Y coordinate is used.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, @@ -196,7 +196,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {172,-1,-1}, "entry(E)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x013 */ - { "pochaMori", "Generates a leaf splash effect when a player touches KCL flag 0x1A with variant 2. Only Y coordinate is used.", + { "pochaMori", "Generates a leaf splash effect when a player touches KCL flag 0x1A with variant 2. Only the Y coordinate is used. Only works on slots 4.2 and arena slot 2.5 with group Y KCL index set to 5.", OBF_OBJECT | OBF_UNIQUE | OBF_EFFECT | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK | OBF_M_ARENA, obj_charact_ta, &settings_format_uuuu, &settings_format_uuuu, @@ -204,7 +204,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = { "Group Y KCL Index", 0, 0, 0, 0, 0, 0, 0 }}, /* 0x014 */ - { "eline_control", "Enemy line controller. Multiple controllers can be chained together. The timer of the next controller in a chain begins after the end of the previous. Controller ID 0 is reserved to indicate the end of a controller chain. Enemies can choose to not obey a controller unless the next EHPH Section is set to -1. Found in slots 1.4, 2.2, 3.4 and 4.1 and in Arena 1.2.", + { "eline_control", "Enemy line controller. Multiple controllers can be chained together. The timer of the next controller in a chain begins after the end of the previous controller. Controller ID 0 is reserved to indicate the end of a controller chain. Enemies can choose to not obey a controller unless the next ENPH Section is set to -1. Found in slots 1.4, 2.2, 3.4, 4.1, and arena slot 1.2.", OBF_OBJFLOW | OBF_NO_ROUTE | OBF_M_TRACK | OBF_M_ARENA, obj_charact_ta, &settings_format_uuuu, &settings_format_uuuu, @@ -216,14 +216,14 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = 0, 0, 0, "ENPH Section; if -1, use ENPH of previous controller" }}, /* 0x015 */ - { "sound_Mii", "Generates a mii crowd sound effect, the range where the sound comes from is controlled by the route, so makes use of it.", + { "sound_Mii", "Generates a Mii crowd sound effect. The range where the sound comes from is controlled by the route, so make use of it. Only works on slots 1.1 and 3.1.", OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x016 */ - { "begoman_manager", "Galaxy Colosseum Topmen manager; object not used in any track. Once the topmen controlled by the first manager are defeated, the topmen controlled by the second manager will spawn, etc...", + { "begoman_manager", "Galaxy Colosseum Topmen manager; object not used in any track. Once the Topmen controlled by the first manager are defeated, the Topmen controlled by the second manager will spawn and so forth.", OBF_OBJFLOW | OBF_NO_ROUTE | OBF_F_OTHER, obj_charact_o, &settings_format_uuuu, &settings_format_uuuu, @@ -231,18 +231,20 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = { "Manager ID (1-based)", "[?] Number of Topmen to control", "First Topman ID to control", - "[?] Topman behavior: 1: Coward, they will ignore the player 2: Aggressive, they will attack the player", + "[?] Topman behavior: 0: *unknown* 1: Coward, they will ignore the player 2: Aggressive, they will attack the player", "[?] Number of Topmen under control + Number of Topmen controlled by the previous manager", - 0, 0, 0 }}, + "[?] *unknown*", + "[?] *unknown*", + "[?] *unknown*" }}, /* 0x017 */ - { "ice", "Generates ice around the player when respawned after falling in an icy water fall boundary flag; the location doesn't matter, the ice effect is always gotten. This object can be used to enable tracks for slot 6.1. But is has only impact with in combination with an icy boundary flag. In this case it works only at slot 6.1.", + { "ice", "Generates ice around the player when respawned after falling in an icy water fall boundary flag; the location does not matter, the ice effect is always enabled. This object can be used to enable tracks for slot 6.1, but it only has impact in combination with an icy boundary flag. In this case, it only works on slot 6.1.", OBF_OPTIONAL | OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, {191,-1,-1}, "ice(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x018 */ - { "startline2D", "Generates a finish line at given location, this object is used in competitions where you have to drive laps on a battle course and some others; object not used in any track.", + { "startline2D", "Generates a finish line at given location. This object is used in tournaments where you have to drive laps on a battle arena and some others; object not used in any track.", OBF_OBJFLOW, obj_charact, &settings_format_uuuu, &settings_format_uuuu, @@ -325,7 +327,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = /* 0x063 */ { 0,0,0,0,0,0, {-1,-1,-1},0, {0,0,0,0,0,0,0,0} }, /* 0x064 */ { 0,0,0,0,0,0, {-1,-1,-1},0, {0,0,0,0,0,0,0,0} }, /* 0x065 */ - { "itembox", "Spinning box with a question mark in it. If touched it snaps and an item lottery begins; after the lottery the item shown is gotten.", + { "itembox", "Spinning box with a question mark inside it. If touched, it snaps and an item lottery begins; after the lottery, the item shown is retrieved.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_FOUND | OBF_ITEMBOX, obj_charact_s_tao, &settings_format_uxxu, &settings_format_uuuu, @@ -339,7 +341,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "[?] Additional height, multiplied with unknown number (always 1?).", "Unknown" }}, /* 0x066 */ - { "DummyPole", "Solidity of the poles of different courses. Deleting this object will cause the Dummy pole itself to be unsolid.", + { "DummyPole", "Pole solidity across different tracks. Deleting this object will cause the pole itself to be unsolid.", OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_M_TRACK | OBF_F_OTHER, obj_charact_s_to, &settings_format_uuuu, &settings_format_uuuu, @@ -361,56 +363,56 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {176,-1,-1}, "flagBlend", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x069 */ - { "gnd_sphere", "Object not used in any track. Green sphere with animation, solid.", + { "gnd_sphere", "Object not used in any track. Solid green sphere with an animation.", OBF_OBJFLOW, obj_charact, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x06a */ - { "gnd_trapezoid", "Object not used in any track. Red trapezoid with animation, solid.", + { "gnd_trapezoid", "Object not used in any track. Solid red trapezoid with an animation.", OBF_OBJFLOW, obj_charact, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x06b */ - { "gnd_wave1", "Object not used in any track. Blue object that makes wave animation. If CPUs touch down the object, they dissapear.", + { "gnd_wave1", "Object not used in any track. Blue object that makes a wave animation. If CPUs touch down the object, they disappear.", OBF_OBJFLOW, obj_charact, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x06c */ - { "gnd_wave2", "Object not used in any track. Yellow object that makes wave animation. If CPUs touch down the object, they dissapear.", + { "gnd_wave2", "Object not used in any track. Yellow object that makes a wave animation. If CPUs touch down the object, they disappear.", OBF_OBJFLOW, obj_charact, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x06d */ - { "gnd_wave3", "Object not used in any track. Orange object that makes wave animation. If CPUs touch down the object, they dissapear.", + { "gnd_wave3", "Object not used in any track. Orange object that makes a wave animation. If CPUs touch down the object, they disappear.", OBF_OBJFLOW, obj_charact, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x06e */ - { "gnd_wave4", "Object not used in any track. Blue object that makes wave animation. If CPUs touch down the object, they dissapear.", + { "gnd_wave4", "Object not used in any track. Blue object that makes a wave animation. If CPUs touch down the object, they disappear.", OBF_OBJFLOW, obj_charact, &settings_format_uuuu, &settings_format_uuuu, {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x06f */ - { "sun", "The sun in the vrcorn, often used with `lensFX'.", + { "sun", "The sun in the background; often used with `lensFX'.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK | OBF_M_ARENA, obj_charact_ta, &settings_format_uuuu, &settings_format_uuuu, {240,-1,-1}, "sun(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x070 */ - { "woodbox", "Wooden box. When touched the player slows down and the box drops an item. The wooden boxes respawn after 5 seconds, drop from 5000 units above the origin and drop onto the first face they touch. In Time Trial it becomes an unbreakable `ironbox'.", + { "woodbox", "Wooden box. When touched, the player slows down and the box drops an item. The wooden boxes respawn after five seconds, drop from 5000 units above the origin and drop onto the first face they touch. In Time Trials, it becomes an unbreakable `ironbox'.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_SCALE | OBF_ROTATE | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -428,7 +430,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {73,-1,-1}, "KmoonZ(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x072 */ - { "sunDS", "The Angry Sun from DS Desert Hills. It changes point of view and rotation of the crown according to player's position. Route Setting 2 controls the behavior depending on the value X: X < 30 (1E in hex) → Stays for X/60 seconds X ≥ 30 (1E in hex) → Drops a `FireSnake' staying for X/60 seconds. In both cases the dropping animation is viewed; if the route start point is set to drop, it will drop at the second \"lap\" of the route. Only slots 3.1 and 7.1 support this object.", + { "sunDS", "The Angry Sun from <small>DS</small> Desert Hills. It changes point of view and rotation of the crown according to player's position. Route Setting 2 controls the behavior depending on the value X: X < 30 (1E in hex) → Stays for X/60 seconds X ≥ 30 (1E in hex) → Drops a `FireSnake' staying for X/60 seconds. In both cases, the dropping animation is viewed; if the route start point is set to drop, it will drop at the second \"lap\" of the route. Only slots 3.1, 4.2, 6.2, and 7.1 support this object.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, @@ -437,7 +439,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Delay before starting in 1/60 seconds after starting of countdown. 240 (F0 in hex) = Starts immediately after the \"GO!\"", 0, 0, 0, 0, 0, 0 }}, /* 0x073 */ - { "coin", "Present in all battle courses in Coin Runners mode and in some tournaments, when touched it disappears and the player gets one coin. Some coins don't appear at the start of the battle but show up later. See Object/coin for details.", + { "coin", "Present within all battle arenas in Coin Runners mode and in some tournaments. When touched, it disappears and the player gets one coin. Some coins do not appear at the start of the battle but show up later on. See Object/coin for details.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_SCALE | OBF_ROTATE | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_ARENA, obj_charact_s_a, &settings_format_uuuu, &settings_format_uuuu, @@ -454,7 +456,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x075 */ - { "ItemDirect", "Object used in tournaments (SNES Battle Course 4 and Daisy Circuit). Can be used to place an item directly onto the track. They will not show up in time trial. You must not place more than 11 of these in a track otherwise your track will freeze or hang in online play.", + { "ItemDirect", "Object used in tournaments (Daisy Circuit and <small>SNES</small> Battle Course 4). Can be used to place an item directly onto the track; they will not show up in Time Trials. You must not place more than 11 of these in a track; otherwise, your track will freeze or hang in online play.", OBF_OBJFLOW, obj_charact, &settings_format_uuuu, &settings_format_uuuu, @@ -462,7 +464,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = { "0 = Green Shell 1 = Red Shell 2 = Banana 3 = Mushroom 4 = Star", 0, 0, 0, 0, 0, 0, 0 }}, /* 0x076 */ - { "s_itembox", "Item box that acts like a kart, it moves with moving KCL. When placed high, it falls until it reaches the ground, and when placed on a steep surface, it falls.", + { "s_itembox", "Item box that acts similarly to a placed item. It moves in conjunction with most moving objects and is normally locked in a relative Y-position, moving along with the object's behavior. Otherwise, it typically phases through object collision altogether. Some interactions might be slot specific, such as with `quicksand'. When placed high without an object underneath, it falls until it reaches the ground, and when placed on a steep surface, it falls down the slope, but can sometimes cause a crash due to unknown reasons.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK | OBF_M_ARENA | OBF_ITEMBOX, obj_charact_s_ta, &settings_format_uxxu, &settings_format_uuuu, @@ -473,10 +475,10 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "[?] Disables shadow if set", 0, "[?] Timing lottery", - "?", + "Height offset with object's position, signed.", "[?] Unknown" }}, /* 0x077 */ - { "pile_coin", "Object not used in any track. This is the pile of coins above the players used in battle mode, static and without collision.", + { "pile_coin", "Object not used in any track. This is the pile of coins above the players used in Battle Mode; static and without collision.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_SCALE | OBF_ROTATE | OBF_OBJFLOW | OBF_SOLID | OBF_FNAME, obj_charact_s, &settings_format_uuuu, &settings_format_uuuu, @@ -576,7 +578,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Route start point", 0, 0, 0 }}, /* 0x0ca */ - { "MashBalloonGC", "Airballoon as seen on GCN Mario Circuit. It has an assigned route but also floats from Y to Y.", + { "MashBalloonGC", "Air balloon as seen in <small>GCN</small> Mario Circuit. It has an assigned route but also floats from Y to Y. It turns to face the direction it is traveling in.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK | OBF_F_OTHER, obj_charact_r_to, &settings_format_uuuu, &settings_format_uuuu, @@ -585,7 +587,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Max Y difference", 0, 0, 0, 0, 0, 0 }}, /* 0x0cb */ - { "WLwallGC", "Horizontal moving Piranha Plant wall from GCN Waluigi Stadium. It moves like a sine function (inside → outside → inside); normally combined with `WLdokanGC'.", + { "WLwallGC", "Horizontal moving Piranha Plant wall from <small>GCN</small> Waluigi Stadium. It moves like a sine function (inside → outside → inside); normally combined with `WLdokanGC'.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_KCL | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -597,7 +599,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Going out first time", 0, 0, 0 }}, /* 0x0cc */ - { "CarA1", "Moving Car from Coconut Mall. It moves exactly like `WLwallGC' but instead left → right.", + { "CarA1", "Moving car from Coconut Mall. It moves exactly like `WLwallGC' but instead left → right.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -607,7 +609,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Time of pause", 0, 0, 0, 0, 0 }}, /* 0x0cd */ - { "basabasa", "Bats following a route, when touched they act like a wall. The bats are released as groups which can be edited in any way.", + { "basabasa", "Swoopers that follow a route. When touched, they act like a wall. They are released as groups which can be edited in any way.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -621,7 +623,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Start delay in 1/60 seconds", "?" }}, /* 0x0ce */ - { "HeyhoShipGBA", "Shy Guy ship which shoots exploding cannonballs; cannonball object is `HeyhoBallGBA'. This object is made for counterclockwise directed tracks, so if a track is clockwise directed this object must be modified with BrawlBox in the following ways: Cullmode from Materials must be set on Cull_Outside and Z scale in KMP must be -1. Only slot 6.2 supports this object and it's necessary to allow tracks to work on this slot.", + { "HeyhoShipGBA", "Shy Guy ship which shoots exploding cannonballs; cannonball object is `HeyhoBallGBA'. This object is made for counterclockwise directed tracks, so if a track is clockwise directed, this object must be modified with BrawlBox in the following ways: CullMode from Materials must be set on Cull_Outside and the Z scale in the KMP must be -1. Only slot 6.2 supports this object and it is necessary to allow tracks to work on this slot.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, @@ -630,7 +632,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "How strong it moves up and down", 0, 0, 0, 0, 0, 0 }}, /* 0x0cf */ - { "koopaBall", "Gigantic exploding fireball, used with `koopaFigure'.", + { "koopaBall", "Gigantic exploding fireball; used with `koopaFigure'. It bounces on every new route point and explodes on the last one if the route cycle setting is turned on. This object always spins northward. Scale is only obeyed if the route cycle setting is turned off, although the fiery effect still does not obey scaling.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -649,7 +651,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Texturing: 0 = MooMoo 1 = Fruit 2 = Factory", 0, 0, 0, 0 }}, /* 0x0d1 */ - { "car_body", "Car from Moonview Highway. Route Setting 1 is used for blinking (1 = Left, 2 = Right) Route Setting 2 selects the speed (0 or 1)", + { "car_body", "Car from Moonview Highway. Route Setting 1 is used for blinking (1 = Left, 2 = Right) Route Setting 2 selects the speed (0 or 1).", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -661,7 +663,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Unknown", 0, 0, 0 }}, /* 0x0d2 */ - { "skyship", "Blimp from Luigi Circuit.", + { "skyship", "Blimp from Luigi Circuit. It turns to face the direction it is traveling in.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK | OBF_F_OTHER, obj_charact_r_to, &settings_format_uuuu, &settings_format_uuuu, @@ -670,7 +672,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "[?] Max Y difference", 0, 0, 0, 0, 0, 0 }}, /* 0x0d3 */ - { "w_woodbox", "Box following route. Route Setting 1 sets the speed (gets added to S1).", + { "w_woodbox", "Wooden box that follows a route. Route Setting 1 sets the speed (gets added to S1).", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_SCALE | OBF_ROTATE | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -684,7 +686,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Max amount of boxes", 0 }}, /* 0x0d4 */ - { "w_itembox", "Itemboxes following route.", + { "w_itembox", "Multiple item boxes that follow a route from a starting point to an ending point.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK | OBF_ITEMBOX, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -698,7 +700,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Number of itemboxes on the route (default 5)", 0 }}, /* 0x0d5 */ - { "w_itemboxline", "`Press', block.brres and `itembox' combination from Toad's Factory. Each block follows a route until it reach the press and the press converts it to an itembox which continues the route. Route setting 1 is the speed it slows down to (if 0 it uses the speed setting in S1). Route setting 2: 0x1: press activates when a block reaches this point 0x2: determines where the itembox glows", + { "w_itemboxline", "`Press', block.brres and `itembox' combination from Toad's Factory. Each block follows a route until it reach the press and the press converts it to an item box which continues the route. Route setting 1 is the speed it slows down to (if 0 it uses the speed setting in S1). Route setting 2: 0x1: press activates when a block reaches this point 0x2: determines where the item box goes", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_MULTI_FNAME | OBF_M_TRACK | OBF_ITEMBOX, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -710,7 +712,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Number of Blocks/Item Boxes that can exist at any one time", 0 }}, /* 0x0d6 */ - { "VolcanoBall1", "Firery rock from Grumble Volcano. When created a volcano explosion occurs and it follows the route until it touches a solid part, then it becomes a fire; slot 3.4 enables its SFX.", + { "VolcanoBall1", "Fiery rock from Grumble Volcano. When created, a volcano explosion occurs and it follows the route until it touches a solid part, then it becomes a fire; slot 3.4 enables its SFX.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -721,7 +723,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Time until the fire goes out", 0, 0, 0, 0 }}, /* 0x0d7 */ - { "penguin_s", "Small penguin from N64 Sherbet Land, creates a symmetrical copy of itself under the ground to simulate ice reflection. Route Setting 1: 0 = Default; 1 = Glide; 2 = Animation faster; 3 = Default. Route Setting 2 describes the speed when Route Setting 1 ≠ 0, but is always required a value ≠ 0. Slot 6.1 enables its SFX.", + { "penguin_s", "Small penguin from <small>N64</small> Sherbet Land. It creates a symmetrical copy of itself under the ground to simulate an ice reflection. Route Setting 1: 0 = Default; 1 = Glide; 2 = Animation faster; 3 = Default. Route Setting 2 describes the speed when Route Setting 1 ≠ 0, but always requires a value ≠ 0. Slot 6.1 enables its SFX.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_BRASD | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -729,7 +731,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = { "Speed", 0, 0, 0, 0, 0, 0, 0 }}, /* 0x0d8 */ - { "penguin_m", "Medium penguin from N64 Sherbet Land. Slot 6.1 enables its SFX.", + { "penguin_m", "Medium penguin from <small>N64</small> Sherbet Land. Slot 6.1 enables its SFX.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_BRASD | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -738,9 +740,9 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "LE-CODE or cheat code required: Route start point.", "LE-CODE or cheat code required: If S8=1: Item to drop (same as ItemDirect).", 0, 0, 0, 0, - "LE-CODE or special cheat code required: 0: normal behaviour 1: custom \"mushroom car\" behaviour developed by KHacker." }}, + "LE-CODE or special cheat code required: 0: normal behavior 1: custom \"mushroom car\" behavior developed by kHacker35000vr." }}, /* 0x0d9 */ - { "penguin_l", "Large penguin from N64 Sherbet Land.", + { "penguin_l", "Large penguin from <small>N64</small> Sherbet Land.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, @@ -757,7 +759,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Max Y difference", 0, 0, 0, 0, 0, 0 }}, /* 0x0db */ - { "dossunc", "Thwomp with optional route; without route, S1 and S2 must be 0. If S2 = 2, a 3-point route is needed to make effect: 1 → Start point, Route Setting 2 = 0 2 → Rotation point, Route Setting 2 = 1 3 → Going down point, Route Setting 2 = 0. The couple starts, at the second point turns of 180° and goes left and right, going down around the third point according to player's direction, then goes back to the first point. To make effect the object needs a rotation of ±90°, route points must have the same Y and Z coordinate and no other object must be near the start point. In GP and VS Race the object is activated by the proximity of a main player (not a CPU) and the speed is proportional to the player's; in Time Trial speed and start delay are the same of respective settings in KMP file. If S2 = 3, Route Setting 2 (\"cycle\") must be 1, or else the Thwomp will spin endlessly when hit by an item.", + { "dossunc", "Thwomp with optional route; without route, S1 and S2 must be 0. If S2 = 2, a 3-point route is needed to make effect: 1 → Start point, Route Setting 2 = 0 2 → Rotation point, Route Setting 2 = 1 3 → Going down point, Route Setting 2 = 0. The couple starts, at the second point turns of 180° and goes left and right, going down around the third point according to player's direction, then goes back to the first point. To make effect, the object needs a rotation of ±90°, route points must have the same Y and Z coordinate and no other object must be near the start point. In Grand Prix and VS races, the object is activated by the proximity of a main player (not a CPU) and the speed is proportional to the player's; in Time Trial speed and start delay are the same of respective settings in KMP file. If S2 = 3, Route Setting 2 (\"cycle\") must be 1, or else the Thwomp will spin endlessly when hit by an item.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_SOLID | OBF_OPT_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_or_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -775,7 +777,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x0dd */ - { "boble", "Podoboo from GBA Bowser Castle 3. Route Setting 1 controls the speed (gets added to S1), Route Setting 2 = 1 means that the model flips horizontally.", + { "boble", "Lava bubble from <small>GBA</small> Bowser Castle 3. Route Setting 1 controls the speed (gets added to S1), Route Setting 2 = 1 means that the model flips horizontally.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -814,7 +816,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {194,-1,-1}, "kart_truck_dummy", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x0e2 */ - { "hanachan", "Wiggler from Maple Treeway. Route Setting 1 sets the time in 1/60 seconds of stop in that point. Define the route heights carfefully. If the Wiggler has issues with the body segments, move the route to a more flat area.", + { "hanachan", "Wiggler from Maple Treeway. It shows up on the minimap in non-racing modes. Route Setting 1 sets the time in 1/60 seconds of stop in that point. Define the route heights carefully. If the Wiggler has issues with the body segments, move the route to a more flat area.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_BRASD | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -822,7 +824,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = { "Speed", 0, 0, 0, 0, 0, 0, 0 }}, /* 0x0e3 */ - { "seagull", "Seagull route following from tracks with marine setting.", + { "seagull", "Seagull that follows a route. It is found in tracks with a marine setting.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, @@ -839,7 +841,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = { "Speed", 0, 0, 0, 0, 0, 0, 0 }}, /* 0x0e5 */ - { "crab", "Crab from GBA Shy Guy Beach. Route Setting 1 sets the time in 1/60 seconds of stop in that point.", + { "crab", "Crab from <small>GBA</small> Shy Guy Beach. Route Setting 1 sets the time in 1/60 seconds of stop in that point.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_BRASD | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -855,7 +857,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x0e7 */ - { "CarA2", "Moving Car from Coconut Mall.", + { "CarA2", "Moving car from Coconut Mall.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -865,7 +867,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Time of pause", 0, 0, 0, 0, 0 }}, /* 0x0e8 */ - { "CarA3", "Moving Car from Coconut Mall.", + { "CarA3", "Moving car from Coconut Mall.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -875,7 +877,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Time of pause", 0, 0, 0, 0, 0 }}, /* 0x0e9 */ - { "Hwanwan", "Route-following Chain Chomp from DS Peach Gardens. Hwanwan and wanwan only work together if the effect files are absent. Route Setting 2 = 1 plays a rollover animation, originally used on a Competition in Rainbow Road.", + { "Hwanwan", "Route-following Chain Chomp from <small>DS</small> Peach Gardens. Hwanwan and wanwan only work together if the effect files are absent. Route Setting 2 = 1 plays a rollover animation, originally used within a tournament in Rainbow Road.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -884,7 +886,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Amount of item boxes carried", 0, 0, 0, 0, 0, 0 }}, /* 0x0ea */ - { "HeyhoBallGBA", "Cannonball landing area, which explodes after 3 seconds, shot by `HeyhoShipGBA'; in GP and VS Race it explodes if touched. The object's scale doesn't affect the explosion effect's dimension. Generally CPUs don't go against this object as they try to avoid them. This objects requires `HeyhoShipGBA' and therefor it can only be used on 6.2. Note that no more than 59 of this object can be used.", + { "HeyhoBallGBA", "Cannonball landing area that explodes after three seconds, shot by `HeyhoShipGBA'; in Grand Prix and VS races, it explodes if touched. The object's scale does not affect the explosion effect's dimension. Generally, CPUs do not go against this object as they try to avoid them. This objects requires `HeyhoShipGBA', and therefore, it can only be used on slot 6.2. Note that no more than 59 of this object can be used.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -893,7 +895,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Time between shot and arrival in 1/60 seconds", 0, 0, 0, 0, 0, 0 }}, /* 0x0eb */ - { "Twanwan", "Rolling Chain Chomp from Chain Chomp Wheel. The object has two different kind of movements; one being a route and one relative to it's current location based off a sine wave, whereby the wave is controlled by s3 and s4.", + { "Twanwan", "Rolling Chain Chomp from Chain Chomp Wheel. The object has two different kind of movements; one being a route and one relative to its current location based on a sine wave, whereby the wave is controlled by s3 and s4. It appears on the minimap when playing on arena slot 1.4.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_ARENA, obj_charact_r_s_a, &settings_format_uuuu, &settings_format_uuuu, @@ -914,7 +916,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = { "Start speed", 0, 0, 0, 0, 0, 0, 0 }}, /* 0x0ed */ - { "bird", "Eagle route following from GCN DK Mountain.", + { "bird", "Route-following eagle from <small>GCN</small> DK Mountain.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, @@ -923,7 +925,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Number of eagles", 0, 0, 0, 0, 0, 0 }}, /* 0x0ee */ - { "sin_itembox", "Item box following a route back and forth; speed is like sine function. Route Setting 2: 0 = Asymetric; 1 = Symetric.", + { "sin_itembox", "Item box following a route back and forth; speed is like a sine function. Route Setting 2: 0 = Asymetric; 1 = Symetric.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_SOLID | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_M_TRACK | OBF_ITEMBOX, obj_charact_r_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -940,18 +942,18 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {131,-1,-1}, "Twanwan_ue", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x0f0 */ - { "BossHanachan", "Big Wiggler boss used in the Wario's Gold Mine competition; follows a route. If S2 of the route point = 0002 (S1 needs to be 0000 otherwise it will try to do different things at the same time and Wiggler's body will glitch out), it will play Wiggler's trick animation once Wiggler gets to the point. See BossHanachan for more information about his route settings.", + { "BossHanachan", "Big Wiggler boss used in the Wario's Gold Mine tournament; follows a route. If S2 of the route point = 0002 (S1 needs to be 0000; otherwise, it will try to do different things at the same time and Wiggler's body will glitch out), it will play Wiggler's trick animation once Wiggler gets to the point. See BossHanachan for more information about its route settings.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_BRASD | OBF_OBJFLOW | OBF_SOLID | OBF_FNAME, obj_charact_s, &settings_format_uuuu, &settings_format_uuuu, {187,-1,-1}, "hanachan(BE2D)", { "Primary Wiggler Speed", - "Unknown", + "Time in 1/60 seconds wiggler stops before using its angry speed. Used instead of s7 if player is behind point specified in s6 when wiggler stops", "Secondary Wiggler Speed", - "Point where wiggler changes to speed two. If passed before wiggler stops, it will not change to speed two. Route settings must be 0000 0001", + "Point player must pass to change wiggler to speed two. The wiggler must stop to activate this speed change. Route settings 0000 0001", "Angry Wiggler Speed", - "Point where wiggler changes to angry speed. It will function as long as the second speed change has been added, and route settings are 0000 0001", - "Time Wiggler stop to being angry (in decimals)", + "Point player must pass to allow the wiggler to become angry. Route settings 0000 0001", + "Time in 1/60 seconds wiggler stops before using its angry speed. Used instead of s2 if player is past point specified in s6 when wiggler stops", 0 }}, /* 0x0f1 */ { "Kdossunc", "Object not used in any track.", @@ -961,7 +963,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x0f2 */ - { "BossHanachanHead", "Object used in the Wario's Gold Mine competition to show the Wiggler's head on the map. It is not found in the KMP, but adding BossHanachan will automatically generate it in game.", + { "BossHanachanHead", "Object used in the Wario's Gold Mine tournament to show the Wiggler's head on the minimap. It is not found in the KMP, but adding BossHanachan will automatically generate it in-game.", OBF_OBJFLOW | OBF_SOLID, obj_charact_s, &settings_format_uuuu, &settings_format_uuuu, @@ -1039,7 +1041,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {171,-1,-1}, "dummy", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x12e */ - { "dokan_sfc", "Pipe from Luigi Circuit and SNES Mario Circuit 3.", + { "dokan_sfc", "Pipe from Luigi Circuit and <small>SNES</small> Mario Circuit 3.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_SCALE | OBF_ROTATE | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -1198,7 +1200,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {197,-1,-1}, "kinokoT2", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x144 */ - { "pylon01", "Street cone from Daisy Circuit. Only slots 3.1 and 7.1 support this object with a limit of 30. Colors can be changed in the CLR0 (maybe even added).", + { "pylon01", "Street cone from Daisy Circuit. Only slots 3.1, 4.2, 6.2 and 7.1 support this object with a limit of 30. Colors can be changed in the CLR0 (maybe even added).", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -1206,7 +1208,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = { "Color: 0 = Red 1 = Blue 2 = Yellow", 0, 0, 0, 0, 0, 0, 0 }}, /* 0x145 */ - { "PalmTree", "Solid palm from Coconut Mall. It's the largest tree of Mario Kart Wii.", + { "PalmTree", "Solid palm from Coconut Mall. It is the largest tree of Mario Kart Wii.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_SCALE | OBF_ROTATE | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -1234,7 +1236,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {70,-1,-1}, "K_sticklift00(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x149 */ - { "heyho2", "Manager of the Shy Guy Ski Lift from DK Summit. Spawns 30 Chairlifts that travel on a route. Route setting 0 removes the Shy Guys. Route setting 1 randomly makes either 0, 1 or 2 randomly coloured Shy Guys spawn on the chair.", + { "heyho2", "Manager of the Shy Guy Ski Lift from DK Summit. Spawns 30 Chairlifts that travel on a route. Route setting 0 removes the Shy Guys. Route setting 1 randomly makes either 0, 1 or 2 randomly colored Shy Guys spawn on the chair.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_ALWAYS_ROUTE | OBF_FNAME | OBF_MULTI_FNAME | OBF_M_TRACK, obj_charact_r_t, &settings_format_uuuu, &settings_format_uuuu, @@ -1328,7 +1330,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {46,-1,-1}, "FlagB2(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x156 */ - { "FlagA3", "\"Mario Kart\" flag from DS Delfino Square. Strangely, scales must follow a precise proportion: Xscale < Yscale < Zscale, or game freezes. It's a bit buggy, so it's better use another \"FlagA\" object and import the original texture.", + { "FlagA3", "\"Mario Kart\" flag from DS Delfino Square. Strangely, scales must follow a precise proportion: Xscale < Yscale < Zscale, or game freezes. It is a bit buggy, so it is better use another \"FlagA\" object and import the original texture.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, @@ -1412,7 +1414,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {255,-1,-1}, "windmill(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x162 */ - { "dossun", "Thwomp caged in N64 Bowser's Castle growling when a player approaches; it's an unsolid decoration.", + { "dossun", "Thwomp caged in N64 Bowser's Castle growling when a player approaches; it is an unsolid decoration.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, @@ -1426,7 +1428,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {128,-1,-1}, "TownTreeDS(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x164 */ - { "Ksticketc", "Port, opens when approaching.", + { "Ksticketc", "Toll booth gate from Moonview Highway, opens when approaching. Opens for cars and trucks only on slot 4.2.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -1561,14 +1563,14 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {247,-1,-1}, "v_stand2", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x175 */ - { "leaf_effect", "Leaf effect when player drives or flies through tree leafs.", + { "leaf_effect", "Leaf effect when player drives or flies through tree leaves. Its SFX is exclusive to certain slot(s).", OBF_OBJECT | OBF_UNIQUE | OBF_EFFECT | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, {202,-1,-1}, "leaf_effect(E)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x176 */ - { "karehayama", "Leaf pile from Maple Treeway.", + { "karehayama", "Leaf pile from Maple Treeway. Its SFX is exclusive to certain slot(s).", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_SCALE | OBF_ROTATE | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uxuu, &settings_format_uuuu, @@ -1641,7 +1643,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {98,-1,-1}, "MiiSphinxY2(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x180 */ - { "FlagA5", "Start line flag from Koopa Cape. It's less buggy than `FlagA3'.", + { "FlagA5", "Start line flag from Koopa Cape. It is less buggy than `FlagA3'.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, @@ -1817,13 +1819,13 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = { "Length of chain in game units", "Unknown", 0, - "Let (X,Y) be the the center of the wedge points to, then (X/10) if X positive, 65536+(X/10) if X negative", - "Let (X,Y) be the the center of the wedge points to, then (Y/10) if Y positive, 65536+(Y/10) if Y negative", - "Time to wander around (in 1/60 seconds); if 0, about 5 seconds is used. Add 3,5 seconds for full cycle time", + "Let (X,Y) be the center of the area where the Chain Chomp snaps to (neither X nor Y are height coordinates). If X is positive, X/10 is the X-Value for the setting; if X is negative, 65536 + X/10 is the X-Value for the setting (make sure to include the negative sign when adding!).", + "Let (X,Y) be the center of the area where the Chain Chomp snaps to (neither X nor Y are height coordinates). If Y is positive, Y/10 is the Y-Value for the setting; if Y is negative, 65536 + Y/10 is the Y-Value for the setting (make sure to include the negative sign when adding!).", + "Time to wander around (in 1/60 seconds); if 0, about 5 seconds is used. Add 3.5 seconds for full cycle time", "(Width of wedge in degrees-35)/2", 0 }}, /* 0x197 */ - { "poihana", "Cataquack from GCN Peach Beach. It flings players into the air. In GP and VS race, it looks for players. In Time Trials, it flings only if touched. It is likely possible to add further colors by modifying the Pat0.", + { "poihana", "Cataquack from GCN Peach Beach. It flings players into the air. In GP and VS race, it looks for players. In Time Trials, it flings only if touched. It is likely possible to add further colors by modifying the Pat0. Only works on Slot 5.1 if psea or venice_nami is present for a splash sfx.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_BRASD | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -1929,7 +1931,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {217,-1,-1}, "pakkun_dokan(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x1a3 */ - { "begoman_spike", "Topman from Galaxy Colosseum; object not used in any track. To appear, it (or they) must be the first object of section GOBJ. Note that the rings are hardcoded to have their centre at (0,0)", + { "begoman_spike", "Topman from Galaxy Colosseum; object not used in any track. To appear, it (or they) must be the first object of section GOBJ. They appear to not obey wall collision. Note that the rings are hardcoded to have their centre at (0,0).", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_F_OTHER, obj_charact_s_o, &settings_format_uuuu, &settings_format_uuuu, @@ -1941,9 +1943,9 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Time in frames from the start of the race until the topman will switch from the 2nd ring to the 3rd ring.", "The radius of the 3rd ring in which the topman is allowed to roam in.", "Time in frames from the start of the race until the topman will switch from the 3rd ring to the 4th ring.", - "The radius of the 3rd ring in which the topman is allowed to roam in." }}, + "The radius of the 4th ring in which the topman is allowed to roam in." }}, /* 0x1a4 */ - { "FireSnake", "Grounded Podoboo from DS Desert Hills. It bounces casually around its position point. It works with the object `sunDS', so it only works on slots 3.1 and 7.1.", + { "FireSnake", "Grounded Podoboo from DS Desert Hills. It bounces casually around its position point. It works with the object `sunDS', so it only works on slots 3.1, 4.2, 6.2 and 7.1.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -1971,7 +1973,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = { "Rotations per 12 seconds", "Direction: 0 = Clockwise 1 = Counterclockwise", 0, 0, 0, 0, 0, - "[?] Unused in the normal game. With this cheat code this setting can be used to change the speed to S1/(30*S8) instead of S1/30, allowing for slower Epropellers." }}, + "[?] Unused in the normal game. With LE-CODE or this cheat code this setting can be used to change the speed to S1/(30*S8) instead of S1/30, allowing for slower Epropellers." }}, /* 0x1a7 */ { "dc_pillar_c", "Object not used in any track.", OBF_OBJFLOW | OBF_SOLID, @@ -1980,17 +1982,17 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x1a8 */ - { "FireSnake_v", "Grounded Podoboo from Grumble Volcano. It jump from its position point describing a parabola and after landing bounces casually around the arrival point.", + { "FireSnake_v", "Grounded Podoboo from Grumble Volcano. It jump from its position point describing a parabola and after landing bounces casually around the arrival point for 10 seconds until it vanishes.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, {39,-1,-1}, "FireSnake(BE)", { "Start delay in 1/60 seconds after starting of countdown. 240 (F0 in hex) = Starts immediately after the \"GO!\"", - "Duration and respawn factor, K reference value is 600 (258 in hex): X < K → Duration time in 1/60 seconds, then respawn without loading vanishing animation X = K → 10 seconds of duration, then respawn after other 10 seconds X > K → 10 seconds of duration, then respawn after (X - 600)/60 seconds. Normally is used the third option", - "Units of distance from position point to landing point following the Y angulation", + "The time between two firesnake spawns. <600 causes the previous snake to disappear, 600 despawns each second snake immediately.", + "Units of distance from position point to landing point following the Y angulation.", 0, 0, 0, 0, 0 }}, /* 0x1a9 */ - { "honeBall", "Object not used in regular tracks. Used in the N64 Bowser castle competition with Dry Bowser.", + { "honeBall", "Object not used in regular tracks. Used in the <small>N64</small> Bowser's Castle tournament with Dry Bowser. For use of this object in Mission Mode, at least one CPU must be defined. The location of the object does not matter. If more than one CPU is defined, it will cause weird behavior. If more than one CPU exists in a mission with this object, only the one that is the closest to the player will fire at them. Occasionally, some will try and fire at the same time, but this causes them to spin out repeatedly until another fireball is fired. Regardless of how many CPUs are defined in a mission with this object, or how many times this object is added, only one of the CPUs will fire at the player.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_COMMONOBJ | OBF_OBJFLOW | OBF_SOLID | OBF_FNAME, obj_charact_s, &settings_format_uuuu, &settings_format_uuuu, @@ -2004,7 +2006,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {229,-1,-1}, "puchi_pakkun(BD)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x1ab */ - { "sanbo_big", "Giant Pokey used in the Thwomp Desert Competition, where its scale is 7 on the X, Y, and Z axis KMP KMP cloud seems to slightly corrupt the giant pokey, as its sound will not be loaded and its head will not appear on the minimap.", + { "sanbo_big", "Giant Pokey used in the Thwomp Desert tournament, where its scale is 7 on the X, Y and Z-axes. KMP KMP Cloud seems to slightly corrupt the Giant Pokey, as its sound will not be loaded and its head will not appear on the minimap.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_BRASD | OBF_OBJFLOW | OBF_SOLID | OBF_FNAME, obj_charact_s, &settings_format_uuuu, &settings_format_uuuu, @@ -2090,23 +2092,30 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = /* 0x1f3 */ { 0,0,0,0,0,0, {-1,-1,-1},0, {0,0,0,0,0,0,0,0} }, /* 0x1f4 */ { 0,0,0,0,0,0, {-1,-1,-1},0, {0,0,0,0,0,0,0,0} }, /* 0x1f5 */ - { "kinoko_ud", "Moving decoration mushroom from Mushroom Gorge.", + { "kinoko_ud", "Moving bouncy mushroom from Mushroom Gorge.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_KCL | OBF_SCALE | OBF_ROTATE | OBF_FALLDOWN | OBF_OBJFLOW | OBF_SOLID | OBF_ROAD | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, {195,-1,-1}, "kinoko(B4K)", - { "[?] Texturing: 0 = Light 1 = Dark", - 0, 0, 0, 0, 0, 0, 0 }}, + { "[?] Texturing: nonzero values load the dark variant for the stem instead", + "[?] Amplitude of the up-down movement", + "[?] Time in 1/60s for a full up-down cycle", + "[?] Cycle shift (controls where in the cycle to start)", + "[?] Time in 1/60s to pause at the lowest point in the cycle", + 0, 0, 0 }}, /* 0x1f6 */ - { "kinoko_bend", "Bouncy mushroom.", + { "kinoko_bend", "Bouncy mushroom. The model perpetually loops an animation that resembles pulling a rubber band and letting go. It appears on the minimap as a solid circle in non-racing modes.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_KCL | OBF_SCALE | OBF_ROTATE | OBF_FALLDOWN | OBF_OBJFLOW | OBF_SOLID | OBF_ROAD | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, {195,-1,-1}, "kinoko(B4K)", - { "Texturing: 0 = Light 1 = Dark", - 0, 0, 0, 0, 0, 0, 0 }}, + { "Texturing: nonzero values load the dark variant instead", + "[?] Maximum angle", + "[?] Time in 1/60s for a full cycle", + "[?] Cycle shift (controls where in the cycle to start)", + 0, 0, 0, 0 }}, /* 0x1f7 */ - { "VolcanoRock1", "Floating drivable rock (at Grumble Volcano in the lava), it moves like a cosine on the x-axis and the y-axis.", + { "VolcanoRock1", "Floating drivable rock (at Grumble Volcano in the lava). It moves like a cosine on the X-axis and the Y-axis.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_KCL | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -2115,11 +2124,11 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Time to go from x1 to x2 and back in 1/60 seconds", "Max X movement in both directions", "Offsets starting X and Y position within the specified movement in 1/60 seconds", - "Time of one period on the y-axis in 1/60 secons", - "The amplitude of the cosine on the y-axis", + "Time of one period on the Y-axis in 1/60 seconds", + "The amplitude of the cosine on the Y-axis", 0, 0 }}, /* 0x1f8 */ - { "bulldozer_left", "The moving bulldozer from Toad's Factory.", + { "bulldozer_left", "Moving bulldozer from Toad's Factory. Regardless of Y-rotation, it moves eastward from its current position.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_KCL | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -2143,12 +2152,12 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Time of standing still", 0, 0, 0 }}, /* 0x1fa */ - { "kinoko_nm", "Green mushroom.", + { "kinoko_nm", "Green mushroom. It appears on the minimap as a solid circle in non-racing modes.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_KCL | OBF_SCALE | OBF_ROTATE | OBF_FALLDOWN | OBF_OBJFLOW | OBF_SOLID | OBF_ROAD | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, {195,-1,-1}, "kinoko(B4K)", - { "Texturing: 0 = Light 1 = Dark", + { "Texturing: nonzero values load the dark variant instead", 0, 0, 0, 0, 0, 0, 0 }}, /* 0x1fb */ { "Crane", "Crane platform Toad's Factory. Slot 1.4 enables its SFX.", @@ -2157,8 +2166,8 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = &settings_format_uuuu, &settings_format_uuuu, {13,-1,-1}, "Crane(BK)", { 0, - "Movement Distance", - "Movement Time", + "Amplitude of the motion (in game units)", + "Period of the motion (in 1/60s)", "Time before starting", 0, 0, 0, 0 }}, /* 0x1fc */ @@ -2219,7 +2228,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {-1,-1,-1}, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x202 */ - { "DKturibashiGCc", "Wooden, Swaying bridge from GCN DK Mountain. The object collision is not affected by rotation, so all rotation values need to be 0 in order to work properly.", + { "DKturibashiGCc", "Wooden, Swaying bridge from GCN DK Mountain. The object collision is not affected by rotation or scale, so all rotation values need to be 0 and scale 1 in order to work properly.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_SCALE | OBF_ROTATE | OBF_FALLDOWN | OBF_OBJFLOW | OBF_SOLID | OBF_ROAD | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -2240,7 +2249,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {143,-1,-1}, "aurora(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x205 */ - { "venice_saku", "Fence gate from Delfino Pier.", + { "venice_saku", "Fence gate from Delfino Pier. Using multiple of this object appears to cause all of them to rise simultaneously.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_KCL | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_ARENA, obj_charact_s_a, &settings_format_uuuu, &settings_format_uuuu, @@ -2250,7 +2259,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Speed that it moves up", 0, 0, 0, 0, 0 }}, /* 0x206 */ - { "casino_roulette", "The rotating parts of Chain Chomp Wheel; when used with KCL flag 0x1D, the road slowly around the object counterclockwise. X, Y and Z positions and rotations need to be 0 and scales need to be 1 in order to work properly. Arena slot 1.4 enables functionality that causes players to additionally rotate the direction they are facing on both the object by itself and on KCL flag 0x1D.", + { "casino_roulette", "The rotating parts of Chain Chomp Wheel; when used with KCL flag 0x1D, the road slowly rotates around the object counterclockwise. X, Y and Z positions and rotations need to be 0 and scales need to be 1 in order to work properly. Additionally, the file must have a texture animation named \"dushBoard\" (without quotations), or else the game will crash. Arena slot 1.4 enables functionality that causes players to additionally rotate the direction they are facing on both the object by itself and on KCL flag 0x1D. For more information: Moving Terrain", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_KCL | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_ARENA, obj_charact_s_a, &settings_format_uuuu, &settings_format_uuuu, @@ -2352,20 +2361,20 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = &settings_format_uuuu, &settings_format_uuuu, {117,-1,-1}, "RM_ring1(B8K)", { "Ring ID; 1 = Outer ring 2 = ring in the middle 3 = Inner ring", - "Time after course start when the ring starts shaking (seconds)", + "Time after course start when the ring starts shaking (seconds) (s2=0 means the ring will never fall)", "Time that ring shakes (seconds)", "[?] Delay after ring shakes before falling down (1/60 seconds)", 0, 0, 0, 0 }}, /* 0x212 */ - { "FlamePole_v", "Fire geyser without a base.", + { "FlamePole_v", "Fire geyser without a base. It rises like a parabolic curve for 1 second, stays up for s1 - s4 - 490 frames, drops in a linear line for 3 seconds and waits for the time specified in s4 before restarting. Before rising, the geyser has an additional state of 50 frames whereby it is enabled but not rising yet, for this reason it is recommended to not put geysers above track section.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_EFFECT | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, {51,-1,-1}, "FlamePole_v(BE)", - { "Time outside the lava, K reference value is 500 (1F4 in hex): X < K → Stays outside the lava for 5 seconds X ≥ K → Stays outside the lava for X/100 seconds", + { "Total cycle length, affects time between rising and dropping only.", "Start delay in 1/60 seconds; it starts 3 seconds before the \"GO!\"", - "Scale factor; values up to 3 shrink the size, 4 and above grow the size", - "Cycle time in 1/60 seconds + 8.25 seconds", + "The dropping height of the pillar / 384", + "Idling time - 200 (1/60 seconds)", 0, 0, 0, 0 }}, /* 0x213 */ { "M_obj_s_jump", "Ramp used on competitions; object not used in any track.", @@ -2407,7 +2416,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "S1 activator and S2 conditioner: 0 = S1 Deactivated 1 = S1 Activated", 0, 0, 0, 0, 0 }}, /* 0x217 */ - { "Mdush", "Small jump ramp from Mario Circuit and Moo Moo Meadows.", + { "Mdush", "Small jump ramp from Mario Circuit.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_KCL | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -2510,21 +2519,21 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {26,-1,-1}, "DonkyCannonGC(BED)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x25a */ - { "BeltEasy", "Second set of belts from Toad's Factory.", + { "BeltEasy", "Second set of belts from Toad's Factory. For more information: Moving Terrain", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, {5,-1,-1}, "BeltEasy(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x25b */ - { "BeltCrossing", "First set of belts from Toad's Factory.", + { "BeltCrossing", "First set of belts from Toad's Factory. For more information: Moving Terrain", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, {2,-1,-1}, "BeltCrossing(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x25c */ - { "BeltCurveA", "Third set of belts from Toad's Factory. Object is not scalable.", + { "BeltCurveA", "Third set of belts from Toad's Factory. Object is not scalable. For more information: Moving Terrain", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, @@ -2541,7 +2550,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {4,-1,-1}, "BeltCurveB", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x25e */ - { "escalator", "Coconut Mall escalator.", + { "escalator", "Coconut Mall escalator. For more information: Moving Terrain", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_KCL | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -2561,7 +2570,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {27,-1,-1}, "DonkyCannon_wii(BED)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x260 */ - { "escalator_group", "2 Time Escalators from Coconut Mall. One of the two escalators uses the given speed, the other uses multiplies the speed with -1 (negative speed), so they always run in opposite directions.", + { "escalator_group", "2 Time Escalators from Coconut Mall. One of the two escalators uses the given speed, the other uses a multiplied speed of -1 (negative speed), so they always run in opposite directions. For more information: Moving Terrain", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_KCL | OBF_OBJFLOW | OBF_SOLID | OBF_NO_ROUTE | OBF_FNAME | OBF_MULTI_FNAME | OBF_M_TRACK, obj_charact_s_t, &settings_format_uuuu, &settings_format_uuuu, @@ -2833,7 +2842,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, {57,-1,-1}, "Flash_W(E)", - { "Unknown", + { "0 = flashWaluigi_A 1 = flashWaluigi_B 2 = flashWaluigi_C", 0, 0, 0, 0, 0, 0, 0 }}, /* 0x2d3 */ { "Flash_M", "Audience camera flashes on N64 Mario Raceway. Active whenever the audience ambience is playing.", @@ -2848,7 +2857,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = obj_charact_a, &settings_format_uuuu, &settings_format_uuuu, {56,-1,-1}, "Flash_S(E)", - { "Unknown", + { "0 = flashSkate_A 1 = flashSkate_B", 0, 0, 0, 0, 0, 0, 0 }}, /* 0x2d5 */ { "MiiSignNoko", "Koopa face sign from Koopa Cape.", @@ -2872,7 +2881,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {124,-1,-1}, "Spot64(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x2d8 */ - { "DemoEf", "Object not used in any track.", + { "DemoEf", "Fireworks used in the Mario Circuit winning demo.", OBF_OBJECT | OBF_UNIQUE | OBF_EFFECT | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_F_OTHER, obj_charact_o, &settings_format_uuuu, &settings_format_uuuu, @@ -2886,12 +2895,12 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {37,-1,-1}, "Fall_MH(E)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x2da */ - { "Fall_Y", "Part of the waterfall effects from Koopa Cape and DS Yoshi Falls.", + { "Fall_Y", "Breff animation of the waterfall effects from Koopa Cape and DS Yoshi Falls.", OBF_OBJECT | OBF_UNIQUE | OBF_EFFECT | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, {38,-1,-1}, "Fall_Y(E)", - { "0 = A, 1 = B or 2 = C breff animation", + { "0 = A 1 = B 2 = C", 0, 0, 0, 0, 0, 0, 0 }}, /* 0x2db */ { "DemoJugemu", "Lakitu model from the Mario Circuit winning demo.", @@ -3006,7 +3015,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {93,-1,-1}, "MiiObjD03(B)", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x2eb */ - { "mare_a", "Toad from GCN Peach Peach.", + { "mare_a", "Yellow Noki from GCN Peach Peach.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, @@ -3017,7 +3026,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = "Distance at which it loads the clapping chr0.", 0, 0, 0, 0 }}, /* 0x2ec */ - { "mare_b", "Toad from GCN Peach Peach.", + { "mare_b", "Green Noki from GCN Peach Peach.", OBF_OBJECT | OBF_UNIQUE | OBF_BRRES | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, @@ -3056,7 +3065,7 @@ const ObjectInfo_t ObjectInfo[N_KMP_GOBJ] = {83,-1,-1}, "M_obj_start", { 0, 0, 0, 0, 0, 0, 0, 0 }}, /* 0x2f1 */ - { "EnvKarehaUp", "Upward Leaf effect on screen from Maple Treeway; AREA type 0x01 activates this object.", + { "EnvKarehaUp", "Upward Leaf effect on screen from Maple Treeway; AREA type 0x01 activates this object if the first AREA setting is set to 1. Instead of surrounding the player with the particle effect, the object's position is used to create a region in which the effect will occur. This region is loosely 10000un eastward and 10000un above the object's position.", OBF_OBJECT | OBF_UNIQUE | OBF_EFFECT | OBF_OBJFLOW | OBF_NO_ROUTE | OBF_FNAME | OBF_M_TRACK, obj_charact_t, &settings_format_uuuu, &settings_format_uuuu, diff --git a/project/src/db-object.h b/project/src/db-object.h index 7055eb9..763df57 100644 --- a/project/src/db-object.h +++ b/project/src/db-object.h @@ -172,10 +172,10 @@ extern const ObjSpec_t ObjSpec[N_OBJ_SPEC+1]; /////////////////////////////////////////////////////////////////////////////// #define OBJ_FW_NAME 18 -#define OBJ_FW_INFO 897 +#define OBJ_FW_INFO 908 #define OBJ_FW_FNAME 46 #define OBJ_FW_CHAR 55 -#define OBJ_FW_SETTING 330 +#define OBJ_FW_SETTING 280 // diff --git a/project/src/lib-breff.c b/project/src/lib-breff.c index 8fe2a38..ca7e366 100644 --- a/project/src/lib-breff.c +++ b/project/src/lib-breff.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-breff.h b/project/src/lib-breff.h index bd82adc..6cec9ee 100644 --- a/project/src/lib-breff.h +++ b/project/src/lib-breff.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-brres.c b/project/src/lib-brres.c index 4bb1058..b441176 100644 --- a/project/src/lib-brres.c +++ b/project/src/lib-brres.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -2098,6 +2098,7 @@ void ListNameRef ( FILE *f, int indent, name_ref_t *nr, SortMode_t sort ) break; case SORT_OFFSET: + case SORT_SIZE: sort_func = sort_nr_by_offset; sort_info = "sorted by offset"; break; diff --git a/project/src/lib-brres.h b/project/src/lib-brres.h index f0ae424..d0f4e08 100644 --- a/project/src/lib-brres.h +++ b/project/src/lib-brres.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-bzip2.c b/project/src/lib-bzip2.c index 894463f..25a3668 100644 --- a/project/src/lib-bzip2.c +++ b/project/src/lib-bzip2.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-bzip2.h b/project/src/lib-bzip2.h index 4e2ea8c..290a0cb 100644 --- a/project/src/lib-bzip2.h +++ b/project/src/lib-bzip2.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-checksum.c b/project/src/lib-checksum.c index ed45e7a..b4f19ba 100644 --- a/project/src/lib-checksum.c +++ b/project/src/lib-checksum.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -533,7 +533,7 @@ void ScanSlotTranslation } - //--- standart text file + //--- standard text file if ( verbose > 1 ) printf("Scan translation%s[TEXT/%s]: %s\n", diff --git a/project/src/lib-checksum.h b/project/src/lib-checksum.h index 25f8786..2215f0b 100644 --- a/project/src/lib-checksum.h +++ b/project/src/lib-checksum.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-common.c b/project/src/lib-common.c index 1b7cffc..e5f301b 100644 --- a/project/src/lib-common.c +++ b/project/src/lib-common.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-common.h b/project/src/lib-common.h index 8ca2390..4137ab0 100644 --- a/project/src/lib-common.h +++ b/project/src/lib-common.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-ctcode.c b/project/src/lib-ctcode.c index c89dd38..4b3f0bb 100644 --- a/project/src/lib-ctcode.c +++ b/project/src/lib-ctcode.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -56,6 +56,20 @@ /////////////// helpers /////////////// /////////////////////////////////////////////////////////////////////////////// +uint NormalizeMusicID ( uint music_id ) +{ + if ( music_id < MKW_N_TRACKS ) + music_id = track_info[music_id].music_id; + else if ( music_id < MKW_N_TRACKS + MKW_N_ARENAS ) + music_id = arena_info[music_id-MKW_N_TRACKS].music_id; + + if ( MusicID2TrackId(music_id,music_id,-1) == -1 ) + music_id = track_info[0].music_id; + return music_id; +} + +/////////////////////////////////////////////////////////////////////////////// + int MusicID2TrackId ( uint music_id, int no_track, int not_found ) { if ( music_id >= MKW_MUSIC_MIN_ID && music_id <= MKW_MUSIC_MAX_ID ) @@ -362,8 +376,26 @@ ccp PrintMusicID ( uint mid, bool force_hex ) ccp PrintPropertyID ( uint tid, bool force_hex ) { - if ( tid < MKW_N_TRACKS && !force_hex ) - return track_info[tid].abbrev; + if (!force_hex) + { + if (IsMkwTrack(tid)) + return track_info[tid].abbrev; + if (IsMkwArena(tid)) + return arena_info[tid-MKW_ARENA_BEG].abbrev; + } + + const int bufsize = 8; + char *buf = GetCircBuf(bufsize); + snprintf(buf,bufsize,"0x%02x",tid); + return buf; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintArenaSlot ( uint tid, bool force_hex ) +{ + if ( !force_hex && IsMkwArena(tid) ) + return PrintCircBuf("A%u",arena_info[tid-MKW_ARENA_BEG].def_slot); const int bufsize = 8; char *buf = GetCircBuf(bufsize); @@ -1948,7 +1980,101 @@ static enumError ScanRTL_Track /////////////////////////////////////////////////////////////////////////////// -static enumError ScanRacingTrackList ( ctcode_t *ctcode, ScanInfo_t * si ) +enumError ScanSetupArena ( ctcode_arena_t *ca, ScanInfo_t * si ) +{ + DASSERT(ca); + DASSERT(si); + + enumError max_err = ERR_OK; + for(;;) + { + char ch = NextCharSI(si,true); + if ( !ch || ch == '[' ) + break; + + ScanFile_t *sf = si->cur_file; + DASSERT(sf); + ccp ptr0 = sf->ptr; + + uint slot; + enumError err = ScanUIntValueSI(si,&slot); + if (err) + return err; + + if ( slot < MKW_ARENA_BEG || slot >= MKW_ARENA_END ) + { + ccp eol = FindNextLineFeedSI(si,true); + if ( si->no_warn <= 0 ) + { + ERROR0(ERR_WARNING, + "Invalid arena slot #%d [%s @%u]: %.*s\n", + slot, sf->name, sf->line, (int)(eol - ptr0), ptr0 ); + } + sf->ptr = eol; + continue; + } + + + //--- property id + + if ( NextCharSI(si,false) == ';' ) + sf->ptr++; + + ptr0 = sf->ptr; + int property_id; + err = ScanIntValueSI(si,&property_id); + if (err) + return err; + + if ( property_id > 0 && ( property_id < MKW_ARENA_BEG || property_id >= MKW_ARENA_END )) + { + ccp eol = FindNextLineFeedSI(si,true); + if ( si->no_warn <= 0 ) + { + ERROR0(ERR_WARNING, + "Invalid arena slot #%d [%s @%u]: %.*s\n", + property_id, sf->name, sf->line, (int)(eol - ptr0), ptr0 ); + } + sf->ptr = eol; + continue; + } + + + //--- music id + + if ( NextCharSI(si,false) == ';' ) + sf->ptr++; + + int music_id = -1; + if (NextCharSI(si,false)) + { + err = ScanIntValueSI(si,&music_id); + if (err) + return err; + } + + + //--- store data id + + slot -= MKW_ARENA_BEG; + if ( property_id >= 0 ) + ca->prop[slot] = property_id; + if ( music_id >= 0 ) + ca->music[slot] = NormalizeMusicID(music_id); + + CheckEolSI(si); + if ( max_err < err ) + max_err = err; + } + + //HexDump16(stdout,0,0,ca->prop,sizeof(ca->prop)); + //HexDump16(stdout,0,0,ca->music,sizeof(ca->music)); + return max_err; +} + +/////////////////////////////////////////////////////////////////////////////// + +static enumError ScanTrackList ( ctcode_t *ctcode, ScanInfo_t * si ) { DASSERT(ctcode); DASSERT(si); @@ -2015,6 +2141,12 @@ static enumError ScanRacingTrackList ( ctcode_t *ctcode, ScanInfo_t * si ) err = ScanRTL_Track(ctcode,si,true,false); break; + case 'b': + case 'B': + sf->ptr++; + err = ScanRTL_Track(ctcode,si,true,true); + break; + default: { ccp eol = FindNextLineFeedSI(si,true); @@ -2035,11 +2167,99 @@ static enumError ScanRacingTrackList ( ctcode_t *ctcode, ScanInfo_t * si ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// ScanTextArena() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +enumError ScanTextArena +( + ctcode_arena_t *ca, // valid data structure + ccp fname, // NULL or file name for error messages + const void *data, // data to scan + uint data_size // size of 'data' +) +{ + DASSERT(ca); + + const uint CTCODE_VERSION = 1; + + //--- setup parser + + enum { SECT_SETUP_ARENA, N_SECT }; + const KeywordTab_t sect_names[] = + { + { SECT_SETUP_ARENA, "SETUP-ARENA", 0, 0 }, + { 0,0,0,0 } + }; + + ScanInfo_t si; + InitializeSI(&si,data,data_size,fname,CTCODE_VERSION); + si.predef = SetupVarsCTCODE(); + + + //--- main loop + + enumError max_err = ERR_OK; + + for(;;) + { + char ch = NextCharSI(&si,true); + if (!ch) + break; + + if ( ch != '[' ) + { + NextLineSI(&si,true,false); + continue; + } + ResetLocalVarsSI(&si,CTCODE_VERSION); + + si.cur_file->ptr++; + char name[20]; + ScanNameSI(&si,name,sizeof(name),true,true,0); + + int abbrev_count; + const KeywordTab_t *cmd = ScanKeyword(&abbrev_count,name,sect_names); + if ( !cmd || abbrev_count ) + continue; + NextLineSI(&si,false,false); + PRINT("--> %-6s #%-4u |%.3s|\n",cmd->name1,si.cur_file->line,si.cur_file->ptr); + + if ( cmd->id < 0 || cmd->id > N_SECT ) + continue; + + enumError err = ERR_OK; + switch (cmd->id) + { + case SECT_SETUP_ARENA: + PRINT("SCAN [SETUP-ARENA]\n"); + err = ScanSetupArena(ca,&si); + break; + + default: + // ignore all other section without any warnings + break; + } + + if ( max_err < err ) + max_err = err; + } + + CheckLevelSI(&si); + if ( max_err < ERR_WARNING && si.total_err ) + max_err = ERR_WARNING; + PRINT("ERR(ScanTextCTCODE) = %u (errcount=%u)\n", max_err, si.total_err ); + ResetSI(&si); + + return max_err; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// ScanTextCTCODE() /////////////// /////////////////////////////////////////////////////////////////////////////// static enumError ScanSetup ( ctcode_t *ctcode, ScanInfo_t * si ); -static enumError ScanRacingTrackList ( ctcode_t *ctcode, ScanInfo_t * si ); +static enumError ScanTrackList ( ctcode_t *ctcode, ScanInfo_t * si ); //----------------------------------------------------------------------------- @@ -2072,11 +2292,14 @@ enumError ScanTextCTCODE //--- setup parser - enum { SECT_SETUP, SECT_RACING_TRACK_LIST, N_SECT }; + enum { SECT_SETUP, SECT_SETUP_ARENA, + SECT_TRACK_LIST, SECT_RACING_TRACK_LIST, N_SECT }; const KeywordTab_t sect_names[] = { { SECT_SETUP, "SETUP", 0, 0 }, - { SECT_RACING_TRACK_LIST, "RACING-TRACK-LIST", 0, 0 }, + { SECT_SETUP_ARENA, "SETUP-ARENA", 0, 0 }, + { SECT_TRACK_LIST, "TRACK-LIST", 0, 0 }, + { SECT_RACING_TRACK_LIST, "RACING-TRACK-LIST", 0, 0 }, // [[deprecated]] 2021-08 { 0,0,0,0 } }; @@ -2124,9 +2347,19 @@ enumError ScanTextCTCODE err = ScanSetup(ctcode,&si); break; + case SECT_SETUP_ARENA: + PRINT("SCAN [SETUP-ARENA]\n"); + err = ScanSetupArena(&ctcode->arena,&si); + break; + + case SECT_TRACK_LIST: + PRINT("SCAN [TRACK-LIST]\n"); + err = ScanTrackList(ctcode,&si); + break; + case SECT_RACING_TRACK_LIST: PRINT("SCAN [RACING-TRACK-LIST]\n"); - err = ScanRacingTrackList(ctcode,&si); + err = ScanTrackList(ctcode,&si); break; default: @@ -2661,6 +2894,15 @@ enumError ScanLEBinCTCODE } + //--- copy arena properties + + for ( int a = 0; a < MKW_N_ARENAS; a++ ) + { + ctcode->arena.prop[a] = ana.property[a+MKW_ARENA_BEG]; + ctcode->arena.music[a] = ana.music[a+MKW_ARENA_BEG]; + } + + //--- copy lecode parameter if (!ctcode->lpar) @@ -2962,10 +3204,35 @@ enumError SaveTextCTCODE ctcode->n_unused_cups ); + //--- print arena setup + + if (omode.lecode) + { + fputs(section_sep,F.f); + fputs(text_ctcode_setup_arena_cr,F.f); + + for ( int i = 0; i < MKW_N_ARENAS; i++ ) + { + if ( i == MKW_N_ARENAS/2 ) + fputs("\r\n",F.f); + + const int a = arena_pos[i]; + const TrackInfo_t *ai = arena_info+a; + const int prop = ctcode->arena.prop[a] ? ctcode->arena.prop[a] : ai->track_id; + const int music = ctcode->arena.music[a] ? ctcode->arena.music[a] : ai->music_id; + fprintf(F.f, "%s %s %s\r\n", + PrintArenaSlot(ai->track_id,false), + PrintArenaSlot(prop,false), + music == ai->music_id ? "" : PrintMusicID(music,false) ); + } + } + + //--- print track list if ( omode.mode & 1 && ctcode->used_tracks ) { +// [[2do]] [TRACK-LIST] fprintf(F.f,"%s[RACING-TRACK-LIST]\r\n%s", section_sep, omode.syntax diff --git a/project/src/lib-ctcode.h b/project/src/lib-ctcode.h index f444e8c..9f6bf5b 100644 --- a/project/src/lib-ctcode.h +++ b/project/src/lib-ctcode.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -40,6 +40,7 @@ #include "lib-std.h" #include "lib-xbmg.h" +#include "lib-mkw.h" // /////////////////////////////////////////////////////////////////////////////// @@ -221,6 +222,19 @@ ctcode_cupref_t; // /////////////////////////////////////////////////////////////////////////////// +/////////////// struct ctcode_arena_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[ctcode_arena_t]] + +typedef struct ctcode_arena_t +{ + le_property_t prop[MKW_N_ARENAS]; // only valid if !=0 + le_music_t music[MKW_N_ARENAS]; // only valid if le_prop[]!=0 +} +ctcode_arena_t; + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// struct ctcode_t /////////////// /////////////////////////////////////////////////////////////////////////////// // [[ctcode_t]] @@ -252,6 +266,11 @@ typedef struct ctcode_t uint n_unused_cups; // number of unused cups + //--- arenas setup fir LE-CODE + + ctcode_arena_t arena; // data of section [SETUP-ARENA] + + //--- track data ctcode_crs1_head_t *crs; // NULL or data pointer to CRS1 data @@ -291,7 +310,7 @@ typedef struct ctcode_t bool use_lecode; // true: enable le-code support bool use_le_flags; // true: le_flags enabled struct le_lpar_t *lpar; // NULL or LPAR parameters - + //--- misc @@ -372,9 +391,23 @@ void PrepareExportCTCODE ( ctcode_t * ctcode ); void PatchNamesCTCODE ( ctcode_t * ctcode ); void PrepareSaveCTCODE ( ctcode_t * ctcode ); -int MusicID2TrackId ( uint music_id, int no_track, int not_found ); -ccp PrintMusicID ( uint mid, bool force_hex ); -ccp PrintPropertyID ( uint tid, bool force_hex ); +uint NormalizeMusicID ( uint music_id ); +int MusicID2TrackId ( uint music_id, int no_track, int not_found ); +ccp PrintMusicID ( uint mid, bool force_hex ); +ccp PrintPropertyID ( uint tid, bool force_hex ); +ccp PrintArenaSlot ( uint tid, bool force_hex ); + +/////////////////////////////////////////////////////////////////////////////// + +enumError ScanSetupArena ( ctcode_arena_t *ca, ScanInfo_t * si ); + +enumError ScanTextArena +( + ctcode_arena_t *ca, // valid data structure + ccp fname, // NULL or file name for error messages + const void *data, // data to scan + uint data_size // size of 'data' +); /////////////////////////////////////////////////////////////////////////////// diff --git a/project/src/lib-ctdata.c b/project/src/lib-ctdata.c index f39f10f..1517773 100644 --- a/project/src/lib-ctdata.c +++ b/project/src/lib-ctdata.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-file.c b/project/src/lib-file.c index fe7ab02..18a5bd1 100644 --- a/project/src/lib-file.c +++ b/project/src/lib-file.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -104,6 +104,19 @@ void SetSource ( ccp source ) /////////////////////////////////////////////////////////////////////////////// +void SetReference ( ccp source ) +{ + #ifdef __CYGWIN__ + opt_reference = IsWindowsDriveSpec(source) + ? AllocNormalizedFilenameCygwin(source,false) + : source; + #else + opt_reference = source; + #endif +} + +/////////////////////////////////////////////////////////////////////////////// + void SetDest ( ccp dest, bool mkdir ) { #ifdef __CYGWIN__ @@ -742,7 +755,6 @@ file_format_t GetByMagicFF case BMG_MAGIC8_NUM: return FF_BMG; case PNG_MAGIC8_NUM: return FF_PNG; case GCT_MAGIC8_NUM: return FF_GCT; - case LE_LPAR_MAGIC_NUM: return FF_LPAR; case ADDR_PORT_MAGIC_NUM: return FF_PORTDB; //--- see below for BOM support @@ -754,6 +766,7 @@ file_format_t GetByMagicFF case GH_IOBJ_TEXT_MAGIC8_NUM: return FF_GH_IOBJ_TXT; case GH_KART_TEXT_MAGIC8_NUM: return FF_GH_KART_TXT; case GH_KOBJ_TEXT_MAGIC8_NUM: return FF_GH_KOBJ_TXT; + case LE_LPAR_MAGIC_NUM: return FF_LPAR; } } @@ -785,10 +798,6 @@ file_format_t GetByMagicFF case KMG_MAGIC_NUM: return FF_KMG; case KRT_MAGIC_NUM: return FF_KRT; case KRM_MAGIC_NUM: return FF_KRM; -// [[obj-type+]] 3x -// case OBJFLOW_MAGIC_NUM: return FF_OBJFLOW; -// case GH_ITEM_MAGIC_NUM: return FF_GH_ITEM; -// case GH_KART_MAGIC_NUM: return FF_GH_KART; case U8_MAGIC_NUM: return FF_U8; case WU8_MAGIC_NUM: return FF_WU8; @@ -860,12 +869,13 @@ file_format_t GetByMagicFF { case CT_TEXT_MAGIC8_NUM: return FF_CT_TEXT; case DISTRIB_MAGIC8_NUM: return FF_DISTRIB; + case ITEMSLT_TEXT_MAGIC_NUM: return FF_ITEMSLT_TXT; case OBJFLOW_TEXT_MAGIC8_NUM: return FF_OBJFLOW_TXT; -// [[obj-type+]] case GH_ITEM_TEXT_MAGIC8_NUM: return FF_GH_ITEM_TXT; case GH_IOBJ_TEXT_MAGIC8_NUM: return FF_GH_IOBJ_TXT; case GH_KART_TEXT_MAGIC8_NUM: return FF_GH_KART_TXT; case GH_KOBJ_TEXT_MAGIC8_NUM: return FF_GH_KOBJ_TXT; + case LE_LPAR_MAGIC_NUM: return FF_LPAR; } } diff --git a/project/src/lib-geohit.c b/project/src/lib-geohit.c index 6acf70c..1d5a357 100644 --- a/project/src/lib-geohit.c +++ b/project/src/lib-geohit.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-image.h b/project/src/lib-image.h index 40d6012..b00ec9d 100644 --- a/project/src/lib-image.h +++ b/project/src/lib-image.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-image1.c b/project/src/lib-image1.c index 054fb6b..571df55 100644 --- a/project/src/lib-image1.c +++ b/project/src/lib-image1.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-image2.c b/project/src/lib-image2.c index a91f9e3..0bcb22b 100644 --- a/project/src/lib-image2.c +++ b/project/src/lib-image2.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-image3.c b/project/src/lib-image3.c index 916c379..a242106 100644 --- a/project/src/lib-image3.c +++ b/project/src/lib-image3.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-itemslot.c b/project/src/lib-itemslot.c index d2716e7..8e32690 100644 --- a/project/src/lib-itemslot.c +++ b/project/src/lib-itemslot.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-kcl-image.c b/project/src/lib-kcl-image.c index fcb2f9e..ad6fd22 100644 --- a/project/src/lib-kcl-image.c +++ b/project/src/lib-kcl-image.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-kcl.c b/project/src/lib-kcl.c index 6c4de32..4a25173 100644 --- a/project/src/lib-kcl.c +++ b/project/src/lib-kcl.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -148,6 +148,7 @@ static const KeywordTab_t opt_kcl_tab[] = { KCLMD_CONV_FACEUP, "CONV-FACEUP", "CONVFACEUP", 0 }, { KCLMD_WEAK_WALLS, "WEAK-WALLS", "WEAKWALLS", 0 }, + { KCLMD_CLR_VISUAL, "CLR-VISUAL", "CLRVISUAL", 0 }, { KCLMD_NEW, "NEW", 0, 0 }, { KCLMD_SORT, "SORT", 0, 0 }, @@ -568,41 +569,88 @@ uint n_user_color = 0; /////////////////////////////////////////////////////////////////////////////// -void InitializeKCL ( kcl_t * kcl ) +kcl_flag_t * CreatePatchFlagKCL +( + // returns NULL or N_KCL_FLAG elements + + kcl_mode_t kcl_mode, // relevant: KCLMD_CLR_VISUAL | KCLMD_WEAK_WALLS + SlotMode_t slot_mode, // relevant: SLOTMD_ICE_TO_WATER | SLOTMD_WATER_TO_ICE + bool null_on_orig // TRUE: return NULL on no flag modifications +) { - //--- one time setup + kcl_flag_t *flag = MALLOC( N_KCL_FLAG * sizeof(*flag) ); + for ( int i = 0; i < N_KCL_FLAG; i++ ) + flag[i] = i; - static int done = 0; - if (!done) + if ( opt_slot & (SLOTMD_ICE_TO_WATER|SLOTMD_WATER_TO_ICE) ) { - ++done; - if ( opt_slot & (SLOTMD_ICE_TO_WATER|SLOTMD_WATER_TO_ICE) ) - { - SetupPatchKclFlag(); - const u16 search = opt_slot & SLOTMD_ICE_TO_WATER ? 0x0070 : 0x0030; - - uint i; - for ( i = 0; i < N_KCL_FLAG; i++ ) - if ( ( patch_kcl_flag[i] & 0x00ff ) == search ) - patch_kcl_flag[i] = patch_kcl_flag[i] ^ 0x0040; + const u16 search = opt_slot & SLOTMD_ICE_TO_WATER ? 0x0070 : 0x0030; + for ( int i = 0; i < N_KCL_FLAG; i++ ) + if ( ( flag[i] & 0x00ff ) == search ) + flag[i] = flag[i] ^ 0x0040; + } - PurgePatchKclFlag(); + if ( kcl_mode & KCLMD_WEAK_WALLS ) + { + for ( int i = 0; i < N_KCL_FLAG; i++ ) + { + const int type = GET_KCL_TYPE(i); + if ( type >= 0 && kcl_type[type].attrib & KCLT_C_WALL ) + flag[i] |= 0x8000; } + } - if ( KCL_MODE & KCLMD_WEAK_WALLS ) + if ( kcl_mode & KCLMD_CLR_VISUAL ) + { + static u16 tab[32] = { - SetupPatchKclFlag(); - uint i; - for ( i = 0; i < N_KCL_FLAG; i++ ) + 0xe01f,0xe01f,0xe01f,0xe01f, 0xe01f,0xe01f,0xe0ff,0xe0ff, + 0xe0ff,0xe0ff,0xe01f,0xe0ff, 0x601f,0x60ff,0x60ff,0x601f, + 0xe01f,0xe0ff,0xffff,0xe0ff, 0xe01f,0xe0ff,0xe01f,0xe01f, + 0x001f,0xffff,0xe01f,0xffff, 0xe0ff,0xe0ff,0x601f,0x60ff, + }; + + for ( int i = 0; i < N_KCL_FLAG; i++ ) + flag[i] &= tab[i&31]; + } + + if (null_on_orig) + { + bool have_patch = false; + for ( int i = 0; i < N_KCL_FLAG; i++ ) + if ( flag[i] != i ) { - const int type = GET_KCL_TYPE(i); - if ( type >= 0 && kcl_type[type].attrib & KCLT_C_WALL ) - patch_kcl_flag[i] |= 0x8000; + have_patch = true; + break; } - PurgePatchKclFlag(); + if (!have_patch) + { + FREE(flag); + flag = 0; } } + return flag; +} + +/////////////////////////////////////////////////////////////////////////////// + +void InitializeKCL ( kcl_t * kcl ) +{ + //--- one time setup + + static int done = 0; + if (!done++) + { + SetupPatchKclFlag(); + kcl_flag_t *flag = CreatePatchFlagKCL(KCL_MODE,opt_slot,false); + DASSERT(flag); + memcpy(patch_kcl_flag,flag,sizeof(*patch_kcl_flag)*N_KCL_FLAG); + FREE(flag); + PurgePatchKclFlag(); + } + + //--- object setup DASSERT(kcl); @@ -6767,7 +6815,7 @@ bool TransformKCL /////////////// Patch KCL /////////////// /////////////////////////////////////////////////////////////////////////////// -u16 *patch_kcl_flag = 0; // NULL or 'N_KCL_FLAG' elements +kcl_flag_t *patch_kcl_flag = 0; // NULL or 'N_KCL_FLAG' elements /////////////////////////////////////////////////////////////////////////////// @@ -6810,8 +6858,7 @@ void ResetPatchKclFlag() patch_kcl_flag = MALLOC( N_KCL_FLAG * sizeof(*patch_kcl_flag) ); } - uint i; - for ( i = 0; i < N_KCL_FLAG; i++ ) + for ( int i = 0; i < N_KCL_FLAG; i++ ) patch_kcl_flag[i] = i; } @@ -7615,6 +7662,9 @@ int CheckKCL DASSERT(kcl); PRINT("CheckKCL(%d)\n",mode); + if ( disable_checks > 0 ) + return 0; + //--- setup diff --git a/project/src/lib-kcl.h b/project/src/lib-kcl.h index 6deb16a..19444f2 100644 --- a/project/src/lib-kcl.h +++ b/project/src/lib-kcl.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -116,6 +116,7 @@ __attribute__ ((packed)) kcl_head_t; /////////////////////////////////////////////////////////////////////////////// /////////////// kcl_triangle_t /////////////// /////////////////////////////////////////////////////////////////////////////// +// [[kcl_triangle_t]] typedef struct kcl_triangle_t { @@ -319,12 +320,14 @@ typedef enum kcl_mode_t KCLMD_CONV_FACEUP = 1ull<<34, // convert face up walls to road KCLMD_WEAK_WALLS = 1ull<<35, // OR 0x8000 to KCL flags of walls - KCLMD_NEW = 1ull<<36, // create a new KCL file even if nothing changed - KCLMD_SORT = 1ull<<37, // sort triangles + KCLMD_CLR_VISUAL = 1ull<<36, // clear effect bits + KCLMD_NEW = 1ull<<37, // create a new KCL file even if nothing changed + KCLMD_SORT = 1ull<<38, // sort triangles KCLMD_M_PATCH = KCLMD_M_DROP | KCLMD_M_RM | KCLMD_CONV_FACEUP | KCLMD_WEAK_WALLS + | KCLMD_CLR_VISUAL | KCLMD_NEW | KCLMD_SORT, @@ -380,7 +383,7 @@ typedef enum kcl_mode_t | KCLMD_TEST, KCLMD_M_PRINT = KCLMD_M_ALL // all relevant bits for obj output - % ~KCLMD_ADD_ROAD + & ~KCLMD_ADD_ROAD & ~KCLMD_IN_SWAP & ~KCLMD_AUTO & ~KCLMD_M_HEX @@ -615,6 +618,16 @@ bool DropSortHelper bool sort // true: sort triangles ); +typedef u16 kcl_flag_t; +kcl_flag_t * CreatePatchFlagKCL +( + // returns NULL or N_KCL_FLAG elements + + kcl_mode_t kcl_mode, // relevant: KCLMD_CLR_VISUAL | KCLMD_WEAK_WALLS + SlotMode_t slot_mode, // relevant: SLOTMD_ICE_TO_WATER | SLOTMD_WATER_TO_ICE + bool null_on_orig // TRUE: return NULL on no flag modifications +); + bool KCL_ACTION_LOG ( const char * format, ... ) __attribute__ ((__format__(__printf__,1,2))); @@ -1096,7 +1109,7 @@ uint GetExportFlagKCL ( uint kcl_flag ); extern int have_kcl_patch_count; extern StringField_t kcl_script_list; -extern u16 *patch_kcl_flag; // NULL or 'N_KCL_FLAG' elements +extern kcl_flag_t *patch_kcl_flag; // NULL or 'N_KCL_FLAG' elements //----------------------------------------------------------------------------- diff --git a/project/src/lib-kmp-diff.c b/project/src/lib-kmp-diff.c index 35774f9..4a0c86d 100644 --- a/project/src/lib-kmp-diff.c +++ b/project/src/lib-kmp-diff.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -207,7 +207,11 @@ static void print_ph else printf("%4u",*d1); } - putchar('\n'); + + printf(" : %s0x%02x %s0x%02x%s\n", + p1->setting[0] == p2->setting[0] ? ok : warn, p1->setting[0], + p1->setting[1] == p2->setting[1] ? ok : warn, p1->setting[1], + colout->reset ); } else { @@ -225,7 +229,8 @@ static void print_ph else printf("%4u",*d1); } - putchar('\n'); + + printf(" : 0x%02x 0x%02x\n", p1->setting[0], p1->setting[1] ); } } @@ -254,7 +259,10 @@ static sort_ph_t * print_ph_single ( const section_info_t *si, static int diff_ph ( const sort_ph_t *e1, const sort_ph_t *e2 ) { - if (!memcmp(&e1->data,&e2->data,sizeof(e1->data))) + uint size = sizeof(e1->data); + if ( opt_battle_mode <= OFFON_OFF ) + size -= sizeof(e1->data.setting); + if (!memcmp(&e1->data,&e2->data,size)) return 0; uint count = ( e1->data.pt_start != e2->data.pt_start ) @@ -947,7 +955,7 @@ static void print_area printf( "%c %5u %5u %11.3f %11.3f %11.3f %#6x %#6x\n" "%c %5u %5u %11.3f %11.3f %11.3f %6s %6s %#6x\n" "%c %24.3f %11.3f %11.3f\n", - mode, + mode, e1->mode, e1->type, e1->position[0], e1->position[1], e1->position[2], e1->setting[0], e1->setting[1], diff --git a/project/src/lib-kmp-draw.c b/project/src/lib-kmp-draw.c index 23f573b..b7a8106 100644 --- a/project/src/lib-kmp-draw.c +++ b/project/src/lib-kmp-draw.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -699,7 +699,7 @@ void AddRoutes2KCL ( DrawKCL_t * dk, // pointer to initalized object uint sect_pt, // KMP section - uint color_std // standart color index + uint color_std // standard color index ) { DASSERT(dk); diff --git a/project/src/lib-kmp-pflags.c b/project/src/lib-kmp-pflags.c index 9e3e674..d6d84da 100644 --- a/project/src/lib-kmp-pflags.c +++ b/project/src/lib-kmp-pflags.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -863,9 +863,9 @@ void AnalyseGobj ( kmp_ana_gobj_t *ag, const kmp_t *kmp ) continue; ag->n_object++; - info->obj_id = relevant_id; - info->type = KGTY_OBJECT; - info->status |= KGST_USED; + info->obj_id = relevant_id; + info->type = KGTY_OBJECT; + info->status |= KGST_USED; if ( gobj->obj_id < GOBJ_M_OBJECT ) { @@ -1844,7 +1844,7 @@ static uint DiffXPF ( xpf_mode1_info_t *l1, xpf_mode1_info_t *l2, int loop ) } } - eval += 999 - 3*abs( e1->index - e2->index ); + eval += 999 - 3*abs( e1->index - e2->index ); if ( e1->eval < eval || e1->eval == eval && e1->diff_sum > diff_sum ) { diff --git a/project/src/lib-kmp-text.c b/project/src/lib-kmp-text.c index 507cbc0..1e83f41 100644 --- a/project/src/lib-kmp-text.c +++ b/project/src/lib-kmp-text.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -1393,14 +1393,26 @@ static enumError GroupPrevGL DASSERT(gl); DASSERT(si); - if ( !gl->used) + if (!gl->used) { GotoEolSI(si); return ERR_OK; } SkipCharSI(si,':'); - kmp_group_t *grp = gl->group + gl->used - 1; + const int idx = gl->used - 1; + kmp_group_t *grp = gl->group + idx; + grp->have_prev_cmd = true; + + #if 0 // [[auto-prev]] + if ( idx < KMP_MAX_GROUP ) + { + kmp_ph_t *ph = grp->ph; + if (ph) + ph->gopt[idx].have_prev_cmd = true; + } + #endif + ScanGroupNames(gl,grp->prev,si); //HEXDUMP16(0,0,grp->prev,sizeof(grp->prev)); return CheckEolSI(si); @@ -1618,7 +1630,7 @@ static enumError AddGroupGL const bool split_group = !strcmp(name,"$SPLIT"); if (split_group) { - if ( gl->ph && gl->ph->ac_mode != KMP_AC_PREV ) + if ( gl->ph && gl->ph->ac_mode != KMP_AC_PREV && gl->ph->ac_mode != KMP_AC_AUTO_PREV ) { si->total_err++; sf->line_err++; @@ -1626,7 +1638,7 @@ static enumError AddGroupGL if (!si->no_warn) ERROR0(ERR_WARNING, "Command '$SPLIT' only possible if AUTO-CONNECT is set to AC$PREV" - " => ignored [%s @%u].\n", sf->name, sf->line ); + " or AC$AUTO_PREV => ignored [%s @%u].\n", sf->name, sf->line ); return ERR_WARNING; } @@ -1843,7 +1855,6 @@ static void TermGL CheckLevelSI(si); ResetRouteLinksKMP(kmp); - const bool auto_prev = gl->ph->ac_mode == KMP_AC_PREV; memset(gl->ph->gname,0,sizeof(gl->ph->gname)); List_t *list = kmp->dlist + sect_ph; @@ -1871,10 +1882,25 @@ static void TermGL rotate_links = rotate_links <= 0 ? 0 : rotate_links % KMP_MAX_PH_LINK; PRINT_IF(rotate_links,"ROTATE-LINKS %d\n",rotate_links); + kmp_ph_t *ph = gl->ph; + DASSERT(ph); + for ( i = 0, grp = gl->group; i < gl->used; i++, grp++ ) { //--- NEXT links + // [[auto-prev]] + #if 1 + const bool auto_prev + = gl->ph->ac_mode == KMP_AC_PREV + || gl->ph->ac_mode == KMP_AC_AUTO_PREV && !grp->have_prev_cmd; + if (sect_ph==KMP_ENPH) PRINT1("auto_prev=%d ; %s\n",auto_prev,grp->name); + #else + const bool auto_prev + = gl->ph->ac_mode == KMP_AC_PREV + || gl->ph->ac_mode == KMP_AC_AUTO_PREV; + #endif + uint l; for ( l = 0; l < KMP_MAX_PH_LINK; l++ ) { @@ -1917,6 +1943,7 @@ static void TermGL kmp_section_name[gl->ph->sect_pt].name1, grp->name, lname); } + //--- PREV links if (!auto_prev) @@ -1958,9 +1985,6 @@ static void TermGL //--- @AUTO-CONNECT == AC$DISPATCH - kmp_ph_t *ph = gl->ph; - DASSERT(ph); - if ( ph && ph->ac_mode == KMP_AC_DISPATCH && ( sect_ph == KMP_ENPH || sect_ph == KMP_ITPH )) { @@ -2452,10 +2476,12 @@ const VarMap_t * SetupVarsKMP() { "AC$OFF", KMP_AC_OFF }, { "AC$PREV", KMP_AC_PREV }, + { "AC$AUTO_PREV", KMP_AC_AUTO_PREV }, { "AC$DISPATCH", KMP_AC_DISPATCH }, { "ACF$FIX_PREV", KMP_ACF_FIX_PREV }, { "ACF$FIX_NEXT", KMP_ACF_FIX_NEXT }, { "ACF$FIX", KMP_ACF_FIX }, + { "ACF$PR_PREV", KMP_ACF_PR_PREV }, { "AM$OFF", KMP_AM_OFF }, { "AM$NORM", KMP_AM_NORM }, @@ -2464,10 +2490,11 @@ const VarMap_t * SetupVarsKMP() { "AM$SHORT", KMP_AM_SHORT }, { "AM$UNLIMIT", KMP_AM_UNLIMIT }, - { "SORT$OFF", KMP_SORT_OFF }, - { "SORT$GROUPING", KMP_SORT_GROUPING }, - { "SORT$ANGLE", KMP_SORT_ANGLE }, - { "SORT$TINY", KMP_SORT_TINY }, + { "SORT$OFF", KSORT_OFF }, + { "SORT$GROUPING", KSORT_GROUP }, + { "SORT$ANGLE", KSORT_ANGLE }, + { "SORT$XYZ", KSORT_XYZ }, + { "SORT$TINY", KSORT_TINY }, { "DOB$OFF", KMP_DOB_OFF }, { "DOB$BEGIN", KMP_DOB_BEGIN }, @@ -3026,7 +3053,7 @@ static enumError ScanText_PT_PH const kmp_enpt_entry_t * prev = GetListElem(ptlist,-1,&temp); if (!ptlist->used) // no previous point available gl.line.n = 1; - else if ( auto_fill >= 1.0 + else if ( auto_fill >= 1.0 && gl.line.n == 1 && gl.used && ptlist->used != gl.group[gl.used-1].first_index ) @@ -3626,7 +3653,7 @@ static enumError ScanTextGOBJ kcl_fall_t kfall; ResetKclFall(&kfall); - int auto_object_name = 0, sort_objects = 0; + int auto_object_name = 0, sort_objects = KSORT_OFF; int fix_objdef = 0, sort_objdef = 0; int fix_reference = 0, sort_reference = 0; uint auto_enemy_item = 0, auto_enemy_index = 32; @@ -5828,7 +5855,11 @@ static ccp print_kmp_group //--- $PREV - bool print_prev = ph->ac_mode != KMP_AC_PREV; + // [[auto-prev]] + bool print_prev = ph->ac_mode != KMP_AC_PREV && ph->ac_mode != KMP_AC_AUTO_PREV + || ph->ac_flags & KMP_ACF_PR_PREV + || KMP_MODE & KMPMD_PR_PREV; + if ( !print_prev && idx < KMP_MAX_LINFO ) { SetupRouteLinksKMP(kmp,ph->sect_ph,false); @@ -6000,7 +6031,7 @@ static void print_kmp_pt if ( opt_route_options > OFFON_OFF ) { - ccp ac_mode, ac_fix; + ccp ac_mode, ac_fix, ac_pr_prev; switch ( ph->ac_flags & KMP_ACF_FIX ) { @@ -6010,22 +6041,26 @@ static void print_kmp_pt default: ac_fix = ""; break; } + ac_pr_prev = ph->ac_flags & KMP_ACF_PR_PREV ? " | ACF$PR_PREV" : ""; + switch( ph->ac_mode ) { case KMP_AC_OFF: ac_mode = "AC$OFF"; break; case KMP_AC_PREV: ac_mode = "AC$PREV"; break; + case KMP_AC_AUTO_PREV: ac_mode = "AC$AUTO_PREV"; break; case KMP_AC_DISPATCH: ac_mode = "AC$DISPATCH"; break; default: // should never happen snprintf(buf,sizeof(buf),"0x%0x",ph->ac_mode|ph->ac_flags); - ac_mode = buf; - ac_fix = ""; + ac_mode = buf; + ac_fix = ""; + ac_pr_prev = ""; } if ( sect_pt == KMP_ENPT ) - fprintf(F->f,text_kmp_enpt_ropt_cr, ph->show_options, ac_mode, ac_fix ); + fprintf(F->f,text_kmp_enpt_ropt_cr, ph->show_options, ac_mode,ac_fix,ac_pr_prev ); else - fprintf(F->f,text_kmp_itpt_ropt_cr, ph->show_options, ac_mode, ac_fix ); + fprintf(F->f,text_kmp_itpt_ropt_cr, ph->show_options, ac_mode,ac_fix,ac_pr_prev ); } if ( ph->mask[0] != 0xffff || ph->mask[1] != 0xffff ) @@ -6154,6 +6189,7 @@ static void print_kmp_ph ccp pt_name = kmp_section_name[sect_pt].name1; ccp ph_name = kmp_section_name[sect_ph].name1; + //--- print data fprintf(F->f,text_kmp_ph_cr, @@ -6501,7 +6537,7 @@ enumError SaveTextKMP "#%.78s\r\n", area->prio, area->rotation[0], area->rotation[1], area->rotation[2], - PrintU8M1(area->route), PrintU8M1(area->enemy), area->unknown_2e, + PrintU8M1(area->route), PrintU8M1(area->enemy), area->unknown_2e, area->scale[0], area->scale[1], area->scale[2], Minus300 ); } @@ -7126,8 +7162,7 @@ enumError SaveTextKMP fputs("\r\n",F.f); double total_len = 0.0, total_tim = 0.0; - uint ei; - for ( ei = 0; ei < en; ei++, i++, pp++ ) + for ( uint ei = 0; ei < en; ei++, i++, pp++ ) { fprintf(F.f, "%4u %11.3f %11.3f %11.3f %5u %5u #", ei, diff --git a/project/src/lib-kmp.c b/project/src/lib-kmp.c index 7c39d97..820639e 100644 --- a/project/src/lib-kmp.c +++ b/project/src/lib-kmp.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -569,6 +569,8 @@ static const KeywordTab_t opt_kmp_tab[] = { KMPMD_RM_EMPTY, "RM-EMPTY", "RMEMPTY", 0 }, { KMPMD_MINIMIZE, "MINIMIZE", 0, 0 }, + { KMPMD_PR_PREV, "PR-PREV", "PRPREV", 0 }, + { KMPMD_TEST1, "TEST1", 0, 0 }, { KMPMD_TEST2, "TEST2", 0, 0 }, @@ -3647,6 +3649,24 @@ static int sort_gobj ( const sort_gobj_t * a, const sort_gobj_t * b ) //----------------------------------------------------------------------------- +static int sort_gobj_xyz ( const sort_gobj_t * a, const sort_gobj_t * b ) +{ + int stat = a->rank - b->rank; + if (!stat) + { + stat = a->data.position[0] < b->data.position[0] ? -1 + : a->data.position[0] > b->data.position[0] ? 1 + : a->data.position[1] < b->data.position[1] ? -1 + : a->data.position[1] > b->data.position[1] ? 1 + : a->data.position[2] < b->data.position[2] ? -1 + : a->data.position[2] > b->data.position[2] ? 1 + : a->pos - b->pos; + } + return stat; +} + +//----------------------------------------------------------------------------- + static int sort_gobj_tiny ( const sort_gobj_t * a, const sort_gobj_t * b ) { int stat = memcmp( a->data.setting, @@ -3673,17 +3693,15 @@ static int sort_gobj_tiny ( const sort_gobj_t * a, const sort_gobj_t * b ) bool SortGOBJ ( kmp_t * kmp, // pointer to valid KMP - int sort_mode // <=0: dont sort - // 1: group only - // 2: secondary sort by angle - // 3: sort for TINY + kmp_sort_t sort_mode // one of KSORT_OFF, KSORT_GROUP, + // KSORT_ANGLE, KSORT_XYZ or KSORT_TINY ) { DASSERT(kmp); PRINT("SortGOBJ(%d)\n",sort_mode); List_t *dlist = kmp->dlist + KMP_GOBJ; - if ( sort_mode < 1 || dlist->used < 2 ) + if ( sort_mode <= KSORT_OFF || dlist->used < 2 ) return false; @@ -3713,21 +3731,26 @@ bool SortGOBJ const typeof(gobj->obj_id) obj_id = gobj->obj_id; sg->pos = sg - sg_beg; sg->rank = obj_id < N_KMP_GOBJ ? rank[obj_id] : obj_id; - if ( sort_mode == KMP_SORT_ANGLE ) + if ( sort_mode == KSORT_ANGLE ) { sg->angle = atan2(gobj->position[0],gobj->position[2]) * (180000000/M_PI); - if ( sg->angle < 0) + if ( sg->angle < 0 ) sg->angle += 360000000; } memcpy(&sg->data,gobj,sizeof(sg->data)); } + //--- sort data - if ( sort_mode == KMP_SORT_TINY ) - qsort( sg_beg, dlist->used, sizeof(*sg_beg), (qsort_func)sort_gobj_tiny ); - else - qsort( sg_beg, dlist->used, sizeof(*sg_beg), (qsort_func)sort_gobj ); + int (*func) ( const sort_gobj_t * a, const sort_gobj_t * b ); + switch (sort_mode) + { + case KSORT_XYZ: func = sort_gobj_xyz; break; + case KSORT_TINY: func = sort_gobj_tiny; break; + default: func = sort_gobj; break; + } + qsort( sg_beg, dlist->used, sizeof(*sg_beg), (qsort_func)func ); //--- store sorted data @@ -5225,7 +5248,7 @@ bool PatchKMP } } - SortGOBJ(kmp,KMP_SORT_TINY); + SortGOBJ(kmp,KSORT_TINY); } @@ -5827,7 +5850,7 @@ void ModifyUsedPosObj obj->allowed.v[i] *= stretch->v[i]; } } - EvaluateUsedPosObj(obj); + EvaluateUsedPosObj(obj); obj->useful = useful; if (src) @@ -5864,7 +5887,7 @@ ccp GetUsedPosObjSuggestion if (obj->pos_factor_valid) return PrintCircBuf("@ITEM-POS-FACTOR=v(%4.2f,%4.2f,%4.2f)", obj->pos_factor.x, obj->pos_factor.y, obj->pos_factor.z ); - } + } return return_if_empty; } @@ -5881,7 +5904,7 @@ void PrintUsedPosObj ( FILE *f, int indent, const kmp_usedpos_obj_t *obj ) "R=%d,%d,%d, P=%d/%1.2f,%1.2f,%1.2f\n", indent,"", obj->valid, obj->useful, obj->shift_active, obj->stretch_active, - obj->min.x/1000, obj->min.y/1000, obj->min.z/1000, + obj->min.x/1000, obj->min.y/1000, obj->min.z/1000, obj->max.x/1000, obj->max.y/1000, obj->max.z/1000, obj->allowed.x/1000, obj->allowed.y/1000, obj->allowed.z/1000, obj->shift.x/1000, obj->shift.y/1000, obj->shift.z/1000, @@ -6106,6 +6129,7 @@ const kmp_obj_info_t have_kmp_info[HAVEKMP__N] = { 0, "coob-r", "Conditional OOB by Riidefi" }, // HAVEKMP_COOB_R { 0, "coob-k", "Conditional OOB by kHacker35000vr" }, // HAVEKMP_COOB_K { 0, "uoob", "Unconditional OOB" }, // HAVEKMP_UOOB + { 0, "goomba-sz", "Goomba with scale other than 1.00" }, // HAVEKMP_GOOMBA_SIZE }; /////////////////////////////////////////////////////////////////////////////// @@ -6161,6 +6185,11 @@ void DetectSpecialKMP res[HAVEKMP_PENGUIN_POS]++; break; + case 0x191: // goomba (kuribo) + if ( gobj->scale[0] != 1.0 || gobj->scale[1] != 1.0 || gobj->scale[2] != 1.0 ) + res[HAVEKMP_GOOMBA_SIZE]++; + break; + case 0x1a6: // Epropeller if ( gobj->setting[7] && res[HAVEKMP_EPROP_SPEED] < 0xff ) res[HAVEKMP_EPROP_SPEED]++; @@ -6213,7 +6242,7 @@ ccp CreateSpecialInfoKMP // /////////////////////////////////////////////////////////////////////////////// -/////////////// CkeckKMP() /////////////// +/////////////// CheckKMP() /////////////// /////////////////////////////////////////////////////////////////////////////// // [[check_kmp_t]] @@ -6722,6 +6751,9 @@ int CheckKMP DASSERT(kmp); PRINT("CheckKMP(%d)\n",mode); + if ( disable_checks > 0 ) + return 0; + //--- setup check_kmp_t chk; diff --git a/project/src/lib-kmp.h b/project/src/lib-kmp.h index 050444e..09b7a4a 100644 --- a/project/src/lib-kmp.h +++ b/project/src/lib-kmp.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -175,13 +175,6 @@ enum KMP_AM_SHORT, // define modes to get a very short race KMP_AM_UNLIMIT, // remove lap counter for unlimited race - //----- sort modes - - KMP_SORT_OFF = 0, // sort is off - KMP_SORT_GROUPING, // grouping only - KMP_SORT_ANGLE, // grouping and sorting by angle - KMP_SORT_TINY, // grouping and sorting optimized for TINY - //----- definition-object (DOB) sort modes KMP_DOB_OFF = 0, // sort if off @@ -221,16 +214,18 @@ typedef enum kmp_ac_mode //--- modes KMP_AC_OFF = 0, // don't auto connect, always 0 - KMP_AC_PREV, // auto connect PREV by NEXT + KMP_AC_PREV, // auto connect PREV by NEXT always + KMP_AC_AUTO_PREV, // auto connect PREV by NEXT if $PREV not used KMP_AC_DISPATCH, // auto connect for arenas, mode DISPATCH KMP_AC_MASK = 0x0f, // mask for modes //--- flags/options - KMP_ACF_FIX_PREV = 0x10, // flags/options - KMP_ACF_FIX_NEXT = 0x20, // flags/options + KMP_ACF_FIX_PREV = 0x10, // fix prev links + KMP_ACF_FIX_NEXT = 0x20, // fix next links KMP_ACF_FIX = KMP_ACF_FIX_PREV | KMP_ACF_FIX_NEXT, - KMP_ACF_MASK = KMP_ACF_FIX, // mask for flags + KMP_ACF_PR_PREV = 0x40, // print $PREV:... + KMP_ACF_MASK = 0x70, // mask for flags } __attribute__ ((packed)) kmp_ac_mode; @@ -369,7 +364,6 @@ typedef struct kmp_head_info_t uint max_off; // max usable offset (end-4) int n_sect; // number of section, 0 on error u32 *sect_off; // list mit section offsets - } kmp_head_info_t; @@ -425,7 +419,7 @@ __attribute__ ((packed)) kmp_enpt_entry_t; typedef kmp_enpt_entry_t kmp_itpt_entry_t; /////////////////////////////////////////////////////////////////////////////// -// [[kmp_enph_entry_t]] +// [[kmp_enph_entry_t]] typedef struct kmp_enph_entry_t { @@ -602,6 +596,22 @@ __attribute__ ((packed)) kmp_stgi_entry_t; // /////////////////////////////////////////////////////////////////////////////// +/////////////// KMP sort modes /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_sort_t]] + +typedef enum kmp_sort_t +{ + KSORT_OFF, // don't sort + KSORT_GROUP, // sort by groups + KSORT_ANGLE, // sort by groups and angles + KSORT_XYZ, // sort by groups and coordonates in xyz order + KSORT_TINY, // sort for TINY +} +kmp_sort_t; + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// Wim0 support /////////////// /////////////////////////////////////////////////////////////////////////////// // [[kmp_wim0_sect_id]] @@ -806,6 +816,7 @@ typedef struct kmp_gopt2_t kmp_rtype_mode rtype_active; // active route type kmp_oneway_mode ac_oneway; // oneway mode for auto-connect u8 setting[2]; // values of bytes at offeset 0x0e and 0x0f +// u8 have_prev_cmd; // >0: $PREV command used kmp_gopt_t prev; // values for first point (prev link) kmp_gopt_t next; // values for last point (next link) @@ -817,7 +828,7 @@ kmp_gopt2_t; typedef struct kmp_group_elem_t { - kmp_group_name_t name; // name of eleemns + kmp_group_name_t name; // name of element kmp_oneway_mode oneway; // oneway mode } kmp_group_elem_t; @@ -830,6 +841,7 @@ typedef struct kmp_group_t int first_index; // index of first point int last_index; // index of last point bool no_rotate; // true: do not rotate links + bool have_prev_cmd; // >0: $PREV command scannend kmp_group_name_t name; // name of group kmp_group_elem_t prev[KMP_MAX_PH_LINK]; // prev-link names and status @@ -848,7 +860,7 @@ typedef struct kmp_group_list_t uint used; // used groups kmp_group_t group[KMP_MAX_GROUP]; // list with groups char selector; // '!' selector - bool have_options; // >0 at least one option detected + bool have_options; // >0_ at least one option detected Line_t line; // '$LINE' settings } kmp_group_list_t; @@ -982,13 +994,21 @@ typedef enum kmp_mode_t KMPMD_RM_EMPTY = KMPMD_TINY_1 << 3, // skip empty KMP sections KMPMD_MINIMIZE = KMPMD_RM_EMPTY << 1, // minimize KMP by reordering [[obsolete]] not used + + //--- misc + + KMPMD_PR_PREV = KMPMD_MINIMIZE << 1, // print $PREV: ... (CKPT,ENPT,ITPT) + KMPMD_M_MISC = KMPMD_PR_PREV, + + //--- tests - KMPMD_TEST1 = KMPMD_MINIMIZE << 1, // reserved for testing + KMPMD_TEST1 = KMPMD_PR_PREV << 1, // reserved for testing KMPMD_TEST2 = KMPMD_TEST1 << 1, // reserved for testing KMPMD_M_TEST = KMPMD_TEST1 | KMPMD_TEST2, + //--- summaries KMPMD_M_DEFAULT = 0, // default settings @@ -1003,6 +1023,7 @@ typedef enum kmp_mode_t | KMPMD_M_TINY | KMPMD_RM_EMPTY | KMPMD_MINIMIZE + | KMPMD_M_MISC | KMPMD_M_TEST, KMPMD_M_ALL = KMPMD_M_GENERAL // all relevant bits @@ -1465,9 +1486,8 @@ enumError SaveTextKMP bool SortGOBJ ( kmp_t * kmp, // pointer to valid KMP - int sort_mode // <=0: dont sort - // 1: group only - // 2: secondary sort by angle + kmp_sort_t sort_mode // one of KSORT_OFF, KSORT_GROUP, + // KSORT_ANGLE, KSORT_XYZ or KSORT_TINY ); //----------------------------------------------------------------------------- @@ -1795,7 +1815,7 @@ void AddRoutes2KCL ( DrawKCL_t * dk, // pointer to initalized object uint sect_pt, // KMP section - uint color_std // standart color index + uint color_std // standard color index ); //----------------------------------------------------------------------------- @@ -2186,7 +2206,7 @@ uint CountPresenceFlags ( const kmp_t *kmp, kmp_pflags_t *pf ); // 13 0x2000 Online race with 19 or more players total and 2 humans at Wii. //-------------------------------------------------------------------------- // 14 0x4000 RESERVED1. In Versus (setting #3) it is used for Time Trial. -// 15 0x8000 RESERVED2. +// 15 0x8000 RESERVED2. //-------------------------------------------------------------------------- /////////////////////////////////////////////////////////////////////////////// @@ -2766,7 +2786,7 @@ typedef enum xpf_mode1_t XMODE1_CONDREF, // MODE==1 && conditiopn reference XMODE1_OBJREF, // MODE==1 && object reference XMODE1__N - + } xpf_mode1_t; diff --git a/project/src/lib-lecode.c b/project/src/lib-lecode.c index 8c71067..331db20 100644 --- a/project/src/lib-lecode.c +++ b/project/src/lib-lecode.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -50,6 +50,7 @@ /////////////////////////////////////////////////////////////////////////////// ccp opt_le_define = 0; +ccp opt_le_arena = 0; ccp opt_lpar = 0; ccp opt_track_dest = 0; ParamField_t opt_track_source = {0}; @@ -474,9 +475,10 @@ bool GetNextDebugMode ( lecode_debug_info_t *ldi ) { LEDEB_POSITION, 0, "POSITION" }, { LEDEB_CHECK_POINT, LEDEB_S_CHECK_POINT, "CHECK-POINT" }, { LEDEB_RESPAWN, 0, "RESPAWN" }, + { LEDEB_ITEM_POINT, 0, "ITEM-POINT" }, + { LEDEB_KCL_TYPE, 0, "KCL-TYPE" }, { LEDEB_LAP_POS, 0, "LAP-POS" }, - { LEDEB_XPF, LEDEB_S_XPF, "XPF" }, -// [[xpf+]] + { LEDEB_XPF, LEDEB_S_XPF, "XPF" }, }; while ( ldi->index >= 0 && ldi->index < sizeof(tab)/sizeof(*tab) ) @@ -518,6 +520,8 @@ lecode_debug_t DecodeLecodeDebug ( lecode_debug_ex_t *lde, lecode_debug_t mode ) lde->position = ( mode & LEDEB_POSITION ) > 0; lde->check_point = mode >> LEDEB_S_CHECK_POINT & LEDEB_M_CHECK_POINT; lde->respawn = ( mode & LEDEB_RESPAWN ) > 0; + 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->xpf = mode >> LEDEB_S_XPF & LEDEB_M_XPF; @@ -541,6 +545,8 @@ lecode_debug_t EncodeLecodeDebug ( lecode_debug_ex_t *lde ) if ( lde->space ) mode |= LEDEB_SPACE; if ( lde->position ) mode |= LEDEB_POSITION; if ( lde->respawn ) mode |= LEDEB_RESPAWN; + if ( lde->item_point ) mode |= LEDEB_ITEM_POINT; + if ( lde->kcl_type ) mode |= LEDEB_KCL_TYPE; if ( lde->lap_pos ) mode |= LEDEB_LAP_POS; return DecodeLecodeDebug(lde,mode); // normalize all settings @@ -597,10 +603,11 @@ bool SetupLecodeDebugLPAR { PREDEBUG_VERTICAL,-1, 0 }, // hide speedo { PREDEBUG_VERTICAL, 1, LEDEB_CHECK_POINT }, { PREDEBUG_VERTICAL, 2, LEDEB_RESPAWN }, - { PREDEBUG_VERTICAL, 3, LEDEB_LAP_POS }, - { PREDEBUG_VERTICAL, 4, LEDEB_POSITION }, - { PREDEBUG_VERTICAL, 5, LEDEB_LONG_XPF }, -// [[xpf+]] + { PREDEBUG_VERTICAL, 3, LEDEB_ITEM_POINT }, + { PREDEBUG_VERTICAL, 4, LEDEB_KCL_TYPE }, + { PREDEBUG_VERTICAL, 5, LEDEB_LAP_POS }, + { PREDEBUG_VERTICAL, 6, LEDEB_POSITION }, + { PREDEBUG_VERTICAL, 7, LEDEB_LONG_XPF }, {0,0,0} }; @@ -920,7 +927,7 @@ void InitializeLPAR ( le_lpar_t *lpar, bool load_lpar ) } /////////////////////////////////////////////////////////////////////////////// - + static void NormalizeLPAR ( le_lpar_t * lp ) { DASSERT(lp); @@ -1178,7 +1185,7 @@ enumError WriteSectionLPAR { fputs(text_lpar_sect_chat_cr,f); - int i; + int i; for ( i = 0; i < BMG_N_CHAT; i++ ) if ( lpar->chat_mode_1[i] || lpar->chat_mode_2[i] ) break; @@ -1186,7 +1193,7 @@ enumError WriteSectionLPAR fputs(text_lpar_sect_chat_example_cr,f); } - int last_group = -1; + int last_group = -1; for ( int i = 0; i < BMG_N_CHAT; i++ ) { const u16 mode1 = lpar->chat_mode_1[i]; @@ -1296,6 +1303,66 @@ void ResetLEAnalyseUsage ( le_analyse_t *ana ) /////////////////////////////////////////////////////////////////////////////// +static void ApplyArena ( le_analyse_t * ana, const ctcode_arena_t * ca ) +{ + DASSERT(ana); + DASSERT(ca); + + if (!ana->arena_setup) + SetupArenasLEAnalyse(ana,false); + + if (ana->property) + for ( int a = 0; a < MKW_N_ARENAS; a++ ) + if (ca->prop[a]) + { + ana->property[a+MKW_ARENA_BEG] = ca->prop[a]; + 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->arena_applied = true; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void SetupArenasLEAnalyse ( le_analyse_t *ana, bool force ) +{ + DASSERT(ana); + if ( ana->property && ana->music ) + { + ana->arena_setup = true; + + if ( force || !ana->property[MKW_ARENA_BEG] ) + { + const TrackInfo_t *ai = arena_info; + for ( int a = 0; a < MKW_N_ARENAS; a++, ai++ ) + { + ana->property[a+MKW_ARENA_BEG] = ai->track_id; + ana->music[a+MKW_ARENA_BEG] = ai->music_id; + } + } + + if ( opt_le_arena && *opt_le_arena ) + { + raw_data_t raw; + if ( LoadRawData(&raw,true,opt_le_arena,0,false,0) == ERR_OK ) + { + ctcode_arena_t ca = {{0}}; + ScanTextArena(&ca,raw.fname,raw.data,raw.data_size); + ApplyArena(ana,&ca); + } + ResetRawData(&raw); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + enumError AnalyseLEBinary ( le_analyse_t *ana, // NULL or destination of analysis @@ -1567,9 +1634,9 @@ enumError AnalyseLEBinary *(uint*)((u8*)ana+pnm->off_max) = max; } + SetupArenasLEAnalyse(ana,false); CalculateStatsLE(ana); - //--- return return ana->valid & LE_PARAM_VALID ? ERR_OK : @@ -1801,7 +1868,7 @@ static ccp GetSlotInfo uint *warnings // not NULL: increment on warnings ) { - if ( tid < ana->n_slot ) + if ( tid < ana->n_slot || IsMkwArena(tid) ) { uint warn = 0; @@ -1848,7 +1915,7 @@ static ccp GetSlotInfo music0 = col->reset; } } - else if (!(music&1)) + else if ( !(music&1) || IsMkwArena(tid) && MusicID2TrackId(music,0,0) != tid ) { warn |= 1; if (col) @@ -1887,17 +1954,14 @@ static ccp GetSlotInfo flags = "-?-"; static const char warn_list[] = " <!!"; - char buf[40]; - const int len = is_alias - ? snprintf(buf,sizeof(buf),"[%s->%4x %s,%s] ", + return is_alias + ? PrintCircBuf("[%s->%4x %s,%s] ", col->differ, TrackByAliasLE(prop,music), col->reset, flags ) - : snprintf(buf,sizeof(buf),"[%s%s%s,%s%s%s,%s]%c", + : PrintCircBuf("[%s%s%s,%s%s%s,%s]%c", prop1, propx, prop0, music1, musicx, music0, flags, warn_list[warn] ); - if ( len > 0 ) - return CopyCircBuf0(buf,len); } if (col) @@ -2310,7 +2374,7 @@ void DumpLEAnalyse ( FILE *f, uint indent, const le_analyse_t *ana ) "%*s" "Allow cheat codes: %u = %s\n" ,indent,"", h->cheat_mode, GetCheatModeInfo(h->cheat_mode) ); - + fprintf(f, "%*s" "Engine chances: " "%u + %u + %u = %u (1%s0cc+mirror=total)\n" @@ -2350,7 +2414,7 @@ void DumpLEAnalyse ( FILE *f, uint indent, const le_analyse_t *ana ) } else comment = ""; - + fprintf(f, "%*s" "Speedometer: %u%s\n", indent,"", h->enable_speedo, comment ); @@ -2603,13 +2667,16 @@ const ctcode_t * LoadLEFile ( uint le_phase ) le_file_done = false; } + + // --le-define + if ( !le_file_done && opt_le_define && *opt_le_define ) { PRINT("le=%d, ctm=%d[%s]\n", le_phase, ct_mode, GetCtModeNameBMG(ct_mode,true) ); if ( logging > 1 ) - fprintf(stdlog,"Load LE definition for phase %d (%s)\n", - le_phase, GetCtModeNameBMG(ct_mode,true) ); + fprintf(stdlog,"Load LE definition (%s)\n", + GetCtModeNameBMG(ct_mode,true) ); le_file_done = true; le_file = MALLOC(sizeof(*le_file)); @@ -2633,6 +2700,8 @@ const ctcode_t * LoadLEFile ( uint le_phase ) enumError ApplyLEFile ( le_analyse_t * ana ) { DASSERT(ana); + SetupArenasLEAnalyse(ana,false); + const ctcode_t *ctcode = LoadLEFile(ana->version); return ctcode ? ApplyCTCODE(ana,ctcode) : ERR_ERROR; } @@ -2742,6 +2811,15 @@ enumError ApplyCTCODE ( le_analyse_t * ana, const ctcode_t * ctcode ) } } + + //--- arena setup (override) + + SetupArenasLEAnalyse(ana,false); + ApplyArena(ana,&ctcode->arena); + + + //--- setup by version + switch (ana->param_vers) { case 1: diff --git a/project/src/lib-lecode.h b/project/src/lib-lecode.h index e37b36e..c8ed13d 100644 --- a/project/src/lib-lecode.h +++ b/project/src/lib-lecode.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -119,12 +119,14 @@ typedef enum lecode_debug_t LEDEB_XPF = 0x0300, // 2 bits! LEDEB_SHORT_XPF = 0x0100, LEDEB_LONG_XPF = 0x0200, + LEDEB_ITEM_POINT = 0x0400, + LEDEB_KCL_TYPE = 0x0800, //--- derived values - LEDEB__STD = 0x00f9, // standard output - LEDEB__OUTPUT = 0x03f8, // flags that produce output - LEDEB__ALL = 0x03ff, // all flags + LEDEB__STD = 0x0ff9, // standard output + LEDEB__OUTPUT = 0x0ff8, // flags that produce output + LEDEB__ALL = 0x0fff, // all flags LEDEB_S_CHECK_POINT = 4, // shift for LEDEB_CHECK_POINT LEDEB_M_CHECK_POINT = 3, // mask after shift @@ -184,6 +186,8 @@ typedef struct lecode_debug_ex_t u8 position; u8 check_point; u8 respawn; + u8 item_point; + u8 kcl_type; u8 lap_pos; u8 xpf; @@ -400,7 +404,7 @@ typedef struct le_binpar_v1_35_t /*20*/ u32 off_course_par; // offset of course param /*24*/ u32 off_property; // offset of property list /*28*/ u32 off_music; // offset of music list - /*2c*/ u32 off_flags; // offset of music list + /*2c*/ u32 off_flags; // offset of flags /*30*/ u8 engine[3]; // 100cc, 150cc, mirror (sum always 100) /*33*/ u8 enable_200cc; // TRUE: 200C enabled => 150cc, 200cc, mirror @@ -427,7 +431,7 @@ typedef struct le_binpar_v1_37_t /*20*/ u32 off_course_par; // offset of course param /*24*/ u32 off_property; // offset of property list /*28*/ u32 off_music; // offset of music list - /*2c*/ u32 off_flags; // offset of music list + /*2c*/ u32 off_flags; // offset of flags /*30*/ u8 engine[3]; // 100cc, 150cc, mirror (sum always 100) /*33*/ u8 enable_200cc; // TRUE: 200C enabled => 150cc, 200cc, mirror @@ -456,7 +460,7 @@ typedef struct le_binpar_v1_f8_t /*20*/ u32 off_course_par; // offset of course param /*24*/ u32 off_property; // offset of property list /*28*/ u32 off_music; // offset of music list - /*2c*/ u32 off_flags; // offset of music list + /*2c*/ u32 off_flags; // offset of flags /*30*/ u8 engine[3]; // 100cc, 150cc, mirror (sum always 100) /*33*/ u8 enable_200cc; // TRUE: 200C enabled => 150cc, 200cc, mirror @@ -487,7 +491,7 @@ typedef struct le_binpar_v1_1b8_t /*020*/ u32 off_course_par; // offset of course param /*024*/ u32 off_property; // offset of property list /*028*/ u32 off_music; // offset of music list - /*02c*/ u32 off_flags; // offset of music list + /*02c*/ u32 off_flags; // offset of flags /*030*/ u8 engine[3]; // 100cc, 150cc, mirror (sum always 100) /*033*/ u8 enable_200cc; // TRUE: 200C enabled => 150cc, 200cc, mirror @@ -519,7 +523,7 @@ typedef struct le_binpar_v1_1bc_t /*020*/ u32 off_course_par; // offset of course param /*024*/ u32 off_property; // offset of property list /*028*/ u32 off_music; // offset of music list - /*02c*/ u32 off_flags; // offset of music list + /*02c*/ u32 off_flags; // offset of flags /*030*/ u8 engine[3]; // 100cc, 150cc, mirror (sum always 100) /*033*/ u8 enable_200cc; // TRUE: 200C enabled => 150cc, 200cc, mirror @@ -558,7 +562,7 @@ typedef struct le_binpar_v1_260_t /*020*/ u32 off_course_par; // offset of course param /*024*/ u32 off_property; // offset of property list /*028*/ u32 off_music; // offset of music list - /*02c*/ u32 off_flags; // offset of music list + /*02c*/ u32 off_flags; // offset of flags /*030*/ u8 engine[3]; // 100cc, 150cc, mirror (sum always 100) /*033*/ u8 enable_200cc; // TRUE: 200C enabled => 150cc, 200cc, mirror @@ -599,7 +603,7 @@ typedef struct le_binpar_v1_264_t /*020*/ u32 off_course_par; // offset of course param /*024*/ u32 off_property; // offset of property list /*028*/ u32 off_music; // offset of music list - /*02c*/ u32 off_flags; // offset of music list + /*02c*/ u32 off_flags; // offset of flags /*030*/ u8 engine[3]; // 100cc, 150cc, mirror (sum always 100) /*033*/ u8 enable_200cc; // TRUE: 200C enabled => 150cc, 200cc, mirror @@ -708,6 +712,9 @@ typedef struct le_analyse_t le_usage_t *usage; // NULL or alloced list[n_slot], setup by GetLEUsage() uint usage_size; // number of alloed 'usage' elements + bool arena_setup; // set by SetupArenasLEAnalyse() + bool arena_applied; // set by ApplyArena() + //--- binary data @@ -746,6 +753,7 @@ le_analyse_t; void ResetLEAnalyse ( le_analyse_t *ana ); void ResetLEAnalyseUsage ( le_analyse_t *ana ); +void SetupArenasLEAnalyse ( le_analyse_t *ana, bool force ); enumError AnalyseLEBinary ( @@ -791,6 +799,7 @@ uint GetNextRacingTrackLE ( uint tid ); /////////////////////////////////////////////////////////////////////////////// extern ccp opt_le_define; +extern ccp opt_le_arena; extern ccp opt_lpar; extern ccp opt_track_dest; extern ParamField_t opt_track_source; diff --git a/project/src/lib-lex.c b/project/src/lib-lex.c index db63bfe..5640674 100644 --- a/project/src/lib-lex.c +++ b/project/src/lib-lex.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -135,6 +135,7 @@ static const feature_var_t szs_feature_list[] = static const feature_var_t kmp_feature_list[] = { + DEF_VAR( 0,HAVEKMP_GOOMBA_SIZE, kmp_goomba_size, "KMP: Goomba with scale != 1.00" ), DEF_VAR( 0,HAVEKMP_WOODBOX_HT, kmp_woodbox_ht, "KMP: Woodbox with fall height" ), DEF_VAR( 0,HAVEKMP_MUSHROOM_CAR, kmp_mushroom_car, "KMP: penguin_m as mushroom car" ), DEF_VAR( 0,HAVEKMP_PENGUIN_POS, kmp_penguin_pos, "KMP: Alternative start of penguin_m" ), @@ -160,10 +161,10 @@ static const feature_var_t lex_section_list[] = DEF_VAR( 0,HAVELEXS_SET1, lex_sect_set1, "LEX section SET1" ), DEF_VAR( 0,HAVELEXS_CANN, lex_sect_cann, "LEX section CANN" ), DEF_VAR( 0,HAVELEXS_HIPT, lex_sect_hipt, "LEX section HIPT" ), - // move HAVELEXS_TEST to here {0,0,0,0,0} }; + //----------------------------------------------------------------------------- static const feature_var_t lex_feature_list[] = @@ -172,7 +173,7 @@ static const feature_var_t lex_feature_list[] = DEF_VAR( 0,HAVELEXF_ITEM_RANGE, lex_item_range, "LEX: Expand the range of item positions" ), DEF_VAR( 0,HAVELEXF_CANNON, lex_cannon, "LEX: Alternative cannon settings" ), DEF_VAR( 0,HAVELEXF_HIDE_POS, lex_hide_pos, "LEX: Hide position tracker conditionally" ), - // move HAVELEXF_TEST_ACTIVE to here + DEF_VAR( 0,HAVELEXF_START_ITEM, lex_start_item, "LEX: Player can get item before start of race." ), {0,0,0,0,0} }; @@ -194,6 +195,7 @@ typedef struct feature_list_t const feature_var_t *var; // var list uint var_type; // one of enum feature_list_var_type uint offset; // offset in analyse_szs_t + uint max_value; // maximum possible value ccp ref_prefix; // prefix for references ccp heading1; // heading1 ccp heading2; // heading2 @@ -207,6 +209,7 @@ static const feature_list_t feature_lists[] = { szs_feature_list, FVT_BYTE_ARRAY, offsetof(szs_have_t,szs), + FZV_MAYBE_IMPACT, "SZS file", "Additional sub-files found in SZS file", "0:no file, 1:unmodified file, 2:modified file" }, @@ -214,32 +217,35 @@ static const feature_list_t feature_lists[] = { kmp_feature_list, FVT_BOOL_ARRAY, offsetof(szs_have_t,kmp), + FZV_IMPACT, "KMP feature", "Special features found in KMP (sub-file course.kmp)", - 0 }, + "0:not found, 1:found without impact, 3:found with impact" }, { lex_section_list, FVT_UINT_BITS, offsetof(szs_have_t,lex_sect), + FZV_MAYBE_IMPACT, "LEX section", "Sections found in LEX (sub-file course.lex)", - 0 }, + "0:section not found, 1:section found, 2:found and relevant" }, { lex_feature_list, FVT_UINT_BITS, offsetof(szs_have_t,lex_feat), + FZV_IMPACT, "LEX feature", "Special features found in LEX (sub-file course.lex)", - 0 }, + "0:not found, 1:found without impact, 3:found with impact" }, - {0,0,0,0,0} + {0,0,0,0,0,0} }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void InitializeFeaturesSZS ( features_szs_t * fs ) -{ +{ DASSERT(fs); memset(fs,0,sizeof(*fs)); fs->size_be = htons(sizeof(*fs)); @@ -323,8 +329,8 @@ void SetupFeaturesSZS ( features_szs_t *fs, const szs_have_t *have, bool is_lex for ( var = list->var; var->offset; var++ ) ((u8*)fs)[var->offset] = is_lex && var->no_lex - ? 1 - : src[var->index] > 0; + ? list->max_value + : src[var->index] > 0 ? list->max_value : 0; } break; @@ -334,7 +340,7 @@ void SetupFeaturesSZS ( features_szs_t *fs, const szs_have_t *have, bool is_lex for ( var = list->var; var->offset; var++ ) ((u8*)fs)[var->offset] = is_lex && var->no_lex - ? 1 + ? list->max_value : src[var->index]; } break; @@ -345,8 +351,8 @@ void SetupFeaturesSZS ( features_szs_t *fs, const szs_have_t *have, bool is_lex for ( var = list->var; var->offset; var++ ) ((u8*)fs)[var->offset] = is_lex && var->no_lex - ? 1 - : ( val & 1 << var->index ) != 0; + ? list->max_value + : ( val & 1 << var->index ) != 0 ? list->max_value : 0; } break; @@ -355,6 +361,10 @@ void SetupFeaturesSZS ( features_szs_t *fs, const szs_have_t *have, bool is_lex } } + //------------------------------------------------------------------------- + + NormalizeFeatures(fs); + // ??? [[2do]] } @@ -407,16 +417,34 @@ void PrintFeaturesSZS ( PrintScript_t *ps, // valid output definition const features_szs_t *fs, // valid source - bool is_lex, // TRUE: Create output for a LEX file + bool is_lex, // TRUE: Create output for a LEX file int comments, // >0: add extended comments int print_modes, // >0: append ",MODES" - u8 include, // print only if all bits match + u8 include, // print only if all bits match u8 exclude // exclude if any bit match ) { DASSERT(ps); DASSERT(fs); + PrintScriptVars(ps,0, + "\n" + "# The base value (lower bits) of each feature is one of:\n" + "# %u: file or feature not found.\n" + "# %u: file or feature found, but no impact.\n" + "# %u: file or feature found, maybe some settings with impact.\n" + "# %u: feature found with impact to game play.\n", + FZV_UNDEF, FZV_NO_IMPACT, FZV_MAYBE_IMPACT, FZV_IMPACT ); + + if ( comments >= 1 ) + PrintScriptVars(ps,0, + "#\n" + "# If value is %u, then some additional bits may be set:\n" + "# 0x%02x: Impact to game play of time-trial.\n" + "# 0x%02x: Impact to game play of offline (local) races and battles.\n" + "# 0x%02x: Impact to game play of online races and battles.\n", + FZV_IMPACT, FZM_TIMETRIAL, FZM_OFFLINE, FZM_ONLINE ); + if ( ps->fform == PSFF_UNKNOWN && comments >= 0 ) ps->fform = PSFF_ASSIGN; @@ -470,11 +498,18 @@ void PrintFeaturesSZS if (effect) PrintScriptVars(ps,0,"# %s\n",effect); } + + char valbuf[30]; + if ( value & FZV_M_OPTIONS && !is_lex && comments ) + snprintf(valbuf,sizeof(valbuf),"0x%02x",value); + else + snprintf(valbuf,sizeof(valbuf),"%u", value & FZV_M_VALUE ); + if ( print_modes > 0 ) - PrintScriptVars(ps,0,"%s=\"%u,%s\"\n", - var->name, value, GetFeaturesMode(mode) ); + PrintScriptVars(ps,0,"%s=\"%s,%s\"\n", + var->name, valbuf, GetFeaturesMode(mode) ); else - PrintScriptVars(ps,0,"%s=%u\n",var->name,value); + PrintScriptVars(ps,0,"%s=%s\n",var->name,valbuf); } } } @@ -495,7 +530,7 @@ const features_szs_t * GetFeaturesModes() if (!m.size_be) { InitializeFeaturesSZS(&m); - + const u8 invalid = FZM_SECTION | FZM_BATTLE | FZM_TIMETRIAL; memset((u8*)&m+sizeof(m.size_be),invalid,sizeof(m)-sizeof(m.size_be)); @@ -512,6 +547,7 @@ const features_szs_t * GetFeaturesModes() m.f_aiparam_baa = FZM_GAMEPLAY | FZM_M_TYPE | FZM_OFFLINE; m.f_aiparam_bas = FZM_GAMEPLAY | FZM_M_TYPE | FZM_OFFLINE; + m.kmp_goomba_size = FZM_GAMEPLAY | FZM_M_TYPE | FZM_M_WHERE; m.kmp_woodbox_ht = FZM_GAMEPLAY | FZM_M_TYPE | no_timetrial; m.kmp_mushroom_car = FZM_VISUAL | FZM_GAMEPLAY | FZM_M_TYPE | FZM_M_WHERE; m.kmp_penguin_pos = FZM_GAMEPLAY | FZM_M_TYPE | FZM_M_WHERE; @@ -523,18 +559,20 @@ const features_szs_t * GetFeaturesModes() m.kmp_eprop_speed = FZM_GAMEPLAY | FZM_M_TYPE | FZM_M_WHERE; m.kmp_coob_riidefii = FZM_GAMEPLAY | FZM_M_TYPE | FZM_M_WHERE; m.kmp_coob_khacker = FZM_GAMEPLAY | FZM_M_TYPE | FZM_M_WHERE; - m.kmp_uncond_oob = FZM_GAMEPLAY | FZM_M_TYPE | FZM_M_WHERE; + m.kmp_uncond_oob = FZM_M_TYPE | FZM_M_WHERE; - m.lex_sect_fea0 = FZM_SECTION; + // existence of a section don't have impact to gameplay => see lex attributes + m.lex_sect_fea0 = FZM_SECTION; m.lex_sect_test = FZM_VISUAL | FZM_GAMEPLAY | FZM_M_TYPE | no_timetrial | FZM_SECTION; - m.lex_sect_set1 = FZM_GAMEPLAY | FZM_M_TYPE | FZM_ONLINE | FZM_SECTION; - m.lex_sect_cann = FZM_GAMEPLAY | FZM_M_TYPE | FZM_M_WHERE | FZM_SECTION; - m.lex_sect_hipt = FZM_VISUAL | FZM_M_TYPE | no_timetrial | FZM_SECTION; + m.lex_sect_set1 = FZM_GAMEPLAY | FZM_M_TYPE | FZM_ONLINE | FZM_SECTION; + m.lex_sect_cann = FZM_GAMEPLAY | FZM_M_TYPE | FZM_M_WHERE | FZM_SECTION; + m.lex_sect_hipt = FZM_VISUAL | FZM_M_TYPE | no_timetrial | FZM_SECTION; m.lex_test_active = FZM_VISUAL | FZM_GAMEPLAY | FZM_M_TYPE | no_timetrial; m.lex_item_range = FZM_GAMEPLAY | FZM_M_TYPE | FZM_ONLINE; m.lex_cannon = FZM_GAMEPLAY | FZM_M_TYPE | FZM_M_WHERE; m.lex_hide_pos = FZM_VISUAL | FZM_M_TYPE | no_timetrial; + m.lex_start_item = FZM_GAMEPLAY | FZM_M_TYPE | FZM_ONLINE; #if CHECK_FEATURES uint err_count = 0; @@ -581,10 +619,10 @@ ccp GetFeaturesEffects ( features_szs_mode_t mode ) { { 0,FZM_SECTION, "section" }, - { 1,FZM_M_KIND, "no effects" }, - { 0,FZM_M_KIND, "visual and gameplay effects" }, - { 0,FZM_VISUAL, "visual effects only" }, - { 0,FZM_GAMEPLAY, "gameplay effects" }, + { 1,FZM_M_KIND, "no impact" }, + { 0,FZM_M_KIND, "visual and gameplay impact" }, + { 0,FZM_VISUAL, "visual impact only" }, + { 0,FZM_GAMEPLAY, "gameplay impact" }, { 0,FZM_M_TYPE, 0 }, { 0,FZM_BATTLE, "battle only" }, @@ -631,6 +669,31 @@ ccp GetFeaturesEffectsByOffset ( uint offset ) return GetFeaturesEffects(((u8*)fs)[offset]); } +//----------------------------------------------------------------------------- + +void NormalizeFeatures ( features_szs_t *fs ) +{ + if (fs) + { + const features_szs_t *mode = GetFeaturesModes(); + for ( int idx = 2; idx < sizeof(features_szs_t); idx++ ) + { + const u8 md = ((u8*)mode)[idx]; + + u8 *ptr = ((u8*)fs) + idx; + u8 val = *ptr & FZV_M_VALUE; + if ( val >= FZV_IMPACT ) + { + if ( md & FZM_GAMEPLAY ) + val = FZV_IMPACT | md & FZV_M_OPTIONS; + else + val = FZV_NO_IMPACT; + } + *ptr = val; + } + } +} + // /////////////////////////////////////////////////////////////////////////////// /////////////// lecode extension LEX /////////////// @@ -745,6 +808,8 @@ static void FixLEXElement_SET1 ( lex_set1_t *set1 ) if ( !isnormal(f) || f < 1.0 ) write_bef4(set1->item_factor.v+i,1.0); } + + set1->start_item = set1->start_item > 0; } //----------------------------------------------------------------------------- @@ -1105,6 +1170,10 @@ static uint GetLexFeaturesSET1 ( const lex_element_t *elem ) have_feat |= 1 << HAVELEXF_ITEM_RANGE; } } + + if ( size > offsetof(lex_set1_t,start_item) && set1->start_item ) + have_feat |= 1 << HAVELEXF_START_ITEM; + return have_feat; } @@ -1156,6 +1225,7 @@ const have_lex_info_t have_lex_feat_info[HAVELEXF__N] = { HAVELEXF_ITEM_RANGE, "itempos", 0 }, { HAVELEXF_CANNON, "cannon", 0 }, { HAVELEXF_HIDE_POS, "hipt", 0 }, + { HAVELEXF_START_ITEM, "startitem", 0 }, //--- add new sections here (order is important) }; @@ -1665,16 +1735,22 @@ static enumError ScanLEXElement_SET1 //--- setup data - lex_set1_t set1; - memset(&set1,0,sizeof(set1)); + lex_set1_t set1 = { .item_factor.v = {1,1,1} }; + //HexDump16(stdout,0,0,&set1,sizeof(set1)); const ScanParam_t ptab[] = { { "ITEM-POS-FACTOR", SPM_FLOAT3_BE, &set1.item_factor }, - { "TEST1", SPM_U8, set1.test+0 }, - { "TEST2", SPM_U8, set1.test+1 }, - { "TEST3", SPM_U8, set1.test+2 }, - { "TEST4", SPM_U8, set1.test+3 }, + { "START-ITEM", SPM_U8, &set1.start_item }, + + // renamed at 2021-05-12 + { "TEST1", SPM_U8, &set1.start_item }, // [[obsolete]] 2022 + { "TEST2", SPM_U8, &set1.test_0d }, // [[obsolete]] 2022 + { "TEST_0D", SPM_U8, &set1.test_0d }, + { "TEST3", SPM_U8, &set1.test_0e }, // [[obsolete]] 2022 + { "TEST_0E", SPM_U8, &set1.test_0e }, + { "TEST4", SPM_U8, &set1.test_0f }, // [[obsolete]] 2022 + { "TEST_0F", SPM_U8, &set1.test_0f }, {0} }; @@ -2257,13 +2333,15 @@ static enumError SaveTextLEX_SET1 ,bef4(&set1->item_factor.x) ,bef4(&set1->item_factor.y) ,bef4(&set1->item_factor.z) + ,set1->start_item ); - if (*(u32*)set1->test) + if ( set1->test_0d || set1->test_0e || set1->test_0f ) fprintf(f,text_lex_elem_set1_develop_cr - ,set1->test[0],set1->test[1],set1->test[2],set1->test[3] + ,set1->test_0d + ,set1->test_0e + ,set1->test_0f ); - if ( size > sizeof(lex_set1_t) ) { fputs("\n# Hex dump for unknown settings:\n",f); diff --git a/project/src/lib-lex.h b/project/src/lib-lex.h index 96c2d4f..da54ab3 100644 --- a/project/src/lib-lex.h +++ b/project/src/lib-lex.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -62,6 +62,8 @@ typedef struct features_szs_t u16 size_be; // size of features_szs_t in big endian // == version number + // ==> see enum features_szs_value_t for following feature values + //--- SZS files (initial list) u8 f_lex; // HAVESZS_COURSE_LEX @@ -77,6 +79,7 @@ typedef struct features_szs_t //--- KMP features (initial list) + u8 kmp_goomba_size; // HAVEKMP_GOOMBA_SIZE u8 kmp_woodbox_ht; // HAVEKMP_WOODBOX_HT u8 kmp_mushroom_car; // HAVEKMP_MUSHROOM_CAR u8 kmp_penguin_pos; // HAVEKMP_PENGUIN_POS @@ -104,6 +107,7 @@ typedef struct features_szs_t u8 lex_item_range; // HAVELEXF_ITEM_RANGE u8 lex_cannon; // HAVELEXF_CANNON u8 lex_hide_pos; // HAVELEXF_HIDE_POS + u8 lex_start_item; // HAVELEXF_START_ITEM //--- new files and features will be appended here } @@ -128,10 +132,10 @@ void PrintFeaturesSZS ( PrintScript_t *ps, // valid output definition const features_szs_t *fs, // valid source - bool is_lex, // TRUE: Create output for a LEX file + bool is_lex, // TRUE: Create output for a LEX file int comments, // >0: add extended comments int print_modes, // >0: append ",MODES" - u8 include, // print only if all bits match + u8 include, // print only if all bits match u8 exclude // exclude if any bit match ); @@ -151,27 +155,69 @@ typedef enum features_szs_mode_t FZM_RACING = 0x10, // R: impact on racings FZM_TIMETRIAL = 0x20, // T: impact on time trial - FZM_OFFLINE = 0x40, // L: impact on offline battles/races + FZM_OFFLINE = 0x40, // L: impact on local battles/races FZM_ONLINE = 0x80, // O: impact on online battles/races FZM_M_KIND = FZM_VISUAL | FZM_GAMEPLAY, FZM_M_TYPE = FZM_BATTLE | FZM_RACING, FZM_M_WHERE = FZM_TIMETRIAL | FZM_OFFLINE | FZM_ONLINE, - FZM__MASK = FZM_SECTION | FZM_M_KIND | FZM_M_TYPE | FZM_M_WHERE, + FZM__MASK = FZM_SECTION | FZM_M_KIND | FZM_M_TYPE | FZM_M_WHERE, } features_szs_mode_t; //----------------------------------------------------------------------------- +// [[features_szs_value_t]] + +typedef enum features_szs_value_t +{ + // values for struct features_szs_t + + FZV_UNDEF, // feature not defined + FZV_NO_IMPACT, // feature defined but without gameplay impact + FZV_MAYBE_IMPACT, // feature defined, gameplay impact is possible + FZV_IMPACT, // feature defined, with gameplay impact + + // masks for struct features_szs_t + + FZV_M_VALUE = 7, // mask for values + FZV_M_OPTIONS = FZM_M_WHERE, // mask for options +} +features_szs_value_t; + +//----------------------------------------------------------------------------- ccp GetFeaturesMode ( features_szs_mode_t mode ); ccp GetFeaturesEffects ( features_szs_mode_t mode ); ccp GetFeaturesEffectsByOffset ( uint offset ); +void NormalizeFeatures ( features_szs_t *fs ); const features_szs_t * GetFeaturesModes(); // /////////////////////////////////////////////////////////////////////////////// +/////////////// check_features_szs_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[check_features_szs_t]] + +typedef struct check_features_szs_t +{ + bool have_features; // true: szs has LEX/FEA0 section + bool need_features; // true: szs needs a LEX/FEA0 section + bool wrong_features; // true: 'current' and 'correct' differ + + features_szs_t current; // current features + features_szs_t correct; // correct features +} +check_features_szs_t __attribute__((aligned(4))); + +//----------------------------------------------------------------------------- + +void SetupCheckFeaturesSZS + ( check_features_szs_t *cfs, const struct szs_have_t *have, bool is_lex ); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// lecode extension LEX /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -209,6 +255,7 @@ typedef enum have_lex_feat_t HAVELEXF_ITEM_RANGE, HAVELEXF_CANNON, HAVELEXF_HIDE_POS, + HAVELEXF_START_ITEM, //--- add new elements here (order is important) HAVELEXF__N } @@ -274,8 +321,11 @@ __attribute__ ((packed)) lex_element_t; typedef struct lex_set1_t { - float3 item_factor; // factor for item positions, always >=1.0 - u8 test[4]; // 4 test values (TEST1..TEST4) + /*00*/ float3 item_factor; // factor for item positions, always >=1.0 + /*0c*/ u8 start_item; // 1: player can get an item before start (hint only) + /*0d*/ u8 test_0d; // reserved + /*0e*/ u8 test_0e; // reserved + /*0f*/ u8 test_0f; // reserved } __attribute__ ((packed,aligned(4))) lex_set1_t; diff --git a/project/src/lib-mdl.c b/project/src/lib-mdl.c index 88bd7cd..7b3650f 100644 --- a/project/src/lib-mdl.c +++ b/project/src/lib-mdl.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -3874,6 +3874,7 @@ static int ana_slot42_brres u8 *data = it->szs->data + it->off; if ( !term + && it->off +4 <= it->size && ( it->fform == FF_MDL || it->fform == FF_UNKNOWN && !memcmp(data,MDL_MAGIC,4) ) && !strcasecmp(it->name,"course") diff --git a/project/src/lib-mdl.h b/project/src/lib-mdl.h index bf0142f..b8f1e80 100644 --- a/project/src/lib-mdl.h +++ b/project/src/lib-mdl.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-minigame.c b/project/src/lib-minigame.c index 2c4b53f..a9ae7a6 100644 --- a/project/src/lib-minigame.c +++ b/project/src/lib-minigame.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -173,7 +173,7 @@ static void limit_duration ( be16_t *dest ) const u16 limith = opt_kmg_limit; const u16 limitn = htons(limith); - + u16 *end; for ( end = dest + 10*11; dest < end; dest++ ) if ( ntohs(*dest) > limith ) @@ -844,7 +844,7 @@ int ScanOptKmgLimit ( ccp arg ) return 1; } - opt_kmg_limit = num < 0 ? 0 : num > 0xffff ? 0xffff : num; + opt_kmg_limit = num < 0 ? 0 : num > 0xffff ? 0xffff : num; return 0; } diff --git a/project/src/lib-numeric.c b/project/src/lib-numeric.c index b868f84..7e47199 100644 --- a/project/src/lib-numeric.c +++ b/project/src/lib-numeric.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-numeric.h b/project/src/lib-numeric.h index a7c741a..c52261b 100644 --- a/project/src/lib-numeric.h +++ b/project/src/lib-numeric.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -2015,6 +2015,25 @@ enumError ScanUValueSI //----------------------------------------------------------------------------- +enumError ScanIntValueSI +( + ScanInfo_t * si, // valid data + int * num // return value +); + +//----------------------------------------------------------------------------- + +static inline enumError ScanUIntValueSI +( + ScanInfo_t * si, // valid data + uint * num // return value +) +{ + return ScanIntValueSI(si,(int*)num); +} + +//----------------------------------------------------------------------------- + enumError ScanDValueSI ( ScanInfo_t * si, // valid data diff --git a/project/src/lib-object.c b/project/src/lib-object.c index 9e93781..23ffcdd 100644 --- a/project/src/lib-object.c +++ b/project/src/lib-object.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-object.h b/project/src/lib-object.h index ff96b32..7aa9f95 100644 --- a/project/src/lib-object.h +++ b/project/src/lib-object.h @@ -18,7 +18,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -151,6 +151,7 @@ typedef enum have_kmp_obj_t HAVEKMP_COOB_R, // Conditional Out of Bounds by Riidefi HAVEKMP_COOB_K, // Conditional Out of Bounds by kHacker35000vr HAVEKMP_UOOB, // Unconditional Out of Bounds + HAVEKMP_GOOMBA_SIZE, // 0x191:goomba (kuribo) with scale !0 1.00 HAVEKMP__N } __attribute__ ((packed)) have_kmp_obj_t; diff --git a/project/src/lib-objflow.c b/project/src/lib-objflow.c index 5cda47a..d7cb1cc 100644 --- a/project/src/lib-objflow.c +++ b/project/src/lib-objflow.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-pack.c b/project/src/lib-pack.c index ecc57d9..9473108 100644 --- a/project/src/lib-pack.c +++ b/project/src/lib-pack.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-pack.h b/project/src/lib-pack.h index dc01a00..aa6ab75 100644 --- a/project/src/lib-pack.h +++ b/project/src/lib-pack.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-parser-func.c b/project/src/lib-parser-func.c index d8e1e48..6854619 100644 --- a/project/src/lib-parser-func.c +++ b/project/src/lib-parser-func.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-parser.c b/project/src/lib-parser.c index df0cc21..f375395 100644 --- a/project/src/lib-parser.c +++ b/project/src/lib-parser.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -5972,7 +5972,7 @@ void CalcExpr FreeV(dest); dest->mode = VAR_INT; dest->i = op_id == OPI_NEQNEQ; - return; + return; case OPI_EQ: // S case OPI_NEQ: // S @@ -7355,6 +7355,46 @@ enumError ScanUValueSI /////////////////////////////////////////////////////////////////////////////// +enumError ScanIntValueSI +( + ScanInfo_t * si, // valid data + int * num // return value +) +{ + DASSERT(si); + DASSERT(num); + + DEFINE_VAR(var); + enumError err = ScanValueSI(si,&var); + SkipCharSI(si,','); + + switch(var.mode) + { + case VAR_UNSET: + *num = 0; + return err; + + case VAR_INT: + *num = var.i; + return err; + + case VAR_DOUBLE: + case VAR_VECTOR: + *num = double2int(var.d); + return err; + + case VAR_STRING: + *num = var.str_len ? str2l(var.str,0,10) : 0; + break; + } + + // only needed to avoid compiler warnings + *num = 0; + return err; +} + +/////////////////////////////////////////////////////////////////////////////// + enumError ScanDValueSI ( ScanInfo_t * si, // valid data diff --git a/project/src/lib-pat.c b/project/src/lib-pat.c index 0a37c90..535c8d7 100644 --- a/project/src/lib-pat.c +++ b/project/src/lib-pat.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-pat.h b/project/src/lib-pat.h index 7157544..eb8e5a9 100644 --- a/project/src/lib-pat.h +++ b/project/src/lib-pat.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-rarc.c b/project/src/lib-rarc.c index 3088ddf..7e4b1f5 100644 --- a/project/src/lib-rarc.c +++ b/project/src/lib-rarc.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-rarc.h b/project/src/lib-rarc.h index 3514668..dc793ec 100644 --- a/project/src/lib-rarc.h +++ b/project/src/lib-rarc.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-rkc.c b/project/src/lib-rkc.c index c1e4afb..8e8d103 100644 --- a/project/src/lib-rkc.c +++ b/project/src/lib-rkc.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-rkc.h b/project/src/lib-rkc.h index 53be8ec..ec44445 100644 --- a/project/src/lib-rkc.h +++ b/project/src/lib-rkc.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-rkg.c b/project/src/lib-rkg.c index d89dd7c..2838c65 100644 --- a/project/src/lib-rkg.c +++ b/project/src/lib-rkg.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-rkg.h b/project/src/lib-rkg.h index d82245c..4c9737f 100644 --- a/project/src/lib-rkg.h +++ b/project/src/lib-rkg.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-staticr.c b/project/src/lib-staticr.c index 10e0ff1..eef7e60 100644 --- a/project/src/lib-staticr.c +++ b/project/src/lib-staticr.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -733,6 +733,7 @@ const str_server_patch_t ServerPatch[217+1] = static const addr_port_t *addr_port = addr_port_0; static int addr_port_records = sizeof(addr_port_0)/sizeof(*addr_port_0); +ccp addr_port_file = "<intern>"; //----------------------------------------------------------------------------- @@ -810,6 +811,7 @@ enumError LoadAddrPortDB ( ccp path1, int silent ) PrintTimeByFormat("%F",version->timestamp), version->revision ); + addr_port_file = STRDUP(path); addr_port_records = n_records; addr_port = (addr_port_t*)mgr.data; memcpy(&addr_port_version,version,sizeof(addr_port_version)); @@ -834,7 +836,7 @@ void SetupAddrPortDB() static bool done = false; if (!done) { - addr_port_version.revision = REVISION_NUM; + addr_port_version.revision = REVISION_NUM; if ( addr_port_version.timestamp < BINTIME ) addr_port_version.timestamp = BINTIME; @@ -1922,7 +1924,7 @@ const rel_info_t * GetInfoREL ( str_mode_t mode ) default: return 0; } - DASSERT(ri) + DASSERT(ri); if (!ri->sect[0].addr) { for ( dol_sect_info_t *ptr = ri->sect; ptr->section >= 0; ptr++ ) @@ -2872,6 +2874,7 @@ const addr_port_t * GetPortingRecord ( str_mode_t mode, u32 addr ) const int region = mode - STR_ZBI_FIRST; const addr_port_t **base = *list_ptr; + #if 1 while ( beg <= end ) { const uint idx = (beg+end)/2; @@ -2885,6 +2888,28 @@ const addr_port_t * GetPortingRecord ( str_mode_t mode, u32 addr ) else return p; } + #else + while ( beg <= end ) + { + const uint idx = (beg+end)/2; + const addr_port_t *p = base[idx]; + const u32 raddr = p->addr[region]; + + if ( addr < raddr ) + end = idx - 1 ; + else if ( addr > raddr ) + beg = idx + 1; + else + break; + } + + const addr_port_t *p = base[beg]; + PRINT1("%u/%u: %08x + %06x + %06x, %08x\n", + beg, addr_port_records, + p->addr[region], p->size1, p->size2, + (p[1]).addr[region] ); + return p; + #endif return 0; } @@ -6976,6 +7001,7 @@ wcode_t opt_wcode = WCODE_AUTO; ccp opt_port_db = 0; ccp opt_order = 0; bool opt_no_0x = false; +bool opt_upper = false; /////////////////////////////////////////////////////////////////////////////// diff --git a/project/src/lib-staticr.h b/project/src/lib-staticr.h index 157498b..1bdc247 100644 --- a/project/src/lib-staticr.h +++ b/project/src/lib-staticr.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -527,7 +527,7 @@ extern const char rel_section_name[REL_SECT__N+1][5]; typedef struct rel_info_t { u32 offset_sect; // offset of section data, always 0xd4 - u32 fix_size; // OSLinkFixed (and of reserved mem) + u32 fix_size; // OSLinkFixed (and of reserved mem) u32 bss_size; // size of BSS, always 0x78b0 u32 load_addr; // address, at which file is loaded @@ -674,8 +674,8 @@ __attribute__ ((packed)) addr_port_t; typedef struct addr_port_version_t { - char magic[8]; // ADDR_PORT_MAGIC - u32 db_version; // ADDR_PORT_DB_VERSION + char magic[8]; // ADDR_PORT_MAGIC + u32 db_version; // ADDR_PORT_DB_VERSION u32 revision; // REVISION_NUM u32 timestamp; // time(0) u32 n_records; // number of records @@ -686,6 +686,7 @@ __attribute__ ((packed)) addr_port_version_t; void SetupAddrPortDB(); const addr_port_version_t * GetAddrPortVersion(); +extern ccp addr_port_file; const addr_port_t * GetPortingRecord ( str_mode_t mode, u32 addr ); const addr_port_t * GetPortingRecordPAL ( u32 addr ); @@ -940,6 +941,7 @@ extern char patch_bt_str[2]; extern ccp opt_port_db; extern ccp opt_order; extern bool opt_no_0x; +extern bool opt_upper; int ScanOptVS ( bool is_bt, bool allow_2, ccp arg ); diff --git a/project/src/lib-std.c b/project/src/lib-std.c index 97323ba..3200eb4 100644 --- a/project/src/lib-std.c +++ b/project/src/lib-std.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -63,6 +63,7 @@ #include "db-mkw.h" #include "crypt.h" #include "logo.inc" +#include "sha1-db.inc" #if defined(TEST) && !defined(__APPLE__) && !defined(__CYGWIN__) #include <mcheck.h> @@ -77,7 +78,6 @@ ccp opt_config = 0; ccp tool_name = "?"; ccp std_share_path = 0; ccp share_path = 0; -volatile int SIGINT_level = 0; volatile int verbose = 0; volatile int logging = 0; bool allow_all = false; @@ -91,12 +91,14 @@ int testmode = 0; int force_count = 0; uint opt_tiny = 0; bool force_kmp = false; +int disable_checks = 0; OffOn_t opt_battle_mode = OFFON_AUTO; OffOn_t opt_export_flags = OFFON_AUTO; int opt_route_options = 0; OffOn_t opt_wim0 = OFFON_AUTO; ccp opt_source = 0; StringField_t source_list = {0}; +ccp opt_reference = 0; ccp opt_dest = 0; bool opt_mkdir = false; bool opt_overwrite = false; @@ -376,6 +378,9 @@ void SetupLib ( int argc, char ** argv, ccp tname, ccp tvers, ccp ttitle ) GetTimerMSec(); SetupColors(); + AddDefaultToSizeofInfoMgr(); + //AddListToSizeofInfoMgr(si_list); + #if defined(TEST) && !defined(__APPLE__) && !defined(__CYGWIN__) mtrace(); #endif @@ -459,6 +464,12 @@ void SetupLib ( int argc, char ** argv, ccp tname, ccp tvers, ccp ttitle ) TRACE_SIZEOF(exmem_key_t); TRACE_SIZEOF(exmem_list_t); + TRACE("- sha1\n"); + TRACE_SIZEOF(sha1_hash_t); + TRACE_SIZEOF(sha1_hex_t); + TRACE_SIZEOF(sha1_type_t); + TRACE_SIZEOF(sha1_db_t); + TRACE("- arch\n"); TRACE_SIZEOF(yaz0_header_t); TRACE_SIZEOF(wbz_header_t); @@ -949,6 +960,27 @@ ccp LibGetErrorText ( int stat, ccp ret_not_found ) return ret_not_found; } +/////////////////////////////////////////////////////////////////////////////// + +void SetupPager() +{ + if (isatty(fileno(stdout))) + { + opt_colorize = 1; + SetupColors(); + StdoutToPager(); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void PrintHelpColor ( const InfoUI_t * iu ) +{ + SetupPager(); + PrintHelp(iu,stdout,0,"HELP",0,URI_HOME,first_param?first_param->arg:0); + ClosePager(); +} + // /////////////////////////////////////////////////////////////////////////////// /////////////// compatibility /////////////// @@ -1032,6 +1064,97 @@ char * PrintOptCompatible() // /////////////////////////////////////////////////////////////////////////////// +/////////////// warnings /////////////// +/////////////////////////////////////////////////////////////////////////////// + +warn_mode_t WARN_MODE = WARN_M_DEFAULT; + +/////////////////////////////////////////////////////////////////////////////// + +static const KeywordTab_t opt_warn_tab[] = +{ + { 0, "NONE", "OFF", WARN_M_ALL | WARN_F_HIDE }, + { WARN_M_DEFAULT, "DEFAULT", 0, WARN_M_ALL | WARN_F_HIDE }, + { WARN_M_ALL, "ALL", 0, WARN_M_ALL }, + + { WARN_INVALID_OFFSET, "INVALID-OFFSET", 0, 0 }, + + { WARN_LOG, "LOG", 0, 0 }, + { WARN_TEST, "TEST", "T", 0 }, + + { 0,0,0,0 } +}; + +/////////////////////////////////////////////////////////////////////////////// + +int ScanOptWarn ( ccp arg ) +{ + if (!arg) + return 0; + + s64 stat = ScanKeywordList(arg,opt_warn_tab,0,true,0,WARN_MODE, + "Option --warn",ERR_SYNTAX); + if ( stat == -1 ) + return 1; + + WARN_MODE = stat; + if ( WARN_MODE & WARN_LOG ) + { + char buf[200]; + PrintWarnMode(buf,sizeof(buf),WARN_MODE); + fprintf(stderr,"WARN MODE: %s\n",buf); + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +uint PrintWarnMode ( char *buf, uint bufsize, warn_mode_t mode ) +{ + DASSERT(buf); + DASSERT(bufsize>10); + char *dest = buf; + char *end = buf + bufsize - 1; + + mode = mode & WARN_M_ALL | WARN_F_HIDE; + warn_mode_t mode1 = mode; + + const KeywordTab_t *ct; + for ( ct = opt_warn_tab; ct->name1 && dest < end; ct++ ) + { + if ( ct->opt & WARN_F_HIDE ) + continue; + + if ( ct->opt ? (mode & ct->opt) == ct->id : mode & ct->id ) + { + if ( dest > buf ) + *dest++ = ','; + dest = StringCopyE(dest,end,ct->name1); + mode &= ~(ct->id|ct->opt); + } + } + + if ( mode1 == (WARN_M_DEFAULT|WARN_F_HIDE) ) + dest = StringCopyE(dest,end," (default)"); + else if (!mode1) + dest = StringCopyE(dest,end,"(none)"); + + *dest = 0; + return dest-buf; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp GetWarnMode() +{ + static char buf[200] = {0}; + if (!*buf) + PrintWarnMode(buf,sizeof(buf),WARN_MODE); + return buf; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// output_mode_t /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -3703,6 +3826,7 @@ SortMode_t GetSortMode case SORT_NONE: case SORT_INAME: case SORT_OFFSET: + case SORT_SIZE: case SORT_U8: case SORT_PACK: case SORT_BRRES: @@ -3740,8 +3864,10 @@ SortMode_t GetSortMode static const KeywordTab_t opt_sort_tab[] = { { SORT_NONE, "NONE", "0", 0 }, - { SORT_INAME, "NAME", "INAME", 0 }, + { SORT_INAME, "NAME", "N", 0 }, + { SORT_INAME, "INAME", 0, 0 }, { SORT_OFFSET, "OFFSET", 0, 0 }, + { SORT_SIZE, "SIZE", "S", 0 }, { SORT_U8, "U8", 0, 0 }, { SORT_PACK, "PACK", 0, 0 }, @@ -3938,7 +4064,7 @@ enumError cmd_install() printf("\nInstall files to the share directory: %s\n",share_path); if ( !share_path || !*share_path ) return ERR_ERROR; // should never happen - + char destbuf[PATH_MAX]; enumError max_err = ERR_OK; @@ -5170,34 +5296,49 @@ file_format_t RepairMagicByOpt // /////////////////////////////////////////////////////////////////////////////// -/////////////// misc /////////////// +/////////////// SHA1 support /////////////// /////////////////////////////////////////////////////////////////////////////// -void SetupPrintScriptByOptions ( PrintScript_t *ps ) +const sha1_db_t * GetSha1DbHex ( sha1_type_t type, ccp hex, ccp end ) { - DASSERT(ps); + sha1_hash_t hash; + Sha1Hex2Bin(hash,hex,end); + return GetSha1DbBin(type,hash); +} - InitializePrintScript(ps); - ps->force_case = opt_case; - ps->create_array = script_array > 0; - ps->var_name = script_varname ? script_varname : "res"; - ps->var_prefix = script_varname ? script_varname : "res_"; - ps->eq_tabstop = 2; - ps->ena_empty = brief_count < 2; - ps->ena_comments = brief_count < 1; +/////////////////////////////////////////////////////////////////////////////// - switch(script_fform) +const sha1_db_t * GetSha1DbBin ( sha1_type_t type, cvp hash ) +{ + int beg = 0; + int end = SHA1_DB_N -1; + while ( beg <= end ) { - case FF_JSON: ps->fform = PSFF_JSON; break; - case FF_BASH: ps->fform = PSFF_BASH; break; - case FF_SH: ps->fform = PSFF_SH; break; - case FF_PHP: ps->fform = PSFF_PHP; break; - case FF_MAKEDOC: ps->fform = PSFF_MAKEDOC; break; - default: ps->fform = print_sections ? PSFF_CONFIG : PSFF_UNKNOWN; break; + const int idx = (beg+end)/2; + const int stat = memcmp(hash,sha1_db[idx].sha1,sizeof(sha1_db->sha1)); + if ( stat < 0 ) + end = idx - 1 ; + else if ( stat > 0 ) + beg = idx + 1; + else + { + const sha1_db_t *res = sha1_db + idx; + return res->type & type ? res : 0; + } } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +u8 GetSha1Slot ( sha1_type_t type, cvp hash ) +{ + const sha1_db_t *res = GetSha1DbBin(type,hash); + return res ? res->slot : 0; } /////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// void SHA1_to_ID ( sha1_id_t id, const sha1_hash_t hash ) { @@ -5228,6 +5369,44 @@ void SHA1_to_ID ( sha1_id_t id, const sha1_hash_t hash ) } /////////////////////////////////////////////////////////////////////////////// + +ccp GetSha1Data ( cvp data, uint size ) +{ + sha1_hash_t hash; + SHA1(data,size,hash); + return GetSha1Hex(hash); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// misc /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void SetupPrintScriptByOptions ( PrintScript_t *ps ) +{ + DASSERT(ps); + + InitializePrintScript(ps); + ps->force_case = opt_case; + ps->create_array = script_array > 0; + ps->var_name = script_varname ? script_varname : "res"; + ps->var_prefix = script_varname ? script_varname : "res_"; + ps->eq_tabstop = 2; + ps->ena_empty = brief_count < 2; + ps->ena_comments = brief_count < 1; + + switch(script_fform) + { + case FF_JSON: ps->fform = PSFF_JSON; break; + case FF_BASH: ps->fform = PSFF_BASH; break; + case FF_SH: ps->fform = PSFF_SH; break; + case FF_PHP: ps->fform = PSFF_PHP; break; + case FF_MAKEDOC: ps->fform = PSFF_MAKEDOC; break; + default: ps->fform = print_sections ? PSFF_CONFIG : PSFF_UNKNOWN; break; + } +} + +/////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool IsExtractEnabled() diff --git a/project/src/lib-std.h b/project/src/lib-std.h index 52d633a..f5d042d 100644 --- a/project/src/lib-std.h +++ b/project/src/lib-std.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -153,6 +153,12 @@ enum ccp LibGetErrorName ( int stat, ccp ret_not_found ); ccp LibGetErrorText ( int stat, ccp ret_not_found ); +void SetupPager(); +static inline void ClosePager() { CloseStdoutToPager(); } + +struct InfoUI_t; +void PrintHelpColor ( const struct InfoUI_t * iu ); + // /////////////////////////////////////////////////////////////////////////////// /////////////// compatibility /////////////// @@ -193,6 +199,53 @@ char * PrintOptCompatible(); // circ-buf // /////////////////////////////////////////////////////////////////////////////// +/////////////// warn_mode_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[warn_mode_t]] + +typedef enum warn_mode_t +{ + //--- general mode + + WARN_INVALID_OFFSET = 0x0000001, + + + //--- hidden options + + WARN_LOG = 1<<28, // enable kcl trace log to stdout + WARN_M_HIDDEN = WARN_LOG, + + WARN_F_HIDE = 1<<29, // help flag to hide modes in PrintWarnMode() + + + //--- test mode + + WARN_TEST = 1<<30, // reserved for testing + + + //--- summaries + + WARN_M_DEFAULT = WARN_INVALID_OFFSET // default settings + | 0, + + WARN_M_ALL = WARN_INVALID_OFFSET // all relevant bits + | 0, + + WARN_M_PRINT = WARN_M_ALL // all relevant bits for obj output + & ~WARN_M_HIDDEN, +} +warn_mode_t; + +//----------------------------------------------------------------------------- + +extern warn_mode_t WARN_MODE; + +int ScanOptWarn ( ccp arg ); +uint PrintWarnMode( char *buf, uint bufsize, warn_mode_t mode ); +ccp GetWarnMode(); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// warn level /////////////// /////////////////////////////////////////////////////////////////////////////// // [[WarnLevel_t]] Same as CTW: WarnLevel @@ -1131,6 +1184,7 @@ typedef enum SortMode_t SORT_INAME, // sort with strcasecmp() SORT_OFFSET, // sort by offset and size + SORT_SIZE, // sort by size (and offset) SORT_U8, // sort like Nintendo sort U8 archives SORT_PACK, // sort like Nintendo sort U8 archives (inexact) @@ -1159,6 +1213,7 @@ int ScanOptSort ( ccp arg ); /////////////////////////////////////////////////////////////////////////////// /////////////// slot mode /////////////// /////////////////////////////////////////////////////////////////////////////// +// [[SlotMode_t]] typedef enum SlotMode_t { @@ -1169,13 +1224,13 @@ typedef enum SlotMode_t //--- jobs - SLOTMD_RM_ICE = 0x0001, // rm ice.brres from SZS and KMP - SLOTMD_RM_SUNDS = 0x0002, // rm 'sunDS' and 'pylon01' from SZS and KMP - SLOTMD_RM_SHYGUY = 0x0004, // rm 'HeyhoShipGBA'+'HeyhoBallGBA' from SZS and KMP + SLOTMD_RM_ICE = 0x0001, // remove ice.brres from SZS+KMP + SLOTMD_RM_SUNDS = 0x0002, // remove 'sunDS' and 'pylon01' from SZS+KMP + SLOTMD_RM_SHYGUY = 0x0004, // remove 'HeyhoShipGBA'+'HeyhoBallGBA' from SZS+KMP SLOTMD_ADD_GICE = 0x0010, // add 'ice' to KMP/GOBJ SLOTMD_ADD_BICE = 0x0020, // add 'ice.brres' to SZS - SLOTMD_ADD_SHYGUY = 0x0040, // add 'HeyhoShipGBA' to SZS and KMP + SLOTMD_ADD_SHYGUY = 0x0040, // add 'HeyhoShipGBA' to SZS+KMP SLOTMD_ICE_TO_WATER = 0x0100, // change KCL flag 0x70 to 0x30 SLOTMD_WATER_TO_ICE = 0x0200, // change KCL flag 0x30 to 0x70 @@ -1607,6 +1662,7 @@ static inline uint GetStrIdxCountMIL ( const MemItem_t * mi ) //----------------------------------------------------------------------------- void SetSource ( ccp source ); +void SetReference ( ccp source ); void SetDest ( ccp dest, bool mkdir ); void CheckOptDest ( ccp default_dest, bool default_mkdir ); @@ -2008,6 +2064,42 @@ extern ccp autoadd_destination; // /////////////////////////////////////////////////////////////////////////////// +/////////////// SHA1 support /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[sha1_type_t]] + +typedef enum sha1_type_t +{ + SHA1T_KCL = 0x01, + SHA1T_KMP = 0x02, + SHA1T_MAP = 0x04, + + SHA1T__ALL = 0x07 +} +__attribute__ ((packed)) sha1_type_t; + +//----------------------------------------------------------------------------- +// [[sha1_db_t]] + +typedef struct sha1_db_t +{ + u8 slot; // 11..84, 111..125 + sha1_type_t type; + sha1_hash_t sha1; +} +__attribute__ ((packed)) sha1_db_t; + +//----------------------------------------------------------------------------- + +const sha1_db_t * GetSha1DbHex ( sha1_type_t type, ccp hex, ccp end ); +const sha1_db_t * GetSha1DbBin ( sha1_type_t type, cvp hash ); +u8 GetSha1Slot ( sha1_type_t type, cvp hash ); + +void SHA1_to_ID ( sha1_id_t id, const sha1_hash_t hash ); +ccp GetSha1Data ( cvp data, uint size ); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// misc /////////////// /////////////////////////////////////////////////////////////////////////////// // [[IsArena_t]] @@ -2073,8 +2165,6 @@ void AnalyzeKMP ( const struct kmp_t * kmp, ccp base_fname ); struct kcl_t; void AnalyzeKCL ( const struct kcl_t * kcl ); -void SHA1_to_ID ( sha1_id_t id, const sha1_hash_t hash ); - /////////////////////////////////////////////////////////////////////////////// bool IsExtractEnabled(); // return true if enabled and mkdir() successful @@ -2178,7 +2268,8 @@ typedef struct output_mode_t bool syntax; // true: print syntax infos u8 mode; // 1:list, 2:ref, 3:full bool cross_ref; // true: print cross reference infos - bool hex; // force hex out + bool hex; // true: force hex out + bool lecode; // true: print LE-CODE specific data } output_mode_t; @@ -2214,7 +2305,6 @@ extern ccp config_path; extern ccp tool_name; extern ccp std_share_path; extern ccp share_path; -extern volatile int SIGINT_level; extern volatile int verbose; extern volatile int logging; extern bool allow_all; @@ -2228,12 +2318,14 @@ extern int testmode; extern int force_count; extern uint opt_tiny; extern bool force_kmp; +extern int disable_checks; extern OffOn_t opt_battle_mode; extern OffOn_t opt_export_flags; extern int opt_route_options; extern OffOn_t opt_wim0; extern ccp opt_source; extern StringField_t source_list; +extern ccp opt_reference; extern ccp opt_dest; extern bool opt_mkdir; extern bool opt_overwrite; diff --git a/project/src/lib-szs-create.c b/project/src/lib-szs-create.c index 163d2c2..9463e5b 100644 --- a/project/src/lib-szs-create.c +++ b/project/src/lib-szs-create.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -1317,7 +1317,7 @@ void FindSpecialFilesSZS if ( !strcasecmp(fname,have_szs_file[i]) ) { const BZ2Manager_t *bm = GetCommonBZ2Manager(have_szs_fform[i]); - const have_file_mode_t hfm = + const have_file_mode_t hfm = bm && file->size == bm->size && !memcmp( file->data ? file->data : szs->data + file->offset, @@ -3146,6 +3146,9 @@ int CheckSZS { DASSERT(szs); PRINT("CheckSZS(%d,%d)\n",szs_mode,sub_mode); + if ( disable_checks > 0 ) + return 0; + szs_mode = GetMainCheckMode(szs_mode,true); sub_mode = GetSubCheckMode(sub_mode,true); @@ -4958,6 +4961,8 @@ void AnalyseSZS SHA1(szs->course_kmp_data,szs->course_kmp_size,sha1_data.hash); Sha1Bin2Hex(as->sha1_kmp,sha1_data.hash); memcpy(as->sha1_kmp_norm,as->sha1_kmp,sizeof(as->sha1_kmp_norm)); + as->sha1_kmp_slot = as->sha1_kmp_norm_slot + = GetSha1Slot(SHA1T_KMP,sha1_data.hash); kmp_t kmp; InitializeKMP(&kmp); @@ -4979,6 +4984,7 @@ void AnalyseSZS SHA1(szs->course_kmp_data,szs->course_kmp_size,sha1_data.hash); Sha1Bin2Hex(as->sha1_kmp_norm,sha1_data.hash); + as->sha1_kmp_norm_slot = GetSha1Slot(SHA1T_KMP,sha1_data.hash); stgi->lap_count = as->lap_count; stgi->speed_mod = as->speed_mod; @@ -5050,6 +5056,7 @@ void AnalyseSZS || szs->have.kmp[HAVEKMP_MUSHROOM_CAR] || szs->have.kmp[HAVEKMP_PENGUIN_POS] || szs->have.kmp[HAVEKMP_EPROP_SPEED] + || szs->have.kmp[HAVEKMP_GOOMBA_SIZE] ) { ct_dest = StringCopyE(ct_dest,ct_end,",gobj"); @@ -5108,6 +5115,7 @@ void AnalyseSZS { SHA1(szs->course_kcl_data,szs->course_kcl_size,sha1_data.hash); Sha1Bin2Hex(as->sha1_kcl,sha1_data.hash); + as->sha1_kcl_slot = GetSha1Slot(SHA1T_KCL,sha1_data.hash); } else valid_track = false; @@ -5146,6 +5154,7 @@ void AnalyseSZS { SHA1(szs->map_model_data,szs->map_model_size,sha1_data.hash); Sha1Bin2Hex(as->sha1_minimap,sha1_data.hash); + as->sha1_minimap_slot = GetSha1Slot(SHA1T_MAP,sha1_data.hash); } else szs->warn_bits |= 1 << WARNSZS_NO_MINIMAP; @@ -5167,5 +5176,641 @@ void AnalyseSZS // /////////////////////////////////////////////////////////////////////////////// +/////////////// check texture hacks /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void PrepareCheckTextureSZS ( szs_file_t * szs ) +{ + DASSERT(szs); + + static kcl_flag_t *kcl_flag = 0; + if (!kcl_flag) + kcl_flag = CreatePatchFlagKCL(KCL_MODE|KCLMD_CLR_VISUAL,opt_slot,false); + + szs_iterator_t res; + int stat = FindFileSZS(szs,"course.kcl",0,false,&res); + if ( stat > 0 ) + { + kcl_analyze_t ka; + u8 *data = szs->data + res.off; + if ( IsValidKCL(&ka,data,res.size,res.size,res.path) < VALID_ERROR ) + { + const uint n_tri = ka.n[2]; + kcl_triangle_t *tri = (kcl_triangle_t*)( data + ka.off[2] ); + for ( int i = 0; i < n_tri; i++, tri++ ) + { + const kcl_flag_t flag = ntohs(tri->flag); + tri->flag = htons(kcl_flag[flag]); + if ( (flag&0x1f) == 0x12 ) // KCL flag 'force recalculation' + szs->check_enpt = true; + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +enumError CheckTextureRefSZS +( + // returns ERR_OK | ERR_DIFFER | ERR_NOTHING_TO_DO | ERR_NO_SOURCE_FOUND | >=ERR_ERROR + szs_file_t * szs2, // NULL or second szs to compare + ccp *status // not NULL: store status info here -> FreeString() + // if !opt_reference: *status=NULL +) +{ + DASSERT(szs2); + if (status) + { + FreeString(*status); + *status = 0; + } + + if ( !opt_reference || !*opt_reference ) + return ERR_NOTHING_TO_DO; + + static int err = -1; + static szs_file_t *ref_szs = 0; + + if ( err == -1 ) + { + ref_szs = CALLOC(1,sizeof(*ref_szs)); + err = LoadSZS(ref_szs,opt_reference,true,opt_ignore>0,true); + if (err) + { + ResetSZS(ref_szs); + FREE(ref_szs); + ref_szs = 0; + } + else + PrepareCheckTextureSZS(ref_szs); + } + + if ( err || !ref_szs ) + { + if (status) + *status = STRDUP("-1=err"); + return err; + } + + return szs2 ? CheckTextureSZS(ref_szs,szs2,status) : ERR_OK; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +#define KMP_POS_EPSILON 0.1 +#define KMP_ROT_EPSILON 0.05 +#define KMP_SCALE_EPSILON 0.01 + +//----------------------------------------------------------------------------- + +typedef struct check_texture_t +{ + char info_buf[200]; + char *info_ptr; + char *info_end; + + char kinfo_buf[20]; + char *kinfo_ptr; + char *kinfo_end; + + kmp_t kmp1, kmp2; + u8 check_route[0x100]; +} +check_texture_t; + +/////////////////////////////////////////////////////////////////////////////// + +static bool compare_texture_helper +( + szs_file_t *szs1, + szs_file_t *szs2, + ccp subfile, + check_texture_t *ck, + ccp msg +) +{ + szs_iterator_t res1, res2; + const int stat1 = FindFileSZS(szs1,subfile,0,false,&res1); + const int stat2 = FindFileSZS(szs2,subfile,0,false,&res2); + bool same = stat1 == stat2; + if ( same && stat1 > 0 ) + same = res1.size == res2.size + && !memcmp( szs1->data + res1.off, szs2->data + res2.off, res1.size ); + if ( !same && ck && msg ) + ck->info_ptr = StringCopyE(ck->info_ptr,ck->info_end,msg); + + return same; +} + +/////////////////////////////////////////////////////////////////////////////// + +static bool compare_kmp_ck ( check_texture_t *ck ) +{ + DASSERT(ck); + + if ( ck->kmp1.dlist[KMP_CKPH].used != ck->kmp2.dlist[KMP_CKPH].used + || ck->kmp1.dlist[KMP_CKPT].used != ck->kmp2.dlist[KMP_CKPT].used + ) + { + PRINT("N(CKPH)=%d,%d, N(CKPT)=%d,%d\n", + ck->kmp1.dlist[KMP_CKPH].used,ck->kmp2.dlist[KMP_CKPH].used, + ck->kmp1.dlist[KMP_CKPT].used,ck->kmp2.dlist[KMP_CKPT].used); + *ck->kinfo_ptr++ = 'c'; + return false; + } + + const kmp_ckph_entry_t *h1 = (kmp_ckph_entry_t*)ck->kmp1.dlist[KMP_CKPH].list; + const kmp_ckph_entry_t *h2 = (kmp_ckph_entry_t*)ck->kmp2.dlist[KMP_CKPH].list; + for ( int n = ck->kmp1.dlist[KMP_CKPH].used; n>0; n--, h1++, h2++ ) + if (memcmp(h1,h2,sizeof(*h1))) + { + *ck->kinfo_ptr++ = 'c'; + return false; + } + + const kmp_ckpt_entry_t *p1 = (kmp_ckpt_entry_t*)ck->kmp1.dlist[KMP_CKPT].list; + const kmp_ckpt_entry_t *p2 = (kmp_ckpt_entry_t*)ck->kmp2.dlist[KMP_CKPT].list; + for ( int n = ck->kmp1.dlist[KMP_CKPT].used; n>0; n--, p1++, p2++ ) + { + if ( p1->respawn != p2->respawn + || p1->mode != p2->mode + || p1->prev != p2->prev + || p1->next != p2->next + || fabs( p1->left[0] - p2->left[0] ) > KMP_POS_EPSILON + || fabs( p1->left[1] - p2->left[1] ) > KMP_POS_EPSILON + || fabs( p1->right[0] - p2->right[0] ) > KMP_POS_EPSILON + || fabs( p1->right[1] - p2->right[1] ) > KMP_POS_EPSILON + ) + { + PRINT("A: %2x %2x %2x %2x %10.3f %10.3f %10.3f %10.3f\n", + p1->respawn, p1->mode, p1->prev, p1->next, + p1->left[0], p1->left[1], p1->right[0], p1->right[1] ); + PRINT("B: %2x %2x %2x %2x %10.3f %10.3f %10.3f %10.3f\n", + p2->respawn, p2->mode, p2->prev, p2->next, + p2->left[0], p2->left[1], p2->right[0], p2->right[1] ); + *ck->kinfo_ptr++ = 'c'; + return false; + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +static const kmp_area_entry_t * next_area + ( const kmp_area_entry_t *p, const kmp_area_entry_t *e ) +{ + for ( ; p < e; p++ ) + if ( p->type == 3 || p->type == 4 || p->type >= 8 && p->type <= 10 ) + break; + return p; +} + +//----------------------------------------------------------------------------- + +static bool compare_kmp_area ( check_texture_t *ck ) +{ + DASSERT(ck); + + if ( ck->kmp1.dlist[KMP_AREA].used != ck->kmp2.dlist[KMP_AREA].used ) + { + *ck->kinfo_ptr++ = 'a'; + return false; + } + + const kmp_area_entry_t *p1 = (kmp_area_entry_t*)ck->kmp1.dlist[KMP_AREA].list; + const kmp_area_entry_t *e1 = p1 + ck->kmp1.dlist[KMP_AREA].used; + + const kmp_area_entry_t *p2 = (kmp_area_entry_t*)ck->kmp2.dlist[KMP_AREA].list; + const kmp_area_entry_t *e2 = p2 + ck->kmp2.dlist[KMP_AREA].used; + + for (;;) + { + p1 = next_area(p1,e1); + p2 = next_area(p2,e2); + if ( p1 >= e1 || p2 >= e2 ) + break; + + if ( memcmp( &p1->mode, &p2->mode, 4 ) + || memcmp( p1->setting, p2->setting, 8 ) + || fabs( p1->position[0] - p2->position[0] ) > KMP_POS_EPSILON + || fabs( p1->position[1] - p2->position[1] ) > KMP_POS_EPSILON + || fabs( p1->position[2] - p2->position[2] ) > KMP_POS_EPSILON + || fabs( p1->rotation[0] - p2->rotation[0] ) > KMP_ROT_EPSILON + || fabs( p1->rotation[1] - p2->rotation[1] ) > KMP_ROT_EPSILON + || fabs( p1->rotation[2] - p2->rotation[2] ) > KMP_ROT_EPSILON + || fabs( p1->scale[0] - p2->scale[0] ) > KMP_SCALE_EPSILON + || fabs( p1->scale[1] - p2->scale[1] ) > KMP_SCALE_EPSILON + || fabs( p1->scale[2] - p2->scale[2] ) > KMP_SCALE_EPSILON + ) + { + *ck->kinfo_ptr++ = 'a'; + return false; + } + + p1++; + p2++; + } + + if ( p1 != e1 || p2 != e2 ) + { + *ck->kinfo_ptr++ = 'a'; + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +static const kmp_gobj_entry_t * next_gobj + ( const kmp_gobj_entry_t *p, const kmp_gobj_entry_t *e ) +{ + for ( ; p < e; p++ ) + { + if ( p->obj_id >= GOBJ_MIN_DEF ) + break; + if ( p->pflags ) + { + const u16 relevant_id = GetRelevantObjectId(p->obj_id); + if ( ObjectInfo[relevant_id].flags & OBF_SOLID ) + break; + } + } + return p; +} + +//----------------------------------------------------------------------------- + +static bool compare_kmp_gobj ( check_texture_t *ck ) +{ + DASSERT(ck); + + SortGOBJ(&ck->kmp1,KSORT_XYZ); + SortGOBJ(&ck->kmp2,KSORT_XYZ); + + const kmp_gobj_entry_t *p1 = (kmp_gobj_entry_t*)ck->kmp1.dlist[KMP_GOBJ].list; + const kmp_gobj_entry_t *e1 = p1 + ck->kmp1.dlist[KMP_GOBJ].used; + + const kmp_gobj_entry_t *p2 = (kmp_gobj_entry_t*)ck->kmp2.dlist[KMP_GOBJ].list; + const kmp_gobj_entry_t *e2 = p2 + ck->kmp2.dlist[KMP_GOBJ].used; + + bool valid = true; + for (;;) + { + p1 = next_gobj(p1,e1); + p2 = next_gobj(p2,e2); + if ( p1 >= e1 || p2 >= e2 ) + break; + + if ( p1->route_id < sizeof(ck->check_route) ) + ck->check_route[p1->route_id] = 1; + + if ( valid && + ( memcmp( &p1->obj_id, &p2->obj_id, 4 ) + || memcmp( &p1->route_id, &p2->route_id, 20 ) + || fabs( p1->position[0] - p2->position[0] ) > KMP_POS_EPSILON + || fabs( p1->position[1] - p2->position[1] ) > KMP_POS_EPSILON + || fabs( p1->position[2] - p2->position[2] ) > KMP_POS_EPSILON + || fabs( p1->rotation[0] - p2->rotation[0] ) > KMP_ROT_EPSILON + || fabs( p1->rotation[1] - p2->rotation[1] ) > KMP_ROT_EPSILON + || fabs( p1->rotation[2] - p2->rotation[2] ) > KMP_ROT_EPSILON + || fabs( p1->scale[0] - p2->scale[0] ) > KMP_SCALE_EPSILON + || fabs( p1->scale[1] - p2->scale[1] ) > KMP_SCALE_EPSILON + || fabs( p1->scale[2] - p2->scale[2] ) > KMP_SCALE_EPSILON + )) + { + valid = false; + } + + p1++; + p2++; + } + + if ( !valid || p1 != e1 || p2 != e2 ) + { + *ck->kinfo_ptr++ = 'g'; + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +static bool compare_kmp_poti ( check_texture_t *ck ) +{ + DASSERT(ck); + + const int ng1 = ck->kmp1.dlist[KMP_POTI].used; + const int ng2 = ck->kmp2.dlist[KMP_POTI].used; + const int np1 = ck->kmp1.poti_point.used; + const int np2 = ck->kmp2.poti_point.used; + + if ( ng1 != ng2 || np1 != np2 ) + { + err: + *ck->kinfo_ptr++ = 'p'; + return false; + } + + const kmp_poti_group_t * pg1 = (kmp_poti_group_t*)ck->kmp1.dlist[KMP_POTI].list; + const kmp_poti_group_t * pg2 = (kmp_poti_group_t*)ck->kmp2.dlist[KMP_POTI].list; + const kmp_poti_point_t * pp1 = (kmp_poti_point_t*)ck->kmp1.poti_point.list; + const kmp_poti_point_t * pp2 = (kmp_poti_point_t*)ck->kmp2.poti_point.list; + + int i, gi; + for ( gi = i = 0; gi < ng1 && i < np1; gi++, pg1++, pg2++ ) + { + if (memcmp(pg1,pg2,sizeof(*pg1))) + goto err; + + const int en = pg1->n_point; + if ( gi < sizeof(ck->check_route) && !ck->check_route[gi] ) + { + pp1 += en; + pp2 += en; + continue; + } + + for ( int ei = 0; ei < en; ei++, i++, pp1++, pp2++ ) + { + if ( pp1->speed != pp2->speed + || pp1->unknown != pp2->unknown + || fabs( pp1->position[0] - pp2->position[0] ) > KMP_POS_EPSILON + || fabs( pp1->position[1] - pp2->position[1] ) > KMP_POS_EPSILON + || fabs( pp1->position[2] - pp2->position[2] ) > KMP_POS_EPSILON + ) + { + *ck->kinfo_ptr++ = 'p'; + return false; + } + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +static bool compare_kmp_stgi ( check_texture_t *ck ) +{ + DASSERT(ck); + + if ( ck->kmp1.dlist[KMP_STGI].used != ck->kmp2.dlist[KMP_STGI].used ) + { + *ck->kinfo_ptr++ = 's'; + return false; + } + + const kmp_stgi_entry_t *p1 = (kmp_stgi_entry_t*)ck->kmp1.dlist[KMP_STGI].list; + const kmp_stgi_entry_t *p2 = (kmp_stgi_entry_t*)ck->kmp2.dlist[KMP_STGI].list; + for ( int n = ck->kmp1.dlist[KMP_STGI].used; n>0; n--, p1++, p2++ ) + { + const u8 lap_count1 = p1->lap_count ? p1->lap_count : 3; + const u8 lap_count2 = p2->lap_count ? p2->lap_count : 3; + const u16 speed_mod1 = p1->speed_mod ? p1->speed_mod : 0x3f80; + const u16 speed_mod2 = p2->speed_mod ? p2->speed_mod : 0x3f80; + + if ( lap_count1 != lap_count2 + || speed_mod1 != speed_mod2 + || p1->pole_pos != p2->pole_pos + || p1->narrow_start != p2->narrow_start + ) + { + *ck->kinfo_ptr++ = 's'; + return false; + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +static bool compare_kmp_pt1 +( + check_texture_t *ck, + kmp_entry_t sect, // KMP_JGPT | KMP_CNPT | KMP_MSPT | KMP_KTPT + char msg +) +{ + DASSERT(ck); + + if ( ck->kmp1.dlist[sect].used != ck->kmp2.dlist[sect].used ) + { + *ck->kinfo_ptr++ = msg; + return false; + } + + const kmp_jgpt_entry_t *p1 = (kmp_jgpt_entry_t*)ck->kmp1.dlist[sect].list; + const kmp_jgpt_entry_t *p2 = (kmp_jgpt_entry_t*)ck->kmp2.dlist[sect].list; + for ( int n = ck->kmp1.dlist[sect].used; n>0; n--, p1++, p2++ ) + { + if ( p1->id != p2->id + || p1->effect != p2->effect + || fabs( p1->position[0] - p2->position[0] ) > KMP_POS_EPSILON + || fabs( p1->position[1] - p2->position[1] ) > KMP_POS_EPSILON + || fabs( p1->position[2] - p2->position[2] ) > KMP_POS_EPSILON + || fabs( p1->rotation[0] - p2->rotation[0] ) > KMP_ROT_EPSILON + || fabs( p1->rotation[1] - p2->rotation[1] ) > KMP_ROT_EPSILON + || fabs( p1->rotation[2] - p2->rotation[2] ) > KMP_ROT_EPSILON + ) + { + *ck->kinfo_ptr++ = msg; + return false; + } + } + + return true; +}; + +/////////////////////////////////////////////////////////////////////////////// + +static bool compare_kmp_pt2 +( + check_texture_t *ck, + kmp_entry_t sect_ph, // KMP_ENPH | KMP_ITPH + kmp_entry_t sect_pt, // KMP_ENPT | KMP_ITPT + char msg +) +{ + DASSERT(); + + if ( ck->kmp1.dlist[sect_ph].used != ck->kmp2.dlist[sect_ph].used + || ck->kmp1.dlist[sect_pt].used != ck->kmp2.dlist[sect_pt].used + ) + { + *ck->kinfo_ptr++ = msg; + return false; + } + + const kmp_enph_entry_t *h1 = (kmp_enph_entry_t*)ck->kmp1.dlist[sect_ph].list; + const kmp_enph_entry_t *h2 = (kmp_enph_entry_t*)ck->kmp2.dlist[sect_ph].list; + uint size = sizeof(*h1); + if ( opt_battle_mode <= OFFON_OFF ) + size -= sizeof(h1->setting); + for ( int n = ck->kmp1.dlist[sect_ph].used; n>0; n--, h1++, h2++ ) + if (memcmp(h1,h2,size)) + { + *ck->kinfo_ptr++ = msg; + return false; + } + + const kmp_enpt_entry_t *p1 = (kmp_enpt_entry_t*)ck->kmp1.dlist[sect_pt].list; + const kmp_enpt_entry_t *p2 = (kmp_enpt_entry_t*)ck->kmp2.dlist[sect_pt].list; + for ( int n = ck->kmp1.dlist[sect_pt].used; n>0; n--, p1++, p2++ ) + { + if ( p1->prop[0] != p2->prop[0] + || p1->prop[1] != p2->prop[1] + || fabs( p1->position[0] - p2->position[0] ) > KMP_POS_EPSILON + || fabs( p1->position[1] - p2->position[1] ) > KMP_POS_EPSILON + || fabs( p1->position[2] - p2->position[2] ) > KMP_POS_EPSILON + || fabs( p1->scale - p2->scale ) > KMP_SCALE_EPSILON + ) + { + *ck->kinfo_ptr++ = msg; + return false; + } + } + + return true; +}; + +/////////////////////////////////////////////////////////////////////////////// + +enumError CheckTextureSZS +( + // returns ERR_OK | ERR_DIFFER | ERR_ERROR + szs_file_t * szs1, // first szs to compare + szs_file_t * szs2, // second szs to compare + ccp *status // not NULL: store status info here -> FreeString() +) +{ + DASSERT(szs1); + DASSERT(szs2); + disable_checks++; + + if (status) + { + FreeString(*status); + *status = 0; + } + + check_texture_t ck; + memset(&ck,0,sizeof(ck)); + ck.info_end = ck.info_buf + sizeof(ck.info_buf) - 2; + ck.info_ptr = StringCopyE(ck.info_buf,ck.info_end,"0=no"); + char *info_start = ck.info_ptr; + + + //--- check KCL + + compare_texture_helper(szs1,szs2,"course.kcl",&ck,",KCL"); + + + //--- last check: KMP + + szs_iterator_t res1, res2; + int stat1 = FindFileSZS(szs1,"course.kmp",0,false,&res1); + int stat2 = FindFileSZS(szs2,"course.kmp",0,false,&res2); + + if ( stat1 != stat2 ) + ck.info_ptr = StringCopyE(ck.info_ptr,ck.info_end,",KMP"); + else if ( stat1 > 0 + && ( res1.size != res2.size + || memcmp( szs1->data + res1.off, szs2->data + res2.off, res1.size ))) + { + InitializeKMP(&ck.kmp1); + InitializeKMP(&ck.kmp2); + enumError err1 = ScanKMP(&ck.kmp1,false,szs1->data+res1.off,res1.size,0); + enumError err2 = ScanKMP(&ck.kmp2,false,szs2->data+res2.off,res2.size,0); + if ( err1 || err2 ) + ck.info_ptr = StringCopyE(ck.info_ptr,ck.info_end,",KMP"); + else + { + ck.kinfo_end = ck.kinfo_buf + sizeof(ck.kinfo_buf) - 2; + ck.kinfo_ptr = StringCopyE(ck.kinfo_buf,ck.kinfo_end,",KMP="); + char *kinfo_start = ck.kinfo_ptr; + + compare_kmp_area(&ck); // KMP_AREA (a) +//X // KMP_CAME (?) not needed + compare_kmp_ck(&ck); // KMP_CKPH + CKPT (c) + if ( szs1->check_enpt || szs2->check_enpt ) + compare_kmp_pt2(&ck,KMP_ENPH,KMP_ENPT,'e'); // KMP_ENPH + ENPT (e) + compare_kmp_gobj(&ck); // KMP_GOBJ (g) + compare_kmp_pt2(&ck,KMP_ITPH,KMP_ITPT,'i'); // KMP_ITPH+ ITPT (i) + compare_kmp_pt1(&ck,KMP_JGPT,'j'); // KMP_JGPT (j) + compare_kmp_pt1(&ck,KMP_KTPT,'k'); // KMP_KTPT (k) + compare_kmp_pt1(&ck,KMP_MSPT,'m'); // KMP_MSPT (m) + compare_kmp_pt1(&ck,KMP_CNPT,'n'); // KMP_CNPT (n) + compare_kmp_poti(&ck); // KMP_POTI (p) + compare_kmp_stgi(&ck); // KMP_STGI (s) + + //--- KMP summary + + if ( ck.kinfo_ptr > kinfo_start ) + { + *ck.kinfo_ptr = 0; + ck.info_ptr = StringCopyE(ck.info_ptr,ck.info_end,ck.kinfo_buf); + } + } + ResetKMP(&ck.kmp1); + ResetKMP(&ck.kmp2); + } + + + //--- check LEX + + compare_texture_helper(szs1,szs2,"course.lex",&ck,",LEX"); + + + //--- check MAP + + stat1 = FindFileSZS(szs1,"map_model.brres",0,false,&res1); + stat2 = FindFileSZS(szs2,"map_model.brres",0,false,&res2); + if ( stat1 > 0 && stat2 > 0 ) + { + sha1_hash_t hash; + SHA1( szs1->data+res1.off, res1.size, hash ); + int slot1 = GetSha1Slot(SHA1T_MAP,hash); + if (slot1) + { + SHA1( szs2->data+res2.off, res2.size, hash ); + int slot2 = GetSha1Slot(SHA1T_MAP,hash); + if ( slot2 && slot2 != slot1 ) + { + if ( slot2 > 100 ) + ck.info_ptr = snprintfE(ck.info_ptr,ck.info_end,",MAP=A%u",slot2%100); + else + ck.info_ptr = snprintfE(ck.info_ptr,ck.info_end,",MAP=%u",slot2); + } + } + } + + + //--- finalize + + disable_checks--; + if ( ck.info_ptr > info_start ) + { + if (status) + { + *info_start = ' '; + *status = STRDUP(ck.info_buf); + } + return ERR_DIFFER; + } + + if (status) + *status = STRDUP("1=yes"); + return ERR_OK; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// END /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/src/lib-szs.c b/project/src/lib-szs.c index edf4700..7230c73 100644 --- a/project/src/lib-szs.c +++ b/project/src/lib-szs.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -41,6 +41,7 @@ #include <sys/stat.h> #include "lib-szs.h" +#include "lib-kcl.h" #include "lib-rarc.h" #include "lib-pack.h" #include "lib-rkc.h" @@ -55,7 +56,8 @@ /////////////////////////////////////////////////////////////////////////////// /////////////// have_szs_file /////////////// /////////////////////////////////////////////////////////////////////////////// -// order is important, compare enum have_szs_file_t and ct.wiimm.de +// order is important, +// compare have_szs_name[], have_szs_file[], have_szs_fform[] and ct.wiimm.de const ccp have_szs_name[HAVESZS__N] = { @@ -101,6 +103,41 @@ const file_format_t have_szs_fform[HAVESZS__N] = // /////////////////////////////////////////////////////////////////////////////// +/////////////// have_attrib /////////////// +/////////////////////////////////////////////////////////////////////////////// + +const ccp have_attrib_name[HAVEATT__N] = +{ + "cheat", // HAVEATT_CHEAT + "edit", // HAVEATT_EDIT + "reverse", // HAVEATT_REVERSE +}; + +/////////////////////////////////////////////////////////////////////////////// + +ccp CreateSpecialInfoAttrib + ( have_attrib_t attrib, bool add_value, ccp return_if_empty ) +{ + static char buf[500]; + char *dest = buf; + + if (add_value) + dest = snprintfE( dest, buf+sizeof(buf), "%u=" , attrib ); + + uint i, mask; + ccp sep = ""; + for ( i = 0, mask = 1; i < HAVEATT__N; i++, mask <<= 1 ) + if ( attrib & mask ) + { + dest = StringCat2E(dest,buf+sizeof(buf),sep,have_attrib_name[i]); + sep = ","; + } + + return dest == buf ? return_if_empty : CopyCircBuf0(buf,dest-buf); +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// szs_file_t /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -3192,7 +3229,7 @@ static int iterate_sort_files { if ( it->off > it->szs->size || it->off + it->size > it->szs->size ) { - if ( it->size != M1(it->size) ) + if ( it->size != M1(it->size) && WARN_MODE & WARN_INVALID_OFFSET && verbose >= -2 ) ERROR0(ERR_WARNING, "Invalid offset [%x..%x, size=%zx] for subfile.\n" "=> File ignored: %s%s%s\n", @@ -3270,12 +3307,13 @@ static int iterate_sub_files { if ( it->off > it->szs->size || it->off + it->size > it->szs->size ) { - ERROR0(ERR_WARNING, - "Invalid offset [%x..%x, size=%zx] for subfile.\n" - "=> File ignored: %s%s%s\n", - it->off, it->off+it->size, it->szs->size, - it->szs->fname, *it->szs->fname ? "/" : "", - it->path ); + if ( WARN_MODE & WARN_INVALID_OFFSET && verbose >= -2 ) + ERROR0(ERR_WARNING, + "Invalid offset [%x..%x, size=%zx] for subfile.\n" + "=> File ignored: %s%s%s\n", + it->off, it->off+it->size, it->szs->size, + it->szs->fname, *it->szs->fname ? "/" : "", + it->path ); return 0; } @@ -3335,16 +3373,17 @@ static int iterate_sub_files return it->func_sub(it,term); } + /////////////////////////////////////////////////////////////////////////////// // [[IterateFilesSZS]] int IterateFilesSZS ( - szs_file_t * szs, // valid szs + szs_file_t *szs, // valid szs szs_iterator_func func, // call back function - void * param, // user defined parameter + void *param, // user defined parameter const iterator_param_t - *p_itpar, // NULL or iteration parameters + *p_itpar, // NULL or iteration parameters int recurse // 0:off, <0:unlimited, >0:max depth ) { @@ -3404,9 +3443,9 @@ int IterateFilesSZS int IterateFilesParSZS ( - szs_file_t * szs, // valid szs + szs_file_t *szs, // valid szs szs_iterator_func func, // call back function - void * param, // user defined parameter + void *param, // user defined parameter bool clean_path, // true: clean path from ../ and more bool show_root_node, // true: include root node in iteration int recurse, // 0:off, <0:unlimited, >0:max depth @@ -3622,6 +3661,90 @@ int IterateFilesData // /////////////////////////////////////////////////////////////////////////////// +/////////////// FindFileSZS() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +struct find_subfile_t +{ + ccp path; + int status; + szs_iterator_t result; +}; + +/////////////////////////////////////////////////////////////////////////////// + +int find_subfile_iter +( + struct szs_iterator_t *it, // iterator struct with all infos + bool term // true: termination hint +) +{ + if (!term) + { + struct find_subfile_t *fsub = it->param; + DASSERT(fsub); + + ccp path = it->path; + if ( path[0] == '.' && path[1] == '/' ) + path += 2; + if (!strcmp(path,fsub->path)) + { + fsub->status = 1; + fsub->result = *it; + return 1; + } + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +int FindFileSZS +( + // -1: error, 0: not found + result cleared, 1: found + result set + szs_file_t *szs, // valid szs + ccp path, // path to find + const iterator_param_t + *p_itpar, // NULL or iteration parameters + int recurse, // 0:off, <0:unlimited, >0:max depth + szs_iterator_t *result // not NULL: store result here +) +{ + if ( !szs || !path ) + goto err; + + while ( path[0] == '.' && path[1] == '/' ) + path += 2; + if (!*path) + goto err; + + struct find_subfile_t fsub = {0}; + fsub.path = path; + + int stat = IterateFilesSZS(szs,find_subfile_iter,&fsub,p_itpar,recurse); + DASSERT(szs); +//DEL printf("FindFileSZS(%s): %d\n",path,stat); + if ( stat >= 0 ) + { + if (result) + { + if ( fsub.status > 0 ) + memcpy(result,&fsub.result,sizeof(*result)); + else + memset(result,0,sizeof(*result)); + } + if ( fsub.status >= 0 ) + return fsub.status; + } + + err: + if (result) + memset(result,0,sizeof(*result)); + return -1; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// cut files: BRSUB /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -3797,10 +3920,11 @@ int CutFilesBRSUB { if ( (u8*)bcut.eptr > max_eptr ) { - ERROR0(ERR_WARNING, - "Invalid offset for BRSUB file => %u of %u entries ignored: %s%s%s\n", - bg_n_entry - cur_entry, bg_n_entry, - it->szs->fname, *it->szs->fname ? "/" : "", it->path ); + if ( WARN_MODE & WARN_INVALID_OFFSET && verbose >= -2 ) + ERROR0(ERR_WARNING, + "Invalid offset for BRSUB file => %u of %u entries ignored: %s%s%s\n", + bg_n_entry - cur_entry, bg_n_entry, + it->szs->fname, *it->szs->fname ? "/" : "", it->path ); break; } u32 data_off = bcut.endian->rd32(&bcut.eptr->data_off); @@ -4387,6 +4511,7 @@ CmpFuncSubFile GetCmpFunc return cmp_subfile_pack; case SORT_OFFSET: + case SORT_SIZE: return cmp_subfile_offset; //case SORT_BREFF: @@ -4474,7 +4599,7 @@ bool SortSubFilesSZS enumError DiffSZS ( szs_file_t * szs1, // first szs to compare - szs_file_t * szs2, // second szs tp compare + szs_file_t * szs2, // second szs to compare int recurse, // 0:off, <0:unlimited, >0:max depth int cut_files, // <0:never, =0:auto, >0:always bool quiet // true: be quiet diff --git a/project/src/lib-szs.h b/project/src/lib-szs.h index eea6912..25405d5 100644 --- a/project/src/lib-szs.h +++ b/project/src/lib-szs.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -276,7 +276,8 @@ enum szs_marker_t /////////////// have_szs_file_t /////////////// /////////////////////////////////////////////////////////////////////////////// // [[have_szs_file_t]] -// order is important, compare have_szs_name[], have_szs_file[] and ct.wiimm.de +// order is important, +// compare have_szs_name[], have_szs_file[], have_szs_fform[] and ct.wiimm.de typedef enum have_szs_file_t { @@ -311,6 +312,24 @@ __attribute__ ((packed)) have_file_mode_t; typedef have_file_mode_t szs_special_t[HAVESZS__N]; +/////////////////////////////////////////////////////////////////////////////// +// [[have_attrib_t]] +// order is important, compare have_attrib_name[] and ct.wiimm.de + +typedef enum have_attrib_t +{ + HAVEATT_CHEAT, // attribut "cheat" found + HAVEATT_EDIT, // attribut "edit" found + HAVEATT_REVERSE, // attribut "reverse" found + HAVEATT__N +} +__attribute__ ((packed)) have_attrib_t; + +extern const ccp have_attrib_name[HAVEATT__N]; + +ccp CreateSpecialInfoAttrib + ( have_attrib_t attrib, bool add_value, ccp return_if_empty ); + // /////////////////////////////////////////////////////////////////////////////// /////////////// szs_have_t /////////////// @@ -319,11 +338,12 @@ typedef have_file_mode_t szs_special_t[HAVESZS__N]; typedef struct szs_have_t { - bool valid; // TRUE: SZS analyzed - szs_special_t szs; // u8-list: one of have_file_mode_t (H_*) - kmp_special_t kmp; // u8-list: elem>0: number of special KMP objects found - uint lex_sect; // bit field for found lex sections - uint lex_feat; // bit field for found lex features + bool valid; // TRUE: SZS analyzed + szs_special_t szs; // u8-list: one of have_file_mode_t (H_*) + kmp_special_t kmp; // u8-list: elem>0: number of special KMP objects found + uint lex_sect; // bit field for found lex sections + uint lex_feat; // bit field for found lex features + have_attrib_t attrib; // bit field for special attributes } szs_have_t; @@ -446,6 +466,11 @@ typedef struct szs_file_t ParamField_t *special_file; // list with files of directory /common/ + + //--- options set by PrepareCheckTextureSZS() + + bool check_enpt; // true: check ENPT too + } szs_file_t; //----------------------------------------------------------------------------- @@ -496,7 +521,7 @@ typedef struct szs_norm_t //--- for output via PrintNorm() - FILE *f; // NULL or output file + FILE *f; // NULL or output file int indent; // indention char modified[SZI__N+1]; // info vector about modification -> szs_norm_info_t } @@ -745,12 +770,30 @@ bool IsFileOptionalSZS enumError DiffSZS ( szs_file_t * szs1, // first szs to compare - szs_file_t * szs2, // second szs tp compare + szs_file_t * szs2, // second szs to compare int recurse, // 0:off, <0:unlimited, >0:max depth int cut_files, // <0:never, =0:auto, >0:always bool quiet // true: be quiet ); +void PrepareCheckTextureSZS ( szs_file_t * szs ); + +enumError CheckTextureRefSZS +( + // returns ERR_OK | ERR_DIFFER | ERR_NOTHING_TO_DO | ERR_NO_SOURCE_FOUND | >=ERR_ERROR + szs_file_t * szs2, // NULL or second szs to compare + ccp *status // not NULL: store status info here -> FreeString() + // if !opt_reference: *status=NULL +); + +enumError CheckTextureSZS +( + // returns ERR_OK | ERR_DIFFER | ERR_ERROR + szs_file_t * szs1, // first szs to compare + szs_file_t * szs2, // second szs to compare + ccp *status // not NULL: store status info here -> FreeString() +); + bool SortSubFilesSZS ( szs_file_t * szs, // valid szs structure @@ -845,6 +888,7 @@ ccp CreateSpecialFileInfo /////////////////////////////////////////////////////////////////////////////// /////////////// szs file iterator /////////////// /////////////////////////////////////////////////////////////////////////////// +// [[szs_iterator_func]] struct szs_iterator_t; typedef int (*szs_iterator_func) @@ -947,11 +991,24 @@ extern szs_iterator_func cut_iter_func[FF_N]; //----------------------------------------------------------------------------- +int FindFileSZS +( + // -1: error, 0: not found + result cleared, 1: found + result set + szs_file_t *szs, // valid szs + ccp path, // path to find + const iterator_param_t + *p_itpar, // NULL or iteration parameters + int recurse, // 0:off, <0:unlimited, >0:max depth + szs_iterator_t *result // not NULL: store result here +); + +//----------------------------------------------------------------------------- + int IterateFilesSZS ( - szs_file_t * szs, // valid szs + szs_file_t *szs, // valid szs szs_iterator_func func, // call back function - void * param, // user defined parameter + void *param, // user defined parameter const iterator_param_t *p_itpar, // NULL or iteration parameters int recurse // 0:off, <0:unlimited, >0:max depth @@ -959,9 +1016,9 @@ int IterateFilesSZS int IterateFilesParSZS ( - szs_file_t * szs, // valid szs + szs_file_t *szs, // valid szs szs_iterator_func func, // call back function - void * param, // user defined parameter + void *param, // user defined parameter bool clean_path, // true: clean path from ../ and more bool show_root_node, // true: include root node in iteration int recurse, // 0:off, <0:unlimited, >0:max depth @@ -1404,6 +1461,12 @@ typedef struct analyse_szs_t sha1_hex_t sha1_vrcorn; // SHA1 of vrcorn sha1_hex_t sha1_minimap; // SHA1 of minimap + //--- slots of orgiginal tarcks: 0:none, 11.84:track 111..125:arena + + u8 sha1_kmp_slot; + u8 sha1_kmp_norm_slot; + u8 sha1_kcl_slot; + u8 sha1_minimap_slot; //--- sub files diff --git a/project/src/lib-transform.c b/project/src/lib-transform.c index 2f0c912..106c63d 100644 --- a/project/src/lib-transform.c +++ b/project/src/lib-transform.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-xbmg.c b/project/src/lib-xbmg.c index 1aee2ef..5a82e46 100644 --- a/project/src/lib-xbmg.c +++ b/project/src/lib-xbmg.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/lib-xbmg.h b/project/src/lib-xbmg.h index 69fcf1e..a391330 100644 --- a/project/src/lib-xbmg.h +++ b/project/src/lib-xbmg.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/types.h b/project/src/types.h index ba1c230..af9ee98 100644 --- a/project/src/types.h +++ b/project/src/types.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/ui/gen-ui.c b/project/src/ui/gen-ui.c index 7563642..40a35a7 100644 --- a/project/src/ui/gen-ui.c +++ b/project/src/ui/gen-ui.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/ui/tab-wbmgt.inc b/project/src/ui/tab-wbmgt.inc index 40a02fa..753342c 100644 --- a/project/src/ui/tab-wbmgt.inc +++ b/project/src/ui/tab-wbmgt.inc @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -221,6 +221,9 @@ { T_OPT_GM, "LOGGING", "L|logging", 0, 0 /* copy of wszst */ }, + { T_OPT_GP, "WARN", "W|warn", + 0, 0 /* copy of wszst */ }, + { T_OPT_G, "DE", "de", 0, 0 /* copy of wszst */ }, diff --git a/project/src/ui/tab-wctct.inc b/project/src/ui/tab-wctct.inc index 33e5203..bb24731 100644 --- a/project/src/ui/tab-wctct.inc +++ b/project/src/ui/tab-wctct.inc @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -208,6 +208,9 @@ { T_OPT_GM, "LOGGING", "L|logging", 0, 0 /* copy of wszst */ }, + { T_OPT_GP, "WARN", "W|warn", + 0, 0 /* copy of wszst */ }, + { T_OPT_G, "DE", "de", 0, 0 /* copy of wszst */ }, diff --git a/project/src/ui/tab-wimgt.inc b/project/src/ui/tab-wimgt.inc index 6c572fc..3ab70bd 100644 --- a/project/src/ui/tab-wimgt.inc +++ b/project/src/ui/tab-wimgt.inc @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -178,6 +178,9 @@ { T_OPT_GM, "LOGGING", "L|logging", 0, 0 /* copy of wszst */ }, + { T_OPT_GP, "WARN", "W|warn", + 0, 0 /* copy of wszst */ }, + { T_OPT_G, "DE", "de", 0, 0 /* copy of wszst */ }, diff --git a/project/src/ui/tab-wkclt.inc b/project/src/ui/tab-wkclt.inc index 682dd7b..2a137c8 100644 --- a/project/src/ui/tab-wkclt.inc +++ b/project/src/ui/tab-wkclt.inc @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -169,6 +169,17 @@ " If the flag file already exists, only missing group names" " are added at the end of file." }, + { H_DEF_CMD, "TYPES", "TYPES", + "wkclt TYPES arg...", + "Print a line with KCL flag details for each argument." + " ARG is a comma or space separated list of a optional BASEVAL" + " and a list of TERMS. BASEVAL can be any hexa-decimal number." + " The format of TERMS is @X[=]VALUE@." + " So a TERM begin with letter @T@ (Type), @V@ (Value) or a group" + " identifier (W, X,Y or Z), followed by an optional equal sign" + " and finished by a decimal number." + " It overrides the related part of BASEVAL." }, + { T_DEF_CMD, "FLAGS", "FLAGS|F", "wkclt FLAGS source...", "Print a KCL type and flag usage statistic for each source" @@ -226,6 +237,11 @@ " Hints and warnings are written to standard output." " The exit status is @'DIFFER'@ if at least one KMP warning found." }, + { T_DEF_CMD, "SHA1", "SHA1", + "wszst SHA1 [source]...", + "Print a SHA1 checksum of the KCL for each source." + " The checksum is calculated after patching." }, + { H_DEF_CMD, "ANALYZE", "ANALYZE", "wkclt ANALYZE source...", "Analyze some KCL data." }, @@ -275,6 +291,9 @@ { T_OPT_GM, "LOGGING", "L|logging", 0, 0 /* copy of wszst */ }, + { T_OPT_GP, "WARN", "W|warn", + 0, 0 /* copy of wszst */ }, + { T_OPT_G, "DE", "de", 0, 0 /* copy of wszst */ }, @@ -367,6 +386,18 @@ { T_OPT_CP, "SLOT", "slot", 0, 0 /* copy of wszst */ }, + { T_OPT_C, "ID", "id", + 0, 0 /* copy of wszst */ }, + + { T_OPT_CO, "BASE64", "base64", + 0, 0 /* copy of wszst */ }, + + { T_OPT_CO, "DB64", "db64", + 0, 0 /* copy of wszst */ }, + + { T_OPT_CP, "CODING", "coding", + 0, 0 /* copy of wszst */ }, + { T_OPT_C, "ROUND", "round", 0, 0 /* copy of wszst */ }, @@ -701,6 +732,13 @@ { T_COPT, "CONST", 0,0,0 }, { T_COPT, "FLAG_FILE", 0,0,0 }, + //---------- COMMAND wkclt TYPES ---------- + + { T_CMD_BEG, "TYPES", 0,0,0 }, + { T_COPT, "NO_HEADER", 0,0,0 }, + { T_COPT, "BRIEF", 0,0, + "Print only the resulting flag." }, + //---------- COMMAND wkclt FLAGS ---------- { T_CMD_BEG, "FLAGS", 0,0,0 }, @@ -795,6 +833,19 @@ { T_COPT, "NO_CHECK", 0,0,0 }, { T_COPT, "IGNORE", 0,0,0 }, + //---------- COMMAND wkclt SHA1 ---------- + + { T_CMD_BEG, "SHA1", 0,0,0 }, + { T_COPT, "IGNORE", 0,0,0 }, + { T_COPT, "ID", 0,0,0 }, + { T_COPT, "BASE64", 0,0,0 }, + { T_COPT, "DB64", 0,0,0 }, + { T_COPT, "CODING", 0,0,0 }, + { T_COPT, "BRIEF", 0,0, + "Suppress output of the filename." }, + { T_SEP_OPT, 0,0,0,0 }, + { T_COPY_GRP, "TRANSFORM", 0,0,0 }, + //---------- COMMAND wkclt ANALYZE ---------- { T_CMD_BEG, "ANALYZE", 0,0,0 }, diff --git a/project/src/ui/tab-wkmpt.inc b/project/src/ui/tab-wkmpt.inc index ace5125..0b2a49a 100644 --- a/project/src/ui/tab-wkmpt.inc +++ b/project/src/ui/tab-wkmpt.inc @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -275,6 +275,9 @@ { T_OPT_GM, "LOGGING", "L|logging", 0, 0 /* copy of wszst */ }, + { T_OPT_GP, "WARN", "W|warn", + 0, 0 /* copy of wszst */ }, + { T_OPT_G, "DE", "de", 0, 0 /* copy of wszst */ }, diff --git a/project/src/ui/tab-wlect.inc b/project/src/ui/tab-wlect.inc index 1aba6e5..d5ac35d 100644 --- a/project/src/ui/tab-wlect.inc +++ b/project/src/ui/tab-wlect.inc @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -231,6 +231,9 @@ { T_OPT_GM, "LOGGING", "L|logging", 0, 0 /* copy of wszst */ }, + { T_OPT_GP, "WARN", "W|warn", + 0, 0 /* copy of wszst */ }, + { T_OPT_G, "DE", "de", 0, 0 /* copy of wszst */ }, @@ -426,6 +429,12 @@ " The file format can be LE-BIN or any supported CT-CODE file" " (BRRES, TEX0, CT-CODE or CT-TEXT)." }, + { H_OPT_CP, "LE_ARENA", "le-arena|learena", + "file", + "Use this file to define property and music defaults for arenas." + " The file format can be an text file." + " Option {--le-define} may override these defaults." }, + { T_OPT_CP, "LPAR", "lpar", "file", "Read a LPAR file to overwrite settings of LE-CODE section LPAR." }, @@ -637,6 +646,7 @@ { T_GRP_BEG, "PATCH", 0,0,0 }, { T_COPT, "LE_DEFINE", 0,0,0 }, + { H_COPT, "LE_ARENA", 0,0,0 }, { T_COPT, "LPAR", 0,0,0 }, { T_COPT, "ALIAS", 0,0,0 }, { T_COPY_GRP, "PARAM", 0,0,0 }, diff --git a/project/src/ui/tab-wmdlt.inc b/project/src/ui/tab-wmdlt.inc index ced4e6a..85018fd 100644 --- a/project/src/ui/tab-wmdlt.inc +++ b/project/src/ui/tab-wmdlt.inc @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -201,6 +201,9 @@ { T_OPT_GM, "LOGGING", "L|logging", 0, 0 /* copy of wszst */ }, + { T_OPT_GP, "WARN", "W|warn", + 0, 0 /* copy of wszst */ }, + { T_OPT_G, "DE", "de", 0, 0 /* copy of wszst */ }, diff --git a/project/src/ui/tab-wpatt.inc b/project/src/ui/tab-wpatt.inc index 5b7e71a..b2f193e 100644 --- a/project/src/ui/tab-wpatt.inc +++ b/project/src/ui/tab-wpatt.inc @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -169,6 +169,9 @@ { T_OPT_GM, "LOGGING", "L|logging", 0, 0 /* copy of wszst */ }, + { T_OPT_GP, "WARN", "W|warn", + 0, 0 /* copy of wszst */ }, + { T_OPT_G, "DE", "de", 0, 0 /* copy of wszst */ }, diff --git a/project/src/ui/tab-wstrt.inc b/project/src/ui/tab-wstrt.inc index 3bef0fb..4015738 100644 --- a/project/src/ui/tab-wstrt.inc +++ b/project/src/ui/tab-wstrt.inc @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -116,10 +116,11 @@ " Keywords are @PAL@ (default), @USA@, @JAPAN@, @KOREA@, or any abbreviation of them." " They select the region for the following addresses." " The hex numbers (with or without @0x@ prefix) are interpreted as addresses." - " If possible, they are ported to all other regions." + " If an address begins with @m@ or @s@," + " then it is interpreted as a file offset for @main.dol@ or @staticr.rel@." + " All addresses are ported to all other regions." " The result is printed as colorized table." - "\n" - " This address porting is EXPERIMENTAL!" }, + "\1 See https://szs.wiimm.de/cmd/wstrt/port for more details." }, { T_DEF_CMD, "WHERE", "WHERE", "wstrt WHERE address...", @@ -129,7 +130,8 @@ " The result is output as a human and machine readable table." "\n " " This command is well suited to converting addresses" - " into file offsets and vice versa." }, + " into file offsets and vice versa." + "\1 See https://szs.wiimm.de/cmd/wstrt/where for more details." }, { H_DEF_CMD, "HTTPS", "_HTTPS", "wstrt _HTTPS file...", @@ -230,6 +232,9 @@ { T_OPT_GM, "LOGGING", "L|logging", 0, 0 /* copy of wszst */ }, + { T_OPT_GP, "WARN", "W|warn", + 0, 0 /* copy of wszst */ }, + { T_OPT_G, "DE", "de", 0, 0 /* copy of wszst */ }, @@ -660,7 +665,13 @@ { T_OPT_C, "NO_0X", "0|no-0x|no0x", 0, - "Suppress 0x prefix of hex numbers." }, + "Suppress 0x prefix of hex numbers." + " This is the default for cheat codes." }, + + { T_OPT_C, "UPPER", "U|upper", + 0, + "Print digits A-F of hex numbers in upper case." + " This is the default for cheat codes." }, { T_SEP_OPT, 0,0,0,0 }, //----- separator ----- @@ -995,6 +1006,7 @@ { T_COPT, "PORT_DB", 0,0,0 }, { T_COPT, "ORDER", 0,0,0 }, { T_COPT, "NO_0X", 0,0,0 }, + { T_COPT, "UPPER", 0,0,0 }, { T_COPT, "NO_HEADER", 0,0, "Suppress the table header and footer and output exactly 1 line for" " each specified address. This makes the output more machine-readable." }, @@ -1008,6 +1020,7 @@ { T_CMD_BEG, "WHERE", 0,0,0 }, { T_COPT, "ORDER", 0,0,0 }, { T_COPT, "NO_0X", 0,0,0 }, + { T_COPT, "UPPER", 0,0,0 }, { T_COPT, "NO_HEADER", 0,0, "Suppress the table header and footer and output exactly 1 line for" " each specified address. This makes the output more machine-readable." }, diff --git a/project/src/ui/tab-wszst.inc b/project/src/ui/tab-wszst.inc index 8220457..d836fdf 100644 --- a/project/src/ui/tab-wszst.inc +++ b/project/src/ui/tab-wszst.inc @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -226,6 +226,11 @@ "This hidden command exports some definitions to standard output." " Use keyword @HELP@ to get a list of possible keywords." }, + { H_DEF_CMD, "SIZEOF", "SIZEOF", + "wszst SIZEOF key...", + "This hidden command prints a list with the size of" + " data structures and variables." }, + { H_DEF_CMD, "CODE", "_CODE", "wszst _CODE [files]", "All bytes of all input files are xor'ed with 0xDC and copied to stdout." @@ -340,15 +345,28 @@ { T_DEF_CMD, "SHA1", "SHA1", "wszst SHA1 [source]...", "Print a SHA1 checksum for each source." - " The checksum is calculated by using the uncompressed data." }, + " The checksum is calculated by using the uncompressed data" + " and after patching." }, { T_DEF_CMD, "ANALYZE", "ANALYZE|ANA|ANALYSE", "wszst ANALYZE [source]...", "Analyse track files and print results in machine readable format." }, + { T_DEF_CMD, "IS_TEXTURE", "IS-TEXTURE|ISTEXTURE", + "wszst IS-TEXTURE --reference reference [source]...", + "Test each source to see if it's a texture hack versus a reference file." + " For each source, one human and machine readable status line is printed." + " It is either »-1=err« on error, »1=yes« for a texture hack," + " or »0=no LIST« with a comma separated list of reasons." + "\n " + " At the moment KCL, KMP (see notes) and LEX are checked." + " KMP section CAME has been intentionally left out." + " Section ENPT is only checked if KCL contains a least one face" + " of type force-recalculation." }, + { H_DEF_CMD, "FEATURES", "FEATURES", "wszst FEATURES [source]...", - "Analyse track files and a feature list in machine readable format." }, + "Analyse track files and create a feature list in machine readable format." }, { T_DEF_CMD, "DISTRIBUTION", "DISTRIBUTION|DIST", "wszst DISTRIBUTION result source...\n" @@ -673,9 +691,8 @@ "MAX_WIDTH", "max-width|maxwidth", "maxwidth", "Define the maximum terminal width (number of columns)" - " for help and some other messages" - " and disable the automatic detection of the terminal width." - " This option is ignored if {--width} is set." }, + " for help and some other messages." + " The default is 120. This option is ignored if --width is set." }, { T_OPT_GM, "QUIET", "q|quiet", 0, @@ -695,6 +712,20 @@ 0, "This debug option enables the logging of internal lists and maps." }, + { T_OPT_GP, "WARN", "W|warn", + "list", + "Enable or disable warnings." + " Parameter @'list'@ is a comma separated list of keywords." + " A minus sign before a keyword disables a warning." + " Each occurrence of the option will only change entered warning" + " and all other warnings are untouched." + "\n " + " Keyword @DEFAULT@ resets the default settings, @OFF@ disables and @ALL@ enables all." + " The other allowed keywords are:" + " @INVALID-OFFSET@." + // "\1 See https://szs.wiimm.de/opt/warn for details." + }, + { T_OPT_G, "DE", "de", 0, "Use german track and arena names." }, @@ -1017,7 +1048,7 @@ "@MODE@ is either @OFF@, @AUTO@ (default) or @ON@." " Without value, @ON@ is used." "\n " - " If mode is @ON@, assume a battle arena and enable a spüecial battle support." + " If mode is @ON@, assume a battle arena and enable a special battle support." " If mode is @OFF@, disable special battle arena support." " If mode is @AUTO@, analyse the KMP and estimate, if it is a battle areana." " Modes @ON@ and @OFF@ override KMP parameter @BATTLE-MODE@." }, @@ -1519,7 +1550,7 @@ { T_OPT_CP, "CODING", "coding", "mode", "Define the coding of the non alphanumeric characters for BASE64:" - " STANDART (+/=, default), URL (-_=), STAR (-_*) or XML (.-*)." }, + " STANDARD (+/=, default), URL (-_=), STAR (-_*) or XML (.-*)." }, { T_OPT_C, "VERIFY", "verify", 0, @@ -1955,6 +1986,10 @@ "\1 Read https://szs.wiimm.de/opt/source for more details." }, + { T_OPT_CP, "REFERENCE", "ref|reference", + "path", + "Define a reference SZS." }, + { T_OPT_CP, "DEST", "d|dest", "path", "Define a destination path (directory/file)." @@ -2796,6 +2831,16 @@ { T_CMD_BEG, "EXPORT", 0,0,0 }, + //---------- COMMAND wszst _SIZEOF ---------- + + { T_CMD_BEG, "SIZEOF", 0,0,0 }, + { T_COPT, "SORT", 0,0, + "Define a sort mode. Keywords are:" + " @NONE@ (default), @NAME@ end @SIZE@." }, + { T_COPT, "BRIEF", 0,0, + "Limit output to SZS specific data." }, + { T_COPT, "LOGGING", 0,0,0 }, + //---------- COMMAND wszst _CODE ---------- { T_CMD_BEG, "CODE", 0,0,0 }, @@ -2981,9 +3026,19 @@ { T_SEP_OPT, 0,0,0,0 }, { T_COPY_GRP, "SCRIPT", 0,0,0 }, { T_SEP_OPT, 0,0,0,0 }, + { T_COPT, "REFERENCE", 0,0,0 }, { T_COPT, "DEST", 0,0,0 }, { T_COPT, "DEST2", 0,0,0 }, + //---------- COMMAND wszst IS_TEXTURE ---------- + + { T_CMD_BEG, "IS_TEXTURE", 0,0,0 }, + { T_COPT, "IGNORE", 0,0,0 }, + { T_COPT, "REFERENCE", 0,0,0 }, + { T_COPT, "BATTLE", 0,0,0 }, + { T_COPT, "LONG", 0,0, + "Append a colon and the filename after each status." }, + //---------- COMMAND wszst FEATURES ---------- { T_CMD_BEG, "FEATURES", 0,0,0 }, @@ -2992,7 +3047,7 @@ " If set twice, suppress empty lines (for grouping) too." " If set three times, omit inactive features (=0) too." }, { T_COPT, "LONG", 0,0, - "Print additnal comments." }, + "Print additional comments." }, { T_COPT, "IGNORE", 0,0,0 }, { T_COPT, "QUIET", 0,0, "Suppress logging of input and output files." }, diff --git a/project/src/ui/ui-wbmgt.c b/project/src/ui/ui-wbmgt.c index 29ef8b5..aa991c4 100644 --- a/project/src/ui/ui-wbmgt.c +++ b/project/src/ui/ui-wbmgt.c @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -349,8 +349,8 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_MAX_WIDTH, false, false, false, true, false, 0, "max-width", "maxwidth", "Define the maximum terminal width (number of columns) for help and" - " some other messages and disable the automatic detection of the" - " terminal width. This option is ignored if --width is set." + " some other messages. The default is 120. This option is ignored if" + " --width is set." }, { OPT_QUIET, false, false, false, false, false, 'q', "quiet", @@ -371,6 +371,16 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "This debug option enables the logging of internal lists and maps." }, + { OPT_WARN, false, false, false, false, false, 'W', "warn", + "list", + "Enable or disable warnings. Parameter 'list' is a comma separated" + " list of keywords. A minus sign before a keyword disables a warning." + " Each occurrence of the option will only change entered warning and" + " all other warnings are untouched.\n" + " Keyword DEFAULT resets the default settings, OFF disables and ALL" + " enables all. The other allowed keywords are: INVALID-OFFSET." + }, + { OPT_DE, false, false, false, false, false, 0, "de", 0, "Use german track and arena names." @@ -531,7 +541,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " helper option." }, - {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 63 + {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 64 }; @@ -660,7 +670,7 @@ static const KeywordTab_t CommandTab[] = /////////////// OptionShort & OptionLong /////////////// /////////////////////////////////////////////////////////////////////////////// -static const char OptionShort[] = "VhqvLc:lHBM:T:A:td:D:E:orupiP:1X"; +static const char OptionShort[] = "VhqvLW:c:lHBM:T:A:td:D:E:orupiP:1X"; static const struct option OptionLong[] = { @@ -677,6 +687,7 @@ static const struct option OptionLong[] = { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, { "logging", 0, 0, 'L' }, + { "warn", 1, 0, 'W' }, { "de", 0, 0, GO_DE }, { "colors", 2, 0, GO_COLORS }, { "no-colors", 0, 0, GO_NO_COLORS }, @@ -803,7 +814,7 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x054 T */ OPT_TRACKS, /* 0x055 */ 0, /* 0x056 V */ OPT_VERSION, - /* 0x057 */ 0, + /* 0x057 W */ OPT_WARN, /* 0x058 X */ OPT_EXPORT, /* 0x059 */ 0,0,0,0, 0,0,0,0, 0,0, /* 0x063 c */ OPT_CONST, @@ -1029,6 +1040,7 @@ static const InfoOption_t * option_tab_tool[] = OptionInfo + OPT_QUIET, OptionInfo + OPT_VERBOSE, OptionInfo + OPT_LOGGING, + OptionInfo + OPT_WARN, OptionInfo + OPT_DE, OptionInfo + OPT_COLORS, OptionInfo + OPT_NO_COLORS, @@ -1410,7 +1422,7 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = "wbmgt [option]... command [option|parameter|file]...", "Wiimms BMG Tool : Convert and patch raw and text BMG (message) files.", 0, - 25, + 26, option_tab_tool, 0 }, diff --git a/project/src/ui/ui-wbmgt.h b/project/src/ui/ui-wbmgt.h index e957987..855342f 100644 --- a/project/src/ui/ui-wbmgt.h +++ b/project/src/ui/ui-wbmgt.h @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -103,6 +103,7 @@ typedef enum enumOptions OPT_QUIET, OPT_VERBOSE, OPT_LOGGING, + OPT_WARN, OPT_DE, OPT_COLORS, OPT_NO_COLORS, @@ -124,7 +125,7 @@ typedef enum enumOptions OPT_NEW, OPT_EXTRACT, - OPT__N_TOTAL // == 63 + OPT__N_TOTAL // == 64 } enumOptions; @@ -350,6 +351,7 @@ typedef enum enumGetOpt GO_PATCH_BMG = 'P', GO_TRACKS = 'T', GO_VERSION = 'V', + GO_WARN = 'W', GO_EXPORT = 'X', GO_CONST = 'c', diff --git a/project/src/ui/ui-wctct.c b/project/src/ui/ui-wctct.c index 10469ab..1344aa3 100644 --- a/project/src/ui/ui-wctct.c +++ b/project/src/ui/ui-wctct.c @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -449,8 +449,8 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_MAX_WIDTH, false, false, false, true, false, 0, "max-width", "maxwidth", "Define the maximum terminal width (number of columns) for help and" - " some other messages and disable the automatic detection of the" - " terminal width. This option is ignored if --width is set." + " some other messages. The default is 120. This option is ignored if" + " --width is set." }, { OPT_QUIET, false, false, false, false, false, 'q', "quiet", @@ -471,6 +471,16 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "This debug option enables the logging of internal lists and maps." }, + { OPT_WARN, false, false, false, false, false, 'W', "warn", + "list", + "Enable or disable warnings. Parameter 'list' is a comma separated" + " list of keywords. A minus sign before a keyword disables a warning." + " Each occurrence of the option will only change entered warning and" + " all other warnings are untouched.\n" + " Keyword DEFAULT resets the default settings, OFF disables and ALL" + " enables all. The other allowed keywords are: INVALID-OFFSET." + }, + { OPT_DE, false, false, false, false, false, 0, "de", 0, "Use german track and arena names." @@ -662,7 +672,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " 0x3b:0x41 and 0x44:0xfe." }, - {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 82 + {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 83 }; @@ -851,7 +861,7 @@ static const KeywordTab_t CommandTab[] = /////////////// OptionShort & OptionLong /////////////// /////////////////////////////////////////////////////////////////////////////// -static const char OptionShort[] = "VhqvLc:lHB1XPNM:T:A:td:D:E:orupi"; +static const char OptionShort[] = "VhqvLW:c:lHB1XPNM:T:A:td:D:E:orupi"; static const struct option OptionLong[] = { @@ -868,6 +878,7 @@ static const struct option OptionLong[] = { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, { "logging", 0, 0, 'L' }, + { "warn", 1, 0, 'W' }, { "de", 0, 0, GO_DE }, { "colors", 2, 0, GO_COLORS }, { "no-colors", 0, 0, GO_NO_COLORS }, @@ -1021,7 +1032,7 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x054 T */ OPT_TRACKS, /* 0x055 */ 0, /* 0x056 V */ OPT_VERSION, - /* 0x057 */ 0, + /* 0x057 W */ OPT_WARN, /* 0x058 X */ OPT_EXPORT, /* 0x059 */ 0,0,0,0, 0,0,0,0, 0,0, /* 0x063 c */ OPT_CONST, @@ -1264,6 +1275,7 @@ static const InfoOption_t * option_tab_tool[] = OptionInfo + OPT_QUIET, OptionInfo + OPT_VERBOSE, OptionInfo + OPT_LOGGING, + OptionInfo + OPT_WARN, OptionInfo + OPT_DE, OptionInfo + OPT_COLORS, OptionInfo + OPT_NO_COLORS, @@ -1642,7 +1654,7 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = "Wiimms CT-CODE Tool : Manage the CT-CODE extension. BRRES, TEX0," " CT-CODE, CT-TEXT and LE-BIN files are accepted as input.", 0, - 27, + 28, option_tab_tool, 0 }, diff --git a/project/src/ui/ui-wctct.h b/project/src/ui/ui-wctct.h index f943d52..532b082 100644 --- a/project/src/ui/ui-wctct.h +++ b/project/src/ui/ui-wctct.h @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -118,6 +118,7 @@ typedef enum enumOptions OPT_QUIET, OPT_VERBOSE, OPT_LOGGING, + OPT_WARN, OPT_DE, OPT_COLORS, OPT_NO_COLORS, @@ -143,7 +144,7 @@ typedef enum enumOptions OPT_CT_LOG, OPT_ALLOW_SLOTS, - OPT__N_TOTAL // == 82 + OPT__N_TOTAL // == 83 } enumOptions; @@ -420,6 +421,7 @@ typedef enum enumGetOpt GO_NO_PARAM = 'P', GO_TRACKS = 'T', GO_VERSION = 'V', + GO_WARN = 'W', GO_EXPORT = 'X', GO_CONST = 'c', diff --git a/project/src/ui/ui-wimgt.c b/project/src/ui/ui-wimgt.c index 367da79..7ffff1c 100644 --- a/project/src/ui/ui-wimgt.c +++ b/project/src/ui/ui-wimgt.c @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -312,8 +312,8 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_MAX_WIDTH, false, false, false, true, false, 0, "max-width", "maxwidth", "Define the maximum terminal width (number of columns) for help and" - " some other messages and disable the automatic detection of the" - " terminal width. This option is ignored if --width is set." + " some other messages. The default is 120. This option is ignored if" + " --width is set." }, { OPT_QUIET, false, false, false, false, false, 'q', "quiet", @@ -334,6 +334,16 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "This debug option enables the logging of internal lists and maps." }, + { OPT_WARN, false, false, false, false, false, 'W', "warn", + "list", + "Enable or disable warnings. Parameter 'list' is a comma separated" + " list of keywords. A minus sign before a keyword disables a warning." + " Each occurrence of the option will only change entered warning and" + " all other warnings are untouched.\n" + " Keyword DEFAULT resets the default settings, OFF disables and ALL" + " enables all. The other allowed keywords are: INVALID-OFFSET." + }, + { OPT_DE, false, false, false, false, false, 0, "de", 0, "Use german track and arena names." @@ -482,7 +492,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " helper option." }, - {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 56 + {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 57 }; @@ -601,7 +611,7 @@ static const KeywordTab_t CommandTab[] = /////////////// OptionShort & OptionLong /////////////// /////////////////////////////////////////////////////////////////////////////// -static const char OptionShort[] = "VhqvLc:lHBM:T:A:td:D:E:orupiaP:x:"; +static const char OptionShort[] = "VhqvLW:c:lHBM:T:A:td:D:E:orupiaP:x:"; static const struct option OptionLong[] = { @@ -618,6 +628,7 @@ static const struct option OptionLong[] = { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, { "logging", 0, 0, 'L' }, + { "warn", 1, 0, 'W' }, { "de", 0, 0, GO_DE }, { "colors", 2, 0, GO_COLORS }, { "no-colors", 0, 0, GO_NO_COLORS }, @@ -726,7 +737,8 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x054 T */ OPT_TRACKS, /* 0x055 */ 0, /* 0x056 V */ OPT_VERSION, - /* 0x057 */ 0,0,0,0, 0,0,0,0, 0,0, + /* 0x057 W */ OPT_WARN, + /* 0x058 */ 0,0,0,0, 0,0,0,0, 0, /* 0x061 a */ OPT_ALL, /* 0x062 */ 0, /* 0x063 c */ OPT_CONST, @@ -896,6 +908,7 @@ static const InfoOption_t * option_tab_tool[] = OptionInfo + OPT_QUIET, OptionInfo + OPT_VERBOSE, OptionInfo + OPT_LOGGING, + OptionInfo + OPT_WARN, OptionInfo + OPT_DE, OptionInfo + OPT_COLORS, OptionInfo + OPT_NO_COLORS, @@ -1175,7 +1188,7 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = "Wiimms Image Tool : Extract and convert graphic images. The file" " formats TPL, TEX, BTI, BREFT and PNG are supported.", 0, - 22, + 23, option_tab_tool, 0 }, diff --git a/project/src/ui/ui-wimgt.h b/project/src/ui/ui-wimgt.h index 93bb369..4595e8e 100644 --- a/project/src/ui/ui-wimgt.h +++ b/project/src/ui/ui-wimgt.h @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -97,6 +97,7 @@ typedef enum enumOptions OPT_QUIET, OPT_VERBOSE, OPT_LOGGING, + OPT_WARN, OPT_DE, OPT_COLORS, OPT_NO_COLORS, @@ -117,7 +118,7 @@ typedef enum enumOptions OPT_NEW, OPT_EXTRACT, - OPT__N_TOTAL // == 56 + OPT__N_TOTAL // == 57 } enumOptions; @@ -282,6 +283,7 @@ typedef enum enumGetOpt GO_PATCH = 'P', GO_TRACKS = 'T', GO_VERSION = 'V', + GO_WARN = 'W', GO_ALL = 'a', GO_CONST = 'c', diff --git a/project/src/ui/ui-wkclt.c b/project/src/ui/ui-wkclt.c index 9670bbd..adcb273 100644 --- a/project/src/ui/ui-wkclt.c +++ b/project/src/ui/ui-wkclt.c @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -261,6 +261,34 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " See https://szs.wiimm.de/opt/slot for details." }, + { OPT_ID, false, false, false, false, false, 0, "id", + 0, + "Print an ID with 8 characters instead of a SHA-1 sum with 40" + " characters. The SHA-1 sum is used to calculate the ID. The ID" + " consists of '0'-'9' and 'a'-'w' (32 characters)." + }, + + { OPT_BASE64, true, false, false, false, false, 0, "base64", + "[=mode]", + "Encode the the checksum string as BASE64 with 27 characters instead" + " of hex. If a parameter is set, it acts like --coding=mode." + }, + + { OPT_DB64, true, false, false, false, false, 0, "db64", + "[=mode]", + "Encode the the checksum string and some length as BASE64 with 32" + " characters instead of hex for database searches. This options" + " implies --coding=URL if no other coding is defined. If a parameter" + " is set, it acts like --coding=mode. Option --db64 has priority over" + " --base64." + }, + + { OPT_CODING, false, false, false, false, false, 0, "coding", + "mode", + "Define the coding of the non alphanumeric characters for BASE64:" + " STANDARD (+/=, default), URL (-_=), STAR (-_*) or XML (.-*)." + }, + { OPT_ROUND, false, false, false, false, false, 0, "round", 0, "Print additional lines with rounded values (to 3 and 2 bytes for" @@ -365,7 +393,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "Print in machine readable sections and parameter lines." }, - {0,0,0,0,0,0,0,0,0,0}, // OPT__N_SPECIFIC == 37 + {0,0,0,0,0,0,0,0,0,0}, // OPT__N_SPECIFIC == 41 //----- global options ----- @@ -421,8 +449,8 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_MAX_WIDTH, false, false, false, true, false, 0, "max-width", "maxwidth", "Define the maximum terminal width (number of columns) for help and" - " some other messages and disable the automatic detection of the" - " terminal width. This option is ignored if --width is set." + " some other messages. The default is 120. This option is ignored if" + " --width is set." }, { OPT_QUIET, false, false, false, false, false, 'q', "quiet", @@ -443,6 +471,16 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "This debug option enables the logging of internal lists and maps." }, + { OPT_WARN, false, false, false, false, false, 'W', "warn", + "list", + "Enable or disable warnings. Parameter 'list' is a comma separated" + " list of keywords. A minus sign before a keyword disables a warning." + " Each occurrence of the option will only change entered warning and" + " all other warnings are untouched.\n" + " Keyword DEFAULT resets the default settings, OFF disables and ALL" + " enables all. The other allowed keywords are: INVALID-OFFSET." + }, + { OPT_DE, false, false, false, false, false, 0, "de", 0, "Use german track and arena names." @@ -642,7 +680,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " helper option." }, - {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 72 + {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 77 }; @@ -773,6 +811,12 @@ static const InfoOption_t option_cmd_CFF_BRIEF = "Suppress the comments with the alternative expression formats." }; +static const InfoOption_t option_cmd_TYPES_BRIEF = + { OPT_BRIEF, false, false, false, false, false, 'B', "brief", + 0, + "Print only the resulting flag." + }; + static const InfoOption_t option_cmd_FLAGS_BRIEF = { OPT_BRIEF, false, false, false, false, false, 'B', "brief", 0, @@ -851,6 +895,12 @@ static const InfoOption_t option_cmd_CHECK_QUIET = "Be quiet until the first warning or hint is found." }; +static const InfoOption_t option_cmd_SHA1_BRIEF = + { OPT_BRIEF, false, false, false, false, false, 'B', "brief", + 0, + "Suppress output of the filename." + }; + // /////////////////////////////////////////////////////////////////////////////// @@ -880,6 +930,7 @@ static const KeywordTab_t CommandTab[] = { CMD_ENCODE, "ENCODE", "ENC", 0 }, { CMD_COPY, "COPY", "CP", 0 }, { CMD_CFF, "CFF", 0, 0 }, + { CMD_TYPES, "TYPES", 0, 0 }, { CMD_FLAGS, "FLAGS", "F", 0 }, { CMD_DUMP, "DUMP", "D", 0 }, { CMD_DBRIEF, "DBRIEF", "DB", 0 }, @@ -888,6 +939,7 @@ static const KeywordTab_t CommandTab[] = { CMD_TRAVERSE, "TRAVERSE", 0, 0 }, { CMD_FALL, "FALL", 0, 0 }, { CMD_CHECK, "CHECK", "CHK", 0 }, + { CMD_SHA1, "SHA1", 0, 0 }, { CMD_ANALYZE, "ANALYZE", 0, 0 }, { CMD_BLOW, "BLOW", 0, 0 }, @@ -899,7 +951,7 @@ static const KeywordTab_t CommandTab[] = /////////////// OptionShort & OptionLong /////////////// /////////////////////////////////////////////////////////////////////////////// -static const char OptionShort[] = "VhqvLc:lHBPNM:T:A:td:D:E:orupi"; +static const char OptionShort[] = "VhqvLW:c:lHBPNM:T:A:td:D:E:orupi"; static const struct option OptionLong[] = { @@ -916,6 +968,7 @@ static const struct option OptionLong[] = { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, { "logging", 0, 0, 'L' }, + { "warn", 1, 0, 'W' }, { "de", 0, 0, GO_DE }, { "colors", 2, 0, GO_COLORS }, { "no-colors", 0, 0, GO_NO_COLORS }, @@ -961,6 +1014,10 @@ static const struct option OptionLong[] = { "xtridata", 2, 0, GO_XTRIDATA }, { "xtri", 2, 0, GO_XTRIDATA }, { "slot", 1, 0, GO_SLOT }, + { "id", 0, 0, GO_ID }, + { "base64", 2, 0, GO_BASE64 }, + { "db64", 2, 0, GO_DB64 }, + { "coding", 1, 0, GO_CODING }, { "round", 0, 0, GO_ROUND }, { "long", 0, 0, 'l' }, { "no-header", 0, 0, 'H' }, @@ -1040,7 +1097,8 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x054 T */ OPT_TRACKS, /* 0x055 */ 0, /* 0x056 V */ OPT_VERSION, - /* 0x057 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 0x057 W */ OPT_WARN, + /* 0x058 */ 0,0,0,0, 0,0,0,0, 0,0,0, /* 0x063 c */ OPT_CONST, /* 0x064 d */ OPT_DEST, /* 0x065 */ 0,0,0, @@ -1093,20 +1151,24 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x0a0 */ OPT_FLAG_FILE, /* 0x0a1 */ OPT_XTRIDATA, /* 0x0a2 */ OPT_SLOT, - /* 0x0a3 */ OPT_ROUND, - /* 0x0a4 */ OPT_NO_ECHO, - /* 0x0a5 */ OPT_UTF_8, - /* 0x0a6 */ OPT_NO_UTF_8, - /* 0x0a7 */ OPT_FORCE, - /* 0x0a8 */ OPT_REPAIR_MAGICS, - /* 0x0a9 */ OPT_TINY, - /* 0x0aa */ OPT_OLD, - /* 0x0ab */ OPT_STD, - /* 0x0ac */ OPT_NEW, - /* 0x0ad */ OPT_EXTRACT, - /* 0x0ae */ OPT_NUMBER, - /* 0x0af */ OPT_SECTIONS, - /* 0x0b0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 0x0a3 */ OPT_ID, + /* 0x0a4 */ OPT_BASE64, + /* 0x0a5 */ OPT_DB64, + /* 0x0a6 */ OPT_CODING, + /* 0x0a7 */ OPT_ROUND, + /* 0x0a8 */ OPT_NO_ECHO, + /* 0x0a9 */ OPT_UTF_8, + /* 0x0aa */ OPT_NO_UTF_8, + /* 0x0ab */ OPT_FORCE, + /* 0x0ac */ OPT_REPAIR_MAGICS, + /* 0x0ad */ OPT_TINY, + /* 0x0ae */ OPT_OLD, + /* 0x0af */ OPT_STD, + /* 0x0b0 */ OPT_NEW, + /* 0x0b1 */ OPT_EXTRACT, + /* 0x0b2 */ OPT_NUMBER, + /* 0x0b3 */ OPT_SECTIONS, + /* 0x0b4 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x0c0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x0d0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x0e0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, @@ -1122,184 +1184,196 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /////////////// opt_allowed_cmd_* /////////////// /////////////////////////////////////////////////////////////////////////////// -static u8 option_allowed_cmd_VERSION[37] = // cmd #1 +static u8 option_allowed_cmd_VERSION[41] = // cmd #1 { - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,1,0, 0,0,0,0,0, - 0,0,0,0,0, 0,1 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 1 }; -static u8 option_allowed_cmd_HELP[37] = // cmd #2 +static u8 option_allowed_cmd_HELP[41] = // cmd #2 { 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1, 1,1 + 1,1,1,1,1, 1,1,1,1,1, 1 }; -static u8 option_allowed_cmd_CONFIG[37] = // cmd #3 +static u8 option_allowed_cmd_CONFIG[41] = // cmd #3 { - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,1,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_ARGTEST[37] = // cmd #4 +static u8 option_allowed_cmd_ARGTEST[41] = // cmd #4 { 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1, 1,1 + 1,1,1,1,1, 1,1,1,1,1, 1 }; -static u8 option_allowed_cmd_TEST[37] = // cmd #5 +static u8 option_allowed_cmd_TEST[41] = // cmd #5 { 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1, 1,1 + 1,1,1,1,1, 1,1,1,1,1, 1 }; -static u8 option_allowed_cmd_COLORS[37] = // cmd #6 +static u8 option_allowed_cmd_COLORS[41] = // cmd #6 { - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,1,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_ERROR[37] = // cmd #7 +static u8 option_allowed_cmd_ERROR[41] = // cmd #7 { - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,1,1,0, 0,0,0,0,0, - 0,0,0,0,0, 0,1 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,1,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 1 }; -static u8 option_allowed_cmd_FILETYPE[37] = // cmd #8 +static u8 option_allowed_cmd_FILETYPE[41] = // cmd #8 { - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 1,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,1, 0 }; -static u8 option_allowed_cmd_FILEATTRIB[37] = // cmd #9 +static u8 option_allowed_cmd_FILEATTRIB[41] = // cmd #9 { - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_SYMBOLS[37] = // cmd #10 +static u8 option_allowed_cmd_SYMBOLS[41] = // cmd #10 { - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_FUNCTIONS[37] = // cmd #11 +static u8 option_allowed_cmd_FUNCTIONS[41] = // cmd #11 { - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,1,1,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,1,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_CALCULATE[37] = // cmd #12 +static u8 option_allowed_cmd_CALCULATE[41] = // cmd #12 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0 + 0,0,0,0,0, 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_MATRIX[37] = // cmd #13 +static u8 option_allowed_cmd_MATRIX[41] = // cmd #13 { - 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,0,1,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0 + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_FLOAT[37] = // cmd #14 +static u8 option_allowed_cmd_FLOAT[41] = // cmd #14 { - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_EXPORT[37] = // cmd #15 +static u8 option_allowed_cmd_EXPORT[41] = // cmd #15 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0 + 0,0,0,0,0, 0,0,0,0,0, 0 +}; + +static u8 option_allowed_cmd_CAT[41] = // cmd #16 +{ + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,0,0,0,1, + 1,0,0,0,0, 0,0,0,0,1, 0 }; -static u8 option_allowed_cmd_CAT[37] = // cmd #16 +static u8 option_allowed_cmd_DECODE[41] = // cmd #17 { - 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,1,0,0,0, - 0,0,0,0,0, 1,0 + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,0,0,0,1, + 1,1,1,1,1, 1,1,1,1,1, 0 }; -static u8 option_allowed_cmd_DECODE[37] = // cmd #17 +static u8 option_allowed_cmd_ENCODE[41] = // cmd #18 { - 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,1,1,1,1, - 1,1,1,1,1, 1,0 + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,0,0,0,1, + 1,1,1,1,1, 1,1,1,1,1, 0 }; -static u8 option_allowed_cmd_ENCODE[37] = // cmd #18 +static u8 option_allowed_cmd_COPY[41] = // cmd #19 { - 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,1,1,1,1, - 1,1,1,1,1, 1,0 + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,0,0,0,1, + 1,1,1,1,1, 1,1,1,1,1, 0 }; -static u8 option_allowed_cmd_COPY[37] = // cmd #19 +static u8 option_allowed_cmd_CFF[41] = // cmd #20 { - 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,1,1,1,1, - 1,1,1,1,1, 1,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 1,0,1,0,1, + 1,1,1,1,1, 1,1,1,1,1, 0 }; -static u8 option_allowed_cmd_CFF[37] = // cmd #20 +static u8 option_allowed_cmd_TYPES[41] = // cmd #21 { - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,1,0,1,0, 1,1,1,1,1, - 1,1,1,1,1, 1,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_FLAGS[37] = // cmd #21 +static u8 option_allowed_cmd_FLAGS[41] = // cmd #22 { - 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,1,1,0, 0,1,0,0,0, - 0,0,0,0,0, 1,0 + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,1,1,0,0, + 1,0,0,0,0, 0,0,0,0,1, 0 }; -static u8 option_allowed_cmd_DUMP[37] = // cmd #22 +static u8 option_allowed_cmd_DUMP[41] = // cmd #23 { - 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,0,1,0, 0,1,0,0,0, - 0,0,0,0,0, 1,0 + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,0,1,0,0, + 1,0,0,0,0, 0,0,0,0,1, 0 }; -static u8 option_allowed_cmd_DBRIEF[37] = // cmd #23 +static u8 option_allowed_cmd_DBRIEF[41] = // cmd #24 { - 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,0,1,0, 0,1,0,0,0, - 0,0,0,0,0, 1,0 + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,0,1,0,0, + 1,0,0,0,0, 0,0,0,0,1, 0 }; -static u8 option_allowed_cmd_LIST[37] = // cmd #24 +static u8 option_allowed_cmd_LIST[41] = // cmd #25 { - 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,1,0,0,0, - 0,0,0,0,0, 1,0 + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,0,0,0,0, + 1,0,0,0,0, 0,0,0,0,1, 0 }; -static u8 option_allowed_cmd_TRIANGLES[37] = // cmd #25 +static u8 option_allowed_cmd_TRIANGLES[41] = // cmd #26 { - 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,0,1,0, 0,1,0,0,0, - 0,0,0,0,0, 1,0 + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,0,1,0,0, + 1,0,0,0,0, 0,0,0,0,1, 0 }; -static u8 option_allowed_cmd_TRAVERSE[37] = // cmd #26 +static u8 option_allowed_cmd_TRAVERSE[41] = // cmd #27 { - 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,0,1,0, 0,1,0,0,0, - 0,0,0,0,0, 1,0 + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,0,1,0,0, + 1,0,0,0,0, 0,0,0,0,1, 0 }; -static u8 option_allowed_cmd_FALL[37] = // cmd #27 +static u8 option_allowed_cmd_FALL[41] = // cmd #28 { - 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,0,1,0, 0,1,0,0,0, - 0,0,0,0,0, 1,0 + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,0,1,0,0, + 1,0,0,0,0, 0,0,0,0,1, 0 }; -static u8 option_allowed_cmd_CHECK[37] = // cmd #28 +static u8 option_allowed_cmd_CHECK[41] = // cmd #29 { - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,1,0, 1,1,0,0,0, - 0,0,0,0,0, 1,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,0,1,0,1, + 1,0,0,0,0, 0,0,0,0,1, 0 }; -static u8 option_allowed_cmd_ANALYZE[37] = // cmd #29 +static u8 option_allowed_cmd_SHA1[41] = // cmd #30 +{ + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,1, 0 +}; + +static u8 option_allowed_cmd_ANALYZE[41] = // cmd #31 { 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 1,0 + 0,0,0,0,0, 0,0,0,0,1, 0 }; -static u8 option_allowed_cmd_BLOW[37] = // cmd #30 +static u8 option_allowed_cmd_BLOW[41] = // cmd #32 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 1,0 + 0,0,0,0,0, 0,0,0,0,1, 0 }; @@ -1321,6 +1395,7 @@ static const InfoOption_t * option_tab_tool[] = OptionInfo + OPT_QUIET, OptionInfo + OPT_VERBOSE, OptionInfo + OPT_LOGGING, + OptionInfo + OPT_WARN, OptionInfo + OPT_DE, OptionInfo + OPT_COLORS, OptionInfo + OPT_NO_COLORS, @@ -1688,6 +1763,14 @@ static const InfoOption_t * option_tab_cmd_CFF[] = 0 }; +static const InfoOption_t * option_tab_cmd_TYPES[] = +{ + OptionInfo + OPT_NO_HEADER, + &option_cmd_TYPES_BRIEF, + + 0 +}; + static const InfoOption_t * option_tab_cmd_FLAGS[] = { OptionInfo + OPT_NO_HEADER, @@ -1952,6 +2035,44 @@ static const InfoOption_t * option_tab_cmd_CHECK[] = 0 }; +static const InfoOption_t * option_tab_cmd_SHA1[] = +{ + OptionInfo + OPT_IGNORE, + OptionInfo + OPT_ID, + OptionInfo + OPT_BASE64, + OptionInfo + OPT_DB64, + OptionInfo + OPT_CODING, + &option_cmd_SHA1_BRIEF, + + OptionInfo + OPT_NONE, // separator + + OptionInfo + OPT_CONST, + OptionInfo + OPT_SCALE, + OptionInfo + OPT_SHIFT, + OptionInfo + OPT_XSS, + OptionInfo + OPT_YSS, + OptionInfo + OPT_ZSS, + OptionInfo + OPT_ROT, + OptionInfo + OPT_XROT, + OptionInfo + OPT_YROT, + OptionInfo + OPT_ZROT, + OptionInfo + OPT_TRANSLATE, + OptionInfo + OPT_NULL, + OptionInfo + OPT_NEXT, + OptionInfo + OPT_ASCALE, + OptionInfo + OPT_AROT, + OptionInfo + OPT_TFORM_SCRIPT, + OptionInfo + OPT_KCL, + OptionInfo + OPT_KCL_FLAG, + OptionInfo + OPT_KCL_SCRIPT, + OptionInfo + OPT_TRI_AREA, + OptionInfo + OPT_TRI_HEIGHT, + OptionInfo + OPT_FLAG_FILE, + OptionInfo + OPT_SLOT, + + 0 +}; + static const InfoOption_t * option_tab_cmd_ANALYZE[] = { OptionInfo + OPT_IGNORE, @@ -2010,7 +2131,7 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = "Wiimms KCL Tool : Analyze, modify, export and create KCL and OBJ" " files.", 0, - 26, + 27, option_tab_tool, 0 }, @@ -2358,6 +2479,26 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = option_allowed_cmd_CFF }, + { CMD_TYPES, + true, + false, + false, + "TYPES", + 0, + "wkclt TYPES arg...", + "Print a line with KCL flag details for each argument. ARG is a comma" + " or space separated list of a optional BASEVAL and a list of TERMS." + " BASEVAL can be any hexa-decimal number. The format of TERMS is" + " X[=]VALUE. So a TERM begin with letter T (Type), V (Value) or a" + " group identifier (W, X,Y or Z), followed by an optional equal sign" + " and finished by a decimal number. It overrides the related part of" + " BASEVAL.", + 0, + 2, + option_tab_cmd_TYPES, + option_allowed_cmd_TYPES + }, + { CMD_FLAGS, false, false, @@ -2491,6 +2632,21 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = option_allowed_cmd_CHECK }, + { CMD_SHA1, + false, + false, + false, + "SHA1", + 0, + "wszst SHA1 [source]...", + "Print a SHA1 checksum of the KCL for each source. The checksum is" + " calculated after patching.", + 0, + 29, + option_tab_cmd_SHA1, + option_allowed_cmd_SHA1 + }, + { CMD_ANALYZE, true, false, diff --git a/project/src/ui/ui-wkclt.h b/project/src/ui/ui-wkclt.h index a23e0d9..50c89ca 100644 --- a/project/src/ui/ui-wkclt.h +++ b/project/src/ui/ui-wkclt.h @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -75,6 +75,10 @@ typedef enum enumOptions OPT_KCL_SCRIPT, OPT_FLAG_FILE, OPT_SLOT, + OPT_ID, + OPT_BASE64, + OPT_DB64, + OPT_CODING, OPT_ROUND, OPT_LONG, OPT_NO_HEADER, @@ -93,7 +97,7 @@ typedef enum enumOptions OPT_IGNORE, OPT_SECTIONS, - OPT__N_SPECIFIC, // == 37 + OPT__N_SPECIFIC, // == 41 //----- global options ----- @@ -108,6 +112,7 @@ typedef enum enumOptions OPT_QUIET, OPT_VERBOSE, OPT_LOGGING, + OPT_WARN, OPT_DE, OPT_COLORS, OPT_NO_COLORS, @@ -133,7 +138,7 @@ typedef enum enumOptions OPT_NEW, OPT_EXTRACT, - OPT__N_TOTAL // == 72 + OPT__N_TOTAL // == 77 } enumOptions; @@ -167,6 +172,10 @@ typedef enum enumOptions // OB_KCL_SCRIPT = 1llu << OPT_KCL_SCRIPT, // OB_FLAG_FILE = 1llu << OPT_FLAG_FILE, // OB_SLOT = 1llu << OPT_SLOT, +// OB_ID = 1llu << OPT_ID, +// OB_BASE64 = 1llu << OPT_BASE64, +// OB_DB64 = 1llu << OPT_DB64, +// OB_CODING = 1llu << OPT_CODING, // OB_ROUND = 1llu << OPT_ROUND, // OB_LONG = 1llu << OPT_LONG, // OB_NO_HEADER = 1llu << OPT_NO_HEADER, @@ -285,6 +294,9 @@ typedef enum enumOptions // | OB_IGNORE // | OB_FLAG_FILE, // +// OB_CMD_TYPES = OB_NO_HEADER +// | OB_BRIEF, +// // OB_CMD_FLAGS = OB_NO_HEADER // | OB_NO_CHECK // | OB_IGNORE @@ -327,6 +339,14 @@ typedef enum enumOptions // | OB_NO_CHECK // | OB_IGNORE, // +// OB_CMD_SHA1 = OB_IGNORE +// | OB_ID +// | OB_BASE64 +// | OB_DB64 +// | OB_CODING +// | OB_BRIEF +// | OB_GRP_TRANSFORM, +// // OB_CMD_ANALYZE = OB_IGNORE // | OB_GRP_TRANSFORM, // @@ -364,6 +384,7 @@ typedef enum enumCommands CMD_ENCODE, CMD_COPY, CMD_CFF, + CMD_TYPES, CMD_FLAGS, CMD_DUMP, CMD_DBRIEF, @@ -372,11 +393,12 @@ typedef enum enumCommands CMD_TRAVERSE, CMD_FALL, CMD_CHECK, + CMD_SHA1, CMD_ANALYZE, CMD_BLOW, - CMD__N // == 31 + CMD__N // == 33 } enumCommands; @@ -400,6 +422,7 @@ typedef enum enumGetOpt GO_NO_PARAM = 'P', GO_TRACKS = 'T', GO_VERSION = 'V', + GO_WARN = 'W', GO_CONST = 'c', GO_DEST = 'd', @@ -449,6 +472,10 @@ typedef enum enumGetOpt GO_FLAG_FILE, GO_XTRIDATA, GO_SLOT, + GO_ID, + GO_BASE64, + GO_DB64, + GO_CODING, GO_ROUND, GO_NO_ECHO, GO_UTF_8, diff --git a/project/src/ui/ui-wkmpt.c b/project/src/ui/ui-wkmpt.c index 3227bcd..3d566eb 100644 --- a/project/src/ui/ui-wkmpt.c +++ b/project/src/ui/ui-wkmpt.c @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -541,8 +541,8 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_MAX_WIDTH, false, false, false, true, false, 0, "max-width", "maxwidth", "Define the maximum terminal width (number of columns) for help and" - " some other messages and disable the automatic detection of the" - " terminal width. This option is ignored if --width is set." + " some other messages. The default is 120. This option is ignored if" + " --width is set." }, { OPT_QUIET, false, false, false, false, false, 'q', "quiet", @@ -563,6 +563,16 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "This debug option enables the logging of internal lists and maps." }, + { OPT_WARN, false, false, false, false, false, 'W', "warn", + "list", + "Enable or disable warnings. Parameter 'list' is a comma separated" + " list of keywords. A minus sign before a keyword disables a warning." + " Each occurrence of the option will only change entered warning and" + " all other warnings are untouched.\n" + " Keyword DEFAULT resets the default settings, OFF disables and ALL" + " enables all. The other allowed keywords are: INVALID-OFFSET." + }, + { OPT_DE, false, false, false, false, false, 0, "de", 0, "Use german track and arena names." @@ -622,7 +632,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_BATTLE, true, false, false, false, false, 0, "battle", "[=mode]", "MODE is either OFF, AUTO (default) or ON. Without value, ON is used.\n" - " If mode is ON, assume a battle arena and enable a spüecial battle" + " If mode is ON, assume a battle arena and enable a special battle" " support. If mode is OFF, disable special battle arena support. If" " mode is AUTO, analyse the KMP and estimate, if it is a battle" " areana. Modes ON and OFF override KMP parameter BATTLE-MODE." @@ -867,7 +877,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " helper option." }, - {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 93 + {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 94 }; @@ -1151,7 +1161,7 @@ static const KeywordTab_t CommandTab[] = /////////////// OptionShort & OptionLong /////////////// /////////////////////////////////////////////////////////////////////////////// -static const char OptionShort[] = "VhqvLc:w:lHBXPGNM:T:A:td:D:E:orupi"; +static const char OptionShort[] = "VhqvLW:c:w:lHBXPGNM:T:A:td:D:E:orupi"; static const struct option OptionLong[] = { @@ -1168,6 +1178,7 @@ static const struct option OptionLong[] = { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, { "logging", 0, 0, 'L' }, + { "warn", 1, 0, 'W' }, { "de", 0, 0, GO_DE }, { "colors", 2, 0, GO_COLORS }, { "no-colors", 0, 0, GO_NO_COLORS }, @@ -1328,7 +1339,7 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x054 T */ OPT_TRACKS, /* 0x055 */ 0, /* 0x056 V */ OPT_VERSION, - /* 0x057 */ 0, + /* 0x057 W */ OPT_WARN, /* 0x058 X */ OPT_EXPORT, /* 0x059 */ 0,0,0,0, 0,0,0,0, 0,0, /* 0x063 c */ OPT_CONST, @@ -1629,6 +1640,7 @@ static const InfoOption_t * option_tab_tool[] = OptionInfo + OPT_QUIET, OptionInfo + OPT_VERBOSE, OptionInfo + OPT_LOGGING, + OptionInfo + OPT_WARN, OptionInfo + OPT_DE, OptionInfo + OPT_COLORS, OptionInfo + OPT_NO_COLORS, @@ -2184,7 +2196,7 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = "Wiimms KMP Tool : Analyze, modify, export and create (compile) KMP" " files.", 0, - 35, + 36, option_tab_tool, 0 }, diff --git a/project/src/ui/ui-wkmpt.h b/project/src/ui/ui-wkmpt.h index 7c0fbe2..a40d695 100644 --- a/project/src/ui/ui-wkmpt.h +++ b/project/src/ui/ui-wkmpt.h @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -120,6 +120,7 @@ typedef enum enumOptions OPT_QUIET, OPT_VERBOSE, OPT_LOGGING, + OPT_WARN, OPT_DE, OPT_COLORS, OPT_NO_COLORS, @@ -154,7 +155,7 @@ typedef enum enumOptions OPT_NEW, OPT_EXTRACT, - OPT__N_TOTAL // == 93 + OPT__N_TOTAL // == 94 } enumOptions; @@ -435,6 +436,7 @@ typedef enum enumGetOpt GO_NO_PARAM = 'P', GO_TRACKS = 'T', GO_VERSION = 'V', + GO_WARN = 'W', GO_EXPORT = 'X', GO_CONST = 'c', diff --git a/project/src/ui/ui-wlect.c b/project/src/ui/ui-wlect.c index ef0a3e4..1c67b0d 100644 --- a/project/src/ui/ui-wlect.c +++ b/project/src/ui/ui-wlect.c @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -117,6 +117,13 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " CT-TEXT)." }, + { OPT_LE_ARENA, false, true, false, false, false, 0, "le-arena", + "file", + "Use this file to define property and music defaults for arenas. The" + " file format can be an text file. Option --le-define may override" + " these defaults." + }, + { OPT_LPAR, false, false, false, false, false, 0, "lpar", "file", "Read a LPAR file to overwrite settings of LE-CODE section LPAR." @@ -351,7 +358,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "Print in machine readable sections and parameter lines." }, - {0,0,0,0,0,0,0,0,0,0}, // OPT__N_SPECIFIC == 43 + {0,0,0,0,0,0,0,0,0,0}, // OPT__N_SPECIFIC == 44 //----- global options ----- @@ -407,8 +414,8 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_MAX_WIDTH, false, false, false, true, false, 0, "max-width", "maxwidth", "Define the maximum terminal width (number of columns) for help and" - " some other messages and disable the automatic detection of the" - " terminal width. This option is ignored if --width is set." + " some other messages. The default is 120. This option is ignored if" + " --width is set." }, { OPT_QUIET, false, false, false, false, false, 'q', "quiet", @@ -429,6 +436,16 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "This debug option enables the logging of internal lists and maps." }, + { OPT_WARN, false, false, false, false, false, 'W', "warn", + "list", + "Enable or disable warnings. Parameter 'list' is a comma separated" + " list of keywords. A minus sign before a keyword disables a warning." + " Each occurrence of the option will only change entered warning and" + " all other warnings are untouched.\n" + " Keyword DEFAULT resets the default settings, OFF disables and ALL" + " enables all. The other allowed keywords are: INVALID-OFFSET." + }, + { OPT_DE, false, false, false, false, false, 0, "de", 0, "Use german track and arena names." @@ -595,7 +612,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " helper option." }, - {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 77 + {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 79 }; @@ -756,7 +773,7 @@ static const KeywordTab_t CommandTab[] = /////////////// OptionShort & OptionLong /////////////// /////////////////////////////////////////////////////////////////////////////// -static const char OptionShort[] = "VhqvLc:lHBXPM:tCd:D:E:orupi"; +static const char OptionShort[] = "VhqvLW:c:lHBXPM:tCd:D:E:orupi"; static const struct option OptionLong[] = { @@ -773,6 +790,7 @@ static const struct option OptionLong[] = { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, { "logging", 0, 0, 'L' }, + { "warn", 1, 0, 'W' }, { "de", 0, 0, GO_DE }, { "colors", 2, 0, GO_COLORS }, { "no-colors", 0, 0, GO_NO_COLORS }, @@ -833,6 +851,8 @@ static const struct option OptionLong[] = { "EXTRACT", 0, 0, GO_EXTRACT }, { "le-define", 1, 0, GO_LE_DEFINE }, { "ledefine", 1, 0, GO_LE_DEFINE }, + { "le-arena", 1, 0, GO_LE_ARENA }, + { "learena", 1, 0, GO_LE_ARENA }, { "lpar", 1, 0, GO_LPAR }, { "alias", 1, 0, GO_ALIAS }, { "engine", 1, 0, GO_ENGINE }, @@ -916,7 +936,7 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x050 P */ OPT_NO_PARAM, /* 0x051 */ 0,0,0,0, 0, /* 0x056 V */ OPT_VERSION, - /* 0x057 */ 0, + /* 0x057 W */ OPT_WARN, /* 0x058 X */ OPT_EXPORT, /* 0x059 */ 0,0,0,0, 0,0,0,0, 0,0, /* 0x063 c */ OPT_CONST, @@ -968,29 +988,30 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x09d */ OPT_NEW, /* 0x09e */ OPT_EXTRACT, /* 0x09f */ OPT_LE_DEFINE, - /* 0x0a0 */ OPT_LPAR, - /* 0x0a1 */ OPT_ALIAS, - /* 0x0a2 */ OPT_ENGINE, - /* 0x0a3 */ OPT_200CC, - /* 0x0a4 */ OPT_PERFMON, - /* 0x0a5 */ OPT_CUSTOM_TT, - /* 0x0a6 */ OPT_XPFLAGS, - /* 0x0a7 */ OPT_SPEEDOMETER, - /* 0x0a8 */ OPT_DEBUG, - /* 0x0a9 */ OPT_TRACK_DIR, - /* 0x0aa */ OPT_COPY_TRACKS, - /* 0x0ab */ OPT_MOVE_TRACKS, - /* 0x0ac */ OPT_MOVE1_TRACKS, - /* 0x0ad */ OPT_LINK_TRACKS, - /* 0x0ae */ OPT_LOAD_BMG, - /* 0x0af */ OPT_PATCH_BMG, - /* 0x0b0 */ OPT_MACRO_BMG, - /* 0x0b1 */ OPT_PATCH_NAMES, - /* 0x0b2 */ OPT_ORDER_BY, - /* 0x0b3 */ OPT_ORDER_ALL, - /* 0x0b4 */ OPT_NUMBER, - /* 0x0b5 */ OPT_SECTIONS, - /* 0x0b6 */ 0,0,0,0, 0,0,0,0, 0,0, + /* 0x0a0 */ OPT_LE_ARENA, + /* 0x0a1 */ OPT_LPAR, + /* 0x0a2 */ OPT_ALIAS, + /* 0x0a3 */ OPT_ENGINE, + /* 0x0a4 */ OPT_200CC, + /* 0x0a5 */ OPT_PERFMON, + /* 0x0a6 */ OPT_CUSTOM_TT, + /* 0x0a7 */ OPT_XPFLAGS, + /* 0x0a8 */ OPT_SPEEDOMETER, + /* 0x0a9 */ OPT_DEBUG, + /* 0x0aa */ OPT_TRACK_DIR, + /* 0x0ab */ OPT_COPY_TRACKS, + /* 0x0ac */ OPT_MOVE_TRACKS, + /* 0x0ad */ OPT_MOVE1_TRACKS, + /* 0x0ae */ OPT_LINK_TRACKS, + /* 0x0af */ OPT_LOAD_BMG, + /* 0x0b0 */ OPT_PATCH_BMG, + /* 0x0b1 */ OPT_MACRO_BMG, + /* 0x0b2 */ OPT_PATCH_NAMES, + /* 0x0b3 */ OPT_ORDER_BY, + /* 0x0b4 */ OPT_ORDER_ALL, + /* 0x0b5 */ OPT_NUMBER, + /* 0x0b6 */ OPT_SECTIONS, + /* 0x0b7 */ 0,0,0,0, 0,0,0,0, 0, /* 0x0c0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x0d0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x0e0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, @@ -1006,154 +1027,154 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /////////////// opt_allowed_cmd_* /////////////// /////////////////////////////////////////////////////////////////////////////// -static u8 option_allowed_cmd_VERSION[43] = // cmd #1 +static u8 option_allowed_cmd_VERSION[44] = // cmd #1 { 0,0,1,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,1 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1 }; -static u8 option_allowed_cmd_HELP[43] = // cmd #2 +static u8 option_allowed_cmd_HELP[44] = // cmd #2 { 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1 + 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1 }; -static u8 option_allowed_cmd_CONFIG[43] = // cmd #3 +static u8 option_allowed_cmd_CONFIG[44] = // cmd #3 { 0,0,1,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_ARGTEST[43] = // cmd #4 +static u8 option_allowed_cmd_ARGTEST[44] = // cmd #4 { 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1 + 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1 }; -static u8 option_allowed_cmd_TEST[43] = // cmd #5 +static u8 option_allowed_cmd_TEST[44] = // cmd #5 { 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1 + 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1 }; -static u8 option_allowed_cmd_COLORS[43] = // cmd #6 +static u8 option_allowed_cmd_COLORS[44] = // cmd #6 { 0,0,1,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_ERROR[43] = // cmd #7 +static u8 option_allowed_cmd_ERROR[44] = // cmd #7 { 0,0,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,1 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1 }; -static u8 option_allowed_cmd_FILETYPE[43] = // cmd #8 +static u8 option_allowed_cmd_FILETYPE[44] = // cmd #8 { 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,1,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0 }; -static u8 option_allowed_cmd_FILEATTRIB[43] = // cmd #9 +static u8 option_allowed_cmd_FILEATTRIB[44] = // cmd #9 { 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_SYMBOLS[43] = // cmd #10 +static u8 option_allowed_cmd_SYMBOLS[44] = // cmd #10 { 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_FUNCTIONS[43] = // cmd #11 +static u8 option_allowed_cmd_FUNCTIONS[44] = // cmd #11 { 0,0,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_CALCULATE[43] = // cmd #12 +static u8 option_allowed_cmd_CALCULATE[44] = // cmd #12 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_FLOAT[43] = // cmd #13 +static u8 option_allowed_cmd_FLOAT[44] = // cmd #13 { 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_EXPORT[43] = // cmd #14 +static u8 option_allowed_cmd_EXPORT[44] = // cmd #14 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_DPAD[43] = // cmd #15 +static u8 option_allowed_cmd_DPAD[44] = // cmd #15 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_DUMP[43] = // cmd #16 +static u8 option_allowed_cmd_DUMP[44] = // cmd #16 { - 0,0,1,0,0, 0,0,0,0,0, 0,1,1,1,1, 1,1,1,1,1, 1,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,1,0,0, 0,0,0,0,0, 0,1,1,1,1, 1,1,1,1,1, 1,1,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_DL[43] = // cmd #17 +static u8 option_allowed_cmd_DL[44] = // cmd #17 { - 0,0,1,0,0, 0,0,0,0,0, 0,1,1,1,1, 1,1,1,1,1, 1,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,1,0,0, 0,0,0,0,0, 0,1,1,1,1, 1,1,1,1,1, 1,1,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_DLL[43] = // cmd #18 +static u8 option_allowed_cmd_DLL[44] = // cmd #18 { - 0,0,1,0,0, 0,0,0,0,0, 0,1,1,1,1, 1,1,1,1,1, 1,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,1,0,0, 0,0,0,0,0, 0,1,1,1,1, 1,1,1,1,1, 1,1,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_BIN_DIFF[43] = // cmd #19 +static u8 option_allowed_cmd_BIN_DIFF[44] = // cmd #19 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 }; -static u8 option_allowed_cmd_PATCH[43] = // cmd #20 +static u8 option_allowed_cmd_PATCH[44] = // cmd #20 { - 0,0,0,0,0, 0,0,0,0,0, 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,0,0,0,0, - 0,0,0,1,1, 1,1,1,1,1, 1,1,0 + 0,0,0,0,0, 0,0,0,0,0, 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,0,0,0, + 0,0,0,0,1, 1,1,1,1,1, 1,1,1,0 }; -static u8 option_allowed_cmd_LPAR[43] = // cmd #21 +static u8 option_allowed_cmd_LPAR[44] = // cmd #21 { - 0,0,0,1,1, 1,0,0,0,0, 0,1,1,1,1, 1,1,1,1,1, 1,0,0,0,0, 0,0,0,0,0, - 0,0,0,1,1, 1,1,1,1,1, 1,1,0 + 0,0,0,1,1, 1,0,0,0,0, 0,1,1,1,1, 1,1,1,1,1, 1,1,0,0,0, 0,0,0,0,0, + 0,0,0,0,1, 1,1,1,1,1, 1,1,1,0 }; -static u8 option_allowed_cmd_CREATE[43] = // cmd #22 +static u8 option_allowed_cmd_CREATE[44] = // cmd #22 { - 0,0,0,1,1, 1,0,1,1,1, 1,0,1,0,1, 1,1,1,1,1, 1,0,0,0,0, 0,0,0,0,0, - 0,0,0,1,1, 1,1,1,1,1, 1,1,0 + 0,0,0,1,1, 1,0,1,1,1, 1,0,0,1,0, 1,1,1,1,1, 1,1,0,0,0, 0,0,0,0,0, + 0,0,0,0,1, 1,1,1,1,1, 1,1,1,0 }; -static u8 option_allowed_cmd_CAT[43] = // cmd #23 +static u8 option_allowed_cmd_CAT[44] = // cmd #23 { - 0,0,0,1,1, 1,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,1,0 + 0,0,0,1,1, 1,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0 }; -static u8 option_allowed_cmd_DECODE[43] = // cmd #24 +static u8 option_allowed_cmd_DECODE[44] = // cmd #24 { - 0,0,0,1,1, 1,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, - 0,0,0,1,1, 1,1,1,1,1, 1,1,0 + 0,0,0,1,1, 1,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, + 0,0,0,0,1, 1,1,1,1,1, 1,1,1,0 }; -static u8 option_allowed_cmd_ENCODE[43] = // cmd #25 +static u8 option_allowed_cmd_ENCODE[44] = // cmd #25 { - 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, - 0,0,0,1,1, 1,1,1,1,1, 1,1,0 + 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, + 0,0,0,0,1, 1,1,1,1,1, 1,1,1,0 }; @@ -1175,6 +1196,7 @@ static const InfoOption_t * option_tab_tool[] = OptionInfo + OPT_QUIET, OptionInfo + OPT_VERBOSE, OptionInfo + OPT_LOGGING, + OptionInfo + OPT_WARN, OptionInfo + OPT_DE, OptionInfo + OPT_COLORS, OptionInfo + OPT_NO_COLORS, @@ -1573,7 +1595,7 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = "wlect [option]... command [option|parameter|file]...", "Wiimms LE-CODE Tool : Manage the LE-CODE and LEX extensions.", 0, - 27, + 28, option_tab_tool, 0 }, diff --git a/project/src/ui/ui-wlect.h b/project/src/ui/ui-wlect.h index 15ffb62..4e6198e 100644 --- a/project/src/ui/ui-wlect.h +++ b/project/src/ui/ui-wlect.h @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -67,6 +67,7 @@ typedef enum enumOptions OPT_LT_ONLINE, OPT_LT_N_PLAYERS, OPT_LE_DEFINE, + OPT_LE_ARENA, OPT_LPAR, OPT_ALIAS, OPT_ENGINE, @@ -99,7 +100,7 @@ typedef enum enumOptions OPT_IGNORE, OPT_SECTIONS, - OPT__N_SPECIFIC, // == 43 + OPT__N_SPECIFIC, // == 44 //----- global options ----- @@ -114,6 +115,7 @@ typedef enum enumOptions OPT_QUIET, OPT_VERBOSE, OPT_LOGGING, + OPT_WARN, OPT_DE, OPT_COLORS, OPT_NO_COLORS, @@ -138,7 +140,7 @@ typedef enum enumOptions OPT_NEW, OPT_EXTRACT, - OPT__N_TOTAL // == 77 + OPT__N_TOTAL // == 79 } enumOptions; @@ -164,6 +166,7 @@ typedef enum enumOptions // OB_LT_ONLINE = 1llu << OPT_LT_ONLINE, // OB_LT_N_PLAYERS = 1llu << OPT_LT_N_PLAYERS, // OB_LE_DEFINE = 1llu << OPT_LE_DEFINE, +// OB_LE_ARENA = 1llu << OPT_LE_ARENA, // OB_LPAR = 1llu << OPT_LPAR, // OB_ALIAS = 1llu << OPT_ALIAS, // OB_ENGINE = 1llu << OPT_ENGINE, @@ -216,6 +219,7 @@ typedef enum enumOptions // | OB_DEBUG, // // OB_GRP_PATCH = OB_LE_DEFINE +// | OB_LE_ARENA // | OB_LPAR // | OB_ALIAS // | OB_GRP_PARAM, @@ -379,6 +383,7 @@ typedef enum enumGetOpt GO_MAX_FILE_SIZE = 'M', GO_NO_PARAM = 'P', GO_VERSION = 'V', + GO_WARN = 'W', GO_EXPORT = 'X', GO_CONST = 'c', @@ -426,6 +431,7 @@ typedef enum enumGetOpt GO_NEW, GO_EXTRACT, GO_LE_DEFINE, + GO_LE_ARENA, GO_LPAR, GO_ALIAS, GO_ENGINE, diff --git a/project/src/ui/ui-wmdlt.c b/project/src/ui/ui-wmdlt.c index 712ab1e..14d0016 100644 --- a/project/src/ui/ui-wmdlt.c +++ b/project/src/ui/ui-wmdlt.c @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -371,8 +371,8 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_MAX_WIDTH, false, false, false, true, false, 0, "max-width", "maxwidth", "Define the maximum terminal width (number of columns) for help and" - " some other messages and disable the automatic detection of the" - " terminal width. This option is ignored if --width is set." + " some other messages. The default is 120. This option is ignored if" + " --width is set." }, { OPT_QUIET, false, false, false, false, false, 'q', "quiet", @@ -393,6 +393,16 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "This debug option enables the logging of internal lists and maps." }, + { OPT_WARN, false, false, false, false, false, 'W', "warn", + "list", + "Enable or disable warnings. Parameter 'list' is a comma separated" + " list of keywords. A minus sign before a keyword disables a warning." + " Each occurrence of the option will only change entered warning and" + " all other warnings are untouched.\n" + " Keyword DEFAULT resets the default settings, OFF disables and ALL" + " enables all. The other allowed keywords are: INVALID-OFFSET." + }, + { OPT_DE, false, false, false, false, false, 0, "de", 0, "Use german track and arena names." @@ -562,7 +572,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " helper option." }, - {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 65 + {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 66 }; @@ -719,7 +729,7 @@ static const KeywordTab_t CommandTab[] = /////////////// OptionShort & OptionLong /////////////// /////////////////////////////////////////////////////////////////////////////// -static const char OptionShort[] = "VhqvLc:lHBPNM:T:A:td:D:E:orupi"; +static const char OptionShort[] = "VhqvLW:c:lHBPNM:T:A:td:D:E:orupi"; static const struct option OptionLong[] = { @@ -736,6 +746,7 @@ static const struct option OptionLong[] = { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, { "logging", 0, 0, 'L' }, + { "warn", 1, 0, 'W' }, { "de", 0, 0, GO_DE }, { "colors", 2, 0, GO_COLORS }, { "no-colors", 0, 0, GO_NO_COLORS }, @@ -843,7 +854,8 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x054 T */ OPT_TRACKS, /* 0x055 */ 0, /* 0x056 V */ OPT_VERSION, - /* 0x057 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 0x057 W */ OPT_WARN, + /* 0x058 */ 0,0,0,0, 0,0,0,0, 0,0,0, /* 0x063 c */ OPT_CONST, /* 0x064 d */ OPT_DEST, /* 0x065 */ 0,0,0, @@ -1064,6 +1076,7 @@ static const InfoOption_t * option_tab_tool[] = OptionInfo + OPT_QUIET, OptionInfo + OPT_VERBOSE, OptionInfo + OPT_LOGGING, + OptionInfo + OPT_WARN, OptionInfo + OPT_DE, OptionInfo + OPT_COLORS, OptionInfo + OPT_NO_COLORS, @@ -1439,7 +1452,7 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = "wmdlt [option]... command [option|parameter|file]...", "Wiimms MDL Tool : Decode raw MDL and encode text MDL files.", 0, - 24, + 25, option_tab_tool, 0 }, diff --git a/project/src/ui/ui-wmdlt.h b/project/src/ui/ui-wmdlt.h index 80b7b9b..54e94e3 100644 --- a/project/src/ui/ui-wmdlt.h +++ b/project/src/ui/ui-wmdlt.h @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -104,6 +104,7 @@ typedef enum enumOptions OPT_QUIET, OPT_VERBOSE, OPT_LOGGING, + OPT_WARN, OPT_DE, OPT_COLORS, OPT_NO_COLORS, @@ -126,7 +127,7 @@ typedef enum enumOptions OPT_NEW, OPT_EXTRACT, - OPT__N_TOTAL // == 65 + OPT__N_TOTAL // == 66 } enumOptions; @@ -343,6 +344,7 @@ typedef enum enumGetOpt GO_NO_PARAM = 'P', GO_TRACKS = 'T', GO_VERSION = 'V', + GO_WARN = 'W', GO_CONST = 'c', GO_DEST = 'd', diff --git a/project/src/ui/ui-wpatt.c b/project/src/ui/ui-wpatt.c index 3e4d23a..b0df846 100644 --- a/project/src/ui/ui-wpatt.c +++ b/project/src/ui/ui-wpatt.c @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -213,8 +213,8 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_MAX_WIDTH, false, false, false, true, false, 0, "max-width", "maxwidth", "Define the maximum terminal width (number of columns) for help and" - " some other messages and disable the automatic detection of the" - " terminal width. This option is ignored if --width is set." + " some other messages. The default is 120. This option is ignored if" + " --width is set." }, { OPT_QUIET, false, false, false, false, false, 'q', "quiet", @@ -235,6 +235,16 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "This debug option enables the logging of internal lists and maps." }, + { OPT_WARN, false, false, false, false, false, 'W', "warn", + "list", + "Enable or disable warnings. Parameter 'list' is a comma separated" + " list of keywords. A minus sign before a keyword disables a warning." + " Each occurrence of the option will only change entered warning and" + " all other warnings are untouched.\n" + " Keyword DEFAULT resets the default settings, OFF disables and ALL" + " enables all. The other allowed keywords are: INVALID-OFFSET." + }, + { OPT_DE, false, false, false, false, false, 0, "de", 0, "Use german track and arena names." @@ -393,7 +403,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " helper option." }, - {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 49 + {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 50 }; @@ -516,7 +526,7 @@ static const KeywordTab_t CommandTab[] = /////////////// OptionShort & OptionLong /////////////// /////////////////////////////////////////////////////////////////////////////// -static const char OptionShort[] = "VhqvLc:lHBPNM:T:A:td:D:E:orupi"; +static const char OptionShort[] = "VhqvLW:c:lHBPNM:T:A:td:D:E:orupi"; static const struct option OptionLong[] = { @@ -533,6 +543,7 @@ static const struct option OptionLong[] = { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, { "logging", 0, 0, 'L' }, + { "warn", 1, 0, 'W' }, { "de", 0, 0, GO_DE }, { "colors", 2, 0, GO_COLORS }, { "no-colors", 0, 0, GO_NO_COLORS }, @@ -622,7 +633,8 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x054 T */ OPT_TRACKS, /* 0x055 */ 0, /* 0x056 V */ OPT_VERSION, - /* 0x057 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 0x057 W */ OPT_WARN, + /* 0x058 */ 0,0,0,0, 0,0,0,0, 0,0,0, /* 0x063 c */ OPT_CONST, /* 0x064 d */ OPT_DEST, /* 0x065 */ 0,0,0, @@ -787,6 +799,7 @@ static const InfoOption_t * option_tab_tool[] = OptionInfo + OPT_QUIET, OptionInfo + OPT_VERBOSE, OptionInfo + OPT_LOGGING, + OptionInfo + OPT_WARN, OptionInfo + OPT_DE, OptionInfo + OPT_COLORS, OptionInfo + OPT_NO_COLORS, @@ -987,7 +1000,7 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = "wpatt [option]... command [option|parameter|file]...", "Wiimms PAT Tool : Decode raw PAT and encode text PAT files.", 0, - 23, + 24, option_tab_tool, 0 }, diff --git a/project/src/ui/ui-wpatt.h b/project/src/ui/ui-wpatt.h index 06cf1ed..414f0a8 100644 --- a/project/src/ui/ui-wpatt.h +++ b/project/src/ui/ui-wpatt.h @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -89,6 +89,7 @@ typedef enum enumOptions OPT_QUIET, OPT_VERBOSE, OPT_LOGGING, + OPT_WARN, OPT_DE, OPT_COLORS, OPT_NO_COLORS, @@ -110,7 +111,7 @@ typedef enum enumOptions OPT_NEW, OPT_EXTRACT, - OPT__N_TOTAL // == 49 + OPT__N_TOTAL // == 50 } enumOptions; @@ -266,6 +267,7 @@ typedef enum enumGetOpt GO_NO_PARAM = 'P', GO_TRACKS = 'T', GO_VERSION = 'V', + GO_WARN = 'W', GO_CONST = 'c', GO_DEST = 'd', diff --git a/project/src/ui/ui-wstrt.c b/project/src/ui/ui-wstrt.c index 32cace8..b82ca2a 100644 --- a/project/src/ui/ui-wstrt.c +++ b/project/src/ui/ui-wstrt.c @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -306,7 +306,14 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_NO_0X, false, false, false, false, false, '0', "no-0x", 0, - "Suppress 0x prefix of hex numbers." + "Suppress 0x prefix of hex numbers. This is the default for cheat" + " codes." + }, + + { OPT_UPPER, false, false, false, false, false, 'U', "upper", + 0, + "Print digits A-F of hex numbers in upper case. This is the default" + " for cheat codes." }, { OPT_VADDR, false, false, false, false, true, 0, "vaddr", @@ -479,7 +486,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " dependent (multiple of format size)." }, - {0,0,0,0,0,0,0,0,0,0}, // OPT__N_SPECIFIC == 65 + {0,0,0,0,0,0,0,0,0,0}, // OPT__N_SPECIFIC == 66 //----- global options ----- @@ -540,8 +547,8 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_MAX_WIDTH, false, false, false, true, false, 0, "max-width", "maxwidth", "Define the maximum terminal width (number of columns) for help and" - " some other messages and disable the automatic detection of the" - " terminal width. This option is ignored if --width is set." + " some other messages. The default is 120. This option is ignored if" + " --width is set." }, { OPT_QUIET, false, false, false, false, false, 'q', "quiet", @@ -562,6 +569,16 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "This debug option enables the logging of internal lists and maps." }, + { OPT_WARN, false, false, false, false, false, 'W', "warn", + "list", + "Enable or disable warnings. Parameter 'list' is a comma separated" + " list of keywords. A minus sign before a keyword disables a warning." + " Each occurrence of the option will only change entered warning and" + " all other warnings are untouched.\n" + " Keyword DEFAULT resets the default settings, OFF disables and ALL" + " enables all. The other allowed keywords are: INVALID-OFFSET." + }, + { OPT_DE, false, false, false, false, false, 0, "de", 0, "Use german track and arena names." @@ -869,7 +886,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " directory." }, - {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 116 + {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 118 }; @@ -1079,7 +1096,7 @@ static const KeywordTab_t CommandTab[] = /////////////// OptionShort & OptionLong /////////////// /////////////////////////////////////////////////////////////////////////////// -static const char OptionShort[] = "Vh@qvLc:lBHT:A:R:td:D:E:orupi0"; +static const char OptionShort[] = "Vh@qvLW:c:lBHT:A:R:td:D:E:orupi0U"; static const struct option OptionLong[] = { @@ -1097,6 +1114,7 @@ static const struct option OptionLong[] = { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, { "logging", 0, 0, 'L' }, + { "warn", 1, 0, 'W' }, { "de", 0, 0, GO_DE }, { "colors", 2, 0, GO_COLORS }, { "no-colors", 0, 0, GO_NO_COLORS }, @@ -1210,6 +1228,7 @@ static const struct option OptionLong[] = { "order", 1, 0, GO_ORDER }, { "no-0x", 0, 0, '0' }, { "no0x", 0, 0, '0' }, + { "upper", 0, 0, 'U' }, { "vaddr", 1, 0, GO_VADDR }, { "va", 1, 0, GO_VADDR }, { "faddr", 1, 0, GO_FADDR }, @@ -1281,9 +1300,10 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x052 R */ OPT_REGION, /* 0x053 */ 0, /* 0x054 T */ OPT_TRACKS, - /* 0x055 */ 0, + /* 0x055 U */ OPT_UPPER, /* 0x056 V */ OPT_VERSION, - /* 0x057 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 0x057 W */ OPT_WARN, + /* 0x058 */ 0,0,0,0, 0,0,0,0, 0,0,0, /* 0x063 c */ OPT_CONST, /* 0x064 d */ OPT_DEST, /* 0x065 */ 0,0,0, @@ -1407,172 +1427,172 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /////////////// opt_allowed_cmd_* /////////////// /////////////////////////////////////////////////////////////////////////////// -static u8 option_allowed_cmd_VERSION[65] = // cmd #1 +static u8 option_allowed_cmd_VERSION[66] = // cmd #1 { 0,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_HELP[65] = // cmd #2 +static u8 option_allowed_cmd_HELP[66] = // cmd #2 { 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1 + 1,1,1,1,1, 1 }; -static u8 option_allowed_cmd_CONFIG[65] = // cmd #3 +static u8 option_allowed_cmd_CONFIG[66] = // cmd #3 { 0,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_ARGTEST[65] = // cmd #4 +static u8 option_allowed_cmd_ARGTEST[66] = // cmd #4 { 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1 + 1,1,1,1,1, 1 }; -static u8 option_allowed_cmd_TEST[65] = // cmd #5 +static u8 option_allowed_cmd_TEST[66] = // cmd #5 { 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1 + 1,1,1,1,1, 1 }; -static u8 option_allowed_cmd_COLORS[65] = // cmd #6 +static u8 option_allowed_cmd_COLORS[66] = // cmd #6 { 0,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_ERROR[65] = // cmd #7 +static u8 option_allowed_cmd_ERROR[66] = // cmd #7 { 0,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_FILETYPE[65] = // cmd #8 +static u8 option_allowed_cmd_FILETYPE[66] = // cmd #8 { 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_FILEATTRIB[65] = // cmd #9 +static u8 option_allowed_cmd_FILEATTRIB[66] = // cmd #9 { 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_RAWDUMP[65] = // cmd #10 +static u8 option_allowed_cmd_RAWDUMP[66] = // cmd #10 { 0,0,0,0,0, 0,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_DUMP[65] = // cmd #11 +static u8 option_allowed_cmd_DUMP[66] = // cmd #11 { 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_CDUMP[65] = // cmd #12 +static u8 option_allowed_cmd_CDUMP[66] = // cmd #12 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_HEXDUMP[65] = // cmd #13 +static u8 option_allowed_cmd_HEXDUMP[66] = // cmd #13 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1 + 0,0,0,0,0, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, + 1,1,1,1,1, 1 }; -static u8 option_allowed_cmd_PORT[65] = // cmd #14 +static u8 option_allowed_cmd_PORT[66] = // cmd #14 { 0,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,1,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_WHERE[65] = // cmd #15 +static u8 option_allowed_cmd_WHERE[66] = // cmd #15 { 0,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_HTTPS[65] = // cmd #16 +static u8 option_allowed_cmd_HTTPS[66] = // cmd #16 { 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_EXTRACT[65] = // cmd #17 +static u8 option_allowed_cmd_EXTRACT[66] = // cmd #17 { 0,0,0,0,0, 0,1,1,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_TRACKS[65] = // cmd #18 +static u8 option_allowed_cmd_TRACKS[66] = // cmd #18 { 0,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_ARENAS[65] = // cmd #19 +static u8 option_allowed_cmd_ARENAS[66] = // cmd #19 { 0,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_FILES[65] = // cmd #20 +static u8 option_allowed_cmd_FILES[66] = // cmd #20 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_FIND[65] = // cmd #21 +static u8 option_allowed_cmd_FIND[66] = // cmd #21 { 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_POINTS[65] = // cmd #22 +static u8 option_allowed_cmd_POINTS[66] = // cmd #22 { 0,1,1,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_ANALYZE[65] = // cmd #23 +static u8 option_allowed_cmd_ANALYZE[66] = // cmd #23 { 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; -static u8 option_allowed_cmd_PATCH[65] = // cmd #24 +static u8 option_allowed_cmd_PATCH[66] = // cmd #24 { 0,0,0,0,0, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0 + 0,0,0,0,0, 0 }; @@ -1594,6 +1614,7 @@ static const InfoOption_t * option_tab_tool[] = OptionInfo + OPT_QUIET, OptionInfo + OPT_VERBOSE, OptionInfo + OPT_LOGGING, + OptionInfo + OPT_WARN, OptionInfo + OPT_DE, OptionInfo + OPT_COLORS, OptionInfo + OPT_NO_COLORS, @@ -1772,6 +1793,7 @@ static const InfoOption_t * option_tab_cmd_PORT[] = OptionInfo + OPT_PORT_DB, OptionInfo + OPT_ORDER, OptionInfo + OPT_NO_0X, + OptionInfo + OPT_UPPER, &option_cmd_PORT_NO_HEADER, &option_cmd_PORT_BRIEF, &option_cmd_PORT_LONG, @@ -1783,6 +1805,7 @@ static const InfoOption_t * option_tab_cmd_WHERE[] = { OptionInfo + OPT_ORDER, OptionInfo + OPT_NO_0X, + OptionInfo + OPT_UPPER, &option_cmd_WHERE_NO_HEADER, &option_cmd_WHERE_BRIEF, &option_cmd_WHERE_LONG, @@ -1997,7 +2020,7 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = "Wiimms StaticR Tool : Manipulate the 'main.dol' and 'StaticR.rel'" " files of Mario Kart Wii.", 0, - 39, + 40, option_tab_tool, 0 }, @@ -2218,12 +2241,13 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = "The command expects a list of keywords or hex numbers. Keywords are" " PAL (default), USA, JAPAN, KOREA, or any abbreviation of them. They" " select the region for the following addresses. The hex numbers (with" - " or without 0x prefix) are interpreted as addresses. If possible," - " they are ported to all other regions. The result is printed as" - " colorized table.\n" - " This address porting is EXPERIMENTAL!", + " or without 0x prefix) are interpreted as addresses. If an address" + " begins with m or s, then it is interpreted as a file offset for" + " main.dol or staticr.rel. All addresses are ported to all other" + " regions. The result is printed as colorized table. See" + " https://szs.wiimm.de/cmd/wstrt/port for more details.", 0, - 6, + 7, option_tab_cmd_PORT, option_allowed_cmd_PORT }, @@ -2239,9 +2263,10 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = " in which the specified addresses are located is calculated for each" " region. The result is output as a human and machine readable table.\n" " This command is well suited to converting addresses into file" - " offsets and vice versa.", + " offsets and vice versa. See https://szs.wiimm.de/cmd/wstrt/where for" + " more details.", 0, - 5, + 6, option_tab_cmd_WHERE, option_allowed_cmd_WHERE }, diff --git a/project/src/ui/ui-wstrt.h b/project/src/ui/ui-wstrt.h index f3ca5e2..31ecfe0 100644 --- a/project/src/ui/ui-wstrt.h +++ b/project/src/ui/ui-wstrt.h @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -89,6 +89,7 @@ typedef enum enumOptions OPT_PORT_DB, OPT_ORDER, OPT_NO_0X, + OPT_UPPER, OPT_VADDR, OPT_FADDR, OPT_SNAME, @@ -121,7 +122,7 @@ typedef enum enumOptions OPT_WIDE, OPT_BYTES, - OPT__N_SPECIFIC, // == 65 + OPT__N_SPECIFIC, // == 66 //----- global options ----- @@ -137,6 +138,7 @@ typedef enum enumOptions OPT_QUIET, OPT_VERBOSE, OPT_LOGGING, + OPT_WARN, OPT_DE, OPT_COLORS, OPT_NO_COLORS, @@ -177,7 +179,7 @@ typedef enum enumOptions OPT_CLEAN_DOL, OPT_CT_DIR, - OPT__N_TOTAL // == 116 + OPT__N_TOTAL // == 118 } enumOptions; @@ -225,6 +227,7 @@ typedef enum enumOptions // OB_PORT_DB = 1llu << OPT_PORT_DB, // OB_ORDER = 1llu << OPT_ORDER, // OB_NO_0X = 1llu << OPT_NO_0X, +// OB_UPPER = 1llu << OPT_UPPER, // OB_VADDR = 1llu << OPT_VADDR, // OB_FADDR = 1llu << OPT_FADDR, // OB_SNAME = 1llu << OPT_SNAME, @@ -340,12 +343,14 @@ typedef enum enumOptions // OB_CMD_PORT = OB_PORT_DB // | OB_ORDER // | OB_NO_0X +// | OB_UPPER // | OB_NO_HEADER // | OB_BRIEF // | OB_LONG, // // OB_CMD_WHERE = OB_ORDER // | OB_NO_0X +// | OB_UPPER // | OB_NO_HEADER // | OB_BRIEF // | OB_LONG, @@ -459,7 +464,9 @@ typedef enum enumGetOpt GO_LOGGING = 'L', GO_REGION = 'R', GO_TRACKS = 'T', + GO_UPPER = 'U', GO_VERSION = 'V', + GO_WARN = 'W', GO_CONST = 'c', GO_DEST = 'd', diff --git a/project/src/ui/ui-wszst.c b/project/src/ui/ui-wszst.c index 124c1ea..1d62e8e 100644 --- a/project/src/ui/ui-wszst.c +++ b/project/src/ui/ui-wszst.c @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -466,7 +466,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_CODING, false, false, false, false, false, 0, "coding", "mode", "Define the coding of the non alphanumeric characters for BASE64:" - " STANDART (+/=, default), URL (-_=), STAR (-_*) or XML (.-*)." + " STANDARD (+/=, default), URL (-_=), STAR (-_*) or XML (.-*)." }, { OPT_VERIFY, false, false, false, false, false, 0, "verify", @@ -720,6 +720,11 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " https://szs.wiimm.de/opt/source for more details." }, + { OPT_REFERENCE, false, false, false, false, false, 0, "ref", + "path", + "Define a reference SZS." + }, + { OPT_DEST, false, false, false, false, false, 'd', "dest", "path", "Define a destination path (directory/file). The destination - means:" @@ -1127,7 +1132,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "Print in machine readable sections and parameter lines." }, - {0,0,0,0,0,0,0,0,0,0}, // OPT__N_SPECIFIC == 134 + {0,0,0,0,0,0,0,0,0,0}, // OPT__N_SPECIFIC == 135 //----- global options ----- @@ -1183,8 +1188,8 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_MAX_WIDTH, false, false, false, true, false, 0, "max-width", "maxwidth", "Define the maximum terminal width (number of columns) for help and" - " some other messages and disable the automatic detection of the" - " terminal width. This option is ignored if --width is set." + " some other messages. The default is 120. This option is ignored if" + " --width is set." }, { OPT_QUIET, false, false, false, false, false, 'q', "quiet", @@ -1205,6 +1210,16 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = "This debug option enables the logging of internal lists and maps." }, + { OPT_WARN, false, false, false, false, false, 'W', "warn", + "list", + "Enable or disable warnings. Parameter 'list' is a comma separated" + " list of keywords. A minus sign before a keyword disables a warning." + " Each occurrence of the option will only change entered warning and" + " all other warnings are untouched.\n" + " Keyword DEFAULT resets the default settings, OFF disables and ALL" + " enables all. The other allowed keywords are: INVALID-OFFSET." + }, + { OPT_DE, false, false, false, false, false, 0, "de", 0, "Use german track and arena names." @@ -1264,7 +1279,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = { OPT_BATTLE, true, false, false, false, false, 0, "battle", "[=mode]", "MODE is either OFF, AUTO (default) or ON. Without value, ON is used.\n" - " If mode is ON, assume a battle arena and enable a spüecial battle" + " If mode is ON, assume a battle arena and enable a special battle" " support. If mode is OFF, disable special battle arena support. If" " mode is AUTO, analyse the KMP and estimate, if it is a battle" " areana. Modes ON and OFF override KMP parameter BATTLE-MODE." @@ -1753,7 +1768,7 @@ static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] = " helper option." }, - {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 209 + {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == 211 }; @@ -1964,6 +1979,18 @@ static const InfoOption_t option_cmd_TRACKS_LONG = " old BRRES sub file formats too." }; +static const InfoOption_t option_cmd_SIZEOF_SORT = + { OPT_SORT, false, false, false, false, false, 'S', "sort", + "mode", + "Define a sort mode. Keywords are: NONE (default), NAME end SIZE." + }; + +static const InfoOption_t option_cmd_SIZEOF_BRIEF = + { OPT_BRIEF, false, false, false, false, false, 'B', "brief", + 0, + "Limit output to SZS specific data." + }; + static const InfoOption_t option_cmd_LIST_LONG = { OPT_LONG, false, false, false, false, false, 'l', "long", 0, @@ -2058,6 +2085,12 @@ static const InfoOption_t option_cmd_ANALYZE_QUIET = "Suppress logging of input and output files." }; +static const InfoOption_t option_cmd_IS_TEXTURE_LONG = + { OPT_LONG, false, false, false, false, false, 'l', "long", + 0, + "Append a colon and the filename after each status." + }; + static const InfoOption_t option_cmd_FEATURES_BRIEF = { OPT_BRIEF, false, false, false, false, false, 'B', "brief", 0, @@ -2068,7 +2101,7 @@ static const InfoOption_t option_cmd_FEATURES_BRIEF = static const InfoOption_t option_cmd_FEATURES_LONG = { OPT_LONG, false, false, false, false, false, 'l', "long", 0, - "Print additnal comments." + "Print additional comments." }; static const InfoOption_t option_cmd_FEATURES_QUIET = @@ -2258,6 +2291,7 @@ static const KeywordTab_t CommandTab[] = { CMD_TRACKS, "TRACKS", 0, 0 }, { CMD_SCANCACHE, "SCANCACHE", 0, 0 }, { CMD_EXPORT, "_EXPORT", 0, 0 }, + { CMD_SIZEOF, "SIZEOF", 0, 0 }, { CMD_CODE, "_CODE", 0, 0 }, { CMD_RECODE, "_RECODE", 0, 0 }, { CMD_SUBFILE, "_SUBFILE", 0, 0 }, @@ -2288,6 +2322,7 @@ static const KeywordTab_t CommandTab[] = { CMD_SHA1, "SHA1", 0, 0 }, { CMD_ANALYZE, "ANALYZE", "ANA", 0 }, { CMD_ANALYZE, "ANALYSE", 0, 0 }, + { CMD_IS_TEXTURE, "IS-TEXTURE", "ISTEXTURE", 0 }, { CMD_FEATURES, "FEATURES", 0, 0 }, { CMD_DISTRIBUTION, "DISTRIBUTION", "DIST", 0 }, { CMD_DIFF, "DIFF", "CMP", 0 }, @@ -2330,7 +2365,7 @@ static const KeywordTab_t CommandTab[] = /////////////// OptionShort & OptionLong /////////////// /////////////////////////////////////////////////////////////////////////////// -static const char OptionShort[] = "VhqvLc:lHB1XPS:M:T:A:x:ts:d:D:E:orupiNC:nRea"; +static const char OptionShort[] = "VhqvLW:c:lHB1XPS:M:T:A:x:ts:d:D:E:orupiNC:nRea"; static const struct option OptionLong[] = { @@ -2347,6 +2382,7 @@ static const struct option OptionLong[] = { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, { "logging", 0, 0, 'L' }, + { "warn", 1, 0, 'W' }, { "de", 0, 0, GO_DE }, { "colors", 2, 0, GO_COLORS }, { "no-colors", 0, 0, GO_NO_COLORS }, @@ -2575,6 +2611,8 @@ static const struct option OptionLong[] = { "EXTRACT", 1, 0, GO_EXTRACT }, { "source", 1, 0, 's' }, { "src", 1, 0, 's' }, + { "ref", 1, 0, GO_REFERENCE }, + { "reference", 1, 0, GO_REFERENCE }, { "dest", 1, 0, 'd' }, { "DEST", 1, 0, 'D' }, { "esc", 1, 0, 'E' }, @@ -2721,7 +2759,7 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x054 T */ OPT_TRACKS, /* 0x055 */ 0, /* 0x056 V */ OPT_VERSION, - /* 0x057 */ 0, + /* 0x057 W */ OPT_WARN, /* 0x058 X */ OPT_EXPORT, /* 0x059 */ 0,0,0,0, 0,0,0,0, /* 0x061 a */ OPT_ALL, @@ -2880,49 +2918,50 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /* 0x102 */ OPT_STD, /* 0x103 */ OPT_NEW, /* 0x104 */ OPT_EXTRACT, - /* 0x105 */ OPT_NUMBER, - /* 0x106 */ OPT_REMOVE_SRC, - /* 0x107 */ OPT_IGNORE_SETUP, - /* 0x108 */ OPT_PURGE, - /* 0x109 */ OPT_ALIGN_U8, - /* 0x10a */ OPT_ALIGN_PACK, - /* 0x10b */ OPT_ALIGN_BRRES, - /* 0x10c */ OPT_ALIGN_BREFF, - /* 0x10d */ OPT_ALIGN_BREFT, - /* 0x10e */ OPT_ALIGN, - /* 0x10f */ OPT_ENCODE_ALL, - /* 0x110 */ OPT_ENCODE_IMG, - /* 0x111 */ OPT_NO_ENCODE, - /* 0x112 */ OPT_NO_RECURSE, - /* 0x113 */ OPT_AUTO_ADD, - /* 0x114 */ OPT_NO_ECHO, - /* 0x115 */ OPT_PT_DIR, - /* 0x116 */ OPT_RM_AIPARAM, - /* 0x117 */ OPT_U8, - /* 0x118 */ OPT_SZS, - /* 0x119 */ OPT_WU8, - /* 0x11a */ OPT_XWU8, - /* 0x11b */ OPT_WBZ, - /* 0x11c */ OPT_PACK, - /* 0x11d */ OPT_BRRES, - /* 0x11e */ OPT_BREFF, - /* 0x11f */ OPT_BREFT, - /* 0x120 */ OPT_NO_COMPRESS, - /* 0x121 */ OPT_FAST, - /* 0x122 */ OPT_LINKS, - /* 0x123 */ OPT_BASEDIR, - /* 0x124 */ OPT_DECODE, - /* 0x125 */ OPT_MIPMAPS, - /* 0x126 */ OPT_NO_MIPMAPS, - /* 0x127 */ OPT_N_MIPMAPS, - /* 0x128 */ OPT_MAX_MIPMAPS, - /* 0x129 */ OPT_MIPMAP_SIZE, - /* 0x12a */ OPT_FAST_MIPMAPS, - /* 0x12b */ OPT_CMPR_DEFAULT, - /* 0x12c */ OPT_CUT, - /* 0x12d */ OPT_RAW, - /* 0x12e */ OPT_SECTIONS, - /* 0x12f */ 0,0,0,0, 0,0,0, + /* 0x105 */ OPT_REFERENCE, + /* 0x106 */ OPT_NUMBER, + /* 0x107 */ OPT_REMOVE_SRC, + /* 0x108 */ OPT_IGNORE_SETUP, + /* 0x109 */ OPT_PURGE, + /* 0x10a */ OPT_ALIGN_U8, + /* 0x10b */ OPT_ALIGN_PACK, + /* 0x10c */ OPT_ALIGN_BRRES, + /* 0x10d */ OPT_ALIGN_BREFF, + /* 0x10e */ OPT_ALIGN_BREFT, + /* 0x10f */ OPT_ALIGN, + /* 0x110 */ OPT_ENCODE_ALL, + /* 0x111 */ OPT_ENCODE_IMG, + /* 0x112 */ OPT_NO_ENCODE, + /* 0x113 */ OPT_NO_RECURSE, + /* 0x114 */ OPT_AUTO_ADD, + /* 0x115 */ OPT_NO_ECHO, + /* 0x116 */ OPT_PT_DIR, + /* 0x117 */ OPT_RM_AIPARAM, + /* 0x118 */ OPT_U8, + /* 0x119 */ OPT_SZS, + /* 0x11a */ OPT_WU8, + /* 0x11b */ OPT_XWU8, + /* 0x11c */ OPT_WBZ, + /* 0x11d */ OPT_PACK, + /* 0x11e */ OPT_BRRES, + /* 0x11f */ OPT_BREFF, + /* 0x120 */ OPT_BREFT, + /* 0x121 */ OPT_NO_COMPRESS, + /* 0x122 */ OPT_FAST, + /* 0x123 */ OPT_LINKS, + /* 0x124 */ OPT_BASEDIR, + /* 0x125 */ OPT_DECODE, + /* 0x126 */ OPT_MIPMAPS, + /* 0x127 */ OPT_NO_MIPMAPS, + /* 0x128 */ OPT_N_MIPMAPS, + /* 0x129 */ OPT_MAX_MIPMAPS, + /* 0x12a */ OPT_MIPMAP_SIZE, + /* 0x12b */ OPT_FAST_MIPMAPS, + /* 0x12c */ OPT_CMPR_DEFAULT, + /* 0x12d */ OPT_CUT, + /* 0x12e */ OPT_RAW, + /* 0x12f */ OPT_SECTIONS, + /* 0x130 */ 0,0,0,0, 0,0, }; // @@ -2930,688 +2969,706 @@ static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] = /////////////// opt_allowed_cmd_* /////////////// /////////////////////////////////////////////////////////////////////////////// -static u8 option_allowed_cmd_VERSION[134] = // cmd #1 +static u8 option_allowed_cmd_VERSION[135] = // cmd #1 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1 }; -static u8 option_allowed_cmd_HELP[134] = // cmd #2 +static u8 option_allowed_cmd_HELP[135] = // cmd #2 { 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1 + 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }; -static u8 option_allowed_cmd_CONFIG[134] = // cmd #3 +static u8 option_allowed_cmd_CONFIG[135] = // cmd #3 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1 }; -static u8 option_allowed_cmd_INSTALL[134] = // cmd #4 +static u8 option_allowed_cmd_INSTALL[135] = // cmd #4 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_ARGTEST[134] = // cmd #5 +static u8 option_allowed_cmd_ARGTEST[135] = // cmd #5 { 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1 + 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }; -static u8 option_allowed_cmd_TEST[134] = // cmd #6 +static u8 option_allowed_cmd_TEST[135] = // cmd #6 { 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1 + 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }; -static u8 option_allowed_cmd_COLORS[134] = // cmd #7 +static u8 option_allowed_cmd_COLORS[135] = // cmd #7 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_ERROR[134] = // cmd #8 +static u8 option_allowed_cmd_ERROR[135] = // cmd #8 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1 }; -static u8 option_allowed_cmd_FILETYPE[134] = // cmd #9 +static u8 option_allowed_cmd_FILETYPE[135] = // cmd #9 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_FILEATTRIB[134] = // cmd #10 +static u8 option_allowed_cmd_FILEATTRIB[135] = // cmd #10 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_BRSUB[134] = // cmd #11 +static u8 option_allowed_cmd_BRSUB[135] = // cmd #11 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_SYMBOLS[134] = // cmd #12 +static u8 option_allowed_cmd_SYMBOLS[135] = // cmd #12 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_FUNCTIONS[134] = // cmd #13 +static u8 option_allowed_cmd_FUNCTIONS[135] = // cmd #13 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_CALCULATE[134] = // cmd #14 +static u8 option_allowed_cmd_CALCULATE[135] = // cmd #14 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_MATRIX[134] = // cmd #15 +static u8 option_allowed_cmd_MATRIX[135] = // cmd #15 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_FLOAT[134] = // cmd #16 +static u8 option_allowed_cmd_FLOAT[135] = // cmd #16 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_VR_CALC[134] = // cmd #17 +static u8 option_allowed_cmd_VR_CALC[135] = // cmd #17 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_VR_RACE[134] = // cmd #18 +static u8 option_allowed_cmd_VR_RACE[135] = // cmd #18 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_AUTOADD[134] = // cmd #19 +static u8 option_allowed_cmd_AUTOADD[135] = // cmd #19 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 0,1,0,0,1, 0,1,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,0,1,0,0, 1,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_TRACKS[134] = // cmd #20 +static u8 option_allowed_cmd_TRACKS[135] = // cmd #20 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,1,0,0, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0 }; -static u8 option_allowed_cmd_SCANCACHE[134] = // cmd #21 +static u8 option_allowed_cmd_SCANCACHE[135] = // cmd #21 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_EXPORT[134] = // cmd #22 +static u8 option_allowed_cmd_EXPORT[135] = // cmd #22 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_CODE[134] = // cmd #23 +static u8 option_allowed_cmd_SIZEOF[135] = // cmd #23 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 +}; + +static u8 option_allowed_cmd_CODE[135] = // cmd #24 +{ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_RECODE[134] = // cmd #24 +static u8 option_allowed_cmd_RECODE[135] = // cmd #25 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_SUBFILE[134] = // cmd #25 +static u8 option_allowed_cmd_SUBFILE[135] = // cmd #26 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,0,1, 1,1,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,1,1,1,0, 1,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_TESTNORM[134] = // cmd #26 +static u8 option_allowed_cmd_TESTNORM[135] = // cmd #27 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_LIST[134] = // cmd #27 +static u8 option_allowed_cmd_LIST[135] = // cmd #28 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,1,0,1,1, 1,1,1,1,1, 1,1,0,0 + 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,1,0,1, 1,1,1,1,1, 1,1,1,0,0 }; -static u8 option_allowed_cmd_LIST_L[134] = // cmd #28 +static u8 option_allowed_cmd_LIST_L[135] = // cmd #29 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,1,0,1,1, 1,1,1,1,1, 1,1,0,0 + 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,1,0,1, 1,1,1,1,1, 1,1,1,0,0 }; -static u8 option_allowed_cmd_LIST_LL[134] = // cmd #29 +static u8 option_allowed_cmd_LIST_LL[135] = // cmd #30 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,1,0,1,1, 1,1,1,1,1, 1,1,0,0 + 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,1,0,1, 1,1,1,1,1, 1,1,1,0,0 }; -static u8 option_allowed_cmd_LIST_LLL[134] = // cmd #30 +static u8 option_allowed_cmd_LIST_LLL[135] = // cmd #31 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,1,0,1,1, 1,1,1,1,1, 1,1,0,0 + 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,1,0,1, 1,1,1,1,1, 1,1,1,0,0 }; -static u8 option_allowed_cmd_LIST_A[134] = // cmd #31 +static u8 option_allowed_cmd_LIST_A[135] = // cmd #32 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,1,0,1,1, 1,1,1,1,1, 1,1,0,0 + 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,1,0,1, 1,1,1,1,1, 1,1,1,0,0 }; -static u8 option_allowed_cmd_LIST_LA[134] = // cmd #32 +static u8 option_allowed_cmd_LIST_LA[135] = // cmd #33 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,1,0,1,1, 1,1,1,1,1, 1,1,0,0 + 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,1,0,1, 1,1,1,1,1, 1,1,1,0,0 }; -static u8 option_allowed_cmd_NAME_REF[134] = // cmd #33 +static u8 option_allowed_cmd_NAME_REF[135] = // cmd #34 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_ILIST[134] = // cmd #34 +static u8 option_allowed_cmd_ILIST[135] = // cmd #35 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,0,0,1,1, 1,1,1,1,1, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,0,0,1, 1,1,1,1,1, 1,0,1,0,0 }; -static u8 option_allowed_cmd_ILIST_L[134] = // cmd #35 +static u8 option_allowed_cmd_ILIST_L[135] = // cmd #36 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,0,0,1,1, 1,1,1,1,1, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,0,0,1, 1,1,1,1,1, 1,0,1,0,0 }; -static u8 option_allowed_cmd_ILIST_LL[134] = // cmd #36 +static u8 option_allowed_cmd_ILIST_LL[135] = // cmd #37 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,0,0,1,1, 1,1,1,1,1, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,0,0,1, 1,1,1,1,1, 1,0,1,0,0 }; -static u8 option_allowed_cmd_ILIST_A[134] = // cmd #37 +static u8 option_allowed_cmd_ILIST_A[135] = // cmd #38 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,0,0,1,1, 1,1,1,1,1, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,0,0,1, 1,1,1,1,1, 1,0,1,0,0 }; -static u8 option_allowed_cmd_ILIST_LA[134] = // cmd #38 +static u8 option_allowed_cmd_ILIST_LA[135] = // cmd #39 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,0,0,1,1, 1,1,1,1,1, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,0,0,1, 1,1,1,1,1, 1,0,1,0,0 }; -static u8 option_allowed_cmd_MEMORY[134] = // cmd #39 +static u8 option_allowed_cmd_MEMORY[135] = // cmd #40 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,0,0 + 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0 }; -static u8 option_allowed_cmd_MEMORY_A[134] = // cmd #40 +static u8 option_allowed_cmd_MEMORY_A[135] = // cmd #41 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,0,0 + 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,0,0 }; -static u8 option_allowed_cmd_DUMP[134] = // cmd #41 +static u8 option_allowed_cmd_DUMP[135] = // cmd #42 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 0,0,0,1,1, 1,1,1,1,1, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,0,0,0,1, 1,1,1,1,1, 1,0,1,0,0 }; -static u8 option_allowed_cmd_SHA1[134] = // cmd #42 +static u8 option_allowed_cmd_SHA1[135] = // cmd #43 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,1,1,1, 1,0,1,0,1, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 0,0,0,1,1, 1,1,1,1,1, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,0,0,0,1, 1,1,1,1,1, 1,0,1,0,0 +}; + +static u8 option_allowed_cmd_ANALYZE[135] = // cmd #44 +{ + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,0,0,0,0, 0,0,0,1,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1 }; -static u8 option_allowed_cmd_ANALYZE[134] = // cmd #43 +static u8 option_allowed_cmd_IS_TEXTURE[135] = // cmd #45 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_FEATURES[134] = // cmd #44 +static u8 option_allowed_cmd_FEATURES[135] = // cmd #46 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,1, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,1, 1,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1 }; -static u8 option_allowed_cmd_DISTRIBUTION[134] = // cmd #45 +static u8 option_allowed_cmd_DISTRIBUTION[135] = // cmd #47 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,1,1,0, - 0,0,0,1,1, 1,1,1,1,1, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,1,1, + 0,0,0,0,1, 1,1,1,1,1, 1,0,1,0,0 }; -static u8 option_allowed_cmd_DIFF[134] = // cmd #46 +static u8 option_allowed_cmd_DIFF[135] = // cmd #48 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 1,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 1,0,0,0,0, 0,0,0,0,0, 1,1,0,0 + 0,1,0,0,0, 0,0,0,0,0, 0,1,1,0,0 }; -static u8 option_allowed_cmd_CHECK[134] = // cmd #47 +static u8 option_allowed_cmd_CHECK[135] = // cmd #49 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,1,0,1, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,0,1,0, - 0,0,0,1,1, 1,1,1,1,1, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,1, + 0,0,0,0,1, 1,1,1,1,1, 1,0,1,0,0 }; -static u8 option_allowed_cmd_SLOTS[134] = // cmd #48 +static u8 option_allowed_cmd_SLOTS[135] = // cmd #50 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,0,1, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,0,1,0, - 0,0,0,1,1, 1,1,1,1,1, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,1, + 0,0,0,0,1, 1,1,1,1,1, 1,0,1,0,0 }; -static u8 option_allowed_cmd_STGI[134] = // cmd #49 +static u8 option_allowed_cmd_STGI[135] = // cmd #51 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_ISARENA[134] = // cmd #50 +static u8 option_allowed_cmd_ISARENA[135] = // cmd #52 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_NORMALIZE[134] = // cmd #51 +static u8 option_allowed_cmd_NORMALIZE[135] = // cmd #53 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,0,0, - 1,1,1,1,1, 1,0,0,0,0, 1,0,0,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,1,1,1,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,1,1,1,1, 1,1,1,1,0, + 0,1,1,1,1, 1,1,0,0,0, 0,1,0,0,1, 1,1,1,1,1, 1,0,0,0,0, 0,0,1,1,1, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_PATCH[134] = // cmd #52 +static u8 option_allowed_cmd_PATCH[135] = // cmd #54 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,0,0, - 1,1,1,1,1, 1,0,0,0,0, 1,0,0,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,1,1,1,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,1,1,1,1, 1,1,1,1,0, + 0,1,1,1,1, 1,1,0,0,0, 0,1,0,0,1, 1,1,1,1,1, 1,0,0,0,0, 0,1,1,1,1, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_COPY[134] = // cmd #53 +static u8 option_allowed_cmd_COPY[135] = // cmd #55 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,0,0, - 1,1,1,1,1, 1,0,0,0,0, 1,0,0,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,1,1,1,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,1,1,1,1, 1,1,1,1,0, + 0,1,1,1,1, 1,1,0,0,0, 0,1,0,0,1, 1,1,1,1,1, 1,0,0,0,0, 0,1,1,1,1, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_DUPLICATE[134] = // cmd #54 +static u8 option_allowed_cmd_DUPLICATE[135] = // cmd #56 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,1,0,1,1, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,0,0, - 1,1,1,1,1, 1,0,0,0,0, 1,0,0,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,1,1,1,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,1,1,1,1, 1,1,1,1,0, + 0,1,1,1,1, 1,1,0,0,0, 0,1,0,0,1, 1,1,1,1,1, 1,0,0,0,0, 0,1,1,1,1, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_MINIMAP[134] = // cmd #55 +static u8 option_allowed_cmd_MINIMAP[135] = // cmd #57 { 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 0,1,1,0,0, - 1,1,1,1,1, 1,0,0,0,0, 1,0,0,1,1, 0,0,0,0,0, 0,0,0,0,0, 1,1,1,1,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,0,1,1,0, + 0,1,1,1,1, 1,1,0,0,0, 0,1,0,0,1, 1,0,0,0,0, 0,0,0,0,0, 0,1,1,1,1, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_COMPRESS[134] = // cmd #56 +static u8 option_allowed_cmd_COMPRESS[135] = // cmd #58 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,0,0, - 1,1,1,1,1, 1,0,0,0,0, 1,0,0,1,1, 1,1,1,1,1, 0,0,0,0,0, 1,1,1,1,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,1,1,1,1, 1,1,1,1,0, + 0,1,1,1,1, 1,1,0,0,0, 0,1,0,0,1, 1,1,1,1,1, 1,0,0,0,0, 0,1,1,1,1, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_DECOMPRESS[134] = // cmd #57 +static u8 option_allowed_cmd_DECOMPRESS[135] = // cmd #59 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,0,0, - 1,1,1,1,1, 1,0,0,0,0, 1,0,0,1,1, 1,0,1,0,0, 0,0,0,0,0, 0,0,1,1,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,1,1,1,1, 1,1,1,1,0, + 0,1,1,1,1, 1,1,0,0,0, 0,1,0,0,1, 1,1,0,1,0, 0,0,0,0,0, 0,0,0,1,1, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_ENCODE[134] = // cmd #58 +static u8 option_allowed_cmd_ENCODE[135] = // cmd #60 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, - 1,1,1,1,1, 1,1,1,1,1, 0,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,1,1, 1,1,1,1,1, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, + 0,1,1,1,1, 1,1,1,1,1, 1,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,1, 1,1,1,1,1, 1,0,1,0,0 }; -static u8 option_allowed_cmd_CREATE[134] = // cmd #59 +static u8 option_allowed_cmd_CREATE[135] = // cmd #61 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,1,1, 1,1,1,0,1, 1,1,0,1,0, - 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,0,1,0, - 0,0,0,1,1, 1,1,1,1,1, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,1, 1,1,1,1,0, 1,1,1,0,1, + 0,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,0,1, + 0,0,0,0,1, 1,1,1,1,1, 1,0,1,0,0 }; -static u8 option_allowed_cmd_UPDATE[134] = // cmd #60 +static u8 option_allowed_cmd_UPDATE[135] = // cmd #62 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,1,1,1, 1,1,1,0,1, 1,1,1,0,0, - 0,0,0,0,0, 0,1,1,1,1, 0,1,1,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, - 1,0,0,0,0, 0,0,0,0,0, 0,1,0,0 + 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,1,0,1, 1,1,1,1,0, 1,1,1,1,0, + 0,0,0,0,0, 0,0,1,1,1, 1,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 1,1,1,0,0, + 0,1,0,0,0, 0,0,0,0,0, 0,0,1,0,0 }; -static u8 option_allowed_cmd_EXTRACT[134] = // cmd #61 +static u8 option_allowed_cmd_EXTRACT[135] = // cmd #63 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,1,1, 0,1,1,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 1,1,0,1,1, 1,1,1,0,1, 1,1,1,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, - 1,1,1,1,1, 0,0,0,1,1, 1,1,1,0 + 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 1,1,0,0,1, 1,1,1,1,0, 1,1,1,1,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, + 1,1,1,1,1, 1,0,0,0,1, 1,1,1,1,0 }; -static u8 option_allowed_cmd_XDECODE[134] = // cmd #62 +static u8 option_allowed_cmd_XDECODE[135] = // cmd #64 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,1,1, 0,1,1,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 1,1,0,1,1, 1,1,1,0,1, 1,1,1,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, - 1,1,1,1,1, 0,0,0,1,1, 1,1,1,0 + 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 1,1,0,0,1, 1,1,1,1,0, 1,1,1,1,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, + 1,1,1,1,1, 1,0,0,0,1, 1,1,1,1,0 }; -static u8 option_allowed_cmd_XEXPORT[134] = // cmd #63 +static u8 option_allowed_cmd_XEXPORT[135] = // cmd #65 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,1,1, 0,1,1,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 1,1,0,1,1, 1,1,1,0,1, 1,1,1,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, - 1,1,1,1,1, 0,0,0,1,1, 1,1,1,0 + 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 1,1,0,0,1, 1,1,1,1,0, 1,1,1,1,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, + 1,1,1,1,1, 1,0,0,0,1, 1,1,1,1,0 }; -static u8 option_allowed_cmd_XALL[134] = // cmd #64 +static u8 option_allowed_cmd_XALL[135] = // cmd #66 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,1,1, 0,1,1,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 1,1,0,1,1, 1,1,1,0,1, 1,1,1,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, - 1,1,1,1,1, 0,0,0,1,1, 1,1,1,0 + 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 1,1,0,0,1, 1,1,1,1,0, 1,1,1,1,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, + 1,1,1,1,1, 1,0,0,0,1, 1,1,1,1,0 }; -static u8 option_allowed_cmd_XCOMMON[134] = // cmd #65 +static u8 option_allowed_cmd_XCOMMON[135] = // cmd #67 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,0,1, 1,1,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,1,1,1,0, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_BINARY[134] = // cmd #66 +static u8 option_allowed_cmd_BINARY[135] = // cmd #68 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,0,1, 1,1,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,1,1,1,0, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_TEXT[134] = // cmd #67 +static u8 option_allowed_cmd_TEXT[135] = // cmd #69 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,1, 0,1,1,0,1, 1,1,1,1,1, - 1,1,1,1,1, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,0,1, 1,1,1,0,0, + 1,1,1,1,1, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,0,1, 1,1,1,1,0, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_CAT[134] = // cmd #68 +static u8 option_allowed_cmd_CAT[135] = // cmd #70 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,1, 0,1,1,0,1, 1,1,1,1,1, - 1,1,1,1,1, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, + 1,1,1,1,1, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_BMG[134] = // cmd #69 +static u8 option_allowed_cmd_BMG[135] = // cmd #71 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,1, 0,0,0,0,1, 1,1,1,1,1, - 1,1,1,1,1, 1,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, + 1,1,1,1,1, 1,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_KCL[134] = // cmd #70 +static u8 option_allowed_cmd_KCL[135] = // cmd #72 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_KMP[134] = // cmd #71 +static u8 option_allowed_cmd_KMP[135] = // cmd #73 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,0, 1,0,0,1,1, 1,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_LEX[134] = // cmd #72 +static u8 option_allowed_cmd_LEX[135] = // cmd #74 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, + 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_INFO[134] = // cmd #73 +static u8 option_allowed_cmd_INFO[135] = // cmd #75 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_GHOST[134] = // cmd #74 +static u8 option_allowed_cmd_GHOST[135] = // cmd #76 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,1,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1 }; -static u8 option_allowed_cmd_YAZDUMP[134] = // cmd #75 +static u8 option_allowed_cmd_YAZDUMP[135] = // cmd #77 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,1,1,0,1, 1,1,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 1,1,1,1,0, 1,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; -static u8 option_allowed_cmd_VEHICLE[134] = // cmd #76 +static u8 option_allowed_cmd_VEHICLE[135] = // cmd #78 { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,1, 0,1,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,1, 1,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; @@ -3633,6 +3690,7 @@ static const InfoOption_t * option_tab_tool[] = OptionInfo + OPT_QUIET, OptionInfo + OPT_VERBOSE, OptionInfo + OPT_LOGGING, + OptionInfo + OPT_WARN, OptionInfo + OPT_DE, OptionInfo + OPT_COLORS, OptionInfo + OPT_NO_COLORS, @@ -3916,6 +3974,15 @@ static const InfoOption_t * option_tab_cmd_EXPORT[] = 0 }; +static const InfoOption_t * option_tab_cmd_SIZEOF[] = +{ + &option_cmd_SIZEOF_SORT, + &option_cmd_SIZEOF_BRIEF, + OptionInfo + OPT_LOGGING, + + 0 +}; + static const InfoOption_t * option_tab_cmd_CODE[] = { @@ -4908,12 +4975,23 @@ static const InfoOption_t * option_tab_cmd_ANALYZE[] = OptionInfo + OPT_NONE, // separator + OptionInfo + OPT_REFERENCE, OptionInfo + OPT_DEST, OptionInfo + OPT_DEST2, 0 }; +static const InfoOption_t * option_tab_cmd_IS_TEXTURE[] = +{ + OptionInfo + OPT_IGNORE, + OptionInfo + OPT_REFERENCE, + OptionInfo + OPT_BATTLE, + &option_cmd_IS_TEXTURE_LONG, + + 0 +}; + static const InfoOption_t * option_tab_cmd_FEATURES[] = { &option_cmd_FEATURES_BRIEF, @@ -6825,7 +6903,7 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = " SZS, U8, PACK, BRRES, BREFF and BREFT archives. Additonally, RARC" " archive can be extracted. It is also a wrapper to all other tools.", 0, - 66, + 67, option_tab_tool, 0 }, @@ -7204,6 +7282,21 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = option_allowed_cmd_EXPORT }, + { CMD_SIZEOF, + true, + false, + false, + "SIZEOF", + 0, + "wszst SIZEOF key...", + "This hidden command prints a list with the size of data structures" + " and variables.", + 0, + 3, + option_tab_cmd_SIZEOF, + option_allowed_cmd_SIZEOF + }, + { CMD_CODE, true, false, @@ -7503,7 +7596,7 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = 0, "wszst SHA1 [source]...", "Print a SHA1 checksum for each source. The checksum is calculated by" - " using the uncompressed data.", + " using the uncompressed data and after patching.", 0, 48, option_tab_cmd_SHA1, @@ -7519,11 +7612,31 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = "wszst ANALYZE [source]...", "Analyse track files and print results in machine readable format.", 0, - 15, + 16, option_tab_cmd_ANALYZE, option_allowed_cmd_ANALYZE }, + { CMD_IS_TEXTURE, + false, + false, + false, + "IS-TEXTURE", + "ISTEXTURE", + "wszst IS-TEXTURE --reference reference [source]...", + "Test each source to see if it's a texture hack versus a reference" + " file. For each source, one human and machine readable status line is" + " printed. It is either »-1=err« on error, »1=yes« for a texture" + " hack, or »0=no LIST« with a comma separated list of reasons.\n" + " At the moment KCL, KMP (see notes) and LEX are checked. KMP section" + " CAME has been intentionally left out. Section ENPT is only checked" + " if KCL contains a least one face of type force-recalculation.", + 0, + 4, + option_tab_cmd_IS_TEXTURE, + option_allowed_cmd_IS_TEXTURE + }, + { CMD_FEATURES, true, false, @@ -7531,7 +7644,8 @@ static const InfoCommand_t CommandInfo[CMD__N+1] = "FEATURES", 0, "wszst FEATURES [source]...", - "Analyse track files and a feature list in machine readable format.", + "Analyse track files and create a feature list in machine readable" + " format.", 0, 18, option_tab_cmd_FEATURES, diff --git a/project/src/ui/ui-wszst.h b/project/src/ui/ui-wszst.h index 997abfe..161aa7e 100644 --- a/project/src/ui/ui-wszst.h +++ b/project/src/ui/ui-wszst.h @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -133,6 +133,7 @@ typedef enum enumOptions OPT_ANALYZE, OPT_ANALYZE_MODE, OPT_SOURCE, + OPT_REFERENCE, OPT_DEST, OPT_DEST2, OPT_ESC, @@ -190,7 +191,7 @@ typedef enum enumOptions OPT_RAW, OPT_SECTIONS, - OPT__N_SPECIFIC, // == 134 + OPT__N_SPECIFIC, // == 135 //----- global options ----- @@ -205,6 +206,7 @@ typedef enum enumOptions OPT_QUIET, OPT_VERBOSE, OPT_LOGGING, + OPT_WARN, OPT_DE, OPT_COLORS, OPT_NO_COLORS, @@ -270,7 +272,7 @@ typedef enum enumOptions OPT_NEW, OPT_EXTRACT, - OPT__N_TOTAL // == 209 + OPT__N_TOTAL // == 211 } enumOptions; @@ -362,6 +364,7 @@ typedef enum enumOptions // OB_ANALYZE = 1llu << OPT_ANALYZE, // OB_ANALYZE_MODE = 1llu << OPT_ANALYZE_MODE, // OB_SOURCE = 1llu << OPT_SOURCE, +// OB_REFERENCE = 1llu << OPT_REFERENCE, // OB_DEST = 1llu << OPT_DEST, // OB_DEST2 = 1llu << OPT_DEST2, // OB_ESC = 1llu << OPT_ESC, @@ -625,6 +628,9 @@ typedef enum enumOptions // // OB_CMD_EXPORT = 0, // +// OB_CMD_SIZEOF = OB_SORT +// | OB_BRIEF, +// // OB_CMD_CODE = 0, // // OB_CMD_RECODE = 0, @@ -713,9 +719,14 @@ typedef enum enumOptions // OB_CMD_ANALYZE = OB_LONG // | OB_IGNORE // | OB_GRP_SCRIPT +// | OB_REFERENCE // | OB_DEST // | OB_DEST2, // +// OB_CMD_IS_TEXTURE = OB_IGNORE +// | OB_REFERENCE +// | OB_LONG, +// // OB_CMD_FEATURES = OB_BRIEF // | OB_LONG // | OB_IGNORE @@ -955,6 +966,7 @@ typedef enum enumCommands CMD_TRACKS, CMD_SCANCACHE, CMD_EXPORT, + CMD_SIZEOF, CMD_CODE, CMD_RECODE, CMD_SUBFILE, @@ -980,6 +992,7 @@ typedef enum enumCommands CMD_SHA1, CMD_ANALYZE, + CMD_IS_TEXTURE, CMD_FEATURES, CMD_DISTRIBUTION, @@ -1018,7 +1031,7 @@ typedef enum enumCommands CMD_VEHICLE, - CMD__N // == 77 + CMD__N // == 79 } enumCommands; @@ -1047,6 +1060,7 @@ typedef enum enumGetOpt GO_SORT = 'S', GO_TRACKS = 'T', GO_VERSION = 'V', + GO_WARN = 'W', GO_EXPORT = 'X', GO_ALL = 'a', @@ -1200,6 +1214,7 @@ typedef enum enumGetOpt GO_STD, GO_NEW, GO_EXTRACT, + GO_REFERENCE, GO_NUMBER, GO_REMOVE_SRC, GO_IGNORE_SETUP, diff --git a/project/src/ui/ui.def b/project/src/ui/ui.def index 4631580..8e47764 100644 --- a/project/src/ui/ui.def +++ b/project/src/ui/ui.def @@ -246,12 +246,22 @@ #:def_cmd( "SHA1", "SHA1", \ "wszst SHA1 [source]...", \ "Print a SHA1 checksum for each source. The checksum is calculated by" \ - " using the uncompressed data." ) + " using the uncompressed data and after patching." ) #:def_cmd( "ANALYZE", "ANALYZE|ANA|ANALYSE", \ "wszst ANALYZE [source]...", \ "Analyse track files and print results in machine readable format." ) +#:def_cmd( "IS_TEXTURE", "IS-TEXTURE|ISTEXTURE", \ + "wszst IS-TEXTURE --reference reference [source]...", \ + "Test each source to see if it's a texture hack versus a reference" \ + " file. For each source, one human and machine readable status line is" \ + " printed. It is either »-1=err« on error, »1=yes« for a texture" \ + " hack, or »0=no LIST« with a comma separated list of reasons.\n" \ + " At the moment KCL, KMP (see notes) and LEX are checked. KMP section" \ + " CAME has been intentionally left out. Section ENPT is only checked" \ + " if KCL contains a least one face of type force-recalculation." ) + #:def_cmd( "DISTRIBUTION", "DISTRIBUTION|DIST", \ "wszst DISTRIBUTION result source...\n" \ "wszst DISTRIBUTION directory [source]...", \ @@ -524,8 +534,8 @@ #:def_opt( "MAX_WIDTH", "max-width|maxwidth", "GP", \ "maxwidth", \ "Define the maximum terminal width (number of columns) for help and" \ - " some other messages and disable the automatic detection of the" \ - " terminal width. This option is ignored if {--width} is set." ) + " some other messages. The default is 120. This option is ignored if" \ + " --width is set." ) #:def_opt( "QUIET", "q|quiet", "GM", \ "", \ @@ -542,6 +552,15 @@ "", \ "This debug option enables the logging of internal lists and maps." ) +#:def_opt( "WARN", "W|warn", "GP", \ + "list", \ + "Enable or disable warnings. Parameter @'list'@ is a comma separated" \ + " list of keywords. A minus sign before a keyword disables a warning." \ + " Each occurrence of the option will only change entered warning and" \ + " all other warnings are untouched.\n" \ + " Keyword @DEFAULT@ resets the default settings, @OFF@ disables and" \ + " @ALL@ enables all. The other allowed keywords are: @INVALID-OFFSET@." ) + #:def_opt( "DE", "de", "G", \ "", \ "Use german track and arena names." ) @@ -825,11 +844,10 @@ "[=mode]", \ "@MODE@ is either @OFF@, @AUTO@ (default) or @ON@. Without value, @ON@" \ " is used.\n" \ - " If mode is @ON@, assume a battle arena and enable a spüecial" \ - " battle support. If mode is @OFF@, disable special battle arena" \ - " support. If mode is @AUTO@, analyse the KMP and estimate, if it is a" \ - " battle areana. Modes @ON@ and @OFF@ override KMP parameter" \ - " @BATTLE-MODE@." ) + " If mode is @ON@, assume a battle arena and enable a special battle" \ + " support. If mode is @OFF@, disable special battle arena support. If" \ + " mode is @AUTO@, analyse the KMP and estimate, if it is a battle" \ + " areana. Modes @ON@ and @OFF@ override KMP parameter @BATTLE-MODE@." ) #:def_opt( "EXPORT_FLAGS", "export-flags|exportflags|exflags", "GO", \ "[=mode]", \ @@ -1224,7 +1242,7 @@ #:def_opt( "CODING", "coding", "CP", \ "mode", \ "Define the coding of the non alphanumeric characters for BASE64:" \ - " STANDART (+/=, default), URL (-_=), STAR (-_*) or XML (.-*)." ) + " STANDARD (+/=, default), URL (-_=), STAR (-_*) or XML (.-*)." ) #:def_opt( "VERIFY", "verify", "C", \ "", \ @@ -1538,6 +1556,10 @@ " A @'?'@ direct behind @'%'@ in @%E@ and @%T@ conversions avoid that" \ " the same extension is used twice in row." ) +#:def_opt( "REFERENCE", "ref|reference", "CP", \ + "path", \ + "Define a reference SZS." ) + #:def_opt( "DEST", "d|dest", "CP", \ "path", \ "Define a destination path (directory/file). The destination @-@" \ @@ -2229,6 +2251,19 @@ "", \ "" ) +#:def_cmd_opt( "SIZEOF", "SORT", \ + "", \ + "Define a sort mode. Keywords are: @NONE@ (default), @NAME@ end" \ + " @SIZE@." ) + +#:def_cmd_opt( "SIZEOF", "BRIEF", \ + "", \ + "Limit output to SZS specific data." ) + +#:def_cmd_opt( "SIZEOF", "LOGGING", \ + "", \ + "" ) + #:def_cmd_opt( "SUBFILE", "DEST", \ "", \ "" ) @@ -5138,6 +5173,10 @@ "", \ "" ) +#:def_cmd_opt( "ANALYZE", "REFERENCE", \ + "", \ + "" ) + #:def_cmd_opt( "ANALYZE", "DEST", \ "", \ "" ) @@ -5146,6 +5185,22 @@ "", \ "" ) +#:def_cmd_opt( "IS_TEXTURE", "IGNORE", \ + "", \ + "" ) + +#:def_cmd_opt( "IS_TEXTURE", "REFERENCE", \ + "", \ + "" ) + +#:def_cmd_opt( "IS_TEXTURE", "BATTLE", \ + "", \ + "" ) + +#:def_cmd_opt( "IS_TEXTURE", "LONG", \ + "", \ + "Append a colon and the filename after each status." ) + #:def_cmd_opt( "FEATURES", "BRIEF", \ "", \ "Suppres any comments at all. If set twice, suppress empty lines (for" \ @@ -5153,7 +5208,7 @@ #:def_cmd_opt( "FEATURES", "LONG", \ "", \ - "Print additnal comments." ) + "Print additional comments." ) #:def_cmd_opt( "FEATURES", "IGNORE", \ "", \ @@ -11349,8 +11404,8 @@ #:def_opt( "MAX_WIDTH", "max-width|maxwidth", "GP", \ "maxwidth", \ "Define the maximum terminal width (number of columns) for help and" \ - " some other messages and disable the automatic detection of the" \ - " terminal width. This option is ignored if {--width} is set." ) + " some other messages. The default is 120. This option is ignored if" \ + " --width is set." ) #:def_opt( "QUIET", "q|quiet", "GM", \ "", \ @@ -11367,6 +11422,15 @@ "", \ "This debug option enables the logging of internal lists and maps." ) +#:def_opt( "WARN", "W|warn", "GP", \ + "list", \ + "Enable or disable warnings. Parameter @'list'@ is a comma separated" \ + " list of keywords. A minus sign before a keyword disables a warning." \ + " Each occurrence of the option will only change entered warning and" \ + " all other warnings are untouched.\n" \ + " Keyword @DEFAULT@ resets the default settings, @OFF@ disables and" \ + " @ALL@ enables all. The other allowed keywords are: @INVALID-OFFSET@." ) + #:def_opt( "DE", "de", "G", \ "", \ "Use german track and arena names." ) @@ -12601,8 +12665,8 @@ #:def_opt( "MAX_WIDTH", "max-width|maxwidth", "GP", \ "maxwidth", \ "Define the maximum terminal width (number of columns) for help and" \ - " some other messages and disable the automatic detection of the" \ - " terminal width. This option is ignored if {--width} is set." ) + " some other messages. The default is 120. This option is ignored if" \ + " --width is set." ) #:def_opt( "QUIET", "q|quiet", "GM", \ "", \ @@ -12619,6 +12683,15 @@ "", \ "This debug option enables the logging of internal lists and maps." ) +#:def_opt( "WARN", "W|warn", "GP", \ + "list", \ + "Enable or disable warnings. Parameter @'list'@ is a comma separated" \ + " list of keywords. A minus sign before a keyword disables a warning." \ + " Each occurrence of the option will only change entered warning and" \ + " all other warnings are untouched.\n" \ + " Keyword @DEFAULT@ resets the default settings, @OFF@ disables and" \ + " @ALL@ enables all. The other allowed keywords are: @INVALID-OFFSET@." ) + #:def_opt( "DE", "de", "G", \ "", \ "Use german track and arena names." ) @@ -13954,8 +14027,8 @@ #:def_opt( "MAX_WIDTH", "max-width|maxwidth", "GP", \ "maxwidth", \ "Define the maximum terminal width (number of columns) for help and" \ - " some other messages and disable the automatic detection of the" \ - " terminal width. This option is ignored if {--width} is set." ) + " some other messages. The default is 120. This option is ignored if" \ + " --width is set." ) #:def_opt( "QUIET", "q|quiet", "GM", \ "", \ @@ -13972,6 +14045,15 @@ "", \ "This debug option enables the logging of internal lists and maps." ) +#:def_opt( "WARN", "W|warn", "GP", \ + "list", \ + "Enable or disable warnings. Parameter @'list'@ is a comma separated" \ + " list of keywords. A minus sign before a keyword disables a warning." \ + " Each occurrence of the option will only change entered warning and" \ + " all other warnings are untouched.\n" \ + " Keyword @DEFAULT@ resets the default settings, @OFF@ disables and" \ + " @ALL@ enables all. The other allowed keywords are: @INVALID-OFFSET@." ) + #:def_opt( "DE", "de", "G", \ "", \ "Use german track and arena names." ) @@ -14894,6 +14976,11 @@ " output. The exit status is @'DIFFER'@ if at least one KMP warning" \ " found." ) +#:def_cmd( "SHA1", "SHA1", \ + "wszst SHA1 [source]...", \ + "Print a SHA1 checksum of the KCL for each source. The checksum is" \ + " calculated after patching." ) + #:def_cmd( "BLOW", "BLOW", \ "wkclt BLOW source...", \ "Try to calculate the used blow size (KCL_BLOW) of a KCL. Print one" \ @@ -14945,8 +15032,8 @@ #:def_opt( "MAX_WIDTH", "max-width|maxwidth", "GP", \ "maxwidth", \ "Define the maximum terminal width (number of columns) for help and" \ - " some other messages and disable the automatic detection of the" \ - " terminal width. This option is ignored if {--width} is set." ) + " some other messages. The default is 120. This option is ignored if" \ + " --width is set." ) #:def_opt( "QUIET", "q|quiet", "GM", \ "", \ @@ -14963,6 +15050,15 @@ "", \ "This debug option enables the logging of internal lists and maps." ) +#:def_opt( "WARN", "W|warn", "GP", \ + "list", \ + "Enable or disable warnings. Parameter @'list'@ is a comma separated" \ + " list of keywords. A minus sign before a keyword disables a warning." \ + " Each occurrence of the option will only change entered warning and" \ + " all other warnings are untouched.\n" \ + " Keyword @DEFAULT@ resets the default settings, @OFF@ disables and" \ + " @ALL@ enables all. The other allowed keywords are: @INVALID-OFFSET@." ) + #:def_opt( "DE", "de", "G", \ "", \ "Use german track and arena names." ) @@ -15237,6 +15333,30 @@ " are also accepted. For some conversions, the auto-add library is" \ " needed." ) +#:def_opt( "ID", "id", "C", \ + "", \ + "Print an ID with 8 characters instead of a SHA-1 sum with 40" \ + " characters. The SHA-1 sum is used to calculate the ID. The ID" \ + " consists of '0'-'9' and 'a'-'w' (32 characters)." ) + +#:def_opt( "BASE64", "base64", "CO", \ + "[=mode]", \ + "Encode the the checksum string as BASE64 with 27 characters instead" \ + " of hex. If a parameter is set, it acts like {--coding=mode}." ) + +#:def_opt( "DB64", "db64", "CO", \ + "[=mode]", \ + "Encode the the checksum string and some length as BASE64 with 32" \ + " characters instead of hex for database searches. This options" \ + " implies {--coding=URL} if no other coding is defined. If a parameter" \ + " is set, it acts like {--coding=mode}. Option {--db64} has priority" \ + " over {--base64}." ) + +#:def_opt( "CODING", "coding", "CP", \ + "mode", \ + "Define the coding of the non alphanumeric characters for BASE64:" \ + " STANDARD (+/=, default), URL (-_=), STAR (-_*) or XML (.-*)." ) + #:def_opt( "ROUND", "round", "C", \ "", \ "Print additional lines with rounded values (to 3 and 2 bytes for" \ @@ -16152,6 +16272,14 @@ "", \ "" ) +#:def_cmd_opt( "TYPES", "NO_HEADER", \ + "", \ + "" ) + +#:def_cmd_opt( "TYPES", "BRIEF", \ + "", \ + "Print only the resulting flag." ) + #:def_cmd_opt( "FLAGS", "NO_HEADER", \ "", \ "" ) @@ -16940,6 +17068,122 @@ "", \ "" ) +#:def_cmd_opt( "SHA1", "IGNORE", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "ID", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "BASE64", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "DB64", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "CODING", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "BRIEF", \ + "", \ + "Suppress output of the filename." ) + +#:def_cmd_opt( "SHA1", "CONST", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "SCALE", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "SHIFT", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "XSS", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "YSS", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "ZSS", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "ROT", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "XROT", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "YROT", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "ZROT", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "TRANSLATE", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "NULL", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "NEXT", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "ASCALE", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "AROT", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "TFORM_SCRIPT", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "KCL", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "KCL_FLAG", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "KCL_SCRIPT", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "TRI_AREA", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "TRI_HEIGHT", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "FLAG_FILE", \ + "", \ + "" ) + +#:def_cmd_opt( "SHA1", "SLOT", \ + "", \ + "" ) + #:def_cmd_opt( "ANALYZE", "IGNORE", \ "", \ "" ) @@ -17295,8 +17539,8 @@ #:def_opt( "MAX_WIDTH", "max-width|maxwidth", "GP", \ "maxwidth", \ "Define the maximum terminal width (number of columns) for help and" \ - " some other messages and disable the automatic detection of the" \ - " terminal width. This option is ignored if {--width} is set." ) + " some other messages. The default is 120. This option is ignored if" \ + " --width is set." ) #:def_opt( "QUIET", "q|quiet", "GM", \ "", \ @@ -17313,6 +17557,15 @@ "", \ "This debug option enables the logging of internal lists and maps." ) +#:def_opt( "WARN", "W|warn", "GP", \ + "list", \ + "Enable or disable warnings. Parameter @'list'@ is a comma separated" \ + " list of keywords. A minus sign before a keyword disables a warning." \ + " Each occurrence of the option will only change entered warning and" \ + " all other warnings are untouched.\n" \ + " Keyword @DEFAULT@ resets the default settings, @OFF@ disables and" \ + " @ALL@ enables all. The other allowed keywords are: @INVALID-OFFSET@." ) + #:def_opt( "DE", "de", "G", \ "", \ "Use german track and arena names." ) @@ -17524,11 +17777,10 @@ "[=mode]", \ "@MODE@ is either @OFF@, @AUTO@ (default) or @ON@. Without value, @ON@" \ " is used.\n" \ - " If mode is @ON@, assume a battle arena and enable a spüecial" \ - " battle support. If mode is @OFF@, disable special battle arena" \ - " support. If mode is @AUTO@, analyse the KMP and estimate, if it is a" \ - " battle areana. Modes @ON@ and @OFF@ override KMP parameter" \ - " @BATTLE-MODE@." ) + " If mode is @ON@, assume a battle arena and enable a special battle" \ + " support. If mode is @OFF@, disable special battle arena support. If" \ + " mode is @AUTO@, analyse the KMP and estimate, if it is a battle" \ + " areana. Modes @ON@ and @OFF@ override KMP parameter @BATTLE-MODE@." ) #:def_opt( "EXPORT_FLAGS", "export-flags|exportflags|exflags", "GO", \ "[=mode]", \ @@ -19356,8 +19608,8 @@ #:def_opt( "MAX_WIDTH", "max-width|maxwidth", "GP", \ "maxwidth", \ "Define the maximum terminal width (number of columns) for help and" \ - " some other messages and disable the automatic detection of the" \ - " terminal width. This option is ignored if {--width} is set." ) + " some other messages. The default is 120. This option is ignored if" \ + " --width is set." ) #:def_opt( "QUIET", "q|quiet", "GM", \ "", \ @@ -19374,6 +19626,15 @@ "", \ "This debug option enables the logging of internal lists and maps." ) +#:def_opt( "WARN", "W|warn", "GP", \ + "list", \ + "Enable or disable warnings. Parameter @'list'@ is a comma separated" \ + " list of keywords. A minus sign before a keyword disables a warning." \ + " Each occurrence of the option will only change entered warning and" \ + " all other warnings are untouched.\n" \ + " Keyword @DEFAULT@ resets the default settings, @OFF@ disables and" \ + " @ALL@ enables all. The other allowed keywords are: @INVALID-OFFSET@." ) + #:def_opt( "DE", "de", "G", \ "", \ "Use german track and arena names." ) @@ -20618,8 +20879,8 @@ #:def_opt( "MAX_WIDTH", "max-width|maxwidth", "GP", \ "maxwidth", \ "Define the maximum terminal width (number of columns) for help and" \ - " some other messages and disable the automatic detection of the" \ - " terminal width. This option is ignored if {--width} is set." ) + " some other messages. The default is 120. This option is ignored if" \ + " --width is set." ) #:def_opt( "QUIET", "q|quiet", "GM", \ "", \ @@ -20636,6 +20897,15 @@ "", \ "This debug option enables the logging of internal lists and maps." ) +#:def_opt( "WARN", "W|warn", "GP", \ + "list", \ + "Enable or disable warnings. Parameter @'list'@ is a comma separated" \ + " list of keywords. A minus sign before a keyword disables a warning." \ + " Each occurrence of the option will only change entered warning and" \ + " all other warnings are untouched.\n" \ + " Keyword @DEFAULT@ resets the default settings, @OFF@ disables and" \ + " @ALL@ enables all. The other allowed keywords are: @INVALID-OFFSET@." ) + #:def_opt( "DE", "de", "G", \ "", \ "Use german track and arena names." ) @@ -21874,8 +22144,8 @@ #:def_opt( "MAX_WIDTH", "max-width|maxwidth", "GP", \ "maxwidth", \ "Define the maximum terminal width (number of columns) for help and" \ - " some other messages and disable the automatic detection of the" \ - " terminal width. This option is ignored if {--width} is set." ) + " some other messages. The default is 120. This option is ignored if" \ + " --width is set." ) #:def_opt( "QUIET", "q|quiet", "GM", \ "", \ @@ -21892,6 +22162,15 @@ "", \ "This debug option enables the logging of internal lists and maps." ) +#:def_opt( "WARN", "W|warn", "GP", \ + "list", \ + "Enable or disable warnings. Parameter @'list'@ is a comma separated" \ + " list of keywords. A minus sign before a keyword disables a warning." \ + " Each occurrence of the option will only change entered warning and" \ + " all other warnings are untouched.\n" \ + " Keyword @DEFAULT@ resets the default settings, @OFF@ disables and" \ + " @ALL@ enables all. The other allowed keywords are: @INVALID-OFFSET@." ) + #:def_opt( "DE", "de", "G", \ "", \ "Use german track and arena names." ) @@ -22384,9 +22663,10 @@ " @PAL@ (default), @USA@, @JAPAN@, @KOREA@, or any abbreviation of" \ " them. They select the region for the following addresses. The hex" \ " numbers (with or without @0x@ prefix) are interpreted as addresses." \ - " If possible, they are ported to all other regions. The result is" \ - " printed as colorized table.\n" \ - " This address porting is EXPERIMENTAL!" ) + " If an address begins with @m@ or @s@, then it is interpreted as a" \ + " file offset for @main.dol@ or @staticr.rel@. All addresses are" \ + " ported to all other regions. The result is printed as colorized" \ + " table." ) #:def_cmd( "WHERE", "WHERE", \ "wstrt WHERE address...", \ @@ -22489,8 +22769,8 @@ #:def_opt( "MAX_WIDTH", "max-width|maxwidth", "GP", \ "maxwidth", \ "Define the maximum terminal width (number of columns) for help and" \ - " some other messages and disable the automatic detection of the" \ - " terminal width. This option is ignored if {--width} is set." ) + " some other messages. The default is 120. This option is ignored if" \ + " --width is set." ) #:def_opt( "QUIET", "q|quiet", "GM", \ "", \ @@ -22507,6 +22787,15 @@ "", \ "This debug option enables the logging of internal lists and maps." ) +#:def_opt( "WARN", "W|warn", "GP", \ + "list", \ + "Enable or disable warnings. Parameter @'list'@ is a comma separated" \ + " list of keywords. A minus sign before a keyword disables a warning." \ + " Each occurrence of the option will only change entered warning and" \ + " all other warnings are untouched.\n" \ + " Keyword @DEFAULT@ resets the default settings, @OFF@ disables and" \ + " @ALL@ enables all. The other allowed keywords are: @INVALID-OFFSET@." ) + #:def_opt( "DE", "de", "G", \ "", \ "Use german track and arena names." ) @@ -22867,7 +23156,13 @@ #:def_opt( "NO_0X", "0|no-0x|no0x", "C", \ "", \ - "Suppress 0x prefix of hex numbers." ) + "Suppress 0x prefix of hex numbers. This is the default for cheat" \ + " codes." ) + +#:def_opt( "UPPER", "U|upper", "C", \ + "", \ + "Print digits A-F of hex numbers in upper case. This is the default" \ + " for cheat codes." ) #:def_opt( "VADDR", "vaddr|va", "CP", \ "RANGE", \ @@ -23243,6 +23538,10 @@ "", \ "" ) +#:def_cmd_opt( "PORT", "UPPER", \ + "", \ + "" ) + #:def_cmd_opt( "PORT", "NO_HEADER", \ "", \ "Suppress the table header and footer and output exactly 1 line for" \ @@ -23264,6 +23563,10 @@ "", \ "" ) +#:def_cmd_opt( "WHERE", "UPPER", \ + "", \ + "" ) + #:def_cmd_opt( "WHERE", "NO_HEADER", \ "", \ "Suppress the table header and footer and output exactly 1 line for" \ diff --git a/project/src/ui/ui.h b/project/src/ui/ui.h index 72b5a90..409b8fd 100644 --- a/project/src/ui/ui.h +++ b/project/src/ui/ui.h @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * diff --git a/project/src/wbmgt.c b/project/src/wbmgt.c index 8c9ac2e..58ca368 100644 --- a/project/src/wbmgt.c +++ b/project/src/wbmgt.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -68,6 +68,7 @@ static void help_exit ( bool xmode ) { + SetupPager(); fputs( TITLE "\n", stdout ); if (xmode) @@ -79,6 +80,7 @@ static void help_exit ( bool xmode ) else PrintHelpCmd(&InfoUI_wbmgt,stdout,0,0,"HELP",0,URI_HOME); + ClosePager(); exit(ERR_OK); } @@ -772,6 +774,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_QUIET: verbose = verbose > -1 ? -1 : verbose - 1; break; case GO_VERBOSE: verbose = verbose < 0 ? 0 : verbose + 1; break; case GO_LOGGING: logging++; break; + case GO_WARN: err += ScanOptWarn(optarg); break; case GO_DE: use_de = true; break; case GO_CT_CODE: ctcode_enabled = true; break; case GO_LE_CODE: lecode_enabled = true; break; @@ -887,8 +890,7 @@ static enumError CheckCommand ( int argc, char ** argv ) switch ((enumCommands)cmd_ct->id) { case CMD_VERSION: version_exit(); - case CMD_HELP: PrintHelp(&InfoUI_wbmgt,stdout,0,"HELP",0,URI_HOME, - first_param ? first_param->arg : 0 ); break; + case CMD_HELP: PrintHelpColor(&InfoUI_wbmgt); break; case CMD_CONFIG: err = cmd_config(); break; case CMD_ARGTEST: err = cmd_argtest(argc,argv); break; case CMD_TEST: err = cmd_test(); break; diff --git a/project/src/wctct.c b/project/src/wctct.c index b81066f..82bd675 100644 --- a/project/src/wctct.c +++ b/project/src/wctct.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -58,6 +58,7 @@ static void help_exit ( bool xmode ) { + SetupPager(); fputs( TITLE "\n", stdout ); if (xmode) @@ -69,6 +70,7 @@ static void help_exit ( bool xmode ) else PrintHelpCmd(&InfoUI_wctct,stdout,0,0,"HELP",0,URI_HOME); + ClosePager(); exit(ERR_OK); } @@ -749,6 +751,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_QUIET: verbose = verbose > -1 ? -1 : verbose - 1; break; case GO_VERBOSE: verbose = verbose < 0 ? 0 : verbose + 1; break; case GO_LOGGING: logging++; break; + case GO_WARN: err += ScanOptWarn(optarg); break; case GO_DE: use_de = true; break; case GO_COLORS: err += ScanOptColorize(0,optarg,0); break; case GO_NO_COLORS: opt_colorize = COLMD_OFF; break; @@ -892,8 +895,7 @@ static enumError CheckCommand ( int argc, char ** argv ) switch ((enumCommands)cmd_ct->id) { case CMD_VERSION: version_exit(); - case CMD_HELP: PrintHelp(&InfoUI_wctct,stdout,0,"HELP",0,URI_HOME, - first_param ? first_param->arg : 0 ); break; + case CMD_HELP: PrintHelpColor(&InfoUI_wctct); break; case CMD_CONFIG: err = cmd_config(); break; case CMD_ARGTEST: err = cmd_argtest(argc,argv); break; case CMD_TEST: err = cmd_test(); break; diff --git a/project/src/wimgt.c b/project/src/wimgt.c index 61ef456..835e34e 100644 --- a/project/src/wimgt.c +++ b/project/src/wimgt.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -64,6 +64,7 @@ static void help_exit ( bool xmode ) { + SetupPager(); fputs( TITLE "\n", stdout ); if (xmode) @@ -75,6 +76,7 @@ static void help_exit ( bool xmode ) else PrintHelpCmd(&InfoUI_wimgt,stdout,0,0,"HELP",0,URI_HOME); + ClosePager(); exit(ERR_OK); } @@ -585,6 +587,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_QUIET: verbose = verbose > -1 ? -1 : verbose - 1; break; case GO_VERBOSE: verbose = verbose < 0 ? 0 : verbose + 1; break; case GO_LOGGING: logging++; break; + case GO_WARN: err += ScanOptWarn(optarg); break; case GO_DE: use_de = true; break; case GO_CT_CODE: ctcode_enabled = true; break; case GO_LE_CODE: lecode_enabled = true; break; @@ -692,8 +695,7 @@ static enumError CheckCommand ( int argc, char ** argv ) switch ((enumCommands)cmd_ct->id) { case CMD_VERSION: version_exit(); - case CMD_HELP: PrintHelp(&InfoUI_wimgt,stdout,0,"HELP",0,URI_HOME, - first_param ? first_param->arg : 0 ); break; + case CMD_HELP: PrintHelpColor(&InfoUI_wimgt); break; case CMD_CONFIG: err = cmd_config(); break; case CMD_ARGTEST: err = cmd_argtest(argc,argv); break; case CMD_TEST: err = cmd_test(); break; diff --git a/project/src/wkclt.c b/project/src/wkclt.c index fd55727..5538ecd 100644 --- a/project/src/wkclt.c +++ b/project/src/wkclt.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -37,6 +37,8 @@ #include "lib-kcl.h" #include "lib-szs.h" +#include "crypt.h" +#include "lib-checksum.h" #include "ui.h" // [[dclib]] wrapper #include "ui-wkclt.c" #include <math.h> @@ -58,6 +60,7 @@ extern const char text_kcl_flag_template_cr[]; static void help_exit ( bool xmode ) { + SetupPager(); fputs( TITLE "\n", stdout ); if (xmode) @@ -69,6 +72,7 @@ static void help_exit ( bool xmode ) else PrintHelpCmd(&InfoUI_wkclt,stdout,0,0,"HELP",0,URI_HOME); + ClosePager(); exit(ERR_OK); } @@ -655,6 +659,80 @@ static enumError cmd_cff() // /////////////////////////////////////////////////////////////////////////////// +/////////////// command types /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static enumError cmd_types() +{ + stdlog = stderr; + + if (print_header) + { + if (brief_count) + printf("\n flag\n" + "-------\n"); + else + printf("\n flag = type | variant : W X Y Z Ty\n" + "-----------------------------------------\n"); + } + + enumError cmd_err = ERR_OK; + ParamList_t *param; + for ( param = first_param; param; param = param->next ) + { + char *arg = param->arg; + u16 value = str2ul(arg,&arg,16); + for(;;) + { + while ( *arg > 0 && *arg <= ' ' || *arg == ',' ) + arg++; + if (!*arg) + break; + char ch = tolower((int)*arg++); + if ( *arg == '=' ) + arg++; + u16 mask = 0, par = str2ul(arg,&arg,10); + int shift = 0; + switch (ch) + { + case 't': mask = 0x001f; break; + case 'v': mask = 0xffe0; shift = 5; break; + case 'w': mask = 0xe000; shift = 13; break; + case 'x': mask = 0x1800; shift = 11; break; + case 'y': mask = 0x0700; shift = 8; break; + case 'z': mask = 0x00e0; shift = 5; break; + } + if (!mask) + break; + value = value & ~mask | (par<<shift) & mask; + } + + if (brief_count) + printf("0x%04x\n",value); + else + { + const int w = value >> 13 & 7; + const int x = value >> 11 & 3; + const int y = value >> 8 & 7; + const int z = value >> 5 & 7; + + printf( + " 0x%04x = 0x%02x | 0x%03x << 5 : %c %c %c %c %2d\n", + value, value & 0x1f, value >> 5, + w ? '0'+w : '-', + x ? '0'+x : '-', + y ? '0'+y : '-', + z ? '0'+z : '-', + value & 0x1f ); + } + } + if (print_header) + putchar('\n'); + return cmd_err; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// command flags /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -695,8 +773,8 @@ static enumError cmd_flags() memset(tcount,0,sizeof(tcount)); if ( print_header && !brief_count ) - printf("\n flag type variant triangle count\n" - "-----------------------------------------------\n"); + printf("\n flag = type | variant : W X Y Z Ty : triangle count\n" + "------------------------------------------------------------\n"); uint i, j; for ( i = 0; i < N_KCL_TYPE; i++ ) @@ -709,8 +787,21 @@ static enumError cmd_flags() if (!brief_count) { done++; - printf(" 0x%04x = 0x%02x | 0x%03x << 5 :%7u = %6.2f%%\n", + const int w = j >> 13 & 7; + const int x = j >> 11 & 3; + const int y = j >> 8 & 7; + const int z = j >> 5 & 7; + + printf( + " 0x%04x = 0x%02x | 0x%03x << 5" + " : %c %c %c %c %2d" + " :%7u = %6.2f%%\n", j, j & 0x1f, j >> 5, + w ? '0'+w : '-', + x ? '0'+x : '-', + y ? '0'+y : '-', + z ? '0'+z : '-', + j & 0x1f, count[j], 100.0 * count[j] / n ); } } @@ -720,12 +811,12 @@ static enumError cmd_flags() if (print_header) printf( "\n" - " type triangle count type description\n" - "--------------------------------------------------\n"); + " type : triangle count : type description\n" + "---------------------------------------------------\n"); for ( i = 0; i < N_KCL_TYPE; i++ ) if (tcount[i]) - printf(" T 0x%02x :%7u = %6.2f%% %s\n", + printf(" T 0x%02x :%7u = %6.2f%% : %s\n", i, tcount[i], 100.0 * tcount[i] / n, kcl_type[i].info ); putchar('\n'); @@ -946,6 +1037,74 @@ static enumError cmd_check() // /////////////////////////////////////////////////////////////////////////////// +/////////////// command sha1 /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static enumError cmd_sha1() +{ + stdlog = stderr; + enumError max_err = ERR_OK; + SetPatchFileModeReadonly(); + SetupCoding64( opt_coding64, opt_db64 ? ENCODE_BASE64URL : ENCODE_BASE64 ); + + 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,autoname,opt_ignore>0,FF_KCL); + + if ( max_err < err ) + max_err = err; + + if ( err > ERR_WARNING || err == ERR_NOT_EXISTS ) + { + if ( opt_db64 ) + { + putchar('-'); + if (long_count) + fputs(" -1 -1 0.000 -",stdout); + if (brief_count) + putchar('\n'); + else + printf(" %s\n",param->arg); + } + + if ( err == ERR_NOT_EXISTS || opt_ignore ) + continue; + return err; + } + + kcl_t kcl; + err = ScanRawDataKCL(&kcl,true,&raw,true,0); + if ( err > ERR_WARNING ) + return err; + + err = CreateRawKCL(&kcl,false); + if ( err > ERR_WARNING ) + return err; + + sha1_size_t info; + SHA1(kcl.raw_data,kcl.raw_data_size,info.hash); + info.size = htonl(kcl.raw_data_size); + char checksum[100]; + CreateSSChecksum(checksum,sizeof(checksum),&info); + + if (brief_count) + printf("%s\n",checksum); + else + printf("%s %s\n",checksum,kcl.fname); + ResetKCL(&kcl); + } + + ResetRawData(&raw); + return max_err; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// command analyze /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -1022,6 +1181,7 @@ static void analyze_kcl ( kcl_t *kcl ) static enumError cmd_analyze() { stdlog = stderr; + patch_action_log_disabled++; raw_data_t raw; InitializeRawData(&raw); @@ -1125,6 +1285,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_QUIET: verbose = verbose > -1 ? -1 : verbose - 1; break; case GO_VERBOSE: verbose = verbose < 0 ? 0 : verbose + 1; break; case GO_LOGGING: logging++; break; + case GO_WARN: err += ScanOptWarn(optarg); break; case GO_DE: use_de = true; break; case GO_CT_CODE: ctcode_enabled = true; break; case GO_LE_CODE: lecode_enabled = true; break; @@ -1186,6 +1347,11 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_TRACKS: err += ScanOptTracks(optarg); break; case GO_ARENAS: err += ScanOptArenas(optarg); break; + case GO_ID: opt_id = true; break; + case GO_BASE64: opt_base64 = true; err += ScanOptCoding64(optarg); break; + case GO_DB64: opt_db64 = true; err += ScanOptCoding64(optarg); break; + case GO_CODING: err += ScanOptCoding64(optarg); break; + case GO_ROUND: opt_round = true; break; case GO_LONG: long_count++; break; case GO_NO_HEADER: print_header = false; break; @@ -1249,8 +1415,7 @@ static enumError CheckCommand ( int argc, char ** argv ) switch ((enumCommands)cmd_ct->id) { case CMD_VERSION: version_exit(); - case CMD_HELP: PrintHelp(&InfoUI_wkclt,stdout,0,"HELP",0,URI_HOME, - first_param ? first_param->arg : 0 ); break; + case CMD_HELP: PrintHelpColor(&InfoUI_wkclt); break; case CMD_CONFIG: err = cmd_config(); break; case CMD_ARGTEST: err = cmd_argtest(argc,argv); break; case CMD_TEST: err = cmd_test(); break; @@ -1271,6 +1436,7 @@ static enumError CheckCommand ( int argc, char ** argv ) case CMD_ENCODE: err = cmd_convert(cmd_ct->id,"ENCODE","\1P/\1N\1?T"); break; case CMD_COPY: err = cmd_copy(); break; case CMD_CFF: err = cmd_cff(); break; + case CMD_TYPES: err = cmd_types(); break; case CMD_FLAGS: err = cmd_flags(); break; case CMD_DUMP: err = cmd_dump(0,CMD_DUMP); break; case CMD_DBRIEF: err = cmd_dump(1,CMD_DUMP); break; @@ -1279,6 +1445,7 @@ static enumError CheckCommand ( int argc, char ** argv ) case CMD_TRAVERSE: err = cmd_traverse(false); break; case CMD_FALL: err = cmd_traverse(true); break; case CMD_CHECK: err = cmd_check(); break; + case CMD_SHA1: err = cmd_sha1(); break; case CMD_ANALYZE: err = cmd_analyze(); break; case CMD_BLOW: err = cmd_blow(); break; diff --git a/project/src/wkmpt.c b/project/src/wkmpt.c index 60ffafb..9c5b341 100644 --- a/project/src/wkmpt.c +++ b/project/src/wkmpt.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -59,6 +59,7 @@ static const char autoname[] = "/course.kmp"; static void help_exit ( bool xmode ) { + SetupPager(); fputs( TITLE "\n", stdout ); if (xmode) @@ -70,6 +71,7 @@ static void help_exit ( bool xmode ) else PrintHelpCmd(&InfoUI_wkmpt,stdout,0,0,"HELP",0,URI_HOME); + ClosePager(); exit(ERR_OK); } @@ -385,7 +387,7 @@ static enumError cmd_xexport() if ( strlen(cr->info) >= sizeof(cr->info) ) printf("ERR: STRLEN(INFO,%#x): %zd >= %zd : %s\n", cr->ref_id, strlen(cr->info), sizeof(cr->info), cr->info ); - + if (!(cr->ref_id&1)) { const gobj_cond_ref_t *next = cr+1; @@ -1581,6 +1583,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_QUIET: verbose = verbose > -1 ? -1 : verbose - 1; break; case GO_VERBOSE: verbose = verbose < 0 ? 0 : verbose + 1; break; case GO_LOGGING: logging++; break; + case GO_WARN: err += ScanOptWarn(optarg); break; case GO_DE: use_de = true; break; case GO_CT_CODE: ctcode_enabled = true; break; case GO_LE_CODE: lecode_enabled = true; break; @@ -1728,8 +1731,7 @@ static enumError CheckCommand ( int argc, char ** argv ) switch ((enumCommands)cmd_ct->id) { case CMD_VERSION: version_exit(); - case CMD_HELP: PrintHelp(&InfoUI_wkmpt,stdout,0,"HELP",0,URI_HOME, - first_param ? first_param->arg : 0 ); break; + case CMD_HELP: PrintHelpColor(&InfoUI_wkmpt); break; case CMD_CONFIG: err = cmd_config(); break; case CMD_ARGTEST: err = cmd_argtest(argc,argv); break; case CMD_TEST: err = cmd_test(); break; diff --git a/project/src/wlect.c b/project/src/wlect.c index 2fc1bea..3ea7ea5 100644 --- a/project/src/wlect.c +++ b/project/src/wlect.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -60,6 +60,7 @@ static const char autoname[] = "/course.lex"; static void help_exit ( bool xmode ) { + SetupPager(); fputs( TITLE "\n", stdout ); if (xmode) @@ -71,6 +72,7 @@ static void help_exit ( bool xmode ) else PrintHelpCmd(&InfoUI_wlect,stdout,0,0,"HELP",0,URI_HOME); + ClosePager(); exit(ERR_OK); } @@ -251,11 +253,19 @@ static enumError cmd_dpad() ccp arg = param->arg; while ( *arg && (uint)*arg <= ' ' ) arg++; + + bool hex_scanned = false; u32 num = 0; if ( *arg >= '0' && *arg <= '9' || *arg >= 'a' && *arg <= 'f' || *arg >= 'A' && *arg <= 'F' ) - num = str2l(arg,0,16); - else { + char *end; + num = str2ul(arg,&end,16); + hex_scanned = num && !*end; + } + + if (!hex_scanned) + { + num = 0; while (*arg) { switch (*arg++) @@ -959,6 +969,7 @@ static enumError cmd_cat() if (!testmode) { InitializeOutputMode(&output_mode); + output_mode.lecode = true; err = SaveTextCTCODE(&ctcode,"-",false,&output_mode); fflush(stdout); if ( err > ERR_WARNING ) @@ -1117,6 +1128,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_QUIET: verbose = verbose > -1 ? -1 : verbose - 1; break; case GO_VERBOSE: verbose = verbose < 0 ? 0 : verbose + 1; break; case GO_LOGGING: logging++; break; + case GO_WARN: err += ScanOptWarn(optarg); break; case GO_DE: use_de = true; break; case GO_CT_CODE: ctcode_enabled = true; break; case GO_LE_CODE: lecode_enabled = true; break; @@ -1159,6 +1171,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_ORDER_ALL: opt_order_all = true; break; case GO_LE_DEFINE: opt_le_define = optarg; break; + case GO_LE_ARENA: opt_le_arena = optarg; break; case GO_LPAR: opt_lpar = optarg; break; case GO_ALIAS: err += ScanOptAlias(optarg); break; case GO_ENGINE: err += ScanOptEngine(optarg); break; @@ -1270,8 +1283,7 @@ static enumError CheckCommand ( int argc, char ** argv ) switch ((enumCommands)cmd_ct->id) { case CMD_VERSION: version_exit(); - case CMD_HELP: PrintHelp(&InfoUI_wlect,stdout,0,"HELP",0,URI_HOME, - first_param ? first_param->arg : 0 ); break; + case CMD_HELP: PrintHelpColor(&InfoUI_wlect); break; case CMD_CONFIG: err = cmd_config(); break; case CMD_ARGTEST: err = cmd_argtest(argc,argv); break; case CMD_TEST: err = cmd_test(); break; diff --git a/project/src/wmdlt.c b/project/src/wmdlt.c index 77bc384..b78ea83 100644 --- a/project/src/wmdlt.c +++ b/project/src/wmdlt.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -53,6 +53,7 @@ static void help_exit ( bool xmode ) { + SetupPager(); fputs( TITLE "\n", stdout ); if (xmode) @@ -64,6 +65,7 @@ static void help_exit ( bool xmode ) else PrintHelpCmd(&InfoUI_wmdlt,stdout,0,0,"HELP",0,URI_HOME); + ClosePager(); exit(ERR_OK); } @@ -542,6 +544,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_QUIET: verbose = verbose > -1 ? -1 : verbose - 1; break; case GO_VERBOSE: verbose = verbose < 0 ? 0 : verbose + 1; break; case GO_LOGGING: logging++; break; + case GO_WARN: err += ScanOptWarn(optarg); break; case GO_DE: use_de = true; break; case GO_CT_CODE: ctcode_enabled = true; break; case GO_LE_CODE: lecode_enabled = true; break; @@ -659,8 +662,7 @@ static enumError CheckCommand ( int argc, char ** argv ) switch ((enumCommands)cmd_ct->id) { case CMD_VERSION: version_exit(); - case CMD_HELP: PrintHelp(&InfoUI_wmdlt,stdout,0,"HELP",0,URI_HOME, - first_param ? first_param->arg : 0 ); break; + case CMD_HELP: PrintHelpColor(&InfoUI_wmdlt); break; case CMD_CONFIG: err = cmd_config(); break; case CMD_ARGTEST: err = cmd_argtest(argc,argv); break; case CMD_TEST: err = cmd_test(); break; diff --git a/project/src/wpatt.c b/project/src/wpatt.c index 0cfb061..47107a5 100644 --- a/project/src/wpatt.c +++ b/project/src/wpatt.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -53,6 +53,7 @@ static void help_exit ( bool xmode ) { + SetupPager(); fputs( TITLE "\n", stdout ); if (xmode) @@ -64,6 +65,7 @@ static void help_exit ( bool xmode ) else PrintHelpCmd(&InfoUI_wpatt,stdout,0,0,"HELP",0,URI_HOME); + ClosePager(); exit(ERR_OK); } @@ -351,6 +353,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_QUIET: verbose = verbose > -1 ? -1 : verbose - 1; break; case GO_VERBOSE: verbose = verbose < 0 ? 0 : verbose + 1; break; case GO_LOGGING: logging++; break; + case GO_WARN: err += ScanOptWarn(optarg); break; case GO_DE: use_de = true; break; case GO_CT_CODE: ctcode_enabled = true; break; case GO_LE_CODE: lecode_enabled = true; break; @@ -453,8 +456,7 @@ static enumError CheckCommand ( int argc, char ** argv ) switch ((enumCommands)cmd_ct->id) { case CMD_VERSION: version_exit(); - case CMD_HELP: PrintHelp(&InfoUI_wpatt,stdout,0,"HELP",0,URI_HOME, - first_param ? first_param->arg : 0 ); break; + case CMD_HELP: PrintHelpColor(&InfoUI_wpatt); break; case CMD_CONFIG: err = cmd_config(); break; case CMD_ARGTEST: err = cmd_argtest(argc,argv); break; case CMD_TEST: err = cmd_test(); break; diff --git a/project/src/wstrt.c b/project/src/wstrt.c index 8bdcf39..7708f78 100644 --- a/project/src/wstrt.c +++ b/project/src/wstrt.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -65,6 +65,7 @@ static void help_exit ( bool xmode ) { + SetupPager(); fputs( TITLE "\n", stdout ); if (xmode) @@ -76,6 +77,7 @@ static void help_exit ( bool xmode ) else PrintHelpCmd(&InfoUI_wstrt,stdout,0,0,"HELP",0,URI_HOME); + ClosePager(); exit(ERR_OK); } @@ -419,6 +421,7 @@ static void setup_order ( int index[STR_ZBI_N], int delta ) switch(*ptr++) { case 'p': case 'P': idx = STR_M_PAL - STR_ZBI_FIRST; break; + case 'e': case 'E': case 'u': case 'U': idx = STR_M_USA - STR_ZBI_FIRST; break; case 'j': case 'J': idx = STR_M_JAP - STR_ZBI_FIRST; break; case 'k': case 'K': idx = STR_M_KOR - STR_ZBI_FIRST; break; @@ -453,7 +456,7 @@ typedef struct hex_in_t u32 cheat; // if is_cheat: highest 7 bits bool is_dol_offset; // true: prefix 'M' used bool is_rel_offset; // true: prefix 'S' used - bool is_cheat; // if a cheat code, where only lowest 25 bits are relevant + bool is_cheat; // it's a cheat code, where only lowest 25 bits are relevant bool is_6hex; // hex number with exact 6 hex digits } hex_in_t; @@ -462,7 +465,7 @@ hex_in_t; static hex_in_t scan_hex ( str_mode_t mode, ccp arg ) { - hex_in_t hex = {0}; + hex_in_t hex = { .cheat = ~0 }; hex.is_dol_offset = *arg == 'm' || *arg == 'M'; hex.is_rel_offset = *arg == 's' || *arg == 'S'; @@ -495,20 +498,32 @@ static hex_in_t scan_hex ( str_mode_t mode, ccp arg ) static void print_address ( u32 addr, bool highlight, u32 cheat_code ) { - if (cheat_code) + const bool is_cheat_code = cheat_code != ~0; + if (is_cheat_code) addr = addr & 0x01ffffff | cheat_code; + ccp col1, col2; if (highlight) { + col1 = colout->value; + col2 = colout->reset; + } + else + col1 = col2 = ""; + + if ( opt_upper || is_cheat_code ) + { if (opt_no_0x) - printf(" %s%08x%s",colout->value,addr,colout->reset); + printf(" %s%08X%s",col1,addr,col2); + else if (is_cheat_code) + printf(" %s%08X%s",col1,addr,col2); else - printf(" %s%#010x%s",colout->value,addr,colout->reset); + printf(" %s%#010X%s",col1,addr,col2); } else if (opt_no_0x) - printf(" %08x",addr); + printf(" %s%08x%s",col1,addr,col2); else - printf(" %#010x",addr); + printf(" %s%#010x%s",col1,addr,col2); } /////////////////////////////////////////////////////////////////////////////// @@ -519,17 +534,29 @@ static void print_offset ( str_mode_t mode, u32 addr, bool highlight ) if ( aoff < 0 ) printf(" %s-", opt_no_0x ? "": " " ); - else if ( highlight ) + else { - if (opt_no_0x) - printf(" %s%6x%s",colout->value,aoff,colout->reset); + ccp col1, col2; + if (highlight) + { + col1 = colout->value; + col2 = colout->reset; + } else - printf(" %s%#8x%s",colout->value,aoff,colout->reset); + col1 = col2 = ""; + + if ( opt_upper ) + { + if (opt_no_0x) + printf(" %s%6X%s",col1,aoff,col2); + else + printf(" %s%#8X%s",col1,aoff,col2); + } + else if (opt_no_0x) + printf(" %s%6x%s",col1,aoff,col2); + else + printf(" %s%#8x%s",col1,aoff,col2); } - else if (opt_no_0x) - printf(" %6x",aoff); - else - printf(" %#8x",aoff); } // @@ -547,12 +574,14 @@ static enumError cmd_port() SetupAddrPortDB(); const addr_port_version_t *vers = GetAddrPortVersion(); printf("\nAddress Porting Database:\n" - " Time stamp: %s\n" + " File: %s\n" + " Timestamp: %s\n" " DB version: %5u\n" " Revision: %5u\n" " N(records): %5u\n" " Size: %5s\n" - ,PrintTimeByFormat("%F %T",vers->timestamp) + ,addr_port_file + ,PrintTimeByFormat("%F %T %Z",vers->timestamp) ,vers->db_version ,vers->revision ,vers->n_records @@ -1557,6 +1586,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_QUIET: verbose = verbose > -1 ? -1 : verbose - 1; break; case GO_VERBOSE: verbose = verbose < 0 ? 0 : verbose + 1; break; case GO_LOGGING: logging++; break; + case GO_WARN: err += ScanOptWarn(optarg); break; case GO_DE: use_de = true; break; case GO_CT_CODE: ctcode_enabled = true; break; case GO_LE_CODE: lecode_enabled = true; break; @@ -1641,6 +1671,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_PORT_DB: opt_port_db = optarg; break; case GO_ORDER: opt_order = optarg; break; case GO_NO_0X: opt_no_0x = true; break; + case GO_UPPER: opt_upper = true; break; case GO_VADDR: InsertAddressMemMap(&vaddr,true,optarg,16); break; case GO_FADDR: InsertAddressMemMap(&faddr,true,optarg,16); break; @@ -1754,8 +1785,7 @@ static enumError CheckCommand ( int argc, char ** argv ) switch ((enumCommands)cmd_ct->id) { case CMD_VERSION: version_exit(); - case CMD_HELP: PrintHelp(&InfoUI_wstrt,stdout,0,"HELP",0,URI_HOME, - first_param ? first_param->arg : 0 ); break; + case CMD_HELP: PrintHelpColor(&InfoUI_wstrt); break; case CMD_CONFIG: err = cmd_config(); break; case CMD_ARGTEST: err = cmd_argtest(argc,argv); break; case CMD_TEST: err = cmd_test(); break; diff --git a/project/src/wszst.c b/project/src/wszst.c index 4171de9..f39bd59 100644 --- a/project/src/wszst.c +++ b/project/src/wszst.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -51,6 +51,12 @@ #include "lib-image.h" #include "lib-common.h" #include "lib-rkg.h" +#include "lib-bzip2.h" +#include "lib-pack.h" +#include "lib-rarc.h" +#include "lib-rkc.h" +#include "lib-staticr.h" +#include "db-dol.h" #include "crypt.h" #include "ui.h" // [[dclib]] wrapper #include "ui-wszst.c" @@ -81,6 +87,7 @@ static void help_exit ( bool xmode ) { + SetupPager(); fputs( TITLE "\n", stdout ); if (xmode) @@ -92,6 +99,7 @@ static void help_exit ( bool xmode ) else PrintHelpCmd(&InfoUI_wszst,stdout,0,0,"HELP",0,URI_HOME); + ClosePager(); exit(ERR_OK); } @@ -245,6 +253,344 @@ static void set_all ( bool force_cut ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// sizeof data /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static const sizeof_info_t sizeof_info_szs_list[] = +{ + SIZEOF_INFO_TITLE("SZS basics") + SIZEOF_INFO_ENTRY(compatible_info_t) + SIZEOF_INFO_ENTRY(SubFile_t) + SIZEOF_INFO_ENTRY(SubFileList_t) + SIZEOF_INFO_ENTRY(SubDirList_t) + SIZEOF_INFO_ENTRY(SubDir_t) + SIZEOF_INFO_ENTRY(SubFileIterator_t) + SIZEOF_INFO_ENTRY(DataContainer_t) + SIZEOF_INFO_ENTRY(search_filter_t) + SIZEOF_INFO_ENTRY(SubstString_t) + SIZEOF_INFO_ENTRY(repair_ff_t) + SIZEOF_INFO_ENTRY(slot_info_t) + SIZEOF_INFO_ENTRY(FormatFieldItem_t) + SIZEOF_INFO_ENTRY(FormatField_t) + SIZEOF_INFO_ENTRY(tiny_param_t) + SIZEOF_INFO_ENTRY(ParamList_t) + SIZEOF_INFO_ENTRY(List_t) + SIZEOF_INFO_ENTRY(MemItem_t) + SIZEOF_INFO_ENTRY(SetupDef_t) + SIZEOF_INFO_ENTRY(ListDef_t) + SIZEOF_INFO_ENTRY(SetupParam_t) + SIZEOF_INFO_ENTRY(config_t) + SIZEOF_INFO_ENTRY(data_tab_t) + SIZEOF_INFO_ENTRY(output_mode_t) + + SIZEOF_INFO_TITLE("SZS basics: numeric") + SIZEOF_INFO_ENTRY(tri_metrics_t) + SIZEOF_INFO_ENTRY(octahedron_t) + SIZEOF_INFO_ENTRY(cuboid_t) + SIZEOF_INFO_ENTRY(IndexList_t) + SIZEOF_INFO_ENTRY(FuncParam_t) + SIZEOF_INFO_ENTRY(FuncTable_t) + SIZEOF_INFO_ENTRY(FuncInfo_t) + SIZEOF_INFO_ENTRY(Var_t) + SIZEOF_INFO_ENTRY(VarMap_t) + SIZEOF_INFO_ENTRY(ScanLoop_t) + SIZEOF_INFO_ENTRY(ScanMacro_t) + SIZEOF_INFO_ENTRY(ScanFile_t) + SIZEOF_INFO_ENTRY(ScanInfo_t) + SIZEOF_INFO_ENTRY(ScanParam_t) + SIZEOF_INFO_ENTRY(Line_t) + + SIZEOF_INFO_TITLE("Archives and packing") + SIZEOF_INFO_ENTRY(BZIP2_t) + SIZEOF_INFO_ENTRY(BZ2Manager_t) + SIZEOF_INFO_ENTRY(BZ2Source_t) + SIZEOF_INFO_ENTRY(sha1_size_t) + SIZEOF_INFO_ENTRY(sha1_type_t) + SIZEOF_INFO_ENTRY(sha1_db_t) + SIZEOF_INFO_ENTRY(DistributionInfo_t) + SIZEOF_INFO_ENTRY(pack_header_t) + SIZEOF_INFO_ENTRY(pack_metric_t) + + SIZEOF_INFO_TITLE("BREFF & BREFT") + SIZEOF_INFO_ENTRY(breff_root_head_t) + SIZEOF_INFO_ENTRY(breff_root_t) + SIZEOF_INFO_ENTRY(breff_item_name_t) + SIZEOF_INFO_ENTRY(breff_item_data_t) + SIZEOF_INFO_ENTRY(breff_item_list_t) + SIZEOF_INFO_ENTRY(breft_image_t) + + SIZEOF_INFO_TITLE("BRRES") + SIZEOF_INFO_ENTRY(brres_info_t) + SIZEOF_INFO_ENTRY(brsub_list_t) + SIZEOF_INFO_ENTRY(brsub_info_t) + SIZEOF_INFO_ENTRY(brsub_iterator_t) + SIZEOF_INFO_ENTRY(brres_t) + SIZEOF_INFO_ENTRY(tex_info_t) + SIZEOF_INFO_ENTRY(name_ref_elem_t) + SIZEOF_INFO_ENTRY(name_ref_var_t) + SIZEOF_INFO_ENTRY(name_ref_t) + + SIZEOF_INFO_TITLE("Common files") + SIZEOF_INFO_ENTRY(object_type_t) + SIZEOF_INFO_ENTRY(object_mgr_t) + SIZEOF_INFO_ENTRY(itemslot_bin_t) + SIZEOF_INFO_ENTRY(itemslot_t) + SIZEOF_INFO_ENTRY(minigame_kmg_head_t) + SIZEOF_INFO_ENTRY(minigame_kmg_t) + SIZEOF_INFO_ENTRY(minigame_t) + SIZEOF_INFO_ENTRY(objflow_bin_t) + SIZEOF_INFO_ENTRY(objflow_t) + SIZEOF_INFO_ENTRY(geohit_bin_t) + SIZEOF_INFO_ENTRY(geohit_t) + + SIZEOF_INFO_TITLE("CT-CODE") + SIZEOF_INFO_ENTRY(ctcode_sect_info_t) + SIZEOF_INFO_ENTRY(ctcode_header_t) + SIZEOF_INFO_ENTRY(ctcode_cup1_data_t) + SIZEOF_INFO_ENTRY(ctcode_cup1_head_t) + SIZEOF_INFO_ENTRY(ctcode_crs1_data_t) + SIZEOF_INFO_ENTRY(ctcode_crs1_head_t) + SIZEOF_INFO_ENTRY(ctcode_cupref_t) + SIZEOF_INFO_ENTRY(ctcode_arena_t) + SIZEOF_INFO_ENTRY(ctcode_t) + + SIZEOF_INFO_TITLE("DOL") + SIZEOF_INFO_ENTRY(DolSectionMap_t) + SIZEOF_INFO_ENTRY(DolAddressMap_t) + + SIZEOF_INFO_TITLE("File DB") + SIZEOF_INFO_ENTRY(DbFile_t) + SIZEOF_INFO_ENTRY(DbFileSZS_t) + SIZEOF_INFO_ENTRY(DbFileSHA1_t) + SIZEOF_INFO_ENTRY(DbFileFILE_t) + SIZEOF_INFO_ENTRY(DbFileGROUP_t) + + SIZEOF_INFO_TITLE("Images") + SIZEOF_INFO_ENTRY(MipmapOptions_t) + SIZEOF_INFO_ENTRY(ImageGeometry_t) + SIZEOF_INFO_ENTRY(Image_t) + SIZEOF_INFO_ENTRY(cmpr_info_t) + SIZEOF_INFO_ENTRY(tpl_header_t) + SIZEOF_INFO_ENTRY(tpl_imgtab_t) + SIZEOF_INFO_ENTRY(tpl_pal_header_t) + SIZEOF_INFO_ENTRY(tpl_img_header_t) + SIZEOF_INFO_ENTRY(bti_header_t) + + SIZEOF_INFO_TITLE("KCL") + SIZEOF_INFO_ENTRY(kcl_attrib_name_t) + SIZEOF_INFO_ENTRY(kcl_class_t) + SIZEOF_INFO_ENTRY(kcl_type_t) + SIZEOF_INFO_ENTRY(kcl_analyze_t) + SIZEOF_INFO_ENTRY(kcl_head_t) + SIZEOF_INFO_ENTRY(kcl_triangle_t) + SIZEOF_INFO_ENTRY(kcl_tridata_flt_t) + SIZEOF_INFO_ENTRY(kcl_tridata_dbl_t) + SIZEOF_INFO_ENTRY(kcl_tridata0_t) + SIZEOF_INFO_ENTRY(kcl_tridata1_t) + SIZEOF_INFO_ENTRY(kcl_t) + SIZEOF_INFO_ENTRY(kcl_tri_param_t) + SIZEOF_INFO_ENTRY(kcl_cube_t) + #if SUPPORT_KCL_CUBE + SIZEOF_INFO_ENTRY(kcl_cube_list_t) + #endif + SIZEOF_INFO_ENTRY(kcl_tri_t) + + SIZEOF_INFO_TITLE("KMP basics") + SIZEOF_INFO_ENTRY(kmp_file_gen_t) + SIZEOF_INFO_ENTRY(kmp_file_mkw_t) + SIZEOF_INFO_ENTRY(kmp_file_wim0_t) + SIZEOF_INFO_ENTRY(kmp_head_info_t) + SIZEOF_INFO_ENTRY(kmp_list_head_t) + SIZEOF_INFO_ENTRY(kmp_ktpt_entry_t) + SIZEOF_INFO_ENTRY(kmp_enpt_entry_t) + SIZEOF_INFO_ENTRY(kmp_enph_entry_t) + SIZEOF_INFO_ENTRY(kmp_ckpt_entry_t) + SIZEOF_INFO_ENTRY(kmp_gobj_entry_t) + SIZEOF_INFO_ENTRY(kmp_poti_group_t) + SIZEOF_INFO_ENTRY(kmp_poti_point_t) + SIZEOF_INFO_ENTRY(kmp_area_entry_t) + SIZEOF_INFO_ENTRY(kmp_came_entry_t) + SIZEOF_INFO_ENTRY(kmp_jgpt_entry_t) + SIZEOF_INFO_ENTRY(kmp_stgi_entry_t) + SIZEOF_INFO_ENTRY(kmp_wim0_t) + SIZEOF_INFO_ENTRY(kmp_wim0_sect_t) + SIZEOF_INFO_ENTRY(kmp_wim0_info_t) + SIZEOF_INFO_ENTRY(kmp_section_t) + SIZEOF_INFO_ENTRY(kmp_rtype_info_t) + SIZEOF_INFO_ENTRY(kmp_gopt_t) + SIZEOF_INFO_ENTRY(kmp_gopt2_t) + SIZEOF_INFO_ENTRY(kmp_group_elem_t) + SIZEOF_INFO_ENTRY(kmp_group_t) + SIZEOF_INFO_ENTRY(kmp_group_list_t) + SIZEOF_INFO_ENTRY(kmp_rtobj_t) + SIZEOF_INFO_ENTRY(kmp_rtobj_list_t) + SIZEOF_INFO_ENTRY(kmp_ph_t) + SIZEOF_INFO_ENTRY(kmp_flag_t) + SIZEOF_INFO_ENTRY(kmp_t) + SIZEOF_INFO_ENTRY(Itembox_t) + SIZEOF_INFO_ENTRY(DrawKCL_t) + SIZEOF_INFO_ENTRY(pos_param_t) + SIZEOF_INFO_ENTRY(pos_file_t) + SIZEOF_INFO_ENTRY(kmp_obj_info_t) + + SIZEOF_INFO_TITLE("KMP analysis") + SIZEOF_INFO_ENTRY(kmp_linfo_t) + SIZEOF_INFO_ENTRY(kmp_finish_t) + SIZEOF_INFO_ENTRY(kmp_usedpos_obj_t) + SIZEOF_INFO_ENTRY(kmp_usedpos_t) + SIZEOF_INFO_ENTRY(kmp_pflags_t) + SIZEOF_INFO_ENTRY(gobj_cond_ref_t) + SIZEOF_INFO_ENTRY(gobj_cond_mask_t) + SIZEOF_INFO_ENTRY(cond_ref_info_t) + SIZEOF_INFO_ENTRY(kmp_ana_defobj_t) + SIZEOF_INFO_ENTRY(kmp_ana_ref_t) + SIZEOF_INFO_ENTRY(gobj_condition_t) + SIZEOF_INFO_ENTRY(gobj_condition_set_t) + SIZEOF_INFO_ENTRY(kmp_gobj_info_t) + SIZEOF_INFO_ENTRY(kmp_ana_gobj_t) + SIZEOF_INFO_ENTRY(kmp_ana_pflag_res_t) + SIZEOF_INFO_ENTRY(kmp_ana_pflag_t) + + SIZEOF_INFO_TITLE("LE-CODE") + SIZEOF_INFO_ENTRY(lecode_debug_info_t) + SIZEOF_INFO_ENTRY(lecode_debug_ex_t) + SIZEOF_INFO_ENTRY(le_lpar_t) + SIZEOF_INFO_ENTRY(le_binary_head_t) + SIZEOF_INFO_ENTRY(le_binary_head_v4_t) + SIZEOF_INFO_ENTRY(le_binary_param_t) + SIZEOF_INFO_ENTRY(le_binpar_v1_35_t) + SIZEOF_INFO_ENTRY(le_binpar_v1_37_t) + SIZEOF_INFO_ENTRY(le_binpar_v1_f8_t) + SIZEOF_INFO_ENTRY(le_binpar_v1_1b8_t) + SIZEOF_INFO_ENTRY(le_binpar_v1_1bc_t) + SIZEOF_INFO_ENTRY(le_binpar_v1_260_t) + SIZEOF_INFO_ENTRY(le_binpar_v1_264_t) + SIZEOF_INFO_ENTRY(le_binpar_v1_t) + SIZEOF_INFO_ENTRY(le_cup_par_t) + SIZEOF_INFO_ENTRY(le_course_par_t) + SIZEOF_INFO_ENTRY(le_analyse_t) + + SIZEOF_INFO_TITLE("LEX") + SIZEOF_INFO_ENTRY(features_szs_t) + SIZEOF_INFO_ENTRY(check_features_szs_t) + SIZEOF_INFO_ENTRY(have_lex_info_t) + SIZEOF_INFO_ENTRY(lex_header_t) + SIZEOF_INFO_ENTRY(lex_element_t) + SIZEOF_INFO_ENTRY(lex_set1_t) + SIZEOF_INFO_ENTRY(lex_hipt_rule_t) + SIZEOF_INFO_ENTRY(lex_test_t) + SIZEOF_INFO_ENTRY(lex_item_t) + SIZEOF_INFO_ENTRY(lex_t) + SIZEOF_INFO_ENTRY(lex_info_t) + + SIZEOF_INFO_TITLE("MDL") + SIZEOF_INFO_ENTRY(mdl_head_t) + SIZEOF_INFO_ENTRY(mdl_t) + SIZEOF_INFO_ENTRY(mdl_sect0_t) + SIZEOF_INFO_ENTRY(mdl_sect1_t) + SIZEOF_INFO_ENTRY(mdl_sect2_t) + SIZEOF_INFO_ENTRY(mdl_sect8_t) + SIZEOF_INFO_ENTRY(mdl_sect8_layer_t) + SIZEOF_INFO_ENTRY(Slot42MaterialInfo_t) + SIZEOF_INFO_ENTRY(Slot42MaterialStat_t) + SIZEOF_INFO_ENTRY(mdl_sect10_t) + SIZEOF_INFO_ENTRY(mdl_minimap_t) + SIZEOF_INFO_ENTRY(StringIteratorMDL_t) + + SIZEOF_INFO_TITLE("MKW") + SIZEOF_INFO_ENTRY(TrackInfo_t) + SIZEOF_INFO_ENTRY(MusicInfo_t) + + SIZEOF_INFO_TITLE("Object DB") + SIZEOF_INFO_ENTRY(ObjSettingFormat_t) + SIZEOF_INFO_ENTRY(ObjectInfo_t) + SIZEOF_INFO_ENTRY(ObjSpec_t) + SIZEOF_INFO_ENTRY(UsedObject_t) + SIZEOF_INFO_ENTRY(UsedFile_t) + SIZEOF_INFO_ENTRY(UsedFileSZS_t) + SIZEOF_INFO_ENTRY(UsedFileSHA1_t) + SIZEOF_INFO_ENTRY(UsedFileFILE_t) + SIZEOF_INFO_ENTRY(UsedFileGROUP_t) + + SIZEOF_INFO_TITLE("PAT") + SIZEOF_INFO_ENTRY(pat_head_t) + SIZEOF_INFO_ENTRY(pat_s0_belem_t) + SIZEOF_INFO_ENTRY(pat_s0_bhead_t) + SIZEOF_INFO_ENTRY(pat_s0_sref_t) + SIZEOF_INFO_ENTRY(pat_s0_selem_t) + SIZEOF_INFO_ENTRY(pat_s0_shead_t) + SIZEOF_INFO_ENTRY(pat_analyse_t) + SIZEOF_INFO_ENTRY(pat_element_t) + SIZEOF_INFO_ENTRY(pat_t) + + SIZEOF_INFO_TITLE("RARC") + SIZEOF_INFO_ENTRY(rarc_file_header_t) + SIZEOF_INFO_ENTRY(rarc_header_t) + SIZEOF_INFO_ENTRY(rarc_node_t) + SIZEOF_INFO_ENTRY(rarc_entry_t) + + SIZEOF_INFO_TITLE("RKC") + SIZEOF_INFO_ENTRY(rkco_t) + SIZEOF_INFO_ENTRY(rkct_t) + + SIZEOF_INFO_TITLE("RKG") + SIZEOF_INFO_ENTRY(rkg_head_t) + SIZEOF_INFO_ENTRY(rkg_info_t) + + SIZEOF_INFO_TITLE("StaticR") + SIZEOF_INFO_ENTRY(str_server_list_t) + SIZEOF_INFO_ENTRY(str_server_patch_t) + SIZEOF_INFO_ENTRY(staticr_t) + SIZEOF_INFO_ENTRY(VersusPointsInfo_t) + SIZEOF_INFO_ENTRY(rel_header_t) + SIZEOF_INFO_ENTRY(rel_sect_info_t) + SIZEOF_INFO_ENTRY(rel_imp_t) + SIZEOF_INFO_ENTRY(rel_data_t) + SIZEOF_INFO_ENTRY(rel_info_t) + SIZEOF_INFO_ENTRY(wpf_t) + SIZEOF_INFO_ENTRY(wpf_head_t) + SIZEOF_INFO_ENTRY(addr_port_t) + SIZEOF_INFO_ENTRY(addr_port_version_t) + + SIZEOF_INFO_TITLE("SZS") + SIZEOF_INFO_ENTRY(yaz0_header_t) + SIZEOF_INFO_ENTRY(u8_header_t) + SIZEOF_INFO_ENTRY(u8_node_t) + SIZEOF_INFO_ENTRY(string_pool_t) + SIZEOF_INFO_ENTRY(szs_subfile_t) + SIZEOF_INFO_ENTRY(szs_subfile_list_t) + SIZEOF_INFO_ENTRY(szs_have_t) + SIZEOF_INFO_ENTRY(szs_file_t) + SIZEOF_INFO_ENTRY(szs_norm_t) +// SIZEOF_INFO_ENTRY(check_szs_t) + SIZEOF_INFO_ENTRY(slot_ana_t) + SIZEOF_INFO_ENTRY(iterator_param_t) + SIZEOF_INFO_ENTRY(szs_iterator_t) + SIZEOF_INFO_ENTRY(brres_header_t) + SIZEOF_INFO_ENTRY(brres_entry_t) + SIZEOF_INFO_ENTRY(brres_group_t) + SIZEOF_INFO_ENTRY(brres_root_t) + SIZEOF_INFO_ENTRY(brsub_header_t) + SIZEOF_INFO_ENTRY(brsub_cut_t) + SIZEOF_INFO_ENTRY(szs_extract_t) + SIZEOF_INFO_ENTRY(raw_data_t) + SIZEOF_INFO_ENTRY(wbz_header_t) + SIZEOF_INFO_ENTRY(analyse_szs_t) + SIZEOF_INFO_ENTRY(file_type_t) + + SIZEOF_INFO_TERM() +}; + +//----------------------------------------------------------------------------- + +static const sizeof_info_t *sizeof_info_szs[] = +{ + sizeof_info_szs_list, + 0 +}; + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// command test /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -254,6 +600,7 @@ static enumError cmd_test_options() printf(" test: %16x = %12d\n",testmode,testmode); printf(" verbose: %16x = %12d\n",verbose,verbose); + printf(" warn modes: %16llx = \"%s\"\n",(u64)WARN_MODE,GetWarnMode()); printf(" force: %16x = %12d (kmp=%d)\n",force_count,force_count,force_kmp); printf(" sort: %16x = %12d\n",opt_sort,opt_sort); printf(" width: %16x = %12d\n",opt_width,opt_width); @@ -844,6 +1191,42 @@ static enumError cmd_export() // /////////////////////////////////////////////////////////////////////////////// +/////////////// command sizeof /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static enumError cmd_sizeof() +{ + sizeof_info_order_t order; + switch (GetSortMode(opt_sort,0,SORT_NONE)) + { + case SORT_INAME: order = SIZEOF_ORDER_NAME; break; + case SORT_SIZE: order = SIZEOF_ORDER_SIZE; break; + default: order = SIZEOF_ORDER_NONE; break; + } + + SetupPager(); + PrintMode_t pm = { .fout = stdout, .cout = colout, .debug = logging }; + ArgManager_t am = { .force_case = LOUP_LOWER }; + for ( ParamList_t *param = first_param; param; param = param->next ) + AppendArgManager(&am,param->arg,0,false); + + const sizeof_info_t **si_list; + if (brief_count) + si_list = sizeof_info_szs; + else + { + AddListToSizeofInfoMgr(sizeof_info_szs); + si_list = GetSizeofInfoMgrList(); + } + + ListSizeofInfo(&pm,si_list,&am,order); + + ClosePager(); + return ERR_OK; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// command _CODE /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -985,7 +1368,7 @@ void PrintNorm ( const szs_norm_t *norm ) if ( !norm || !norm->f ) return; - + } /////////////////////////////////////////////////////////////////////////////// @@ -1907,6 +2290,9 @@ static enumError cmd_analyze() PrintScript_t ps; SetupPrintScriptByOptions(&ps); + patch_action_log_disabled++; + CheckTextureRefSZS(&szs,0); + ParamList_t *param; for ( param = first_param; param; param = param->next ) { @@ -1939,6 +2325,7 @@ static enumError cmd_analyze() //--- analyse szs + const u_usec_t start_usec = GetTimerUSec(); AnalyseSZS(&as,false,&szs,param->arg); @@ -1975,12 +2362,42 @@ static enumError cmd_analyze() name_attrib++; ccp end = strrchr(name_attrib,']'); if (end) + { name_attrib_len = end - name_attrib; + for ( ccp ptr = name_attrib; ptr < end; ) + { + ccp sep = strchr(ptr,','); + if (!sep) + sep = end; + switch ( sep-ptr ) + { + case 4: + if (!memcmp(ptr,"edit",4)) szs.have.attrib |= 1 << HAVEATT_EDIT; + break; + + case 5: + if (!memcmp(ptr,"cheat",5)) szs.have.attrib |= 1 << HAVEATT_CHEAT; + break; + + case 7: + if (!memcmp(ptr,"reverse",7)) szs.have.attrib |= 1 << HAVEATT_REVERSE; + break; + } + ptr = sep + 1; + } + } } else name_attrib = EmptyString; + ccp texture_info = 0; + PrepareCheckTextureSZS(&szs); + CheckTextureRefSZS(&szs,&texture_info); + + const u_usec_t duration_usec = GetTimerUSec() - start_usec; + + //--- print result PrintScriptVars(&ps,1, @@ -1995,6 +2412,10 @@ static enumError cmd_analyze() "sha1_course=\"%s\"\n" "sha1_vrcorn=\"%s\"\n" "sha1_minimap=\"%s\"\n" + "sha1_kcl_slot=%u\n" + "sha1_kmp_slot=%u\n" + "sha1_kmp_norm_slot=%u\n" + "sha1_minimap_slot=%u\n" "valid_track=%u\n" "is_arena=\"%u %s\"\n" "n_ckpt0=%d\n" @@ -2015,13 +2436,14 @@ static enumError cmd_analyze() "special_files=\"%s\"\n" "original_files=\"%s\"\n" "modified_files=\"%s\"\n" + "special_attrib=\"%s\"\n" "special_kmp=\"%s\"\n" "lex_sections=\"%s\"\n" "lex_features=\"%s\"\n" "warn=\"%u=%s\"\n" "ct_attributes=\"%s\"\n" "name_attributes=\"%.*s\"\n" - "duration_usec=%llu\n" + ,dest ,szs.size ,as.db64 @@ -2033,6 +2455,10 @@ static enumError cmd_analyze() ,as.sha1_course ,as.sha1_vrcorn ,as.sha1_minimap + ,as.sha1_kcl_slot + ,as.sha1_kmp_slot + ,as.sha1_kmp_norm_slot + ,as.sha1_minimap_slot ,as.valid_track ,szs.is_arena ,is_arena_name[szs.is_arena] @@ -2066,15 +2492,18 @@ static enumError cmd_analyze() ,CreateSpecialFileInfo(&szs,~(1<<HFM_NONE),true,"") ,CreateSpecialFileInfo(&szs,1<<HFM_ORIGINAL,true,"") ,CreateSpecialFileInfo(&szs,1<<HFM_MODIFIED,true,"") + ,CreateSpecialInfoAttrib(szs.have.attrib,true,"") ,CreateSpecialInfoKMP(szs.have.kmp,true,"") ,CreateSectionInfoLEX(szs.have.lex_sect,true,"") ,CreateFeatureInfoLEX(szs.have.lex_feat,true,"") ,szs.warn_bits,GetWarnSZSNames(szs.warn_bits,' ') ,as.ct_attrib+1 ,name_attrib_len,name_attrib - ,as.duration_usec ); + if (texture_info) + PrintScriptVars(&ps,0,"texture_hack=\"%s\"\n",texture_info); + if ( long_count > 0 ) { const uint n = szs.special_file ? szs.special_file->used : 0; @@ -2091,6 +2520,7 @@ static enumError cmd_analyze() } } + PrintScriptVars(&ps,0,"duration_usec=%llu\n",duration_usec); PutScriptVars(&ps,2,0); if (!script_array) @@ -2111,6 +2541,74 @@ static enumError cmd_analyze() // /////////////////////////////////////////////////////////////////////////////// +/////////////// command is-texture /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static enumError cmd_is_texture() +{ + disable_checks++; + + int max_err = 0; + szs_file_t szs; + InitializeSZS(&szs); + patch_action_log_disabled++; + + uint max_fw = 0; + struct { FastBuf_t b; char space[500]; } fbuf; + if (long_count) + InitializeFastBuf(&fbuf,sizeof(fbuf)); + + for ( ParamList_t *param = first_param; param; param = param->next ) + { + NORMALIZE_FILENAME_PARAM(param); + + ResetSZS(&szs); + enumError err = LoadCreateSZS(&szs,param->arg,true,opt_ignore>0,true); + if ( err > ERR_WARNING ) + { + if (long_count) + { + AppendFastBuf(&fbuf.b,"-1=err",7); + if ( max_fw < 7 ) + max_fw = 7; + } + if ( max_err < err ) + max_err = err; + continue; + } + + ccp texture_info = 0; + PrepareCheckTextureSZS(&szs); + CheckTextureRefSZS(&szs,&texture_info); + + if (long_count) + { + ccp x = texture_info ? texture_info : "-1"; + const int len = strlen(x); + AppendFastBuf(&fbuf.b,x,len+1); + if ( max_fw < len ) + max_fw = len; + } + else + printf("%s\n", texture_info ? texture_info : "-1" ); + } + + if (long_count) + { + ccp par = fbuf.b.buf; + for ( ParamList_t *param = first_param; param; param = param->next ) + { + printf("%-*s : %s\n",max_fw,par,param->arg); + par += strlen(par) + 1; + } + ResetFastBuf(&fbuf.b); + } + + return max_err; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// command features /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -5089,6 +5587,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_QUIET: verbose = verbose > -1 ? -1 : verbose - 1; break; case GO_VERBOSE: verbose = verbose < 0 ? 0 : verbose + 1; break; case GO_LOGGING: logging++; break; + case GO_WARN: err += ScanOptWarn(optarg); break; case GO_DE: use_de = true; break; case GO_CT_CODE: ctcode_enabled = true; break; case GO_LE_CODE: lecode_enabled = true; break; @@ -5185,6 +5684,7 @@ static enumError CheckOptions ( int argc, char ** argv, bool is_env ) case GO_ESC: err += ScanEscapeChar(optarg) < 0; break; case GO_SOURCE: SetSource(optarg); break; + case GO_REFERENCE: SetReference(optarg); break; case GO_DEST: SetDest(optarg,false); break; case GO_DEST2: SetDest(optarg,true); break; case GO_OVERWRITE: opt_overwrite = true; break; @@ -5383,14 +5883,12 @@ static enumError CheckCommand ( int argc, char ** argv ) switch ((enumCommands)cmd_ct->id) { case CMD_VERSION: version_exit(); - case CMD_HELP: PrintHelp(&InfoUI_wszst,stdout,0,"HELP",0,URI_HOME, - first_param ? first_param->arg : 0 ); break; + case CMD_HELP: PrintHelpColor(&InfoUI_wszst); break; case CMD_CONFIG: err = cmd_config(); break; case CMD_INSTALL: err = cmd_install(); break; case CMD_ARGTEST: err = cmd_argtest(argc,argv); break; case CMD_TEST: err = cmd_test(); break; - case CMD_COLORS: err = Command_COLORS(brief_count?-brief_count:long_count,0,0); - break; + case CMD_COLORS: err = Command_COLORS(brief_count?-brief_count:long_count,0,0); break; case CMD_ERROR: err = cmd_error(); break; case CMD_FILETYPE: err = cmd_filetype(); break; case CMD_FILEATTRIB: err = cmd_fileattrib(); break; @@ -5408,6 +5906,7 @@ static enumError CheckCommand ( int argc, char ** argv ) case CMD_TRACKS: err = cmd_tracks(); break; case CMD_SCANCACHE: err = cmd_scancache(); break; case CMD_EXPORT: err = cmd_export(); break; + case CMD_SIZEOF: err = cmd_sizeof(); break; case CMD_CODE: err = cmd_code(); break; case CMD_RECODE: err = cmd_recode(); break; case CMD_SUBFILE: err = cmd_subfile(); break; @@ -5433,6 +5932,7 @@ static enumError CheckCommand ( int argc, char ** argv ) case CMD_MEMORY_A: set_all(1); err = cmd_memory(); break; case CMD_SHA1: err = cmd_sha1(); break; case CMD_ANALYZE: err = cmd_analyze(); break; + case CMD_IS_TEXTURE: err = cmd_is_texture(); break; case CMD_FEATURES: err = cmd_features(); break; case CMD_DISTRIBUTION: err = cmd_distribution(); break; case CMD_DIFF: err = cmd_diff(); break; diff --git a/project/src/wtest.c b/project/src/wtest.c index bf4a6a3..2283dd8 100644 --- a/project/src/wtest.c +++ b/project/src/wtest.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * @@ -41,10 +41,13 @@ #include <dirent.h> #include <stddef.h> #include <time.h> +#include <locale.h> //#include <sys/stat.h> //#include <fcntl.h> +#include "dclib-utf8.h" #include "dclib-debug.h" + #include "version.h" #include "lib-std.h" #include "lib-image.h" @@ -3886,7 +3889,7 @@ static enumError test_eml ( int argc, char ** argv ) exmem_t data = ExMemByString(eq?eq:arg); if ( *arg == '-' ) - RemoveEML(&eml,arg+1); + RemoveByKeyEML(&eml,arg+1); else if ( *arg == '+' ) ReplaceEML(&eml,arg+1,CPM_COPY,&data,CPM_COPY); else if ( *arg == '%' ) @@ -3922,8 +3925,7 @@ static enumError test_eml ( int argc, char ** argv ) static enumError test_cygpath ( int argc, char ** argv ) { - int i; - for ( i = 1; i < argc; i++ ) + for ( int i = 1; i < argc; i++ ) { ccp arg = argv[i]; bool try_circ = *arg != '-'; @@ -3950,6 +3952,104 @@ static enumError test_cygpath ( int argc, char ** argv ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// test_utf8() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static enumError test_utf8 ( int argc, char ** argv ) +{ + setlocale(LC_ALL,"C.utf8"); + printf("|%6s|\n|%6ls|\n","abc",L"äöü"); + + static ccp text[] = { "aousA", "äöüßÄ", "├─┼─┤","12345", 0 }; + for ( ccp *ptr = text; *ptr; ptr++ ) + { + mem_t src = MemByString(*ptr); + mem_t mid = MidMem8(src,1,2); + mem_t left = LeftMem8(src,-3); + mem_t right = RightMem8(src,-3); + + printf(" | %.*s | %.*s | %.*s | ~~ |%s|%s|%s|%s|\n", + mid.len, mid.ptr, + left.len, left.ptr, + right.len, right.ptr, + AlignUTF8ToCircBuf(*ptr,10,-1), + AlignUTF8ToCircBuf(*ptr,-10,-1), + AlignUTF8ToCircBuf(*ptr,-10,2), + *ptr ); + } + return 0; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// test_nice() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static enumError test_nice ( int argc, char ** argv ) +{ + putchar('\n'); + for ( int i = 1; i < argc; i++ ) + { + ccp arg = argv[i], end; + int nice4, nice5, nice6; + + if (!strcmp(arg,"-")) + { + putchar('\n'); + continue; + } + + end = ScanNiceID4(&nice4,arg); + if ( !*end && nice4 >= 0 ) + printf("%20s => %8d : %s\n",arg,nice4,PrintNiceID4(nice4)); + + end = ScanNiceID5(&nice5,arg); + if ( !*end && nice5 >= 0 ) + printf("%20s => %8d : %s\n",arg,nice5,PrintNiceID5(nice5)); + + end = ScanNiceID6(&nice6,arg); + if ( !*end && nice6 >= 0 ) + printf("%20s => %8d : %s\n",arg,nice6,PrintNiceID6(nice6)); + + uint num = str2ul(arg,0,10); + if ( num > 0 || *arg == '0' ) + printf("%20s => %8d : %s %s %s\n", + arg, num, + PrintNiceID4(num), + PrintNiceID5(num), + PrintNiceID6(num)); + } + putchar('\n'); + return 0; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// test_arg_manager() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static enumError test_arg_manager ( int argc, char ** argv ) +{ + putchar('\n'); + for ( int i = 1; i < argc; i++ ) + { + ccp arg = argv[i]; + printf("\n|%s|\n",arg); + ArgManager_t am = {0}; + ScanSimpleArgManager(&am,arg); + AppendArgManager(&am,"----------",0,false); + ScanQuotedArgManager(&am,arg,true); + + for ( int i = 0; i < am.argc; i++ ) + printf(" [%02u] |%s|\n",i,am.argv[i]); + ResetArgManager(&am); + } + putchar('\n'); + return 0; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// develop() /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -3973,6 +4073,7 @@ const gobj_cond_ref_t * FindConditionRef2 ( u16 ref_id ) } /////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// static enumError develop ( int argc, char ** argv ) { @@ -4225,6 +4326,9 @@ enum CMD_QUOTE, // test_quote(argc,argv) CMD_EML, // test_eml(argc,argv) CMD_CYGPATH, // test_cygpath(argc,argv) + CMD_UTF8, // test_utf8(argc,argv) + CMD_NICE, // test_nice(argc,argv) + CMD_ARG_MANAGER, // test_arg_manager(argc,argv) #ifdef HAVE_WIIMM_EXT CMD_WIIMM, // test_wiimm(argc,argv) @@ -4294,6 +4398,9 @@ static const KeywordTab_t CommandTab[] = { CMD_QUOTE, "QUOTE", "Q", 0 }, { CMD_EML, "EML", 0, 0 }, { CMD_CYGPATH, "CYGPATH", 0, 0 }, + { CMD_UTF8, "UTF8", 0, 0 }, + { CMD_NICE, "NICE", 0, 0 }, + { CMD_ARG_MANAGER, "ARG-MANAGER", "AM", 0 }, #ifdef HAVE_WIIMM_EXT { CMD_WIIMM, "WIIMM", "W", 0 }, @@ -4313,6 +4420,8 @@ static const KeywordTab_t CommandTab[] = void help_exit() { + SetupPager(); + printf("\nCommands:\n\n"); const KeywordTab_t * cmd; for ( cmd = CommandTab; cmd->name1; cmd++ ) @@ -4324,6 +4433,8 @@ void help_exit() #ifdef HAVE_WIIMM_EXT wiimm_help_exit(false); #endif + + ClosePager(); exit(ERR_SYNTAX); }; @@ -4348,8 +4459,7 @@ int main ( int argc, char ** argv ) print_title_func = print_title; SetupLib(argc,argv,NAME,VERSION,TITLE); - if (1) - printf("ADDRT_*: mem-beg:%x, mem-end:%x, mir-beg:%x, mir-end:%x, N:%x,%x\n", + PRINT0("ADDRT_*: mem-beg:%x, mem-end:%x, mir-beg:%x, mir-end:%x, N:%x,%x\n", ADDRT_MEMORY_BEGIN, ADDRT_MEMORY_END, ADDRT_MIRROR_BEGIN, ADDRT_MIRROR_END, ADDRT__N, ADDRT__NN ); @@ -4451,6 +4561,9 @@ int main ( int argc, char ** argv ) case CMD_QUOTE: test_quote(argc,argv); break; case CMD_EML: test_eml(argc,argv); break; case CMD_CYGPATH: test_cygpath(argc,argv); break; + case CMD_UTF8: test_utf8(argc,argv); break; + case CMD_NICE: test_nice(argc,argv); break; + case CMD_ARG_MANAGER: test_arg_manager(argc,argv); break; #ifdef HAVE_WIIMM_EXT case CMD_WIIMM: test_wiimm(argc,argv); break; diff --git a/project/templates/HISTORY-v1.txt b/project/templates/HISTORY-v1.txt index bd7db5c..b694c00 100644 --- a/project/templates/HISTORY-v1.txt +++ b/project/templates/HISTORY-v1.txt @@ -1003,7 +1003,7 @@ szs v1.54a r7393 - 2017-08-14 - Support for RKC (competition) files added: RKC files are handled like other archives. Tool wszst is able to detect, list, extract or create a RKC file, also recursive. Direct creation and - optimation of the included SZS is not implemented yet. + optimization of the included SZS is not implemented yet. - New keyword for option --kmp: MAX-LAPS: Keyword MAX-LAPS has only impact, if one of 1LAP,...,9LAPS is set too. Then, the number of laps is only decreased to the specified number, but never increased. diff --git a/project/templates/HISTORY.txt b/project/templates/HISTORY.txt index b18c2a5..a938816 100644 --- a/project/templates/HISTORY.txt +++ b/project/templates/HISTORY.txt @@ -507,6 +507,25 @@ szs v2.25a r8443 - 2021-04-24 - Support of LE-CODE build 29. +szs v2.26a r8462 - 2021-05-08 + + - wstrt PORT & wstrt WHERE: + - Address scanning: If an address starts with letter 'm' or 'M' (main.dol) + or 's' or 'S' (staticr.rel), then it is interpreted as file offset. + If an address without prefix is exact 6 characters long, then value + 0x80000000 is added. This makes cut+paste from cheat codes easier. + - New option: --no-0x (short: -0): Suppress 0x prefix for hex numbers. + - New option: --long (short: -l): Print file offsets too. + - wstrt PORT: + - Bug fix: Wrong column was highlighted when region order was changed by + option --order. + - Internal porting database updated. + - New option: --port-db=file: Load the specified update file and replace + the internal porting database. + - wstrt DUMP: More details for StaticR.rel files. + - New command: wszst INSTALL: Install files to the shared directory. + + @@MODULE(last-history.txt)@@ diff --git a/project/templates/module/last-history.txt b/project/templates/module/last-history.txt index 37ef9fc..c984d02 100644 --- a/project/templates/module/last-history.txt +++ b/project/templates/module/last-history.txt @@ -1,20 +1,24 @@ szs v@@VERSION@@ r@@REV-NEXT@@ - @@@@-@@-@@ - - wstrt PORT & wstrt WHERE: - - Address scanning: If an address starts with letter 'm' or 'M' (main.dol) - or 's' or 'S' (staticr.rel), then it is interpreted as file offset. - If an address without prefix is exact 6 characters long, then value - 0x80000000 is added. This makes cut+paste from cheat codes easier. - - New option: --no-0x (short: -0): Suppress 0x prefix for hex numbers. - - New option: --long (short: -l): Print file offsets too. - - wstrt PORT: - - Bug fix: Wrong column was highlighted when region order was changed by - option --order. - - Internal porting database updated. - - New option: --port-db=file: Load the specified update file and replace - the internal porting database. - - wstrt DUMP: More details for StaticR.rel files. - - New command: wszst INSTALL: Install files to the shared directory. + - New parameter for LEX section SET1: START-ITEM: Declare that a player can + get an item through an item box before race start. + - wszst ANALYSE: LEX:SET1:START-ITEM is recognized and evaluated. + - wstrt PORT+WHERE: Use new option --upper (-U) to force upper case digits in + hex numbers. + - wstrt PORT: Ported cheat codes are always printed with upper case digits + and without 0x prefix. + - wstrt PORT: Porting database updated. Many false records removed by + updated generator script. + - Fewer program crashes when reading faulty SZS files. + - New section [SETUP-ARENA] for LE-CODE definition files: Define music and + property slots for battle arenas. + - New global option: --warn=LIST (short -W LIST): Enable or disable warnings. + - New command: wkclt SHA1: Print a SHA1 checksum of the KCL for each source. + The checksum is calculated after patching. + - New command: wkclt TYPES: Scan KCL types from command line in different + variants and print the result as flag, type, value and groups W, X, Y & Z. + - New command: wszst IS-TEXTURE: Test tracks to see if it's a texture hack. + - wszst ANALYZE: Detect goombas with scale other than 1.00. ~ - MDL support: Scanning a MDL file and transferring the data into an internal ~ format was already implemented, but only used for analysis purposes. Now it diff --git a/project/text-files/kmp.inc/kmp-enpt-ropt-cr.inc b/project/text-files/kmp.inc/kmp-enpt-ropt-cr.inc index 367eee0..2900da1 100644 --- a/project/text-files/kmp.inc/kmp-enpt-ropt-cr.inc +++ b/project/text-files/kmp.inc/kmp-enpt-ropt-cr.inc @@ -3,34 +3,36 @@ @SHOW-OPTIONS = %d # >0: force printing of all route options # AUTO-CONNECT is one of the following AC$* symbols: -# For racing tracks and for battle areenas with manual links setup: -# AC$OFF -# Do not any auto connection. Route connection are fully under control -# of the user. -# AC$PREV +# For racing tracks and for battle arenas with manual links setup: +# AC$OFF +# Do not add any auto connection. Route connection are fully under +# control of the user. +# AC$PREV # Setup PREV links by NEXT links of other routes. Existing PREV links -# are cleared before. This is the default and the behavior of all versions -# before v1.60a. +# are cleared before. This is the default and the behavior of all +# versions before v1.60a. # -# Modes for automatic route connection in battle arenas: -# AC$DISPATCH +# Modes for automatic route connection in battle arenas: +# AC$DISPATCH # Find dispatch points and create links automatically if not already # set manually. This is the default for enemy routes, if dispatch # points detected. # -# Flags: The modes of above can be combined with the following options by -# the OR operator '|' (example: AC$PREV | ACF$FIX) +# Flags: The modes of above can be combined with the following options by +# the OR operator '|' (example: AC$PREV | ACF$FIX) # ACF$FIX_PREV -# Add self-links, if a PREV list is empty. +# Add a self-link, if a PREV list is empty. # ACF$FIX_NEXT -# Add self-links, if a NEXT list is empty. +# Add a self-link, if a NEXT list is empty. # ACF$FIX # Abbreviation for: ACF$FIX_PREV | ACF$FIX_NEXT # This is the default for item routes to avoid a freeze. +# ACF$PR_PREV +# Print "$PREV : ..." always. # -@AUTO-CONNECT = %s%s +@AUTO-CONNECT = %s%s%s -# Syntax of new command with impact to all following $GROUP commands: +# Syntax of a new command with impact to all following $GROUP commands: # "$DEF-CLASS" [":"] class_name # Syntax of new route commands (placed behind $GROUP command): diff --git a/project/text-files/kmp.inc/kmp-itpt-ropt-cr.inc b/project/text-files/kmp.inc/kmp-itpt-ropt-cr.inc index 87659bd..7fe2065 100644 --- a/project/text-files/kmp.inc/kmp-itpt-ropt-cr.inc +++ b/project/text-files/kmp.inc/kmp-itpt-ropt-cr.inc @@ -1,4 +1,4 @@ # Route options. See section [ENPT] for details. @SHOW-OPTIONS = %d # >0: force printing of all route options -@AUTO-CONNECT = %s%s +@AUTO-CONNECT = %s%s%s diff --git a/project/text-files/lex.inc/lex-elem-set1-cr.inc b/project/text-files/lex.inc/lex-elem-set1-cr.inc index 487f5b5..4700bc8 100644 --- a/project/text-files/lex.inc/lex-elem-set1-cr.inc +++ b/project/text-files/lex.inc/lex-elem-set1-cr.inc @@ -13,8 +13,15 @@ #------------------------- # Online, item positions are only transmitted correctly, if the positions of -# all 3 axis are between -131071 and +131071. The following vector defines 3 -# factors to increase the range at the expense of accuracy. Factors <1.0 are -# ignored and set to 1.0. +# all 3 axis are between -131072 and +131071. The following vector defines 3 +# stretch factors to increase the range at the expense of accuracy. Factors +# <1.0 are ignored and set to 1.0. @ITEM-POS-FACTOR = v( %5.3f, %5.3f, %5.3f ) + +# Wiimmfi and tool mkw-ana support an automatic ban systems, that detect items +# before race start. Unfortunately, there are some tracks where players get +# an item through an item box before race start. And it is precisely these +# tracks that must be marked with value 1 as an exception to avoid banning. + +@START-ITEM = %u diff --git a/project/text-files/lex.inc/lex-elem-set1-develop-cr.inc b/project/text-files/lex.inc/lex-elem-set1-develop-cr.inc index 9950fb2..b639c61 100644 --- a/project/text-files/lex.inc/lex-elem-set1-develop-cr.inc +++ b/project/text-files/lex.inc/lex-elem-set1-develop-cr.inc @@ -5,7 +5,6 @@ # values can still change. Therefore, they should not be used, or at most # experimentally. -@TEST1 = %d -@TEST2 = %d -@TEST3 = %d -@TEST4 = %d +@TEST_0D = %d +@TEST_0E = %d +@TEST_0F = %d diff --git a/project/text-files/lpar.inc/lpar-sect-debug-docu-cr.inc b/project/text-files/lpar.inc/lpar-sect-debug-docu-cr.inc index a454674..44b1b46 100644 --- a/project/text-files/lpar.inc/lpar-sect-debug-docu-cr.inc +++ b/project/text-files/lpar.inc/lpar-sect-debug-docu-cr.inc @@ -72,6 +72,14 @@ # If enabled then print the respawn index defined by the current check point. # This information may help to test all respawn points of a track. +# ITEM-POINT = 0|1 +# Output: I=i +# If enabled print the current item point index of the player. + +# KCL-TYPE = 0|1 +# Output: K=t,v +# If enabled print current KCL type (t=00-1F) and KCL variant (v=000-7FF). + # LAP-POS = 0|1 # Output: L=lap # Print the current lap position as floating point value with 3 digits. The diff --git a/project/text-files/ui-head.inc b/project/text-files/ui-head.inc index 69e5800..4703b50 100644 --- a/project/text-files/ui-head.inc +++ b/project/text-files/ui-head.inc @@ -16,7 +16,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> * + * Copyright (c) 2011-2022 by Dirk Clemens <wiimm@wiimm.de> * * * *************************************************************************** * * |
