mirror of https://github.com/inolen/redream.git
use references for dc / rb
align ir locals when allocating
This commit is contained in:
parent
d234f630f1
commit
98ca25fecb
|
@ -92,13 +92,13 @@ void Emulator::Run(const char *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Emulator::CreateDreamcast() {
|
bool Emulator::CreateDreamcast() {
|
||||||
dc_.sh4 = new SH4(&dc_);
|
dc_.sh4 = new SH4(dc_);
|
||||||
dc_.aica = new AICA(&dc_);
|
dc_.aica = new AICA(dc_);
|
||||||
dc_.gdrom = new GDROM(&dc_);
|
dc_.gdrom = new GDROM(dc_);
|
||||||
dc_.holly = new Holly(&dc_);
|
dc_.holly = new Holly(dc_);
|
||||||
dc_.maple = new Maple(&dc_);
|
dc_.maple = new Maple(dc_);
|
||||||
dc_.pvr = new PVR2(&dc_);
|
dc_.pvr = new PVR2(dc_);
|
||||||
dc_.ta = new TileAccelerator(&dc_, window_.render_backend());
|
dc_.ta = new TileAccelerator(dc_, window_.render_backend());
|
||||||
|
|
||||||
if (!dc_.Init()) {
|
if (!dc_.Init()) {
|
||||||
DestroyDreamcast();
|
DestroyDreamcast();
|
||||||
|
|
|
@ -81,7 +81,7 @@ TextureHandle TraceTextureCache::GetTexture(hw::holly::TextureKey texture_key) {
|
||||||
|
|
||||||
Tracer::Tracer(Window &window)
|
Tracer::Tracer(Window &window)
|
||||||
: window_(window),
|
: window_(window),
|
||||||
rb_(*window.render_backend()),
|
rb_(window.render_backend()),
|
||||||
tile_renderer_(rb_, texcache_),
|
tile_renderer_(rb_, texcache_),
|
||||||
hide_params_() {
|
hide_params_() {
|
||||||
window_.AddListener(this);
|
window_.AddListener(this);
|
||||||
|
|
|
@ -8,16 +8,16 @@ using namespace re::hw;
|
||||||
using namespace re::hw::aica;
|
using namespace re::hw::aica;
|
||||||
using namespace re::hw::holly;
|
using namespace re::hw::holly;
|
||||||
|
|
||||||
AICA::AICA(Dreamcast *dc)
|
AICA::AICA(Dreamcast &dc)
|
||||||
: Device(*dc),
|
: Device(dc),
|
||||||
MemoryInterface(this),
|
MemoryInterface(this),
|
||||||
dc_(dc),
|
dc_(dc),
|
||||||
aica_regs_(nullptr),
|
aica_regs_(nullptr),
|
||||||
wave_ram_(nullptr) {}
|
wave_ram_(nullptr) {}
|
||||||
|
|
||||||
bool AICA::Init() {
|
bool AICA::Init() {
|
||||||
aica_regs_ = dc_->memory->TranslateVirtual(AICA_REG_START);
|
aica_regs_ = dc_.memory->TranslateVirtual(AICA_REG_START);
|
||||||
wave_ram_ = dc_->memory->TranslateVirtual(WAVE_RAM_START);
|
wave_ram_ = dc_.memory->TranslateVirtual(WAVE_RAM_START);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ void AICA::MapPhysicalMemory(Memory &memory, MemoryMap &memmap) {
|
||||||
// // if (MCIEB || MCIPD) {
|
// // if (MCIEB || MCIPD) {
|
||||||
// // LOG_INFO("0x%x & 0x%x", MCIEB, MCIPD);
|
// // LOG_INFO("0x%x & 0x%x", MCIEB, MCIPD);
|
||||||
// // }
|
// // }
|
||||||
// // dc_->holly()->RequestInterrupt(HOLLY_INTC_G2AICINT);
|
// // dc_.holly()->RequestInterrupt(HOLLY_INTC_G2AICINT);
|
||||||
|
|
||||||
// return cycles;
|
// return cycles;
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace aica {
|
||||||
|
|
||||||
class AICA : public Device, public MemoryInterface {
|
class AICA : public Device, public MemoryInterface {
|
||||||
public:
|
public:
|
||||||
AICA(Dreamcast *dc);
|
AICA(Dreamcast &dc);
|
||||||
|
|
||||||
bool Init() final;
|
bool Init() final;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class AICA : public Device, public MemoryInterface {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void WriteWave(uint32_t addr, T value);
|
void WriteWave(uint32_t addr, T value);
|
||||||
|
|
||||||
Dreamcast *dc_;
|
Dreamcast &dc_;
|
||||||
uint8_t *aica_regs_;
|
uint8_t *aica_regs_;
|
||||||
uint8_t *wave_ram_;
|
uint8_t *wave_ram_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,8 +13,8 @@ using namespace re::hw::sh4;
|
||||||
#define SWAP_24(fad) \
|
#define SWAP_24(fad) \
|
||||||
(((fad & 0xff) << 16) | (fad & 0x00ff00) | ((fad & 0xff0000) >> 16))
|
(((fad & 0xff) << 16) | (fad & 0x00ff00) | ((fad & 0xff0000) >> 16))
|
||||||
|
|
||||||
GDROM::GDROM(Dreamcast *dc)
|
GDROM::GDROM(Dreamcast &dc)
|
||||||
: Device(*dc),
|
: Device(dc),
|
||||||
dc_(dc),
|
dc_(dc),
|
||||||
memory_(nullptr),
|
memory_(nullptr),
|
||||||
holly_(nullptr),
|
holly_(nullptr),
|
||||||
|
@ -35,9 +35,9 @@ GDROM::GDROM(Dreamcast *dc)
|
||||||
GDROM::~GDROM() { delete[] dma_buffer_; }
|
GDROM::~GDROM() { delete[] dma_buffer_; }
|
||||||
|
|
||||||
bool GDROM::Init() {
|
bool GDROM::Init() {
|
||||||
memory_ = dc_->memory;
|
memory_ = dc_.memory;
|
||||||
holly_ = dc_->holly;
|
holly_ = dc_.holly;
|
||||||
holly_regs_ = dc_->holly_regs;
|
holly_regs_ = dc_.holly_regs;
|
||||||
|
|
||||||
SetDisc(nullptr);
|
SetDisc(nullptr);
|
||||||
|
|
||||||
|
@ -196,12 +196,12 @@ void GDROM::WriteRegister(uint32_t addr, T value) {
|
||||||
// SB_GDSTAR, SB_GDLEN, or SB_GDDIR register is overwritten while a DMA
|
// SB_GDSTAR, SB_GDLEN, or SB_GDDIR register is overwritten while a DMA
|
||||||
// operation is in progress, the new setting has no effect on the
|
// operation is in progress, the new setting has no effect on the
|
||||||
// current DMA operation.
|
// current DMA operation.
|
||||||
CHECK_EQ(dc_->SB_GDEN, 1); // dma enabled
|
CHECK_EQ(dc_.SB_GDEN, 1); // dma enabled
|
||||||
CHECK_EQ(dc_->SB_GDDIR, 1); // gd-rom -> system memory
|
CHECK_EQ(dc_.SB_GDDIR, 1); // gd-rom -> system memory
|
||||||
CHECK_EQ(dc_->SB_GDLEN, (uint32_t)dma_size_);
|
CHECK_EQ(dc_.SB_GDLEN, (uint32_t)dma_size_);
|
||||||
|
|
||||||
int transfer_size = dc_->SB_GDLEN;
|
int transfer_size = dc_.SB_GDLEN;
|
||||||
uint32_t start = dc_->SB_GDSTAR;
|
uint32_t start = dc_.SB_GDSTAR;
|
||||||
|
|
||||||
LOG_INFO("GD DMA START 0x%x -> 0x%x, 0x%x bytes", start,
|
LOG_INFO("GD DMA START 0x%x -> 0x%x, 0x%x bytes", start,
|
||||||
start + transfer_size, transfer_size);
|
start + transfer_size, transfer_size);
|
||||||
|
@ -209,9 +209,9 @@ void GDROM::WriteRegister(uint32_t addr, T value) {
|
||||||
memory_->Memcpy(start, dma_buffer_, transfer_size);
|
memory_->Memcpy(start, dma_buffer_, transfer_size);
|
||||||
|
|
||||||
// done
|
// done
|
||||||
dc_->SB_GDSTARD = start + transfer_size;
|
dc_.SB_GDSTARD = start + transfer_size;
|
||||||
dc_->SB_GDLEND = transfer_size;
|
dc_.SB_GDLEND = transfer_size;
|
||||||
dc_->SB_GDST = 0;
|
dc_.SB_GDST = 0;
|
||||||
holly_->RequestInterrupt(HOLLY_INTC_G1DEINT);
|
holly_->RequestInterrupt(HOLLY_INTC_G1DEINT);
|
||||||
|
|
||||||
// finish off CD_READ command
|
// finish off CD_READ command
|
||||||
|
|
|
@ -207,7 +207,7 @@ class GDROM : public Device {
|
||||||
friend class holly::Holly;
|
friend class holly::Holly;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GDROM(Dreamcast *dc);
|
GDROM(Dreamcast &dc);
|
||||||
~GDROM();
|
~GDROM();
|
||||||
|
|
||||||
bool Init() final;
|
bool Init() final;
|
||||||
|
@ -231,7 +231,7 @@ class GDROM : public Device {
|
||||||
int ReadSectors(int fad, SectorFormat format, DataMask mask, int num_sectors,
|
int ReadSectors(int fad, SectorFormat format, DataMask mask, int num_sectors,
|
||||||
uint8_t *dst);
|
uint8_t *dst);
|
||||||
|
|
||||||
Dreamcast *dc_;
|
Dreamcast &dc_;
|
||||||
Memory *memory_;
|
Memory *memory_;
|
||||||
holly::Holly *holly_;
|
holly::Holly *holly_;
|
||||||
Register *holly_regs_;
|
Register *holly_regs_;
|
||||||
|
|
|
@ -13,8 +13,8 @@ using namespace re::hw::maple;
|
||||||
using namespace re::hw::sh4;
|
using namespace re::hw::sh4;
|
||||||
using namespace re::sys;
|
using namespace re::sys;
|
||||||
|
|
||||||
Holly::Holly(Dreamcast *dc)
|
Holly::Holly(Dreamcast &dc)
|
||||||
: Device(*dc),
|
: Device(dc),
|
||||||
MemoryInterface(this),
|
MemoryInterface(this),
|
||||||
dc_(dc),
|
dc_(dc),
|
||||||
holly_regs_(nullptr),
|
holly_regs_(nullptr),
|
||||||
|
@ -23,10 +23,10 @@ Holly::Holly(Dreamcast *dc)
|
||||||
sh4_(nullptr) {}
|
sh4_(nullptr) {}
|
||||||
|
|
||||||
bool Holly::Init() {
|
bool Holly::Init() {
|
||||||
holly_regs_ = dc_->holly_regs;
|
holly_regs_ = dc_.holly_regs;
|
||||||
gdrom_ = dc_->gdrom;
|
gdrom_ = dc_.gdrom;
|
||||||
maple_ = dc_->maple;
|
maple_ = dc_.maple;
|
||||||
sh4_ = dc_->sh4;
|
sh4_ = dc_.sh4;
|
||||||
|
|
||||||
// initialize registers
|
// initialize registers
|
||||||
#define HOLLY_REG(addr, name, flags, default, type) \
|
#define HOLLY_REG(addr, name, flags, default, type) \
|
||||||
|
@ -43,20 +43,20 @@ void Holly::RequestInterrupt(HollyInterrupt intr) {
|
||||||
uint32_t irq = static_cast<uint32_t>(intr & ~HOLLY_INTC_MASK);
|
uint32_t irq = static_cast<uint32_t>(intr & ~HOLLY_INTC_MASK);
|
||||||
|
|
||||||
if (intr == HOLLY_INTC_PCVOINT) {
|
if (intr == HOLLY_INTC_PCVOINT) {
|
||||||
dc_->maple->VBlank();
|
dc_.maple->VBlank();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case HOLLY_INTC_NRM:
|
case HOLLY_INTC_NRM:
|
||||||
dc_->SB_ISTNRM |= irq;
|
dc_.SB_ISTNRM |= irq;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HOLLY_INTC_EXT:
|
case HOLLY_INTC_EXT:
|
||||||
dc_->SB_ISTEXT |= irq;
|
dc_.SB_ISTEXT |= irq;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HOLLY_INTC_ERR:
|
case HOLLY_INTC_ERR:
|
||||||
dc_->SB_ISTERR |= irq;
|
dc_.SB_ISTERR |= irq;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,15 +70,15 @@ void Holly::UnrequestInterrupt(HollyInterrupt intr) {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case HOLLY_INTC_NRM:
|
case HOLLY_INTC_NRM:
|
||||||
dc_->SB_ISTNRM &= ~irq;
|
dc_.SB_ISTNRM &= ~irq;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HOLLY_INTC_EXT:
|
case HOLLY_INTC_EXT:
|
||||||
dc_->SB_ISTEXT &= ~irq;
|
dc_.SB_ISTEXT &= ~irq;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HOLLY_INTC_ERR:
|
case HOLLY_INTC_ERR:
|
||||||
dc_->SB_ISTERR &= ~irq;
|
dc_.SB_ISTERR &= ~irq;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,10 +122,10 @@ T Holly::ReadRegister(uint32_t addr) {
|
||||||
// bits in SB_ISTEXT and SB_ISTERR, respectively, and writes to these two
|
// bits in SB_ISTEXT and SB_ISTERR, respectively, and writes to these two
|
||||||
// bits are ignored.
|
// bits are ignored.
|
||||||
uint32_t v = reg.value & 0x3fffffff;
|
uint32_t v = reg.value & 0x3fffffff;
|
||||||
if (dc_->SB_ISTEXT) {
|
if (dc_.SB_ISTEXT) {
|
||||||
v |= 0x40000000;
|
v |= 0x40000000;
|
||||||
}
|
}
|
||||||
if (dc_->SB_ISTERR) {
|
if (dc_.SB_ISTERR) {
|
||||||
v |= 0x80000000;
|
v |= 0x80000000;
|
||||||
}
|
}
|
||||||
return static_cast<T>(v);
|
return static_cast<T>(v);
|
||||||
|
@ -219,15 +219,15 @@ void Holly::WriteRegister(uint32_t addr, T value) {
|
||||||
|
|
||||||
// FIXME what are SB_LMMODE0 / SB_LMMODE1
|
// FIXME what are SB_LMMODE0 / SB_LMMODE1
|
||||||
void Holly::CH2DMATransfer() {
|
void Holly::CH2DMATransfer() {
|
||||||
sh4_->DDT(2, DDT_W, dc_->SB_C2DSTAT);
|
sh4_->DDT(2, DDT_W, dc_.SB_C2DSTAT);
|
||||||
|
|
||||||
dc_->SB_C2DLEN = 0;
|
dc_.SB_C2DLEN = 0;
|
||||||
dc_->SB_C2DST = 0;
|
dc_.SB_C2DST = 0;
|
||||||
RequestInterrupt(HOLLY_INTC_DTDE2INT);
|
RequestInterrupt(HOLLY_INTC_DTDE2INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Holly::SortDMATransfer() {
|
void Holly::SortDMATransfer() {
|
||||||
dc_->SB_SDST = 0;
|
dc_.SB_SDST = 0;
|
||||||
RequestInterrupt(HOLLY_INTC_DTDESINT);
|
RequestInterrupt(HOLLY_INTC_DTDESINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,9 +235,8 @@ void Holly::ForwardRequestInterrupts() {
|
||||||
// trigger the respective level-encoded interrupt on the sh4 interrupt
|
// trigger the respective level-encoded interrupt on the sh4 interrupt
|
||||||
// controller
|
// controller
|
||||||
{
|
{
|
||||||
if ((dc_->SB_ISTNRM & dc_->SB_IML6NRM) ||
|
if ((dc_.SB_ISTNRM & dc_.SB_IML6NRM) || (dc_.SB_ISTERR & dc_.SB_IML6ERR) ||
|
||||||
(dc_->SB_ISTERR & dc_->SB_IML6ERR) ||
|
(dc_.SB_ISTEXT & dc_.SB_IML6EXT)) {
|
||||||
(dc_->SB_ISTEXT & dc_->SB_IML6EXT)) {
|
|
||||||
sh4_->RequestInterrupt(SH4_INTC_IRL_9);
|
sh4_->RequestInterrupt(SH4_INTC_IRL_9);
|
||||||
} else {
|
} else {
|
||||||
sh4_->UnrequestInterrupt(SH4_INTC_IRL_9);
|
sh4_->UnrequestInterrupt(SH4_INTC_IRL_9);
|
||||||
|
@ -245,9 +244,8 @@ void Holly::ForwardRequestInterrupts() {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
if ((dc_->SB_ISTNRM & dc_->SB_IML4NRM) ||
|
if ((dc_.SB_ISTNRM & dc_.SB_IML4NRM) || (dc_.SB_ISTERR & dc_.SB_IML4ERR) ||
|
||||||
(dc_->SB_ISTERR & dc_->SB_IML4ERR) ||
|
(dc_.SB_ISTEXT & dc_.SB_IML4EXT)) {
|
||||||
(dc_->SB_ISTEXT & dc_->SB_IML4EXT)) {
|
|
||||||
sh4_->RequestInterrupt(SH4_INTC_IRL_11);
|
sh4_->RequestInterrupt(SH4_INTC_IRL_11);
|
||||||
} else {
|
} else {
|
||||||
sh4_->UnrequestInterrupt(SH4_INTC_IRL_11);
|
sh4_->UnrequestInterrupt(SH4_INTC_IRL_11);
|
||||||
|
@ -255,9 +253,8 @@ void Holly::ForwardRequestInterrupts() {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
if ((dc_->SB_ISTNRM & dc_->SB_IML2NRM) ||
|
if ((dc_.SB_ISTNRM & dc_.SB_IML2NRM) || (dc_.SB_ISTERR & dc_.SB_IML2ERR) ||
|
||||||
(dc_->SB_ISTERR & dc_->SB_IML2ERR) ||
|
(dc_.SB_ISTEXT & dc_.SB_IML2EXT)) {
|
||||||
(dc_->SB_ISTEXT & dc_->SB_IML2EXT)) {
|
|
||||||
sh4_->RequestInterrupt(SH4_INTC_IRL_13);
|
sh4_->RequestInterrupt(SH4_INTC_IRL_13);
|
||||||
} else {
|
} else {
|
||||||
sh4_->UnrequestInterrupt(SH4_INTC_IRL_13);
|
sh4_->UnrequestInterrupt(SH4_INTC_IRL_13);
|
||||||
|
|
|
@ -158,7 +158,7 @@ enum HollyInterrupt : uint64_t {
|
||||||
|
|
||||||
class Holly : public Device, public MemoryInterface {
|
class Holly : public Device, public MemoryInterface {
|
||||||
public:
|
public:
|
||||||
Holly(Dreamcast *dc);
|
Holly(Dreamcast &dc);
|
||||||
|
|
||||||
bool Init() final;
|
bool Init() final;
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ class Holly : public Device, public MemoryInterface {
|
||||||
void SortDMATransfer();
|
void SortDMATransfer();
|
||||||
void ForwardRequestInterrupts();
|
void ForwardRequestInterrupts();
|
||||||
|
|
||||||
Dreamcast *dc_;
|
Dreamcast &dc_;
|
||||||
Register *holly_regs_;
|
Register *holly_regs_;
|
||||||
gdrom::GDROM *gdrom_;
|
gdrom::GDROM *gdrom_;
|
||||||
maple::Maple *maple_;
|
maple::Maple *maple_;
|
||||||
|
|
|
@ -11,8 +11,8 @@ using namespace re::hw::holly;
|
||||||
using namespace re::hw::sh4;
|
using namespace re::hw::sh4;
|
||||||
using namespace re::renderer;
|
using namespace re::renderer;
|
||||||
|
|
||||||
PVR2::PVR2(Dreamcast *dc)
|
PVR2::PVR2(Dreamcast &dc)
|
||||||
: Device(*dc),
|
: Device(dc),
|
||||||
MemoryInterface(this),
|
MemoryInterface(this),
|
||||||
dc_(dc),
|
dc_(dc),
|
||||||
scheduler_(nullptr),
|
scheduler_(nullptr),
|
||||||
|
@ -26,12 +26,12 @@ PVR2::PVR2(Dreamcast *dc)
|
||||||
current_scanline_(0) {}
|
current_scanline_(0) {}
|
||||||
|
|
||||||
bool PVR2::Init() {
|
bool PVR2::Init() {
|
||||||
scheduler_ = dc_->scheduler;
|
scheduler_ = dc_.scheduler;
|
||||||
holly_ = dc_->holly;
|
holly_ = dc_.holly;
|
||||||
ta_ = dc_->ta;
|
ta_ = dc_.ta;
|
||||||
pvr_regs_ = dc_->pvr_regs;
|
pvr_regs_ = dc_.pvr_regs;
|
||||||
palette_ram_ = dc_->memory->TranslateVirtual(PVR_PALETTE_START);
|
palette_ram_ = dc_.memory->TranslateVirtual(PVR_PALETTE_START);
|
||||||
video_ram_ = dc_->memory->TranslateVirtual(PVR_VRAM32_START);
|
video_ram_ = dc_.memory->TranslateVirtual(PVR_VRAM32_START);
|
||||||
|
|
||||||
// initialize registers
|
// initialize registers
|
||||||
#define PVR_REG(addr, name, flags, default, type) \
|
#define PVR_REG(addr, name, flags, default, type) \
|
||||||
|
@ -101,7 +101,7 @@ void PVR2::WriteRegister(uint32_t addr, uint32_t value) {
|
||||||
|
|
||||||
case TA_LIST_INIT_OFFSET: {
|
case TA_LIST_INIT_OFFSET: {
|
||||||
if (value & 0x80000000) {
|
if (value & 0x80000000) {
|
||||||
ta_->InitContext(dc_->TA_ISP_BASE.base_address);
|
ta_->InitContext(dc_.TA_ISP_BASE.base_address);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ void PVR2::WriteRegister(uint32_t addr, uint32_t value) {
|
||||||
|
|
||||||
case STARTRENDER_OFFSET: {
|
case STARTRENDER_OFFSET: {
|
||||||
if (value) {
|
if (value) {
|
||||||
ta_->FinalizeContext(dc_->PARAM_BASE.base_address);
|
ta_->FinalizeContext(dc_.PARAM_BASE.base_address);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -160,22 +160,21 @@ void PVR2::WriteVRamInterleaved(uint32_t addr, T value) {
|
||||||
void PVR2::ReconfigureSPG() {
|
void PVR2::ReconfigureSPG() {
|
||||||
// get and scale pixel clock frequency
|
// get and scale pixel clock frequency
|
||||||
int pixel_clock = 13500000;
|
int pixel_clock = 13500000;
|
||||||
if (dc_->FB_R_CTRL.vclk_div) {
|
if (dc_.FB_R_CTRL.vclk_div) {
|
||||||
pixel_clock *= 2;
|
pixel_clock *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// hcount is number of pixel clock cycles per line - 1
|
// hcount is number of pixel clock cycles per line - 1
|
||||||
line_clock_ = pixel_clock / (dc_->SPG_LOAD.hcount + 1);
|
line_clock_ = pixel_clock / (dc_.SPG_LOAD.hcount + 1);
|
||||||
if (dc_->SPG_CONTROL.interlace) {
|
if (dc_.SPG_CONTROL.interlace) {
|
||||||
line_clock_ *= 2;
|
line_clock_ *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO(
|
LOG_INFO(
|
||||||
"ReconfigureSPG: pixel_clock %d, line_clock %d, vcount %d, hcount %d, "
|
"ReconfigureSPG: pixel_clock %d, line_clock %d, vcount %d, hcount %d, "
|
||||||
"interlace %d, vbstart %d, vbend %d",
|
"interlace %d, vbstart %d, vbend %d",
|
||||||
pixel_clock, line_clock_, dc_->SPG_LOAD.vcount, dc_->SPG_LOAD.hcount,
|
pixel_clock, line_clock_, dc_.SPG_LOAD.vcount, dc_.SPG_LOAD.hcount,
|
||||||
dc_->SPG_CONTROL.interlace, dc_->SPG_VBLANK.vbstart,
|
dc_.SPG_CONTROL.interlace, dc_.SPG_VBLANK.vbstart, dc_.SPG_VBLANK.vbend);
|
||||||
dc_->SPG_VBLANK.vbend);
|
|
||||||
|
|
||||||
if (line_timer_ != INVALID_TIMER) {
|
if (line_timer_ != INVALID_TIMER) {
|
||||||
scheduler_->CancelTimer(line_timer_);
|
scheduler_->CancelTimer(line_timer_);
|
||||||
|
@ -187,34 +186,34 @@ void PVR2::ReconfigureSPG() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PVR2::NextScanline() {
|
void PVR2::NextScanline() {
|
||||||
uint32_t num_scanlines = dc_->SPG_LOAD.vcount + 1;
|
uint32_t num_scanlines = dc_.SPG_LOAD.vcount + 1;
|
||||||
if (current_scanline_ > num_scanlines) {
|
if (current_scanline_ > num_scanlines) {
|
||||||
current_scanline_ = 0;
|
current_scanline_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// vblank in
|
// vblank in
|
||||||
if (current_scanline_ == dc_->SPG_VBLANK_INT.vblank_in_line_number) {
|
if (current_scanline_ == dc_.SPG_VBLANK_INT.vblank_in_line_number) {
|
||||||
holly_->RequestInterrupt(HOLLY_INTC_PCVIINT);
|
holly_->RequestInterrupt(HOLLY_INTC_PCVIINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// vblank out
|
// vblank out
|
||||||
if (current_scanline_ == dc_->SPG_VBLANK_INT.vblank_out_line_number) {
|
if (current_scanline_ == dc_.SPG_VBLANK_INT.vblank_out_line_number) {
|
||||||
holly_->RequestInterrupt(HOLLY_INTC_PCVOINT);
|
holly_->RequestInterrupt(HOLLY_INTC_PCVOINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// hblank in
|
// hblank in
|
||||||
holly_->RequestInterrupt(HOLLY_INTC_PCHIINT);
|
holly_->RequestInterrupt(HOLLY_INTC_PCHIINT);
|
||||||
|
|
||||||
// bool was_vsync = dc_->SPG_STATUS.vsync;
|
// bool was_vsync = dc_.SPG_STATUS.vsync;
|
||||||
dc_->SPG_STATUS.vsync = dc_->SPG_VBLANK.vbstart < dc_->SPG_VBLANK.vbend
|
dc_.SPG_STATUS.vsync = dc_.SPG_VBLANK.vbstart < dc_.SPG_VBLANK.vbend
|
||||||
? (current_scanline_ >= dc_->SPG_VBLANK.vbstart &&
|
? (current_scanline_ >= dc_.SPG_VBLANK.vbstart &&
|
||||||
current_scanline_ < dc_->SPG_VBLANK.vbend)
|
current_scanline_ < dc_.SPG_VBLANK.vbend)
|
||||||
: (current_scanline_ >= dc_->SPG_VBLANK.vbstart ||
|
: (current_scanline_ >= dc_.SPG_VBLANK.vbstart ||
|
||||||
current_scanline_ < dc_->SPG_VBLANK.vbend);
|
current_scanline_ < dc_.SPG_VBLANK.vbend);
|
||||||
dc_->SPG_STATUS.scanline = current_scanline_++;
|
dc_.SPG_STATUS.scanline = current_scanline_++;
|
||||||
|
|
||||||
// FIXME toggle SPG_STATUS.fieldnum on vblank?
|
// FIXME toggle SPG_STATUS.fieldnum on vblank?
|
||||||
// if (!was_vsync && dc_->SPG_STATUS.vsync) {
|
// if (!was_vsync && dc_.SPG_STATUS.vsync) {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// reschedule
|
// reschedule
|
||||||
|
|
|
@ -18,7 +18,7 @@ class TileAccelerator;
|
||||||
|
|
||||||
class PVR2 : public Device, public MemoryInterface {
|
class PVR2 : public Device, public MemoryInterface {
|
||||||
public:
|
public:
|
||||||
PVR2(Dreamcast *dc);
|
PVR2(Dreamcast &dc);
|
||||||
|
|
||||||
bool Init() final;
|
bool Init() final;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ class PVR2 : public Device, public MemoryInterface {
|
||||||
void ReconfigureSPG();
|
void ReconfigureSPG();
|
||||||
void NextScanline();
|
void NextScanline();
|
||||||
|
|
||||||
Dreamcast *dc_;
|
Dreamcast &dc_;
|
||||||
Scheduler *scheduler_;
|
Scheduler *scheduler_;
|
||||||
holly::Holly *holly_;
|
holly::Holly *holly_;
|
||||||
holly::TileAccelerator *ta_;
|
holly::TileAccelerator *ta_;
|
||||||
|
|
|
@ -206,13 +206,13 @@ int TileAccelerator::GetVertexType(const PCW &pcw) {
|
||||||
pcw.para_type * TA_NUM_LISTS + pcw.list_type];
|
pcw.para_type * TA_NUM_LISTS + pcw.list_type];
|
||||||
}
|
}
|
||||||
|
|
||||||
TileAccelerator::TileAccelerator(Dreamcast *dc, Backend *rb)
|
TileAccelerator::TileAccelerator(Dreamcast &dc, Backend &rb)
|
||||||
: Device(*dc),
|
: Device(dc),
|
||||||
MemoryInterface(this),
|
MemoryInterface(this),
|
||||||
WindowInterface(this),
|
WindowInterface(this),
|
||||||
dc_(dc),
|
dc_(dc),
|
||||||
rb_(rb),
|
rb_(rb),
|
||||||
tile_renderer_(*rb, *this),
|
tile_renderer_(rb, *this),
|
||||||
memory_(nullptr),
|
memory_(nullptr),
|
||||||
holly_(nullptr),
|
holly_(nullptr),
|
||||||
video_ram_(nullptr),
|
video_ram_(nullptr),
|
||||||
|
@ -227,9 +227,9 @@ TileAccelerator::TileAccelerator(Dreamcast *dc, Backend *rb)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TileAccelerator::Init() {
|
bool TileAccelerator::Init() {
|
||||||
memory_ = dc_->memory;
|
memory_ = dc_.memory;
|
||||||
holly_ = dc_->holly;
|
holly_ = dc_.holly;
|
||||||
video_ram_ = dc_->memory->TranslateVirtual(PVR_VRAM32_START);
|
video_ram_ = dc_.memory->TranslateVirtual(PVR_VRAM32_START);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ TextureHandle TileAccelerator::GetTexture(const TSP &tsp, const TCW &tcw,
|
||||||
uint32_t texture_addr = tcw.texture_addr << 3;
|
uint32_t texture_addr = tcw.texture_addr << 3;
|
||||||
|
|
||||||
// get the texture data
|
// get the texture data
|
||||||
uint8_t *video_ram = dc_->memory->TranslateVirtual(PVR_VRAM32_START);
|
uint8_t *video_ram = dc_.memory->TranslateVirtual(PVR_VRAM32_START);
|
||||||
uint8_t *texture = &video_ram[texture_addr];
|
uint8_t *texture = &video_ram[texture_addr];
|
||||||
int width = 8 << tsp.texture_u_size;
|
int width = 8 << tsp.texture_u_size;
|
||||||
int height = 8 << tsp.texture_v_size;
|
int height = 8 << tsp.texture_v_size;
|
||||||
|
@ -263,7 +263,7 @@ TextureHandle TileAccelerator::GetTexture(const TSP &tsp, const TCW &tcw,
|
||||||
int texture_size = (width * height * element_size_bits) >> 3;
|
int texture_size = (width * height * element_size_bits) >> 3;
|
||||||
|
|
||||||
// get the palette data
|
// get the palette data
|
||||||
uint8_t *palette_ram = dc_->memory->TranslateVirtual(PVR_PALETTE_START);
|
uint8_t *palette_ram = dc_.memory->TranslateVirtual(PVR_PALETTE_START);
|
||||||
uint8_t *palette = nullptr;
|
uint8_t *palette = nullptr;
|
||||||
uint32_t palette_addr = 0;
|
uint32_t palette_addr = 0;
|
||||||
int palette_size = 0;
|
int palette_size = 0;
|
||||||
|
@ -459,7 +459,7 @@ void TileAccelerator::OnPaint(bool show_main_menu) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileAccelerator::WritePolyFIFO(uint32_t addr, uint32_t value) {
|
void TileAccelerator::WritePolyFIFO(uint32_t addr, uint32_t value) {
|
||||||
WriteContext(dc_->TA_ISP_BASE.base_address, value);
|
WriteContext(dc_.TA_ISP_BASE.base_address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileAccelerator::WriteTextureFIFO(uint32_t addr, uint32_t value) {
|
void TileAccelerator::WriteTextureFIFO(uint32_t addr, uint32_t value) {
|
||||||
|
@ -517,7 +517,7 @@ void TileAccelerator::InvalidateTexture(TextureCacheMap::iterator it) {
|
||||||
RemoveAccessWatch(entry.palette_watch);
|
RemoveAccessWatch(entry.palette_watch);
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_->FreeTexture(entry.handle);
|
rb_.FreeTexture(entry.handle);
|
||||||
|
|
||||||
textures_.erase(it);
|
textures_.erase(it);
|
||||||
}
|
}
|
||||||
|
@ -552,23 +552,23 @@ void TileAccelerator::HandlePaletteWrite(const Exception &ex, void *data) {
|
||||||
|
|
||||||
void TileAccelerator::SaveRegisterState(TileContext *tctx) {
|
void TileAccelerator::SaveRegisterState(TileContext *tctx) {
|
||||||
// autosort
|
// autosort
|
||||||
if (!dc_->FPU_PARAM_CFG.region_header_type) {
|
if (!dc_.FPU_PARAM_CFG.region_header_type) {
|
||||||
tctx->autosort = !dc_->ISP_FEED_CFG.presort;
|
tctx->autosort = !dc_.ISP_FEED_CFG.presort;
|
||||||
} else {
|
} else {
|
||||||
uint32_t region_data = memory_->R32(PVR_VRAM64_START + dc_->REGION_BASE);
|
uint32_t region_data = memory_->R32(PVR_VRAM64_START + dc_.REGION_BASE);
|
||||||
tctx->autosort = !(region_data & 0x20000000);
|
tctx->autosort = !(region_data & 0x20000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// texture stride
|
// texture stride
|
||||||
tctx->stride = dc_->TEXT_CONTROL.stride * 32;
|
tctx->stride = dc_.TEXT_CONTROL.stride * 32;
|
||||||
|
|
||||||
// texture palette pixel format
|
// texture palette pixel format
|
||||||
tctx->pal_pxl_format = dc_->PAL_RAM_CTRL.pixel_format;
|
tctx->pal_pxl_format = dc_.PAL_RAM_CTRL.pixel_format;
|
||||||
|
|
||||||
// write out video width to help with unprojecting the screen space
|
// write out video width to help with unprojecting the screen space
|
||||||
// coordinates
|
// coordinates
|
||||||
if (dc_->SPG_CONTROL.interlace ||
|
if (dc_.SPG_CONTROL.interlace ||
|
||||||
(!dc_->SPG_CONTROL.NTSC && !dc_->SPG_CONTROL.PAL)) {
|
(!dc_.SPG_CONTROL.NTSC && !dc_.SPG_CONTROL.PAL)) {
|
||||||
// interlaced and VGA mode both render at full resolution
|
// interlaced and VGA mode both render at full resolution
|
||||||
tctx->video_width = 640;
|
tctx->video_width = 640;
|
||||||
tctx->video_height = 480;
|
tctx->video_height = 480;
|
||||||
|
@ -585,7 +585,7 @@ void TileAccelerator::SaveRegisterState(TileContext *tctx) {
|
||||||
// correct solution
|
// correct solution
|
||||||
uint32_t vram_offset =
|
uint32_t vram_offset =
|
||||||
PVR_VRAM64_START +
|
PVR_VRAM64_START +
|
||||||
((tctx->addr + dc_->ISP_BACKGND_T.tag_address * 4) & 0x7fffff);
|
((tctx->addr + dc_.ISP_BACKGND_T.tag_address * 4) & 0x7fffff);
|
||||||
|
|
||||||
// get surface parameters
|
// get surface parameters
|
||||||
tctx->bg_isp.full = memory_->R32(vram_offset);
|
tctx->bg_isp.full = memory_->R32(vram_offset);
|
||||||
|
@ -594,20 +594,20 @@ void TileAccelerator::SaveRegisterState(TileContext *tctx) {
|
||||||
vram_offset += 12;
|
vram_offset += 12;
|
||||||
|
|
||||||
// get the background depth
|
// get the background depth
|
||||||
tctx->bg_depth = re::load<float>(&dc_->ISP_BACKGND_D);
|
tctx->bg_depth = re::load<float>(&dc_.ISP_BACKGND_D);
|
||||||
|
|
||||||
// get the byte size for each vertex. normally, the byte size is
|
// get the byte size for each vertex. normally, the byte size is
|
||||||
// ISP_BACKGND_T.skip + 3, but if parameter selection volume mode is in
|
// ISP_BACKGND_T.skip + 3, but if parameter selection volume mode is in
|
||||||
// effect and the shadow bit is 1, then the byte size is
|
// effect and the shadow bit is 1, then the byte size is
|
||||||
// ISP_BACKGND_T.skip * 2 + 3
|
// ISP_BACKGND_T.skip * 2 + 3
|
||||||
int vertex_size = dc_->ISP_BACKGND_T.skip;
|
int vertex_size = dc_.ISP_BACKGND_T.skip;
|
||||||
if (!dc_->FPU_SHAD_SCALE.intensity_volume_mode && dc_->ISP_BACKGND_T.shadow) {
|
if (!dc_.FPU_SHAD_SCALE.intensity_volume_mode && dc_.ISP_BACKGND_T.shadow) {
|
||||||
vertex_size *= 2;
|
vertex_size *= 2;
|
||||||
}
|
}
|
||||||
vertex_size = (vertex_size + 3) * 4;
|
vertex_size = (vertex_size + 3) * 4;
|
||||||
|
|
||||||
// skip to the first vertex
|
// skip to the first vertex
|
||||||
vram_offset += dc_->ISP_BACKGND_T.tag_offset * vertex_size;
|
vram_offset += dc_.ISP_BACKGND_T.tag_offset * vertex_size;
|
||||||
|
|
||||||
// copy vertex data to context
|
// copy vertex data to context
|
||||||
for (int i = 0, bg_offset = 0; i < 3; i++) {
|
for (int i = 0, bg_offset = 0; i < 3; i++) {
|
||||||
|
|
|
@ -52,7 +52,7 @@ class TileAccelerator : public Device,
|
||||||
static int GetPolyType(const PCW &pcw);
|
static int GetPolyType(const PCW &pcw);
|
||||||
static int GetVertexType(const PCW &pcw);
|
static int GetVertexType(const PCW &pcw);
|
||||||
|
|
||||||
TileAccelerator(Dreamcast *dc, renderer::Backend *rb);
|
TileAccelerator(Dreamcast &dc, renderer::Backend &rb);
|
||||||
|
|
||||||
bool Init() final;
|
bool Init() final;
|
||||||
|
|
||||||
|
@ -86,8 +86,8 @@ class TileAccelerator : public Device,
|
||||||
|
|
||||||
void ToggleTracing();
|
void ToggleTracing();
|
||||||
|
|
||||||
Dreamcast *dc_;
|
Dreamcast &dc_;
|
||||||
renderer::Backend *rb_;
|
renderer::Backend &rb_;
|
||||||
TileRenderer tile_renderer_;
|
TileRenderer tile_renderer_;
|
||||||
Memory *memory_;
|
Memory *memory_;
|
||||||
Holly *holly_;
|
Holly *holly_;
|
||||||
|
|
|
@ -11,8 +11,8 @@ using namespace re::hw::maple;
|
||||||
using namespace re::hw::sh4;
|
using namespace re::hw::sh4;
|
||||||
using namespace re::ui;
|
using namespace re::ui;
|
||||||
|
|
||||||
Maple::Maple(Dreamcast *dc)
|
Maple::Maple(Dreamcast &dc)
|
||||||
: Device(*dc),
|
: Device(dc),
|
||||||
WindowInterface(this),
|
WindowInterface(this),
|
||||||
dc_(dc),
|
dc_(dc),
|
||||||
memory_(nullptr),
|
memory_(nullptr),
|
||||||
|
@ -24,9 +24,9 @@ Maple::Maple(Dreamcast *dc)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Maple::Init() {
|
bool Maple::Init() {
|
||||||
memory_ = dc_->memory;
|
memory_ = dc_.memory;
|
||||||
holly_ = dc_->holly;
|
holly_ = dc_.holly;
|
||||||
holly_regs_ = dc_->holly_regs;
|
holly_regs_ = dc_.holly_regs;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,8 @@ bool Maple::Init() {
|
||||||
// in synchronization with the V-BLANK signal. These methods are selected
|
// in synchronization with the V-BLANK signal. These methods are selected
|
||||||
// through the trigger selection register (SB_MDTSEL).
|
// through the trigger selection register (SB_MDTSEL).
|
||||||
void Maple::VBlank() {
|
void Maple::VBlank() {
|
||||||
uint32_t enabled = dc_->SB_MDEN;
|
uint32_t enabled = dc_.SB_MDEN;
|
||||||
uint32_t vblank_initiate = dc_->SB_MDTSEL;
|
uint32_t vblank_initiate = dc_.SB_MDTSEL;
|
||||||
|
|
||||||
if (enabled && vblank_initiate) {
|
if (enabled && vblank_initiate) {
|
||||||
StartDMA();
|
StartDMA();
|
||||||
|
@ -89,7 +89,7 @@ void Maple::WriteRegister(uint32_t addr, T value) {
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case SB_MDST_OFFSET: {
|
case SB_MDST_OFFSET: {
|
||||||
uint32_t enabled = dc_->SB_MDEN;
|
uint32_t enabled = dc_.SB_MDEN;
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
if (value) {
|
if (value) {
|
||||||
StartDMA();
|
StartDMA();
|
||||||
|
@ -102,7 +102,7 @@ void Maple::WriteRegister(uint32_t addr, T value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maple::StartDMA() {
|
void Maple::StartDMA() {
|
||||||
uint32_t start_addr = dc_->SB_MDSTAR;
|
uint32_t start_addr = dc_.SB_MDSTAR;
|
||||||
MapleTransferDesc desc;
|
MapleTransferDesc desc;
|
||||||
MapleFrame frame, res;
|
MapleFrame frame, res;
|
||||||
|
|
||||||
|
@ -135,6 +135,6 @@ void Maple::StartDMA() {
|
||||||
}
|
}
|
||||||
} while (!desc.last);
|
} while (!desc.last);
|
||||||
|
|
||||||
dc_->SB_MDST = 0;
|
dc_.SB_MDST = 0;
|
||||||
holly_->RequestInterrupt(HOLLY_INTC_MDEINT);
|
holly_->RequestInterrupt(HOLLY_INTC_MDEINT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ class Maple : public Device, public WindowInterface {
|
||||||
friend class holly::Holly;
|
friend class holly::Holly;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Maple(Dreamcast *dc);
|
Maple(Dreamcast &dc);
|
||||||
|
|
||||||
bool Init() final;
|
bool Init() final;
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ class Maple : public Device, public WindowInterface {
|
||||||
bool HandleFrame(const MapleFrame &frame, MapleFrame &res);
|
bool HandleFrame(const MapleFrame &frame, MapleFrame &res);
|
||||||
void StartDMA();
|
void StartDMA();
|
||||||
|
|
||||||
Dreamcast *dc_;
|
Dreamcast &dc_;
|
||||||
Memory *memory_;
|
Memory *memory_;
|
||||||
holly::Holly *holly_;
|
holly::Holly *holly_;
|
||||||
Register *holly_regs_;
|
Register *holly_regs_;
|
||||||
|
|
|
@ -29,8 +29,8 @@ enum {
|
||||||
SH4_CLOCK_FREQ = 200000000,
|
SH4_CLOCK_FREQ = 200000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
SH4::SH4(Dreamcast *dc)
|
SH4::SH4(Dreamcast &dc)
|
||||||
: Device(*dc),
|
: Device(dc),
|
||||||
DebugInterface(this),
|
DebugInterface(this),
|
||||||
ExecuteInterface(this),
|
ExecuteInterface(this),
|
||||||
MemoryInterface(this),
|
MemoryInterface(this),
|
||||||
|
@ -54,8 +54,8 @@ SH4::SH4(Dreamcast *dc)
|
||||||
SH4::~SH4() { delete code_cache_; }
|
SH4::~SH4() { delete code_cache_; }
|
||||||
|
|
||||||
bool SH4::Init() {
|
bool SH4::Init() {
|
||||||
memory_ = dc_->memory;
|
memory_ = dc_.memory;
|
||||||
scheduler_ = dc_->scheduler;
|
scheduler_ = dc_.scheduler;
|
||||||
|
|
||||||
code_cache_ = new SH4CodeCache(memory_, &ctx_, &SH4::CompilePC);
|
code_cache_ = new SH4CodeCache(memory_, &ctx_, &SH4::CompilePC);
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ void SH4::Step() {
|
||||||
block->run();
|
block->run();
|
||||||
|
|
||||||
// let the debugger know we've stopped
|
// let the debugger know we've stopped
|
||||||
dc_->debugger->Trap();
|
dc_.debugger->Trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SH4::AddBreakpoint(int type, uint32_t addr) {
|
void SH4::AddBreakpoint(int type, uint32_t addr) {
|
||||||
|
@ -367,7 +367,7 @@ void SH4::InvalidInstruction(SH4Context *ctx, uint64_t data) {
|
||||||
self->ctx_.num_cycles = 0;
|
self->ctx_.num_cycles = 0;
|
||||||
|
|
||||||
// let the debugger know execution has stopped
|
// let the debugger know execution has stopped
|
||||||
self->dc_->debugger->Trap();
|
self->dc_.debugger->Trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SH4::Prefetch(SH4Context *ctx, uint64_t data) {
|
void SH4::Prefetch(SH4Context *ctx, uint64_t data) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ class SH4 : public Device,
|
||||||
friend void RunSH4Test(const SH4Test &);
|
friend void RunSH4Test(const SH4Test &);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SH4(Dreamcast *dc);
|
SH4(Dreamcast &dc);
|
||||||
~SH4();
|
~SH4();
|
||||||
|
|
||||||
bool Init() final;
|
bool Init() final;
|
||||||
|
@ -108,7 +108,7 @@ class SH4 : public Device,
|
||||||
template <int N>
|
template <int N>
|
||||||
void ExpireTimer();
|
void ExpireTimer();
|
||||||
|
|
||||||
Dreamcast *dc_;
|
Dreamcast &dc_;
|
||||||
Memory *memory_;
|
Memory *memory_;
|
||||||
Scheduler *scheduler_;
|
Scheduler *scheduler_;
|
||||||
SH4CodeCache *code_cache_;
|
SH4CodeCache *code_cache_;
|
||||||
|
|
|
@ -39,12 +39,7 @@ bool InterpreterEmitter::Emit(ir::IRBuilder &builder, void *guest_ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign local offsets
|
// assign local offsets
|
||||||
*locals_size = 0;
|
*locals_size = builder.locals_size();
|
||||||
for (auto local : builder.locals()) {
|
|
||||||
int type_size = SizeForType(local->type());
|
|
||||||
local->set_offset(builder.AllocConstant(*locals_size));
|
|
||||||
*locals_size += type_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// translate each instruction
|
// translate each instruction
|
||||||
*instr = reinterpret_cast<IntInstr *>(codegen_);
|
*instr = reinterpret_cast<IntInstr *>(codegen_);
|
||||||
|
|
|
@ -115,15 +115,7 @@ BlockPointer X64Emitter::Emit(IRBuilder &builder, Memory &memory,
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::EmitProlog(IRBuilder &builder, int *out_stack_size) {
|
void X64Emitter::EmitProlog(IRBuilder &builder, int *out_stack_size) {
|
||||||
int stack_size = STACK_SIZE;
|
int stack_size = STACK_SIZE + builder.locals_size();
|
||||||
|
|
||||||
// align locals
|
|
||||||
for (auto local : builder.locals()) {
|
|
||||||
int type_size = SizeForType(local->type());
|
|
||||||
stack_size = re::align_up(stack_size, type_size);
|
|
||||||
local->set_offset(builder.AllocConstant(stack_size));
|
|
||||||
stack_size += type_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// stack must be 16 byte aligned
|
// stack must be 16 byte aligned
|
||||||
stack_size = re::align_up(stack_size, 16);
|
stack_size = re::align_up(stack_size, 16);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include "core/math.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "jit/ir/ir_builder.h"
|
#include "jit/ir/ir_builder.h"
|
||||||
#include "jit/ir/ir_writer.h"
|
#include "jit/ir/ir_writer.h"
|
||||||
|
@ -80,7 +81,8 @@ Instr::~Instr() {}
|
||||||
//
|
//
|
||||||
// IRBuilder
|
// IRBuilder
|
||||||
//
|
//
|
||||||
IRBuilder::IRBuilder() : arena_(1024), current_instr_(nullptr) {}
|
IRBuilder::IRBuilder()
|
||||||
|
: arena_(1024), current_instr_(nullptr), locals_size_(0) {}
|
||||||
|
|
||||||
void IRBuilder::Dump() const {
|
void IRBuilder::Dump() const {
|
||||||
IRWriter writer;
|
IRWriter writer;
|
||||||
|
@ -522,16 +524,17 @@ Value *IRBuilder::AllocConstant(double c) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *IRBuilder::AllocDynamic(ValueType type) {
|
|
||||||
Value *v = arena_.Alloc<Value>();
|
|
||||||
new (v) Value(type);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
Local *IRBuilder::AllocLocal(ValueType type) {
|
Local *IRBuilder::AllocLocal(ValueType type) {
|
||||||
|
// align local to natural size
|
||||||
|
int type_size = SizeForType(type);
|
||||||
|
locals_size_ = re::align_up(locals_size_, type_size);
|
||||||
|
|
||||||
Local *l = arena_.Alloc<Local>();
|
Local *l = arena_.Alloc<Local>();
|
||||||
new (l) Local(type, AllocConstant(0));
|
new (l) Local(type, AllocConstant(locals_size_));
|
||||||
locals_.Append(l);
|
locals_.Append(l);
|
||||||
|
|
||||||
|
locals_size_ += type_size;
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,14 +238,7 @@ class Local : public IntrusiveListNode<Local> {
|
||||||
Local(ValueType ty, Value *offset);
|
Local(ValueType ty, Value *offset);
|
||||||
|
|
||||||
ValueType type() const { return type_; }
|
ValueType type() const { return type_; }
|
||||||
ValueType type() { return type_; }
|
|
||||||
|
|
||||||
Value *offset() const { return offset_; }
|
Value *offset() const { return offset_; }
|
||||||
Value *offset() { return offset_; }
|
|
||||||
void set_offset(Value *offset) {
|
|
||||||
offset_->ReplaceRefsWith(offset);
|
|
||||||
offset_ = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ValueType type_;
|
ValueType type_;
|
||||||
|
@ -314,8 +307,7 @@ class IRBuilder {
|
||||||
const IntrusiveList<Instr> &instrs() const { return instrs_; }
|
const IntrusiveList<Instr> &instrs() const { return instrs_; }
|
||||||
IntrusiveList<Instr> &instrs() { return instrs_; }
|
IntrusiveList<Instr> &instrs() { return instrs_; }
|
||||||
|
|
||||||
const IntrusiveList<Local> &locals() const { return locals_; }
|
int locals_size() const { return locals_size_; }
|
||||||
IntrusiveList<Local> &locals() { return locals_; }
|
|
||||||
|
|
||||||
void Dump() const;
|
void Dump() const;
|
||||||
|
|
||||||
|
@ -398,7 +390,6 @@ class IRBuilder {
|
||||||
Value *AllocConstant(int64_t c);
|
Value *AllocConstant(int64_t c);
|
||||||
Value *AllocConstant(float c);
|
Value *AllocConstant(float c);
|
||||||
Value *AllocConstant(double c);
|
Value *AllocConstant(double c);
|
||||||
Value *AllocDynamic(ValueType type);
|
|
||||||
Local *AllocLocal(ValueType type);
|
Local *AllocLocal(ValueType type);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -408,8 +399,9 @@ class IRBuilder {
|
||||||
|
|
||||||
Arena arena_;
|
Arena arena_;
|
||||||
IntrusiveList<Instr> instrs_;
|
IntrusiveList<Instr> instrs_;
|
||||||
IntrusiveList<Local> locals_;
|
|
||||||
Instr *current_instr_;
|
Instr *current_instr_;
|
||||||
|
IntrusiveList<Local> locals_;
|
||||||
|
int locals_size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const Instr *Value::def() const {
|
inline const Instr *Value::def() const {
|
||||||
|
|
|
@ -193,11 +193,7 @@ bool IRReader::ParseValue(IRLexer &lex, IRBuilder &builder, Value **value) {
|
||||||
|
|
||||||
int slot = atoi(&ident[1]);
|
int slot = atoi(&ident[1]);
|
||||||
auto it = slots_.find(slot);
|
auto it = slots_.find(slot);
|
||||||
if (it == slots_.end()) {
|
CHECK_NE(it, slots_.end());
|
||||||
auto res =
|
|
||||||
slots_.insert(std::make_pair(slot, builder.AllocDynamic(type)));
|
|
||||||
it = res.first;
|
|
||||||
}
|
|
||||||
|
|
||||||
*value = it->second;
|
*value = it->second;
|
||||||
} else if (lex.tok() == TOK_INTEGER) {
|
} else if (lex.tok() == TOK_INTEGER) {
|
||||||
|
|
|
@ -17,7 +17,7 @@ ImGuiImpl::~ImGuiImpl() {
|
||||||
|
|
||||||
bool ImGuiImpl::Init() {
|
bool ImGuiImpl::Init() {
|
||||||
ImGuiIO &io = ImGui::GetIO();
|
ImGuiIO &io = ImGui::GetIO();
|
||||||
Backend *rb = window_.render_backend();
|
Backend &rb = window_.render_backend();
|
||||||
|
|
||||||
// don't really care if this is accurate
|
// don't really care if this is accurate
|
||||||
io.DeltaTime = 1.0f / 60.0f;
|
io.DeltaTime = 1.0f / 60.0f;
|
||||||
|
@ -57,7 +57,7 @@ bool ImGuiImpl::Init() {
|
||||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||||
|
|
||||||
TextureHandle handle =
|
TextureHandle handle =
|
||||||
rb->RegisterTexture(PXL_RGBA, FILTER_BILINEAR, WRAP_REPEAT, WRAP_REPEAT,
|
rb.RegisterTexture(PXL_RGBA, FILTER_BILINEAR, WRAP_REPEAT, WRAP_REPEAT,
|
||||||
false, width, height, pixels);
|
false, width, height, pixels);
|
||||||
|
|
||||||
io.Fonts->TexID = reinterpret_cast<void *>(static_cast<intptr_t>(handle));
|
io.Fonts->TexID = reinterpret_cast<void *>(static_cast<intptr_t>(handle));
|
||||||
|
@ -81,7 +81,7 @@ void ImGuiImpl::OnPrePaint() {
|
||||||
|
|
||||||
void ImGuiImpl::OnPostPaint() {
|
void ImGuiImpl::OnPostPaint() {
|
||||||
ImGuiIO &io = ImGui::GetIO();
|
ImGuiIO &io = ImGui::GetIO();
|
||||||
Backend *rb = window_.render_backend();
|
Backend &rb = window_.render_backend();
|
||||||
|
|
||||||
// if there are any focused items, enable text input
|
// if there are any focused items, enable text input
|
||||||
window_.EnableTextInput(ImGui::IsAnyItemActive());
|
window_.EnableTextInput(ImGui::IsAnyItemActive());
|
||||||
|
@ -93,7 +93,7 @@ void ImGuiImpl::OnPostPaint() {
|
||||||
// get the latest draw batches, and pass them off out the render backend
|
// get the latest draw batches, and pass them off out the render backend
|
||||||
ImDrawData *data = ImGui::GetDrawData();
|
ImDrawData *data = ImGui::GetDrawData();
|
||||||
|
|
||||||
rb->Begin2D();
|
rb.Begin2D();
|
||||||
|
|
||||||
for (int i = 0; i < data->CmdListsCount; ++i) {
|
for (int i = 0; i < data->CmdListsCount; ++i) {
|
||||||
const auto cmd_list = data->CmdLists[i];
|
const auto cmd_list = data->CmdLists[i];
|
||||||
|
@ -104,7 +104,7 @@ void ImGuiImpl::OnPostPaint() {
|
||||||
uint16_t *indices = cmd_list->IdxBuffer.Data;
|
uint16_t *indices = cmd_list->IdxBuffer.Data;
|
||||||
int num_indices = cmd_list->IdxBuffer.size();
|
int num_indices = cmd_list->IdxBuffer.size();
|
||||||
|
|
||||||
rb->BeginSurfaces2D(verts, num_verts, indices, num_indices);
|
rb.BeginSurfaces2D(verts, num_verts, indices, num_indices);
|
||||||
|
|
||||||
int index_offset = 0;
|
int index_offset = 0;
|
||||||
|
|
||||||
|
@ -125,15 +125,15 @@ void ImGuiImpl::OnPostPaint() {
|
||||||
surf.first_vert = index_offset;
|
surf.first_vert = index_offset;
|
||||||
surf.num_verts = cmd.ElemCount;
|
surf.num_verts = cmd.ElemCount;
|
||||||
|
|
||||||
rb->DrawSurface2D(surf);
|
rb.DrawSurface2D(surf);
|
||||||
|
|
||||||
index_offset += cmd.ElemCount;
|
index_offset += cmd.ElemCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
rb->EndSurfaces2D();
|
rb.EndSurfaces2D();
|
||||||
}
|
}
|
||||||
|
|
||||||
rb->End2D();
|
rb.End2D();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiImpl::OnTextInput(const char *text) {
|
void ImGuiImpl::OnTextInput(const char *text) {
|
||||||
|
|
|
@ -1598,7 +1598,7 @@ MicroProfileImpl::MicroProfileImpl(Window &window)
|
||||||
MicroProfileImpl::~MicroProfileImpl() { window_.RemoveListener(this); }
|
MicroProfileImpl::~MicroProfileImpl() { window_.RemoveListener(this); }
|
||||||
|
|
||||||
bool MicroProfileImpl::Init() {
|
bool MicroProfileImpl::Init() {
|
||||||
Backend *rb = window_.render_backend();
|
Backend &rb = window_.render_backend();
|
||||||
|
|
||||||
// register and enable gpu and runtime group by default
|
// register and enable gpu and runtime group by default
|
||||||
uint16_t gpu_group = MicroProfileGetGroup("gpu", MicroProfileTokenTypeCpu);
|
uint16_t gpu_group = MicroProfileGetGroup("gpu", MicroProfileTokenTypeCpu);
|
||||||
|
@ -1612,7 +1612,7 @@ bool MicroProfileImpl::Init() {
|
||||||
g_MicroProfile.nBars |= MP_DRAW_TIMERS | MP_DRAW_AVERAGE | MP_DRAW_CALL_COUNT;
|
g_MicroProfile.nBars |= MP_DRAW_TIMERS | MP_DRAW_AVERAGE | MP_DRAW_CALL_COUNT;
|
||||||
|
|
||||||
// register the font texture
|
// register the font texture
|
||||||
font_tex_ = rb->RegisterTexture(
|
font_tex_ = rb.RegisterTexture(
|
||||||
PXL_RGBA, FILTER_NEAREST, WRAP_CLAMP_TO_EDGE, WRAP_CLAMP_TO_EDGE, false,
|
PXL_RGBA, FILTER_NEAREST, WRAP_CLAMP_TO_EDGE, WRAP_CLAMP_TO_EDGE, false,
|
||||||
FONT_WIDTH, FONT_HEIGHT, reinterpret_cast<const uint8_t *>(s_font_data));
|
FONT_WIDTH, FONT_HEIGHT, reinterpret_cast<const uint8_t *>(s_font_data));
|
||||||
|
|
||||||
|
@ -1627,18 +1627,18 @@ void MicroProfileImpl::OnPostPaint() {
|
||||||
MicroProfileDraw(window_.width(), window_.height());
|
MicroProfileDraw(window_.width(), window_.height());
|
||||||
|
|
||||||
// render the surfaces
|
// render the surfaces
|
||||||
Backend *rb = window_.render_backend();
|
Backend &rb = window_.render_backend();
|
||||||
|
|
||||||
rb->Begin2D();
|
rb.Begin2D();
|
||||||
rb->BeginSurfaces2D(verts_, num_verts_, nullptr, 0);
|
rb.BeginSurfaces2D(verts_, num_verts_, nullptr, 0);
|
||||||
|
|
||||||
for (int i = 0; i < num_surfs_; i++) {
|
for (int i = 0; i < num_surfs_; i++) {
|
||||||
Surface2D &surf = surfs_[i];
|
Surface2D &surf = surfs_[i];
|
||||||
rb->DrawSurface2D(surf);
|
rb.DrawSurface2D(surf);
|
||||||
}
|
}
|
||||||
|
|
||||||
rb->EndSurfaces2D();
|
rb.EndSurfaces2D();
|
||||||
rb->End2D();
|
rb.End2D();
|
||||||
|
|
||||||
// reset surfaces
|
// reset surfaces
|
||||||
num_surfs_ = 0;
|
num_surfs_ = 0;
|
||||||
|
|
|
@ -20,7 +20,7 @@ enum {
|
||||||
class Window {
|
class Window {
|
||||||
public:
|
public:
|
||||||
SDL_Window *handle() { return window_; }
|
SDL_Window *handle() { return window_; }
|
||||||
renderer::Backend *render_backend() { return rb_; }
|
renderer::Backend &render_backend() { return *rb_; }
|
||||||
|
|
||||||
int width() { return width_; }
|
int width() { return width_; }
|
||||||
int height() { return height_; }
|
int height() { return height_; }
|
||||||
|
|
|
@ -155,7 +155,7 @@ void RunSH4Test(const SH4Test &test) {
|
||||||
// perhaps initialize the machine once, resetting the SH4 context between
|
// perhaps initialize the machine once, resetting the SH4 context between
|
||||||
// runs?
|
// runs?
|
||||||
std::unique_ptr<Dreamcast> dc(new Dreamcast());
|
std::unique_ptr<Dreamcast> dc(new Dreamcast());
|
||||||
std::unique_ptr<SH4> sh4(new SH4(dc.get()));
|
std::unique_ptr<SH4> sh4(new SH4(*dc.get()));
|
||||||
|
|
||||||
CHECK(dc->Init());
|
CHECK(dc->Init());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue