home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
177.lha
/
Deemu_v1.0
/
config.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-04-28
|
10KB
|
490 lines
/*
* CONFIG.C
*
* (C)Copyright 1988, Matthew Dillon, All Rights Reserved.
* Permission is granted to distribute for non-profit only.
*
* config file1 file2 file3.... filen
*
* Configure one or more executables. The executables must conform to
* the Static User Modifiable Data Standard (SUMDS)
*
* This program configures the static parameters of C programs which
* contain the appropriate structures. Unknown parameters may be
* configured in raw hex if you know the format.
*/
#include <stdio.h>
#define arysize(array) (sizeof(array)/sizeof(array[0]))
extern void *malloc();
typedef unsigned char ubyte;
typedef unsigned short uword;
typedef unsigned long ulong;
char Show;
char XDebug;
main(ac, av)
char *av[];
{
register short i;
FILE *fi;
long pos, len;
puts("CONFIG V1.00, Matthew Dillon.");
for (i = 1; i < ac; ++i) {
fi = fopen(av[i], "r+");
if (fi == NULL) {
printf("Could not open %s for reading\n", av[i]);
continue;
}
switch(FindData(fi, &pos, &len)) {
case -2:
printf("%s contains unknown hunk #%ld\n", av[i], pos);
break;
case -1:
printf("%s is not an executable\n", av[i]);
break;
case 0:
printf("could not find configuration header in %s\n", av[i]);
break;
case 1:
switch(Configure(fi, pos, len*4)) {
case -3:
printf("Unable to malloc %ld bytes\n", len);
break;
case -2:
puts("Error reading data block or badly formatted data");
break;
case -1:
puts("No 'END ' entry found in header");
break;
case 0:
puts("No modifications made to file");
break;
case 1:
puts("File updated");
break;
}
break;
}
fclose(fi);
}
}
/*
* Search through the beginning of all HUNK_DATA hunks for 'STRT', 0
*
* symb: object modules only, not defined here.
* HUNK_OVERLAY cannot be handled yet.
*/
#define HUNK_UNIT 999 /* N, Nlws of name */
#define HUNK_NAME 1000 /* N, Nlws of name */
#define HUNK_CODE 1001 /* N, Nlws of code */
#define HUNK_DATA 1002 /* N, Nlws of data */
#define HUNK_BSS 1003 /* N (Nlws of bss) */
#define HUNK_RELOC32 1004 /* N, (N+1)lws, N ... 0 */
#define HUNK_RELOC16 1005 /* N, (N+1)lws, N ... 0 */
#define HUNK_RELOC8 1006 /* N, (N+1)lws, N ... 0 */
#define HUNK_EXT 1007 /* N, symb,symb... 0 */
#define HUNK_SYMBOL 1008 /* N, symb,symb... 0 */
#define HUNK_DEBUG 1009 /* N, Nlws of debug */
#define HUNK_END 1010 /* - */
#define HUNK_HEADER 1011 /* N, Nlwsname, N.. 0, tabsize, F, L, F-L+1 sizes */
#define HUNK_OVERLAY 1013 /* tabsize, M+2,M+1 ... ovr data table */
#define HUNK_BREAK 1014 /* - */
FindData(fi, ppos, plen)
FILE *fi;
long *ppos;
long *plen;
{
long type;
long len;
long pos;
long ary[3];
static long buf[256];
if (fread(&type, 4, 1, fi) != 1 || type != HUNK_HEADER)
return(-1);
for (;;) {
if (fread(&len, 4, 1, fi) != 1)
return(-1);
if (len == 0)
break;
fseek(fi, len*4, 1);
}
if (fread(ary, 4, 3, fi) != 3)
return(-1);
fseek(fi, 4*(ary[2] - ary[1] + 1), 1);
while (fread(&type, 4, 1, fi) == 1) {
len = 0;
if (XDebug)
printf("type: %ld\n", type);
switch(type) {
case HUNK_CODE:
fread(&len, 4, 1, fi);
break;
case HUNK_DATA:
fread(&len, 4, 1, fi); /* # of longwords */
pos = ftell(fi);
if (len >= 4) {
register short i;
register short j = (len > arysize(buf)) ? arysize(buf) : len;
register long *ptr;
fread(buf, j, 4, fi);
for (i = 0; i < j; ++i) {
ptr = buf + i;
if (ptr[0] == 'STRT' && ptr[1] == 0) {
*ppos = pos+i*4;
*plen = len - i;
fseek(fi, *ppos, 0);
return(1);
}
ptr = (long *)((short *)ptr + 1);
if (ptr[0] == 'STRT' && ptr[1] == 0) {
*ppos = pos+i*4+2;
*plen = len - i;
fseek(fi, *ppos, 0);
return(1);
}
}
}
fseek(fi, pos, 0);
break;
case HUNK_BSS:
fread(&len, 4, 1, fi);
len = 0;
break;
case HUNK_RELOC32:
case HUNK_RELOC16:
case HUNK_RELOC8:
for (;;) {
if (fread(&len, 4, 1, fi) != 1)
return(-1);
if (len == 0)
break;
++len;
fseek(fi, len*4, 1);
}
break;
case HUNK_SYMBOL:
for (;;) {
if (fread(&len, 4, 1, fi) != 1)
return(-1);
if (len == 0)
break;
len = (len + 1) & 0x00FFFFFF;
if (len <= 32) /* reading is faster */
fread(buf, len, 4, fi);
else /* very long name? */
fseek(fi, len*4, 1);
}
break;
case HUNK_DEBUG:
if (fread(&len, 4, 1, fi) != 1)
return(-1);
break;
case HUNK_END:
break;
default:
*ppos = type;
return(-2);
}
fseek(fi, len*4, 1);
}
return(0);
}
Configure(fi, pos, len)
FILE *fi;
long pos;
long len; /* bytes */
{
register uword *buf = malloc(len+1);
register long i;
short j;
long modified = 0;
short numentries = 0;
len >>= 1; /* Words */
if (buf == NULL)
return(-3);
fseek(fi, pos, 0);
if (fread(buf, len, 2, fi) != 2)
return(-2);
for (i = 4; i < len;) {
if (buf[i] == 'EN' && buf[i+1] == 'D ' && buf[i+2] == 0)
break;
++numentries;
i += 4 + ((buf[i+3]+1)>>1);
}
if (i > len)
return(-2);
if (i == len)
return(-1);
len = i;
printf("%ld entries found\n\n", numentries);
for (i = 4; i < len;) {
register long data = (buf[i]<<16)|buf[i+1];
long dlen = buf[i+3];
uword *ptr = buf + i + 4;
printf("----(%c%c%c%c,%2ld): ", data>>24, data>>16, data>>8, data, dlen);
switch(data) {
case 'NW ':
puts("NEW WINDOW STRUCTURE");
modified += Edit_WINP(ptr, dlen);
break;
case 'TEXT':
puts("TEXT");
modified += Edit_TEXT(ptr, dlen);
break;
default:
puts("UNKNOWN STRUCTURE, HEX EDIT");
modified += Edit_Hex(ptr, dlen);
break;
}
i += 4 + ((dlen+1)>>1);
puts("");
}
{
long response = (modified) ? 0 : 'n';
char ibuf[64];
while (response != 'y' && response != 'n') {
printf("Write data back to file (y/n): ");
fflush(stdout);
if (gets(ibuf) == NULL)
break;
response = ibuf[0] | 0x20;
}
if (response == 'y') {
fseek(fi, pos, 0);
fwrite(buf, len, 2, fi);
return(1);
} else {
return(0);
}
}
}
Edit_WINP(buf, bytes)
char *buf;
short bytes;
{
short i;
short modified = 0;
for (i = 0; i < bytes;) {
switch(i) {
case 0: /* LeftEdge */
modified += strscanvalue(buf+i, 2, "LeftEdge", "(Negative = Relative to Screen Right)");
i += 2;
break;
case 2: /* TopEdge */
modified += strscanvalue(buf+i, 2, "TopEdge", "(Negative = Relative to Screen Bottom)");
i += 2;
break;
case 4: /* Width */
modified += strscanvalue(buf+i, 2, "Width", "(0 = Full Width, < 0 = ScreenWidth - (-width)");
i += 2;
break;
case 6: /* Height */
modified += strscanvalue(buf+i, 2, "Height", "(0 = Full Height, < 0 = ScreenHeight - (-height)");
i += 2;
break;
case 8: /* DetailPen */
modified += strscanvalue(buf+i, 1, "DetailPen", NULL);
++i;
break;
case 9: /* BlockPen */
modified += strscanvalue(buf+i, 1, "BlockPen", NULL);
++i;
break;
case 10: /* IDCMP */
modified += strscanvalue(buf+i, 4, "IDCMP", NULL);
i += 4;
break;
case 14: /* Flags */
modified += strscanvalue(buf+i, 4, "Flags", NULL);
i += 4;
break;
default:
i = bytes;
break;
}
}
return(modified);
}
/*
* Edit TEXT. The buffer holds a 'type' string, \0, then space for a text
* string.
*/
Edit_TEXT(lb, len)
char *lb;
{
register short i, slen;
char buf[256];
char *prompt = lb;
while (*lb) {
++lb;
--len;
}
++lb;
--len;
if (len <= 0) {
puts("TEXT ERROR: UNTERMINATED BUFFER");
return(0);
}
loop:
printf("%-15s (%ld chars max) (%15s) :", prompt, len - 1, lb);
if (gets(buf) == NULL || buf[0] == 0)
strcpy(buf, lb);
if (strcmp(buf, lb) != 0) {
slen = strlen(buf);
if (slen > len - 1) {
printf("Maximum of %ld chars!", len - 1);
goto loop;
}
strcpy(lb, buf);
return(1);
}
return(0);
}
Edit_Extended(i, size, lb)
short i;
char *lb;
{
printf(" #%ld (Blind entry) ", i);
return(scanvalue(lb, size));
}
Edit_Hex(lb, len)
char *lb;
long len;
{
short modified = 0;
short i;
puts(" (Unknown Type, blind data entry)");
for (i = 0; i < len; ++i) {
printf(" Entry %2ld/%2ld ", i, len-1);
modified += scanvalue(lb+i, 1);
}
return(modified);
}
strscanvalue(lb, size, prompt, desc)
char *lb;
char *prompt;
char *desc;
{
if (desc)
printf(" note: %s\n", desc);
printf("%15s ", prompt);
return(scanvalue(lb, size));
}
scanvalue(lb, size)
ubyte *lb;
{
register long val;
register char *str;
short neg;
char buf[128];
top:
switch(size) {
case 1:
val = *lb;
printf("( $%02x %3ld) :", val, (char)val);
break;
case 2:
val = *(uword *)lb;
printf("( $%04x %6ld) :", val, (short)val);
break;
case 4:
val = *(long *)lb;
printf("($%08lx %7ld) :", val, val);
break;
}
fflush(stdout);
neg = 1;
if (gets(buf) && buf[0]) {
val = 0;
str = buf;
if (*str == '-') {
neg = -1;
++str;
}
/* hex */
if (str[0] == '$' || (str[0] == '0' && (str[1]|0x20) == 'x')) {
if (*str++ != '$')
++str;
for (; *str; ++str) {
*str |= 0x20;
if (*str >= '0' && *str <= '9') {
val = (val << 4) | (*str & 15);
continue;
}
if (*str >= 'a' && *str <= 'f') {
val = (val << 4) | (*str - 'a' + 10);
continue;
}
break;
}
} else
if (*str == '%') { /* binary */
for (++str; *str >= '0' && *str <= '1'; ++str)
val = (val << 1) | (*str & 1);
} else if (*str) { /* decimal */
for (; *str >= '0' && *str <= '9'; ++str)
val = val * 10 + *str - '0';
}
if (*str) {
printf("Illegal char '%c', try again\n ? ", *str);
goto top;
}
}
if (neg < 0)
val = -val;
switch(size) {
case 1:
if ((ubyte)val != *lb) {
*lb = val;
return(1);
}
break;
case 2:
if ((uword)val != *(uword *)lb) {
*(uword *)lb = val;
return(1);
}
break;
case 4:
if (val != *(long *)lb) {
*(long *)lb = val;
return(1);
}
break;
}
return(0);
}