rpcsx/rpcs3/Emu/GS/Null/NullGSRender.h
Cornee Traas f4b98074b0 Merge remote-tracking branch 'upstream/master'
Conflicts:
	rpcs3/Emu/GS/GL/GLGSRender.cpp
	rpcs3/Gui/InterpreterDisAsm.cpp
	rpcs3/Gui/MainFrame.cpp
2013-09-03 19:26:31 +02:00

191 lines
3.6 KiB
C++

#pragma once
#include "Emu/GS/GSRender.h"
struct NullGSFrame : public GSFrame
{
NullGSFrame() : GSFrame(NULL, "GSFrame[Null]")
{
Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(GSFrame::OnLeftDclick));
}
void Draw() { Draw(wxClientDC(this)); }
private:
virtual void OnPaint(wxPaintEvent& event) { Draw(wxPaintDC(this)); }
virtual void OnSize(wxSizeEvent& event)
{
GSFrame::OnSize(event);
Draw();
}
void Draw(wxDC& dc)
{
dc.DrawText("Null GS output", 0, 0);
}
};
struct NullRSXThread : public wxThread
{
wxWindow* m_parent;
Stack<u32> call_stack;
NullRSXThread(wxWindow* parent);
virtual void OnExit();
void Start();
ExitCode Entry();
};
class NullGSRender
: public wxWindow
, public GSRender
{
private:
NullRSXThread* m_rsx_thread;
public:
NullGSFrame* m_frame;
NullGSRender()
: m_frame(nullptr)
, m_rsx_thread(nullptr)
{
m_draw = false;
m_frame = new NullGSFrame();
}
~NullGSRender()
{
Close();
m_frame->Close();
}
private:
virtual void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)
{
if(m_frame->IsShown()) return;
m_frame->SetSize(740, 480);
m_frame->Show();
m_ioAddress = ioAddress;
m_ctrlAddress = ctrlAddress;
m_ioSize = ioSize;
m_local_mem_addr = localAddress;
m_ctrl = (CellGcmControl*)Memory.GetMemFromAddr(m_ctrlAddress);
(m_rsx_thread = new NullRSXThread(this))->Start();
}
public:
void DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 count)
{
switch(cmd)
{
case NV406E_SET_REFERENCE:
m_ctrl->ref = re32(args[0]);
break;
}
}
virtual void Draw()
{
//if(m_frame && !m_frame->IsBeingDeleted()) m_frame->Draw();
m_draw = true;
}
virtual void Close()
{
if(m_rsx_thread) m_rsx_thread->Delete();
if(m_frame->IsShown()) m_frame->Hide();
m_ctrl = NULL;
}
};
NullRSXThread::NullRSXThread(wxWindow* parent)
: wxThread(wxTHREAD_DETACHED)
, m_parent(parent)
{
}
void NullRSXThread::OnExit()
{
call_stack.Clear();
}
void NullRSXThread::Start()
{
Create();
Run();
}
wxThread::ExitCode NullRSXThread::Entry()
{
ConLog.Write("Null RSX thread entry");
NullGSRender& p = *(NullGSRender*)m_parent;
while(!TestDestroy() && p.m_frame && !p.m_frame->IsBeingDeleted())
{
wxCriticalSectionLocker lock(p.m_cs_main);
if(p.m_ctrl->get == p.m_ctrl->put || !Emu.IsRunning())
{
SemaphorePostAndWait(p.m_sem_flush);
if(p.m_draw)
{
p.m_draw = false;
p.m_flip_status = 0;
if(SemaphorePostAndWait(p.m_sem_flip)) continue;
}
Sleep(1);
continue;
}
const u32 get = re(p.m_ctrl->get);
const u32 cmd = Memory.Read32(p.m_ioAddress + get);
const u32 count = (cmd >> 18) & 0x7ff;
if(cmd & CELL_GCM_METHOD_FLAG_JUMP)
{
p.m_ctrl->get = re32(cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT));
ConLog.Warning("rsx jump!");
continue;
}
if(cmd & CELL_GCM_METHOD_FLAG_CALL)
{
call_stack.Push(get + 4);
p.m_ctrl->get = re32(cmd & ~CELL_GCM_METHOD_FLAG_CALL);
ConLog.Warning("rsx call!");
continue;
}
if(cmd & CELL_GCM_METHOD_FLAG_RETURN)
{
p.m_ctrl->get = re32(call_stack.Pop());
ConLog.Warning("rsx return!");
continue;
}
if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
{
//ConLog.Warning("non increment cmd! 0x%x", cmd);
}
if(cmd == 0)
{
ConLog.Warning("null cmd: addr=0x%x, put=0x%x, get=0x%x", p.m_ioAddress + get, re(p.m_ctrl->put), get);
Emu.Pause();
continue;
}
p.DoCmd(cmd, cmd & 0x3ffff, mem32_t(p.m_ioAddress + get + 4), count);
re(p.m_ctrl->get, get + (count + 1) * 4);
}
ConLog.Write("Null RSX thread exit...");
call_stack.Clear();
return (ExitCode)0;
}