/*
 *  adf_blk.h - general blocks structures
 *
 *  Copyright (C) 1997-2022 Laurent Clevy
 *                2023-2025 Tomasz Wolak
 *
 *  This file is part of ADFLib.
 *
 *  ADFLib is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  ADFLib is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with ADFLib; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifndef ADF_BLK_H
#define ADF_BLK_H

#include "adf_types.h"


#define ADF_LOGICAL_BLOCK_SIZE  512

/* ----- FILE SYSTEM ----- */

/*
 * Filesystem type, defined in volume's bootblock as "DOSn"
 * where bitmasked n has the meaning as below.
 * ( see also: http://lclevy.free.fr/adflib/adf_info.html#p41 )
 */
#define ADF_DOSFS_OFS         0   /* 000 */
#define ADF_DOSFS_FFS         1   /* 001 */
#define ADF_DOSFS_INTL        2   /* 010 */
#define ADF_DOSFS_DIRCACHE    4   /* 100 */

static inline bool adfDosFsIsFFS( const uint8_t c ) {
    return c & ADF_DOSFS_FFS;
}

static inline bool adfDosFsIsOFS( const uint8_t c ) {
    return ! adfDosFsIsFFS( c );
}

static inline bool adfDosFsHasINTL( const uint8_t c ) {
    return c & ADF_DOSFS_INTL;
}

static inline bool adfDosFsHasDIRCACHE( const uint8_t c ) {
    return c & ADF_DOSFS_DIRCACHE;
}


/* ----- ENTRIES ----- */

/* access constants */

#define ADF_ACCMASK_D	( 1 << 0 )
#define ADF_ACCMASK_E	( 1 << 1 )
#define ADF_ACCMASK_W	( 1 << 2 )
#define ADF_ACCMASK_R	( 1 << 3 )
#define ADF_ACCMASK_A	( 1 << 4 )
#define ADF_ACCMASK_P	( 1 << 5 )
#define ADF_ACCMASK_S	( 1 << 6 )
#define ADF_ACCMASK_H	( 1 << 7 )

#define ADF_ACCMASK_GD	( 1 << 8 )
#define ADF_ACCMASK_GE	( 1 << 9 )
#define ADF_ACCMASK_GW	( 1 << 10 )
#define ADF_ACCMASK_GR	( 1 << 11 )

#define ADF_ACCMASK_OD	( 1 << 12 )
#define ADF_ACCMASK_OE	( 1 << 13 )
#define ADF_ACCMASK_OW	( 1 << 14 )
#define ADF_ACCMASK_OR	( 1 << 15 )

static inline bool adfAccHasD( const int32_t c )  { return c & ADF_ACCMASK_D; }
static inline bool adfAccHasE( const int32_t c )  { return c & ADF_ACCMASK_E; }
static inline bool adfAccHasW( const int32_t c )  { return c & ADF_ACCMASK_W; }
static inline bool adfAccHasR( const int32_t c )  { return c & ADF_ACCMASK_R; }
static inline bool adfAccHasA( const int32_t c )  { return c & ADF_ACCMASK_A; }
static inline bool adfAccHasP( const int32_t c )  { return c & ADF_ACCMASK_P; }
static inline bool adfAccHasS( const int32_t c )  { return c & ADF_ACCMASK_S; }
static inline bool adfAccHasH( const int32_t c )  { return c & ADF_ACCMASK_H; }

static inline bool adfAccHasGD( const int32_t c )  { return c & ADF_ACCMASK_GD; }
static inline bool adfAccHasGE( const int32_t c )  { return c & ADF_ACCMASK_GE; }
static inline bool adfAccHasGW( const int32_t c )  { return c & ADF_ACCMASK_GW; }
static inline bool adfAccHasGR( const int32_t c )  { return c & ADF_ACCMASK_GR; }

static inline bool adfAccHasOD( const int32_t c )  { return c & ADF_ACCMASK_OD; }
static inline bool adfAccHasOE( const int32_t c )  { return c & ADF_ACCMASK_OE; }
static inline bool adfAccHasOW( const int32_t c )  { return c & ADF_ACCMASK_OW; }
static inline bool adfAccHasOR( const int32_t c )  { return c & ADF_ACCMASK_OR; }


/* ----- BLOCKS ----- */

/* block constants */

#define ADF_BM_VALID            -1
#define ADF_BM_INVALID           0

#define ADF_HT_SIZE             72
#define ADF_BM_PAGES_ROOT_SIZE  25
#define ADF_BM_PAGES_EXT_SIZE  127
#define ADF_BM_MAP_SIZE        127
#define ADF_MAX_DATABLK         72

#define ADF_MAX_NAME_LEN        30
#define ADF_MAX_COMMENT_LEN     79


/* block primary and secondary types */

#define ADF_T_HEADER    2
#define ADF_ST_ROOT     1
#define ADF_ST_DIR      2
#define ADF_ST_FILE    -3
#define ADF_ST_LFILE   -4
#define ADF_ST_LDIR     4
#define ADF_ST_LSOFT    3
#define ADF_T_LIST     16
#define ADF_T_DATA      8
#define ADF_T_DIRC     33


/*
 * ------------- block structures -------------
 */


/*--- boot block structure ---*/

struct AdfBootBlock {
/*000*/	char      dosType[ 4 ];
/*004*/	uint32_t  checkSum;
/*008*/	int32_t	  rootBlock;
/*00c*/	uint8_t   data[ 500 + 512 ];
};


/*--- root block structure ---*/

struct AdfRootBlock {
/*000*/	int32_t	  type;
        int32_t	  headerKey;
        int32_t	  highSeq;
/*00c*/	int32_t	  hashTableSize;
        int32_t	  firstData;
/*014*/	uint32_t  checkSum;
/*018*/	int32_t	  hashTable[ ADF_HT_SIZE ];       /* hash table */
/*138*/	int32_t	  bmFlag;        /* bitmap flag, -1 means VALID */
/*13c*/	int32_t	  bmPages[ ADF_BM_PAGES_ROOT_SIZE ];
/*1a0*/	int32_t	  bmExt;
/*1a4*/	int32_t	  cDays;         /* creation date FFS and OFS */
/*1a8*/	int32_t	  cMins;
/*1ac*/	int32_t	  cTicks;
/*1b0*/	uint8_t	  nameLen;
/*1b1*/	char 	  diskName[ ADF_MAX_NAME_LEN + 1 ];
        char	  r2[ 8 ];
/*1d8*/	int32_t	  days;          /* last access : days after 1 jan 1978 */
/*1dc*/	int32_t	  mins;          /* hours and minutes in minutes */
/*1e0*/	int32_t	  ticks;         /* 1/50 seconds */
/*1e4*/	int32_t	  coDays;        /* creation date OFS */
/*1e8*/	int32_t	  coMins;
/*1ec*/	int32_t	  coTicks;
        int32_t	  nextSameHash;  /* == 0 */
        int32_t	  parent;        /* == 0 */
/*1f8*/	int32_t	  extension;     /* FFS: first directory cache block */
/*1fc*/	int32_t	  secType;       /* == 1 */
};


/*--- dir. entry block structure ---*/

struct AdfEntryBlock {
/*000*/	int32_t	  type;       /* ADF_T_HEADER == 2 */
/*004*/	int32_t	  headerKey;  /* current block number */
        int32_t	  r1[ 3 ];
/*014*/	uint32_t  checkSum;
/*018*/	int32_t	  hashTable[ ADF_HT_SIZE ];
        int32_t	  r2[ 2 ];
/*140*/	int32_t	  access;     /* bit0 = del, 1 = modif, 2 = write, 3 = read */
/*144*/	uint32_t  byteSize;
/*148*/	uint8_t	  commLen;
/*149*/	char	  comment[ ADF_MAX_COMMENT_LEN + 1 ];
        char	  r3[ 91 - ( ADF_MAX_COMMENT_LEN + 1 ) ];
/*1a4*/	int32_t	  days;
/*1a8*/	int32_t	  mins;
/*1ac*/	int32_t	  ticks;
/*1b0*/	uint8_t	  nameLen;
/*1b1*/	char	  name[ ADF_MAX_NAME_LEN + 1 ];
        int32_t	  r4;
/*1d4*/	int32_t	  realEntry;
/*1d8*/	int32_t	  nextLink;
        int32_t	  r5[ 5 ];
/*1f0*/	int32_t	  nextSameHash;
/*1f4*/	int32_t	  parent;
/*1f8*/	int32_t	  extension;
/*1fc*/	int32_t	  secType;
};


/*--- file header block structure ---*/

struct AdfFileHeaderBlock {
/*000*/	int32_t	  type;          /* == 2 */
/*004*/	int32_t	  headerKey;     /* current block number */
/*008*/	int32_t	  highSeq;       /* number of data block in this hdr block */
/*00c*/	int32_t	  dataSize;      /* == 0 */
/*010*/	int32_t	  firstData;
/*014*/	uint32_t  checkSum;
/*018*/	int32_t   dataBlocks[ ADF_MAX_DATABLK ];
/*138*/	int32_t   r1;
/*13c*/	int32_t   r2;
/*140*/	int32_t   access;        /* bit0 = del, 1 = modif, 2 = write, 3 = read */
/*144*/	uint32_t  byteSize;
/*148*/	uint8_t	  commLen;
/*149*/	char      comment[ ADF_MAX_COMMENT_LEN + 1 ];
        char      r3[ 91 - ( ADF_MAX_COMMENT_LEN + 1 ) ];
/*1a4*/	int32_t   days;
/*1a8*/	int32_t   mins;
/*1ac*/	int32_t   ticks;
/*1b0*/	uint8_t   nameLen;
/*1b1*/	char      fileName[ ADF_MAX_NAME_LEN + 1 ];
        int32_t   r4;
/*1d4*/	int32_t   real;          /* unused == 0 */
/*1d8*/	int32_t   nextLink;      /* link chain */
        int32_t   r5[ 5 ];
/*1f0*/	int32_t   nextSameHash;  /* next entry with sane hash */
/*1f4*/	int32_t   parent;        /* parent directory */
/*1f8*/	int32_t   extension;     /* pointer to extension block */
/*1fc*/	int32_t   secType;       /* == -3 */
};


/*--- file header extension block structure ---*/

struct AdfFileExtBlock {
/*000*/	int32_t   type;          /* == 0x10 */
/*004*/	int32_t   headerKey;
/*008*/	int32_t   highSeq;
/*00c*/	int32_t   dataSize;      /* == 0 */
/*010*/	int32_t   firstData;     /* == 0 */
/*014*/	uint32_t  checkSum;
/*018*/	int32_t   dataBlocks[ ADF_MAX_DATABLK ];
        int32_t   r[ 45 ];
        int32_t   info;          /* == 0 */
        int32_t   nextSameHash;  /* == 0 */
/*1f4*/	int32_t   parent;        /* header block */
/*1f8*/	int32_t   extension;     /* next header extension block */
/*1fc*/	int32_t   secType;       /* -3 */
};


/*--- directory block structure ---*/

struct AdfDirBlock {
/*000*/	int32_t   type;                      /* == 2 */
/*004*/	int32_t   headerKey;
/*008*/	int32_t   highSeq;                   /* == 0 */
/*00c*/	int32_t   hashTableSize;             /* == 0 */
        int32_t   r1;                        /* == 0 */
/*014*/	uint32_t  checkSum;
/*018*/	int32_t   hashTable[ ADF_HT_SIZE ];  /* hash table */
        int32_t   r2[ 2 ];
/*140*/	int32_t   access;
        int32_t   r4;                        /* == 0 */
/*148*/	uint8_t   commLen;
/*149*/	char      comment[ ADF_MAX_COMMENT_LEN + 1 ];
        char      r5[ 91 - ( ADF_MAX_COMMENT_LEN + 1 ) ];
/*1a4*/	int32_t   days;                      /* last access */
/*1a8*/	int32_t   mins;
/*1ac*/	int32_t   ticks;
/*1b0*/	uint8_t   nameLen;
/*1b1*/	char      dirName[ ADF_MAX_NAME_LEN + 1 ];
        int32_t   r6;
/*1d4*/	int32_t   real;                      /* == 0 */
/*1d8*/	int32_t   nextLink;                  /* link list */
        int32_t   r7[ 5 ];
/*1f0*/	int32_t   nextSameHash;
/*1f4*/	int32_t   parent;
/*1f8*/	int32_t   extension;                 /* FFS : first directory cache */
/*1fc*/	int32_t   secType;                   /* == 2 */
};


/*--- OFS data block structure ---*/

struct AdfOFSDataBlock {
/*000*/	int32_t   type;         /* == 8 */
/*004*/	int32_t   headerKey;    /* pointer to file_hdr block */
/*008*/	uint32_t  seqNum;       /* file data block number */
/*00c*/	uint32_t  dataSize;     /* <= 0x1e8 */
/*010*/	int32_t   nextData;     /* next data block */
/*014*/	uint32_t  checkSum;
/*018*/	uint8_t   data[ 488 ];
/*200*/
};


/* --- bitmap block structure --- */

struct AdfBitmapBlock {
/*000*/	uint32_t  checkSum;
/*004*/	uint32_t  map[ ADF_BM_MAP_SIZE ];
};


/* --- bitmap extension block structure --- */

struct AdfBitmapExtBlock {
/*000*/	int32_t  bmPages[ ADF_BM_PAGES_EXT_SIZE ];
/*1fc*/	int32_t  nextBlock;
};


/* --- link block structure --- */

struct AdfLinkBlock {
/*000*/	int32_t   type;         /* == 2 */
/*004*/	int32_t   headerKey;    /* self pointer */
        int32_t   r1[ 3 ];
/*014*/	uint32_t  checkSum;
/*018*/	char      realName[ 64 ];
        int32_t   r2[ 83 ];
/*1a4*/	int32_t   days;         /* last access */
/*1a8*/	int32_t   mins;
/*1ac*/	int32_t   ticks;
/*1b0*/	uint8_t   nameLen;
/*1b1*/	char      name[ ADF_MAX_NAME_LEN + 1 ];
        int32_t   r3;
/*1d4*/	int32_t   realEntry;
/*1d8*/	int32_t   nextLink;
        int32_t   r4[ 5 ];
/*1f0*/	int32_t   nextSameHash;
/*1f4*/	int32_t   parent;
        int32_t   r5;
/*1fc*/	int32_t   secType;      /* == -4, 4, 3 */
};


/*--- directory cache block structure ---*/

struct AdfDirCacheBlock {
/*000*/	int32_t   type;		/* == 33 */
/*004*/	int32_t   headerKey;
/*008*/	int32_t   parent;
/*00c*/	int32_t   recordsNb;
/*010*/	int32_t   nextDirC;
/*014*/	uint32_t  checkSum;
/*018*/	uint8_t   records[ 488 ];
};


#endif  /* ADF_BLK_H */
