294 lines
7.6 KiB
C
294 lines
7.6 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;
|
|
}
|