split up Dreamcast object into hw::Dreamcast and emu::Emulator

This commit is contained in:
Anthony Pesch 2015-09-11 00:07:20 -07:00
parent e83cad251a
commit 0bcc30559b
20 changed files with 532 additions and 418 deletions

View File

@ -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

258
src/emu/emulator.cc Normal file
View File

@ -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<int>(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<int>(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<uint8_t *>(malloc(size));
int n = static_cast<int>(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> 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();
}

36
src/emu/emulator.h Normal file
View File

@ -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

View File

@ -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) {

View File

@ -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_;
};

View File

@ -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<type &>(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<type &>(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<Scheduler>(new Scheduler());
memory_ = std::unique_ptr<Memory>(new Memory());
rb_ = std::unique_ptr<renderer::Backend>(new GLBackend(sys_));
rt_frontend_ =
std::unique_ptr<frontend::Frontend>(new SH4Frontend(*memory()));
rt_backend_ = std::unique_ptr<backend::Backend>(new X64Backend(*memory()));
runtime_ = std::unique_ptr<Runtime>(
new Runtime(*memory(), *rt_frontend_.get(), *rt_backend_.get()));
sh4_ = std::unique_ptr<SH4>(new SH4(*memory(), *runtime()));
aica_ = std::unique_ptr<AICA>(new AICA(this));
holly_ = std::unique_ptr<Holly>(new Holly(this));
pvr_ = std::unique_ptr<PVR2>(new PVR2(this));
ta_ = std::unique_ptr<TileAccelerator>(new TileAccelerator(this));
gdrom_ = std::unique_ptr<GDROM>(new GDROM(this));
maple_ = std::unique_ptr<Maple>(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<int>(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<int>(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<uint8_t *>(malloc(size));
int n = static_cast<int>(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> 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<TraceWriter>(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();
}

View File

@ -1,25 +1,23 @@
#ifndef DREAMCAST_H
#define DREAMCAST_H
#include <memory>
#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<type &>(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<type &>(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<hw::Memory> memory_;
std::unique_ptr<hw::Scheduler> scheduler_;
std::unique_ptr<renderer::Backend> rb_;
std::unique_ptr<jit::frontend::Frontend> rt_frontend_;
std::unique_ptr<jit::backend::Backend> rt_backend_;
std::unique_ptr<jit::Runtime> runtime_;
std::unique_ptr<hw::aica::AICA> aica_;
std::unique_ptr<hw::gdrom::GDROM> gdrom_;
std::unique_ptr<hw::holly::Holly> holly_;
std::unique_ptr<hw::holly::PVR2> pvr_;
std::unique_ptr<hw::holly::TileAccelerator> ta_;
std::unique_ptr<hw::maple::Maple> maple_;
std::unique_ptr<hw::sh4::SH4> sh4_;
std::unique_ptr<trace::TraceWriter> 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_;
};
}
}

View File

@ -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> disc) {

View File

@ -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> 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_;

View File

@ -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) {

View File

@ -4,16 +4,14 @@
#include <stdint.h>
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_;
};
}

View File

@ -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) {

View File

@ -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_;

View File

@ -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() {

View File

@ -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<TextureKey, renderer::TextureHandle> 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_;

View File

@ -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<MapleController>(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) {

View File

@ -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<MapleDevice> devices_[MAX_PORTS];
};

View File

@ -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; }

View File

@ -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);

View File

@ -1,7 +1,6 @@
#include <memory>
#include <stdio.h>
#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<TraceViewer> tracer(new TraceViewer());
tracer->Run(load);
TraceViewer tracer;
tracer.Run(load);
} else {
std::unique_ptr<Dreamcast> emu(new Dreamcast());
emu->Run(load);
Emulator emu;
emu.Run(load);
}
ShutdownFlags();