summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.gitignore2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/d_iwad.c91
-rw-r--r--src/doom/.gitignore2
-rw-r--r--src/doom/g_game.c14
-rw-r--r--src/doom/hu_stuff.c30
-rw-r--r--src/doom/p_map.c21
-rw-r--r--src/doom/p_setup.c27
-rw-r--r--src/doom/p_sight.c10
-rw-r--r--src/doom/st_stuff.c18
-rw-r--r--src/i_video.c1
-rw-r--r--src/mus2mid.c1019
-rw-r--r--src/resource.rc.in2
-rw-r--r--src/setup/.gitignore7
-rw-r--r--src/setup/Makefile.am7
-rw-r--r--src/setup/execute.c33
16 files changed, 743 insertions, 543 deletions
diff --git a/src/.gitignore b/src/.gitignore
index d7e732ad..973a0073 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -5,3 +5,5 @@ Makefile.in
chocolate-doom
chocolate-server
*.exe
+tags
+TAGS
diff --git a/src/Makefile.am b/src/Makefile.am
index fc7e8852..9e550e15 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -190,7 +190,7 @@ EXTRA_DIST = \
if HAVE_PYTHON
-icon.c : $(top_builddir)/data/doom.ico
+icon.c : $(top_builddir)/data/doom8.ico
$(top_builddir)/data/convert-icon $^ $@
endif
diff --git a/src/d_iwad.c b/src/d_iwad.c
index ba9f9ae1..ab1dd823 100644
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -330,44 +330,85 @@ static void CheckDOSDefaults(void)
#endif
+// Returns true if the specified path is a path to a file
+// of the specified name.
+
+static boolean DirIsFile(char *path, char *filename)
+{
+ size_t path_len;
+ size_t filename_len;
+
+ path_len = strlen(path);
+ filename_len = strlen(filename);
+
+ return path_len >= filename_len + 1
+ && path[path_len - filename_len - 1] == DIR_SEPARATOR
+ && !strcasecmp(&path[path_len - filename_len], filename);
+}
+
+// Check if the specified directory contains the specified IWAD
+// file, returning the full path to the IWAD if found, or NULL
+// if not found.
+
+static char *CheckDirectoryHasIWAD(char *dir, char *iwadname)
+{
+ char *filename;
+
+ // As a special case, the "directory" may refer directly to an
+ // IWAD file if the path comes from DOOMWADDIR or DOOMWADPATH.
+
+ if (DirIsFile(dir, iwadname) && M_FileExists(dir))
+ {
+ return strdup(dir);
+ }
+
+ // Construct the full path to the IWAD if it is located in
+ // this directory, and check if it exists.
+
+ filename = malloc(strlen(dir) + strlen(iwadname) + 3);
+
+ if (!strcmp(dir, "."))
+ {
+ strcpy(filename, iwadname);
+ }
+ else
+ {
+ sprintf(filename, "%s%c%s", dir, DIR_SEPARATOR, iwadname);
+ }
+
+ if (M_FileExists(filename))
+ {
+ return filename;
+ }
+
+ free(filename);
+
+ return NULL;
+}
+
// Search a directory to try to find an IWAD
// Returns the location of the IWAD if found, otherwise NULL.
static char *SearchDirectoryForIWAD(char *dir, int mask, GameMission_t *mission)
{
+ char *filename;
size_t i;
for (i=0; i<arrlen(iwads); ++i)
{
- char *filename;
- char *iwadname;
-
if (((1 << iwads[i].mission) & mask) == 0)
{
continue;
}
- iwadname = DEH_String(iwads[i].name);
-
- filename = malloc(strlen(dir) + strlen(iwadname) + 3);
-
- if (!strcmp(dir, "."))
- {
- strcpy(filename, iwadname);
- }
- else
- {
- sprintf(filename, "%s%c%s", dir, DIR_SEPARATOR, iwadname);
- }
+ filename = CheckDirectoryHasIWAD(dir, DEH_String(iwads[i].name));
- if (M_FileExists(filename))
+ if (filename != NULL)
{
*mission = iwads[i].mission;
return filename;
}
-
- free(filename);
}
return NULL;
@@ -528,7 +569,6 @@ char *D_FindWADByName(char *name)
{
char *buf;
int i;
- boolean exists;
// Absolute path?
@@ -543,14 +583,21 @@ char *D_FindWADByName(char *name)
for (i=0; i<num_iwad_dirs; ++i)
{
+ // As a special case, if this is in DOOMWADDIR or DOOMWADPATH,
+ // the "directory" may actually refer directly to an IWAD
+ // file.
+
+ if (DirIsFile(iwad_dirs[i], name) && M_FileExists(iwad_dirs[i]))
+ {
+ return strdup(iwad_dirs[i]);
+ }
+
// Construct a string for the full path
buf = malloc(strlen(iwad_dirs[i]) + strlen(name) + 5);
sprintf(buf, "%s%c%s", iwad_dirs[i], DIR_SEPARATOR, name);
- exists = M_FileExists(buf);
-
- if (exists)
+ if (M_FileExists(buf))
{
return buf;
}
diff --git a/src/doom/.gitignore b/src/doom/.gitignore
index d7e732ad..973a0073 100644
--- a/src/doom/.gitignore
+++ b/src/doom/.gitignore
@@ -5,3 +5,5 @@ Makefile.in
chocolate-doom
chocolate-server
*.exe
+tags
+TAGS
diff --git a/src/doom/g_game.c b/src/doom/g_game.c
index 35bf4d74..8d0e4503 100644
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -588,10 +588,20 @@ void G_BuildTiccmd (ticcmd_t* cmd)
if (lowres_turn)
{
- // round angleturn to the nearest 256 boundary
+ static signed short carry = 0;
+ signed short desired_angleturn;
+
+ desired_angleturn = cmd->angleturn + carry;
+
+ // round angleturn to the nearest 256 unit boundary
// for recording demos with single byte values for turn
- cmd->angleturn = (cmd->angleturn + 128) & 0xff00;
+ cmd->angleturn = (desired_angleturn + 128) & 0xff00;
+
+ // Carry forward the error from the reduced resolution to the
+ // next tic, so that successive small movements can accumulate.
+
+ carry = desired_angleturn - cmd->angleturn;
}
}
diff --git a/src/doom/hu_stuff.c b/src/doom/hu_stuff.c
index a106978e..ca74ce92 100644
--- a/src/doom/hu_stuff.c
+++ b/src/doom/hu_stuff.c
@@ -52,9 +52,9 @@
// Locally used constants, shortcuts.
//
#define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1])
-#define HU_TITLE2 (mapnames2[gamemap-1])
-#define HU_TITLEP (mapnamesp[gamemap-1])
-#define HU_TITLET (mapnamest[gamemap-1])
+#define HU_TITLE2 (mapnames_commercial[gamemap-1])
+#define HU_TITLEP (mapnames_commercial[gamemap-1 + 32])
+#define HU_TITLET (mapnames_commercial[gamemap-1 + 64])
#define HU_TITLE_CHEX (mapnames[gamemap - 1])
#define HU_TITLEHEIGHT 1
#define HU_TITLEX 0
@@ -171,8 +171,16 @@ char* mapnames[] = // DOOM shareware/registered/retail (Ultimate) names.
"NEWLEVEL"
};
-char* mapnames2[] = // DOOM 2 map names.
+// List of names for levels in commercial IWADs
+// (doom2.wad, plutonia.wad, tnt.wad). These are stored in a
+// single large array; WADs like pl2.wad have a MAP33, and rely on
+// the layout in the Vanilla executable, where it is possible to
+// overflow the end of one array into the next.
+
+char *mapnames_commercial[] =
{
+ // DOOM 2 map names.
+
HUSTR_1,
HUSTR_2,
HUSTR_3,
@@ -206,12 +214,10 @@ char* mapnames2[] = // DOOM 2 map names.
HUSTR_29,
HUSTR_30,
HUSTR_31,
- HUSTR_32
-};
+ HUSTR_32,
+ // Plutonia WAD map names.
-char* mapnamesp[] = // Plutonia WAD map names.
-{
PHUSTR_1,
PHUSTR_2,
PHUSTR_3,
@@ -245,12 +251,10 @@ char* mapnamesp[] = // Plutonia WAD map names.
PHUSTR_29,
PHUSTR_30,
PHUSTR_31,
- PHUSTR_32
-};
-
+ PHUSTR_32,
+
+ // TNT WAD map names.
-char *mapnamest[] = // TNT WAD map names.
-{
THUSTR_1,
THUSTR_2,
THUSTR_3,
diff --git a/src/doom/p_map.c b/src/doom/p_map.c
index 3f88aabc..925e4398 100644
--- a/src/doom/p_map.c
+++ b/src/doom/p_map.c
@@ -885,7 +885,17 @@ PTR_AimTraverse (intercept_t* in)
dist = FixedMul (attackrange, in->frac);
- if (li->frontsector->floorheight != li->backsector->floorheight)
+ // Return false if there is no back sector. This should never
+ // be the case if the line is two-sided; however, some WADs
+ // (eg. ottawau.wad) use this as an "impassible glass" trick
+ // and rely on Vanilla Doom's (unintentional) support for this.
+
+ if (li->backsector == NULL)
+ {
+ return false;
+ }
+
+ if (li->frontsector->floorheight != li->backsector->floorheight)
{
slope = FixedDiv (openbottom - shootz , dist);
if (slope > bottomslope)
@@ -973,7 +983,14 @@ boolean PTR_ShootTraverse (intercept_t* in)
dist = FixedMul (attackrange, in->frac);
- if (li->frontsector->floorheight != li->backsector->floorheight)
+ // Check if backsector is NULL. See comment in PTR_AimTraverse.
+
+ if (li->backsector == NULL)
+ {
+ goto hitline;
+ }
+
+ if (li->frontsector->floorheight != li->backsector->floorheight)
{
slope = FixedDiv (openbottom - shootz , dist);
if (slope > aimslope)
diff --git a/src/doom/p_setup.c b/src/doom/p_setup.c
index 5cf7a628..2a3a8f85 100644
--- a/src/doom/p_setup.c
+++ b/src/doom/p_setup.c
@@ -167,6 +167,7 @@ void P_LoadSegs (int lump)
line_t* ldef;
int linedef;
int side;
+ int sidenum;
numsegs = W_LumpLength (lump) / sizeof(mapseg_t);
segs = Z_Malloc (numsegs*sizeof(seg_t),PU_LEVEL,0);
@@ -179,7 +180,7 @@ void P_LoadSegs (int lump)
{
li->v1 = &vertexes[SHORT(ml->v1)];
li->v2 = &vertexes[SHORT(ml->v2)];
-
+
li->angle = (SHORT(ml->angle))<<16;
li->offset = (SHORT(ml->offset))<<16;
linedef = SHORT(ml->linedef);
@@ -188,10 +189,28 @@ void P_LoadSegs (int lump)
side = SHORT(ml->side);
li->sidedef = &sides[ldef->sidenum[side]];
li->frontsector = sides[ldef->sidenum[side]].sector;
- if (ldef-> flags & ML_TWOSIDED)
- li->backsector = sides[ldef->sidenum[side^1]].sector;
- else
+
+ if (ldef-> flags & ML_TWOSIDED)
+ {
+ sidenum = ldef->sidenum[side ^ 1];
+
+ // If the sidenum is out of range, this may be a "glass hack"
+ // impassible window. Point at side #0 (this may not be
+ // the correct Vanilla behavior; however, it seems to work for
+ // OTTAWAU.WAD, which is the one place I've seen this trick
+ // used).
+
+ if (sidenum < 0 || sidenum >= numsides)
+ {
+ sidenum = 0;
+ }
+
+ li->backsector = sides[sidenum].sector;
+ }
+ else
+ {
li->backsector = 0;
+ }
}
W_ReleaseLumpNum(lump);
diff --git a/src/doom/p_sight.c b/src/doom/p_sight.c
index e192567b..79c1bb1d 100644
--- a/src/doom/p_sight.c
+++ b/src/doom/p_sight.c
@@ -173,7 +173,7 @@ boolean P_CrossSubsector (int num)
continue;
line->validcount = validcount;
-
+
v1 = line->v1;
v2 = line->v2;
s1 = P_DivlineSide (v1->x,v1->y, &strace);
@@ -194,6 +194,14 @@ boolean P_CrossSubsector (int num)
if (s1 == s2)
continue;
+ // Backsector may be NULL if this is an "impassible
+ // glass" hack line.
+
+ if (line->backsector == NULL)
+ {
+ return false;
+ }
+
// stop because it is not two sided anyway
// might do this after updating validcount?
if ( !(line->flags & ML_TWOSIDED) )
diff --git a/src/doom/st_stuff.c b/src/doom/st_stuff.c
index e6ef0828..160244ce 100644
--- a/src/doom/st_stuff.c
+++ b/src/doom/st_stuff.c
@@ -260,9 +260,6 @@
// Height, in lines.
#define ST_OUTHEIGHT 1
-#define ST_MAPWIDTH \
- (strlen(mapnames[(gameepisode-1)*9+(gamemap-1)]))
-
#define ST_MAPTITLEX \
(SCREENWIDTH - ST_MAPWIDTH * ST_CHATFONTWIDTH)
@@ -418,10 +415,6 @@ cheatseq_t cheat_clev = CHEAT("idclev", 2);
cheatseq_t cheat_mypos = CHEAT("idmypos", 0);
-//
-extern char* mapnames[];
-
-
//
// STATUS BAR CODE
//
@@ -985,6 +978,17 @@ void ST_doPaletteStuff(void)
else
palette = 0;
+ // In Chex Quest, the player never sees red. Instead, the
+ // radiation suit palette is used to tint the screen green,
+ // as though the player is being covered in goo by an
+ // attacking flemoid.
+
+ if (gameversion == exe_chex
+ && palette >= STARTREDPALS && palette < STARTREDPALS + NUMREDPALS)
+ {
+ palette = RADIATIONPAL;
+ }
+
if (palette != st_palette)
{
st_palette = palette;
diff --git a/src/i_video.c b/src/i_video.c
index 64a2e8eb..a370fc08 100644
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -503,6 +503,7 @@ void I_ShutdownGraphics(void)
{
if (initialized)
{
+ SDL_SetCursor(cursors[1]);
SDL_ShowCursor(1);
SDL_WM_GrabInput(SDL_GRAB_OFF);
diff --git a/src/mus2mid.c b/src/mus2mid.c
index 8ba1a5ff..88d24c97 100644
--- a/src/mus2mid.c
+++ b/src/mus2mid.c
@@ -1,4 +1,4 @@
-// Emacs style mode select -*- C++ -*-
+// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright(C) 1993-1996 Id Software, Inc.
@@ -31,594 +31,663 @@
#include "memio.h"
#include "mus2mid.h"
+#define NUM_CHANNELS 16
+
+#define MIDI_PERCUSSION_CHAN 9
+#define MUS_PERCUSSION_CHAN 15
+
// MUS event codes
-typedef enum
+typedef enum
{
- mus_releasekey = 0x00,
- mus_presskey = 0x10,
- mus_pitchwheel = 0x20,
- mus_systemevent = 0x30,
- mus_changecontroller = 0x40,
- mus_scoreend = 0x60
+ mus_releasekey = 0x00,
+ mus_presskey = 0x10,
+ mus_pitchwheel = 0x20,
+ mus_systemevent = 0x30,
+ mus_changecontroller = 0x40,
+ mus_scoreend = 0x60
} musevent;
// MIDI event codes
-typedef enum
+typedef enum
{
- midi_releasekey = 0x80,
- midi_presskey = 0x90,
- midi_aftertouchkey = 0xA0,
- midi_changecontroller = 0xB0,
- midi_changepatch = 0xC0,
- midi_aftertouchchannel = 0xD0,
- midi_pitchwheel = 0xE0
+ midi_releasekey = 0x80,
+ midi_presskey = 0x90,
+ midi_aftertouchkey = 0xA0,
+ midi_changecontroller = 0xB0,
+ midi_changepatch = 0xC0,
+ midi_aftertouchchannel = 0xD0,
+ midi_pitchwheel = 0xE0
} midievent;
-
// Structure to hold MUS file header
-typedef struct
+typedef struct
{
- byte id[4];
- unsigned short scorelength;
- unsigned short scorestart;
- unsigned short primarychannels;
- unsigned short secondarychannels;
- unsigned short instrumentcount;
+ byte id[4];
+ unsigned short scorelength;
+ unsigned short scorestart;
+ unsigned short primarychannels;
+ unsigned short secondarychannels;
+ unsigned short instrumentcount;
} PACKEDATTR musheader;
// Standard MIDI type 0 header + track header
-static byte midiheader[] =
+static const byte midiheader[] =
{
- 'M', 'T', 'h', 'd', // Main header
- 0x00, 0x00, 0x00, 0x06, // Header size
- 0x00, 0x00, // MIDI type (0)
- 0x00, 0x01, // Number of tracks
- 0x00, 0x46, // Resolution
- 'M', 'T', 'r', 'k', // Start of track
- 0x00, 0x00, 0x00, 0x00 // Placeholder for track length
+ 'M', 'T', 'h', 'd', // Main header
+ 0x00, 0x00, 0x00, 0x06, // Header size
+ 0x00, 0x00, // MIDI type (0)
+ 0x00, 0x01, // Number of tracks
+ 0x00, 0x46, // Resolution
+ 'M', 'T', 'r', 'k', // Start of track
+ 0x00, 0x00, 0x00, 0x00 // Placeholder for track length
};
// Cached channel velocities
-static byte channelvelocities[] =
-{
- 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 127, 127, 127, 127
+static byte channelvelocities[] =
+{
+ 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127
};
// Timestamps between sequences of MUS events
-static unsigned int queuedtime = 0;
+static unsigned int queuedtime = 0;
// Counter for the length of the track
static unsigned int tracksize;
-static byte mus2midi_translation[] =
-{
- 0x00, 0x20, 0x01, 0x07, 0x0A, 0x0B, 0x5B, 0x5D,
- 0x40, 0x43, 0x78, 0x7B, 0x7E, 0x7F, 0x79
+static const byte controller_map[] =
+{
+ 0x00, 0x20, 0x01, 0x07, 0x0A, 0x0B, 0x5B, 0x5D,
+ 0x40, 0x43, 0x78, 0x7B, 0x7E, 0x7F, 0x79
};
+static int channel_map[NUM_CHANNELS];
+
// Write timestamp to a MIDI file.
-static boolean midi_writetime(unsigned int time, MEMFILE *midioutput)
+static boolean WriteTime(unsigned int time, MEMFILE *midioutput)
{
- unsigned int buffer = time & 0x7F;
- byte writeval;
-
- while ((time >>= 7) != 0)
- {
- buffer <<= 8;
- buffer |= ((time & 0x7F) | 0x80);
- }
-
- for (;;)
- {
- writeval = (byte)(buffer & 0xFF);
-
- if (mem_fwrite(&writeval, 1, 1, midioutput) != 1)
- {
- return true;
- }
-
- ++tracksize;
-
- if ((buffer & 0x80) != 0)
- {
- buffer >>= 8;
- }
- else
- {
- queuedtime = 0;
- return false;
- }
- }
+ unsigned int buffer = time & 0x7F;
+ byte writeval;
+
+ while ((time >>= 7) != 0)
+ {
+ buffer <<= 8;
+ buffer |= ((time & 0x7F) | 0x80);
+ }
+
+ for (;;)
+ {
+ writeval = (byte)(buffer & 0xFF);
+
+ if (mem_fwrite(&writeval, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
+
+ ++tracksize;
+
+ if ((buffer & 0x80) != 0)
+ {
+ buffer >>= 8;
+ }
+ else
+ {
+ queuedtime = 0;
+ return false;
+ }
+ }
}
// Write the end of track marker
-static boolean midi_writeendtrack(MEMFILE *midioutput)
+static boolean WriteEndTrack(MEMFILE *midioutput)
{
- byte endtrack[] = {0xFF, 0x2F, 0x00};
+ byte endtrack[] = {0xFF, 0x2F, 0x00};
- if (midi_writetime(queuedtime, midioutput))
- {
- return true;
- }
+ if (WriteTime(queuedtime, midioutput))
+ {
+ return true;
+ }
- if (mem_fwrite(endtrack, 1, 3, midioutput) != 3)
- {
- return true;
- }
+ if (mem_fwrite(endtrack, 1, 3, midioutput) != 3)
+ {
+ return true;
+ }
- tracksize += 3;
- return false;
+ tracksize += 3;
+ return false;
}
// Write a key press event
-static boolean midi_writepresskey(byte channel, byte key,
- byte velocity, MEMFILE *midioutput)
+static boolean WritePressKey(byte channel, byte key,
+ byte velocity, MEMFILE *midioutput)
{
- byte working = midi_presskey | channel;
-
- if (midi_writetime(queuedtime, midioutput))
- {
- return true;
- }
-
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
-
- working = key & 0x7F;
-
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
-
- working = velocity & 0x7F;
-
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
-
- tracksize += 3;
-
- return false;
+ byte working = midi_presskey | channel;
+
+ if (WriteTime(queuedtime, midioutput))
+ {
+ return true;
+ }
+
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
+
+ working = key & 0x7F;
+
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
+
+ working = velocity & 0x7F;
+
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
+
+ tracksize += 3;
+
+ return false;
}
// Write a key release event
-static boolean midi_writereleasekey(byte channel, byte key,
- MEMFILE *midioutput)
+static boolean WriteReleaseKey(byte channel, byte key,
+ MEMFILE *midioutput)
{
- byte working = midi_releasekey | channel;
+ byte working = midi_releasekey | channel;
- if (midi_writetime(queuedtime, midioutput))
- {
- return true;
- }
+ if (WriteTime(queuedtime, midioutput))
+ {
+ return true;
+ }
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- working = key & 0x7F;
+ working = key & 0x7F;
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- working = 0;
+ working = 0;
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- tracksize += 3;
+ tracksize += 3;
- return false;
+ return false;
}
// Write a pitch wheel/bend event
-static boolean midi_writepitchwheel(byte channel, short wheel,
- MEMFILE *midioutput)
+static boolean WritePitchWheel(byte channel, short wheel,
+ MEMFILE *midioutput)
{
- byte working = midi_pitchwheel | channel;
+ byte working = midi_pitchwheel | channel;
- if (midi_writetime(queuedtime, midioutput))
- {
- return true;
- }
+ if (WriteTime(queuedtime, midioutput))
+ {
+ return true;
+ }
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- working = wheel & 0x7F;
+ working = wheel & 0x7F;
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- working = (wheel >> 7) & 0x7F;
+ working = (wheel >> 7) & 0x7F;
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- tracksize += 3;
- return false;
+ tracksize += 3;
+ return false;
}
// Write a patch change event
-static boolean midi_writechangepatch(byte channel, byte patch,
- MEMFILE *midioutput)
+static boolean WriteChangePatch(byte channel, byte patch,
+ MEMFILE *midioutput)
{
- byte working = midi_changepatch | channel;
-
- if (midi_writetime(queuedtime, midioutput))
- {
- return true;
- }
+ byte working = midi_changepatch | channel;
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (WriteTime(queuedtime, midioutput))
+ {
+ return true;
+ }
- working = patch & 0x7F;
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ working = patch & 0x7F;
- tracksize += 2;
-
- return false;
-}
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
+ tracksize += 2;
+ return false;
+}
// Write a valued controller change event
-static boolean midi_writechangecontroller_valued(byte channel,
- byte control,
- byte value,
- MEMFILE *midioutput)
+
+static boolean WriteChangeController_Valued(byte channel,
+ byte control,
+ byte value,
+ MEMFILE *midioutput)
{
- byte working = midi_changecontroller | channel;
+ byte working = midi_changecontroller | channel;
+
+ if (WriteTime(queuedtime, midioutput))
+ {
+ return true;
+ }
- if (midi_writetime(queuedtime, midioutput))
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ working = control & 0x7F;
- working = control & 0x7F;
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
- // Quirk in vanilla DOOM? MUS controller values should be
- // 7-bit, not 8-bit.
+ // Quirk in vanilla DOOM? MUS controller values should be
+ // 7-bit, not 8-bit.
- working = value;// & 0x7F;
+ working = value;// & 0x7F;
- // Fix on said quirk to stop MIDI players from complaining that
- // the value is out of range:
+ // Fix on said quirk to stop MIDI players from complaining that
+ // the value is out of range:
- if (working & 0x80)
- {
- working = 0x7F;
- }
+ if (working & 0x80)
+ {
+ working = 0x7F;
+ }
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- tracksize += 3;
+ tracksize += 3;
- return false;
+ return false;
}
// Write a valueless controller change event
-static boolean midi_writechangecontroller_valueless(byte channel,
- byte control,
- MEMFILE *midioutput)
+static boolean WriteChangeController_Valueless(byte channel,
+ byte control,
+ MEMFILE *midioutput)
{
- return midi_writechangecontroller_valued(channel, control, 0,
- midioutput);
+ return WriteChangeController_Valued(channel, control, 0,
+ midioutput);
}
-static boolean read_musheader(MEMFILE *file, musheader *header)
+// Allocate a free MIDI channel.
+
+static int AllocateMIDIChannel(void)
{
- boolean result;
-
- result = (mem_fread(&header->id, sizeof(byte), 4, file) == 4)
- && (mem_fread(&header->scorelength, sizeof(short), 1, file) == 1)
- && (mem_fread(&header->scorestart, sizeof(short), 1, file) == 1)
- && (mem_fread(&header->primarychannels, sizeof(short), 1, file) == 1)
- && (mem_fread(&header->secondarychannels, sizeof(short), 1, file) == 1)
- && (mem_fread(&header->instrumentcount, sizeof(short), 1, file) == 1);
-
- if (result)
- {
- header->scorelength = SHORT(header->scorelength);
- header->scorestart = SHORT(header->scorestart);
- header->primarychannels = SHORT(header->primarychannels);
- header->secondarychannels = SHORT(header->secondarychannels);
- header->instrumentcount = SHORT(header->instrumentcount);
- }
-
- return result;
+ int result;
+ int max;
+ int i;
+
+ // Find the current highest-allocated channel.
+
+ max = -1;
+
+ for (i=0; i<NUM_CHANNELS; ++i)
+ {
+ if (channel_map[i] > max)
+ {
+ max = channel_map[i];
+ }
+ }
+
+ // max is now equal to the highest-allocated MIDI channel. We can
+ // now allocate the next available channel. This also works if
+ // no channels are currently allocated (max=-1)
+
+ result = max + 1;
+
+ // Don't allocate the MIDI percussion channel!
+
+ if (result == MIDI_PERCUSSION_CHAN)
+ {
+ ++result;
+ }
+
+ return result;
}
+// Given a MUS channel number, get the MIDI channel number to use
+// in the outputted file.
-// Read a MUS file from a stream (musinput) and output a MIDI file to
+static int GetMIDIChannel(int mus_channel)
+{
+ // Find the MIDI channel to use for this MUS channel.
+ // MUS channel 15 is the percusssion channel.
+
+ if (mus_channel == MUS_PERCUSSION_CHAN)
+ {
+ return MIDI_PERCUSSION_CHAN;
+ }
+ else
+ {
+ // If a MIDI channel hasn't been allocated for this MUS channel
+ // yet, allocate the next free MIDI channel.
+
+ if (channel_map[mus_channel] == -1)
+ {
+ channel_map[mus_channel] = AllocateMIDIChannel();
+ }
+
+ return channel_map[mus_channel];
+ }
+}
+
+static boolean ReadMusHeader(MEMFILE *file, musheader *header)
+{
+ boolean result;
+
+ result = mem_fread(&header->id, sizeof(byte), 4, file) == 4
+ && mem_fread(&header->scorelength, sizeof(short), 1, file) == 1
+ && mem_fread(&header->scorestart, sizeof(short), 1, file) == 1
+ && mem_fread(&header->primarychannels, sizeof(short), 1, file) == 1
+ && mem_fread(&header->secondarychannels, sizeof(short), 1, file) == 1
+ && mem_fread(&header->instrumentcount, sizeof(short), 1, file) == 1;
+
+ if (result)
+ {
+ header->scorelength = SHORT(header->scorelength);
+ header->scorestart = SHORT(header->scorestart);
+ header->primarychannels = SHORT(header->primarychannels);
+ header->secondarychannels = SHORT(header->secondarychannels);
+ header->instrumentcount = SHORT(header->instrumentcount);
+ }
+
+ return result;
+}
+
+
+// Read a MUS file from a stream (musinput) and output a MIDI file to
// a stream (midioutput).
//
// Returns 0 on success or 1 on failure.
-boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput)
+boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput)
{
- // Header for the MUS file
- musheader musfileheader;
+ // Header for the MUS file
+ musheader musfileheader;
+
+ // Descriptor for the current MUS event
+ byte eventdescriptor;
+ int channel; // Channel number
+ musevent event;
+
+
+ // Bunch of vars read from MUS lump
+ byte key;
+ byte controllernumber;
+ byte controllervalue;
- // Descriptor for the current MUS event
- byte eventdescriptor;
- int channel; // Channel number
- musevent event;
-
+ // Buffer used for MIDI track size record
+ byte tracksizebuffer[4];
- // Bunch of vars read from MUS lump
- byte key;
- byte controllernumber;
- byte controllervalue;
+ // Flag for when the score end marker is hit.
+ int hitscoreend = 0;
- // Buffer used for MIDI track size record
- byte tracksizebuffer[4];
+ // Temp working byte
+ byte working;
+ // Used in building up time delays
+ unsigned int timedelay;
- // Flag for when the score end marker is hit.
- int hitscoreend = 0;
+ // Initialise channel map to mark all channels as unused.
- // Temp working byte
- byte working;
- // Used in building up time delays
- unsigned int timedelay;
+ for (channel=0; channel<NUM_CHANNELS; ++channel)
+ {
+ channel_map[channel] = -1;
+ }
- // Grab the header
+ // Grab the header
- if (!read_musheader(musinput, &musfileheader))
- {
- return true;
- }
+ if (!ReadMusHeader(musinput, &musfileheader))
+ {
+ return true;
+ }
#ifdef CHECK_MUS_HEADER
- // Check MUS header
- if (musfileheader.id[0] != 'M'
- || musfileheader.id[1] != 'U'
- || musfileheader.id[2] != 'S'
- || musfileheader.id[3] != 0x1A)
- {
- return true;
- }
+ // Check MUS header
+ if (musfileheader.id[0] != 'M'
+ || musfileheader.id[1] != 'U'
+ || musfileheader.id[2] != 'S'
+ || musfileheader.id[3] != 0x1A)
+ {
+ return true;
+ }
#endif
- // Seek to where the data is held
- if (mem_fseek(musinput, (long)musfileheader.scorestart,
- MEM_SEEK_SET) != 0)
- {
- return true;
- }
-
- // So, we can assume the MUS file is faintly legit. Let's start
- // writing MIDI data...
-
- mem_fwrite(midiheader, 1, sizeof(midiheader), midioutput);
- tracksize = 0;
-
- // Now, process the MUS file:
- while (!hitscoreend)
- {
- // Handle a block of events:
-
- while (!hitscoreend)
- {
- // Fetch channel number and event code:
-
- if (mem_fread(&eventdescriptor, 1, 1, musinput) != 1)
- {
- return true;
- }
-
- channel = eventdescriptor & 0x0F;
- event = eventdescriptor & 0x70;
-
- // Swap channels 15 and 9.
- // MIDI channel 9 = percussion.
- // MUS channel 15 = percussion.
-
- if (channel == 15)
- {
- channel = 9;
- }
- else if (channel == 9)
- {
- channel = 15;
- }
-
- switch (event)
- {
- case mus_releasekey:
- if (mem_fread(&key, 1, 1, musinput) != 1)
- {
- return true;
- }
-
- if (midi_writereleasekey(channel, key, midioutput))
- {
- return true;
- }
-
- break;
-
- case mus_presskey:
- if (mem_fread(&key, 1, 1, musinput) != 1)
- {
- return true;
- }
-
- if (key & 0x80)
- {
- if (mem_fread(&channelvelocities[channel], 1, 1, musinput) != 1)
- {
- return true;
- }
-
- channelvelocities[channel] &= 0x7F;
- }
-
- if (midi_writepresskey(channel, key, channelvelocities[channel], midioutput))
- {
- return true;
- }
-
- break;
-
- case mus_pitchwheel:
- if (mem_fread(&key, 1, 1, musinput) != 1)
- {
- break;
- }
- if (midi_writepitchwheel(channel, (short)(key * 64), midioutput))
- {
- return true;
- }
-
- break;
-
- case mus_systemevent:
- if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
- {
- return true;
- }
- if (controllernumber < 10 || controllernumber > 14)
- {
- return true;
- }
-
- if (midi_writechangecontroller_valueless(channel, mus2midi_translation[controllernumber], midioutput))
- {
- return true;
- }
-
- break;
-
- case mus_changecontroller:
- if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
- {
- return true;
- }
-
- if (mem_fread(&controllervalue, 1, 1, musinput) != 1)
- {
- return true;
- }
-
- if (controllernumber == 0)
- {
- if (midi_writechangepatch(channel, controllervalue, midioutput))
- {
- return true;
- }
- }
- else
- {
- if (controllernumber < 1 || controllernumber > 9)
- {
- return true;
- }
-
- if (midi_writechangecontroller_valued(channel, mus2midi_translation[controllernumber], controllervalue, midioutput))
- {
- return true;
- }
- }
-
- break;
-
- case mus_scoreend:
- hitscoreend = 1;
- break;
-
- default:
- return true;
- break;
- }
-
- if (eventdescriptor & 0x80)
- {
- break;
- }
- }
- // Now we need to read the time code:
- if (!hitscoreend)
- {
- timedelay = 0;
- for (;;)
- {
- if (mem_fread(&working, 1, 1, musinput) != 1)
- {
- return true;
- }
-
- timedelay = timedelay * 128 + (working & 0x7F);
- if ((working & 0x80) == 0)
- {
- break;
- }
- }
- queuedtime += timedelay;
- }
- }
-
- // End of track
- if (midi_writeendtrack(midioutput))
- {
- return true;
- }
-
- // Write the track size into the stream
- if (mem_fseek(midioutput, 18, MEM_SEEK_SET))
- {
- return true;
- }
-
- tracksizebuffer[0] = (tracksize >> 24) & 0xff;
- tracksizebuffer[1] = (tracksize >> 16) & 0xff;
- tracksizebuffer[2] = (tracksize >> 8) & 0xff;
- tracksizebuffer[3] = tracksize & 0xff;
-
- if (mem_fwrite(tracksizebuffer, 1, 4, midioutput) != 4)
- {
- return true;
- }
-
- return false;
+ // Seek to where the data is held
+ if (mem_fseek(musinput, (long)musfileheader.scorestart,
+ MEM_SEEK_SET) != 0)
+ {
+ return true;
+ }
+
+ // So, we can assume the MUS file is faintly legit. Let's start
+ // writing MIDI data...
+
+ mem_fwrite(midiheader, 1, sizeof(midiheader), midioutput);
+ tracksize = 0;
+
+ // Now, process the MUS file:
+ while (!hitscoreend)
+ {
+ // Handle a block of events:
+
+ while (!hitscoreend)
+ {
+ // Fetch channel number and event code:
+
+ if (mem_fread(&eventdescriptor, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ channel = GetMIDIChannel(eventdescriptor & 0x0F);
+ event = eventdescriptor & 0x70;
+
+ switch (event)
+ {
+ case mus_releasekey:
+ if (mem_fread(&key, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ if (WriteReleaseKey(channel, key, midioutput))
+ {
+ return true;
+ }
+
+ break;
+
+ case mus_presskey:
+ if (mem_fread(&key, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ if (key & 0x80)
+ {
+ if (mem_fread(&channelvelocities[channel], 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ channelvelocities[channel] &= 0x7F;
+ }
+
+ if (WritePressKey(channel, key,
+ channelvelocities[channel], midioutput))
+ {
+ return true;
+ }
+
+ break;
+
+ case mus_pitchwheel:
+ if (mem_fread(&key, 1, 1, musinput) != 1)
+ {
+ break;
+ }
+ if (WritePitchWheel(channel, (short)(key * 64), midioutput))
+ {
+ return true;
+ }
+
+ break;
+
+ case mus_systemevent:
+ if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+ if (controllernumber < 10 || controllernumber > 14)
+ {
+ return true;
+ }
+
+ if (WriteChangeController_Valueless(channel,
+ controller_map[controllernumber],
+ midioutput))
+ {
+ return true;
+ }
+
+ break;
+
+ case mus_changecontroller:
+ if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ if (mem_fread(&controllervalue, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ if (controllernumber == 0)
+ {
+ if (WriteChangePatch(channel, controllervalue,
+ midioutput))
+ {
+ return true;
+ }
+ }
+ else
+ {
+ if (controllernumber < 1 || controllernumber > 9)
+ {
+ return true;
+ }
+
+ if (WriteChangeController_Valued(channel,
+ controller_map[controllernumber],
+ controllervalue,
+ midioutput))
+ {
+ return true;
+ }
+ }
+
+ break;
+
+ case mus_scoreend:
+ hitscoreend = 1;
+ break;
+
+ default:
+ return true;
+ break;
+ }
+
+ if (eventdescriptor & 0x80)
+ {
+ break;
+ }
+ }
+ // Now we need to read the time code:
+ if (!hitscoreend)
+ {
+ timedelay = 0;
+ for (;;)
+ {
+ if (mem_fread(&working, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ timedelay = timedelay * 128 + (working & 0x7F);
+ if ((working & 0x80) == 0)
+ {
+ break;
+ }
+ }
+ queuedtime += timedelay;
+ }
+ }
+
+ // End of track
+ if (WriteEndTrack(midioutput))
+ {
+ return true;
+ }
+
+ // Write the track size into the stream
+ if (mem_fseek(midioutput, 18, MEM_SEEK_SET))
+ {
+ return true;
+ }
+
+ tracksizebuffer[0] = (tracksize >> 24) & 0xff;
+ tracksizebuffer[1] = (tracksize >> 16) & 0xff;
+ tracksizebuffer[2] = (tracksize >> 8) & 0xff;
+ tracksizebuffer[3] = tracksize & 0xff;
+
+ if (mem_fwrite(tracksizebuffer, 1, 4, midioutput) != 4)
+ {
+ return true;
+ }
+
+ return false;
}
diff --git a/src/resource.rc.in b/src/resource.rc.in
index 7eb5d00f..f8b64331 100644
--- a/src/resource.rc.in
+++ b/src/resource.rc.in
@@ -13,7 +13,7 @@ FILETYPE 1
VALUE "FileDescription", "@PACKAGE_STRING@"
VALUE "InternalName", "@PACKAGE_TARNAME@"
VALUE "CompanyName", "@PACKAGE_BUGREPORT@"
- VALUE "LegalCopyright", "GNU General Public License"
+ VALUE "LegalCopyright", "@PACKAGE_COPYRIGHT@. Licensed under @PACKAGE_LICENSE@"
VALUE "ProductName", "@PACKAGE_NAME@"
VALUE "ProductVersion", "@PACKAGE_VERSION@"
}
diff --git a/src/setup/.gitignore b/src/setup/.gitignore
index d7e732ad..37c8e4c1 100644
--- a/src/setup/.gitignore
+++ b/src/setup/.gitignore
@@ -1,7 +1,8 @@
-Makefile
Makefile.in
+Makefile
.deps
+chocolate-setup
*.rc
-chocolate-doom
-chocolate-server
*.exe
+tags
+TAGS
diff --git a/src/setup/Makefile.am b/src/setup/Makefile.am
index 07d7c936..25ab38e3 100644
--- a/src/setup/Makefile.am
+++ b/src/setup/Makefile.am
@@ -27,3 +27,10 @@ libsetup_a_SOURCES = $(SOURCE_FILES)
EXTRA_DIST= \
setup_icon.c
+if HAVE_PYTHON
+
+setup_icon.c : $(top_builddir)/data/setup8.ico
+ $(top_builddir)/data/convert-icon $^ $@
+
+endif
+
diff --git a/src/setup/execute.c b/src/setup/execute.c
index be7214f5..4be44149 100644
--- a/src/setup/execute.c
+++ b/src/setup/execute.c
@@ -172,29 +172,38 @@ static void ConcatWCString(wchar_t *buf, const char *value)
static wchar_t *BuildCommandLine(const char *program, const char *arg)
{
+ wchar_t exe_path[MAX_PATH];
wchar_t *result;
- char *sep;
+ wchar_t *sep;
+
+ // Get the path to this .exe file.
+
+ GetModuleFileNameW(NULL, exe_path, MAX_PATH);
- result = calloc(strlen(myargv[0]) + strlen(program) + strlen(arg) + 6,
+ // Allocate buffer to contain result string.
+
+ result = calloc(wcslen(exe_path) + strlen(program) + strlen(arg) + 6,
sizeof(wchar_t));
wcscpy(result, L"\"");
- sep = strrchr(myargv[0], DIR_SEPARATOR);
+ // Copy the path part of the filename (including ending \)
+ // into the result buffer:
+
+ sep = wcsrchr(exe_path, DIR_SEPARATOR);
if (sep != NULL)
{
- ConcatWCString(result, myargv[0]);
-
- // Cut off the string after the last directory separator,
- // before appending the actual program.
-
- result[sep - myargv[0] + 2] = '\0';
-
+ wcsncpy(result + 1, exe_path, sep - exe_path + 1);
+ result[sep - exe_path + 2] = '\0';
}
+ // Concatenate the name of the program:
+
ConcatWCString(result, program);
+ // End of program name, start of argument:
+
wcscat(result, L"\" \"");
ConcatWCString(result, arg);
@@ -290,7 +299,7 @@ static int ExecuteCommand(const char *program, const char *arg)
execvp(argv[0], (char **) argv);
- exit(-1);
+ exit(0x80);
}
else
{
@@ -299,7 +308,7 @@ static int ExecuteCommand(const char *program, const char *arg)
waitpid(childpid, &result, 0);
- if (WIFEXITED(result))
+ if (WIFEXITED(result) && WEXITSTATUS(result) != 0x80)
{
return WEXITSTATUS(result);
}