From 1192c4575ea7afdf38e3fa0df4587a08620af11e Mon Sep 17 00:00:00 2001 From: root Date: Tue, 21 Jul 2020 10:00:46 +0200 Subject: SZS v2.18a --- project/src/lib-minigame.c | 923 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 923 insertions(+) create mode 100755 project/src/lib-minigame.c (limited to 'project/src/lib-minigame.c') diff --git a/project/src/lib-minigame.c b/project/src/lib-minigame.c new file mode 100755 index 0000000..b97e086 --- /dev/null +++ b/project/src/lib-minigame.c @@ -0,0 +1,923 @@ + +/*************************************************************************** + * _______ _______ _______ * + * | ___ |____ | ___ | * + * | | |_| / /| | |_| * + * | |_____ / / | |_____ * + * |_____ | / / |_____ | * + * _ | | / / _ | | * + * | |___| |/ /____| |___| | * + * |_______|_______|_______| * + * * + * 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 * + * * + *************************************************************************** + * * + * 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 + +#include "dclib-xdump.h" +#include "lib-szs.h" +#include "lib-common.h" +#include "lib-numeric.h" +#include "lib-bzip2.h" +#include "dclib-numeric.h" + +#include "minigame.inc" + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// data /////////////// +/////////////////////////////////////////////////////////////////////////////// + +int opt_kmg_arena = -1; +int opt_kmg_limit = -1; + +//----------------------------------------------------------------------------- + +enum +{ + HEAD_PARAM = 0, + BALLOON_PARAM = 1, + COIN_PARAM = 2, +}; + +//----------------------------------------------------------------------------- + +static ccp minigame_param_title[] = +{ + "Parameters of file header (16 bit)", + "Parameters for balloon battle (16 bit, offsets 0x1c8..0x1da)", + "Parameters for coin runners (16 bit, offsets 0x704..0x716)", +}; + +//----------------------------------------------------------------------------- + +static const KeywordTab_t minigame_param_list[] = +{ + { 0x008, "OFFSET-008", 0, HEAD_PARAM }, + { 0x00a, "OFFSET-00A", 0, HEAD_PARAM }, + + { 0x1c8, "OFFSET-1C8", "POINTS-IF-HIT-OTHER", BALLOON_PARAM }, + { 0x1ca, "OFFSET-1CA", "POINTS-IF-DEFEAT", BALLOON_PARAM }, + { 0x1cc, "OFFSET-1CC", "POINTS-IF-BALLOONS-LOST", BALLOON_PARAM }, + // [[obsolete]], typo "BALLON" fixed in 2020-01 + { 0x1cc, "POINTS-IF-BALLONS-LOST", 0, BALLOON_PARAM }, + { 0x1ce, "OFFSET-1CE", "POINTS-IF-HIT", BALLOON_PARAM }, + { 0x1d0, "OFFSET-1D0", "POINTS-HITTING-TEAMMATE", BALLOON_PARAM }, + { 0x1d2, "OFFSET-1D2", "POINTS-IF-HIT-BY-TEAMMATE", BALLOON_PARAM }, + { 0x1d4, "OFFSET-1D4", 0, BALLOON_PARAM }, + { 0x1d6, "OFFSET-1D6", 0, BALLOON_PARAM }, + { 0x1d8, "OFFSET-1D8", 0, BALLOON_PARAM }, + { 0x1da, "OFFSET-1DA", 0, BALLOON_PARAM }, + + { 0x704, "OFFSET-704", 0, COIN_PARAM }, + { 0x706, "OFFSET-706", 0, COIN_PARAM }, + { 0x708, "OFFSET-708", 0, COIN_PARAM }, + { 0x70a, "OFFSET-70A", 0, COIN_PARAM }, + { 0x70c, "OFFSET-70C", 0, COIN_PARAM }, + { 0x70e, "OFFSET-70E", 0, COIN_PARAM }, + { 0x710, "OFFSET-710", 0, COIN_PARAM }, + { 0x712, "OFFSET-712", "MIN-LOST-FALLDOWN", COIN_PARAM }, + { 0x714, "OFFSET-714", "MIN-LOST-IF-HIT", COIN_PARAM }, + { 0x716, "OFFSET-716", "LOST-PERCENTAGE", COIN_PARAM }, + + { 0,0,0,0 } +}; + +//----------------------------------------------------------------------------- + +static const KeywordTab_t minigame_table_list[] = +{ + { 0x010, "OFFSET-010", "BALLOON-DURATION", BALLOON_PARAM }, + // [[obsolete]], typo "BALLON" fixed in 2020-01 + { 0x010, "BALLON-DURATION", 0, BALLOON_PARAM }, + { 0x0ec, "OFFSET-0EC", 0, BALLOON_PARAM }, + + { 0x1dc, "OFFSET-1DC", "COIN-DURATION", COIN_PARAM }, + { 0x2b8, "OFFSET-2B8", 0, COIN_PARAM }, + { 0x394, "OFFSET-394", "START-COINS", COIN_PARAM }, + { 0x470, "OFFSET-470", "MAX-COINS", COIN_PARAM }, + { 0x54c, "OFFSET-54C", 0, COIN_PARAM }, + { 0x628, "OFFSET-628", 0, COIN_PARAM }, + + { 0,0,0,0 } +}; + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// MINIGAME setup /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void InitializeMINIGAME ( minigame_t * minigame, file_format_t fform ) +{ + DASSERT(minigame); + memset(minigame,0,sizeof(*minigame)); + minigame->fname = EmptyString; + minigame->fform_source = fform; + SetupBZ2MgrMINIGAME(minigame,true); +} + +/////////////////////////////////////////////////////////////////////////////// + +void ResetMINIGAME ( minigame_t * minigame ) +{ + DASSERT(minigame); + const typeof(minigame->fform_source) fform = minigame->fform_source; + FreeString(minigame->fname); + InitializeMINIGAME(minigame,fform); +} + +/////////////////////////////////////////////////////////////////////////////// + +bool GetOriginalMINIGAME ( minigame_kmg_t *dest ) +{ + DASSERT(dest); + BZ2Manager_t *bz = GetCommonBZ2Manager(FF_KMG); + DASSERT(bz); + DASSERT( bz->size == sizeof(*dest) ); + if ( bz && bz->size == sizeof(*dest) ) + { + memcpy(dest,bz->data,sizeof(*dest)); + return true; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +static void limit_duration ( be16_t *dest ) +{ + DASSERT(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 ) + *dest = limitn; +} + +//----------------------------------------------------------------------------- + +static void dup_slot ( be16_t dest[10][11] ) +{ + const be16_t *src = dest[opt_kmg_arena]; + uint slot; + for ( slot = 0; slot < 10; slot++ ) + if ( slot != opt_kmg_arena ) + memcpy(dest[slot],src,sizeof(dest[slot])); +} + +//----------------------------------------------------------------------------- + +static void PatchMINIGAME ( minigame_kmg_t *dest ) +{ + DASSERT(dest); + + if ( opt_kmg_limit > 0 ) + { + limit_duration(dest->dur_balloon[0]); + limit_duration(dest->dur_coin[0]); + } + + if ( opt_kmg_arena >= 0 && opt_kmg_arena < 10 ) + { + dup_slot(dest->dur_balloon); + dup_slot(dest->off_0ec); + + dup_slot(dest->dur_coin); + dup_slot(dest->off_2b8); + dup_slot(dest->start_coins); + dup_slot(dest->max_coins); + dup_slot(dest->off_5c4); + dup_slot(dest->off_628); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void SetupBZ2MgrMINIGAME ( minigame_t * minigame, bool reload_bin ) +{ + DASSERT(minigame); + if ( reload_bin || memcmp(minigame->data.head.magic,KMG_MAGIC,4) ) + { + GetOriginalMINIGAME(&minigame->data); + PatchMINIGAME(&minigame->data); + } +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// ScanRawMINIGAME() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +enumError ScanRawMINIGAME +( + minigame_t * minigame, // MINIGAME data structure + bool init_minigame, // true: initialize 'minigame' first + const void * data, // data to scan + uint data_size // size of 'data' +) +{ + DASSERT(minigame); + if (init_minigame) + InitializeMINIGAME(minigame,FF_KMG); + + if ( !data || data_size != sizeof(minigame->data) ) + { + SetupBZ2MgrMINIGAME(minigame,true); + return ERROR0(ERR_INVALID_DATA, + "Invalid file size (%u but not %zu bytes: %s\n", + data_size, sizeof(minigame->data), minigame->fname ); + } + memcpy(&minigame->data,data,sizeof(minigame->data)); + PatchMINIGAME(&minigame->data); + return ERR_OK; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// ScanTextMINIGAME() helpers /////////////// +/////////////////////////////////////////////////////////////////////////////// + +enum +{ + MINIGAME_IGNORE, + MINIGAME_SETUP, + MINIGAME_PARAMETERS, +}; + +//----------------------------------------------------------------------------- + +static const KeywordTab_t minigame_section_name[] = +{ + { MINIGAME_IGNORE, "END", 0, 0 }, + { MINIGAME_SETUP, "SETUP", 0, 0 }, + { MINIGAME_PARAMETERS, "PARAMETERS", 0, 0 }, + { 0,0,0,0 } +}; + +/////////////////////////////////////////////////////////////////////////////// + +static enumError ScanTextSETUP +( + minigame_t * minigame, // MINIGAME data structure + ScanInfo_t * si // valid data +) +{ + DASSERT(minigame); + 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*)&minigame->revision,1,0); + si->init_revision = si->cur_file->revision = minigame->revision; + DefineIntVar(&si->gvar,"REVISION$SETUP",minigame->revision); + DefineIntVar(&si->gvar,"REVISION$ACTIVE",minigame->revision); + } + else + GotoEolSI(si); + CheckEolSI(si); + } + + CheckLevelSI(si); + return ERR_OK; +} + +/////////////////////////////////////////////////////////////////////////////// + +static enumError ScanTextPARAMETERS +( + minigame_t * minigame, // MINIGAME data structure + ScanInfo_t * si // valid data +) +{ + DASSERT(minigame); + 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 + { + int abbrev_count; + const KeywordTab_t *par = ScanKeyword(&abbrev_count,name,minigame_param_list); + if ( !par || abbrev_count ) + { + // WARNING + GotoEolSI(si); + continue; + } + + const uint offset = par->id; + u16 *dest = (u16*)( (u8*)&minigame->data + offset ); + ScanBE16SI(si,dest,1,0); + } + CheckEolSI(si); + } + + CheckLevelSI(si); + return ERR_OK; +} + + +/////////////////////////////////////////////////////////////////////////////// + +static enumError ScanTextTABLE +( + minigame_t * minigame, // MINIGAME data structure + ScanInfo_t * si, // valid data + const KeywordTab_t * cmd // valid section pointer +) +{ + DASSERT(minigame); + DASSERT(si); + DASSERT(cmd); + + for(;;) + { + char ch = NextCharSI(si,true); + if ( !ch || ch == '[' ) + break; + + if ( ch == '@' ) + { + ScanParamSI(si,0); + continue; + } + + ScanFile_t *sf = si->cur_file; + + long slot; + enumError err = ScanUValueSI(si,&slot,0); + if (err) + break; + if ( slot >= 10 ) + { + ccp eol = FindNextLineFeedSI(si,true); + if ( si->no_warn <= 0 ) + ERROR0(ERR_WARNING, + "Slot must be between 0 and 9: [%s @%u]: %.*s\n", + sf->name, sf->line, (int)(eol-sf->ptr), sf->ptr ); + sf->ptr = eol; + continue; + } + + u16 *dest = (u16*)( (u8*)&minigame->data + cmd->id ) + slot * 11; + uint idx; + for ( idx = 0; idx < 11; idx++ ) + { + ch = NextCharSI(si,false); + if (!ch) + break; + + long val; + err = ScanUValueSI(si,&val,0); + if (err) + break; + *dest++ = htons(val); + } + CheckEolSI(si); + } + + return ERR_OK; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// ScanTextMINIGAME() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +enumError ScanTextMINIGAME +( + minigame_t * minigame, // MINIGAME data structure + bool init_minigame, // true: initialize 'minigame' first + const void * data, // data to scan + uint data_size, // size of 'data' + file_format_t fform // file format +) +{ + DASSERT(minigame); + PRINT("ScanTextMINIGAME(init=%d)\n",init_minigame); + + if (init_minigame) + InitializeMINIGAME(minigame,FF_KMG_TXT); + else + { + minigame->fform_source = FF_KMG_TXT; + SetupBZ2MgrMINIGAME(minigame,true); + } + + ScanInfo_t si; + InitializeSI(&si,data,data_size,minigame->fname,minigame->revision); + si.predef = SetupVarsCOMMON(); + + enumError max_err = ERR_OK; + minigame->is_pass2 = false; + + for(;;) + { + PRINT("----- SCAN MINIGAME SECTIONS, PASS%u ...\n",minigame->is_pass2+1); + + max_err = ERR_OK; + si.no_warn = !minigame->is_pass2; + si.total_err = 0; + DefineIntVar(&si.gvar, "$PASS", minigame->is_pass2+1 ); + + for(;;) + { + char ch = NextCharSI(&si,true); + if (!ch) + break; + + if ( ch != '[' ) + { + NextLineSI(&si,true,false); + continue; + } + ResetLocalVarsSI(&si,minigame->revision); + + si.cur_file->ptr++; + char name[20]; + ScanNameSI(&si,name,sizeof(name),true,true,0); + noPRINT("--> pass=%u: #%04u: %s\n",minigame->is_pass2+1,si.cur_file->line,name); + + int abbrev_count; + const KeywordTab_t *cmd = ScanKeyword(&abbrev_count,name,minigame_section_name); + if ( !cmd || abbrev_count ) + { + cmd = ScanKeyword(&abbrev_count,name,minigame_table_list); + if ( cmd && !abbrev_count ) + { + while ( cmd > minigame_table_list && cmd[-1].id == cmd->id ) + cmd--; + NextLineSI(&si,false,false); + enumError err = ScanTextTABLE(minigame,&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 MINIGAME_SETUP: + err = ScanTextSETUP(minigame,&si); + break; + + case MINIGAME_PARAMETERS: + err = ScanTextPARAMETERS(minigame,&si); + break; + + default: + // ignore all other section without any warnings + break; + } + + if ( max_err < err ) + max_err = err; + } + + if (minigame->is_pass2) + break; + + minigame->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(ScanTextMINIGAME) = %u (errcount=%u)\n", max_err, si.total_err ); + ResetSI(&si); + + return max_err; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// MINIGAME: scan and load /////////////// +/////////////////////////////////////////////////////////////////////////////// + +enumError ScanMINIGAME +( + minigame_t * minigame, // MINIGAME data structure + bool init_minigame, // true: initialize 'minigame' first + const void * data, // data to scan + uint data_size // size of 'data' +) +{ + DASSERT(minigame); + + enumError err; +// [[analyse-magic]] + const file_format_t fform = GetByMagicFF(data,data_size,data_size); + switch (fform) + { + case FF_KMG: + err = ScanRawMINIGAME(minigame,init_minigame,data,data_size); + break; + + case FF_KMG_TXT: + err = ScanTextMINIGAME(minigame,init_minigame,data,data_size,fform); + break; + + default: + if (init_minigame) + InitializeMINIGAME(minigame,0); + return ERROR0(ERR_INVALID_DATA, + "No MINIGAME file: %s\n", minigame->fname ? minigame->fname : "?"); + } + + return err; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +enumError LoadMINIGAME +( + minigame_t * minigame, // MINIGAME data structure + bool init_minigame, // true: initialize 'minigame' first + ccp fname, // valid pointer to filenname + bool ignore_no_file // ignore if file does not exists + // and return warning ERR_NOT_EXISTS +) +{ + DASSERT(minigame); + DASSERT(fname); + if (init_minigame) + InitializeMINIGAME(minigame,0); + else + ResetMINIGAME(minigame); + + //--- load and scan data + + raw_data_t raw; + enumError err = LoadRawData(&raw,true,fname,0,ignore_no_file,0); + if (!err) + { + minigame->fname = raw.fname; + raw.fname = 0; + err = ScanMINIGAME(minigame,false,raw.data,raw.data_size); + } + + ResetRawData(&raw); + return err; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// SaveRawMINIGAME() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +enumError SaveRawMINIGAME +( + minigame_t * minigame, // pointer to valid MINIGAME + ccp fname, // filename of destination + bool set_time // true: set time stamps +) +{ + DASSERT(minigame); + DASSERT(fname); + + PRINT("SaveRawMINIGAME(%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,&minigame->fatt,0); + + const uint size = sizeof(minigame->data); + if ( fwrite(&minigame->data,1,size,F.f) != size ) + FILEERROR1(&F,ERR_WRITE_FAILED,"Write failed: %s\n",fname); + return ResetFile(&F,set_time); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// SaveTextMINIGAME() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +enumError SaveTextMINIGAME +( + const minigame_t * minigame, // pointer to valid MINIGAME + 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(minigame); + DASSERT(fname); + PRINT("SaveTextMINIGAME(%s,%d)\n",fname,set_time); + + BZ2Manager_t *bz = GetCommonBZ2Manager(FF_KMG); + + + //--- open file + + File_t F; + enumError err = CreateFileOpt(&F,true,fname,testmode,minigame->fname); + if ( err > ERR_WARNING || !F.f ) + return err; + SetFileAttrib(&F.fatt,&minigame->fatt,0); + + + //--- print header + syntax info + + const bool explain = print_header && !brief_count && !export_count; + if (explain) + fputs(text_minigame_info_cr,F.f); + else + fputs(text_minigame_head_cr,F.f); + + const bool tiny = brief_count > 1 || export_count; + if (!tiny) + fprintf(F.f,text_minigame_setup_cr, + tool_name, SYSTEM, VERSION, REVISION_NUM, DATE ); + + + //--- print parameters + + bool sect_head_done = false; + int last_mode = -1; + uint active_offset = ~0; + + const KeywordTab_t *par; + for ( par = minigame_param_list; par->name1; par++ ) + { + const uint offset = par->id; + if ( active_offset == offset ) // skip entries for same parameter + continue; + active_offset = offset; + + const s16 val = be16((u8*)&minigame->data+offset); + const s16 orig = be16(bz->data+offset); + if ( !minimize || val != orig ) + { + if (!sect_head_done) + { + sect_head_done = true; + fputs( brief_count < 2 ? section_sep : "\r\n", F.f ); + fprintf(F.f,text_minigame_param_cr,REVISION_NUM); + } + + if ( last_mode != par->opt ) + { + last_mode = par->opt; + fprintf(F.f,"\r\n# %s\r\n",minigame_param_title[last_mode]); + } + ccp name = par->name2 ? par->name2 : par->name1; + const int tablen = (39-strlen(name))/8; + fprintf(F.f, "%s%.*s=%6d # orig:%6d%s\r\n", + name, tablen > 1 ? tablen : 1, Tabs20, + val, orig, val == orig || minimize ? "" : " DIFFER!" ); + } + } + + + //--- print tables + + const uint slot_size = 11*2; + const uint table_size = 10*slot_size; + + for ( par = minigame_table_list; par->name1; par++ ) + { + const uint offset = par->id; + if ( active_offset == offset ) // skip entries for same section + continue; + active_offset = offset; + + const u8 *val = (u8*)&minigame->data + offset; + const u8 *orig = bz->data + offset; + if ( !minimize || memcmp(val,orig,table_size) ) + { + fputs( brief_count < 2 ? section_sep : "\r\n", F.f ); + fprintf(F.f, text_minigame_table_cr, + par->name2 ? par->name2 : par->name1, + offset, REVISION_NUM ); + // [[2do]] ??? table dependent info + fputs(text_minigame_table_head_cr,F.f); + + uint slot; + for ( slot = 0; slot < 10; slot++ ) + { + const int differ = memcmp(val,orig,slot_size); + if ( !minimize || differ ) + { + fprintf(F.f,"%5u ",slot); + uint pl; + for ( pl = 0; pl < 11; pl++, val += 2 ) + fprintf(F.f," %4d",be16(val)); + fprintf(F.f," # A%02u %s\r\n", + arena_info[slot].def_slot, arena_info[slot].name_en ); + + if (differ) + { + fputs("#ORIG:",F.f); + val -= slot_size; + for ( pl = 0; pl < 11; pl++, val += 2, orig += 2 ) + if ( be16(val) == be16(orig) ) + fputs(" .",F.f); + else + fprintf(F.f," %4d",be16(orig)); + fputs("\r\n",F.f); + if (minimize) + fputs("\r\n",F.f); + } + else + orig += slot_size; + } + else + { + val += slot_size; + orig += slot_size; + } + } + } + } + + + //--- terminate + + fputs( brief_count < 2 ? section_end :"\r\n", F.f ); + ResetFile(&F,set_time); + return ERR_OK; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// scan options /////////////// +/////////////////////////////////////////////////////////////////////////////// + +int ScanOptKmgLimit ( ccp arg ) +{ + char *end; + const long num = str2l(arg,&end,10); + if ( end == arg || *end ) + { + ERROR0(ERR_SYNTAX,"Invalid argumant for option --kmg-limit: '%s'\n",arg); + return 1; + } + + opt_kmg_limit = num < 0 ? 0 : num > 0xffff ? 0xffff : num; + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +int ScanOptKmgCopy ( ccp arg ) +{ + static const KeywordTab_t keytab[] = + { + { 0, "0", "A12", 0 }, + { 1, "1", "A11", 0 }, + { 2, "2", "A14", 0 }, + { 3, "3", "A13", 0 }, + { 4, "4", "A15", 0 }, + { 5, "5", "A24", 0 }, + { 6, "6", "A25", 0 }, + { 7, "7", "A21", 0 }, + { 8, "8", "A22", 0 }, + { 9, "9", "A23", 0 }, + { -1, "-1", "OFF", 0 }, + {0,0,0,0} + }; + + if ( !arg || !*arg ) + { + opt_kmg_arena = -1; + return 0; + } + + ccp p1 = strrchr(arg,'['); + if (p1) + { + ccp p2 = strchr(++p1,']'); + if (p2) + { + while ( p1 < p2 ) + { + ccp comma = strchr(p1,','); + if ( !comma || comma > p2 ) + comma = p2; + uint len = comma - p1; + char name[10]; + if ( ( *p1 == 'a' || *p1 == 'A' ) && len < sizeof(name) ) + { + memcpy(name,p1,len); + name[len] = 0; + const KeywordTab_t *key = ScanKeyword(0,name,keytab); + if (key) + { + opt_kmg_arena = key->id; + return 0; + } + } + p1 = comma+1; + } + return 0; + } + } + + int abbrev; + const KeywordTab_t *key = ScanKeyword(&abbrev,arg,keytab); + if (!key) + { + PrintKeywordError(keytab,arg,abbrev,0, + "keyword for option --kmg-arena"); + return 1; + } + opt_kmg_arena = key->id; + return 0; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// END /////////////// +/////////////////////////////////////////////////////////////////////////////// + -- cgit v1.3.1