aboutsummaryrefslogtreecommitdiff
path: root/project/src/lib-itemslot.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/lib-itemslot.c
parent76de8a89f7c1d1b4522eb66e8f89d248e8c1781f (diff)
SZS v2.18a
Diffstat (limited to 'project/src/lib-itemslot.c')
-rwxr-xr-xproject/src/lib-itemslot.c790
1 files changed, 790 insertions, 0 deletions
diff --git a/project/src/lib-itemslot.c b/project/src/lib-itemslot.c
new file mode 100755
index 0000000..20d0060
--- /dev/null
+++ b/project/src/lib-itemslot.c
@@ -0,0 +1,790 @@
+
+/***************************************************************************
+ * _______ _______ _______ *
+ * | ___ |____ | ___ | *
+ * | | |_| / /| | |_| *
+ * | |_____ / / | |_____ *
+ * |_____ | / / |_____ | *
+ * _ | | / / _ | | *
+ * | |___| |/ /____| |___| | *
+ * |_______|_______|_______| *
+ * *
+ * 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 <stddef.h>
+
+#include "dclib-xdump.h"
+#include "lib-szs.h"
+#include "lib-common.h"
+#include "lib-numeric.h"
+#include "lib-bzip2.h"
+
+#include "itemslot.inc"
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// data ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enum
+{
+ RACE_PARAM = 0,
+ BATTLE_PARAM = 1,
+};
+
+static const KeywordTab_t itemslot_table_list[] =
+{
+ { 0x001, "GRAND-PRIX-PLAYER", 0, RACE_PARAM },
+ { 0x0e7, "GRAND-PRIX-ENEMY", 0, RACE_PARAM },
+ { 0x1cd, "VERSUS-PLAYER", 0, RACE_PARAM },
+ { 0x2b3, "VERSUS-ENEMY", 0, RACE_PARAM },
+ { 0x399, "VERSUS-ONLINE", 0, RACE_PARAM },
+ { 0x47f, "SPECIAL", 0, RACE_PARAM },
+
+ // typo "BALLON" will be [[obsolete]], "BALLOON" since 2020-01 (3x)
+ { 0x5b1, "BALLOON-PLAYER", "BALLON-PLAYER", BATTLE_PARAM },
+ { 0x5ec, "BALLOON-ENEMY", "BALLON-ENEMY", BATTLE_PARAM },
+ { 0x627, "COIN-PLAYER", 0, BATTLE_PARAM },
+ { 0x662, "COIN-ENEMY", 0, BATTLE_PARAM },
+ { 0x69d, "BALLOON-ONLINE", "BALLON-ONLINE", BATTLE_PARAM },
+ { 0x6d8, "COIN-ONLINE", 0, BATTLE_PARAM },
+
+ { 0,0,0,0 }
+};
+
+//-----------------------------------------------------------------------------
+
+static ccp item_info[] =
+{
+ "Green Shell",
+ "Red Shell",
+ "Banana",
+ "Fake Item Box",
+ "Mushroom",
+ "Triple Mushroom",
+ "Bob-omb",
+ "Blue Shell",
+ "Lightning",
+ "Star",
+ "Golden Mushroom",
+ "Mega Mushroom",
+ "Blooper",
+ "POW Block",
+ "Thundercloud",
+ "Bullet Bill",
+ "Triple Green Shells",
+ "Triple Red Shells",
+ "Triple Bananas",
+};
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// ITEMSLOT setup ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+void InitializeITEMSLOT ( itemslot_t * itemslot, file_format_t fform )
+{
+ DASSERT(itemslot);
+ memset(itemslot,0,sizeof(*itemslot));
+ itemslot->fname = EmptyString;
+ itemslot->fform_source = fform;
+ itemslot->add_battle = true;
+ SetupBZ2MgrITEMSLOT(itemslot,true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ResetITEMSLOT ( itemslot_t * itemslot )
+{
+ DASSERT(itemslot);
+ const typeof(itemslot->fform_source) fform = itemslot->fform_source;
+ FreeString(itemslot->fname);
+ InitializeITEMSLOT(itemslot,fform);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool GetOriginalITEMSLOT ( itemslot_bin_t *dest )
+{
+ DASSERT(dest);
+ BZ2Manager_t *bz = GetCommonBZ2Manager(FF_ITEMSLT);
+ DASSERT(bz);
+ DASSERT( bz->size == sizeof(*dest) );
+ if ( bz && bz->size == sizeof(*dest) )
+ {
+ memcpy(dest,bz->data,sizeof(*dest));
+ return true;
+ }
+
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SetupBZ2MgrITEMSLOT ( itemslot_t * itemslot, bool reload_bin )
+{
+ DASSERT(itemslot);
+ if ( reload_bin || !itemslot->data.n_table )
+ GetOriginalITEMSLOT(&itemslot->data);
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// ScanRawITEMSLOT() ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enumError ScanRawITEMSLOT
+(
+ itemslot_t * itemslot, // ITEMSLOT data structure
+ bool init_itemslot, // true: initialize 'itemslot' first
+ const void * data, // data to scan
+ uint data_size // size of 'data'
+)
+{
+ DASSERT(itemslot);
+ if (init_itemslot)
+ InitializeITEMSLOT(itemslot,FF_ITEMSLT);
+
+ SetupBZ2MgrITEMSLOT(itemslot,true);
+ if ( !data || data_size != ITEMSLT_SIZE6 && data_size != ITEMSLT_SIZE12 )
+ return ERROR0(ERR_INVALID_DATA,
+ "Invalid file size (%u but not %zu bytes: %s\n",
+ data_size, sizeof(itemslot->data), itemslot->fname );
+
+ memcpy(&itemslot->data,data,data_size);
+ itemslot->add_battle = data_size == ITEMSLT_SIZE12;
+
+
+ //--- fix table headers
+
+ BZ2Manager_t *bz = GetCommonBZ2Manager(FF_ITEMSLT);
+ const KeywordTab_t *par;
+ for ( par = itemslot_table_list; par->name1; par++ )
+ {
+ const uint offset = par->id;
+ u8 *val = (u8*)&itemslot->data + offset;
+ const u8 *orig = bz->data + offset;
+ *val++ = *orig++;
+ *val++ = *orig++;
+ }
+
+ return ERR_OK;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// ScanTextITEMSLOT() helpers ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enum
+{
+ ITEMSLOT_IGNORE,
+ ITEMSLOT_SETUP,
+ ITEMSLOT_PARAMETERS,
+};
+
+//-----------------------------------------------------------------------------
+
+static const KeywordTab_t itemslot_section_name[] =
+{
+ { ITEMSLOT_IGNORE, "END", 0, 0 },
+ { ITEMSLOT_SETUP, "SETUP", 0, 0 },
+ { ITEMSLOT_PARAMETERS, "PARAMETERS", 0, 0 },
+ { 0,0,0,0 }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError ScanTextSETUP
+(
+ itemslot_t * itemslot, // ITEMSLOT data structure
+ ScanInfo_t * si // valid data
+)
+{
+ DASSERT(itemslot);
+ DASSERT(si);
+ TRACE("ScanTextSETUP()\n");
+
+ for(;;)
+ {
+ char ch = NextCharSI(si,true);
+ if ( !ch || ch == '[' )
+ break;
+
+ char name[50];
+ if ( !ScanNameSI(si,name,sizeof(name),true,true,0)
+ || NextCharSI(si,true) != '=' )
+ {
+ CheckEolSI(si);
+ continue;
+ }
+ DASSERT(si->cur_file);
+ si->cur_file->ptr++;
+ noPRINT("### %s = %.4s...\n",name,si->cur_file->ptr);
+
+ if (!strcmp(name,"REVISION"))
+ {
+ ScanU32SI(si,(u32*)&itemslot->revision,1,0);
+ si->init_revision = si->cur_file->revision = itemslot->revision;
+ DefineIntVar(&si->gvar,"REVISION$SETUP",itemslot->revision);
+ DefineIntVar(&si->gvar,"REVISION$ACTIVE",itemslot->revision);
+ }
+ else
+ GotoEolSI(si);
+ CheckEolSI(si);
+ }
+
+ CheckLevelSI(si);
+ return ERR_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError ScanTextPARAMETERS
+(
+ itemslot_t * itemslot, // ITEMSLOT data structure
+ ScanInfo_t * si // valid data
+)
+{
+ DASSERT(itemslot);
+ DASSERT(si);
+ TRACE("ScanTextSETUP()\n");
+
+ for(;;)
+ {
+ char ch = NextCharSI(si,true);
+ if ( !ch || ch == '[' )
+ break;
+
+ if ( ch == '@' )
+ si->cur_file->ptr++;
+
+ char name[50];
+ if ( !ScanNameSI(si,name,sizeof(name),true,true,0)
+ || NextCharSI(si,true) != '=' )
+ {
+ CheckEolSI(si);
+ continue;
+ }
+ DASSERT(si->cur_file);
+ si->cur_file->ptr++;
+ PRINT0("### %s = %.4s...\n",name,si->cur_file->ptr);
+
+ if (!strcmp(name,"REVISION"))
+ {
+ u32 rev;
+ ScanU32SI(si,&rev,1,0);
+ si->cur_file->revision = rev;
+ DefineIntVar(&si->gvar,"REVISION$ACTIVE",rev);
+ }
+ else if (!strcmp(name,"ADD-BATTLE"))
+ {
+ int val;
+ const enumError err = ScanAssignIntSI(si,&val);
+ if (!err)
+ itemslot->add_battle = val > 0 ;
+ }
+ else if (!strcmp(name,"USE-SLT"))
+ {
+ int val;
+ const enumError err = ScanAssignIntSI(si,&val);
+ if (!err)
+ itemslot->use_slt = val > 0 ;
+ }
+ CheckEolSI(si);
+ }
+
+ CheckLevelSI(si);
+ return ERR_OK;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError ScanTextTABLE
+(
+ itemslot_t * itemslot, // ITEMSLOT data structure
+ ScanInfo_t * si, // valid data
+ const KeywordTab_t * par // valid section pointer
+)
+{
+ DASSERT(itemslot);
+ DASSERT(si);
+ DASSERT(par);
+
+ const uint offset = par->id;
+ u8 *val = (u8*)&itemslot->data + offset;
+ const uint n_col = *val++;
+ const uint n_row = *val++;
+
+ PRINT0(">> SCAN offset 0x%03x, size %2u*%u %s\n",
+ offset, n_col, n_row, par->name1 );
+ si->point_is_null++;
+
+ for(;;)
+ {
+ char ch = NextCharSI(si,true);
+ if ( !ch || ch == '[' )
+ break;
+
+ if ( ch == '@' )
+ {
+ ScanParamSI(si,0);
+ continue;
+ }
+
+ ScanFile_t *sf = si->cur_file;
+
+ long item;
+ enumError err = ScanUValueSI(si,&item,0);
+ if (err)
+ break;
+ if ( item >= n_row )
+ {
+ ccp eol = FindNextLineFeedSI(si,true);
+ if ( si->no_warn <= 0 )
+ ERROR0(ERR_WARNING,
+ "Item ID is %lu but must be between 0 and %u: [%s @%u]: %.*s\n",
+ item, n_row-1, sf->name, sf->line, (int)(eol-sf->ptr), sf->ptr );
+ sf->ptr = eol;
+ continue;
+ }
+
+ u8 *dest = val + item * n_col;;
+ uint idx;
+ for ( idx = 0; idx < n_col; idx++ )
+ {
+ ch = NextCharSI(si,false);
+ if (!ch)
+ break;
+
+ long val;
+ err = ScanUValueSI(si,&val,0);
+ if (err)
+ break;
+ *dest++ = val;
+ }
+ CheckEolSI(si);
+ }
+
+ si->point_is_null--;
+ return ERR_OK;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// ScanTextITEMSLOT() ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enumError ScanTextITEMSLOT
+(
+ itemslot_t * itemslot, // ITEMSLOT data structure
+ bool init_itemslot, // true: initialize 'itemslot' first
+ const void * data, // data to scan
+ uint data_size, // size of 'data'
+ file_format_t fform // file format
+)
+{
+ DASSERT(itemslot);
+ PRINT("ScanTextITEMSLOT(init=%d)\n",init_itemslot);
+
+ if (init_itemslot)
+ InitializeITEMSLOT(itemslot,FF_ITEMSLT_TXT);
+ else
+ {
+ itemslot->fform_source = FF_ITEMSLT_TXT;
+ SetupBZ2MgrITEMSLOT(itemslot,true);
+ }
+
+ ScanInfo_t si;
+ InitializeSI(&si,data,data_size,itemslot->fname,itemslot->revision);
+ si.predef = SetupVarsCOMMON();
+
+ enumError max_err = ERR_OK;
+ itemslot->is_pass2 = false;
+
+ for(;;)
+ {
+ PRINT("----- SCAN ITEMSLOT SECTIONS, PASS%u ...\n",itemslot->is_pass2+1);
+
+ max_err = ERR_OK;
+ si.no_warn = !itemslot->is_pass2;
+ si.total_err = 0;
+ DefineIntVar(&si.gvar, "$PASS", itemslot->is_pass2+1 );
+
+ for(;;)
+ {
+ char ch = NextCharSI(&si,true);
+ if (!ch)
+ break;
+
+ if ( ch != '[' )
+ {
+ NextLineSI(&si,true,false);
+ continue;
+ }
+ ResetLocalVarsSI(&si,itemslot->revision);
+
+ si.cur_file->ptr++;
+ char name[20];
+ ScanNameSI(&si,name,sizeof(name),true,true,0);
+ noPRINT("--> pass=%u: #%04u: %s\n",itemslot->is_pass2+1,si.cur_file->line,name);
+
+ int abbrev_count;
+ const KeywordTab_t *cmd = ScanKeyword(&abbrev_count,name,itemslot_section_name);
+ if ( !cmd || abbrev_count )
+ {
+ cmd = ScanKeyword(&abbrev_count,name,itemslot_table_list);
+ if ( cmd && !abbrev_count )
+ {
+ while ( cmd > itemslot_table_list && cmd[-1].id == cmd->id )
+ cmd--;
+ NextLineSI(&si,false,false);
+ enumError err = ScanTextTABLE(itemslot,&si,cmd);
+ if ( max_err < err )
+ max_err = err;
+ }
+ continue;
+ }
+
+ NextLineSI(&si,false,false);
+ noPRINT("--> %-6s #%-4u |%.3s|\n",cmd->name1,si.cur_file->line,si.cur_file->ptr);
+
+ enumError err = ERR_OK;
+ switch (cmd->id)
+ {
+ case ITEMSLOT_SETUP:
+ err = ScanTextSETUP(itemslot,&si);
+ break;
+
+ case ITEMSLOT_PARAMETERS:
+ err = ScanTextPARAMETERS(itemslot,&si);
+ break;
+
+ default:
+ // ignore all other section without any warnings
+ break;
+ }
+
+ if ( max_err < err )
+ max_err = err;
+ }
+
+ if (itemslot->is_pass2)
+ break;
+
+ itemslot->is_pass2 = true;
+
+ RestartSI(&si);
+ }
+
+ #if HAVE_PRINT0
+ printf("VAR DUMP/GLOBAL:\n");
+ DumpVarMap(stdout,3,&si.gvar,false);
+ #endif
+
+ CheckLevelSI(&si);
+ if ( max_err < ERR_WARNING && si.total_err )
+ max_err = ERR_WARNING;
+ PRINT("ERR(ScanTextITEMSLOT) = %u (errcount=%u)\n", max_err, si.total_err );
+ ResetSI(&si);
+
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// ITEMSLOT: scan and load ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enumError ScanITEMSLOT
+(
+ itemslot_t * itemslot, // ITEMSLOT data structure
+ bool init_itemslot, // true: initialize 'itemslot' first
+ const void * data, // data to scan
+ uint data_size, // size of 'data'
+ ccp fname // not NULL: Analyse file extention for '.slt'
+)
+{
+ DASSERT(itemslot);
+
+ enumError err;
+ const file_format_t fform = GetByMagicFF(data,data_size,data_size);
+ switch (fform)
+ {
+ case FF_ITEMSLT:
+ err = ScanRawITEMSLOT(itemslot,init_itemslot,data,data_size);
+ if (fname)
+ {
+ const uint fnlen = strlen(fname);
+ itemslot->use_slt = fnlen > 4 && !strcasecmp(fname+fnlen-4,".slt");
+ PRINT("USE_SLT=%d, ADD_BATTLE=%d\n",itemslot->use_slt,itemslot->add_battle);
+ }
+ break;
+
+ case FF_ITEMSLT_TXT:
+ err = ScanTextITEMSLOT(itemslot,init_itemslot,data,data_size,fform);
+ break;
+
+ default:
+ if (init_itemslot)
+ InitializeITEMSLOT(itemslot,0);
+ return ERROR0(ERR_INVALID_DATA,
+ "No ITEMSLOT file: %s\n", itemslot->fname ? itemslot->fname : "?");
+ }
+
+ return err;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enumError LoadITEMSLOT
+(
+ itemslot_t * itemslot, // ITEMSLOT data structure
+ bool init_itemslot, // true: initialize 'itemslot' first
+ ccp fname, // valid pointer to filenname
+ bool ignore_no_file // ignore if file does not exists
+ // and return warning ERR_NOT_EXISTS
+)
+{
+ DASSERT(itemslot);
+ DASSERT(fname);
+ if (init_itemslot)
+ InitializeITEMSLOT(itemslot,0);
+ else
+ ResetITEMSLOT(itemslot);
+
+ //--- load and scan data
+
+ raw_data_t raw;
+ enumError err = LoadRawData(&raw,true,fname,0,ignore_no_file,0);
+ if (!err)
+ {
+ itemslot->fname = raw.fname;
+ raw.fname = 0;
+ err = ScanITEMSLOT(itemslot,false,raw.data,raw.data_size,fname);
+ }
+
+ ResetRawData(&raw);
+ return err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// SaveRawITEMSLOT() ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enumError SaveRawITEMSLOT
+(
+ itemslot_t * itemslot, // pointer to valid ITEMSLOT
+ ccp fname, // filename of destination
+ bool set_time // true: set time stamps
+)
+{
+ DASSERT(itemslot);
+ DASSERT(fname);
+
+ PRINT("SaveRawITEMSLOT(%s,%d)\n",fname,set_time);
+
+ //--- write to file
+
+ File_t F;
+ enumError err = CreateFileOpt(&F,true,fname,testmode,fname);
+ if ( err > ERR_WARNING || !F.f )
+ return err;
+ SetFileAttrib(&F.fatt,&itemslot->fatt,0);
+
+ const uint size = itemslot->add_battle ? ITEMSLT_SIZE12 : ITEMSLT_SIZE6;
+ itemslot->data.n_table = itemslot->add_battle ? 12 : 6;
+ if ( fwrite(&itemslot->data,1,size,F.f) != size )
+ FILEERROR1(&F,ERR_WRITE_FAILED,"Write failed: %s\n",fname);
+ return ResetFile(&F,set_time);
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// SaveTextITEMSLOT() ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enumError SaveTextITEMSLOT
+(
+ const itemslot_t * itemslot, // pointer to valid ITEMSLOT
+ ccp fname, // filename of destination
+ bool set_time, // true: set time stamps
+// [[minimize]]
+ int minimize // usually a copy of global 'minimize_level':
+ // >0: write only modified sections
+ // >1: write only modified records
+ // >9: minimize output
+)
+{
+ // use DOS/Windows line format -> unix can handle it ;)
+
+ DASSERT(itemslot);
+ DASSERT(fname);
+ PRINT("SaveTextITEMSLOT(%s,%d)\n",fname,set_time);
+
+ BZ2Manager_t *bz = GetCommonBZ2Manager(FF_ITEMSLT);
+
+
+ //--- open file
+
+ File_t F;
+ enumError err = CreateFileOpt(&F,true,fname,testmode,itemslot->fname);
+ if ( err > ERR_WARNING || !F.f )
+ return err;
+ SetFileAttrib(&F.fatt,&itemslot->fatt,0);
+
+
+ //--- print header + syntax info
+
+ const bool explain = print_header && !brief_count && !export_count;
+ if (explain)
+ fputs(text_itemslot_info_cr,F.f);
+ else
+ fputs(text_itemslot_head_cr,F.f);
+
+ const bool tiny = brief_count > 1 || export_count;
+ if (!tiny)
+ fprintf(F.f,text_itemslot_setup_cr,
+ tool_name, SYSTEM, VERSION, REVISION_NUM, DATE );
+
+
+ //--- print parameters
+
+ if ( minimize < 10 )
+ {
+ fputs( brief_count < 2 ? section_sep : "\r\n", F.f );
+ fprintf(F.f,text_itemslot_param_cr,
+ REVISION_NUM, itemslot->add_battle, itemslot->use_slt );
+ }
+
+
+ //--- print tables
+
+ uint active_offset = 0;
+ const uint N_SUM = 20;
+ uint sum[N_SUM];
+
+ const KeywordTab_t *par;
+ for ( par = itemslot_table_list; par->name1; par++ )
+ {
+ const uint offset = par->id;
+ if ( active_offset == offset ) // skip entries for same section
+ continue;
+ active_offset = offset;
+
+ const bool is_battle = par->opt == BATTLE_PARAM;
+ if ( is_battle && !itemslot->add_battle )
+ continue;
+
+ const u8 *val = (u8*)&itemslot->data + offset + 2;
+ const u8 *orig = bz->data + offset;
+ const uint n_col = *orig++;
+ const uint n_row = *orig++;
+ const uint table_size = n_row * n_col;
+ DASSERT( n_col <= N_SUM );
+
+ if ( minimize < 1 || memcmp(val,orig,table_size) )
+ {
+ uint row, col;
+ memset(sum,0,sizeof(sum));
+
+ fputs( brief_count < 2 ? section_sep : "\r\n", F.f );
+ fprintf(F.f, text_itemslot_table_cr,
+ par->name2 ? par->name2 : par->name1,
+ is_battle ? "battle" : "racing",
+ offset, n_row, n_col, REVISION_NUM );
+ // [[2do]] ??? table dependent info
+
+ const uint fw1 = 7 + 4*n_col;
+ const uint fw2 = 25;
+ fprintf(F.f,"#%.*s#%.*s\r\n# item",fw1,Minus300,fw2,Minus300);
+ for ( col = 0; col < n_col; col++ )
+ fprintf(F.f,"%3u.",col+1);
+ fprintf(F.f," # sum item name\r\n#%.*s#%.*s\r\n",fw1,Minus300,fw2,Minus300);
+
+ for ( row = 0; row < n_row; row++ )
+ {
+ const int differ = memcmp(val,orig,n_col);
+ if ( delta_count < 2 || differ )
+ {
+ fprintf(F.f,"%5u ",row);
+ uint row_sum = 0;
+ for ( col = 0; col < n_col; col++ )
+ {
+ const uint num = val[col];
+ if (num)
+ {
+ row_sum += num;
+ sum[col] += num;
+ fprintf(F.f,"%4u",num);
+ }
+ else
+ fputs(" .",F.f);
+ }
+ fprintf(F.f," #%4u %s\r\n",row_sum,item_info[row]);
+
+ if (differ)
+ {
+ fputs("#ORIG:",F.f);
+ for ( col = 0; col < n_col; col++ )
+ if ( val[col] == orig[col] )
+ fputs(" .",F.f);
+ else
+ fprintf(F.f,"%4d",orig[col]);
+ fputs("\r\n",F.f);
+ if ( minimize < 2 )
+ fputs("\r\n",F.f);
+ }
+ }
+ val += n_col;
+ orig += n_col;
+ }
+ if ( minimize < 2 )
+ {
+ fprintf(F.f,"#%.*s#%.*s\r\n#SUM: ",fw1,Minus300,fw2,Minus300);
+ for ( col = 0; col < n_col; col++ )
+ fprintf(F.f,"%4d",sum[col]);
+ fputs("\r\n",F.f);
+ }
+ }
+ }
+
+ //--- terminate
+
+ fputs( brief_count < 2 ? section_end :"\r\n", F.f );
+ ResetFile(&F,set_time);
+ return ERR_OK;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// END ///////////////
+///////////////////////////////////////////////////////////////////////////////
+