Window and cursor abstractions

This commit is contained in:
william 2024-01-14 21:59:13 -05:00
parent 9db7b680d3
commit 091a5e3bf5
12 changed files with 471 additions and 106 deletions

View File

@ -3,7 +3,11 @@ add_library(DEBUG
memory_view.c
dialog.c
program_view.c
program_view.h)
program_view.h
cursor.c
cursor.h
window.c
window.h)
find_package(Curses)

78
debugger/cursor.c Normal file
View File

@ -0,0 +1,78 @@
//
// Created by william on 1/12/24.
//
#include <assert.h>
#include "cursor.h"
void cursor_init(Cursor *cursor, WINDOW *window, int max_x, int max_y) {
cursor->window = window;
cursor->min_x = 1;
cursor->min_y = 1;
cursor->max_x = max_x;
cursor->max_y = max_y;
cursor->multiplier_x = 1;
cursor->multiplier_y = 1;
cursor->width = 1;
cursor->pos_x = 0;
cursor->pos_y = 0;
cursor->enabled = false;
}
void cursor_set_at(Cursor *cursor, int at) {
int win_x = cursor->min_x + cursor->pos_x * cursor->multiplier_x;
int win_y = cursor->min_y + cursor->pos_y * cursor->multiplier_y;
mvwchgat(cursor->window, win_y, win_x, cursor->width, at, 0, NULL);
}
void cursor_enable(Cursor *cursor) {
cursor_set_at(cursor, CURSOR_AT_ENABLED);
cursor->enabled = true;
}
void cursor_disable(Cursor *cursor) {
cursor_set_at(cursor, CURSOR_AT_DISABLED);
cursor->enabled = false;
}
void cursor_set_pos(Cursor *cursor, int x, int y) {
assert(x >= 0);
assert(y >= 0);
bool enabled = cursor->enabled;
if (enabled) {
// Remove the cursor from its old position
cursor_disable(cursor);
}
cursor->pos_x = x;
cursor->pos_y = y;
if (enabled) {
// Display the cursor in the new position
cursor_enable(cursor);
}
}
int cursor_limit(int value, int limit) {
if (value < 0) {
return 0;
}
if (value > limit) {
return limit;
}
return value;
}
void cursor_move(Cursor *cursor, int offset_x, int offset_y) {
int x = cursor->pos_x + offset_x;
x = cursor_limit(x, cursor->max_x);
int y = cursor->pos_y + offset_y;
y = cursor_limit(y, cursor->max_y);
cursor_set_pos(cursor, x, y);
}

74
debugger/cursor.h Normal file
View File

@ -0,0 +1,74 @@
//
// Created by william on 1/12/24.
//
#ifndef NESEMULATOR_CURSOR_H
#define NESEMULATOR_CURSOR_H
#include <curses.h>
#define CURSOR_OFFSET_UP (-1)
#define CURSOR_OFFSET_DOWN 1
#define CURSOR_OFFSET_LEFT (-1)
#define CURSOR_OFFSET_RIGHT 1
#define CURSOR_AT_ENABLED A_REVERSE
#define CURSOR_AT_DISABLED A_NORMAL
typedef struct cursor {
WINDOW *window;
int min_x;
int min_y;
int max_x;
int max_y;
int multiplier_x;
int multiplier_y;
int width;
int pos_x;
int pos_y;
bool enabled;
} Cursor;
/**
* Initializes a cursor with default values.
*
* @param cursor A reference to the cursor to initialize
* @param window The window the cursor is in
*/
void cursor_init(Cursor *cursor, WINDOW *window, int max_x, int max_y);
/**
* Enables a cursor, making it visible in its window.
*
* @param cursor The cursor
*/
void cursor_enable(Cursor *cursor);
/**
* Disables a cursor, removing it from the display.
*
* @param cursor The cursor
*/
void cursor_disable(Cursor *cursor);
/**
* Sets the position of the cursor.
* The positions are from left to right (horizontal) and top to bottom (vertical).
*
* @param cursor The cursor
* @param x The new horizontal position
* @param y The new vertical position
*/
void cursor_set_pos(Cursor *cursor, int x, int y);
/**
* Moves the position of the cursor by an offset. This function ensures that the cursor is kept in the window bounds.
* A negative offset moves the cursor position towards the 0 direction (left or top).
* A position offset moves it in the opposite direction (right or bottom).
*
* @param cursor The cursor
* @param offset_x The horizontal offset
* @param offset_y The vertical offset
*/
void cursor_move(Cursor *cursor, int offset_x, int offset_y);
#endif //NESEMULATOR_CURSOR_H

View File

@ -25,13 +25,13 @@ void create_window() {
}
void start_debugger(System *system) {
MemoryView m_view;
ProgramView p_view;
InteractWindow windows[2];
InteractWindow *current_window;
create_window();
memory_view_init(&m_view, system->ram, 0, 0);
program_view_init(&p_view, MEMORY_VIEW_WIDTH, 0);
memory_view_init(&windows[0], system->ram, 0, 0);
program_view_init(&windows[1], system->ram, MEMORY_VIEW_WIDTH, 0);
update_panels();
doupdate();
@ -39,19 +39,19 @@ void start_debugger(System *system) {
int keycode;
while ((keycode = getch()) != CTRL_KEY_EXIT) {
if (keycode == KEY_UP) {
memory_view_move_cursor(&m_view, 0, MEMORY_VIEW_DIRECTION_DOWN);
current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_UP);
}
if (keycode == KEY_DOWN) {
memory_view_move_cursor(&m_view, 0, MEMORY_VIEW_DIRECTION_UP);
current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_DOWN);
}
if (keycode == KEY_LEFT) {
memory_view_move_cursor(&m_view, MEMORY_VIEW_DIRECTION_LEFT, 0);
current_window->handle_cursor_move(current_window, CURSOR_OFFSET_LEFT, 0);
}
if (keycode == KEY_RIGHT) {
memory_view_move_cursor(&m_view, MEMORY_VIEW_DIRECTION_RIGHT, 0);
current_window->handle_cursor_move(current_window, CURSOR_OFFSET_RIGHT, 0);
}
if (keycode == CTRL_KEY_G) {
@ -63,7 +63,7 @@ void start_debugger(System *system) {
if (!cancelled) {
memory_view_goto(&m_view, input);
memory_view_set_cursor_addr(&m_view, input);
memory_view_cursor_set_addr(&m_view, input);
}
}
@ -71,5 +71,8 @@ void start_debugger(System *system) {
doupdate();
}
window_inter_deinit(&windows[0]);
window_inter_deinit(&windows[1]);
endwin();
}

View File

@ -2,11 +2,11 @@
// Created by william on 1/6/24.
//
#include "../include/system.h"
#ifndef NESEMULATOR_DEBUGGER_H
#define NESEMULATOR_DEBUGGER_H
#include "../include/system.h"
void start_debugger(System *system);
#endif //NESEMULATOR_DEBUGGER_H

View File

@ -1,58 +1,47 @@
#include <curses.h>
#include <panel.h>
#include <assert.h>
#include <stdlib.h>
#include "memory_view.h"
//
// Created by william on 1/6/24.
// Created by william on 6/1/24.
//
void memory_view_highlight_cursor(MemoryView *view) {
int win_x = 8 + view->cursor_x * 3;
int win_y = 2 + view->cursor_y;
mvwchgat(view->panel->win, win_y, win_x, 2, A_REVERSE, 0, NULL);
}
void memory_view_set_cursor_pos(MemoryView *view, int x, int y) {
assert(x >= 0);
assert(x <= 0xf);
assert(y >= 0);
assert(y <= 0xf);
int old_win_x = 8 + view->cursor_x * 3;
int old_win_y = 2 + view->cursor_y;
mvwchgat(view->panel->win, old_win_y, old_win_x, 2, A_NORMAL, 0, NULL);
view->cursor_x = (char) x;
view->cursor_y = (char) y;
memory_view_highlight_cursor(view);
}
void memory_view_write_line(WINDOW *window, int line, address base_address, byte *data) {
mvwprintw(window, line + 2, 1, "[%04x]", base_address);
void memory_view_write_line(MemoryView *view, int line, address base_address, byte *data) {
window_inter_print(view->window, 0, line + 1, "[%04x]", base_address);
for (int i = 0; i <= MEMORY_VIEW_LINE_BYTE_COUNT; i++) {
mvwprintw(window, line + 2, 8 + i * 3, "%02x", data[i]);
window_inter_print(view->window, 7 + i * 3, line + 1, "%02x", data[i]);
}
}
void memory_view_init(MemoryView *view, ram ram, int x, int y) {
WINDOW *window = newwin(MEMORY_VIEW_HEIGHT, MEMORY_VIEW_WIDTH, y, x);
box(window, 0, 0);
void memory_view_cursor_init(MemoryView *view) {
Cursor *cursor = &view->window->cursor;
window_inter_cursor_init(view->window, 0xf, 0xf);
cursor->min_x = 8;
cursor->min_y = 2;
cursor->multiplier_x = 3;
cursor->width = 2;
mvwprintw(window, 0, 1, " MEMORY VIEW ");
mvwprintw(window, 1, 1, " +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f");
cursor_enable(cursor);
}
view->panel = new_panel(window);
void memory_view_handle_key_down(InteractWindow *window, int keycode) {
}
void memory_view_init(InteractWindow *interact, ram ram, int x, int y) {
MemoryView *view = malloc(sizeof(MemoryView));
view->window = interact;
view->ram = ram;
view->base_address = 0x0000;
view->cursor_x = 0;
view->cursor_y = 0;
interact->view = view;
interact->handle_cursor_move = &memory_view_cursor_move;
interact->handle_key_down = &memory_view_handle_key_down;
window_inter_init(interact, x, y, MEMORY_VIEW_WIDTH, MEMORY_VIEW_HEIGHT, "MEMORY VIEW");
window_inter_print(interact, 0, 0, " +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f");
memory_view_print(view);
memory_view_set_cursor_pos(view, 0, 0);
memory_view_cursor_init(view);
}
void memory_view_print(MemoryView *view) {
@ -60,7 +49,7 @@ void memory_view_print(MemoryView *view) {
address line_address = view->base_address + line * (MEMORY_VIEW_LINE_BYTE_COUNT + 1);
byte *data = &view->ram[line_address];
memory_view_write_line(view->panel->win, line, line_address, data);
memory_view_write_line(view, line, line_address, data);
}
}
@ -77,14 +66,14 @@ void memory_view_goto(MemoryView *view, address target) {
memory_view_print(view);
}
void memory_view_scroll(MemoryView *view, char direction) {
assert(direction == MEMORY_VIEW_DIRECTION_DOWN || direction == MEMORY_VIEW_DIRECTION_UP);
void memory_view_scroll(MemoryView *view, int direction) {
assert(direction == CURSOR_OFFSET_DOWN || direction == CURSOR_OFFSET_UP);
int offset = 0;
if (direction == MEMORY_VIEW_DIRECTION_DOWN && view->base_address > MEMORY_VIEW_LINE_BYTE_COUNT) {
if (direction == CURSOR_OFFSET_UP && view->base_address > MEMORY_VIEW_LINE_BYTE_COUNT) {
offset -= MEMORY_VIEW_LINE_BYTE_COUNT + 1;
}
if (direction == MEMORY_VIEW_DIRECTION_UP && view->base_address < RAM_SIZE - MEMORY_VIEW_BYTE_COUNT) {
if (direction == CURSOR_OFFSET_DOWN && view->base_address < RAM_SIZE - MEMORY_VIEW_BYTE_COUNT) {
offset += MEMORY_VIEW_LINE_BYTE_COUNT + 1;
}
@ -92,28 +81,23 @@ void memory_view_scroll(MemoryView *view, char direction) {
memory_view_goto(view, target);
}
void memory_view_move_cursor(MemoryView *view, char horizontal, char vertical) {
if (horizontal == MEMORY_VIEW_DIRECTION_UP && view->cursor_x == 0xf ||
horizontal == MEMORY_VIEW_DIRECTION_DOWN && view->cursor_x == 0) {
return;
}
void memory_view_cursor_move(InteractWindow *window, int horizontal, int vertical) {
MemoryView *view = (MemoryView *) window->view;
if (vertical == MEMORY_VIEW_DIRECTION_RIGHT && view->cursor_y == 0xf ||
vertical == MEMORY_VIEW_DIRECTION_LEFT && view->cursor_y == 0) {
if (vertical == CURSOR_OFFSET_DOWN && view->window->cursor.pos_y == 0xf ||
vertical == CURSOR_OFFSET_UP && view->window->cursor.pos_y == 0) {
// Scroll the view
memory_view_scroll(view, vertical);
memory_view_highlight_cursor(view);
return;
}
int target_x = view->cursor_x + horizontal;
int target_y = view->cursor_y + vertical;
memory_view_set_cursor_pos(view, target_x, target_y);
// We are not on any edge, move the cursor
cursor_move(&view->window->cursor, horizontal, vertical);
}
void memory_view_set_cursor_addr(MemoryView *view, address target) {
void memory_view_cursor_set_addr(MemoryView *view, address target) {
int view_byte = target - view->base_address;
int x = view_byte & 0x0f;
int y = (view_byte & 0xf0) >> 4;
memory_view_set_cursor_pos(view, x, y);
cursor_set_pos(&view->window->cursor, x, y);
}

View File

@ -1,5 +1,5 @@
//
// Created by william on 1/6/24.
// Created by william on 6/1/24.
//
#ifndef NESEMULATOR_MEMORY_VIEW_H
@ -7,6 +7,8 @@
#include <panel.h>
#include "../include/types.h"
#include "cursor.h"
#include "window.h"
#define MEMORY_VIEW_HEIGHT 19
#define MEMORY_VIEW_WIDTH 56
@ -14,17 +16,10 @@
#define MEMORY_VIEW_LINE_BYTE_COUNT 0xf
#define MEMORY_VIEW_BYTE_COUNT 0xff
#define MEMORY_VIEW_DIRECTION_UP 1
#define MEMORY_VIEW_DIRECTION_DOWN (-1)
#define MEMORY_VIEW_DIRECTION_RIGHT 1
#define MEMORY_VIEW_DIRECTION_LEFT (-1)
typedef struct memory_view {
PANEL *panel;
InteractWindow *window;
byte *ram;
address base_address;
char cursor_x;
char cursor_y;
} MemoryView;
/**
@ -34,7 +29,7 @@ typedef struct memory_view {
* @param view A pointer to the view to initialize
* @param ram A pointer to the RAM
*/
void memory_view_init(MemoryView *view, ram ram, int x, int y);
void memory_view_init(InteractWindow *interact, ram ram, int x, int y);
/**
* Prints the RAM content from the viewer base address.
@ -57,7 +52,7 @@ void memory_view_goto(MemoryView *view, address target);
* @param view
* @param direction The scroll direction
*/
void memory_view_scroll(MemoryView *view, char direction);
void memory_view_scroll(MemoryView *view, int direction);
/**
* Moves the cursor up, down, right or left.
@ -66,7 +61,7 @@ void memory_view_scroll(MemoryView *view, char direction);
* @param horizontal
* @param vertical
*/
void memory_view_move_cursor(MemoryView *view, char horizontal, char vertical);
void memory_view_cursor_move(InteractWindow *window, int horizontal, int vertical);
/**
* Moves the cursor to a specific memory address.
@ -75,6 +70,6 @@ void memory_view_move_cursor(MemoryView *view, char horizontal, char vertical);
* @param view
* @param target
*/
void memory_view_set_cursor_addr(MemoryView *view, address target);
void memory_view_cursor_set_addr(MemoryView *view, address target);
#endif //NESEMULATOR_MEMORY_VIEW_H

View File

@ -2,42 +2,118 @@
// Created by william on 10/01/24.
//
#include <stdlib.h>
#include "program_view.h"
#include "../cpu/op.h"
void decode_operands(byte *ram, address start_addr) {
void decode_operands(DebugOperand *operands, const byte *ram, address start_addr) {
int pc = start_addr;
for (int i = 0; i < 10; i++) {
DebugOperand operand;
byte op_code = ram[pc];
operand.addr = pc;
operand.op_code = op_code;
operand.addr_mode = get_op_addr_mode(op_code);
pc += 1;
if (operand.addr_mode == ADDR_MODE_ACCUMULATOR || operand.addr_mode == ADDR_MODE_IMPLICIT) {
operand.type = OPERAND_TYPE_ACCUMULATOR;
operand.value = 0;
} else if (operand.addr_mode == ADDR_MODE_IMMEDIATE) {
operand.type = OPERAND_TYPE_IMMEDIATE;
operand.value = ram[pc];
pc += 1;
} else if (operand.addr_mode == ADDR_MODE_RELATIVE) {
operand.type = OPERAND_TYPE_ADDRESS;
operand.value = ram[pc];
pc += 1;
} else {
operand.type = OPERAND_TYPE_ADDRESS;
operand.value = ram[pc];
operand.value += ram[pc + 1] << 8;
pc += 2;
}
operands[i] = operand;
}
}
void program_view_write_line(WINDOW *window, int line, address addr) {
mvwprintw(window, line + 1, 1, "%04x:", addr);
mvwprintw(window, line + 1, 7, "%s", "BRK");
}
void program_view_print(ProgramView *view) {
for (int line = 0; line <= 0xf; line++) {
address addr = 0x8000 + line;
program_view_write_line(view->panel->win, line, addr);
char *get_addr_mode_format_str(AddressingMode addr_mode) {
switch (addr_mode) {
case ADDR_MODE_ABSOLUTE:
return "$%04x";
case ADDR_MODE_ABSOLUTE_INDEXED_X:
return "$%04x,x";
case ADDR_MODE_ABSOLUTE_INDEXED_Y:
return "$%04x,y";
case ADDR_MODE_ACCUMULATOR:
return "A";
case ADDR_MODE_IMMEDIATE:
return "#$%02x";
case ADDR_MODE_IMPLICIT:
return "";
case ADDR_MODE_INDIRECT_X:
return "($%04x,x)";
case ADDR_MODE_INDIRECT_JUMP:
return "($%04x)";
case ADDR_MODE_INDIRECT_Y:
return "($%04x),y";
case ADDR_MODE_RELATIVE:
return "$%04x";
case ADDR_MODE_ZERO_PAGE:
return "$%02x,y";
case ADDR_MODE_ZERO_PAGE_INDEXED_X:
return "$%02x,x";
case ADDR_MODE_ZERO_PAGE_INDEXED_Y:
return "$%02x,y";
}
}
void program_view_init(ProgramView *view, ram ram, int x, int y) {
WINDOW *window = newwin(PROGRAM_VIEW_HEIGHT, PROGRAM_VIEW_WIDTH, y, x);
box(window, 0, 0);
void program_view_write_line(ProgramView *view, int line, DebugOperand *operand) {
char *op_name = get_op_code_name(operand->op_code);
mvwprintw(window, 0, 1, " PROGRAM VIEW ");
window_inter_print(view->window, 0, line, "%04x:", operand->addr);
window_inter_print(view->window, 6, line, "%s", op_name);
view->panel = new_panel(window);
char *format = get_addr_mode_format_str(operand->addr_mode);
window_inter_print(view->window, 10, line, format, operand->value);
}
void program_view_print(ProgramView *view, DebugOperand *operands) {
for (int line = 0; line < 10; line++) {
program_view_write_line(view, line, &operands[line]);
}
}
void program_view_cursor_init(ProgramView *view) {
window_inter_cursor_init(view->window, 0, 10);
view->window->cursor.width = PROGRAM_VIEW_WIDTH - 2;
cursor_enable(&view->window->cursor);
}
void program_view_handle_cursor_move(InteractWindow *window, int horizontal, int vertical) {
cursor_move(&window->cursor, horizontal, vertical);
}
void program_view_handle_key_down(InteractWindow *window, int keycode) {
}
void program_view_init(InteractWindow *interact, ram ram, int x, int y) {
ProgramView *view = malloc(sizeof(ProgramView));
view->window = interact;
view->ram = ram;
program_view_print(view);
interact->view = view;
interact->handle_cursor_move = &program_view_handle_cursor_move;
interact->handle_key_down = &program_view_handle_key_down;
window_inter_init(interact, x, y, PROGRAM_VIEW_WIDTH, PROGRAM_VIEW_HEIGHT, "PROGRAM VIEW");
DebugOperand operands[10];
decode_operands(&operands[0], ram, 0xc004);
program_view_print(view, &operands[0]);
program_view_cursor_init(view);
}

View File

@ -2,27 +2,32 @@
// Created by william on 10/01/24.
//
#ifndef NESEMULATOR_PROGRAM_VIEW_H
#define NESEMULATOR_PROGRAM_VIEW_H
#include <panel.h>
#include "../include/types.h"
#include "../cpu/decoding.h"
#ifndef NESEMULATOR_PROGRAM_VIEW_H
#define NESEMULATOR_PROGRAM_VIEW_H
#include "cursor.h"
#include "window.h"
#define PROGRAM_VIEW_HEIGHT 19
#define PROGRAM_VIEW_WIDTH 42
typedef struct program_view {
PANEL *panel;
InteractWindow *window;
byte *ram;
address base_address;
} ProgramView;
typedef struct debug_operand {
address addr;
byte op_code;
AddressingMode addr_mode;
enum OperandType type;
word value;
} DebugOperand;
void program_view_init(ProgramView *view, ram ram, int x, int y);
void program_view_init(InteractWindow *interact, ram ram, int x, int y);
#endif //NESEMULATOR_PROGRAM_VIEW_H

61
debugger/window.c Normal file
View File

@ -0,0 +1,61 @@
//
// Created by william on 1/12/24.
//
#include <assert.h>
#include <stdlib.h>
#include "window.h"
void window_init(Window *window, int x, int y, int width, int height, char *title) {
assert(x >= 0);
assert(y >= 0);
assert(width > 0);
assert(height > 0);
WINDOW *curse_win = newwin(height, width, y, x);
box(curse_win, 0, 0);
mvwprintw(curse_win, 0, 1, " %s ", title);
window->panel = new_panel(curse_win);
window->width = width;
window->height = height;
}
void window_inter_init(InteractWindow *window, int x, int y, int width, int height, char *title) {
window_init(&window->window, x, y, width, height, title);
}
void window_print_va(Window *window, int x, int y, const char *fmt, va_list args) {
assert(x >= 0);
assert(x < window->width - 1);
assert(y >= 0);
assert(y < window->height - 1);
wmove(window->panel->win, y + 1, x + 1);
vw_printw(window->panel->win, fmt, args);
}
void window_inter_cursor_init(InteractWindow *window, int max_x, int max_y) {
cursor_init(&window->cursor, window->window.panel->win, max_x, max_y);
}
void window_print(Window *window, int x, int y, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
window_print_va(window, x, y, fmt, args);
va_end(args);
}
void window_inter_print(InteractWindow *window, int x, int y, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
window_print_va(&window->window, x, y, fmt, args);
va_end(args);
}
void window_inter_deinit(InteractWindow *window) {
assert(window->view != NULL);
free(window->view);
}

84
debugger/window.h Normal file
View File

@ -0,0 +1,84 @@
//
// Created by william on 1/12/24.
//
#ifndef NESEMULATOR_WINDOW_H
#define NESEMULATOR_WINDOW_H
#include <panel.h>
#include "cursor.h"
typedef struct window {
PANEL *panel;
int width;
int height;
} Window;
typedef struct interact_window {
Window window;
Cursor cursor;
void *view;
void (*handle_cursor_move)(struct interact_window *window, int horizontal, int vertical);
void (*handle_key_down)(struct interact_window *window, int keycode);
} InteractWindow;
/**
* Initializes a window with a position, size and title.
*
* @param window The window to initialize
* @param x The horizontal position (left to right)
* @param y The vertical position (top to bottom)
* @param width The window width
* @param height The window height
* @param title The window title
*/
void window_init(Window *window, int x, int y, int width, int height, char *title);
/**
* Initializes an interactable window with a position, size and title.
*
* @param window The window to initialize
* @param x The horizontal position (left to right)
* @param y The vertical position (top to bottom)
* @param width The window width
* @param height The window height
* @param title The window title
*/
void window_inter_init(InteractWindow *window, int x, int y, int width, int height, char *title);
/**
* Initializes the cursor of an interactable window.
*
* @param window The window
* @param max_x The cursor's maximum horizontal position
* @param max_y The cursor's maximum vertical position
*/
void window_inter_cursor_init(InteractWindow *window, int max_x, int max_y);
/**
* Prints text on a window.
*
* @param window The window
* @param x The horizontal position (left to right)
* @param y The vertical position (top to bottom)
* @param fmt A format string
* @param ... The format string arguments
*/
void window_print(Window *window, int x, int y, const char *fmt, ...);
/**
* Prints text on an interactable window.
*
* @param window The window
* @param x The horizontal position (left to right)
* @param y The vertical position (top to bottom)
* @param fmt A format string
* @param ... The format string arguments
*/
void window_inter_print(InteractWindow *window, int x, int y, const char *fmt, ...);
void window_inter_deinit(InteractWindow *window);
#endif //NESEMULATOR_WINDOW_H

View File

@ -1,3 +1,4 @@
BreakPoint: startAddr=00000014 endAddr=00000000 flags=ER--X- condition="" desc=""
BreakPoint: startAddr=00000023 endAddr=00000000 flags=ER--X- condition="" desc=""
BreakPoint: startAddr=00000000 endAddr=00000000 flags=EC--X- condition="" desc=""
Bookmark: addr=C10F desc=""