private void init_sample(_MultiPCM ptChip, _Sample sample, UInt16 index) { UInt32 address = (UInt32)((index * 12) & ptChip.ROMMask); sample.start = (uint)((ptChip.ROM[address + 0] << 16) | (ptChip.ROM[address + 1] << 8) | ptChip.ROM[address + 2]); sample.format = (byte)((sample.start >> 20) & 0xfe); sample.start &= 0x3fffff; sample.loop = (uint)((ptChip.ROM[address + 3] << 8) | ptChip.ROM[address + 4]); sample.end = (uint)(0xffff - ((ptChip.ROM[address + 5] << 8) | ptChip.ROM[address + 6])); sample.attack_reg = (byte)((ptChip.ROM[address + 8] >> 4) & 0xf); sample.decay1_reg = (byte)(ptChip.ROM[address + 8] & 0xf); sample.decay2_reg = (byte)(ptChip.ROM[address + 9] & 0xf); sample.decay_level = (byte)((ptChip.ROM[address + 9] >> 4) & 0xf); sample.release_reg = (byte)(ptChip.ROM[address + 10] & 0xf); sample.key_rate_scale = (byte)((ptChip.ROM[address + 10] >> 4) & 0xf); sample.lfo_vibrato_reg = ptChip.ROM[address + 7]; sample.lfo_amplitude_reg = (byte)(ptChip.ROM[address + 11] & 0xf); }
private void WriteSlot(_MultiPCM ptChip, _SLOT slot, Int32 reg, byte data) { slot.Regs[reg] = data; switch (reg) { case 0: //PANPOT slot.Pan = (UInt32)((data >> 4) & 0xf); break; case 1: //Sample //according to YMF278 sample write causes some base params written to the regs (envelope+lfos) //the game should never change the sample while playing. { _Sample Sample = ptChip.Samples[slot.Regs[1]]; WriteSlot(ptChip, slot, 6, Sample.LFOVIB); WriteSlot(ptChip, slot, 7, Sample.AM); } break; case 2: //Pitch case 3: { UInt32 oct = (UInt32)(((slot.Regs[3] >> 4) - 1) & 0xf); UInt32 pitch = (UInt32)(((slot.Regs[3] & 0xf) << 6) | (slot.Regs[2] >> 2)); pitch = ptChip.FNS_Table[pitch]; if ((oct & 0x8) != 0) { pitch >>= (Int32)(16 - oct); } else { pitch <<= (Int32)oct; } slot.step = (UInt32)(pitch / ptChip.Rate); } break; case 4: //KeyOn/Off (and more?) { if ((data & 0x80) != 0) //KeyOn { slot.Sample = ptChip.Samples[slot.Regs[1]]; slot.Playing = 1; slot.Base = slot.Sample.Start; slot.offset = 0; slot.Prev = 0; slot.TL = slot.DstTL << SHIFT; EG_Calc(ptChip, slot); slot.EG.state = _STATE.ATTACK; slot.EG.volume = 0; if (slot.Base >= 0x100000) { if ((slot.Pan & 8) != 0) { slot.Base = (slot.Base & 0xfffff) | (ptChip.BankL); } else { slot.Base = (slot.Base & 0xfffff) | (ptChip.BankR); } } } else { if (slot.Playing != 0) { if (slot.Sample.RR != 0xf) { slot.EG.state = _STATE.RELEASE; } else { slot.Playing = 0; } } } } break; case 5: //TL+Interpolation { slot.DstTL = (UInt32)((data >> 1) & 0x7f); if ((data & 1) == 0) //Interpolate TL { if ((slot.TL >> SHIFT) > slot.DstTL) { slot.TLStep = TLSteps[0]; //decrease } else { slot.TLStep = TLSteps[1]; //increase } } else { slot.TL = slot.DstTL << SHIFT; } } break; case 6: //LFO freq+PLFO { if (data != 0) { LFO_ComputeStep(ptChip, slot.PLFO, (UInt32)(slot.Regs[6] >> 3) & 7, (UInt32)(slot.Regs[6] & 7), 0); LFO_ComputeStep(ptChip, slot.ALFO, (UInt32)(slot.Regs[6] >> 3) & 7, (UInt32)(slot.Regs[7] & 7), 1); } } break; case 7: //ALFO { if (data != 0) { LFO_ComputeStep(ptChip, slot.PLFO, (UInt32)(slot.Regs[6] >> 3) & 7, (UInt32)(slot.Regs[6] & 7), 0); LFO_ComputeStep(ptChip, slot.ALFO, (UInt32)(slot.Regs[6] >> 3) & 7, (UInt32)(slot.Regs[7] & 7), 1); } } break; } }