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