Remove lumpmod tool

Superceded by far superior tools
This commit is contained in:
Eidolon 2022-07-17 19:49:58 -05:00
parent 7a5f1dec9e
commit 405c2101c2
5 changed files with 0 additions and 1418 deletions

View file

@ -1,16 +0,0 @@
# Makfile for SRB2 Lumpmod
# by Alam Arias et al.
SRC=lumpmod.c lump.c
OBJ=$(SRC:.c=.o)# replaces the .c from SRC with .o
EXE=lumpmod
.PHONY : all # .PHONY ignores files named all
all: $(EXE) # all is dependent on $(BIN) to be complete
$(EXE): $(OBJ) # $(EXE) is dependent on all of the files in $(OBJ) to exist
$(CC) $(OBJ) $(LDFLAGS) -o $@
.PHONY : clean # .PHONY ignores files named clean
clean:
-$(RM) $(OBJ) $(EXE)

View file

@ -1,473 +0,0 @@
/*
LumpMod v0.2.1, a command-line utility for working with lumps in wad
files.
Copyright (C) 2003 Thunder Palace Entertainment.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
lump.c: Provides functions for dealing with lumps
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "lump.h"
/* Read contents of a wad file and store them in memory.
* fpoint is the file to read, opened with "rb" mode.
* A pointer to a new wadfile struct will be returned, or NULL on error.
*/
struct wadfile *read_wadfile(FILE *fpoint) {
struct wadfile *wfptr;
struct lumplist *curlump;
long diroffset, filelen;
unsigned long count;
/* Allocate memory for wadfile struct */
wfptr = malloc(sizeof(struct wadfile));
if(wfptr == NULL) return NULL;
/* Read first four characters (PWAD or IWAD) */
if(fread(wfptr->id, 4, 1, fpoint) < 1) {
free(wfptr);
return NULL;
}
/* Read number of lumps */
if(fread(&(wfptr->numlumps), 4, 1, fpoint) < 1) {
free(wfptr);
return NULL;
}
/* If number of lumps is zero, nothing more needs to be done */
if(wfptr->numlumps == 0) {
wfptr->head = NULL;
return wfptr;
}
/* Read offset of directory */
if(fread(&diroffset, 4, 1, fpoint) < 1) {
free(wfptr);
return NULL;
}
/* Verify that the directory as long as it needs to be */
fseek(fpoint, 0, SEEK_END);
filelen = ftell(fpoint);
if((filelen - diroffset) / DIRENTRYLEN < wfptr->numlumps) {
free(wfptr);
return NULL;
}
/* Allocate memory for head lumplist item and set head pointer */
curlump = malloc(sizeof(struct lumplist));
if(curlump == NULL) {
free(wfptr);
return NULL;
}
wfptr->head = curlump;
curlump->cl = NULL;
/* Read directory entries and lumps */
for(count = 0; count < wfptr->numlumps; count++) {
long lumpdataoffset;
/* Advance to a new list item */
curlump->next = malloc(sizeof(struct lumplist));
if(curlump->next == NULL) {
free_wadfile(wfptr);
return NULL;
}
curlump = curlump->next;
curlump->next = NULL;
/* Allocate memory for the lump info */
curlump->cl = malloc(sizeof(struct lump));
if(curlump->cl == NULL) {
free_wadfile(wfptr);
return NULL;
}
/* Seek to the proper position in the file */
if(fseek(fpoint, diroffset + (count * DIRENTRYLEN), SEEK_SET) != 0) {
free_wadfile(wfptr);
return NULL;
}
/* Read offset of lump data */
if(fread(&lumpdataoffset, 4, 1, fpoint) < 1) {
free_wadfile(wfptr);
return NULL;
}
/* Read size of lump in bytes */
if(fread(&(curlump->cl->len), 4, 1, fpoint) < 1) {
free_wadfile(wfptr);
return NULL;
}
/* Read lump name */
if(fread(curlump->cl->name, 8, 1, fpoint) < 1) {
free_wadfile(wfptr);
return NULL;
}
/* Read actual lump data, unless lump size is 0 */
if(curlump->cl->len > 0) {
if(fseek(fpoint, lumpdataoffset, SEEK_SET) != 0) {
free_wadfile(wfptr);
return NULL;
}
/* Allocate memory for data */
curlump->cl->data = malloc(curlump->cl->len);
if(curlump->cl->data == NULL) {
free_wadfile(wfptr);
return NULL;
}
/* Fill the data buffer */
if(fread(curlump->cl->data, curlump->cl->len, 1, fpoint) < 1) {
free_wadfile(wfptr);
return NULL;
}
} else curlump->cl->data = NULL;
} /* End of directory reading loop */
return wfptr;
}
/* Free a wadfile from memory as well as all related structures.
*/
void free_wadfile(struct wadfile *wfptr) {
struct lumplist *curlump, *nextlump;
if(wfptr == NULL) return;
curlump = wfptr->head;
/* Free items in the lump list */
while(curlump != NULL) {
/* Free the actual lump and its data, if necessary */
if(curlump->cl != NULL) {
if(curlump->cl->data != NULL) free(curlump->cl->data);
free(curlump->cl);
}
/* Advance to next lump and free this one */
nextlump = curlump->next;
free(curlump);
curlump = nextlump;
}
free(wfptr);
}
/* Write complete wadfile to a file stream, opened with "wb" mode.
* fpoint is the stream to write to.
* wfptr is a pointer to the wadfile structure to use.
* Return zero on success, nonzero on failure.
*/
int write_wadfile(FILE *fpoint, struct wadfile *wfptr) {
struct lumplist *curlump;
long lumpdataoffset, diroffset;
if(wfptr == NULL) return 1;
/* Write four-character ID ("PWAD" or "IWAD") */
if(fwrite(wfptr->id, 4, 1, fpoint) < 1) return 2;
/* Write number of lumps */
if(fwrite(&(wfptr->numlumps), 4, 1, fpoint) < 1) return 3;
/* Offset of directory is not known yet. For now, write number of lumps
* again, just to fill the space.
*/
if(fwrite(&(wfptr->numlumps), 4, 1, fpoint) < 1) return 4;
/* Loop through lump list, writing lump data */
for(curlump = wfptr->head; curlump != NULL; curlump = curlump->next) {
/* Don't write anything for the head of the lump list or for lumps of
zero length */
if(curlump->cl == NULL || curlump->cl->data == NULL) continue;
/* Write the data */
if(fwrite(curlump->cl->data, curlump->cl->len, 1, fpoint) < 1)
return 5;
}
/* Current position is where directory will start */
diroffset = ftell(fpoint);
/* Offset for the first lump's data is always 12 */
lumpdataoffset = 12;
/* Loop through lump list again, this time writing directory entries */
for(curlump = wfptr->head; curlump != NULL; curlump = curlump->next) {
/* Don't write anything for the head of the lump list */
if(curlump->cl == NULL) continue;
/* Write offset for lump data */
if(fwrite(&lumpdataoffset, 4, 1, fpoint) < 1) return 6;
/* Write size of lump data */
if(fwrite(&(curlump->cl->len), 4, 1, fpoint) < 1) return 7;
/* Write lump name */
if(fwrite(curlump->cl->name, 8, 1, fpoint) < 1) return 8;
/* Increment lumpdataoffset variable as appropriate */
lumpdataoffset += curlump->cl->len;
}
/* Go back to header and write the proper directory offset */
fseek(fpoint, 8, SEEK_SET);
if(fwrite(&diroffset, 4, 1, fpoint) < 1) return 9;
return 0;
}
/* Get the name of a lump, as a null-terminated string.
* item is a pointer to the lump (not lumplist) whose name will be obtained.
* Return NULL on error.
*/
char *get_lump_name(struct lump *item) {
char convname[9], *retname;
if(item == NULL) return NULL;
memcpy(convname, item->name, 8);
convname[8] = '\0';
retname = malloc(strlen(convname) + 1);
if(retname != NULL) strcpy(retname, convname);
return retname;
}
/* Find the lump after start and before end having a certain name.
* Return a pointer to the list item for that lump, or return NULL if no lump
* by that name is found or lumpname is too long.
* lumpname is a null-terminated string.
* If end parameter is NULL, search to the end of the entire list.
*/
struct lumplist *find_previous_lump(struct lumplist *start, struct lumplist
*end, char *lumpname) {
struct lumplist *curlump, *lastlump;
char *curname;
int found = 0;
/* Verify that parameters are valid */
if(start==NULL || start==end || lumpname==NULL || strlen(lumpname) > 8)
return NULL;
/* Loop through the list from start parameter */
lastlump = start;
for(curlump = start->next; curlump != end && curlump != NULL;
curlump = curlump->next) {
/* Skip header lump */
if(curlump->cl == NULL) continue;
/* Find name of this lump */
curname = get_lump_name(curlump->cl);
if(curname == NULL) continue;
/* Compare names to see if this is the lump we want */
if(strcmp(curname, lumpname) == 0) {
found = 1;
break;
}
/* Free memory allocated to curname */
free(curname);
lastlump = curlump;
}
if(found) return lastlump;
return NULL;
}
/* Remove a lump from the list, free it, and free its data.
* before is the lump immediately preceding the lump to be removed.
* wfptr is a pointer to the wadfile structure to which the removed lump
* belongs, so that numlumps can be decreased.
*/
void remove_next_lump(struct wadfile *wfptr, struct lumplist *before) {
struct lumplist *removed;
/* Verify that parameters are valid */
if(before == NULL || before->next == NULL || wfptr == NULL) return;
/* Update linked list to omit removed lump */
removed = before->next;
before->next = removed->next;
/* Free lump info and data if necessary */
if(removed->cl != NULL) {
if(removed->cl->data != NULL) free(removed->cl->data);
free(removed->cl);
}
free(removed);
/* Decrement numlumps */
wfptr->numlumps--;
}
/* Add a lump.
* The lump will follow prev in the list and be named name, with a data size
* of len.
* A copy will be made of the data.
* Return zero on success or nonzero on failure.
*/
int add_lump(struct wadfile *wfptr, struct lumplist *prev, char *name, long
len, unsigned char *data) {
struct lump *newlump;
struct lumplist *newlumplist;
unsigned char *copydata;
/* Verify that parameters are valid */
if(wfptr == NULL || prev == NULL || name == NULL || strlen(name) > 8)
return 1;
/* Allocate space for newlump and newlumplist */
newlump = malloc(sizeof(struct lump));
newlumplist = malloc(sizeof(struct lumplist));
if(newlump == NULL || newlumplist == NULL) return 2;
/* Copy lump data and set up newlump */
if(len == 0 || data == NULL) {
newlump->len = 0;
newlump->data = NULL;
} else {
newlump->len = len;
copydata = malloc(len);
if(copydata == NULL) return 3;
memcpy(copydata, data, len);
newlump->data = copydata;
}
/* Set name of newlump */
memset(newlump->name, '\0', 8);
if(strlen(name) == 8) memcpy(newlump->name, name, 8);
else strcpy(newlump->name, name);
/* Set up newlumplist and alter prev appropriately */
newlumplist->cl = newlump;
newlumplist->next = prev->next;
prev->next = newlumplist;
/* Increment numlumps */
wfptr->numlumps++;
return 0;
}
/* Rename a lump.
* renamed is a pointer to the lump (not lumplist) that needs renaming.
* newname is a null-terminated string with the new name.
* Return zero on success or nonzero on failure.
*/
int rename_lump(struct lump *renamed, char *newname) {
/* Verify that parameters are valid. */
if(newname == NULL || renamed == NULL || strlen(newname) > 8) return 1;
/* Do the renaming. */
memset(renamed->name, '\0', 8);
if(strlen(newname) == 8) memcpy(renamed->name, newname, 8);
else strcpy(renamed->name, newname);
return 0;
}
/* Find the last lump in a wadfile structure.
* Return this lump or NULL on failure.
*/
struct lumplist *find_last_lump(struct wadfile *wfptr) {
struct lumplist *curlump;
if(wfptr == NULL || wfptr->head == NULL) return NULL;
curlump = wfptr->head;
while(curlump->next != NULL) curlump = curlump->next;
return curlump;
}
/* Find the last lump between start and end.
* Return this lump or NULL on failure.
*/
struct lumplist *find_last_lump_between(struct lumplist *start, struct
lumplist *end) {
struct lumplist *curlump;
if(start == NULL) return NULL;
curlump = start;
while(curlump->next != end) {
curlump = curlump->next;
if(curlump == NULL) break;
}
return curlump;
}
/* Find the next section lump. A section lump is MAPxx (0 <= x <= 9), ExMy
* (0 <= x <= 9, 0 <= y <= 9), or any lump whose name ends in _START or _END.
* Return NULL if there are no section lumps after start.
*/
struct lumplist *find_next_section_lump(struct lumplist *start) {
struct lumplist *curlump, *found = NULL;
char *curname;
/* Verify that parameter is valid */
if(start == NULL || start->next == NULL) return NULL;
/* Loop through the list from start parameter */
for(curlump = start->next; curlump != NULL && found == NULL;
curlump = curlump->next) {
/* Skip header lump */
if(curlump->cl == NULL) continue;
/* Find name of this lump */
curname = get_lump_name(curlump->cl);
if(curname == NULL) continue;
/* Check to see if this is a section lump */
if(strlen(curname) == 5 && strncmp("MAP", curname, 3) == 0 &&
isdigit(curname[3]) && isdigit(curname[4]))
found = curlump;
else if(strlen(curname) == 4 && curname[0] == 'E' && curname[2] ==
'M' && isdigit(curname[1]) && isdigit(curname[3]))
found = curlump;
else if(strlen(curname) == 7 && strcmp("_START", &curname[1]) == 0)
found = curlump;
else if(strlen(curname) == 8 && strcmp("_START", &curname[2]) == 0)
found = curlump;
else if(strlen(curname) == 5 && strcmp("_END", &curname[1]) == 0)
found = curlump;
else if(strlen(curname) == 6 && strcmp("_END", &curname[2]) == 0)
found = curlump;
/* Free memory allocated to curname */
free(curname);
}
return found;
}

View file

@ -1,62 +0,0 @@
/*
LumpMod v0.2.1, a command-line utility for working with lumps in wad
files.
Copyright (C) 2003 Thunder Palace Entertainment.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
lump.h: Defines constants, structures, and functions used in lump.c
*/
#ifndef __LUMP_H
#define __LUMP_H
/* Entries in the wadfile directory are 16 bytes */
#define DIRENTRYLEN 16
/* Lumps and associated info */
struct lump {
long len;
unsigned char *data;
char name[8];
};
/* Linked list of lumps */
struct lumplist {
struct lump *cl; /* actual content of the lump */
struct lumplist *next;
};
/* Structure to contain all wadfile data */
struct wadfile {
char id[4]; /* IWAD or PWAD */
long numlumps; /* 32-bit integer */
struct lumplist *head; /* points to first entry */
};
/* Function declarations */
struct wadfile *read_wadfile(FILE *);
void free_wadfile(struct wadfile *);
int write_wadfile(FILE *, struct wadfile *);
char *get_lump_name(struct lump *);
struct lumplist *find_previous_lump(struct lumplist *, struct lumplist *, char *);
void remove_next_lump(struct wadfile *, struct lumplist *);
int add_lump(struct wadfile *, struct lumplist *, char *, long, unsigned char *);
int rename_lump(struct lump *, char *);
struct lumplist *find_last_lump(struct wadfile *);
struct lumplist *find_last_lump_between(struct lumplist *, struct lumplist *);
struct lumplist *find_next_section_lump(struct lumplist *);
#endif

View file

@ -1,785 +0,0 @@
/*
LumpMod v0.2.1, a command-line utility for working with lumps in wad
files.
Copyright (C) 2003 Thunder Palace Entertainment.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
lumpmod.c: Provides program functionality; depends on lump.c and lump.h
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lump.h"
int main(int argc, char *argv[]) {
enum commands { C_ADD, C_ADDSECT, C_DELETE, C_DELSECT, C_EXTRACT, C_LIST,
C_RENAME, C_UPDATE } cmd;
struct wadfile *wfptr;
struct lumplist *startitem, *enditem = NULL;
FILE *fpoint;
char *progname, **params;
char *startname = NULL, *endname = NULL;
int numargs, numparams, insection = 0;
progname = argv[0];
numargs = argc - 1;
/* Verify that there are enough arguments */
if(numargs < 2) {
fprintf(stderr, "%s: not enough arguments\n", progname);
return EXIT_FAILURE;
}
/* Identify the command used */
if(strcmp(argv[2], "add" ) == 0) cmd = C_ADD;
else if(strcmp(argv[2], "addsect") == 0) cmd = C_ADDSECT;
else if(strcmp(argv[2], "delete" ) == 0) cmd = C_DELETE;
else if(strcmp(argv[2], "delsect") == 0) cmd = C_DELSECT;
else if(strcmp(argv[2], "extract") == 0) cmd = C_EXTRACT;
else if(strcmp(argv[2], "list" ) == 0) cmd = C_LIST;
else if(strcmp(argv[2], "rename" ) == 0) cmd = C_RENAME;
else if(strcmp(argv[2], "update" ) == 0) cmd = C_UPDATE;
else {
fprintf(stderr, "%s: invalid command %s\n", progname, argv[2]);
return EXIT_FAILURE;
}
/* Check for -s option */
if(numargs >= 4 && strcmp(argv[3], "-s") == 0) {
if(cmd == C_ADDSECT || cmd == C_DELSECT) {
fprintf(stderr, "%s: no option -s for command %s\n", progname, argv[2]);
return EXIT_FAILURE;
}
insection = 1;
params = &argv[5];
numparams = numargs - 4;
/* Assume a map name if length > 2 */
if(strlen(argv[4]) > 2) startname = argv[4];
else {
startname = malloc(strlen(argv[4]) + 7);
endname = malloc(strlen(argv[4]) + 5);
if(startname == NULL || endname == NULL) {
fprintf(stderr, "%s: out of memory\n", progname);
return EXIT_FAILURE;
}
sprintf(startname, "%s_START", argv[4]);
sprintf(endname, "%s_END", argv[4]);
}
} else {
params = &argv[3];
numparams = numargs - 2;
} /* end of check for -s option */
/* Load the wadfile into memory, since all commands require this */
fpoint = fopen(argv[1], "rb");
if(fpoint == NULL) {
fprintf(stderr, "%s: unable to open file %s\n", progname, argv[1]);
return EXIT_FAILURE;
}
wfptr = read_wadfile(fpoint);
fclose(fpoint);
if(wfptr == NULL) {
fprintf(stderr, "%s: %s is not a valid wadfile\n", progname, argv[1]);
return EXIT_FAILURE;
}
/* Find startitem and enditem, using startname and endname */
if(startname == NULL) startitem = wfptr->head;
else {
startitem = find_previous_lump(wfptr->head, NULL, startname);
if(startitem == NULL) {
fprintf(stderr, "%s: can't find lump %s in %s", progname,
startname, argv[1]);
return EXIT_FAILURE;
}
startitem = startitem->next;
if(endname == NULL) {
if(startitem->next != NULL) {
char *itemname;
enditem = startitem->next;
itemname = get_lump_name(enditem->cl);
while( strcmp(itemname, "THINGS" ) == 0 ||
strcmp(itemname, "LINEDEFS") == 0 ||
strcmp(itemname, "SIDEDEFS") == 0 ||
strcmp(itemname, "VERTEXES") == 0 ||
strcmp(itemname, "SEGS" ) == 0 ||
strcmp(itemname, "SSECTORS") == 0 ||
strcmp(itemname, "NODES" ) == 0 ||
strcmp(itemname, "SECTORS" ) == 0 ||
strcmp(itemname, "REJECT" ) == 0 ||
strcmp(itemname, "BLOCKMAP") == 0) {
enditem = enditem->next;
if(enditem == NULL) break;
free(itemname);
itemname = get_lump_name(enditem->cl);
}
free(itemname);
if(enditem != NULL) enditem = enditem->next;
} else enditem = NULL;
} else {
enditem = find_previous_lump(startitem, NULL, endname);
if(enditem == NULL) {
fprintf(stderr, "%s: can't find lump %s in %s", progname,
endname, argv[1]);
return EXIT_FAILURE;
}
enditem = enditem->next;
}
} /* end of finding startitem and enditem */
/* Do stuff specific to each command */
switch(cmd) {
case C_ADD: {
struct lumplist *startitem2, *before, *existing;
int overwrite = 1, firstentry = 0, canduplicate = 0;
char *startname2 = NULL;
/* Parse options: -a, -b, -d, -n */
while(numparams > 2) {
if(params[0][0] != '-') break;
if(strcmp(params[0], "-n") == 0) overwrite = 0;
else if(strcmp(params[0], "-d") == 0) canduplicate = 1;
else if(strcmp(params[0], "-b") == 0) firstentry = 1;
else if(strcmp(params[0], "-a") == 0) {
params = &params[1];
numparams--;
startname2 = params[0];
} else {
fprintf(stderr, "%s: no option %s for command %s",
progname, params[0], argv[2]);
return EXIT_FAILURE;
}
params = &params[1];
numparams--;
}
if(numparams < 2) {
fprintf(stderr, "%s: not enough parameters for %s", progname,
argv[2]);
return EXIT_FAILURE;
}
/* Find the lump after which to add */
if(firstentry) before = startitem;
else if(startname2 != NULL) {
before = find_previous_lump(startitem, enditem, startname2);
if(before == NULL) {
fprintf(stderr, "%s: can't find lump %s in %s", progname,
startname2, argv[1]);
return EXIT_FAILURE;
}
before = before->next;
} else {
if(insection) {
before = find_last_lump_between(startitem, enditem);
if(before == NULL) before = startitem;
} else before = find_last_lump(wfptr);
}
startitem2 = before;
/* Add LUMPNAME FILENAME pairs */
printf("Adding lumps in %s...\n", argv[1]);
for(;;) {
long newlumpsize;
unsigned char *newlumpdata;
/* Check whether the lump already exists, unless -d is used */
if(canduplicate) existing = NULL;
else existing = find_previous_lump(startitem, enditem, params[0]);
if(existing != NULL) existing = existing->next;
if(existing != NULL && overwrite == 0) {
printf("Lump %s already exists. Taking no action.\n", params[0]);
numparams -= 2;
if(numparams < 2) break;
params = &params[2];
continue;
}
/* Read the file with new lump data */
fpoint = fopen(params[1], "rb");
if(fpoint == NULL) {
fprintf(stderr, "%s: can't open file %s\n", progname,
params[1]);
return EXIT_FAILURE;
}
/* Find size of lump data */
fseek(fpoint, 0, SEEK_END);
newlumpsize = ftell(fpoint);
fseek(fpoint, 0, SEEK_SET);
/* Copy lump data to memory */
if(newlumpsize == 0) newlumpdata = NULL;
else {
newlumpdata = malloc(newlumpsize);
if(newlumpdata == NULL) {
fprintf(stderr, "%s: out of memory\n", progname);
return EXIT_FAILURE;
}
if(fread(newlumpdata, newlumpsize, 1, fpoint) < 1) {
fprintf(stderr, "%s: unable to read file %s\n",
progname, params[1]);
return EXIT_FAILURE;
}
}
/* Close the file */
fclose(fpoint);
/* Add or update lump */
if(existing == NULL) {
if(add_lump(wfptr, before, params[0], newlumpsize,
newlumpdata) != 0) {
fprintf(stderr, "%s: unable to add lump %s\n",
progname, params[0]);
return EXIT_FAILURE;
}
printf("Lump %s added.\n", params[0]);
/* Other lumps will be added after the new one */
before = before->next;
} else {
existing->cl->len = newlumpsize;
free(existing->cl->data);
existing->cl->data = malloc(newlumpsize);
if(existing->cl->data == NULL) {
fprintf(stderr, "%s: out of memory\n", progname);
return EXIT_FAILURE;
}
memcpy(existing->cl->data, newlumpdata, newlumpsize);
printf("Lump %s updated.\n", params[0]);
}
/* Advance to the next pair, if there is a next pair */
numparams -= 2;
if(numparams < 2) break;
params = &params[2];
} /* end of adding LUMPNAME FILENAME pairs */
/* Save the modified wadfile */
fpoint = fopen(argv[1], "wb");
if(fpoint == NULL) {
fprintf(stderr, "%s: unable to open file %s for writing\n",
progname, argv[1]);
return EXIT_FAILURE;
}
if(write_wadfile(fpoint, wfptr) != 0) {
fprintf(stderr, "%s: unable to write wadfile to disk\n",
progname);
return EXIT_FAILURE;
}
fclose(fpoint);
printf("File %s successfully updated.\n", argv[1]);
} /* end of C_ADD */
break;
case C_UPDATE: {
struct lumplist *existing;
/* Parse options (none) */
if(numparams > 2 && params[0][0] == '-') {
fprintf(stderr, "%s: no option %s for command %s",
progname, params[0], argv[2]);
return EXIT_FAILURE;
}
if(numparams < 2) {
fprintf(stderr, "%s: not enough parameters for %s", progname,
argv[2]);
return EXIT_FAILURE;
}
/* Update LUMPNAME FILENAME pairs */
printf("Updating lumps in %s...\n", argv[1]);
for(;;) {
long newlumpsize;
unsigned char *newlumpdata;
/* Check whether the lump already exists */
existing = find_previous_lump(startitem, enditem, params[0]);
if(existing == NULL) {
printf("Lump %s does not exist. Taking no action.\n",
params[0]);
numparams -= 2;
if(numparams < 2) break;
params = &params[2];
continue;
}
existing = existing->next;
/* Read the file with new lump data */
fpoint = fopen(params[1], "rb");
if(fpoint == NULL) {
fprintf(stderr, "%s: can't open file %s\n", progname,
params[1]);
return EXIT_FAILURE;
}
/* Find size of lump data */
fseek(fpoint, 0, SEEK_END);
newlumpsize = ftell(fpoint);
fseek(fpoint, 0, SEEK_SET);
/* Copy lump data to memory */
if(newlumpsize == 0) newlumpdata = NULL;
else {
newlumpdata = malloc(newlumpsize);
if(newlumpdata == NULL) {
fprintf(stderr, "%s: out of memory\n", progname);
return EXIT_FAILURE;
}
if(fread(newlumpdata, newlumpsize, 1, fpoint) < 1) {
fprintf(stderr, "%s: unable to read file %s\n",
progname, params[1]);
return EXIT_FAILURE;
}
}
/* Close the file */
fclose(fpoint);
/* Update lump */
existing->cl->len = newlumpsize;
free(existing->cl->data);
existing->cl->data = malloc(newlumpsize);
if(existing->cl->data == NULL) {
fprintf(stderr, "%s: out of memory\n", progname);
return EXIT_FAILURE;
}
memcpy(existing->cl->data, newlumpdata, newlumpsize);
printf("Lump %s updated.\n", params[0]);
/* Advance to the next pair, if there is a next pair */
numparams -= 2;
if(numparams < 2) break;
params = &params[2];
} /* end of updating LUMPNAME FILENAME pairs */
/* Save the modified wadfile */
fpoint = fopen(argv[1], "wb");
if(fpoint == NULL) {
fprintf(stderr, "%s: unable to open file %s for writing\n",
progname, argv[1]);
return EXIT_FAILURE;
}
if(write_wadfile(fpoint, wfptr) != 0) {
fprintf(stderr, "%s: unable to write wadfile to disk\n",
progname);
return EXIT_FAILURE;
}
fclose(fpoint);
printf("File %s successfully updated.\n", argv[1]);
} /* end of C_UPDATE */
break;
case C_DELETE: {
struct lumplist *before;
/* Parse options (none) */
if(numparams > 1 && params[0][0] == '-') {
fprintf(stderr, "%s: no option %s for command %s",
progname, params[0], argv[2]);
return EXIT_FAILURE;
}
if(numparams < 1) {
fprintf(stderr, "%s: not enough parameters for %s", progname,
argv[2]);
return EXIT_FAILURE;
}
/* Delete LUMPNAME lumps */
printf("Deleting lumps in %s...\n", argv[1]);
for(;;) {
/* Find the lump to delete */
before = find_previous_lump(startitem, enditem, params[0]);
if(before == NULL) {
printf("Lump %s does not exist. Taking no action.\n",
params[0]);
numparams--;
if(numparams < 1) break;
params = &params[1];
continue;
}
/* Delete it */
remove_next_lump(wfptr, before);
printf("Lump %s deleted.\n", params[0]);
/* Advance to the next item to delete, if there is one */
numparams--;
if(numparams < 1) break;
params = &params[1];
} /* end of deleting LUMPNAME lumps */
/* Save the modified wadfile */
fpoint = fopen(argv[1], "wb");
if(fpoint == NULL) {
fprintf(stderr, "%s: unable to open file %s for writing\n",
progname, argv[1]);
return EXIT_FAILURE;
}
if(write_wadfile(fpoint, wfptr) != 0) {
fprintf(stderr, "%s: unable to write wadfile to disk\n",
progname);
return EXIT_FAILURE;
}
fclose(fpoint);
printf("File %s successfully updated.\n", argv[1]);
} /* end of C_DELETE */
break;
case C_RENAME: {
struct lumplist *renamed;
/* Parse options (none) */
if(numparams > 2 && params[0][0] == '-') {
fprintf(stderr, "%s: no option %s for command %s",
progname, params[0], argv[2]);
return EXIT_FAILURE;
}
if(numparams < 2) {
fprintf(stderr, "%s: not enough parameters for %s", progname,
argv[2]);
return EXIT_FAILURE;
}
/* Rename OLDNAME NEWNAME pairs */
printf("Renaming lumps in %s...\n", argv[1]);
for(;;) {
/* Find the lump to rename */
renamed = find_previous_lump(startitem, enditem, params[0]);
if(renamed == NULL) {
printf("Lump %s does not exist. Taking no action.\n",
params[0]);
numparams -= 2;
if(numparams < 2) break;
params = &params[2];
continue;
}
renamed = renamed->next;
/* Rename lump */
memset(renamed->cl->name, '\0', 8);
if(strlen(params[1]) >= 8) memcpy(renamed->cl->name,
params[1], 8);
else strcpy(renamed->cl->name, params[1]);
printf("Lump %s renamed to %s.\n", params[0], params[1]);
/* Advance to the next pair, if there is a next pair */
numparams -= 2;
if(numparams < 2) break;
params = &params[2];
} /* end of renaming OLDNAME NEWNAME pairs */
/* Save the modified wadfile */
fpoint = fopen(argv[1], "wb");
if(fpoint == NULL) {
fprintf(stderr, "%s: unable to open file %s for writing\n",
progname, argv[1]);
return EXIT_FAILURE;
}
if(write_wadfile(fpoint, wfptr) != 0) {
fprintf(stderr, "%s: unable to write wadfile to disk\n",
progname);
return EXIT_FAILURE;
}
fclose(fpoint);
printf("File %s successfully updated.\n", argv[1]);
} /* end of C_RENAME */
break;
case C_EXTRACT: {
struct lumplist *extracted;
/* Parse options (none) */
if(numparams > 2 && params[0][0] == '-') {
fprintf(stderr, "%s: no option %s for command %s",
progname, params[0], argv[2]);
return EXIT_FAILURE;
}
if(numparams < 2) {
fprintf(stderr, "%s: not enough parameters for %s", progname,
argv[2]);
return EXIT_FAILURE;
}
/* Extract LUMPNAME FILENAME pairs */
printf("Extracting lumps from %s...\n", argv[1]);
for(;;) {
/* Find the lump to extract */
extracted = find_previous_lump(startitem, enditem, params[0]);
if(extracted == NULL) {
printf("Lump %s does not exist. Taking no action.\n",
params[0]);
numparams -= 2;
if(numparams < 2) break;
params = &params[2];
continue;
}
extracted = extracted->next;
/* Open the file to extract to */
fpoint = fopen(params[1], "wb");
if(fpoint == NULL) {
fprintf(stderr, "%s: can't open file %s for writing\n",
progname, params[1]);
return EXIT_FAILURE;
}
/* Extract lump */
if(fwrite(extracted->cl->data, extracted->cl->len, 1, fpoint)
< 1) {
fprintf(stderr, "%s: unable to write lump %s to disk\n",
progname, params[0]);
return EXIT_FAILURE;
}
/* Close the file */
fclose(fpoint);
printf("Lump %s saved as %s.\n", params[0], params[1]);
/* Advance to the next pair, if there is a next pair */
numparams -= 2;
if(numparams < 2) break;
params = &params[2];
} /* end of extracting LUMPNAME FILENAME pairs */
printf("Finished extracting lumps from file %s.\n", argv[1]);
} /* end of C_EXTRACT */
break;
case C_LIST: {
struct lumplist *curlump;
int verbose = 0, i = 0;
/* Parse options: -v */
while(numparams > 0) {
if(params[0][0] != '-') break;
if(strcmp(params[0], "-v") == 0) verbose = 1;
else {
fprintf(stderr, "%s: no option %s for command %s",
progname, params[0], argv[2]);
return EXIT_FAILURE;
}
params = &params[1];
numparams--;
}
/* Loop through the lump list, printing lump info */
for(curlump = startitem->next; curlump != enditem; curlump =
curlump->next) {
i++;
if(verbose) printf("%5i %-8s %7li\n", i,
get_lump_name(curlump->cl), curlump->cl->len);
else printf("%s\n", get_lump_name(curlump->cl));
}
} /* end of C_LIST */
break;
case C_DELSECT: {
/* Parse options (none) */
if(numparams > 1 && params[0][0] == '-') {
fprintf(stderr, "%s: no option %s for command %s",
progname, params[0], argv[2]);
return EXIT_FAILURE;
}
if(numparams < 1) {
fprintf(stderr, "%s: not enough parameters for %s", progname,
argv[2]);
return EXIT_FAILURE;
}
/* Delete sections */
printf("Deleting sections in %s...\n", argv[1]);
for(;;) {
struct lumplist *curlump;
/* Assume a map name if length > 2 */
if(strlen(params[0]) > 2) startname = params[0];
else {
startname = malloc(strlen(params[0]) + 7);
endname = malloc(strlen(params[0]) + 5);
if(startname == NULL || endname == NULL) {
fprintf(stderr, "%s: out of memory\n", progname);
return EXIT_FAILURE;
}
sprintf(startname, "%s_START", params[0]);
sprintf(endname, "%s_END", params[0]);
}
/* Find startitem and enditem, using startname and endname */
startitem = find_previous_lump(wfptr->head, NULL, startname);
if(startitem == NULL) {
fprintf(stderr, "%s: can't find lump %s in %s", progname,
startname, argv[1]);
return EXIT_FAILURE;
}
if(endname == NULL && startitem->next != NULL) {
char *itemname;
enditem = startitem->next;
itemname = get_lump_name(enditem->cl);
do {
enditem = enditem->next;
if(enditem == NULL) break;
free(itemname);
itemname = get_lump_name(enditem->cl);
} while(strcmp(itemname, "THINGS" ) == 0 ||
strcmp(itemname, "LINEDEFS") == 0 ||
strcmp(itemname, "SIDEDEFS") == 0 ||
strcmp(itemname, "VERTEXES") == 0 ||
strcmp(itemname, "SEGS" ) == 0 ||
strcmp(itemname, "SSECTORS") == 0 ||
strcmp(itemname, "NODES" ) == 0 ||
strcmp(itemname, "SECTORS" ) == 0 ||
strcmp(itemname, "REJECT" ) == 0 ||
strcmp(itemname, "BLOCKMAP") == 0);
free(itemname);
}
else {
enditem = find_previous_lump(startitem, NULL, endname);
if(enditem == NULL) {
fprintf(stderr, "%s: can't find lump %s in %s",
progname, endname, argv[1]);
return EXIT_FAILURE;
}
enditem = enditem->next->next;
} /* end of finding startitem and enditem */
/* Loop through the section lumps, deleting them */
curlump = startitem;
while(curlump->next != enditem)
remove_next_lump(wfptr, curlump);
printf("Deleted section %s.\n", params[0]);
/* Move to next parameter, if it exists */
numparams--;
if(numparams < 1) break;
params = &params[1];
} /* end of deleting sections */
/* Save the modified wadfile */
fpoint = fopen(argv[1], "wb");
if(fpoint == NULL) {
fprintf(stderr, "%s: unable to open file %s for writing\n",
progname, argv[1]);
return EXIT_FAILURE;
}
if(write_wadfile(fpoint, wfptr) != 0) {
fprintf(stderr, "%s: unable to write wadfile to disk\n",
progname);
return EXIT_FAILURE;
}
fclose(fpoint);
printf("File %s successfully updated.\n", argv[1]);
} /* end of C_DELSECT */
break;
case C_ADDSECT: {
/* Parse options (none) */
if(numparams > 1 && params[0][0] == '-') {
fprintf(stderr, "%s: no option %s for command %s",
progname, params[0], argv[2]);
return EXIT_FAILURE;
}
if(numparams < 1) {
fprintf(stderr, "%s: not enough parameters for %s", progname,
argv[2]);
return EXIT_FAILURE;
}
/* Add sections */
printf("Adding sections in %s...\n", argv[1]);
for(;;) {
struct lumplist *curlump;
/* Assume a map name if length > 2 */
if(strlen(params[0]) > 2) startname = params[0];
else {
startname = malloc(strlen(params[0]) + 7);
endname = malloc(strlen(params[0]) + 5);
if(startname == NULL || endname == NULL) {
fprintf(stderr, "%s: out of memory\n", progname);
return EXIT_FAILURE;
}
sprintf(startname, "%s_START", params[0]);
sprintf(endname, "%s_END", params[0]);
}
/* Add section, unless it already exists */
if(find_previous_lump(wfptr->head, NULL, startname) == NULL) {
struct lumplist *last;
last = find_last_lump(wfptr);
if(add_lump(wfptr, last, startname, 0, NULL) != 0) {
fprintf(stderr, "%s: unable to add lump %s\n",
progname, startname);
return EXIT_FAILURE;
}
if(endname != NULL) {
last = last->next;
if(add_lump(wfptr, last, endname, 0, NULL) != 0) {
fprintf(stderr, "%s: unable to add lump %s\n",
progname, endname);
return EXIT_FAILURE;
}
}
printf("Added section %s.\n", params[0]);
} else
printf("Section %s already exists. Taking no action.\n",
params[0]);
/* Move to next parameter, if it exists */
numparams--;
if(numparams < 1) break;
params = &params[1];
} /* end of adding sections */
/* Save the modified wadfile */
fpoint = fopen(argv[1], "wb");
if(fpoint == NULL) {
fprintf(stderr, "%s: unable to open file %s for writing\n",
progname, argv[1]);
return EXIT_FAILURE;
}
if(write_wadfile(fpoint, wfptr) != 0) {
fprintf(stderr, "%s: unable to write wadfile to disk\n",
progname);
return EXIT_FAILURE;
}
fclose(fpoint);
printf("File %s successfully updated.\n", argv[1]);
} /* end of C_ADDSECT */
} /* end of command-specific stuff */
return EXIT_SUCCESS;
}

View file

@ -1,82 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head><meta http-equiv="content-type"
content="application/xhtml+xml; charset=utf-8" />
<title>LumpMod v0.2.1 Documentation</title></head><body>
<h1>LumpMod v0.2.1</h1>
<p>LumpMod is a small command-line utility for working with lumps in wad
files in the format used by DOOM and DOOM 2. It can add, delete, extract,
rename, list, and update individual lumps. It can also add sections
(XX_START and XX_END, for instance) and delete entire sections.</p>
<h2>Usage</h2>
<p><code>lumpmod [wadfile] [command] [-s section] [parameters]</code></p>
<p>Sections are MAPxx (xx = 01-99, where that map exists in the file), ExMy
(x, y = 1-9, where that map exists in the file), and anything else will be
the section between WHATEVER_START and WHATEVER_END. Sections that do not
exist in the wad file cannot be used. The section part can be left out to
work with the whole file. Any section specified here while using the addsect
or delsect commands will cause an error.</p>
<p>Note that the []... parameters in the command listings can be repeated.
For example, you can use <code>lumpmod clowns.wad add CLOWNS clowns.lmp</code> to
add a CLOWNS lump, or <code>lumpmod clowns.wad add CLOWN1 clown1.lmp CLOWN2
clown2.lmp</code> to add two clown-related lumps.</p>
<p>Note also that lump names and commands are case sensitive. There is an
<code>update</code> command, but no <code>UPDATE</code> command.</p>
<h2>Commands</h2>
<p><code>add [-a lumpname] [-b] [-d] [-n] [LUMPNAME FILENAME]...</code></p>
<p>Add a lump to the end of the wad, or after the lump specified with the -a
option. If the lump already exists, it will be overwritten (with its position
unchanged) unless the -n option is specified, in which case no action will be
taken, or the -d option is specified, in which case an additional lump with
the same name will be added. If the lump specified in the -a option does not
exist, an error will occur. The -b option will add the lump at the beginning,
overriding the -a option.</p>
<p><code>addsect [SECTNAME]...</code></p>
<p>Add a section. The name must be one or two characters long. If section
name is HX, zero-length entries HX_START and HX_END will be added to the end
of the wad file. If this section already exists, no action will be taken.</p>
<p><code>delete [LUMPNAME]...</code></p>
<p>Remove LUMPNAME from the wad.</p>
<p><code>delsect [SECTNAME]...</code></p>
<p>Delete a section and anything inside it. If the section doesn't exist, no
action will be taken.</p>
<p><code>extract [LUMPNAME FILENAME]...</code></p>
<p>Save the contents of LUMPNAME to the file named FILENAME. (Wad file will
not be changed in any way.)</p>
<p><code>list [-v]</code></p>
<p>List all lumps in the wad, in the order they appear in the directory.
With the -v option, include numbers and lump lengths.</p>
<p><code>rename [OLDNAME NEWNAME]...</code></p>
<p>Rename a lump in the wad.</p>
<p><code>update [LUMPNAME FILENAME]...</code></p>
<p>Update LUMPNAME with the contents of FILENAME. If no lump named LUMPNAME
exists in the wad, no action will be taken.</p>
<h2>Changes</h2>
<p>Version 0.2.1 adds the -d option to the add command.</p>
<p>Version 0.2 contains a fix to a bug involving empty sections. The initial
public release was version 0.1.</p>
<h2>Bugs</h2>
<p>LumpMod currently chokes on completely empty wad files (i.e., those that
contain absolutely no lumps). Let me know if you find any other bugs.</p>
<h2>Author</h2>
<p>Catatonic Porpoise, &lt;<a href="mailto:graue@oceanbase.org">graue@oceanbase.org</a>&gt;.
Updates can be found at <a href="http://www.thunderpalace.com/software/">http://www.thunderpalace.com/software/</a>.</p>
<h2>Thanks</h2>
<p>Thanks to Matthew S. Fell for writing &quot;The Unofficial DOOM
Specs,&quot; which were very helpful in making this program.</p>
<h2>License</h2>
<p>Copyright &copy; 2003 Thunder Palace Entertainment.</p>
<p>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.</p>
<p>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.</p>
<p>You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.</p>
</body></html>