m6502/m4510.cpp: CPU I/O port support (backport from M6510 core)

This commit is contained in:
angelosa 2024-08-17 23:20:04 +02:00
parent 1853ece4b7
commit 1e3ee8b40d
3 changed files with 138 additions and 19 deletions

View File

@ -20,7 +20,10 @@ DEFINE_DEVICE_TYPE(M4510, m4510_device, "m4510", "CSG 4510")
m4510_device::m4510_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m65ce02_device(mconfig, M4510, tag, owner, clock),
map_enable(0),
nomap(false)
nomap(false),
read_port(*this, 0),
write_port(*this),
dir(0), port(0), drive(0)
{
program_config.m_addr_width = 20;
program_config.m_logaddr_width = 16;
@ -28,6 +31,14 @@ m4510_device::m4510_device(const machine_config &mconfig, const char *tag, devic
sprogram_config.m_addr_width = 20;
sprogram_config.m_logaddr_width = 16;
sprogram_config.m_page_shift = 13;
pullup = 0x00;
floating = 0x00;
}
void m4510_device::set_pulls(uint8_t _pullup, uint8_t _floating)
{
pullup = _pullup;
floating = _floating;
}
std::unique_ptr<util::disasm_interface> m4510_device::create_disassembler()
@ -35,11 +46,21 @@ std::unique_ptr<util::disasm_interface> m4510_device::create_disassembler()
return std::make_unique<m4510_disassembler>();
}
void m4510_device::init_port()
{
save_item(NAME(pullup));
save_item(NAME(floating));
save_item(NAME(dir));
save_item(NAME(port));
save_item(NAME(drive));
}
void m4510_device::device_start()
{
mintf = std::make_unique<mi_4510>(this);
m65ce02_device::init();
init_port();
save_item(NAME(map_offset));
save_item(NAME(map_enable));
@ -51,10 +72,44 @@ void m4510_device::device_reset()
map_enable = 0;
nomap = true;
// Wild guess, this setting makes the cpu start executing some code in the c65 driver
//map_offset[1] = 0x2e000;
//map_enable = 0x80;
m65ce02_device::device_reset();
dir = 0x00;
port = 0x00;
drive = 0x00;
update_port();
}
void m4510_device::update_port()
{
drive = (port & dir) | (drive & ~dir);
write_port((port & dir) | (pullup & ~dir));
}
uint8_t m4510_device::get_port()
{
return (port & dir) | (pullup & ~dir);
}
uint8_t m4510_device::dir_r()
{
return dir;
}
uint8_t m4510_device::port_r()
{
return ((read_port() | (floating & drive)) & ~dir) | (port & dir);
}
void m4510_device::dir_w(uint8_t data)
{
dir = data;
update_port();
}
void m4510_device::port_w(uint8_t data)
{
port = data;
update_port();
}
bool m4510_device::memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space)
@ -75,22 +130,41 @@ m4510_device::mi_4510::mi_4510(m4510_device *_base)
uint8_t m4510_device::mi_4510::read(uint16_t adr)
{
return program.read_byte(base->map(adr));
uint8_t res = program.read_byte(base->map(adr));
if(adr == 0x0000)
res = base->dir_r();
else if(adr == 0x0001)
res = base->port_r();
return res;
}
uint8_t m4510_device::mi_4510::read_sync(uint16_t adr)
{
return csprogram.read_byte(base->map(adr));
uint8_t res = csprogram.read_byte(base->map(adr));
if(adr == 0x0000)
res = base->dir_r();
else if(adr == 0x0001)
res = base->port_r();
return res;
}
uint8_t m4510_device::mi_4510::read_arg(uint16_t adr)
{
return cprogram.read_byte(base->map(adr));
uint8_t res = cprogram.read_byte(base->map(adr));
if(adr == 0x0000)
res = base->dir_r();
else if(adr == 0x0001)
res = base->port_r();
return res;
}
void m4510_device::mi_4510::write(uint16_t adr, uint8_t val)
{
program.write_byte(base->map(adr), val);
if(adr == 0x0000)
base->dir_w(val);
else if(adr == 0x0001)
base->port_w(val);
}
#include "cpu/m6502/m4510.hxx"

View File

@ -26,6 +26,12 @@ public:
bool get_nomap() const { return nomap; }
uint8_t get_port();
void set_pulls(uint8_t pullup, uint8_t pulldown);
auto read_callback() { return read_port.bind(); }
auto write_callback() { return write_port.bind(); }
protected:
uint32_t map_offset[2];
uint8_t map_enable;
@ -43,6 +49,11 @@ protected:
virtual void write(uint16_t adr, uint8_t val) override;
};
devcb_read8 read_port;
devcb_write8 write_port;
uint8_t pullup, floating, dir, port, drive;
virtual void device_start() override;
virtual void device_reset() override;
virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override;
@ -56,6 +67,14 @@ protected:
return adr;
}
uint8_t dir_r();
void dir_w(uint8_t data);
uint8_t port_r();
void port_w(uint8_t data);
void init_port();
void update_port();
#define O(o) void o ## _full(); void o ## _partial()
// 4510 opcodes

View File

@ -300,6 +300,9 @@ public:
//, m_roma_view(*this, "roma_view")
, m_romc_view(*this, "romc_view")
//, m_rome_view(*this, "rome_view")
//, m_loram_view(*this, "loram_view")
//, m_hiram_view(*this, "hiram_view")
, m_charen_view(*this, "charen_view")
, m_screen(*this, "screen")
, m_palette(*this, "palette")
, m_workram(*this, "work_ram", 0x20000, ENDIANNESS_LITTLE)
@ -334,6 +337,10 @@ private:
//memory_view m_roma_view;
memory_view m_romc_view;
//memory_view m_rome_view;
//memory_view m_loram_view;
//memory_view m_hiram_view;
memory_view m_charen_view;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
memory_share_creator<uint8_t> m_workram;
@ -359,6 +366,8 @@ private:
uint8_t cia0_portb_r();
void cia0_portb_w(uint8_t data);
void cia1_porta_w(uint8_t data);
uint8_t cpu_r();
void cpu_w(uint8_t data);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void palette_init(palette_device &palette);
@ -994,23 +1003,25 @@ void c65_state::c65_map(address_map &map)
map(0x0c000, 0x0cfff).view(m_romc_view);
m_romc_view[0](0x0c000, 0x0cfff).rw(FUNC(c65_state::ram_r<0x0c000>), FUNC(c65_state::ram_w<0x0c000>));
m_romc_view[1](0x0c000, 0x0cfff).rom().region("ipl", 0x0c000);
map(0x0d000, 0x0d07f).m(*this, FUNC(c65_state::vic4567_map));
map(0x0d000, 0x0dfff).view(m_charen_view);
m_charen_view[0](0x0d000, 0x0dfff).rom().region("ipl", 0x0d000);
m_charen_view[1](0x0d000, 0x0d07f).m(*this, FUNC(c65_state::vic4567_map));
// 0x0d080, 0x0d09f FDC
map(0x0d080, 0x0d09f).lr8(NAME([] (offs_t offset) { return 0; }));
m_charen_view[1](0x0d080, 0x0d09f).lr8(NAME([] (offs_t offset) { return 0; }));
// 0x0d0a0, 0x0d0ff Ram Expansion Control (REC)
map(0x0d100, 0x0d1ff).ram().w(FUNC(c65_state::palette_red_w)).share("redpal");
map(0x0d200, 0x0d2ff).ram().w(FUNC(c65_state::palette_green_w)).share("greenpal");
map(0x0d300, 0x0d3ff).ram().w(FUNC(c65_state::palette_blue_w)).share("bluepal");
m_charen_view[1](0x0d100, 0x0d1ff).ram().w(FUNC(c65_state::palette_red_w)).share("redpal");
m_charen_view[1](0x0d200, 0x0d2ff).ram().w(FUNC(c65_state::palette_green_w)).share("greenpal");
m_charen_view[1](0x0d300, 0x0d3ff).ram().w(FUNC(c65_state::palette_blue_w)).share("bluepal");
// 0x0d400, 0x0d4*f Right SID
// keyboard hold left shift will read to $d484 (?)
map(0x0d400, 0x0d41f).mirror(0x80).rw(m_sid[1], FUNC(mos6581_device::read), FUNC(mos6581_device::write));
m_charen_view[1](0x0d400, 0x0d41f).mirror(0x80).rw(m_sid[1], FUNC(mos6581_device::read), FUNC(mos6581_device::write));
// 0x0d440, 0x0d4*f Left SID
map(0x0d440, 0x0d45f).mirror(0x80).rw(m_sid[0], FUNC(mos6581_device::read), FUNC(mos6581_device::write));
map(0x0d600, 0x0d6ff).rw(FUNC(c65_state::uart_r), FUNC(c65_state::uart_w));
m_charen_view[1](0x0d440, 0x0d45f).mirror(0x80).rw(m_sid[0], FUNC(mos6581_device::read), FUNC(mos6581_device::write));
m_charen_view[1](0x0d600, 0x0d6ff).rw(FUNC(c65_state::uart_r), FUNC(c65_state::uart_w));
// 0x0d700, 0x0d7** DMAgic
map(0x0d700, 0x0d703).m(m_dma, FUNC(dmagic_f018_device::map));
m_charen_view[1](0x0d700, 0x0d703).m(m_dma, FUNC(dmagic_f018_device::map));
// 0x0d800, 0x0d8** Color matrix
map(0x0d800, 0x0dfff).view(m_cram_view);
m_charen_view[1](0x0d800, 0x0dfff).view(m_cram_view);
// maps lower 1024 bytes regardless of the setting (essentially touches $dc00 as overlay)
m_cram_view[0](0x0d800, 0x0dbff).lrw8(
NAME([this] (offs_t offset) { return m_cram[offset]; }),
@ -1211,11 +1222,27 @@ void c65_state::irq_check(uint8_t irq_cause)
m_irqs->in_w<1>(m_irq_mask & m_irq_pending);
}
uint8_t c65_state::cpu_r()
{
return 0x07;
}
void c65_state::cpu_w(uint8_t data)
{
// m_loram = BIT(data, 0);
// m_hiram = BIT(data, 1);
m_charen_view.select(BIT(data, 2));
}
void c65_state::c65(machine_config &config)
{
/* basic machine hardware */
M4510(config, m_maincpu, MAIN_C65_CLOCK);
m_maincpu->set_addrmap(AS_PROGRAM, &c65_state::c65_map);
m_maincpu->read_callback().set(FUNC(c65_state::cpu_r));
m_maincpu->write_callback().set(FUNC(c65_state::cpu_w));
m_maincpu->set_pulls(0x07, 0xc0);
// TODO: multiply by x8 because with a more canonical x1 no transfer will complete in time.
// is this thing a mixed burst/cycle steal really?
@ -1266,9 +1293,8 @@ void c65_state::c65(machine_config &config)
//m_sid->poty().set(FUNC(c64_state::sid_poty_r));
m_sid[1]->add_route(ALL_OUTPUTS, "rspeaker", 0.50);
// software list
SOFTWARE_LIST(config, "flop_list").set_original("c65_flop");
// SOFTWARE_LIST(config, "cart_list").set_compatible("c64_cart");
}