More Pro Audio Spectrum 16 work, closes #4313.
This commit is contained in:
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))
|
||||
|
||||
Reference in New Issue
Block a user