mirror of
https://github.com/holub/mame
synced 2025-07-03 00:56:03 +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) :
|
||||
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"
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user