#ifndef BASICNEWTON_H
#define BASICNEWTON_H

typedef unsigned long ULong;		// unsigned 32 bit int
typedef unsigned short UShort;		// unsigned 16 bit int
typedef unsigned char Byte;			// unsigned 8 bit char
typedef unsigned short UniChar;		// unsigned 16 bit char
typedef unsigned long Date;			// unsigned 32 bit int

#define SIGNATURE_LEN   8

typedef struct InfoRef_struct
{
  UShort offset;
  UShort length;
} InfoRef;

typedef struct FixedHeader_struct
{
  Byte signature[SIGNATURE_LEN+1];
  ULong reserved1;
  ULong flags;
  ULong version;
  InfoRef copyright;
  InfoRef name;
  ULong size;
  Date creationDate;
  Date modificationDate;
  ULong reserved3;
  ULong directorySize;
  ULong numParts;
} FixedHeader;

enum FixedHeaderConstants
{
  kAutoRemoveFlag           = 0x80000000,
  kCopyProtectFlag          = 0x40000000,
  kNoCompressionFlag        = 0x10000000,
  kRelocationFlag           = 0x04000000,
  kUseFasterCompressionFlag = 0x02000000,
  fixedHeaderSize           = 7*sizeof(ULong)+4*sizeof(UShort)+2*sizeof(Date)+8*sizeof(Byte)
};

typedef struct PartEntry_struct
{
  ULong offset;
  ULong size;
  ULong size2;
  ULong type;
  ULong reserved1;
  ULong flags;
  InfoRef info;
  ULong reserved2;
} PartEntry;

enum PartEntryConstants
{
  kProtocolPart    = 0x00000000,
  kNOSPart         = 0x00000001,
  kRawPart         = 0x00000002,
  kAutoLoadFlag    = 0x00000010,
  kAutoRemoveFlagP = 0x00000020,
  kNotifyFlag      = 0x00000080,
  kAutoCopyFlag    = 0x00000100,
  bookMarker       = 0x626F6F6B,	/* Hollerith constant "book" */
  partEntrySize    = 7*sizeof(ULong)+2*sizeof(UShort)
};

typedef struct RelocationHeader_struct
{
  ULong reserved;
  ULong relocationSize;
  ULong pageSize;
  ULong numEntries;
  ULong baseAddress;
} RelocationHeader;

enum RefConstants
{
  kIntegerFlag   = 0x00,
  kPointerFlag   = 0x01,
  kCharacterFlag = 0x0A,
  kSpecialFlag   = 0x02,
  kMagicFlag     = 0x03,
  kTrueFlag      = 0x1A,
  kNilFlag       = 0x02,
  kSymbolClass   = 0x55552,
  kMapSorted     = 1,
  kMapProto      = 4,
  relocationHeaderSize = 5*sizeof(ULong)
};

typedef struct ObjectHeaderPlus_struct
{
  ULong flags;
  ULong marker;
  ULong classOrMap;
} ObjectHeaderPlus;
  
enum ObjectConstants
{
  kObjSlotted = 0x01,
  kObjFrame   = 0x02,
  kVerifier   = 0x40,
  objectHeaderPlusSize = 3*sizeof(ULong)
};

/* prototypes */
void reportError();
wchar_t *ulong2wchar(ULong input,wchar_t *output);
ULong getULong();
UShort getUShort();
int isPointer(ULong ref);
ULong getPointer(ULong ref);
int isInt(ULong ref);
ULong getInt(ULong ref);
int isNil(ULong ref);
int isArray(ULong ref);
int isFrame(ULong ref);
int isBinary(ULong ref);
int isSymbol(ULong classRef);
ULong extractSize(ULong ref);
ULong getNumOfSlots(ULong ref);
void printField(char *field,char *map[],ULong slots[],ULong numOfSlots);
void printDate(Date dateToPrint,int needsFixing);
void printDateField(char *field,char *map[],ULong slots[],ULong numOfSlots,int needsFixing);
void printStringsFromField(char *field,char *map[],ULong slots[],ULong numOfSlots,char *separator);
ULong symbolHashFunction(char* name);
char* loadSymbol(unsigned long location,char *symbol);
ULong isString(unsigned long location);
wchar_t* loadString(unsigned long location,wchar_t *stringData);
void linearizeMap(ULong mapStart,ULong map[],unsigned int last,ULong numOfSlots);
void processObject(ULong location,char *separator);
void processContentsFrame(ULong frameStart,int needsFixing);
void processPartFrame(ULong partFrameStart,int needsFixing);

#endif

