diff --git a/src/dma.c b/src/dma.c index b7c4b4863..ebe75bba6 100644 --- a/src/dma.c +++ b/src/dma.c @@ -42,6 +42,7 @@ static int dma_wp[2]; static uint8_t dma_stat; static uint8_t dma_stat_rq; static uint8_t dma_stat_rq_pc; +static uint8_t dma_stat_adv_pend; static uint8_t dma_command[2]; static uint8_t dma_req_is_soft; static uint8_t dma_advanced; @@ -457,6 +458,7 @@ dma_read(uint16_t addr, UNUSED(void *priv)) { int channel = (addr >> 1) & 3; uint8_t temp; + int count; switch (addr & 0xf) { case 0: @@ -473,10 +475,13 @@ dma_read(uint16_t addr, UNUSED(void *priv)) case 5: case 7: /*Count registers*/ dma_wp[0] ^= 1; + count = dma[channel].cc/* + 1*/; + // if (count > dma[channel].cb) + // count = 0x0000; if (dma_wp[0]) - temp = dma[channel].cc & 0xff; + temp = count & 0xff; else - temp = dma[channel].cc >> 8; + temp = count >> 8; return temp; case 8: /*Status register*/ @@ -529,8 +534,10 @@ dma_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) case 8: /*Control register*/ dma_command[0] = val; +#ifdef ENABLE_DMA_LOG if (val & 0x01) pclog("[%08X:%04X] Memory-to-memory enable\n", CS, cpu_state.pc); +#endif return; case 9: /*Request register */ @@ -538,7 +545,9 @@ dma_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) if (val & 4) { dma_stat_rq_pc |= (1 << channel); if ((channel == 0) && (dma_command[0] & 0x01)) { +#ifdef ENABLE_DMA_LOG pclog("Memory to memory transfer start\n"); +#endif dma_mem_to_mem_transfer(); } else dma_block_transfer(channel); @@ -767,9 +776,16 @@ static uint8_t dma16_read(uint16_t addr, UNUSED(void *priv)) { int channel = ((addr >> 2) & 3) + 4; - uint8_t temp; +#ifdef ENABLE_DMA_LOG + uint16_t port = addr; +#endif + uint8_t ret; + int count; addr >>= 1; + + ret = dmaregs[1][addr & 0xf]; + switch (addr & 0xf) { case 0: case 2: @@ -778,41 +794,53 @@ dma16_read(uint16_t addr, UNUSED(void *priv)) dma_wp[1] ^= 1; if (dma_ps2.is_ps2) { if (dma_wp[1]) - return (dma[channel].ac); - return ((dma[channel].ac >> 8) & 0xff); - } - if (dma_wp[1]) - return ((dma[channel].ac >> 1) & 0xff); - return ((dma[channel].ac >> 9) & 0xff); + ret = (dma[channel].ac); + else + ret = ((dma[channel].ac >> 8) & 0xff); + } else if (dma_wp[1]) + ret = ((dma[channel].ac >> 1) & 0xff); + else + ret = ((dma[channel].ac >> 9) & 0xff); + break; case 1: case 3: case 5: case 7: /*Count registers*/ dma_wp[1] ^= 1; + count = dma[channel].cc/* + 1*/; + // if (count > dma[channel].cb) + // count = 0x0000; if (dma_wp[1]) - temp = dma[channel].cc & 0xff; + ret = count & 0xff; else - temp = dma[channel].cc >> 8; - return temp; + ret = count >> 8; + break; case 8: /*Status register*/ - temp = (dma_stat_rq_pc & 0xf0); - temp |= dma_stat >> 4; + ret = (dma_stat_rq_pc & 0xf0); + ret |= dma_stat >> 4; dma_stat &= ~0xf0; - return temp; + break; default: break; } - return (dmaregs[1][addr & 0xf]); +#ifdef ENABLE_DMA_LOG + pclog("dma16_read(%08X) = %02X\n", port, ret); +#endif + + return ret; } static void dma16_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) { int channel = ((addr >> 2) & 3) + 4; +#ifdef ENABLE_DMA_LOG + pclog("dma16_write(%08X, %02X)\n", addr, val); +#endif addr >>= 1; dmaregs[1][addr & 0xf] = val; @@ -1076,11 +1104,12 @@ dma_reset(void) dma[c].transfer_mode = (c & 4) ? 0x0202 : 0x0101; } - dma_stat = 0x00; - dma_stat_rq = 0x00; - dma_stat_rq_pc = 0x00; - dma_req_is_soft = 0; - dma_advanced = 0; + dma_stat = 0x00; + dma_stat_rq = 0x00; + dma_stat_rq_pc = 0x00; + dma_stat_adv_pend = 0x00; + dma_req_is_soft = 0; + dma_advanced = 0; memset(dma_buffer, 0x00, sizeof(dma_buffer)); memset(dma16_buffer, 0x00, sizeof(dma16_buffer)); @@ -1401,23 +1430,130 @@ int dma_channel_readable(int channel) { dma_t *dma_c = &dma[channel]; + int ret = 1; if (channel < 4) { if (dma_command[0] & 0x04) - return 0; + ret = 0; } else { if (dma_command[1] & 0x04) - return 0; + ret = 0; } if (!(dma_e & (1 << channel))) - return 0; + ret = 0; if ((dma_m & (1 << channel)) && !dma_req_is_soft) - return 0; + ret = 0; if ((dma_c->mode & 0xC) != 8) - return 0; + ret = 0; - return 1; + return ret; +} + +int +dma_channel_read_only(int channel) +{ + dma_t *dma_c = &dma[channel]; + uint16_t temp; + + if (channel < 4) { + if (dma_command[0] & 0x04) + return (DMA_NODATA); + } else { + if (dma_command[1] & 0x04) + return (DMA_NODATA); + } + + if (!(dma_e & (1 << channel))) + return (DMA_NODATA); + if ((dma_m & (1 << channel)) && !dma_req_is_soft) + return (DMA_NODATA); + if ((dma_c->mode & 0xC) != 8) + return (DMA_NODATA); + + dma_channel_advance(channel); + + if (!dma_at && !channel) + refreshread(); + + if (!dma_c->size) { + temp = _dma_read(dma_c->ac, dma_c); + + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac--; + else if (dma_advanced) + dma_retreat(dma_c); + else + dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac - 1) & 0xffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac++; + else if (dma_advanced) + dma_advance(dma_c); + else + dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac + 1) & 0xffff); + } + } else { + temp = _dma_readw(dma_c->ac, dma_c); + + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac -= 2; + else if (dma_advanced) + dma_retreat(dma_c); + else + dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac += 2; + else if (dma_advanced) + dma_advance(dma_c); + else + dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac + 2) & 0x1ffff); + } + } + + dma_stat_rq |= (1 << channel); + + dma_stat_adv_pend |= (1 << channel); + + return temp; +} + +int +dma_channel_advance(int channel) +{ + dma_t *dma_c = &dma[channel]; + int tc = 0; + + if (dma_stat_adv_pend & (1 << channel)) { + dma_c->cc--; + if (dma_c->cc < 0) { + if (dma_advanced && (dma_c->sg_status & 1) && !(dma_c->sg_status & 6)) + dma_sg_next_addr(dma_c); + else { + tc = 1; + if (dma_c->mode & 0x10) { /*Auto-init*/ + dma_c->cc = dma_c->cb; + dma_c->ac = dma_c->ab; + } else + dma_m |= (1 << channel); + dma_stat |= (1 << channel); + } + } + + if (tc) { + if (dma_advanced && (dma_c->sg_status & 1) && ((dma_c->sg_command & 0xc0) == 0x40)) { + picint(1 << 13); + dma_c->sg_status |= 8; + } + } + + dma_stat_adv_pend &= ~(1 << channel); + } + + return tc; } int @@ -1442,6 +1578,9 @@ dma_channel_read(int channel) if ((dma_c->mode & 0xC) != 8) return (DMA_NODATA); + if (dma_stat_adv_pend & (1 << channel)) + dma_channel_advance(channel); + if (!dma_at && !channel) refreshread(); @@ -1573,6 +1712,8 @@ dma_channel_write(int channel, uint16_t val) dma_stat_rq |= (1 << channel); + dma_stat_adv_pend &= ~(1 << channel); + dma_c->cc--; if (dma_c->cc < 0) { if (dma_advanced && (dma_c->sg_status & 1) && !(dma_c->sg_status & 6)) diff --git a/src/include/86box/dma.h b/src/include/86box/dma.h index ff0dc0b5d..23ce04898 100644 --- a/src/include/86box/dma.h +++ b/src/include/86box/dma.h @@ -96,6 +96,8 @@ extern void writedma2(uint8_t temp); extern int dma_get_drq(int channel); extern void dma_set_drq(int channel, int set); +extern int dma_channel_read_only(int channel); +extern int dma_channel_advance(int channel); extern int dma_channel_read(int channel); extern int dma_channel_write(int channel, uint16_t val); diff --git a/src/pit.c b/src/pit.c index 340cdccde..7ae50f413 100644 --- a/src/pit.c +++ b/src/pit.c @@ -246,9 +246,9 @@ ctr_tick(ctr_t *ctr, void *priv) } else ctr->count -= (ctr->newcount ? 1 : 2); if (ctr->count < 0) { + ctr_set_out(ctr, 0, pit); ctr_load_count(ctr); ctr->state = 3; - ctr_set_out(ctr, 0, pit); } else if (ctr->newcount) ctr->newcount = 0; } @@ -265,9 +265,9 @@ ctr_tick(ctr_t *ctr, void *priv) } else ctr->count -= (ctr->newcount ? 3 : 2); if (ctr->count < 0) { + ctr_set_out(ctr, 1, pit); ctr_load_count(ctr); ctr->state = 2; - ctr_set_out(ctr, 1, pit); } else if (ctr->newcount) ctr->newcount = 0; } @@ -443,8 +443,6 @@ pit_ctr_set_gate(void *data, int counter_id, int gate) int old = ctr->gate; uint8_t mode = ctr->m & 3; - ctr->gate = gate; - switch (mode) { case 1: case 2: @@ -470,6 +468,8 @@ pit_ctr_set_gate(void *data, int counter_id, int gate) default: break; } + + ctr->gate = gate; } static __inline void diff --git a/src/pit_fast.c b/src/pit_fast.c index 0da671bfe..e986600ee 100644 --- a/src/pit_fast.c +++ b/src/pit_fast.c @@ -133,7 +133,7 @@ pitf_read_timer(ctrf_t *ctr) read = 0; if (read > 0x10000) read = 0x10000; - if (ctr->m == 3) + if ((ctr->m == 3) && ctr->using_timer) read <<= 1; return read; } @@ -191,6 +191,8 @@ pitf_ctr_load(ctrf_t *ctr, void *priv) ctr->count = l; if (ctr->using_timer) timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * ctr->pit_const)); + else + ctr->newcount = (l & 1); pitf_ctr_set_out(ctr, 1, pit); ctr->thit = 0; } @@ -269,6 +271,8 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate, void *priv) ctr->count = l; if (ctr->using_timer) timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * ctr->pit_const)); + else + ctr->newcount = (l & 1); pitf_ctr_set_out(ctr, 1, pit); ctr->thit = 0; } @@ -330,14 +334,23 @@ pitf_over(ctrf_t *ctr, void *priv) case 3: /*Square wave mode*/ if (ctr->out) { pitf_ctr_set_out(ctr, 0, pit); - ctr->count += (l >> 1); - if (ctr->using_timer) + if (ctr->using_timer) { + ctr->count += (l >> 1); timer_advance_u64(&ctr->timer, (uint64_t) ((l >> 1) * ctr->pit_const)); + } else { + ctr->count += l; + ctr->newcount = (l & 1); + } } else { pitf_ctr_set_out(ctr, 1, pit); ctr->count += ((l + 1) >> 1); - if (ctr->using_timer) + if (ctr->using_timer) { + ctr->count += (l >> 1); timer_advance_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * ctr->pit_const)); + } else { + ctr->count += l; + ctr->newcount = (l & 1); + } } #if 0 if (!t) @@ -631,7 +644,12 @@ pitf_ctr_clock(void *data, int counter_id) if (ctr->using_timer) return; - ctr->count -= (ctr->m == 3) ? 2 : 1; + if ((ctr->m == 3) && ctr->newcount) { + ctr->count -= ctr->out ? 1 : 3; + ctr->newcount = 0; + } else + ctr->count -= (ctr->m == 3) ? 2 : 1; + if (!ctr->count) pitf_over(ctr, pit); } diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 0a5c046b7..9812ced64 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -154,10 +154,14 @@ typedef struct pas16_t { uint16_t base; uint16_t new_base; + uint16_t sb_compat_base; + uint16_t mpu401_base; + uint16_t dma8_dat; + uint16_t ticks; uint16_t pcm_dat_l; uint16_t pcm_dat_r; - int16_t pcm_buffer[2][SOUNDBUFLEN * 2]; + int32_t pcm_buffer[2][SOUNDBUFLEN * 2]; int pos; int midi_r; @@ -371,7 +375,11 @@ pas16_in(uint16_t port, void *priv) break; case 0xec03: - ret = pas16->type ? 0x0c : 0x04; +#ifdef NEWER_PAS16 + ret = pas16->type ? 0x0c : 0x06; +#else + ret = pas16->type ? 0x0f : 0x06; +#endif break; case 0xf000: @@ -390,7 +398,13 @@ pas16_in(uint16_t port, void *priv) break; case 0xf400: - ret = pas16->compat; + ret = (pas16->compat & 0xf3); + + if (pas16->dsp.sb_irqm8 || pas16->dsp.sb_irqm16 || pas16->dsp.sb_irqm401) + ret |= 0x04; + + if (pas16->mpu->mode == M_UART) + ret |= 0x08; break; case 0xf401: ret = pas16->compat_base; @@ -402,11 +416,13 @@ pas16_in(uint16_t port, void *priv) case 0xfc00: /* Board model */ /* PAS16 or PASPlus */ - ret = pas16->type ? 0x04 : 0x01; + ret = pas16->type ? 0x0c : 0x01; break; case 0xfc03: /* Master mode read */ /* AT bus, XT/AT timing */ - ret = pas16->type ? (0x20 | 0x10 | 0x01) : (0x10 | 0x01); + ret = 0x11; + if (pas16->type) + ret |= 0x20; break; default: @@ -458,7 +474,6 @@ pas16_reset_pcm(void *priv) pas16->pcm_ctrl = 0x00; pas16->stereo_lr = 0; - pas16->dma8_ff = 0; pas16->irq_stat &= 0xd7; @@ -490,6 +505,7 @@ pas16_reset_regs(void *priv) pitf_ctr_set_gate(pit, 1, 0); pas16_reset_pcm(pas16); + pas16->dma8_ff = 0; pas16->irq_ena = 0x00; pas16->irq_stat = 0x00; @@ -522,6 +538,11 @@ pas16_reset(void *priv) pas16_io_handler(pas16, 1); pas16->new_base = 0x0388; + + pas16->sb_compat_base = 0x0220; + pas16->compat = 0x02; + pas16->compat_base = 0x02; + sb_dsp_setaddr(&pas16->dsp, pas16->sb_compat_base); } static void @@ -546,25 +567,25 @@ pas16_out(uint16_t port, uint8_t val, void *priv) break; case 0x0801: pas16->irq_stat &= ~val; + if (!(pas16->irq_stat & 0x1f)) + picintc(1 << pas16->irq); break; case 0x0802: + pas16_update(pas16); + + pitf_ctr_set_gate(pas16->pit, 1, !!(val & 0x80)); + pitf_ctr_set_gate(pas16->pit, 0, !!(val & 0x40)); + + pas16->stereo_lr = 0; + pas16->dma8_ff = 0; + if ((val & 0x20) && !(pas16->audiofilt & 0x20)) { pas16_log("Reset.\n"); - val = 0x20; pas16_reset_regs(pas16); } - pas16_update(pas16); - pitf_ctr_set_gate(pas16->pit, 0, 1); - pitf_ctr_set_gate(pas16->pit, 1, 1); - // pas16->pit->counters[0].gate = !!(val & 0x40); - // pas16->pit->counters[0].enabled = !!(val & 0x40); - // pas16->pit->counters[1].gate = !!(val & 0x80); - // pas16->pit->counters[1].enabled = !!(val & 0x80); - pas16->stereo_lr = 0; - pas16->irq_stat &= 0xdf; - pas16->dma8_ff = 0; pas16->audiofilt = val; + if (val & 0x1f) { pas16->filter = 1; switch (val & 0x1f) { @@ -595,6 +616,10 @@ pas16_out(uint16_t port, uint8_t val, void *priv) break; case 0x0803: pas16->irq_ena = val & 0x1f; + pas16->irq_stat &= ((val & 0x1f) | 0xe0); + + if (!(pas16->irq_stat & 0x1f)) + picintc(1 << pas16->irq); break; case 0x0c00: @@ -607,7 +632,7 @@ pas16_out(uint16_t port, uint8_t val, void *priv) if ((val & PAS16_PCM_ENA) && !(pas16->pcm_ctrl & PAS16_PCM_ENA)) { /* Guess */ pas16->stereo_lr = 0; - pas16->irq_stat &= 0xdf; + pas16->irq_stat &= 0xd7; /* Needed for 8-bit DMA to work correctly on a 16-bit DMA channel. */ pas16->dma8_ff = 0; } @@ -713,10 +738,10 @@ pas16_out(uint16_t port, uint8_t val, void *priv) break; case 0xf400: - pas16->compat = val; + pas16->compat = val & 0xf3; pas16_log("PCM compression is now %sabled\n", (val & 0x10) ? "en" : "dis"); if (pas16->compat & 0x02) - sb_dsp_setaddr(&pas16->dsp, ((pas16->compat_base & 0xf) << 4) | 0x200); + sb_dsp_setaddr(&pas16->dsp, pas16->sb_compat_base); else sb_dsp_setaddr(&pas16->dsp, 0); if (pas16->compat & 0x01) @@ -726,14 +751,17 @@ pas16_out(uint16_t port, uint8_t val, void *priv) break; case 0xf401: pas16->compat_base = val; + pas16->sb_compat_base = ((pas16->compat_base & 0xf) << 4) | 0x200; + pas16_log("SB Compatibility base: %04X\n", pas16->sb_compat_base); if (pas16->compat & 0x02) - sb_dsp_setaddr(&pas16->dsp, ((pas16->compat_base & 0xf) << 4) | 0x200); + sb_dsp_setaddr(&pas16->dsp, pas16->sb_compat_base); if (pas16->compat & 0x01) mpu401_change_addr(pas16->mpu, ((pas16->compat_base & 0xf0) | 0x300)); break; case 0xf802: pas16->sb_irqdma = val; + mpu401_setirq(pas16->mpu, pas16_sb_irqs[val & 7]); 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], @@ -774,18 +802,33 @@ pas16_out(uint16_t port, uint8_t val, void *priv) alongside the previous sample; - A 16-bit sample always takes two ctr_clock() ticks. */ +static uint16_t +pas16_dma_channel_read(pas16_t *pas16, int channel) +{ + int status; + uint16_t ret; + + if (pas16->pcm_ctrl & PAS16_PCM_DMA_ENA) { + if (pas16->dma >= 5) { + dma_channel_advance(pas16->dma); + status = dma_channel_read_only(pas16->dma); + } else + status = dma_channel_read(pas16->dma); + ret = (status == DMA_NODATA) ? 0x0000 : (status & 0xffff); + } else + ret = 0x0000; + + return ret; +} + static uint16_t pas16_dma_readb(pas16_t *pas16, uint8_t timer1_ticks) { uint16_t ret; - if (pas16->pcm_ctrl & PAS16_PCM_DMA_ENA) - ret = dma_channel_read(pas16->dma); - else - ret = 0x0000; + ret = pas16_dma_channel_read(pas16, pas16->dma); - for (uint8_t i = 0; i < timer1_ticks; i++) - pitf_ctr_clock(pas16->pit, 1); + pas16->ticks += timer1_ticks; return ret; } @@ -795,16 +838,14 @@ pas16_dma_readw(pas16_t *pas16, uint8_t timer1_ticks) { uint16_t ret; - if (pas16->pcm_ctrl & PAS16_PCM_DMA_ENA) { - ret = dma_channel_read(pas16->dma); + if (pas16->dma >= 5) + ret = pas16_dma_channel_read(pas16, pas16->dma); + else { + ret = pas16_dma_channel_read(pas16, pas16->dma); + ret |= (pas16_dma_channel_read(pas16, pas16->dma) << 8); + } - if (pas16->dma < 5) - ret |= (dma_channel_read(pas16->dma) << 8); - } else - ret = 0x0000; - - for (uint8_t i = 0; i < timer1_ticks; i++) - pitf_ctr_clock(pas16->pit, 1); + pas16->ticks += timer1_ticks; return ret; } @@ -812,20 +853,19 @@ pas16_dma_readw(pas16_t *pas16, uint8_t timer1_ticks) static uint16_t pas16_readdmab(pas16_t *pas16) { - static uint16_t temp; uint16_t ret; if (pas16->dma >= 5) { if (pas16->dma8_ff) - temp >>= 8; + pas16->dma8_dat >>= 8; else - temp = pas16_dma_readb(pas16, 1); + pas16->dma8_dat = pas16_dma_readb(pas16, 1); pas16->dma8_ff = !pas16->dma8_ff; } else - temp = pas16_dma_readb(pas16, 1); + pas16->dma8_dat = pas16_dma_readb(pas16, 1); - ret = ((temp & 0xff) ^ 0x80) << 8; + ret = ((pas16->dma8_dat & 0xff) ^ 0x80) << 8; return ret; } @@ -844,8 +884,9 @@ static uint16_t pas16_readdmaw_stereo(pas16_t *pas16) { uint16_t ret; + uint16_t ticks = (pas16->sys_conf_1 & 0x02) ? (1 + (pas16->dma < 5)) : 2; - ret = pas16_dma_readw(pas16, 2); + ret = pas16_dma_readw(pas16, ticks); return ret; } @@ -895,17 +936,17 @@ pas16_pit_timer0(int new_out, UNUSED(int old_out), void *priv) pas16_t *pas16 = (pas16_t *) pit->dev_priv; uint16_t temp; - pas16_update(pas16); + if (!pas16->pit->counters[0].gate) + return; + + if (!dma_channel_readable(pas16->dma)) + return; + pas16_update_irq(pas16); - pas16->irq_stat |= PAS16_INT_SAMP; - if (pas16->irq_ena & PAS16_INT_SAMP) { - pas16_log("INT SAMP.\n"); - picint(1 << pas16->irq); - } + if (((pas16->pcm_ctrl & PAS16_PCM_ENA) == PAS16_PCM_ENA) && (pit->counters[1].m & 2) && new_out) { + pas16->ticks = 0; - if (((pas16->pcm_ctrl & PAS16_PCM_AND_DMA_ENA) == PAS16_PCM_AND_DMA_ENA) && - dma_channel_readable(pas16->dma) && (pit->counters[1].m & 2) && new_out) { if (pas16->pcm_ctrl & PAS16_PCM_MONO) { temp = pas16_readdma_mono(pas16); @@ -929,7 +970,22 @@ pas16_pit_timer0(int new_out, UNUSED(int old_out), void *priv) pas16->irq_stat = (pas16->irq_stat & 0xdf) | (pas16->stereo_lr << 5); } } - } + + if (pas16->ticks) { + for (uint8_t i = 0; i < pas16->ticks; i++) + pitf_ctr_clock(pas16->pit, 1); + + pas16->ticks = 0; + } + + pas16->irq_stat |= PAS16_INT_SAMP; + if (pas16->irq_ena & PAS16_INT_SAMP) { + pas16_log("INT SAMP.\n"); + picint(1 << pas16->irq); + } + + pas16_update(pas16); + } } static void @@ -938,16 +994,15 @@ pas16_pit_timer1(int new_out, UNUSED(int old_out), void *priv) pitf_t *pit = (pitf_t * )priv; pas16_t *pas16 = (pas16_t *) pit->dev_priv; + if (!pas16->pit->counters[1].gate) + return; + /* At new_out = 0, it's in the counter reload phase. */ if ((pas16->pcm_ctrl & PAS16_PCM_ENA) && (pit->counters[1].m & 2) && new_out) { if (pas16->irq_ena & PAS16_INT_PCM) { pas16->irq_stat |= PAS16_INT_PCM; pas16_log("pas16_pcm_poll : cause IRQ %i %02X\n", pas16->irq, 1 << pas16->irq); picint(1 << pas16->irq); - - pas16->stereo_lr = 0; - pas16->irq_stat &= 0xdf; - pas16->dma8_ff = 0; } } } @@ -1019,14 +1074,19 @@ pas16_update(pas16_t *pas16) for (; pas16->pos < sound_pos_global; pas16->pos++) { pas16->pcm_buffer[0][pas16->pos] = 0; pas16->pcm_buffer[1][pas16->pos] = 0; +#ifdef CROSS_CHANNEL if (pas16->pcm_ctrl & 0x08) - pas16->pcm_buffer[0][pas16->pos] += pas16->pcm_dat_l; + pas16->pcm_buffer[0][pas16->pos] += (int16_t) pas16->pcm_dat_l; if (pas16->pcm_ctrl & 0x04) - pas16->pcm_buffer[0][pas16->pos] += pas16->pcm_dat_r; + pas16->pcm_buffer[0][pas16->pos] += (int16_t) pas16->pcm_dat_r; if (pas16->pcm_ctrl & 0x02) - pas16->pcm_buffer[1][pas16->pos] += pas16->pcm_dat_l; + pas16->pcm_buffer[1][pas16->pos] += (int16_t) pas16->pcm_dat_l; if (pas16->pcm_ctrl & 0x01) - pas16->pcm_buffer[1][pas16->pos] += pas16->pcm_dat_r; + pas16->pcm_buffer[1][pas16->pos] += (int16_t) pas16->pcm_dat_r; +#else + pas16->pcm_buffer[0][pas16->pos] += (int16_t) pas16->pcm_dat_l; + pas16->pcm_buffer[1][pas16->pos] += (int16_t) pas16->pcm_dat_r; +#endif } } } @@ -1039,11 +1099,11 @@ pas16_get_buffer(int32_t *buffer, int len, void *priv) sb_dsp_update(&pas16->dsp); pas16_update(pas16); for (int c = 0; c < len * 2; c++) { - buffer[c] += (int16_t) (sb_iir(0, c & 1, (double) pas16->dsp.buffer[c]) / 1.3) / 2; + buffer[c] += (int32_t) (sb_iir(0, c & 1, (double) pas16->dsp.buffer[c]) / 1.3) / 2; if (pas16->filter) - buffer[c] += (low_fir_pas16(0, c & 1, (double) pas16->pcm_buffer[c & 1][c >> 1])) / 2.0; + buffer[c] += (low_fir_pas16(0, c & 1, (double) pas16->pcm_buffer[c & 1][c >> 1]) / 1.3) / 2.0; else - buffer[c] += (pas16->pcm_buffer[c & 1][c >> 1] / 2); + buffer[c] += ((pas16->pcm_buffer[c & 1][c >> 1] / 1.3) / 2); } pas16->pos = 0; @@ -1086,9 +1146,11 @@ pas16_init(const device_t *info) 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")); + mpu401_init(pas16->mpu, 0, 0, M_INTELLIGENT, device_get_config_int("receive_input401")); sb_dsp_set_mpu(&pas16->dsp, pas16->mpu); + pas16->sb_compat_base = 0x0000; + io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16); pas16->this_id = 0xbc + pas16_next;