Initial CLI11 integration.

This commit is contained in:
Maxim Poliakovski 2020-09-20 23:25:29 +02:00
parent 9efea80e43
commit 599659495b
9 changed files with 8542 additions and 76 deletions

View File

@ -35,6 +35,8 @@ set(BUILD_TOOLS OFF CACHE BOOL "Build Cubeb tools")
add_subdirectory(thirdparty/cubeb EXCLUDE_FROM_ALL)
set(CLI11_ROOT ${PROJECT_SOURCE_DIR}/thirdparty/CLI11)
include_directories("${PROJECT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/devices"
"${PROJECT_SOURCE_DIR}/cpu/ppc"
"${PROJECT_SOURCE_DIR}/debugger"
@ -65,6 +67,7 @@ target_link_libraries(dingusppc "${PROJECT_SOURCE_DIR}/thirdparty/SDL2/lib/x64/S
else()
#target_link_libraries(dingusppc libsoundio_static ${LIBSOUNDIO_LIBS} ${SDL2_LIBRARIES})
target_link_libraries(dingusppc cubeb ${SDL2_LIBRARIES} ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
target_include_directories(dingusppc PRIVATE ${CLI11_ROOT})
endif()

View File

@ -50,11 +50,11 @@ bool check_ram_size(std::string machine_str, uint32_t number_to_check) {
max_ram = PowerMacG3_Properties.find("maxram")->second.IntRep();
}
if ((number_to_check > max_ram) ||
(number_to_check > max_ram) ||
if ((number_to_check > max_ram) ||
(number_to_check > max_ram) ||
!(is_power_of_two(number_to_check))) {
return false;
}
}
else {
return true;
}
@ -86,14 +86,14 @@ void search_properties(std::string machine_str) {
uint32_t gfx_type = 0;
if (machine_str.compare("PowerMacG3") == 0) {
cpu_str = PowerMac6100_Properties.find("cputype")->second.getString();
cpu_str = PowerMac6100_Properties.find("cputype")->second.get_string();
cpu_type = get_cpu_type(cpu_str);
ram_size = PowerMac6100_Properties.find("rambank1")->second.IntRep();
gfx_size = PowerMac6100_Properties.find("gfxmem")->second.IntRep();
gfx_type = PowerMac6100_Properties.find("gfxcard")->second.IntRep();
}
else if (machine_str.compare("PowerMac6100") == 0) {
cpu_str = PowerMacG3_Properties.find("cputype")->second.getString();
cpu_str = PowerMacG3_Properties.find("cputype")->second.get_string();
cpu_type = get_cpu_type(cpu_str);
ram_size = PowerMacG3_Properties.find("rambank1")->second.IntRep();
gfx_size = PowerMacG3_Properties.find("gfxmem")->second.IntRep();
@ -142,7 +142,7 @@ int establish_machine_presets(
if (machine_str.compare("PowerMacG3") == 0) {
create_gossamer(ram_sizes, gfx_mem);
}
}
}
else {
return -1;
}
@ -151,4 +151,4 @@ int establish_machine_presets(
rom_file.close();
return 0;
}
}

View File

@ -27,6 +27,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "machinefactory.h"
#include "devices/memctrlbase.h"
#include "memreadwrite.h"
#include "machineproperties.h"
#include <cinttypes>
#include <cstring>
#include <fstream>
@ -37,29 +38,117 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
using namespace std;
/**
Power Macintosh ROM identification string
Power Macintosh ROM identification map.
is located in the ConfigInfo structure starting at 0x30D064 (PCI Macs)
or 0x30C064 (Nubus Macs).
Maps Bootstrap string located at offset 0x30D064 (PCI Macs)
or 0x30C064 (Nubus Macs) to machine name and description.
*/
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"}, // Piltdown Man (6100/7100/8100)
{0x50697020, "Bandai Pippin"}, // Pippin
//{"Powe", "Generic Power Mac"}, // PowerMac?
//{"Spar", "20th Anniversay Mac"}, // Spartacus
{0x544E5420, "Power Mac 7xxxx/8xxx series"}, // Trinitrotoluene :-)
{0x5A616E7A, "Power Mac 4400/7220"}, // Zanzibar
//{"????", "A clone, perhaps?"} // N/A (Placeholder ID)
static const map<uint32_t, std::tuple<string, const char*>> rom_identity = {
{0x416C6368, {"pm6400", "Performa 6400"}}, // Alchemy
//{"Come", "PowerBook 2400"}, // Comet
{0x436F7264, {"pm5200", "Power Mac 5200/6200 series"}}, // Cordyceps
{0x47617A65, {"pm6500", "Power Mac 6500"}}, // Gazelle
{0x476F7373, {"pmg3", "Power Mac G3 Beige"}}, // Gossamer
{0x47525820, {"pbg3", "PowerBook G3 Wallstreet"}},
//{"Hoop", "PowerBook 3400"}, // Hooper
{0x50425820, {"pb-preg3", "PowerBook Pre-G3"}},
{0x50444D20, {"pm6100", "Nubus Power Mac"}}, // Piltdown Man (6100/7100/8100)
{0x50697020, {"pippin", "Bandai Pippin"}}, // Pippin
//{"Powe", "Generic Power Mac"}, // PowerMac?
//{"Spar", "20th Anniversay Mac"}, // Spartacus
{0x544E5420, {"pm7200", "Power Mac 7xxxx/8xxx series"}}, // Trinitrotoluene :-)
{0x5A616E7A, {"pm4400", "Power Mac 4400/7220"}}, // Zanzibar
};
typedef std::map<std::string, StrProperty> Settings;
static const Settings GossamerSettings = {
{"rambank1_size", StrProperty("256MB")},
{"rambank2_size", StrProperty("0") },
{"rambank3_size", StrProperty("0") },
{"gfxmem_size", StrProperty("2MB") }
};
static const map<string, Settings> machines = {
{"pmg3", GossamerSettings}
};
string machine_name_from_rom(string& rom_filepath) {
ifstream rom_file;
uint32_t file_size, config_info_offset, rom_id;
char rom_id_str[17];
string machine_name = "";
rom_file.open(rom_filepath, ios::in | ios::binary);
if (rom_file.fail()) {
LOG_F(ERROR, "Cound not open the specified ROM file.");
goto bail_out;
}
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.");
goto bail_out;
}
/* 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.");
goto bail_out;
}
/* 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",
std::get<1>(rom_identity.at(rom_id)));
machine_name = std::get<0>(rom_identity.at(rom_id));
bail_out:
rom_file.close();
return machine_name;
}
int get_machine_settings(string& id, map<string, string> &settings) {
try {
Settings props = machines.at(id);
for (auto& p : props) {
settings[p.first] = p.second.get_string();
}
}
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) {
cout << s.first << " : " << s.second << endl;
}
}
int create_machine_for_id(uint32_t id, uint32_t* grab_ram_size, uint32_t gfx_size) {
switch (id) {
@ -134,7 +223,7 @@ int create_machine_for_rom(const char* rom_filepath, uint32_t* grab_ram_size, ui
/* 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());
LOG_F(INFO, "The machine is identified as... %s\n", std::get<1>(rom_identity.at(rom_id)));
create_machine_for_id(rom_id, grab_ram_size, gfx_size);

View File

@ -29,9 +29,17 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "machinebase.h"
#include <fstream>
#include <string>
using namespace std;
std::string machine_name_from_rom(std::string& rom_filepath);
void load_rom(std::ifstream& rom_file, uint32_t file_size);
int get_machine_settings(string& id, map<string, string> &settings);
void set_machine_settings(map<string, string> &settings);
int create_machine_for_rom(const char* rom_filepath, uint32_t* grab_ram_size, uint32_t gfx_size);
int create_gossamer(uint32_t* grab_ram_size, uint32_t gfx_size);

View File

@ -36,6 +36,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "machineproperties.h"
#include <thirdparty/loguru/loguru.hpp>
static void setup_ram_slot(std::string name, int i2c_addr, int capacity_megs) {
if (!capacity_megs)
return;

View File

@ -1,28 +1,28 @@
#include "machineproperties.h"
#include <map>
static std::map<std::string, StringProperty> PowerMac6100_Properties = {
{"machineid", StringProperty("PowerMacG3")},
{"cputype", StringProperty("PPC_MPC750")},
{"motherboard", StringProperty("Grackle")},
{"ioboard", StringProperty("Heathrow")},
{"rambank1", StringProperty("64")},
{"minram", StringProperty("32")},
{"maxram", StringProperty("256")},
{"gfxcard", StringProperty("Nubus_Video")},
{"gfxmem", StringProperty("2")}
static std::map<std::string, StrProperty> PowerMac6100_Properties = {
{"machineid", StrProperty("PowerMacG3")},
{"cputype", StrProperty("PPC_MPC750")},
{"motherboard", StrProperty("Grackle")},
{"ioboard", StrProperty("Heathrow")},
{"rambank1", StrProperty("64")},
{"minram", StrProperty("32")},
{"maxram", StrProperty("256")},
{"gfxcard", StrProperty("Nubus_Video")},
{"gfxmem", StrProperty("2")}
};
static std::map<std::string, StringProperty> PowerMacG3_Properties = {
{"machineid", StringProperty("PowerMacG3")},
{"cputype", StringProperty("PPC_MPC750")},
{"motherboard", StringProperty("Grackle")},
{"ioboard", StringProperty("Heathrow")},
{"rambank1", StringProperty("64")},
{"minram", StringProperty("32")},
{"maxram", StringProperty("256")},
{"gfxcard", StringProperty("ATI_Rage_Pro")},
{"gfxmem", StringProperty("2")}
static std::map<std::string, StrProperty> PowerMacG3_Properties = {
{"machineid", StrProperty("PowerMacG3")},
{"cputype", StrProperty("PPC_MPC750")},
{"motherboard", StrProperty("Grackle")},
{"ioboard", StrProperty("Heathrow")},
{"rambank1", StrProperty("64")},
{"minram", StrProperty("32")},
{"maxram", StrProperty("256")},
{"gfxcard", StrProperty("ATI_Rage_Pro")},
{"gfxmem", StrProperty("2")}
};
static std::map<std::string, uint32_t> PPC_CPUs = {

View File

@ -1,4 +1,5 @@
#include "endianswap.h"
#include <thirdparty/loguru/loguru.hpp>
#include <cinttypes>
#include <string>
#include <map>
@ -11,19 +12,23 @@ using namespace std;
#define ILLEGAL_DEVICE_VALUE 0x168A523B
class StringProperty {
class StrProperty {
public:
StringProperty(string EnterString) {
StringInput = EnterString;
StrProperty(string str) {
this->prop_val = str;
}
string getString() {
return StringInput;
string get_string() {
return this->prop_val;
}
void set_string(string str) {
this->prop_val = str;
}
uint32_t IntRep() {
try {
return strtoul(getString().c_str(), 0, 0);
return strtoul(get_string().c_str(), 0, 0);
} catch (string bad_string) {
cerr << "Could not convert string " << bad_string << "to an ineteger!" << endl;
@ -32,7 +37,31 @@ public:
}
private:
string StringInput = std::to_string(ILLEGAL_DEVICE_VALUE);
string prop_val = string("");
};
class IntProperty {
public:
IntProperty(string str) {
this->prop_val = str;
}
void set_string(string str) {
this->prop_val = str;
}
uint32_t get_int() {
try {
return strtoul(this->prop_val.c_str(), 0, 0);
} catch (string bad_string) {
LOG_F(ERROR, "Could not convert string %s to an integer!",
bad_string.c_str());
}
return 0;
}
private:
string prop_val = string("");
};
uint32_t get_gfx_card(std::string gfx_str);
@ -41,4 +70,4 @@ void search_properties(uint32_t chosen_gestalt);
int establish_machine_presets(
const char* rom_filepath, std::string machine_str, uint32_t* ram_sizes, uint32_t gfx_mem);
#endif /* MACHINE_PROPERTIES_H */
#endif /* MACHINE_PROPERTIES_H */

120
main.cpp
View File

@ -32,6 +32,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <CLI11.hpp>
#include <thirdparty/SDL2/include/SDL.h>
#include <thirdparty/loguru/loguru.hpp>
@ -82,11 +83,88 @@ int main(int argc, char** argv) {
bool machine_specified = false;
string machine_name = "";
std::cout << "DingusPPC - Prototype 5bf5 (8/23/2020) " << endl;
std::cout << "Written by divingkatae and maximumspatium " << endl;
std::cout << "(c) 2018-2020 The DingusPPC Dev Team. " << endl;
std::cout << "This is not intended for general use. " << endl;
std::cout << "Use at your own discretion. " << endl;
CLI::App app("DingusPPC CLI");
app.allow_windows_style_options(); /* we want Windows-style options */
app.allow_extras();
cout << endl;
cout << "DingusPPC - Prototype 5bf5 (8/23/2020) " << endl;
cout << "Written by divingkatae and maximumspatium " << endl;
cout << "(c) 2018-2020 The DingusPPC Dev Team. " << endl;
cout << "This is not intended for general use. " << endl;
cout << "Use at your own discretion. " << endl;
cout << endl;
bool realtime_enabled, debugger_enabled;
string machine_str;
string bootrom_path("bootrom.bin");
app.add_flag("-r,--realtime", realtime_enabled,
"Run the emulator in real-time");
app.add_flag("-d,--debugger", debugger_enabled,
"Enter the built-in debugger");
app.add_option("-b,--bootrom", bootrom_path, "Specifies BootROM path")
->check(CLI::ExistingFile);
CLI::Option* machine_opt = app.add_option("-m,--machine",
machine_str, "Specify machine ID");
auto list_cmd = app.add_subcommand("machines",
"Display available machine configurations and exit");
CLI11_PARSE(app, argc, argv);
if (debugger_enabled) {
if (realtime_enabled)
cout << "Both realtime and debugger enabled! Using debugger" << endl;
execution_mode = 1;
}
/* initialize logging */
loguru::g_preamble_date = false;
loguru::g_preamble_time = false;
loguru::g_preamble_thread = false;
if (execution_mode) {
loguru::g_stderr_verbosity = loguru::Verbosity_OFF;
loguru::init(argc, argv);
loguru::add_file("dingusppc.log", loguru::Append, 0);
} else {
loguru::g_stderr_verbosity = 0;
loguru::init(argc, argv);
}
if (*machine_opt) {
LOG_F(INFO, "Machine option was passed in: %s", machine_str.c_str());
} else {
machine_str = machine_name_from_rom(bootrom_path);
if (machine_str.empty()) {
LOG_F(ERROR, "Could not autodetect machine");
return 0;
}
LOG_F(INFO, "Machine was autodetected as: %s", machine_str.c_str());
}
/* handle overriding of machine settings from CLI */
map<string, string> settings;
get_machine_settings(machine_str, settings);
CLI::App sa;
sa.allow_extras();
for (auto& s : settings) {
sa.add_option("--" + s.first, s.second);
}
sa.parse(app.remaining_for_passthrough()); /* TODO: handle exceptions! */
set_machine_settings(settings);
cout << "BootROM path: " << bootrom_path << endl;
cout << "Execution mode: " << execution_mode << endl;
return 0;
if (argc < 1) {
display_help();
@ -94,14 +172,14 @@ int main(int argc, char** argv) {
return 0;
}
else {
std::string rom_file = "rom.bin", disk_file = "disk.img";
int video_card_vendor = 0x1002, video_card_id = 0x4750;
for (int arg_loop = 1; arg_loop < argc; arg_loop++) {
string checker = argv[arg_loop];
cout << checker << endl;
if ((checker == "realtime") || (checker == "-realtime") || (checker == "/realtime")) {
loguru::g_stderr_verbosity = loguru::Verbosity_OFF;
loguru::g_preamble_date = false;
@ -119,23 +197,23 @@ int main(int argc, char** argv) {
loguru::g_preamble_thread = false;
loguru::init(argc, argv);
execution_mode = 1;
}
}
else if ((checker == "help") || (checker == "/help") || (checker == "-help")) {
display_help();
return 0;
}
}
else if ((checker == "pmg3") || (checker == "/pmg3") || (checker == "-pmg3")) {
machine_name = "PowerMacG3";
machine_specified = true;
}
}
else if ((checker == "pm6100") || (checker == "/pm6100") || (checker == "-pm6100")) {
machine_name = "PowerMac6100";
machine_specified = true;
}
}
else if ((checker == "machinehelp") || (checker == "/machinehelp") || (checker == "-machinehelp")) {
machine_name = "MachineHelp";
machine_specified = true;
}
}
else if ((checker == "ram") || (checker == "/ram") || (checker == "-ram")) {
arg_loop++;
string ram_banks = argv[arg_loop];
@ -143,7 +221,7 @@ int main(int argc, char** argv) {
for (int check_loop = 0; check_loop < ram_loop; check_loop++) {
sys_ram_size[check_loop] = stoi(argv[arg_loop]);
}
}
}
else if ((checker == "gfxmem") || (checker == "/gfxmem") || (checker == "-gfxmem")) {
arg_loop++;
string vram_amount = argv[arg_loop];
@ -154,23 +232,23 @@ int main(int argc, char** argv) {
arg_loop++;
rom_file = argv[arg_loop];
LOG_F(INFO, "ROM FILE will now be: %s", rom_file.c_str());
}
}
else if ((checker == "diskimg") || (checker == "/diskimg") || (checker == "-diskimg")) {
arg_loop++;
rom_file = argv[arg_loop];
LOG_F(INFO, "Load the DISK IMAGE from: %s", rom_file.c_str());
}
}
else if ((checker == "videocard") || (checker == "/videocard") || (checker == "-videocard")) {
arg_loop++;
string check_card = argv[arg_loop];
if (checker.compare("RagePro") == 0) {
video_card_vendor = 0x1002;
video_card_id = 0x4750;
}
}
else if (checker.compare("Rage128") == 0) {
video_card_vendor = 0x1002;
video_card_id = 0x5046;
}
}
else if (checker.compare("Radeon7000") == 0) {
video_card_vendor = 0x1002;
video_card_id = 0x5159;
@ -185,16 +263,16 @@ int main(int argc, char** argv) {
if (establish_machine_presets(rom_file.c_str(), machine_name, sys_ram_size, gfx_mem)) {
goto bail;
}
}
}
else if (machine_name.compare("PowerMac6100") == 0) {
LOG_F(ERROR, "Board not yet ready for: %s", machine_name.c_str());
return -1;
}
}
else {
display_recognized_machines();
return -1;
}
}
}
else {
if (create_machine_for_rom(rom_file.c_str(), sys_ram_size, gfx_mem)) {
goto bail;
@ -219,7 +297,7 @@ int main(int argc, char** argv) {
LOG_F(ERROR, "Invalid EXECUTION MODE");
return 1;
}
}
}
bail:
LOG_F(INFO, "Cleaning up...");

8258
thirdparty/CLI11/CLI11.hpp vendored Normal file

File diff suppressed because it is too large Load Diff