コード例 #1
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        /************************************************************
         *
         *      DRQ callback
         *
         *************************************************************/

        /*static TIMER_CALLBACK( upd7759_slave_update )
         * {
         *      upd7759_state *chip = (upd7759_state *)ptr;
         *      UINT8 olddrq = chip.drq;
         *
         *      // update the stream
         *      //stream_update(chip.channel);
         *
         *      // advance the state
         *      advance_state(chip);
         *
         *      // if the DRQ changed, update it
         *      logerror("slave_update: DRQ %d->%d\n", olddrq, chip.drq);
         *      if (olddrq != chip.drq && chip.drqcallback)
         *              //(*chip.drqcallback)(chip.device, chip.drq);
         *              (*chip.drqcallback)(chip.drq);
         *
         *      // set a timer to go off when that is done
         *      //if (chip.state != STATE_IDLE)
         *      //	timer_adjust_oneshot(chip.timer, attotime_mul(chip.clock_period, chip.clocks_left), 0);
         * }*/


        /************************************************************
         *
         *      Sound startup
         *
         *************************************************************/

        private void upd7759_reset(_upd7759_state chip)
        {
            chip.pos                = 0;
            chip.fifo_in            = 0;
            chip.drq                = 0;
            chip.state              = (sbyte)STATE.IDLE;
            chip.clocks_left        = 0;
            chip.nibbles_left       = 0;
            chip.repeat_count       = 0;
            chip.post_drq_state     = (sbyte)STATE.IDLE;
            chip.post_drq_clocks    = 0;
            chip.req_sample         = 0;
            chip.last_sample        = 0;
            chip.block_header       = 0;
            chip.sample_rate        = 0;
            chip.first_valid_header = 0;
            chip.offset             = 0;
            chip.repeat_offset      = 0;
            chip.adpcm_state        = 0;
            chip.adpcm_data         = 0;
            chip.sample             = 0;

            // Valley Bell: reset buffer
            chip.data_buf[0]    = chip.data_buf[1] = 0x00;
            chip.dbuf_pos_read  = 0x00;
            chip.dbuf_pos_write = 0x00;

            /* turn off any timer */
            //if (chip.timer)
            //	timer_adjust_oneshot(chip.timer, attotime_never, 0);
            if (chip.ChipMode != 0)
            {
                chip.clocks_left = -1;
            }
        }
コード例 #2
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        //static DEVICE_RESET( upd7759 )
        private void device_reset_upd7759(byte ChipID)
        {
            _upd7759_state chip = UPD7759Data[ChipID];

            //upd7759_reset(get_safe_token(device));
            upd7759_reset(chip);
        }
コード例 #3
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        public void uPD7759_write_rom2(byte ChipID, int ROMSize, int DataStart, int DataLength, byte[] ROMData, int SrcStartAdr)
        {
            _upd7759_state chip = UPD7759Data[ChipID];

            if (chip.romsize != ROMSize)
            {
                chip.rombase = new byte[ROMSize];                // (UINT8*) realloc(chip.rombase, ROMSize);
                chip.romsize = (uint)ROMSize;
                for (int i = 0; i < ROMSize; i++)
                {
                    chip.rombase[i] = 0xff;
                }

                chip.rom    = chip.rombase;
                chip.romPtr = (int)chip.romoffset;
            }
            if (DataStart > ROMSize)
            {
                return;
            }
            if (DataStart + DataLength > ROMSize)
            {
                DataLength = ROMSize - DataStart;
            }

            for (int i = 0; i < DataLength; i++)
            {
                chip.rombase[i + DataStart] = ROMData[i + SrcStartAdr];
            }

            return;
        }
コード例 #4
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        //void upd7759_start_w(running_device *device, UINT8 data)
        private void upd7759_start_w(byte ChipID, byte data)
        {
            /* update the start value */
            //upd7759_state *chip = get_safe_token(device);
            _upd7759_state chip     = UPD7759Data[ChipID];
            byte           oldstart = chip.start;

            chip.start = (byte)((data != 0) ? 1 : 0);

#if DEBUG
            if (DEBUG_STATES != 0)
            {
                logerror(string.Format("upd7759_start_w: {0}->{1}\n", oldstart, chip.start));
            }
#endif
            /* update the stream first */
            //stream_update(chip.channel);

            /* on the rising edge, if we're idle, start going, but not if we're held in reset */
            if (chip.state == STATE.IDLE && oldstart == 0 && chip.start != 0 && chip.reset != 0)
            {
                chip.state = STATE.START;

                /* for slave mode, start the timer going */
                //if (chip.timer)
                //	timer_adjust_oneshot(chip.timer, attotime_zero, 0);
                chip.clocks_left = 0;
            }
        }
コード例 #5
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        //int upd7759_busy_r(running_device *device)
        private int upd7759_busy_r(byte ChipID)
        {
            /* return /BUSY */
            //upd7759_state *chip = get_safe_token(device);
            _upd7759_state chip = UPD7759Data[ChipID];

            return((chip.state == (sbyte)STATE.IDLE) ? 1 : 0);
        }
コード例 #6
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        //void upd7759_set_bank_base(running_device *device, UINT32 base)
        private void upd7759_set_bank_base(byte ChipID, UInt32 base_)
        {
            //upd7759_state *chip = get_safe_token(device);
            _upd7759_state chip = UPD7759Data[ChipID];

            chip.rom       = chip.rombase;
            chip.romPtr    = (int)base_;
            chip.romoffset = base_;
        }
コード例 #7
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        private void device_stop_upd7759(byte ChipID)
        {
            _upd7759_state chip = UPD7759Data[ChipID];

            //free(chip.rombase); chip.rombase = NULL;
            chip.rom     = null;
            chip.romPtr  = 0;
            chip.rombase = null;

            return;
        }
コード例 #8
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        /************************************************************
         *
         *      Master chip state machine
         *
         *************************************************************/

        private void get_fifo_data(_upd7759_state chip)
        {
            if (chip.dbuf_pos_read == chip.dbuf_pos_write)
            {
                logerror("Warning: UPD7759 reading empty FIFO!\n");
                return;
            }

            chip.fifo_in = chip.data_buf[chip.dbuf_pos_read];
            chip.dbuf_pos_read++;
            chip.dbuf_pos_read &= 0x3F;

            return;
        }
コード例 #9
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        /************************************************************
         *
         *              ADPCM sample updater
         *
         *************************************************************/

        private void update_adpcm(_upd7759_state chip, int data)
        {
            /* update the sample and the state */
            chip.sample      += (Int16)upd7759_step[chip.adpcm_state][data];
            chip.adpcm_state += (sbyte)upd7759_state_table[data];

            /* clamp the state to 0..15 */
            if (chip.adpcm_state < 0)
            {
                chip.adpcm_state = 0;
            }
            else if (chip.adpcm_state > 15)
            {
                chip.adpcm_state = 15;
            }
        }
コード例 #10
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        /************************************************************
         *
         *      I/O handlers
         *
         *************************************************************/

        //void upd7759_reset_w(running_device *device, UINT8 data)
        private void upd7759_reset_w(byte ChipID, byte data)
        {
            /* update the reset value */
            //upd7759_state *chip = get_safe_token(device);
            _upd7759_state chip     = UPD7759Data[ChipID];
            byte           oldreset = chip.reset;

            chip.reset = (byte)((data != 0) ? 1 : 0);

            /* update the stream first */
            //stream_update(chip.channel);

            /* on the falling edge, reset everything */
            if (oldreset != 0 && chip.reset == 0)
            {
                upd7759_reset(chip);
            }
        }
コード例 #11
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        //WRITE8_DEVICE_HANDLER( upd7759_port_w )
        private void upd7759_port_w(byte ChipID, int offset, byte data)
        {
            /* update the FIFO value */
            //upd7759_state *chip = get_safe_token(device);
            _upd7759_state chip = UPD7759Data[ChipID];

            if (chip.ChipMode == 0)
            {
                chip.fifo_in = data;
            }
            else
            {
                // Valley Bell: added FIFO buffer for Slave mode
                chip.data_buf[chip.dbuf_pos_write] = data;
                chip.dbuf_pos_write++;
                chip.dbuf_pos_write &= 0x3F;
            }
        }
コード例 #12
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        /************************************************************
         *
         *      Stream callback
         *
         *************************************************************/

        //static STREAM_UPDATE( upd7759_update )
        private void upd7759_update(byte ChipID, int[][] outputs, int samples)
        {
            //upd7759_state *chip = (upd7759_state *)param;
            _upd7759_state chip        = UPD7759Data[ChipID];
            Int32          clocks_left = chip.clocks_left;
            Int16          sample      = chip.sample;
            UInt32         step        = chip.step;
            UInt32         pos         = chip.pos;

            int[] buffer     = outputs[0];
            int[] buffer2    = outputs[1];
            int   bufferPtr  = 0;
            int   bufferPtr2 = 0;

            /* loop until done */
            if (chip.state != (sbyte)STATE.IDLE)
            {
                while (samples != 0)
                {
                    /* store the current sample */
                    buffer[bufferPtr++]   = sample << 7;
                    buffer2[bufferPtr2++] = sample << 7;
                    samples--;

                    /* advance by the number of clocks/output sample */
                    pos += step;

                    /* handle clocks, but only in standalone mode */
                    if (chip.ChipMode == 0)
                    {
                        while (chip.rom != null && pos >= FRAC_ONE)
                        {
                            int clocks_this_time = (int)(pos >> FRAC_BITS);
                            if (clocks_this_time > clocks_left)
                            {
                                clocks_this_time = clocks_left;
                            }

                            /* clock once */
                            pos         -= (uint)(clocks_this_time * FRAC_ONE);
                            clocks_left -= clocks_this_time;

                            /* if we're out of clocks, time to handle the next state */
                            if (clocks_left == 0)
                            {
                                /* advance one state; if we hit idle, bail */
                                advance_state(chip);
                                if (chip.state == (sbyte)STATE.IDLE)
                                {
                                    break;
                                }

                                /* reimport the variables that we cached */
                                clocks_left = chip.clocks_left;
                                sample      = chip.sample;
                            }
                        }
                    }
                    else
                    {
                        byte CntFour;

                        if (clocks_left == 0)
                        {
                            advance_state(chip);
                            clocks_left = chip.clocks_left;
                        }

                        // advance the state (4x because of Clock Divider /4)
                        for (CntFour = 0; CntFour < 4; CntFour++)
                        {
                            clocks_left--;
                            if (clocks_left == 0)
                            {
                                advance_state(chip);
                                clocks_left = chip.clocks_left;
                            }
                        }
                    }
                }
            }

            /* if we got out early, just zap the rest of the buffer */
            if (samples != 0)
            {
                for (int i = 0; i < buffer.Length; i++)
                {
                    buffer[i] = 0;
                }
                for (int i = 0; i < buffer2.Length; i++)
                {
                    buffer2[i] = 0;
                }
            }

            /* flush the state back */
            chip.clocks_left = clocks_left;
            chip.pos         = pos;
        }
コード例 #13
0
ファイル: upd7759.cs プロジェクト: kuma4649/MDSound
        private void advance_state(_upd7759_state chip)
        {
            switch (chip.state)
            {
            /* Idle state: we stick around here while there's nothing to do */
            case STATE.IDLE:
                chip.clocks_left = 4;
                break;

            /* drop DRQ state: update to the intended state */
            case STATE.DROP_DRQ:
                chip.drq = 0;

                if (chip.ChipMode != 0)
                {
                    get_fifo_data(chip);                                // Slave Mode only
                }
                chip.clocks_left = chip.post_drq_clocks;
                chip.state       = chip.post_drq_state;
                break;

            /* Start state: we begin here as soon as a sample is triggered */
            case STATE.START:
                chip.req_sample = (byte)(chip.rom != null ? chip.fifo_in : 0x10);
#if DEBUG
                if (DEBUG_STATES != 0)
                {
                    DEBUG_METHOD(string.Format("UPD7759: req_sample = {0:02X}\n", chip.req_sample));
                }
#endif

                /* 35+ cycles after we get here, the /DRQ goes low
                 *     (first byte (number of samples in ROM) should be sent in response)
                 *
                 * (35 is the minimum number of cycles I found during heavy tests.
                 * Depending on the state the chip was in just before the /MD was set to 0 (reset, standby
                 * or just-finished-playing-previous-sample) this number can range from 35 up to ~24000).
                 * It also varies slightly from test to test, but not much - a few cycles at most.) */
                chip.clocks_left = 70;                         /* 35 - breaks cotton */
                chip.state       = STATE.FIRST_REQ;
                break;

            /* First request state: issue a request for the first byte */
            /* The expected response will be the index of the last sample */
            case STATE.FIRST_REQ:
#if DEBUG
                if (DEBUG_STATES != 0)
                {
                    DEBUG_METHOD("UPD7759: first data request\n");
                }
#endif
                chip.drq = 1;

                /* 44 cycles later, we will latch this value and request another byte */
                chip.clocks_left = 44;
                chip.state       = STATE.LAST_SAMPLE;
                break;

            /* Last sample state: latch the last sample value and issue a request for the second byte */
            /* The second byte read will be just a dummy */
            case STATE.LAST_SAMPLE:
                chip.last_sample = chip.rom != null ? chip.rom[chip.romPtr + 0] : chip.fifo_in;
#if DEBUG
                if (DEBUG_STATES != 0)
                {
                    DEBUG_METHOD(string.Format("UPD7759: last_sample = {0:02X}, requesting dummy 1\n", chip.last_sample));
                }
#endif
                chip.drq = 1;

                /* 28 cycles later, we will latch this value and request another byte */
                chip.clocks_left = 28;                         /* 28 - breaks cotton */
                chip.state       = ((chip.req_sample > chip.last_sample) ? STATE.IDLE : STATE.DUMMY1);
                break;

            /* First dummy state: ignore any data here and issue a request for the third byte */
            /* The expected response will be the MSB of the sample address */
            case STATE.DUMMY1:
#if DEBUG
                if (DEBUG_STATES != 0)
                {
                    DEBUG_METHOD("UPD7759: dummy1, requesting offset_hi\n");
                }
#endif
                chip.drq = 1;

                /* 32 cycles later, we will latch this value and request another byte */
                chip.clocks_left = 32;
                chip.state       = STATE.ADDR_MSB;
                break;

            /* Address MSB state: latch the MSB of the sample address and issue a request for the fourth byte */
            /* The expected response will be the LSB of the sample address */
            case STATE.ADDR_MSB:
                chip.offset = (uint)((chip.rom != null ? chip.rom[chip.romPtr + (chip.req_sample * 2 + 5)] : chip.fifo_in) << 9);
#if DEBUG
                if (DEBUG_STATES != 0)
                {
                    DEBUG_METHOD(string.Format("UPD7759: offset_hi = {0:02X}, requesting offset_lo\n", chip.offset >> 9));
                }
#endif
                chip.drq = 1;

                /* 44 cycles later, we will latch this value and request another byte */
                chip.clocks_left = 44;
                chip.state       = STATE.ADDR_LSB;
                break;

            /* Address LSB state: latch the LSB of the sample address and issue a request for the fifth byte */
            /* The expected response will be just a dummy */
            case STATE.ADDR_LSB:
                chip.offset |= (uint)((chip.rom != null ? chip.rom[chip.romPtr + (chip.req_sample * 2 + 6)] : chip.fifo_in) << 1);
#if DEBUG
                if (DEBUG_STATES != 0)
                {
                    DEBUG_METHOD(string.Format("UPD7759: offset_lo = {0:02X}, requesting dummy 2\n", (chip.offset >> 1) & 0xff));
                }
#endif
                chip.drq = 1;

                /* 36 cycles later, we will latch this value and request another byte */
                chip.clocks_left = 36;
                chip.state       = STATE.DUMMY2;
                break;

            /* Second dummy state: ignore any data here and issue a request for the the sixth byte */
            /* The expected response will be the first block header */
            case STATE.DUMMY2:
                chip.offset++;
                chip.first_valid_header = 0;
#if DEBUG
                if (DEBUG_STATES != 0)
                {
                    DEBUG_METHOD("UPD7759: dummy2, requesting block header\n");
                }
#endif
                chip.drq = 1;

                /* 36?? cycles later, we will latch this value and request another byte */
                chip.clocks_left = 36;
                chip.state       = STATE.BLOCK_HEADER;
                break;

            /* Block header state: latch the header and issue a request for the first byte afterwards */
            case STATE.BLOCK_HEADER:

                /* if we're in a repeat loop, reset the offset to the repeat point and decrement the count */
                if (chip.repeat_count != 0)
                {
                    chip.repeat_count--;
                    chip.offset = chip.repeat_offset;
                }
                chip.block_header = chip.rom != null ? chip.rom[chip.romPtr + (chip.offset++ & 0x1ffff)] : chip.fifo_in;
#if DEBUG
                if (DEBUG_STATES != 0)
                {
                    DEBUG_METHOD(string.Format("UPD7759: header (@{0:05X}) = {1:02X}, requesting next byte\n", chip.offset, chip.block_header));
                }
#endif
                chip.drq = 1;

                /* our next step depends on the top two bits */
                switch (chip.block_header & 0xc0)
                {
                case 0x00:                                  /* silence */
                    chip.clocks_left = 1024 * ((chip.block_header & 0x3f) + 1);
                    chip.state       = (chip.block_header == 0 && chip.first_valid_header != 0) ? STATE.IDLE : STATE.BLOCK_HEADER;
                    chip.sample      = 0;
                    chip.adpcm_state = 0;
                    break;

                case 0x40:                                  /* 256 nibbles */
                    chip.sample_rate  = (byte)((chip.block_header & 0x3f) + 1);
                    chip.nibbles_left = 256;
                    chip.clocks_left  = 36;                                    /* just a guess */
                    chip.state        = STATE.NIBBLE_MSN;
                    break;

                case 0x80:                                  /* n nibbles */
                    chip.sample_rate = (byte)((chip.block_header & 0x3f) + 1);
                    chip.clocks_left = 36;                  /* just a guess */
                    chip.state       = STATE.NIBBLE_COUNT;
                    break;

                case 0xc0:                                  /* repeat loop */
                    chip.repeat_count  = (byte)((chip.block_header & 7) + 1);
                    chip.repeat_offset = chip.offset;
                    chip.clocks_left   = 36;                                   /* just a guess */
                    chip.state         = STATE.BLOCK_HEADER;
                    break;
                }

                /* set a flag when we get the first non-zero header */
                if (chip.block_header != 0)
                {
                    chip.first_valid_header = 1;
                }
                break;

            /* Nibble count state: latch the number of nibbles to play and request another byte */
            /* The expected response will be the first data byte */
            case STATE.NIBBLE_COUNT:
                chip.nibbles_left = (UInt16)((chip.rom != null ? chip.rom[chip.romPtr + (chip.offset++ & 0x1ffff)] : chip.fifo_in) + 1);
#if DEBUG
                if (DEBUG_STATES != 0)
                {
                    DEBUG_METHOD(string.Format("UPD7759: nibble_count = {0}, requesting next byte\n", chip.nibbles_left));
                }
#endif
                chip.drq = 1;

                /* 36?? cycles later, we will latch this value and request another byte */
                chip.clocks_left = 36;                         /* just a guess */
                chip.state       = STATE.NIBBLE_MSN;
                break;

            /* MSN state: latch the data for this pair of samples and request another byte */
            /* The expected response will be the next sample data or another header */
            case STATE.NIBBLE_MSN:
                chip.adpcm_data = chip.rom != null ? chip.rom[chip.romPtr + (chip.offset++ & 0x1ffff)] : chip.fifo_in;
                update_adpcm(chip, chip.adpcm_data >> 4);
                chip.drq = 1;

                /* we stay in this state until the time for this sample is complete */
                chip.clocks_left = chip.sample_rate * 4;
                if (--chip.nibbles_left == 0)
                {
                    chip.state = STATE.BLOCK_HEADER;
                }
                else
                {
                    chip.state = STATE.NIBBLE_LSN;
                }
                break;

            /* LSN state: process the lower nibble */
            case STATE.NIBBLE_LSN:
                update_adpcm(chip, chip.adpcm_data & 15);

                /* we stay in this state until the time for this sample is complete */
                chip.clocks_left = chip.sample_rate * 4;
                if (--chip.nibbles_left == 0)
                {
                    chip.state = STATE.BLOCK_HEADER;
                }
                else
                {
                    chip.state = STATE.NIBBLE_MSN;
                }
                break;
            }

            /* if there's a DRQ, fudge the state */
            if (chip.drq != 0)
            {
                chip.post_drq_state  = chip.state;
                chip.post_drq_clocks = chip.clocks_left - 21;
                chip.state           = STATE.DROP_DRQ;
                chip.clocks_left     = 21;
            }
        }