mirror of
https://github.com/86Box/86Box.git
synced 2025-01-22 17:22:25 -05:00
More Pro Audio Spectrum 16 work, closes #4313.
This commit is contained in:
parent
fcbbae181f
commit
f93692a045
5 changed files with 322 additions and 99 deletions
195
src/dma.c
195
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))
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue