rockbox/apps/plugins/xrick/resources.c
Solomon Peachy 2c0bcc0be9 xrick: finally fix the red.
Change-Id: I1e0b4e2d77c8988a286051d391d99aeb7907f9c4
2025-09-07 15:21:59 -04:00

1297 lines
33 KiB
C

/*
* xrick/resources.c
*
* Copyright (C) 2008-2014 Pierluigi Vicinanza. All rights reserved.
*
* The use and distribution terms for this software are contained in the file
* named README, which can be found in the root of this distribution. By
* using this software in any fashion, you are agreeing to be bound by the
* terms of this license.
*
* You must not remove this notice, or any other, from this software.
*/
#include "xrick/resources.h"
#include "xrick/draw.h"
#include "xrick/ents.h"
#include "xrick/maps.h"
#include "xrick/util.h"
#include "xrick/data/sprites.h"
#include "xrick/data/tiles.h"
#include "xrick/data/pics.h"
#include "xrick/system/basic_funcs.h"
#include "xrick/system/miniz_config.h"
#include "xrick/3rd_party/miniz/miniz.c"
/*
* prototypes
*/
static bool readFile(const unsigned id);
static bool checkCrc32(const unsigned id);
static bool readHeader(file_t fp, const unsigned id);
static bool loadString(file_t fp, char ** str, const char terminator);
static void unloadString(char ** buffer);
static bool loadResourceFilelist(file_t fp);
static void unloadResourceFilelist(void);
static bool loadResourceEntdata(file_t fp);
static void unloadResourceEntdata(void);
static bool loadRawData(file_t fp, void ** buffer, const size_t size, size_t * count);
static void unloadRawData(void ** buffer, size_t * count);
static bool loadResourceMaps(file_t fp);
static void unloadResourceMaps(void);
static bool loadResourceSubmaps(file_t fp);
static void unloadResourceSubmaps(void);
static bool loadResourceImapsteps(file_t fp);
static void unloadResourceImapsteps(void);
static bool loadResourceImaptext(file_t fp);
static void unloadResourceImaptext(void);
static bool loadResourceHighScores(file_t fp);
static void unloadResourceHighScores(void);
static bool loadResourceSpritesData(file_t fp);
static void unloadResourceSpritesData(void);
static bool loadResourceTilesData(file_t fp);
static void unloadResourceTilesData(void);
static bool loadImage(file_t fp, img_t ** image);
static void unloadImage(img_t ** image);
#ifdef GFXST
static bool loadPicture(file_t fp, pic_t ** picture);
static void unloadPicture(pic_t ** picture);
#endif /* GFXST */
#ifdef ENABLE_SOUND
static bool fromResourceIdToSound(const unsigned id, sound_t *** sound);
static bool loadSound(const unsigned id);
static void unloadSound(const unsigned id);
#endif /* ENABLE_SOUND */
/*
* local vars
*/
static char * resourceFiles[Resource_MAX_COUNT] =
{
BOOTSTRAP_RESOURCE_NAME,
/* the rest initialised to NULL by default */
};
/*
* load 16b length + not-terminated string
*/
static bool loadString(file_t fp, char ** buffer, const char terminator)
{
size_t length;
U16 u16Temp;
char * bufferTemp;
if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
{
return false;
}
length = letoh16(u16Temp);
bufferTemp = sysmem_push(length + 1);
*buffer = bufferTemp;
if (!bufferTemp)
{
return false;
}
if (length)
{
if (sysfile_read(fp, bufferTemp, length, 1) != 1)
{
return false;
}
}
bufferTemp[length] = terminator;
return true;
}
/*
*
*/
static void unloadString(char ** buffer)
{
sysmem_pop(*buffer);
*buffer = NULL;
}
/*
*
*/
static bool loadResourceFilelist(file_t fp)
{
unsigned id;
for (id = Resource_PALETTE; id < Resource_MAX_COUNT; ++id)
{
if (!loadString(fp, &(resourceFiles[id]), 0x00))
{
return false;
}
}
return true;
}
/*
*
*/
static void unloadResourceFilelist()
{
unsigned id;
for (id = Resource_MAX_COUNT - 1; id >= Resource_PALETTE; --id)
{
unloadString(&(resourceFiles[id]));
}
}
/*
*
*/
static bool loadResourceEntdata(file_t fp)
{
size_t i;
U16 u16Temp;
resource_entdata_t dataTemp;
if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
{
return false;
}
ent_nbr_entdata = letoh16(u16Temp);
ent_entdata = sysmem_push(ent_nbr_entdata * sizeof(*ent_entdata));
if (!ent_entdata)
{
return false;
}
for (i = 0; i < ent_nbr_entdata; ++i)
{
if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
{
return false;
}
ent_entdata[i].w = dataTemp.w;
ent_entdata[i].h = dataTemp.h;
memcpy(&u16Temp, dataTemp.spr, sizeof(U16));
ent_entdata[i].spr = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.sni, sizeof(U16));
ent_entdata[i].sni = letoh16(u16Temp);
ent_entdata[i].trig_w = dataTemp.trig_w;
ent_entdata[i].trig_h = dataTemp.trig_h;
ent_entdata[i].snd = dataTemp.snd;
}
return true;
}
/*
*
*/
static void unloadResourceEntdata()
{
sysmem_pop(ent_entdata);
ent_entdata = NULL;
ent_nbr_entdata = 0;
}
/*
*
*/
static bool loadRawData(file_t fp, void ** buffer, const size_t size, size_t * count)
{
U16 u16Temp;
if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
{
return false;
}
*count = letoh16(u16Temp);
*buffer = sysmem_push((*count) * size);
if (!(*buffer))
{
return false;
}
if (sysfile_read(fp, *buffer, size, *count) != (int)(*count))
{
return false;
}
return true;
}
/*
*
*/
static void unloadRawData(void ** buffer, size_t * count)
{
sysmem_pop(*buffer);
*buffer = NULL;
*count = 0;
}
/*
*
*/
static bool loadResourceMaps(file_t fp)
{
size_t i;
U16 u16Temp;
resource_map_t dataTemp;
if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
{
return false;
}
map_nbr_maps = letoh16(u16Temp);
map_maps = sysmem_push(map_nbr_maps * sizeof(*map_maps));
if (!map_maps)
{
return false;
}
for (i = 0; i < map_nbr_maps; ++i)
{
#ifdef ENABLE_SOUND
sound_t **soundTemp;
#endif
if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
{
return false;
}
memcpy(&u16Temp, dataTemp.x, sizeof(U16));
map_maps[i].x = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.y, sizeof(U16));
map_maps[i].y = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.row, sizeof(U16));
map_maps[i].row = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.submap, sizeof(U16));
map_maps[i].submap = letoh16(u16Temp);
#ifdef ENABLE_SOUND
memcpy(&u16Temp, dataTemp.tuneId, sizeof(U16));
if (!fromResourceIdToSound(letoh16(u16Temp), &soundTemp))
{
return false;
}
map_maps[i].tune = *soundTemp;
#endif /* ENABLE_SOUND */
}
return true;
}
/*
*
*/
static void unloadResourceMaps()
{
sysmem_pop(map_maps);
map_maps = NULL;
map_nbr_maps = 0;
}
/*
*
*/
static bool loadResourceSubmaps(file_t fp)
{
size_t i;
U16 u16Temp;
resource_submap_t dataTemp;
if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
{
return false;
}
map_nbr_submaps = letoh16(u16Temp);
map_submaps = sysmem_push(map_nbr_submaps * sizeof(*map_submaps));
if (!map_submaps)
{
return false;
}
for (i = 0; i < map_nbr_submaps; ++i)
{
if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
{
return false;
}
memcpy(&u16Temp, dataTemp.page, sizeof(U16));
map_submaps[i].page = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.bnum, sizeof(U16));
map_submaps[i].bnum = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.connect, sizeof(U16));
map_submaps[i].connect = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.mark, sizeof(U16));
map_submaps[i].mark = letoh16(u16Temp);
}
return true;
}
/*
*
*/
static void unloadResourceSubmaps()
{
sysmem_pop(map_submaps);
map_submaps = NULL;
map_nbr_submaps = 0;
}
/*
*
*/
static bool loadResourceImapsteps(file_t fp)
{
size_t i;
U16 u16Temp;
resource_imapsteps_t dataTemp;
if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
{
return false;
}
screen_nbr_imapstesps = letoh16(u16Temp);
screen_imapsteps = sysmem_push(screen_nbr_imapstesps * sizeof(*screen_imapsteps));
if (!screen_imapsteps)
{
return false;
}
for (i = 0; i < screen_nbr_imapstesps; ++i)
{
if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
{
return false;
}
memcpy(&u16Temp, dataTemp.count, sizeof(U16));
screen_imapsteps[i].count = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.dx, sizeof(U16));
screen_imapsteps[i].dx = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.dy, sizeof(U16));
screen_imapsteps[i].dy = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.base, sizeof(U16));
screen_imapsteps[i].base = letoh16(u16Temp);
}
return true;
}
/*
*
*/
static void unloadResourceImapsteps()
{
sysmem_pop(screen_imapsteps);
screen_imapsteps = NULL;
screen_nbr_imapstesps = 0;
}
/*
*
*/
static bool loadResourceImaptext(file_t fp)
{
size_t i;
U16 u16Temp;
if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
{
return false;
}
screen_nbr_imaptext = letoh16(u16Temp);
screen_imaptext = sysmem_push(screen_nbr_imaptext * sizeof(*screen_imaptext));
if (!screen_imapsteps)
{
return false;
}
for (i = 0; i < screen_nbr_imaptext; ++i)
{
if (!loadString(fp, (char **)(&(screen_imaptext[i])), 0xFE))
{
return false;
}
}
return true;
}
/*
*
*/
static void unloadResourceImaptext()
{
int i;
for (i = screen_nbr_imaptext - 1; i >= 0; --i)
{
unloadString((char **)(&(screen_imaptext[i])));
}
sysmem_pop(screen_imaptext);
screen_imaptext = NULL;
screen_nbr_imaptext = 0;
}
/*
*
*/
static bool loadResourceHighScores(file_t fp)
{
size_t i;
U16 u16Temp;
U32 u32Temp;
resource_hiscore_t dataTemp;
if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
{
return false;
}
screen_nbr_hiscores = letoh16(u16Temp);
screen_highScores = sysmem_push(screen_nbr_hiscores * sizeof(*screen_highScores));
if (!screen_highScores)
{
return false;
}
for (i = 0; i < screen_nbr_hiscores; ++i)
{
if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
{
return false;
}
memcpy(&u32Temp, dataTemp.score, sizeof(U32));
screen_highScores[i].score = letoh32(u32Temp);
memcpy(screen_highScores[i].name, dataTemp.name, HISCORE_NAME_SIZE);
}
return true;
}
/*
*
*/
static void unloadResourceHighScores()
{
sysmem_pop(screen_highScores);
screen_highScores = NULL;
screen_nbr_hiscores = 0;
}
/*
*
*/
static bool loadResourceSpritesData(file_t fp)
{
size_t i, j;
U16 u16Temp;
if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
{
return false;
}
sprites_nbr_sprites = letoh16(u16Temp);
sprites_data = sysmem_push(sprites_nbr_sprites * sizeof(*sprites_data));
if (!sprites_data)
{
return false;
}
#ifdef GFXST
for (i = 0; i < sprites_nbr_sprites; ++i)
{
for (j = 0; j < SPRITES_NBR_DATA; ++j)
{
U32 u32Temp;
if (sysfile_read(fp, &u32Temp, sizeof(u32Temp), 1) != 1)
{
return false;
}
sprites_data[i][j] = letoh32(u32Temp);
}
}
#endif /* GFXST */
#ifdef GFXPC
for (i = 0; i < sprites_nbr_sprites; ++i)
{
for (j = 0; j < SPRITES_NBR_COLS; ++j)
{
size_t k;
for (k = 0; k < SPRITES_NBR_ROWS; ++k)
{
resource_spriteX_t dataTemp;
if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
{
return false;
}
memcpy(&u16Temp, dataTemp.mask, sizeof(U16));
sprites_data[i][j][k].mask = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.pict, sizeof(U16));
sprites_data[i][j][k].pict = letoh16(u16Temp);
}
}
}
#endif /* GFXPC */
return true;
}
/*
*
*/
static void unloadResourceSpritesData()
{
sysmem_pop(sprites_data);
sprites_data = NULL;
sprites_nbr_sprites = 0;
}
/*
*
*/
static bool loadResourceTilesData(file_t fp)
{
size_t i, j, k;
U16 u16Temp;
if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
{
return false;
}
tiles_nbr_banks = letoh16(u16Temp);
tiles_data = sysmem_push(tiles_nbr_banks * TILES_NBR_TILES * sizeof(*tiles_data));
if (!tiles_data)
{
return false;
}
for (i = 0; i < tiles_nbr_banks ; ++i)
{
for (j = 0; j < TILES_NBR_TILES; ++j)
{
for (k = 0; k < TILES_NBR_LINES ; ++k)
{
#ifdef GFXPC
if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
{
return false;
}
tiles_data[i * TILES_NBR_TILES + j][k] = letoh16(u16Temp);
#endif /* GFXPC */
#ifdef GFXST
U32 u32Temp;
if (sysfile_read(fp, &u32Temp, sizeof(u32Temp), 1) != 1)
{
return false;
}
tiles_data[i * TILES_NBR_TILES + j][k] = letoh32(u32Temp);
#endif /* GFXST */
}
}
}
return true;
}
/*
*
*/
static void unloadResourceTilesData()
{
sysmem_pop(tiles_data);
tiles_data = NULL;
tiles_nbr_banks = 0;
}
/*
*
*/
static bool loadImage(file_t fp, img_t ** image)
{
U16 u16Temp;
size_t pixelCount, colorCount;
resource_pic_t dataTemp;
img_t * imgTemp;
void * vp;
bool success;
imgTemp = sysmem_push(sizeof(*imgTemp));
*image = imgTemp;
if (!imgTemp)
{
return false;
}
if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
{
return false;
}
memcpy(&u16Temp, dataTemp.width, sizeof(U16));
imgTemp->width = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.height, sizeof(U16));
imgTemp->height = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.xPos, sizeof(U16));
imgTemp->xPos = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.yPos, sizeof(U16));
imgTemp->yPos = letoh16(u16Temp);
vp = imgTemp->colors;
success = loadRawData(fp, &vp, sizeof(*imgTemp->colors), &colorCount);
imgTemp->ncolors = colorCount;
imgTemp->colors = vp;
if (!success)
{
return false;
}
pixelCount = (imgTemp->width * imgTemp->height); /*we use 8b per pixel*/
imgTemp->pixels = sysmem_push(pixelCount * sizeof(U8));
if (!imgTemp->pixels)
{
return false;
}
if (sysfile_read(fp, imgTemp->pixels, sizeof(U8), pixelCount) != (int)pixelCount)
{
return false;
}
return true;
}
/*
*
*/
static void unloadImage(img_t ** image)
{
if (*image)
{
sysmem_pop((*image)->pixels);
sysmem_pop((*image)->colors);
}
sysmem_pop(*image);
*image = NULL;
}
/*
*
*/
#ifdef GFXST
static bool loadPicture(file_t fp, pic_t ** picture)
{
U16 u16Temp;
size_t i, pixelWords32b;
resource_pic_t dataTemp;
pic_t * picTemp;
picTemp = sysmem_push(sizeof(*picTemp));
*picture = picTemp;
if (!picTemp)
{
return false;
}
if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
{
return false;
}
memcpy(&u16Temp, dataTemp.width, sizeof(U16));
picTemp->width = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.height, sizeof(U16));
picTemp->height = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.xPos, sizeof(U16));
picTemp->xPos = letoh16(u16Temp);
memcpy(&u16Temp, dataTemp.yPos, sizeof(U16));
picTemp->yPos = letoh16(u16Temp);
pixelWords32b = (picTemp->width * picTemp->height) / 8; /*we use 4b per pixel*/
picTemp->pixels = sysmem_push(pixelWords32b * sizeof(U32));
if (!picTemp->pixels)
{
return false;
}
for (i = 0; i < pixelWords32b; ++i)
{
U32 u32Temp;
if (sysfile_read(fp, &u32Temp, sizeof(u32Temp), 1) != 1)
{
return false;
}
picTemp->pixels[i] = letoh32(u32Temp);
}
return true;
}
/*
*
*/
static void unloadPicture(pic_t ** picture)
{
if (*picture)
{
sysmem_pop((*picture)->pixels);
}
sysmem_pop(*picture);
*picture = NULL;
}
#endif /* GFXST */
#ifdef ENABLE_SOUND
/*
*
*/
static bool fromResourceIdToSound(const unsigned id, sound_t *** sound)
{
switch (id)
{
case Resource_SOUNDBOMBSHHT: *sound = &soundBombshht; return true;
case Resource_SOUNDBONUS: *sound = &soundBonus; return true;
case Resource_SOUNDBOX: *sound = &soundBox; return true;
case Resource_SOUNDBULLET: *sound = &soundBullet; return true;
case Resource_SOUNDCRAWL: *sound = &soundCrawl; return true;
case Resource_SOUNDDIE: *sound = &soundDie; return true;
case Resource_SOUNDENTITY0: *sound = &(soundEntity[0]); return true;
case Resource_SOUNDENTITY1: *sound = &(soundEntity[1]); return true;
case Resource_SOUNDENTITY2: *sound = &(soundEntity[2]); return true;
case Resource_SOUNDENTITY3: *sound = &(soundEntity[3]); return true;
case Resource_SOUNDENTITY4: *sound = &(soundEntity[4]); return true;
case Resource_SOUNDENTITY5: *sound = &(soundEntity[5]); return true;
case Resource_SOUNDENTITY6: *sound = &(soundEntity[6]); return true;
case Resource_SOUNDENTITY7: *sound = &(soundEntity[7]); return true;
case Resource_SOUNDENTITY8: *sound = &(soundEntity[8]); return true;
case Resource_SOUNDEXPLODE: *sound = &soundExplode; return true;
case Resource_SOUNDGAMEOVER: *sound = &soundGameover; return true;
case Resource_SOUNDJUMP: *sound = &soundJump; return true;
case Resource_SOUNDPAD: *sound = &soundPad; return true;
case Resource_SOUNDSBONUS1: *sound = &soundSbonus1; return true;
case Resource_SOUNDSBONUS2: *sound = &soundSbonus2; return true;
case Resource_SOUNDSTICK: *sound = &soundStick; return true;
case Resource_SOUNDTUNE0: *sound = &soundTune0; return true;
case Resource_SOUNDTUNE1: *sound = &soundTune1; return true;
case Resource_SOUNDTUNE2: *sound = &soundTune2; return true;
case Resource_SOUNDTUNE3: *sound = &soundTune3; return true;
case Resource_SOUNDTUNE4: *sound = &soundTune4; return true;
case Resource_SOUNDTUNE5: *sound = &soundTune5; return true;
case Resource_SOUNDWALK: *sound = &soundWalk; return true;
default:
{
sys_error("(resources) no associated sound found for ID %d", id);
return false;
}
}
}
/*
*
*/
static bool loadSound(const unsigned id)
{
sound_t ** sound;
file_t fp;
wave_header_t header;
U16 u16Temp;
U32 u32Temp;
int bytesRead;
bool isHeaderValid;
if (!fromResourceIdToSound(id, &sound))
{
return false;
}
*sound = sysmem_push(sizeof(**sound));
if (!*sound)
{
return false;
}
(*sound)->buf = NULL;
(*sound)->dispose = true; /* sounds are "fire and forget" by default */
(*sound)->name = u_strdup(resourceFiles[id]);
if (!(*sound)->name)
{
return false;
}
fp = sysfile_open(resourceFiles[id]);
if (!fp)
{
sys_error("(resources) unable to open \"%s\"", resourceFiles[id]);
return false;
}
bytesRead = sysfile_read(fp, &header, sizeof(header), 1);
sysfile_close(fp);
if (bytesRead != 1)
{
sys_error("(resources) unable to read WAVE header from \"%s\"", resourceFiles[id]);
return false;
}
isHeaderValid = false;
for (;;)
{
if (memcmp(header.riffChunkId, "RIFF", 4) ||
memcmp(header.riffType, "WAVE", 4) ||
memcmp(header.formatChunkId, "fmt ", 4) ||
memcmp(header.dataChunkId, "data", 4))
{
break;
}
memcpy(&u16Temp, header.audioFormat, sizeof(u16Temp));
if (letoh16(u16Temp) != Wave_AUDIO_FORMAT)
{
break;
}
memcpy(&u16Temp, header.channelCount, sizeof(u16Temp));
if (letoh16(u16Temp) != Wave_CHANNEL_COUNT)
{
break;
}
memcpy(&u32Temp, header.sampleRate, sizeof(u32Temp));
if (letoh32(u32Temp) != Wave_SAMPLE_RATE)
{
isHeaderValid = false;
break;
}
memcpy(&u16Temp, header.bitsPerSample, sizeof(u16Temp));
if (letoh16(u16Temp) != Wave_BITS_PER_SAMPLE)
{
isHeaderValid = false;
break;
}
memcpy(&u32Temp, header.dataChunkSize, sizeof(u32Temp));
(*sound)->len = letoh32(u32Temp);
isHeaderValid = true;
break;
}
if (!isHeaderValid)
{
sys_error("(resources) incompatible WAVE header for \"%s\"", resourceFiles[id]);
return false;
}
return true;
}
/*
*
*/
static void unloadSound(const unsigned id)
{
sound_t ** sound;
if (!fromResourceIdToSound(id, &sound))
{
return;
}
if (!*sound)
{
return;
}
sysmem_pop((*sound)->name);
sysmem_pop(*sound);
*sound = NULL;
}
#endif /* ENABLE_SOUND */
/*
*
*/
static bool readHeader(file_t fp, const unsigned id)
{
resource_header_t header;
U16 u16Temp;
if (sysfile_read(fp, &header, sizeof(header), 1) != 1)
{
sys_error("(resources) unable to read header from \"%s\"", resourceFiles[id]);
return false;
}
if (memcmp(header.magic, resource_magic, sizeof(header.magic)) != 0)
{
sys_error("(resources) wrong header for \"%s\"", resourceFiles[id]);
return false;
}
memcpy(&u16Temp, header.version, sizeof(u16Temp));
u16Temp = htole16(u16Temp);
if (u16Temp != DATA_VERSION)
{
sys_error("(resources) incompatible version for \"%s\"", resourceFiles[id]);
return false;
}
memcpy(&u16Temp, header.resourceId, sizeof(u16Temp));
u16Temp = htole16(u16Temp);
if (u16Temp != id)
{
sys_error("(resources) mismatching ID for \"%s\"", resourceFiles[id]);
return false;
}
return true;
}
/*
*
*/
static bool checkCrc32(const unsigned id)
{
int bytesRead;
U8 tempBuffer[1024];
U32 expectedCrc32, calculatedCrc32 = MZ_CRC32_INIT;
file_t fp = sysfile_open(resourceFiles[id]);
if (fp == NULL)
{
sys_error("(resources) unable to open \"%s\"", resourceFiles[id]);
return false;
}
bytesRead = sysfile_read(fp, tempBuffer, sizeof(U32), 1); /* prepare beginning of buffer for the following loop */
if (bytesRead != 1)
{
sys_error("(resources) not enough data for \"%s\"", resourceFiles[id]);
sysfile_close(fp);
return false;
}
do
{
bytesRead = sysfile_read(fp, tempBuffer + sizeof(U32), sizeof(U8), sizeof(tempBuffer) - sizeof(U32));
calculatedCrc32 = mz_crc32(calculatedCrc32, tempBuffer, bytesRead);
memcpy(tempBuffer, tempBuffer + bytesRead, sizeof(U32));
} while (bytesRead == sizeof(tempBuffer) - sizeof(U32));
sysfile_close(fp);
memcpy(&expectedCrc32, tempBuffer, sizeof(U32));
expectedCrc32 = letoh32(expectedCrc32);
if (expectedCrc32 != calculatedCrc32)
{
sys_error("(resources) crc check failed for \"%s\"", resourceFiles[id]);
return false;
}
return true;
}
/*
*
*/
static bool readFile(const unsigned id)
{
bool success;
file_t fp;
void * vp;
switch (id)
{
#ifndef GFXST
case Resource_PICHAF: /* fallthrough */
case Resource_PICCONGRATS: /* fallthrough */
case Resource_PICSPLASH: return true;
#endif /* ndef GFXST */
#ifndef GFXPC
case Resource_IMAINHOFT: /* fallthrough */
case Resource_IMAINRDT: /* fallthrough */
case Resource_IMAINCDC: /* fallthrough */
case Resource_SCREENCONGRATS: return true;
#endif /* ndef GFXPC */
default: break;
}
if (resourceFiles[id] == NULL)
{
sys_error("(resources) resource ID %d not available", id);
return false;
}
if (!checkCrc32(id))
{
return false;
}
fp = sysfile_open(resourceFiles[id]);
if (fp == NULL)
{
if (id == Resource_FILELIST)
sys_error("Please install resource files!");
else
sys_error("(resources) unable to open \"%s\"", resourceFiles[id]);
return false;
}
success = readHeader(fp, id);
if (success)
{
switch (id)
{
case Resource_FILELIST: success = loadResourceFilelist(fp); break;
case Resource_PALETTE:
{
vp = game_colors;
success = loadRawData(fp, &vp, sizeof(*game_colors), &game_color_count);
game_colors = vp;
break;
}
case Resource_ENTDATA: success = loadResourceEntdata(fp); break;
case Resource_SPRSEQ:
{
vp = ent_sprseq;
success = loadRawData(fp, &vp, sizeof(*ent_sprseq), &ent_nbr_sprseq);
ent_sprseq = vp;
break;
}
case Resource_MVSTEP:
{
vp = ent_mvstep;
success = loadRawData(fp, &vp, sizeof(*ent_mvstep), &ent_nbr_mvstep);
ent_mvstep = vp;
break;
}
case Resource_MAPS: success = loadResourceMaps(fp); break;
case Resource_SUBMAPS: success = loadResourceSubmaps(fp); break;
case Resource_CONNECT:
{
vp = map_connect;
success = loadRawData(fp, &vp, sizeof(*map_connect), &map_nbr_connect);
map_connect = vp;
break;
}
case Resource_BNUMS:
{
vp = map_bnums;
success = loadRawData(fp, &vp, sizeof(*map_bnums), &map_nbr_bnums);
map_bnums = vp;
break;
}
case Resource_BLOCKS:
{
vp = map_blocks;
success = loadRawData(fp, &vp, sizeof(*map_blocks), &map_nbr_blocks);
map_blocks = vp;
break;
}
case Resource_MARKS:
{
vp = map_marks;
success = loadRawData(fp, &vp, sizeof(*map_marks), &map_nbr_marks);
map_marks = vp;
break;
}
case Resource_EFLGC:
{
vp = map_eflg_c;
success = loadRawData(fp, &vp, sizeof(*map_eflg_c), &map_nbr_eflgc);
map_eflg_c = vp;
break;
}
case Resource_IMAPSL:
{
vp = screen_imapsl;
success = loadRawData(fp, &vp, sizeof(*screen_imapsl), &screen_nbr_imapsl);
screen_imapsl = vp;
break;
}
case Resource_IMAPSTEPS: success = loadResourceImapsteps(fp); break;
case Resource_IMAPSOFS:
{
vp = screen_imapsofs;
success = loadRawData(fp, &vp, sizeof(*screen_imapsofs), &screen_nbr_imapsofs);
screen_imapsofs = vp;
break;
}
case Resource_IMAPTEXT: success = loadResourceImaptext(fp); break;
case Resource_GAMEOVERTXT: success = loadString(fp, (char **)(&screen_gameovertxt), 0xFE); break;
case Resource_PAUSEDTXT: success = loadString(fp, (char **)(&screen_pausedtxt), 0xFE); break;
case Resource_SPRITESDATA: success = loadResourceSpritesData(fp); break;
case Resource_TILESDATA: success = loadResourceTilesData(fp); break;
case Resource_HIGHSCORES: success = loadResourceHighScores(fp); break;
case Resource_IMGSPLASH: success = loadImage(fp, &img_splash); break;
#ifdef GFXST
case Resource_PICHAF: success = loadPicture(fp, &pic_haf); break;
case Resource_PICCONGRATS: success = loadPicture(fp, &pic_congrats); break;
case Resource_PICSPLASH: success = loadPicture(fp, &pic_splash); break;
#endif /* GFXST */
#ifdef GFXPC
case Resource_IMAINHOFT: success = loadString(fp, (char **)(&screen_imainhoft), 0xFE); break;
case Resource_IMAINRDT: success = loadString(fp, (char **)(&screen_imainrdt), 0xFE); break;
case Resource_IMAINCDC: success = loadString(fp, (char **)(&screen_imaincdc), 0xFE); break;
case Resource_SCREENCONGRATS: success = loadString(fp, (char **)(&screen_congrats), 0xFE); break;
#endif /* GFXPC */
default: success = false; break;
}
}
if (!success)
{
sys_error("(resources) error when parsing \"%s\"", resourceFiles[id]);
}
sysfile_close(fp);
return success;
}
/*
*
*/
bool resources_load()
{
bool success;
unsigned id;
/* note: loading order is important: file list first, then sounds, then the rest */
success = readFile(Resource_FILELIST);
#ifdef ENABLE_SOUND
for (id = Resource_SOUNDBOMBSHHT; (id <= Resource_SOUNDWALK) && success; ++id)
{
success = loadSound(id);
}
#endif /* ENABLE_SOUND */
for (id = Resource_PALETTE; (id <= Resource_SCREENCONGRATS) && success; ++id)
{
success = readFile(id);
}
return success;
}
/*
*
*/
void resources_unload()
{
int id;
void * vp;
for (id = Resource_SCREENCONGRATS; id >= Resource_PALETTE; --id)
{
switch (id)
{
case Resource_PALETTE:
{
vp = game_colors;
unloadRawData(&vp, &game_color_count);
game_colors = vp;
break;
}
case Resource_ENTDATA: unloadResourceEntdata(); break;
case Resource_SPRSEQ:
{
vp = ent_sprseq;
unloadRawData(&vp, &ent_nbr_sprseq);
ent_sprseq = vp;
break;
}
case Resource_MVSTEP:
{
vp = ent_mvstep;
unloadRawData(&vp, &ent_nbr_mvstep);
ent_mvstep = vp;
break;
}
case Resource_MAPS: unloadResourceMaps(); break;
case Resource_SUBMAPS: unloadResourceSubmaps(); break;
case Resource_CONNECT:
{
vp = map_connect;
unloadRawData(&vp, &map_nbr_connect);
map_connect = vp;
break;
}
case Resource_BNUMS:
{
vp = map_bnums;
unloadRawData(&vp, &map_nbr_bnums);
map_bnums = vp;
break;
}
case Resource_BLOCKS:
{
vp = map_blocks;
unloadRawData(&vp, &map_nbr_blocks);
map_blocks = vp;
break;
}
case Resource_MARKS:
{
vp = map_marks;
unloadRawData(&vp, &map_nbr_marks);
map_marks = vp;
break;
}
case Resource_EFLGC:
{
vp = map_eflg_c;
unloadRawData(&vp, &map_nbr_eflgc);
map_eflg_c = vp;
break;
}
case Resource_IMAPSL:
{
vp = screen_imapsl;
unloadRawData(&vp, &screen_nbr_imapsl);
screen_imapsl = vp;
break;
}
case Resource_IMAPSTEPS: unloadResourceImapsteps(); break;
case Resource_IMAPSOFS:
{
vp = screen_imapsofs;
unloadRawData(&vp, &screen_nbr_imapsofs);
screen_imapsofs = vp;
break;
}
case Resource_IMAPTEXT: unloadResourceImaptext(); break;
case Resource_GAMEOVERTXT: unloadString((char **)(&screen_gameovertxt)); break;
case Resource_PAUSEDTXT: unloadString((char **)(&screen_pausedtxt)); break;
case Resource_SPRITESDATA: unloadResourceSpritesData(); break;
case Resource_TILESDATA: unloadResourceTilesData(); break;
case Resource_HIGHSCORES: unloadResourceHighScores(); break;
case Resource_IMGSPLASH: unloadImage(&img_splash); break;
#ifdef GFXST
case Resource_PICHAF: unloadPicture(&pic_haf); break;
case Resource_PICCONGRATS: unloadPicture(&pic_congrats); break;
case Resource_PICSPLASH: unloadPicture(&pic_splash); break;
#endif /* GFXST */
#ifdef GFXPC
case Resource_IMAINHOFT: unloadString((char **)(&screen_imainhoft)); break;
case Resource_IMAINRDT: unloadString((char **)(&screen_imainrdt)); break;
case Resource_IMAINCDC: unloadString((char **)(&screen_imaincdc)); break;
case Resource_SCREENCONGRATS: unloadString((char **)(&screen_congrats)); break;
#endif /* GFXPC */
default: break;
}
}
#ifdef ENABLE_SOUND
for (id = Resource_SOUNDWALK; id >= Resource_SOUNDBOMBSHHT; --id)
{
unloadSound(id);
}
#endif /* ENABLE_SOUND */
unloadResourceFilelist();
}
/* eof */