147 lines
2.7 KiB
C
147 lines
2.7 KiB
C
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <wchar.h>
|
|
|
|
#include "cpu.h"
|
|
#include <86box/86box.h>
|
|
#include <86box/filters.h>
|
|
#include <86box/lpt.h>
|
|
#include <86box/machine.h>
|
|
#include <86box/sound.h>
|
|
#include <86box/timer.h>
|
|
#include <86box/plat_unused.h>
|
|
|
|
typedef struct dss_t {
|
|
void *lpt;
|
|
|
|
uint8_t fifo[16];
|
|
int read_idx;
|
|
int write_idx;
|
|
|
|
uint8_t dac_val;
|
|
uint8_t status;
|
|
|
|
pc_timer_t timer;
|
|
|
|
int16_t buffer[SOUNDBUFLEN];
|
|
int pos;
|
|
} dss_t;
|
|
|
|
static void
|
|
dss_update(dss_t *dss)
|
|
{
|
|
for (; dss->pos < sound_pos_global; dss->pos++)
|
|
dss->buffer[dss->pos] = (int8_t) (dss->dac_val ^ 0x80) * 0x40;
|
|
}
|
|
|
|
static void
|
|
dss_update_status(dss_t *dss)
|
|
{
|
|
uint8_t old = dss->status;
|
|
|
|
dss->status &= ~0x40;
|
|
|
|
if ((dss->write_idx - dss->read_idx) >= 16)
|
|
dss->status |= 0x40;
|
|
|
|
if ((old & 0x40) && !(dss->status & 0x40))
|
|
lpt_irq(dss->lpt, 1);
|
|
}
|
|
|
|
static void
|
|
dss_write_data(uint8_t val, void *priv)
|
|
{
|
|
dss_t *dss = (dss_t *) priv;
|
|
|
|
if ((dss->write_idx - dss->read_idx) < 16) {
|
|
dss->fifo[dss->write_idx & 15] = val;
|
|
dss->write_idx++;
|
|
dss_update_status(dss);
|
|
}
|
|
}
|
|
|
|
static void
|
|
dss_write_ctrl(UNUSED(uint8_t val), UNUSED(void *priv))
|
|
{
|
|
//
|
|
}
|
|
|
|
static uint8_t
|
|
dss_read_status(void *priv)
|
|
{
|
|
const dss_t *dss = (dss_t *) priv;
|
|
|
|
return dss->status | 0x0f;
|
|
}
|
|
|
|
static void
|
|
dss_get_buffer(int32_t *buffer, int len, void *priv)
|
|
{
|
|
dss_t *dss = (dss_t *) priv;
|
|
int16_t val;
|
|
float fval;
|
|
|
|
dss_update(dss);
|
|
|
|
for (int c = 0; c < len * 2; c += 2) {
|
|
fval = dss_iir((float) dss->buffer[c >> 1]);
|
|
val = fval;
|
|
|
|
buffer[c] += val;
|
|
buffer[c + 1] += val;
|
|
}
|
|
|
|
dss->pos = 0;
|
|
}
|
|
|
|
static void
|
|
dss_callback(void *priv)
|
|
{
|
|
dss_t *dss = (dss_t *) priv;
|
|
|
|
dss_update(dss);
|
|
|
|
if ((dss->write_idx - dss->read_idx) > 0) {
|
|
dss->dac_val = dss->fifo[dss->read_idx & 15];
|
|
dss->read_idx++;
|
|
dss_update_status(dss);
|
|
}
|
|
|
|
timer_advance_u64(&dss->timer, (TIMER_USEC * (1000000.0 / 7000.0)));
|
|
}
|
|
|
|
static void *
|
|
dss_init(void *lpt)
|
|
{
|
|
dss_t *dss = malloc(sizeof(dss_t));
|
|
memset(dss, 0, sizeof(dss_t));
|
|
|
|
dss->lpt = lpt;
|
|
|
|
sound_add_handler(dss_get_buffer, dss);
|
|
timer_add(&dss->timer, dss_callback, dss, 1);
|
|
|
|
return dss;
|
|
}
|
|
static void
|
|
dss_close(void *priv)
|
|
{
|
|
dss_t *dss = (dss_t *) priv;
|
|
|
|
free(dss);
|
|
}
|
|
|
|
const lpt_device_t dss_device = {
|
|
.name = "Disney Sound Source",
|
|
.internal_name = "dss",
|
|
.init = dss_init,
|
|
.close = dss_close,
|
|
.write_data = dss_write_data,
|
|
.write_ctrl = dss_write_ctrl,
|
|
.read_data = NULL,
|
|
.read_status = dss_read_status,
|
|
.read_ctrl = NULL
|
|
};
|