From b1ad02893d6678aba4a416132a0718f014cc941f Mon Sep 17 00:00:00 2001 From: beeanyew Date: Tue, 11 May 2021 11:48:53 +0200 Subject: [PATCH] Add memset to PiStorm API, robustify some things to not destroy the bus --- .../amiga/pistorm-dev/pistorm-dev-enums.h | 1 + platforms/amiga/pistorm-dev/pistorm-dev.c | 32 ++++++++++++++---- .../pistorm-dev/pistorm_dev_amiga/PiSimple | Bin 14572 -> 17708 bytes .../pistorm_dev_amiga/pistorm_dev.c | 8 +++++ .../pistorm_dev_amiga/pistorm_dev.h | 1 + 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/platforms/amiga/pistorm-dev/pistorm-dev-enums.h b/platforms/amiga/pistorm-dev/pistorm-dev-enums.h index 4d81ede..eaa938e 100644 --- a/platforms/amiga/pistorm-dev/pistorm-dev-enums.h +++ b/platforms/amiga/pistorm-dev/pistorm-dev-enums.h @@ -30,6 +30,7 @@ enum pistorm_dev_cmds { PI_CMD_GET_FB = 0x010C, // [R] Get the current framebuffer address. PI_CMD_COPYRECT = 0x0110, // [W] Generic memory copyrect with source and destination pitch. PI_CMD_COPYRECT_EX = 0x0112, // [W] Extended memory copyrect with additional source/destination X/Y coordinates. + PI_CMD_MEMSET = 0x0114, // [W] Accelerated memset functionality to quickly clear a region of memory to a specific value. PI_CMD_QBASIC = 0x0FFC, // QBasic PI_CMD_NIBBLES = 0x0FFE, // Nibbles diff --git a/platforms/amiga/pistorm-dev/pistorm-dev.c b/platforms/amiga/pistorm-dev/pistorm-dev.c index 99c8236..4aafd19 100644 --- a/platforms/amiga/pistorm-dev/pistorm-dev.c +++ b/platforms/amiga/pistorm-dev/pistorm-dev.c @@ -61,7 +61,7 @@ int32_t grab_amiga_string(uint32_t addr, uint8_t *dest, uint32_t str_max_len) { if (r == -1) { DEBUG("[GRAB_AMIGA_STRING] No mapped range found for address $%.8X. Grabbing string data over the bus.\n", addr); do { - dest[index] = read8(addr + index); + dest[index] = (unsigned char)m68k_read_memory_8(addr + index); index++; } while (dest[index - 1] != 0x00 && index < str_max_len); } @@ -98,7 +98,7 @@ int32_t amiga_transfer_file(uint32_t addr, char *filename) { for (uint32_t i = 0; i < filesize; i++) { tmp_read = (uint8_t)fgetc(in); - write8(addr + i, tmp_read); + m68k_write_memory_8(addr + i, tmp_read); } } else { uint8_t *dst = cfg->map_data[r] + (addr - cfg->map_offset[r]); @@ -200,16 +200,36 @@ void handle_pistorm_dev_write(uint32_t addr_, uint32_t val, uint8_t type) { printf("!!! doing manual memcpy\n"); uint8_t tmp = 0; for (uint32_t i = 0; i < val; i++) { - if (src == -1) tmp = read8(pi_ptr[0] + i); + if (src == -1) tmp = (unsigned char)m68k_read_memory_8(pi_ptr[0] + i); else tmp = cfg->map_data[src][pi_ptr[0] - cfg->map_offset[src] + i]; - if (dst == -1) write8(pi_ptr[1] + i, tmp); + if (dst == -1) m68k_write_memory_8(pi_ptr[1] + i, tmp); else cfg->map_data[dst][pi_ptr[1] - cfg->map_offset[dst] + i] = tmp; } } //DEBUG("[PISTORM-DEV] Copied %d bytes from $%.8X to $%.8X\n", val, pi_ptr[0], pi_ptr[1]); } break; + case PI_CMD_MEMSET: + //DEBUG("[PISTORM-DEV} Write to MEMSET: %d (%.8X)\n", val, val); + if (pi_ptr[0] == 0) { + printf("[PISTORM-DEV] MEMSET with null pointer not allowed. Aborting.\n"); + pi_cmd_result = PI_RES_INVALIDVALUE; + } else if (val == 0) { + printf("[PISTORM-DEV] MEMSET called with size 0. Aborting.\n"); + pi_cmd_result = PI_RES_INVALIDVALUE; + } else { + int32_t dst = get_mapped_item_by_address(cfg, pi_ptr[0]); + if (dst != -1) { + uint8_t *dst_ptr = &cfg->map_data[dst][(pi_ptr[0] - cfg->map_offset[dst])]; + memset(dst_ptr, pi_byte[0], val); + } else { + for (uint32_t i = 0; i < val; i++) { + m68k_write_memory_8(pi_ptr[0] + i, val); + } + } + } + break; case PI_CMD_COPYRECT: case PI_CMD_COPYRECT_EX: if (pi_ptr[0] == 0 || pi_ptr[1] == 0) { @@ -256,10 +276,10 @@ void handle_pistorm_dev_write(uint32_t addr_, uint32_t val, uint8_t type) { for (uint32_t y = 0; y < pi_word[3]; y++) { for (uint32_t x = 0; x < pi_word[2]; x++) { - if (src == -1) tmp = read8(pi_ptr[0] + src_offset + x); + if (src == -1) tmp = (unsigned char)m68k_read_memory_8(pi_ptr[0] + src_offset + x); else tmp = cfg->map_data[src][(pi_ptr[0] + src_offset + x) - cfg->map_offset[src]]; - if (dst == -1) write8(pi_ptr[1] + dst_offset + x, tmp); + if (dst == -1) m68k_write_memory_8(pi_ptr[1] + dst_offset + x, tmp); else cfg->map_data[dst][(pi_ptr[1] + dst_offset + x) - cfg->map_offset[dst]] = tmp; } src_offset += pi_word[0]; diff --git a/platforms/amiga/pistorm-dev/pistorm_dev_amiga/PiSimple b/platforms/amiga/pistorm-dev/pistorm_dev_amiga/PiSimple index f3c265dd281a004ae08c24e395784c23a008ca2b..167a224560880aac2d76d6839473247ba4187884 100755 GIT binary patch literal 17708 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 literal 14572 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 eA