mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-04 20:05:05 +00:00
prepare for the last chips for 0.6pre1
YMZ280B is counted. don't worry.
This commit is contained in:
parent
0ef0296b7d
commit
251734bd04
13 changed files with 1011 additions and 4 deletions
|
@ -256,6 +256,7 @@ extern/opl/opl3.c
|
||||||
src/engine/platform/sound/sn76496.cpp
|
src/engine/platform/sound/sn76496.cpp
|
||||||
src/engine/platform/sound/ay8910.cpp
|
src/engine/platform/sound/ay8910.cpp
|
||||||
src/engine/platform/sound/saa1099.cpp
|
src/engine/platform/sound/saa1099.cpp
|
||||||
|
src/engine/platform/sound/namco.cpp
|
||||||
src/engine/platform/sound/gb/apu.c
|
src/engine/platform/sound/gb/apu.c
|
||||||
src/engine/platform/sound/gb/timing.c
|
src/engine/platform/sound/gb/timing.c
|
||||||
src/engine/platform/sound/pce_psg.cpp
|
src/engine/platform/sound/pce_psg.cpp
|
||||||
|
|
|
@ -223,6 +223,8 @@ size | description
|
||||||
| - 0xb7: PC-98 extended - 19 channels
|
| - 0xb7: PC-98 extended - 19 channels
|
||||||
| - 0xb8: YMZ280B - 8 channels
|
| - 0xb8: YMZ280B - 8 channels
|
||||||
| - 0xb9: Namco WSG - 3 channels
|
| - 0xb9: Namco WSG - 3 channels
|
||||||
|
| - 0xba: Namco 15xx - 8 channels
|
||||||
|
| - 0xbb: Namco CUS30 - 8 channels
|
||||||
| - 0xde: YM2610B extended - 19 channels
|
| - 0xde: YM2610B extended - 19 channels
|
||||||
| - 0xe0: QSound - 19 channels
|
| - 0xe0: QSound - 19 channels
|
||||||
| - 0xfd: Dummy System - 8 channels
|
| - 0xfd: Dummy System - 8 channels
|
||||||
|
@ -407,6 +409,7 @@ size | description
|
||||||
| - 28: MultiPCM
|
| - 28: MultiPCM
|
||||||
| - 29: SNES
|
| - 29: SNES
|
||||||
| - 30: Sound Unit
|
| - 30: Sound Unit
|
||||||
|
| - 31: Namco WSG
|
||||||
1 | reserved
|
1 | reserved
|
||||||
STR | instrument name
|
STR | instrument name
|
||||||
--- | **FM instrument data**
|
--- | **FM instrument data**
|
||||||
|
|
|
@ -58,6 +58,7 @@ enum DivInstrumentType: unsigned short {
|
||||||
DIV_INS_MULTIPCM=28,
|
DIV_INS_MULTIPCM=28,
|
||||||
DIV_INS_SNES=29,
|
DIV_INS_SNES=29,
|
||||||
DIV_INS_SU=30,
|
DIV_INS_SU=30,
|
||||||
|
DIV_INS_NAMCO=31,
|
||||||
DIV_INS_MAX,
|
DIV_INS_MAX,
|
||||||
DIV_INS_NULL
|
DIV_INS_NULL
|
||||||
};
|
};
|
||||||
|
|
|
@ -581,7 +581,7 @@ YM2203 English datasheet: http://www.appleii-box.de/APPLE2/JonasCard/YM2203%20da
|
||||||
YM2203 Japanese datasheet contents, translated: http://www.larwe.com/technical/chip_ym2203.html
|
YM2203 Japanese datasheet contents, translated: http://www.larwe.com/technical/chip_ym2203.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// additional modifications by tildearrow and Eulous for furnace (particularly AY8930 emulation)
|
// additional modifications by tildearrow, Eulous, cam900 and Grauw for furnace (particularly AY8930 emulation)
|
||||||
|
|
||||||
#include "ay8910.h"
|
#include "ay8910.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
804
src/engine/platform/sound/namco.cpp
Normal file
804
src/engine/platform/sound/namco.cpp
Normal file
|
@ -0,0 +1,804 @@
|
||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Nicola Salmoria,Aaron Giles
|
||||||
|
/***************************************************************************
|
||||||
|
|
||||||
|
NAMCO sound driver.
|
||||||
|
|
||||||
|
This driver handles the four known types of NAMCO wavetable sounds:
|
||||||
|
|
||||||
|
- 3-voice mono (PROM-based design: Pac-Man, Pengo, Dig Dug, etc)
|
||||||
|
- 8-voice quadrophonic (Pole Position 1, Pole Position 2)
|
||||||
|
- 8-voice mono (custom 15XX: Mappy, Dig Dug 2, etc)
|
||||||
|
- 8-voice stereo (System 1)
|
||||||
|
|
||||||
|
The 15XX custom does not have a DAC of its own; instead, it streams
|
||||||
|
the 4-bit PROM data directly into the 99XX custom DAC. Most pre-99XX
|
||||||
|
(and pre-15XX) Namco games use a LS273 latch (cleared when sound is
|
||||||
|
disabled), a 4.7K/2.2K/1K/470 resistor-weighted DAC, and a 4066 and
|
||||||
|
second group of resistors (10K/22K/47K/100K) for volume control.
|
||||||
|
Pole Position does more complicated sound mixing: a 4051 multiplexes
|
||||||
|
wavetable sound with four signals derived from the 52XX and 54XX, the
|
||||||
|
selected signal is distributed to four volume control sections, and
|
||||||
|
finally the engine noise is mixed into all four channels. The later
|
||||||
|
CUS30 also uses the 99XX DAC, or two 99XX in the optional 16-channel
|
||||||
|
stereo configuration, but it uses no PROM and delivers its own samples.
|
||||||
|
|
||||||
|
The CUS30 has been decapped and verified to be a ULA.
|
||||||
|
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
// additional modifications by tildearrow for furnace
|
||||||
|
|
||||||
|
#include "namco.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* quality parameter: internal sample rate is 192 KHz, output is 48 KHz */
|
||||||
|
#define INTERNAL_RATE 192000
|
||||||
|
|
||||||
|
/* 16 bits: sample bits of the stream buffer */
|
||||||
|
/* 4 bits: volume */
|
||||||
|
/* 4 bits: prom sample bits */
|
||||||
|
#define MIXLEVEL (1 << (16 - 4 - 4))
|
||||||
|
|
||||||
|
/* stream output level */
|
||||||
|
#define OUTPUT_LEVEL(n) ((n) * MIXLEVEL / m_voices)
|
||||||
|
|
||||||
|
/* a position of waveform sample */
|
||||||
|
#define WAVEFORM_POSITION(n) (((n) >> m_f_fracbits) & 0x1f)
|
||||||
|
|
||||||
|
namco_audio_device::namco_audio_device(uint32_t clock)
|
||||||
|
: m_wave_ptr(NULL)
|
||||||
|
, m_last_channel(nullptr)
|
||||||
|
, m_wavedata(nullptr)
|
||||||
|
, m_wave_size(0)
|
||||||
|
, m_sound_enable(false)
|
||||||
|
, m_namco_clock(0)
|
||||||
|
, m_sample_rate(0)
|
||||||
|
, m_f_fracbits(0)
|
||||||
|
, m_voices(0)
|
||||||
|
, m_stereo(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
namco_device::namco_device(uint32_t clock)
|
||||||
|
: namco_audio_device(clock)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
namco_15xx_device::namco_15xx_device(uint32_t clock)
|
||||||
|
:namco_audio_device(clock)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
namco_cus30_device::namco_cus30_device(uint32_t clock)
|
||||||
|
: namco_audio_device(clock)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// device_start - device-specific startup
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void namco_audio_device::device_start()
|
||||||
|
{
|
||||||
|
/* extract globals from the interface */
|
||||||
|
m_last_channel = m_channel_list + m_voices;
|
||||||
|
|
||||||
|
/* build the waveform table */
|
||||||
|
build_decoded_waveform(m_wave_ptr);
|
||||||
|
|
||||||
|
/* start with sound enabled, many games don't have a sound enable register */
|
||||||
|
m_sound_enable = true;
|
||||||
|
|
||||||
|
/* reset all the voices */
|
||||||
|
for (sound_channel *voice = m_channel_list; voice < m_last_channel; voice++)
|
||||||
|
{
|
||||||
|
voice->frequency = 0;
|
||||||
|
voice->volume[0] = voice->volume[1] = 0;
|
||||||
|
voice->waveform_select = 0;
|
||||||
|
voice->counter = 0;
|
||||||
|
voice->noise_sw = 0;
|
||||||
|
voice->noise_state = 0;
|
||||||
|
voice->noise_seed = 1;
|
||||||
|
voice->noise_counter = 0;
|
||||||
|
voice->noise_hold = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void namco_device::device_start()
|
||||||
|
{
|
||||||
|
namco_audio_device::device_start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void namco_15xx_device::device_start()
|
||||||
|
{
|
||||||
|
namco_audio_device::device_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void namco_audio_device::device_clock_changed()
|
||||||
|
{
|
||||||
|
int clock_multiple;
|
||||||
|
|
||||||
|
/* adjust internal clock */
|
||||||
|
m_namco_clock = clock();
|
||||||
|
for (clock_multiple = 0; m_namco_clock < INTERNAL_RATE; clock_multiple++)
|
||||||
|
m_namco_clock *= 2;
|
||||||
|
|
||||||
|
m_f_fracbits = clock_multiple + 15;
|
||||||
|
|
||||||
|
/* adjust output clock */
|
||||||
|
m_sample_rate = m_namco_clock;
|
||||||
|
|
||||||
|
//logerror("Namco: freq fractional bits = %d: internal freq = %d, output freq = %d\n", m_f_fracbits, m_namco_clock, m_sample_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* update the decoded waveform data */
|
||||||
|
void namco_audio_device::update_namco_waveform(int offset, uint8_t data)
|
||||||
|
{
|
||||||
|
if (m_wave_size == 1)
|
||||||
|
{
|
||||||
|
int16_t wdata;
|
||||||
|
int v;
|
||||||
|
|
||||||
|
/* use full byte, first 4 high bits, then low 4 bits */
|
||||||
|
for (v = 0; v < (int)MAX_VOLUME; v++)
|
||||||
|
{
|
||||||
|
wdata = ((data >> 4) & 0x0f) - 8;
|
||||||
|
m_waveform[v][offset * 2] = OUTPUT_LEVEL(wdata * v);
|
||||||
|
wdata = (data & 0x0f) - 8;
|
||||||
|
m_waveform[v][offset * 2 + 1] = OUTPUT_LEVEL(wdata * v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int v;
|
||||||
|
|
||||||
|
/* use only low 4 bits */
|
||||||
|
for (v = 0; v < (int)MAX_VOLUME; v++)
|
||||||
|
m_waveform[v][offset] = OUTPUT_LEVEL(((data & 0x0f) - 8) * v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* build the decoded waveform table */
|
||||||
|
void namco_audio_device::build_decoded_waveform(uint8_t *rgnbase)
|
||||||
|
{
|
||||||
|
if (rgnbase != nullptr)
|
||||||
|
m_wavedata = rgnbase;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_wavedata = m_waveram_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int offset = 0; offset < 256; offset++)
|
||||||
|
update_namco_waveform(offset, m_wavedata[offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* generate sound by oversampling */
|
||||||
|
uint32_t namco_audio_device::namco_update_one(short* buffer, int size, const int16_t *wave, uint32_t counter, uint32_t freq)
|
||||||
|
{
|
||||||
|
for (int sampindex = 0; sampindex < size; sampindex++)
|
||||||
|
{
|
||||||
|
buffer[sampindex]=wave[WAVEFORM_POSITION(counter)];
|
||||||
|
counter += freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void namco_audio_device::sound_enable_w(int state)
|
||||||
|
{
|
||||||
|
m_sound_enable = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************************/
|
||||||
|
|
||||||
|
/* pacman register map
|
||||||
|
0x05: ch 0 waveform select
|
||||||
|
0x0a: ch 1 waveform select
|
||||||
|
0x0f: ch 2 waveform select
|
||||||
|
|
||||||
|
0x10: ch 0 the first voice has extra frequency bits
|
||||||
|
0x11-0x14: ch 0 frequency
|
||||||
|
0x15: ch 0 volume
|
||||||
|
|
||||||
|
0x16-0x19: ch 1 frequency
|
||||||
|
0x1a: ch 1 volume
|
||||||
|
|
||||||
|
0x1b-0x1e: ch 2 frequency
|
||||||
|
0x1f: ch 2 volume
|
||||||
|
*/
|
||||||
|
|
||||||
|
void namco_device::pacman_sound_w(int offset, uint8_t data)
|
||||||
|
{
|
||||||
|
sound_channel *voice;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
data &= 0x0f;
|
||||||
|
if (m_soundregs[offset] == data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* set the register */
|
||||||
|
m_soundregs[offset] = data;
|
||||||
|
|
||||||
|
if (offset < 0x10)
|
||||||
|
ch = (offset - 5) / 5;
|
||||||
|
else if (offset == 0x10)
|
||||||
|
ch = 0;
|
||||||
|
else
|
||||||
|
ch = (offset - 0x11) / 5;
|
||||||
|
|
||||||
|
if (ch >= m_voices)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* recompute the voice parameters */
|
||||||
|
voice = m_channel_list + ch;
|
||||||
|
switch (offset - ch * 5)
|
||||||
|
{
|
||||||
|
case 0x05:
|
||||||
|
voice->waveform_select = data & 7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x10:
|
||||||
|
case 0x11:
|
||||||
|
case 0x12:
|
||||||
|
case 0x13:
|
||||||
|
case 0x14:
|
||||||
|
/* the frequency has 20 bits */
|
||||||
|
/* the first voice has extra frequency bits */
|
||||||
|
voice->frequency = (ch == 0) ? m_soundregs[0x10] : 0;
|
||||||
|
voice->frequency += (m_soundregs[ch * 5 + 0x11] << 4);
|
||||||
|
voice->frequency += (m_soundregs[ch * 5 + 0x12] << 8);
|
||||||
|
voice->frequency += (m_soundregs[ch * 5 + 0x13] << 12);
|
||||||
|
voice->frequency += (m_soundregs[ch * 5 + 0x14] << 16); /* always 0 */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x15:
|
||||||
|
voice->volume[0] = data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void namco_cus30_device::pacman_sound_w(int offset, uint8_t data)
|
||||||
|
{
|
||||||
|
sound_channel *voice;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
uint8_t *soundregs = &m_wavedata[0x100];
|
||||||
|
|
||||||
|
data &= 0x0f;
|
||||||
|
if (soundregs[offset] == data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* set the register */
|
||||||
|
soundregs[offset] = data;
|
||||||
|
|
||||||
|
if (offset < 0x10)
|
||||||
|
ch = (offset - 5) / 5;
|
||||||
|
else if (offset == 0x10)
|
||||||
|
ch = 0;
|
||||||
|
else
|
||||||
|
ch = (offset - 0x11) / 5;
|
||||||
|
|
||||||
|
if (ch >= m_voices)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* recompute the voice parameters */
|
||||||
|
voice = m_channel_list + ch;
|
||||||
|
switch (offset - ch * 5)
|
||||||
|
{
|
||||||
|
case 0x05:
|
||||||
|
voice->waveform_select = data & 7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x10:
|
||||||
|
case 0x11:
|
||||||
|
case 0x12:
|
||||||
|
case 0x13:
|
||||||
|
case 0x14:
|
||||||
|
/* the frequency has 20 bits */
|
||||||
|
/* the first voice has extra frequency bits */
|
||||||
|
voice->frequency = (ch == 0) ? soundregs[0x10] : 0;
|
||||||
|
voice->frequency += (soundregs[ch * 5 + 0x11] << 4);
|
||||||
|
voice->frequency += (soundregs[ch * 5 + 0x12] << 8);
|
||||||
|
voice->frequency += (soundregs[ch * 5 + 0x13] << 12);
|
||||||
|
voice->frequency += (soundregs[ch * 5 + 0x14] << 16); /* always 0 */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x15:
|
||||||
|
voice->volume[0] = data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************************/
|
||||||
|
|
||||||
|
/* polepos register map
|
||||||
|
Note: even if there are 8 voices, the game doesn't use the first 2 because
|
||||||
|
it select the 54XX/52XX outputs on those channels
|
||||||
|
|
||||||
|
0x00-0x01 ch 0 frequency
|
||||||
|
0x02 ch 0 xxxx---- GAIN 2 volume
|
||||||
|
0x03 ch 0 xxxx---- GAIN 3 volume
|
||||||
|
----xxxx GAIN 4 volume
|
||||||
|
|
||||||
|
0x04-0x07 ch 1
|
||||||
|
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
|
||||||
|
0x1c-0x1f ch 7
|
||||||
|
|
||||||
|
0x23 ch 0 xxxx---- GAIN 1 volume
|
||||||
|
-----xxx waveform select
|
||||||
|
----x-xx channel output select
|
||||||
|
0-7 (all the same, shared with waveform select) = wave
|
||||||
|
8 = CHANL1 (54XX pins 17-20)
|
||||||
|
9 = CHANL2 (54XX pins 8-11)
|
||||||
|
A = CHANL3 (54XX pins 4-7)
|
||||||
|
B = CHANL4 (52XX)
|
||||||
|
0x27 ch 1
|
||||||
|
0x2b ch 2
|
||||||
|
0x2f ch 3
|
||||||
|
0x33 ch 4
|
||||||
|
0x37 ch 5
|
||||||
|
0x3b ch 6
|
||||||
|
0x3f ch 7
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint8_t namco_device::polepos_sound_r(int offset)
|
||||||
|
{
|
||||||
|
return m_soundregs[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
void namco_device::polepos_sound_w(int offset, uint8_t data)
|
||||||
|
{
|
||||||
|
sound_channel *voice;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
if (m_soundregs[offset] == data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* set the register */
|
||||||
|
m_soundregs[offset] = data;
|
||||||
|
|
||||||
|
ch = (offset & 0x1f) / 4;
|
||||||
|
|
||||||
|
/* recompute the voice parameters */
|
||||||
|
voice = m_channel_list + ch;
|
||||||
|
switch (offset & 0x23)
|
||||||
|
{
|
||||||
|
case 0x00:
|
||||||
|
case 0x01:
|
||||||
|
/* the frequency has 16 bits */
|
||||||
|
voice->frequency = m_soundregs[ch * 4 + 0x00];
|
||||||
|
voice->frequency += m_soundregs[ch * 4 + 0x01] << 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x23:
|
||||||
|
voice->waveform_select = data & 7;
|
||||||
|
[[fallthrough]];
|
||||||
|
case 0x02:
|
||||||
|
case 0x03:
|
||||||
|
voice->volume[0] = voice->volume[1] = 0;
|
||||||
|
// front speakers ?
|
||||||
|
voice->volume[0] += m_soundregs[ch * 4 + 0x03] >> 4;
|
||||||
|
voice->volume[1] += m_soundregs[ch * 4 + 0x03] & 0x0f;
|
||||||
|
// rear speakers ?
|
||||||
|
voice->volume[0] += m_soundregs[ch * 4 + 0x23] >> 4;
|
||||||
|
voice->volume[1] += m_soundregs[ch * 4 + 0x02] >> 4;
|
||||||
|
|
||||||
|
voice->volume[0] /= 2;
|
||||||
|
voice->volume[1] /= 2;
|
||||||
|
|
||||||
|
/* if 54XX or 52XX selected, silence this voice */
|
||||||
|
if (m_soundregs[ch * 4 + 0x23] & 8)
|
||||||
|
voice->volume[0] = voice->volume[1] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************************/
|
||||||
|
|
||||||
|
/* 15XX register map
|
||||||
|
0x03 ch 0 volume
|
||||||
|
0x04-0x05 ch 0 frequency
|
||||||
|
0x06 ch 0 waveform select & frequency
|
||||||
|
|
||||||
|
0x0b ch 1 volume
|
||||||
|
0x0c-0x0d ch 1 frequency
|
||||||
|
0x0e ch 1 waveform select & frequency
|
||||||
|
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
|
||||||
|
0x3b ch 7 volume
|
||||||
|
0x3c-0x3d ch 7 frequency
|
||||||
|
0x3e ch 7 waveform select & frequency
|
||||||
|
|
||||||
|
Grobda also stuffs values into register offset 0x02 with a frequency of zero
|
||||||
|
to make 15XX channels act like a 4-bit DAC instead of waveform voices. This
|
||||||
|
has been emulated by allowing writes to set the upper counter bits directly.
|
||||||
|
Possibly offsets 0x00 and 0x01 can be used to set the fractional bits.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <typename T, typename U> constexpr T make_bitmask(U n)
|
||||||
|
{
|
||||||
|
return T((n < (int)(8 * sizeof(T)) ? (std::make_unsigned_t<T>(1) << n) : std::make_unsigned_t<T>(0)) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void namco_15xx_device::namco_15xx_w(int offset, uint8_t data)
|
||||||
|
{
|
||||||
|
sound_channel *voice;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
if (m_soundregs[offset] == data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* set the register */
|
||||||
|
m_soundregs[offset] = data;
|
||||||
|
|
||||||
|
ch = offset / 8;
|
||||||
|
if (ch >= m_voices)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* recompute the voice parameters */
|
||||||
|
voice = m_channel_list + ch;
|
||||||
|
switch (offset - ch * 8)
|
||||||
|
{
|
||||||
|
case 0x02:
|
||||||
|
voice->counter &= make_bitmask<uint32_t>(m_f_fracbits);
|
||||||
|
voice->counter |= uint32_t(data & 0x1f) << m_f_fracbits;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x03:
|
||||||
|
voice->volume[0] = data & 0x0f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x06:
|
||||||
|
voice->waveform_select = (data >> 4) & 7;
|
||||||
|
[[fallthrough]];
|
||||||
|
case 0x04:
|
||||||
|
case 0x05:
|
||||||
|
/* the frequency has 20 bits */
|
||||||
|
voice->frequency = m_soundregs[ch * 8 + 0x04];
|
||||||
|
voice->frequency += m_soundregs[ch * 8 + 0x05] << 8;
|
||||||
|
voice->frequency += (m_soundregs[ch * 8 + 0x06] & 15) << 16; /* high bits are from here */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************************/
|
||||||
|
|
||||||
|
/* namcos1 register map
|
||||||
|
0x00 ch 0 left volume
|
||||||
|
0x01 ch 0 waveform select & frequency
|
||||||
|
0x02-0x03 ch 0 frequency
|
||||||
|
0x04 ch 0 right volume AND
|
||||||
|
0x04 ch 1 noise sw
|
||||||
|
|
||||||
|
0x08 ch 1 left volume
|
||||||
|
0x09 ch 1 waveform select & frequency
|
||||||
|
0x0a-0x0b ch 1 frequency
|
||||||
|
0x0c ch 1 right volume AND
|
||||||
|
0x0c ch 2 noise sw
|
||||||
|
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
|
||||||
|
0x38 ch 7 left volume
|
||||||
|
0x39 ch 7 waveform select & frequency
|
||||||
|
0x3a-0x3b ch 7 frequency
|
||||||
|
0x3c ch 7 right volume AND
|
||||||
|
0x3c ch 0 noise sw
|
||||||
|
*/
|
||||||
|
|
||||||
|
void namco_cus30_device::namcos1_sound_w(int offset, uint8_t data)
|
||||||
|
{
|
||||||
|
sound_channel *voice;
|
||||||
|
int ch;
|
||||||
|
int nssw;
|
||||||
|
|
||||||
|
|
||||||
|
/* verify the offset */
|
||||||
|
if (offset > 63)
|
||||||
|
{
|
||||||
|
//logerror("NAMCOS1 sound: Attempting to write past the 64 registers segment\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *soundregs = &m_wavedata[0x100];
|
||||||
|
|
||||||
|
if (soundregs[offset] == data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* set the register */
|
||||||
|
soundregs[offset] = data;
|
||||||
|
|
||||||
|
ch = offset / 8;
|
||||||
|
if (ch >= m_voices)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* recompute the voice parameters */
|
||||||
|
voice = m_channel_list + ch;
|
||||||
|
switch (offset - ch * 8)
|
||||||
|
{
|
||||||
|
case 0x00:
|
||||||
|
voice->volume[0] = data & 0x0f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x01:
|
||||||
|
voice->waveform_select = (data >> 4) & 15;
|
||||||
|
[[fallthrough]];
|
||||||
|
case 0x02:
|
||||||
|
case 0x03:
|
||||||
|
/* the frequency has 20 bits */
|
||||||
|
voice->frequency = (soundregs[ch * 8 + 0x01] & 15) << 16; /* high bits are from here */
|
||||||
|
voice->frequency += soundregs[ch * 8 + 0x02] << 8;
|
||||||
|
voice->frequency += soundregs[ch * 8 + 0x03];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x04:
|
||||||
|
voice->volume[1] = data & 0x0f;
|
||||||
|
|
||||||
|
nssw = ((data & 0x80) >> 7);
|
||||||
|
if (++voice == m_last_channel)
|
||||||
|
voice = m_channel_list;
|
||||||
|
voice->noise_sw = nssw;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void namco_cus30_device::namcos1_cus30_w(int offset, uint8_t data)
|
||||||
|
{
|
||||||
|
if (offset < 0x100)
|
||||||
|
{
|
||||||
|
if (m_wavedata[offset] != data)
|
||||||
|
{
|
||||||
|
|
||||||
|
m_wavedata[offset] = data;
|
||||||
|
|
||||||
|
/* update the decoded waveform table */
|
||||||
|
update_namco_waveform(offset, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (offset < 0x140)
|
||||||
|
namcos1_sound_w(offset - 0x100,data);
|
||||||
|
else
|
||||||
|
m_wavedata[offset] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t namco_cus30_device::namcos1_cus30_r(int offset)
|
||||||
|
{
|
||||||
|
return m_wavedata[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t namco_15xx_device::sharedram_r(int offset)
|
||||||
|
{
|
||||||
|
return m_soundregs[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
void namco_15xx_device::sharedram_w(int offset, uint8_t data)
|
||||||
|
{
|
||||||
|
if (offset < 0x40)
|
||||||
|
namco_15xx_w(offset, data);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_soundregs[offset] = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// sound_stream_update - handle a stream update
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void namco_audio_device::sound_stream_update(short** outputs, int len)
|
||||||
|
{
|
||||||
|
if (m_stereo)
|
||||||
|
{
|
||||||
|
/* zap the contents of the buffers */
|
||||||
|
memset(outputs[0],0,len*sizeof(short));
|
||||||
|
memset(outputs[1],0,len*sizeof(short));
|
||||||
|
|
||||||
|
/* if no sound, we're done */
|
||||||
|
if (!m_sound_enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* loop over each voice and add its contribution */
|
||||||
|
for (sound_channel *voice = m_channel_list; voice < m_last_channel; voice++)
|
||||||
|
{
|
||||||
|
short* lmix = outputs[0];
|
||||||
|
short* rmix = outputs[1];
|
||||||
|
int lv = voice->volume[0];
|
||||||
|
int rv = voice->volume[1];
|
||||||
|
|
||||||
|
if (voice->noise_sw)
|
||||||
|
{
|
||||||
|
int f = voice->frequency & 0xff;
|
||||||
|
|
||||||
|
/* only update if we have non-zero volume */
|
||||||
|
if (lv || rv)
|
||||||
|
{
|
||||||
|
int hold_time = 1 << (m_f_fracbits - 16);
|
||||||
|
int hold = voice->noise_hold;
|
||||||
|
uint32_t delta = f << 4;
|
||||||
|
uint32_t c = voice->noise_counter;
|
||||||
|
int16_t l_noise_data = OUTPUT_LEVEL(0x07 * (lv >> 1));
|
||||||
|
int16_t r_noise_data = OUTPUT_LEVEL(0x07 * (rv >> 1));
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* add our contribution */
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
if (voice->noise_state)
|
||||||
|
{
|
||||||
|
lmix[i]=l_noise_data;
|
||||||
|
rmix[i]=r_noise_data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lmix[i]=-l_noise_data;
|
||||||
|
rmix[i]=-r_noise_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hold)
|
||||||
|
{
|
||||||
|
hold--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hold = hold_time;
|
||||||
|
|
||||||
|
c += delta;
|
||||||
|
cnt = (c >> 12);
|
||||||
|
c &= (1 << 12) - 1;
|
||||||
|
for( ;cnt > 0; cnt--)
|
||||||
|
{
|
||||||
|
if ((voice->noise_seed + 1) & 2) voice->noise_state ^= 1;
|
||||||
|
if (voice->noise_seed & 1) voice->noise_seed ^= 0x28000;
|
||||||
|
voice->noise_seed >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update the counter and hold time for this voice */
|
||||||
|
voice->noise_counter = c;
|
||||||
|
voice->noise_hold = hold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* save the counter for this voice */
|
||||||
|
uint32_t c = voice->counter;
|
||||||
|
|
||||||
|
/* only update if we have non-zero left volume */
|
||||||
|
if (lv)
|
||||||
|
{
|
||||||
|
const int16_t *lw = &m_waveform[lv][voice->waveform_select * 32];
|
||||||
|
|
||||||
|
/* generate sound into the buffer */
|
||||||
|
c = namco_update_one(lmix, len, lw, voice->counter, voice->frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only update if we have non-zero right volume */
|
||||||
|
if (rv)
|
||||||
|
{
|
||||||
|
const int16_t *rw = &m_waveform[rv][voice->waveform_select * 32];
|
||||||
|
|
||||||
|
/* generate sound into the buffer */
|
||||||
|
c = namco_update_one(rmix, len, rw, voice->counter, voice->frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update the counter for this voice */
|
||||||
|
voice->counter = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sound_channel *voice;
|
||||||
|
|
||||||
|
short* buffer = outputs[0];
|
||||||
|
/* zap the contents of the buffer */
|
||||||
|
memset(buffer,0,len*sizeof(short));
|
||||||
|
|
||||||
|
/* if no sound, we're done */
|
||||||
|
if (!m_sound_enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* loop over each voice and add its contribution */
|
||||||
|
for (voice = m_channel_list; voice < m_last_channel; voice++)
|
||||||
|
{
|
||||||
|
int v = voice->volume[0];
|
||||||
|
if (voice->noise_sw)
|
||||||
|
{
|
||||||
|
int f = voice->frequency & 0xff;
|
||||||
|
|
||||||
|
/* only update if we have non-zero volume */
|
||||||
|
if (v)
|
||||||
|
{
|
||||||
|
int hold_time = 1 << (m_f_fracbits - 16);
|
||||||
|
int hold = voice->noise_hold;
|
||||||
|
uint32_t delta = f << 4;
|
||||||
|
uint32_t c = voice->noise_counter;
|
||||||
|
int16_t noise_data = OUTPUT_LEVEL(0x07 * (v >> 1));
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* add our contribution */
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
if (voice->noise_state)
|
||||||
|
buffer[i]=noise_data;
|
||||||
|
else
|
||||||
|
buffer[i]=-noise_data;
|
||||||
|
|
||||||
|
if (hold)
|
||||||
|
{
|
||||||
|
hold--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hold = hold_time;
|
||||||
|
|
||||||
|
c += delta;
|
||||||
|
cnt = (c >> 12);
|
||||||
|
c &= (1 << 12) - 1;
|
||||||
|
for( ;cnt > 0; cnt--)
|
||||||
|
{
|
||||||
|
if ((voice->noise_seed + 1) & 2) voice->noise_state ^= 1;
|
||||||
|
if (voice->noise_seed & 1) voice->noise_seed ^= 0x28000;
|
||||||
|
voice->noise_seed >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update the counter and hold time for this voice */
|
||||||
|
voice->noise_counter = c;
|
||||||
|
voice->noise_hold = hold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* only update if we have non-zero volume */
|
||||||
|
if (v)
|
||||||
|
{
|
||||||
|
const int16_t *w = &m_waveform[v][voice->waveform_select * 32];
|
||||||
|
|
||||||
|
/* generate sound into buffer and update the counter for this voice */
|
||||||
|
voice->counter = namco_update_one(buffer, len, w, voice->counter, voice->frequency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void namco_device::sound_stream_update(short** outputs, int len)
|
||||||
|
{
|
||||||
|
namco_audio_device::sound_stream_update(outputs,len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void namco_15xx_device::sound_stream_update(short** outputs, int len)
|
||||||
|
{
|
||||||
|
namco_audio_device::sound_stream_update(outputs,len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void namco_cus30_device::sound_stream_update(short** outputs, int len)
|
||||||
|
{
|
||||||
|
namco_audio_device::sound_stream_update(outputs,len);
|
||||||
|
}
|
130
src/engine/platform/sound/namco.h
Normal file
130
src/engine/platform/sound/namco.h
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Nicola Salmoria,Aaron Giles
|
||||||
|
#ifndef MAME_SOUND_NAMCO_H
|
||||||
|
#define MAME_SOUND_NAMCO_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class namco_audio_device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// configuration
|
||||||
|
void set_voices(int voices) { m_voices = voices; }
|
||||||
|
void set_stereo(bool stereo) { m_stereo = stereo; }
|
||||||
|
|
||||||
|
void sound_enable_w(int state);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static constexpr unsigned MAX_VOICES = 8;
|
||||||
|
static constexpr unsigned MAX_VOLUME = 16;
|
||||||
|
|
||||||
|
/* this structure defines the parameters for a channel */
|
||||||
|
struct sound_channel
|
||||||
|
{
|
||||||
|
uint32_t frequency;
|
||||||
|
uint32_t counter;
|
||||||
|
int32_t volume[2];
|
||||||
|
int32_t noise_sw;
|
||||||
|
int32_t noise_state;
|
||||||
|
int32_t noise_seed;
|
||||||
|
uint32_t noise_counter;
|
||||||
|
int32_t noise_hold;
|
||||||
|
int32_t waveform_select;
|
||||||
|
};
|
||||||
|
|
||||||
|
namco_audio_device(uint32_t clock);
|
||||||
|
|
||||||
|
// device-level overrides
|
||||||
|
void device_start();
|
||||||
|
void device_clock_changed();
|
||||||
|
|
||||||
|
// internal state
|
||||||
|
|
||||||
|
void build_decoded_waveform( uint8_t *rgnbase );
|
||||||
|
void update_namco_waveform(int offset, uint8_t data);
|
||||||
|
uint32_t namco_update_one(short* buffer, int size, const int16_t *wave, uint32_t counter, uint32_t freq);
|
||||||
|
|
||||||
|
/* waveform region */
|
||||||
|
uint8_t* m_wave_ptr;
|
||||||
|
|
||||||
|
/* data about the sound system */
|
||||||
|
sound_channel m_channel_list[MAX_VOICES];
|
||||||
|
sound_channel *m_last_channel;
|
||||||
|
uint8_t *m_wavedata;
|
||||||
|
|
||||||
|
/* global sound parameters */
|
||||||
|
int m_wave_size;
|
||||||
|
bool m_sound_enable;
|
||||||
|
int m_namco_clock;
|
||||||
|
int m_sample_rate;
|
||||||
|
int m_f_fracbits;
|
||||||
|
|
||||||
|
int m_voices; /* number of voices */
|
||||||
|
bool m_stereo; /* set to indicate stereo (e.g., System 1) */
|
||||||
|
|
||||||
|
uint8_t m_waveram_alloc[0x400];
|
||||||
|
|
||||||
|
/* decoded waveform table */
|
||||||
|
int16_t m_waveform[MAX_VOLUME][512];
|
||||||
|
|
||||||
|
virtual void sound_stream_update(short** outputs, int len);
|
||||||
|
};
|
||||||
|
|
||||||
|
class namco_device : public namco_audio_device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
namco_device(uint32_t clock);
|
||||||
|
|
||||||
|
void pacman_sound_w(int offset, uint8_t data);
|
||||||
|
|
||||||
|
uint8_t polepos_sound_r(int offset);
|
||||||
|
void polepos_sound_w(int offset, uint8_t data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// device-level overrides
|
||||||
|
virtual void device_start();
|
||||||
|
|
||||||
|
virtual void sound_stream_update(short** outputs, int len);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t m_soundregs[0x400];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class namco_15xx_device : public namco_audio_device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
namco_15xx_device(uint32_t clock);
|
||||||
|
|
||||||
|
void namco_15xx_w(int offset, uint8_t data);
|
||||||
|
uint8_t sharedram_r(int offset);
|
||||||
|
void sharedram_w(int offset, uint8_t data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// device-level overrides
|
||||||
|
virtual void device_start();
|
||||||
|
|
||||||
|
virtual void sound_stream_update(short** outputs, int len);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t m_soundregs[0x400];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class namco_cus30_device : public namco_audio_device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
namco_cus30_device(uint32_t clock);
|
||||||
|
|
||||||
|
void namcos1_cus30_w(int offset, uint8_t data); /* wavedata + sound registers + RAM */
|
||||||
|
uint8_t namcos1_cus30_r(int offset);
|
||||||
|
void namcos1_sound_w(int offset, uint8_t data);
|
||||||
|
|
||||||
|
void pacman_sound_w(int offset, uint8_t data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void sound_stream_update(short** outputs, int len);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAME_SOUND_NAMCO_H
|
|
@ -107,6 +107,9 @@ enum DivSystem {
|
||||||
DIV_SYSTEM_SOUND_UNIT,
|
DIV_SYSTEM_SOUND_UNIT,
|
||||||
DIV_SYSTEM_MSM6295,
|
DIV_SYSTEM_MSM6295,
|
||||||
DIV_SYSTEM_MSM6258,
|
DIV_SYSTEM_MSM6258,
|
||||||
|
DIV_SYSTEM_NAMCO,
|
||||||
|
DIV_SYSTEM_NAMCO_15XX,
|
||||||
|
DIV_SYSTEM_NAMCO_CUS30,
|
||||||
DIV_SYSTEM_DUMMY
|
DIV_SYSTEM_DUMMY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1966,9 +1966,42 @@ void DivEngine::registerSystems() {
|
||||||
{DIV_INS_AMIGA}
|
{DIV_INS_AMIGA}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
sysDefs[DIV_SYSTEM_NAMCO]=new DivSysDef(
|
||||||
|
"Namco WSG", NULL, 0xb9, 0, 3, false, true, 0, false,
|
||||||
|
"a wavetable sound chip used in Pac-Man, among other early Namco arcade games.",
|
||||||
|
{"Channel 1", "Channel 2", "Channel 3"},
|
||||||
|
{"CH1", "CH2", "CH3"},
|
||||||
|
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
{DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO},
|
||||||
|
{},
|
||||||
|
waveOnlyEffectHandler
|
||||||
|
);
|
||||||
|
|
||||||
|
sysDefs[DIV_SYSTEM_NAMCO_15XX]=new DivSysDef(
|
||||||
|
"Namco 15XX WSG", NULL, 0xba, 0, 8, false, true, 0, false,
|
||||||
|
"successor of the original Namco WSG chip, used in later Namco arcade games.",
|
||||||
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
||||||
|
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
||||||
|
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
{DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO},
|
||||||
|
{},
|
||||||
|
waveOnlyEffectHandler
|
||||||
|
);
|
||||||
|
|
||||||
|
sysDefs[DIV_SYSTEM_NAMCO_CUS30]=new DivSysDef(
|
||||||
|
"Namco CUS30 WSG", NULL, 0xbb, 0, 8, false, true, 0, false,
|
||||||
|
"like Namco 15XX but with stereo sound.",
|
||||||
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
||||||
|
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
||||||
|
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
|
{DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO, DIV_INS_NAMCO},
|
||||||
|
{},
|
||||||
|
waveOnlyEffectHandler
|
||||||
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_DUMMY]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_DUMMY]=new DivSysDef(
|
||||||
"Dummy System", NULL, 0xfd, 0, 8, false, true, 0, false,
|
"Dummy System", NULL, 0xfd, 0, 8, false, true, 0, false,
|
||||||
"this is a system designed for testing purposes..",
|
"this is a system designed for testing purposes.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"},
|
||||||
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"},
|
||||||
{DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
{DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
|
||||||
|
|
|
@ -228,6 +228,10 @@ void FurnaceGUI::drawInsList() {
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_SU]);
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_SU]);
|
||||||
name=fmt::sprintf(ICON_FA_MICROCHIP " %.2X: %s##_INS%d",i,ins->name,i);
|
name=fmt::sprintf(ICON_FA_MICROCHIP " %.2X: %s##_INS%d",i,ins->name,i);
|
||||||
break;
|
break;
|
||||||
|
case DIV_INS_NAMCO:
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_NAMCO]);
|
||||||
|
name=fmt::sprintf(ICON_FA_PIE_CHART " %.2X: %s##_INS%d",i,ins->name,i);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_UNKNOWN]);
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_UNKNOWN]);
|
||||||
name=fmt::sprintf(ICON_FA_QUESTION " %.2X: %s##_INS%d",i,ins->name,i);
|
name=fmt::sprintf(ICON_FA_QUESTION " %.2X: %s##_INS%d",i,ins->name,i);
|
||||||
|
|
|
@ -149,6 +149,7 @@ enum FurnaceGUIColors {
|
||||||
GUI_COLOR_INSTR_MULTIPCM,
|
GUI_COLOR_INSTR_MULTIPCM,
|
||||||
GUI_COLOR_INSTR_SNES,
|
GUI_COLOR_INSTR_SNES,
|
||||||
GUI_COLOR_INSTR_SU,
|
GUI_COLOR_INSTR_SU,
|
||||||
|
GUI_COLOR_INSTR_NAMCO,
|
||||||
GUI_COLOR_INSTR_UNKNOWN,
|
GUI_COLOR_INSTR_UNKNOWN,
|
||||||
|
|
||||||
GUI_COLOR_CHANNEL_FM,
|
GUI_COLOR_CHANNEL_FM,
|
||||||
|
@ -937,6 +938,7 @@ class FurnaceGUI {
|
||||||
int horizontalDataView;
|
int horizontalDataView;
|
||||||
int noMultiSystem;
|
int noMultiSystem;
|
||||||
int oldMacroVSlider;
|
int oldMacroVSlider;
|
||||||
|
int displayAllInsTypes;
|
||||||
unsigned int maxUndoSteps;
|
unsigned int maxUndoSteps;
|
||||||
String mainFontPath;
|
String mainFontPath;
|
||||||
String patFontPath;
|
String patFontPath;
|
||||||
|
@ -1026,6 +1028,7 @@ class FurnaceGUI {
|
||||||
horizontalDataView(0),
|
horizontalDataView(0),
|
||||||
noMultiSystem(0),
|
noMultiSystem(0),
|
||||||
oldMacroVSlider(0),
|
oldMacroVSlider(0),
|
||||||
|
displayAllInsTypes(0),
|
||||||
maxUndoSteps(100),
|
maxUndoSteps(100),
|
||||||
mainFontPath(""),
|
mainFontPath(""),
|
||||||
patFontPath(""),
|
patFontPath(""),
|
||||||
|
|
|
@ -79,7 +79,7 @@ const int vgmVersions[6]={
|
||||||
0x171
|
0x171
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* insTypes[DIV_INS_MAX]={
|
const char* insTypes[DIV_INS_MAX+1]={
|
||||||
"Standard (SMS/NES)",
|
"Standard (SMS/NES)",
|
||||||
"FM (4-operator)",
|
"FM (4-operator)",
|
||||||
"Game Boy",
|
"Game Boy",
|
||||||
|
@ -111,6 +111,8 @@ const char* insTypes[DIV_INS_MAX]={
|
||||||
"MultiPCM",
|
"MultiPCM",
|
||||||
"SNES",
|
"SNES",
|
||||||
"Sound Unit",
|
"Sound Unit",
|
||||||
|
"Namco WSG",
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* sampleDepths[17]={
|
const char* sampleDepths[17]={
|
||||||
|
@ -754,6 +756,7 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={
|
||||||
D(GUI_COLOR_INSTR_MULTIPCM,"",ImVec4(1.0f,0.8f,0.1f,1.0f)),
|
D(GUI_COLOR_INSTR_MULTIPCM,"",ImVec4(1.0f,0.8f,0.1f,1.0f)),
|
||||||
D(GUI_COLOR_INSTR_SNES,"",ImVec4(0.8f,0.7f,1.0f,1.0f)),
|
D(GUI_COLOR_INSTR_SNES,"",ImVec4(0.8f,0.7f,1.0f,1.0f)),
|
||||||
D(GUI_COLOR_INSTR_SU,"",ImVec4(0.95f,0.98f,1.0f,1.0f)),
|
D(GUI_COLOR_INSTR_SU,"",ImVec4(0.95f,0.98f,1.0f,1.0f)),
|
||||||
|
D(GUI_COLOR_INSTR_NAMCO,"",ImVec4(1.0f,1.0f,0.0f,1.0f)),
|
||||||
D(GUI_COLOR_INSTR_UNKNOWN,"",ImVec4(0.3f,0.3f,0.3f,1.0f)),
|
D(GUI_COLOR_INSTR_UNKNOWN,"",ImVec4(0.3f,0.3f,0.3f,1.0f)),
|
||||||
|
|
||||||
D(GUI_COLOR_CHANNEL_FM,"",ImVec4(0.2f,0.8f,1.0f,1.0f)),
|
D(GUI_COLOR_CHANNEL_FM,"",ImVec4(0.2f,0.8f,1.0f,1.0f)),
|
||||||
|
@ -877,6 +880,11 @@ const int availableSystems[]={
|
||||||
DIV_SYSTEM_MMC5,
|
DIV_SYSTEM_MMC5,
|
||||||
DIV_SYSTEM_SCC,
|
DIV_SYSTEM_SCC,
|
||||||
DIV_SYSTEM_SCC_PLUS,
|
DIV_SYSTEM_SCC_PLUS,
|
||||||
|
DIV_SYSTEM_MSM6258,
|
||||||
|
DIV_SYSTEM_MSM6295,
|
||||||
|
DIV_SYSTEM_NAMCO,
|
||||||
|
DIV_SYSTEM_NAMCO_15XX,
|
||||||
|
DIV_SYSTEM_NAMCO_CUS30,
|
||||||
0 // don't remove this last one!
|
0 // don't remove this last one!
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1404,7 +1404,15 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if (ImGui::BeginCombo("##Type",insTypes[insType])) {
|
if (ImGui::BeginCombo("##Type",insTypes[insType])) {
|
||||||
for (DivInstrumentType i: e->getPossibleInsTypes()) {
|
std::vector<DivInstrumentType> insTypeList;
|
||||||
|
if (settings.displayAllInsTypes) {
|
||||||
|
for (int i=0; insTypes[i]; i++) {
|
||||||
|
insTypeList.push_back((DivInstrumentType)i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
insTypeList=e->getPossibleInsTypes();
|
||||||
|
}
|
||||||
|
for (DivInstrumentType i: insTypeList) {
|
||||||
if (ImGui::Selectable(insTypes[i],insType==i)) {
|
if (ImGui::Selectable(insTypes[i],insType==i)) {
|
||||||
ins->type=i;
|
ins->type=i;
|
||||||
|
|
||||||
|
|
|
@ -1368,6 +1368,7 @@ void FurnaceGUI::drawSettings() {
|
||||||
UI_COLOR_CONFIG(GUI_COLOR_INSTR_MULTIPCM,"MultiPCM");
|
UI_COLOR_CONFIG(GUI_COLOR_INSTR_MULTIPCM,"MultiPCM");
|
||||||
UI_COLOR_CONFIG(GUI_COLOR_INSTR_SNES,"SNES");
|
UI_COLOR_CONFIG(GUI_COLOR_INSTR_SNES,"SNES");
|
||||||
UI_COLOR_CONFIG(GUI_COLOR_INSTR_SU,"Sound Unit");
|
UI_COLOR_CONFIG(GUI_COLOR_INSTR_SU,"Sound Unit");
|
||||||
|
UI_COLOR_CONFIG(GUI_COLOR_INSTR_NAMCO,"Namco WSG");
|
||||||
UI_COLOR_CONFIG(GUI_COLOR_INSTR_UNKNOWN,"Other/Unknown");
|
UI_COLOR_CONFIG(GUI_COLOR_INSTR_UNKNOWN,"Other/Unknown");
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
@ -1797,6 +1798,7 @@ void FurnaceGUI::drawSettings() {
|
||||||
// these are the cheat codes:
|
// these are the cheat codes:
|
||||||
// "Debug" - toggles mobile UI
|
// "Debug" - toggles mobile UI
|
||||||
// "Nice Amiga cover of the song!" - enables hidden systems (YMU759/SoundUnit/Dummy)
|
// "Nice Amiga cover of the song!" - enables hidden systems (YMU759/SoundUnit/Dummy)
|
||||||
|
// "42 63" - enables all instrument types
|
||||||
if (ImGui::BeginTabItem("Cheat Codes")) {
|
if (ImGui::BeginTabItem("Cheat Codes")) {
|
||||||
ImVec2 settingsViewSize=ImGui::GetContentRegionAvail();
|
ImVec2 settingsViewSize=ImGui::GetContentRegionAvail();
|
||||||
settingsViewSize.y-=ImGui::GetFrameHeight()+ImGui::GetStyle().WindowPadding.y;
|
settingsViewSize.y-=ImGui::GetFrameHeight()+ImGui::GetStyle().WindowPadding.y;
|
||||||
|
@ -1824,6 +1826,10 @@ void FurnaceGUI::drawSettings() {
|
||||||
mmlString[30]=":smile: :star_struck: :sunglasses: :ok_hand:";
|
mmlString[30]=":smile: :star_struck: :sunglasses: :ok_hand:";
|
||||||
settings.hiddenSystems=!settings.hiddenSystems;
|
settings.hiddenSystems=!settings.hiddenSystems;
|
||||||
}
|
}
|
||||||
|
if (checker==0xe888896b && checker1==0xbde) {
|
||||||
|
mmlString[30]="enabled all instrument types";
|
||||||
|
settings.displayAllInsTypes=!settings.displayAllInsTypes;
|
||||||
|
}
|
||||||
|
|
||||||
mmlString[31]="";
|
mmlString[31]="";
|
||||||
}
|
}
|
||||||
|
@ -1944,6 +1950,7 @@ void FurnaceGUI::syncSettings() {
|
||||||
settings.horizontalDataView=e->getConfInt("horizontalDataView",0);
|
settings.horizontalDataView=e->getConfInt("horizontalDataView",0);
|
||||||
settings.noMultiSystem=e->getConfInt("noMultiSystem",0);
|
settings.noMultiSystem=e->getConfInt("noMultiSystem",0);
|
||||||
settings.oldMacroVSlider=e->getConfInt("oldMacroVSlider",0);
|
settings.oldMacroVSlider=e->getConfInt("oldMacroVSlider",0);
|
||||||
|
settings.displayAllInsTypes=e->getConfInt("displayAllInsTypes",0);
|
||||||
|
|
||||||
clampSetting(settings.mainFontSize,2,96);
|
clampSetting(settings.mainFontSize,2,96);
|
||||||
clampSetting(settings.patFontSize,2,96);
|
clampSetting(settings.patFontSize,2,96);
|
||||||
|
@ -2018,6 +2025,7 @@ void FurnaceGUI::syncSettings() {
|
||||||
clampSetting(settings.horizontalDataView,0,1);
|
clampSetting(settings.horizontalDataView,0,1);
|
||||||
clampSetting(settings.noMultiSystem,0,1);
|
clampSetting(settings.noMultiSystem,0,1);
|
||||||
clampSetting(settings.oldMacroVSlider,0,1);
|
clampSetting(settings.oldMacroVSlider,0,1);
|
||||||
|
clampSetting(settings.displayAllInsTypes,0,1);
|
||||||
|
|
||||||
settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys",""));
|
settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys",""));
|
||||||
if (settings.initialSys.size()<4) {
|
if (settings.initialSys.size()<4) {
|
||||||
|
@ -2140,6 +2148,7 @@ void FurnaceGUI::commitSettings() {
|
||||||
e->setConf("horizontalDataView",settings.horizontalDataView);
|
e->setConf("horizontalDataView",settings.horizontalDataView);
|
||||||
e->setConf("noMultiSystem",settings.noMultiSystem);
|
e->setConf("noMultiSystem",settings.noMultiSystem);
|
||||||
e->setConf("oldMacroVSlider",settings.oldMacroVSlider);
|
e->setConf("oldMacroVSlider",settings.oldMacroVSlider);
|
||||||
|
e->setConf("displayAllInsTypes",settings.displayAllInsTypes);
|
||||||
|
|
||||||
// colors
|
// colors
|
||||||
for (int i=0; i<GUI_COLOR_MAX; i++) {
|
for (int i=0; i<GUI_COLOR_MAX; i++) {
|
||||||
|
|
Loading…
Reference in a new issue