1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3 /*
4 
5 program rom contains the following details
6 
7 COMPANY:FUN TECH CORPORATION
8 PRODUCT-NAME:SUPER TWO IN ONE
9 PROJECTOR:TIEN YUAN CHIEN,NOMA
10 HARDWARE-DESIGNER:EN YU CHENG
11 SOFTWARE-DESIGNER:RANG CHANG LI,CHIH HNI HUANG,WEN CHANG LIN
12 PROGRAM-VERSION:1.0
13 PROGRAM-DATE:09/23/1993
14 
15 8x8 tiles and 8x32 reels, likely going to be very similar to skylncr.cpp or goldstar.cpp (which are both very similar anyway)
16 palette addresses are the same as unkch in goldstar.cpp, but the io stuff is definitely different here
17 
18 board has an M5255 for sound
19 and an unpopulated position for a YM2413 or UM3567
20 
21 */
22 
23 #include "emu.h"
24 
25 #include "cpu/z80/z80.h"
26 #include "sound/ay8910.h"
27 #include "machine/nvram.h"
28 #include "machine/ticket.h"
29 #include "emupal.h"
30 #include "screen.h"
31 #include "speaker.h"
32 #include "tilemap.h"
33 
34 #include "fts2in1.lh"
35 
36 
37 
38 class fun_tech_corp_state : public driver_device
39 {
40 public:
fun_tech_corp_state(const machine_config & mconfig,device_type type,const char * tag)41 	fun_tech_corp_state(const machine_config &mconfig, device_type type, const char *tag) :
42 		driver_device(mconfig, type, tag),
43 		m_fgram(*this, "fgram"),
44 		m_reel_ram(*this, "reel_ram.%u", 0U),
45 		m_reel_scroll(*this, "reel_scroll.%u", 0U),
46 		m_reel1_alt_scroll(*this, "reel1_alt_scroll"),
47 		m_maincpu(*this, "maincpu"),
48 		m_hopper(*this, "hopper"),
49 		m_gfxdecode(*this, "gfxdecode"),
50 		m_lamps(*this, "lamp%u", 0U)
51 	{ }
52 
53 	void funtech(machine_config &config);
54 
55 protected:
56 	virtual void machine_start() override;
57 	virtual void video_start() override;
58 
59 private:
60 	required_shared_ptr<uint8_t> m_fgram;
61 	required_shared_ptr_array<uint8_t, 3> m_reel_ram;
62 	required_shared_ptr_array<uint8_t, 3> m_reel_scroll;
63 	required_shared_ptr<uint8_t> m_reel1_alt_scroll;
64 	required_device<cpu_device> m_maincpu;
65 	required_device<ticket_dispenser_device> m_hopper;
66 	required_device<gfxdecode_device> m_gfxdecode;
67 	output_finder<6> m_lamps;
68 
69 	uint8_t m_vreg;
70 
71 	tilemap_t *m_fg_tilemap;
72 
73 	INTERRUPT_GEN_MEMBER(vblank_interrupt);
74 
75 	void lamps_w(uint8_t data);
76 	void coins_w(uint8_t data);
77 	void vreg_w(uint8_t data);
78 
79 	void fgram_w(offs_t offset, uint8_t data);
80 
81 	TILE_GET_INFO_MEMBER(get_fg_tile_info);
82 
83 	tilemap_t *m_reel_tilemap[3];
84 
85 	template<uint8_t Reel> void reel_ram_w(offs_t offset, uint8_t data);
86 
87 	template<uint8_t Reel> TILE_GET_INFO_MEMBER(get_reel_tile_info);
88 
89 	uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
90 
91 	void funtech_io_map(address_map &map);
92 	void funtech_map(address_map &map);
93 };
94 
95 
TILE_GET_INFO_MEMBER(fun_tech_corp_state::get_fg_tile_info)96 TILE_GET_INFO_MEMBER(fun_tech_corp_state::get_fg_tile_info)
97 {
98 	int code = m_fgram[tile_index];
99 	int attr = m_fgram[tile_index+0x800];
100 
101 	code |= (attr & 0x0f) << 8;
102 
103 	if (m_vreg&1) code |= 0x1000;
104 
105 	tileinfo.set(0,
106 			code,
107 			attr>>4,
108 			0);
109 }
110 
111 template<uint8_t Reel>
TILE_GET_INFO_MEMBER(fun_tech_corp_state::get_reel_tile_info)112 TILE_GET_INFO_MEMBER(fun_tech_corp_state::get_reel_tile_info)
113 {
114 	int code = m_reel_ram[Reel][tile_index];
115 	if (m_vreg & 0x4) code |= 0x100;
116 	if (m_vreg & 0x8) code |= 0x200;
117 
118 	tileinfo.set(1,
119 			code,
120 			0,
121 			0);
122 }
123 
124 template<uint8_t Reel>
reel_ram_w(offs_t offset,uint8_t data)125 void fun_tech_corp_state::reel_ram_w(offs_t offset, uint8_t data)
126 {
127 	m_reel_ram[Reel][offset] = data;
128 	m_reel_tilemap[Reel]->mark_tile_dirty(offset);
129 }
130 
video_start()131 void fun_tech_corp_state::video_start()
132 {
133 	m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(fun_tech_corp_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
134 	m_fg_tilemap->set_transparent_pen(0);
135 
136 	m_reel_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(fun_tech_corp_state::get_reel_tile_info<0>)), TILEMAP_SCAN_ROWS, 8, 32, 64, 8);
137 	m_reel_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(fun_tech_corp_state::get_reel_tile_info<1>)), TILEMAP_SCAN_ROWS, 8, 32, 64, 8);
138 	m_reel_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(fun_tech_corp_state::get_reel_tile_info<2>)), TILEMAP_SCAN_ROWS, 8, 32, 64, 8);
139 
140 	m_reel_tilemap[0]->set_scroll_cols(64);
141 	m_reel_tilemap[1]->set_scroll_cols(64);
142 	m_reel_tilemap[2]->set_scroll_cols(64);
143 
144 }
145 
fgram_w(offs_t offset,uint8_t data)146 void fun_tech_corp_state::fgram_w(offs_t offset, uint8_t data)
147 {
148 	m_fgram[offset] = data;
149 	m_fg_tilemap->mark_tile_dirty(offset&0x7ff);
150 }
151 
152 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)153 uint32_t fun_tech_corp_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
154 {
155 	bitmap.fill(0, cliprect);
156 
157 	if (!(m_vreg & 0x40))
158 	{
159 		for (uint8_t reel = 0; reel < 3; reel++)
160 		{
161 			for (int i = 0; i < 64; i++)
162 			{
163 				m_reel_tilemap[reel]->set_scrolly(i, m_reel_scroll[reel][i]);
164 			}
165 		}
166 
167 		const rectangle visible1(0 * 8, (14 + 48) * 8 - 1, 4 * 8, (4 + 7) * 8 - 1);
168 		const rectangle visible2(0 * 8, (14 + 48) * 8 - 1, 12 * 8, (12 + 7) * 8 - 1);
169 		const rectangle visible3(0 * 8, (14 + 48) * 8 - 1, 18 * 8, (18 + 7) * 8 - 1);
170 
171 		m_reel_tilemap[0]->draw(screen, bitmap, visible1, 0, 0);
172 		m_reel_tilemap[1]->draw(screen, bitmap, visible2, 0, 0);
173 		m_reel_tilemap[2]->draw(screen, bitmap, visible3, 0, 0);
174 	}
175 	else
176 	{
177 		// this mode seems to draw reel1 as fullscreen using a different set of scroll regs
178 		for (int i = 0; i < 64; i++)
179 		{
180 			m_reel_tilemap[0]->set_scrolly(i, m_reel1_alt_scroll[i]);
181 		}
182 
183 		m_reel_tilemap[0]->draw(screen, bitmap, cliprect, 0, 0);
184 	}
185 
186 
187 	m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
188 	return 0;
189 }
190 
191 
192 
INTERRUPT_GEN_MEMBER(fun_tech_corp_state::vblank_interrupt)193 INTERRUPT_GEN_MEMBER(fun_tech_corp_state::vblank_interrupt)
194 {
195 //  if (m_nmi_enable)
196 		device.execute().pulse_input_line(INPUT_LINE_NMI, attotime::zero);
197 }
198 
199 
200 
funtech_map(address_map & map)201 void fun_tech_corp_state::funtech_map(address_map &map)
202 {
203 	map(0x0000, 0xbfff).rom();
204 
205 	map(0xc000, 0xc1ff).ram().w("palette", FUNC(palette_device::write8)).share("palette");
206 	map(0xc800, 0xc9ff).ram().w("palette", FUNC(palette_device::write8_ext)).share("palette_ext");
207 
208 	map(0xd000, 0xd7ff).rom(); // maybe
209 
210 	map(0xd800, 0xdfff).ram().share("nvram");
211 
212 	map(0xe000, 0xefff).ram().w(FUNC(fun_tech_corp_state::fgram_w)).share(m_fgram);
213 	map(0xf000, 0xf1ff).ram().w(FUNC(fun_tech_corp_state::reel_ram_w<0>)).share(m_reel_ram[0]);
214 	map(0xf200, 0xf3ff).ram().w(FUNC(fun_tech_corp_state::reel_ram_w<1>)).share(m_reel_ram[1]);
215 	map(0xf400, 0xf5ff).ram().w(FUNC(fun_tech_corp_state::reel_ram_w<2>)).share(m_reel_ram[2]);
216 	map(0xf600, 0xf7ff).ram();
217 
218 	map(0xf840, 0xf87f).ram().share(m_reel_scroll[0]);
219 	map(0xf880, 0xf8bf).ram().share(m_reel_scroll[1]);
220 	map(0xf900, 0xf93f).ram().share(m_reel_scroll[2]);
221 
222 	map(0xf9c0, 0xf9ff).ram().share(m_reel1_alt_scroll); // or a mirror, gets used in 'full screen' mode.
223 }
224 
225 
lamps_w(uint8_t data)226 void fun_tech_corp_state::lamps_w(uint8_t data)
227 {
228 	for (int i = 0; i < 6; i++)
229 		m_lamps[i] = BIT(data, i);
230 
231 	// bit 6 (0x40) is set when displaying a hand in poker, but there are only six lamp outputs
232 	// bit 7 (0x80) is always set
233 }
234 
coins_w(uint8_t data)235 void fun_tech_corp_state::coins_w(uint8_t data)
236 {
237 	if (data & 0x01) logerror("coins_w %02x\n", data);
238 
239 	machine().bookkeeping().coin_counter_w(4, BIT(data, 1)); // COUNTER HOPPER
240 	machine().bookkeeping().coin_counter_w(0, BIT(data, 2)); // COUNTER A (coin A)
241 	machine().bookkeeping().coin_counter_w(1, BIT(data, 3)); // COUNTER B (keyin B)
242 	machine().bookkeeping().coin_counter_w(2, BIT(data, 4)); // COUNTER C (coin C)
243 	machine().bookkeeping().coin_counter_w(3, BIT(data, 5)); // COUNTER D (coin D)
244 	machine().bookkeeping().coin_counter_w(5, BIT(data, 6)); // COUNTER CREDIT OUT
245 
246 	m_hopper->motor_w(BIT(data, 7));
247 }
248 
vreg_w(uint8_t data)249 void fun_tech_corp_state::vreg_w(uint8_t data)
250 {
251 	if (data & 0xb2) logerror("vreg_w %02x\n", data);
252 
253 	// -x-- rr-t
254 	// t = text tile bank
255 	// r = reel tile bank
256 	// x = show reel 1 full screen?
257 
258 	m_vreg = data;
259 	m_fg_tilemap->mark_all_dirty();
260 	m_reel_tilemap[0]->mark_all_dirty();
261 }
262 
263 
264 
funtech_io_map(address_map & map)265 void fun_tech_corp_state::funtech_io_map(address_map &map)
266 {
267 	map.global_mask(0xff);
268 	// lamps?
269 	map(0x00, 0x00).w(FUNC(fun_tech_corp_state::lamps_w));
270 	map(0x01, 0x01).w(FUNC(fun_tech_corp_state::coins_w));
271 
272 	map(0x03, 0x03).w(FUNC(fun_tech_corp_state::vreg_w));
273 
274 	map(0x04, 0x04).portr("IN0");
275 	map(0x05, 0x05).portr("IN1");
276 	map(0x06, 0x06).portr("DSW4");
277 	map(0x07, 0x07).portr("DSW3");
278 
279 	map(0x10, 0x10).r("aysnd", FUNC(ay8910_device::data_r));
280 	map(0x11, 0x11).w("aysnd", FUNC(ay8910_device::data_w));
281 	map(0x12, 0x12).w("aysnd", FUNC(ay8910_device::address_w));
282 }
283 
284 static INPUT_PORTS_START( funtech )
285 	PORT_START("IN0")
286 	// the buttons are all multi-purpose as it's a 2-in-1.
287 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD5 )   PORT_NAME("Hold 5, Bet")
288 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN1 )         PORT_NAME("Coin A")
289 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN3 )         PORT_NAME("Coin C")
290 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN4 )         PORT_NAME("Coin D")
291 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD1 )   PORT_NAME("Hold 1, Take Score, Odds, Left Stop") // shows odds in 8-liner game
292 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_POKER_HOLD4 )   PORT_NAME("Hold 4, Double-Up") // manual suggests this shows odds, but it doesn't
293 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_POKER_HOLD3 )   PORT_NAME("Hold 3, Small, Right Stop")
294 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_POKER_HOLD2 )   PORT_NAME("Hold 2, Big, Center Stop")
295 
296 	PORT_START("IN1")
297 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK )
298 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT )
299 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", ticket_dispenser_device, line_r)
300 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_NAME("Credit Out")
301 	PORT_DIPNAME( 0x10, 0x10, "IN1-10" ) // prevents start from working in the poker game at least
302 	PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
303 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
304 	PORT_SERVICE_NO_TOGGLE(   0x20, IP_ACTIVE_LOW )
305 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START1 )        PORT_NAME("Start, All Stop")
306 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN )  PORT_NAME("Keyin B")
307 
308 	// the board contains 4 banks of 8 dipswitches
309 	PORT_START("DSW1")
310 	PORT_DIPNAME( 0x03, 0x03, "Hopper Limit" )                PORT_DIPLOCATION("NO. 1:1,2")
311 	PORT_DIPSETTING(    0x00, "300" )
312 	PORT_DIPSETTING(    0x02, "500" )
313 	PORT_DIPSETTING(    0x01, "1000" )
314 	PORT_DIPSETTING(    0x03, "Unlimited" )
315 	PORT_DIPNAME( 0x1c, 0x1c, "Credit Limit" )                PORT_DIPLOCATION("NO. 1:3,4,5")
316 	PORT_DIPSETTING(    0x00, "5,000" )
317 	PORT_DIPSETTING(    0x10, "10,000" )
318 	PORT_DIPSETTING(    0x08, "20,000" )
319 	PORT_DIPSETTING(    0x18, "30,000" )
320 	PORT_DIPSETTING(    0x04, "40,000" )
321 	PORT_DIPSETTING(    0x14, "50,000" )
322 	PORT_DIPSETTING(    0x0c, "100,000" )
323 	PORT_DIPSETTING(    0x1c, "Unlimited" )
324 	PORT_DIPNAME( 0x20, 0x20, "Credit Limit Display" )        PORT_DIPLOCATION("NO. 1:6")
325 	PORT_DIPSETTING(    0x20, "Not Displayed" )
326 	PORT_DIPSETTING(    0x00, "Displayed" )
327 	PORT_DIPNAME( 0xc0, 0xc0, "Coin A Rate" )                 PORT_DIPLOCATION("NO. 1:7,8")
328 	PORT_DIPSETTING(    0xc0, DEF_STR( 1C_1C ) )
329 	PORT_DIPSETTING(    0x40, DEF_STR( 1C_2C ) )
330 	PORT_DIPSETTING(    0x80, DEF_STR( 1C_5C ) )
331 	PORT_DIPSETTING(    0x00, "1 Coin/10 Credits" )
332 
333 	PORT_START("DSW2")
334 	PORT_DIPNAME( 0x07, 0x07, "Keyin B Rate" )                PORT_DIPLOCATION("NO. 2:1,2,3")
335 	PORT_DIPSETTING(    0x00, DEF_STR( 1C_1C ) )
336 	PORT_DIPSETTING(    0x04, DEF_STR( 1C_2C ) )
337 	PORT_DIPSETTING(    0x02, DEF_STR( 1C_5C ) )
338 	PORT_DIPSETTING(    0x06, "1 Coin/10 Credits" )
339 	PORT_DIPSETTING(    0x01, "1 Coin/20 Credits" )
340 	PORT_DIPSETTING(    0x05, "1 Coin/25 Credits" )
341 	PORT_DIPSETTING(    0x03, "1 Coin/50 Credits" )
342 	PORT_DIPSETTING(    0x07, "1 Coin/100 Credits" )
343 	PORT_DIPNAME( 0x18, 0x18, "Coin C Rate" )                 PORT_DIPLOCATION("NO. 2:4,5")
344 	PORT_DIPSETTING(    0x00, DEF_STR( 1C_1C ) )
345 	PORT_DIPSETTING(    0x10, DEF_STR( 1C_2C ) )
346 	PORT_DIPSETTING(    0x08, DEF_STR( 1C_5C ) )
347 	PORT_DIPSETTING(    0x18, "1 Coin/10 Credits" )
348 	PORT_DIPNAME( 0xe0, 0xe0, "Coin D Rate" )                 PORT_DIPLOCATION("NO. 2:6,7,8")
349 	PORT_DIPSETTING(    0x00, DEF_STR( 5C_1C) )
350 	PORT_DIPSETTING(    0x80, DEF_STR( 2C_1C ) )
351 	PORT_DIPSETTING(    0x40, DEF_STR( 1C_1C ) )
352 	PORT_DIPSETTING(    0xc0, DEF_STR( 1C_2C ) )
353 	PORT_DIPSETTING(    0x20, DEF_STR( 1C_5C ) )
354 	PORT_DIPSETTING(    0xa0, "1 Coin/10 Credits" )
355 	PORT_DIPSETTING(    0x60, "1 Coin/25 Credits" )
356 	PORT_DIPSETTING(    0xe0, "1 Coin/50 Credits" )
357 
358 	PORT_START("DSW3")
359 	PORT_DIPNAME( 0x0f, 0x0f, "Main Game Pay Rate" )          PORT_DIPLOCATION("NO. 3:1,2,3,4")
360 	PORT_DIPSETTING(    0x00, "50%" )
361 	PORT_DIPSETTING(    0x08, "53%" )
362 	PORT_DIPSETTING(    0x04, "56%" )
363 	PORT_DIPSETTING(    0x0c, "59%" )
364 	PORT_DIPSETTING(    0x02, "62%" )
365 	PORT_DIPSETTING(    0x0a, "65%" )
366 	PORT_DIPSETTING(    0x06, "68%" )
367 	PORT_DIPSETTING(    0x0e, "71%" )
368 	PORT_DIPSETTING(    0x01, "74%" )
369 	PORT_DIPSETTING(    0x09, "77%" )
370 	PORT_DIPSETTING(    0x05, "80%" )
371 	PORT_DIPSETTING(    0x0d, "83%" )
372 	PORT_DIPSETTING(    0x03, "86%" )
373 	PORT_DIPSETTING(    0x0b, "89%" )
374 	PORT_DIPSETTING(    0x07, "92%" )
375 	PORT_DIPSETTING(    0x0f, "95%" )
376 	PORT_DIPNAME( 0x10, 0x10, "Double Up Game" )              PORT_DIPLOCATION("NO. 3:5")
377 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
378 	PORT_DIPSETTING(    0x10, DEF_STR( On ) )
379 	PORT_DIPNAME( 0x20, 0x20, "Double Up Pay Rate" )          PORT_DIPLOCATION("NO. 3:6")
380 	PORT_DIPSETTING(    0x00, "80%" )
381 	PORT_DIPSETTING(    0x20, "90%" )
382 	PORT_DIPNAME( 0x40, 0x40, "Double Up 7 Player Value" )    PORT_DIPLOCATION("NO. 3:7")
383 	PORT_DIPSETTING(    0x40, "Loss" )
384 	PORT_DIPSETTING(    0x00, "Draw" )
385 	PORT_DIPNAME( 0x80, 0x80, "Double Up Girl Display" )      PORT_DIPLOCATION("NO. 3:8") // if set to No girl remains clothed when winning
386 	PORT_DIPSETTING(    0x00, DEF_STR( No ) )
387 	PORT_DIPSETTING(    0x80, DEF_STR( Yes ) )
388 
389 	PORT_START("DSW4")
390 	PORT_DIPNAME( 0x01, 0x01, "Reel Speed" )                  PORT_DIPLOCATION("NO. 4:1")
391 	PORT_DIPSETTING(    0x01, "Low" )
392 	PORT_DIPSETTING(    0x00, "High" )
393 	PORT_DIPNAME( 0x06, 0x06, "Max Bet" )                     PORT_DIPLOCATION("NO. 4:2,3")
394 	PORT_DIPSETTING(    0x00, "8" )
395 	PORT_DIPSETTING(    0x04, "16" )
396 	PORT_DIPSETTING(    0x02, "32" )
397 	PORT_DIPSETTING(    0x06, "64" )
398 	PORT_DIPNAME( 0x08, 0x08, "Min Bet for Any Bonus" )       PORT_DIPLOCATION("NO. 4:4")
399 	PORT_DIPSETTING(    0x00, "8" )
400 	PORT_DIPSETTING(    0x08, "16" )
401 	PORT_DIPNAME( 0x30, 0x30, "Bonus Games Entry Condition" ) PORT_DIPLOCATION("NO. 4:5,6")
402 	PORT_DIPSETTING(    0x00, "1-3-1-5-1" )
403 	PORT_DIPSETTING(    0x20, "1-4-1-6-1" )
404 	PORT_DIPSETTING(    0x10, "1-5-1-7-1" )
405 	PORT_DIPSETTING(    0x30, "1-6-1-8-1" )
406 	PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unused ) )             PORT_DIPLOCATION("NO. 4:7") // unused according to manual
407 	PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
408 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
409 	PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unused ) )             PORT_DIPLOCATION("NO. 4:8") // unused according to manual
410 	PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
411 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
412 INPUT_PORTS_END
413 
414 
415 static const gfx_layout tiles8x32_layout =
416 {
417 	8,32,
418 	RGN_FRAC(1,1),
419 	8,
420 	{ 0, 1, 2, 3, 4 ,5, 6, 7 },
421 	{ 0, 8, 16, 24, 32, 40, 48, 56 },
422 	{ 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64, 8*64, 9*64, 10*64, 11*64, 12*64, 13*64, 14*64, 15*64, 16*64, 17*64, 18*64, 19*64, 20*64, 21*64, 22*64, 23*64, 24*64, 25*64, 26*64, 27*64, 28*64, 29*64, 30*64, 31*64 },
423 	32*64
424 };
425 
426 
427 static const gfx_layout tiles8x8_layout =
428 {
429 	8,8,
430 	RGN_FRAC(1,1),
431 	4,
432 	{ 0, 1, 2, 3 },
433 	{ 4, 0, 12, 8, 20, 16, 28, 24 },
434 	{ 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 },
435 	32*8
436 };
437 
438 
439 static GFXDECODE_START( gfx_funtech )
440 	GFXDECODE_ENTRY( "gfx1", 0, tiles8x8_layout, 0, 16 )
441 	GFXDECODE_ENTRY( "gfx2", 0, tiles8x32_layout, 0x100, 1 )
442 GFXDECODE_END
443 
444 
445 
446 
machine_start()447 void fun_tech_corp_state::machine_start()
448 {
449 	m_lamps.resolve();
450 
451 	save_item(NAME(m_vreg));
452 }
453 
454 
funtech(machine_config & config)455 void fun_tech_corp_state::funtech(machine_config &config)
456 {
457 	/* basic machine hardware */
458 	Z80(config, m_maincpu, 4000000);         /* ? MHz */
459 	m_maincpu->set_addrmap(AS_PROGRAM, &fun_tech_corp_state::funtech_map);
460 	m_maincpu->set_addrmap(AS_IO, &fun_tech_corp_state::funtech_io_map);
461 	m_maincpu->set_vblank_int("screen", FUNC(fun_tech_corp_state::vblank_interrupt));
462 
463 	/* video hardware */
464 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
465 	screen.set_refresh_hz(60);
466 	screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
467 	screen.set_size(512, 256);
468 	screen.set_visarea(0, 512-1, 8, 256-8-1);
469 	screen.set_screen_update(FUNC(fun_tech_corp_state::screen_update));
470 	screen.set_palette("palette");
471 
472 	GFXDECODE(config, m_gfxdecode, "palette", gfx_funtech);
473 	PALETTE(config, "palette").set_format(palette_device::xBGR_555, 0x200);
474 
475 	NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_1);
476 
477 	TICKET_DISPENSER(config, m_hopper, attotime::from_msec(50), TICKET_MOTOR_ACTIVE_HIGH, TICKET_STATUS_ACTIVE_HIGH);
478 
479 	/* sound hardware */
480 	SPEAKER(config, "mono").front_center();
481 
482 	ay8910_device &aysnd(AY8910(config, "aysnd", 1500000)); /* M5255, ? MHz */
483 	aysnd.port_a_read_callback().set_ioport("DSW1");
484 	aysnd.port_b_read_callback().set_ioport("DSW2");
485 	aysnd.add_route(ALL_OUTPUTS, "mono", 1.00);
486 }
487 
488 
489 
490 ROM_START( fts2in1 )
491 	ROM_REGION( 0x10000, "maincpu", 0 )
492 	ROM_LOAD( "u5.bin", 0x00000, 0x10000, CRC(ab19fd28) SHA1(a65ff732e0aaaec256cc63beff5f24419e691645) )
493 
494 	ROM_REGION( 0x80000, "gfx1", 0 ) // crc printed on label matches half the data, even if chip was double size. Seen on a second PCB with correct sized ROM.
495 	ROM_LOAD( "u18.bin", 0x00000, 0x80000, CRC(d1154aac) SHA1(dc03c4b7a4dfda2a30bfabaeb0ce053660961663) ) // 1ST AND 2ND HALF IDENTICAL
496 
497 	ROM_REGION( 0x40000, "gfx2", 0 )
498 	ROM_LOAD16_BYTE( "u29.bin", 0x00000, 0x20000, CRC(ed6a1e2f) SHA1(2c72e764c7c8091a8fa1dfc257a84d61e2da0e4b) )
499 	ROM_LOAD16_BYTE( "u30.bin", 0x00001, 0x20000, CRC(d572bddc) SHA1(06499aeb47085a02af9eb4987ed987f9a3a397f7) )
500 ROM_END
501 
502 GAMEL( 1993, fts2in1, 0, funtech, funtech, fun_tech_corp_state, empty_init, ROT0, "Fun Tech Corporation", "Super Two In One", MACHINE_SUPPORTS_SAVE, layout_fts2in1 )
503