3rdParty: backport some patches from simple64 to mupen64plus-core

This commit is contained in:
Rosalie Wanders
2025-02-06 21:24:41 +01:00
parent 572792a1c8
commit f6264336f9
14 changed files with 253 additions and 118 deletions
@@ -199,6 +199,7 @@ typedef void (*ptr_ViWidthChanged)(void);
typedef void (*ptr_ReadScreen2)(void *dest, int *width, int *height, int front);
typedef void (*ptr_SetRenderingCallback)(void (*callback)(int));
typedef void (*ptr_ResizeVideoOutput)(int width, int height);
typedef void (*ptr_FullSync)(void);
#if defined(M64P_PLUGIN_PROTOTYPES)
EXPORT void CALL ChangeWindow(void);
EXPORT int CALL InitiateGFX(GFX_INFO Gfx_Info);
@@ -212,6 +213,7 @@ EXPORT void CALL ViWidthChanged(void);
EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front);
EXPORT void CALL SetRenderingCallback(void (*callback)(int));
EXPORT void CALL ResizeVideoOutput(int width, int height);
EXPORT void CALL FullSync(void);
#endif
/* frame buffer plugin spec extension */
+2 -1
View File
@@ -129,6 +129,7 @@ void init_device(struct device* dev,
{ &dev->dd, dd_mecha_int_handler }, /* DD MECHA */
{ &dev->dd, dd_bm_int_handler }, /* DD BM */
{ &dev->dd, dd_dv_int_handler }, /* DD DRIVE */
{ &dev->sp, rsp_task_event },
};
#define R(x) read_ ## x
@@ -141,7 +142,7 @@ void init_device(struct device* dev,
/* memory map */
{ A(MM_RDRAM_DRAM, 0x3efffff), M64P_MEM_RDRAM, { &dev->rdram, RW(rdram_dram) } },
{ A(MM_RDRAM_REGS, 0xfffff), M64P_MEM_RDRAMREG, { &dev->rdram, RW(rdram_regs) } },
{ A(MM_RSP_MEM, 0xffff), M64P_MEM_RSPMEM, { &dev->sp, RW(rsp_mem) } },
{ A(MM_RSP_MEM, 0x3ffff), M64P_MEM_RSPMEM, { &dev->sp, RW(rsp_mem) } },
{ A(MM_RSP_REGS, 0xffff), M64P_MEM_RSPREG, { &dev->sp, RW(rsp_regs) } },
{ A(MM_RSP_REGS2, 0xffff), M64P_MEM_RSP, { &dev->sp, RW(rsp_regs2) } },
{ A(MM_DPC_REGS, 0xffff), M64P_MEM_DP, { &dev->dp, RW(dpc_regs) } },
+3 -2
View File
@@ -173,11 +173,12 @@ struct interrupt_handler
void (*callback)(void*);
};
enum { CP0_INTERRUPT_HANDLERS_COUNT = 16 };
enum { CP0_INTERRUPT_HANDLERS_COUNT = 17 };
enum {
INTR_UNSAFE_R4300 = 0x01,
INTR_UNSAFE_RSP = 0x02,
INTR_UNSAFE_RSP = 0x02,
INTR_UNSAFE_RDP = 0x04,
};
struct cp0
@@ -656,6 +656,11 @@ void gen_interrupt(struct r4300_core* r4300)
call_interrupt_handler(&r4300->cp0, 15);
break;
case RSP_TSK_EVT:
remove_interrupt_event(&r4300->cp0);
call_interrupt_handler(&r4300->cp0, 16);
break;
default:
DebugMessage(M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", r4300->cp0.q.first->data.type);
remove_interrupt_event(&r4300->cp0);
@@ -69,5 +69,6 @@ void nmi_int_handler(void* opaque);
#define DD_MC_INT 0x1000
#define DD_BM_INT 0x2000
#define DD_DV_INT 0x4000
#define RSP_TSK_EVT 0x8000
#endif /* M64P_DEVICE_R4300_INTERRUPT_H */
@@ -26,6 +26,7 @@
#include "device/memory/memory.h"
#include "device/rcp/mi/mi_controller.h"
#include "device/rcp/rsp/rsp_core.h"
#include "device/r4300/r4300_core.h"
#include "plugin/plugin.h"
static void update_dpc_status(struct rdp_core* dp, uint32_t w)
@@ -40,7 +41,14 @@ static void update_dpc_status(struct rdp_core* dp, uint32_t w)
dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_FREEZE;
if (dp->do_on_unfreeze & DELAY_DP_INT)
{
gfx.fullSync();
dp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RDP;
signal_rcp_interrupt(dp->mi, MI_INTR_DP);
clear_rsp_wait(dp->sp, WAIT_PENDING_DP_SYNC);
}
if (dp->do_on_unfreeze & DELAY_UPDATESCREEN)
gfx.updateScreen();
dp->do_on_unfreeze = 0;
@@ -51,6 +59,22 @@ static void update_dpc_status(struct rdp_core* dp, uint32_t w)
if (w & DPC_CLR_FLUSH) dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_FLUSH;
if (w & DPC_SET_FLUSH) dp->dpc_regs[DPC_STATUS_REG] |= DPC_STATUS_FLUSH;
if (w & DPC_CLR_TMEM_CTR)
{
dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_TMEM_BUSY;
dp->dpc_regs[DPC_TMEM_REG] = 0;
}
if (w & DPC_CLR_PIPE_CTR)
{
dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_PIPE_BUSY;
dp->dpc_regs[DPC_PIPEBUSY_REG] = 0;
}
if (w & DPC_CLR_CMD_CTR)
{
dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_CMD_BUSY;
dp->dpc_regs[DPC_BUFBUSY_REG] = 0;
}
/* clear clock counter */
if (w & DPC_CLR_CLOCK_CTR) dp->dpc_regs[DPC_CLOCK_REG] = 0;
}
@@ -73,11 +97,13 @@ void poweron_rdp(struct rdp_core* dp)
{
memset(dp->dpc_regs, 0, DPC_REGS_COUNT*sizeof(uint32_t));
memset(dp->dps_regs, 0, DPS_REGS_COUNT*sizeof(uint32_t));
dp->dpc_regs[DPC_STATUS_REG] |= DPC_STATUS_START_GCLK;
dp->dpc_regs[DPC_STATUS_REG] |= DPC_STATUS_START_GCLK | DPC_STATUS_PIPE_BUSY | DPC_STATUS_CBUF_READY;
dp->do_on_unfreeze = 0;
poweron_fb(&dp->fb);
dp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RDP;
}
@@ -106,18 +132,39 @@ void write_dpc_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mas
return;
}
masked_write(&dp->dpc_regs[reg], value, mask);
//masked_write(&dp->dpc_regs[reg], value, mask);
switch(reg)
{
case DPC_START_REG:
dp->dpc_regs[DPC_CURRENT_REG] = dp->dpc_regs[DPC_START_REG];
if (!(dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_START_VALID))
{
masked_write(&dp->dpc_regs[reg], value & UINT32_C(0xFFFFF8), mask);
}
dp->dpc_regs[DPC_STATUS_REG] |= DPC_STATUS_START_VALID;
break;
case DPC_END_REG:
unprotect_framebuffers(&dp->fb);
//unprotect_framebuffers(&dp->fb);
masked_write(&dp->dpc_regs[reg], value & UINT32_C(0xFFFFF8), mask);
if (dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_START_VALID)
{
dp->dpc_regs[DPC_CURRENT_REG] = dp->dpc_regs[DPC_START_REG];
dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_START_VALID;
}
gfx.processRDPList();
protect_framebuffers(&dp->fb);
signal_rcp_interrupt(dp->mi, MI_INTR_DP);
if (dp->mi->regs[MI_INTR_REG] & MI_INTR_DP)
{
dp->mi->regs[MI_INTR_REG] &= ~MI_INTR_DP;
dp->mi->r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_RDP;
if (dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_FREEZE) {
dp->do_on_unfreeze |= DELAY_DP_INT;
} else {
add_interrupt_event(&dp->mi->r4300->cp0, DP_INT, dp->dpc_regs[DPC_CLOCK_REG]);
}
}
break;
//protect_framebuffers(&dp->fb);
//signal_rcp_interrupt(dp->mi, MI_INTR_DP);
break;
}
}
@@ -149,6 +196,11 @@ void rdp_interrupt_event(void* opaque)
{
struct rdp_core* dp = (struct rdp_core*)opaque;
gfx.fullSync();
dp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RDP;
raise_rcp_interrupt(dp->mi, MI_INTR_DP);
clear_rsp_wait(dp->sp, WAIT_PENDING_DP_SYNC);
}
@@ -37,7 +37,11 @@ enum
DPC_STATUS_FREEZE = 0x002,
DPC_STATUS_FLUSH = 0x004,
DPC_STATUS_START_GCLK = 0x008,
DPC_STATUS_TMEM_BUSY = 0x010,
DPC_STATUS_PIPE_BUSY = 0x020,
DPC_STATUS_CMD_BUSY = 0x040,
DPC_STATUS_CBUF_READY = 0x080,
DPC_STATUS_DMA_BUSY = 0x100,
DPC_STATUS_END_VALID = 0x200,
DPC_STATUS_START_VALID = 0x400,
/* DPC status - write */
+119 -104
View File
@@ -76,13 +76,16 @@ static void do_sp_dma(struct rsp_core* sp, const struct sp_dma* dma)
pre_framebuffer_read(&sp->dp->fb, dramaddr);
for(i=0; i<length; i++) {
spmem[(memaddr^S8) & 0xfff] = dram[(dramaddr^S8) & 0x7fffff];
spmem[(memaddr & 0xfff)^S8] = dram[(dramaddr^S8) & 0x7fffff];
memaddr++;
dramaddr++;
}
dramaddr+=skip;
}
sp->regs[SP_MEM_ADDR_REG] = (memaddr & 0xfff) + (dma->memaddr & 0x1000);
sp->regs[SP_DRAM_ADDR_REG] = dramaddr;
sp->regs[SP_MEM_ADDR_REG] = memaddr & 0xfff;
sp->regs[SP_DRAM_ADDR_REG] = dramaddr & 0xffffff;
sp->regs[SP_RD_LEN_REG] = 0xff8;
@@ -146,69 +149,87 @@ static void fifo_pop(struct rsp_core* sp)
static void update_sp_status(struct rsp_core* sp, uint32_t w)
{
/* clear / set halt */
if ((w & 0x3) == 0x1) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_HALT;
if ((w & 0x3) == 0x2) sp->regs[SP_STATUS_REG] |= SP_STATUS_HALT;
if ((w & SP_CLR_HALT) && !(w & SP_SET_HALT))
{
sp->rsp_wait &= ~WAIT_HALTED;
sp->regs[SP_STATUS_REG] &= ~SP_STATUS_HALT;
}
if ((w & SP_SET_HALT) && !(w & SP_CLR_HALT))
{
remove_event(&sp->mi->r4300->cp0.q, SP_INT);
sp->rsp_status = 0;
sp->first_run = 1;
sp->rsp_wait |= WAIT_HALTED;
sp->regs[SP_STATUS_REG] |= SP_STATUS_HALT;
}
/* clear broke */
if (w & 0x4) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_BROKE;
if (w & SP_CLR_BROKE) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_BROKE;
/* clear SP interrupt */
if ((w & 0x18) == 0x8)
if ((w & SP_CLR_INTR) && !(w & SP_SET_INTR))
{
clear_rcp_interrupt(sp->mi, MI_INTR_SP);
}
/* set SP interrupt */
if ((w & 0x18) == 0x10)
if ((w & SP_SET_INTR) && !(w & SP_CLR_INTR))
{
signal_rcp_interrupt(sp->mi, MI_INTR_SP);
}
/* clear / set single step */
if ((w & 0x60) == 0x20) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SSTEP;
if ((w & 0x60) == 0x40) sp->regs[SP_STATUS_REG] |= SP_STATUS_SSTEP;
if ((w & SP_CLR_SSTEP) && !(w & SP_SET_SSTEP)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SSTEP;
if ((w & SP_SET_SSTEP) && !(w & SP_CLR_SSTEP)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SSTEP;
/* clear / set interrupt on break */
if ((w & 0x180) == 0x80) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_INTR_BREAK;
if ((w & 0x180) == 0x100) sp->regs[SP_STATUS_REG] |= SP_STATUS_INTR_BREAK;
if ((w & SP_CLR_INTR_BREAK) && !(w & SP_SET_INTR_BREAK))
{
if (sp->rsp_wait & WAIT_PENDING_SP_INT_BROKE)
{
// If a game clears SP_SET_INTR_BREAK before the interrupt happens,
// that means it would have been cleared before the BREAK command
remove_event(&sp->mi->r4300->cp0.q, SP_INT);
sp->rsp_wait &= ~WAIT_PENDING_SP_INT_BROKE;
sp->regs[SP_STATUS_REG] = sp->rsp_status;
sp->rsp_status = 0;
}
sp->regs[SP_STATUS_REG] &= ~SP_STATUS_INTR_BREAK;
}
if ((w & SP_SET_INTR_BREAK) && !(w & SP_CLR_INTR_BREAK)) sp->regs[SP_STATUS_REG] |= SP_STATUS_INTR_BREAK;
/* clear / set signal 0 */
if ((w & 0x600) == 0x200) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG0;
if ((w & 0x600) == 0x400) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG0;
if ((w & SP_CLR_SIG0) && !(w & SP_SET_SIG0)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG0;
if ((w & SP_SET_SIG0) && !(w & SP_CLR_SIG0)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG0;
/* clear / set signal 1 */
if ((w & 0x1800) == 0x800) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG1;
if ((w & 0x1800) == 0x1000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG1;
if ((w & SP_CLR_SIG1) && !(w & SP_SET_SIG1)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG1;
if ((w & SP_SET_SIG1) && !(w & SP_CLR_SIG1)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG1;
/* clear / set signal 2 */
if ((w & 0x6000) == 0x2000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG2;
if ((w & 0x6000) == 0x4000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG2;
if ((w & SP_CLR_SIG2) && !(w & SP_SET_SIG2)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG2;
if ((w & SP_SET_SIG2) && !(w & SP_CLR_SIG2)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG2;
/* clear / set signal 3 */
if ((w & 0x18000) == 0x8000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG3;
if ((w & 0x18000) == 0x10000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG3;
if ((w & SP_CLR_SIG3) && !(w & SP_SET_SIG3)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG3;
if ((w & SP_SET_SIG3) && !(w & SP_CLR_SIG3)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG3;
/* clear / set signal 4 */
if ((w & 0x60000) == 0x20000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG4;
if ((w & 0x60000) == 0x40000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG4;
if ((w & SP_CLR_SIG4) && !(w & SP_SET_SIG4)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG4;
if ((w & SP_SET_SIG4) && !(w & SP_CLR_SIG4)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG4;
/* clear / set signal 5 */
if ((w & 0x180000) == 0x80000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG5;
if ((w & 0x180000) == 0x100000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG5;
if ((w & SP_CLR_SIG5) && !(w & SP_SET_SIG5)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG5;
if ((w & SP_SET_SIG5) && !(w & SP_CLR_SIG5)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG5;
/* clear / set signal 6 */
if ((w & 0x600000) == 0x200000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG6;
if ((w & 0x600000) == 0x400000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG6;
if ((w & SP_CLR_SIG6) && !(w & SP_SET_SIG6)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG6;
if ((w & SP_SET_SIG6) && !(w & SP_CLR_SIG6)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG6;
/* clear / set signal 7 */
if ((w & 0x1800000) == 0x800000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG7;
if ((w & 0x1800000) == 0x1000000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG7;
if ((w & SP_CLR_SIG7) && !(w & SP_SET_SIG7)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG7;
if ((w & SP_SET_SIG7) && !(w & SP_CLR_SIG7)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG7;
if (sp->rsp_task_locked && (get_event(&sp->mi->r4300->cp0.q, SP_INT))) return;
if (!((w & 0x3) == 1) && !(w & 0x4) && !sp->rsp_task_locked)
return;
if (!(sp->regs[SP_STATUS_REG] & SP_STATUS_HALT))
do_SP_Task(sp);
do_SP_Task(sp);
}
void init_rsp(struct rsp_core* sp,
@@ -230,7 +251,9 @@ void poweron_rsp(struct rsp_core* sp)
memset(sp->regs2, 0, SP_REGS2_COUNT*sizeof(uint32_t));
memset(sp->fifo, 0, SP_DMA_FIFO_SIZE*sizeof(struct sp_dma));
sp->rsp_task_locked = 0;
sp->rsp_status = 0;
sp->first_run = 1;
sp->rsp_wait = 0;
sp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RSP;
sp->regs[SP_STATUS_REG] = 1;
sp->regs[SP_RD_LEN_REG] = 0xff8;
@@ -286,6 +309,12 @@ void write_rsp_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mas
switch(reg)
{
case SP_MEM_ADDR_REG:
sp->regs[SP_MEM_ADDR_REG] &= 0x1ff8;
break;
case SP_DRAM_ADDR_REG:
sp->regs[SP_DRAM_ADDR_REG] &= 0xfffff8;
break;
case SP_RD_LEN_REG:
fifo_push(sp, SP_DMA_WRITE);
break;
@@ -317,7 +346,10 @@ void write_rsp_regs2(void* opaque, uint32_t address, uint32_t value, uint32_t ma
uint32_t reg = rsp_reg2(address);
if (reg == SP_PC_REG)
mask &= 0xffc;
{
masked_write(&sp->regs2[SP_PC_REG], value & 0xffc, mask);
return;
}
if (reg < SP_REGS2_COUNT)
masked_write(&sp->regs2[reg], value, mask);
@@ -325,97 +357,66 @@ void write_rsp_regs2(void* opaque, uint32_t address, uint32_t value, uint32_t ma
void do_SP_Task(struct rsp_core* sp)
{
uint32_t save_pc = sp->regs2[SP_PC_REG] & ~0xfff;
if (sp->rsp_wait)
return;
if (get_event(&sp->mi->r4300->cp0.q, RSP_TSK_EVT))
return;
uint32_t sp_delay_time;
uint32_t saved_status = sp->regs[SP_STATUS_REG];
uint32_t sp_bit_set = sp->mi->regs[MI_INTR_REG] & MI_INTR_SP;
uint32_t dp_bit_set = sp->mi->regs[MI_INTR_REG] & MI_INTR_DP;
if (sp->mem[0xfc0/4] == 1)
uint32_t rsp_cycles = rsp.doRspCycles(sp->first_run) / 2;
if (sp->mi->regs[MI_INTR_REG] & MI_INTR_DP && !dp_bit_set)
{
unprotect_framebuffers(&sp->dp->fb);
//gfx.processDList();
sp->regs2[SP_PC_REG] &= 0xfff;
#if defined(PROFILE)
timed_section_start(TIMED_SECTION_GFX);
#endif
rsp.doRspCycles(0xffffffff);
#if defined(PROFILE)
timed_section_end(TIMED_SECTION_GFX);
#endif
sp->regs2[SP_PC_REG] |= save_pc;
new_frame();
if (sp->mi->regs[MI_INTR_REG] & MI_INTR_DP)
{
sp->mi->regs[MI_INTR_REG] &= ~MI_INTR_DP;
if (sp->dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_FREEZE) {
sp->dp->do_on_unfreeze |= DELAY_DP_INT;
} else {
cp0_update_count(sp->mi->r4300);
add_interrupt_event(&sp->mi->r4300->cp0, DP_INT, 4000);
}
sp->mi->regs[MI_INTR_REG] &= ~MI_INTR_DP;
sp->mi->r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_RDP;
sp->rsp_wait |= WAIT_PENDING_DP_SYNC;
if (sp->dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_FREEZE) {
sp->dp->do_on_unfreeze |= DELAY_DP_INT;
} else {
add_interrupt_event(&sp->mi->r4300->cp0, DP_INT, rsp_cycles + sp->dp->dpc_regs[DPC_CLOCK_REG]);
}
sp_delay_time = 1000;
protect_framebuffers(&sp->dp->fb);
}
else if (sp->mem[0xfc0/4] == 2)
{
//audio.processAList();
sp->regs2[SP_PC_REG] &= 0xfff;
#if defined(PROFILE)
timed_section_start(TIMED_SECTION_AUDIO);
#endif
rsp.doRspCycles(0xffffffff);
#if defined(PROFILE)
timed_section_end(TIMED_SECTION_AUDIO);
#endif
sp->regs2[SP_PC_REG] |= save_pc;
sp_delay_time = 4000;
sp->rsp_status = sp->regs[SP_STATUS_REG];
if ((sp->regs[SP_STATUS_REG] & SP_STATUS_HALT) == 0)
{
add_interrupt_event(&sp->mi->r4300->cp0, RSP_TSK_EVT, rsp_cycles);
sp->first_run = 0;
}
else
{
sp->regs2[SP_PC_REG] &= 0xfff;
rsp.doRspCycles(0xffffffff);
sp->regs2[SP_PC_REG] |= save_pc;
sp_delay_time = 0;
sp->rsp_wait |= WAIT_HALTED;
sp->first_run = 1;
}
sp->rsp_task_locked = 0;
sp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RSP;
if ((sp->regs[SP_STATUS_REG] & (SP_STATUS_HALT | SP_STATUS_BROKE)) == 0)
if ((sp->regs[SP_STATUS_REG] & SP_STATUS_BROKE) && (sp->regs[SP_STATUS_REG] & SP_STATUS_INTR_BREAK))
{
sp->rsp_task_locked = 1;
sp->mi->r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_RSP;
sp->mi->regs[MI_INTR_REG] |= MI_INTR_SP;
sp->rsp_wait |= WAIT_PENDING_SP_INT_BROKE;
add_interrupt_event(&sp->mi->r4300->cp0, SP_INT, rsp_cycles);
sp->regs[SP_STATUS_REG] = saved_status;
}
if (sp->mi->regs[MI_INTR_REG] & MI_INTR_SP)
else if (sp->mi->regs[MI_INTR_REG] & MI_INTR_SP && !sp_bit_set)
{
cp0_update_count(sp->mi->r4300);
add_interrupt_event(&sp->mi->r4300->cp0, SP_INT, sp_delay_time);
sp->rsp_wait |= WAIT_PENDING_SP_INT;
add_interrupt_event(&sp->mi->r4300->cp0, SP_INT, rsp_cycles);
}
sp->mi->r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_RSP;
if (!sp_bit_set)
sp->mi->regs[MI_INTR_REG] &= ~MI_INTR_SP;
}
sp->regs[SP_STATUS_REG] &=
~(SP_STATUS_TASKDONE | SP_STATUS_BROKE | SP_STATUS_HALT);
}
void rsp_interrupt_event(void* opaque)
{
struct rsp_core* sp = (struct rsp_core*)opaque;
if (!sp->rsp_task_locked)
{
sp->regs[SP_STATUS_REG] |=
SP_STATUS_TASKDONE | SP_STATUS_BROKE | SP_STATUS_HALT;
}
sp->regs[SP_STATUS_REG] = sp->rsp_status;
sp->rsp_status = 0;
sp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RSP;
raise_rcp_interrupt(sp->mi, MI_INTR_SP);
if ((sp->regs[SP_STATUS_REG] & SP_STATUS_INTR_BREAK) != 0)
{
raise_rcp_interrupt(sp->mi, MI_INTR_SP);
}
clear_rsp_wait(sp, WAIT_PENDING_SP_INT | WAIT_PENDING_SP_INT_BROKE);
}
void rsp_end_of_dma_event(void* opaque)
@@ -423,3 +424,17 @@ void rsp_end_of_dma_event(void* opaque)
struct rsp_core* sp = (struct rsp_core*)opaque;
fifo_pop(sp);
}
void rsp_task_event(void* opaque)
{
struct rsp_core* sp = (struct rsp_core*)opaque;
do_SP_Task(sp);
}
void clear_rsp_wait(struct rsp_core* sp, uint32_t value)
{
sp->rsp_wait &= ~value;
do_SP_Task(sp);
}
@@ -55,6 +55,36 @@ enum
SP_STATUS_SIG7 = 0x4000,
};
enum
{
/* SP_STATUS - write */
SP_CLR_HALT = 0x0000001,
SP_SET_HALT = 0x0000002,
SP_CLR_BROKE = 0x0000004,
SP_CLR_INTR = 0x0000008,
SP_SET_INTR = 0x0000010,
SP_CLR_SSTEP = 0x0000020,
SP_SET_SSTEP = 0x0000040,
SP_CLR_INTR_BREAK = 0x0000080,
SP_SET_INTR_BREAK = 0x0000100,
SP_CLR_SIG0 = 0x0000200,
SP_SET_SIG0 = 0x0000400,
SP_CLR_SIG1 = 0x0000800,
SP_SET_SIG1 = 0x0001000,
SP_CLR_SIG2 = 0x0002000,
SP_SET_SIG2 = 0x0004000,
SP_CLR_SIG3 = 0x0008000,
SP_SET_SIG3 = 0x0010000,
SP_CLR_SIG4 = 0x0020000,
SP_SET_SIG4 = 0x0040000,
SP_CLR_SIG5 = 0x0080000,
SP_SET_SIG5 = 0x0100000,
SP_CLR_SIG6 = 0x0200000,
SP_SET_SIG6 = 0x0400000,
SP_CLR_SIG7 = 0x0800000,
SP_SET_SIG7 = 0x1000000,
};
enum sp_registers
{
SP_MEM_ADDR_REG,
@@ -81,6 +111,14 @@ enum sp_dma_dir
SP_DMA_WRITE
};
enum sp_rsp_wait
{
WAIT_PENDING_SP_INT_BROKE = 0x1,
WAIT_PENDING_SP_INT = 0x2,
WAIT_PENDING_DP_SYNC = 0x4,
WAIT_HALTED = 0x8
};
enum { SP_DMA_FIFO_SIZE = 2} ;
struct sp_dma
@@ -96,7 +134,9 @@ struct rsp_core
uint32_t* mem;
uint32_t regs[SP_REGS_COUNT];
uint32_t regs2[SP_REGS2_COUNT];
uint32_t rsp_task_locked;
uint32_t rsp_status;
uint32_t first_run;
uint32_t rsp_wait;
struct mi_controller* mi;
struct rdp_core* dp;
@@ -141,4 +181,7 @@ void do_SP_Task(struct rsp_core* sp);
void rsp_interrupt_event(void* opaque);
void rsp_end_of_dma_event(void* opaque);
void rsp_task_event(void* opaque);
void clear_rsp_wait(struct rsp_core* sp, uint32_t value);
#endif
+2 -2
View File
@@ -949,7 +949,7 @@ static int savestates_load_m64p(struct device* dev, char *filepath)
/* reset fb state */
poweron_fb(&dev->dp.fb);
dev->sp.rsp_task_locked = 0;
//dev->sp.rsp_task_locked = 0;
dev->r4300.cp0.interrupt_unsafe_state = 0;
*r4300_cp0_last_addr(&dev->r4300.cp0) = *r4300_pc(&dev->r4300);
@@ -1253,7 +1253,7 @@ static int savestates_load_pj64(struct device* dev,
// No flashram info in pj64 savestate.
poweron_flashram(&dev->cart.flashram);
dev->sp.rsp_task_locked = 0;
//dev->sp.rsp_task_locked = 0;
dev->r4300.cp0.interrupt_unsafe_state = 0;
/* extra fb state */
+3 -1
View File
@@ -127,4 +127,6 @@ void dummyvideo_ResizeVideoOutput(int width, int height)
{
}
void dummyvideo_FullSync(void)
{
}
@@ -41,6 +41,7 @@ extern void dummyvideo_ViWidthChanged(void);
extern void dummyvideo_ReadScreen2(void *dest, int *width, int *height, int front);
extern void dummyvideo_SetRenderingCallback(void (*callback)(int));
extern void dummyvideo_ResizeVideoOutput(int width, int height);
extern void dummyvideo_FullSync(void);
extern void dummyvideo_FBRead(unsigned int addr);
extern void dummyvideo_FBWrite(unsigned int addr, unsigned int size);
+7
View File
@@ -69,6 +69,7 @@ static const gfx_plugin_functions dummy_gfx = {
dummyvideo_ReadScreen2,
dummyvideo_SetRenderingCallback,
dummyvideo_ResizeVideoOutput,
dummyvideo_FullSync,
dummyvideo_FBRead,
dummyvideo_FBWrite,
dummyvideo_FBGetFrameBufferInfo
@@ -198,6 +199,7 @@ static m64p_error plugin_connect_gfx(m64p_dynlib_handle plugin_handle)
/* set function pointers for optional functions */
gfx.resizeVideoOutput = (ptr_ResizeVideoOutput)osal_dynlib_getproc(plugin_handle, "ResizeVideoOutput");
gfx.fullSync = (ptr_FullSync)osal_dynlib_getproc(plugin_handle, "FullSync");
/* check the version info */
(*gfx.getVersion)(&PluginType, &PluginVersion, &APIVersion, NULL, NULL);
@@ -222,6 +224,11 @@ static m64p_error plugin_connect_gfx(m64p_dynlib_handle plugin_handle)
DebugMessage(M64MSG_WARNING, "Fallback for Video plugin API (%02i.%02i.%02i) < 2.2.0. Resizable video will not work", VERSION_PRINTF_SPLIT(APIVersion));
gfx.resizeVideoOutput = dummyvideo_ResizeVideoOutput;
}
if (APIVersion < 0x20201 || gfx.fullSync == NULL)
{
DebugMessage(M64MSG_WARNING, "Fallback for Video plugin API (%02i.%02i.%02i) < 2.2.1. No FullSync function", VERSION_PRINTF_SPLIT(APIVersion));
gfx.fullSync = dummyvideo_FullSync;
}
l_GfxAttached = 1;
}
+2 -1
View File
@@ -36,7 +36,7 @@ extern CONTROL Controls[NUM_CONTROLLER];
/*** Version requirement information ***/
#define RSP_API_VERSION 0x20000
#define GFX_API_VERSION 0x20200
#define GFX_API_VERSION 0x20201
#define AUDIO_API_VERSION 0x20000
#define INPUT_API_VERSION 0x20101
@@ -58,6 +58,7 @@ typedef struct _gfx_plugin_functions
ptr_ReadScreen2 readScreen;
ptr_SetRenderingCallback setRenderingCallback;
ptr_ResizeVideoOutput resizeVideoOutput;
ptr_FullSync fullSync;
/* frame buffer plugin spec extension */
ptr_FBRead fBRead;