/* relocate -- read relocation data */ static void relocate(int size) { int base, i, m, n, nwords; value *p; unsigned reloc[REL_BLOCK]; for (base = 0; base < size; base += n) { n = min(size - base, REL_BLOCK * CODES_PER_WORD * WORD_SIZE); nwords = (n/WORD_SIZE+CODES_PER_WORD-1)/CODES_PER_WORD; binread(reloc, nwords * sizeof(unsigned)); for (i = 0; i < n; i += WORD_SIZE) { int rbits = reloc_bits(reloc, i/WORD_SIZE); #ifdef DEBUG if (dflag > 2) printf("Reloc %d %d\n", base+i, rbits); #endif m = get_int(&dmem[base+i]); p = (value *) &dmem[base+i]; switch (rbits) { case R_WORD: (*p).i = m; break; case R_DATA: (*p).x = dmem + m; break; case R_CODE: (*p).x = imem + m; break; case R_SUBR: (*p).z = primtab[m]; break; } } } }
// split initial table seg loader to handle only other table types(0x01, 0x02, etc) // let specialized loader below handle all tables referenced // this should simplify the logic requiered in the main loader and keep code // readable and maintainable void IMD_Load0x01(BINHANDLE *infile, IMD_SEG *seg) { WORD curTag = 0; IMD_OFS curOfs; IMD_OFS oldOfs; IMD_VERT_LIST *curVertList = NULL; IMD_COL_VERT_LIST *curColVertList = NULL; IMD_VERT *workingVert = NULL; P6T_TEXTURE *curTexInfo = NULL; P6T_TEXTURE_ENV *curTexEnvInfo = NULL; FILE *bindump = NULL; DWORD i = 0; DWORD numSubBlocks = 0; DWORD realBlockSize = 0; DWORD lastBlockSize = 0; DWORD bytesToRead = 0; DWORD vertBytes = 0; IMD_VERTSUBINFO tempSubInfo; // read first offset and tag binread(&curOfs, sizeof(IMD_OFS), 1, infile); oldOfs.offset = bintell(infile); //setVListBase(NULL); while(curOfs.offset != NULL) { binseek(infile, curOfs.offset, BIN_SET); binread(&curTag, sizeof(WORD), 1, infile); switch(curTag) { case IMD_BLOCK_LINKINFO: printf("LINKINFO @ %x from %x\n", curOfs.offset, oldOfs.offset); binseek(infile, 0xE, BIN_CUR); // skip padding binread(&seg->link, sizeof(IMD_LINK), 1, infile); // if 0x02 block exists, xref start offset, if not loaded, then load and push, set pointer to data in seg struct break; case IMD_BLOCK_HITBOX: printf("HITBOX @ %x from %x\n", curOfs.offset, oldOfs.offset); binseek(infile, 0xE, BIN_CUR); // skip padding binread(seg->hitbox, sizeof(IMD_SIMPLE_VERT)*8, 1, infile); break; case IMD_BLOCK_TEXINFO_MAT: printf("Unsupported block type IMD_BLOCK_TEXINFO_MAT @ %x from %x\n", curOfs.offset, oldOfs.offset); binseek(infile, 0xE, BIN_CUR); // skip padding // unsupported break; case IMD_BLOCK_TEXINFO_ENV: printf("IMD_BLOCK_TEXINFO_ENV @ %x from %x\n", curOfs.offset, oldOfs.offset); binseek(infile, 0xE, BIN_CUR); // skip padding curTexInfo = (P6T_TEXTURE*)malloc((sizeof(P6T_TEXTURE))); memset(curTexInfo, 0, sizeof(P6T_TEXTURE)); binread(curTexInfo, (0x10), 1, infile); pushTex(curTexInfo); break; case IMD_BLOCK_TEXINFO23: case IMD_BLOCK_TEXINFO: printf("TEXINFO @ %x from %x\n", curOfs.offset,oldOfs.offset); binseek(infile, 0x0E, BIN_CUR); // skip padding curTexInfo = (P6T_TEXTURE*)malloc((sizeof(P6T_TEXTURE))); memset(curTexInfo, 0, sizeof(P6T_TEXTURE)); binread(curTexInfo, (sizeof(P6T_TEXTURE)-12), 1, infile); pushTex(curTexInfo); break; case IMD_BLOCK_VERTINFO2: curColVertList = (IMD_COL_VERT_LIST*)malloc(sizeof(IMD_COL_VERT_LIST)); if(getColVList() == NULL) { setColVListBase(curColVertList); seg->vertColLists = curColVertList; } if(curTexInfo != NULL) curColVertList->texID = curTexInfo->texID; else curColVertList->texID = 0; printf("IMD_VERTINFO2 @ %x from %x\n", curOfs.offset,oldOfs.offset); curColVertList->header = (IMD_VERTINFO*)malloc(sizeof(IMD_VERTINFO)); binseek(infile, 0x6, BIN_CUR); binread(curColVertList->header, sizeof(IMD_VERTINFO), 1, infile); binread(&tempSubInfo, sizeof(IMD_VERTSUBINFO), 1, infile); // read first sub info numSubBlocks = curColVertList->header->totalVerts/((tempSubInfo.numVerts*4)+4); if(curColVertList->header->totalVerts % ((tempSubInfo.numVerts*4)+4) != 0) numSubBlocks++; bytesToRead = (tempSubInfo.numVerts*4*4*4); curColVertList->verts = (IMD_COL_VERT*)malloc(bytesToRead*numSubBlocks); curColVertList->realNumVerts = tempSubInfo.numVerts; binread(curColVertList->verts, bytesToRead, 1, infile); for(i = 1; i<=numSubBlocks-1; i++) { binseek(infile, 0x10, BIN_CUR); // skip actual 0x17 tag binread(&tempSubInfo, sizeof(IMD_VERTSUBINFO), 1, infile); // read next sub info bytesToRead = (tempSubInfo.numVerts*4*4*4); binread(&curColVertList->verts[(curColVertList->realNumVerts)], bytesToRead, 1, infile); curColVertList->realNumVerts += tempSubInfo.numVerts; } pushColVList(curColVertList); break; case IMD_BLOCK_VERTINFO3: printf("IMD_VERTINFO3 @ %x from %x\n", curOfs.offset,oldOfs.offset); curVertList = (IMD_VERT_LIST*)malloc(sizeof(IMD_VERT_LIST)); if(getVList() == NULL) { setVListBase(curVertList); seg->vertLists = curVertList; } if(curTexInfo != NULL) curVertList->texID = curTexInfo->texID; else curVertList->texID = 0; curVertList->header = (IMD_VERTINFO*)malloc(sizeof(IMD_VERTINFO)); binseek(infile, 0x6, BIN_CUR); binread(curVertList->header, sizeof(IMD_VERTINFO), 1, infile); binread(&tempSubInfo, sizeof(IMD_VERTSUBINFO), 1, infile); // read first sub info numSubBlocks = curVertList->header->totalVerts/((tempSubInfo.numVerts*3)+4); if(curVertList->header->totalVerts % ((tempSubInfo.numVerts*3)+4) != 0) numSubBlocks++; bytesToRead = (tempSubInfo.numVerts*3*4*4); curVertList->verts = (IMD_VERT*)malloc(bytesToRead*numSubBlocks); curVertList->realNumVerts = tempSubInfo.numVerts; binread(curVertList->verts, bytesToRead, 1, infile); for(i = 1; i<=numSubBlocks-1; i++) { binseek(infile, 0x10, BIN_CUR); // skip actual 0x17 tag binread(&tempSubInfo, sizeof(IMD_VERTSUBINFO), 1, infile); // read next sub info bytesToRead = (tempSubInfo.numVerts*3*4*4); binread(&curVertList->verts[(curVertList->realNumVerts)], bytesToRead, 1, infile); curVertList->realNumVerts += tempSubInfo.numVerts; } pushVList(curVertList); break; case IMD_BLOCK_VERTINFO: printf("IMD_VERTINFO1 @ %x from %x\n", curOfs.offset,oldOfs.offset); curVertList = (IMD_VERT_LIST*)malloc(sizeof(IMD_VERT_LIST)); if(getVList() == NULL) { setVListBase(curVertList); seg->vertLists = curVertList; } if(curTexInfo != NULL) curVertList->texID = curTexInfo->texID; else curVertList->texID = 0; curVertList->header = (IMD_VERTINFO*)malloc(sizeof(IMD_VERTINFO)); binseek(infile, 0x6, BIN_CUR); binread(curVertList->header, sizeof(IMD_VERTINFO), 1, infile); binread(&tempSubInfo, sizeof(IMD_VERTSUBINFO), 1, infile); // read first sub info numSubBlocks = curVertList->header->totalVerts/((tempSubInfo.numVerts*3)+4); if(curVertList->header->totalVerts % ((tempSubInfo.numVerts*3)+4) != 0) numSubBlocks++; bytesToRead = (tempSubInfo.numVerts*3*4*4); curVertList->verts = (IMD_VERT*)malloc(bytesToRead*numSubBlocks); curVertList->realNumVerts = tempSubInfo.numVerts; binread(curVertList->verts, bytesToRead, 1, infile); for(i = 1; i<=numSubBlocks-1; i++) { binseek(infile, 0x10, BIN_CUR); // skip actual 0x17 tag binread(&tempSubInfo, sizeof(IMD_VERTSUBINFO), 1, infile); // read next sub info bytesToRead = (tempSubInfo.numVerts*3*4*4); binread(&curVertList->verts[(curVertList->realNumVerts)], bytesToRead, 1, infile); curVertList->realNumVerts += tempSubInfo.numVerts; } pushVList(curVertList); break; case IMD_BLOCK_TAG_22: //case IMD_BLOCK_TAG_23: case IMD_BLOCK_TAG_24: case IMD_BLOCK_TAG_25: case IMD_BLOCK_TAG_26: //case IMD_BLOCK_TEXINFO_ENV_TEX: case IMD_BLOCK_TAG_50: case IMD_BLOCK_TAG_52: case IMD_BLOCK_TAG_60: case IMD_BLOCK_TAG_68: printf("Unsupported block type %x @ %x from %x\n", curTag, curOfs.offset, oldOfs.offset); break; default: printf("Unknown TAG %x @ %x from %x\n", curTag, curOfs.offset, oldOfs.offset-8); break; } binseek(infile, oldOfs.offset, BIN_SET); binread(&curOfs, sizeof(IMD_OFS), 1, infile); oldOfs.offset = bintell(infile); } }
int main(void){ binwrite(); binread(); txtwrite(); txtread(); }
/* read_int -- input a 4-byte value in portable byte order */ static int read_int() { uchar buf[4]; binread(buf, 4); return get_int(buf); }
static int bingetc(void) { char buf[1]; if (binread(buf, 1) == 0) return EOF; return buf[0]; }
/* load_file -- load a file of object code */ void load_file(FILE *bfp) { trailer t; int i, nread; int seglen[NSEGS]; int start; /* Get trailer */ fseek(bfp, -sizeof(trailer), SEEK_END); nread = fread(&t, 1, sizeof(trailer), bfp); /* Check magic numbers */ if (strncmp((char *) t.magic, MAGIC, 4) != 0) panic("bad magic number\n%s", "[The program you are running is not a valid" " Oberon bytecode file]"); if (get_int(t.sig) != SIG) panic("bad signature %#0.8x\n%s\n%s", get_int(t.sig), "[Although this appears to be an Oberon bytecode file,", " it needs a different version of the runtime system]"); if (prim_check != 0 && (unsigned) get_int(t.primsig) != prim_check) panic("bad primitive checksum\n%s\n%s", "[This program uses a different set of primitives", " from the ones built into the runtime system]"); /* Decode the other data */ for (i = 0; i < NSEGS; i++) seglen[i] = get_int(t.segment[i]); code_size = seglen[S_CODE]; stack_size = seglen[S_STACK]; nmods = get_int(t.nmods); nprocs = get_int(t.nprocs); nsyms = get_int(t.nsyms); start = get_int(t.start); #ifdef DEBUG if (dflag) { printf("csize = %d, dsize = %d, bss = %d, stk = %d\n", seglen[S_CODE], seglen[S_DATA], seglen[S_BSS], seglen[S_STACK]); printf("nmods = %d, nprocs = %d, nsyms = %d\n", nmods, nprocs, nsyms); } #endif fseek(bfp, start, SEEK_END); binfp = bfp; /* Load the code */ imem = (uchar *) scratch_alloc(seglen[S_CODE], TRUE); binread(imem, seglen[S_CODE]); /* Load and relocate the data */ dmem = (uchar *) scratch_alloc(seglen[S_DATA]+seglen[S_BSS], FALSE); binread(dmem, seglen[S_DATA]); relocate(seglen[S_DATA]); memset(dmem+seglen[S_DATA], 0, seglen[S_BSS]); /* Allocate stack */ stack = (uchar *) scratch_alloc(stack_size, FALSE); /* Save the entry point, pointer map and library path */ entry = (value *) &dmem[get_int(t.entry)]; gcmap = (value *) &dmem[get_int(t.gcmap)]; if (get_int(t.libdir) != 0) libpath = (char *) &dmem[get_int(t.libdir)]; /* Read the symbols */ if (nsyms > 0) read_symbols(seglen[S_DATA]); }