diff options
-rw-r--r-- | includes/cdutils.h | 1 | ||||
-rw-r--r-- | lib/cdutils.cpp | 51 | ||||
-rw-r--r-- | lib/luacd.cpp | 73 |
3 files changed, 125 insertions, 0 deletions
diff --git a/includes/cdutils.h b/includes/cdutils.h index 3666491..bf38473 100644 --- a/includes/cdutils.h +++ b/includes/cdutils.h @@ -114,6 +114,7 @@ class cdutils : public Base { int show_dir(struct DirEntry * dir); struct DirEntry find_dir_entry(struct DirEntry * dir, const String & name); struct DirEntry * find_dir_entry(Byte ** buffer, struct DirEntry * dir, const String & name); + struct DirEntry get_next_dir_entry(struct DirEntry * dir, int * cursor, String & name); static Uint8 from_BCD(Uint8 x); static Uint8 to_BCD(Uint8 x); static bool is_valid_BCD(Uint8 x); diff --git a/lib/cdutils.cpp b/lib/cdutils.cpp index d863927..607d42b 100644 --- a/lib/cdutils.cpp +++ b/lib/cdutils.cpp @@ -541,6 +541,57 @@ struct cdutils::DirEntry cdutils::find_dir_entry(struct DirEntry * dir, const St return r; } +struct cdutils::DirEntry cdutils::get_next_dir_entry(struct DirEntry * dir, int * cursor, String & name) { + unsigned int ptr, size; + Uint8 * buffer; + struct DirEntry r = {0, 0, 0, 0, 0}; + Uint32 Sector; + + if (!(dir->Flags & 2)) { + return r; + } + + size = from_LE32(dir->Size); + Sector = from_LE32(dir->Sector); + + buffer = (Uint8 *) malloc(size); + read_data(buffer, size, GUESS, Sector); + + dir = 0; + + ptr = 0; + if (*cursor < size) { + dir = (struct DirEntry *) &(buffer[*cursor]); + if (!dir->R) { + (*cursor)++; + if (*cursor < size) { + dir = (struct DirEntry *) &(buffer[*cursor]); + } else { + dir = 0; + } + } + if (dir) + *cursor += dir->R; + } + + if (dir && dir->R) { + if ((dir->N == 1) && (dir->id[0] == 0)) { + name = "."; + } else if ((dir->N == 1) && (dir->id[0] == 1)) { + name = ".."; + } else { + name = String(dir->id, dir->N); + } + + r = *dir; + } else { + name = ""; + } + + free(buffer); + return r; +} + struct cdutils::DirEntry * cdutils::find_dir_entry(Byte ** bufout, struct cdutils::DirEntry * dir, const String & name) { unsigned int ptr, size; Byte * buffer; diff --git a/lib/luacd.cpp b/lib/luacd.cpp index 97dbbaf..a32ecaf 100644 --- a/lib/luacd.cpp +++ b/lib/luacd.cpp @@ -598,6 +598,11 @@ enum direntry_methods_t { DIRENTRY_ISXASTR, DIRENTRY_ISXAXA, DIRENTRY_ISXAFORM1, + DIRENTRY_ITERATE, +}; + +enum direntry_functions_t { + DIRENTRY_ITERATOR = 0, }; struct lua_functypes_t direntry_methods[] = { @@ -610,6 +615,11 @@ struct lua_functypes_t direntry_methods[] = { { DIRENTRY_ISXASTR, "isxastr", 0, 0, 0 }, { DIRENTRY_ISXAXA, "isxaxa", 0, 0, 0 }, { DIRENTRY_ISXAFORM1, "isxaform1", 0, 0, 0 }, + { DIRENTRY_ITERATE, "iterate", 1, 1, { BLUA_OBJECT } }, +}; + +struct lua_functypes_t direntry_functions[] = { + { DIRENTRY_ITERATOR, "iterator", 2, 2, { BLUA_TABLE, BLUA_ANY } }, { -1, 0, 0, 0, 0 } }; @@ -624,8 +634,11 @@ class sLua_direntry : public Base { DECLARE_METHOD(direntry, DIRENTRY_ISXASTR); DECLARE_METHOD(direntry, DIRENTRY_ISXAXA); DECLARE_METHOD(direntry, DIRENTRY_ISXAFORM1); + DECLARE_METHOD(direntry, DIRENTRY_ITERATE); + DECLARE_FUNCTION(direntry, DIRENTRY_ITERATOR); private: static int direntry_proceed(Lua * L, int n, direntry * obj, int caller); + static int direntry_proceed_statics(Lua * L, int n, int caller); }; void Luadirentry::pushmembers(Lua * L) { @@ -640,6 +653,7 @@ void Luadirentry::pushmembers(Lua * L) { PUSH_METHOD(direntry, DIRENTRY_ISXASTR); PUSH_METHOD(direntry, DIRENTRY_ISXAXA); PUSH_METHOD(direntry, DIRENTRY_ISXAFORM1); + PUSH_METHOD(direntry, DIRENTRY_ITERATE); } int sLua_direntry::direntry_proceed(Lua * L, int n, direntry * dir, int caller) { @@ -647,6 +661,7 @@ int sLua_direntry::direntry_proceed(Lua * L, int n, direntry * dir, int caller) String index; bool has_xa = false; Byte * p; + int cursor; s = 33 + dir->N; if (s & 1) { @@ -740,11 +755,69 @@ int sLua_direntry::direntry_proceed(Lua * L, int n, direntry * dir, int caller) } else { L->push(); } + break; + case DIRENTRY_ITERATE: + L->push(function_DIRENTRY_ITERATOR); + L->newtable(); + L->push("direntry"); + L->copy(1); + L->settable(); + L->push("cdutil"); + L->copy(2); + L->settable(); + L->push("cursor"); + { + int * cursor = (int *) L->newuser(sizeof(int)); + *cursor = 0; + } + L->settable(); + L->push(); + r = 3; + break; } return r; } +int sLua_direntry::direntry_proceed_statics(Lua * L, int n, int caller) { + int r = 0; + cdutils::DirEntry * dir = 0, rdir; + cdutils * cdutil = 0; + int * cursor = 0; + String name; + + switch (caller) { + case DIRENTRY_ITERATOR: + L->push("cursor"); + L->gettable(1); + cursor = (int *) L->touserdata(); + L->pop(); + L->push("cdutil"); + L->gettable(1); + cdutil = L->recast<cdutils>(3); + L->pop(); + L->push("direntry"); + L->gettable(1); + dir = (cdutils::DirEntry *) LuaObject::getme(L, 3); + L->pop(); + rdir = cdutil->get_next_dir_entry(dir, cursor, name); + + if ((rdir.R == 0) && (rdir.NExt == 0) && (rdir.Sector == 0) && (rdir.BESector == 0) && (rdir.Size == 0)) { + L->push(); + L->push(); + } else { + L->push(name); + dir = (cdutils::DirEntry *) malloc(rdir.R); + memcpy(dir, &rdir, rdir.R); + Luadirentry ldir(dir); + ldir.pushdestruct(L); + } + r = 2; + break; + } + + return r; +} /***************************\ |** class direntry exports **| |