|
#281
|
||||
|
||||
![]()
No, I'm pretty sure you're right about it.
It was never an issue because if(SEMAPHORE) was the most likely condition. else if (MFCO_count has pointer addr to something that exists) was the next branch frame after that. else (some other way of setting SP_STATUS_HALT using MTC0 strictly) was almost impossible because no game ever seems to do that. So the second branch frame may as well be an unconditional `else`, and it would still work just as well. I just forgot to change it back when I made MFC0_count an array counting for each of the 32 scalar GPRs. Quote:
I'm running Top Gear Rally (U), and I'm able to get in-game past the menus and start a race. You can try creating a new global int variable flagging a MFC0_count overflow and checking that at the end outside the run_task() function instead if you like.
__________________
http://theoatmeal.com/comics/cat_vs_internet |
#282
|
||||
|
||||
![]()
My fault, get stuck on vc build z64gl. Don't why vc build z64gl is more unstable than mingw build.
__________________
--------------------- CPU: Intel U7300 1.3 GHz GPU: Mobile Intel 4 Series (on board) AUDIO: Realtek HD Audio (on board) RAM: 4 GB OS: Windows 7 - 32 bit |
#283
|
||||
|
||||
![]()
I turned MFC0_count into an array of counts instead of just one total count for all the scalar registers, because World Driver gave me problems using zilmar's method. zilmar just counted the total MFC0 status reads and said that if it exceeded 10 the RSP was probably stuck in a permanent loop and should restart.
It gave me an error that there was an alternative reason the HALT bit was getting set at some point in World Driver, so I needed to change the MFC0 count limit to exceed or make it into an array. I made it into an array so that I could have a smaller count, less looping of the RSP to wait to find out if it was a permanent loop. I guess it fixed the issue just perfectly, but not in the way that I expected...it was for the wrong reasons. The if() was unconditional as you pointed out. I can worry about fixing it later if there is a game this has a problem with. Until then I am way busier finding things out about the RDP now.
__________________
http://theoatmeal.com/comics/cat_vs_internet |
#284
|
||||
|
||||
![]() Quote:
Code:
#ifdef WAIT_FOR_CPU_HOST if (IsWaitForCpuHost()) { MFC0_count_exceed = 0; for (rt = 0; rt < 32; rt++) MFC0_count[rt] = 0; } #endif Code:
#ifdef WAIT_FOR_CPU_HOST static int MFC0_count[32]; static int MFC0_count_exceed; /* Keep one C0 MF status read count for each scalar register. */ #endif Code:
case 0x4: SR[rt] = *RSP.SP_STATUS_REG; #ifdef WAIT_FOR_CPU_HOST ++MFC0_count[rt]; if (MFC0_count[rt] > 7) { *RSP.SP_STATUS_REG |= 0x00000001; /* Let OS restart the task. */ MFC0_count_exceed = 1; } #endif Code:
if (*RSP.SP_SEMAPHORE_REG == 0x00000001) /* SP semaphore lock (zilmar) */ *RSP.SP_STATUS_REG &= ~0x00000001; /* Guess I need to let emu retask. */ #ifdef WAIT_FOR_CPU_HOST else if (MFC0_count_exceed) *RSP.SP_STATUS_REG &= ~0x00000001; /* CPU restarts with correct SIGs. */ #endif else { message("Halted RSP CPU loop by means of MTC0.", 2); /* not sure */ *RSP.MI_INTR_REG |= 0x00000001; /* VR4300 SP interrupt */ RSP.CheckInterrupts(); } When testing with World Driver Championship, after the title menu, the HALT flag will set and MFC0_count_exceed is not overflow, but one element of MFC0_count array is 1. If at this time return to CPU without clear the HALT flag, no more RSP task will send to RSP. And with this modification, most game won't boot. So I think actually the code can simplify as no matter what causes current task to halt, just clear the HALT flag before return to CPU: Code:
#if 0 if (*RSP.SP_SEMAPHORE_REG == 0x00000001) /* SP semaphore lock (zilmar) */ *RSP.SP_STATUS_REG &= ~0x00000001; /* Guess I need to let emu retask. */ #ifdef WAIT_FOR_CPU_HOST else if (MFC0_count_exceed) *RSP.SP_STATUS_REG &= ~0x00000001; /* CPU restarts with correct SIGs. */ #endif else { message("Halted RSP CPU loop by means of MTC0.", 2); /* not sure */ *RSP.MI_INTR_REG |= 0x00000001; /* VR4300 SP interrupt */ RSP.CheckInterrupts(); } #endif // just clear current HALT flag *RSP.SP_STATUS_REG &= ~0x00000001;
__________________
--------------------- CPU: Intel U7300 1.3 GHz GPU: Mobile Intel 4 Series (on board) AUDIO: Realtek HD Audio (on board) RAM: 4 GB OS: Windows 7 - 32 bit |
#285
|
||||
|
||||
![]() Quote:
Code:
.name SP_STATUS $c4 #define SP_STATUS_HALT 0x00000001 mfc0 $at, SP_STATUS ori $at, SP_STATUS_HALT mtc0 $at, SP_STATUS Funny thing is, zilmar's RSP emulator never supported that properly. It sets the HALT bit, but he relies on a custom `RSP_Running` global Boolean which he declined to maintain in that function. So if this was the correct path of code for World Driver to reach it would have broken his interpreter. Yet, it doesn't break his interpreter, which most likely means that code was never encountered...I'm not sure if that's good or bad. I will look into it later. Quote:
The compiler would most likely optimize that change you just did by in-lining the halt clear at the end of both if() blocks like I did, to avoid branching out of the block to reach the shared common code. So it would possibly be a size change, but not really an efficiency change on the low level of things. I wrote out the cases for when HALT should be un-set so Project64 knows to re-try the task. If all cases fail, it should remain set, because mtc0 instructed HALT to be set. Otherwise I wrote out the cases where it should be cleared.
__________________
http://theoatmeal.com/comics/cat_vs_internet |
#286
|
||||
|
||||
![]()
Just taking notes.
DP command-fetching queue code: Code:
for (i = 0; i < length; i += 4) { rdp_cmd_data[rdp_cmd_ptr++] = READ_RDP_DATA(*gfx.DPC_CURRENT_REG + i); if (rdp_cmd_ptr >= 0x00010000) { fatalerror( "overflow\n0x%x 0x%x 0x%x", rdp_cmd_ptr, length, ptr_onstart); } } I was thinking why not factor out the if() out of the loop: Code:
if ((rdp_cmd_ptr + length>>2) & ~0x0000FFFF) { MessageBoxA(gfx.hWnd, "ProcessRDPList", NULL, 0x00000010); return; } for (i = 0; i < length; i += 4) { rdp_cmd_data[rdp_cmd_ptr++] = READ_RDP_DATA(*gfx.DPC_CURRENT_REG + i); } Still, it's a fair, static speed-up. But there are two interesting ways of doing the first `if`: method A Code:
if ((rdp_cmd_ptr + length>>2) & ~0x0000FFFF) On Intel however, I'm thinking the arithmetic method may be faster.... method B, algebraically rewritten off of method A Code:
if ((P + L>>2) & ~0x0000FFFF) if (P + L/4 > 0x0000FFFF) if (P + L/4 >= 0x00010000) if (4*P + L >= 0x00040000) Code:
if ((rdp_cmd_ptr<<2 + length) & ~0x0003FFFF)
__________________
http://theoatmeal.com/comics/cat_vs_internet Last edited by HatCat; 26th May 2013 at 07:01 PM. |
#287
|
||||
|
||||
![]()
Far be it from the truth that this is the only thing I am optimizing.
But there is something special about this precise inefficiency. Have a closer look at the original code here in angrylion's plugin: http://code.google.com/p/angrylions-...video.cpp#7476 Notice: `dp_current += rdp_command_length[cmd];` (dp_current is a defined macro for *gfx.DP_CURRENT_REG.) dp_current is never read from anywhere within the body of that loop. dp_current is never read from anywhere after the body of that loop. dp_current is *completely overwritten* at the end of the loop: Code:
( ... loop body ... ) }; rdp_cmd_ptr = 0; rdp_cmd_cur = 0; dp_start = dp_current = dp_end; } it probably was one of those MAME prototype rewrites that got overlooked and never removed from a while back Unless I am missing some informational value behind that code? But it looks redundant/pointless.
__________________
http://theoatmeal.com/comics/cat_vs_internet |
#288
|
||||
|
||||
![]() Quote:
But if rdp_process_list has cycles limitation and is possible to break the loop when runs out of CPU cycles, then it is make sense to keep track dp_current.
__________________
--------------------- CPU: Intel U7300 1.3 GHz GPU: Mobile Intel 4 Series (on board) AUDIO: Realtek HD Audio (on board) RAM: 4 GB OS: Windows 7 - 32 bit |
#289
|
||||
|
||||
![]()
True, as a vendor-extension viewpoint.
For if someone should decide to merge in cycle-accuracy. For reasons like that I'd decided that, being the least of the bottlenecks behind the slow speed I leave it in, just commented.
__________________
http://theoatmeal.com/comics/cat_vs_internet |
#290
|
|||
|
|||
![]()
Mia Hamm Soccer 64 (U) seems to quit with "LUV illegal element" / "SQV illegal element".
|