[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Looking for info on ProDOS disk format...
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