mirror of
https://github.com/libretro/libretro-wolfenstein3d.git
synced 2024-11-27 02:30:31 +00:00
1117 lines
26 KiB
C
1117 lines
26 KiB
C
// ID_CA.C
|
|
|
|
// this has been customized for WOLF
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
Id Software Caching Manager
|
|
---------------------------
|
|
|
|
Must be started BEFORE the memory manager, because it needs to get the headers
|
|
loaded into the data segment
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#if defined _WIN32
|
|
#include <io.h>
|
|
#else
|
|
#include <sys/uio.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
#include "wl_def.h"
|
|
#include <retro_endian.h>
|
|
|
|
#define THREEBYTEGRSTARTS
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
LOCAL CONSTANTS
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
typedef struct
|
|
{
|
|
word bit0,bit1; /* 0-255 is a character, > is a pointer to a node */
|
|
} huffnode;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
word RLEWtag;
|
|
int32_t headeroffsets[100];
|
|
} mapfiletype;
|
|
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
GLOBAL VARIABLES
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
#define BUFFERSIZE 0x1000
|
|
static int32_t bufferseg[BUFFERSIZE/4];
|
|
|
|
int mapon;
|
|
|
|
word *mapsegs[MAPPLANES];
|
|
static maptype* mapheaderseg[NUMMAPS];
|
|
byte *audiosegs[NUMSNDCHUNKS];
|
|
byte *grsegs[NUMCHUNKS];
|
|
|
|
word RLEWtag;
|
|
|
|
int numEpisodesMissing = 0;
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
LOCAL VARIABLES
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
char extension[5]; /* Need a string, not constant to change cache files */
|
|
char graphext[5];
|
|
char audioext[5];
|
|
static const char gheadname[] = "vgahead.";
|
|
static const char gfilename[] = "vgagraph.";
|
|
static const char gdictname[] = "vgadict.";
|
|
static const char mheadname[] = "maphead.";
|
|
|
|
static const char aheadname[] = "audiohed.";
|
|
static const char afilename[] = "audiot.";
|
|
|
|
void CA_CannotOpen(const char *string);
|
|
|
|
static int32_t grstarts[NUMCHUNKS + 1];
|
|
static int32_t* audiostarts; /* array of offsets in audio / audiot */
|
|
|
|
#ifdef GRHEADERLINKED
|
|
huffnode *grhuffman;
|
|
#else
|
|
huffnode grhuffman[255];
|
|
#endif
|
|
|
|
int grhandle = -1; /* handle to EGAGRAPH */
|
|
int maphandle = -1; /* handle to MAPTEMP / GAMEMAPS */
|
|
int audiohandle = -1; /* handle to AUDIOT / AUDIO */
|
|
|
|
int32_t chunkcomplen,chunkexplen;
|
|
|
|
SDMode oldsoundmode;
|
|
|
|
|
|
static int32_t GRFILEPOS(const size_t idx)
|
|
{
|
|
assert(idx < lengthof(grstarts));
|
|
return grstarts[idx];
|
|
}
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
LOW LEVEL ROUTINES
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
/*
|
|
============================
|
|
=
|
|
= CAL_GetGrChunkLength
|
|
=
|
|
= Gets the length of an explicit length chunk (not tiles)
|
|
= The file pointer is positioned so the compressed data can be read in next.
|
|
=
|
|
============================
|
|
*/
|
|
|
|
void CAL_GetGrChunkLength (int chunk)
|
|
{
|
|
lseek(grhandle,GRFILEPOS(chunk),SEEK_SET);
|
|
read(grhandle,&chunkexplen,sizeof(chunkexplen));
|
|
chunkexplen = Retro_SwapLES32(chunkexplen);
|
|
chunkcomplen = GRFILEPOS(chunk+1)-GRFILEPOS(chunk)-4;
|
|
}
|
|
|
|
|
|
/*
|
|
==========================
|
|
=
|
|
= CA_WriteFile
|
|
=
|
|
= Writes a file from a memory buffer
|
|
=
|
|
==========================
|
|
*/
|
|
|
|
boolean CA_WriteFile (const char *filename, void *ptr, int32_t length)
|
|
{
|
|
const int handle = open(filename, O_CREAT | O_WRONLY | O_BINARY, 0644);
|
|
if (handle == -1)
|
|
return false;
|
|
|
|
if (!write (handle,ptr,length))
|
|
{
|
|
close (handle);
|
|
return false;
|
|
}
|
|
close (handle);
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
==========================
|
|
=
|
|
= CA_LoadFile
|
|
=
|
|
= Allocate space for and load a file
|
|
=
|
|
==========================
|
|
*/
|
|
|
|
boolean CA_LoadFile (const char *filename, memptr *ptr)
|
|
{
|
|
int32_t size;
|
|
|
|
const int handle = open(filename, O_RDONLY | O_BINARY);
|
|
if (handle == -1)
|
|
return false;
|
|
|
|
size = lseek(handle, 0, SEEK_END);
|
|
lseek(handle, 0, SEEK_SET);
|
|
*ptr=malloc(size);
|
|
CHECKMALLOCRESULT(*ptr);
|
|
if (!read (handle,*ptr,size))
|
|
{
|
|
close (handle);
|
|
return false;
|
|
}
|
|
close (handle);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
============================================================================
|
|
|
|
COMPRESSION routines, see JHUFF.C for more
|
|
|
|
============================================================================
|
|
*/
|
|
|
|
static void CAL_HuffExpand(byte *source, byte *dest, int32_t length, huffnode *hufftable)
|
|
{
|
|
byte *end;
|
|
huffnode *headptr, *huffptr;
|
|
|
|
if(!length || !dest)
|
|
{
|
|
Quit("length or dest is null!");
|
|
return;
|
|
}
|
|
|
|
headptr = hufftable+254; /* head node is always node 254 */
|
|
|
|
int written = 0;
|
|
|
|
end=dest+length;
|
|
|
|
byte val = *source++;
|
|
byte mask = 1;
|
|
word nodeval;
|
|
huffptr = headptr;
|
|
while(1)
|
|
{
|
|
if(!(val & mask))
|
|
nodeval = huffptr->bit0;
|
|
else
|
|
nodeval = huffptr->bit1;
|
|
if(mask==0x80)
|
|
{
|
|
val = *source++;
|
|
mask = 1;
|
|
}
|
|
else mask <<= 1;
|
|
|
|
if(nodeval<256)
|
|
{
|
|
*dest++ = (byte) nodeval;
|
|
written++;
|
|
huffptr = headptr;
|
|
if(dest>=end) break;
|
|
}
|
|
else
|
|
{
|
|
huffptr = hufftable + (nodeval - 256);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CAL_CarmackExpand
|
|
=
|
|
= Length is the length of the EXPANDED data
|
|
=
|
|
======================
|
|
*/
|
|
|
|
#define NEARTAG 0xa7
|
|
#define FARTAG 0xa8
|
|
|
|
void CAL_CarmackExpand (byte *source, word *dest, int length)
|
|
{
|
|
word ch,chhigh,count,offset;
|
|
byte *inptr;
|
|
word *copyptr, *outptr;
|
|
|
|
length /= 2;
|
|
inptr = (byte *) source;
|
|
outptr = dest;
|
|
|
|
while (length>0)
|
|
{
|
|
ch = READWORD(&inptr);
|
|
chhigh = ch>>8;
|
|
if (chhigh == NEARTAG)
|
|
{
|
|
count = ch&0xff;
|
|
|
|
/* have to insert a word containing the tag byte */
|
|
if (!count)
|
|
{
|
|
ch |= *inptr++;
|
|
*outptr++ = ch;
|
|
length--;
|
|
}
|
|
else
|
|
{
|
|
offset = *inptr++;
|
|
copyptr = outptr - offset;
|
|
length -= count;
|
|
|
|
if(length < 0)
|
|
return;
|
|
|
|
while (count--)
|
|
*outptr++ = *copyptr++;
|
|
}
|
|
}
|
|
else if (chhigh == FARTAG)
|
|
{
|
|
count = ch & 0xff;
|
|
|
|
/* have to insert a word containing the tag byte */
|
|
if (!count)
|
|
{
|
|
ch |= *inptr++;
|
|
*outptr++ = ch;
|
|
length --;
|
|
}
|
|
else
|
|
{
|
|
offset = READWORD(&inptr);
|
|
copyptr = dest + offset;
|
|
length -= count;
|
|
if(length < 0)
|
|
return;
|
|
while (count--)
|
|
*outptr++ = *copyptr++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*outptr++ = ch;
|
|
length --;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CA_RLEWcompress
|
|
=
|
|
======================
|
|
*/
|
|
|
|
int32_t CA_RLEWCompress (word *source, int32_t length, word *dest, word rlewtag)
|
|
{
|
|
word value,count;
|
|
unsigned i;
|
|
word *start,*end;
|
|
|
|
start = dest;
|
|
|
|
end = source + (length+1)/2;
|
|
|
|
/* compress it */
|
|
do
|
|
{
|
|
count = 1;
|
|
value = *source++;
|
|
while (*source == value && source<end)
|
|
{
|
|
count++;
|
|
source++;
|
|
}
|
|
if (count>3 || value == rlewtag)
|
|
{
|
|
/* send a tag / count / value string */
|
|
*dest++ = rlewtag;
|
|
*dest++ = count;
|
|
*dest++ = value;
|
|
}
|
|
else
|
|
{
|
|
/* send word without compressing */
|
|
for (i=1;i<=count;i++)
|
|
*dest++ = value;
|
|
}
|
|
}while (source<end);
|
|
|
|
return (int32_t)(2*(dest-start));
|
|
}
|
|
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CA_RLEWexpand
|
|
= length is EXPANDED length
|
|
=
|
|
======================
|
|
*/
|
|
|
|
void CA_RLEWexpand (word *source, word *dest, int32_t length, word rlewtag)
|
|
{
|
|
word value,count,i;
|
|
word *end=dest+length/2;
|
|
|
|
/* expand it */
|
|
do
|
|
{
|
|
value = *source++;
|
|
|
|
/* uncompressed */
|
|
if (value != rlewtag)
|
|
*dest++=value;
|
|
else
|
|
{
|
|
/* compressed string */
|
|
count = *source++;
|
|
value = *source++;
|
|
for (i=1;i<=count;i++)
|
|
*dest++ = value;
|
|
}
|
|
} while (dest<end);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
CACHE MANAGER ROUTINES
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CAL_SetupGrFile
|
|
=
|
|
======================
|
|
*/
|
|
|
|
void CAL_SetupGrFile (void)
|
|
{
|
|
char fname[13];
|
|
int handle;
|
|
int j;
|
|
byte *compseg;
|
|
const byte* d = NULL;
|
|
int32_t* i = NULL;
|
|
|
|
#ifdef GRHEADERLINKED
|
|
|
|
grhuffman = (huffnode *)&EGAdict;
|
|
grstarts = (int32_t _seg *)FP_SEG(&EGAhead);
|
|
|
|
#else
|
|
|
|
/* load ???dict.ext (huffman dictionary for graphics files) */
|
|
strcpy(fname,gdictname);
|
|
strcat(fname,graphext);
|
|
|
|
handle = open(fname, O_RDONLY | O_BINARY);
|
|
if (handle == -1)
|
|
CA_CannotOpen(fname);
|
|
|
|
read(handle, grhuffman, sizeof(grhuffman));
|
|
|
|
for(j = 0; j < sizeof(grhuffman) / sizeof(huffnode); j++)
|
|
{
|
|
grhuffman[j].bit0 = (word)Retro_SwapLES16(grhuffman[j].bit0);
|
|
grhuffman[j].bit1 = (word)Retro_SwapLES16(grhuffman[j].bit1);
|
|
}
|
|
|
|
close(handle);
|
|
|
|
/* load the data offsets from ???head.ext */
|
|
strcpy(fname,gheadname);
|
|
strcat(fname,graphext);
|
|
|
|
handle = open(fname, O_RDONLY | O_BINARY);
|
|
if (handle == -1)
|
|
CA_CannotOpen(fname);
|
|
|
|
long headersize = lseek(handle, 0, SEEK_END);
|
|
lseek(handle, 0, SEEK_SET);
|
|
|
|
#ifndef APOGEE_1_0
|
|
int expectedsize = lengthof(grstarts) - numEpisodesMissing;
|
|
#else
|
|
int expectedsize = lengthof(grstarts);
|
|
#endif
|
|
|
|
if(!param_ignorenumchunks && headersize / 3 != (long) expectedsize)
|
|
Quit("Chocolate Wolfenstein 3D was not compiled for these data files:\n"
|
|
"%s contains a wrong number of offsets (%i instead of %i)!\n\n"
|
|
"Please check whether you are using the right executable!\n"
|
|
"(For mod developers: perhaps you forgot to update NUMCHUNKS?)",
|
|
fname, headersize / 3, expectedsize);
|
|
|
|
byte data[lengthof(grstarts) * 3];
|
|
read(handle, data, sizeof(data));
|
|
close(handle);
|
|
|
|
d = data;
|
|
for (i = grstarts; i != endof(grstarts); ++i)
|
|
{
|
|
const int32_t val = d[0] | d[1] << 8 | d[2] << 16;
|
|
*i = (val == 0x00FFFFFF ? -1 : val);
|
|
d += 3;
|
|
}
|
|
#endif
|
|
|
|
/* Open the graphics file, leaving it open until the game is finished */
|
|
strcpy(fname,gfilename);
|
|
strcat(fname,graphext);
|
|
|
|
grhandle = open(fname, O_RDONLY | O_BINARY);
|
|
if (grhandle == -1)
|
|
CA_CannotOpen(fname);
|
|
|
|
/* load the pic and sprite headers into the arrays in the data segment */
|
|
pictable=(pictabletype *) malloc(NUMPICS*sizeof(pictabletype));
|
|
CHECKMALLOCRESULT(pictable);
|
|
CAL_GetGrChunkLength(STRUCTPIC); /* position file pointer */
|
|
compseg=(byte *) malloc(chunkcomplen);
|
|
CHECKMALLOCRESULT(compseg);
|
|
read (grhandle,compseg,chunkcomplen);
|
|
CAL_HuffExpand(compseg, (byte*)pictable, NUMPICS * sizeof(pictabletype), grhuffman);
|
|
free(compseg);
|
|
|
|
for (j = 0; j < NUMPICS; j++)
|
|
{
|
|
pictable[j].height = (word)Retro_SwapLES16(pictable[j].height);
|
|
pictable[j].width = (word)Retro_SwapLES16(pictable[j].width);
|
|
}
|
|
}
|
|
|
|
//==========================================================================
|
|
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CAL_SetupMapFile
|
|
=
|
|
======================
|
|
*/
|
|
|
|
void CAL_SetupMapFile (void)
|
|
{
|
|
int i, j;
|
|
int handle;
|
|
int32_t length,pos;
|
|
char fname[13];
|
|
|
|
/* load maphead.ext (offsets and tileinfo for map file) */
|
|
strcpy(fname,mheadname);
|
|
strcat(fname,extension);
|
|
|
|
handle = open(fname, O_RDONLY | O_BINARY);
|
|
if (handle == -1)
|
|
CA_CannotOpen(fname);
|
|
|
|
length = NUMMAPS*4+2; /* used to be "filelength(handle);" */
|
|
mapfiletype *tinf=(mapfiletype *) malloc(sizeof(mapfiletype));
|
|
CHECKMALLOCRESULT(tinf);
|
|
read(handle, tinf, length);
|
|
|
|
tinf->RLEWtag = (word)Retro_SwapLES16(tinf->RLEWtag);
|
|
|
|
for(j = 0; j < sizeof(tinf->headeroffsets) / sizeof(int32_t); j++)
|
|
tinf->headeroffsets[j] = Retro_SwapLES32(tinf->headeroffsets[j]);
|
|
|
|
close(handle);
|
|
|
|
RLEWtag=tinf->RLEWtag;
|
|
|
|
/* open the data file */
|
|
#ifdef CARMACIZED
|
|
strcpy(fname, "gamemaps.");
|
|
strcat(fname, extension);
|
|
|
|
maphandle = open(fname, O_RDONLY | O_BINARY);
|
|
if (maphandle == -1)
|
|
CA_CannotOpen(fname);
|
|
#else
|
|
strcpy(fname,mfilename);
|
|
strcat(fname,extension);
|
|
|
|
maphandle = open(fname, O_RDONLY | O_BINARY);
|
|
if (maphandle == -1)
|
|
CA_CannotOpen(fname);
|
|
#endif
|
|
|
|
/* load all map header */
|
|
for (i=0;i<NUMMAPS;i++)
|
|
{
|
|
pos = tinf->headeroffsets[i];
|
|
if (pos<0) /* $FFFFFFFF start is a sparse map */
|
|
continue;
|
|
|
|
mapheaderseg[i]=(maptype *) malloc(sizeof(maptype));
|
|
CHECKMALLOCRESULT(mapheaderseg[i]);
|
|
lseek(maphandle,pos,SEEK_SET);
|
|
read (maphandle,(memptr)mapheaderseg[i],sizeof(maptype));
|
|
|
|
mapheaderseg[i]->height = (word)Retro_SwapLES16(mapheaderseg[i]->height);
|
|
|
|
for(j = 0; j < sizeof(mapheaderseg[i]->planelength) / sizeof(word); j++)
|
|
mapheaderseg[i]->planelength[j] = (word)Retro_SwapLES16(mapheaderseg[i]->planelength[j]);
|
|
|
|
for(j = 0; j < sizeof(mapheaderseg[i]->planestart) / sizeof(int32_t); j++)
|
|
mapheaderseg[i]->planestart[j] = Retro_SwapLES32(mapheaderseg[i]->planestart[j]);
|
|
|
|
mapheaderseg[i]->width = (word)Retro_SwapLES16(mapheaderseg[i]->width);
|
|
}
|
|
|
|
free(tinf);
|
|
|
|
/* allocate space for 3 64*64 plane */
|
|
for (i=0;i<MAPPLANES;i++)
|
|
{
|
|
mapsegs[i]=(word *) malloc(maparea*2);
|
|
CHECKMALLOCRESULT(mapsegs[i]);
|
|
}
|
|
}
|
|
|
|
|
|
//==========================================================================
|
|
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CAL_SetupAudioFile
|
|
=
|
|
======================
|
|
*/
|
|
|
|
void CAL_SetupAudioFile (void)
|
|
{
|
|
char fname[13];
|
|
|
|
/* load audiohed.ext (offsets for audio file) */
|
|
strcpy(fname,aheadname);
|
|
strcat(fname,audioext);
|
|
|
|
void* ptr;
|
|
if (!CA_LoadFile(fname, &ptr))
|
|
CA_CannotOpen(fname);
|
|
audiostarts = (int32_t*)ptr;
|
|
|
|
/* open the data file */
|
|
strcpy(fname,afilename);
|
|
strcat(fname,audioext);
|
|
|
|
audiohandle = open(fname, O_RDONLY | O_BINARY);
|
|
if (audiohandle == -1)
|
|
CA_CannotOpen(fname);
|
|
}
|
|
|
|
//==========================================================================
|
|
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CA_Startup
|
|
=
|
|
= Open all files and load in headers
|
|
=
|
|
======================
|
|
*/
|
|
|
|
void CA_Startup (void)
|
|
{
|
|
#ifdef PROFILE
|
|
unlink ("PROFILE.TXT");
|
|
profilehandle = open("PROFILE.TXT", O_CREAT | O_WRONLY | O_TEXT);
|
|
#endif
|
|
|
|
CAL_SetupMapFile ();
|
|
CAL_SetupGrFile ();
|
|
CAL_SetupAudioFile ();
|
|
|
|
mapon = -1;
|
|
}
|
|
|
|
//==========================================================================
|
|
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CA_Shutdown
|
|
=
|
|
= Closes all files
|
|
=
|
|
======================
|
|
*/
|
|
|
|
void CA_Shutdown (void)
|
|
{
|
|
int i,start;
|
|
|
|
if(maphandle != -1)
|
|
close(maphandle);
|
|
if(grhandle != -1)
|
|
close(grhandle);
|
|
if(audiohandle != -1)
|
|
close(audiohandle);
|
|
|
|
for(i=0; i<NUMCHUNKS; i++)
|
|
UNCACHEGRCHUNK(i);
|
|
free(pictable);
|
|
|
|
switch(oldsoundmode)
|
|
{
|
|
case sdm_Off:
|
|
return;
|
|
case sdm_PC:
|
|
start = STARTPCSOUNDS;
|
|
break;
|
|
case sdm_AdLib:
|
|
start = STARTADLIBSOUNDS;
|
|
break;
|
|
}
|
|
|
|
for(i=0; i<NUMSOUNDS; i++,start++)
|
|
UNCACHEAUDIOCHUNK(start);
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CA_CacheAudioChunk
|
|
=
|
|
======================
|
|
*/
|
|
|
|
int32_t CA_CacheAudioChunk (int chunk)
|
|
{
|
|
int32_t pos = Retro_SwapLES32(audiostarts[chunk]);
|
|
int32_t size = Retro_SwapLES32(audiostarts[chunk+1]) -pos;
|
|
|
|
/* already in memory */
|
|
if (audiosegs[chunk])
|
|
return size;
|
|
|
|
audiosegs[chunk]=(byte *) malloc(size);
|
|
CHECKMALLOCRESULT(audiosegs[chunk]);
|
|
|
|
lseek(audiohandle,pos,SEEK_SET);
|
|
read(audiohandle,audiosegs[chunk],size);
|
|
|
|
return size;
|
|
}
|
|
|
|
void CA_CacheAdlibSoundChunk (int chunk)
|
|
{
|
|
int32_t pos = Retro_SwapLES32(audiostarts[chunk]);
|
|
int32_t size = Retro_SwapLES32(audiostarts[chunk+1]) - pos;
|
|
|
|
/* already in memory */
|
|
if (audiosegs[chunk])
|
|
return;
|
|
|
|
lseek(audiohandle, pos, SEEK_SET);
|
|
read(audiohandle, bufferseg, ORIG_ADLIBSOUND_SIZE - 1); /* without data[1] */
|
|
|
|
AdLibSound *sound = (AdLibSound *) malloc(size + sizeof(AdLibSound) - ORIG_ADLIBSOUND_SIZE);
|
|
CHECKMALLOCRESULT(sound);
|
|
|
|
byte *ptr = (byte *) bufferseg;
|
|
sound->common.length = READLONGWORD(&ptr);
|
|
sound->common.priority = READWORD(&ptr);
|
|
sound->inst.mChar = *ptr++;
|
|
sound->inst.cChar = *ptr++;
|
|
sound->inst.mScale = *ptr++;
|
|
sound->inst.cScale = *ptr++;
|
|
sound->inst.mAttack = *ptr++;
|
|
sound->inst.cAttack = *ptr++;
|
|
sound->inst.mSus = *ptr++;
|
|
sound->inst.cSus = *ptr++;
|
|
sound->inst.mWave = *ptr++;
|
|
sound->inst.cWave = *ptr++;
|
|
sound->inst.nConn = *ptr++;
|
|
sound->inst.voice = *ptr++;
|
|
sound->inst.mode = *ptr++;
|
|
sound->inst.unused[0] = *ptr++;
|
|
sound->inst.unused[1] = *ptr++;
|
|
sound->inst.unused[2] = *ptr++;
|
|
sound->block = *ptr++;
|
|
|
|
read(audiohandle, sound->data, size - ORIG_ADLIBSOUND_SIZE + 1); /* + 1 because of byte data[1] */
|
|
|
|
audiosegs[chunk]=(byte *) sound;
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CA_LoadAllSounds
|
|
=
|
|
= Purges all sounds, then loads all new ones (mode switch)
|
|
=
|
|
======================
|
|
*/
|
|
|
|
void CA_LoadAllSounds (void)
|
|
{
|
|
unsigned start,i;
|
|
|
|
switch (oldsoundmode)
|
|
{
|
|
case sdm_Off:
|
|
goto cachein;
|
|
case sdm_PC:
|
|
start = STARTPCSOUNDS;
|
|
break;
|
|
case sdm_AdLib:
|
|
start = STARTADLIBSOUNDS;
|
|
break;
|
|
}
|
|
|
|
for (i=0;i<NUMSOUNDS;i++,start++)
|
|
UNCACHEAUDIOCHUNK(start);
|
|
|
|
cachein:
|
|
|
|
oldsoundmode = SoundMode;
|
|
|
|
switch (SoundMode)
|
|
{
|
|
case sdm_Off:
|
|
start = STARTADLIBSOUNDS; /* needed for priorities... */
|
|
break;
|
|
case sdm_PC:
|
|
start = STARTPCSOUNDS;
|
|
break;
|
|
case sdm_AdLib:
|
|
start = STARTADLIBSOUNDS;
|
|
break;
|
|
}
|
|
|
|
if(start == STARTADLIBSOUNDS)
|
|
{
|
|
for (i=0;i<NUMSOUNDS;i++,start++)
|
|
CA_CacheAdlibSoundChunk(start);
|
|
}
|
|
else
|
|
{
|
|
for (i=0;i<NUMSOUNDS;i++,start++)
|
|
CA_CacheAudioChunk(start);
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CAL_ExpandGrChunk
|
|
=
|
|
= Does whatever is needed with a pointer to a compressed chunk
|
|
=
|
|
======================
|
|
*/
|
|
|
|
void CAL_ExpandGrChunk (int chunk, int32_t *source)
|
|
{
|
|
int32_t expanded;
|
|
|
|
if (chunk >= STARTTILE8 && chunk < STARTEXTERNS)
|
|
{
|
|
/* expanded sizes of tile8/16/32 are implicit */
|
|
|
|
#define BLOCK 64
|
|
#define MASKBLOCK 128
|
|
|
|
/* tile 8s are all in one chunk! */
|
|
if (chunk<STARTTILE8M)
|
|
expanded = BLOCK*NUMTILE8;
|
|
else if (chunk<STARTTILE16)
|
|
expanded = MASKBLOCK*NUMTILE8M;
|
|
/* all other tiles are one/chunk */
|
|
else if (chunk<STARTTILE16M)
|
|
expanded = BLOCK*4;
|
|
else if (chunk<STARTTILE32)
|
|
expanded = MASKBLOCK*4;
|
|
else if (chunk<STARTTILE32M)
|
|
expanded = BLOCK*16;
|
|
else
|
|
expanded = MASKBLOCK*16;
|
|
}
|
|
else
|
|
{
|
|
/* everything else has an explicit size longword */
|
|
expanded = Retro_SwapLES32(*source++);
|
|
}
|
|
|
|
/*
|
|
* allocate final space, decompress it, and free bigbuffer.
|
|
* Sprites need to have shifts made and various other junk. */
|
|
grsegs[chunk]=(byte *) malloc(expanded);
|
|
CHECKMALLOCRESULT(grsegs[chunk]);
|
|
CAL_HuffExpand((byte *) source, grsegs[chunk], expanded, grhuffman);
|
|
}
|
|
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CA_CacheGrChunk
|
|
=
|
|
= Makes sure a given chunk is in memory, loadiing it if needed
|
|
=
|
|
======================
|
|
*/
|
|
|
|
void CA_CacheGrChunk (int chunk)
|
|
{
|
|
int32_t pos,compressed;
|
|
int32_t *source;
|
|
int next;
|
|
|
|
/* already in memory */
|
|
if (grsegs[chunk])
|
|
return;
|
|
|
|
/* load the chunk into a buffer,
|
|
* either the miscbuffer if it fits, or allocate
|
|
* a larger buffer. */
|
|
pos = GRFILEPOS(chunk);
|
|
|
|
/* $FFFFFFFF start is a sparse tile */
|
|
if (pos<0)
|
|
return;
|
|
|
|
next = chunk +1;
|
|
|
|
/* skip past any sparse tiles */
|
|
while (GRFILEPOS(next) == -1)
|
|
next++;
|
|
|
|
compressed = GRFILEPOS(next)-pos;
|
|
|
|
lseek(grhandle,pos,SEEK_SET);
|
|
|
|
if (compressed<=BUFFERSIZE)
|
|
{
|
|
read(grhandle,bufferseg,compressed);
|
|
source = bufferseg;
|
|
}
|
|
else
|
|
{
|
|
source = (int32_t *) malloc(compressed);
|
|
CHECKMALLOCRESULT(source);
|
|
read(grhandle,source,compressed);
|
|
}
|
|
|
|
CAL_ExpandGrChunk (chunk,source);
|
|
|
|
if (compressed>BUFFERSIZE)
|
|
free(source);
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CA_CacheScreen
|
|
=
|
|
= Decompresses a chunk from disk straight onto the screen
|
|
=
|
|
======================
|
|
*/
|
|
|
|
void CA_CacheScreen (int chunk)
|
|
{
|
|
int32_t pos,compressed,expanded;
|
|
memptr bigbufferseg;
|
|
int32_t *source;
|
|
int next;
|
|
unsigned x, y, scx, scy;
|
|
unsigned i, j;
|
|
byte *vbuf = NULL;
|
|
|
|
/* load the chunk into a buffer */
|
|
pos = GRFILEPOS(chunk);
|
|
next = chunk +1;
|
|
|
|
/* skip past any sparse tiles */
|
|
while (GRFILEPOS(next) == -1)
|
|
next++;
|
|
compressed = GRFILEPOS(next)-pos;
|
|
|
|
lseek(grhandle,pos,SEEK_SET);
|
|
|
|
bigbufferseg=malloc(compressed);
|
|
CHECKMALLOCRESULT(bigbufferseg);
|
|
read(grhandle,bigbufferseg,compressed);
|
|
source = (int32_t *) bigbufferseg;
|
|
|
|
expanded = Retro_SwapLES32(*source++);
|
|
|
|
/*
|
|
* allocate final space, decompress it, and free bigbuffer
|
|
* Sprites need to have shifts made and various other junk. */
|
|
byte *pic = (byte *) malloc(64000);
|
|
CHECKMALLOCRESULT(pic);
|
|
CAL_HuffExpand((byte *) source, pic, expanded, grhuffman);
|
|
|
|
vbuf = VL_LockSurface(curSurface);
|
|
for(y = 0, scy = 0; y < 200; y++, scy += scaleFactor)
|
|
{
|
|
for(x = 0, scx = 0; x < 320; x++, scx += scaleFactor)
|
|
{
|
|
byte col = pic[(y * 80 + (x >> 2)) + (x & 3) * 80 * 200];
|
|
for(i = 0; i < scaleFactor; i++)
|
|
for(j = 0; j < scaleFactor; j++)
|
|
vbuf[(scy + i) * curPitch + scx + j] = col;
|
|
}
|
|
}
|
|
VL_UnlockSurface(curSurface);
|
|
free(pic);
|
|
free(bigbufferseg);
|
|
}
|
|
|
|
//==========================================================================
|
|
|
|
/*
|
|
======================
|
|
=
|
|
= CA_CacheMap
|
|
=
|
|
= WOLF: This is specialized for a 64*64 map size
|
|
=
|
|
======================
|
|
*/
|
|
|
|
void CA_CacheMap (int mapnum)
|
|
{
|
|
int32_t pos,compressed;
|
|
int plane;
|
|
word *dest;
|
|
memptr bigbufferseg;
|
|
unsigned size;
|
|
word *source;
|
|
#ifdef CARMACIZED
|
|
word *buffer2seg;
|
|
int32_t expanded;
|
|
#endif
|
|
|
|
mapon = mapnum;
|
|
|
|
/* load the planes into the allready allocated buffers */
|
|
size = maparea*2;
|
|
|
|
for (plane = 0; plane<MAPPLANES; plane++)
|
|
{
|
|
pos = mapheaderseg[mapnum]->planestart[plane];
|
|
compressed = mapheaderseg[mapnum]->planelength[plane];
|
|
|
|
dest = mapsegs[plane];
|
|
|
|
lseek(maphandle,pos,SEEK_SET);
|
|
if (compressed<=BUFFERSIZE)
|
|
source = (word *) bufferseg;
|
|
else
|
|
{
|
|
bigbufferseg=malloc(compressed);
|
|
CHECKMALLOCRESULT(bigbufferseg);
|
|
source = (word *) bigbufferseg;
|
|
}
|
|
|
|
read(maphandle,source,compressed);
|
|
#ifdef CARMACIZED
|
|
// unhuffman, then unRLEW
|
|
// The huffman'd chunk has a two byte expanded length first
|
|
// The resulting RLEW chunk also does, even though it's not really
|
|
// needed
|
|
expanded = Retro_SwapLES16(*source);
|
|
source++;
|
|
buffer2seg = (word *) malloc(expanded);
|
|
CHECKMALLOCRESULT(buffer2seg);
|
|
CAL_CarmackExpand((byte *) source, buffer2seg,expanded);
|
|
CA_RLEWexpand(buffer2seg+1,dest,size,RLEWtag);
|
|
free(buffer2seg);
|
|
|
|
#else
|
|
/* unRLEW, skipping expanded length */
|
|
CA_RLEWexpand (source+1,dest,size,RLEWtag);
|
|
#endif
|
|
|
|
if (compressed>BUFFERSIZE)
|
|
free(bigbufferseg);
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
void CA_CannotOpen(const char *string)
|
|
{
|
|
char str[30];
|
|
|
|
strcpy(str,"Can't open ");
|
|
strcat(str,string);
|
|
strcat(str,"!\n");
|
|
Quit (str);
|
|
}
|