Add config
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
parent
ff06adaedb
commit
c5acf56209
@ -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
32
config.toml
Normal 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
273
main.cpp
@ -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());
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user