-jak_care: Hooked up spg2xx software wave-in channel, hooked up muls and fir_mov ops in unsp. Allows voice to work. [Ryan Holtz, Tahg, smf]

This commit is contained in:
mooglyguy 2020-02-08 18:33:52 +01:00
parent 8e98c7e905
commit 3e6ace480a
6 changed files with 94 additions and 33 deletions

View File

@ -228,6 +228,7 @@ void unsp_device::device_start()
m_drcuml->symbol_add(&m_core->m_r[REG_PC], sizeof(uint32_t), "PC");
m_drcuml->symbol_add(&m_core->m_enable_irq, sizeof(uint32_t), "IRQE");
m_drcuml->symbol_add(&m_core->m_enable_fiq, sizeof(uint32_t), "FIQE");
m_drcuml->symbol_add(&m_core->m_fir_move, sizeof(uint32_t), "FIR_MOV");
m_drcuml->symbol_add(&m_core->m_irq, sizeof(uint32_t), "IRQ");
m_drcuml->symbol_add(&m_core->m_fiq, sizeof(uint32_t), "FIQ");
m_drcuml->symbol_add(&m_core->m_sb, sizeof(uint32_t), "SB");
@ -251,9 +252,10 @@ void unsp_device::device_start()
state_add(UNSP_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%06X");
state_add(UNSP_IRQ_EN, "IRQE", m_core->m_enable_irq).formatstr("%1u");
state_add(UNSP_FIQ_EN, "FIQE", m_core->m_enable_fiq).formatstr("%1u");
state_add(UNSP_FIR_MOV_EN, "FIR_MOV", m_core->m_fir_move).formatstr("%1u");
state_add(UNSP_IRQ, "IRQ", m_core->m_irq).formatstr("%1u");
state_add(UNSP_FIQ, "FIQ", m_core->m_fiq).formatstr("%1u");
state_add(UNSP_SB, "SB", m_core->m_sb).formatstr("%1u");
state_add(UNSP_SB, "SB", m_core->m_sb).formatstr("%1X");
#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
state_add(UNSP_LOG_OPS,"LOG", m_log_ops).formatstr("%1u");
#endif
@ -264,6 +266,7 @@ void unsp_device::device_start()
save_item(NAME(m_core->m_r));
save_item(NAME(m_core->m_enable_irq));
save_item(NAME(m_core->m_enable_fiq));
save_item(NAME(m_core->m_fir_move));
save_item(NAME(m_core->m_irq));
save_item(NAME(m_core->m_fiq));
save_item(NAME(m_core->m_curirq));
@ -307,6 +310,7 @@ void unsp_device::device_reset()
m_core->m_r[REG_PC] = read16(0xfff7);
m_core->m_enable_irq = 0;
m_core->m_enable_fiq = 0;
m_core->m_fir_move = 0;
m_core->m_irq = 0;
m_core->m_fiq = 0;
}
@ -389,10 +393,10 @@ void unsp_device::state_import(const device_state_entry &entry)
/*****************************************************************************/
void unsp_device::update_nzsc(uint32_t value, uint16_t r0, uint16_t r1)
void unsp_device::update_nzsc(uint32_t value, int32_t svalue)
{
m_core->m_r[REG_SR] &= ~(UNSP_N | UNSP_Z | UNSP_S | UNSP_C);
if (int16_t(r0) < int16_t(~r1))
if (svalue < 0)
m_core->m_r[REG_SR] |= UNSP_S;
if (BIT(value, 15))
m_core->m_r[REG_SR] |= UNSP_N;

View File

@ -60,6 +60,7 @@ enum
UNSP_IRQ_EN,
UNSP_FIQ_EN,
UNSP_FIR_MOV_EN,
UNSP_IRQ,
UNSP_FIQ,
#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
@ -164,9 +165,10 @@ protected:
struct internal_unsp_state
{
uint32_t m_r[16]; // why are these 32-bit? they're 16-bit regs? (changing to uint16_t causes crashes tho, so something is depending on this)
uint32_t m_r[16]; // required to be 32 bits due to DRC
uint32_t m_enable_irq;
uint32_t m_enable_fiq;
uint32_t m_fir_move;
uint32_t m_irq;
uint32_t m_fiq;
uint32_t m_curirq;
@ -214,6 +216,7 @@ protected:
void execute_fxxx_100_group(uint16_t op);
virtual void execute_extended_group(uint16_t op);
virtual void execute_exxx_group(uint16_t op);
void execute_muls(const uint16_t rd, const uint16_t rs, const uint16_t size);
void unimplemented_opcode(uint16_t op);
void unimplemented_opcode(uint16_t op, uint16_t ximm);
void unimplemented_opcode(uint16_t op, uint16_t ximm, uint16_t ximm_2);
@ -231,7 +234,7 @@ protected:
uint16_t pop(uint32_t *reg);
void update_nz(uint32_t value);
void update_nzsc(uint32_t value, uint16_t r0, uint16_t r1);
void update_nzsc(uint32_t value, int32_t svalue);
bool do_basic_alu_ops(const uint16_t& op0, uint32_t& lres, uint16_t& r0, uint16_t& r1, uint32_t& r2, bool update_flags);
private:

View File

@ -60,15 +60,11 @@ inline void unsp_device::execute_fxxx_000_group(uint16_t op)
// MUL us ( signed * unsigned )
// MUL 1 1 1 1* r r r 0* 0 0 0 0 1 r r r (** = sign bits, fixed here)
const uint16_t opa = (op >> 9) & 7;
const uint16_t opb = op & 7;
const uint16_t rd = (op >> 9) & 7;
const uint16_t rs = op & 7;
m_core->m_icount -= 12;
uint32_t lres = m_core->m_r[opa] * m_core->m_r[opb];
if (m_core->m_r[opb] & 0x8000)
{
lres -= m_core->m_r[opa] << 16;
}
m_core->m_r[REG_R4] = lres >> 16;
int32_t lres = (int32_t)(uint32_t)m_core->m_r[rd] * (int32_t)(int16_t)m_core->m_r[rs];
m_core->m_r[REG_R4] = (uint16_t)(lres >> 16);
m_core->m_r[REG_R3] = (uint16_t)lres;
return;
@ -290,15 +286,13 @@ void unsp_12_device::execute_fxxx_101_group(uint16_t op)
return;
case 0xf144: case 0xf344: case 0xf544: case 0xf744: case 0xf944: case 0xfb44: case 0xfd44: case 0xff44:
logerror("unimplemented: fir_mov on\n");
m_core->m_icount -= 1;
//unimplemented_opcode(op); // generalplus_gpac800 games do this on startup
m_core->m_fir_move = 1;
return;
case 0xf145: case 0xf345: case 0xf545: case 0xf745: case 0xf945: case 0xfb45: case 0xfd45: case 0xff45:
logerror("unimplemented: fir_mov off\n");
m_core->m_icount -= 1;
//unimplemented_opcode(op); // generalplus_gpac800 games do this on startup
m_core->m_fir_move = 0;
return;
case 0xf161: case 0xf361: case 0xf561: case 0xf761: case 0xf961: case 0xfb61: case 0xfd61: case 0xff61:
@ -392,13 +386,11 @@ void unsp_device::execute_fxxx_101_group(uint16_t op)
return;
case 0xf144: case 0xf344: case 0xf544: case 0xf744: case 0xf944: case 0xfb44: case 0xfd44: case 0xff44:
logerror("fir_mov on (shouldn't exist on 1.0, is this 1.2 or does it act as a NOP?)\n");
//unimplemented_opcode(op); // jak_care triggers this, which again strongly suggests that everything we have is 1.2 or above even if most new features are unused
m_core->m_fir_move = 1;
return;
case 0xf145: case 0xf345: case 0xf545: case 0xf745: case 0xf945: case 0xfb45: case 0xfd45: case 0xff45:
logerror("fir_mov off (shouldn't exist on 1.0, is this 1.2 or does it act as a NOP?)\n");
//unimplemented_opcode(op); // jak_care triggers this, see above
m_core->m_fir_move = 0;
return;
case 0xf160: case 0xf360: case 0xf560: case 0xf760: case 0xf960: case 0xfb60: case 0xfd60: case 0xff60:
@ -458,8 +450,45 @@ inline void unsp_device::execute_fxxx_110_group(uint16_t op)
// MULS 1 1 1 1* r r r 1* 1 0*s s s r r r (1* = sign bit, 1* = sign bit 0* = upper size bit)
// MULS ss with upper size bit not set
//unimplemented_opcode(op);
//return;
const uint16_t size = ((op >> 3) & 7) ? ((op >> 3) & 7) : 16;
const uint16_t rd = (op >> 9) & 7;
const uint16_t rs = op & 7;
execute_muls(rd, rs, size);
}
inline void unsp_device::execute_muls(const uint16_t rd, const uint16_t rs, const uint16_t size)
{
const uint32_t rdv = m_core->m_r[rd];
const uint32_t rsv = m_core->m_r[rs];
int64_t lres = 0;
uint16_t values[16];
for (uint16_t i = 0; i < size; i++)
{
values[i] = read16(rdv + i);
const uint16_t rhs = read16(rsv + i);
uint32_t tres = values[i] * rhs;
if (values[i] & 0x8000)
{
tres -= rhs << 16;
}
if (rhs & 0x8000)
{
tres -= values[i] << 16;
}
lres += (int64_t)(int32_t)tres;
}
m_core->m_sb = 0;
if (m_core->m_fir_move)
{
for (uint16_t i = size - 1; i > 0; i--)
{
write16(rdv + i, values[i - 1]);
}
}
m_core->m_r[rd] += size;
m_core->m_r[rs] += size;
m_core->m_r[REG_R4] = (uint16_t)(lres >> 16);
m_core->m_r[REG_R3] = (uint16_t)lres;
}
inline void unsp_device::execute_fxxx_111_group(uint16_t op)
@ -472,8 +501,9 @@ inline void unsp_device::execute_fxxx_111_group(uint16_t op)
// MULS 1 1 1 1* r r r 1* 1 1*s s s r r r (1* = sign bit, 1* = sign bit 1* = upper size bit)
// MULS ss with upper size bit set.
//unimplemented_opcode(op);
//return;
const uint16_t rd = (op >> 9) & 7;
const uint16_t rs = op & 7;
execute_muls(rd, rs, ((op >> 3) & 7) + 8);
}
void unsp_device::execute_fxxx_group(uint16_t op)

View File

@ -281,40 +281,46 @@ void unsp_device::execute_remaining(const uint16_t op)
bool unsp_device::do_basic_alu_ops(const uint16_t &op0, uint32_t &lres, uint16_t &r0, uint16_t &r1, uint32_t &r2, bool update_flags)
{
int32_t sres = 0;
switch (op0)
{
case 0x00: // Add
{
lres = r0 + r1;
sres = (int16_t)r0 + (int16_t)r1;
if (update_flags)
update_nzsc(lres, r0, r1);
update_nzsc(lres, sres);
break;
}
case 0x01: // Add w/ carry
{
uint32_t c = (m_core->m_r[REG_SR] & UNSP_C) ? 1 : 0;
lres = r0 + r1 + c;
sres = (int16_t)r0 + (int16_t)r1 + (int16_t)c;
if (update_flags)
update_nzsc(lres, r0, r1);
update_nzsc(lres, sres);
break;
}
case 0x02: // Subtract
lres = r0 + (uint16_t)(~r1) + uint32_t(1);
sres = (int16_t)r0 - (int16_t)r1;
if (update_flags)
update_nzsc(lres, r0, ~r1);
update_nzsc(lres, sres);
break;
case 0x03: // Subtract w/ carry
{
uint32_t c = (m_core->m_r[REG_SR] & UNSP_C) ? 1 : 0;
lres = r0 + (uint16_t)(~r1) + c;
sres = (int16_t)r0 - ((int16_t)r1 - (int16_t)c);
if (update_flags)
update_nzsc(lres, r0, ~r1);
update_nzsc(lres, sres);
break;
}
case 0x04: // Compare
lres = r0 + (uint16_t)(~r1) + uint32_t(1);
sres = (int16_t)r0 - (int16_t)r1;
if (update_flags)
update_nzsc(lres, r0, ~r1);
update_nzsc(lres, sres);
return false;
case 0x06: // Negate
lres = -r1;

View File

@ -265,6 +265,14 @@ offs_t unsp_disassembler::disassemble_fxxx_101_group(std::ostream& stream, offs_
util::stream_format(stream, "int fiq,irq");
return UNSP_DASM_OK;
case 0xf144: case 0xf344: case 0xf544: case 0xf744: case 0xf944: case 0xfb44: case 0xfd44: case 0xff44:
util::stream_format(stream, "fir_mov on");
return UNSP_DASM_OK;
case 0xf145: case 0xf345: case 0xf545: case 0xf745: case 0xf945: case 0xfb45: case 0xfd45: case 0xff45:
util::stream_format(stream, "fir_mov off");
return UNSP_DASM_OK;
case 0xf160: case 0xf360: case 0xf560: case 0xf760: case 0xf960: case 0xfb60: case 0xfd60: case 0xff60:
case 0xf168: case 0xf368: case 0xf568: case 0xf768: case 0xf968: case 0xfb68: case 0xfd68: case 0xff68:
case 0xf170: case 0xf370: case 0xf570: case 0xf770: case 0xf970: case 0xfb70: case 0xfd70: case 0xff70:

View File

@ -67,7 +67,6 @@ sunplus_gcm394_audio_device::sunplus_gcm394_audio_device(const machine_config &m
{
}
void spg2xx_audio_device::device_start()
{
m_audio_beat = timer_alloc(TIMER_BEAT);
@ -636,11 +635,13 @@ WRITE16_MEMBER(spg2xx_audio_device::audio_ctrl_w)
case AUDIO_WAVE_IN_L:
LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Wave In (L) / FIFO Write Data: %04x\n", data);
m_stream->update();
m_audio_ctrl_regs[offset] = data;
break;
case AUDIO_WAVE_IN_R:
LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Wave In (R) / Software Channel FIFO IRQ Control: %04x\n", data);
m_stream->update();
m_audio_ctrl_regs[offset] = data;
break;
@ -945,6 +946,11 @@ void spg2xx_audio_device::sound_stream_update(sound_stream &stream, stream_sampl
}
}
if (m_audio_ctrl_regs[AUDIO_WAVE_IN_L])
left_total += (int32_t)(m_audio_ctrl_regs[AUDIO_WAVE_IN_L] - 0x8000);
if (m_audio_ctrl_regs[AUDIO_WAVE_IN_R])
right_total += (int32_t)(m_audio_ctrl_regs[AUDIO_WAVE_IN_R] - 0x8000);
switch (get_vol_sel())
{
case 0: // 1/16
@ -958,8 +964,12 @@ void spg2xx_audio_device::sound_stream_update(sound_stream &stream, stream_sampl
right_total >>= 2;
break;
}
*out_l++ = (left_total * (int16_t)m_audio_ctrl_regs[AUDIO_MAIN_VOLUME]) >> 7;
*out_r++ = (right_total * (int16_t)m_audio_ctrl_regs[AUDIO_MAIN_VOLUME]) >> 7;
int32_t left_final = (int16_t)((left_total * (int16_t)m_audio_ctrl_regs[AUDIO_MAIN_VOLUME]) >> 7);
int32_t right_final = (int16_t)((right_total * (int16_t)m_audio_ctrl_regs[AUDIO_MAIN_VOLUME]) >> 7);
*out_l++ = (int16_t)left_final;
*out_r++ = (int16_t)right_final;
}
}