commit 3993520c03cb1dcf7584f1b3fccd339f9711bf83 Author: mikew50 Date: Sun Mar 11 20:33:50 2018 -0600 DumpObj 2.0.1 source from the Opus ][ CD diff --git a/DumpOBJ.cc b/DumpOBJ.cc new file mode 100755 index 0000000..481f32a --- /dev/null +++ b/DumpOBJ.cc @@ -0,0 +1 @@ +/************************************************************** * * DumpOBJ 2.0 * * By Phil Montoya * Translation to ORCA/C & 2.0 enhancements by Mike Westerfield. * * DumpOBJ 1.1 Copyright November 1986-88 * By the Byte Works, Inc. * * DumpOBJ 2.0 Copyright 1991 * Byte Works, Inc. * **************************************************************** * * Version 2.0.1, 7 July 94 * Mike Westerfield * * 1. Added resource fork. * ****************************************************************/ #pragma keep "DumpOBJ" #pragma optimize 9 /* GS specific declarations */ /*--------------------------*/ extern pascal void PDosInt(); int toolerror(void); #define WRITE_CONSOLE(parm) (PDosInt(0x015A,parm)) #define GetFileInfoGS(pBlockPtr) PDosInt(0x2006,pBlockPtr) #pragma lint -1 /* Standard C Libraries */ /*----------------------*/ #include #include #include #include /* Constants */ /*-----------*/ #define BOOLEAN int /* boolean variables */ #define TRUE 1 #define FALSE 0 #define FILEMAX 1024 /* max length of file name */ #define NAMEMAX 512 /* maximum size of variable len name */ #define NAMESIZE 11 /* size of label name */ #define OBJFL 177 /* minimum object file type */ #define MAXFL 190 /* maximum object file type */ #define LIBFL 178 /* library file type */ #define BLKSIZE 512 /* size of block */ #define COP 2 /* COP opcode */ #define REP 194 /* REP opcode */ #define SEP 226 /* SEP opcode */ /* Object File Opcodes */ /*---------------------*/ #define OPALIGN 224 /* align to a boundry */ #define OPORG 225 /* set code origin */ #define OPRELOC 226 /* relocation entry */ #define OPINTSEG 227 /* inserseg record */ #define OPUSING 228 /* use data area */ #define OPSTRONG 229 /* force segment inclusion */ #define OPGLOBAL 230 /* define global label */ #define OPGEQU 231 /* define global constant */ #define OPMEM 232 /* reserve absolute memory */ #define OPEXPR 235 /* computed value */ #define OPZEXPR 236 /* computed zero page value */ #define OPBEXPR 237 /* computed local bank value */ #define OPRELEXPR 238 /* computed relative ofset */ #define OPLOCAL 239 /* define local label */ #define OPEQU 240 /* define local constant */ #define OPDS 241 /* define storage */ #define OPLONG 242 /* long constant > $DF bytes */ #define OPLEXPR 243 /* outer segment expression */ #define OPENTRY 244 /* run time lib entry dictionary */ #define OPSRELOC 245 /* short relocation entry */ #define OPSINTSEG 246 /* short interseg entry */ #define OPSUPER 247 /* super compressed records */ /* Program variables */ /*-------------------*/ char fname[FILEMAX]; /* input file name buffer */ char nlist[NAMEMAX]; /* names list */ char symbol[NAMEMAX]; /* symbol name buffer */ BOOLEAN names; /* names list flag */ BOOLEAN sTable; /* found a COP symbol table? */ int act_lablen; /* actual length of label read */ int status; /* shell return status */ int namc; /* name argument counter */ int ftype; /* current file type */ long blocks; /* used to get to next segment */ long constant; /* constant byte counter and flag */ long opcode; /* opcode storage */ long segmark; /* start of segment marker */ long count; /* file counter */ long number; /* number read variable */ long pc; /* segment program counter */ long tkind; /* type of node for tree */ long *root; /* root pointer for expression tree */ FILE *input; /* input file */ /* Output Control Settings */ /*-------------------------*/ int format; /* format of output 0 opcode dump 1 dissassembly dump 2 hex dump */ BOOLEAN shorth; /* print short headers? */ BOOLEAN ireg; /* long index registers? */ BOOLEAN mreg; /* long accumulator? */ BOOLEAN longc; /* print long constants? */ BOOLEAN header; /* print segment headers? */ BOOLEAN body; /* print segment bodies? */ BOOLEAN checkf; /* check file types? */ BOOLEAN colf; /* print displacement numbers? */ /* Object Module Header */ /*----------------------*/ int kind; /* kind of segment */ long blkcnt; /* number of block in segment */ long resspc; /* reserved space at end of segment */ long length; /* length of finished segment */ int kind1; /* this is kind for version 1 */ int lablen; /* label length */ int numlen; /* number length */ int version; /* version number */ long banksize; /* banksize */ int kind2; /* this is kind for version 2 */ int unused; /* undefined field */ long pgorg; /* program org */ long align; /* alignment factor */ int numsex; /* significance of numbers */ int lang_card; /* language card */ int segnum; /* segment number */ long ent_disp; /* disp to beg of segment */ int nam_disp; /* displacment to names */ int bod_disp; /* displacment to body */ char loadname[NAMESIZE]; /* load file name */ char segname[NAMEMAX]; /* segment name */ /* Opcode arrays */ /*---------------*/ char opKind[] = {5,8,5,14,2,2,2,13,5,1,4,5,2,2,2,3, 17,6,12,15,2,9,9,7,5,10,4,5,2,9,9,11, 2,8,2,14,2,2,2,13,5,1,4,5,2,2,2,3, 17,6,12,15,9,9,9,7,5,10,4,5,9,9,9,11, 5,8,5,14,16,2,2,13,5,1,4,5,2,2,2,3, 17,6,12,15,16,9,9,7,5,10,5,5,3,9,9,11, 5,8,5,14,2,2,2,13,5,1,4,5,12,2,2,3, 17,6,12,15,9,9,9,7,5,10,5,5,8,9,9,11, 17,8,17,14,2,2,2,13,5,1,5,5,2,2,2,3, 17,6,12,15,9,9,10,7,5,10,5,5,2,9,9,11, 1,8,1,14,2,2,2,13,5,1,5,5,2,2,2,3, 17,6,12,15,9,9,10,7,5,10,5,5,9,9,10,11, 1,8,1,14,2,2,2,13,5,1,5,5,2,2,2,3, 17,6,12,15,5,9,9,7,5,10,5,5,12,9,9,11, 1,8,1,14,2,2,2,13,5,1,5,5,2,2,2,3, 17,6,12,15,5,9,9,7,5,10,5,5,8,9,9,11}; char opLen[] = {1,1,1,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,2,2,2,3, 2,1,3,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,2,2,2,3, 0,1,0,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,3,2,2,3, 0,1,2,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,2,2,2,3, 1,1,2,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,2,2,2,3, 5,1,5,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,2,2,2,3, 5,1,1,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,2,2,2,3, 5,1,1,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,2,1,1,1,0,2,0,0,2,2,2,3}; char opName[] = "BRKORACOPORATSBORAASLORAPHPORAASLPHDTSBORAASLORA" "BPLORAORAORATRBORAASLORACLCORAINCTCSTRBORAASLORA" "JSRANDJSLANDBITANDROLANDPLPANDROLPLDBITANDROLAND" "BMIANDANDANDBITANDROLANDSECANDDECTSCBITANDROLAND" "RTIEORWDMEORMVPEORLSREORPHAEORLSRPHKJMPEORLSREOR" "BVCEOREOREORMVNEORLSREORCLIEORPHYTCDJMPEORLSREOR" "RTSADCPERADCSTZADCRORADCPLAADCRORRTLJMPADCRORADC" "BVSADCADCADCSTZADCRORADCSEIADCPLYTDCJMPADCRORADC" "BRASTABRLSTASTYSTASTXSTADEYBITTXAPHBSTYSTASTXSTA" "BCCSTASTASTASTYSTASTXSTATYASTATXSTXYSTZSTASTZSTA" "LDYLDALDXLDALDYLDALDXLDATAYLDATAXPLBLDYLDALDXLDA" "BCSLDALDALDALDYLDALDXLDACLVLDATSXTYXLDYLDALDXLDA" "CPYCMPREPCMPCPYCMPDECCMPINYCMPDEXWAICPYCMPDECCMP" "BNECMPCMPCMPPEICMPDECCMPCLDCMPPHXSTPJMLCMPDECCMP" "CPXSBCSEPSBCCPXSBCINCSBCINXSBCNOPXBACPXSBCINCSBC" "BEQSBCSBCSBCPEASBCINCSBCSEDSBCPLXXCEJSRSBCINCSBC"; /**** Utility Subroutines *****************************************/ /*************************************************************** * * fgeti - read an integer from the file * * Inputs: * f - file to read from * * Outputs: * Returns integer read * ***************************************************************/ int fgeti (FILE *f) { return fgetc(f) | (fgetc(f) << 8); } /*************************************************************** * * Error - Writes out an error * ***************************************************************/ void Error (int errnum, char *str) { status = -1; switch (errnum) { case 1: fputs("Format type not supported", stderr); break; case 2: fputs("Could not read segment header", stderr); break; case 3: fputs("Segment version not supported", stderr); break; case 4: fputs("Bad input ", stderr); break; case 5: fputs("Could not open file ", stderr); break; case 6: fputs("Not an object file ", stderr); break; case 7: fputs("Unknown Opcode", stderr); break; case 8: fputs("Illegal header entry", stderr); break; case 9: fputs("End of file encountered", stderr); default: break; } if (str[0] != ' ') fputs(str, stderr); fputc('\n', stderr); } /*************************************************************** * * CheckESC - Checks to see if 'escape' is pressed * * Notes: Returns to shell if open-apple period has been pressed. * ***************************************************************/ void CheckESC (void) { char *keyboard; char *strobe; char *flags; struct { int pcount; char ch; } parm; keyboard = (void *) 0x00C000; strobe = (void *) 0x00C010; flags = (void *) 0x00C025; if (*keyboard & 0x80) { if ((*keyboard & 0x7F) == '.') if (*flags & 0x80) { *strobe = (char) 0; exit(-1); } *strobe = (char) 0; parm.pcount = 1; parm.ch = (char) 27; WRITE_CONSOLE(&parm); parm.ch = (char) 15; WRITE_CONSOLE(&parm); parm.ch = (char) 0x43; WRITE_CONSOLE(&parm); parm.ch = (char) 24; WRITE_CONSOLE(&parm); parm.ch = (char) 14; WRITE_CONSOLE(&parm); parm.ch = (char) 8; WRITE_CONSOLE(&parm); while (! (*keyboard & 0x80)) ; parm.ch = (char) 32; WRITE_CONSOLE(&parm); parm.ch = (char) 8; WRITE_CONSOLE(&parm); if ((*keyboard & 0x7F) == '.') if (*flags & 0x80) { *strobe = (char) 0; exit(-1); } *strobe = (char) 0; } } /**** Segment I/O Subroutines *************************************/ /*************************************************************** * * Checks and updates output header information. * * Returns: * TRUE - if header OK. * FALSE - if header not OK and flags error. * ****************************************************************/ BOOLEAN CheckHead (void) { long talign; if ((version != 1) && (version != 2)) { Error(3," "); return FALSE; } if ((lablen > 256) || (numlen > 4) || (numlen < 1)) { Error(8," "); return FALSE; } if (align) { /* insure only 1 bit set in alignment */ talign = align; while (! (talign & 1)) talign = talign >> 1; if (talign != 1) { Error(8," "); return FALSE; } } return TRUE; } /*************************************************************** * * GetEOF - Returns The End of File Marker * * Returns: mark or -1 if error * ***************************************************************/ long GetEOF (FILE *f) { long mark, pos; pos = ftell(f); if (pos == -1) return -1; if (fseek(f, -1, SEEK_END)) return -1; mark = ftell(f)+1; if (pos == -1) return -1; if (fseek(f, pos, SEEK_SET)) return -1; return mark; } /*************************************************************** * * GetHead - Reads In The Segment Header * * Inputs: * f - file to read the header from * ***************************************************************/ int GetHead (FILE *f) { struct { long blkcnt, resspc, length; char kind1, lablen, numlen, version; long banksize; int kind2, unused; long pgorg, align; char numsex, lang_card; int segnum; long ent_disp; int nam_disp, bod_disp; } header; int i, disp, len; fseek(f, 0, SEEK_CUR); /* read the common parts of the header */ if (fread(&header, sizeof(header), 1, f) != 1) return -1; blkcnt = header.blkcnt; resspc = header.resspc; length = header.length; kind1 = header.kind1; lablen = header.lablen; numlen = header.numlen; version = header.version; banksize = header.banksize; kind2 = header.kind2; unused = header.unused; pgorg = header.pgorg; align = header.align; numsex = header.numsex; lang_card = header.lang_card; segnum = header.segnum; ent_disp = header.ent_disp; nam_disp = header.nam_disp; bod_disp = header.bod_disp; disp = nam_disp-sizeof(header); /* skip any extra stuff */ if (disp) for (i = 0; i < disp; ++i) fgetc(f); for (i = 0; i < 10; ++i) /* read the load segment name */ loadname[i] = fgetc(f); loadname[10] = (char) 0; len = fgetc(f); /* read the code segment name */ for (i = 0; i < len; ++i) segname[i] = fgetc(f); segname[len] = (char) 0; if (version == 2) /* set the kind field */ kind = kind2; else kind = kind1; return 0; } /*************************************************************** * * IsInList - Checks to see if segment is in names list * ***************************************************************/ BOOLEAN IsInList (void) { int len, chpos; if (! names) return TRUE; len = chpos = 0; /* get length of segment name */ while (isalnum(segname[len]) || (segname[len] == '~') || (segname[len] == '_')) len++; while (nlist[chpos]) { /* see if name matches a list name */ while (nlist[chpos] == ' ') chpos++; if ((! strncmp(segname,nlist+chpos,len)) && ((nlist[chpos+len] == ' ') || (! nlist[chpos+len]))) return TRUE; while ((nlist[chpos]) && (nlist[chpos] != ' ')) chpos++; } return FALSE; } /*************************************************************** * * NextSeg - Returns the next segment * * Output: * positions file marker at next segment 0 if at end of file * ***************************************************************/ BOOLEAN NextSeg(void) { if ((format == 2) || ((format == 1) && !header && !checkf)) { numsex = 0; return TRUE; } do { if ((ftype == LIBFL) || (version == 2)) { if (fseek(input, segmark + blocks, SEEK_SET)) return FALSE; } else { if (fseek(input,segmark + (blocks * BLKSIZE), SEEK_SET)) return FALSE; } segmark = ftell(input); /* set next segment marker */ if (segmark >= (GetEOF(input))) return FALSE; GetHead(input); blocks = blkcnt; if (! blocks) return FALSE; fseek(input, segmark, SEEK_SET); } while (! IsInList()); /* check to see if in names list */ return TRUE; } /*************************************************************** * * PutComment - Writes a comment line if colf is not active * ***************************************************************/ void PutComment (void) { if (! colf) printf("! "); } /*************************************************************** * * PutKind - Writes out the kind in name format * ***************************************************************/ void PutKind (int kind) { if (version == 1) { if (kind & 128) printf("dynamic "); else printf("static "); if (kind & 64) printf("private "); if (kind & 32) printf("position independent "); } else { if (kind & 32768) printf("dynamic "); else printf("static "); if (kind & 16384) printf("private "); if (kind & 8192) printf("position independent "); if (kind & 4096) printf("no special memory "); if (kind & 2048) printf("absolute bank "); if (kind & 1024) printf("reload "); } switch(kind & 31) { case 0: printf("code segment"); break; case 1: printf("data segment"); break; case 2: printf("jump table segment"); break; case 4: printf("pathname segment"); break; case 8: printf("library dictionary segment"); break; case 16: printf("initialization segment"); break; case 17: printf("absolute bank segment"); break; case 18: printf("direct page/stack segment"); break; default: printf("unknown segment: $04X", kind); } } /*************************************************************** * * PutHeader - Writes Out The Header * * Returns: FALSE if an error was found, else TRUE. * ***************************************************************/ BOOLEAN PutHeader (void) { long mark; int kind2; mark = ftell(input); /* save the file marker */ if (GetHead(input)) { Error(2," "); return FALSE; } if ((checkf) && ((version != 1) && (version != 2))) { Error(3," "); return FALSE; } blocks = blkcnt; /* set the new block counter */ if (! header) /* split on write/don't write header */ fseek(input,mark,SEEK_SET); else { count = ftell(input) - mark; /* set the file counter */ if (shorth) { /* split on short or long header */ PutComment(); printf("%s (", segname); PutKind(kind); printf(")\n"); return CheckHead(); } else { /* print the full header */ PutComment(); /* write block count */ if (version == 2) printf("Byte count : $%08lX%14ld\n", blkcnt, blkcnt); else printf("Block count : $%08lX%14ld\n", blkcnt, blkcnt); CheckESC(); PutComment(); /* write reserved space */ printf("Reserved space: $%08lX%14ld\n", resspc, resspc); CheckESC(); PutComment(); /* write segment length */ printf("Length : $%08lX%14ld\n", length, length); CheckESC(); PutComment(); /* write label length */ printf("Label length : $%02X%20d\n", lablen, lablen); CheckESC(); PutComment(); /* write number length */ printf("Number length : $%02X%20d\n", numlen, numlen); CheckESC(); PutComment(); /* write segment version */ printf("Version : $%02X%20d\n", version, version); CheckESC(); PutComment(); /* write bank size */ printf("Bank size : $%08lX%14ld\n", banksize, banksize); CheckESC(); PutComment(); /* write segment kind */ if (version == 2) { printf("Kind : $%04X%18d (", kind, kind); kind2 = kind; } else { printf("Kind : $%02X%20d (", kind, kind); kind2 = ((kind & 0xE0) << 8) | (kind & 0x1F); } switch (kind & 0x001F) { case 0x00: printf("code"); break; case 0x01: printf("data"); break; case 0x02: printf("jump table"); break; case 0x04: printf("pathname"); break; case 0x08: printf("library"); break; case 0x10: printf("initialization"); break; case 0x11: printf("absolute bank"); break; case 0x12: printf("direct-page/stack"); break; default: printf("unknown"); break; } if (kind & 0x8000) printf(",dynamic"); else printf(",static"); if (kind & 0x4000) printf(",private"); if (kind & 0x2000) printf(",position independent"); if (kind & 0x1000) printf(",no special memory"); if (kind & 0x0800) printf(",absolute bank"); if (kind & 0x0400) printf(",reload"); if (kind & 0x0200) printf(",skip"); if (kind & 0x0100) printf(",bank relative"); printf(")\n"); CheckESC(); PutComment(); /* write segment org */ printf("Org : $%08lX%14ld\n", pgorg, pgorg); CheckESC(); PutComment(); /* write alignment factor */ printf("Alignment : $%08lX%14ld\n", align, align); CheckESC(); PutComment(); /* write number sex */ printf("Number sex : $%02X%20d\n", numsex, numsex); CheckESC(); if (version == 1) { /* write language card */ PutComment(); printf("Language card : $%02X%20d\n", lang_card, lang_card); CheckESC(); } PutComment(); /* write segment number */ printf("Segment number: $%04X%18d\n", segnum, segnum); CheckESC(); PutComment(); /* write segment entry */ printf("Segment entry : $%08lX%14ld\n", ent_disp, ent_disp); CheckESC(); PutComment(); /* write segment names disp */ printf("Disp to names : $%04X%18d\n", nam_disp, nam_disp); CheckESC(); PutComment(); /* write segment body disp */ printf("Disp to body : $%04X%18d\n", bod_disp, bod_disp); CheckESC(); if (! CheckHead()) /* don't print labels if header error */ return FALSE; PutComment(); /* write load name */ printf("Load name : %s\n", loadname); CheckESC(); PutComment(); /* write segment name */ printf("Segment name : %s\n", segname); CheckESC(); } } return TRUE; } /**** Opcode Dump Subroutines *************************************/ void DoExpr (void); /*************************************************************** * * Reads the opcode into "opcode" * ***************************************************************/ int GetOpCode (void) { ++count; /* advance byte counter */ opcode = fgetc(input); if (opcode == -1) { /* check for end of file */ opcode = 0; Error(9," "); /* end of file encountered */ exit(status); } return opcode; } /*************************************************************** * * NewLine - Issues a Formatted New Line * ***************************************************************/ void NewLine (void) { int count; putchar('\n'); if (colf) count = 33; else count = 17; while (count--) putchar(' '); } /*************************************************************** * * ReadInt - reads an integer * * Inputs: * numsex - number sex * input - reference number of file * numlen - length of number * nPtr - pointer to place result * ***************************************************************/ void ReadInt (long *nPtr, int numlen, FILE *f, int numsex) { int i; long k,n; union { char c[4]; long l; } u; if (numlen <= 4) { u.l = 0; for (i = 0; i < numlen; ++i) u.c[i] = fgetc(f); *nPtr = u.l; if (numsex) { n = *nPtr; for (i = 0; i < 4; ++i) { k = (k << 8) | (n && 0xFF); n = n >> 8; } *nPtr = k; } } } /*************************************************************** * * ReadName - reads in a symbol name * * Inputs: * name - pointer to place the name * lablen - length of name * f - open file ref number * ***************************************************************/ void ReadName (char *name, int lablen, FILE *f) { int i; if (lablen) /* get the label length */ act_lablen = lablen; else act_lablen = fgetc(f); for (i = 0; i < act_lablen; ++i) /* read the name */ name[i] = fgetc(f); name[act_lablen] = (char) 0; /* set the null terminator */ } /*************************************************************** * * PrintW - Writes a word in a string to the console * * Inputs: * str - pointer to the string to write * ***************************************************************/ void PrintW (char *str) { int i = 0; while ((str[i]) && (! isspace(str[i]))) putchar(str[i++]); } /*************************************************************** * * PutConst - Writes the constant bytes for opcode format * * Inputs: * len - number of bytes to write * input - file to get bytes from * ***************************************************************/ void PutConst (long len, int flag) { long k; int i; if (flag) { /* see if we print out record */ i = 0; for (k = 0; k < len; ++k) { ++i; /* allow 23 numbers per line */ if (i == 24) { /* see if we need to issue a new line */ i = 1; NewLine(); } printf("%02X", (int) fgetc(input)); /* write the hex */ CheckESC(); } } else fseek(input, ftell(input)+len, SEEK_SET); } /*************************************************************** * * PutCTPC - Writes the count and program counter * ***************************************************************/ void PutCTPC(void) { putchar('\n'); if (colf) /* check to make sure you write col */ printf("%06lX %06lX | ", count, pc); } /*************************************************************** * * PutNumber - Writes a number * * Inputs: * input - input file * * Outputs: * number - contains number read * ***************************************************************/ void PutNumber (void) { ReadInt(&number,numlen,input,numsex); switch (numlen) { case 1: printf("%02X", (int) number); case 2: printf("%04X", (int) number); case 3: printf("%06lX", (long) number); case 4: printf("%08lX", (long) number); } count = count + numlen; } /*************************************************************** * * Putsymbol - Writes the symbol * * Inputs: * input - input file * * Outputs: * symbol - symbol read * ***************************************************************/ void PutSymbol (void) { ReadName(symbol,lablen,input); PrintW(symbol); if (lablen) count = count + lablen; else count = count + act_lablen + 1; } /*************************************************************** * * PutOpCode - Writes the opcode * * Inputs: * opcode - opcode to write * input - input file * * Outputs: * write opcode * pc, count = updates accordingly * ***************************************************************/ void PutOpCode (void) { long k; int p1, p2, p3; /* temp storage for calculated parms */ if (opcode < OPALIGN) { /* handle short constant opcode */ printf("CONST ($%02X) | ", (int) opcode); pc = pc + opcode; count = count + opcode; PutConst(opcode,longc); /* write the constant opcodes */ } else switch (opcode) { case OPALIGN: /* handle align opcode */ printf("ALIGN ($E0) | "); PutNumber(); pc = pc + (pc % number); break; case OPORG: /* handle org opcode */ printf("ORG ($E1) | "); PutNumber(); pc = pc + number; break; case OPRELOC: /* handle reloc opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("RELOC ($E2) | %02X : %02X : ", p1, p2); PutNumber(); printf(" : "); PutNumber(); count = count + 2; break; case OPINTSEG: /* handle interseg opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("INTERSEG ($E3) | %02X : %02X : ", p1, p2); PutNumber(); printf(" : "); ReadInt(&number,2,input,numsex); printf("%04X : ", (int) number); ReadInt(&number,2,input,numsex); printf("%04X : ", (int) number); PutNumber(); count = count + 6; break; case OPUSING: /* handle using opcode */ printf("USING ($E4) | "); PutSymbol(); break; case OPSTRONG: /* handle strong opcode */ printf("STRONG ($E5) | "); PutSymbol(); break; case OPGLOBAL: /* handle global opcode */ printf("GLOBAL ($E6) | "); PutSymbol(); if (version == 1) { p1 = fgetc(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %02X : %02X : %02X", p1, p2, p3); count = count + 3; } else { p1 = fgeti(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %04X : %02X : %02X", p1, p2, p3); count = count + 4; } break; case OPGEQU: /* handle gequ opcode */ printf("GEQU ($E7) | "); PutSymbol(); if (version == 1) { p1 = fgetc(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %02X : %02X : %02X :", p1, p2, p3); count = count + 3; } else { p1 = fgeti(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %04X : %02X : %02X :", p1, p2, p3); count = count + 4; } DoExpr(); break; case OPMEM: /* handle mem opcode */ printf("MEM ($E8) | "); PutNumber(); printf(" : "); PutNumber(); break; case OPEXPR: /* handle expr opcode */ k = fgetc(input); count++; printf("EXPR ($EB) | %02X :", (int) k); pc = pc + k; DoExpr(); break; case OPZEXPR: /* handle zexpr opcode */ k = fgetc(input); count++; printf("ZEXPR ($EC) | %02X :", (int) k); pc = pc + k; DoExpr(); break; case OPBEXPR: /* handle bexpr opcode */ k = fgetc(input); count++; printf("BEXPR ($ED) | %02X :", (int) k); pc = pc + k; DoExpr(); break; case OPRELEXPR: /* handle relexpr opcode */ k = fgetc(input); count++; printf("RELEXPR ($EE) | %02X : ", (int) k); PutNumber(); pc = pc + k; printf(" :"); DoExpr(); break; case OPLOCAL: /* handle local opcode */ printf("LOCAL ($EF) | "); PutSymbol(); if (version == 1) { p1 = fgetc(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %02X : %02X : %02X", p1, p2, p3); count = count + 3; } else { p1 = fgeti(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %04X : %02X : %02X", p1, p2, p3); count = count + 4; } break; case OPEQU: /* handle equ opcode */ printf("EQU ($F0) | "); PutSymbol(); if (version == 1) { p1 = fgetc(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %02X : %02X : %02X :", p1, p2, p3); count = count + 3; } else { p1 = fgeti(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %04X : %02X : %02X :", p1, p2, p3); count = count + 4; } DoExpr(); break; case OPDS: /* handle ds opcode */ printf("DS ($F1) | "); PutNumber(); pc = pc + number; break; case OPLONG: /* handle long constant opcode */ printf("LCONST ($F2) | "); PutNumber(); printf(" : "); NewLine(); pc = pc + number; count = count + number; PutConst(number,longc); /* write the constant opcodes */ break; case OPLEXPR: /* handle long expression opcode */ k = fgetc(input); count++; printf("LEXPR ($F3) | %02X :", (int) k); pc = pc + k; DoExpr(); break; case OPENTRY: /* handle entry opcode */ printf("ENTRY ($F4) | "); PutNumber(); printf(" : "); PutSymbol(); break; case OPSRELOC: /* handle short reloc opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("cRELOC ($F5) | %02X : %02X : ", p1, p2); ReadInt(&number,2,input,numsex); printf("%04X : ", (int) number); ReadInt(&number,2,input,numsex); printf("%04X", (int) number); count = count + 6; break; case OPSINTSEG: /* handle short interseg opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("cINTRSEG ($F6) | %02X : %02X : ", p1, p2); ReadInt(&number,2,input,numsex); printf("%04X : %02X : ", (int) number, (int) fgetc(input)); ReadInt(&number,2,input,numsex); printf("%04X", (int) number); count = count + 7; break; case OPSUPER: /* handle short interseg opcode */ printf("SUPER ($F7) | "); ReadInt(&number,4,input,numsex); printf("%08lX : %02X", (long) number, (int) fgetc(input)); NewLine(); count = count + number; PutConst(number-1,1); break; default: Error(7," "); break; } } /*************************************************************** * * PutOpCodeBody - dump the body of one segment in opcode format * ***************************************************************/ void PutOpCodeBody (void) { while (GetOpCode()) { --count; /* adjust the counter */ PutCTPC(); /* write the count and pc */ count++; PutOpCode(); /* write out the opcode */ CheckESC(); } --count; /* write out the end opcode */ PutCTPC(); puts("END ($00)"); /* print end directive */ } /*************************************************************** * * DpOpCode - Dump file in opcode format * ***************************************************************/ void DpOpCode(void) { while (NextSeg()) { count = /* initialize counter and pc */ pc = 0; CheckESC(); if (! PutHeader()) /* write out the header */ return; if (body) { /* write out the body */ if ((! header) && checkf) { count = bod_disp; fseek(input, ftell(input) + bod_disp, SEEK_CUR); } PutOpCodeBody(); } if ((! shorth) || body) puts("\n"); } } /**** Expression Output Subroutines *******************************/ /*************************************************************** * * DoOper - Writes an operation * * Inputs: * space - print a leading space? * ***************************************************************/ void DoOper (BOOLEAN space) { if (space) putchar(' '); switch(opcode) { case 1: /* handle addition */ putchar('+'); break; case 2: /* handle subtraction */ putchar('-'); break; case 3: /* handle multiplication */ putchar('*'); break; case 4: /* handle division */ putchar('/'); break; case 5: /* handle modulo */ putchar('%'); break; case 6: /* handle negation */ if (format != 1) printf("--"); else printf("unary -"); break; case 7: /* handle bit shift */ putchar('|'); break; case 8: /* handle logical and */ printf(".AND."); break; case 9: /* handle logical or */ printf(".OR."); break; case 10: /* handle logical xor */ printf(".EOR."); break; case 11: /* handle logical not */ printf(".NOT."); break; case 12: /* handle less or equal */ printf("<="); break; case 13: /* handle greater or equal */ printf(">="); break; case 14: /* handle not equal */ printf("<>"); break; case 15: /* handle less */ putchar('<'); break; case 16: /* handle greater */ putchar('>'); break; case 17: /* handle equal */ putchar('='); break; case 18: /* handle bit and */ printf(".BAND."); break; case 19: /* handle bit or */ printf(".BOR."); break; case 20: /* handle bit xor */ printf(".BEOR."); break; } } /*************************************************************** * * DoOpnd - Writes an operand * ***************************************************************/ void DoOpnd (void) { switch(opcode) { case 128: /* handle location counter */ printf(" (*)"); break; case 129: /* handle constant */ printf(" $"); PutNumber(); break; case 130: /* handle weak reference */ printf(" W:"); PutSymbol(); break; case 131: /* handle value of label */ putchar(' '); PutSymbol(); break; case 132: /* handle length attribute */ printf(" L:"); PutSymbol(); break; case 133: /* handle type attribute */ printf(" T:"); PutSymbol(); break; case 134: /* handle count attribute */ printf(" C:"); PutSymbol(); break; case 135: /* handle relative ofset */ printf(" ("); PrintW(segname); printf("+$"); PutNumber(); putchar(')'); break; } } /*************************************************************** * * DoExpr - Writes an expression * ***************************************************************/ void DoExpr (void) { while (GetOpCode()) { if (opcode < 128) DoOper(TRUE); else DoOpnd(); } } /**** Disassembler Subroutines ************************************/ /*************************************************************** * * ReadSym - Reads in a symbol and appends it to symbol * ***************************************************************/ void ReadSym (void) { int i,k; k = strlen(symbol); if (lablen) /* handle variable length labels */ act_lablen = lablen; else { act_lablen = fgetc(input); ++count; } for (i=0; i 4) { /* handle avariable I instruction */ if (imode) return 2; return 1; } return len; /* return a fixed length */ } /*************************************************************** * * GtOpName - Returns Pointer to Opcode Name * * Inputs: * opcode - operation code * * Outputs: * pointer to numonic string * * Notes: There is no terminating null on the string. The * caller should use exactly 3 characters. * ***************************************************************/ char *GtOpName (int opcode) { return &opName[opcode*3]; } /*************************************************************** * * IsExpr - Check to see if OPCODE is from an expression * * Inputs: * op - object module opcode * * Outputs: * true if from an expression; else false * Note: if constant != 0 then --constant, return false * if constant == 0 then * if (constant_opcode) set constant, getopcode, return false * else return true * ***************************************************************/ BOOLEAN IsExpr (int op) { if ((! checkf) && (! header)) return FALSE; if (constant) /* handle in a constant */ return FALSE; if (op < OPALIGN) { /* handle short constant */ constant = op; GetOpCode(); return FALSE; } if (op == OPLONG) { /* handle long constant */ ReadInt(&constant,numlen,input,numsex); count = count + numlen; GetOpCode(); return FALSE; } return TRUE; } /*************************************************************** * * PutLSymbol - Writes the symbol * * Inputs: * input - input file * * Outputs: * symbol - symbol read * ***************************************************************/ void PutLSymbol (void) { int i; ReadName(symbol,lablen,input); printf(symbol); for (i=act_lablen; i<8; i++) /* fill out with spaces */ putchar(' '); putchar(' '); if (lablen) /* handle variable length labels */ count = count + lablen; else count = count + act_lablen + 1; } /*************************************************************** * * PutStreg - Writes out the registar status * * Inputs: * mreg - accumulator flag * ireg - index registar flag * ***************************************************************/ void PutStreg (void) { PutCTPC(); printf(" LONGA "); if (mreg) printf("ON"); else printf("OFF"); PutCTPC(); printf(" LONGI "); if (ireg) printf("ON"); else printf("OFF"); } /*************************************************************** * * ReadOpVal - reads an integer from a constant field * * Inputs: * numsex - number sex * input - reference number of file * numlen - length of number * nPtr - pointer to place result * * Outputs: * Returns true if successful, else false. * ***************************************************************/ BOOLEAN ReadOpVal (long *nPtr, int numlen, FILE *f, int numsex) { int i; long k,n; union { char c[4]; long l; } u; if (numlen <= 4) { u.l = 0; for (i = 0; i < numlen; ++i) { if (!constant) { GetOpCode(); if (opcode && (opcode < OPALIGN)) constant = opcode; else return FALSE; } else --constant; u.c[i] = fgetc(f); } *nPtr = u.l; if (numsex) { n = *nPtr; for (i = 0; i < 4; ++i) { k = (k << 8) | (n && 0xFF); n = n >> 8; } *nPtr = k; } } return TRUE; } /*************************************************************** * * PutOpnd - Writes the operand for an instruction * * Outputs: * Returns true if successful, false if an expression * was encountered in the middle of operand. * ***************************************************************/ BOOLEAN PutOpnd (int op) { BOOLEAN success; int i; long addr; i = GtOpLen(op,mreg,ireg); pc = pc + i; if (constant) { /* split on constant or expression */ count = count + i; /* update the file counter */ success = ReadOpVal(&number,i,input,numsex); /* get the value and print it */ printf("$%0*lX", (int) i*2, (long) number); if (op == REP) { /* check for REP */ if (number & 32) mreg = 1; if (number & 16) ireg = 1; PutStreg(); } if (op == SEP) { /* check for SEP */ if (number & 32) mreg = 0; if (number & 16) ireg = 0; PutStreg(); } if (op == COP) { /* special handling for debug COPs */ switch (number) { case 0: case 1: case 2: success = ReadOpVal(&number,2,input,numsex); printf(",%d", (int) number); count += 2; pc += 2; break; case 5: sTable = TRUE; break; } } } else { /* handle case where operand is an exp */ switch(GetOpCode()) { case OPEXPR: case OPZEXPR: case OPBEXPR: case OPLEXPR: fgetc(input); ++count; DoInexp(); /* write expression in infix form */ break; case OPRELEXPR: fgetc(input); ReadInt(&number,numlen,input,numsex); count = count + numlen + 1; DoInexp(); /* write expression in infix form */ break; default: /* case with unexpected input */ printf("???"); break; } } return success; } /*************************************************************** * * Dis_DC - Disassembles a DC format * * Inputs: * op - object module opcode * ***************************************************************/ void Dis_DC (int op) { int i; int p1, p2; /* temps for computed parameters */ switch(op) { case OPGEQU: case OPEQU: /* handle equates */ PutLSymbol(); if (op == OPEQU) printf("EQU "); else printf("GEQU "); fgetc(input); fgetc(input); fgetc(input); count = count+3; if (version == 2) { fgetc(input); ++count; } DoInexp(); break; case OPUSING: /* handle using directives */ printf(" USING "); PutSymbol(); break; case OPLOCAL: case OPGLOBAL: /* handle local and global labels */ PutLSymbol(); if (op == OPLOCAL) printf("ANOP"); else printf("ENTRY"); fgetc(input); fgetc(input); fgetc(input); count = count + 3; if (version == 2) { fgetc(input); ++count; } break; case OPDS: case OPALIGN: /* handle ds and align directive */ if (op == OPALIGN) printf(" ALIGN $"); else printf(" DS $"); PutNumber(); if (op == OPALIGN) pc = pc + (pc % number); else pc = pc + number; break; case OPSTRONG: /* handle strong reference */ printf(" DC R'"); PutSymbol(); putchar('\''); break; case OPORG: /* handle inter-segment org */ printf(" ORG *+$"); PutNumber(); pc = pc + number; break; case OPMEM: /* handle inter-segment mem */ printf(" MEM $"); PutNumber(); printf(",$"); PutNumber(); break; case OPEXPR: case OPZEXPR: /* handle expressions */ case OPBEXPR: case OPLEXPR: case OPRELEXPR: printf(" DC "); i = fgetc(input); if (i == 1) printf("I1'"); else if (i == 2) printf("I2'"); else if (i == 3) printf("I3'"); else printf("I4'"); ++count; pc = pc + i; if (op == OPRELEXPR) { PutNumber(); putchar('+'); } DoInexp(); /* write expression in infix form */ putchar('\''); break; case OPRELOC: /* handle reloc opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("! RELOC ($E2) | %02X : %02X : ", p1, p2); PutNumber(); printf(" : "); PutNumber(); count = count + 2; break; case OPINTSEG: /* handle interseg opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("! INTERSEG ($E3) | %02X : %02X : ", p1, p2); PutNumber(); printf(" : "); ReadInt(&number,2,input,numsex); printf("%04X : ", (int) number); ReadInt(&number,2,input,numsex); printf("%04X : ", (int) number); PutNumber(); count = count + 6; break; case OPENTRY: /* handle entry opcode */ printf("! ENTRY ($F4) | "); PutNumber(); printf(" : "); PutSymbol(); break; default: Error(7," "); break; } } /*************************************************************** * * Disasm - Disassembles OPCODE * * Inputs: * op - assembly language opcode * * Outputs: * Returns true if successful, false if an expression * was hit trying to process an operand. * ***************************************************************/ BOOLEAN Disasm (int op) { BOOLEAN success; int i; char opn[4]; sTable = FALSE; /* no COP symbol table found (yet) */ success = TRUE; /* assume everything will work */ --constant; /* now this is a constant */ ++pc; /* update program counter */ strncpy(opn, GtOpName(op), 3); opn[3] = (char) 0; printf(" %s ", opn); switch(GtOpKind(op)) { /* split on type of output format */ case 1: /* handle '# operand' */ putchar('#'); success = PutOpnd(op); break; case 2: /* handle 'operand' */ success = PutOpnd(op); break; case 3: /* handle '> operand' */ putchar('>'); success = PutOpnd(op); break; case 4: /* handle 'A' */ putchar('A'); break; case 5: /* handle ' ' or 'operand' */ if (GtOpLen(op,mreg,ireg)) success = PutOpnd(op); break; case 6: /* handle '(operand),Y' */ putchar('('); success = PutOpnd(op); printf("),Y"); break; case 7: /* handle '[operand],Y' */ putchar('['); success = PutOpnd(op); printf("],Y"); break; case 8: /* handle '(operand,X)' */ putchar('('); success = PutOpnd(op); printf(",X)"); break; case 9: /* handle 'operand,X' */ success = PutOpnd(op); printf(",X"); break; case 10: /* handle 'operand,Y' */ success = PutOpnd(op); printf(",Y"); break; case 11: /* handle '>operand,X' */ putchar('>'); success = PutOpnd(op); printf(",X"); break; case 12: /* handle '(operand)' */ putchar('('); success = PutOpnd(op); putchar(')'); break; case 13: /* handle '[operand]' */ putchar('['); success = PutOpnd(op); putchar(']'); break; case 14: /* handle 'operand,S' */ success = PutOpnd(op); printf(",S"); break; case 15: /* handle '(operand,S),Y */ putchar('('); success = PutOpnd(op); printf(",S),Y"); break; case 16: /* handle 'operand,operand' */ success = PutOpnd(op); putchar(','); success = PutOpnd(op); break; case 17: /* handle relative branches */ if (constant) { i = GtOpLen(op,mreg,ireg); pc = pc + i; count = count + i; /* update the file counter */ constant = constant - i; /* set new constant number */ number = 0; ReadInt(&number,i,input,numsex); /* get the value and print it */ if (i == 1) { if (number > 127) number = number | -256; } else { if (number > 32767) number = number | -32768; } number = number + i + 1; if (number < 0) { number = -number; printf("*-$"); } else printf("*+$"); printf("%0*lX", (int) i*2, (long) number); } else success = PutOpnd(op); break; default: printf("Operand Error"); status = -1; break; } return success; } /*************************************************************** * * DisSTable - disassemble a COP 5 symbol table * ***************************************************************/ void DisSTable (void) { long tlen; int p1, p2, p3, p4; /* temps for computed parms */ if (!constant) { GetOpCode(); if (opcode && (opcode < OPALIGN)) constant = opcode; else { PutCTPC(); Dis_DC(opcode); } } if (constant >= 2) { ReadInt(&tlen,2,input,numsex); /* get and print the table length */ PutCTPC(); printf(" DC I'%d'", (int) tlen); pc += 2; count += 2; constant -= 2; CheckESC(); while (tlen > 0) { if (!constant) { GetOpCode(); if (opcode && (opcode < OPALIGN)) constant = opcode; } if (constant) { ReadOpVal(&number,4,input,numsex); PutCTPC(); printf(" DC I4'%d'", (long) number); pc += 4; count += 4; } else { PutCTPC(); Dis_DC(opcode); } if (!constant) { GetOpCode(); if (opcode && (opcode < OPALIGN)) constant = opcode; } if (constant) { ReadOpVal(&number,4,input,numsex); PutCTPC(); printf(" DC I4'%d'", (long) number); pc += 4; count += 4; } else { PutCTPC(); Dis_DC(opcode); } if (!constant) { GetOpCode(); if (opcode && (opcode < OPALIGN)) constant = opcode; else { PutCTPC(); Dis_DC(opcode); } } if (constant >= 4) { PutCTPC(); p1 = fgetc(input); p2 = fgetc(input); p3 = fgetc(input); p4 = fgetc(input); printf(" DC H'%02X %02X %02X%02X'", p1, p2, p3, p4); pc += 4; count += 4; constant -= 4; } tlen -= 12; } } } /*************************************************************** * * Dis_Cns - disassemble a constant as a DC statement(s) * ***************************************************************/ void Dis_Cns (int opcode) { int i, delta; int b1,b2; while (opcode != 0) { printf(" DC H'"); i = 16; while ((i != 0) && (opcode != 0)) { if (opcode == 1) { printf("%02X", (int) fgetc(input)); delta = 1; } else { b1 = fgetc(input); b2 = fgetc(input); if (opcode == 2) printf("%02X%02X", (int) b1, (int) b2); else printf("%02X%02X ", (int) b1, (int) b2); delta = 2; } opcode -= delta; i -= delta; pc += delta; count += delta; } putchar('\''); if (opcode != 0) { CheckESC(); PutCTPC(); } } } /*************************************************************** * * DpDisasm - Dump file in disassembled format * ***************************************************************/ void DpDisasm (void) { int i; long mark; long codelen; while (NextSeg()) { count = /* initialize counter and pc */ pc = constant = 0; /* we're not in a constant */ CheckESC(); if (checkf || header) /* write out the header */ if (! PutHeader()) return; if ((! checkf) && (! header)) { /* get segment length */ mark = GetEOF(input); blocks = 30000; } else if ((ftype == LIBFL) || (version == 2)) mark = blkcnt; else mark = blkcnt*512; if (body) { /* write out the body */ if ((! header) && checkf) { count = bod_disp; fseek(input, ftell(input) + bod_disp, SEEK_SET); } PutStreg(); /* write the registar status */ PutCTPC(); printf(segname); /* print the segment name */ for (i=strlen(segname); i<8; i++) /* fill out with spaces */ putchar(' '); if (kind & 1) /* print out segment type */ printf(" DATA"); else printf(" START"); codelen = length-resspc; while (count <= mark) { PutCTPC(); GetOpCode(); if (checkf && ((pc > codelen) || ((! opcode) && (pc == codelen)))) break; if (((kind & 0x001F) == 1) && checkf && (opcode < OPALIGN) && (opcode != 0)) Dis_Cns(opcode); else if (IsExpr(opcode)) Dis_DC(opcode); else if (!Disasm(opcode)) { PutCTPC(); Dis_DC(opcode); } else if (sTable) DisSTable(); CheckESC(); } if (resspc) { printf(" DS $%08lX", (long) resspc); count += resspc; } if (count > mark) PutCTPC(); puts(" END"); /* print out the end directive */ } if ((! shorth) || body) puts("\n"); } } /**** Hex Dump Subroutines ****************************************/ /*************************************************************** * * DpHex - Dump file in hex format * ***************************************************************/ void DpHex (void) { long mark; long ch = 0; char chline[20]; int k, i, space; while (NextSeg()) { count = 0L; CheckESC(); if (! PutHeader()) /* write out the header */ return; /* if we don't print header and we're not doing file checking then dump the entire file and forget about segment scanning */ if ((! checkf) && (! header)) { /* get the segment length */ mark = GetEOF(input); blocks = 30000; } else if ((ftype == LIBFL) || (version == 2)) mark = blkcnt; else mark = blkcnt*512; if (body) { /* write out the body */ if ((! header) && checkf) { count = bod_disp; fseek(input, ftell(input) + bod_disp, SEEK_SET); } while (count <= mark) { putchar('\n'); if (colf) printf("%06lX | ", count); space = 0; for (k=0; k<16; k++) { ch = fgetc(input); count++; if (count > mark) { printf(" "); ch = 0; } else printf("%02X", ch); if ((ch & 127) > 31) chline[k] = ch & 127; else chline[k] = ' '; space++; if (space == 4) { putchar(' '); space = 0; } CheckESC(); } chline[16] = 0; printf(" | %s", chline); CheckESC(); } } if ((! shorth) || body) printf("\n\n"); } } /**** Command Line Input Subroutines ******************************/ /*************************************************************** * * GetFType - Return Type Of File * * Inputs: * name - file name to get the type of * * Returns: file type; 0 if not found * ***************************************************************/ int GetFType (char name[]) { struct FileInfoRecGS { int pCount; struct { int length; char name[FILEMAX]; } *fname; int access; int fileType; } parm; parm.pCount = 3; parm.fname = (void *) malloc (sizeof(int) + FILEMAX); if (parm.fname == NULL) return 0; parm.fname->length = strlen(name); strcpy(parm.fname->name, name); GetFileInfoGS(&parm); free(parm.fname); if (toolerror()) return 0; return parm.fileType; } /*************************************************************** * * CheckFile - Checks For Valid File * ***************************************************************/ BOOLEAN CheckFile (char file[]) { if (! checkf) { /* see if we have to check file type */ ftype = FALSE; /* unspecified file type */ return TRUE; } /* insure file exists and is an OMF type of file */ if (! (ftype = GetFType(file))) { Error(5,file); return FALSE; } if ((ftype < OBJFL) || (ftype > MAXFL)) { Error(6,file); return FALSE; } return TRUE; } /*************************************************************** * * ExpandDev - Expand devices and prefixes * ***************************************************************/ #define INIT_WILDCARD(parm) (PDosInt(0x0149,parm)) #define NEXT_WILDCARD(parm) (PDosInt(0x014A,parm)) void ExpandDev (char name[]) { struct { /* parameter block for Init_Wildcard */ int pcount; struct { int length; char name[FILEMAX]; } *inName; int flags; } iwRec; struct { /* parameter block for Next_Wildcard */ int pcount; struct { int buffLen; int length; char name[FILEMAX]; } *outName; } nwRec; iwRec.inName = (void *) malloc (sizeof(int) + FILEMAX); nwRec.outName = (void *) malloc (sizeof(int)*2 + FILEMAX); if ((iwRec.inName == NULL) || (nwRec.outName == NULL)) { if (iwRec.inName != NULL) free(iwRec.inName); if (nwRec.outName != NULL) free(nwRec.outName); return; } iwRec.pcount = 2; iwRec.inName->length = strlen(name); strcpy(iwRec.inName->name, name); iwRec.flags = 0x4000; nwRec.pcount = 1; nwRec.outName->buffLen = FILEMAX+4; INIT_WILDCARD(&iwRec); if (!toolerror()) { NEXT_WILDCARD(&nwRec); if (!toolerror()) { memcpy(name, nwRec.outName->name, nwRec.outName->length); name[nwRec.outName->length] = (char) 0; } } free(iwRec.inName); free(nwRec.outName); } /*************************************************************** * * SetFlag - Sets the input parameters flags * ***************************************************************/ BOOLEAN SetFlag (char *str) { char ch; if (strlen(str) != 2) { Error(4,str); return FALSE; } ch = toupper(str[1]); if ((str[0]) == '+') { /* handle + flags */ if (ch == 'X') {format = 2;} else if (ch == 'D') {format = 1;} else if (ch == 'S') {shorth = FALSE;} else if (ch == 'I') {ireg = TRUE;} else if (ch == 'L') {longc = TRUE;} else if (ch == 'M') {mreg = TRUE;} else if (ch == 'H') {header = TRUE;} else if (ch == 'O') {body = TRUE;} else if (ch == 'F') {checkf = TRUE;} else if (ch == 'A') {colf = TRUE;} else {Error(4, str); return FALSE;} } else { /* handle - flags */ if (ch == 'X') {format = 0;} else if (ch == 'D') {format = 0;} else if (ch == 'S') {shorth = TRUE;} else if (ch == 'I') {ireg = FALSE;} else if (ch == 'L') {longc = FALSE;} else if (ch == 'M') {mreg = FALSE;} else if (ch == 'H') {header = FALSE;} else if (ch == 'O') {body = FALSE;} else if (ch == 'F') {checkf = FALSE;} else if (ch == 'A') {colf = FALSE;} else {Error(4, str); return FALSE;} } return TRUE; } /*************************************************************** * * Reads the names list and sets up namelist pointers * ***************************************************************/ BOOLEAN GetList (int num, int argc, char *argv[]) { char local[NAMEMAX]; int i, k; if (num == argc) { names = FALSE; return TRUE; } for (i=num; i<=argc; i++) { strncat(nlist, argv[i], strlen(argv[i])); strncat(nlist, " ", 1); } strcpy(local, nlist); if (strlen(nlist) < 8) { Error(4,local); names = FALSE; return FALSE; } for (i=0; i<5; i++) nlist[i] = toupper(nlist[i]); if (strncmp(nlist,"NAMES=(",7) != 0) { Error(4,local); names = FALSE; return FALSE; } for (i=0; i<7; i++) nlist[i] = ' '; i = 0; while (nlist[i] && (nlist[i] != ')')) { if (nlist[i] == ',') nlist[i] = ' '; i++; } if (! nlist[i]) { Error(4,local); names = FALSE; return FALSE; } nlist[i] = 0; names = TRUE; return TRUE; } /*************************************************************** * * GetName - This is the name input routine * ***************************************************************/ void GetName (char *name) { int i, x; char ch; fputs("File name: ", stdout); /* prompt for file name */ name[0] = (char) 0; /* read the file name */ fgets(name, NAMEMAX, stdin); x = strlen(name); /* strip whitespace */ while ((x != 0) && isspace(name[x-1])) name[--x] = (char) 0; while (((x = strlen(name)) != 0) && isspace(name[0])) for (i = 0; i < x; ++i) name[i] = name[i+1]; } /*************************************************************** * * GetParms - Gets the input parameters * ***************************************************************/ BOOLEAN GetParms (int argc, char *argv[]) { char local[NAMEMAX]; int i; i = 1; while (i <= argc) { /* first set the flags */ strcpy(local,argv[i]); ++i; if ((local[0] == '+') || (local[0] == '-')) { if (! SetFlag(local)) return FALSE; } else break; } if (i <= argc) /* get file name */ strcpy(fname,argv[i-1]); else { GetName(fname); /* ask for and get file name */ i = argc; /* no names list */ } ExpandDev(fname); /* expand devices */ if (! CheckFile(fname)) return FALSE; if ((input = fopen(fname,"rb")) == NULL) { Error(5,fname); return FALSE; } return GetList(i, argc, argv); } /**************************************************************** * * Initialize - Initialize variables * ****************************************************************/ void Initialize (void) { puts("DumpOBJ 2.0.1\n"); /* write the header */ format = /* dump in opcode format */ namc = /* no names in namelist */ ftype = /* no specified file type yet */ status = 0; /* assume no errors */ segmark = /* start with begining segment */ blocks = 0L; /* no block yet */ shorth = FALSE; /* don't do "scan" type output */ ireg = /* use long index registars */ mreg = /* use long accumulator */ header = /* print the header */ longc = /* print long constants */ body = /* print the body */ checkf = /* check input file type */ colf = TRUE; /* write out the numbers */ } /**** Main Programs ***********************************************/ /**************************************************************** * * Main - Begin Program * ****************************************************************/ int main (int argc, char * argv[]) { Initialize(); /* initialize variables */ if (GetParms(argc, argv)) { /* get input parameters */ switch (format) { case 0: DpOpCode(); break; /* dump file in opcode format */ case 1: DpDisasm(); break; /* dump file in disassembled format */ case 2: DpHex(); break; /* dump file in hex format */ default: Error(1," "); /* flag error if not one of these */ } } putchar('\n'); return status; } \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6fa58b0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,11 @@ +DumpObj is released by the copyright holder under the terms of the original copyright. + +The Byte Works, Inc. grants you the right to use this source code privately, fork it, and change it. + +You may not redistribute the code in any form other than submission to this repository without the written permission of the copyright holder. + +The copyright holder decided to do things this way for two reasons: + +1. Reserve commercial distribution rights. + +2. Ensure that any contributions and updates are available from a centralized source (this GitHib repository, for now). diff --git a/README.md b/README.md new file mode 100644 index 0000000..e0973c3 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# DumpObj +A utility designed for use with the ORCA development environment for the Apple IIGS, DumpObj prints a more-or-less human readable version of Apple IIGS object files. + +__Binary downloads for the latest DumpObj release are on the [releases page][releases].__ + +[releases]: https://github.com/byteworksinc/DumpObj/releases + +If you would like to make changes to this utility and distribute them to others, feel free to submit them here. If the changes apply to compilation on and for an Apple IIGS, they will generally be approved for distribution on the master branch. + +The general conditions that must be met before a change is released on master are: + +1. The modified utility must compile under the currently released version of ORCA/C. + +Contact support@byteworks.us if you need contributor access. + +A complete distribution of the ORCA languages, including installers and documentation, is available from the Juiced GS store at https://juiced.gs/store/category/software/. It is distributed as part of the Opus ][ package. + +## Line Endings and File Types + +The text and source files in this repository originally used CR line endings, as usual for Apple II text files, but they have been converted to use LF line endings because that is the format expected by Git. If you wish to move them to a real or emulated Apple II and build them there, you will need to convert them back to CR line endings. + +If you wish, you can configure Git to perform line ending conversions as files are checked in and out of the Git repository. With this configuration, the files in your local working copy will contain CR line endings suitable for use on an Apple II. To set this up, perform the following steps in your local copy of the Git repository (these should be done when your working copy has no uncommitted changes): + +1. Add the following lines at the end of the `.git/config` file: +``` +[filter "crtext"] + clean = LC_CTYPE=C tr \\\\r \\\\n + smudge = LC_CTYPE=C tr \\\\n \\\\r +``` + +2. Add the following line to the `.git/info/attributes` file, creating it if necessary: +``` +* filter=crtext +``` + +3. Run the following commands to convert the existing files in your working copy: +``` +rm .git/index +git checkout HEAD -- . +``` + +Alternatively, you can keep the LF line endings in your working copy of the Git repository, but convert them when you copy the files to an Apple II. There are various tools to do this. One option is `udl`, which is [available][udl] both as a IIGS shell utility and as C code that can be built and used on modern systems. + +[udl]: http://ftp.gno.org/pub/apple2/gs.specific/gno/file.convert/udl.114.shk + +In addition to converting the line endings, you will also have to set the files to the appropriate file types before building ORCA/C on a IIGS. The included `settypes` script (for use under the ORCA shell) does this for the sources to the ORCA/C compiler itself, although it does not currently cover the test cases and headers. diff --git a/doit b/doit new file mode 100755 index 0000000..04126e5 --- /dev/null +++ b/doit @@ -0,0 +1 @@ +make copy -c dumpobj 17 \ No newline at end of file diff --git a/dumpobj.rez b/dumpobj.rez new file mode 100755 index 0000000..d9194e5 --- /dev/null +++ b/dumpobj.rez @@ -0,0 +1 @@ +/*--------------------------------------------------------------*/ /* */ /* Resources for DumpOBJ */ /* */ /*--------------------------------------------------------------*/ #include "types.rez" /*- Finder Interface -------------------------------------------*/ resource rVersion(1) { { 2, /* Major revision */ 0, /* Minor revision */ 1, /* Bug version */ release, /* Release stage */ 0, /* Non-final release # */ }, verUS, /* Region code */ "DumpOBJ", /* Short version number */ "Copyright 1994, Byte Works, Inc." /* Long version number */ }; \ No newline at end of file diff --git a/make b/make new file mode 100755 index 0000000..bcfd20e --- /dev/null +++ b/make @@ -0,0 +1 @@ +* * DumpOBJ * unset exit Newer DumpOBJ DumpOBJ.rez if {Status} != 0 set exit on echo compile DumpOBJ.rez keep=DumpOBJ compile DumpOBJ.rez keep=DumpOBJ unset exit end MoreRecent DumpOBJ.a DumpOBJ.cc if {Status} != 0 set exit on echo compile +t +e DumpOBJ.cc compile +t +e DumpOBJ.cc unset exit end set auxtype $DB01 echo set auxtype $DB01 echo link DumpOBJ keep=DumpOBJ link DumpOBJ keep=DumpOBJ rename dumpobj DumpOBJ \ No newline at end of file