supermario/base/SuperMarioProj.1994-02-09/Tools/hiram.c
2019-06-29 23:17:50 +08:00

1409 lines
55 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
File: Hiram.c
Contains: Source to MPW tool that converts linker output into a ROM image.
Written by: J. T. Coonen
Copyright: © 1985-1990, 1992 by Apple Computer, Inc., all rights reserved.
Change History (most recent first):
<SM6> 10/18/92 CCH Bumped block size for interleaved writes to 2MB to make writes
fast.
<SM5> 6/16/92 CS (RB) Include TextUtils.h to comply with new interface files.
<SM4> 5/29/92 RB Modified output of ROM statistics to also show sizes in K bytes.
<3> 3/26/92 JSM OSEvents.h is obsolete, use Events.h only. Update copyright to
1992. Rolled this version of the file into Reality.
<2> 2/11/92 RB Need to check in version 4 of Hiram from the Zydeco project to
fully support 2 Meg ROMs. Included String, Strings and
StdLib.h's Changed variable name Alignment to gAlignment to
avoid a conflict. Added prototypes.
———————————————————————————————————————————————————————————————————————————————————————
Pre Super Mario ROM comments begin here.
———————————————————————————————————————————————————————————————————————————————————————
<4> 12/02/91 jmp Changed references to GetResource to Get1Resource to fix a
problem with various System Extensions that patch things like
the standard WDEFs, CDEFs, MBDFs, etc….
<3> 11/11/91 BG Added a local -long- variable and copied *rsrcID* to it, then
passed the long to -sprintf()- since passing negative -short-
values to it causes it to print the unsigned value under MPW3.2.
<2> 10/25/91 jmp Checking in Sams changes from Horror into Zydeco-TERROR.
<1> 10/23/91 SAM Reformatted all of the screen output so that it agrees with the
rest of the build status strings. Recompiled under MPW 3.2.
Bumped version to d2.
———————————————————————————————————————————————————————————————————————————————————————
Pre-Zydeco ROM comments begin here.
———————————————————————————————————————————————————————————————————————————————————————
<4> 1/30/92 JSM Cleanup header, update copyright to 1992, rename Alignment
global to byteAlignment, include StdLib.h, String.h, and
Strings.h and add more function prototypes to avoid warnings.
This tool is now built and run from inside :Objects:ROM: as part
of a normal ROM build.
<3> 1/16/90 CCH Removed extraneous header info.
<2> 1/12/90 CCH Version 3.21: Updated copyright to 1990.
<2.4> 7/25/89 CCH Changes:
- Changed encryption algorithm slightly to make it less
obvious, and changed key to match Romulator v1.0.
<2.3> 7/20/89 CCH Changes:
- Added "-pd" option to make the forced date a pascal
date.
- Date should now be entered without "[]"'s surrounding
it.
<2.1> 7/19/89 CCH Changes:
- Added "-nd" option to supress inclusion of date in
ROM.
<2.2> 7/19/89 CCH Changes:
- Removed "-nd" option in favor of new "-fd" option to
force a date into the ROM.
<2.0> 7/6/89 CCH Changes:
- Added "-a" option to set alignment of resources. -
Fixed bug in AlignBelow macro.
<1.8> 6/30/89 CCH Changes:
- Modified to put ROM rsrc's at the end of ROM.
- Added a new reference entry field that gives an offset
to the rsrc data for that entry.
<1.9> 6/30/89 CCH Changes:
- Fixed bug in "DeclData loaded at" output.
- Spiffed up output file.
<1.7> 6/22/89 CCH Changes:
- Redesigned how ROM resources are stored to accomodate
multiple-resources of the same type, ID, and name in the ROM.
Hiram reads a resource-list file to determine what resources are
loaded. This file also contains information about which
resources should be made available to the O/S at any one time,
and the filenames they are contained in.
- Removed unmount and eject code
<1.6> 5/12/89 CCH Added encryption for RAM-based images, and sped up checksumming
loop.
<1.5> 4/11/89 CCH Zeros out individual cksums before cksumming, and excludes first
4 bytes from all checksumming. Added check for null initials
handle (so it doesn't crash).
<1.4> 3/17/89 CCH Now stuffs ROMSize at RomBase+0x40. Added new "-o" option to
generate slice file output. "-n" is now required unless ROM is
one slice. Added Copyright notice along with initials at end of
ROM.
<1.3> 2/8/89 CCH Stop generating ROM slice files unless specifically asked for
with the "-n" option.
<1.2> 1/25/89 CCH Extensive modification to always compute slice checksums, and to
halve the runtime memory requirements. Also added '-32' option
to support 32-bit clean ROMs.
<1.1> 12/15/88 CCH Changed "\r"'s to "\n"'s...
<1.0> 11/14/88 CCH Adding to EASE. Fixed up error msgs to be more informative.
1/8/88 rwh added support for multiple ROM overpatch files. Also made GWN's
change to read in declaration data a command line option (-d).
2/16/87 bbm changed output of rom totals to display in hex.
2/4/87 bbm made resources and map long word go on long word boundries.
11/11/86 JTC Force 0 pad byte for odd-sized resources.
<A250> 10/10/86 JTC Clean up ROM rsrc map to have zero in fields of no <10Oct86>
relevance, such as 16-byte duplicate of file header (various
offsets and the like), the 4-byte handle to next map, and the
pad byte for odd-sized maps.
8/28/86 JTC Write new file ROMCat, the concatenation of the N files produced
by -s and -b options. <28Aug86>
8/6/86 JTC A little help for our friends in hardware: a option -b (for
Brian(s)) is added to permit high and low options, each to be
split into SLICES number of slices. How nice! The -b option will
take no integer parameter. <06Aug86> Have high bytes take up
ZeroImage, OneImage, etc. and have low bytes take NImage,
(N+1)Image, etc.
6/2/86 JTC Major rework for MPW, continuing 19Mar86 changes. Add
<argc,argv> support (see comment below), watch for flushing of
feedback in output window, and remove the old ROM: disk stuff,
building the output files in the default directory. Some bugs in
new use of FSxxx file system calls since some arguments must be
passed by address. Oh, Pascal!
3/19/86 JTC Moved from Consulair world, and correctly integrated Milwaukee
changes. Among major changes: (1) use high-level file system
calls; (2) parameterize ROM length and number of slices of ROM;
(3) render time/date stuff in C.
1/27/86 JTC A few quick file changes for Milwaukee.
1/16/86 bbm added support for 8 byte master pointer.
10/6/85 JTC Heavens, fixed for real this time!
10/4/85 JTC Fix loop end for checksum.
8/26/85 JTC Fix eject to use volume name. Change RSRC layout to remove bogus
MP block from ROM, placing offsets to the RSRC data in the map
(file offset slot) itself.
7/22/85 JTC Fix bug in sizing ROM -- 8-byte header not added in! Also, allow
at least one byte of date at end of ROM.
7/15/85 JTC Leave ROM:ROMImageL on disk!
7/1/85 JTC Added adjustable ROMSTART constant for non-Mac builds.
5/20/85 JTC Make map refNum = 2.
5/15/85 JTC Stuff ROM date into last bytes of ROM, with TRAILING length.
5/14/85 JTC Finally got the COLON right in UnmountVol! The 'last' set of
changes collects data into a summary file HiROMErr.TXT.
5/13/85 JTC Eject and unmount after write.
5/11/85 JTC BUG in checksum: accumulated words into long sum were
sign-extended, a No-No.
4/11/85 JTC Add conditional compilation to write either ROMImageH &
ROMImageL or ROMImageEven & ROMImageODD
4/11/85 JTC Modify to use Consulair OSIO.h definitions.
3/18/85 JTC Modify HeapMagic constant for 4 master pointers in ROM zone,
rather than DefaultMasters, as it was.
2/18/85 JTC Revise block IO to use Mac routines directly, incorporating
experimental structure definitions from jtCIODefs.h
2/12/85 JTC Revise resources to put fake memory manager header in front of
each resource. Mark it Relocatable+Nonrelocatable, with logical
= phys size, and mp offset as though master pointers will be
allocated first in system heap after first master pointer block.
2/9/85 JTC Changed name of output file to ROMImageH. Look for file
ROMImageL, and if found, concatenate the two to ROMMondo; else
write one word of 0's to ROMMondo. Sleazy bum -- forcing volume
name to be ROM:
2/1/85 JTC Changed format of output image to begin with word map and mp
block size. Set res attribute bits to 0x58: No sys ref / Sys
heap / Not Purgeable / Locked / Protected / Not pre-loaded / Not
changed / reserved Also, mark master pointers as locked.
1/22/85 JTC Changed name of input file.
*/
/**************************************************************************
** MPW3.2 build commands
** C Hiram.c
** Link -c "MPS " -t "MPST" -o Hiram Hiram.c.o ∂
** {Libraries}RunTime.o ∂
** {CLibraries}StdCLib.o ∂
** {Libraries}Interface.o ∂
** {Libraries}ToolLibs.o
**************************************************************************/
/**************************************************************************
**
** Hiram.c -- program to build ROM images, complete with RSRCs and checksum.
** Written by J. T. Coonen 18 Dec 84.
**
** MPW command line usage:
** Hiram -s 256 -o -32 -n 2 -a 16 -i RDCBBM,etc -fd <date> -b -d -p <PatchFileName PatchOffset>
** where:
** -32 tells hiram to make the heap a 32-bit clean heap <1.2>
** -a V tells Hiram to align resources to V bytes. <2.0>
** -b says to split the ROM into high and low clusters of slices.
** -d says to load declaration data at the end of the ROM from the <08Jan88>
** named DeclDataL <08Jan88>
** -fd S Forces S to be used as the date string for the ROM <2.2>
** -i AAAAA gives the initials string which the ROM image is initialized to.
** To allow the use of spaces in the initials string, all underscores will
** be changed to spaces.
** -n K gives the number of slices to split the image into
** -o generates output files for each slice <1.4>
** -p <PatchFileName PatchOffset> gives the filenames and offsets from <08Jan88>
** start of ROM for up to (MaxPatches) ROM overpatches. The <>'s <08Jan88>
** should not be used - they just signify that several name-offset <08Jan88>
** pairs may be given. <08Jan88>
** -pd pascal date. Precedes the date with a length byte <2.3>
** -s NNN gives the size in multiples of 1024
** -t tells hiram to make Terror Rom.
**
**
**
** Input -- ROMResources.RSRC and ROMImageL, and potentially DeclDataL and <08Jan88>
** some files with ROM overpatches. <08Jan88>
**
** Output -- ROMImageL, ROMMondo, HiramLog and one of: <02Jun86>
** <no more files> or
** ROMImage0 and ROMImage1 or
** ROMImage0, ROMImage1, ROMImage2 and ROMImage3 or
** Low Half: ROMImageH0 & ROMImageL0, High: ROMImageH1 & ROMImageL1
**
** The format of ROMMondo is:
** 0x000000 (long) checksum of entire ROM
** 0x000004 ROM code
** 0x00001A (long) ResOff = offset to ROM resource structure table <1.7>
** 0x00001E - 0x00002F ROM code
** 0x000030 - 0x00003F checksums for slices (zero for unused slices)
** 0x000040 ROM size <1.4>
** 0x000044 - ResOff ROM code
**
** ResOff ROM Resource Structure Table:
** long offsetToFirst; offset from base Of Rom to first rsrc Reference Entry in linked list
** char maxValidIndex; maximum value for PRAM combo index
** char comboFieldSize; size in bytes of combo field
** short comboVersion; version of combo field
** short headerSize; length of memory headers
**
** RefEntry ROM Resource Reference Entry:
** long offsetToNext; offset from base Of Rom to next ref entry in linked list
** long offsetToData; offset from base Of Rom to rsrc data for this entry
** long rsrcType; resource type
** short rsrcID; resource ID
** char rsrcAttr; resource attributes
** char nameLen; length of resource name
** char rsrcName[]; resource name followed by longword aligned resource data
**
** The resource structure has the following amusing properties:
**
** You can have resources with the same type and ID as long as they are not
** members of the same resource combination.
**
** The resource attributes byte has the value 0x58, corresponding to:
** No sys ref / Sys heap / Not Purgeable / Locked /
** Protected / Not pre-loaded / Not changed / reserved
**
** Each resource is placed as a true MM block, complete with header.
** The tags say Reloc/Nonreloc (unused to date), the size fudge factor
** is 0, the physical size field is honest, and the relative handle
** depends on the following system heap configuration:
**
** System Heap layout after ROM resources "loaded". Note that the absolute
** address of the start of System Heap is irrelevant! In 32 bit mode, memory block-headers
** are 12 bytes instead of 8, hence the following wierdness:
** 0x0000 Zone header, pointed to by (SysZone); size = HeapData = 0x34
** 0x0034 master ptr block; size = BlkData + 8*CMoreMasters = 0x18 0x1C < 1/25/89 >
** where CMoreMasters = 2, for now... Master pointers are 8 bytes to
** be compatible with a/ux. Initresources uses these relative handles
** to figure out where to put the master pointers in the System heap at
** boot time.
** 0x004C (24) header of bogus master pointer block; size = BlkData = 0x8
** 0x0050 (32) header of bogus master pointer block; size = BlkData = 0x0C < 1/25/89 >
** 0x0054 (24) first bogus master pointer...
** 0x005C (32) first bogus mp...add 8 byte of blkdata (12 byte block header) < 1/25/89 >
**
*************************************************************************/
#define k64KBytes 0x10000
#define CIDeclDataPtr 0x7ec1a
#define Align4(A) ((ulong)(A+3)&0xFFFFFFFC)
#define Align(A,Size) ((ulong)(A+(Size-1))&(~(Size-1)))
#define AlignBelow(A,Size) (((ulong)(A+(Size-1))&(~(Size-1)))-(((ulong)(A))&(Size-1)?Size:0))
#define BitSet(byte,bit) (byte |= (1<<bit))
#define BLOCKSIZE 0x200000 /* Size of file block transfers. */
#define HeapMagic24 0x0054 /* 24-bit mode - Offset from heap start to first bogus mp */
#define HeapMagic32 0x005c /* 32-bit mode - Offset from heap start to first bogus mp */
#define Chekov 0x0000 /* Offset to checksum in ROM */
#define Mapov 0x001A /* Offset to rsrc part of ROM */
#define Byteov 0x0030 /* Offset to 4 long checksums */ /* <10Oct86> */
#define RomSizeOv 0x0040 /* Offset to size of ROM */
#define MaxPatches 16 /* At most 16 separate ROM overpatches */ /* 08Jan88 */
#define IntrLvAppend 1 /* interleavedWrite appendFlag values */
#define IntrLvCreate 0
#define RSRCLISTTYPE 'hirm' /* resource type for resource-list resource <1.7> */
#define RSRCLISTID 0 /* resource ID for resource-list resource <1.7> */
#define VERSION "4.1"
#include <Types.h>
#include <Errors.h>
#include <Events.h>
#include <Files.h>
#include <Memory.h>
#include <OSUtils.h>
#include <Packages.h>
#include <Quickdraw.h>
#include <Resources.h>
#include <Stdio.h>
#include <CursorCtl.h>
#include <String.h>
#include <Strings.h>
#include <StdLib.h>
#include <TextUtils.h>
/*************************************************************************
** Type definitions
*************************************************************************/
typedef unsigned long ulong;
typedef unsigned short ushort;
typedef unsigned char uchar;
typedef struct StructTable { /* <1.7> */
long offsetToFirst; /* offset from base Of Rom to first rsrc Ref Entry */
char maxValidIndex; /* maximum value for PRAM combo index */
char comboFieldSize; /* size in bytes of combo field */
short comboVersion; /* version of combo field */
short headerSize; /* length of memory headers */
} StructTable, *StructTablePtr;
typedef struct RefEntry { /* <1.8> */
long offsetToNext; /* offset from base Of Rom to next ref entry */
long offsetToData; /* offset from base Of Rom to rsrc data for this entry */
long rsrcType; /* resource type */
short rsrcID; /* resource ID */
char rsrcAttr; /* resource attributes */
char nameLen; /* length of resource name */
char rsrcName[]; /* resource name */
} RefEntry, *RefEntryPtr;
/*************************************************************************
** Forward Referenced Routines
*************************************************************************/
extern void stuffResData();
extern void parseArgs();
extern char * PasName();
extern char * CName();
/*************************************************************************
** Prototypes
*************************************************************************/
void parseArgs(int argc, char *argv[]);
void initTheWorld(void);
void openErrs(void);
void readROMCode(void);
void setupRsrcInput(void);
void buildRsrcImage(void);
void makeComboField(Ptr *listPtr, short comboFieldSize, char *comboField, char *maxIndex);
void readDeclData(void);
void readOverPatches(void);
void writeROMOutputs(void);
void closeErrs(void);
void computeCheckSums(void);
void getDate(char *date);
void fastRead(char *fName, char *fBuffer, int *pSize);
void fastWrite(char *fName, char *fBuffer, int fSize);
void interleavedWrite(char *fName, char *fBuffer, int slices, int whichSlice, int appendFlag);
void MySignal(char *msg, int retCode);
char * PasName(char *cName);
char * CName(char *str);
void tabTo(char *str, int pos);
/*************************************************************************
** Global data.
*************************************************************************/
uchar *ROMImage; /* pointer to ROM array */
FILE *ErrFile; /* output error file */
char *ErrFName; /* output error file name */
uchar *HRmap, *HRdata; /* handy ROMImage pointers <26Aug85> */
int CodeSize,evCodeSize; /* size of code from ROMImageL <04feb87>*/
int DeclDataSize; /* size of DeclData */
int ROMSize; /* size of code plus resources */
long ROMLEN; /* Milw (today), Mac+:128K 02Jun86 */
int ROMSLICES; /* Milw:4, Mac+:2, ... 02Jun86 */
int ROMBRIAN; /* Milw:1, Aladdin:2 06Aug86 */
int REALSLICES; /* ROMSLICES*REALSLICES 06Aug86 */
Handle InitialsH; /* 02Jun86 */
Boolean TerrorROM; /* Are we building a Terror Rom <2> HJR 8/23/90 */
Boolean DeclData; /* true if declaration data needed 08Jan88
at the end of the ROM 08Jan88 */
ulong DeclDataPtr; /* points to where decldata starts in image <1.8> */
int NumPatches; /* number of ROM overpatch files 08Jan88 */
char *PatchFileNames[MaxPatches];/* pointers to patch file names 08Jan88 */
long PatchOffsets[MaxPatches]; /* offset to patch location in ROM 08Jan88 */
char pName[256]; /* buffer for converting C filenames to Pascal strings */
int headerLen; /* length of heap headers (32 vs. 24 bit mode) */
char outputSlices; /* should we output slice files? <1.3> */
char RAMVersion; /* true if we should make an encrypted version */
Handle rsrcListHdl; /* handle to resource-list resource <1.7> */
short rsrcListRefnum; /* refnum for resource-list file <1.7> */
short NumROMBanks; /* Number of ROM banks that we are using. <2> HJR 8/23/90 */
Handle TopBankrsrcListHdl; /* handle to top bank of resource-list resource <2> HJR 8/23/90 */
short TopBankrsrcListRefnum; /* refnum for top bank of resource-list file <2> HJR 8/23/90 */
ulong gAlignment; /* byte alignment factor <1.8> */
char DateStr[64]; /* forced date string <2.2> */
char pascalDate; /* true to precede the date with a length byte <2.3> */
/*************************************************************************
** Entry point for Hiram. Coordinates build of image.
*************************************************************************/
main(argc,argv)
int argc;
char *argv[];
{
SpinCursor(32);
printf("\t\◊ Beginning Hiram v%s…\n", VERSION);
fflush(stdout);
parseArgs(argc, argv); /* 02Jun86 */
initTheWorld();
openErrs();
readROMCode(); /* Allocate memory, initialize with initials, read the code */
if (DeclData) /* 08Jan88 <1.8> */
readDeclData(); /* 08Jan88 <1.8> */
else /* <1.8> */
DeclDataPtr = (ulong)(ROMImage + ROMLEN); /* if no DeclData, point to end <1.8> */
readOverPatches(); /* 08Jan88 <1.8> */
setupRsrcInput(); /* open rsrc list file */
buildRsrcImage(); /* read the rsrc's into image */
/*
** Compute byte-wide checksums for each of the slices into special
** locations. Then compute the checksum, a 32-bit sum of unsigned
** 16-bit quantities.
*/
computeCheckSums(); /* <10Oct86> */
writeROMOutputs();
closeErrs();
printf("\t\◊ Hiram complete.\n");
return(0);
}
/*************************************************************************
** Set up default values of ROMLEN, ROMSLICES, ROMBRIAN, InitialsH and
** NumPatches. Then go looking for command line args.
*************************************************************************/
void parseArgs(argc, argv) /* 02Jun86 */
int argc;
char *argv[];
{
char *s;
/* Try a 128K rom, one image only, contiguous, with no initials,
no declaration data and no overpatches */
ROMLEN = 128;
ROMSLICES = 1;
ROMBRIAN = 1; /* 06Aug86 */
InitialsH = 0;
DeclData = false; /* 08Jan88 */
NumPatches = 0; /* 08Jan88 */
headerLen = 8; /* <1.2> CCH 1/25/89 */
outputSlices = false; /* <1.3> CCH 2/8/89 */
RAMVersion = false; /* <1.6> CCH 5/11/89 */
gAlignment = 4; /* <1.8> CCH 6/29/89 */
DateStr[0] = '\0'; /* <2.3> CCH 7/19/89 */
pascalDate = false; /* <2.3> CCH 7/20/89 */
TerrorROM = false; /* <2> HJR 8/23/90 */
NumROMBanks = 1; /* <2> HJR 8/23/90 */
while ((--argc > 0) && ((*++argv)[0] == '-'))
{
switch ((*argv)[1]) {
case '3': /* <1.2> CCH 1/25/89 */
if ((*argv)[2] == '2') /* looking for "-32" <2.1> CCH 7/19/89 */
headerLen = 12;
break;
case 'a': /* <2.0> CCH 7/6/89 */
if (sscanf(*++argv, "%ld", &gAlignment) != 1)
MySignal("Bad alignment argument.", 0);
if (gAlignment & 1)
MySignal("Alignment must be even.", 0);
--argc;
break;
case 'b': /* 06Aug86 */
ROMBRIAN = 2; /* split to high and low halves 06Aug86 */
break; /* 06Aug86 */
case 'd':
DeclData = true;
break;
case 'f':
if ((*argv)[2] == 'd') { /* looking for "-fd" <2.2> CCH 7/19/89 */
strcpy(DateStr,*++argv);
--argc;
}
break;
case 'i':
--argc;
InitialsH = NewHandle(strlen(*++argv) + 5);
strcpy(*InitialsH, "<<");
strcat(*InitialsH, *argv);
strcat(*InitialsH, ">>");
for ((s = *InitialsH); *s != '\0'; s++)
if (*s == '_')
*s = ' ';
break;
case 'n':
if (sscanf(*++argv, "%ld", &ROMSLICES) != 1)
MySignal("Bad pieces argument.", 0);
if ((ROMSLICES != 1) && (ROMSLICES != 2) && (ROMSLICES != 4))
MySignal("Must be 1, 2 or 4 pieces.", 0);
--argc;
break;
case 'o':
outputSlices = true;
break;
case 'p':
if ((*argv)[2] == 'd') /* looking for "-pd" <2.3> CCH 7/20/89 */
pascalDate = true;
else { /* by here, "-p" */
while ((--argc > 0) && ((*++argv)[0] != '-')) {
PatchFileNames[NumPatches] = *argv;
if (!(--argc))
MySignal("No offset given for overpatch file", 0);
if (sscanf(*++argv, "%lx", &PatchOffsets[NumPatches]) != 1)
MySignal("Bad overpatch offset.", 0);
if (++NumPatches == MaxPatches)
MySignal("Too many ROM overpatches", 0);
}
if (argc++)
argv--;
}
break;
case 'r': /* <1.6> CCH 5/11/89 */
RAMVersion = true;
break;
case 's':
if (sscanf(*++argv, "%ld", &ROMLEN) != 1)
MySignal("Bad size argument.", 0);
--argc;
break;
case 't':
TerrorROM = true;
NumROMBanks = 2;
break;
default:
MySignal("bad option: Usage: Hiram -s SIZE [-o] [-a align] -n COUNT -i INITIALS", 0);
}
}
if (argc)
MySignal("more args: Usage: Hiram -s SIZE -n COUNT -b -i INITIALS", 0); /* 06Aug86 */
if (!InitialsH)
MySignal("whoops: You forgot your initials!", 0);
/* To finish up, scale the length by 1024 and deduce real number of pieces. */
ROMLEN *= 1024;
REALSLICES = ROMSLICES * ROMBRIAN; /* 06Aug86 */
if ((ROMBRIAN == 2) && (ROMSLICES == 4)) /* 06Aug86 */
MySignal("Only -n 1 or 2 allowed with -b!", 0); /* 06Aug86 */
if (headerLen == 8)
printf("\t\t24-bit Mode.\n");
else
printf("\t\t32-bit Mode.\n");
fflush(stdout);
HLock(InitialsH);
printf("\t\tSize is %d bytes in %d slices; initials are: %s.\n", ROMLEN, ROMSLICES, *InitialsH);
HUnlock(InitialsH);
fflush(stdout);
}
/*************************************************************************
** InitGraf and InitWindows are automatically called by MacC start code;
** the QuickDraw globals are kept in the pre-assigned global, QD.
** Here we just initialize the rest of the Mac system, and whatever of
** our own variables need it.
*************************************************************************/
void initTheWorld()
{
InitGraf(&qd.thePort);
InitCursor();
}
/*************************************************************************
*************************************************************************/
void openErrs()
{
ErrFName = "HiramLog";
if ( (ErrFile = fopen(ErrFName, "w")) == NULL )
printf("\t\• Couldn't open %s ... off to the screen!\n\n", ErrFName);
fprintf(ErrFile, "Beginning Hiram Log:\n");
fflush(stdout);
}
/*************************************************************************
** Allocate ROMImages: always get a buffer the size of the final ROM;
** then assume there are 0, 2, or 4 ROM slices, and allocate buffers
** accordingly. Initialize ROM buffer with -- what else -- initials!
** Finally, load the pure code input and stuff away its size (i.e. the
** offset to the RSRC part of the ROM) at location MapOv.
*************************************************************************/
void readROMCode()
{
char *codePtr, *namePtr, ROMDate[64];
char *copyRight = "[(c) Copyright Apple Computer, Inc. 1989-1992]";
long i;
/** allocate space for image and align it **/ /* <2.0> */
if ( ! (ROMImage = NewPtr(ROMLEN+gAlignment)) ) /* <2.0> */
MySignal("Couldn't allocate memory for ROMImage!", 0);
ROMImage = (Ptr) Align(ROMImage,gAlignment); /* <2.0> */
/** fill space with initials and copyrights **/ /* <1.4> */
i = GetHandleSize(InitialsH);
if (DateStr[0]) { /* do we want to force a date? <2.2> */
strcpy(ROMDate,"[");
if (pascalDate) {
c2pstr(DateStr);
strncat(ROMDate,DateStr,DateStr[0]+1);
} else
strcat(ROMDate,DateStr);
strcat(ROMDate,"]");
} else
getDate(ROMDate); /* get the date string */
SetHandleSize(InitialsH, i+strlen(copyRight)+strlen(ROMDate)+1); /* get extra space for strings */
HLock(InitialsH);
strcat(*InitialsH, copyRight);
strcat(*InitialsH, ROMDate);
codePtr = ROMImage;
namePtr = *InitialsH; /* 02Jun86 */
for (i=0; i< ROMLEN; i++)
{
*codePtr++ = *namePtr++;
if (*namePtr == 0)
namePtr = *InitialsH; /* 02Jun86 */
}
DisposHandle( InitialsH );
/* Read existing ROMImageL into first CodeSize bytes of ROMImage. */
fastRead("ROMImageL", ROMImage, &CodeSize); /* 02Jun86 */
evCodeSize = Align4(CodeSize); /* 04feb87 */
if (CodeSize != evCodeSize) /* 04feb87 */
*( (short *) (ROMImage + CodeSize) ) = 0; /* 04feb87 */
/* fprintf(ErrFile, "Read from ROMImageL:\t$%lx bytes\n", CodeSize); */
/* Stuff size of ROM into another secret longword */
*( (long *) (ROMImage + RomSizeOv) ) = ROMLEN;
}
/*************************************************************************
** Open the resource-list resource file, load the resource-list resource.
** 6/13/89 <1.7> Rewrote for multiple-resources
** 8/23/90 <2> Added ability for multiple banks of ROM rsrc.
*************************************************************************/
void setupRsrcInput()
{
char *inputFileName;
/*** Now open the file containing the description of which resources to **
*** load, and which combinations they should be included in */
inputFileName = "ROM.rsrc";
printf("\t\tOpening resource-list file “%s”\n",inputFileName);
fflush(stdout);
rsrcListRefnum = OpenResFile( PasName(inputFileName));
if ( rsrcListRefnum <= 0 )
MySignal("Couldn't open resource-list file", ResError());
rsrcListHdl = Get1Resource(RSRCLISTTYPE, RSRCLISTID);
if (!rsrcListHdl)
MySignal("Couldn't get resource-list resource!", ResError());
if(TerrorROM) { /* <2> HJR 8/23/90 */
inputFileName = "TopBankROM.rsrc";
printf("\t\tOpening resource-list file “%s”\n",inputFileName);
fflush(stdout);
TopBankrsrcListRefnum = OpenResFile( PasName(inputFileName));
if ( TopBankrsrcListRefnum <= 0 )
MySignal("Couldn't open resource-list file", ResError());
TopBankrsrcListHdl = Get1Resource(RSRCLISTTYPE, RSRCLISTID);
if (!TopBankrsrcListHdl)
MySignal("Couldn't get resource-list resource!", ResError());
}
} /*setupRsrcInput*/
/*************************************************************************
** Steps for building ROM resource images:
** - read combo version and field size
** - FOR each entry in the resource-list resource:
** - set up a reference entry for each resource
** - set up a fake block-header for each one
** - read data in after block-header
** 6/13/89 <1.7> Rewrote to accomodate combinatorial resources in ROM
** 6/30/89 <1.8> Modified to put ROM rsrc's at the end of ROM, and to
** use a new reference entry field that gives an offset
** to the rsrc data for that entry.
** 8/23/90 <2> Added ability for multiple banks of ROM rsrc,
** specifically for Terror.
*************************************************************************/
void buildRsrcImage()
{
char maxIndex, *filename, rsrcStr[5], comboField[32], logStr[256], tempStr[256];
short comboFieldSize, rsrcID, refnum, ROMBanks;
int i, j, k, rsrcCount;
long entryCount, IDCount, bogusOff, rsrcSize;
Handle rsrcHdl;
Ptr listPtr, imagePtr, imageSave, rsrcDataPtr, lastPtr;
OSType rsrcType;
StructTablePtr structTable;
long longRsrcID;
long tempLong;
/*** Read the beginning of the resource-list data, and set up the structure table ***/
/*** just below DeclData, aligned to Alignment variable. ***/
if(TerrorROM) /* <2> HJR 8/23/90 */
structTable = (StructTablePtr) AlignBelow(ROMImage + CIDeclDataPtr - sizeof(StructTable),gAlignment);
else
structTable = (StructTablePtr) AlignBelow(DeclDataPtr - sizeof(StructTable),gAlignment);
*( (ulong *) (ROMImage + Mapov) ) = (Ptr)structTable - ROMImage; /* Stuff offset to rsrc stuff */
imagePtr = (Ptr) structTable; /* point to just before struct table */
listPtr = *rsrcListHdl; /* ptr to rsrc-list data */
structTable->comboVersion = *(short*) listPtr; /* save combo version */
listPtr += 2;
structTable->comboFieldSize = *(short*)listPtr; /* save field size */
listPtr += 2;
structTable->headerSize = headerLen; /* save header size */
comboFieldSize = structTable->comboFieldSize; /* make an extra copy */
/*** Prepare to traverse each entry ***/
rsrcCount = 0; /* number of resources loaded */
maxIndex = 0; /* max index begins at zero */
bogusOff = 0; /* use first master pointer */
lastPtr = (Ptr) structTable; /* where to put offset to next block */
entryCount = *(long*)listPtr; /* number of entries in resource-list */
listPtr += 4; /* bump ptr past entryCount longword */
fprintf(ErrFile,"\nResource information:\n\n");
fprintf(ErrFile,"Rsrc/ID\t\t\t\tOffset\t\tSize\t\tFile\n");
fprintf(ErrFile,"-------\t\t\t\t------\t\t----\t\t----\n");
/*** Here we have the ability for multiple ROM Resource banks. One just has to set the imagePtr ***/
/*** to the beginning of the resource list and have the resource list in the same format. <2> HJR 8/23/90 ***/
for (ROMBanks=0; ROMBanks<NumROMBanks; ROMBanks++) {
if (ROMBanks == 1) {
imagePtr = (Ptr) AlignBelow(ROMImage + ROMLEN - k64KBytes,gAlignment); /* Give DeclData a 64k of space */
listPtr = *TopBankrsrcListHdl + 4; /* ptr to rsrc-list data */
entryCount = *(long*)listPtr; /* number of entries in resource-list */
listPtr += 4; /* bump ptr past entryCount longword */
fprintf(ErrFile,"\nResource information for TopBankROM.rsrc:\n\n");
fprintf(ErrFile,"Rsrc/ID\t\t\t\tOffset\t\tSize\t\tFile\n");
fprintf(ErrFile,"-------\t\t\t\t------\t\t----\t\t----\n");
}
for (i=0; i<entryCount; i++) {
/*** Get the vital information from this entry, and try to open the target file ***/
makeComboField(&listPtr, comboFieldSize, comboField, &maxIndex); /* read combos into field */
filename = (char*) listPtr; /* set filename */
listPtr += *(char*)listPtr + 1; /* skip past name and length byte */
listPtr = (Ptr)Align4(listPtr); /* align to a longword */
rsrcType = *(OSType*)listPtr; /* get resource type for this entry */
listPtr += 4; /* bump ptr past entryCount longword */
IDCount = *(long*)listPtr; /* get number of IDs in this entry */
listPtr += 4; /* bump ptr past entryCount longword */
refnum = OpenResFile(filename); /* open the resource file */
if (refnum < 0) {
printf("\t\• couldn't open resource file “%s”\n",CName(filename));
fflush(stdout);
listPtr += IDCount * 2; /* bump pointer past ID list */
continue; /* go to next entry */
}
*(long*)rsrcStr = rsrcType; /* make rsrc type into a string */
rsrcStr[4] = '\0'; /* a null-terminated string, that is */
/*** we've got the file open now, get the resources listed in the ID list, and ***/
/*** store them in the image with a reference entry and a fake memory block-header ***/
for (j=0; j<IDCount; j++) {
rsrcID = *(short*)listPtr; /* get an ID from the list */
listPtr += 2; /* bump ptr past entryCount longword */
rsrcHdl = Get1Resource(rsrcType, rsrcID); /* load the resource into memory */
if (!rsrcHdl) {
fprintf(ErrFile,"# couldn't find resource ('%s',ID=%hd) in “%s”\n",rsrcStr,rsrcID,CName(filename));
printf("\t\• couldn't find resource ('%s',ID=%hd) in “%s”\n",rsrcStr,rsrcID,CName(filename));
fflush(stdout);
continue;
}
/*** allocate space for rsrc data and move it in ***/
rsrcSize = GetHandleSize(rsrcHdl); /* get size of resource */
GetResInfo(rsrcHdl, &rsrcID, &rsrcType, tempStr); /* read resource information */
imagePtr = (Ptr)AlignBelow(imagePtr - rsrcSize, gAlignment); /* allocate space for rsrc in image */
BlockMove(*rsrcHdl, imagePtr, rsrcSize);
rsrcDataPtr = imagePtr; /* save a ptr to the data */
/*** create a fake block-header ***/
imagePtr -= headerLen; /* point to beginning of block-header */
if (headerLen == 12) { /* if we're in 32-bit mode */
*(ulong*)imagePtr = 0xc0a00000; /* relocatable AND nonrelocatable */
imagePtr += 4; /* bump up ptr */
*(ulong*)imagePtr = Align(rsrcSize + 12,gAlignment); /* size of block & resource */
imagePtr += 4; /* bump pointer past block to data */
*(ulong*)imagePtr = HeapMagic32 + bogusOff; /* point to a fake master pointer in sysheap */
} else {
*(ulong*)imagePtr = Align(rsrcSize + 8,gAlignment); /* size of block & resource */
*imagePtr = 0xc0; /* relocatable AND nonrelocatable */
imagePtr += 4; /* bump pointer past block to data */
*(ulong*)imagePtr = HeapMagic24 + bogusOff; /* point to a fake master pointer in sysheap */
}
bogusOff += 8; /* use next master pointer */
imagePtr += 4; /* bump ptr past relative handle */
/*** create a reference table entry ***/
imagePtr = (Ptr)AlignBelow(imagePtr-headerLen-tempStr[0]-sizeof(RefEntry)-comboFieldSize,gAlignment);
imageSave = imagePtr; /* save this location */
*(ulong*)lastPtr = imagePtr - ROMImage; /* link entry to this one */
for (k=0; k<comboFieldSize; k++) /* put combo field first */
*imagePtr++ = comboField[k];
lastPtr = imagePtr; /* where to put offset to next block */
imagePtr += 4; /* skip over offset */
*(ulong*)imagePtr = rsrcDataPtr - ROMImage; /* stuff ptr to rsrc block-header */
imagePtr += 4;
*(OSType*)imagePtr = rsrcType; /* save resource type */
imagePtr += 4; /* skip over type */
*(ushort*)imagePtr = rsrcID; /* save resource ID */
imagePtr += 2; /* skip over ID */
*(uchar*)imagePtr = 0x58; /* tweak resource attributes to 0x58 */
imagePtr += 1; /* skip over attributes */
strncpy(imagePtr,tempStr,tempStr[0]+1); /* write resource name */
imagePtr = imageSave; /* restore imagePtr to beginning of entry */
rsrcCount++;
/*** Output useful information to log file ***/
/* needed because MPW3.2 StdCLib doesn't handle printing negative shorts with %hd correctly */
longRsrcID = (long) rsrcID; /* convert to a signed long BEFORE calling sprintf() */
sprintf(logStr,"('%s',ID=%d)",rsrcStr,longRsrcID);
tabTo(logStr, 20);
sprintf(tempStr,"$%lx", imagePtr - ROMImage);
strcat(logStr,tempStr);
tabTo(logStr, 32);
sprintf(tempStr,"%ld", rsrcSize);
strcat(logStr,tempStr);
tabTo(logStr, 44);
sprintf(tempStr,"“%s”", CName(filename));
strcat(logStr,tempStr);
fprintf(ErrFile,"%s\n", logStr);
} /*for*/
CloseResFile(refnum); /* close the resource file for this entry */
} /*for*/
} /*for*/
fprintf(ErrFile,"\nResource Count = %d\n",rsrcCount);
fprintf(ErrFile,"Resources Start at:\t$%lx\n\n",imageSave-ROMImage);
CloseResFile(rsrcListRefnum);
if(TerrorROM) /* <2> HJR 8/23/90 */
CloseResFile(TopBankrsrcListRefnum);
structTable->maxValidIndex = maxIndex; /* save max index value */
*(ulong*)lastPtr = 0; /* end of linked list */
fprintf(ErrFile,"ROM Statistics\n");
fprintf(ErrFile,"--------------\n\n");
fprintf(ErrFile,"Code:\t\t\t$%lx bytes\t\t%-5ldK\n",evCodeSize, evCodeSize / 1024L);
tempLong = (long) DeclDataPtr-imageSave;
fprintf(ErrFile,"Resources:\t\t$%lx bytes\t\t%-5ldK\n",tempLong, tempLong / 1024L);
tempLong = (long) ROMImage+ROMLEN-DeclDataPtr;
fprintf(ErrFile,"DeclData:\t\t$%lx bytes\t\t%-5ldK\n",tempLong, tempLong / 1024L);
tempLong = (long) imageSave-evCodeSize-ROMImage;
fprintf(ErrFile,"Free:\t\t\t$%lx bytes\t\t%-5ldK\n",tempLong, tempLong / 1024L);
fprintf(ErrFile,"------------------------------------------\n");
fprintf(ErrFile,"Total Size:\t\t$%lx bytes\n\n",ROMLEN);
} /*buildRsrcImage*/
/*************************************************************************
** Make a combination field.
** - start reading combination list at listPtr
** - set bits in comboField, which is comboFieldSize bytes long
** - on return listPtr should point to byte following combo list
*************************************************************************/
void makeComboField(listPtr, comboFieldSize, comboField, maxIndex)
Ptr *listPtr;
short comboFieldSize;
char *comboField;
char *maxIndex;
{
char combo;
int i, byte, bit;
long comboCount;
Ptr myPtr;
myPtr = *listPtr; /* get a local copy */
comboCount = *(long*)myPtr; /* get count of combos in list */
myPtr += 4;
for (i=0; i<comboFieldSize; i++)
comboField[i] = 0; /* clear the field first */
for (i=0; i<comboCount; i++) {
combo = *myPtr++; /* get a comination from the list */
if (combo > (comboFieldSize*8))
continue;
if (combo > *maxIndex) /* did we hit a maximum? */
*maxIndex = combo;
byte = combo / 8; /* byte in combo field */
bit = combo % 8; /* bit in combo field */
BitSet(comboField[byte], 7-bit); /* set bit in field */
} /*for*/
*listPtr = myPtr; /* return new position */
} /*makeComboField*/
/************************************************************************* <X000 GWN 08-11-87>
** Load the declaration data file. <X000 GWN 08-11-87>
*************************************************************************/
void readDeclData() /* <X000 GWN 08-11-87> */
{
char *codePtr;
short refNum, retCode;
long SizeDeclData;
retCode = FSOpen(PasName("DeclDataL"), 0, &refNum); /* Open the DeclData file */
if (retCode) /* Error? */
MySignal("Couldn't open DeclDataL",retCode); /* Show error */
retCode = GetEOF(refNum,&SizeDeclData); /* Get the size of the file */
if (retCode) /* Error? */
MySignal("Failed GetEOF on DeclDataL.",retCode);/* Show error */
retCode = FSClose(refNum); /* Close it */
codePtr = ROMImage + ROMLEN - SizeDeclData; /* Ptr to where decl data is to begin */
DeclDataPtr = codePtr; /* save ptr to beginning of decl data */
fastRead("DeclDataL", codePtr, &DeclDataSize); /* Read decl data into initials space. */
fprintf(ErrFile,"\nDeclData loaded at:\t\t$%lx\n",codePtr-ROMImage);
}
/************************************************************************* <08Jan88>
** Load the ROM overpatches from their files
*************************************************************************/
void readOverPatches()
{
char *codePtr;
int i, PatchSize;
for (i = 0; i < NumPatches; i++) {
SpinCursor(32);
codePtr = ROMImage + PatchOffsets[i]; /* Pointer to where overpatch begins */
fastRead(PatchFileNames[i], codePtr, &PatchSize); /* Read the dang thing */
printf("Overpatch %d: Filename \"%s\", offset 0x%lx, size 0x%lx\n",
i+1, PatchFileNames[i], PatchOffsets[i], PatchSize);
}
}
/*************************************************************************
** Given a ROMImage, write back updated ROMImageL, and write new
** ROMImageH and ROMMondo.
**
** 1/25/89 <1.2> CCH Rewritten to use only one buffer for the ROM Image.
** 2/8/89 <1.3> CCH Only Outputs slice files if outputSlices is true.
** 5/11/89 <1.6> CCH Added option to create encrypted RAM version.
** 7/25/89 <2.4> CCH Changed encryption slightly; now increments
** an extra count for each character.
*************************************************************************/
void writeROMOutputs()
{
char fileName[80], *cPtr, *cMax;
char *keyindex, *keymax, *key = "(c) Copyright Apple Computer, Inc. 1989-1990";
int i;
fastWrite( "ROMMondo", ROMImage, ROMLEN );
if ( (ROMBRIAN != 1) || (ROMSLICES != 1) && outputSlices) { /* create catenated slices file */
interleavedWrite( "ROMCat", ROMImage, ROMSLICES, 0, IntrLvCreate );
for (i=1; i<ROMSLICES; i++)
interleavedWrite("ROMCat", ROMImage, ROMSLICES, i, IntrLvAppend);
}
if (outputSlices) { /* do we want slice files? <1.3><1.6> */
if (ROMBRIAN == 1)
for (i=0; i<ROMSLICES; i++) {
sprintf(fileName,"ROMImage%c",i+0x30); /* ROMImage0..n */
interleavedWrite(fileName, ROMImage, ROMSLICES, i, IntrLvCreate);
} /*for*/
else
if (ROMSLICES == 1)
for (i=0; i<REALSLICES; i++) {
sprintf(fileName,"ROMImage%c",i+0x30); /* ROMImage0..n */
interleavedWrite(fileName, ROMImage, REALSLICES, i, IntrLvCreate);
} /*for*/
else
for (i=0; i<REALSLICES; i++) {
sprintf(fileName,"ROMImage%c%c", (i&1?'L':'H'), (i>>1)+0x30);
interleavedWrite(fileName, ROMImage, REALSLICES, i, IntrLvCreate);
} /*for*/
}
if (RAMVersion) { /* do we want a special encrypted version for RAM? */
printf("\t\tEncoding RAM-based version…\n");
fflush(stdout);
cPtr = ROMImage;
cMax = ROMImage + ROMLEN;
keyindex = key;
keymax = key + strlen(key);
while (cPtr < cMax) {
*cPtr = (*cPtr + *keyindex + 1) & 0xff; /* encode a byte */
if (++keyindex == keymax) /* reset index if necessary */
keyindex = key;
cPtr++;
} /*while*/
fastWrite( "RAMMondo", ROMImage, ROMLEN );
}
} /*writeROMOutputs*/
/*************************************************************************
** Close the error file and set the file type (if the file exists at all).
*************************************************************************/
void closeErrs()
{
OSErr e;
FInfo fi;
fprintf(ErrFile, "Ending Hiram Log.\n");
fclose(ErrFile);
e = GetFInfo(PasName(ErrFName), 0, &fi);
if (e == 0)
{
fi.fdType = 0x54455854; /* TEXT */
fi.fdCreator = 0x4D505320; /* MPS */
e = SetFInfo(PasName(ErrFName), 0, &fi);
}
}
/*************************************************************************
**************************************************************************
** Lower-level utilities subordinate to the main flow.
**************************************************************************
*************************************************************************/
/*************************************************************************
** Presuming locations 0x30-0x3F are 0, compute byte-wide checksums for each
** of the ROM slices. After all are computed, stuff them into the relevant
** longs in the ROM image. Must not overwrite the ROM image until ALL are
** computed, to simplify the summing loop.
** Accumulate 16-bit words into 32-bit sum, stuff it in first long.
** Have ROMLEN-4 bytes to be split into words for the sum.
**
** 1/24/89 <1.2> CCH Rewritten to always calc slice cksums
** 4/11/89 <1.5> CCH Zeros out individual cksums before doing anything, and
** excludes first 4 bytes from all checksumming.
** 5/11/89 <1.6> CCH Sped up checksum loop.
*************************************************************************/
void computeCheckSums()
{
uchar *cPtr, *cMax;
int i, top;
ushort *wp;
ulong cs, csum[8];
printf("\t\tCalculating checksums…\n");
fflush(stdout);
/** zero slice cksums **/
cs = 0;
for (i=0; i < ROMSLICES; i++) {
csum[i] = 0;
*(ulong*)(ROMImage+48+(i<<2)) = 0;
}
/** calc slice cksums during loop through ROMImage **/
i = 0;
cPtr = ROMImage + 4; /* skip first long word */
cMax = ROMImage + ROMLEN;
while (cPtr < cMax) {
csum[i] += *cPtr++; /* add to approp. slice */
if (++i == ROMSLICES) /* reset if necessary */
i = 0;
} /*while*/
/** store slice checksums in the ROM Image **/
for (i=0; i < ROMSLICES; i++)
*(ulong*)(ROMImage + Byteov + (i*4)) = csum[i];
/** calc main during loop through ROMImage **/
wp = (ushort*)(ROMImage + 4);
top = (ROMLEN-4)/2;
for (i=0;i<top;i++) {
cs += *wp++;
}
/** store the complete checksum in the ROM Image **/
*(ulong*)(ROMImage + Chekov) = cs;
} /*computeCheckSums*/
/*************************************************************************
** Returns a formatted date string to be placed in the initials string.
*************************************************************************/
void getDate(date)
char *date;
{
char dstr[64];
unsigned long secs;
GetDateTime(&secs); /* current seconds since 1904 */
IUDateString(secs, abbrevDate, dstr); /* date as a C string */
sprintf(date,"[%P]",dstr); /* make it look purdy */
}
/*************************************************************************
** Utility to read a file named fName in BLOCKSIZE chunks into fBuffer,
** returning file size in bytes in *pSize.
*************************************************************************/
void fastRead(fName, fBuffer, pSize)
char *fName, *fBuffer;
int *pSize;
{
char *fPtr;
long codeRead, fSize;
short refNum, retCode;
printf("\t\tOpening file “%s” for reading.\n", fName);
fflush(stdout);
retCode = FSOpen(PasName(fName), 0, &refNum);
if (retCode) {
printf("File = %s ; Retcode = %d\n", fName, retCode);
MySignal("Failed open.", retCode);
}
/* Read it in blkSize chunks. */
fPtr = fBuffer;
fSize = 0;
do {
codeRead = BLOCKSIZE;
retCode = FSRead(refNum, &codeRead, fPtr);
fPtr += codeRead;
fSize += codeRead;
SpinCursor(8);
} while (codeRead == BLOCKSIZE);
if (retCode != eofErr) /* permit only EOF to go unnoticed */
MySignal("Read loop terminated by other than EOF.", retCode);
retCode = FSClose(refNum);
*pSize = fSize; /* return the size */
}
/*************************************************************************
** Utility to write a file quickly using low-level IO.
*************************************************************************/
void fastWrite(fName, fBuffer, fSize)
char *fName, *fBuffer;
int fSize;
{
long codeWrit, codeWantWrit;
short refNum, retCode;
printf("\t\tOpening file “%s” to write 0x%x characters.\n", fName, fSize);
fflush(stdout);
/*
** Strategy for writing a file: Attempt to create it: if not OK, but not
** because file already exists, then die; else, open it and set EOF to 0.
*/
retCode = Create(PasName(fName), 0, 0x4849524D, 0x524F4D20);
if ((retCode != dupFNErr) && (retCode)) { /* error, not a dupe? */
printf("\t\• Create of “%s” failed…\n", fName);
fflush(stdout);
MySignal("Create failed, and not a duplicate filename error.", retCode);
}
retCode = FSOpen(PasName(fName), 0, &refNum);
if (retCode) {
printf("\t\• Create of “%s” failed…\n", fName);
fflush(stdout);
MySignal("Open for R/W failed.", retCode);
}
retCode = SetEOF(refNum, 0);
if (retCode) {
printf("\t\• SetEOF of “%s” failed…\n", fName);
fflush(stdout);
MySignal("SetEOF failed after create.", retCode);
}
/* Write it in blkSize chunks, until last chunks... */
do {
codeWantWrit = (fSize > BLOCKSIZE) ? BLOCKSIZE : fSize;
codeWrit = codeWantWrit;
retCode = FSWrite(refNum, &codeWrit, fBuffer);
if (codeWrit != codeWantWrit) {
printf("\t\• Error writing “%s”…\n", fName);
fflush(stdout);
MySignal("Couldn't write everything to file…", retCode);
}
fBuffer += codeWrit;
fSize -= codeWrit;
SpinCursor(1);
} while (fSize > 0);
if (retCode) {
printf("\t\• Couldn't write “%s”…\n", fName);
fflush(stdout);
MySignal("Failure in file write.", retCode);
}
retCode = FSClose(refNum);
}
/*************************************************************************
** Utility to write a copy of a ROM slice to a file
** 1/25/89 CCH
*************************************************************************/
void interleavedWrite(fName, fBuffer, slices, whichSlice, appendFlag)
char *fName, *fBuffer;
int slices, whichSlice, appendFlag;
{
long codeWrit, codeWantWrit;
char *top, *src, *dest, *buffer;
long size;
short refNum, retCode;
size = ROMLEN / slices;
if (!appendFlag) {
printf("\t\tOpening file “%s” to write 0x%x bytes.\n", fName, size);
fflush(stdout);
} else {
printf("\t\tconcatentating 0x%x bytes to file %s.\n", size, fName);
fflush(stdout);
}
/*
** Strategy for writing a file: Attempt to create it: if not OK, but not
** because file already exists, then die; else, open it and either clear it
** or set pointer to end of file.
*/
if (!appendFlag) {
retCode = Create(PasName(fName), 0, 'HIRM', 'ROM ');
if ((retCode != dupFNErr) && (retCode)) { /* error, not a dupe? */
printf("\t\• Create of “%s” failed…\n", fName);
fflush(stdout);
MySignal("Create failed, and not a duplicate filename error.", retCode);
}
}
retCode = FSOpen(PasName(fName), 0, &refNum);
if (retCode) {
printf("\t\• Open of “%s” failed…\n", fName);
fflush(stdout);
MySignal("Open for R/W failed.", retCode);
}
if (appendFlag) /* if appending */
SetFPos(refNum, fsFromLEOF, 0); /* set pointer to end-of-file */
else {
retCode = SetEOF(refNum, 0); /* otherwise, zero out file */
if (retCode) {
printf("\t\• SetEOF of “%s” failed…\n", fName);
fflush(stdout);
MySignal("SetEOF failed after open.", retCode);
}
}
/*
** write strategy: allocate a temporary buffer, dump the slice into
** that buffer, then do a series of block writes. Free the buffer when done
*/
dest = buffer = NewPtr(size); /* allocate a temporary buffer */
if (!buffer) {
printf("\t\• Out of memory in interleavedWrite…\n");
fflush(stdout);
MySignal("Couldn't allocate temporary buffer…", 0);
}
top = ROMLEN + fBuffer;
for (src=fBuffer+whichSlice; src<top; src+=slices) /* copy slice into temp buffer */
*dest++ = *src;
/* Write it in blkSize chunks, until last chunks... */
dest = buffer;
do {
codeWantWrit = (size > BLOCKSIZE) ? BLOCKSIZE : size;
codeWrit = codeWantWrit;
retCode = FSWrite(refNum, &codeWrit, dest);
if (codeWrit != codeWantWrit) {
printf("\t\• Error writing “%s”…\n", fName);
fflush(stdout);
MySignal("Couldn't write everything to file…", retCode);
}
dest += codeWrit;
size -= codeWrit;
SpinCursor(1);
} while (size > 0);
if (retCode) {
printf("\t\• Couldn't write “%s”…\n", fName);
fflush(stdout);
MySignal("Failure in file write.", retCode);
}
DisposPtr(buffer); /* free the temporary buffer */
retCode = FSClose(refNum);
} /*interleavedWrite*/
/*************************************************************************
** Write a message and exit, closing all files.
*************************************************************************/
void MySignal(msg, retCode)
char *msg;
int retCode;
{
printf("**** Hiram Error: %s", msg);
if (retCode)
printf(" ; Return Code = %d\n", retCode);
else
putchar('\n');
exit(1);
}
/*************************************************************************
** Convert C filenames to Pascal names.
*************************************************************************/
char * PasName(cName)
char *cName;
{
strcpy (pName,cName); /* name better be < 255 characters */
return((char *) c2pstr(pName)); /* 1.2 */
}
/*************************************************************************
** Convert Pascal filenames to C names.
*************************************************************************/
char * CName(str)
char *str;
{
strncpy (pName,str,str[0]+1); /* name better be < 255 characters */
return((char *) p2cstr(pName)); /* 1.2 */
}
/*************************************************************************
** String formatting routine
*************************************************************************/
void tabTo( str, pos)
char *str;
int pos;
{
int len, i;
len = strlen(str);
for (i=pos; i>len; i--)
strcat(str," ");
} /*tabTo*/
/*******************
* End Of Hiram.c
********************/