diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dfed3fb9..11265d09a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,7 +151,6 @@ endif() cmake_dependent_option(AMD_K5 "AMD K5" ON "DEV_BRANCH" OFF) cmake_dependent_option(AN430TX "Intel AN430TX" ON "DEV_BRANCH" OFF) cmake_dependent_option(CYRIX_6X86 "Cyrix 6x86" ON "DEV_BRANCH" OFF) -cmake_dependent_option(DESKPRO386 "Compaq Deskpro 386" ON "DEV_BRANCH" OFF) cmake_dependent_option(GUSMAX "Gravis UltraSound MAX" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_IAB "Intel Above Board" ON "DEV_BRANCH" OFF) @@ -160,7 +159,6 @@ cmake_dependent_option(LASERXT "VTech Laser XT" cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF) cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF) cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF) -cmake_dependent_option(PAS16 "Pro Audio Spectrum 16" ON "DEV_BRANCH" OFF) cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF) cmake_dependent_option(VGAWONDER "ATI VGA Wonder (ATI-18800)" ON "DEV_BRANCH" OFF) cmake_dependent_option(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF) diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index d288b7e6c..d9bce667d 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; @@ -55,9 +56,11 @@ typedef struct ctr_t { }; uint32_t l; + uint32_t lback; + uint32_t lback2; 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 +71,11 @@ typedef struct PIT { ctr_t counters[3]; uint8_t ctrl; + void *dev_priv; } pit_t; +extern pit_t *ext_pit; + enum { PIT_8253 = 0, PIT_8254 = 1, @@ -87,7 +93,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 +119,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 +145,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..20baf3f66 100644 --- a/src/pit.c +++ b/src/pit.c @@ -94,13 +94,16 @@ 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 +149,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 +159,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 +169,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 +189,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 +209,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 +218,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 +244,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 +263,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 +288,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 +320,7 @@ ctr_clock(void *data, int counter_id) if (ctr->using_timer) return; - ctr_tick(ctr); + ctr_tick(ctr, pit); } static void @@ -351,7 +355,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); + pit_log("Counter loaded, state = %i, gate = %i, latch = %i\n", ctr->state, ctr->gate, ctr->latch); } static __inline void @@ -390,7 +394,7 @@ ctr_latch_count(ctr_t *ctr) break; } - pit_log("latched counter = %04X\n", ctr->rl & 0xffff); + pit_log("rm = %x, latched counter = %04X\n", ctr->rm & 0x03, ctr->rl & 0xffff); } uint16_t @@ -415,7 +419,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 +452,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 +469,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 +489,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 +521,7 @@ 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); timer_advance_u64(&dev->callback_timer, PITCONST >> 1ULL); } @@ -528,7 +533,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))) + pit_log("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); switch (addr & 3) { case 3: /* control */ @@ -544,7 +550,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))) + pit_log("PIT %i: Initiated readback command\n", t); } if (!(val & 0x10)) { if (val & 2) @@ -561,7 +568,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))) + pit_log("PIT %i: Initiated latched read, %i bytes latched\n", t, ctr->latched); } else { ctr->ctrl = val; @@ -571,14 +579,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))) + pit_log("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))) + pit_log("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out); } } break; @@ -594,31 +604,44 @@ pit_write(uint16_t addr, uint8_t val, void *priv) break; case 1: ctr->l = val; + ctr->lback = ctr->l; + ctr->lback2 = ctr->l; + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) + pit_log("PIT %i (1): Written byte %02X, latch now %04X\n", t, val, ctr->l); 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); + ctr->lback = ctr->l; + ctr->lback2 = ctr->l; + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) + pit_log("PIT %i (2): Written byte %02X, latch now %04X\n", t, val, ctr->l); 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); + ctr->lback = ctr->l; + ctr->lback2 = ctr->l; + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) + pit_log("PIT %i (0x83): 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); + ctr->lback = ctr->l; + ctr->lback2 = ctr->l; + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) + pit_log("PIT %i (3): 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 +772,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))) + pit_log("[%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 +794,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 +828,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; @@ -876,6 +900,7 @@ pit_init(const device_t *info) } dev->flags = info->local; + dev->dev_priv = NULL; if (!(dev->flags & PIT_EXT_IO)) { io_sethandler((dev->flags & PIT_SECONDARY) ? 0x0048 : 0x0040, 0x0004, @@ -899,6 +924,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 +995,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..d8187cf0f 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,49 +133,46 @@ 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 fifo_stat; + int midi_r; + int midi_w; + int midi_uart_out; + int midi_uart_in; + uint8_t midi_queue[256]; + int sysex; fm_drv_t opl; sb_dsp_t dsp; + mpu_t *mpu; + pc_timer_t timer; int16_t pcm_buffer[2][SOUNDBUFLEN]; int pos; + + 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 }; -static int pas16_irqs[16] = { 0, 2, 3, 4, 5, 6, 7, 10, 11, 12, 14, 15, 0, 0, 0, 0 }; static int pas16_sb_irqs[8] = { 0, 2, 3, 5, 7, 10, 11, 12 }; 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 { PAS16_PCM_MONO = 0x20, - PAS16_PCM_ENA = 0x40 + PAS16_PCM_ENA = 0x40, + PAS16_PCM_DMA_ENA = 0x80 }; enum { @@ -204,52 +202,92 @@ pas16_log(const char *fmt, ...) # define pas16_log(fmt, ...) #endif +static uint8_t +pas16_in(uint16_t port, void *priv); +static void +pas16_out(uint16_t port, uint8_t val, void *priv); + +static void +pas16_update_irq(pas16_t *pas16) +{ + if (pas16->midi_uart_out && (pas16->midi_stat & 0x18)) { + pas16->irq_stat |= PAS16_INT_MIDI; + if (pas16->irq_ena & PAS16_INT_MIDI) + picint(1 << pas16->irq); + } + if (pas16->midi_uart_in && (pas16->midi_stat & 0x04)) { + pas16->irq_stat |= PAS16_INT_MIDI; + if (pas16->irq_ena & PAS16_INT_MIDI) + picint(1 << pas16->irq); + } +} + static uint8_t pas16_in(uint16_t port, void *priv) { pas16_t *pas16 = (pas16_t *) priv; uint8_t temp = 0xff; - switch ((port - pas16->base) + 0x388) { + switch (port) { case 0x388: case 0x389: case 0x38a: case 0x38b: - temp = pas16->opl.read((port - pas16->base) + 0x388, pas16->opl.priv); + temp = pas16->opl.read(port, pas16->opl.priv); break; case 0xb88: temp = pas16->audio_mixer; break; - case 0xb89: temp = pas16->irq_stat; break; - case 0xb8a: temp = pas16->audiofilt; break; - case 0xb8b: - temp = (pas16->irq_ena & ~0xe0) | 0x20; + temp = pas16->irq_ena | 0x20; + pas16_log("IRQ Mask read=%02x.\n", temp); break; case 0xf8a: temp = pas16->pcm_ctrl; break; - case 0x1388: - case 0x1389: - case 0x138a: - case 0x138b: - temp = pas16_pit_in(port, pas16); + case 0x1789: + case 0x178b: + temp = pas16->midi_ctrl; + break; + case 0x178a: + case 0x1b8a: + temp = 0; + if (pas16->midi_uart_in) { + if ((pas16->midi_data == 0xaa) && (pas16->midi_ctrl & 0x04)) + temp = pas16->midi_data; + else { + temp = pas16->midi_queue[pas16->midi_r]; + if (pas16->midi_r != pas16->midi_w) { + pas16->midi_r++; + pas16->midi_r &= 0xff; + } + } + pas16->midi_stat &= ~0x04; + pas16_update_irq(pas16); + } + break; + + case 0x1b88: + temp = pas16->midi_stat; + break; + case 0x1b89: + temp = pas16->fifo_stat; break; case 0x2789: /*Board revision*/ - temp = 0; + temp = 0x00; break; case 0x7f89: - temp = pas16->enhancedscsi & ~1; + temp = pas16->enhancedscsi & ~0x01; break; case 0x8388: @@ -258,15 +296,18 @@ pas16_in(uint16_t port, void *priv) case 0x8389: temp = pas16->sys_conf_2; break; - case 0x838b: + case 0x838a: temp = pas16->sys_conf_3; break; - case 0x838c: + case 0x838b: temp = pas16->sys_conf_4; break; + case 0xbf88: + temp = pas16->waitstates; + break; case 0xef8b: - temp = 0x0c; + temp = 0x00; break; case 0xf388: @@ -274,11 +315,13 @@ pas16_in(uint16_t port, void *priv) break; case 0xf389: temp = pas16->io_conf_2; + pas16_log("pas16_in : set PAS DMA %i\n", pas16->dma); + break; + case 0xf38a: + temp = pas16->io_conf_3; + pas16_log("pas16_in : set PAS IRQ %i\n", pas16->irq); break; case 0xf38b: - temp = pas16->io_conf_3; - break; - case 0xf38c: temp = pas16->io_conf_4; break; @@ -294,7 +337,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*/ @@ -311,30 +354,28 @@ static void pas16_out(uint16_t port, uint8_t val, void *priv) { pas16_t *pas16 = (pas16_t *) priv; + pit_t *pit = (pit_t *) pas16->pit; pas16_log("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS, cpu_state.pc); - switch ((port - pas16->base) + 0x388) { + switch (port) { case 0x388: case 0x389: case 0x38a: case 0x38b: - pas16->opl.write((port - pas16->base) + 0x388, val, pas16->opl.priv); + pas16->opl.write(port, val, pas16->opl.priv); break; case 0xb88: pas16->audio_mixer = val; break; - case 0xb89: pas16->irq_stat &= ~val; break; - case 0xb8a: pas16_update(pas16); pas16->audiofilt = val; break; - case 0xb8b: - pas16->irq_ena = val; + pas16->irq_ena = val & 0x1f; break; case 0xf88: @@ -348,14 +389,39 @@ 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->midi_ctrl = val; + if ((val & 0x60) == 0x60) { + pas16->midi_uart_out = 0; + pas16->midi_uart_in = 0; + } else if (val & 0x18) { + pas16->midi_uart_out = 1; + } else if (val & 0x04) + pas16->midi_uart_in = 1; + else + pas16->midi_uart_out = 1; + + pas16_update_irq(pas16); + break; + case 0x178a: + case 0x1b8a: + pas16->midi_data = val; + pas16_log("UART OUT=%d.\n", pas16->midi_uart_out); + if (pas16->midi_uart_out) + midi_raw_out_byte(val); + break; + + case 0x1b88: + pas16->midi_stat = val; + pas16_update_irq(pas16); + break; + case 0x1b89: + pas16->fifo_stat = val; break; case 0x7f89: @@ -363,6 +429,11 @@ pas16_out(uint16_t port, uint8_t val, void *priv) break; case 0x8388: + if ((val & 0xc0) && !(pas16->sys_conf_1 & 0xc0)) { + pas16_log("Reset.\n"); + picintc(1 << pas16->irq); + val = 0x00; + } pas16->sys_conf_1 = val; break; case 0x8389: @@ -375,6 +446,10 @@ 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; @@ -385,8 +460,15 @@ pas16_out(uint16_t port, uint8_t val, void *priv) 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); + pas16->irq = val & 0x0f; + if (pas16->irq <= 6) { + pas16->irq++; + } else if ((pas16->irq > 6) && (pas16->irq < 0x0b)) + pas16->irq += 3; + else + pas16->irq += 4; + + pas16_log("pas16_out : set PAS IRQ %i, val=%02x\n", pas16->irq, val & 0x0f); break; case 0xf38b: pas16->io_conf_4 = val; @@ -398,193 +480,29 @@ 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: pas16->sb_irqdma = val; sb_dsp_setirq(&pas16->dsp, pas16_sb_irqs[(val >> 3) & 7]); sb_dsp_setdma8(&pas16->dsp, pas16_sb_dmas[(val >> 6) & 3]); - pas16_log("pas16_out : set SB IRQ %i DMA %i\n", pas16_sb_irqs[(val >> 3) & 7], pas16_sb_dmas[(val >> 6) & 3]); + pas16_log("pas16_out : set SB IRQ %i DMA %i.\n", pas16_sb_irqs[(val >> 3) & 7], pas16_sb_dmas[(val >> 6) & 3]); break; default: pas16_log("pas16_out : unknown %04X\n", port); } -#if 0 - if (cpu_state.pc == 0x80048CF3) { - if (output) - fatal("here\n"); - output = 3; - } -#endif -} - -static void -pas16_pit_out(uint16_t port, uint8_t val, void *priv) -{ - 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; - - 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; } static uint8_t @@ -597,31 +515,45 @@ static void pas16_pcm_poll(void *priv) { pas16_t *pas16 = (pas16_t *) priv; + pit_t *pit = (pit_t *) pas16->pit; + int data; + 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 & 0x02) { + if (pit->counters[0].l & 0xff) { + if (pas16->dma >= 5) + timer_advance_u64(&pas16->timer, (pit->counters[0].l & 0xff) * (PITCONST << 1ULL)); + else + timer_advance_u64(&pas16->timer, (pit->counters[0].l & 0xff) * PITCONST); + } else { + if (pas16->dma >= 5) + timer_advance_u64(&pas16->timer, 0x100 * (PITCONST << 1ULL)); + else + timer_advance_u64(&pas16->timer, 0x100 * PITCONST); + } } + pas16_update_irq(pas16); + pas16->irq_stat |= PAS16_INT_SAMP; - if (pas16->irq_ena & PAS16_INT_SAMP) + if (pas16->irq_ena & PAS16_INT_SAMP) { + pas16_log("INT SAMP.\n"); picint(1 << pas16->irq); + } /*Update sample rate counter*/ - if (pas16->pit.enable[1]) { - if (pas16->pcm_ctrl & PAS16_PCM_ENA) { - uint16_t temp; - + pas16_log("T1=%d, master bit 1=%x, counter0=%d, counter1=%d, pcm dma ena=%02x 16bit?=%02x.\n", pit->counters[1].enable, pit->counters[0].m & 0x02, pit->counters[0].l, pit->counters[1].l, pas16->pcm_ctrl & 0xc0, pas16->sys_conf_2 & PAS16_SC2_16BIT); + if (pit->counters[1].enable) { + if ((pas16->pcm_ctrl & (PAS16_PCM_ENA | PAS16_PCM_DMA_ENA))) { if (pas16->sys_conf_2 & PAS16_SC2_16BIT) { - temp = pas16_readdma(pas16) << 8; - temp |= pas16_readdma(pas16); - } else - temp = (pas16_readdma(pas16) ^ 0x80) << 8; + data = pas16_readdma(pas16) << 8; + data |= pas16_readdma(pas16); + temp = data; + } else { + data = pas16_readdma(pas16); + temp = (data ^ 0x80) << 8; + } if (pas16->sys_conf_2 & PAS16_SC2_MSBINV) temp ^= 0x8000; @@ -636,75 +568,120 @@ pas16_pcm_poll(void *priv) pas16->stereo_lr = !pas16->stereo_lr; } } - if (pas16->sys_conf_2 & PAS16_SC2_16BIT) - pas16->pit.c[1] -= 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]; - else - pas16->pit.c[1] += 0x10000; - } else { - pas16->pit.c[1] = -1; - pas16->pit.enable[1] = 0; + if (pas16->sys_conf_2 & PAS16_SC2_16BIT) { + pit->counters[1].lback -= 2; + if (!pit->counters[1].lback) { + if (pit->counters[1].m & 0x02) { + if (pit->counters[1].lback2 & 0xfffe) + pit->counters[1].lback = pit->counters[1].lback2 & 0xfffe; + else + pit->counters[1].lback = 0; + } else { + pit->counters[1].lback = 0; + pit->counters[1].enable = 0; + } + pas16_log("16-bit: New counter=%d, mode=%x.\n", pit->counters[1].lback, pit->counters[1].m & 0x03); + pas16->irq_stat |= PAS16_INT_PCM; + if (pas16->irq_ena & PAS16_INT_PCM) { + pas16_log("16-bit: INT PCM.\n"); + picint(1 << pas16->irq); + } } - - 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); - picint(1 << pas16->irq); + } else { + pit->counters[1].lback--; + if (!pit->counters[1].lback) { + if (pit->counters[1].m & 0x02) { + if (pit->counters[1].lback2 & 0xffff) + pit->counters[1].lback = pit->counters[1].lback2 & 0xffff; + else + pit->counters[1].lback = 0; + } else { + pit->counters[1].lback = 0; + pit->counters[1].enable = 0; + } + pas16_log("8-bit: New counter=%d, mode=%x.\n", pit->counters[1].lback, pit->counters[1].m & 0x03); + pas16->irq_stat |= PAS16_INT_PCM; + if (pas16->irq_ena & PAS16_INT_PCM) { + pas16_log("8-bit: INT PCM.\n"); + picint(1 << pas16->irq); + } } } } } +static void +pas16_pit_timer0(int new_out, UNUSED(int old_out), void *priv) +{ + pit_t *pit = (pit_t *)priv; + pas16_t *pas16 = (pas16_t *)pit->dev_priv; + + pas16_log("PAS16 pit timer0 out=%x, cnt0=%d, cnt1=%d.\n", new_out, pit->counters[0].l, pit->counters[1].l); + pit_ctr_set_clock(&pit->counters[0], new_out, pit); + pit->counters[1].enable = new_out; + if (!timer_is_enabled(&pas16->timer)) { + if (pas16->dma >= 5) + timer_set_delay_u64(&pas16->timer, (pit->counters[0].l & 0xff) * (PITCONST << 1ULL)); + else + timer_set_delay_u64(&pas16->timer, (pit->counters[0].l & 0xff) * PITCONST); + } +} + static void pas16_out_base(UNUSED(uint16_t port), uint8_t val, void *priv) { pas16_t *pas16 = (pas16_t *) priv; - io_removehandler((pas16->base - 0x388) + 0x0388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - 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); - io_removehandler((pas16->base - 0x388) + 0x1788, 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); - io_removehandler((pas16->base - 0x388) + 0xbf88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xe388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xe788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xeb88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xef88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xf388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xf788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xfb88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xff88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + for (uint32_t addr = 0x000; addr < 0x10000; addr += 0x400) { + if (addr != 0x1000) { + io_removehandler(pas16->base + addr, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler(pas16->base + addr, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + } + } + pit_handler(0, pas16->base + 0x1000, 0x0004, pas16->pit); + pit_handler(1, pas16->base + 0x1000, 0x0004, pas16->pit); pas16->base = val << 2; - pas16_log("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); - io_sethandler((pas16->base - 0x388) + 0x1788, 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); - io_sethandler((pas16->base - 0x388) + 0xbf88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xe388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xe788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xeb88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xef88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xf388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xf788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xfb88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xff88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); +static void +pas16_input_msg(void *priv, uint8_t *msg, uint32_t len) +{ + pas16_t *pas16 = (pas16_t *) priv; + + if (pas16->sysex) + return; + + if (pas16->midi_uart_in) { + pas16->midi_stat |= 0x04; + + for (uint32_t i = 0; i < len; i++) { + pas16->midi_queue[pas16->midi_w++] = msg[i]; + pas16->midi_w &= 0xff; + } + + pas16_update_irq(pas16); + } +} + +static int +pas16_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort) +{ + pas16_t *pas16 = (pas16_t *) priv; + + if (abort) { + pas16->sysex = 0; + return 0; + } + pas16->sysex = 1; + for (uint32_t i = 0; i < len; i++) { + if (pas16->midi_r == pas16->midi_w) + return (len - i); + pas16->midi_queue[pas16->midi_w++] = buffer[i]; + pas16->midi_w &= 0xff; + } + pas16->sysex = 0; + return 0; } static void @@ -758,15 +735,33 @@ pas16_init(UNUSED(const device_t *info)) memset(pas16, 0, sizeof(pas16_t)); fm_driver_get(FM_YMF262, &pas16->opl); + sb_dsp_set_real_opl(&pas16->dsp, 1); 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->pit->dev_priv = pas16; + pas16->irq = 10; + pas16->dma = 3; + pas16->base = 0x0388; io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16); + 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); - timer_add(&pas16->pit.timer[0], pas16_pcm_poll, pas16, 0); + timer_add(&pas16->timer, pas16_pcm_poll, pas16, 0); sound_add_handler(pas16_get_buffer, pas16); music_add_handler(pas16_get_music_buffer, pas16); + if (device_get_config_int("receive_input")) + midi_in_handler(1, pas16_input_msg, pas16_input_sysex, pas16); + return pas16; } @@ -778,10 +773,28 @@ 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 = "receive_input", + .description = "Receive input (PAS16 MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .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 +802,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 },