mirror of
https://github.com/holub/mame
synced 2025-10-06 17:08:28 +03:00
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:
parent
80807d7453
commit
b7a49aff4a
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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 ¶ms);
|
||||
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 )
|
||||
|
Loading…
Reference in New Issue
Block a user