Adding vblank interrupt.
This commit is contained in:
parent
998467ce05
commit
91f62918f6
|
@ -45,7 +45,8 @@ namespace {
|
|||
|
||||
|
||||
Processor::Processor(xe_memory_ref memory, shared_ptr<Backend> backend) :
|
||||
sym_table_(NULL), jit_(NULL) {
|
||||
sym_table_(NULL), jit_(NULL),
|
||||
interrupt_thread_lock_(NULL), interrupt_thread_state_(NULL) {
|
||||
memory_ = xe_memory_retain(memory);
|
||||
backend_ = backend;
|
||||
|
||||
|
@ -64,6 +65,9 @@ Processor::~Processor() {
|
|||
}
|
||||
modules_.clear();
|
||||
|
||||
DeallocThread(interrupt_thread_state_);
|
||||
xe_mutex_free(interrupt_thread_lock_);
|
||||
|
||||
delete jit_;
|
||||
delete sym_table_;
|
||||
|
||||
|
@ -98,6 +102,9 @@ void Processor::set_export_resolver(
|
|||
int Processor::Setup() {
|
||||
XEASSERTNULL(jit_);
|
||||
|
||||
interrupt_thread_lock_ = xe_mutex_alloc(10000);
|
||||
interrupt_thread_state_ = AllocThread(16 * 1024, 0, 0);
|
||||
|
||||
sym_table_ = new SymbolTable();
|
||||
|
||||
jit_ = backend_->CreateJIT(memory_, sym_table_);
|
||||
|
@ -245,6 +252,15 @@ uint64_t Processor::Execute(ThreadState* thread_state, uint32_t address,
|
|||
return ppc_state->r[3];
|
||||
}
|
||||
|
||||
uint64_t Processor::ExecuteInterrupt(uint32_t address,
|
||||
uint64_t arg0, uint64_t arg1) {
|
||||
// Acquire lock on interrupt thread (we can only dispatch one at a time).
|
||||
xe_mutex_lock(interrupt_thread_lock_);
|
||||
uint64_t result = Execute(interrupt_thread_state_, address, arg0, arg1);
|
||||
xe_mutex_unlock(interrupt_thread_lock_);
|
||||
return result;
|
||||
}
|
||||
|
||||
FunctionSymbol* Processor::GetFunction(uint32_t address) {
|
||||
// Attempt to grab the function symbol from the global lookup table.
|
||||
FunctionSymbol* fn_symbol = sym_table_->GetFunction(address);
|
||||
|
|
|
@ -56,10 +56,14 @@ public:
|
|||
ThreadState* AllocThread(uint32_t stack_size, uint32_t thread_state_address,
|
||||
uint32_t thread_id);
|
||||
void DeallocThread(ThreadState* thread_state);
|
||||
|
||||
int Execute(ThreadState* thread_state, uint32_t address);
|
||||
uint64_t Execute(ThreadState* thread_state, uint32_t address, uint64_t arg0);
|
||||
uint64_t Execute(ThreadState* thread_state, uint32_t address,
|
||||
uint64_t arg0, uint64_t arg1);
|
||||
|
||||
uint64_t ExecuteInterrupt(uint32_t address, uint64_t arg0, uint64_t arg1);
|
||||
|
||||
sdb::FunctionSymbol* GetFunction(uint32_t address);
|
||||
void* GetFunctionPointer(uint32_t address);
|
||||
|
||||
|
@ -72,6 +76,9 @@ private:
|
|||
sdb::SymbolTable* sym_table_;
|
||||
JIT* jit_;
|
||||
std::vector<ExecModule*> modules_;
|
||||
|
||||
xe_mutex_t* interrupt_thread_lock_;
|
||||
ThreadState* interrupt_thread_state_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <xenia/gpu/graphics_system.h>
|
||||
|
||||
#include <xenia/cpu/processor.h>
|
||||
#include <xenia/gpu/ring_buffer_worker.h>
|
||||
|
||||
|
||||
|
@ -16,7 +17,8 @@ using namespace xe;
|
|||
using namespace xe::gpu;
|
||||
|
||||
|
||||
GraphicsSystem::GraphicsSystem(const CreationParams* params) {
|
||||
GraphicsSystem::GraphicsSystem(const CreationParams* params) :
|
||||
interrupt_callback_(0), interrupt_callback_data_(0) {
|
||||
memory_ = xe_memory_retain(params->memory);
|
||||
|
||||
worker_ = new RingBufferWorker(memory_);
|
||||
|
@ -33,6 +35,21 @@ xe_memory_ref GraphicsSystem::memory() {
|
|||
return xe_memory_retain(memory_);
|
||||
}
|
||||
|
||||
shared_ptr<cpu::Processor> GraphicsSystem::processor() {
|
||||
return processor_;
|
||||
}
|
||||
|
||||
void GraphicsSystem::set_processor(shared_ptr<cpu::Processor> processor) {
|
||||
processor_ = processor;
|
||||
}
|
||||
|
||||
void GraphicsSystem::SetInterruptCallback(uint32_t callback,
|
||||
uint32_t user_data) {
|
||||
interrupt_callback_ = callback;
|
||||
interrupt_callback_data_ = user_data;
|
||||
XELOGGPU("SetInterruptCallback(%.4X, %.4X)", callback, user_data);
|
||||
}
|
||||
|
||||
void GraphicsSystem::InitializeRingBuffer(uint32_t ptr, uint32_t page_count) {
|
||||
worker_->Initialize(ptr, page_count);
|
||||
}
|
||||
|
@ -44,6 +61,12 @@ void GraphicsSystem::EnableReadPointerWriteBack(uint32_t ptr,
|
|||
|
||||
uint64_t GraphicsSystem::ReadRegister(uint32_t r) {
|
||||
XELOGGPU("ReadRegister(%.4X)", r);
|
||||
|
||||
switch (r) {
|
||||
case 0x6544: // ? vblank pending?
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -60,3 +83,12 @@ void GraphicsSystem::WriteRegister(uint32_t r, uint64_t value) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsSystem::DispatchInterruptCallback() {
|
||||
// NOTE: we may be executing in some random thread.
|
||||
if (!interrupt_callback_) {
|
||||
return;
|
||||
}
|
||||
processor_->ExecuteInterrupt(
|
||||
interrupt_callback_, 0, interrupt_callback_data_);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,13 @@
|
|||
#include <xenia/core.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
class Processor;
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
|
||||
|
@ -32,19 +39,25 @@ public:
|
|||
virtual ~GraphicsSystem();
|
||||
|
||||
xe_memory_ref memory();
|
||||
shared_ptr<cpu::Processor> processor();
|
||||
void set_processor(shared_ptr<cpu::Processor> processor);
|
||||
|
||||
virtual void Initialize() = 0;
|
||||
void SetInterruptCallback(uint32_t callback, uint32_t user_data);
|
||||
void InitializeRingBuffer(uint32_t ptr, uint32_t page_count);
|
||||
void EnableReadPointerWriteBack(uint32_t ptr, uint32_t block_size);
|
||||
|
||||
virtual uint64_t ReadRegister(uint32_t r);
|
||||
virtual void WriteRegister(uint32_t r, uint64_t value);
|
||||
|
||||
void DispatchInterruptCallback();
|
||||
|
||||
public:
|
||||
static uint64_t ReadRegisterThunk(GraphicsSystem* this_ptr, uint32_t r) {
|
||||
return this_ptr->ReadRegister(r);
|
||||
}
|
||||
static void WriteRegisterThunk(GraphicsSystem* this_ptr, uint32_t r, uint64_t value) {
|
||||
static void WriteRegisterThunk(GraphicsSystem* this_ptr, uint32_t r,
|
||||
uint64_t value) {
|
||||
this_ptr->WriteRegister(r, value);
|
||||
}
|
||||
|
||||
|
@ -52,8 +65,12 @@ protected:
|
|||
GraphicsSystem(const CreationParams* params);
|
||||
|
||||
xe_memory_ref memory_;
|
||||
shared_ptr<cpu::Processor> processor_;
|
||||
|
||||
RingBufferWorker* worker_;
|
||||
|
||||
uint32_t interrupt_callback_;
|
||||
uint32_t interrupt_callback_data_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -17,12 +17,41 @@ using namespace xe::gpu;
|
|||
using namespace xe::gpu::nop;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void __stdcall NopGraphicsSystemVsyncCallback(NopGraphicsSystem* gs, BOOLEAN) {
|
||||
gs->DispatchInterruptCallback();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
NopGraphicsSystem::NopGraphicsSystem(const CreationParams* params) :
|
||||
GraphicsSystem(params) {
|
||||
GraphicsSystem(params),
|
||||
timer_queue_(NULL),
|
||||
vsync_timer_(NULL) {
|
||||
}
|
||||
|
||||
NopGraphicsSystem::~NopGraphicsSystem() {
|
||||
if (vsync_timer_) {
|
||||
DeleteTimerQueueTimer(timer_queue_, vsync_timer_, NULL);
|
||||
}
|
||||
if (timer_queue_) {
|
||||
DeleteTimerQueueEx(timer_queue_, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void NopGraphicsSystem::Initialize() {
|
||||
XEASSERTNULL(timer_queue_);
|
||||
XEASSERTNULL(vsync_timer_);
|
||||
|
||||
timer_queue_ = CreateTimerQueue();
|
||||
CreateTimerQueueTimer(
|
||||
&vsync_timer_,
|
||||
timer_queue_,
|
||||
(WAITORTIMERCALLBACK)NopGraphicsSystemVsyncCallback,
|
||||
this,
|
||||
16,
|
||||
100,
|
||||
WT_EXECUTEINTIMERTHREAD);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,10 @@ public:
|
|||
virtual ~NopGraphicsSystem();
|
||||
|
||||
virtual void Initialize();
|
||||
|
||||
private:
|
||||
HANDLE timer_queue_;
|
||||
HANDLE vsync_timer_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ void xeVdInitializeEngines(uint32_t unk0, uint32_t callback, uint32_t unk1,
|
|||
}
|
||||
|
||||
// r3 = 0x4F810000
|
||||
// r4 = function ptr (ready callback?)
|
||||
// r4 = function ptr (cleanup callback?)
|
||||
// r5 = 0
|
||||
// r6/r7 = some binary data in .data
|
||||
|
||||
|
@ -166,7 +166,7 @@ void xeVdSetGraphicsInterruptCallback(uint32_t callback, uint32_t user_data) {
|
|||
// r3 = bool 0/1 - 0 is normal interrupt, 1 is some acquire/lock mumble
|
||||
// r4 = user_data (r4 of VdSetGraphicsInterruptCallback)
|
||||
|
||||
//gs->SetupInterruptCallback(callback, user_data);
|
||||
gs->SetInterruptCallback(callback, user_data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -230,6 +230,8 @@ void xeVdEnableRingBufferRPtrWriteBack(uint32_t ptr, uint32_t block_size) {
|
|||
printf("%.8X", ptr);
|
||||
// 0x0110343c
|
||||
|
||||
// r3 = 0x2B10(d3d?) + 0x3C
|
||||
|
||||
//((p + 0x3C) & 0x1FFFFFFF) + ((((p + 0x3C) >> 20) + 0x200) & 0x1000)
|
||||
//also 0x3C offset into WriteBacks is PrimaryRingBufferReadIndex
|
||||
//(1:17:38 AM) Rick: .text:8201B348 lwz r11, 0x2B10(r31)
|
||||
|
|
|
@ -68,6 +68,8 @@ int Run::Setup() {
|
|||
|
||||
processor_ = shared_ptr<Processor>(new Processor(memory_, backend_));
|
||||
processor_->set_graphics_system(graphics_system_);
|
||||
graphics_system_->set_processor(processor_);
|
||||
|
||||
XEEXPECTZERO(processor_->Setup());
|
||||
|
||||
runtime_ = shared_ptr<Runtime>(new Runtime(processor_, XT("")));
|
||||
|
|
Loading…
Reference in New Issue