this repo has no description
1#include "ResourceFork.h"
2#include "BinaryIO.h"
3
4#include <iostream>
5#include <map>
6#include <vector>
7
8void Resources::addResources(const Resources& res)
9{
10 for(auto& rr : res.resources)
11 addResource(rr.second);
12}
13
14void Resources::writeFork(std::ostream& out) const
15{
16 std::streampos start = out.tellp();
17 longword(out,0x100);
18 longword(out,0);
19 longword(out,0);
20 longword(out,0);
21 for(int i = 0; i < 0x100 - 16; i++)
22 byte(out, 0);
23
24 std::map< ResType, std::map<int, int> > resourceInfos;
25 std::streampos datastart = out.tellp();
26 for(auto& rr : resources)
27 {
28 const Resource& r = rr.second;
29 const std::string& data = r.getData();
30 unsigned offset = out.tellp() - datastart;
31 offset = (r.getAttr() << 24) | (offset & 0xFFFFFF);
32 resourceInfos[ r.getType() ][ r.getID() ] = (int)offset;
33 longword(out, data.size());
34 out << data;
35 }
36 std::streampos dataend = out.tellp();
37// while(out.tellp() % 0x100)
38// out.put(0);
39 std::streampos resmap = out.tellp();
40 for(int i = 0; i < 16+4+2+2; i++)
41 byte(out, 0);
42 word(out,16+4+2+2+2+2); // offset to resource type list
43 std::streampos resnameOffset = out.tellp();
44 word(out,0);
45 std::streampos typelist = out.tellp();
46 word(out,resourceInfos.size() - 1);
47 for(std::map< ResType, std::map<int, int> >::iterator p = resourceInfos.begin();
48 p != resourceInfos.end(); ++p)
49 {
50 if(p->second.size())
51 {
52 ostype(out,p->first);
53 word(out,p->second.size()-1);
54 word(out,0); // replaced later
55 }
56 }
57 int typeIndex = 0;
58 int nameOffset = 0;
59 for(std::map< ResType, std::map<int, int> >::iterator p = resourceInfos.begin();
60 p != resourceInfos.end(); ++p)
61 {
62 if(p->second.size())
63 {
64 std::streampos pos = out.tellp();
65 out.seekp((int)typelist + 2 + 8 * typeIndex + 6);
66 word(out, pos - typelist);
67 out.seekp(pos);
68 typeIndex++;
69
70 for(std::map<int,int>::iterator q = p->second.begin(); q != p->second.end(); ++q)
71 {
72 std::string name = resources.find(ResRef(p->first, q->first))->second.getName();
73 word(out,q->first);
74 if(name.size() == 0)
75 word(out,-1);
76 else
77 {
78 word(out, nameOffset);
79 nameOffset += (name.size() > 255 ? 255 : name.size()) + 1;
80 }
81 longword(out,q->second);
82 longword(out,0);
83 }
84 }
85 }
86 std::streampos resnames = out.tellp();
87 out.seekp(resnameOffset);
88 word(out, resnames - resmap);
89 out.seekp(resnames);
90
91 for(std::map< ResType, std::map<int, int> >::iterator p = resourceInfos.begin();
92 p != resourceInfos.end(); ++p)
93 {
94 for(std::map<int,int>::iterator q = p->second.begin(); q != p->second.end(); ++q)
95 {
96 std::string name = resources.find(ResRef(p->first, q->first))->second.getName();
97 if(name.size() > 0)
98 {
99 int sz = name.size() > 255 ? 255 : name.size();
100 byte(out, sz);
101 for(int i = 0; i < sz; i++)
102 byte(out, name[i]);
103 }
104 }
105 }
106
107 std::streampos end = out.tellp();
108 out.seekp(start + std::streampos(4));
109 longword(out, resmap - start);
110 longword(out, dataend - start - std::streampos(0x100));
111 longword(out, end - resmap);
112 out.seekp(end);
113}
114
115Resources::Resources(std::istream &in)
116{
117 std::streampos start = in.tellg();
118 int resdataOffset = longword(in);
119 int resmapOffset = longword(in);
120
121 in.seekg(start + std::streampos(resmapOffset + 16 + 4 + 2 + 2));
122 int typeListOffset = word(in);
123 int nameListOffset = word(in);
124 int nTypes = (word(in) + 1) & 0xFFFF;
125
126 for(int i = 0; i < nTypes; i++)
127 {
128 in.seekg(start + std::streampos(resmapOffset + typeListOffset + 2 + i * 8));
129 std::string type = ostype(in);
130 int nRes = (word(in) + 1) & 0xFFFF;
131 int refListOffset = word(in);
132
133 for(int j = 0; j < nRes; j++)
134 {
135 in.seekg(start + std::streampos(resmapOffset + typeListOffset + refListOffset + j * 12));
136 int id = (short) word(in);
137 int nameOffset = word(in);
138 int attr = byte(in);
139 int off1 = byte(in);
140 int off2 = byte(in);
141 int off3 = byte(in);
142 int offset = (off1 << 16) | (off2 << 8) | off3;
143 std::string name;
144 if(nameOffset != 0xFFFF)
145 {
146 in.seekg(start + std::streampos(resmapOffset + nameListOffset + nameOffset));
147 int nameLen = byte(in);
148 char buf[256];
149 in.read(buf, nameLen);
150 name = std::string(buf, nameLen);
151 }
152
153 in.seekg(start + std::streampos(resdataOffset + offset));
154 int size = longword(in);
155 std::vector<char> tmp(size);
156 in.read(tmp.data(), size);
157 std::string data(tmp.data(), size);
158
159 addResource(Resource(type, id, data, name, attr));
160 }
161 }
162}