]> git.sesse.net Git - pistorm/blobdiff - platforms/amiga/hunk-reloc.c
[WIP] PiSCSI custom file system experiments
[pistorm] / platforms / amiga / hunk-reloc.c
index 6421c06d3f67b7f45b26ce0f1da1d5799aab5f2c..4869600f95571b6515a4dae8580fc20afd6db0dc 100644 (file)
@@ -6,13 +6,21 @@
 #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) {
@@ -70,7 +78,7 @@ int process_hunk(uint32_t index, struct hunk_info *info, FILE *f, struct hunk_re
         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;
@@ -80,7 +88,7 @@ int process_hunk(uint32_t index, struct hunk_info *info, FILE *f, struct hunk_re
             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++) {
@@ -114,13 +122,14 @@ int process_hunk(uint32_t index, struct hunk_info *info, FILE *f, struct hunk_re
         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;
@@ -148,24 +157,87 @@ void reloc_hunk(struct hunk_reloc *h, uint8_t *buf, struct hunk_info *i) {
     *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;
+}