mirror of
https://github.com/holub/mame
synced 2025-05-08 23:31:54 +03:00
bus/nes/konami.cpp : Fix sound clock, volume for VRC7
ym2413.cpp : Implement instrument table for VRC7, Add notes
This commit is contained in:
parent
2b30eeae8e
commit
c6d0ce68a7
@ -81,7 +81,7 @@ nes_konami_vrc6_device::nes_konami_vrc6_device(const machine_config &mconfig, co
|
||||
}
|
||||
|
||||
nes_konami_vrc7_device::nes_konami_vrc7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: nes_konami_vrc4_device(mconfig, NES_VRC7, tag, owner, clock), m_ym2413(*this, "ym")
|
||||
: nes_konami_vrc4_device(mconfig, NES_VRC7, tag, owner, clock), m_vrc7snd(*this, "vrc7snd")
|
||||
{
|
||||
}
|
||||
|
||||
@ -681,11 +681,11 @@ void nes_konami_vrc7_device::write_h(offs_t offset, uint8_t data)
|
||||
|
||||
case 0x1010:
|
||||
case 0x1018:
|
||||
m_ym2413->register_port_w(data);
|
||||
m_vrc7snd->register_port_w(data);
|
||||
break;
|
||||
case 0x1030:
|
||||
case 0x1038:
|
||||
m_ym2413->data_port_w(data);
|
||||
m_vrc7snd->data_port_w(data);
|
||||
break;
|
||||
|
||||
case 0x2000:
|
||||
@ -758,8 +758,6 @@ void nes_konami_vrc7_device::write_h(offs_t offset, uint8_t data)
|
||||
// and has one output pin for audio, multiplexed for all 6 channels; OPLL has two output pins, one for
|
||||
// FM and one for Rhythm, and has no special status pin.
|
||||
|
||||
// FIXME: we currently emulate this as a base YM2413!
|
||||
|
||||
void nes_konami_vrc7_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
// additional sound hardware
|
||||
@ -767,5 +765,5 @@ void nes_konami_vrc7_device::device_add_mconfig(machine_config &config)
|
||||
|
||||
// TODO: this is not how VRC7 clock signaling works!
|
||||
// The board uses the CLK pin in reality, not hardcoded NTSC values!
|
||||
YM2413(config, m_ym2413, XTAL(21'477'272)/12).add_route(ALL_OUTPUTS, "addon", 0.5);
|
||||
VRC7(config, m_vrc7snd, XTAL(21'477'272)/6).add_route(0, "addon", 1.0).add_route(1, "addon", 0.0);
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ protected:
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
private:
|
||||
required_device<ym2413_device> m_ym2413;
|
||||
required_device<vrc7snd_device> m_vrc7snd;
|
||||
};
|
||||
|
||||
|
||||
|
@ -42,6 +42,8 @@ to do:
|
||||
#include "emu.h"
|
||||
#include "ym2413.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
|
||||
#define EG_SH 16 /* 16.16 fixed point (EG timing) */
|
||||
#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */
|
||||
@ -131,7 +133,7 @@ const uint32_t ym2413_device::sl_tab[16] = {
|
||||
};
|
||||
#undef SC
|
||||
|
||||
const unsigned char ym2413_device::eg_inc[15*RATE_STEPS] = {
|
||||
const uint8_t ym2413_device::eg_inc[15*RATE_STEPS] = {
|
||||
/*cycle:0 1 2 3 4 5 6 7*/
|
||||
|
||||
/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */
|
||||
@ -158,7 +160,7 @@ const unsigned char ym2413_device::eg_inc[15*RATE_STEPS] = {
|
||||
#define O(a) (a*RATE_STEPS)
|
||||
|
||||
/*note that there is no O(13) in this table - it's directly in the code */
|
||||
const unsigned char ym2413_device::eg_rate_select[16+64+16] = { /* Envelope Generator rates (16 + 64 rates + 16 RKS) */
|
||||
const uint8_t ym2413_device::eg_rate_select[16+64+16] = { /* Envelope Generator rates (16 + 64 rates + 16 RKS) */
|
||||
/* 16 infinite time rates */
|
||||
O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
|
||||
O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
|
||||
@ -199,7 +201,7 @@ const unsigned char ym2413_device::eg_rate_select[16+64+16] = { /* Envelope Ge
|
||||
/*mask 8191, 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0 */
|
||||
|
||||
#define O(a) (a*1)
|
||||
const unsigned char ym2413_device::eg_rate_shift[16+64+16] = { /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */
|
||||
const uint8_t ym2413_device::eg_rate_shift[16+64+16] = { /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */
|
||||
/* 16 infinite time rates */
|
||||
O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
|
||||
O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
|
||||
@ -350,7 +352,7 @@ const int8_t ym2413_device::lfo_pm_table[8*8] = {
|
||||
- waveform DC and DM select are 100% correct
|
||||
*/
|
||||
|
||||
const unsigned char ym2413_device::table[19][8] = {
|
||||
const uint8_t ym2413_device::table[19][8] = {
|
||||
/* MULT MULT modTL DcDmFb AR/DR AR/DR SL/RR SL/RR */
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
{0x49, 0x4c, 0x4c, 0x12, 0x00, 0x00, 0x00, 0x00 }, //0
|
||||
@ -390,6 +392,44 @@ const unsigned char ym2413_device::table[19][8] = {
|
||||
{0x05, 0x01, 0x00, 0x00, 0xf8, 0xba, 0x49, 0x55 },/* TOM(multi,env verified), TOP CYM(multi verified, env verified) */
|
||||
};
|
||||
|
||||
// VRC7 Instruments : Dumped from internal ROM (melodic only)
|
||||
// reference : https://siliconpr0n.org/archive/doku.php?id=vendor:yamaha:opl2
|
||||
const uint8_t vrc7snd_device::vrc7_table[19][8] = {
|
||||
/* MULT MULT modTL DcDmFb AR/DR AR/DR SL/RR SL/RR */
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //0 (Correct?)
|
||||
|
||||
{0x03, 0x21, 0x05, 0x06, 0xe8, 0x81, 0x42, 0x27 }, //1
|
||||
{0x13, 0x41, 0x14, 0x0d, 0xd8, 0xf6, 0x23, 0x12 }, //2
|
||||
{0x11, 0x11, 0x08, 0x08, 0xfa, 0xb2, 0x20, 0x12 }, //3
|
||||
{0x31, 0x61, 0x0c, 0x07, 0xa8, 0x64, 0x61, 0x27 }, //4
|
||||
|
||||
{0x32, 0x21, 0x1e, 0x06, 0xe1, 0x76, 0x01, 0x28 }, //5
|
||||
|
||||
{0x02, 0x01, 0x06, 0x00, 0xa3, 0xe2, 0xf4, 0xf4 }, //6
|
||||
|
||||
{0x21, 0x61, 0x1d, 0x07, 0x82, 0x81, 0x11, 0x07 }, //7
|
||||
{0x23, 0x21, 0x22, 0x17, 0xa2, 0x72, 0x01, 0x17 }, //8
|
||||
{0x35, 0x11, 0x25, 0x00, 0x40, 0x73, 0x72, 0x01 }, //9
|
||||
|
||||
{0xb5, 0x01, 0x0f, 0x0f, 0xa8, 0xa5, 0x51, 0x02 }, //A
|
||||
|
||||
{0x17, 0xc1, 0x24, 0x07, 0xf8, 0xf8, 0x22, 0x12 }, //B
|
||||
{0x71, 0x23, 0x11, 0x06, 0x65, 0x74, 0x18, 0x16 }, //C
|
||||
|
||||
{0x01, 0x02, 0xd3, 0x05, 0xc9, 0x95, 0x03, 0x02 }, //D
|
||||
|
||||
{0x61, 0x63, 0x0c, 0x00, 0x94, 0xc0, 0x33, 0xf6 }, //E
|
||||
{0x21, 0x72, 0x0d, 0x00, 0xc1, 0xd5, 0x56, 0x06 }, //F
|
||||
|
||||
/* Not dumped drum instruments yet, and disconnected */
|
||||
/* MULTI MULTI modTL xxx AR/DR AR/DR SL/RR SL/RR */
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
{0x01, 0x01, 0x18, 0x0f, 0xdf, 0xf8, 0x6a, 0x6d },/* BD(multi verified, modTL verified, mod env - verified(close), carr. env verifed) */
|
||||
{0x01, 0x01, 0x00, 0x00, 0xc8, 0xd8, 0xa7, 0x68 },/* HH(multi verified), SD(multi not used) */
|
||||
{0x05, 0x01, 0x00, 0x00, 0xf8, 0xaa, 0x59, 0x55 },/* TOM(multi,env verified), TOP CYM(multi verified, env verified) */
|
||||
};
|
||||
|
||||
/* work table */
|
||||
#define SLOT7_1 (&P_CH[7].SLOT[SLOT1])
|
||||
#define SLOT7_2 (&P_CH[7].SLOT[SLOT2])
|
||||
@ -823,21 +863,21 @@ void ym2413_device::rhythm_calc( OPLL_CH *CH, unsigned int noise )
|
||||
*/
|
||||
|
||||
/* base frequency derived from operator 1 in channel 7 */
|
||||
unsigned char bit7 = ((SLOT7_1->phase>>FREQ_SH)>>7)&1;
|
||||
unsigned char bit3 = ((SLOT7_1->phase>>FREQ_SH)>>3)&1;
|
||||
unsigned char bit2 = ((SLOT7_1->phase>>FREQ_SH)>>2)&1;
|
||||
uint8_t bit7 = ((SLOT7_1->phase>>FREQ_SH)>>7)&1;
|
||||
uint8_t bit3 = ((SLOT7_1->phase>>FREQ_SH)>>3)&1;
|
||||
uint8_t bit2 = ((SLOT7_1->phase>>FREQ_SH)>>2)&1;
|
||||
|
||||
unsigned char res1 = (bit2 ^ bit7) | bit3;
|
||||
uint8_t res1 = (bit2 ^ bit7) | bit3;
|
||||
|
||||
/* when res1 = 0 phase = 0x000 | 0xd0; */
|
||||
/* when res1 = 1 phase = 0x200 | (0xd0>>2); */
|
||||
uint32_t phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;
|
||||
|
||||
/* enable gate based on frequency of operator 2 in channel 8 */
|
||||
unsigned char bit5e= ((SLOT8_2->phase>>FREQ_SH)>>5)&1;
|
||||
unsigned char bit3e= ((SLOT8_2->phase>>FREQ_SH)>>3)&1;
|
||||
uint8_t bit5e= ((SLOT8_2->phase>>FREQ_SH)>>5)&1;
|
||||
uint8_t bit3e= ((SLOT8_2->phase>>FREQ_SH)>>3)&1;
|
||||
|
||||
unsigned char res2 = (bit3e | bit5e);
|
||||
uint8_t res2 = (bit3e | bit5e);
|
||||
|
||||
/* when res2 = 0 pass the phase from calculation above (res1); */
|
||||
/* when res2 = 1 phase = 0x200 | (0xd0>>2); */
|
||||
@ -868,7 +908,7 @@ void ym2413_device::rhythm_calc( OPLL_CH *CH, unsigned int noise )
|
||||
if( env < ENV_QUIET )
|
||||
{
|
||||
/* base frequency derived from operator 1 in channel 7 */
|
||||
unsigned char bit8 = ((SLOT7_1->phase>>FREQ_SH)>>8)&1;
|
||||
uint8_t bit8 = ((SLOT7_1->phase>>FREQ_SH)>>8)&1;
|
||||
|
||||
/* when bit8 = 0 phase = 0x100; */
|
||||
/* when bit8 = 1 phase = 0x200; */
|
||||
@ -894,21 +934,21 @@ void ym2413_device::rhythm_calc( OPLL_CH *CH, unsigned int noise )
|
||||
if( env < ENV_QUIET )
|
||||
{
|
||||
/* base frequency derived from operator 1 in channel 7 */
|
||||
unsigned char bit7 = ((SLOT7_1->phase>>FREQ_SH)>>7)&1;
|
||||
unsigned char bit3 = ((SLOT7_1->phase>>FREQ_SH)>>3)&1;
|
||||
unsigned char bit2 = ((SLOT7_1->phase>>FREQ_SH)>>2)&1;
|
||||
uint8_t bit7 = ((SLOT7_1->phase>>FREQ_SH)>>7)&1;
|
||||
uint8_t bit3 = ((SLOT7_1->phase>>FREQ_SH)>>3)&1;
|
||||
uint8_t bit2 = ((SLOT7_1->phase>>FREQ_SH)>>2)&1;
|
||||
|
||||
unsigned char res1 = (bit2 ^ bit7) | bit3;
|
||||
uint8_t res1 = (bit2 ^ bit7) | bit3;
|
||||
|
||||
/* when res1 = 0 phase = 0x000 | 0x100; */
|
||||
/* when res1 = 1 phase = 0x200 | 0x100; */
|
||||
uint32_t phase = res1 ? 0x300 : 0x100;
|
||||
|
||||
/* enable gate based on frequency of operator 2 in channel 8 */
|
||||
unsigned char bit5e= ((SLOT8_2->phase>>FREQ_SH)>>5)&1;
|
||||
unsigned char bit3e= ((SLOT8_2->phase>>FREQ_SH)>>3)&1;
|
||||
uint8_t bit5e= ((SLOT8_2->phase>>FREQ_SH)>>5)&1;
|
||||
uint8_t bit3e= ((SLOT8_2->phase>>FREQ_SH)>>3)&1;
|
||||
|
||||
unsigned char res2 = (bit3e | bit5e);
|
||||
uint8_t res2 = (bit3e | bit5e);
|
||||
/* when res2 = 0 pass the phase from calculation above (res1); */
|
||||
/* when res2 = 1 phase = 0x200 | 0x100; */
|
||||
if (res2)
|
||||
@ -1635,11 +1675,14 @@ void ym2413_device::device_reset()
|
||||
noise_rng = 1; /* noise shift register */
|
||||
|
||||
/* setup instruments table */
|
||||
for (int i=0; i<19; i++)
|
||||
if (m_inst_table != nullptr)
|
||||
{
|
||||
for (int c=0; c<8; c++)
|
||||
for (int i=0; i<19; i++)
|
||||
{
|
||||
inst_tab[i][c] = table[i][c];
|
||||
for (int c=0; c<8; c++)
|
||||
{
|
||||
inst_tab[i][c] = m_inst_table[i][c];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1686,7 +1729,37 @@ void ym2413_device::data_port_w(u8 data)
|
||||
DEFINE_DEVICE_TYPE(YM2413, ym2413_device, "ym2413", "Yamaha YM2413 OPLL")
|
||||
|
||||
ym2413_device::ym2413_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, YM2413, tag, owner, clock)
|
||||
: ym2413_device(mconfig, YM2413, tag, owner, clock)
|
||||
{
|
||||
for (int i = 0; i < 19; i++)
|
||||
{
|
||||
for (int c = 0; c < 8; c++)
|
||||
{
|
||||
m_inst_table[i][c] = table[i][c];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ym2413_device::ym2413_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, device_sound_interface(mconfig, *this)
|
||||
{
|
||||
for (int i = 0; i < 19; i++)
|
||||
{
|
||||
std::fill_n(&m_inst_table[i][0], 8, 0);
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_DEVICE_TYPE(VRC7, vrc7snd_device, "vrc7snd", "Konami VRC7 (Sound)")
|
||||
|
||||
vrc7snd_device::vrc7snd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: ym2413_device(mconfig, VRC7, tag, owner, clock)
|
||||
{
|
||||
for (int i = 0; i < 19; i++)
|
||||
{
|
||||
for (int c = 0; c < 8; c++)
|
||||
{
|
||||
m_inst_table[i][c] = vrc7_table[i][c];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ public:
|
||||
void data_port_w(u8 data);
|
||||
|
||||
protected:
|
||||
ym2413_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_clock_changed() override;
|
||||
@ -25,6 +27,8 @@ protected:
|
||||
// sound stream update overrides
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
|
||||
|
||||
uint8_t m_inst_table[19][8];
|
||||
|
||||
private:
|
||||
struct OPLL_SLOT
|
||||
{
|
||||
@ -106,13 +110,13 @@ private:
|
||||
static const double ksl_tab[8*16];
|
||||
static const uint32_t ksl_shift[4];
|
||||
static const uint32_t sl_tab[16];
|
||||
static const unsigned char eg_inc[15*RATE_STEPS];
|
||||
static const unsigned char eg_rate_select[16+64+16];
|
||||
static const unsigned char eg_rate_shift[16+64+16];
|
||||
static const uint8_t eg_inc[15*RATE_STEPS];
|
||||
static const uint8_t eg_rate_select[16+64+16];
|
||||
static const uint8_t eg_rate_shift[16+64+16];
|
||||
static const uint8_t mul_tab[16];
|
||||
static const uint8_t lfo_am_table[LFO_AM_TAB_ELEMENTS];
|
||||
static const int8_t lfo_pm_table[8*8];
|
||||
static const unsigned char table[19][8];
|
||||
static const uint8_t table[19][8];
|
||||
|
||||
int tl_tab[TL_TAB_LEN];
|
||||
|
||||
@ -185,4 +189,15 @@ private:
|
||||
|
||||
DECLARE_DEVICE_TYPE(YM2413, ym2413_device)
|
||||
|
||||
class vrc7snd_device : public ym2413_device
|
||||
{
|
||||
public:
|
||||
vrc7snd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
private:
|
||||
static const uint8_t vrc7_table[19][8];
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(VRC7, vrc7snd_device)
|
||||
|
||||
#endif // MAME_SOUND_YM2413_H
|
||||
|
Loading…
Reference in New Issue
Block a user