mirror of
https://github.com/iaddis/metalnes.git
synced 2024-06-02 19:38:28 -04:00
312 lines
7 KiB
C++
312 lines
7 KiB
C++
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <vector>
|
|
#include <queue>
|
|
#include <mutex>
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
|
|
#include "Application.h"
|
|
#include "Core/Log.h"
|
|
#include "Core/File.h"
|
|
#include "render/context.h"
|
|
|
|
#include "imgui_support.h"
|
|
|
|
#include "Core/Path.h"
|
|
#include "Core/StopWatch.h"
|
|
#include "Core/String.h"
|
|
#include "Core/File.h"
|
|
#include "metalnes/system.h"
|
|
#include "metalnes/nesrom.h"
|
|
|
|
#include "UnitTests.h"
|
|
#include "metalnes/wire_module.h"
|
|
#include "metalnes/handler_log.h"
|
|
|
|
using namespace metalnes;
|
|
|
|
|
|
static std::string s_resource_dir;
|
|
static std::string s_data_dir;
|
|
static std::string s_system_def_dir;
|
|
|
|
static std::vector<std::string> s_rom_dirs;
|
|
static std::vector<system_state_ptr> _system_list;
|
|
|
|
|
|
std::string getSystemDefDir()
|
|
{
|
|
return s_system_def_dir;
|
|
}
|
|
|
|
|
|
struct RomInfo
|
|
{
|
|
std::string path;
|
|
std::string name;
|
|
};
|
|
|
|
static std::vector<RomInfo> s_rom_list;
|
|
|
|
static nesrom_ptr load_rom(std::string rom_name)
|
|
{
|
|
for (auto rom_dir : s_rom_dirs)
|
|
{
|
|
std::string rom_path = Core::Path::Combine(rom_dir, rom_name);
|
|
|
|
nesrom_ptr rom = nesrom::LoadFromFile(rom_path);
|
|
if (rom) {
|
|
printf("Loaded rom from '%s'\n", rom_path.c_str());
|
|
return rom;
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool load_system(std::string rom_name)
|
|
{
|
|
nesrom_ptr rom = load_rom(rom_name);
|
|
if (!rom)
|
|
{
|
|
printf("Could not load rom '%s'\n", rom_name.c_str());
|
|
return false;
|
|
}
|
|
|
|
|
|
system_state_ptr system = system_state::Create(s_system_def_dir, s_data_dir, rom);
|
|
if (!system)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// one system at a time....
|
|
_system_list.clear();
|
|
|
|
_system_list.push_back(system);
|
|
return true;
|
|
}
|
|
|
|
|
|
static bool _window_open_romselector = true;
|
|
static int s_selected_rom = -1;
|
|
|
|
void onGuiRomSelector()
|
|
{
|
|
|
|
ImGuiWindowFlags window_flags = 0; //ImGuiWindowFlags_MenuBar;
|
|
// ImGui::SetNextWindowPos(ImVec2(0,0)); //, ImGuiCond_Always);
|
|
// ImGui::SetNextWindowContentSize(ImVec2(800,600)); //, ImGuiCond_Always);
|
|
if (!ImGui::Begin("Rom Browser", &_window_open_romselector, window_flags))
|
|
{
|
|
ImGui::End();
|
|
return;
|
|
}
|
|
|
|
auto &rom_list = s_rom_list;
|
|
|
|
if (rom_list.empty())
|
|
{
|
|
// list all roms
|
|
for (auto dir : s_rom_dirs)
|
|
{
|
|
std::vector<std::string> files;
|
|
Core::Directory::GetDirectoryFiles(dir, files, true);
|
|
|
|
std::sort( files.begin(), files.end());
|
|
|
|
for (auto file : files)
|
|
{
|
|
if (Core::Path::GetExtensionLower(file) == ".nes")
|
|
{
|
|
std::string name = file.substr(dir.size());
|
|
rom_list.push_back( {file, name });
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (ImGui::Button("Load"))
|
|
{
|
|
if (s_selected_rom >= 0)
|
|
{
|
|
load_system( rom_list[s_selected_rom].path );
|
|
}
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
ImGuiTableFlags flags = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
|
|
// const float TEXT_BASE_WIDTH = 16.0f;
|
|
ImVec2 size = ImVec2(0,0);
|
|
if (ImGui::BeginTable("##rom_table", 1, flags, size))
|
|
{
|
|
ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible
|
|
// ImGui::TableSetupColumn("X", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 1);
|
|
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_None);
|
|
ImGui::TableHeadersRow();
|
|
|
|
|
|
// Demonstrate using clipper for large vertical lists
|
|
ImGuiListClipper clipper;
|
|
clipper.Begin( (int)rom_list.size() );
|
|
while (clipper.Step())
|
|
{
|
|
for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++)
|
|
{
|
|
ImGui::TableNextRow();
|
|
ImGui::TableNextColumn();
|
|
|
|
bool selected = (s_selected_rom == row);
|
|
if (ImGui::Selectable( rom_list[row].name.c_str(), selected, ImGuiSelectableFlags_AllowDoubleClick | ImGuiSelectableFlags_SpanAllColumns))
|
|
{
|
|
s_selected_rom = row;
|
|
|
|
if (ImGui::IsMouseDoubleClicked(0))
|
|
load_system( rom_list[s_selected_rom].path );
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
ImGui::EndTable();
|
|
}
|
|
|
|
ImGui::End();
|
|
|
|
}
|
|
|
|
|
|
extern bool _demo_window_open;
|
|
|
|
void AppOnGui(render::ContextPtr context)
|
|
{
|
|
// show rom selector
|
|
onGuiRomSelector();
|
|
|
|
// onGuiUnitTests();
|
|
|
|
// ongui all the systems
|
|
int to_erase = -1;
|
|
int i = 0;
|
|
for (auto system : _system_list)
|
|
{
|
|
if (!system->onGui(context))
|
|
{
|
|
to_erase = i;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
if (to_erase >= 0)
|
|
{
|
|
// erase to_erase from system list
|
|
_system_list.erase(_system_list.begin() + to_erase);
|
|
|
|
}
|
|
|
|
|
|
if (_demo_window_open) {
|
|
ImGui::ShowDemoWindow(&_demo_window_open);
|
|
}
|
|
}
|
|
|
|
namespace metalnes {
|
|
void run_tests();
|
|
}
|
|
|
|
void AppInit(render::ContextPtr context, std::string resource_dir, std::string data_dir, const std::vector<std::string> &args)
|
|
{
|
|
ImGuiSupport_Init(context, resource_dir, data_dir );
|
|
|
|
|
|
s_resource_dir = resource_dir;
|
|
s_data_dir = data_dir;
|
|
s_system_def_dir = Core::Path::Combine(resource_dir, "data/system-def");
|
|
|
|
s_rom_dirs.push_back( Core::Path::Combine( getenv("HOME"), "dev/nes/roms/") );
|
|
s_rom_dirs.push_back( Core::Path::Combine(resource_dir, "data/roms/") );
|
|
|
|
#if 1
|
|
|
|
if (!args.empty())
|
|
{
|
|
for (auto arg : args)
|
|
{
|
|
load_system(arg);
|
|
}
|
|
}
|
|
|
|
if (args.empty())
|
|
{
|
|
|
|
|
|
// load_system("NES Test Cart (Official Nintendo) (U) [!].nes");
|
|
load_system("Super Mario Bros. (W) [!].nes");
|
|
// load_system("Donkey Kong (JU).nes");
|
|
// load_system("Excitebike (JU).nes");
|
|
|
|
// load_system("nes-test-roms/apu_mixer/square.nes");
|
|
|
|
if (_system_list.empty())
|
|
{
|
|
load_system("nes-test-roms/instr_misc/rom_singles/01-abs_x_wrap.nes");
|
|
// load_system("nes-test-roms/instr_misc/rom_singles/02-branch_wrap.nes");
|
|
// load_system("nes-test-roms/instr_misc/rom_singles/03-dummy_reads.nes");
|
|
// load_system("nes-test-roms/instr_misc/rom_singles/04-dummy_reads_apu.nes");
|
|
|
|
}
|
|
}
|
|
#else
|
|
// run_tests();
|
|
RunUnitTests();
|
|
#endif
|
|
}
|
|
|
|
void AppShutdown()
|
|
{
|
|
_system_list.clear();
|
|
|
|
ImGuiSupport_Shutdown();
|
|
|
|
}
|
|
|
|
|
|
bool AppShouldQuit()
|
|
{
|
|
for (auto system : _system_list)
|
|
{
|
|
if (system->shouldQuit())
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void AppRender(render::ContextPtr context)
|
|
{
|
|
if (context)
|
|
{
|
|
ImGuiSupport_NewFrame();
|
|
AppOnGui(context);
|
|
context->SetRenderTarget(nullptr, "ImGui", render::LoadAction::Clear, Color4F(0,0,0,0));
|
|
ImGuiSupport_Render();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|