⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tms5220.c

📁 这个是延伸mame的在wince平台下的游戏模拟器的代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********************************************************************************************

     TMS5220 simulator

     Written for MAME by Frank Palazzolo
     With help from Neill Corlett
     Additional tweaking by Aaron Giles

***********************************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "driver.h"
#include "tms5220.h"


/* Pull in the ROM tables */
#include "tms5220r.c"


/* these contain data that describes the 128-bit data FIFO */
#define FIFO_SIZE 16
static unsigned char fifo[FIFO_SIZE];
static int fifo_head;
static int fifo_tail;
static int fifo_count;
static int bits_taken;


/* these contain global status bits */
static int speak_external;
static int talk_status;
static int buffer_low;
static int buffer_empty;
static int irq_pin;

static void (*irq_func)(void);


/* these contain data describing the current and previous voice frames */
static unsigned short old_energy = 0;
static unsigned short old_pitch = 0;
static int old_k[10] = {0,0,0,0,0,0,0,0,0,0};

static unsigned short new_energy = 0;
static unsigned short new_pitch = 0;
static int new_k[10] = {0,0,0,0,0,0,0,0,0,0};


/* these are all used to contain the current state of the sound generation */
static unsigned short current_energy = 0;
static unsigned short current_pitch = 0;
static int current_k[10] = {0,0,0,0,0,0,0,0,0,0};

static unsigned short target_energy = 0;
static unsigned short target_pitch = 0;
static int target_k[10] = {0,0,0,0,0,0,0,0,0,0};

static int interp_count = 0;       /* number of interp periods (0-7) */
static int sample_count = 0;       /* sample number within interp (0-24) */
static int pitch_count = 0;

static int u[11] = {0,0,0,0,0,0,0,0,0,0,0};
static int x[10] = {0,0,0,0,0,0,0,0,0,0};

static int randbit = 0;


/* Static function prototypes */
static void process_command (void);
static int extract_bits (int count);
static int parse_frame (int removeit);
static void check_buffer_low (void);
static void cause_interrupt (void);


/**********************************************************************************************

     tms5220_reset -- resets the TMS5220

***********************************************************************************************/

void tms5220_reset (void)
{
    /* initialize the FIFO */
    memset (fifo, 0, sizeof (fifo));
    fifo_head = fifo_tail = fifo_count = bits_taken = 0;

    /* initialize the chip state */
    speak_external = talk_status = buffer_empty = irq_pin = 0;
    buffer_low = 1;

    /* initialize the energy/pitch/k states */
    old_energy = new_energy = current_energy = target_energy = 0;
    old_pitch = new_pitch = current_pitch = target_pitch = 0;
    memset (old_k, 0, sizeof (old_k));
    memset (new_k, 0, sizeof (new_k));
    memset (current_k, 0, sizeof (current_k));
    memset (target_k, 0, sizeof (target_k));

    /* initialize the sample generators */
    interp_count = sample_count = pitch_count = 0;
    randbit = 0;
    memset (u, 0, sizeof (u));
    memset (x, 0, sizeof (x));

}



/**********************************************************************************************

     tms5220_reset -- reset the TMS5220

***********************************************************************************************/

void tms5220_set_irq (void (*func)(void))
{
    irq_func = func;
}


/**********************************************************************************************

     tms5220_data_write -- handle a write to the TMS5220

***********************************************************************************************/

void tms5220_data_write (int data)
{
    /* add this byte to the FIFO */
    if (fifo_count < FIFO_SIZE)
    {
        fifo[fifo_tail] = data;
        fifo_tail = (fifo_tail + 1) % FIFO_SIZE;
        fifo_count++;

    }

    /* update the buffer low state */
    check_buffer_low ();
}


/**********************************************************************************************

     tms5220_status_read -- read status from the TMS5220

	  From the data sheet:
        bit 0 = TS - Talk Status is active (high) when the VSP is processing speech data.
                Talk Status goes active at the initiation of a Speak command or after nine
                bytes of data are loaded into the FIFO following a Speak External command. It
                goes inactive (low) when the stop code (Energy=1111) is processed, or
                immediately by a buffer empty condition or a reset command.
        bit 1 = BL - Buffer Low is active (high) when the FIFO buffer is more than half empty.
                Buffer Low is set when the "Last-In" byte is shifted down past the half-full
                boundary of the stack. Buffer Low is cleared when data is loaded to the stack
                so that the "Last-In" byte lies above the half-full boundary and becomes the
                ninth data byte of the stack.
        bit 2 = BE - Buffer Empty is active (high) when the FIFO buffer has run out of data
                while executing a Speak External command. Buffer Empty is set when the last bit
                of the "Last-In" byte is shifted out to the Synthesis Section. This causes
                Talk Status to be cleared. Speed is terminated at some abnormal point and the
                Speak External command execution is terminated.

***********************************************************************************************/

int tms5220_status_read (void)
{
    /* clear the interrupt pin */
    irq_pin = 0;

    return (talk_status << 7) | (buffer_low << 6) | (buffer_empty << 5);
}



/**********************************************************************************************

     tms5220_ready_read -- returns the ready state of the TMS5220

***********************************************************************************************/

int tms5220_ready_read (void)
{
    return (fifo_count < FIFO_SIZE-1);
}



/**********************************************************************************************

     tms5220_int_read -- returns the interrupt state of the TMS5220

***********************************************************************************************/

int tms5220_int_read (void)
{
    return irq_pin;
}



/**********************************************************************************************

     tms5220_process -- fill the buffer with a specific number of samples

***********************************************************************************************/

void tms5220_process(signed char *buffer, unsigned int size)
{
    int buf_count=0;
    int i, interp_period;

tryagain:

    /* if we're not speaking, parse commands */
    while (!speak_external && fifo_count > 0)
        process_command ();

    /* if there's nothing to do, bail */
    if (!size)
        return;

    /* if we're empty and still not speaking, fill with nothingness */
    if (!speak_external)
        goto empty;

    /* if we're to speak, but haven't started, wait for the 9th byte */
    if (!talk_status)
    {
        if (fifo_count < 9)
           goto empty;

        /* parse but don't remove the first frame, and set the status to 1 */
        parse_frame (0);
        talk_status = 1;
        buffer_empty = 0;
    }

    /* loop until the buffer is full or we've stopped speaking */
    while ((size > 0) && speak_external)
    {
        int current_val;

        /* if we're ready for a new frame */
        if ((interp_count == 0) && (sample_count == 0))
        {
            /* Parse a new frame */
            if (!parse_frame (1))
                break;

            /* Set old target as new start of frame */
            current_energy = old_energy;
            current_pitch = old_pitch;
            for (i = 0; i < 10; i++)
                current_k[i] = old_k[i];

            /* is this a zero energy frame? */
            if (current_energy == 0)
            {
                /*printf("processing frame: zero energy\n");*/
                target_energy = 0;
                target_pitch = current_pitch;
                for (i = 0; i < 10; i++)
                    target_k[i] = current_k[i];
            }

            /* is this a stop frame? */
            else if (current_energy == (energytable[15] >> 6))
            {
                /*printf("processing frame: stop frame\n");*/
                current_energy = energytable[0] >> 6;
                target_energy = current_energy;
                speak_external = talk_status = 0;
                interp_count = sample_count = pitch_count = 0;

                /* generate an interrupt if necessary */
                cause_interrupt ();

                /* try to fetch commands again */
                goto tryagain;
            }
            else
            {
                /* is this the ramp down frame? */
                if (new_energy == (energytable[15] >> 6))
                {
                    /*printf("processing frame: ramp down\n");*/
                    target_energy = 0;
                    target_pitch = current_pitch;
                    for (i = 0; i < 10; i++)
                        target_k[i] = current_k[i];
                }
                /* Reset the step size */
                else
                {
                    /*printf("processing frame: Normal\n");*/
                    /*printf("*** Energy = %d\n",current_energy);*/
                    /*printf("proc: %d %d\n",last_fbuf_head,fbuf_head);*/

                    target_energy = new_energy;
                    target_pitch = new_pitch;

                    for (i = 0; i < 4; i++)
                        target_k[i] = new_k[i];
                    if (current_pitch == 0)
                        for (i = 4; i < 10; i++)
                        {
                            target_k[i] = current_k[i] = 0;
                        }
                    else
                        for (i = 4; i < 10; i++)
                            target_k[i] = new_k[i];
                }
            }
        }
        else if (interp_count == 0)
        {
            /* Update values based on step values */
            /*printf("\n");*/

            interp_period = sample_count / 25;
            current_energy += (target_energy - current_energy) / interp_coeff[interp_period];
            if (old_pitch != 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -