diff --git a/src/emu/emulator.cc b/src/emu/emulator.cc index b1ec0718..8aa8df69 100644 --- a/src/emu/emulator.cc +++ b/src/emu/emulator.cc @@ -20,7 +20,7 @@ using namespace dreavm::system; DEFINE_string(bios, "dc_bios.bin", "Path to BIOS"); DEFINE_string(flash, "dc_flash.bin", "Path to flash ROM"); -Emulator::Emulator(System &sys) : sys_(sys) { +Emulator::Emulator() { bios_ = new uint8_t[BIOS_SIZE]; flash_ = new uint8_t[FLASH_SIZE]; ram_ = new uint8_t[MAIN_RAM_M0_SIZE]; @@ -34,7 +34,7 @@ Emulator::Emulator(System &sys) : sys_(sys) { rt_frontend_ = new SH4Frontend(*memory_); // rt_backend_ = new InterpreterBackend(*memory_); rt_backend_ = new X64Backend(*memory_); - rb_ = new GLBackend(sys); + rb_ = new GLBackend(sys_); } Emulator::~Emulator() { @@ -55,9 +55,53 @@ Emulator::~Emulator() { delete rb_; } +void Emulator::Run(const char *path) { + if (!Init()) { + LOG_WARNING("Failed to initialize emulator"); + return; + } + + if (path) { + LOG_INFO("Launching %s", path); + + if ((strstr(path, ".bin") && !LaunchBIN(path)) || + (strstr(path, ".gdi") && !LaunchGDI(path))) { + LOG_WARNING("Failed to launch %s", path); + return; + } + } + + static const std::chrono::nanoseconds step = HZ_TO_NANO(60); + std::chrono::nanoseconds time_remaining = std::chrono::nanoseconds(0); + auto current_time = std::chrono::high_resolution_clock::now(); + auto last_time = current_time; + + while (true) { + current_time = std::chrono::high_resolution_clock::now(); + time_remaining += current_time - last_time; + last_time = current_time; + + if (time_remaining < step) { + continue; + } + + time_remaining -= step; + + PumpEvents(); + + scheduler_->Tick(step); + + RenderFrame(); + } +} + bool Emulator::Init() { InitMemory(); + if (!sys_.Init()) { + return false; + } + if (!rb_->Init()) { return false; } @@ -91,26 +135,6 @@ bool Emulator::Init() { return true; } -bool Emulator::Launch(const char *path) { - LOG_INFO("Launching %s", path); - - if (strstr(path, ".bin")) { - return LaunchBIN(path); - } else if (strstr(path, ".gdi")) { - return LaunchGDI(path); - } - - return false; -} - -void Emulator::Tick() { - PumpEvents(); - - scheduler_->Tick(); - - RenderFrame(); -} - void Emulator::InitMemory() { memory_->Mount(BIOS_START, BIOS_END, MIRROR_MASK, bios_); memory_->Mount(FLASH_START, FLASH_END, MIRROR_MASK, flash_); @@ -230,25 +254,33 @@ bool Emulator::LaunchGDI(const char *path) { void Emulator::PumpEvents() { SystemEvent ev; + sys_.PumpEvents(); + while (sys_.PollEvent(&ev)) { - if (ev.type == SE_KEY) { - // let the profiler take a stab at the input first - if (!Profiler::HandleInput(ev.key.code, ev.key.value)) { - // debug tracing - if (ev.key.code == K_F2) { - if (ev.key.value) { - holly_->pvr().ToggleTracing(); + switch (ev.type) { + case SE_KEY: { + // let the profiler take a stab at the input first + if (!Profiler::HandleInput(ev.key.code, ev.key.value)) { + // debug tracing + if (ev.key.code == K_F2) { + if (ev.key.value) { + holly_->pvr().ToggleTracing(); + } + } + // else, forward to maple + else { + holly_->maple().HandleInput(0, ev.key.code, ev.key.value); } } - // else, forward to maple - else { - holly_->maple().HandleInput(0, ev.key.code, ev.key.value); - } - } - } else if (ev.type == SE_MOUSEMOVE) { - Profiler::HandleMouseMove(ev.mousemove.x, ev.mousemove.y); - } else if (ev.type == SE_RESIZE) { - rb_->SetFramebufferSize(FB_DEFAULT, ev.resize.width, ev.resize.height); + } break; + + case SE_MOUSEMOVE: { + Profiler::HandleMouseMove(ev.mousemove.x, ev.mousemove.y); + } break; + + case SE_RESIZE: { + rb_->ResizeVideo(ev.resize.width, ev.resize.height); + } break; } } } @@ -256,14 +288,12 @@ void Emulator::PumpEvents() { void Emulator::RenderFrame() { rb_->BeginFrame(); - // render latest TA output - rb_->RenderFramebuffer(FB_TILE_ACCELERATOR); + holly_->pvr().RenderLastFrame(); // render stats char stats[512]; - snprintf(stats, sizeof(stats), "%.2f%%, %.2f fps, %.2f vbps", - scheduler_->perf(), holly_->pvr().fps(), holly_->pvr().vbps()); - // LOG_EVERY_N(INFO, 10) << stats; + snprintf(stats, sizeof(stats), "%.2f fps, %.2f vbps", holly_->pvr().fps(), + holly_->pvr().vbps()); rb_->RenderText2D(0, 0, 12.0f, 0xffffffff, stats); // render profiler diff --git a/src/emu/emulator.h b/src/emu/emulator.h index caaebda3..a55bf366 100644 --- a/src/emu/emulator.h +++ b/src/emu/emulator.h @@ -14,14 +14,13 @@ namespace emu { class Emulator { public: - Emulator(system::System &sys); + Emulator(); ~Emulator(); - bool Init(); - bool Launch(const char *path); - void Tick(); + void Run(const char *path); private: + bool Init(); void InitMemory(); bool LoadBios(const char *path); bool LoadFlash(const char *path); @@ -32,7 +31,7 @@ class Emulator { void PumpEvents(); void RenderFrame(); - system::System &sys_; + system::System sys_; emu::Scheduler *scheduler_; emu::Memory *memory_; cpu::Runtime *runtime_; diff --git a/src/emu/scheduler.cc b/src/emu/scheduler.cc index b1b1fae8..42b18bbb 100644 --- a/src/emu/scheduler.cc +++ b/src/emu/scheduler.cc @@ -4,21 +4,14 @@ using namespace dreavm::emu; -Scheduler::Scheduler() - : next_timer_handle_(0), - timeslice_(HZ_TO_NANO(60)), - base_time_(), - next_time_(base_time_ + timeslice_), - tick_deltas_(), - tick_idx_(0), - perf_(0.0f) {} +Scheduler::Scheduler() : next_timer_handle_(0), base_time_() {} DeviceHandle Scheduler::AddDevice(Device *device) { devices_.push_back(DeviceInfo(device)); return static_cast(devices_.size() - 1); } -TimerHandle Scheduler::AddTimer(std::chrono::nanoseconds period, +TimerHandle Scheduler::AddTimer(const std::chrono::nanoseconds &period, TimerCallback callback) { TimerHandle handle = next_timer_handle_++; @@ -28,7 +21,7 @@ TimerHandle Scheduler::AddTimer(std::chrono::nanoseconds period, } void Scheduler::AdjustTimer(TimerHandle handle, - std::chrono::nanoseconds period) { + const std::chrono::nanoseconds &period) { std::set::iterator it; for (it = timers_.begin(); it != timers_.end(); ++it) { @@ -69,14 +62,14 @@ void Scheduler::RemoveTimer(TimerHandle handle) { timers_.erase(it); } -void Scheduler::Tick() { - UpdatePerf(); +void Scheduler::Tick(const std::chrono::nanoseconds &delta) { + auto next_time = base_time_ + delta; - while (base_time_ < next_time_) { - std::chrono::high_resolution_clock::time_point target_time = next_time_; + while (base_time_ < next_time) { + std::chrono::high_resolution_clock::time_point target_time = next_time; // run devices up until the next timer expiration - if (timers_.size() && timers_.begin()->expire < next_time_) { + if (timers_.size() && timers_.begin()->expire < next_time) { target_time = timers_.begin()->expire; } @@ -112,21 +105,4 @@ void Scheduler::Tick() { timers_.insert(t); } } - - next_time_ = base_time_ + timeslice_; -} - -void Scheduler::UpdatePerf() { - auto now = std::chrono::high_resolution_clock::now(); - auto delta = - std::chrono::duration_cast(now - last_tick_); - tick_deltas_[tick_idx_] = delta.count(); - tick_idx_ = (tick_idx_ + 1) % NUM_TICK_DELTAS; - last_tick_ = now; - - int64_t total = 0; - for (int i = 0; i < NUM_TICK_DELTAS; i++) { - total += tick_deltas_[i]; - } - perf_ = ((timeslice_.count() * NUM_TICK_DELTAS) / (float)total) * 100.0f; } diff --git a/src/emu/scheduler.h b/src/emu/scheduler.h index 423e6ea7..7a12261d 100644 --- a/src/emu/scheduler.h +++ b/src/emu/scheduler.h @@ -12,7 +12,7 @@ namespace emu { typedef std::function TimerCallback; -enum { INVALID_HANDLE = -1, NS_PER_SEC = 1000000000, NUM_TICK_DELTAS = 10 }; +enum { INVALID_HANDLE = -1, NS_PER_SEC = 1000000000, NS_PER_MS = 1000000 }; static inline std::chrono::nanoseconds HZ_TO_NANO(int64_t hz) { return std::chrono::nanoseconds(NS_PER_SEC / hz); @@ -51,29 +51,19 @@ class Scheduler { public: Scheduler(); - float perf() const { return perf_; } - DeviceHandle AddDevice(Device *device); - TimerHandle AddTimer(std::chrono::nanoseconds period, TimerCallback callback); - void AdjustTimer(TimerHandle handle, std::chrono::nanoseconds period); + TimerHandle AddTimer(const std::chrono::nanoseconds &period, + TimerCallback callback); + void AdjustTimer(TimerHandle handle, const std::chrono::nanoseconds &period); void RemoveTimer(TimerHandle handle); - void Tick(); + void Tick(const std::chrono::nanoseconds &delta); private: - void UpdatePerf(); - std::vector devices_; std::set timers_; TimerHandle next_timer_handle_; - std::chrono::nanoseconds timeslice_; std::chrono::high_resolution_clock::time_point base_time_; - std::chrono::high_resolution_clock::time_point next_time_; - - int64_t tick_deltas_[NUM_TICK_DELTAS]; - int tick_idx_; - std::chrono::high_resolution_clock::time_point last_tick_; - float perf_; }; } } diff --git a/src/holly/pvr2.cc b/src/holly/pvr2.cc index e195727c..702eb440 100644 --- a/src/holly/pvr2.cc +++ b/src/holly/pvr2.cc @@ -11,7 +11,6 @@ PVR2::PVR2(Scheduler &scheduler, Memory &memory, Holly &holly) memory_(memory), holly_(holly), ta_(memory, holly, *this), - rb_(nullptr), line_timer_(INVALID_HANDLE), current_scanline_(0), fps_(0), @@ -26,21 +25,20 @@ PVR2::~PVR2() { } bool PVR2::Init(Backend *rb) { - rb_ = rb; - InitMemory(); - if (!ta_.Init(rb_)) { + if (!ta_.Init(rb)) { return false; } Reset(); - ReconfigureVideoOutput(); ReconfigureSPG(); return true; } +void PVR2::RenderLastFrame() { ta_.RenderLastContext(); } + void PVR2::ToggleTracing() { ta_.ToggleTracing(); } namespace dreavm { @@ -121,6 +119,8 @@ void PVR2::WriteRegister(void *ctx, uint32_t addr, uint32_t value) { if (reset_ta) { pvr->ta_.SoftReset(); } + } else if (reg.offset == TA_LIST_INIT_OFFSET) { + pvr->ta_.InitContext(pvr->TA_ISP_BASE.base_address); } else if (reg.offset == STARTRENDER_OFFSET) { { auto now = std::chrono::high_resolution_clock::now(); @@ -130,13 +130,9 @@ void PVR2::WriteRegister(void *ctx, uint32_t addr, uint32_t value) { pvr->fps_ = 1000000000.0f / delta.count(); } - pvr->ta_.RenderContext(pvr->PARAM_BASE.base_address); - } else if (reg.offset == SPG_CONTROL_OFFSET) { - pvr->ReconfigureVideoOutput(); + pvr->ta_.SaveLastContext(pvr->PARAM_BASE.base_address); } else if (reg.offset == SPG_LOAD_OFFSET || reg.offset == FB_R_CTRL_OFFSET) { pvr->ReconfigureSPG(); - } else if (reg.offset == TA_LIST_INIT_OFFSET) { - pvr->ta_.InitContext(pvr->TA_ISP_BASE.base_address); } } } @@ -169,25 +165,6 @@ void PVR2::Reset() { #undef PVR_REG } -void PVR2::ReconfigureVideoOutput() { - int render_width = 320; - int render_height = 240; - - // interlaced and VGA mode both render at full resolution - if (SPG_CONTROL.interlace || (!SPG_CONTROL.NTSC && !SPG_CONTROL.PAL)) { - render_width = 640; - render_height = 480; - } - - LOG_INFO( - "ReconfigureVideoOutput width %d, height %d, interlace %d, NTSC %d, PAL " - "%d", - render_width, render_height, SPG_CONTROL.interlace, SPG_CONTROL.NTSC, - SPG_CONTROL.PAL); - - ta_.ResizeVideo(render_width, render_height); -} - void PVR2::ReconfigureSPG() { static const int PIXEL_CLOCK = 27000000; // 27mhz diff --git a/src/holly/pvr2.h b/src/holly/pvr2.h index 05926a53..43a9df70 100644 --- a/src/holly/pvr2.h +++ b/src/holly/pvr2.h @@ -213,6 +213,7 @@ class PVR2 { float vbps() { return vbps_; } bool Init(renderer::Backend *rb); + void RenderLastFrame(); void ToggleTracing(); private: @@ -227,7 +228,6 @@ class PVR2 { void InitMemory(); void Reset(); - void ReconfigureVideoOutput(); void ReconfigureSPG(); void LineClockUpdate(); @@ -235,7 +235,6 @@ class PVR2 { emu::Memory &memory_; Holly &holly_; TileAccelerator ta_; - renderer::Backend *rb_; emu::TimerHandle line_timer_; uint32_t current_scanline_; diff --git a/src/holly/tile_accelerator.cc b/src/holly/tile_accelerator.cc index de746073..dcabd5dd 100644 --- a/src/holly/tile_accelerator.cc +++ b/src/holly/tile_accelerator.cc @@ -269,7 +269,8 @@ TileAccelerator::TileAccelerator(Memory &memory, Holly &holly, PVR2 &pvr) holly_(holly), pvr_(pvr), texcache_(*this), - renderer_(texcache_) {} + tile_renderer_(texcache_), + last_context_(&scratch_context_) {} TileAccelerator::~TileAccelerator() { while (contexts_.size()) { @@ -290,14 +291,6 @@ bool TileAccelerator::Init(Backend *rb) { return true; } -void TileAccelerator::ResizeVideo(int width, int height) { - rb_->SetFramebufferSize(FB_TILE_ACCELERATOR, width, height); - - if (trace_writer_) { - trace_writer_->WriteResizeVideo(width, height); - } -} - void TileAccelerator::SoftReset() { // FIXME what are we supposed to do here? } @@ -360,24 +353,29 @@ void TileAccelerator::WriteContext(uint32_t addr, uint32_t value) { } } -void TileAccelerator::RenderContext(uint32_t addr) { - // get context and update with PVR state - TileContext *tactx = GetContext(addr); +void TileAccelerator::SaveLastContext(uint32_t addr) { + // swap context with last context to be delayed rendered + auto it = FindContext(addr); + TileContext *tmp = last_context_; + last_context_ = it->second; + it->second = tmp; - WritePVRState(tactx); - WriteBackgroundState(tactx); + // save PVR state to context + WritePVRState(last_context_); + WriteBackgroundState(last_context_); - // do the actual rendering - renderer_.RenderContext(tactx, rb_); - - // let holly know the rendering is complete + // tell holly that rendering is complete holly_.RequestInterrupt(HOLLY_INTC_PCEOVINT); holly_.RequestInterrupt(HOLLY_INTC_PCEOIINT); holly_.RequestInterrupt(HOLLY_INTC_PCEOTINT); +} + +void TileAccelerator::RenderLastContext() { + tile_renderer_.RenderContext(last_context_, rb_); // add render to trace if (trace_writer_) { - trace_writer_->WriteRenderContext(tactx); + trace_writer_->WriteRenderContext(last_context_); } } @@ -395,11 +393,6 @@ void TileAccelerator::ToggleTracing() { LOG_INFO("Begin tracing to %s", filename); - // write out the initial framebuffer size - int width, height; - rb_->GetFramebufferSize(FB_TILE_ACCELERATOR, &width, &height); - trace_writer_->WriteResizeVideo(width, height); - // clear the texture cache, so the next render will write out insert // texture commands for any textures in use texcache_.Clear(); @@ -456,18 +449,25 @@ void TileAccelerator::InitMemory() { &TileAccelerator::WriteTexture, nullptr); } -TileContext *TileAccelerator::GetContext(uint32_t addr) { - auto it = contexts_.find(addr); +TileContextIterator TileAccelerator::FindContext(uint32_t addr) { + TileContextIterator it = contexts_.find(addr); - if (it != contexts_.end()) { - return it->second; + // add context if it doesn't exist + if (it == contexts_.end()) { + TileContext *ctx = new TileContext(); + auto result = contexts_.insert(std::make_pair(addr, ctx)); + it = result.first; } - TileContext *ctx = new TileContext(); - ctx->addr = addr; + // set context address + it->second->addr = addr; - auto result = contexts_.insert(std::make_pair(addr, ctx)); - return result.first->second; + return it; +} + +TileContext *TileAccelerator::GetContext(uint32_t addr) { + TileContextIterator it = FindContext(addr); + return it->second; } void TileAccelerator::WritePVRState(TileContext *tactx) { @@ -484,6 +484,18 @@ void TileAccelerator::WritePVRState(TileContext *tactx) { // texture palette pixel format tactx->pal_pxl_format = pvr_.PAL_RAM_CTRL.pixel_format; + + // write out video width to help with unprojecting the screen space + // coordinates + if (pvr_.SPG_CONTROL.interlace || + (!pvr_.SPG_CONTROL.NTSC && !pvr_.SPG_CONTROL.PAL)) { + // interlaced and VGA mode both render at full resolution + tactx->video_width = 640; + tactx->video_height = 480; + } else { + tactx->video_width = 320; + tactx->video_height = 240; + } } void TileAccelerator::WriteBackgroundState(TileContext *tactx) { diff --git a/src/holly/tile_accelerator.h b/src/holly/tile_accelerator.h index 761e7497..4415bd57 100644 --- a/src/holly/tile_accelerator.h +++ b/src/holly/tile_accelerator.h @@ -452,6 +452,8 @@ struct TileContext { bool autosort; int stride; int pal_pxl_format; + int video_width; + int video_height; ISP_TSP bg_isp; TSP bg_tsp; TCW bg_tcw; @@ -486,6 +488,9 @@ class TileTextureCache : public TextureCache { std::unordered_map textures_; }; +typedef std::unordered_map TileContextMap; +typedef TileContextMap::iterator TileContextIterator; + class TileAccelerator { friend class TileTextureCache; @@ -499,12 +504,11 @@ class TileAccelerator { bool Init(renderer::Backend *rb); - void ResizeVideo(int width, int height); - void SoftReset(); void InitContext(uint32_t addr); void WriteContext(uint32_t addr, uint32_t value); - void RenderContext(uint32_t addr); + void SaveLastContext(uint32_t addr); + void RenderLastContext(); void ToggleTracing(); @@ -515,6 +519,7 @@ class TileAccelerator { static void WriteTexture(void *ctx, uint32_t addr, T value); void InitMemory(); + TileContextIterator FindContext(uint32_t addr); TileContext *GetContext(uint32_t addr); void WritePVRState(TileContext *tactx); void WriteBackgroundState(TileContext *tactx); @@ -525,8 +530,10 @@ class TileAccelerator { renderer::Backend *rb_; TileTextureCache texcache_; - TileRenderer renderer_; - std::unordered_map contexts_; + TileRenderer tile_renderer_; + TileContextMap contexts_; + TileContext scratch_context_; + TileContext *last_context_; std::unique_ptr trace_writer_; }; diff --git a/src/holly/tile_renderer.cc b/src/holly/tile_renderer.cc index 63221a90..0157d734 100644 --- a/src/holly/tile_renderer.cc +++ b/src/holly/tile_renderer.cc @@ -113,8 +113,6 @@ void TileRenderer::RenderContext(const TileContext *tactx, Backend *rb) { Reset(); - rb->GetFramebufferSize(FB_TILE_ACCELERATOR, &width_, &height_); - ParseBackground(tactx); while (data < end) { @@ -163,12 +161,10 @@ void TileRenderer::RenderContext(const TileContext *tactx, Backend *rb) { data += TileAccelerator::GetParamSize(pcw, vertex_type_); } - // LOG_INFO("StartRender %d surfs, %d verts, %d bytes", num_surfs_, num_verts, - // tactx->size); + // LOG_INFO("StartRender %d surfs, %d verts, %d bytes", num_surfs_, + // num_verts_, tactx->size); - const Eigen::Matrix4f &projection = GetProjectionMatrix(); - rb->BindFramebuffer(FB_TILE_ACCELERATOR); - rb->Clear(0.1f, 0.39f, 0.88f, 1.0f); + const Eigen::Matrix4f &projection = GetProjectionMatrix(tactx); rb->RenderSurfaces(projection, surfs_, num_surfs_, verts_, num_verts_, sorted_surfs_); } @@ -328,13 +324,13 @@ void TileRenderer::ParseBackground(const TileContext *tactx) { // override the xyz values supplied by ISP_BACKGND_T. while the hardware docs // act like the should be correct, they're most definitely not in most cases verts[0]->xyz[0] = 0.0f; - verts[0]->xyz[1] = (float)height_; + verts[0]->xyz[1] = (float)tactx->video_height; verts[0]->xyz[2] = tactx->bg_depth; verts[1]->xyz[0] = 0.0f; verts[1]->xyz[1] = 0.0f; verts[1]->xyz[2] = tactx->bg_depth; - verts[2]->xyz[0] = (float)width_; - verts[2]->xyz[1] = (float)height_; + verts[2]->xyz[0] = (float)tactx->video_width; + verts[2]->xyz[1] = (float)tactx->video_height; verts[2]->xyz[2] = tactx->bg_depth; // 4th vertex isn't supplied, fill it out automatically @@ -657,7 +653,7 @@ void TileRenderer::ParseEndOfList(const TileContext *tactx) { // projection on the vertices as they're already perspective correct, the // renderer backend will have to deal with setting the W component of each // in order to perspective correct the texture mapping. -Eigen::Matrix4f TileRenderer::GetProjectionMatrix() { +Eigen::Matrix4f TileRenderer::GetProjectionMatrix(const TileContext *tactx) { float znear = std::numeric_limits::min(); float zfar = std::numeric_limits::max(); @@ -682,8 +678,8 @@ Eigen::Matrix4f TileRenderer::GetProjectionMatrix() { // convert from window space coordinates into clip space Eigen::Matrix4f p = Eigen::Matrix4f::Identity(); - p(0, 0) = 2.0f / (float)width_; - p(1, 1) = -2.0f / (float)height_; + p(0, 0) = 2.0f / (float)tactx->video_width; + p(1, 1) = -2.0f / (float)tactx->video_height; p(0, 3) = -1.0f; p(1, 3) = 1.0f; p(2, 2) = (-znear - zfar) / zdepth; diff --git a/src/holly/tile_renderer.h b/src/holly/tile_renderer.h index 66dcaacf..407869ac 100644 --- a/src/holly/tile_renderer.h +++ b/src/holly/tile_renderer.h @@ -58,7 +58,7 @@ class TileRenderer { void ParseVertexParam(const TileContext *tactx, renderer::Backend *rb, const VertexParam *param); void ParseEndOfList(const TileContext *tactx); - Eigen::Matrix4f GetProjectionMatrix(); + Eigen::Matrix4f GetProjectionMatrix(const TileContext *tactx); renderer::TextureHandle RegisterTexture(const TileContext *tactx, renderer::Backend *rb, const TSP &tsp, @@ -82,7 +82,6 @@ class TileRenderer { // current render state renderer::Surface surfs_[MAX_SURFACES]; renderer::Vertex verts_[MAX_VERTICES]; - int width_, height_; int num_surfs_; int num_verts_; int sorted_surfs_[MAX_SURFACES]; diff --git a/src/main.cc b/src/main.cc index 15382704..7750c98f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,5 +1,4 @@ #include -#include "system/system.h" #include "emu/emulator.h" #include "trace/trace_viewer.h" @@ -29,60 +28,19 @@ void InitFlags(int *argc, char ***argv) { void ShutdownFlags() { google::ShutDownCommandLineFlags(); } -void RunEmulator(const char *launch) { - System sys; - Emulator emu(sys); - - if (!sys.Init()) { - LOG_FATAL("Failed to initialize window."); - } - - if (!emu.Init()) { - LOG_FATAL("Failed to initialize emulator."); - } - - if (launch && !emu.Launch(launch)) { - LOG_FATAL("Failed to load %s", launch); - } - - while (1) { - sys.Tick(); - emu.Tick(); - } -} - -void RunTraceViewer(const char *trace) { - System sys; - TraceViewer tracer(sys); - - if (!sys.Init()) { - LOG_FATAL("Failed to initialize window."); - } - - if (!tracer.Init()) { - LOG_FATAL("Failed to initialize tracer."); - } - - if (!tracer.Load(trace)) { - LOG_FATAL("Failed to load %s", trace); - } - - while (1) { - sys.Tick(); - tracer.Tick(); - } -} - int main(int argc, char **argv) { EnsureAppDirExists(); InitFlags(&argc, &argv); const char *load = argc > 1 ? argv[1] : nullptr; + if (load && strstr(load, ".trace")) { - RunTraceViewer(load); + TraceViewer tracer; + tracer.Run(load); } else { - RunEmulator(load); + Emulator emu; + emu.Run(load); } ShutdownFlags(); diff --git a/src/renderer/backend.h b/src/renderer/backend.h index acbda847..eda8cbba 100644 --- a/src/renderer/backend.h +++ b/src/renderer/backend.h @@ -13,11 +13,6 @@ enum FilterMode { // FILTER_BILINEAR }; -enum Framebuffer { // - FB_DEFAULT, - FB_TILE_ACCELERATOR -}; - enum PixelFormat { PXL_INVALID, PXL_RGBA5551, @@ -110,18 +105,14 @@ class Backend { virtual bool Init() = 0; + virtual void ResizeVideo(int width, int height) = 0; + virtual TextureHandle RegisterTexture(PixelFormat format, FilterMode filter, bool gen_mipmaps, int width, int height, const uint8_t *buffer) = 0; virtual void FreeTexture(TextureHandle handle) = 0; - virtual void SetFramebufferSize(Framebuffer fb, int width, int height) = 0; - virtual void GetFramebufferSize(Framebuffer fb, int *width, int *height) = 0; - virtual void BeginFrame() = 0; - virtual void BindFramebuffer(Framebuffer fb) = 0; - virtual void Clear(float r, float g, float b, float a) = 0; - virtual void RenderFramebuffer(Framebuffer fb) = 0; virtual void RenderText2D(int x, int y, float point_size, uint32_t color, const char *text) = 0; virtual void RenderBox2D(int x0, int y0, int x1, int y1, uint32_t color, diff --git a/src/renderer/gl_backend.cc b/src/renderer/gl_backend.cc index dfaeaca4..5add777f 100644 --- a/src/renderer/gl_backend.cc +++ b/src/renderer/gl_backend.cc @@ -53,23 +53,20 @@ static GLenum blend_funcs[] = { GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR}; GLBackend::GLBackend(GLContext &ctx) - : ctx_(ctx), textures_{0}, fb_ta_(0), num_verts2d_(0), num_surfs2d_(0) {} + : ctx_(ctx), textures_{0}, num_verts2d_(0), num_surfs2d_(0) {} GLBackend::~GLBackend() { DestroyFonts(); DestroyVertexBuffers(); DestroyShaders(); DestroyTextures(); - DestroyFramebuffers(); } bool GLBackend::Init() { - if (!ctx_.GLInit(&state_.video_width, &state_.video_height)) { + if (!ctx_.GLInitContext(&state_.video_width, &state_.video_height)) { return false; } - // can't initialize framebuffers here, must wait for first resize - // InitFramebuffers(); InitTextures(); InitShaders(); InitVertexBuffers(); @@ -79,6 +76,11 @@ bool GLBackend::Init() { return true; } +void GLBackend::ResizeVideo(int width, int height) { + state_.video_width = width; + state_.video_height = height; +} + TextureHandle GLBackend::RegisterTexture(PixelFormat format, FilterMode filter, bool gen_mipmaps, int width, int height, const uint8_t *buffer) { @@ -141,114 +143,16 @@ void GLBackend::FreeTexture(TextureHandle handle) { gltex = 0; } -void GLBackend::SetFramebufferSize(Framebuffer fb, int width, int height) { - switch (fb) { - case FB_DEFAULT: - state_.video_width = width; - state_.video_height = height; - break; - - case FB_TILE_ACCELERATOR: - state_.ta_width = width; - state_.ta_height = height; - DestroyFramebuffers(); - InitFramebuffers(); - break; - } -} - -void GLBackend::GetFramebufferSize(Framebuffer fb, int *width, int *height) { - switch (fb) { - case FB_DEFAULT: - *width = state_.video_width; - *height = state_.video_height; - break; - - case FB_TILE_ACCELERATOR: - *width = state_.ta_width; - *height = state_.ta_height; - break; - } -} - void GLBackend::BeginFrame() { - BindFramebuffer(FB_DEFAULT); - - Clear(0.0f, 0.0f, 0.0f, 1.0f); -} - -void GLBackend::BindFramebuffer(Framebuffer fb) { - Flush2D(); - - GLuint buffer = 0; - int width = 0; - int height = 0; - - switch (fb) { - case FB_DEFAULT: - buffer = 0; - width = state_.video_width; - height = state_.video_height; - break; - - case FB_TILE_ACCELERATOR: - // ensure ta was initialized through SetFramebufferSize - CHECK_GT(fb_ta_, 0); - buffer = fb_ta_; - width = state_.ta_width; - height = state_.ta_height; - break; - } - - glBindFramebuffer(GL_FRAMEBUFFER, buffer); - glViewport(0, 0, width, height); - glScissor(0, 0, width, height); -} - -void GLBackend::Clear(float r, float g, float b, float a) { SetDepthMask(true); - glClearColor(r, g, b, a); + glViewport(0, 0, state_.video_width, state_.video_height); + glScissor(0, 0, state_.video_width, state_.video_height); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } -void GLBackend::RenderFramebuffer(Framebuffer fb) { - switch (fb) { - case FB_DEFAULT: - LOG_FATAL("Unsupported"); - break; - - case FB_TILE_ACCELERATOR: - Vertex2D *vert = AllocVertices2D( - {GL_TRIANGLES, (int)fb_ta_color_, BLEND_NONE, BLEND_NONE, 0}, 6); - - Q0(vert, x, 0.0f); - Q0(vert, y, 0.0f); - Q0(vert, color, 0xffffffff); - Q0(vert, u, 0.0f); - Q0(vert, v, 1.0f); - - Q1(vert, x, (float)state_.video_width); - Q1(vert, y, 0.0f); - Q1(vert, color, 0xffffffff); - Q1(vert, u, 1.0f); - Q1(vert, v, 1.0f); - - Q2(vert, x, (float)state_.video_width); - Q2(vert, y, (float)state_.video_height); - Q2(vert, color, 0xffffffff); - Q2(vert, u, 1.0f); - Q2(vert, v, 0.0f); - - Q3(vert, x, 0.0f); - Q3(vert, y, (float)state_.video_height); - Q3(vert, color, 0xffffffff); - Q3(vert, u, 0.0f); - Q3(vert, v, 0.0f); - break; - } -} - void GLBackend::RenderText2D(int x, int y, float point_size, uint32_t color, const char *text) { float fx = (float)x; @@ -429,43 +333,6 @@ void GLBackend::EndFrame() { ctx_.GLSwapBuffers(); } -void GLBackend::InitFramebuffers() { - CHECK_GT(state_.ta_width, 0); - CHECK_GT(state_.ta_height, 0); - - glGenFramebuffers(1, &fb_ta_); - glGenTextures(1, &fb_ta_color_); - glGenRenderbuffers(1, &fb_ta_depth_); - - glBindTexture(GL_TEXTURE_2D, fb_ta_color_); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, state_.ta_width, state_.ta_height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - - glBindRenderbuffer(GL_RENDERBUFFER, fb_ta_depth_); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, state_.ta_width, - state_.ta_height); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - - glBindFramebuffer(GL_FRAMEBUFFER, fb_ta_); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, fb_ta_color_, 0); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, fb_ta_depth_); - GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - CHECK_EQ(status, GL_FRAMEBUFFER_COMPLETE); - Clear(0.0f, 0.0f, 0.0f, 1.0f); - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} - -void GLBackend::DestroyFramebuffers() { - glDeleteFramebuffers(1, &fb_ta_); - glDeleteTextures(1, &fb_ta_color_); - glDeleteRenderbuffers(1, &fb_ta_depth_); -} - void GLBackend::InitTextures() { uint8_t pixels[64 * 64 * 4]; memset(pixels, 0xff, sizeof(pixels)); @@ -580,12 +447,7 @@ void GLBackend::DestroyFonts() { } } -void GLBackend::SetupDefaultState() { - glEnable(GL_SCISSOR_TEST); - glDrawBuffer(GL_FRONT_AND_BACK); - Clear(0.0f, 0.0f, 0.0f, 1.0f); - glDrawBuffer(GL_BACK); -} +void GLBackend::SetupDefaultState() { glEnable(GL_SCISSOR_TEST); } void GLBackend::SetDepthMask(bool enabled) { if (state_.depth_mask == enabled) { diff --git a/src/renderer/gl_backend.h b/src/renderer/gl_backend.h index d9909472..fecfb388 100644 --- a/src/renderer/gl_backend.h +++ b/src/renderer/gl_backend.h @@ -71,18 +71,14 @@ class GLBackend : public Backend { bool Init(); + void ResizeVideo(int width, int height); + TextureHandle RegisterTexture(PixelFormat format, FilterMode filter, bool gen_mipmaps, int width, int height, const uint8_t *buffer); void FreeTexture(TextureHandle handle); - void SetFramebufferSize(Framebuffer fb, int width, int height); - void GetFramebufferSize(Framebuffer fb, int *width, int *height); - void BeginFrame(); - void BindFramebuffer(Framebuffer fb); - void Clear(float r, float g, float b, float a); - void RenderFramebuffer(Framebuffer fb); void RenderText2D(int x, int y, float point_size, uint32_t color, const char *text); void RenderBox2D(int x0, int y0, int x1, int y1, uint32_t color, @@ -95,8 +91,6 @@ class GLBackend : public Backend { void EndFrame(); private: - void InitFramebuffers(); - void DestroyFramebuffers(); void InitTextures(); void DestroyTextures(); void InitShaders(); @@ -130,8 +124,6 @@ class GLBackend : public Backend { GLuint ui_vao_, ui_vbo_; GLuint ta_vao_, ta_vbo_; - GLuint fb_ta_, fb_ta_color_, fb_ta_depth_; - Vertex2D verts2d_[MAX_2D_VERTICES]; int num_verts2d_; diff --git a/src/renderer/gl_context.h b/src/renderer/gl_context.h index 215906a2..390f4729 100644 --- a/src/renderer/gl_context.h +++ b/src/renderer/gl_context.h @@ -6,7 +6,8 @@ namespace renderer { class GLContext { public: - virtual bool GLInit(int *width, int *height) = 0; + virtual bool GLInitContext(int *width, int *height) = 0; + virtual void GLDestroyContext() = 0; virtual void GLSwapBuffers() = 0; }; } diff --git a/src/system/system.cc b/src/system/system.cc index cad0a89d..a14f9a1f 100644 --- a/src/system/system.cc +++ b/src/system/system.cc @@ -4,8 +4,8 @@ #include "core/core.h" #include "system/system.h" -#define DEFAULT_VIDEO_WIDTH 800 -#define DEFAULT_VIDEO_HEIGHT 600 +#define DEFAULT_VIDEO_WIDTH 640 +#define DEFAULT_VIDEO_HEIGHT 480 using namespace dreavm::core; using namespace dreavm::system; @@ -43,14 +43,10 @@ System::System() events_(MAX_EVENTS) {} System::~System() { + GLDestroyContext(); DestroyInput(); DestroyWindow(); DestroySDL(); - - if (glcontext_) { - SDL_GL_DeleteContext(glcontext_); - glcontext_ = nullptr; - } } bool System::Init() { @@ -69,16 +65,7 @@ bool System::Init() { return true; } -void System::Tick() { PumpEvents(); } - -void System::QueueEvent(const SystemEvent &ev) { - if (events_.Full()) { - LOG_WARNING("System event overflow"); - return; - } - - events_.PushBack(ev); -} +void System::PumpEvents() { PumpSDLEvents(); } bool System::PollEvent(SystemEvent *ev) { if (events_.Empty()) { @@ -91,11 +78,16 @@ bool System::PollEvent(SystemEvent *ev) { return true; } -bool System::GLInit(int *width, int *height) { +bool System::GLInitContext(int *width, int *height) { + // need at least a 3.3 core context for our shaders SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + // request a 24-bit depth buffer. 16-bits isn't enough precision when + // unprojecting dreamcast coordinates, see TileRenderer::GetProjectionMatrix + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + glcontext_ = SDL_GL_CreateContext(window_); if (!glcontext_) { LOG_WARNING("OpenGL context creation failed: %s"); @@ -119,10 +111,17 @@ bool System::GLInit(int *width, int *height) { return true; } +void System::GLDestroyContext() { + if (glcontext_) { + SDL_GL_DeleteContext(glcontext_); + glcontext_ = nullptr; + } +} + void System::GLSwapBuffers() { SDL_GL_SwapWindow(window_); } bool System::InitSDL() { - if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) < 0) { + if (SDL_Init(0) < 0) { LOG_WARNING("SDL initialization failed: %s", SDL_GetError()); return false; } @@ -133,11 +132,14 @@ bool System::InitSDL() { void System::DestroySDL() { SDL_Quit(); } bool System::InitWindow() { - unsigned window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; + if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { + LOG_WARNING("Video initialization failed: %s", SDL_GetError()); + return false; + } window_ = SDL_CreateWindow("dreavm", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, video_width_, - video_height_, window_flags); + video_height_, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if (!window_) { LOG_WARNING("Window creation failed: %s", SDL_GetError()); return false; @@ -147,8 +149,10 @@ bool System::InitWindow() { } void System::DestroyWindow() { - SDL_DestroyWindow(window_); - window_ = nullptr; + if (window_) { + SDL_DestroyWindow(window_); + window_ = nullptr; + } } bool System::InitInput() { @@ -187,6 +191,15 @@ void System::DestroyJoystick() { } } +void System::QueueEvent(const SystemEvent &ev) { + if (events_.Full()) { + LOG_WARNING("System event overflow"); + return; + } + + events_.PushBack(ev); +} + Keycode System::TranslateSDLKey(SDL_Keysym keysym) { Keycode out = K_UNKNOWN; @@ -818,5 +831,3 @@ void System::PumpSDLEvents() { } } } - -void System::PumpEvents() { PumpSDLEvents(); } diff --git a/src/system/system.h b/src/system/system.h index f1a8a00c..bce99470 100644 --- a/src/system/system.h +++ b/src/system/system.h @@ -14,7 +14,7 @@ enum { NUM_JOYSTICK_AXES = (K_AXIS15 - K_AXIS0) + 1, NUM_JOYSTICK_KEYS = (K_JOY31 - K_JOY0) + 1 }; -enum SystemEventType { SE_NONE, SE_KEY, SE_MOUSEMOVE, SE_RESIZE }; +enum SystemEventType { SE_KEY, SE_MOUSEMOVE, SE_RESIZE }; struct SystemEvent { SystemEventType type; @@ -41,10 +41,12 @@ class System : public renderer::GLContext { ~System(); bool Init(); - void Tick(); + + void PumpEvents(); bool PollEvent(SystemEvent *ev); - bool GLInit(int *width, int *height); + bool GLInitContext(int *width, int *height); + void GLDestroyContext(); void GLSwapBuffers(); private: @@ -61,7 +63,6 @@ class System : public renderer::GLContext { Keycode TranslateSDLKey(SDL_Keysym keysym); void PumpSDLEvents(); - void PumpEvents(); int video_width_; int video_height_; diff --git a/src/trace/trace.cc b/src/trace/trace.cc index 1e88d054..0dbd8abe 100644 --- a/src/trace/trace.cc +++ b/src/trace/trace.cc @@ -78,10 +78,6 @@ bool TraceReader::PatchPointers() { // patch relative data pointers switch (curr_cmd->type) { - case TRACE_RESIZE_VIDEO: { - ptr += sizeof(*curr_cmd); - } break; - case TRACE_INSERT_TEXTURE: { curr_cmd->insert_texture.texture += reinterpret_cast(ptr); curr_cmd->insert_texture.palette += reinterpret_cast(ptr); @@ -111,18 +107,10 @@ bool TraceReader::PatchPointers() { bool TraceReader::PatchOverrides() { TraceCommand *cmd = cmd_head(); - TraceCommand *last_resize = nullptr; std::unordered_map last_inserts; while (cmd) { switch (cmd->type) { - case TRACE_RESIZE_VIDEO: { - if (last_resize) { - cmd->override = last_resize; - } - last_resize = cmd; - } break; - case TRACE_INSERT_TEXTURE: { uint32_t texture_key = TextureCache::GetTextureKey( cmd->insert_texture.tsp, cmd->insert_texture.tcw); @@ -168,15 +156,6 @@ void TraceWriter::Close() { } } -void TraceWriter::WriteResizeVideo(int width, int height) { - TraceCommand cmd; - cmd.type = TRACE_RESIZE_VIDEO; - cmd.resize_video.width = width; - cmd.resize_video.height = height; - - CHECK_EQ(fwrite(&cmd, sizeof(cmd), 1, file_), 1); -} - void TraceWriter::WriteInsertTexture(const TSP &tsp, const TCW &tcw, const uint8_t *texture, int texture_size, const uint8_t *palette, int palette_size) { @@ -205,6 +184,8 @@ void TraceWriter::WriteRenderContext(TileContext *tactx) { cmd.render_context.autosort = tactx->autosort; cmd.render_context.stride = tactx->stride; cmd.render_context.pal_pxl_format = tactx->pal_pxl_format; + cmd.render_context.video_width = tactx->video_width; + cmd.render_context.video_height = tactx->video_height; cmd.render_context.bg_isp = tactx->bg_isp; cmd.render_context.bg_tsp = tactx->bg_tsp; cmd.render_context.bg_tcw = tactx->bg_tcw; diff --git a/src/trace/trace.h b/src/trace/trace.h index 28c5f617..517a52d0 100644 --- a/src/trace/trace.h +++ b/src/trace/trace.h @@ -6,11 +6,7 @@ namespace dreavm { namespace trace { -enum TraceCommandType { - TRACE_RESIZE_VIDEO, - TRACE_INSERT_TEXTURE, - TRACE_RENDER_CONTEXT -}; +enum TraceCommandType { TRACE_INSERT_TEXTURE, TRACE_RENDER_CONTEXT }; struct TraceCommand { TraceCommand() : prev(nullptr), next(nullptr), override(nullptr) {} @@ -25,11 +21,6 @@ struct TraceCommand { // the data pointers in these structs are written out relative to the cmd, // and patched to absolute pointers on read union { - struct { - uint32_t width; - uint32_t height; - } resize_video; - struct { holly::TSP tsp; holly::TCW tcw; @@ -45,6 +36,8 @@ struct TraceCommand { int8_t autosort; uint32_t stride; uint32_t pal_pxl_format; + uint32_t video_width; + uint32_t video_height; holly::ISP_TSP bg_isp; holly::TSP bg_tsp; holly::TCW bg_tcw; @@ -85,7 +78,6 @@ class TraceWriter { bool Open(const char *filename); void Close(); - void WriteResizeVideo(int width, int height); void WriteInsertTexture(const holly::TSP &tsp, const holly::TCW &tcw, const uint8_t *texture, int texture_size, const uint8_t *palette, int palette_size); diff --git a/src/trace/trace_viewer.cc b/src/trace/trace_viewer.cc index 1fc330dc..0be328a1 100644 --- a/src/trace/trace_viewer.cc +++ b/src/trace/trace_viewer.cc @@ -42,13 +42,34 @@ TextureHandle TraceTextureCache::GetTexture( return texture.handle; } -TraceViewer::TraceViewer(System &sys) : sys_(sys), renderer_(texcache_) { - rb_ = new GLBackend(sys); +TraceViewer::TraceViewer() : tile_renderer_(texcache_) { + rb_ = new GLBackend(sys_); } TraceViewer::~TraceViewer() { delete rb_; } +void TraceViewer::Run(const char *path) { + if (!Init()) { + LOG_WARNING("Failed to initialize trace viewer"); + return; + } + + if (!Parse(path)) { + return; + } + + while (true) { + PumpEvents(); + + RenderFrame(); + } +} + bool TraceViewer::Init() { + if (!sys_.Init()) { + return false; + } + if (!rb_->Init()) { return false; } @@ -56,14 +77,15 @@ bool TraceViewer::Init() { return true; } -bool TraceViewer::Load(const char *path) { +bool TraceViewer::Parse(const char *path) { if (!reader_.Parse(path)) { - LOG_INFO("Failed to parse %s", path); + LOG_WARNING("Failed to parse %s", path); return false; } num_frames_ = GetNumFrames(); if (!num_frames_) { + LOG_WARNING("No frames in %s", path); return false; } @@ -74,24 +96,23 @@ bool TraceViewer::Load(const char *path) { return true; } -void TraceViewer::Tick() { - PumpEvents(); - - RenderFrame(); -} - void TraceViewer::PumpEvents() { SystemEvent ev; + sys_.PumpEvents(); + while (sys_.PollEvent(&ev)) { - if (ev.type == SE_KEY) { - if (ev.key.code == K_LEFT && ev.key.value) { - PrevContext(); - } else if (ev.key.code == K_RIGHT && ev.key.value) { - NextContext(); - } - } else if (ev.type == SE_RESIZE) { - rb_->SetFramebufferSize(FB_DEFAULT, ev.resize.width, ev.resize.height); + switch (ev.type) { + case SE_KEY: { + if (ev.key.code == K_LEFT && ev.key.value) { + PrevContext(); + } else if (ev.key.code == K_RIGHT && ev.key.value) { + NextContext(); + } + } break; + + default: + break; } } } @@ -99,7 +120,7 @@ void TraceViewer::PumpEvents() { void TraceViewer::RenderFrame() { rb_->BeginFrame(); - rb_->RenderFramebuffer(FB_TILE_ACCELERATOR); + tile_renderer_.RenderContext(¤t_ctx_, rb_); // render stats char stats[512]; @@ -136,6 +157,8 @@ void TraceViewer::CopyCommandToContext(const TraceCommand *cmd, ctx->bg_tsp = cmd->render_context.bg_tsp; ctx->bg_tcw = cmd->render_context.bg_tcw; ctx->bg_depth = cmd->render_context.bg_depth; + ctx->video_width = cmd->render_context.video_width; + ctx->video_height = cmd->render_context.video_height; memcpy(ctx->bg_vertices, cmd->render_context.bg_vertices, cmd->render_context.bg_vertices_size); memcpy(ctx->data, cmd->render_context.data, cmd->render_context.data_size); @@ -155,14 +178,7 @@ void TraceViewer::PrevContext() { while (current_cmd_) { TraceCommand *override = current_cmd_->override; - if (current_cmd_->type == TRACE_RESIZE_VIDEO) { - if (override) { - CHECK_EQ(override->type, TRACE_RESIZE_VIDEO); - rb_->SetFramebufferSize(FB_TILE_ACCELERATOR, - override->resize_video.width, - override->resize_video.height); - } - } else if (current_cmd_->type == TRACE_INSERT_TEXTURE) { + if (current_cmd_->type == TRACE_INSERT_TEXTURE) { texcache_.RemoveTexture(current_cmd_->insert_texture.tsp, current_cmd_->insert_texture.tcw); @@ -183,10 +199,7 @@ void TraceViewer::PrevContext() { CHECK_NOTNULL(current_cmd_); - // render the context - TileContext ctx; - CopyCommandToContext(current_cmd_, &ctx); - renderer_.RenderContext(&ctx, rb_); + CopyCommandToContext(current_cmd_, ¤t_ctx_); } void TraceViewer::NextContext() { @@ -198,11 +211,7 @@ void TraceViewer::NextContext() { current_cmd_ = current_cmd_ ? current_cmd_->next : reader_.cmd_head(); while (current_cmd_) { - if (current_cmd_->type == TRACE_RESIZE_VIDEO) { - rb_->SetFramebufferSize(FB_TILE_ACCELERATOR, - current_cmd_->resize_video.width, - current_cmd_->resize_video.height); - } else if (current_cmd_->type == TRACE_INSERT_TEXTURE) { + if (current_cmd_->type == TRACE_INSERT_TEXTURE) { texcache_.AddTexture(current_cmd_->insert_texture.tsp, current_cmd_->insert_texture.tcw, current_cmd_->insert_texture.texture, @@ -219,7 +228,5 @@ void TraceViewer::NextContext() { CHECK_NOTNULL(current_cmd_); // render the context - TileContext ctx; - CopyCommandToContext(current_cmd_, &ctx); - renderer_.RenderContext(&ctx, rb_); + CopyCommandToContext(current_cmd_, ¤t_ctx_); } diff --git a/src/trace/trace_viewer.h b/src/trace/trace_viewer.h index 64c5894e..70d61660 100644 --- a/src/trace/trace_viewer.h +++ b/src/trace/trace_viewer.h @@ -34,14 +34,15 @@ class TraceTextureCache : public holly::TextureCache { class TraceViewer { public: - TraceViewer(system::System &sys); + TraceViewer(); ~TraceViewer(); - bool Init(); - bool Load(const char *path); - void Tick(); + void Run(const char *path); private: + bool Init(); + bool Parse(const char *path); + void PumpEvents(); void RenderFrame(); @@ -50,15 +51,16 @@ class TraceViewer { void PrevContext(); void NextContext(); - system::System &sys_; + system::System sys_; TraceTextureCache texcache_; - holly::TileRenderer renderer_; + holly::TileRenderer tile_renderer_; renderer::Backend *rb_; TraceReader reader_; TraceCommand *current_cmd_; int num_frames_; int current_frame_; + holly::TileContext current_ctx_; }; } }