mirror of
https://github.com/ksherlock/wdc-utils.git
synced 2024-12-12 19:30:38 +00:00
generate express load segment.
This commit is contained in:
parent
960170f831
commit
432a023213
3
link.cpp
3
link.cpp
@ -1093,9 +1093,10 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (flags._o.empty()) flags._o = "out.omf";
|
||||
void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::string &path);
|
||||
|
||||
save_omf(omf_segments, false, "out.omf");
|
||||
save_omf(omf_segments, !flags._X, flags._o);
|
||||
|
||||
|
||||
}
|
||||
|
156
omf.cpp
156
omf.cpp
@ -36,6 +36,28 @@ struct omf_header {
|
||||
uint16_t dispdata = 0;
|
||||
};
|
||||
|
||||
struct omf_express_header {
|
||||
uint32_t lconst_mark;
|
||||
uint32_t lconst_size;
|
||||
uint32_t reloc_mark;
|
||||
uint32_t reloc_size;
|
||||
uint8_t unused1 = 0;
|
||||
uint8_t lablen = 0;
|
||||
uint8_t numlen = 4;
|
||||
uint8_t version = 2;
|
||||
uint32_t banksize = 0;
|
||||
uint16_t kind = 0;
|
||||
uint16_t unused2 = 0;
|
||||
uint32_t org = 0;
|
||||
uint32_t alignment = 0;
|
||||
uint8_t numsex = 0;
|
||||
uint8_t unused3 = 0;
|
||||
uint16_t segnum = 0;
|
||||
uint32_t entry = 0;
|
||||
uint16_t dispname = 0;
|
||||
uint16_t dispdata = 0;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
void push(std::vector<uint8_t> &v, uint8_t x) {
|
||||
@ -67,12 +89,11 @@ void push(std::vector<uint8_t> &v, const std::string &s) {
|
||||
|
||||
void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::string &path) {
|
||||
|
||||
if (expressload) {
|
||||
for (auto &s : segments) {
|
||||
s.segnum++;
|
||||
for (auto &r : s.intersegs) r.segment++;
|
||||
}
|
||||
}
|
||||
// expressload doesn't support links to other files.
|
||||
// fortunately, we don't either.
|
||||
|
||||
std::vector<uint8_t> expr_headers;
|
||||
std::vector<unsigned> expr_offsets;
|
||||
|
||||
int fd;
|
||||
fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
|
||||
@ -81,6 +102,29 @@ void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::
|
||||
}
|
||||
|
||||
|
||||
uint32_t offset = 0;
|
||||
if (expressload) {
|
||||
for (auto &s : segments) {
|
||||
s.segnum++;
|
||||
for (auto &r : s.intersegs) r.segment++;
|
||||
}
|
||||
|
||||
// calculate express load segment size.
|
||||
// sizeof includes the trailing 0, so no need to add in byte size.
|
||||
offset = sizeof(omf_header) + 10 + sizeof("~ExpressLoad");
|
||||
|
||||
offset += 6; // lconst + end
|
||||
offset += 6; // header.
|
||||
for (auto &s : segments) {
|
||||
offset += 8 + 2;
|
||||
offset += sizeof(omf_express_header) + 10;
|
||||
offset += s.segname.length() + 1;
|
||||
}
|
||||
|
||||
lseek(fd, offset, SEEK_SET);
|
||||
}
|
||||
|
||||
|
||||
for (auto &s : segments) {
|
||||
omf_header h;
|
||||
h.length = s.data.size();
|
||||
@ -97,11 +141,20 @@ void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::
|
||||
h.dispname = sizeof(omf_header);
|
||||
h.dispdata = sizeof(omf_header) + data.size();
|
||||
|
||||
|
||||
|
||||
uint32_t lconst_offset = offset + sizeof(omf_header) + data.size() + 5;
|
||||
uint32_t lconst_size = h.length;
|
||||
|
||||
//lconst record
|
||||
push(data, (uint8_t)0xf2);
|
||||
push(data, (uint32_t)h.length);
|
||||
data.insert(data.end(), s.data.begin(), s.data.end());
|
||||
|
||||
|
||||
uint32_t reloc_offset = offset + sizeof(omf_header) + data.size();
|
||||
uint32_t reloc_size = 0;
|
||||
|
||||
// should interseg/reloc records be sorted?
|
||||
// todo -- compress into super records.
|
||||
for (const auto &r : s.relocs) {
|
||||
@ -111,12 +164,14 @@ void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::
|
||||
push(data, (uint8_t)r.shift);
|
||||
push(data, (uint16_t)r.offset);
|
||||
push(data, (uint16_t)r.value);
|
||||
reloc_size += 7;
|
||||
} else {
|
||||
push(data, (uint8_t)0xe5);
|
||||
push(data, (uint8_t)r.size);
|
||||
push(data, (uint8_t)r.shift);
|
||||
push(data, (uint32_t)r.offset);
|
||||
push(data, (uint32_t)r.value);
|
||||
reloc_size += 11;
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,26 +181,107 @@ void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::
|
||||
push(data, (uint8_t)r.size);
|
||||
push(data, (uint8_t)r.shift);
|
||||
push(data, (uint16_t)r.offset);
|
||||
push(data, (uint16_t)r.segment);
|
||||
push(data, (uint16_t)r.segment_offset);
|
||||
push(data, (uint8_t)r.segment);
|
||||
push(data, (uint16_t)r.segment_offset);
|
||||
reloc_size += 8;
|
||||
} else {
|
||||
push(data, (uint8_t)0xe3);
|
||||
push(data, (uint8_t)r.size);
|
||||
push(data, (uint8_t)r.shift);
|
||||
push(data, (uint32_t)r.offset);
|
||||
push(data, (uint16_t)r.file);
|
||||
push(data, (uint32_t)r.segment);
|
||||
push(data, (uint32_t)r.segment_offset);
|
||||
push(data, (uint16_t)r.segment);
|
||||
push(data, (uint32_t)r.segment_offset);
|
||||
reloc_size += 15;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// end-of-record
|
||||
push(data, (uint8_t)0x00);
|
||||
|
||||
h.bytecount = data.size() + sizeof(omf_header);
|
||||
|
||||
// todo -- byteswap to little-endian!
|
||||
offset += write(fd, &h, sizeof(h));
|
||||
offset += write(fd, data.data(), data.size());
|
||||
|
||||
if (expressload) {
|
||||
|
||||
expr_offsets.emplace_back(expr_headers.size());
|
||||
|
||||
if (lconst_size == 0) lconst_offset = 0;
|
||||
if (reloc_size == 0) reloc_offset = 0;
|
||||
|
||||
|
||||
push(expr_headers, (uint32_t)lconst_offset);
|
||||
push(expr_headers, (uint32_t)lconst_size);
|
||||
push(expr_headers, (uint32_t)reloc_offset);
|
||||
push(expr_headers, (uint32_t)reloc_size);
|
||||
|
||||
push(expr_headers, h.unused1);
|
||||
push(expr_headers, h.lablen);
|
||||
push(expr_headers, h.numlen);
|
||||
push(expr_headers, h.version);
|
||||
push(expr_headers, h.banksize);
|
||||
push(expr_headers, h.kind);
|
||||
push(expr_headers, h.unused2);
|
||||
push(expr_headers, h.org);
|
||||
push(expr_headers, h.alignment);
|
||||
push(expr_headers, h.numsex);
|
||||
push(expr_headers, h.unused3);
|
||||
push(expr_headers, h.segnum);
|
||||
push(expr_headers, h.entry);
|
||||
push(expr_headers, (uint16_t)(h.dispname-4));
|
||||
push(expr_headers, h.dispdata);
|
||||
|
||||
expr_headers.insert(expr_headers.end(), 10, ' ');
|
||||
push(expr_headers, s.segname);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (expressload) {
|
||||
omf_header h;
|
||||
h.segnum = 1;
|
||||
h.banksize = 0x00010000;
|
||||
h.kind = 0x8001;
|
||||
h.dispname = 0x2c;
|
||||
h.dispdata = 0x43;
|
||||
|
||||
unsigned fudge = 10 * segments.size();
|
||||
|
||||
h.length = 6 + expr_headers.size() + fudge;
|
||||
|
||||
std::vector<uint8_t> data;
|
||||
data.insert(data.begin(), 10, ' ');
|
||||
push(data, std::string("~ExpressLoad"));
|
||||
push(data, (uint8_t)0xf2); // lconst.
|
||||
push(data, (uint32_t)h.length);
|
||||
|
||||
push(data, (uint32_t)0); // reserved
|
||||
push(data, (uint16_t)(segments.size() - 1)); // seg count - 1
|
||||
|
||||
|
||||
for (auto &offset : expr_offsets) {
|
||||
push(data, (uint16_t)(fudge + offset));
|
||||
push(data, (uint16_t)0);
|
||||
push(data, (uint32_t)0);
|
||||
}
|
||||
|
||||
for (auto &s : segments) {
|
||||
push(data, (uint16_t)s.segnum);
|
||||
}
|
||||
|
||||
data.insert(data.end(), expr_headers.begin(), expr_headers.end());
|
||||
push(data, (uint8_t)0); // end.
|
||||
|
||||
h.bytecount = data.size() + sizeof(omf_header);
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
write(fd, &h, sizeof(h));
|
||||
write(fd, data.data(), data.size());
|
||||
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
Loading…
Reference in New Issue
Block a user