Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
6c78b0f
Added hex viewer
chrisgleissner Jul 4, 2023
1e1e778
Reduced memory use of hex viewer and using Editor inheritance hierarchy
chrisgleissner Jul 4, 2023
541af31
Support new editor keyboard shortcuts to better navigate across large…
chrisgleissner Jul 4, 2023
b1ccf72
Peek and poke
chrisgleissner Jul 8, 2023
af617ad
Added hex monitor for entire C64 RAM
chrisgleissner Jul 8, 2023
257e20e
Fixed monitor for U64 in 'Freeze' UI mode
chrisgleissner Jul 9, 2023
bf47964
Fix peek to work in both freeze and HDMI overlay modes
chrisgleissner Jul 9, 2023
c0d8f95
Merge remote-tracking branch 'origin/master' into feature/151-machine…
chrisgleissner Apr 26, 2026
7cc22c2
Merge branch 'master' into feature/151-machine-code-monitor
chrisgleissner Apr 26, 2026
0a3ba0e
Add machine code monitor
chrisgleissner Apr 28, 2026
6fb642a
Removed machine code monitor buffering and fixed borders
chrisgleissner Apr 28, 2026
607c5ed
Fix scrolling in disassembly mode
chrisgleissner Apr 28, 2026
484fcbe
Implement freeze mode support in machine monitor and memory backend
chrisgleissner Apr 28, 2026
70ecddf
Fix U2+ build
chrisgleissner Apr 28, 2026
5f22ff4
Refactor machine monitor and add assembler functionality
chrisgleissner Apr 29, 2026
142a61e
Refactor DEL key handling in MachineMonitor for unified behavior acro…
chrisgleissner Apr 29, 2026
22ca9e8
Add binary view and file I/O support to Machine Monitor
chrisgleissner Apr 29, 2026
9f6bf74
Move machine code monitor source to dedicated subfolder
chrisgleissner Apr 29, 2026
fb5d9d7
Remove unused build date and version macros from system_info.cc
chrisgleissner Apr 29, 2026
1b49b75
Refactor U64Machine to streamline CPU port access and improve memory …
chrisgleissner Apr 29, 2026
7c7a57e
Fix monitor edge cases
chrisgleissner Apr 29, 2026
68594db
Refactor Machine Monitor: Update CPU and VIC bank status handling. Im…
chrisgleissner Apr 30, 2026
23e82be
Add live VIC bank management and improve memory backend handling for …
chrisgleissner Apr 30, 2026
b106db9
Allow for concurrent use of multiple machine code monitors, both dire…
chrisgleissner Apr 30, 2026
1d1328d
Update key definitions to support user interface overlay/freeze mode …
chrisgleissner Apr 30, 2026
15e6286
Implement number picker functionality in Machine Monitor: add preview…
chrisgleissner Apr 30, 2026
ccb3535
Refactor machine monitor commands and improve popup handling
chrisgleissner Apr 30, 2026
428c617
Add opcode candidate collection with deterministic ordering and impro…
chrisgleissner Apr 30, 2026
710af6d
Refactor frozen byte write logic
chrisgleissner Apr 30, 2026
e795ac5
Enhance Machine Monitor number picker functionality for assembly view
chrisgleissner Apr 30, 2026
3d81fba
Simplify machine monitor codebase
chrisgleissner Apr 30, 2026
691fc27
Integrate and harden the machine code monitor
chrisgleissner May 1, 2026
9a4c22e
Reintroduce poke functionality
chrisgleissner May 1, 2026
c598b46
Refactor machine monitor to reduce code changes
chrisgleissner May 1, 2026
a406a2e
Enhance TreeBrowser and related classes with synthetic picker entry f…
chrisgleissner May 1, 2026
f71e9a3
Enhance machine monitor functionality with go command handling and co…
chrisgleissner May 1, 2026
c7a7570
Relocated machine code monitor to software/monitor and software/test/…
chrisgleissner May 1, 2026
c5eb37b
Reduce formatting churn in current branch
chrisgleissner May 1, 2026
3f165aa
Reduce formatting churn in current branch
chrisgleissner May 1, 2026
9f44142
Add machine code monitor initialization
chrisgleissner May 1, 2026
ef11326
Add context manager for test checks and enhance monitor tests
chrisgleissner May 1, 2026
99c3c35
Add support for U2
chrisgleissner May 1, 2026
0caa5df
Refactor conditional compilation for monitor initialization and task …
chrisgleissner May 1, 2026
9b62686
Add monitor bookmarks and polling
chrisgleissner May 2, 2026
cc46d0b
Add monitor bookmarks and polling
chrisgleissner May 2, 2026
51222e0
Improved binary rendering and bookmark shortcuts
chrisgleissner May 2, 2026
4c4804b
Remove test binaries
chrisgleissner May 2, 2026
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
14 changes: 14 additions & 0 deletions software/components/indexed_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,20 @@ class IndexedList
LEAVE_SAFE_SECTION
// printf("ed. El=%d. Size=%d\n", elements, size);
}

void prepend(T el) {
ENTER_SAFE_SECTION
if(elements == size)
expand();
for(int i=elements; i>0; i--) {
element_array[i] = element_array[i-1];
removal[i] = removal[i-1];
}
element_array[0] = el;
removal[0] = 0;
elements++;
LEAVE_SAFE_SECTION
}

int remove(T el) {
ENTER_SAFE_SECTION
Expand Down
60 changes: 60 additions & 0 deletions software/io/c64/c64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,66 @@ bool C64::is_in_reset(void)
return (C64_MODE & C64_MODE_RESET);
}

uint8_t C64::monitor_read_memory(uint16_t address)
{
bool stopped_it = false;
volatile uint8_t *ram = (volatile uint8_t *)C64_MEMORY_BASE;
uint8_t value;

if (!is_stopped()) {
stop(false);
stopped_it = true;
}

if (isFrozen && address >= 0x0400 && address < 0x0800) {
value = ((uint8_t *)screen_backup)[address - 0x0400];
} else if (isFrozen && address >= 0x0800 && address < 0x1000) {
value = ((uint8_t *)ram_backup)[address - 0x0800];
} else if (isFrozen && address >= 0xD800 && address < 0xDC00) {
value = ((uint8_t *)color_backup)[address - 0xD800];
} else {
value = ram[address];
}

if (stopped_it) {
resume();
}
return value;
}

void C64::monitor_write_memory(uint16_t address, uint8_t value)
{
bool stopped_it = false;
volatile uint8_t *ram = (volatile uint8_t *)C64_MEMORY_BASE;

if (!is_stopped()) {
stop(false);
stopped_it = true;
}

if (isFrozen && address >= 0x0400 && address < 0x0800) {
((uint8_t *)screen_backup)[address - 0x0400] = value;
} else if (isFrozen && address >= 0x0800 && address < 0x1000) {
((uint8_t *)ram_backup)[address - 0x0800] = value;
} else if (isFrozen && address >= 0xD800 && address < 0xDC00) {
((uint8_t *)color_backup)[address - 0xD800] = value;
} else {
ram[address] = value;
}

if (stopped_it) {
resume();
}
}

void C64::monitor_read_memory_block(uint16_t address, uint8_t *dst, uint16_t len)
{
while (len) {
*dst++ = monitor_read_memory(address++);
len--;
}
}

/*
-------------------------------------------------------------------------------
freeze (split in subfunctions)
Expand Down
14 changes: 13 additions & 1 deletion software/io/c64/c64.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#define MENU_MEASURE_TIMING_API 0x6413
#define MENU_C64_POWERCYCLE 0x6414
#define MENU_C64_CLEARMEM 0x6415
#define MENU_C64_MONITOR 0x6416

#define C64_DMA_LOAD 0x6464
#define C64_DRIVE_LOAD 0x6465
Expand Down Expand Up @@ -316,6 +317,8 @@ class C64 : public GenericHost, ConfigurableObject
void measure_timing(uint8_t *buffer);
virtual void get_all_memory(uint8_t *) { /* NOT YET IMPLEMENTED */ };
virtual void clear_ram(void) { /* NOT YET IMPLEMENTED */ };
virtual uint8_t peek(uint16_t) { return 0; /* NOT YET IMPLEMENTED */ };
virtual void poke(uint16_t, uint8_t) { /* NOT YET IMPLEMENTED */ };
static uint8_t get_exrom_game(void) {
return (C64_CLOCK_DETECT & 0x0C) >> 2;
}
Expand Down Expand Up @@ -377,7 +380,13 @@ class C64 : public GenericHost, ConfigurableObject
if (!cfg) return 0;
return cfg->get_value(id);
}


const char *get_cfg_string(uint8_t id)
{
if (!cfg) return "";
return cfg->get_string(id);
}

/* C64 specifics */
void resetConfigInFlash(int page);
void unfreeze(void);
Expand All @@ -388,6 +397,9 @@ class C64 : public GenericHost, ConfigurableObject
void reset(void);
void start(void);
bool is_in_reset(void);
uint8_t monitor_read_memory(uint16_t address);
void monitor_write_memory(uint16_t address, uint8_t value);
void monitor_read_memory_block(uint16_t address, uint8_t *dst, uint16_t len);

static void clear_cart_definition(cart_def *def) {
def->custom_addr = 0;
Expand Down
30 changes: 29 additions & 1 deletion software/io/c64/c64_subsys.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
#include "u64.h"
#include "c1541.h"
#include "endianness.h"
#if !U64 && !defined(RECOVERYAPP)
#include "monitor_init.h"
#include "u2_memory_backend.h"
#include "userinterface.h"
#endif
#if U64 == 2
#include "wifi.h"
#endif
Expand Down Expand Up @@ -88,6 +93,21 @@ C64_Subsys::~C64_Subsys() {

}

SubsysResultCode_e C64_Subsys :: S_run_monitor(SubsysCommand *cmd)
{
#if U64 || defined(RECOVERYAPP)
return SSRET_NOT_IMPLEMENTED;
#else
if (!cmd->user_interface) {
return SSRET_NO_USER_INTERFACE;
}

U2MemoryBackend monitor_backend;
cmd->user_interface->run_machine_monitor(&monitor_backend);
return SSRET_OK;
#endif
}

void C64_Subsys :: create_task_items(void)
{
myActions.reset = new Action("Reset C64", SUBSYSID_C64, MENU_C64_RESET);
Expand All @@ -105,6 +125,9 @@ void C64_Subsys :: create_task_items(void)
myActions.savemp3c = new Action("Save MP3 Drv C", SUBSYSID_C64, MENU_C64_SAVE_MP3_DRV_C);
myActions.savemp3d = new Action("Save MP3 Drv D", SUBSYSID_C64, MENU_C64_SAVE_MP3_DRV_D);
myActions.measure = new Action("Measure Cart Bus", SUBSYSID_C64, MENU_MEASURE_TIMING);
#if !U64 && !defined(RECOVERYAPP)
myActions.monitor = register_machine_monitor_task(C64_Subsys::S_run_monitor, MENU_C64_MONITOR);
#endif

taskCategory->append(myActions.reset);
taskCategory->append(myActions.reboot);
Expand Down Expand Up @@ -636,7 +659,9 @@ int C64_Subsys :: dma_load(File *f, const uint8_t *buffer, const int bufferSize,
if (run_code & RUNCODE_JUMP_BIT) {
C64_POKE(C64_BOOTCRT_JUMPADDR, buffer[0]);
C64_POKE(C64_BOOTCRT_JUMPADDR+1, buffer[1]);
load_buffer_dma(buffer+2, bufferSize-2, 0);
if (bufferSize > 2) {
load_buffer_dma(buffer+2, bufferSize-2, 0);
}
} else {
load_buffer_dma(buffer, bufferSize, 0);
}
Expand Down Expand Up @@ -724,6 +749,9 @@ int C64_Subsys :: load_file_dma(File *f, uint16_t reloc)

int C64_Subsys :: load_buffer_dma(const uint8_t *buffer, const int bufferSize, uint16_t reloc)
{
if (!buffer || bufferSize < 2) {
return 0;
}
uint16_t load_address = 0;

load_address = (uint16_t)buffer[0] | ((uint16_t)buffer[1]) << 8;
Expand Down
2 changes: 2 additions & 0 deletions software/io/c64/c64_subsys.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ class C64_Subsys : public SubSystem, ObjectWithMenu
Action *savemp3c;
Action *savemp3d;
Action *measure;
Action *monitor;
} myActions;

static void poll(void *a);
static SubsysResultCode_e S_run_monitor(SubsysCommand *cmd);

/* Subsystem */
const char *identify(void) { return "C64 Machine"; }
Expand Down
35 changes: 33 additions & 2 deletions software/io/c64/keyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,27 @@ class Keyboard
#define KEY_CTRL_HOME 0x14

#define KEY_CTRL_A 0x01
#define KEY_CTRL_B 0x02
#define KEY_CTRL_C 0x03
#define KEY_CTRL_N 0x0E
#define KEY_CTRL_V 0x16
#define KEY_CTRL_D 0x04
#define KEY_CTRL_E 0x05
#define KEY_CTRL_I 0x09
#define KEY_CTRL_J 0x0A
#define KEY_CTRL_L 0x0C
#define KEY_CTRL_N 0x0E
#define KEY_CTRL_O 0x0F
#define KEY_CTRL_V 0x16

#define KEY_CTRL_0 0xB0
#define KEY_CTRL_1 0xB1
#define KEY_CTRL_2 0xB2
#define KEY_CTRL_3 0xB3
#define KEY_CTRL_4 0xB4
#define KEY_CTRL_5 0xB5
#define KEY_CTRL_6 0xB6
#define KEY_CTRL_7 0xB7
#define KEY_CTRL_8 0xB8
#define KEY_CTRL_9 0xB9

#define KEY_A 0x61
#define KEY_S 0x73
Expand Down Expand Up @@ -68,6 +84,21 @@ class Keyboard
#define KEY_SCRLOCK 0xA3
#define KEY_NUMLOCK 0xA4

static inline bool key_is_ctrl_digit(int key)
{
return key >= KEY_CTRL_0 && key <= KEY_CTRL_9;
}

static inline int key_ctrl_digit_value(int key)
{
return key_is_ctrl_digit(key) ? (key - KEY_CTRL_0) : -1;
}

static inline int key_ctrl_digit(int digit)
{
return (digit >= 0 && digit <= 9) ? (KEY_CTRL_0 + digit) : KEY_ERR;
}

// Specials
#define KEY_MENU 0x1FE
#define KEY_SEARCH 0x1FD
Expand Down
10 changes: 5 additions & 5 deletions software/io/c64/keyboard_c64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ const uint8_t keymap_shifted[] = {

const uint8_t keymap_control[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x17, 0x01, 0x00, 0x1a, 0x13, 0x05, 0x00, // 3, w, a, 4, z, s, e, empty
0x00, 0x12, 0x04, 0x00, 0x03, 0x06, 0x14, 0x18, // 5, r, d, 6, c, f, t, x
0x00, 0x19, 0x07, 0x00, 0x02, 0x08, 0x15, 0x16, // 7, y, g, 8, b, h, u, v
0x00, 0x09, 0x0A, 0x00, 0x0D, 0x0B, 0x0F, 0x0E, // 9, i, j, 0, m, k, o, n
KEY_CTRL_3, 0x17, 0x01, KEY_CTRL_4, 0x1a, 0x13, 0x05, 0x00, // 3, w, a, 4, z, s, e, empty
KEY_CTRL_5, 0x12, 0x04, KEY_CTRL_6, 0x03, 0x06, 0x14, 0x18, // 5, r, d, 6, c, f, t, x
KEY_CTRL_7, 0x19, 0x07, KEY_CTRL_8, KEY_CTRL_B, 0x08, 0x15, 0x16, // 7, y, g, 8, b, h, u, v
KEY_CTRL_9, 0x09, 0x0A, KEY_CTRL_0, 0x0D, 0x0B, 0x0F, 0x0E, // 9, i, j, 0, m, k, o, n
0x00, 0x10, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, // +, p, l, -, ., :, @, ,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, // \, *, ;, Home , (empty), =, |, /
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, // 1, `, (empty), 2, SP, (empty), q, RunStop
KEY_CTRL_1, 0x00, 0x00, KEY_CTRL_2, 0x00, 0x00, 0x11, 0x00, // 1, `, (empty), 2, SP, (empty), q, RunStop
0x00 };

const uint8_t *keymaps[8] = {
Expand Down
1 change: 1 addition & 0 deletions software/io/c64/screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class Screen

// for character mapped screens. Does not work for VT100.
virtual void backup(void) { }
virtual bool prefers_full_refresh(void) { return false; }
virtual void restore(void) { }

// Static
Expand Down
6 changes: 6 additions & 0 deletions software/io/stream/keyboard_vt100.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ int Keyboard_VT100 :: getch()
} else if (charin == '[') {
escape_state = e_esc_bracket;
escape_value = 0;
} else if (charin >= '0' && charin <= '9') {
escape_state = e_esc_idle;
ret = key_ctrl_digit(charin - '0');
} else if (charin == 'b' || charin == 'B') {
escape_state = e_esc_idle;
ret = KEY_CTRL_B;
} else {
if (charin != '\e')
escape_state = e_esc_idle;
Expand Down
1 change: 1 addition & 0 deletions software/io/stream/screen_vt100.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class Screen_VT100: public Screen {

// VT100 specific
void restore_terminal(void);
bool prefers_full_refresh(void) { return true; }
};

#endif /* IO_STREAM_SCREEN_VT100_H_ */
10 changes: 5 additions & 5 deletions software/io/usb/keyboard_usb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,19 @@ const uint8_t keymap_shifted[] = {
KEY_UP, KEY_PAGEUP, KEY_INSERT, KEY_DELETE, 0x00 };

const uint8_t keymap_control[] = {
0x00, KEY_ERR, KEY_ERR, KEY_ERR, 0x01, 0x02, 0x03, 0x04,
0x00, KEY_ERR, KEY_ERR, KEY_ERR, 0x01, KEY_CTRL_B, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, '1', '2',
'3', '4', '5', '6', '7', '8', '9', '0',
0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, KEY_CTRL_1, KEY_CTRL_2,
KEY_CTRL_3, KEY_CTRL_4, KEY_CTRL_5, KEY_CTRL_6, KEY_CTRL_7, KEY_CTRL_8, KEY_CTRL_9, KEY_CTRL_0,
KEY_RETURN, KEY_ESCAPE, KEY_BACK, KEY_TAB, ' ', '-', '=', '[',
']', '\\', 0x00, ';', '\'', '`', ',', '.',
'/', KEY_CAPS, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6,
KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_PRSCR, KEY_SCRLOCK,
KEY_BREAK, KEY_INSERT, KEY_CTRL_HOME, KEY_PAGEUP, KEY_DELETE, KEY_END, KEY_PAGEDOWN, KEY_RIGHT,
KEY_LEFT, KEY_DOWN, KEY_UP, KEY_NUMLOCK, '/', '*', '-', '+',
KEY_RETURN, '1', '2', '3', '4', '5', '6', '7',
'8', '9', '0', '.', 0x00 };
KEY_RETURN, KEY_CTRL_1, KEY_CTRL_2, KEY_CTRL_3, KEY_CTRL_4, KEY_CTRL_5, KEY_CTRL_6, KEY_CTRL_7,
KEY_CTRL_8, KEY_CTRL_9, KEY_CTRL_0, '.', 0x00 };

const uint8_t keymap_usb2matrix[] = {
0x0F, 0xFF, 0xFF, 0xFF, 0x0A, 0x1C, 0x14, 0x12,
Expand Down
39 changes: 38 additions & 1 deletion software/io/usb/tests/usb_keyboard_queue_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,43 @@ TEST(KeyboardUsbQueueTest, PushHeadPrependsInjectedKey)
EXPECT_EQ(-1, keyboard.getch());
}

TEST(KeyboardUsbQueueTest, ControlBookmarkDigitsStayDistinctFromRecall)
{
Keyboard_USB keyboard;
uint8_t recall_report[USB_DATA_SIZE] = { 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t set_slot_report[USB_DATA_SIZE] = { 0x01, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t release[USB_DATA_SIZE] = { 0x00 };
uint8_t list_report[USB_DATA_SIZE] = { 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t edit_report[USB_DATA_SIZE] = { 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 };

keyboard.process_data(recall_report);
EXPECT_EQ('1', keyboard.getch());
keyboard.process_data(release);

keyboard.process_data(set_slot_report);
EXPECT_EQ(KEY_CTRL_1, keyboard.getch());
keyboard.process_data(release);

keyboard.process_data(list_report);
EXPECT_EQ(KEY_CTRL_B, keyboard.getch());
keyboard.process_data(release);

keyboard.process_data(edit_report);
EXPECT_EQ(KEY_CTRL_E, keyboard.getch());
}

TEST(KeyboardUsbQueueTest, CbmDigitDecodeRejectsInvalidKeys)
{
EXPECT_TRUE(key_is_ctrl_digit(KEY_CTRL_0));
EXPECT_TRUE(key_is_ctrl_digit(KEY_CTRL_9));
EXPECT_FALSE(key_is_ctrl_digit('0'));
EXPECT_FALSE(key_is_ctrl_digit(KEY_CTRL_B));
EXPECT_EQ(0, key_ctrl_digit_value(KEY_CTRL_0));
EXPECT_EQ(9, key_ctrl_digit_value(KEY_CTRL_9));
EXPECT_EQ(-1, key_ctrl_digit_value('0'));
EXPECT_EQ(-1, key_ctrl_digit_value(KEY_CTRL_B));
}

TEST(KeyboardUsbQueueTest, PushHeadRepeatIsBounded)
{
Keyboard_USB keyboard;
Expand Down Expand Up @@ -66,4 +103,4 @@ TEST(KeyboardUsbQueueTest, RemoveInjectedKeyDropsPendingDirection)
EXPECT_EQ(0, keyboard.count_injected_key(KEY_DOWN));
EXPECT_EQ(KEY_UP, keyboard.getch());
EXPECT_EQ(-1, keyboard.getch());
}
}
Loading
Loading