1 // license:BSD-3-Clause
2 // copyright-holders:R. Belmont, Ryan Holtz, Andreas Naive
3 /**************************************************************************
4  *
5  * 39in1.cpp - bootleg MAME-based "39-in-1" arcade PCB
6  * Skeleton by R. Belmont, thanks to the Guru
7  * PXA255 Peripheral hookup by Ryan Holtz
8  * Decrypt by Andreas Naive
9  *
10  * CPU: Intel Xscale PXA255 series @ 200 MHz, configured little-endian
11  * Xscale PXA consists of:
12  *    ARMv5TE instruction set without the FPU
13  *    ARM standard MMU
14  *    ARM DSP extensions
15  *    VGA-ish frame buffer with some 2D acceleration features
16  *    AC97 stereo audio CODEC
17  *
18  * PCB also contains a custom ASIC, probably used for the decryption
19  *
20  * TODO:
21  *   - PXA255 peripherals
22  *   - 4in1a and 4in1b are very similar to 39in1, currently boot but stuck at
23  *     'Hardware Check' with an error
24  *   - rodent should be correctly decrypted but expects something different
25        from the CPLD (probably)
26  *   - 19in1, 48in1, 48in1a, 48in1b, 60in1 have more conditional XORs,
27  *     encryption isn't completely beaten yet
28  *
29  * 39in1 notes:
30  * The actual PCB just normally boots up to the game, whereas in MAME it
31  * defaults to test mode and checks the rom, then jumps out to the game
32  * after loading all 39 games. It is almost like it is defaulting to test
33  * mode on at bootup. On the real PCB, it just loads the 39 games then
34  * shows the game selection menu. Going into the test mode does the same
35  * code check but then shows  a test screen with color bars. Pressing
36  * next shows a high score clear screen (if the HS dip is on). Pressing
37  * next shows the game dips screens and allows you to set up soft dip
38  * switches for each of the 39 games.
39  **************************************************************************/
40 
41 #include "emu.h"
42 #include "cpu/arm7/arm7.h"
43 #include "cpu/arm7/arm7core.h"
44 #include "machine/eepromser.h"
45 #include "machine/pxa255.h"
46 
47 class _39in1_state : public driver_device
48 {
49 public:
_39in1_state(const machine_config & mconfig,device_type type,const char * tag)50 	_39in1_state(const machine_config &mconfig, device_type type, const char *tag)
51 		: driver_device(mconfig, type, tag)
52 		, m_pxa_periphs(*this, "pxa_periphs")
53 		, m_ram(*this, "ram")
54 		, m_eeprom(*this, "eeprom")
55 		, m_maincpu(*this, "maincpu")
56 	{ }
57 
58 	void _39in1(machine_config &config);
59 
60 	void init_4in1a();
61 	void init_4in1b();
62 	void init_19in1();
63 	void init_39in1();
64 	void init_48in1();
65 	void init_48in1a();
66 	void init_60in1();
67 	void init_rodent();
68 
69 private:
70 	uint32_t m_seed;
71 	uint32_t m_magic;
72 	uint32_t m_state;
73 	uint32_t m_mcu_ipt_pc;
74 
75 	void driver_init() override;
76 
77 	required_device<pxa255_periphs_device> m_pxa_periphs;
78 	required_shared_ptr<uint32_t> m_ram;
79 	required_device<eeprom_serial_93cxx_device> m_eeprom;
80 
81 	uint32_t eeprom_r();
82 	void eeprom_w(uint32_t data, uint32_t mem_mask = ~0);
83 
84 	uint32_t cpld_r(offs_t offset);
85 	void cpld_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
86 	uint32_t prot_cheater_r();
87 	required_device<cpu_device> m_maincpu;
88 	void _39in1_map(address_map &map);
89 
90 	inline void ATTR_PRINTF(3,4) verboselog(int n_level, const char *s_fmt, ... );
91 
92 	void decrypt(uint8_t xor00, uint8_t xor08, uint8_t xor10, uint8_t xor20, uint8_t xor40, uint8_t bit7, uint8_t bit6, uint8_t bit5, uint8_t bit4, uint8_t bit3, uint8_t bit2, uint8_t bit1, uint8_t bit0);
93 	void further_decrypt(uint8_t xor400, uint8_t xor800, uint8_t xor1000, uint8_t xor2000, uint8_t xor4000, uint8_t xor8000);
94 };
95 
96 
97 #define VERBOSE_LEVEL (0)
98 
verboselog(int n_level,const char * s_fmt,...)99 inline void ATTR_PRINTF(3,4) _39in1_state::verboselog(int n_level, const char *s_fmt, ... )
100 {
101 	if (VERBOSE_LEVEL >= n_level)
102 	{
103 		va_list v;
104 		char buf[32768];
105 		va_start( v, s_fmt );
106 		vsprintf( buf, s_fmt, v );
107 		va_end( v );
108 		logerror("%s: %s", machine().describe_context(), buf);
109 	}
110 }
111 
eeprom_r()112 uint32_t _39in1_state::eeprom_r()
113 {
114 	return (m_eeprom->do_read() << 5) | (1 << 1); // Must be on.  Probably a DIP switch.
115 }
116 
eeprom_w(uint32_t data,uint32_t mem_mask)117 void _39in1_state::eeprom_w(uint32_t data, uint32_t mem_mask)
118 {
119 	if (BIT(mem_mask, 2))
120 		m_eeprom->cs_write(ASSERT_LINE);
121 	if (BIT(mem_mask, 3))
122 		m_eeprom->clk_write(BIT(data, 3) ? ASSERT_LINE : CLEAR_LINE);
123 	if (BIT(mem_mask, 4))
124 		m_eeprom->di_write(BIT(data, 4));
125 }
126 
cpld_r(offs_t offset)127 uint32_t _39in1_state::cpld_r(offs_t offset)
128 {
129 	// if (m_maincpu->pc() != m_mcu_ipt_pc) printf("CPLD read @ %x (PC %x state %d)\n", offset, m_maincpu->pc(), m_state);
130 
131 	if (m_maincpu->pc() == 0x3f04)
132 	{
133 		return 0xf0;      // any non-zero value works here
134 	}
135 	else if (m_maincpu->pc() == m_mcu_ipt_pc)
136 	{
137 		return ioport("MCUIPT")->read();
138 	}
139 	else
140 	{
141 		if (m_state == 0)
142 		{
143 			return 0;
144 		}
145 		else if (m_state == 1)
146 		{
147 			switch (offset & ~1)
148 			{
149 				case 0x40010: return 0x55;
150 				case 0x40012: return 0x93;
151 				case 0x40014: return 0x89;
152 				case 0x40016: return 0xa2;
153 				case 0x40018: return 0x31;
154 				case 0x4001a: return 0x75;
155 				case 0x4001c: return 0x97;
156 				case 0x4001e: return 0xb1;
157 				default: printf("State 1 unknown offset %x\n", offset); break;
158 			}
159 		}
160 		else if (m_state == 2)                      // 29c0: 53 ac 0c 2b a2 07 e6 be 31
161 		{
162 			uint32_t seed = m_seed;
163 			uint32_t magic = m_magic;
164 
165 			magic = ( (((~(seed >> 16))       ^ (magic >> 1))        & 0x01) |
166 				(((~((seed >> 19) << 1))        ^ ((magic >> 5) << 1)) & 0x02) |
167 				(((~((seed >> 20) << 2))        ^ ((magic >> 3) << 2)) & 0x04) |
168 				(((~((seed >> 22) << 3))        ^ ((magic >> 6) << 3)) & 0x08) |
169 				(((~((seed >> 23) << 4))        ^   magic)             & 0x10) |
170 				(((~(((seed >> 16) >> 2) << 5)) ^ ((magic >> 2) << 5)) & 0x20) |
171 				(((~(((seed >> 16) >> 1) << 6)) ^ ((magic >> 7) << 6)) & 0x40) |
172 				(((~(((seed >> 16) >> 5) << 7)) ^  (magic << 7))       & 0x80));
173 
174 			m_magic = magic;
175 			return magic;
176 		}
177 	}
178 
179 	return 0;
180 }
181 
cpld_w(offs_t offset,uint32_t data,uint32_t mem_mask)182 void _39in1_state::cpld_w(offs_t offset, uint32_t data, uint32_t mem_mask)
183 {
184 	if (mem_mask == 0xffff)
185 	{
186 		m_seed = data<<16;
187 	}
188 
189 	if (m_maincpu->pc() == 0x280c)
190 	{
191 		m_state = 1;
192 	}
193 	if (m_maincpu->pc() == 0x2874)
194 	{
195 		m_state = 2;
196 		m_magic = m_maincpu->space(AS_PROGRAM).read_byte(0xa02d4ff0);
197 	}
198 	else if (offset == 0xa)
199 	{
200 	}
201 #if 0
202 	else
203 	{
204 		printf("%08x: CPLD_W: %08x = %08x & %08x\n", m_maincpu->pc(), offset, data, mem_mask);
205 	}
206 #endif
207 }
208 
prot_cheater_r()209 uint32_t _39in1_state::prot_cheater_r()
210 {
211 	return 0x37;
212 }
213 
driver_init()214 void _39in1_state::driver_init()
215 {
216 	address_space &space = m_maincpu->space(AS_PROGRAM);
217 	space.install_read_handler (0xa0151648, 0xa015164b, read32smo_delegate(*this, FUNC(_39in1_state::prot_cheater_r)));
218 }
219 
_39in1_map(address_map & map)220 void _39in1_state::_39in1_map(address_map &map)
221 {
222 	map(0x00000000, 0x0007ffff).rom();
223 	map(0x00400000, 0x005fffff).rom().region("data", 0);
224 	map(0x04000000, 0x047fffff).rw(FUNC(_39in1_state::cpld_r), FUNC(_39in1_state::cpld_w));
225 	map(0x40000000, 0x400002ff).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::dma_r), FUNC(pxa255_periphs_device::dma_w));
226 	map(0x40400000, 0x40400083).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::i2s_r), FUNC(pxa255_periphs_device::i2s_w));
227 	map(0x40a00000, 0x40a0001f).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::ostimer_r), FUNC(pxa255_periphs_device::ostimer_w));
228 	map(0x40d00000, 0x40d00017).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::intc_r), FUNC(pxa255_periphs_device::intc_w));
229 	map(0x40e00000, 0x40e0006b).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::gpio_r), FUNC(pxa255_periphs_device::gpio_w));
230 	map(0x44000000, 0x4400021f).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::lcd_r), FUNC(pxa255_periphs_device::lcd_w));
231 	map(0xa0000000, 0xa07fffff).ram().share("ram");
232 }
233 
234 static INPUT_PORTS_START( 39in1 )
235 	PORT_START("MCUIPT")
236 	PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_START1 )
237 	PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1)
238 	PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1)
239 	PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1)
240 	PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1)
241 	PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
242 	PORT_BIT( 0x00000040, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
243 	PORT_BIT( 0x00000080, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1)
244 	PORT_BIT( 0x00000100, IP_ACTIVE_LOW, IPT_UNKNOWN )
245 	PORT_BIT( 0x00000200, IP_ACTIVE_LOW, IPT_UNKNOWN )
246 	PORT_BIT( 0x00000400, IP_ACTIVE_LOW, IPT_UNKNOWN )
247 	PORT_BIT( 0x00000800, IP_ACTIVE_LOW, IPT_COIN1 )
248 	PORT_BIT( 0x00001000, IP_ACTIVE_LOW, IPT_COIN2 )
249 	PORT_BIT( 0x00002000, IP_ACTIVE_LOW, IPT_COIN3 )
250 	PORT_BIT( 0x00004000, IP_ACTIVE_LOW, IPT_UNKNOWN )
251 	PORT_BIT( 0x00008000, IP_ACTIVE_LOW, IPT_SERVICE1 )
252 	PORT_BIT( 0x00010000, IP_ACTIVE_LOW, IPT_START2 )
253 	PORT_BIT( 0x00020000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
254 	PORT_BIT( 0x00040000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
255 	PORT_BIT( 0x00080000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
256 	PORT_BIT( 0x00100000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
257 	PORT_BIT( 0x00200000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
258 	PORT_BIT( 0x00400000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
259 	PORT_BIT( 0x00800000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
260 	PORT_BIT( 0x01000000, IP_ACTIVE_LOW, IPT_UNKNOWN )
261 	PORT_BIT( 0x02000000, IP_ACTIVE_LOW, IPT_UNKNOWN )
262 	PORT_BIT( 0x04000000, IP_ACTIVE_LOW, IPT_UNKNOWN )
263 	PORT_BIT( 0x08000000, IP_ACTIVE_LOW, IPT_UNKNOWN )
264 	PORT_BIT( 0x10000000, IP_ACTIVE_LOW, IPT_UNKNOWN )
265 	PORT_BIT( 0x20000000, IP_ACTIVE_LOW, IPT_UNKNOWN )
266 	PORT_BIT( 0x40000000, IP_ACTIVE_LOW, IPT_UNKNOWN )
267 	PORT_SERVICE_NO_TOGGLE( 0x80000000, IP_ACTIVE_LOW )
268 
269 //  The following dips apply to 39in1 and 48in1. 60in1 is the same but the last unused dipsw#4 is test mode off/on.
270 
271 	PORT_START("DSW")      // 1x 4-position DIP switch labelled SW3
DEF_STR(Flip_Screen)272 	PORT_DIPNAME( 0x01, 0x01, DEF_STR( Flip_Screen ) )    PORT_DIPLOCATION("SW3:1")
273 	PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
274 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
275 	PORT_DIPNAME( 0x02, 0x00, "Display Mode" )            PORT_DIPLOCATION("SW3:2")
276 	PORT_DIPSETTING(    0x02, "VGA 31.5kHz" )
277 	PORT_DIPSETTING(    0x00, "CGA 15.75kHz" )
278 	PORT_DIPNAME( 0x04, 0x04, "High Score Saver" )        PORT_DIPLOCATION("SW3:3")
279 	PORT_DIPSETTING(    0x04, "Disabled" )
280 	PORT_DIPSETTING(    0x00, "Enabled" )
281 	PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unused ) )         PORT_DIPLOCATION("SW3:4")
282 	PORT_DIPSETTING(    0x08, DEF_STR( Off ) )
283 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
284 INPUT_PORTS_END
285 
286 void _39in1_state::decrypt(uint8_t xor00, uint8_t xor08, uint8_t xor10, uint8_t xor20, uint8_t xor40, uint8_t bit7, uint8_t bit6, uint8_t bit5, uint8_t bit4, uint8_t bit3, uint8_t bit2, uint8_t bit1, uint8_t bit0)
287 {
288 	uint8_t *rom = memregion("maincpu")->base();
289 
290 	for (int i = 0; i < 0x80000; i += 2)
291 	{
292 		if (i & 0x08)
293 			rom[i] ^= xor08;
294 		if (i & 0x10)
295 			rom[i] ^= xor10;
296 		if (i & 0x20)
297 			rom[i] ^= xor20;
298 		if (i & 0x40)
299 			rom[i] ^= xor40;
300 
301 		rom[i] = bitswap<8>(rom[i] ^ xor00, bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0);
302 	}
303 }
304 
further_decrypt(uint8_t xor400,uint8_t xor800,uint8_t xor1000,uint8_t xor2000,uint8_t xor4000,uint8_t xor8000)305 void _39in1_state::further_decrypt(uint8_t xor400, uint8_t xor800, uint8_t xor1000, uint8_t xor2000, uint8_t xor4000, uint8_t xor8000) // later versions have more conditional XORs
306 {
307 	uint8_t *rom = memregion("maincpu")->base();
308 
309 	for (int i = 0; i < 0x80000; i += 2)
310 	{
311 		if (i & 0x400)
312 			rom[i] ^= xor400; // always 0x00 in the available dumps
313 		if (i & 0x800)
314 			rom[i] ^= xor800;
315 		if (i & 0x1000)
316 			rom[i] ^= xor1000;
317 		if (i & 0x2000)
318 			rom[i] ^= xor2000;
319 		if (i & 0x4000)
320 			rom[i] ^= xor4000; // TODO: currently unverified if the games actually use this
321 		if (i & 0x8000)
322 			rom[i] ^= xor8000; // TODO: currently unverified if the games actually use this
323 		// TODO: 0x10000, 0x20000, 0x40000?
324 	}
325 
326 	/*{
327 	    char filename[256];
328 	    sprintf(filename,"p_decrypted_%s", machine().system().name);
329 	    FILE *fp = fopen(filename, "w+b");
330 	    if (fp)
331 	    {
332 	    fwrite(rom, 0x80000, 1, fp);
333 	    fclose(fp);
334 	    }
335 	}*/
336 }
337 
init_39in1()338 void _39in1_state::init_39in1()  { driver_init(); decrypt(0xc0, 0x02, 0x40, 0x04, 0x80, 7, 2, 5, 6, 0, 3, 1, 4); m_mcu_ipt_pc = 0xe3af4; } // good
init_4in1a()339 void _39in1_state::init_4in1a()  { driver_init(); decrypt(0x25, 0x01, 0x80, 0x04, 0x40, 6, 0, 2, 1, 7, 5, 4, 3); m_mcu_ipt_pc = 0x45814; } // good
init_4in1b()340 void _39in1_state::init_4in1b()  { driver_init(); decrypt(0x43, 0x80, 0x04, 0x40, 0x08, 2, 4, 0, 6, 7, 3, 1, 5); m_mcu_ipt_pc = 0x57628; } // good
init_19in1()341 void _39in1_state::init_19in1()  { driver_init(); decrypt(0x00, 0x04, 0x01, 0x80, 0x40, 2, 1, 7, 4, 5, 0, 6, 3); further_decrypt(0x00, 0x01, 0x00, 0x10, 0x00, 0x00); m_mcu_ipt_pc = 0x00000; } // TODO: 0x4000, 0x8000, 0x10000, 0x20000, 0x40000 conditional XORs?
init_48in1()342 void _39in1_state::init_48in1()  { driver_init(); decrypt(0x00, 0x01, 0x40, 0x00, 0x20, 5, 3, 2, 1, 4, 6, 0, 7); further_decrypt(0x00, 0x01, 0x20, 0x10, 0x00, 0x00); m_mcu_ipt_pc = 0x00000; } // applies to both 48in1 and 48in1b, same main CPU ROM. TODO: see above
init_48in1a()343 void _39in1_state::init_48in1a() { init_48in1(); m_mcu_ipt_pc = 0x00000; } // same encryption as 48in1
init_rodent()344 void _39in1_state::init_rodent() { init_4in1b(); /*m_mcu_ipt_pc = 0x?????;*/ } // same encryption as 4in1b, thus good, but doesn't boot because of different CPLD calls
init_60in1()345 void _39in1_state::init_60in1()  { driver_init(); decrypt(0x00, 0x40, 0x10, 0x80, 0x20, 5, 1, 4, 2, 0, 7, 6, 3); further_decrypt(0x00, 0x01, 0x00, 0x10, 0x00, 0x00); m_mcu_ipt_pc = 0x00000; } // TODO: see 19in1
346 
_39in1(machine_config & config)347 void _39in1_state::_39in1(machine_config &config)
348 {
349 	PXA255(config, m_maincpu, 200000000);
350 	m_maincpu->set_addrmap(AS_PROGRAM, &_39in1_state::_39in1_map);
351 
352 	EEPROM_93C66_16BIT(config, "eeprom");
353 
354 	PXA255_PERIPHERALS(config, m_pxa_periphs, 200000000, m_maincpu);
355 	m_pxa_periphs->gpio0_write().set(FUNC(_39in1_state::eeprom_w));
356 	m_pxa_periphs->gpio0_read().set(FUNC(_39in1_state::eeprom_r));
357 	m_pxa_periphs->gpio1_read().set_ioport("DSW").lshift(21);
358 }
359 
360 ROM_START( 39in1 )
361 	// main program, encrypted
362 	ROM_REGION( 0x80000, "maincpu", 0 )
363 	ROM_LOAD( "27c4096_plz-v001_ver.300.bin", 0x000000, 0x080000, CRC(9149dbc4) SHA1(40efe1f654f11474f75ae7fee1613f435dbede38) )
364 
365 	// data ROM - contains a filesystem with ROMs, fonts, graphics, etc. in an unknown compressed format
366 	ROM_REGION32_LE( 0x200000, "data", 0 )
367 	ROM_LOAD( "16mflash.bin", 0x000000, 0x200000, CRC(a089f0f8) SHA1(e975eadd9176a8b9e416229589dfe3158cba22cb) )
368 
369 	// EEPROM - contains security data
370 	ROM_REGION16_BE( 0x200, "eeprom", 0 )
371 	ROM_LOAD16_WORD_SWAP( "93c66_eeprom.bin", 0x000, 0x200, CRC(a423a969) SHA1(4c68654c81e70367209b9f6c712564aae89a3122) )
372 ROM_END
373 
374 ROM_START( 48in1 )
375 	// main program, encrypted
376 	ROM_REGION( 0x80000, "maincpu", 0 )
377 	ROM_LOAD( "hph_ver309",   0x000000, 0x080000, CRC(27023186) SHA1(a2b3770c4b03d6026c6a0ff2e62ab17c3b359b12) )
378 
379 	// data ROM - contains a filesystem with ROMs, fonts, graphics, etc. in an unknown compressed format
380 	ROM_REGION32_LE( 0x200000, "data", 0 )
381 	ROM_LOAD( "16mflash.bin", 0x000000, 0x200000, CRC(a089f0f8) SHA1(e975eadd9176a8b9e416229589dfe3158cba22cb) )
382 
383 	// EEPROM - contains security data
384 	ROM_REGION16_BE( 0x200, "eeprom", 0 )
385 	ROM_LOAD16_WORD_SWAP( "48in1_93c66_eeprom.bin", 0x000, 0x200, NO_DUMP )
386 ROM_END
387 
388 
389 ROM_START( 48in1b )
390 	// main program, encrypted
391 	ROM_REGION( 0x80000, "maincpu", 0 )
392 	ROM_LOAD( "hph_ver309",   0x000000, 0x080000, CRC(27023186) SHA1(a2b3770c4b03d6026c6a0ff2e62ab17c3b359b12) )
393 
394 	// data ROM - contains a filesystem with ROMs, fonts, graphics, etc. in an unknown compressed format
395 	ROM_REGION32_LE( 0x400000, "data", 0 )
396 	ROM_LOAD( "48_flash.u19", 0x000000, 0x400000, CRC(a975db44) SHA1(5be6520b2ba7728e9e2de3c62ae7c3b88b25172a) )
397 
398 	// EEPROM - contains security data
399 	ROM_REGION16_BE( 0x200, "eeprom", 0 )
400 	ROM_LOAD16_WORD_SWAP( "48_93c66.u32", 0x000, 0x200, CRC(cec06912) SHA1(2bc2e45602c5b1e8a3e031dd384e9f16be4e2ddb) )
401 ROM_END
402 
403 
404 ROM_START( 48in1a )
405 	// main program, encrypted
406 	ROM_REGION( 0x80000, "maincpu", 0 )
407 	ROM_LOAD( "ver302.u2",    0x000000, 0x080000, CRC(5ea25870) SHA1(66edc59a3d355bc3462e98d2062ada721c371af6) )
408 
409 	// data ROM - contains a filesystem with ROMs, fonts, graphics, etc. in an unknown compressed format
410 	ROM_REGION32_LE( 0x200000, "data", 0 )
411 	ROM_LOAD( "16mflash.bin", 0x000000, 0x200000, CRC(a089f0f8) SHA1(e975eadd9176a8b9e416229589dfe3158cba22cb) )
412 
413 	// EEPROM - contains security data
414 	ROM_REGION16_BE( 0x200, "eeprom", 0 )
415 	ROM_LOAD16_WORD_SWAP( "48in1_93c66_eeprom.bin", 0x000, 0x200, NO_DUMP )
416 ROM_END
417 
418 
419 ROM_START( 60in1 )
420 	// main program, encrypted
421 	ROM_REGION( 0x80000, "maincpu", 0 )
422 	ROM_LOAD( "hph_ver300.u8",   0x000000, 0x080000, CRC(6fba84c4) SHA1(28881e51227e94a80c8449d9c00a1a675f008d64) )
423 
424 	// data ROM - contains a filesystem with ROMs, fonts, graphics, etc. in an unknown compressed format
425 	ROM_REGION32_LE( 0x400000, "data", 0 )
426 	ROM_LOAD( "flash.u19", 0x000000, 0x400000, CRC(0cfed2a0) SHA1(9aac23f5267af56255e6f8aefade9f00bc106325) )
427 
428 	// EEPROM - contains security data
429 	ROM_REGION16_BE( 0x200, "eeprom", 0 )
430 	ROM_LOAD16_WORD_SWAP( "60in1_eeprom.u32", 0x000, 0x200, CRC(54af5973) SHA1(30aca7790458f4be906f7fa7c74206e16d9fc36f) )
431 ROM_END
432 
433 ROM_START( 4in1a )
434 	// main program, encrypted
435 	ROM_REGION( 0x80000, "maincpu", 0 )
436 	ROM_LOAD( "plz-v014_ver300.bin", 0x000000, 0x080000, CRC(775f101d) SHA1(8a299a67b487518ba2e2cb5334347b93f8640190) )
437 
438 	// data ROM - contains a filesystem with ROMs, fonts, graphics, etc. in an unknown compressed format
439 	ROM_REGION32_LE( 0x200000, "data", 0 )
440 	ROM_LOAD( "16mflash.bin", 0x000000, 0x200000, CRC(a089f0f8) SHA1(e975eadd9176a8b9e416229589dfe3158cba22cb) ) // confirmed same flash rom as 39 in 1
441 
442 	// EEPROM - contains security data
443 	ROM_REGION16_BE( 0x200, "eeprom", 0 )
444 	ROM_LOAD16_WORD_SWAP( "4in1_eeprom.bin", 0x000, 0x200, CRC(df1724f7) SHA1(07814aee3622f4bb8bada938f2a93fae791d6e31) )
445 ROM_END
446 
447 ROM_START( 4in1b )
448 	// main program, encrypted
449 	ROM_REGION( 0x80000, "maincpu", 0 )
450 	ROM_LOAD( "pzv001-4.bin", 0x000000, 0x080000, CRC(7679a95f) SHA1(56c20fa7d086560b76477b42208cb43d42adba41) )
451 
452 	// data ROM - contains a filesystem with ROMs, fonts, graphics, etc. in an unknown compressed format
453 	ROM_REGION32_LE( 0x200000, "data", 0 )
454 	ROM_LOAD( "16mflash.bin", 0x000000, 0x200000, CRC(a089f0f8) SHA1(e975eadd9176a8b9e416229589dfe3158cba22cb) )
455 
456 	// EEPROM - contains security data
457 	ROM_REGION16_BE( 0x200, "eeprom", 0 )
458 	ROM_LOAD16_WORD_SWAP( "93c66-4.bin", 0x000, 0x200, CRC(84d1c26a) SHA1(de823adddf949bf77d8478762720fe0b56fba8ea) )
459 ROM_END
460 
461 // 19-in-1 is visibly different hardware, extent of differences unknown due to lack of quality pictures/scans
462 // also, there is a bootleg of the 19-in-1 which may have less or different protection
463 ROM_START( 19in1 )
464 	// main program, encrypted
465 	ROM_REGION( 0x80000, "maincpu", 0 )
466 	ROM_LOAD( "19in1.u8",    0x000000, 0x080000, CRC(87b0506c) SHA1(c43ae4b403864a28e56370685572fa02e7572e66) )
467 
468 	// data ROM - contains a filesystem with ROMs, fonts, graphics, etc. in an unknown compressed format
469 	ROM_REGION32_LE( 0x200000, "data", 0 )
470 	ROM_LOAD( "16mflash.bin", 0x000000, 0x200000, CRC(a089f0f8) SHA1(e975eadd9176a8b9e416229589dfe3158cba22cb) ) // assuming same flash rom
471 
472 	// EEPROM - contains security data
473 	ROM_REGION16_BE( 0x200, "eeprom", 0 )
474 	ROM_LOAD16_WORD_SWAP( "19in1_eeprom.bin", 0x000, 0x200, NO_DUMP )
475 ROM_END
476 
477 ROM_START( rodent )
478 	ROM_REGION( 0x80000, "maincpu", 0 )
479 	ROM_LOAD( "exterminator.u2", 0x00000, 0x80000, CRC(23c1d21f) SHA1(349565b0f0a015196827707cabb8d9ce6560d2cc) )
480 
481 	ROM_REGION32_LE( 0x200000, "data", 0 )
482 	ROM_LOAD( "m29w160db.u19", 0x000000, 0x200000, CRC(665ee79c) SHA1(35896b97378e8cd78e99d4527b9dc7392e545e17) )
483 
484 	ROM_REGION16_BE( 0x200, "eeprom", 0 )
485 	ROM_LOAD( "93c66.u32", 0x000, 0x200, CRC(c311c7bc) SHA1(8328002b7f6a8b7a3ffca079b7960bc990211d7b) )
486 ROM_END
487 
488 GAME(2004, 4in1a,  39in1, _39in1, 39in1, _39in1_state, init_4in1a,  ROT90, "bootleg", "4 in 1 MAME bootleg (set 1, ver 3.00, PLZ-V014)",             MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
489 GAME(2004, 4in1b,  39in1, _39in1, 39in1, _39in1_state, init_4in1b,  ROT90, "bootleg", "4 in 1 MAME bootleg (set 2, PLZ-V001)",                       MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
490 GAME(2004, 19in1,  39in1, _39in1, 39in1, _39in1_state, init_19in1,  ROT90, "bootleg", "19 in 1 MAME bootleg (BAR-V000)",                             MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
491 GAME(2004, 39in1,  0,     _39in1, 39in1, _39in1_state, init_39in1,  ROT90, "bootleg", "39 in 1 MAME bootleg (GNO-V000)",                             MACHINE_IMPERFECT_SOUND)
492 GAME(2004, 48in1,  39in1, _39in1, 39in1, _39in1_state, init_48in1,  ROT90, "bootleg", "48 in 1 MAME bootleg (set 1, ver 3.09, HPH-V000)",            MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
493 GAME(2004, 48in1b, 39in1, _39in1, 39in1, _39in1_state, init_48in1,  ROT90, "bootleg", "48 in 1 MAME bootleg (set 2, ver 3.09, HPH-V000, alt flash)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
494 GAME(2004, 48in1a, 39in1, _39in1, 39in1, _39in1_state, init_48in1a, ROT90, "bootleg", "48 in 1 MAME bootleg (set 3, ver 3.02, HPH-V000)",            MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
495 GAME(2004, 60in1,  39in1, _39in1, 39in1, _39in1_state, init_60in1,  ROT90, "bootleg", "60 in 1 MAME bootleg (ver 3.00, ICD-V000)",                   MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
496 GAME(2005, rodent, 0,     _39in1, 39in1, _39in1_state, init_rodent, ROT0,  "The Game Room", "Rodent Exterminator",                                   MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
497