Merge branch 'master' into sm8521

This commit is contained in:
tildearrow 2023-02-11 17:11:39 -05:00
commit 5b52d9111b
10 changed files with 53 additions and 299 deletions

View file

@ -13,180 +13,6 @@
// DO NOT USE THIS ONE!
void es5506_core::tick()
{
// CLKIN
if (m_clkin.tick())
{
// BCLK
if (m_clkin.edge().changed() && (!m_mode.bclk_en())) // BCLK is freely running clock
{
if (m_bclk.tick())
{
m_intf.bclk(m_bclk.current_edge());
// Serial output
if (!m_mode.lrclk_en())
{
if (m_bclk.falling_edge())
{
// LRCLK
if (m_lrclk.tick())
{
m_intf.lrclk(m_lrclk.current_edge());
if (m_lrclk.rising_edge())
{
m_w_st_curr = m_w_st;
m_w_end_curr = m_w_end;
}
if (m_lrclk.falling_edge())
{ // update width
m_lrclk.set_width_latch(m_lr_end);
}
}
}
}
// WCLK
if (!m_mode.wclk_en())
{
if (!m_mode.lrclk_en())
{
if (m_lrclk.edge().changed())
{
m_wclk = 0;
}
}
if (m_bclk.falling_edge())
{
if (m_wclk == m_w_st_curr)
{
m_intf.wclk(true);
if (m_lrclk.current_edge())
{
for (int i = 0; i < 6; i++)
{
// copy output
m_output[i].copy_output(m_output_temp[i]);
// clamp to 20 bit (upper 3 bits are
// overflow guard bits)
m_output_latch[i].clamp20(m_ch[i]);
m_output_temp[i].reset();
m_output_latch[i].clamp20();
// set signed
if (m_output_latch[i].left() < 0)
{
m_output_temp[i].set_left(-1);
}
if (m_output_latch[i].right() < 0)
{
m_output_temp[i].set_right(-1);
}
}
}
m_wclk_lr = m_lrclk.current_edge();
m_output_bit = 20;
}
if (m_wclk < m_w_end_curr)
{
s8 output_bit = --m_output_bit;
if (m_output_bit >= 0)
{
for (int i = 0; i < 6; i++)
{
if (m_wclk_lr)
{
// Right output
m_output_temp[i].serial_in(
m_wclk_lr,
bitfield(m_output_latch[i].right(), output_bit));
}
else
{
// Left output
m_output_temp[i].serial_in(
m_wclk_lr,
bitfield(m_output_latch[i].left(), output_bit));
}
}
}
}
if (m_wclk == m_w_end_curr)
{
m_intf.wclk(false);
}
m_wclk++;
}
}
}
}
// /CAS, E
if (m_clkin.falling_edge()) // falling edge triggers /CAS, E clock
{
// /CAS
if (m_cas.tick())
{
// single OTTO master mode, /CAS high, E low: get sample address
// single OTTO early mode, /CAS falling, E high: get sample
// address
if (m_cas.falling_edge())
{
if (!m_e.current_edge())
{
// single OTTO master mode, /CAS low, E low: fetch
// sample
if (m_mode.master())
{
m_voice[m_voice_cycle].fetch(m_voice_fetch);
}
}
else if (m_e.current_edge())
{
// dual OTTO slave mode, /CAS low, E high: fetch sample
if (m_mode.dual() && (!m_mode.master()))
{ // Dual OTTO, slave mode
m_voice[m_voice_cycle].fetch(m_voice_fetch);
}
}
}
}
// E
if (m_e.tick())
{
m_intf.e_pin(m_e.current_edge());
if (m_e.rising_edge())
{
m_host_intf.update_strobe();
}
else if (m_e.falling_edge())
{
m_host_intf.clear_host_access();
voice_tick();
}
if (m_e.current_edge()) // Host interface
{
if (m_host_intf.m_host_access)
{
if (m_host_intf.m_rw && (m_e.cycle() == 0)) // Read
{
m_hd = read(m_ha);
m_host_intf.clear_host_access();
}
else if ((!m_host_intf.m_rw) && (m_e.cycle() == 2))
{ // Write
write(m_ha, m_hd);
}
}
}
else if (!m_e.current_edge())
{
if (m_e.cycle() == 2)
{
// reset host access state
m_hd = 0;
m_host_intf.clear_strobe();
}
}
}
}
}
}
// less cycle accurate, but less CPU heavy routine
@ -195,7 +21,7 @@ void es5506_core::tick_perf()
// output
if (((!m_mode.lrclk_en()) && (!m_mode.bclk_en()) && (!m_mode.wclk_en())) && (m_w_st < m_w_end))
{
const int output_bits = (20 - (m_w_end - m_w_st)) * 2;
const int output_bits = (20 - (m_w_end - m_w_st));
if (output_bits < 20)
{
for (int c = 0; c < 6; c++)
@ -218,35 +44,21 @@ void es5506_core::tick_perf()
}
}
bool bounce=m_voice_end;
// update
if (bounce) {
// falling edge
m_e.edge().set(false);
m_intf.e_pin(false);
m_host_intf.clear_host_access();
m_host_intf.clear_strobe();
}
m_voice[m_voice_cycle].fetch(0);
voice_tick();
if (bounce) {
// rising edge
m_e.edge().set(true);
m_intf.e_pin(true);
m_host_intf.update_strobe();
}
}
void es5506_core::voice_tick()
{
// Voice updates every 2 E clock cycle (or 4 BCLK clock cycle)
// Update voice
m_voice[m_voice_cycle].tick(m_voice_cycle);
for (int i=0; i<VGS_CLAMP(m_active,4,31); i++) {
m_voice[i].tick(i);
}
// Refresh output
if ((++m_voice_cycle) > VGS_CLAMP(m_active, 4, 31)) // 5 ~ 32 voices
{
m_voice_end = true;
m_voice_cycle = 0;
for (int i=0; i<6; i++)
@ -264,11 +76,6 @@ void es5506_core::voice_tick()
m_voice[i].ch().reset();
}
}
else
{
m_voice_end = false;
}
}
void es5506_core::voice_t::fetch(u8 cycle)
{
@ -297,13 +104,14 @@ void es5506_core::voice_t::tick(u8 voice)
m_ch.reset();
// Filter execute
m_filter.tick(m_alu.interpolation());
if (m_alu.busy())
{
fetch(0);
m_filter.tick(m_alu.interpolation());
// Send to output
m_output[0] = m_mute ? 0 : volume_calc(m_lvol, sign_ext<s32>(m_filter.o4_1(), 16));
m_output[1] = m_mute ? 0 : volume_calc(m_rvol, sign_ext<s32>(m_filter.o4_1(), 16));
m_output[0] = m_mute ? 0 : volume_calc(m_lvol, (short)m_filter.o4_1());
m_output[1] = m_mute ? 0 : volume_calc(m_rvol, (short)m_filter.o4_1());
m_ch.set_left(m_output[0]);
m_ch.set_right(m_output[1]);
@ -313,6 +121,8 @@ void es5506_core::voice_t::tick(u8 voice)
{
m_alu.loop_exec();
}
} else {
m_filter.tick(m_alu.interpolation());
}
// Envelope
if (m_ecount != 0)
@ -346,7 +156,7 @@ void es5506_core::voice_t::tick(u8 voice)
m_filtcount = bitfield(m_filtcount + 1, 0, 3);
// Update IRQ
m_alu.irq_exec(m_host.m_intf, m_host.m_irqv, voice);
//m_alu.irq_exec(m_host.m_intf, m_host.m_irqv, voice);
}
// Compressed format
@ -363,9 +173,7 @@ s16 es5506_core::voice_t::decompress(u8 sample)
// volume calculation
s32 es5506_core::voice_t::volume_calc(u16 volume, s32 in)
{
u8 exponent = bitfield(volume, 12, 4);
u8 mantissa = bitfield(volume, 4, 8);
return (in * s32(0x100 | mantissa)) >> (20 - exponent);
return (in * s32(0x100 | ((volume>>4)&255))) >> (20 - ((volume>>12)&15));
}
void es5506_core::reset()
@ -425,38 +233,18 @@ void es5506_core::voice_t::reset()
// Accessors
u8 es5506_core::host_r(u8 address)
{
if (!m_host_intf.m_host_access)
{
m_ha = address;
if (m_e.rising_edge())
{ // update directly
m_hd = read(m_ha, true);
}
else
{
m_host_intf.set_strobe(true);
}
}
return m_hd;
}
void es5506_core::host_w(u8 address, u8 data)
{
if (!m_host_intf.m_host_access)
{
m_ha = address;
m_hd = data;
if (m_e.rising_edge())
{ // update directly
write(m_ha, m_hd);
}
else
{
m_host_intf.set_strobe(false);
}
}
}
u8 es5506_core::read(u8 address, bool cpu_access)
{

View file

@ -347,7 +347,7 @@ class es550x_shared_core : public vgsound_emu_core
inline u8 loop() { return (m_lpe << 0) | (m_ble << 1); }
private:
public:
u8 m_stop0 : 1; // Stop with ALU
u8 m_stop1 : 1; // Stop with processor
u8 m_lpe : 1; // Loop enable
@ -429,8 +429,8 @@ class es550x_shared_core : public vgsound_emu_core
inline s32 o4_1() { return m_o[4][0]; }
private:
void lp_exec(s32 coeff, s32 in, s32 out);
void hp_exec(s32 coeff, s32 in, s32 out);
void lp_exec(s32 coeff, const s32 in, const s32 out);
void hp_exec(s32 coeff, const s32 in, const s32 out);
// Registers
u8 m_lp = 0; // Filter mode

View file

@ -33,24 +33,19 @@ bool es550x_shared_core::es550x_voice_t::es550x_alu_t::tick()
}
m_accum &= m_accum_mask;
return ((!m_cr.lei()) &&
(((m_cr.dir()) && (m_accum < m_start)) || ((!m_cr.dir()) && (m_accum > m_end))))
return ((!m_cr.m_lei) &&
(((m_cr.m_dir) && (m_accum < m_start)) || ((!m_cr.m_dir) && (m_accum > m_end))))
? true
: false;
}
void es550x_shared_core::es550x_voice_t::es550x_alu_t::loop_exec()
{
if (m_cr.irqe())
{ // Set IRQ
m_cr.set_irq(true);
}
if (m_cr.dir()) // Reverse playback
if (m_cr.m_dir) // Reverse playback
{
if (m_cr.lpe()) // Loop enable
if (m_cr.m_lpe) // Loop enable
{
if (m_cr.ble()) // Bidirectional
if (m_cr.m_ble) // Bidirectional
{
m_cr.set_dir(false);
m_accum = m_start + (m_start - m_accum);
@ -60,7 +55,7 @@ void es550x_shared_core::es550x_voice_t::es550x_alu_t::loop_exec()
m_accum = m_end - (m_start - m_accum);
}
}
else if (m_cr.ble() && m_transwave) // m_transwave
else if (m_cr.m_ble && m_transwave) // m_transwave
{
m_cr.set_loop(0);
m_cr.set_lei(true); // Loop end ignore
@ -73,9 +68,9 @@ void es550x_shared_core::es550x_voice_t::es550x_alu_t::loop_exec()
}
else
{
if (m_cr.lpe()) // Loop enable
if (m_cr.m_lpe) // Loop enable
{
if (m_cr.ble()) // Bidirectional
if (m_cr.m_ble) // Bidirectional
{
m_cr.set_dir(true);
m_accum = m_end - (m_end - m_accum);
@ -85,7 +80,7 @@ void es550x_shared_core::es550x_voice_t::es550x_alu_t::loop_exec()
m_accum = (m_accum - m_end) + m_start;
}
}
else if (m_cr.ble() && m_transwave) // m_transwave
else if (m_cr.m_ble && m_transwave) // m_transwave
{
m_cr.set_loop(0);
m_cr.set_lei(true); // Loop end ignore

View file

@ -50,7 +50,7 @@ void es550x_shared_core::es550x_voice_t::es550x_filter_t::tick(s32 in)
}
}
void es550x_shared_core::es550x_voice_t::es550x_filter_t::lp_exec(s32 coeff, s32 in, s32 out)
void es550x_shared_core::es550x_voice_t::es550x_filter_t::lp_exec(s32 coeff, const s32 in, const s32 out)
{
// Store previous filter data
m_o[out][1] = m_o[out][0];
@ -59,7 +59,7 @@ void es550x_shared_core::es550x_voice_t::es550x_filter_t::lp_exec(s32 coeff, s32
m_o[out][0] = ((coeff * (m_o[in][0] - m_o[out][0])) / 4096) + m_o[out][0];
}
void es550x_shared_core::es550x_voice_t::es550x_filter_t::hp_exec(s32 coeff, s32 in, s32 out)
void es550x_shared_core::es550x_voice_t::es550x_filter_t::hp_exec(s32 coeff, const s32 in, const s32 out)
{
// Store previous filter data
m_o[out][1] = m_o[out][0];

View file

@ -1,6 +1,6 @@
# Yamaha YM2151
the sound chip powering several arcade boards and the Sharp X1/X68000. Eight 4-op FM channels, with overpowered LFO and almost unused noise generator.
the sound chip powering several arcade boards, the Sharp X1/X68000 and the Commander X16. Eight 4-op FM channels, with overpowered LFO and almost unused noise generator.
it also was present on several pinball machines and synthesizers of the era, and later surpassed by the YM2414 (OPZ) present in the world-famous TX81Z.

View file

@ -20,6 +20,7 @@ writers:
- DeMOSic
- cam900
- host12prog
- WindowxDeveloper
other:

View file

@ -113,24 +113,7 @@ const char** DivPlatformES5506::getRegisterSheet() {
}
void DivPlatformES5506::acquire(short** buf, size_t len) {
int coL[6], coR[6];
for (size_t h=0; h<len; h++) {
coL[0]=0;
coL[1]=0;
coL[2]=0;
coL[3]=0;
coL[4]=0;
coL[5]=0;
coR[0]=0;
coR[1]=0;
coR[2]=0;
coR[3]=0;
coR[4]=0;
coR[5]=0;
for (int i=31; i>(int)chanMax; i--) {
oscBuf[i]->data[oscBuf[i]->needle++]=0;
}
// convert 32 bit access to 8 bit host interface
while (!hostIntf32.empty()) {
QueuedHostIntf w=hostIntf32.front();
@ -147,35 +130,22 @@ void DivPlatformES5506::acquire(short** buf, size_t len) {
}
hostIntf32.pop();
}
for (int i=0; i<32; i++) {
prevChanCycle=es5506.voice_cycle();
es5506.tick_perf();
if (es5506.voice_end()) {
for (int j=chanMax; j>=0; j--) {
oscBuf[j]->data[oscBuf[j]->needle++]=(es5506.voice_lout(j)+es5506.voice_rout(j))>>5;
}
}
for (int o=0; o<6; o++) {
coL[o]+=es5506.lout(o);
coR[o]+=es5506.rout(o);
buf[(o<<1)|0][h]=es5506.lout(o);
buf[(o<<1)|1][h]=es5506.rout(o);
}
}
for (int o=0; o<6; o++) {
coL[o]>>=3;
coR[o]>>=3;
}
for (int o=0; o<6; o++) {
buf[(o<<1)|0][h]=coL[o];
buf[(o<<1)|1][h]=coR[o];
for (int i=chanMax; i>=0; i--) {
oscBuf[i]->data[oscBuf[i]->needle++]=(es5506.voice_lout(i)+es5506.voice_rout(i))>>5;
}
}
}
void DivPlatformES5506::e_pin(bool state) {
if (state) { // host interface
if (cycle) { // wait until delay
cycle--;
} else if (!hostIntf8.empty()) {
if (cycle>0) { // wait until delay
cycle-=2;
} else while (!hostIntf8.empty()) {
QueuedHostIntf w=hostIntf8.front();
unsigned char shift=24-(w.step<<3);
if (w.isRead) {
@ -200,6 +170,7 @@ void DivPlatformES5506::e_pin(bool state) {
maskedVal=((w.val>>shift)&mask)|(es5506.host_r((w.addr<<2)+w.step)&~mask);
isMasked=true;
}
if (cycle>0) break;
}
}
}
@ -1141,7 +1112,6 @@ void DivPlatformES5506::reset() {
irqv=0x80;
isMasked=false;
irqTrigger=false;
prevChanCycle=0;
chanMax=initChanMax;
pageWriteMask(0x00,0x60,0x0b,chanMax);

View file

@ -272,7 +272,6 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
bool isMasked, isReaded;
bool irqTrigger;
unsigned int curCR;
unsigned char prevChanCycle;
unsigned char initChanMax, chanMax;

View file

@ -55,6 +55,8 @@ const char* aboutLine[]={
"nicco1690",
"DeMOSic",
"cam900",
"host12prog",
"WindowxDeveloper",
"",
"-- demo songs --",
"0x5066",

View file

@ -500,7 +500,6 @@ void putDispatchChip(void* data, int type) {
ImGui::Text("- maskedVal: %.2x",ch->maskedVal);
ImGui::Text("- irqv: %.2x",ch->irqv);
ImGui::Text("- curCR: %.8x",ch->curCR);
ImGui::Text("- prevChanCycle: %d",ch->prevChanCycle);
ImGui::Text("- initChanMax: %d",ch->initChanMax);
ImGui::Text("- chanMax: %d",ch->chanMax);
COMMON_CHIP_DEBUG_BOOL;