Enable proper save stating for bfm_bd1 machine which should fix MT bug#03990 as well. [James Wallace]

This commit is contained in:
Scott Stone 2012-06-10 17:23:15 +00:00
parent a8be0f08b8
commit fafa5a515c
6 changed files with 498 additions and 505 deletions

View File

@ -104,7 +104,11 @@ class bfm_sc1_state : public driver_device
{
public:
bfm_sc1_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag) { }
: driver_device(mconfig, type, tag),
m_vfd0(*this, "vfd0")
{ }
optional_device<bfm_bd1_t> m_vfd0;
int m_mmtr_latch;
int m_triac_latch;
@ -162,6 +166,7 @@ public:
DECLARE_READ8_MEMBER(nec_r);
DECLARE_WRITE8_MEMBER(nec_reset_w);
DECLARE_WRITE8_MEMBER(nec_latch_w);
};
#define VFD_RESET 0x20
@ -347,21 +352,16 @@ WRITE8_MEMBER(bfm_sc1_state::vfd_w)
{ // vfd reset line changed
if ( !(data & VFD_RESET) )
{ // reset the vfd
BFM_BD1_reset(0);
BFM_BD1_reset(1);
BFM_BD1_reset(2);
m_vfd0->reset();
}
}
if ( changed & VFD_CLOCK1 )
{ // clock line changed
if ( !(data & VFD_CLOCK1) && (data & VFD_RESET) )
{ // new data clocked into vfd
BFM_BD1_shift_data(0, data & VFD_DATA );
m_vfd0->shift_data(data & VFD_DATA );
}
}
BFM_BD1_draw(0);
BFM_BD1_draw(1);
BFM_BD1_draw(2);
}
}
@ -633,7 +633,6 @@ READ8_MEMBER(bfm_sc1_state::vid_uart_ctrl_r)
static MACHINE_RESET( bfm_sc1 )
{
bfm_sc1_state *state = machine.driver_data<bfm_sc1_state>();
BFM_BD1_init(0);
state->m_vfd_latch = 0;
state->m_mmtr_latch = 0;
state->m_triac_latch = 0;
@ -649,9 +648,7 @@ static MACHINE_RESET( bfm_sc1 )
state->m_mux2_datahi = 0;
state->m_mux2_input = 0;
BFM_BD1_reset(0); // reset display1
BFM_BD1_reset(1); // reset display2
BFM_BD1_reset(2); // reset display3
state->m_vfd0->reset();
// reset stepper motors /////////////////////////////////////////////////////////////
{
@ -1095,6 +1092,7 @@ static MACHINE_CONFIG_START( scorpion1, bfm_sc1_state )
MCFG_CPU_PERIODIC_INT(timer_irq, 1000 ) // generate 1000 IRQ's per second
MCFG_WATCHDOG_TIME_INIT(PERIOD_OF_555_MONOSTABLE(120000,100e-9))
MCFG_BFMBD1_ADD("vfd0",0)
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("aysnd",AY8912, MASTER_CLOCK/4)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
@ -1168,26 +1166,18 @@ static DRIVER_INIT(toppoker)
sc1_common_init(machine,3,1, 3);
adder2_decode_char_roms(machine); // decode GFX roms
MechMtr_config(machine,8);
BFM_BD1_init(0);
}
static DRIVER_INIT(lotse)
{
sc1_common_init(machine,6,1, 3);
MechMtr_config(machine,8);
BFM_BD1_init(0);
BFM_BD1_init(1);
}
static DRIVER_INIT(lotse_bank0)
{
sc1_common_init(machine,6,1, 0);
MechMtr_config(machine,8);
BFM_BD1_init(0);
BFM_BD1_init(1);
}
@ -1195,18 +1185,12 @@ static DRIVER_INIT(nocrypt)
{
sc1_common_init(machine,6,0, 3);
MechMtr_config(machine,8);
BFM_BD1_init(0);
BFM_BD1_init(1);
}
static DRIVER_INIT(nocrypt_bank0)
{
sc1_common_init(machine,6,0, 0);
MechMtr_config(machine,8);
BFM_BD1_init(0);
BFM_BD1_init(1);
}
@ -1216,8 +1200,6 @@ static DRIVER_INIT(rou029)
{
sc1_common_init(machine,6,0, 3);
MechMtr_config(machine,8);
BFM_BD1_init(0);
}
/////////////////////////////////////////////////////////////////////////////////////
@ -1228,8 +1210,6 @@ static DRIVER_INIT(clatt)
sc1_common_init(machine,6,1, 3);
MechMtr_config(machine,8);
BFM_BD1_init(0);
Scorpion1_SetSwitchState(state,3,2,1);
Scorpion1_SetSwitchState(state,3,3,1);
Scorpion1_SetSwitchState(state,3,6,1);

View File

@ -178,7 +178,13 @@ class bfm_sc2_state : public driver_device
{
public:
bfm_sc2_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag) { }
: driver_device(mconfig, type, tag),
m_vfd0(*this, "vfd0"),
m_vfd1(*this, "vfd1")
{ }
optional_device<bfm_bd1_t> m_vfd0;
optional_device<bfm_bd1_t> m_vfd1;
int m_sc2gui_update_mmtr;
UINT8 *m_nvram;
@ -186,8 +192,6 @@ public:
UINT8 m_e2ram[1024];
int m_mmtr_latch;
int m_triac_latch;
int m_vfd1_latch;
int m_vfd2_latch;
int m_irq_status;
int m_optic_pattern;
int m_uart1_data;
@ -323,8 +327,6 @@ static void e2ram_reset(running_machine &machine);
static void on_scorpion2_reset(running_machine &machine)
{
bfm_sc2_state *state = machine.driver_data<bfm_sc2_state>();
state->m_vfd1_latch = 0;
state->m_vfd2_latch = 0;
state->m_mmtr_latch = 0;
state->m_triac_latch = 0;
state->m_irq_status = 0;
@ -351,9 +353,6 @@ static void on_scorpion2_reset(running_machine &machine)
state->m_slide_states[4] = 0;
state->m_slide_states[5] = 0;
BFM_BD1_reset(0); // reset display1
BFM_BD1_reset(1); // reset display2
e2ram_reset(machine);
devtag_reset(machine, "ymsnd");
@ -944,19 +943,15 @@ WRITE8_MEMBER(bfm_sc2_state::payout_select_w)
WRITE8_MEMBER(bfm_sc2_state::vfd2_data_w)
{
m_vfd2_latch = data;
BFM_BD1_newdata(1, data);
BFM_BD1_draw(1);
m_vfd1->write_char(data);
}
///////////////////////////////////////////////////////////////////////////
WRITE8_MEMBER(bfm_sc2_state::vfd_reset_w)
{
BFM_BD1_reset(0); // reset both VFD's
BFM_BD1_reset(1);
BFM_BD1_draw(0);
BFM_BD1_draw(1);
m_vfd0->reset();
m_vfd1->reset();
}
///////////////////////////////////////////////////////////////////////////
@ -1177,7 +1172,6 @@ READ8_MEMBER(bfm_sc2_state::vfd_status_r)
WRITE8_MEMBER(bfm_sc2_state::vfd1_data_w)
{
m_vfd1_latch = data;
if (machine().device("matrix"))
{
@ -1185,8 +1179,7 @@ WRITE8_MEMBER(bfm_sc2_state::vfd1_data_w)
}
else
{
BFM_BD1_newdata(0, data);
BFM_BD1_draw(0);
m_vfd0->write_char(data);
}
}
@ -1414,25 +1407,14 @@ static int read_e2ram(running_machine &machine)
static MACHINE_RESET( init )
{
// reset adder2
MACHINE_RESET_CALL(adder2);
bfm_sc2_state *state = machine.driver_data<bfm_sc2_state>();
// reset the board //////////////////////////////////////////////////////
on_scorpion2_reset(machine);
BFM_BD1_init(0);
BFM_BD1_init(1);
}
state->m_vfd0->reset();
state->m_vfd1->reset();
static SCREEN_UPDATE_IND16( addersc2 )
{
bfm_sc2_state *state = screen.machine().driver_data<bfm_sc2_state>();
if ( state->m_sc2_show_door )
{
output_set_value("door",( Scorpion2_GetSwitchState(screen.machine(),state->m_sc2_door_state>>4, state->m_sc2_door_state & 0x0F) ) );
}
return SCREEN_UPDATE16_CALL(adder2);
}
@ -2164,6 +2146,8 @@ static MACHINE_CONFIG_START( scorpion2_vid, bfm_sc2_state )
MCFG_CPU_PERIODIC_INT(timer_irq, 1000) // generate 1000 IRQ's per second
MCFG_WATCHDOG_TIME_INIT(PERIOD_OF_555_MONOSTABLE(120000,100e-9))
MCFG_BFMBD1_ADD("vfd0",0)
MCFG_NVRAM_ADD_0FILL("nvram")
MCFG_NVRAM_HANDLER(bfm_sc2)
MCFG_DEFAULT_LAYOUT(layout_bfm_sc2)
@ -2172,9 +2156,9 @@ static MACHINE_CONFIG_START( scorpion2_vid, bfm_sc2_state )
MCFG_SCREEN_SIZE( 400, 280)
MCFG_SCREEN_VISIBLE_AREA( 0, 400-1, 0, 280-1)
MCFG_SCREEN_REFRESH_RATE(50)
MCFG_SCREEN_UPDATE_STATIC(addersc2)
MCFG_VIDEO_START( adder2)
MCFG_SCREEN_UPDATE_STATIC(adder2)
MCFG_VIDEO_RESET( adder2)
MCFG_PALETTE_LENGTH(16)
@ -2609,9 +2593,11 @@ static const bfmdm01_interface dm01_interface =
/* machine init (called only once) */
static MACHINE_RESET( awp_init )
{
bfm_sc2_state *state = machine.driver_data<bfm_sc2_state>();
on_scorpion2_reset(machine);
BFM_BD1_init(0);
BFM_BD1_init(1);
state->m_vfd0->reset();
state->m_vfd1->reset();
}
@ -3700,6 +3686,9 @@ static MACHINE_CONFIG_START( scorpion2, bfm_sc2_state )
MCFG_CPU_PERIODIC_INT(timer_irq, 1000 )
MCFG_WATCHDOG_TIME_INIT(PERIOD_OF_555_MONOSTABLE(120000,100e-9))
MCFG_BFMBD1_ADD("vfd0",0)
MCFG_BFMBD1_ADD("vfd1",1)
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("upd",UPD7759, UPD7759_STANDARD_CLOCK)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
@ -3731,7 +3720,6 @@ static MACHINE_CONFIG_START( scorpion2_dm01, bfm_sc2_state )
MCFG_CPU_PERIODIC_INT(timer_irq, 1000 )
MCFG_WATCHDOG_TIME_INIT(PERIOD_OF_555_MONOSTABLE(120000,100e-9))
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("ymsnd",YM2413, XTAL_3_579545MHz)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
@ -3789,9 +3777,6 @@ static DRIVER_INIT (bbrkfst)
sc2awp_common_init(machine,5, 1);
MechMtr_config(machine,8);
BFM_BD1_init(0);
BFM_BD1_init(1);
state->m_has_hopper = 0;
Scorpion2_SetSwitchState(machine,4,0, 1); /* GBP1 Low Level Switch */
@ -3812,9 +3797,6 @@ static DRIVER_INIT (drwho_common)
MechMtr_config(machine,8);
BFM_BD1_init(0);
BFM_BD1_init(1);
state->m_has_hopper = 0;
Scorpion2_SetSwitchState(machine,4,0, 0); /* GBP1 Low Level Switch */
@ -3844,8 +3826,6 @@ static DRIVER_INIT (focus)
{
sc2awp_common_init(machine,6, 1);
MechMtr_config(machine,5);
BFM_BD1_init(0);
}
static DRIVER_INIT (cpeno1)
@ -3934,7 +3914,6 @@ static DRIVER_INIT (bfmcgslm)
bfm_sc2_state *state = machine.driver_data<bfm_sc2_state>();
sc2awp_common_init(machine,6, 1);
MechMtr_config(machine,8);
BFM_BD1_init(0);
state->m_has_hopper = 0;
}

View File

@ -37,7 +37,6 @@
#include "sound/ymz280b.h"
#include "machine/68681.h"
#include "bfm_sc4.lh"
#include "machine/bfm_bd1.h"
#include "video/awpvid.h"
//DMD01
#include "video/bfm_dm01.h"
@ -456,8 +455,7 @@ void bfm_sc4_reset_serial_vfd(running_machine &machine)
{
sc4_state *state = machine.driver_data<sc4_state>();
BFM_BD1_reset(0);
BFM_BD1_draw(0);
state->m_vfd0->reset();
state->vfd_old_clock = false;
}
@ -481,6 +479,8 @@ void bfm_sc4_write_serial_vfd(running_machine &machine, bool cs, bool clock, boo
{
if ( !clock )
{
//Should move to the internal serial process when DM01 is device-ified
// m_vfd0->shift_data(!data);
state->vfd_ser_value <<= 1;
if (data) state->vfd_ser_value |= 1;
@ -494,8 +494,7 @@ void bfm_sc4_write_serial_vfd(running_machine &machine, bool cs, bool clock, boo
}
else
{
BFM_BD1_newdata(0, state->vfd_ser_value);
BFM_BD1_draw(0);
state->m_vfd0->write_char(state->vfd_ser_value);
}
}
}
@ -642,8 +641,6 @@ static MACHINE_START( sc4 )
bfm_sc4_68307_portb_w );
m68307_set_duart68681(machine.device("maincpu"),machine.device("m68307_68681"));
BFM_BD1_init(0);
int reels = 6;
state->m_reels=reels;
@ -782,6 +779,7 @@ MACHINE_CONFIG_START( sc4, sc4_state )
MCFG_DUART68681_ADD("duart68681", 16000000/4, bfm_sc4_duart68681_config) // ?? Mhz
MCFG_BFMBD1_ADD("vfd0",0)
MCFG_DEFAULT_LAYOUT(layout_bfm_sc4)
@ -803,12 +801,15 @@ static MACHINE_START( adder4 )
MACHINE_CONFIG_DERIVED_CLASS( sc4_adder4, sc4, sc4_adder4_state )
MCFG_CPU_ADD("adder4", M68340, 25175000) // 68340 (CPU32 core)
MCFG_CPU_PROGRAM_MAP(sc4_adder4_map)
MCFG_BFMBD1_ADD("vfd0",0)
MCFG_MACHINE_START( adder4 )
MACHINE_CONFIG_END
MACHINE_CONFIG_DERIVED_CLASS( sc4dmd, sc4, sc4_state )
/* video hardware */
MCFG_BFMBD1_REMOVE("vfd0")
MCFG_DEFAULT_LAYOUT(layout_sc4_dmd)
MCFG_CPU_ADD("matrix", M6809, 2000000 ) /* matrix board 6809 CPU at 2 Mhz ?? I don't know the exact freq.*/
MCFG_CPU_PROGRAM_MAP(bfm_dm01_memmap)
@ -816,6 +817,7 @@ MACHINE_CONFIG_DERIVED_CLASS( sc4dmd, sc4, sc4_state )
MCFG_MACHINE_START( sc4 )
MACHINE_CONFIG_END
INPUT_PORTS_START( sc4_base )
PORT_START("IN-0")
PORT_DIPNAME( 0x01, 0x00, "IN-0:0" )

View File

@ -2,63 +2,19 @@
Bellfruit BD1 VFD module interface and emulation by J.Wallace
TODO: Implement flashing (our only datasheet has that section
completely illegible)
**********************************************************************/
#include "emu.h"
#include "bfm_bd1.h"
static struct
{
UINT8 type, // type of alpha display
const device_type BFM_BD1 = &device_creator<bfm_bd1_t>;
changed, // flag <>0, if contents are changed
window_start, // display window start pos 0-15
window_end, // display window end pos 0-15
window_size, // window size
pad; // unused align byte
INT8 pcursor_pos, // previous cursor pos
cursor_pos; // current cursor pos
UINT16 user_def, // user defined character state
user_data; // user defined character data (16 bit)
UINT8 scroll_active, // flag <>0, scrolling active
display_mode, // display scroll mode, 0/1/2/3
display_blanking, // display blanking mode, 0/1/2/3
blank_flag,
flash_rate, // flash rate 0-F
flash_control, // flash control 0/1/2/3
flash_flag;
UINT8 string[18]; // text buffer
UINT32 segments[16], // segments
outputs[16]; // standardised outputs
UINT8 count, // bit counter
data; // receive register
} bd1[MAX_BD1];
// local prototypes ///////////////////////////////////////////////////////
static void ScrollLeft( int id);
static int BD1_setdata(int id, int segdata, int data);
// local vars /////////////////////////////////////////////////////////////
//
// Bellfruit BD1 charset to ASCII conversion table
//
static const char BD1ASCII[] =
//0123456789ABCDEF0123456789ABC DEF01 23456789ABCDEF0123456789ABCDEF
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ ?\"#$%%'()*+.-./0123456789&%<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ ?\"#$%%'()*+.-./0123456789&%<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ ?\"#$%%'()*+.-./0123456789&%<=>?";
/*
BD1 14 segment charset lookup table
BD1 14 segment charset lookup table, according to datasheet (we rewire this later)
2
---------
|\ |3 /|
@ -71,6 +27,8 @@ static const char BD1ASCII[] =
--------- C
9
8 is flashing
*/
static const UINT16 BD1charset[]=
@ -112,7 +70,7 @@ static const UINT16 BD1charset[]=
0x0009, // 0000 0000 0000 1001 ".
0xC62A, // 1100 0110 0010 1010 #.
0xC62D, // 1100 0110 0010 1101 $.
0x0100, // 0000 0000 0000 0000 flash ?
0x0100, // 0000 0001 0000 0000 flash character
0x0000, // 0000 0000 0000 0000 not defined
0x0040, // 0000 0000 1000 0000 '.
0x0880, // 0000 1000 1000 0000 (.
@ -141,322 +99,347 @@ static const UINT16 BD1charset[]=
0x4406, // 0100 0100 0000 0110 ?
};
///////////////////////////////////////////////////////////////////////////
void BFM_BD1_init(int id)
bfm_bd1_t::bfm_bd1_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, BFM_BD1, "BFM BD1 VFD controller", tag, owner, clock),
m_port_val(0)
{
assert_always((id >= 0) && (id < MAX_BD1), "BFM_BD1_init called on an invalid display ID!");
memset( &bd1[id], 0, sizeof(bd1[0]));
BFM_BD1_reset(id);
}
///////////////////////////////////////////////////////////////////////////
void BFM_BD1_reset(int id)
void bfm_bd1_t::static_set_value(device_t &device, int val)
{
bd1[id].window_end = 15;
bd1[id].window_size = (bd1[id].window_end - bd1[id].window_start)+1;
memset(bd1[id].string, ' ', 16);
bd1[id].count = 0;
bd1[id].changed |= 1;
bfm_bd1_t &bd1 = downcast<bfm_bd1_t &>(device);
bd1.m_port_val = val;
}
///////////////////////////////////////////////////////////////////////////
UINT32 *BFM_BD1_get_segments(int id)
void bfm_bd1_t::device_start()
{
return bd1[id].segments;
m_timer=timer_alloc(0);
save_item(NAME(m_cursor));
save_item(NAME(m_cursor_pos));
save_item(NAME(m_window_start)); // display window start pos 0-15
save_item(NAME(m_window_end)); // display window end pos 0-15
save_item(NAME(m_window_size)); // window size
save_item(NAME(m_shift_count));
save_item(NAME(m_shift_data));
save_item(NAME(m_pcursor_pos));
save_item(NAME(m_blank_flag));
save_item(NAME(m_flash_flag));
save_item(NAME(m_scroll_active));
save_item(NAME(m_display_mode));
save_item(NAME(m_flash_rate));
save_item(NAME(m_flash_control));
save_item(NAME(m_chars));
save_item(NAME(m_attrs));
save_item(NAME(m_user_data)); // user defined character data (16 bit)
save_item(NAME(m_user_def)); // user defined character state
device_reset();
}
///////////////////////////////////////////////////////////////////////////
UINT32 *BFM_BD1_get_outputs(int id)
void bfm_bd1_t::device_reset()
{
return bd1[id].outputs;
m_cursor = 0;
m_cursor_pos = 0;
m_window_start = 0;
m_window_end = 0;
m_window_size = 0;
m_shift_count = 0;
m_shift_data = 0;
m_pcursor_pos = 0;
m_blank_flag = 0;
m_flash_flag = 0;
m_scroll_active = 0;
m_display_mode = 0;
m_flash_rate = 0;
m_flash_control = 0;
m_user_data = 0;
m_user_def = 0;
memset(m_chars, 0, sizeof(m_chars));
memset(m_attrs, 0, sizeof(m_attrs));
m_timer->adjust(attotime::from_hz(clock()), 0);
}
///////////////////////////////////////////////////////////////////////////
UINT32 *BFM_BD1_set_outputs(int id)
void bfm_bd1_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
int cursor;
for (cursor = 0; cursor < 16; cursor++)
update_display();
m_timer->adjust(attotime::from_hz(clock()), 0);
}
UINT32 bfm_bd1_t::set_display(UINT16 segin)
{
UINT32 segout=0;
if ( segin & 0x0004 ) segout |= 0x0001;
else segout &= ~0x0001;
if ( segin & 0x0002 ) segout |= 0x0002;
else segout &= ~0x0002;
if ( segin & 0x0020 ) segout |= 0x0004;
else segout &= ~0x0004;
if ( segin & 0x0200 ) segout |= 0x0008;
else segout &= ~0x0008;
if ( segin & 0x2000 ) segout |= 0x0010;
else segout &= ~0x0010;
if ( segin & 0x0001 ) segout |= 0x0020;
else segout &= ~0x0020;
if ( segin & 0x8000 ) segout |= 0x0040;
else segout &= ~0x0040;
if ( segin & 0x4000 ) segout |= 0x0080;
else segout &= ~0x0080;
if ( segin & 0x0008 ) segout |= 0x0100;
else segout &= ~0x0100;
if ( segin & 0x0400 ) segout |= 0x0200;
else segout &= ~0x0200;
if ( segin & 0x0010 ) segout |= 0x0400;
else segout &= ~0x0400;
if ( segin & 0x0040 ) segout |= 0x0800;
else segout &= ~0x0800;
if ( segin & 0x0080 ) segout |= 0x1000;
else segout &= ~0x1000;
if ( segin & 0x0800 ) segout |= 0x2000;
else segout &= ~0x2000;
if ( segin & 0x1000 ) segout |= 0x4000;
else segout &= ~0x4000;
return segout;
}
void bfm_bd1_t::device_post_load()
{
for (int i =0; i<16; i++)
{
if ( BFM_BD1_get_segments(id)[cursor] & 0x0004 ) bd1[id].outputs[cursor] |= 0x0001;
else bd1[id].outputs[cursor] &= ~0x0001;
if ( BFM_BD1_get_segments(id)[cursor] & 0x0002 ) bd1[id].outputs[cursor] |= 0x0002;
else bd1[id].outputs[cursor] &= ~0x0002;
if ( BFM_BD1_get_segments(id)[cursor] & 0x0020 ) bd1[id].outputs[cursor] |= 0x0004;
else bd1[id].outputs[cursor] &= ~0x0004;
if ( BFM_BD1_get_segments(id)[cursor] & 0x0200 ) bd1[id].outputs[cursor] |= 0x0008;
else bd1[id].outputs[cursor] &= ~0x0008;
if ( BFM_BD1_get_segments(id)[cursor] & 0x2000 ) bd1[id].outputs[cursor] |= 0x0010;
else bd1[id].outputs[cursor] &= ~0x0010;
if ( BFM_BD1_get_segments(id)[cursor] & 0x0001 ) bd1[id].outputs[cursor] |= 0x0020;
else bd1[id].outputs[cursor] &= ~0x0020;
if ( BFM_BD1_get_segments(id)[cursor] & 0x8000 ) bd1[id].outputs[cursor] |= 0x0040;
else bd1[id].outputs[cursor] &= ~0x0040;
if ( BFM_BD1_get_segments(id)[cursor] & 0x4000 ) bd1[id].outputs[cursor] |= 0x0080;
else bd1[id].outputs[cursor] &= ~0x0080;
if ( BFM_BD1_get_segments(id)[cursor] & 0x0008 ) bd1[id].outputs[cursor] |= 0x0100;
else bd1[id].outputs[cursor] &= ~0x0100;
if ( BFM_BD1_get_segments(id)[cursor] & 0x0400 ) bd1[id].outputs[cursor] |= 0x0200;
else bd1[id].outputs[cursor] &= ~0x0200;
if ( BFM_BD1_get_segments(id)[cursor] & 0x0010 ) bd1[id].outputs[cursor] |= 0x0400;
else bd1[id].outputs[cursor] &= ~0x0400;
if ( BFM_BD1_get_segments(id)[cursor] & 0x0040 ) bd1[id].outputs[cursor] |= 0x0800;
else bd1[id].outputs[cursor] &= ~0x0800;
if ( BFM_BD1_get_segments(id)[cursor] & 0x0080 ) bd1[id].outputs[cursor] |= 0x1000;
else bd1[id].outputs[cursor] &= ~0x1000;
if ( BFM_BD1_get_segments(id)[cursor] & 0x0800 ) bd1[id].outputs[cursor] |= 0x2000;
else bd1[id].outputs[cursor] &= ~0x2000;
if ( BFM_BD1_get_segments(id)[cursor] & 0x1000 ) bd1[id].outputs[cursor] |= 0x4000;
else bd1[id].outputs[cursor] &= ~0x4000;
//Flashing ? Set an unused pin as a control
if ( BFM_BD1_get_segments(id)[cursor] & 0x100 ) bd1[id].outputs[cursor] |= 0x40000;
else bd1[id].outputs[cursor] &= ~0x40000;
output_set_indexed_value("vfd", (m_port_val*16) + i, m_outputs[i]);
}
}
void bfm_bd1_t::update_display()
{
m_outputs[m_cursor] = set_display(m_chars[m_cursor]);;
output_set_indexed_value("vfd", (m_port_val*16) + m_cursor, m_outputs[m_cursor]);
m_cursor++;
if (m_cursor >15)
{
m_cursor=0;
}
}
///////////////////////////////////////////////////////////////////////////
void bfm_bd1_t::blank(int data)
{
switch ( data & 0x04 )
{
case 0x00: // blank all
{
memset(m_chars, 0, sizeof(m_chars));
memset(m_attrs, 0, sizeof(m_attrs));
}
break;
case 0x01: // blank inside window
if ( m_window_size > 0 )
{
memset(m_chars+m_window_start,0,m_window_size);
memset(m_attrs+m_window_start,0,m_window_size);
}
break;
case 0x02: // blank outside window
if ( m_window_size > 0 )
{
if ( m_window_start > 0 )
{
for (int i = 0; i < m_window_start; i++)
{
memset(m_chars+i,0,i);
memset(m_attrs+i,0,i);
}
}
if (m_window_end < 15 )
{
for (int i = m_window_end; i < 15- m_window_end ; i++)
{
memset(m_chars+i,0,i);
memset(m_attrs+i,0,i);
}
}
}
break;
case 0x03: // blank entire display
{
memset(m_chars, 0, sizeof(m_chars));
memset(m_attrs, 0, sizeof(m_attrs));
}
break;
}
}
int bfm_bd1_t::write_char(int data)
{
int change = 0;
if ( m_user_def )
{
m_user_def--;
m_user_data <<= 8;
m_user_data |= data;
if ( m_user_def )
{
return 0;
}
setdata( m_user_data, data);
change ++;
}
else
{
if(data < 0x80)//characters
{
if (m_blank_flag || m_flash_flag)
{
if (m_blank_flag)
{
//m_display_blanking = data & 0x0F;
blank( data & 0x04 );
m_blank_flag = 0;
}
if (m_flash_flag)
{
//not setting yet
m_flash_flag = 0;
}
}
else
{
if (data > 0x3F)
{
// logerror("Undefined character %x \n", data);
}
setdata(BD1charset[(data & 0x3F)], data);
}
}
else
{
switch ( data & 0xF0 )
{
case 0x80: // 0x80 - 0x8F Set display blanking
if (data ==0x84)// futaba setup
{
m_blank_flag = 1;
}
else
{
blank(data&0x04);//use the blanking data
}
break;
case 0x90: // 0x90 - 0x9F Set cursor pos
m_cursor_pos = data & 0x0F;
m_scroll_active = 0;
if ( m_display_mode == 2 )
{
if ( m_cursor_pos >= m_window_end) m_scroll_active = 1;
}
break;
case 0xA0: // 0xA0 - 0xAF Set display mode
m_display_mode = data &0x03;
break;
case 0xB0: // 0xB0 - 0xBF Clear display area
switch ( data & 0x03 )
{
case 0x00: // clr nothing
break;
case 0x01: // clr inside window
if ( m_window_size > 0 )
{
memset(m_chars+m_window_start,0,m_window_size);
memset(m_attrs+m_window_start,0,m_window_size);
}
break;
case 0x02: // clr outside window
if ( m_window_size > 0 )
{
if ( m_window_start > 0 )
{
for (int i = 0; i < m_window_start; i++)
{
memset(m_chars+i,0,i);
memset(m_attrs+i,0,i);
}
}
if (m_window_end < 15 )
{
for (int i = m_window_end; i < 15- m_window_end ; i++)
{
memset(m_chars+i,0,i);
memset(m_attrs+i,0,i);
}
}
}
case 0x03: // clr entire display
{
memset(m_chars, 0, sizeof(m_chars));
memset(m_attrs, 0, sizeof(m_attrs));
}
}
break;
case 0xC0: // 0xC0 - 0xCF Set flash rate
m_flash_rate = data & 0x0F;
break;
case 0xD0: // 0xD0 - 0xDF Set Flash control
m_flash_control = data & 0x03;
break;
case 0xE0: // 0xE0 - 0xEF Set window start pos
m_window_start = data &0x0F;
m_window_size = (m_window_end - m_window_start)+1;
break;
case 0xF0: // 0xF0 - 0xFF Set window end pos
m_window_end = data &0x0F;
m_window_size = (m_window_end - m_window_start)+1;
m_scroll_active = 0;
if ( m_display_mode == 2 )
{
if ( m_cursor_pos >= m_window_end)
{
m_scroll_active = 1;
m_cursor_pos = m_window_end;
}
}
break;
}
}
}
return 0;
}
///////////////////////////////////////////////////////////////////////////
char *BFM_BD1_get_string( int id)
void bfm_bd1_t::setdata(int segdata, int data)
{
return (char *)bd1[id].string;
}
///////////////////////////////////////////////////////////////////////////
void BFM_BD1_shift_data(int id, int data)
{
bd1[id].data <<= 1;
if ( !data ) bd1[id].data |= 1;
if ( ++bd1[id].count >= 8 )
{
if ( BFM_BD1_newdata(id, bd1[id].data) )
{
bd1[id].changed |= 1;
}
//logerror("vfd %3d -> %02X \"%s\"\n", id, bd1[id].data, bd1[id].string);
bd1[id].count = 0;
bd1[id].data = 0;
}
}
///////////////////////////////////////////////////////////////////////////
int BFM_BD1_newdata(int id, int data)
{
int change = 0;
int cursor;
if ( bd1[id].user_def )
{
bd1[id].user_def--;
bd1[id].user_data <<= 8;
bd1[id].user_data |= data;
if ( bd1[id].user_def )
{
return 0;
}
data = '@';
change = BD1_setdata(id, bd1[id].user_def, data);
}
else
{
}
switch ( data & 0xF0 )
{
case 0x80: // 0x80 - 0x8F Set display blanking
//TODO: Implement this, MAME artwork not mature enough
switch ( data & 0x04 )
{
case 0x00: // blank all
break;
case 0x01: // blank inside window
break;
case 0x02: // blank outside window
break;
case 0x03: // blank entire display
break;
case 0x04: // futaba setup
bd1[id].blank_flag = 1;
break;
}
break;
case 0x90: // 0x90 - 0x9F Set cursor pos
bd1[id].cursor_pos = data & 0x0F;
bd1[id].scroll_active = 0;
if ( bd1[id].display_mode == 2 )
{
if ( bd1[id].cursor_pos >= bd1[id].window_end) bd1[id].scroll_active = 1;
}
break;
case 0xA0: // 0xA0 - 0xAF Set display mode
bd1[id].display_mode = data &0x03;
break;
case 0xB0: // 0xB0 - 0xBF Clear display area
switch ( data & 0x03 )
{
case 0x00: // clr nothing
break;
case 0x01: // clr inside window
if ( bd1[id].window_size > 0 )
{
memset( bd1[id].string+bd1[id].window_start, ' ',bd1[id].window_size );
}
break;
case 0x02: // clr outside window
if ( bd1[id].window_size > 0 )
{
if ( bd1[id].window_start > 0 )
{
memset( bd1[id].string, ' ', bd1[id].window_start);
for (cursor = 0; cursor < bd1[id].window_start; cursor++)
{
bd1[id].segments[cursor] = 0x0000;
}
}
if (bd1[id].window_end < 15 )
{
memset( bd1[id].string+bd1[id].window_end, ' ', 15-bd1[id].window_end);
for (cursor = bd1[id].window_end; cursor < 15-bd1[id].window_end; cursor++)
{
bd1[id].segments[cursor] = 0x0000;
}
}
}
case 0x03: // clr entire display
memset(bd1[id].string, ' ' , 16);
for (cursor = 0; cursor < 16; cursor++)
{
bd1[id].segments[cursor] = 0x0000;
}
break;
}
change = 1;
break;
case 0xC0: // 0xC0 - 0xCF Set flash rate
bd1[id].flash_rate = data & 0x0F;
break;
case 0xD0: // 0xD0 - 0xDF Set Flash control
bd1[id].flash_control = data & 0x03;
break;
case 0xE0: // 0xE0 - 0xEF Set window start pos
bd1[id].window_start = data &0x0F;
bd1[id].window_size = (bd1[id].window_end - bd1[id].window_start)+1;
break;
case 0xF0: // 0xF0 - 0xFF Set window end pos
bd1[id].window_end = data &0x0F;
bd1[id].window_size = (bd1[id].window_end - bd1[id].window_start)+1;
bd1[id].scroll_active = 0;
if ( bd1[id].display_mode == 2 )
{
if ( bd1[id].cursor_pos >= bd1[id].window_end)
{
bd1[id].scroll_active = 1;
bd1[id].cursor_pos = bd1[id].window_end;
}
}
break;
default:
if (bd1[id].blank_flag || bd1[id].flash_flag)
{
if (bd1[id].blank_flag)
{
bd1[id].display_blanking = data & 0x0F;
change = 1;
bd1[id].blank_flag = 0;
}
if (bd1[id].flash_flag)
{
//not setting yet
bd1[id].blank_flag = 0;
}
}
else
{
if (data > 0x3F)
{
// logerror("Undefined character %x \n", data);
}
change = BD1_setdata(id, BD1charset[data & 0x3F], data);
}
break;
}
return change;
}
///////////////////////////////////////////////////////////////////////////
static void ScrollLeft(int id)
{
int i = bd1[id].window_start;
while ( i < bd1[id].window_end )
{
bd1[id].string[ i ] = bd1[id].string[ i+1 ];
bd1[id].segments[i] = bd1[id].segments[i+1];
i++;
}
}
///////////////////////////////////////////////////////////////////////////
static int BD1_setdata(int id, int segdata, int data)
{
int change = 0, move = 0;
int move = 0;
int change =0;
switch ( data )
{
case 0x25: // flash
move++;
if(m_chars[m_pcursor_pos] & (1<<8))
{
move++;
}
else
{
m_chars[m_pcursor_pos] |= (1<<8);
}
break;
case 0x26: // undefined
@ -465,8 +448,14 @@ static int BD1_setdata(int id, int segdata, int data)
case 0x2C: // semicolon
case 0x2E: // decimal point
bd1[id].segments[bd1[id].pcursor_pos] |= (1<<12);
change++;
if( m_chars[m_pcursor_pos] & (1<<12))
{
move++;
}
else
{
m_chars[m_pcursor_pos] |= (1<<12);
}
break;
case 0x3B: // dummy char
@ -474,139 +463,143 @@ static int BD1_setdata(int id, int segdata, int data)
break;
case 0x3A:
bd1[id].user_def = 2;
m_user_def = 2;
break;
default:
move = 1;
change = 1;
move++;
change++;
}
if ( move )
{
int mode = bd1[id].display_mode;
bd1[id].pcursor_pos = bd1[id].cursor_pos;
int mode = m_display_mode;
if ( bd1[id].window_size <= 0 || (bd1[id].window_size > 16))
{ // no window selected default to rotate mode
m_pcursor_pos = m_cursor_pos;
if ( m_window_size <= 0 || (m_window_size > 16))
{ // if no window selected default to equivalent rotate mode
if ( mode == 2 ) mode = 0;
else if ( mode == 3 ) mode = 1;
//mode &= -2;
}
switch ( mode )
{
case 0: // rotate left
bd1[id].cursor_pos &= 0x0F;
m_cursor_pos &= 0x0F;
if ( change )
{
bd1[id].string[bd1[id].cursor_pos] = BD1ASCII[data];
bd1[id].segments[bd1[id].cursor_pos] = segdata;
m_chars[m_cursor_pos] = segdata;
}
bd1[id].cursor_pos++;
if ( bd1[id].cursor_pos >= 16 ) bd1[id].cursor_pos = 0;
m_cursor_pos++;
if ( m_cursor_pos >= 16 ) m_cursor_pos = 0;
break;
case 1: // Rotate right
bd1[id].cursor_pos &= 0x0F;
m_cursor_pos &= 0x0F;
if ( change )
{
bd1[id].string[bd1[id].cursor_pos] = BD1ASCII[data];
bd1[id].segments[bd1[id].cursor_pos] = segdata;
m_chars[m_cursor_pos] = segdata;
}
bd1[id].cursor_pos--;
if ( bd1[id].cursor_pos < 0 ) bd1[id].cursor_pos = 15;
m_cursor_pos--;
if ( m_cursor_pos < 0 ) m_cursor_pos = 15;
break;
case 2: // Scroll left
if ( bd1[id].cursor_pos < bd1[id].window_end )
if ( m_cursor_pos < m_window_end )
{
bd1[id].scroll_active = 0;
m_scroll_active = 0;
if ( change )
{
bd1[id].string[bd1[id].cursor_pos] = BD1ASCII[data];
bd1[id].segments[bd1[id].cursor_pos] = segdata;
m_chars[m_cursor_pos] = segdata;
}
if ( move ) bd1[id].cursor_pos++;
m_cursor_pos++;
}
else
{
if ( move )
{
if ( bd1[id].scroll_active ) ScrollLeft(id);
else bd1[id].scroll_active = 1;
if ( m_scroll_active )
{
int i = m_window_start;
while ( i < m_window_end )
{
m_chars[i] = m_chars[i+1];
i++;
}
}
else m_scroll_active = 1;
}
if ( change )
{
bd1[id].string[bd1[id].window_end] = BD1ASCII[data];
bd1[id].segments[bd1[id].cursor_pos] = segdata;
m_chars[m_window_end] = segdata;
}
else
{
bd1[id].string[bd1[id].window_end] = ' ';
bd1[id].segments[bd1[id].cursor_pos] = 0;
m_chars[m_window_end] = 0;
}
}
break;
case 3: // Scroll right
if ( bd1[id].cursor_pos > bd1[id].window_start )
if ( m_cursor_pos > m_window_start )
{
if ( change )
{
bd1[id].string[bd1[id].cursor_pos] = BD1ASCII[data];
bd1[id].segments[bd1[id].cursor_pos] = segdata;
m_chars[m_cursor_pos] = segdata;
}
bd1[id].cursor_pos--;
m_cursor_pos--;
if ( m_cursor_pos > 15 ) m_cursor_pos = 0;
}
else
{
int i = bd1[id].window_end;
while ( i > bd1[id].window_start )
if ( move )
{
bd1[id].string[ i ] = bd1[id].string[ i-1 ];
bd1[id].segments[i] = bd1[id].segments[i-1];
i--;
}
if ( m_scroll_active )
{
int i = m_window_end;
while ( i > m_window_start )
{
m_chars[i] = m_chars[i-1];
i--;
}
}
else m_scroll_active = 1;
}
if ( change )
{
bd1[id].string[bd1[id].window_start] = BD1ASCII[data];
bd1[id].segments[bd1[id].window_start] = segdata;
m_chars[m_window_start] = segdata;
}
else
{
m_chars[m_window_start] = 0;
}
}
break;
}
}
return change;
}
void BFM_BD1_draw(int id)
void bfm_bd1_t::shift_data(int data)
{
int cursor;
BFM_BD1_set_outputs(id);
m_shift_data <<= 1;
if ( !data ) m_shift_data |= 1;
for (cursor = 0; cursor < 16; cursor++)
if ( ++m_shift_count >= 8 )
{
output_set_indexed_value("vfd", (id*16)+cursor, BFM_BD1_get_outputs(id)[cursor]);
if (BFM_BD1_get_outputs(id)[cursor] & 0x40000)
{
//activate flashing (unimplemented, just toggle on and off)
}
else
{
//deactivate flashing (unimplemented)
}
write_char(m_shift_data);
m_shift_count = 0;
m_shift_data = 0;
}
}

View File

@ -1,22 +1,70 @@
#ifndef BFM_BD1
#define BFM_BD1
#pragma once
#ifndef BFM_BD1_H
#define BFM_BD1_H
#define MAX_BD1 3 // max number of displays emulated
//Based on the datasheet, the makimum oscillation rate for one character is 31.25 KHz, so we set our character clock to that.
#define MCFG_BFMBD1_ADD(_tag,_val) \
MCFG_DEVICE_ADD(_tag, BFM_BD1,312500)\
MCFG_BD1_PORT(_val) \
void BFM_BD1_init( int id ); // setup a display
#define MCFG_BD1_PORT(_val) \
bfm_bd1_t::static_set_value(*device, _val); \
void BFM_BD1_reset( int id); // reset the alpha
#define MCFG_BFMBD1_REMOVE(_tag) \
MCFG_DEVICE_REMOVE(_tag)
class bfm_bd1_t : public device_t
{
public:
typedef delegate<void (bool state)> line_cb;
bfm_bd1_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
void BFM_BD1_shift_data(int id, int data); // clock in a bit of data
int BFM_BD1_newdata( int id, int data); // clock in 8 bits of data
// inline configuration helpers
static void static_set_value(device_t &device, int val);
UINT32 *BFM_BD1_get_segments(int id); // get current segments displayed
UINT32 *BFM_BD1_set_outputs(int id); // convert segments to standard for display
UINT32 *BFM_BD1_get_outputs(int id); // get converted segments
int write_char(int data);
virtual void update_display();
UINT8 m_port_val;
void blank(int data);
void shift_data(int data);
void setdata(int segdata, int data);
UINT32 set_display(UINT16 segin);
char *BFM_BD1_get_string( int id); // get current string displayed (not as accurate)
protected:
static const UINT8 AT_NORMAL = 0x00;
static const UINT8 AT_FLASH = 0x01;
static const UINT8 AT_FLASHED = 0x80; // set when character should be blinked off
void BFM_BD1_draw(int id);
emu_timer *m_timer;
int m_cursor_pos;
int m_window_start; // display window start pos 0-15
int m_window_end; // display window end pos 0-15
int m_window_size; // window size
int m_shift_count;
int m_shift_data;
int m_pcursor_pos;
int m_blank_flag;
int m_flash_flag;
int m_scroll_active;
int m_display_mode;
int m_flash_rate;
int m_flash_control;
UINT8 m_cursor;
UINT16 m_chars[16];
UINT16 m_outputs[16];
UINT8 m_attrs[16];
UINT16 m_user_data; // user defined character data (16 bit)
UINT16 m_user_def; // user defined character state
virtual void device_start();
virtual void device_reset();
virtual void device_post_load();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
};
extern const device_type BFM_BD1;
#endif

View File

@ -248,15 +248,6 @@ PALETTE_INIT( adder2 )
///////////////////////////////////////////////////////////////////////////
MACHINE_RESET( adder2 )
{
// setup the standard bellfruit BD1 display /////////////////////////////
BFM_BD1_init(0);
}
///////////////////////////////////////////////////////////////////////////
INTERRUPT_GEN( adder2_vbl )
{
if ( adder2_c101 & 0x01 )