[SDL] Appending resources to .exe

Martin Storsjö martin at martin.st
Tue Apr 3 23:37:10 PDT 2007


On Tue, 3 Apr 2007, Andre de Leiradella wrote:

>
> I did this (well, a little bit more complicated, with compression and
> stuff...) and everything works great, except that MP3 musics had to be
> extracted to a regular file before being read. Apparently the code in
> SDL_Mixer that detects MP3 files if not working or I have some problems
> with my MP3 files and they were not being loaded properly directly from
> a SDL_RWops. OGG works fine though.

IIRC, there's the same problem when trying to read TTF files using 
SDL_ttf, too. The problem is that when creating a SDL_RWops structure from 
an open file handle, you can't limit the SDL_RWops to a subsection of the 
file.

Any request to seek to the beginning/end of the SDL_RWops seeks to the 
beginning/end of the containing file, not to the end of the logical file 
within. This can be fixed by creating SDL_RWops manually.

struct rw_fp {
         FILE *fp;
         int begin, size, pos;
         bool autoclose;
};

int rw_fp_seek(SDL_RWops *ctx, int offset, int whence) {
         struct rw_fp *data = (struct rw_fp*) ctx->hidden.unknown.data1;
         switch (whence) {
         case SEEK_SET:
                 data->pos = offset;
                 break;
         case SEEK_CUR:
                 data->pos += offset;
                 break;
         case SEEK_END:
                 data->pos = data->size+offset;
                 break;
         default:
                 return -1;
                 break;
         }
         if (data->pos<0) data->pos = 0;
         if (data->pos>data->size) data->pos = data->size;
         if (fseek(data->fp,data->begin+data->pos,SEEK_SET)==0)
                 return data->pos;
//      SDL_Error(SDL_EFSEEK);
         return -1;
}

int rw_fp_read(SDL_RWops *ctx, void *ptr, int size, int maxnum) {
         struct rw_fp *data = (struct rw_fp*) ctx->hidden.unknown.data1;
         int n = maxnum;
         int n2 = (data->size-data->pos)/size;
         if (n2<n) n = n2;
//      if (data->pos == data->size) return -1;
         n = fread(ptr,size,n,data->fp);
         data->pos += n*size;
//      if (n==0 && ferror(data->fp))
//              SDL_Error(SDL_EFREAD);
         return n;
}

int rw_fp_write(SDL_RWops *ctx, const void *ptr, int size, int num) {
         struct rw_fp *data = (struct rw_fp*) ctx->hidden.unknown.data1;
         int n = num;
         int n2 = (data->size-data->pos)/size;
         if (n2<n) n = n2;
//      if (data->pos == data->size) return -1;
         n = fwrite(ptr,size,n,data->fp);
         data->pos += n*size;
//      if (n==0 && ferror(data->fp))
//              SDL_Error(SDL_EFWRITE);
         return n;
}

int rw_fp_close(SDL_RWops *ctx) {
         struct rw_fp *data = (struct rw_fp*) ctx->hidden.unknown.data1;
         if (data->autoclose)
                 fclose(data->fp);
         free(data);
         free(ctx);
         return 0;
}

SDL_RWops *rwFromFP(FILE *in, int size, bool autoclose = true) {
         SDL_RWops *rw = (SDL_RWops*) malloc(sizeof(SDL_RWops));
         if (rw==NULL) return NULL;
         rw->hidden.unknown.data1 = malloc(sizeof(struct rw_fp));
         if (rw->hidden.unknown.data1==NULL) {
                 free(rw);
                 return NULL;
         }
         struct rw_fp *data = (struct rw_fp*) rw->hidden.unknown.data1;
         data->fp = in;
         data->begin = ftell(in);
         data->size = size;
         data->pos = 0;
         data->autoclose = autoclose;
         rw->seek = rw_fp_seek;
         rw->read = rw_fp_read;
         rw->write = rw_fp_write;
         rw->close = rw_fp_close;
         return rw;
}

This allows you to create a SDL_RWops structure essentially containing 
only a part of the file, which allows seeking back and forth. If others
see a need for this, I'd be glad to see this integrated into SDL.

// Martin


More information about the SDL mailing list