// ========================================================================
//
// romhdr.h
//
// Structural definition of the N64 cart image header, and a macro to
// allow the header to be defined in-code for a given project
//
// Based on info in n64ops
//
// Developed at Ground Zero Development (www.g0dev.com)
//
// ========================================================================

#ifndef  ROMHDR_H
#define  ROMPDR_H

#include <basetype.h>

//
// Contrary to common belief, the first 4 bytes of the header are not a
// 'magic signature'.  The master (PIF) boot code at 0xbfc00000 (which runs
// first at N64 boot) interprets the first 4 bytes as a set of configuration
// parameters for cartridge memory access, defining its speed etc.
//


// ------------------------------------------------------------------------
//
// Declare a structure to represent the header
//
//

typedef void (* PFnUltraCartInitialPc) (void);

typedef struct SUltraCartHeader {
   USHORT usMagic;
#define  ULTRACART_MAGIC                     0x8037U
#define  ULTRACART_MAGIC_RVS                 0x3780U

   UBYTE  ubRtoolInfo;
#define  ULTRACART_RTOOL_UNCOMPRESSED        0x12U
#define  ULTRACART_RTOOL_COMPRESSED          0x13U

   UBYTE ubUnknown1;
#define  ULTRACART_UNKNOWN1                  0x40U

   ULONG ulClockRate;
#define  ULTRACART_CLOCKRATE                 0x0000000fU

   PFnUltraCartInitialPc pfnInitialPc;

   ULONG ulReleaseId;
#define  ULTRACART_RELEASEID_DEFAULT         0x00001444U

   ULONG ulCrc1;
   ULONG ulCrc2;
   ULONG ulMbz1;
   ULONG ulMbz2;
   char szImageName [20];
   UBYTE aubMbz3 [7];

   UBYTE ubManufacturerId;
#define  ULTRACART_MANUF_NINTENDO            0x4eU

   USHORT usCartId;

   UBYTE ubCountryId;
#define  ULTRACART_COUNTRY_GERMANY           0x44U
#define  ULTRACART_COUNTRY_USA               0x45U
#define  ULTRACART_COUNTRY_JAPAN             0x4aU
#define  ULTRACART_COUNTRY_EUROPE            0x50U
#define  ULTRACART_COUNTRY_AUSTRALIA         0x55U

   UBYTE ubMbz4;

   UBYTE abBootCode [1008 * 4];

} SUltraCartHeader, * PSUltraCartHeader;


// ------------------------------------------------------------------------
//
// Declare a macro to support in-code definition of the header info
// for an image being built.  The macro will generate a populated
// header just by supplying the name.
//
// 

extern SUltraCartHeader UltraCartHeader;


#define  DEFINE_ROMHEADER(IMAGE_NAME) \
   /* Declare pointer to the crt0 startup code */ \
 \
   EXTERN_C void _start (void); \
 \
   /* Force the header into a seg so link script can put it at the */ \
   /* start of the image.  The struct name is exported and referenced */ \
   /* so linker can complain if its absent */ \
 \
   SUltraCartHeader UltraCartHeader WITH_SECTION_ATTR (".cartheader") = { \
      ULTRACART_MAGIC, \
      ULTRACART_RTOOL_UNCOMPRESSED, \
      ULTRACART_UNKNOWN1, \
      ULTRACART_CLOCKRATE, \
      _start, \
      ULTRACART_RELEASEID_DEFAULT, \
      0xc1c1c1c1, /* Checksum generated later */ \
      0xc2c2c2c2, /* Checksum generated later */ \
      0, \
      0, \
      IMAGE_NAME, \
      { 0 }, \
      ULTRACART_MANUF_NINTENDO, \
      0x0000, \
      ULTRACART_COUNTRY_USA, \
      0, \
      { 0 /* cart boot code inserted later */ } \
   };

#endif
