From 27e78da4ec9f849b60615c85792d9a5f87ad1737 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 18 Mar 2024 17:10:36 +0100 Subject: [PATCH] WIP: PAS16. See above, currently very WIP. --- src/include/86box/pit.h | 28 ++- src/include/86box/pit_fast.h | 3 +- src/include/86box/sound.h | 2 - src/pit.c | 117 +++++---- src/pit_fast.c | 67 ++--- src/sound/CMakeLists.txt | 7 +- src/sound/snd_pas16.c | 475 ++++++++++++++++++----------------- src/sound/sound.c | 2 - 8 files changed, 381 insertions(+), 320 deletions(-) diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index d288b7e6c..078694633 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -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; diff --git a/src/include/86box/pit_fast.h b/src/include/86box/pit_fast.h index 2485a360c..845105185 100644 --- a/src/include/86box/pit_fast.h +++ b/src/include/86box/pit_fast.h @@ -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 { diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index b8f9be5b2..0359c0ff8 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -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; diff --git a/src/pit.c b/src/pit.c index 6045fd842..4f64d40c1 100644 --- a/src/pit.c +++ b/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; diff --git a/src/pit_fast.c b/src/pit_fast.c index f9d055375..9c5d622ec 100644 --- a/src/pit_fast.c +++ b/src/pit_fast.c @@ -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); } } diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 72f05ff6d..c1bbc811f 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -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() diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 3ce9b5c4c..32879cd1e 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -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,29 +620,42 @@ 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 pas16_out_base(UNUSED(uint16_t port), uint8_t val, void *priv) { @@ -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 }; diff --git a/src/sound/sound.c b/src/sound/sound.c index 81f70d921..50eb984d6 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -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 },