mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2024-12-27 04:41:23 +00:00
392 lines
8.2 KiB
C
392 lines
8.2 KiB
C
// Emacs style mode select -*- C++ -*-
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// libwad: Doom WAD format interface library.
|
|
// Copyright (C) 2011 by Callum Dickinson.
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//-----------------------------------------------------------------------------
|
|
/// \file lump.c
|
|
/// \brief Lump interface functionality.
|
|
|
|
#include "wad_static.h"
|
|
|
|
//
|
|
// Create a lump name from the file name
|
|
// of a lump. Used for when no name for
|
|
// a lump was given.
|
|
//
|
|
char *WAD_LumpNameFromFileName(char *path)
|
|
{
|
|
wad_int32_t i;
|
|
char *name, *tempname, *file = WAD_BaseName(path);
|
|
|
|
if (!file)
|
|
return NULL;
|
|
|
|
//
|
|
// Process the filename for a suitable lump name.
|
|
//
|
|
// Get rid of any hidden file period.
|
|
if (file[0] == '.')
|
|
{
|
|
if (!(tempname = malloc(sizeof(*file) * strlen(&file[1]))))
|
|
{
|
|
free(file);
|
|
return NULL;
|
|
}
|
|
strcpy(tempname, &file[1]);
|
|
free(file);
|
|
}
|
|
else
|
|
tempname = file;
|
|
|
|
// Get rid of any extensions.
|
|
for (i = 0; tempname[i] != '.' && tempname[i] != '\0'; i++);
|
|
|
|
// Then, take the first eight characters of
|
|
// the resulting filename to get the lump name.
|
|
if (i > 8)
|
|
i = 8;
|
|
|
|
if (!(name = malloc(sizeof(*name) * (i+1))))
|
|
{
|
|
free(tempname);
|
|
return NULL;
|
|
}
|
|
|
|
strncpy(name, tempname, i);
|
|
name[i+1] = '\0';
|
|
|
|
//
|
|
// Done processing lump name.
|
|
//
|
|
free(tempname);
|
|
return name;
|
|
}
|
|
|
|
lump_t *WAD_LumpInWADByNum(wad_t *wad, wad_uint32_t num)
|
|
{
|
|
lump_t *lump;
|
|
|
|
if (!wad || !num)
|
|
return NULL;
|
|
|
|
for (lump = wad->lumps; lump; lump = lump->next)
|
|
if (num == lump->num)
|
|
return lump;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
lump_t *WAD_LumpInWADByName(wad_t *wad, const char *name)
|
|
{
|
|
lump_t *lump;
|
|
|
|
if (!wad || !name)
|
|
return NULL;
|
|
|
|
for (lump = wad->lumps; lump; lump = lump->next)
|
|
if (!strcmp(name, lump->name))
|
|
return lump;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
lump_t *WAD_LumpByName(const char *name)
|
|
{
|
|
wad_uint32_t i;
|
|
lump_t *lump;
|
|
|
|
for (i = 0; i < wad_numwads; i = WAD_WADLoopAdvance(i))
|
|
if ((lump = WAD_LumpInWADByName(WAD_WADByNum(i), name)))
|
|
return lump;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
inline wad_uint32_t WAD_LumpNum(lump_t *lump)
|
|
{
|
|
return lump->num;
|
|
}
|
|
|
|
inline wad_uint32_t WAD_LumpNumInWADByName(wad_t *wad, const char *name)
|
|
{
|
|
return WAD_LumpNum(WAD_LumpInWADByName(wad, name));
|
|
}
|
|
|
|
inline wad_uint32_t WAD_LumpNumByName(const char *name)
|
|
{
|
|
return WAD_LumpNum(WAD_LumpByName(name));
|
|
}
|
|
|
|
inline size_t WAD_LumpSize(lump_t *lump)
|
|
{
|
|
return lump->size;
|
|
}
|
|
|
|
inline size_t WAD_LumpSizeInWADByName(wad_t *wad, const char *name)
|
|
{
|
|
return WAD_LumpSize(WAD_LumpInWADByName(wad, name));
|
|
}
|
|
|
|
inline size_t WAD_LumpSizeByName(const char *name)
|
|
{
|
|
return WAD_LumpSize(WAD_LumpByName(name));
|
|
}
|
|
|
|
static void WAD_AddLumpToTree(lump_t *lump, lump_t *destlump)
|
|
{
|
|
lump_t *l;
|
|
|
|
if (destlump)
|
|
{
|
|
lump->wad = destlump->wad;
|
|
lump->num = destlump->num;
|
|
for (l = destlump; l; l = l->next)
|
|
l->num++;
|
|
if (destlump->prev)
|
|
destlump->prev->next = lump;
|
|
lump->prev = destlump->prev;
|
|
destlump->prev = lump;
|
|
lump->next = destlump;
|
|
}
|
|
else
|
|
{
|
|
for (l = lump->wad->lumps; l; l = l->next)
|
|
if (!l->next)
|
|
break;
|
|
lump->num = lump->wad->header->numlumps;
|
|
l->next = lump;
|
|
lump->prev = l;
|
|
lump->next = NULL;
|
|
}
|
|
lump->wad->header->numlumps++;
|
|
}
|
|
|
|
lump_t *WAD_AddLump(wad_t *wad, lump_t *destlump, const char *name, const char *filename)
|
|
{
|
|
// The open lump file.
|
|
FILE *file = NULL;
|
|
// Pointer to the lump.
|
|
lump_t *lump;
|
|
// Lump structure.
|
|
wad_uint64_t disksize; // lump->disksize
|
|
size_t size; // lump->size
|
|
wad_boolean_t compressed;// lump->compressed
|
|
void *data; // lump->data
|
|
|
|
if (!wad)
|
|
return NULL;
|
|
|
|
if (!name && !filename)
|
|
return NULL;
|
|
|
|
if (filename)
|
|
{
|
|
if (!(file = fopen(filename, "rb")))
|
|
return NULL;
|
|
|
|
fseek(file, 0, SEEK_END);
|
|
disksize = size = (unsigned)ftell(file);
|
|
compressed = false;
|
|
|
|
|
|
if (!(data = malloc(size)))
|
|
{
|
|
fclose(file);
|
|
return NULL;
|
|
}
|
|
|
|
fseek(file, 0, SEEK_SET);
|
|
if (fread(data, disksize, 1, file) < 1)
|
|
return NULL;
|
|
fclose(file);
|
|
}
|
|
else
|
|
{
|
|
disksize = size = 0;
|
|
compressed = false;
|
|
data = NULL;
|
|
}
|
|
|
|
|
|
if (!(lump = malloc(sizeof(*lump))))
|
|
{
|
|
WAD_FreeMemory(NULL, NULL, NULL, lump, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
lump->wad = wad;
|
|
if (!strcpy(lump->name, (name) ? name : WAD_LumpNameFromFileName((char *)filename)))
|
|
{
|
|
WAD_FreeMemory(NULL, NULL, NULL, lump, NULL);
|
|
return NULL;
|
|
}
|
|
lump->disksize = disksize;
|
|
lump->size = size;
|
|
lump->compressed = compressed;
|
|
|
|
lump->data = data;
|
|
|
|
WAD_AddLumpToTree(lump, destlump);
|
|
|
|
return lump;
|
|
}
|
|
|
|
inline lump_t *WAD_AddLumpInWADByNum(wad_t *wad, wad_uint32_t num, const char *name, const char *filename)
|
|
{
|
|
return WAD_AddLump(wad, WAD_LumpInWADByNum(wad, num), name, filename);
|
|
}
|
|
|
|
inline lump_t *WAD_AddLumpInWADByName(wad_t *wad, const char *destname, const char *name, const char *filename)
|
|
{
|
|
return WAD_AddLump(wad, WAD_LumpInWADByName(wad, destname), name, filename);
|
|
}
|
|
|
|
inline lump_t *WAD_AddLumpByName(const char *destname, const char *name, const char *filename)
|
|
{
|
|
lump_t *l = WAD_LumpByName(destname);
|
|
return WAD_AddLump(l->wad, l, name, filename);
|
|
}
|
|
|
|
lump_t *WAD_CacheLump(lump_t *lump)
|
|
{
|
|
return lump; // TODO: WAD_CacheLump, dynamic lump loading.
|
|
}
|
|
|
|
inline lump_t *WAD_CacheLumpInWADByNum(wad_t *wad, wad_uint32_t num)
|
|
{
|
|
return WAD_CacheLump(WAD_LumpInWADByNum(wad, num));
|
|
}
|
|
|
|
inline lump_t *WAD_CacheLumpInWADByName(wad_t *wad, const char *name)
|
|
{
|
|
return WAD_CacheLump(WAD_LumpInWADByName(wad, name));
|
|
}
|
|
|
|
inline lump_t *WAD_CacheLumpByName(const char *name)
|
|
{
|
|
return WAD_CacheLump(WAD_LumpByName(name));
|
|
}
|
|
|
|
lump_t *WAD_MoveLump(lump_t *lump, lump_t *destlump)
|
|
{
|
|
lump_t *l;
|
|
|
|
if (!destlump)
|
|
return NULL;
|
|
|
|
//
|
|
// Link the previous and next nodes in the WAD tree with each other.
|
|
//
|
|
if (lump->next)
|
|
{
|
|
lump->next->prev = lump->prev;
|
|
for (l = lump->next; l; l = l->next)
|
|
l->num--;
|
|
}
|
|
if (lump->prev)
|
|
lump->prev->next = lump->next;
|
|
lump->wad->header->numlumps--;
|
|
|
|
//
|
|
WAD_AddLumpToTree(lump, destlump);
|
|
|
|
return lump;
|
|
}
|
|
|
|
inline lump_t *WAD_MoveLumpInWADByNum(wad_t *wad, wad_uint32_t num, wad_t *destwad, wad_uint32_t destnum)
|
|
{
|
|
return WAD_MoveLump(WAD_LumpInWADByNum(wad, num), WAD_LumpInWADByNum(destwad, destnum));
|
|
}
|
|
|
|
inline lump_t *WAD_MoveLumpInWADByName(wad_t *wad, const char *name, wad_t *destwad, const char *destname)
|
|
{
|
|
return WAD_MoveLump(WAD_LumpInWADByName(wad, name), WAD_LumpInWADByName(destwad, destname));
|
|
}
|
|
|
|
inline lump_t *WAD_MoveLumpByName(const char *name, const char *destname)
|
|
{
|
|
return WAD_MoveLump(WAD_LumpByName(name), WAD_LumpByName(destname));
|
|
}
|
|
|
|
void WAD_UncacheLump(lump_t *lump)
|
|
{
|
|
(void)lump; // TODO: WAD_UncacheLump, dynamic lump loading.
|
|
}
|
|
|
|
inline void WAD_UncacheLumpInWADByNum(wad_t *wad, wad_uint32_t num)
|
|
{
|
|
WAD_UncacheLump(WAD_LumpInWADByNum(wad, num));
|
|
}
|
|
|
|
inline void WAD_UncacheLumpInWADByName(wad_t *wad, const char *name)
|
|
{
|
|
WAD_UncacheLump(WAD_LumpInWADByName(wad, name));
|
|
}
|
|
|
|
inline void WAD_UncacheLumpByName(const char *name)
|
|
{
|
|
WAD_UncacheLump(WAD_LumpByName(name));
|
|
}
|
|
|
|
void WAD_RemoveLump(lump_t *lump)
|
|
{
|
|
lump_t *l;
|
|
|
|
if (!lump)
|
|
return;
|
|
|
|
//
|
|
// Link the previous and next nodes in the WAD tree with each other.
|
|
//
|
|
lump->next->prev = lump->prev;
|
|
lump->prev->next = lump->next;
|
|
|
|
//
|
|
// Modify the lump numbers for all the subsequent lumps,
|
|
// and the total lumps in the WAD.
|
|
//
|
|
lump->wad->header->numlumps--;
|
|
|
|
if (lump->num == 0)
|
|
lump->wad->lumps = lump->next;
|
|
|
|
for (l = lump->next; l; l = l->next)
|
|
l->num--;
|
|
|
|
//
|
|
// While, at the same time, blanking the references
|
|
// to these nodes so they don't get removed.
|
|
//
|
|
lump->next = NULL;
|
|
|
|
//
|
|
// Free this lump's memory.
|
|
//
|
|
WAD_FreeMemory(NULL, NULL, NULL, lump, NULL);
|
|
}
|
|
|
|
inline void WAD_RemoveLumpInWADByNum(wad_t *wad, wad_uint32_t num)
|
|
{
|
|
WAD_RemoveLump(WAD_LumpInWADByNum(wad, num));
|
|
}
|
|
|
|
inline void WAD_RemoveLumpInWADByName(wad_t *wad, const char *name)
|
|
{
|
|
WAD_RemoveLump(WAD_LumpInWADByName(wad, name));
|
|
}
|
|
|
|
inline void WAD_RemoveLumpByName(const char *name)
|
|
{
|
|
WAD_RemoveLump(WAD_LumpByName(name));
|
|
}
|