📄 exe2rom.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 + -