summaryrefslogtreecommitdiff
path: root/vidoom.c
diff options
context:
space:
mode:
Diffstat (limited to 'vidoom.c')
-rw-r--r--vidoom.c892
1 files changed, 892 insertions, 0 deletions
diff --git a/vidoom.c b/vidoom.c
new file mode 100644
index 0000000..467912c
--- /dev/null
+++ b/vidoom.c
@@ -0,0 +1,892 @@
+/*
+
+ viDOOM - level editor for DOOM
+
+ Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ Doom I/II editor
+
+*/
+static const char rcs_id[]="$Id$";
+
+#include "config.h"
+#include "globals.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "wad.h"
+#include "platgui.h"
+#include "gui.h"
+#include "gfx.h"
+#include "file.h"
+#include "mem.h"
+#include "edit.h"
+#include "texture.h"
+#include "things.h"
+#include "runcmd.h"
+#include "names.h"
+#include "util.h"
+
+/* ---------------------------------------- VARS
+*/
+static WadMap *wad=NULL;
+static char mapname[32]="NONE";
+static GFX_IMAGE doom_image;
+
+/* Menu for asking game type
+*/
+static PLAT_MENU game_type_menu[]=
+ {
+ {"Doom", DOOM},
+ {"Ultimate Doom", ULTIMATE_DOOM},
+ {"Doom II", DOOM_2},
+ {"TNT:Evilution", FINAL_TNT},
+ {"The Plutonia Experiment", FINAL_PLUTONIA},
+ {"ZDoom", ZDOOM},
+ {NULL,0}
+ };
+
+
+/* ---------------------------------------- PROTOS
+*/
+static void MainMenu(void);
+static void GPL_clear(void);
+static int CreateHexenMap(void);
+
+
+/* ---------------------------------------- MAIN
+*/
+int viDOOM(int argc,char *argv[])
+{
+ char *load,*p;
+ int f;
+
+ if (getenv("VIDOOM_DIR"))
+ Cd(getenv("VIDOOM_DIR"));
+
+ GFX_init();
+
+ if (GFX_mouse_buttons()<2)
+ GFX_exit(EXIT_FAILURE,"viDOOM expects at least a 2-button mouse\n");
+
+ LoadGlobalsPart1();
+
+ if ((disp_width<640)||(disp_height<480))
+ GFX_exit(EXIT_FAILURE,"viDOOM expects at least a display of 640x480\n");
+
+ GFX_open(disp_width,disp_height);
+ EditSetScreen(disp_width,disp_height);
+ GuiSetScreen(disp_width,disp_height);
+ GUI_setscreen(disp_width,disp_height);
+
+ GPL_clear();
+
+ /* Ask for game type?
+ */
+ if (ask_for_game_type)
+ {
+ int new;
+
+ GFX_redraw();
+
+ new=GUI_menu("Select type of game to edit",
+ disp_width/2,disp_height/2,game_type_menu,-666);
+
+ if (new!=-666)
+ game=(GameType)new;
+ }
+
+ LoadGlobalsPart2();
+
+ if (AddIWAD(IWAD_path)!=WAD_OK)
+ {
+ GuiInfoBox("ERROR","AddIWAD(%s): %s",IWAD_path,WadErrorString());
+ GFX_close();
+ return(EXIT_FAILURE);
+ }
+
+ /* Read in resource WADS from preloaded config
+ */
+ if (PWAD_preload[0])
+ {
+ load=Strdup(PWAD_preload);
+
+ p=strtok(load,";");
+
+ while(p)
+ {
+ if (AddPWAD(p)!=WAD_OK)
+ GuiInfoBox("ERROR","AddPWAD(%s): %s",p,WadErrorString());
+
+ p=strtok(NULL,";");
+ }
+
+ Release(load);
+ }
+
+ /* Read in WADS from command line
+ */
+ for(f=1;f<argc;f++)
+ if (AddPWAD(argv[f])!=WAD_OK)
+ GuiInfoBox("ERROR","AddPWAD(%s): %s",argv[f],WadErrorString());
+
+ /* Read in editor configuration
+ */
+ GPL_clear();
+ GuiDrawInfoBox("Please wait",GUI_CENTRE,GUI_CENTRE,TRUE,
+ "Reading editor|config file");
+ GFX_redraw();
+ LoadConfig();
+
+ /* Read in TEXTURES and FLATS
+ */
+ GPL_clear();
+ ReadWADTextures();
+
+ GPL_clear();
+ ReadWADFlats();
+
+ if (show_titlepic)
+ doom_image=DecodeGraphicsLump("TITLEPIC");
+ else
+ doom_image=NULL;
+
+
+ /* Auto load levels
+ */
+ if (!STREQ(auto_loadmap,""))
+ {
+ char *orig;
+
+ UCase(auto_loadmap);
+ orig=Strdup(auto_loadmap);
+ p=strtok(auto_loadmap,",");
+
+ while((p)&&(!wad))
+ {
+ if ((wad=LoadMap(p)))
+ {
+ strcpy(mapname,p);
+ EditLoad(wad);
+ }
+
+ p=strtok(NULL,",");
+ }
+
+ if (!wad)
+ GuiInfoBox("ERROR","Failed to load any of the following:|%s",orig);
+
+ Release(orig);
+ }
+ else
+ {
+ /* Create initial empty map
+ */
+ if (initial_empty_map)
+ {
+ switch(level_style)
+ {
+ case DOOM_LEVELS:
+ case ULTIMATE_DOOM_LEVELS:
+ strcpy(mapname,"E1M1");
+ break;
+
+ case DOOM_2_LEVELS:
+ strcpy(mapname,"MAP01");
+ break;
+
+ }
+
+ wad=NewMap(CreateHexenMap());
+ EditLoad(wad);
+ }
+ }
+
+ MainMenu();
+
+ GFX_close();
+
+ return(EXIT_SUCCESS);
+}
+
+/* Clear screen and show simple GPL warning during startup
+*/
+static void GPL_clear(void)
+{
+ GFX_clear(BLACK);
+
+ GuiDrawInfoBox("viDOOM " VIDOOMVER " " VIDOOMRELEASE,
+ GUI_CENTRE,GUI_FLUSH_TOP,TRUE,
+ "Copyright (c) 2000 Ian Cowburn| |"
+ "viDOOM comes with ABSOLUTELY NO WARRANTY.|"
+ "For details see LICENSE.| |"
+ "This is free software, and you are welcome|"
+ "to redistribute it under certain conditions.|"
+ "See LICENSE for details.");
+}
+
+
+/* Returns TRUE/FALSE as to whether to create a HEXEN map
+*/
+static int CreateHexenMap(void)
+{
+ switch(create_hexen)
+ {
+ case GEN_NO:
+ return(FALSE);
+ break;
+
+ case GEN_YES:
+ return(TRUE);
+ break;
+
+ case GEN_ASK:
+ return(GUI_yesno("Create as a HEXEN map?"));
+ break;
+ }
+
+ return(FALSE);
+}
+
+
+/* Format an argument for the node builder command
+*/
+static char *FormatArg(char *path, char *arg)
+{
+ char *ret;
+ char *p;
+
+ ret=Grab(PATH_MAX);
+ p=ret;
+
+ while(*arg)
+ if (*arg=='%')
+ {
+ *p=0;
+ strcat(ret,path);
+ p+=strlen(path);
+ arg++;
+ }
+ else
+ *p++=*arg++;
+
+ return(ret);
+}
+
+
+/* Upper case a string
+*/
+static void ToUpper(char *p)
+{
+ while(*p)
+ {
+ *p=toupper(*p);
+ p++;
+ }
+}
+
+
+/* Check whether file should be ignored for node building
+*/
+static int IsIgnored(char *path)
+{
+ char i[PATH_MAX];
+ char w[PATH_MAX];
+
+ if (!build_ignore[0])
+ return(FALSE);
+
+ strcpy(w,Basename(path));
+ strcpy(i,build_ignore);
+
+ ToUpper(w);
+ ToUpper(i);
+
+ return((int)strstr(w,i));
+}
+
+
+/* ---------------------------------------- TOP LEVEL MENU
+*/
+static void MainMenu(void)
+{
+# define MENU_NEW 1
+# define MENU_LOAD 2
+# define MENU_EDIT 3
+# define MENU_SAVE 4
+# define MENU_OPEN 5
+# define MENU_CLOSE 6
+# define MENU_PREVIEW 7
+# define MENU_ABOUT 8
+# define MENU_QUIT 9
+# define MENU_RENAME 10
+# define MENU_LISTDIR 11
+# define MENU_DEBUG 12
+# define MENU_LICENSE 13
+
+ static PLAT_MENU main_menu[]=
+ {
+ {"Edit current level", MENU_EDIT},
+ {"Load level from open WADs", MENU_LOAD},
+ {"Save current level", MENU_SAVE},
+ {"Create new empty level", MENU_NEW},
+ {"Change current level name", MENU_RENAME},
+ {"Open PWAD file", MENU_OPEN},
+ {"Close PWAD file", MENU_CLOSE},
+ {"Preview level", MENU_PREVIEW},
+ {"View entries in WAD directory", MENU_LISTDIR},
+ {"About viDOOM " VIDOOMVER, MENU_ABOUT},
+ {"View License", MENU_LICENSE},
+#ifdef VIDOOM_DEBUG
+ {"DEBUG", MENU_DEBUG},
+#endif
+ {"Quit", MENU_QUIT},
+ {NULL,0}
+ };
+
+ int quit;
+ int edited;
+
+ quit=FALSE;
+ edited=FALSE;
+
+#ifdef VIDOOM_DEBUG
+ if (FileExists("todo"))
+ GUI_view_file("TODO list","todo");
+#endif
+
+ while(!quit)
+ {
+ char *open;
+
+ GFX_clear(BLACK);
+
+ if (doom_image)
+ GFX_fill_screen(doom_image);
+
+ if (STREQ(mapname,"NONE"))
+ GuiDrawInfoBox(GameName(),GUI_FLUSH_RIGHT,GUI_FLUSH_TOP,FALSE,
+ "Current map : %s|"
+ " | |"
+ "Open WAD files :|%s",
+ mapname,open=OpenWads());
+ else
+ GuiDrawInfoBox(GameName(),GUI_FLUSH_RIGHT,GUI_FLUSH_TOP,FALSE,
+ "Current map : %s|"
+ " %s| |"
+ "Open WAD files :|%s",
+ mapname,MapName(mapname),open=OpenWads());
+
+ Release(open);
+
+ GFX_redraw();
+
+ switch(GUI_menu("MAIN MENU",10,10,main_menu,-1))
+ {
+ case MENU_NEW:
+ {
+ char *name;
+ int new=TRUE;
+
+ if ((name=GuiPickLevel("Pick map to create")))
+ {
+ if (wad)
+ if ((!map_warn)||
+ (new=GUI_yesno("Map already open. Continue?")))
+ {
+ strcpy(mapname,"NONE");
+ wad=ClearMap(wad);
+ edited=FALSE;
+ }
+
+ if (new)
+ {
+ strcpy(mapname,name);
+ wad=NewMap(CreateHexenMap());
+ EditLoad(wad);
+ edited=FALSE;
+ }
+ }
+
+ break;
+ }
+
+ case MENU_LOAD:
+ {
+ char *name;
+ int load=TRUE;
+
+ if ((name=GuiPickLevel("Pick map to load for editting")))
+ {
+ if (wad)
+ if ((!map_warn)||
+ (load=GUI_yesno("Map already open. Continue?")))
+ {
+ strcpy(mapname,"NONE");
+ wad=ClearMap(wad);
+ edited=FALSE;
+ }
+
+ if (load)
+ {
+ GuiDrawInfoBox("Loading...",GUI_CENTRE,GUI_CENTRE,TRUE,
+ "Loading level %s",name);
+ GFX_redraw();
+
+ if (!(wad=LoadMap(name)))
+ GuiInfoBox("ERROR","LoadMap(%s): %s",
+ name,WadErrorString());
+ else
+ {
+ strcpy(mapname,name);
+ EditLoad(wad);
+ edited=FALSE;
+ }
+ }
+ }
+
+ break;
+ }
+
+ case MENU_EDIT:
+ if (!wad)
+ GuiInfoBox("ERROR","No map currently being edited");
+ else
+ {
+ EditLoop();
+ edited=TRUE;
+ }
+ break;
+
+ case MENU_SAVE:
+ {
+ char *wadf;
+
+ if (!wad)
+ GuiInfoBox("ERROR","No map currently being edited");
+ else
+ if ((wadf=GUI_fsel
+ ("Select WAD to save map as",PWAD_dir,".WAD")))
+ {
+ int ok;
+
+ if (WadFileType(wadf)==FILE_IS_IWAD)
+ {
+ GuiInfoBox("ERROR","Cannot overwrite %s|"
+ "It is an IWAD",wadf);
+
+ ok=FALSE;
+ }
+ else
+ {
+ if ((overwrite_warning)&&(FileExists(wadf)))
+ ok=GUI_yesno("Overwrite file?");
+ else
+ ok=TRUE;
+ }
+
+ if (ok)
+ {
+ GuiDrawInfoBox
+ ("Saving...",GUI_CENTRE,GUI_CENTRE,TRUE,
+ "Saving level %s to %s",mapname,wadf);
+ GFX_redraw();
+
+ EditCompact();
+ EditSave(wad);
+
+ if (SaveMap(wad,mapname,wadf)!=WAD_OK)
+ GuiInfoBox("ERROR","SaveMap(%s)|%s",
+ wadf,WadErrorString());
+ else
+ {
+ int do_build;
+ char *open;
+ char *p;
+
+ edited=FALSE;
+
+ if (use_build)
+ do_build=!IsIgnored(wadf);
+ else
+ do_build=FALSE;
+
+ if (do_build)
+ {
+ char path[PATH_MAX];
+ char *arg[4];
+
+ arg[0]=build_cmd;
+
+ if (build_in_before_out)
+ {
+ arg[1]=FormatArg(wadf,build_in);
+ arg[2]=FormatArg(wadf,build_out);
+ }
+ else
+ {
+ arg[2]=FormatArg(wadf,build_in);
+ arg[1]=FormatArg(wadf,build_out);
+ }
+
+ arg[3]=NULL;
+
+ if (RunCommand(arg,path))
+ {
+ if ((build_always_view)&&(path[0]))
+ GUI_view_file("Node Builder",path);
+ }
+ else
+ if (path[0])
+ GUI_view_file("Node Builder FAILED",
+ path);
+ else
+ GuiInfoBox("ERROR",
+ "Node builder|%s|failed|"
+ "(no results available)",
+ build_cmd);
+
+ if (path[0])
+ remove(path);
+
+ Release(arg[1]);
+ Release(arg[2]);
+ }
+
+ /* Check to see if we've saved on of the
+ currently loaded PWADS
+ */
+ if ((open=OpenWads()))
+ {
+ p=open;
+
+ p=strtok(p,"|");
+
+ while(p)
+ {
+ if (FilenamesEqual(p,wadf))
+ {
+ if (CloseWad(wadf)!=WAD_OK)
+ GuiInfoBox
+ ("ERROR","CloseWad(%s)|%s",
+ wadf,WadErrorString());
+
+ if (AddPWAD(wadf)!=WAD_OK)
+ GuiInfoBox
+ ("ERROR","AddPWAD(%s)|%s",
+ wadf,WadErrorString());
+
+ p=NULL;
+ }
+ else
+ p=strtok(NULL,"|");
+ }
+
+ Release(open);
+ }
+ }
+ }
+
+ Release(wadf);
+ }
+ break;
+ }
+
+ case MENU_RENAME:
+ {
+ char *name;
+
+ if (!wad)
+ GuiInfoBox("ERROR","No map currently being edited");
+ else
+ if ((name=GuiPickLevel("Pick new name for level")))
+ strcpy(mapname,name);
+
+ break;
+ }
+
+ case MENU_OPEN:
+ {
+ char *wadf;
+
+ if ((wadf=GUI_fsel("Select WAD to open",PWAD_dir,".WAD")))
+ {
+ GuiDrawInfoBox("Loading...",GUI_CENTRE,GUI_CENTRE,TRUE,
+ "Loading PWAD %s",wadf);
+ GFX_redraw();
+
+ if (AddPWAD(wadf)!=WAD_OK)
+ GuiInfoBox("ERROR","AddPWAD(%s)|%s",
+ wadf,WadErrorString());
+
+ Release(wadf);
+ }
+ }
+ break;
+
+ case MENU_CLOSE:
+ {
+ char *open;
+ char *wadf[512];
+ char *p;
+ int f;
+
+ if ((open=OpenWads()))
+ {
+ p=strtok(open,"|");
+ f=0;
+
+ while(p)
+ {
+ wadf[f++]=p;
+ p=strtok(NULL,"|");
+ }
+
+ wadf[f]=NULL;
+
+ f=GUI_picklist("Select WAD file to close",wadf);
+
+ if (f!=-1)
+ {
+ if (strcmp(wadf[f],IWAD_path)==0)
+ GuiInfoBox("ERROR","Cannot unload base IWAD|%s",
+ wadf[f]);
+ else
+ {
+ GuiDrawInfoBox("Closing...",
+ GUI_CENTRE,GUI_CENTRE,TRUE,
+ "Closing PWAD %s",wadf[f]);
+
+ if (CloseWad(wadf[f])!=WAD_OK)
+ GuiInfoBox("ERROR","CloseWad(%s)|%s",
+ wadf[f],WadErrorString());
+ }
+ }
+
+ Release(open);
+ }
+
+ break;
+ }
+
+ case MENU_LISTDIR:
+ {
+ char s[256];
+ WadDir *wd;
+ Iterator i;
+ char **list;
+ WadDir **dir;
+ int f;
+ int opt;
+
+ list=Grab(sizeof(char *)*(GetWadDirSize()+1));
+ dir=Grab(sizeof(WadDir *)*(GetWadDirSize()));
+ i=GetWadDir();
+
+ f=0;
+ while(i)
+ {
+ wd=IteratorData(i);
+ i=IteratorNext(i);
+
+ sprintf(s,"%-9s 0x%.8lx 0x%.8lx %s",
+ wd->name,wd->off,wd->size,Basename(wd->wad));
+
+ dir[f]=wd;
+ list[f]=Strdup(s);
+
+ f++;
+ }
+
+ list[f]=NULL;
+
+ if ((opt=GUI_picklist
+ ("WAD DIR (Name, Offset, Size, WAD file)",list))!=-1)
+ {
+ char asc[9];
+ unsigned char *lump;
+ Long len;
+ FILE *fp;
+ char *path;
+ int r;
+
+ if ((lump=GetLumpFrom(dir[opt],&len)))
+ {
+ if (len)
+ {
+ path=tmpnam(NULL);
+ if ((fp=fopen(path,"w")))
+ {
+ f=0;
+
+ while(f<len)
+ {
+ strcpy(asc," ");
+
+ fprintf(fp,"%6.6x: ",f);
+
+ for(r=0;r<8;r++)
+ {
+ if ((f+r)<len)
+ {
+ fprintf(fp,"%2.2x ",
+ (unsigned char)lump[f+r]);
+
+ if (isprint(lump[f+r]))
+ asc[r]=lump[f+r];
+ else
+ asc[r]='.';
+ }
+ else
+ fprintf(fp,"** ");
+ }
+
+ fprintf(fp," \"%s\"\n",asc);
+
+ f+=8;
+ }
+
+ fclose(fp);
+
+ sprintf(s,"%s (Offset 0x%lx, "
+ "Size 0x%lx) from %s",
+ dir[opt]->name,
+ dir[opt]->off,
+ dir[opt]->size,
+ Basename(dir[opt]->wad));
+
+ GUI_view_file(s,path);
+
+ remove(path);
+ }
+ }
+ else
+ GuiInfoBox("NOTICE",
+ "%s is a zero length lump",dir[opt]->name);
+
+ Release(lump);
+ }
+ }
+
+ f=0;
+ while(list[f])
+ {
+ Release(list[f]);
+ f++;
+ }
+
+ Release(list);
+ Release(dir);
+
+ break;
+ }
+
+ case MENU_PREVIEW:
+ {
+ char *name;
+ WadMap *preview;
+
+ if ((name=GuiPickLevel("Pick map to preview")))
+ {
+ if (!(preview=LoadMap(name)))
+ GuiInfoBox("ERROR","LoadMap(%s): %s",
+ name,WadErrorString());
+ else
+ {
+ EditPreviewWadMap(name,preview);
+ preview=ClearMap(preview);
+ }
+ }
+
+ break;
+ }
+
+ case MENU_ABOUT:
+ GuiInfoBox ("viDOOM " VIDOOMVER " " VIDOOMRELEASE,
+ "Copyright (c) 2000 Ian Cowburn|"
+ "http://www.noddybox.demon.co.uk/vidoom/| |"
+
+ "viDOOM comes with ABSOLUTELY NO WARRANTY.|"
+ "For details see LICENSE.| |"
+
+ "This is free software, and you are welcome|"
+ "to redistribute it under certain conditions.|"
+ "See LICENSE for details.| |"
+
+ "DOOM, Ultimate DOOM, DOOM 2 and Final DOOM|"
+ "(c) id Software.|"
+ "http://www.idsoftware.com/| |"
+ "Levels in DOOM, DOOM 2 and Ultimate DOOM|"
+ "designed by id Software.| |"
+ "Levels in The Plutonia Experiment designed by|"
+ "Milo & Dario Casali whilst in Team TNT.| |"
+ "Levels in TNT:Evilution designed by|"
+ "various members of Team TNT. Get details at|"
+ "http://www.teamtnt.com/| |"
+ "Thanks to all concerned for some of my favourite|"
+ "Lovecraftian Dark Evil Places.| |"
+ "viDOOM will only work if you have the registered|"
+ "version of any of the follow id Sofwtare games:|"
+ "DOOM, Ultimate DOOM, DOOM 2 or Final DOOM");
+ break;
+
+ case MENU_LICENSE:
+ GUI_view_file("viDOOM " VIDOOMVER " " VIDOOMRELEASE,
+ "LICENSE");
+ break;
+
+ case MENU_QUIT:
+ if ((map_exit_warn)&&(edited))
+ quit=GUI_yesno("Map may have been changed "
+ "- really quit?");
+ else
+ quit=TRUE;
+ break;
+
+#ifdef VIDOOM_DEBUG
+ case MENU_DEBUG:
+ GuiInfoBox("DEBUG",
+ "block_bit=%d|"
+ "block_mask=%d|"
+ "side2_bit=%d|"
+ "side2_mask=%d|"
+ "upper_bit=%d|"
+ "upper_mask=%d|"
+ "lower_bit=%d|"
+ "lower_mask=%d|"
+ "empty_texture='%s'|"
+ "",
+ block_bit,block_mask,
+ side2_bit,side2_mask,
+ upper_peg_bit,upper_peg_mask,
+ lower_peg_bit,lower_peg_mask,
+ empty_texture);
+ break;
+#endif
+
+ default:
+ break;
+ }
+ }
+}
+
+
+/* END OF FILE */