mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-12-22 15:29:58 +00:00
Refactor MachineBase and MachineFactory classes.
Adding new machines is much easier now. A significant amount of duplicated code has been reduced.
This commit is contained in:
parent
9971052a78
commit
c0078ce97d
@ -51,14 +51,17 @@ AMIC::AMIC() : MMIODevice()
|
|||||||
|
|
||||||
supports_types(HWCompType::MMIO_DEV | HWCompType::INT_CTRL);
|
supports_types(HWCompType::MMIO_DEV | HWCompType::INT_CTRL);
|
||||||
|
|
||||||
// register I/O devices
|
// connect internal SCSI controller
|
||||||
this->scsi = std::unique_ptr<Sc53C94> (new Sc53C94());
|
this->scsi = dynamic_cast<Sc53C94*>(gMachineObj->get_comp_by_name("Sc53C94"));
|
||||||
gMachineObj->add_subdevice("Curio_SCSI0", this->scsi.get());
|
|
||||||
|
|
||||||
this->escc = std::unique_ptr<EsccController> (new EsccController());
|
// connect serial HW
|
||||||
this->mace = std::unique_ptr<MaceController> (new MaceController(MACE_ID));
|
this->escc = dynamic_cast<EsccController*>(gMachineObj->get_comp_by_name("Escc"));
|
||||||
this->viacuda = std::unique_ptr<ViaCuda> (new ViaCuda());
|
|
||||||
gMachineObj->add_subdevice("ViaCuda", this->viacuda.get());
|
// connect Ethernet HW
|
||||||
|
this->mace = dynamic_cast<MaceController*>(gMachineObj->get_comp_by_name("Mace"));
|
||||||
|
|
||||||
|
// connect Cuda
|
||||||
|
this->viacuda = dynamic_cast<ViaCuda*>(gMachineObj->get_comp_by_name("ViaCuda"));
|
||||||
|
|
||||||
// initialize sound HW
|
// initialize sound HW
|
||||||
this->snd_out_dma = std::unique_ptr<AmicSndOutDma> (new AmicSndOutDma());
|
this->snd_out_dma = std::unique_ptr<AmicSndOutDma> (new AmicSndOutDma());
|
||||||
@ -69,11 +72,10 @@ AMIC::AMIC() : MMIODevice()
|
|||||||
this->disp_id = std::unique_ptr<DisplayID> (new DisplayID());
|
this->disp_id = std::unique_ptr<DisplayID> (new DisplayID());
|
||||||
this->def_vid = std::unique_ptr<PdmOnboardVideo> (new PdmOnboardVideo());
|
this->def_vid = std::unique_ptr<PdmOnboardVideo> (new PdmOnboardVideo());
|
||||||
|
|
||||||
// intialize floppy disk HW
|
// initialize floppy disk HW
|
||||||
this->swim3 = std::unique_ptr<Swim3::Swim3Ctrl> (new Swim3::Swim3Ctrl());
|
this->swim3 = dynamic_cast<Swim3::Swim3Ctrl*>(gMachineObj->get_comp_by_name("Swim3"));
|
||||||
this->floppy_dma = std::unique_ptr<AmicFloppyDma> (new AmicFloppyDma());
|
this->floppy_dma = std::unique_ptr<AmicFloppyDma> (new AmicFloppyDma());
|
||||||
this->swim3->set_dma_channel(this->floppy_dma.get());
|
this->swim3->set_dma_channel(this->floppy_dma.get());
|
||||||
gMachineObj->add_subdevice("SWIM3", this->swim3.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int AMIC::device_postinit()
|
int AMIC::device_postinit()
|
||||||
@ -530,7 +532,7 @@ DmaPullResult AmicFloppyDma::pull_data(uint32_t req_len, uint32_t *avail_len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static vector<string> Amic_Subdevices = {
|
static vector<string> Amic_Subdevices = {
|
||||||
"Swim3", "Escc"
|
"Sc53C94", "Escc", "Mace", "ViaCuda", "Swim3"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const DeviceDescription Amic_Descriptor = {
|
static const DeviceDescription Amic_Descriptor = {
|
||||||
|
@ -228,13 +228,14 @@ private:
|
|||||||
|
|
||||||
uint32_t pseudo_vbl_tid; // ID for the pseudo-VBL timer
|
uint32_t pseudo_vbl_tid; // ID for the pseudo-VBL timer
|
||||||
|
|
||||||
// AMIC subdevices instances
|
// AMIC subdevice instances
|
||||||
std::unique_ptr<Sc53C94> scsi;
|
Sc53C94* scsi;
|
||||||
std::unique_ptr<EsccController> escc;
|
EsccController* escc;
|
||||||
std::unique_ptr<MaceController> mace;
|
MaceController* mace;
|
||||||
std::unique_ptr<ViaCuda> viacuda;
|
ViaCuda* viacuda;
|
||||||
std::unique_ptr<AwacDevicePdm> awacs;
|
Swim3::Swim3Ctrl* swim3;
|
||||||
|
|
||||||
|
std::unique_ptr<AwacDevicePdm> awacs;
|
||||||
std::unique_ptr<AmicSndOutDma> snd_out_dma;
|
std::unique_ptr<AmicSndOutDma> snd_out_dma;
|
||||||
std::unique_ptr<AmicFloppyDma> floppy_dma;
|
std::unique_ptr<AmicFloppyDma> floppy_dma;
|
||||||
|
|
||||||
@ -242,8 +243,6 @@ private:
|
|||||||
std::unique_ptr<DisplayID> disp_id;
|
std::unique_ptr<DisplayID> disp_id;
|
||||||
std::unique_ptr<PdmOnboardVideo> def_vid;
|
std::unique_ptr<PdmOnboardVideo> def_vid;
|
||||||
uint8_t mon_id;
|
uint8_t mon_id;
|
||||||
|
|
||||||
std::unique_ptr<Swim3::Swim3Ctrl> swim3;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AMIC_H
|
#endif // AMIC_H
|
||||||
|
@ -48,13 +48,11 @@ GrandCentral::GrandCentral() : PCIDevice("mac-io/grandcentral"), InterruptCtrl()
|
|||||||
this->notify_bar_change(bar_num);
|
this->notify_bar_change(bar_num);
|
||||||
};
|
};
|
||||||
|
|
||||||
// construct subdevices
|
// NVRAM connection
|
||||||
this->mace = std::unique_ptr<MaceController> (new MaceController(MACE_ID));
|
this->nvram = dynamic_cast<NVram*>(gMachineObj->get_comp_by_name("NVRAM"));
|
||||||
this->viacuda = std::unique_ptr<ViaCuda> (new ViaCuda());
|
|
||||||
this->nvram = std::unique_ptr<NVram> (new NVram());
|
|
||||||
|
|
||||||
gMachineObj->add_subdevice("ViaCuda", this->viacuda.get());
|
// connect Cuda
|
||||||
gMachineObj->add_subdevice("NVRAM", this->nvram.get());
|
this->viacuda = dynamic_cast<ViaCuda*>(gMachineObj->get_comp_by_name("ViaCuda"));
|
||||||
|
|
||||||
// initialize sound chip and its DMA output channel, then wire them together
|
// initialize sound chip and its DMA output channel, then wire them together
|
||||||
this->awacs = std::unique_ptr<AwacsScreamer> (new AwacsScreamer());
|
this->awacs = std::unique_ptr<AwacsScreamer> (new AwacsScreamer());
|
||||||
@ -65,13 +63,17 @@ GrandCentral::GrandCentral() : PCIDevice("mac-io/grandcentral"), InterruptCtrl()
|
|||||||
std::bind(&AwacsScreamer::dma_end, this->awacs.get())
|
std::bind(&AwacsScreamer::dma_end, this->awacs.get())
|
||||||
);
|
);
|
||||||
|
|
||||||
this->escc = std::unique_ptr<EsccController> (new EsccController());
|
// connect serial HW
|
||||||
|
this->escc = dynamic_cast<EsccController*>(gMachineObj->get_comp_by_name("Escc"));
|
||||||
|
|
||||||
this->scsi_0 = std::unique_ptr<Sc53C94> (new Sc53C94());
|
// connect SCSI HW
|
||||||
gMachineObj->add_subdevice("Curio_SCSI0", this->scsi_0.get());
|
this->scsi_0 = dynamic_cast<Sc53C94*>(gMachineObj->get_comp_by_name("Sc53C94"));
|
||||||
|
|
||||||
this->swim3 = std::unique_ptr<Swim3::Swim3Ctrl> (new Swim3::Swim3Ctrl());
|
// connect Ethernet HW
|
||||||
gMachineObj->add_subdevice("SWIM3", this->swim3.get());
|
this->mace = dynamic_cast<MaceController*>(gMachineObj->get_comp_by_name("Mace"));
|
||||||
|
|
||||||
|
// connect floppy disk HW
|
||||||
|
this->swim3 = dynamic_cast<Swim3::Swim3Ctrl*>(gMachineObj->get_comp_by_name("Swim3"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrandCentral::notify_bar_change(int bar_num)
|
void GrandCentral::notify_bar_change(int bar_num)
|
||||||
@ -273,7 +275,7 @@ void GrandCentral::ack_dma_int(uint32_t irq_id, uint8_t irq_line_state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const vector<string> GCSubdevices = {
|
static const vector<string> GCSubdevices = {
|
||||||
"Swim3", "Escc"
|
"NVRAM", "ViaCuda", "Escc", "Sc53C94", "Mace", "Swim3"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const DeviceDescription GC_Descriptor = {
|
static const DeviceDescription GC_Descriptor = {
|
||||||
|
@ -60,11 +60,11 @@ HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow"), InterruptCtrl()
|
|||||||
this->notify_bar_change(bar_num);
|
this->notify_bar_change(bar_num);
|
||||||
};
|
};
|
||||||
|
|
||||||
this->nvram = std::unique_ptr<NVram> (new NVram());
|
// NVRAM connection
|
||||||
gMachineObj->add_subdevice("NVRAM", this->nvram.get());
|
this->nvram = dynamic_cast<NVram*>(gMachineObj->get_comp_by_name("NVRAM"));
|
||||||
|
|
||||||
this->viacuda = std::unique_ptr<ViaCuda> (new ViaCuda());
|
// connect Cuda
|
||||||
gMachineObj->add_subdevice("ViaCuda", this->viacuda.get());
|
this->viacuda = dynamic_cast<ViaCuda*>(gMachineObj->get_comp_by_name("ViaCuda"));
|
||||||
|
|
||||||
// initialize sound chip and its DMA output channel, then wire them together
|
// initialize sound chip and its DMA output channel, then wire them together
|
||||||
this->screamer = std::unique_ptr<AwacsScreamer> (new AwacsScreamer());
|
this->screamer = std::unique_ptr<AwacsScreamer> (new AwacsScreamer());
|
||||||
@ -75,12 +75,14 @@ HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow"), InterruptCtrl()
|
|||||||
std::bind(&AwacsScreamer::dma_end, this->screamer.get())
|
std::bind(&AwacsScreamer::dma_end, this->screamer.get())
|
||||||
);
|
);
|
||||||
|
|
||||||
this->mesh = std::unique_ptr<MESHController> (new MESHController(HeathrowMESHID));
|
// connect SCSI HW
|
||||||
this->escc = std::unique_ptr<EsccController> (new EsccController());
|
this->mesh = dynamic_cast<MESHController*>(gMachineObj->get_comp_by_name("Mesh"));
|
||||||
|
|
||||||
// intialize floppy disk HW
|
// connect serial HW
|
||||||
this->swim3 = std::unique_ptr<Swim3::Swim3Ctrl> (new Swim3::Swim3Ctrl());
|
this->escc = dynamic_cast<EsccController*>(gMachineObj->get_comp_by_name("Escc"));
|
||||||
gMachineObj->add_subdevice("SWIM3", this->swim3.get());
|
|
||||||
|
// connect floppy disk HW
|
||||||
|
this->swim3 = dynamic_cast<Swim3::Swim3Ctrl*>(gMachineObj->get_comp_by_name("Swim3"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeathrowIC::notify_bar_change(int bar_num)
|
void HeathrowIC::notify_bar_change(int bar_num)
|
||||||
@ -359,7 +361,7 @@ void HeathrowIC::ack_dma_int(uint32_t irq_id, uint8_t irq_line_state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const vector<string> Heathrow_Subdevices = {
|
static const vector<string> Heathrow_Subdevices = {
|
||||||
"Swim3", "Escc"
|
"NVRAM", "ViaCuda", "Mesh", "Escc", "Swim3"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const DeviceDescription Heathrow_Descriptor = {
|
static const DeviceDescription Heathrow_Descriptor = {
|
||||||
|
@ -116,14 +116,15 @@ private:
|
|||||||
|
|
||||||
uint32_t nvram_addr_hi;
|
uint32_t nvram_addr_hi;
|
||||||
|
|
||||||
// device cells
|
// subdevice objects
|
||||||
std::unique_ptr<MaceController> mace;
|
|
||||||
std::unique_ptr<AwacsScreamer> awacs; // AWACS audio codec instance
|
std::unique_ptr<AwacsScreamer> awacs; // AWACS audio codec instance
|
||||||
std::unique_ptr<ViaCuda> viacuda; // VIA cell with Cuda MCU attached to it
|
|
||||||
std::unique_ptr<NVram> nvram; // NVRAM module
|
NVram* nvram; // NVRAM module
|
||||||
std::unique_ptr<EsccController> escc; // ESCC serial controller
|
MaceController* mace;
|
||||||
std::unique_ptr<Sc53C94> scsi_0; // external SCSI
|
ViaCuda* viacuda; // VIA cell with Cuda MCU attached to it
|
||||||
std::unique_ptr<Swim3::Swim3Ctrl> swim3; // floppy disk controller
|
EsccController* escc; // ESCC serial controller
|
||||||
|
Sc53C94* scsi_0; // external SCSI
|
||||||
|
Swim3::Swim3Ctrl* swim3; // floppy disk controller
|
||||||
|
|
||||||
std::unique_ptr<DMAChannel> snd_out_dma;
|
std::unique_ptr<DMAChannel> snd_out_dma;
|
||||||
};
|
};
|
||||||
@ -194,15 +195,17 @@ private:
|
|||||||
uint32_t feat_ctrl = 0; // features control register
|
uint32_t feat_ctrl = 0; // features control register
|
||||||
uint32_t aux_ctrl = 0; // aux features control register
|
uint32_t aux_ctrl = 0; // aux features control register
|
||||||
|
|
||||||
/* device cells */
|
// subdevice objects
|
||||||
std::unique_ptr<ViaCuda> viacuda; // VIA cell with Cuda MCU attached to it
|
|
||||||
std::unique_ptr<NVram> nvram; // NVRAM cell
|
|
||||||
std::unique_ptr<AwacsScreamer> screamer; // Screamer audio codec instance
|
std::unique_ptr<AwacsScreamer> screamer; // Screamer audio codec instance
|
||||||
std::unique_ptr<MESHController> mesh; // MESH SCSI cell instance
|
//std::unique_ptr<MESHController> mesh; // MESH SCSI cell instance
|
||||||
std::unique_ptr<EsccController> escc; // ESCC serial controller
|
|
||||||
std::unique_ptr<Swim3::Swim3Ctrl> swim3; // floppy disk controller
|
|
||||||
|
|
||||||
std::unique_ptr<DMAChannel> snd_out_dma;
|
NVram* nvram; // NVRAM
|
||||||
|
ViaCuda* viacuda; // VIA cell with Cuda MCU attached to it
|
||||||
|
MESHController* mesh; // MESH SCSI cell instance
|
||||||
|
EsccController* escc; // ESCC serial controller
|
||||||
|
Swim3::Swim3Ctrl* swim3; // floppy disk controller
|
||||||
|
|
||||||
|
std::unique_ptr<DMAChannel> snd_out_dma;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* MACIO_H */
|
#endif /* MACIO_H */
|
||||||
|
@ -22,6 +22,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
#include <core/timermanager.h>
|
#include <core/timermanager.h>
|
||||||
#include <devices/common/hwcomponent.h>
|
#include <devices/common/hwcomponent.h>
|
||||||
#include <devices/common/pci/pcidevice.h>
|
#include <devices/common/pci/pcidevice.h>
|
||||||
|
#include <devices/deviceregistry.h>
|
||||||
#include <devices/video/atirage.h>
|
#include <devices/video/atirage.h>
|
||||||
#include <devices/video/displayid.h>
|
#include <devices/video/displayid.h>
|
||||||
#include <endianswap.h>
|
#include <endianswap.h>
|
||||||
@ -89,14 +90,14 @@ static const std::map<uint16_t, std::string> mach64_reg_names = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
ATIRage::ATIRage(uint16_t dev_id, uint32_t vmem_size_mb)
|
ATIRage::ATIRage(uint16_t dev_id)
|
||||||
: PCIDevice("ati-rage"), VideoCtrlBase(1024, 768)
|
: PCIDevice("ati-rage"), VideoCtrlBase(1024, 768)
|
||||||
{
|
{
|
||||||
uint8_t asic_id;
|
uint8_t asic_id;
|
||||||
|
|
||||||
supports_types(HWCompType::MMIO_DEV | HWCompType::PCI_DEV);
|
supports_types(HWCompType::MMIO_DEV | HWCompType::PCI_DEV);
|
||||||
|
|
||||||
this->vram_size = vmem_size_mb << 20; // convert MBs to bytes
|
this->vram_size = GET_INT_PROP("gfxmem_size") << 20; // convert MBs to bytes
|
||||||
|
|
||||||
/* allocate video RAM */
|
/* allocate video RAM */
|
||||||
this->vram_ptr = std::unique_ptr<uint8_t[]> (new uint8_t[this->vram_size]);
|
this->vram_ptr = std::unique_ptr<uint8_t[]> (new uint8_t[this->vram_size]);
|
||||||
@ -590,3 +591,21 @@ void ATIRage::draw_hw_cursor(uint8_t *dst_buf, int dst_pitch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const PropMap AtiRage_Properties = {
|
||||||
|
{"gfxmem_size",
|
||||||
|
new IntProperty( 2, vector<uint32_t>({2, 4, 6}))},
|
||||||
|
{"mon_id",
|
||||||
|
new StrProperty("")},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const DeviceDescription AtiRageGT_Descriptor = {
|
||||||
|
ATIRage::create_gt, {}, AtiRage_Properties
|
||||||
|
};
|
||||||
|
|
||||||
|
static const DeviceDescription AtiRagePro_Descriptor = {
|
||||||
|
ATIRage::create_pro, {}, AtiRage_Properties
|
||||||
|
};
|
||||||
|
|
||||||
|
REGISTER_DEVICE(AtiRageGT, AtiRageGT_Descriptor);
|
||||||
|
REGISTER_DEVICE(AtiRagePro, AtiRagePro_Descriptor);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
Copyright (C) 2018-21 divingkatae and maximum
|
Copyright (C) 2018-22 divingkatae and maximum
|
||||||
(theweirdo) spatium
|
(theweirdo) spatium
|
||||||
|
|
||||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
@ -44,9 +44,17 @@ enum {
|
|||||||
|
|
||||||
class ATIRage : public PCIDevice, public VideoCtrlBase {
|
class ATIRage : public PCIDevice, public VideoCtrlBase {
|
||||||
public:
|
public:
|
||||||
ATIRage(uint16_t dev_id, uint32_t vmem_size_mb);
|
ATIRage(uint16_t dev_id);
|
||||||
~ATIRage() = default;
|
~ATIRage() = default;
|
||||||
|
|
||||||
|
static std::unique_ptr<HWComponent> create_gt() {
|
||||||
|
return std::unique_ptr<ATIRage>(new ATIRage(ATI_RAGE_GT_DEV_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<HWComponent> create_pro() {
|
||||||
|
return std::unique_ptr<ATIRage>(new ATIRage(ATI_RAGE_PRO_DEV_ID));
|
||||||
|
}
|
||||||
|
|
||||||
/* MMIODevice methods */
|
/* MMIODevice methods */
|
||||||
uint32_t read(uint32_t reg_start, uint32_t offset, int size);
|
uint32_t read(uint32_t reg_start, uint32_t offset, int size);
|
||||||
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size);
|
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size);
|
||||||
@ -91,4 +99,5 @@ private:
|
|||||||
|
|
||||||
int comp_index; /* color component index for DAC palette access */
|
int comp_index; /* color component index for DAC palette access */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ATI_RAGE_H */
|
#endif /* ATI_RAGE_H */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
Copyright (C) 2018-21 divingkatae and maximum
|
Copyright (C) 2018-22 divingkatae and maximum
|
||||||
(theweirdo) spatium
|
(theweirdo) spatium
|
||||||
|
|
||||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
@ -33,59 +33,28 @@ MachineBase::MachineBase(std::string name) {
|
|||||||
this->name = name;
|
this->name = name;
|
||||||
|
|
||||||
/* initialize internal maps */
|
/* initialize internal maps */
|
||||||
this->comp_map.clear();
|
this->device_map.clear();
|
||||||
this->subdev_map.clear();
|
|
||||||
this->aliases.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MachineBase::~MachineBase() {
|
MachineBase::~MachineBase() {
|
||||||
for (auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
|
this->device_map.clear();
|
||||||
delete it->second;
|
|
||||||
}
|
|
||||||
this->comp_map.clear();
|
|
||||||
this->aliases.clear();
|
|
||||||
this->subdev_map.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MachineBase::add_component(std::string name, HWComponent* dev_obj) {
|
void MachineBase::add_device(std::string name, std::unique_ptr<HWComponent> dev_obj) {
|
||||||
if (this->comp_map.count(name)) {
|
if (this->device_map.count(name)) {
|
||||||
LOG_F(ERROR, "Component %s already exists!", name.c_str());
|
LOG_F(ERROR, "Device %s already exists!", name.c_str());
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->comp_map[name] = dev_obj;
|
this->device_map[name] = std::move(dev_obj);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MachineBase::add_subdevice(std::string name, HWComponent* dev_obj) {
|
|
||||||
if (this->subdev_map.count(name)) {
|
|
||||||
LOG_F(ERROR, "Subdevice %s already exists!", name.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->subdev_map[name] = dev_obj;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MachineBase::add_alias(std::string name, std::string alias) {
|
|
||||||
this->aliases[alias] = name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HWComponent* MachineBase::get_comp_by_name(std::string name) {
|
HWComponent* MachineBase::get_comp_by_name(std::string name) {
|
||||||
if (this->aliases.count(name)) {
|
if (this->device_map.count(name)) {
|
||||||
name = this->aliases[name];
|
return this->device_map[name].get();
|
||||||
}
|
|
||||||
|
|
||||||
if (this->comp_map.count(name)) {
|
|
||||||
return this->comp_map[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->subdev_map.count(name)) {
|
|
||||||
return this->subdev_map[name];
|
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
LOG_F(WARNING, "Component name %s not found!", name.c_str());
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,19 +62,7 @@ HWComponent* MachineBase::get_comp_by_type(HWCompType type) {
|
|||||||
std::string comp_name;
|
std::string comp_name;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
for (auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
|
for (auto it = this->device_map.begin(); it != this->device_map.end(); it++) {
|
||||||
if (it->second->supports_type(type)) {
|
|
||||||
comp_name = it->first;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
return this->get_comp_by_name(comp_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto it = this->subdev_map.begin(); it != this->subdev_map.end(); it++) {
|
|
||||||
if (it->second->supports_type(type)) {
|
if (it->second->supports_type(type)) {
|
||||||
comp_name = it->first;
|
comp_name = it->first;
|
||||||
found = true;
|
found = true;
|
||||||
@ -116,19 +73,14 @@ HWComponent* MachineBase::get_comp_by_type(HWCompType type) {
|
|||||||
if (found) {
|
if (found) {
|
||||||
return this->get_comp_by_name(comp_name);
|
return this->get_comp_by_name(comp_name);
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
LOG_F(WARNING, "No component of type %lu was found!", type);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachineBase::postinit_devices()
|
int MachineBase::postinit_devices()
|
||||||
{
|
{
|
||||||
for (auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
|
for (auto it = this->device_map.begin(); it != this->device_map.end(); it++) {
|
||||||
if (it->second->device_postinit()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto it = this->subdev_map.begin(); it != this->subdev_map.end(); it++) {
|
|
||||||
if (it->second->device_postinit()) {
|
if (it->second->device_postinit()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
Copyright (C) 2018-21 divingkatae and maximum
|
Copyright (C) 2018-22 divingkatae and maximum
|
||||||
(theweirdo) spatium
|
(theweirdo) spatium
|
||||||
|
|
||||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
@ -38,18 +38,14 @@ public:
|
|||||||
MachineBase(std::string name);
|
MachineBase(std::string name);
|
||||||
~MachineBase();
|
~MachineBase();
|
||||||
|
|
||||||
bool add_component(std::string name, HWComponent* dev_obj);
|
void add_device(std::string name, std::unique_ptr<HWComponent> dev_obj);
|
||||||
bool add_subdevice(std::string name, HWComponent* dev_obj);
|
|
||||||
void add_alias(std::string name, std::string alias);
|
|
||||||
HWComponent* get_comp_by_name(std::string name);
|
HWComponent* get_comp_by_name(std::string name);
|
||||||
HWComponent* get_comp_by_type(HWCompType type);
|
HWComponent* get_comp_by_type(HWCompType type);
|
||||||
int postinit_devices();
|
int postinit_devices();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string name;
|
std::string name;
|
||||||
std::map<std::string, HWComponent*> comp_map;
|
std::map<std::string, std::unique_ptr<HWComponent>> device_map;
|
||||||
std::map<std::string, HWComponent*> subdev_map;
|
|
||||||
std::map<std::string, std::string> aliases;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::unique_ptr<MachineBase> gMachineObj;
|
extern std::unique_ptr<MachineBase> gMachineObj;
|
||||||
|
@ -26,48 +26,24 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
#include <devices/common/scsi/scsi.h>
|
#include <devices/common/scsi/scsi.h>
|
||||||
#include <devices/ioctrl/macio.h>
|
#include <devices/ioctrl/macio.h>
|
||||||
#include <devices/memctrl/platinum.h>
|
#include <devices/memctrl/platinum.h>
|
||||||
#include <devices/video/atimach64gx.h>
|
|
||||||
#include <loguru.hpp>
|
#include <loguru.hpp>
|
||||||
#include <machines/machinebase.h>
|
#include <machines/machinebase.h>
|
||||||
|
#include <machines/machinefactory.h>
|
||||||
#include <machines/machineproperties.h>
|
#include <machines/machineproperties.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
int create_catalyst(std::string& id)
|
int initialize_catalyst(std::string& id)
|
||||||
{
|
{
|
||||||
PlatinumCtrl* platinum_obj;
|
PlatinumCtrl* platinum_obj;
|
||||||
|
|
||||||
if (gMachineObj) {
|
|
||||||
LOG_F(ERROR, "Global machine object not empty!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_F(INFO, "Initializing the Catalyst hardware...");
|
|
||||||
|
|
||||||
// initialize the global machine object
|
|
||||||
gMachineObj.reset(new MachineBase("Catalyst"));
|
|
||||||
|
|
||||||
// add memory controller
|
|
||||||
gMachineObj->add_component("Platinum", new PlatinumCtrl());
|
|
||||||
|
|
||||||
// add the ARBus-to-PCI bridge
|
|
||||||
gMachineObj->add_component("Bandit1", new Bandit(1, "Bandit-PCI1"));
|
|
||||||
|
|
||||||
PCIHost *pci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("Bandit1"));
|
PCIHost *pci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("Bandit1"));
|
||||||
|
|
||||||
// start the sound server
|
|
||||||
gMachineObj->add_component("SoundServer", new SoundServer());
|
|
||||||
|
|
||||||
// add the GrandCentral I/O controller
|
// add the GrandCentral I/O controller
|
||||||
gMachineObj->add_component("GrandCentral", new GrandCentral());
|
|
||||||
pci_host->pci_register_device(
|
pci_host->pci_register_device(
|
||||||
32, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("GrandCentral")));
|
32, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("GrandCentral")));
|
||||||
|
|
||||||
// HACK: attach temporary ATI Mach64 video card
|
|
||||||
//gMachineObj->add_component("AtiMach64", new AtiMach64Gx);
|
|
||||||
//pci_host->pci_register_device(
|
|
||||||
// 4, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("AtiMach64")));
|
|
||||||
|
|
||||||
// get (raw) pointer to the memory controller
|
// get (raw) pointer to the memory controller
|
||||||
platinum_obj = dynamic_cast<PlatinumCtrl*>(gMachineObj->get_comp_by_name("Platinum"));
|
platinum_obj = dynamic_cast<PlatinumCtrl*>(gMachineObj->get_comp_by_name("Platinum"));
|
||||||
|
|
||||||
@ -84,18 +60,39 @@ int create_catalyst(std::string& id)
|
|||||||
platinum_obj->map_phys_ram();
|
platinum_obj->map_phys_ram();
|
||||||
|
|
||||||
// add single SCSI bus
|
// add single SCSI bus
|
||||||
gMachineObj->add_component("SCSI0", new ScsiBus);
|
gMachineObj->add_device("SCSI0", std::unique_ptr<ScsiBus>(new ScsiBus()));
|
||||||
|
|
||||||
// init virtual CPU and request MPC601
|
// init virtual CPU and request MPC601
|
||||||
ppc_cpu_init(platinum_obj, PPC_VER::MPC601, 7833600ULL);
|
ppc_cpu_init(platinum_obj, PPC_VER::MPC601, 7833600ULL);
|
||||||
|
|
||||||
// post-initialize all devices
|
|
||||||
if (gMachineObj->postinit_devices()) {
|
|
||||||
LOG_F(ERROR, "Could not post-initialize devices!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_F(INFO, "Initialization complete.\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const PropMap pm7200_settings = {
|
||||||
|
{"rambank1_size",
|
||||||
|
new IntProperty(16, vector<uint32_t>({4, 8, 16, 32, 64, 128}))},
|
||||||
|
{"rambank2_size",
|
||||||
|
new IntProperty( 0, vector<uint32_t>({0, 4, 8, 16, 32, 64, 128}))},
|
||||||
|
{"rambank3_size",
|
||||||
|
new IntProperty( 0, vector<uint32_t>({0, 4, 8, 16, 32, 64, 128}))},
|
||||||
|
{"rambank4_size",
|
||||||
|
new IntProperty( 0, vector<uint32_t>({0, 4, 8, 16, 32, 64, 128}))},
|
||||||
|
{"gfxmem_size",
|
||||||
|
new IntProperty( 1, vector<uint32_t>({1, 2, 4}))},
|
||||||
|
{"mon_id",
|
||||||
|
new StrProperty("HiRes12-14in")},
|
||||||
|
};
|
||||||
|
|
||||||
|
static vector<string> pm7200_devices = {
|
||||||
|
"Platinum", "Bandit1", "GrandCentral"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const MachineDescription pm7200_descriptor = {
|
||||||
|
.name = "pm7200",
|
||||||
|
.description = "Power Macintosh 7200",
|
||||||
|
.devices = pm7200_devices,
|
||||||
|
.settings = pm7200_settings,
|
||||||
|
.init_func = &initialize_catalyst
|
||||||
|
};
|
||||||
|
|
||||||
|
REGISTER_MACHINE(pm7200, pm7200_descriptor);
|
||||||
|
@ -24,8 +24,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
Author: Max Poliakovski
|
Author: Max Poliakovski
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <devices/deviceregistry.h>
|
||||||
#include <devices/memctrl/memctrlbase.h>
|
#include <devices/memctrl/memctrlbase.h>
|
||||||
|
#include <devices/sound/soundserver.h>
|
||||||
#include <loguru.hpp>
|
#include <loguru.hpp>
|
||||||
|
#include <machines/machinebase.h>
|
||||||
#include <machines/machinefactory.h>
|
#include <machines/machinefactory.h>
|
||||||
#include <machines/machineproperties.h>
|
#include <machines/machineproperties.h>
|
||||||
#include <memaccess.h>
|
#include <memaccess.h>
|
||||||
@ -56,7 +59,7 @@ static const map<uint32_t, std::tuple<string, const char*>> rom_identity = {
|
|||||||
//{"Come", "PowerBook 2400"}, // Comet
|
//{"Come", "PowerBook 2400"}, // Comet
|
||||||
{0x436F7264, {"pm5200", "Power Mac 5200/6200 series"}}, // Cordyceps
|
{0x436F7264, {"pm5200", "Power Mac 5200/6200 series"}}, // Cordyceps
|
||||||
{0x47617A65, {"pm6500", "Power Mac 6500"}}, // Gazelle
|
{0x47617A65, {"pm6500", "Power Mac 6500"}}, // Gazelle
|
||||||
{0x476F7373, {"pmg3", "Power Mac G3 Beige"}}, // Gossamer
|
{0x476F7373, {"pmg3dt", "Power Mac G3 Beige"}}, // Gossamer
|
||||||
{0x47525820, {"pbg3", "PowerBook G3 Wallstreet"}},
|
{0x47525820, {"pbg3", "PowerBook G3 Wallstreet"}},
|
||||||
//{"Hoop", "PowerBook 3400"}, // Hooper
|
//{"Hoop", "PowerBook 3400"}, // Hooper
|
||||||
{0x50425820, {"pb-preg3", "PowerBook Pre-G3"}},
|
{0x50425820, {"pb-preg3", "PowerBook Pre-G3"}},
|
||||||
@ -67,67 +70,6 @@ static const map<uint32_t, std::tuple<string, const char*>> rom_identity = {
|
|||||||
{0x5A616E7A, {"pm4400", "Power Mac 4400/7220"}}, // Zanzibar
|
{0x5A616E7A, {"pm4400", "Power Mac 4400/7220"}}, // Zanzibar
|
||||||
};
|
};
|
||||||
|
|
||||||
static const vector<string> WriteToggle = {"ON", "on", "OFF", "off"};
|
|
||||||
|
|
||||||
static const vector<string> CharIoBackends = {"null", "stdio"};
|
|
||||||
|
|
||||||
static const PropMap CatalystSettings = {
|
|
||||||
{"rambank1_size",
|
|
||||||
new IntProperty(16, vector<uint32_t>({4, 8, 16, 32, 64, 128}))},
|
|
||||||
{"rambank2_size",
|
|
||||||
new IntProperty( 0, vector<uint32_t>({0, 4, 8, 16, 32, 64, 128}))},
|
|
||||||
{"rambank3_size",
|
|
||||||
new IntProperty( 0, vector<uint32_t>({0, 4, 8, 16, 32, 64, 128}))},
|
|
||||||
{"rambank4_size",
|
|
||||||
new IntProperty( 0, vector<uint32_t>({0, 4, 8, 16, 32, 64, 128}))},
|
|
||||||
{"gfxmem_size",
|
|
||||||
new IntProperty( 1, vector<uint32_t>({1, 2, 4}))},
|
|
||||||
{"mon_id",
|
|
||||||
new StrProperty("HiRes12-14in")},
|
|
||||||
{"fdd_img",
|
|
||||||
new StrProperty("")},
|
|
||||||
{"serial_backend", new StrProperty("null", CharIoBackends)},
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PropMap GossamerSettings = {
|
|
||||||
{"rambank1_size",
|
|
||||||
new IntProperty(256, vector<uint32_t>({8, 16, 32, 64, 128, 256}))},
|
|
||||||
{"rambank2_size",
|
|
||||||
new IntProperty( 0, vector<uint32_t>({0, 8, 16, 32, 64, 128, 256}))},
|
|
||||||
{"rambank3_size",
|
|
||||||
new IntProperty( 0, vector<uint32_t>({0, 8, 16, 32, 64, 128, 256}))},
|
|
||||||
{"gfxmem_size",
|
|
||||||
new IntProperty( 2, vector<uint32_t>({2, 4, 6}))},
|
|
||||||
{"mon_id",
|
|
||||||
new StrProperty("")},
|
|
||||||
{"fdd_img",
|
|
||||||
new StrProperty("")},
|
|
||||||
{"fdd_wr_prot", new StrProperty("OFF", WriteToggle)},
|
|
||||||
{"serial_backend", new StrProperty("null", CharIoBackends)},
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Monitors supported by the PDM on-board video. */
|
|
||||||
/* see displayid.cpp for the full list of supported monitor IDs. */
|
|
||||||
static const vector<string> PDMBuiltinMonitorIDs = {
|
|
||||||
"PortraitGS", "MacRGB12in", "MacRGB15in", "HiRes12-14in", "VGA-SVGA",
|
|
||||||
"MacRGB16in", "Multiscan15in", "Multiscan17in", "Multiscan20in",
|
|
||||||
"NotConnected"
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PropMap PDMSettings = {
|
|
||||||
{"rambank1_size",
|
|
||||||
new IntProperty(0, vector<uint32_t>({0, 8, 16, 32, 64, 128}))},
|
|
||||||
{"rambank2_size",
|
|
||||||
new IntProperty(0, vector<uint32_t>({0, 8, 16, 32, 64, 128}))},
|
|
||||||
{"mon_id",
|
|
||||||
new StrProperty("HiRes12-14in", PDMBuiltinMonitorIDs)},
|
|
||||||
{"fdd_img",
|
|
||||||
new StrProperty("")},
|
|
||||||
{"fdd_wr_prot",
|
|
||||||
new StrProperty("OFF", WriteToggle)},
|
|
||||||
{"serial_backend", new StrProperty("null", CharIoBackends)},
|
|
||||||
};
|
|
||||||
|
|
||||||
static const map<string, string> PropHelp = {
|
static const map<string, string> PropHelp = {
|
||||||
{"rambank1_size", "specifies RAM bank 1 size in MB"},
|
{"rambank1_size", "specifies RAM bank 1 size in MB"},
|
||||||
{"rambank2_size", "specifies RAM bank 2 size in MB"},
|
{"rambank2_size", "specifies RAM bank 2 size in MB"},
|
||||||
@ -135,18 +77,182 @@ static const map<string, string> PropHelp = {
|
|||||||
{"rambank4_size", "specifies RAM bank 4 size in MB"},
|
{"rambank4_size", "specifies RAM bank 4 size in MB"},
|
||||||
{"gfxmem_size", "specifies video memory size in MB"},
|
{"gfxmem_size", "specifies video memory size in MB"},
|
||||||
{"fdd_img", "specifies path to floppy disk image"},
|
{"fdd_img", "specifies path to floppy disk image"},
|
||||||
{"fdd_wr_prot", "toggles floppy disks write protection"},
|
{"fdd_wr_prot", "toggles floppy disk's write protection"},
|
||||||
{"mon_id", "specifies which monitor to emulate"},
|
{"mon_id", "specifies which monitor to emulate"},
|
||||||
{"serial_backend", "specifies the backend for the serial port"},
|
{"serial_backend", "specifies the backend for the serial port"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const map<string, tuple<PropMap, function<int(string&)>, string>> machines = {
|
bool MachineFactory::add(const string& machine_id, MachineDescription desc)
|
||||||
{"pm6100", {PDMSettings, create_pdm, "PowerMacintosh 6100"}},
|
{
|
||||||
{"pm7200", {CatalystSettings, create_catalyst, "PowerMacintosh 7200"}},
|
if (get_registry().find(machine_id) != get_registry().end()) {
|
||||||
{"pmg3", {GossamerSettings, create_gossamer, "Power Macintosh G3 (Beige)"}},
|
return false;
|
||||||
};
|
}
|
||||||
|
|
||||||
string machine_name_from_rom(string& rom_filepath) {
|
get_registry()[machine_id] = desc;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachineFactory::list_machines()
|
||||||
|
{
|
||||||
|
cout << endl << "Supported machines:" << endl << endl;
|
||||||
|
|
||||||
|
for (auto& m : get_registry()) {
|
||||||
|
cout << setw(13) << m.first << "\t\t" << m.second.description << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachineFactory::create_device(string& dev_name, DeviceDescription& dev)
|
||||||
|
{
|
||||||
|
for (auto& subdev_name : dev.subdev_list) {
|
||||||
|
create_device(subdev_name, DeviceRegistry::get_descriptor(subdev_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
gMachineObj->add_device(dev_name, dev.m_create_func());
|
||||||
|
}
|
||||||
|
|
||||||
|
int MachineFactory::create(string& mach_id)
|
||||||
|
{
|
||||||
|
auto it = get_registry().find(mach_id);
|
||||||
|
if (it == get_registry().end()) {
|
||||||
|
LOG_F(ERROR, "Unknown machine id %s", mach_id.c_str());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_F(INFO, "Initializing %s hardware...", it->second.description.c_str());
|
||||||
|
|
||||||
|
// initialize global machine object
|
||||||
|
gMachineObj.reset(new MachineBase(it->second.name));
|
||||||
|
|
||||||
|
// create and register sound server
|
||||||
|
gMachineObj->add_device("SoundServer", std::unique_ptr<SoundServer>(new SoundServer()));
|
||||||
|
|
||||||
|
// recursively create device objects
|
||||||
|
for (auto& dev_name : it->second.devices) {
|
||||||
|
create_device(dev_name, DeviceRegistry::get_descriptor(dev_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it->second.init_func(mach_id)) {
|
||||||
|
LOG_F(ERROR, "Machine initialization function failed!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// post-initialize all devices
|
||||||
|
if (gMachineObj->postinit_devices()) {
|
||||||
|
LOG_F(ERROR, "Could not post-initialize devices!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_F(INFO, "Initialization completed.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachineFactory::list_properties()
|
||||||
|
{
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
for (auto& mach : get_registry()) {
|
||||||
|
cout << mach.second.description << " supported properties:" << endl << endl;
|
||||||
|
|
||||||
|
print_settings(mach.second.settings);
|
||||||
|
|
||||||
|
for (auto& d : mach.second.devices) {
|
||||||
|
list_device_settings(DeviceRegistry::get_descriptor(d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachineFactory::list_device_settings(DeviceDescription& dev)
|
||||||
|
{
|
||||||
|
for (auto& d : dev.subdev_list) {
|
||||||
|
list_device_settings(DeviceRegistry::get_descriptor(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
print_settings(dev.properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachineFactory::print_settings(PropMap& prop_map)
|
||||||
|
{
|
||||||
|
for (auto& p : prop_map) {
|
||||||
|
cout << setw(13) << p.first << "\t\t" << PropHelp.at(p.first)
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
cout << setw(13) << "\t\t\t" "Valid values: ";
|
||||||
|
|
||||||
|
switch(p.second->get_type()) {
|
||||||
|
case PROP_TYPE_INTEGER:
|
||||||
|
cout << dynamic_cast<IntProperty*>(p.second)->get_valid_values_as_str()
|
||||||
|
<< endl;
|
||||||
|
break;
|
||||||
|
case PROP_TYPE_STRING:
|
||||||
|
cout << dynamic_cast<StrProperty*>(p.second)->get_valid_values_as_str()
|
||||||
|
<< endl;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachineFactory::get_device_settings(DeviceDescription& dev, map<string, string> &settings)
|
||||||
|
{
|
||||||
|
for (auto& d : dev.subdev_list) {
|
||||||
|
get_device_settings(DeviceRegistry::get_descriptor(d), settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& p : dev.properties) {
|
||||||
|
settings[p.first] = p.second->get_string();
|
||||||
|
|
||||||
|
// populate dynamic machine settings from presets
|
||||||
|
gMachineSettings[p.first] = unique_ptr<BasicProperty>(p.second->clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MachineFactory::get_machine_settings(const string& id, map<string, string> &settings)
|
||||||
|
{
|
||||||
|
auto it = get_registry().find(id);
|
||||||
|
if (it != get_registry().end()) {
|
||||||
|
auto props = it->second.settings;
|
||||||
|
|
||||||
|
gMachineSettings.clear();
|
||||||
|
|
||||||
|
for (auto& p : props) {
|
||||||
|
settings[p.first] = p.second->get_string();
|
||||||
|
|
||||||
|
// populate dynamic machine settings from presets
|
||||||
|
gMachineSettings[p.first] = unique_ptr<BasicProperty>(p.second->clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& dev : it->second.devices) {
|
||||||
|
get_device_settings(DeviceRegistry::get_descriptor(dev), settings);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_F(ERROR, "Unknown machine id %s", id.c_str());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachineFactory::set_machine_settings(map<string, string> &settings) {
|
||||||
|
for (auto& s : settings) {
|
||||||
|
gMachineSettings.at(s.first)->set_string(s.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print machine settings summary
|
||||||
|
cout << endl << "Machine settings summary: " << endl;
|
||||||
|
|
||||||
|
for (auto& p : gMachineSettings) {
|
||||||
|
cout << p.first << " : " << p.second->get_string() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string MachineFactory::machine_name_from_rom(string& rom_filepath) {
|
||||||
ifstream rom_file;
|
ifstream rom_file;
|
||||||
uint32_t file_size, config_info_offset, rom_id;
|
uint32_t file_size, config_info_offset, rom_id;
|
||||||
char rom_id_str[17];
|
char rom_id_str[17];
|
||||||
@ -202,96 +308,8 @@ bail_out:
|
|||||||
return machine_name;
|
return machine_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_machine_settings(string& id, map<string, string> &settings) {
|
|
||||||
try {
|
|
||||||
auto props = get<0>(machines.at(id));
|
|
||||||
|
|
||||||
gMachineSettings.clear();
|
|
||||||
|
|
||||||
for (auto& p : props) {
|
|
||||||
settings[p.first] = p.second->get_string();
|
|
||||||
|
|
||||||
/* populate dynamic machine settings from presets */
|
|
||||||
gMachineSettings[p.first] = unique_ptr<BasicProperty>(p.second->clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(out_of_range ex) {
|
|
||||||
LOG_F(ERROR, "Unknown machine id %s", id.c_str());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_machine_settings(map<string, string> &settings) {
|
|
||||||
for (auto& s : settings) {
|
|
||||||
gMachineSettings.at(s.first)->set_string(s.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* print machine settings summary */
|
|
||||||
cout << endl << "Machine settings summary: " << endl;
|
|
||||||
|
|
||||||
for (auto& p : gMachineSettings) {
|
|
||||||
cout << p.first << " : " << p.second->get_string() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void list_machines() {
|
|
||||||
cout << endl << "Supported machines:" << endl << endl;
|
|
||||||
|
|
||||||
for (auto& mach : machines) {
|
|
||||||
cout << setw(13) << mach.first << "\t\t" << get<2>(mach.second) << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void list_properties() {
|
|
||||||
cout << endl;
|
|
||||||
|
|
||||||
for (auto& mach : machines) {
|
|
||||||
cout << get<2>(mach.second) << " supported properties:" << endl << endl;
|
|
||||||
|
|
||||||
for (auto& p : get<0>(mach.second)) {
|
|
||||||
cout << setw(13) << p.first << "\t\t" << PropHelp.at(p.first)
|
|
||||||
<< endl;
|
|
||||||
|
|
||||||
cout << setw(13) << "\t\t\t" "Valid values: ";
|
|
||||||
|
|
||||||
switch(p.second->get_type()) {
|
|
||||||
case PROP_TYPE_INTEGER:
|
|
||||||
cout << dynamic_cast<IntProperty*>(p.second)->get_valid_values_as_str()
|
|
||||||
<< endl;
|
|
||||||
break;
|
|
||||||
case PROP_TYPE_STRING:
|
|
||||||
cout << dynamic_cast<StrProperty*>(p.second)->get_valid_values_as_str()
|
|
||||||
<< endl;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read ROM file content and transfer it to the dedicated ROM region */
|
/* Read ROM file content and transfer it to the dedicated ROM region */
|
||||||
void load_rom(std::ifstream& rom_file, uint32_t file_size) {
|
int MachineFactory::load_boot_rom(string& rom_filepath) {
|
||||||
unsigned char* sysrom_mem = new unsigned char[file_size];
|
|
||||||
|
|
||||||
rom_file.seekg(0, ios::beg);
|
|
||||||
rom_file.read((char*)sysrom_mem, file_size);
|
|
||||||
|
|
||||||
MemCtrlBase* mem_ctrl = dynamic_cast<MemCtrlBase*>(
|
|
||||||
gMachineObj->get_comp_by_type(HWCompType::MEM_CTRL));
|
|
||||||
|
|
||||||
mem_ctrl->set_data(0xFFC00000, sysrom_mem, file_size);
|
|
||||||
delete[] sysrom_mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read ROM file content and transfer it to the dedicated ROM region */
|
|
||||||
int load_boot_rom(string& rom_filepath) {
|
|
||||||
ifstream rom_file;
|
ifstream rom_file;
|
||||||
size_t file_size;
|
size_t file_size;
|
||||||
int result;
|
int result;
|
||||||
@ -336,17 +354,8 @@ int load_boot_rom(string& rom_filepath) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MachineFactory::create_machine_for_id(string& id, string& rom_filepath) {
|
||||||
int create_machine_for_id(string& id, string& rom_filepath) {
|
if (MachineFactory::create(id) < 0 || load_boot_rom(rom_filepath) < 0) {
|
||||||
try {
|
|
||||||
auto machine = machines.at(id);
|
|
||||||
|
|
||||||
/* build machine and load boot ROM */
|
|
||||||
if (get<1>(machine)(id) < 0 || load_boot_rom(rom_filepath) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} catch(out_of_range ex) {
|
|
||||||
LOG_F(ERROR, "Unknown machine id %s", id.c_str());
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
Copyright (C) 2018-21 divingkatae and maximum
|
Copyright (C) 2018-22 divingkatae and maximum
|
||||||
(theweirdo) spatium
|
(theweirdo) spatium
|
||||||
|
|
||||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
@ -27,24 +27,58 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
#ifndef MACHINE_FACTORY_H
|
#ifndef MACHINE_FACTORY_H
|
||||||
#define MACHINE_FACTORY_H
|
#define MACHINE_FACTORY_H
|
||||||
|
|
||||||
|
#include <devices/deviceregistry.h>
|
||||||
#include <machines/machinebase.h>
|
#include <machines/machinebase.h>
|
||||||
|
#include <machines/machineproperties.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
std::string machine_name_from_rom(std::string& rom_filepath);
|
struct MachineDescription {
|
||||||
|
string name;
|
||||||
|
string description;
|
||||||
|
vector<string> devices;
|
||||||
|
PropMap settings;
|
||||||
|
function<int(string&)> init_func;
|
||||||
|
};
|
||||||
|
|
||||||
int get_machine_settings(string& id, map<string, string> &settings);
|
class MachineFactory
|
||||||
void set_machine_settings(map<string, string> &settings);
|
{
|
||||||
int create_machine_for_id(string& id, string& rom_filepath);
|
public:
|
||||||
void list_machines(void);
|
MachineFactory() = delete;
|
||||||
void list_properties(void);
|
|
||||||
|
|
||||||
/* Machine-specific factory functions. */
|
static bool add(const string& machine_id, MachineDescription desc);
|
||||||
int create_catalyst(string& id);
|
|
||||||
int create_gossamer(string& id);
|
static string machine_name_from_rom(string& rom_filepath);
|
||||||
int create_pdm(string& id);
|
|
||||||
|
static int create(string& mach_id);
|
||||||
|
static int create_machine_for_id(string& id, string& rom_filepath);
|
||||||
|
|
||||||
|
static int get_machine_settings(const string& id, map<string, string> &settings);
|
||||||
|
static void set_machine_settings(map<string, string> &settings);
|
||||||
|
|
||||||
|
static void list_machines();
|
||||||
|
static void list_properties();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void create_device(string& dev_name, DeviceDescription& dev);
|
||||||
|
static void print_settings(PropMap& p);
|
||||||
|
static void list_device_settings(DeviceDescription& dev);
|
||||||
|
static void get_device_settings(DeviceDescription& dev, map<string, string> &settings);
|
||||||
|
static int load_boot_rom(string& rom_filepath);
|
||||||
|
|
||||||
|
static map<string, MachineDescription> & get_registry() {
|
||||||
|
static map<string, MachineDescription> machine_registry;
|
||||||
|
return machine_registry;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define REGISTER_MACHINE(mach_name, mach_desc) \
|
||||||
|
static bool mach_name ## _registered = MachineFactory::add(#mach_name, (mach_desc))
|
||||||
|
|
||||||
#endif /* MACHINE_FACTORY_H */
|
#endif /* MACHINE_FACTORY_H */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
Copyright (C) 2018-21 divingkatae and maximum
|
Copyright (C) 2018-22 divingkatae and maximum
|
||||||
(theweirdo) spatium
|
(theweirdo) spatium
|
||||||
|
|
||||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
@ -34,89 +34,86 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
#include <devices/video/atirage.h>
|
#include <devices/video/atirage.h>
|
||||||
#include <loguru.hpp>
|
#include <loguru.hpp>
|
||||||
#include <machines/machinebase.h>
|
#include <machines/machinebase.h>
|
||||||
|
#include <machines/machinefactory.h>
|
||||||
#include <machines/machineproperties.h>
|
#include <machines/machineproperties.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
static void setup_ram_slot(std::string name, int i2c_addr, int capacity_megs) {
|
static void setup_ram_slot(std::string name, int i2c_addr, int capacity_megs) {
|
||||||
if (!capacity_megs)
|
if (!capacity_megs)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gMachineObj->add_component(name, new SpdSdram168(i2c_addr));
|
gMachineObj->add_device(name, std::unique_ptr<SpdSdram168>(new SpdSdram168(i2c_addr)));
|
||||||
SpdSdram168* ram_dimm = dynamic_cast<SpdSdram168*>(gMachineObj->get_comp_by_name(name));
|
SpdSdram168* ram_dimm = dynamic_cast<SpdSdram168*>(gMachineObj->get_comp_by_name(name));
|
||||||
ram_dimm->set_capacity(capacity_megs);
|
ram_dimm->set_capacity(capacity_megs);
|
||||||
|
|
||||||
/* register RAM DIMM with the I2C bus */
|
// register RAM DIMM with the I2C bus
|
||||||
I2CBus* i2c_bus = dynamic_cast<I2CBus*>(gMachineObj->get_comp_by_type(HWCompType::I2C_HOST));
|
I2CBus* i2c_bus = dynamic_cast<I2CBus*>(gMachineObj->get_comp_by_type(HWCompType::I2C_HOST));
|
||||||
i2c_bus->register_device(i2c_addr, ram_dimm);
|
i2c_bus->register_device(i2c_addr, ram_dimm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int create_gossamer(std::string& id) {
|
int initialize_gossamer(std::string& id)
|
||||||
if (gMachineObj) {
|
{
|
||||||
LOG_F(ERROR, "Global machine object not empty!");
|
// get pointer to the memory controller/PCI host bridge object
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_F(INFO, "Initializing the Gossamer hardware...");
|
|
||||||
|
|
||||||
/* initialize the global machine object */
|
|
||||||
gMachineObj.reset(new MachineBase("Gossamer"));
|
|
||||||
|
|
||||||
/* register MPC106 aka Grackle as memory controller and PCI host */
|
|
||||||
gMachineObj->add_component("Grackle", new MPC106);
|
|
||||||
gMachineObj->add_alias("Grackle", "PCI_Host");
|
|
||||||
|
|
||||||
/* get raw pointer to MPC106 object */
|
|
||||||
MPC106* grackle_obj = dynamic_cast<MPC106*>(gMachineObj->get_comp_by_name("Grackle"));
|
MPC106* grackle_obj = dynamic_cast<MPC106*>(gMachineObj->get_comp_by_name("Grackle"));
|
||||||
|
|
||||||
/* add the machine ID register */
|
// add the machine ID register
|
||||||
gMachineObj->add_component("MachineID", new GossamerID(0xBF3D));
|
gMachineObj->add_device("MachineID", std::unique_ptr<GossamerID>(new GossamerID(0xBF3D)));
|
||||||
grackle_obj->add_mmio_region(
|
grackle_obj->add_mmio_region(
|
||||||
0xFF000004, 4096, dynamic_cast<MMIODevice*>(gMachineObj->get_comp_by_name("MachineID")));
|
0xFF000004, 4096, dynamic_cast<MMIODevice*>(gMachineObj->get_comp_by_name("MachineID")));
|
||||||
|
|
||||||
gMachineObj->add_component("SoundServer", new SoundServer());
|
// register the Heathrow I/O controller with the PCI host bridge
|
||||||
|
|
||||||
/* add the Heathrow I/O controller */
|
|
||||||
gMachineObj->add_component("Heathrow", new HeathrowIC);
|
|
||||||
grackle_obj->pci_register_device(
|
grackle_obj->pci_register_device(
|
||||||
16, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("Heathrow")));
|
16, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("Heathrow")));
|
||||||
|
|
||||||
/* allocate ROM region */
|
// allocate ROM region
|
||||||
if (!grackle_obj->add_rom_region(0xFFC00000, 0x400000)) {
|
if (!grackle_obj->add_rom_region(0xFFC00000, 0x400000)) {
|
||||||
LOG_F(ERROR, "Could not allocate ROM region!\n");
|
LOG_F(ERROR, "Could not allocate ROM region!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* configure RAM slots */
|
// configure RAM slots
|
||||||
setup_ram_slot("RAM_DIMM_1", 0x57, GET_INT_PROP("rambank1_size"));
|
setup_ram_slot("RAM_DIMM_1", 0x57, GET_INT_PROP("rambank1_size"));
|
||||||
setup_ram_slot("RAM_DIMM_2", 0x56, GET_INT_PROP("rambank2_size"));
|
setup_ram_slot("RAM_DIMM_2", 0x56, GET_INT_PROP("rambank2_size"));
|
||||||
setup_ram_slot("RAM_DIMM_3", 0x55, GET_INT_PROP("rambank3_size"));
|
setup_ram_slot("RAM_DIMM_3", 0x55, GET_INT_PROP("rambank3_size"));
|
||||||
|
|
||||||
/* register ATI 3D Rage Pro video card with the PCI host bridge */
|
// select built-in GPU name
|
||||||
gMachineObj->add_component("ATIRage",
|
std::string gpu_name = "AtiRageGT";
|
||||||
new ATIRage(ATI_RAGE_PRO_DEV_ID, GET_INT_PROP("gfxmem_size")));
|
if (id == "pmg3twr") {
|
||||||
|
gpu_name = "AtiRagePro";
|
||||||
|
}
|
||||||
|
|
||||||
|
// register built-in ATI Rage GPU with the PCI host bridge
|
||||||
grackle_obj->pci_register_device(
|
grackle_obj->pci_register_device(
|
||||||
18, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("ATIRage")));
|
18, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name(gpu_name)));
|
||||||
|
|
||||||
/* Init virtual CPU and request MPC750 CPU aka G3 */
|
// initialize virtual CPU and request MPC750 CPU aka G3
|
||||||
ppc_cpu_init(grackle_obj, PPC_VER::MPC750, 16705000ULL);
|
ppc_cpu_init(grackle_obj, PPC_VER::MPC750, 16705000ULL);
|
||||||
|
|
||||||
// post-initialize all devices
|
|
||||||
if (gMachineObj->postinit_devices()) {
|
|
||||||
LOG_F(ERROR, "Could not post-initialize devices!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for a floppy image to be inserted into the virtual superdrive */
|
|
||||||
std::string fdd_path = GET_STR_PROP("fdd_img");
|
|
||||||
std::string fd_write_prot = GET_STR_PROP("fdd_wr_prot");
|
|
||||||
if (!fdd_path.empty()) {
|
|
||||||
open_floppy_image(fdd_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_F(INFO, "Initialization complete.\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const PropMap gossamer_settings = {
|
||||||
|
{"rambank1_size",
|
||||||
|
new IntProperty(256, vector<uint32_t>({8, 16, 32, 64, 128, 256}))},
|
||||||
|
{"rambank2_size",
|
||||||
|
new IntProperty( 0, vector<uint32_t>({0, 8, 16, 32, 64, 128, 256}))},
|
||||||
|
{"rambank3_size",
|
||||||
|
new IntProperty( 0, vector<uint32_t>({0, 8, 16, 32, 64, 128, 256}))},
|
||||||
|
};
|
||||||
|
|
||||||
|
static vector<string> pmg3_devices = {
|
||||||
|
"Grackle", "Heathrow", "AtiRageGT"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const MachineDescription pmg3dt_descriptor = {
|
||||||
|
.name = "pmg3",
|
||||||
|
.description = "Power Macintosh G3 (Beige) Desktop",
|
||||||
|
.devices = pmg3_devices,
|
||||||
|
.settings = gossamer_settings,
|
||||||
|
.init_func = &initialize_gossamer
|
||||||
|
};
|
||||||
|
|
||||||
|
REGISTER_MACHINE(pmg3dt, pmg3dt_descriptor);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
Copyright (C) 2018-21 divingkatae and maximum
|
Copyright (C) 2018-22 divingkatae and maximum
|
||||||
(theweirdo) spatium
|
(theweirdo) spatium
|
||||||
|
|
||||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
@ -27,97 +27,94 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
#include <cpu/ppc/ppcemu.h>
|
#include <cpu/ppc/ppcemu.h>
|
||||||
#include <devices/common/machineid.h>
|
#include <devices/common/machineid.h>
|
||||||
#include <devices/common/scsi/scsi.h>
|
#include <devices/common/scsi/scsi.h>
|
||||||
#include <devices/floppy/superdrive.h>
|
|
||||||
#include <devices/ioctrl/amic.h>
|
|
||||||
#include <devices/memctrl/hmc.h>
|
#include <devices/memctrl/hmc.h>
|
||||||
#include <devices/sound/soundserver.h>
|
|
||||||
#include <loguru.hpp>
|
#include <loguru.hpp>
|
||||||
#include <machines/machinebase.h>
|
#include <machines/machinebase.h>
|
||||||
|
#include <machines/machinefactory.h>
|
||||||
#include <machines/machineproperties.h>
|
#include <machines/machineproperties.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
int create_pdm(std::string& id) {
|
int initialize_pdm(std::string& id)
|
||||||
if (gMachineObj) {
|
{
|
||||||
LOG_F(ERROR, "PDM Factory: global machine object not empty!");
|
uint16_t machine_id;
|
||||||
|
|
||||||
|
// get raw pointer to HMC object
|
||||||
|
HMC* hmc_obj = dynamic_cast<HMC*>(gMachineObj->get_comp_by_name("HMC"));
|
||||||
|
|
||||||
|
if (id == "pm6100") {
|
||||||
|
machine_id = 0x3010;
|
||||||
|
} else if (id == "pm7100") {
|
||||||
|
machine_id = 0x3012;
|
||||||
|
} else if (id == "pm8100") {
|
||||||
|
machine_id = 0x3013;
|
||||||
|
} else {
|
||||||
|
LOG_F(ERROR, "Unknown machine ID: %s!", id.c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_F(INFO, "Initializing the %s hardware...", id.c_str());
|
// create machine ID register
|
||||||
|
//gMachineObj->add_component("MachineID", new NubusMacID(machine_id));
|
||||||
/* initialize the global machine object */
|
gMachineObj->add_device("MachineID", std::unique_ptr<NubusMacID>(new NubusMacID(machine_id)));
|
||||||
gMachineObj.reset(new MachineBase("PDM"));
|
|
||||||
|
|
||||||
/* register HMC memory controller */
|
|
||||||
gMachineObj->add_component("HMC", new HMC);
|
|
||||||
|
|
||||||
/* start the sound server. */
|
|
||||||
gMachineObj->add_component("SoundServer", new SoundServer());
|
|
||||||
|
|
||||||
/* register AMIC I/O controller */
|
|
||||||
gMachineObj->add_component("AMIC", new AMIC);
|
|
||||||
|
|
||||||
/* get raw pointer to HMC object */
|
|
||||||
HMC* hmc_obj = dynamic_cast<HMC*>(gMachineObj->get_comp_by_name("HMC"));
|
|
||||||
|
|
||||||
// allocate machine ID register and tell we're running PowerMac 6100
|
|
||||||
// TODO: add a possibility to select another machine
|
|
||||||
// to be used with the same ROM
|
|
||||||
gMachineObj->add_component("MachineID", new NubusMacID(0x3010));
|
|
||||||
hmc_obj->add_mmio_region(0x5FFFFFFC, 4,
|
hmc_obj->add_mmio_region(0x5FFFFFFC, 4,
|
||||||
dynamic_cast<MMIODevice*>(gMachineObj->get_comp_by_name("MachineID")));
|
dynamic_cast<MMIODevice*>(gMachineObj->get_comp_by_name("MachineID")));
|
||||||
|
|
||||||
/* allocate ROM region */
|
// allocate ROM region
|
||||||
if (!hmc_obj->add_rom_region(0x40000000, 0x400000)) {
|
if (!hmc_obj->add_rom_region(0x40000000, 0x400000)) {
|
||||||
LOG_F(ERROR, "Could not allocate ROM region!\n");
|
LOG_F(ERROR, "Could not allocate ROM region!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mirror ROM to 0xFFC00000 for a PowerPC CPU to start */
|
// mirror ROM to 0xFFC00000 for a PowerPC CPU to start
|
||||||
if (!hmc_obj->add_mem_mirror(0xFFC00000, 0x40000000)) {
|
if (!hmc_obj->add_mem_mirror(0xFFC00000, 0x40000000)) {
|
||||||
LOG_F(ERROR, "Could not create ROM mirror!\n");
|
LOG_F(ERROR, "Could not create ROM mirror!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add 8MB of soldered on-board RAM */
|
// add 8MB of soldered on-board RAM
|
||||||
if (!hmc_obj->add_ram_region(0x00000000, 0x800000)) {
|
if (!hmc_obj->add_ram_region(0x00000000, 0x800000)) {
|
||||||
LOG_F(ERROR, "Could not allocate built-in RAM region!\n");
|
LOG_F(ERROR, "Could not allocate built-in RAM region!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add internal SCSI bus */
|
// add internal SCSI bus
|
||||||
gMachineObj->add_component("SCSI0", new ScsiBus);
|
gMachineObj->add_device("SCSI0", std::unique_ptr<ScsiBus>(new ScsiBus()));
|
||||||
|
|
||||||
/* Init virtual CPU and request MPC601 */
|
// Init virtual CPU and request MPC601
|
||||||
ppc_cpu_init(hmc_obj, PPC_VER::MPC601, 7812500ULL);
|
ppc_cpu_init(hmc_obj, PPC_VER::MPC601, 7812500ULL);
|
||||||
|
|
||||||
// post-initialize all devices
|
|
||||||
if (gMachineObj->postinit_devices()) {
|
|
||||||
LOG_F(ERROR, "Could not post-initialize devices!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if a floppy image was given "insert" it into the virtual superdrive
|
|
||||||
std::string fd_image_path = GET_STR_PROP("fdd_img");
|
|
||||||
std::string fd_write_prot = GET_STR_PROP("fdd_wr_prot");
|
|
||||||
if (!fd_image_path.empty()) {
|
|
||||||
using namespace MacSuperdrive;
|
|
||||||
|
|
||||||
MacSuperDrive* fdd = dynamic_cast<MacSuperDrive*>
|
|
||||||
(gMachineObj->get_comp_by_name("Superdrive"));
|
|
||||||
|
|
||||||
bool write_flag = false;
|
|
||||||
|
|
||||||
if (!fd_write_prot.empty()) {
|
|
||||||
if ((fd_write_prot.compare("ON") == 0) || (fd_write_prot.compare("on") == 0)) {
|
|
||||||
write_flag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fdd->insert_disk(fd_image_path, write_flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_F(INFO, "Initialization completed.\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Monitors supported by the PDM on-board video.
|
||||||
|
// see displayid.cpp for the full list of supported monitor IDs.
|
||||||
|
static const vector<string> PDMBuiltinMonitorIDs = {
|
||||||
|
"PortraitGS", "MacRGB12in", "MacRGB15in", "HiRes12-14in", "VGA-SVGA",
|
||||||
|
"MacRGB16in", "Multiscan15in", "Multiscan17in", "Multiscan20in",
|
||||||
|
"NotConnected"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const PropMap pm6100_settings = {
|
||||||
|
{"rambank1_size",
|
||||||
|
new IntProperty(0, vector<uint32_t>({0, 8, 16, 32, 64, 128}))},
|
||||||
|
{"rambank2_size",
|
||||||
|
new IntProperty(0, vector<uint32_t>({0, 8, 16, 32, 64, 128}))},
|
||||||
|
{"mon_id",
|
||||||
|
new StrProperty("HiRes12-14in", PDMBuiltinMonitorIDs)},
|
||||||
|
};
|
||||||
|
|
||||||
|
static vector<string> pm6100_devices = {
|
||||||
|
"HMC", "Amic"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const MachineDescription pm6100_descriptor = {
|
||||||
|
.name = "pm6100",
|
||||||
|
.description = "Power Macintosh 6100",
|
||||||
|
.devices = pm6100_devices,
|
||||||
|
.settings = pm6100_settings,
|
||||||
|
.init_func = initialize_pdm
|
||||||
|
};
|
||||||
|
|
||||||
|
// self-registration with the MachineFactory
|
||||||
|
REGISTER_MACHINE(pm6100, pm6100_descriptor);
|
||||||
|
14
main.cpp
14
main.cpp
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
Copyright (C) 2018-21 divingkatae and maximum
|
Copyright (C) 2018-22 divingkatae and maximum
|
||||||
(theweirdo) spatium
|
(theweirdo) spatium
|
||||||
|
|
||||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
@ -110,9 +110,9 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
if (*list_cmd) {
|
if (*list_cmd) {
|
||||||
if (sub_arg == "machines") {
|
if (sub_arg == "machines") {
|
||||||
list_machines();
|
MachineFactory::list_machines();
|
||||||
} else if (sub_arg == "properties") {
|
} else if (sub_arg == "properties") {
|
||||||
list_properties();
|
MachineFactory::list_properties();
|
||||||
} else {
|
} else {
|
||||||
cout << "Unknown list subcommand " << sub_arg << endl;
|
cout << "Unknown list subcommand " << sub_arg << endl;
|
||||||
}
|
}
|
||||||
@ -142,7 +142,7 @@ int main(int argc, char** argv) {
|
|||||||
if (*machine_opt) {
|
if (*machine_opt) {
|
||||||
LOG_F(INFO, "Machine option was passed in: %s", machine_str.c_str());
|
LOG_F(INFO, "Machine option was passed in: %s", machine_str.c_str());
|
||||||
} else {
|
} else {
|
||||||
machine_str = machine_name_from_rom(bootrom_path);
|
machine_str = MachineFactory::machine_name_from_rom(bootrom_path);
|
||||||
if (machine_str.empty()) {
|
if (machine_str.empty()) {
|
||||||
LOG_F(ERROR, "Could not autodetect machine");
|
LOG_F(ERROR, "Could not autodetect machine");
|
||||||
return 0;
|
return 0;
|
||||||
@ -154,7 +154,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
/* handle overriding of machine settings from command line */
|
/* handle overriding of machine settings from command line */
|
||||||
map<string, string> settings;
|
map<string, string> settings;
|
||||||
if (get_machine_settings(machine_str, settings) < 0) {
|
if (MachineFactory::get_machine_settings(machine_str, settings) < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
sa.parse(app.remaining_for_passthrough()); /* TODO: handle exceptions! */
|
sa.parse(app.remaining_for_passthrough()); /* TODO: handle exceptions! */
|
||||||
|
|
||||||
set_machine_settings(settings);
|
MachineFactory::set_machine_settings(settings);
|
||||||
|
|
||||||
cout << "BootROM path: " << bootrom_path << endl;
|
cout << "BootROM path: " << bootrom_path << endl;
|
||||||
cout << "Execution mode: " << execution_mode << endl;
|
cout << "Execution mode: " << execution_mode << endl;
|
||||||
@ -179,7 +179,7 @@ int main(int argc, char** argv) {
|
|||||||
// initialize global profiler object
|
// initialize global profiler object
|
||||||
gProfilerObj.reset(new Profiler());
|
gProfilerObj.reset(new Profiler());
|
||||||
|
|
||||||
if (create_machine_for_id(machine_str, bootrom_path) < 0) {
|
if (MachineFactory::create_machine_for_id(machine_str, bootrom_path) < 0) {
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user