mirror of
https://github.com/holub/mame
synced 2025-07-04 09:28:51 +03:00
e0c6s46: add e0c6s48
New working systems ------------------- Angel Gotch (Japan) [hap, azya] Mothra no Tamagotch (Japan) [hap, azya]
This commit is contained in:
parent
7772559b28
commit
20f91f2974
@ -4,17 +4,17 @@
|
||||
|
||||
Seiko Epson E0C6200 CPU core and E0C62 MCU family
|
||||
|
||||
References:
|
||||
- 1998 MF297-06a E0C6200/E0C6200A Core CPU Manual
|
||||
- 1998 MF1049-01a E0C6S46 Technical Manual
|
||||
References:
|
||||
- 1998 MF297-06a E0C6200/E0C6200A Core CPU Manual
|
||||
- 1998 MF1049-01a E0C6S46 Technical Manual
|
||||
|
||||
E0C6200 is a CPU core used as the basis of many chips, it is not standalone.
|
||||
Seiko Epson often changed prefixes of their device names. Depending on when,
|
||||
the E0C6200 is known as SMC6200, E0C6200, S1C6200.
|
||||
E0C6200 is a CPU core used as the basis of many chips, it is not standalone.
|
||||
Seiko Epson often changed prefixes of their device names. Depending on when,
|
||||
the E0C6200 is known as SMC6200, E0C6200, S1C6200.
|
||||
|
||||
TODO:
|
||||
- RLC is part of the r,q opcodes and requires that r == q, what happens otherwise?
|
||||
- documentation is conflicting on whether or not the zero flag is set on RLC/RRC
|
||||
TODO:
|
||||
- RLC is part of the r,q opcodes and requires that r == q, what happens otherwise?
|
||||
- documentation is conflicting on whether or not the zero flag is set on RLC/RRC
|
||||
|
||||
*/
|
||||
|
||||
@ -839,7 +839,7 @@ void e0c6200_cpu_device::execute_one()
|
||||
|
||||
// illegal opcode
|
||||
default:
|
||||
logerror("unknown opcode $%03X at $%04X\n", m_op, m_prev_pc);
|
||||
op_illegal();
|
||||
break;
|
||||
|
||||
} // 0xff0
|
||||
|
@ -91,6 +91,7 @@ protected:
|
||||
void inc_x();
|
||||
void inc_y();
|
||||
void do_branch(int condition = 1);
|
||||
void op_illegal();
|
||||
|
||||
// opcode handlers
|
||||
u8 op_inc(u8 x);
|
||||
|
@ -116,6 +116,11 @@ void e0c6200_cpu_device::do_branch(int condition)
|
||||
m_pc = m_jpc | (m_op & 0xff);
|
||||
}
|
||||
|
||||
void e0c6200_cpu_device::op_illegal()
|
||||
{
|
||||
logerror("unknown opcode $%03X at $%04X\n", m_op, m_prev_pc);
|
||||
}
|
||||
|
||||
|
||||
// common opcodes (simpler ones are handled directly)
|
||||
// note: it is implied that all opcodes below except RRC take 7 clock cycles (5 already deducted)
|
||||
|
@ -2,16 +2,18 @@
|
||||
// copyright-holders:hap
|
||||
/*
|
||||
|
||||
Seiko Epson E0C6S46 MCU
|
||||
QFP5-128pin, see manual for pinout
|
||||
Seiko Epson E0C6S46 family
|
||||
|
||||
TODO:
|
||||
- finish i/o ports
|
||||
- serial interface
|
||||
- buzzer envelope addition
|
||||
- what happens if OSC3 is selected while OSCC (bit 2) is low?
|
||||
- K input interrupt can trigger if input is active while writing to the mask register
|
||||
- add mask options for ports (eg. buzzer on output port R4x is optional)
|
||||
E0C6S46: 6144x12 ROM, 640x4 RAM, 2*80x4 VRAM, LCD has 16 commons and 40 segments
|
||||
E0C6S48: 8192x12 ROM, 768x4 RAM, 2*102x4 VRAM, LCD has 16 commons and 51 segments
|
||||
|
||||
TODO:
|
||||
- finish i/o ports
|
||||
- serial interface
|
||||
- buzzer envelope addition
|
||||
- what happens if OSC3 is selected while OSCC (bit 2) is low?
|
||||
- K input interrupt can trigger if input is active while writing to the mask register
|
||||
- add mask options for ports (eg. buzzer on output port R4x is optional)
|
||||
|
||||
*/
|
||||
|
||||
@ -28,17 +30,23 @@ enum
|
||||
IRQREG_INPUT1
|
||||
};
|
||||
|
||||
// device definitions
|
||||
DEFINE_DEVICE_TYPE(E0C6S46, e0c6s46_device, "e0c6s46", "Seiko Epson E0C6S46")
|
||||
DEFINE_DEVICE_TYPE(E0C6S48, e0c6s48_device, "e0c6s48", "Seiko Epson E0C6S48")
|
||||
|
||||
|
||||
// internal memory maps
|
||||
void e0c6s46_device::e0c6s46_program(address_map &map)
|
||||
void e0c6s46_device::program_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x17ff).rom();
|
||||
}
|
||||
|
||||
void e0c6s48_device::program_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x1fff).rom();
|
||||
}
|
||||
|
||||
void e0c6s46_device::e0c6s46_data(address_map &map)
|
||||
void e0c6s46_device::data_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x027f).ram();
|
||||
map(0x0e00, 0x0e4f).ram().share(m_vram[0]);
|
||||
@ -46,20 +54,35 @@ void e0c6s46_device::e0c6s46_data(address_map &map)
|
||||
map(0x0f00, 0x0f7f).rw(FUNC(e0c6s46_device::io_r), FUNC(e0c6s46_device::io_w));
|
||||
}
|
||||
|
||||
void e0c6s48_device::data_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x02ff).ram();
|
||||
map(0x0e00, 0x0e65).ram().share(m_vram[0]);
|
||||
map(0x0e80, 0x0ee5).ram().share(m_vram[1]);
|
||||
map(0x0f00, 0x0f7f).rw(FUNC(e0c6s48_device::io_r), FUNC(e0c6s48_device::io_w));
|
||||
}
|
||||
|
||||
// device definitions
|
||||
e0c6s46_device::e0c6s46_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
e0c6200_cpu_device(mconfig, E0C6S46, tag, owner, clock, address_map_constructor(FUNC(e0c6s46_device::e0c6s46_program), this), address_map_constructor(FUNC(e0c6s46_device::e0c6s46_data), this)),
|
||||
|
||||
// constructor
|
||||
e0c6s46_device::e0c6s46_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor program, address_map_constructor data) :
|
||||
e0c6200_cpu_device(mconfig, type, tag, owner, clock, program, data),
|
||||
m_vram(*this, "vram%u", 1U),
|
||||
m_osc3(0),
|
||||
m_write_segs(*this),
|
||||
m_write_contrast(*this),
|
||||
m_pixel_cb(*this),
|
||||
m_write_r(*this),
|
||||
m_read_p(*this, 0),
|
||||
m_write_p(*this)
|
||||
m_write_p(*this),
|
||||
m_osc3(0)
|
||||
{ }
|
||||
|
||||
e0c6s46_device::e0c6s46_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
e0c6s46_device(mconfig, E0C6S46, tag, owner, clock, address_map_constructor(FUNC(e0c6s46_device::program_map), this), address_map_constructor(FUNC(e0c6s46_device::data_map), this))
|
||||
{ }
|
||||
|
||||
e0c6s48_device::e0c6s48_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
e0c6s46_device(mconfig, E0C6S48, tag, owner, clock, address_map_constructor(FUNC(e0c6s48_device::program_map), this), address_map_constructor(FUNC(e0c6s48_device::data_map), this))
|
||||
{ }
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -78,9 +101,8 @@ void e0c6s46_device::device_start()
|
||||
m_core_256_handle = timer_alloc(FUNC(e0c6s46_device::core_256_cb), this);
|
||||
m_core_256_handle->adjust(attotime::from_ticks(64, m_osc1));
|
||||
m_prgtimer_handle = timer_alloc(FUNC(e0c6s46_device::prgtimer_cb), this);
|
||||
m_prgtimer_handle->adjust(attotime::never);
|
||||
m_buzzer_handle = timer_alloc(FUNC(e0c6s46_device::buzzer_cb), this);
|
||||
m_buzzer_handle->adjust(attotime::never);
|
||||
m_osc_change = timer_alloc(FUNC(e0c6s46_device::osc_change), this);
|
||||
m_lcd_driver = timer_alloc(FUNC(e0c6s46_device::lcd_driver_cb), this);
|
||||
m_lcd_driver->adjust(attotime::from_ticks(1024, m_osc1));
|
||||
|
||||
@ -226,9 +248,9 @@ void e0c6s46_device::execute_one()
|
||||
{
|
||||
// E0C6S46 has no support for SLP opcode
|
||||
if (m_op == 0xff9)
|
||||
return;
|
||||
|
||||
e0c6200_cpu_device::execute_one();
|
||||
op_illegal();
|
||||
else
|
||||
e0c6200_cpu_device::execute_one();
|
||||
}
|
||||
|
||||
|
||||
@ -394,6 +416,12 @@ TIMER_CALLBACK_MEMBER(e0c6s46_device::core_256_cb)
|
||||
clock_clktimer();
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(e0c6s46_device::osc_change)
|
||||
{
|
||||
// set MCU instruction clock on CLKCHG change
|
||||
set_clock((m_osc & 8) ? m_osc3 : m_osc1);
|
||||
}
|
||||
|
||||
|
||||
// clock-timer
|
||||
|
||||
@ -790,7 +818,12 @@ void e0c6s46_device::io_w(offs_t offset, u8 data)
|
||||
// d2: OSC3 on (high freq)
|
||||
// d3: clock source OSC1 or OSC3
|
||||
if ((m_osc ^ data) & 8)
|
||||
set_clock((data & 8) ? m_osc3 : m_osc1);
|
||||
{
|
||||
if (m_osc1 == m_osc3)
|
||||
logerror("io_w unhandled OSC change, PC=$%04X\n", m_prev_pc);
|
||||
else
|
||||
m_osc_change->adjust(attotime::zero);
|
||||
}
|
||||
m_osc = data;
|
||||
break;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// copyright-holders:hap
|
||||
/*
|
||||
|
||||
Seiko Epson E0C6S46 MCU
|
||||
Seiko Epson E0C6S46 family
|
||||
|
||||
*/
|
||||
|
||||
@ -11,6 +11,19 @@
|
||||
|
||||
#include "e0c6200.h"
|
||||
|
||||
// for the 2 K input ports, use set_input_line(line, state)
|
||||
enum
|
||||
{
|
||||
E0C6S46_LINE_K00 = 0,
|
||||
E0C6S46_LINE_K01,
|
||||
E0C6S46_LINE_K02,
|
||||
E0C6S46_LINE_K03,
|
||||
E0C6S46_LINE_K10,
|
||||
E0C6S46_LINE_K11,
|
||||
E0C6S46_LINE_K12,
|
||||
E0C6S46_LINE_K13
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
E0C6S46_PORT_R0X = 0,
|
||||
@ -28,18 +41,7 @@ enum
|
||||
E0C6S46_PORT_P3X
|
||||
};
|
||||
|
||||
// for the 2 K input ports, use set_input_line(line, state)
|
||||
enum
|
||||
{
|
||||
E0C6S46_LINE_K00 = 0,
|
||||
E0C6S46_LINE_K01,
|
||||
E0C6S46_LINE_K02,
|
||||
E0C6S46_LINE_K03,
|
||||
E0C6S46_LINE_K10,
|
||||
E0C6S46_LINE_K11,
|
||||
E0C6S46_LINE_K12,
|
||||
E0C6S46_LINE_K13
|
||||
};
|
||||
// no pinout diagram here, refer to the manual
|
||||
|
||||
|
||||
class e0c6s46_device : public e0c6200_cpu_device
|
||||
@ -72,6 +74,8 @@ public:
|
||||
void set_osc3(u32 osc) { m_osc3 = osc; }
|
||||
|
||||
protected:
|
||||
e0c6s46_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor program, address_map_constructor data);
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override ATTR_COLD;
|
||||
virtual void device_reset() override ATTR_COLD;
|
||||
@ -81,20 +85,18 @@ protected:
|
||||
virtual void execute_one() override;
|
||||
virtual bool check_interrupt() override;
|
||||
|
||||
void e0c6s46_data(address_map &map) ATTR_COLD;
|
||||
void e0c6s46_program(address_map &map) ATTR_COLD;
|
||||
|
||||
private:
|
||||
u8 io_r(offs_t offset);
|
||||
void io_w(offs_t offset, u8 data);
|
||||
|
||||
required_shared_ptr_array<u8, 2> m_vram;
|
||||
|
||||
private:
|
||||
void program_map(address_map &map) ATTR_COLD;
|
||||
void data_map(address_map &map) ATTR_COLD;
|
||||
|
||||
u8 m_irqflag[6];
|
||||
u8 m_irqmask[6];
|
||||
u8 m_osc;
|
||||
u32 m_osc1;
|
||||
u32 m_osc3;
|
||||
u8 m_svd;
|
||||
|
||||
// lcd driver
|
||||
@ -167,9 +169,25 @@ private:
|
||||
void schedule_buzzer();
|
||||
void reset_buzzer();
|
||||
void clock_bz_1shot();
|
||||
|
||||
u32 m_osc1;
|
||||
u32 m_osc3;
|
||||
emu_timer *m_osc_change;
|
||||
TIMER_CALLBACK_MEMBER(osc_change);
|
||||
};
|
||||
|
||||
class e0c6s48_device : public e0c6s46_device
|
||||
{
|
||||
public:
|
||||
e0c6s48_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
private:
|
||||
void program_map(address_map &map) ATTR_COLD;
|
||||
void data_map(address_map &map) ATTR_COLD;
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(E0C6S46, e0c6s46_device)
|
||||
DECLARE_DEVICE_TYPE(E0C6S48, e0c6s48_device)
|
||||
|
||||
#endif // MAME_CPU_E0C6200_E0C6S46_H
|
||||
|
@ -11,8 +11,8 @@ to play the games for a longer time. For the drivers that don't have an SVG
|
||||
screen, use -prescale or -nofilter to disable bilinear filtering.
|
||||
|
||||
TODO:
|
||||
- add the Mothra Tamagotchi version that was recently dumped (has a E0C6S48)
|
||||
- SVGs could be more accurate? it seems they're handmade instead of a 1:1 scan
|
||||
like for eg. the Game & Watch LCDs
|
||||
- alienfev unmapped reads/writes, or are they harmless?
|
||||
- add LCD deflicker like hh_sm510? see venusdm for example
|
||||
- hook up LCD contrast, does any game use it? (eg. for fade-out)
|
||||
@ -51,7 +51,7 @@ protected:
|
||||
void lcd_segment_w(offs_t offset, u8 data) { m_out_x[offset & 0xf][offset >> 4] = data; }
|
||||
|
||||
required_device<e0c6s46_device> m_maincpu;
|
||||
output_finder<16, 40> m_out_x;
|
||||
output_finder<16, 51> m_out_x; // max 16 * 51
|
||||
};
|
||||
|
||||
void hh_e0c6x_state::machine_start()
|
||||
@ -93,7 +93,7 @@ INPUT_CHANGED_MEMBER(hh_e0c6x_state::input_changed)
|
||||
* Seiko Epson E0C6S46 MCU under epoxy
|
||||
* 32*16 LCD screen + 8 custom segments, 1-bit sound
|
||||
|
||||
Generation 2 is on the exact same hardware
|
||||
Generation 2 is on the exact same hardware.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
@ -164,13 +164,87 @@ ROM_END
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Bandai Tamagotchi Angel (aka Angel Gotch in Japan)
|
||||
* Seiko Epson E0C6S48
|
||||
* 32*16 LCD screen + 8 custom segments, 1-bit sound
|
||||
|
||||
Mothra no Tamagotch is on similar hardware.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
class tamaang_state : public hh_e0c6x_state
|
||||
{
|
||||
public:
|
||||
tamaang_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
hh_e0c6x_state(mconfig, type, tag)
|
||||
{ }
|
||||
|
||||
void tamaang(machine_config &config);
|
||||
};
|
||||
|
||||
// inputs
|
||||
|
||||
static INPUT_PORTS_START( tamaang )
|
||||
PORT_INCLUDE( tama )
|
||||
|
||||
PORT_MODIFY("K0")
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_CHANGED_CB(3) PORT_NAME("Vibration Sensor")
|
||||
INPUT_PORTS_END
|
||||
|
||||
// config
|
||||
|
||||
void tamaang_state::tamaang(machine_config &config)
|
||||
{
|
||||
// basic machine hardware
|
||||
E0C6S48(config, m_maincpu, 32.768_kHz_XTAL);
|
||||
m_maincpu->set_osc3(1'000'000);
|
||||
m_maincpu->write_r<4>().set("speaker", FUNC(speaker_sound_device::level_w)).bit(3);
|
||||
m_maincpu->write_segs().set(FUNC(tamaang_state::lcd_segment_w));
|
||||
|
||||
// video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_SVG));
|
||||
screen.set_refresh_hz(32);
|
||||
screen.set_size(1119, 1080);
|
||||
screen.set_visarea_full();
|
||||
|
||||
config.set_default_layout(layout_hh_e0c6x_lcd);
|
||||
|
||||
// sound hardware
|
||||
SPEAKER(config, "mono").front_center();
|
||||
SPEAKER_SOUND(config, "speaker").add_route(ALL_OUTPUTS, "mono", 0.25);
|
||||
}
|
||||
|
||||
// roms
|
||||
|
||||
ROM_START( tamaang )
|
||||
ROM_REGION( 0x4000, "maincpu", 0 )
|
||||
ROM_LOAD( "tamaang.bin", 0x0000, 0x4000, CRC(87bcb59f) SHA1(f5899bb7717756ac581451cf16cf97d909961c5c) )
|
||||
|
||||
ROM_REGION( 139978, "screen", 0)
|
||||
ROM_LOAD( "tamaang.svg", 0, 139978, CRC(76f27f06) SHA1(b416275a12173316e053fa994c5fd68a4d5c1a5c) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( tamamot )
|
||||
ROM_REGION( 0x4000, "maincpu", 0 )
|
||||
ROM_LOAD( "tamamot.bin", 0x0000, 0x4000, CRC(85e4bee9) SHA1(74c1f6761724b7cbda8bca3113db78586b786d2d) )
|
||||
|
||||
ROM_REGION( 138289, "screen", 0)
|
||||
ROM_LOAD( "tamamot.svg", 0, 138289, CRC(4e8210c2) SHA1(522536ae5bf744889c0d028c3a292bdf649f81e3) )
|
||||
ROM_END
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Epoch Chibi Pachi: Alien Fever
|
||||
* Seiko Epson E0C6S46 MCU
|
||||
* 39*16 LCD screen, 1-bit sound
|
||||
|
||||
It's a Pachislot keychain game, the MCU runs on the higher-speed OSC3.
|
||||
It's a Pachislot keychain game, the MCU constantly runs on the higher-speed OSC3.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
@ -200,8 +274,8 @@ void alienfev_state::alienfev(machine_config &config)
|
||||
{
|
||||
// basic machine hardware
|
||||
E0C6S46(config, m_maincpu, 32.768_kHz_XTAL);
|
||||
m_maincpu->write_r<4>().set("speaker", FUNC(speaker_sound_device::level_w)).bit(3);
|
||||
m_maincpu->set_osc3(1'000'000);
|
||||
m_maincpu->write_r<4>().set("speaker", FUNC(speaker_sound_device::level_w)).bit(3);
|
||||
|
||||
// video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
|
||||
@ -310,6 +384,8 @@ ROM_END
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
|
||||
SYST( 1997, tama, 0, 0, tama, tama, tama_state, empty_init, "Bandai", "Tamagotchi (Gen. 1, World)", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK )
|
||||
SYST( 1997, tamag2, 0, 0, tama, tama, tama_state, empty_init, "Bandai", "Tamagotchi (Gen. 2, Japan)", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK )
|
||||
SYST( 1997, tamaang, 0, 0, tamaang, tamaang, tamaang_state, empty_init, "Bandai", "Angel Gotch (Japan)", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK )
|
||||
SYST( 1997, tamamot, 0, 0, tamaang, tama, tamaang_state, empty_init, "Bandai", "Mothra no Tamagotch (Japan)", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK )
|
||||
|
||||
SYST( 1997, alienfev, 0, 0, alienfev, alienfev, alienfev_state, empty_init, "Epoch", "Chibi Pachi: Alien Fever", MACHINE_SUPPORTS_SAVE )
|
||||
|
||||
|
@ -19148,7 +19148,9 @@ qkspeller // National Semiconductor
|
||||
@source:handheld/hh_e0c6x.cpp
|
||||
alienfev // Epoch
|
||||
tama // Bandai
|
||||
tamaang // Bandai
|
||||
tamag2 // Bandai
|
||||
tamamot // Bandai
|
||||
venusdm // Nikko
|
||||
|
||||
@source:handheld/hh_hmcs40.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user