(MESS) fc100 : added cassette, sound, F4 display

This commit is contained in:
Robbbert 2014-04-20 12:29:03 +00:00
parent 2e61d01be8
commit 62fdedd01c

View File

@ -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 )