// license:BSD-3-Clause
// copyright-holders:Ralf Schaefer, Cowering
/**********************************************************************
Mephisto Chess Computers
**********************************************************************/
#include "emu.h"
#include "includes/mboard.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
#define IsPiece(x) ((m_board[x] >=1) && (m_board[x] <=12))
const int mboard_state::start_board[64] =
{
BR, BN, BB, BQ, BK, BB, BN, BR,
BP, BP, BP, BP, BP, BP, BP, BP,
EM, EM, EM, EM, EM, EM, EM, EM,
EM, EM, EM, EM, EM, EM, EM, EM,
EM, EM, EM, EM, EM, EM, EM, EM,
EM, EM, EM, EM, EM, EM, EM, EM,
WP, WP, WP, WP, WP, WP, WP, WP,
WR, WN, WB, WQ, WK, WB, WN, WR
};
UINT8 mboard_state::border_pieces[12] = {WK,WQ,WR,WB,WN,WP,BK,BQ,BR,BB,BN,BP,};
int mboard_state::get_first_bit(UINT8 data)
{
int i;
for (i = 0; i < 8; i++)
if (BIT(data, i))
return i;
return NOT_VALID;
}
inline UINT8 mboard_state::pos_to_num(UINT8 val)
{
switch (val)
{
case 0xfe: return 7;
case 0xfd: return 6;
case 0xfb: return 5;
case 0xf7: return 4;
case 0xef: return 3;
case 0xdf: return 2;
case 0xbf: return 1;
case 0x7f: return 0;
default: return 0xff;
}
}
int mboard_state::get_first_cleared_bit(UINT8 data)
{
int i;
for (i=0;i<8;i++)
if (!BIT(data, i))
return i;
return NOT_VALID;
}
UINT8 mboard_state::read_board()
{
UINT8 i_18, i_AH;
UINT8 data;
data = 0xff;
/*
Example board scan:
Starting postion and pawn on E2 is lifted
mask: 7f 0111 1111 Line 8
data: 0 0000 0000 all fields occupied
mask: bf 1011 1111 Line 7
data: 0 0000 0000 all fields occupied
mask: df 1101 1111 Line 6
data: ff 1111 1111 all fields empty
mask: ef 1110 1111 Line 5
data: ff 1111 1111 all fields empty
mask: f7 1111 0111 Line 4
data: ff 1111 1111 all fields empty
mask: fb 1111 1011 Line 3
data: ff 1111 1111 all fields empty
mask: fd 1111 1101 Line 2
data: 10 0001 0000 E2 is empty rest is occupied
mask: fe 1111 1110 Line 1
data: 0 0000 0000 all fields occupied
*/
/* looking for cleared bit in mask Line18_REED => current line */
if (data && Line18_REED)
{
i_18 = get_first_cleared_bit(Line18_REED);
if (i_18 == NOT_VALID)
printf("No cleared bit in mask Line18_REED!\n");
else
{
/* looking for a piece in this line and clear bit in data if found */
for (i_AH = 0; i_AH < 8; i_AH = i_AH + 1)
if (IsPiece(64 - (i_18 * 8 + 8 - i_AH)))
data &= ~(1 << i_AH); // clear bit
read_board_flag = TRUE;
}
}
return data;
}
void mboard_state::write_board(UINT8 data)
{
Line18_REED=data;
if (read_board_flag && !strcmp(machine().system().name,"glasgow") ) //HACK
Line18_LED = 0;
else
Line18_LED = data;
read_board_flag = FALSE;
if (data == 0xff)
mboard_key_selector = 0;
}
void mboard_state::write_LED(UINT8 data)
{
int i;
UINT8 i_AH, i_18;
UINT8 LED;
mboard_lcd_invert = 1;
/*
Example: turn led E2 on
mask: fd 1111 1101 Line 2
data: 10 0001 0000 Line E
*/
for (i=0; i < 64; i++) /* all LED's off */
output_set_led_value(i, 0);
if (Line18_LED)
{
for (i_AH = 0; i_AH < 8; i_AH++) /* turn LED on depending on bit masks */
{
if (BIT(data,i_AH))
{
for (i_18 = 0; i_18 < 8; i_18++)
{
LED = (i_18*8 + 8-i_AH-1);
if (!(Line18_LED & (1 << i_18))) /* cleared bit */
output_set_led_value(LED, 1);
//else
// output_set_led_value(LED, 0);
}
}
}
}
}
READ8_MEMBER(mboard_state::mboard_read_board_8)
{
UINT8 data;
data=read_board();
logerror("Read Board Port Data = %d\n ",data);
return data;
}
READ16_MEMBER(mboard_state::mboard_read_board_16)
{
UINT8 data;
data=read_board();
return data << 8;
}
READ32_MEMBER(mboard_state::mboard_read_board_32)
{
UINT8 data;
data=read_board();
return data<<24;
}
WRITE8_MEMBER(mboard_state::mboard_write_board_8)
{
write_board(data);
logerror("Write Board Port Data = %02x\n",data);
}
WRITE16_MEMBER(mboard_state::mboard_write_board_16)
{
if (data & 0xff) write_board(data);
logerror("write board 16 %08x\n",data);
write_board(data>>8);
}
WRITE32_MEMBER(mboard_state::mboard_write_board_32)
{
// data |= data << 24;
//printf("write board %08x %08x\n",offset,data);
logerror("write board 32 o: %08x d: %08x\n",offset,data);
if (offset) write_board(data);
else write_board(data>>24);
}
WRITE8_MEMBER(mboard_state::mboard_write_LED_8)
{
write_LED(data);
space.device().execute().spin_until_time(attotime::from_usec(7));
}
WRITE16_MEMBER(mboard_state::mboard_write_LED_16)
{
write_LED(data >> 8);
space.device().execute().spin_until_time(attotime::from_usec(9));
}
WRITE32_MEMBER(mboard_state::mboard_write_LED_32)
{
// data = data | data << 24;
//printf("write LED %08x %08x\n",offset,data);
if (offset) write_LED(data);
else write_LED(data >> 24);
logerror("write LED 32 o: %08x d: %08x\n",offset,data);
// space.device().execute().spin_until_time(ATTOTIME_IN_USEC(20));
}
/* save states callback */
void mboard_state::board_presave()
{
int i;
for (i=0;i<64;i++)
save_board[i]=m_board[i];
}
void mboard_state::board_postload()
{
int i;
for (i=0;i<64;i++)
m_board[i]=save_board[i];
}
void mboard_state::mboard_savestate_register()
{
save_item(NAME(save_board));
machine().save().register_postload(save_prepost_delegate(FUNC(mboard_state::board_postload),this));
machine().save().register_presave(save_prepost_delegate(FUNC(mboard_state::board_presave),this));
}
void mboard_state::mboard_set_board()
{
read_board_flag = TRUE;
int i;
for (i=0;i<64;i++)
m_board[i]=start_board[i];
}
void mboard_state::clear_board()
{
int i;
for (i=0;i<64;i++)
m_board[i]=EM;
}
void mboard_state::set_artwork()
{
int i;
for (i=0;i<64;i++)
output_set_indexed_value("P", i, m_board[i]);
}
void mboard_state::mboard_set_border_pieces()
{
int i;
for (i=0;i<12;i++)
output_set_indexed_value("Q", i, border_pieces[i]);
}
TIMER_DEVICE_CALLBACK_MEMBER(mboard_state::mboard_update_artwork )
{
check_board_buttons();
set_artwork();
mboard_set_border_pieces();
}
void mboard_state::check_board_buttons()
{
int field;
int i;
UINT8 port_input=0;
UINT8 data = 0xff;
static const char *const keynames[] = { "LINE2", "LINE3", "LINE4", "LINE5", "LINE6", "LINE7", "LINE8", "LINE9" };
static UINT8 board_row = 0;
static UINT16 mouse_down = 0;
UINT8 pos2num_res = 0;
board_row++;
board_row &= 7;
int click_on_border_piece=FALSE;
/* check click on border pieces */
i=0;
port_input=ioport("B_BLACK")->read();
if (port_input)
{
i=get_first_bit(port_input)+6;
click_on_border_piece=TRUE;
}
port_input=ioport("B_WHITE")->read();
if (port_input)
{
i=get_first_bit(port_input);
click_on_border_piece=TRUE;
}
if (click_on_border_piece)
{
if (!mouse_down)
{
if (border_pieces[i] > 12 ) /* second click on selected border piece */
{
mouse_hold_border_piece=FALSE;
border_pieces[i]=border_pieces[i]-12;
mouse_hold_from=0;
mouse_hold_piece=0;
}
else if (!mouse_hold_piece) /*select border piece */
{
if (mouse_hold_border_piece)
border_pieces[mouse_hold_from]=border_pieces[mouse_hold_from]-12;
mouse_hold_from=i;
mouse_hold_piece=border_pieces[i];
border_pieces[i]=border_pieces[i]+12;
mouse_hold_border_piece=TRUE;
}
mouse_down = board_row + 1;
}
return;
}
/* check click on board */
data = ioport(keynames[board_row])->read_safe(0xff);
if ((data != 0xff) && (!mouse_down) )
{
pos2num_res = pos_to_num(data);
field=64-(board_row*8+8-pos2num_res);
if (!(pos2num_res < 8))
logerror("Position out of bound!");
else if ((mouse_hold_piece) && (!IsPiece(field)))
{
/* Moving a piece onto a blank */
m_board[field] = mouse_hold_piece;
if (mouse_hold_border_piece)
{
border_pieces[mouse_hold_from]=border_pieces[mouse_hold_from]-12;
}else if ( field != mouse_hold_from ) /* Put a selected piece back to the source field */
m_board[mouse_hold_from] = 0;
mouse_hold_from = 0;
mouse_hold_piece = 0;
mouse_hold_border_piece=FALSE;
}
else if ((!mouse_hold_piece) )
{
/* Picking up a piece */
if (IsPiece(field))
{
mouse_hold_from = field;
mouse_hold_piece = m_board[field];
m_board[field] = m_board[field]+12;
}
}
mouse_down = board_row + 1;
}
else if ((data == 0xff) && (mouse_down == (board_row + 1))) /* Wait for mouse to be released */
mouse_down = 0;
/* check click on border - remove selected piece*/
if (ioport("LINE10")->read_safe(0x01))
{
if (mouse_hold_piece)
{
if (mouse_hold_border_piece)
border_pieces[mouse_hold_from]=border_pieces[mouse_hold_from]-12;
else
m_board[mouse_hold_from] = 0;
mouse_hold_from = 0;
mouse_hold_piece = 0;
mouse_hold_border_piece = FALSE;
}
return;
}
/* check additional buttons */
if (data == 0xff)
{
port_input=ioport("B_BUTTONS")->read();
if (port_input==0x01)
{
clear_board();
return;
}else if (port_input==0x02)
{
mboard_set_board();
return;
}
}
}
extern INPUT_PORTS_START( chessboard )
PORT_START("LINE2")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_START("LINE3")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_START("LINE4")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_START("LINE5")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_START("LINE6")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_START("LINE7")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_START("LINE8")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_START("LINE9")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD)
PORT_START("LINE10")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_START("B_WHITE")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_START("B_BLACK")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_START("B_BUTTONS")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)
PORT_START("MOUSE_X")
PORT_BIT( 0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100)
PORT_START("MOUSE_Y")
PORT_BIT( 0xffff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100)
PORT_START("BUTTON_L")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_CODE(MOUSECODE_BUTTON1) PORT_NAME("left button")
PORT_START("BUTTON_R")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_CODE(MOUSECODE_BUTTON2) PORT_NAME("right button")
INPUT_PORTS_END