mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-27 15:03:01 +00:00
Merge branch 'master' into sm8521
This commit is contained in:
commit
5b52d9111b
10 changed files with 53 additions and 299 deletions
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ writers:
|
|||
- DeMOSic
|
||||
- cam900
|
||||
- host12prog
|
||||
- WindowxDeveloper
|
||||
|
||||
other:
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -55,6 +55,8 @@ const char* aboutLine[]={
|
|||
"nicco1690",
|
||||
"DeMOSic",
|
||||
"cam900",
|
||||
"host12prog",
|
||||
"WindowxDeveloper",
|
||||
"",
|
||||
"-- demo songs --",
|
||||
"0x5066",
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue