From db569858283496e45f3e113d1929deb14cd9eb72 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Sun, 28 Feb 2010 09:18:48 +0100 Subject: [PATCH] Finished all basic parsers. Added --quiet option to esmtool. --- esm/loadbook.hpp | 2 +- esm/loadcell.hpp | 3 +- esm/loadcont.hpp | 4 +- esm/loadcrea.hpp | 1 + esm/loaddial.hpp | 46 +++++++++++++ esm/loadgmst.hpp | 2 + esm/records.hpp | 1 + esm/tests/esmtool.cpp | 121 ++++++++++++++++++++++++++++++++++- esm/tests/esmtool.ggo | 1 + esm/tests/esmtool_cmd.c | 20 +++++- esm/tests/esmtool_cmd.h | 2 + old_d_version/esm/loadspel.d | 96 --------------------------- 12 files changed, 194 insertions(+), 105 deletions(-) create mode 100644 esm/loaddial.hpp delete mode 100644 old_d_version/esm/loadspel.d diff --git a/esm/loadbook.hpp b/esm/loadbook.hpp index 8bff9d22f..8e9da0d51 100644 --- a/esm/loadbook.hpp +++ b/esm/loadbook.hpp @@ -6,7 +6,7 @@ namespace ESM { /* - * Books + * Books, magic scrolls, notes and so on */ struct Book diff --git a/esm/loadcell.hpp b/esm/loadcell.hpp index 07bcb5347..44d8e3498 100644 --- a/esm/loadcell.hpp +++ b/esm/loadcell.hpp @@ -57,12 +57,11 @@ struct Cell if(esm.isNextSub("DELE")) esm.skipHSub(); esm.getHNT(data, "DATA", 12); + region = esm.getHNOString("RGNN"); // Save position and move on context = esm.getContext(); esm.skipRecord(); - - region = esm.getHNOString("RGNN"); } }; } diff --git a/esm/loadcont.hpp b/esm/loadcont.hpp index 0ebedf723..0e54caf8e 100644 --- a/esm/loadcont.hpp +++ b/esm/loadcont.hpp @@ -22,9 +22,9 @@ struct InventoryList void load(ESMReader &esm) { ContItem ci; - while(esm.hasMoreSubs()) + while(esm.isNextSub("NPCO")) { - esm.getHNT(ci, "NPCO", 36); + esm.getHT(ci, 36); list.push_back(ci); } } diff --git a/esm/loadcrea.hpp b/esm/loadcrea.hpp index 09a864b60..2a22cebe0 100644 --- a/esm/loadcrea.hpp +++ b/esm/loadcrea.hpp @@ -72,6 +72,7 @@ struct Creature esm.getHNT(data, "NPDT", 96); esm.getHNT(flags, "FLAG"); + scale = 1.0; esm.getHNOT(scale, "XSCL"); inventory.load(esm); diff --git a/esm/loaddial.hpp b/esm/loaddial.hpp new file mode 100644 index 000000000..4c80fc783 --- /dev/null +++ b/esm/loaddial.hpp @@ -0,0 +1,46 @@ +#ifndef _ESM_DIAL_H +#define _ESM_DIAL_H + +#include "esm_reader.hpp" + +namespace ESM { + +/* + * Dialogue topic and journal entries. The actual data is contained in + * the INFO records following the DIAL. + */ + +struct Dialogue +{ + enum Type + { + Topic = 0, + Voice = 1, + Greeting = 2, + Persuasion = 3, + Journal = 4, + Deleted = -1 + }; + + char type; + + void load(ESMReader &esm) + { + esm.getSubNameIs("DATA"); + esm.getSubHeader(); + int si = esm.getSubSize(); + if(si == 1) + esm.getT(type); + else if(si == 4) + { + // These are just markers, their values are not used. + int i; + esm.getT(i); + esm.getHNT(i,"DELE"); + type = Deleted; + } + else esm.fail("Unknown sub record size"); + } +}; +} +#endif diff --git a/esm/loadgmst.hpp b/esm/loadgmst.hpp index 4f456280d..40f5111ac 100644 --- a/esm/loadgmst.hpp +++ b/esm/loadgmst.hpp @@ -203,6 +203,8 @@ struct GameSetting void load(ESMReader &esm) { + assert(id != ""); + dirty = false; // We are apparently allowed to be empty diff --git a/esm/records.hpp b/esm/records.hpp index d4385dad1..4ef8ce564 100644 --- a/esm/records.hpp +++ b/esm/records.hpp @@ -14,6 +14,7 @@ #include "loadcont.hpp" #include "loadcrea.hpp" #include "loadcrec.hpp" +#include "loaddial.hpp" #include "loaddoor.hpp" #include "loadench.hpp" #include "loadfact.hpp" diff --git a/esm/tests/esmtool.cpp b/esm/tests/esmtool.cpp index 860c5381a..eae11a16e 100644 --- a/esm/tests/esmtool.cpp +++ b/esm/tests/esmtool.cpp @@ -42,6 +42,8 @@ int main(int argc, char**argv) return 0; } + bool quiet = info.quiet_given; + esm.open(filename); cout << "Author: " << esm.getAuthor() << endl; @@ -57,10 +59,11 @@ int main(int argc, char**argv) while(esm.hasMoreRecs()) { NAME n = esm.getRecName(); - cout << "\nRecord: " << n.toString(); esm.getRecHeader(); string id = esm.getHNOString("NAME"); - cout << " '" << id << "'\n"; + if(!quiet) + cout << "\nRecord: " << n.toString() + << " '" << id << "'\n"; switch(n.val) { @@ -68,15 +71,33 @@ int main(int argc, char**argv) { Activator ac; ac.load(esm); + if(quiet) break; cout << " Name: " << ac.name << endl; cout << " Mesh: " << ac.model << endl; cout << " Script: " << ac.script << endl; break; } + case REC_ALCH: + { + Potion p; + p.load(esm); + if(quiet) break; + cout << " Name: " << p.name << endl; + break; + } + case REC_APPA: + { + Apparatus p; + p.load(esm); + if(quiet) break; + cout << " Name: " << p.name << endl; + break; + } case REC_ARMO: { Armor am; am.load(esm); + if(quiet) break; cout << " Name: " << am.name << endl; cout << " Mesh: " << am.model << endl; cout << " Icon: " << am.icon << endl; @@ -90,23 +111,83 @@ int main(int argc, char**argv) { BodyPart bp; bp.load(esm); + if(quiet) break; cout << " Name: " << bp.name << endl; cout << " Mesh: " << bp.model << endl; break; } + case REC_BOOK: + { + Book b; + b.load(esm); + if(quiet) break; + cout << " Name: " << b.name << endl; + cout << " Mesh: " << b.model << endl; + break; + } case REC_BSGN: { BirthSign bs; bs.load(esm); + if(quiet) break; cout << " Name: " << bs.name << endl; cout << " Texture: " << bs.texture << endl; cout << " Description: " << bs.description << endl; break; } + case REC_CELL: + { + Cell b; + b.load(esm); + if(quiet) break; + cout << " Name: " << b.name << endl; + cout << " Region: " << b.region << endl; + break; + } + case REC_CLAS: + { + Class b; + b.load(esm); + if(quiet) break; + cout << " Name: " << b.name << endl; + cout << " Description: " << b.description << endl; + break; + } + case REC_CLOT: + { + Clothing b; + b.load(esm); + if(quiet) break; + cout << " Name: " << b.name << endl; + break; + } + case REC_CONT: + { + Container b; + b.load(esm); + if(quiet) break; + cout << " Name: " << b.name << endl; + break; + } + case REC_CREA: + { + Creature b; + b.load(esm); + if(quiet) break; + cout << " Name: " << b.name << endl; + break; + } + case REC_DIAL: + { + Dialogue b; + b.load(esm); + break; + } case REC_DOOR: { Door d; d.load(esm); + if(quiet) break; cout << " Name: " << d.name << endl; cout << " Mesh: " << d.model << endl; cout << " Script: " << d.script << endl; @@ -114,10 +195,42 @@ int main(int argc, char**argv) cout << " CloseSound: " << d.closeSound << endl; break; } + case REC_ENCH: + { + Enchantment b; + b.load(esm); + break; + } + case REC_GMST: + { + GameSetting b; + b.id = id; + b.load(esm); + if(quiet) break; + cout << " Value: "; + if(b.type == VT_String) + cout << "'" << b.str << "' (string)"; + else if(b.type == VT_Float) + cout << b.f << " (float)"; + else if(b.type == VT_Int) + cout << b.i << " (int)"; + cout << "\n Dirty: " << b.dirty << endl; + break; + } + case REC_INFO: + { + DialInfo p; + p.load(esm); + if(quiet) break; + cout << " Id: " << p.id << endl; + cout << " Text: " << p.response << endl; + break; + } case REC_SOUN: { Sound d; d.load(esm); + if(quiet) break; cout << " Sound: " << d.sound << endl; cout << " Volume: " << (int)d.data.volume << endl; break; @@ -126,12 +239,14 @@ int main(int argc, char**argv) { Spell s; s.load(esm); + if(quiet) break; cout << " Name: " << s.name << endl; break; } default: - cout << " Skipping\n"; esm.skipRecord(); + if(quiet) break; + cout << " Skipping\n"; } } diff --git a/esm/tests/esmtool.ggo b/esm/tests/esmtool.ggo index d8d8e4a19..5ad53a5ad 100644 --- a/esm/tests/esmtool.ggo +++ b/esm/tests/esmtool.ggo @@ -4,5 +4,6 @@ purpose "Inspect and extract from Morrowind ES files (ESM, ESP, ESS)" args "--unamed-opts=ES-FILE -F esmtool_cmd -G" option "raw" r "Show an unformattet list of all records and subrecords" optional +option "quiet" q "Supress all record information. Useful for speed tests." optional text "\nIf no option is given, the default action is to parse the entire archive and diplay diagnostic information." diff --git a/esm/tests/esmtool_cmd.c b/esm/tests/esmtool_cmd.c index f04fdb4e7..0a619ff2b 100644 --- a/esm/tests/esmtool_cmd.c +++ b/esm/tests/esmtool_cmd.c @@ -34,6 +34,7 @@ const char *gengetopt_args_info_help[] = { " -h, --help Print help and exit", " -V, --version Print version and exit", " -r, --raw Show an unformattet list of all records and subrecords", + " -q, --quiet Supress all record information. Useful for speed tests.", "\nIf no option is given, the default action is to parse the entire archive and \ndiplay diagnostic information.", 0 }; @@ -60,6 +61,7 @@ void clear_given (struct gengetopt_args_info *args_info) args_info->help_given = 0 ; args_info->version_given = 0 ; args_info->raw_given = 0 ; + args_info->quiet_given = 0 ; } static @@ -77,6 +79,7 @@ void init_args_info(struct gengetopt_args_info *args_info) args_info->help_help = gengetopt_args_info_help[0] ; args_info->version_help = gengetopt_args_info_help[1] ; args_info->raw_help = gengetopt_args_info_help[2] ; + args_info->quiet_help = gengetopt_args_info_help[3] ; } @@ -192,6 +195,8 @@ cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) write_into_file(outfile, "version", 0, 0 ); if (args_info->raw_given) write_into_file(outfile, "raw", 0, 0 ); + if (args_info->quiet_given) + write_into_file(outfile, "quiet", 0, 0 ); i = EXIT_SUCCESS; @@ -1019,6 +1024,7 @@ cmdline_parser_internal ( { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "raw", 0, NULL, 'r' }, + { "quiet", 0, NULL, 'q' }, { 0, 0, 0, 0 } }; @@ -1027,7 +1033,7 @@ cmdline_parser_internal ( custom_opterr = opterr; custom_optopt = optopt; - c = custom_getopt_long (argc, argv, "hVr", long_options, &option_index); + c = custom_getopt_long (argc, argv, "hVrq", long_options, &option_index); optarg = custom_optarg; optind = custom_optind; @@ -1060,6 +1066,18 @@ cmdline_parser_internal ( goto failure; break; + case 'q': /* Supress all record information. Useful for speed tests.. */ + + + if (update_arg( 0 , + 0 , &(args_info->quiet_given), + &(local_args_info.quiet_given), optarg, 0, 0, ARG_NO, + check_ambiguity, override, 0, 0, + "quiet", 'q', + additional_error)) + goto failure; + + break; case 0: /* Long option with no short option */ case '?': /* Invalid option. */ diff --git a/esm/tests/esmtool_cmd.h b/esm/tests/esmtool_cmd.h index 1d0708ac9..3559623e6 100644 --- a/esm/tests/esmtool_cmd.h +++ b/esm/tests/esmtool_cmd.h @@ -40,10 +40,12 @@ struct gengetopt_args_info const char *help_help; /**< @brief Print help and exit help description. */ const char *version_help; /**< @brief Print version and exit help description. */ const char *raw_help; /**< @brief Show an unformattet list of all records and subrecords help description. */ + const char *quiet_help; /**< @brief Supress all record information. Useful for speed tests. help description. */ unsigned int help_given ; /**< @brief Whether help was given. */ unsigned int version_given ; /**< @brief Whether version was given. */ unsigned int raw_given ; /**< @brief Whether raw was given. */ + unsigned int quiet_given ; /**< @brief Whether quiet was given. */ char **inputs ; /**< @brief unamed options (options without names) */ unsigned inputs_num ; /**< @brief unamed options number */ diff --git a/old_d_version/esm/loadspel.d b/old_d_version/esm/loadspel.d deleted file mode 100644 index 6eca2d03c..000000000 --- a/old_d_version/esm/loadspel.d +++ /dev/null @@ -1,96 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (loadspel.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - 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. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module esm.loadspel; -import esm.imports; - -/* - * Spell - */ - -struct SpellList -{ - RegionBuffer!(Spell*) list; - - void load() - { - list = esFile.getRegion().getBuffer!(Spell*)(0,1); - - while(esFile.isNextSub("NPCS")) - list ~= esFile.getHPtr!(Spell)(spells); - } -} - -struct Spell -{ - char[] id; - LoadState state; - - enum SpellType - { - Spell = 0, // Normal spell, must be cast and costs mana - Ability = 1, // Inert ability, always in effect - Blight = 2, // Blight disease - Disease = 3, // Common disease - Curse = 4, // Curse (?) - Power = 5 // Power, can use once a day - } - - enum Flags - { - Autocalc = 1, - PCStart = 2, - Always = 4 // Casting always succeeds - } - - align(1) struct SPDTstruct - { - SpellType type; - int cost; - Flags flags; - - static assert(SPDTstruct.sizeof==12); - } - - SPDTstruct data; - - char[] name; - EffectList effects; - - void load() - {with(esFile){ - name = getHNOString("FNAM"); - readHNExact(&data, data.sizeof, "SPDT"); - - effects = getRegion().getBuffer!(ENAMstruct)(0,1); - - while(isNextSub("ENAM")) - { - effects.length = effects.length + 1; - readHExact(&effects.array[$-1], effects.array[$-1].sizeof); - } - }} - -} - -ListID!(Spell) spells;