foxygit / doom Log in
commit 4a00203152591556f2ba271a446b918b3ea3e172
Author:     Nuke.YKT <alexeytf2@gmail.com>
AuthorDate: Fri Jul 17 12:28:22 2015 +0900
Commit:     Nuke.YKT <alexeytf2@gmail.com>
CommitDate: Fri Jul 17 12:28:22 2015 +0900

    Doom v1.666, 1.7, 1.8 support.
---
 src/d_mode.c          |   1 +
 src/doom/d_main.c     |  70 ++++++++++++++++++++++-------
 src/doom/m_menu.c     |   5 ++-
 src/doom/s_sound.c    |  17 +++++++-
 src/doom/st_stuff.c   |   3 +-
 src/heretic/s_sound.c |   2 +-
 src/hexen/s_sound.c   |   2 +-
 src/i_oplmusic.c      | 119 +++++++++++++++++++++++++++++++++++---------------
 src/i_sound.h         |   5 ++-
 src/strife/s_sound.c  |   2 +-
 10 files changed, 166 insertions(+), 60 deletions(-)

diff --git a/src/d_mode.c b/src/d_mode.c
index afd84acb..16331c38 100644
--- a/src/d_mode.c
+++ b/src/d_mode.c
@@ -120,6 +120,7 @@ static struct {
     GameMission_t mission;
     GameVersion_t version;
 } valid_versions[] = {
+    { doom,     exe_doom_1_666 },
     { doom,     exe_doom_1_9 },
     { doom,     exe_hacx },
     { doom,     exe_ultimate },
diff --git a/src/doom/d_main.c b/src/doom/d_main.c
index bcdfcaa3..50be07c2 100644
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -607,6 +607,10 @@ static char *banners[] =
     "                         "
     "DOOM 2: Hell on Earth v%i.%i"
     "                           ",
+    // doom2.wad v1.666
+    "                         "
+    "DOOM 2: Hell on Earth v%i.%i66"
+    "                          ",
     // doom1.wad
     "                            "
     "DOOM Shareware Startup v%i.%i"
@@ -619,6 +623,10 @@ static char *banners[] =
     "                          "
     "DOOM System Startup v%i.%i"
     "                          ",
+    // Doom v1.666
+    "                          "
+    "DOOM System Startup v%i.%i66"
+    "                          "
     // doom.wad (Ultimate DOOM)
     "                         "
     "The Ultimate DOOM Startup v%i.%i"
@@ -945,8 +953,12 @@ static struct

 static void InitGameVersion(void)
 {
+    byte *demolump;
+    byte demolumpname[6];
+    int demoversion;
     int p;
     int i;
+    boolean status;

     //!
     // @arg <version>
@@ -998,13 +1010,46 @@ static void InitGameVersion(void)

             gameversion = exe_hacx;
         }
-        else if (gamemode == shareware || gamemode == registered)
+        else if (gamemode == shareware || gamemode == registered
+              || (gamemode == commercial && gamemission == doom2))
         {
             // original
-
             gameversion = exe_doom_1_9;

-            // TODO: Detect IWADs earlier than Doom v1.9.
+            // Detect version from demo lump
+            for (i = 1; i <= 3; ++i)
+            {
+                M_snprintf(demolumpname, 6, "demo%i", i);
+                if (W_CheckNumForName(demolumpname) > 0)
+                {
+                    demolump = W_CacheLumpName(demolumpname, PU_STATIC);
+                    demoversion = demolump[0];
+                    W_ReleaseLumpName(demolumpname);
+                    status = true;
+                    switch (demoversion)
+                    {
+                        case 106:
+                            gameversion = exe_doom_1_666;
+                            break;
+                        case 107:
+                            gameversion = exe_doom_1_7;
+                            break;
+                        case 108:
+                            gameversion = exe_doom_1_8;
+                            break;
+                        case 109:
+                            gameversion = exe_doom_1_9;
+                            break;
+                        default:
+                            status = false;
+                            break;
+                    }
+                    if (status)
+                    {
+                        break;
+                    }
+                }
+            }
         }
         else if (gamemode == retail)
         {
@@ -1012,20 +1057,13 @@ static void InitGameVersion(void)
         }
         else if (gamemode == commercial)
         {
-            if (gamemission == doom2)
-            {
-                gameversion = exe_doom_1_9;
-            }
-            else
-            {
-                // Final Doom: tnt or plutonia
-                // Defaults to emulating the first Final Doom executable,
-                // which has the crash in the demo loop; however, having
-                // this as the default should mean that it plays back
-                // most demos correctly.
+            // Final Doom: tnt or plutonia
+            // Defaults to emulating the first Final Doom executable,
+            // which has the crash in the demo loop; however, having
+            // this as the default should mean that it plays back
+            // most demos correctly.

-                gameversion = exe_final;
-            }
+            gameversion = exe_final;
         }
     }

diff --git a/src/doom/m_menu.c b/src/doom/m_menu.c
index 9a166a43..db40937f 100644
--- a/src/doom/m_menu.c
+++ b/src/doom/m_menu.c
@@ -751,6 +751,9 @@ void M_DrawReadThis1(void)

     switch (gameversion)
     {
+        case exe_doom_1_666:
+        case exe_doom_1_7:
+        case exe_doom_1_8:
         case exe_doom_1_9:
         case exe_hacx:

@@ -1074,7 +1077,7 @@ void M_ReadThis2(int choice)
     // Doom 1.9 had two menus when playing Doom 1
     // All others had only one

-    if (gameversion == exe_doom_1_9 && gamemode != commercial)
+    if (gameversion <= exe_doom_1_9 && gamemode != commercial)
     {
         choice = 0;
         M_SetupNextMenu(&ReadDef2);
diff --git a/src/doom/s_sound.c b/src/doom/s_sound.c
index 4263e631..4f48a3e2 100644
--- a/src/doom/s_sound.c
+++ b/src/doom/s_sound.c
@@ -116,7 +116,22 @@ void S_Init(int sfxVolume, int musicVolume)
 {
     int i;

-    I_SetOPLDriverVer(opl_v_new);
+    if (gameversion == exe_doom_1_666)
+    {
+        if (logical_gamemission == doom)
+        {
+            I_SetOPLDriverVer(opl_doom1_1_666);
+        }
+        else
+        {
+            I_SetOPLDriverVer(opl_doom2_1_666);
+        }
+    }
+    else
+    {
+        I_SetOPLDriverVer(opl_doom_1_9);
+    }
+
     I_PrecacheSounds(S_sfx, NUMSFX);

     S_SetSfxVolume(sfxVolume);
diff --git a/src/doom/st_stuff.c b/src/doom/st_stuff.c
index 693b6ef2..e00d1edc 100644
--- a/src/doom/st_stuff.c
+++ b/src/doom/st_stuff.c
@@ -528,7 +528,8 @@ ST_Responder (event_t* ev)
 	{
 	  musnum = mus_runnin + (buf[0]-'0')*10 + buf[1]-'0' - 1;

-	  if (((buf[0]-'0')*10 + buf[1]-'0') > 35)
+	  if (((buf[0]-'0')*10 + buf[1]-'0') > 35
+       && gameversion >= exe_doom_1_8)
 	    plyr->message = DEH_String(STSTR_NOMUS);
 	  else
 	    S_ChangeMusic(musnum, 1);
diff --git a/src/heretic/s_sound.c b/src/heretic/s_sound.c
index b4a026c0..82927891 100644
--- a/src/heretic/s_sound.c
+++ b/src/heretic/s_sound.c
@@ -513,7 +513,7 @@ void S_UpdateSounds(mobj_t * listener)

 void S_Init(void)
 {
-    I_SetOPLDriverVer(opl_v_old);
+    I_SetOPLDriverVer(opl_doom2_1_666);
     soundCurve = Z_Malloc(MAX_SND_DIST, PU_STATIC, NULL);
     if (snd_Channels > 8)
     {
diff --git a/src/hexen/s_sound.c b/src/hexen/s_sound.c
index 947b3bfd..bd16d107 100644
--- a/src/hexen/s_sound.c
+++ b/src/hexen/s_sound.c
@@ -787,7 +787,7 @@ void S_UpdateSounds(mobj_t * listener)

 void S_Init(void)
 {
-    I_SetOPLDriverVer(opl_v_old);
+    I_SetOPLDriverVer(opl_doom2_1_666);
     SoundCurve = W_CacheLumpName("SNDCURVE", PU_STATIC);
 //      SoundCurve = Z_Malloc(MAX_SND_DIST, PU_STATIC, NULL);

diff --git a/src/i_oplmusic.c b/src/i_oplmusic.c
index 239c9794..33685a5f 100644
--- a/src/i_oplmusic.c
+++ b/src/i_oplmusic.c
@@ -307,7 +307,7 @@ static const unsigned int volume_mapping_table[] = {
     124, 124, 125, 125, 126, 126, 127, 127
 };

-static opl_driver_ver_t opl_drv_ver = opl_v_new;
+static opl_driver_ver_t opl_drv_ver = opl_doom_1_9;
 static boolean music_initialized = false;

 //static boolean musicpaused = false;
@@ -470,7 +470,7 @@ static void ReleaseVoice(opl_voice_t *voice)
     *rover = voice;
     voice->next = NULL;

-    if (next != NULL && double_voice && opl_drv_ver == opl_v_old)
+    if (next != NULL && double_voice && opl_drv_ver != opl_doom_1_9)
     {
         VoiceKeyOff(next);
         ReleaseVoice(next);
@@ -770,10 +770,29 @@ static void ReplaceExistingVoice(void)
     ReleaseVoice(result);
 }

-// Alternate version of ReplaceExistingVoice() used when emulating old
-// versions of the DMX library used in Heretic and Hexen.
+// Alternate versions of ReplaceExistingVoice() used when emulating old
+// versions of the DMX library used in Doom 1.666, Heretic and Hexen.

-static void ReplaceExistingVoiceOld(opl_channel_data_t *channel)
+static void ReplaceExistingVoiceDoom1(void)
+{
+    opl_voice_t *rover;
+    opl_voice_t *result;
+
+    result = voice_alloced_list;
+
+    for (rover = voice_alloced_list; rover != NULL; rover = rover->next)
+    {
+        if (rover->channel > result->channel)
+        {
+            result = rover;
+        }
+    }
+
+    VoiceKeyOff(result);
+    ReleaseVoice(result);
+}
+
+static void ReplaceExistingVoiceDoom2(opl_channel_data_t *channel)
 {
     opl_voice_t *rover;
     opl_voice_t *result;
@@ -918,6 +937,11 @@ static void VoiceKeyOn(opl_channel_data_t *channel,
 {
     opl_voice_t *voice;

+    if (!opl_opl3mode && opl_drv_ver == opl_doom1_1_666)
+    {
+        instrument_voice = 0;
+    }
+
     // Find a voice to use for this new note.

     voice = GetFreeVoice();
@@ -962,7 +986,7 @@ static void KeyOnEvent(opl_track_data_t *track, midi_event_t *event)
 {
     genmidi_instr_t *instrument;
     opl_channel_data_t *channel;
-    unsigned int note, key, volume;
+    unsigned int note, key, volume, voicenum;
     boolean double_voice;

 /*
@@ -1009,43 +1033,66 @@ static void KeyOnEvent(opl_track_data_t *track, midi_event_t *event)

     double_voice = (SHORT(instrument->flags) & GENMIDI_FLAG_2VOICE) != 0;

-    if (opl_drv_ver == opl_v_old)
+    switch (opl_drv_ver)
     {
-        if (voice_alloced_num == num_opl_voices)
-        {
-            ReplaceExistingVoiceOld(channel);
-        }
-        if (voice_alloced_num == num_opl_voices - 1 && double_voice)
-        {
-            ReplaceExistingVoiceOld(channel);
-        }
+        case opl_doom1_1_666:
+            voicenum = double_voice + 1;
+            if (!opl_opl3mode)
+            {
+                voicenum = 1;
+            }
+            while (voice_alloced_num > num_opl_voices - voicenum)
+            {
+                ReplaceExistingVoiceDoom1();
+            }

-        // Find and program a voice for this instrument.  If this
-        // is a double voice instrument, we must do this twice.
+            // Find and program a voice for this instrument.  If this
+            // is a double voice instrument, we must do this twice.

-        if (double_voice)
-        {
-            VoiceKeyOn(channel, instrument, 1, note, key, volume);
-        }
+            if (double_voice)
+            {
+                VoiceKeyOn(channel, instrument, 1, note, key, volume);
+            }

-        VoiceKeyOn(channel, instrument, 0, note, key, volume);
-    }
-    else
-    {
-        if (voice_free_list == NULL)
-        {
-            ReplaceExistingVoice();
-        }
+            VoiceKeyOn(channel, instrument, 0, note, key, volume);
+            break;
+        case opl_doom2_1_666:
+            if (voice_alloced_num == num_opl_voices)
+            {
+                ReplaceExistingVoiceDoom2(channel);
+            }
+            if (voice_alloced_num == num_opl_voices - 1 && double_voice)
+            {
+                ReplaceExistingVoiceDoom2(channel);
+            }

-        // Find and program a voice for this instrument.  If this
-        // is a double voice instrument, we must do this twice.
+            // Find and program a voice for this instrument.  If this
+            // is a double voice instrument, we must do this twice.

-        VoiceKeyOn(channel, instrument, 0, note, key, volume);
+            if (double_voice)
+            {
+                VoiceKeyOn(channel, instrument, 1, note, key, volume);
+            }

-        if (double_voice)
-        {
-            VoiceKeyOn(channel, instrument, 1, note, key, volume);
-        }
+            VoiceKeyOn(channel, instrument, 0, note, key, volume);
+            break;
+        default:
+        case opl_doom_1_9:
+            if (voice_free_list == NULL)
+            {
+                ReplaceExistingVoice();
+            }
+
+            // Find and program a voice for this instrument.  If this
+            // is a double voice instrument, we must do this twice.
+
+            VoiceKeyOn(channel, instrument, 0, note, key, volume);
+
+            if (double_voice)
+            {
+                VoiceKeyOn(channel, instrument, 1, note, key, volume);
+            }
+            break;
     }
 }

diff --git a/src/i_sound.h b/src/i_sound.h
index d1d4f407..f984c8f6 100644
--- a/src/i_sound.h
+++ b/src/i_sound.h
@@ -239,8 +239,9 @@ void I_BindSoundVariables(void);

 // DMX version to emulate for OPL emulation:
 typedef enum {
-    opl_v_old,   // Hexen, Heretic
-    opl_v_new    // Doom, Strife
+    opl_doom1_1_666,    // Doom 1 v1.666
+    opl_doom2_1_666,    // Doom 2 v1.666, Hexen, Heretic
+    opl_doom_1_9        // Doom v1.9, Strife
 } opl_driver_ver_t;

 void I_SetOPLDriverVer(opl_driver_ver_t ver);
diff --git a/src/strife/s_sound.c b/src/strife/s_sound.c
index b0008d67..f7beaace 100644
--- a/src/strife/s_sound.c
+++ b/src/strife/s_sound.c
@@ -138,7 +138,7 @@ void S_Init(int sfxVolume, int musicVolume, int voiceVolume)
 {
     int i;

-    I_SetOPLDriverVer(opl_v_new);
+    I_SetOPLDriverVer(opl_doom_1_9);
     I_PrecacheSounds(S_sfx, NUMSFX);

     S_SetSfxVolume(sfxVolume);