Ejemplo n.º 1
0
        public override void Reset(byte ChipID)
        {
            int             i;
            SN76489_Context chip = SN76489_Chip[ChipID];

            chip.PSGStereo = 0xFF;

            for (i = 0; i <= 3; i++)
            {
                /* Initialise PSG state */
                chip.Registers[2 * i]     = 1;   /* tone freq=1 */
                chip.Registers[2 * i + 1] = 0xf; /* vol=off */
                chip.NoiseFreq            = 0x10;

                /* Set counters to 0 */
                chip.ToneFreqVals[i] = 0;

                /* Set flip-flops to 1 */
                chip.ToneFreqPos[i] = 1;

                /* Set intermediate positions to do-not-use value */
                chip.IntermediatePos[i] = float.MinValue;

                /* Set panning to centre */
                //centre_panning( chip.panning[i] );
            }

            chip.LatchedRegister = 0;

            /* Initialise noise generator */
            chip.NoiseShiftRegister = NoiseInitialState;

            /* Zero clock */
            chip.Clock = 0;
        }
Ejemplo n.º 2
0
        /*void SN76489_UpdateOne(SN76489_Context* chip, int *l, int *r)
         * {
         * INT16 tl,tr;
         * INT16 *buff[2] = { &tl, &tr };
         * SN76489_Update( chip, buff, 1 );
         * l = tl;
         * r = tr;
         * }*/

        /*int  SN76489_GetMute(SN76489_Context* chip)
         * {
         * return chip->Mute;
         * }*/

        private void SN76489_SetPanning(SN76489_Context chip, int ch0, int ch1, int ch2, int ch3)
        {
            calc_panning(chip.panning[0], ch0);
            calc_panning(chip.panning[1], ch1);
            calc_panning(chip.panning[2], ch2);
            calc_panning(chip.panning[3], ch3);
        }
Ejemplo n.º 3
0
        public void SN76489_GGStereoWrite(byte ChipID, int data)
        {
            SN76489_Context chip = SN76489_Chip[ChipID];

            chip.PSGStereo = data;
            //Console.WriteLine("WrPSGStereo:0:{0}", SN76489_Chip[0].PSGStereo);
            //Console.WriteLine("WrPSGStereo:1:{0}", SN76489_Chip[1].PSGStereo);
        }
Ejemplo n.º 4
0
        private void SN76489_Write(byte ChipID, int data)
        {
            SN76489_Context chip = SN76489_Chip[ChipID];

            if ((data & 0x80) != 0)
            {
                /* Latch/data byte  %1 cc t dddd */
                chip.LatchedRegister = (data >> 4) & 0x07;
                chip.Registers[chip.LatchedRegister] =
                    (chip.Registers[chip.LatchedRegister] & 0x3f0) /* zero low 4 bits */
                    | (data & 0xf);                                /* and replace with data */
            }
            else
            {
                /* Data byte        %0 - dddddd */
                if ((chip.LatchedRegister % 2) == 0 && (chip.LatchedRegister < 5))
                {
                    /* Tone register */
                    chip.Registers[chip.LatchedRegister] =
                        (chip.Registers[chip.LatchedRegister] & 0x00f) /* zero high 6 bits */
                        | ((data & 0x3f) << 4);                        /* and replace with data */
                }
                else
                {
                    /* Other register */
                    chip.Registers[chip.LatchedRegister] = data & 0x0f; /* Replace with data */
                }
            }
            switch (chip.LatchedRegister)
            {
            case 0:
            case 2:
            case 4:     /* Tone channels */
                if (chip.Registers[chip.LatchedRegister] == 0)
                {
                    chip.Registers[chip.LatchedRegister] = 1;     /* Zero frequency changed to 1 to avoid div/0 */
                }
                break;

            case 6:                                                          /* Noise */
                chip.NoiseShiftRegister = NoiseInitialState;                 /* reset shift register */
                chip.NoiseFreq          = 0x10 << (chip.Registers[6] & 0x3); /* set noise signal generator frequency */
                break;
            }
        }
Ejemplo n.º 5
0
        public override uint Start(byte ChipID, uint SamplingRate, uint PSGClockValue, params object[] option)
        {
            int i;

            SN76489_Chip[ChipID] = new SN76489_Context();
            SN76489_Context chip = SN76489_Chip[ChipID];

            if (chip != null)
            {
                chip.dClock = (float)(PSGClockValue & 0x7FFFFFF) / 16 / SamplingRate;

                SN76489_SetMute(ChipID, 15);
                SN76489_Config(chip, /*MUTE_ALLON,*/ feedback_patterns.FB_SEGAVDP, sr_widths.SRW_SEGAVDP, 1);

                for (i = 0; i <= 3; i++)
                {
                    centre_panning(chip.panning[i]);
                }
                //SN76489_Reset(chip);

                if ((PSGClockValue & 0x80000000) != 0 && LastChipInit != null)
                {
                    // Activate special NeoGeoPocket Mode
                    LastChipInit.NgpFlags = 0x80 | 0x00;
                    chip.NgpFlags         = 0x80 | 0x01;
                    chip.NgpChip2         = LastChipInit;
                    LastChipInit.NgpChip2 = chip;
                    LastChipInit          = null;
                }
                else
                {
                    chip.NgpFlags = 0x00;
                    chip.NgpChip2 = null;
                    LastChipInit  = chip;
                }
            }

            return(SamplingRate);
        }
Ejemplo n.º 6
0
        //static unsigned short int FNumLimit;

        private void SN76489_Config(SN76489_Context chip, /*int mute,*/ feedback_patterns feedback, sr_widths sr_width, int boost_noise)
        {
            //chip->Mute = mute;
            chip.WhiteNoiseFeedback = feedback;
            chip.SRWidth            = sr_width;
        }
Ejemplo n.º 7
0
        public void SN76489_SetMute(byte ChipID, int val)
        {
            SN76489_Context chip = SN76489_Chip[ChipID];

            chip.Mute = val;
        }
Ejemplo n.º 8
0
        public override void Update(byte ChipID, int[][] buffer, int length)
        {
            SN76489_Context chip = SN76489_Chip[ChipID];
            //Console.WriteLine("PSGStereo:1:{0}", SN76489_Chip[1].PSGStereo);

            int             i, j;
            int             NGPMode;
            SN76489_Context chip2  = null;
            SN76489_Context chip_t = null;
            SN76489_Context chip_n = null;

            NGPMode = (chip.NgpFlags >> 7) & 0x01;
            if (NGPMode == 0)
            {
                chip2  = null;
                chip_t = chip_n = chip;
            }
            else
            {
                chip2 = (SN76489_Context)chip.NgpChip2;
                if ((chip.NgpFlags & 0x01) == 0)
                {
                    chip_t = chip;
                    chip_n = chip2;
                }
                else
                {
                    chip_t = chip2;
                    chip_n = chip;
                }
            }

            for (j = 0; j < length; j++)
            {
                /* Tone channels */
                for (i = 0; i <= 2; ++i)
                {
                    if ((chip_t.Mute >> i & 1) != 0)
                    {
                        if (chip_t.IntermediatePos[i] != float.MinValue)
                        {
                            /* Intermediate position (antialiasing) */
                            chip.Channels[i] = (short)(PSGVolumeValues[chip.Registers[2 * i + 1]] * chip_t.IntermediatePos[i]);
                        }
                        else
                        {
                            /* Flat (no antialiasing needed) */
                            chip.Channels[i] = PSGVolumeValues[chip.Registers[2 * i + 1]] * chip_t.ToneFreqPos[i];
                        }
                    }
                    else
                    {
                        /* Muted channel */
                        chip.Channels[i] = 0;
                    }
                }

                /* Noise channel */
                if ((chip_n.Mute >> 3 & 1) != 0)
                {
                    //chip->Channels[3] = PSGVolumeValues[chip->Registers[7]] * ( chip_n->NoiseShiftRegister & 0x1 ) * 2; /* double noise volume */
                    // Now the noise is bipolar, too. -Valley Bell
                    chip.Channels[3] = PSGVolumeValues[chip.Registers[7]] * ((chip_n.NoiseShiftRegister & 0x1) * 2 - 1);
                    // due to the way the white noise works here, it seems twice as loud as it should be
                    if ((chip.Registers[6] & 0x4) != 0)
                    {
                        chip.Channels[3] >>= 1;
                    }
                }
                else
                {
                    chip.Channels[i] = 0;
                }

                // Build stereo result into buffer
                buffer[0][j] = 0;
                buffer[1][j] = 0;
                int bl = 0;
                int br = 0;
                if (chip.NgpFlags == 0)
                {
                    // For all 4 channels
                    for (i = 0; i <= 3; ++i)
                    {
                        if (((chip.PSGStereo >> i) & 0x11) == 0x11)
                        {
                            //Console.WriteLine("ggpan1");
                            // no GG stereo for this channel
                            if (chip.panning[i][0] == 1.0f)
                            {
                                bl = chip.Channels[i]; // left
                                br = chip.Channels[i]; // right
                            }
                            else
                            {
                                bl = (int)(chip.panning[i][0] * chip.Channels[i]); // left
                                br = (int)(chip.panning[i][1] * chip.Channels[i]); // right
                            }
                        }
                        else
                        {
                            //Console.WriteLine("ggpan2");
                            // GG stereo overrides panning
                            bl = ((chip.PSGStereo >> (i + 4)) & 0x1) * chip.Channels[i]; // left
                            br = ((chip.PSGStereo >> i) & 0x1) * chip.Channels[i];       // right
                            //Console.WriteLine("Ch:bl:br:{0}:{1}:{2}:{3}",i,bl,br, chip.Channels[i]);
                        }

                        buffer[0][j]     += bl;
                        buffer[1][j]     += br;
                        chip.volume[i][0] = Math.Abs(bl); // Math.Max(bl, chip.volume[i][0]);
                        chip.volume[i][1] = Math.Abs(br); // Math.Max(br, chip.volume[i][1]);
                    }
                    //Log.WriteLine(LogLevel.TRACE,string.Format("{0}", chip.Channels[3]));
                }
                else
                {
                    if ((chip.NgpFlags & 0x01) == 0)
                    {
                        // For all 3 tone channels
                        for (i = 0; i < 3; i++)
                        {
                            bl                = (chip.PSGStereo >> (i + 4) & 0x1) * chip.Channels[i]; // left
                            br                = (chip.PSGStereo >> i & 0x1) * chip2.Channels[i];      // right
                            buffer[0][j]     += bl;
                            buffer[1][j]     += br;
                            chip.volume[i][0] = Math.Abs(bl); // Math.Max(bl, chip.volume[i][0]);
                            chip.volume[i][1] = Math.Abs(br); // Math.Max(br, chip.volume[i][1]);
                        }
                    }
                    else
                    {
                        // noise channel
                        i                 = 3;
                        bl                = (chip.PSGStereo >> (i + 4) & 0x1) * chip2.Channels[i]; // left
                        br                = (chip.PSGStereo >> i & 0x1) * chip.Channels[i];        // right
                        buffer[0][j]     += bl;
                        buffer[1][j]     += br;
                        chip.volume[i][0] = Math.Abs(bl); // Math.Max(bl, chip.volume[i][0]);
                        chip.volume[i][1] = Math.Abs(br); // Math.Max(br, chip.volume[i][1]);
                    }
                }


                /* Increment clock by 1 sample length */
                chip.Clock += chip.dClock;
                chip.NumClocksForSample = (int)chip.Clock;  /* truncate */
                chip.Clock -= chip.NumClocksForSample;      /* remove integer part */

                /* Decrement tone channel counters */
                for (i = 0; i <= 2; ++i)
                {
                    chip.ToneFreqVals[i] -= chip.NumClocksForSample;
                }

                /* Noise channel: match to tone2 or decrement its counter */
                if (chip.NoiseFreq == 0x80)
                {
                    chip.ToneFreqVals[3] = chip.ToneFreqVals[2];
                }
                else
                {
                    chip.ToneFreqVals[3] -= chip.NumClocksForSample;
                }

                /* Tone channels: */
                for (i = 0; i <= 2; ++i)
                {
                    if (chip.ToneFreqVals[i] <= 0)
                    {   /* If the counter gets below 0... */
                        if (chip.Registers[i * 2] >= PSG_CUTOFF)
                        {
                            /* For tone-generating values, calculate how much of the sample is + and how much is - */
                            /* This is optimised into an even more confusing state than it was in the first place... */
                            chip.IntermediatePos[i] = (chip.NumClocksForSample - chip.Clock + 2 * chip.ToneFreqVals[i]) * chip.ToneFreqPos[i] / (chip.NumClocksForSample + chip.Clock);
                            /* Flip the flip-flop */
                            chip.ToneFreqPos[i] = -chip.ToneFreqPos[i];
                        }
                        else
                        {
                            /* stuck value */
                            chip.ToneFreqPos[i]     = 1;
                            chip.IntermediatePos[i] = float.MinValue;
                        }
                        chip.ToneFreqVals[i] += chip.Registers[i * 2] * (chip.NumClocksForSample / chip.Registers[i * 2] + 1);
                    }
                    else
                    {
                        /* signal no antialiasing needed */
                        chip.IntermediatePos[i] = float.MinValue;
                    }
                }

                /* Noise channel */
                if (chip.ToneFreqVals[3] <= 0)
                {
                    /* If the counter gets below 0... */
                    /* Flip the flip-flop */
                    chip.ToneFreqPos[3] = -chip.ToneFreqPos[3];
                    if (chip.NoiseFreq != 0x80)
                    {
                        /* If not matching tone2, decrement counter */
                        chip.ToneFreqVals[3] += chip.NoiseFreq * (chip.NumClocksForSample / chip.NoiseFreq + 1);
                    }
                    if (chip.ToneFreqPos[3] == 1)
                    {
                        /* On the positive edge of the square wave (only once per cycle) */
                        int Feedback;
                        if ((chip.Registers[6] & 0x4) != 0)
                        {
                            /* White noise */
                            /* Calculate parity of fed-back bits for feedback */
                            switch (chip.WhiteNoiseFeedback)
                            {
                            /* Do some optimised calculations for common (known) feedback values */
                            //case 0x0003: /* SC-3000, BBC %00000011 */
                            case feedback_patterns.FB_SEGAVDP:     /* SMS, GG, MD  %00001001 */
                                                                   /* If two bits fed back, I can do Feedback=(nsr & fb) && (nsr & fb ^ fb) */
                                                                   /* since that's (one or more bits set) && (not all bits set) */
                                Feedback = chip.NoiseShiftRegister & (int)chip.WhiteNoiseFeedback;
                                Feedback = (Feedback > 0) && (((chip.NoiseShiftRegister & (int)chip.WhiteNoiseFeedback) ^ (int)chip.WhiteNoiseFeedback) > 0) ? 1 : 0;
                                break;

                            default:
                                /* Default handler for all other feedback values */
                                /* XOR fold bits into the final bit */
                                Feedback  = chip.NoiseShiftRegister & (int)chip.WhiteNoiseFeedback;
                                Feedback ^= Feedback >> 8;
                                Feedback ^= Feedback >> 4;
                                Feedback ^= Feedback >> 2;
                                Feedback ^= Feedback >> 1;
                                Feedback &= 1;
                                break;
                            }
                        }
                        else      /* Periodic noise */
                        {
                            Feedback = chip.NoiseShiftRegister & 1;
                        }

                        chip.NoiseShiftRegister = (chip.NoiseShiftRegister >> 1) | (Feedback << ((int)chip.SRWidth - 1));
                    }
                }
            }

            visVolume[ChipID][0][0] = chip.volume[0][0];
            visVolume[ChipID][0][1] = chip.volume[0][1];
        }