~thestr4ng3r/rz-commodore

8abfcf9e370d950677ec94e0a088b63cb3f625c9 — Florian Märkl a month ago f2e3fc3
Prepare Get Regs Available
7 files changed, 162 insertions(+), 20 deletions(-)

M CMakeLists.txt
M include/vic_ii.h
M include/vice.h
A src/debug_vice.c
M src/io_vice.c
A src/io_vice.h
M src/vice.c
M CMakeLists.txt => CMakeLists.txt +17 -2
@@ 36,11 36,26 @@ target_link_libraries(vice PUBLIC Rizin::librz)
find_package(LibUV REQUIRED)
target_link_libraries(vice PUBLIC LibUV::LibUV)

if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
	string (REPLACE ";" " " LD_RPATH_STR "@loader_path")
else()
	string (REPLACE ";" " " LD_RPATH_STR "$ORIGIN")
endif()

add_library(io_vice SHARED
	src/io_vice.c)
	src/io_vice.c
	src/io_vice.h)
set_target_properties(io_vice PROPERTIES PREFIX "")
target_link_libraries(io_vice PUBLIC vice)

add_library(debug_vice SHARED
	src/debug_vice.c)
set_target_properties(debug_vice PROPERTIES
	PREFIX ""
	BUILD_RPATH "${LD_RPATH_STR}"
	INSTALL_RPATH "${LD_RPATH_STR}")
target_link_libraries(debug_vice PUBLIC io_vice)

if(ENABLE_VICE_MONITOR_DEMO)
	target_compile_definitions(vice PUBLIC -DVICE_MONITOR_DEMO)
	file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/vicemon.c"


@@ 50,5 65,5 @@ if(ENABLE_VICE_MONITOR_DEMO)
	target_link_libraries(vicemon vice)
endif()

install(TARGETS asm_cbm_basic core_commodore io_vice
install(TARGETS asm_cbm_basic core_commodore io_vice debug_vice
	DESTINATION "${RIZIN_INSTALL_PLUGDIR}")

M include/vic_ii.h => include/vic_ii.h +1 -0
@@ 3,6 3,7 @@
#define RZ_VICII_H

#include <rz_util.h>
#include <rz_cons.h>

#define RZ_VIC_II_COLORS_COUNT 0x10


M include/vice.h => include/vice.h +2 -0
@@ 28,6 28,8 @@ typedef enum {
	RZ_VICE_MON_MEM_SPACE_DRIVE_11 = 0x4
} RzVICEMonMemSpace;

#define RZ_VICE_MON_MEM_SPACE_COUNT (RZ_VICE_MON_MEM_SPACE_DRIVE_11 + 1)

typedef enum {
	RZ_VICE_MON_BANK_DEFAULT,
	RZ_VICE_MON_BANK_CPU,

A src/debug_vice.c => src/debug_vice.c +51 -0
@@ 0,0 1,51 @@

#include "io_vice.h"

#include <rz_debug.h>
#include <rz_lib.h>

typedef struct {
	RzVICEMon *mon;
} DebugVICECtx;

static bool debug_vice_init(RzDebug *dbg, void **user) {
	DebugVICECtx *ctx = RZ_NEW0(DebugVICECtx);
	if (!ctx) {
		return false;
	}
	*user = ctx;
	return true;
}

static void debug_vice_fini(RzDebug *dbg, void *user) {
	free(user);
}

static int debug_vice_attach(RzDebug *dbg, int pid) {
	RzIODesc *d = dbg->iob.io->desc;
	if (!d || !d->plugin || !d->plugin->name || !d->data) {
		eprintf("Failed to attach VICE Debug Plugin to IO\n");
		return false;
	}
	RzVICEDesc *vd = d->data;
	DebugVICECtx *ctx = dbg->plugin_data;
	ctx->mon = vd->mon;
	return !!ctx->mon;
}

RzDebugPlugin rz_debug_plugin_vice = {
	.name = "vice",
	.license = "LGPL3",
	.arch = "6502",
	.bits = RZ_SYS_BITS_16,
	.init = debug_vice_init,
	.fini = debug_vice_fini
};

#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
	.type = RZ_LIB_TYPE_DBG,
	.data = &rz_debug_plugin_vice,
	.version = RZ_VERSION
};
#endif

M src/io_vice.c => src/io_vice.c +2 -7
@@ 1,16 1,11 @@

#include <vice.h>
#include "io_vice.h"

#include <rz_io.h>
#include <rz_lib.h>

#define URI_SCHEME "vice://"

typedef struct rz_vice_desc_t {
	RzVICEMon *mon;
	ut64 off;
} RzVICEDesc;

static int __close(RzIODesc *fd);
extern RzIOPlugin rz_io_plugin_vice;



@@ 153,7 148,7 @@ RzIOPlugin rz_io_plugin_vice = {
	.check = __check,
	.lseek = __lseek,
	.write = __write,
	// .isdbg = true
	.isdbg = true
};

#ifndef RZ_PLUGIN_INCORE

A src/io_vice.h => src/io_vice.h +11 -0
@@ 0,0 1,11 @@
#ifndef RZ_COMMODORE_IO_VICE_H
#define RZ_COMMODORE_IO_VICE_H

#include <vice.h>

typedef struct rz_vice_desc_t {
	RzVICEMon *mon;
	ut64 off;
} RzVICEDesc;

#endif

M src/vice.c => src/vice.c +78 -11
@@ 5,7 5,7 @@

#include <uv.h>

#define DEBUG_RAW 0
#define DEBUG_RAW 1

#define RZ_VICE_MON_STX               '\x02'
#define RZ_VICE_MON_API_VERSION_ID    0x01


@@ 23,6 23,7 @@ typedef enum {
	RZ_VICE_MON_COMMAND_MEM_SET = 0x02,
	RZ_VICE_MON_COMMAND_CHECKPOINT_SET = 0x12,
	RZ_VICE_MON_COMMAND_BANKS_AVAILABLE = 0x82,
	RZ_VICE_MON_COMMAND_REGS_AVAILABLE = 0x83
} RzVICEMonCommandType;

typedef struct {


@@ 48,11 49,16 @@ typedef struct rz_vice_mon_command_mem_set_args_t {
	const ut8 *buf;
} RzVICEMonCommandMemSetArgs;

typedef struct rz_vice_mon_command_regs_available_args_t {
	RzVICEMonMemSpace space;
} RzVICEMonCommandRegsAvailableArgs;

typedef struct rz_vice_mon_command_t {
	RzVICEMonCommandType type;
	union {
		RzVICEMonCommandMemGetArgs mem_get;
		RzVICEMonCommandMemSetArgs mem_set;
		RzVICEMonCommandRegsAvailableArgs regs_available;
	};
} RzVICEMonCommand;



@@ 64,7 70,8 @@ typedef enum {
	RZ_VICE_MON_RESPONSE_JAM = 0x61,
	RZ_VICE_MON_RESPONSE_STOPPED = 0x62,
	RZ_VICE_MON_RESPONSE_RESUMED = 0x63,
	RZ_VICE_MON_RESPONSE_BANKS_AVAILABLE = 0x82
	RZ_VICE_MON_RESPONSE_BANKS_AVAILABLE = 0x82,
	RZ_VICE_MON_RESPONSE_REGS_AVAILABLE = 0x83
} RzVICEMonResponseType;

typedef struct rz_vice_mon_response_raw_t {


@@ 132,6 139,15 @@ typedef struct rz_vice_mon_response {
				char *name;
			} banks[RZ_VICE_MON_BANKS_COUNT_MAX];
		} banks_available;
		struct {
			RzVICEMonMemSpace space;
			size_t count;
			struct {
				ut8 id;
				ut8 bits;
				char *name;
			} regs[RZ_VICE_MON_REGS_COUNT_MAX];
		} regs_available;
	};
} RzVICEMonResponse;



@@ 141,7 157,7 @@ typedef struct rz_vice_mon_pending_req_t {
	ut32 req_id;
	MonResponseCb cb;
	void *cb_user;
	uv_timer_t timeout;
	uv_timer_t *timeout;
} RzVICEMonPendingReq;

struct rz_vice_mon_t {


@@ 230,7 246,7 @@ static void rz_vice_mon_command_raw_fini(RzVICEMonCommandRaw *cmd) {
}

static void rz_vice_mon_pending_req_fini(RzVICEMonPendingReq *req) {
	uv_close((uv_handle_t *)&req->timeout, NULL);
	uv_close((uv_handle_t *)req->timeout, (uv_close_cb)free);
}

static void rz_vice_mon_pending_req_fini2(RzVICEMonPendingReq *req, void *user) {


@@ 350,11 366,15 @@ typedef struct {
	uv_connect_t *conn;
	struct addrinfo *addr_root;
	struct addrinfo *addr_next;
	RzVICEMonMemSpace get_regs_available_cur;
} OpenCtx;

static void open_getaddrinfo_cb(uv_getaddrinfo_t *req, int status, struct addrinfo *res);
static void handle_next_addrinfo(RzVICEMon *mon, OpenCtx *ctx);
static void open_connect_cb(uv_connect_t *req, int status);
static void open_get_regs_available(RzVICEMon *mon, OpenCtx *ctx);
static void open_regs_available_resp_cb(RzVICEMon *mon, RzVICEMonErr r, RzVICEMonResponse *resp, void *user);
static void open_get_banks(RzVICEMon *mon, OpenCtx *ctx);
static void open_banks_resp_cb(RzVICEMon *mon, RzVICEMonErr r, RzVICEMonResponse *resp, void *user);

static RzVICEMonErr mon_send(RzVICEMon *mon, RzVICEMonCommand *cmd, MonResponseCb cb, void *user);


@@ 480,8 500,29 @@ static void open_connect_cb(uv_connect_t *req, int status) {
	}

	uv_read_start((uv_stream_t *)mon->tcp, read_alloc_cb, read_cb);
	open_get_regs_available(mon, ctx);
}

static void open_get_regs_available(RzVICEMon *mon, OpenCtx *ctx) {
	if (ctx->get_regs_available_cur >= RZ_VICE_MON_MEM_SPACE_COUNT) {
		// all done! proceed to banks.
		open_get_banks(mon, ctx);
		return;
	}
	RzVICEMonCommand cmd = {
		.type = RZ_VICE_MON_COMMAND_REGS_AVAILABLE,
		.regs_available = { .space = ctx->get_regs_available_cur++ }
	};
	mon_send(mon, &cmd, open_regs_available_resp_cb, ctx);
}

static void open_regs_available_resp_cb(RzVICEMon *mon, RzVICEMonErr r, RzVICEMonResponse *resp, void *user) {
	eprintf("TODO: got resp\n");
	OpenCtx *ctx = user;
	open_get_regs_available(mon, ctx);
}

	// Fetch banks before doing anything else
static void open_get_banks(RzVICEMon *mon, OpenCtx *ctx) {
	RzVICEMonCommand cmd = {
		.type = RZ_VICE_MON_COMMAND_BANKS_AVAILABLE
	};


@@ 637,7 678,7 @@ static RzVICEMonErr mon_send_raw(RzVICEMon *mon, RzVICEMonCommandRaw *cmd,
	write->data = ctx;
	uv_buf_t ubuf = { .base = (char *)buf, .len = buf_sz };
#if DEBUG_RAW
	eprintf("--\nsend command type %u with req_id %#x\n",
	eprintf("--\nsend command type %#x with req_id %#x\n",
		(unsigned int)cmd->type, (unsigned int)req_id);
	if (cmd->body) {
		char *hex = rz_hex_bin2strdup(buf, RZ_VICE_MON_REQ_HEADER_SZ);


@@ 649,6 690,7 @@ static RzVICEMonErr mon_send_raw(RzVICEMon *mon, RzVICEMonCommandRaw *cmd,
	}
	eprintf("--\n");
#endif
	eprintf("uv_write %p\n", write);
	uv_write(write, (uv_stream_t *)mon->tcp, &ubuf, 1, send_raw_write_cb);
	*req_id_out = req_id;
	return RZ_VICE_MON_ERR_SUCCESS;


@@ 707,6 749,14 @@ static RzVICEMonErr format_command(RZ_OUT RzVICEMonCommandRaw *cmd_raw, RZ_IN Rz
		memcpy(cmd_raw->body + 8, cmd->mem_set.buf, buf_sz);
		break;
	}
	case RZ_VICE_MON_COMMAND_REGS_AVAILABLE:
		cmd_raw->body_sz = 1;
		cmd_raw->body = malloc(cmd_raw->body_sz);
		if (!cmd_raw->body) {
			return RZ_VICE_MON_ERR_MEMORY;
		}
		cmd_raw->body[0] = (ut8)cmd->regs_available.space;
		break;
	default:
		// TODO: insert all formats here
		break;


@@ 730,9 780,10 @@ static RzVICEMonErr mon_send(RzVICEMon *mon, RzVICEMonCommand *cmd, MonResponseC
	req->req_id = req_id;
	req->cb = cb;
	req->cb_user = user;
	uv_timer_init(&mon->loop, &req->timeout);
	req->timeout.data = (void *)(size_t)req_id;
	uv_timer_start(&req->timeout, send_timeout_resp_cb, REQUEST_TIMEOUT_MS, 0);
	req->timeout = RZ_NEW(uv_timer_t);
	uv_timer_init(&mon->loop, req->timeout);
	req->timeout->data = (void *)(size_t)req_id;
	uv_timer_start(req->timeout, send_timeout_resp_cb, REQUEST_TIMEOUT_MS, 0);
	return err;
}



@@ 756,7 807,7 @@ static void finalize_req_resp(RzVICEMon *mon, ut32 req_id, RzVICEMonErr err, RzV
			if (preq->cb) {
				preq->cb(mon, err, resp, preq->cb_user);
			}
			uv_close((uv_handle_t *)&preq->timeout, NULL);
			uv_close((uv_handle_t *)preq->timeout, NULL);
			rz_vector_remove_at(&mon->pending_reqs, i, NULL);
			return;
		}


@@ 879,7 930,7 @@ static RzVICEMonErr parse_response(RzVICEMonResponse *resp, RzVICEMonResponseRaw

static void read_handle_resp_raw(RzVICEMon *mon, RzVICEMonResponseRaw *resp_raw) {
#if DEBUG_RAW
	eprintf("--\nreceived response type %u with req_id %#x, error_code %#x\n",
	eprintf("--\nreceived response type %#x with req_id %#x, error_code %#x\n",
		(unsigned int)resp_raw->type, (unsigned int)resp_raw->req_id, (unsigned int)resp_raw->error_code);
	if (resp_raw->body) {
		char *hex = rz_hex_bin2strdup(resp_raw->body, resp_raw->body_sz);


@@ 978,6 1029,8 @@ static RzVICEMonErr parse_response(RzVICEMonResponse *resp, RzVICEMonResponseRaw
		}
		return err;
	}
	case RZ_VICE_MON_RESPONSE_REGS_AVAILABLE:
		// TODO:
	default:
		return RZ_VICE_MON_ERR_INVALID_RESPONSE;
	}


@@ 988,6 1041,8 @@ static RzVICEMonErr parse_response(RzVICEMonResponse *resp, RzVICEMonResponseRaw
// -----------------------
// API

// -- mem read

typedef struct {
	RzVICEMonCommandMemGetArgs args;
	ut8 *buf;


@@ 1037,6 1092,8 @@ RZ_API RzVICEMonErr rz_vice_mon_mem_read(RzVICEMon *mon, RzVICEMonMemSpace space
	return (RzVICEMonErr)(size_t)async_call_run(mon, async_mem_read, &args);
}

// -- mem write

typedef struct {
	RzVICEMonCommandMemSetArgs args;
} MemWriteAsyncArgs;


@@ 1075,6 1132,16 @@ RZ_API RzVICEMonErr rz_vice_mon_mem_write(RzVICEMon *mon, RzVICEMonMemSpace spac
	return (RzVICEMonErr)(size_t)async_call_run(mon, async_mem_write, &args);
}

// -- registers get

typedef void RzVICERegisters;

RZ_API RzVICEMonErr rz_vice_mon_regs_get(RzVICEMon *mon, RzVICEMonMemSpace space, RzVICERegisters *regs_out) {
	return RZ_VICE_MON_ERR_UNKNOWN;
}

// -- misc

RZ_API ut16 rz_vice_mon_get_bank_id(RzVICEMon *mon, RzVICEMonBankType bank) {
	ut16 fallback = 1;
	for (size_t i = 0; i < mon->banks_count; i++) {