~thestr4ng3r/rz-commodore

e067eaa7df33b887935c7a493d6613a306609c42 — Florian Märkl 4 months ago e2fbce7
Add VICE Mem Set
3 files changed, 90 insertions(+), 4 deletions(-)

M include/vice.h
M src/io_vice.c
M src/vice.c
M include/vice.h => include/vice.h +2 -0
@@ 45,6 45,8 @@ RZ_API RzVICEMonErr rz_vice_mon_open(RzVICEMon *mon, const char *host, ut16 port
RZ_API RzVICEMonErr rz_vice_mon_close(RzVICEMon *mon);
RZ_API RzVICEMonErr rz_vice_mon_mem_read(RzVICEMon *mon, RzVICEMonMemSpace space,
	ut16 start, ut16 end, ut16 bank_id, bool side_effects, RZ_OUT ut8 *buf);
RZ_API RzVICEMonErr rz_vice_mon_mem_write(RzVICEMon *mon, RzVICEMonMemSpace space,
	ut16 start, ut16 end, ut16 bank_id, bool side_effects, RZ_IN const ut8 *buf);
RZ_API ut16 rz_vice_mon_get_bank_id(RzVICEMon *mon, RzVICEMonBankType bank);

#endif

M src/io_vice.c => src/io_vice.c +21 -4
@@ 80,7 80,23 @@ err_v:
#define BANK  RZ_VICE_MON_BANK_CPU

static int __write(RzIO *io, RzIODesc *fd, const ut8 *buf, int count) {
	return -1;
	RzVICEDesc *desc = fd->data;

	RzVICEMonMemSpace space = SPACE;
	ut16 bank_id = rz_vice_mon_get_bank_id(desc->mon, BANK);

	RzVICEMonErr err = RZ_VICE_MON_ERR_SUCCESS;
	ut64 end64 = desc->off + count - 1;
	if (desc->off < UT16_MAX) {
		err = rz_vice_mon_mem_write(desc->mon, space,
			(ut16)desc->off, (ut16)RZ_MIN(end64, UT16_MAX),
			bank_id, false, buf);
	} else if (end64 < UT16_MAX) {
		err = rz_vice_mon_mem_write(desc->mon, space,
			0, (ut16)end64,
			bank_id, false, buf + (0 - desc->off));
	}
	return err == RZ_VICE_MON_ERR_SUCCESS ? count : -1;
}

static ut64 __lseek(RzIO *io, RzIODesc *fd, ut64 offset, int whence) {


@@ 105,17 121,18 @@ static int __read(RzIO *io, RzIODesc *fd, ut8 *buf, int count) {
	RzVICEMonMemSpace space = SPACE;
	ut16 bank_id = rz_vice_mon_get_bank_id(desc->mon, BANK);

	RzVICEMonErr err = RZ_VICE_MON_ERR_SUCCESS;
	ut64 end64 = desc->off + count - 1;
	if (desc->off < UT16_MAX) {
		rz_vice_mon_mem_read(desc->mon, space,
		err = rz_vice_mon_mem_read(desc->mon, space,
			(ut16)desc->off, (ut16)RZ_MIN(end64, UT16_MAX),
			bank_id, false, buf);
	} else if (end64 < UT16_MAX) {
		rz_vice_mon_mem_read(desc->mon, space,
		err = rz_vice_mon_mem_read(desc->mon, space,
			0, (ut16)end64,
			bank_id, false, buf + (0 - desc->off));
	}
	return count;
	return err == RZ_VICE_MON_ERR_SUCCESS ? count : -1;
}

static int __close(RzIODesc *fd) {

M src/vice.c => src/vice.c +67 -0
@@ 20,6 20,7 @@

typedef enum {
	RZ_VICE_MON_COMMAND_MEM_GET = 0x01,
	RZ_VICE_MON_COMMAND_MEM_SET = 0x02,
	RZ_VICE_MON_COMMAND_CHECKPOINT_SET = 0x12,
	RZ_VICE_MON_COMMAND_BANKS_AVAILABLE = 0x82,
} RzVICEMonCommandType;


@@ 38,15 39,26 @@ typedef struct rz_vice_mon_command_mem_get_args_t {
	bool side_effects;
} RzVICEMonCommandMemGetArgs;

typedef struct rz_vice_mon_command_mem_set_args_t {
	RzVICEMonMemSpace space;
	ut16 start;
	ut16 end;
	ut16 bank_id;
	bool side_effects;
	const ut8 *buf;
} RzVICEMonCommandMemSetArgs;

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

typedef enum {
	RZ_VICE_MON_RESPONSE_MEM_GET = 0x01,
	RZ_VICE_MON_RESPONSE_MEM_SET = 0x02,
	RZ_VICE_MON_RESPONSE_CHECKPOINT_INFO = 0x11,
	RZ_VICE_MON_RESPONSE_REGISTER_INFO = 0x31,
	RZ_VICE_MON_RESPONSE_JAM = 0x61,


@@ 680,6 692,21 @@ static RzVICEMonErr format_command(RZ_OUT RzVICEMonCommandRaw *cmd_raw, RZ_IN Rz
		cmd_raw->body[5] = (ut8)cmd->mem_get.space;
		rz_write_at_le16(cmd_raw->body, cmd->mem_get.bank_id, 6);
		break;
	case RZ_VICE_MON_COMMAND_MEM_SET: {
		size_t buf_sz = (size_t)(cmd->mem_set.end - cmd->mem_set.start) + 1;
		cmd_raw->body_sz = 8 + buf_sz;
		cmd_raw->body = malloc(cmd_raw->body_sz);
		if (!cmd_raw->body) {
			return RZ_VICE_MON_ERR_MEMORY;
		}
		cmd_raw->body[0] = cmd->mem_set.side_effects ? 1 : 0;
		rz_write_at_le16(cmd_raw->body, cmd->mem_set.start, 1);
		rz_write_at_le16(cmd_raw->body, cmd->mem_set.end, 3);
		cmd_raw->body[5] = (ut8)cmd->mem_set.space;
		rz_write_at_le16(cmd_raw->body, cmd->mem_set.bank_id, 6);
		memcpy(cmd_raw->body + 8, cmd->mem_set.buf, buf_sz);
		break;
	}
	default:
		// TODO: insert all formats here
		break;


@@ 890,6 917,8 @@ static RzVICEMonErr parse_response(RzVICEMonResponse *resp, RzVICEMonResponseRaw
		memcpy(resp->mem_get.buf, raw->body + 2, rsz);
		break;
	}
	case RZ_VICE_MON_RESPONSE_MEM_SET:
		break;
	case RZ_VICE_MON_RESPONSE_CHECKPOINT_INFO:
		if (raw->body_sz != 0x15) {
			return RZ_VICE_MON_ERR_INVALID_RESPONSE;


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

typedef struct {
	RzVICEMonCommandMemSetArgs args;
} MemWriteAsyncArgs;

static void mem_write_resp_cb(RzVICEMon *mon, RzVICEMonErr r, RzVICEMonResponse *resp, void *user);

static void async_mem_write(RzVICEMon *mon, AsyncCall *call) {
	MemWriteAsyncArgs *args = call->user;
	RzVICEMonCommand cmd = { 0 };
	cmd.type = RZ_VICE_MON_COMMAND_MEM_SET;
	cmd.mem_set = args->args;
	mon_send(mon, &cmd, mem_write_resp_cb, call);
}

static void mem_write_resp_cb(RzVICEMon *mon, RzVICEMonErr r, RzVICEMonResponse *resp, void *user) {
	AsyncCall *call = user;
	MemWriteAsyncArgs *args = call->user;
	size_t buf_sz = (size_t)(args->args.end - args->args.start) + 1;
	if (r == RZ_VICE_MON_ERR_SUCCESS && resp->type != RZ_VICE_MON_RESPONSE_MEM_SET) {
		r = RZ_VICE_MON_ERR_INVALID_RESPONSE;
	}
	async_call_fulfill(mon, call, (void *)(size_t)r);
}

RZ_API RzVICEMonErr rz_vice_mon_mem_write(RzVICEMon *mon, RzVICEMonMemSpace space,
	ut16 start, ut16 end, ut16 bank_id, bool side_effects, RZ_IN const ut8 *buf) {
	MemWriteAsyncArgs args = {
		.args = {
			.space = space,
			.start = start,
			.end = end,
			.bank_id = bank_id,
			.side_effects = side_effects,
			.buf = buf }
	};
	return (RzVICEMonErr)(size_t)async_call_run(mon, async_mem_write, &args);
}

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++) {