Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7f99f82
iris: Minor fixes
allkern Sep 19, 2025
718333a
input: Map keys to analog stick
allkern Sep 19, 2025
0d7b5d5
frontend: Implement performance overlay
allkern Sep 19, 2025
4cc4f22
timers: Initial T4 prescaler implementation
allkern Sep 19, 2025
33f755d
spu2: Fix SPU IRQs and implement capture buffers
allkern Sep 19, 2025
49901ad
cdvd: Implement proper EEPROM support
allkern Sep 19, 2025
986ee60
renderer: Implement debug stats
allkern Sep 19, 2025
d83803d
gs: Implement proper frame timings
allkern Sep 19, 2025
523e025
ee: Implement remaining MMI instructions
allkern Sep 19, 2025
aa98a37
ps2: Run scheduler at real EE speed
allkern Sep 19, 2025
0d588bf
dmac: Fix SPR_TO NULL dereference
allkern Sep 19, 2025
1244de2
timers: Don't update timers when CUE is reset
allkern Sep 19, 2025
cedb547
misc: Add signed fields to uint128 union
allkern Sep 19, 2025
6dbb4bc
frontend: Show ImGui framerate on statusbar
allkern Sep 19, 2025
a9b082a
frontend: Add remaining icons
allkern Sep 19, 2025
4cd9017
frontend: Show correct bss address on module viewer
allkern Sep 19, 2025
9b97fe8
iris: Add Roboto Black font (performance overlay)
allkern Sep 19, 2025
9309ebc
iris: Add timescale setting
allkern Oct 1, 2025
8f5ac32
iris: Misc cleanup
allkern Oct 1, 2025
e69f737
renderer: Fix Z format blits
allkern Oct 1, 2025
fcda371
gs: Fix double SIGNAL writes
allkern Oct 1, 2025
ad8b08b
vu: Implement hazard detection
allkern Oct 1, 2025
58450a4
ee: Implement INTC/CSR spin skip
allkern Oct 1, 2025
a1bbc8d
dmac: Fix PATH2 garbage data
allkern Oct 1, 2025
45426e1
iris: Reimplement breakpoints
allkern Oct 1, 2025
5c1439e
vif: Fix STAT and CODE reads after IRQs
allkern Oct 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@
[submodule "incbin"]
path = incbin
url = https://github.com/graphitemaster/incbin
[submodule "implot"]
path = implot
url = https://github.com/epezent/implot
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ target_sources(iris PRIVATE
frontend/ui/memory_card_tool.cpp
frontend/ui/menubar.cpp
frontend/ui/modules.cpp
frontend/ui/overlay.cpp
frontend/ui/pad.cpp
frontend/ui/settings.cpp
frontend/ui/spu2.cpp
Expand Down Expand Up @@ -171,13 +172,17 @@ target_sources(iris PRIVATE
imgui/imgui_tables.cpp
imgui/imgui_widgets.cpp
imgui/backends/imgui_impl_sdl3.cpp
imgui/backends/imgui_impl_sdlgpu3.cpp)
imgui/backends/imgui_impl_sdlgpu3.cpp
implot/implot_demo.cpp
implot/implot_items.cpp
implot/implot.cpp)

add_subdirectory(SDL EXCLUDE_FROM_ALL)

target_include_directories(iris PRIVATE
imgui
imgui/backends
implot
SDL/include
frontend
incbin
Expand Down
2 changes: 2 additions & 0 deletions compat.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
"Klonoa 2 - Lunatea's Veil (USA)" - Doesn't work on Release builds (!), requires 16-bit DMAC writes
"Namco Museum 50th Anniversary (USA)" - Requires MFIFO
"R-Type Final (Japan)" - Requires MFIFO
"Sega Ages 2500 Series Vol. 23 - Sega Memorial Selection (Japan)" - GIF DMA read from NULL
"Sega Genesis Collection (USA)" - Works, "forgets" to change the videomode causing wrong graphics at startup (needs 24-bit 640x448 interlaced?)
"Simpsons, The - Hit & Run (USA)" - Needs MFIFO
"Tekken 4 (USA)" - Needs MFIFO
"Tekken Tag Tournament (USA) (v1.00)" - Needs MFIFO
"Thunder Force VI (Japan)" - Crashes on an invalid GIF DMA address when starting up (compare against Dobie)
"Virtua Fighter 4 - Evolution (USA)" - Works, uses filling mode
"Virtua Fighter - Cyber Generation - Judgment Six no Yabou (Japan)" - PMTHL unimplemented
"We Love Katamari (USA)" - Uses filling mode, gets stuck trying to play an FMV after the Namco logo?
11 changes: 11 additions & 0 deletions frontend/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ void handle_keydown_event(iris::instance* iris, SDL_KeyboardEvent& key) {
case SDLK_0: {
ps2_iop_intc_irq(iris->ps2->iop_intc, IOP_INTC_USB);
} break;
case SDLK_I: ds_analog_change(iris->ds[0], DS_AX_LEFT_V, 0xff); break;
case SDLK_J: ds_analog_change(iris->ds[0], DS_AX_LEFT_H, 0); break;
case SDLK_K: ds_analog_change(iris->ds[0], DS_AX_LEFT_V, 0); break;
case SDLK_L: ds_analog_change(iris->ds[0], DS_AX_LEFT_H, 0xff); break;
}

uint16_t mask = map_button(key.key);
Expand All @@ -159,6 +163,13 @@ void handle_keydown_event(iris::instance* iris, SDL_KeyboardEvent& key) {
}

void handle_keyup_event(iris::instance* iris, SDL_KeyboardEvent& key) {
switch (key.key) {
case SDLK_I: ds_analog_change(iris->ds[0], DS_AX_LEFT_V, 0x80); break;
case SDLK_J: ds_analog_change(iris->ds[0], DS_AX_LEFT_H, 0x80); break;
case SDLK_K: ds_analog_change(iris->ds[0], DS_AX_LEFT_V, 0x80); break;
case SDLK_L: ds_analog_change(iris->ds[0], DS_AX_LEFT_H, 0x80); break;
}

uint16_t mask = map_button(key.key);

ds_button_release(iris->ds[0], mask);
Expand Down
1 change: 1 addition & 0 deletions frontend/iris.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ void update_window(iris::instance* iris) {
// if (iris->show_gamelist) show_gamelist(iris);
if (iris->show_imgui_demo) ShowDemoWindow(&iris->show_imgui_demo);
if (iris->show_bios_setting_window) show_bios_setting_window(iris);
if (iris->show_overlay) show_overlay(iris);

// Display little pause icon in the top right corner
if (iris->pause) {
Expand Down
40 changes: 40 additions & 0 deletions frontend/iris.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,40 @@ struct elf_symbol {
uint32_t size;
};

// Event -> Action
enum {
INPUT_ACTION_PRESS_BUTTON,
INPUT_ACTION_RELEASE_BUTTON,
INPUT_ACTION_MOVE_AXIS
};

enum {
INPUT_CONTROLLER_DUALSHOCK2

// Large To-do list here, we're missing the Namco GunCon
// controllers, JogCon, NegCon, Buzz! Buzzer, the Train
// controllers, Taiko Drum Master controller, the Dance Dance
// Revolution mat, Guitar Hero controllers, etc.
};

// struct input_action {
// int action;

// union {
// uint32_t button;
// uint8_t axis;
// };
// };

// class input_device {
// int controller;

// public:
// void set_controller(int controller);
// int get_controller();
// virtual input_action map_event(SDL_Event* event) = 0;
// };

struct instance {
SDL_Window* window = nullptr;
SDL_GPUDevice* device = nullptr;
Expand Down Expand Up @@ -101,6 +135,7 @@ struct instance {
ImFont* font_body = nullptr;
ImFont* font_icons = nullptr;
ImFont* font_icons_big = nullptr;
ImFont* font_black = nullptr;

std::string elf_path = "";
std::string boot_path = "";
Expand Down Expand Up @@ -149,6 +184,7 @@ struct instance {
bool show_memory_card_tool = false;
bool show_imgui_demo = false;
bool show_vu_disassembler = false;
bool show_overlay = false;

// Special windows
bool show_bios_setting_window = false;
Expand Down Expand Up @@ -177,6 +213,7 @@ struct instance {
int menubar_height = 0;
bool mute = false;
float volume = 1.0f;
int timescale = 8;

bool limit_fps = true;
float fps_cap = 60.0f;
Expand All @@ -192,6 +229,8 @@ struct instance {
struct ds_state* ds[2] = { nullptr };
struct mcd_state* mcd[2] = { nullptr };

// input_device* device[2];

float drop_file_alpha = 0.0f;
float drop_file_alpha_delta = 0.0f;
float drop_file_alpha_target = 0.0f;
Expand Down Expand Up @@ -239,6 +278,7 @@ void show_settings(iris::instance* iris);
void show_pad_debugger(iris::instance* iris);
void show_symbols(iris::instance* iris);
void show_threads(iris::instance* iris);
void show_overlay(iris::instance* iris);
void show_memory_card_tool(iris::instance* iris);
void show_bios_setting_window(iris::instance* iris);
// void show_gamelist(iris::instance* iris);
Expand Down
15 changes: 13 additions & 2 deletions frontend/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ int parse_toml_settings(iris::instance* iris) {
iris->integer_scaling = display["integer_scaling"].value_or(false);
iris->scale = display["scale"].value_or(1.5f);
iris->renderer_backend = display["renderer"].value_or(RENDERER_SOFTWARE_THREAD);
iris->window_width = display["window_width"].value_or(960);
iris->window_height = display["window_height"].value_or(720);

auto audio = tbl["audio"];
iris->mute = audio["mute"].value_or(false);
Expand All @@ -108,10 +110,13 @@ int parse_toml_settings(iris::instance* iris) {
iris->show_status_bar = debugger["show_status_bar"].value_or(true);
iris->show_pad_debugger = debugger["show_pad_debugger"].value_or(false);
iris->show_threads = debugger["show_threads"].value_or(false);
iris->show_overlay = debugger["show_overlay"].value_or(false);

// iris->show_symbols = debugger["show_symbols"].value_or(false);
iris->show_breakpoints = debugger["show_breakpoints"].value_or(false);
iris->show_imgui_demo = debugger["show_imgui_demo"].value_or(false);
iris->skip_fmv = debugger["skip_fmv"].value_or(false);
iris->timescale = debugger["timescale"].value_or(8);

toml::array* recents = tbl["recents"]["array"].as_array();

Expand All @@ -123,6 +128,8 @@ int parse_toml_settings(iris::instance* iris) {
renderer_set_integer_scaling(iris->ctx, iris->integer_scaling);
renderer_set_scale(iris->ctx, iris->scale);

ps2_set_timescale(iris->ps2, iris->timescale);

ee_set_fmv_skip(iris->ps2->ee, iris->skip_fmv);

return 0;
Expand Down Expand Up @@ -282,15 +289,19 @@ void close_settings(iris::instance* iris) {
{ "show_breakpoints", iris->show_breakpoints },
{ "show_threads", iris->show_threads },
{ "show_imgui_demo", iris->show_imgui_demo },
{ "skip_fmv", iris->skip_fmv }
{ "show_overlay", iris->show_overlay },
{ "skip_fmv", iris->skip_fmv },
{ "timescale", iris->timescale }
} },
{ "display", toml::table {
{ "scale", iris->scale },
{ "aspect_mode", iris->aspect_mode },
{ "integer_scaling", iris->integer_scaling },
{ "fullscreen", iris->fullscreen },
{ "bilinear", iris->bilinear },
{ "renderer", iris->renderer_backend }
{ "renderer", iris->renderer_backend },
{ "window_width", iris->window_width },
{ "window_height", iris->window_height }
} },
{ "audio", toml::table {
{ "mute", iris->mute },
Expand Down
58 changes: 53 additions & 5 deletions frontend/ui/menubar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ void show_main_menubar(iris::instance* iris) {
ImGui::EndMenu();
}

if (BeginMenu("Scale")) {
if (BeginMenu(ICON_MS_CROP " Scale")) {
for (int i = 2; i <= 6; i++) {
char buf[16]; snprintf(buf, 16, "%.1fx", (float)i * 0.5f);

Expand All @@ -248,7 +248,7 @@ void show_main_menubar(iris::instance* iris) {
ImGui::EndMenu();
}

if (BeginMenu("Aspect mode")) {
if (BeginMenu(ICON_MS_ASPECT_RATIO " Aspect mode")) {
for (int i = 0; i < 7; i++) {
if (Selectable(aspect_mode_names[i], iris->aspect_mode == i)) {
iris->aspect_mode = i;
Expand All @@ -260,7 +260,7 @@ void show_main_menubar(iris::instance* iris) {
ImGui::EndMenu();
}

if (BeginMenu("Scaling filter")) {
if (BeginMenu(ICON_MS_FILTER " Scaling filter")) {
if (Selectable("Nearest", !iris->bilinear)) {
iris->bilinear = false;

Expand All @@ -276,11 +276,43 @@ void show_main_menubar(iris::instance* iris) {
ImGui::EndMenu();
}

if (MenuItem("Integer scaling", nullptr, &iris->integer_scaling)) {
if (BeginMenu(ICON_MS_ASPECT_RATIO " Window size")) {
const char* sizes[] = {
"640x480",
"800x600",
"960x720",
"1024x768",
"1280x720",
"1280x800"
};

int widths[] = {
640, 800, 960, 1024, 1280, 1280
};

int heights[] = {
480, 600, 720, 768, 720, 800
};

for (int i = 0; i < 6; i++) {
bool selected = iris->window_width == widths[i] && iris->window_height == heights[i];

if (MenuItem(sizes[i], nullptr, selected)) {
iris->window_width = widths[i];
iris->window_height = heights[i];

SDL_SetWindowSize(iris->window, iris->window_width, iris->window_height);
}
}

ImGui::EndMenu();
}

if (MenuItem(ICON_MS_SPEED_2X " Integer scaling", nullptr, &iris->integer_scaling)) {
renderer_set_integer_scaling(iris->ctx, iris->integer_scaling);
}

if (MenuItem("Fullscreen", "F11", &iris->fullscreen)) {
if (MenuItem(ICON_MS_FULLSCREEN " Fullscreen", "F11", &iris->fullscreen)) {
SDL_SetWindowFullscreen(iris->window, iris->fullscreen);
}

Expand Down Expand Up @@ -385,9 +417,24 @@ void show_main_menubar(iris::instance* iris) {
if (MenuItem(ICON_MS_MEMORY " Memory viewer", NULL, &iris->show_memory_viewer));
if (MenuItem(ICON_MS_VIEW_IN_AR " VU disassembler", NULL, &iris->show_vu_disassembler));
if (MenuItem(ICON_MS_GAMEPAD " DualShock debugger", NULL, &iris->show_pad_debugger));
if (MenuItem(ICON_MS_BUG_REPORT " Performance overlay", NULL, &iris->show_overlay));

Separator();

if (BeginMenu(ICON_MS_MORE_TIME " Timescale")) {
for (int i = 0; i < 9; i++) {
char buf[16]; snprintf(buf, 16, "%dx", 1 << i);

if (Selectable(buf, iris->timescale == (1 << i))) {
iris->timescale = (1 << i);

ps2_set_timescale(iris->ps2, iris->timescale);
}
}

ImGui::EndMenu();
}

if (MenuItem(ICON_MS_SKIP_NEXT " Skip FMVs", NULL, &iris->skip_fmv)) {
printf("Skip FMVs: %d\n", iris->skip_fmv);
ee_set_fmv_skip(iris->ps2->ee, iris->skip_fmv);
Expand All @@ -413,6 +460,7 @@ void show_main_menubar(iris::instance* iris) {
iris->show_symbols = false;
iris->show_threads = false;
iris->show_breakpoints = false;
iris->show_overlay = false;
}

ImGui::EndMenu();
Expand Down
2 changes: 1 addition & 1 deletion frontend/ui/modules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static inline void show_modules_table(iris::instance* iris) {
// bss section
TableSetColumnIndex(3);
addr += mod->data_size;
Text("0x%08x", iop->module_list[i].text_addr);
Text("0x%08x", addr);

PopFont();
}
Expand Down
Loading