WIP: PAS16.
See above, currently very WIP.
This commit is contained in:
@@ -42,6 +42,7 @@ typedef struct ctr_t {
|
||||
int state;
|
||||
int null_count;
|
||||
int do_read_status;
|
||||
int enable;
|
||||
|
||||
union {
|
||||
int32_t count;
|
||||
@@ -57,7 +58,7 @@ typedef struct ctr_t {
|
||||
uint32_t l;
|
||||
|
||||
void (*load_func)(uint8_t new_m, int new_count);
|
||||
void (*out_func)(int new_out, int old_out);
|
||||
void (*out_func)(int new_out, int old_out, void *priv);
|
||||
} ctr_t;
|
||||
|
||||
typedef struct PIT {
|
||||
@@ -68,8 +69,12 @@ typedef struct PIT {
|
||||
ctr_t counters[3];
|
||||
|
||||
uint8_t ctrl;
|
||||
void *dev_priv;
|
||||
void (*dev_timer)(void *priv);
|
||||
} pit_t;
|
||||
|
||||
extern pit_t *ext_pit;
|
||||
|
||||
enum {
|
||||
PIT_8253 = 0,
|
||||
PIT_8254 = 1,
|
||||
@@ -87,7 +92,7 @@ typedef struct pit_intf_t {
|
||||
/* Sets if a counter's CLOCK input is from the timer or not - used by PCjr. */
|
||||
void (*set_using_timer)(void *data, int counter_id, int using_timer);
|
||||
/* Sets a counter's OUT output handler. */
|
||||
void (*set_out_func)(void *data, int counter_id, void (*func)(int new_out, int old_out));
|
||||
void (*set_out_func)(void *data, int counter_id, void (*func)(int new_out, int old_out, void *priv));
|
||||
/* Sets a counter's load count handler. */
|
||||
void (*set_load_func)(void *data, int counter_id, void (*func)(uint8_t new_m, int new_count));
|
||||
void (*ctr_clock)(void *data, int counter_id);
|
||||
@@ -113,20 +118,24 @@ extern uint64_t RTCCONST;
|
||||
extern int refresh_at_enable;
|
||||
|
||||
/* Sets a counter's CLOCK input. */
|
||||
extern void pit_ctr_set_clock(ctr_t *ctr, int clock);
|
||||
extern void pit_ctr_set_clock(ctr_t *ctr, int clock, void *priv);
|
||||
|
||||
extern pit_t *pit_common_init(int type, void (*out0)(int new_out, int old_out), void (*out1)(int new_out, int old_out));
|
||||
extern void pit_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out, void *priv));
|
||||
|
||||
extern void pit_ctr_set_using_timer(void *data, int counter_id, int using_timer);
|
||||
|
||||
extern pit_t *pit_common_init(int type, void (*out0)(int new_out, int old_out, void *priv), void (*out1)(int new_out, int old_out, void *priv));
|
||||
extern pit_t *pit_ps2_init(int type);
|
||||
extern void pit_reset(pit_t *dev);
|
||||
|
||||
extern void pit_irq0_timer_ps2(int new_out, int old_out);
|
||||
extern void pit_irq0_timer_ps2(int new_out, int old_out, void *priv);
|
||||
|
||||
extern void pit_refresh_timer_xt(int new_out, int old_out);
|
||||
extern void pit_refresh_timer_at(int new_out, int old_out);
|
||||
extern void pit_refresh_timer_xt(int new_out, int old_out, void *priv);
|
||||
extern void pit_refresh_timer_at(int new_out, int old_out, void *priv);
|
||||
|
||||
extern void pit_speaker_timer(int new_out, int old_out);
|
||||
extern void pit_speaker_timer(int new_out, int old_out, void *priv);
|
||||
|
||||
extern void pit_nmi_timer_ps2(int new_out, int old_out);
|
||||
extern void pit_nmi_timer_ps2(int new_out, int old_out, void *priv);
|
||||
|
||||
extern void pit_set_clock(uint32_t clock);
|
||||
extern void pit_handler(int set, uint16_t base, int size, void *priv);
|
||||
@@ -135,6 +144,7 @@ extern uint8_t pit_read_reg(void *priv, uint8_t reg);
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t i8253_device;
|
||||
extern const device_t i8253_ext_io_device;
|
||||
extern const device_t i8254_device;
|
||||
extern const device_t i8254_sec_device;
|
||||
extern const device_t i8254_ext_io_device;
|
||||
|
@@ -59,7 +59,8 @@ typedef struct ctrf_t {
|
||||
pc_timer_t timer;
|
||||
|
||||
void (*load_func)(uint8_t new_m, int new_count);
|
||||
void (*out_func)(int new_out, int old_out);
|
||||
void (*out_func)(int new_out, int old_out, void *priv);
|
||||
void *priv;
|
||||
} ctrf_t;
|
||||
|
||||
typedef struct pitf_t {
|
||||
|
@@ -123,10 +123,8 @@ extern const device_t cms_device;
|
||||
/* Gravis UltraSound and UltraSound Max */
|
||||
extern const device_t gus_device;
|
||||
|
||||
# if defined(DEV_BRANCH) && defined(USE_PAS16)
|
||||
/* Pro Audio Spectrum 16 */
|
||||
extern const device_t pas16_device;
|
||||
# endif
|
||||
|
||||
/* IBM PS/1 Audio Card */
|
||||
extern const device_t ps1snd_device;
|
||||
|
117
src/pit.c
117
src/pit.c
@@ -94,13 +94,15 @@ pit_log(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
ctr_set_out(ctr_t *ctr, int out)
|
||||
ctr_set_out(ctr_t *ctr, int out, void *priv)
|
||||
{
|
||||
pit_t *pit = (pit_t *)priv;
|
||||
|
||||
if (ctr == NULL)
|
||||
return;
|
||||
|
||||
if (ctr->out_func != NULL)
|
||||
ctr->out_func(out, ctr->out);
|
||||
ctr->out_func(out, ctr->out, pit);
|
||||
ctr->out = out;
|
||||
}
|
||||
|
||||
@@ -146,8 +148,9 @@ ctr_load_count(ctr_t *ctr)
|
||||
}
|
||||
|
||||
static void
|
||||
ctr_tick(ctr_t *ctr)
|
||||
ctr_tick(ctr_t *ctr, void *priv)
|
||||
{
|
||||
pit_t *pit = (pit_t *)priv;
|
||||
uint8_t state = ctr->state;
|
||||
|
||||
if ((state & 0x03) == 0x01) {
|
||||
@@ -155,7 +158,7 @@ ctr_tick(ctr_t *ctr)
|
||||
ctr_load_count(ctr);
|
||||
ctr->state++;
|
||||
if (((ctr->m & 0x07) == 0x01) && (ctr->state == 2))
|
||||
ctr_set_out(ctr, 0);
|
||||
ctr_set_out(ctr, 0, pit);
|
||||
} else switch (ctr->m & 0x07) {
|
||||
case 0:
|
||||
/* Interrupt on terminal count */
|
||||
@@ -165,7 +168,7 @@ ctr_tick(ctr_t *ctr)
|
||||
ctr_decrease_count(ctr);
|
||||
if (ctr->count < 1) {
|
||||
ctr->state = 3;
|
||||
ctr_set_out(ctr, 1);
|
||||
ctr_set_out(ctr, 1, pit);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -185,7 +188,7 @@ ctr_tick(ctr_t *ctr)
|
||||
ctr_decrease_count(ctr);
|
||||
if (ctr->count < 1) {
|
||||
ctr->state = 3;
|
||||
ctr_set_out(ctr, 1);
|
||||
ctr_set_out(ctr, 1, pit);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -205,7 +208,7 @@ ctr_tick(ctr_t *ctr)
|
||||
case 3:
|
||||
ctr_load_count(ctr);
|
||||
ctr->state = 2;
|
||||
ctr_set_out(ctr, 1);
|
||||
ctr_set_out(ctr, 1, pit);
|
||||
break;
|
||||
case 2:
|
||||
if (ctr->gate == 0)
|
||||
@@ -214,7 +217,7 @@ ctr_tick(ctr_t *ctr)
|
||||
ctr_decrease_count(ctr);
|
||||
if (ctr->count < 2) {
|
||||
ctr->state = 3;
|
||||
ctr_set_out(ctr, 0);
|
||||
ctr_set_out(ctr, 0, pit);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -240,7 +243,7 @@ ctr_tick(ctr_t *ctr)
|
||||
if (ctr->count < 0) {
|
||||
ctr_load_count(ctr);
|
||||
ctr->state = 3;
|
||||
ctr_set_out(ctr, 0);
|
||||
ctr_set_out(ctr, 0, pit);
|
||||
} else if (ctr->newcount)
|
||||
ctr->newcount = 0;
|
||||
}
|
||||
@@ -259,7 +262,7 @@ ctr_tick(ctr_t *ctr)
|
||||
if (ctr->count < 0) {
|
||||
ctr_load_count(ctr);
|
||||
ctr->state = 2;
|
||||
ctr_set_out(ctr, 1);
|
||||
ctr_set_out(ctr, 1, pit);
|
||||
} else if (ctr->newcount)
|
||||
ctr->newcount = 0;
|
||||
}
|
||||
@@ -284,13 +287,13 @@ ctr_tick(ctr_t *ctr)
|
||||
ctr_decrease_count(ctr);
|
||||
if (ctr->count < 1) {
|
||||
ctr->state = 3;
|
||||
ctr_set_out(ctr, 0);
|
||||
ctr_set_out(ctr, 0, pit);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
ctr->state = 0;
|
||||
ctr_set_out(ctr, 1);
|
||||
ctr_set_out(ctr, 1, pit);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -316,7 +319,7 @@ ctr_clock(void *data, int counter_id)
|
||||
if (ctr->using_timer)
|
||||
return;
|
||||
|
||||
ctr_tick(ctr);
|
||||
ctr_tick(ctr, pit);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -351,7 +354,7 @@ ctr_load(ctr_t *ctr)
|
||||
if (ctr->load_func != NULL)
|
||||
ctr->load_func(ctr->m, ctr->l ? ctr->l : 0x10000);
|
||||
|
||||
pit_log("Counter loaded, state = %i, gate = %i\n", ctr->state, ctr->gate);
|
||||
pclog("Counter loaded, state = %i, gate = %i, latch = %i\n", ctr->state, ctr->gate, ctr->latch);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
@@ -390,7 +393,7 @@ ctr_latch_count(ctr_t *ctr)
|
||||
break;
|
||||
}
|
||||
|
||||
pit_log("latched counter = %04X\n", ctr->rl & 0xffff);
|
||||
pclog("rm = %x, latched counter = %04X\n", ctr->rm & 0x03, ctr->rl & 0xffff);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
@@ -415,7 +418,7 @@ pit_ctr_set_load_func(void *data, int counter_id, void (*func)(uint8_t new_m, in
|
||||
}
|
||||
|
||||
void
|
||||
pit_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out))
|
||||
pit_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out, void *priv))
|
||||
{
|
||||
if (data == NULL)
|
||||
return;
|
||||
@@ -448,14 +451,14 @@ pit_ctr_set_gate(void *data, int counter_id, int gate)
|
||||
/* Here we handle the rising edges. */
|
||||
if (mode & 1) {
|
||||
if (mode != 1)
|
||||
ctr_set_out(ctr, 1);
|
||||
ctr_set_out(ctr, 1, pit);
|
||||
ctr->state = 1;
|
||||
} else if (mode == 2)
|
||||
ctr->state = 3;
|
||||
} else if (old && !gate) {
|
||||
/* Here we handle the lowering edges. */
|
||||
if (mode & 2)
|
||||
ctr_set_out(ctr, 1);
|
||||
ctr_set_out(ctr, 1, pit);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -465,8 +468,9 @@ pit_ctr_set_gate(void *data, int counter_id, int gate)
|
||||
}
|
||||
|
||||
static __inline void
|
||||
pit_ctr_set_clock_common(ctr_t *ctr, int clock)
|
||||
pit_ctr_set_clock_common(ctr_t *ctr, int clock, void *priv)
|
||||
{
|
||||
pit_t *pit = (pit_t *)priv;
|
||||
int old = ctr->clock;
|
||||
|
||||
ctr->clock = clock;
|
||||
@@ -484,18 +488,18 @@ pit_ctr_set_clock_common(ctr_t *ctr, int clock)
|
||||
ctr->s1_det++; /* Falling edge. */
|
||||
if (ctr->s1_det >= 2) {
|
||||
ctr->s1_det = 0;
|
||||
ctr_tick(ctr);
|
||||
ctr_tick(ctr, pit);
|
||||
}
|
||||
}
|
||||
} else if (old && !ctr->clock)
|
||||
ctr_tick(ctr);
|
||||
ctr_tick(ctr, pit);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pit_ctr_set_clock(ctr_t *ctr, int clock)
|
||||
pit_ctr_set_clock(ctr_t *ctr, int clock, void *priv)
|
||||
{
|
||||
pit_ctr_set_clock_common(ctr, clock);
|
||||
pit_ctr_set_clock_common(ctr, clock, priv);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -516,7 +520,10 @@ pit_timer_over(void *priv)
|
||||
dev->clock ^= 1;
|
||||
|
||||
for (uint8_t i = 0; i < 3; i++)
|
||||
pit_ctr_set_clock_common(&dev->counters[i], dev->clock);
|
||||
pit_ctr_set_clock_common(&dev->counters[i], dev->clock, dev);
|
||||
|
||||
if (dev->dev_timer != NULL)
|
||||
dev->dev_timer(dev);
|
||||
|
||||
timer_advance_u64(&dev->callback_timer, PITCONST >> 1ULL);
|
||||
}
|
||||
@@ -528,7 +535,8 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
|
||||
int t = (addr & 3);
|
||||
ctr_t *ctr;
|
||||
|
||||
pit_log("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv);
|
||||
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
|
||||
pclog("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv);
|
||||
|
||||
switch (addr & 3) {
|
||||
case 3: /* control */
|
||||
@@ -544,7 +552,8 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
|
||||
ctr_latch_count(&dev->counters[1]);
|
||||
if (val & 8)
|
||||
ctr_latch_count(&dev->counters[2]);
|
||||
pit_log("PIT %i: Initiated readback command\n", t);
|
||||
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
|
||||
pclog("PIT %i: Initiated readback command\n", t);
|
||||
}
|
||||
if (!(val & 0x10)) {
|
||||
if (val & 2)
|
||||
@@ -561,7 +570,8 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
if (!(dev->ctrl & 0x30)) {
|
||||
ctr_latch_count(ctr);
|
||||
pit_log("PIT %i: Initiated latched read, %i bytes latched\n",
|
||||
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
|
||||
pclog("PIT %i: Initiated latched read, %i bytes latched\n",
|
||||
t, ctr->latched);
|
||||
} else {
|
||||
ctr->ctrl = val;
|
||||
@@ -571,14 +581,16 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
|
||||
ctr->m &= 3;
|
||||
ctr->null_count = 1;
|
||||
ctr->bcd = (ctr->ctrl & 0x01);
|
||||
ctr_set_out(ctr, !!ctr->m);
|
||||
ctr_set_out(ctr, !!ctr->m, dev);
|
||||
ctr->state = 0;
|
||||
if (ctr->latched) {
|
||||
pit_log("PIT %i: Reload while counter is latched\n", t);
|
||||
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
|
||||
pclog("PIT %i: Reload while counter is latched\n", t);
|
||||
ctr->rl--;
|
||||
}
|
||||
|
||||
pit_log("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out);
|
||||
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
|
||||
pclog("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -595,30 +607,31 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 1:
|
||||
ctr->l = val;
|
||||
if (ctr->m == 0)
|
||||
ctr_set_out(ctr, 0);
|
||||
ctr_set_out(ctr, 0, dev);
|
||||
ctr_load(ctr);
|
||||
break;
|
||||
case 2:
|
||||
ctr->l = (val << 8);
|
||||
if (ctr->m == 0)
|
||||
ctr_set_out(ctr, 0);
|
||||
ctr_set_out(ctr, 0, dev);
|
||||
ctr_load(ctr);
|
||||
break;
|
||||
case 3:
|
||||
case 0x83:
|
||||
if (ctr->wm & 0x80) {
|
||||
ctr->l = (ctr->l & 0x00ff) | (val << 8);
|
||||
pit_log("PIT %i: Written high byte %02X, latch now %04X\n", t, val, ctr->l);
|
||||
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
|
||||
pclog("PIT %i: Written high byte %02X, latch now %04X\n", t, val, ctr->l);
|
||||
ctr_load(ctr);
|
||||
} else {
|
||||
ctr->l = (ctr->l & 0xff00) | val;
|
||||
pit_log("PIT %i: Written low byte %02X, latch now %04X\n", t, val, ctr->l);
|
||||
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
|
||||
pclog("PIT %i: Written low byte %02X, latch now %04X\n", t, val, ctr->l);
|
||||
if (ctr->m == 0) {
|
||||
ctr->state = 0;
|
||||
ctr_set_out(ctr, 0);
|
||||
ctr_set_out(ctr, 0, dev);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctr->wm & 0x80)
|
||||
ctr->wm &= ~0x80;
|
||||
else
|
||||
@@ -749,13 +762,14 @@ pit_read(uint16_t addr, void *priv)
|
||||
break;
|
||||
}
|
||||
|
||||
pit_log("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret);
|
||||
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
|
||||
pclog("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
pit_irq0_timer_ps2(int new_out, int old_out)
|
||||
pit_irq0_timer_ps2(int new_out, int old_out, UNUSED(void *priv))
|
||||
{
|
||||
if (new_out && !old_out) {
|
||||
picint(1);
|
||||
@@ -770,21 +784,21 @@ pit_irq0_timer_ps2(int new_out, int old_out)
|
||||
}
|
||||
|
||||
void
|
||||
pit_refresh_timer_xt(int new_out, int old_out)
|
||||
pit_refresh_timer_xt(int new_out, int old_out, UNUSED(void *priv))
|
||||
{
|
||||
if (new_out && !old_out)
|
||||
dma_channel_read(0);
|
||||
}
|
||||
|
||||
void
|
||||
pit_refresh_timer_at(int new_out, int old_out)
|
||||
pit_refresh_timer_at(int new_out, int old_out, UNUSED(void *priv))
|
||||
{
|
||||
if (refresh_at_enable && new_out && !old_out)
|
||||
ppi.pb ^= 0x10;
|
||||
}
|
||||
|
||||
void
|
||||
pit_speaker_timer(int new_out, UNUSED(int old_out))
|
||||
pit_speaker_timer(int new_out, UNUSED(int old_out), UNUSED(void *priv))
|
||||
{
|
||||
int l;
|
||||
|
||||
@@ -804,7 +818,7 @@ pit_speaker_timer(int new_out, UNUSED(int old_out))
|
||||
}
|
||||
|
||||
void
|
||||
pit_nmi_timer_ps2(int new_out, UNUSED(int old_out))
|
||||
pit_nmi_timer_ps2(int new_out, UNUSED(int old_out), UNUSED(void *priv))
|
||||
{
|
||||
nmi = new_out;
|
||||
|
||||
@@ -882,6 +896,9 @@ pit_init(const device_t *info)
|
||||
pit_read, NULL, NULL, pit_write, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
dev->dev_priv = NULL;
|
||||
dev->dev_timer = NULL;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
@@ -899,6 +916,20 @@ const device_t i8253_device = {
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t i8253_ext_io_device = {
|
||||
.name = "Intel 8253 Programmable Interval Timer (External I/O)",
|
||||
.internal_name = "i8253_ext_io",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = PIT_8253 | PIT_EXT_IO,
|
||||
.init = pit_init,
|
||||
.close = pit_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t i8254_device = {
|
||||
.name = "Intel 8254 Programmable Interval Timer",
|
||||
.internal_name = "i8254",
|
||||
@@ -956,7 +987,7 @@ const device_t i8254_ps2_device = {
|
||||
};
|
||||
|
||||
pit_t *
|
||||
pit_common_init(int type, void (*out0)(int new_out, int old_out), void (*out1)(int new_out, int old_out))
|
||||
pit_common_init(int type, void (*out0)(int new_out, int old_out, void *priv), void (*out1)(int new_out, int old_out, void *priv))
|
||||
{
|
||||
void *pit;
|
||||
|
||||
|
@@ -66,13 +66,15 @@ pit_log(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
pitf_ctr_set_out(ctrf_t *ctr, int out)
|
||||
pitf_ctr_set_out(ctrf_t *ctr, int out, void *priv)
|
||||
{
|
||||
pitf_t *pit = (pitf_t *)priv;
|
||||
|
||||
if (ctr == NULL)
|
||||
return;
|
||||
|
||||
if (ctr->out_func != NULL)
|
||||
ctr->out_func(out, ctr->out);
|
||||
ctr->out_func(out, ctr->out, pit);
|
||||
ctr->out = out;
|
||||
}
|
||||
|
||||
@@ -98,7 +100,7 @@ pitf_ctr_get_count(void *data, int counter_id)
|
||||
}
|
||||
|
||||
static void
|
||||
pitf_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out))
|
||||
pitf_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out, void *priv))
|
||||
{
|
||||
if (data == NULL)
|
||||
return;
|
||||
@@ -154,8 +156,9 @@ pitf_dump_and_disable_timer(ctrf_t *ctr)
|
||||
}
|
||||
|
||||
static void
|
||||
pitf_ctr_load(ctrf_t *ctr)
|
||||
pitf_ctr_load(ctrf_t *ctr, void *priv)
|
||||
{
|
||||
pitf_t *pit = (pitf_t *)priv;
|
||||
int l = ctr->l ? ctr->l : 0x10000;
|
||||
|
||||
ctr->newcount = 0;
|
||||
@@ -166,7 +169,7 @@ pitf_ctr_load(ctrf_t *ctr)
|
||||
ctr->count = l;
|
||||
if (ctr->using_timer)
|
||||
timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST));
|
||||
pitf_ctr_set_out(ctr, 0);
|
||||
pitf_ctr_set_out(ctr, 0, pit);
|
||||
ctr->thit = 0;
|
||||
ctr->enabled = ctr->gate;
|
||||
break;
|
||||
@@ -178,7 +181,7 @@ pitf_ctr_load(ctrf_t *ctr)
|
||||
ctr->count = l - 1;
|
||||
if (ctr->using_timer)
|
||||
timer_set_delay_u64(&ctr->timer, (uint64_t) ((l - 1) * PITCONST));
|
||||
pitf_ctr_set_out(ctr, 1);
|
||||
pitf_ctr_set_out(ctr, 1, pit);
|
||||
ctr->thit = 0;
|
||||
}
|
||||
ctr->enabled = ctr->gate;
|
||||
@@ -188,7 +191,7 @@ pitf_ctr_load(ctrf_t *ctr)
|
||||
ctr->count = l;
|
||||
if (ctr->using_timer)
|
||||
timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST));
|
||||
pitf_ctr_set_out(ctr, 1);
|
||||
pitf_ctr_set_out(ctr, 1, pit);
|
||||
ctr->thit = 0;
|
||||
}
|
||||
ctr->enabled = ctr->gate;
|
||||
@@ -200,7 +203,7 @@ pitf_ctr_load(ctrf_t *ctr)
|
||||
ctr->count = l;
|
||||
if (ctr->using_timer)
|
||||
timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST));
|
||||
pitf_ctr_set_out(ctr, 0);
|
||||
pitf_ctr_set_out(ctr, 0, pit);
|
||||
ctr->thit = 0;
|
||||
}
|
||||
ctr->enabled = ctr->gate;
|
||||
@@ -223,8 +226,9 @@ pitf_ctr_load(ctrf_t *ctr)
|
||||
}
|
||||
|
||||
static void
|
||||
pitf_set_gate_no_timer(ctrf_t *ctr, int gate)
|
||||
pitf_set_gate_no_timer(ctrf_t *ctr, int gate, void *priv)
|
||||
{
|
||||
pitf_t *pit = (pitf_t *)priv;
|
||||
int l = ctr->l ? ctr->l : 0x10000;
|
||||
|
||||
if (ctr->disabled) {
|
||||
@@ -245,7 +249,7 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate)
|
||||
ctr->count = l;
|
||||
if (ctr->using_timer)
|
||||
timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST));
|
||||
pitf_ctr_set_out(ctr, 0);
|
||||
pitf_ctr_set_out(ctr, 0, pit);
|
||||
ctr->thit = 0;
|
||||
ctr->enabled = 1;
|
||||
}
|
||||
@@ -255,7 +259,7 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate)
|
||||
ctr->count = l - 1;
|
||||
if (ctr->using_timer)
|
||||
timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST));
|
||||
pitf_ctr_set_out(ctr, 1);
|
||||
pitf_ctr_set_out(ctr, 1, pit);
|
||||
ctr->thit = 0;
|
||||
}
|
||||
ctr->enabled = gate;
|
||||
@@ -265,7 +269,7 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate)
|
||||
ctr->count = l;
|
||||
if (ctr->using_timer)
|
||||
timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST));
|
||||
pitf_ctr_set_out(ctr, 1);
|
||||
pitf_ctr_set_out(ctr, 1, pit);
|
||||
ctr->thit = 0;
|
||||
}
|
||||
ctr->enabled = gate;
|
||||
@@ -291,12 +295,13 @@ pitf_ctr_set_gate(void *data, int counter_id, int gate)
|
||||
return;
|
||||
}
|
||||
|
||||
pitf_set_gate_no_timer(ctr, gate);
|
||||
pitf_set_gate_no_timer(ctr, gate, pit);
|
||||
}
|
||||
|
||||
static void
|
||||
pitf_over(ctrf_t *ctr)
|
||||
pitf_over(ctrf_t *ctr, void *priv)
|
||||
{
|
||||
pitf_t *pit = (pitf_t *)priv;
|
||||
int l = ctr->l ? ctr->l : 0x10000;
|
||||
if (ctr->disabled) {
|
||||
ctr->count += 0xffff;
|
||||
@@ -309,7 +314,7 @@ pitf_over(ctrf_t *ctr)
|
||||
case 0: /*Interrupt on terminal count*/
|
||||
case 1: /*Hardware retriggerable one-shot*/
|
||||
if (!ctr->thit)
|
||||
pitf_ctr_set_out(ctr, 1);
|
||||
pitf_ctr_set_out(ctr, 1, pit);
|
||||
ctr->thit = 1;
|
||||
ctr->count += 0xffff;
|
||||
if (ctr->using_timer)
|
||||
@@ -319,17 +324,17 @@ pitf_over(ctrf_t *ctr)
|
||||
ctr->count += l;
|
||||
if (ctr->using_timer)
|
||||
timer_advance_u64(&ctr->timer, (uint64_t) (l * PITCONST));
|
||||
pitf_ctr_set_out(ctr, 0);
|
||||
pitf_ctr_set_out(ctr, 1);
|
||||
pitf_ctr_set_out(ctr, 0, pit);
|
||||
pitf_ctr_set_out(ctr, 1, pit);
|
||||
break;
|
||||
case 3: /*Square wave mode*/
|
||||
if (ctr->out) {
|
||||
pitf_ctr_set_out(ctr, 0);
|
||||
pitf_ctr_set_out(ctr, 0, pit);
|
||||
ctr->count += (l >> 1);
|
||||
if (ctr->using_timer)
|
||||
timer_advance_u64(&ctr->timer, (uint64_t) ((l >> 1) * PITCONST));
|
||||
} else {
|
||||
pitf_ctr_set_out(ctr, 1);
|
||||
pitf_ctr_set_out(ctr, 1, pit);
|
||||
ctr->count += ((l + 1) >> 1);
|
||||
if (ctr->using_timer)
|
||||
timer_advance_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST));
|
||||
@@ -341,8 +346,8 @@ pitf_over(ctrf_t *ctr)
|
||||
break;
|
||||
case 4: /*Software triggered strove*/
|
||||
if (!ctr->thit) {
|
||||
pitf_ctr_set_out(ctr, 0);
|
||||
pitf_ctr_set_out(ctr, 1);
|
||||
pitf_ctr_set_out(ctr, 0, pit);
|
||||
pitf_ctr_set_out(ctr, 1, pit);
|
||||
}
|
||||
if (ctr->newcount) {
|
||||
ctr->newcount = 0;
|
||||
@@ -358,8 +363,8 @@ pitf_over(ctrf_t *ctr)
|
||||
break;
|
||||
case 5: /*Hardware triggered strove*/
|
||||
if (!ctr->thit) {
|
||||
pitf_ctr_set_out(ctr, 0);
|
||||
pitf_ctr_set_out(ctr, 1);
|
||||
pitf_ctr_set_out(ctr, 0, pit);
|
||||
pitf_ctr_set_out(ctr, 1, pit);
|
||||
}
|
||||
ctr->thit = 1;
|
||||
ctr->count += 0xffff;
|
||||
@@ -453,9 +458,9 @@ pitf_write(uint16_t addr, uint8_t val, void *priv)
|
||||
ctr->rereadlatch = 1;
|
||||
ctr->initial = 1;
|
||||
if (!ctr->m)
|
||||
pitf_ctr_set_out(ctr, 0);
|
||||
pitf_ctr_set_out(ctr, 0, dev);
|
||||
else
|
||||
pitf_ctr_set_out(ctr, 1);
|
||||
pitf_ctr_set_out(ctr, 1, dev);
|
||||
ctr->disabled = 1;
|
||||
|
||||
pit_log("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out);
|
||||
@@ -472,16 +477,16 @@ pitf_write(uint16_t addr, uint8_t val, void *priv)
|
||||
switch (ctr->wm) {
|
||||
case 1:
|
||||
ctr->l = val;
|
||||
pitf_ctr_load(ctr);
|
||||
pitf_ctr_load(ctr, dev);
|
||||
break;
|
||||
case 2:
|
||||
ctr->l = (val << 8);
|
||||
pitf_ctr_load(ctr);
|
||||
pitf_ctr_load(ctr, dev);
|
||||
break;
|
||||
case 0:
|
||||
ctr->l &= 0xFF;
|
||||
ctr->l |= (val << 8);
|
||||
pitf_ctr_load(ctr);
|
||||
pitf_ctr_load(ctr, dev);
|
||||
ctr->wm = 3;
|
||||
break;
|
||||
case 3:
|
||||
@@ -610,7 +615,8 @@ static void
|
||||
pitf_timer_over(void *priv)
|
||||
{
|
||||
ctrf_t *ctr = (ctrf_t *) priv;
|
||||
pitf_over(ctr);
|
||||
pit_t *pit = (pit_t *)ctr->priv;
|
||||
pitf_over(ctr, pit);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -627,7 +633,7 @@ pitf_ctr_clock(void *data, int counter_id)
|
||||
|
||||
ctr->count -= (ctr->m == 3) ? 2 : 1;
|
||||
if (!ctr->count)
|
||||
pitf_over(ctr);
|
||||
pitf_over(ctr, pit);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -679,6 +685,7 @@ pitf_init(const device_t *info)
|
||||
if (!(dev->flags & PIT_PS2) && !(dev->flags & PIT_CUSTOM_CLOCK)) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ctrf_t *ctr = &dev->counters[i];
|
||||
ctr->priv = dev;
|
||||
timer_add(&ctr->timer, pitf_timer_over, (void *) ctr, 0);
|
||||
}
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_opl_ymfm.cpp snd_re
|
||||
midi.c snd_speaker.c snd_pssj.c snd_lpt_dac.c snd_ac97_codec.c snd_ac97_via.c
|
||||
snd_lpt_dss.c snd_ps1.c snd_adlib.c snd_adlibgold.c snd_ad1848.c snd_audiopci.c
|
||||
snd_azt2316a.c snd_cms.c snd_cmi8x38.c snd_cs423x.c snd_gus.c snd_sb.c snd_sb_dsp.c
|
||||
snd_emu8k.c snd_mpu401.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c
|
||||
snd_emu8k.c snd_mpu401.c snd_pas16.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c
|
||||
snd_optimc.c)
|
||||
|
||||
if(OPENAL)
|
||||
@@ -116,11 +116,6 @@ endif()
|
||||
add_subdirectory(ymfm)
|
||||
target_link_libraries(86Box ymfm)
|
||||
|
||||
if(PAS16)
|
||||
target_compile_definitions(snd PRIVATE USE_PAS16)
|
||||
target_sources(snd PRIVATE snd_pas16.c)
|
||||
endif()
|
||||
|
||||
if(GUSMAX)
|
||||
target_compile_definitions(snd PRIVATE USE_GUSMAX)
|
||||
endif()
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include <86box/dma.h>
|
||||
#include <86box/filters.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/midi.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/pit.h>
|
||||
@@ -132,34 +133,25 @@ typedef struct pas16_t {
|
||||
uint8_t sys_conf_2;
|
||||
uint8_t sys_conf_3;
|
||||
uint8_t sys_conf_4;
|
||||
|
||||
struct {
|
||||
uint32_t l[3];
|
||||
int64_t c[3];
|
||||
pc_timer_t timer[3];
|
||||
uint8_t m[3];
|
||||
uint8_t ctrl;
|
||||
uint8_t ctrls[2];
|
||||
int wp;
|
||||
int rm[3];
|
||||
int wm[3];
|
||||
uint16_t rl[3];
|
||||
int thit[3];
|
||||
int delay[3];
|
||||
int rereadlatch[3];
|
||||
int64_t enable[3];
|
||||
} pit;
|
||||
uint8_t waitstates;
|
||||
uint8_t midi_ctrl;
|
||||
uint8_t midi_stat;
|
||||
uint8_t midi_data;
|
||||
uint8_t midi_fifo[16];
|
||||
|
||||
fm_drv_t opl;
|
||||
sb_dsp_t dsp;
|
||||
mpu_t *mpu;
|
||||
|
||||
int16_t pcm_buffer[2][SOUNDBUFLEN];
|
||||
|
||||
int pos;
|
||||
|
||||
int midi_uart_out;
|
||||
|
||||
pit_t *pit;
|
||||
} pas16_t;
|
||||
|
||||
static uint8_t pas16_pit_in(uint16_t port, void *priv);
|
||||
static void pas16_pit_out(uint16_t port, uint8_t val, void *priv);
|
||||
static void pas16_update(pas16_t *pas16);
|
||||
|
||||
static int pas16_dmas[8] = { 4, 1, 2, 3, 0, 5, 6, 7 };
|
||||
@@ -169,7 +161,8 @@ static int pas16_sb_dmas[8] = { 0, 1, 2, 3 };
|
||||
|
||||
enum {
|
||||
PAS16_INT_SAMP = 0x04,
|
||||
PAS16_INT_PCM = 0x08
|
||||
PAS16_INT_PCM = 0x08,
|
||||
PAS16_INT_MIDI = 0x10,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -204,6 +197,96 @@ pas16_log(const char *fmt, ...)
|
||||
# define pas16_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
pas16_update_midi_irqs(pas16_t *pas16)
|
||||
{
|
||||
int irq = 0;
|
||||
|
||||
pas16->irq_stat &= ~PAS16_INT_MIDI;
|
||||
|
||||
if ((pas16->uart_status & 0x18) || (dev->uart_status & 0x04)) {
|
||||
pas16->irq_stat |= PAS16_INT_MIDI;
|
||||
irq = 1;
|
||||
}
|
||||
|
||||
if (irq)
|
||||
picint(1 << pas16->irq);
|
||||
else
|
||||
picintc(1 << pas16->irq);
|
||||
}
|
||||
|
||||
static void
|
||||
pas16_update_tx_irq(pas16_t *pas16)
|
||||
{
|
||||
pas16->uart_status &= ~0x18;
|
||||
|
||||
if ((pas16->irq_ena & PAS16_INT_MIDI) && (pas16->uart_ctrl & 0x18))
|
||||
pas16->uart_status |= 0x18;
|
||||
|
||||
pas16_update_midi_irqs(pas16);
|
||||
}
|
||||
|
||||
static void
|
||||
pas16_update_rx_irq(pas16_t *pas16)
|
||||
{
|
||||
pas16->uart_status &= ~0x04;
|
||||
|
||||
if ((pas16->irq_ena & PAS16_INT_MIDI) && (pas16->uart_ctrl & 0x04))
|
||||
pas16->uart_status |= 0x04;
|
||||
|
||||
pas16_update_midi_irqs(pas16);
|
||||
}
|
||||
|
||||
static void
|
||||
pas16_scan_fifo(pas16_t *pas16)
|
||||
{
|
||||
if (pas16->read_fifo_pos != pas16->write_fifo_pos) {
|
||||
pas16->uart_data = pas16->uart_fifo[pas16->read_fifo_pos];
|
||||
pas16->read_fifo_pos = (pas16->read_fifo_pos + 1) & 0x0f;
|
||||
|
||||
es1371_set_rx_irq(pas16, 1);
|
||||
} else
|
||||
es1371_set_rx_irq(pas16, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
es1371_write_fifo(es1371_t *dev, uint8_t val)
|
||||
{
|
||||
if (dev->write_fifo_pos < 16) {
|
||||
dev->uart_fifo[dev->write_fifo_pos] = val | UART_FIFO_BYTE_VALID;
|
||||
dev->write_fifo_pos = (dev->write_fifo_pos + 1) & 0x0f;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
es1371_reset_fifo(es1371_t *dev)
|
||||
{
|
||||
for (uint8_t i = 0; i < 16; i++)
|
||||
dev->uart_fifo[i] = 0x00000000;
|
||||
|
||||
dev->read_fifo_pos = dev->write_fifo_pos = 0;
|
||||
|
||||
es1371_set_rx_irq(dev, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
pas16_reset(void *priv)
|
||||
{
|
||||
pas16_t *pas16 = (pas16_t *) priv;
|
||||
|
||||
pas16->uart_status = 0xff;
|
||||
pas16->uart_ctrl = 0x00;
|
||||
|
||||
for (uint8_t i = 0; i < 16; i++)
|
||||
pas16->uart_fifo[i] = 0x00;
|
||||
|
||||
pas16_set_tx_irq(pas16, 0);
|
||||
|
||||
pas16_reset_fifo(pas16);
|
||||
|
||||
pas16_update_midi_irqs(pas16);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
pas16_in(uint16_t port, void *priv)
|
||||
{
|
||||
@@ -230,18 +313,24 @@ pas16_in(uint16_t port, void *priv)
|
||||
break;
|
||||
|
||||
case 0xb8b:
|
||||
temp = (pas16->irq_ena & ~0xe0) | 0x20;
|
||||
temp = pas16->irq_ena & ~0xe0;
|
||||
temp |= 0x01;
|
||||
break;
|
||||
|
||||
case 0xf8a:
|
||||
temp = pas16->pcm_ctrl;
|
||||
break;
|
||||
|
||||
case 0x1388:
|
||||
case 0x1389:
|
||||
case 0x138a:
|
||||
case 0x138b:
|
||||
temp = pas16_pit_in(port, pas16);
|
||||
case 0x1789:
|
||||
temp = 0;
|
||||
break;
|
||||
case 0x178a:
|
||||
temp = pas16->uart_data;
|
||||
pas16_set_rx_irq(pas16, 0);
|
||||
break;
|
||||
|
||||
case 0x1b88:
|
||||
temp = pas16->uart_status;
|
||||
break;
|
||||
|
||||
case 0x2789: /*Board revision*/
|
||||
@@ -249,7 +338,7 @@ pas16_in(uint16_t port, void *priv)
|
||||
break;
|
||||
|
||||
case 0x7f89:
|
||||
temp = pas16->enhancedscsi & ~1;
|
||||
temp = pas16->enhancedscsi & ~0x01;
|
||||
break;
|
||||
|
||||
case 0x8388:
|
||||
@@ -265,6 +354,10 @@ pas16_in(uint16_t port, void *priv)
|
||||
temp = pas16->sys_conf_4;
|
||||
break;
|
||||
|
||||
case 0xbf88:
|
||||
temp = pas16->waitstates;
|
||||
break;
|
||||
|
||||
case 0xef8b:
|
||||
temp = 0x0c;
|
||||
break;
|
||||
@@ -275,10 +368,10 @@ pas16_in(uint16_t port, void *priv)
|
||||
case 0xf389:
|
||||
temp = pas16->io_conf_2;
|
||||
break;
|
||||
case 0xf38b:
|
||||
case 0xf38a:
|
||||
temp = pas16->io_conf_3;
|
||||
break;
|
||||
case 0xf38c:
|
||||
case 0xf38b:
|
||||
temp = pas16->io_conf_4;
|
||||
break;
|
||||
|
||||
@@ -294,7 +387,7 @@ pas16_in(uint16_t port, void *priv)
|
||||
break;
|
||||
|
||||
case 0xff88: /*Board model*/
|
||||
temp = 4; /*PAS16*/
|
||||
temp = 0x04; /*PAS16*/
|
||||
break;
|
||||
case 0xff8b: /*Master mode read*/
|
||||
temp = 0x20 | 0x10 | 0x01; /*AT bus, XT/AT timing*/
|
||||
@@ -303,7 +396,7 @@ pas16_in(uint16_t port, void *priv)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pas16_log("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS, cpu_state.pc);
|
||||
pclog("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS, cpu_state.pc);
|
||||
return temp;
|
||||
}
|
||||
|
||||
@@ -311,7 +404,8 @@ static void
|
||||
pas16_out(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
pas16_t *pas16 = (pas16_t *) priv;
|
||||
pas16_log("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS, cpu_state.pc);
|
||||
pit_t *pit = (pit_t *) pas16->pit;
|
||||
pclog("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS, cpu_state.pc);
|
||||
switch ((port - pas16->base) + 0x388) {
|
||||
case 0x388:
|
||||
case 0x389:
|
||||
@@ -348,14 +442,35 @@ pas16_out(uint16_t port, uint8_t val, void *priv)
|
||||
case 0xf8a:
|
||||
if ((val & PAS16_PCM_ENA) && !(pas16->pcm_ctrl & PAS16_PCM_ENA)) /*Guess*/
|
||||
pas16->stereo_lr = 0;
|
||||
|
||||
pas16->pcm_ctrl = val;
|
||||
break;
|
||||
|
||||
case 0x1388:
|
||||
case 0x1389:
|
||||
case 0x138a:
|
||||
case 0x138b:
|
||||
pas16_pit_out(port, val, pas16);
|
||||
case 0x1789:
|
||||
case 0x178b:
|
||||
pas16->uart_ctrl = val;
|
||||
|
||||
if ((val & 0x60) == 0x60) {
|
||||
/* Reset TX */
|
||||
pas16_set_tx_irq(pas16, 1);
|
||||
|
||||
/* Software reset */
|
||||
pas16_reset_fifo(pas16);
|
||||
} else {
|
||||
pas16_set_tx_irq(pas16, 1);
|
||||
|
||||
pas16_update_tx_irq(pas16);
|
||||
pas16_update_rx_irq(pas16);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x178a:
|
||||
midi_raw_out_byte(val);
|
||||
pas16_set_tx_irq(pas16, 1);
|
||||
break;
|
||||
|
||||
case 0x1b88:
|
||||
pas16->uart_status = val;
|
||||
break;
|
||||
|
||||
case 0x7f89:
|
||||
@@ -363,6 +478,10 @@ pas16_out(uint16_t port, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case 0x8388:
|
||||
if ((val & 0x80) && !(pas16->sys_conf_1 & 0x80)) {
|
||||
pclog("Reset.\n");
|
||||
pas16_reset(pas16);
|
||||
}
|
||||
pas16->sys_conf_1 = val;
|
||||
break;
|
||||
case 0x8389:
|
||||
@@ -375,18 +494,22 @@ pas16_out(uint16_t port, uint8_t val, void *priv)
|
||||
pas16->sys_conf_4 = val;
|
||||
break;
|
||||
|
||||
case 0xbf88:
|
||||
pas16->waitstates = val;
|
||||
break;
|
||||
|
||||
case 0xf388:
|
||||
pas16->io_conf_1 = val;
|
||||
break;
|
||||
case 0xf389:
|
||||
pas16->io_conf_2 = val;
|
||||
pas16->dma = pas16_dmas[val & 0x7];
|
||||
pas16_log("pas16_out : set PAS DMA %i\n", pas16->dma);
|
||||
pclog("pas16_out : set PAS DMA %i\n", pas16->dma);
|
||||
break;
|
||||
case 0xf38a:
|
||||
pas16->io_conf_3 = val;
|
||||
pas16->irq = pas16_irqs[val & 0xf];
|
||||
pas16_log("pas16_out : set PAS IRQ %i\n", pas16->irq);
|
||||
pclog("pas16_out : set PAS IRQ %i\n", pas16->irq);
|
||||
break;
|
||||
case 0xf38b:
|
||||
pas16->io_conf_4 = val;
|
||||
@@ -398,11 +521,17 @@ pas16_out(uint16_t port, uint8_t val, void *priv)
|
||||
sb_dsp_setaddr(&pas16->dsp, ((pas16->compat_base & 0xf) << 4) | 0x200);
|
||||
else
|
||||
sb_dsp_setaddr(&pas16->dsp, 0);
|
||||
if (pas16->compat & 0x01)
|
||||
mpu401_change_addr(pas16->mpu, ((pas16->compat_base & 0xf0) | 0x300));
|
||||
else
|
||||
mpu401_change_addr(pas16->mpu, 0);
|
||||
break;
|
||||
case 0xf789:
|
||||
pas16->compat_base = val;
|
||||
if (pas16->compat & 0x02)
|
||||
sb_dsp_setaddr(&pas16->dsp, ((pas16->compat_base & 0xf) << 4) | 0x200);
|
||||
if (pas16->compat & 0x01)
|
||||
mpu401_change_addr(pas16->mpu, ((pas16->compat_base & 0xf0) | 0x300));
|
||||
break;
|
||||
|
||||
case 0xfb8a:
|
||||
@@ -413,7 +542,7 @@ pas16_out(uint16_t port, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
default:
|
||||
pas16_log("pas16_out : unknown %04X\n", port);
|
||||
pclog("pas16_out : unknown %04X\n", port);
|
||||
}
|
||||
#if 0
|
||||
if (cpu_state.pc == 0x80048CF3) {
|
||||
@@ -424,167 +553,17 @@ pas16_out(uint16_t port, uint8_t val, void *priv)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pas16_pit_out(uint16_t port, uint8_t val, void *priv)
|
||||
pas16_scan_fifo(pas16_t *pas16)
|
||||
{
|
||||
pas16_t *pas16 = (pas16_t *) priv;
|
||||
int t;
|
||||
switch (port & 3) {
|
||||
case 3: /*CTRL*/
|
||||
if ((val & 0xC0) == 0xC0) {
|
||||
if (!(val & 0x20)) {
|
||||
if (val & 2)
|
||||
pas16->pit.rl[0] = timer_get_remaining_u64(&pas16->pit.timer[0]) / PITCONST;
|
||||
if (val & 4)
|
||||
pas16->pit.rl[1] = pas16->pit.c[1];
|
||||
if (val & 8)
|
||||
pas16->pit.rl[2] = pas16->pit.c[2];
|
||||
}
|
||||
return;
|
||||
}
|
||||
t = val >> 6;
|
||||
pas16->pit.ctrls[t] = pas16->pit.ctrl = val;
|
||||
if (t == 3) {
|
||||
printf("Bad PIT reg select\n");
|
||||
return;
|
||||
}
|
||||
if (!(pas16->pit.ctrl & 0x30)) {
|
||||
if (!t)
|
||||
pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST;
|
||||
else {
|
||||
pas16->pit.rl[t] = pas16->pit.c[t];
|
||||
if (pas16->pit.c[t] < 0)
|
||||
pas16->pit.rl[t] = 0;
|
||||
}
|
||||
pas16->pit.ctrl |= 0x30;
|
||||
pas16->pit.rereadlatch[t] = 0;
|
||||
pas16->pit.rm[t] = 3;
|
||||
} else {
|
||||
pas16->pit.rm[t] = pas16->pit.wm[t] = (pas16->pit.ctrl >> 4) & 3;
|
||||
pas16->pit.m[t] = (val >> 1) & 7;
|
||||
if (pas16->pit.m[t] > 5)
|
||||
pas16->pit.m[t] &= 3;
|
||||
if (!pas16->pit.rm[t]) {
|
||||
pas16->pit.rm[t] = 3;
|
||||
if (!t)
|
||||
pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST;
|
||||
else
|
||||
pas16->pit.rl[t] = pas16->pit.c[t];
|
||||
}
|
||||
pas16->pit.rereadlatch[t] = 1;
|
||||
}
|
||||
pas16->pit.wp = 0;
|
||||
pas16->pit.thit[t] = 0;
|
||||
break;
|
||||
case 0:
|
||||
case 1:
|
||||
case 2: /*Timers*/
|
||||
t = port & 3;
|
||||
switch (pas16->pit.wm[t]) {
|
||||
case 1:
|
||||
pas16->pit.l[t] = val;
|
||||
pas16->pit.thit[t] = 0;
|
||||
pas16->pit.c[t] = pas16->pit.l[t];
|
||||
if (!t)
|
||||
timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST);
|
||||
pas16->pit.enable[t] = 1;
|
||||
break;
|
||||
case 2:
|
||||
pas16->pit.l[t] = val << 8;
|
||||
pas16->pit.thit[t] = 0;
|
||||
pas16->pit.c[t] = pas16->pit.l[t];
|
||||
if (!t)
|
||||
timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST);
|
||||
pas16->pit.enable[t] = 1;
|
||||
break;
|
||||
case 0:
|
||||
pas16->pit.l[t] &= 0xFF;
|
||||
pas16->pit.l[t] |= (val << 8);
|
||||
pas16->pit.c[t] = pas16->pit.l[t];
|
||||
if (!t)
|
||||
timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST);
|
||||
pas16->pit.thit[t] = 0;
|
||||
pas16->pit.wm[t] = 3;
|
||||
pas16->pit.enable[t] = 1;
|
||||
break;
|
||||
case 3:
|
||||
pas16->pit.l[t] &= 0xFF00;
|
||||
pas16->pit.l[t] |= val;
|
||||
pas16->pit.wm[t] = 0;
|
||||
break;
|
||||
if (pas16->read_fifo_pos != pas16->write_fifo_pos) {
|
||||
pas16->uart_data = pas16->uart_fifo[pas16->read_fifo_pos];
|
||||
pas16->read_fifo_pos = (pas16->read_fifo_pos + 1) & 7;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!pas16->pit.l[t]) {
|
||||
pas16->pit.l[t] |= 0x10000;
|
||||
pas16->pit.c[t] = pas16->pit.l[t];
|
||||
if (!t)
|
||||
timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
pas16_pit_in(uint16_t port, void *priv)
|
||||
{
|
||||
pas16_t *pas16 = (pas16_t *) priv;
|
||||
uint8_t temp = 0xff;
|
||||
int t = port & 3;
|
||||
switch (port & 3) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2: /*Timers*/
|
||||
if (pas16->pit.rereadlatch[t]) {
|
||||
pas16->pit.rereadlatch[t] = 0;
|
||||
if (!t) {
|
||||
pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST;
|
||||
if ((timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST) > 65536)
|
||||
pas16->pit.rl[t] = 0xFFFF;
|
||||
} else {
|
||||
pas16->pit.rl[t] = pas16->pit.c[t];
|
||||
if (pas16->pit.c[t] > 65536)
|
||||
pas16->pit.rl[t] = 0xFFFF;
|
||||
}
|
||||
}
|
||||
switch (pas16->pit.rm[t]) {
|
||||
case 0:
|
||||
temp = pas16->pit.rl[t] >> 8;
|
||||
pas16->pit.rm[t] = 3;
|
||||
pas16->pit.rereadlatch[t] = 1;
|
||||
break;
|
||||
case 1:
|
||||
temp = (pas16->pit.rl[t]) & 0xFF;
|
||||
pas16->pit.rereadlatch[t] = 1;
|
||||
break;
|
||||
case 2:
|
||||
temp = (pas16->pit.rl[t]) >> 8;
|
||||
pas16->pit.rereadlatch[t] = 1;
|
||||
break;
|
||||
case 3:
|
||||
temp = (pas16->pit.rl[t]) & 0xFF;
|
||||
if (pas16->pit.m[t] & 0x80)
|
||||
pas16->pit.m[t] &= 7;
|
||||
else
|
||||
pas16->pit.rm[t] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3: /*Control*/
|
||||
temp = pas16->pit.ctrl;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return temp;
|
||||
pas16_set_rx_irq(pas16, 1);
|
||||
} else
|
||||
pas16_set_rx_irq(pas16, 0);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
@@ -593,30 +572,34 @@ pas16_readdma(pas16_t *pas16)
|
||||
return dma_channel_read(pas16->dma);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pas16_pcm_poll(void *priv)
|
||||
{
|
||||
pas16_t *pas16 = (pas16_t *) priv;
|
||||
pit_t *pit = (pit_t *)priv;
|
||||
pas16_t *pas16 = (pas16_t *) pit->dev_priv;
|
||||
uint16_t temp = 0x0000;
|
||||
|
||||
|
||||
pas16_update(pas16);
|
||||
if (pas16->pit.m[0] & 2) {
|
||||
if (pas16->pit.l[0])
|
||||
timer_advance_u64(&pas16->pit.timer[0], pas16->pit.l[0] * PITCONST);
|
||||
else
|
||||
timer_advance_u64(&pas16->pit.timer[0], 0x10000 * PITCONST);
|
||||
} else {
|
||||
pas16->pit.enable[0] = 0;
|
||||
if (pit->counters[0].m & 2) {
|
||||
if (pit->counters[0].l)
|
||||
timer_advance_u64(&pit->callback_timer, pit->counters[0].l * (PITCONST << 1ULL));
|
||||
else {
|
||||
timer_advance_u64(&pit->callback_timer, 0x10000 * (PITCONST << 1ULL));
|
||||
}
|
||||
}
|
||||
|
||||
pas16->irq_stat |= PAS16_INT_SAMP;
|
||||
if (pas16->irq_ena & PAS16_INT_SAMP)
|
||||
picint(1 << pas16->irq);
|
||||
else
|
||||
picintc(1 << pas16->irq);
|
||||
|
||||
/*Update sample rate counter*/
|
||||
if (pas16->pit.enable[1]) {
|
||||
pas16_log("Enable (t1) = %d.\n", pit->counters[1].enable);
|
||||
if (pit->counters[1].enable) {
|
||||
if (pas16->pcm_ctrl & PAS16_PCM_ENA) {
|
||||
uint16_t temp;
|
||||
|
||||
if (pas16->sys_conf_2 & PAS16_SC2_16BIT) {
|
||||
temp = pas16_readdma(pas16) << 8;
|
||||
temp |= pas16_readdma(pas16);
|
||||
@@ -637,27 +620,40 @@ pas16_pcm_poll(void *priv)
|
||||
}
|
||||
}
|
||||
if (pas16->sys_conf_2 & PAS16_SC2_16BIT)
|
||||
pas16->pit.c[1] -= 2;
|
||||
pit->counters[1].rl -= 2;
|
||||
else
|
||||
pas16->pit.c[1]--;
|
||||
if (pas16->pit.c[1] == 0) {
|
||||
if (pas16->pit.m[1] & 2) {
|
||||
if (pas16->pit.l[1])
|
||||
pas16->pit.c[1] += pas16->pit.l[1];
|
||||
pit->counters[1].rl--;
|
||||
|
||||
pas16_log("RL=%d, mode=%x.\n", pit->counters[1].rl, pit->counters[1].m & 0x03);
|
||||
if (pit->counters[1].rl == 0xffff) {
|
||||
if (pit->counters[1].m & 2) {
|
||||
if (pit->counters[1].l & 0xffff)
|
||||
pit->counters[1].rl = pit->counters[1].l & 0xffff;
|
||||
else
|
||||
pas16->pit.c[1] += 0x10000;
|
||||
pit->counters[1].rl = 0;
|
||||
} else {
|
||||
pas16->pit.c[1] = -1;
|
||||
pas16->pit.enable[1] = 0;
|
||||
pit->counters[1].enable = 0;
|
||||
pit->counters[1].rl = 0;
|
||||
}
|
||||
|
||||
pas16_log("New counter=%d, mode=%x.\n", pit->counters[1].rl, pit->counters[1].m & 0x03);
|
||||
pas16->irq_stat |= PAS16_INT_PCM;
|
||||
if (pas16->irq_ena & PAS16_INT_PCM) {
|
||||
pas16_log("pas16_pcm_poll : cause IRQ %i %02X\n", pas16->irq, 1 << pas16->irq);
|
||||
pclog("pas16_pcm_poll : cause IRQ %i %02X, enable timer 1 = %x\n", pas16->irq, 1 << pas16->irq, pit->counters[1].enable);
|
||||
picint(1 << pas16->irq);
|
||||
} else
|
||||
picintc(1 << pas16->irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pas16_pit_timer0(int new_out, int old_out, void *priv)
|
||||
{
|
||||
pit_t *pit = (pit_t *)priv;
|
||||
pclog("NewOut=%d, OldOut=%d.\n", new_out, old_out);
|
||||
pit->counters[1].enable = new_out;
|
||||
pit_ctr_set_clock(&pit->counters[0], new_out, pit);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -669,8 +665,9 @@ pas16_out_base(UNUSED(uint16_t port), uint8_t val, void *priv)
|
||||
io_removehandler((pas16->base - 0x388) + 0x0788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_removehandler((pas16->base - 0x388) + 0x0b88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_removehandler((pas16->base - 0x388) + 0x0f88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_removehandler((pas16->base - 0x388) + 0x1388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
pit_handler(0, (pas16->base - 0x388) + 0x1388, 0x0004, pas16->pit);
|
||||
io_removehandler((pas16->base - 0x388) + 0x1788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_removehandler((pas16->base - 0x388) + 0x1b88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_removehandler((pas16->base - 0x388) + 0x2788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_removehandler((pas16->base - 0x388) + 0x7f88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_removehandler((pas16->base - 0x388) + 0x8388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
@@ -685,14 +682,15 @@ pas16_out_base(UNUSED(uint16_t port), uint8_t val, void *priv)
|
||||
io_removehandler((pas16->base - 0x388) + 0xff88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
|
||||
pas16->base = val << 2;
|
||||
pas16_log("pas16_write_base : PAS16 base now at %04X\n", pas16->base);
|
||||
pclog("pas16_write_base : PAS16 base now at %04X\n", pas16->base);
|
||||
|
||||
io_sethandler((pas16->base - 0x388) + 0x0388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_sethandler((pas16->base - 0x388) + 0x0788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_sethandler((pas16->base - 0x388) + 0x0b88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_sethandler((pas16->base - 0x388) + 0x0f88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_sethandler((pas16->base - 0x388) + 0x1388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
pit_handler(1, (pas16->base - 0x388) + 0x1388, 0x0004, pas16->pit);
|
||||
io_sethandler((pas16->base - 0x388) + 0x1788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_sethandler((pas16->base - 0x388) + 0x1b88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_sethandler((pas16->base - 0x388) + 0x2788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_sethandler((pas16->base - 0x388) + 0x7f88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
io_sethandler((pas16->base - 0x388) + 0x8388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16);
|
||||
@@ -759,10 +757,22 @@ pas16_init(UNUSED(const device_t *info))
|
||||
|
||||
fm_driver_get(FM_YMF262, &pas16->opl);
|
||||
sb_dsp_init(&pas16->dsp, SB2, SB_SUBTYPE_DEFAULT, pas16);
|
||||
pas16->mpu = (mpu_t *) malloc(sizeof(mpu_t));
|
||||
memset(pas16->mpu, 0, sizeof(mpu_t));
|
||||
mpu401_init(pas16->mpu, 0, 0, M_UART, device_get_config_int("receive_input401"));
|
||||
sb_dsp_set_mpu(&pas16->dsp, pas16->mpu);
|
||||
|
||||
pas16->pit = device_add(&i8254_ext_io_device);
|
||||
|
||||
pas16->midi_uart_out = 1;
|
||||
|
||||
io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16);
|
||||
|
||||
timer_add(&pas16->pit.timer[0], pas16_pcm_poll, pas16, 0);
|
||||
pit_ctr_set_out_func(pas16->pit, 0, pas16_pit_timer0);
|
||||
pit_ctr_set_using_timer(pas16->pit, 0, 1);
|
||||
pit_ctr_set_using_timer(pas16->pit, 1, 0);
|
||||
pit_ctr_set_using_timer(pas16->pit, 2, 0);
|
||||
pas16->pit->dev_priv = pas16;
|
||||
pas16->pit->dev_timer = pas16_pcm_poll;
|
||||
|
||||
sound_add_handler(pas16_get_buffer, pas16);
|
||||
music_add_handler(pas16_get_music_buffer, pas16);
|
||||
@@ -778,10 +788,21 @@ pas16_close(void *priv)
|
||||
free(pas16);
|
||||
}
|
||||
|
||||
static const device_config_t pas16_config[] = {
|
||||
{
|
||||
.name = "receive_input401",
|
||||
.description = "Receive input (MPU-401)",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_string = "",
|
||||
.default_int = 0
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
|
||||
const device_t pas16_device = {
|
||||
.name = "Pro Audio Spectrum 16",
|
||||
.internal_name = "pas16",
|
||||
.flags = DEVICE_ISA,
|
||||
.flags = DEVICE_ISA | DEVICE_AT,
|
||||
.local = 0,
|
||||
.init = pas16_init,
|
||||
.close = pas16_close,
|
||||
@@ -789,5 +810,5 @@ const device_t pas16_device = {
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.config = pas16_config
|
||||
};
|
||||
|
@@ -149,9 +149,7 @@ static const SOUND_CARD sound_cards[] = {
|
||||
{ &sb_vibra16s_device },
|
||||
{ &sb_vibra16xv_device },
|
||||
{ &ssi2001_device },
|
||||
#if defined(DEV_BRANCH) && defined(USE_PAS16)
|
||||
{ &pas16_device },
|
||||
#endif
|
||||
{ &pssj_isa_device },
|
||||
{ &tndy_device },
|
||||
{ &wss_device },
|
||||
|
Reference in New Issue
Block a user