//	Nibblizer.h

#ifndef _H_Nibblizer
#define	_H_Nibblizer

#include "FileSystemTypes.h"
#include "GenStructs.h"
#include "ByteMunger.h"

#pragma options align = packed

#define		kNib_TrackSizeSm		6250UL
#define		kNib_DiskSizeSm			218750UL

//	things with "Sm" after them are the "Small" version
//	of nib disks, used in Dapple and the emu it's based on
#define		kNib_TrackSize			6656UL
#define		kNib_DiskSize			232960UL

typedef	struct {
	Byte	data[3];
} Nib_Logue;

#define	kNibFirstPrologueByte	0xD5

#define	kNibAddrPrologue	{	kNibFirstPrologueByte, 0xAA, 0x96	}
#define	kNibDataPrologue	{	kNibFirstPrologueByte, 0xAA, 0xAD	}
#define	kNibEpliogue		{	0xDE, 0xAA, 0xEB	}
extern	Nib_Logue			gNibAddrPrologue;
extern	Nib_Logue			gNibDataPrologue;
extern	Nib_Logue			gNibEpliogue;

typedef RboShort	Nib_4n4Short;
typedef Byte		Nib_6n2Byte;

typedef struct {
	Nib_Logue		prologue;
	Nib_4n4Short	volume;
	Nib_4n4Short	track;
	Nib_4n4Short	sector;
	Nib_4n4Short	checksum;
	Nib_Logue		epilogue;
} Nib_AddressField;

#define		kNib_4n4Mask			(Byte)0xAA

#define		Nib_kBytesPerSector		342UL
#define		Nib_kChecksumIndex		Nib_kBytesPerSector
#define		Nib_kEpilogStartIndex	(Nib_kBytesPerSector + 1)

typedef struct {
	Nib_Logue		prologue;
	Nib_6n2Byte		data[Nib_kBytesPerSector];	//	[0..341]
	Nib_6n2Byte		checksum;					//	342
	Nib_Logue		epilogue;					//	343
} Nib_DataField;

/*
	Note: the following 3 numbers are arbitrary values
		but must follow these rules:
	1) each must be >= 5
	2) they must sum to 53 (or 27 for "SMall")
	3) optionally they may fall within the range specified
*/
#define		Nib_kSync1Bytes			34UL	//	[40..95]
#define		Nib_kSync2Bytes			5UL		//	[5..10]
#define		Nib_kSync3Bytes			14UL	//	[14..24]
#define		Nib_kTotalSyncBytes		53UL

#define		Nib_kSync1BytesSm			8UL	//	[40..95]
#define		Nib_kSync2BytesSm			5UL		//	[5..10]
#define		Nib_kSync3BytesSm			14UL	//	[14..24]
#define		Nib_kTotalSyncBytesSm		27UL

#define		Nib_kTrackFillBytesSm		10UL

typedef struct {
	Byte				sync_1[Nib_kSync1Bytes];
	Nib_AddressField	address;
	Byte				sync_2[Nib_kSync2Bytes];
	Nib_DataField		data;
	Byte				sync_3[Nib_kSync3Bytes];
} Nib_Sector;

typedef struct {
	Byte				sync_1[Nib_kSync1BytesSm];
	Nib_AddressField	address;
	Byte				sync_2[Nib_kSync2BytesSm];
	Nib_DataField		data;
	Byte				sync_3[Nib_kSync3BytesSm];
} Nib_SectorSm;

typedef struct {
	Nib_Sector		sector[Gen_kSectorsPerTrack];
} Nib_Track;

typedef struct {
	Nib_SectorSm	sector[Gen_kSectorsPerTrack];
	Byte			fill[Nib_kSync3Bytes];
} Nib_TrackSm;

typedef struct {
	unsigned char	byte[kNib_TrackSize];
} Nib_ByteTrack;

typedef struct {
	unsigned char	byte[kNib_TrackSizeSm];
} Nib_ByteTrackSm;

typedef struct Nib_Disk {
	Nib_Track		track[Gen_kTracksPerDisk];
} Nib_Disk;

typedef struct Nib_DiskSm {
	Nib_TrackSm		track[Gen_kTracksPerDisk];
} Nib_DiskSm;

#pragma options align = reset

Boolean		Nib_Normalize(Boolean smallB, Nib_Disk *nibDisk);
Boolean		Nib_DeNibblize(Nib_Disk *nibDiskP, DiskImageRec *imageRec);
void		Nib_Nibblize(DiskImageRec *imageRec, Nib_Disk *nibDiskP);

#endif
