saturnng/src/pack.c
2024-03-26 13:36:50 +01:00

269 lines
8.5 KiB
C

/* -------------------------------------------------------------------------
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 <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "config.h"
#include "machdep.h"
#include "cpu.h"
#include "disk_io.h"
#define CHF_MODULE_ID UTIL_CHF_MODULE_ID
#include <Chf.h>
/* 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;
}