aboutsummaryrefslogtreecommitdiff
path: root/project/src/lib-geohit.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-geohit.c
parent76de8a89f7c1d1b4522eb66e8f89d248e8c1781f (diff)
SZS v2.18a
Diffstat (limited to 'project/src/lib-geohit.c')
-rw-r--r--project/src/lib-geohit.c766
1 files changed, 766 insertions, 0 deletions
diff --git a/project/src/lib-geohit.c b/project/src/lib-geohit.c
new file mode 100644
index 0000000..55d13c9
--- /dev/null
+++ b/project/src/lib-geohit.c
@@ -0,0 +1,766 @@
+
+/***************************************************************************
+ * _______ _______ _______ *
+ * | ___ |____ | ___ | *
+ * | | |_| / /| | |_| *
+ * | |_____ / / | |_____ *
+ * |_____ | / / |_____ | *
+ * _ | | / / _ | | *
+ * | |___| |/ /____| |___| | *
+ * |_______|_______|_______| *
+ * *
+ * 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 "geohit.inc"
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// GEOHIT setup ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static void verify_geohit_obj ( const geohit_t * geohit, ccp identify )
+{
+ if ( geohit && geohit->bin )
+ {
+ PRINT("verify_geohit_obj(%s) USE_OBJECT_MANAGER=%d\n",
+ identify, USE_OBJECT_MANAGER );
+
+ #if USE_OBJECT_MANAGER > 1
+ VerifyObjMgr(&geohit->obj_mgr,geohit->bin,geohit->bin_size,identify);
+ #elif USE_OBJECT_MANAGER
+ VerifyBinObjMgr(geohit->bin,geohit->bin_size,identify);
+ #endif
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void InitializeGEOHIT ( geohit_t * geohit, file_format_t fform )
+{
+ DASSERT(geohit);
+ memset(geohit,0,sizeof(*geohit));
+ geohit->fname = EmptyString;
+ geohit->fform_source = fform;
+
+ InitializeObjMgr(&geohit->obj_mgr,fform);
+ SetupBZ2MgrGEOHIT(geohit,fform,true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ResetGEOHIT ( geohit_t * geohit )
+{
+ DASSERT(geohit);
+ const typeof(geohit->fform_source) fform = geohit->fform_source;
+
+ ResetObjMgr(&geohit->obj_mgr);
+ FreeString(geohit->fname);
+ FREE(geohit->bin);
+
+ InitializeGEOHIT(geohit,fform);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SetupBZ2MgrGEOHIT
+ ( geohit_t * geohit, file_format_t fform, bool reload_bin )
+{
+ DASSERT(geohit);
+ if (geohit->bin)
+ ScanObjType( &geohit->obj_mgr.otype,
+ geohit->bin, geohit->bin_size, geohit->bin_size );
+
+ #if USE_OBJECT_MANAGER
+ uint prio = OM_PRIO_DEFAULT;
+ #endif
+ if ( reload_bin || !geohit->bin )
+ {
+ BZ2Manager_t *bz = GetCommonBZ2Manager(fform);
+ if (!bz)
+ {
+ const file_format_t ff = GetObjTypeFF(&geohit->obj_mgr.otype,false);
+ bz = GetCommonBZ2Manager(ff);
+ }
+
+ if (bz)
+ {
+ FREE(geohit->bin);
+ geohit->bin_size = bz->size;
+ geohit->bin = MEMDUP(bz->data,geohit->bin_size);
+ #if USE_OBJECT_MANAGER
+ prio = OM_PRIO_ORIG;
+ #endif
+ }
+ }
+
+ if (geohit->bin)
+ {
+ #if USE_OBJECT_MANAGER
+ SetupObjMgrByData( &geohit->obj_mgr, geohit->bin, geohit->bin_size, prio );
+ #else
+ ScanObjType( &geohit->obj_mgr.otype,
+ geohit->bin, geohit->bin_size, geohit->bin_size );
+ #endif
+
+ #if USE_OBJECT_MANAGER < 3
+ geohit->n_rec = be16(geohit->bin);
+ const uint max = ( geohit->bin_size - 2 ) / geohit->obj_mgr.otype.row_size;
+ if ( geohit->n_rec > max )
+ geohit->n_rec = max;
+ #endif
+ }
+
+ PRINT0("GEOHIT: ff=%s,%s, nr=%03d, np=%02zd, rs=%02u, kart=%d, obj=%d\n",
+ GetNameFF(0,geohit->fform_source),
+ GetNameFF(0,geohit->obj_mgr.otype.fform),
+ #if USE_OBJECT_MANAGER < 2
+ geohit->n_rec,
+ #else
+ -1,
+ #endif
+ geohit->obj_mgr.otype.row_size/sizeof(s16) - 1,
+ geohit->obj_mgr.otype.row_size,
+ geohit->obj_mgr.otype.is_kart, geohit->obj_mgr.otype.is_obj );
+
+ verify_geohit_obj(geohit,"GeoHit/setup");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+geohit_bin_t * GetBinGEOHIT ( cvp data, uint index )
+{
+ DASSERT(data);
+ const uint nr = be16(data);
+ const uint rsize = (be16(data+2)+1) * sizeof(u16);
+ return index < nr
+ ? (geohit_bin_t*)( (u8*)data + 4 + index * rsize )
+ : 0;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// ScanRawGEOHIT() ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enumError ScanRawGEOHIT
+(
+ geohit_t * geohit, // GEOHIT data structure
+ bool init_geohit, // true: initialize 'geohit' first
+ const void * data, // data to scan
+ uint data_size // size of 'data'
+)
+{
+ DASSERT(geohit);
+ if (init_geohit)
+ InitializeGEOHIT(geohit,FF_GH_ITEM);
+
+ FREE(geohit->bin);
+ geohit->bin_size = data_size;
+ geohit->bin = MEMDUP(data,data_size);
+ SetupBZ2MgrGEOHIT(geohit,FF_UNKNOWN,false);
+ return ERR_OK;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// ScanTextGEOHIT() helpers ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enum
+{
+ GEOHIT_IGNORE,
+ GEOHIT_SETUP,
+ GEOHIT_OBJECTS,
+};
+
+//-----------------------------------------------------------------------------
+
+static const KeywordTab_t geohit_section_name[] =
+{
+ { GEOHIT_IGNORE, "END", 0, 0 },
+ { GEOHIT_SETUP, "SETUP", 0, 0 },
+ { GEOHIT_OBJECTS, "OBJECTS", 0, 0 },
+ { 0,0,0,0 }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError ScanTextSETUP
+(
+ geohit_t * geohit, // GEOHIT data structure
+ ScanInfo_t * si // valid data
+)
+{
+ DASSERT(geohit);
+ DASSERT(si);
+ TRACE("ScanTextSETUP()\n");
+
+ bool setup_geohit = false;
+ 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*)&geohit->revision,1,0);
+ si->init_revision = si->cur_file->revision = geohit->revision;
+ DefineIntVar(&si->gvar,"REVISION$SETUP",geohit->revision);
+ DefineIntVar(&si->gvar,"REVISION$ACTIVE",geohit->revision);
+ }
+ else if (!strcmp(name,"IS-OBJ")) // [[obsolete]] in mid 2020
+ {
+ u32 num;
+ if (!ScanU32SI(si,&num,1,0))
+ {
+ setup_geohit = true;
+ geohit->obj_mgr.otype.is_obj = num > 0;
+ }
+ }
+// [[obj-type]]
+ #if USE_OBJECT_MANAGER > 1
+ else if (!SetupObjMgrBySI(&geohit->obj_mgr,si,name))
+ GotoEolSI(si);
+ #else
+ else
+ GotoEolSI(si);
+ #endif
+ CheckEolSI(si);
+ }
+
+ CheckLevelSI(si);
+ if (setup_geohit)
+ SetupBZ2MgrGEOHIT(geohit,FF_UNKNOWN,false);
+ return ERR_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static geohit_bin_t * FindObjectGEOHIT ( const geohit_t *geohit, u16 oid )
+{
+ oid = htons(oid);
+ geohit_bin_t *bin = GetBinGEOHIT(geohit->bin,0);
+
+ uint i;
+ for ( i = 0; i < geohit->n_rec; i++ )
+ {
+ if ( bin->id == oid )
+ return bin;
+
+ bin = (geohit_bin_t*)( (u8*)bin + geohit->obj_mgr.otype.row_size );
+ }
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+static enumError ScanTextOBJECTS
+(
+ geohit_t * geohit, // GEOHIT data structure
+ ScanInfo_t * si // valid data
+)
+{
+ DASSERT(geohit);
+ DASSERT(geohit->bin);
+ DASSERT(si);
+ TRACE("ScanTextSETUP()\n");
+
+ geohit_bin_t *obj = 0;
+ si->point_is_null++;
+ const int n_param = geohit->obj_mgr.otype.row_size/sizeof(s16) - 1;
+
+ for(;;)
+ {
+ char ch = NextCharSI(si,true);
+ if ( !ch || ch == '[' )
+ break;
+
+ if ( ch == '@' )
+ {
+ ScanParamSI(si,0);
+ continue;
+ }
+
+ long oid;
+ ScanUValueSI(si,&oid,0);
+ obj = FindObjectGEOHIT(geohit,oid);
+ PRINT0("OID: %lx -> %p\n",oid,obj);
+ if (!obj)
+ {
+ if ( si->no_warn <= 0 )
+ {
+ ccp eol = FindNextLineFeedSI(si,true);
+ ScanFile_t *sf = si->cur_file;
+ ERROR0(ERR_WARNING,
+ "Object 0x%03lx not found: [%s @%u]: %.*s\n",
+ oid, sf->name, sf->line, (int)(eol-sf->ptr), sf->ptr );
+ }
+ GotoEolSI(si);
+ continue;
+ }
+
+ int i;
+ for ( i = 0; i < n_param; i++ )
+ {
+ const char ch = NextCharSI(si,false);
+ if (!ch)
+ break;
+ if ( ch == '=' )
+ {
+ si->cur_file->ptr++;
+ SkipCharSI(si,',');
+ }
+ else
+ {
+ long num;
+ ScanUValueSI(si,&num,0);
+ obj->param[i] = htons(num);
+ }
+ }
+ CheckEolSI(si);
+ }
+
+ si->point_is_null--;
+ CheckLevelSI(si);
+ return ERR_OK;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// ScanTextGEOHIT() ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enumError ScanTextGEOHIT
+(
+ geohit_t * geohit, // GEOHIT data structure
+ bool init_geohit, // true: initialize 'geohit' first
+ const void * data, // data to scan
+ uint data_size, // size of 'data'
+ file_format_t fform // file format
+)
+{
+ DASSERT(geohit);
+ PRINT("ScanTextGEOHIT(init=%d)\n",init_geohit);
+
+ if ( fform == FF_UNKNOWN )
+ fform = GetByMagicFF(data,data_size,data_size);
+ if (init_geohit)
+ InitializeGEOHIT(geohit,fform);
+ else
+ {
+ geohit->fform_source = fform;
+ SetupBZ2MgrGEOHIT(geohit,fform,true);
+ }
+
+
+ ScanInfo_t si;
+ InitializeSI(&si,data,data_size,geohit->fname,geohit->revision);
+ si.predef = SetupVarsCOMMON();
+
+ enumError max_err = ERR_OK;
+ geohit->is_pass2 = false;
+
+ for(;;)
+ {
+ PRINT("----- SCAN GEOHIT SECTIONS, PASS%u ...\n",geohit->is_pass2+1);
+
+ max_err = ERR_OK;
+ si.no_warn = !geohit->is_pass2;
+ si.total_err = 0;
+ DefineIntVar(&si.gvar, "$PASS", geohit->is_pass2+1 );
+
+ for(;;)
+ {
+ char ch = NextCharSI(&si,true);
+ if (!ch)
+ break;
+
+ if ( ch != '[' )
+ {
+ NextLineSI(&si,true,false);
+ continue;
+ }
+ ResetLocalVarsSI(&si,geohit->revision);
+
+ si.cur_file->ptr++;
+ char name[20];
+ ScanNameSI(&si,name,sizeof(name),true,true,0);
+ noPRINT("--> pass=%u: #%04u: %s\n",geohit->is_pass2+1,si.cur_file->line,name);
+
+ int abbrev_count;
+ const KeywordTab_t *cmd = ScanKeyword(&abbrev_count,name,geohit_section_name);
+ if ( !cmd || abbrev_count )
+ 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 GEOHIT_SETUP:
+ err = ScanTextSETUP(geohit,&si);
+ break;
+
+ case GEOHIT_OBJECTS:
+ err = ScanTextOBJECTS(geohit,&si);
+ break;
+
+ default:
+ // ignore all other section without any warnings
+ break;
+ }
+
+ if ( max_err < err )
+ max_err = err;
+ }
+
+ if (geohit->is_pass2)
+ break;
+
+ geohit->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(ScanTextGEOHIT) = %u (errcount=%u)\n", max_err, si.total_err );
+ ResetSI(&si);
+
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// GEOHIT: scan and load ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enumError ScanGEOHIT
+(
+ geohit_t * geohit, // GEOHIT data structure
+ bool init_geohit, // true: initialize 'geohit' first
+ const void * data, // data to scan
+ uint data_size // size of 'data'
+)
+{
+ DASSERT(geohit);
+
+ enumError err;
+// [[analyse-magic]]
+ const file_format_t fform = GetByMagicFF(data,data_size,data_size);
+ switch (fform)
+ {
+ case FF_GH_ITEM:
+ case FF_GH_IOBJ:
+ case FF_GH_KART:
+ case FF_GH_KOBJ:
+ err = ScanRawGEOHIT(geohit,init_geohit,data,data_size);
+ break;
+
+ case FF_GH_ITEM_TXT:
+ case FF_GH_IOBJ_TXT:
+ case FF_GH_KART_TXT:
+ case FF_GH_KOBJ_TXT:
+ err = ScanTextGEOHIT(geohit,init_geohit,data,data_size,fform);
+ break;
+
+ default:
+ if (init_geohit)
+ InitializeGEOHIT(geohit,0);
+ return ERROR0(ERR_INVALID_DATA,
+ "No GEOHIT file: %s\n", geohit->fname ? geohit->fname : "?");
+ }
+
+ return err;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enumError LoadGEOHIT
+(
+ geohit_t * geohit, // GEOHIT data structure
+ bool init_geohit, // true: initialize 'geohit' first
+ ccp fname, // valid pointer to filenname
+ bool ignore_no_file // ignore if file does not exists
+ // and return warning ERR_NOT_EXISTS
+)
+{
+ DASSERT(geohit);
+ DASSERT(fname);
+ if (init_geohit)
+ InitializeGEOHIT(geohit,0);
+ else
+ ResetGEOHIT(geohit);
+
+ //--- load and scan data
+
+ raw_data_t raw;
+ enumError err = LoadRawData(&raw,true,fname,0,ignore_no_file,0);
+ if (!err)
+ {
+ geohit->fname = raw.fname;
+ raw.fname = 0;
+ err = ScanGEOHIT(geohit,false,raw.data,raw.data_size);
+ }
+
+ ResetRawData(&raw);
+ return err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// SaveRawGEOHIT() ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+enumError SaveRawGEOHIT
+(
+ geohit_t * geohit, // pointer to valid GEOHIT
+ ccp fname, // filename of destination
+ bool set_time // true: set time stamps
+)
+{
+ DASSERT(geohit);
+ DASSERT(geohit->bin);
+ DASSERT(fname);
+
+ PRINT("SaveRawGEOHIT(%s,%d)\n",fname,set_time);
+ verify_geohit_obj(geohit,"GeoHit/save-raw");
+
+
+ //--- 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,&geohit->fatt,0);
+
+ if ( fwrite(geohit->bin,1,geohit->bin_size,F.f) != geohit->bin_size )
+ FILEERROR1(&F,ERR_WRITE_FAILED,"Write failed: %s\n",fname);
+ return ResetFile(&F,set_time);
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// SaveTextGEOHIT() ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+void PrintParamGEOHIT ( FILE *f, uint fw, cvp param0, cvp cmp0, int n )
+{
+ const u16 *param = param0;
+ const u16 *cmp = cmp0;
+
+ int extra = 4;
+ while ( n-- > 0 )
+ {
+ if (!extra--)
+ {
+ extra = 3;
+ fputc(' ',f);
+ }
+
+ const u16 p = ntohs(*param++);
+ if ( cmp && ntohs(*cmp++) == p )
+ fprintf(f," %*c",fw,'=');
+ else if (p)
+ fprintf(f," %*d",fw,(s16)p);
+ else
+ fprintf(f," %*c",fw,'.');
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+enumError SaveTextGEOHIT
+(
+ const geohit_t * geohit, // pointer to valid GEOHIT
+ 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
+ // >9: minimize output
+)
+{
+ // use DOS/Windows line format -> unix can handle it ;)
+
+ DASSERT(geohit);
+ DASSERT(geohit->bin);
+ DASSERT(fname);
+ PRINT("SaveTextGEOHIT(%s,%d)\n",fname,set_time);
+ verify_geohit_obj(geohit,"GeoHit/save-text");
+
+
+ //--- open file
+
+ File_t F;
+ enumError err = CreateFileOpt(&F,true,fname,testmode,geohit->fname);
+ if ( err > ERR_WARNING || !F.f )
+ return err;
+ SetFileAttrib(&F.fatt,&geohit->fatt,0);
+
+
+ //--- print header
+
+ const bool explain = print_header && !brief_count && !export_count;
+ const bool tiny = brief_count > 1 || export_count;
+ const file_format_t ff_text = GetObjTypeFF(&geohit->obj_mgr.otype,true);
+ ccp magic = GetMagicStringFF(ff_text);
+ BZ2Manager_t *bz_orig = GetCommonBZ2Manager(ff_text);
+
+ if (geohit->obj_mgr.otype.is_kart)
+ {
+ if (explain)
+ fprintf(F.f,text_geohit_kart_info_cr,magic);
+ else
+ fprintf(F.f,text_geohit_kart_head_cr,magic);
+
+ if (!tiny)
+ fprintf(F.f,text_geohit_kart_setup_cr,
+ tool_name, SYSTEM, VERSION, REVISION_NUM, DATE );
+
+ #if USE_OBJECT_MANAGER > 1
+ WriteObjMgrToSetupSection( F.f, &geohit->obj_mgr,
+ long_count>0, tiny, explain );
+ #endif
+ }
+ else
+ {
+ if (explain)
+ fprintf(F.f,text_geohit_item_info_cr,magic);
+ else
+ fprintf(F.f,text_geohit_item_head_cr,magic);
+
+ if (!tiny)
+ fprintf(F.f,text_geohit_item_setup_cr,
+ tool_name, SYSTEM, VERSION, REVISION_NUM, DATE );
+
+ #if USE_OBJECT_MANAGER > 1
+ WriteObjMgrToSetupSection( F.f, &geohit->obj_mgr,
+ long_count>0, tiny, explain );
+ #endif
+ }
+
+
+ //--- iterate records
+
+ const int row_size = geohit->obj_mgr.otype.row_size;
+ const int n_param = row_size/sizeof(s16) - 1;
+ const int fw = n_param < 8 ? 5 : 3;
+
+ const geohit_bin_t *bin = GetBinGEOHIT(geohit->bin,0);
+ const geohit_bin_t *ref = bz_orig ? GetBinGEOHIT(bz_orig->data,0) : 0;
+ if (!ref)
+ minimize = 0;
+
+ bool sect_head_done = false;
+ int i, last_grp = -1;
+ for ( i = 0; i < geohit->n_rec; i++ )
+ {
+ const int differ = ref && memcmp( bin, ref, row_size );
+
+ if ( differ || !minimize )
+ {
+ if (!sect_head_done)
+ {
+ sect_head_done = true;
+ fputs( brief_count < 2 ? section_sep : "\r\n", F.f );
+ if (geohit->obj_mgr.otype.is_kart)
+ fprintf(F.f,text_geohit_kart_objects_cr,REVISION_NUM);
+ else
+ fprintf(F.f,text_geohit_item_objects_cr,REVISION_NUM);
+ }
+
+ const uint obj_id = ntohs(bin->id);
+ const uint grp = obj_id >> 4;
+ if ( last_grp != grp )
+ {
+ if ( last_grp != -1 )
+ fputs("\r\n",F.f);
+ last_grp = grp;
+ }
+
+ fprintf(F.f,"\r\n 0x%03x ",obj_id);
+ PrintParamGEOHIT(F.f,fw,bin->param,0,n_param);
+ if ( obj_id < N_KMP_GOBJ )
+ fprintf(F.f," # %s",ObjectInfo[obj_id].name);
+
+ if (differ)
+ {
+ fputs("\r\n #ORIG:",F.f);
+ PrintParamGEOHIT(F.f,fw,ref->param,bin->param,n_param);
+//DEL HexDump16(stderr,0,0,bin,row_size);
+//DEL HexDump16(stderr,0,0,ref,row_size);
+ }
+ }
+
+ bin = (geohit_bin_t*)( (u8*)bin + row_size );
+ if (ref)
+ ref = (geohit_bin_t*)( (u8*)ref + row_size );
+ }
+
+
+ //--- terminate
+
+ fputs("\r\n",F.f);
+ fputs( brief_count < 2 ? section_end :"\r\n", F.f );
+ ResetFile(&F,set_time);
+ return err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// END ///////////////
+///////////////////////////////////////////////////////////////////////////////
+