mc68328: Improve integration of emulated device (nw)

- Derive class from m68000_device instead of using CPU finder
- Internalize read/write handlers and mapping for on-chip registers
- Read video memory from cached address space instead of hardcoded RAM device in screen_update
- Generate vectors upon interrupt acknowledgment instead of using set_input_line_and_vector
- Mask out low 3 bits of IVR
- Move callback resolution to device_resolve_objects
This commit is contained in:
AJR 2019-04-03 20:17:07 -04:00
parent 80807d7453
commit b7a49aff4a
3 changed files with 76 additions and 60 deletions

View File

@ -10,8 +10,6 @@
#include "emu.h"
#include "machine/mc68328.h"
#include "cpu/m68000/m68000.h"
#include "machine/ram.h"
#define SCR_BETO 0x80
@ -350,8 +348,14 @@ static inline void ATTR_PRINTF(3,4) verboselog(device_t &device, int n_level, co
DEFINE_DEVICE_TYPE(MC68328, mc68328_device, "mc68328", "MC68328 DragonBall Integrated Processor")
void mc68328_device::internal_map(address_map &map)
{
map(0xfff000, 0xffffff).rw(FUNC(mc68328_device::internal_read), FUNC(mc68328_device::internal_write));
}
mc68328_device::mc68328_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, MC68328, tag, owner, clock)
: m68000_device(mconfig, tag, owner, clock, MC68328, 16, 24, address_map_constructor(FUNC(mc68328_device::internal_map), this))
, m_rtc(nullptr), m_pwm(nullptr)
, m_out_port_a_cb(*this)
, m_out_port_b_cb(*this)
@ -377,16 +381,19 @@ mc68328_device::mc68328_device(const machine_config &mconfig, const char *tag, d
, m_out_spim_cb(*this)
, m_in_spim_cb(*this)
, m_spim_xch_trigger_cb(*this)
, m_cpu(*this, finder_base::DUMMY_TAG)
{
}
//-------------------------------------------------
// device_start - device-specific startup
// device_resolve_objects - resolve objects that
// may be needed for other devices to set
// initial conditions at start time
//-------------------------------------------------
void mc68328_device::device_start()
void mc68328_device::device_resolve_objects()
{
m68000_device::device_resolve_objects();
m_out_port_a_cb.resolve();
m_out_port_b_cb.resolve();
m_out_port_c_cb.resolve();
@ -415,6 +422,15 @@ void mc68328_device::device_start()
m_in_spim_cb.resolve();
m_spim_xch_trigger_cb.resolve();
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void mc68328_device::device_start()
{
m68000_device::device_start();
m_gptimer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mc68328_device::timer1_hit),this));
m_gptimer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mc68328_device::timer2_hit),this));
@ -430,6 +446,10 @@ void mc68328_device::device_start()
void mc68328_device::device_reset()
{
m68000_device::device_reset();
m_int_ack_callback = device_irq_acknowledge_delegate(FUNC(mc68328_device::vector_gen), this);
m_regs.scr = 0x0c;
m_regs.grpbasea = 0x0000;
m_regs.grpbaseb = 0x0000;
@ -575,31 +595,31 @@ void mc68328_device::set_interrupt_line(uint32_t line, uint32_t active)
if (m_regs.isr & INT_M68K_LINE7)
{
m_cpu->set_input_line_and_vector(M68K_IRQ_7, ASSERT_LINE, m_regs.ivr | 0x07);
set_input_line(M68K_IRQ_7, ASSERT_LINE);
}
else if (m_regs.isr & INT_M68K_LINE6)
{
m_cpu->set_input_line_and_vector(M68K_IRQ_6, ASSERT_LINE, m_regs.ivr | 0x06);
set_input_line(M68K_IRQ_6, ASSERT_LINE);
}
else if (m_regs.isr & INT_M68K_LINE5)
{
m_cpu->set_input_line_and_vector(M68K_IRQ_5, ASSERT_LINE, m_regs.ivr | 0x05);
set_input_line(M68K_IRQ_5, ASSERT_LINE);
}
else if (m_regs.isr & INT_M68K_LINE4)
{
m_cpu->set_input_line_and_vector(M68K_IRQ_4, ASSERT_LINE, m_regs.ivr | 0x04);
set_input_line(M68K_IRQ_4, ASSERT_LINE);
}
else if (m_regs.isr & INT_M68K_LINE3)
{
m_cpu->set_input_line_and_vector(M68K_IRQ_3, ASSERT_LINE, m_regs.ivr | 0x03);
set_input_line(M68K_IRQ_3, ASSERT_LINE);
}
else if (m_regs.isr & INT_M68K_LINE2)
{
m_cpu->set_input_line_and_vector(M68K_IRQ_2, ASSERT_LINE, m_regs.ivr | 0x02);
set_input_line(M68K_IRQ_2, ASSERT_LINE);
}
else if (m_regs.isr & INT_M68K_LINE1)
{
m_cpu->set_input_line_and_vector(M68K_IRQ_1, ASSERT_LINE, m_regs.ivr | 0x01);
set_input_line(M68K_IRQ_1, ASSERT_LINE);
}
}
}
@ -609,31 +629,31 @@ void mc68328_device::set_interrupt_line(uint32_t line, uint32_t active)
if ((line & INT_M68K_LINE7) && !(m_regs.isr & INT_M68K_LINE7))
{
m_cpu->set_input_line(M68K_IRQ_7, CLEAR_LINE);
set_input_line(M68K_IRQ_7, CLEAR_LINE);
}
if ((line & INT_M68K_LINE6) && !(m_regs.isr & INT_M68K_LINE6))
{
m_cpu->set_input_line(M68K_IRQ_6, CLEAR_LINE);
set_input_line(M68K_IRQ_6, CLEAR_LINE);
}
if ((line & INT_M68K_LINE5) && !(m_regs.isr & INT_M68K_LINE5))
{
m_cpu->set_input_line(M68K_IRQ_5, CLEAR_LINE);
set_input_line(M68K_IRQ_5, CLEAR_LINE);
}
if ((line & INT_M68K_LINE4) && !(m_regs.isr & INT_M68K_LINE4))
{
m_cpu->set_input_line(M68K_IRQ_4, CLEAR_LINE);
set_input_line(M68K_IRQ_4, CLEAR_LINE);
}
if ((line & INT_M68K_LINE3) && !(m_regs.isr & INT_M68K_LINE3))
{
m_cpu->set_input_line(M68K_IRQ_3, CLEAR_LINE);
set_input_line(M68K_IRQ_3, CLEAR_LINE);
}
if ((line & INT_M68K_LINE2) && !(m_regs.isr & INT_M68K_LINE2))
{
m_cpu->set_input_line(M68K_IRQ_2, CLEAR_LINE);
set_input_line(M68K_IRQ_2, CLEAR_LINE);
}
if ((line & INT_M68K_LINE1) && !(m_regs.isr & INT_M68K_LINE1))
{
m_cpu->set_input_line(M68K_IRQ_1, CLEAR_LINE);
set_input_line(M68K_IRQ_1, CLEAR_LINE);
}
}
}
@ -685,6 +705,11 @@ void mc68328_device::set_port_d_lines(uint8_t state, int bit)
poll_port_d_interrupts();
}
IRQ_CALLBACK_MEMBER( mc68328_device::vector_gen )
{
return m_regs.ivr | irqline;
}
uint32_t mc68328_device::get_timer_frequency(uint32_t index)
{
uint32_t frequency = 0;
@ -918,7 +943,7 @@ TIMER_CALLBACK_MEMBER( mc68328_device::rtc_tick )
}
}
WRITE16_MEMBER( mc68328_device::write )
void mc68328_device::internal_write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
uint32_t address = offset << 1;
uint16_t temp16[4] = { 0 };
@ -1198,8 +1223,8 @@ WRITE16_MEMBER( mc68328_device::write )
}
else
{
verboselog( *this, 2, "mc68328_w: IVR = %02x\n", (data >> 8) & 0x00ff);
m_regs.ivr = (data >> 8) & 0x00ff;
verboselog( *this, 2, "mc68328_w: IVR = %02x\n", (data >> 8) & 0x00f8);
m_regs.ivr = (data >> 8) & 0x00f8;
}
break;
@ -2112,7 +2137,7 @@ WRITE16_MEMBER( mc68328_device::write )
}
}
READ16_MEMBER( mc68328_device::read )
uint16_t mc68328_device::internal_read(offs_t offset, uint16_t mem_mask)
{
uint16_t temp16;
uint32_t address = offset << 1;
@ -3014,7 +3039,8 @@ READ16_MEMBER( mc68328_device::read )
/* THIS IS PRETTY MUCH TOTALLY WRONG AND DOESN'T REFLECT THE MC68328'S INTERNAL FUNCTIONALITY AT ALL! */
uint32_t mc68328_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
uint16_t *video_ram = (uint16_t *)(machine().device<ram_device>(RAM_TAG)->pointer() + (m_regs.lssa & 0x00ffffff));
auto mcache = space(AS_PROGRAM).cache<1, 0, ENDIANNESS_BIG>();
uint32_t vram_addr = m_regs.lssa & 0x00fffffe;
uint16_t word;
uint16_t *line;
int y, x, b;
@ -3025,9 +3051,9 @@ uint32_t mc68328_device::screen_update(screen_device &screen, bitmap_ind16 &bitm
{
line = &bitmap.pix16(y);
for (x = 0; x < 160; x += 16)
for (x = 0; x < 160; x += 16, vram_addr += 2)
{
word = *(video_ram++);
word = mcache->read_word(vram_addr);
for (b = 0; b < 16; b++)
{
line[x + b] = (word >> (15 - b)) & 0x0001;

View File

@ -87,17 +87,12 @@
#ifndef MAME_MACHINE_MC68328_H
#define MAME_MACHINE_MC68328_H
#include "cpu/m68000/m68000.h"
class mc68328_device : public device_t
class mc68328_device : public m68000_device
{
public:
template <typename T>
mc68328_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag)
: mc68328_device(mconfig, tag, owner, clock)
{
m_cpu.set_tag(std::forward<T>(cpu_tag));
}
mc68328_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto out_port_a() { return m_out_port_a_cb.bind(); }
@ -125,9 +120,6 @@ public:
auto in_spim() { return m_in_spim_cb.bind(); }
auto spim_xch_trigger() { return m_spim_xch_trigger_cb.bind(); }
DECLARE_WRITE16_MEMBER(write);
DECLARE_READ16_MEMBER(read);
DECLARE_WRITE_LINE_MEMBER(set_penirq_line);
void set_port_d_lines(uint8_t state, int bit);
@ -135,6 +127,7 @@ public:
protected:
// device-level overrides
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
@ -332,9 +325,12 @@ private:
uint8_t unused42[1260];
};
void internal_map(address_map &map);
// internal state
void set_interrupt_line(uint32_t line, uint32_t active);
void poll_port_d_interrupts();
IRQ_CALLBACK_MEMBER(vector_gen);
uint32_t get_timer_frequency(uint32_t index);
void maybe_start_timer(uint32_t index, uint32_t new_enable);
void timer_compare_event(uint32_t index);
@ -346,6 +342,9 @@ private:
TIMER_CALLBACK_MEMBER(pwm_transition);
TIMER_CALLBACK_MEMBER(rtc_tick);
void internal_write(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff);
uint16_t internal_read(offs_t offset, uint16_t mem_mask = 0xffff);
mc68328_regs_t m_regs;
emu_timer *m_gptimer[2];
@ -380,8 +379,6 @@ private:
devcb_read16 m_in_spim_cb; /* 16-bit input */
devcb_write_line m_spim_xch_trigger_cb; /* SPIM exchange trigger */ /*todo: not really a write line, fix*/
required_device<cpu_device> m_cpu;
};

View File

@ -21,15 +21,12 @@
#include "screen.h"
#include "speaker.h"
#define MC68328_TAG "dragonball"
class palm_state : public driver_device
{
public:
palm_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_lsi(*this, MC68328_TAG),
m_ram(*this, RAM_TAG),
m_io_penx(*this, "PENX"),
m_io_peny(*this, "PENY"),
@ -64,8 +61,7 @@ private:
offs_t palm_dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer &params);
void palm_map(address_map &map);
required_device<cpu_device> m_maincpu;
required_device<mc68328_device> m_lsi;
required_device<mc68328_device> m_maincpu;
required_device<ram_device> m_ram;
uint8_t m_port_f_latch;
uint16_t m_spim_data;
@ -85,15 +81,15 @@ INPUT_CHANGED_MEMBER(palm_state::pen_check)
uint8_t button = m_io_penb->read();
if(button)
m_lsi->set_penirq_line(1);
m_maincpu->set_penirq_line(1);
else
m_lsi->set_penirq_line(0);
m_maincpu->set_penirq_line(0);
}
INPUT_CHANGED_MEMBER(palm_state::button_check)
{
uint8_t button_state = m_io_portd->read();
m_lsi->set_port_d_lines(button_state, (int)(uintptr_t)param);
m_maincpu->set_port_d_lines(button_state, (int)(uintptr_t)param);
}
WRITE8_MEMBER(palm_state::palm_port_f_out)
@ -174,7 +170,6 @@ void palm_state::palm_palette(palette_device &palette) const
void palm_state::palm_map(address_map &map)
{
map(0xc00000, 0xe07fff).rom().region("bios", 0);
map(0xfff000, 0xffffff).rw(m_lsi, FUNC(mc68328_device::read), FUNC(mc68328_device::write));
}
@ -185,9 +180,16 @@ void palm_state::palm_map(address_map &map)
void palm_state::palm(machine_config &config)
{
/* basic machine hardware */
M68000(config, m_maincpu, 32768*506); /* 16.580608 MHz */
MC68328(config, m_maincpu, 32768*506); /* 16.580608 MHz */
m_maincpu->set_addrmap(AS_PROGRAM, &palm_state::palm_map);
m_maincpu->set_dasm_override(FUNC(palm_state::palm_dasm_override));
m_maincpu->out_port_f().set(FUNC(palm_state::palm_port_f_out));
m_maincpu->in_port_c().set(FUNC(palm_state::palm_port_c_in));
m_maincpu->in_port_f().set(FUNC(palm_state::palm_port_f_in));
m_maincpu->out_pwm().set("dac", FUNC(dac_bit_interface::write));
m_maincpu->out_spim().set(FUNC(palm_state::palm_spim_out));
m_maincpu->in_spim().set(FUNC(palm_state::palm_spim_in));
m_maincpu->spim_xch_trigger().set(FUNC(palm_state::palm_spim_exchange));
config.m_minimum_quantum = attotime::from_hz(60);
@ -198,7 +200,7 @@ void palm_state::palm(machine_config &config)
screen.set_video_attributes(VIDEO_UPDATE_BEFORE_VBLANK);
screen.set_size(160, 220);
screen.set_visarea(0, 159, 0, 219);
screen.set_screen_update(MC68328_TAG, FUNC(mc68328_device::screen_update));
screen.set_screen_update("maincpu", FUNC(mc68328_device::screen_update));
screen.set_palette("palette");
PALETTE(config, "palette", FUNC(palm_state::palm_palette), 2);
@ -208,15 +210,6 @@ void palm_state::palm(machine_config &config)
DAC_1BIT(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.25);
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
MC68328(config, m_lsi, 0, "maincpu"); // on-board peripherals
m_lsi->out_port_f().set(FUNC(palm_state::palm_port_f_out));
m_lsi->in_port_c().set(FUNC(palm_state::palm_port_c_in));
m_lsi->in_port_f().set(FUNC(palm_state::palm_port_f_in));
m_lsi->out_pwm().set("dac", FUNC(dac_bit_interface::write));
m_lsi->out_spim().set(FUNC(palm_state::palm_spim_out));
m_lsi->in_spim().set(FUNC(palm_state::palm_spim_in));
m_lsi->spim_xch_trigger().set(FUNC(palm_state::palm_spim_exchange));
}
static INPUT_PORTS_START( palm )