From 6c78b0f24c5eabb0a3eaf451f74f657958bba0cf Mon Sep 17 00:00:00 2001 From: Christian Gleissner Date: Tue, 4 Jul 2023 14:34:01 +0100 Subject: [PATCH 1/7] Added hex viewer --- .../userinterface/user_file_interaction.cc | 28 +++++++++++-- .../userinterface/user_file_interaction.h | 1 + software/userinterface/userinterface.cc | 42 +++++++++++++++++++ software/userinterface/userinterface.h | 4 ++ 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/software/userinterface/user_file_interaction.cc b/software/userinterface/user_file_interaction.cc index bdb22b2a8..bdf20e229 100644 --- a/software/userinterface/user_file_interaction.cc +++ b/software/userinterface/user_file_interaction.cc @@ -14,6 +14,9 @@ #include "home_directory.h" #include "subsys.h" +#define MAX_FILE_SIZE_TO_VIEW 262144 +#define MAX_FILE_SIZE_TO_HEX_VIEW 26 * 1024 // TODO Investigate how this limit can be increased + // member int UserFileInteraction::fetch_context_items(BrowsableDirEntry *br, IndexedList &list) { @@ -30,8 +33,13 @@ int UserFileInteraction::fetch_context_items(BrowsableDirEntry *br, IndexedList< list.append(new Action("Enter", UserFileInteraction::S_enter, 0)); count++; } - if ((info->size <= 262144) && (!(info->attrib & AM_DIR))) { + if ((info->size <= MAX_FILE_SIZE_TO_VIEW) && (!(info->attrib & AM_DIR))) { list.append(new Action("View", UserFileInteraction::S_view, 0)); + if (info->size <= MAX_FILE_SIZE_TO_HEX_VIEW) { + printf("Hex view: file size %d <= %d\n", info->size, MAX_FILE_SIZE_TO_HEX_VIEW); + list.append(new Action("Hex View", UserFileInteraction::S_hex_view, 0)); + count++; + } count++; } if (info->is_writable()) { @@ -131,7 +139,7 @@ int UserFileInteraction::S_delete(SubsysCommand *cmd) return 0; } -int UserFileInteraction::S_view(SubsysCommand *cmd) +int _view(SubsysCommand *cmd, bool hex) { FileManager *fm = FileManager::getFileManager(); File *f = 0; @@ -143,12 +151,26 @@ int UserFileInteraction::S_view(SubsysCommand *cmd) FRESULT fres = f->read(text_buf, size, &transferred); printf("Res = %d. Read text buffer: %d bytes\n", fres, transferred); text_buf[transferred] = 0; - cmd->user_interface->run_editor(text_buf, transferred); + if (hex) { + cmd->user_interface->run_hex_editor(text_buf, transferred); + } else { + cmd->user_interface->run_editor(text_buf, transferred); + } delete text_buf; } return 0; } +int UserFileInteraction::S_view(SubsysCommand *cmd) +{ + return _view(cmd, false); +} + +int UserFileInteraction::S_hex_view(SubsysCommand *cmd) +{ + return _view(cmd, true); +} + int UserFileInteraction::S_createDir(SubsysCommand *cmd) { char buffer[64]; diff --git a/software/userinterface/user_file_interaction.h b/software/userinterface/user_file_interaction.h index bf7e6bf81..2ef9dc304 100644 --- a/software/userinterface/user_file_interaction.h +++ b/software/userinterface/user_file_interaction.h @@ -26,6 +26,7 @@ class UserFileInteraction : public SubSystem, ObjectWithMenu { static int S_rename(SubsysCommand *cmd); static int S_delete(SubsysCommand *cmd); static int S_view(SubsysCommand *cmd); + static int S_hex_view(SubsysCommand *cmd); static int S_createDir(SubsysCommand *cmd); static int S_runApp(SubsysCommand *cmd); diff --git a/software/userinterface/userinterface.cc b/software/userinterface/userinterface.cc index faa02717b..cd5698109 100644 --- a/software/userinterface/userinterface.cc +++ b/software/userinterface/userinterface.cc @@ -394,6 +394,48 @@ void UserInterface :: run_editor(const char *text_buf, int max_len) edit->deinit(); } +void add_hex_byte(char *buf, int offset, uint8_t byte) +{ + char hex_chars[] = "0123456789ABCDEF"; + buf[offset] = hex_chars[(byte >> 4) & 0x0F]; + buf[offset + 1] = hex_chars[byte & 0x0F]; +} + +void add_hex_word(char *buf, int offset, uint16_t word) +{ + add_hex_byte(buf, offset, (word >> 8) & 0xFF); + add_hex_byte(buf, offset + 2, word & 0xFF); +} + +void UserInterface :: run_hex_editor(const char *text_buf, int max_len) +{ + #define HEX_COL_START 5 + #define TXT_COL_START (HEX_COL_START + (3 * BYTES_PER_HEX_ROW)) + int hex_len = CHARS_PER_HEX_ROW * (max_len / BYTES_PER_HEX_ROW + 1); + char hex_buf[hex_len + 1]; + for (int i = 0; i < hex_len; i++) { + hex_buf[i] = ' '; + } + int row_offset = 0; + for (int i = 0; i < max_len; i++) { + int col = i % BYTES_PER_HEX_ROW; + // offset and line break + if (col == 0) { + if (i > 0) { + hex_buf[row_offset + CHARS_PER_HEX_ROW - 1] = '\n'; + row_offset += CHARS_PER_HEX_ROW; + } + add_hex_word(hex_buf, row_offset, i); + } + // data + unsigned char c = text_buf[i]; + add_hex_byte(hex_buf, row_offset + HEX_COL_START + (3 * col), c); + // represent all non-printable characters as '.' based on the character set used by firmware version 3.10j + hex_buf[row_offset + TXT_COL_START + col] = (char) ((c == 0 || c == 8 || c == 10 || c == 13 || (c >=20 && c <= 31) || (c >= 144 && c <= 159)) ? '.' : c); + } + run_editor(hex_buf, hex_len); +} + int UserInterface :: enterSelection() { #ifndef NO_FILE_ACCESS diff --git a/software/userinterface/userinterface.h b/software/userinterface/userinterface.h index e7c14bc4d..c148edd48 100644 --- a/software/userinterface/userinterface.h +++ b/software/userinterface/userinterface.h @@ -28,6 +28,9 @@ #define CFG_USERIF_ULTICOPY_NAME 0x0B #define CFG_USERIF_FILENAME_OVERFLOW_SQUEEZE 0x0C +#define BYTES_PER_HEX_ROW 8 +#define CHARS_PER_HEX_ROW 38 + class UserInterface : public ConfigurableObject, public HostClient { private: @@ -83,6 +86,7 @@ class UserInterface : public ConfigurableObject, public HostClient int getPreferredType(void); void run_editor(const char *, int); + void run_hex_editor(const char *, int); void swapDisk(void); UIObject *get_root_object(void) { return ui_objects[0]; } From 1e1e7782700153549d93145a7733f2b0a9533df9 Mon Sep 17 00:00:00 2001 From: Christian Gleissner Date: Tue, 4 Jul 2023 17:43:13 +0100 Subject: [PATCH 2/7] Reduced memory use of hex viewer and using Editor inheritance hierarchy --- software/userinterface/editor.cc | 14 +++-- software/userinterface/editor.h | 14 ++++- software/userinterface/hex_editor.cc | 57 +++++++++++++++++++ .../userinterface/user_file_interaction.cc | 29 +++++----- .../userinterface/user_file_interaction.h | 2 + software/userinterface/userinterface.cc | 47 +++------------ software/userinterface/userinterface.h | 6 +- target/u64/nios2/ultimate/Makefile | 1 + 8 files changed, 108 insertions(+), 62 deletions(-) create mode 100644 software/userinterface/hex_editor.cc diff --git a/software/userinterface/editor.cc b/software/userinterface/editor.cc index 5e0350d22..12342ca35 100644 --- a/software/userinterface/editor.cc +++ b/software/userinterface/editor.cc @@ -124,20 +124,26 @@ void Editor :: init(Screen *scr, Keyboard *key) void Editor :: draw(void) { - struct Line line; + struct Line line, *line_ptr; int width = window->get_size_x(); for(int i=0;imove_cursor(0, i); - line = (*text)[i + first_line]; + int line_idx = i + first_line; + line = (*text)[line_idx]; if (line.buffer) { - window->output_length(line.buffer, line.length); - window->repeat(' ', width - line.length); + draw(line_idx, &line); } else { window->repeat(' ', width); } } } +void Editor :: draw(int line_idx, Line *line) +{ + window->output_length(line->buffer, line->length); + window->repeat(' ', window->get_size_x() - line->length); +} + void Editor :: deinit() { if(window) diff --git a/software/userinterface/editor.h b/software/userinterface/editor.h index 1a43ef3ce..3817867f1 100644 --- a/software/userinterface/editor.h +++ b/software/userinterface/editor.h @@ -13,8 +13,6 @@ class UserInterface; class Editor : public UIObject { UserInterface *user_interface; - void line_breakdown(const char *text_buffer, int buffer_size); - void draw(); public: int line_length; int height; @@ -34,8 +32,20 @@ class Editor : public UIObject virtual void init(Screen *win, Keyboard *k); virtual void deinit(void); + virtual void line_breakdown(const char *text_buffer, int buffer_size); + virtual void draw(); + virtual void draw(int line_idx, Line *line); virtual int poll(int); virtual int handle_key(uint8_t); }; +class HexEditor : public Editor +{ + UserInterface *user_interface; + void line_breakdown(const char *text_buffer, int buffer_size); + void draw(int line_idx, Line *line); +public: + HexEditor(UserInterface *ui, const char *text_buffer, int max_len); +}; + #endif diff --git a/software/userinterface/hex_editor.cc b/software/userinterface/hex_editor.cc new file mode 100644 index 000000000..df1bbce11 --- /dev/null +++ b/software/userinterface/hex_editor.cc @@ -0,0 +1,57 @@ +#include "editor.h" +#include +#include + +static const char hex_chars[] = "0123456789ABCDEF"; + +HexEditor :: HexEditor(UserInterface *ui, const char *text_buffer, int max_len) : Editor(ui, text_buffer, max_len) +{ +} + +void HexEditor :: line_breakdown(const char *text_buffer, int buffer_size) +{ + Line current; + int pos = 0; + linecount = 0; + + text->clear_list(); + while (pos < buffer_size) { + current.buffer = text_buffer + pos; + current.length = (buffer_size - pos > BYTES_PER_HEX_ROW) ? BYTES_PER_HEX_ROW : buffer_size - pos;; + text->append(current); + pos += current.length; + linecount++; + } +} + +inline void add_hex_byte(char *buf, int offset, uint8_t byte) +{ + buf[offset] = hex_chars[(byte >> 4) & 0x0F]; + buf[offset + 1] = hex_chars[byte & 0x0F]; +} + +inline void add_hex_word(char *buf, int offset, uint16_t word) +{ + add_hex_byte(buf, offset, (word >> 8) & 0xFF); + add_hex_byte(buf, offset + 2, word & 0xFF); +} + +void HexEditor :: draw(int line_idx, Line *line) +{ + #define HEX_COL_START 5 + #define TXT_COL_START (HEX_COL_START + (3 * BYTES_PER_HEX_ROW)) + + char hex_buf[CHARS_PER_HEX_ROW]; + memset(hex_buf, ' ', CHARS_PER_HEX_ROW); + add_hex_word(hex_buf, 0, line_idx * BYTES_PER_HEX_ROW); + + for (int i = 0; i < line->length; i++) { + uint8_t c = (uint8_t) line->buffer[i]; + add_hex_byte(hex_buf, HEX_COL_START + (3 * i), c); + // represent all non-printable characters as '.' based on the character set used by firmware version 3.10j + hex_buf[TXT_COL_START + i] = (char) ((c == 0 || c == 8 || c == 10 || c == 13 || (c >=20 && c <= 31) || (c >= 144 && c <= 159)) ? '.' : c); + } + + window->output_length(hex_buf, CHARS_PER_HEX_ROW); + window->repeat(' ', window->get_size_x() - CHARS_PER_HEX_ROW); +} diff --git a/software/userinterface/user_file_interaction.cc b/software/userinterface/user_file_interaction.cc index bdf20e229..9f25d9862 100644 --- a/software/userinterface/user_file_interaction.cc +++ b/software/userinterface/user_file_interaction.cc @@ -13,9 +13,9 @@ #include "home_directory.h" #include "subsys.h" +#include "editor.h" #define MAX_FILE_SIZE_TO_VIEW 262144 -#define MAX_FILE_SIZE_TO_HEX_VIEW 26 * 1024 // TODO Investigate how this limit can be increased // member int UserFileInteraction::fetch_context_items(BrowsableDirEntry *br, IndexedList &list) @@ -35,12 +35,8 @@ int UserFileInteraction::fetch_context_items(BrowsableDirEntry *br, IndexedList< } if ((info->size <= MAX_FILE_SIZE_TO_VIEW) && (!(info->attrib & AM_DIR))) { list.append(new Action("View", UserFileInteraction::S_view, 0)); - if (info->size <= MAX_FILE_SIZE_TO_HEX_VIEW) { - printf("Hex view: file size %d <= %d\n", info->size, MAX_FILE_SIZE_TO_HEX_VIEW); - list.append(new Action("Hex View", UserFileInteraction::S_hex_view, 0)); - count++; - } - count++; + list.append(new Action("Hex View", UserFileInteraction::S_hex_view, 0)); + count += 2; } if (info->is_writable()) { list.append(new Action("Rename", UserFileInteraction::S_rename, 0)); @@ -139,7 +135,7 @@ int UserFileInteraction::S_delete(SubsysCommand *cmd) return 0; } -int _view(SubsysCommand *cmd, bool hex) +int _view(SubsysCommand *cmd, EditorType editor_type) { FileManager *fm = FileManager::getFileManager(); File *f = 0; @@ -149,12 +145,15 @@ int _view(SubsysCommand *cmd, bool hex) uint32_t size = f->get_size(); char *text_buf = new char[size + 1]; FRESULT fres = f->read(text_buf, size, &transferred); - printf("Res = %d. Read text buffer: %d bytes\n", fres, transferred); + printf("Res = %d. Read text buffer: %d bytes. File size: %d bytes\n", fres, transferred, size); text_buf[transferred] = 0; - if (hex) { - cmd->user_interface->run_hex_editor(text_buf, transferred); - } else { - cmd->user_interface->run_editor(text_buf, transferred); + switch (editor_type) { + case HEX_EDITOR: + cmd->user_interface->run_hex_editor(text_buf, transferred); + break; + default: + cmd->user_interface->run_editor(text_buf, transferred); + break; } delete text_buf; } @@ -163,12 +162,12 @@ int _view(SubsysCommand *cmd, bool hex) int UserFileInteraction::S_view(SubsysCommand *cmd) { - return _view(cmd, false); + return _view(cmd, TEXT_EDITOR); } int UserFileInteraction::S_hex_view(SubsysCommand *cmd) { - return _view(cmd, true); + return _view(cmd, HEX_EDITOR); } int UserFileInteraction::S_createDir(SubsysCommand *cmd) diff --git a/software/userinterface/user_file_interaction.h b/software/userinterface/user_file_interaction.h index 2ef9dc304..3119deec7 100644 --- a/software/userinterface/user_file_interaction.h +++ b/software/userinterface/user_file_interaction.h @@ -13,6 +13,8 @@ #include "subsys.h" #include "filemanager.h" +enum EditorType { TEXT_EDITOR, HEX_EDITOR}; + class Path; class Action; class BrowsableDirEntry; diff --git a/software/userinterface/userinterface.cc b/software/userinterface/userinterface.cc index cd5698109..0ea64a36e 100644 --- a/software/userinterface/userinterface.cc +++ b/software/userinterface/userinterface.cc @@ -383,57 +383,24 @@ void UserInterface :: hide_progress(void) delete status_box; } -void UserInterface :: run_editor(const char *text_buf, int max_len) +void UserInterface :: run_editor(Editor *editor) { - Editor *edit = new Editor(this, text_buf, max_len); - edit->init(screen, keyboard); + editor->init(screen, keyboard); int ret; do { - ret = edit->poll(0); + ret = editor->poll(0); } while(!ret); - edit->deinit(); + editor->deinit(); } -void add_hex_byte(char *buf, int offset, uint8_t byte) -{ - char hex_chars[] = "0123456789ABCDEF"; - buf[offset] = hex_chars[(byte >> 4) & 0x0F]; - buf[offset + 1] = hex_chars[byte & 0x0F]; -} - -void add_hex_word(char *buf, int offset, uint16_t word) +void UserInterface :: run_editor(const char *text_buf, int max_len) { - add_hex_byte(buf, offset, (word >> 8) & 0xFF); - add_hex_byte(buf, offset + 2, word & 0xFF); + run_editor(new Editor(this, text_buf, max_len)); } void UserInterface :: run_hex_editor(const char *text_buf, int max_len) { - #define HEX_COL_START 5 - #define TXT_COL_START (HEX_COL_START + (3 * BYTES_PER_HEX_ROW)) - int hex_len = CHARS_PER_HEX_ROW * (max_len / BYTES_PER_HEX_ROW + 1); - char hex_buf[hex_len + 1]; - for (int i = 0; i < hex_len; i++) { - hex_buf[i] = ' '; - } - int row_offset = 0; - for (int i = 0; i < max_len; i++) { - int col = i % BYTES_PER_HEX_ROW; - // offset and line break - if (col == 0) { - if (i > 0) { - hex_buf[row_offset + CHARS_PER_HEX_ROW - 1] = '\n'; - row_offset += CHARS_PER_HEX_ROW; - } - add_hex_word(hex_buf, row_offset, i); - } - // data - unsigned char c = text_buf[i]; - add_hex_byte(hex_buf, row_offset + HEX_COL_START + (3 * col), c); - // represent all non-printable characters as '.' based on the character set used by firmware version 3.10j - hex_buf[row_offset + TXT_COL_START + col] = (char) ((c == 0 || c == 8 || c == 10 || c == 13 || (c >=20 && c <= 31) || (c >= 144 && c <= 159)) ? '.' : c); - } - run_editor(hex_buf, hex_len); + run_editor(new HexEditor(this, text_buf, max_len)); } int UserInterface :: enterSelection() diff --git a/software/userinterface/userinterface.h b/software/userinterface/userinterface.h index c148edd48..0eeb1b212 100644 --- a/software/userinterface/userinterface.h +++ b/software/userinterface/userinterface.h @@ -29,8 +29,10 @@ #define CFG_USERIF_FILENAME_OVERFLOW_SQUEEZE 0x0C #define BYTES_PER_HEX_ROW 8 -#define CHARS_PER_HEX_ROW 38 +#define CHARS_PER_HEX_ROW 37 +class Editor; +class HexEditor; class UserInterface : public ConfigurableObject, public HostClient { private: @@ -48,6 +50,8 @@ class UserInterface : public ConfigurableObject, public HostClient void set_screen_title(void); bool pollFocussed(void); bool buttonDownFor(uint32_t ms); + void run_editor(Editor *); + UIStatusBox *status_box; public: int color_border, color_bg, color_fg, color_sel, color_sel_bg, config_save, filename_overflow_squeeze; diff --git a/target/u64/nios2/ultimate/Makefile b/target/u64/nios2/ultimate/Makefile index a3769e025..ba6344ad9 100755 --- a/target/u64/nios2/ultimate/Makefile +++ b/target/u64/nios2/ultimate/Makefile @@ -89,6 +89,7 @@ SRCS_CC = u2p_init.cc \ ui_elements.cc \ user_file_interaction.cc \ editor.cc \ + hex_editor.cc \ tree_browser.cc \ tree_browser_state.cc \ config_menu.cc \ From 541af318890c3e6db6a939b9bfb10e48d794f99a Mon Sep 17 00:00:00 2001 From: Christian Gleissner Date: Tue, 4 Jul 2023 18:06:48 +0100 Subject: [PATCH 3/7] Support new editor keyboard shortcuts to better navigate across large files: home/F2 (start of file) and end/F8 (end of file) --- software/userinterface/editor.cc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/software/userinterface/editor.cc b/software/userinterface/editor.cc index 12342ca35..ed0ca625c 100644 --- a/software/userinterface/editor.cc +++ b/software/userinterface/editor.cc @@ -188,7 +188,7 @@ int Editor :: handle_key(uint8_t c) draw(); } break; - case KEY_F1: // F1 -> page up + case KEY_F1: // page up case KEY_PAGEUP: first_line -= height + 1; if (first_line < 0) { @@ -196,7 +196,12 @@ int Editor :: handle_key(uint8_t c) } draw(); break; - case KEY_F7: // F7 -> page down + case KEY_F2: // start + case KEY_HOME: + first_line = 0; + draw(); + break; + case KEY_F7: // page down case KEY_PAGEDOWN: first_line += height - 1; if (first_line >= linecount - height) { @@ -206,6 +211,11 @@ int Editor :: handle_key(uint8_t c) } draw(); break; + case KEY_F8: // end + case KEY_END: + first_line = linecount - height; + draw(); + break; case KEY_BACK: // backspace break; case KEY_SPACE: // space From b1ccf72fd68cf6a03751c3d2b7fb7f3c6ca0dc0a Mon Sep 17 00:00:00 2001 From: Christian Gleissner Date: Sat, 8 Jul 2023 20:58:46 +0100 Subject: [PATCH 4/7] Peek and poke --- software/system/dump_hex.c | 14 ++++ software/system/dump_hex.h | 2 + software/u64/u64_config.cc | 106 ++++++++++++++++++++++----- software/u64/u64_config.h | 4 + software/userinterface/ass_editor.cc | 58 +++++++++++++++ software/userinterface/editor.cc | 6 +- software/userinterface/editor.h | 9 +++ software/userinterface/hex_editor.cc | 19 +---- 8 files changed, 180 insertions(+), 38 deletions(-) create mode 100644 software/userinterface/ass_editor.cc diff --git a/software/system/dump_hex.c b/software/system/dump_hex.c index 0ffac6f01..d042cf0c5 100644 --- a/software/system/dump_hex.c +++ b/software/system/dump_hex.c @@ -27,6 +27,8 @@ #define DUMP_BYTES 16 #endif +static const char hex_chars[] = "0123456789ABCDEF"; + void dump_hex_actual(void *pp, int len, int relative) { int w,t; @@ -124,3 +126,15 @@ void dump_hex_verify(void *pp1, void *pp2, int len) } } } + +void dump_hex_byte(char *buf, int offset, uint8_t byte) +{ + buf[offset] = hex_chars[(byte >> 4) & 0x0F]; + buf[offset + 1] = hex_chars[byte & 0x0F]; +} + +void dump_hex_word(char *buf, int offset, uint16_t word) +{ + dump_hex_byte(buf, offset, (word >> 8) & 0xFF); + dump_hex_byte(buf, offset + 2, word & 0xFF); +} diff --git a/software/system/dump_hex.h b/software/system/dump_hex.h index e249b82d1..8ea2a576a 100644 --- a/software/system/dump_hex.h +++ b/software/system/dump_hex.h @@ -33,6 +33,8 @@ void dump_hex_relative(void *pp, int len); void dump_hex_actual(void *pp, int len, int relative); void dump_hex_dirty(void *p, int len, uint8_t ptrn); void dump_hex_verify(void *pp1, void *pp2, int len); +void dump_hex_byte(char *buf, int offset, uint8_t byte); +void dump_hex_word(char *buf, int offset, uint16_t word); #ifdef __cplusplus } diff --git a/software/u64/u64_config.cc b/software/u64/u64_config.cc index 2a5fc424b..a65ca96b5 100755 --- a/software/u64/u64_config.cc +++ b/software/u64/u64_config.cc @@ -128,9 +128,12 @@ static SemaphoreHandle_t resetSemaphore; #define CFG_BADLINES_EN 0x53 #define CFG_SUPERCPU_DET 0x54 +#define CFG_MONITOR 0x60 + #define CFG_SCAN_MODE_TEST 0xA8 #define CFG_VIC_TEST 0xA9 + uint8_t C64_EMUSID1_BASE_BAK; uint8_t C64_EMUSID2_BASE_BAK; uint8_t C64_SID1_BASE_BAK; @@ -1050,11 +1053,15 @@ int U64Config :: setSidEmuParams(ConfigItem *it) #define MENU_U64_WIFI_ENABLE 4 #define MENU_U64_WIFI_BOOT 5 #define MENU_U64_DETECT_SIDS 6 -#define MENU_U64_POKE 7 +#define MENU_U64_PEEK 7 +#define MENU_U64_PEEK_RANGE 8 +#define MENU_U64_POKE 9 void U64Config :: create_task_items(void) { TaskCategory *dev = TasksCollection :: getCategory("Developer", SORT_ORDER_DEVELOPER); + myActions.peek = new Action("Peek", SUBSYSID_U64, MENU_U64_PEEK); + myActions.peekrange = new Action("Peek Range", SUBSYSID_U64, MENU_U64_PEEK_RANGE); myActions.poke = new Action("Poke", SUBSYSID_U64, MENU_U64_POKE); myActions.saveedid = new Action("Save EDID to file", SUBSYSID_U64, MENU_U64_SAVEEDID); myActions.siddetect = new Action("Detect SIDs", SUBSYSID_U64, MENU_U64_DETECT_SIDS); @@ -1062,9 +1069,11 @@ void U64Config :: create_task_items(void) myActions.wifion = new Action("Enable WiFi", SUBSYSID_U64, MENU_U64_WIFI_ENABLE); myActions.wifiboot = new Action("Enable WiFi Boot", SUBSYSID_U64, MENU_U64_WIFI_BOOT); - dev->append(myActions.saveedid ); + dev->append(myActions.saveedid); + dev->append(myActions.peek); + dev->append(myActions.peekrange); + dev->append(myActions.poke); #if DEVELOPER > 0 - dev->append(myActions.poke ); dev->append(myActions.siddetect); dev->append(myActions.wifioff ); dev->append(myActions.wifion ); @@ -1077,6 +1086,24 @@ void U64Config :: update_task_items(bool writablePath, Path *p) myActions.saveedid->setDisabled(!writablePath); } +bool U64Config :: stop_c64() { + portENTER_CRITICAL(); + bool running = !(C64_STOP & C64_HAS_STOPPED); + if (running) { + C64 *machine = C64 :: getMachine(); + machine->stop(false); + } + return running; +} + +void U64Config :: resume_c64(bool stopped) { + if (stopped) { + C64 *machine = C64 :: getMachine(); + machine->start(); + } + portEXIT_CRITICAL(); +} + int U64Config :: executeCommand(SubsysCommand *cmd) { File *f = 0; @@ -1091,7 +1118,9 @@ int U64Config :: executeCommand(SubsysCommand *cmd) C64 *machine; I2C_Driver i2c; static char poke_buffer[16]; - uint32_t addr, value; + static char peek_buffer[16]; + static char peek_range_buffer[16]; + uint32_t addr, end_addr, value; switch(cmd->functionID) { case MENU_U64_SAVEEDID: @@ -1153,24 +1182,66 @@ int U64Config :: executeCommand(SubsysCommand *cmd) U64_WIFI_CONTROL = 7; break; - case MENU_U64_POKE: - if (cmd->user_interface->string_box("Poke AAAA,DD", poke_buffer, 16)) { + case MENU_U64_PEEK: + if (cmd->user_interface->string_box("Peek AAAA", peek_buffer, 16)) { + sscanf(peek_buffer, "%x", &addr); - sscanf(poke_buffer, "%x,%x", &addr, &value); - - C64 *machine = C64 :: getMachine(); - portENTER_CRITICAL(); + bool stopped = stop_c64(); + value = C64_PEEK(addr); + resume_c64(stopped); - if (!(C64_STOP & C64_HAS_STOPPED)) { - machine->stop(false); + char msg[20]; + sprintf(msg, "Peek(%4x)=%2x", addr, value); + cmd->user_interface->popup(msg, BUTTON_OK); + } + break; - C64_POKE(addr, value); + // TODO This functionality could evolve into a machine code monitor + case MENU_U64_PEEK_RANGE: + if (cmd->user_interface->string_box("Peek AAAA,BBBB", peek_range_buffer, 16)) { + sscanf(peek_range_buffer, "%x,%x", &addr, &end_addr); + int len = end_addr - addr; + if (len > 128) { + cmd->user_interface->popup("Max supported range is 128 bytes", BUTTON_OK); + return 0; + } - machine->resume(); - } else { - C64_POKE(addr, value); + char msg[700]; + memset(msg, ' ', 699); + int src_offset = 0; + int dst_offset = 0; + bool stopped = stop_c64(); + for (int src_offset = 0; src_offset < len; src_offset++) { + int a = addr + src_offset; + int src_offset_in_current_line = src_offset % 8; + if (src_offset_in_current_line == 0) { + if (src_offset > 0) { + msg[dst_offset + 37] = '\n'; + dst_offset += 38; + } + dump_hex_word(msg, dst_offset, a); + } + uint8_t c = (uint8_t) C64_PEEK(a); + dump_hex_byte(msg, dst_offset + 5 + (3 * src_offset_in_current_line), c); + msg[dst_offset + 32] = (char) ((c == 0 || c == 8 || c == 10 || c == 13 || (c >=20 && c <= 31) || (c >= 144 && c <= 159)) ? '.' : c); } - portEXIT_CRITICAL(); + resume_c64(stopped); + + cmd->user_interface->popup(msg, BUTTON_OK); + } + break; + + case MENU_U64_POKE: + if (cmd->user_interface->string_box("Poke AAAA,DD", poke_buffer, 16)) { + sscanf(poke_buffer, "%x,%x", &addr, &value); + + bool stopped = stop_c64(); + C64_POKE(addr, value); + resume_c64(stopped); + + char msg[20]; + sprintf(msg, "Poke(%4x,%2x)", addr, value); + cmd->user_interface->popup(msg, BUTTON_OK); } break; @@ -1194,7 +1265,6 @@ int U64Config :: executeCommand(SubsysCommand *cmd) return 0; } - uint8_t U64Config :: GetSidType(int slot) { uint8_t val; diff --git a/software/u64/u64_config.h b/software/u64/u64_config.h index cabd2350e..f96e9ef1f 100755 --- a/software/u64/u64_config.h +++ b/software/u64/u64_config.h @@ -25,6 +25,8 @@ extern U64Config u64_configurator; class U64Config : public ConfigurableObject, ObjectWithMenu, SubSystem { struct { + Action *peek; + Action *peekrange; Action *poke; Action *saveedid; Action *siddetect; @@ -103,6 +105,8 @@ class U64Config : public ConfigurableObject, ObjectWithMenu, SubSystem void create_task_items(void); void update_task_items(bool writablePath, Path *p); int executeCommand(SubsysCommand *cmd); + bool stop_c64(); + void resume_c64(bool stopped); void effectuate_settings(); static int setPllOffset(ConfigItem *it); diff --git a/software/userinterface/ass_editor.cc b/software/userinterface/ass_editor.cc new file mode 100644 index 000000000..62f53120c --- /dev/null +++ b/software/userinterface/ass_editor.cc @@ -0,0 +1,58 @@ +#include "editor.h" +#include +#include + +static const char hex_chars[] = "0123456789ABCDEF"; + +// Assembly editor; currently only supports disassembly. +AssEditor :: AssEditor(UserInterface *ui, const char *text_buffer, int max_len) : Editor(ui, text_buffer, max_len) +{ +} + +void AssEditor :: line_breakdown(const char *text_buffer, int buffer_size) +{ + Line current; + int pos = 0; + linecount = 0; + + text->clear_list(); + while (pos < buffer_size) { + current.buffer = text_buffer + pos; + current.length = (buffer_size - pos > BYTES_PER_HEX_ROW) ? BYTES_PER_HEX_ROW : buffer_size - pos;; + text->append(current); + pos += current.length; + linecount++; + } +} + +inline void add_hex_byte(char *buf, int offset, uint8_t byte) +{ + buf[offset] = hex_chars[(byte >> 4) & 0x0F]; + buf[offset + 1] = hex_chars[byte & 0x0F]; +} + +inline void add_hex_word(char *buf, int offset, uint16_t word) +{ + add_hex_byte(buf, offset, (word >> 8) & 0xFF); + add_hex_byte(buf, offset + 2, word & 0xFF); +} + +void HexEditor :: draw(int line_idx, Line *line) +{ + #define HEX_COL_START 5 + #define TXT_COL_START (HEX_COL_START + (3 * BYTES_PER_HEX_ROW)) + + char hex_buf[CHARS_PER_HEX_ROW]; + memset(hex_buf, ' ', CHARS_PER_HEX_ROW); + add_hex_word(hex_buf, 0, line_idx * BYTES_PER_HEX_ROW); + + for (int i = 0; i < line->length; i++) { + uint8_t c = (uint8_t) line->buffer[i]; + add_hex_byte(hex_buf, HEX_COL_START + (3 * i), c); + // represent all non-printable characters as '.' based on the character set used by firmware version 3.10j + hex_buf[TXT_COL_START + i] = (char) ((c == 0 || c == 8 || c == 10 || c == 13 || (c >=20 && c <= 31) || (c >= 144 && c <= 159)) ? '.' : c); + } + + window->output_length(hex_buf, CHARS_PER_HEX_ROW); + window->repeat(' ', window->get_size_x() - CHARS_PER_HEX_ROW); +} diff --git a/software/userinterface/editor.cc b/software/userinterface/editor.cc index ed0ca625c..a1cc56a67 100644 --- a/software/userinterface/editor.cc +++ b/software/userinterface/editor.cc @@ -60,7 +60,7 @@ void Editor :: line_breakdown(const char *text_buffer, int buffer_size) // printf("Line length = %d\n", line_length); text->clear_list(); - while(text_buffer[pos] && pos < buffer_size) { + while(pos < buffer_size) { current.buffer = &text_buffer[pos]; current.length = -1; last_space = -1; @@ -68,13 +68,11 @@ void Editor :: line_breakdown(const char *text_buffer, int buffer_size) int max_line_length = (line_length > (buffer_size - pos)) ? buffer_size - pos : line_length; for(int i=0;iappend(current); linecount++; - if(last == 0) - return; i++; if((c[i] == 0x0a)&&(last == 0x0d)) i++; diff --git a/software/userinterface/editor.h b/software/userinterface/editor.h index 3817867f1..c52d8ffde 100644 --- a/software/userinterface/editor.h +++ b/software/userinterface/editor.h @@ -48,4 +48,13 @@ class HexEditor : public Editor HexEditor(UserInterface *ui, const char *text_buffer, int max_len); }; +class AssEditor : public Editor +{ + UserInterface *user_interface; + void line_breakdown(const char *text_buffer, int buffer_size); + void draw(int line_idx, Line *line); +public: + AssEditor(UserInterface *ui, const char *text_buffer, int max_len); +}; + #endif diff --git a/software/userinterface/hex_editor.cc b/software/userinterface/hex_editor.cc index df1bbce11..3f82b6264 100644 --- a/software/userinterface/hex_editor.cc +++ b/software/userinterface/hex_editor.cc @@ -1,8 +1,7 @@ #include "editor.h" #include #include - -static const char hex_chars[] = "0123456789ABCDEF"; +#include HexEditor :: HexEditor(UserInterface *ui, const char *text_buffer, int max_len) : Editor(ui, text_buffer, max_len) { @@ -24,18 +23,6 @@ void HexEditor :: line_breakdown(const char *text_buffer, int buffer_size) } } -inline void add_hex_byte(char *buf, int offset, uint8_t byte) -{ - buf[offset] = hex_chars[(byte >> 4) & 0x0F]; - buf[offset + 1] = hex_chars[byte & 0x0F]; -} - -inline void add_hex_word(char *buf, int offset, uint16_t word) -{ - add_hex_byte(buf, offset, (word >> 8) & 0xFF); - add_hex_byte(buf, offset + 2, word & 0xFF); -} - void HexEditor :: draw(int line_idx, Line *line) { #define HEX_COL_START 5 @@ -43,11 +30,11 @@ void HexEditor :: draw(int line_idx, Line *line) char hex_buf[CHARS_PER_HEX_ROW]; memset(hex_buf, ' ', CHARS_PER_HEX_ROW); - add_hex_word(hex_buf, 0, line_idx * BYTES_PER_HEX_ROW); + dump_hex_word(hex_buf, 0, line_idx * BYTES_PER_HEX_ROW); for (int i = 0; i < line->length; i++) { uint8_t c = (uint8_t) line->buffer[i]; - add_hex_byte(hex_buf, HEX_COL_START + (3 * i), c); + dump_hex_byte(hex_buf, HEX_COL_START + (3 * i), c); // represent all non-printable characters as '.' based on the character set used by firmware version 3.10j hex_buf[TXT_COL_START + i] = (char) ((c == 0 || c == 8 || c == 10 || c == 13 || (c >=20 && c <= 31) || (c >= 144 && c <= 159)) ? '.' : c); } From af617add6a6a874e55594994c315b24c2f75cffd Mon Sep 17 00:00:00 2001 From: Christian Gleissner Date: Sat, 8 Jul 2023 23:44:51 +0100 Subject: [PATCH 5/7] Added hex monitor for entire C64 RAM --- software/u64/u64_config.cc | 51 ++++++-------------------------------- software/u64/u64_config.h | 2 +- 2 files changed, 9 insertions(+), 44 deletions(-) diff --git a/software/u64/u64_config.cc b/software/u64/u64_config.cc index a65ca96b5..6cacd4024 100755 --- a/software/u64/u64_config.cc +++ b/software/u64/u64_config.cc @@ -1054,15 +1054,15 @@ int U64Config :: setSidEmuParams(ConfigItem *it) #define MENU_U64_WIFI_BOOT 5 #define MENU_U64_DETECT_SIDS 6 #define MENU_U64_PEEK 7 -#define MENU_U64_PEEK_RANGE 8 -#define MENU_U64_POKE 9 +#define MENU_U64_POKE 8 +#define MENU_U64_MONITOR 9 void U64Config :: create_task_items(void) { TaskCategory *dev = TasksCollection :: getCategory("Developer", SORT_ORDER_DEVELOPER); myActions.peek = new Action("Peek", SUBSYSID_U64, MENU_U64_PEEK); - myActions.peekrange = new Action("Peek Range", SUBSYSID_U64, MENU_U64_PEEK_RANGE); myActions.poke = new Action("Poke", SUBSYSID_U64, MENU_U64_POKE); + myActions.monitor = new Action("Monitor", SUBSYSID_U64, MENU_U64_MONITOR); myActions.saveedid = new Action("Save EDID to file", SUBSYSID_U64, MENU_U64_SAVEEDID); myActions.siddetect = new Action("Detect SIDs", SUBSYSID_U64, MENU_U64_DETECT_SIDS); myActions.wifioff = new Action("Disable WiFi", SUBSYSID_U64, MENU_U64_WIFI_DISABLE); @@ -1071,8 +1071,8 @@ void U64Config :: create_task_items(void) dev->append(myActions.saveedid); dev->append(myActions.peek); - dev->append(myActions.peekrange); dev->append(myActions.poke); + dev->append(myActions.monitor); #if DEVELOPER > 0 dev->append(myActions.siddetect); dev->append(myActions.wifioff ); @@ -1185,52 +1185,13 @@ int U64Config :: executeCommand(SubsysCommand *cmd) case MENU_U64_PEEK: if (cmd->user_interface->string_box("Peek AAAA", peek_buffer, 16)) { sscanf(peek_buffer, "%x", &addr); - - bool stopped = stop_c64(); value = C64_PEEK(addr); - resume_c64(stopped); - char msg[20]; sprintf(msg, "Peek(%4x)=%2x", addr, value); cmd->user_interface->popup(msg, BUTTON_OK); } break; - // TODO This functionality could evolve into a machine code monitor - case MENU_U64_PEEK_RANGE: - if (cmd->user_interface->string_box("Peek AAAA,BBBB", peek_range_buffer, 16)) { - sscanf(peek_range_buffer, "%x,%x", &addr, &end_addr); - int len = end_addr - addr; - if (len > 128) { - cmd->user_interface->popup("Max supported range is 128 bytes", BUTTON_OK); - return 0; - } - - char msg[700]; - memset(msg, ' ', 699); - int src_offset = 0; - int dst_offset = 0; - bool stopped = stop_c64(); - for (int src_offset = 0; src_offset < len; src_offset++) { - int a = addr + src_offset; - int src_offset_in_current_line = src_offset % 8; - if (src_offset_in_current_line == 0) { - if (src_offset > 0) { - msg[dst_offset + 37] = '\n'; - dst_offset += 38; - } - dump_hex_word(msg, dst_offset, a); - } - uint8_t c = (uint8_t) C64_PEEK(a); - dump_hex_byte(msg, dst_offset + 5 + (3 * src_offset_in_current_line), c); - msg[dst_offset + 32] = (char) ((c == 0 || c == 8 || c == 10 || c == 13 || (c >=20 && c <= 31) || (c >= 144 && c <= 159)) ? '.' : c); - } - resume_c64(stopped); - - cmd->user_interface->popup(msg, BUTTON_OK); - } - break; - case MENU_U64_POKE: if (cmd->user_interface->string_box("Poke AAAA,DD", poke_buffer, 16)) { sscanf(poke_buffer, "%x,%x", &addr, &value); @@ -1245,6 +1206,10 @@ int U64Config :: executeCommand(SubsysCommand *cmd) } break; + case MENU_U64_MONITOR: + cmd->user_interface->run_hex_editor((const char *) C64_MEMORY_BASE, 0x10000); + break; + case MENU_U64_DETECT_SIDS: machine = C64 :: getMachine(); machine->stop(false); diff --git a/software/u64/u64_config.h b/software/u64/u64_config.h index f96e9ef1f..d2642454f 100755 --- a/software/u64/u64_config.h +++ b/software/u64/u64_config.h @@ -26,8 +26,8 @@ class U64Config : public ConfigurableObject, ObjectWithMenu, SubSystem { struct { Action *peek; - Action *peekrange; Action *poke; + Action *monitor; Action *saveedid; Action *siddetect; Action *wifioff; From 257e20e06896c2ceba8b6d5b447d2e9fb1a0c8e7 Mon Sep 17 00:00:00 2001 From: Christian Gleissner Date: Sun, 9 Jul 2023 01:03:38 +0100 Subject: [PATCH 6/7] Fixed monitor for U64 in 'Freeze' UI mode --- software/u64/u64_config.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/software/u64/u64_config.cc b/software/u64/u64_config.cc index 6cacd4024..99b8c7648 100755 --- a/software/u64/u64_config.cc +++ b/software/u64/u64_config.cc @@ -1062,7 +1062,7 @@ void U64Config :: create_task_items(void) TaskCategory *dev = TasksCollection :: getCategory("Developer", SORT_ORDER_DEVELOPER); myActions.peek = new Action("Peek", SUBSYSID_U64, MENU_U64_PEEK); myActions.poke = new Action("Poke", SUBSYSID_U64, MENU_U64_POKE); - myActions.monitor = new Action("Monitor", SUBSYSID_U64, MENU_U64_MONITOR); + myActions.monitor = new Action("Monitor", SUBSYSID_U64, MENU_U64_MONITOR); myActions.saveedid = new Action("Save EDID to file", SUBSYSID_U64, MENU_U64_SAVEEDID); myActions.siddetect = new Action("Detect SIDs", SUBSYSID_U64, MENU_U64_DETECT_SIDS); myActions.wifioff = new Action("Disable WiFi", SUBSYSID_U64, MENU_U64_WIFI_DISABLE); @@ -1070,9 +1070,11 @@ void U64Config :: create_task_items(void) myActions.wifiboot = new Action("Enable WiFi Boot", SUBSYSID_U64, MENU_U64_WIFI_BOOT); dev->append(myActions.saveedid); + #if U64 dev->append(myActions.peek); dev->append(myActions.poke); dev->append(myActions.monitor); + #endif #if DEVELOPER > 0 dev->append(myActions.siddetect); dev->append(myActions.wifioff ); @@ -1182,6 +1184,7 @@ int U64Config :: executeCommand(SubsysCommand *cmd) U64_WIFI_CONTROL = 7; break; + // TODO Only works in "Config / User Interface / HDMI overlay mode"; ensure it also works in "Freeze mode" case MENU_U64_PEEK: if (cmd->user_interface->string_box("Peek AAAA", peek_buffer, 16)) { sscanf(peek_buffer, "%x", &addr); @@ -1192,6 +1195,7 @@ int U64Config :: executeCommand(SubsysCommand *cmd) } break; + // TODO Only works in "Config / User Interface / HDMI overlay mode"; ensure it also works in "Freeze mode" case MENU_U64_POKE: if (cmd->user_interface->string_box("Poke AAAA,DD", poke_buffer, 16)) { sscanf(poke_buffer, "%x,%x", &addr, &value); @@ -1207,7 +1211,11 @@ int U64Config :: executeCommand(SubsysCommand *cmd) break; case MENU_U64_MONITOR: - cmd->user_interface->run_hex_editor((const char *) C64_MEMORY_BASE, 0x10000); + int ram_size = 64 * 1024; + uint8_t *pb = new uint8_t[ram_size]; + C64 :: getMachine()->get_all_memory(pb); + cmd->user_interface->run_hex_editor((const char *) pb, ram_size); + delete[] pb; break; case MENU_U64_DETECT_SIDS: From bf47964782b0c4511c1eca5b1055677bcfdb373b Mon Sep 17 00:00:00 2001 From: Christian Gleissner Date: Sun, 9 Jul 2023 08:59:50 +0100 Subject: [PATCH 7/7] Fix peek to work in both freeze and HDMI overlay modes --- software/io/c64/c64.h | 5 +++- software/u64/u64_config.cc | 21 +++++++++------- software/u64/u64_machine.cc | 50 +++++++++++++++++++++++++++++++------ software/u64/u64_machine.h | 8 +++++- 4 files changed, 66 insertions(+), 18 deletions(-) diff --git a/software/io/c64/c64.h b/software/io/c64/c64.h index 252a207b5..279a2d9c3 100644 --- a/software/io/c64/c64.h +++ b/software/io/c64/c64.h @@ -304,7 +304,10 @@ class C64 : public GenericHost, ConfigurableObject static void hard_stop(void); void resume(void); void freeze(void); - virtual void get_all_memory(uint8_t *) { /* NOT YET IMPLEMENTED */ }; + + virtual void get_all_memory(uint8_t *) { /* NOT YET IMPLEMENTED EXCEPT FOR U64*/ }; + virtual uint8_t peek(uint32_t) { /* NOT YET IMPLEMENTED EXCEPT FOR U64*/ }; + virtual void poke(uint32_t, uint8_t) { /* NOT YET IMPLEMENTED EXCEPT FOR U64*/ }; static uint8_t get_exrom_game(void) { return (C64_CLOCK_DETECT & 0x0C) >> 2; diff --git a/software/u64/u64_config.cc b/software/u64/u64_config.cc index 99b8c7648..46abb90c8 100755 --- a/software/u64/u64_config.cc +++ b/software/u64/u64_config.cc @@ -1070,11 +1070,13 @@ void U64Config :: create_task_items(void) myActions.wifiboot = new Action("Enable WiFi Boot", SUBSYSID_U64, MENU_U64_WIFI_BOOT); dev->append(myActions.saveedid); - #if U64 + +#if U64 dev->append(myActions.peek); dev->append(myActions.poke); dev->append(myActions.monitor); - #endif +#endif + #if DEVELOPER > 0 dev->append(myActions.siddetect); dev->append(myActions.wifioff ); @@ -1184,28 +1186,27 @@ int U64Config :: executeCommand(SubsysCommand *cmd) U64_WIFI_CONTROL = 7; break; - // TODO Only works in "Config / User Interface / HDMI overlay mode"; ensure it also works in "Freeze mode" case MENU_U64_PEEK: if (cmd->user_interface->string_box("Peek AAAA", peek_buffer, 16)) { sscanf(peek_buffer, "%x", &addr); - value = C64_PEEK(addr); + + value = C64 :: getMachine()->peek(addr); + char msg[20]; sprintf(msg, "Peek(%4x)=%2x", addr, value); cmd->user_interface->popup(msg, BUTTON_OK); } break; - // TODO Only works in "Config / User Interface / HDMI overlay mode"; ensure it also works in "Freeze mode" case MENU_U64_POKE: if (cmd->user_interface->string_box("Poke AAAA,DD", poke_buffer, 16)) { sscanf(poke_buffer, "%x,%x", &addr, &value); - bool stopped = stop_c64(); - C64_POKE(addr, value); - resume_c64(stopped); + C64 :: getMachine()->poke(addr, (uint8_t) value); + uint8_t verified_value = C64 :: getMachine()->peek(addr); char msg[20]; - sprintf(msg, "Poke(%4x,%2x)", addr, value); + sprintf(msg, "Poke(%4x,%2x)=%2x", addr, value, verified_value); cmd->user_interface->popup(msg, BUTTON_OK); } break; @@ -1213,7 +1214,9 @@ int U64Config :: executeCommand(SubsysCommand *cmd) case MENU_U64_MONITOR: int ram_size = 64 * 1024; uint8_t *pb = new uint8_t[ram_size]; + C64 :: getMachine()->get_all_memory(pb); + cmd->user_interface->run_hex_editor((const char *) pb, ram_size); delete[] pb; break; diff --git a/software/u64/u64_machine.cc b/software/u64/u64_machine.cc index 89bdb7bc9..8e4d964b3 100644 --- a/software/u64/u64_machine.cc +++ b/software/u64/u64_machine.cc @@ -3,24 +3,60 @@ #include "FreeRTOS.h" #include -void U64Machine :: get_all_memory(uint8_t *pb) -{ +bool U64Machine :: before_memory_access() { bool freezerMenu = isFrozen; - if (!freezerMenu) { stop(false); } portENTER_CRITICAL(); C64_DMA_MEMONLY = 1; - memcpy(pb, (uint8_t *)C64_MEMORY_BASE, 65536); + return freezerMenu; +} + +void U64Machine :: after_memory_access(uint8_t *pb, bool freezerMenu) { C64_DMA_MEMONLY = 0; portEXIT_CRITICAL(); - if (!freezerMenu) { resume(); - } else { // if we were in freezer menu, the backup of the 1K-4K RAM should be used - // restore memory + } else { + // if we were in freezer menu, the backup of the 1K-4K RAM should be used to restore memory memcpy(pb + 1024, screen_backup, 1024); memcpy(pb + 2048, ram_backup, 2048); } } + +void U64Machine :: get_all_memory(uint8_t *pb) +{ + bool freezerMenu = before_memory_access(); + memcpy(pb, (uint8_t *)C64_MEMORY_BASE, 65536); + after_memory_access(pb, freezerMenu); +} + +uint8_t U64Machine :: peek(uint32_t address) +{ + bool freezerMenu = before_memory_access(); + uint8_t *pb = new uint8_t[64 * 1024]; + get_all_memory(pb); + + uint8_t byte = *(pb + address); + printf("peek(%d + %d)=%d", pb, address, byte); + + after_memory_access(pb, freezerMenu); + delete[] pb; + return byte; +} + +void U64Machine :: poke(uint32_t address, uint8_t byte) +{ + bool freezerMenu = before_memory_access(); + uint8_t *pb = new uint8_t[64 * 1024]; + get_all_memory(pb); + + // TODO Ensure this works on freeze mode, not just in HDMI overlay mode + memset((void *) C64_MEMORY_BASE + address, byte, 1); + printf("poke(%d + %d)=%d", C64_MEMORY_BASE, address, byte); + + after_memory_access(pb, freezerMenu); + delete[] pb; +} + diff --git a/software/u64/u64_machine.h b/software/u64/u64_machine.h index 12008b731..4a814352d 100644 --- a/software/u64/u64_machine.h +++ b/software/u64/u64_machine.h @@ -8,9 +8,15 @@ class U64Machine : public C64 { U64Machine() { } ~U64Machine() { } + + bool before_memory_access(); + void after_memory_access(uint8_t *, bool); + void get_all_memory(uint8_t *pb); -public: + uint8_t peek(uint32_t address); + void poke(uint32_t address, uint8_t byte); +public: friend class C64; };