/*  HUNKER V1.0 written by Axel Peters © 03.01.89	
 							
	Aztec C V3.40					
	cc Hunker.c -s +l [-DSYMBOLS]				
	ln Hunker.o -lc32				

   Wenn die Variable SYMBOLS definiert wurde ( auch mit -DSYMBOLS ),
   so werden bei HUNK_SYMBOL, HUNK_EXT die Label-Namen ausgegeben !  

*/

#include <exec/types.h>
#include <libraries/dos.h>

#define HUNK_HEADER 0x03F3L
#define HUNK_END    0x03F2L
#define MEMF_PUBLIC 0x00000000	
#define MEMF_CHIP   0x40000000
#define MEMF_FAST   0x80000000
#define PCR printf("\n")			/* Print Carriage Return */
#define MASK1 0x3fffffff		
#define MASK2 0x00ffffff

struct FileHandle *Handle;
extern Enable_Abort;


_abort()				/* Hat Meldung beim Linken zur Folge, 	 */
{					/* da org. _abort() überschrieben wird ! */
	Enable_Abort=0;	/* Break sperren */
	Leave(5);
}

UBYTE types[][14] = 	{	
			"HUNK_UNIT   ",	/* $03E7 */
			"HUNK_NAME   ",	/* $03E8 */	
			"HUNK_CODE   ",	/* $03E9 */
			"HUNK_DATA   ",	/* $03EA */
			"HUNK_BSS    ",	/* $03EB */
			"HUNK_RELOC32",	/* $03EC */
			"HUNK_RELOC16",	/* $03ED */
			"HUNK_RELOC8 ",	/* $03EE */
			"HUNK_EXT    ",	/* $03EF */
			"HUNK_SYMBOL ",	/* $03F0 */
			"HUNK_DEBUG  ",	/* $03F1 */
			"HUNK_END    ",	/* $03F2 */
			"HUNK_HEADER "		/* $03F3 */
	    	    	};

UBYTE errors[][28] =	{	
			"Can't find File !         ",	/* Fehlermeldungen */
			"Can't find Header !       ",
			"Unable to work with Hunk !",
			"Just give me a Filename ! ",
			"YOU BREAKED !             ",
			"Can't write !             "
			};

UBYTE mem[][12]    =	{
			"MEMF_PUBLIC",				/* Speichertypen */
			"MEMF_CHIP  ",
			"MEMF_FAST  ",
			"RESERVED   "
			};

		
main(argc,argv)
LONG argc;
UBYTE *argv[];
{
UBYTE hname[32],answ[10];
ULONG daten,numhunk,pos,typ,i; 

	Enable_Abort = 1; 						/* Break freigeben */
	if((argc<=1)||(*argv[1]=='?'))Leave(4);		/* Eingabe prüfen  */
	if(argc>2)printf("Just using first argument\n");

	printf("\nWorking on File: %s\n",argv[1]);	/*  File öffnen  */
	if(!(Handle=Open(argv[1],MODE_OLDFILE)))Leave(1);

	if((daten=GetLong())!=HUNK_HEADER)Leave(2);	/*   ein Prg ?	  */
	while(daten=GetLong())					/*  Namen holen  */
		{
		Read(Handle,hname,daten*4);printf("HunkName: %s\n",hname);
	}

	printf("Number of Hunks: %ld\n\n",numhunk=GetLong());
	pos=Seek(Handle,8,OFFSET_CURRENT);			/* First/Last Hunk */
	Seek(Handle,numhunk*4,OFFSET_CURRENT);		/* überspringen    */

	for(i=0;i<numhunk;i++)					/* Hunks ausgeben  */
		{
		printf("Hunk: %ld\n",i);
		GetHunks();			
		}

	printf("\nModify Mem-Types (y/n) ? ");
	if((!scanf("%s",answ))||(answ[0]!='y'))Leave(0); PCR;
 
	Seek(Handle,pos+8,OFFSET_BEGINNING);

	for(i=0;i<numhunk;i++)					/* Größe/Type holen*/
		{
		daten=GetLong();
		printf("Hunk: %-2ld %7ld Bytes  ",i,daten<<2);
		printf("%s  ",mem[daten>>30]);		/* Typ ausgeben    */
		printf("Modify to (P/C/F) : "); 
		scanf("%s",answ);

		daten&=MASK1;	
		switch(answ[0])			/* Bits für Speichtyp setzen */
			{
			case 'p':
			case 'P': daten|=MEMF_PUBLIC; break;
			case 'c':
			case 'C': daten|=MEMF_CHIP; break;
			case 'f': 
			case 'F': daten|=MEMF_FAST;break;
			case 'q':
			case 'Q': Leave(5);		/*    Abbruch    */
			default : continue;		/* Nächsten Hunk */
			}
		Seek(Handle,-4,OFFSET_CURRENT);	/* Pointer in File -4 Bytes */ 	
		if(Write(Handle,&daten,4)==-1)Leave(6);
		}
	Leave(0);
}

GetLong()					/* Long aus File holen */
{
ULONG daten;

	Read(Handle,&daten,4); 
	return(daten);
}	

OutType(code)				/* Hunk-Typ ausgeben */
ULONG code;
{
	printf("	%s  ",types[code-0x3e7]);
}

Leave(num)			/* Prg verlassen mit Meldung */
UBYTE num;
{	
	if(num)printf("\nOH NO: %s\n",errors[--num]);	
	if(Handle)Close(Handle); 	
	exit(0);
}

GetHunks()			/* Hunk-Blocks ausgeben		*/
{
ULONG daten,num;
UBYTE Name[33];

	while((daten=GetLong())!=HUNK_END)
		{
		if(daten>=0x3e7&&daten<=0x3f3)OutType(daten);
		switch(daten&MASK1)
			{
			case 0x3e8:				
				   num=GetLong();
				   Read(Handle,Name,num*4);		
				   printf(" Name: %s \n",Name);
				   break;		
			case 0x3e9:
			case 0x3ea:
				   PCR;	
				   num=GetLong();
				   Seek(Handle,num*4,OFFSET_CURRENT);
				   break;	
			case 0x3eb:
				   printf("Used Bytes: %ld\n",num=GetLong()*4);
				   break;	 			
			case 0x3ec:
			case 0x3ed:
			case 0x3ee:
				   printf("   on Hunk: ");		
				   while(num=GetLong())
					{
					printf("%ld  ",GetLong());
					Seek(Handle,num*4,OFFSET_CURRENT);
					}	
				   PCR;	
				   break;	
			case 0x3ef:
			case 0x3f0:
				   while(num=GetLong())
					{
					num&=MASK2;
#ifdef SYMBOLS
					Read(Handle,Name,num*4); num=GetLong();
					printf("\n      %-32s Offs. : %lx",Name,num);
#else
					Seek(Handle,(++num)*4,OFFSET_CURRENT);
#endif
					}
				   PCR;
				   break;
			case 0x3f1:
				   num=GetLong();
				   Seek(Handle,num*4,OFFSET_CURRENT);
				   PCR;
				   break;	
			default:
				   printf("        ERROR : UNKNOWN BLOCK !\n");
				   while(GetLong()!=HUNK_END);
				   return();
			}
		}
	OutType(daten); PCR;
}
