From ec415e2315bfcf647e07febba35db4ef709b27d0 Mon Sep 17 00:00:00 2001 From: Hugo Villeneuve Date: Wed, 12 May 2004 05:19:56 +0000 Subject: [PATCH] Add options -h and -version Merge common function LoadHexFile() to file.c. --- doc/emu8051.man | 2 +- src/EmuConsole.cpp | 219 ++++++++++++++++----------------------------- src/EmuConsole.hpp | 5 +- src/EmuGtk.cpp | 133 +++++---------------------- src/EmuGtk.hpp | 7 +- src/Makefile.am | 5 +- src/common.h | 46 ++++++++++ src/file.c | 138 ++++++++++++++++++++++++++++ src/file.h | 11 +++ src/options.c | 119 ++++++++++++++++++++++++ src/options.h | 14 +++ 11 files changed, 434 insertions(+), 265 deletions(-) create mode 100644 src/common.h create mode 100644 src/file.c create mode 100644 src/file.h create mode 100644 src/options.c create mode 100644 src/options.h diff --git a/doc/emu8051.man b/doc/emu8051.man index 956d4c9..8b50f42 100644 --- a/doc/emu8051.man +++ b/doc/emu8051.man @@ -20,7 +20,7 @@ It is written in C++, and uses Perl scripts to generate automatically C++ functi \fB\-h\fR display usage and exit .TP -\fB\-v\fR +\fB\-version\fR output version information and exit .SH CREDITS diff --git a/src/EmuConsole.cpp b/src/EmuConsole.cpp index 0a0fe66..d28e568 100644 --- a/src/EmuConsole.cpp +++ b/src/EmuConsole.cpp @@ -1,4 +1,4 @@ -// EmuConsole.cpp +/* EmuConsole.cpp */ #include #include @@ -9,6 +9,21 @@ #include "Reg8051.hpp" #include "Keyboard.hpp" +extern "C" { +#include "options.h" +#include "file.h" +} + + +EmuConsole *EmuConsolePtr; + + +static void +cpu_write_pgm( unsigned int Address, unsigned char Value ) +{ + EmuConsolePtr->CPU->WritePGM( Address, Value ); +} + int main( int argc, char **argv ) { @@ -26,6 +41,37 @@ int main( int argc, char **argv ) } +unsigned int +Ascii2Hex_TEMP( string istring, unsigned int length ) +{ + if ( !length || ( length > istring.size() ) ) + length = istring.size(); + + if ( istring.empty() ) + throw MissingParameter(); + + unsigned int result = 0; + unsigned int i, ascii_code; + for ( i = 0; i < length; i++ ) { + ascii_code = istring[ i ]; + if ( ascii_code > 0x39 ) + ascii_code &= 0xDF; + if ( ( ascii_code >= 0x30 && ascii_code <= 0x39 ) || ( ascii_code >= 0x41 && ascii_code <= 0x46 ) ) { + ascii_code -= 0x30; + if ( ascii_code > 9 ) + ascii_code -= 7; + result <<= 4; + result += ascii_code; + } + else { + throw SyntaxError(); + } + } + return result; +} + + + ////////////////////////////////////////////////////////////////////////////// // EmuConsole::EmuConsole( int argc, char **argv, CPU8051 *mCPU ) // EmuConsole constructor @@ -35,7 +81,14 @@ EmuConsole::EmuConsole( int argc, char **argv, CPU8051 *mCPU ) CPU = mCPU; CPU->Reset( ); NbBreakpoints = 0; - if ( argc > 1 ) LoadHexFile( argv[ 1 ] ); + + EmuConsolePtr = this; + + ParseCommandLineOptions( argc, argv ); + + if( GetHexFileName() != NULL ) { + LoadHexFile( GetHexFileName(), cpu_write_pgm ); + } } ////////////////////////////////////////////////////////////////////////////// @@ -183,18 +236,18 @@ void EmuConsole::Main( ) if ( Parameter1.empty() || Parameter2.empty() ) throw MissingParameter(); else if ( Command == "ME" ) { - unsigned int adresse = Ascii2Hex( Parameter1, 4 ); - unsigned char valeur = Ascii2Hex( Parameter2, 2 ); + unsigned int adresse = Ascii2Hex_TEMP( Parameter1, 4 ); + unsigned char valeur = Ascii2Hex_TEMP( Parameter2, 2 ); CPU->WriteExt( adresse, valeur ); } else if ( Command == "MI" ) { - unsigned char adresse = Ascii2Hex( Parameter1, 2 ); - unsigned char valeur = Ascii2Hex( Parameter2, 2 ); + unsigned char adresse = Ascii2Hex_TEMP( Parameter1, 2 ); + unsigned char valeur = Ascii2Hex_TEMP( Parameter2, 2 ); CPU->WriteInt( adresse, valeur ); } else if ( Command == "MP" ) { - unsigned int adresse = Ascii2Hex( Parameter1, 4 ); - unsigned char valeur = Ascii2Hex( Parameter2, 2 ); + unsigned int adresse = Ascii2Hex_TEMP( Parameter1, 4 ); + unsigned char valeur = Ascii2Hex_TEMP( Parameter2, 2 ); CPU->WritePGM( adresse, valeur ); } else if ( Command == "MR" ) @@ -215,7 +268,7 @@ void EmuConsole::Main( ) if ( Parameter1.empty( ) ) ClearBreakpoint( CPU->GetPC( ) ); else - ClearBreakpoint( Ascii2Hex( Parameter1, 4 ) ); + ClearBreakpoint( Ascii2Hex_TEMP( Parameter1, 4 ) ); } else throw SyntaxError( ); @@ -227,7 +280,7 @@ void EmuConsole::Main( ) if ( Parameter1.empty( ) ) SetBreakpoint( CPU->GetPC( ) ); else - SetBreakpoint( Ascii2Hex( Parameter1, 4 ) ); + SetBreakpoint( Ascii2Hex_TEMP( Parameter1, 4 ) ); } else throw SyntaxError( ); @@ -299,7 +352,7 @@ void EmuConsole::Reset( ) ////////////////////////////////////////////////////////////////////////////// void EmuConsole::Trace( string Address ) { - if ( !Address.empty( ) ) CPU->SetPC( Ascii2Hex( Address, Address.size( ) ) ); + if ( !Address.empty( ) ) CPU->SetPC( Ascii2Hex_TEMP( Address, Address.size( ) ) ); CPU->Exec( ); ShowRegisters( ); DisasmN( CPU->GetPC( ), 1 ); @@ -315,10 +368,10 @@ void EmuConsole::Exec( string Address, string NumberInst ) int NbInst = -1; // -1 is infinity if ( !Address.empty( ) ) { Capitalize( &Address ); - if ( Address != "PC" ) CPU->SetPC( Ascii2Hex( Address, Address.size( ) ) ); + if ( Address != "PC" ) CPU->SetPC( Ascii2Hex_TEMP( Address, Address.size( ) ) ); } - if ( !NumberInst.empty( ) ) NbInst = Ascii2Hex( NumberInst, NumberInst.size( ) ); + if ( !NumberInst.empty( ) ) NbInst = Ascii2Hex_TEMP( NumberInst, NumberInst.size( ) ); InitUnixKB( ); @@ -392,9 +445,9 @@ void EmuConsole::Disasm( string Address, string NumberInst ) unsigned int MemAddress, NbInst; Capitalize( &Address ); if ( Address.empty( ) || ( Address == "PC" ) ) MemAddress = CPU->GetPC( ); - else MemAddress = Ascii2Hex( Address, Address.size( ) ); + else MemAddress = Ascii2Hex_TEMP( Address, Address.size( ) ); if ( NumberInst.empty( ) ) NumberInst = "10"; - NbInst = Ascii2Hex( NumberInst, NumberInst.size( ) ); + NbInst = Ascii2Hex_TEMP( NumberInst, NumberInst.size( ) ); DisasmN( MemAddress, NbInst ); } @@ -426,7 +479,7 @@ void EmuConsole::DumpPGM( string Address ) if ( Address == "PC" ) MemAddress = CPU->GetPC( ); else - MemAddress = Ascii2Hex( Address, Address.size( ) ); + MemAddress = Ascii2Hex_TEMP( Address, Address.size( ) ); } for ( Offset = 0; Offset < 256; Offset += 16 ) { printf( "%.4X ", MemAddress + Offset ); @@ -456,7 +509,7 @@ void EmuConsole::DumpI( string Address ) unsigned int MemAddress = 0; int Offset, Column; unsigned char Byte; - if ( !Address.empty( ) ) MemAddress = Ascii2Hex( Address, Address.size( ) ); + if ( !Address.empty( ) ) MemAddress = Ascii2Hex_TEMP( Address, Address.size( ) ); for ( Offset = 0; Offset < 256; Offset += 16 ) { printf( "%.4X ", MemAddress + Offset ); for ( Column = 0; Column < 16; Column++ ) @@ -482,7 +535,7 @@ void EmuConsole::DumpInt( string Address ) int Offset, Column; unsigned char Byte; if ( !Address.empty( ) ) - MemAddress = Ascii2Hex( Address, 4 ); + MemAddress = Ascii2Hex_TEMP( Address, 4 ); for ( Offset = 0; Offset < 256; Offset += 16 ) { printf( "%.4X ", MemAddress + Offset ); for ( Column = 0; Column < 16; Column++ ) @@ -509,7 +562,7 @@ void EmuConsole::DumpExt( string Address ) int Offset, Column; unsigned char Byte; if ( !Address.empty( ) ) - MemAddress = Ascii2Hex( Address, 4 ); + MemAddress = Ascii2Hex_TEMP( Address, 4 ); for ( Offset = 0; Offset < 256; Offset += 16 ) { printf( "%.4X ", MemAddress + Offset ); for ( Column = 0; Column < 16; Column++ ) @@ -534,7 +587,7 @@ void EmuConsole::DumpD( string Address ) unsigned int MemAddress = 0; int Offset, Column; unsigned char Byte; - if ( !Address.empty( ) ) MemAddress = Ascii2Hex( Address, Address.size( ) ); + if ( !Address.empty( ) ) MemAddress = Ascii2Hex_TEMP( Address, Address.size( ) ); for ( Offset = 0; Offset < 256; Offset += 16 ) { printf( "%.4X ", MemAddress + Offset ); for ( Column = 0; Column < 16; Column++ ) @@ -557,10 +610,10 @@ void EmuConsole::DumpD( string Address ) void EmuConsole::SetRegister( string Register, string NewValue ) { Capitalize( &Register ); - if ( Register == "PC" ) CPU->SetPC( Ascii2Hex( NewValue, 4 ) ); - else if ( Register == "A" ) CPU->WriteD( _ACC_, Ascii2Hex( NewValue, 2 ) ); - else if ( Register == "B" ) CPU->WriteD( _B_, Ascii2Hex( NewValue, 2 ) ); - else if ( Register == "SP" ) CPU->WriteD( _SP_, Ascii2Hex( NewValue, 2 ) ); + if ( Register == "PC" ) CPU->SetPC( Ascii2Hex_TEMP( NewValue, 4 ) ); + else if ( Register == "A" ) CPU->WriteD( _ACC_, Ascii2Hex_TEMP( NewValue, 2 ) ); + else if ( Register == "B" ) CPU->WriteD( _B_, Ascii2Hex_TEMP( NewValue, 2 ) ); + else if ( Register == "SP" ) CPU->WriteD( _SP_, Ascii2Hex_TEMP( NewValue, 2 ) ); else throw InvalidRegister( ); } @@ -617,121 +670,3 @@ void EmuConsole::ShowRegisters( ) printf( "----------------------------------------------------------------------%s", ENDLINE ); } - -////////////////////////////////////////////////////////////////////////////// -// void EmuConsole::LoadHexFile( string Filename ) -// -////////////////////////////////////////////////////////////////////////////// -void EmuConsole::LoadHexFile( string Filename ) -{ - - printf("LoadHex\n"); - int i, j, RecLength, LoadOffset, RecType, Data, Checksum; - char Line[ 250 ]; - - ifstream HexFile( Filename.c_str() ); - try { - if ( ! HexFile ) - throw ErrorOpeningFile(); - - while( ! HexFile.eof() ) { - i = 0; - Checksum = 0; - HexFile.getline( Line, 250, '\n' ); - - if ( Line[ i++ ] != ':' ) - throw ErrorHexFileFormat(); - - RecLength = Ascii2Hex( &Line[ i ], 2 ); - i += 2; - Checksum += RecLength; - - LoadOffset = Ascii2Hex( &Line[i], 4 ); - Checksum += LoadOffset / 256; - Checksum += LoadOffset % 256; - i += 4; - - RecType = Ascii2Hex( &Line[i],2); - i += 2; - Checksum += RecType; - - if ( RecType == 1 ) { - Checksum += Ascii2Hex( &Line[ i ], 2 ); - if ( Checksum &= 0x000000FF ) - throw ErrorHexFileFormat(); - throw FinishedLoading(); - } - if ( RecType ) - throw ErrorHexFileFormat(); - - for ( j = 0; j < RecLength; j++ ) { - Data = Ascii2Hex( &Line[ i ], 2 ); - CPU->WritePGM( (unsigned int)(LoadOffset + j), (unsigned char)Data ); - i += 2; - Checksum += Data; - } - RecType = Ascii2Hex( &Line[ i ], 2 ); - Checksum += RecType; - - if ( Checksum &= 0x000000FF ) - throw ErrorHexFileFormat(); - } - throw ErrorHexFileFormat(); - } - catch ( ErrorOpeningFile ) { - cout << "Error opening file " << Filename << endl; - } - catch ( ErrorHexFileFormat ) { - cout << "Invalid format for " << Filename << " file..." << endl; - } - catch ( SyntaxError ) { - cout << "Invalid format for " << Filename << " file..." << endl; - } - catch ( MissingParameter ) { - cout << "Invalid format for " << Filename << " file..." << endl; - } - catch ( FinishedLoading ) { - cout << "Using file " << Filename << " as input program." << endl; - } - HexFile.close(); - -} - -////////////////////////////////////////////////////////////////////////////// -// unsigned int EmuConsole::Ascii2Hex( string istring, int length ) -// -////////////////////////////////////////////////////////////////////////////// -unsigned int EmuConsole::Ascii2Hex( string istring, unsigned int length ) -{ - if ( !length || ( length > istring.size() ) ) - length = istring.size(); - - if ( istring.empty() ) - throw MissingParameter(); - - unsigned int result = 0; - unsigned int i, ascii_code; - for ( i = 0; i < length; i++ ) { - ascii_code = istring[ i ]; - if ( ascii_code > 0x39 ) - ascii_code &= 0xDF; - if ( ( ascii_code >= 0x30 && ascii_code <= 0x39 ) || ( ascii_code >= 0x41 && ascii_code <= 0x46 ) ) { - ascii_code -= 0x30; - if ( ascii_code > 9 ) - ascii_code -= 7; - result <<= 4; - result += ascii_code; - } - else { - throw SyntaxError(); - } - } - return result; -} - - - - - - - diff --git a/src/EmuConsole.hpp b/src/EmuConsole.hpp index 0c2c094..e84d56a 100644 --- a/src/EmuConsole.hpp +++ b/src/EmuConsole.hpp @@ -24,6 +24,8 @@ public: EmuConsole( int argc, char **argv, CPU8051 *mCPU ); ~EmuConsole( ); + CPU8051 *CPU; + void Main( ); void Reset( ); @@ -46,12 +48,9 @@ public: private: - CPU8051 *CPU; int NbBreakpoints; unsigned int Breakpoints[ MAXBP ]; - void LoadHexFile( string Filename ); - unsigned int Ascii2Hex( string istring, unsigned int length ); void Capitalize( string *InputString ); void RemoveSpaces( string *InputString ); diff --git a/src/EmuGtk.cpp b/src/EmuGtk.cpp index 4ac5245..74a6e66 100644 --- a/src/EmuGtk.cpp +++ b/src/EmuGtk.cpp @@ -11,6 +11,11 @@ #include "stop.xpm" #include "step.xpm" +extern "C" { +#include "options.h" +#include "file.h" +} + int EmuGtkNumber = 0; int NbSignals = 0; @@ -32,6 +37,13 @@ enum }; +static void +cpu_write_pgm( unsigned int Address, unsigned char Value ) +{ + EmuGtkPtr->CPU->WritePGM( Address, Value ); +} + + int main( int argc, char **argv ) { CPU8051 *maincpu = new CPU8051; @@ -46,6 +58,7 @@ int main( int argc, char **argv ) return 0; } + ////////////////////////////////////////////////////////////////////////////// // EmuGtk::EmuGtk( ) // EmuGtk constructor @@ -55,6 +68,8 @@ EmuGtk::EmuGtk( int argc, char **argv, CPU8051 *mCPU ) CPU = mCPU; RunningState = 0; + ParseCommandLineOptions( argc, argv ); + g_print( "\n" ); gtk_init( &argc, &argv ); @@ -161,12 +176,12 @@ EmuGtk::EmuGtk( int argc, char **argv, CPU8051 *mCPU ) EmuGtkNumber++; } - if ( argc > 1 ) - LoadHexFile( argv[1] ); + if( GetHexFileName() != NULL ) { + LoadHexFile( GetHexFileName(), cpu_write_pgm ); + } } - ////////////////////////////////////////////////////////////////////////////// // void AddButtons() // Create and show the Reset, Run, Stop, Trace and Step buttons @@ -411,13 +426,13 @@ void FileOpenDialog_OK( GtkButton *button, gpointer data ) const gchar *SelectedFile; - SelectedFile = gtk_file_selection_get_filename ( GTK_FILE_SELECTION ( data ) ); + SelectedFile = (const gchar *) gtk_file_selection_get_filename ( GTK_FILE_SELECTION ( data ) ); g_print( "EmuGtk::File = %s\n", SelectedFile ); EmuGtkPtr->StopRunning( ); - EmuGtkPtr->LoadHexFile( SelectedFile ); + LoadHexFile( SelectedFile, cpu_write_pgm ); gtk_widget_destroy( GTK_WIDGET( data ) ); @@ -505,114 +520,6 @@ void EmuGtk::StepEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) Step( ); } -////////////////////////////////////////////////////////////////////////////// -// unsigned int EmuGtk::Ascii2Hex( string istring, int length = 0 ) -// Convert an ascii string to an hexadecimal number -////////////////////////////////////////////////////////////////////////////// -unsigned int EmuGtk::Ascii2Hex( string istring, int length = 0 ) -{ - if ( !length || ( length > (int) istring.size() ) ) - length = istring.size(); - - if ( istring.empty() ) - throw MissingParameter(); - - unsigned int result = 0; - int i, ascii_code; - for ( i = 0; i < length; i++ ) { - ascii_code = istring[ i ]; - if ( ascii_code > 0x39 ) - ascii_code &= 0xDF; - if ( ( ascii_code >= 0x30 && ascii_code <= 0x39 ) || ( ascii_code >= 0x41 && ascii_code <= 0x46 ) ) { - ascii_code -= 0x30; - if ( ascii_code > 9 ) - ascii_code -= 7; - result <<= 4; - result += ascii_code; - } - else { - throw SyntaxError(); - } - } - return result; -} - -////////////////////////////////////////////////////////////////////////////// -// void EmuGtk::LoadHexFile( string Filename ) -// Load an HEX file into program memory -////////////////////////////////////////////////////////////////////////////// -void EmuGtk::LoadHexFile( string Filename ) -{ - printf("LoadHex\n"); - int i, j, RecLength, LoadOffset, RecType, Data, Checksum; - char Line[ 250 ]; - - ifstream HexFile( Filename.c_str() ); - try { - if ( ! HexFile ) - throw ErrorOpeningFile(); - - while( ! HexFile.eof() ) { - i = 0; - Checksum = 0; - HexFile.getline( Line, 250, '\n' ); - - if ( Line[ i++ ] != ':' ) - throw ErrorHexFileFormat(); - - RecLength = Ascii2Hex( &Line[ i ], 2 ); - i += 2; - Checksum += RecLength; - - LoadOffset = Ascii2Hex( &Line[i], 4 ); - Checksum += LoadOffset / 256; - Checksum += LoadOffset % 256; - i += 4; - - RecType = Ascii2Hex( &Line[i],2); - i += 2; - Checksum += RecType; - - if ( RecType == 1 ) { - Checksum += Ascii2Hex( &Line[ i ], 2 ); - if ( Checksum &= 0x000000FF ) - throw ErrorHexFileFormat(); - throw FinishedLoading(); - } - if ( RecType ) - throw ErrorHexFileFormat(); - - for ( j = 0; j < RecLength; j++ ) { - Data = Ascii2Hex( &Line[ i ], 2 ); - CPU->WritePGM( (unsigned int)(LoadOffset + j), (unsigned char)Data ); - i += 2; - Checksum += Data; - } - RecType = Ascii2Hex( &Line[ i ], 2 ); - Checksum += RecType; - - if ( Checksum &= 0x000000FF ) - throw ErrorHexFileFormat(); - } - throw ErrorHexFileFormat(); - } - catch ( ErrorOpeningFile ) { - cout << "Error opening file " << Filename << endl; - } - catch ( ErrorHexFileFormat ) { - cout << "Invalid format for " << Filename << " file..." << endl; - } - catch ( SyntaxError ) { - cout << "Invalid format for " << Filename << " file..." << endl; - } - catch ( MissingParameter ) { - cout << "Invalid format for " << Filename << " file..." << endl; - } - catch ( FinishedLoading ) { - cout << "Using file " << Filename << " as input program." << endl; - } - HexFile.close(); -} ////////////////////////////////////////////////////////////////////////////// // gint EmuGtkSignalStub2( GtkWidget *widget, gpointer data ) diff --git a/src/EmuGtk.hpp b/src/EmuGtk.hpp index 8fe4713..b94b784 100644 --- a/src/EmuGtk.hpp +++ b/src/EmuGtk.hpp @@ -22,6 +22,8 @@ class EmuGtk { public: EmuGtk( int argc , char **argv, CPU8051 *mCPU ); ~EmuGtk( ); + + CPU8051 *CPU; /* Test */ void Main( ); @@ -49,12 +51,11 @@ public: void StopRunning( ); void Running( ); - void LoadHexFile( string Filename ); void UpdateDisplay(); private: int EmuGtkID; - CPU8051 *CPU; + int RunningState; int RunFuncTag; MemWin *memwin; @@ -96,8 +97,6 @@ private: GdkPixmap *STEP_pixmap; GtkWidget *STEP_widget; GtkWidget *ButtonStep; - - unsigned int Ascii2Hex( string istring, int length ); }; void EmuGtkSignalStub3( GtkWidget *widget, GdkEvent *event, gpointer data ); diff --git a/src/Makefile.am b/src/Makefile.am index f17fac9..ede6e24 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,10 +5,11 @@ INCLUDES = -I$(top_srcdir)/pixmaps bin_PROGRAMS = emu8051 emu8051_console emu8051_SOURCES = EmuGtk.hpp EmuGtk.cpp CPU8051.hpp CPU8051.cpp Memory.hpp Memory.cpp \ - MemWin.hpp MemWin.cpp PgmWin.hpp PgmWin.cpp RegWin.hpp RegWin.cpp + MemWin.hpp MemWin.cpp PgmWin.hpp PgmWin.cpp RegWin.hpp RegWin.cpp options.c \ + common.h file.c emu8051_console_SOURCES = EmuConsole.hpp EmuConsole.cpp CPU8051.hpp CPU8051.cpp Memory.hpp \ - Memory.cpp Keyboard.hpp + Memory.cpp Keyboard.hpp options.c common.h file.c # These headers will be included in the distribution tarball, but will not be # installed by 'make install' diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..9a3d3e8 --- /dev/null +++ b/src/common.h @@ -0,0 +1,46 @@ +/* common.h */ + +#ifndef COMMON_H +#define COMMON_H 1 + + +#include +#include +#include + +#if STDC_HEADERS +# include +#elif HAVE_STRINGS_H +# include +#endif + + +/* Common constants. */ +#ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# define EXIT_FAILURE 1 +#endif + +typedef int bool; +#ifndef FALSE +# define FALSE 0 +# define TRUE 1 +#endif + + +/* Returns TRUE if the strings 'a' and 'b' are equal. */ +#define STREQ(a, b) (strcmp((a), (b)) == 0) + +/* Returns TRUE if the first 'c' characters of strings 'a' and 'b' are equal. */ +#define STREQ_LEN(a, b, c) (strncmp((a), (b), (c)) == 0) + + +inline void +ErrorLocation( const char *file, int line ); + +/*@out@*/ /*@only@*/ +void * +xmalloc( size_t size, const char *filename, int line_number ); + + +#endif /* COMMON_H */ diff --git a/src/file.c b/src/file.c new file mode 100644 index 0000000..90d99d5 --- /dev/null +++ b/src/file.c @@ -0,0 +1,138 @@ +/* file.c -- functions for loading an Intel HEX file + Copyright (C) 2004 Hugo Villeneuve */ + + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#if STDC_HEADERS +# include +#elif HAVE_STRINGS_H +# include +#endif + +#include "common.h" + + +/* Convert an ascii string to an hexadecimal number. */ +static unsigned int +Ascii2Hex( char *istring, int length ) +{ + unsigned int result = 0; + int i, ascii_code; + + if ( !length || ( length > (int) strlen(istring) ) ) { + length = strlen(istring); + } + + for ( i = 0; i < length; i++ ) { + ascii_code = istring[ i ]; + if ( ascii_code > 0x39 ) { + ascii_code &= 0xDF; + } + if ( ( ascii_code >= 0x30 && ascii_code <= 0x39 ) || + ( ascii_code >= 0x41 && ascii_code <= 0x46 ) ) { + ascii_code -= 0x30; + if ( ascii_code > 9 ) { + ascii_code -= 7; + } + result <<= 4; + result += ascii_code; + } + else { + printf( "%s: In Ascii2Hex(), syntax error.\n", PACKAGE ); + } + } + return result; +} + + +void +LoadHexFile( const char *filename, void (* cpu_write_pgm)( unsigned int Address, unsigned char Value ) ) +{ + int i, j, RecLength, LoadOffset, RecType, Data, Checksum; + +#define LINE_BUFFER_LEN 256 + FILE *fp; + int status; + char line[LINE_BUFFER_LEN]; + + if( filename != NULL ) { + /* Trying to open the file. */ + fp = fopen( filename, "r" ); + if( fp == NULL ) { + perror( PACKAGE ); + /*ErrorLocation( __FILE__, __LINE__ );*/ + exit( EXIT_FAILURE ); + } + } + + /* Reading one line of data from the configuration file. */ + /* char *fgets(char *s, int size, FILE *stream); + Reading stops after an EOF or a newline. If a newline is read, it is + stored into the buffer. A '\0' is stored after the last character in + the buffer. */ + while( fgets( line, LINE_BUFFER_LEN, fp ) != NULL ) { + i = 0; + Checksum = 0; + + if ( line[ i++ ] != ':' ) { + printf( "%s: line not beginning with \":\"\n", PACKAGE ); + goto close_file; + } + + RecLength = Ascii2Hex( &line[ i ], 2 ); + i += 2; + Checksum += RecLength; + + LoadOffset = Ascii2Hex( &line[i], 4 ); + Checksum += LoadOffset / 256; + Checksum += LoadOffset % 256; + i += 4; + + RecType = Ascii2Hex( &line[i],2); + i += 2; + Checksum += RecType; + + if ( RecType == 1 ) { + Checksum += Ascii2Hex( &line[ i ], 2 ); + if ( Checksum &= 0x000000FF ) { + /* Error. */ + printf( "%s: Invalid format\n", PACKAGE ); + goto close_file; + } + else { + /* OK */ + goto close_file; + } + } + + for ( j = 0; j < RecLength; j++ ) { + Data = Ascii2Hex( &line[ i ], 2 ); + (*cpu_write_pgm)( (unsigned int)(LoadOffset + j), (unsigned char)Data ); + i += 2; + Checksum += Data; + } + + RecType = Ascii2Hex( &line[ i ], 2 ); + Checksum += RecType; + + if ( Checksum &= 0x000000FF ) { + printf( "%s: Invalid format\n", PACKAGE ); + goto close_file; + } + } + + close_file: + status = fclose( fp ); + if( status != EXIT_SUCCESS ) { + fprintf( stderr, "%s: Error closing configuration file.\n", PACKAGE ); + /*ErrorLocation( __FILE__, __LINE__ );*/ + exit( EXIT_FAILURE ); + } +} diff --git a/src/file.h b/src/file.h new file mode 100644 index 0000000..d163725 --- /dev/null +++ b/src/file.h @@ -0,0 +1,11 @@ +/* file.h */ + +#ifndef FILE_H +#define FILE_H 1 + + +void +LoadHexFile( const char *filename, void (* cpu_write_pgm)( unsigned int Address, unsigned char Value ) ); + + +#endif /* FILE_H */ diff --git a/src/options.c b/src/options.c new file mode 100644 index 0000000..e32f811 --- /dev/null +++ b/src/options.c @@ -0,0 +1,119 @@ +/* options.c -- functions for processing command-line options and arguments + Copyright (C) 2003 Hugo Villeneuve */ + + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#if STDC_HEADERS +# include +#elif HAVE_STRINGS_H +# include +#endif + +#include "common.h" +#include "options.h" + + +char *hex_file; + + +char * +GetHexFileName( void ) +{ + return hex_file; +} + + +/******************************************************************************* + * Display the help message and exit + ******************************************************************************/ +static void +DisplayUsage( void ) +{ + printf( "Usage: %s [OPTION]... [FILENAME]\n", PACKAGE ); + printf( "Simulator/emulator for 8051 family microcontrollers.\n\n" ); + printf( " -h display this help and exit\n" ); + printf( " -version display version information and exit\n"); + printf( "\n" ); +} + + +/******************************************************************************* + * Display version information and exit + ******************************************************************************/ +static void +DisplayVersion( void ) +{ + printf( "\n" ); + printf( " %s, version %s\n", PACKAGE, VERSION ); + printf( " Written by Hugo Villeneuve, Jonathan St-André and Pascal Fecteau.\n\n" ); +} + + +static void +InvalidOption( const char *message, /*@null@*/ const char *string ) +{ + if( string == NULL ) { + fprintf(stderr, "%s: %s\n", PACKAGE, message ); + } + else { + fprintf(stderr, "%s: %s %s\n", PACKAGE, message, string ); + } + + fprintf(stderr, "Try `%s -h' for more information.\n", PACKAGE ); + + exit( EXIT_FAILURE ); +} + + +/******************************************************************************* + * Initializes the different options passed as arguments on the command line. + ******************************************************************************/ +void +ParseCommandLineOptions( int argc, char *argv[] ) +{ + int i; + char *token; + + for( i = 1; i < argc; i++ ) { + token = argv[i]; + switch( token[0] ) { + case '-': + /* Processing options names */ + switch( token[1] ) { + case 'h': + if( strlen( &token[1] ) == 1 ) { + DisplayUsage(); + exit( EXIT_SUCCESS ); + } + InvalidOption( "invalid option", token ); + break; + case 'v' : + if( STREQ( "version", &token[1] ) ) { + DisplayVersion(); + exit( EXIT_SUCCESS ); + } + else { + InvalidOption( "invalid option", token ); + } + break; + default: + InvalidOption( "invalid option", token ); + break; + } /* end switch( token[1] ) */ + break; + default: + /* Processing options arguments */ + /* Must be the filename... */ + hex_file = token; + break; + } /* end switch( token[0] ) */ + } /* end for */ + +} diff --git a/src/options.h b/src/options.h new file mode 100644 index 0000000..657e263 --- /dev/null +++ b/src/options.h @@ -0,0 +1,14 @@ +/* options.h */ + +#ifndef OPTIONS_H +#define OPTIONS_H 1 + + +char * +GetHexFileName( void ); + +void +ParseCommandLineOptions( int argc, char *argv[] ); + + +#endif /* OPTIONS_H */ -- 2.20.1