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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
// license:BSD-3-Clause
// copyright-holders:R. Belmont,Aaron Giles
/*********************************************************************
midiin.h
MIDI In image device
*********************************************************************/
#ifndef MAME_IMAGEDEV_MIDIIN_H
#define MAME_IMAGEDEV_MIDIIN_H
#pragma once
#include "diserial.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
class midiin_device : public device_t,
public device_image_interface,
public device_serial_interface
{
public:
// construction/destruction
midiin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto input_callback() { return m_input_cb.bind(); }
// image-level overrides
virtual image_init_result call_load() override;
virtual void call_unload() override;
// image device
virtual bool is_readable() const noexcept override { return true; }
virtual bool is_writeable() const noexcept override { return false; }
virtual bool is_creatable() const noexcept override { return false; }
virtual bool is_reset_on_load() const noexcept override { return false; }
virtual const char *file_extensions() const noexcept override { return "mid"; }
virtual bool core_opens_image_file() const noexcept override { return false; }
virtual const char *image_type_name() const noexcept override { return "midiin"; }
virtual const char *image_brief_type_name() const noexcept override { return "min"; }
protected:
// device-level overrides
virtual ioport_constructor device_input_ports() const override;
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param) override;
// serial overrides
virtual void tra_complete() override; // Tx completed sending byte
virtual void tra_callback() override; // Tx send bit
private:
static const int XMIT_RING_SIZE = (8192*4*4);
void xmit_char(uint8_t data);
std::unique_ptr<osd_midi_device> m_midi;
required_ioport m_config;
emu_timer *m_timer;
devcb_write_line m_input_cb;
uint8_t m_xmitring[XMIT_RING_SIZE];
int m_xmit_read, m_xmit_write;
bool m_tx_busy;
// internal helper class for parsing
class midi_parser
{
public:
// minimal error class
class error
{
public:
error(char const *description) : m_description(description) { }
char const *description() const { return m_description; }
private:
char const *m_description;
};
// construction
midi_parser(u8 const *data, u32 length, u32 offset);
// end of buffer?
bool eob() const { return (m_offset >= m_length); }
// create a subset
midi_parser subset(u32 length);
// change position within buffer
midi_parser &rewind(u32 count);
midi_parser &reset() { return rewind(m_offset); }
// read data of various sizes and endiannesses
u8 byte() { check_bounds(1); return m_data[m_offset++]; }
u16 word_be() { u16 result = byte() << 8; return result | byte(); }
u32 triple_be() { u32 result = word_be() << 8; return result | byte(); }
u32 dword_be() { u32 result = word_be() << 16; return result | word_be(); }
u32 dword_le() { return swapendian_int32(dword_be()); }
// special variable reader for MIDI
u32 variable();
private:
// internal helper
void check_bounds(u32 length);
// internal state
u8 const *m_data;
u32 m_length;
u32 m_offset;
};
// internal helper class reperesenting an event at a given
// time containing MIDI data
class midi_event
{
public:
// constructor
midi_event(u32 tick) :
m_tick(tick) { }
// simple getters
u32 tick() const { return m_tick; }
attotime const &time() const { return m_time; }
std::vector<u8> const &data() const { return m_data; }
// simple setters
void set_time(attotime const &time) { m_time = time; }
// append data to the buffer
midi_event &append(u8 byte) { m_data.push_back(byte); return *this; }
private:
// internal state
u32 m_tick;
attotime m_time;
std::vector<u8> m_data;
};
// internal helper class representing a MIDI sequence
class midi_sequence
{
public:
// constructor
midi_sequence() : m_iterator(m_list.begin()) { }
// clear the sequence
void clear() { m_list.clear(); }
// parse a new sequence
bool parse(u8 const *data, u32 length);
// rewind to the start of time
void rewind(attotime const &basetime);
midi_event *current_event() const { return (m_iterator == m_list.end()) ? nullptr : &(*m_iterator); }
midi_event *advance_event() { ++m_iterator; return current_event(); }
attotime const &duration() { return m_list.back().time(); }
private:
// internal helpers
midi_event &event_at(u32 tick);
u32 parse_track_data(midi_parser &buffer, u32 start_tick);
void parse_midi_data(midi_parser &buffer);
// internal state
std::list<midi_event> m_list;
std::list<midi_event>::iterator m_iterator;
};
midi_sequence m_sequence;
attotime m_sequence_start;
};
// device type definition
DECLARE_DEVICE_TYPE(MIDIIN, midiin_device)
// device iterator
typedef device_type_enumerator<midiin_device> midiin_device_enumerator;
#endif // MAME_IMAGEDEV_MIDIIN_H
|