From 0bcc30559bd3e75e5b699e960a2affacd01207fc Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Fri, 11 Sep 2015 00:07:20 -0700 Subject: [PATCH] split up Dreamcast object into hw::Dreamcast and emu::Emulator --- CMakeLists.txt | 3 +- src/emu/emulator.cc | 258 +++++++++++++++++++++ src/emu/emulator.h | 36 +++ src/hw/aica/aica.cc | 8 +- src/hw/aica/aica.h | 12 +- src/{emu => hw}/dreamcast.cc | 373 ++++++++----------------------- src/{emu => hw}/dreamcast.h | 128 +++++------ src/hw/gdrom/gdrom.cc | 8 +- src/hw/gdrom/gdrom.h | 15 +- src/hw/holly/holly.cc | 8 +- src/hw/holly/holly.h | 16 +- src/hw/holly/pvr2.cc | 8 +- src/hw/holly/pvr2.h | 14 +- src/hw/holly/tile_accelerator.cc | 8 +- src/hw/holly/tile_accelerator.h | 15 +- src/hw/maple/maple.cc | 8 +- src/hw/maple/maple.h | 15 +- src/hw/sh4/sh4.cc | 4 +- src/hw/sh4/sh4.h | 2 +- src/main.cc | 11 +- 20 files changed, 532 insertions(+), 418 deletions(-) create mode 100644 src/emu/emulator.cc create mode 100644 src/emu/emulator.h rename src/{emu => hw}/dreamcast.cc (59%) rename src/{emu => hw}/dreamcast.h (54%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2669375..2f18d58c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,7 +106,7 @@ set(DREAVM_SOURCES src/core/assert.cc src/core/filesystem.cc src/core/log.cc - src/emu/dreamcast.cc + src/emu/emulator.cc src/emu/profiler.cc src/hw/aica/aica.cc src/hw/gdrom/disc.cc @@ -118,6 +118,7 @@ set(DREAVM_SOURCES src/hw/maple/maple.cc src/hw/maple/maple_controller.cc src/hw/sh4/sh4.cc + src/hw/dreamcast.cc src/hw/scheduler.cc src/jit/backend/interpreter/interpreter_backend.cc src/jit/backend/interpreter/interpreter_block.cc diff --git a/src/emu/emulator.cc b/src/emu/emulator.cc new file mode 100644 index 00000000..26ea2c92 --- /dev/null +++ b/src/emu/emulator.cc @@ -0,0 +1,258 @@ +#include "core/core.h" +#include "emu/emulator.h" +#include "emu/profiler.h" +#include "renderer/gl_backend.h" + +using namespace dreavm::core; +using namespace dreavm::emu; +using namespace dreavm::hw; +using namespace dreavm::hw::gdrom; +using namespace dreavm::renderer; +using namespace dreavm::system; +using namespace dreavm::trace; + +DEFINE_string(bios, "dc_bios.bin", "Path to BIOS"); +DEFINE_string(flash, "dc_flash.bin", "Path to flash ROM"); + +Emulator::Emulator() : trace_writer_(nullptr) { + rb_ = new GLBackend(sys_); + dc_.set_rb(rb_); +} + +Emulator::~Emulator() { + delete rb_; + delete trace_writer_; +} + +void Emulator::Run(const char *path) { + Profiler::Init(); + + if (!sys_.Init()) { + return; + } + + if (!rb_->Init()) { + return; + } + + if (!dc_.Init()) { + return; + } + + if (!LoadBios(FLAGS_bios.c_str())) { + return; + } + + if (!LoadFlash(FLAGS_flash.c_str())) { + 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(); + + dc_.scheduler()->Tick(step); + + RenderFrame(); + } +} + +bool Emulator::LoadBios(const char *path) { + FILE *fp = fopen(path, "rb"); + if (!fp) { + LOG_WARNING("Failed to open bios at \"%s\"", path); + return false; + } + + fseek(fp, 0, SEEK_END); + int size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + if (size != BIOS_SIZE) { + LOG_WARNING("Bios size mismatch, is %d, expected %d", size, BIOS_SIZE); + fclose(fp); + return false; + } + + int n = static_cast(fread(dc_.bios(), sizeof(uint8_t), size, fp)); + fclose(fp); + + if (n != size) { + LOG_WARNING("Bios read failed"); + return false; + } + + return true; +} + +bool Emulator::LoadFlash(const char *path) { + FILE *fp = fopen(path, "rb"); + if (!fp) { + LOG_WARNING("Failed to open flash at \"%s\"", path); + return false; + } + + fseek(fp, 0, SEEK_END); + int size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + if (size != FLASH_SIZE) { + LOG_WARNING("Flash size mismatch, is %d, expected %d", size, FLASH_SIZE); + fclose(fp); + return false; + } + + int n = static_cast(fread(dc_.flash(), sizeof(uint8_t), size, fp)); + fclose(fp); + + if (n != size) { + LOG_WARNING("Flash read failed"); + return false; + } + + return true; +} + +bool Emulator::LaunchBIN(const char *path) { + FILE *fp = fopen(path, "rb"); + if (!fp) { + return false; + } + + fseek(fp, 0, SEEK_END); + int size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + uint8_t *data = reinterpret_cast(malloc(size)); + int n = static_cast(fread(data, sizeof(uint8_t), size, fp)); + fclose(fp); + + if (n != size) { + free(data); + return false; + } + + // load to 0x0c010000 (area 3) which is where 1ST_READ.BIN is normally + // loaded to + dc_.memory()->Memcpy(0x0c010000, data, size); + free(data); + + dc_.sh4()->SetPC(0x0c010000); + + return true; +} + +bool Emulator::LaunchGDI(const char *path) { + std::unique_ptr gdi(new GDI()); + + if (!gdi->Load(path)) { + return false; + } + + dc_.gdrom()->SetDisc(std::move(gdi)); + dc_.sh4()->SetPC(0xa0000000); + + return true; +} + +void Emulator::PumpEvents() { + SystemEvent ev; + + sys_.PumpEvents(); + + while (sys_.PollEvent(&ev)) { + 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) { + ToggleTracing(); + } + } + // else, forward to maple + else { + dc_.maple()->HandleInput(0, ev.key.code, ev.key.value); + } + } + } 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; + } + } +} + +void Emulator::ToggleTracing() { + if (!trace_writer_) { + char filename[PATH_MAX]; + GetNextTraceFilename(filename, sizeof(filename)); + + trace_writer_ = new TraceWriter(); + + if (!trace_writer_->Open(filename)) { + delete trace_writer_; + trace_writer_ = nullptr; + + LOG_INFO("Failed to start tracing"); + + return; + } + + LOG_INFO("Begin tracing to %s", filename); + } else { + delete trace_writer_; + trace_writer_ = nullptr; + + LOG_INFO("End tracing"); + } + + dc_.set_trace_writer(trace_writer_); +} + +void Emulator::RenderFrame() { + rb_->BeginFrame(); + + dc_.ta()->RenderLastContext(); + + // render stats + char stats[512]; + snprintf(stats, sizeof(stats), "%.2f fps, %.2f vbps", dc_.pvr()->fps(), + dc_.pvr()->vbps()); + rb_->RenderText2D(0, 0, 12.0f, 0xffffffff, stats); + + // render profiler + Profiler::Render(rb_); + + rb_->EndFrame(); +} diff --git a/src/emu/emulator.h b/src/emu/emulator.h new file mode 100644 index 00000000..248e0e25 --- /dev/null +++ b/src/emu/emulator.h @@ -0,0 +1,36 @@ +#ifndef EMULATOR_H +#define EMULATOR_H + +#include "hw/dreamcast.h" +#include "renderer/backend.h" +#include "system/system.h" + +namespace dreavm { +namespace emu { + +class Emulator { + public: + Emulator(); + ~Emulator(); + + void Run(const char *path); + + private: + bool LoadBios(const char *path); + bool LoadFlash(const char *path); + bool LaunchBIN(const char *path); + bool LaunchGDI(const char *path); + + void PumpEvents(); + void ToggleTracing(); + void RenderFrame(); + + system::System sys_; + hw::Dreamcast dc_; + renderer::Backend *rb_; + trace::TraceWriter *trace_writer_; +}; +} +} + +#endif diff --git a/src/hw/aica/aica.cc b/src/hw/aica/aica.cc index f8b42138..e49b4d39 100644 --- a/src/hw/aica/aica.cc +++ b/src/hw/aica/aica.cc @@ -1,15 +1,17 @@ -#include "emu/dreamcast.h" #include "hw/aica/aica.h" +#include "hw/dreamcast.h" -using namespace dreavm::emu; +using namespace dreavm::hw; using namespace dreavm::hw::aica; using namespace dreavm::hw::holly; AICA::AICA(Dreamcast *dc) : dc_(dc) {} -void AICA::Init() { +bool AICA::Init() { aica_regs_ = dc_->aica_regs(); wave_ram_ = dc_->wave_ram(); + + return true; } uint32_t AICA::Execute(uint32_t cycles) { diff --git a/src/hw/aica/aica.h b/src/hw/aica/aica.h index a203f5ce..e0f7cc0a 100644 --- a/src/hw/aica/aica.h +++ b/src/hw/aica/aica.h @@ -5,20 +5,18 @@ #include "hw/device.h" namespace dreavm { -namespace emu { -class Dreamcast; -} - namespace hw { +class Dreamcast; + namespace aica { class AICA : public hw::Device { public: - AICA(emu::Dreamcast *dc); + AICA(hw::Dreamcast *dc); uint32_t GetClockFrequency() { return 22579200; } - void Init(); + bool Init(); uint32_t Execute(uint32_t cycles); uint32_t ReadRegister32(uint32_t addr); @@ -28,7 +26,7 @@ class AICA : public hw::Device { void WriteWave32(uint32_t addr, uint32_t value); private: - emu::Dreamcast *dc_; + hw::Dreamcast *dc_; uint8_t *aica_regs_; uint8_t *wave_ram_; }; diff --git a/src/emu/dreamcast.cc b/src/hw/dreamcast.cc similarity index 59% rename from src/emu/dreamcast.cc rename to src/hw/dreamcast.cc index e9679db5..e84ff7ba 100644 --- a/src/emu/dreamcast.cc +++ b/src/hw/dreamcast.cc @@ -1,14 +1,10 @@ #include "core/core.h" +#include "hw/dreamcast.h" #include "jit/backend/interpreter/interpreter_backend.h" #include "jit/backend/x64/x64_backend.h" #include "jit/frontend/sh4/sh4_frontend.h" -#include "emu/dreamcast.h" -#include "emu/profiler.h" -#include "hw/maple/maple_controller.h" -#include "renderer/gl_backend.h" using namespace dreavm::core; -using namespace dreavm::emu; using namespace dreavm::hw; using namespace dreavm::hw::aica; using namespace dreavm::hw::gdrom; @@ -20,118 +16,127 @@ using namespace dreavm::jit::backend::interpreter; using namespace dreavm::jit::backend::x64; using namespace dreavm::jit::frontend::sh4; using namespace dreavm::renderer; -using namespace dreavm::system; using namespace dreavm::trace; -DEFINE_string(bios, "dc_bios.bin", "Path to BIOS"); -DEFINE_string(flash, "dc_flash.bin", "Path to flash ROM"); +Dreamcast::Dreamcast() + : // allocate registers and initialize references + holly_regs_(new Register[HOLLY_REG_SIZE >> 2]), +#define HOLLY_REG(offset, name, flags, default, type) \ + name{reinterpret_cast(holly_regs_[name##_OFFSET].value)}, +#include "hw/holly/holly_regs.inc" +#undef HOLLY_REG + pvr_regs_(new Register[PVR_REG_SIZE >> 2]), +#define PVR_REG(offset, name, flags, default, type) \ + name{reinterpret_cast(pvr_regs_[name##_OFFSET].value)}, +#include "hw/holly/pvr2_regs.inc" +#undef PVR_REG + rb_(nullptr), + trace_writer_(nullptr) { +// initialize register values +#define HOLLY_REG(addr, name, flags, default, type) \ + holly_regs_[name##_OFFSET] = {flags, default}; +#include "hw/holly/holly_regs.inc" +#undef HOLLY_REG -Dreamcast::Dreamcast() { - scheduler_ = std::unique_ptr(new Scheduler()); - memory_ = std::unique_ptr(new Memory()); - rb_ = std::unique_ptr(new GLBackend(sys_)); - rt_frontend_ = - std::unique_ptr(new SH4Frontend(*memory())); - rt_backend_ = std::unique_ptr(new X64Backend(*memory())); - runtime_ = std::unique_ptr( - new Runtime(*memory(), *rt_frontend_.get(), *rt_backend_.get())); - sh4_ = std::unique_ptr(new SH4(*memory(), *runtime())); - aica_ = std::unique_ptr(new AICA(this)); - holly_ = std::unique_ptr(new Holly(this)); - pvr_ = std::unique_ptr(new PVR2(this)); - ta_ = std::unique_ptr(new TileAccelerator(this)); - gdrom_ = std::unique_ptr(new GDROM(this)); - maple_ = std::unique_ptr(new Maple(this)); +#define PVR_REG(addr, name, flags, default, type) \ + pvr_regs_[name##_OFFSET] = {flags, default}; +#include "hw/holly/pvr2_regs.inc" +#undef PVR_REG + + bios_ = new uint8_t[BIOS_SIZE](); + flash_ = new uint8_t[FLASH_SIZE](); + ram_ = new uint8_t[MAIN_RAM_SIZE](); + unassigned_ = new uint8_t[UNASSIGNED_SIZE](); + modem_mem_ = new uint8_t[MODEM_REG_SIZE](); + aica_regs_ = new uint8_t[AICA_REG_SIZE](); + wave_ram_ = new uint8_t[WAVE_RAM_SIZE](); + expdev_mem_ = new uint8_t[EXPDEV_SIZE](); + video_ram_ = new uint8_t[PVR_VRAM32_SIZE](); + palette_ram_ = new uint8_t[PVR_PALETTE_SIZE](); + + scheduler_ = new Scheduler(); + memory_ = new Memory(); + rt_frontend_ = new SH4Frontend(*memory_); + rt_backend_ = new X64Backend(*memory_); + runtime_ = new Runtime(*memory_, *rt_frontend_, *rt_backend_); + aica_ = new AICA(this); + gdrom_ = new GDROM(this); + holly_ = new Holly(this); + maple_ = new Maple(this); + pvr_ = new PVR2(this); + sh4_ = new SH4(*memory_, *runtime_); + ta_ = new TileAccelerator(this); } -void Dreamcast::Run(const char *path) { - if (!Init()) { - LOG_WARNING("Failed to initialize emulator"); - return; - } +Dreamcast::~Dreamcast() { + delete[] holly_regs_; + delete[] pvr_regs_; - if (!LoadBios(FLAGS_bios.c_str())) { - return; - } + delete bios_; + delete flash_; + delete ram_; + delete unassigned_; + delete modem_mem_; + delete aica_regs_; + delete wave_ram_; + delete expdev_mem_; + delete video_ram_; + delete palette_ram_; - if (!LoadFlash(FLAGS_flash.c_str())) { - 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(); - } + delete scheduler_; + delete memory_; + delete rt_frontend_; + delete rt_backend_; + delete runtime_; + delete aica_; + delete gdrom_; + delete holly_; + delete maple_; + delete pvr_; + delete sh4_; + delete ta_; } bool Dreamcast::Init() { - if (!sys_.Init()) { + MapMemory(); + + if (!aica_->Init()) { return false; } - if (!rb_->Init()) { + if (!gdrom_->Init()) { return false; } - Profiler::Init(); + if (!holly_->Init()) { + return false; + } - InitMemory(); - InitRegisters(); + if (!maple_->Init()) { + return false; + } - sh4_->Init(); - aica_->Init(); - holly_->Init(); - pvr_->Init(); - ta_->Init(); - gdrom_->Init(); - maple_->Init(); + if (!pvr_->Init()) { + return false; + } - scheduler_->AddDevice(sh4()); - scheduler_->AddDevice(aica()); + if (!sh4_->Init()) { + return false; + } + + if (!ta_->Init()) { + return false; + } + + scheduler_->AddDevice(aica_); + scheduler_->AddDevice(sh4_); return true; } -void Dreamcast::InitMemory() { +void Dreamcast::MapMemory() { using namespace std::placeholders; - memset(ram_, 0, sizeof(ram_)); - memset(unassigned_, 0, sizeof(unassigned_)); - memset(modem_mem_, 0, sizeof(modem_mem_)); - memset(aica_regs_, 0, sizeof(aica_regs_)); - memset(wave_ram_, 0, sizeof(wave_ram_)); - memset(expdev_mem_, 0, sizeof(expdev_mem_)); - memset(video_ram_, 0, sizeof(video_ram_)); - memset(palette_ram_, 0, sizeof(palette_ram_)); - // main ram memory_->Mount(BIOS_START, BIOS_END, MIRROR_MASK, bios_); memory_->Mount(FLASH_START, FLASH_END, MIRROR_MASK, flash_); @@ -265,187 +270,3 @@ void Dreamcast::InitMemory() { std::bind(&SH4::WriteSQ32, sh4(), _1, _2), // nullptr); } - -void Dreamcast::InitRegisters() { -#define HOLLY_REG(addr, name, flags, default, type) \ - holly_regs_[name##_OFFSET] = {flags, default}; -#include "hw/holly/holly_regs.inc" -#undef HOLLY_REG - -#define PVR_REG(addr, name, flags, default, type) \ - pvr_regs_[name##_OFFSET] = {flags, default}; -#include "hw/holly/pvr2_regs.inc" -#undef PVR_REG -} - -bool Dreamcast::LoadBios(const char *path) { - FILE *fp = fopen(path, "rb"); - if (!fp) { - LOG_WARNING("Failed to open bios at \"%s\"", path); - return false; - } - - fseek(fp, 0, SEEK_END); - int size = ftell(fp); - fseek(fp, 0, SEEK_SET); - - if (size != BIOS_SIZE) { - LOG_WARNING("Bios size mismatch, is %d, expected %d", size, BIOS_SIZE); - fclose(fp); - return false; - } - - int n = static_cast(fread(bios_, sizeof(uint8_t), size, fp)); - fclose(fp); - - if (n != size) { - LOG_WARNING("Bios read failed"); - return false; - } - - return true; -} - -bool Dreamcast::LoadFlash(const char *path) { - FILE *fp = fopen(path, "rb"); - if (!fp) { - LOG_WARNING("Failed to open flash at \"%s\"", path); - return false; - } - - fseek(fp, 0, SEEK_END); - int size = ftell(fp); - fseek(fp, 0, SEEK_SET); - - if (size != FLASH_SIZE) { - LOG_WARNING("Flash size mismatch, is %d, expected %d", size, FLASH_SIZE); - fclose(fp); - return false; - } - - int n = static_cast(fread(flash_, sizeof(uint8_t), size, fp)); - fclose(fp); - - if (n != size) { - LOG_WARNING("Flash read failed"); - return false; - } - - return true; -} - -bool Dreamcast::LaunchBIN(const char *path) { - FILE *fp = fopen(path, "rb"); - if (!fp) { - return false; - } - - fseek(fp, 0, SEEK_END); - int size = ftell(fp); - fseek(fp, 0, SEEK_SET); - - uint8_t *data = reinterpret_cast(malloc(size)); - int n = static_cast(fread(data, sizeof(uint8_t), size, fp)); - fclose(fp); - - if (n != size) { - free(data); - return false; - } - - // load to 0x0c010000 (area 3) which is where 1ST_READ.BIN is normally - // loaded to - memory_->Memcpy(0x0c010000, data, size); - free(data); - - sh4_->SetPC(0x0c010000); - - return true; -} - -bool Dreamcast::LaunchGDI(const char *path) { - std::unique_ptr gdi(new GDI()); - - if (!gdi->Load(path)) { - return false; - } - - gdrom_->SetDisc(std::move(gdi)); - sh4_->SetPC(0xa0000000); - - return true; -} - -void Dreamcast::PumpEvents() { - SystemEvent ev; - - sys_.PumpEvents(); - - while (sys_.PollEvent(&ev)) { - 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) { - ToggleTracing(); - } - } - // else, forward to maple - else { - maple_->HandleInput(0, ev.key.code, ev.key.value); - } - } - } 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; - } - } -} - -void Dreamcast::ToggleTracing() { - if (!trace_writer_) { - char filename[PATH_MAX]; - GetNextTraceFilename(filename, sizeof(filename)); - - trace_writer_ = std::unique_ptr(new TraceWriter()); - - if (!trace_writer_->Open(filename)) { - trace_writer_ = nullptr; - - LOG_INFO("Failed to start tracing"); - - return; - } - - LOG_INFO("Begin tracing to %s", filename); - } else { - trace_writer_ = nullptr; - - LOG_INFO("End tracing"); - } -} - -void Dreamcast::RenderFrame() { - rb_->BeginFrame(); - - ta_->RenderLastContext(); - - // render stats - char stats[512]; - snprintf(stats, sizeof(stats), "%.2f fps, %.2f vbps", pvr_->fps(), - pvr_->vbps()); - rb_->RenderText2D(0, 0, 12.0f, 0xffffffff, stats); - - // render profiler - Profiler::Render(rb()); - - rb_->EndFrame(); -} diff --git a/src/emu/dreamcast.h b/src/hw/dreamcast.h similarity index 54% rename from src/emu/dreamcast.h rename to src/hw/dreamcast.h index 7f247379..42ffa81f 100644 --- a/src/emu/dreamcast.h +++ b/src/hw/dreamcast.h @@ -1,25 +1,23 @@ #ifndef DREAMCAST_H #define DREAMCAST_H -#include #include "hw/aica/aica.h" -#include "hw/sh4/sh4.h" #include "hw/gdrom/gdrom.h" #include "hw/holly/holly.h" #include "hw/holly/pvr2.h" #include "hw/holly/tile_accelerator.h" #include "hw/maple/maple.h" +#include "hw/sh4/sh4.h" #include "hw/memory.h" #include "hw/scheduler.h" #include "jit/backend/backend.h" #include "jit/frontend/frontend.h" #include "jit/runtime.h" #include "renderer/backend.h" -#include "system/system.h" #include "trace/trace.h" namespace dreavm { -namespace emu { +namespace hw { // // memory layout @@ -80,101 +78,103 @@ struct Register { enum { #define AICA_REG(addr, name, flags, default, type) \ - name##_OFFSET = addr - emu::AICA_REG_START, + name##_OFFSET = addr - hw::AICA_REG_START, #include "hw/aica/aica_regs.inc" #undef AICA_REG #define HOLLY_REG(addr, name, flags, default, type) \ - name##_OFFSET = (addr - emu::HOLLY_REG_START) >> 2, + name##_OFFSET = (addr - hw::HOLLY_REG_START) >> 2, #include "hw/holly/holly_regs.inc" #undef HOLLY_REG #define PVR_REG(addr, name, flags, default_value, type) \ - name##_OFFSET = (addr - emu::PVR_REG_START) >> 2, + name##_OFFSET = (addr - hw::PVR_REG_START) >> 2, #include "hw/holly/pvr2_regs.inc" #undef PVR_REG }; class Dreamcast { public: - hw::Memory *memory() { return memory_.get(); } - hw::Scheduler *scheduler() { return scheduler_.get(); } - renderer::Backend *rb() { return rb_.get(); } - jit::Runtime *runtime() { return runtime_.get(); } - hw::aica::AICA *aica() { return aica_.get(); } - hw::gdrom::GDROM *gdrom() { return gdrom_.get(); } - hw::holly::Holly *holly() { return holly_.get(); } - hw::holly::PVR2 *pvr() { return pvr_.get(); } - hw::holly::TileAccelerator *ta() { return ta_.get(); } - hw::maple::Maple *maple() { return maple_.get(); } - hw::sh4::SH4 *sh4() { return sh4_.get(); } - trace::TraceWriter *trace_writer() { return trace_writer_.get(); } - uint8_t *aica_regs() { return aica_regs_; } Register *holly_regs() { return holly_regs_; } Register *pvr_regs() { return pvr_regs_; } + uint8_t *bios() { return bios_; } + uint8_t *flash() { return flash_; } uint8_t *wave_ram() { return wave_ram_; } uint8_t *palette_ram() { return palette_ram_; } uint8_t *video_ram() { return video_ram_; } + hw::Memory *memory() { return memory_; } + hw::Scheduler *scheduler() { return scheduler_; } + jit::Runtime *runtime() { return runtime_; } + hw::aica::AICA *aica() { return aica_; } + hw::gdrom::GDROM *gdrom() { return gdrom_; } + hw::holly::Holly *holly() { return holly_; } + hw::maple::Maple *maple() { return maple_; } + hw::holly::PVR2 *pvr() { return pvr_; } + hw::sh4::SH4 *sh4() { return sh4_; } + hw::holly::TileAccelerator *ta() { return ta_; } + + renderer::Backend *rb() { return rb_; } + void set_rb(renderer::Backend *rb) { rb_ = rb; } + + trace::TraceWriter *trace_writer() { return trace_writer_; } + void set_trace_writer(trace::TraceWriter *trace_writer) { + trace_writer_ = trace_writer; + } + Dreamcast(); + ~Dreamcast(); - void Run(const char *path); + bool Init(); -#define HOLLY_REG(offset, name, flags, default, type) \ - type &name{reinterpret_cast(holly_regs_[name##_OFFSET].value)}; + private: + Register *holly_regs_; + + public: +#define HOLLY_REG(offset, name, flags, default, type) type &name; #include "hw/holly/holly_regs.inc" #undef HOLLY_REG -#define PVR_REG(offset, name, flags, default, type) \ - type &name{reinterpret_cast(pvr_regs_[name##_OFFSET].value)}; + private: + Register *pvr_regs_; + + public: +#define PVR_REG(offset, name, flags, default, type) type &name; #include "hw/holly/pvr2_regs.inc" #undef PVR_REG private: - bool Init(); - void InitMemory(); - void InitRegisters(); + void MapMemory(); - bool LoadBios(const char *path); - bool LoadFlash(const char *path); - bool LaunchBIN(const char *path); - bool LaunchGDI(const char *path); + uint8_t *bios_; + uint8_t *flash_; + uint8_t *ram_; + uint8_t *unassigned_; + uint8_t *modem_mem_; + uint8_t *aica_regs_; + uint8_t *wave_ram_; + uint8_t *expdev_mem_; + uint8_t *video_ram_; + uint8_t *palette_ram_; - void PumpEvents(); - void ToggleTracing(); - void RenderFrame(); + hw::Memory *memory_; + hw::Scheduler *scheduler_; + jit::frontend::Frontend *rt_frontend_; + jit::backend::Backend *rt_backend_; + jit::Runtime *runtime_; + hw::aica::AICA *aica_; + hw::gdrom::GDROM *gdrom_; + hw::holly::Holly *holly_; + hw::maple::Maple *maple_; + hw::holly::PVR2 *pvr_; + hw::sh4::SH4 *sh4_; + hw::holly::TileAccelerator *ta_; - system::System sys_; - std::unique_ptr memory_; - std::unique_ptr scheduler_; - std::unique_ptr rb_; - std::unique_ptr rt_frontend_; - std::unique_ptr rt_backend_; - std::unique_ptr runtime_; - std::unique_ptr aica_; - std::unique_ptr gdrom_; - std::unique_ptr holly_; - std::unique_ptr pvr_; - std::unique_ptr ta_; - std::unique_ptr maple_; - std::unique_ptr sh4_; - std::unique_ptr trace_writer_; - - Register holly_regs_[HOLLY_REG_SIZE >> 2]; - Register pvr_regs_[PVR_REG_SIZE >> 2]; - - uint8_t bios_[BIOS_SIZE]; - uint8_t flash_[FLASH_SIZE]; - uint8_t ram_[MAIN_RAM_SIZE]; - uint8_t unassigned_[UNASSIGNED_SIZE]; - uint8_t modem_mem_[MODEM_REG_SIZE]; - uint8_t aica_regs_[AICA_REG_SIZE]; - uint8_t wave_ram_[WAVE_RAM_SIZE]; - uint8_t expdev_mem_[EXPDEV_SIZE]; - uint8_t video_ram_[PVR_VRAM32_SIZE]; - uint8_t palette_ram_[PVR_PALETTE_SIZE]; + // not owned by us + renderer::Backend *rb_; + trace::TraceWriter *trace_writer_; }; } } diff --git a/src/hw/gdrom/gdrom.cc b/src/hw/gdrom/gdrom.cc index c19b3c5c..9a0f5347 100644 --- a/src/hw/gdrom/gdrom.cc +++ b/src/hw/gdrom/gdrom.cc @@ -1,9 +1,9 @@ #include "core/core.h" -#include "emu/dreamcast.h" #include "hw/gdrom/gdrom_replies.inc" +#include "hw/dreamcast.h" using namespace dreavm::core; -using namespace dreavm::emu; +using namespace dreavm::hw; using namespace dreavm::hw::gdrom; using namespace dreavm::hw::holly; using namespace dreavm::hw::sh4; @@ -28,12 +28,14 @@ GDROM::GDROM(Dreamcast *dc) GDROM::~GDROM() { delete[] dma_buffer_; } -void GDROM::Init() { +bool GDROM::Init() { memory_ = dc_->memory(); holly_ = dc_->holly(); holly_regs_ = dc_->holly_regs(); SetDisc(nullptr); + + return true; } void GDROM::SetDisc(std::unique_ptr disc) { diff --git a/src/hw/gdrom/gdrom.h b/src/hw/gdrom/gdrom.h index 32dc86ef..f6bcd5bf 100644 --- a/src/hw/gdrom/gdrom.h +++ b/src/hw/gdrom/gdrom.h @@ -5,17 +5,14 @@ #include "hw/gdrom/disc.h" namespace dreavm { -namespace emu { -class Dreamcast; -struct Register; -} - namespace hw { namespace holly { class Holly; } +class Dreamcast; class Memory; +struct Register; namespace gdrom { @@ -207,10 +204,10 @@ enum DataMask { class GDROM { public: - GDROM(emu::Dreamcast *dc); + GDROM(hw::Dreamcast *dc); ~GDROM(); - void Init(); + bool Init(); void SetDisc(std::unique_ptr disc); @@ -234,10 +231,10 @@ class GDROM { int ReadSectors(int fad, SectorFormat format, DataMask mask, int num_sectors, uint8_t *dst); - emu::Dreamcast *dc_; + hw::Dreamcast *dc_; hw::Memory *memory_; hw::holly::Holly *holly_; - emu::Register *holly_regs_; + hw::Register *holly_regs_; GD_FEATURES_T features_; GD_INTREASON_T intreason_; diff --git a/src/hw/holly/holly.cc b/src/hw/holly/holly.cc index 163283b2..1414074e 100644 --- a/src/hw/holly/holly.cc +++ b/src/hw/holly/holly.cc @@ -1,8 +1,8 @@ #include "core/core.h" -#include "emu/dreamcast.h" +#include "hw/dreamcast.h" using namespace dreavm::core; -using namespace dreavm::emu; +using namespace dreavm::hw; using namespace dreavm::hw::holly; using namespace dreavm::hw::sh4; using namespace dreavm::renderer; @@ -10,9 +10,11 @@ using namespace dreavm::system; Holly::Holly(Dreamcast *dc) : dc_(dc) {} -void Holly::Init() { +bool Holly::Init() { sh4_ = dc_->sh4(); holly_regs_ = dc_->holly_regs(); + + return true; } void Holly::RequestInterrupt(HollyInterrupt intr) { diff --git a/src/hw/holly/holly.h b/src/hw/holly/holly.h index e43cf133..f4a5f0e6 100644 --- a/src/hw/holly/holly.h +++ b/src/hw/holly/holly.h @@ -4,16 +4,14 @@ #include namespace dreavm { -namespace emu { -class Dreamcast; -struct Register; -} - namespace hw { namespace sh4 { class SH4; } +class Dreamcast; +struct Register; + namespace holly { // interrupts @@ -153,9 +151,9 @@ enum HollyInterrupt : uint64_t { class Holly { public: - Holly(emu::Dreamcast *dc); + Holly(hw::Dreamcast *dc); - void Init(); + bool Init(); void RequestInterrupt(HollyInterrupt intr); void UnrequestInterrupt(HollyInterrupt intr); @@ -168,8 +166,8 @@ class Holly { void SortDMATransfer(); void ForwardRequestInterrupts(); - emu::Dreamcast *dc_; - emu::Register *holly_regs_; + hw::Dreamcast *dc_; + hw::Register *holly_regs_; hw::sh4::SH4 *sh4_; }; } diff --git a/src/hw/holly/pvr2.cc b/src/hw/holly/pvr2.cc index 88803151..4d82e208 100644 --- a/src/hw/holly/pvr2.cc +++ b/src/hw/holly/pvr2.cc @@ -1,7 +1,7 @@ #include "core/core.h" -#include "emu/dreamcast.h" +#include "hw/dreamcast.h" -using namespace dreavm::emu; +using namespace dreavm::hw; using namespace dreavm::hw::holly; using namespace dreavm::hw::sh4; using namespace dreavm::renderer; @@ -13,7 +13,7 @@ PVR2::PVR2(Dreamcast *dc) fps_(0), vbps_(0) {} -void PVR2::Init() { +bool PVR2::Init() { scheduler_ = dc_->scheduler(); holly_ = dc_->holly(); ta_ = dc_->ta(); @@ -21,6 +21,8 @@ void PVR2::Init() { video_ram_ = dc_->video_ram(); ReconfigureSPG(); + + return true; } uint32_t PVR2::ReadRegister32(uint32_t addr) { diff --git a/src/hw/holly/pvr2.h b/src/hw/holly/pvr2.h index 1bfa72a5..c28d8f0e 100644 --- a/src/hw/holly/pvr2.h +++ b/src/hw/holly/pvr2.h @@ -5,11 +5,9 @@ #include "hw/scheduler.h" namespace dreavm { -namespace emu { -class Dreamcast; -} - namespace hw { +class Dreamcast; + namespace holly { class Holly; @@ -198,12 +196,12 @@ union TA_ISP_BASE_T { class PVR2 { public: - PVR2(emu::Dreamcast *dc); + PVR2(hw::Dreamcast *dc); float fps() { return fps_; } float vbps() { return vbps_; } - void Init(); + bool Init(); uint32_t ReadRegister32(uint32_t addr); void WriteRegister32(uint32_t addr, uint32_t value); @@ -218,11 +216,11 @@ class PVR2 { void ReconfigureSPG(); void LineClockUpdate(); - emu::Dreamcast *dc_; + hw::Dreamcast *dc_; hw::Scheduler *scheduler_; hw::holly::Holly *holly_; hw::holly::TileAccelerator *ta_; - emu::Register *pvr_regs_; + hw::Register *pvr_regs_; uint8_t *video_ram_; hw::TimerHandle line_timer_; diff --git a/src/hw/holly/tile_accelerator.cc b/src/hw/holly/tile_accelerator.cc index 08279cd5..dec25baa 100644 --- a/src/hw/holly/tile_accelerator.cc +++ b/src/hw/holly/tile_accelerator.cc @@ -1,9 +1,9 @@ #include "core/core.h" -#include "emu/dreamcast.h" #include "hw/holly/pixel_convert.h" +#include "hw/dreamcast.h" using namespace dreavm::core; -using namespace dreavm::emu; +using namespace dreavm::hw; using namespace dreavm::hw::holly; using namespace dreavm::renderer; using namespace dreavm::trace; @@ -288,10 +288,12 @@ TileAccelerator::~TileAccelerator() { } } -void TileAccelerator::Init() { +bool TileAccelerator::Init() { memory_ = dc_->memory(); holly_ = dc_->holly(); video_ram_ = dc_->video_ram(); + + return true; } void TileAccelerator::SoftReset() { diff --git a/src/hw/holly/tile_accelerator.h b/src/hw/holly/tile_accelerator.h index a6b71233..70e9fb51 100644 --- a/src/hw/holly/tile_accelerator.h +++ b/src/hw/holly/tile_accelerator.h @@ -7,15 +7,12 @@ #include "renderer/backend.h" namespace dreavm { -namespace emu { -class Dreamcast; -} - namespace trace { class TraceWriter; } namespace hw { +class Dreamcast; class Memory; namespace holly { @@ -479,7 +476,7 @@ struct TileContext { class TileTextureCache : public TextureCache { public: - TileTextureCache(emu::Dreamcast *dc); + TileTextureCache(hw::Dreamcast *dc); void Clear(); // void RemoveTexture(uint32_t addr); @@ -487,7 +484,7 @@ class TileTextureCache : public TextureCache { RegisterTextureCallback register_cb); private: - emu::Dreamcast *dc_; + hw::Dreamcast *dc_; trace::TraceWriter *trace_writer_; std::unordered_map textures_; @@ -502,10 +499,10 @@ class TileAccelerator { static int GetPolyType(const PCW &pcw); static int GetVertexType(const PCW &pcw); - TileAccelerator(emu::Dreamcast *dc); + TileAccelerator(hw::Dreamcast *dc); ~TileAccelerator(); - void Init(); + bool Init(); void SoftReset(); void InitContext(uint32_t addr); @@ -522,7 +519,7 @@ class TileAccelerator { void WritePVRState(TileContext *tactx); void WriteBackgroundState(TileContext *tactx); - emu::Dreamcast *dc_; + hw::Dreamcast *dc_; hw::Memory *memory_; hw::holly::Holly *holly_; uint8_t *video_ram_; diff --git a/src/hw/maple/maple.cc b/src/hw/maple/maple.cc index 0da1e1ce..f680b27e 100644 --- a/src/hw/maple/maple.cc +++ b/src/hw/maple/maple.cc @@ -1,9 +1,9 @@ #include "core/core.h" -#include "emu/dreamcast.h" #include "hw/maple/maple_controller.h" +#include "hw/dreamcast.h" using namespace dreavm::core; -using namespace dreavm::emu; +using namespace dreavm::hw; using namespace dreavm::hw::holly; using namespace dreavm::hw::maple; using namespace dreavm::hw::sh4; @@ -14,10 +14,12 @@ Maple::Maple(Dreamcast *dc) : dc_(dc), devices_() { devices_[0] = std::unique_ptr(new MapleController()); } -void Maple::Init() { +bool Maple::Init() { memory_ = dc_->memory(); holly_ = dc_->holly(); holly_regs_ = dc_->holly_regs(); + + return true; } bool Maple::HandleInput(int port, Keycode key, int16_t value) { diff --git a/src/hw/maple/maple.h b/src/hw/maple/maple.h index 3242de7d..9db3c451 100644 --- a/src/hw/maple/maple.h +++ b/src/hw/maple/maple.h @@ -4,17 +4,14 @@ #include "system/keys.h" namespace dreavm { -namespace emu { -class Dreamcast; -struct Register; -} - namespace hw { namespace holly { class Holly; } +class Dreamcast; class Memory; +struct Register; namespace maple { @@ -103,9 +100,9 @@ class MapleDevice { class Maple { public: - Maple(emu::Dreamcast *dc); + Maple(hw::Dreamcast *dc); - void Init(); + bool Init(); bool HandleInput(int port, system::Keycode key, int16_t value); void VBlank(); @@ -117,10 +114,10 @@ class Maple { bool HandleFrame(const MapleFrame &frame, MapleFrame &res); void StartDMA(); - emu::Dreamcast *dc_; + hw::Dreamcast *dc_; hw::Memory *memory_; hw::holly::Holly *holly_; - emu::Register *holly_regs_; + hw::Register *holly_regs_; std::unique_ptr devices_[MAX_PORTS]; }; diff --git a/src/hw/sh4/sh4.cc b/src/hw/sh4/sh4.cc index 7892e346..fffddbe7 100644 --- a/src/hw/sh4/sh4.cc +++ b/src/hw/sh4/sh4.cc @@ -25,7 +25,7 @@ SH4::SH4(Memory &memory, Runtime &runtime) requested_interrupts_(0), pending_interrupts_(0) {} -void SH4::Init() { +bool SH4::Init() { memset(&ctx_, 0, sizeof(ctx_)); ctx_.pc = 0xa0000000; ctx_.pr = 0x0; @@ -43,6 +43,8 @@ void SH4::Init() { memset(cache_, 0, sizeof(cache_)); ReprioritizeInterrupts(); + + return true; } void SH4::SetPC(uint32_t pc) { ctx_.pc = pc; } diff --git a/src/hw/sh4/sh4.h b/src/hw/sh4/sh4.h index a751ebe8..d20227f4 100644 --- a/src/hw/sh4/sh4.h +++ b/src/hw/sh4/sh4.h @@ -120,7 +120,7 @@ class SH4 : public hw::Device { uint32_t GetClockFrequency() { return 200000000; } - void Init(); + bool Init(); void SetPC(uint32_t pc); uint32_t Execute(uint32_t cycles); diff --git a/src/main.cc b/src/main.cc index 932ca1c1..25d7d3ea 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,7 +1,6 @@ -#include #include #include "core/core.h" -#include "emu/dreamcast.h" +#include "emu/emulator.h" #include "trace/trace_viewer.h" using namespace dreavm::core; @@ -37,11 +36,11 @@ int main(int argc, char **argv) { const char *load = argc > 1 ? argv[1] : nullptr; if (load && strstr(load, ".trace")) { - std::unique_ptr tracer(new TraceViewer()); - tracer->Run(load); + TraceViewer tracer; + tracer.Run(load); } else { - std::unique_ptr emu(new Dreamcast()); - emu->Run(load); + Emulator emu; + emu.Run(load); } ShutdownFlags();