From 7096342f719470fff7b18111f1b7513ad3cd4617 Mon Sep 17 00:00:00 2001 From: beeanyew Date: Sat, 26 Dec 2020 22:54:10 +0100 Subject: [PATCH 1/8] Some minor optimizations, hopefully fewer jumps and such --- .gitignore | 1 + config_file/config_file.h | 3 + emulator.c | 107 ++++++++++++++---------------- memory_mapped.c | 4 +- platforms/amiga/amiga-platform.c | 26 +++++++- platforms/amiga/amiga-registers.c | 84 +++++++++++------------ platforms/amiga/amiga-registers.h | 8 +++ 7 files changed, 128 insertions(+), 105 deletions(-) diff --git a/.gitignore b/.gitignore index da773f7..cccd3bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.o +*.img /m68kmake /m68kmake.exe /m68kops.c diff --git a/config_file/config_file.h b/config_file/config_file.h index c66fd80..81f2956 100644 --- a/config_file/config_file.h +++ b/config_file/config_file.h @@ -64,10 +64,13 @@ struct emulator_config { unsigned char mouse_enabled, keyboard_enabled; unsigned int loop_cycles; + unsigned int map_low, map_high; + unsigned int custom_low, custom_high; }; struct platform_config { char *subsys; + unsigned char id; int (*custom_read)(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type); int (*custom_write)(struct emulator_config *cfg, unsigned int addr, unsigned int val, unsigned char type); diff --git a/emulator.c b/emulator.c index 39648f3..5c1c013 100644 --- a/emulator.c +++ b/emulator.c @@ -21,6 +21,8 @@ #include "platforms/platforms.h" #include "input/input.h" +#include "platforms/amiga/amiga-registers.h" + //#define BCM2708_PERI_BASE 0x20000000 //pi0-1 //#define BCM2708_PERI_BASE 0xFE000000 //pi4 #define BCM2708_PERI_BASE 0x3F000000 // pi3 @@ -461,16 +463,27 @@ int cpu_irq_ack(int level) { static unsigned int target = 0; -unsigned int m68k_read_memory_8(unsigned int address) { - if (cfg->platform->custom_read && cfg->platform->custom_read(cfg, address, &target, OP_TYPE_BYTE) != -1) { - return target; - } +#define PLATFORM_CHECK_READ(a) \ + if (address >= cfg->custom_low && address < cfg->custom_high) { \ + unsigned int target = 0; \ + switch(cfg->platform->id) { \ + case PLATFORM_AMIGA: { \ + if (custom_read_amiga(cfg, address, &target, a) != -1) { \ + return target; \ + } \ + break; \ + } \ + default: \ + break; \ + } \ + } \ + if (ovl || (address >= cfg->map_low && address < cfg->map_high)) { \ + if (handle_mapped_read(cfg, address, &target, a, ovl) != -1) \ + return target; \ + } \ - if (cfg) { - int ret = handle_mapped_read(cfg, address, &target, OP_TYPE_BYTE, ovl); - if (ret != -1) - return target; - } +unsigned int m68k_read_memory_8(unsigned int address) { + PLATFORM_CHECK_READ(OP_TYPE_BYTE); address &=0xFFFFFF; // if (address < 0xffffff) { @@ -481,15 +494,7 @@ unsigned int m68k_read_memory_8(unsigned int address) { } unsigned int m68k_read_memory_16(unsigned int address) { - if (cfg->platform->custom_read && cfg->platform->custom_read(cfg, address, &target, OP_TYPE_WORD) != -1) { - return target; - } - - if (cfg) { - int ret = handle_mapped_read(cfg, address, &target, OP_TYPE_WORD, ovl); - if (ret != -1) - return target; - } + PLATFORM_CHECK_READ(OP_TYPE_WORD); if (mouse_hook_enabled) { if (address == JOY0DAT) { @@ -527,15 +532,7 @@ unsigned int m68k_read_memory_16(unsigned int address) { } unsigned int m68k_read_memory_32(unsigned int address) { - if (cfg->platform->custom_read && cfg->platform->custom_read(cfg, address, &target, OP_TYPE_LONGWORD) != -1) { - return target; - } - - if (cfg) { - int ret = handle_mapped_read(cfg, address, &target, OP_TYPE_LONGWORD, ovl); - if (ret != -1) - return target; - } + PLATFORM_CHECK_READ(OP_TYPE_LONGWORD); // if (address < 0xffffff) { address &=0xFFFFFF; @@ -547,16 +544,26 @@ unsigned int m68k_read_memory_32(unsigned int address) { // return 1; } -void m68k_write_memory_8(unsigned int address, unsigned int value) { - if (cfg->platform->custom_write && cfg->platform->custom_write(cfg, address, value, OP_TYPE_BYTE) != -1) { - return; - } +#define PLATFORM_CHECK_WRITE(a) \ + if (address >= cfg->custom_low && address < cfg->custom_high) { \ + switch(cfg->platform->id) { \ + case PLATFORM_AMIGA: { \ + if (custom_write_amiga(cfg, address, value, OP_TYPE_BYTE) != -1) { \ + return; \ + } \ + break; \ + } \ + default: \ + break; \ + } \ + } \ + if (address >= cfg->map_low && address < cfg->map_high) { \ + if (handle_mapped_write(cfg, address, value, OP_TYPE_BYTE, ovl) != -1) \ + return; \ + } \ - if (cfg) { - int ret = handle_mapped_write(cfg, address, value, OP_TYPE_BYTE, ovl); - if (ret != -1) - return; - } +void m68k_write_memory_8(unsigned int address, unsigned int value) { + PLATFORM_CHECK_WRITE(OP_TYPE_BYTE); if (address == 0xbfe001) { ovl = (value & (1 << 0)); @@ -573,15 +580,7 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) { } void m68k_write_memory_16(unsigned int address, unsigned int value) { - if (cfg->platform->custom_write && cfg->platform->custom_write(cfg, address, value, OP_TYPE_WORD) != -1) { - return; - } - - if (cfg) { - int ret = handle_mapped_write(cfg, address, value, OP_TYPE_WORD, ovl); - if (ret != -1) - return; - } + PLATFORM_CHECK_WRITE(OP_TYPE_WORD); // if (address < 0xffffff) { address &=0xFFFFFF; @@ -592,15 +591,7 @@ void m68k_write_memory_16(unsigned int address, unsigned int value) { } void m68k_write_memory_32(unsigned int address, unsigned int value) { - if (cfg->platform->custom_write && cfg->platform->custom_write(cfg, address, value, OP_TYPE_LONGWORD) != -1) { - return; - } - - if (cfg) { - int ret = handle_mapped_write(cfg, address, value, OP_TYPE_LONGWORD, ovl); - if (ret != -1) - return; - } + PLATFORM_CHECK_WRITE(OP_TYPE_LONGWORD); // if (address < 0xffffff) { address &=0xFFFFFF; @@ -612,7 +603,7 @@ void m68k_write_memory_32(unsigned int address, unsigned int value) { // return; } -void write16(uint32_t address, uint32_t data) { +inline void write16(uint32_t address, uint32_t data) { uint32_t addr_h_s = (address & 0x0000ffff) << 8; uint32_t addr_h_r = (~address & 0x0000ffff) << 8; uint32_t addr_l_s = (address >> 16) << 8; @@ -650,7 +641,7 @@ void write16(uint32_t address, uint32_t data) { // asm volatile ("dmb" ::: "memory"); } -void write8(uint32_t address, uint32_t data) { +inline void write8(uint32_t address, uint32_t data) { if ((address & 1) == 0) data = data + (data << 8); // EVEN, A0=0,UDS else @@ -692,7 +683,7 @@ void write8(uint32_t address, uint32_t data) { // asm volatile ("dmb" ::: "memory"); } -uint32_t read16(uint32_t address) { +inline uint32_t read16(uint32_t address) { volatile int val; uint32_t addr_h_s = (address & 0x0000ffff) << 8; uint32_t addr_h_r = (~address & 0x0000ffff) << 8; @@ -729,7 +720,7 @@ uint32_t read16(uint32_t address) { return (val >> 8) & 0xffff; } -uint32_t read8(uint32_t address) { +inline uint32_t read8(uint32_t address) { int val; uint32_t addr_h_s = (address & 0x0000ffff) << 8; uint32_t addr_h_r = (~address & 0x0000ffff) << 8; diff --git a/memory_mapped.c b/memory_mapped.c index e2dd9a4..ae9bf2a 100644 --- a/memory_mapped.c +++ b/memory_mapped.c @@ -15,7 +15,7 @@ const char *op_type_names[OP_TYPE_NUM] = { "MEM", }; -int handle_mapped_read(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type, unsigned char mirror) { +inline int handle_mapped_read(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type, unsigned char mirror) { unsigned char *read_addr = NULL; char handle_regs = 0; @@ -82,7 +82,7 @@ int handle_mapped_read(struct emulator_config *cfg, unsigned int addr, unsigned return -1; } -int handle_mapped_write(struct emulator_config *cfg, unsigned int addr, unsigned int value, unsigned char type, unsigned char mirror) { +inline int handle_mapped_write(struct emulator_config *cfg, unsigned int addr, unsigned int value, unsigned char type, unsigned char mirror) { unsigned char *write_addr = NULL; char handle_regs = 0; diff --git a/platforms/amiga/amiga-platform.c b/platforms/amiga/amiga-platform.c index 4fe96e1..21a2c62 100644 --- a/platforms/amiga/amiga-platform.c +++ b/platforms/amiga/amiga-platform.c @@ -17,6 +17,7 @@ extern int ac_z3_pic_count; extern int ac_z3_done; extern int ac_z3_type[AC_PIC_LIMIT]; extern int ac_z3_index[AC_PIC_LIMIT]; +extern int gayle_emulation_enabled; char *z2_autoconf_id = "z2_autoconf_fast"; char *z2_autoconf_zap_id = "^2_autoconf_fast"; @@ -25,7 +26,7 @@ char *z3_autoconf_zap_id = "^3_autoconf_fast"; extern const char *op_type_names[OP_TYPE_NUM]; -int custom_read_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type) { +inline int custom_read_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type) { if (!ac_z2_done && addr >= AC_Z2_BASE && addr < AC_Z2_BASE + AC_SIZE) { if (ac_z2_pic_count == 0) { ac_z2_done = 1; @@ -56,7 +57,7 @@ int custom_read_amiga(struct emulator_config *cfg, unsigned int addr, unsigned i return -1; } -int custom_write_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int val, unsigned char type) { +inline int custom_write_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int val, unsigned char type) { if (!ac_z2_done && addr >= AC_Z2_BASE && addr < AC_Z2_BASE + AC_SIZE) { if (type == OP_TYPE_BYTE) { if (ac_z2_pic_count == 0) { @@ -156,11 +157,29 @@ int setup_platform_amiga(struct emulator_config *cfg) { index = get_named_mapped_item(cfg, z3_autoconf_id); if (index != -1) goto more_z3_fast; - for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i ++) { + for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) { if (cfg->map_id[i] && strcmp(cfg->map_id[i], z3_autoconf_zap_id) == 0) { cfg->map_id[i][0] = z3_autoconf_id[0]; } } + + // Set up the min/max ranges for mapped reads/writes + for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) { + if (cfg->map_type[i] != MAPTYPE_NONE) { + if ((cfg->map_offset[i] != 0 && cfg->map_offset[i] < cfg->map_low) || cfg->map_low == 0) + cfg->map_low = cfg->map_offset[i]; + if (cfg->map_offset[i] + cfg->map_size[i] > cfg->map_high) + cfg->map_high = cfg->map_offset[i] + cfg->map_size[i]; + } + } + + if (gayle_emulation_enabled) { + cfg->custom_low = GAYLEBASE; + cfg->custom_high = GAYLEBASE + GAYLESIZE; + } + + printf("Platform custom range: %.8X-%.8X\n", cfg->custom_low, cfg->custom_high); + printf("Platform mapped range: %.8X-%.8X\n", cfg->map_low, cfg->map_high); return 0; } @@ -194,6 +213,7 @@ void create_platform_amiga(struct platform_config *cfg, char *subsys) { cfg->platform_initial_setup = setup_platform_amiga; cfg->setvar = setvar_amiga; + cfg->id = PLATFORM_AMIGA; if (subsys) { cfg->subsys = malloc(strlen(subsys) + 1); diff --git a/platforms/amiga/amiga-registers.c b/platforms/amiga/amiga-registers.c index 96aa653..d5e3b69 100644 --- a/platforms/amiga/amiga-registers.c +++ b/platforms/amiga/amiga-registers.c @@ -1,13 +1,9 @@ #include "../../Gayle.h" #include "../../config_file/config_file.h" - -#define GAYLEBASE 0xD80000 // D7FFFF -#define GAYLESIZE 0x6FFFF - -#define CLOCKBASE 0xDC0000 -#define CLOCKSIZE 0x010000 +#include "amiga-registers.h" uint8_t rtc_emulation_enabled = 1; +extern int gayle_emulation_enabled; void configure_rtc_emulation_amiga(uint8_t enabled) { if (enabled == rtc_emulation_enabled) @@ -18,50 +14,54 @@ void configure_rtc_emulation_amiga(uint8_t enabled) { } int handle_register_read_amiga(unsigned int addr, unsigned char type, unsigned int *val) { - if (!rtc_emulation_enabled && addr >= CLOCKBASE && addr < CLOCKBASE + CLOCKSIZE) - return -1; - if (addr >= GAYLEBASE && addr < GAYLEBASE + GAYLESIZE) { - switch(type) { - case OP_TYPE_BYTE: - *val = readGayleB(addr); - return 1; - break; - case OP_TYPE_WORD: - *val = readGayle(addr); - return 1; - break; - case OP_TYPE_LONGWORD: - *val = readGayleL(addr); - return 1; - break; - case OP_TYPE_MEM: + if (gayle_emulation_enabled) { + if (!rtc_emulation_enabled && addr >= CLOCKBASE && addr < CLOCKBASE + CLOCKSIZE) return -1; - break; + if (addr >= GAYLEBASE && addr < GAYLEBASE + GAYLESIZE) { + switch(type) { + case OP_TYPE_BYTE: + *val = readGayleB(addr); + return 1; + break; + case OP_TYPE_WORD: + *val = readGayle(addr); + return 1; + break; + case OP_TYPE_LONGWORD: + *val = readGayleL(addr); + return 1; + break; + case OP_TYPE_MEM: + return -1; + break; + } } } return -1; } int handle_register_write_amiga(unsigned int addr, unsigned int value, unsigned char type) { - if (!rtc_emulation_enabled && addr >= CLOCKBASE && addr < CLOCKBASE + CLOCKSIZE) - return -1; - if (addr >= GAYLEBASE && addr < GAYLEBASE + GAYLESIZE) { - switch(type) { - case OP_TYPE_BYTE: - writeGayleB(addr, value); - return 1; - break; - case OP_TYPE_WORD: - writeGayle(addr, value); - return 1; - break; - case OP_TYPE_LONGWORD: - writeGayleL(addr, value); - return 1; - break; - case OP_TYPE_MEM: + if (gayle_emulation_enabled) { + if (!rtc_emulation_enabled && addr >= CLOCKBASE && addr < CLOCKBASE + CLOCKSIZE) return -1; - break; + if (addr >= GAYLEBASE && addr < GAYLEBASE + GAYLESIZE) { + switch(type) { + case OP_TYPE_BYTE: + writeGayleB(addr, value); + return 1; + break; + case OP_TYPE_WORD: + writeGayle(addr, value); + return 1; + break; + case OP_TYPE_LONGWORD: + writeGayleL(addr, value); + return 1; + break; + case OP_TYPE_MEM: + return -1; + break; + } } } return -1; diff --git a/platforms/amiga/amiga-registers.h b/platforms/amiga/amiga-registers.h index df010da..53a7b90 100644 --- a/platforms/amiga/amiga-registers.h +++ b/platforms/amiga/amiga-registers.h @@ -1,2 +1,10 @@ void configure_rtc_emulation_amiga(uint8_t enabled); void set_hard_drive_image_file_amiga(uint8_t index, char *filename); +int custom_read_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type); +int custom_write_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int val, unsigned char type); + +#define GAYLEBASE 0xD80000 +#define GAYLESIZE 0x70000 + +#define CLOCKBASE 0xDC0000 +#define CLOCKSIZE 0x010000 From 20b1a1fa0b8142b5be8e8dbbbbd6d71a9f2a931e Mon Sep 17 00:00:00 2001 From: beeanyew Date: Mon, 28 Dec 2020 16:13:25 +0100 Subject: [PATCH 2/8] More tiny optimizations, some Z2/Z3 fixes Also disables keyboard input for now, until more investigating can be done. --- config_file/config_file.c | 1 + config_file/config_file.h | 8 +- emulator.c | 20 ++-- memory_mapped.c | 174 ++++++++++++++----------------- platforms/amiga/amiga-autoconf.c | 16 ++- platforms/amiga/amiga-platform.c | 70 +++++++++---- 6 files changed, 159 insertions(+), 130 deletions(-) diff --git a/config_file/config_file.c b/config_file/config_file.c index 1d41335..76d0bb6 100644 --- a/config_file/config_file.c +++ b/config_file/config_file.c @@ -185,6 +185,7 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad cfg->map_type[index] = type; cfg->map_offset[index] = addr; cfg->map_size[index] = size; + cfg->map_high[index] = addr + size; cfg->map_mirror[index] = mirr_addr; if (strlen(map_id)) { cfg->map_id[index] = (char *)malloc(strlen(map_id) + 1); diff --git a/config_file/config_file.h b/config_file/config_file.h index 81f2956..2e8cbae 100644 --- a/config_file/config_file.h +++ b/config_file/config_file.h @@ -50,6 +50,7 @@ struct emulator_config { unsigned char map_type[MAX_NUM_MAPPED_ITEMS]; long map_offset[MAX_NUM_MAPPED_ITEMS]; + long map_high[MAX_NUM_MAPPED_ITEMS]; unsigned int map_size[MAX_NUM_MAPPED_ITEMS]; unsigned int rom_size[MAX_NUM_MAPPED_ITEMS]; unsigned char *map_data[MAX_NUM_MAPPED_ITEMS]; @@ -64,7 +65,7 @@ struct emulator_config { unsigned char mouse_enabled, keyboard_enabled; unsigned int loop_cycles; - unsigned int map_low, map_high; + unsigned int mapped_low, mapped_high; unsigned int custom_low, custom_high; }; @@ -79,13 +80,14 @@ struct platform_config { int (*register_write)(unsigned int addr, unsigned int value, unsigned char type); int (*platform_initial_setup)(struct emulator_config *cfg); + void (*handle_reset)(struct emulator_config *cfg); void (*setvar)(char *var, char *val); }; unsigned int get_m68k_cpu_type(char *name); struct emulator_config *load_config_file(char *filename); -int handle_mapped_read(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type, unsigned char mirror); -int handle_mapped_write(struct emulator_config *cfg, unsigned int addr, unsigned int value, unsigned char type, unsigned char mirror); +int handle_mapped_read(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type); +int handle_mapped_write(struct emulator_config *cfg, unsigned int addr, unsigned int value, unsigned char type); int get_named_mapped_item(struct emulator_config *cfg, char *name); unsigned int get_int(char *str); diff --git a/emulator.c b/emulator.c index 5c1c013..a019512 100644 --- a/emulator.c +++ b/emulator.c @@ -152,7 +152,7 @@ volatile uint32_t srdata2_old; //unsigned char g_kick[524288]; //unsigned char g_ram[FASTSIZE + 1]; /* RAM */ unsigned char toggle; -static volatile unsigned char ovl; +int ovl; static volatile unsigned char maprom; void sigint_handler(int sig_num) { @@ -383,7 +383,7 @@ int main(int argc, char *argv[]) { m68k_execute(loop_cycles); // FIXME: Rework this to use keyboard events instead. - while (get_key_char(&c)) { + /*while (get_key_char(&c)) { if (c == cfg->keyboard_toggle_key && !kb_hook_enabled) { kb_hook_enabled = 1; printf("Keyboard hook enabled.\n"); @@ -412,7 +412,7 @@ int main(int argc, char *argv[]) { goto stop_cpu_emulation; } } - } + }*/ /* if (toggle == 1){ srdata = read_reg(); @@ -477,10 +477,10 @@ static unsigned int target = 0; break; \ } \ } \ - if (ovl || (address >= cfg->map_low && address < cfg->map_high)) { \ - if (handle_mapped_read(cfg, address, &target, a, ovl) != -1) \ + if (ovl || (address >= cfg->mapped_low && address < cfg->mapped_high)) { \ + if (handle_mapped_read(cfg, address, &target, a) != -1) \ return target; \ - } \ + } unsigned int m68k_read_memory_8(unsigned int address) { PLATFORM_CHECK_READ(OP_TYPE_BYTE); @@ -548,7 +548,7 @@ unsigned int m68k_read_memory_32(unsigned int address) { if (address >= cfg->custom_low && address < cfg->custom_high) { \ switch(cfg->platform->id) { \ case PLATFORM_AMIGA: { \ - if (custom_write_amiga(cfg, address, value, OP_TYPE_BYTE) != -1) { \ + if (custom_write_amiga(cfg, address, value, a) != -1) { \ return; \ } \ break; \ @@ -557,10 +557,10 @@ unsigned int m68k_read_memory_32(unsigned int address) { break; \ } \ } \ - if (address >= cfg->map_low && address < cfg->map_high) { \ - if (handle_mapped_write(cfg, address, value, OP_TYPE_BYTE, ovl) != -1) \ + if (address >= cfg->mapped_low && address < cfg->mapped_high) { \ + if (handle_mapped_write(cfg, address, value, a) != -1) \ return; \ - } \ + } void m68k_write_memory_8(unsigned int address, unsigned int value) { PLATFORM_CHECK_WRITE(OP_TYPE_BYTE); diff --git a/memory_mapped.c b/memory_mapped.c index ae9bf2a..bf42406 100644 --- a/memory_mapped.c +++ b/memory_mapped.c @@ -4,8 +4,10 @@ #include #define CHKRANGE(a, b, c) a >= (unsigned int)b && a < (unsigned int)(b + c) +#define CHKRANGE_ABS(a, b, c) a >= (unsigned int)b && a < (unsigned int) c static unsigned int target; +extern int ovl; extern const char *map_type_names[MAPTYPE_NUM]; const char *op_type_names[OP_TYPE_NUM] = { @@ -15,64 +17,35 @@ const char *op_type_names[OP_TYPE_NUM] = { "MEM", }; -inline int handle_mapped_read(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type, unsigned char mirror) { +inline int handle_mapped_read(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type) { unsigned char *read_addr = NULL; - char handle_regs = 0; - - //printf("Mapped read: %.8x\n", addr); for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) { if (cfg->map_type[i] == MAPTYPE_NONE) continue; - switch(cfg->map_type[i]) { - case MAPTYPE_ROM: - if (CHKRANGE(addr, cfg->map_offset[i], cfg->map_size[i])) + else if (ovl && cfg->map_type[i] == MAPTYPE_ROM) { + if (cfg->map_mirror[i] != -1 && CHKRANGE_ABS(addr, cfg->map_mirror[i], cfg->map_high[i])) { + read_addr = cfg->map_data[i] + ((addr - cfg->map_mirror[i]) % cfg->rom_size[i]); + goto read_value; + } + } + else if (CHKRANGE_ABS(addr, cfg->map_offset[i], cfg->map_high[i])) { + switch(cfg->map_type[i]) { + case MAPTYPE_ROM: read_addr = cfg->map_data[i] + ((addr - cfg->map_offset[i]) % cfg->rom_size[i]); - else if (cfg->map_mirror[i] != -1 && mirror && CHKRANGE(addr, cfg->map_mirror[i], cfg->map_size[i])) - read_addr = cfg->map_data[i] + ((addr - cfg->map_mirror[i]) % cfg->rom_size[i]); - break; - case MAPTYPE_RAM: - if (CHKRANGE(addr, cfg->map_offset[i], cfg->map_size[i])) + goto read_value; + break; + case MAPTYPE_RAM: read_addr = cfg->map_data[i] + (addr - cfg->map_offset[i]); - break; - case MAPTYPE_REGISTER: - if (CHKRANGE(addr, cfg->map_offset[i], cfg->map_size[i])) - handle_regs = 1; - break; - } - - if (!read_addr && !handle_regs) - continue; - - if (handle_regs) { - if (cfg->platform && cfg->platform->register_read) { - if (cfg->platform->register_read(addr, type, &target) != -1) { - *val = target; - return 1; - } - } - return -1; - } - else if (read_addr) { - //printf("[PC: %.8X] Read %s from %s (%.8X) (%d)\n", m68k_get_reg(NULL, M68K_REG_PC), op_type_names[type], map_type_names[cfg->map_type[i]], addr, mirror); - //printf("Readaddr: %.8lX (Base %.8lX\n", (uint64_t)(read_addr), (uint64_t)cfg->map_data[i]); - switch(type) { - case OP_TYPE_BYTE: - *val = read_addr[0]; - //printf("Read val: %.8lX (%d)\n", (uint64_t)val, *val); - return 1; + goto read_value; break; - case OP_TYPE_WORD: - *val = be16toh(((unsigned short *)read_addr)[0]); - //printf("Read val: %.8lX (%d)\n", (uint64_t)val, *val); - return 1; - break; - case OP_TYPE_LONGWORD: - *val = be32toh(((unsigned int *)read_addr)[0]); - //printf("Read val: %.8lX (%d)\n", (uint64_t)val, *val); - return 1; - break; - case OP_TYPE_MEM: + case MAPTYPE_REGISTER: + if (cfg->platform && cfg->platform->register_read) { + if (cfg->platform->register_read(addr, type, &target) != -1) { + *val = target; + return 1; + } + } return -1; break; } @@ -80,66 +53,75 @@ inline int handle_mapped_read(struct emulator_config *cfg, unsigned int addr, un } return -1; + +read_value:; + //printf("Read value from %.8X\n", addr); + switch(type) { + case OP_TYPE_BYTE: + *val = read_addr[0]; + return 1; + break; + case OP_TYPE_WORD: + *val = be16toh(((unsigned short *)read_addr)[0]); + return 1; + break; + case OP_TYPE_LONGWORD: + *val = be32toh(((unsigned int *)read_addr)[0]); + return 1; + break; + case OP_TYPE_MEM: + return -1; + break; + } + + return 1; } -inline int handle_mapped_write(struct emulator_config *cfg, unsigned int addr, unsigned int value, unsigned char type, unsigned char mirror) { +inline int handle_mapped_write(struct emulator_config *cfg, unsigned int addr, unsigned int value, unsigned char type) { unsigned char *write_addr = NULL; - char handle_regs = 0; - - //printf("Mapped write: %.8x\n", addr); - if (mirror) { } for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) { if (cfg->map_type[i] == MAPTYPE_NONE) continue; - switch(cfg->map_type[i]) { - case MAPTYPE_ROM: - if (CHKRANGE(addr, cfg->map_offset[i], cfg->map_size[i])) + else if (CHKRANGE_ABS(addr, cfg->map_offset[i], cfg->map_high[i])) { + switch(cfg->map_type[i]) { + case MAPTYPE_ROM: return 1; - break; - case MAPTYPE_RAM: - if (CHKRANGE(addr, cfg->map_offset[i], cfg->map_size[i])) + break; + case MAPTYPE_RAM: write_addr = cfg->map_data[i] + (addr - cfg->map_offset[i]); - break; - case MAPTYPE_REGISTER: - if (CHKRANGE(addr, cfg->map_offset[i], cfg->map_size[i])) - handle_regs = 1; - break; - } - - if (!write_addr && !handle_regs) - continue; - - if (handle_regs) { - if (cfg->platform && cfg->platform->register_write) { - return cfg->platform->register_write(addr, value, type); - } - } - else if (write_addr) { - //printf("[PC: %.8X] Write %s to %s (%.8X) (%d)\n", m68k_get_reg(NULL, M68K_REG_PC), op_type_names[type], map_type_names[cfg->map_type[i]], addr, mirror); - //printf("Writeaddr: %.8lX (Base %.8lX\n", (uint64_t)(write_addr), (uint64_t)cfg->map_data[i]); - switch(type) { - case OP_TYPE_BYTE: - write_addr[0] = (unsigned char)value; - //printf("Write val: %.8X (%d)\n", (uint32_t)value, value); - return 1; + goto write_value; break; - case OP_TYPE_WORD: - ((short *)write_addr)[0] = htobe16(value); - //printf("Write val: %.8X (%d)\n", (uint32_t)value, value); - return 1; - break; - case OP_TYPE_LONGWORD: - ((int *)write_addr)[0] = htobe32(value); - //printf("Write val: %.8X (%d)\n", (uint32_t)value, value); - return 1; - break; - case OP_TYPE_MEM: - return -1; + case MAPTYPE_REGISTER: + if (cfg->platform && cfg->platform->register_write) { + return cfg->platform->register_write(addr, value, type); + } break; } } } return -1; + +write_value:; + //printf("Write value to %.8X\n", addr); + switch(type) { + case OP_TYPE_BYTE: + write_addr[0] = (unsigned char)value; + return 1; + break; + case OP_TYPE_WORD: + ((short *)write_addr)[0] = htobe16(value); + return 1; + break; + case OP_TYPE_LONGWORD: + ((int *)write_addr)[0] = htobe32(value); + return 1; + break; + case OP_TYPE_MEM: + return -1; + break; + } + + return 1; } diff --git a/platforms/amiga/amiga-autoconf.c b/platforms/amiga/amiga-autoconf.c index 913d6c2..b27c0ec 100644 --- a/platforms/amiga/amiga-autoconf.c +++ b/platforms/amiga/amiga-autoconf.c @@ -66,6 +66,8 @@ unsigned char get_autoconf_size_ext(int size) { return AC_MEM_SIZE_EXT_64MB; } +extern void adjust_ranges_amiga(struct emulator_config *cfg); + unsigned int autoconfig_read_memory_z3_8(struct emulator_config *cfg, unsigned int address_) { int address = address_ - AC_Z3_BASE; int index = ac_z3_index[ac_z3_current_pic]; @@ -180,9 +182,12 @@ void autoconfig_write_memory_z3_8(struct emulator_config *cfg, unsigned int addr nib_latch = 0; printf("Address of Z3 autoconf RAM assigned to $%.8x\n", ac_base[ac_z3_current_pic]); cfg->map_offset[index] = ac_base[ac_z3_current_pic]; + cfg->map_high[index] = cfg->map_offset[index] + cfg->map_size[index]; ac_z3_current_pic++; - if (ac_z3_current_pic == ac_z3_pic_count) + if (ac_z3_current_pic == ac_z3_pic_count) { ac_z3_done = 1; + adjust_ranges_amiga(cfg); + } } return; @@ -255,6 +260,7 @@ unsigned int autoconfig_read_memory_8(struct emulator_config *cfg, unsigned int void autoconfig_write_memory_8(struct emulator_config *cfg, unsigned int address_, unsigned int value) { int address = address_ - AC_Z2_BASE; int done = 0; + int index = ac_z2_index[ac_z2_current_pic]; unsigned int *base = NULL; @@ -292,9 +298,13 @@ void autoconfig_write_memory_8(struct emulator_config *cfg, unsigned int address if (done) { printf("Address of Z2 autoconf RAM assigned to $%.8x\n", ac_base[ac_z2_current_pic]); - cfg->map_offset[ac_z2_index[ac_z2_current_pic]] = ac_base[ac_z2_current_pic]; + cfg->map_offset[index] = ac_base[ac_z2_current_pic]; + cfg->map_high[index] = cfg->map_offset[index] + cfg->map_size[index]; + printf("Z2 PIC %d at $%.8lX-%.8lX, Size: %d MB\n", ac_z2_current_pic, cfg->map_offset[index], cfg->map_high[index], cfg->map_size[index] / SIZE_MEGA); ac_z2_current_pic++; - if (ac_z2_current_pic == ac_z2_pic_count) + if (ac_z2_current_pic == ac_z2_pic_count) { ac_z2_done = 1; + adjust_ranges_amiga(cfg); + } } } diff --git a/platforms/amiga/amiga-platform.c b/platforms/amiga/amiga-platform.c index 21a2c62..c2361e3 100644 --- a/platforms/amiga/amiga-platform.c +++ b/platforms/amiga/amiga-platform.c @@ -26,6 +26,9 @@ char *z3_autoconf_zap_id = "^3_autoconf_fast"; extern const char *op_type_names[OP_TYPE_NUM]; +#define min(a, b) (a < b) ? a : b +#define max(a, b) (a > b) ? a : b + inline int custom_read_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type) { if (!ac_z2_done && addr >= AC_Z2_BASE && addr < AC_Z2_BASE + AC_SIZE) { if (ac_z2_pic_count == 0) { @@ -65,7 +68,7 @@ inline int custom_write_amiga(struct emulator_config *cfg, unsigned int addr, un return -1; } - printf("Write to Z2 autoconf area.\n"); + //printf("Write to Z2 autoconf area.\n"); autoconfig_write_memory_8(cfg, addr, val); return 1; } @@ -95,6 +98,45 @@ inline int custom_write_amiga(struct emulator_config *cfg, unsigned int addr, un return -1; } +void adjust_ranges_amiga(struct emulator_config *cfg) { + cfg->mapped_high = 0; + cfg->mapped_low = 0; + cfg->custom_high = 0; + cfg->custom_low = 0; + + // Set up the min/max ranges for mapped reads/writes + if (gayle_emulation_enabled) { + cfg->mapped_low = GAYLEBASE; + cfg->mapped_high = GAYLEBASE + GAYLESIZE; + } + for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) { + if (cfg->map_type[i] != MAPTYPE_NONE) { + if ((cfg->map_offset[i] != 0 && cfg->map_offset[i] < cfg->mapped_low) || cfg->mapped_low == 0) + cfg->mapped_low = cfg->map_offset[i]; + if (cfg->map_offset[i] + cfg->map_size[i] > cfg->mapped_high) + cfg->mapped_high = cfg->map_offset[i] + cfg->map_size[i]; + } + } + + if (ac_z2_pic_count && !ac_z2_done) { + if (cfg->custom_low == 0) + cfg->custom_low = AC_Z2_BASE; + else + cfg->custom_low = min(cfg->custom_low, AC_Z2_BASE); + cfg->custom_high = max(cfg->custom_high, AC_Z2_BASE + AC_SIZE); + } + if (ac_z3_pic_count && !ac_z3_done) { + if (cfg->custom_low == 0) + cfg->custom_low = AC_Z3_BASE; + else + cfg->custom_low = min(cfg->custom_low, AC_Z3_BASE); + cfg->custom_high = max(cfg->custom_high, AC_Z3_BASE + AC_SIZE); + } + + printf("Platform custom range: %.8X-%.8X\n", cfg->custom_low, cfg->custom_high); + printf("Platform mapped range: %.8X-%.8X\n", cfg->mapped_low, cfg->mapped_high); +} + int setup_platform_amiga(struct emulator_config *cfg) { if (cfg) {} printf("Performing setup for Amiga platform.\n"); @@ -163,23 +205,7 @@ int setup_platform_amiga(struct emulator_config *cfg) { } } - // Set up the min/max ranges for mapped reads/writes - for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) { - if (cfg->map_type[i] != MAPTYPE_NONE) { - if ((cfg->map_offset[i] != 0 && cfg->map_offset[i] < cfg->map_low) || cfg->map_low == 0) - cfg->map_low = cfg->map_offset[i]; - if (cfg->map_offset[i] + cfg->map_size[i] > cfg->map_high) - cfg->map_high = cfg->map_offset[i] + cfg->map_size[i]; - } - } - - if (gayle_emulation_enabled) { - cfg->custom_low = GAYLEBASE; - cfg->custom_high = GAYLEBASE + GAYLESIZE; - } - - printf("Platform custom range: %.8X-%.8X\n", cfg->custom_low, cfg->custom_high); - printf("Platform mapped range: %.8X-%.8X\n", cfg->map_low, cfg->map_high); + adjust_ranges_amiga(cfg); return 0; } @@ -205,12 +231,20 @@ void setvar_amiga(char *var, char *val) { } } +void handle_reset_amiga(struct emulator_config *cfg) { + ac_z3_done = 0; + ac_z2_done = 0; + + adjust_ranges_amiga(cfg); +} + void create_platform_amiga(struct platform_config *cfg, char *subsys) { cfg->register_read = handle_register_read_amiga; cfg->register_write = handle_register_write_amiga; cfg->custom_read = custom_read_amiga; cfg->custom_write = custom_write_amiga; cfg->platform_initial_setup = setup_platform_amiga; + cfg->handle_reset = handle_reset_amiga; cfg->setvar = setvar_amiga; cfg->id = PLATFORM_AMIGA; From 2eb8474c924b9b5d9c5241d0f8f385890084c896 Mon Sep 17 00:00:00 2001 From: beeanyew Date: Thu, 31 Dec 2020 12:15:42 +0100 Subject: [PATCH 3/8] Plug some read/write mappings directly into Musashi --- m68k.h | 4 +++ m68kcpu.c | 47 ++++++++++++++++++++++++++++++ m68kcpu.h | 50 ++++++++++++++++++++++++++++++++ platforms/amiga/amiga-autoconf.c | 10 +++++-- platforms/amiga/amiga-platform.c | 6 +++- 5 files changed, 113 insertions(+), 4 deletions(-) diff --git a/m68k.h b/m68k.h index 555b314..e005ca9 100644 --- a/m68k.h +++ b/m68k.h @@ -199,6 +199,10 @@ void m68k_write_memory_8(unsigned int address, unsigned int value); void m68k_write_memory_16(unsigned int address, unsigned int value); void m68k_write_memory_32(unsigned int address, unsigned int value); +/* PiStorm speed hax */ +void m68k_add_ram_range(uint32_t addr, uint32_t upper, unsigned char *ptr); +void m68k_add_rom_range(uint32_t addr, uint32_t upper, unsigned char *ptr); + /* Special call to simulate undocumented 68k behavior when move.l with a * predecrement destination mode is executed. * To simulate real 68k behavior, first write the high word to diff --git a/m68kcpu.c b/m68kcpu.c index 1012799..cc54957 100644 --- a/m68kcpu.c +++ b/m68kcpu.c @@ -45,6 +45,15 @@ extern unsigned char m68ki_cycles[][0x10000]; extern void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ extern void m68ki_build_opcode_table(void); +static unsigned char read_ranges; +static unsigned int read_addr[8]; +static unsigned int read_upper[8]; +static unsigned char *read_data[8]; +static unsigned char write_ranges; +static unsigned int write_addr[8]; +static unsigned int write_upper[8]; +static unsigned char *write_data[8]; + #include "m68kops.h" #include "m68kcpu.h" @@ -1165,6 +1174,44 @@ void m68k_set_context(void* src) if(src) m68ki_cpu = *(m68ki_cpu_core*)src; } +void m68k_add_ram_range(uint32_t addr, uint32_t upper, unsigned char *ptr) +{ + if (read_ranges + 1 < 8) { + read_addr[read_ranges] = addr; + read_upper[read_ranges] = upper; + read_data[read_ranges] = ptr; + read_ranges++; + printf("[MUSASHI] Mapped read range %d: %.8X-%.8X (%p)\n", read_ranges, addr, upper, ptr); + } + else { + printf("Can't Musashi map more than eight RAM/ROM read ranges.\n"); + } + if (write_ranges + 1 < 8) { + write_addr[write_ranges] = addr; + write_upper[write_ranges] = upper; + write_data[write_ranges] = ptr; + write_ranges++; + printf("[MUSASHI] Mapped write range %d: %.8X-%.8X (%p)\n", write_ranges, addr, upper, ptr); + } + else { + printf("Can't Musashi map more than eight RAM write ranges.\n"); + } +} + +void m68k_add_rom_range(uint32_t addr, uint32_t upper, unsigned char *ptr) +{ + if (read_ranges + 1 < 8) { + read_addr[read_ranges] = addr; + read_upper[read_ranges] = upper; + read_data[read_ranges] = ptr; + read_ranges++; + printf("[MUSASHI] Mapped read range %d: %.8X-%.8X (%p)\n", read_ranges, addr, upper, ptr); + } + else { + printf("Can't Musashi map more than eight RAM/ROM read ranges.\n"); + } +} + /* ======================================================================== */ /* ============================== MAME STUFF ============================== */ /* ======================================================================== */ diff --git a/m68kcpu.h b/m68kcpu.h index 467169b..0ba7aee 100644 --- a/m68kcpu.h +++ b/m68kcpu.h @@ -40,6 +40,7 @@ extern "C" { #include "m68k.h" #include +#include #include @@ -1124,6 +1125,16 @@ static inline uint m68ki_read_imm_32(void) * These functions will also check for address error and set the function * code if they are enabled in m68kconf.h. */ + +static unsigned char read_ranges; +static unsigned int read_addr[8]; +static unsigned int read_upper[8]; +static unsigned char *read_data[8]; +static unsigned char write_ranges; +static unsigned int write_addr[8]; +static unsigned int write_upper[8]; +static unsigned char *write_data[8]; + static inline uint m68ki_read_8_fc(uint address, uint fc) { (void)fc; @@ -1134,6 +1145,12 @@ static inline uint m68ki_read_8_fc(uint address, uint fc) address = pmmu_translate_addr(address); #endif + for (int i = 0; i < read_ranges; i++) { + if(address >= read_addr[i] && address < read_upper[i]) { + return read_data[i][address]; + } + } + return m68k_read_memory_8(ADDRESS_68K(address)); } static inline uint m68ki_read_16_fc(uint address, uint fc) @@ -1147,6 +1164,12 @@ static inline uint m68ki_read_16_fc(uint address, uint fc) address = pmmu_translate_addr(address); #endif + for (int i = 0; i < read_ranges; i++) { + if(address >= read_addr[i] && address < read_upper[i]) { + return be16toh(((unsigned short *)(read_data[i] + (address - read_addr[i])))[0]); + } + } + return m68k_read_memory_16(ADDRESS_68K(address)); } static inline uint m68ki_read_32_fc(uint address, uint fc) @@ -1160,6 +1183,12 @@ static inline uint m68ki_read_32_fc(uint address, uint fc) address = pmmu_translate_addr(address); #endif + for (int i = 0; i < read_ranges; i++) { + if(address >= read_addr[i] && address < read_upper[i]) { + return be32toh(((unsigned int *)(read_data[i] + (address - read_addr[i])))[0]); + } + } + return m68k_read_memory_32(ADDRESS_68K(address)); } @@ -1173,6 +1202,13 @@ static inline void m68ki_write_8_fc(uint address, uint fc, uint value) address = pmmu_translate_addr(address); #endif + for (int i = 0; i < write_ranges; i++) { + if(address >= write_addr[i] && address < write_upper[i]) { + write_data[i][address] = (unsigned char)value; + return; + } + } + m68k_write_memory_8(ADDRESS_68K(address), value); } static inline void m68ki_write_16_fc(uint address, uint fc, uint value) @@ -1186,6 +1222,13 @@ static inline void m68ki_write_16_fc(uint address, uint fc, uint value) address = pmmu_translate_addr(address); #endif + for (int i = 0; i < write_ranges; i++) { + if(address >= write_addr[i] && address < write_upper[i]) { + ((short *)(read_data[i] + (address - read_addr[i])))[0] = htobe16(value); + return; + } + } + m68k_write_memory_16(ADDRESS_68K(address), value); } static inline void m68ki_write_32_fc(uint address, uint fc, uint value) @@ -1199,6 +1242,13 @@ static inline void m68ki_write_32_fc(uint address, uint fc, uint value) address = pmmu_translate_addr(address); #endif + for (int i = 0; i < write_ranges; i++) { + if(address >= write_addr[i] && address < write_upper[i]) { + ((int *)(read_data[i] + (address - read_addr[i])))[0] = htobe32(value); + return; + } + } + m68k_write_memory_32(ADDRESS_68K(address), value); } diff --git a/platforms/amiga/amiga-autoconf.c b/platforms/amiga/amiga-autoconf.c index b27c0ec..68f1252 100644 --- a/platforms/amiga/amiga-autoconf.c +++ b/platforms/amiga/amiga-autoconf.c @@ -180,9 +180,10 @@ void autoconfig_write_memory_z3_8(struct emulator_config *cfg, unsigned int addr if (done) { nib_latch = 0; - printf("Address of Z3 autoconf RAM assigned to $%.8x\n", ac_base[ac_z3_current_pic]); + printf("Address of Z3 autoconf RAM assigned to $%.8x [B]\n", ac_base[ac_z3_current_pic]); cfg->map_offset[index] = ac_base[ac_z3_current_pic]; cfg->map_high[index] = cfg->map_offset[index] + cfg->map_size[index]; + m68k_add_ram_range(cfg->map_offset[index], cfg->map_high[index], cfg->map_data[index]); ac_z3_current_pic++; if (ac_z3_current_pic == ac_z3_pic_count) { ac_z3_done = 1; @@ -201,7 +202,7 @@ void autoconfig_write_memory_z3_16(struct emulator_config *cfg, unsigned int add switch(address & 0xFF) { case AC_Z3_REG_WR_ADDR_HI: - // This is, as far as I know, the only regiter it should write a 16-bit value to. + // This is, as far as I know, the only register it should write a 16-bit value to. ac_base[ac_z3_current_pic] = (ac_base[ac_z3_current_pic] & 0x00000000) | (val << 16); done = 1; break; @@ -212,8 +213,10 @@ void autoconfig_write_memory_z3_16(struct emulator_config *cfg, unsigned int add } if (done) { - printf("Address of Z3 autoconf RAM assigned to $%.8x\n", ac_base[ac_z3_current_pic]); + printf("Address of Z3 autoconf RAM assigned to $%.8x [W]\n", ac_base[ac_z3_current_pic]); cfg->map_offset[index] = ac_base[ac_z3_current_pic]; + cfg->map_high[index] = cfg->map_offset[index] + cfg->map_size[index]; + m68k_add_ram_range(cfg->map_offset[index], cfg->map_high[index], cfg->map_data[index]); ac_z3_current_pic++; if (ac_z3_current_pic == ac_z3_pic_count) ac_z3_done = 1; @@ -300,6 +303,7 @@ void autoconfig_write_memory_8(struct emulator_config *cfg, unsigned int address printf("Address of Z2 autoconf RAM assigned to $%.8x\n", ac_base[ac_z2_current_pic]); cfg->map_offset[index] = ac_base[ac_z2_current_pic]; cfg->map_high[index] = cfg->map_offset[index] + cfg->map_size[index]; + m68k_add_ram_range(cfg->map_offset[index], cfg->map_high[index], cfg->map_data[index]); printf("Z2 PIC %d at $%.8lX-%.8lX, Size: %d MB\n", ac_z2_current_pic, cfg->map_offset[index], cfg->map_high[index], cfg->map_size[index] / SIZE_MEGA); ac_z2_current_pic++; if (ac_z2_current_pic == ac_z2_pic_count) { diff --git a/platforms/amiga/amiga-platform.c b/platforms/amiga/amiga-platform.c index c2361e3..71fd2b5 100644 --- a/platforms/amiga/amiga-platform.c +++ b/platforms/amiga/amiga-platform.c @@ -138,7 +138,6 @@ void adjust_ranges_amiga(struct emulator_config *cfg) { } int setup_platform_amiga(struct emulator_config *cfg) { - if (cfg) {} printf("Performing setup for Amiga platform.\n"); // Look for Z2 autoconf Fast RAM by id int index = get_named_mapped_item(cfg, z2_autoconf_id); @@ -205,6 +204,11 @@ int setup_platform_amiga(struct emulator_config *cfg) { } } + index = get_named_mapped_item(cfg, "cpu_slot_ram"); + if (index != -1) { + m68k_add_ram_range((uint32_t)cfg->map_offset[index], (uint32_t)cfg->map_high[index], cfg->map_data[index]); + } + adjust_ranges_amiga(cfg); return 0; From c86423760eca307a8d4a9c21219084233cccc83a Mon Sep 17 00:00:00 2001 From: beeanyew Date: Thu, 31 Dec 2020 14:30:28 +0100 Subject: [PATCH 4/8] Map some ROMs directly to Musashi as well? --- config_file/config_file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config_file/config_file.c b/config_file/config_file.c index 76d0bb6..2ce16e1 100644 --- a/config_file/config_file.c +++ b/config_file/config_file.c @@ -231,6 +231,8 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad } printf("[MAP %d] Added %s mapping for range %.8lX-%.8lX ID: %s\n", index, map_type_names[type], cfg->map_offset[index], cfg->map_offset[index] + cfg->map_size[index] - 1, cfg->map_id[index] ? cfg->map_id[index] : "None"); + if (cfg->map_size[index] == cfg->rom_size[index]) + m68k_add_rom_range(cfg->map_offset[index], cfg->map_high[index], cfg->map_data[index]); return; From 2e157e066598f2f7e30cba110ea345e7082c235a Mon Sep 17 00:00:00 2001 From: beeanyew Date: Thu, 31 Dec 2020 17:21:06 +0100 Subject: [PATCH 5/8] Fix the stupid --- m68kcpu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/m68kcpu.h b/m68kcpu.h index 0ba7aee..4262cd9 100644 --- a/m68kcpu.h +++ b/m68kcpu.h @@ -1224,7 +1224,7 @@ static inline void m68ki_write_16_fc(uint address, uint fc, uint value) for (int i = 0; i < write_ranges; i++) { if(address >= write_addr[i] && address < write_upper[i]) { - ((short *)(read_data[i] + (address - read_addr[i])))[0] = htobe16(value); + ((short *)(write_data[i] + (address - write_addr[i])))[0] = htobe16(value); return; } } @@ -1244,7 +1244,7 @@ static inline void m68ki_write_32_fc(uint address, uint fc, uint value) for (int i = 0; i < write_ranges; i++) { if(address >= write_addr[i] && address < write_upper[i]) { - ((int *)(read_data[i] + (address - read_addr[i])))[0] = htobe32(value); + ((int *)(write_data[i] + (address - write_addr[i])))[0] = htobe32(value); return; } } From aa872670359c1df1d5b99a39cb78ae697632775e Mon Sep 17 00:00:00 2001 From: beeanyew Date: Fri, 1 Jan 2021 01:24:04 +0100 Subject: [PATCH 6/8] Fix a bunch of stuff, add working RICOH RTC emulation. The MSM/OKI RTC emulation probably also works, but DiagROM seems to be reading it wrong. --- Gayle.c | 192 +++++++++++++++++++++++++++++- config_file/config_file.c | 3 +- emulator.c | 6 +- memory_mapped.c | 4 +- platforms/amiga/amiga-registers.h | 13 +- 5 files changed, 211 insertions(+), 7 deletions(-) diff --git a/Gayle.c b/Gayle.c index 8ed0448..f07bf2a 100644 --- a/Gayle.c +++ b/Gayle.c @@ -16,7 +16,11 @@ #include #include #include +#include +#include #include "ide.h" +#include "config_file/config_file.h" +#include "platforms/amiga/amiga-registers.h" //#define GSTATUS 0xda201c //#define GCLOW 0xda2010 @@ -45,7 +49,7 @@ #define GCS 0xDA8000 // Card Control #define GIRQ 0xDA9000 // IRQ #define GINT 0xDAA000 // Int enable -#define GCONF 0xDAB00 // Gayle Config +#define GCONF 0xDAB000 // Gayle Config /* DA8000 */ #define GAYLE_CS_IDE 0x80 /* IDE int status */ @@ -93,6 +97,8 @@ static uint8_t gayle_irq, gayle_int, gayle_cs, gayle_cs_mask, gayle_cfg; static struct ide_controller *ide0; int fd; +uint8_t rtc_type = RTC_TYPE_RICOH; + char *hdd_image_file[GAYLE_MAX_HARDFILES]; void set_hard_drive_image_file_amiga(uint8_t index, char *filename) { @@ -198,6 +204,15 @@ void writeGayleB(unsigned int address, unsigned int value) { return; } + if ((address & GAYLEMASK) == CLOCKBASE) { + if ((address & CLOCKMASK) >= 0x8000) { + printf("Byte write to CDTV SRAM?\n"); + return; + } + put_rtc_byte(address, value, rtc_type); + return; + } + printf("Write Byte to Gayle Space 0x%06x (0x%06x)\n", address, value); } @@ -207,13 +222,164 @@ void writeGayle(unsigned int address, unsigned int value) { return; } + if ((address & GAYLEMASK) == CLOCKBASE) { + if ((address & CLOCKMASK) >= 0x8000) { + printf("Word write to CDTV SRAM?\n"); + return; + } + printf("Word write to RTC.\n"); + put_rtc_byte(address, (value & 0xFF), rtc_type); + put_rtc_byte(address + 1, (value >> 8), rtc_type); + return; + } + printf("Write Word to Gayle Space 0x%06x (0x%06x)\n", address, value); } void writeGayleL(unsigned int address, unsigned int value) { + if ((address & GAYLEMASK) == CLOCKBASE) { + if ((address & CLOCKMASK) >= 0x8000) { + printf("Longword write to CDTV SRAM?\n"); + return; + } + printf("Longword write to RTC.\n"); + put_rtc_byte(address, (value & 0xFF), rtc_type); + put_rtc_byte(address + 1, ((value & 0x0000FF00) >> 8), rtc_type); + put_rtc_byte(address + 2, ((value & 0x00FF0000) >> 16), rtc_type); + put_rtc_byte(address + 3, (value >> 24), rtc_type); + return; + } + printf("Write Long to Gayle Space 0x%06x (0x%06x)\n", address, value); } +static unsigned char rtc_mystery_reg[3]; + +void put_rtc_byte(uint32_t address_, uint8_t value, uint8_t rtc_type) { + uint32_t address = address_ & 0x3F; + address >>= 2; + if (rtc_type == RTC_TYPE_MSM) { + switch(address) { + case 0x0D: + rtc_mystery_reg[address - 0x0D] = value & (0x01 | 0x08); + break; + case 0x0E: + case 0x0F: + rtc_mystery_reg[address - 0x0D] = value; + break; + default: + return; + } + } + else { + int rtc_bank = (rtc_mystery_reg[0] & 0x03); + if ((rtc_bank & 0x02) && address < 0x0D) { + // RTC memory access? + printf("Write to Ricoh RTC memory.\n"); + return; + } + else if ((rtc_bank & 0x01) && address < 0x0D) { + // RTC alarm access? + printf("Write to Ricoh RTC alarm.\n"); + return; + } + else if (address >= 0x0D) { + rtc_mystery_reg[address - 0x0D] = value; + return; + } + } +} + +uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type) { + uint32_t address = address_; + address >>= 2; + time_t t; + time(&t); + struct tm *rtc_time = localtime(&t); + + if (rtc_type == RTC_TYPE_RICOH) { + int rtc_bank = (rtc_mystery_reg[0] & 0x03); + if ((rtc_bank & 0x02) && address < 0x0D) { + // RTC memory access? + printf("Read from Ricoh RTC memory.\n"); + return 0; + } + else if ((rtc_bank & 0x01) && address < 0x0D) { + // RTC alarm access? + printf("Read from Ricoh RTC alarm.\n"); + return 0; + } + } + + switch (address) { + case 0x00: // Seconds low? + return rtc_time->tm_sec % 10; + case 0x01: // Seconds high? + return rtc_time->tm_sec / 10; + case 0x02: // Minutes low? + return rtc_time->tm_min % 10; + case 0x03: // Minutes high? + return rtc_time->tm_min / 10; + case 0x04: // Hours low? + return rtc_time->tm_hour % 10; + case 0x05: // Hours high? + if (rtc_type == RTC_TYPE_MSM) { + if (rtc_mystery_reg[2] & 4) { + return ((rtc_time->tm_hour / 10) | (rtc_time->tm_hour > 12) ? 0x04 : 0x00); + } + else + return rtc_time->tm_hour / 10; + } + else { + break; + } + case 0x06: // Day low? + if (rtc_type == RTC_TYPE_MSM) + return rtc_time->tm_mday % 10; + else + return rtc_time->tm_wday; + case 0x07: // Day high? + if (rtc_type == RTC_TYPE_MSM) + return rtc_time->tm_mday / 10; + else + return rtc_time->tm_mday % 10; + case 0x08: // Month low? + if (rtc_type == RTC_TYPE_MSM) + return (rtc_time->tm_mon + 1) % 10; + else + return rtc_time->tm_mday / 10; + case 0x09: // Month high? + if (rtc_type == RTC_TYPE_MSM) + return (rtc_time->tm_mon + 1) / 10; + else + return (rtc_time->tm_mon + 1) % 10; + case 0x0A: // Year low? + if (rtc_type == RTC_TYPE_MSM) + return rtc_time->tm_year % 10; + else + return (rtc_time->tm_mon + 1) / 10; + case 0x0B: // Year high? + if (rtc_type == RTC_TYPE_MSM) + return rtc_time->tm_year / 10; + else + return rtc_time->tm_year % 10; + case 0x0C: // Day of week? + if (rtc_type == RTC_TYPE_MSM) + return rtc_time->tm_wday; + else + return rtc_time->tm_year / 10; + case 0x0D: // Mystery register D-F? + return rtc_mystery_reg[address - 0x0D]; + case 0x0E: + case 0x0F: + return 0; + default: + break; + } + + return 0x00; +} + uint8_t readGayleB(unsigned int address) { if (address == GERROR) { return ide_read8(ide0, ide_error_r); @@ -246,6 +412,14 @@ uint8_t readGayleB(unsigned int address) { return ide_read8(ide0, ide_altst_r); } + if ((address & GAYLEMASK) == CLOCKBASE) { + if ((address & CLOCKMASK) >= 0x8000) { + printf("Byte read from CDTV SRAM?\n"); + return 0; + } + return get_rtc_byte((address & 0x3F), rtc_type); + } + if (address == GIDENT) { uint8_t val; // printf("Read Byte from Gayle Ident 0x%06x (0x%06x)\n",address,counter); @@ -304,11 +478,27 @@ uint16_t readGayle(unsigned int address) { return value; } + if ((address & GAYLEMASK) == CLOCKBASE) { + if ((address & CLOCKMASK) >= 0x8000) { + printf("Word read from CDTV SRAM?\n"); + return 0; + } + return ((get_rtc_byte((address & 0x3F), rtc_type) << 8) | (get_rtc_byte(((address + 1) & 0x3F), rtc_type))); + } + printf("Read Word From Gayle Space 0x%06x\n", address); return 0x8000; } uint32_t readGayleL(unsigned int address) { + if ((address & GAYLEMASK) == CLOCKBASE) { + if ((address & CLOCKMASK) >= 0x8000) { + printf("Longword read from CDTV SRAM?\n"); + return 0; + } + return ((get_rtc_byte((address & 0x3F), rtc_type) << 24) | (get_rtc_byte(((address + 1) & 0x3F), rtc_type) << 16) | (get_rtc_byte(((address + 2) & 0x3F), rtc_type) << 8) | (get_rtc_byte(((address + 3) & 0x3F), rtc_type))); + } + printf("Read Long From Gayle Space 0x%06x\n", address); return 0x8000; } diff --git a/config_file/config_file.c b/config_file/config_file.c index 2ce16e1..b0b9a48 100644 --- a/config_file/config_file.c +++ b/config_file/config_file.c @@ -212,6 +212,7 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad file_size = (int)ftell(in); if (size == 0) { cfg->map_size[index] = file_size; + cfg->map_high[index] = addr + cfg->map_size[index]; } fseek(in, 0, SEEK_SET); cfg->map_data[index] = (unsigned char *)calloc(1, cfg->map_size[index]); @@ -230,7 +231,7 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad break; } - printf("[MAP %d] Added %s mapping for range %.8lX-%.8lX ID: %s\n", index, map_type_names[type], cfg->map_offset[index], cfg->map_offset[index] + cfg->map_size[index] - 1, cfg->map_id[index] ? cfg->map_id[index] : "None"); + printf("[MAP %d] Added %s mapping for range %.8lX-%.8lX ID: %s\n", index, map_type_names[type], cfg->map_offset[index], cfg->map_high[index] - 1, cfg->map_id[index] ? cfg->map_id[index] : "None"); if (cfg->map_size[index] == cfg->rom_size[index]) m68k_add_rom_range(cfg->map_offset[index], cfg->map_high[index], cfg->map_data[index]); diff --git a/emulator.c b/emulator.c index a019512..d2d3eab 100644 --- a/emulator.c +++ b/emulator.c @@ -566,8 +566,10 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) { PLATFORM_CHECK_WRITE(OP_TYPE_BYTE); if (address == 0xbfe001) { - ovl = (value & (1 << 0)); - printf("OVL:%x\n", ovl); + if (ovl != (value & (1 << 0)) { + ovl = (value & (1 << 0)); + printf("OVL:%x\n", ovl); + } } // if (address < 0xffffff) { diff --git a/memory_mapped.c b/memory_mapped.c index bf42406..1e5522c 100644 --- a/memory_mapped.c +++ b/memory_mapped.c @@ -24,12 +24,12 @@ inline int handle_mapped_read(struct emulator_config *cfg, unsigned int addr, un if (cfg->map_type[i] == MAPTYPE_NONE) continue; else if (ovl && cfg->map_type[i] == MAPTYPE_ROM) { - if (cfg->map_mirror[i] != -1 && CHKRANGE_ABS(addr, cfg->map_mirror[i], cfg->map_high[i])) { + if (cfg->map_mirror[i] != -1 && CHKRANGE(addr, cfg->map_mirror[i], cfg->map_size[i])) { read_addr = cfg->map_data[i] + ((addr - cfg->map_mirror[i]) % cfg->rom_size[i]); goto read_value; } } - else if (CHKRANGE_ABS(addr, cfg->map_offset[i], cfg->map_high[i])) { + if (CHKRANGE_ABS(addr, cfg->map_offset[i], cfg->map_high[i])) { switch(cfg->map_type[i]) { case MAPTYPE_ROM: read_addr = cfg->map_data[i] + ((addr - cfg->map_offset[i]) % cfg->rom_size[i]); diff --git a/platforms/amiga/amiga-registers.h b/platforms/amiga/amiga-registers.h index 53a7b90..3e19e65 100644 --- a/platforms/amiga/amiga-registers.h +++ b/platforms/amiga/amiga-registers.h @@ -3,8 +3,19 @@ void set_hard_drive_image_file_amiga(uint8_t index, char *filename); int custom_read_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type); int custom_write_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int val, unsigned char type); +void put_rtc_byte(uint32_t address_, uint8_t value, uint8_t rtc_type); +uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type); + #define GAYLEBASE 0xD80000 -#define GAYLESIZE 0x70000 +#define GAYLESIZE 0x070000 +#define GAYLEMASK 0xDF0000 #define CLOCKBASE 0xDC0000 #define CLOCKSIZE 0x010000 +#define CLOCKMASK 0x00FFFF + +enum rtc_types { + RTC_TYPE_MSM, + RTC_TYPE_RICOH, + RTC_TYPE_NONE, +}; \ No newline at end of file From 038912b981e7c641e9b0c12def47b20bc07ed089 Mon Sep 17 00:00:00 2001 From: beeanyew Date: Fri, 1 Jan 2021 11:34:49 +0100 Subject: [PATCH 7/8] Clean up RTC and move it out of Gayle.c --- Gayle.c | 134 +---------------------- Makefile | 3 +- platforms/amiga/amiga-registers.h | 9 -- platforms/shared/rtc.c | 172 ++++++++++++++++++++++++++++++ platforms/shared/rtc.h | 8 ++ 5 files changed, 186 insertions(+), 140 deletions(-) create mode 100644 platforms/shared/rtc.c create mode 100644 platforms/shared/rtc.h diff --git a/Gayle.c b/Gayle.c index f07bf2a..9b21f90 100644 --- a/Gayle.c +++ b/Gayle.c @@ -21,6 +21,7 @@ #include "ide.h" #include "config_file/config_file.h" #include "platforms/amiga/amiga-registers.h" +#include "platforms/shared/rtc.h" //#define GSTATUS 0xda201c //#define GCLOW 0xda2010 @@ -253,133 +254,6 @@ void writeGayleL(unsigned int address, unsigned int value) { printf("Write Long to Gayle Space 0x%06x (0x%06x)\n", address, value); } -static unsigned char rtc_mystery_reg[3]; - -void put_rtc_byte(uint32_t address_, uint8_t value, uint8_t rtc_type) { - uint32_t address = address_ & 0x3F; - address >>= 2; - if (rtc_type == RTC_TYPE_MSM) { - switch(address) { - case 0x0D: - rtc_mystery_reg[address - 0x0D] = value & (0x01 | 0x08); - break; - case 0x0E: - case 0x0F: - rtc_mystery_reg[address - 0x0D] = value; - break; - default: - return; - } - } - else { - int rtc_bank = (rtc_mystery_reg[0] & 0x03); - if ((rtc_bank & 0x02) && address < 0x0D) { - // RTC memory access? - printf("Write to Ricoh RTC memory.\n"); - return; - } - else if ((rtc_bank & 0x01) && address < 0x0D) { - // RTC alarm access? - printf("Write to Ricoh RTC alarm.\n"); - return; - } - else if (address >= 0x0D) { - rtc_mystery_reg[address - 0x0D] = value; - return; - } - } -} - -uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type) { - uint32_t address = address_; - address >>= 2; - time_t t; - time(&t); - struct tm *rtc_time = localtime(&t); - - if (rtc_type == RTC_TYPE_RICOH) { - int rtc_bank = (rtc_mystery_reg[0] & 0x03); - if ((rtc_bank & 0x02) && address < 0x0D) { - // RTC memory access? - printf("Read from Ricoh RTC memory.\n"); - return 0; - } - else if ((rtc_bank & 0x01) && address < 0x0D) { - // RTC alarm access? - printf("Read from Ricoh RTC alarm.\n"); - return 0; - } - } - - switch (address) { - case 0x00: // Seconds low? - return rtc_time->tm_sec % 10; - case 0x01: // Seconds high? - return rtc_time->tm_sec / 10; - case 0x02: // Minutes low? - return rtc_time->tm_min % 10; - case 0x03: // Minutes high? - return rtc_time->tm_min / 10; - case 0x04: // Hours low? - return rtc_time->tm_hour % 10; - case 0x05: // Hours high? - if (rtc_type == RTC_TYPE_MSM) { - if (rtc_mystery_reg[2] & 4) { - return ((rtc_time->tm_hour / 10) | (rtc_time->tm_hour > 12) ? 0x04 : 0x00); - } - else - return rtc_time->tm_hour / 10; - } - else { - break; - } - case 0x06: // Day low? - if (rtc_type == RTC_TYPE_MSM) - return rtc_time->tm_mday % 10; - else - return rtc_time->tm_wday; - case 0x07: // Day high? - if (rtc_type == RTC_TYPE_MSM) - return rtc_time->tm_mday / 10; - else - return rtc_time->tm_mday % 10; - case 0x08: // Month low? - if (rtc_type == RTC_TYPE_MSM) - return (rtc_time->tm_mon + 1) % 10; - else - return rtc_time->tm_mday / 10; - case 0x09: // Month high? - if (rtc_type == RTC_TYPE_MSM) - return (rtc_time->tm_mon + 1) / 10; - else - return (rtc_time->tm_mon + 1) % 10; - case 0x0A: // Year low? - if (rtc_type == RTC_TYPE_MSM) - return rtc_time->tm_year % 10; - else - return (rtc_time->tm_mon + 1) / 10; - case 0x0B: // Year high? - if (rtc_type == RTC_TYPE_MSM) - return rtc_time->tm_year / 10; - else - return rtc_time->tm_year % 10; - case 0x0C: // Day of week? - if (rtc_type == RTC_TYPE_MSM) - return rtc_time->tm_wday; - else - return rtc_time->tm_year / 10; - case 0x0D: // Mystery register D-F? - return rtc_mystery_reg[address - 0x0D]; - case 0x0E: - case 0x0F: - return 0; - default: - break; - } - - return 0x00; -} - uint8_t readGayleB(unsigned int address) { if (address == GERROR) { return ide_read8(ide0, ide_error_r); @@ -417,7 +291,7 @@ uint8_t readGayleB(unsigned int address) { printf("Byte read from CDTV SRAM?\n"); return 0; } - return get_rtc_byte((address & 0x3F), rtc_type); + return get_rtc_byte(address, rtc_type); } if (address == GIDENT) { @@ -483,7 +357,7 @@ uint16_t readGayle(unsigned int address) { printf("Word read from CDTV SRAM?\n"); return 0; } - return ((get_rtc_byte((address & 0x3F), rtc_type) << 8) | (get_rtc_byte(((address + 1) & 0x3F), rtc_type))); + return ((get_rtc_byte(address, rtc_type) << 8) | (get_rtc_byte(address + 1, rtc_type))); } printf("Read Word From Gayle Space 0x%06x\n", address); @@ -496,7 +370,7 @@ uint32_t readGayleL(unsigned int address) { printf("Longword read from CDTV SRAM?\n"); return 0; } - return ((get_rtc_byte((address & 0x3F), rtc_type) << 24) | (get_rtc_byte(((address + 1) & 0x3F), rtc_type) << 16) | (get_rtc_byte(((address + 2) & 0x3F), rtc_type) << 8) | (get_rtc_byte(((address + 3) & 0x3F), rtc_type))); + return ((get_rtc_byte(address, rtc_type) << 24) | (get_rtc_byte(address + 1, rtc_type) << 16) | (get_rtc_byte(address + 2, rtc_type) << 8) | (get_rtc_byte(address + 3, rtc_type))); } printf("Read Long From Gayle Space 0x%06x\n", address); diff --git a/Makefile b/Makefile index 6e7f301..c32a147 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,8 @@ MAINFILES = emulator.c \ platforms/amiga/amiga-platform.c \ platforms/amiga/amiga-registers.c \ platforms/dummy/dummy-platform.c \ - platforms/dummy/dummy-registers.c + platforms/dummy/dummy-registers.c \ + platforms/shared/rtc.c MUSASHIFILES = m68kcpu.c softfloat/softfloat.c MUSASHIGENCFILES = m68kops.c diff --git a/platforms/amiga/amiga-registers.h b/platforms/amiga/amiga-registers.h index 3e19e65..fb6e285 100644 --- a/platforms/amiga/amiga-registers.h +++ b/platforms/amiga/amiga-registers.h @@ -3,9 +3,6 @@ void set_hard_drive_image_file_amiga(uint8_t index, char *filename); int custom_read_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type); int custom_write_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int val, unsigned char type); -void put_rtc_byte(uint32_t address_, uint8_t value, uint8_t rtc_type); -uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type); - #define GAYLEBASE 0xD80000 #define GAYLESIZE 0x070000 #define GAYLEMASK 0xDF0000 @@ -13,9 +10,3 @@ uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type); #define CLOCKBASE 0xDC0000 #define CLOCKSIZE 0x010000 #define CLOCKMASK 0x00FFFF - -enum rtc_types { - RTC_TYPE_MSM, - RTC_TYPE_RICOH, - RTC_TYPE_NONE, -}; \ No newline at end of file diff --git a/platforms/shared/rtc.c b/platforms/shared/rtc.c new file mode 100644 index 0000000..8b3772c --- /dev/null +++ b/platforms/shared/rtc.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include "rtc.h" + +static unsigned char rtc_mystery_reg[3]; +unsigned char ricoh_memory[0x0F]; +unsigned char ricoh_alarm[0x0F]; + +void put_rtc_byte(uint32_t address_, uint8_t value, uint8_t rtc_type) { + uint32_t address = address_ & 0x3F; + address >>= 2; + if (rtc_type == RTC_TYPE_MSM) { + switch(address) { + case 0x0D: + rtc_mystery_reg[address - 0x0D] = value & (0x01 | 0x08); + break; + case 0x0E: + case 0x0F: + rtc_mystery_reg[address - 0x0D] = value; + break; + default: + return; + } + } + else { + int rtc_bank = (rtc_mystery_reg[0] & 0x03); + if ((rtc_bank & 0x02) && address < 0x0D) { + if (rtc_bank & 0x01) { + // Low nibble of value -> high nibble in RTC memory + ricoh_memory[address] &= 0x0F; + ricoh_memory[address] |= ((value & 0x0F) << 4); + } + else { + // Low nibble of value -> low nibble in RTC memory + ricoh_memory[address] &= 0xF0; + ricoh_memory[address] |= (value & 0x0F); + } + return; + } + else if ((rtc_bank & 0x01) && address < 0x0D) { + // RTC alarm stuff, no idea what this is supposed to be for. + switch(address) { + case 0x00: + case 0x01: + case 0x09: + case 0x0C: + ricoh_alarm[address] = 0; + break; + case 0x03: + case 0x06: + ricoh_alarm[address] = (value & (0x08 & 0xFF)); + break; + case 0x05: + case 0x08: + case 0x0B: + ricoh_alarm[address] = (value & (0x0C & 0xFF)); + break; + case 0x0A: + ricoh_alarm[address] = (value & (0x0E & 0xFF)); + break; + default: + ricoh_alarm[address] = value; + break; + } + return; + } + else if (address >= 0x0D) { + rtc_mystery_reg[address - 0x0D] = value; + return; + } + } +} + +uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type) { + uint32_t address = address_ & 0x3F; + address >>= 2; + time_t t; + time(&t); + struct tm *rtc_time = localtime(&t); + + if (rtc_type == RTC_TYPE_RICOH) { + int rtc_bank = (rtc_mystery_reg[0] & 0x03); + if ((rtc_bank & 0x02) && address < 0x0D) { + // Get low/high nibble from memory (bank 2/3) + return ((ricoh_memory[address] >> (rtc_bank & 0x01) ? 4 : 0) & 0x0F); + } + else if ((rtc_bank & 0x01) && address < 0x0D) { + // Get byte from alarm + return ricoh_alarm[address]; + } + } + + switch (address) { + case 0x00: // Seconds low? + return rtc_time->tm_sec % 10; + case 0x01: // Seconds high? + return rtc_time->tm_sec / 10; + case 0x02: // Minutes low? + return rtc_time->tm_min % 10; + case 0x03: // Minutes high? + return rtc_time->tm_min / 10; + case 0x04: // Hours low? + return rtc_time->tm_hour % 10; + case 0x05: // Hours high? + if (rtc_type == RTC_TYPE_MSM) { + if (rtc_mystery_reg[2] & 4) { + return ((rtc_time->tm_hour / 10) | (rtc_time->tm_hour >= 12) ? 0x04 : 0x00); + } + else + return rtc_time->tm_hour / 10; + } + else { + if (ricoh_alarm[10] & 0x01) { + return rtc_time->tm_hour / 10; + } + else { + return ((rtc_time->tm_hour / 10) | (rtc_time->tm_hour >= 12) ? 0x02 : 0x00); + } + break; + } + case 0x06: // Day low? + if (rtc_type == RTC_TYPE_MSM) + return rtc_time->tm_mday % 10; + else + return rtc_time->tm_wday; + case 0x07: // Day high? + if (rtc_type == RTC_TYPE_MSM) + return rtc_time->tm_mday / 10; + else + return rtc_time->tm_mday % 10; + case 0x08: // Month low? + if (rtc_type == RTC_TYPE_MSM) + return (rtc_time->tm_mon + 1) % 10; + else + return rtc_time->tm_mday / 10; + case 0x09: // Month high? + if (rtc_type == RTC_TYPE_MSM) + return (rtc_time->tm_mon + 1) / 10; + else + return (rtc_time->tm_mon + 1) % 10; + case 0x0A: // Year low? + if (rtc_type == RTC_TYPE_MSM) + return rtc_time->tm_year % 10; + else + return (rtc_time->tm_mon + 1) / 10; + case 0x0B: // Year high? + if (rtc_type == RTC_TYPE_MSM) + return rtc_time->tm_year / 10; + else + return rtc_time->tm_year % 10; + case 0x0C: // Day of week? + if (rtc_type == RTC_TYPE_MSM) + return rtc_time->tm_wday; + else + return rtc_time->tm_year / 10; + case 0x0D: // Mystery register D-F? + case 0x0E: + case 0x0F: + if (rtc_type == RTC_TYPE_MSM) { + return rtc_mystery_reg[address - 0x0D]; + } + else { + if (address == 0x0D) return rtc_mystery_reg[address - 0x0D]; + return 0; + } + default: + break; + } + + return 0x00; +} diff --git a/platforms/shared/rtc.h b/platforms/shared/rtc.h new file mode 100644 index 0000000..107ae93 --- /dev/null +++ b/platforms/shared/rtc.h @@ -0,0 +1,8 @@ +void put_rtc_byte(uint32_t address_, uint8_t value, uint8_t rtc_type); +uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type); + +enum rtc_types { + RTC_TYPE_MSM, + RTC_TYPE_RICOH, + RTC_TYPE_NONE, +}; \ No newline at end of file From 0eb7deffb62e5153425c4931ec9d4c8c068c7feb Mon Sep 17 00:00:00 2001 From: beeanyew Date: Fri, 1 Jan 2021 11:59:35 +0100 Subject: [PATCH 8/8] Fix silly RTC and emulator.c mistakes --- emulator.c | 2 +- platforms/shared/rtc.c | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/emulator.c b/emulator.c index d2d3eab..a898541 100644 --- a/emulator.c +++ b/emulator.c @@ -566,7 +566,7 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) { PLATFORM_CHECK_WRITE(OP_TYPE_BYTE); if (address == 0xbfe001) { - if (ovl != (value & (1 << 0)) { + if (ovl != (value & (1 << 0))) { ovl = (value & (1 << 0)); printf("OVL:%x\n", ovl); } diff --git a/platforms/shared/rtc.c b/platforms/shared/rtc.c index 8b3772c..dd5edad 100644 --- a/platforms/shared/rtc.c +++ b/platforms/shared/rtc.c @@ -49,20 +49,21 @@ void put_rtc_byte(uint32_t address_, uint8_t value, uint8_t rtc_type) { break; case 0x03: case 0x06: - ricoh_alarm[address] = (value & (0x08 & 0xFF)); + ricoh_alarm[address] &= (value & (0x08 ^ 0xFF)); break; case 0x05: case 0x08: case 0x0B: - ricoh_alarm[address] = (value & (0x0C & 0xFF)); + ricoh_alarm[address] = (value & (0x0C ^ 0xFF)); break; case 0x0A: - ricoh_alarm[address] = (value & (0x0E & 0xFF)); + ricoh_alarm[address] = (value & (0x0E ^ 0xFF)); break; default: ricoh_alarm[address] = value; break; } + //printf("Write to Ricoh alarm @%.2X: %.2X -> %.2X\n", address, value, ricoh_alarm[address]); return; } else if (address >= 0x0D) { @@ -105,7 +106,7 @@ uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type) { case 0x05: // Hours high? if (rtc_type == RTC_TYPE_MSM) { if (rtc_mystery_reg[2] & 4) { - return ((rtc_time->tm_hour / 10) | (rtc_time->tm_hour >= 12) ? 0x04 : 0x00); + return (((rtc_time->tm_hour % 12) / 10) | (rtc_time->tm_hour >= 12) ? 0x04 : 0x00); } else return rtc_time->tm_hour / 10; @@ -115,7 +116,7 @@ uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type) { return rtc_time->tm_hour / 10; } else { - return ((rtc_time->tm_hour / 10) | (rtc_time->tm_hour >= 12) ? 0x02 : 0x00); + return (((rtc_time->tm_hour % 12) / 10) | (rtc_time->tm_hour >= 12) ? 0x02 : 0x00); } break; }