diff --git a/targets/mega65/Makefile b/targets/mega65/Makefile index 67d8e6d4..e8b2087d 100644 --- a/targets/mega65/Makefile +++ b/targets/mega65/Makefile @@ -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-2022 LGB (Gábor Lénárt) +## Copyright (C)2016-2023 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 @@ -20,7 +20,7 @@ TARGET = mega65 PRG_TARGET = xmega65 EMU_DESCRIPTION = MEGA65 -SRCS_TARGET_xmega65 = configdb.c mega65.c sdcard.c uart_monitor.c hypervisor.c m65_snapshot.c memory_mapper.c io_mapper.c vic4.c vic4_palette.c ethernet65.c input_devices.c memcontent.c ui.c fat32.c sdcontent.c audio65.c inject.c dma65.c rom.c hdos.c matrix_mode.c +SRCS_TARGET_xmega65 = configdb.c mega65.c sdcard.c uart_monitor.c hypervisor.c m65_snapshot.c memory_mapper.c io_mapper.c vic4.c vic4_palette.c ethernet65.c input_devices.c memcontent.c ui.c fat32.c sdcontent.c audio65.c inject.c dma65.c rom.c hdos.c matrix_mode.c cart.c SRCS_COMMON_xmega65 = emutools.c cpu65.c cia6526.c emutools_hid.c sid.c f011_core.c c64_kbd_mapping.c emutools_config.c emutools_snapshot.c emutools_files.c emutools_umon.c emutools_socketapi.c ethertap.c d81access.c emutools_gui.c basic_text.c opl3.c lodepng.c CFLAGS_TARGET_xmega65 = $(SDL2_CFLAGS) $(MATH_CFLAGS) $(SOCKET_CFLAGS) $(XEMUGUI_CFLAGS) LDFLAGS_TARGET_xmega65 = $(SDL2_LIBS) $(MATH_LIBS) $(SOCKET_LIBS) $(XEMUGUI_LIBS) diff --git a/targets/mega65/cart.c b/targets/mega65/cart.c new file mode 100644 index 00000000..2ff074e5 --- /dev/null +++ b/targets/mega65/cart.c @@ -0,0 +1,84 @@ +/* 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) + +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 +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +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 "cart.h" +#include "xemu/emutools_files.h" + +static Uint8 cart_mem[0x10000]; +static int loaded = 0; + + +void cart_init ( void ) +{ + memset(cart_mem, 0xFF, sizeof cart_mem); +} + + +Uint8 cart_read_byte ( unsigned int addr ) +{ + Uint8 data = 0xFF; + if (addr < sizeof(cart_mem)) + data = cart_mem[addr]; + DEBUGPRINT("CART: reading byte ($%02X) at $%X" NL, data, addr + 0x4000000); + return data; +} + + +void cart_write_byte ( unsigned int addr, Uint8 data ) +{ + DEBUGPRINT("CART: writing byte ($%02X) at $%X" NL, data, addr + 0x4000000); +} + + +int cart_load_bin ( const char *fn, const unsigned int addr, const char *cry ) +{ + if (!fn || !*fn) + return 0; + loaded = 0; + if (addr >= sizeof(cart_mem)) { + if (cry) + ERROR_WINDOW("%s\nOutside of 64K range\n%s", cry, fn); + return -1; + } + const int ret = xemu_load_file(fn, cart_mem + addr, 1, sizeof(cart_mem) - addr, cry); + if (ret <= 0) + return -1; + DEBUGPRINT("CART: %d byte(s) loaded at offset $%04X from file %s" NL, ret, addr, fn); + loaded = 1; + return 0; +} + + +int cart_detect_id ( void ) +{ + static const Uint8 cart_id[] = {'M', '6', '5'}; + return memcmp(cart_mem + 0x8007, cart_id, sizeof cart_id); +} + + +int cart_is_loaded ( void ) +{ + return loaded; +} + + +void cart_copy_from ( const Uint16 cart_addr, Uint8 *target, const Uint16 size ) +{ + memcpy(target, cart_mem + cart_addr, size); +} diff --git a/targets/mega65/cart.h b/targets/mega65/cart.h new file mode 100644 index 00000000..140b74e4 --- /dev/null +++ b/targets/mega65/cart.h @@ -0,0 +1,30 @@ +/* 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) + +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 +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +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 */ + +#ifndef XEMU_MEGA65_CART_H_INCLUDED +#define XEMU_MEGA65_CART_H_INCLUDED + +extern void cart_init ( void ); +extern Uint8 cart_read_byte ( unsigned int addr ); +extern void cart_write_byte ( unsigned int addr, Uint8 data ); +extern int cart_load_bin ( const char *fn, const unsigned int addr, const char *cry ); +extern void cart_copy_from ( const Uint16 cart_addr, Uint8 *target, const Uint16 size ); +extern int cart_detect_id ( void ); +extern int cart_is_loaded ( void ); + +#endif diff --git a/targets/mega65/configdb.c b/targets/mega65/configdb.c index 40a7467a..d9c82af7 100644 --- a/targets/mega65/configdb.c +++ b/targets/mega65/configdb.c @@ -75,6 +75,7 @@ static const struct xemutools_configdef_str_st str_options[] = { #endif { "gui", NULL, "Select GUI type for usage. Specify some insane str to get a list", &configdb.selectedgui }, { "importbas", NULL, "Import and RUN BASIC65 program from TEXT file", &configdb.importbas }, + { "cartbin8000",NULL, "Load binary cartridge image from $8000", &configdb.cartbin8000 }, { NULL } }; @@ -151,6 +152,7 @@ static const void *do_not_save_opts[] = { &emu_is_sleepless, &emu_is_headless, &configdb.testing, &configdb.dumpmem, &configdb.dumpscreen, &configdb.screenshot_and_exit, &configdb.testing, &configdb.hyperdebug, &configdb.hyperdebugfreezer, &configdb.usestubrom, &configdb.useinitrom, &configdb.useutilmenu, + &configdb.cartbin8000, NULL }; diff --git a/targets/mega65/configdb.h b/targets/mega65/configdb.h index 76c16a91..34c1dc4f 100644 --- a/targets/mega65/configdb.h +++ b/targets/mega65/configdb.h @@ -97,6 +97,7 @@ struct configdb_st { // $60/$61/$62 = qmtecha100t/qmtecha200t/qmtecha325t, $21/$22=megaphoner1/megaphoner4 int mega65_model; int colour_effect; + char *cartbin8000; int hicked; int prgmode; int rtc_hour_offset; diff --git a/targets/mega65/mega65.c b/targets/mega65/mega65.c index e0a5dd22..76fbcb80 100644 --- a/targets/mega65/mega65.c +++ b/targets/mega65/mega65.c @@ -42,6 +42,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "configdb.h" #include "xemu/emutools_socketapi.h" #include "rom.h" +#include "cart.h" // "Typical" size in default settings (video standard is PAL, default border settings). // See also vic4.h @@ -355,6 +356,7 @@ static void mega65_init ( void ) } while (0); // *** Initializes memory subsystem of MEGA65 emulation itself memory_init(); + cart_load_bin(configdb.cartbin8000, 0x8000, "Cannot load binary cartridge image from $8000"); // Load contents of NVRAM. // Also store as "nvram_original" so we can sense on shutdown of the emu, if we need to up-date the on-disk version // If we fail to load it (does not exist?) it will be written out anyway on exit. diff --git a/targets/mega65/memory_mapper.c b/targets/mega65/memory_mapper.c index 9dc18e19..f70f0ec0 100644 --- a/targets/mega65/memory_mapper.c +++ b/targets/mega65/memory_mapper.c @@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ethernet65.h" #include "audio65.h" #include "sdcard.h" +#include "cart.h" #include #define ALLOW_CPU_CUSTOM_FUNCTIONS_INCLUDE @@ -338,6 +339,14 @@ DEFINE_WRITER(i2c_io_writer) { break; } } +// "Slow device" ~ cardridge space +DEFINE_READER(slowdev_reader) { + return cart_read_byte(GET_READER_OFFSET()); +} +DEFINE_WRITER(slowdev_writer) { + cart_write_byte(GET_WRITER_OFFSET(), data); +} + // Not implemented yet, just here, since freezer accesses this memory area, and without **some** dummy // support, it would cause "unhandled memory access" warning in Xemu. DEFINE_READER(mem1541_reader) { @@ -372,7 +381,7 @@ static const struct m65_memory_map_st m65_memory_map[] = { { 0xFFD7000, 0xFFD7FFF, i2c_io_reader, i2c_io_writer }, // I2C devices { 0x8000000, 0x8000000 + SLOW_RAM_SIZE - 1, slow_ram_reader, slow_ram_writer }, // "slow RAM" also called "hyper RAM" (not to be confused with hypervisor RAM!) { 0x8000000 + SLOW_RAM_SIZE, 0xFDFFFFF, dummy_reader, dummy_writer }, // ununsed big part of the "slow RAM" or so ... - { 0x4000000, 0x7FFFFFF, dummy_reader, dummy_writer }, // slow RAM memory area, not exactly known what it's for, let's define as "dummy" + { 0x4000000, 0x7FFFFFF, slowdev_reader, slowdev_writer }, // slow RAM memory area ~ cartridge { 0xFE00000, 0xFE000FF, opl3_reader, opl3_writer }, { 0x60000, 0xFFFFF, dummy_reader, dummy_writer }, // upper "unused" area of C65 (!) memory map. It seems C65 ROMs want it (Expansion RAM?) so we define as unused. { 0xFFDB000, 0xFFDFFFF, mem1541_reader, mem1541_writer }, // 1541's 16K ROM + 4K RAM, not so much used currently, but freezer seems to access it, for example ... @@ -498,6 +507,7 @@ void memory_init ( void ) memset(D6XX_registers, 0, sizeof D6XX_registers); memset(D7XX, 0xFF, sizeof D7XX); memset(i2c_regs, 0, sizeof i2c_regs); + cart_init(); rom_protect = 0; in_hypervisor = 0; for (a = 0; a < MEM_SLOTS; a++) { diff --git a/targets/mega65/ui.c b/targets/mega65/ui.c index 6d21d757..6376d721 100644 --- a/targets/mega65/ui.c +++ b/targets/mega65/ui.c @@ -40,6 +40,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "hypervisor.h" #include "xemu/cpu65.h" #include "xemu/emutools_config.h" +#include "cart.h" // Used by UI CBs to maintain configDB persistence @@ -653,10 +654,46 @@ static void ui_cb_colour_effect ( const struct menu_st *m, int *query ) vic4_set_emulation_colour_effect(VOIDPTR_TO_INT(m->user_data)); } +static void ui_cb_load_bin_cart ( const struct menu_st *m, int *query ) +{ + char fnbuf[PATH_MAX + 1]; + static char dir[PATH_MAX + 1] = ""; + _check_file_selection_default_override(dir); + if (!xemugui_file_selector( + XEMUGUI_FSEL_OPEN | XEMUGUI_FSEL_FLAG_STORE_DIR, + "Select binary cartridge", + dir, + fnbuf, + sizeof fnbuf + )) { + if (!cart_load_bin(fnbuf, VOIDPTR_TO_INT(m->user_data), "Cannot load binary cartridge")) + xemucfg_set_str(&configdb.cartbin8000, fnbuf); + } else + DEBUGPRINT("UI: file selection for PRG injection was cancelled." NL); +} + +static void ui_start_cartridge ( void ) +{ + if (!cart_is_loaded()) { + ERROR_WINDOW("No cartridge is loaded yet."); + return; + } + if (cart_detect_id()) { + INFO_WINDOW("Cartridge signature M65 not detected. Start with your own risk."); + } + cart_copy_from(0x8000, main_ram + 0x8000, 0x2000); + INFO_WINDOW("Copied. Type BANK0:SYS$8000 to start"); +} + /**** MENU SYSTEM ****/ +static const struct menu_st menu_cartridge[] = { + { "Load BIN cartridge to $8000",XEMUGUI_MENUID_CALLABLE, ui_cb_load_bin_cart, (void*)0x8000 }, + { "Start cartridge", XEMUGUI_MENUID_CALLABLE, xemugui_cb_call_user_data, ui_start_cartridge }, + { NULL } +}; static const struct menu_st menu_colour_effects[] = { { "Normal colours", XEMUGUI_MENUID_CALLABLE | XEMUGUI_MENUFLAG_QUERYBACK, ui_cb_colour_effect, (void*)0 }, { "Grayscale", XEMUGUI_MENUID_CALLABLE | XEMUGUI_MENUFLAG_QUERYBACK, ui_cb_colour_effect, (void*)1 }, @@ -857,6 +894,7 @@ static const struct menu_st menu_disks[] = { { "Drive-8", XEMUGUI_MENUID_SUBMENU, NULL, menu_drv8 }, { "Drive-9", XEMUGUI_MENUID_SUBMENU, NULL, menu_drv9 }, { "SD-card", XEMUGUI_MENUID_SUBMENU, NULL, menu_sdcard }, + { "Cartridge", XEMUGUI_MENUID_SUBMENU, NULL, menu_cartridge }, { NULL } }; static const struct menu_st menu_audio_stereo[] = { @@ -942,7 +980,7 @@ static const struct menu_st menu_main[] = { { "Display", XEMUGUI_MENUID_SUBMENU, NULL, menu_display }, { "Input devices", XEMUGUI_MENUID_SUBMENU, NULL, menu_inputdevices }, { "Audio", XEMUGUI_MENUID_SUBMENU, NULL, menu_audio }, - { "Disks", XEMUGUI_MENUID_SUBMENU, NULL, menu_disks }, + { "Disks / Cart", XEMUGUI_MENUID_SUBMENU, NULL, menu_disks }, { "Reset / ROM switching", XEMUGUI_MENUID_SUBMENU, NULL, menu_reset }, { "Debug / Advanced", XEMUGUI_MENUID_SUBMENU, NULL, menu_debug }, { "Configuration", XEMUGUI_MENUID_SUBMENU, NULL, menu_config },