RetroLinker
Linker for several 8-bit, 16-bit and 32-bit formats
Loading...
Searching...
No Matches
macos.h
1#ifndef MACOS_H
2#define MACOS_H
3
4#include <filesystem>
5#include <optional>
6#include <set>
7#include <vector>
8#include "apple.h"
9#include "../dumper/dumper.h"
10#include "../linker/module.h"
11#include "../linker/segment.h"
12#include "../linker/segment_manager.h"
13#include "../linker/writer.h"
14
15/* Classic 68000 Mac OS file formats */
16
17namespace Apple
18{
19 typedef char OSType[4];
20
21 static constexpr uint32_t OSTypeToUInt32(char type0, char type1, char type2, char type3)
22 {
23 return
24 (uint32_t(uint8_t(type0)) << 24)
25 | (uint32_t(uint8_t(type1)) << 16)
26 | (uint32_t(uint8_t(type2)) << 8)
27 | uint32_t(uint8_t(type3));
28 }
29
30 uint32_t OSTypeToUInt32(const OSType& type);
31 void UInt32ToOSType(OSType& type, uint32_t value);
32
33 /* TODO: rework with Linker::Format */
34
44 {
45 public:
46 bool FormatSupportsResources() const override
47 {
48 return true;
49 }
50
51 enum memory_model_t
52 {
53 MODEL_DEFAULT,
54 MODEL_TINY,
55 };
56 memory_model_t memory_model = MODEL_DEFAULT;
57
58 void SetOptions(std::map<std::string, std::string>& options) override;
59
60 static std::vector<Linker::OptionDescription<void>> MemoryModelNames;
61 std::vector<Linker::OptionDescription<void>> GetMemoryModelNames() override;
62 void SetModel(std::string model) override;
63
64 class Resource : public Linker::Format
65 {
66 public:
68 virtual void ReadFile(Linker::Reader& rd, offset_t length) = 0;
69 void Dump(Dumper::Dumper& dump) const override;
70 virtual int GetDisplayOptions() const;
71 virtual void Dump(Dumper::Dumper& dump, offset_t file_offset) const;
72 virtual void AddFields(Dumper::Dumper& dump, Dumper::Region& region, offset_t file_offset) const;
73 virtual std::unique_ptr<Dumper::Region> CreateRegion(std::string name, offset_t offset, offset_t length, unsigned display_width) const;
74
75 protected:
76 Resource(const char type[4], uint16_t id, uint8_t attributes = 0)
77 : id(id), attributes(attributes)
78 {
79 memcpy(this->type, type, 4);
80 }
81
82 Resource(const char type[4], uint16_t id, std::string name, uint8_t attributes = 0)
83 : id(id), name(name), attributes(attributes)
84 {
85 memcpy(this->type, type, 4);
86 }
87
88 public:
89 char type[4];
90 uint16_t id;
91
92 std::optional<std::string> name;
93 uint8_t attributes;
94
95 offset_t ImageSize() const override = 0;
96
97 virtual void CalculateValues() = 0;
98 };
99
101 {
102 public:
103 GenericResource(const char type[4], uint16_t id)
104 : Resource(type, id)
105 {
106 }
107
108 std::shared_ptr<Linker::Contents> image;
109
110 void CalculateValues() override;
111
112 offset_t ImageSize() const override;
113
114 void ReadFile(Linker::Reader& rd) override;
115 void ReadFile(Linker::Reader& rd, offset_t length) override;
116
118 offset_t WriteFile(Linker::Writer& wr) const override;
119 using Resource::Dump;
120 std::unique_ptr<Dumper::Region> CreateRegion(std::string name, offset_t offset, offset_t length, unsigned display_width) const override;
121 };
122
124 {
125 public:
127 : Resource("CODE", 0)
128 {
129 }
130
131 struct Entry
132 {
133 uint16_t segment;
134 uint32_t offset;
135 };
136
137 uint32_t above_a5 = 0;
138 uint32_t below_a5 = 0;
139 uint32_t jump_table_offset = 32;
140 std::vector<Entry> near_entries;
141 std::vector<Entry> far_entries;
142
143 void CalculateValues() override;
144
145 offset_t ImageSize() const override;
146
147 enum
148 {
149 MOVE_DATA_SP = 0x3F3C,
150 LOADSEG = 0xA9F0,
151 };
152
153 void ReadFile(Linker::Reader& rd) override;
154 void ReadFile(Linker::Reader& rd, offset_t length) override;
155
157 offset_t WriteFile(Linker::Writer& wr) const override;
159 int GetDisplayOptions() const override;
160 void Dump(Dumper::Dumper& dump, offset_t file_offset) const override;
161 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, offset_t file_offset) const override;
162 };
163
164 class CodeResource : public Resource
165 {
166 public:
167 static constexpr uint32_t OSType = OSTypeToUInt32('C', 'O', 'D', 'E');
168
169 std::shared_ptr<JumpTableCodeResource> jump_table;
170 std::shared_ptr<Linker::Contents> image;
171 uint32_t zero_fill = 0; // used for code generation
172
173 CodeResource(uint16_t id, std::shared_ptr<JumpTableCodeResource> jump_table = nullptr)
174 : Resource("CODE", id), jump_table(jump_table)/*, image("code")*/
175 {
176 }
177
178 bool is_far = false; /* TODO: test far segments thoroughly */
179 uint32_t a5_address = 0; /* TODO: meaning */
180 uint32_t base_address = 0; /* TODO: meaning */
181
182 // used for generation
183 std::set<uint16_t> near_entries;
184 uint16_t near_entry_count = 0;
185 // used for generation
186 std::set<uint32_t> far_entries;
187 uint16_t far_entry_count = 0;
188 std::set<uint32_t> a5_relocations;
189 std::set<uint32_t> segment_relocations;
190
191 /* filled in after calculation */
192 uint32_t first_near_entry_offset;
193 uint32_t first_far_entry_offset;
194 uint32_t a5_relocation_offset;
195 uint32_t segment_relocation_offset;
196 uint32_t resource_size;
197
198 void CalculateValues() override;
199
200 offset_t ImageSize() const override;
201
202 void ReadFile(Linker::Reader& rd) override;
203 void ReadFile(Linker::Reader& rd, offset_t length) override;
204
205 uint32_t MeasureRelocations(std::set<uint32_t>& relocations) const;
206
207 void ReadRelocations(Linker::Reader& rd, std::set<uint32_t>& relocations) const;
208 void WriteRelocations(Linker::Writer& wr, const std::set<uint32_t>& relocations) const;
209
211 offset_t WriteFile(Linker::Writer& wr) const override;
213 int GetDisplayOptions() const override;
214 void Dump(Dumper::Dumper& dump, offset_t file_offset) const override;
215 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, offset_t file_offset) const override;
216 std::unique_ptr<Dumper::Region> CreateRegion(std::string name, offset_t offset, offset_t length, unsigned display_width) const override;
217 };
218
220 /*: a5world(".bss")*/
221 {
222 }
223
225 {
226 uint16_t id = 0;
227 uint16_t name_offset = 0xFFFF;
228 std::optional<std::string> name;
229 uint8_t attributes = 0;
230 uint32_t data_offset = 0;
231 std::shared_ptr<Resource> data;
232 };
233
235 {
236 OSType type { 0, 0, 0, 0 };
237 uint32_t count = 0;
238 uint16_t offset = 0;
239 std::vector<ResourceReference> references;
240 };
241
242 static std::shared_ptr<Resource> ReadResource(Linker::Reader& rd, const ResourceType& type, const ResourceReference& reference);
243
244 uint16_t attributes = 0; /* TODO: parametrize */
246 std::vector<ResourceType> resource_types;
248 std::vector<std::string> resource_names;
249
251 std::map<uint32_t, std::map<uint16_t, std::shared_ptr<Resource>>> resources;
252
253 /* these will be calculated */
254 uint32_t data_offset = 0, data_length = 0, map_offset = 0, map_length = 0;
255 uint16_t resource_type_list_offset = 28;
256 uint16_t name_list_offset = 0;
257
258 /* filled in during generation */
259 std::shared_ptr<JumpTableCodeResource> jump_table;
260 std::vector<std::shared_ptr<CodeResource>> codes;
261 std::map<std::shared_ptr<Linker::Segment>, std::shared_ptr<CodeResource>> segments;
262 std::shared_ptr<Linker::Segment> a5world;
263
264 void AddResource(std::shared_ptr<Resource> resource);
265
266 void OnNewSegment(std::shared_ptr<Linker::Segment> segment) override;
267
268 std::unique_ptr<Script::List> GetScript(Linker::Module& module);
269
270 void Link(Linker::Module& module);
271
272 void ProcessModule(Linker::Module& module) override;
273
274 void CalculateValues() override;
275
276 offset_t ImageSize() const override;
277
278 void ReadFile(Linker::Reader& rd) override;
279
281 offset_t WriteFile(Linker::Writer& wr) const override;
282
283 void Dump(Dumper::Dumper& dump) const override;
284
285 void GenerateFile(std::string filename, Linker::Module& module) override;
286
288 std::string GetDefaultExtension(Linker::Module& module) const override;
289 };
290
295 {
296 public:
297 std::shared_ptr<AppleSingleDouble> apple_single;
298
299 enum version_t
300 {
301 /* assigning values to the first two does not matter, because we don't generate the fields that hold them */
302 MACBIN1,
303 MACBIN1_GETINFO, /* extension */
304 MACBIN2 = 0x11,
305 MACBIN3 = 0x12,
306 };
307 version_t version, minimum_version;
308
309 uint16_t secondary_header_size = 0; /* TODO */
310 mutable uint16_t crc = 0;
311
312 uint8_t attributes = 0;
313 uint32_t creation = 0;
314 uint32_t modification = 0;
315
316 /* only used during parsing */
317 uint32_t data_fork_length = 0;
318 uint32_t resource_fork_length = 0;
319 uint16_t comment_length = 0;
320
321 std::string generated_file_name;
322
323 MacBinary(version_t version = MACBIN3)
324 : apple_single(std::make_shared<AppleSingleDouble>(AppleSingleDouble::DOUBLE)), version(version), minimum_version(version <= MACBIN2 ? version : MACBIN2)
325 {
326 }
327
328 MacBinary(version_t version, version_t minimum_version)
329 : apple_single(std::make_shared<AppleSingleDouble>(AppleSingleDouble::DOUBLE)), version(version), minimum_version(version < minimum_version ? version : minimum_version)
330 {
331 }
332
333 explicit MacBinary(std::shared_ptr<AppleSingleDouble> apple, version_t version, version_t minimum_version)
334 : apple_single(apple), version(version), minimum_version(version < minimum_version ? version : minimum_version)
335 {
336 }
337
338 /* CRC16-CCITT */
339 static uint16_t crc_step[256];
340
341 void CRC_Initialize() const;
342
343 void CRC_Step(uint8_t byte = 0) const;
344
345 void Skip(Linker::Writer& wr, size_t count) const;
346
347 void WriteData(Linker::Writer& wr, size_t count, const void * data) const;
348
349 void WriteData(Linker::Writer& wr, size_t count, std::string text) const;
350
351 void WriteWord(Linker::Writer& wr, size_t bytes, uint64_t value) const;
352
353 void ReadHeader(Linker::Reader& rd);
354 void WriteHeader(Linker::Writer& wr) const;
355
356 void CalculateValues();
357
358 void ReadFile(Linker::Reader& rd) override;
359
361 offset_t WriteFile(Linker::Writer& wr) const override;
362
363 void Dump(Dumper::Dumper& dump) const override;
364 };
365
374 {
375 public:
394
409
410 /* Typical combinations:
411 * - Executor: Generate a data fork and an AppleDouble with % prefix
412 * - Basilisk: Generate a data fork, a resource fork (under .rsrc) and a Finder Info file (under .finf)
413 * - Generate a MacBinary with .mbin extension
414 * - Generate an AppleSingle
415 */
416
417 unsigned apple_single_double_version = 2;
418 /* Only relevant for version 1 */
419 AppleSingleDouble::hfs_type home_file_system = AppleSingleDouble::HFS_UNDEFINED;
420
421 MacBinary::version_t macbinary_version = MacBinary::MACBIN3, macbinary_minimum_version = MacBinary::MACBIN2;
422
424 : target(target),
427 : produce_format_t(0))
428 {
429 }
430
433 {
434 }
435
436 bool AddSupplementaryOutputFormat(std::string subformat) override;
437
438 protected:
451
453 std::shared_ptr<AppleSingleDouble> apple_single;
455 std::shared_ptr<MacBinary> mac_binary;
456
458 virtual void OnContainerCreated();
460 virtual void OnCalculateValues();
462 virtual void OnReadFile(Linker::Reader& rd);
464 virtual offset_t OnWriteFile(Linker::Writer& wr) const;
466 virtual void OnDump(Dumper::Dumper& dump) const;
467
468 public:
470 void GenerateFiles(std::string filename, std::shared_ptr<Contents> data_fork, std::shared_ptr<Contents> resource_fork);
471
472 void ReadFile(Linker::Reader& rd) override;
473
475 offset_t WriteFile(Linker::Writer& wr) const override;
476
477 void Dump(Dumper::Dumper& dump) const override;
478 };
479
484 {
485 public:
488 {
489 }
490
493 {
494 }
495
496 bool FormatSupportsResources() const override;
497
498 private:
500 std::shared_ptr<MacintoshResourceFileFormat> resource_fork;
501 std::shared_ptr<FinderInfo> finder_info;
502
503 std::map<std::string, std::string> options;
504 std::string model;
505 std::string script_file;
506 std::map<std::string, std::string> script_options;
507
508 public:
509 void SetOptions(std::map<std::string, std::string>& options) override;
510
511 std::vector<Linker::OptionDescription<void>> GetMemoryModelNames() override;
512 void SetModel(std::string model) override;
513
514 void SetLinkScript(std::string script_file, std::map<std::string, std::string>& options) override;
515
516 void GenerateFile(std::string filename, Linker::Module& module) override;
517
518 protected:
519 void OnContainerCreated() override;
520 void OnCalculateValues() override;
521 void OnReadFile(Linker::Reader& rd) override;
522 offset_t OnWriteFile(Linker::Writer& wr) const override;
523 void OnDump(Dumper::Dumper& dump) const override;
524
525 public:
526 void ReadFile(Linker::Reader& rd) override;
527
528 std::string GetDefaultExtension(Linker::Module& module) const override;
529 std::string GetDefaultExtension(Linker::Module& module, std::string filename) const override;
530 };
531}
532
533#endif /* MACOS_H */
Interface to generate files required for the Classic 68K Mac OS runtime.
Definition macos.h:484
void GenerateFile(std::string filename, Linker::Module &module) override
The main function that handles processing, calculating and generating the final image.
Definition macos.cc:1639
void OnCalculateValues() override
Called if there is no container allocated.
Definition macos.cc:1668
void OnContainerCreated() override
Called after the container is created.
Definition macos.cc:1656
void SetLinkScript(std::string script_file, std::map< std::string, std::string > &options) override
Selects a script file to use for linking.
Definition macos.cc:1633
void OnReadFile(Linker::Reader &rd) override
Called if there is no container allocated.
Definition macos.cc:1673
void SetModel(std::string model) override
Sets the way memory is organized, typically modifying a built-in script.
Definition macos.cc:1628
bool FormatSupportsResources() const override
Whether the format supports resources.
Definition macos.cc:1612
void OnDump(Dumper::Dumper &dump) const override
Called if there is no container allocated.
Definition macos.cc:1692
offset_t OnWriteFile(Linker::Writer &wr) const override
Called if there is no container allocated.
Definition macos.cc:1687
std::string GetDefaultExtension(Linker::Module &module) const override
Provides a default filename for the output file.
Definition macos.cc:1707
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition macos.cc:1697
void SetOptions(std::map< std::string, std::string > &options) override
Passes command line parameters as settings over to format object.
Definition macos.cc:1617
std::vector< Linker::OptionDescription< void > > GetMemoryModelNames() override
Returns a list of the supported memory models, used for documentation.
Definition macos.cc:1622
MacBinary is an alternative format to AppleSingle for representing a Macintosh file on a non-Macintos...
Definition macos.h:295
offset_t WriteFile(Linker::Writer &wr) const override
Stores data in memory to file.
Definition macos.cc:1232
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition macos.cc:1259
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition macos.cc:1203
This is not actually a file format, but an interface to permit generating multiple binary outputs for...
Definition macos.h:374
void GenerateFiles(std::string filename, std::shared_ptr< Contents > data_fork, std::shared_ptr< Contents > resource_fork)
Tasked to create all the requested files.
Definition macos.cc:1366
produce_format_t produce
Bitset of other files to produce.
Definition macos.h:408
container_format_t container
The container type used to store metainformation while processing.
Definition macos.h:450
produce_format_t
Represents what additional files should be generated.
Definition macos.h:397
@ PRODUCE_MAC_BINARY
Creates a MacBinary with the .mbin extension.
Definition macos.h:405
@ PRODUCE_FINDER_INFO
Places a Finder Information file under the directory .finf.
Definition macos.h:401
@ PRODUCE_APPLE_DOUBLE
Creates an AppleDouble binary with the '' prefix.
Definition macos.h:403
@ PRODUCE_RESOURCE_FORK
Places a Macintosh format resource file under the directory .rsrc.
Definition macos.h:399
virtual void OnContainerCreated()
Called after the container is created.
Definition macos.cc:1343
virtual void OnDump(Dumper::Dumper &dump) const
Called if there is no container allocated.
Definition macos.cc:1361
target_format_t target
Format of "filename".
Definition macos.h:393
virtual void OnCalculateValues()
Called if there is no container allocated.
Definition macos.cc:1345
std::shared_ptr< AppleSingleDouble > apple_single
Container for all the necessary additional information.
Definition macos.h:453
std::shared_ptr< MacBinary > mac_binary
Container for MacBinary.
Definition macos.h:455
container_format_t
Format of container stored in memory.
Definition macos.h:441
@ CONTAINER_APPLE_SINGLE
Use an AppleSingle container.
Definition macos.h:445
@ CONTAINER_MAC_BINARY
Use a MacBinary container as well as an AppleSingle container.
Definition macos.h:447
@ CONTAINER_NONE
No container is stored.
Definition macos.h:443
virtual void OnReadFile(Linker::Reader &rd)
Called if there is no container allocated.
Definition macos.cc:1350
target_format_t
Represents the file type of the main file.
Definition macos.h:378
@ TARGET_NONE
Do not generate main file.
Definition macos.h:380
@ TARGET_RESOURCE_FORK
Main file is a resource fork.
Definition macos.h:384
@ TARGET_APPLE_SINGLE
Main file is an AppleSingle.
Definition macos.h:386
@ TARGET_APPLE_DOUBLE
Main file is an AppleDouble.
Definition macos.h:388
@ TARGET_MAC_BINARY
Main file as a MacBinary.
Definition macos.h:390
@ TARGET_DATA_FORK
Main file is a data fork, typically empty.
Definition macos.h:382
bool AddSupplementaryOutputFormat(std::string subformat) override
If the output format actually drives multiple output formats (resource file, apple double,...
Definition macos.cc:1312
virtual offset_t OnWriteFile(Linker::Writer &wr) const
Called if there is no container allocated.
Definition macos.cc:1355
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition macos.cc:1528
offset_t WriteFile(Linker::Writer &wr) const override
Stores data in memory to file.
Definition macos.cc:1577
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition macos.cc:1592
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition macos.cc:371
offset_t ImageSize() const override
Retrieves size of stored data.
Definition macos.cc:291
offset_t WriteFile(Linker::Writer &wr) const override
Stores data in memory to file.
Definition macos.cc:404
offset_t WriteFile(Linker::Writer &wr) const override
Stores data in memory to file.
Definition macos.cc:116
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition macos.cc:106
offset_t ImageSize() const override
Retrieves size of stored data.
Definition macos.cc:101
offset_t WriteFile(Linker::Writer &wr) const override
Stores data in memory to file.
Definition macos.cc:187
offset_t ImageSize() const override
Retrieves size of stored data.
Definition macos.cc:139
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition macos.cc:151
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition macos.cc:66
offset_t ImageSize() const override=0
Retrieves size of stored data.
A Macintosh resource fork.
Definition macos.h:44
void GenerateFile(std::string filename, Linker::Module &module) override
The main function that handles processing, calculating and generating the final image.
Definition macos.cc:942
offset_t ImageSize() const override
Retrieves size of stored data.
Definition macos.cc:725
std::map< uint32_t, std::map< uint16_t, std::shared_ptr< Resource > > > resources
A convenient collection of resources.
Definition macos.h:251
void OnNewSegment(std::shared_ptr< Linker::Segment > segment) override
Callback function when allocating a new segment When the linker script runs, it creates segments cons...
Definition macos.cc:472
bool FormatSupportsResources() const override
Whether the format supports resources.
Definition macos.h:46
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition macos.cc:730
void SetOptions(std::map< std::string, std::string > &options) override
Passes command line parameters as settings over to format object.
Definition macos.cc:31
void SetModel(std::string model) override
Sets the way memory is organized, typically modifying a built-in script.
Definition macos.cc:47
offset_t WriteFile(Linker::Writer &wr) const override
Stores data in memory to file.
Definition macos.cc:805
std::vector< ResourceType > resource_types
A list of all resource types, as stored in the file.
Definition macos.h:246
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition macos.cc:863
std::vector< Linker::OptionDescription< void > > GetMemoryModelNames() override
Returns a list of the supported memory models, used for documentation.
Definition macos.cc:42
std::string GetDefaultExtension(Linker::Module &module) const override
Provides a default filename for the output file.
Definition macos.cc:952
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
Definition macos.cc:674
std::vector< std::string > resource_names
A list of all resource names, as stored in the file.
Definition macos.h:248
void ProcessModule(Linker::Module &module) override
Processes the module object and initializes format fields.
Definition macos.cc:602
An abstract interface that separates structure and presentation of the data inside a file.
Definition dumper.h:828
A record that represents a region within the file.
Definition dumper.h:721
A class to encode a general file format.
Definition format.h:29
virtual void Dump(Dumper::Dumper &dump) const
Display file contents in a nice manner.
Definition format.cc:11
virtual void ReadFile(Reader &rd)=0
Loads file into memory.
offset_t WriteFile(Writer &wr) const override=0
Stores data in memory to file.
Encodes an object module file as a collection of sections, symbols and relocations.
Definition module.h:24
A class that provides a general interface to setting up generation for a format.
Definition format.h:64
virtual std::string GetDefaultExtension(Module &module, std::string filename) const
Appends a default extension to the filename.
A helper class, encapsulating functionality needed to import binary data.
Definition reader.h:20
A helper class to collect sections into segments.
Definition segment_manager.h:32
A helper class, encapsulating functionality needed to export binary data.
Definition writer.h:15