1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
// license:BSD-3-Clause
// copyright-holders:hap
/*
Generic sensorboard device
*/
#ifndef MAME_MACHINE_SENSORBOARD_H
#define MAME_MACHINE_SENSORBOARD_H
#pragma once
class sensorboard_device : public device_t, public device_nvram_interface
{
public:
sensorboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
enum sb_type
{
NOSENSORS = 0,
BUTTONS,
MAGNETS,
INDUCTIVE
};
// configuration helpers
sensorboard_device &set_type(sb_type type); // sensor type
sensorboard_device &set_size(u8 width, u8 height) { m_width = width; m_height = height; return *this; } // board dimensions, max 12 * 10
sensorboard_device &set_spawnpoints(u8 i) { m_maxspawn = i; m_maxid = i; return *this; } // number of piece spawnpoints, max 16
sensorboard_device &set_max_id(u8 i) { m_maxid = i; return *this; } // maximum piece id (if larger than set_spawnpoints)
sensorboard_device &set_delay(attotime delay) { m_sensordelay = delay; return *this; } // delay when activating a sensor (like PORT_IMPULSE), set to attotime::never to disable
sensorboard_device &set_nvram_enable(bool b) { m_nvram_auto = b; return *this; } // load last board position on start
sensorboard_device &set_ui_enable(bool b) { if (!b) m_maxspawn = 0; m_ui_enabled = (b) ? 7 : 0; return *this; } // enable UI inputs
sensorboard_device &set_mod_enable(bool b) { if (b) m_ui_enabled |= 1; else m_ui_enabled &= ~1; return *this; } // enable modifier keys
auto init_cb() { return m_custom_init_cb.bind(); } // for setting pieces starting position
auto sensor_cb() { return m_custom_sensor_cb.bind(); } // x = offset & 0xf, y = offset >> 4 & 0xf
auto spawn_cb() { return m_custom_spawn_cb.bind(); } // spawnpoint/piece = offset, retval = new piece id
auto output_cb() { return m_custom_output_cb.bind(); } // pos = offset(A8 for ui/board, A9 for count), id = data
void preset_chess(int state); // init_cb() preset for chessboards
// read sensors
u8 read_sensor(u8 x, u8 y);
u16 read_file(u8 x, bool reverse = false);
u16 read_rank(u8 y, bool reverse = false);
bool is_inductive() { return m_inductive; }
// handle board state
u8 read_piece(u8 x, u8 y) { return m_curstate[y * m_width + x]; }
void write_piece(u8 x, u8 y, u8 id) { m_curstate[y * m_width + x] = id; }
void clear_board() { memset(m_curstate, 0, sizeof(m_curstate)); }
void refresh();
void cancel_sensor();
// handle pieces
void cancel_hand();
void remove_hand();
int get_handpos() { return m_handpos; }
bool drop_piece(u8 x, u8 y);
bool pickup_piece(u8 x, u8 y);
// input handlers
DECLARE_INPUT_CHANGED_MEMBER(sensor);
DECLARE_INPUT_CHANGED_MEMBER(ui_spawn);
DECLARE_INPUT_CHANGED_MEMBER(ui_hand);
DECLARE_INPUT_CHANGED_MEMBER(ui_undo);
DECLARE_INPUT_CHANGED_MEMBER(ui_init);
DECLARE_INPUT_CHANGED_MEMBER(ui_refresh) { refresh(); }
DECLARE_CUSTOM_INPUT_MEMBER(check_sensor_busy) { return (m_sensorpos == -1) ? 0 : 1; }
DECLARE_CUSTOM_INPUT_MEMBER(check_bs_mask) { return m_bs_mask; }
DECLARE_CUSTOM_INPUT_MEMBER(check_ss_mask) { return m_ss_mask; }
DECLARE_CUSTOM_INPUT_MEMBER(check_ui_enabled) { return m_ui_enabled; }
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_post_load() override { refresh(); }
virtual ioport_constructor device_input_ports() const override;
// device_nvram_interface overrides
virtual void nvram_default() override;
virtual bool nvram_read(util::read_stream &file) override;
virtual bool nvram_write(util::write_stream &file) override;
virtual bool nvram_can_write() const override;
private:
output_finder<0x10, 0x10> m_out_piece;
output_finder<0x20+1> m_out_pui;
output_finder<2> m_out_count;
required_ioport_array<10> m_inp_rank;
required_ioport m_inp_spawn;
required_ioport m_inp_ui;
required_ioport m_inp_conf;
devcb_write_line m_custom_init_cb;
devcb_read8 m_custom_sensor_cb;
devcb_read8 m_custom_spawn_cb;
devcb_write16 m_custom_output_cb;
bool m_nosensors;
bool m_magnets;
bool m_inductive;
u8 m_width;
u8 m_height;
u32 m_bs_mask;
u32 m_ss_mask;
u8 m_maxspawn;
u8 m_maxid;
u8 m_hand;
int m_handpos;
int m_droppos;
int m_sensorpos;
u8 m_ui_enabled;
u8 m_curstate[0x100];
u8 m_history[1000][0x100];
u8 m_uselect;
u32 m_upointer;
u32 m_ufirst;
u32 m_ulast;
u32 m_usize;
bool m_nvram_auto;
bool nvram_on() const;
emu_timer *m_undotimer;
TIMER_CALLBACK_MEMBER(undo_tick);
void undo_reset();
attotime m_sensordelay;
emu_timer *m_sensortimer;
TIMER_CALLBACK_MEMBER(sensor_off) { cancel_sensor(); }
};
DECLARE_DEVICE_TYPE(SENSORBOARD, sensorboard_device)
#endif // MAME_MACHINE_SENSORBOARD_H
|