/*!
    \file  Fat12.h
    \brief Fat12

    Copyright (c) 2005 HigePon
    WITHOUT ANY WARRANTY

    \author  HigePon
    \version $Revision$
    \date   create:2005/03/26 update:$Date$
*/

#ifndef _FAT12_
#define _FAT12_

#include "types.h"
#include "IStorageDevice.h"
#include "BitMap.h"

namespace FatFS
{

/*----------------------------------------------------------------------
    Boot Parameter block
----------------------------------------------------------------------*/
#pragma pack(1)
typedef struct Bpb
{
    byte jumpBoot[3];
    byte sysName[8];
    word bytesPerSector;
    byte sectorsPerCluster;
    word reservedSectors;
    byte fatCount;
    word maxRootEntries;
    word totalSectors1;
    byte mediaDescriptor;
    word sectorsPerFAT;
    word sectorsPerTrack;
    word headCount;
    dword hiddenSectors;
    dword totalSectors2;
    byte driveNumber;
    byte reserved1;
    byte extBootSignature;
    dword volumeSerial;
    byte volumeLabel[11];
    byte reserved2[8];
};
#pragma pack(0)

#pragma pack(1)
typedef struct DirectoryEntry
{
    byte filename[8];
    byte extension[3];
    byte attributes;
    byte reserved[10];
    word time;
    word date;
    word startCluster;
    dword fileSize;
};
#pragma pack(0)

/*----------------------------------------------------------------------
    Fat12
----------------------------------------------------------------------*/
class Fat12
{
public:
    Fat12(IStorageDevice* fd);
    virtual ~Fat12();

public:
    bool Initialize();

    dword GetNextCluster(dword cluster);
    bool GetPreviousCluster(dword start, dword cluster, dword* found);
    bool GetClusterFromChain(dword startCluster, dword count, dword* foundCluster);
    dword GetLbaFromCluster(dword cluster);
    void SetNextCluster(dword cluster, dword nextCluster);
    bool Flush();

    dword GetMaxRootEntries() const {return this->bpb.maxRootEntries;}
    dword GetSectorsPerFat() const {return this->bpb.sectorsPerFAT;}
    dword GetFatCount() const {return this->bpb.fatCount;}
    int GetLastError() const {return this->lastError;}

public:
    enum
    {
        SECTOR_SIZE = 512,
        END_OF_CLUSTER = 0x0fff,
    };

private:
    bool ReadCluster(dword cluster, void* buffer);
    bool WriteCluster(dword cluster, void* buffer);
    bool ReadBpb();
    bool ReadAndSetFat();
    bool ReadAtOnce(dword lba, void* buffer, dword size);
private:

    enum
    {
        FAT_START_SECTOR = 1,
    };

    Bpb bpb;
    dword notClusterArea;
    dword rootDirectorySectors;
    byte* fat;
    int lastError;
    byte* sectorBuffer;
    BitMap* flushTargetMap;
    IStorageDevice* fd;
};





};

#endif
