#include <endian.h>
#include "hunk-reloc.h"
+#ifdef FAKESTORM
+#define lseek64 lseek
+#endif
+
#define DEBUG(...)
//#define DEBUG printf
+#define BE(val) be32toh(val)
+#define BE16(val) be16toh(val)
+
#define READLW(a, b) fread(&a, 4, 1, b); a = be32toh(a);
#define READW(a, b) fread(&a, 2, 1, b); a = be16toh(a);
-uint32_t lw;
+uint32_t lw = 0;
+static uint32_t file_offset = 0, add_size = 0;
char *hunk_id_name(uint32_t index) {
switch (index) {
case HUNKTYPE_CODE:
DEBUG("Hunk %d: CODE.\n", info->current_hunk);
READLW(discard, f);
- info->hunk_offsets[info->current_hunk] = ftell(f);
+ info->hunk_offsets[info->current_hunk] = ftell(f) - file_offset;
DEBUG("Code hunk size: %d (%.8X)\n", discard * 4, discard * 4);
fseek(f, discard * 4, SEEK_CUR);
return 0;
DEBUG("Processing Reloc32 hunk.\n");
do {
READLW(discard, f);
- if (discard) {
+ if (discard && discard != 0xFFFFFFFF) {
READLW(cur_hunk, f);
DEBUG("Relocating %d offsets pointing to hunk %d.\n", discard, cur_hunk);
for(uint32_t i = 0; i < discard; i++) {
case HUNKTYPE_BSS:
DEBUG("Hunk %d: BSS.\n", info->current_hunk);
READLW(discard, f);
- info->hunk_offsets[info->current_hunk] = ftell(f);
+ info->hunk_offsets[info->current_hunk] = ftell(f) - file_offset;
DEBUG("Skipping BSS hunk. Size: %d\n", discard * 4);
+ add_size += (discard * 4);
return 0;
case HUNKTYPE_DATA:
DEBUG("Hunk %d: DATA.\n", info->current_hunk);
READLW(discard, f);
- info->hunk_offsets[info->current_hunk] = ftell(f);
+ info->hunk_offsets[info->current_hunk] = ftell(f) - file_offset;
DEBUG("Skipping data hunk. Size: %d.\n", discard * 4);
fseek(f, discard * 4, SEEK_CUR);
return 0;
*src_ptr = htobe32(dst);
}
-void process_hunks(FILE *in, struct hunk_info *h_info, struct hunk_reloc *r) {
+void process_hunks(FILE *in, struct hunk_info *h_info, struct hunk_reloc *r, uint32_t offset) {
READLW(lw, in);
DEBUG("Hunk ID: %.8X (%s)\n", lw, hunk_id_name(lw));
- while(!feof(in) && process_hunk(lw, h_info, in, r) != -1) {
+ file_offset = offset;
+ add_size = 0;
+
+ while (!feof(in) && process_hunk(lw, h_info, in, r) != -1) {
READLW(lw, in);
if (feof(in)) goto end_parse;
DEBUG("Hunk ID: %.8X (%s)\n", lw, hunk_id_name(lw));
- DEBUG("File pos: %.8lX\n", ftell(in));
+ DEBUG("File pos: %.8lX\n", ftell(in) - file_offset);
}
end_parse:;
DEBUG("Done processing hunks.\n");
}
void reloc_hunks(struct hunk_reloc *r, uint8_t *buf, struct hunk_info *h_info) {
- for(uint32_t i = 0; i < h_info->reloc_hunks; i++) {
- reloc_hunk(&r[i], buf, h_info);
+ DEBUG("Relocating %d offsets.\n", h_info->reloc_hunks);
+ for (uint32_t i = 0; i < h_info->reloc_hunks; i++) {
DEBUG("Relocating offset %d.\n", i);
+ reloc_hunk(&r[i], buf, h_info);
}
DEBUG("Done relocating offsets.\n");
}
+
+struct LoadSegBlock {
+ uint32_t lsb_ID;
+ uint32_t lsb_SummedLongs;
+ int32_t lsb_ChkSum;
+ uint32_t lsb_HostID;
+ uint32_t lsb_Next;
+ uint32_t lsb_LoadData[123]; // Assumes 512 byte blocks
+};
+#define LOADSEG_IDENTIFIER 0x4C534547
+
+int load_lseg(int fd, uint8_t **buf_p, struct hunk_info *i, struct hunk_reloc *relocs) {
+ if (fd == -1)
+ return -1;
+
+ uint8_t *block = malloc(512);
+ uint32_t next_blk = 0;
+ struct LoadSegBlock *lsb = (struct LoadSegBlock *)block;
+
+ read(fd, block, 512);
+ if (BE(lsb->lsb_ID) != LOADSEG_IDENTIFIER) {
+ DEBUG("[LOAD_LSEG] Attempted to load a non LSEG-block: %.8X", BE(lsb->lsb_ID));
+ goto fail;
+ }
+
+ char *filename = "data/lsegout.bin";
+ FILE *out = fopen(filename, "wb+");
+
+ DEBUG("[LOAD_LSEG] LSEG data:\n");
+ DEBUG("[LOAD_LSEG] Longs: %d HostID: %d\n", BE(lsb->lsb_SummedLongs), BE(lsb->lsb_HostID));
+ DEBUG("[LOAD_LSEG] Next: %d LoadData: %p\n", BE(lsb->lsb_Next), (void *)lsb->lsb_LoadData);
+ next_blk = BE(lsb->lsb_Next);
+ do {
+ next_blk = BE(lsb->lsb_Next);
+ fwrite(lsb->lsb_LoadData, 4, 123, out);
+ lseek64(fd, next_blk * 512, SEEK_SET);
+ read(fd, block, 512);
+ } while (next_blk != 0xFFFFFFFF);
+
+ uint32_t file_size = ftell(out);
+ fseek(out, 0, SEEK_SET);
+ uint8_t *buf = malloc(file_size + 1024);
+ fread(buf, file_size, 1, out);
+ fseek(out, 0, SEEK_SET);
+ process_hunks(out, i, relocs, 0x0);
+
+ fclose(out);
+ *buf_p = buf;
+ i->byte_size = file_size;
+ i->alloc_size = file_size + add_size;
+
+ return 0;
+
+fail:;
+ if (block)
+ free(block);
+
+ return -1;
+}