1. Expanded Framelimit range from 20 to 120 in case someone wants to run a little faster than full speed but still controllable not like wild OFF.
2. Fixed a bug (for Win 32bit) that reports "No possible memory base pointer found!" even when there IS valid memory base found. 3. Made Metroid Prime 2 (maybe also other games) boot PS: There is definitely some initialization problem with Dolphin (not found exact location yet), which prevents Metroid Prime 2 from first time booting (If you boot some other GC game first, stop it, then MP2 can boot without problem). So I added an instant BP hack that can make MP2 boot even at first time. And I've tested all my games to guarantee it won't break any game that already boots before this hack. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4795 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
69fdb7ae5c
commit
a3cfafcd12
|
@ -244,12 +244,13 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena
|
|||
u32 max_base_addr = 0x7FFF0000 - 0x31000000;
|
||||
u8 *base = NULL;
|
||||
int base_attempts = 1;
|
||||
for (u32 base_addr = 0; base_addr < max_base_addr; base_addr += 0x40000)
|
||||
for (u32 base_addr = 0x40000; base_addr < max_base_addr; base_addr += 0x40000)
|
||||
{
|
||||
base = (u8 *)base_addr;
|
||||
if (Memory_TryBase(base, views, num_views, flags, arena))
|
||||
{
|
||||
INFO_LOG(MEMMAP, "Found valid memory base at %p after %i tries.", base, base_attempts);
|
||||
base_attempts = 0;
|
||||
break;
|
||||
}
|
||||
base_attempts++;
|
||||
|
@ -266,7 +267,7 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena
|
|||
#endif
|
||||
|
||||
#endif
|
||||
if (!base)
|
||||
if (base_attempts)
|
||||
PanicAlert("No possible memory base pointer found!");
|
||||
return base;
|
||||
}
|
||||
|
|
|
@ -231,7 +231,7 @@ void SConfig::LoadSettings()
|
|||
ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false);
|
||||
ini.Get("Core", "RunCompareClient", &m_LocalCoreStartupParameter.bRunCompareClient, false);
|
||||
ini.Get("Core", "TLBHack", &m_LocalCoreStartupParameter.iTLBHack, 0);
|
||||
ini.Get("Core", "FrameLimit", &m_Framelimit, 0); // auto frame limit by default
|
||||
ini.Get("Core", "FrameLimit", &m_Framelimit, 1); // auto frame limit by default
|
||||
|
||||
// Plugins
|
||||
ini.Get("Core", "GFXPlugin", &m_LocalCoreStartupParameter.m_strVideoPlugin, m_DefaultGFXPlugin.c_str());
|
||||
|
|
|
@ -67,7 +67,7 @@ struct SConfig
|
|||
// interface language
|
||||
INTERFACE_LANGUAGE m_InterfaceLanguage;
|
||||
// framelimit choose
|
||||
u32 m_Framelimit;
|
||||
int m_Framelimit;
|
||||
// other interface settings
|
||||
bool m_InterfaceToolbar;
|
||||
bool m_InterfaceStatusbar;
|
||||
|
|
|
@ -592,16 +592,17 @@ void ScreenShot()
|
|||
// This should only be called from VI
|
||||
void VideoThrottle()
|
||||
{
|
||||
u32 TargetVPS = (SConfig::GetInstance().m_Framelimit > 1) ? SConfig::GetInstance().m_Framelimit * 5
|
||||
u32 TargetVPS = (SConfig::GetInstance().m_Framelimit > 1) ? SConfig::GetInstance().m_Framelimit * 10
|
||||
: VideoInterface::TargetRefreshRate;
|
||||
|
||||
// When frame limit is NOT off
|
||||
if (SConfig::GetInstance().m_Framelimit != 1)
|
||||
if (SConfig::GetInstance().m_Framelimit)
|
||||
{
|
||||
// a full screen scan consists of 2 fields
|
||||
u32 frametime = DrawnVideo * 2 * 1000 / TargetVPS;
|
||||
while ((u32)Timer.GetTimeDifference() < frametime)
|
||||
//Common::YieldCPU();
|
||||
Common::SleepCurrentThread(1);
|
||||
Common::YieldCPU();
|
||||
//Common::SleepCurrentThread(1);
|
||||
}
|
||||
|
||||
// Update info per second
|
||||
|
@ -612,10 +613,10 @@ void VideoThrottle()
|
|||
|
||||
u32 FPS = Common::AtomicLoad(DrawnFrame) * 1000 / ElapseTime;
|
||||
u32 VPS = DrawnVideo * 2 * 1000 / ElapseTime;
|
||||
u32 Speed = VPS * 100 / TargetVPS;
|
||||
u32 Speed = VPS * 100 / VideoInterface::TargetRefreshRate;
|
||||
|
||||
// Settings are shown the same for both extended and summary info
|
||||
std::string SSettings = StringFromFormat("Core: %s %s",
|
||||
std::string SSettings = StringFromFormat("%s %s",
|
||||
#if defined(JITTEST) && JITTEST
|
||||
#ifdef _M_IX86
|
||||
_CoreParameter.bUseJIT ? "JIT32IL" : "Int32",
|
||||
|
@ -674,16 +675,18 @@ void VideoThrottle()
|
|||
Common::AtomicStore(DrawnFrame, 0);
|
||||
DrawnVideo = 0;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
DrawnVideo++;
|
||||
}
|
||||
}
|
||||
|
||||
// Executed from GPU thread
|
||||
// reports if a frame should be skipped or not
|
||||
// depending on the framelimit set
|
||||
bool report_slow(int skipped)
|
||||
{
|
||||
u32 TargetFPS = (SConfig::GetInstance().m_Framelimit > 1) ? SConfig::GetInstance().m_Framelimit * 5
|
||||
u32 TargetFPS = (SConfig::GetInstance().m_Framelimit > 1) ? SConfig::GetInstance().m_Framelimit * 10
|
||||
: VideoInterface::TargetRefreshRate;
|
||||
u32 frames = Common::AtomicLoad(DrawnFrame);
|
||||
bool fps_slow = (Timer.GetTimeDifference() < (frames + skipped) * 1000 / TargetFPS) ? false : true;
|
||||
|
|
|
@ -211,7 +211,7 @@ union UVIInterruptRegister
|
|||
unsigned : 1;
|
||||
unsigned IR_MASK : 1; // Interrupt Enable Bit
|
||||
unsigned : 2;
|
||||
unsigned IR_INT : 1; // Interrupt Status (1=Active) (Write to clear)
|
||||
unsigned IR_INT : 1; // Interrupt Status (1=Active) (Read to clear)
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -547,6 +547,8 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
|
|||
// RETRACE STUFF ...
|
||||
case VI_PRERETRACE_HI:
|
||||
_uReturnValue = m_InterruptRegister[0].Hi;
|
||||
m_InterruptRegister[0].IR_INT = 0;
|
||||
UpdateInterrupts();
|
||||
return;
|
||||
case VI_PRERETRACE_LO:
|
||||
_uReturnValue = m_InterruptRegister[0].Lo;
|
||||
|
@ -554,6 +556,8 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
|
|||
|
||||
case VI_POSTRETRACE_HI:
|
||||
_uReturnValue = m_InterruptRegister[1].Hi;
|
||||
m_InterruptRegister[1].IR_INT = 0;
|
||||
UpdateInterrupts();
|
||||
return;
|
||||
case VI_POSTRETRACE_LO:
|
||||
_uReturnValue = m_InterruptRegister[1].Lo;
|
||||
|
@ -561,6 +565,8 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
|
|||
|
||||
case VI_DISPLAY_INTERRUPT_2_HI:
|
||||
_uReturnValue = m_InterruptRegister[2].Hi;
|
||||
m_InterruptRegister[2].IR_INT = 0;
|
||||
UpdateInterrupts();
|
||||
return;
|
||||
case VI_DISPLAY_INTERRUPT_2_LO:
|
||||
_uReturnValue = m_InterruptRegister[2].Lo;
|
||||
|
@ -568,6 +574,8 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
|
|||
|
||||
case VI_DISPLAY_INTERRUPT_3_HI:
|
||||
_uReturnValue = m_InterruptRegister[3].Hi;
|
||||
m_InterruptRegister[3].IR_INT = 0;
|
||||
UpdateInterrupts();
|
||||
return;
|
||||
case VI_DISPLAY_INTERRUPT_3_LO:
|
||||
_uReturnValue = m_InterruptRegister[3].Lo;
|
||||
|
@ -795,8 +803,6 @@ void Write16(const u16 _iValue, const u32 _iAddress)
|
|||
// RETRACE STUFF ...
|
||||
case VI_PRERETRACE_HI:
|
||||
m_InterruptRegister[0].Hi = _iValue;
|
||||
m_InterruptRegister[0].IR_INT = 0;
|
||||
UpdateInterrupts();
|
||||
break;
|
||||
case VI_PRERETRACE_LO:
|
||||
m_InterruptRegister[0].Lo = _iValue;
|
||||
|
@ -804,8 +810,6 @@ void Write16(const u16 _iValue, const u32 _iAddress)
|
|||
|
||||
case VI_POSTRETRACE_HI:
|
||||
m_InterruptRegister[1].Hi = _iValue;
|
||||
m_InterruptRegister[1].IR_INT = 0;
|
||||
UpdateInterrupts();
|
||||
break;
|
||||
case VI_POSTRETRACE_LO:
|
||||
m_InterruptRegister[1].Lo = _iValue;
|
||||
|
@ -813,8 +817,6 @@ void Write16(const u16 _iValue, const u32 _iAddress)
|
|||
|
||||
case VI_DISPLAY_INTERRUPT_2_HI:
|
||||
m_InterruptRegister[2].Hi = _iValue;
|
||||
m_InterruptRegister[2].IR_INT = 0;
|
||||
UpdateInterrupts();
|
||||
break;
|
||||
case VI_DISPLAY_INTERRUPT_2_LO:
|
||||
m_InterruptRegister[2].Lo = _iValue;
|
||||
|
@ -822,8 +824,6 @@ void Write16(const u16 _iValue, const u32 _iAddress)
|
|||
|
||||
case VI_DISPLAY_INTERRUPT_3_HI:
|
||||
m_InterruptRegister[3].Hi = _iValue;
|
||||
m_InterruptRegister[3].IR_INT = 0;
|
||||
UpdateInterrupts();
|
||||
break;
|
||||
case VI_DISPLAY_INTERRUPT_3_LO:
|
||||
m_InterruptRegister[3].Lo = _iValue;
|
||||
|
|
|
@ -176,19 +176,10 @@ void CConfigMain::CreateGUIControls()
|
|||
// GUI
|
||||
arrayStringFor_InterfaceLang = arrayStringFor_GCSystemLang;
|
||||
// Framelimit
|
||||
arrayStringFor_Framelimit.Add(wxT("auto"));
|
||||
arrayStringFor_Framelimit.Add(wxT("off"));
|
||||
arrayStringFor_Framelimit.Add(wxT("10"));
|
||||
arrayStringFor_Framelimit.Add(wxT("15"));
|
||||
arrayStringFor_Framelimit.Add(wxT("20"));
|
||||
arrayStringFor_Framelimit.Add(wxT("25"));
|
||||
arrayStringFor_Framelimit.Add(wxT("30"));
|
||||
arrayStringFor_Framelimit.Add(wxT("35"));
|
||||
arrayStringFor_Framelimit.Add(wxT("40"));
|
||||
arrayStringFor_Framelimit.Add(wxT("45"));
|
||||
arrayStringFor_Framelimit.Add(wxT("50"));
|
||||
arrayStringFor_Framelimit.Add(wxT("55"));
|
||||
arrayStringFor_Framelimit.Add(wxT("60"));
|
||||
arrayStringFor_Framelimit.Add(wxT("Off"));
|
||||
arrayStringFor_Framelimit.Add(wxT("Auto"));
|
||||
for (int i = 20; i <= 120; i+=10) // from 20 to 120
|
||||
arrayStringFor_Framelimit.Add(wxString::Format(wxT("%i"), i));
|
||||
|
||||
// Create the notebook and pages
|
||||
Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize);
|
||||
|
@ -219,6 +210,7 @@ void CConfigMain::CreateGUIControls()
|
|||
// Framelimit
|
||||
wxStaticText *FramelimitText = new wxStaticText(GeneralPage, ID_FRAMELIMIT_TEXT, wxT("Framelimit :"), wxDefaultPosition, wxDefaultSize);
|
||||
Framelimit = new wxChoice(GeneralPage, ID_FRAMELIMIT, wxDefaultPosition, wxDefaultSize, arrayStringFor_Framelimit, 0, wxDefaultValidator);
|
||||
Framelimit->SetToolTip(wxT("If you set Framelimit higher than game full speed (NTSC:60, PAL:50),\nyou also have to disable Audio Throttle in DSP to make it effective."));
|
||||
Framelimit->SetSelection(SConfig::GetInstance().m_Framelimit);
|
||||
|
||||
// Core Settings - Advanced
|
||||
|
|
|
@ -243,10 +243,7 @@ EVT_MENU(IDM_IMPORTSAVE, CFrame::OnImportSave)
|
|||
EVT_MENU(IDM_CHEATS, CFrame::OnShow_CheatsWindow)
|
||||
EVT_MENU(IDM_CHANGEDISC, CFrame::OnChangeDisc)
|
||||
EVT_MENU(IDM_LOAD_WII_MENU, CFrame::OnLoadWiiMenu)
|
||||
EVT_MENU(IDM_CONNECT_WIIMOTE1, CFrame::OnConnectWiimote)
|
||||
EVT_MENU(IDM_CONNECT_WIIMOTE2, CFrame::OnConnectWiimote)
|
||||
EVT_MENU(IDM_CONNECT_WIIMOTE3, CFrame::OnConnectWiimote)
|
||||
EVT_MENU(IDM_CONNECT_WIIMOTE4, CFrame::OnConnectWiimote)
|
||||
|
||||
EVT_MENU(IDM_TOGGLE_FULLSCREEN, CFrame::OnToggleFullscreen)
|
||||
EVT_MENU(IDM_TOGGLE_DUALCORE, CFrame::OnToggleDualCore)
|
||||
EVT_MENU(IDM_TOGGLE_SKIPIDLE, CFrame::OnToggleSkipIdle)
|
||||
|
@ -274,6 +271,7 @@ EVT_MENU_RANGE(IDM_LOADSLOT1, IDM_LOADSLOT8, CFrame::OnLoadState)
|
|||
EVT_MENU_RANGE(IDM_SAVESLOT1, IDM_SAVESLOT8, CFrame::OnSaveState)
|
||||
EVT_MENU_RANGE(IDM_FRAMESKIP0, IDM_FRAMESKIP9, CFrame::OnFrameSkip)
|
||||
EVT_MENU_RANGE(IDM_DRIVE1, IDM_DRIVE24, CFrame::OnBootDrive)
|
||||
EVT_MENU_RANGE(IDM_CONNECT_WIIMOTE1, IDM_CONNECT_WIIMOTE4, CFrame::OnConnectWiimote)
|
||||
|
||||
// Other
|
||||
EVT_ACTIVATE(CFrame::OnActive)
|
||||
|
|
|
@ -172,7 +172,7 @@ void Shutdown()
|
|||
|
||||
void Read16(u16& _rReturnValue, const u32 _Address)
|
||||
{
|
||||
DEBUG_LOG(COMMANDPROCESSOR, "(r): 0x%08x", _Address);
|
||||
INFO_LOG(COMMANDPROCESSOR, "(r): 0x%08x", _Address);
|
||||
switch (_Address & 0xFFF)
|
||||
{
|
||||
case STATUS_REGISTER:
|
||||
|
@ -185,12 +185,6 @@ void Read16(u16& _rReturnValue, const u32 _Address)
|
|||
//m_CPStatusReg.ReadIdle = 1;
|
||||
//m_CPStatusReg.CommandIdle = 1;
|
||||
|
||||
m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint;
|
||||
_rReturnValue = m_CPStatusReg.Hex;
|
||||
|
||||
// Clear on read
|
||||
UpdateInterrupts(false);
|
||||
|
||||
DEBUG_LOG(COMMANDPROCESSOR, "(r) status: iBP %s | fReadIdle %s | fCmdIdle %s | iOvF %s | iUndF %s"
|
||||
, m_CPStatusReg.Breakpoint ? "ON" : "OFF"
|
||||
, m_CPStatusReg.ReadIdle ? "ON" : "OFF"
|
||||
|
@ -199,6 +193,9 @@ void Read16(u16& _rReturnValue, const u32 _Address)
|
|||
, m_CPStatusReg.UnderflowLoWatermark ? "ON" : "OFF"
|
||||
);
|
||||
|
||||
_rReturnValue = m_CPStatusReg.Hex;
|
||||
// Clear on read
|
||||
UpdateInterrupts(false);
|
||||
return;
|
||||
|
||||
case CTRL_REGISTER: _rReturnValue = m_CPCtrlReg.Hex; return;
|
||||
|
@ -331,7 +328,7 @@ void Read16(u16& _rReturnValue, const u32 _Address)
|
|||
|
||||
case CLKS_PER_VTX_OUT:
|
||||
_rReturnValue = 4; //Number of clocks per vertex.. TODO: Calculate properly
|
||||
WARN_LOG(COMMANDPROCESSOR, "Read from CLKS_PER_VTX_OUT: %04x", _rReturnValue);
|
||||
DEBUG_LOG(COMMANDPROCESSOR, "Read from CLKS_PER_VTX_OUT: %04x", _rReturnValue);
|
||||
return;
|
||||
//add all the other regs here? are they ever read?
|
||||
default:
|
||||
|
@ -411,9 +408,14 @@ void Write16(const u16 _Value, const u32 _Address)
|
|||
{
|
||||
// Clear old BP and initiate new BP
|
||||
Common::AtomicStore(fifo.bFF_Breakpoint, 0);
|
||||
// AyuanX: The following is a hack
|
||||
// There is definitely some initialization problem with Dolphin (not found exact location yet)
|
||||
// Which prevents Metroid Prime 2 from first time booting (If you boot some other GC game first then MP2 can boot)
|
||||
// But somehow this instant BP hack can make MP2 boot even at first time
|
||||
UpdateInterrupts(true);
|
||||
}
|
||||
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
|
||||
INFO_LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | LINK %s | BP %s || Init %s | OvF %s | UndF %s"
|
||||
, fifo.bFF_GPReadEnable ? "ON" : "OFF"
|
||||
, fifo.bFF_GPLinkEnable ? "ON" : "OFF"
|
||||
|
@ -425,11 +427,6 @@ void Write16(const u16 _Value, const u32 _Address)
|
|||
}
|
||||
break;
|
||||
|
||||
case PERF_SELECT:
|
||||
// Seems to select which set of perf registers should be exposed.
|
||||
DEBUG_LOG(COMMANDPROCESSOR, "write to PERF_SELECT: %04x", _Value);
|
||||
break;
|
||||
|
||||
case CLEAR_REGISTER:
|
||||
// We don't care since we don't implement Watermark
|
||||
//m_CPClearReg.Hex = 0;
|
||||
|
@ -438,6 +435,11 @@ void Write16(const u16 _Value, const u32 _Address)
|
|||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x", _Value);
|
||||
break;
|
||||
|
||||
case PERF_SELECT:
|
||||
// Seems to select which set of perf registers should be exposed.
|
||||
DEBUG_LOG(COMMANDPROCESSOR, "write to PERF_SELECT: %04x", _Value);
|
||||
break;
|
||||
|
||||
// Fifo Registers
|
||||
case FIFO_TOKEN_REGISTER:
|
||||
m_tokenReg = _Value;
|
||||
|
@ -726,7 +728,8 @@ void UpdateFifoRegister()
|
|||
|
||||
void UpdateInterrupts(bool active)
|
||||
{
|
||||
DEBUG_LOG(COMMANDPROCESSOR, "Fifo Breakpoint Interrupt: %s", (active)? "Asserted" : "Deasserted");
|
||||
INFO_LOG(COMMANDPROCESSOR, "Fifo Breakpoint Interrupt: %s", (active)? "Asserted" : "Deasserted");
|
||||
m_CPStatusReg.Breakpoint = active;
|
||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_CP, active);
|
||||
}
|
||||
|
||||
|
|
|
@ -169,7 +169,9 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
|||
)
|
||||
{
|
||||
Common::AtomicStore(_fifo.bFF_Breakpoint, 1);
|
||||
CommandProcessor::UpdateInterruptsFromVideoPlugin(true);
|
||||
// Replaced by instant BP hack
|
||||
// TODO: figure out why the correct trigger method doesn't work for MP2
|
||||
//CommandProcessor::UpdateInterruptsFromVideoPlugin(true);
|
||||
break;
|
||||
}
|
||||
distToSend = 32;
|
||||
|
|
Loading…
Reference in New Issue