//	GenStructs.h

#ifndef _H_GenStructs
#define _H_GenStructs

#include "Utils.h"
#include "GenDiskLocSpec.h"

//	constants
#define	Gen_kBytesPerBlock			512L		//	0x0200L
#define Gen_kBytesPerSector			256UL
#define Gen_kSectorsPerTrack 		16UL
#define Gen_kTracksPerDisk 			35UL

typedef unsigned short	Gen_BlockNum;

//	disk structs
typedef struct {
	Byte		byte[Gen_kBytesPerBlock];
} Gen_Block;

typedef struct {
	Byte		byte[Gen_kBytesPerSector];
} Gen_Sector;

typedef struct {
	Gen_Sector	sector[Gen_kSectorsPerTrack];
} Gen_Track;

typedef struct Gen_Disk {
	Gen_Track	track[Gen_kTracksPerDisk];
} Gen_Disk;

#define FOR_EACH_TRACK_SECTOR_SPEC(_curSpec, _max_tracks, _max_sectors)	\
	for (									\
		_curSpec.track = 0;					\
		_curSpec.track < _max_tracks;		\
		_curSpec.track++					\
	) for (									\
		_curSpec.sector = 0;				\
		_curSpec.sector < _max_sectors;		\
		_curSpec.sector++					\
	)

#define FOR_EACH_TRACK_SECTOR(_curSpec)	\
	FOR_EACH_TRACK_SECTOR_SPEC(_curSpec, Gen_kTracksPerDisk, Gen_kSectorsPerTrack)

//	400/800K DOS 3.3 disk structs
#define Gen_kSectorsPerTrack400	32UL
#define Gen_kTracksPerDisk400	50UL

#define FOR_EACH_TRACK_SECTOR400(_curSpec)	\
	FOR_EACH_TRACK_SECTOR_SPEC(_curSpec, Gen_kTracksPerDisk400, Gen_kSectorsPerTrack400)

typedef struct {
	Gen_Sector		sector[Gen_kSectorsPerTrack400];
} Gen_Track400;

typedef struct {
	Gen_Track400	track[Gen_kTracksPerDisk400];
} Gen_Disk400;

typedef struct {
	unsigned char	destroyEnable	: 1;
	unsigned char	renameEnable	: 1;
	unsigned char	backup			: 1;
	unsigned char	unused			: 3;
	unsigned char	writeEnable		: 1;
	unsigned char	readEnable		: 1;
} Gen_AccessBits;

#define		Gen_kBytesPerDisk	(Gen_kTracksPerDisk * Gen_kSectorsPerTrack * Gen_kBytesPerSector)

/****************************/
typedef enum {
	//	must match DiskMap_SubPaneType
	Gen_Alloc_NONE, 		//	entryP points to CDisk
	Gen_Alloc_FILE, 		//	entryP points to CFile
	Gen_Alloc_FILE_BAS, 	//	entryP points to CFile
	Gen_Alloc_FILE_BIN, 	//	entryP points to CFile
	Gen_Alloc_FILE_TXT, 	//	entryP points to CFile
	Gen_Alloc_EXTENTS, 		//	entryP points to CFile
	Gen_Alloc_MYSTERY, 		//	entryP points to CDisk
	Gen_Alloc_MULTI,	 	//	$$$ entryP points to Gen_AllocNodeRec A HANDLE
	Gen_Alloc_DIRECTORY, 	//	entryP points to CFolder or CDisk
	Gen_Alloc_BOOT, 		//	entryP points to CDisk
	Gen_Alloc_V_BITMAP, 	//	entryP points to CDisk
	
	Gen_Alloc_NUMTYPES
} Gen_AllocType;

typedef enum {
	Gen_AllocSize_NONE, 
	
	Gen_AllocSize_SECTORS, 
	Gen_AllocSize_SECTORS400, 
	Gen_AllocSize_SHORT, 
	Gen_AllocSize_BYTE, 
	
	Gen_AllocSize_NUMTYPES
} Gen_AllocSizeType;

#define	Gen_UseBlocks(_allocSize)	(_allocSize == Gen_AllocSize_SHORT || _allocSize == Gen_AllocSize_BYTE)

extern	Gen_SectorSpec		Gen_gLastValidSector;
extern	Gen_SectorSpec		Gen_gLastValidSector400;

#define	Gen_LastValidSector(_size)			\
	((_size) == Gen_AllocSize_SECTORS		\
		? Gen_gLastValidSector				\
		: Gen_gLastValidSector400)

#define	Gen_ValidSector(_size, _spec)							\
	(															\
		(_spec).track < Gen_LastValidSector(_size).track 		\
		&& (_spec).sector < Gen_LastValidSector(_size).sector)	\
		
typedef union {
	Ptr				ptr;
	Gen_SectorSpec	*sectorsA;
	ushort			*short_blocksA;
	Byte			*byte_blocksA;
} Gen_Alloc, *Gen_AllocP;

typedef struct {
	ushort		totalS;
	Gen_Alloc	u;
} Gen_AllocTypeRec;

/****************************/
//	this is a list of all the types of allocation lists an entry 
//	has.  an entry can have more than one type of allocation list
typedef struct {
	Gen_AllocSizeType		allocSize;
	Gen_AllocTypeRec		type[Gen_Alloc_NUMTYPES];
} Gen_EntryAlloc;

/****************************/
class	CEntry;

typedef struct {
	Gen_AllocType		allocType;
	CEntry				*entryP;
} Gen_AllocNodeRec;

typedef struct {
	Gen_AllocNodeRec	sector[Gen_kSectorsPerTrack];
} Gen_TrackBitMap;

typedef struct {
	Gen_TrackBitMap		track[Gen_kTracksPerDisk];
} Gen_DiskBitMap;

typedef struct {
	Gen_AllocNodeRec	sector[Gen_kSectorsPerTrack400];
} Gen_TrackBitMap400;

typedef struct {
	Gen_TrackBitMap400	track[Gen_kTracksPerDisk400];
} Gen_DiskBitMap400;

typedef union {
	Gen_DiskBitMap		disk140;
	Gen_DiskBitMap400	disk400;
} Gen_DiskBitUnion;

typedef struct {
	Gen_AllocSizeType	allocSize;

	ushort				maxSizeS;
	ushort				curSizeS;
	ushort				nonExistantS;
	
	union {
		Ptr					ptr;
		Gen_AllocNodeRec	*blockA;
		Gen_DiskBitMap		*disk140A;
		Gen_DiskBitMap400	*disk400A;
	} map;
	
} Gen_AllocMap;

typedef struct DiskImageRec DiskImageRec;

//	accessing a sector
Gen_Sector	*Gen_GetSector(DiskImageRec *imageRecP, Gen_SectorSpec sectorSpec);

//	sector equivalence
#define	Gen_EqualSector(sectorA, sectorB)	\
	(*(short *)&(sectorA) == *(short *)&(sectorB))

//	empty sector
#define Gen_IsNullSector(sector)			\
	(*(short *)&(sector) == 0)

typedef struct {
	char		*name;
	Boolean		unique;
} Gen_GetUniqueNameRec;

#endif