Add config

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
Slendi 2024-06-20 19:05:36 +03:00
parent ff06adaedb
commit c5acf56209
4 changed files with 18002 additions and 100 deletions

View File

@ -1,11 +1,17 @@
#include <pspkernel.h>
int exit_callback(int arg1, int arg2, void *common) {
(void)arg1;
(void)arg2;
(void)common;
sceKernelExitGame();
return 0;
}
int callback_thread(SceSize args, void *argp) {
(void)args;
(void)argp;
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", (SceKernelCallbackFunction)exit_callback, NULL);

32
config.toml Normal file
View File

@ -0,0 +1,32 @@
[[keymap]]
name = 'Rogue'
[ keymap.normal ]
KEY_1 = 'Cross'
KEY_2 = 'Up'
KEY_3 = 'Triangle'
KEY_4 = 'Left'
KEY_5 = 'Circle'
KEY_6 = 'Right'
KEY_7 = 'Square'
KEY_8 = 'Down'
KEY_9 = 'Select'
[ keymap.shifted ]
KEY_A = 'Left'
KEY_B = 'Right'
KEY_C = 'Square'
KEY_D = 'Triangle'
KEY_E = 'Cross'
KEY_F = 'Circle'
KEY_0 = 'Down'
[[keymap]]
name = 'WASD'
[ keymap.normal ]
KEY_1 = 'Cross'
KEY_2 = 'Triangle'
KEY_3 = 'Circle'
KEY_5 = 'Up'
KEY_7 = 'Left'
KEY_8 = 'Down'
KEY_9 = 'Right'
[ keymap.shifted ]

273
main.cpp
View File

@ -17,6 +17,7 @@
#include <stack>
#include <string>
#include <thread>
#include <unordered_map>
#include <vector>
#include <unistd.h>
@ -24,7 +25,11 @@
#include "callback.h"
#include "util.h"
#include "toml.hpp"
namespace fs = std::filesystem;
using namespace std::string_literals;
using namespace std::string_view_literals;
PSP_MODULE_INFO("psp-chip8", 0, 1, 1);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
@ -141,21 +146,103 @@ enum Key {
KEY_F,
};
struct KeyMap {
std::string name;
int keys_normal[4 * 4] = { 0 };
int keys_shift[4 * 4] = { 0 };
};
struct Config {
Config(toml::table const &table);
std::vector<KeyMap> mappings;
};
std::unordered_map<std::string, int> key_map = {
{ "Cross", PSP_CTRL_CROSS },
{ "Triangle", PSP_CTRL_TRIANGLE },
{ "Circle", PSP_CTRL_CIRCLE },
{ "Square", PSP_CTRL_SQUARE },
{ "Up", PSP_CTRL_UP },
{ "Down", PSP_CTRL_DOWN },
{ "Left", PSP_CTRL_LEFT },
{ "Right", PSP_CTRL_RIGHT },
{ "Select", PSP_CTRL_SELECT },
};
std::unordered_map<std::string_view, int> indexes = {
{ "KEY_1"sv, KEY_1 },
{ "KEY_2"sv, KEY_2 },
{ "KEY_3"sv, KEY_3 },
{ "KEY_C"sv, KEY_C },
{ "KEY_4"sv, KEY_4 },
{ "KEY_5"sv, KEY_5 },
{ "KEY_6"sv, KEY_6 },
{ "KEY_D"sv, KEY_D },
{ "KEY_7"sv, KEY_7 },
{ "KEY_8"sv, KEY_8 },
{ "KEY_9"sv, KEY_9 },
{ "KEY_E"sv, KEY_E },
{ "KEY_A"sv, KEY_A },
{ "KEY_0"sv, KEY_0 },
{ "KEY_B"sv, KEY_B },
{ "KEY_F"sv, KEY_F },
};
void parse_keys(toml::table const &table, int *keys) {
for (auto const &[key, value] : table) {
if (value.is_string()) {
std::string value_str = *value.value<std::string>();
auto it = key_map.find(value_str);
if (it != key_map.end()) {
auto it_key = indexes.find(key.str());
if (it_key != indexes.end())
keys[it_key->second] = it->second;
}
}
}
}
Config::Config(toml::table const &table) {
if (auto keymaps = table["keymap"].as_array()) {
int i = 1;
for (auto const &el : *keymaps) {
if (!el.is_table()) {
std::cerr << "Error: Element is not a table" << std::endl;
continue;
}
auto const &map_table = *el.as_table();
KeyMap map;
if (auto name = map_table["name"].value<std::string>())
map.name = *name;
else
map.name = std::string("Unnamed") + std::to_string(i++);
if (auto normal = map_table["normal"].as_table())
parse_keys(*normal, map.keys_normal);
if (auto shifted = map_table["shifted"].as_table())
parse_keys(*shifted, map.keys_shift);
mappings.push_back(map);
}
}
}
class Keypad {
public:
enum class Map {
Rogue,
WASD,
END,
};
std::vector<KeyMap> mappings;
void update(void);
bool keys[4 * 4] = { 0 };
bool start() const { return m_start; }
bool second() const { return m_second; }
Map map() const { return m_map; }
bool start() const { return m_start; }
bool second() const { return m_second; }
std::string const &map_name() const { return mappings[m_map].name; }
private:
SceCtrlData m_pad;
@ -163,76 +250,32 @@ private:
bool m_start = false;
bool m_second = false;
Map m_map = Map::Rogue;
bool m_prev_rtrigger = false;
size_t m_map = 0;
bool m_prev_rtrigger = false;
};
char const *KeypadMapCString(Keypad::Map map) {
switch (map) {
case Keypad::Map::Rogue:
return "Rogue";
case Keypad::Map::WASD:
return "WASD";
case Keypad::Map::END:
return "Invalid";
}
return "UNKNOWN";
}
void Keypad::update(void) {
sceCtrlReadBufferPositive(&m_pad, 1);
for (auto &key : keys)
key = false;
if (!m_pad.Buttons)
return;
if (!m_prev_rtrigger && (m_pad.Buttons & PSP_CTRL_RTRIGGER))
m_map = (m_map + 1) % mappings.size();
if (!m_prev_rtrigger && (m_pad.Buttons & PSP_CTRL_RTRIGGER)) {
int c = (int)m_map;
c++;
c %= (int)Map::END;
m_map = (Map)c;
}
if (m_map == Map::Rogue) {
if (m_pad.Buttons & PSP_CTRL_LTRIGGER) {
keys[KEY_A] = m_pad.Buttons & PSP_CTRL_LEFT;
keys[KEY_B] = m_pad.Buttons & PSP_CTRL_RIGHT;
keys[KEY_C] = m_pad.Buttons & PSP_CTRL_SQUARE;
keys[KEY_D] = m_pad.Buttons & PSP_CTRL_TRIANGLE;
keys[KEY_E] = m_pad.Buttons & PSP_CTRL_CROSS;
keys[KEY_F] = m_pad.Buttons & PSP_CTRL_CIRCLE;
m_second = true;
} else {
keys[KEY_1] = m_pad.Buttons & PSP_CTRL_CROSS;
keys[KEY_2] = m_pad.Buttons & PSP_CTRL_UP;
keys[KEY_3] = m_pad.Buttons & PSP_CTRL_TRIANGLE;
keys[KEY_4] = m_pad.Buttons & PSP_CTRL_LEFT;
keys[KEY_5] = m_pad.Buttons & PSP_CTRL_CIRCLE;
keys[KEY_6] = m_pad.Buttons & PSP_CTRL_RIGHT;
keys[KEY_7] = m_pad.Buttons & PSP_CTRL_SQUARE;
keys[KEY_8] = m_pad.Buttons & PSP_CTRL_DOWN;
keys[KEY_9] = m_pad.Buttons & PSP_CTRL_SELECT;
m_second = false;
}
} else if (m_map == Map::WASD) {
if (m_pad.Buttons & PSP_CTRL_LTRIGGER) {
m_second = true;
} else {
keys[KEY_1] = m_pad.Buttons & PSP_CTRL_CROSS;
keys[KEY_2] = m_pad.Buttons & PSP_CTRL_TRIANGLE;
keys[KEY_3] = m_pad.Buttons & PSP_CTRL_CIRCLE;
keys[KEY_5] = m_pad.Buttons & PSP_CTRL_UP;
keys[KEY_7] = m_pad.Buttons & PSP_CTRL_LEFT;
keys[KEY_8] = m_pad.Buttons & PSP_CTRL_DOWN;
keys[KEY_9] = m_pad.Buttons & PSP_CTRL_RIGHT;
m_second = false;
}
if (!m_pad.Buttons || mappings.empty())
goto end;
m_second = m_pad.Buttons & PSP_CTRL_LTRIGGER;
for (int i = 0; i < 4 * 4; i++) {
if (m_second)
keys[i] = m_pad.Buttons & mappings[m_map].keys_shift[i];
else
keys[i] = m_pad.Buttons & mappings[m_map].keys_normal[i];
}
end:
m_prev_rtrigger = m_pad.Buttons & PSP_CTRL_RTRIGGER;
m_start = m_pad.Buttons & PSP_CTRL_START;
}
@ -377,7 +420,7 @@ void CHIP8::step() {
break;
}
case 0x5: { // SUB Vx, Vy Set Vx = Vx - Vy, set VF = NOT borrow.
bool not_borrow = this->registers[X] > this->registers[Y];
bool not_borrow = this->registers[X] > this->registers[Y] ? 1 : 0;
this->registers[X] -= this->registers[Y];
this->registers[0xF] = not_borrow;
break;
@ -389,7 +432,7 @@ void CHIP8::step() {
break;
}
case 0x7: { // SUBN Vx, Vy Set Vx = Vy - Vx, set VF = NOT borrow.
bool not_borrow = this->registers[X] < this->registers[Y];
bool not_borrow = this->registers[Y] > this->registers[X] ? 1 : 0;
this->registers[X] = this->registers[Y] - this->registers[X];
this->registers[0xF] = not_borrow;
break;
@ -600,21 +643,23 @@ enum class Screen {
Emulator,
};
void get_files(fs::path path, std::vector<fs::path> &list, std::vector<int> &sizes,
std::vector<bool> &is_dir) {
list.clear();
sizes.clear();
is_dir.clear();
struct FileInfo {
fs::path path;
int size;
bool is_dir;
};
void get_files(fs::path path, std::vector<FileInfo> &list) {
list.clear();
list.push_back(FileInfo { fs::path { ".." }, 0, true });
list.push_back(fs::path { ".." });
sizes.push_back(0);
is_dir.push_back(true);
for (auto const &entry : fs::directory_iterator(path)) {
bool dir = true;
bool dir = entry.is_directory();
int fs = 0;
if (entry.is_regular_file()) {
fs = fs::file_size(entry.path());
dir = false;
fs = static_cast<int>(fs::file_size(entry.path()));
if (fs > (0x1000 - 0x200))
continue;
if (entry.path().filename().string() == "PARAM.SFO")
@ -623,16 +668,21 @@ void get_files(fs::path path, std::vector<fs::path> &list, std::vector<int> &siz
continue;
if (entry.path().filename().string() == "cmake_install.cmake")
continue;
} else if (!entry.is_directory())
} else if (!dir) {
continue;
}
if (entry.path().filename().string() == "CMakeFiles")
continue;
is_dir.push_back(dir);
list.push_back(entry.path().filename().string());
sizes.push_back(fs);
list.push_back(FileInfo { entry.path().filename(), fs, dir });
}
std::sort(list.begin(), list.end(), [](FileInfo const &a, FileInfo const &b) {
if (a.is_dir != b.is_dir)
return a.is_dir > b.is_dir;
return a.path.string() < b.path.string();
});
}
fs::path resolve_path(fs::path const &path) {
@ -683,6 +733,9 @@ int main(void) {
pspDebugScreenInit();
setup_callbacks();
Config cfg(toml::parse_file("config.toml"));
g_chip8.keypad.mappings = cfg.mappings;
scePowerUnlock(0);
scePowerSetClockFrequency(333, 333, 166);
@ -730,13 +783,11 @@ int main(void) {
auto last = std::chrono::high_resolution_clock::now();
std::vector<fs::path> file_list;
std::vector<int> file_sizes;
std::vector<bool> file_is_dir;
std::vector<FileInfo> file_list;
fs::path path { "." };
ssize_t menu_y = 0;
get_files(path, file_list, file_sizes, file_is_dir);
get_files(path, file_list);
SceUID chip_thread_id
= sceKernelCreateThread("chip_thread", &chip_thread, 0x18, 0x10000, 0, nullptr);
@ -834,11 +885,11 @@ int main(void) {
}
if ((pad.Buttons & PSP_CTRL_CROSS) && !(prev_pad.Buttons & PSP_CTRL_CROSS)) {
fs::path newp = path / file_list[menu_y];
fs::path newp = path / file_list[menu_y].path;
if (fs::is_directory(newp)) {
path = resolve_path(newp);
get_files(path, file_list, file_sizes, file_is_dir);
get_files(path, file_list);
} else {
auto data = load_binary_file(newp.c_str());
if (data.has_value()) {
@ -891,25 +942,47 @@ int main(void) {
pspDebugScreenSetTextColor(0xFF222222);
for (int i = 0; i < MAX_SCREEN_X; i++)
pspDebugScreenPrintf("=");
ssize_t i = 0;
for (auto &entry : file_list) {
static ssize_t scroll_off = 0;
if (menu_y - scroll_off >= MAX_SCREEN_Y - 3)
scroll_off++;
if (menu_y < scroll_off)
scroll_off--;
if (scroll_off < 0)
scroll_off = 0;
for (ssize_t i = scroll_off; i < file_list.size() && i < scroll_off + MAX_SCREEN_Y - 3;
i++) {
auto &entry = file_list[i];
auto &path = entry.path;
if (i == menu_y)
pspDebugScreenSetTextColor(0xFF113311);
else
pspDebugScreenSetTextColor(0xFFFFFFFF);
pspDebugScreenSetTextColor(0xFF2b7311);
else {
if (entry.is_dir)
pspDebugScreenSetTextColor(0xFF750e0b);
else
pspDebugScreenSetTextColor(0xFFFFFFFF);
}
if (file_is_dir[i])
pspDebugScreenPrintf("D %-66s\n", entry.c_str());
if (entry.is_dir)
pspDebugScreenPrintf("%-68s", path.c_str());
else
pspDebugScreenPrintf("F %-46s%20d\n", entry.c_str(), file_sizes[i]);
i++;
pspDebugScreenPrintf("%-63s%5d", path.c_str(), entry.size);
}
pspDebugScreenSetXY(0, MAX_SCREEN_Y - 1);
pspDebugScreenSetTextColor(0xFF222222);
for (int i = 0; i < MAX_SCREEN_X; i++)
pspDebugScreenPrintf("=");
pspDebugScreenSetTextColor(0xFFFFFFFF);
pspDebugScreenPrintf(
"Select(X), Move(UP/DOWN), DecHold(LT), StepSkips(/\\), Delay([])");
} else {
pspDebugScreenPrintf("%sMessage: %s Map: %s SK: %d D: %dms File: %s",
g_chip8.halted ? "HALTED " : "", g_chip8.message.c_str(),
KeypadMapCString(g_chip8.keypad.map()), g_step_skips, g_artificial_delay,
g_chip8.keypad.map_name().c_str(), g_step_skips, g_artificial_delay,
filename.c_str());
}

17791
toml.hpp Normal file

File diff suppressed because it is too large Load Diff