Btw you can just allocate an array of 31 FIBS. It is not possible to got more than 31 levels deeps, because max path is 63.
My assembly is broken. Somehow the program terminates after walk("*.*"). When I run this on a dir as floppy, I sometime get the question to change the system time.
while (!ret) { if (fibStore->Filename[0] != '.') { // debug -> address of the FIB structure String_Format(outBuf,"%i\n\r$",fibStore); DOS_StringOutput(outBuf); // display filename String_Format(outBuf,"%s\n\r$",fibStore->Filename); DOS_StringOutput(outBuf); // is a directory? if ((fibStore->Attribute & 0x10) == 0x10 ) { DOS_ChangeDir(fibStore->Filename); walk("*.*"); DOS_StringOutput("Are we back?$"); //<- this line will never be executed } } //fib = DOS_FindNextEntry(); ret = FNext(fibStore); }
I think there is a confusion in the use of Mem_HeapAlloc
/ Mem_HeapFree
function.
As said before, it is a flat allocator; extremely fast, but that can only be used for static memory allocation or temporary buffer.
Mem_HeapFree()
takes a size as a parameter while you pass it a pointer.
If you are sure that all the allocations are linear (which should be the case with a recursive directory tree), you can use this function with the size of the FIB structure.
Otherwise you can use the dynamic allocator which is more expensive (even if I optimized it for the z80) but works like the one in C.
There is an example of use in the sample s_sys
.
The working code
//************************************************************************** //* recursively walk a directory tree //* dialect : MSXgl //************************************************************************** #include #include #include // at this location there is BASIC buffer which is unused, use for 256Bytes u8 __at(0xF55E) outBuf[256]; // Change Directory u8 DOS_ChangeDir(const c8* path) { path; // HL __asm ex de,hl ld c, #DOS_FUNC_CHDIR // DOS routine call BDOS ret __endasm; } // Find First File // requires a *FIB so each recursion can have its own FIB // c8* search pattern u8 FFirst(DOS_FIB* fib,const c8* param) // fib HL // param DE { fib; //HL param; //DE __asm push ix ld b,#0x37 // attributes ld c,#0x40 // Find First File push hl pop ix call BDOS pop ix __endasm; } // continue search with *FIB u8 FNext(DOS_FIB* fib) // fib HL { fib; //HL __asm push ix //save ix push hl pop ix xor b // b == 0 ld c,#0x41 // fnext call BDOS pop ix __endasm; } void walk(const u8* param) { u8 ret; Mem_Set('$',outBuf,15); DOS_FIB* fibStore =(DOS_FIB*)Mem_HeapAlloc(sizeof(DOS_FIB)); ret = FFirst(fibStore,param); while (!ret) { if (fibStore->Filename[0] != '.') { String_Format(outBuf,"%s\n\r$",fibStore->Filename); DOS_StringOutput(outBuf); if ((fibStore->Attribute & 0x10) == 0x10 ) { DOS_ChangeDir(fibStore->Filename); walk("*.*"); DOS_ChangeDir(".."); } } ret = FNext(fibStore); } Mem_HeapFree(sizeof(DOS_FIB)); } void main() { walk("*.*"); // this is the current directory }