mirror of
https://github.com/holub/mame
synced 2025-07-06 02:18:09 +03:00
m6502/m4510.cpp: CPU I/O port support (backport from M6510 core)
This commit is contained in:
parent
1853ece4b7
commit
1e3ee8b40d
@ -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) :
|
m4510_device::m4510_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||||
m65ce02_device(mconfig, M4510, tag, owner, clock),
|
m65ce02_device(mconfig, M4510, tag, owner, clock),
|
||||||
map_enable(0),
|
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_addr_width = 20;
|
||||||
program_config.m_logaddr_width = 16;
|
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_addr_width = 20;
|
||||||
sprogram_config.m_logaddr_width = 16;
|
sprogram_config.m_logaddr_width = 16;
|
||||||
sprogram_config.m_page_shift = 13;
|
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()
|
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>();
|
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()
|
void m4510_device::device_start()
|
||||||
{
|
{
|
||||||
mintf = std::make_unique<mi_4510>(this);
|
mintf = std::make_unique<mi_4510>(this);
|
||||||
|
|
||||||
m65ce02_device::init();
|
m65ce02_device::init();
|
||||||
|
init_port();
|
||||||
|
|
||||||
save_item(NAME(map_offset));
|
save_item(NAME(map_offset));
|
||||||
save_item(NAME(map_enable));
|
save_item(NAME(map_enable));
|
||||||
@ -51,10 +72,44 @@ void m4510_device::device_reset()
|
|||||||
map_enable = 0;
|
map_enable = 0;
|
||||||
nomap = true;
|
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();
|
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)
|
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)
|
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)
|
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)
|
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)
|
void m4510_device::mi_4510::write(uint16_t adr, uint8_t val)
|
||||||
{
|
{
|
||||||
program.write_byte(base->map(adr), 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"
|
#include "cpu/m6502/m4510.hxx"
|
||||||
|
@ -26,6 +26,12 @@ public:
|
|||||||
|
|
||||||
bool get_nomap() const { return nomap; }
|
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:
|
protected:
|
||||||
uint32_t map_offset[2];
|
uint32_t map_offset[2];
|
||||||
uint8_t map_enable;
|
uint8_t map_enable;
|
||||||
@ -43,6 +49,11 @@ protected:
|
|||||||
virtual void write(uint16_t adr, uint8_t val) override;
|
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_start() override;
|
||||||
virtual void device_reset() override;
|
virtual void device_reset() override;
|
||||||
virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override;
|
virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override;
|
||||||
@ -56,6 +67,14 @@ protected:
|
|||||||
return adr;
|
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()
|
#define O(o) void o ## _full(); void o ## _partial()
|
||||||
|
|
||||||
// 4510 opcodes
|
// 4510 opcodes
|
||||||
|
@ -300,6 +300,9 @@ public:
|
|||||||
//, m_roma_view(*this, "roma_view")
|
//, m_roma_view(*this, "roma_view")
|
||||||
, m_romc_view(*this, "romc_view")
|
, m_romc_view(*this, "romc_view")
|
||||||
//, m_rome_view(*this, "rome_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_screen(*this, "screen")
|
||||||
, m_palette(*this, "palette")
|
, m_palette(*this, "palette")
|
||||||
, m_workram(*this, "work_ram", 0x20000, ENDIANNESS_LITTLE)
|
, m_workram(*this, "work_ram", 0x20000, ENDIANNESS_LITTLE)
|
||||||
@ -334,6 +337,10 @@ private:
|
|||||||
//memory_view m_roma_view;
|
//memory_view m_roma_view;
|
||||||
memory_view m_romc_view;
|
memory_view m_romc_view;
|
||||||
//memory_view m_rome_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<screen_device> m_screen;
|
||||||
required_device<palette_device> m_palette;
|
required_device<palette_device> m_palette;
|
||||||
memory_share_creator<uint8_t> m_workram;
|
memory_share_creator<uint8_t> m_workram;
|
||||||
@ -359,6 +366,8 @@ private:
|
|||||||
uint8_t cia0_portb_r();
|
uint8_t cia0_portb_r();
|
||||||
void cia0_portb_w(uint8_t data);
|
void cia0_portb_w(uint8_t data);
|
||||||
void cia1_porta_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);
|
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||||
void palette_init(palette_device &palette);
|
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);
|
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[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);
|
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
|
// 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)
|
// 0x0d0a0, 0x0d0ff Ram Expansion Control (REC)
|
||||||
map(0x0d100, 0x0d1ff).ram().w(FUNC(c65_state::palette_red_w)).share("redpal");
|
m_charen_view[1](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");
|
m_charen_view[1](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](0x0d300, 0x0d3ff).ram().w(FUNC(c65_state::palette_blue_w)).share("bluepal");
|
||||||
// 0x0d400, 0x0d4*f Right SID
|
// 0x0d400, 0x0d4*f Right SID
|
||||||
// keyboard hold left shift will read to $d484 (?)
|
// 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
|
// 0x0d440, 0x0d4*f Left SID
|
||||||
map(0x0d440, 0x0d45f).mirror(0x80).rw(m_sid[0], FUNC(mos6581_device::read), FUNC(mos6581_device::write));
|
m_charen_view[1](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](0x0d600, 0x0d6ff).rw(FUNC(c65_state::uart_r), FUNC(c65_state::uart_w));
|
||||||
// 0x0d700, 0x0d7** DMAgic
|
// 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
|
// 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)
|
// maps lower 1024 bytes regardless of the setting (essentially touches $dc00 as overlay)
|
||||||
m_cram_view[0](0x0d800, 0x0dbff).lrw8(
|
m_cram_view[0](0x0d800, 0x0dbff).lrw8(
|
||||||
NAME([this] (offs_t offset) { return m_cram[offset]; }),
|
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);
|
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)
|
void c65_state::c65(machine_config &config)
|
||||||
{
|
{
|
||||||
/* basic machine hardware */
|
/* basic machine hardware */
|
||||||
M4510(config, m_maincpu, MAIN_C65_CLOCK);
|
M4510(config, m_maincpu, MAIN_C65_CLOCK);
|
||||||
m_maincpu->set_addrmap(AS_PROGRAM, &c65_state::c65_map);
|
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.
|
// 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?
|
// 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->poty().set(FUNC(c64_state::sid_poty_r));
|
||||||
m_sid[1]->add_route(ALL_OUTPUTS, "rspeaker", 0.50);
|
m_sid[1]->add_route(ALL_OUTPUTS, "rspeaker", 0.50);
|
||||||
|
|
||||||
|
|
||||||
// software list
|
|
||||||
SOFTWARE_LIST(config, "flop_list").set_original("c65_flop");
|
SOFTWARE_LIST(config, "flop_list").set_original("c65_flop");
|
||||||
|
// SOFTWARE_LIST(config, "cart_list").set_compatible("c64_cart");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user