From a9c399ff2af276cfea29b5ada2ccb6c8d76f2b78 Mon Sep 17 00:00:00 2001 From: Wolfgang Thaller Date: Wed, 8 Oct 2014 02:52:15 +0200 Subject: [PATCH] MakeAPPL: factor out resource file code --- MakeAPPL/BinaryIO.cc | 52 ++++++++++ MakeAPPL/BinaryIO.h | 17 ++++ MakeAPPL/CMakeLists.txt | 4 + MakeAPPL/ResType.cc | 38 +++++++ MakeAPPL/ResType.h | 23 +++++ MakeAPPL/ResourceFiles.cc | 129 +++++++++++++++++++++++ MakeAPPL/ResourceFiles.h | 42 ++++++++ MakeAPPL/main.cc | 209 +------------------------------------- 8 files changed, 308 insertions(+), 206 deletions(-) create mode 100644 MakeAPPL/BinaryIO.cc create mode 100644 MakeAPPL/BinaryIO.h create mode 100644 MakeAPPL/ResType.cc create mode 100644 MakeAPPL/ResType.h create mode 100644 MakeAPPL/ResourceFiles.cc create mode 100644 MakeAPPL/ResourceFiles.h diff --git a/MakeAPPL/BinaryIO.cc b/MakeAPPL/BinaryIO.cc new file mode 100644 index 0000000000..32070edbd4 --- /dev/null +++ b/MakeAPPL/BinaryIO.cc @@ -0,0 +1,52 @@ +#include "BinaryIO.h" +#include +#include + +void byte(std::ostream& out, int byte) +{ + out.put((unsigned char)byte); +} +void word(std::ostream& out, int word) +{ + byte(out,(word >> 8) & 0xFF); + byte(out,word & 0xFF); +} +void ostype(std::ostream& out, std::string type) +{ + assert(type.size() == 4); + out << type; +} +void longword(std::ostream& out, int longword) +{ + byte(out,(longword >> 24) & 0xFF); + byte(out,(longword >> 16) & 0xFF); + byte(out,(longword >> 8) & 0xFF); + byte(out,longword & 0xFF); +} + +int byte(std::istream& in) +{ + return in.get() & 0xFF; +} +int word(std::istream& in) +{ + int a = byte(in); + int b = byte(in); + return (a << 8) | b; +} +std::string ostype(std::istream& in) +{ + char s[5]; + in.read(s,4); + s[4] = 0; + return s; +} +int longword(std::istream& in) +{ + int a = byte(in); + int b = byte(in); + int c = byte(in); + int d = byte(in); + return (a << 24) | (b << 16) | (c << 8) | d; +} + diff --git a/MakeAPPL/BinaryIO.h b/MakeAPPL/BinaryIO.h new file mode 100644 index 0000000000..e4b84d4336 --- /dev/null +++ b/MakeAPPL/BinaryIO.h @@ -0,0 +1,17 @@ +#ifndef BINARYIO_H +#define BINARYIO_H + +#include +#include + +void byte(std::ostream& out, int byte); +void word(std::ostream& out, int word); +void ostype(std::ostream& out, std::string type); +void longword(std::ostream& out, int longword); + +int byte(std::istream& in); +int word(std::istream& in); +std::string ostype(std::istream& in); +int longword(std::istream& in); + +#endif // BINARYIO_H diff --git a/MakeAPPL/CMakeLists.txt b/MakeAPPL/CMakeLists.txt index 8bd5489b1e..11347f2356 100644 --- a/MakeAPPL/CMakeLists.txt +++ b/MakeAPPL/CMakeLists.txt @@ -16,7 +16,11 @@ # along with Retro68. If not, see . cmake_minimum_required(VERSION 2.8) +set(CMAKE_CXX_FLAGS "--std=c++0x") +add_library(ResourceFiles ResourceFiles.h ResourceFiles.cc BinaryIO.h BinaryIO.cc ResType.h ResType.cc) +target_include_directories(ResourceFiles PUBLIC .) add_executable(MakeAPPL main.cc) +target_link_libraries(MakeAPPL ResourceFiles) install(TARGETS MakeAPPL RUNTIME DESTINATION bin) diff --git a/MakeAPPL/ResType.cc b/MakeAPPL/ResType.cc new file mode 100644 index 0000000000..add8a6302a --- /dev/null +++ b/MakeAPPL/ResType.cc @@ -0,0 +1,38 @@ +#include "ResType.h" +#include + +ResType::ResType(const std::string &str) +{ + auto p = str.begin(); + auto e = str.end(); + + x = 0; + while(p != e) + { + x <<= 8; + x |= (*p) & 0xFF; + ++p; + } +} + +ResType::operator std::string() +{ + char c1 = static_cast(x >> 24); + char c2 = static_cast(x >> 16); + char c3 = static_cast(x >> 8); + char c4 = static_cast(x); + + return std::string{ c1, c2, c3, c4 }; +} + +std::ostream &operator<<(std::ostream &out, ResType t) +{ + char c1 = static_cast((int)t >> 24); + char c2 = static_cast((int)t >> 16); + char c3 = static_cast((int)t >> 8); + char c4 = static_cast((int)t); + + out << "'" << c1 << c2 << c3 << c4 << "'"; + return out; +} + diff --git a/MakeAPPL/ResType.h b/MakeAPPL/ResType.h new file mode 100644 index 0000000000..324d94c002 --- /dev/null +++ b/MakeAPPL/ResType.h @@ -0,0 +1,23 @@ +#ifndef RESTYPE_H +#define RESTYPE_H + +#include +#include + +class ResType +{ + int x; +public: + ResType() : x(0) {} + ResType(int x) : x(x) {} + ResType(const std::string& s); + + operator int() const { return x; } + bool operator<(ResType y) const { return x < y.x; } + + operator std::string(); +}; + +std::ostream& operator<<(std::ostream& out, ResType t); + +#endif // RESTYPE_H diff --git a/MakeAPPL/ResourceFiles.cc b/MakeAPPL/ResourceFiles.cc new file mode 100644 index 0000000000..9f84426d7f --- /dev/null +++ b/MakeAPPL/ResourceFiles.cc @@ -0,0 +1,129 @@ +#include "ResourceFiles.h" +#include "BinaryIO.h" + +#include +#include + +void Resources::addResources(const Resources& res) +{ + resources.insert(resources.end(),res.resources.begin(), res.resources.end()); +} + +void Resources::writeFork(std::ostream& out) const +{ + std::streampos start = out.tellp(); + longword(out,0x100); + longword(out,0); + longword(out,0); + longword(out,0); + out.seekp(start + std::streampos(0x100)); + std::map< std::string, std::map > resourceInfos; + std::streampos datastart = out.tellp(); + for(std::vector::const_iterator p = resources.begin(); p != resources.end(); ++p) + { + const std::string& data = p->getData(); + resourceInfos[ p->getType() ][ p->getID() ] = out.tellp() - datastart; + longword(out, data.size()); + out << data; + } + std::streampos dataend = out.tellp(); +// while(out.tellp() % 0x100) +// out.put(0); + std::streampos resmap = out.tellp(); + out.seekp(16+4+2+2, std::ios::cur); + word(out,16+4+2+2+2+2); // offset to resource type list + std::streampos resnameOffset = out.tellp(); + word(out,0); + std::streampos typelist = out.tellp(); + word(out,resourceInfos.size() - 1); + for(std::map< std::string, std::map >::iterator p = resourceInfos.begin(); + p != resourceInfos.end(); ++p) + { + if(p->second.size()) + { + ostype(out,p->first); + word(out,p->second.size()-1); + word(out,0); // replaced later + } + } + int typeIndex = 0; + for(std::map< std::string, std::map >::iterator p = resourceInfos.begin(); + p != resourceInfos.end(); ++p) + { + if(p->second.size()) + { + std::streampos pos = out.tellp(); + out.seekp((int)typelist + 2 + 8 * typeIndex + 6); + word(out, pos - typelist); + out.seekp(pos); + typeIndex++; + + for(std::map::iterator q = p->second.begin(); q != p->second.end(); ++q) + { + word(out,q->first); + word(out,-1); + longword(out,q->second); + longword(out,0); + } + } + } + std::streampos resnames = out.tellp(); + out.seekp(resnameOffset); + word(out, resnames - resmap); + out.seekp(resnames); + std::streampos end = out.tellp(); + out.seekp(start + std::streampos(4)); + longword(out, resmap - start); + longword(out, dataend - start - std::streampos(0x100)); + longword(out, end - resmap); + out.seekp(end); +} + +Resources::Resources(std::istream &in) +{ + std::streampos start = in.tellg(); + int resdataOffset = longword(in); + int resmapOffset = longword(in); + + in.seekg(start + std::streampos(resmapOffset + 16 + 4 + 2 + 2)); + int typeListOffset = word(in); + int nameListOffset = word(in); + int nTypes = (word(in) + 1) & 0xFFFF; + + for(int i = 0; i < nTypes; i++) + { + in.seekg(start + std::streampos(resmapOffset + typeListOffset + 2 + i * 8)); + std::string type = ostype(in); + int nRes = (word(in) + 1) & 0xFFFF; + int refListOffset = word(in); + + for(int j = 0; j < nRes; j++) + { + in.seekg(start + std::streampos(resmapOffset + typeListOffset + refListOffset + j * 12)); + int id = word(in); + int nameOffset = word(in); + int attr = byte(in); + int off1 = byte(in); + int off2 = byte(in); + int off3 = byte(in); + int offset = (off1 << 16) | (off2 << 8) | off3; + std::string name; + if(nameOffset != 0xFFFF) + { + in.seekg(start + std::streampos(resmapOffset + nameListOffset + nameOffset)); + int nameLen = byte(in); + char buf[256]; + in.read(buf, nameLen); + name = std::string(buf, nameLen); + } + + in.seekg(start + std::streampos(resdataOffset + offset)); + int size = longword(in); + std::vector tmp(size); + in.read(tmp.data(), size); + std::string data(tmp.data(), size); + + addResource(Resource(type, id, data, name, attr)); + } + } +} diff --git a/MakeAPPL/ResourceFiles.h b/MakeAPPL/ResourceFiles.h new file mode 100644 index 0000000000..8e24ca80cb --- /dev/null +++ b/MakeAPPL/ResourceFiles.h @@ -0,0 +1,42 @@ +#ifndef RESOURCEFILES_H +#define RESOURCEFILES_H + +#include +#include + +class Resource +{ + std::string type; + int id; + std::string name; + std::string data; + int attr; +public: + Resource(std::string type, int id, std::string data, std::string name = "", int attr = 0) + : type(type), id(id), data(data), name(name), attr(attr) {} + + const std::string& getData() const { return data; } + inline std::string getType() const { return type; } + inline int getID() const { return id; } +}; + +class Fork +{ +public: + virtual void writeFork(std::ostream& out) const { } + virtual ~Fork() {} +}; + +class Resources : public Fork +{ + std::vector resources; +public: + Resources() {} + Resources(std::istream& in); + void writeFork(std::ostream& out) const; + void addResource(Resource res) { resources.push_back(res); } + + void addResources(const Resources& res); +}; + +#endif // RESOURCEFILES_H diff --git a/MakeAPPL/main.cc b/MakeAPPL/main.cc index 79bc813083..e2baaa3d5d 100644 --- a/MakeAPPL/main.cc +++ b/MakeAPPL/main.cc @@ -28,6 +28,9 @@ #include #include +#include "ResourceFiles.h" +#include "BinaryIO.h" + std::string commandPath; void wrapMacBinary(std::string macBinaryFile, std::string diskImagePath) @@ -45,212 +48,6 @@ void wrapMacBinary(std::string macBinaryFile, std::string diskImagePath) std::system((commandPath + "hcopy -m " + macBinaryFile + " :").c_str()); } -class Resource -{ - std::string type; - int id; - std::string name; - std::string data; - int attr; -public: - Resource(std::string type, int id, std::string data, std::string name = "", int attr = 0) - : type(type), id(id), data(data), name(name), attr(attr) {} - - const std::string& getData() const { return data; } - inline std::string getType() const { return type; } - inline int getID() const { return id; } -}; - -class Fork -{ -public: - virtual void writeFork(std::ostream& out) const { } - virtual ~Fork() {} -}; - -class Resources : public Fork -{ - std::vector resources; -public: - Resources() {} - Resources(std::istream& in); - void writeFork(std::ostream& out) const; - void addResource(Resource res) { resources.push_back(res); } - - void addResources(const Resources& res); -}; - -void byte(std::ostream& out, int byte) -{ - out.put((unsigned char)byte); -} -void word(std::ostream& out, int word) -{ - byte(out,(word >> 8) & 0xFF); - byte(out,word & 0xFF); -} -void ostype(std::ostream& out, std::string type) -{ - assert(type.size() == 4); - out << type; -} -void longword(std::ostream& out, int longword) -{ - byte(out,(longword >> 24) & 0xFF); - byte(out,(longword >> 16) & 0xFF); - byte(out,(longword >> 8) & 0xFF); - byte(out,longword & 0xFF); -} - -int byte(std::istream& in) -{ - return in.get() & 0xFF; -} -int word(std::istream& in) -{ - int a = byte(in); - int b = byte(in); - return (a << 8) | b; -} -std::string ostype(std::istream& in) -{ - char s[5]; - in.read(s,4); - s[4] = 0; - return s; -} -int longword(std::istream& in) -{ - int a = byte(in); - int b = byte(in); - int c = byte(in); - int d = byte(in); - return (a << 24) | (b << 16) | (c << 8) | d; -} - -void Resources::addResources(const Resources& res) -{ - resources.insert(resources.end(),res.resources.begin(), res.resources.end()); -} - -void Resources::writeFork(std::ostream& out) const -{ - std::streampos start = out.tellp(); - longword(out,0x100); - longword(out,0); - longword(out,0); - longword(out,0); - out.seekp(start + std::streampos(0x100)); - std::map< std::string, std::map > resourceInfos; - std::streampos datastart = out.tellp(); - for(std::vector::const_iterator p = resources.begin(); p != resources.end(); ++p) - { - const std::string& data = p->getData(); - resourceInfos[ p->getType() ][ p->getID() ] = out.tellp() - datastart; - longword(out, data.size()); - out << data; - } - std::streampos dataend = out.tellp(); -// while(out.tellp() % 0x100) -// out.put(0); - std::streampos resmap = out.tellp(); - out.seekp(16+4+2+2, std::ios::cur); - word(out,16+4+2+2+2+2); // offset to resource type list - std::streampos resnameOffset = out.tellp(); - word(out,0); - std::streampos typelist = out.tellp(); - word(out,resourceInfos.size() - 1); - for(std::map< std::string, std::map >::iterator p = resourceInfos.begin(); - p != resourceInfos.end(); ++p) - { - if(p->second.size()) - { - ostype(out,p->first); - word(out,p->second.size()-1); - word(out,0); // replaced later - } - } - int typeIndex = 0; - for(std::map< std::string, std::map >::iterator p = resourceInfos.begin(); - p != resourceInfos.end(); ++p) - { - if(p->second.size()) - { - std::streampos pos = out.tellp(); - out.seekp((int)typelist + 2 + 8 * typeIndex + 6); - word(out, pos - typelist); - out.seekp(pos); - typeIndex++; - - for(std::map::iterator q = p->second.begin(); q != p->second.end(); ++q) - { - word(out,q->first); - word(out,-1); - longword(out,q->second); - longword(out,0); - } - } - } - std::streampos resnames = out.tellp(); - out.seekp(resnameOffset); - word(out, resnames - resmap); - out.seekp(resnames); - std::streampos end = out.tellp(); - out.seekp(start + std::streampos(4)); - longword(out, resmap - start); - longword(out, dataend - start - std::streampos(0x100)); - longword(out, end - resmap); - out.seekp(end); -} - -Resources::Resources(std::istream &in) -{ - std::streampos start = in.tellg(); - int resdataOffset = longword(in); - int resmapOffset = longword(in); - - in.seekg(start + std::streampos(resmapOffset + 16 + 4 + 2 + 2)); - int typeListOffset = word(in); - int nameListOffset = word(in); - int nTypes = (word(in) + 1) & 0xFFFF; - - for(int i = 0; i < nTypes; i++) - { - in.seekg(start + std::streampos(resmapOffset + typeListOffset + 2 + i * 8)); - std::string type = ostype(in); - int nRes = (word(in) + 1) & 0xFFFF; - int refListOffset = word(in); - - for(int j = 0; j < nRes; j++) - { - in.seekg(start + std::streampos(resmapOffset + typeListOffset + refListOffset + j * 12)); - int id = word(in); - int nameOffset = word(in); - int attr = byte(in); - int off1 = byte(in); - int off2 = byte(in); - int off3 = byte(in); - int offset = (off1 << 16) | (off2 << 8) | off3; - std::string name; - if(nameOffset != 0xFFFF) - { - in.seekg(start + std::streampos(resmapOffset + nameListOffset + nameOffset)); - int nameLen = byte(in); - char buf[256]; - in.read(buf, nameLen); - name = std::string(buf, nameLen); - } - - in.seekg(start + std::streampos(resdataOffset + offset)); - int size = longword(in); - std::vector tmp(size); - in.read(tmp.data(), size); - std::string data(tmp.data(), size); - - addResource(Resource(type, id, data, name, attr)); - } - } -} // CRC 16 table lookup array static unsigned short CRC16Table[256] =