mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-06-25 23:29:33 +00:00
Create machine factory.
It manages various hardware configurations referred to as machines.
This commit is contained in:
parent
4adcd811e3
commit
822f6cafd2
|
@ -9,6 +9,7 @@ set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
|
||||||
|
|
||||||
add_subdirectory("${PROJECT_SOURCE_DIR}/cpu/ppc/")
|
add_subdirectory("${PROJECT_SOURCE_DIR}/cpu/ppc/")
|
||||||
add_subdirectory("${PROJECT_SOURCE_DIR}/devices/")
|
add_subdirectory("${PROJECT_SOURCE_DIR}/devices/")
|
||||||
|
add_subdirectory("${PROJECT_SOURCE_DIR}/machines/")
|
||||||
add_subdirectory("${PROJECT_SOURCE_DIR}/thirdparty/")
|
add_subdirectory("${PROJECT_SOURCE_DIR}/thirdparty/")
|
||||||
|
|
||||||
include_directories("${PROJECT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/devices"
|
include_directories("${PROJECT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/devices"
|
||||||
|
@ -21,10 +22,13 @@ file(GLOB SOURCES "${PROJECT_SOURCE_DIR}/*.cpp"
|
||||||
|
|
||||||
file(GLOB TEST_SOURCES "${PROJECT_SOURCE_DIR}/cpu/ppc/test/*.cpp")
|
file(GLOB TEST_SOURCES "${PROJECT_SOURCE_DIR}/cpu/ppc/test/*.cpp")
|
||||||
|
|
||||||
add_executable(dingusppc ${SOURCES} $<TARGET_OBJECTS:cpu_ppc> $<TARGET_OBJECTS:devices>
|
add_executable(dingusppc ${SOURCES} $<TARGET_OBJECTS:cpu_ppc>
|
||||||
|
$<TARGET_OBJECTS:devices>
|
||||||
|
$<TARGET_OBJECTS:machines>
|
||||||
$<TARGET_OBJECTS:loguru>)
|
$<TARGET_OBJECTS:loguru>)
|
||||||
|
|
||||||
add_executable(testppc ${TEST_SOURCES} $<TARGET_OBJECTS:cpu_ppc> $<TARGET_OBJECTS:devices>
|
add_executable(testppc ${TEST_SOURCES} $<TARGET_OBJECTS:cpu_ppc>
|
||||||
|
$<TARGET_OBJECTS:devices>
|
||||||
$<TARGET_OBJECTS:loguru>)
|
$<TARGET_OBJECTS:loguru>)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
|
|
|
@ -245,8 +245,8 @@ extern uint32_t exceptions_performed;
|
||||||
extern uint32_t supervisor_inst_num;
|
extern uint32_t supervisor_inst_num;
|
||||||
|
|
||||||
//Function prototypes
|
//Function prototypes
|
||||||
extern void ppc_cpu_init(uint32_t proc_version);
|
extern void ppc_cpu_init(MemCtrlBase *mem_ctrl, uint32_t proc_version);
|
||||||
extern void ppc_mmu_init(void);
|
extern void ppc_mmu_init();
|
||||||
|
|
||||||
void ppc_illegalop();
|
void ppc_illegalop();
|
||||||
void ppc_opcode4();
|
void ppc_opcode4();
|
||||||
|
|
|
@ -760,10 +760,12 @@ again:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void ppc_cpu_init(uint32_t proc_version)
|
void ppc_cpu_init(MemCtrlBase *mem_ctrl, uint32_t proc_version)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
mem_ctrl_instance = mem_ctrl;
|
||||||
|
|
||||||
clock_test_begin = clock();
|
clock_test_begin = clock();
|
||||||
timebase_counter = 0;
|
timebase_counter = 0;
|
||||||
|
|
||||||
|
|
7
machines/CMakeLists.txt
Normal file
7
machines/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
|
include_directories("${PROJECT_SOURCE_DIR}")
|
||||||
|
|
||||||
|
file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
|
||||||
|
|
||||||
|
add_library(machines OBJECT ${SOURCES})
|
76
machines/machinebase.cpp
Normal file
76
machines/machinebase.cpp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <thirdparty/loguru.hpp>
|
||||||
|
#include "machinebase.h"
|
||||||
|
|
||||||
|
std::unique_ptr<MachineBase> gMachineObj = 0;
|
||||||
|
|
||||||
|
|
||||||
|
MachineBase::MachineBase(std::string name)
|
||||||
|
{
|
||||||
|
this->name = name;
|
||||||
|
|
||||||
|
/* initialize internal maps */
|
||||||
|
this->comp_map.clear();
|
||||||
|
this->name_to_type.clear();
|
||||||
|
this->aliases.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
MachineBase::~MachineBase()
|
||||||
|
{
|
||||||
|
for(auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
|
this->comp_map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MachineBase::add_component(std::string name, HWCompType type, MMIODevice *dev_obj)
|
||||||
|
{
|
||||||
|
if (this->comp_map.count(name)) {
|
||||||
|
LOG_F(ERROR, "Component %s already exists!", name.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->comp_map[name] = dev_obj;
|
||||||
|
this->name_to_type[name] = type;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachineBase::add_alias(std::string name, std::string alias, HWCompType type)
|
||||||
|
{
|
||||||
|
this->aliases[alias] = name;
|
||||||
|
this->name_to_type[alias] = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
MMIODevice *MachineBase::get_comp_by_name(std::string name)
|
||||||
|
{
|
||||||
|
if (this->aliases.count(name)) {
|
||||||
|
name = this->aliases[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->comp_map.count(name)) {
|
||||||
|
return this->comp_map[name];
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MMIODevice *MachineBase::get_comp_by_type(HWCompType type)
|
||||||
|
{
|
||||||
|
std::string comp_name;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for(auto it = this->name_to_type.begin(); it != this->name_to_type.end(); it++) {
|
||||||
|
if (it->second == type) {
|
||||||
|
comp_name = it->first;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return this->get_comp_by_name(comp_name);
|
||||||
|
}
|
68
machines/machinebase.h
Normal file
68
machines/machinebase.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
|
Copyright (C) 2018-20 divingkatae and maximum
|
||||||
|
(theweirdo) spatium
|
||||||
|
|
||||||
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file Base class for managing different HW components of a machine.
|
||||||
|
|
||||||
|
Author: Max Poliakovski
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MACHINE_BASE_H
|
||||||
|
#define MACHINE_BASE_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include "devices/mmiodevice.h"
|
||||||
|
|
||||||
|
/** types of different HW components */
|
||||||
|
enum HWCompType : int {
|
||||||
|
UNKNOWN = 0, /* unknown component type */
|
||||||
|
MEM_CTRL = 1, /* memory controller */
|
||||||
|
ROM = 2, /* read-only memory */
|
||||||
|
RAM = 3, /* random access memory */
|
||||||
|
MMIO_DEV = 4, /* memory mapped I/O device */
|
||||||
|
PCI_HOST = 5, /* PCI host */
|
||||||
|
PCI_DEV = 6, /* PCI device */
|
||||||
|
I2C_DEV = 7, /* I2C device */
|
||||||
|
ADB_DEV = 8 /* ADB device */
|
||||||
|
};
|
||||||
|
|
||||||
|
class MachineBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MachineBase(std::string name);
|
||||||
|
~MachineBase();
|
||||||
|
|
||||||
|
bool add_component(std::string name, HWCompType type, MMIODevice *dev_obj);
|
||||||
|
void add_alias(std::string name, std::string alias, HWCompType type);
|
||||||
|
MMIODevice *get_comp_by_name(std::string name);
|
||||||
|
MMIODevice *get_comp_by_type(HWCompType type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
std::map<std::string, MMIODevice *>comp_map;
|
||||||
|
std::map<std::string, int> name_to_type;
|
||||||
|
std::map<std::string, std::string> aliases;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern std::unique_ptr<MachineBase> gMachineObj;
|
||||||
|
|
||||||
|
#endif /* MACHINE_BASE_H */
|
151
machines/machinefactory.cpp
Normal file
151
machines/machinefactory.cpp
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
|
Copyright (C) 2018-20 divingkatae and maximum
|
||||||
|
(theweirdo) spatium
|
||||||
|
|
||||||
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file Factory for creating different machines.
|
||||||
|
|
||||||
|
Author: Max Poliakovski
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <thirdparty/loguru.hpp>
|
||||||
|
#include "memreadwrite.h"
|
||||||
|
#include "machinefactory.h"
|
||||||
|
#include "devices/memctrlbase.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Power Macintosh ROM identification string
|
||||||
|
|
||||||
|
is located in the ConfigInfo structure starting at 0x30D064 (PCI Macs)
|
||||||
|
or 0x30C064 (Nubus Macs).
|
||||||
|
*/
|
||||||
|
static const map<uint32_t, string> rom_identity = {
|
||||||
|
{0x416C6368, "Performa 6400"}, //Alchemy
|
||||||
|
//{"Come", "PowerBook 2400"}, //Comet
|
||||||
|
{0x436F7264, "Power Mac 5200/6200 series"}, //Cordyceps
|
||||||
|
{0x47617A65, "Power Mac 6500"}, //Gazelle
|
||||||
|
{0x476F7373, "Power Mac G3 Beige"}, //Gossamer
|
||||||
|
{0x47525820, "PowerBook G3 Wallstreet"},
|
||||||
|
//{"Hoop", "PowerBook 3400"}, //Hooper
|
||||||
|
{0x50425820, "PowerBook Pre-G3"},
|
||||||
|
{0x50444D20, "Nubus Power Mac or WGS"}, //Piltdown Man (6100/7100/8100)
|
||||||
|
{0x50697020, "Bandai Pippin"}, //Pippin
|
||||||
|
//{"Powe", "Generic Power Mac"}, //PowerMac?
|
||||||
|
//{"Spar", "20th Anniversay Mac"}, //Spartacus
|
||||||
|
//{"Tanz", "Power Mac 4400"}, //Tanzania
|
||||||
|
{0x544E5420, "Power Mac 7xxxx/8xxx series"}, //Trinitrotoluene :-)
|
||||||
|
//{"Zanz", "A complete engima."}, //Zanzibar (mentioned in Sheepshaver's code, but no match to any known ROM)
|
||||||
|
//{"????", "A clone, perhaps?"} //N/A (Placeholder ID)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int create_machine_for_id(uint32_t id)
|
||||||
|
{
|
||||||
|
switch(id) {
|
||||||
|
case 0x476F7373:
|
||||||
|
create_gossamer();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_F(ERROR, "Unknown machine ID: %X", id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read ROM file content and transfer it to the dedicated ROM region */
|
||||||
|
void load_rom(ifstream& rom_file, uint32_t file_size)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int create_machine_for_rom(const char* rom_filepath)
|
||||||
|
{
|
||||||
|
ifstream rom_file;
|
||||||
|
int result;
|
||||||
|
uint32_t file_size, config_info_offset, rom_id;
|
||||||
|
char rom_id_str[17];
|
||||||
|
|
||||||
|
rom_file.open(rom_filepath, ios::in|ios::binary);
|
||||||
|
if (rom_file.fail()) {
|
||||||
|
LOG_F(ERROR, "Cound not open the specified ROM file.");
|
||||||
|
rom_file.close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rom_file.seekg(0, rom_file.end);
|
||||||
|
file_size = rom_file.tellg();
|
||||||
|
rom_file.seekg(0, rom_file.beg);
|
||||||
|
|
||||||
|
if (file_size != 0x400000UL){
|
||||||
|
LOG_F(ERROR, "Unxpected ROM File size. Expected size is 4 megabytes.");
|
||||||
|
rom_file.close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read config info offset from file */
|
||||||
|
config_info_offset = 0;
|
||||||
|
rom_file.seekg(0x300080, ios::beg);
|
||||||
|
rom_file.read((char *)&config_info_offset, 4);
|
||||||
|
config_info_offset = READ_DWORD_BE_A(&config_info_offset);
|
||||||
|
|
||||||
|
/* rewind to ConfigInfo.BootstrapVersion field */
|
||||||
|
rom_file.seekg(0x300064 + config_info_offset, ios::beg);
|
||||||
|
|
||||||
|
/* read BootstrapVersion as C string */
|
||||||
|
rom_file.read(rom_id_str, 16);
|
||||||
|
rom_id_str[16] = 0;
|
||||||
|
LOG_F(INFO, "ROM BootstrapVersion: %s", rom_id_str);
|
||||||
|
|
||||||
|
if (strncmp(rom_id_str, "Boot", 4) != 0) {
|
||||||
|
LOG_F(ERROR, "Invalid BootstrapVersion string.");
|
||||||
|
rom_file.close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert BootstrapVersion string to ROM ID */
|
||||||
|
rom_id = (rom_id_str[5] << 24) | (rom_id_str[6] << 16) |
|
||||||
|
(rom_id_str[7] << 8) | rom_id_str[8];
|
||||||
|
|
||||||
|
LOG_F(INFO, "The machine is identified as... %s\n", rom_identity.at(rom_id).c_str());
|
||||||
|
|
||||||
|
create_machine_for_id(rom_id);
|
||||||
|
|
||||||
|
load_rom(rom_file, file_size);
|
||||||
|
|
||||||
|
rom_file.close();
|
||||||
|
return 0;
|
||||||
|
}
|
36
machines/machinefactory.h
Normal file
36
machines/machinefactory.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
|
Copyright (C) 2018-20 divingkatae and maximum
|
||||||
|
(theweirdo) spatium
|
||||||
|
|
||||||
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file Factory for creating different machines.
|
||||||
|
|
||||||
|
Author: Max Poliakovski
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MACHINE_FACTORY_H
|
||||||
|
#define MACHINE_FACTORY_H
|
||||||
|
|
||||||
|
#include "machinebase.h"
|
||||||
|
|
||||||
|
int create_machine_for_rom(const char* rom_filepath);
|
||||||
|
|
||||||
|
int create_gossamer(void);
|
||||||
|
|
||||||
|
#endif /* MACHINE_FACTORY_H */
|
77
machines/machinegossamer.cpp
Normal file
77
machines/machinegossamer.cpp
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
|
Copyright (C) 2018-20 divingkatae and maximum
|
||||||
|
(theweirdo) spatium
|
||||||
|
|
||||||
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file Constructs the Gossamer machine.
|
||||||
|
|
||||||
|
Author: Max Poliakovski
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <thirdparty/loguru.hpp>
|
||||||
|
#include "machinebase.h"
|
||||||
|
#include "devices/mpc106.h"
|
||||||
|
#include "devices/machineid.h"
|
||||||
|
#include "devices/macio.h"
|
||||||
|
#include "cpu/ppc/ppcemu.h"
|
||||||
|
#include "machinebase.h"
|
||||||
|
|
||||||
|
int create_gossamer()
|
||||||
|
{
|
||||||
|
if (gMachineObj) {
|
||||||
|
LOG_F(ERROR, "Global machine object not empty!");
|
||||||
|
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", HWCompType::MEM_CTRL, new MPC106);
|
||||||
|
gMachineObj->add_alias("Grackle", "PCI_Host", HWCompType::PCI_HOST);
|
||||||
|
|
||||||
|
/* get raw pointer to MPC106 object */
|
||||||
|
MPC106 *grackle_obj = dynamic_cast<MPC106 *>(gMachineObj->get_comp_by_name("Grackle"));
|
||||||
|
|
||||||
|
/* add the machine ID register */
|
||||||
|
gMachineObj->add_component("MachineID", HWCompType::MMIO_DEV,
|
||||||
|
new GossamerID(0x3d8c));
|
||||||
|
grackle_obj->add_mmio_region(0xFF000004, 4096,
|
||||||
|
gMachineObj->get_comp_by_name("MachineID"));
|
||||||
|
|
||||||
|
/* add the Heathrow I/O controller */
|
||||||
|
gMachineObj->add_component("Heathrow", HWCompType::MMIO_DEV, new HeathrowIC);
|
||||||
|
grackle_obj->pci_register_device(16,
|
||||||
|
dynamic_cast<PCIDevice *>(gMachineObj->get_comp_by_name("Heathrow")));
|
||||||
|
|
||||||
|
/* allocate ROM region */
|
||||||
|
if (!grackle_obj->add_rom_region(0xFFC00000, 0x400000)) {
|
||||||
|
LOG_F(ERROR, "Could not allocate ROM region!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init virtual CPU and request MPC750 CPU aka G3 */
|
||||||
|
ppc_cpu_init(grackle_obj, PPC_VER::MPC750);
|
||||||
|
|
||||||
|
LOG_F(INFO, "Initialization complete.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
144
main.cpp
144
main.cpp
|
@ -24,54 +24,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include <thirdparty/loguru.hpp>
|
#include <thirdparty/loguru.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <array>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fstream>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include "ppcemu.h"
|
#include "ppcemu.h"
|
||||||
#include "ppcmmu.h"
|
|
||||||
#include "memreadwrite.h"
|
|
||||||
#include "devices/mpc106.h"
|
|
||||||
#include "debugger/debugger.h"
|
#include "debugger/debugger.h"
|
||||||
#include "devices/machineid.h"
|
#include "machines/machinefactory.h"
|
||||||
#include "devices/macio.h"
|
|
||||||
#include "devices/mpc106.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
/**
|
|
||||||
Power Macintosh ROM identification string
|
|
||||||
|
|
||||||
is located in the ConfigInfo structure starting at 0x30D064 (PCI Macs)
|
|
||||||
or 0x30C064 (Nubus Macs). This helps a lot to determine which
|
|
||||||
hardware is to be used.
|
|
||||||
*/
|
|
||||||
static const map<string,string> PPCMac_ROMIdentity = { //Codename Abbreviation for...
|
|
||||||
{"Alch", "Performa 6400"}, //Alchemy
|
|
||||||
{"Come", "PowerBook 2400"}, //Comet
|
|
||||||
{"Cord", "Power Mac 5200/6200 series"}, //Cordyceps
|
|
||||||
{"Gaze", "Power Mac 6500"}, //Gazelle
|
|
||||||
{"Goss", "Power Mac G3 Beige"}, //Gossamer
|
|
||||||
{"GRX ", "PowerBook G3 Wallstreet"}, //(Unknown)
|
|
||||||
{"Hoop", "PowerBook 3400"}, //Hooper
|
|
||||||
{"PBX ", "PowerBook Pre-G3"}, //(Unknown)
|
|
||||||
{"PDM ", "Nubus Power Mac or WGS"}, //Piltdown Man (6100/7100/8100)
|
|
||||||
{"Pip ", "Pippin... uh... yeah..."}, //Pippin
|
|
||||||
{"Powe", "Generic Power Mac"}, //PowerMac?
|
|
||||||
{"Spar", "20th Anniversay Mac, you lucky thing."}, //Spartacus
|
|
||||||
{"Tanz", "Power Mac 4400"}, //Tanzania
|
|
||||||
{"TNT ", "Power Mac 7xxxx/8xxx series"}, //Trinitrotoluene :-)
|
|
||||||
{"Zanz", "A complete engima."}, //Zanzibar (mentioned in Sheepshaver's code, but no match to any known ROM)
|
|
||||||
{"????", "A clone, perhaps?"} //N/A (Placeholder ID)
|
|
||||||
};
|
|
||||||
|
|
||||||
HeathrowIC *heathrow = 0;
|
|
||||||
GossamerID *machine_id;
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -106,101 +67,10 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
uint32_t rom_filesize;
|
uint32_t rom_filesize;
|
||||||
|
|
||||||
/* Init virtual CPU and request MPC750 CPU aka G3 */
|
if (create_machine_for_rom("rom.bin")) {
|
||||||
ppc_cpu_init(PPC_VER::MPC750);
|
goto bail;
|
||||||
|
|
||||||
|
|
||||||
LOG_F(INFO, "Checking for ROM file");
|
|
||||||
|
|
||||||
//Open the ROM File.
|
|
||||||
ifstream romFile;
|
|
||||||
|
|
||||||
romFile.open("rom.bin", ios::in|ios::binary);
|
|
||||||
|
|
||||||
if (romFile.fail()){
|
|
||||||
cerr << "rom.bin not present. Please provide an appropriate ROM file"
|
|
||||||
<< " and restart this program.\n";
|
|
||||||
|
|
||||||
romFile.close();
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Calculate and validate ROM file size.
|
|
||||||
romFile.seekg(0, romFile.end);
|
|
||||||
rom_filesize = (uint32_t) romFile.tellg();
|
|
||||||
LOG_F(INFO, "Rom SIZE: %d \n", rom_filesize);
|
|
||||||
romFile.seekg (0, romFile.beg);
|
|
||||||
|
|
||||||
if (rom_filesize != 0x400000){
|
|
||||||
cerr << "Unsupported ROM File size. Expected size is 4 megabytes.\n";
|
|
||||||
romFile.close();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char configGrab = 0;
|
|
||||||
uint32_t configInfoOffset = 0;
|
|
||||||
|
|
||||||
romFile.seekg (0x300082, ios::beg); //This is where the place to get the offset is
|
|
||||||
romFile.get(configGrab); //just one byte to determine ConfigInfo location
|
|
||||||
configInfoOffset = (uint32_t)(configGrab & 0xff);
|
|
||||||
|
|
||||||
uint32_t configInfoAddr = 0x300000 + (configInfoOffset << 8) + 0x69; //address to check the identifier string
|
|
||||||
char memPPCBlock[5] = { 0 }; //First four chars are enough to distinguish between codenames
|
|
||||||
romFile.seekg (configInfoAddr, ios::beg);
|
|
||||||
romFile.read(memPPCBlock, 4);
|
|
||||||
memPPCBlock[4] = 0;
|
|
||||||
uint32_t rom_id = READ_DWORD_BE_A(memPPCBlock);
|
|
||||||
|
|
||||||
std::string string_test = std::string(memPPCBlock);
|
|
||||||
|
|
||||||
//Just auto-iterate through the list
|
|
||||||
for (auto iter = PPCMac_ROMIdentity.begin(); iter != PPCMac_ROMIdentity.end(); ){
|
|
||||||
|
|
||||||
string redo_me = iter->first;
|
|
||||||
|
|
||||||
if (string_test.compare(redo_me) == 0){
|
|
||||||
const char* check_me = iter->second.c_str();
|
|
||||||
LOG_F(INFO, "The machine is identified as... %s \n", check_me);
|
|
||||||
romFile.seekg (0x0, ios::beg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(rom_id) {
|
|
||||||
case 0x476F7373: {
|
|
||||||
LOG_F(INFO, "Initialize Gossamer hardware... \n");
|
|
||||||
MPC106 *mpc106 = new MPC106();
|
|
||||||
mem_ctrl_instance = mpc106;
|
|
||||||
if (!mem_ctrl_instance->add_rom_region(0xFFC00000, 0x400000)) {
|
|
||||||
LOG_F(ERROR, "Failed to Gossamer hardware... \n");
|
|
||||||
delete(mem_ctrl_instance);
|
|
||||||
romFile.close();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
machine_id = new GossamerID(0x3d8c);
|
|
||||||
mpc106->add_mmio_region(0xFF000004, 4096, machine_id);
|
|
||||||
|
|
||||||
heathrow = new HeathrowIC();
|
|
||||||
mpc106->pci_register_device(16, heathrow);
|
|
||||||
LOG_F(INFO, "Initialization complete. \n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_F(INFO, "This machine not supported yet. \n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read ROM file content and transfer it to the dedicated ROM region */
|
|
||||||
unsigned char *sysrom_mem = new unsigned char[rom_filesize];
|
|
||||||
romFile.read ((char *)sysrom_mem, rom_filesize);
|
|
||||||
mem_ctrl_instance->set_data(0xFFC00000, sysrom_mem, rom_filesize);
|
|
||||||
romFile.close();
|
|
||||||
delete[] sysrom_mem;
|
|
||||||
|
|
||||||
|
|
||||||
if ((checker == "1") || (checker == "realtime") || \
|
if ((checker == "1") || (checker == "realtime") || \
|
||||||
(checker == "-realtime") || (checker == "/realtime")) {
|
(checker == "-realtime") || (checker == "/realtime")) {
|
||||||
ppc_exec();
|
ppc_exec();
|
||||||
|
@ -219,10 +89,10 @@ int main(int argc, char **argv)
|
||||||
std::cout << "debugger - Enter the interactive debugger. " << endl;
|
std::cout << "debugger - Enter the interactive debugger. " << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free memory after the emulation is completed. */
|
bail:
|
||||||
delete(heathrow);
|
LOG_F(INFO, "Cleaning up...");
|
||||||
delete(machine_id);
|
|
||||||
delete(mem_ctrl_instance);
|
delete gMachineObj.release();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
2
thirdparty/CMakeLists.txt
vendored
2
thirdparty/CMakeLists.txt
vendored
|
@ -1,3 +1,5 @@
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
include_directories("${PROJECT_SOURCE_DIR}")
|
include_directories("${PROJECT_SOURCE_DIR}")
|
||||||
|
|
||||||
file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/loguru.cpp"
|
file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/loguru.cpp"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user