aboutsummaryrefslogtreecommitdiff
path: root/engines/parallaction
diff options
context:
space:
mode:
Diffstat (limited to 'engines/parallaction')
-rw-r--r--engines/parallaction/adlib.cpp808
-rw-r--r--engines/parallaction/callables_ns.cpp12
-rw-r--r--engines/parallaction/debug.cpp8
-rw-r--r--engines/parallaction/dialogue.cpp8
-rw-r--r--engines/parallaction/disk_br.cpp4
-rw-r--r--engines/parallaction/disk_ns.cpp11
-rw-r--r--engines/parallaction/exec.cpp6
-rw-r--r--engines/parallaction/exec_br.cpp8
-rw-r--r--engines/parallaction/exec_ns.cpp8
-rw-r--r--engines/parallaction/font.cpp4
-rw-r--r--engines/parallaction/gfxbase.cpp13
-rw-r--r--engines/parallaction/graphics.cpp4
-rw-r--r--engines/parallaction/graphics.h4
-rw-r--r--engines/parallaction/gui_ns.cpp2
-rw-r--r--engines/parallaction/input.cpp22
-rw-r--r--engines/parallaction/module.mk1
-rw-r--r--engines/parallaction/objects.cpp4
-rw-r--r--engines/parallaction/parallaction.cpp32
-rw-r--r--engines/parallaction/parallaction.h24
-rw-r--r--engines/parallaction/parallaction_br.cpp14
-rw-r--r--engines/parallaction/parallaction_ns.cpp20
-rw-r--r--engines/parallaction/parser_br.cpp4
-rw-r--r--engines/parallaction/parser_ns.cpp2
-rw-r--r--engines/parallaction/saveload.cpp6
-rw-r--r--engines/parallaction/sound.h2
-rw-r--r--engines/parallaction/sound_br.cpp34
-rw-r--r--engines/parallaction/sound_ns.cpp6
-rw-r--r--engines/parallaction/staticres.cpp28
-rw-r--r--engines/parallaction/walk.cpp28
-rw-r--r--engines/parallaction/walk.h8
30 files changed, 985 insertions, 150 deletions
diff --git a/engines/parallaction/adlib.cpp b/engines/parallaction/adlib.cpp
new file mode 100644
index 0000000000..134e5cfbf3
--- /dev/null
+++ b/engines/parallaction/adlib.cpp
@@ -0,0 +1,808 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/debug.h"
+#include "common/system.h"
+
+#include "audio/fmopl.h"
+#include "audio/mpu401.h"
+#include "audio/softsynth/emumidi.h"
+
+namespace Parallaction {
+
+const uint kNumVoices = 9;
+// adlib FM voices 0-5
+const uint kNumMelodic = 6;
+// adlib FM voice 6 and 7-8
+const uint kNumPercussion = 5;
+
+// mask for maximum volume level
+#define LEVEL_MASK 0x7f
+
+struct OPLOperator {
+ uint8 characteristic; // amplitude modulation, vibrato, envelope, keyboard scaling, modulator frequency
+ uint8 levels;
+ uint8 attackDecay;
+ uint8 sustainRelease;
+ uint8 waveform;
+};
+
+struct MelodicProgram {
+ OPLOperator op[2];
+ uint8 feedbackAlgo;
+};
+
+struct PercussionNote {
+ OPLOperator op[2];
+ uint8 feedbackAlgo;
+ uint8 percussion;
+ uint8 valid;
+ uint16 frequency;
+ uint8 octave;
+};
+
+static const MelodicProgram melodicPrograms[128] = {
+ {{{ 0x1, 0x51, 0xf2, 0xb2, 0x0 }, { 0x11, 0x0, 0xf2, 0xa2, 0x0 }}, 0x0 },
+ {{{ 0xc2, 0x4b, 0xf1, 0x53, 0x0 }, { 0xd2, 0x0, 0xf2, 0x74, 0x0 }}, 0x4 },
+ {{{ 0x81, 0x9d, 0xf2, 0x74, 0x0 }, { 0x13, 0x0, 0xf2, 0xf1, 0x0 }}, 0x6 },
+ {{{ 0x3, 0x4f, 0xf1, 0x53, 0x0 }, { 0x17, 0x3, 0xf2, 0x74, 0x0 }}, 0x6 },
+ {{{ 0xd1, 0x81, 0x81, 0x73, 0x2 }, { 0xd4, 0x0, 0xe1, 0x34, 0x0 }}, 0x3 },
+ {{{ 0x1, 0x0, 0x94, 0xa6, 0x0 }, { 0x2, 0x0, 0x83, 0x26, 0x0 }}, 0x1 },
+ {{{ 0xf3, 0x84, 0x81, 0x2, 0x1 }, { 0x55, 0x80, 0xdd, 0x3, 0x0 }}, 0x4 },
+ {{{ 0x5, 0x8a, 0xf2, 0x26, 0x0 }, { 0x1, 0x80, 0xf3, 0x48, 0x0 }}, 0x0 },
+ {{{ 0x32, 0x0, 0xb1, 0x14, 0x0 }, { 0x12, 0x0, 0xfd, 0x36, 0x0 }}, 0x3 },
+ {{{ 0x1, 0x0, 0x82, 0xa, 0x2 }, { 0x2, 0x0, 0x85, 0x15, 0x0 }}, 0x3 },
+ {{{ 0xd1, 0x1, 0x97, 0xaa, 0x0 }, { 0x4, 0xd, 0xf3, 0xa5, 0x1 }}, 0x9 },
+ {{{ 0x17, 0x0, 0xf2, 0x62, 0x0 }, { 0x12, 0x0, 0xf2, 0x72, 0x0 }}, 0x8 },
+ {{{ 0x6, 0x0, 0xff, 0xf4, 0x0 }, { 0xc4, 0x0, 0xf8, 0xb5, 0x0 }}, 0xe },
+ {{{ 0xc0, 0x81, 0xf2, 0x13, 0x2 }, { 0xc0, 0xc1, 0xf3, 0x14, 0x2 }}, 0xb },
+ {{{ 0x44, 0x53, 0xf5, 0x31, 0x0 }, { 0x60, 0x80, 0xfd, 0x22, 0x0 }}, 0x6 },
+ {{{ 0xe0, 0x80, 0xf4, 0xf2, 0x0 }, { 0x61, 0x0, 0xf2, 0x6, 0x0 }}, 0x8 },
+ {{{ 0xc1, 0x6, 0x83, 0x23, 0x0 }, { 0xc1, 0x4, 0xf0, 0x26, 0x0 }}, 0x1 },
+ {{{ 0x26, 0x0, 0xf4, 0xb6, 0x0 }, { 0x21, 0x0, 0x81, 0x4b, 0x0 }}, 0x1 },
+ {{{ 0x24, 0x80, 0xff, 0xf, 0x0 }, { 0x21, 0x80, 0xff, 0xf, 0x0 }}, 0x1 },
+ {{{ 0x24, 0x4f, 0xf2, 0xb, 0x0 }, { 0x31, 0x0, 0x52, 0xb, 0x0 }}, 0xb },
+ {{{ 0x31, 0x8, 0x81, 0xb, 0x0 }, { 0xa1, 0x80, 0x92, 0x3b, 0x0 }}, 0x0 },
+ {{{ 0x70, 0xc5, 0x52, 0x11, 0x1 }, { 0x71, 0x80, 0x31, 0xfe, 0x1 }}, 0x0 },
+ {{{ 0x51, 0x88, 0x10, 0xf0, 0x0 }, { 0x42, 0x83, 0x40, 0xfc, 0x0 }}, 0x8 },
+ {{{ 0xf0, 0xd9, 0x81, 0x3, 0x0 }, { 0xb1, 0x80, 0xf1, 0x5, 0x0 }}, 0xa },
+ {{{ 0x21, 0x4f, 0xf1, 0x31, 0x0 }, { 0x2, 0x80, 0xc3, 0x45, 0x0 }}, 0x0 },
+ {{{ 0x7, 0x8f, 0x9c, 0x33, 0x1 }, { 0x1, 0x80, 0x8a, 0x13, 0x0 }}, 0x0 },
+ {{{ 0x21, 0x40, 0xf1, 0x31, 0x0 }, { 0x6, 0x80, 0xf4, 0x44, 0x0 }}, 0x0 },
+ {{{ 0x21, 0x40, 0xf1, 0x31, 0x3 }, { 0x81, 0x0, 0xf4, 0x44, 0x2 }}, 0x2 },
+ {{{ 0x11, 0x8d, 0xfd, 0x11, 0x0 }, { 0x11, 0x80, 0xfd, 0x11, 0x0 }}, 0x8 },
+ {{{ 0xf0, 0x1, 0x97, 0x17, 0x0 }, { 0x21, 0xd, 0xf1, 0x18, 0x0 }}, 0x8 },
+ {{{ 0xf1, 0x1, 0x97, 0x17, 0x0 }, { 0x21, 0xd, 0xf1, 0x18, 0x0 }}, 0x8 },
+ {{{ 0xcd, 0x9e, 0x55, 0xd1, 0x0 }, { 0xd1, 0x0, 0xf2, 0x71, 0x0 }}, 0xe },
+ {{{ 0x1, 0x0, 0xf2, 0x88, 0x0 }, { 0x1, 0x0, 0xf5, 0x88, 0x0 }}, 0x1 },
+ {{{ 0x30, 0xd, 0xf2, 0xef, 0x0 }, { 0x21, 0x0, 0xf5, 0x78, 0x0 }}, 0x6 },
+ {{{ 0x0, 0x10, 0xf4, 0xd9, 0x0 }, { 0x0, 0x0, 0xf5, 0xd7, 0x0 }}, 0x4 },
+ {{{ 0x1, 0x4c, 0xf2, 0x50, 0x0 }, { 0x1, 0x40, 0xd2, 0x59, 0x0 }}, 0x8 },
+ {{{ 0x20, 0x11, 0xe2, 0x8a, 0x0 }, { 0x20, 0x0, 0xe4, 0xa8, 0x0 }}, 0xa },
+ {{{ 0x21, 0x40, 0x7b, 0x4, 0x1 }, { 0x21, 0x0, 0x75, 0x72, 0x0 }}, 0x2 },
+ {{{ 0x31, 0xd, 0xf2, 0xef, 0x0 }, { 0x21, 0x0, 0xf5, 0x78, 0x0 }}, 0xa },
+ {{{ 0x1, 0xc, 0xf5, 0x2f, 0x1 }, { 0x0, 0x80, 0xf5, 0x5c, 0x0 }}, 0x0 },
+ {{{ 0xb0, 0x1c, 0x81, 0x3, 0x2 }, { 0x20, 0x0, 0x54, 0x67, 0x2 }}, 0xe },
+ {{{ 0x1, 0x0, 0xf1, 0x65, 0x0 }, { 0x1, 0x80, 0xa3, 0xa8, 0x2 }}, 0x1 },
+ {{{ 0xe1, 0x4f, 0xc1, 0xd3, 0x2 }, { 0x21, 0x0, 0x32, 0x74, 0x1 }}, 0x0 },
+ {{{ 0x2, 0x0, 0xf6, 0x16, 0x0 }, { 0x12, 0x0, 0xf2, 0xf8, 0x0 }}, 0x1 },
+ {{{ 0xe0, 0x63, 0xf8, 0xf3, 0x0 }, { 0x70, 0x80, 0xf7, 0xf3, 0x0 }}, 0x4 },
+ {{{ 0x1, 0x6, 0xf3, 0xff, 0x0 }, { 0x8, 0x0, 0xf7, 0xff, 0x0 }}, 0x4 },
+ {{{ 0x21, 0x16, 0xb0, 0x81, 0x1 }, { 0x22, 0x0, 0xb3, 0x13, 0x1 }}, 0xc },
+ {{{ 0x1, 0x4f, 0xf0, 0xff, 0x0 }, { 0x30, 0x0, 0x90, 0xf, 0x0 }}, 0x6 },
+ {{{ 0x0, 0x10, 0xf1, 0xf2, 0x2 }, { 0x1, 0x0, 0xf1, 0xf2, 0x3 }}, 0x0 },
+ {{{ 0x1, 0x4f, 0xf1, 0x50, 0x0 }, { 0x21, 0x80, 0xa3, 0x5, 0x3 }}, 0x6 },
+ {{{ 0xb1, 0x3, 0x55, 0x3, 0x0 }, { 0xb1, 0x3, 0x8, 0xa, 0x0 }}, 0x9 },
+ {{{ 0x22, 0x0, 0xa9, 0x34, 0x1 }, { 0x1, 0x0, 0xa2, 0x42, 0x2 }}, 0x2 },
+ {{{ 0xa0, 0xdc, 0x81, 0x31, 0x3 }, { 0xb1, 0x80, 0xf1, 0x1, 0x3 }}, 0x0 },
+ {{{ 0x1, 0x4f, 0xf1, 0x50, 0x0 }, { 0x21, 0x80, 0xa3, 0x5, 0x3 }}, 0x6 },
+ {{{ 0xf1, 0x80, 0xa0, 0x72, 0x0 }, { 0x74, 0x0, 0x90, 0x22, 0x0 }}, 0x9 },
+ {{{ 0xe1, 0x13, 0x71, 0xae, 0x0 }, { 0xe1, 0x0, 0xf0, 0xfc, 0x1 }}, 0xa },
+ {{{ 0x31, 0x1c, 0x41, 0xb, 0x0 }, { 0xa1, 0x80, 0x92, 0x3b, 0x0 }}, 0xe },
+ {{{ 0x71, 0x1c, 0x41, 0x1f, 0x0 }, { 0xa1, 0x80, 0x92, 0x3b, 0x0 }}, 0xe },
+ {{{ 0x21, 0x1c, 0x53, 0x1d, 0x0 }, { 0xa1, 0x80, 0x52, 0x3b, 0x0 }}, 0xc },
+ {{{ 0x21, 0x1d, 0xa4, 0xae, 0x1 }, { 0x21, 0x0, 0xb1, 0x9e, 0x0 }}, 0xc },
+ {{{ 0xe1, 0x16, 0x71, 0xae, 0x0 }, { 0xe1, 0x0, 0x81, 0x9e, 0x0 }}, 0xa },
+ {{{ 0xe1, 0x15, 0x71, 0xae, 0x0 }, { 0xe2, 0x0, 0x81, 0x9e, 0x0 }}, 0xe },
+ {{{ 0x21, 0x16, 0x71, 0xae, 0x0 }, { 0x21, 0x0, 0x81, 0x9e, 0x0 }}, 0xe },
+ {{{ 0x71, 0x1c, 0x41, 0x1f, 0x0 }, { 0xa1, 0x80, 0x92, 0x3b, 0x0 }}, 0xe },
+ {{{ 0x21, 0x4f, 0x81, 0x53, 0x0 }, { 0x32, 0x0, 0x22, 0x2c, 0x0 }}, 0xa },
+ {{{ 0x22, 0x4f, 0x81, 0x53, 0x0 }, { 0x32, 0x0, 0x22, 0x2c, 0x0 }}, 0xa },
+ {{{ 0x23, 0x4f, 0x81, 0x53, 0x0 }, { 0x34, 0x0, 0x22, 0x2c, 0x0 }}, 0xa },
+ {{{ 0xe1, 0x16, 0x71, 0xae, 0x0 }, { 0xe1, 0x0, 0x81, 0x9e, 0x0 }}, 0xa },
+ {{{ 0x71, 0xc5, 0x6e, 0x17, 0x0 }, { 0x22, 0x5, 0x8b, 0xe, 0x0 }}, 0x2 },
+ {{{ 0xe6, 0x27, 0x70, 0xf, 0x1 }, { 0xe3, 0x0, 0x60, 0x9f, 0x0 }}, 0xa },
+ {{{ 0x30, 0xc8, 0xd5, 0x19, 0x0 }, { 0xb1, 0x80, 0x61, 0x1b, 0x0 }}, 0xc },
+ {{{ 0x32, 0x9a, 0x51, 0x1b, 0x0 }, { 0xa1, 0x82, 0xa2, 0x3b, 0x0 }}, 0xc },
+ {{{ 0xad, 0x3, 0x74, 0x29, 0x0 }, { 0xa2, 0x82, 0x73, 0x29, 0x0 }}, 0x7 },
+ {{{ 0x21, 0x83, 0x74, 0x17, 0x0 }, { 0x62, 0x8d, 0x65, 0x17, 0x0 }}, 0x7 },
+ {{{ 0x94, 0xb, 0x85, 0xff, 0x1 }, { 0x13, 0x0, 0x74, 0xff, 0x0 }}, 0xc },
+ {{{ 0x74, 0x87, 0xa4, 0x2, 0x0 }, { 0xd6, 0x80, 0x45, 0x42, 0x0 }}, 0x2 },
+ {{{ 0xb3, 0x85, 0x76, 0x21, 0x1 }, { 0x20, 0x0, 0x3d, 0xc1, 0x0 }}, 0x6 },
+ {{{ 0x17, 0x4f, 0xf2, 0x61, 0x0 }, { 0x12, 0x8, 0xf1, 0xb4, 0x0 }}, 0x8 },
+ {{{ 0x4f, 0x86, 0x65, 0x1, 0x0 }, { 0x1f, 0x0, 0x32, 0x74, 0x0 }}, 0x4 },
+ {{{ 0xe1, 0x23, 0x71, 0xae, 0x0 }, { 0xe4, 0x0, 0x82, 0x9e, 0x0 }}, 0xa },
+ {{{ 0x11, 0x86, 0xf2, 0xbd, 0x0 }, { 0x4, 0x80, 0xa0, 0x9b, 0x1 }}, 0x8 },
+ {{{ 0x20, 0x90, 0xf5, 0x9e, 0x2 }, { 0x11, 0x0, 0xf4, 0x5b, 0x3 }}, 0xc },
+ {{{ 0xf0, 0x80, 0x34, 0xe4, 0x0 }, { 0x7e, 0x0, 0xa2, 0x6, 0x0 }}, 0x8 },
+ {{{ 0x90, 0xf, 0xff, 0x1, 0x3 }, { 0x0, 0x0, 0x1f, 0x1, 0x0 }}, 0xe },
+ {{{ 0x1, 0x4f, 0xf0, 0xff, 0x0 }, { 0x33, 0x0, 0x90, 0xf, 0x0 }}, 0x6 },
+ {{{ 0x1e, 0x0, 0x1f, 0xf, 0x0 }, { 0x10, 0x0, 0x1f, 0x7f, 0x0 }}, 0x0 },
+ {{{ 0xbe, 0x0, 0xf1, 0x1, 0x3 }, { 0x31, 0x0, 0xf1, 0x1, 0x0 }}, 0x4 },
+ {{{ 0xbe, 0x0, 0xf1, 0x1, 0x3 }, { 0x31, 0x0, 0xf1, 0x1, 0x0 }}, 0x4 },
+ {{{ 0x93, 0x6, 0xc1, 0x4, 0x1 }, { 0x82, 0x0, 0x51, 0x9, 0x0 }}, 0x6 },
+ {{{ 0xa0, 0x0, 0x96, 0x33, 0x0 }, { 0x20, 0x0, 0x55, 0x2b, 0x0 }}, 0x6 },
+ {{{ 0x0, 0xc0, 0xff, 0x5, 0x0 }, { 0x0, 0x0, 0xff, 0x5, 0x3 }}, 0x0 },
+ {{{ 0x4, 0x8, 0xf8, 0x7, 0x0 }, { 0x1, 0x0, 0x82, 0x74, 0x0 }}, 0x8 },
+ {{{ 0x0, 0x0, 0x2f, 0x5, 0x0 }, { 0x20, 0x0, 0xff, 0x5, 0x3 }}, 0xa },
+ {{{ 0x93, 0x0, 0xf7, 0x7, 0x2 }, { 0x0, 0x0, 0xf7, 0x7, 0x0 }}, 0xa },
+ {{{ 0x0, 0x40, 0x80, 0x7a, 0x0 }, { 0xc4, 0x0, 0xc0, 0x7e, 0x0 }}, 0x8 },
+ {{{ 0x90, 0x80, 0x55, 0xf5, 0x0 }, { 0x0, 0x0, 0x55, 0xf5, 0x0 }}, 0x8 },
+ {{{ 0xe1, 0x80, 0x34, 0xe4, 0x0 }, { 0x69, 0x0, 0xf2, 0x6, 0x0 }}, 0x8 },
+ {{{ 0x3, 0x2, 0xf0, 0xff, 0x3 }, { 0x11, 0x80, 0xf0, 0xff, 0x2 }}, 0x2 },
+ {{{ 0x1e, 0x0, 0x1f, 0xf, 0x0 }, { 0x10, 0x0, 0x1f, 0x7f, 0x0 }}, 0x0 },
+ {{{ 0x0, 0x0, 0x2f, 0x1, 0x0 }, { 0x0, 0x0, 0xff, 0x1, 0x0 }}, 0x4 },
+ {{{ 0xbe, 0x0, 0xf1, 0x1, 0x3 }, { 0x31, 0x0, 0xf1, 0x1, 0x0 }}, 0x4 },
+ {{{ 0x93, 0x85, 0x3f, 0x6, 0x1 }, { 0x0, 0x0, 0x5f, 0x7, 0x0 }}, 0x6 },
+ {{{ 0x6, 0x0, 0xa0, 0xf0, 0x0 }, { 0x44, 0x0, 0xc5, 0x75, 0x0 }}, 0xe },
+ {{{ 0x60, 0x0, 0x10, 0x81, 0x0 }, { 0x20, 0x8c, 0x12, 0x91, 0x0 }}, 0xe },
+ {{{ 0x1, 0x40, 0xf1, 0x53, 0x0 }, { 0x8, 0x40, 0xf1, 0x53, 0x0 }}, 0x0 },
+ {{{ 0x31, 0x0, 0x56, 0x31, 0x0 }, { 0x16, 0x0, 0x7d, 0x41, 0x0 }}, 0x0 },
+ {{{ 0x0, 0x10, 0xf2, 0x72, 0x0 }, { 0x13, 0x0, 0xf2, 0x72, 0x0 }}, 0xc },
+ {{{ 0x10, 0x0, 0x75, 0x93, 0x1 }, { 0x1, 0x0, 0xf5, 0x82, 0x1 }}, 0x0 },
+ {{{ 0x0, 0x0, 0xf6, 0xff, 0x2 }, { 0x0, 0x0, 0xf6, 0xff, 0x0 }}, 0x8 },
+ {{{ 0x30, 0x0, 0xff, 0xa0, 0x3 }, { 0x63, 0x0, 0x65, 0xb, 0x2 }}, 0x0 },
+ {{{ 0x2a, 0x0, 0xf6, 0x87, 0x0 }, { 0x2b, 0x0, 0x76, 0x25, 0x0 }}, 0x0 },
+ {{{ 0x85, 0x0, 0xb8, 0x84, 0x0 }, { 0x43, 0x0, 0xe5, 0x8f, 0x0 }}, 0x6 },
+ {{{ 0x7, 0x4f, 0xf2, 0x60, 0x0 }, { 0x12, 0x0, 0xf2, 0x72, 0x0 }}, 0x8 },
+ {{{ 0x5, 0x40, 0xb3, 0xd3, 0x0 }, { 0x86, 0x80, 0xf2, 0x24, 0x0 }}, 0x2 },
+ {{{ 0xd0, 0x0, 0x11, 0xcf, 0x0 }, { 0xd1, 0x0, 0xf4, 0xe8, 0x3 }}, 0x0 },
+ {{{ 0x5, 0x4e, 0xda, 0x25, 0x2 }, { 0x1, 0x0, 0xf9, 0x15, 0x0 }}, 0xa },
+ {{{ 0x3, 0x0, 0x8f, 0x7, 0x2 }, { 0x2, 0x0, 0xff, 0x6, 0x0 }}, 0x0 },
+ {{{ 0x13, 0x0, 0x8f, 0x7, 0x2 }, { 0x2, 0x0, 0xf9, 0x5, 0x0 }}, 0x0 },
+ {{{ 0xf0, 0x1, 0x97, 0x17, 0x0 }, { 0x21, 0xd, 0xf1, 0x18, 0x0 }}, 0x8 },
+ {{{ 0xf1, 0x41, 0x11, 0x11, 0x0 }, { 0xf1, 0x41, 0x11, 0x11, 0x0 }}, 0x2 },
+ {{{ 0x13, 0x0, 0x8f, 0x7, 0x2 }, { 0x2, 0x0, 0xff, 0x6, 0x0 }}, 0x0 },
+ {{{ 0x1, 0x0, 0x2f, 0x1, 0x0 }, { 0x1, 0x0, 0xaf, 0x1, 0x3 }}, 0xf },
+ {{{ 0x1, 0x6, 0xf3, 0xff, 0x0 }, { 0x8, 0x0, 0xf7, 0xff, 0x0 }}, 0x4 },
+ {{{ 0xc0, 0x4f, 0xf1, 0x3, 0x0 }, { 0xbe, 0xc, 0x10, 0x1, 0x0 }}, 0x2 },
+ {{{ 0x0, 0x2, 0xf0, 0xff, 0x0 }, { 0x11, 0x80, 0xf0, 0xff, 0x0 }}, 0x6 },
+ {{{ 0x81, 0x47, 0xf1, 0x83, 0x0 }, { 0xa2, 0x4, 0x91, 0x86, 0x0 }}, 0x6 },
+ {{{ 0xf0, 0xc0, 0xff, 0xff, 0x3 }, { 0xe5, 0x0, 0xfb, 0xf0, 0x0 }}, 0xe },
+ {{{ 0x0, 0x2, 0xf0, 0xff, 0x0 }, { 0x11, 0x80, 0xf0, 0xff, 0x0 }}, 0x6 }
+};
+
+static const PercussionNote percussionNotes[47] = {
+ {{{ 0x0, 0xb, 0xa8, 0x38, 0x0 }, { 0x0, 0x0, 0xd6, 0x49, 0x0 }}, 0x0, 0x4, 0x1, 0x97, 0x4 },
+ {{{ 0xc0, 0xc0, 0xf8, 0x3f, 0x2 }, { 0xc0, 0x0, 0xf6, 0x8e, 0x0 }}, 0x0, 0x4, 0x1, 0xf7, 0x4 },
+ {{{ 0xc0, 0x80, 0xc9, 0xab, 0x0 }, { 0xeb, 0x40, 0xb5, 0xf6, 0x0 }}, 0x1, 0x3, 0x1, 0x6a, 0x6 },
+ {{{ 0xc, 0x0, 0xd8, 0xa6, 0x0 }, { 0x0, 0x0, 0xd6, 0x4f, 0x0 }}, 0x1, 0x3, 0x1, 0x6c, 0x5 },
+ {{{ 0x1, 0x0, 0xe2, 0xd2, 0x0 }, { 0x3, 0x41, 0x8f, 0x48, 0x49 }}, 0xc, 0x4, 0x1, 0x2f, 0x5 },
+ {{{ 0x0, 0x0, 0xc8, 0x58, 0x3 }, { 0x0, 0x0, 0xf6, 0x4f, 0x0 }}, 0x9, 0x3, 0x1, 0x108, 0x4 },
+ {{{ 0x1, 0x0, 0xff, 0x5, 0x0 }, { 0xf2, 0xff, 0xe0, 0x50, 0x52 }}, 0x5d, 0x2, 0x1, 0x9f, 0x5 },
+ {{{ 0xe, 0x9, 0xb9, 0x47, 0x0 }, { 0xeb, 0x40, 0xf5, 0xe6, 0x0 }}, 0x0, 0x0, 0x1, 0x82, 0x6 },
+ {{{ 0x0, 0x0, 0xd6, 0x83, 0x0 }, { 0xd6, 0xd7, 0xe0, 0x41, 0x5e }}, 0x4a, 0x2, 0x1, 0xc7, 0x5 },
+ {{{ 0x1, 0x9, 0x89, 0x67, 0x0 }, { 0xd6, 0xd7, 0xe0, 0x41, 0x5e }}, 0x4a, 0x0, 0x1, 0x80, 0x6 },
+ {{{ 0x1, 0x0, 0xd6, 0x96, 0x0 }, { 0xd6, 0xd7, 0xe0, 0x41, 0x5e }}, 0x4a, 0x2, 0x1, 0xed, 0x5 },
+ {{{ 0x0, 0x9, 0xa9, 0x55, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x1, 0x82, 0x6 },
+ {{{ 0x2, 0x0, 0xc6, 0x96, 0x0 }, { 0xe0, 0x0, 0xe0, 0x40, 0x0 }}, 0x1, 0x2, 0x1, 0x123, 0x5 },
+ {{{ 0x5, 0x0, 0xf6, 0x56, 0x0 }, { 0xf7, 0xff, 0xb3, 0x90, 0x4f }}, 0x1, 0x2, 0x1, 0x15b, 0x5 },
+ {{{ 0x1, 0x0, 0xf7, 0x14, 0x0 }, { 0xf7, 0xff, 0x36, 0x90, 0x79 }}, 0xe7, 0x1, 0x1, 0x1ac, 0x5 },
+ {{{ 0x0, 0x0, 0xf6, 0x56, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x1, 0x2, 0x1, 0x18b, 0x5 },
+ {{{ 0x0, 0x83, 0xfb, 0x5, 0x0 }, { 0xf7, 0x41, 0x39, 0x90, 0x79 }}, 0x1, 0x1, 0x1, 0xc8, 0x5 },
+ {{{ 0x0, 0x0, 0xff, 0x5, 0x0 }, { 0xf7, 0xff, 0x36, 0x90, 0x79 }}, 0xe7, 0x1, 0x1, 0xf9, 0x5 },
+ {{{ 0x1, 0x0, 0xa0, 0x5, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x2, 0x1, 0x27a, 0x6 },
+ {{{ 0x0, 0x5, 0xf3, 0x6, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x2, 0x1, 0x108, 0x7 },
+ {{{ 0x1, 0x0, 0xf9, 0x34, 0x0 }, { 0xf7, 0xff, 0x36, 0x90, 0x79 }}, 0xe7, 0x1, 0x1, 0x147, 0x4 },
+ {{{ 0x0, 0x0, 0xf7, 0x16, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x2, 0x1, 0x120, 0x6 },
+ {{{ 0x1, 0x0, 0xff, 0x5, 0x0 }, { 0xf7, 0xff, 0x36, 0x90, 0x79 }}, 0xe7, 0x1, 0x1, 0x42, 0x6 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x1, 0x0, 0xff, 0x5, 0x0 }, { 0xf7, 0xff, 0x36, 0x90, 0x79 }}, 0xe7, 0x1, 0x1, 0x6d, 0x5 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 }
+};
+
+const uint16 melodicFrequencies[36] = {
+ 0x55, 0x5a, 0x60, 0x66, 0x6c, 0x72, 0x79, 0x80, 0x88,
+ 0x90, 0x99, 0xa1, 0xab, 0xb5, 0xc0, 0xcc, 0xd8, 0xe5,
+ 0xf2, 0x101, 0x110, 0x120, 0x132, 0x143, 0x156, 0x16b, 0x181,
+ 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x241, 0x263, 0x286
+};
+
+class AdLibDriver;
+
+class AdLibChannel : public MidiChannel_MPU401 {
+public:
+ void reset();
+
+ uint8 _program;
+ uint8 _volume;
+ uint8 _pedal;
+};
+
+struct MelodicVoice {
+ bool _used;
+ uint8 _channel;
+ uint8 _program;
+
+ uint8 _key;
+ uint32 _timestamp;
+ uint16 _frequency;
+ int8 _octave;
+};
+
+class AdLibDriver : public MidiDriver_Emulated {
+public:
+ AdLibDriver(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer) {
+ for (uint i = 0; i < 16; ++i)
+ _channels[i].init(this, i);
+ }
+
+ int open();
+ void close();
+ void send(uint32 b);
+ MidiChannel *allocateChannel();
+ MidiChannel *getPercussionChannel() { return &_channels[9]; }
+
+ bool isStereo() const { return false; }
+ int getRate() const { return _mixer->getOutputRate(); }
+
+ void generateSamples(int16 *buf, int len);
+
+protected:
+ OPL::OPL *_opl;
+ AdLibChannel _channels[16];
+ MelodicVoice _voices[kNumMelodic];
+ uint8 _notesPerPercussion[kNumPercussion];
+
+ uint _lastVoice;
+
+ uint8 _percussionMask;
+
+ void noteOff(uint8 channel, uint8 note);
+ void noteOn(uint8 channel, uint8 note, uint8 velocity);
+ void allNotesOff();
+ void setModulationWheel(uint8 channel, uint8 value);
+ void setFootController(uint8 channel, uint8 value);
+ void setVolume(uint8 channel, uint8 value);
+ void setPitchBend(uint8 channel, int16 value);
+
+ void playNote(uint8 voice, uint8 octave, uint16 frequency);
+
+ void programOperatorSimple(uint8 offset, const OPLOperator &op);
+ void programOperator(uint8 offset, const OPLOperator &op);
+ void setOperatorLevel(uint8 offset, const OPLOperator &op, uint8 velocity, uint8 channel, bool forceVolume);
+
+ void setupPercussion(const PercussionNote &note);
+ void playPercussion(uint8 channel, const PercussionNote &note, uint8 velocity);
+
+ void programMelodicVoice(uint8 voice, uint8 program);
+ void playMelodicNote(uint8 voice, uint8 channel, uint8 note, uint8 velocity);
+ void muteMelodicVoice(uint8 voice);
+
+ void initVoices();
+};
+
+MidiDriver *createAdLibDriver() {
+ return new AdLibDriver(g_system->getMixer());
+}
+
+void AdLibChannel::reset() {
+ _program = 0;
+ _volume = 127;
+ _pedal = 0;
+}
+
+/*
+ bit 7 - Clear: AM depth is 1 dB
+ bit 6 - Clear: Vibrato depth is 7 cent
+ bit 5 - Set: Rhythm enabled (6 melodic voices)
+ bit 4 - Bass drum off
+ bit 3 - Snare drum off
+ bit 2 - Tom tom off
+ bit 1 - Cymbal off
+ bit 0 - Hi Hat off
+*/
+const uint8 kDefaultPercussionMask = 0x20;
+
+int AdLibDriver::open() {
+ if (_isOpen)
+ return MERR_ALREADY_OPEN;
+
+ MidiDriver_Emulated::open();
+
+ _opl = OPL::Config::create();
+ _opl->init(getRate());
+ _opl->writeReg(0x1, 0x20); // set bit 5 (enable all waveforms)
+
+ // Reset the OPL registers.
+ for (uint i = 0; i < kNumVoices; ++i) {
+ _opl->writeReg(0xA0 + i, 0); // frequency
+ _opl->writeReg(0xB0 + i, 0); // key on
+ _opl->writeReg(0xC0 + i, 0); // feedback
+ }
+ _opl->writeReg(0xBD, kDefaultPercussionMask);
+
+ initVoices();
+
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+ return 0;
+}
+
+void AdLibDriver::close() {
+ if (!_isOpen)
+ return;
+
+ _isOpen = false;
+ _mixer->stopHandle(_mixerSoundHandle);
+
+ delete _opl;
+}
+
+void AdLibDriver::send(uint32 b) {
+ uint channel = b & 0xf;
+ uint cmd = (b >> 4) & 0xf;
+ uint param1 = (b >> 8) & 0xff;
+ uint param2 = (b >> 16) & 0xff;
+
+ switch (cmd) {
+ case 8:
+ noteOff(channel, param1);
+ break;
+ case 9:
+ // TODO: map volume?
+ noteOn(channel, param1, param2);
+ break;
+ case 11:
+ // controller change
+ switch (param1) {
+ case 1:
+ setModulationWheel(channel, param2);
+ break;
+ case 4:
+ setFootController(channel, param2);
+ break;
+ case 7:
+ setVolume(channel, param2);
+ break;
+ case 123:
+ // all notes off
+ allNotesOff();
+ break;
+ }
+ break;
+ case 12:
+ // program change
+ _channels[channel]._program = param1;
+ break;
+ case 14:
+ setPitchBend(channel, (param1 | (param2 << 7)) - 0x2000);
+ break;
+ }
+}
+
+void AdLibDriver::noteOff(uint8 channel, uint8 note) {
+ if (channel == 9) {
+ if (note < 35 || note > 81)
+ return;
+
+ _percussionMask &= ~(1 << percussionNotes[note - 35].percussion);
+ _opl->writeReg(0xBD, _percussionMask);
+ return;
+ }
+
+ for (int i = kNumMelodic - 1; i >= 0; --i) {
+ if (_voices[i]._channel != channel)
+ continue;
+ if (_voices[i]._key != note)
+ continue;
+ muteMelodicVoice(i);
+ _voices[i]._used = false;
+ return;
+ }
+
+ //debug(1, "failed to find voice off for channel %d, note %d", channel, note);
+}
+
+void AdLibDriver::noteOn(uint8 channel, uint8 note, uint8 velocity) {
+ if (channel == 9) {
+ if (note < 35 || note > 81)
+ return;
+
+ const PercussionNote &info = percussionNotes[note - 35];
+ if (!info.valid)
+ return;
+
+ if (note != _notesPerPercussion[info.percussion]) {
+ setupPercussion(info);
+ _notesPerPercussion[info.percussion] = note;
+ }
+
+ playPercussion(channel, info, velocity);
+ return;
+ }
+
+ if (velocity == 0) {
+ noteOff(channel, note);
+ return;
+ }
+
+ // We want to play a note on a melodic (voice) channel.
+
+ // First, look for a voice playing the same note with the same program.
+ for (uint i = 0; i < kNumMelodic; ++i) {
+ if (_voices[i]._channel != channel || _voices[i]._key != note)
+ continue;
+ if (_voices[i]._program != _channels[channel]._program)
+ continue;
+ muteMelodicVoice(i);
+ playMelodicNote(i, channel, note, velocity);
+ return;
+ }
+
+ // The loops below try to start at _lastVoice and find a voice to use.
+ // They ignore _lastVoice itself, and update _lastVoice if they succeed.
+
+ // Then, try finding a melodic voice with the same program.
+ for (uint i = (_lastVoice + 1) % kNumMelodic; i != _lastVoice; i = (i + 1) % kNumMelodic) {
+ if (_voices[i]._used)
+ continue;
+ if (_voices[i]._program != _channels[channel]._program)
+ continue;
+ playMelodicNote(i, channel, note, velocity);
+ _lastVoice = i;
+ return;
+ }
+
+ // Then, try finding a free melodic voice of any kind.
+ for (uint i = (_lastVoice + 1) % kNumMelodic; i != _lastVoice; i = (i + 1) % kNumMelodic) {
+ if (_voices[i]._used)
+ continue;
+ programMelodicVoice(i, _channels[channel]._program);
+ playMelodicNote(i, channel, note, velocity);
+ _lastVoice = i;
+ return;
+ }
+
+ // Then just try finding a melodic voice with the same program,
+ // and steal it.
+ for (uint i = (_lastVoice + 1) % kNumMelodic; i != _lastVoice; i = (i + 1) % kNumMelodic) {
+ if (_voices[i]._program != _channels[channel]._program)
+ continue;
+ muteMelodicVoice(i);
+ playMelodicNote(i, channel, note, velocity);
+ _lastVoice = i;
+ return;
+ }
+
+ // Finally, just take control of the channel used least recently.
+ uint voiceId = 0;
+ uint32 bestTimestamp = 0xffffffff;
+ for (uint i = 0; i < kNumMelodic; ++i)
+ if (bestTimestamp > _voices[i]._timestamp) {
+ voiceId = i;
+ bestTimestamp = _voices[i]._timestamp;
+ }
+
+ //debug(1, "ran out of voices for channel %d, note %d, program %d: reused voice %d", channel, note, _channels[channel]._program, voiceId);
+ programMelodicVoice(voiceId, _channels[channel]._program);
+ playMelodicNote(voiceId, channel, note, velocity);
+ _lastVoice = voiceId;
+}
+
+// TODO: this doesn't match original
+void AdLibDriver::allNotesOff() {
+ for (uint i = 0; i < kNumMelodic; ++i) {
+ muteMelodicVoice(i);
+ _voices[i]._used = false;
+ }
+
+ _percussionMask = kDefaultPercussionMask;
+ _opl->writeReg(0xBD, kDefaultPercussionMask);
+}
+
+void AdLibDriver::setModulationWheel(uint8 channel, uint8 value) {
+ if (value >= 64)
+ _percussionMask |= 0x80;
+ else
+ _percussionMask &= 0x7f;
+
+ _opl->writeReg(0xBD, _percussionMask);
+}
+
+void AdLibDriver::setFootController(uint8 channel, uint8 value) {
+ _channels[channel]._pedal = (value >= 64);
+}
+
+void AdLibDriver::setVolume(uint8 channel, uint8 value) {
+ _channels[channel]._volume = value;
+}
+
+void AdLibDriver::setPitchBend(uint8 channel, int16 value) {
+ for (uint i = 0; i < kNumMelodic; ++i) {
+ if (_voices[i]._channel != channel || !_voices[i]._used)
+ continue;
+
+ // index into frequency table
+ uint f = 12 + (_voices[i]._key % 12);
+
+ int16 bendAmount = value;
+ if (bendAmount > 0) {
+ // bend up two semitones
+ bendAmount *= (melodicFrequencies[f + 2] - melodicFrequencies[f]);
+ } else {
+ // bend down two semitones
+ bendAmount *= (melodicFrequencies[f] - melodicFrequencies[f - 2]);
+ }
+ bendAmount /= 0x2000;
+ bendAmount += melodicFrequencies[f]; // add the base frequency
+ playNote(i, _voices[i]._octave, bendAmount);
+ _voices[i]._timestamp = g_system->getMillis();
+ }
+}
+
+void AdLibDriver::playNote(uint8 voice, uint8 octave, uint16 frequency) {
+ /* Percussions are always fed keyOn = 0 even to set the note, as they are activated using the
+ BD register instead. I wonder if they can just be fed the same value as melodic voice and
+ be done with it. */
+ uint8 keyOn = (voice < kNumMelodic) ? 0x20 : 0;
+
+ // key on, octave, high 2 bits of frequency
+ _opl->writeReg(0xB0 + voice, keyOn | ((octave & 7) << 2) | ((frequency >> 8) & 3));
+ // low 8 bits of frequency
+ _opl->writeReg(0xA0 + voice, frequency & 0xff);
+}
+
+void AdLibDriver::programOperatorSimple(uint8 offset, const OPLOperator &op) {
+ _opl->writeReg(0x40 + offset, op.levels & LEVEL_MASK);
+ _opl->writeReg(0x60 + offset, op.attackDecay);
+ _opl->writeReg(0x80 + offset, op.sustainRelease);
+}
+
+void AdLibDriver::programOperator(uint8 offset, const OPLOperator &op) {
+ _opl->writeReg(0x20 + offset, op.characteristic);
+ _opl->writeReg(0x60 + offset, op.attackDecay);
+ _opl->writeReg(0x80 + offset, op.sustainRelease);
+ _opl->writeReg(0xE0 + offset, op.waveform);
+ _opl->writeReg(0x40 + offset, op.levels);
+}
+
+const uint16 adlibLogVolume[] = {
+ 0, 37, 58, 73, 85, 95, 103, 110, 116, 121, 127, 131, 135, 139, 143, 146,
+ 149, 153, 155, 158, 161, 163, 165, 168, 170, 172, 174, 176, 178, 179, 181, 183,
+ 184, 186, 188, 189, 191, 192, 193, 195, 196, 197, 198, 200, 201, 202, 203, 204,
+ 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 219,
+ 220, 221, 222, 223, 223, 224, 225, 226, 226, 227, 228, 228, 229, 230, 231, 231,
+ 232, 233, 233, 234, 234, 235, 236, 236, 237, 237, 238, 239, 239, 240, 240, 241,
+ 241, 242, 242, 243, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249,
+ 249, 250, 250, 251, 251, 252, 252, 253, 253, 253, 254, 254, 255, 255, 256, 256,
+ 256
+};
+
+void AdLibDriver::setOperatorLevel(uint8 offset, const OPLOperator &op, uint8 velocity, uint8 channel, bool forceVolume) {
+ uint8 programLevel = LEVEL_MASK;
+ if (!forceVolume)
+ programLevel -= (op.levels & LEVEL_MASK);
+
+ uint32 noteLevel = adlibLogVolume[velocity];
+ uint32 channelLevel = adlibLogVolume[_channels[channel]._volume];
+ // programLevel comes from the static data and is probably already in the correct logarithmic scale
+ uint32 finalLevel = LEVEL_MASK - ((noteLevel * channelLevel * programLevel) >> 16);
+
+ // high 2 bits are scaling level, the rest is (inversed) volume
+ _opl->writeReg(0x40 + offset, (op.levels & 0xc0) | (finalLevel & 0x3f));
+}
+
+const uint8 operatorOffsetsForPercussion[] = {
+ 0x11, // hi-hat
+ 0x15, // cymbal
+ 0x12, // tom tom
+ 0x14 // snare drum
+};
+
+void AdLibDriver::setupPercussion(const PercussionNote &note) {
+ if (note.percussion < 4) {
+ // simple percussion (1 operator)
+
+ // turn off relevant percussion
+ _percussionMask &= ~(1 << note.percussion);
+ _opl->writeReg(0xBD, _percussionMask);
+
+ programOperatorSimple(operatorOffsetsForPercussion[note.percussion], note.op[0]);
+ return;
+ }
+
+ // bass drum (2 operators)
+
+ // turn off bass drum
+ _percussionMask &= ~(0x10);
+ _opl->writeReg(0xBD, _percussionMask);
+
+ programOperator(0x10, note.op[0]);
+ programOperator(0x13, note.op[1]);
+
+ _opl->writeReg(0xC0 + 6, note.feedbackAlgo);
+}
+
+void AdLibDriver::playPercussion(uint8 channel, const PercussionNote &note, uint8 velocity) {
+ if (note.percussion < 4) {
+ // simple percussion (1 operator)
+
+ // turn off relevant percussion
+ _percussionMask &= ~(1 << note.percussion);
+ _opl->writeReg(0xBD, _percussionMask);
+
+ setOperatorLevel(operatorOffsetsForPercussion[note.percussion], note.op[0], velocity, channel, true);
+
+ if (note.percussion == 2) {
+ // tom tom
+ playNote(8, note.octave, note.frequency);
+ } else if (note.percussion == 3) {
+ // snare drum
+ playNote(7, note.octave, note.frequency);
+ }
+
+ // turn on relevant percussion
+ _percussionMask |= (1 << note.percussion);
+ _opl->writeReg(0xBD, _percussionMask);
+ return;
+ }
+
+ // turn off bass drum
+ _percussionMask &= ~(0x10);
+ _opl->writeReg(0xBD, _percussionMask);
+
+ if (note.feedbackAlgo & 1) {
+ // operators 1 and 2 in additive synthesis
+ setOperatorLevel(0x10, note.op[0], velocity, channel, true);
+ setOperatorLevel(0x13, note.op[1], velocity, channel, true);
+ } else {
+ // operator 2 is modulating operator 1
+ setOperatorLevel(0x13, note.op[1], velocity, channel, true);
+ }
+
+ playNote(6, note.octave, note.frequency);
+
+ // turn on bass drum
+ _percussionMask |= 0x10;
+ _opl->writeReg(0xBD, _percussionMask);
+}
+
+const uint8 offset1ForMelodic[kNumVoices] = { 0x0, 0x1, 0x2, 0x8, 0x9, 0xa, 0x10, 0x11, 0x12 };
+const uint8 offset2ForMelodic[kNumVoices] = { 0x3, 0x4, 0x5, 0xb, 0xc, 0xd, 0x13, 0x14, 0x15 };
+
+void AdLibDriver::programMelodicVoice(uint8 voice, uint8 program) {
+ assert(program < 128);
+ assert(voice < kNumMelodic);
+
+ const MelodicProgram &info = melodicPrograms[program];
+ uint8 offset1 = offset1ForMelodic[voice];
+ uint8 offset2 = offset2ForMelodic[voice];
+
+ // Start at lowest volume.
+ _opl->writeReg(0x40 + offset1, LEVEL_MASK);
+ _opl->writeReg(0x40 + offset2, LEVEL_MASK);
+
+ muteMelodicVoice(voice);
+
+ programOperator(offset1, info.op[0]);
+ programOperator(offset2, info.op[1]);
+
+ _opl->writeReg(0xC0 + voice, info.feedbackAlgo);
+}
+
+void AdLibDriver::playMelodicNote(uint8 voice, uint8 channel, uint8 note, uint8 velocity) {
+ assert(voice < kNumMelodic);
+
+ uint8 octave = note / 12;
+ uint8 f = 12 + (note % 12);
+
+ if (octave > 7)
+ octave = 7;
+
+ const MelodicProgram &info = melodicPrograms[_channels[channel]._program];
+ uint8 offset1 = offset1ForMelodic[voice];
+ uint8 offset2 = offset2ForMelodic[voice];
+
+ if (info.feedbackAlgo & 1) {
+ setOperatorLevel(offset1, info.op[0], velocity, channel, false);
+ setOperatorLevel(offset2, info.op[1], velocity, channel, false);
+ } else {
+ setOperatorLevel(offset2, info.op[1], velocity, channel, true);
+ }
+
+ playNote(voice, octave, melodicFrequencies[f]);
+
+ _voices[voice]._program = _channels[channel]._program;
+ _voices[voice]._key = note;
+ _voices[voice]._channel = channel;
+ _voices[voice]._timestamp = g_system->getMillis();
+ _voices[voice]._frequency = melodicFrequencies[f];
+ _voices[voice]._octave = octave;
+ _voices[voice]._used = true;
+}
+
+void AdLibDriver::muteMelodicVoice(uint8 voice) {
+ _opl->writeReg(0xB0 + voice, 0 | ((_voices[voice]._octave & 7) << 2) | ((_voices[voice]._frequency >> 8) & 3));
+}
+
+MidiChannel *AdLibDriver::allocateChannel() {
+ for (uint i = 0; i < 16; ++i) {
+ if (i == 9)
+ continue;
+
+ if (_channels[i].allocate())
+ return &_channels[i];
+ }
+
+ return NULL;
+}
+
+void AdLibDriver::generateSamples(int16 *buf, int len) {
+ memset(buf, 0, sizeof(int16) * len);
+ _opl->readBuffer(buf, len);
+}
+
+void AdLibDriver::initVoices() {
+ _percussionMask = kDefaultPercussionMask;
+ _opl->writeReg(0xBD, _percussionMask);
+
+ for (uint i = 0; i < 16; ++i)
+ _channels[i].reset();
+
+ for (uint i = 0; i < kNumMelodic; ++i) {
+ _voices[i]._key = 0xff;
+ _voices[i]._program = 0xff;
+ _voices[i]._channel = 0xff;
+ _voices[i]._timestamp = 0;
+ _voices[i]._frequency = 0;
+ _voices[i]._octave = 0;
+ _voices[i]._used = false;
+ }
+
+ for (uint i = 0; i < kNumPercussion; ++i)
+ _notesPerPercussion[i] = 0xff;
+
+ _lastVoice = 0;
+}
+
+} // namespace Parallaction
diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp
index 64885c7ff3..c1720a1a8e 100644
--- a/engines/parallaction/callables_ns.cpp
+++ b/engines/parallaction/callables_ns.cpp
@@ -275,7 +275,7 @@ void Parallaction_ns::_c_contaFoglie(void *parm) {
if (num_foglie != 6)
return;
- _globalFlags |= 0x1000;
+ g_globalFlags |= 0x1000;
return;
}
@@ -286,7 +286,7 @@ void Parallaction_ns::_c_zeroFoglie(void *parm) {
}
void Parallaction_ns::_c_trasformata(void *parm) {
- _engineFlags ^= kEngineTransformedDonna;
+ g_engineFlags ^= kEngineTransformedDonna;
// No need to invoke changeCharacter here, as
// transformation happens on a location switch
// and character change is automatically triggered.
@@ -295,11 +295,11 @@ void Parallaction_ns::_c_trasformata(void *parm) {
void Parallaction_ns::_c_offMouse(void *parm) {
_input->setMouseState(MOUSE_DISABLED);
- _engineFlags |= kEngineBlockInput;
+ g_engineFlags |= kEngineBlockInput;
}
void Parallaction_ns::_c_onMouse(void *parm) {
- _engineFlags &= ~kEngineBlockInput;
+ g_engineFlags &= ~kEngineBlockInput;
_input->setMouseState(MOUSE_ENABLED_SHOW);
}
@@ -389,7 +389,7 @@ void Parallaction_ns::_c_finito(void *parm) {
}
void Parallaction_ns::_c_ridux(void *parm) {
- changeCharacter(_minidinoName);
+ changeCharacter(g_minidinoName);
return;
}
@@ -444,7 +444,7 @@ void Parallaction_ns::_c_startIntro(void *parm) {
_soundManI->playMusic();
}
- _engineFlags |= kEngineBlockInput;
+ g_engineFlags |= kEngineBlockInput;
_input->setMouseState(MOUSE_DISABLED);
_intro = true;
}
diff --git a/engines/parallaction/debug.cpp b/engines/parallaction/debug.cpp
index 0cb329e0f0..25acac9b06 100644
--- a/engines/parallaction/debug.cpp
+++ b/engines/parallaction/debug.cpp
@@ -103,7 +103,7 @@ bool Debugger::Cmd_Locations(int argc, const char **argv) {
bool Debugger::Cmd_GlobalFlags(int argc, const char **argv) {
- uint32 flags = _globalFlags;
+ uint32 flags = g_globalFlags;
DebugPrintf("+------------------------------+---------+\n"
"| flag name | value |\n"
@@ -128,10 +128,10 @@ bool Debugger::Cmd_ToggleGlobalFlag(int argc, const char **argv) {
DebugPrintf("invalid flag '%s'\n", argv[1]);
} else {
i--;
- if ((_globalFlags & (1 << i)) == 0)
- _globalFlags |= (1 << i);
+ if ((g_globalFlags & (1 << i)) == 0)
+ g_globalFlags |= (1 << i);
else
- _globalFlags &= ~(1 << i);
+ g_globalFlags &= ~(1 << i);
}
break;
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index e0bd6a6677..78cc23311f 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -192,7 +192,7 @@ void DialogueManager::transitionToState(DialogueState newState) {
bool DialogueManager::testAnswerFlags(Answer *a) {
uint32 flags = _vm->getLocationFlags();
if (a->_yesFlags & kFlagsGlobal)
- flags = _globalFlags | kFlagsGlobal;
+ flags = g_globalFlags | kFlagsGlobal;
return ((a->_yesFlags & flags) == a->_yesFlags) && ((a->_noFlags & ~flags) == a->_noFlags);
}
@@ -370,9 +370,9 @@ protected:
bool _askPassword;
bool checkPassword() {
- return ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && _vm->_password.hasPrefix("1732461")) ||
- (!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && _vm->_password.hasPrefix("1622")) ||
- (!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && _vm->_password.hasPrefix("179")));
+ return ((!scumm_stricmp(_vm->_char.getBaseName(), g_doughName) && _vm->_password.hasPrefix("1732461")) ||
+ (!scumm_stricmp(_vm->_char.getBaseName(), g_donnaName) && _vm->_password.hasPrefix("1622")) ||
+ (!scumm_stricmp(_vm->_char.getBaseName(), g_dinoName) && _vm->_password.hasPrefix("179")));
}
void resetPassword() {
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index ee981a2c7d..8988897456 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -31,7 +31,7 @@
namespace Parallaction {
-extern byte _braAmigaFramesDefaultPalette[];
+extern byte braAmigaFramesDefaultPalette[];
struct Sprite {
uint16 size;
@@ -475,7 +475,7 @@ void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) {
}
delete stream;
} else {
- p = _braAmigaFramesDefaultPalette;
+ p = braAmigaFramesDefaultPalette;
for (i = 0; i < 16; i++) {
r = *p >> 2;
p++;
diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp
index 8d4afd6847..bad854525d 100644
--- a/engines/parallaction/disk_ns.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -262,8 +262,15 @@ Common::SeekableReadStream *DosDisk_ns::tryOpenFile(const char* name) {
Script* Disk_ns::loadLocation(const char *name) {
char path[PATH_LEN];
+ const char *charName = _vm->_char.getBaseName();
- sprintf(path, "%s%s/%s.loc", _vm->_char.getBaseName(), _language.c_str(), name);
+ // WORKAROUND: Special case for the Multilingual DOS version: during the ending
+ // sequence, it tries to load a non-existing file using "Dinor" as a character
+ // name. In this case, the character name should be just "dino".
+ if (!strcmp(charName, "Dinor"))
+ charName = "dino";
+
+ sprintf(path, "%s%s/%s.loc", charName, _language.c_str(), name);
debugC(3, kDebugDisk, "Disk_ns::loadLocation(%s): trying '%s'", name, path);
Common::SeekableReadStream *stream = tryOpenFile(path);
@@ -328,7 +335,7 @@ GfxObj* DosDisk_ns::loadTalk(const char *name) {
}
char v20[30];
- if (_engineFlags & kEngineTransformedDonna) {
+ if (g_engineFlags & kEngineTransformedDonna) {
sprintf(v20, "%stta.cnv", name);
} else {
sprintf(v20, "%stal.cnv", name);
diff --git a/engines/parallaction/exec.cpp b/engines/parallaction/exec.cpp
index 8594d02641..122abf9e0e 100644
--- a/engines/parallaction/exec.cpp
+++ b/engines/parallaction/exec.cpp
@@ -56,7 +56,7 @@ void ProgramExec::runScript(ProgramPtr script, AnimationPtr a) {
}
void ProgramExec::runScripts(ProgramList::iterator first, ProgramList::iterator last) {
- if (_engineFlags & kEnginePauseJobs) {
+ if (g_engineFlags & kEnginePauseJobs) {
return;
}
@@ -110,7 +110,7 @@ void CommandExec::runList(CommandList::iterator first, CommandList::iterator las
}
if (cmd->_flagsOn & kFlagsGlobal) {
- useFlags = _globalFlags | kFlagsGlobal;
+ useFlags = g_globalFlags | kFlagsGlobal;
useLocalFlags = false;
} else {
useFlags = _vm->getLocationFlags();
@@ -182,7 +182,7 @@ void CommandExec::suspend() {
}
void CommandExec::runSuspended() {
- if (_engineFlags & kEngineWalking) {
+ if (g_engineFlags & kEngineWalking) {
return;
}
diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp
index 658ef5af82..985ea29311 100644
--- a/engines/parallaction/exec_br.cpp
+++ b/engines/parallaction/exec_br.cpp
@@ -307,7 +307,7 @@ DECLARE_COMMAND_OPCODE(testsfx) {
DECLARE_COMMAND_OPCODE(ret) {
- _engineFlags |= kEngineReturn;
+ g_engineFlags |= kEngineReturn;
}
@@ -327,7 +327,7 @@ DECLARE_INSTRUCTION_OPCODE(invalid) {
DECLARE_COMMAND_OPCODE(clear) {
if (ctxt._cmd->_flags & kFlagsGlobal) {
ctxt._cmd->_flags &= ~kFlagsGlobal;
- _globalFlags &= ~ctxt._cmd->_flags;
+ g_globalFlags &= ~ctxt._cmd->_flags;
} else {
_vm->clearLocationFlags(ctxt._cmd->_flags);
}
@@ -356,7 +356,7 @@ DECLARE_COMMAND_OPCODE(get) {
DECLARE_COMMAND_OPCODE(toggle) {
if (ctxt._cmd->_flags & kFlagsGlobal) {
ctxt._cmd->_flags &= ~kFlagsGlobal;
- _globalFlags ^= ctxt._cmd->_flags;
+ g_globalFlags ^= ctxt._cmd->_flags;
} else {
_vm->toggleLocationFlags(ctxt._cmd->_flags);
}
@@ -373,7 +373,7 @@ DECLARE_COMMAND_OPCODE(invalid) {
DECLARE_COMMAND_OPCODE(set) {
if (ctxt._cmd->_flags & kFlagsGlobal) {
ctxt._cmd->_flags &= ~kFlagsGlobal;
- _globalFlags |= ctxt._cmd->_flags;
+ g_globalFlags |= ctxt._cmd->_flags;
} else {
_vm->setLocationFlags(ctxt._cmd->_flags);
}
diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp
index d8fbdea971..3ea4332e50 100644
--- a/engines/parallaction/exec_ns.cpp
+++ b/engines/parallaction/exec_ns.cpp
@@ -151,7 +151,7 @@ DECLARE_INSTRUCTION_OPCODE(call) {
DECLARE_INSTRUCTION_OPCODE(wait) {
- if (_engineFlags & kEngineWalking) {
+ if (g_engineFlags & kEngineWalking) {
ctxt._ip--;
ctxt._suspend = true;
}
@@ -198,7 +198,7 @@ DECLARE_COMMAND_OPCODE(invalid) {
DECLARE_COMMAND_OPCODE(set) {
if (ctxt._cmd->_flags & kFlagsGlobal) {
ctxt._cmd->_flags &= ~kFlagsGlobal;
- _globalFlags |= ctxt._cmd->_flags;
+ g_globalFlags |= ctxt._cmd->_flags;
} else {
_vm->setLocationFlags(ctxt._cmd->_flags);
}
@@ -208,7 +208,7 @@ DECLARE_COMMAND_OPCODE(set) {
DECLARE_COMMAND_OPCODE(clear) {
if (ctxt._cmd->_flags & kFlagsGlobal) {
ctxt._cmd->_flags &= ~kFlagsGlobal;
- _globalFlags &= ~ctxt._cmd->_flags;
+ g_globalFlags &= ~ctxt._cmd->_flags;
} else {
_vm->clearLocationFlags(ctxt._cmd->_flags);
}
@@ -267,7 +267,7 @@ DECLARE_COMMAND_OPCODE(call) {
DECLARE_COMMAND_OPCODE(toggle) {
if (ctxt._cmd->_flags & kFlagsGlobal) {
ctxt._cmd->_flags &= ~kFlagsGlobal;
- _globalFlags ^= ctxt._cmd->_flags;
+ g_globalFlags ^= ctxt._cmd->_flags;
} else {
_vm->toggleLocationFlags(ctxt._cmd->_flags);
}
diff --git a/engines/parallaction/font.cpp b/engines/parallaction/font.cpp
index d4c9aefd32..3b40960381 100644
--- a/engines/parallaction/font.cpp
+++ b/engines/parallaction/font.cpp
@@ -29,7 +29,7 @@
namespace Parallaction {
-extern byte _amigaTopazFont[];
+extern byte amigaTopazFont[];
class BraFont : public Font {
@@ -675,7 +675,7 @@ void Parallaction_ns::initFonts() {
_introFont = _disk->loadFont("slide");
} else {
_dialogueFont = _disk->loadFont("comic");
- Common::MemoryReadStream stream(_amigaTopazFont, 2600, DisposeAfterUse::NO);
+ Common::MemoryReadStream stream(amigaTopazFont, 2600, DisposeAfterUse::NO);
_labelFont = new AmigaFont(stream);
_menuFont = _disk->loadFont("slide");
_introFont = _disk->loadFont("intro");
diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp
index 852235ce34..a9889cc7af 100644
--- a/engines/parallaction/gfxbase.cpp
+++ b/engines/parallaction/gfxbase.cpp
@@ -152,22 +152,22 @@ void Gfx::freeCharacterObjects() {
freeDialogueObjects();
}
-void BackgroundInfo::loadGfxObjMask(const char *name, GfxObj *obj) {
+void BackgroundInfo::loadGfxObjMask(Parallaction *vm, const char *name, GfxObj *obj) {
debugC(1, kDebugGraphics, "BackgroundInfo::loadGfxObjMask(\"%s\")", name);
Common::Rect rect;
obj->getRect(0, rect);
- MaskBuffer *buf = _vm->_disk->loadMask(name, rect.width(), rect.height());
+ MaskBuffer *buf = vm->_disk->loadMask(name, rect.width(), rect.height());
obj->_maskId = addMaskPatch(buf);
obj->_hasMask = true;
}
-void BackgroundInfo::loadGfxObjPath(const char *name, GfxObj *obj) {
+void BackgroundInfo::loadGfxObjPath(Parallaction *vm, const char *name, GfxObj *obj) {
Common::Rect rect;
obj->getRect(0, rect);
- PathBuffer *buf = _vm->_disk->loadPath(name, rect.width(), rect.height());
+ PathBuffer *buf = vm->_disk->loadPath(name, rect.width(), rect.height());
obj->_pathId = addPathPatch(buf);
obj->_hasPath = true;
@@ -226,6 +226,11 @@ void Gfx::drawGfxObject(GfxObj *obj, Graphics::Surface &surf) {
rect.translate(x, y);
data = obj->getData(obj->frame);
+ // WORKAROUND: During the end credits, game scripts try to show a
+ // non-existing frame. We change it to an existing one here.
+ if (obj->frame == 14 && obj->getNum() == 9 && !strcmp(obj->getName(), "Dinor"))
+ obj->frame = 8;
+
if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) {
blt(rect, data, &surf, obj->layer, obj->scale, obj->transparentKey);
} else {
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index 9855830478..59cd02e6ef 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -80,11 +80,11 @@ void drawCircle(int xCenter, int yCenter, int radius, int color, void (*plotProc
Palette::Palette() {
- int gameType = _vm->getGameType();
+ int gameType = g_vm->getGameType();
if (gameType == GType_Nippon) {
_colors = 32;
- _hb = (_vm->getPlatform() == Common::kPlatformAmiga);
+ _hb = (g_vm->getPlatform() == Common::kPlatformAmiga);
} else
if (gameType == GType_BRA) {
_colors = 256;
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index f8cb4b3647..e9daabb194 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -377,14 +377,14 @@ public:
void toggleMaskPatch(uint id, int x, int y, bool apply);
uint16 getMaskLayer(uint16 z) const;
void finalizeMask();
- void loadGfxObjMask(const char *name, GfxObj *obj);
+ void loadGfxObjMask(Parallaction *vm, const char *name, GfxObj *obj);
// path management
bool hasPath();
uint addPathPatch(PathBuffer *patch);
void togglePathPatch(uint id, int x, int y, bool apply);
void finalizePath();
- void loadGfxObjPath(const char *name, GfxObj *obj);
+ void loadGfxObjPath(Parallaction *vm, const char *name, GfxObj *obj);
};
diff --git a/engines/parallaction/gui_ns.cpp b/engines/parallaction/gui_ns.cpp
index 3794aeae29..082c37f666 100644
--- a/engines/parallaction/gui_ns.cpp
+++ b/engines/parallaction/gui_ns.cpp
@@ -787,7 +787,7 @@ public:
}
destroyLabels();
- _engineFlags &= ~kEngineBlockInput;
+ g_engineFlags &= ~kEngineBlockInput;
return _helper->getState("selectcharacter");
}
diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp
index 453bf9849d..4fbd9b99cc 100644
--- a/engines/parallaction/input.cpp
+++ b/engines/parallaction/input.cpp
@@ -188,15 +188,15 @@ int Input::updateGameInput() {
int event = kEvNone;
if (!isMouseEnabled() ||
- (_engineFlags & kEngineBlockInput) ||
- (_engineFlags & kEngineWalking) ||
- (_engineFlags & kEngineChangeLocation)) {
+ (g_engineFlags & kEngineBlockInput) ||
+ (g_engineFlags & kEngineWalking) ||
+ (g_engineFlags & kEngineChangeLocation)) {
debugC(3, kDebugInput, "updateGameInput: input flags (mouse: %i, block: %i, walking: %i, changeloc: %i)",
isMouseEnabled(),
- (_engineFlags & kEngineBlockInput) == 0,
- (_engineFlags & kEngineWalking) == 0,
- (_engineFlags & kEngineChangeLocation) == 0
+ (g_engineFlags & kEngineBlockInput) == 0,
+ (g_engineFlags & kEngineWalking) == 0,
+ (g_engineFlags & kEngineChangeLocation) == 0
);
return event;
@@ -289,7 +289,7 @@ void Input::walkTo(const Common::Point &dest) {
bool Input::translateGameInput() {
- if (_engineFlags & kEnginePauseJobs) {
+ if (g_engineFlags & kEnginePauseJobs) {
return false;
}
@@ -312,7 +312,7 @@ bool Input::translateGameInput() {
// test if mouse is hovering on an interactive zone for the currently selected inventory item
ZonePtr z = _vm->hitZone(_activeItem._id, mousePos.x, mousePos.y);
- if (((_mouseButtons == kMouseLeftUp) && (_activeItem._id == 0) && ((_engineFlags & kEngineWalking) == 0)) && ((!z) || (ACTIONTYPE(z) != kZoneCommand))) {
+ if (((_mouseButtons == kMouseLeftUp) && (_activeItem._id == 0) && ((g_engineFlags & kEngineWalking) == 0)) && ((!z) || (ACTIONTYPE(z) != kZoneCommand))) {
walkTo(mousePos);
return true;
}
@@ -361,7 +361,7 @@ void Input::enterInventoryMode() {
if (hitCharacter) {
if (_activeItem._id != 0) {
_activeItem._index = (_activeItem._id >> 16) & 0xFFFF;
- _engineFlags |= kEngineDragging;
+ g_engineFlags |= kEngineDragging;
} else {
setArrowCursor();
}
@@ -384,9 +384,9 @@ void Input::exitInventoryMode() {
int pos = _vm->getHoverInventoryItem(mousePos.x, mousePos.y);
_vm->highlightInventoryItem(-1); // disable
- if ((_engineFlags & kEngineDragging)) {
+ if ((g_engineFlags & kEngineDragging)) {
- _engineFlags &= ~kEngineDragging;
+ g_engineFlags &= ~kEngineDragging;
ZonePtr z = _vm->hitZone(kZoneMerge, _activeItem._index, _vm->getInventoryItemIndex(pos));
if (z) {
diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk
index d65653cd92..36572a51df 100644
--- a/engines/parallaction/module.mk
+++ b/engines/parallaction/module.mk
@@ -1,6 +1,7 @@
MODULE := engines/parallaction
MODULE_OBJS := \
+ adlib.o \
balloons.o \
callables_br.o \
callables_ns.o \
diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp
index d3529c5dd9..50556c3ec4 100644
--- a/engines/parallaction/objects.cpp
+++ b/engines/parallaction/objects.cpp
@@ -203,7 +203,7 @@ Zone::Zone() {
}
Zone::~Zone() {
- _vm->_gfx->unregisterLabel(_label);
+ g_vm->_gfx->unregisterLabel(_label);
delete _label;
}
@@ -325,7 +325,7 @@ int16 ScriptVar::getValue() {
}
if (_flags & kParaRandom) {
- return (_vm->_rnd.getRandomNumber(65536) * _value) >> 16;
+ return (g_vm->_rnd.getRandomNumber(65536) * _value) >> 16;
}
error("Parameter is not an r-value");
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index 3b1b7d54a0..e6ef53aa78 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -33,12 +33,12 @@
#include "parallaction/walk.h"
namespace Parallaction {
-Parallaction *_vm = NULL;
+Parallaction *g_vm = NULL;
// public stuff
-char _saveData1[30] = { '\0' };
-uint32 _engineFlags = 0;
-uint32 _globalFlags = 0;
+char g_saveData1[30] = { '\0' };
+uint32 g_engineFlags = 0;
+uint32 g_globalFlags = 0;
// private stuff
@@ -48,7 +48,7 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam
// Setup mixer
syncSoundSettings();
- _vm = this;
+ g_vm = this;
DebugMan.addDebugChannel(kDebugDialogue, "dialogue", "Dialogues debug level");
DebugMan.addDebugChannel(kDebugParser, "parser", "Parser debug level");
DebugMan.addDebugChannel(kDebugDisk, "disk", "Disk debug level");
@@ -87,7 +87,7 @@ Parallaction::~Parallaction() {
Common::Error Parallaction::init() {
_gameType = getGameType();
- _engineFlags = 0;
+ g_engineFlags = 0;
_objectsNames = NULL;
_globalFlagsNames = NULL;
_location._hasSound = false;
@@ -129,13 +129,9 @@ GUI::Debugger *Parallaction::getDebugger() {
return _debugger;
}
-bool canScroll() {
- return (_vm->_gfx->_backgroundInfo->width > _vm->_screenWidth);
-}
-
void Parallaction::updateView() {
- if ((_engineFlags & kEnginePauseJobs) && (_input->_inputMode != Input::kInputModeInventory)) {
+ if ((g_engineFlags & kEnginePauseJobs) && (_input->_inputMode != Input::kInputModeInventory)) {
return;
}
@@ -147,14 +143,14 @@ void Parallaction::updateView() {
void Parallaction::pauseJobs() {
debugC(9, kDebugExec, "pausing jobs execution");
- _engineFlags |= kEnginePauseJobs;
+ g_engineFlags |= kEnginePauseJobs;
return;
}
void Parallaction::resumeJobs() {
debugC(9, kDebugExec, "resuming jobs execution");
- _engineFlags &= ~kEnginePauseJobs;
+ g_engineFlags &= ~kEnginePauseJobs;
return;
}
@@ -265,7 +261,7 @@ void Parallaction::runGameFrame(int event) {
if (shouldQuit())
return;
- if (_engineFlags & kEngineChangeLocation) {
+ if (g_engineFlags & kEngineChangeLocation) {
changeLocation();
}
@@ -900,14 +896,14 @@ void CharacterName::bind(const char *name) {
if (!_dummy) {
if (!strcmp(name, "donna")) {
- _engineFlags &= ~kEngineTransformedDonna;
+ g_engineFlags &= ~kEngineTransformedDonna;
} else {
- if (_engineFlags & kEngineTransformedDonna) {
+ if (g_engineFlags & kEngineTransformedDonna) {
_suffix = _suffixTras;
} else {
const char *s = strstr(name, "tras");
if (s) {
- _engineFlags |= kEngineTransformedDonna;
+ g_engineFlags |= kEngineTransformedDonna;
_suffix = _suffixTras;
end = s;
}
@@ -953,7 +949,7 @@ void Parallaction::beep() {
void Parallaction::scheduleLocationSwitch(const char *location) {
debugC(9, kDebugExec, "scheduleLocationSwitch(%s)\n", location);
_newLocationName = location;
- _engineFlags |= kEngineChangeLocation;
+ g_engineFlags |= kEngineChangeLocation;
}
} // End of namespace Parallaction
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 0d56b62e2f..2dbb0227d6 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -104,17 +104,17 @@ struct PARALLACTIONGameDescription;
-extern uint32 _engineFlags;
-extern char _saveData1[];
-extern uint32 _globalFlags;
-extern const char *_dinoName;
-extern const char *_donnaName;
-extern const char *_doughName;
-extern const char *_drkiName;
-extern const char *_minidinoName;
-extern const char *_minidonnaName;
-extern const char *_minidoughName;
-extern const char *_minidrkiName;
+extern uint32 g_engineFlags;
+extern char g_saveData1[];
+extern uint32 g_globalFlags;
+extern const char *g_dinoName;
+extern const char *g_donnaName;
+extern const char *g_doughName;
+extern const char *g_drkiName;
+extern const char *g_minidinoName;
+extern const char *g_minidonnaName;
+extern const char *g_minidoughName;
+extern const char *g_minidrkiName;
@@ -601,7 +601,7 @@ private:
void _c_password(void *);
};
-extern Parallaction *_vm;
+extern Parallaction *g_vm;
} // End of namespace Parallaction
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index 658a8e8795..07755fac5f 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -79,7 +79,7 @@ Common::Error Parallaction_br::init() {
_cmdExec = new CommandExec_br(this);
_programExec = new ProgramExec_br(this);
- _walker = new PathWalker_BR;
+ _walker = new PathWalker_BR(this);
_part = -1;
_nextPart = -1;
@@ -161,10 +161,10 @@ Common::Error Parallaction_br::go() {
// initCharacter();
- while (((_engineFlags & kEngineReturn) == 0) && (!shouldQuit())) {
+ while (((g_engineFlags & kEngineReturn) == 0) && (!shouldQuit())) {
runGame();
}
- _engineFlags &= ~kEngineReturn;
+ g_engineFlags &= ~kEngineReturn;
cleanupGame();
}
@@ -259,7 +259,7 @@ void Parallaction_br::cleanupGame() {
_countersNames = 0;
_numLocations = 0;
- _globalFlags = 0;
+ g_globalFlags = 0;
memset(_localFlags, 0, sizeof(_localFlags));
memset(_locationNames, 0, sizeof(_locationNames));
memset(_zoneFlags, 0, sizeof(_zoneFlags));
@@ -275,7 +275,7 @@ void Parallaction_br::changeLocation() {
cleanupGame();
// more cleanup needed for part changes (see also saveload)
- _globalFlags = 0;
+ g_globalFlags = 0;
cleanInventory(true);
strcpy(_characterName1, "null");
@@ -358,7 +358,7 @@ void Parallaction_br::changeLocation() {
// TODO: implement the music commands which control music execution
_soundMan->execute(SC_PLAYMUSIC);
- _engineFlags &= ~kEngineChangeLocation;
+ g_engineFlags &= ~kEngineChangeLocation;
_newLocationName.clear();
_nextPart = -1;
}
@@ -548,7 +548,7 @@ void Parallaction_br::scheduleWalk(int16 x, int16 y, bool fromUser) {
}
}
- _engineFlags |= kEngineWalking;
+ g_engineFlags |= kEngineWalking;
}
void Parallaction_br::setFollower(const Common::String &name) {
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index 0b92db1f0a..d33be0aa47 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -182,7 +182,7 @@ Common::Error Parallaction_ns::init() {
_cmdExec = new CommandExec_ns(this);
_programExec = new ProgramExec_ns(this);
- _walker = new PathWalker_NS;
+ _walker = new PathWalker_NS(this);
_sarcophagusDeltaX = 0;
_movingSarcophagus = false;
@@ -310,6 +310,7 @@ void Parallaction_ns::changeBackground(const char* background, const char* mask,
_system->delayMillis(20);
_gfx->setPalette(pal);
_gfx->updateScreen();
+ return;
}
if (path == 0) {
@@ -382,8 +383,8 @@ void Parallaction_ns::changeLocation() {
changeCharacter(locname.character());
}
- strcpy(_saveData1, locname.location());
- parseLocation(_saveData1);
+ strcpy(g_saveData1, locname.location());
+ parseLocation(g_saveData1);
if (_location._startPosition.x != -1000) {
_char._ani->setX(_location._startPosition.x);
@@ -399,7 +400,7 @@ void Parallaction_ns::changeLocation() {
// BUG #1837503: kEngineChangeLocation flag must be cleared *before* commands
// and acommands are executed, so that it can be set again if needed.
- _engineFlags &= ~kEngineChangeLocation;
+ g_engineFlags &= ~kEngineChangeLocation;
_cmdExec->run(_location._commands);
@@ -412,6 +413,11 @@ void Parallaction_ns::changeLocation() {
if (!_intro) {
_input->setMouseState(oldMouseState);
+ // WORKAROUND: Fix a script bug in the Multilingual DOS version of
+ // Nippon Safes: the mouse cursor is incorrectly hidden outside the
+ // cave at the end of the game. Fix it here.
+ if (!strcmp(_location._name, "ingressocav"))
+ _input->setMouseState(MOUSE_ENABLED_SHOW);
}
debugC(1, kDebugExec, "changeLocation() done");
@@ -526,10 +532,10 @@ void Parallaction_ns::cleanupGame() {
_soundManI->stopMusic();
_inTestResult = false;
- _engineFlags &= ~kEngineTransformedDonna;
+ g_engineFlags &= ~kEngineTransformedDonna;
_numLocations = 0;
- _globalFlags = 0;
+ g_globalFlags = 0;
memset(_localFlags, 0, sizeof(_localFlags));
memset(_locationNames, 0, sizeof(_locationNames));
@@ -553,7 +559,7 @@ void Parallaction_ns::scheduleWalk(int16 x, int16 y, bool fromUser) {
}
_walker->buildPath(a, x, y);
- _engineFlags |= kEngineWalking;
+ g_engineFlags |= kEngineWalking;
}
}// namespace Parallaction
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
index 0904dbf655..e7f1b1b1ed 100644
--- a/engines/parallaction/parser_br.cpp
+++ b/engines/parallaction/parser_br.cpp
@@ -767,10 +767,10 @@ void LocationParser_br::parseGetData(ZonePtr z) {
data->_gfxobj = obj;
} else
if (!scumm_stricmp(_tokens[0], "mask")) {
- _out->_info->loadGfxObjMask(_tokens[1], data->_gfxobj);
+ _out->_info->loadGfxObjMask(_vm, _tokens[1], data->_gfxobj);
} else
if (!scumm_stricmp(_tokens[0], "path")) {
- _out->_info->loadGfxObjPath(_tokens[1], data->_gfxobj);
+ _out->_info->loadGfxObjPath(_vm, _tokens[1], data->_gfxobj);
} else
if (!scumm_stricmp(_tokens[0], "icon")) {
data->_getIcon = 4 + _vm->_objectsNames->lookup(_tokens[1]);
diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp
index f1d1db53e9..41ff74f0b4 100644
--- a/engines/parallaction/parser_ns.cpp
+++ b/engines/parallaction/parser_ns.cpp
@@ -246,7 +246,7 @@ DECLARE_ANIM_PARSER(file) {
char vC8[200];
strcpy(vC8, _tokens[1]);
- if (_engineFlags & kEngineTransformedDonna) {
+ if (g_engineFlags & kEngineTransformedDonna) {
if (!scumm_stricmp(_tokens[1], "donnap") || !scumm_stricmp(_tokens[1], "donnapa")) {
strcat(vC8, "tras");
}
diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp
index 8de2d89b18..2ecc5377a4 100644
--- a/engines/parallaction/saveload.cpp
+++ b/engines/parallaction/saveload.cpp
@@ -88,7 +88,7 @@ void SaveLoad_ns::doLoadGame(uint16 slot) {
_vm->_score = atoi(s.c_str());
s = f->readLine();
- _globalFlags = atoi(s.c_str());
+ g_globalFlags = atoi(s.c_str());
s = f->readLine();
_vm->_numLocations = atoi(s.c_str());
@@ -151,7 +151,7 @@ void SaveLoad_ns::doSaveGame(uint16 slot, const char* name) {
sprintf(s, "%s\n", _vm->_char.getFullName());
f->writeString(s);
- sprintf(s, "%s\n", _saveData1);
+ sprintf(s, "%s\n", g_saveData1);
f->writeString(s);
sprintf(s, "%d\n", _vm->_char._ani->getX());
f->writeString(s);
@@ -159,7 +159,7 @@ void SaveLoad_ns::doSaveGame(uint16 slot, const char* name) {
f->writeString(s);
sprintf(s, "%d\n", _vm->_score);
f->writeString(s);
- sprintf(s, "%u\n", _globalFlags);
+ sprintf(s, "%u\n", g_globalFlags);
f->writeString(s);
sprintf(s, "%d\n", _vm->_numLocations);
diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h
index e875e69334..e12e50e278 100644
--- a/engines/parallaction/sound.h
+++ b/engines/parallaction/sound.h
@@ -33,6 +33,7 @@
#define PATH_LEN 200
class MidiParser;
+class MidiDriver;
namespace Parallaction {
@@ -41,6 +42,7 @@ class MidiPlayer;
class Parallaction_br;
class MidiPlayer_MSC;
+MidiDriver *createAdLibDriver();
class SoundManImpl {
public:
diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp
index 0925e55309..ad510eb1f1 100644
--- a/engines/parallaction/sound_br.cpp
+++ b/engines/parallaction/sound_br.cpp
@@ -91,20 +91,20 @@ public:
};
void MidiParser_MSC::parseMetaEvent(EventInfo &info) {
- uint8 type = read1(_position._play_pos);
- uint8 len = read1(_position._play_pos);
+ uint8 type = read1(_position._playPos);
+ uint8 len = read1(_position._playPos);
info.ext.type = type;
info.length = len;
info.ext.data = 0;
if (type == 0x51) {
- info.ext.data = _position._play_pos;
+ info.ext.data = _position._playPos;
} else {
warning("unknown meta event 0x%02X", type);
info.ext.type = 0;
}
- _position._play_pos += len;
+ _position._playPos += len;
}
void MidiParser_MSC::parseMidiEvent(EventInfo &info) {
@@ -116,13 +116,13 @@ void MidiParser_MSC::parseMidiEvent(EventInfo &info) {
case 0xA:
case 0xB:
case 0xE:
- info.basic.param1 = read1(_position._play_pos);
- info.basic.param2 = read1(_position._play_pos);
+ info.basic.param1 = read1(_position._playPos);
+ info.basic.param2 = read1(_position._playPos);
break;
case 0xC:
case 0xD:
- info.basic.param1 = read1(_position._play_pos);
+ info.basic.param1 = read1(_position._playPos);
info.basic.param2 = 0;
break;
@@ -135,9 +135,9 @@ void MidiParser_MSC::parseMidiEvent(EventInfo &info) {
}
void MidiParser_MSC::parseNextEvent(EventInfo &info) {
- info.start = _position._play_pos;
+ info.start = _position._playPos;
- if (_position._play_pos >= _trackEnd) {
+ if (_position._playPos >= _trackEnd) {
// fake an end-of-track meta event
info.delta = 0;
info.event = 0xFF;
@@ -146,8 +146,9 @@ void MidiParser_MSC::parseNextEvent(EventInfo &info) {
return;
}
- info.delta = readVLQ(_position._play_pos);
- info.event = read1(_position._play_pos);
+ info.length = 0;
+ info.delta = readVLQ(_position._playPos);
+ info.event = read1(_position._playPos);
if (info.event == 0xFF) {
parseMetaEvent(info);
@@ -155,7 +156,7 @@ void MidiParser_MSC::parseNextEvent(EventInfo &info) {
}
if (info.event < 0x80) {
- _position._play_pos--;
+ _position._playPos--;
info.event = _lastEvent;
}
@@ -185,7 +186,7 @@ bool MidiParser_MSC::loadMusic(byte *data, uint32 size) {
_lastEvent = 0;
_trackEnd = data + size;
- _num_tracks = 1;
+ _numTracks = 1;
_tracks[0] = pos;
setTempo(500000);
@@ -224,7 +225,12 @@ MidiPlayer_MSC::MidiPlayer_MSC()
: _paused(false) {
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- _driver = MidiDriver::createMidi(dev);
+ const MusicType musicType = MidiDriver::getMusicType(dev);
+ if (musicType == MT_ADLIB) {
+ _driver = createAdLibDriver();
+ } else {
+ _driver = MidiDriver::createMidi(dev);
+ }
assert(_driver);
int ret = _driver->open();
diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp
index dcc71e4f2f..0ee3d73556 100644
--- a/engines/parallaction/sound_ns.cpp
+++ b/engines/parallaction/sound_ns.cpp
@@ -168,13 +168,13 @@ void DosSoundMan_ns::playCharacterMusic(const char *character) {
char *name = const_cast<char *>(character);
const char *newMusicFile = 0;
- if (!scumm_stricmp(name, _dinoName)) {
+ if (!scumm_stricmp(name, g_dinoName)) {
newMusicFile = "dino";
} else
- if (!scumm_stricmp(name, _donnaName)) {
+ if (!scumm_stricmp(name, g_donnaName)) {
newMusicFile = "donna";
} else
- if (!scumm_stricmp(name, _doughName)) {
+ if (!scumm_stricmp(name, g_doughName)) {
newMusicFile = "nuts";
} else {
warning("unknown character '%s' in DosSoundMan_ns_ns::playCharacterMusic", character);
diff --git a/engines/parallaction/staticres.cpp b/engines/parallaction/staticres.cpp
index 73e78cae3c..f09b1241bc 100644
--- a/engines/parallaction/staticres.cpp
+++ b/engines/parallaction/staticres.cpp
@@ -89,14 +89,14 @@ byte Input::_resMouseArrow_BR_Amiga[512] = {
/*
This palette snippet is used for animations in Big Red Adventure.
*/
-byte _braAmigaFramesDefaultPalette[48] = {
+byte braAmigaFramesDefaultPalette[48] = {
0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0xFF, 0xE0, 0xCF, 0x7F, 0x7F, 0x7F, 0xD9, 0x9C, 0x84, 0x00,
0x9E, 0xF0, 0x91, 0xCC, 0x36, 0xFF, 0x6A, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0x11, 0xB0, 0xEE,
0xF0, 0xFF, 0x17, 0x3D, 0x18, 0xAC, 0x3A, 0xB0, 0x00, 0x00, 0x7D, 0x00, 0x00, 0xFF, 0xA8, 0xFF,
};
-byte _amigaTopazFont[2600] = {
+byte amigaTopazFont[2600] = {
0x00, 0x00, 0x03, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x79, 0x00, 0x00, 0x03, 0xe9, 0x00, 0x00, 0x02, 0x79,
0x70, 0xff, 0x4e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
@@ -263,7 +263,7 @@ byte _amigaTopazFont[2600] = {
};
-const char *_callableNamesRes_ns[] = {
+const char *callableNamesRes_ns[] = {
"Projector",
"HBOff",
"StartIntro",
@@ -292,7 +292,7 @@ const char *_callableNamesRes_ns[] = {
};
-const char *_callableNamesRes_br[] = {
+const char *callableNamesRes_br[] = {
"blufade",
"resetpalette",
"ferrcycle",
@@ -301,15 +301,15 @@ const char *_callableNamesRes_br[] = {
"password"
};
-const char *_dinoName = "dino";
-const char *_donnaName = "donna";
-const char *_doughName = "dough";
-const char *_drkiName = "drki";
+const char *g_dinoName = "dino";
+const char *g_donnaName = "donna";
+const char *g_doughName = "dough";
+const char *g_drkiName = "drki";
-const char *_minidinoName = "minidino";
-const char *_minidonnaName = "minidonna";
-const char *_minidoughName = "minidough";
-const char *_minidrkiName = "minidrki";
+const char *g_minidinoName = "minidino";
+const char *g_minidonnaName = "minidonna";
+const char *g_minidoughName = "minidough";
+const char *g_minidrkiName = "minidrki";
#define CALLABLE_NS(x) &Parallaction_ns::x
@@ -391,7 +391,7 @@ const Parallaction_br::Callable Parallaction_br::_amigaCallables[] = {
void Parallaction_ns::initResources() {
- _callableNames = new Table(ARRAYSIZE(_callableNamesRes_ns), _callableNamesRes_ns);
+ _callableNames = new Table(ARRAYSIZE(callableNamesRes_ns), callableNamesRes_ns);
_localFlagNames = new FixedTable(NUM_LOCATIONS, 1);
_localFlagNames->addData("visited");
@@ -406,7 +406,7 @@ void Parallaction_ns::initResources() {
void Parallaction_br::initResources() {
- _callableNames = new Table(ARRAYSIZE(_callableNamesRes_br), _callableNamesRes_br);
+ _callableNames = new Table(ARRAYSIZE(callableNamesRes_br), callableNamesRes_br);
_localFlagNames = new FixedTable(NUM_LOCATIONS, 2);
_localFlagNames->addData("visited");
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index 53237db4ef..19162cd7db 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -55,27 +55,27 @@ WalkFrames _char24WalkFrames_NS = {
};
static int getPathWidth() {
- if (!_vm->_gfx->_backgroundInfo->_path) {
+ if (!g_vm->_gfx->_backgroundInfo->_path) {
warning("getPathWidth() _path is NULL!");
return 0;
} else
- return _vm->_gfx->_backgroundInfo->_path->w;
+ return g_vm->_gfx->_backgroundInfo->_path->w;
}
static int getPathHeight() {
- if (!_vm->_gfx->_backgroundInfo->_path) {
+ if (!g_vm->_gfx->_backgroundInfo->_path) {
warning("getPathHeight() _path is NULL!");
return 0;
} else
- return _vm->_gfx->_backgroundInfo->_path->h;
+ return g_vm->_gfx->_backgroundInfo->_path->h;
}
static bool isPathClear(uint16 x, uint16 y) {
- if (!_vm->_gfx->_backgroundInfo->_path) {
+ if (!g_vm->_gfx->_backgroundInfo->_path) {
warning("isPathClear() _path is NULL!");
return false;
} else
- return (_vm->_gfx->_backgroundInfo->_path->getValue(x, y) ? true : false);
+ return (g_vm->_gfx->_backgroundInfo->_path->getValue(x, y) ? true : false);
}
// adjusts position towards nearest walkable point
@@ -306,7 +306,7 @@ void PathWalker_NS::checkDoor(const Common::Point &foot) {
}
void PathWalker_NS::finalizeWalk() {
- _engineFlags &= ~kEngineWalking;
+ g_engineFlags &= ~kEngineWalking;
Common::Point foot;
_a->getFoot(foot);
@@ -316,7 +316,7 @@ void PathWalker_NS::finalizeWalk() {
}
void PathWalker_NS::walk() {
- if ((_engineFlags & kEngineWalking) == 0) {
+ if ((g_engineFlags & kEngineWalking) == 0) {
return;
}
@@ -382,7 +382,7 @@ void PathWalker_NS::updateDirection(const Common::Point& pos, const Common::Poin
_a->setF(frames->firstWalkFrame[_direction] + (_step / frames->frameRepeat[_direction]) % frames->numWalkFrames[_direction]);
}
-PathWalker_NS::PathWalker_NS() : _direction(WALK_DOWN), _step(0) {
+PathWalker_NS::PathWalker_NS(Parallaction *vm) : _direction(WALK_DOWN), _step(0), _vm(vm) {
}
bool PathWalker_BR::directPathExists(const Common::Point &from, const Common::Point &to) {
@@ -481,7 +481,7 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) {
}
void PathWalker_BR::finalizeWalk(State &s) {
- _engineFlags &= ~kEngineWalking;
+ g_engineFlags &= ~kEngineWalking;
Common::Point foot;
_character._a->getFoot(foot);
@@ -508,8 +508,8 @@ void PathWalker_BR::finalizeWalk(State &s) {
#if 0
// TODO: Input::walkTo must be extended to support destination frame in addition to coordinates
- if (_engineFlags & FINAL_WALK_FRAME) { // this flag is set in readInput()
- _engineFlags &= ~FINAL_WALK_FRAME;
+ if (g_engineFlags & FINAL_WALK_FRAME) { // this flag is set in readInput()
+ g_engineFlags &= ~FINAL_WALK_FRAME;
_ch._a->_frame = _moveToF; // from readInput()...
} else {
_ch._a->_frame = _dirFrame; // from walk()
@@ -523,7 +523,7 @@ void PathWalker_BR::finalizeWalk(State &s) {
}
void PathWalker_BR::walk() {
- if ((_engineFlags & kEngineWalking) == 0) {
+ if ((g_engineFlags & kEngineWalking) == 0) {
return;
}
@@ -714,7 +714,7 @@ void PathWalker_BR::doWalk(State &s) {
}
}
-PathWalker_BR::PathWalker_BR() {
+PathWalker_BR::PathWalker_BR(Parallaction *vm) : _vm(vm) {
_character._active = false;
_character._step = 0;
_follower._active = false;
diff --git a/engines/parallaction/walk.h b/engines/parallaction/walk.h
index 6796991f9d..ae6db6eaf1 100644
--- a/engines/parallaction/walk.h
+++ b/engines/parallaction/walk.h
@@ -49,8 +49,10 @@ class PathWalker_NS {
void checkDoor(const Common::Point &foot);
void updateDirection(const Common::Point& pos, const Common::Point& to);
+ Parallaction *_vm;
+
public:
- PathWalker_NS();
+ PathWalker_NS(Parallaction *vm);
void buildPath(AnimationPtr a, uint16 x, uint16 y);
void walk();
@@ -79,8 +81,10 @@ class PathWalker_BR {
void doWalk(State &s);
void checkTrap(const Common::Point &p);
+ Parallaction *_vm;
+
public:
- PathWalker_BR();
+ PathWalker_BR(Parallaction *vm);
~PathWalker_BR() { }
void setCharacterPath(AnimationPtr a, uint16 x, uint16 y);