bus/msx/slot/panasonic08r.cpp: Added MSX Turbo-R internal firmware mapper. (#12737)

This commit is contained in:
wilbertpol 2024-09-10 17:08:30 +01:00 committed by GitHub
parent a85e3cbc0f
commit ca1df2fcb2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 222 additions and 0 deletions

View File

@ -2010,6 +2010,8 @@ if (BUSES["MSX_SLOT"]~=null) then
MAME_DIR .. "src/devices/bus/msx/slot/music.h",
MAME_DIR .. "src/devices/bus/msx/slot/panasonic08.cpp",
MAME_DIR .. "src/devices/bus/msx/slot/panasonic08.h",
MAME_DIR .. "src/devices/bus/msx/slot/panasonic08r.cpp",
MAME_DIR .. "src/devices/bus/msx/slot/panasonic08r.h",
MAME_DIR .. "src/devices/bus/msx/slot/rom.cpp",
MAME_DIR .. "src/devices/bus/msx/slot/rom.h",
MAME_DIR .. "src/devices/bus/msx/slot/ram.cpp",

View File

@ -0,0 +1,165 @@
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol
/*
Emulation of the firmware mapper as found in Panasonic FS-A1ST and FS-A1GT Turbo-R machines.
*/
#include "emu.h"
#include "panasonic08r.h"
DEFINE_DEVICE_TYPE(MSX_SLOT_PANASONIC08R, msx_slot_panasonic08r_device, "msx_slot_panasonic08r", "MSX Internal Panasonic08r")
msx_slot_panasonic08r_device::msx_slot_panasonic08r_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, MSX_SLOT_PANASONIC08R, tag, owner, clock)
, msx_internal_slot_interface(mconfig, *this)
, m_sram_size(0)
, m_nvram(*this, "nvram")
, m_rom_region(*this, finder_base::DUMMY_TAG)
, m_bank(*this, "bank%u", 0U)
, m_view{
{*this, "view0"}, {*this, "view1"}, {*this, "view2"}, {*this, "view3"},
{*this, "view4"}, {*this, "view5"}, {*this, "view6"}, {*this, "view7"}
}
, m_mm(*this, finder_base::DUMMY_TAG)
, m_region_offset(0)
, m_control(0)
{
}
void msx_slot_panasonic08r_device::device_add_mconfig(machine_config &config)
{
NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0);
}
void msx_slot_panasonic08r_device::device_start()
{
// Sanity checks
if (m_rom_region->bytes() < m_region_offset + 0x400000)
fatalerror("Memory region '%s' is too small for the panasonic08r firmware\n", m_rom_region.finder_tag());
if (m_sram_size != 0x4000 && m_sram_size != 0x8000)
fatalerror("Invalid SRAM size for the panasonic08r firmware\n");
m_sram = std::make_unique<u8[]>(m_sram_size);
m_nvram->set_base(&m_sram[0], m_sram_size);
save_item(NAME(m_selected_bank));
save_item(NAME(m_control));
save_item(NAME(m_bank9));
for (int i = 0; i < 8; i++)
{
m_bank[i]->configure_entries(0, 0x200, m_rom_region->base() + m_region_offset, 0x2000);
m_bank[i]->configure_entry(0x80, &m_sram[0]);
m_bank[i]->configure_entry(0x81, &m_sram[0x2000]);
if (m_sram_size >= 0x8000)
{
m_bank[i]->configure_entry(0x82, &m_sram[0x4000]);
m_bank[i]->configure_entry(0x83, &m_sram[0x6000]);
}
// Assuming smaller internal RAM is mirrored.
int internal_ram_banks = m_mm->get_ram().size() / 0x2000;
int start_bank = 0x180;
do {
int nr_banks = internal_ram_banks;
if (start_bank + nr_banks > 0x200)
nr_banks = 0x200 - start_bank;
m_bank[i]->configure_entries(start_bank, nr_banks, m_mm->get_ram().data(), 0x2000);
start_bank += internal_ram_banks;
}
while (start_bank < 0x200);
}
for (int i = 0; i < 8; i++)
{
const u16 start = 0x2000 * i;
const u16 end = start + 0x1fff;
page(i/2)->install_view(start, end, m_view[i]);
m_view[i][0].install_read_bank(start, end, m_bank[i]);
m_view[i][1].install_readwrite_bank(start, end, m_bank[i]);
}
m_view[3][2].install_read_bank(0x6000, 0x7fff, m_bank[3]);
m_view[3][2].install_read_handler(0x7ff0, 0x7ff7, read8sm_delegate(*this, [this] (offs_t offset) { return m_selected_bank[offset] & 0xff; }, "bank_r"));
m_view[3][3].install_readwrite_bank(0x6000, 0x7fff, m_bank[3]);
m_view[3][3].install_read_handler(0x7ff0, 0x7ff7, read8sm_delegate(*this, [this] (offs_t offset) { return m_selected_bank[offset] & 0xff; }, "bank_r"));
page(1)->install_write_handler(0x6000, 0x6000, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<0>)));
page(1)->install_write_handler(0x6400, 0x6400, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<1>)));
page(1)->install_write_handler(0x6800, 0x6800, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<2>)));
page(1)->install_write_handler(0x6c00, 0x6c00, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<3>)));
page(1)->install_write_handler(0x7000, 0x7000, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<4>)));
page(1)->install_write_handler(0x7400, 0x7400, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<6>)));
page(1)->install_write_handler(0x7800, 0x7800, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<5>)));
page(1)->install_write_handler(0x7c00, 0x7c00, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<7>)));
page(1)->install_readwrite_handler(0x7ff8, 0x7ff8,
read8smo_delegate(*this, [this] () { return m_bank9; }, "bank9_r"),
write8smo_delegate(*this, [this] (u8 data)
{
m_bank9 = data;
select_banks();
}, "bank9_w"));
page(1)->install_write_handler(0x7ff9, 0x7ff9, write8smo_delegate(*this, [this] (u8 data)
{
m_control = data;
select_banks();
}, "control_w"
));
}
void msx_slot_panasonic08r_device::device_reset()
{
m_control = 0;
m_bank9 = 0;
for (int i = 0 ; i < 8; i++)
{
m_selected_bank[i] = 0;
m_bank[i]->set_entry(0);
m_view[i].select(0);
}
}
template <int Bank>
void msx_slot_panasonic08r_device::set_view()
{
const bool sram_active = (m_selected_bank[Bank] >= 0x80 && m_selected_bank[Bank] < 0x84);
const bool ram_active = (m_selected_bank[Bank] >= 0x180);
const int view = ((sram_active || ram_active) ? 1 : 0) | ((Bank == 3 && BIT(m_control, 2)) ? 2 : 0);
m_view[Bank].select(view);
}
template <int Bank>
void msx_slot_panasonic08r_device::bank_w(u8 data)
{
u16 bank = data;
if (BIT(m_control, 4))
bank |= (BIT(m_bank9, Bank) << 8);
m_selected_bank[Bank] = bank;
m_bank[Bank]->set_entry(bank);
set_view<Bank>();
}
void msx_slot_panasonic08r_device::select_banks()
{
bank_w<0>(m_selected_bank[0]);
bank_w<1>(m_selected_bank[1]);
bank_w<2>(m_selected_bank[2]);
bank_w<3>(m_selected_bank[3]);
bank_w<4>(m_selected_bank[4]);
bank_w<5>(m_selected_bank[5]);
bank_w<6>(m_selected_bank[6]);
bank_w<7>(m_selected_bank[7]);
}

View File

@ -0,0 +1,52 @@
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol
#ifndef MAME_BUS_MSX_SLOT_PANASONIC08R_H
#define MAME_BUS_MSX_SLOT_PANASONIC08R_H
#pragma once
#include "ram_mm.h"
#include "slot.h"
#include "machine/nvram.h"
DECLARE_DEVICE_TYPE(MSX_SLOT_PANASONIC08R, msx_slot_panasonic08r_device)
class msx_slot_panasonic08r_device : public device_t, public msx_internal_slot_interface
{
public:
msx_slot_panasonic08r_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// configuration helpers
template <typename T> msx_slot_panasonic08r_device &set_mm_tag(T &&tag) { m_mm.set_tag(std::forward<T>(tag)); return *this; }
void set_rom_start(const char *region, u32 offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
msx_slot_panasonic08r_device &set_sram_size(u16 size) { m_sram_size = size; return *this; }
protected:
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
private:
template <int Bank> void set_view();
template <int Bank> void bank_w(u8 data);
void select_banks();
u16 m_sram_size;
required_device<nvram_device> m_nvram;
required_memory_region m_rom_region;
memory_bank_array_creator<8> m_bank;
memory_view m_view[8];
required_device<msx_slot_ram_mm_device> m_mm;
u32 m_region_offset;
u16 m_selected_bank[8];
u8 m_control;
u8 m_bank9;
std::unique_ptr<u8[]> m_sram;
};
#endif // MAME_BUS_MSX_SLOT_PANASONIC08R_H

View File

@ -15,6 +15,9 @@ public:
msx_slot_ram_mm_device &set_total_size(u32 total_size) { m_total_size = total_size; return *this; }
msx_slot_ram_mm_device &set_unused_bits(u8 unused_bits) { m_unused_bits = unused_bits; return *this; }
// Backdoor for the Turbo-R firmware/internal mapper to access internal RAM.
std::vector<u8> &get_ram() { return m_ram; }
protected:
virtual void device_start() override;