1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3 /* Electrocoin Pyramid HW type */
4 
5 // this seems to not like our Z180 timers much? (or wants a 10ms interrupt externally?)
6 // also quite a few of the reads / writes are fall-through from Z180 internal reads/writes
7 
8 // assuming this is like the other hardware EC produced the IO devices should probably
9 // be several 8255s on 4-byte boundaries
10 
11 // what is the sound hardware on this one? (should there be sound roms, or does the main CPU drive it directly?)
12 
13 // 2 of the sets contain program scrambled roms (where the last 0x2000 bytes match between games) why, badly dumped?
14 
15 #include "emu.h"
16 
17 #include "cpu/z180/z180.h"
18 #include "machine/i8255.h"
19 #include "machine/steppers.h" // stepper motor
20 #include "sound/sn76496.h"
21 #include "video/awpvid.h" // drawing reels
22 #include "speaker.h"
23 
24 #include "ecoinf3.lh"
25 
26 #include <algorithm>
27 
28 
29 class ecoinf3_state : public driver_device
30 {
31 public:
ecoinf3_state(const machine_config & mconfig,device_type type,const char * tag)32 	ecoinf3_state(const machine_config &mconfig, device_type type, const char *tag) :
33 		driver_device(mconfig, type, tag),
34 		m_maincpu(*this, "maincpu"),
35 		m_reels(*this, "reel%u", 0U),
36 		m_lamp_outputs(*this, "lamp%u", 0U),
37 		m_vfd_outputs(*this, "vfd%u", 0U)
38 	{
39 	}
40 
41 	void init_ecoinf3();
42 	void init_ecoinf3_swap();
43 	void ecoinf3_pyramid(machine_config &config);
44 
45 private:
machine_start()46 	virtual void machine_start() override
47 	{
48 		m_lamp_outputs.resolve();
49 		m_vfd_outputs.resolve();
50 
51 		save_item(NAME(m_lamps));
52 		save_item(NAME(m_chars));
53 		save_item(NAME(m_strobe_addr));
54 		save_item(NAME(m_strobe_amount));
55 		save_item(NAME(m_optic_pattern));
56 		save_item(NAME(m_percent_mux));
57 	}
58 
DECLARE_WRITE_LINE_MEMBER(reel_optic_cb)59 	template <unsigned N> DECLARE_WRITE_LINE_MEMBER(reel_optic_cb) { if (state) m_optic_pattern |= (1 << N); else m_optic_pattern &= ~(1 << N); }
60 
ppi8255_intf_a_read_a()61 	uint8_t ppi8255_intf_a_read_a() { int ret = 0x00; logerror("%04x - ppi8255_intf_a_read_a %02x\n", m_maincpu->pcbase(), ret); return ret; }
ppi8255_intf_a_read_b()62 	uint8_t ppi8255_intf_a_read_b()
63 	{
64 		int ret = ioport("IN1")->read();
65 		logerror("%04x - ppi8255_intf_a_(used)read_b %02x\n", m_maincpu->pcbase(), ret);
66 		return ret;
67 	}
68 
ppi8255_intf_a_read_c()69 	uint8_t ppi8255_intf_a_read_c()
70 	{
71 		int ret = ioport("IN5")->read();
72 		logerror("%04x - ppi8255_intf_a_(used)read_c %02x\n", m_maincpu->pcbase(), ret);
73 		return ret;
74 	}
75 
ppi8255_intf_b_read_a()76 	uint8_t ppi8255_intf_b_read_a() { int ret = 0x00; logerror("%04x - ppi8255_intf_b_read_a %02x\n", m_maincpu->pcbase(), ret); return ret; }
ppi8255_intf_b_read_b()77 	uint8_t ppi8255_intf_b_read_b() { int ret = 0x00; logerror("%04x - ppi8255_intf_b_read_b %02x\n", m_maincpu->pcbase(), ret); return ret; }
ppi8255_intf_b_read_c()78 	uint8_t ppi8255_intf_b_read_c() { int ret = 0x00; logerror("%04x - ppi8255_intf_b_read_c %02x\n", m_maincpu->pcbase(), ret); return ret; }
79 
ppi8255_intf_c_read_a()80 	uint8_t ppi8255_intf_c_read_a() { int ret = 0x00; logerror("%04x - ppi8255_intf_c_(used)read_a %02x\n", m_maincpu->pcbase(), ret); return ret; }
ppi8255_intf_c_read_b()81 	uint8_t ppi8255_intf_c_read_b()
82 	{
83 		int ret = ioport("IN2")->read();
84 		logerror("%04x - ppi8255_intf_c_(used)read_b %02x (COINS+TEST)\n", m_maincpu->pcbase(), ret);
85 		return ret;
86 	} // changing to 00 gives coin tamper
87 
ppi8255_intf_c_read_c()88 	uint8_t ppi8255_intf_c_read_c()
89 	{
90 		int ret = ioport("IN6")->read();
91 		logerror("%04x - ppi8255_intf_c_(used)read_c %02x\n", m_maincpu->pcbase(), ret);
92 		return ret;
93 	}
94 
ppi8255_intf_d_read_a()95 	uint8_t ppi8255_intf_d_read_a() { int ret = 0x00; logerror("%04x - ppi8255_intf_d_read_a %02x\n", m_maincpu->pcbase(), ret); return ret; }
ppi8255_intf_d_read_b()96 	uint8_t ppi8255_intf_d_read_b()
97 	{
98 		int ret = ioport("IN7")->read();
99 		logerror("%04x - ppi8255_intf_d_(used)read_b %02x\n", m_maincpu->pcbase(), ret);
100 		return ret;
101 	}
102 
ppi8255_intf_d_read_c()103 	uint8_t ppi8255_intf_d_read_c()
104 	{
105 		// guess, what are the bottom 4 bits, if anything?
106 
107 		int ret = m_optic_pattern | (ioport("IN0")->read() & 0xf);
108 
109 		// | 0x80 = reel 4 fault
110 		// | 0x40 = reel 3 fault
111 		// | 0x20 = reel 2 fault
112 		// | 0x10 = reel 1 fault
113 
114 		logerror("%04x - ppi8255_intf_d_(used)read_c %02x (Reel Optics)\n", m_maincpu->pcbase(), ret);
115 
116 		return ret;
117 
118 
119 	}
120 
ppi8255_intf_e_read_a()121 	uint8_t ppi8255_intf_e_read_a() { int ret = 0x00; logerror("%04x - ppi8255_intf_e_read_a %02x\n", m_maincpu->pcbase(), ret); return ret; }
ppi8255_intf_e_read_b()122 	uint8_t ppi8255_intf_e_read_b()
123 	{   // changing gives no % key error in sphinx
124 
125 		int ret;
126 
127 		if (m_percent_mux==1)
128 		{
129 			ret = ioport("PERKEY")->read();
130 			logerror("%04x - ppi8255_intf_e_(used)read_b (PER KEY) %02x\n", m_maincpu->pcbase(), ret);
131 		}
132 		else if (m_percent_mux==0x80)
133 		{
134 			ret = ioport("BUTTONS")->read();
135 			logerror("%04x - ppi8255_intf_e_(used)read_b (BUTTONS?) %02x\n", m_maincpu->pcbase(), ret);
136 		}
137 		else
138 		{
139 			ret = 0x00;
140 			logerror("%04x - ppi8255_intf_e_(used)read_b (UNK MUX %02x) %02x\n", m_maincpu->pcbase(), m_percent_mux, ret);
141 		}
142 		return ret;
143 
144 	}
145 
ppi8255_intf_e_read_c()146 	uint8_t ppi8255_intf_e_read_c() { int ret = 0x00; logerror("%04x - ppi8255_intf_e_read_c %02x\n", m_maincpu->pcbase(), ret); return ret; }
147 
ppi8255_intf_f_read_a()148 	uint8_t ppi8255_intf_f_read_a()
149 	{
150 		int ret = ioport("IN4")->read();
151 		logerror("%04x - ppi8255_intf_f_(used)read_a %02x\n", m_maincpu->pcbase(), ret);
152 		return ret;
153 	}
154 
ppi8255_intf_f_read_b()155 	uint8_t ppi8255_intf_f_read_b() { int ret = 0x00; logerror("%04x - ppi8255_intf_f_read_b %02x\n", m_maincpu->pcbase(), ret); return ret; }
ppi8255_intf_f_read_c()156 	uint8_t ppi8255_intf_f_read_c() { int ret = 0x00; logerror("%04x - ppi8255_intf_f_read_c %02x\n", m_maincpu->pcbase(), ret); return ret; }
157 
ppi8255_intf_g_read_a()158 	uint8_t ppi8255_intf_g_read_a() { int ret = 0x00; logerror("%04x - ppi8255_intf_g_read_a %02x\n", m_maincpu->pcbase(), ret); return ret; }
ppi8255_intf_g_read_b()159 	uint8_t ppi8255_intf_g_read_b() { int ret = 0x00; logerror("%04x - ppi8255_intf_g_read_b %02x\n", m_maincpu->pcbase(), ret); return ret; }
ppi8255_intf_g_read_c()160 	uint8_t ppi8255_intf_g_read_c() { int ret = 0x00; logerror("%04x - ppi8255_intf_g_read_c %02x\n", m_maincpu->pcbase(), ret); return ret; }
161 
ppi8255_intf_h_read_a()162 	uint8_t ppi8255_intf_h_read_a() { int ret = 0x00; logerror("%04x - ppi8255_intf_h_read_a %02x\n", m_maincpu->pcbase(), ret); return ret; }
ppi8255_intf_h_read_b()163 	uint8_t ppi8255_intf_h_read_b()
164 	{
165 		int ret = ioport("IN5")->read();
166 		logerror("%04x - ppi8255_intf_h_(used)read_b %02x\n", m_maincpu->pcbase(), ret);
167 		return ret;
168 	}
ppi8255_intf_h_read_c()169 	uint8_t ppi8255_intf_h_read_c() { int ret = 0x00; logerror("%04x - ppi8255_intf_h_read_c %02x\n", m_maincpu->pcbase(), ret); return ret; }
170 
update_lamps()171 	void update_lamps()
172 	{
173 		for (int i=0; i<16; i++)
174 		{
175 			for (int bit=0; bit<16; bit++)
176 				m_lamp_outputs[(i << 4) | bit] = BIT(m_lamps[i], 15 - bit);
177 		}
178 
179 	}
180 
ppi8255_intf_a_write_a_strobedat0(uint8_t data)181 	void ppi8255_intf_a_write_a_strobedat0(uint8_t data)
182 	{
183 	//  logerror("%04x - ppi8255_intf_a_(used)write_a %02x (STROBEDAT?)\n", m_maincpu->pcbase(), data);
184 		if (m_strobe_amount)
185 		{
186 			m_lamps[m_strobe_addr] = (m_lamps[m_strobe_addr] & 0xff00) | (data & 0x00ff);
187 			m_strobe_amount--;
188 		}
189 	}
190 
ppi8255_intf_a_write_b_strobedat1(uint8_t data)191 	void ppi8255_intf_a_write_b_strobedat1(uint8_t data)
192 	{
193 	//  logerror("%04x - ppi8255_intf_a_(used)write_b %02x (STROBEDAT?)\n", m_maincpu->pcbase(), data);
194 		if (m_strobe_amount)
195 		{
196 			m_lamps[m_strobe_addr] = (m_lamps[m_strobe_addr] & 0x00ff) | (data << 8);
197 			m_strobe_amount--;
198 		}
199 	}
ppi8255_intf_a_write_c_strobe(uint8_t data)200 	void ppi8255_intf_a_write_c_strobe(uint8_t data)
201 	{
202 		if (data>=0xf0)
203 		{
204 		//  logerror("%04x - ppi8255_intf_a_(used)write_c %02x (STROBE?)\n", m_maincpu->pcbase(), data);
205 			m_strobe_addr = data & 0xf;
206 
207 			// hack, it writes values for the lamps, then writes 0x00 afterwards, probably giving the bulbs power, then removing the power
208 			// before switching the strobe to the next line?
209 			m_strobe_amount = 2;
210 
211 			update_lamps();
212 		}
213 		else logerror("%04x - ppi8255_intf_a_(used)write_c %02x (UNUSUAL?)\n", m_maincpu->pcbase(), data);
214 	}
215 
ppi8255_intf_b_write_a(uint8_t data)216 	void ppi8255_intf_b_write_a(uint8_t data) { logerror("%04x - ppi8255_intf_b_(used)write_a %02x\n", m_maincpu->pcbase(), data); }
ppi8255_intf_b_write_b(uint8_t data)217 	void ppi8255_intf_b_write_b(uint8_t data) { logerror("%04x - ppi8255_intf_b_(used)write_b %02x\n", m_maincpu->pcbase(), data); }
ppi8255_intf_b_write_c(uint8_t data)218 	void ppi8255_intf_b_write_c(uint8_t data) { logerror("%04x - ppi8255_intf_b_(used)write_c %02x\n", m_maincpu->pcbase(), data); }
219 
ppi8255_intf_c_write_a(uint8_t data)220 	void ppi8255_intf_c_write_a(uint8_t data) { logerror("%04x - ppi8255_intf_c_(used)write_a %02x\n", m_maincpu->pcbase(), data); }
ppi8255_intf_c_write_b(uint8_t data)221 	void ppi8255_intf_c_write_b(uint8_t data) { logerror("%04x - ppi8255_intf_c_(used)write_b %02x\n", m_maincpu->pcbase(), data); }
ppi8255_intf_c_write_c(uint8_t data)222 	void ppi8255_intf_c_write_c(uint8_t data) { logerror("%04x - ppi8255_intf_c_(used)write_c %02x\n", m_maincpu->pcbase(), data); }
223 
ppi8255_intf_d_write_a_reel01(uint8_t data)224 	void ppi8255_intf_d_write_a_reel01(uint8_t data)
225 	{
226 //      logerror("%04x - ppi8255_intf_d_(used)write_a %02x\n", m_maincpu->pcbase(), data);
227 		m_reels[0]->update( data    &0x0f);
228 		m_reels[1]->update((data>>4)&0x0f);
229 
230 		awp_draw_reel(machine(),"reel1", *m_reels[0]);
231 		awp_draw_reel(machine(),"reel2", *m_reels[1]);
232 	}
233 
ppi8255_intf_d_write_b_reel23(uint8_t data)234 	void ppi8255_intf_d_write_b_reel23(uint8_t data)
235 	{
236 //      logerror("%04x - ppi8255_intf_d_(used)write_b %02x\n", m_maincpu->pcbase(), data);
237 
238 		m_reels[2]->update( data    &0x0f);
239 		m_reels[3]->update((data>>4)&0x0f);
240 
241 		awp_draw_reel(machine(),"reel3", *m_reels[2]);
242 		awp_draw_reel(machine(),"reel4", *m_reels[3]);
243 	}
244 
ppi8255_intf_d_write_c(uint8_t data)245 	void ppi8255_intf_d_write_c(uint8_t data) { logerror("%04x - ppi8255_intf_d_(used)write_c %02x\n", m_maincpu->pcbase(), data);}
246 
247 	void ppi8255_intf_e_write_a_alpha_display(uint8_t data);
ppi8255_intf_e_write_b(uint8_t data)248 	void ppi8255_intf_e_write_b(uint8_t data) { logerror("%04x - ppi8255_intf_e_write_b %02x\n", m_maincpu->pcbase(), data); }
ppi8255_intf_e_write_c(uint8_t data)249 	void ppi8255_intf_e_write_c(uint8_t data)
250 	{
251 		m_percent_mux = data;
252 
253 		logerror("%04x - ppi8255_intf_e_write_c %02x (INPUT MUX?)\n", m_maincpu->pcbase(), data);
254 	}
255 
ppi8255_intf_f_write_a(uint8_t data)256 	void ppi8255_intf_f_write_a(uint8_t data) { logerror("%04x - ppi8255_intf_f_write_a %02x\n", m_maincpu->pcbase(), data); }
ppi8255_intf_f_write_b(uint8_t data)257 	void ppi8255_intf_f_write_b(uint8_t data) { logerror("%04x - ppi8255_intf_f_write_b %02x\n", m_maincpu->pcbase(), data); }
ppi8255_intf_f_write_c(uint8_t data)258 	void ppi8255_intf_f_write_c(uint8_t data) { logerror("%04x - ppi8255_intf_f_write_c %02x\n", m_maincpu->pcbase(), data); }
259 
ppi8255_intf_g_write_a(uint8_t data)260 	void ppi8255_intf_g_write_a(uint8_t data) { logerror("%04x - ppi8255_intf_g_write_a %02x\n", m_maincpu->pcbase(), data); }
ppi8255_intf_g_write_b(uint8_t data)261 	void ppi8255_intf_g_write_b(uint8_t data) { logerror("%04x - ppi8255_intf_g_write_b %02x\n", m_maincpu->pcbase(), data); }
ppi8255_intf_g_write_c(uint8_t data)262 	void ppi8255_intf_g_write_c(uint8_t data) { logerror("%04x - ppi8255_intf_g_write_c %02x\n", m_maincpu->pcbase(), data); }
263 
ppi8255_intf_h_write_a(uint8_t data)264 	void ppi8255_intf_h_write_a(uint8_t data) { logerror("%04x - ppi8255_intf_h_(used)write_a %02x\n", m_maincpu->pcbase(), data); }
ppi8255_intf_h_write_b(uint8_t data)265 	void ppi8255_intf_h_write_b(uint8_t data) { logerror("%04x - ppi8255_intf_h_(used)write_b %02x\n", m_maincpu->pcbase(), data); }
ppi8255_intf_h_write_c(uint8_t data)266 	void ppi8255_intf_h_write_c(uint8_t data) { logerror("%04x - ppi8255_intf_h_(used)write_c %02x\n", m_maincpu->pcbase(), data); }
267 
268 	void pyramid_memmap(address_map &map);
269 	void pyramid_portmap(address_map &map);
270 
271 	required_device<z180_device> m_maincpu;
272 	required_device_array<stepper_device, 4> m_reels;
273 	output_finder<16 * 16> m_lamp_outputs;
274 	output_finder<14> m_vfd_outputs;
275 
276 	uint16_t m_lamps[16];
277 	uint16_t m_chars[14];
278 
279 	int m_strobe_addr = 0;
280 	int m_strobe_amount = 0;
281 	int m_optic_pattern = 0;
282 
283 	int m_percent_mux = 0;
284 };
285 
286 
287 // this is a copy of roc10937charset for now, I don't know what chip we're meant be using here
288 // it is some kind of 14 digit, 16 seg display tho
289 static const uint16_t ecoin_charset[]=
290 {            // FEDC BA98 7654 3210
291 	0x507F, // 0101 0000 0111 1111 @.
292 	0x44CF, // 0100 0100 1100 1111 A.
293 	0x153F, // 0001 0101 0011 1111 B.
294 	0x00F3, // 0000 0000 1111 0011 C.
295 	0x113F, // 0001 0001 0011 1111 D.
296 	0x40F3, // 0100 0000 1111 0011 E.
297 	0x40C3, // 0100 0000 1100 0011 F.
298 	0x04FB, // 0000 0100 1111 1011 G.
299 	0x44CC, // 0100 0100 1100 1100 H.
300 	0x1133, // 0001 0001 0011 0011 I.
301 	0x007C, // 0000 0000 0111 1100 J.
302 	0x4AC0, // 0100 1010 1100 0000 K.
303 	0x00F0, // 0000 0000 1111 0000 L.
304 	0x82CC, // 1000 0010 1100 1100 M.
305 	0x88CC, // 1000 1000 1100 1100 N.
306 	0x00FF, // 0000 0000 1111 1111 O.
307 	0x44C7, // 0100 0100 1100 0111 P.
308 	0x08FF, // 0000 1000 1111 1111 Q.
309 	0x4CC7, // 0100 1100 1100 0111 R.
310 	0x44BB, // 0100 0100 1011 1011 S.
311 	0x1103, // 0001 0001 0000 0011 T.
312 	0x00FC, // 0000 0000 1111 1100 U.
313 	0x22C0, // 0010 0010 1100 0000 V.
314 	0x28CC, // 0010 1000 1100 1100 W.
315 	0xAA00, // 1010 1010 0000 0000 X.
316 	0x9200, // 1001 0010 0000 0000 Y.
317 	0x2233, // 0010 0010 0011 0011 Z.
318 	0x00E1, // 0000 0000 1110 0001 [.
319 	0x8800, // 1000 1000 0000 0000 \.
320 	0x001E, // 0000 0000 0001 1110 ].
321 	0x2800, // 0010 1000 0000 0000 ^.
322 	0x0030, // 0000 0000 0011 0000 _.
323 	0x0000, // 0000 0000 0000 0000 dummy.
324 	0x8121, // 1000 0001 0010 0001 !.
325 	0x0180, // 0000 0001 1000 0000 ".
326 	0x553C, // 0101 0101 0011 1100 #.
327 	0x55BB, // 0101 0101 1011 1011 $.
328 	0x7799, // 0111 0111 1001 1001 %.
329 	0xC979, // 1100 1001 0111 1001 &.
330 	0x0200, // 0000 0010 0000 0000 '.
331 	0x0A00, // 0000 1010 0000 0000 (.
332 	0xA050, // 1010 0000 0000 0000 ).
333 	0xFF00, // 1111 1111 0000 0000 *.
334 	0x5500, // 0101 0101 0000 0000 +.
335 	0x0000, // 0000 0000 0000 0000 ;. (Set separately)
336 	0x4400, // 0100 0100 0000 0000 --.
337 	0x0000, // 0000 0000 0000 0000 . .(Set separately)
338 	0x2200, // 0010 0010 0000 0000 /.
339 	0x22FF, // 0010 0010 1111 1111 0.
340 	0x1100, // 0001 0001 0000 0000 1.
341 	0x4477, // 0100 0100 0111 0111 2.
342 	0x443F, // 0100 0100 0011 1111 3.
343 	0x448C, // 0100 0100 1000 1100 4.
344 	0x44BB, // 0100 0100 1011 1011 5.
345 	0x44FB, // 0100 0100 1111 1011 6.
346 	0x000F, // 0000 0000 0000 1111 7.
347 	0x44FF, // 0100 0100 1111 1111 8.
348 	0x44BF, // 0100 0100 1011 1111 9.
349 	0x0021, // 0000 0000 0010 0001 -
350 			//                     -.
351 	0x2001, // 0010 0000 0000 0001 -
352 			//                     /.
353 	0x2430, // 0010 0100 0011 0000 <.
354 	0x4430, // 0100 0100 0011 0000 =.
355 	0x8830, // 1000 1000 0011 0000 >.
356 	0x1407, // 0001 0100 0000 0111 ?.
357 };
358 
set_display(uint32_t segin)359 static uint32_t set_display(uint32_t segin)
360 {
361 	return bitswap<32>(segin, 31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,11,9,15,13,12,8,10,14,7,6,5,4,3,2,1,0);
362 }
363 
364 // is the 2 digit bank display part of this, or multiplexed elsewhere
ppi8255_intf_e_write_a_alpha_display(uint8_t data)365 void ecoinf3_state::ppi8255_intf_e_write_a_alpha_display(uint8_t data)
366 {
367 	if ((data>=0x20) && (data<0x5b))  logerror("%04x - ppi8255_intf_e_write_a %02x (alpha) '%c'\n", m_maincpu->pcbase(), data, data);
368 	else logerror("%04x - ppi8255_intf_e_write_a %02x (alpha)\n", m_maincpu->pcbase(), data);
369 
370 	static uint8_t send_buffer = 0;
371 	static int count = 0;
372 	// writes the 'PYRAMID' string from RAM (copied from ROM) here...
373 	// along with port 40/41/42 accesses
374 	// also error messages? (well it looks like it should, but code is strange and skips them) I guess it's a debug port or the vfd?
375 	// watch ram around e3e0
376 
377 	// Pyramid - Writes PYRAMID V6, and 10MS INIT ERROR
378 	// Labyrinth - Same behavior as Pyramid
379 	// Secret Castle - Same behavior as Pyramid
380 
381 	// Sphinx - Writes "No % Key"  -- depends on port 0x51, writes "SPHINX  V- 1" if it's happy with that .. after that you get COIN TAMPER,  a count down with COINS TRIM and a reboot
382 	// Pennies from Heaven - same behavior as Sphinx
383 
384 	// typically writes a letter (sometimes twice) then 0x00, usually twice
385 
386 	if (data==0x00)
387 	{
388 		if (send_buffer!=0x00)
389 		{
390 			if ((send_buffer>=0x20) && (send_buffer<0x5b))
391 			{
392 				if (count<14)
393 				{
394 					int chr = send_buffer & 0x3f;
395 
396 					if (chr>0 && chr<0x3f)
397 						m_chars[count] =  ecoin_charset[chr];
398 
399 				}
400 				//printf("%c", send_buffer);
401 			}
402 			else
403 			{
404 				// control characters?
405 				//printf(" (%02x) ", send_buffer);
406 				count = -1;
407 			}
408 
409 			count++;
410 			if (count%14 == 0)
411 			{
412 				//printf("\n");
413 				count = 0;
414 
415 			}
416 
417 
418 			send_buffer = 0x00;
419 		}
420 	}
421 	else
422 	{
423 		send_buffer = data;
424 	}
425 
426 	std::transform(std::begin(m_chars), std::end(m_chars), std::begin(m_vfd_outputs), set_display);
427 }
428 
pyramid_memmap(address_map & map)429 void ecoinf3_state::pyramid_memmap(address_map &map)
430 {
431 	map(0x0000, 0xdfff).rom();
432 	map(0xe000, 0xffff).ram();
433 }
434 
pyramid_portmap(address_map & map)435 void ecoinf3_state::pyramid_portmap(address_map &map)
436 {
437 	map.global_mask(0xff);
438 	map(0x00, 0x3f).ram(); // z180 internal area!
439 
440 	map(0x40, 0x43).rw("ppi8255_a", FUNC(i8255_device::read), FUNC(i8255_device::write));
441 	map(0x44, 0x47).rw("ppi8255_b", FUNC(i8255_device::read), FUNC(i8255_device::write));
442 	map(0x48, 0x4b).rw("ppi8255_c", FUNC(i8255_device::read), FUNC(i8255_device::write));
443 	map(0x4c, 0x4f).rw("ppi8255_d", FUNC(i8255_device::read), FUNC(i8255_device::write));
444 	map(0x50, 0x53).rw("ppi8255_e", FUNC(i8255_device::read), FUNC(i8255_device::write));
445 	map(0x54, 0x57).rw("ppi8255_f", FUNC(i8255_device::read), FUNC(i8255_device::write));
446 	map(0x58, 0x5b).rw("ppi8255_g", FUNC(i8255_device::read), FUNC(i8255_device::write));
447 	map(0x5c, 0x5f).rw("ppi8255_h", FUNC(i8255_device::read), FUNC(i8255_device::write));
448 	// frequently accesses DB after 5B, mirror? bug?
449 	map(0xDB, 0xDB).w("sn1", FUNC(sn76489_device::write));  // no idea what the sound chip is, this sounds terrible
450 
451 
452 }
453 
454 
455 
456 
457 static INPUT_PORTS_START( ecoinf3 )
458 	PORT_START("IN0")
459 	PORT_DIPNAME( 0x01, 0x01, "IN0:01" )
DEF_STR(Off)460 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
461 	PORT_DIPSETTING(    0x01, DEF_STR( On ) )
462 	PORT_DIPNAME( 0x02, 0x02, "IN0:02" )
463 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
464 	PORT_DIPSETTING(    0x02, DEF_STR( On ) )
465 	PORT_DIPNAME( 0x04, 0x04, "IN0:04" )
466 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
467 	PORT_DIPSETTING(    0x04, DEF_STR( On ) )
468 	PORT_DIPNAME( 0x08, 0x08, "IN0:08" )
469 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
470 	PORT_DIPSETTING(    0x08, DEF_STR( On ) )
471 
472 	PORT_START("IN1")
473 	PORT_DIPNAME( 0x01, 0x01, "IN1:01" )
474 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
475 	PORT_DIPSETTING(    0x01, DEF_STR( On ) )
476 	PORT_DIPNAME( 0x02, 0x02, "IN1:02" )
477 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
478 	PORT_DIPSETTING(    0x02, DEF_STR( On ) )
479 	PORT_DIPNAME( 0x04, 0x04, "IN1:04" )
480 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
481 	PORT_DIPSETTING(    0x04, DEF_STR( On ) )
482 	PORT_DIPNAME( 0x08, 0x08, "IN1:08" )
483 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
484 	PORT_DIPSETTING(    0x08, DEF_STR( On ) )
485 	PORT_DIPNAME( 0x10, 0x10, "IN1:18" )
486 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
487 	PORT_DIPSETTING(    0x10, DEF_STR( On ) )
488 	PORT_DIPNAME( 0x20, 0x20, "IN1:20" )
489 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
490 	PORT_DIPSETTING(    0x20, DEF_STR( On ) )
491 	PORT_DIPNAME( 0x40, 0x40, "IN1:40" )
492 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
493 	PORT_DIPSETTING(    0x40, DEF_STR( On ) )
494 	PORT_DIPNAME( 0x80, 0x80, "IN1:80" )
495 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
496 	PORT_DIPSETTING(    0x80, DEF_STR( On ) )
497 
498 	PORT_START("IN2")
499 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
500 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
501 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN3 )
502 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN4 )
503 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN5 )
504 	PORT_DIPNAME( 0x20, 0x20, "IN2:20" )
505 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
506 	PORT_DIPSETTING(    0x20, DEF_STR( On ) )
507 	PORT_DIPNAME( 0x40, 0x40, "IN2:40" )
508 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
509 	PORT_DIPSETTING(    0x40, DEF_STR( On ) )
510 	PORT_DIPNAME( 0x80, 0x80, "IN2:80" )
511 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
512 	PORT_DIPSETTING(    0x80, DEF_STR( On ) )
513 
514 	PORT_START("PERKEY")
515 	PORT_DIPNAME( 0x0f, 0x00, "% Key?" )
516 	PORT_DIPSETTING(    0x00, "0x00" )
517 	PORT_DIPSETTING(    0x01, "0x01" )
518 	PORT_DIPSETTING(    0x02, "0x02" )
519 	PORT_DIPSETTING(    0x03, "0x03" )
520 	PORT_DIPSETTING(    0x04, "0x04" )
521 	PORT_DIPSETTING(    0x05, "0x05" )
522 	PORT_DIPSETTING(    0x06, "0x06" )
523 	PORT_DIPSETTING(    0x07, "0x07" )
524 	PORT_DIPSETTING(    0x08, "0x08" )
525 	PORT_DIPSETTING(    0x09, "0x09" )
526 	PORT_DIPSETTING(    0x0a, "0x0a" )
527 	PORT_DIPSETTING(    0x0b, "0x0b" )
528 	PORT_DIPSETTING(    0x0c, "0x0c" )
529 	PORT_DIPSETTING(    0x0d, "0x0d" )
530 	PORT_DIPSETTING(    0x0e, "0x0e" )
531 	PORT_DIPSETTING(    0x0f, "None" )
532 	PORT_DIPNAME( 0x10, 0x10, "PER_KEY:10" )
533 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
534 	PORT_DIPSETTING(    0x10, DEF_STR( On ) )
535 	PORT_DIPNAME( 0x20, 0x20, "PER_KEY:20" )
536 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
537 	PORT_DIPSETTING(    0x20, DEF_STR( On ) )
538 	PORT_DIPNAME( 0x40, 0x40, "PER_KEY:40" )
539 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
540 	PORT_DIPSETTING(    0x40, DEF_STR( On ) )
541 	PORT_DIPNAME( 0x80, 0x80, "PER_KEY:80" )
542 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
543 	PORT_DIPSETTING(    0x80, DEF_STR( On ) )
544 
545 	PORT_START("BUTTONS")
546 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Nudge / Hold 3") PORT_CODE(KEYCODE_D)
547 	PORT_DIPNAME( 0x02, 0x02, "BT:02" )
548 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
549 	PORT_DIPSETTING(    0x02, DEF_STR( On ) )
550 	PORT_DIPNAME( 0x04, 0x04, "BT:04" )
551 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
552 	PORT_DIPSETTING(    0x04, DEF_STR( On ) )
553 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("Cancel Holds") PORT_CODE(KEYCODE_F)
554 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Nudge / Hold 1") PORT_CODE(KEYCODE_A)
555 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 )
556 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Nudge / Hold 2") PORT_CODE(KEYCODE_S)
557 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START1 ) // ?? advances through test items, spins the reels
558 
559 	PORT_START("IN4")
560 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON7 ) // causes various spins etc. (but also causes the whole thing to freak out?)
561 	PORT_DIPNAME( 0x02, 0x02, "IN4:02" )
562 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
563 	PORT_DIPSETTING(    0x02, DEF_STR( On ) )
564 	PORT_DIPNAME( 0x04, 0x04, "IN4:04" )
565 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
566 	PORT_DIPSETTING(    0x04, DEF_STR( On ) )
567 	PORT_DIPNAME( 0x08, 0x08, "IN4:08" )
568 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
569 	PORT_DIPSETTING(    0x08, DEF_STR( On ) )
570 	PORT_DIPNAME( 0x10, 0x10, "IN4:10" )
571 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
572 	PORT_DIPSETTING(    0x10, DEF_STR( On ) )
573 	PORT_DIPNAME( 0x20, 0x20, "IN4:20" )
574 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
575 	PORT_DIPSETTING(    0x20, DEF_STR( On ) )
576 	PORT_DIPNAME( 0x40, 0x40, "IN4:40" )
577 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
578 	PORT_DIPSETTING(    0x40, DEF_STR( On ) )
579 	PORT_DIPNAME( 0x80, 0x80, "IN4:80" )
580 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
581 	PORT_DIPSETTING(    0x80, DEF_STR( On ) )
582 
583 	PORT_START("IN5")
584 	PORT_DIPNAME( 0x01, 0x01, "IN5:01" )
585 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
586 	PORT_DIPSETTING(    0x01, DEF_STR( On ) )
587 	PORT_DIPNAME( 0x02, 0x02, "IN5:02" )
588 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
589 	PORT_DIPSETTING(    0x02, DEF_STR( On ) )
590 	PORT_DIPNAME( 0x04, 0x04, "IN5:04" )
591 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
592 	PORT_DIPSETTING(    0x04, DEF_STR( On ) )
593 	PORT_DIPNAME( 0x08, 0x08, "IN5:08" )
594 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
595 	PORT_DIPSETTING(    0x08, DEF_STR( On ) )
596 	PORT_DIPNAME( 0x10, 0x10, "Meter Connection (leave on)" )
597 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
598 	PORT_DIPSETTING(    0x10, DEF_STR( On ) )
599 	PORT_DIPNAME( 0x20, 0x20, "IN5:20" )
600 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
601 	PORT_DIPSETTING(    0x20, DEF_STR( On ) )
602 	PORT_DIPNAME( 0x40, 0x40, "IN5:40" )
603 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
604 	PORT_DIPSETTING(    0x40, DEF_STR( On ) )
605 	PORT_DIPNAME( 0x80, 0x80, "IN5:80" )
606 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
607 	PORT_DIPSETTING(    0x80, DEF_STR( On ) )
608 
609 	PORT_START("IN6")
610 	PORT_DIPNAME( 0x01, 0x01, "IN6:01" )
611 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
612 	PORT_DIPSETTING(    0x01, DEF_STR( On ) )
613 	PORT_DIPNAME( 0x02, 0x02, "IN6:02" )
614 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
615 	PORT_DIPSETTING(    0x02, DEF_STR( On ) )
616 	PORT_DIPNAME( 0x04, 0x04, "IN6:04" )
617 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
618 	PORT_DIPSETTING(    0x04, DEF_STR( On ) )
619 	PORT_DIPNAME( 0x08, 0x08, "IN6:08" )
620 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
621 	PORT_DIPSETTING(    0x08, DEF_STR( On ) )
622 	PORT_DIPNAME( 0x10, 0x10, "IN6:10" )
623 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
624 	PORT_DIPSETTING(    0x10, DEF_STR( On ) )
625 	PORT_DIPNAME( 0x20, 0x20, "IN6:20" )
626 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
627 	PORT_DIPSETTING(    0x20, DEF_STR( On ) )
628 	PORT_DIPNAME( 0x40, 0x40, "IN6:40" )
629 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
630 	PORT_DIPSETTING(    0x40, DEF_STR( On ) )
631 	PORT_DIPNAME( 0x80, 0x80, "IN6:80" )
632 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
633 	PORT_DIPSETTING(    0x80, DEF_STR( On ) )
634 
635 	PORT_START("IN7")
636 	PORT_DIPNAME( 0x01, 0x01, "IN7:01" )
637 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
638 	PORT_DIPSETTING(    0x01, DEF_STR( On ) )
639 	PORT_DIPNAME( 0x02, 0x02, "IN7:02" )
640 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
641 	PORT_DIPSETTING(    0x02, DEF_STR( On ) )
642 	PORT_DIPNAME( 0x04, 0x04, "IN7:04" )
643 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
644 	PORT_DIPSETTING(    0x04, DEF_STR( On ) )
645 	PORT_DIPNAME( 0x08, 0x08, "IN7:08" )
646 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
647 	PORT_DIPSETTING(    0x08, DEF_STR( On ) )
648 	PORT_DIPNAME( 0x10, 0x10, "IN7:10" )
649 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
650 	PORT_DIPSETTING(    0x10, DEF_STR( On ) )
651 	PORT_DIPNAME( 0x20, 0x20, "IN7:20" )
652 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
653 	PORT_DIPSETTING(    0x20, DEF_STR( On ) )
654 	PORT_DIPNAME( 0x40, 0x40, "IN7:40" )
655 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
656 	PORT_DIPSETTING(    0x40, DEF_STR( On ) )
657 	PORT_DIPNAME( 0x80, 0x80, "IN7:80" )
658 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
659 	PORT_DIPSETTING(    0x80, DEF_STR( On ) )
660 INPUT_PORTS_END
661 
662 
663 void ecoinf3_state::ecoinf3_pyramid(machine_config &config)
664 {
665 	/* basic machine hardware */
666 	Z80180(config, m_maincpu, 8000000); // certainly not a plain z80 at least, invalid opcodes for that
667 	m_maincpu->set_addrmap(AS_PROGRAM, &ecoinf3_state::pyramid_memmap);
668 	m_maincpu->set_addrmap(AS_IO, &ecoinf3_state::pyramid_portmap);
669 
670 	config.set_default_layout(layout_ecoinf3);
671 
672 	SPEAKER(config, "mono").front_center();
673 
674 	SN76489(config, "sn1", 4000000).add_route(ALL_OUTPUTS, "mono", 0.30); // no idea what the sound chip is, this sounds terrible
675 
676 	i8255_device &ppia(I8255(config, "ppi8255_a"));
677 	ppia.in_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_a_read_a));
678 	ppia.out_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_a_write_a_strobedat0));
679 	ppia.in_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_a_read_b));
680 	ppia.out_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_a_write_b_strobedat1));
681 	ppia.in_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_a_read_c));
682 	ppia.out_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_a_write_c_strobe));
683 
684 	i8255_device &ppib(I8255(config, "ppi8255_b"));
685 	ppib.in_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_b_read_a));
686 	ppib.out_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_b_write_a));
687 	ppib.in_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_b_read_b));
688 	ppib.out_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_b_write_b));
689 	ppib.in_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_b_read_c));
690 	ppib.out_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_b_write_c));
691 
692 	i8255_device &ppic(I8255(config, "ppi8255_c"));
693 	ppic.in_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_c_read_a));
694 	ppic.out_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_c_write_a));
695 	ppic.in_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_c_read_b));
696 	ppic.out_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_c_write_b));
697 	ppic.in_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_c_read_c));
698 	ppic.out_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_c_write_c));
699 
700 	i8255_device &ppid(I8255(config, "ppi8255_d"));
701 	ppid.in_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_d_read_a));
702 	ppid.out_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_d_write_a_reel01));
703 	ppid.in_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_d_read_b));
704 	ppid.out_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_d_write_b_reel23));
705 	ppid.in_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_d_read_c));
706 	ppid.out_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_d_write_c));
707 
708 	i8255_device &ppie(I8255(config, "ppi8255_e"));
709 	ppie.in_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_e_read_a));
710 	ppie.out_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_e_write_a_alpha_display));    // alpha display characters
711 	ppie.in_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_e_read_b));
712 	ppie.out_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_e_write_b));  // not written at an appropriate time for it to be a 'send' address for the text
713 	ppie.in_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_e_read_c));
714 	ppie.out_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_e_write_c));  // not written at an appropriate time for it to be a 'send' address for the text
715 
716 	i8255_device &ppif(I8255(config, "ppi8255_f"));
717 	ppif.in_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_f_read_a));
718 	ppif.out_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_f_write_a));
719 	ppif.in_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_f_read_b));
720 	ppif.out_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_f_write_b));
721 	ppif.in_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_f_read_c));
722 	ppif.out_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_f_write_c));
723 
724 	i8255_device &ppig(I8255(config, "ppi8255_g"));
725 	ppig.in_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_g_read_a));
726 	ppig.out_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_g_write_a));
727 	ppig.in_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_g_read_b));
728 	ppig.out_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_g_write_b));
729 	ppig.in_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_g_read_c));
730 	ppig.out_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_g_write_c));
731 
732 	i8255_device &ppih(I8255(config, "ppi8255_h"));
733 	ppih.in_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_h_read_a));
734 	ppih.out_pa_callback().set(FUNC(ecoinf3_state::ppi8255_intf_h_write_a));
735 	ppih.in_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_h_read_b));
736 	ppih.out_pb_callback().set(FUNC(ecoinf3_state::ppi8255_intf_h_write_b));
737 	ppih.in_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_h_read_c));
738 	ppih.out_pc_callback().set(FUNC(ecoinf3_state::ppi8255_intf_h_write_c));
739 
740 	REEL(config, m_reels[0], ECOIN_200STEP_REEL, 12, 24, 0x09, 7, 200*2);
741 	m_reels[0]->optic_handler().set(FUNC(ecoinf3_state::reel_optic_cb<0>));
742 	REEL(config, m_reels[1], ECOIN_200STEP_REEL, 12, 24, 0x09, 7, 200*2);
743 	m_reels[1]->optic_handler().set(FUNC(ecoinf3_state::reel_optic_cb<1>));
744 	REEL(config, m_reels[2], ECOIN_200STEP_REEL, 12, 24, 0x09, 7, 200*2);
745 	m_reels[2]->optic_handler().set(FUNC(ecoinf3_state::reel_optic_cb<2>));
746 	REEL(config, m_reels[3], ECOIN_200STEP_REEL, 12, 24, 0x09, 7, 200*2);
747 	m_reels[3]->optic_handler().set(FUNC(ecoinf3_state::reel_optic_cb<3>));
748 }
749 
750 
751 /********************************************************************************************************************
752  ROMs for PYRAMID Hw Type
753 ********************************************************************************************************************/
754 
755 ROM_START( ec_pyram )
756 	ROM_REGION( 0x200000, "maincpu", 0 ) /* the last 0x2000 bytes (unmapped?) are the same as on the ec_sphin set */
757 	ROM_LOAD( "pyramid.bin", 0x0000, 0x010000, CRC(370a6d2c) SHA1(ea4f899adeca734529b19ba8de0e371841982c20) )
758 ROM_END
759 
ROM_START(ec_pyrama)760 ROM_START( ec_pyrama )
761 	ROM_REGION( 0x200000, "maincpu", 0 )
762 	ROM_LOAD( "pyramid 5p 3.bin", 0x0000, 0x010000, CRC(06a047d8) SHA1(4a1a15f1ab9defd3a0c5f2d333beae0daa16c6a4) )
763 ROM_END
764 
765 ROM_START( ec_sphin ) /* the last 0x2000 bytes (unmapped?) are the same as on the ec_pyram set */
766 	ROM_REGION( 0x200000, "maincpu", 0 )
767 	ROM_LOAD( "spnx5p", 0x0000, 0x010000, CRC(b4b49259) SHA1(a26172b659b739564b25dcc0f3f31f131a144d52) )
768 ROM_END
769 
770 ROM_START( ec_sphina )
771 	ROM_REGION( 0x200000, "maincpu", 0 )
772 	ROM_LOAD( "spx10cv2.bin", 0x0000, 0x00e000, CRC(e2bf11a0) SHA1(f267385dbb06b2be8bcad7ae5e5804f5bb467f6d) )
773 ROM_END
774 
775 ROM_START( ec_sphinb )
776 	ROM_REGION( 0x200000, "maincpu", 0 ) // z80 ROMS but truncated, other sets just seem to contain garbage at the end tho, so probably OK
777 	ROM_LOAD( "sphinx8c.bin", 0x0000, 0x00e000, CRC(f8e110fc) SHA1(4f55b5de87151f9127b84ffcf7f6f2e3ce34469f) )
778 ROM_END
779 
780 ROM_START( ec_penni )
781 	ROM_REGION( 0x200000, "maincpu", 0 )
782 	ROM_LOAD( "pfh_8c.bin", 0x0000, 0x010000, CRC(282a42d8) SHA1(f985d238c72577e755090ce0f04dcc7850af6f3b) )
783 ROM_END
784 
785 ROM_START( ec_pennia )
786 	ROM_REGION( 0x200000, "maincpu", 0 ) // z80 ROMS but truncated, other sets just seem to contain garbage at the end tho, so probably OK
787 	ROM_LOAD( "pfh_v6.bin", 0x0000, 0x00e000, CRC(febb3fce) SHA1(f8df085a563405ea5adcd15a4162a7ba56bcfad7) )
788 ROM_END
789 
790 
791 ROM_START( ec_stair )
792 	ROM_REGION( 0x200000, "maincpu", 0 )
793 	ROM_LOAD("sth5.4",      0x0000, 0x010000, CRC(879c8dcb) SHA1(358d9bb567da4b7913434d29dcd8a81c51c5fe2e) )
794 ROM_END
795 
796 ROM_START( ec_staira )
797 	ROM_REGION( 0x200000, "maincpu", 0 )
798 	ROM_LOAD("sth5.8c", 0x0000, 0x010000, CRC(7ce6b760) SHA1(c828689481d7e187c504dd072bd6714222888d33) )
799 ROM_END
800 
801 
802 
803 ROM_START( ec_laby ) // no header info with these
804 	ROM_REGION( 0x200000, "maincpu", 0 )
805 	ROM_LOAD( "lab1v8.bin", 0x0000, 0x008000, CRC(16f0eeac) SHA1(9e28a6ae9176f730234dd8a7a8e50bad2904b611) )
806 	ROM_LOAD( "lab2v8.bin", 0x8000, 0x008000, CRC(14d7c58b) SHA1(e6b19523d96c9c1f39b743f8c52791465ab79637) )
807 ROM_END
808 
809 ROM_START( ec_labya ) // no header info with these
810 	ROM_REGION( 0x200000, "maincpu", 0 )
811 	ROM_LOAD( "laby10", 0x0000, 0x010000, CRC(a8b58fc3) SHA1(16e940b04fa85ff85a29197b4e45c8a39f5cad19) )
812 ROM_END
813 
814 ROM_START( ec_secrt )
815 	ROM_REGION( 0x200000, "maincpu", 0 )
816 	ROM_LOAD( "scastle1.bin", 0x0000, 0x010000, CRC(e6abb596) SHA1(35518c46f1ddf1d3a85af13e4ba8bee07e804f64) )
817 ROM_END
818 
819 void ecoinf3_state::init_ecoinf3()
820 {
821 }
822 
init_ecoinf3_swap()823 void ecoinf3_state::init_ecoinf3_swap()
824 {
825 	// not all sets have this, are they just badly dumped?
826 	uint8_t table[] =
827 	{
828 		0x48, 0x4c, 0x49, 0x4d, 0x40, 0x44, 0x41, 0x45,     0x68, 0x78, 0x60, 0x70, 0x6a, 0x7a, 0x62, 0x72,
829 		0x08, 0x0c, 0x09, 0x0d, 0x00, 0x04, 0x01, 0x05,     0x6c, 0x7c, 0x64, 0x74, 0x6e, 0x7e, 0x66, 0x76,
830 		0x58, 0x5c, 0x59, 0x5d, 0x50, 0x54, 0x51, 0x55,     0x28, 0x38, 0x20, 0x30, 0x2a, 0x3a, 0x22, 0x32,
831 		0x18, 0x1c, 0x19, 0x1d, 0x10, 0x14, 0x11, 0x15,     0x2c, 0x3c, 0x24, 0x34, 0x2e, 0x3e, 0x26, 0x36,
832 		0x56, 0x52, 0x57, 0x53, 0x5e, 0x5a, 0x5f, 0x5b,     0x75, 0x65, 0x7d, 0x6d, 0x77, 0x67, 0x7f ,0x6f,
833 		0x16, 0x12, 0x17, 0x13, 0x1e, 0x1a, 0x1f, 0x1b,     0x71, 0x61, 0x79, 0x69, 0x73, 0x63, 0x7b, 0x6b,
834 		0x46, 0x42, 0x47, 0x43, 0x4e, 0x4a, 0x4f, 0x4b,     0x35, 0x25, 0x3d, 0x2d, 0x37, 0x27, 0x3f ,0x2f,
835 		0x06, 0x02, 0x07, 0x03, 0x0e, 0x0a, 0x0f, 0x0b,     0x31, 0x21, 0x39, 0x29, 0x33, 0x23, 0x3b, 0x2b,
836 	};
837 
838 	auto buffer = std::make_unique<uint8_t[]>(0x10000);
839 	uint8_t *rom = memregion( "maincpu" )->base();
840 	for (int i = 0; i < 0x10000; i++)
841 	{
842 		buffer[i] = rom[(i&0xff80)|table[i&0x7f]];
843 	}
844 
845 	memcpy(rom,buffer.get(),0x10000);
846 
847 }
848 
849 
850 
851 // another hw type (similar to stuff in ecoinf2.c) (watchdog on port 58?)
852 GAME( 19??, ec_pyram,  0,        ecoinf3_pyramid, ecoinf3, ecoinf3_state, init_ecoinf3_swap, ROT0, "Electrocoin", "Pyramid (v1) (Electrocoin)",             MACHINE_NO_SOUND|MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING|MACHINE_MECHANICAL)
853 GAME( 19??, ec_pyrama, ec_pyram, ecoinf3_pyramid, ecoinf3, ecoinf3_state, init_ecoinf3,      ROT0, "Electrocoin", "Pyramid (v6) (Electrocoin)",             MACHINE_NO_SOUND|MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING|MACHINE_MECHANICAL)
854 GAME( 19??, ec_sphin,  0,        ecoinf3_pyramid, ecoinf3, ecoinf3_state, init_ecoinf3_swap, ROT0, "Electrocoin", "Sphinx (v2) (Electrocoin) (set 1)",      MACHINE_NO_SOUND|MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING|MACHINE_MECHANICAL)
855 GAME( 19??, ec_sphina, ec_sphin, ecoinf3_pyramid, ecoinf3, ecoinf3_state, init_ecoinf3,      ROT0, "Electrocoin", "Sphinx (v2) (Electrocoin) (set 2)",      MACHINE_NO_SOUND|MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING|MACHINE_MECHANICAL)
856 GAME( 19??, ec_sphinb, ec_sphin, ecoinf3_pyramid, ecoinf3, ecoinf3_state, init_ecoinf3,      ROT0, "Electrocoin", "Sphinx (v1) (Electrocoin)",              MACHINE_NO_SOUND|MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING|MACHINE_MECHANICAL)
857 GAME( 19??, ec_penni,  0,        ecoinf3_pyramid, ecoinf3, ecoinf3_state, init_ecoinf3,      ROT0, "Electrocoin", "Pennies From Heaven (v1) (Electrocoin)", MACHINE_NO_SOUND|MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING|MACHINE_MECHANICAL)
858 GAME( 19??, ec_pennia, ec_penni, ecoinf3_pyramid, ecoinf3, ecoinf3_state, init_ecoinf3,      ROT0, "Electrocoin", "Pennies From Heaven (v6) (Electrocoin)", MACHINE_NO_SOUND|MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING|MACHINE_MECHANICAL)
859 GAME( 19??, ec_stair,  0,        ecoinf3_pyramid, ecoinf3, ecoinf3_state, init_ecoinf3,      ROT0, "Electrocoin", "Stairway To Heaven (v11) (Electrocoin)", MACHINE_NO_SOUND|MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING|MACHINE_MECHANICAL)
860 GAME( 19??, ec_staira, ec_stair, ecoinf3_pyramid, ecoinf3, ecoinf3_state, init_ecoinf3,      ROT0, "Electrocoin", "Stairway To Heaven (v1) (Electrocoin)",  MACHINE_NO_SOUND|MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING|MACHINE_MECHANICAL)
861 GAME( 19??, ec_laby,   0,        ecoinf3_pyramid, ecoinf3, ecoinf3_state, init_ecoinf3,      ROT0, "Electrocoin", "Labyrinth (v8) (Electrocoin)",           MACHINE_NO_SOUND|MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING|MACHINE_MECHANICAL)
862 GAME( 19??, ec_labya,  ec_laby,  ecoinf3_pyramid, ecoinf3, ecoinf3_state, init_ecoinf3,      ROT0, "Electrocoin", "Labyrinth (v10) (Electrocoin)",          MACHINE_NO_SOUND|MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING|MACHINE_MECHANICAL)
863 GAME( 19??, ec_secrt,  0,        ecoinf3_pyramid, ecoinf3, ecoinf3_state, init_ecoinf3,      ROT0, "Electrocoin", "Secret Castle (v1) (Electrocoin)",       MACHINE_NO_SOUND|MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING|MACHINE_MECHANICAL)
864