- Assorted N64 SP/DP/CPU comms accuracy fixes. [Ryan Holtz]

This commit is contained in:
Ryan Holtz 2012-02-19 00:44:19 +00:00
parent 444ded2016
commit a286574bb1
4 changed files with 84 additions and 35 deletions

View File

@ -109,6 +109,8 @@ public:
void poll_reset_button(bool button); void poll_reset_button(bool button);
UINT32 dp_clock;
protected: protected:
// device-level overrides // device-level overrides
virtual void device_start(); virtual void device_start();
@ -169,7 +171,6 @@ private:
int sp_dma_count; int sp_dma_count;
int sp_dma_skip; int sp_dma_skip;
UINT32 sp_semaphore; UINT32 sp_semaphore;
UINT32 dp_clock;
// Disk Drive (DD) registers and functions // Disk Drive (DD) registers and functions
UINT32 dd_buffer[256]; UINT32 dd_buffer[256];

View File

@ -204,7 +204,6 @@ void n64_periphs::device_reset()
{ {
// CIC-NUS-6105 // CIC-NUS-6105
//printf("CIC-NUS-6105 detected\n"); //printf("CIC-NUS-6105 detected\n");
pif_ram[0x24] = 0x00; pif_ram[0x24] = 0x00;
pif_ram[0x25] = 0x02; pif_ram[0x25] = 0x02;
pif_ram[0x26] = 0x91; pif_ram[0x26] = 0x91;
@ -361,10 +360,12 @@ void n64_periphs::check_interrupts()
{ {
if (mi_intr_mask & mi_interrupt) if (mi_intr_mask & mi_interrupt)
{ {
//printf("Asserting IRQ, %02x : %02x\n", mi_intr_mask, mi_interrupt);
cputag_set_input_line(machine(), "maincpu", INPUT_LINE_IRQ0, ASSERT_LINE); cputag_set_input_line(machine(), "maincpu", INPUT_LINE_IRQ0, ASSERT_LINE);
} }
else else
{ {
//printf("Deasserting IRQ, %02x : %02x\n", mi_intr_mask, mi_interrupt);
cputag_set_input_line(machine(), "maincpu", INPUT_LINE_IRQ0, CLEAR_LINE); cputag_set_input_line(machine(), "maincpu", INPUT_LINE_IRQ0, CLEAR_LINE);
} }
} }
@ -485,12 +486,14 @@ WRITE32_MEMBER( n64_periphs::rdram_reg_w )
void n64_periphs::sp_dma(int direction) void n64_periphs::sp_dma(int direction)
{ {
sp_dma_length++; UINT32 length = sp_dma_length + 1;
if ((sp_dma_length & 7) != 0)
if ((length & 7) != 0)
{ {
sp_dma_length = (sp_dma_length + 7) & ~7; length = (length + 7) & ~7;
} }
//printf("Length %08x Skip %08x Count %08x\n", length, sp_dma_skip, sp_dma_count);
if (sp_mem_addr & 0x3) if (sp_mem_addr & 0x3)
{ {
sp_mem_addr = sp_mem_addr & ~3; sp_mem_addr = sp_mem_addr & ~3;
@ -500,11 +503,11 @@ void n64_periphs::sp_dma(int direction)
sp_dram_addr = sp_dram_addr & ~7; sp_dram_addr = sp_dram_addr & ~7;
} }
if ((sp_mem_addr & 0xfff) + (sp_dma_length) > 0x1000) if ((sp_mem_addr & 0xfff) + (length) > 0x1000)
{ {
//printf("sp_dma: dma out of memory area: %08X, %08X\n", sp_mem_addr, sp_dma_length); //printf("sp_dma: dma out of memory area: %08X, %08X, %08X\n", sp_mem_addr, sp_dram_addr, length);
//fatalerror("sp_dma: dma out of memory area: %08X, %08X\n", sp_mem_addr, sp_dma_length); //fatalerror("sp_dma: dma out of memory area: %08X, %08X\n", sp_mem_addr, length);
sp_dma_length = 0x1000 - (sp_mem_addr & 0xfff); length = 0x1000 - (sp_mem_addr & 0xfff);
} }
UINT32 *sp_mem[2] = { rsp_dmem, rsp_imem }; UINT32 *sp_mem[2] = { rsp_dmem, rsp_imem };
@ -516,13 +519,13 @@ void n64_periphs::sp_dma(int direction)
UINT32 src = (sp_dram_addr & 0x007fffff) >> 2; UINT32 src = (sp_dram_addr & 0x007fffff) >> 2;
UINT32 dst = (sp_mem_addr & 0x1fff) >> 2; UINT32 dst = (sp_mem_addr & 0x1fff) >> 2;
for(int i = 0; i < sp_dma_length / 4; i++) for(int i = 0; i < length / 4; i++)
{ {
sp_mem[(dst + i) >> 10][(dst + i) & 0x3ff] = rdram[src + i]; sp_mem[(dst + i) >> 10][(dst + i) & 0x3ff] = rdram[src + i];
} }
sp_mem_addr += sp_dma_length; sp_mem_addr += length;
sp_dram_addr += sp_dma_length; sp_dram_addr += length;
sp_mem_addr += sp_dma_skip; sp_mem_addr += sp_dma_skip;
} }
@ -534,13 +537,13 @@ void n64_periphs::sp_dma(int direction)
UINT32 src = (sp_mem_addr & 0x1fff) >> 2; UINT32 src = (sp_mem_addr & 0x1fff) >> 2;
UINT32 dst = (sp_dram_addr & 0x007fffff) >> 2; UINT32 dst = (sp_dram_addr & 0x007fffff) >> 2;
for(int i = 0; i < sp_dma_length / 4; i++) for(int i = 0; i < length / 4; i++)
{ {
rdram[dst + i] = sp_mem[(src + i) >> 10][(src + i) & 0x3ff]; rdram[dst + i] = sp_mem[(src + i) >> 10][(src + i) & 0x3ff];
} }
sp_mem_addr += sp_dma_length; sp_mem_addr += length;
sp_dram_addr += sp_dma_length; sp_dram_addr += length;
sp_dram_addr += sp_dma_skip; sp_dram_addr += sp_dma_skip;
} }
@ -617,20 +620,47 @@ UINT32 n64_periphs::sp_reg_r(UINT32 offset)
break; break;
case 0x20/4: // DP_CMD_START case 0x20/4: // DP_CMD_START
{
n64_state *state = machine().driver_data<n64_state>();
ret = state->m_rdp->GetStartReg();
break;
}
case 0x24/4: // DP_CMD_END case 0x24/4: // DP_CMD_END
{
n64_state *state = machine().driver_data<n64_state>();
ret = state->m_rdp->GetEndReg();
break;
}
case 0x28/4: // DP_CMD_CURRENT case 0x28/4: // DP_CMD_CURRENT
{
n64_state *state = machine().driver_data<n64_state>();
ret = state->m_rdp->GetCurrentReg();
break;
}
case 0x34/4: // DP_CMD_BUSY case 0x34/4: // DP_CMD_BUSY
case 0x38/4: // DP_CMD_PIPE_BUSY case 0x38/4: // DP_CMD_PIPE_BUSY
case 0x3c/4: // DP_CMD_TMEM_BUSY case 0x3c/4: // DP_CMD_TMEM_BUSY
break; break;
case 0x2c/4: // DP_CMD_STATUS case 0x2c/4: // DP_CMD_STATUS
ret = 0x88; {
n64_state *state = machine().driver_data<n64_state>();
ret = state->m_rdp->GetStatusReg();
break; break;
}
case 0x30/4: // DP_CMD_CLOCK case 0x30/4: // DP_CMD_CLOCK
ret = ++dp_clock; {
if(!(machine().driver_data<n64_state>()->m_rdp->GetStatusReg() & DP_STATUS_FREEZE))
{
dp_clock += 13;
ret = dp_clock;
}
break; break;
}
case 0x40000/4: // PC case 0x40000/4: // PC
ret = cpu_get_reg(rspcpu, RSP_PC) & 0x00000fff; ret = cpu_get_reg(rspcpu, RSP_PC) & 0x00000fff;
@ -641,7 +671,7 @@ UINT32 n64_periphs::sp_reg_r(UINT32 offset)
break; break;
} }
//printf("sp_reg_r %08x = %08x\n", offset * 4, ret); //printf("%08x sp_reg_r %08x = %08x\n", (UINT32)cpu_get_reg(maincpu, MIPS3_PC), offset * 4, ret);
return ret; return ret;
} }
@ -652,8 +682,7 @@ READ32_DEVICE_HANDLER( n64_sp_reg_r )
void n64_periphs::sp_reg_w(UINT32 offset, UINT32 data, UINT32 mem_mask) void n64_periphs::sp_reg_w(UINT32 offset, UINT32 data, UINT32 mem_mask)
{ {
//printf("sp_reg_w %08x %08x %08x\n", offset * 4, data, mem_mask); //printf("%08x sp_reg_w %08x %08x %08x\n", (UINT32)cpu_get_reg(maincpu, MIPS3_PC), offset * 4, data, mem_mask);
//device_yield(machine().device("maincpu"));
if ((offset & 0x10000) == 0) if ((offset & 0x10000) == 0)
{ {
@ -719,6 +748,7 @@ void n64_periphs::sp_reg_w(UINT32 offset, UINT32 data, UINT32 mem_mask)
if(!(oldstatus & (RSP_STATUS_BROKE | RSP_STATUS_HALT))) if(!(oldstatus & (RSP_STATUS_BROKE | RSP_STATUS_HALT)))
{ {
cpu_set_reg(rspcpu, RSP_STEPCNT, 1 ); cpu_set_reg(rspcpu, RSP_STEPCNT, 1 );
device_yield(machine().device("maincpu"));
} }
} }
if (data & 0x00000080) if (data & 0x00000080)
@ -847,6 +877,7 @@ void dp_full_sync(running_machine &machine)
READ32_DEVICE_HANDLER( n64_dp_reg_r ) READ32_DEVICE_HANDLER( n64_dp_reg_r )
{ {
n64_state *state = device->machine().driver_data<n64_state>(); n64_state *state = device->machine().driver_data<n64_state>();
n64_periphs *periphs = device->machine().device<n64_periphs>("rcp");
UINT32 ret = 0; UINT32 ret = 0;
switch (offset) switch (offset)
{ {
@ -866,20 +897,31 @@ READ32_DEVICE_HANDLER( n64_dp_reg_r )
ret = state->m_rdp->GetStatusReg(); ret = state->m_rdp->GetStatusReg();
break; break;
case 0x10/4: // DP_CLOCK_REG
{
if(!(state->m_rdp->GetStatusReg() & DP_STATUS_FREEZE))
{
periphs->dp_clock += 13;
ret = periphs->dp_clock;
}
break;
}
default: default:
logerror("dp_reg_r: %08X, %08X at %08X\n", offset, mem_mask, cpu_get_pc(device)); logerror("dp_reg_r: %08X, %08X at %08X\n", offset, mem_mask, cpu_get_pc(device));
break; break;
} }
//printf("dp_reg_r %08x = %08x\n", offset, ret); //printf("%08x dp_reg_r %08x = %08x\n", (UINT32)cpu_get_reg(device->machine().device("rsp"), RSP_PC), offset, ret);
return ret; return ret;
} }
WRITE32_DEVICE_HANDLER( n64_dp_reg_w ) WRITE32_DEVICE_HANDLER( n64_dp_reg_w )
{ {
n64_state *state = device->machine().driver_data<n64_state>(); n64_state *state = device->machine().driver_data<n64_state>();
n64_periphs *periphs = device->machine().device<n64_periphs>("rcp");
//printf("dp_reg_w %08x %08x %08x\n", offset, data, mem_mask); //printf("%08x dp_reg_w %08x %08x %08x\n", (UINT32)cpu_get_reg(device->machine().device("rsp"), RSP_PC), offset, data, mem_mask);
switch (offset) switch (offset)
{ {
case 0x00/4: // DP_START_REG case 0x00/4: // DP_START_REG
@ -903,7 +945,8 @@ WRITE32_DEVICE_HANDLER( n64_dp_reg_w )
if (data & 0x00000004) current_status &= ~DP_STATUS_FREEZE; if (data & 0x00000004) current_status &= ~DP_STATUS_FREEZE;
if (data & 0x00000008) current_status |= DP_STATUS_FREEZE; if (data & 0x00000008) current_status |= DP_STATUS_FREEZE;
if (data & 0x00000010) current_status &= ~DP_STATUS_FLUSH; if (data & 0x00000010) current_status &= ~DP_STATUS_FLUSH;
if (data & 0x00000020) current_status |= DP_STATUS_FLUSH; if (data & 0x00000020) current_status |= DP_STATUS_FLUSH;
if (data & 0x00000200) periphs->dp_clock = 0;
state->m_rdp->SetStatusReg(current_status); state->m_rdp->SetStatusReg(current_status);
break; break;
} }

View File

@ -1169,6 +1169,7 @@ UINT32 n64_rdp::ReadData(UINT32 address)
{ {
if (m_status & 0x1) // XBUS_DMEM_DMA enabled if (m_status & 0x1) // XBUS_DMEM_DMA enabled
{ {
//printf("%08x\n", rsp_dmem[(address & 0xfff) / 4]);
return rsp_dmem[(address & 0xfff) / 4]; return rsp_dmem[(address & 0xfff) / 4];
} }
else else
@ -3579,9 +3580,14 @@ void n64_rdp::CmdNoOp(UINT32 w1, UINT32 w2)
void n64_rdp::ProcessList() void n64_rdp::ProcessList()
{ {
UINT32 length = m_end - m_current; INT32 length = m_end - m_current;
if(length < 0)
{
m_current = m_end;
return;
}
//printf("%08x %d\n", m_end, length);
// load command data // load command data
for(int i = 0; i < length; i += 4) for(int i = 0; i < length; i += 4)
{ {
@ -3861,14 +3867,7 @@ SCREEN_UPDATE_RGB32(n64)
if (n64->vi_blank) if (n64->vi_blank)
{ {
for (int j = 0; j < state->m_rdp->visarea.max_y; j++) bitmap.fill(0, state->m_rdp->visarea);
{
UINT32 *d = &bitmap.pix32(j);
for (int i = 0; i < state->m_rdp->MiscState.FBWidth; i++)
{
d[BYTE_XOR_BE(i)] = 0;
}
}
return 0; return 0;
} }

View File

@ -437,10 +437,16 @@ class n64_rdp : public poly_manager<UINT32, rdp_poly_state, 8, 32000>
void SetMachine(running_machine& machine) { m_machine = &machine; } void SetMachine(running_machine& machine) { m_machine = &machine; }
// CPU-visible registers // CPU-visible registers
void SetStartReg(UINT32 val) { m_start = val; } void SetStartReg(UINT32 val)
{
m_start = val;
}
UINT32 GetStartReg() const { return m_start; } UINT32 GetStartReg() const { return m_start; }
void SetEndReg(UINT32 val) { m_end = val; } void SetEndReg(UINT32 val)
{
m_end = val;
}
UINT32 GetEndReg() const { return m_end; } UINT32 GetEndReg() const { return m_end; }
void SetCurrentReg(UINT32 val) { m_current = val; } void SetCurrentReg(UINT32 val) { m_current = val; }