I too am interested in open-sourcing my code for accessing ProDOS disks. The code I have is complete AFAIK, handles reading, writing, sparse files, forked files, the whole nine yards. as an example, here's the ProDOS header: if anybody wants more info, feel free to write. my project runs on the mac, and supports DOS 3.3, CP/M and Pascal as well, and you can drag and drop exchange with the Finder. http://www.lazilong.com/apple_II/adfs/ // ProStructs.h #ifndef _H_ProStructs #define _H_ProStructs #include "FileSystemTypes.h" #include "ProDiskLocSpec.h" #pragma options align = packed /***********************************************************/ // disk structs #define Pro_kBytesPerBlock 512L // 0x0200L #define Pro_kShortsPerBlock (Pro_kBytesPerBlock >> 1) #define Pro_kLongsPerBlock (Pro_kBytesPerBlock >> 2) // 140k disk stuff #define Pro_kBlocksPerDisk 280L // 0x0118L #define Pro_kSectorsPerBlock 2L #define Pro_kBlocksPerTrack 8L #define Pro_kBlocksPerDisk400 800L #define Pro_kBlocksPerDisk800 1600L #define Pro_kBlocksPerDisk1440 2880L #define Pro_kBlocksPerDisk5M 10240L #define Pro_kBlocksPerDisk10M 20480L #define Pro_kBlocksPerDisk15M 30720L #define Pro_kBlocksPerDisk20M 40960L #define Pro_kBlocksPerDisk32M 65535L #define Pro_kDirStartBlock 2 #define Pro_kEntryLen 39 #define Pro_kEntriesPerVolDir 51L #define Pro_kNumBootBlocks 2L #define Pro_kNumDirBlocks 4L typedef unsigned short Pro_BlockNum; // disk structs typedef struct Pro_Block { Byte byte[Pro_kBytesPerBlock]; } Pro_Block; typedef struct { ushort data[Pro_kShortsPerBlock]; } Pro_ShortBlock; typedef struct Pro_HalfBlock { Byte byte[Pro_kShortsPerBlock]; } Pro_HalfBlock; typedef struct { Pro_HalfBlock low; Pro_HalfBlock high; } Pro_IndexBlock; typedef unsigned long Pro_BitMapBlock[Pro_kLongsPerBlock]; #define Pro_kFreeBlock 1 #define Pro_kUsedBlock 0 typedef struct Pro_Disk { Pro_Block block[Pro_kBlocksPerDisk]; } Pro_Disk; typedef struct Pro_Disk800 { Pro_Block block[Pro_kBlocksPerDisk800]; } Pro_Disk800; typedef struct Pro_Disk1440 { Pro_Block block[Pro_kBlocksPerDisk1440]; } Pro_Disk1440; #define kPro_Disk140_Size sizeof(Pro_Disk) #define kPro_Disk800_Size sizeof(Pro_Disk800) #define kPro_Disk1440_Size sizeof(Pro_Disk1440) /***********************************************************/ // date and time typedef union { struct { short ymd; short hm; } split; struct { unsigned short year : 7; unsigned short month : 4; unsigned short day : 5; unsigned short unused1 : 3; unsigned short hour : 5; unsigned short unused2 : 2; unsigned short minute : 6; } dt; } Pro_DateTimeMem; typedef struct { RboShort ymd; RboShort hm; } Pro_DateTime; /***********************************************************/ // block list typedef struct { Pro_BlockSpec previous; Pro_BlockSpec next; } Pro_BlockListNode; /***********************************************************/ // Storage Type, Name Length, File Name enum { Pro_Storage_INACTIVE, Pro_Storage_SEEDLING, Pro_Storage_SAPLING, Pro_Storage_TREE, Pro_Storage_PASCAL, Pro_Storage_FORKED, // forked Pro_Storage_SUBDIR_FILE = 0x0D, Pro_Storage_SUBDIR_HEADER, Pro_Storage_VOL_HEADER }; typedef unsigned char Pro_StorageType; typedef struct { Pro_StorageType storageType : 4; unsigned char nameLength : 4; } Pro_StorTypNamLen; // file name #define Pro_kNameLength 15 typedef char Pro_FileName[Pro_kNameLength]; typedef char Pro_FileNameStr[Pro_kNameLength + 1]; typedef struct { Pro_StorTypNamLen stnl; Pro_FileName name; } Pro_TypeName; #define Pro_kUseLocaseBits 0x8000 /***********************************************************/ // Extended (forked) file info enum { Pro_ForkFInfoEntry_NONE, Pro_ForkFInfoEntry_FInfo, Pro_ForkFInfoEntry_FXInfo }; typedef Byte Pro_ForkFInfoEntryType; #define Pro_ForkFInfoSize 16 // must be 16 bytes long #define Pro_ForkFInfoEntrySize (Pro_ForkFInfoSize + 2) // must be 18 bytes long typedef struct { Byte entrySize; // == Pro_ForkFInfoEntrySize Pro_ForkFInfoEntryType entryType; char fInfo[Pro_ForkFInfoSize]; // MacOS Finder Info } Pro_ForkFInfo; typedef struct { unsigned char reserved : 4; Pro_StorageType storageType : 4; } Pro_LowStorType; typedef struct { Pro_LowStorType lowStorType; Pro_BlockSpec key; RboShort blocksUsed; Rbo3Byte eof; // only the data fork has the following extra fields, in // the res fork, it's all zeroes Pro_ForkFInfo fInfo1; Pro_ForkFInfo fInfo2; Byte unused[212]; } Pro_ForkEntry; typedef struct { Pro_ForkEntry data; Pro_ForkEntry resource; } Pro_ExtendedIndexBlock; /***********************************************************/ // access privileges #define Pro_kUseOldTwirlDown TRUE typedef unsigned char Pro_AccessPrivMem; typedef struct { Pro_AccessPrivMem destroyEnable : 1; // 0x80 Pro_AccessPrivMem renameEnable : 1; // 0x40 Pro_AccessPrivMem backup : 1; // 0x20 #if Pro_kUseOldTwirlDown Pro_AccessPrivMem unused0 : 1; #else Pro_AccessPrivMem twirledDownB : 1; #endif Pro_AccessPrivMem unused1 : 2; Pro_AccessPrivMem writeEnable : 1; // 0x02 Pro_AccessPrivMem readEnable : 1; // 0x01 } Pro_AccessPriv; extern Pro_AccessPriv Pro_kAccess_FOLDER; extern Pro_AccessPriv Pro_kAccess_UNLOCKED; extern Pro_AccessPriv Pro_kAccess_LOCKED; extern Pro_FileNameStr Pro_kUntitledFolderStr; extern Pro_FileNameStr Pro_kUntitledFileStr; /***********************************************************/ // directory header typedef struct { Pro_TypeName typeName; RboShort unknown; // vol = 0x00, dir = 0x75 (117d) Pro_DateTime modifiedTime; RboShort locaseBits; Pro_DateTime createdTime; Byte version; Byte minVersion; Pro_AccessPriv access; Byte entryLen; Byte entriesPerBlock; RboShort fileCount; union { struct { Pro_BlockSpec bitMap; RboShort totalBlocks; } volume; struct { Pro_BlockSpec parent; Byte parentEntryNum; Byte parentEntryLength; } directory; } headerType; } Pro_DirHeader; /***********************************************************/ // Directory entry typedef Byte Pro_FileType; #define Pro_FileType_BINA ((Pro_FileType)0x00) #define Pro_FileType_BAD ((Pro_FileType)0x01) // bad blocks #define Pro_FileType_PCD ((Pro_FileType)0x02) // Pascal code #define Pro_FileType_PTX ((Pro_FileType)0x03) // Pascal text #define Pro_FileType_TXT ((Pro_FileType)0x04) #define Pro_FileType_PDA ((Pro_FileType)0x05) // Pascal data #define Pro_FileType_BIN ((Pro_FileType)0x06) #define Pro_FileType_FNT ((Pro_FileType)0x07) #define Pro_FileType_DIR ((Pro_FileType)0x0F) #define Pro_FileType_AWD ((Pro_FileType)0x19) #define Pro_FileType_AWP ((Pro_FileType)0x1A) #define Pro_FileType_AWS ((Pro_FileType)0x1B) #define Pro_FileType_S16 ((Pro_FileType)0xB3) #define Pro_FileType_INT ((Pro_FileType)0xFA) #define Pro_FileType_BAS ((Pro_FileType)0xFC) #define Pro_FileType_REL ((Pro_FileType)0xFE) #define Pro_FileType_SYS ((Pro_FileType)0xFF) typedef struct { Pro_TypeName typeName; Pro_FileType fileType; Pro_BlockSpec key; RboShort blocksUsed; Rbo3Byte eof; Pro_DateTime createdTime; RboShort locaseBits; Pro_AccessPriv access; RboShort auxType; Pro_DateTime modifiedTime; Pro_BlockSpec header; } Pro_DirEntry; /***********************************************************/ // Directory block typedef short Pro_EntryIndex; #define Pro_kMaxEntriesPerBlock 13 typedef struct { Pro_BlockListNode list; union { Pro_TypeName typeName; struct { Pro_DirHeader header; Pro_DirEntry entry[Pro_kMaxEntriesPerBlock - 1]; } key; struct { Pro_DirEntry entry[Pro_kMaxEntriesPerBlock]; } standard; } blockType; #if Pro_kUseOldTwirlDown Byte twirledDownB; #else Byte unused; #endif } Pro_DirBlock; /***********************************************************/ // Entry location specification typedef struct { Pro_BlockNum block; Pro_EntryIndex entryIndex; // within block (zero based) Pro_EntryIndex dirIndex; // within directory (one based) } Pro_EntryLocSpec; #pragma options align = reset Boolean Pro_IsPro(DiskImageRec *imageRec); OSErr Pro_GetBlock(DiskImageRec *imageRec, Pro_BlockNum blockNum, Pro_Block **blockP); #endif