1 // license:BSD-3-Clause
2 // copyright-holders:Olivier Galibert, R. Belmont, MetalliC
3 /***************************************************************************
4 
5     Yamaha YMZ770C "AMMS-A" and YMZ774 "AMMS2C"
6 
7     Emulation by R. Belmont and MetalliC
8     AMM decode by Olivier Galibert
9 
10 -----
11 TODO:
12 - What does channel ATBL mean?
13 - Simple Access mode. SACs is register / data lists same as SEQ. in 770C, when both /SEL and /CS pins goes low - will be run SAC with number set at data bus.
14   can not be used in CV1K (/SEL pin is NC, internally pulled to VCC), probably not used in PGM2 too.
15  770:
16 - sequencer timers implemented but seems unused, presumably because of design flaws or bugs, likely due to lack of automatic adding of sequencer # to register offset.
17   in result sequences uses very long chains of 32-sample wait commands instead, wasting a lot of ROM space.
18 - sequencer triggers not implemented, not sure how they works (Deathsmiles ending tune starts sequence with TGST = 01h, likely a bug and don't affect tune playback)
19  774:
20 - 4 channel output
21 - Equalizer
22 - pan delayed transition (not used in games)
23 - sequencer off trigger (not used in games)
24 
25  known SPUs in this series:
26   YMZ770B  AMMSL    Capcom medal hardware (alien.cpp), sample format is not AMM, in other parts looks like 770C
27   YMZ770C  AMMS-A   Cave CV1000
28   YMZ771   SSGS3
29   YMZ773   AMMS2    Cron corp. video slots
30   YMZ775   AMMS2B
31   YMZ774   AMMS2C   IGS PGM2
32   YMZ776   AMMS3    uses AM3 sample format (modified Ogg?)
33   YMZ778   AMMS3S
34   YMZ779   AMMS3D
35   YMZ870   AMMS3EX
36 
37 ***************************************************************************/
38 
39 #include "emu.h"
40 #include "ymz770.h"
41 #include "mpeg_audio.h"
42 
43 // device type definition
44 DEFINE_DEVICE_TYPE(YMZ770, ymz770_device, "ymz770", "Yamaha YMZ770C AMMS-A")
45 DEFINE_DEVICE_TYPE(YMZ774, ymz774_device, "ymz774", "Yamaha YMZ774 AMMS2C")
46 
47 //-------------------------------------------------
48 //  ymz770_device - constructor
49 //-------------------------------------------------
50 
ymz770_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)51 ymz770_device::ymz770_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
52 	: ymz770_device(mconfig, YMZ770, tag, owner, clock, 16000)
53 {
54 }
55 
ymz770_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,uint32_t sclock)56 ymz770_device::ymz770_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t sclock)
57 	: device_t(mconfig, type, tag, owner, clock)
58 	, device_sound_interface(mconfig, *this)
59 	, m_stream(nullptr)
60 	, m_sclock(sclock)
61 	, m_cur_reg(0)
62 	, m_mute(0)
63 	, m_doen(0)
64 	, m_vlma(0)
65 	, m_vlma1(0)
66 	, m_bsl(0)
67 	, m_cpl(0)
68 	, m_rom(*this, DEVICE_SELF)
69 {
70 }
71 
72 
73 //-------------------------------------------------
74 //  device_start - device-specific startup
75 //-------------------------------------------------
76 
device_start()77 void ymz770_device::device_start()
78 {
79 	// create the stream
80 	m_stream = stream_alloc(0, 2, m_sclock);
81 
82 	for (auto & channel : m_channels)
83 	{
84 		channel.is_playing = false;
85 		channel.decoder = new mpeg_audio(&m_rom[0], mpeg_audio::AMM, false, 0);
86 	}
87 	for (auto & sequence : m_sequences)
88 		sequence.is_playing = false;
89 	for (auto & sqc : m_sqcs)
90 		sqc.is_playing = false;
91 
92 	// register for save states
93 	save_item(NAME(m_cur_reg));
94 	save_item(NAME(m_mute));
95 	save_item(NAME(m_doen));
96 	save_item(NAME(m_vlma));
97 	save_item(NAME(m_vlma1));
98 	save_item(NAME(m_bsl));
99 	save_item(NAME(m_cpl));
100 
101 	save_item(STRUCT_MEMBER(m_channels, phrase));
102 	save_item(STRUCT_MEMBER(m_channels, pan));
103 	save_item(STRUCT_MEMBER(m_channels, pan_delay));
104 	save_item(STRUCT_MEMBER(m_channels, pan1));
105 	save_item(STRUCT_MEMBER(m_channels, pan1_delay));
106 	save_item(STRUCT_MEMBER(m_channels, volume));
107 	save_item(STRUCT_MEMBER(m_channels, volume_target));
108 	save_item(STRUCT_MEMBER(m_channels, volume_delay));
109 	save_item(STRUCT_MEMBER(m_channels, volume2));
110 	save_item(STRUCT_MEMBER(m_channels, loop));
111 	save_item(STRUCT_MEMBER(m_channels, is_playing));
112 	save_item(STRUCT_MEMBER(m_channels, last_block));
113 	save_item(STRUCT_MEMBER(m_channels, is_paused));
114 	save_item(STRUCT_MEMBER(m_channels, output_remaining));
115 	save_item(STRUCT_MEMBER(m_channels, output_ptr));
116 	save_item(STRUCT_MEMBER(m_channels, atbl));
117 	save_item(STRUCT_MEMBER(m_channels, pptr));
118 	save_item(STRUCT_MEMBER(m_channels, output_data));
119 
120 	save_item(STRUCT_MEMBER(m_sequences, delay));
121 	save_item(STRUCT_MEMBER(m_sequences, sequence));
122 	save_item(STRUCT_MEMBER(m_sequences, timer));
123 	save_item(STRUCT_MEMBER(m_sequences, stopchan));
124 	save_item(STRUCT_MEMBER(m_sequences, loop));
125 	save_item(STRUCT_MEMBER(m_sequences, bank));
126 	save_item(STRUCT_MEMBER(m_sequences, is_playing));
127 	save_item(STRUCT_MEMBER(m_sequences, is_paused));
128 	save_item(STRUCT_MEMBER(m_sequences, offset));
129 
130 	save_item(STRUCT_MEMBER(m_sqcs, sqc));
131 	save_item(STRUCT_MEMBER(m_sqcs, loop));
132 	save_item(STRUCT_MEMBER(m_sqcs, is_playing));
133 	save_item(STRUCT_MEMBER(m_sqcs, is_waiting));
134 	save_item(STRUCT_MEMBER(m_sqcs, offset));
135 }
136 
137 
138 //-------------------------------------------------
139 //  device_reset - device-specific reset
140 //-------------------------------------------------
141 
device_reset()142 void ymz770_device::device_reset()
143 {
144 	for (auto & channel : m_channels)
145 	{
146 		channel.phrase = 0;
147 		channel.pan = 64;
148 		channel.pan_delay = 0;
149 		channel.pan1 = 64;
150 		channel.pan1_delay = 0;
151 		channel.volume = 0;
152 		channel.volume_target = 0;
153 		channel.volume_delay = 0;
154 		channel.volume2 = 0;
155 		channel.loop = 0;
156 		channel.is_playing = false;
157 		channel.is_paused = false;
158 		channel.output_remaining = 0;
159 		channel.decoder->clear();
160 	}
161 	for (auto & sequence : m_sequences)
162 	{
163 		sequence.delay = 0;
164 		sequence.sequence = 0;
165 		sequence.timer = 0;
166 		sequence.stopchan = 0;
167 		sequence.loop = 0;
168 		sequence.bank = 0;
169 		sequence.is_playing = false;
170 		sequence.is_paused = false;
171 	}
172 	for (auto & sqc : m_sqcs)
173 	{
174 		sqc.is_playing = false;
175 		sqc.loop = 0;
176 	}
177 }
178 
179 
180 //-------------------------------------------------
181 //  sound_stream_update - handle update requests for
182 //  our sound stream
183 //-------------------------------------------------
184 
sound_stream_update(sound_stream & stream,std::vector<read_stream_view> const & inputs,std::vector<write_stream_view> & outputs)185 void ymz770_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
186 {
187 	auto &outL = outputs[0];
188 	auto &outR = outputs[1];
189 
190 	for (int i = 0; i < outL.samples(); i++)
191 	{
192 		sequencer();
193 
194 		// process channels
195 		int32_t mixl = 0;
196 		int32_t mixr = 0;
197 
198 		for (auto & channel : m_channels)
199 		{
200 			if (channel.output_remaining > 0)
201 			{
202 				// force finish current block
203 				int32_t smpl = ((int32_t)channel.output_data[channel.output_ptr++] * (channel.volume >> 17)) >> 7;   // volume is linear, 0 - 128 (100%)
204 				smpl = (smpl * channel.volume2) >> 7;
205 				mixr += (smpl * channel.pan) >> 7;  // pan seems linear, 0 - 128, where 0 = 100% left, 128 = 100% right, 64 = 50% left 50% right
206 				mixl += (smpl * (128 - channel.pan)) >> 7;
207 				channel.output_remaining--;
208 
209 				if (channel.output_remaining == 0 && !channel.is_playing)
210 					channel.decoder->clear();
211 			}
212 
213 			else if (channel.is_playing && !channel.is_paused)
214 			{
215 retry:
216 				if (channel.last_block)
217 				{
218 					if (channel.loop)
219 					{
220 						if (channel.loop != 255)
221 							--channel.loop;
222 						// loop sample
223 						int phrase = channel.phrase;
224 						channel.atbl = m_rom[(4*phrase)+0] >> 4 & 7;
225 						channel.pptr = 8 * get_phrase_offs(phrase);
226 					}
227 					else
228 					{
229 						channel.is_playing = false;
230 						channel.output_remaining = 0;
231 						channel.decoder->clear();
232 					}
233 				}
234 
235 				if (channel.is_playing)
236 				{
237 					// next block
238 					int sample_rate, channel_count;
239 					if (!channel.decoder->decode_buffer(channel.pptr, m_rom.bytes()*8, channel.output_data, channel.output_remaining, sample_rate, channel_count) || channel.output_remaining == 0)
240 					{
241 						channel.is_playing = !channel.last_block; // detect infinite retry loop
242 						channel.last_block = true;
243 						channel.output_remaining = 0;
244 						goto retry;
245 					}
246 
247 					channel.last_block = channel.output_remaining < 1152;
248 					channel.output_remaining--;
249 					channel.output_ptr = 1;
250 
251 					int32_t smpl = ((int32_t)channel.output_data[0] * (channel.volume >> 17)) >> 7;
252 					smpl = (smpl * channel.volume2) >> 7;
253 					mixr += (smpl * channel.pan) >> 7;
254 					mixl += (smpl * (128 - channel.pan)) >> 7;
255 				}
256 			}
257 		}
258 
259 		mixr *= m_vlma; // main volume is linear, 0 - 255, where 128 = 100%
260 		mixl *= m_vlma;
261 		mixr >>= 7 - m_bsl;
262 		mixl >>= 7 - m_bsl;
263 		// Clip limiter: 0 - off, 1 - 6.02 dB (100%), 2 - 4.86 dB (87.5%), 3 - 3.52 dB (75%)
264 		constexpr int32_t ClipMax3 = 32768 * 75 / 100;
265 		constexpr int32_t ClipMax2 = 32768 * 875 / 1000;
266 		switch (m_cpl)
267 		{
268 		case 3:
269 			mixl = (mixl > ClipMax3) ? ClipMax3 : (mixl < -ClipMax3) ? -ClipMax3 : mixl;
270 			mixr = (mixr > ClipMax3) ? ClipMax3 : (mixr < -ClipMax3) ? -ClipMax3 : mixr;
271 			break;
272 		case 2:
273 			mixl = (mixl > ClipMax2) ? ClipMax2 : (mixl < -ClipMax2) ? -ClipMax2 : mixl;
274 			mixr = (mixr > ClipMax2) ? ClipMax2 : (mixr < -ClipMax2) ? -ClipMax2 : mixr;
275 			break;
276 		case 1:
277 			mixl = (mixl > 32767) ? 32767 : (mixl < -32768) ? -32768 : mixl;
278 			mixr = (mixr > 32767) ? 32767 : (mixr < -32768) ? -32768 : mixr;
279 			break;
280 		}
281 		if (m_mute)
282 			mixr = mixl = 0;
283 		outL.put_int(i, mixl, 32768);
284 		outR.put_int(i, mixr, 32768);
285 	}
286 }
287 
sequencer()288 void ymz770_device::sequencer()
289 {
290 	for (auto & sequence : m_sequences)
291 	{
292 		if (sequence.is_playing)
293 		{
294 			if (sequence.delay > 0)
295 				sequence.delay--;
296 			else
297 			{
298 				int reg = get_rom_byte(sequence.offset++);
299 				uint8_t data = get_rom_byte(sequence.offset++);
300 				switch (reg)
301 				{
302 				case 0x0f:
303 					for (int ch = 0; ch < 8; ch++) // might be wrong, ie not needed in case of loop
304 						if (sequence.stopchan & (1 << ch))
305 							m_channels[ch].is_playing = false;
306 					if (sequence.loop)
307 						sequence.offset = get_seq_offs(sequence.sequence); // loop sequence
308 					else
309 						sequence.is_playing = false;
310 					break;
311 				case 0x0e:
312 					sequence.delay = sequence.timer * 32 + 32 - 1;
313 					break;
314 				default:
315 					internal_reg_write(reg, data);
316 					break;
317 				}
318 			}
319 		}
320 	}
321 }
322 
323 //-------------------------------------------------
324 //  write - write to the chip's registers
325 //-------------------------------------------------
326 
write(offs_t offset,uint8_t data)327 void ymz770_device::write(offs_t offset, uint8_t data)
328 {
329 	if (offset & 1)
330 	{
331 		m_stream->update();
332 		internal_reg_write(m_cur_reg, data);
333 	}
334 	else
335 		m_cur_reg = data;
336 }
337 
338 
internal_reg_write(uint8_t reg,uint8_t data)339 void ymz770_device::internal_reg_write(uint8_t reg, uint8_t data)
340 {
341 	// global registers
342 	if (reg < 0x40)
343 	{
344 		switch (reg)
345 		{
346 			case 0x00:
347 				m_mute = data & 1;
348 				m_doen = data >> 1 & 1;
349 				break;
350 
351 			case 0x01:
352 				m_vlma = data;
353 				break;
354 
355 			case 0x02:
356 				m_bsl = data & 7;
357 				m_cpl = data >> 4 & 7;
358 				break;
359 
360 			// unused
361 			default:
362 				logerror("unimplemented write %02X %02X\n", reg, data);
363 				break;
364 		}
365 	}
366 
367 	// playback registers
368 	else if (reg < 0x60)
369 	{
370 		int ch = reg >> 2 & 0x07;
371 
372 		switch (reg & 0x03)
373 		{
374 			case 0:
375 				m_channels[ch].phrase = data;
376 				break;
377 
378 			case 1:
379 				m_channels[ch].volume2 = data;
380 				m_channels[ch].volume = 128 << 17;
381 				break;
382 
383 			case 2:
384 				m_channels[ch].pan = data << 3;
385 				break;
386 
387 			case 3:
388 				if ((data & 6) == 2 || ((data & 6) == 6 && !m_channels[ch].is_playing)) // both KON bits is 1 = "Keep Playing", do not restart channel in this case
389 				{
390 					uint8_t phrase = m_channels[ch].phrase;
391 					m_channels[ch].atbl = m_rom[(4*phrase)+0] >> 4 & 7;
392 					m_channels[ch].pptr = 8 * get_phrase_offs(phrase);
393 					m_channels[ch].last_block = false;
394 
395 					m_channels[ch].is_playing = true;
396 				}
397 				else if ((data & 6) == 0)
398 					m_channels[ch].is_playing = false;
399 
400 				m_channels[ch].loop = (data & 1) ? 255 : 0;
401 				break;
402 		}
403 	}
404 
405 	// sequencer registers
406 	else if (reg >= 0x80)
407 	{
408 		int ch = reg >> 4 & 0x07;
409 
410 		switch (reg & 0x0f)
411 		{
412 			case 0: // SQSN
413 				m_sequences[ch].sequence = data;
414 				break;
415 			case 1: // SQON SQLP
416 				if ((data & 6) == 2 || ((data & 6) == 6 && !m_sequences[ch].is_playing)) // both KON bits 1 is "Keep Playing"
417 				{
418 					m_sequences[ch].offset = get_seq_offs(m_sequences[ch].sequence);
419 					m_sequences[ch].delay = 0;
420 					m_sequences[ch].is_playing = true;
421 				}
422 				else if ((data & 6) == 0 && m_sequences[ch].is_playing)
423 				{
424 					m_sequences[ch].is_playing = false;
425 					for (int i = 0; i < 8; i++)
426 						if (m_sequences[ch].stopchan & (1 << i))
427 							m_channels[i].is_playing = false;
428 				}
429 
430 				m_sequences[ch].loop = data & 1;
431 				break;
432 			case 2: // TMRH
433 				m_sequences[ch].timer = (m_sequences[ch].timer & 0x00ff) | (data << 8);
434 				break;
435 			case 3: // TMRL
436 				m_sequences[ch].timer = (m_sequences[ch].timer & 0xff00) | data;
437 				break;
438 			case 6: // SQOF
439 				m_sequences[ch].stopchan = data;
440 				break;
441 			//case 4: // TGST "ON trigger playback channel selection bitmask"
442 			//case 5: // TGEN "OFF trigger playback channel selection bitmask"
443 			//case 7: // YMZ770: unused, but CV1K games write 1 here, must be game bugs or YMZ770C datasheet is wrong and have messed 7 and 8 registers ? ; YMZ771: SQOF_SSG
444 			//case 8: // YMZ770: docs said "set to 01h" but CV1K games never write it, see above. ; YMZ771: TEMPO (wait timer speed control)
445 			default:
446 				if (data)
447 					logerror("unimplemented write %02X %02X\n", reg, data);
448 				break;
449 		}
450 	}
451 	else
452 		logerror("unimplemented write %02X %02X\n", reg, data);
453 }
454 
455 //-------------------------------------------------
456 //  ymz774_device
457 //-------------------------------------------------
458 
ymz774_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)459 ymz774_device::ymz774_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
460 	: ymz770_device(mconfig, YMZ774, tag, owner, clock, 44100)
461 {
462 	// calculate volume increments, fixed point values, fractions of 0x20000
463 	for (u32 i = 0; i < 256; i++)
464 	{
465 		if (i < 0x20)
466 			volinc[i] = i;
467 		else
468 			volinc[i] = (0x20 | (i & 0x1f)) << ((i >> 5) - 1);
469 	}
470 }
471 
read(offs_t offset)472 uint8_t ymz774_device::read(offs_t offset)
473 {
474 	if (offset & 1)
475 	{
476 		if (m_cur_reg == 0xe3 || m_cur_reg == 0xe4)
477 		{
478 			m_stream->update();
479 			uint8_t res = 0;
480 			int bank = (m_cur_reg == 0xe3) ? 8 : 0;
481 			for (int i = 0; i < 8; i++)
482 				if (m_channels[i + bank].is_playing)
483 					res |= 1 << i;
484 			return res;
485 		}
486 	}
487 	logerror("unimplemented read %02X\n", m_cur_reg);
488 	return 0;
489 }
490 
internal_reg_write(uint8_t reg,uint8_t data)491 void ymz774_device::internal_reg_write(uint8_t reg, uint8_t data)
492 {
493 	// playback registers
494 	if (reg < 0x10)  // phrase num H and L
495 	{
496 		int ch = ((reg >> 1) & 7) + m_bank * 8;
497 		if (reg & 1)
498 			m_channels[ch].phrase = (m_channels[ch].phrase & 0xff00) | data;
499 		else
500 			m_channels[ch].phrase = (m_channels[ch].phrase & 0x00ff) | ((data & 7) << 8);
501 	}
502 	else if (reg < 0x60)
503 	{
504 		int ch = (reg & 7) + m_bank * 8;
505 		switch (reg & 0xf8)
506 		{
507 		case 0x10: // Volume 1
508 			m_channels[ch].volume_target = data;
509 			break;
510 		case 0x18: // Volume 1 delayed transition
511 			m_channels[ch].volume_delay = data;
512 			break;
513 		case 0x20: // Volume 2
514 			m_channels[ch].volume2 = data;
515 			break;
516 		case 0x28: // Pan L/R
517 			m_channels[ch].pan = data;
518 			break;
519 		case 0x30: // Pan L/R delayed transition
520 			if (data) logerror("unimplemented write %02X %02X\n", reg, data);
521 			m_channels[ch].pan_delay = data;
522 			break;
523 		case 0x38: // Pan T/B
524 			m_channels[ch].pan1 = data;
525 			break;
526 		case 0x40: // Pan T/B delayed transition
527 			if (data) logerror("unimplemented write %02X %02X\n", reg, data);
528 			m_channels[ch].pan1_delay = data;
529 			break;
530 		case 0x48: // Loop
531 			m_channels[ch].loop = data;
532 			break;
533 		case 0x50: // Start / Stop
534 			if (data)
535 			{
536 				int phrase = m_channels[ch].phrase;
537 				m_channels[ch].atbl = m_rom[(4 * phrase) + 0] >> 4 & 7;
538 				m_channels[ch].pptr = 8 * get_phrase_offs(phrase);
539 				m_channels[ch].last_block = false;
540 
541 				m_channels[ch].is_playing = true;
542 				m_channels[ch].is_paused = false; // checkme, might be not needed
543 			}
544 			else
545 				m_channels[ch].is_playing = false;
546 			break;
547 		case 0x58: // Pause / Resume
548 			m_channels[ch].is_paused = data ? true : false;
549 			if (data) logerror("CHECKME: CHAN pause/resume %02X %02X\n", reg, data);
550 			break;
551 		}
552 	}
553 	else if (reg < 0xd0)
554 	{
555 		if (m_bank == 0)
556 		{
557 			int sq = reg & 7;
558 			switch (reg & 0xf8)
559 			{
560 			case 0x60: // sequence num H and L
561 			case 0x68:
562 				sq = (reg >> 1) & 7;
563 				if (reg & 1)
564 					m_sequences[sq].sequence = (m_sequences[sq].sequence & 0xff00) | data;
565 				else
566 					m_sequences[sq].sequence = (m_sequences[sq].sequence & 0x00ff) | ((data & 0x07) << 8);
567 				break;
568 			case 0x70: // Start / Stop
569 				if (data)
570 				{
571 					//logerror("SEQ %d start (%s)\n", sq, m_sequences[sq].is_playing ? "playing":"stopped");
572 					m_sequences[sq].offset = get_seq_offs(m_sequences[sq].sequence);
573 					m_sequences[sq].delay = 0;
574 					m_sequences[sq].is_playing = true;
575 					m_sequences[sq].is_paused = false; // checkme, might be not needed
576 				}
577 				else
578 				{
579 					//logerror("SEQ %d stop (%s)\n", sq, m_sequences[sq].is_playing ? "playing" : "stopped");
580 					if (m_sequences[sq].is_playing)
581 						for (int ch = 0; ch < 16; ch++)
582 							if (m_sequences[sq].stopchan & (1 << ch))
583 								m_channels[ch].is_playing = false;
584 					m_sequences[sq].is_playing = false;
585 				}
586 				break;
587 			case 0x78: // Pause / Resume
588 				m_sequences[sq].is_paused = data ? true : false;
589 				if (data) logerror("CHECKME: SEQ pause/resume %02X %02X\n", reg, data);
590 				break;
591 			case 0x80: // Loop count, 0 = off, 255 - infinite
592 				m_sequences[sq].loop = data;
593 				break;
594 			case 0x88: // timer H and L
595 			case 0x90:
596 				sq = (reg - 0x88) >> 1;
597 				if (reg & 1)
598 					m_sequences[sq].timer = (m_sequences[sq].timer & 0xff00) | data;
599 				else
600 					m_sequences[sq].timer = (m_sequences[sq].timer & 0x00ff) | (data << 8);
601 				break;
602 			case 0x98: // Off trigger, bit4 = on/off, bits0-3 channel (end sequence when channel playback ends)
603 				if (data) logerror("SEQ Off trigger unimplemented %02X %02X\n", reg, data);
604 				break;
605 			case 0xa0: // stop channel mask H and L (when sequence stopped)
606 			case 0xa8:
607 				sq = (reg >> 1) & 7;
608 				if (reg & 1)
609 					m_sequences[sq].stopchan = (m_sequences[sq].stopchan & 0xff00) | data;
610 				else
611 					m_sequences[sq].stopchan = (m_sequences[sq].stopchan & 0x00ff) | (data << 8);
612 				break;
613 			case 0xb0: // SQC number
614 				m_sqcs[sq].sqc = data;
615 				break;
616 			case 0xb8: // SQC start / stop
617 				if (data)
618 				{
619 					//logerror("SQC %d start (%s)\n", sq, m_sqcs[sq].is_playing ? "playing" : "stopped");
620 					m_sqcs[sq].offset = get_sqc_offs(m_sqcs[sq].sqc);
621 					m_sqcs[sq].is_playing = true;
622 					m_sqcs[sq].is_waiting = false;
623 				}
624 				else
625 				{
626 					//logerror("SQC %d stop (%s)\n", sq, m_sqcs[sq].is_playing ? "playing" : "stopped");
627 					m_sqcs[sq].is_playing = false;
628 					// stop SEQ too, and stop channels
629 					if (m_sequences[sq].is_playing)
630 						for (int ch = 0; ch < 16; ch++)
631 							if (m_sequences[sq].stopchan & (1 << ch))
632 								m_channels[ch].is_playing = false;
633 					m_sequences[sq].is_playing = false;
634 				}
635 				break;
636 			case 0xc0: // SQC loop (255 = infinite)
637 				m_sqcs[sq].loop = data;
638 				break;
639 			default:
640 				logerror("unimplemented write %02X %02X\n", reg, data);
641 				break;
642 			}
643 		}
644 		// else bank1 - Equalizer control
645 	}
646 	// global registers
647 	else
648 	{
649 		switch (reg) {
650 		case 0xd0: // Total Volume L0/R0
651 			m_vlma = data;
652 			break;
653 		case 0xd1: // Total Volume L1/R1
654 			m_vlma1 = data;
655 			break;
656 		case 0xd2: // Clip limit
657 			m_cpl = data;
658 			break;
659 		//case 0xd3: // Digital/PWM output
660 		//case 0xd4: // Digital audio IF/IS L0/R0
661 		//case 0xd5: // Digital audio IF/IS L1/R1
662 		//case 0xd8: // GPIO A
663 		//case 0xdd: // GPIO B
664 		//case 0xde: // GPIO C
665 		case 0xf0:
666 			m_bank = data & 1;
667 			if (data > 1) logerror("Set bank %02X!\n", data);
668 			break;
669 		default:
670 			logerror("unimplemented write %02X %02X\n", reg, data);
671 			break;
672 		}
673 	}
674 }
675 
sequencer()676 void ymz774_device::sequencer()
677 {
678 	for (auto & chan : m_channels)
679 	{
680 		if (chan.is_playing && !chan.is_paused && (chan.volume >> 17) != chan.volume_target)
681 		{
682 			if (chan.volume_delay)
683 			{
684 				if ((chan.volume >> 17) < chan.volume_target)
685 					chan.volume += volinc[chan.volume_delay];
686 				else
687 					chan.volume -= volinc[chan.volume_delay];
688 			}
689 			else
690 				chan.volume = chan.volume_target << 17;
691 		}
692 	}
693 
694 	for (int i = 0; i < 8; i++)
695 	{
696 		auto & sqc = m_sqcs[i];
697 		auto & sequence = m_sequences[i];
698 
699 		if (sqc.is_playing && !sqc.is_waiting)
700 		{
701 			// SQC consists of 4 byte records: SEQ num H, SEQ num L, SEQ Loop count, End flag (0xff)
702 			sequence.sequence = ((get_rom_byte(sqc.offset) << 8) | get_rom_byte(sqc.offset + 1)) & 0x7ff;
703 			sqc.offset += 2;
704 			sequence.loop = get_rom_byte(sqc.offset++);
705 			sequence.offset = get_seq_offs(sequence.sequence);
706 			sequence.delay = 0;
707 			sequence.is_playing = true;
708 			sequence.is_paused = false; // checkme, might be not needed
709 			sqc.is_waiting = true;
710 			if (get_rom_byte(sqc.offset++) == 0xff)
711 			{
712 				if (sqc.loop)
713 				{
714 					if (sqc.loop != 255)
715 						--sqc.loop;
716 					sqc.offset = get_sqc_offs(sqc.sqc);
717 				}
718 				else
719 					sqc.is_playing = false;
720 			}
721 		}
722 
723 		if (sequence.is_playing && !sequence.is_paused)
724 		{
725 			if (sequence.delay > 0)
726 				--sequence.delay;
727 			else
728 			{
729 				int reg = get_rom_byte(sequence.offset++);
730 				uint8_t data = get_rom_byte(sequence.offset++);
731 				switch (reg)
732 				{
733 				case 0xff: // end
734 					for (int ch = 0; ch < 16; ch++) // might be wrong, ie not needed in case of loop
735 						if (sequence.stopchan & (1 << ch))
736 							m_channels[ch].is_playing = false;
737 					if (sequence.loop)
738 					{
739 						if (sequence.loop != 255)
740 							--sequence.loop;
741 						sequence.offset = get_seq_offs(sequence.sequence);
742 					}
743 					else
744 					{
745 						sequence.is_playing = false;
746 						sqc.is_waiting = false;
747 					}
748 					break;
749 				case 0xfe: // timer delay
750 					sequence.delay = sequence.timer * 32 + 32 - 1;
751 					break;
752 				case 0xf0:
753 					sequence.bank = data & 1;
754 					break;
755 				default:
756 				{
757 					uint8_t temp = m_bank;
758 					m_bank = sequence.bank;
759 					if (m_bank == 0 && reg >= 0x60 && reg < 0xb0) // if we hit SEQ registers need to add this sequence offset
760 					{
761 						int sqn = i;
762 						if (reg < 0x70 || (reg >= 0x88 && reg < 0x98) || reg >= 0xa0)
763 							sqn = i * 2;
764 						internal_reg_write(reg + sqn, data);
765 					}
766 					else
767 						internal_reg_write(reg, data);
768 					m_bank = temp;
769 				}
770 					break;
771 				}
772 			}
773 		}
774 	}
775 }
776