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-kmp.h | 2846 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2846 insertions(+) create mode 100644 project/src/lib-kmp.h (limited to 'project/src/lib-kmp.h') diff --git a/project/src/lib-kmp.h b/project/src/lib-kmp.h new file mode 100644 index 0000000..c3b583c --- /dev/null +++ b/project/src/lib-kmp.h @@ -0,0 +1,2846 @@ + +/*************************************************************************** + * _______ _______ _______ * + * | ___ |____ | ___ | * + * | | |_| / /| | |_| * + * | |_____ / / | |_____ * + * |_____ | / / |_____ | * + * _ | | / / _ | | * + * | |___| |/ /____| |___| | * + * |_______|_______|_______| * + * * + * 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 * + * * + ***************************************************************************/ + +// all about BMG files: +// http://wiki.tockdom.de/index.php?title=BMG + +/////////////////////////////////////////////////////////////////////////////// + +#ifndef SZS_LIB_KMP_H +#define SZS_LIB_KMP_H 1 + +#include "lib-std.h" +#include "lib-object.h" +#include "lib-lecode.h" + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// definitions /////////////// +/////////////////////////////////////////////////////////////////////////////// + +#define KMP_MAGIC "RKMD" +#define KMP_MAGIC_NUM 0x524B4D44 + +#define KMP_TEXT_MAGIC "#KMP" +#define KMP_TEXT_MAGIC_NUM 0x234b4d50 + +#define KMP_MAX_PH_LINK 6 +#define KMP_MAX_GROUP 255 +#define KMP_MAX_POINT 255 +#define KMP_MAX_NAME_LEN 20 + +#define KMP_DIST_HINT 10.0 +#define KMP_DIST_WARN 1.0 + +#define GOBJ_ELINE_CONTROL 0x014 +#define GOBJ_ICE 0x017 +#define GOBJ_ITEMBOX 0x065 +#define GOBJ_SUN_DS 0x072 +#define GOBJ_COIN 0x073 +#define GOBJ_HEYHO_SHIP 0x0ce +#define GOBJ_HEYHO_BALL 0x0ea +#define GOBJ_OBAKE_BLOCK 0x13c +#define GOBJ_PYLON01 0x144 + +#define KMP_COIN_IS_INVALID 50 + +//----------------------------------------------------------------------------- +// +// XPF ID map: +// +// 0000-03ff : Real objects +// 1000-13ff : Disabled objects +// +// 1000-1fff : reserved for predifined conditions +// 1000-102d : hard coded conditions +// 1100-18ff : >FREE (8 maps of 8 bits) +// 1900-1903 : developer conditions +// 1a00-1dff : >FREE (4 maps of 8 bits) +// 1e00-1e7f : engine classes +// 1f00-1fff : random scenarios +// +// 2000-3fff : Definition objects type BITS +// 4000-5fff : Definition objects type OR +// 6000-7fff : Definition objects type AND +// +// 8000-dfff : >FREE (6 maps of 12 bits) +// +// e000-e3ff : test conditions (debug version only) +// +// f000-ffff : >FREE (1 map of 12 bits) +// +//----------------------------------------------------------------------------- + +// KMP/GOBJ/obj_id +#define GOBJ_M_OBJECT 0x03ff +#define GOBJ_M_FLAGS ( 0xffff & ~GOBJ_M_OBJECT ) + +#define GOBJ_BIT_LECODE 12 // maybe enabled by lecode +#define GOBJ_BIT_CONDITION 12 // indicator bit for predefinied condition + +#define GOBJ_M_LECODE (1< POTI + /*0x04*/ u16 came_speed; // unsure! + /*0x06*/ u16 zoom_speed; // zoom speed in units per 100/60 sec + /*0x08*/ u16 viewpt_speed; // view point speed in units per 100/60 sec + /*0x0a*/ u16 unknown_0x0a; + /*0x0c*/ float32 position[3]; // camera position + /*0x18*/ float32 rotation[3]; // rotation? (always 0) + /*0x24*/ float32 zoom_begin; // zoom value begin + /*0x28*/ float32 zoom_end; // zoom value end + /*0x2c*/ float32 viewpt_begin[3];// view point begin + /*0x38*/ float32 viewpt_end[3]; // view point end + /*0x44*/ float32 time; // active time of the camera + /*0x48*/ +} +__attribute__ ((packed)) kmp_came_entry_t; + +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_jgpt_entry_t]] + +typedef struct kmp_jgpt_entry_t +{ + // Jugem points: Respawn positions + + /*0x00*/ float32 position[3]; + /*0x0c*/ float32 rotation[3]; + /*0x18*/ s16 id; + /*0x1a*/ u16 effect; + /*0x1c*/ +} +__attribute__ ((packed)) kmp_jgpt_entry_t; + +// [[kmp_cnpt_entry_t]] Cannon Points: Cannon target positions +typedef kmp_jgpt_entry_t kmp_cnpt_entry_t; + +// [[kmp_mspt_entry_t]] +// After battles and competitions have ended the players are placed on this point(s) +typedef kmp_jgpt_entry_t kmp_mspt_entry_t; + +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_stgi_entry_t]] + +typedef struct kmp_stgi_entry_t +{ + // Stage Information + + /*0x00*/ u8 lap_count; // XML suggest but ignored + /*0x01*/ u8 pole_pos; // 0:left, 1:right + /*0x02*/ u8 narrow_start; // 0:normal, 1:closer together + /*0x03*/ u8 enable_lens_flare; // 0:off, 1:enabled + /*0x04*/ u32 flare_color; // 0xe6e6e6 or 0xffffff + /*0x08*/ u8 flare_alpha; // alpha channel (transparency) + /*0x09*/ u8 unknown_09; // always 0 + /*0x0a*/ u16 speed_mod; // nintendo: always 0 + // custom: MSB of speed modifier + /*0x0c*/ +} +__attribute__ ((packed)) kmp_stgi_entry_t; + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// Wim0 support /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_wim0_sect_id]] + +typedef enum kmp_wim0_sect_id +{ + W0ID_END = 0, + W0ID_VERSION = 'V' << 8 | 'e', +// W0ID_AUTO_CONNECT = 'A' << 8 | 'C', +} +kmp_wim0_sect_id; + +extern const KeywordTab_t Wim0SectionName[]; + +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_wim0_format_t]] + +typedef enum kmp_wim0_format_t +{ + W0F_UNKNOWN = 0, + W0F_BINARY, + W0F_TEXT, + W0F__N +} +kmp_wim0_format_t; + +extern ccp Wim0FormatName[]; + +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_wim0_t]] + +typedef struct kmp_wim0_t +{ + u8 *data; // uncompressed data, alloced + uint used; // number of used bytes + uint size; // number of alloced bytes + + u8 *bz2data; // NULL or bzip2 data, alloced + uint bz2size; // size of bz2data +} +__attribute__ ((packed)) kmp_wim0_t; + +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_wim0_sect_t]] + +typedef struct kmp_wim0_sect_t +{ + u16 id; // one of kmp_wim0_sect_id + u16 words; // number of words (2=bytes) of data + u16 data[]; // data, always ALIGN(2) +} +__attribute__ ((packed)) kmp_wim0_sect_t; + +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_wim0_info_t]] + +typedef struct kmp_wim0_info_t +{ + kmp_wim0_sect_id sect_id; // one of kmp_wim0_sect_id + uint index; // 0..N: Index of section + uint offset; // Offset relative to first WIM0 section + char name[8]; // either key->name1 or "0x####" + kmp_wim0_format_t format; // format of data, fallback to W0F_UNKNOWN + + const + kmp_wim0_sect_t *sect; // pointer to section + const u8 *data; // pointer to section data + uint size; // size of section data + +} +__attribute__ ((packed)) kmp_wim0_info_t; + +/////////////////////////////////////////////////////////////////////////////// + +void InitializeWim0 ( kmp_wim0_t *w0 ); +void ResetWim0 ( kmp_wim0_t *w0 ); +void * NeedWim0 ( kmp_wim0_t *w0, uint size, uint align ); +enumError CompressWim0 ( kmp_wim0_t *w0 ); +enumError DecompressWim0 ( kmp_wim0_t *w0 ); + +kmp_wim0_sect_t * AppendSectionWim0 +( + kmp_wim0_t *w0, // data structure + kmp_wim0_sect_id sect_id, // section id + cvp data, // pointer to data + uint size // size of data in bytes +); + +bool GetFirstSectionWim0 +( + kmp_wim0_info_t *info, // store result here (never NULL) + const struct kmp_t *kmp // pointer to valid KMP +); + +bool GetNextSectionWim0 +( + kmp_wim0_info_t *info, // update result (never NULL) + const struct kmp_t *kmp // pointer to valid KMP +); + +const kmp_wim0_sect_t * FindSectionWim0 +( + // return NULL or a pointer to found kmp_wim0_sect_t + + kmp_wim0_info_t *info, // not NULL: store extended result here + const struct kmp_t *kmp, // pointer to valid KMP + kmp_wim0_sect_id sect_id // section id to search +); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// kmp_section_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_section_t]] + +typedef struct kmp_section_t +{ + int sect; // -1: invalid, -2:unknown, else: kmp_entry_t + uint index; // index of analyse section + kmp_list_head_t *ptr; // pointer to section + uint size; // size of section +} +kmp_section_t; + +//----------------------------------------------------------------------------- + +bool AnalyseSectionKMP +( + // return true if known section found + + kmp_section_t *ks, // store result here + const void *data, // KMP raw data to scan + uint size, // size of 'data' + uint index // index of section to analyse +); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// route types /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_rtype_mode]] + +typedef enum kmp_rtype_mode +{ + KMP_RT_AUTO, // route type detected automatically + KMP_RT_ROUTE, // is real route + KMP_RT_DISPATCH, // is dispatch point + +} +__attribute__ ((packed)) kmp_rtype_mode; + +extern const KeywordTab_t kmp_rtype_name[]; + +//----------------------------------------------------------------------------- +// [[kmp_rtype_info_t]] + +typedef struct kmp_rtype_info_t +{ + // section type + uint sect_ph; // PH section index + uint sect_pt; // PT section index + + // basic stats + uint n_group; // number of route groups + uint n_point; // number of route points + + // analysis + uint n_route0; // number of routes with 0 points (ERROR) + uint n_route1; // number of real routes with only one points + uint n_route2; // number of real routes with >1 points + uint n_dispatch; // number of dispatch points (=not real route) +} +kmp_rtype_info_t; + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// kmp_group_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_group_name_t]] + +typedef char kmp_group_name_t[KMP_MAX_NAME_LEN+1]; + +//----------------------------------------------------------------------------- +// [[kmp_gopt_t]] + +typedef struct kmp_gopt_t +{ + u8 rclass; // route class (for incomming connections) + u8 lclass; // link class (for outgoing connections) + u8 min_links; // minimal links to auto-add + u8 max_links; // maxmal links to auto-add + double distance; // if >0: max distance for N>min +} +kmp_gopt_t; + +//----------------------------------------------------------------------------- +// [[kmp_gopt2_t]] + +typedef struct kmp_gopt2_t +{ + kmp_rtype_mode rtype_user; // route type set by user + kmp_rtype_mode rtype_active; // active route type + kmp_oneway_mode ac_oneway; // oneway mode for auto-connect + u8 setting[2]; // values of bytes at offeset 0x0e and 0x0f + + kmp_gopt_t prev; // values for first point (prev link) + kmp_gopt_t next; // values for last point (next link) +} +kmp_gopt2_t; + +//----------------------------------------------------------------------------- +// [[kmp_group_elem_t]] + +typedef struct kmp_group_elem_t +{ + kmp_group_name_t name; // name of eleemns + kmp_oneway_mode oneway; // oneway mode + +} kmp_group_elem_t; + +//----------------------------------------------------------------------------- +// [[kmp_group_t]] + +typedef struct kmp_group_t +{ + int first_index; // index of first point + int last_index; // index of last point + bool no_rotate; // true: do not rotate links + + kmp_group_name_t name; // name of group + kmp_group_elem_t prev[KMP_MAX_PH_LINK]; // prev-link names and status + kmp_group_elem_t next[KMP_MAX_PH_LINK]; // next-link names and status + +} kmp_group_t; + +//----------------------------------------------------------------------------- +// [[kmp_group_list_t]] + +typedef struct kmp_group_list_t +{ + struct kmp_t *kmp; // related kmp, never NULL + struct kmp_ph_t *ph; // related ph info, never NULL + + uint used; // used groups + kmp_group_t group[KMP_MAX_GROUP]; // list with groups + char selector; // '!' selector + bool have_options; // >0 at least one option detected + Line_t line; // '$LINE' settings + +} kmp_group_list_t; + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// kmp_rtobj_t, kmp_rtobj_list_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_rtobj_t]] + +typedef struct kmp_rtobj_t +{ + u16 obj; // object to use + float3 shift; // add to position + float3 scale; // store as 'scale' factor + float3 rotate; // add to rotation + +} kmp_rtobj_t; + +//----------------------------------------------------------------------------- +// [[kmp_rtobj_list_t]] + +typedef struct kmp_rtobj_list_t +{ + kmp_rtobj_t rtobj; // object to use + u16 index; // index to POTI group + +} kmp_rtobj_list_t; + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// kmp_mode_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_mode_t]] + +typedef enum kmp_mode_t +{ + //--- general options + + KMPMD_FORCE = 0x00000001, // like --force: accept little repairable issues + KMPMD_M_GENERAL = KMPMD_FORCE, + + + //--- KMP patching options + + KMPMD_NEW = 0x00000010, // create a new KMP file even if nothing changed + KMPMD_RM_SPCITEM = 0x00000020, // remove special items + KMPMD_REVERSE = 0x00000040, // reverse the track order + KMPMD_MAX_LAPS = 0x00000080, // set LAPS only if larger + + KMPMD_1_LAP = 0x00000100, // set lap count to #1 + KMPMD_2_LAPS = 0x00000200, // set lap count to #2 + KMPMD_3_LAPS = 0x00000300, // set lap count to #3 + KMPMD_4_LAPS = 0x00000400, // set lap count to #4 + KMPMD_5_LAPS = 0x00000500, // set lap count to #5 + KMPMD_6_LAPS = 0x00000600, // set lap count to #6 + KMPMD_7_LAPS = 0x00000700, // set lap count to #7 + KMPMD_8_LAPS = 0x00000800, // set lap count to #8 + KMPMD_9_LAPS = 0x00000900, // set lap count to #9 + KMPMD_M_LAPS = 0x00000f00, + KMPMD_SHIFT_LAPS = 8, + + KMPMD_POLE_LEFT = 0x00001000, // set pole position to left side + KMPMD_POLE_RIGHT = 0x00002000, // set pole position to right side + KMPMD_SP_WIDE = 0x00004000, // set start mode 'wide' + KMPMD_SP_NARROW = 0x00008000, // set start mode 'narrow' + KMPMD_M_POLE = KMPMD_POLE_LEFT + | KMPMD_POLE_RIGHT, + KMPMD_M_STARTPOS = KMPMD_SP_WIDE + | KMPMD_SP_NARROW, + KMPMD_M_STGI = KMPMD_M_POLE + | KMPMD_M_STARTPOS + | KMPMD_M_LAPS, + + KMPMD_FIX_CKPH = 0x00010000, // automatic calculations of section CKPH + KMPMD_FIX_ENPH = 0x00020000, // automatic calculations of section ENPH + KMPMD_FIX_ITPH = 0x00040000, // automatic calculations of section ITPH + KMPMD_FIX_CKNEXT = 0x00080000, // CKPT: auto calc of 'prev' and 'next' + KMPMD_FIX_CKJGPT = 0x00100000, // CKPT: fix invalid JGPT indices + KMPMD_M_FIX_PH = KMPMD_FIX_CKPH + | KMPMD_FIX_ENPH + | KMPMD_FIX_ITPH, + KMPMD_M_FIX_CK = KMPMD_FIX_CKPH + | KMPMD_FIX_CKNEXT + | KMPMD_FIX_CKJGPT, + KMPMD_M_FIX_ALL = KMPMD_M_FIX_PH + | KMPMD_M_FIX_CK, + + KMPMD_MASK_PFLAGS = 0x00200000, // mask presence flags by 0x3f & clear padding + KMPMD_RM_LECODE = 0x00400000, // remove LE-CODE objects of section GOBJ + KMPMD_PURGE_GOBJ = 0x00800000, // remove invalid objects of section GOBJ except def-obj + KMPMD_FULL_DEFOBJ = 0x01000000, // Display definitions objects as full object + KMPMD_M_XPF = KMPMD_MASK_PFLAGS + | KMPMD_RM_LECODE + | KMPMD_PURGE_GOBJ + | KMPMD_FULL_DEFOBJ, + + //--- dump options + + KMPMD_DUMP_CLASS = 0x02000000, // dump class list at end of section if not empty + KMPMD_DUMP_ONEWAY = 0x04000000, // dump oneway list at end of section if not empty + KMPMD_M_DUMP_ALL = KMPMD_DUMP_CLASS + | KMPMD_DUMP_ONEWAY, + + + //--- hidden options + + KMPMD_LOG = 0x08000000, // enable kmp trace log to stdout + KMPMD_SILENT = 0x10000000, // disable logging of patching operations + KMPMD_INPLACE = 0x20000000, // force inplace patching + KMPMD_M_HIDDEN = KMPMD_LOG + | KMPMD_SILENT + | KMPMD_INPLACE, + + KMPMD_F_HIDE = 0x40000000, // help flag to hide + + + //--- tiny modes + + KMPMD_S_TINY = 32, + KMPMD_TINY_0 = 0ull << KMPMD_S_TINY, // TINY levels + KMPMD_TINY_1 = 1ull << KMPMD_S_TINY, + KMPMD_TINY_2 = 2ull << KMPMD_S_TINY, + KMPMD_TINY_3 = 3ull << KMPMD_S_TINY, + KMPMD_TINY_4 = 4ull << KMPMD_S_TINY, + KMPMD_TINY_5 = 5ull << KMPMD_S_TINY, + KMPMD_TINY_6 = 6ull << KMPMD_S_TINY, + KMPMD_TINY_7 = 7ull << KMPMD_S_TINY, + KMPMD_M_TINY = KMPMD_TINY_7, + + KMPMD_RM_EMPTY = KMPMD_TINY_1 << 3, // skip empty KMP sections + KMPMD_MINIMIZE = KMPMD_RM_EMPTY << 1, // minimize KMP by reordering + + //--- tests + + KMPMD_TEST1 = KMPMD_MINIMIZE << 1, // reserved for testing + KMPMD_TEST2 = KMPMD_TEST1 << 1, // reserved for testing + KMPMD_M_TEST = KMPMD_TEST1 + | KMPMD_TEST2, + + //--- summaries + + KMPMD_M_DEFAULT = 0, // default settings + + KMPMD_M_PATCH = KMPMD_NEW // patching flags + | KMPMD_RM_SPCITEM + | KMPMD_REVERSE + | KMPMD_MAX_LAPS + | KMPMD_M_STGI + | KMPMD_M_FIX_ALL + | KMPMD_M_XPF + | KMPMD_M_TINY + | KMPMD_RM_EMPTY + | KMPMD_MINIMIZE + | KMPMD_M_TEST, + + KMPMD_M_ALL = KMPMD_M_GENERAL // all relevant bits + | KMPMD_M_PATCH + | KMPMD_M_DUMP_ALL + | KMPMD_M_HIDDEN, + + KMPMD_M_PRINT = KMPMD_M_ALL // all relevant bits for obj output + & ~KMPMD_M_HIDDEN, +} +kmp_mode_t; + +//----------------------------------------------------------------------------- +// [[kmp_diff_mode_t]] + +typedef enum kmp_diff_mode_t +{ + KDMD_NONE = 0, + + KDMD_KTPT = 1 << KMP_KTPT, + KDMD_ENPT = 1 << KMP_ENPT, + KDMD_ENPH = 1 << KMP_ENPH, + KDMD_ITPT = 1 << KMP_ITPT, + KDMD_ITPH = 1 << KMP_ITPH, + KDMD_CKPT = 1 << KMP_CKPT, + KDMD_CKPH = 1 << KMP_CKPH, + KDMD_GOBJ = 1 << KMP_GOBJ, + KDMD_POTI = 1 << KMP_POTI, + KDMD_AREA = 1 << KMP_AREA, + KDMD_CAME = 1 << KMP_CAME, + KDMD_JGPT = 1 << KMP_JGPT, + KDMD_CNPT = 1 << KMP_CNPT, + KDMD_MSPT = 1 << KMP_MSPT, + KDMD_STGI = 1 << KMP_STGI, + KDMD_M_SECTION = (1<0: enabled + kmp_class_mode default_class; // default class + kmp_ac_mode ac_mode; // one of KMP_AC_* + kmp_ac_mode ac_flags; // bitfield of KMP_ACF_* + u16 mask[2]; // (ENPH+ITPH only) + + // oneway support + uint oneway_used; // number of used elements + uint oneway_size; // number of alloced elements + u16 *oneway_list; // list of elements (from<<8|to) + + // lists + ParamField_t class_name; // list with class names + kmp_gopt2_t gopt[KMP_MAX_GROUP]; // group options (ENPH+ITPH only) + + // [[obsolete]] -> replaced by 'kmp_t::index' + kmp_group_name_t gname[KMP_MAX_GROUP]; // group names of check points +} +kmp_ph_t; + +//----------------------------------------------------------------------------- + +void InitializePH ( kmp_ph_t *ph, uint sect_ph, uint sect_pt, uint ac_default ); +void ResetPH ( kmp_ph_t *ph ); + +void InsertOnewayPH ( kmp_ph_t *ph, u8 from, u8 to ); +bool FindOnewayPH ( const kmp_ph_t *ph, u8 from, u8 to ); +void SortOnewayPH ( const kmp_ph_t *ph ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct kmp_flag_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_flag_t]] // special settings for ENPT, ITPH and JGPT + +typedef struct kmp_flag_t +{ + u8 import; // >0: flags imported + u8 export; // >0: flag export enabled + + u8 mask; // any of KPFL_M_* + u8 flags[KMP_MAX_POINT]; // kmp_pt_flag_t +} +kmp_flag_t; + +//----------------------------------------------------------------------------- + +void InitializeKMPFlags ( kmp_flag_t * kf, u8 mask ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// kmp_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_t]] + +typedef struct kmp_t +{ + //--- base info + + ccp fname; // alloced filename of loaded file + FileAttrib_t fatt; // file attribute + file_format_t fform; // FF_KMP | FF_KMP_TXT + struct lex_info_t *lexinfo; // NULL or valid LEX info + + //--- error control: if >0: suppress warnings for ... + + int nowarn_format; // .. invalid file formats + + //--- data + + List_t dlist[KMP_N_SECT]; // data lists + List_t poti_point; // POTI points list + + int revision; // tool revision + u32 kmp_version; // unknown value if file header + u16 value[KMP_N_SECT+1]; // 'value' of section header + IsArena_t battle_mode; // one of ARENA_* + IndexList_t index[KMP_N_SECT]; // named indices + + char * info; // string behind last section + const u8 * max_scanned; // raw scanning: max scanned area + + //--- wim0 support + + kmp_wim0_sect_t *wim0_data; // NULL or (decompressed) data + uint wim0_size; // size of wim0_data in bytes + uint wim0_import_size; // 0 or total size of found WIM0 section + u8 wim0_import_bz2; // >0: found WIM0 section was bz2'ipped. + u8 wim0_export; // >0: create section WIM0 on export + + //--- support for PH sections + + kmp_ph_t ckph; + kmp_ph_t enph; + kmp_ph_t itph; + + //--- flags support + + kmp_flag_t enpt_flag; + kmp_flag_t itpt_flag; + kmp_flag_t jgpt_flag; + + //--- snap variables: if not VAR_UNSET + // => move each JGPT to next ENPT and and snap value + //--- priority: 'snap2' before 'snap' before 'hsnap' + + Var_t jgpt_snap2; // not VAR_UNSET: snap2 JGPT + Var_t cnpt_snap2; // not VAR_UNSET: snap2 CNPT + Var_t mspt_snap2; // not VAR_UNSET: snap2 MSPT + Var_t jgpt_snap; // not VAR_UNSET: snap JGPT + Var_t cnpt_snap; // not VAR_UNSET: snap CNPT + Var_t mspt_snap; // not VAR_UNSET: snap MSPT + Var_t jgpt_hsnap; // not VAR_UNSET: hsnap JGPT + Var_t cnpt_hsnap; // not VAR_UNSET: hsnap CNPT + Var_t mspt_hsnap; // not VAR_UNSET: hsnap MSPT + + //--- route objects (insert objects into KMP to show routes) + + kmp_rtobj_t rtobj; // predefined route object + kmp_rtobj_t rtobj_enpt; // >0: for each ENPT 1 object + kmp_rtobj_t rtobj_itpt; // >0: for each ITPT 1 object + kmp_rtobj_t rtobj_jgpt; // >0: for each JGPT 1 object + kmp_rtobj_t rtobj_cnpt; // >0: for each CNPT 1 object + kmp_rtobj_t rtobj_mspt; // >0: for each MSPT 1 object + kmp_rtobj_list_t rtobj_poti[50]; // objects for POTI routes + uint n_rtobj_poti; // number of valid elements + // in 'rtobj_poti[]' + //--- objects on check points + + int ckpt_object_mode; // view mode + int ckpt_object1; // object 1 + int ckpt_object2; // object 2 + Var_t ckpt_object1_scale; // scale of object 1 + Var_t ckpt_object2_scale; // scale of object 2 + float ckpt_object1_base; // y base of object 1 + float ckpt_object2_base; // y base of object 2 + + //--- special settings + + u8 ckpt_auto_respawn[KMP_MAX_POINT]; // >0: assign nearest JGPT + + int jgpt_auto_define; // >0 and valid section: auto define JGPT + float jgpt_auto_distance; // >0.0: define only if no other pt in distance + Var_t jgpt_auto_adjust; // add this vector to auto defined point + int jgpt_auto_remove; // >0: remove unused: 1=auto defined, 2=all + + //--- misc + + bool is_pass2; // true: KMP compiler runs pass2 + bool is_shrinked; // true: source is a shrinked KMP + bool multi_ckpt_mode_0_ok; // true: disable warnings about mode 0 + bool enable_fall_kcl; // true: enable 'fall_kcl' support + struct kcl_t *fall_kcl; // NULL or pointer to own fall-down kcl + + struct kmp_linfo_t *linfo; // NULL or link infos for 'linfo_sect' + kmp_entry_t linfo_sect; // section of 'linfo' + + const kmp_stgi_entry_t *stgi; // pointer to raw STGI section. + // only valid after ScanRawKMP() + // as long as source is valid too + + //--- raw data, created by CreateRawKMP() + + u8 * raw_data; // NULL or data + uint raw_data_size; // size of 'raw_data' + uint raw_head_size; // size of file header of 'raw_data' + +} kmp_t; + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// KMP interface /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void InitializeKMP ( kmp_t * kmp ); +void ResetKMP ( kmp_t * kmp ); +void ClearSectionsKMP ( kmp_t * kmp ); +const VarMap_t * SetupVarsKMP(); + +/////////////////////////////////////////////////////////////////////////////// + +enumError ScanRawKMP +( + kmp_t * kmp, // KMP data structure + bool init_kmp, // true: initialize 'kmp' first + const void * data, // data to scan + uint data_size // size of 'data' +); + +//----------------------------------------------------------------------------- + +enumError ScanTextKMP +( + kmp_t * kmp, // KMP data structure + bool init_kmp, // true: initialize 'kmp' first + const void * data, // data to scan + uint data_size // size of 'data' +); + +//----------------------------------------------------------------------------- + +enumError ScanKMP +( + kmp_t * kmp, // KMP data structure + bool init_kmp, // true: initialize 'kmp' first + const void * data, // data to scan + uint data_size, // size of 'data' + CheckMode_t mode // not NULL: call CheckKMP(mode) +); + +//----------------------------------------------------------------------------- + +enumError ScanRawDataKMP +( + kmp_t * kmp, // KMP data structure + bool init_kmp, // true: initialize 'kmp' first + struct raw_data_t * raw, // valid raw data + CheckMode_t mode // not NULL: call CheckKMP(mode) +); + +/////////////////////////////////////////////////////////////////////////////// + +enumError LoadKMP +( + kmp_t * kmp, // KMP data structure + bool init_kmp, // true: initialize 'kmp' first + ccp fname, // valid pointer to filenname + bool ignore_no_file, // ignore if file does not exists + // and return warning ERR_NOT_EXISTS + CheckMode_t mode // not NULL: call CheckKMP(mode) +); + +//----------------------------------------------------------------------------- + +enumError CreateRawKMP +( + kmp_t * kmp // pointer to valid KMP +); + +//----------------------------------------------------------------------------- + +enumError SaveRawKMP +( + kmp_t * kmp, // pointer to valid KMP + ccp fname, // filename of destination + bool set_time // true: set time stamps +); + +//----------------------------------------------------------------------------- + +enumError SaveTextKMP +( + const kmp_t * kmp, // pointer to valid KMP + ccp fname, // filename of destination + bool set_time // true: set time stamps +); + +/////////////////////////////////////////////////////////////////////////////// + +bool SortGOBJ +( + kmp_t * kmp, // pointer to valid KMP + int sort_mode // <=0: dont sort + // 1: group only + // 2: secondary sort by angle +); + +//----------------------------------------------------------------------------- + +bool TransformKMP +( + kmp_t * kmp // pointer to valid KMP +); + +//----------------------------------------------------------------------------- + +bool PatchKMP +( + kmp_t * kmp // pointer to valid KMP +); + +//----------------------------------------------------------------------------- + +bool PatchRawDataKMP +( + void * data, // data to scan + uint data_size // size of 'data' +); + +/////////////////////////////////////////////////////////////////////////////// + +int GetNextPointKMP +( + const kmp_t * kmp, // KMP data structure + uint sect, // KMP PT section index + int pt_index, // index of point, <0: add N + int sub_index, // index into 'next' + // -1: use 'pt_index+1' in a group + // find first valid at group end + // !-1 && KMP_CKPT: try to use 'next' link + bool unique, // return 'not_found_val' on duplicates + int not_found_val, // return this value, if next point not found + int *ret_pt_index, // not NULL: store fixed 'pt_index' here + int *ret_sub_index, // not NULL: store used sub index here + bool *ret_new_group, // not NULL: store true, if new group + const kmp_enph_entry_t **ret_ph // not NULL: store found ph-record +); + +/////////////////////////////////////////////////////////////////////////////// + +const kmp_enph_entry_t * FindPH +( + const kmp_t * kmp, // KMP data structure + uint sect, // KMP PT or PH section index + int pt_index, // index of point, <0: add N + int * res_ph_index // not NULL: store ph_index or -1 here +); + +/////////////////////////////////////////////////////////////////////////////// + +int CheckConvexCKPT +( + // returns + // -1: illegal index + // 0: convex + // 1: concave + + const kmp_t *kmp, // KMP data structure + uint ckpt1, // index of first check point (robust) + uint ckpt2, // index of second check point (robust) + double *min_distance // not NULL: store minimum distance here +); + +/////////////////////////////////////////////////////////////////////////////// + +void RenameGroupKMP +( + kmp_t * kmp, // KMP data structure + uint sect_ph, // ph section index + kmp_group_name_t * gname, // pointer to group name array + bool enable_dp // enable dispatch point support +); + +/////////////////////////////////////////////////////////////////////////////// + +void InsertLinkPH +( + u8 * vector, // insert into vector + u8 link, // link to insert + ScanInfo_t * si, // not NULL: print error message + ccp name, // NULL or name of line for error message + bool allow_dup // true: allow multiple links into same section +); + +/////////////////////////////////////////////////////////////////////////////// + +#define MAX_CLASS_NAMES 255 + +//----------------------------------------------------------------------------- + +void SetupClassNamePH +( + kmp_ph_t * ph // valid PH data structure +); + +//----------------------------------------------------------------------------- + +int InsertClassNamePH +( + // return 1..254 if found or set, 255 if list is full, -1 on error + + kmp_ph_t * ph, // valid PH data structure + ccp cname, // NULL or name of class + bool no_warn // TRUE: suppress warning about full list +); + +//----------------------------------------------------------------------------- + +int FindClassNamePH +( + // return -1, if not found, 1..254 else + + kmp_ph_t * ph, // valid PH data structure + ccp cname // NULL or name of class +); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// KMP itembox support /////////////// +/////////////////////////////////////////////////////////////////////////////// + +typedef struct Itembox_t +{ + ObjectFlags_t + obj_flags; // >0: ObjectFlags_t of analyzed itembox + u16 obj_id; // >0: ID of analyzed itembox + u16 item_player; // mode of player item + u16 item_enemy; // mode of enemy item + bool unsure_player; // true: not sure, if 'item_player' is correct + bool unsure_enemy; // true: not sure, if 'item_enemy' is correct +} +Itembox_t; + +// initialze 'ibox' and returns 'ibox->obj_id' +u16 AnalyseItembox ( Itembox_t *ibox, const kmp_gobj_entry_t *op ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// KMP draw support /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[draw_mode_t]] + +typedef enum draw_mode_t +{ + DMD_NONE = 0, + + DMD_KTPT = 1 << KMP_KTPT, + DMD_ENPT = 1 << KMP_ENPT, + DMD_ITPT = 1 << KMP_ITPT, + DMD_CKPT = 1 << KMP_CKPT, + //DMD_GOBJ = 1 << KMP_GOBJ, + DMD_POTI = 1 << KMP_POTI, + DMD_AREA = 1 << KMP_AREA, + //DMD_CAME = 1 << KMP_CAME, + DMD_JGPT = 1 << KMP_JGPT, + DMD_CNPT = 1 << KMP_CNPT, + //DMD_MSPT = 1 << KMP_MSPT, + + DMD_SHIFT_PFLAGS = KMP_N_SECT, // shift right to get presence flags + DMD_1OFFLINE = 1 << KMP_N_SECT, + DMD_2OFFLINE = DMD_1OFFLINE << 1, + DMD_3OFFLINE = DMD_2OFFLINE << 1, + DMD_1ONLINE = DMD_3OFFLINE << 1, + DMD_2ONLINE = DMD_1ONLINE << 1, + DMD_3ONLINE = DMD_2ONLINE << 1, + + DMD_CJGPT = DMD_3ONLINE << 1, + DMD_ITEMBOX = DMD_CJGPT << 1, + DMD_COIN = DMD_ITEMBOX << 1, + DMD_ROADOBJ = DMD_COIN << 1, + DMD_SOLIDOBJ = DMD_ROADOBJ << 1, + DMD_DECORATION = DMD_SOLIDOBJ << 1, + DMD_DISPATCH = DMD_DECORATION << 1, + DMD_BLACK = DMD_DISPATCH << 1, + DMD_WHITE = DMD_BLACK << 1, + DMD_KCL = DMD_WHITE << 1, + + DMD_DETAILED = DMD_KCL * 2ull, + DMD_WARNINGS = DMD_DETAILED * 2ull, + + DMD_M_OFFLINE = DMD_1OFFLINE // offline presence flags + | DMD_2OFFLINE + | DMD_3OFFLINE, + + DMD_M_ONLINE = DMD_1ONLINE // online presence flags + | DMD_2ONLINE + | DMD_3ONLINE, + + DMD_M_PFLAGS = DMD_M_OFFLINE // all presence flags + | DMD_M_ONLINE, + + DMD_M_FLAGS = DMD_DETAILED // flags + | DMD_WARNINGS, + + DMD_M_RESPAWN = DMD_CKPT // all about respawning + | DMD_JGPT + | DMD_CJGPT + | DMD_KTPT + | DMD_KCL, + + DMD_M_PTS = DMD_JGPT // single points + | DMD_KTPT, + + DMD_M_GOBJ = DMD_ITEMBOX // global objects + | DMD_COIN + | DMD_ROADOBJ + | DMD_SOLIDOBJ + | DMD_DECORATION, + + DMD_M_ADD = DMD_M_PTS // modes that add faces + | DMD_M_GOBJ + | DMD_ENPT + | DMD_ITPT + | DMD_CKPT + | DMD_POTI + | DMD_AREA + | DMD_CNPT + | DMD_CJGPT + | DMD_DISPATCH + | DMD_BLACK + | DMD_WHITE, + + DMD_M_ALL = DMD_M_ADD // all possible modes + | DMD_KCL + | DMD_M_PFLAGS + | DMD_M_FLAGS, + + DMD_M_RESET = DMD_M_ALL // reset these bits + & ~DMD_M_FLAGS, + + DMD_M_NEED_REF = DMD_CNPT, // needs a reference KCL + + DMD_M_DEFAULT = DMD_M_ALL // default setting + & ~DMD_M_PFLAGS + +} draw_mode_t; + +/////////////////////////////////////////////////////////////////////////////// + +extern draw_mode_t KMP_DRAW; + +int ScanOptDraw ( ccp arg ); +ccp GetDrawMode(); + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[DrawRouteMode_t]] + +typedef enum DrawRouteMode_t +{ + // order by priority, lowest priority first + + DRTM_OFF, // draw none + DRTM_POTI, // draw standard route + //DRTM_CAME, // draw came route + DRTM_GOBJ, // draw route for GOBJ objects + DRTM_ITEMBOX, // draw route for standard itembox + DRTM_ITEMBOX_ENEMY, // draw route for itembox with special item for enemies + DRTM_ITEMBOX_PLAYER, // draw route for itembox with special item for players +} +__attribute__ ((packed)) DrawRouteMode_t; + +/////////////////////////////////////////////////////////////////////////////// +// [[DrawKCL_t]] + +#define MAX_ROUTE 0x100 + +typedef struct DrawKCL_t +{ + struct kcl_t *draw; // valid pointer to draw-KCL, maybe same as 'kcl' + + const struct kcl_t *kcl; // NULL or pointer to related source KCL + const struct kmp_t *kmp; // NULL or pointer to related source KMP + + DrawRouteMode_t route[MAX_ROUTE]; // List of routes to draw + bool warnings; // true: draw warnings in red + bool detailed; // true: print more detailed + bool as_road; // true: print as road (KCL flag 0x0000) +} +DrawKCL_t; + +//----------------------------------------------------------------------------- + +static inline void InitializeDrawKCL ( DrawKCL_t *dk ) + { DASSERT(dk); memset(dk,0,sizeof(*dk)); } + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// KMP draw functions /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void AddAreas2KCL +( + DrawKCL_t * dk // pointer to initalized object +); + +//----------------------------------------------------------------------------- + +void AddCheckPoints2KCL +( + DrawKCL_t * dk, // pointer to initalized object + bool draw_jgpt // true: draw connections to JGPT +); + +//----------------------------------------------------------------------------- + +void AddArrow2KCL +( + DrawKCL_t * dk, // pointer to initalized object + uint sect, // KMP section + uint arrow_color, // color of arrow + uint area_color, // color of area behind arrow + double area_len, // >0.0: width of area behind arrow + double area_wd // >0.0: length of area behind arrow +); + +//----------------------------------------------------------------------------- + +void AddRoutes2KCL +( + DrawKCL_t * dk, // pointer to initalized object + uint sect_pt, // KMP section + uint color_std // standart color index +); + +//----------------------------------------------------------------------------- + +void AddPotiRoutes2KCL +( + DrawKCL_t * dk // pointer to initalized object +); + +//----------------------------------------------------------------------------- + +void AddCannons2KCL +( + DrawKCL_t * dk // pointer to initalized object +); + +//----------------------------------------------------------------------------- + +void AddObject2KCL +( + DrawKCL_t * dk, // pointer to initalized object + const + kmp_gobj_entry_t * op // object to draw +); + +//----------------------------------------------------------------------------- + +void AddObjectsById2KCL +( + DrawKCL_t * dk, // pointer to initalized object + u16 obj_id // object id to draw +); + +//----------------------------------------------------------------------------- + +void AddObjectsByFlag2KCL +( + DrawKCL_t * dk, // pointer to initalized object + u32 flag_mask, // mask the object flag with this ... + u32 flag_result // ... and draw it, if the result is this. +); + +//----------------------------------------------------------------------------- + +void AddZeroGround2KCL +( + DrawKCL_t * dk, // pointer to initalized object + uint color // color of ground +); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// pos file support /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[pos_param_t]] [[pos_file_t]] + +#define MAX_POS_FILE_INDEX 50 +#define MAX_POS_PARAM 15 +#define MAX_POS_FILTER 3 + +typedef struct pos_param_t +{ + //--- columns, all column indeces are 1 based + + uint idx_x; // >0: column index of x-pos + uint idx_y; // >0: column index of y-pos + uint idx_z; // >0: column index of z-pos + uint idx_d; // >0: column index of directiion (degree) + + //--- color + + uint autocolor; // >0: column for auto color, ignore color + uint color; // kcl_flag_* + int transp; // 0,1,2 for transparency selection, -1:disabled + + //--- filter + + uint idx_f[MAX_POS_FILTER]; // column index of filter A + char filter[MAX_POS_FILTER][20]; // text of filter A +} +pos_param_t; + +typedef struct pos_file_t +{ + struct pos_file_t *next; // link to next entry + ccp fname; // filename (alloced). NULL if invalid + + uint n_param; // number of used 'param' elements + pos_param_t param[MAX_POS_PARAM]; +} +pos_file_t; + +//----------------------------------------------------------------------------- + +extern pos_param_t default_pos_param; +extern pos_file_t current_pos_param; +extern pos_file_t *first_pos_file; + +//----------------------------------------------------------------------------- + +int ScanOptPosFile ( ccp arg ); +int ScanOptPosMode ( ccp arg ); + +void DrawPosFiles( DrawKCL_t *draw ); +enumError DrawPosFile ( DrawKCL_t *draw, pos_file_t *pf ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// link info /////////////// +/////////////////////////////////////////////////////////////////////////////// + +#define KMP_MAX_LINFO 0x100 + +//----------------------------------------------------------------------------- +// [[kmp_linfo_g_mode]] + +typedef enum kmp_linfo_g_mode +{ + LINFOG_DISPATCH = 0x01, // group is dispatch point +} +__attribute__ ((packed)) kmp_linfo_g_mode; + +//----------------------------------------------------------------------------- +// [[kmp_linfo_mode]] + +typedef enum kmp_linfo_mode +{ + LINFO_D_PREV = 0x01, // $1 links directly to $2 by PREV + LINFO_D_NEXT = 0x02, // $1 links directly to $2 by NEXT + LINFO_D_BY_PREV = 0x04, // $1 is directly linked from $2 by PREV + LINFO_D_BY_NEXT = 0x08, // $1 is directly linked from $2 by NEXT + + LINFO_G_PREV = 0x10, // $1 links via group to $2 by PREV + LINFO_G_NEXT = 0x20, // $1 links via group to $2 by NEXT + LINFO_G_BY_PREV = 0x40, // $1 is linked via group from $2 by PREV + LINFO_G_BY_NEXT = 0x80, // $1 is linked via group from $2 by NEXT + + LINFO_PREV = LINFO_D_PREV | LINFO_G_PREV, + LINFO_NEXT = LINFO_D_NEXT | LINFO_G_NEXT, + LINFO_BY_PREV = LINFO_D_BY_PREV | LINFO_G_BY_PREV, + LINFO_BY_NEXT = LINFO_D_BY_NEXT | LINFO_G_BY_NEXT, + + LINFO_M_D = LINFO_D_PREV | LINFO_D_NEXT | LINFO_D_BY_PREV | LINFO_D_BY_NEXT, + LINFO_M_G = LINFO_G_PREV | LINFO_G_NEXT | LINFO_G_BY_PREV | LINFO_G_BY_NEXT, +} +__attribute__ ((packed)) kmp_linfo_mode; + +//----------------------------------------------------------------------------- +// [[kmp_linfo_t]] + +typedef struct kmp_linfo_t +{ + uint sect_pt; + uint sect_ph; + + uint used; + + u8 n_point[KMP_MAX_LINFO]; + kmp_linfo_g_mode gmode[KMP_MAX_LINFO]; + kmp_linfo_mode summary[KMP_MAX_LINFO]; + kmp_linfo_mode list[KMP_MAX_LINFO][KMP_MAX_LINFO]; + +} +kmp_linfo_t; + +//----------------------------------------------------------------------------- + +void ResetRouteLinksKMP ( const kmp_t *kmp ); +kmp_linfo_t * SetupRouteLinksKMP ( const kmp_t *ckmp, uint sect, bool force ); + +uint AnalyseRouteKMP ( kmp_linfo_t *li, const kmp_t *kmp, uint sect ); +uint AnalyseGroupLinksKMP ( kmp_linfo_t *li, const kmp_t *kmp, uint sect_ph ); +uint AnalyseRouteLinksKMP ( kmp_linfo_t *li, const kmp_t *kmp, uint sect_pt ); +uint AnalyseRouteLinksCKPT ( kmp_linfo_t *li, const kmp_t *kmp ); + +// print_group: -1=never, 0:auto, 1:always +ccp PrintLinkInfoMode ( kmp_linfo_mode mode, int print_group, bool adjust ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// detect KMP types /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static inline bool IsDispatchPointKMP ( const kmp_enph_entry_t *p ) +{ +// return p->pt_len == 1 && p->prev[0] == 0xff && p->next[0] != 0xff; + return p->pt_len == 1 && p->prev[0] == 0xff; +} + +//----------------------------------------------------------------------------- + +void GetRouteTypeInfoKMP +( + kmp_rtype_info_t *rti, // store result here (never NULL) + const struct kmp_t *kmp, // KMP data + uint sect // section to check (PT or PH) +); + +/////////////////////////////////////////////////////////////////////////////// + +IsArena_t IsArenaKMP ( const struct kmp_t * kmp ); +IsArena_t CheckBattleModeKMP ( const struct kmp_t * kmp ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// kmp_finish_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_finish_t]] + +typedef struct kmp_finish_t +{ + bool valid; // true: record is valid => + // finish_ktpt >= 0 && finish_ckpt >= 0 + u8 hint; // bit field: 1=direction, 2=distance + u8 warn; // bit field: 1=direction, 2=distance + + u8 n_ckpt_0; // number of check points + u8 n_ktpt_m; // number of KTPT with index <0 + + s16 ckpt; // -1 or index of relevant CKPT + s16 ckpt_opt; // -1 or index of CKPT used for optimized KTPT + s16 ktpt; // -1 or index of relevant KTPT + s16 enpt_rec; // -1 or index of ENPT used for recommended KTPT + + float3 pos_ckpt; // neareast point to ktpt + float3 pos_ktpt; // position + float3 pos_ktpt_opt; // optimized position + float3 pos_ktpt_rec; // recommended position + + float dir_ckpt; // direction of CKPT, (0..360( + float dir_ktpt; // direction of KTPT, (0..360( + float dir_ktpt_opt; // optimized direction of KTPT, (0..360( + float dir_ktpt_rec; // recommended direction of KTPT, (0..360( + float dir_delta; // abs(dir_ckpt-dir_ckpt), (0..180) + float distance; // 2D distance of KTPT and finish line + float distance_rec; // 2D distance of 'pos_ktpt' and 'pos_ktpt_rec' +} +kmp_finish_t; + +//----------------------------------------------------------------------------- + +void InitializeFinishLine ( kmp_finish_t *kf ); + +double CalcCheckPointDistance +( + const kmp_ckpt_entry_t *ckpt, + double x, + double z +); + +void CalcFinishLine +( + const kmp_t *kmp, // not NULL: use it for recommendation + kmp_finish_t *kf, // valid data + const kmp_ckpt_entry_t *ckpt, // valid CKPT + const kmp_ktpt_entry_t *ktpt // valid KTPT +); + +bool CheckFinishLine ( const kmp_t *kmp, kmp_finish_t *kf ); +ccp LogFinishLine ( kmp_finish_t *kf ); + + +int InsertSecondKTPT +( + // returns: 0=not possible, 1:inserted, 2:replaced + + kmp_t *kmp, // valid KMP + double3 pos // position to insert +); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// kmp_usedpos_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_usedpos_obj_t]] + +typedef struct kmp_usedpos_obj_t +{ + //--- input + + float3 min; // minimal and maximal coordinates ... + float3 max; // ... used by ENPT and ITPT. + float3 allowed; // allowed values, init by 131071 == 2^17-1 + + //--- info (not used for calculations, set by ModifyUsedPosObj()) + + float3 shift; // active shift value + float3 stretch; // active stretch factor + + //--- results + + bool valid; // true: record is valid + bool useful; // true: record has useful data + bool shift_active; // true: shift is active + bool stretch_active; // true: stretch is active + + WarnLevel_t max_rating; // max 'rating' + WarnLevel_t rating[3]; // rating for each axis of min_used & max_used + bool pos_factor_valid; // TRUE: 'pos_factor' is valid + float3 pos_factor; // recommended factors for LEX/SET1/ITEM-POS-FACTOR +} +kmp_usedpos_obj_t; + +//----------------------------------------------------------------------------- + +void InitializeUsedPosObj ( kmp_usedpos_obj_t *obj ); +void EvaluateUsedPosObj ( kmp_usedpos_obj_t *obj ); +void ModifyUsedPosObj + ( kmp_usedpos_obj_t *obj, kmp_usedpos_obj_t *src, float3 *shift, float3 *stretch ); +ccp GetUsedPosObjSuggestion + ( const kmp_usedpos_obj_t *obj, bool force, ccp return_if_empty ); +void PrintUsedPosObj ( FILE *f, int indent, const kmp_usedpos_obj_t *obj ); + +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_usedpos_t]] + +typedef struct kmp_usedpos_t +{ + kmp_usedpos_obj_t orig; // original values + kmp_usedpos_obj_t orig_lex; // impact LEX/SET1/ITEM-POS-FACTOR + kmp_usedpos_obj_t center; // after shifting to center + kmp_usedpos_obj_t center_lex; // + impact LEX/SET1/ITEM-POS-FACTOR + + kmp_usedpos_obj_t *suggest; // one of above, never NULL +} +kmp_usedpos_t; + +//----------------------------------------------------------------------------- + +void InitializeUsedPos ( kmp_usedpos_t *up ); +void CheckUsedPos ( const kmp_t *kmp, kmp_usedpos_t *up ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// kmp_pflags_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_pflags_t]] + +typedef struct kmp_pflags_t +{ + u32 n_gobj; // number of GOBJ elements + u32 n_standard; // number of standard elements + u32 n_xpflags; // number of GOBJ elements with mode>0 + u32 n_cat_std; // number of used 'std_count' categories + u32 n_cat_mode; // number of used 'mode_count' categories + + u32 n_defobj; // number of total definition-objects + u32 n_defobj_bits; // number of definition-objects type BITS + u32 n_defobj_or; // number of definition-objects type OR + u32 n_defobj_and; // number of definition-objects type AND + u32 n_obj_ref; // number of valid object references + u32 n_cond_ref; // number of valid condition references + u32 n_cond_rnd; // number of valid randpm condition references + + u32 n_mode[16]; // number of elements with mode N>0 + u8 n_std[64]; // counters for standard bits (pflags&0x3f) +} +kmp_pflags_t; + +//----------------------------------------------------------------------------- + +uint CountPresenceFlags ( const kmp_t *kmp, kmp_pflags_t *pf ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// support for extension of pflags /////////////// +/////////////////////////////////////////////////////////////////////////////// +// INFO + +//-------------------------------------------------------------------------- +// bit mask info +//-------------------------------------------------------------------------- +// 0 0x0001 Offline race with 1 human player. +// 1 0x0002 Offline race with 2 human players. +// 2 0x0004 Offline race with 3 human players. +// 3 0x0008 Offline race with 4 human players. +//-------------------------------------------------------------------------- +// 4 0x0010 Online race with 1-6 players total and 1 human at Wii. +// 5 0x0020 Online race with 1-6 players total and 2 humans at Wii. +// 6 0x0040 Online race with 7-9 players total and 1 human at Wii. +// 7 0x0080 Online race with 7-9 players total and 2 humans at Wii. +// 8 0x0100 Online race with 10-12 players total and 1 human at Wii. +// 9 0x0200 Online race with 10-12 players total and 2 humans at Wii. +// 10 0x0400 Online race with 13-18 players total and 1 human at Wii. +// 11 0x0800 Online race with 13-18 players total and 2 humans at Wii. +// 12 0x1000 Online race with 19 or more players total and 1 human at Wii. +// 13 0x2000 Online race with 19 or more players total and 2 humans at Wii. +//-------------------------------------------------------------------------- +// 14 0x4000 RESERVED1. In Versus (setting #3) it is used for Time Trial. +// 15 0x8000 RESERVED2. +//-------------------------------------------------------------------------- + +/////////////////////////////////////////////////////////////////////////////// +// enum [[condition_ref_t]] + +typedef enum condition_ref_t // extended IF +{ + COR_NEVER = GOBJ_MIN_CONDITION, + COR_LECODE, + COR_SINGLE, + COR_MULTI, + COR_OFFLINE, + COR_ONLINE, + + COR_LE6, // 0x1006 + COR_GE7, + COR_LE9, + COR_GE10, + COR_LE12, + COR_GE13, + COR_LE18, + COR_GE19, + + COR_7_9, // 0x100e + COR_NOT_7_9, + COR_7_12, + COR_NOT_7_12, + COR_7_18, + COR_NOT_7_18, + COR_10_12, + COR_NOT_10_12, + COR_10_18, + COR_NOT_10_18, + COR_13_18, + COR_NOT_13_18, + + COR_TIMETRIAL, // 0x101a + COR_NO_TIMETRIAL, + COR_BATTLE, + COR_RACE, + + COR_BALLOON, // 0x101e + COR_NO_BALLOON, + COR_COIN, + COR_NO_COIN, + COR_VERSUS, + COR_NO_VERSUS, + COR_ITEMRAIN, + COR_NO_ITEMRAIN, + COR_SETTING5, + COR_NO_SETTING5, + COR_SETTING6, + COR_NO_SETTING6, + COR_SETTING7, + COR_NO_SETTING7, + COR_SETTING8, + COR_NO_SETTING8, + + COR_P2, + COR_P134, + COR_P3, + COR_P124, + COR_P4, + COR_P123, + COR_P12, + COR_P34, + COR_P13, + COR_P24, + COR_P14, + COR_P23, + + COR__N, // 0x102e + + + //--- developer values + + CORD_DEBUG = GOBJ_DEV_CONDITION, + CORD_RELEASE, + CORD_TESTVAL, + CORD_NO_TESTVAL, + + CORD__N // 0x1904 +} +condition_ref_t; + +//----------------------------------------------------------------------------- +// [[gobj_cond_ref_t]] + +typedef struct gobj_cond_ref_t +{ + u16 ref_id; + char name[14]; + char alias[6]; + u8 option; // Prefix: 0:no "", 2:"IF$", 4:"IFDEV$" + // &1: new group + char info[20]; + + u16 cond_mask; // mask for consitions + u8 set_mask; // mask to select setting + u8 op; // operator: + // 0: cond_mask || set_mask + // 1: cond_mask && set_mask + // *: disabled +} +gobj_cond_ref_t; + +//----------------------------------------------------------------------------- + +extern const gobj_cond_ref_t cond_ref_tab[COR__N+1]; +const gobj_cond_ref_t * FindConditionRef ( u16 ref_id ); + +/////////////////////////////////////////////////////////////////////////////// +// [[gobj_cond_mask_t]] + +typedef struct gobj_cond_mask_t +{ + u16 bit_mask; // mask to select bit of 'setting' + u8 game_mask; // mask to select 'setting' + u8 engine_mask; // mask to select am engine + u8 random_mask; // mask to select a random scenario +} +gobj_cond_mask_t; + +// if cref==NULL, then it is searched if needed. +bool IsConditionRefEnabled + ( const gobj_cond_mask_t *cm, u16 ref_id, const gobj_cond_ref_t *cref ); + +/////////////////////////////////////////////////////////////////////////////// +// [[cond_ref_info_t]] + +typedef struct cond_ref_info_t +{ + bool is_condref; // true: is valid ref_id for condition-ref + const gobj_cond_ref_t + *condref; // not NULL: definition found + ccp cmd_suffix; // either "DISABLE || "ENABLE", NULL if !is_condref + u16 xor; // 0|1, if 1: ref_id xor'd to get 'cond' + char cond[80]; // either "IF$.." or "0x1234" or "0" (if !is_condref) + char info[44]; // info for user +} +cond_ref_info_t; + +// returns 'cri->s_condref' +bool GetConditionRefInfo + ( cond_ref_info_t *cri, u16 ref_id, u16 obj_id, bool create_cond ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// XPF: support for extension of pflags /////////////// +/////////////////////////////////////////////////////////////////////////////// + +u16 GetActiveObjectId ( const kmp_gobj_entry_t *g ); + +static inline u16 GetRelevantObjectId ( u16 obj_id ) + { return obj_id < GOBJ_MIN_DEF ? obj_id & GOBJ_M_OBJECT : obj_id; } + +static inline u16 GetPFlagsMode ( u16 pflags ) + { return ( pflags & GOBJ_M_PF_MODE ) >> GOBJ_S_PF_MODE; } + +//--------------- + +static inline bool IsConditionRefId ( u16 ref_id ) + { return ref_id >= GOBJ_MIN_CONDITION + && ref_id <= GOBJ_MAX_CONDITION; } + +static inline bool IsConditionRefEngineId ( u16 ref_id ) + { return ref_id >= GOBJ_MIN_COND_ENGINE + && ref_id <= GOBJ_MAX_COND_ENGINE; } + +static inline bool IsConditionRefRandomId ( u16 ref_id ) + { return ref_id >= GOBJ_MIN_COND_RND + && ref_id <= GOBJ_MAX_COND_RND; } + +static inline bool IsConditionRefRelevantRandomId ( u16 ref_id ) + { return ref_id > GOBJ_MIN_COND_RND + && ref_id < GOBJ_MAX_COND_RND; } + +static inline bool IsConditionRefTestId ( u16 ref_id ) + { return ref_id >= GOBJ_MIN_COND_TEST + && ref_id <= GOBJ_MAX_COND_TEST; } + +//--------------- + +static inline bool IsDefinitionObjectIdBITS ( u16 obj_id ) + { return obj_id >= GOBJ_MIN_DEF_BITS + && obj_id <= GOBJ_MAX_DEF_BITS; } + +static inline bool IsDefinitionObjectIdOR ( u16 obj_id ) + { return obj_id >= GOBJ_MIN_DEF_OR + && obj_id <= GOBJ_MAX_DEF_OR; } + +static inline bool IsDefinitionObjectIdAND ( u16 obj_id ) + { return obj_id >= GOBJ_MIN_DEF_AND + && obj_id <= GOBJ_MAX_DEF_AND; } + +static inline bool IsDefinitionObjectId ( u16 obj_id ) +{ + return obj_id >= GOBJ_MIN_DEF_BITS && obj_id <= GOBJ_MAX_DEF_BITS + || obj_id >= GOBJ_MIN_DEF_OR && obj_id <= GOBJ_MAX_DEF_OR + || obj_id >= GOBJ_MIN_DEF_AND && obj_id <= GOBJ_MAX_DEF_AND; +} + +#if 0 // not used yet + +static inline bool IsDefinitionObjectRefBITS ( u16 obj_id ) + { return obj_id >= GOBJ_MIN_DEF_BITS + && obj_id <= (GOBJ_MAX_DEF_BITS|GOBJ_DEF_F_NOT); } + +static inline bool IsDefinitionObjectRefOR ( u16 obj_id ) + { return obj_id >= GOBJ_MIN_DEF_OR + && obj_id <= (GOBJ_MAX_DEF_OR|GOBJ_DEF_F_NOT); } + +static inline bool IsDefinitionObjectRefAND ( u16 obj_id ) + { return obj_id >= GOBJ_MIN_DEF_AND + && obj_id <= (GOBJ_MAX_DEF_AND|GOBJ_DEF_F_NOT); } + +static inline bool IsDefinitionObjectRef ( u16 obj_id ) + { return obj_id >= GOBJ_MIN_DEF && obj_id <= GOBJ_MAX_DEF;} + +#endif + + +static inline bool HaveDefinitionReference ( const kmp_gobj_entry_t *g ) + { return g + && IsDefinitionObjectId(g->ref_id) + && ( g->pflags & GOBJ_M_PF_MODE ) == GOBJ_PF_MODE1; } + +/////////////////////////////////////////////////////////////////////////////// +// [[opt_gamemode_t]] + +typedef enum opt_gamemode_t +{ + //--- main modes + + GMD_STD = 0x00000001, // standard modes + GMD_BALLOON = 0x00000002, // balloon battle + GMD_COIN = 0x00000004, // coin runners + GMD_VERSUS = 0x00000008, // versus races + GMD_ITEMRAIN = 0x00000010, // item rain + GMD__RESERVED = 0x000001e0, // reserved for settings 5-8 + + GMD_MD_BATTLE = 0x00000006, + GMD_MD_RACE = 0x00000018, + GMD_MD_DEFAULT = 0x0000011f, + GMD_MD_ALL = 0x0000011f, + + + //--- filters + + GMD_NO_MODES = 0x00001000, // suppress modes (only auto mode) + GMD_OFFLINE = 0x00002000, // offline modes + GMD_ONLINE = 0x00004000, // online modes + GMD_FI_DEFAULT = 0x00006000, + GMD_FI_ALL = 0x00007000, + + + //--- options + + GMD_AUTO = 0x00010000, // add generic case + GMD_STD_FIRST = 0x00020000, // create std settings first + GMD_ENGINE = 0x00040000, // append engine selection + GMD_RANDOM = 0x00080000, // append random selection + GMD_NO_TT = 0x00100000, // exclude time trial + GMD_FORCE_TT = 0x00200000, // force time trial + GMD_FULL = 0x00400000, // don't eliminate duplicates from list + GMD_NSORT = 0x00800000, // sort scenarios by name + GMD_ISORT = 0x01000000, // sort scenarios by index + GMD_DEBUG = 0x02000000, // enable debug mode + GMD_DUMP = 0x04000000, // enable dump mode + GMD_OP_ALL = 0x07ff0000, + + //--- flags + + GMD_F_HIDE = 0x40000000, // help flag to hide + + GMD_M_SORT = GMD_NSORT + | GMD_ISORT, + + GMD_M_OPTIONS = GMD_ENGINE // start flags if scanning options + | GMD_RANDOM, + + GMD_M_DEFAULT = GMD_MD_DEFAULT + | GMD_FI_DEFAULT + | GMD_ENGINE + | GMD_RANDOM, + + GMD_M_ALL = GMD_MD_ALL + | GMD_FI_ALL + | GMD_OP_ALL +} +opt_gamemode_t; + +extern opt_gamemode_t opt_gamemodes; +int ScanOptGamemodes ( ccp arg ); + +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_ana_defobj_t]] + +typedef struct kmp_ana_defobj_t +{ + bool is_defobj; // true: is a valid id for definition-objects + bool is_pure_defobj; // true: is_defobj && other parms=default + bool is_logical; // true: is OR or AND condition + + ccp cmd_name; // suffix for "$DEFOBJ-" or "IF$" + ccp par_info; // Info about parameters + int index_beg; // first index of settings to print + int index_end; // first index of settings to skip +} +kmp_ana_defobj_t; + +void AnalyseDefObject ( kmp_ana_defobj_t *ad, const kmp_gobj_entry_t *gobj ); + +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_ana_ref_t]] + +typedef struct kmp_ana_ref_t +{ + u16 mode; // mode of presence flags (pflags) + bool mode_valid; // true: valid mode + + bool condref_valid; // true: valid reference_id for condition-ref + bool condeng_valid; // true: valid reference_id for engine condition-ref + bool condrnd_valid; // true: valid reference_id for random condition-ref + bool condtest_valid; // true: valid reference_id for test values + bool objref_valid; // true: valid reference_id for def-object + + bool is_condref; // true: mode_valid && condref_valid + bool is_condeng; // true: mode_valid && condeng_valid + bool is_condrnd; // true: mode_valid && condrnd_valid + bool is_condtest; // true: mode_valid && condtest_valid + bool is_objref; // true: mode_valid && objref_valid + bool is_valid; // true: is_condref || is_objref +} +kmp_ana_ref_t; + +void AnalyseRefObject ( kmp_ana_ref_t *ar, const kmp_gobj_entry_t *gobj ); +kmp_gobj_entry_t * FindRefObject ( const kmp_t *kmp, const kmp_gobj_entry_t *gobj ); +kmp_gobj_entry_t * FindRefObjectByID ( const kmp_t *kmp, u16 ref_id ); + +/////////////////////////////////////////////////////////////////////////////// + +bool NormalizeDefObj ( kmp_gobj_entry_t *gobj ); +uint CountDefObjUsage ( const kmp_t *kmp, u16 obj_id ); +ccp GetDefObjConditionName ( u16 cond ); + +bool FixDefObj +( + kmp_t * kmp, // pointer to valid KMP + int fix_mode // >0: clear unused parameters +); + +bool SortDefObj +( + kmp_t * kmp, // pointer to valid KMP + int sort_mode // sort if KMP_DOB_BEGIN || KMP_DOB_END +); + +/////////////////////////////////////////////////////////////////////////////// + +bool FixReference +( + kmp_t * kmp, // pointer to valid KMP + int fix_mode // >0: fix if valid mode + // >1: fix for all modes +); + +bool SortReference +( + kmp_t * kmp, // pointer to valid KMP + int sort_mode // sort if KMP_DOB_BEFORE || KMP_DOB_BEHIND +); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// XPF: Convert conditions to text /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[gobj_condition_t]] + +typedef struct gobj_condition_t +{ + u16 mask; // Any of 0001..ffff. + u8 setting; // 1 bit (bits 0-7) for each setting (#1..#8) + s8 bitnum; // 0..15 for a single bit, -1 for a bit combination + s8 min_offline; // number of min online players (-1:not defined) + s8 max_offline; // number of max online players (-1:not defined) + s8 min_online; // number of min online players (-1:not defined) + s8 max_online; // number of max online players (-1:not defined) + ccp info; // related info. NULL: list terminator +} +gobj_condition_t; + +extern const gobj_condition_t gobj_condition[]; + +//----------------------------------------------------------------------------- +// [[gobj_condition_set_t]] + +#define GOBJ_COND_SET_MAX 10 + +typedef struct gobj_condition_set_t +{ + u16 mask; // evaluated mask + u8 setting_mask; // setting mask + uint n; // number of used elements of 'cond[]' without term + gobj_condition_t cond[GOBJ_COND_SET_MAX+1]; + // 'n' elements + terminator +} +gobj_condition_set_t; + +//----------------------------------------------------------------------------- + +// terminated by info==0 +extern const gobj_condition_t gobj_condition[]; + +// if setting==-1: evaluate for all settings +uint GetGobjConditions ( gobj_condition_set_t *gcs, int setting, u16 mask ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// XPF: Analyse GOBJ elements /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_gobj_type_t]] + +typedef enum kmp_gobj_type_t +{ + KGTY_NULL, // object-id is null + KGTY_INVALID, // from object range, but invalid + KGTY_OBJECT, // valid object + + KGTY_DEFOBJ_BITS, // definition-objects type BITS + KGTY_DEFOBJ_OR, // definition-objects type OR + KGTY_DEFOBJ_AND, // definition-objects type AND + + KGTY__N +} +__attribute__ ((packed)) kmp_gobj_type_t; + +//----------------------------------------------------------------------------- +// [[kmp_gobj_status_t]] + +typedef enum kmp_gobj_status_t +{ + KGST_USED = 0x0001, // object used + KGST_ENABLED = 0x0002, // object enabled by default + KGST_CONDREF = 0x0004, // object uses a condition-reference + KGST_DEFOBJ = 0x0008, // object uses a definition-object + KGST_REF_VALID = 0x0010, // condition-reference/definition-object valid + KGST_ENGINE = 0x0020, // uses a engine condition + KGST_RANDOM = 0x0040, // uses a random condition + KGST_DISABLED_BY = 0x0080, // always disabled by condition + + KGST_M_DERIVE = KGST_ENGINE|KGST_RANDOM, +} +__attribute__ ((packed)) kmp_gobj_status_t; + +//----------------------------------------------------------------------------- +// [[kmp_gobj_info_t]] + +typedef struct kmp_gobj_info_t +{ + u16 obj_id; // cleared object id + u16 ref_id; // cleared reference id + s16 defobj; // >=0: index of related definition-object + u16 ref_count; // number of references + kmp_gobj_status_t status; // object status + kmp_gobj_type_t type; // object type +} +kmp_gobj_info_t; + +//----------------------------------------------------------------------------- +// [[kmp_ana_gobj_t]] + +typedef struct kmp_ana_gobj_t +{ + //--- parameters + + const kmp_t *kmp; // valid kmp + const kmp_gobj_entry_t + *gobj; // pointer to GOBJ list + uint n_gobj; // number of elements in 'gobj' + + //--- analysis + + kmp_gobj_info_t *info; // alloced array of 'n_gobj' elements + + uint n_object; // number of objects := n_disabled+n_enabled + uint n_disabled; // number of initial disabled elements + uint n_enabled; // number of initial enabled elements + uint n_engine; // number of elements using a engine condition + uint n_random; // number of elements using a random condition + + uint n_defobj; // total number of definition-objects + uint n_defobj_bits; // number of definition-objects type BITS + uint n_defobj_or; // number of definition-objects type OR + uint n_defobj_and; // number of definition-objects type AND + uint n_defobj_used; // number of used definition-objects + + + //--- misc + + uint dur_usec; // duration in micro seconds +} +kmp_ana_gobj_t; + +//----------------------------------------------------------------------------- + +void ResetAnaGobj ( kmp_ana_gobj_t *ag ); +void AnalyseGobj ( kmp_ana_gobj_t *ag, const kmp_t *kmp ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// XPF: Analyse PFlag scenarios /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[kmp_ana_pflag_res_t]] + +typedef struct kmp_ana_pflag_res_t +{ + char name[16]; // name + u16 version; // version id + u8 n_std; // >0: result used by standard + u8 n_ext; // >0: result used by extension + lex_test_t lex_test; // template for LEX section TEST + ccp status; // alloced status, size=n_gobj+1 +} +kmp_ana_pflag_res_t; + +//----------------------------------------------------------------------------- +// [[kmp_ana_pflag_t]] + +typedef struct kmp_ana_pflag_t +{ + //--- parameters + + kmp_ana_gobj_t ag; + opt_gamemode_t opt_gamemode; // game mode to analyze + bool auto_sep; // true: automatic separators enabled + + //--- analysis + + uint status_len; // number of chars in res.status + uint n_res; // number of valid results + uint n_version; // number of different results + uint n_res_std; // number of different results for std-code + uint n_res_ext; // number of different results for extension + + kmp_ana_pflag_res_t *res_list; // alloced array with results + uint res_size; // number of alloced elements for 'res_list' + + //--- misc + + uint dur_usec; // duration in micro seconds +} +kmp_ana_pflag_t; + +//----------------------------------------------------------------------------- + +void ResetPFlagScenarios ( kmp_ana_pflag_t *ap ); +void AnalysePFlagScenarios + ( kmp_ana_pflag_t *ap, const kmp_t *kmp, opt_gamemode_t gmode ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// XPF: repair /////////////// +/////////////////////////////////////////////////////////////////////////////// + +int ScanOptRepairXPF ( ccp arg ); +enumError RepairXPF ( kmp_t *kmp ); + +/////////////////////////////////////////////////////////////////////////////// +// [[xpf_mode1_t]] + +typedef enum xpf_mode1_t +{ + XMODE1_NONE, // MODE!=1 + XMODE1_NULL, // MODE==1, but ref_id=0 + XMODE1_INVALID, // MODE==1, but invalid ref_id + XMODE1_CONDREF, // MODE==1 && conditiopn reference + XMODE1_OBJREF, // MODE==1 && object reference + XMODE1__N + +} +xpf_mode1_t; + +xpf_mode1_t CheckMode1GOBJ ( const kmp_gobj_entry_t *g ); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// KMP misc /////////////// +/////////////////////////////////////////////////////////////////////////////// + +extern uint kmp_start_pos_mirror; // last used setting +extern uint kmp_start_pos_narrow; // last used setting +extern bool kmp_start_pos_auto; // last call used 'automode'; + +const double3 * GetStartPosKMP +( + // Return NULL on failure. + // Otherwise return a pointer to 'tab' or to an internal static buffer + // with N elements. This buffer is overwritten on next call. + + double3 *tab, // table with 'n' elements to store the result. + // if NULL: use internal static buffer + uint n, // number of players: 1..12 + bool mirror, // true: mirror the data (pole is right) + bool narrow, // true: use 'narrow' mode + + kmp_t *kmp, // not NULL: Use KTPT/#0 and STGI/#0 + uint automode // bit field: Use KMP to override parameters + // 1: return absolute positions, if KMP available + // 2: use pole position of KMP if available + // 4: use narrow mode of KMP if available +); + +/////////////////////////////////////////////////////////////////////////////// + +void DetectSpecialKMP +( + const kmp_t *kmp, // pointer to valid KMP + kmp_special_t res // store result here, never NULL +); + +ccp CreateSpecialInfoKMP + ( kmp_special_t special, bool add_value, ccp return_if_empty ); + +/////////////////////////////////////////////////////////////////////////////// + +int CheckKMP +( + // returns number of errors + + const kmp_t *kmp, // pointer to valid KMP + CheckMode_t mode // print mode +); + +/////////////////////////////////////////////////////////////////////////////// + +enumError DiffKMP +( + kmp_t * kmp1, // first kmp to compare + kmp_t * kmp2, // second kmp tp compare + uint verbose // 0:quiet, 1:summary only, 2:full report +); + +/////////////////////////////////////////////////////////////////////////////// + +extern int have_kmp_patch_count; + +int ScanOptRmGobj ( ccp arg ); +int ScanOptBattle ( ccp arg ); +int ScanOptExportFlags ( ccp arg ); +int ScanOptRouteOptions ( ccp arg ); +int ScanOptWim0 ( ccp arg ); + +enumError cmd_stgi(); +enumError cmd_ktpt(); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// END /////////////// +/////////////////////////////////////////////////////////////////////////////// + +#endif // SZS_LIB_KMP_H -- cgit v1.3.1