mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
(MESS) fc100 : added cassette, sound, F4 display
This commit is contained in:
parent
2e61d01be8
commit
62fdedd01c
@ -11,11 +11,9 @@ Shift-Run to BREAK out of CLOAD.
|
||||
Cassette uses the uart.
|
||||
|
||||
TODO:
|
||||
- Sound
|
||||
- Cassette
|
||||
- Hookup Graphics modes
|
||||
- Unknown i/o ports
|
||||
- Does it have a cart slot?
|
||||
- Does it have a cart slot? Yes. What address?
|
||||
- Expansion?
|
||||
- It misses keystrokes if you type quickly
|
||||
|
||||
@ -27,6 +25,10 @@ TODO:
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "video/mc6847.h"
|
||||
#include "machine/i8251.h"
|
||||
#include "machine/clock.h"
|
||||
#include "sound/ay8910.h"
|
||||
#include "imagedev/cassette.h"
|
||||
#include "sound/wave.h"
|
||||
|
||||
|
||||
class fc100_state : public driver_device
|
||||
@ -36,26 +38,30 @@ public:
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_s68047p(*this, "s68047p")
|
||||
, m_videoram(*this, "videoram")
|
||||
, m_p_videoram(*this, "videoram")
|
||||
, m_cass(*this, "cassette")
|
||||
, m_uart(*this, "uart")
|
||||
{ }
|
||||
|
||||
DECLARE_READ8_MEMBER(mc6847_videoram_r);
|
||||
DECLARE_WRITE8_MEMBER(port31_w);
|
||||
DECLARE_WRITE8_MEMBER(port33_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(irq_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(txdata_callback);
|
||||
DECLARE_WRITE_LINE_MEMBER(uart_clock_w);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(timer_c);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(timer_p);
|
||||
|
||||
UINT8 *m_p_chargen;
|
||||
static UINT8 get_char_rom(running_machine &machine, UINT8 ch, int line)
|
||||
{
|
||||
fc100_state *state = machine.driver_data<fc100_state>();
|
||||
return state->m_p_chargen[(ch&0x7F)*16+line];
|
||||
return state->m_p_chargen[ch*16+line];
|
||||
}
|
||||
private:
|
||||
virtual void machine_start();
|
||||
virtual void machine_reset();
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<s68047_device> m_s68047p;
|
||||
required_shared_ptr<UINT8> m_videoram;
|
||||
|
||||
// graphics signals
|
||||
UINT8 m_ag;
|
||||
UINT8 m_gm2;
|
||||
@ -65,6 +71,14 @@ private:
|
||||
UINT8 m_css;
|
||||
UINT8 m_intext;
|
||||
UINT8 m_inv;
|
||||
UINT8 m_cass_data[4];
|
||||
bool m_cass_state;
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<s68047_device> m_s68047p;
|
||||
required_shared_ptr<UINT8> m_p_videoram;
|
||||
required_device<cassette_image_device> m_cass;
|
||||
required_device<i8251_device> m_uart;
|
||||
};
|
||||
|
||||
|
||||
@ -94,8 +108,13 @@ static ADDRESS_MAP_START( fc100_io, AS_IO, 8, fc100_state )
|
||||
AM_RANGE(0x0D, 0x0D) AM_READ_PORT("0D")
|
||||
AM_RANGE(0x0E, 0x0E) AM_READ_PORT("0E")
|
||||
AM_RANGE(0x0F, 0x0F) AM_READ_PORT("0F")
|
||||
AM_RANGE(0x21, 0x21) AM_DEVWRITE("psg", ay8910_device, data_w)
|
||||
AM_RANGE(0x22, 0x22) AM_DEVREAD("psg", ay8910_device, data_r)
|
||||
AM_RANGE(0x23, 0x23) AM_DEVWRITE("psg", ay8910_device, address_w)
|
||||
AM_RANGE(0x31, 0x31) AM_WRITE(port31_w)
|
||||
AM_RANGE(0x33, 0x33) AM_WRITE(port33_w)
|
||||
// AM_RANGE(0x60, 0x61) writes 0 to both ports at boot
|
||||
// AM_RANGE(0x70, 0x70) each screen character also gets written here
|
||||
AM_RANGE(0x70, 0x70) AM_WRITENOP // each screen character also gets written here
|
||||
// AM_RANGE(0x71, 0x71) writes 0 at boot
|
||||
AM_RANGE(0xb0, 0xb0) AM_DEVREADWRITE("uart", i8251_device, data_r, data_w)
|
||||
AM_RANGE(0xb8, 0xb8) AM_DEVREADWRITE("uart", i8251_device, status_r, control_w)
|
||||
@ -204,33 +223,7 @@ static INPUT_PORTS_START( fc100 )
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
void fc100_state::machine_start()
|
||||
{
|
||||
m_ag = 0;
|
||||
m_gm2 = 0;
|
||||
m_gm1 = 0;
|
||||
m_gm0 = 0;
|
||||
m_as = 0;
|
||||
m_css = 0;
|
||||
m_intext = 0;
|
||||
m_inv = 0;
|
||||
|
||||
save_item(NAME(m_ag));
|
||||
save_item(NAME(m_gm2));
|
||||
save_item(NAME(m_gm1));
|
||||
save_item(NAME(m_gm0));
|
||||
save_item(NAME(m_as));
|
||||
save_item(NAME(m_css));
|
||||
save_item(NAME(m_intext));
|
||||
save_item(NAME(m_inv));
|
||||
}
|
||||
|
||||
|
||||
void fc100_state::machine_reset()
|
||||
{
|
||||
m_p_chargen = memregion("chargen")->base();
|
||||
}
|
||||
|
||||
//********************* AUDIO **********************************
|
||||
#if 0
|
||||
WRITE8_MEMBER( fc100_state::ay_port_a_w )
|
||||
{
|
||||
@ -257,18 +250,19 @@ WRITE8_MEMBER( fc100_state::ay_port_b_w )
|
||||
{
|
||||
//logerror("ay_port_b_w: %02X\n", data);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static const ay8910_interface fc100_ay8910_interface =
|
||||
static const ay8910_interface ay8910_intf =
|
||||
{
|
||||
AY8910_LEGACY_OUTPUT,
|
||||
AY8910_DEFAULT_LOADS,
|
||||
DEVCB_DRIVER_MEMBER(fc100_state, ay_port_a_r),
|
||||
DEVCB_DRIVER_MEMBER(fc100_state, ay_port_b_r),
|
||||
DEVCB_DRIVER_MEMBER(fc100_state, ay_port_a_w),
|
||||
DEVCB_DRIVER_MEMBER(fc100_state, ay_port_b_w)
|
||||
DEVCB_NULL,//DEVCB_DRIVER_MEMBER(fc100_state, ay_port_a_r),
|
||||
DEVCB_NULL,//DEVCB_DRIVER_MEMBER(fc100_state, ay_port_b_r),
|
||||
DEVCB_NULL,//DEVCB_DRIVER_MEMBER(fc100_state, ay_port_a_w),
|
||||
DEVCB_NULL,//DEVCB_DRIVER_MEMBER(fc100_state, ay_port_b_w)
|
||||
};
|
||||
#endif
|
||||
|
||||
//******************** VIDEO **********************************
|
||||
|
||||
READ8_MEMBER( fc100_state::mc6847_videoram_r )
|
||||
{
|
||||
@ -280,18 +274,18 @@ READ8_MEMBER( fc100_state::mc6847_videoram_r )
|
||||
{
|
||||
// 256 x 192 / 6KB
|
||||
offset = ( ( offset & 0x1fc0 ) >> 1 ) | ( offset & 0x1f );
|
||||
return m_videoram[offset % 0xc00];
|
||||
return m_p_videoram[offset % 0xc00];
|
||||
}
|
||||
else
|
||||
{
|
||||
// 256 x 96 / 3KB
|
||||
return m_videoram[offset % 0xc00];
|
||||
return m_p_videoram[offset % 0xc00];
|
||||
}
|
||||
}
|
||||
|
||||
// Standard text
|
||||
UINT8 data = m_videoram[offset];
|
||||
UINT8 attr = m_videoram[offset+0x200];
|
||||
UINT8 data = m_p_videoram[offset];
|
||||
UINT8 attr = m_p_videoram[offset+0x200];
|
||||
|
||||
m_s68047p->inv_w( BIT( attr, 0 ));
|
||||
|
||||
@ -321,6 +315,111 @@ static const mc6847_interface fc100_mc6847_interface =
|
||||
&fc100_state::get_char_rom
|
||||
};
|
||||
|
||||
/* F4 Character Displayer */
|
||||
static const gfx_layout u53_charlayout =
|
||||
{
|
||||
7, 15, /* 7 x 15 characters */
|
||||
256, /* 256 characters */
|
||||
1, /* 1 bits per pixel */
|
||||
{ 0 }, /* no bitplanes */
|
||||
/* x offsets */
|
||||
{ 1, 2, 3, 4, 5, 6, 7 },
|
||||
/* y offsets */
|
||||
{ 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
|
||||
8*16 /* every char takes 16 bytes */
|
||||
};
|
||||
|
||||
static GFXDECODE_START( fc100 )
|
||||
GFXDECODE_ENTRY( "chargen", 0x0000, u53_charlayout, 0, 1 )
|
||||
GFXDECODE_END
|
||||
|
||||
//********************** UART/CASSETTE ***********************************
|
||||
|
||||
WRITE8_MEMBER( fc100_state::port31_w )
|
||||
{
|
||||
if (data == 8)
|
||||
m_cass->change_state(CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( fc100_state::port33_w )
|
||||
{
|
||||
if (data == 0)
|
||||
m_cass->change_state(CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( fc100_state::txdata_callback )
|
||||
{
|
||||
m_cass_state = state;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( fc100_state::uart_clock_w )
|
||||
{
|
||||
m_uart->write_txc(state);
|
||||
m_uart->write_rxc(state);
|
||||
}
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER( fc100_state::timer_c )
|
||||
{
|
||||
m_cass_data[3]++;
|
||||
|
||||
if (m_cass_state)
|
||||
m_cass->output(BIT(m_cass_data[3], 0) ? -1.0 : +1.0); // 2400Hz
|
||||
else
|
||||
m_cass->output(BIT(m_cass_data[3], 1) ? -1.0 : +1.0); // 1200Hz
|
||||
}
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER( fc100_state::timer_p)
|
||||
{
|
||||
/* cassette - turn 1200/2400Hz to a bit */
|
||||
m_cass_data[1]++;
|
||||
UINT8 cass_ws = (m_cass->input() > +0.03) ? 1 : 0;
|
||||
|
||||
if (cass_ws != m_cass_data[0])
|
||||
{
|
||||
m_cass_data[0] = cass_ws;
|
||||
m_uart->write_rxd((m_cass_data[1] < 12) ? 1 : 0);
|
||||
m_cass_data[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static const cassette_interface fc100_cassette_interface =
|
||||
{
|
||||
cassette_default_formats,
|
||||
NULL,
|
||||
(cassette_state) (CASSETTE_PLAY | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED),
|
||||
"fc100_cass",
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
//******************** MACHINE ******************************
|
||||
|
||||
void fc100_state::machine_start()
|
||||
{
|
||||
m_ag = 0;
|
||||
m_gm2 = 0;
|
||||
m_gm1 = 0;
|
||||
m_gm0 = 0;
|
||||
m_as = 0;
|
||||
m_css = 0;
|
||||
m_intext = 0;
|
||||
m_inv = 0;
|
||||
|
||||
save_item(NAME(m_ag));
|
||||
save_item(NAME(m_gm2));
|
||||
save_item(NAME(m_gm1));
|
||||
save_item(NAME(m_gm0));
|
||||
save_item(NAME(m_as));
|
||||
save_item(NAME(m_css));
|
||||
save_item(NAME(m_intext));
|
||||
save_item(NAME(m_inv));
|
||||
}
|
||||
|
||||
void fc100_state::machine_reset()
|
||||
{
|
||||
m_p_chargen = memregion("chargen")->base();
|
||||
}
|
||||
|
||||
static MACHINE_CONFIG_START( fc100, fc100_state )
|
||||
/* basic machine hardware */
|
||||
@ -332,23 +431,39 @@ static MACHINE_CONFIG_START( fc100, fc100_state )
|
||||
MCFG_MC6847_ADD("s68047p", S68047, 9159090/3, fc100_mc6847_interface ) // Clock not verified
|
||||
MCFG_MC6847_FSYNC_CALLBACK(WRITELINE(fc100_state, irq_w))
|
||||
MCFG_SCREEN_MC6847_NTSC_ADD("screen", "s68047p")
|
||||
MCFG_GFXDECODE_ADD("gfxdecode", "f4palette", fc100)
|
||||
MCFG_PALETTE_ADD_MONOCHROME_AMBER("f4palette")
|
||||
|
||||
/* sound hardware */
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette")
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
|
||||
MCFG_SOUND_ADD("psg", AY8910, 9159090/3/2) /* AY-3-8910 - clock not verified */
|
||||
MCFG_SOUND_CONFIG(ay8910_intf)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.50)
|
||||
|
||||
/* Devices */
|
||||
MCFG_CASSETTE_ADD("cassette", default_cassette_interface) //fc100_cassette_interface)
|
||||
MCFG_DEVICE_ADD("uart", I8251, 0)
|
||||
MCFG_I8251_TXD_HANDLER(WRITELINE(fc100_state, txdata_callback))
|
||||
MCFG_DEVICE_ADD("uart_clock", CLOCK, XTAL_4_9152MHz/16/16) // gives 19200
|
||||
MCFG_CLOCK_SIGNAL_HANDLER(WRITELINE(fc100_state, uart_clock_w))
|
||||
MCFG_TIMER_DRIVER_ADD_PERIODIC("timer_c", fc100_state, timer_c, attotime::from_hz(4800))
|
||||
MCFG_TIMER_DRIVER_ADD_PERIODIC("timer_p", fc100_state, timer_p, attotime::from_hz(40000))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
/* ROM definition */
|
||||
ROM_START( fc100 )
|
||||
ROM_REGION( 0x6000, "roms", 0 )
|
||||
ROM_LOAD( "08-01.u48", 0x0000, 0x2000, CRC(24e78e75) SHA1(13121706544256a702635448ed2950a75c13f491) )
|
||||
ROM_LOAD( "08-02.u49", 0x2000, 0x2000, CRC(e14fc7e9) SHA1(9c5821e65c1efe698e25668d24c36929ea4c3ad7) )
|
||||
ROM_LOAD( "06-03.u50", 0x4000, 0x2000, CRC(d783c84e) SHA1(6d1bf53995e08724d5ecc24198cdda4442eb2eb9) )
|
||||
ROM_LOAD( "08-01.u48", 0x0000, 0x2000, CRC(24e78e75) SHA1(13121706544256a702635448ed2950a75c13f491) )
|
||||
ROM_LOAD( "08-02.u49", 0x2000, 0x2000, CRC(e14fc7e9) SHA1(9c5821e65c1efe698e25668d24c36929ea4c3ad7) )
|
||||
ROM_LOAD( "06-03.u50", 0x4000, 0x2000, CRC(d783c84e) SHA1(6d1bf53995e08724d5ecc24198cdda4442eb2eb9) )
|
||||
|
||||
ROM_REGION( 0x1000, "chargen", 0 )
|
||||
ROM_LOAD( "cgen.u53", 0x0000, 0x1000, CRC(2de75b7f) SHA1(464369d98cbae92ffa322ebaa4404cf5b26825f1) )
|
||||
ROM_LOAD( "cg-04-01.u53", 0x0000, 0x1000, CRC(2de75b7f) SHA1(464369d98cbae92ffa322ebaa4404cf5b26825f1) )
|
||||
ROM_END
|
||||
|
||||
/* Driver */
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME STATUS FLAGS */
|
||||
CONS( 1982, fc100, 0, 0, fc100, fc100, driver_device, 0, "Goldstar", "Famicom FC-100", GAME_IS_SKELETON )
|
||||
CONS( 1982, fc100, 0, 0, fc100, fc100, driver_device, 0, "Goldstar", "Famicom FC-100", GAME_NOT_WORKING )
|
||||
|
Loading…
Reference in New Issue
Block a user