From 778cd2bc4686b40d75af3e46cb7f6f2c8e2b7ce2 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 21 Mar 2024 22:00:48 +0100 Subject: [PATCH] Refactor PAS16 code (Audio/MIDI/PIT) This should make it work once and for all after many years of being broken/not working. --- src/include/86box/pit.h | 3 +- src/pit.c | 40 ++-- src/sound/snd_pas16.c | 478 ++++++++++++++++++++-------------------- 3 files changed, 261 insertions(+), 260 deletions(-) diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index 078694633..d9bce667d 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -56,6 +56,8 @@ 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 *priv); @@ -70,7 +72,6 @@ typedef struct PIT { uint8_t ctrl; void *dev_priv; - void (*dev_timer)(void *priv); } pit_t; extern pit_t *ext_pit; diff --git a/src/pit.c b/src/pit.c index 4f64d40c1..20baf3f66 100644 --- a/src/pit.c +++ b/src/pit.c @@ -103,6 +103,7 @@ ctr_set_out(ctr_t *ctr, int out, void *priv) if (ctr->out_func != NULL) ctr->out_func(out, ctr->out, pit); + ctr->out = out; } @@ -354,7 +355,7 @@ ctr_load(ctr_t *ctr) if (ctr->load_func != NULL) ctr->load_func(ctr->m, ctr->l ? ctr->l : 0x10000); - pclog("Counter loaded, state = %i, gate = %i, latch = %i\n", ctr->state, ctr->gate, ctr->latch); + pit_log("Counter loaded, state = %i, gate = %i, latch = %i\n", ctr->state, ctr->gate, ctr->latch); } static __inline void @@ -393,7 +394,7 @@ ctr_latch_count(ctr_t *ctr) break; } - pclog("rm = %x, latched counter = %04X\n", ctr->rm & 0x03, ctr->rl & 0xffff); + pit_log("rm = %x, latched counter = %04X\n", ctr->rm & 0x03, ctr->rl & 0xffff); } uint16_t @@ -522,9 +523,6 @@ pit_timer_over(void *priv) for (uint8_t i = 0; i < 3; i++) 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); } @@ -536,7 +534,7 @@ pit_write(uint16_t addr, uint8_t val, void *priv) ctr_t *ctr; if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) - pclog("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); + pit_log("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); switch (addr & 3) { case 3: /* control */ @@ -553,7 +551,7 @@ pit_write(uint16_t addr, uint8_t val, void *priv) if (val & 8) ctr_latch_count(&dev->counters[2]); if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) - pclog("PIT %i: Initiated readback command\n", t); + pit_log("PIT %i: Initiated readback command\n", t); } if (!(val & 0x10)) { if (val & 2) @@ -571,7 +569,7 @@ pit_write(uint16_t addr, uint8_t val, void *priv) if (!(dev->ctrl & 0x30)) { ctr_latch_count(ctr); if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) - pclog("PIT %i: Initiated latched read, %i bytes latched\n", + pit_log("PIT %i: Initiated latched read, %i bytes latched\n", t, ctr->latched); } else { ctr->ctrl = val; @@ -585,12 +583,12 @@ pit_write(uint16_t addr, uint8_t val, void *priv) ctr->state = 0; if (ctr->latched) { if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) - pclog("PIT %i: Reload while counter is latched\n", t); + pit_log("PIT %i: Reload while counter is latched\n", t); ctr->rl--; } 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); + pit_log("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out); } } break; @@ -606,12 +604,20 @@ 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, 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, dev); ctr_load(ctr); @@ -620,13 +626,17 @@ pit_write(uint16_t addr, uint8_t val, void *priv) case 0x83: if (ctr->wm & 0x80) { ctr->l = (ctr->l & 0x00ff) | (val << 8); + ctr->lback = ctr->l; + ctr->lback2 = 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); + 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; + ctr->lback = ctr->l; + ctr->lback2 = 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); + 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, dev); @@ -763,7 +773,7 @@ pit_read(uint16_t addr, void *priv) } if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) - pclog("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); + pit_log("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); return ret; } @@ -890,15 +900,13 @@ 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, pit_read, NULL, NULL, pit_write, NULL, NULL, dev); } - dev->dev_priv = NULL; - dev->dev_timer = NULL; - return dev; } diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 32879cd1e..d8187cf0f 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -137,25 +137,29 @@ typedef struct pas16_t { uint8_t midi_ctrl; uint8_t midi_stat; uint8_t midi_data; - uint8_t midi_fifo[16]; + 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; - int midi_uart_out; - pit_t *pit; } pas16_t; 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 }; @@ -167,7 +171,8 @@ enum { enum { PAS16_PCM_MONO = 0x20, - PAS16_PCM_ENA = 0x40 + PAS16_PCM_ENA = 0x40, + PAS16_PCM_DMA_ENA = 0x80 }; enum { @@ -197,124 +202,51 @@ pas16_log(const char *fmt, ...) # define pas16_log(fmt, ...) #endif +static uint8_t +pas16_in(uint16_t port, void *priv); static void -pas16_update_midi_irqs(pas16_t *pas16) +pas16_out(uint16_t port, uint8_t val, void *priv); + +static void +pas16_update_irq(pas16_t *pas16) { - int irq = 0; - - pas16->irq_stat &= ~PAS16_INT_MIDI; - - if ((pas16->uart_status & 0x18) || (dev->uart_status & 0x04)) { + if (pas16->midi_uart_out && (pas16->midi_stat & 0x18)) { pas16->irq_stat |= PAS16_INT_MIDI; - irq = 1; + if (pas16->irq_ena & PAS16_INT_MIDI) + picint(1 << pas16->irq); } - - 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; + 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 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) { 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; - temp |= 0x01; + temp = pas16->irq_ena | 0x20; + pas16_log("IRQ Mask read=%02x.\n", temp); break; case 0xf8a: @@ -322,19 +254,36 @@ pas16_in(uint16_t port, void *priv) break; case 0x1789: - temp = 0; + case 0x178b: + temp = pas16->midi_ctrl; break; case 0x178a: - temp = pas16->uart_data; - pas16_set_rx_irq(pas16, 0); + 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->uart_status; + temp = pas16->midi_stat; + break; + case 0x1b89: + temp = pas16->fifo_stat; break; case 0x2789: /*Board revision*/ - temp = 0; + temp = 0x00; break; case 0x7f89: @@ -347,19 +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: @@ -367,9 +315,11 @@ 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_4; @@ -396,7 +346,7 @@ pas16_in(uint16_t port, void *priv) default: break; } - pclog("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS, cpu_state.pc); + pas16_log("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS, cpu_state.pc); return temp; } @@ -405,30 +355,27 @@ pas16_out(uint16_t port, uint8_t val, void *priv) { pas16_t *pas16 = (pas16_t *) priv; 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) { + pas16_log("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS, cpu_state.pc); + 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: @@ -448,29 +395,33 @@ pas16_out(uint16_t port, uint8_t val, void *priv) case 0x1789: case 0x178b: - pas16->uart_ctrl = val; - + pas16->midi_ctrl = val; if ((val & 0x60) == 0x60) { - /* Reset TX */ - pas16_set_tx_irq(pas16, 1); + 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; - /* Software reset */ - pas16_reset_fifo(pas16); - } else { - pas16_set_tx_irq(pas16, 1); - - pas16_update_tx_irq(pas16); - pas16_update_rx_irq(pas16); - } + pas16_update_irq(pas16); break; - case 0x178a: - midi_raw_out_byte(val); - pas16_set_tx_irq(pas16, 1); + 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->uart_status = val; + pas16->midi_stat = val; + pas16_update_irq(pas16); + break; + case 0x1b89: + pas16->fifo_stat = val; break; case 0x7f89: @@ -478,9 +429,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); + if ((val & 0xc0) && !(pas16->sys_conf_1 & 0xc0)) { + pas16_log("Reset.\n"); + picintc(1 << pas16->irq); + val = 0x00; } pas16->sys_conf_1 = val; break; @@ -504,12 +456,19 @@ pas16_out(uint16_t port, uint8_t val, void *priv) case 0xf389: pas16->io_conf_2 = val; pas16->dma = pas16_dmas[val & 0x7]; - pclog("pas16_out : set PAS DMA %i\n", pas16->dma); + pas16_log("pas16_out : set PAS DMA %i\n", pas16->dma); break; case 0xf38a: pas16->io_conf_3 = val; - pas16->irq = pas16_irqs[val & 0xf]; - pclog("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; @@ -538,32 +497,12 @@ pas16_out(uint16_t port, uint8_t val, void *priv) 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: - pclog("pas16_out : unknown %04X\n", port); + 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_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) & 7; - - pas16_set_rx_irq(pas16, 1); - } else - pas16_set_rx_irq(pas16, 0); } static uint8_t @@ -572,39 +511,49 @@ pas16_readdma(pas16_t *pas16) return dma_channel_read(pas16->dma); } - static void pas16_pcm_poll(void *priv) { - pit_t *pit = (pit_t *)priv; - pas16_t *pas16 = (pas16_t *) pit->dev_priv; + pas16_t *pas16 = (pas16_t *) priv; + pit_t *pit = (pit_t *) pas16->pit; + int data; uint16_t temp = 0x0000; - pas16_update(pas16); - 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)); + 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); - else - picintc(1 << pas16->irq); + } /*Update sample rate counter*/ - pas16_log("Enable (t1) = %d.\n", pit->counters[1].enable); + 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) { + 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; @@ -619,41 +568,63 @@ pas16_pcm_poll(void *priv) pas16->stereo_lr = !pas16->stereo_lr; } } - if (pas16->sys_conf_2 & PAS16_SC2_16BIT) - pit->counters[1].rl -= 2; - else - 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 - pit->counters[1].rl = 0; - } else { - pit->counters[1].enable = 0; - pit->counters[1].rl = 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); + } + } + } 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); + } } - - 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) { - 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) +pas16_pit_timer0(int new_out, UNUSED(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; + 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 @@ -661,48 +632,56 @@ 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); - 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); - 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; - 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); - 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); - 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 @@ -756,6 +735,7 @@ 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)); @@ -763,20 +743,25 @@ pas16_init(UNUSED(const device_t *info)) sb_dsp_set_mpu(&pas16->dsp, pas16->mpu); pas16->pit = device_add(&i8254_ext_io_device); - - pas16->midi_uart_out = 1; + 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); - pas16->pit->dev_priv = pas16; - pas16->pit->dev_timer = pas16_pcm_poll; + + 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; } @@ -796,6 +781,13 @@ static const device_config_t pas16_config[] = { .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 } };