Merge branch 'master' into ay_divider
This commit is contained in:
commit
76997fd5ba
16 changed files with 577 additions and 27 deletions
|
|
@ -480,7 +480,7 @@ if (m_choffs == 0)
|
|||
#endif
|
||||
|
||||
// early out if the envelope is effectively off
|
||||
if (m_env_attenuation > EG_QUIET)
|
||||
if (m_env_attenuation > EG_QUIET && m_cache.eg_shift == 0)
|
||||
return 0;
|
||||
|
||||
// get the absolute value of the sin, as attenuation, as a 4.8 fixed point value
|
||||
|
|
|
|||
|
|
@ -70,16 +70,24 @@
|
|||
// OPZ supports a "fixed frequency" mode for each operator, with a 3-bit
|
||||
// range and 4-bit frequency value, plus a 1-bit enable. Not sure how that
|
||||
// works at all, so it's not implemented.
|
||||
// note by tildearrow:
|
||||
// - I have verified behavior of this mode against real hardware.
|
||||
// after applying a small fix on the existing early implementation, it matches hardware.
|
||||
// this means fixed frequency is fully implemented and working.
|
||||
//
|
||||
// There are also several mystery fields in the operators which I have no
|
||||
// clue about: "fine" (4 bits), "eg_shift" (2 bits), and "rev" (3 bits).
|
||||
// eg_shift is some kind of envelope generator effect, but how it works is
|
||||
// unknown.
|
||||
// note by tildearrow:
|
||||
// - behavior of "fine" is now confirmed and matches hardware.
|
||||
//
|
||||
// Also, according to the site above, the panning controls are changed from
|
||||
// OPM, with a "mono" bit and only one control bit for the right channel.
|
||||
// Current implementation is just a guess.
|
||||
//
|
||||
// additional modifications by tildearrow for Furnace
|
||||
//
|
||||
|
||||
namespace ymfm
|
||||
{
|
||||
|
|
@ -409,9 +417,6 @@ uint32_t opz_registers::lfo_am_offset(uint32_t choffs) const
|
|||
|
||||
void opz_registers::cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache)
|
||||
{
|
||||
// TODO: how does fixed frequency mode work? appears to be enabled by
|
||||
// op_fix_mode(), and controlled by op_fix_range(), op_fix_frequency()
|
||||
|
||||
// TODO: what is op_rev()?
|
||||
|
||||
// set up the easy stuff
|
||||
|
|
@ -467,8 +472,8 @@ void opz_registers::cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata
|
|||
if (reverb != 0)
|
||||
cache.eg_rate[EG_REVERB] = std::min<uint32_t>(effective_rate(reverb * 4 + 2, ksrval), cache.eg_rate[EG_REVERB]);
|
||||
|
||||
// set the envelope shift; TX81Z manual says operator 1 shift is fixed at "off"
|
||||
cache.eg_shift = ((opoffs & 0x18) == 0) ? 0 : op_eg_shift(opoffs);
|
||||
// set the envelope shift; TX81Z manual says operator 1 (actually operator 4) shift is fixed at "off"
|
||||
cache.eg_shift = ((opoffs & 0x18) == 0x18) ? 0 : op_eg_shift(opoffs);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -919,12 +919,13 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
|
|||
}
|
||||
case DIV_CMD_FM_FIXFREQ: {
|
||||
if (c.value<0 || c.value>3) break;
|
||||
printf("fixfreq %x\n",c.value2);
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.egt=(c.value2>0);
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.egt<<5)|(op.rs<<6));
|
||||
if (op.egt) {
|
||||
rWrite(baseAddr+ADDR_MULT_DT,((c.value2>>4)&15)|((c.value2>>8)&7));
|
||||
rWrite(baseAddr+ADDR_MULT_DT,((c.value2>>4)&15)|(((c.value2>>8)&7)<<4));
|
||||
rWrite(baseAddr+ADDR_WS_FINE,(c.value2&15)|(op.ws<<4));
|
||||
} else {
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|((op.egt?(op.dt&7):dtTable[op.dt&7])<<4));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue