MakeAPPL: factor out resource file code

This commit is contained in:
Wolfgang Thaller 2014-10-08 02:52:15 +02:00
parent cb25b8106c
commit a9c399ff2a
8 changed files with 308 additions and 206 deletions

52
MakeAPPL/BinaryIO.cc Normal file
View File

@ -0,0 +1,52 @@
#include "BinaryIO.h"
#include <iostream>
#include <cassert>
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;
}

17
MakeAPPL/BinaryIO.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef BINARYIO_H
#define BINARYIO_H
#include <iosfwd>
#include <string>
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

View File

@ -16,7 +16,11 @@
# along with Retro68. If not, see <http://www.gnu.org/licenses/>.
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)

38
MakeAPPL/ResType.cc Normal file
View File

@ -0,0 +1,38 @@
#include "ResType.h"
#include <iostream>
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<char>(x >> 24);
char c2 = static_cast<char>(x >> 16);
char c3 = static_cast<char>(x >> 8);
char c4 = static_cast<char>(x);
return std::string{ c1, c2, c3, c4 };
}
std::ostream &operator<<(std::ostream &out, ResType t)
{
char c1 = static_cast<char>((int)t >> 24);
char c2 = static_cast<char>((int)t >> 16);
char c3 = static_cast<char>((int)t >> 8);
char c4 = static_cast<char>((int)t);
out << "'" << c1 << c2 << c3 << c4 << "'";
return out;
}

23
MakeAPPL/ResType.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef RESTYPE_H
#define RESTYPE_H
#include <string>
#include <iosfwd>
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

129
MakeAPPL/ResourceFiles.cc Normal file
View File

@ -0,0 +1,129 @@
#include "ResourceFiles.h"
#include "BinaryIO.h"
#include <iostream>
#include <map>
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<int, int> > resourceInfos;
std::streampos datastart = out.tellp();
for(std::vector<Resource>::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<int, int> >::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<int, int> >::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<int,int>::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<char> tmp(size);
in.read(tmp.data(), size);
std::string data(tmp.data(), size);
addResource(Resource(type, id, data, name, attr));
}
}
}

42
MakeAPPL/ResourceFiles.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef RESOURCEFILES_H
#define RESOURCEFILES_H
#include <string>
#include <vector>
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<Resource> 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

View File

@ -28,6 +28,9 @@
#include <functional>
#include <cstring>
#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<Resource> 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<int, int> > resourceInfos;
std::streampos datastart = out.tellp();
for(std::vector<Resource>::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<int, int> >::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<int, int> >::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<int,int>::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<char> 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] =