home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Large Pack of OldSkool DOS MOD Trackers
/
goattracker_2.68.zip
/
src
/
bme
/
bme_io.c
< prev
next >
Wrap
C/C++ Source or Header
|
2008-07-13
|
8KB
|
354 lines
//
// BME (Blasphemous Multimedia Engine) datafile IO main module
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <SDL/SDL.h>
#include "bme_main.h"
#include "bme_err.h"
#include "bme_cfg.h"
typedef struct
{
Uint32 offset;
Sint32 length;
char name[13];
} HEADER;
typedef struct
{
HEADER *currentheader;
int filepos;
int open;
} HANDLE;
static int io_usedatafile = 0;
static HEADER *fileheaders;
static unsigned files;
static char ident[4];
static char *idstring = "DAT!";
static HANDLE handle[MAX_HANDLES];
static FILE *fileptr[MAX_HANDLES] = {NULL};
static FILE *datafilehandle = NULL;
static unsigned char *datafileptr;
static unsigned char *datafilestart;
static unsigned freadle32(FILE *index);
static void linkedseek(unsigned pos);
static void linkedread(void *buffer, int length);
static unsigned linkedreadle32(void);
void io_setfilemode(int usedf)
{
io_usedatafile = usedf;
}
int io_openlinkeddatafile(unsigned char *ptr)
{
int index;
if (datafilehandle) fclose(datafilehandle);
datafilehandle = NULL;
datafilestart = ptr;
linkedseek(0);
linkedread(ident, 4);
if (memcmp(ident, idstring, 4))
{
bme_error = BME_WRONG_FORMAT;
return BME_ERROR;
}
files = linkedreadle32();
fileheaders = malloc(files * sizeof(HEADER));
if (!fileheaders)
{
bme_error = BME_OUT_OF_MEMORY;
return BME_ERROR;
}
for (index = 0; index < files; index++)
{
fileheaders[index].offset = linkedreadle32();
fileheaders[index].length = linkedreadle32();
linkedread(&fileheaders[index].name, 13);
}
for (index = 0; index < MAX_HANDLES; index++) handle[index].open = 0;
io_usedatafile = 1;
bme_error = BME_OK;
return BME_OK;
}
int io_opendatafile(char *name)
{
int index;
if (name)
{
datafilehandle = fopen(name, "rb");
if (!datafilehandle)
{
bme_error = BME_OPEN_ERROR;
return BME_ERROR;
}
}
fread(ident, 4, 1, datafilehandle);
if (memcmp(ident, idstring, 4))
{
bme_error = BME_WRONG_FORMAT;
return BME_ERROR;
}
files = freadle32(datafilehandle);
fileheaders = malloc(files * sizeof(HEADER));
if (!fileheaders)
{
bme_error = BME_OUT_OF_MEMORY;
return BME_ERROR;
}
for (index = 0; index < files; index++)
{
fileheaders[index].offset = freadle32(datafilehandle);
fileheaders[index].length = freadle32(datafilehandle);
fread(&fileheaders[index].name, 13, 1, datafilehandle);
}
for (index = 0; index < MAX_HANDLES; index++) handle[index].open = 0;
io_usedatafile = 1;
bme_error = BME_OK;
return BME_OK;
}
// Returns nonnegative file handle if successful, -1 on error
int io_open(char *name)
{
if (!name) return -1;
if (!io_usedatafile)
{
int index;
for (index = 0; index < MAX_HANDLES; index++)
{
if (!fileptr[index]) break;
}
if (index == MAX_HANDLES) return -1;
else
{
FILE *file = fopen(name, "rb");
if (!file)
{
return -1;
}
else
{
fileptr[index] = file;
return index;
}
}
}
else
{
int index;
int namelength;
char namecopy[13];
namelength = strlen(name);
if (namelength > 12) namelength = 12;
memcpy(namecopy, name, namelength + 1);
for (index = 0; index < strlen(namecopy); index++)
{
namecopy[index] = toupper(namecopy[index]);
}
for (index = 0; index < MAX_HANDLES; index++)
{
if (!handle[index].open)
{
int count = files;
handle[index].currentheader = fileheaders;
while (count)
{
if (!strcmp(namecopy, handle[index].currentheader->name))
{
handle[index].open = 1;
handle[index].filepos = 0;
return index;
}
count--;
handle[index].currentheader++;
}
return -1;
}
}
return -1;
}
}
// Returns file position after seek or -1 on error
int io_lseek(int index, int offset, int whence)
{
if (!io_usedatafile)
{
fseek(fileptr[index], offset, whence);
return ftell(fileptr[index]);
}
else
{
int newpos;
if ((index < 0) || (index >= MAX_HANDLES)) return -1;
if (!handle[index].open) return -1;
switch(whence)
{
default:
case SEEK_SET:
newpos = offset;
break;
case SEEK_CUR:
newpos = offset + handle[index].filepos;
break;
case SEEK_END:
newpos = offset + handle[index].currentheader->length;
break;
}
if (newpos < 0) newpos = 0;
if (newpos > handle[index].currentheader->length) newpos = handle[index].currentheader->length;
handle[index].filepos = newpos;
return newpos;
}
}
// Returns number of bytes actually read, -1 on error
int io_read(int index, void *buffer, int length)
{
if (!io_usedatafile)
{
return fread(buffer, 1, length, fileptr[index]);
}
else
{
int readbytes;
if ((index < 0) || (index >= MAX_HANDLES)) return -1;
if (!handle[index].open) return -1;
if (length + handle[index].filepos > handle[index].currentheader->length)
length = handle[index].currentheader->length - handle[index].filepos;
if (datafilehandle)
{
fseek(datafilehandle, handle[index].currentheader->offset + handle[index].filepos, SEEK_SET);
readbytes = fread(buffer, 1, length, datafilehandle);
}
else
{
linkedseek(handle[index].currentheader->offset + handle[index].filepos);
linkedread(buffer, length);
readbytes = length;
}
handle[index].filepos += readbytes;
return readbytes;
}
}
// Returns nothing
void io_close(int index)
{
if (!io_usedatafile)
{
fclose(fileptr[index]);
fileptr[index] = NULL;
}
else
{
if ((index < 0) || (index >= MAX_HANDLES)) return;
handle[index].open = 0;
}
}
unsigned io_read8(int index)
{
unsigned char byte;
io_read(index, &byte, 1);
return byte;
}
unsigned io_readle16(int index)
{
unsigned char bytes[2];
io_read(index, bytes, 2);
return (bytes[1] << 8) | bytes[0];
}
unsigned io_readhe16(int index)
{
unsigned char bytes[2];
io_read(index, bytes, 2);
return (bytes[0] << 8) | bytes[1];
}
unsigned io_readle32(int index)
{
unsigned char bytes[4];
io_read(index, bytes, 4);
return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
}
unsigned io_readhe32(int index)
{
unsigned char bytes[4];
io_read(index, bytes, 4);
return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
}
static unsigned freadle32(FILE *file)
{
unsigned char bytes[4];
fread(&bytes, 4, 1, file);
return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
}
static void linkedseek(unsigned pos)
{
datafileptr = &datafilestart[pos];
}
static void linkedread(void *buffer, int length)
{
unsigned char *dest = (unsigned char *)buffer;
while (length--)
{
*dest++ = *datafileptr++;
}
}
static unsigned linkedreadle32(void)
{
unsigned char bytes[4];
linkedread(&bytes, 4);
return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
}