Ejemplo n.º 1
0
        private void envelope_generator_calc(_MultiPCM ptChip, _slot_t slot)
        {
            Int32 octave = ((slot.regs[3] >> 4) - 1) & 0xf;
            Int32 rate;

            if ((octave & 8) != 0)
            {
                octave = octave - 16;
            }

            if (slot.sample.key_rate_scale != 0xf)
            {
                rate = (octave + slot.sample.key_rate_scale) * 2 + ((slot.regs[3] >> 3) & 1);
            }
            else
            {
                rate = 0;
            }

            slot.envelope_gen.attack_rate  = (Int32)get_rate(ptChip.attack_step, (UInt32)rate, slot.sample.attack_reg);
            slot.envelope_gen.decay1_rate  = (Int32)get_rate(ptChip.decay_release_step, (UInt32)rate, slot.sample.decay1_reg);
            slot.envelope_gen.decay2_rate  = (Int32)get_rate(ptChip.decay_release_step, (UInt32)rate, slot.sample.decay2_reg);
            slot.envelope_gen.release_rate = (Int32)get_rate(ptChip.decay_release_step, (UInt32)rate, slot.sample.release_reg);
            slot.envelope_gen.decay_level  = 0xf - slot.sample.decay_level;
        }
Ejemplo n.º 2
0
        //WRITE8_DEVICE_HANDLER( multipcm_w )
        private void multipcm_w(byte ChipID, Int32 offset, byte data)
        {
            //MultiPCM *ptChip = get_safe_token(device);
            _MultiPCM ptChip = MultiPCMData[ChipID];

            switch (offset)
            {
            case 0:         //Data write
                WriteSlot(ptChip, ptChip.Slots[ptChip.CurSlot], (Int32)ptChip.Address, data);
                break;

            case 1:
                ptChip.CurSlot = (UInt32)val2chan[data & 0x1f];
                //Console.WriteLine("CurSlot{0}", ptChip.CurSlot);
                break;

            case 2:
                ptChip.Address = (UInt32)((data > 7) ? 7 : data);
                break;
            }

            /*ptChip->CurSlot = val2chan[(offset >> 3) & 0x1F];
             * ptChip->Address = offset & 0x07;
             * WriteSlot(ptChip, ptChip->Slots + ptChip->CurSlot, ptChip->Address, data);*/
        }
Ejemplo n.º 3
0
        public void multipcm_write_rom2(byte ChipID, UInt32 ROMSize, UInt32 offset, UInt32 length, byte[] data, Int32 srcStartAddress)
        {
            _MultiPCM ptChip = MultiPCMData[ChipID];

            if (ptChip.ROM == null || ptChip.ROM.Length < ROMSize)
            {
                multipcm_alloc_rom(ChipID, ROMSize);
            }

            if (offset > ptChip.ROMSize)
            {
                return;
            }
            if (offset + length > ptChip.ROMSize)
            {
                length = (uint)(ptChip.ROMSize - offset);
            }

            for (int i = 0; i < length; i++)
            {
                if (data.Length <= i + srcStartAddress)
                {
                    break;
                }
                ptChip.ROM[i + offset] = data[i + srcStartAddress];
            }


            return;
        }
Ejemplo n.º 4
0
        /* MAME/M1 access functions */

        //void multipcm_set_bank(running_device *device, UINT32 leftoffs, UINT32 rightoffs)
        public void multipcm_set_bank(byte ChipID, UInt32 leftoffs, UInt32 rightoffs)
        {
            //MultiPCM *ptChip = get_safe_token(device);
            _MultiPCM ptChip = MultiPCMData[ChipID];

            ptChip.BankL = leftoffs;
            ptChip.BankR = rightoffs;
        }
Ejemplo n.º 5
0
        public void device_stop_multipcm(byte ChipID)
        {
            _MultiPCM ptChip = MultiPCMData[ChipID];

            //free(ptChip->ROM);
            ptChip.ROM = null;

            return;
        }
Ejemplo n.º 6
0
        public void multipcm_set_mute_mask(byte ChipID, UInt32 MuteMask)
        {
            _MultiPCM ptChip = MultiPCMData[ChipID];
            byte      CurChn;

            for (CurChn = 0; CurChn < 28; CurChn++)
            {
                ptChip.Slots[CurChn].Muted = (byte)((MuteMask >> CurChn) & 0x01);
            }

            return;
        }
Ejemplo n.º 7
0
        private void multipcm_w_quick(byte ChipID, byte offset, byte data)
        {
            _MultiPCM ptChip = MultiPCMData[ChipID];

            ptChip.cur_slot = VALUE_TO_CHANNEL[(offset >> 3) & 0x1F];
            ptChip.address  = offset & 0x07;
            if (ptChip.cur_slot == -1)
            {
                return;
            }
            write_slot(ptChip, ptChip.slots[ptChip.cur_slot], ptChip.address, data);
        }
Ejemplo n.º 8
0
        public void device_reset_multipcm(byte ChipID)
        {
            _MultiPCM ptChip = MultiPCMData[ChipID];
            int       i;

            for (i = 0; i < 28; ++i)
            {
                ptChip.Slots[i].Num     = (byte)i;
                ptChip.Slots[i].Playing = 0;
            }

            return;
        }
Ejemplo n.º 9
0
        public void multipcm_bank_write(byte ChipID, byte offset, UInt16 data)
        {
            _MultiPCM ptChip = MultiPCMData[ChipID];

            if ((offset & 0x01) != 0)
            {
                ptChip.BankL = (UInt32)(data << 16);
            }
            if ((offset & 0x02) != 0)
            {
                ptChip.BankR = (UInt32)(data << 16);
            }

            return;
        }
Ejemplo n.º 10
0
        private void lfo_compute_step(_MultiPCM ptChip, _lfo_t lfo, UInt32 lfo_frequency, UInt32 lfo_scale, Int32 amplitude_lfo)
        {
            float step = (float)(LFO_FREQ[lfo_frequency] * 256.0f / (float)ptChip.rate);

            lfo.phase_step = (UInt32)((float)(1 << LFO_SHIFT) * step);
            if (amplitude_lfo != 0)
            {
                lfo.table = amplitude_table;
                lfo.scale = amplitude_scale_tables[lfo_scale];
            }
            else
            {
                lfo.table = pitch_table;
                lfo.scale = pitch_scale_tables[lfo_scale];
            }
        }
Ejemplo n.º 11
0
        private void LFO_ComputeStep(_MultiPCM ptChip, _LFO LFO, UInt32 LFOF, UInt32 LFOS, Int32 ALFO)
        {
            float step = (float)(LFOFreq[LFOF] * 256.0 / (float)ptChip.Rate);

            LFO.phase_step = (UInt32)((float)(1 << LFO_SHIFT) * step);
            if (ALFO != 0)
            {
                LFO.table = ALFO_TRI;
                LFO.scale = ASCALES[LFOS];
            }
            else
            {
                LFO.table = PLFO_TRI;
                LFO.scale = PSCALES[LFOS];
            }
        }
Ejemplo n.º 12
0
        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);
        }
Ejemplo n.º 13
0
        public void multipcm_write_rom(byte ChipID, UInt32 offset, UInt32 length, byte[] data)
        {
            _MultiPCM ptChip = MultiPCMData[ChipID];

            if (offset > ptChip.ROMSize)
            {
                return;
            }
            if (offset + length > ptChip.ROMSize)
            {
                length = (uint)(ptChip.ROMSize - offset);
            }

            for (int i = 0; i < length; i++)
            {
                ptChip.ROM[i + offset] = data[i];
            }

            return;
        }
Ejemplo n.º 14
0
        /* MAME/M1 access functions */

        public void multipcm_alloc_rom(byte ChipID, UInt32 memsize)
        {
            _MultiPCM ptChip = MultiPCMData[ChipID];

            if (ptChip.ROMSize == memsize)
            {
                return;
            }

            ptChip.ROM     = new byte[memsize];
            ptChip.ROMSize = memsize;
            for (int i = 0; i < memsize; i++)
            {
                ptChip.ROM[i] = 0xFF;
            }

            ptChip.ROMMask = common.pow2_mask(memsize);

            return;
        }
Ejemplo n.º 15
0
        //WRITE8_DEVICE_HANDLER( multipcm_w )
        private void multipcm_write(byte ChipID, Int32 offset, byte data)
        {
            //MultiPCM *ptChip = get_safe_token(device);
            _MultiPCM ptChip = MultiPCMData[ChipID];

            switch (offset)
            {
            case 0:         //Data write
                if (ptChip.cur_slot == -1)
                {
                    return;
                }
                write_slot(ptChip, ptChip.slots[ptChip.cur_slot], ptChip.address, data);
                break;

            case 1:
                ptChip.cur_slot = VALUE_TO_CHANNEL[data & 0x1f];
                break;

            case 2:
                ptChip.address = (data > 7) ? 7 : data;
                break;

            // special SEGA banking
            case 0x10:      // 1 MB banking (Sega Model 1)
                ptChip.sega_banking = 1;
                ptChip.bank0        = (uint)((data << 20) | 0x000000);
                ptChip.bank1        = (uint)((data << 20) | 0x080000);
                break;

            case 0x11:      // 512 KB banking - low bank (Sega Multi 32)
                ptChip.sega_banking = 1;
                ptChip.bank0        = (uint)(data << 19);
                break;

            case 0x12:      // 512 KB banking - high bank (Sega Multi 32)
                ptChip.sega_banking = 1;
                ptChip.bank1        = (uint)(data << 19);
                break;
            }
        }
Ejemplo n.º 16
0
        private void EG_Calc(_MultiPCM ptChip, _SLOT slot)
        {
            Int32 octave = ((slot.Regs[3] >> 4) - 1) & 0xf;
            Int32 rate;

            if ((octave & 8) != 0)
            {
                octave = octave - 16;
            }
            if (slot.Sample.KRS != 0xf)
            {
                rate = (octave + slot.Sample.KRS) * 2 + ((slot.Regs[3] >> 3) & 1);
            }
            else
            {
                rate = 0;
            }

            slot.EG.AR  = (Int32)Get_RATE(ptChip.ARStep, (UInt32)rate, slot.Sample.AR);
            slot.EG.D1R = (Int32)Get_RATE(ptChip.DRStep, (UInt32)rate, slot.Sample.DR1);
            slot.EG.D2R = (Int32)Get_RATE(ptChip.DRStep, (UInt32)rate, slot.Sample.DR2);
            slot.EG.RR  = (Int32)Get_RATE(ptChip.DRStep, (UInt32)rate, slot.Sample.RR);
            slot.EG.DL  = 0xf - slot.Sample.DL;
        }
Ejemplo n.º 17
0
        public void multipcm_write_rom2(byte ChipID, Int32 ROMSize, Int32 DataStart, Int32 DataLength, byte[] ROMData, Int32 srcStartAddress)
        {
            _MultiPCM ptChip = MultiPCMData[ChipID];
            UInt16    CurSmpl;
            _Sample   TempSmpl;
            //byte[] ptSample;
            Int32 ptSample;

            if (ptChip.ROMSize != ROMSize)
            {
                ptChip.ROM     = new sbyte[ROMSize];// (INT8*)realloc(ptChip.ROM, ROMSize);
                ptChip.ROMSize = (UInt32)ROMSize;

                for (ptChip.ROMMask = 1; ptChip.ROMMask < ROMSize; ptChip.ROMMask <<= 1)
                {
                    ;
                }
                ptChip.ROMMask--;

                for (int i = 0; i < ROMSize; i++)
                {
                    ptChip.ROM[i] = -1;                              //0xff;
                }
                //memset(ptChip.ROM, 0xFF, ROMSize);
            }
            if (DataStart > ROMSize)
            {
                return;
            }
            if (DataStart + DataLength > ROMSize)
            {
                DataLength = ROMSize - DataStart;
            }

            for (int i = 0; i < DataLength; i++)
            {
                ptChip.ROM[i + DataStart] = (sbyte)ROMData[i + srcStartAddress];
            }
            //memcpy(ptChip.ROM + DataStart, ROMData, DataLength);

            if (DataStart < 0x200 * 12)
            {
                for (CurSmpl = 0; CurSmpl < 512; CurSmpl++)
                {
                    TempSmpl = ptChip.Samples[CurSmpl];
                    //ptSample = (byte*)ptChip.ROM + CurSmpl * 12;
                    ptSample        = CurSmpl * 12;
                    TempSmpl.Start  = (UInt32)(((byte)ptChip.ROM[ptSample + 0] << 16) | ((byte)ptChip.ROM[ptSample + 1] << 8) | ((byte)ptChip.ROM[ptSample + 2] << 0));
                    TempSmpl.Loop   = (UInt32)(((byte)ptChip.ROM[ptSample + 3] << 8) | ((byte)ptChip.ROM[ptSample + 4] << 0));
                    TempSmpl.End    = (UInt32)(0xffff - (((byte)ptChip.ROM[ptSample + 5] << 8) | ((byte)ptChip.ROM[ptSample + 6] << 0)));
                    TempSmpl.LFOVIB = (byte)ptChip.ROM[ptSample + 7];
                    TempSmpl.DR1    = (byte)((byte)ptChip.ROM[ptSample + 8] & 0xf);
                    TempSmpl.AR     = (byte)(((byte)ptChip.ROM[ptSample + 8] >> 4) & 0xf);
                    TempSmpl.DR2    = (byte)((byte)ptChip.ROM[ptSample + 9] & 0xf);
                    TempSmpl.DL     = (byte)(((byte)ptChip.ROM[ptSample + 9] >> 4) & 0xf);
                    TempSmpl.RR     = (byte)((byte)ptChip.ROM[ptSample + 10] & 0xf);
                    TempSmpl.KRS    = (byte)(((byte)ptChip.ROM[ptSample + 10] >> 4) & 0xf);
                    TempSmpl.AM     = (byte)(ptChip.ROM[ptSample + 11]);
                    //Console.WriteLine("LFOVIB{0}  AM{1}", ptChip.ROM[ptSample + 7], ptChip.ROM[ptSample + 11]);
                }
            }

            return;
        }
Ejemplo n.º 18
0
        //static STREAM_UPDATE( MultiPCM_update )
        public void MultiPCM_update(byte ChipID, Int32[][] outputs, Int32 samples)
        {
            //MultiPCM *ptChip = (MultiPCM *)param;
            _MultiPCM ptChip = MultiPCMData[ChipID];

            Int32[][] datap = new Int32[2][];
            Int32     i, sl;

            datap[0] = outputs[0];
            datap[1] = outputs[1];

            for (int j = 0; j < samples; j++)
            {
                datap[0][j] = 0;
                datap[1][j] = 0;
            }
            //memset(datap[0], 0, sizeof(*datap[0]) * samples);
            //memset(datap[1], 0, sizeof(*datap[1]) * samples);


            for (i = 0; i < samples; ++i)
            {
                Int32 smpl = 0;
                Int32 smpr = 0;
                for (sl = 0; sl < 28; ++sl)
                {
                    _SLOT slot = ptChip.Slots[sl];
                    if (slot.Playing != 0 && slot.Muted == 0)
                    {
                        UInt32 vol = (slot.TL >> SHIFT) | (slot.Pan << 7);
                        UInt32 adr = slot.offset >> SHIFT;
                        Int32  sample;
                        UInt32 step    = slot.step;
                        Int32  csample = (Int16)(ptChip.ROM[(slot.Base + adr) & ptChip.ROMMask] << 8);
                        Int32  fpart   = (Int32)(slot.offset & ((1 << SHIFT) - 1));
                        sample = (csample * fpart + slot.Prev * ((1 << SHIFT) - fpart)) >> SHIFT;

                        if ((slot.Regs[6] & 7) != 0)    //Vibrato enabled
                        {
                            step   = (UInt32)(step * PLFO_Step(slot.PLFO));
                            step >>= SHIFT;
                        }

                        slot.offset += step;
                        if (slot.offset >= (slot.Sample.End << SHIFT))
                        {
                            slot.offset = slot.Sample.Loop << SHIFT;
                        }
                        if ((adr ^ (slot.offset >> SHIFT)) != 0)
                        {
                            slot.Prev = csample;
                        }

                        if ((slot.TL >> SHIFT) != slot.DstTL)
                        {
                            slot.TL += (UInt32)slot.TLStep;
                        }

                        if ((slot.Regs[7] & 7) != 0)    //Tremolo enabled
                        {
                            sample   = sample * ALFO_Step(slot.ALFO);
                            sample >>= SHIFT;
                        }

                        sample = (sample * EG_Update(slot)) >> 10;

                        smpl += (LPANTABLE[vol] * sample) >> SHIFT;
                        smpr += (RPANTABLE[vol] * sample) >> SHIFT;
                    }
                }

                /*#define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x)
                 *      datap[0][i]=ICLIP16(smpl);
                 *      datap[1][i]=ICLIP16(smpr);*/
                datap[0][i] = smpl;
                datap[1][i] = smpr;
            }
        }
Ejemplo n.º 19
0
        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;
            }
        }
Ejemplo n.º 20
0
        //static STREAM_UPDATE( MultiPCM_update )
        public void MultiPCM_update(byte ChipID, Int32[][] outputs, Int32 samples)
        {
            //MultiPCM *ptChip = (MultiPCM *)param;
            _MultiPCM ptChip = MultiPCMData[ChipID];
            //Int32[][] datap = new Int32[2][];
            Int32 i, sl;

            //datap[0] = outputs[0];
            //datap[1] = outputs[1];

            for (int j = 0; j < samples; j++)
            {
                outputs[0][j] = 0;
                outputs[1][j] = 0;
            }
            //memset(datap[0], 0, sizeof(*datap[0]) * samples);
            //memset(datap[1], 0, sizeof(*datap[1]) * samples);


            for (i = 0; i < samples; ++i)
            {
                Int32 smpl = 0;
                Int32 smpr = 0;
                for (sl = 0; sl < 28; ++sl)
                {
                    _slot_t slot = ptChip.slots[sl];
                    if (slot.playing != 0 && slot.muted == 0)
                    {
                        UInt32 vol     = (slot.total_level >> TL_SHIFT) | (slot.pan << 7);
                        UInt32 spos    = slot.offset >> TL_SHIFT;
                        UInt32 step    = slot.step;
                        Int32  csample = 0;
                        Int32  fpart   = (Int32)(slot.offset & ((1 << TL_SHIFT) - 1));
                        Int32  sample;// = (csample * fpart + slot.prev_sample * ((1 << SHIFT) - fpart)) >> SHIFT;


                        if ((slot.format & 8) != 0)   // 12-bit linear
                        {
                            UInt32 adr = slot.Base + (spos >> 2) * 6;
                            switch (spos & 3)
                            {
                            case 0:
                            {         // ab.c .... ....
                                Int16 w0 = (short)(read_byte(ptChip, adr) << 8 | ((read_byte(ptChip, adr + 1) & 0xf) << 4));
                                csample = w0;
                                break;
                            }

                            case 1:
                            {         // ..C. AB.. ....
                                Int16 w0 = (short)((read_byte(ptChip, adr + 2) << 8) | (read_byte(ptChip, adr + 1) & 0xf0));
                                csample = w0;
                                break;
                            }

                            case 2:
                            {         // .... ..ab .c..
                                Int16 w0 = (short)(read_byte(ptChip, adr + 3) << 8 | ((read_byte(ptChip, adr + 4) & 0xf) << 4));
                                csample = w0;
                                break;
                            }

                            case 3:
                            {         // .... .... C.AB
                                Int16 w0 = (short)((read_byte(ptChip, adr + 5) << 8) | (read_byte(ptChip, adr + 4) & 0xf0));
                                csample = w0;
                                break;
                            }
                            }
                        }
                        else
                        {
                            csample = (Int16)(read_byte(ptChip, slot.Base + spos) << 8);
                        }

                        sample = (csample * fpart + slot.prev_sample * ((1 << TL_SHIFT) - fpart)) >> TL_SHIFT;

                        if ((slot.regs[6] & 7) != 0) // Vibrato enabled
                        {
                            step   = (uint)(step * pitch_lfo_step(slot.pitch_lfo));
                            step >>= TL_SHIFT;
                        }

                        slot.offset += step;
                        if (slot.offset >= (slot.sample.end << TL_SHIFT))
                        {
                            slot.offset = slot.sample.loop << TL_SHIFT;
                        }

                        if ((spos ^ (slot.offset >> TL_SHIFT)) != 0)
                        {
                            slot.prev_sample = csample;
                        }

                        if ((slot.total_level >> TL_SHIFT) != slot.dest_total_level)
                        {
                            slot.total_level += (uint)slot.total_level_step;
                        }

                        if ((slot.regs[7] & 7) != 0) // Tremolo enabled
                        {
                            sample   = sample * amplitude_lfo_step(slot.amplitude_lfo);
                            sample >>= TL_SHIFT;
                        }

                        sample = (sample * envelope_generator_update(slot)) >> 10;

                        smpl += (left_pan_table[vol] * sample) >> TL_SHIFT;
                        smpr += (right_pan_table[vol] * sample) >> TL_SHIFT;
                    }
                }

                outputs[0][i] = smpl;
                outputs[1][i] = smpr;
            }
        }
Ejemplo n.º 21
0
 private byte read_byte(_MultiPCM ptChip, UInt32 addr)
 {
     return(ptChip.ROM[addr & ptChip.ROMMask]);
 }
Ejemplo n.º 22
0
        private void write_slot(_MultiPCM ptChip, _slot_t 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.
                        // patched to load all sample data here, so registers 6 and 7 aren't overridden by KeyOn -Valley Bell
                init_sample(ptChip, slot.sample, (ushort)(slot.regs[1] | ((slot.regs[2] & 1) << 8)));
                write_slot(ptChip, slot, 6, slot.sample.lfo_vibrato_reg);
                write_slot(ptChip, slot, 7, slot.sample.lfo_amplitude_reg);
                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.freq_step_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.playing     = 1;
                    slot.Base        = slot.sample.start;
                    slot.offset      = 0;
                    slot.prev_sample = 0;
                    slot.total_level = slot.dest_total_level << TL_SHIFT;
                    slot.format      = slot.sample.format;

                    envelope_generator_calc(ptChip, slot);
                    slot.envelope_gen.state  = _STATE.ATTACK;
                    slot.envelope_gen.volume = 0;

                    if (ptChip.sega_banking != 0)
                    {
                        slot.Base &= 0x1fffff;
                        if (slot.Base >= 0x100000)
                        {
                            if ((slot.Base & 0x080000) != 0)
                            {
                                slot.Base = (slot.Base & 0x07ffff) | ptChip.bank1;
                            }

                            else
                            {
                                slot.Base = (slot.Base & 0x07ffff) | ptChip.bank0;
                            }
                        }
                    }
                }
                else
                {
                    if (slot.playing != 0)
                    {
                        if (slot.sample.release_reg != 0xf)
                        {
                            slot.envelope_gen.state = _STATE.RELEASE;
                        }
                        else
                        {
                            slot.playing = 0;
                        }
                    }
                }
            }
            break;

            case 5:     //TL+Interpolation
            {
                slot.dest_total_level = (UInt32)((data >> 1) & 0x7f);
                if ((data & 1) == 0)            //Interpolate TL
                {
                    if ((slot.total_level >> TL_SHIFT) > slot.dest_total_level)
                    {
                        slot.total_level_step = ptChip.total_level_steps[0];         // decrease
                    }
                    else
                    {
                        slot.total_level_step = ptChip.total_level_steps[1];         // increase
                    }
                }
                else
                {
                    slot.total_level = slot.dest_total_level << TL_SHIFT;
                }
            }
            break;

            case 6:     //LFO freq+PLFO
            {
                if (data != 0)
                {
                    lfo_compute_step(ptChip, slot.pitch_lfo, (UInt32)(slot.regs[6] >> 3) & 7, (UInt32)(slot.regs[6] & 7), 0);
                    lfo_compute_step(ptChip, slot.amplitude_lfo, (UInt32)(slot.regs[6] >> 3) & 7, (UInt32)(slot.regs[7] & 7), 1);
                }
            }
            break;

            case 7:     //ALFO
            {
                if (data != 0)
                {
                    lfo_compute_step(ptChip, slot.pitch_lfo, (UInt32)(slot.regs[6] >> 3) & 7, (UInt32)(slot.regs[6] & 7), 0);
                    lfo_compute_step(ptChip, slot.amplitude_lfo, (UInt32)(slot.regs[6] >> 3) & 7, (UInt32)(slot.regs[7] & 7), 1);
                }
            }
            break;
            }
        }