Skip to content

Commit

Permalink
Add a screenshot and key command to the debuggrer.
Browse files Browse the repository at this point in the history
  • Loading branch information
Arignir committed Dec 15, 2023
1 parent cbf9b83 commit cab06e7
Show file tree
Hide file tree
Showing 14 changed files with 215 additions and 29 deletions.
3 changes: 2 additions & 1 deletion include/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,12 +329,13 @@ void app_game_key(struct app *app, enum keys key, bool pressed);
void app_game_speed(struct app *app, uint32_t);
void app_game_update_backup(struct app *app);
void app_game_screenshot(struct app *app);
void app_game_screenshot_path(struct app *app, char const *);
void app_game_quicksave(struct app *app, size_t idx);
void app_game_quickload(struct app *app, size_t idx);

#ifdef WITH_DEBUGGER

void app_game_frame(struct app *app);
void app_game_frame(struct app *app, size_t);
void app_game_trace(struct app *app, size_t, void (*)(struct app *));
void app_game_step_in(struct app *app, size_t cnt);
void app_game_step_over(struct app *app, size_t cnt);
Expand Down
5 changes: 5 additions & 0 deletions include/common/channel/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ struct message_set_watchpoints_list {
size_t len;
};

struct message_frame {
struct event_header header;
size_t count;
};

#endif

/*
Expand Down
8 changes: 8 additions & 0 deletions include/dbg/dbg.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ enum commands_list {
CMD_RESET,
CMD_FRAME,
CMD_IO,
CMD_KEY,
CMD_SCREENSHOT,
};

struct io_bitfield {
Expand Down Expand Up @@ -196,6 +198,9 @@ void debugger_cmd_help(struct app *, size_t, struct arg const *);
/* dbg/cmd/io.c */
void debugger_cmd_io(struct app *, size_t, struct arg const *);

/* dbg/cmd/key.c */
void debugger_cmd_key(struct app *, size_t, struct arg const *);

/* dbg/cmd/print.c */
void debugger_cmd_print(struct app *, size_t, struct arg const *);
void debugger_cmd_print_u8(struct app const *, uint32_t, size_t, size_t);
Expand All @@ -208,6 +213,9 @@ void debugger_cmd_registers(struct app *, size_t, struct arg const *);
/* dbg/cmd/reset.c */
void debugger_cmd_reset(struct app *, size_t, struct arg const *);

/* dbg/cmd/screenshot.c */
void debugger_cmd_screenshot(struct app *, size_t, struct arg const *);

/* dbg/cmd/step.c */
void debugger_cmd_step_in(struct app *, size_t, struct arg const *);
void debugger_cmd_step_over(struct app *, size_t, struct arg const *);
Expand Down
4 changes: 4 additions & 0 deletions include/gba/debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ struct debugger {
uint32_t next_pc;
size_t count;
} step;

struct {
size_t count;
} frame;
};

/* gba/debugger.c */
Expand Down
3 changes: 3 additions & 0 deletions include/gba/gba.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ enum keys {
KEY_RIGHT,
KEY_START,
KEY_SELECT,

KEY_MAX,
KEY_MIN = KEY_A,
};

struct shared_data {
Expand Down
52 changes: 34 additions & 18 deletions source/common/game.c
Original file line number Diff line number Diff line change
Expand Up @@ -659,23 +659,15 @@ app_game_update_backup(
** Take a screenshot of the game and writes it to the disk.
*/
void
app_game_screenshot(
struct app *app
app_game_screenshot_path(
struct app *app,
char const *path
) {
time_t now;
struct tm *now_info;
char filename[256];
int out;

time(&now);
now_info = localtime(&now);

hs_mkdir("screenshots");
strftime(filename, sizeof(filename), "screenshots/%Y-%m-%d_%Hh%Mm%Ss.png", now_info);

pthread_mutex_lock(&app->emulation.gba->shared_data.framebuffer.lock);
out = stbi_write_png(
filename,
path,
GBA_SCREEN_WIDTH,
GBA_SCREEN_HEIGHT,
4,
Expand All @@ -688,19 +680,41 @@ app_game_screenshot(
gui_new_notification(
app,
UI_NOTIFICATION_SUCCESS,
"Screenshot saved in %s.",
filename
"Screenshot saved in \"%s\".",
path
);
} else {
gui_new_notification(
app,
UI_NOTIFICATION_ERROR,
"Failed to save screenshot in %s.",
filename
"Failed to save screenshot in \"%s\".",
path
);
}
}

/*
** Take a screenshot of the game and writes it to the disk.
**
** The file's name depends on the current time.
*/
void
app_game_screenshot(
struct app *app
) {
time_t now;
struct tm *now_info;
char path[256];

time(&now);
now_info = localtime(&now);

hs_mkdir("screenshots");
strftime(path, sizeof(path), "screenshots/%Y-%m-%d_%Hh%Mm%Ss.png", now_info);

app_game_screenshot_path(app, path);
}

void
app_game_quicksave(
struct app *app,
Expand Down Expand Up @@ -795,12 +809,14 @@ app_game_quickload(
*/
void
app_game_frame(
struct app *app
struct app *app,
size_t count
) {
struct message event;
struct message_frame event;

event.header.kind = MESSAGE_FRAME;
event.header.size = sizeof(event);
event.count = count;

channel_lock(&app->emulation.gba->channels.messages);
channel_push(&app->emulation.gba->channels.messages, &event.header);
Expand Down
19 changes: 16 additions & 3 deletions source/dbg/cmd/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,20 @@ debugger_cmd_frame(
return;
}

app_game_frame(app);
debugger_wait_for_emulator(app);
debugger_dump_context_auto(app);
if (argc == 0) {
app_game_frame(app, 1);
debugger_wait_for_emulator(app);
debugger_dump_context_auto(app);
} else if (argc == 1) {
if (debugger_check_arg_type(CMD_FRAME, &argv[0], ARGS_INTEGER)) {
return ;
}

app_game_frame(app, argv[0].value.i64);
debugger_wait_for_emulator(app);
debugger_dump_context_auto(app);
} else {
printf("Usage: %s\n", g_commands[CMD_FRAME].usage);
return ;
}
}
64 changes: 64 additions & 0 deletions source/dbg/cmd/key.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/******************************************************************************\
**
** This file is part of the Hades GBA Emulator, and is made available under
** the terms of the GNU General Public License version 2.
**
** Copyright (C) 2021-2023 - The Hades Authors
**
\******************************************************************************/

#include "hades.h"
#include "app.h"
#include "dbg/dbg.h"

static char const * const key_names[] = {
[KEY_A] = "a",
[KEY_B] = "b",
[KEY_L] = "l",
[KEY_R] = "r",
[KEY_UP] = "up",
[KEY_DOWN] = "down",
[KEY_LEFT] = "left",
[KEY_RIGHT] = "right",
[KEY_START] = "start",
[KEY_SELECT] = "select",
};

void
debugger_cmd_key(
struct app *app,
size_t argc,
struct arg const *argv
) {
if (!app->debugger.is_started) {
logln(HS_ERROR, "%s%s%s", g_red, "This command cannot be used when no game is running.", g_reset);
return;
}

if (argc == 2) {
enum keys i;

if (debugger_check_arg_type(CMD_KEY, &argv[0], ARGS_STRING)
|| debugger_check_arg_type(CMD_KEY, &argv[1], ARGS_INTEGER)
) {
return ;
}

for (i = KEY_MIN; i < KEY_MAX; ++i) {
if (!strcmp(argv[0].value.s, key_names[i])) {
app_game_key(app, i, (bool)argv[1].value.i64);
printf(
"Key \"%s\" set to %s.\n",
argv[0].value.s,
argv[1].value.i64 ? "true" : "false"
);
return ;
}
}

printf("Error: unknown key \"%s\".\n", argv[0].value.s);
} else {
printf("Usage: %s\n", g_commands[CMD_KEY].usage);
return ;
}
}
37 changes: 37 additions & 0 deletions source/dbg/cmd/screenshot.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/******************************************************************************\
**
** This file is part of the Hades GBA Emulator, and is made available under
** the terms of the GNU General Public License version 2.
**
** Copyright (C) 2021-2023 - The Hades Authors
**
\******************************************************************************/

#include "hades.h"
#include "app.h"
#include "dbg/dbg.h"

void
debugger_cmd_screenshot(
struct app *app,
size_t argc,
struct arg const *argv
) {
if (!app->debugger.is_started) {
logln(HS_ERROR, "%s%s%s", g_red, "This command cannot be used when no game is running.", g_reset);
return;
}

if (argc == 0) {
app_game_screenshot(app);
} else if (argc == 1) {
if (debugger_check_arg_type(CMD_SCREENSHOT, &argv[0], ARGS_STRING)) {
return ;
}

app_game_screenshot_path(app, argv[0].value.s);
} else {
printf("Usage: %s\n", g_commands[CMD_SCREENSHOT].usage);
return ;
}
}
18 changes: 16 additions & 2 deletions source/dbg/dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ struct command g_commands[] = {
[CMD_FRAME] = {
.name = "frame",
.alias = "f",
.usage = "frame",
.description = "Run until the end of the current frame.",
.usage = "frame [N=1]",
.description = "Run until N frames are completed.",
.func = debugger_cmd_frame,
},
[CMD_IO] = {
Expand All @@ -136,6 +136,20 @@ struct command g_commands[] = {
.description = "Print or set the value of an IO register.",
.func = debugger_cmd_io,
},
[CMD_KEY] = {
.name = "key",
.alias = NULL,
.usage = "key KEY STATE",
.description = "Set the state of any input key.",
.func = debugger_cmd_key,
},
[CMD_SCREENSHOT] = {
.name = "screenshot",
.alias = "screen",
.usage = "screenshot [FILE]",
.description = "Store a screenshot of the screen in FILE.",
.func = debugger_cmd_screenshot
},
{
.name = NULL,
}
Expand Down
15 changes: 12 additions & 3 deletions source/dbg/lang/lexer.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,28 @@ debugger_lang_lexe(
i = 0;
while (input[i]) {
switch (input[i]) {
case '.':
case 'a' ... 'z':
case 'A' ... 'Z': {
/* Lexe the whole identifier */
struct token *t;
size_t j;

j = 0;
while (isalnum(input[i + j])) {
while (isalnum(input[i + j]) || input[i + j] == '.' || input[i + j] == '/') {
++j;
}

t = token_new(lexer, TOKEN_IDENTIFIER);
t->value.identifier = strndup(input + i, j);
if (j >= strlen("true") && !strncmp(input + i, "true", j)) {
t = token_new(lexer, TOKEN_LITTERAL);
t->value.litteral = 1;
} else if (j >= strlen("false") && !strncmp(input + i, "false", j)) {
t = token_new(lexer, TOKEN_LITTERAL);
t->value.litteral = 0;
} else {
t = token_new(lexer, TOKEN_IDENTIFIER);
t->value.identifier = strndup(input + i, j);
}

i += j;
break;
Expand Down
2 changes: 2 additions & 0 deletions source/dbg/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ libdbg = static_library(
'cmd/frame.c',
'cmd/help.c',
'cmd/io.c',
'cmd/key.c',
'cmd/print.c',
'cmd/registers.c',
'cmd/reset.c',
'cmd/screenshot.c',
'cmd/step.c',
'cmd/trace.c',
'cmd/verbose.c',
Expand Down
8 changes: 6 additions & 2 deletions source/gba/debugger.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,12 @@ debugger_execute_run_mode(
break;
};
case GBA_RUN_MODE_FRAME: {
sched_run_for(gba, GBA_CYCLES_PER_PIXEL * GBA_SCREEN_REAL_WIDTH * GBA_SCREEN_HEIGHT);
gba_state_pause(gba);
if (gba->debugger.frame.count) {
--gba->debugger.frame.count;
sched_run_for(gba, GBA_CYCLES_PER_PIXEL * GBA_SCREEN_REAL_WIDTH * GBA_SCREEN_HEIGHT);
} else {
gba_state_pause(gba);
}
break;
};
case GBA_RUN_MODE_TRACE: {
Expand Down
Loading

0 comments on commit cab06e7

Please sign in to comment.