/* ------------------------------------------------------------------------- saturn - A poor-man's emulator of some HP calculators Copyright (C) 1998-2000 Ivan Cibrario Bertolotti This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the documentation of this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. For more information, please contact the author, preferably by email, at the following address: Ivan Cibrario Bertolotti IRITI - National Research Council c/o IEN "Galileo Ferraris" Strada delle Cacce, 91 10135 - Torino (ITALY) email: cibrario@iriti.cnr.it ------------------------------------------------------------------------- */ /* +-+ */ /* .+ .identifier : $Id: pack.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $ .context : SATURN, Saturn CPU / HP48 emulator .title : $RCSfile: pack.c,v $ .kind : C source .author : Ivan Cibrario B. .site : CSTV-CNR .creation : 2-Oct-2000 .keywords : * .description : This file packs a ROM image of emu48/49 (first argument) into a format suitable for saturn (second argument). This utility is totally unsupported and will likely be removed in the near future. .include : * .notes : $Log: pack.c,v $ Revision 4.1 2000/12/11 09:54:19 cibrario Public release. Revision 3.10 2000/10/24 16:14:52 cibrario Added/Replaced GPL header Revision 3.6 2000/10/02 13:55:06 cibrario *** empty log message *** .- */ #ifndef lint static char rcs_id[] = "$Id"; #endif #include #include #include #include #include #include #include #include #include #include "config.h" #include "machdep.h" #include "cpu.h" #include "disk_io.h" #define CHF_MODULE_ID UTIL_CHF_MODULE_ID #include /* Maximum size of source ROM (bytes) handled by this utility; set to a reasonable value */ #define MAX_SRC_SIZE ( 4 * 1024 * 1024 ) /*--------------------------------------------------------------------------- Chf parameters - Do not change. The ABNORMAL_EXIT_CODE is taken from stdlib.h (EXIT_FAILURE) ---------------------------------------------------------------------------*/ #define CONDITION_STACK_SIZE 16 #define HANDLER_STACK_SIZE 8 #define ABNORMAL_EXIT_CODE EXIT_FAILURE /* Conditional prefix and mandatory suffix to make a message catalog name from cat_base_name. */ static const char cat_prefix[] = "./"; static const char cat_suffix[] = ".cat"; #define CAT_PREFIX_LEN ( sizeof( cat_prefix ) + 1 ) #define CAT_SUFFIX_LEN ( sizeof( cat_suffix ) + 1 ) /* Message catalog base_name */ static const char cat_base_name[] = "saturn"; /* Condition codes used by this utility */ #define UTIL_I_PACK_USAGE 1 #define UTIL_F_PACK_CMD_LINE 2 #define UTIL_F_PACK_STAT 3 #define UTIL_F_PACK_SRC_SIZE 4 #define UTIL_F_PACK_MALLOC 5 #define UTIL_F_PACK_OPEN 6 #define UTIL_F_PACK_READ 7 #define UTIL_F_PACK_WRITE_NIBBLES 8 /*--------------------------------------------------------------------------- Public functions ---------------------------------------------------------------------------*/ /* .+ .title : main .kind : C function .creation : 2-Oct-2000 .description : Main program. .notes : 3.6, 2-Oct-2000, creation .- */ int main( int argc, char* argv[] ) { char* cat_name; /* Message catalog name */ struct stat statb; /* stat() buffer on source file */ char* b; /* Source buffer */ Nibble* nb; /* Nibble buffer */ int d; /* Source file descriptor */ int i; int st; if ( ( cat_name = malloc( sizeof( cat_base_name ) + CAT_PREFIX_LEN + CAT_SUFFIX_LEN + 1 ) ) == NULL ) { fprintf( stderr, "Cat_name initialization failed\n" ); exit( ABNORMAL_EXIT_CODE ); } /* Generate catalog name, without optional prefix */ strcpy( cat_name, cat_base_name ); strcat( cat_name, cat_suffix ); /* Chf initialization with msgcat subsystem; notice that on some systems (e.g. Digital UNIX) catopen() can succeed even if it was not able to open the right message catalog; better try it now. */ if ( ( st = ChfMsgcatInit( argv[ 0 ], /* Application's name */ CHF_DEFAULT, /* Options */ cat_name, /* Name of the message catalog */ CONDITION_STACK_SIZE, /* Size of the condition stack */ HANDLER_STACK_SIZE, /* Size of the handler stack */ ABNORMAL_EXIT_CODE /* Abnormal exit code */ ) ) != CHF_S_OK || ChfGetMessage( CHF_MODULE_ID, UTIL_I_PACK_USAGE, NULL ) == NULL ) { if ( st != CHF_S_OK && st != CHF_F_CATOPEN ) { fprintf( stderr, "Chf initialization failed\n" ); exit( ABNORMAL_EXIT_CODE ); } else { fprintf( stderr, "Default message catalog open failed; trying alternate\n" ); /* Bring down Chf before initializing it again */ if ( st == CHF_S_OK ) ChfExit(); /* Try alternate message catalog name (with prefix) */ strcpy( cat_name, cat_prefix ); strcat( cat_name, cat_base_name ); strcat( cat_name, cat_suffix ); if ( ( st = ChfMsgcatInit( argv[ 0 ], /* Application's name */ CHF_DEFAULT, /* Options */ cat_name, /* Name of the message catalog */ CONDITION_STACK_SIZE, /* Size of the condition stack */ HANDLER_STACK_SIZE, /* Size of the handler stack */ ABNORMAL_EXIT_CODE /* Abnormal exit code */ ) ) != CHF_S_OK || ChfGetMessage( CHF_MODULE_ID, UTIL_I_PACK_USAGE, NULL ) == NULL ) { fprintf( stderr, "Alternate Chf initialization failed\n" ); exit( ABNORMAL_EXIT_CODE ); } } } /* cat_name no longer needed */ free( cat_name ); /* Now, do some useful work; pack argv[1] into argv[2] */ if ( argc != 3 ) { ChfCondition UTIL_I_PACK_USAGE, CHF_INFO ChfEnd; ChfCondition UTIL_F_PACK_CMD_LINE, CHF_FATAL ChfEnd; ChfSignal(); } /* Get the size of the source file */ if ( stat( argv[ 1 ], &statb ) ) { ChfErrnoCondition; ChfCondition UTIL_F_PACK_STAT, CHF_FATAL, argv[ 1 ] ChfEnd; ChfSignal(); } /* Check that actual size is reasonable */ if ( statb.st_size > MAX_SRC_SIZE ) { ChfCondition UTIL_F_PACK_SRC_SIZE, CHF_FATAL, statb.st_size ChfEnd; ChfSignal(); } /* Allocate source buffer */ if ( ( b = ( char* )malloc( statb.st_size ) ) == ( char* )NULL || ( nb = ( Nibble* )malloc( sizeof( Nibble ) * statb.st_size ) ) == ( Nibble* )NULL ) { ChfErrnoCondition; ChfCondition UTIL_F_PACK_MALLOC, CHF_FATAL, statb.st_size ChfEnd; ChfSignal(); return EXIT_FAILURE; } /* open/read/close */ if ( ( d = open( argv[ 1 ], O_RDONLY ) ) == -1 ) { ChfErrnoCondition; ChfCondition UTIL_F_PACK_OPEN, CHF_FATAL, argv[ 1 ] ChfEnd; ChfSignal(); } if ( read( d, b, statb.st_size ) != statb.st_size ) { ChfErrnoCondition; ( void )close( d ); ChfCondition UTIL_F_PACK_READ, CHF_FATAL, argv[ 1 ] ChfEnd; ChfSignal(); } ( void )close( d ); /* Convert char -> Nibble */ for ( i = 0; i < statb.st_size; i++ ) nb[ i ] = ( Nibble )b[ i ]; /* Source buffer no longer needed */ free( b ); /* Write */ if ( WriteNibblesToFile( nb, statb.st_size, argv[ 2 ] ) ) { ChfCondition UTIL_F_PACK_WRITE_NIBBLES, CHF_FATAL ChfEnd; ChfSignal(); } return EXIT_SUCCESS; }