⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exe2rom.c

📁 Embedded magazine source code. this is the source code in the year 1989
💻 C
字号:
/*  EXE2ROM  - used for processing .EXE files into .ROM files  */
#include <stdio.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#define MAX_RELOCS 4096
struct EXEHEADER {
	int h_magic;
	int h_lenimage_mod512;
	int h_filesize_512;
	int h_relocnum;
	int h_hsize_paras;
	int h_minbss;
	int h_maxbss;
	int h_stack_paras;
	int h_sp;
	int h_word_checksum;
	int h_ip;
	int h_codeseg_paras;
	int h_reloc_table_offset;
	};
static unsigned int remaining_reloc_entries,chksum,exe_data_segment,
	rom_data_segment,rom_code_segment,startup_parms[8],
	words_in_block,bytes_in_inbuffer,bytes_in_outbuffer,
	consecutive_zeroes,block_buffer[300],*block_pointer,
	initialIP,dseg_relocs,cseg_relocs,offset_within_data,
	*reloc_table_pointer,reloc_table[MAX_RELOCS*2];
static int rom_file,exe_file,reloc_file;
static unsigned long int next_reloc_offset,romaddr,
	header_length,exe_image_length,exe_data_offset,ldummy,
	exe_image_offset,C_ETEXT_offset;

static char inbuffer[4096],*inbuffer_pointer,outbuffer[4096],
	*outbuffer_pointer,sdummy[81],romfilename[50],*startup_ptr;
static struct EXEHEADER hb;
static FILE *spec_filep,*map_filep;
  extern long int lseek();  int segoff_compare();

main(argc,argv)
  int argc;
  char *argv[];
{
	register int i;  register char *p;
	char filename[50],map_data_needed;  unsigned int k,sup_count;
	rom_file = -1;
	printf("\r\n.EXE to .ROM converter, v5.17.89");
	printf("\r\n (c)1989 Real-Time Specialties, inc. (313)434-2412\r\n");
	if (argc<2)
	{
		printf("usage:  exe2rom spec_file_name\r\n\r\n");
		printf("spec file format:\r\n\r\n");
		printf(
"   codeSEG dataSEG exe_file_name initialSP (all on one line)\r\n\r\n");
		printf(
"codeSEG (in hex) = starting segment of ROM in target system.\r\n");
		printf(
"dataSEG (in hex) = starting segment of data in target system.\r\n");
		printf(
"exe_file_name is with or without extension.r\n");
		printf(
"initialSP (in hex) = value communicated to startup code.\r\n");
		exit();
	}
	if( (spec_filep = fopen(argv[1],"r")) == NULL )
		abort_with( "Error opening spec file" );
	if( fscanf(spec_filep,"%x%x%s",
		&rom_code_segment,&rom_data_segment,filename) != 3 )
			abort_with( "Format error in spec file" );
	sup_count=0;
	while(sup_count<=8)
		if(fscanf(spec_filep,"%x",&startup_parms[sup_count]) == 1)
			sup_count++;
		else break;
	romaddr = ((long)rom_code_segment) << 4L;
	printf("\r\nROM starts at %05lxH.",romaddr);
	if(sup_count)
	{
		printf("\r\n  Startup module parameters: ");
		for(i=0; i<sup_count; i++)
			printf(" %04xH",startup_parms[i]);
		printf("\r\n");
	}
	p = filename;
	while( *p )
	{
		if( *p == '.' )  *p = '\0';
		else  p++;
	}				/* find a "." or the end of the file name */
	strcpy( p,".ROM" );
	strcpy( romfilename, filename );
	if((rom_file = open(filename, O_BINARY | O_CREAT | O_WRONLY
		| O_TRUNC, S_IREAD | S_IWRITE)) == -1 )
			abort_with( "Error opening (or creating) .ROM file" );
	strcpy( p,".EXE" );
	if((exe_file = open(filename, O_RDONLY | O_BINARY)) == -1)
		abort_with( "Error opening .EXE file" );
	if((reloc_file = open(filename, O_RDONLY | O_BINARY)) == -1)
		abort_with( "Error opening .EXE file" );
	strcpy( p,".MAP" );
	if((map_filep = fopen(filename,"r")) == NULL)
		abort_with( "Error opening .MAP file" );

/*---------------  Get data from .MAP file:  C_ETEXT */
	map_data_needed = 1;
	while((fgets(inbuffer,81,map_filep) == inbuffer) && map_data_needed)
		if( map_data_needed )
			if(sscanf(inbuffer,"%lxH%lxH%lxH C_ETEXT %s",
				&C_ETEXT_offset, &ldummy, &ldummy, sdummy) == 4)
					map_data_needed = 0;
	if(map_data_needed)
		abort_with( "C_ETEXT not found in .MAP file" );
	exe_data_offset = C_ETEXT_offset + 16L;
	exe_data_segment = exe_data_offset / 16L;
	fclose(map_filep);

/*--------------- Get data from header of .EXE file    */
	if( read(reloc_file,(char*)&hb,sizeof(hb)) != sizeof(hb) )
		abort_with( "Error reading .EXE file header" );
	if( hb.h_magic != 0x5a4d )
		abort_with(".EXE file doesn't start with 4D 5A.");
	header_length = hb.h_hsize_paras * 16L;

	exe_image_length = hb.h_filesize_512 * 512L +
		hb.h_lenimage_mod512 - header_length;
	if( hb.h_lenimage_mod512 )
		exe_image_length -= 512L;
	printf("     EXE image length = %05lxH",exe_image_length);
	remaining_reloc_entries = hb.h_relocnum;
	if(remaining_reloc_entries > MAX_RELOCS)
		abort_with("Too many relocation entries");
	initialIP = hb.h_ip;
	if( lseek(reloc_file,(long)hb.h_reloc_table_offset,SEEK_SET)
		== -1L )
			abort_with( "Error seeking reloc table in .EXE file" );
	printf("    Relocation items: %d",remaining_reloc_entries);
	if( remaining_reloc_entries )
	{
		if( read(reloc_file,(char*)reloc_table,
			remaining_reloc_entries*4) != remaining_reloc_entries*4)
				abort_with( "Error reading RELOC table" );
		reloc_table_pointer = reloc_table;
		qsort((void*)reloc_table, (size_t)remaining_reloc_entries,
			(size_t) 4, segoff_compare );
	}
	set_next_reloc_offset();
	if( lseek(exe_file,header_length,SEEK_SET) == -1L )
			abort_with( "Error seeking load image in .EXE file" );

	block_pointer = &block_buffer[1];
	bytes_in_inbuffer = chksum = words_in_block = 0;
	offset_within_data = bytes_in_outbuffer = 0;
	dseg_relocs = cseg_relocs = 0;
	outbuffer_pointer = outbuffer;
	startup_ptr = (unsigned char *)startup_parms;
	exe_image_offset = 0L;
	printf(
"\r\nEXE data SEG = %04xH      ROM data SEG = %04xH",
	exe_data_segment,rom_data_segment);
	printf("\r\nInitialized data table block lengths:     ");
/*------------------  Main data transfer loop ---------------*/
while( exe_image_offset < exe_image_length )
{
	if( exe_image_offset == next_reloc_offset )
	{				 /* Next word is subject to relocation   */
		k = get_a_byte();
		if( exe_image_offset < exe_image_length)
			k += get_a_byte() << 8;           /*  k = next word  */
		if( k >= exe_data_segment)   /* refers to RAM segment */
		{
			k += rom_data_segment - exe_data_segment;
			dseg_relocs ++;
		}
		else						 /* refers to ROM segment */
		{
			k += rom_code_segment;
			cseg_relocs ++;
		}
		put_a_byte( k & 0xff );
		put_a_byte( k >> 8 );
		set_next_reloc_offset();
	}
	else				/* not a reloc item */
		put_a_byte( get_a_byte() );
}
/*---------------- end of main data transfer loop -----------*/
	flush_block();
	output_a_word(0);  /* End tag for initialized data table */
	if( romaddr > 0xffff0 )
		abort_with( "ROM overflow.  Too much data" );
	printf("\r\n %d DSEG relocs.    %d CSEG relocs."
		,dseg_relocs,cseg_relocs);
	printf("\r\n Padding with %ld bytes of FF.  ",0xffff0-romaddr);
	while(romaddr != 0xffff0)
		output_a_byte( 0xff );
	output_a_byte( 0xea );    /* Inter-Segment Direct JMP  */
	output_a_word( initialIP );
	output_a_word( rom_code_segment );
	for(i=5; i<14; i++)
		output_a_byte( 0 );
	output_a_word( -chksum );
	flush_outbuffer();
	close( rom_file );
	if( next_reloc_offset != 0xfffffffe )
		abort_with( "Relocation table not all used up" );
}

get_a_byte()
{
	if( !bytes_in_inbuffer )
	{
		bytes_in_inbuffer = read(exe_file,inbuffer,sizeof(inbuffer));
		if( bytes_in_inbuffer <= 0 )
			abort_with( "Error or EOF on .EXE file" );
		inbuffer_pointer = inbuffer;
	}
	bytes_in_inbuffer --;
	exe_image_offset ++;
	return ((unsigned char) (*inbuffer_pointer++) );
}

put_a_byte(b)
  unsigned char b;
{
	unsigned register int k;    static unsigned int first_byte;
	if( exe_image_offset > exe_data_offset )
	{						/*  in DATA segments  */
		if(!(offset_within_data & 1))
			first_byte = b;
		else	/* second of two */
		{
			k = (b<<8) + first_byte;
			if( words_in_block )
				block_put(k);
			else		/* No block currently in progess */
				if( k )		/* ..then start a block  with k */
				{
					*block_pointer++ = offset_within_data - 1;
					*block_pointer++ = k;
					consecutive_zeroes = 0;
					words_in_block = 1;
				}
		}
		offset_within_data ++;
	}
	else if( exe_image_offset > C_ETEXT_offset)
		/* Substitute startup parameters (like initialSP) */
			output_a_byte(*startup_ptr++);
	else	/* in CODE segments */
		output_a_byte(b);
}

block_put(j)
{
	*block_pointer++ = j;
	words_in_block++;
	if(j)
		consecutive_zeroes = 0;
	else		/*  j == 0000  */
		if( ++consecutive_zeroes > 2)
			flush_block();
	if(words_in_block > 200)
		flush_block();
}

flush_block()
{
	register int i,j;

	if(block_buffer[0] = (words_in_block -= consecutive_zeroes))
	{
		for(i=0; i<words_in_block+2; i++)
			output_a_word( block_buffer[i] );
		printf("/%3d",words_in_block);
	}
	block_pointer = &block_buffer[1];
	words_in_block = consecutive_zeroes = 0;
}

output_a_word(ww)
{
	output_a_byte( ww & 0xff );
	output_a_byte( ww >> 8   );
}

output_a_byte(bb)
  unsigned char bb;
{
	static unsigned char last_bb;
	if( bytes_in_outbuffer == sizeof(outbuffer) )
		flush_outbuffer();
	bytes_in_outbuffer ++;
	*outbuffer_pointer++ = bb;
	if(romaddr++ & 1L)
		chksum += (bb<<8) + last_bb;
	else
		last_bb = bb;
}

set_next_reloc_offset()
{
	unsigned int k,m,n;
	if( !remaining_reloc_entries )
		next_reloc_offset = 0xfffffffe;
	else
	{
		remaining_reloc_entries --;
		k = *reloc_table_pointer++;		/* OFFSET portion */
		m = *reloc_table_pointer++;		/* SEGMENT portion */
		next_reloc_offset = m * 16L + k;
	}
}

flush_outbuffer()
{
	if(!bytes_in_outbuffer)    return;
	if(write(rom_file, outbuffer, bytes_in_outbuffer )
		!= bytes_in_outbuffer)
			abort_with( "Error writing .ROM file" );
	bytes_in_outbuffer = 0;
	outbuffer_pointer = outbuffer;
}

abort_with( s )
  char *s;
{
	printf("\r\n%s\r\n",s);
	if( rom_file > 0 )
	{
		close( rom_file );
		remove( romfilename );
	}
	exit(9);
}

int segoff_compare(so1,so2)  /* used for Qsorting the reloc table */
  unsigned int *so1,*so2;
{
	unsigned long int k1,k2;
	k1 = *so1 + (   ((unsigned long int)*(so1+1))   << 4 );
	k2 = *so2 + (   ((unsigned long int)*(so2+1))   << 4 );
	if(k1<k2)  return -1;
	if(k1==k2) return 0;
	return 1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -