Ejemplo n.º 1
0
        //#if 0
        //void YM_DELTAT_BRDY_callback(YM_DELTAT *DELTAT)
        //{
        //	logerror("BRDY_callback reached (flag set) !\n");

        //	/* set BRDY bit in status register */
        //	if(DELTAT->status_set_handler)
        //		if(DELTAT->status_change_BRDY_bit)
        //			(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
        //}
        //#endif

        public byte YM_DELTAT_ADPCM_Read(YM_DELTAT DELTAT)
        {
            byte v = 0;

            /* external memory read */
            if ((DELTAT.portstate & 0xe0) == 0x20)
            {
                /* two dummy reads */
                if (DELTAT.memread != 0)
                {
                    DELTAT.now_addr = DELTAT.start << 1;
                    DELTAT.memread--;
                    return(0);
                }


                if (DELTAT.now_addr != (DELTAT.end << 1))
                {
                    v = DELTAT.memory[DELTAT.now_addr >> 1];

                    /*logerror("YM Delta-T memory read  $%08x, v=$%02x\n", DELTAT.now_addr >> 1, v);*/

                    DELTAT.now_addr += 2; /* two nibbles at a time */

                    /* reset BRDY bit in status register, which means we are reading the memory now */
                    if (DELTAT.status_reset_handler != null)
                    {
                        if (DELTAT.status_change_BRDY_bit != 0)
                        {
                            DELTAT.status_reset_handler(DELTAT.status_change_which_chip, DELTAT.status_change_BRDY_bit);
                        }
                    }

                    /* setup a timer that will callback us in 10 master clock cycles for Y8950
                     * in the callback set the BRDY flag to 1 , which means we have another data ready.
                     * For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work.
                     */
                    /* set BRDY bit in status register */
                    if (DELTAT.status_set_handler != null)
                    {
                        if (DELTAT.status_change_BRDY_bit != 0)
                        {
                            DELTAT.status_set_handler(DELTAT.status_change_which_chip, DELTAT.status_change_BRDY_bit);
                        }
                    }
                }
                else
                {
                    /* set EOS bit in status register */
                    if (DELTAT.status_set_handler != null)
                    {
                        if (DELTAT.status_change_EOS_bit != 0)
                        {
                            DELTAT.status_set_handler(DELTAT.status_change_which_chip, DELTAT.status_change_EOS_bit);
                        }
                    }
                }
            }

            return(v);
        }
Ejemplo n.º 2
0
        /* DELTA-T ADPCM write register */
        public void YM_DELTAT_ADPCM_Write(YM_DELTAT DELTAT, int r, int v)
        {
            if (r >= 0x10)
            {
                return;
            }
            DELTAT.reg[DELTAT.regPtr + r] = (byte)v; /* stock data */

            switch (r)
            {
            case 0x00:
                /*
                 * START:
                 *  Accessing *external* memory is started when START bit (D7) is set to "1", so
                 *  you must set all conditions needed for recording/playback before starting.
                 *  If you access *CPU-managed* memory, recording/playback starts after
                 *  read/write of ADPCM data register $08.
                 *
                 * REC:
                 *  0 = ADPCM synthesis (playback)
                 *  1 = ADPCM analysis (record)
                 *
                 * MEMDATA:
                 *  0 = processor (*CPU-managed*) memory (means: using register $08)
                 *  1 = external memory (using start/end/limit registers to access memory: RAM or ROM)
                 *
                 *
                 * SPOFF:
                 *  controls output pin that should disable the speaker while ADPCM analysis
                 *
                 * RESET and REPEAT only work with external memory.
                 *
                 *
                 * some examples:
                 * value:   START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET   meaning:
                 * C8     1      1    0       0       1      0 0 0       Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register
                 * E8     1      1    1       0       1      0 0 0       Analysis (recording) from AUDIO to EXT.MEMORY,       sample rate in PRESCALER register
                 * 80     1      0    0       0       0      0 0 0       Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register
                 * a0     1      0    1       0       0      0 0 0       Synthesis (playing) from EXT.MEMORY to AUDIO,        sample rate in DELTA-N register
                 *
                 * 60     0      1    1       0       0      0 0 0       External memory write via ADPCM data register $08
                 * 20     0      0    1       0       0      0 0 0       External memory read via ADPCM data register $08
                 *
                 */
                /* handle emulation mode */
                if (DELTAT.emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610)
                {
                    v |= 0x20;          /*  YM2610 always uses external memory and doesn't even have memory flag bit. */
                }

                DELTAT.portstate = (byte)(v & (0x80 | 0x40 | 0x20 | 0x10 | 0x01)); /* start, rec, memory mode, repeat flag copy, reset(bit0) */

                if ((DELTAT.portstate & 0x80) != 0)                                /* START,REC,MEMDATA,REPEAT,SPOFF,--,--,RESET */
                {
                    /* set PCM BUSY bit */
                    DELTAT.PCM_BSY = 1;

                    /* start ADPCM */
                    DELTAT.now_step = 0;
                    DELTAT.acc      = 0;
                    DELTAT.prev_acc = 0;
                    DELTAT.adpcml   = 0;
                    DELTAT.adpcmd   = YM_DELTAT_DELTA_DEF;
                    DELTAT.now_data = 0;
                    if (DELTAT.start > DELTAT.end)
                    {
                        logerror("DeltaT-Warning: Start: %06X, End: %06X\n", DELTAT.start, DELTAT.end);
                    }
                }

                if ((DELTAT.portstate & 0x20) != 0)     /* do we access external memory? */
                {
                    DELTAT.now_addr = DELTAT.start << 1;
                    DELTAT.memread  = 2;       /* two dummy reads needed before accesing external memory via register $08*/

                    /* if yes, then let's check if ADPCM memory is mapped and big enough */
                    if (DELTAT.memory == null)
                    {
#if DEBUG
                        logerror("YM Delta-T ADPCM rom not mapped\n");
#endif
                        DELTAT.portstate = 0x00;
                        DELTAT.PCM_BSY   = 0;
                    }
                    else
                    {
                        if (DELTAT.end >= DELTAT.memory_size)     /* Check End in Range */
                        {
#if DEBUG
                            logerror("YM Delta-T ADPCM end out of range: $%08x\n", DELTAT.end);
#endif
                            DELTAT.end = DELTAT.memory_size - 1;
                        }
                        if (DELTAT.start >= DELTAT.memory_size)       /* Check Start in Range */
                        {
#if DEBUG
                            logerror("YM Delta-T ADPCM start out of range: $%08x\n", DELTAT.start);
#endif
                            DELTAT.portstate = 0x00;
                            DELTAT.PCM_BSY   = 0;
                        }
                    }
                }
                else        /* we access CPU memory (ADPCM data register $08) so we only reset now_addr here */
                {
                    DELTAT.now_addr = 0;
                }

                if ((DELTAT.portstate & 0x01) != 0)
                {
                    DELTAT.portstate = 0x00;

                    /* clear PCM BUSY bit (in status register) */
                    DELTAT.PCM_BSY = 0;

                    /* set BRDY flag */
                    if (DELTAT.status_set_handler != null)
                    {
                        if (DELTAT.status_change_BRDY_bit != 0)
                        {
                            DELTAT.status_set_handler(DELTAT.status_change_which_chip, DELTAT.status_change_BRDY_bit);
                        }
                    }
                }
                break;

            case 0x01:      /* L,R,-,-,SAMPLE,DA/AD,RAMTYPE,ROM */
                /* handle emulation mode */
                if (DELTAT.emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610)
                {
                    v |= 0x01;          /*  YM2610 always uses ROM as an external memory and doesn't have ROM/RAM memory flag bit. */
                }

                DELTAT.pan    = DELTAT.output_pointer;
                DELTAT.panPtr = (v >> 6) & 0x03;
                if ((DELTAT.control2 & 3) != (v & 3))
                {
                    /*0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */
                    if (DELTAT.DRAMportshift != dram_rightshift[v & 3])
                    {
                        DELTAT.DRAMportshift = dram_rightshift[v & 3];

                        /* final shift value depends on chip type and memory type selected:
                         *      8 for YM2610 (ROM only),
                         *      5 for ROM for Y8950 and YM2608,
                         *      5 for x8bit DRAMs for Y8950 and YM2608,
                         *      2 for x1bit DRAMs for Y8950 and YM2608.
                         */

                        /* refresh addresses */
                        DELTAT.start = (uint)((DELTAT.reg[DELTAT.regPtr + 0x3] * 0x0100 | DELTAT.reg[DELTAT.regPtr + 0x2]) << (DELTAT.portshift - DELTAT.DRAMportshift));
                        DELTAT.end   = (uint)((DELTAT.reg[DELTAT.regPtr + 0x5] * 0x0100 | DELTAT.reg[DELTAT.regPtr + 0x4]) << (DELTAT.portshift - DELTAT.DRAMportshift));
                        DELTAT.end  += (uint)((1 << (DELTAT.portshift - DELTAT.DRAMportshift)) - 1);
                        DELTAT.limit = (uint)((DELTAT.reg[DELTAT.regPtr + 0xd] * 0x0100 | DELTAT.reg[DELTAT.regPtr + 0xc]) << (DELTAT.portshift - DELTAT.DRAMportshift));
                    }
                }
                DELTAT.control2 = (byte)v;
                break;

            case 0x02:      /* Start Address L */
            case 0x03:      /* Start Address H */
                DELTAT.start = (uint)((DELTAT.reg[DELTAT.regPtr + 0x3] * 0x0100 | DELTAT.reg[DELTAT.regPtr + 0x2]) << (DELTAT.portshift - DELTAT.DRAMportshift));
                /*logerror("DELTAT start: 02=%2x 03=%2x addr=%8x\n",DELTAT.reg[0x2], DELTAT.reg[0x3],DELTAT.start );*/
                break;

            case 0x04:      /* Stop Address L */
            case 0x05:      /* Stop Address H */
                DELTAT.end  = (uint)((DELTAT.reg[DELTAT.regPtr + 0x5] * 0x0100 | DELTAT.reg[DELTAT.regPtr + 0x4]) << (DELTAT.portshift - DELTAT.DRAMportshift));
                DELTAT.end += (uint)((1 << (DELTAT.portshift - DELTAT.DRAMportshift)) - 1);
                /*logerror("DELTAT end  : 04=%2x 05=%2x addr=%8x\n",DELTAT.reg[0x4], DELTAT.reg[0x5],DELTAT.end   );*/
                break;

            case 0x06:      /* Prescale L (ADPCM and Record frq) */
            case 0x07:      /* Prescale H */
                break;

            case 0x08:      /* ADPCM data */

                /*
                 * some examples:
                 * value:   START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET   meaning:
                 * C8     1      1    0       0       1      0 0 0       Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register
                 * E8     1      1    1       0       1      0 0 0       Analysis (recording) from AUDIO to EXT.MEMORY,       sample rate in PRESCALER register
                 * 80     1      0    0       0       0      0 0 0       Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register
                 * a0     1      0    1       0       0      0 0 0       Synthesis (playing) from EXT.MEMORY to AUDIO,        sample rate in DELTA-N register
                 *
                 * 60     0      1    1       0       0      0 0 0       External memory write via ADPCM data register $08
                 * 20     0      0    1       0       0      0 0 0       External memory read via ADPCM data register $08
                 *
                 */

                /* external memory write */
                if ((DELTAT.portstate & 0xe0) == 0x60)
                {
                    if (DELTAT.memread != 0)
                    {
                        DELTAT.now_addr = DELTAT.start << 1;
                        DELTAT.memread  = 0;
                    }

                    /*logerror("YM Delta-T memory write $%08x, v=$%02x\n", DELTAT.now_addr >> 1, v);*/

                    if (DELTAT.now_addr != (DELTAT.end << 1))
                    {
                        DELTAT.memory[DELTAT.now_addr >> 1] = (byte)v;
                        DELTAT.now_addr += 2;     /* two nibbles at a time */

                        /* reset BRDY bit in status register, which means we are processing the write */
                        if (DELTAT.status_reset_handler != null)
                        {
                            if (DELTAT.status_change_BRDY_bit != 0)
                            {
                                DELTAT.status_reset_handler(DELTAT.status_change_which_chip, DELTAT.status_change_BRDY_bit);
                            }
                        }

                        /* setup a timer that will callback us in 10 master clock cycles for Y8950
                         * in the callback set the BRDY flag to 1 , which means we have written the data.
                         * For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work.
                         */
                        /* set BRDY bit in status register */
                        if (DELTAT.status_set_handler != null)
                        {
                            if (DELTAT.status_change_BRDY_bit != 0)
                            {
                                DELTAT.status_set_handler(DELTAT.status_change_which_chip, DELTAT.status_change_BRDY_bit);
                            }
                        }
                    }
                    else
                    {
                        /* set EOS bit in status register */
                        if (DELTAT.status_set_handler != null)
                        {
                            if (DELTAT.status_change_EOS_bit != 0)
                            {
                                DELTAT.status_set_handler(DELTAT.status_change_which_chip, DELTAT.status_change_EOS_bit);
                            }
                        }
                    }

                    return;
                }

                /* ADPCM synthesis from CPU */
                if ((DELTAT.portstate & 0xe0) == 0x80)
                {
                    DELTAT.CPU_data = (byte)v;

                    /* Reset BRDY bit in status register, which means we are full of data */
                    if (DELTAT.status_reset_handler != null)
                    {
                        if (DELTAT.status_change_BRDY_bit != 0)
                        {
                            DELTAT.status_reset_handler(DELTAT.status_change_which_chip, DELTAT.status_change_BRDY_bit);
                        }
                    }
                    return;
                }

                break;

            case 0x09:      /* DELTA-N L (ADPCM Playback Prescaler) */
            case 0x0a:      /* DELTA-N H */
                DELTAT.delta = (uint)(DELTAT.reg[DELTAT.regPtr + 0xa] * 0x0100 | DELTAT.reg[DELTAT.regPtr + 0x9]);
                DELTAT.step  = (uint)((double)(DELTAT.delta /* *(1<<(YM_DELTAT_SHIFT-16)) */) * (DELTAT.freqbase));
                /*logerror("DELTAT deltan:09=%2x 0a=%2x\n",DELTAT.reg[0x9], DELTAT.reg[0xa]);*/
                break;

            case 0x0b:      /* Output level control (volume, linear) */
            {
                int oldvol = DELTAT.volume;
                DELTAT.volume = (v & 0xff) * (DELTAT.output_range / 256) / YM_DELTAT_DECODE_RANGE;

                /*                              v     *     ((1<<16)>>8)        >>  15;
                 *                       thus:   v     *     (1<<8)              >>  15;
                 *                       thus: output_range must be (1 << (15+8)) at least
                 *                               v     *     ((1<<23)>>8)        >>  15;
                 *                               v     *     (1<<15)             >>  15;
                 */
                /*logerror("DELTAT vol = %2x\n",v&0xff);*/
                if (oldvol != 0)
                {
                    DELTAT.adpcml = (int)((double)DELTAT.adpcml / (double)oldvol * (double)DELTAT.volume);
                }
            }
            break;

            case 0x0c:      /* Limit Address L */
            case 0x0d:      /* Limit Address H */
                DELTAT.limit = (uint)((DELTAT.reg[DELTAT.regPtr + 0xd] * 0x0100 | DELTAT.reg[DELTAT.regPtr + 0xc]) << (DELTAT.portshift - DELTAT.DRAMportshift));
                /*logerror("DELTAT limit: 0c=%2x 0d=%2x addr=%8x\n",DELTAT.reg[0xc], DELTAT.reg[0xd],DELTAT.limit );*/
                break;
            }
        }
Ejemplo n.º 3
0
        public static void YM_DELTAT_ADPCM_Write(int r, byte v)
        {
            if (r >= 0x10)
            {
                return;
            }
            DELTAT.reg[r] = v;
            switch (r)
            {
            case 0x00:
                if (DELTAT.emulation_mode == 1)
                {
                    v |= 0x20;
                }
                DELTAT.portstate = (byte)(v & (0x80 | 0x40 | 0x20 | 0x10 | 0x01));
                if ((DELTAT.portstate & 0x80) != 0)
                {
                    DELTAT.PCM_BSY  = 1;
                    DELTAT.now_step = 0;
                    DELTAT.acc      = 0;
                    DELTAT.prev_acc = 0;
                    DELTAT.adpcml   = 0;
                    DELTAT.adpcmd   = YM_DELTAT_DELTA_DEF;
                    DELTAT.now_data = 0;
                }
                if ((DELTAT.portstate & 0x20) != 0)
                {
                    DELTAT.now_addr = DELTAT.start << 1;
                    DELTAT.memread  = 2;
                    if (ymsnddeltatrom == null)
                    {
                        DELTAT.portstate = 0x00;
                        DELTAT.PCM_BSY   = 0;
                    }
                    else
                    {
                        if (DELTAT.end >= DELTAT.memory_size)
                        {
                            DELTAT.end = DELTAT.memory_size - 1;
                        }
                        if (DELTAT.start >= DELTAT.memory_size)
                        {
                            DELTAT.portstate = 0x00;
                            DELTAT.PCM_BSY   = 0;
                        }
                    }
                }
                else
                {
                    DELTAT.now_addr = 0;
                }
                if ((DELTAT.portstate & 0x01) != 0)
                {
                    DELTAT.portstate = 0x00;
                    DELTAT.PCM_BSY   = 0;
                    if (DELTAT.status_set_handler != null)
                    {
                        if (DELTAT.status_change_BRDY_bit != 0)
                        {
                            DELTAT.status_set_handler(DELTAT.status_change_BRDY_bit);
                        }
                    }
                }
                break;

            case 0x01:
                /* handle emulation mode */
                if (DELTAT.emulation_mode == 1)
                {
                    v |= 0x01;
                }
                DELTAT.pan_offset = (v >> 6) & 0x03;
                if ((DELTAT.control2 & 3) != (v & 3))
                {
                    if (DELTAT.DRAMportshift != dram_rightshift[v & 3])
                    {
                        DELTAT.DRAMportshift = dram_rightshift[v & 3];
                        DELTAT.start         = (DELTAT.reg[0x3] * 0x0100 | DELTAT.reg[0x2]) << (DELTAT.portshift - DELTAT.DRAMportshift);
                        DELTAT.end           = (DELTAT.reg[0x5] * 0x0100 | DELTAT.reg[0x4]) << (DELTAT.portshift - DELTAT.DRAMportshift);
                        DELTAT.end          += (1 << (DELTAT.portshift - DELTAT.DRAMportshift)) - 1;
                        DELTAT.limit         = (DELTAT.reg[0xd] * 0x0100 | DELTAT.reg[0xc]) << (DELTAT.portshift - DELTAT.DRAMportshift);
                    }
                }
                DELTAT.control2 = v;
                break;

            case 0x02:
            case 0x03:
                DELTAT.start = (DELTAT.reg[0x3] * 0x0100 | DELTAT.reg[0x2]) << (DELTAT.portshift - DELTAT.DRAMportshift);
                break;

            case 0x04:
            case 0x05:
                DELTAT.end  = (DELTAT.reg[0x5] * 0x0100 | DELTAT.reg[0x4]) << (DELTAT.portshift - DELTAT.DRAMportshift);
                DELTAT.end += (1 << (DELTAT.portshift - DELTAT.DRAMportshift)) - 1;
                break;

            case 0x06:
            case 0x07:
                break;

            case 0x08:
                if ((DELTAT.portstate & 0xe0) == 0x60)
                {
                    if (DELTAT.memread != 0)
                    {
                        DELTAT.now_addr = DELTAT.start << 1;
                        DELTAT.memread  = 0;
                    }
                    if (DELTAT.now_addr != (DELTAT.end << 1))
                    {
                        ymsnddeltatrom[DELTAT.now_addr >> 1] = v;
                        DELTAT.now_addr += 2;
                        if (DELTAT.status_reset_handler != null)
                        {
                            if (DELTAT.status_change_BRDY_bit != 0)
                            {
                                DELTAT.status_reset_handler(DELTAT.status_change_BRDY_bit);
                            }
                        }
                        if (DELTAT.status_set_handler != null)
                        {
                            if (DELTAT.status_change_BRDY_bit != 0)
                            {
                                DELTAT.status_set_handler(DELTAT.status_change_BRDY_bit);
                            }
                        }
                    }
                    else
                    {
                        if (DELTAT.status_set_handler != null)
                        {
                            if (DELTAT.status_change_EOS_bit != 0)
                            {
                                DELTAT.status_set_handler(DELTAT.status_change_EOS_bit);
                            }
                        }
                    }
                    return;
                }
                if ((DELTAT.portstate & 0xe0) == 0x80)
                {
                    DELTAT.CPU_data = v;
                    if (DELTAT.status_reset_handler != null)
                    {
                        if (DELTAT.status_change_BRDY_bit != 0)
                        {
                            DELTAT.status_reset_handler(DELTAT.status_change_BRDY_bit);
                        }
                    }
                    return;
                }
                break;

            case 0x09:
            case 0x0a:
                DELTAT.delta = (DELTAT.reg[0xa] * 0x0100 | DELTAT.reg[0x9]);
                DELTAT.step  = (int)(DELTAT.delta * DELTAT.freqbase);
                break;

            case 0x0b:
            {
                int oldvol = DELTAT.volume;
                DELTAT.volume = (v & 0xff) * (DELTAT.output_range / 256) / YM_DELTAT_DECODE_RANGE;
                if (oldvol != 0)
                {
                    DELTAT.adpcml = (int)((double)DELTAT.adpcml / (double)oldvol * (double)DELTAT.volume);
                }
            }
            break;

            case 0x0c:
            case 0x0d:
                DELTAT.limit = (DELTAT.reg[0xd] * 0x0100 | DELTAT.reg[0xc]) << (DELTAT.portshift - DELTAT.DRAMportshift);
                break;
            }
        }