summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2016-06-19 22:30:07 +0200
committerDennis Brentjes <d.brentjes@gmail.com>2016-06-19 22:30:07 +0200
commitdd8f1658c47db665481c725b9469408cf17e8c2e (patch)
tree185d0354c57f717068e348b322482dd4f826b77d
parentde95ca22ec87cc8b79ceb7beba475301461713a6 (diff)
downloadopenwar-dd8f1658c47db665481c725b9469408cf17e8c2e.tar.gz
openwar-dd8f1658c47db665481c725b9469408cf17e8c2e.tar.bz2
openwar-dd8f1658c47db665481c725b9469408cf17e8c2e.zip
implements a LE file parser and bare outputter.
-rw-r--r--binparse/binparse.hpp2
-rw-r--r--le/CMakeLists.txt13
-rw-r--r--le/le_file.cpp80
-rw-r--r--le/le_file.hpp33
-rw-r--r--le/le_file_parser.cpp56
5 files changed, 183 insertions, 1 deletions
diff --git a/binparse/binparse.hpp b/binparse/binparse.hpp
index 5b21086..e649ce7 100644
--- a/binparse/binparse.hpp
+++ b/binparse/binparse.hpp
@@ -46,7 +46,7 @@ std::array<uint8_t, 8> parse<std::array<uint8_t, 8>>(std::istream& is, std::stri
template<>
std::array<uint8_t, 22> parse<std::array<uint8_t, 22>>(std::istream& is, std::string name);
-void dump_bytes(std::istream& is, std::vector<uint8_t> buffer, std::string name);
+void dump_bytes(std::istream& is, std::vector<uint8_t>& buffer, std::string name);
std::string to_string(Magic16 magic);
diff --git a/le/CMakeLists.txt b/le/CMakeLists.txt
index 646f68b..5d849b3 100644
--- a/le/CMakeLists.txt
+++ b/le/CMakeLists.txt
@@ -29,5 +29,18 @@ target_include_directories(le_header_parser
PRIVATE ${Boost_INCLUDE_DIRS}
)
+add_executable(le_file_parser
+ le_file_parser.cpp
+)
+
+target_link_libraries(le_file_parser
+ PRIVATE le
+ PRIVATE ${Boost_LIBRARIES}
+)
+
+target_include_directories(le_file_parser
+ PRIVATE ${Boost_INCLUDE_DIRS}
+)
+
diff --git a/le/le_file.cpp b/le/le_file.cpp
new file mode 100644
index 0000000..3cec50c
--- /dev/null
+++ b/le/le_file.cpp
@@ -0,0 +1,80 @@
+#include "le_file.hpp"
+
+#include "index_list.hpp"
+
+#include <boost/fusion/adapted/struct.hpp>
+
+typedef std::array<uint8_t, 8> A1;
+typedef std::array<uint8_t, 22> A2;
+
+BOOST_FUSION_ADAPT_STRUCT(
+ le::LEFile,
+ (mz::MZHeader, mz_header)
+ (A1, unused_1)
+ (binparse::Value16, OEM_id)
+ (A2, OEM_info)
+ (binparse::Offset32, le_offset)
+ (std::vector<uint8_t>, dos_exe)
+ (le::LEHeader, le_header)
+ (std::vector<uint8_t>, le_exe)
+)
+
+namespace le {
+
+LEFile parse_file(std::istream& is) {
+ auto mz_h = mz::parse_header(is);
+ auto unused = parse<std::array<uint8_t, 8>>(is, "unused_1");
+ auto OEM_id = parse<binparse::Value16>(is, "OEM_id");
+ auto OEM_info = parse<std::array<uint8_t, 22>>(is, "OEM_info");
+ auto le_offset = parse<binparse::Offset32>(is, "le_offset");
+
+ size_t dos_exe_len = le_offset - 0x40;
+ std::vector<uint8_t> dos_exe = std::vector<uint8_t>(dos_exe_len, 0);
+ binparse::dump_bytes(is, dos_exe, "dos_exe");
+
+ auto le_h = le::parse_header(is);
+ std::string str(std::istreambuf_iterator<char>(is), {});
+ std::vector<uint8_t> le_exe(str.begin(), str.end());
+
+ return {
+ mz_h,
+ unused,
+ OEM_id,
+ OEM_info,
+ le_offset,
+ dos_exe,
+ le_h,
+ le_exe
+ };
+}
+
+std::ostream& operator<<(std::ostream& os, std::array<uint8_t, 8> const& array) {
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os, std::array<uint8_t, 22> const& array) {
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os, std::vector<uint8_t> vec) {
+ return os;
+}
+
+std::ostream& output_impl(std::ostream& os, LEFile const&, indices<>) {
+ return os;
+}
+
+template <int I, int... Indices>
+std::ostream& output_impl(std::ostream& os, const LEFile& file, indices<I, Indices...>) {
+ os << boost::fusion::extension::struct_member_name<LEFile, I>::call() << ": " << boost::fusion::at_c<I>(file) << std::endl;
+ return output_impl(os, file, indices<Indices...>{});
+}
+
+std::ostream&operator<<(std::ostream& os, LEFile const& file)
+{
+ typedef build_indices<boost::fusion::result_of::size<LEFile>::value>::type indices;
+
+ return output_impl(os, file, indices{});
+}
+
+} \ No newline at end of file
diff --git a/le/le_file.hpp b/le/le_file.hpp
new file mode 100644
index 0000000..010c49b
--- /dev/null
+++ b/le/le_file.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "binparse.hpp"
+#include "mz_header.hpp"
+#include "le_header.hpp"
+
+#include <cstdint>
+#include <cstddef>
+#include <memory>
+#include <array>
+#include <vector>
+
+namespace le {
+
+using namespace binparse;
+
+struct LEFile
+{
+ mz::MZHeader mz_header;
+ std::array<uint8_t, 8> unused_1;
+ Value16 OEM_id;
+ std::array<uint8_t, 22> OEM_info;
+ Offset32 le_offset;
+ std::vector<uint8_t> dos_exe;
+ LEHeader le_header;
+ std::vector<uint8_t> le_exe;
+};
+
+LEFile parse_file(std::istream& is);
+
+std::ostream& operator<<(std::ostream& os, LEFile const& file);
+
+}
diff --git a/le/le_file_parser.cpp b/le/le_file_parser.cpp
new file mode 100644
index 0000000..2d5eed9
--- /dev/null
+++ b/le/le_file_parser.cpp
@@ -0,0 +1,56 @@
+
+#include "le_file.hpp"
+
+#include <boost/program_options.hpp>
+#include <boost/filesystem.hpp>
+
+#include <iostream>
+
+int main(int argc, char* argv[]) {
+ boost::program_options::options_description description;
+ description.add_options()
+ ("help,h", "produces this help message")
+ ("exe,e", boost::program_options::value<std::string>(), "The LE executable to parse the header for.")
+ ;
+
+ boost::program_options::variables_map vm;
+ boost::program_options::store(boost::program_options::parse_command_line(argc, argv, description), vm);
+ boost::program_options::notify(vm);
+
+ if(vm.count("help")) {
+ std::cout << description << std::endl;
+ return 0;
+ }
+
+ boost::filesystem::path file_path;
+ if(vm.count("exe")) {
+ std::string exe_file = vm["exe"].as<std::string>();
+
+ if(boost::filesystem::exists(exe_file)) {
+ if(!boost::filesystem::is_directory(exe_file)) {
+ file_path = exe_file;
+ } else {
+ std::cerr << exe_file << " is a folder" << std::endl;
+ std::cerr << std::endl;
+ std::cerr << description << std::endl;
+ return -1;
+ }
+ } else {
+ std::cerr << "file: " << exe_file << " does not exist" << std::endl;
+ std::cerr << std::endl;
+ std::cerr << description << std::endl;
+ return -1;
+ }
+ } else {
+ std::cerr << "Option \"exe_file\" is required";
+ std::cerr << std::endl;
+ std::cerr << description << std::endl;
+ return -1;
+ }
+
+ std::ifstream file(file_path.string());
+ auto x = le::parse_file(file);
+ std::cout << x << std::endl;
+
+ return 0;
+}