From 84970b9090f99ca6a06cb0133b108aabf3caf533 Mon Sep 17 00:00:00 2001 From: npwoods Date: Fri, 22 Oct 2021 22:54:26 -0400 Subject: Initial RPK support for CoCo (#8541) --- src/devices/bus/coco/cococart.cpp | 109 +++++++++++++++++++++++++++++++++++--- 1 file changed, 103 insertions(+), 6 deletions(-) diff --git a/src/devices/bus/coco/cococart.cpp b/src/devices/bus/coco/cococart.cpp index 5f6e543725a..04b22d1471c 100644 --- a/src/devices/bus/coco/cococart.cpp +++ b/src/devices/bus/coco/cococart.cpp @@ -39,6 +39,7 @@ #include "emu.h" #include "cococart.h" +#include "formats/rpk.h" #include "coco_dcmodem.h" #include "coco_fdc.h" @@ -96,6 +97,23 @@ enum }; +// definitions of RPK PCBs in layout.xml +static const char *coco_rpk_pcbdefs[] = +{ + "standard", + "paged16k", + nullptr +}; + + +// ...and their mappings to "default card slots" +static const char *coco_rpk_cardslottypes[] = +{ + "pak", + "banked_16k" +}; + + //************************************************************************** // GLOBAL VARIABLES //************************************************************************** @@ -474,6 +492,63 @@ void cococart_slot_device::set_cart_base_update(cococart_base_update_delegate up } +//------------------------------------------------- +// read_coco_rpk +//------------------------------------------------- + +static std::error_condition read_coco_rpk(std::unique_ptr &&stream, rpk_file::ptr &result) +{ + // sanity checks + static_assert(std::size(coco_rpk_pcbdefs) - 1 == std::size(coco_rpk_cardslottypes)); + + // set up the RPK reader + rpk_reader reader(coco_rpk_pcbdefs, false); + + // and read the RPK file + return reader.read(std::move(stream), result); +} + + +//------------------------------------------------- +// read_coco_rpk +//------------------------------------------------- + +static std::error_condition read_coco_rpk(std::unique_ptr &&stream, u8 *mem, offs_t cart_length, offs_t &actual_length) +{ + actual_length = 0; + + // open the RPK + rpk_file::ptr file; + std::error_condition err = read_coco_rpk(std::move(stream), file); + if (err) + return err; + + // for now, we are just going to load all sockets into the contiguous block of memory + // that cartridges use + offs_t pos = 0; + for (const rpk_socket &socket : file->sockets()) + { + // only ROM supported for now; if we see anything else it should have been caught in the RPK code + assert(socket.type() == rpk_socket::socket_type::ROM); + + // read all bytes + std::vector contents; + err = socket.read_file(contents); + if (err) + return err; + + // copy the bytes + offs_t size = (offs_t) std::min(contents.size(), (size_t)cart_length - pos); + memcpy(&mem[pos], &contents[0], size); + pos += size; + } + + // we're done! + actual_length = pos; + return std::error_condition(); +} + + //------------------------------------------------- // call_load //------------------------------------------------- @@ -486,14 +561,23 @@ image_init_result cococart_slot_device::call_load() u8 *base = cart_mem->base(); offs_t read_length, cart_length = cart_mem->bytes(); - if (!loaded_through_softlist()) + if (loaded_through_softlist()) { - read_length = fread(base, cart_length); + // loaded through softlist + read_length = get_software_region_length("rom"); + memcpy(base, get_software_region("rom"), read_length); + } + else if (is_filetype("rpk")) + { + // RPK file + std::error_condition err = read_coco_rpk(util::core_file_read(image_core_file()), base, cart_length, read_length); + if (err) + return image_init_result::FAIL; } else { - read_length = get_software_region_length("rom"); - memcpy(base, get_software_region("rom"), read_length); + // conventional ROM image + read_length = fread(base, cart_length); } while (read_length < cart_length) @@ -513,9 +597,22 @@ image_init_result cococart_slot_device::call_load() std::string cococart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const { - return software_get_default_slot("pak"); -} + // this is the default for anything not in an RPK file + int pcb_type = 0; + // is this an RPK? + if (hook.is_filetype("rpk")) + { + // RPK file + rpk_file::ptr file; + std::error_condition err = read_coco_rpk(util::core_file_read(*hook.image_file()), file); + if (!err) + pcb_type = file->pcb_type(); + } + + // lookup the default slot + return software_get_default_slot(coco_rpk_cardslottypes[pcb_type]); +} //************************************************************************** -- cgit v1.2.3