ref: 98f798dd4b926ff8e97ed0b058c750ba2d5e2b06
parent: b36170d140fa89f2977e6a14c1042dcaa524b949
parent: 939cbfeb115338cf7868e516019a4ae832b1ebde
author: Simon Howard <fraggle+github@gmail.com>
date: Mon Jan 2 10:02:20 EST 2017
Merge branch 'master' into commandline-savedir
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,6 +1,12 @@
## HEAD
### General
+ * A new parameter -savedir allows users to specify a directory from
+ which to load and save games. (thanks CapnClever)
+
+## 2.3.0 (2016-12-29)
+
+### General
* Bash completion scripts are included (thanks Fabian)
* The OS X launcher now supports the .lmp file format (thanks Jon)
* Pitch-shifting from early versions of Doom, Heretic, and Hexen.
@@ -21,8 +27,9 @@
* Multiple capitalizations are now tried when searching for WAD files,
for convenience when running on case sensitive filesystems (thanks
Fabian).
- * New parameter -savedir allows users to specify a directory from
- which to load and save games. (thanks CapnClever)
+ * A new command line argument, `-strictdemos`, was added, to allow
+ more careful control over demo format extensions. Such extensions
+ are now forbidden in WAD files and warning messages are shown.
### Build systems
* There is better compatibility with BSD Make (thanks R.Rebello)
--- a/codeblocks/config.h
+++ b/codeblocks/config.h
@@ -9,13 +9,13 @@
#define PACKAGE_NAME "Chocolate Doom"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "Chocolate Doom 2.2.1"
+#define PACKAGE_STRING "Chocolate Doom 2.3.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "chocolate-doom"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.2.1"
+#define PACKAGE_VERSION "2.3.0"
/* Change this when you create your awesome forked version */
#define PROGRAM_PREFIX "chocolate-"
@@ -24,7 +24,7 @@
#define STDC_HEADERS 1
/* Version number of package */
-#define VERSION "2.2.1"
+#define VERSION "2.3.0"
/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */
--- a/codeblocks/game-res.rc
+++ b/codeblocks/game-res.rc
@@ -1,8 +1,8 @@
1 ICON "../data/doom.ico"
1 VERSIONINFO
-PRODUCTVERSION 2,2,1,0
-FILEVERSION 2,2,1,0
+PRODUCTVERSION 2,3,0,0
+FILEVERSION 2,3,0,0
FILETYPE 1
{
BLOCK "StringFileInfo"
@@ -9,13 +9,13 @@
{
BLOCK "040904E4"
{
- VALUE "FileVersion", "2.2.1"
- VALUE "FileDescription", "2.2.1"
+ VALUE "FileVersion", "2.3.0"
+ VALUE "FileDescription", "2.3.0"
VALUE "InternalName", "Chocolate Doom"
VALUE "CompanyName", "Chocolate Doom"
VALUE "LegalCopyright", "GNU General Public License"
VALUE "ProductName", "Chocolate Doom"
- VALUE "ProductVersion", "2.2.1"
+ VALUE "ProductVersion", "2.3.0"
}
}
BLOCK "VarFileInfo"
--- a/codeblocks/setup-res.rc
+++ b/codeblocks/setup-res.rc
@@ -1,8 +1,8 @@
1 ICON "../data/setup.ico"
1 VERSIONINFO
-PRODUCTVERSION 2,2,1,0
-FILEVERSION 2,2,1,0
+PRODUCTVERSION 2,3,0,0
+FILEVERSION 2,3,0,0
FILETYPE 1
{
BLOCK "StringFileInfo"
@@ -9,13 +9,13 @@
{
BLOCK "040904E4"
{
- VALUE "FileVersion", "2.2.1"
+ VALUE "FileVersion", "2.3.0"
VALUE "FileDescription", "Chocolate Doom Setup"
VALUE "InternalName", "chocolate-setup"
VALUE "CompanyName", "Chocolate Doom"
VALUE "LegalCopyright", "GNU General Public License"
VALUE "ProductName", "Chocolate Doom Setup"
- VALUE "ProductVersion", "2.2.1"
+ VALUE "ProductVersion", "2.3.0"
}
}
BLOCK "VarFileInfo"
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(Chocolate Doom, 2.2.1, chocolate-doom-dev-list@chocolate-doom.org,
+AC_INIT(Chocolate Doom, 2.3.0, chocolate-doom-dev-list@chocolate-doom.org,
chocolate-doom)
PACKAGE_SHORTNAME=${PACKAGE_NAME% Doom}
--- a/msvc/config.h
+++ b/msvc/config.h
@@ -11,19 +11,19 @@
#define PACKAGE_NAME "Chocolate Doom"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "Chocolate Doom 2.2.1"
+#define PACKAGE_STRING "Chocolate Doom 2.3.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "chocolate-doom"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.2.1"
+#define PACKAGE_VERSION "2.3.0"
/* Change this when you create your awesome forked version */
#define PROGRAM_PREFIX "chocolate-"
/* Version number of package */
-#define VERSION "2.2.1"
+#define VERSION "2.3.0"
/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */
--- a/msvc/win32.rc
+++ b/msvc/win32.rc
@@ -25,8 +25,8 @@
#endif
1 VERSIONINFO
-PRODUCTVERSION 2,2,1,0
-FILEVERSION 2,2,1,0
+PRODUCTVERSION 2,3,0,0
+FILEVERSION 2,3,0,0
FILETYPE 1
BEGIN
BLOCK "StringFileInfo"
@@ -34,12 +34,12 @@
BLOCK "040904E4"
BEGIN
VALUE "FileVersion", "1.0.0"
- VALUE "FileDescription", "Chocolate Doom 2.2.1"
+ VALUE "FileDescription", "Chocolate Doom 2.3.0"
VALUE "InternalName", "chocolate-doom"
VALUE "CompanyName", "fraggle@gmail.com"
VALUE "LegalCopyright", "GNU General Public License"
VALUE "ProductName", "Chocolate Doom"
- VALUE "ProductVersion", "2.2.1"
+ VALUE "ProductVersion", "2.3.0"
END
END
BLOCK "VarFileInfo"
--- a/src/heretic/p_enemy.c
+++ b/src/heretic/p_enemy.c
@@ -845,8 +845,8 @@
r1 = P_SubRandom();
r2 = P_SubRandom();
- mo = P_SpawnMobj(actor->x + (r1 << 11),
- actor->y + (r2 << 11), actor->z,
+ mo = P_SpawnMobj(actor->x + (r2 << 11),
+ actor->y + (r1 << 11), actor->z,
MT_BLOOD);
mo->momx = P_SubRandom() << 10;
mo->momy = P_SubRandom() << 10;
@@ -920,9 +920,9 @@
r1 = P_SubRandom();
r2 = P_SubRandom();
r3 = P_SubRandom();
- P_SpawnMobj(actor->x + (r1 << 10),
+ P_SpawnMobj(actor->x + (r3 << 10),
actor->y + (r2 << 10),
- actor->z + (r3 << 10), MT_PUFFY);
+ actor->z + (r1 << 10), MT_PUFFY);
}
}
@@ -1769,8 +1769,8 @@
r2 = P_SubRandom();
actor->z = actor->floorz;
- mo = P_SpawnMobj(actor->x + (r1 << 10),
- actor->y + (r2 << 10), ONFLOORZ,
+ mo = P_SpawnMobj(actor->x + (r2 << 10),
+ actor->y + (r1 << 10), ONFLOORZ,
MT_MNTRFX3);
mo->target = actor->target;
mo->momx = 1; // Force block checking
@@ -2416,11 +2416,12 @@
void A_SpawnTeleGlitter(mobj_t * actor)
{
mobj_t *mo;
- int r;
+ int r1, r2;
- r = P_Random();
- mo = P_SpawnMobj(actor->x + ((r & 31) - 16) * FRACUNIT,
- actor->y + ((P_Random() & 31) - 16) * FRACUNIT,
+ r1 = P_Random();
+ r2 = P_Random();
+ mo = P_SpawnMobj(actor->x + ((r2 & 31) - 16) * FRACUNIT,
+ actor->y + ((r1 & 31) - 16) * FRACUNIT,
actor->subsector->sector->floorheight, MT_TELEGLITTER);
mo->momz = FRACUNIT / 4;
}
@@ -2434,11 +2435,12 @@
void A_SpawnTeleGlitter2(mobj_t * actor)
{
mobj_t *mo;
- int r;
+ int r1, r2;
- r = P_Random();
- mo = P_SpawnMobj(actor->x + ((r & 31) - 16) * FRACUNIT,
- actor->y + ((P_Random() & 31) - 16) * FRACUNIT,
+ r1 = P_Random();
+ r2 = P_Random();
+ mo = P_SpawnMobj(actor->x + ((r2 & 31) - 16) * FRACUNIT,
+ actor->y + ((r1 & 31) - 16) * FRACUNIT,
actor->subsector->sector->floorheight, MT_TELEGLITTER2);
mo->momz = FRACUNIT / 4;
}
--- a/src/hexen/a_action.c
+++ b/src/hexen/a_action.c
@@ -1175,9 +1175,9 @@
r1 = P_Random();
r2 = P_Random();
r3 = P_Random();
- mo = P_SpawnMobj(actor->x + ((r1 - 128) << 12),
+ mo = P_SpawnMobj(actor->x + ((r3 - 128) << 12),
actor->y + ((r2 - 128) << 12),
- actor->z + (r3 * actor->height / 256),
+ actor->z + (r1 * actor->height / 256),
MT_ZARMORCHUNK);
P_SetMobjState(mo, mo->info->spawnstate + i);
if (mo)
--- a/src/hexen/p_enemy.c
+++ b/src/hexen/p_enemy.c
@@ -1481,13 +1481,14 @@
void A_MntrFloorFire(mobj_t * actor)
{
mobj_t *mo;
- int r;
+ int r1, r2;
- r = P_SubRandom();
+ r1 = P_SubRandom();
+ r2 = P_SubRandom();
actor->z = actor->floorz;
- mo = P_SpawnMobj(actor->x + (r << 10),
- actor->y + (P_SubRandom() << 10), ONFLOORZ,
+ mo = P_SpawnMobj(actor->x + (r2 << 10),
+ actor->y + (r1 << 10), ONFLOORZ,
MT_MNTRFX3);
mo->target = actor->target;
mo->momx = 1; // Force block checking
@@ -2411,10 +2412,12 @@
void A_SerpentSpawnGibs(mobj_t * actor)
{
mobj_t *mo;
- int r = P_Random();
+ int r1, r2;
- mo = P_SpawnMobj(actor->x + ((r - 128) << 12),
- actor->y + ((P_Random() - 128) << 12),
+ r1 = P_Random();
+ r2 = P_Random();
+ mo = P_SpawnMobj(actor->x + ((r2 - 128) << 12),
+ actor->y + ((r1 - 128) << 12),
actor->floorz + FRACUNIT, MT_SERPENT_GIB1);
if (mo)
{
@@ -2422,9 +2425,10 @@
mo->momy = (P_Random() - 128) << 6;
mo->floorclip = 6 * FRACUNIT;
}
- r = P_Random();
- mo = P_SpawnMobj(actor->x + ((r - 128) << 12),
- actor->y + ((P_Random() - 128) << 12),
+ r1 = P_Random();
+ r2 = P_Random();
+ mo = P_SpawnMobj(actor->x + ((r2 - 128) << 12),
+ actor->y + ((r1 - 128) << 12),
actor->floorz + FRACUNIT, MT_SERPENT_GIB2);
if (mo)
{
@@ -2432,9 +2436,10 @@
mo->momy = (P_Random() - 128) << 6;
mo->floorclip = 6 * FRACUNIT;
}
- r = P_Random();
- mo = P_SpawnMobj(actor->x + ((r - 128) << 12),
- actor->y + ((P_Random() - 128) << 12),
+ r1 = P_Random();
+ r2 = P_Random();
+ mo = P_SpawnMobj(actor->x + ((r2 - 128) << 12),
+ actor->y + ((r1 - 128) << 12),
actor->floorz + FRACUNIT, MT_SERPENT_GIB3);
if (mo)
{
@@ -2797,9 +2802,9 @@
r2 = P_SubRandom();
r3 = P_SubRandom();
- mo = P_SpawnMobj(actor->x + (r1 << 12), actor->y
+ mo = P_SpawnMobj(actor->x + (r3 << 12), actor->y
+ (r2 << 12),
- actor->z + (r3 << 11),
+ actor->z + (r1 << 11),
MT_BISHOPPAINBLUR);
if (mo)
{
@@ -3048,9 +3053,9 @@
r1 = P_Random();
r2 = P_Random();
r3 = P_Random();
- mo = P_SpawnMobj(actor->x + ((r1 - 128) << 14),
+ mo = P_SpawnMobj(actor->x + ((r3 - 128) << 14),
actor->y + ((r2 - 128) << 14),
- actor->z + ((r3 - 128) << 12),
+ actor->z + ((r1 - 128) << 12),
MT_DRAGON_FX2);
if (mo)
{
@@ -4865,10 +4870,10 @@
r2 = P_Random();
r3 = P_Random();
mo = P_SpawnMobj(actor->x +
- (((r1 - 128) * actor->radius) >> 7),
+ (((r3 - 128) * actor->radius) >> 7),
actor->y +
(((r2 - 128) * actor->radius) >> 7),
- actor->z + (r3 * actor->height / 255),
+ actor->z + (r1 * actor->height / 255),
MT_ICECHUNK);
P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 3));
if (mo)
@@ -4885,10 +4890,10 @@
r2 = P_Random();
r3 = P_Random();
mo = P_SpawnMobj(actor->x +
- (((r1 - 128) * actor->radius) >> 7),
+ (((r3 - 128) * actor->radius) >> 7),
actor->y +
(((r2 - 128) * actor->radius) >> 7),
- actor->z + (r3 * actor->height / 255),
+ actor->z + (r1 * actor->height / 255),
MT_ICECHUNK);
P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 3));
if (mo)
--- a/src/hexen/p_mobj.c
+++ b/src/hexen/p_mobj.c
@@ -1830,9 +1830,12 @@
void P_BloodSplatter2(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator)
{
mobj_t *mo;
+ int r1, r2;
- mo = P_SpawnMobj(x + ((P_Random() - 128) << 11),
- y + ((P_Random() - 128) << 11), z, MT_AXEBLOOD);
+ r1 = P_Random();
+ r2 = P_Random();
+ mo = P_SpawnMobj(x + ((r2 - 128) << 11),
+ y + ((r1 - 128) << 11), z, MT_AXEBLOOD);
mo->target = originator;
}
--- a/src/hexen/p_pspr.c
+++ b/src/hexen/p_pspr.c
@@ -868,9 +868,9 @@
r1 = P_Random();
r2 = P_Random();
r3 = P_Random();
- P_SpawnMobj(actor->x + ((r1 - 128) << 12), actor->y
+ P_SpawnMobj(actor->x + ((r3 - 128) << 12), actor->y
+ ((r2 - 128) << 12),
- actor->z + ((r3 - 128) << 11), MT_FSWORD_FLAME);
+ actor->z + ((r1 - 128) << 11), MT_FSWORD_FLAME);
}
}
@@ -1003,8 +1003,8 @@
}
r1 = P_Random();
r2 = P_Random();
- mo = P_SpawnMobj(actor->x + ((r1 - 128) * actor->radius / 256),
- actor->y + ((r2 - 128) * actor->radius / 256),
+ mo = P_SpawnMobj(actor->x + ((r2 - 128) * actor->radius / 256),
+ actor->y + ((r1 - 128) * actor->radius / 256),
actor->z + deltaZ, MT_LIGHTNING_ZAP);
if (mo)
{
--- a/src/i_oplmusic.c
+++ b/src/i_oplmusic.c
@@ -101,10 +101,6 @@
typedef struct
{
- // Data for each channel.
-
- opl_channel_data_t channels[MIDI_CHANNELS_PER_TRACK];
-
// Track iterator used to read new events.
midi_track_iter_t *iter;
@@ -149,7 +145,8 @@
unsigned int note_volume;
// The current volume (register value) that has been set for this channel.
- unsigned int reg_volume;
+ unsigned int car_volume;
+ unsigned int mod_volume;
// Pan.
unsigned int reg_pan;
@@ -156,10 +153,6 @@
// Priority.
unsigned int priority;
-
- // Next in linked list; a voice is always either in the
- // free list or the allocated list.
- opl_voice_t *next;
};
// Operators used by the different voices.
@@ -325,12 +318,17 @@
// Voices:
static opl_voice_t voices[OPL_NUM_VOICES * 2];
-static opl_voice_t *voice_free_list;
-static opl_voice_t *voice_alloced_list;
+static opl_voice_t *voice_free_list[OPL_NUM_VOICES * 2];
+static opl_voice_t *voice_alloced_list[OPL_NUM_VOICES * 2];
+static int voice_free_num;
static int voice_alloced_num;
static int opl_opl3mode;
static int num_opl_voices;
+// Data for each channel.
+
+static opl_channel_data_t channels[MIDI_CHANNELS_PER_TRACK];
+
// Track data for playing tracks:
static opl_track_data_t *tracks;
@@ -366,17 +364,10 @@
{
byte *lump;
- lump = W_CacheLumpName("GENMIDI", PU_STATIC);
+ lump = W_CacheLumpName(DEH_String("genmidi"), PU_STATIC);
- // Check header
+ // DMX does not check header
- if (strncmp((char *) lump, GENMIDI_HEADER, strlen(GENMIDI_HEADER)) != 0)
- {
- W_ReleaseLumpName("GENMIDI");
-
- return false;
- }
-
main_instrs = (genmidi_instr_t *) (lump + strlen(GENMIDI_HEADER));
percussion_instrs = main_instrs + GENMIDI_NUM_INSTRS;
main_instr_names =
@@ -391,11 +382,11 @@
static opl_voice_t *GetFreeVoice(void)
{
opl_voice_t *result;
- opl_voice_t **rover;
+ int i;
// None available?
- if (voice_free_list == NULL)
+ if (voice_free_num == 0)
{
return NULL;
}
@@ -402,86 +393,66 @@
// Remove from free list
- result = voice_free_list;
- voice_free_list = voice_free_list->next;
+ result = voice_free_list[0];
- // Add to allocated list
+ voice_free_num--;
- rover = &voice_alloced_list;
-
- while (*rover != NULL)
+ for (i = 0; i < voice_free_num; i++)
{
- rover = &(*rover)->next;
+ voice_free_list[i] = voice_free_list[i + 1];
}
- *rover = result;
- result->next = NULL;
+ // Add to allocated list
- voice_alloced_num++;
+ voice_alloced_list[voice_alloced_num++] = result;
return result;
}
-// Remove a voice from the allocated voices list.
+// Release a voice back to the freelist.
-static void RemoveVoiceFromAllocedList(opl_voice_t *voice)
+static void VoiceKeyOff(opl_voice_t *voice);
+
+static void ReleaseVoice(int index)
{
- opl_voice_t **rover;
+ opl_voice_t *voice;
+ boolean double_voice;
+ int i;
- rover = &voice_alloced_list;
-
- // Search the list until we find the voice, then remove it.
-
- while (*rover != NULL)
+ // Doom 2 1.666 OPL crash emulation.
+ if (index >= voice_alloced_num)
{
- if (*rover == voice)
- {
- *rover = voice->next;
- voice->next = NULL;
- voice_alloced_num--;
- break;
- }
- rover = &(*rover)->next;
+ voice_alloced_num = 0;
+ voice_free_num = 0;
+ return;
}
-}
-// Release a voice back to the freelist.
+ voice = voice_alloced_list[index];
-static void VoiceKeyOff(opl_voice_t *voice);
+ VoiceKeyOff(voice);
-static void ReleaseVoice(opl_voice_t *voice)
-{
- opl_voice_t **rover;
- opl_voice_t *next;
- boolean double_voice;
-
voice->channel = NULL;
voice->note = 0;
double_voice = voice->current_instr_voice != 0;
- next = voice->next;
-
+
// Remove from alloced list.
- RemoveVoiceFromAllocedList(voice);
+ voice_alloced_num--;
- // Search to the end of the freelist (This is how Doom behaves!)
-
- rover = &voice_free_list;
-
- while (*rover != NULL)
+ for (i = index; i < voice_alloced_num; i++)
{
- rover = &(*rover)->next;
+ voice_alloced_list[i] = voice_alloced_list[i + 1];
}
- *rover = voice;
- voice->next = NULL;
+ // Search to the end of the freelist (This is how Doom behaves!)
- if (next != NULL && double_voice && opl_drv_ver != opl_doom_1_9)
+ voice_free_list[voice_free_num++] = voice;
+
+ if (double_voice && opl_drv_ver < opl_doom_1_9)
{
- VoiceKeyOff(next);
- ReleaseVoice(next);
+ ReleaseVoice(index);
}
}
@@ -488,7 +459,7 @@
// Load data to the specified operator
static void LoadOperatorData(int operator, genmidi_op_t *data,
- boolean max_level)
+ boolean max_level, unsigned int *volume)
{
int level;
@@ -495,13 +466,19 @@
// The scale and level fields must be combined for the level register.
// For the carrier wave we always set the maximum level.
- level = (data->scale & 0xc0) | (data->level & 0x3f);
+ level = data->scale;
if (max_level)
{
level |= 0x3f;
}
+ else
+ {
+ level |= data->level;
+ }
+ *volume = level;
+
OPL_WriteRegister(OPL_REGS_LEVEL + operator, level);
OPL_WriteRegister(OPL_REGS_TREMOLO + operator, data->tremolo);
OPL_WriteRegister(OPL_REGS_ATTACK + operator, data->attack);
@@ -540,8 +517,10 @@
// is set in SetVoiceVolume (below). If we are not using
// modulating mode, we must set both to minimum volume.
- LoadOperatorData(voice->op2 | voice->array, &data->carrier, true);
- LoadOperatorData(voice->op1 | voice->array, &data->modulator, !modulating);
+ LoadOperatorData(voice->op2 | voice->array, &data->carrier, true,
+ &voice->car_volume);
+ LoadOperatorData(voice->op1 | voice->array, &data->modulator, !modulating,
+ &voice->mod_volume);
// Set feedback register that control the connection between the
// two operators. Turn on bits in the upper nybble; I think this
@@ -550,10 +529,6 @@
OPL_WriteRegister((OPL_REGS_FEEDBACK + voice->index) | voice->array,
data->feedback | voice->reg_pan);
- // Hack to force a volume update.
-
- voice->reg_volume = 999;
-
// Calculate voice priority.
voice->priority = 0x0f - (data->carrier.attack >> 4)
@@ -584,12 +559,12 @@
// Update the volume register(s) if necessary.
- if (car_volume != voice->reg_volume)
+ if (car_volume != (voice->car_volume & 0x3f))
{
- voice->reg_volume = car_volume | (opl_voice->carrier.scale & 0xc0);
+ voice->car_volume = car_volume | (voice->car_volume & 0xc0);
OPL_WriteRegister((OPL_REGS_LEVEL + voice->op2) | voice->array,
- voice->reg_volume);
+ voice->car_volume);
// If we are using non-modulated feedback mode, we must set the
// volume for both voices.
@@ -597,14 +572,21 @@
if ((opl_voice->feedback & 0x01) != 0
&& opl_voice->modulator.level != 0x3f)
{
- mod_volume = 0x3f - opl_voice->modulator.level;
- if (mod_volume >= car_volume)
+ mod_volume = opl_voice->modulator.level;
+ if (mod_volume < car_volume)
{
mod_volume = car_volume;
}
- OPL_WriteRegister((OPL_REGS_LEVEL + voice->op1) | voice->array,
- mod_volume |
- (opl_voice->modulator.scale & 0xc0));
+
+ mod_volume |= voice->mod_volume & 0xc0;
+
+ if(mod_volume != voice->mod_volume)
+ {
+ voice->mod_volume = mod_volume;
+ OPL_WriteRegister((OPL_REGS_LEVEL + voice->op1) | voice->array,
+ mod_volume |
+ (opl_voice->modulator.scale & 0xc0));
+ }
}
}
}
@@ -627,9 +609,10 @@
int i;
// Start with an empty free list.
+
+ voice_free_num = num_opl_voices;
+ voice_alloced_num = 0;
- voice_free_list = NULL;
-
// Initialize each voice.
for (i = 0; i < num_opl_voices; ++i)
@@ -642,7 +625,7 @@
// Add this voice to the freelist.
- ReleaseVoice(&voices[i]);
+ voice_free_list[i] = &voices[i];
}
}
@@ -653,7 +636,7 @@
static void I_OPL_SetMusicVolume(int volume)
{
- unsigned int i, j;
+ unsigned int i;
if (current_music_volume == volume)
{
@@ -666,20 +649,16 @@
// Update the volume of all voices.
- for (i = 0; i < num_tracks; ++i)
+ for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i)
{
- for (j = 0; j < MIDI_CHANNELS_PER_TRACK; ++j)
+ if (i == 15)
{
- if (j == 15)
- {
- SetChannelVolume(&tracks[i].channels[j], volume, false);
- }
- else
- {
- SetChannelVolume(&tracks[i].channels[j],
- tracks[i].channels[j].volume_base, false);
- }
+ SetChannelVolume(&channels[i], volume, false);
}
+ else
+ {
+ SetChannelVolume(&channels[i], channels[i].volume_base, false);
+ }
}
}
@@ -706,7 +685,7 @@
channel_num = 9;
}
- return &track->channels[channel_num];
+ return &channels[channel_num];
}
// Get the frequency that we should be using for a voice.
@@ -714,8 +693,7 @@
static void KeyOffEvent(opl_track_data_t *track, midi_event_t *event)
{
opl_channel_data_t *channel;
- opl_voice_t *rover;
- opl_voice_t *prev;
+ int i;
unsigned int key;
/*
@@ -731,32 +709,17 @@
// Turn off voices being used to play this key.
// If it is a double voice instrument there will be two.
- rover = voice_alloced_list;
- prev = NULL;
-
- while (rover != NULL)
+ for (i = 0; i < voice_alloced_num; i++)
{
- if (rover->channel == channel && rover->key == key)
+ if (voice_alloced_list[i]->channel == channel
+ && voice_alloced_list[i]->key == key)
{
- VoiceKeyOff(rover);
-
// Finished with this voice now.
- ReleaseVoice(rover);
- if (prev == NULL)
- {
- rover = voice_alloced_list;
- }
- else
- {
- rover = prev->next;
- }
+ ReleaseVoice(i);
+
+ i--;
}
- else
- {
- prev = rover;
- rover = rover->next;
- }
}
}
@@ -767,8 +730,8 @@
static void ReplaceExistingVoice(void)
{
- opl_voice_t *rover;
- opl_voice_t *result;
+ int i;
+ int result;
// Check the allocated voices, if we find an instrument that is
// of a lower priority to the new instrument, discard it.
@@ -778,18 +741,18 @@
// than higher-numbered channels, eg. MIDI channel 1 is never
// discarded for MIDI channel 2.
- result = voice_alloced_list;
+ result = 0;
- for (rover = voice_alloced_list; rover != NULL; rover = rover->next)
+ for (i = 0; i < voice_alloced_num; i++)
{
- if (rover->current_instr_voice != 0
- || rover->channel >= result->channel)
+ if (voice_alloced_list[i]->current_instr_voice != 0
+ || voice_alloced_list[i]->channel
+ >= voice_alloced_list[result]->channel)
{
- result = rover;
+ result = i;
}
}
- VoiceKeyOff(result);
ReleaseVoice(result);
}
@@ -798,53 +761,43 @@
static void ReplaceExistingVoiceDoom1(void)
{
- opl_voice_t *rover;
- opl_voice_t *result;
+ int i;
+ int result;
- result = voice_alloced_list;
+ result = 0;
- for (rover = voice_alloced_list; rover != NULL; rover = rover->next)
+ for (i = 0; i < voice_alloced_num; i++)
{
- if (rover->channel > result->channel)
+ if (voice_alloced_list[i]->channel
+ > voice_alloced_list[result]->channel)
{
- result = rover;
+ result = i;
}
}
- VoiceKeyOff(result);
ReleaseVoice(result);
}
static void ReplaceExistingVoiceDoom2(opl_channel_data_t *channel)
{
- opl_voice_t *rover;
- opl_voice_t *result;
- opl_voice_t *roverend;
int i;
+ int result;
int priority;
- result = voice_alloced_list;
+ result = 0;
- roverend = voice_alloced_list;
+ priority = 0x8000;
for (i = 0; i < voice_alloced_num - 3; i++)
{
- roverend = roverend->next;
- }
-
- priority = 0x8000;
-
- for (rover = voice_alloced_list; rover != roverend; rover = rover->next)
- {
- if (rover->priority < priority
- && rover->channel >= channel)
+ if (voice_alloced_list[i]->priority < priority
+ && voice_alloced_list[i]->channel >= channel)
{
- priority = rover->priority;
- result = rover;
+ priority = voice_alloced_list[i]->priority;
+ result = i;
}
}
- VoiceKeyOff(result);
ReleaseVoice(result);
}
@@ -1101,7 +1054,7 @@
break;
default:
case opl_doom_1_9:
- if (voice_free_list == NULL)
+ if (voice_free_num == 0)
{
ReplaceExistingVoice();
}
@@ -1210,35 +1163,18 @@
// Handler for the MIDI_CONTROLLER_ALL_NOTES_OFF channel event.
static void AllNotesOff(opl_channel_data_t *channel, unsigned int param)
{
- opl_voice_t *rover;
- opl_voice_t *prev;
+ int i;
- rover = voice_alloced_list;
- prev = NULL;
-
- while (rover!=NULL)
+ for (i = 0; i < voice_alloced_num; i++)
{
- if (rover->channel == channel)
+ if (voice_alloced_list[i]->channel == channel)
{
- VoiceKeyOff(rover);
-
// Finished with this voice now.
- ReleaseVoice(rover);
- if (prev == NULL)
- {
- rover = voice_alloced_list;
- }
- else
- {
- rover = prev->next;
- }
+ ReleaseVoice(i);
+
+ i--;
}
- else
- {
- prev = rover;
- rover = rover->next;
- }
}
}
@@ -1286,7 +1222,11 @@
static void PitchBendEvent(opl_track_data_t *track, midi_event_t *event)
{
opl_channel_data_t *channel;
- unsigned int i;
+ int i;
+ opl_voice_t *voice_updated_list[OPL_NUM_VOICES * 2];
+ unsigned int voice_updated_num = 0;
+ opl_voice_t *voice_not_updated_list[OPL_NUM_VOICES * 2];
+ unsigned int voice_not_updated_num = 0;
// Update the channel bend value. Only the MSB of the pitch bend
// value is considered: this is what Doom does.
@@ -1296,13 +1236,29 @@
// Update all voices for this channel.
- for (i = 0; i < num_opl_voices; ++i)
+ for (i = 0; i < voice_alloced_num; ++i)
{
- if (voices[i].channel == channel)
+ if (voice_alloced_list[i]->channel == channel)
{
- UpdateVoiceFrequency(&voices[i]);
+ UpdateVoiceFrequency(voice_alloced_list[i]);
+ voice_updated_list[voice_updated_num++] = voice_alloced_list[i];
}
+ else
+ {
+ voice_not_updated_list[voice_not_updated_num++] =
+ voice_alloced_list[i];
+ }
}
+
+ for (i = 0; i < voice_not_updated_num; i++)
+ {
+ voice_alloced_list[i] = voice_not_updated_list[i];
+ }
+
+ for (i = 0; i < voice_updated_num; i++)
+ {
+ voice_alloced_list[i + voice_not_updated_num] = voice_updated_list[i];
+ }
}
static void MetaSetTempo(unsigned int tempo)
@@ -1400,13 +1356,13 @@
}
static void ScheduleTrack(opl_track_data_t *track);
-static void InitChannel(opl_track_data_t *track, opl_channel_data_t *channel);
+static void InitChannel(opl_channel_data_t *channel);
// Restart a song from the beginning.
static void RestartSong(void *unused)
{
- unsigned int i, j;
+ unsigned int i;
running_tracks = num_tracks;
@@ -1416,11 +1372,12 @@
{
MIDI_RestartIterator(tracks[i].iter);
ScheduleTrack(&tracks[i]);
- for (j = 0; j < MIDI_CHANNELS_PER_TRACK; ++j)
- {
- InitChannel(&tracks[i], &tracks[i].channels[j]);
- }
}
+
+ for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i)
+ {
+ InitChannel(&channels[i]);
+ }
}
// Callback function invoked when another event needs to be read from
@@ -1485,7 +1442,7 @@
// Initialize a channel.
-static void InitChannel(opl_track_data_t *track, opl_channel_data_t *channel)
+static void InitChannel(opl_channel_data_t *channel)
{
// TODO: Work out sensible defaults?
@@ -1505,16 +1462,10 @@
static void StartTrack(midi_file_t *file, unsigned int track_num)
{
opl_track_data_t *track;
- unsigned int i;
track = &tracks[track_num];
track->iter = MIDI_IterateTrack(file, track_num);
- for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i)
- {
- InitChannel(track, &track->channels[i]);
- }
-
// Schedule the first event.
ScheduleTrack(track);
@@ -1555,6 +1506,11 @@
{
StartTrack(file, i);
}
+
+ for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i)
+ {
+ InitChannel(&channels[i]);
+ }
}
static void I_OPL_PauseSong(void)
@@ -1610,13 +1566,9 @@
// Free all voices.
- for (i = 0; i < num_opl_voices; ++i)
+ for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i)
{
- if (voices[i].channel != NULL)
- {
- VoiceKeyOff(&voices[i]);
- ReleaseVoice(&voices[i]);
- }
+ AllNotesOff(&channels[i], 0);
}
// Free all track data.
@@ -1747,7 +1699,7 @@
// Release GENMIDI lump
- W_ReleaseLumpName("GENMIDI");
+ W_ReleaseLumpName(DEH_String("genmidi"));
music_initialized = false;
}
@@ -1854,7 +1806,7 @@
for (i = MIDI_CHANNELS_PER_TRACK - 1; i >= 0; --i)
{
- if (tracks[0].channels[i].instrument != &main_instrs[0])
+ if (channels[i].instrument != &main_instrs[0])
{
return i + 1;
}
@@ -1865,11 +1817,11 @@
static int ChannelInUse(opl_channel_data_t *channel)
{
- opl_voice_t *voice;
+ int i;
- for (voice = voice_alloced_list; voice != NULL; voice = voice->next)
+ for (i = 0; i < voice_alloced_num; i++)
{
- if (voice->channel == channel)
+ if (voice_alloced_list[i]->channel == channel)
{
return 1;
}
@@ -1896,17 +1848,17 @@
for (i = 0; i < NumActiveChannels(); ++i)
{
- if (tracks[0].channels[i].instrument == NULL)
+ if (channels[i].instrument == NULL)
{
continue;
}
- instr_num = tracks[0].channels[i].instrument - main_instrs;
+ instr_num = channels[i].instrument - main_instrs;
M_snprintf(tmp, sizeof(tmp),
"chan %i: %c i#%i (%s)\n",
i,
- ChannelInUse(&tracks[0].channels[i]) ? '\'' : ' ',
+ ChannelInUse(&channels[i]) ? '\'' : ' ',
instr_num + 1,
main_instr_names[instr_num]);
M_StringConcat(result, tmp, result_len);