//	DosStructs.h

#ifndef _H_DosStructs
#define _H_DosStructs

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

#pragma options align = packed

//	accessing a sector
#define	Dos_EqualSector			Gen_EqualSector
#define Dos_IsNullSector		Gen_IsNullSector

//	constants
#define Dos_kBytesPerSector		Gen_kBytesPerSector
#define Dos_kSectorsPerTrack 	Gen_kSectorsPerTrack
#define Dos_kBytesPerTrack 		(Dos_kBytesPerSector * Dos_kSectorsPerTrack)
#define Dos_kTracksPerDisk 		Gen_kTracksPerDisk

//	disk structs
#define	Dos_Sector				Gen_Sector
#define	Dos_Track				Gen_Track
#define	Dos_Disk				Gen_Disk

//	400/800K DOS 3.3 disk structs
#define Dos_kSectorsPerTrack400	Gen_kSectorsPerTrack400
#define Dos_kTracksPerDisk400	Gen_kTracksPerDisk400

#define	Dos_Track400	Gen_Track400
#define	Dos_Disk400		Gen_Disk400

typedef struct {
	Dos_Disk400		vol[2];
} Dos_Disk800;

#define	Dos_kBitMapTrack			((ushort)0x11)
#define	Dos_kBitMapSector			((ushort)0x00)
#define	Dos_kNumBitMapSectors		((ushort)0x01)

#define	Dos_kDirectorySector		((ushort)0x01)
#define	Dos_kNumDirectorySectors	((ushort)0x0F)

#define	Dos_kVtocSector		{ Dos_kBitMapTrack, Dos_kBitMapSector }
extern	Dos_SectorSpec		Dos_gVtocSector;

#define	Dos_kEmptySector	{ (ushort)0x00, (ushort)0x00 }
extern	Dos_SectorSpec		Dos_gEmptySector;

#define	Dos_kInvalidSector	{ (ushort)0xFF, (ushort)0xFF }
extern	Dos_SectorSpec		Dos_gInvalidSector;

#define	Dos_IsInvalidSector(_sector)	\
	Gen_EqualSector((_sector), Dos_gInvalidSector)

typedef struct {
	Byte			lastTrack;
	char			direction;	//	0x01 or 0xFF
} Dos_SectorAlloc;

typedef struct {
	ulong		bitMap;
} Dos_TrackBitmap;

#define	Dos_kFreeSector	1
#define	Dos_kUsedSector	0

#define	Dos_kVolumeNameLen	(0x26 - 0x07 + 1)
typedef	char				Dos_VolumeName[Dos_kVolumeNameLen];
typedef char				Dos_VolumeNameStr[Dos_kVolumeNameLen + 1];

#define Dos_kMaxSectorSpecs		122

typedef struct {
	Byte				unused_1;
	Dos_SectorSpec		dirSector;			//	Dos_DirSector *
	Byte				dosReleaseNumber;
	Byte				twirledDownB;
	Byte				useVolumeName;		//	boolean
	Byte				volumeNumber;
	Dos_VolumeName		volumeName;
	Byte				maxSectorSpecs;		//	Per Sector Of TSList == Dos_kMaxSectorSpecs
	Byte				unused_2[0x2F - 0x28 + 1];
	Dos_SectorAlloc		sectorAlloc;
	short				unused_3;
	
	//	NOT a sector pointer!  actually it is
	//	tracks per disk and sectors per disk
	Dos_SectorSpec		perDisk;				
											
	RboShort			bytesPerSector;
	Dos_TrackBitmap		trackBitmaps[Dos_kTracksPerDisk400];
//	Byte				unused_4[45];
} Dos_VtocSector;

#define	Dos_IsDeleted(entryPtr)		\
	(entryPtr->firstTSSector.track == 0xFF)

#define	Dos_IsEmptyEntry(entryPtr)	\
	(Dos_IsDeleted(entryPtr) || Dos_IsNullSector(entryPtr->firstTSSector))

typedef	Byte					Dos_FileType;
#define	Dos_FileType_TXT		((Dos_FileType)0x00)
#define	Dos_FileType_INT		((Dos_FileType)0x01)
#define	Dos_FileType_BAS		((Dos_FileType)0x02)
#define	Dos_FileType_BIN		((Dos_FileType)0x04)
#define	Dos_FileType_S			((Dos_FileType)0x08)
#define	Dos_FileType_R			((Dos_FileType)0x10)
#define	Dos_FileType_a			((Dos_FileType)0x20)
#define	Dos_FileType_b			((Dos_FileType)0x40)
#define	Dos_FileType_LOCK		((Dos_FileType)0x80)
#define	Dos_FileType_MASK		((Dos_FileType)0x7F)

#define		Dos_kNameLength		(0x20 - 0x03 + 1)
typedef		char				Dos_FileName[Dos_kNameLength];
typedef		char				Dos_FileNameStr[Dos_kNameLength + 1];

typedef struct {
	Dos_SectorSpec		firstTSSector;			//	Dos_TSListSector *;
	Dos_FileType		fileType;
	Dos_FileName		name;
	RboShort			size;					//	in sectors, mod 256
} Dos_DirEntry;

typedef	short	Dos_EntryIndex;
#define	Dos_kMaxEntriesPerSector	7

typedef struct {
	Byte				unused_1;
	Dos_SectorSpec		nextDirSector;
	Byte				unused_2[0x0A - 0x03 + 1];
	Dos_DirEntry		entry[Dos_kMaxEntriesPerSector];
} Dos_DirSector;

typedef struct {
	Byte				unused_1;
	Dos_SectorSpec		nextTsSector;						//	Dos_TSListSector *
	Byte				unused_2[2];
	RboShort			sectorBaseNum;
	Byte				unused_3[5];
	Dos_SectorSpec		fileSectors[Dos_kMaxSectorSpecs];	//	Dos_FileSector *s
} Dos_TSListSector;

/************************
	File Sectors
*/
typedef struct {
	Byte	file[Dos_kBytesPerSector];
} Dos_FileSector;

/************************
	Basic File Sectors
*/
typedef struct {
	RboShort				length;
} Dos_FileHeader_BASIC;

#define	Dos_kBytesPerHeaderSector_BAS	(sizeof(Dos_FileSector) - sizeof(Dos_FileHeader_BASIC))

typedef struct {
	Byte					bytes[Dos_kBytesPerHeaderSector_BAS];
} Dos_FileHeaderBytes_BASIC;

typedef struct {
	Dos_FileHeader_BASIC		header;
	Dos_FileHeaderBytes_BASIC	file;
} Dos_FileSector_BASIC;

/************************
	Binary File Sectors
*/
typedef struct {
	RboShort				loadAddress;
	RboShort				length;
} Dos_FileHeader_BIN;

#define	Dos_kBytesPerHeaderSector_BIN	(sizeof(Dos_FileSector) - sizeof(Dos_FileHeader_BIN))

typedef struct {
	Byte					bytes[Dos_kBytesPerHeaderSector_BIN];
} Dos_FileHeaderBytes_BIN;

typedef struct {
	Dos_FileHeader_BIN			header;
	Dos_FileHeaderBytes_BIN		file;
} Dos_FileSector_BIN;

#pragma options align = reset
/************************************************/
Boolean		Dos_IsDos(DiskImageRec *imageRec);

typedef struct {
	Dos_SectorSpec		sectorSpec;
	Dos_EntryIndex		entryIndex;	//	within block (zero based)
	Dos_EntryIndex		dirIndex;	//	within directory (one based)
} Dos_EntryLocSpec;

typedef enum {
	Dos_FileDesc_TEXT, 
	Dos_FileDesc_INT, 
	Dos_FileDesc_BAS, 
	Dos_FileDesc_BIN, 
	Dos_FileDesc_S, 
	Dos_FileDesc_R, 
	Dos_FileDesc_a, 
	Dos_FileDesc_b, 
	
	Dos_FileDesc_NUMTYPES
} Dos_FileDescType;

typedef char					Dos_FileDescription[32];
extern	Dos_FileDescription		Dos_FileDescArray[];

void				Dos_BuildFileTypeMenu(MenuRef theMenu);
Dos_FileDescType	Dos_FileTypeToDescType(Dos_FileType fileType);
Byte				Dos_GetVolNum(DiskImageRec *imageRec);

OSErr		Dos_GetSector(
	DiskImageRec	*imageRecP, 
	Dos_SectorSpec	sectorSpec, 
	Dos_Sector		**sectorPP);

OSErr		Dos_SetSector(
	DiskImageRec	*imageRecP, 
	Dos_SectorSpec	sectorSpec, 
	Dos_Sector		*sectorP);

Dos_SectorSpec		GetFirstTSSector(Dos_DirEntry *entryP);

#endif