mirror of https://github.com/inolen/redream.git
simplified dreamcast structure so it can be reused with stubs by tests
This commit is contained in:
parent
631a23c11f
commit
f729894480
|
@ -24,17 +24,19 @@ DEFINE_string(bios, "dc_bios.bin", "Path to BIOS");
|
|||
DEFINE_string(flash, "dc_flash.bin", "Path to flash ROM");
|
||||
|
||||
Emulator::Emulator()
|
||||
: tile_renderer_(*dc_.texcache()),
|
||||
trace_writer_(nullptr),
|
||||
: trace_writer_(nullptr),
|
||||
tile_renderer_(nullptr),
|
||||
core_events_(MAX_EVENTS),
|
||||
speed_() {
|
||||
rb_ = new GLBackend(window_);
|
||||
dc_.set_rb(rb_);
|
||||
}
|
||||
|
||||
Emulator::~Emulator() {
|
||||
delete rb_;
|
||||
delete trace_writer_;
|
||||
delete tile_renderer_;
|
||||
|
||||
DestroyDreamcast(dc_);
|
||||
}
|
||||
|
||||
void Emulator::Run(const char *path) {
|
||||
|
@ -46,10 +48,14 @@ void Emulator::Run(const char *path) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!dc_.Init()) {
|
||||
if (!CreateDreamcast(dc_, rb_)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// setup tile renderer with the renderer backend and the dreamcast's
|
||||
// internal textue cache
|
||||
tile_renderer_ = new TileRenderer(*rb_, *dc_.texcache);
|
||||
|
||||
if (!LoadBios(FLAGS_bios.c_str())) {
|
||||
return;
|
||||
}
|
||||
|
@ -98,7 +104,7 @@ bool Emulator::LoadBios(const char *path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
int n = static_cast<int>(fread(dc_.bios(), sizeof(uint8_t), size, fp));
|
||||
int n = static_cast<int>(fread(dc_.bios, sizeof(uint8_t), size, fp));
|
||||
fclose(fp);
|
||||
|
||||
if (n != size) {
|
||||
|
@ -126,7 +132,7 @@ bool Emulator::LoadFlash(const char *path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
int n = static_cast<int>(fread(dc_.flash(), sizeof(uint8_t), size, fp));
|
||||
int n = static_cast<int>(fread(dc_.flash, sizeof(uint8_t), size, fp));
|
||||
fclose(fp);
|
||||
|
||||
if (n != size) {
|
||||
|
@ -158,10 +164,10 @@ bool Emulator::LaunchBIN(const char *path) {
|
|||
|
||||
// load to 0x0c010000 (area 3) which is where 1ST_READ.BIN is normally
|
||||
// loaded to
|
||||
dc_.memory()->Memcpy(0x0c010000, data, size);
|
||||
dc_.memory->Memcpy(0x0c010000, data, size);
|
||||
free(data);
|
||||
|
||||
dc_.sh4()->SetPC(0x0c010000);
|
||||
dc_.sh4->SetPC(0x0c010000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -173,8 +179,8 @@ bool Emulator::LaunchGDI(const char *path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
dc_.gdrom()->SetDisc(std::move(gdi));
|
||||
dc_.sh4()->SetPC(0xa0000000);
|
||||
dc_.gdrom->SetDisc(std::move(gdi));
|
||||
dc_.sh4->SetPC(0xa0000000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -203,7 +209,7 @@ void Emulator::ToggleTracing() {
|
|||
LOG_INFO("End tracing");
|
||||
}
|
||||
|
||||
dc_.set_trace_writer(trace_writer_);
|
||||
dc_.trace_writer = trace_writer_;
|
||||
}
|
||||
|
||||
void Emulator::GraphicsThread() {
|
||||
|
@ -249,14 +255,14 @@ void Emulator::RenderGraphics() {
|
|||
rb_->BeginFrame();
|
||||
|
||||
// render the latest tile context
|
||||
if (TileContext *tactx = dc_.ta()->GetLastContext()) {
|
||||
tile_renderer_.RenderContext(tactx, rb_);
|
||||
if (TileContext *tactx = dc_.ta->GetLastContext()) {
|
||||
tile_renderer_->RenderContext(tactx);
|
||||
}
|
||||
|
||||
// render stats
|
||||
char stats[512];
|
||||
float speed = *reinterpret_cast<float *>(&speed_);
|
||||
snprintf(stats, sizeof(stats), "%.2f%%, %.2f rps", speed, dc_.pvr()->rps());
|
||||
snprintf(stats, sizeof(stats), "%.2f%%, %.2f rps", speed, dc_.pvr->rps());
|
||||
rb_->RenderText2D(0, 0, 12.0f, 0xffffffff, stats);
|
||||
|
||||
// render profiler
|
||||
|
@ -343,7 +349,7 @@ void Emulator::PumpCoreEvents() {
|
|||
ToggleTracing();
|
||||
}
|
||||
} else {
|
||||
dc_.maple()->HandleInput(0, ev.key.code, ev.key.value);
|
||||
dc_.maple->HandleInput(0, ev.key.code, ev.key.value);
|
||||
}
|
||||
} break;
|
||||
|
||||
|
|
|
@ -40,9 +40,9 @@ class Emulator {
|
|||
|
||||
sys::Window window_;
|
||||
hw::Dreamcast dc_;
|
||||
hw::holly::TileRenderer tile_renderer_;
|
||||
renderer::Backend *rb_;
|
||||
trace::TraceWriter *trace_writer_;
|
||||
hw::holly::TileRenderer *tile_renderer_;
|
||||
|
||||
// variables accessed by both the graphics and core thread
|
||||
RingBuffer<sys::WindowEvent> core_events_;
|
||||
|
|
|
@ -9,7 +9,7 @@ AICA::AICA(Dreamcast *dc) : dc_(dc) {}
|
|||
|
||||
bool AICA::Init() {
|
||||
// aica_regs_ = dc_->aica_regs();
|
||||
wave_ram_ = dc_->wave_ram();
|
||||
wave_ram_ = dc_->wave_ram;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
namespace dvm {
|
||||
namespace hw {
|
||||
class Dreamcast;
|
||||
struct Dreamcast;
|
||||
|
||||
namespace aica {
|
||||
|
||||
|
|
|
@ -25,118 +25,30 @@ using namespace dvm::renderer;
|
|||
using namespace dvm::sys;
|
||||
using namespace dvm::trace;
|
||||
|
||||
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
|
||||
|
||||
#define PVR_REG(addr, name, flags, default, type) \
|
||||
pvr_regs_[name##_OFFSET] = {flags, default};
|
||||
#include "hw/holly/pvr2_regs.inc"
|
||||
#undef PVR_REG
|
||||
|
||||
scheduler_ = new Scheduler();
|
||||
memory_ = new Memory();
|
||||
aica_ = new AICA(this);
|
||||
gdrom_ = new GDROM(this);
|
||||
holly_ = new Holly(this);
|
||||
maple_ = new Maple(this);
|
||||
pvr_ = new PVR2(this);
|
||||
sh4_ = new SH4(this);
|
||||
ta_ = new TileAccelerator(this);
|
||||
texcache_ = new TextureCache(this);
|
||||
}
|
||||
|
||||
Dreamcast::~Dreamcast() {
|
||||
delete[] holly_regs_;
|
||||
delete[] pvr_regs_;
|
||||
|
||||
delete scheduler_;
|
||||
delete memory_;
|
||||
delete aica_;
|
||||
delete gdrom_;
|
||||
delete holly_;
|
||||
delete maple_;
|
||||
delete pvr_;
|
||||
delete sh4_;
|
||||
delete ta_;
|
||||
delete texcache_;
|
||||
}
|
||||
|
||||
bool Dreamcast::Init() {
|
||||
if (!MapMemory()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aica_->Init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gdrom_->Init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!holly_->Init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!maple_->Init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pvr_->Init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sh4_->Init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ta_->Init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!texcache_->Init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
namespace dvm {
|
||||
namespace hw {
|
||||
|
||||
// clang-format off
|
||||
bool Dreamcast::MapMemory() {
|
||||
if (!memory_->Init()) {
|
||||
static bool MapMemory(Dreamcast &dc) {
|
||||
Memory *memory = dc.memory;
|
||||
|
||||
if (!memory->Init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// first, allocate static regions
|
||||
RegionHandle a0_handle = memory_->AllocRegion(AREA0_START, AREA0_SIZE);
|
||||
RegionHandle a1_handle = memory_->AllocRegion(AREA1_START, AREA1_SIZE);
|
||||
RegionHandle a0_handle = memory->AllocRegion(AREA0_START, AREA0_SIZE);
|
||||
RegionHandle a1_handle = memory->AllocRegion(AREA1_START, AREA1_SIZE);
|
||||
// area 2 unused
|
||||
RegionHandle a3_handle = memory_->AllocRegion(AREA3_START, AREA3_SIZE);
|
||||
RegionHandle a3_handle = memory->AllocRegion(AREA3_START, AREA3_SIZE);
|
||||
// area 4 unused
|
||||
RegionHandle a5_handle = memory_->AllocRegion(AREA5_START, AREA5_SIZE);
|
||||
RegionHandle a6_handle = memory_->AllocRegion(AREA6_START, AREA6_SIZE);
|
||||
RegionHandle a7_handle = memory_->AllocRegion(AREA7_START, AREA7_SIZE);
|
||||
RegionHandle a5_handle = memory->AllocRegion(AREA5_START, AREA5_SIZE);
|
||||
RegionHandle a6_handle = memory->AllocRegion(AREA6_START, AREA6_SIZE);
|
||||
RegionHandle a7_handle = memory->AllocRegion(AREA7_START, AREA7_SIZE);
|
||||
|
||||
// second, allocate dynamic regions that overlap static regions
|
||||
RegionHandle holly_handle = memory_->AllocRegion(
|
||||
HOLLY_REG_START, HOLLY_REG_SIZE, holly(),
|
||||
RegionHandle holly_handle = memory->AllocRegion(
|
||||
HOLLY_REG_START, HOLLY_REG_SIZE, dc.holly,
|
||||
&Holly::ReadRegister<uint8_t>,
|
||||
&Holly::ReadRegister<uint16_t>,
|
||||
&Holly::ReadRegister<uint32_t>,
|
||||
|
@ -145,8 +57,8 @@ bool Dreamcast::MapMemory() {
|
|||
&Holly::WriteRegister<uint16_t>,
|
||||
&Holly::WriteRegister<uint32_t>,
|
||||
nullptr);
|
||||
RegionHandle pvr_reg_handle = memory_->AllocRegion(
|
||||
PVR_REG_START, PVR_REG_SIZE, pvr(),
|
||||
RegionHandle pvr_reg_handle = memory->AllocRegion(
|
||||
PVR_REG_START, PVR_REG_SIZE, dc.pvr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&PVR2::ReadRegister,
|
||||
|
@ -155,7 +67,7 @@ bool Dreamcast::MapMemory() {
|
|||
nullptr,
|
||||
&PVR2::WriteRegister,
|
||||
nullptr);
|
||||
// RegionHandle aica_reg_handle = memory_->AllocRegion(
|
||||
// RegionHandle aica_reg_handle = memory->AllocRegion(
|
||||
// AICA_REG_START, AICA_REG_SIZE, aica(),
|
||||
// nullptr,
|
||||
// nullptr,
|
||||
|
@ -165,8 +77,8 @@ bool Dreamcast::MapMemory() {
|
|||
// nullptr,
|
||||
// &AICA::WriteRegister,
|
||||
// nullptr);
|
||||
RegionHandle wave_ram_handle = memory_->AllocRegion(
|
||||
WAVE_RAM_START, WAVE_RAM_SIZE, aica(),
|
||||
RegionHandle wave_ram_handle = memory->AllocRegion(
|
||||
WAVE_RAM_START, WAVE_RAM_SIZE, dc.aica,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&AICA::ReadWave,
|
||||
|
@ -175,8 +87,8 @@ bool Dreamcast::MapMemory() {
|
|||
nullptr,
|
||||
&AICA::WriteWave,
|
||||
nullptr);
|
||||
RegionHandle pvr_vram64_handle = memory_->AllocRegion(
|
||||
PVR_VRAM64_START, PVR_VRAM64_SIZE, pvr(),
|
||||
RegionHandle pvr_vram64_handle = memory->AllocRegion(
|
||||
PVR_VRAM64_START, PVR_VRAM64_SIZE, dc.pvr,
|
||||
&PVR2::ReadVRamInterleaved<uint8_t>,
|
||||
&PVR2::ReadVRamInterleaved<uint16_t>,
|
||||
&PVR2::ReadVRamInterleaved<uint32_t>,
|
||||
|
@ -185,8 +97,8 @@ bool Dreamcast::MapMemory() {
|
|||
&PVR2::WriteVRamInterleaved<uint16_t>,
|
||||
&PVR2::WriteVRamInterleaved<uint32_t>,
|
||||
nullptr);
|
||||
RegionHandle ta_cmd_handle = memory_->AllocRegion(
|
||||
TA_CMD_START, TA_CMD_SIZE, ta(),
|
||||
RegionHandle ta_cmd_handle = memory->AllocRegion(
|
||||
TA_CMD_START, TA_CMD_SIZE, dc.ta,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
|
@ -195,8 +107,8 @@ bool Dreamcast::MapMemory() {
|
|||
nullptr,
|
||||
&TileAccelerator::WriteCommand,
|
||||
nullptr);
|
||||
RegionHandle ta_texture_handle = memory_->AllocRegion(
|
||||
TA_TEXTURE_START, TA_TEXTURE_SIZE, ta(),
|
||||
RegionHandle ta_texture_handle = memory->AllocRegion(
|
||||
TA_TEXTURE_START, TA_TEXTURE_SIZE, dc.ta,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
|
@ -205,8 +117,8 @@ bool Dreamcast::MapMemory() {
|
|||
nullptr,
|
||||
&TileAccelerator::WriteTexture,
|
||||
nullptr);
|
||||
RegionHandle sh4_reg_handle = memory_->AllocRegion(
|
||||
SH4_REG_START, SH4_REG_SIZE, sh4(),
|
||||
RegionHandle sh4_reg_handle = memory->AllocRegion(
|
||||
SH4_REG_START, SH4_REG_SIZE, dc.sh4,
|
||||
&SH4::ReadRegister<uint8_t>,
|
||||
&SH4::ReadRegister<uint16_t>,
|
||||
&SH4::ReadRegister<uint32_t>,
|
||||
|
@ -215,8 +127,8 @@ bool Dreamcast::MapMemory() {
|
|||
&SH4::WriteRegister<uint16_t>,
|
||||
&SH4::WriteRegister<uint32_t>,
|
||||
nullptr);
|
||||
RegionHandle sh4_cache_handle = memory_->AllocRegion(
|
||||
SH4_CACHE_START, SH4_CACHE_SIZE, sh4(),
|
||||
RegionHandle sh4_cache_handle = memory->AllocRegion(
|
||||
SH4_CACHE_START, SH4_CACHE_SIZE, dc.sh4,
|
||||
&SH4::ReadCache<uint8_t>,
|
||||
&SH4::ReadCache<uint16_t>,
|
||||
&SH4::ReadCache<uint32_t>,
|
||||
|
@ -225,8 +137,8 @@ bool Dreamcast::MapMemory() {
|
|||
&SH4::WriteCache<uint16_t>,
|
||||
&SH4::WriteCache<uint32_t>,
|
||||
&SH4::WriteCache<uint64_t>);
|
||||
RegionHandle sh4_sq_handle = memory_->AllocRegion(
|
||||
SH4_SQ_START, SH4_SQ_SIZE, sh4(),
|
||||
RegionHandle sh4_sq_handle = memory->AllocRegion(
|
||||
SH4_SQ_START, SH4_SQ_SIZE, dc.sh4,
|
||||
&SH4::ReadSQ<uint8_t>,
|
||||
&SH4::ReadSQ<uint16_t>,
|
||||
&SH4::ReadSQ<uint32_t>,
|
||||
|
@ -273,18 +185,72 @@ bool Dreamcast::MapMemory() {
|
|||
memmap.Mount(sh4_cache_handle, SH4_CACHE_SIZE, SH4_CACHE_START);
|
||||
memmap.Mount(sh4_sq_handle, SH4_SQ_SIZE, SH4_SQ_START);
|
||||
|
||||
if (!memory_->Map(memmap)) {
|
||||
if (!memory->Map(memmap)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bios_ = memory_->virtual_base() + BIOS_START;
|
||||
flash_ = memory_->virtual_base() + FLASH_START;
|
||||
wave_ram_ = memory_->virtual_base() + WAVE_RAM_START;
|
||||
palette_ram_ = memory_->virtual_base() + PVR_PALETTE_START;
|
||||
video_ram_ = memory_->virtual_base() + PVR_VRAM32_START;
|
||||
// aica_regs_ = memory_->virtual_base() + AICA_REG_START;
|
||||
ram_ = memory_->virtual_base() + MAIN_RAM_1_START;
|
||||
dc.bios = memory->virtual_base() + BIOS_START;
|
||||
dc.flash = memory->virtual_base() + FLASH_START;
|
||||
dc.wave_ram = memory->virtual_base() + WAVE_RAM_START;
|
||||
dc.palette_ram = memory->virtual_base() + PVR_PALETTE_START;
|
||||
dc.video_ram = memory->virtual_base() + PVR_VRAM32_START;
|
||||
// dc.aica_regs = memory->virtual_base() + AICA_REG_START;
|
||||
dc.ram = memory->virtual_base() + MAIN_RAM_1_START;
|
||||
|
||||
return true;
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
bool CreateDreamcast(Dreamcast &dc, renderer::Backend *rb) {
|
||||
dc.scheduler = new Scheduler();
|
||||
dc.memory = new Memory();
|
||||
dc.aica = new AICA(&dc);
|
||||
dc.gdrom = new GDROM(&dc);
|
||||
dc.holly = new Holly(&dc);
|
||||
dc.maple = new Maple(&dc);
|
||||
dc.pvr = new PVR2(&dc);
|
||||
dc.sh4 = new SH4(&dc);
|
||||
dc.ta = new TileAccelerator(&dc);
|
||||
dc.texcache = new TextureCache(&dc);
|
||||
dc.rb = rb;
|
||||
|
||||
if (!MapMemory(dc) || //
|
||||
!dc.aica->Init() || //
|
||||
!dc.gdrom->Init() || //
|
||||
!dc.holly->Init() || //
|
||||
!dc.maple->Init() || //
|
||||
!dc.pvr->Init() || //
|
||||
!dc.sh4->Init() || //
|
||||
!dc.ta->Init() || //
|
||||
!dc.texcache->Init()) {
|
||||
DestroyDreamcast(dc);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DestroyDreamcast(Dreamcast &dc) {
|
||||
delete dc.scheduler;
|
||||
dc.scheduler = nullptr;
|
||||
delete dc.memory;
|
||||
dc.memory = nullptr;
|
||||
delete dc.aica;
|
||||
dc.aica = nullptr;
|
||||
delete dc.gdrom;
|
||||
dc.gdrom = nullptr;
|
||||
delete dc.holly;
|
||||
dc.holly = nullptr;
|
||||
delete dc.maple;
|
||||
dc.maple = nullptr;
|
||||
delete dc.pvr;
|
||||
dc.pvr = nullptr;
|
||||
delete dc.sh4;
|
||||
dc.sh4 = nullptr;
|
||||
delete dc.ta;
|
||||
dc.ta = nullptr;
|
||||
delete dc.texcache;
|
||||
dc.texcache = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ class Holly;
|
|||
class PVR2;
|
||||
class TextureCache;
|
||||
class TileAccelerator;
|
||||
class TileRenderer;
|
||||
}
|
||||
|
||||
namespace maple {
|
||||
|
@ -137,84 +136,58 @@ enum {
|
|||
#undef PVR_REG
|
||||
};
|
||||
|
||||
class Dreamcast {
|
||||
public:
|
||||
// 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_; }
|
||||
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_; }
|
||||
hw::holly::TextureCache *texcache() { return texcache_; }
|
||||
|
||||
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();
|
||||
|
||||
bool Init();
|
||||
|
||||
private:
|
||||
Register *holly_regs_;
|
||||
|
||||
public:
|
||||
#define HOLLY_REG(offset, name, flags, default, type) type &name;
|
||||
struct Dreamcast {
|
||||
Dreamcast() {
|
||||
#define HOLLY_REG(addr, name, flags, default, type) \
|
||||
holly_regs[name##_OFFSET] = {flags, default};
|
||||
#include "hw/holly/holly_regs.inc"
|
||||
#undef HOLLY_REG
|
||||
|
||||
private:
|
||||
Register *pvr_regs_;
|
||||
#define PVR_REG(addr, name, flags, default, type) \
|
||||
pvr_regs[name##_OFFSET] = {flags, default};
|
||||
#include "hw/holly/pvr2_regs.inc"
|
||||
#undef PVR_REG
|
||||
}
|
||||
|
||||
public:
|
||||
#define PVR_REG(offset, name, flags, default, type) type &name;
|
||||
// uint8_t *aica_regs;
|
||||
Register holly_regs[HOLLY_REG_SIZE >> 2];
|
||||
Register pvr_regs[PVR_REG_SIZE >> 2];
|
||||
|
||||
#define HOLLY_REG(offset, name, flags, default, type) \
|
||||
type &name{reinterpret_cast<type &>(holly_regs[name##_OFFSET].value)};
|
||||
#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)};
|
||||
#include "hw/holly/pvr2_regs.inc"
|
||||
#undef PVR_REG
|
||||
|
||||
private:
|
||||
bool MapMemory();
|
||||
uint8_t *bios;
|
||||
uint8_t *flash;
|
||||
uint8_t *palette_ram;
|
||||
uint8_t *ram;
|
||||
uint8_t *video_ram;
|
||||
uint8_t *wave_ram;
|
||||
|
||||
// uint8_t *aica_regs_;
|
||||
uint8_t *bios_;
|
||||
uint8_t *flash_;
|
||||
uint8_t *palette_ram_;
|
||||
uint8_t *ram_;
|
||||
uint8_t *video_ram_;
|
||||
uint8_t *wave_ram_;
|
||||
|
||||
hw::Memory *memory_;
|
||||
hw::Scheduler *scheduler_;
|
||||
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_;
|
||||
hw::holly::TextureCache *texcache_;
|
||||
hw::Memory *memory;
|
||||
hw::Scheduler *scheduler;
|
||||
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;
|
||||
hw::holly::TextureCache *texcache;
|
||||
|
||||
// not owned by us
|
||||
renderer::Backend *rb_;
|
||||
trace::TraceWriter *trace_writer_;
|
||||
renderer::Backend *rb;
|
||||
trace::TraceWriter *trace_writer;
|
||||
};
|
||||
|
||||
bool CreateDreamcast(Dreamcast &dc, renderer::Backend *rb);
|
||||
void DestroyDreamcast(Dreamcast &dc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,9 +31,9 @@ GDROM::GDROM(Dreamcast *dc)
|
|||
GDROM::~GDROM() { delete[] dma_buffer_; }
|
||||
|
||||
bool GDROM::Init() {
|
||||
memory_ = dc_->memory();
|
||||
holly_ = dc_->holly();
|
||||
holly_regs_ = dc_->holly_regs();
|
||||
memory_ = dc_->memory;
|
||||
holly_ = dc_->holly;
|
||||
holly_regs_ = dc_->holly_regs;
|
||||
|
||||
SetDisc(nullptr);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace holly {
|
|||
class Holly;
|
||||
}
|
||||
|
||||
class Dreamcast;
|
||||
struct Dreamcast;
|
||||
class Memory;
|
||||
struct Register;
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@ using namespace dvm::sys;
|
|||
Holly::Holly(Dreamcast *dc) : dc_(dc) {}
|
||||
|
||||
bool Holly::Init() {
|
||||
holly_regs_ = dc_->holly_regs();
|
||||
gdrom_ = dc_->gdrom();
|
||||
maple_ = dc_->maple();
|
||||
sh4_ = dc_->sh4();
|
||||
holly_regs_ = dc_->holly_regs;
|
||||
gdrom_ = dc_->gdrom;
|
||||
maple_ = dc_->maple;
|
||||
sh4_ = dc_->sh4;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ void Holly::RequestInterrupt(HollyInterrupt intr) {
|
|||
uint32_t irq = static_cast<uint32_t>(intr & ~HOLLY_INTC_MASK);
|
||||
|
||||
if (intr == HOLLY_INTC_PCVOINT) {
|
||||
dc_->maple()->VBlank();
|
||||
dc_->maple->VBlank();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace sh4 {
|
|||
class SH4;
|
||||
}
|
||||
|
||||
class Dreamcast;
|
||||
struct Dreamcast;
|
||||
struct Register;
|
||||
|
||||
namespace holly {
|
||||
|
|
|
@ -12,13 +12,13 @@ PVR2::PVR2(Dreamcast *dc)
|
|||
: dc_(dc), line_timer_(INVALID_TIMER), current_scanline_(0), rps_(0.0f) {}
|
||||
|
||||
bool PVR2::Init() {
|
||||
scheduler_ = dc_->scheduler();
|
||||
holly_ = dc_->holly();
|
||||
ta_ = dc_->ta();
|
||||
texcache_ = dc_->texcache();
|
||||
pvr_regs_ = dc_->pvr_regs();
|
||||
palette_ram_ = dc_->palette_ram();
|
||||
video_ram_ = dc_->video_ram();
|
||||
scheduler_ = dc_->scheduler;
|
||||
holly_ = dc_->holly;
|
||||
ta_ = dc_->ta;
|
||||
texcache_ = dc_->texcache;
|
||||
pvr_regs_ = dc_->pvr_regs;
|
||||
palette_ram_ = dc_->palette_ram;
|
||||
video_ram_ = dc_->video_ram;
|
||||
|
||||
ReconfigureSPG();
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace dvm {
|
||||
namespace hw {
|
||||
class Dreamcast;
|
||||
struct Dreamcast;
|
||||
struct Register;
|
||||
|
||||
namespace holly {
|
||||
|
|
|
@ -23,9 +23,9 @@ TextureHandle TextureCache::GetTexture(const TSP &tsp, const TCW &tcw,
|
|||
}
|
||||
|
||||
// if the trace writer has changed, clear the cache to force insert events
|
||||
if (dc_->trace_writer() != trace_writer_) {
|
||||
if (dc_->trace_writer != trace_writer_) {
|
||||
Clear();
|
||||
trace_writer_ = dc_->trace_writer();
|
||||
trace_writer_ = dc_->trace_writer;
|
||||
}
|
||||
|
||||
// see if an an entry already exists
|
||||
|
@ -40,7 +40,7 @@ TextureHandle TextureCache::GetTexture(const TSP &tsp, const TCW &tcw,
|
|||
uint32_t texture_addr = tcw.texture_addr << 3;
|
||||
|
||||
// get the texture data
|
||||
uint8_t *video_ram = dc_->video_ram();
|
||||
uint8_t *video_ram = dc_->video_ram;
|
||||
uint8_t *texture = &video_ram[texture_addr];
|
||||
int width = 8 << tsp.texture_u_size;
|
||||
int height = 8 << tsp.texture_v_size;
|
||||
|
@ -50,7 +50,7 @@ TextureHandle TextureCache::GetTexture(const TSP &tsp, const TCW &tcw,
|
|||
int texture_size = (width * height * element_size_bits) >> 3;
|
||||
|
||||
// get the palette data
|
||||
uint8_t *palette_ram = dc_->palette_ram();
|
||||
uint8_t *palette_ram = dc_->palette_ram;
|
||||
uint8_t *palette = nullptr;
|
||||
uint32_t palette_addr = 0;
|
||||
int palette_size = 0;
|
||||
|
@ -175,7 +175,7 @@ void TextureCache::Invalidate(TextureCacheMap::iterator it) {
|
|||
RemoveAccessWatch(entry.palette_watch);
|
||||
}
|
||||
|
||||
dc_->rb()->FreeTexture(entry.handle);
|
||||
dc_->rb->FreeTexture(entry.handle);
|
||||
|
||||
textures_.erase(it);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ class TraceWriter;
|
|||
}
|
||||
|
||||
namespace hw {
|
||||
class Dreamcast;
|
||||
struct Dreamcast;
|
||||
|
||||
namespace holly {
|
||||
|
||||
|
@ -37,7 +37,7 @@ class TextureCache : public TextureProvider {
|
|||
|
||||
bool Init();
|
||||
renderer::TextureHandle GetTexture(const TSP &tsp, const TCW &tcw,
|
||||
RegisterTextureCallback register_cb);
|
||||
RegisterTextureCallback register_cb) final;
|
||||
|
||||
private:
|
||||
static void HandleTextureWrite(void *ctx, const sys::Exception &ex,
|
||||
|
|
|
@ -212,10 +212,10 @@ TileAccelerator::TileAccelerator(Dreamcast *dc) : dc_(dc), contexts_() {
|
|||
}
|
||||
|
||||
bool TileAccelerator::Init() {
|
||||
memory_ = dc_->memory();
|
||||
holly_ = dc_->holly();
|
||||
texcache_ = dc_->texcache();
|
||||
video_ram_ = dc_->video_ram();
|
||||
memory_ = dc_->memory;
|
||||
holly_ = dc_->holly;
|
||||
texcache_ = dc_->texcache;
|
||||
video_ram_ = dc_->video_ram;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -312,8 +312,8 @@ void TileAccelerator::FinalizeContext(uint32_t addr) {
|
|||
WriteBackgroundState(tactx);
|
||||
|
||||
// add context to trace
|
||||
if (dc_->trace_writer()) {
|
||||
dc_->trace_writer()->WriteRenderContext(tactx);
|
||||
if (dc_->trace_writer) {
|
||||
dc_->trace_writer->WriteRenderContext(tactx);
|
||||
}
|
||||
|
||||
// tell holly that rendering is complete
|
||||
|
|
|
@ -13,7 +13,7 @@ class TraceWriter;
|
|||
}
|
||||
|
||||
namespace hw {
|
||||
class Dreamcast;
|
||||
struct Dreamcast;
|
||||
class Memory;
|
||||
|
||||
namespace holly {
|
||||
|
|
|
@ -105,8 +105,9 @@ TextureKey TextureProvider::GetTextureKey(const TSP &tsp, const TCW &tcw) {
|
|||
return ((uint64_t)tsp.full << 32) | tcw.full;
|
||||
}
|
||||
|
||||
TileRenderer::TileRenderer(TextureProvider &texture_provider)
|
||||
: texture_provider_(texture_provider) {
|
||||
TileRenderer::TileRenderer(renderer::Backend &rb,
|
||||
TextureProvider &texture_provider)
|
||||
: rb_(rb), texture_provider_(texture_provider) {
|
||||
surfs_ = new Surface[MAX_SURFACES];
|
||||
verts_ = new Vertex[MAX_VERTICES];
|
||||
sorted_surfs_ = new int[MAX_SURFACES];
|
||||
|
@ -118,11 +119,11 @@ TileRenderer::~TileRenderer() {
|
|||
delete[] sorted_surfs_;
|
||||
}
|
||||
|
||||
void TileRenderer::RenderContext(const TileContext *tactx, Backend *rb) {
|
||||
ParseContext(tactx, rb);
|
||||
void TileRenderer::RenderContext(const TileContext *tactx) {
|
||||
ParseContext(tactx);
|
||||
|
||||
const Eigen::Matrix4f &projection = GetProjectionMatrix(tactx);
|
||||
rb->RenderSurfaces(projection, surfs_, num_surfs_, verts_, num_verts_,
|
||||
rb_.RenderSurfaces(projection, surfs_, num_surfs_, verts_, num_verts_,
|
||||
sorted_surfs_);
|
||||
}
|
||||
|
||||
|
@ -305,7 +306,7 @@ void TileRenderer::ParseBackground(const TileContext *tactx) {
|
|||
|
||||
// NOTE this offset color implementation is not correct at all, see the
|
||||
// Texture/Shading Instruction in the TSP instruction word
|
||||
void TileRenderer::ParsePolyParam(const TileContext *tactx, Backend *rb,
|
||||
void TileRenderer::ParsePolyParam(const TileContext *tactx,
|
||||
const PolyParam *param) {
|
||||
last_poly_ = param;
|
||||
last_vertex_ = nullptr;
|
||||
|
@ -336,10 +337,9 @@ void TileRenderer::ParsePolyParam(const TileContext *tactx, Backend *rb,
|
|||
surf->depth_func = DEPTH_GEQUAL;
|
||||
}
|
||||
|
||||
surf->texture =
|
||||
param->type0.pcw.texture
|
||||
? GetTexture(tactx, rb, param->type0.tsp, param->type0.tcw)
|
||||
: 0;
|
||||
surf->texture = param->type0.pcw.texture
|
||||
? GetTexture(tactx, param->type0.tsp, param->type0.tcw)
|
||||
: 0;
|
||||
|
||||
int poly_type = TileAccelerator::GetPolyType(param->type0.pcw);
|
||||
switch (poly_type) {
|
||||
|
@ -391,7 +391,7 @@ void TileRenderer::ParsePolyParam(const TileContext *tactx, Backend *rb,
|
|||
}
|
||||
}
|
||||
|
||||
void TileRenderer::ParseVertexParam(const TileContext *tactx, Backend *rb,
|
||||
void TileRenderer::ParseVertexParam(const TileContext *tactx,
|
||||
const VertexParam *param) {
|
||||
// If there is no need to change the Global Parameters, a Vertex Parameter for
|
||||
// the next polygon may be input immediately after inputting a Vertex
|
||||
|
@ -608,7 +608,7 @@ void TileRenderer::ParseEndOfList(const TileContext *tactx) {
|
|||
last_sorted_surf_ = num_surfs_;
|
||||
}
|
||||
|
||||
void TileRenderer::ParseContext(const TileContext *tactx, Backend *rb) {
|
||||
void TileRenderer::ParseContext(const TileContext *tactx) {
|
||||
PROFILER_GPU("TileRenderer::ParseContext");
|
||||
|
||||
const uint8_t *data = tactx->data;
|
||||
|
@ -643,17 +643,16 @@ void TileRenderer::ParseContext(const TileContext *tactx, Backend *rb) {
|
|||
|
||||
// global params
|
||||
case TA_PARAM_POLY_OR_VOL:
|
||||
ParsePolyParam(tactx, rb, reinterpret_cast<const PolyParam *>(data));
|
||||
ParsePolyParam(tactx, reinterpret_cast<const PolyParam *>(data));
|
||||
break;
|
||||
|
||||
case TA_PARAM_SPRITE:
|
||||
ParsePolyParam(tactx, rb, reinterpret_cast<const PolyParam *>(data));
|
||||
ParsePolyParam(tactx, reinterpret_cast<const PolyParam *>(data));
|
||||
break;
|
||||
|
||||
// vertex params
|
||||
case TA_PARAM_VERTEX:
|
||||
ParseVertexParam(tactx, rb,
|
||||
reinterpret_cast<const VertexParam *>(data));
|
||||
ParseVertexParam(tactx, reinterpret_cast<const VertexParam *>(data));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -707,8 +706,7 @@ Eigen::Matrix4f TileRenderer::GetProjectionMatrix(const TileContext *tactx) {
|
|||
}
|
||||
|
||||
TextureHandle TileRenderer::RegisterTexture(const TileContext *tactx,
|
||||
Backend *rb, const TSP &tsp,
|
||||
const TCW &tcw,
|
||||
const TSP &tsp, const TCW &tcw,
|
||||
const uint8_t *palette,
|
||||
const uint8_t *texture) {
|
||||
static uint8_t converted[1024 * 1024 * 4];
|
||||
|
@ -883,7 +881,7 @@ TextureHandle TileRenderer::RegisterTexture(const TileContext *tactx,
|
|||
? WRAP_CLAMP_TO_EDGE
|
||||
: (tsp.flip_v ? WRAP_MIRRORED_REPEAT : WRAP_REPEAT);
|
||||
|
||||
TextureHandle handle = rb->RegisterTexture(pixel_fmt, filter, wrap_u, wrap_v,
|
||||
TextureHandle handle = rb_.RegisterTexture(pixel_fmt, filter, wrap_u, wrap_v,
|
||||
mip_mapped, width, height, output);
|
||||
|
||||
if (!handle) {
|
||||
|
@ -894,10 +892,10 @@ TextureHandle TileRenderer::RegisterTexture(const TileContext *tactx,
|
|||
return handle;
|
||||
}
|
||||
|
||||
TextureHandle TileRenderer::GetTexture(const TileContext *tactx, Backend *rb,
|
||||
const TSP &tsp, const TCW &tcw) {
|
||||
TextureHandle TileRenderer::GetTexture(const TileContext *tactx, const TSP &tsp,
|
||||
const TCW &tcw) {
|
||||
return texture_provider_.GetTexture(
|
||||
tsp, tcw, [&](const uint8_t *palette, const uint8_t *texture) {
|
||||
return RegisterTexture(tactx, rb, tsp, tcw, palette, texture);
|
||||
return RegisterTexture(tactx, tsp, tcw, palette, texture);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -42,10 +42,10 @@ enum { MAX_SURFACES = 0x10000, MAX_VERTICES = 0x10000 };
|
|||
|
||||
class TileRenderer {
|
||||
public:
|
||||
TileRenderer(TextureProvider &texture_provider);
|
||||
TileRenderer(renderer::Backend &rb, TextureProvider &texture_provider);
|
||||
~TileRenderer();
|
||||
|
||||
void RenderContext(const TileContext *tactx, renderer::Backend *rb);
|
||||
void RenderContext(const TileContext *tactx);
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
|
@ -59,23 +59,20 @@ class TileRenderer {
|
|||
void ParseOffsetColor(float r, float g, float b, float a, uint32_t *color);
|
||||
void ParseOffsetColor(float intensity, uint32_t *color);
|
||||
void ParseBackground(const TileContext *tactx);
|
||||
void ParsePolyParam(const TileContext *tactx, renderer::Backend *rb,
|
||||
const PolyParam *param);
|
||||
void ParseVertexParam(const TileContext *tactx, renderer::Backend *rb,
|
||||
const VertexParam *param);
|
||||
void ParsePolyParam(const TileContext *tactx, const PolyParam *param);
|
||||
void ParseVertexParam(const TileContext *tactx, const VertexParam *param);
|
||||
void ParseEndOfList(const TileContext *tactx);
|
||||
void ParseContext(const TileContext *tactx, renderer::Backend *rb);
|
||||
void ParseContext(const TileContext *tactx);
|
||||
Eigen::Matrix4f GetProjectionMatrix(const TileContext *tactx);
|
||||
|
||||
renderer::TextureHandle RegisterTexture(const TileContext *tactx,
|
||||
renderer::Backend *rb, const TSP &tsp,
|
||||
const TCW &tcw,
|
||||
const TSP &tsp, const TCW &tcw,
|
||||
const uint8_t *palette,
|
||||
const uint8_t *texture);
|
||||
renderer::TextureHandle GetTexture(const TileContext *tactx,
|
||||
renderer::Backend *rb, const TSP &tsp,
|
||||
renderer::TextureHandle GetTexture(const TileContext *tactx, const TSP &tsp,
|
||||
const TCW &tcw);
|
||||
|
||||
renderer::Backend &rb_;
|
||||
TextureProvider &texture_provider_;
|
||||
|
||||
// current global state
|
||||
|
|
|
@ -17,9 +17,9 @@ Maple::Maple(Dreamcast *dc) : dc_(dc), devices_() {
|
|||
}
|
||||
|
||||
bool Maple::Init() {
|
||||
memory_ = dc_->memory();
|
||||
holly_ = dc_->holly();
|
||||
holly_regs_ = dc_->holly_regs();
|
||||
memory_ = dc_->memory;
|
||||
holly_ = dc_->holly;
|
||||
holly_regs_ = dc_->holly_regs;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace holly {
|
|||
class Holly;
|
||||
}
|
||||
|
||||
class Dreamcast;
|
||||
struct Dreamcast;
|
||||
class Memory;
|
||||
struct Register;
|
||||
|
||||
|
|
|
@ -37,8 +37,8 @@ SH4::SH4(Dreamcast *dc)
|
|||
SH4::~SH4() { delete code_cache_; }
|
||||
|
||||
bool SH4::Init() {
|
||||
memory_ = dc_->memory();
|
||||
scheduler_ = dc_->scheduler();
|
||||
memory_ = dc_->memory;
|
||||
scheduler_ = dc_->scheduler;
|
||||
|
||||
code_cache_ = new SH4CodeCache(memory_, &SH4::CompilePC);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ struct SH4Test;
|
|||
namespace dvm {
|
||||
namespace hw {
|
||||
|
||||
class Dreamcast;
|
||||
struct Dreamcast;
|
||||
|
||||
namespace sh4 {
|
||||
|
||||
|
|
|
@ -42,14 +42,16 @@ TextureHandle TraceTextureCache::GetTexture(
|
|||
return texture.handle;
|
||||
}
|
||||
|
||||
TraceViewer::TraceViewer() : tile_renderer_(texcache_) {
|
||||
TraceViewer::TraceViewer() {
|
||||
rb_ = new GLBackend(wnd_);
|
||||
tile_renderer_ = new TileRenderer(*rb_, texcache_);
|
||||
current_ctx_ = new TileContext();
|
||||
}
|
||||
|
||||
TraceViewer::~TraceViewer() {
|
||||
delete current_ctx_;
|
||||
delete rb_;
|
||||
delete tile_renderer_;
|
||||
delete current_ctx_;
|
||||
}
|
||||
|
||||
void TraceViewer::Run(const char *path) {
|
||||
|
@ -124,7 +126,7 @@ void TraceViewer::PumpEvents() {
|
|||
void TraceViewer::RenderFrame() {
|
||||
rb_->BeginFrame();
|
||||
|
||||
tile_renderer_.RenderContext(current_ctx_, rb_);
|
||||
tile_renderer_->RenderContext(current_ctx_);
|
||||
|
||||
// render stats
|
||||
char stats[512];
|
||||
|
|
|
@ -54,8 +54,8 @@ class TraceViewer {
|
|||
|
||||
sys::Window wnd_;
|
||||
TraceTextureCache texcache_;
|
||||
hw::holly::TileRenderer tile_renderer_;
|
||||
renderer::Backend *rb_;
|
||||
hw::holly::TileRenderer *tile_renderer_;
|
||||
|
||||
TraceReader reader_;
|
||||
TraceCommand *current_cmd_;
|
||||
|
|
Loading…
Reference in New Issue