diff --git a/src/sdl-instead/idf.c b/src/sdl-instead/idf.c index 0cbd24a..37711c8 100644 --- a/src/sdl-instead/idf.c +++ b/src/sdl-instead/idf.c @@ -10,11 +10,11 @@ typedef struct _idfd_t { idf_t idf; } idfd_t; -typedef struct _idff_t { +struct _idff_t { idfd_t *dir; unsigned long pos; FILE *fd; -} idff_t; +}; struct _idf_t { unsigned long size; @@ -294,10 +294,9 @@ err: return rc; } - -static int idfrw_seek(struct SDL_RWops *context, int offset, int whence) + +int idf_seek(idff_t fil, int offset, int whence) { - idff_t *fil = (idff_t *)context->hidden.unknown.data1; idfd_t *dir = fil->dir; switch (whence) { case SEEK_SET: @@ -324,34 +323,37 @@ static int idfrw_seek(struct SDL_RWops *context, int offset, int whence) return -1; } -static int idfrw_read(struct SDL_RWops *context, void *ptr, int size, int maxnum) +static int idfrw_seek(struct SDL_RWops *context, int offset, int whence) +{ + idff_t fil = (idff_t)context->hidden.unknown.data1; + return idf_seek(fil, offset, whence); +} + +int idf_read(idff_t fil, void *ptr, int size, int maxnum) { int rc = 0; long pos; - idff_t *fil = (idff_t *)context->hidden.unknown.data1; + idfd_t *dir = fil->dir; if (fseek(fil->fd, dir->offset + fil->pos, SEEK_SET) < 0) { return 0; } -#if 0 +#if 1 while (maxnum) { - pos = ftell(dir->idf->fd); - dir->pos = pos - dir->offset; + pos = ftell(fil->fd); + fil->pos = pos - dir->offset; - if (dir->pos + size > dir->size) { + if (fil->pos + size > dir->size) { break; } - if (fread(ptr, size, 1, dir->idf->fd) != 1) { - fprintf(stderr, "read 2 err\n"); + if (fread(ptr, size, 1, fil->fd) != 1) break; - } -// dir->pos += size; +// fil->pos += size; ptr += size; maxnum --; rc ++; - } #else rc = fread(ptr, size, maxnum, fil->fd); @@ -361,15 +363,31 @@ static int idfrw_read(struct SDL_RWops *context, void *ptr, int size, int maxnum return rc; } -static int idfrw_close(struct SDL_RWops *context) +static int idfrw_read(struct SDL_RWops *context, void *ptr, int size, int maxnum) { - if (context) { - idff_t *fil = (idff_t *)context->hidden.unknown.data1; + idff_t fil = (idff_t)context->hidden.unknown.data1; + return idf_read(fil, ptr, size, maxnum); +} + +int idf_close(idff_t fil) +{ + if (fil) { fclose(fil->fd); - SDL_FreeRW(context); + free(fil); } return 0; /* nothing todo */ } + +static int idfrw_close(struct SDL_RWops *context) +{ + if (context) { + idff_t fil = (idff_t)context->hidden.unknown.data1; + idf_close(fil); + SDL_FreeRW(context); + } + return 0; +} + #if 0 int idf_extract(idf_t idf, const char *fname) { @@ -398,26 +416,56 @@ int idf_extract(idf_t idf, const char *fname) return 0; } #endif -SDL_RWops *RWFromIdf(idf_t idf, const char *fname) +int idf_eof(idff_t idf) +{ + if (!idf) + return 1; + if (idf->pos >= idf->dir->size) + return 1; + return 0; +} + +int idf_error(idff_t idf) +{ + if (!idf || !idf->fd) + return -1; + return ferror(idf->fd); +} +idff_t idf_open(idf_t idf, const char *fname) { idfd_t *dir = NULL; - idff_t *fil = NULL; - SDL_RWops *n; + idff_t fil = NULL; if (idf) dir = cache_lookup(idf->dir, fname); if (!dir) - return SDL_RWFromFile(dirpath(fname), "rb"); - fil = malloc(sizeof(idff_t)); + return NULL; + + fil = malloc(sizeof(struct _idff_t)); if (!fil) return NULL; - n = SDL_AllocRW(); - if (!n) - goto err; + fil->dir = dir; fil->pos = 0; fil->fd = fopen(dirpath(idf->path), "rb"); if (!fil->fd) goto err; + return fil; +err: + free(fil); + return NULL; +} + +SDL_RWops *RWFromIdf(idf_t idf, const char *fname) +{ + idff_t fil = NULL; + SDL_RWops *n; + fil = idf_open(idf, fname); + if (!fil) + return SDL_RWFromFile(dirpath(fname), "rb"); + + n = SDL_AllocRW(); + if (!n) + goto err; n->seek = idfrw_seek; n->read = idfrw_read; n->close = idfrw_close; diff --git a/src/sdl-instead/idf.h b/src/sdl-instead/idf.h index 1454400..2f6f58e 100644 --- a/src/sdl-instead/idf.h +++ b/src/sdl-instead/idf.h @@ -2,7 +2,9 @@ #define __IDF_H_INCLUDED struct _idf_t; +struct _idff_t; typedef struct _idf_t *idf_t; +typedef struct _idff_t *idff_t; extern idf_t idf_init(const char *path); extern void idf_shrink(idf_t idf); @@ -10,5 +12,13 @@ extern void idf_done(idf_t idf); extern SDL_RWops *RWFromIdf(idf_t idf, const char *fname); extern int idf_create(const char *file, const char *path); +extern idff_t idf_open(idf_t idf, const char *fname); + +extern int idf_seek(idff_t fil, int offset, int whence); +extern int idf_read(idff_t fil, void *ptr, int size, int maxnum); +extern int idf_close(idff_t fil); + +extern int idf_eof(idff_t idf); +extern int idf_error(idff_t idf); #endif \ No newline at end of file diff --git a/src/sdl-instead/instead.c b/src/sdl-instead/instead.c index 757e6ea..6fc19e2 100644 --- a/src/sdl-instead/instead.c +++ b/src/sdl-instead/instead.c @@ -1,6 +1,7 @@ #include "externals.h" #include "internals.h" #include "list.h" +#include "idf.h" #ifndef STEAD_PATH #define STEAD_PATH "./stead" @@ -329,6 +330,7 @@ typedef struct LoadF { int extraline; unsigned char byte; FILE *f; + idff_t idff; int enc; unsigned char buff[4096]; } LoadF; @@ -342,8 +344,17 @@ static const char *getF (lua_State *L, void *ud, size_t *size) { *size = 1; return "\n"; } - if (feof(lf->f)) return NULL; - *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); + + if (lf->f && feof(lf->f)) + return NULL; + if (lf->idff && idf_eof(lf->idff)) + return NULL; + + if (lf->idff) + *size = idf_read(lf->idff, lf->buff, 1, sizeof(lf->buff)); + else + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); + if (lf->enc) { for (i = 0; i < *size; i ++) { unsigned char b = lf->buff[i]; @@ -369,13 +380,26 @@ static int loadfile (lua_State *L, const char *filename, int enc) { int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ lf.extraline = 0; lua_pushfstring(L, "@%s", filename); - lf.f = fopen(filename, "rb"); + lf.idff = idf_open(game_idf, filename); + if (!lf.idff) + lf.f = fopen(filename, "rb"); + else + lf.f = NULL; lf.byte = 0xcc; lf.enc = enc; - if (lf.f == NULL) return errfile(L, "open", fnameindex); + if (lf.f == NULL && lf.idff == NULL) return errfile(L, "open", fnameindex); status = lua_load(L, getF, &lf, lua_tostring(L, -1)); - readstatus = ferror(lf.f); - if (filename) fclose(lf.f); /* close file (even in case of errors) */ + + if (lf.f) + readstatus = ferror(lf.f); + else + readstatus = idf_error(lf.idff); + + if (filename) { + if (lf.f) + fclose(lf.f); /* close file (even in case of errors) */ + idf_close(lf.idff); + } if (readstatus) { lua_settop(L, fnameindex); /* ignore results from `lua_load' */ return errfile(L, "read", fnameindex);