Skip to content

Commit

Permalink
m6502/m4510.cpp: CPU I/O port support (backport from M6510 core)
Browse files Browse the repository at this point in the history
  • Loading branch information
angelosa committed Aug 17, 2024
1 parent 1853ece commit 1e3ee8b
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 19 deletions.
88 changes: 81 additions & 7 deletions src/devices/cpu/m6502/m4510.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,47 @@ 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;
program_config.m_page_shift = 13;
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()
{
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));
Expand All @@ -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)
Expand All @@ -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"
19 changes: 19 additions & 0 deletions src/devices/cpu/m6502/m4510.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ class m4510_device : public m65ce02_device {

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;
Expand All @@ -43,6 +49,11 @@ class m4510_device : public m65ce02_device {
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;
Expand All @@ -56,6 +67,14 @@ class m4510_device : public m65ce02_device {
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
Expand Down
50 changes: 38 additions & 12 deletions src/mame/commodore/c65.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,9 @@ class c65_state : public driver_device
//, 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)
Expand Down Expand Up @@ -334,6 +337,10 @@ class c65_state : public driver_device
//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;
Expand All @@ -359,6 +366,8 @@ class c65_state : public driver_device
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);
Expand Down Expand Up @@ -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]; }),
Expand Down Expand Up @@ -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?
Expand Down Expand Up @@ -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");
}


Expand Down

0 comments on commit 1e3ee8b

Please sign in to comment.