home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d3xx
/
d359
/
dice.lha
/
DICE
/
DICE.lzh
/
dutil
/
libtos.c
Wrap
C/C++ Source or Header
|
1990-04-22
|
6KB
|
316 lines
/*
* LIBTOS.C
*
* This program takes two arguments, AMIGA.LIB, and an OUTPUT FILE,
* and systematically converts all references to the variables below
* from ABSOLUTE to A4-RELATIVE (Using Lattice's DATA-REL16 relocation
* info and symbol extensions).
*
* It converts absolute move's into an A4 relative move and a nop to
* take up the extra word which is now no longer used.
*/
#include <stdio.h>
#include <stdlib.h>
short SymLens[64];
char *FixSymbols[64] = {
"_MathBase",
"_ClistBase",
"_ConsoleDevice",
"_DiskfontBase",
"_DOSBase",
"_SysBase",
"_GfxBase",
"_IconBase",
"_IntuitionBase",
"_LayersBase",
"_MathBase",
"_PothoBase",
"_TimerBase",
"_TranslatorBase",
"_MathIeeeDoubBasBase",
"_MathTransBase",
"_ExpansionBase",
"_RomBootBase",
"_MathIeeeDoubTransBase",
/*
* 1.4 stuff (doesn't effect anything if you
* run on a 1.3 amiga.lib)
*
* BETA BETA, developers should add to this
* list as needed.
*/
"_BattClockBase",
"_BattMemBase",
"_CxBase",
"_GadToolsBase",
"_KeymapBase",
"_MathIeeeSingBasBase",
"_MathIeeeSingTransBase",
"_PotgoBase",
"_UtilityBase",
"_WorkbenchBase",
NULL
};
short DDebug;
short Error;
typedef unsigned char ubyte;
typedef unsigned short uword;
typedef unsigned long ulong;
void InitSyms();
#define MAXHUNKS 32
main(ac, av)
char *av[];
{
FILE *fi;
FILE *fo;
short hunkno;
long *base;
long *scan;
long *bend;
long bytes;
InitSyms();
if (ac < 3) {
puts("libtoslib amiga.lib samiga.lib");
exit(1);
}
if (ac > 3)
DDebug = 1;
fi = fopen(av[1], "r");
if (fi == NULL) {
printf("couldn't open %s\n", av[1]);
exit(1);
}
fseek(fi, 0L, 2);
bytes = ftell(fi);
fseek(fi, 0L, 0);
base = malloc(bytes);
if (base == NULL) {
puts("ran out of memory");
exit(1);
}
fread((char *)base, bytes, 1, fi);
fclose(fi);
bend = base + (bytes >> 2);
for (scan = base; scan < bend;) {
ubyte *data;
long dlen;
short htype;
hunkno = 0;
if (*scan != 0x3E7) {
printf("Expected hunk_unit, got %08lx\n", *scan);
exit(1);
}
scan += scan[1] + 2;
/*
* scan the object module
*/
data = NULL;
dlen = 0;
htype = 0;
while (scan < bend && *scan != 0x3E7) {
ulong len;
switch((uword)*scan) {
case 0x3E8: /* HUNK_NAME */
scan += scan[1] + 2;
break;
case 0x3E9: /* HUNK_CODE */
case 0x3EA: /* HUNK_DATA */
data = (char *)(scan + 2);
dlen = scan[1] << 2;
if (*scan == 0x3EA)
htype = 1;
else
htype = 2;
{
++hunkno;
}
scan += scan[1] + 2;
break;
case 0x3EB: /* HUNK_BSS */
htype = 0;
scan += 2;
break;
case 0x3EC: /* HUNK_RELOC32 */
case 0x3ED: /* HUNK_RELOC16-PC */
case 0x3EE: /* HUNK_RELOC8 */
case 0x3F8: /* HUNK_RELOC16-D (special) */
++scan;
while (*scan)
scan += *scan + 2;
++scan;
break;
case 0x3EF: /* HUNK_EXT */
case 0x3F0: /* HUNK_SYMBOL */
++scan;
while (len = *scan) {
ubyte type = len >> 24;
long *base = scan;
len &= 0x00FFFFFF;
if (DDebug)
printf("extsym %3d %.*s\n", type, len*4, scan + 1);
scan += len + 1;
switch(type) {
case 0: /* SYMB */
case 1: /* DEF */
case 2: /* ABS */
case 3: /* RES */
++scan; /* skip value */
break;
case 130: /* COMMON */
++scan; /* skip common size */
/* fall through */
case 129: /* REF32 */
if (type == 129 && htype == 2) {
if (ScanRelocations(scan[0], scan + 1, data, dlen, base + 1, len*4))
*base = (*base & 0x00FFFFFF) | (134 << 24); /* convert from ABS32 to DATA-REL16 */
}
case 131: /* REF16 */
case 132: /* REF8 */
case 134: /* REF16D */
/* skip relocation info */
scan += scan[0] + 1;
break;
default:
printf("Symbol type %d unknown", type);
exit(1);
}
}
++scan; /* skip 0 terminator */
break;
case 0x3F1: /* HUNK_DEBUG */
scan += scan[1] + 2;
break;
case 0x3F2: /* HUNK_END */
data = NULL;
dlen = 0;
++hunkno;
++scan;
break;
default:
printf("Unknown hunk type $%08lx", *scan);
exit(1);
}
}
}
if (Error) {
puts("ERROR OCCURED, OUTPUT NOT WRITTEN");
return(1);
}
fo = fopen(av[2], "w");
if (fo == NULL) {
printf("couldn't create %s\n", av[2]);
return(1);
}
fwrite((char *)base, bytes, 1, fo);
fclose(fo);
return(0);
}
void
InitSyms()
{
short i;
for (i = 0; FixSymbols[i]; ++i) {
SymLens[i] = strlen(FixSymbols[i]);
}
}
ScanRelocations(entries, scan, data, dlen, name, len)
long entries;
long *scan;
char *data;
long dlen;
char *name;
int len;
{
printf("Relocation: %2d relocations for symbol %-20.*s", entries, len, name);
{
short i;
static char Buf[256];
strncpy(Buf, name, len);
Buf[len] = 0;
for (i = 0; SymLens[i]; ++i) {
if (strcmp(FixSymbols[i], Buf) == 0)
break;
}
if (SymLens[i] == 0) {
printf("(%s %d not modified)\n", Buf, strlen(Buf));
return(0);
}
}
puts("(modifying)");
while (entries) {
long index = *scan;
uword *tscan;
uword opcode;
if (index < 0 || index > dlen - 4) {
printf("relocation index out of range: %d/%d\n", index, dlen);
Error = 1;
}
tscan = (uword *)(data + index - 2);
opcode = *tscan;
printf("\topcode %04x\n", opcode);
/*
* convert abs to off(A4) 0010 0000 0110 1100
*/
switch(opcode) {
case 0x2079: /* move.l abslong,A0 */
tscan[0] = 0x206C;
tscan[1] = tscan[2];
tscan[2] = 0x4E71;
break;
case 0x2C79: /* move.l abslong,A6 */
tscan[0] = 0x2C6C;
tscan[1] = tscan[2];
tscan[2] = 0x4E71;
break;
case 0xD1F9: /* adda.l abslong,A0 */
tscan[0] = 0xD1EC;
tscan[1] = tscan[2];
tscan[2] = 0x4E71;
break;
default:
printf("\tWarning, opcode not understood, could not modify\n");
Error = 1;
break;
}
++scan;
--entries;
}
return(1);
}