//	CDiskCpm.c

#include "ctype.h"
#include "Utils.h"
#include "ADFS_Icons.h"
#include "CDialogCopy.h"
#include "ADFS_O_Callbacks.h"
#include "IC_FileIO.h"
#include "CpmStructs.h"
#include "CFolderCpm.h"
#include "CFileCpm.h"
#include "CDiskCpm.h"

OSErr		CDiskCpm::IDiskCpm(
	CDesktop		*desktop, 
	DiskImageRec	*imageRec
) {
	OSErr			err		= noErr;
	Boolean			twirledB;
	
	i_blockBuf			= NULL;
	i_recentBlockNum	= Cpm_kIllegalBlock;

	if (!err) err = _inherited::IDisk(desktop, imageRec);

	i_blocksInVolume = Cpm_kBlocksPerDisk;

	if (!err) {
		if (NewObject(i_rootDir.cpm, CFolderCpm, err)) {
			err = i_rootDir.cpm->IFolderCpm(this);
		}
	}
	
	//	have to wait until folder is initialized before twirled works
	twirledB = GetTwirled();
	i_topicRef.cTopic->O_IsTwirledDown(NULL, &twirledB);

	return err;
}

void		CDiskCpm::Dispose(void)
{
	_inherited::Dispose();
}

OSErr		CDiskCpm::BuildFileTypeMenu(void)
{
	OSErr		err = noErr;
	
	i_fileTypeMenu = GetMenuHandle(209);
	
	if (!i_fileTypeMenu) {
		i_fileTypeMenu = GetMenu(209);
		if (!i_fileTypeMenu) {
			ReportError(err = IC_Err_COULDNT_LOAD_DLG_ITEM);
		}
		
		if (!err) {
			//Cpm Cpm_BuildFileTypeMenu(i_fileTypeMenu);
		}
	}
	
	return err;
}

short		CDiskCpm::MenuItemToFileType(short menuItem, ushort *auxType)
{
	return 0;
}

Boolean		CDiskCpm::CanRename(void)
{
	return FALSE;
}

char		*CDiskCpm::GetName(char *buf)
{
	//	the "#" means pascal string (!)
	sprintf(buf, "%#s", ImageRec_VolRec(i_imageRec).image.fileSpec.name);
	return buf;
}

Cpm_Block	*CDiskCpm::GetBlock(Cpm_BlockNum blockNum)
{
	if (i_recentBlockNum != blockNum) {
		if (
			blockNum >= Cpm_kUserBlocksPerDisk 
			&& blockNum <= Cpm_kUserBlocksPerDisk + Cpm_kHeaderBlocksPerDisk
		) {
			i_blockBuf	= &(i_imageRec->image.cpm->header[blockNum - Cpm_kUserBlocksPerDisk]);
			i_recentBlockNum	= blockNum;
		} else if (blockNum >= Cpm_kUserBlocksPerDisk) {
			i_blockBuf			= NULL;
			i_recentBlockNum	= Cpm_kIllegalBlock;
			ReportErrorStr(blockNum, "Illegal CP/M Block access");
		} else {
			i_blockBuf			= Cpm_GetBlock(i_imageRec, blockNum);
			i_recentBlockNum	= blockNum;
		}
	}
	
	return i_blockBuf;
}

ulong		CDiskCpm::GetVolumeSize(void)
{
	return Cpm_kUserBlocksPerDisk * Cpm_kBytesPerBlock;
}

OSErr		CDiskCpm::SetBlock(void)
{
	OSErr		err = noErr;
	
	if (i_flushMemLevel == 1) {
		err = WriteImage(i_imageRec);
	}
	
	return err;
}

ADFS_IconType		CDiskCpm::GetIconType(void)
{
	return ADFS_Icon_CPM_SPRO + GetSectorOrderForIcon();
}

char		*CDiskCpm::GetDescription(char *buf)
{
	strcpy(buf, "CP/M Disk");
	return buf;
}

typedef struct {
	Cpm_BlockNum	testBlock;
	Boolean			isFreeB;
} Cpm_IsBlockFreeData;

static	OSErr	Cpm_IsBlockFreeCB(
	CFolderCpm			*thiz, 
	Cpm_DirEntry		*entryP, 
	Cpm_BlockNum		blockNum, 
	Cpm_EntryIndex		entryIndex, 
	Boolean				*doneB, 
	void				*data)
{
	OSErr					err			= noErr;
	Cpm_IsBlockFreeData		*freeData	= (Cpm_IsBlockFreeData *)data;
	
	if (entryP->userNumber != Cpm_kErasedSentinel) {
		Cpm_BlockNum		maxExtent, extentIndex;

		maxExtent = entryP->numRecords / Cpm_kRecordsPerBlock;
		
		for (
			extentIndex = 0; 
			!(*doneB) && extentIndex <= maxExtent; 
			extentIndex++
		) {
			if (entryP->extent[extentIndex] == freeData->testBlock) {
				freeData->isFreeB	= FALSE;
				*doneB				= TRUE;
			}
		}
	}
	
	return err;
}

OSErr			CDiskCpm::IsBlockFree(Cpm_BlockNum curBlock, Boolean *isFreeB)
{
	OSErr					err = noErr;
	Cpm_BlockNum			maxBlcok = 	Cpm_kDirEndBlock;
		
	if (curBlock <= maxBlcok) {
		*isFreeB = FALSE;
	} else {
		Cpm_IsBlockFreeData		freeData;
		
		freeData.testBlock	= curBlock;
		freeData.isFreeB	= TRUE;

		err = i_rootDir.cpm->Cpm_ForEachEntry(Cpm_IsBlockFreeCB, &freeData);

		if (!err) {
			*isFreeB = freeData.isFreeB;
		}
	}
		
	return err;
}

OSErr			CDiskCpm::Cpm_ForEachBitmapBlock(
	Cpm_ForEachBitmapBlockCB	ForEachBitmapBlockUserCB, 
	void						*data)
{
	OSErr				err = noErr;
	Cpm_BlockNum		curBlock;
	Boolean				isFreeB;
	Boolean				doneB = FALSE;
	
	for (
		curBlock = 0; 
		!err && !doneB && curBlock < Cpm_kUserBlocksPerDisk; 
		curBlock++
	) {
		err = IsBlockFree(curBlock, &isFreeB);
		
		if (!err) err = (*ForEachBitmapBlockUserCB)(
			this, curBlock, &isFreeB, &doneB, data);
	}
	
	return err;
}

enum	{
	Cpm_VBM_Select_NONE, 
	Cpm_VBM_Select_GET, 
	Cpm_VBM_Select_COUNT, 
	Cpm_VBM_Select_NUMTYPES
};
typedef	short	Cpm_VBM_SelectType;

typedef struct {
	Cpm_VBM_SelectType		selectType;
	Cpm_BlockNum			block;
	Boolean					free;
} Cpm_FreeBlockCBData;

static	OSErr	Cpm_FreeBlockCB(
	CDiskCpm		*thiz, 
	Cpm_BlockNum	block, 
	Boolean			*free, 
	Boolean			*done, 
	void			*data
) {
	OSErr					err = noErr;
	Cpm_FreeBlockCBData		*cbData = (Cpm_FreeBlockCBData *)data;
	
	switch (cbData->selectType) {

		case Cpm_VBM_Select_GET: {
			if (*free) {
				cbData->free	= TRUE;
				cbData->block	= block;
				*done			= TRUE;
			}
			break;
		}

		case Cpm_VBM_Select_COUNT: {
			if (*free == FALSE) {
				cbData->block++;
			}
			break;
		}

		default: {
			ReportErrorStr(-1, "Huh?");
			err = 1;
			break;
		}
	}

	return err;
}

ulong		CDiskCpm::GetVolumeBytesUsed(void)
{
	OSErr					err = noErr;
	Cpm_FreeBlockCBData		cbData;
	
	cbData.selectType	= Cpm_VBM_Select_COUNT;
	cbData.block		= 0;
	cbData.free			= FALSE;
	
	err = Cpm_ForEachBitmapBlock(Cpm_FreeBlockCB, &cbData);
	
	return cbData.block * sizeof(Cpm_Block);
}

OSErr		CDiskCpm::GetFreeBlock(Cpm_BlockNum *freeBlock)
{
	OSErr					err = noErr;
	Cpm_FreeBlockCBData		cbData;
//	Cpm_BlockNum			blockNum = 0;
	
	cbData.selectType	= Cpm_VBM_Select_GET;
	cbData.free			= FALSE;
	cbData.block		= 0;

	*freeBlock			= 0;
	
	err = Cpm_ForEachBitmapBlock(Cpm_FreeBlockCB, &cbData);

	if (err == noErr) {
		if (cbData.free) {
			*freeBlock = cbData.block;
		} else {
			err = IC_Err_DISK_FULL;
		}
	}
	
	return err;
}

static	OSErr	Cpm_ZeroBlockCB(
	CDiskCpm		*thiz, 
	Cpm_BlockNum	block, 
	Boolean			*free, 
	Boolean			*done, 
	void			*data)
{
	OSErr				err = noErr;
	
	if (*free) {
		Cpm_Block		*blockP;
		
		blockP = thiz->GetBlock(block);

		if (blockP == NULL) {
			err = IC_Err_READ_ILLEGAL_TRACK_SECTOR;
		} else {
			memfill(blockP, Cpm_kErasedSentinel, sizeof(Cpm_Block));
			err = thiz->SetBlock();
		}
	}

	return err;
}

static	OSErr	Cpm_ZeroEntryCB(
	CFolderCpm			*thiz, 
	Cpm_DirEntry		*entryP, 
	Cpm_BlockNum		blockNum, 
	Cpm_EntryIndex		entryIndex, 
	Boolean				*done, 
	void				*data)
{
	if (entryP->userNumber == Cpm_kErasedSentinel) {
		memfill(entryP, Cpm_kErasedSentinel, sizeof(Cpm_DirEntry));
	}
	
	return noErr;
}

OSErr		CDiskCpm::ZeroUnused(void)
{
	OSErr	err = noErr, err2;
	
	(void)FlushMemDisk(FALSE);
	err = Cpm_ForEachBitmapBlock(Cpm_ZeroBlockCB, NULL);
	
	if (!err) err = i_rootDir.cpm->Cpm_ForEachEntry(Cpm_ZeroEntryCB, NULL);
	
	err2 = FlushMemDisk(TRUE);
	if (!err) err = err2;
	
	return err;
}

ulong		CDiskCpm::GetVolumeMaxFileSize(ushort pro_fileTypeS)
{
	return Cpm_kMaxFileSize;
}

ulong		CDiskCpm::CalcBytesUsedByFile(ulong fileSize)
{
	return fileSize;
}

void			CDiskCpm::SetTwirled(Boolean twirledB)
{
	Cpm_DirEntry	*entryP = i_rootDir.cpm ? i_rootDir.cpm->GetEntry(0) : NULL;

	if (entryP) {
		Cpm_AccessBits			cpmBits = Cpm_GetAccessBits(entryP);
		
		Cpm_SetAccessBit(cpmBits, Cpm_kAccessBit_PUBLIC, twirledB);
		Cpm_SetAccessBits(entryP, cpmBits);
		(void)SetBlock();
	}
	
	_inherited::SetTwirled(twirledB);
}

Boolean			CDiskCpm::GetTwirled(void)
{
	Boolean			isTwirledB	= FALSE;
	Cpm_DirEntry	*entryP		= i_rootDir.cpm ? i_rootDir.cpm->GetEntry(0) : NULL;

	if (entryP) {
		Cpm_AccessBits			cpmBits = Cpm_GetAccessBits(entryP);
		
		isTwirledB = Cpm_GetAccessBit(cpmBits, Cpm_kAccessBit_PUBLIC);
	}

	return isTwirledB;
}

static	OSErr	Cpm_VerifyFreeSpaceCB(
	CFolderCpm			*thiz, 
	Cpm_DirEntry		*entryP, 
	Cpm_BlockNum		blockNum, 
	Cpm_EntryIndex		entryIndex, 
	Boolean				*doneB, 
	void				*data)
{
	OSErr		err				= noErr;
	ulong		*free_extentsLP	= (ulong *)data;
	
	if (entryP->userNumber == Cpm_kErasedSentinel) {
		(*free_extentsLP) += Cpm_kBlocksPerExtent * Cpm_kBytesPerBlock;
	}
	
	return err;
}

OSErr		CDiskCpm::VerifyFreeSpace(ulong sizeL)
{
	OSErr		err = _inherited::VerifyFreeSpace(sizeL);
	
	if (!err) {
		ulong		free_extentsL = 0;
		
		err = i_rootDir.cpm->Cpm_ForEachEntry(Cpm_VerifyFreeSpaceCB, &free_extentsL);
		
		if (free_extentsL < sizeL) {
			ReportError(err = IC_Err_DIRECTORY_FULL);
		}
	}
	
	return err;
}

CFileCpm		*CDiskCpm::GetFileFromEntry(Cpm_DirEntry *entryP)
{
	EntryIndex		maxIndex = i_rootDir.cpm->CountEntries();
	EntryIndex		curIndex;
	CFileCpm		*fileP = NULL, *curFileP;
	Cpm_DirEntry	*curEntryP;
	
	for (curIndex = 0; curIndex < maxIndex; curIndex++) {
		curFileP = (CFileCpm *)i_rootDir.cpm->GetIndEntry(curIndex);
		
		if (curFileP) {
			curEntryP = curFileP->GetMyEntry();
			
			if (curEntryP == entryP) {
				fileP = curFileP;
				break;
			}
		}
	}
	
	return fileP;
}

Cpm_DirEntry	*CDiskCpm::ScanForNextEmpty(
	Cpm_DirEntry	*entryP, 
	Cpm_EntryIndex	*offsetP,
	Cpm_DirEntry	**lastRealEntryPP)
{
	Boolean		doneB = FALSE;
	
	*lastRealEntryPP = NULL;
	
	do {
		if (entryP->userNumber == Cpm_kErasedSentinel) {
			doneB = TRUE;
		} else {
			if (entryP->extentNum == 0) {
				*lastRealEntryPP = entryP;
			}
			
			(*offsetP)++;
			entryP++;
		}
	} while (!doneB);
	
	return entryP;
}


OSErr		CDiskCpm::Cpm_GetNextFreeExtentAlloc(
	Cpm_DirEntry	**entryPP, 
	Cpm_BlockNum	**blockNumPP)
{
	OSErr			err = noErr;
	Cpm_DirEntry	*entryP = *entryPP;
	Cpm_DirEntry	recentEntry;
	Boolean			doneB = FALSE;
	
	if (!(	//	if we didn't JUST allocate the file (empty)
		entryP->userNumber == Cpm_kUserNumber 
		&& entryP->numRecords == 0 
		&& entryP->extentNum == 0
		&& entryP->extent[0] == Cpm_kErasedSentinel)
	) {
		do {
			recentEntry	= **entryPP;
			
			doneB = entryP->numRecords != Cpm_kRecordsPerExtent;
			
			if (!doneB) {
				(*entryPP)++;
				entryP = *entryPP;
				doneB = entryP->userNumber == Cpm_kErasedSentinel || entryP->extentNum != recentEntry.extentNum + 1;
			}
		} while (!doneB);

		if (entryP->userNumber == Cpm_kErasedSentinel) {
			*entryP = recentEntry;
			(entryP->extentNum)++;
			entryP->numRecords = 0;
		} else if (
			entryP->numRecords != Cpm_kRecordsPerExtent
		) {
			//	i'm adding another block to this extent
			err = ASSERT(entryP->numRecords % Cpm_kRecordsPerBlock == 0);
		} else if (entryP->extentNum != recentEntry.extentNum + 1) {
			CFileCpm			*origFileP, *firstFileP, *lastFileP;
			Cpm_DirEntry		*lastRealEntryP, *nextEmptyP;
			Cpm_EntryIndex		dirEntriesL		= 0;
			ulong				scrunchEntriesL	= recentEntry.extentNum + 1;
			ulong				scrunchSizeL	= sizeof(Cpm_DirEntry) * scrunchEntriesL;
			Cpm_DirEntry		*scrunchP		= (Cpm_DirEntry *)TrackNewPtr("CP/M Scrunch", scrunchSizeL);
				
			if (scrunchP == NULL) {
				ReportError(err = IC_Err_OUT_OF_MEMORY);
			}
			
			if (!err) {
				origFileP	= GetFileFromEntry(*entryPP);
				firstFileP	= GetFileFromEntry(entryP);
				
				if (origFileP == NULL || firstFileP == NULL) {
					err = IC_Err_ENTRY_NOT_FOUND;
				}
			}
				
			if (!err) {
				memcpy(scrunchP, *entryPP, scrunchSizeL);
				
				nextEmptyP = ScanForNextEmpty(entryP, &dirEntriesL, &lastRealEntryP);
				ASSERT(lastRealEntryP);
				lastFileP = GetFileFromEntry(lastRealEntryP);
				
				if (nextEmptyP == NULL) {
					err = IC_Err_ENTRY_NOT_FOUND;
				}
			}
			
			if (!err) {
				memmove(*entryPP, entryP, (ulong)nextEmptyP - (ulong)entryP);
				*entryPP	= (Cpm_DirEntry *)((ulong)nextEmptyP - scrunchSizeL);
				entryP		= *entryPP;
				memcpy(entryP, scrunchP, scrunchSizeL);
				

				if (lastFileP == NULL) {
					err = IC_Err_ENTRY_NOT_FOUND;
				}
			}
				
			if (!err) err = i_rootDir.cpm->OffsetEachFile(firstFileP, lastFileP, -scrunchEntriesL);
			if (!err) err = i_rootDir.cpm->OffsetEachFile(origFileP, origFileP, dirEntriesL);
			
			if (!err) {
				(*entryPP)++;
				entryP		= *entryPP;
				
				*entryP = recentEntry;
				(entryP->extentNum)++;
				entryP->numRecords = 0;
			}
			
			if (scrunchP) {
				TrackDisposePtr((Ptr)scrunchP);
			}
		} else {
			err = ASSERT(entryP->extentNum == recentEntry.extentNum + 1);
		}
	}
	
	if (!err) {
		err = ASSERT((entryP->numRecords % Cpm_kRecordsPerBlock) == 0);
		
		if (!err)  {
			*blockNumPP = &entryP->extent[entryP->numRecords / Cpm_kRecordsPerBlock];
		}
	}
	
	return err;
}

void	Cpm_EraseDisk(DiskImageRec *imageRecP)
{
	Cpm_BlockNum	curBlock;
	Cpm_Block		*blockP;
	short			curByte;
	
	for (curBlock = 0; curBlock < Cpm_kUserBlocksPerDisk; curBlock++) {
		blockP	= Cpm_GetBlock(imageRecP, curBlock);
		
		for (curByte = 0; curByte < Cpm_kBytesPerBlock; curByte++) {
			blockP->byte[curByte] = Cpm_kErasedSentinel;
		}
	}
}

void		Cpm_SanitizeName(char *nameZ)
{
	if (nameZ[0] == 0) {
		nameZ[0] = 'A';
		nameZ[1] = 0;
	} else {
		short			lenS = strlen(nameZ);
		short			indexS;
		char			*charP;

		charP = &nameZ[0];
		*charP = toupper(*charP);

		if (*charP < 'A' && *charP > 'Z') {
			*charP = 'A';	//	first char must be letter
		}

		for (
			indexS = 1;
			indexS < lenS;
			indexS++
		) {
			charP = &nameZ[indexS];
			*charP = toupper(*charP);
			
			//	illegal becomes an underscore
			if (!(
				(*charP >= 'A' && *charP <= 'Z')
				|| (*charP >= '0' && *charP <= '9'))
			) {
				*charP = '_';
			}
		}
	}
}

/***************************************************/
ushort					CDiskCpm::GetSectorsPerBlock(void)
{
	return Cpm_kSectorsPerBlock;
}

ushort					CDiskCpm::GetBlocksPerTrack(void)
{
	return Cpm_kBlocksPerTrack;
}

Gen_AllocSizeType		CDiskCpm::GetAllocSize(void)
{
	return Gen_AllocSize_BYTE;
}

typedef struct {
	Boolean			getAsBlocksB;
	Cpm_BlockNum	*numFreeSP;
	Cpm_BlockNum	*blockA0;
} Cpm_GetBlockMapRec;

static	OSErr	Cpm_GetBlockMap(
	CDiskCpm		*thiz, 
	Cpm_BlockNum	block, 
	Boolean			*free, 
	Boolean			*done, 
	void			*data
) {
	Cpm_GetBlockMapRec		*blockMapP = (Cpm_GetBlockMapRec *)data;
	
	if (*free) {
		if (blockMapP->blockA0) {
			blockMapP->blockA0[*(blockMapP->numFreeSP)] = block + Cpm_kHeaderBlocksPerDisk;
		}
		
		(*(blockMapP->numFreeSP))++;
	}
	
	return noErr;
}

#define		GetEmptyBlocks(_max, _list)		GetUnAllocBlocks(getAsBlocksB, _max, _list)

OSErr		CDiskCpm::GetUnAllocBlocks(
	Boolean			getAsBlocksB,
	Cpm_BlockNum	*maxEmptyS, 
	Cpm_BlockNum	*blockListA)
{
	OSErr					err = noErr;
	Cpm_GetBlockMapRec		blockMapRec;
	
	blockMapRec.getAsBlocksB	= getAsBlocksB;
	blockMapRec.numFreeSP		= maxEmptyS;
	blockMapRec.blockA0			= blockListA;
	err = Cpm_ForEachBitmapBlock(Cpm_GetBlockMap, &blockMapRec);
	
	return err;
}

OSErr		CDiskCpm::GetEntryAlloc(
	Boolean			getAsBlocksB, 
	Gen_EntryAlloc	**sectorListH)
{
	OSErr			err = noErr;
	Cpm_BlockNum	*blockNumP, curBlockS, maxEmptyS;
	
	*sectorListH	= (Gen_EntryAlloc *)TrackNewPtrClear(
		"entry sectors, for disk", sizeof(Gen_EntryAlloc));
	
	if (*sectorListH == NULL) err = memFullErr;
	
	if (!err) {		
		(**sectorListH).allocSize = getAsBlocksB ? GetAllocSize() : Gen_AllocSize_SECTORS;
		
		blockNumP = (Cpm_BlockNum *)TrackNewPtrClear(
			"entry sectors, boot blocks", 
			sizeof(Cpm_BlockNum) * Cpm_kHeaderBlocksPerDisk);
		
		if (blockNumP == NULL) err = memFullErr;
	}
	
	if (!err) {
		(**sectorListH).type[Gen_Alloc_BOOT].totalS		= Cpm_kHeaderBlocksPerDisk;
		(**sectorListH).type[Gen_Alloc_BOOT].u.byte_blocksA	= blockNumP;
		for (curBlockS = 0; curBlockS < Cpm_kHeaderBlocksPerDisk; curBlockS++) {
			blockNumP[curBlockS] = curBlockS;
		}

		blockNumP = (Cpm_BlockNum *)TrackNewPtrClear(
			"entry sectors, directory blocks", 
			sizeof(Cpm_BlockNum) * Cpm_kNumDirBlocks);

		if (blockNumP == NULL) err = memFullErr;
	}
	
	if (!err) {
		(**sectorListH).type[Gen_Alloc_DIRECTORY].totalS	= Cpm_kNumDirBlocks;
		(**sectorListH).type[Gen_Alloc_DIRECTORY].u.byte_blocksA	= blockNumP;
		for (curBlockS = 0; curBlockS < Cpm_kNumDirBlocks; curBlockS++) {
			blockNumP[curBlockS] = curBlockS + Cpm_kHeaderBlocksPerDisk;
		}
	}
	
	//	no volume bitmap in a CPM disk, so skip right to empty blocks

	maxEmptyS = 0;
	if (!err) err = GetEmptyBlocks(&maxEmptyS, NULL);
			
	if (!err && maxEmptyS) {
		blockNumP = (Cpm_BlockNum *)TrackNewPtrClear(
			"entry sectors, free blocks", 
			sizeof(Cpm_BlockNum) * maxEmptyS);
		
		if (blockNumP == NULL) err = memFullErr;

		if (!err) {
			(**sectorListH).type[Gen_Alloc_NONE].totalS	= maxEmptyS;
			(**sectorListH).type[Gen_Alloc_NONE].u.byte_blocksA	= blockNumP;

			maxEmptyS = 0;
			if (!err) err = GetEmptyBlocks(&maxEmptyS, blockNumP);
		}
	}

	if (!err && !getAsBlocksB) {
		err = EntryBlocksToSectors(*sectorListH);
	}
	
	if (err) {
		DisposeEntryAlloc(*sectorListH);
		*sectorListH = NULL;
	}
	
	return err;
}

OSErr		CDiskCpm::NewDisk_Completion(ADFS_NewDiskCompletionRec *recP)
{
	OSErr		err = noErr;
	
	//	can't set the name of a cpm disk yet
	//err = _inherited::NewDisk_Completion(recP);
	if (!err) {
		CFolderCpm	*folderP	= i_rootDir.cpm;

		if (!recP->newDiskRecP->bootableB) {
			CEntry		*entryP;
			
			recP->copyDialogP->IncrementProgress(FALSE, gProgStrs[ADFS_NewDiskProg_DELETE_BOOT]);
			
			entryP = folderP->GetIndEntry(2);
			if (entryP) entryP->Delete();
			
			entryP = folderP->GetIndEntry(1);
			if (entryP) entryP->Delete();
			
			entryP = folderP->GetIndEntry(0);
			if (entryP) entryP->Delete();
			
			recP->copyDialogP->IncrementProgress(FALSE, gProgStrs[ADFS_NewDiskProg_ZERO]);
			ZeroUnused();
		}
	}
	
	return err;
}
