mirror of
https://github.com/libretro/libretro-wolfenstein3d.git
synced 2024-11-23 00:19:48 +00:00
163 lines
4.1 KiB
C
163 lines
4.1 KiB
C
#include "wl_def.h"
|
|
#include <retro_endian.h>
|
|
|
|
int ChunksInFile;
|
|
int PMSpriteStart;
|
|
int PMSoundStart;
|
|
|
|
bool PMSoundInfoPagePadded = false;
|
|
|
|
/* holds the whole VSWAP */
|
|
uint32_t *PMPageData;
|
|
size_t PMPageDataSize;
|
|
|
|
/*
|
|
* ChunksInFile+1 pointers to page starts.
|
|
* The last pointer points one byte after the last page.
|
|
*/
|
|
uint8_t **PMPages;
|
|
|
|
void PM_Startup(void)
|
|
{
|
|
int i, j, k;
|
|
long fileSize, pageDataSize;
|
|
FILE *file;
|
|
uint32_t *pageOffsets;
|
|
uint32_t dataStart;
|
|
word *pageLengths;
|
|
uint8_t *ptr;
|
|
int alignPadding = 0;
|
|
char fname[13] = "vswap.";
|
|
|
|
strcat(fname,extension);
|
|
|
|
file = fopen(fname,"rb");
|
|
if(!file)
|
|
CA_CannotOpen(fname);
|
|
|
|
ChunksInFile = 0;
|
|
fread(&ChunksInFile, sizeof(word), 1, file);
|
|
ChunksInFile = Retro_SwapLES32(ChunksInFile);
|
|
|
|
PMSpriteStart = 0;
|
|
fread(&PMSpriteStart, sizeof(word), 1, file);
|
|
PMSpriteStart = Retro_SwapLES32(PMSpriteStart);
|
|
|
|
PMSoundStart = 0;
|
|
fread(&PMSoundStart, sizeof(word), 1, file);
|
|
PMSoundStart = Retro_SwapLES32(PMSoundStart);
|
|
|
|
pageOffsets = (uint32_t *) malloc((ChunksInFile + 1) * sizeof(int32_t));
|
|
CHECKMALLOCRESULT(pageOffsets);
|
|
fread(pageOffsets, sizeof(uint32_t), ChunksInFile, file);
|
|
|
|
for (k = 0; k < ChunksInFile; k++)
|
|
{
|
|
pageOffsets[k] = (uint32_t)Retro_SwapLES32(pageOffsets[k]);
|
|
}
|
|
|
|
pageLengths = (word *) malloc(ChunksInFile * sizeof(word));
|
|
CHECKMALLOCRESULT(pageLengths);
|
|
fread(pageLengths, sizeof(word), ChunksInFile, file);
|
|
|
|
for(j = 0; j < ChunksInFile; j++)
|
|
{
|
|
pageLengths[j] = (word)Retro_SwapLES16(pageLengths[j]);
|
|
}
|
|
|
|
fseek(file, 0, SEEK_END);
|
|
fileSize = ftell(file);
|
|
pageDataSize = fileSize - pageOffsets[0];
|
|
|
|
if(pageDataSize > (size_t) -1)
|
|
Quit("The page file \"%s\" is too large!", fname);
|
|
|
|
pageOffsets[ChunksInFile] = fileSize;
|
|
|
|
dataStart = pageOffsets[0];
|
|
|
|
/* Check that all pageOffsets are valid */
|
|
for(i = 0; i < ChunksInFile; i++)
|
|
{
|
|
if(!pageOffsets[i])
|
|
continue; /* sparse page */
|
|
if(pageOffsets[i] < dataStart || pageOffsets[i] >= (size_t) fileSize)
|
|
Quit("Illegal page offset for page %i: %u (filesize: %u)",
|
|
i, pageOffsets[i], fileSize);
|
|
}
|
|
|
|
/* Calculate total amount of padding needed for sprites and sound info page */
|
|
for(i = PMSpriteStart; i < PMSoundStart; i++)
|
|
{
|
|
uint32_t offs;
|
|
|
|
if(!pageOffsets[i])
|
|
continue; /* sparse page */
|
|
|
|
offs = pageOffsets[i] - dataStart + alignPadding;
|
|
|
|
if(offs & 1)
|
|
alignPadding++;
|
|
}
|
|
|
|
if((pageOffsets[ChunksInFile - 1] - dataStart + alignPadding) & 1)
|
|
alignPadding++;
|
|
|
|
PMPageDataSize = (size_t) pageDataSize + alignPadding;
|
|
PMPageData = (uint32_t *) malloc(PMPageDataSize);
|
|
CHECKMALLOCRESULT(PMPageData);
|
|
|
|
PMPages = (uint8_t **) malloc((ChunksInFile + 1) * sizeof(uint8_t *));
|
|
CHECKMALLOCRESULT(PMPages);
|
|
|
|
/* Load pages and initialize PMPages pointers */
|
|
ptr = (uint8_t *) PMPageData;
|
|
|
|
for(i = 0; i < ChunksInFile; i++)
|
|
{
|
|
uint32_t size;
|
|
|
|
if(((i >= PMSpriteStart) && (i < PMSoundStart)) || (i == ChunksInFile - 1))
|
|
{
|
|
size_t offs = ptr - (uint8_t *) PMPageData;
|
|
|
|
/* pad with zeros to make it 2-byte aligned */
|
|
|
|
if(offs & 1)
|
|
{
|
|
*ptr++ = 0;
|
|
if(i == ChunksInFile - 1) PMSoundInfoPagePadded = true;
|
|
}
|
|
}
|
|
|
|
PMPages[i] = ptr;
|
|
|
|
if(!pageOffsets[i])
|
|
continue; // sparse page
|
|
|
|
/* Use specified page length,
|
|
* when next page is sparse page.
|
|
* Otherwise, calculate size from
|
|
* the offset difference between this and the next page. */
|
|
if(!pageOffsets[i + 1]) size = pageLengths[i];
|
|
else size = pageOffsets[i + 1] - pageOffsets[i];
|
|
|
|
fseek(file, pageOffsets[i], SEEK_SET);
|
|
fread(ptr, 1, size, file);
|
|
ptr += size;
|
|
}
|
|
|
|
/* last page points after page buffer */
|
|
PMPages[ChunksInFile] = ptr;
|
|
|
|
free(pageLengths);
|
|
free(pageOffsets);
|
|
fclose(file);
|
|
}
|
|
|
|
void PM_Shutdown(void)
|
|
{
|
|
free(PMPages);
|
|
free(PMPageData);
|
|
}
|