From 74e13c89f3d9406cb857c56e0b41941ec54b7a0f Mon Sep 17 00:00:00 2001 From: "LGB (Gabor Lenart)" Date: Thu, 20 Jun 2024 20:10:19 +0200 Subject: [PATCH] MEGA65: cleanup and reorg uartmon stuff #11 Moving everything out of mega65.c which is uartmon into uart_monitor.c, well, at least allmost everything ... Still, no new feature is used from CPU65 emulation, just mainly reorganization of the source to look nicer for further hacking/developing. --- targets/mega65/mega65.c | 124 +++------------------------ targets/mega65/mega65.h | 20 ++--- targets/mega65/uart_monitor.c | 156 ++++++++++++++++++++++++++++------ targets/mega65/uart_monitor.h | 22 ++--- 4 files changed, 153 insertions(+), 169 deletions(-) diff --git a/targets/mega65/mega65.c b/targets/mega65/mega65.c index 681b399f..5385e948 100644 --- a/targets/mega65/mega65.c +++ b/targets/mega65/mega65.c @@ -56,16 +56,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ static int nmi_level; // please read the comment at nmi_set() below static int emulation_is_running = 0; static int speed_current = -1; -static int paused = 0, paused_old = 0; -static int breakpoint_pc = -1; +int paused = 0; +static int paused_old = 0; #ifdef TRACE_NEXT_SUPPORT static int orig_sp = 0; static int trace_next_trigger = 0; #endif -static int trace_step_trigger = 0; -#ifdef HAS_UARTMON_SUPPORT -static void (*m65mon_callback)(void) = NULL; -#endif +int trace_step_trigger = 0; static char emulator_speed_title[64] = ""; static char fast_mhz_as_string[16] = ""; const char *cpu_clock_speed_string_p = ""; @@ -422,13 +419,13 @@ static void mega65_init ( void ) cia2.TLAH = 1; // *** Initialize DMA (we rely on memory and I/O decoder provided functions here for the purpose) dma_init(); -#ifdef HAS_UARTMON_SUPPORT - uartmon_init(configdb.uartmon); -#endif sprintf(fast_mhz_as_string, "%.2fMHz", configdb.fast_mhz); DEBUGPRINT("SPEED: fast clock is set to %.2fMHz." NL, configdb.fast_mhz); cpu65_init_mega_specific(); cpu65_reset(); // reset CPU (though it fetches its reset vector, we don't use that on M65, but the KS hypervisor trap) +#ifdef HAS_UARTMON_SUPPORT + uartmon_init(configdb.uartmon); +#endif memory_set_rom_protection(0); hypervisor_start_machine(); speed_current = 0; @@ -552,108 +549,7 @@ int reset_mega65_asked ( void ) #ifdef HAS_UARTMON_SUPPORT -void m65mon_show_regs ( void ) -{ - Uint8 pf = cpu65_get_pf(); - umon_printf( - "\r\n" - "PC A X Y Z B SP MAPL MAPH LAST-OP P P-FLAGS RGP uS IO\r\n" - "%04X %02X %02X %02X %02X %02X %04X " // register banned message and things from PC to SP - "%04X %04X %02X %02X %02X " // from MAPL to P - "%c%c%c%c%c%c%c%c ", // P-FLAGS - cpu65.pc, cpu65.a, cpu65.x, cpu65.y, cpu65.z, cpu65.bphi >> 8, cpu65.sphi | cpu65.s, - ((map_mask & 0x0F) << 12) | (map_offset_low >> 8), - ((map_mask & 0xF0) << 8) | (map_offset_high >> 8), - cpu65.op, - pf, 0, // flags - (pf & CPU65_PF_N) ? 'N' : '-', - (pf & CPU65_PF_V) ? 'V' : '-', - (pf & CPU65_PF_E) ? 'E' : '-', - '-', - (pf & CPU65_PF_D) ? 'D' : '-', - (pf & CPU65_PF_I) ? 'I' : '-', - (pf & CPU65_PF_Z) ? 'Z' : '-', - (pf & CPU65_PF_C) ? 'C' : '-' - ); -} - -void m65mon_set_pc ( const Uint16 addr ) -{ - cpu65_debug_set_pc(addr); -} - -void m65mon_dumpmem16 ( Uint16 addr ) -{ - int n = 16; - umon_printf(":000%04X:", addr); - while (n--) - umon_printf("%02X", debug_read_cpu_byte(addr++)); -} - -void m65mon_dumpmem28 ( int addr ) -{ - int n = 16; - addr &= 0xFFFFFFF; - umon_printf(":%07X:", addr); - while (n--) - umon_printf("%02X", debug_read_linear_byte(addr++)); -} - -void m65mon_setmem28 ( int addr, int cnt, Uint8* vals ) -{ - while (--cnt >= 0) - debug_write_linear_byte(addr++, *(vals++)); -} - -void m65mon_set_trace ( int m ) -{ - paused = m; -} - -#ifdef TRACE_NEXT_SUPPORT -void m65mon_do_next ( void ) -{ - if (paused) { - umon_send_ok = 0; // delay command execution! - m65mon_callback = m65mon_show_regs; // register callback - trace_next_trigger = 2; // if JSR, then trigger until RTS to next_addr - orig_sp = cpu65.sphi | cpu65.s; - paused = 0; - } else { - umon_printf(UMON_SYNTAX_ERROR "trace can be used only in trace mode"); - } -} -#endif - -void m65mon_do_trace ( void ) -{ - if (paused) { - umon_send_ok = 0; // delay command execution! - m65mon_callback = m65mon_show_regs; // register callback - trace_step_trigger = 1; // trigger one step - } else { - umon_printf(UMON_SYNTAX_ERROR "trace can be used only in trace mode"); - } -} - -void m65mon_do_trace_c ( void ) -{ - umon_printf(UMON_SYNTAX_ERROR "command 'tc' is not implemented yet"); -} -#ifdef TRACE_NEXT_SUPPORT -void m65mon_next_command ( void ) -{ - if (paused) - m65mon_do_next(); -} -#endif -void m65mon_empty_command ( void ) -{ - if (paused) - m65mon_do_trace(); -} - -void m65mon_breakpoint ( int brk ) +void set_breakpoint ( int brk ) { breakpoint_pc = brk; if (brk < 0) @@ -765,19 +661,25 @@ static void emulation_loop ( void ) cpu_cycles_per_step = 0; } else { DEBUGPRINT("TRACE: leaving trace mode @ $%04X" NL, cpu65.pc); +#ifdef HAS_UARTMON_SUPPORT if (breakpoint_pc < 0) cpu_cycles_per_step = cpu_cycles_per_scanline; else cpu_cycles_per_step = 0; +#else + cpu_cycles_per_step = cpu_cycles_per_scanline; +#endif } } } if (XEMU_UNLIKELY(hypervisor_is_debugged && in_hypervisor)) hypervisor_debug(); +#ifdef HAS_UARTMON_SUPPORT if (XEMU_UNLIKELY(breakpoint_pc == cpu65.pc)) { DEBUGPRINT("TRACE: Breakpoint @ $%04X hit, Xemu moves to trace mode after the execution of this opcode." NL, cpu65.pc); paused = 1; } +#endif cycles += XEMU_UNLIKELY(in_dma) ? dma_update_multi_steps(cpu_cycles_per_scanline) : cpu65_step( #ifdef CPU_STEP_MULTI_OPS cpu_cycles_per_step diff --git a/targets/mega65/mega65.h b/targets/mega65/mega65.h index 2f7f9948..1e98ac7c 100644 --- a/targets/mega65/mega65.h +++ b/targets/mega65/mega65.h @@ -1,6 +1,6 @@ /* A work-in-progess MEGA65 (Commodore-65 clone origins) emulator Part of the Xemu project, please visit: https://github.com/lgblgblgb/xemu - Copyright (C)2016-2023 LGB (Gábor Lénárt) + Copyright (C)2016-2024 LGB (Gábor Lénárt) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,20 +50,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define SID_CYCLES_PER_SEC 1000000 #define AUDIO_SAMPLE_FREQ 44100 -extern void m65mon_show_regs ( void ); -extern void m65mon_set_pc ( const Uint16 addr ); -extern void m65mon_dumpmem16 ( Uint16 addr ); -extern void m65mon_dumpmem28 ( int addr ); -extern void m65mon_setmem28 ( int addr, int cnt, Uint8* vals ); -extern void m65mon_set_trace ( int m ); -extern void m65mon_do_trace ( void ); -#ifdef TRACE_NEXT_SUPPORT -extern void m65mon_next_command ( void ); -#endif -extern void m65mon_empty_command ( void ); -extern void m65mon_do_trace_c ( void ); -extern void m65mon_breakpoint ( int brk ); - extern void machine_set_speed ( int verbose ); extern void reset_mega65 ( void ); @@ -75,9 +61,13 @@ extern int mega65_set_model ( const Uint8 id ); extern int dump_memory ( const char *fn ); extern int dump_screen ( const char *fn ); +extern void set_breakpoint ( int brk ); + extern Uint8 last_dd00_bits; extern const char *last_reset_type; extern int cpu_cycles_per_step; extern const char *cpu_clock_speed_string_p; +extern int paused; +extern int trace_step_trigger; #endif diff --git a/targets/mega65/uart_monitor.c b/targets/mega65/uart_monitor.c index 01ab8cb5..82c0d8ba 100644 --- a/targets/mega65/uart_monitor.c +++ b/targets/mega65/uart_monitor.c @@ -1,6 +1,6 @@ /* A work-in-progess MEGA65 (Commodore-65 clone origins) emulator Part of the Xemu project, please visit: https://github.com/lgblgblgb/xemu - Copyright (C)2016-2023 LGB (Gábor Lénárt) + Copyright (C)2016-2024 LGB (Gábor Lénárt) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,44 +16,34 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "xemu/emutools.h" -#include "mega65.h" -#include "uart_monitor.h" - - #if !defined(HAS_UARTMON_SUPPORT) -// Windows is not supported currently, as it does not have POSIX-standard socket interface (?). -// Also, it's pointless for emscripten, for sure. #warning "Platform does not support UMON" #else +#include "xemu/emutools.h" +#include "mega65.h" +#include "uart_monitor.h" +#include "xemu/cpu65.h" +#include "memory_mapper.h" #include "sdcard.h" - #include "xemu/emutools_socketapi.h" - -//#include -//#include -//#include -//#include #include -//#include #ifndef XEMU_ARCH_WIN #include #include -//#include -//#include -//#include #endif -int umon_write_size; -int umon_send_ok; -char umon_write_buffer[UMON_WRITE_BUFFER_SIZE]; - -#define UNCONNECTED XS_INVALID_SOCKET - -#define PRINTF_SOCK PRINTF_S64 - +#define UMON_WRITE_BUFFER_SIZE 0x4000 +#define umon_printf(...) do { \ + if (XEMU_LIKELY(umon_write_size < UMON_WRITE_BUFFER_SIZE - 1)) \ + umon_write_size += snprintf(umon_write_buffer + umon_write_size, UMON_WRITE_BUFFER_SIZE - umon_write_size, __VA_ARGS__); \ + else \ + _umon_write_size_panic(); \ + } while(0) +#define UMON_SYNTAX_ERROR "?SYNTAX ERROR " +#define UNCONNECTED XS_INVALID_SOCKET +#define PRINTF_SOCK PRINTF_S64 static xemusock_socket_t sock_server = UNCONNECTED; static xemusock_socklen_t sock_len; @@ -62,10 +52,120 @@ static xemusock_socket_t sock_client = UNCONNECTED; static int umon_write_pos, umon_read_pos; static int umon_echo; static char umon_read_buffer [0x1000]; +static int umon_write_size; +static int umon_send_ok; +static char umon_write_buffer[UMON_WRITE_BUFFER_SIZE]; + +void (*m65mon_callback)(void) = NULL; +int breakpoint_pc = -1; -// WARNING: This source is pretty ugly, ie not so much check of overflow of the output (write) buffer. +static void _umon_write_size_panic ( void ) +{ + DEBUGPRINT("UARTMON: warning: too long message (%d/%d), cannot fit into the output buffer!" NL, umon_write_pos, UMON_WRITE_BUFFER_SIZE); +} + +static void m65mon_show_regs ( void ) +{ + Uint8 pf = cpu65_get_pf(); + umon_printf( + "\r\n" + "PC A X Y Z B SP MAPL MAPH LAST-OP P P-FLAGS RGP uS IO\r\n" + "%04X %02X %02X %02X %02X %02X %04X " // register banned message and things from PC to SP + "%04X %04X %02X %02X %02X " // from MAPL to P + "%c%c%c%c%c%c%c%c ", // P-FLAGS + cpu65.pc, cpu65.a, cpu65.x, cpu65.y, cpu65.z, cpu65.bphi >> 8, cpu65.sphi | cpu65.s, + ((map_mask & 0x0F) << 12) | (map_offset_low >> 8), + ((map_mask & 0xF0) << 8) | (map_offset_high >> 8), + cpu65.op, + pf, 0, // flags + (pf & CPU65_PF_N) ? 'N' : '-', + (pf & CPU65_PF_V) ? 'V' : '-', + (pf & CPU65_PF_E) ? 'E' : '-', + '-', + (pf & CPU65_PF_D) ? 'D' : '-', + (pf & CPU65_PF_I) ? 'I' : '-', + (pf & CPU65_PF_Z) ? 'Z' : '-', + (pf & CPU65_PF_C) ? 'C' : '-' + ); +} + +static void m65mon_set_pc ( const Uint16 addr ) +{ + cpu65_debug_set_pc(addr); +} + +static void m65mon_dumpmem16 ( Uint16 addr ) +{ + int n = 16; + umon_printf(":000%04X:", addr); + while (n--) + umon_printf("%02X", debug_read_cpu_byte(addr++)); +} + +static void m65mon_dumpmem28 ( int addr ) +{ + int n = 16; + addr &= 0xFFFFFFF; + umon_printf(":%07X:", addr); + while (n--) + umon_printf("%02X", debug_read_linear_byte(addr++)); +} + +static void m65mon_setmem28 ( int addr, int cnt, Uint8* vals ) +{ + while (--cnt >= 0) + debug_write_linear_byte(addr++, *(vals++)); +} + +static void m65mon_set_trace ( int m ) +{ + paused = m; +} + +#ifdef TRACE_NEXT_SUPPORT +static void m65mon_do_next ( void ) +{ + if (paused) { + umon_send_ok = 0; // delay command execution! + m65mon_callback = m65mon_show_regs; // register callback + trace_next_trigger = 2; // if JSR, then trigger until RTS to next_addr + orig_sp = cpu65.sphi | cpu65.s; + paused = 0; + } else { + umon_printf(UMON_SYNTAX_ERROR "trace can be used only in trace mode"); + } +} +#endif + +static void m65mon_do_trace ( void ) +{ + if (paused) { + umon_send_ok = 0; // delay command execution! + m65mon_callback = m65mon_show_regs; // register callback + trace_step_trigger = 1; // trigger one step + } else { + umon_printf(UMON_SYNTAX_ERROR "trace can be used only in trace mode"); + } +} + +static void m65mon_do_trace_c ( void ) +{ + umon_printf(UMON_SYNTAX_ERROR "command 'tc' is not implemented yet"); +} +#ifdef TRACE_NEXT_SUPPORT +static void m65mon_next_command ( void ) +{ + if (paused) + m65mon_do_next(); +} +#endif +static void m65mon_empty_command ( void ) +{ + if (paused) + m65mon_do_trace(); +} static char *parse_hex_arg ( char *p, int *val, int min, int max ) { @@ -210,7 +310,7 @@ static void execute_command ( char *cmd ) case 'b': cmd = parse_hex_arg(cmd, &par1, 0, 0xFFFF); if (cmd && check_end_of_command(cmd, 1)) - m65mon_breakpoint(par1); + set_breakpoint(par1); break; case 'g': cmd = parse_hex_arg(cmd, &par1, 0, 0xFFFF); diff --git a/targets/mega65/uart_monitor.h b/targets/mega65/uart_monitor.h index 31691190..a02d5e80 100644 --- a/targets/mega65/uart_monitor.h +++ b/targets/mega65/uart_monitor.h @@ -1,6 +1,6 @@ /* A work-in-progess MEGA65 (Commodore-65 clone origins) emulator Part of the Xemu project, please visit: https://github.com/lgblgblgb/xemu - Copyright (C)2016-2023 LGB (Gábor Lénárt) + Copyright (C)2016-2024 LGB (Gábor Lénárt) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,26 +18,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef XEMU_MEGA65_UART_MONITOR_H_INCLUDED #define XEMU_MEGA65_UART_MONITOR_H_INCLUDED - #ifdef HAS_UARTMON_SUPPORT -#define UMON_SYNTAX_ERROR "?SYNTAX ERROR " - #define UMON_DEFAULT_PORT ":4510" -#define UMON_WRITE_BUFFER_SIZE 0x4000 -#define umon_printf(...) umon_write_size += sprintf(umon_write_buffer + umon_write_size, __VA_ARGS__) +extern void (*m65mon_callback)(void); +extern int breakpoint_pc; -extern int umon_write_size; -extern int umon_send_ok; -extern char umon_write_buffer[UMON_WRITE_BUFFER_SIZE]; - -extern int uartmon_init ( const char *fn ); -extern int uartmon_is_active ( void ); -extern void uartmon_update ( void ); -extern void uartmon_close ( void ); +extern int uartmon_init ( const char *fn ); +extern int uartmon_is_active ( void ); +extern void uartmon_update ( void ); +extern void uartmon_close ( void ); extern void uartmon_finish_command ( void ); #endif - #endif