maple: msb selection, implement/fake reset, kill and allreq commands

overrun and illegal address ints in strict mode
This commit is contained in:
Flyinghead 2020-06-15 17:04:04 +02:00
parent 5cfed1e482
commit 8192eea387
5 changed files with 155 additions and 38 deletions

View File

@ -87,8 +87,6 @@ enum MapleDeviceRV
MDRS_JVSReply = 0x87, // JVS I/O
};
#define SWAP32(a) ((((a) & 0xff) << 24) | (((a) & 0xff00) << 8) | (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff))
//fill in the info
void maple_device::Setup(u32 prt)
{
@ -242,6 +240,7 @@ struct maple_sega_controller: maple_base
switch (cmd)
{
case MDC_DeviceRequest:
case MDC_AllStatusReq:
//caps
//4
w32(MFID_0_Input);
@ -270,7 +269,7 @@ struct maple_sega_controller: maple_base
//2
w16(0x01F4); // 50 mA
return MDRS_DeviceStatus;
return cmd == MDC_DeviceRequest ? MDRS_DeviceStatus : MDRS_DeviceStatusAll;
//controller condition
case MDCF_GetCondition:
@ -307,8 +306,14 @@ struct maple_sega_controller: maple_base
return MDRS_DataTransfer;
case MDC_DeviceReset:
return MDRS_DeviceReply;
case MDC_DeviceKill:
return MDRS_DeviceReply;
default:
//printf("maple_sega_controller UNKOWN MAPLE COMMAND %d\n",cmd);
INFO_LOG(MAPLE, "maple_sega_controller: Unknown maple command %d", cmd);
return MDRE_UnknownCmd;
}
}
@ -542,6 +547,7 @@ struct maple_sega_vmu: maple_base
switch (cmd)
{
case MDC_DeviceRequest:
case MDC_AllStatusReq:
//caps
//4
w32(MFID_1_Storage | MFID_2_LCD | MFID_3_Clock);
@ -567,7 +573,7 @@ struct maple_sega_vmu: maple_base
//2
w16(0x0082); // 13 mA
return MDRS_DeviceStatus;
return cmd == MDC_DeviceRequest ? MDRS_DeviceStatus : MDRS_DeviceStatusAll;
//in[0] is function used
//out[0] is function used
@ -829,6 +835,11 @@ struct maple_sega_vmu: maple_base
}
}
case MDC_DeviceReset:
return MDRS_DeviceReply;
case MDC_DeviceKill:
return MDRS_DeviceReply;
default:
DEBUG_LOG(MAPLE, "Unknown MAPLE COMMAND %d", cmd);
@ -870,6 +881,7 @@ struct maple_microphone: maple_base
switch (cmd)
{
case MDC_DeviceRequest:
case MDC_AllStatusReq:
DEBUG_LOG(MAPLE, "maple_microphone::dma MDC_DeviceRequest");
//this was copied from the controller case with just the id and name replaced!
@ -901,7 +913,7 @@ struct maple_microphone: maple_base
//2
w16(0x01F4); // 50 mA
return MDRS_DeviceStatus;
return cmd == MDC_DeviceRequest ? MDRS_DeviceStatus : MDRS_DeviceStatusAll;
case MDCF_GetCondition:
{
@ -1026,6 +1038,9 @@ struct maple_microphone: maple_base
}
}
case MDC_DeviceKill:
return MDRS_DeviceReply;
default:
INFO_LOG(MAPLE, "maple_microphone::dma UNHANDLED MAPLE COMMAND %d", cmd);
return MDRE_UnknownCmd;
@ -1063,6 +1078,7 @@ struct maple_sega_purupuru : maple_base
switch (cmd)
{
case MDC_DeviceRequest:
case MDC_AllStatusReq:
//caps
//4
w32(MFID_8_Vibration);
@ -1091,7 +1107,7 @@ struct maple_sega_purupuru : maple_base
//2
w16(0x0640); // 160 mA
return MDRS_DeviceStatus;
return cmd == MDC_DeviceRequest ? MDRS_DeviceStatus : MDRS_DeviceStatusAll;
//get last vibration
case MDCF_GetCondition:
@ -1161,6 +1177,12 @@ struct maple_sega_purupuru : maple_base
return MDRS_DeviceReply;
case MDC_DeviceReset:
return MDRS_DeviceReply;
case MDC_DeviceKill:
return MDRS_DeviceReply;
default:
INFO_LOG(MAPLE, "UNKOWN MAPLE COMMAND %d", cmd);
return MDRE_UnknownCmd;
@ -1184,6 +1206,7 @@ struct maple_keyboard : maple_base
switch (cmd)
{
case MDC_DeviceRequest:
case MDC_AllStatusReq:
//caps
//4
w32(MFID_6_Keyboard);
@ -1215,7 +1238,7 @@ struct maple_keyboard : maple_base
// Maximum current consumption (2)
w16(0x01F5); // 50.1 mA
return MDRS_DeviceStatus;
return cmd == MDC_DeviceRequest ? MDRS_DeviceStatus : MDRS_DeviceStatusAll;
case MDCF_GetCondition:
w32(MFID_6_Keyboard);
@ -1232,6 +1255,12 @@ struct maple_keyboard : maple_base
return MDRS_DataTransfer;
case MDC_DeviceReset:
return MDRS_DeviceReply;
case MDC_DeviceKill:
return MDRS_DeviceReply;
default:
INFO_LOG(MAPLE, "Keyboard: unknown MAPLE COMMAND %d", cmd);
return MDRE_UnknownCmd;
@ -1278,6 +1307,7 @@ struct maple_mouse : maple_base
switch (cmd)
{
case MDC_DeviceRequest:
case MDC_AllStatusReq:
//caps
//4
w32(MFID_9_Mouse);
@ -1309,7 +1339,7 @@ struct maple_mouse : maple_base
// Maximum current consumption (2)
w16(0x0120); // 28.8 mA
return MDRS_DeviceStatus;
return cmd == MDC_DeviceRequest ? MDRS_DeviceStatus : MDRS_DeviceStatusAll;
case MDCF_GetCondition:
w32(MFID_9_Mouse);
@ -1339,6 +1369,12 @@ struct maple_mouse : maple_base
return MDRS_DataTransfer;
case MDC_DeviceReset:
return MDRS_DeviceReply;
case MDC_DeviceKill:
return MDRS_DeviceReply;
default:
INFO_LOG(MAPLE, "Mouse: unknown MAPLE COMMAND %d", cmd);
return MDRE_UnknownCmd;
@ -1362,6 +1398,7 @@ struct maple_lightgun : maple_base
switch (cmd)
{
case MDC_DeviceRequest:
case MDC_AllStatusReq:
//caps
//4
w32(MFID_7_LightGun | MFID_0_Input);
@ -1393,7 +1430,7 @@ struct maple_lightgun : maple_base
// Maximum current consumption (2)
w16(0x0120); // 28.8 mA
return MDRS_DeviceStatus;
return cmd == MDC_DeviceRequest ? MDRS_DeviceStatus : MDRS_DeviceStatusAll;
case MDCF_GetCondition:
{
@ -1416,9 +1453,14 @@ struct maple_lightgun : maple_base
//4
w32(0x80808080);
}
return MDRS_DataTransfer;
case MDC_DeviceReset:
return MDRS_DeviceReply;
case MDC_DeviceKill:
return MDRS_DeviceReply;
default:
INFO_LOG(MAPLE, "Light gun: unknown MAPLE COMMAND %d", cmd);
return MDRE_UnknownCmd;
@ -2519,15 +2561,21 @@ struct maple_naomi_jamma : maple_sega_controller
w8(0x00);
w8(0x20);
w8(0x00);
break;
case MDC_AllStatusReq:
w8(MDRS_DeviceStatusAll);
w8(0x00);
w8(0x20);
w8(0x00);
break;
case MDC_DeviceReset:
case MDC_DeviceKill:
w8(MDRS_DeviceReply);
w8(0x00);
w8(0x20);
w8(0x00);
break;
case MDCF_GetCondition:

View File

@ -143,3 +143,5 @@ extern s32 mo_y_abs;
extern f32 mo_x_delta;
extern f32 mo_y_delta;
extern f32 mo_wheel_delta;
#define SWAP32(a) ((((a) & 0xff) << 24) | (((a) & 0xff00) << 8) | (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff))

View File

@ -8,7 +8,7 @@ u32 maple_GetPort(u32 addr)
if ((1<<i)&addr)
return i;
}
return 0;
return 5;
}
u32 maple_GetAttachedDevices(u32 bus)
{

View File

@ -66,12 +66,14 @@ void maple_vblank()
if (settings.platform.system == DC_PLATFORM_DREAMCAST)
maple_handle_reconnect();
}
void maple_SB_MSHTCL_Write(u32 addr, u32 data)
static void maple_SB_MSHTCL_Write(u32 addr, u32 data)
{
if (data&1)
maple_ddt_pending_reset=false;
}
void maple_SB_MDST_Write(u32 addr, u32 data)
static void maple_SB_MDST_Write(u32 addr, u32 data)
{
if (data & 0x1)
{
@ -83,7 +85,7 @@ void maple_SB_MDST_Write(u32 addr, u32 data)
}
}
void maple_SB_MDEN_Write(u32 addr, u32 data)
static void maple_SB_MDEN_Write(u32 addr, u32 data)
{
SB_MDEN=data&1;
@ -93,6 +95,26 @@ void maple_SB_MDEN_Write(u32 addr, u32 data)
}
}
static bool check_mdapro(u32 addr)
{
u32 bottom = std::max(0x0C000000u, ((((SB_MDAPRO >> 8) & 0x7f) << 20) | 0x08000000));
u32 top = std::min(0x0FFFFFE0u, (((SB_MDAPRO & 0x7f) << 20) | 0x080fffff));
if (((addr >> 29) & 7) == 7
|| (addr & 0x0fffffff) < bottom
|| (addr & 0x0fffffff) > top)
{
INFO_LOG(MAPLE, "MAPLE ERROR : Invalid address: %08x. SB_MDAPRO: %x %x", addr, (SB_MDAPRO >> 8) & 0x7f, SB_MDAPRO & 0x7f);
return false;
}
return true;
}
static void maple_SB_MDSTAR_Write(u32 addr, u32 data)
{
SB_MDSTAR = data;
if (!check_mdapro(data))
asic_RaiseInterrupt(holly_MAPLE_ILLADDR);
}
bool IsOnSh4Ram(u32 addr)
{
@ -114,6 +136,15 @@ static void maple_DoDma()
DEBUG_LOG(MAPLE, "Maple: DoMapleDma SB_MDSTAR=%x", SB_MDSTAR);
u32 addr = SB_MDSTAR;
#ifdef STRICT_MODE
if (!check_mdapro(addr))
{
asic_RaiseInterrupt(holly_MAPLE_ILLADDR);
SB_MDST = 0;
return;
}
#endif
const bool swap_msb = (SB_MMSEL == 0);
u32 xfer_count=0;
bool last = false;
while (last != true)
@ -132,14 +163,22 @@ static void maple_DoDma()
{
case MP_Start:
{
#ifdef STRICT_MODE
if (!check_mdapro(header_2) || !check_mdapro(addr + 8 + plen * sizeof(u32) - 1))
{
asic_RaiseInterrupt(holly_MAPLE_OVERRUN);
SB_MDST = 0;
return;
}
#else
if (!IsOnSh4Ram(header_2))
{
INFO_LOG(MAPLE, "MAPLE ERROR : DESTINATION NOT ON SH4 RAM 0x%X", header_2);
header_2&=0xFFFFFF;
header_2|=(3<<26);
}
#endif
u32* p_out=(u32*)GetMemPtr(header_2,4);
u32 outlen=0;
u32* p_data =(u32*) GetMemPtr(addr + 8,(plen)*sizeof(u32));
if (p_data == NULL)
@ -148,30 +187,55 @@ static void maple_DoDma()
SB_MDST=0;
return;
}
const u32 frame_header = swap_msb ? SWAP32(p_data[0]) : p_data[0];
//Command code
u32 command=p_data[0] &0xFF;
u32 command = frame_header & 0xFF;
//Recipient address
u32 reci=(p_data[0] >> 8) & 0xFF;//0-5;
u32 reci = (frame_header >> 8) & 0xFF;//0-5;
//Sender address
//u32 send = (frame_header >> 16) & 0xFF;
//Number of additional words in frame
u32 inlen = (frame_header >> 24) & 0xFF;
u32 port=maple_GetPort(reci);
u32 bus=maple_GetBusId(reci);
//Sender address
u32 send=(p_data[0] >> 16) & 0xFF;
//Number of additional words in frame
u32 inlen=(p_data[0]>>24) & 0xFF;
u32 resp=0;
inlen*=4;
if (MapleDevices[bus][5] && MapleDevices[bus][port])
{
u32 outlen = MapleDevices[bus][port]->RawDma(&p_data[0], inlen + 4, &p_out[0]);
if (swap_msb)
{
static u32 maple_in_buf[1024 / 4];
static u32 maple_out_buf[1024 / 4];
maple_in_buf[0] = frame_header;
for (u32 i = 1; i < inlen; i++)
maple_in_buf[i] = SWAP32(p_data[i]);
p_data = maple_in_buf;
p_out = maple_out_buf;
}
u32 outlen = MapleDevices[bus][port]->RawDma(&p_data[0], inlen * 4 + 4, &p_out[0]);
xfer_count += outlen;
#ifdef STRICT_MODE
if (!check_mdapro(header_2 + outlen - 1))
{
// TODO: This isn't correct (with SB_MMSEL=1) since the interrupt
// should be raised before the memory is written to
asic_RaiseInterrupt(holly_MAPLE_OVERRUN);
SB_MDST = 0;
return;
}
#endif
if (swap_msb)
{
u32 *final_out = (u32 *)GetMemPtr(header_2, outlen);
for (u32 i = 0; i < outlen / 4; i++)
final_out[i] = SWAP32(p_out[i]);
}
}
else
{
if (port != 5 && command != 1)
INFO_LOG(MAPLE, "MAPLE: Unknown device bus %d port %d cmd %d", bus, port, command);
outlen=4;
INFO_LOG(MAPLE, "MAPLE: Unknown device bus %d port %d cmd %d reci %d", bus, port, command, reci);
p_out[0]=0xFFFFFFFF;
}
@ -234,6 +298,9 @@ void maple_Init()
sb_rio_register(SB_MDST_addr,RIO_WF,0,&maple_SB_MDST_Write);
sb_rio_register(SB_MDEN_addr,RIO_WF,0,&maple_SB_MDEN_Write);
sb_rio_register(SB_MSHTCL_addr,RIO_WF,0,&maple_SB_MSHTCL_Write);
#ifdef STRICT_MODE
sb_rio_register(SB_MDSTAR_addr, RIO_WF, 0, &maple_SB_MDSTAR_Write);
#endif
maple_schid=sh4_sched_register(0,&maple_schd);
}

View File

@ -109,22 +109,22 @@ enum HollyInterruptID
//bit 0 = RENDER : ISP out of Cache(Buffer over flow)
//bit 1 = RENDER : Hazard Processing of Strip Buffer
holly_PRIM_NOMEM = holly_err | 0x02, //bit 2 = TA : ISP/TSP Parameter Overflow
holly_MATR_NOMEM = holly_err | 0x03 //bit 3 = TA : Object List Pointer Overflow
holly_MATR_NOMEM = holly_err | 0x03, //bit 3 = TA : Object List Pointer Overflow
//bit 4 = TA : Illegal Parameter
//bit 5 = TA : FIFO Overflow
//bit 6 = PVRIF : Illegal Address set
//bit 7 = PVRIF : DMA over run
//bit 8 = MAPLE : Illegal Address set
//bit 9 = MAPLE : DMA over run
//bit 10 = MAPLE : Write FIFO over flow
//bit 11 = MAPLE : Illegal command
holly_MAPLE_ILLADDR = holly_err | 0x08, //bit 8 = MAPLE : Illegal Address set
holly_MAPLE_OVERRUN = holly_err | 0x09, //bit 9 = MAPLE : DMA over run
holly_MAPLE_FIFO = holly_err | 0x0a, //bit 10 = MAPLE : Write FIFO overflow
holly_MAPLE_ILLCMD = holly_err | 0x0b, //bit 11 = MAPLE : Illegal command
//bit 12 = G1 : Illegal Address set
//bit 13 = G1 : GD-DMA over run
//bit 14 = G1 : ROM/FLASH access at GD-DMA
//bit 15 = G2 : AICA-DMA Illegal Address set
//bit 16 = G2 : Ext-DMA1 Illegal Address set
//bit 17 = G2 : Ext-DMA2 Illegal Address set
//bit 18 = G2 : Dev-DMA Illegal Address set
holly_AICA_ILLADDR = holly_err | 0x0f, //bit 15 = G2 : AICA-DMA Illegal Address set
holly_EXT1_ILLADDR = holly_err | 0x10, //bit 16 = G2 : Ext-DMA1 Illegal Address set
holly_EXT2_ILLADDR = holly_err | 0x11, //bit 17 = G2 : Ext-DMA2 Illegal Address set
holly_DEV_ILLADDR = holly_err | 0x12, //bit 18 = G2 : Dev-DMA Illegal Address set
//bit 19 = G2 : AICA-DMA over run
//bit 20 = G2 : Ext-DMA1 over run
//bit 21 = G2 : Ext-DMA2 over run