?? filenode.c
字號(hào):
#include "Platform.h"
#include "Debug/Debug.h"
#include "StdC.h"
#include "Hardware/DRAM.h"
#include "PageStack/PageStack.h"
#include "FileSystem/Fat32/FileTree/NameNode.h"
#include "FileSystem/Fat32/FileTree/FileNode.h"
#include "FileSystem/Fat32/FileTree/Node.h"
//#define SHOW_CREATION // uncomment to see FileNode's get created.
//#define SHOW_VISITS // uncomment to see FileNode's get visited.
struct FileNode
{
ClusterNumber firstClusterOfFile;
NameNodeHandle nameOfFile;
unsigned long sizeInBytes;
FileNodeHandle nextFileSibbling; // next file, ignoring folders
FileNodeHandle prevFileSibbling; // prev file, ignoring folders
FileNodeHandle firstFileOfNextFolder; // first file in the next folder
FileNodeHandle lastFileOfPrevFolder; // last file in the previous folder
char unused[4]; // structure MUST pad to 32 bytes, or any power of 2.
};
XDATA_AT(PAGE_STACK_ADDRESS) struct FileNode _FILENODE_fileNodeTablePort[BYTES_PER_PORT/sizeof(struct FileNode)];
XDATA DramPageIndex _FILENODE_nextNewFilePage;
XDATA unsigned char _FILENODE_nextNewFileIndex;
XDATA FileNodeHandle _FILENODE_lastFileOfPrevFolder; // remember what was the last file of the previous folder.
XDATA FileNodeHandle _FILENODE_prevFile; // remember what was the first file to be created
// these 3 variables are used to keep track of the state
// between calls to FILENODE_DoneAddingFilesToFolder(),
// and are initialzied on each call to FILENODE_DoneAddingFilesToFolder()
XDATA static struct FileNode *_FILENODE_ReLink_scan;
XDATA static FileNodeHandle _FILENODE_ReLink_scanHandle;
XDATA static FileNodeHandle _FILENODE_ReLink_firstFileOfThisFolder;
void FILENODE_Initialize(void)
{
_FILENODE_nextNewFilePage = DRAM_AllocatePage(_STRING_CreateStringInCODE("FILENODE Array"));
_FILENODE_nextNewFileIndex = 0;
_FILENODE_lastFileOfPrevFolder = NO_FILE_NODE;
_FILENODE_prevFile = NO_FILE_NODE;
}
// This routine is adding a new file to a folder.
// It does so, by inserting itself as the first file in that folder,
// and linking what used to be the first file, as its' sibbling instead.
FileNodeHandle FILENODE_AddFile(
ClusterNumber startingClusterNumber,
unsigned long sizeInBytes,
NameNodeHandle nameOfFile)
{
XDATA static FileNodeHandle thisHandle; // the new file being created.
XDATA static FileNodeHandle prevFileHandle;
// figure out the file-handle of the new entry being created.
thisHandle = MakeHandle(_FILENODE_nextNewFilePage, _FILENODE_nextNewFileIndex);
// populate 'self'
{
XDATA static struct FileNode *self;
self = &_FILENODE_fileNodeTablePort[GetIndexChar(thisHandle)];
PAGESTACK_Push(GetPage(thisHandle));
self->firstClusterOfFile = startingClusterNumber;
self->nameOfFile = nameOfFile;
self->sizeInBytes = sizeInBytes;
self->nextFileSibbling = NO_FILE_NODE;
self->prevFileSibbling = _FILENODE_prevFile;
self->firstFileOfNextFolder = NO_FILE_NODE; // this will be filled in when FILENODE_DoneAddingFilesToFolder() is called at the correct time.
self->lastFileOfPrevFolder = _FILENODE_lastFileOfPrevFolder;
#ifdef SHOW_CREATION
DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [new]..."));
DbgMessageHex32(DC_FILENODE, MakeHandle(_FILENODE_nextNewFilePage, _FILENODE_nextNewFileIndex));
DbgMessageNewLine(DC_FILENODE);
DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
PAGESTACK_Pop();
}
// fix the 'nextSibbling' pointer of the previous file...
if(_FILENODE_prevFile != NO_FILE_NODE)
{
XDATA static struct FileNode *prevFile;
prevFile = &_FILENODE_fileNodeTablePort[GetIndexChar(_FILENODE_prevFile)];
PAGESTACK_Push(GetPage(_FILENODE_prevFile));
prevFile->nextFileSibbling = thisHandle;
PAGESTACK_Pop();
}
// remember this file as our new "previous file"...
_FILENODE_prevFile = thisHandle;
// advance pointer for next available object
_FILENODE_nextNewFileIndex++;
if(_FILENODE_nextNewFileIndex == ENTRIES(_FILENODE_fileNodeTablePort))
{
_FILENODE_nextNewFilePage = DRAM_AllocatePage(_STRING_CreateStringInCODE("FILENODE Array"));
_FILENODE_nextNewFileIndex = 0;
}
// return our new file.
return thisHandle;
}
// this is called after the last file has been added to a folder, but before
// any files have been added for the next folder.
void FILENODE_DoneAddingFilesToFolder(void)
{
// go back and fix-up nextFileSibbling's and firstFileOfNextFolder's...
// only if there has been a previous folder...
if(_FILENODE_lastFileOfPrevFolder != NO_FILE_NODE)
{
// get the last file of the previous folder...
_FILENODE_ReLink_scanHandle = _FILENODE_lastFileOfPrevFolder; // start with last file in prev folder
// get the first file of this folder...
_FILENODE_ReLink_scan = &_FILENODE_fileNodeTablePort[GetIndexChar(_FILENODE_ReLink_scanHandle)];
PAGESTACK_Push(GetPage(_FILENODE_ReLink_scanHandle));
_FILENODE_ReLink_firstFileOfThisFolder = _FILENODE_ReLink_scan->nextFileSibbling;
PAGESTACK_Pop();
// only if there are files in the current folder...
if(_FILENODE_ReLink_firstFileOfThisFolder == NO_FILE_NODE)
{
// nothing to do... this will short-circuit the
// FILENODE_LinkFileTreeSomeMore() routine.
_FILENODE_ReLink_scanHandle = NO_FILE_NODE;
}
}
else
{
// nothing to do... this will short-circuit the
// FILENODE_LinkFileTreeSomeMore() routine.
_FILENODE_ReLink_scanHandle = NO_FILE_NODE;
}
// remember new "last file of prev folder"...
_FILENODE_lastFileOfPrevFolder = _FILENODE_prevFile;
}
char FILENODE_LinkFileTreeSomeMore(void)
{
XDATA static char togo;
// NOTE: If the music skips or pauses while the file-tree is being built
// after power-up, then this number can be lowered at the cost of increased
// load-times for the directory tree.
togo = 32; // do this many files each call...
while(_FILENODE_ReLink_scanHandle != NO_FILE_NODE)
{
// decrement the counter which limits the length of time
// this function can execute, per call.
togo--;
if(togo > 0)
{
_FILENODE_ReLink_scan = &_FILENODE_fileNodeTablePort[GetIndexChar(_FILENODE_ReLink_scanHandle)];
PAGESTACK_Push(GetPage(_FILENODE_ReLink_scanHandle));
if(_FILENODE_ReLink_scan->firstFileOfNextFolder == NO_FILE_NODE)
_FILENODE_ReLink_scan->firstFileOfNextFolder = _FILENODE_ReLink_firstFileOfThisFolder;
_FILENODE_ReLink_scanHandle = _FILENODE_ReLink_scan->prevFileSibbling;
PAGESTACK_Pop();
}
else
{
return 0; // not done yet!!
}
}
// DONE!!
return 1;
}
ClusterNumber FILENODE_DiscoverFirstCluster(FileNodeHandle fileNodeHandle)
{
XDATA static struct FileNode *self;
XDATA static ClusterNumber startingClusterNumber;
self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit FirstCluster]..."));
DbgMessageHex32(DC_FILENODE, fileNodeHandle);
DbgMessageNewLine(DC_FILENODE);
DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
startingClusterNumber = self->firstClusterOfFile;
PAGESTACK_Pop();
return startingClusterNumber;
}
FileNodeHandle FILENODE_GetNextFileNodeSibbling(FileNodeHandle fileNodeHandle)
{
XDATA static struct FileNode *self;
XDATA static FileNodeHandle nextFileNode;
self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit NextFileSib]..."));
DbgMessageHex32(DC_FILENODE, fileNodeHandle);
DbgMessageNewLine(DC_FILENODE);
DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
nextFileNode = self->nextFileSibbling;
PAGESTACK_Pop();
return nextFileNode;
}
FileNodeHandle FILENODE_GetPrevFileNodeSibbling(FileNodeHandle fileNodeHandle)
{
XDATA static struct FileNode *self;
XDATA static FileNodeHandle nextFileNode;
self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit PrevFileSib]..."));
DbgMessageHex32(DC_FILENODE, fileNodeHandle);
DbgMessageNewLine(DC_FILENODE);
DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
nextFileNode = self->prevFileSibbling;
PAGESTACK_Pop();
return nextFileNode;
}
FileNodeHandle FILENODE_GetFirstFileNodeOfNextFolder(FileNodeHandle fileNodeHandle)
{
XDATA static struct FileNode *self;
XDATA static FileNodeHandle nextFileNode;
self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit NextFolder]..."));
DbgMessageHex32(DC_FILENODE, fileNodeHandle);
DbgMessageNewLine(DC_FILENODE);
DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
nextFileNode = self->firstFileOfNextFolder;
PAGESTACK_Pop();
return nextFileNode;
}
FileNodeHandle FILENODE_GetLastFileNodeOfPrevFolder(FileNodeHandle fileNodeHandle)
{
XDATA static struct FileNode *self;
XDATA static FileNodeHandle nextFileNode;
self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit PrevFolder]..."));
DbgMessageHex32(DC_FILENODE, fileNodeHandle);
DbgMessageNewLine(DC_FILENODE);
DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
nextFileNode = self->lastFileOfPrevFolder;
PAGESTACK_Pop();
return nextFileNode;
}
unsigned long FILENODE_DiscoverFileSizeInBytes(FileNodeHandle fileNodeHandle)
{
XDATA static struct FileNode *self;
XDATA static unsigned long sizeInBytes;
self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit FileSize]..."));
DbgMessageHex32(DC_FILENODE, fileNodeHandle);
DbgMessageNewLine(DC_FILENODE);
DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
sizeInBytes = self->sizeInBytes;
PAGESTACK_Pop();
return sizeInBytes;
}
NameNodeHandle FILENODE_GetFilename(FileNodeHandle fileNodeHandle)
{
XDATA static struct FileNode *self;
XDATA static NameNodeHandle filename;
self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit GetName]..."));
DbgMessageHex32(DC_FILENODE, fileNodeHandle);
DbgMessageNewLine(DC_FILENODE);
DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
filename = self->nameOfFile;
PAGESTACK_Pop();
return filename;
}
void FILENODE_Dump(FileNodeHandle fileNodeHandle)
{
XDATA static struct FileNode *self;
self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
PAGESTACK_Push(GetPage(fileNodeHandle));
DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
PAGESTACK_Pop();
}
_CONSTANT_DATA(FILENODE)
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -