aboutsummaryrefslogtreecommitdiff
path: root/project/src/wstrt.c
diff options
context:
space:
mode:
authorroot <root@dc13.lemmi>2020-07-21 10:00:46 +0200
committerroot <root@dc13.lemmi>2020-07-21 10:00:46 +0200
commit1192c4575ea7afdf38e3fa0df4587a08620af11e (patch)
tree6910a62487c282d0840d2e668aa7eb40b7c8a3fd /project/src/wstrt.c
parent76de8a89f7c1d1b4522eb66e8f89d248e8c1781f (diff)
SZS v2.18a
Diffstat (limited to '')
-rw-r--r--project/src/wstrt.c1485
1 files changed, 1485 insertions, 0 deletions
diff --git a/project/src/wstrt.c b/project/src/wstrt.c
new file mode 100644
index 0000000..9ae3e33
--- /dev/null
+++ b/project/src/wstrt.c
@@ -0,0 +1,1485 @@
+
+/***************************************************************************
+ * _______ _______ _______ *
+ * | ___ |____ | ___ | *
+ * | | |_| / /| | |_| *
+ * | |_____ / / | |_____ *
+ * |_____ | / / |_____ | *
+ * _ | | / / _ | | *
+ * | |___| |/ /____| |___| | *
+ * |_______|_______|_______| *
+ * *
+ * Wiimms SZS Tools *
+ * https://szs.wiimm.de/ *
+ * *
+ ***************************************************************************
+ * *
+ * This file is part of the SZS project. *
+ * Visit https://szs.wiimm.de/ for project details and sources. *
+ * *
+ * Copyright (c) 2011-2020 by Dirk Clemens <wiimm@wiimm.de> *
+ * *
+ ***************************************************************************
+ * *
+ * This program 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, *
+ * 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. *
+ * *
+ * See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt *
+ * *
+ ***************************************************************************/
+
+#include "lib-staticr.h"
+#include "db-mkw.h"
+#include "lib-mkw.h"
+#include "dclib-utf8.h"
+#include "dclib-xdump.h"
+#include "ui.h" // [[dclib]] wrapper
+#include "ui-wstrt.c"
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// functions not neded by wstrt ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#if !SZS_WRAPPER
+ bool DefineIntVar ( VarMap_t * vm, ccp varname, int value ) { return false; }
+#endif
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// definitions ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#define TITLE WSTRT_SHORT ": " WSTRT_LONG " v" VERSION " r" REVISION \
+ " " SYSTEM " - " AUTHOR " - " DATE
+
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static void help_exit ( bool xmode )
+{
+ fputs( TITLE "\n", stdout );
+
+ if (xmode)
+ {
+ int cmd;
+ for ( cmd = 0; cmd < CMD__N; cmd++ )
+ PrintHelpCmd(&InfoUI_wstrt,stdout,0,cmd,0,0,URI_HOME);
+ }
+ else
+ PrintHelpCmd(&InfoUI_wstrt,stdout,0,0,"HELP",0,URI_HOME);
+
+ exit(ERR_OK);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void print_version_section ( bool print_sect_header )
+{
+ if (print_sect_header)
+ fputs("[version]\n",stdout);
+
+ const u32 base = 0x04030201;
+ const u8 * e = (u8*)&base;
+ const u32 endian = be32(e);
+
+ printf( "prog=" WSTRT_SHORT "\n"
+ "name=" WSTRT_LONG "\n"
+ "version=" VERSION "\n"
+ "beta=%d\n"
+ "revision=" REVISION "\n"
+ "system=" SYSTEM "\n"
+ "endian=%u%u%u%u %s\n"
+ "author=" AUTHOR "\n"
+ "date=" DATE "\n"
+ "url=" URI_HOME WSTRT_SHORT "\n"
+ "\n"
+ , BETA_VERSION
+ , e[0], e[1], e[2], e[3]
+ , endian == 0x01020304 ? "little"
+ : endian == 0x04030201 ? "big" : "mixed" );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void version_exit()
+{
+ if ( brief_count > 1 )
+ fputs( VERSION "\n", stdout );
+ else if (brief_count)
+ fputs( VERSION " r" REVISION " " SYSTEM "\n", stdout );
+ else if (print_sections)
+ print_version_section(true);
+ else if (long_count)
+ print_version_section(false);
+ else
+ fputs( TITLE "\n", stdout );
+
+ exit(ERR_OK);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void print_title ( FILE * f )
+{
+ static bool done = false;
+ if (!done)
+ {
+ done = true;
+ if (print_sections)
+ print_version_section(true);
+ else if ( verbose >= 1 && f == stdout )
+ fprintf(f,"\n%s\n\n",TITLE);
+ else
+ fprintf(f,"***** %s *****\n",TITLE);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static const KeywordTab_t * current_command = 0;
+
+static void hint_exit ( enumError stat )
+{
+ if ( current_command )
+ fprintf(stderr,
+ "-> Type '%s help %s' (pipe it to a pager like 'less') for more help.\n\n",
+ progname, CommandInfo[current_command->id].name1 );
+ else
+ fprintf(stderr,
+ "-> Type '%s -h' or '%s help' (pipe it to a pager like 'less') for more help.\n\n",
+ progname, progname );
+ exit(stat);
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// helpers ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static int ScanOptU64 ( u64 *num, ccp name, ccp arg )
+{
+ DASSERT(num);
+ DASSERT(name);
+
+ return ERR_OK != ScanSizeOptU64(
+ num, // u64 * num
+ arg, // ccp source
+ 1, // default_factor1
+ 0, // int force_base
+ name, // ccp opt_name
+ 0, // u64 min
+ M1(*num), // u64 max
+ 1, // u32 multiple
+ 0, // u32 pow2
+ true // bool print_err
+ );
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command test ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static void print_vsbt ( enum VsBtMode mode, ccp str, ccp std_str )
+{
+ switch (mode)
+ {
+ case VSBT_OFF:
+ break;
+
+ case VSBT_PATCH:
+ printf("%4s%-18c0x%02x 0x%02x = %c%c\n",
+ std_str, ':', str[0], str[1], str[0], str[1] );
+ break;
+
+ case VSBT_TEST:
+ printf("%4s%-23cTEST = %c1 %c2 %c3 %c4\n",
+ std_str, ':',
+ std_str[0], std_str[0], std_str[0], std_str[0] );
+ break;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_test_options()
+{
+ printf("\nOptions (compatibility: %s; format: hex=dec):\n",PrintOptCompatible());
+
+ printf(" test: %16x = %12d\n",testmode,testmode);
+ printf(" verbose: %16x = %12d\n",verbose,verbose);
+ printf(" width: %16x = %12d\n",opt_width,opt_width);
+ printf(" escape-char: %16x = %12d\n",escape_char,escape_char);
+ printf(" all-ranks: %16x = %12d\n",opt_all_ranks,opt_all_ranks);
+
+ printf(" vs-region: %16x = %12d [%c%c]\n",
+ opt_str_vs_region, opt_str_vs_region,
+ opt_str_xvs_region ? 'x' : '-',
+ opt_str_tvs_region ? 't' : '-' );
+ printf(" bt-region: %16x = %12d [%c%c]\n",
+ opt_str_bt_region, opt_str_bt_region,
+ opt_str_xbt_region ? 'x' : '-',
+ opt_str_tbt_region ? 't' : '-' );
+
+ if (opt_tracks)
+ DumpTrackList(0,0,0);
+ if (opt_arenas)
+ DumpArenaList(0,0,0);
+
+ if (opt_https)
+ {
+ printf(" https: %16x = '%s'\n",
+ opt_https, GetHttpsName(opt_https,"?") );
+ printf(" domain:%14s%s\n","",mkw_domain);
+ }
+
+ print_vsbt(patch_vs_mode,patch_vs_str,"vs");
+ print_vsbt(patch_bt_mode,patch_bt_str,"bt");
+
+ if (opt_move_d8)
+ printf(" move-d8: true\n");
+
+ if (n_section_list)
+ {
+ printf(" create %u sections:\n",n_section_list);
+ uint s;
+ for ( s = 0; s < n_section_list; s++ )
+ {
+ const dol_sect_select_t *sl = section_list + s;
+ printf("\t%s: %#10x %c : %s\n",
+ sl->name, sl->addr, sl->use_param ? 'P' : '-', sl->fname );
+ }
+ }
+
+ return ERR_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_test()
+{
+ #if 1 || !defined(TEST) // test options
+
+ return cmd_test_options();
+
+ #elif 0
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ //NORMALIZE_FILENAME_PARAM(param);
+ }
+ return ERR_OK;
+
+ #endif
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command dump ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_dump ( bool use_c )
+{
+ enumError max_err = ERR_OK;
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+ staticr_t str;
+ enumError err = LoadSTR(&str,true,param->arg,opt_ignore>0);
+
+ if ( err <= ERR_WARNING && err != ERR_NOT_EXISTS )
+ {
+ if ( verbose >= 0 )
+ printf("\n%sDUMP of %s:%s\n", use_c ? "C-" : "",
+ GetNameFF(str.fform,0), param->arg );
+ DumpSTR(stdout,2,&str,use_c);
+ }
+
+ if ( max_err < err )
+ max_err = err;
+ ResetSTR(&str);
+ }
+
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command hexdump ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static XDump_t xparam;
+static MemMap_t vaddr = {0};
+static MemMap_t faddr = {0};
+static uint dol_sections = 0;
+
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_hexdump()
+{
+ //--- list addresses of option --vaddr and --faddr
+
+ if ( logging > 1 )
+ {
+ if (dol_sections)
+ fprintf(stdlog,"\nSections: %s\n",
+ DolSectionList2Text(dol_sections));
+
+ if (vaddr.used)
+ {
+ fputs("\nList of virtual addresses (option --vaddr):\n\n",stdlog);
+ PrintMemMap(&vaddr,stdlog,5,0);
+ }
+
+ if (faddr.used)
+ {
+ fputs("\nList of file addresses (option --faddr):\n\n",stdlog);
+ PrintMemMap(&faddr,stdlog,5,0);
+ }
+ }
+
+ SetupXDump(&xparam,XDUMPC_DUMP);
+
+ enumError max_err = ERR_OK;
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+ staticr_t str;
+ enumError err = LoadSTR(&str,true,param->arg,opt_ignore>0);
+
+ bool is_ok = err <= ERR_WARNING && err != ERR_NOT_EXISTS;
+ if ( is_ok && !str.is_dol )
+ {
+ is_ok = false;
+ err = ERROR0(ERR_WRONG_FILE_TYPE,
+ "DOL expected, file ignored: %s\n",param->arg);
+ }
+
+ if (is_ok)
+ {
+ const dol_header_t *dol = (dol_header_t*)str.data;
+
+ MemMap_t mm;
+ InitializeMemMap(&mm);
+ if ( vaddr.used || faddr.used || dol_sections )
+ {
+ CopyMemMap(&mm,&vaddr,true);
+ TranslateDolOffsets(dol,&mm,true,&faddr);
+ TranslateDolSections(dol,&mm,true,dol_sections);
+ }
+ else
+ TranslateAllDolOffsets(dol,&mm,true);
+
+ if ( logging > 1 )
+ {
+ fputs("\nList of virtual addresses to dump:\n\n",stdlog);
+ PrintMemMap(&mm,stdlog,5,0);
+ }
+
+ if ( verbose >= 0 )
+ printf("\nHEXDUMP of %s:%s\n",
+ GetNameFF(str.fform,0), param->arg );
+
+ uint mi;
+ for ( mi = 0; mi < mm.used; mi++ )
+ {
+ const MemMapItem_t *src = mm.field[mi];
+ uint addr = src->off;
+ uint size = src->size;
+ while ( size > 0 )
+ {
+ u32 valid_size;
+ uint off = GetDolOffsetByAddr(dol,addr,size,&valid_size);
+ if ( !off || !valid_size )
+ break;
+ xparam.start_addr = addr;
+ XDump(&xparam,str.data+off,valid_size,true);
+ addr += valid_size;
+ size -= valid_size;
+ }
+ }
+ ResetMemMap(&mm);
+ }
+
+ if ( max_err < err )
+ max_err = err;
+ ResetSTR(&str);
+ }
+
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command https ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static int compare_server_patch
+ ( const str_server_patch_t * a, const str_server_patch_t * b )
+{
+ int stat = (int)a->mode - (int)b->mode;
+ if (!stat)
+ {
+ stat = (int)a->flags - (int)b->flags;
+ if (!stat)
+ {
+ stat = (int)a->serv_type - (int)b->serv_type;
+ if (!stat)
+ stat = (int)a->offset - (int)b->offset;
+ }
+ }
+ return stat;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_https()
+{
+ #if HAVE_ASSERT
+ {
+ const str_server_list_t *sl;
+ for ( sl = ServerList; sl->name; sl++ )
+ ASSERT_MSG( sl->domain_len == strlen(sl->domain),
+ "ServerList[%i], len = %zu\n",
+ (int)(sl-ServerList), strlen(sl->domain) );
+ }
+ #endif
+
+ enumError max_err = ERR_OK;
+
+ enum { LIST_SIZE = 1000 };
+ str_server_patch_t patch_list[LIST_SIZE];
+ memset(patch_list,0,sizeof(patch_list));
+ uint n_list = 0;
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+ staticr_t str;
+ enumError err = LoadSTR(&str,true,param->arg,opt_ignore>0);
+ if ( max_err < err )
+ max_err = err;
+
+ if ( err <= ERR_WARNING && err != ERR_NOT_EXISTS )
+ {
+ AnalyzeSTR(&str);
+ //printf("ST=%x,%x\n",str.str_status,str.dol_status);
+ if ( !( str.is_dol ? str.dol_status & DOL_S_ORIG : str.str_status & STR_S_ORIG ))
+ {
+ printf("\nIGNORE [NO ORIGINAL] %s:%s\n", GetNameFF(str.fform,0), param->arg );
+ goto endloop;
+ }
+
+ if ( verbose >= 0 )
+ printf("SCAN %s:%s\n", GetNameFF(str.fform,0), param->arg );
+
+ const u8 *ptr = str.data;
+ const u8 *end = ptr + str.data_size;
+ while ( ptr < end )
+ {
+ uint is_http;
+ const str_server_list_t *sl;
+ uint off;
+
+ const u8 *ptr_h = memchr(ptr,'h',end-ptr);
+ const u8 *ptr_g = memchr(ptr,'g',end-ptr);
+ if (!ptr_h)
+ {
+ if (!ptr_g)
+ break;
+ ptr_h = ptr_g + 1;
+ }
+ else if (!ptr_g)
+ ptr_g = ptr_h + 1;
+
+ if ( ptr_h < ptr_g )
+ {
+ ptr = ptr_h;
+ if (!ptr)
+ break;
+
+ if (!memcmp(ptr,"https://",8))
+ {
+ off = 8;
+ is_http = 2;
+ }
+ else if (!memcmp(ptr,"http://",7))
+ {
+ off = 7;
+ is_http = 1;
+ }
+ else if (!strcmp((ccp)ptr,"https"))
+ {
+ off = 5;
+ is_http = 2;
+ }
+ else
+ {
+ ptr++;
+ continue;
+ }
+//printf(">H> %06x : %s\n",(int)(ptr-str.data),ptr);
+ sl = ServerList;
+ ptr += off;
+ if (*ptr)
+ {
+ for ( ; sl->name; sl++ )
+ if ( ptr[sl->domain_len] == '/'
+ && !memcmp(ptr,sl->domain,sl->domain_len) )
+ {
+ break;
+ }
+ if (!sl->name)
+ continue;
+ }
+ else if ( is_http != 2 )
+ continue;
+ }
+ else
+ {
+ ptr = ptr_g;
+ if ( memcmp(ptr,"gs.nintendowifi.net",19)
+ || isalnum((int)ptr[19])
+ || isalnum((int)ptr[-1]) )
+ {
+ ptr++;
+ continue;
+ }
+//printf(">G> %06x : %s\n",(int)(ptr-str.data),ptr);
+
+ is_http = 0;
+ off = 19;
+ ptr += off;
+ sl = ServerList + SERV_GS;
+ }
+
+ noPRINT(" -> %s\n",ptr);
+ if ( n_list >= LIST_SIZE )
+ return ERROR0(ERR_FATAL,"Patch list full\n");
+
+ str_server_patch_t *pat = patch_list + n_list++;
+ pat->mode = str.mode;
+ pat->flags = str.is_dol;
+ pat->is_http = is_http;
+ pat->serv_type = sl->serv_type;
+ pat->offset = ptr - off - str.data;
+ pat->url_len = strlen((ccp)ptr) + off;
+ if (is_http)
+ ptr += sl->domain_len;
+ pat->param = STRDUP((ccp)ptr);
+ }
+ }
+
+ endloop:
+ ResetSTR(&str);
+ }
+
+ if ( n_list > 1 )
+ qsort( patch_list, n_list, sizeof(*patch_list),
+ (qsort_func)compare_server_patch );
+
+ if (long_count>0)
+ {
+ printf("\nconst str_server_patch_t ServerPatch[%u+1] =\n{\n",n_list);
+ str_server_patch_t *pat = patch_list;
+ uint i, last_mode = pat->mode, last_flags = pat->flags;
+ for ( i = 0; i < n_list; i++, pat++ )
+ {
+ if ( last_mode != pat->mode || last_flags != pat->flags )
+ {
+ last_mode = pat->mode;
+ last_flags = pat->flags;
+ putchar('\n');
+ }
+
+ ccp name = ServerList[pat->serv_type].name;
+ printf(" { STR_M_%s,%u, %u,SERV_%s,%*s 0x%06x, %2u, \"%s\" },\n",
+ GetStrModeName(pat->mode),
+ pat->flags,
+ pat->is_http,
+ name, (int)(9-strlen(name)), "",
+ pat->offset,
+ pat->url_len,
+ pat->param );
+ }
+ printf("\n {0,0,0,0,0,0,0}\n};\n\n");
+ }
+ else
+ {
+ static ccp http_text[] = { " -- ", "HTTP ", "HTTPS" };
+ printf("\n==> %u strings found:\n",n_list);
+ uint i;
+ const str_server_patch_t *pat = patch_list;
+ for ( i = 0; i < n_list; i++, pat++ )
+ {
+ const int differ = memcmp(pat,ServerPatch+i,sizeof(*pat));
+ printf(" %c %s %s %s %-10s %06x %2u %s\n",
+ differ ? '!' : ' ',
+ GetStrModeName(pat->mode),
+ pat->flags & STR_F_IS_DOL ? "DOL" : "REL",
+ http_text[pat->is_http],
+ ServerList[pat->serv_type].name, pat->offset, pat->url_len,
+ pat->param );
+ if ( differ && verbose > 0 )
+ {
+ HexDump(stdout,5,0,0,sizeof(*pat),pat,sizeof(*pat));
+ HexDump(stdout,5,0,0,sizeof(*pat),ServerPatch+i,sizeof(*pat));
+ }
+ }
+ }
+
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command extract ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_extract()
+{
+ if ( opt_dest && !*opt_dest )
+ opt_dest = 0;
+ opt_mkdir = true;
+
+ enumError max_err = ERR_OK;
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+ staticr_t str;
+ enumError err = LoadSTR(&str,true,param->arg,opt_ignore>0);
+
+ if ( err <= ERR_WARNING && err != ERR_NOT_EXISTS )
+ {
+ char dest[PATH_MAX];
+ StringCat2S(dest,sizeof(dest),param->arg,".d");
+
+ if ( verbose >= 0 || testmode )
+ {
+ fprintf(stdlog,"%s%sEXTRACT %s:%s -> %s\n",
+ verbose > 1 ? "\n" : "",
+ testmode ? "WOULD " : "",
+ GetNameFF(str.fform,0), str.fname, dest );
+ fflush(stdlog);
+ }
+
+ if ( !opt_overwrite && !opt_update )
+ {
+ struct stat st;
+ if (!stat(dest,&st))
+ return ERROR0(ERR_ALREADY_EXISTS,"Destination already exists: %s",dest);
+ }
+
+ ExtractSTR(&str,dest);
+ }
+
+ if ( max_err < err )
+ max_err = err;
+ ResetSTR(&str);
+ }
+
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command tracks ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_tracks()
+{
+ const int mode = brief_count ? 2 : print_header ? 0 : 1;
+ if (!n_param)
+ {
+ DumpTrackList(stdout,0,mode);
+ return ERR_OK;
+ }
+
+ enumError max_err = ERR_OK;
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+
+ printf("\n* Tracks of %s\n",param->arg);
+ staticr_t str;
+ enumError err = LoadSTR(&str,true,param->arg,opt_ignore>0);
+ if (err)
+ {
+ if ( max_err < err )
+ max_err = err;
+ ResetSTR(&str);
+ continue;
+ }
+
+ const u32 * offtab = GetTrackOffsetTab(&str);
+ if (offtab)
+ {
+ PatchSTR(&str);
+
+ const u8 *d = str.data + *offtab;
+ u32 tab[MKW_N_TRACKS];
+ uint i;
+ for ( i = 0; i < MKW_N_TRACKS; i++ )
+ tab[i] = be32( d + i*4 ) - MKW_TRACK_BEG;
+ DumpTrackList(stdout,tab,mode);
+ }
+ ResetSTR(&str);
+ }
+ putchar('\n');
+
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command arenas ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_arenas()
+{
+ const int mode = brief_count ? 2 : print_header ? 0 : 1;
+ if (!n_param)
+ {
+ DumpArenaList(stdout,0,mode);
+ return ERR_OK;
+ }
+
+ enumError max_err = ERR_OK;
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+
+ printf("\n* Arenas of %s\n",param->arg);
+ staticr_t str;
+ enumError err = LoadSTR(&str,true,param->arg,opt_ignore>0);
+ if (err)
+ {
+ if ( max_err < err )
+ max_err = err;
+ ResetSTR(&str);
+ continue;
+ }
+
+ const u32 * offtab = GetArenaOffsetTab(&str);
+ if (offtab)
+ {
+ PatchSTR(&str);
+
+ const u8 *d = str.data + *offtab;
+ u32 tab[MKW_N_ARENAS];
+ uint i;
+ for ( i = 0; i < MKW_N_ARENAS; i++ )
+ tab[i] = be32( d + i*4 ) - MKW_ARENA_BEG;
+ DumpArenaList(stdout,tab,mode);
+ }
+ ResetSTR(&str);
+ }
+ putchar('\n');
+
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command files ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_files()
+{
+ if (!n_param)
+ {
+ DumpTrackFileList(stdout,0,0);
+ return ERR_OK;
+ }
+
+ enumError max_err = ERR_OK;
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+
+ printf("\n* File list of %s\n",param->arg);
+ staticr_t str;
+ enumError err = LoadSTR(&str,true,param->arg,opt_ignore>0);
+ if (err)
+ {
+ if ( max_err < err )
+ max_err = err;
+ ResetSTR(&str);
+ continue;
+ }
+
+ const u32 * track_off_tab = GetTrackOffsetTab(&str);
+ const u32 * arena_off_tab = GetArenaOffsetTab(&str);
+ if ( track_off_tab && arena_off_tab )
+ {
+ PatchSTR(&str);
+
+ uint i;
+ u32 track_tab[MKW_N_TRACKS], arena_tab[MKW_N_ARENAS];
+ const u8 *d = str.data + *track_off_tab;
+ for ( i = 0; i < MKW_N_TRACKS; i++ )
+ track_tab[i] = be32( d + i*4 ) - MKW_TRACK_BEG;
+
+ d = str.data + *arena_off_tab;
+ for ( i = 0; i < MKW_N_ARENAS; i++ )
+ arena_tab[i] = be32( d + i*4 ) - MKW_ARENA_BEG;
+ DumpTrackFileList(stdout,track_tab,arena_tab);
+ }
+ ResetSTR(&str);
+ }
+
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command find ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static void print_found
+ ( uint idx1, uint idx2, uint n, const TrackInfo_t * info, char prefix )
+{
+ DASSERT(info);
+ DASSERT(prefix);
+ if ( long_count > 2 )
+ printf("%c%u.%u %2u %2u %s %s %s %s\n", prefix,
+ idx1/n+1, idx1%n+1,
+ idx1, idx2,
+ info->track_fname, info->sound_n_fname, info->sound_f_fname,
+ use_de ? info->name_de : info->name_en );
+ else if ( long_count > 1 )
+ printf("%c%u.%u %s %s %s %s\n", prefix,
+ idx1/n+1, idx1%n+1,
+ info->track_fname, info->sound_n_fname, info->sound_f_fname,
+ use_de ? info->name_de : info->name_en );
+ else if ( long_count > 0 )
+ printf("%c%u.%u %s\n", prefix,
+ info->def_slot/10, info->def_slot%10,
+ use_de ? info->name_de : info->name_en );
+ else
+ printf("%c%u.%u\n", prefix,
+ info->def_slot/10, info->def_slot%10 );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static bool find_track ( ccp name, bool allow_arenas )
+{
+ int idx = ScanTrack(name);
+ if ( idx >= 0 )
+ print_found(track_pos_r[idx],idx,4,track_info+idx,'T');
+ else if (allow_arenas)
+ {
+ idx = ScanArena(name);
+ if ( idx >= 0 )
+ print_found(arena_pos_r[idx],idx,5,arena_info+idx,'A');
+ }
+
+ if ( idx < 0 )
+ {
+ printf("-\n");
+ return false;
+ }
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static bool find_arena ( ccp name, bool allow_tracks )
+{
+ int idx = ScanArena(name);
+ if ( idx >= 0 )
+ print_found(arena_pos_r[idx],idx,5,arena_info+idx,'A');
+ else if (allow_tracks)
+ {
+ idx = ScanTrack(name);
+ if ( idx >= 0 )
+ print_found(track_pos_r[idx],idx,4,track_info+idx,'T');
+ }
+
+ if ( idx < 0 )
+ {
+ printf("-\n");
+ return false;
+ }
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_find()
+{
+ if (!n_param)
+ return ERROR0(ERR_SYNTAX,"Missing sub command for 'FIND'\n");
+
+ enum { SUBCMD_TRACKS, SUBCMD_ARENAS };
+
+ static const KeywordTab_t tab[] =
+ {
+ { SUBCMD_TRACKS, "TRACKS", 0, 0 },
+ { SUBCMD_ARENAS, "ARENAS", 0, 0 },
+ { SUBCMD_TRACKS, "+TRACKS", 0, 1 },
+ { SUBCMD_ARENAS, "+ARENAS", 0, 1 },
+ { 0,0,0,0 }
+ };
+
+ const KeywordTab_t * cmd = ScanKeyword(0,first_param->arg,tab);
+ if (!cmd)
+ return ERROR0(ERR_SYNTAX,
+ "Invalid sub command for 'FIND': %s\n",first_param->arg);
+
+ enumError err = ERR_OK;
+
+ DASSERT(first_param);
+ ParamList_t *param;
+ for ( param = first_param->next; param; param = param->next )
+ {
+ char name[100];
+ ccp arg = NormalizeTrackName(name,sizeof(name),param->arg);
+ if ( *arg || !*name )
+ {
+ printf("-\n");
+ err = ERR_NOT_EXISTS;
+ }
+ else
+ {
+ bool stat = cmd->id == SUBCMD_TRACKS
+ ? find_track( name, cmd->opt != 0 )
+ : find_arena( name, cmd->opt != 0 );
+ if (!stat)
+ err = ERR_NOT_EXISTS;
+ }
+ }
+
+ return err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command points ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_points()
+{
+ if ( OptionUsed[OPT_POINTS] && n_param )
+ {
+ ERROR0(ERR_WARNING,
+ "%u file parameter%s ignored because of --points\n",
+ n_param, n_param == 1 ? "" : "s" );
+ n_param = 0;
+ }
+
+ uint mode = brief_count ? 2 : 1;
+ u32 cheat_base = 0;
+ if ( opt_cheat_region != STR_M_UNKNOWN )
+ {
+ const VersusPointsInfo_t *vpi = GetVersusPointsInfo(opt_cheat_region);
+ DASSERT(vpi);
+ mode = vpi->region_code;
+ cheat_base = vpi->cheat_base;
+ }
+
+ if (!n_param)
+ {
+ const MkwPointInfo_t *mpi = GetMkwPointInfo(MkwPointsTab);
+ if ( mode < 'A' )
+ printf("\nVersus points [%s]:\n",mpi->info);
+ PrintMkwPoints( stdout, 2, MkwPointsTab, mode, cheat_base, long_count );
+ return ERR_OK;
+ }
+
+ enumError max_err = ERR_OK;
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+
+ printf("\nVersus points of %s\n",param->arg);
+ staticr_t str;
+ enumError err = LoadSTR(&str,true,param->arg,opt_ignore>0);
+ if (err)
+ {
+ if ( max_err < err )
+ max_err = err;
+ ResetSTR(&str);
+ continue;
+ }
+
+ const uint offset = GetVersusPointsOffset(str.mode);
+ if (offset)
+ {
+ const MkwPointInfo_t *mpi = GetMkwPointInfo(str.data+offset);
+ printf("Type: %s\n",mpi->info);
+ PrintMkwPoints( stdout, 2, str.data+offset, mode, cheat_base, long_count );
+ }
+ ResetSTR(&str);
+ }
+ putchar('\n');
+
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command analyze ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_analyze()
+{
+ enumError max_err = ERR_OK;
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ printf("\n* Analyze %s\n",param->arg);
+ staticr_t str;
+ enumError err = LoadSTR(&str,true,param->arg,opt_ignore>0);
+ if (err)
+ {
+ if ( max_err < err )
+ max_err = err;
+ ResetSTR(&str);
+ continue;
+ }
+
+ PatchSTR(&str);
+ AnalyzeSTR(&str);
+ PrintStatusSTR(stdout,2,&str,long_count);
+ ResetSTR(&str);
+ }
+ putchar('\n');
+
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command patch ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_patch()
+{
+ enumError max_err = ERR_OK;
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+ staticr_t str;
+ enumError err = LoadSTR(&str,true,param->arg,opt_ignore>0);
+
+ if ( err <= ERR_WARNING && err != ERR_NOT_EXISTS )
+ {
+ char dest[PATH_MAX];
+ SubstDest(dest,sizeof(dest),param->arg,opt_dest,0,0,false);
+
+ if ( verbose >= 0 || testmode )
+ {
+ if (strcmp(param->arg,dest))
+ fprintf(stdlog,"%sPATCH %s -> %s\n",
+ testmode ? "WOULD " : "", param->arg, dest );
+ else
+ fprintf(stdlog,"%sPATCH %s\n",
+ testmode ? "WOULD " : "", dest );
+ }
+
+ const uint patch_count = PatchSTR(&str);
+
+ char path_buf[PATH_MAX];
+ ccp dest_fname = param->arg;
+ if ( opt_dest && *opt_dest )
+ {
+ if (IsDirectory(opt_dest,0))
+ {
+ ccp slash = strrchr(param->arg,'/');
+ dest_fname = PathCatPP(path_buf,sizeof(path_buf),opt_dest,
+ slash ? slash+1 : param->arg );
+ }
+ else
+ dest_fname = opt_dest;
+ }
+
+ bool create = false;
+ if (patch_count)
+ {
+ create = true;
+ if ( verbose >= 0 )
+ printf("* %save patched file to: %s:%s\n",
+ testmode ? "Would s" : "S",
+ GetNameFF(str.fform,0), dest_fname );
+ }
+ else if (strcmp(dest_fname,param->arg))
+ {
+ create = true;
+ if ( verbose >= 0 )
+ printf("* File not modified, %scopy to: %s:%s\n",
+ testmode ? "would " : "",
+ GetNameFF(str.fform,0), dest_fname );
+ }
+ else
+ {
+ if ( verbose >= 0 )
+ printf("* File not modified: %s:%s\n",
+ GetNameFF(str.fform,0), dest_fname);
+ }
+
+ if (create)
+ {
+ File_t F;
+ err = CreateFileOpt(&F,true,dest,testmode,param->arg);
+ if (F.f)
+ {
+ SetFileAttrib(&F.fatt,&str.fatt,0);
+ size_t wstat = fwrite(str.data,1,str.data_size,F.f);
+ if ( wstat != str.data_size )
+ err = FILEERROR1(&F,
+ ERR_WRITE_FAILED,"Write failed: %s\n",
+ param->arg);
+ }
+ ResetFile(&F,opt_preserve);
+ }
+ }
+
+ if ( max_err < err )
+ max_err = err;
+ ResetSTR(&str);
+ }
+
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// check options ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError CheckOptions ( int argc, char ** argv, bool is_env )
+{
+ TRACE("CheckOptions(%d,%p,%d) optind=%d\n",argc,argv,is_env,optind);
+
+ optind = 0;
+ int err = 0;
+
+ for(;;)
+ {
+ const int opt_stat = getopt_long(argc,argv,OptionShort,OptionLong,0);
+ if ( opt_stat == -1 )
+ break;
+
+ RegisterOptionByName(&InfoUI_wstrt,opt_stat,1,is_env);
+
+ switch ((enumGetOpt)opt_stat)
+ {
+ case GO__ERR: err++; break;
+ case GO_AT_DUMMY: break;
+
+ case GO_VERSION: version_exit();
+ case GO_HELP: help_exit(false);
+ case GO_XHELP: help_exit(true);
+ case GO_ALLOW_ALL: allow_all = true; break;
+ case GO_COMPATIBLE: err += ScanOptCompatible(optarg); break;
+ case GO_WIDTH: err += ScanOptWidth(optarg); break;
+ 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_DE: use_de = true; break;
+ case GO_CT_CODE: ctcode_enabled = true; break;
+ case GO_LE_CODE: lecode_enabled = true; break;
+ case GO_COLORS: err += ScanOptColorize(0,optarg,0); break;
+ case GO_NO_COLORS: opt_colorize = COLMD_OFF; break;
+
+ case GO_CHDIR: err += ScanOptChdir(optarg); break;
+ case GO_CONST: break; // [[2do]] err += ScanOptConst(optarg); break;
+
+ case GO_UTF_8: use_utf8 = true; break;
+ case GO_NO_UTF_8: use_utf8 = false; break;
+
+ case GO_TEST: testmode++; break;
+ case GO_FORCE: force_count++; break;
+ case GO_REPAIR_MAGICS: err += ScanOptRepairMagic(optarg); break;
+
+ #if OPT_OLD_NEW
+ case GO_OLD: opt_new = opt_new>0 ? -1 : opt_new-1; break;
+ case GO_STD: opt_new = 0; break;
+ case GO_NEW: opt_new = opt_new<0 ? +1 : opt_new+1; break;
+ #endif
+ case GO_EXTRACT: opt_extract = optarg; break;
+
+ case GO_ESC: err += ScanEscapeChar(optarg) < 0; break;
+ case GO_DEST: SetDest(optarg,false); break;
+ case GO_DEST2: SetDest(optarg,true); break;
+ case GO_OVERWRITE: opt_overwrite = true; break;
+ case GO_NUMBER: opt_number = true; break;
+ case GO_REMOVE_DEST: opt_remove_dest = true; break;
+ case GO_UPDATE: opt_update = true; break;
+ case GO_PRESERVE: opt_preserve = true; break;
+ case GO_IGNORE: opt_ignore++; break;
+
+ case GO_CLEAN_DOL: opt_clean_dol = true; break;
+ case GO_TRACKS: err += ScanOptTracks(optarg); break;
+ case GO_ARENAS: err += ScanOptArenas(optarg); break;
+ case GO_REGION: err += ScanOptRegion(optarg); break;
+ case GO_VS_REGION: err += ScanOptVersusRegion(optarg); break;
+ case GO_BT_REGION: err += ScanOptBattleRegion(optarg); break;
+ case GO_ALL_RANKS: err += ScanOptAllRanks(optarg); break;
+ case GO_POINTS: err += ScanOptMkwPoints(optarg,false); break;
+ case GO_CHEAT: err += ScanOptCheatRegion(optarg); break;
+ case GO_ADD_LECODE: AppendStringField(&opt_wcode_list,"@LECODE",false); break;
+ case GO_ADD_CTCODE: opt_add_ctcode = true; break;
+ case GO_CT_DIR: AppendStringField(&ct_dir_list,optarg,false); break;
+ case GO_MOVE_D8: opt_move_d8 = true; break;
+ case GO_ADD_SECTION: AppendStringField(&opt_sect_list,optarg,false); break;
+ case GO_FULL_GCH: opt_full_gch = true; break;
+
+ case GO_GCT_SEP: opt_gct_sep = true; break;
+ case GO_GCT_ASM_SEP: opt_gct_asm_sep = true; break;
+ case GO_GCT_LIST: opt_gct_list++; break;
+ case GO_GCT_MOVE: err += ScanOptGctMove(optarg); break;
+ case GO_GCT_ADDR: err += ScanOptGctAddr(optarg); break;
+ case GO_GCT_SPACE: err += ScanOptGctSpace(optarg); break;
+ case GO_ALLOW_USER_GCH: err += ScanOptAllowUserGch(optarg); break;
+ case GO_GCT_NO_SEP: opt_gct_scan_sep = false; break;
+
+ case GO_CREATE_SECT: err += ScanOptCreateSect(optarg); break;
+ case GO_WPF: AppendStringField(&opt_wpf_list,optarg,false); break;
+
+ case GO_HTTPS: err += ScanOptHttps(optarg); break;
+ case GO_DOMAIN: err += ScanOptDomain(0,optarg); break;
+ case GO_WIIMMFI: err += ScanOptDomain("domain","wiimmfi.de"); break;
+ case GO_TWIIMMFI: err += ScanOptDomain("domain","test.wiimmfi.de"); break;
+ case GO_WC24: opt_wc24 = true; break;
+ case GO_WCODE: err += ScanOptWCode(optarg); break;
+ case GO_ADD_WCODE: AppendStringField(&opt_wcode_list,optarg,false); break;
+ case GO_PB_MODE: err += ScanOptPBMode(optarg); break;
+ case GO_PATCHED_BY: err += ScanOptPatchedBy(optarg); break;
+ case GO_VS: err += ScanOptVS(0,0,optarg); break;
+ case GO_VS2: err += ScanOptVS(0,1,optarg); break;
+ case GO_BT: err += ScanOptVS(1,0,optarg); break;
+ case GO_BT2: err += ScanOptVS(1,1,optarg); break;
+ case GO_CANNON: err += ScanOptCannon(optarg); break;
+ case GO_MENO: opt_meno = true; break;
+
+ case GO_LONG: long_count++; break;
+ case GO_BRIEF: brief_count++; break;
+ case GO_NO_HEADER: print_header = false; break;
+ case GO_SECTIONS: print_sections++; break;
+
+ case GO_VADDR: InsertAddressMemMap(&vaddr,true,optarg,16); break;
+ case GO_FADDR: InsertAddressMemMap(&faddr,true,optarg,16); break;
+ case GO_SNAME: dol_sections |= ScanDolSectionList(optarg,0); break;
+
+ case GO_INT1:
+ case GO_INT2:
+ case GO_INT3:
+ case GO_INT4:
+ case GO_INT5:
+ case GO_INT6:
+ case GO_INT7:
+ case GO_INT8: xparam.format = opt_stat - GO_INT1 + XDUMPF_INT_1; break;
+ case GO_FLOAT: xparam.format = XDUMPF_FLOAT; break;
+ case GO_DOUBLE: xparam.format = XDUMPF_DOUBLE; break;
+
+ case GO_LE: xparam.endian = DC_LITTLE_ENDIAN; break;
+ case GO_BE: xparam.endian = DC_BIG_ENDIAN; break;
+
+ case GO_ZEROS: xparam.mode_zero = true; break;
+ case GO_HEX: xparam.mode_dec = false; break;
+ case GO_DEC: xparam.mode_dec = true; break;
+ case GO_C_SYNTAX: xparam.mode_c = true; break;
+
+ case GO_ADDR: err += ScanOptU64(&xparam.start_addr,"addr",optarg); break;
+ case GO_ALIGN: xparam.mode_align = true; break;
+ case GO_TRIGGER: err += ScanOptU64(&xparam.trigger,"trigger",optarg);
+ xparam.have_trigger = true; break;
+ case GO_NO_ADDR: xparam.print_addr = false; break;
+ case GO_NO_NUMBERS: xparam.print_number = false; break;
+ case GO_NO_TEXT: xparam.print_text = false; break;
+ case GO_FORMAT: xparam.print_format = true; break;
+ case GO_NO_NULL: xparam.mode_ignore = true; break;
+
+ case GO_NARROW: xparam.extra_space = -1; break;
+ case GO_BYTES: xparam.min_width = str2ul(optarg,0,10); break;
+
+ case GO_SMALL:
+ if ( !xparam.min_width )
+ xparam.min_width = 8;
+ else if ( xparam.min_width > 1 )
+ xparam.min_width /= 2;
+ break;
+
+ case GO_WIDE:
+ if ( xparam.min_width < 32 )
+ xparam.min_width = 32;
+ else
+ xparam.min_width = ( xparam.min_width / 16 + 1 ) * 16;
+ break;
+
+ // no default case defined
+ // => compiler checks the existence of all enum values
+ }
+ }
+
+ #ifdef DEBUG
+ DumpUsedOptions(&InfoUI_wstrt,TRACE_FILE,11);
+ #endif
+ NormalizeOptions( verbose > 3 && !is_env ? 2 : 0 );
+
+ if (!is_env)
+ {
+ if ( opt_wcode == WCODE_AUTO )
+ opt_wcode = wifi_domain_is_wiimmfi || opt_wcode_list.used
+ ? WCODE_ON : WCODE_OFF;
+ if ( opt_wcode >= WCODE_ON && opt_gct_move < OFFON_FORCE )
+ opt_gct_move = OFFON_FORCE;
+ }
+ return !err ? ERR_OK : max_error ? max_error : ERR_SYNTAX;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// check command ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError CheckCommand ( int argc, char ** argv )
+{
+ const KeywordTab_t * cmd_ct = CheckCommandHelper(argc,argv,CommandTab);
+ if (!cmd_ct)
+ hint_exit(ERR_SYNTAX);
+
+ TRACE("COMMAND FOUND: #%lld = %s\n",(u64)cmd_ct->id,cmd_ct->name1);
+ current_command = cmd_ct;
+
+ if (!allow_all)
+ {
+ enumError err = VerifySpecificOptions(&InfoUI_wstrt,cmd_ct);
+ if (err)
+ hint_exit(err);
+ }
+ WarnDepractedOptions(&InfoUI_wstrt);
+
+ if ( cmd_ct->id != CMD_ARGTEST )
+ {
+ argc -= optind+1;
+ argv += optind+1;
+
+ if ( cmd_ct->id == CMD_TEST )
+ while ( argc-- > 0 )
+ AddParam(*argv++);
+ else
+ while ( argc-- > 0 )
+ AtFileHelper(*argv++,AddParam);
+ }
+
+ extern const data_tab_t maindol_data_tab[];
+
+ enumError err = ERR_OK;
+ 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_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_ERROR: err = cmd_error(); break;
+ case CMD_FILETYPE: err = cmd_filetype(); break;
+ case CMD_FILEATTRIB: err = cmd_fileattrib(); break;
+ case CMD_RAWDUMP: err = cmd_rawdump(maindol_data_tab); break;
+
+ case CMD_DUMP: err = cmd_dump(false); break;
+ case CMD_CDUMP: err = cmd_dump(true); break;
+ case CMD_HEXDUMP: err = cmd_hexdump(); break;
+ case CMD_HTTPS: err = cmd_https(); break;
+ case CMD_EXTRACT: err = cmd_extract(); break;
+
+ case CMD_TRACKS: err = cmd_tracks(); break;
+ case CMD_ARENAS: err = cmd_arenas(); break;
+ case CMD_FILES: err = cmd_files(); break;
+ case CMD_FIND: err = cmd_find(); break;
+ case CMD_POINTS: err = cmd_points(); break;
+
+ case CMD_ANALYZE: err = cmd_analyze(); break;
+ case CMD_PATCH: err = cmd_patch(); break;
+
+ // no default case defined
+ // => compiler checks the existence of all enum values
+
+ case CMD__NONE:
+ case CMD__N:
+ help_exit(false);
+ }
+
+ return PrintErrorStat(err,verbose,cmd_ct->name1);
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// main() ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#if SZS_WRAPPER
+ int main_wstrt ( int argc, char ** argv )
+#else
+ int main ( int argc, char ** argv )
+#endif
+{
+ print_title_func = print_title;
+ SetupLib(argc,argv,WSTRT_SHORT);
+
+ //----- process arguments
+
+ if ( argc < 2 )
+ {
+ printf("\n%s\n%s\nVisit %s%s for more info.\n\n",
+ text_logo, TITLE, URI_HOME, WSTRT_SHORT );
+ hint_exit(ERR_OK);
+ }
+
+ InitializeXDump(&xparam);
+ xparam.f = stdlog;
+ xparam.indent = 2;
+ xparam.endian = DC_BIG_ENDIAN;
+ xparam.min_addr_fw = 8;
+ xparam.print_format = false;
+ xparam.print_summary= false;
+
+ enumError err = CheckEnvOptions("WSTRT_OPT",CheckOptions);
+ if (err)
+ hint_exit(err);
+
+ err = CheckOptions(argc,argv,false);
+ if (err)
+ hint_exit(err);
+
+ err = CheckCommand(argc,argv);
+ DUMP_TRACE_ALLOC(TRACE_FILE);
+
+ if (SIGINT_level)
+ err = ERROR0(ERR_INTERRUPT,"Program interrupted by user.");
+ return err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// END ///////////////
+///////////////////////////////////////////////////////////////////////////////