diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/.gitignore | 2 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/d_iwad.c | 91 | ||||
-rw-r--r-- | src/doom/.gitignore | 2 | ||||
-rw-r--r-- | src/doom/g_game.c | 14 | ||||
-rw-r--r-- | src/doom/hu_stuff.c | 30 | ||||
-rw-r--r-- | src/doom/p_map.c | 21 | ||||
-rw-r--r-- | src/doom/p_setup.c | 27 | ||||
-rw-r--r-- | src/doom/p_sight.c | 10 | ||||
-rw-r--r-- | src/doom/st_stuff.c | 18 | ||||
-rw-r--r-- | src/i_video.c | 1 | ||||
-rw-r--r-- | src/mus2mid.c | 1019 | ||||
-rw-r--r-- | src/resource.rc.in | 2 | ||||
-rw-r--r-- | src/setup/.gitignore | 7 | ||||
-rw-r--r-- | src/setup/Makefile.am | 7 | ||||
-rw-r--r-- | src/setup/execute.c | 33 |
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); } |