1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "sci/sci.h"
24 
25 #include "common/file.h"
26 #include "common/system.h"
27 #include "common/textconsole.h"
28 
29 #include "audio/softsynth/fmtowns_pc98/pc98_audio.h"
30 
31 #include "sci/resource/resource.h"
32 #include "sci/sound/drivers/mididriver.h"
33 
34 /*	PC-98 sound driver for:
35 	Quest for Glory 1		SCI_VERSION_0_LATE		first driver type
36 	Police Quest 2			SCI_VERSION_0_LATE		second driver type
37 	Castle of Dr. Brain		SCI_VERSION_1_LATE		third driver type
38 	Space Quest IV			SCI_VERSION_1_LATE		third driver type
39 	King's Quest V			SCI_VERSION_1_LATE		latest driver type
40 */
41 
42 namespace Sci {
43 
44 class MidiPart_PC9801;
45 class SoundChannel_PC9801 {
46 public:
47 	SoundChannel_PC9801(PC98AudioCore *pc98a, MidiPart_PC9801 **parts, SciVersion version, int type, SciSpan<const uint8> instrumentData, bool &soundOn);
48 	virtual ~SoundChannel_PC9801();
49 
50 	void noteOff();
51 	void noteOn(uint8 note, uint8 velo);
52 
53 	virtual void processNoteEvent(uint8 note, bool soundOn);
54 	void update();
55 	void setVolume(uint8 volume);
56 
57 	virtual void reset();
toggleNoiseGenerator(bool)58 	virtual void toggleNoiseGenerator(bool) {}
59 
getType() const60 	int getType() const { return _type; }
61 
62 	uint8 _assign;
63 	uint8 _note;
64 	uint8 _sustain;
65 	uint16 _duration;
66 
67 protected:
68 	enum ChannelStatusFlags {
69 		kChanVbrEnable = 0x01,
70 		kChanVbrRestartEnv = 0x02,
71 		kChanKeyOn = 0x04,
72 		kChanNgEnable = 0x08,
73 		kChanNgRestartEnv = 0x10,
74 		kChanNgDecrease = 0x20,
75 		kChanVbrMode = 0x40,
76 		kChanVbrDecrease = 0x80
77 	};
78 
79 	int recalculateFrequency(uint16 note, uint16 modifier, uint8 *destOctaveBlock, uint16 *destFrequency, uint8 *destVbrFrequencyModifier);
80 	uint8 getVolume();
81 	virtual void processSounds();
82 	void programChangeInit(SciSpan<const uint8> &data);
83 	void writeReg(uint8 part, uint8 reg, uint8 val);
84 
85 	int8 _transpose;
86 	uint8 _vbrInitialDelay;
87 	uint8 _vbrEnvelopeTimer;
88 	uint8 _vbrEnvelopeSpeed;
89 
90 	uint16 _frequencyCourse;
91 	uint8 _frequencyBlock;
92 	uint8 _frequencyNoteModifier;
93 
94 	uint8 _vbrDepthIncr;
95 	uint8 _vbrDecrTime;
96 	uint8 _vbrDepthDecr;
97 	uint8 _vbrIncrTime;
98 	uint8 _vbrSensitivity;
99 	uint16 _vbrIncrStep;
100 	uint16 _vbrDecrStep;
101 	uint8 _vbrModulationTimer;
102 	uint16 _vbrFrequencyModifier;
103 	uint8 _vbrCur;
104 	uint8 _flags;
105 
106 	const uint16 *_noteFrequency;
107 	const uint16 *_noteFrequencyModifier;
108 
109 	SciSpan<const uint8> _instrumentData;
110 	const SciVersion _version;
111 
112 private:
113 	virtual void programChange(uint8 program) = 0;
114 	virtual bool prepareFrequencyAndVolume(bool updateVolume);
115 	virtual void sendSoundOnOff(bool soundOn) = 0;
116 	virtual void sendFrequency() = 0;
117 	virtual void sendVolume() = 0;
118 
119 	uint8 _velo;
120 	uint8 _volume;
121 	uint8 _program;
122 	bool &_soundOn;
123 
124 	MidiPart_PC9801 **_parts;
125 	PC98AudioCore *_pc98a;
126 	const int _type;
127 };
128 
129 class SoundChannel_PC9801_FM4OP : public SoundChannel_PC9801 {
130 public:
131 	SoundChannel_PC9801_FM4OP(uint8 id, PC98AudioCore *pc98a, MidiPart_PC9801 **parts, SciVersion version, SciSpan<const uint8> instrumentData, uint8 patchSize, bool &soundOn);
~SoundChannel_PC9801_FM4OP()132 	~SoundChannel_PC9801_FM4OP() override {}
133 
134 private:
135 	void programChange(uint8 program) override;
136 	void sendSoundOnOff(bool soundOn) override;
137 	void sendVolume() override;
138 	void sendFrequency() override;
139 
140 	uint8 _operatorLevel[4];
141 	uint8 _carrier;
142 	uint8 _operatorFlags;
143 
144 	const uint8 _regPrt;
145 	const uint8 _regOffs;
146 	const uint8 _patchSize;
147 };
148 
149 class SoundChannel_PC9801_FM2OP : public SoundChannel_PC9801 {
150 public:
151 	SoundChannel_PC9801_FM2OP(uint8 id, PC98AudioCore *pc98a, MidiPart_PC9801 **parts,  SciVersion version, SciSpan<const uint8> instrumentData, uint8 patchSize, bool &soundOn);
~SoundChannel_PC9801_FM2OP()152 	~SoundChannel_PC9801_FM2OP() override {}
153 
154 	void processNoteEvent(uint8 note, bool soundOn) override;
155 	void reset() override;
156 
157 private:
158 	void programChange(uint8 program) override;
159 	bool prepareFrequencyAndVolume(bool updateVolume) override;
160 	void processSounds() override;
161 	void sendSoundOnOff(bool soundOn) override;
162 	void sendVolume() override;
163 	void sendFrequency() override;
164 
165 	uint8 _operatorLevel[2];
166 	uint8 _operatorFrqIndex[2];
167 	uint16 _frequencyCourse2;
168 	uint8 _frequencyNoteModifier2;
169 	int16 _vbrFrequencyModifier2;
170 	uint16 _vbrIncrStep2;
171 	uint16 _vbrDecrStep2;
172 	uint8 _vbrCur2;
173 	static uint8 _activeOperators;
174 
175 	const uint16 *_opFreqOffset;
176 	const uint8 _patchOffset;
177 	const uint8 _regPrt;
178 	const uint8 _regOffs;
179 	const uint8 _patchSize;
180 };
181 
182 class SoundChannel_PC9801_SSG : public SoundChannel_PC9801 {
183 public:
184 	SoundChannel_PC9801_SSG(uint8 id, PC98AudioCore *pc98a, MidiPart_PC9801 **parts, SciVersion version, SciSpan<const uint8> instrumentData, uint8 patchOffset, uint8 patchSize, bool &soundOn);
~SoundChannel_PC9801_SSG()185 	~SoundChannel_PC9801_SSG() override {}
186 	void reset() override;
187 	void toggleNoiseGenerator(bool enable) override;
188 
189 private:
190 	enum {
191 		kEnvSSG_silent = 0x00,
192 		kEnvSSG_decay = 0x01,
193 		kEnvSSG_sustain = 0x02,
194 		kEnvSSG_attack = 0x03,
195 		kEnvSSG_keyOn = 0x10
196 	};
197 
198 	void programChange(uint8 program) override;
199 	void processSounds() override;
200 	void sendSoundOnOff(bool soundOn) override;
201 	void sendVolume() override;
202 	void sendFrequency() override;
203 	void updateNg();
204 	void sendActiveChannelsStatus();
205 
206 	uint8 _instrumentChanMask;
207 	uint8 _chanDisableMask;
208 	uint8 _chanEnableMask1;
209 	uint8 _chanEnableMask2;
210 	uint8 _currentLevel;
211 	uint8 _ngPhaseStep;
212 	uint8 _ngPhase;
213 	uint8 _ngEnvelopeTimer;
214 	uint8 _ngSpeed;
215 	uint8 _ssgEnvelopeTimer;
216 	uint8 _ssgLevel;
217 	uint8 _ssgSpeed;
218 	uint8 _ssgEnvelopeState;
219 	bool _ccngEnabled;
220 
221 	static uint8 _activeChannnelsStatus;
222 	SciSpan<const uint8> _selectedInstrument;
223 
224 	const uint8 *_ngFreq;
225 	const uint8 _regOffs;
226 	const uint8 _patchOffset;
227 	const uint8 _patchSize;
228 };
229 
230 class MidiPart_PC9801 {
231 public:
232 	MidiPart_PC9801(uint8 id, SoundChannel_PC9801 **channels, uint8 numChan, SciVersion version);
~MidiPart_PC9801()233 	~MidiPart_PC9801() {}
234 
235 	void noteOff(uint8 note);
236 	void noteOn(uint8 note, uint8 velo);
237 	void controlChangeVolume(uint8 vol);
238 	void controlChangeSustain(uint8 sus);
239 	void controlChangePolyphony(uint8 numChan);
240 	void controlChangeNoiseGenerator(uint8 status);
241 	void controlChangeAllNotesOff();
242 	void programChange(uint8 prg);
243 	void pitchBend(int16 val);
244 
245 	void addChannels(int num, int resetMissingChannels = -1, int channelType = -1);
246 	void dropChannels(int num);
247 
getCurrentProgram() const248 	uint8 getCurrentProgram() const { return _program; }
getCurrentVolume() const249 	uint8 getCurrentVolume() const { return _volume; }
getCurrentPitchBend() const250 	uint16 getCurrentPitchBend() const { return _pitchBend; }
getMissingChannels() const251 	uint8 getMissingChannels() const { return _chanMissing; }
252 
253 private:
254 	int allocateChannel();
255 	void assignFreeChannels();
256 
257 	uint8 _id;
258 	uint8 _program;
259 	uint8 _volume;
260 	uint8 _sustain;
261 	uint16 _pitchBend;
262 	uint8 _outChan;
263 	uint8 _chanMissing;
264 
265 	SoundChannel_PC9801 **_chan;
266 	const SciVersion _version;
267 	const int _numChan;
268 	const uint8 _noteRangeLow;
269 	const uint8 _noteRangeHigh;
270 };
271 
272 class MidiDriver_PC9801 : public MidiDriver, public PC98AudioPluginDriver {
273 public:
274 	enum {
275 		MIDI_PROP_PLAYSWITCH = 1,
276 		MIDI_PROP_POLYPHONY = 2,
277 		MIDI_PROP_CHANNEL_ID = 3
278 	};
279 
280 	MidiDriver_PC9801(Audio::Mixer *mixer, SciVersion version);
281 	~MidiDriver_PC9801() override;
282 
283 	int open() override;
isOpen() const284 	bool isOpen() const override { return _isOpen; }
285 	void close() override;
286 
287 	void send(uint32 b) override;
288 	static void assignFreeChannels(int num);
289 	uint32 property(int prop, uint32 param) override;
290 	void initTrack(SciSpan<const byte> &header);
291 
292 	void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) override;
293 	uint32 getBaseTempo() override;
allocateChannel()294 	MidiChannel *allocateChannel() override { return 0; }
getPercussionChannel()295 	MidiChannel *getPercussionChannel() override { return 0; }
296 
297 	void timerCallbackB() override;
298 
299 private:
300 	bool loadInstruments(const SciSpan<const uint8> &data);
301 	void updateParser();
302 	void updateChannels();
303 	void reset();
304 
305 	Common::TimerManager::TimerProc _timerProc;
306 	void *_timerProcPara;
307 
308 	static MidiPart_PC9801 **_parts;
309 	SoundChannel_PC9801 **_chan;
310 	Common::SpanOwner<SciSpan<uint8> > _instrumentData;
311 
312 	uint8 _masterVolume;
313 	bool _soundOn;
314 
315 	uint8 _numChan;
316 	uint8 _ssgPatchOffset;
317 	uint8 _patchSize;
318 
319 	uint8 _internalVersion;
320 	const uint8 _playID;
321 	const uint8 _channelMask1;
322 	uint8 _channelMask2;
323 	uint8 _polyphony;
324 
325 	bool _isOpen;
326 	bool _ready;
327 
328 	const uint16 _baseTempo;
329 
330 	PC98AudioCore *_pc98a;
331 	Audio::Mixer *_mixer;
332 	const SciVersion _version;
333 };
334 
335 class MidiPlayer_PC9801 : public MidiPlayer {
336 public:
337 	enum {
338 		MIDI_PROP_PLAYSWITCH = 1,
339 		MIDI_PROP_POLYPHONY = 2,
340 		MIDI_PROP_CHANNEL_ID = 3
341 	};
342 
343 	MidiPlayer_PC9801(SciVersion version);
344 	~MidiPlayer_PC9801() override;
345 
346 	bool hasRhythmChannel() const override;
347 	byte getPlayId() const override;
348 	int getPolyphony() const override;
349 	void playSwitch(bool play) override;
350 
351 	void initTrack(SciSpan<const byte> &trackData) override;
352 };
353 
SoundChannel_PC9801(PC98AudioCore * pc98a,MidiPart_PC9801 ** parts,SciVersion version,int type,SciSpan<const uint8> instrumentData,bool & soundOn)354 SoundChannel_PC9801::SoundChannel_PC9801(PC98AudioCore *pc98a, MidiPart_PC9801 **parts, SciVersion version, int type, SciSpan<const uint8> instrumentData, bool &soundOn)
355 	: _pc98a(pc98a), _parts(parts), _version(version), _type(type), _instrumentData(instrumentData), _soundOn(soundOn), _assign(0xff), _note(0xff), _velo(0),
356 	_volume(0), _transpose(0), _sustain(0), _duration(0), _program(0xff), _vbrInitialDelay(0), _vbrEnvelopeTimer(0),
357 	_vbrEnvelopeSpeed(0), _vbrDepthIncr(0), _vbrDecrTime(0), _vbrDepthDecr(0), _vbrIncrTime(0), _vbrSensitivity(0),
358 	_vbrFrequencyModifier(0), _vbrIncrStep(0), _vbrDecrStep(0), _vbrModulationTimer(0), _flags(0), _vbrCur(0x80),
359 	_frequencyBlock(0), _frequencyCourse(0), _frequencyNoteModifier(0) {
360 
361 	static const uint16 courseV0[] = { 0x269, 0x28D, 0x2B5, 0x2DE, 0x30A, 0x339, 0x368, 0x39D, 0x3D4, 0x40E, 0x44A, 0x48C };
362 	static const uint16 courseV1[] = { 0x26A, 0x28E, 0x2B5, 0x2DF, 0x30A, 0x339, 0x36A, 0x39E, 0x3D5, 0x40F, 0x44D, 0x48F };
363 	static const uint16 fine[] = { 0x24, 0x27, 0x2A, 0x2B, 0x2F, 0x31, 0x34, 0x37, 0x3A, 0x3E, 0x42, 0x45 };
364 
365 	_noteFrequency = (version > SCI_VERSION_0_LATE) ? courseV1 : courseV0;
366 	_noteFrequencyModifier = fine;
367 }
368 
~SoundChannel_PC9801()369 SoundChannel_PC9801::~SoundChannel_PC9801() {
370 	_instrumentData.clear();
371 }
372 
noteOff()373 void SoundChannel_PC9801::noteOff() {
374 	if (_sustain)
375 		return;
376 
377 	processNoteEvent(_note, false);
378 
379 	_note = 0xFF;
380 	_duration = 0;
381 }
382 
noteOn(uint8 note,uint8 velo)383 void SoundChannel_PC9801::noteOn(uint8 note, uint8 velo) {
384 	_duration = 0;
385 
386 	if (_program != _parts[_assign]->getCurrentProgram() && _soundOn) {
387 		_program = _parts[_assign]->getCurrentProgram();
388 		programChange(_program);
389 	}
390 
391 	if (_version > SCI_VERSION_0_LATE) {
392 		velo >>= 1;
393 		if (velo > 63)
394 			velo = 63;
395 		_velo = velo;
396 	}
397 
398 	processNoteEvent(note, true);
399 }
400 
processNoteEvent(uint8 note,bool soundOn)401 void SoundChannel_PC9801::processNoteEvent(uint8 note, bool soundOn) {
402 	if (_note != note) {
403 		_note = note;
404 		_vbrEnvelopeTimer = _vbrInitialDelay;
405 		_vbrFrequencyModifier = 0;
406 		_vbrCur = 0x80;
407 		_flags |= kChanVbrRestartEnv;
408 	}
409 
410 	if (!prepareFrequencyAndVolume(soundOn))
411 		soundOn = false;
412 
413 	sendSoundOnOff(soundOn);
414 }
415 
update()416 void SoundChannel_PC9801::update() {
417 	processSounds();
418 	if (_note != 0xFF)
419 		_duration++;
420 }
421 
setVolume(uint8 volume)422 void SoundChannel_PC9801::setVolume(uint8 volume) {
423 	static const uint8 volumeTable[] = { 0x7F, 0x7F, 0x30, 0x30, 0x28, 0x28, 0x20, 0x20, 0x18, 0x18, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00 };
424 	assert(volume < 16);
425 	_volume = volumeTable[volume];
426 }
427 
reset()428 void SoundChannel_PC9801::reset() {
429 	_assign = 0xFF;
430 	_note = 0xFF;
431 	_volume = 0;
432 }
433 
recalculateFrequency(uint16 note,uint16 modifier,uint8 * destOctaveBlock,uint16 * destFrequency,uint8 * destVbrFrequencyModifier)434 int SoundChannel_PC9801::recalculateFrequency(uint16 note, uint16 modifier, uint8 *destOctaveBlock, uint16 *destFrequency, uint8 *destVbrFrequencyModifier) {
435 	note += _transpose;
436 	uint16 pb = _parts[_assign]->getCurrentPitchBend();
437 
438 	if (pb == 0x2000) {
439 		pb = 0;
440 	} else {
441 		int dir = 1;
442 		if (pb > 0x2000) {
443 			pb -= 0x2000;
444 		} else if (pb < 0x2000) {
445 			pb = 0x2000 - pb;
446 			dir = -1;
447 		}
448 
449 		uint8 noteDiff = pb / 684;
450 		note += (noteDiff * dir);
451 
452 		pb %= 684;
453 		if (pb > 682)
454 			pb = 682;
455 		pb = ((pb * 6) >> 4);
456 		pb *= dir;
457 	}
458 
459 	note += (modifier >> 8);
460 	pb += (modifier & 0xff);
461 	if ((pb >> 8) == 1) {
462 		pb &= 0xFF;
463 		note++;
464 	}
465 
466 	if (_version == SCI_VERSION_0_LATE)
467 		note -= 12;
468 
469 	if (note < 12 || note > 107)
470 		return -1;
471 
472 	if (_version == SCI_VERSION_0_LATE && _type == 2) {
473 		uint16 rs = _noteFrequency[note - 12];
474 		if (destFrequency)
475 			*destFrequency = rs;
476 		return rs;
477 	}
478 
479 	uint8 block = (note / 12) - 1;
480 	note %= 12;
481 	uint16 res =_noteFrequency[note];
482 	uint16 pitchVbrMultiplier = _noteFrequencyModifier[note];
483 
484 	if (_type != 2)
485 		res |= (block << 11);
486 	else if (block == 0)
487 		return -1;
488 
489 	if (pb)
490 		res += (((pb * pitchVbrMultiplier) & 0x0FF0) >> 8);
491 
492 	if (res < 0x4000) {
493 		if (destFrequency)
494 			*destFrequency = res;
495 		if (destOctaveBlock)
496 			*destOctaveBlock = block;
497 		if (destVbrFrequencyModifier)
498 			*destVbrFrequencyModifier = pitchVbrMultiplier;
499 		return res;
500 	}
501 
502 	return -1;
503 }
504 
getVolume()505 uint8 SoundChannel_PC9801::getVolume() {
506 	static const uint8 volumeTable1[] = {
507 		0x00, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x12, 0x13, 0x14, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1d,
508 		0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2d, 0x2d, 0x2e,
509 		0x2f, 0x30, 0x31, 0x32, 0x32, 0x33, 0x34, 0x34, 0x35, 0x36,	0x36, 0x37, 0x38, 0x38, 0x39, 0x3a,
510 		0x3b, 0x3b,	0x3b, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3e,	0x3e, 0x3f, 0x3f, 0x3f
511 	};
512 
513 	static const uint8 volumeTable2[] = {
514 		0x00, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x61,
515 		0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x6f, 0x70,
516 		0x71, 0x72, 0x72, 0x73, 0x74, 0x74, 0x75, 0x76, 0x76, 0x77, 0x78, 0x78, 0x79, 0x79, 0x7a, 0x7a,
517 		0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f
518 	};
519 
520 	uint16 partVolume = ((_assign != 0xFF) ? _parts[_assign]->getCurrentVolume() : 0);
521 	if (_version == SCI_VERSION_0_LATE)
522 		return partVolume;
523 
524 	partVolume += 1;
525 	uint16 velocity = volumeTable1[_velo] + 1;
526 	uint16 volume = _soundOn ? (partVolume * velocity) >> 6 : 0;
527 	volume = volumeTable2[volume] - _volume;
528 
529 	return (volume < 0x7F ? volume : 0);
530 }
531 
processSounds()532 void SoundChannel_PC9801::processSounds() {
533 	if (!(_flags & kChanVbrEnable))
534 		return;
535 
536 	if (_flags & kChanVbrRestartEnv) {
537 		if (--_vbrEnvelopeTimer)
538 			return;
539 
540 		_vbrIncrStep = _vbrDepthIncr * _vbrSensitivity * _frequencyNoteModifier;
541 		_vbrDecrStep = _vbrDepthDecr * _vbrSensitivity * _frequencyNoteModifier;
542 		_vbrModulationTimer = ((_flags & kChanVbrMode) ? _vbrIncrTime : _vbrDecrTime) >> 1;
543 		_vbrCur = 0x80;
544 
545 		_flags &= ~(kChanVbrDecrease | kChanVbrRestartEnv);
546 		if (_flags & kChanVbrMode)
547 			_flags |= kChanVbrDecrease;
548 	}
549 
550 	uint16 t = _vbrEnvelopeTimer + _vbrEnvelopeSpeed;
551 	_vbrEnvelopeTimer = t & 0xFF;
552 	if (t & 0x100)
553 		return;
554 
555 	if (!--_vbrModulationTimer) {
556 		_vbrModulationTimer = (_flags & kChanVbrDecrease) ? _vbrDecrTime : _vbrIncrTime;
557 		_flags ^= kChanVbrDecrease;
558 	}
559 
560 	if (_flags & kChanVbrDecrease) {
561 		uint8 sL = _vbrDecrStep & 0xFF;
562 		uint8 sH = _vbrDecrStep >> 8;
563 		bool ovrflow = (sL > _vbrCur);
564 		_vbrCur -= sL;
565 		if (!ovrflow)
566 			return;
567 		_vbrFrequencyModifier -= (sH + 1);
568 	} else {
569 		uint8 sL = _vbrDecrStep & 0xFF;
570 		uint8 sH = _vbrDecrStep >> 8;
571 		bool ovrflow = (sL + _vbrCur > 255);
572 		_vbrCur += sL;
573 		if (!ovrflow)
574 			return;
575 		_vbrFrequencyModifier += (sH + 1);
576 	}
577 
578 	sendFrequency();
579 }
580 
programChangeInit(SciSpan<const uint8> & data)581 void SoundChannel_PC9801::programChangeInit(SciSpan<const uint8> &data) {
582 	_transpose = (int8)(data[0] & 0xC0 && data[0] < 0xC0 ? data[0] ^ 0x80 : data[0]);
583 	_vbrInitialDelay = data[1];
584 	_vbrDepthIncr = data[2];
585 	_vbrDecrTime = data[3];
586 	_vbrDepthDecr = data[4];
587 	_vbrIncrTime = data[5];
588 	_vbrSensitivity = (data[6] & 3) + 1;
589 	_vbrEnvelopeSpeed = data[6] >> 3;
590 	_flags = (_flags & ~(kChanVbrEnable | kChanVbrMode)) | ((data[6] << 4) & 0x40);
591 	if (_vbrInitialDelay)
592 		_flags |= (kChanVbrEnable | kChanVbrRestartEnv);
593 }
594 
writeReg(uint8 part,uint8 reg,uint8 val)595 void SoundChannel_PC9801::writeReg(uint8 part, uint8 reg, uint8 val) {
596 	_pc98a->writeReg(part, reg, val);
597 }
598 
prepareFrequencyAndVolume(bool updateVolume)599 bool SoundChannel_PC9801::prepareFrequencyAndVolume(bool updateVolume) {
600 	if (recalculateFrequency(_note, 0, &_frequencyBlock, &_frequencyCourse, &_frequencyNoteModifier) == -1)
601 		return false;
602 
603 	sendFrequency();
604 	if (updateVolume)
605 		sendVolume();
606 
607 	return true;
608 }
609 
SoundChannel_PC9801_FM4OP(uint8 id,PC98AudioCore * pc98a,MidiPart_PC9801 ** parts,SciVersion version,SciSpan<const uint8> instrumentData,uint8 patchSize,bool & soundOn)610 SoundChannel_PC9801_FM4OP::SoundChannel_PC9801_FM4OP(uint8 id, PC98AudioCore *pc98a, MidiPart_PC9801 **parts, SciVersion version, SciSpan<const uint8> instrumentData, uint8 patchSize, bool &soundOn)
611 	: SoundChannel_PC9801(pc98a, parts, version, 0, instrumentData, soundOn), _carrier(0), _regPrt(id > 2 ? 1 : 0), _regOffs(id % 3),
612 	_operatorFlags((id > 2 ? 4 : 0) | (id % 3) | 0xF0), _patchSize(patchSize) {
613 	_operatorLevel[0] = _operatorLevel[1] = _operatorLevel[2] = _operatorLevel[3] = 0x7F;
614 }
615 
programChange(uint8 program)616 void SoundChannel_PC9801_FM4OP::programChange(uint8 program) {
617 	static const uint8 carrier[] = { 0x10, 0x10, 0x10, 0x10, 0x30, 0x70, 0x70, 0xF0 };
618 	static const uint8 steps[] = { 0, 16, 8, 24 };
619 	SciSpan<const uint8> data = _instrumentData.subspan(program * _patchSize);
620 
621 	if (_version == SCI_VERSION_1_LATE) {
622 		programChangeInit(data);
623 		uint8 pos = 8;
624 
625 		for (uint8 i = 0x40 + _regOffs; i < 0x50 + _regOffs; i += 4)
626 			writeReg(_regPrt, i, 0xFF);
627 		for (uint8 i = 0x30 + _regOffs; i < 0x40 + _regOffs; i += 4)
628 			writeReg(_regPrt, i, data[pos++]);
629 		for (int i = 0; i < 4; ++i)
630 			_operatorLevel[i] = data[pos++];
631 		for (uint8 i = 0x50 + _regOffs; i < 0xA0 + _regOffs; i += 4)
632 			writeReg(_regPrt, i, data[pos++]);
633 		writeReg(_regPrt, 0xB0 + _regOffs, data[pos]);
634 		_carrier = carrier[data[pos] & 7];
635 
636 	} else {
637 		uint8 pos = 11;
638 		uint8 opFlags = data[pos];
639 		uint8 fba = data[pos + 1] & 0x3F;
640 		_carrier = carrier[fba & 7];
641 
642 		pos += 8;
643 		uint8 reg = 0x30 + _regOffs;
644 		for (int i = 0; i < 4; ++i)
645 			writeReg(_regPrt, reg + (i << 2), data[pos + steps[i & 3]] & 0x7F);
646 
647 		pos -= 3;
648 		_operatorLevel[0] = (opFlags & 0x08) ? data[pos + steps[0]] : 0x7F;
649 		_operatorLevel[1] = (opFlags & 0x20) ? data[pos + steps[1]] : 0x7F;
650 		_operatorLevel[2] = (opFlags & 0x10) ? data[pos + steps[2]] : 0x7F;
651 		_operatorLevel[3] = (opFlags & 0x40) ? data[pos + steps[3]] : 0x7F;
652 
653 		pos += 4;
654 		reg = 0x50 + _regOffs;
655 		for (int i = 0; i < 16; ++i)
656 			writeReg(_regPrt, reg + (i << 2), data[pos + steps[i & 3] + (i >> 2)]);
657 
658 		if (fba >= 24)
659 			fba -= 24;
660 		else
661 			fba &= 7;
662 
663 		writeReg(_regPrt, 0xB0 + _regOffs, fba);
664 		_operatorFlags = (_operatorFlags & 7) | (opFlags << 1);
665 	}
666 }
667 
sendSoundOnOff(bool soundOn)668 void SoundChannel_PC9801_FM4OP::sendSoundOnOff(bool soundOn) {
669 	_flags = soundOn ? (_flags | kChanKeyOn) : (_flags & ~kChanKeyOn);
670 	writeReg(0, 0x28, soundOn ? _operatorFlags : _operatorFlags & 7);
671 }
672 
sendVolume()673 void SoundChannel_PC9801_FM4OP::sendVolume() {
674 	uint8 vol = getVolume();
675 	uint16 c = _carrier;
676 
677 	for (uint8 i = 0; i < 4; ++i) {
678 		uint8 r = _operatorLevel[i];
679 		c += c;
680 		if (c & 0x100) {
681 			c &= 0xFF;
682 			if (_version == SCI_VERSION_1_LATE) {
683 				r = (((r ^ 0x7F) * vol) / 0x7F) * 2;
684 				r = ((r < 0x7F) ? 0x7F - r : 0) + 20;
685 				if (r > 0x7F)
686 					r = 0x7F;
687 			} else {
688 				r = 127 - ((127 - r) * vol / 128);
689 			}
690 		}
691 		writeReg(_regPrt, 0x40 + (i << 2) + _regOffs, r);
692 	}
693 }
694 
sendFrequency()695 void SoundChannel_PC9801_FM4OP::sendFrequency() {
696 	uint16 freq = _frequencyCourse + _vbrFrequencyModifier;
697 	writeReg(_regPrt, 0xA4 + _regOffs, freq >> 8);
698 	writeReg(_regPrt, 0xA0 + _regOffs, freq & 0xFF);
699 }
700 
701 uint8 SoundChannel_PC9801_FM2OP::_activeOperators = 0;
702 
SoundChannel_PC9801_FM2OP(uint8 id,PC98AudioCore * pc98a,MidiPart_PC9801 ** parts,SciVersion version,SciSpan<const uint8> instrumentData,uint8 patchSize,bool & soundOn)703 SoundChannel_PC9801_FM2OP::SoundChannel_PC9801_FM2OP(uint8 id, PC98AudioCore *pc98a, MidiPart_PC9801 **parts, SciVersion version, SciSpan<const uint8> instrumentData, uint8 patchSize, bool &soundOn)
704 	: SoundChannel_PC9801(pc98a, parts, version, 1, instrumentData, soundOn), _patchOffset(37), _patchSize(patchSize), _frequencyCourse2(0), _frequencyNoteModifier2(0),
705 	_vbrFrequencyModifier2(0), _vbrCur2(0x80), _vbrIncrStep2(0), _vbrDecrStep2(0), _regPrt(id > 3 ? 1 : 0), _regOffs(id & 1) {
706 
707 	static const uint16 opFreqOffset[] = { 0x0000, 0x0600, 0x07CF, 0x0980 };
708 
709 	_operatorLevel[0] = _operatorLevel[1] = 0x7F;
710 	_operatorFrqIndex[0] = _operatorFrqIndex[1] = 0;
711 	_opFreqOffset = opFreqOffset;
712 }
713 
processNoteEvent(uint8 note,bool soundOn)714 void SoundChannel_PC9801_FM2OP::processNoteEvent(uint8 note, bool soundOn) {
715 	if (_note != note) {
716 		_vbrCur2 = 0x80;
717 		_vbrFrequencyModifier2 = 0;
718 	}
719 	SoundChannel_PC9801::processNoteEvent(note, soundOn);
720 }
721 
reset()722 void SoundChannel_PC9801_FM2OP::reset() {
723 	SoundChannel_PC9801::reset();
724 	_activeOperators = 0;
725 }
726 
programChange(uint8 program)727 void SoundChannel_PC9801_FM2OP::programChange(uint8 program) {
728 	SciSpan<const uint8> data = _instrumentData.subspan(program * _patchSize + _patchOffset);
729 
730 	programChangeInit(data);
731 	uint8 pos = 7;
732 
733 	for (uint8 i = 0x42 + (_regOffs << 2); i < 0x52 + (_regOffs << 2); i += 8)
734 		writeReg(_regPrt, i, 0xFF);
735 	for (uint8 i = 0x32 + (_regOffs << 2); i < 0x42 + (_regOffs << 2); i += 8)
736 		writeReg(_regPrt, i, data[pos++]);
737 	for (int i = 0; i < 2; ++i)
738 		_operatorLevel[i] = data[pos++];
739 	for (uint8 i = 0x52 + (_regOffs << 2); i < 0x72 + (_regOffs << 2); i += 8)
740 		writeReg(_regPrt, i, data[pos++]);
741 	_operatorFrqIndex[0] = data[pos] >> 6;
742 	_operatorFrqIndex[1] = data[pos + 1] >> 6;
743 	for (uint8 i = 0x72 + (_regOffs << 2); i < 0xA2 + (_regOffs << 2); i += 8)
744 		writeReg(_regPrt, i, data[pos++]);
745 }
746 
prepareFrequencyAndVolume(bool updateVolume)747 bool SoundChannel_PC9801_FM2OP::prepareFrequencyAndVolume(bool updateVolume) {
748 	if (recalculateFrequency(_note, _opFreqOffset[_operatorFrqIndex[0]], 0, &_frequencyCourse, &_frequencyNoteModifier) == -1)
749 		return false;
750 	if (recalculateFrequency(_note, _opFreqOffset[_operatorFrqIndex[1]], 0, &_frequencyCourse2, &_frequencyNoteModifier2) == -1)
751 		return false;
752 
753 	sendFrequency();
754 	if (updateVolume)
755 		sendVolume();
756 
757 	return true;
758 }
759 
sendSoundOnOff(bool soundOn)760 void SoundChannel_PC9801_FM2OP::sendSoundOnOff(bool soundOn) {
761 	uint8 op = 0x30 << (_regOffs << 1);
762 
763 	if (soundOn) {
764 		_flags |= kChanKeyOn;
765 		_activeOperators |= op;
766 	} else {
767 		_flags &= ~kChanKeyOn;
768 		_activeOperators &= ~op;
769 	}
770 
771 	writeReg(0, 0x28, _activeOperators | (_regPrt << 2) | 2);
772 }
773 
sendVolume()774 void SoundChannel_PC9801_FM2OP::sendVolume() {
775 	writeReg(_regPrt, 0x42 + (_regOffs << 2), _operatorLevel[0]);
776 	uint8 r = (((_operatorLevel[1] ^ 0x7F) * getVolume()) / 0x7F) * 2;
777 	r = ((r < 0x7F) ? 0x7F - r : 0) + 16;
778 	writeReg(_regPrt, 0x4A + (_regOffs << 2), r);
779 }
780 
processSounds()781 void SoundChannel_PC9801_FM2OP::processSounds() {
782 	if (!(_flags & kChanVbrEnable))
783 		return;
784 
785 	if (_flags & kChanVbrRestartEnv) {
786 		if (--_vbrEnvelopeTimer)
787 			return;
788 
789 		_vbrIncrStep = _vbrDepthIncr * _vbrSensitivity * _frequencyNoteModifier;
790 		_vbrIncrStep2 = _vbrDepthIncr * _vbrSensitivity * _frequencyNoteModifier2;
791 		_vbrDecrStep = _vbrDepthDecr * _vbrSensitivity * _frequencyNoteModifier;
792 		_vbrDecrStep2 = _vbrDepthDecr * _vbrSensitivity * _frequencyNoteModifier2;
793 		_vbrModulationTimer = ((_flags & kChanVbrMode) ? _vbrIncrTime : _vbrDecrTime) >> 1;
794 		_vbrCur = 0x80;
795 
796 		_flags &= ~(kChanVbrDecrease | kChanVbrRestartEnv);
797 		if (_flags & kChanVbrMode)
798 			_flags |= kChanVbrDecrease;
799 	}
800 
801 	uint16 t = _vbrEnvelopeTimer + _vbrEnvelopeSpeed;
802 	_vbrEnvelopeTimer = t & 0xFF;
803 	if (t & 0x100)
804 		return;
805 
806 	if (!--_vbrModulationTimer) {
807 		_vbrModulationTimer = (_flags & kChanVbrDecrease) ? _vbrDecrTime : _vbrIncrTime;
808 		_flags ^= kChanVbrDecrease;
809 	}
810 
811 	if (_flags & kChanVbrDecrease) {
812 		uint8 sL = _vbrDecrStep & 0xFF;
813 		uint8 sH = _vbrDecrStep >> 8;
814 		bool ovrflow = (sL > _vbrCur);
815 		_vbrCur -= sL;
816 		if (ovrflow)
817 			_vbrFrequencyModifier -= (sH + 1);
818 		sL = _vbrDecrStep2 & 0xFF;
819 		sH = _vbrDecrStep2 >> 8;
820 		ovrflow = (sL > _vbrCur2);
821 		_vbrCur2 -= sL;
822 		if (ovrflow)
823 			_vbrFrequencyModifier2 -= (sH + 1);
824 	} else {
825 		uint8 sL = _vbrDecrStep & 0xFF;
826 		uint8 sH = _vbrDecrStep >> 8;
827 		bool ovrflow = (sL + _vbrCur > 255);
828 		_vbrCur += sL;
829 		if (ovrflow)
830 			_vbrFrequencyModifier += (sH + 1);
831 		sL = _vbrDecrStep2 & 0xFF;
832 		sH = _vbrDecrStep2 >> 8;
833 		ovrflow = (sL + _vbrCur2 > 255);
834 		_vbrCur2 += sL;
835 		if (ovrflow)
836 			_vbrFrequencyModifier2 += (sH + 1);
837 	}
838 
839 	sendFrequency();
840 }
841 
sendFrequency()842 void SoundChannel_PC9801_FM2OP::sendFrequency() {
843 	uint16 freq = _frequencyCourse + _vbrFrequencyModifier;
844 	writeReg(_regPrt, 0xAD - _regOffs, freq >> 8);
845 	writeReg(_regPrt, 0xA9 - _regOffs, freq & 0xFF);
846 	freq = _frequencyCourse2 + _vbrFrequencyModifier2;
847 	writeReg(_regPrt, 0xAE - (_regOffs << 3), freq >> 8);
848 	writeReg(_regPrt, 0xAA - (_regOffs << 3), freq & 0xFF);
849 }
850 
851 uint8 SoundChannel_PC9801_SSG::_activeChannnelsStatus = 0x3F;
852 
SoundChannel_PC9801_SSG(uint8 id,PC98AudioCore * pc98a,MidiPart_PC9801 ** parts,SciVersion version,SciSpan<const uint8> instrumentData,uint8 patchOffset,uint8 patchSize,bool & soundOn)853 SoundChannel_PC9801_SSG::SoundChannel_PC9801_SSG(uint8 id, PC98AudioCore *pc98a, MidiPart_PC9801 **parts, SciVersion version, SciSpan<const uint8> instrumentData, uint8 patchOffset, uint8 patchSize, bool &soundOn)
854 	: SoundChannel_PC9801(pc98a, parts, version, 2, instrumentData, soundOn), _patchOffset(patchOffset), _patchSize(patchSize), _regOffs(id & 3),
855 	_instrumentChanMask(0x3F), _ngPhaseStep(0),	_currentLevel(0), _ssgEnvelopeState(kEnvSSG_silent), _ngEnvelopeTimer(0),
856 	_ngSpeed(0), _ngPhase(0), _ssgEnvelopeTimer(0), _ssgLevel(0), _ssgSpeed(0), _ccngEnabled(false) {
857 
858 	static const uint16 courseV0[] = {
859 		0xfcf, 0xef1, 0xe16, 0xd59, 0xc87, 0xbcd, 0xb27, 0xa93, 0x9ee, 0x96a, 0x8da, 0x865, 0x778, 0x70d, 0x6a6, 0x643,
860 		0x5ec, 0x599, 0x545, 0x4f7, 0x4b5, 0x46d, 0x432, 0x3f4, 0x3c5, 0x386, 0x353, 0x325, 0x2f6, 0x2cc, 0x2a3, 0x27d,
861 		0x25a, 0x238, 0x218, 0x1fa, 0x1dd, 0x1c3, 0x1a9, 0x192, 0x17b, 0x166, 0x152, 0x13f, 0x12d, 0x11c, 0x10c, 0x0fd,
862 		0x0ef, 0x0e1, 0x0d5, 0x0c9, 0x0bd, 0x0b3, 0x0a9, 0x09f, 0x096, 0x08e, 0x086, 0x07e, 0x077, 0x071, 0x06a, 0x064,
863 		0x05f, 0x059, 0x054, 0x050, 0x04b, 0x047, 0x043, 0x03f, 0x03c, 0x038, 0x035, 0x032, 0x02f, 0x02d, 0x02a, 0x028,
864 		0x026, 0x023, 0x021, 0x020, 0x01e, 0x01c, 0x01b, 0x019, 0x018, 0x016, 0x015, 0x014, 0x013, 0x012, 0x011, 0x010
865 	};
866 
867 	static const uint16 courseV1[] = { 0x82D, 0x8A9, 0x92D, 0x9B6, 0xA4D, 0xAEA, 0xB90, 0xC40, 0xCFA, 0xDC0, 0xE90, 0xF6F };
868 	static const uint16 fine[] = { 0x7C, 0x84, 0x8B, 0x94, 0x9D, 0xA6, 0xB0, 0xBA, 0xC5, 0xD0, 0xDE, 0xEB };
869 	static const uint8 noiseFrq[] = { 0x00, 0x01, 0x04, 0x07, 0x0A, 0x0D, 0x10, 0x13, 0x16, 0x19, 0x1C, 0x1F };
870 	static const uint8 disableMask[] = { 0xF6, 0xED, 0xDB };
871 	static const uint8 enableMask1[] = { 0xBE, 0xBD, 0xBB };
872 	static const uint8 enableMask2[] = { 0xB7, 0xAF, 0x9F };
873 
874 	_noteFrequency = (version > SCI_VERSION_0_LATE) ? courseV1 : courseV0;
875 	_noteFrequencyModifier = fine;
876 	_ngFreq = noiseFrq;
877 	_chanDisableMask = disableMask[id & 3];
878 	_chanEnableMask1 = enableMask1[id & 3];
879 	_chanEnableMask2 = enableMask2[id & 3];
880 }
881 
reset()882 void SoundChannel_PC9801_SSG::reset() {
883 	SoundChannel_PC9801::reset();
884 	_activeChannnelsStatus = (_version == SCI_VERSION_1_LATE) ? 0x3F : 0xFF;
885 	sendActiveChannelsStatus();
886 }
887 
toggleNoiseGenerator(bool enable)888 void SoundChannel_PC9801_SSG::toggleNoiseGenerator(bool enable) {
889 	_ccngEnabled = enable;
890 }
891 
programChange(uint8 program)892 void SoundChannel_PC9801_SSG::programChange(uint8 program) {
893 	_selectedInstrument = _instrumentData.subspan(program * _patchSize + _patchOffset);
894 
895 	if (_version == SCI_VERSION_1_LATE) {
896 		programChangeInit(_selectedInstrument);
897 
898 		_flags &= ~kChanNgEnable;
899 		if (_selectedInstrument[7])
900 			_flags |= (kChanNgEnable | kChanNgRestartEnv);
901 		_instrumentChanMask = _selectedInstrument[22];
902 		_activeChannnelsStatus = (_activeChannnelsStatus & _chanDisableMask) | (~_chanDisableMask & (_instrumentChanMask & 0x3F));
903 		if (!(_instrumentChanMask & 8)) {
904 			_ngPhaseStep = _selectedInstrument[21] & 0x1F;
905 			updateNg();
906 		}
907 
908 		sendActiveChannelsStatus();
909 
910 	} else {
911 		writeReg(0, 13, _selectedInstrument[0]);
912 		writeReg(0,  6, _selectedInstrument[1]);
913 		writeReg(0, 11, _selectedInstrument[2]);
914 		writeReg(0, 12, _selectedInstrument[3]);
915 	}
916 
917 	_currentLevel = 0;
918 	_ssgEnvelopeState = kEnvSSG_silent;
919 }
920 
processSounds()921 void SoundChannel_PC9801_SSG::processSounds() {
922 	if (_ssgEnvelopeState == kEnvSSG_silent)
923 		return;
924 
925 	SoundChannel_PC9801::processSounds();
926 
927 	if (!(_instrumentChanMask & 0x38) && (_flags & kChanNgEnable)) {
928 		bool cont = false;
929 		if (_flags & kChanNgRestartEnv) {
930 			if (--_ngEnvelopeTimer) {
931 				cont = true;
932 			} else {
933 				uint8 flg = _selectedInstrument[10] & 4;
934 				_ngSpeed = ((flg ? _selectedInstrument[9] : _selectedInstrument[8]) & 0x1F) >> 1;
935 				_flags = (_flags & ~(kChanNgDecrease | kChanNgRestartEnv)) | (flg << 3);
936 			}
937 		}
938 		if (!cont) {
939 			uint16 s = _ngEnvelopeTimer + (_selectedInstrument[10] >> 3);
940 			_ngEnvelopeTimer = s & 0xFF;
941 			if (s & 0x100)
942 				cont = true;
943 			if (!cont) {
944 				if (--_ngSpeed) {
945 					if (_flags & kChanNgDecrease) {
946 						_ngSpeed = _selectedInstrument[8] & 0x1F;
947 						_flags &= ~kChanNgDecrease;
948 					} else {
949 						_ngSpeed = _selectedInstrument[9] & 0x1F;
950 						_flags |= kChanNgDecrease;
951 					}
952 				}
953 
954 				if (_flags & kChanNgDecrease) {
955 					_ngPhase -= (_selectedInstrument[9] >> 5) * ((_selectedInstrument[10] & 3) + 1);
956 				} else {
957 					_ngPhase += (_selectedInstrument[8] >> 5) * ((_selectedInstrument[10] & 3) + 1);
958 				}
959 				updateNg();
960 			}
961 		}
962 	}
963 
964 	uint16 s = _ssgEnvelopeTimer + (_selectedInstrument[21] & 0x60);
965 	_ssgEnvelopeTimer = s & 0xFF;
966 	if ((s & 0x100) || !(_ssgEnvelopeState & 0x0F))
967 		return;
968 
969 	uint8 vol = _currentLevel;
970 	if (_ssgLevel & 1)
971 		vol = (vol > (_ssgLevel & ~1)) ? vol - (_ssgLevel & ~1) : 0;
972 	else
973 		vol = (vol + _ssgLevel > 255) ? 255 : vol + _ssgLevel;
974 
975 	if (!--_ssgSpeed) {
976 		if (--_ssgEnvelopeState == (kEnvSSG_keyOn | kEnvSSG_sustain)) {
977 			_ssgLevel = _selectedInstrument[13];
978 			_ssgSpeed = _selectedInstrument[14];
979 			vol = (uint8)CLIP<int16>(vol + (int8)(_selectedInstrument[19] & 0xF0), 0, 255);
980 		}
981 		if (_ssgEnvelopeState == (kEnvSSG_keyOn | kEnvSSG_decay)) {
982 			_ssgLevel = _selectedInstrument[15];
983 			_ssgSpeed = _selectedInstrument[16];
984 			vol = (uint8)CLIP<int16>(vol + (int8)((_selectedInstrument[20] & 0x0F) << 4), 0, 255);
985 		}
986 	}
987 
988 	if (_ssgEnvelopeState == kEnvSSG_silent)
989 		vol = 0;
990 
991 	if (_currentLevel != vol) {
992 		_currentLevel = vol;
993 		sendVolume();
994 	}
995 }
996 
sendSoundOnOff(bool soundOn)997 void SoundChannel_PC9801_SSG::sendSoundOnOff(bool soundOn) {
998 	if (_version == SCI_VERSION_1_LATE && soundOn && !(_ssgEnvelopeState & kEnvSSG_keyOn)) {
999 		_currentLevel = _selectedInstrument[19] << 4;
1000 		_ssgEnvelopeState = (kEnvSSG_keyOn | kEnvSSG_attack);
1001 		_ssgLevel = _selectedInstrument[11];
1002 		_ssgSpeed = _selectedInstrument[12];
1003 		_ssgEnvelopeTimer = 1;
1004 		if (!(_selectedInstrument[22] & 0x38)) {
1005 			if (_selectedInstrument[21] & 0x80)
1006 				_ngPhaseStep = _ngFreq[_note % 12];
1007 			_ngEnvelopeTimer = _selectedInstrument[7];
1008 			_ngPhase = 0;
1009 			updateNg();
1010 			_flags |= kChanNgRestartEnv;
1011 		}
1012 	} else if (_version == SCI_VERSION_1_LATE && !soundOn) {
1013 		int16 l = _currentLevel + (int8)(_selectedInstrument[20] & 0xF0);
1014 		_currentLevel = (uint8)CLIP<int16>(l, 0, 255);
1015 		_ssgEnvelopeState = kEnvSSG_decay;
1016 		_ssgLevel = _selectedInstrument[17];
1017 		_ssgSpeed = _selectedInstrument[18];
1018 		_note = 0xFF;
1019 	} else if (_version == SCI_VERSION_0_LATE && soundOn) {
1020 		_activeChannnelsStatus &= _chanEnableMask1;
1021 		if (_ccngEnabled)
1022 			_activeChannnelsStatus &= _chanEnableMask2;
1023 		_currentLevel = 1;
1024 		sendActiveChannelsStatus();
1025 		writeReg(0, 13, _selectedInstrument[0]);
1026 	} else if (_version == SCI_VERSION_0_LATE) {
1027 		_activeChannnelsStatus |= ~_chanEnableMask1;
1028 		if (_ccngEnabled)
1029 			_activeChannnelsStatus |= ~_chanEnableMask2;
1030 		_currentLevel = 0;
1031 		_note = 0xFF;
1032 		sendActiveChannelsStatus();
1033 	}
1034 	sendVolume();
1035 }
1036 
sendVolume()1037 void SoundChannel_PC9801_SSG::sendVolume() {
1038 	uint8 v1 = getVolume();
1039 	uint16 r = 0;
1040 
1041 	if (_version == SCI_VERSION_1_LATE) {
1042 		uint8 vol = v1 + (((v1 >> 1) + v1) >> 2);
1043 
1044 		if (vol > 0x7F)
1045 			vol = 0x7F;
1046 		vol = (vol >> 3) & 0x0F;
1047 
1048 		r = _currentLevel & 0xF0;
1049 		for (uint8 i = 0; i < 4; ++i) {
1050 			r += r;
1051 			if (r & 0x100)
1052 				r = (r + vol) & 0xFF;
1053 		}
1054 
1055 		r = (r + 15) >> 4;
1056 
1057 	} else {
1058 		r = _currentLevel * (0x10 | v1 >> 3);
1059 	}
1060 
1061 	writeReg(0, 8 + _regOffs, r);
1062 }
1063 
sendFrequency()1064 void SoundChannel_PC9801_SSG::sendFrequency() {
1065 	uint16 freq = _frequencyCourse;
1066 
1067 	if (_version > SCI_VERSION_0_LATE) {
1068 		freq = (uint16)(freq + _vbrFrequencyModifier) >> (8 - _frequencyBlock);
1069 		if (!freq)
1070 			return;
1071 		freq = 62400 / freq;
1072 	}
1073 
1074 	writeReg(0, _regOffs << 1, freq & 0xFF);
1075 	writeReg(0, (_regOffs << 1) + 1, freq >> 8);
1076 }
1077 
updateNg()1078 void SoundChannel_PC9801_SSG::updateNg() {
1079 	int p = _ngPhase + _ngPhaseStep;
1080 	if (p > 255)
1081 		p = 0;
1082 	if (p > 31)
1083 		p = 31;
1084 	_ngPhase = p & 0xFF;
1085 	writeReg(0, 6, _ngPhase);
1086 }
1087 
sendActiveChannelsStatus()1088 void SoundChannel_PC9801_SSG::sendActiveChannelsStatus() {
1089 	writeReg(0, 7, (_activeChannnelsStatus & 0x3F) | 0x80);
1090 }
1091 
MidiPart_PC9801(uint8 id,SoundChannel_PC9801 ** channels,uint8 numChan,SciVersion version)1092 MidiPart_PC9801::MidiPart_PC9801(uint8 id, SoundChannel_PC9801 **channels, uint8 numChan, SciVersion version) : _chan(channels), _id(id), _version(version), _numChan(numChan),
1093 	_program(0), _volume(0x3f), _sustain(0), _chanMissing(0), _pitchBend(0x2000), _outChan(0), _noteRangeLow(version > SCI_VERSION_0_LATE ? 12 : 24), _noteRangeHigh(version > SCI_VERSION_0_LATE ? 107 : 119) {
1094 }
1095 
noteOff(uint8 note)1096 void MidiPart_PC9801::noteOff(uint8 note) {
1097 	for (int i = 0; i < _numChan; ++i) {
1098 		if (_chan[i]->_assign != _id || _chan[i]->_note != note)
1099 			continue;
1100 		if (_sustain && _version > SCI_VERSION_0_LATE)
1101 			_chan[i]->_sustain = 1;
1102 		else
1103 			_chan[i]->noteOff();
1104 		return;
1105 	}
1106 }
1107 
noteOn(uint8 note,uint8 velo)1108 void MidiPart_PC9801::noteOn(uint8 note, uint8 velo) {
1109 	if (note < _noteRangeLow || note > _noteRangeHigh)
1110 		return;
1111 
1112 	if (velo == 0) {
1113 		noteOff(note);
1114 		return;
1115 	}
1116 
1117 	velo >>= 1;
1118 
1119 	for (int i = 0; i < _numChan; ++i) {
1120 		if (_chan[i]->_assign != _id || _chan[i]->_note != note)
1121 			continue;
1122 		_chan[i]->_sustain = 0;
1123 		_chan[i]->noteOff();
1124 		_chan[i]->noteOn(note, velo);
1125 		return;
1126 	}
1127 
1128 	int chan = allocateChannel();
1129 	if (chan != -1)
1130 		_chan[chan]->noteOn(note, velo);
1131 }
1132 
controlChangeVolume(uint8 vol)1133 void MidiPart_PC9801::controlChangeVolume(uint8 vol) {
1134 	_volume = (_version < SCI_VERSION_1_LATE) ? vol : CLIP(vol >> 1, 0, 0x3f);
1135 	for (int i = 0; i < _numChan; ++i) {
1136 		if (_chan[i]->_assign == _id && _chan[i]->_note != 0xff)
1137 			_chan[i]->processNoteEvent(_chan[i]->_note, true);
1138 	}
1139 }
1140 
controlChangeSustain(uint8 sus)1141 void MidiPart_PC9801::controlChangeSustain(uint8 sus) {
1142 	if (_version < SCI_VERSION_1_LATE)
1143 		return;
1144 
1145 	_sustain = sus;
1146 	if (_sustain)
1147 		return;
1148 
1149 	for (int i = 0; i < _numChan; ++i) {
1150 		if (_chan[i]->_assign == _id && _chan[i]->_sustain) {
1151 			_chan[i]->_sustain = 0;
1152 			_chan[i]->noteOff();
1153 		}
1154 	}
1155 }
1156 
controlChangePolyphony(uint8 numChan)1157 void MidiPart_PC9801::controlChangePolyphony(uint8 numChan) {
1158 	if (_version < SCI_VERSION_1_LATE)
1159 		return;
1160 
1161 	uint8 numAssigned = 0;
1162 	for (int i = 0; i < _numChan; ++i) {
1163 		if (_chan[i]->_assign == _id)
1164 			numAssigned++;
1165 	}
1166 
1167 	numAssigned += _chanMissing;
1168 	if (numAssigned < numChan) {
1169 		addChannels(numChan - numAssigned);
1170 	} else if (numAssigned > numChan) {
1171 		dropChannels(numAssigned - numChan);
1172 		assignFreeChannels();
1173 	}
1174 }
1175 
controlChangeNoiseGenerator(uint8 enable)1176 void MidiPart_PC9801::controlChangeNoiseGenerator(uint8 enable) {
1177 	if (_version > SCI_VERSION_0_LATE)
1178 		return;
1179 
1180 	for (int i = 0; i < _numChan; ++i) {
1181 		if (_chan[i]->_assign == _id)
1182 			_chan[i]->toggleNoiseGenerator(enable);
1183 	}
1184 }
1185 
controlChangeAllNotesOff()1186 void MidiPart_PC9801::controlChangeAllNotesOff() {
1187 	for (int i = 0; i < _numChan; ++i) {
1188 		if (_chan[i]->_assign == _id && _chan[i]->_note != 0xff)
1189 			_chan[i]->noteOff();
1190 	}
1191 }
1192 
programChange(uint8 prg)1193 void MidiPart_PC9801::programChange(uint8 prg) {
1194 	_program = prg;
1195 }
1196 
pitchBend(int16 val)1197 void MidiPart_PC9801::pitchBend(int16 val) {
1198 	if (_version < SCI_VERSION_1_LATE)
1199 		return;
1200 
1201 	_pitchBend = val;
1202 	for (int i = 0; i < _numChan; ++i) {
1203 		if (_chan[i]->_assign == _id && _chan[i]->_note != 0xff)
1204 			_chan[i]->processNoteEvent(_chan[i]->_note, true);
1205 	}
1206 }
1207 
1208 
addChannels(int num,int resetMissingChannels,int channelType)1209 void MidiPart_PC9801::addChannels(int num, int resetMissingChannels, int channelType) {
1210 	if (resetMissingChannels != -1)
1211 		_chanMissing = resetMissingChannels;
1212 
1213 	for (int i = 0; i < _numChan; ++i) {
1214 		if (_chan[i]->_assign != 0xFF || (channelType != -1 && _chan[i]->getType() != channelType))
1215 			continue;
1216 
1217 		_chan[i]->_assign = _id;
1218 
1219 #ifdef DEBUG_REMAP
1220 		debug("===== MidiDriver_PC9801: hardware channel %d is assigned to device channel %d =====", i, _id);
1221 #endif
1222 		if (_chan[i]->_note != 0xff)
1223 			_chan[i]->noteOff();
1224 
1225 		if (!--num)
1226 			break;
1227 	}
1228 	_chanMissing += num;
1229 }
1230 
dropChannels(int num)1231 void MidiPart_PC9801::dropChannels(int num) {
1232 	if (_chanMissing == num) {
1233 		_chanMissing = 0;
1234 		return;
1235 	} else if (_chanMissing > num) {
1236 		_chanMissing -= num;
1237 		return;
1238 	}
1239 
1240 	num -= _chanMissing;
1241 	_chanMissing = 0;
1242 
1243 	for (int i = 0; i < _numChan; i++) {
1244 		if (_chan[i]->_assign != _id || _chan[i]->_note != 0xff)
1245 			continue;
1246 		_chan[i]->_assign = 0xff;
1247 
1248 #ifdef DEBUG_REMAP
1249 		debug("===== MidiDriver_PC9801: hardware channel %d is dropped from device channel %d =====", i, _id);
1250 #endif
1251 
1252 		if (!--num)
1253 			return;
1254 	}
1255 
1256 	for (int i = 0; i < _numChan; i++) {
1257 		if (_chan[i]->_assign != _id)
1258 			continue;
1259 		_chan[i]->_sustain = 0;
1260 		_chan[i]->noteOff();
1261 		_chan[i]->_assign = 0xff;
1262 		if (!--num)
1263 			return;
1264 	}
1265 }
1266 
allocateChannel()1267 int MidiPart_PC9801::allocateChannel() {
1268 	int chan = _outChan;
1269 	int ovrChan = 0;
1270 	int ld = 0;
1271 	bool found = false;
1272 
1273 	for (bool loop = true; loop; ) {
1274 		if (++chan == _numChan)
1275 			chan = 0;
1276 
1277 		if (chan == _outChan)
1278 			loop = false;
1279 
1280 		if (_id == _chan[chan]->_assign) {
1281 			if (_chan[chan]->_note == 0xff || _version < SCI_VERSION_1_LATE) {
1282 				found = true;
1283 				break;
1284 			}
1285 
1286 			if (_chan[chan]->_duration >= ld) {
1287 				ld = _chan[chan]->_duration;
1288 				ovrChan = chan;
1289 			}
1290 		}
1291 	}
1292 
1293 	if (!found) {
1294 		if (!ld)
1295 			return -1;
1296 		chan = ovrChan;
1297 		_chan[chan]->_sustain = 0;
1298 		_chan[chan]->noteOff();
1299 	}
1300 
1301 	_outChan = chan;
1302 	return chan;
1303 }
1304 
assignFreeChannels()1305 void MidiPart_PC9801::assignFreeChannels() {
1306 	uint8 freeChan = 0;
1307 	for (int i = 0; i < _numChan; i++) {
1308 		if (_chan[i]->_assign == 0xff)
1309 			freeChan++;
1310 	}
1311 
1312 	if (!freeChan)
1313 		return;
1314 
1315 	MidiDriver_PC9801::assignFreeChannels(freeChan);
1316 }
1317 
1318 MidiPart_PC9801 **MidiDriver_PC9801::_parts = 0;
1319 
MidiDriver_PC9801(Audio::Mixer * mixer,SciVersion version)1320 MidiDriver_PC9801::MidiDriver_PC9801(Audio::Mixer *mixer, SciVersion version)
1321 	: _mixer(mixer), _version(version), _pc98a(0), _chan(0), _numChan(6), _internalVersion(0xFF), _ssgPatchOffset(0xFF), _patchSize(0),
1322 	_timerProc(0), _timerProcPara(0), _baseTempo(10080), _ready(false), _isOpen(false), _masterVolume(0x0f) ,_soundOn(true), _playID(0),
1323 	_polyphony(9), _channelMask1(0x10), _channelMask2(0x02) {
1324 }
1325 
~MidiDriver_PC9801()1326 MidiDriver_PC9801::~MidiDriver_PC9801() {
1327 	close();
1328 }
1329 
open()1330 int MidiDriver_PC9801::open() {
1331 	if (_isOpen)
1332 		return MERR_ALREADY_OPEN;
1333 
1334 	if (!_pc98a) {
1335 		_pc98a =
1336 #ifdef SCI_PC98_AUDIO_EXTENDED
1337 		new PC98AudioCore(_mixer, this, kType86);
1338 #else
1339 		new PC98AudioCore(_mixer, this, kType26);
1340 #endif
1341 	}
1342 
1343 	if (!_ready) {
1344 		if (!_pc98a->init())
1345 			return MERR_CANNOT_CONNECT;
1346 		_pc98a->setSoundEffectChanMask(0);
1347 		_pc98a->ssgSetVolume(205);
1348 		_ready = true;
1349 	}
1350 
1351 	ResourceManager *resMan = g_sci->getResMan();
1352 	if (!loadInstruments(*resMan->findResource(ResourceId(kResourceTypePatch, _version < SCI_VERSION_1_LATE ? 2 : 8), false)))
1353 		return MERR_CANNOT_CONNECT;
1354 
1355 	if (_version == SCI_VERSION_0_LATE && _channelMask2 == 0x00) {
1356 		_internalVersion = 0;
1357 		_polyphony = 3;
1358 	} else if (_version == SCI_VERSION_0_LATE && _channelMask2 == 0x02) {
1359 		_internalVersion = 1;
1360 		_polyphony = 6;
1361 	} else if (_patchSize == 60 && _ssgPatchOffset == 37)
1362 		_internalVersion = 2;
1363 	else if (_patchSize == 81 && _ssgPatchOffset == 58)
1364 		_internalVersion = 3;
1365 	else
1366 		return MERR_CANNOT_CONNECT;
1367 
1368 	if (_internalVersion == 3)
1369 		_numChan++;
1370 
1371 	int config = _internalVersion;
1372 
1373 #ifdef	SCI_PC98_AUDIO_EXTENDED
1374 	_numChan = 9;
1375 	config = 4;
1376 #endif
1377 
1378 	static const int channelConfig[6][11] = {
1379 		{  0,  0,  0,  2,  2,  2, -1, -1, -1, -1, -1 },
1380 		{  0,  0,  0,  2,  2,  2, -1, -1, -1, -1, -1 },
1381 		{  0,  0,  0,  2,  2,  2, -1, -1, -1, -1, -1 },
1382 		{  0,  0,  1,  1,  2,  2,  2, -1, -1, -1, -1 },
1383 		{  0,  0,  0,  0,  0,  0,  2,  2,  2, -1, -1 }
1384 	};
1385 
1386 	_parts = new MidiPart_PC9801*[16];
1387 	_chan = new SoundChannel_PC9801*[_numChan];
1388 
1389 	int numSSG = 0;
1390 	for (int i = 0; i < _numChan; ++i) {
1391 		if (channelConfig[config][i] == 0)
1392 			_chan[i] = new SoundChannel_PC9801_FM4OP(i, _pc98a, _parts, _version, *_instrumentData, _patchSize, _soundOn);
1393 		else if (channelConfig[config][i] == 1)
1394 			_chan[i] = new SoundChannel_PC9801_FM2OP(i, _pc98a, _parts, _version, *_instrumentData, _patchSize, _soundOn);
1395 		else if (channelConfig[config][i] == 2)
1396 			_chan[i] = new SoundChannel_PC9801_SSG(numSSG++, _pc98a, _parts, _version, *_instrumentData, _ssgPatchOffset, _patchSize, _soundOn);
1397 		else
1398 			_chan[i] = 0;
1399 	}
1400 
1401 	for (int i = 0; i < 16; ++i)
1402 		_parts[i] = new MidiPart_PC9801(i, _chan, _numChan, _version);
1403 
1404 	_isOpen = true;
1405 
1406 	reset();
1407 
1408 	return 0;
1409 }
1410 
close()1411 void MidiDriver_PC9801::close() {
1412 	if (!_isOpen)
1413 		return;
1414 
1415 	bool ready = _ready;
1416 	_isOpen = _ready = false;
1417 
1418 	delete _pc98a;
1419 	_pc98a = 0;
1420 
1421 	if (_parts) {
1422 		for (int i = 0; i < 16; ++i) {
1423 			delete _parts[i];
1424 			_parts[i] = 0;
1425 		}
1426 		delete[] _parts;
1427 		_parts = 0;
1428 	}
1429 
1430 	if (_chan) {
1431 		for (int i = 0; i < _numChan; ++i) {
1432 			delete _chan[i];
1433 			_chan[i] = 0;
1434 		}
1435 		delete[] _chan;
1436 		_chan = 0;
1437 	}
1438 
1439 	_instrumentData.clear();
1440 
1441 	_ready = ready;
1442 }
1443 
send(uint32 b)1444 void MidiDriver_PC9801::send(uint32 b) {
1445 	if (!_isOpen)
1446 		return;
1447 
1448 	byte para2 = (b >> 16) & 0xFF;
1449 	byte para1 = (b >> 8) & 0xFF;
1450 	byte cmd = b & 0xF0;
1451 
1452 	MidiPart_PC9801 *part = _parts[b & 0x0F];
1453 
1454 	switch (cmd) {
1455 	case 0x80:
1456 		part->noteOff(para1);
1457 		break;
1458 	case 0x90:
1459 		part->noteOn(para1, para2);
1460 		break;
1461 	case 0xb0:
1462 		switch (para1) {
1463 		case 7:
1464 			part->controlChangeVolume(para2);
1465 			break;
1466 		case 64:
1467 			part->controlChangeSustain(para2);
1468 			break;
1469 		case SCI_MIDI_SET_POLYPHONY:
1470 			part->controlChangePolyphony(para2);
1471 			break;
1472 		case 76:
1473 			// This event (from the SCI0 driver) is parsing related and can't be handled here. Lets's see if this ever comes up.
1474 			warning("MidiDriver_PC9801: Midi Control Change '0x%2x' not implemented", para1);
1475 			break;
1476 		case 81:
1477 			part->controlChangeNoiseGenerator(para2);
1478 			break;
1479 		case 96:
1480 			// This event (from the SCI0 driver) is parsing related. It is handled in MidiParser_SCI::processEvent().
1481 			break;
1482 		case SCI_MIDI_CHANNEL_NOTES_OFF:
1483 			part->controlChangeAllNotesOff();
1484 			break;
1485 		default:
1486 			break;
1487 		}
1488 		break;
1489 	case 0xc0:
1490 		part->programChange(para1);
1491 		break;
1492 	case 0xe0:
1493 		part->pitchBend(para1 | (para2 << 7));
1494 		break;
1495 	default:
1496 		break;
1497 	}
1498 }
1499 
assignFreeChannels(int num)1500 void MidiDriver_PC9801::assignFreeChannels(int num) {
1501 	assert(_parts);
1502 	for (int i = 0; i < 16; ++i) {
1503 		uint8 missing = _parts[i]->getMissingChannels();
1504 		if (!missing)
1505 			continue;
1506 		if (missing < num) {
1507 			num -= missing;
1508 			_parts[i]->addChannels(missing, 0);
1509 		} else {
1510 			_parts[i]->addChannels(num, missing - num);
1511 			return;
1512 		}
1513 	}
1514 }
1515 
property(int prop,uint32 param)1516 uint32 MidiDriver_PC9801::property(int prop, uint32 param) {
1517 	if (!_isOpen)
1518 		return 0;
1519 
1520 	switch(prop) {
1521 	case MIDI_PROP_MASTER_VOLUME:
1522 		if (param != 0xffff && param != _masterVolume && param < 16) {
1523 			_masterVolume = param;
1524 			for (int i = 0; i < _numChan; ++i) {
1525 				_chan[i]->setVolume(_masterVolume);
1526 				if (_chan[i]->_note != 0xFF)
1527 					_chan[i]->processNoteEvent(_chan[i]->_note, true);
1528 			}
1529 		}
1530 		return _masterVolume;
1531 	case MIDI_PROP_PLAYSWITCH:
1532 		_soundOn = param;
1533 		break;
1534 	case MIDI_PROP_POLYPHONY:
1535 		return _polyphony;
1536 	case MIDI_PROP_CHANNEL_ID:
1537 		return _version < SCI_VERSION_1_LATE ? (_channelMask1 | _channelMask2) : _playID;
1538 	default:
1539 		break;
1540 	}
1541 	return 0;
1542 }
1543 
initTrack(SciSpan<const byte> & header)1544 void MidiDriver_PC9801::initTrack(SciSpan<const byte> &header) {
1545 	if (!_isOpen || _version > SCI_VERSION_0_LATE)
1546 		return;
1547 
1548 	for (int i = 0; i < _numChan; ++i)
1549 		_chan[i]->reset();
1550 
1551 	uint8 readPos = 0;
1552 	uint8 caps = header.getInt8At(readPos++);
1553 	int numChan = (caps == 2) ? 15 : 16;
1554 	if (caps != 0 && caps != 2)
1555 		return;
1556 
1557 	for (int i = 0; i < numChan; ++i) {
1558 		_parts[i]->controlChangeVolume(103);
1559 
1560 		uint8 num = (_internalVersion == 1) ? (header.getInt8At(readPos) & 0x7F) : 1;
1561 		readPos++;
1562 		uint8 flags = header.getInt8At(readPos);
1563 		readPos++;
1564 
1565 		if (flags & _channelMask1 && num)
1566 			_parts[i]->addChannels(num, -1, 0);
1567 
1568 		if (flags & _channelMask2 && num)
1569 			_parts[i]->addChannels(num, -1, 2);
1570 
1571 		if (_internalVersion == 0)
1572 			_parts[i]->programChange(10);
1573 	}
1574 }
1575 
setTimerCallback(void * timer_param,Common::TimerManager::TimerProc timer_proc)1576 void MidiDriver_PC9801::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
1577 	_timerProc = timer_proc;
1578 	_timerProcPara = timer_param;
1579 }
1580 
getBaseTempo()1581 uint32 MidiDriver_PC9801::getBaseTempo() {
1582 	return _baseTempo;
1583 }
1584 
timerCallbackB()1585 void MidiDriver_PC9801::timerCallbackB() {
1586 	if (!_isOpen)
1587 		return;
1588 	updateParser();
1589 	updateChannels();
1590 }
1591 
loadInstruments(const SciSpan<const uint8> & data)1592 bool MidiDriver_PC9801::loadInstruments(const SciSpan<const uint8> &data) {
1593 	if (!data)
1594 		return false;
1595 
1596 	SciSpan<const uint8> src = data;
1597 	_instrumentData.clear();
1598 
1599 	if (_version == SCI_VERSION_0_LATE) {
1600 		_ssgPatchOffset = 48;
1601 		_patchSize = 52;
1602 
1603 		_instrumentData->allocate(96 * _patchSize);
1604 		SciSpan<uint8> dst = *_instrumentData;
1605 
1606 		for (bool load = true; load; ) {
1607 			for (int i = 0; i < 48; ++i) {
1608 				src.subspan(0, _patchSize).copyDataTo(dst);
1609 				src += 64;
1610 				dst += _patchSize;
1611 			}
1612 			uint16 id = (src.byteSize() >= 2) ? src.getInt16BEAt(0) : 0;
1613 			if (id == 0xABCD || id == 0xCDAB) {
1614 				src += 2;
1615 				_channelMask2 = 0x00;
1616 			} else {
1617 				load = false;
1618 			}
1619 		}
1620 	} else if (_version == SCI_VERSION_1_LATE) {
1621 		_instrumentData->allocateFromSpan(++src);
1622 		_patchSize = (data.byteSize() - 1) / 96;
1623 		_ssgPatchOffset = (_patchSize == 81) ? 58 : 37;
1624 	}
1625 
1626 	return (_instrumentData->byteSize() && _patchSize && _ssgPatchOffset != 0xFF);
1627 }
1628 
updateParser()1629 void MidiDriver_PC9801::updateParser() {
1630 	if (_timerProc) {
1631 		// The mutex lock has to be lifted, before entering the SCI engine space. The engine has its owns mutex and the different threads
1632 		// will often cause an immediate lockup (each thread caught in the mutex lock of the other). I consider this safe for all realistic
1633 		// scenarios, since a reentry of the space guarded by the PC98 audio mutex is not possible without triggering another mutex lock.
1634 		// I have also rearranged the driver deconstruction appropriately.
1635 		PC98AudioCore::MutexLock tempUnlock = _pc98a->stackUnlockMutex();
1636 		_timerProc(_timerProcPara);
1637 	}
1638 }
1639 
updateChannels()1640 void MidiDriver_PC9801::updateChannels() {
1641 	for (int i = 0; i < _numChan; ++i)
1642 		_chan[i]->update();
1643 }
1644 
reset()1645 void MidiDriver_PC9801::reset() {
1646 	if (!_ready)
1647 		return;
1648 
1649 	for (int i = 0; i < 3; ++i) {
1650 		_pc98a->writeReg(0, 0x28, i);
1651 		_pc98a->writeReg(0, i, 0);
1652 		_pc98a->writeReg(0, 8 + i, 0);
1653 	}
1654 
1655 	uint8 flag = 0;
1656 #ifndef SCI_PC98_AUDIO_EXTENDED
1657 	if (_internalVersion == 3) {
1658 		_pc98a->writeReg(0, 0xB2, 0x04);
1659 		flag = 0x40;
1660 	}
1661 #endif
1662 
1663 	_pc98a->writeReg(0, 0x27, 0x38);
1664 	_pc98a->writeReg(0, 0x27, 0x3a | flag);
1665 
1666 	if (!_isOpen)
1667 		return;
1668 
1669 	for (int i = 0; i < _numChan; ++i)
1670 		_chan[i]->reset();
1671 }
1672 
MidiPlayer_PC9801(SciVersion version)1673 MidiPlayer_PC9801::MidiPlayer_PC9801(SciVersion version) : MidiPlayer(version) {
1674 	_driver = new MidiDriver_PC9801(g_system->getMixer(), version);
1675 }
1676 
~MidiPlayer_PC9801()1677 MidiPlayer_PC9801::~MidiPlayer_PC9801() {
1678 	delete _driver;
1679 }
1680 
hasRhythmChannel() const1681 bool MidiPlayer_PC9801::hasRhythmChannel() const {
1682 	return false;
1683 }
1684 
getPlayId() const1685 byte MidiPlayer_PC9801::getPlayId() const {
1686 	return _driver ? _driver->property(MIDI_PROP_CHANNEL_ID, 0) : 0;
1687 }
1688 
getPolyphony() const1689 int MidiPlayer_PC9801::getPolyphony() const {
1690 	return _driver ? _driver->property(MIDI_PROP_POLYPHONY, 0) : 0;
1691 }
1692 
playSwitch(bool play)1693 void MidiPlayer_PC9801::playSwitch(bool play) {
1694 	if (_driver)
1695 		_driver->property(MIDI_PROP_PLAYSWITCH, play ? 1 : 0);
1696 }
1697 
initTrack(SciSpan<const byte> & trackData)1698 void MidiPlayer_PC9801::initTrack(SciSpan<const byte> &trackData) {
1699 	if (_driver)
1700 		static_cast<MidiDriver_PC9801*>(_driver)->initTrack(trackData);
1701 }
1702 
MidiPlayer_PC9801_create(SciVersion _soundVersion)1703 MidiPlayer *MidiPlayer_PC9801_create(SciVersion _soundVersion) {
1704 	return new MidiPlayer_PC9801(_soundVersion);
1705 }
1706 
1707 } // End of namespace Sci
1708 
1709