1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood, ElSemi, Xing Xing
3 /***********************************************************************
4  PGM IGS027A ARM protection simulations & emulation - type 1
5 
6  these are simulations of the 'kov' type ARM device
7  used by
8 
9  Knights of Valor (kov) + bootlegs
10  Knights of Valor Plus (kovplus)
11  Puzzli 2 / Puzzli 2 Super (puzzli2s)
12  Photo Y2k2 (py2k2)
13  Photo Y2k2 - Flash 3-in-1 (pgm3in1)
14  Puzzle Star (puzlstar)
15 
16  These are implemented in 55857E type chips
17 
18  the following appear to have the same basic behavior as the
19  early '55857E' type chips, but are actually using the '55857G'
20  chips, which execute only area (confirmed on ddpdoj at least)
21 
22  DoDonPachi Dai-ou-jou (ddpdoj)
23  Espgaluda (espgal)
24  Ketsui (ket)
25  Oriental Legend Super Plus (oldsplus)
26  Knights of Valor Super Plus (kovshp) + bootlegs
27 
28  the following also use the 55857E type and we emulate the
29  internal ROM
30 
31  Photo Y2k (photoy2k)
32  Knights of Valor Superheros (kovsh) + bootlegs
33 
34  ----
35 
36  Many of the simulations are preliminary.  If functions to access
37  internal tables exist it is sometimes possible to extract the ROM
38  via these functions if the buffers are unchecked, however many
39  games have no table accesses.
40 
41  ----
42 
43  The basic protection communication is the same between all games
44  however the commands differ
45 
46  None of these games have an external ARM rom, although it appears
47  the program code does check for the possibility of one existing.
48 
49  The 68k ROM gets checksummed by the ARM, the code doesn't even
50  get decrytped if it fails.
51 
52  68k code is encrypted on these, decryption table is uploaded to
53  ARM space.
54 
55  Game Region is supplied by internal ARM rom.
56 
57 
58  ***********************************************************************/
59 
60 #include "emu.h"
61 #include "machine/pgmprot_igs027a_type1.h"
62 
63 #include "screen.h"
64 
65 
66 /**************************** EMULATION *******************************/
67 /* used by photoy2k, kovsh */
68 
arm7_type1_protlatch_r(offs_t offset)69 u16 pgm_arm_type1_state::arm7_type1_protlatch_r(offs_t offset)
70 {
71 	if (!machine().side_effects_disabled())
72 		machine().scheduler().synchronize(); // force resync
73 
74 	if (offset & 1)
75 		return m_arm_type1_highlatch_68k_w;
76 	else
77 		return m_arm_type1_lowlatch_68k_w;
78 }
79 
arm7_type1_protlatch_w(offs_t offset,u16 data)80 void pgm_arm_type1_state::arm7_type1_protlatch_w(offs_t offset, u16 data)
81 {
82 	machine().scheduler().synchronize(); // force resync
83 
84 	if (offset & 1)
85 	{
86 		m_arm_type1_highlatch_arm_w = data;
87 		m_arm_type1_highlatch_68k_w = 0;
88 	}
89 	else
90 	{
91 		m_arm_type1_lowlatch_arm_w = data;
92 		m_arm_type1_lowlatch_68k_w = 0;
93 	}
94 }
95 
arm7_type1_68k_protlatch_r(offs_t offset)96 u16 pgm_arm_type1_state::arm7_type1_68k_protlatch_r(offs_t offset)
97 {
98 	if (!machine().side_effects_disabled())
99 		machine().scheduler().synchronize(); // force resync
100 
101 	switch (offset)
102 	{
103 		case 1: return m_arm_type1_highlatch_arm_w;
104 		case 0: return m_arm_type1_lowlatch_arm_w;
105 	}
106 	return -1;
107 }
108 
arm7_type1_68k_protlatch_w(offs_t offset,u16 data)109 void pgm_arm_type1_state::arm7_type1_68k_protlatch_w(offs_t offset, u16 data)
110 {
111 	machine().scheduler().synchronize(); // force resync
112 
113 	switch (offset)
114 	{
115 		case 1:
116 			m_arm_type1_highlatch_68k_w = data;
117 			break;
118 
119 		case 0:
120 			m_arm_type1_lowlatch_68k_w = data;
121 			break;
122 	}
123 }
124 
arm7_type1_ram_r(offs_t offset,u16 mem_mask)125 u16 pgm_arm_type1_state::arm7_type1_ram_r(offs_t offset, u16 mem_mask)
126 {
127 	const u16 *share16 = reinterpret_cast<u16 *>(m_arm7_shareram.target());
128 
129 	if (PGMARM7LOGERROR)
130 		logerror("M68K: ARM7 Shared RAM Read: %04x = %04x (%08x) %s\n", BYTE_XOR_LE(offset), share16[BYTE_XOR_LE(offset)], mem_mask, machine().describe_context());
131 	return share16[BYTE_XOR_LE(offset << 1)];
132 }
133 
arm7_type1_ram_w(offs_t offset,u16 data,u16 mem_mask)134 void pgm_arm_type1_state::arm7_type1_ram_w(offs_t offset, u16 data, u16 mem_mask)
135 {
136 	u16 *share16 = reinterpret_cast<u16 *>(m_arm7_shareram.target());
137 
138 	if (PGMARM7LOGERROR)
139 		logerror("M68K: ARM7 Shared RAM Write: %04x = %04x (%04x) %s\n", BYTE_XOR_LE(offset), data, mem_mask, machine().describe_context());
140 	COMBINE_DATA(&share16[BYTE_XOR_LE(offset << 1)]);
141 }
142 
143 
arm7_type1_unk_r()144 u32 pgm_arm_type1_state::arm7_type1_unk_r()
145 {
146 	const u32 val = m_arm_type1_counter;
147 	if (!machine().side_effects_disabled())
148 		m_arm_type1_counter++;
149 	return val;
150 }
151 
arm7_type1_exrom_r()152 u32 pgm_arm_type1_state::arm7_type1_exrom_r()
153 {
154 	return 0x00000000;
155 }
156 
arm7_type1_shareram_r(offs_t offset,u32 mem_mask)157 u32 pgm_arm_type1_state::arm7_type1_shareram_r(offs_t offset, u32 mem_mask)
158 {
159 	if (PGMARM7LOGERROR)
160 		logerror("ARM7: ARM7 Shared RAM Read: %04x = %08x (%08x) %s\n", offset << 2, m_arm7_shareram[offset], mem_mask, machine().describe_context());
161 	return m_arm7_shareram[offset];
162 }
163 
arm7_type1_shareram_w(offs_t offset,u32 data,u32 mem_mask)164 void pgm_arm_type1_state::arm7_type1_shareram_w(offs_t offset, u32 data, u32 mem_mask)
165 {
166 	if (PGMARM7LOGERROR)
167 		logerror("ARM7: ARM7 Shared RAM Write: %04x = %08x (%08x) %s\n", offset << 2, data, mem_mask, machine().describe_context());
168 	COMBINE_DATA(&m_arm7_shareram[offset]);
169 }
170 
171 /* 55857E? */
172 /* Knights of Valor, Photo Y2k */
173 /*  no execute only space? */
kov_map(address_map & map)174 void pgm_arm_type1_state::kov_map(address_map &map)
175 {
176 	pgm_mem(map);
177 	map(0x100000, 0x4effff).bankr("bank1"); /* Game ROM */
178 	map(0x4f0000, 0x4f003f).rw(FUNC(pgm_arm_type1_state::arm7_type1_ram_r), FUNC(pgm_arm_type1_state::arm7_type1_ram_w)); /* ARM7 Shared RAM */
179 	map(0x500000, 0x500005).rw(FUNC(pgm_arm_type1_state::arm7_type1_68k_protlatch_r), FUNC(pgm_arm_type1_state::arm7_type1_68k_protlatch_w)); /* ARM7 Latch */
180 }
181 
_55857E_arm7_map(address_map & map)182 void pgm_arm_type1_state::_55857E_arm7_map(address_map &map)
183 {
184 	map(0x00000000, 0x00003fff).rom();
185 	map(0x08100000, 0x083fffff).r(FUNC(pgm_arm_type1_state::arm7_type1_exrom_r)); // unpopulated, returns 0 to keep checksum happy
186 	map(0x10000000, 0x100003ff).ram(); // internal ram for asic
187 	map(0x40000000, 0x40000003).rw(FUNC(pgm_arm_type1_state::arm7_type1_protlatch_r), FUNC(pgm_arm_type1_state::arm7_type1_protlatch_w));
188 	map(0x40000008, 0x4000000b).nopw(); // ?
189 	map(0x4000000c, 0x4000000f).r(FUNC(pgm_arm_type1_state::arm7_type1_unk_r));
190 	map(0x50800000, 0x5080003f).rw(FUNC(pgm_arm_type1_state::arm7_type1_shareram_r), FUNC(pgm_arm_type1_state::arm7_type1_shareram_w)).share("arm7_shareram");
191 	map(0x50000000, 0x500003ff).ram(); // uploads xor table to decrypt 68k rom here
192 }
193 
194 
195 /**************************** SIMULATIONS *****************************/
196 
kov_sim_map(address_map & map)197 void pgm_arm_type1_state::kov_sim_map(address_map &map)
198 {
199 	pgm_mem(map);
200 	map(0x100000, 0x4effff).bankr("bank1"); /* Game ROM */
201 }
202 
cavepgm_mem(address_map & map)203 void pgm_arm_type1_state::cavepgm_mem(address_map &map)
204 {
205 	pgm_base_mem(map);
206 	map(0x000000, 0x3fffff).rom();
207 	/* protection devices installed (simulated) later */
208 }
209 
210 
machine_start()211 void pgm_arm_type1_state::machine_start()
212 {
213 	save_item(NAME(m_value0));
214 	save_item(NAME(m_value1));
215 	save_item(NAME(m_valuekey));
216 	save_item(NAME(m_valueresponse));
217 	save_item(NAME(m_curslots));
218 	save_item(NAME(m_slots));
219 }
220 
pgm_arm_type1(machine_config & config)221 void pgm_arm_type1_state::pgm_arm_type1(machine_config &config) // ARM7 Shared motherboard XTAL
222 {
223 	pgmbase(config);
224 	m_maincpu->set_addrmap(AS_PROGRAM, &pgm_arm_type1_state::kov_map);
225 
226 	/* protection CPU */
227 	ARM7(config, m_prot, 20000000);   // 55857E?
228 	m_prot->set_addrmap(AS_PROGRAM, &pgm_arm_type1_state::_55857E_arm7_map);
229 }
230 
pgm_arm_type1_sim(machine_config & config)231 void pgm_arm_type1_state::pgm_arm_type1_sim(machine_config &config) // When simulated
232 {
233 	pgm_arm_type1(config);
234 	m_maincpu->set_addrmap(AS_PROGRAM, &pgm_arm_type1_state::kov_sim_map);
235 
236 	/* protection CPU */
237 	m_prot->set_disable();
238 }
239 
pgm_arm_type1_cave(machine_config & config)240 void pgm_arm_type1_state::pgm_arm_type1_cave(machine_config &config)
241 {
242 	pgm_arm_type1_sim(config);
243 //  pgm_arm_type1(config); // When ARM7 ROM is dumped and hooked up
244 
245 	m_maincpu->set_addrmap(AS_PROGRAM, &pgm_arm_type1_state::cavepgm_mem);
246 }
247 
arm7_type1_latch_init()248 void pgm_arm_type1_state::arm7_type1_latch_init()
249 {
250 	m_arm_type1_highlatch_arm_w = 0;
251 	m_arm_type1_lowlatch_arm_w = 0;
252 	m_arm_type1_highlatch_68k_w = 0;
253 	m_arm_type1_lowlatch_68k_w = 0;
254 	m_arm_type1_counter = 1;
255 
256 	save_item(NAME(m_arm_type1_highlatch_arm_w));
257 	save_item(NAME(m_arm_type1_lowlatch_arm_w));
258 	save_item(NAME(m_arm_type1_highlatch_68k_w));
259 	save_item(NAME(m_arm_type1_lowlatch_68k_w));
260 	save_item(NAME(m_arm_type1_counter));
261 }
262 
kovsh_fake_region_r()263 u16 pgm_arm_type1_state::kovsh_fake_region_r()
264 {
265 	const int regionhack = m_regionhack->read();
266 	if (regionhack != 0xff) return regionhack;
267 
268 	offs_t offset = 0x4;
269 	u16 *share16 = reinterpret_cast<u16 *>(m_arm7_shareram.target());
270 	return share16[BYTE_XOR_LE(offset << 1)];
271 }
272 
init_photoy2k()273 void pgm_arm_type1_state::init_photoy2k()
274 {
275 	pgm_basic_init();
276 	pgm_photoy2k_decrypt(machine());
277 	arm7_type1_latch_init();
278 	/* we only have a china internal ROM dumped for now.. allow region to be changed for debugging (to ensure all alt titles / regions can be seen) */
279 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0008, 0x4f0009, read16smo_delegate(*this, FUNC(pgm_arm_type1_state::kovsh_fake_region_r)));
280 }
281 
init_kovsh()282 void pgm_arm_type1_state::init_kovsh()
283 {
284 	pgm_basic_init();
285 	pgm_kovsh_decrypt(machine());
286 	arm7_type1_latch_init();
287 	/* we only have a china internal ROM dumped for now.. allow region to be changed for debugging (to ensure all alt titles / regions can be seen) */
288 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0008, 0x4f0009, read16smo_delegate(*this, FUNC(pgm_arm_type1_state::kovsh_fake_region_r)));
289 }
290 
291 /* Fake remapping of ASIC commands to the ones used by KOVSH due to the lack of the real ARM rom for this set */
kovshp_asic27a_write_word(offs_t offset,u16 data)292 void pgm_arm_type1_state::kovshp_asic27a_write_word(offs_t offset, u16 data)
293 {
294 	switch (offset)
295 	{
296 		case 0:
297 			m_arm_type1_lowlatch_68k_w = data;
298 		return;
299 
300 		case 1:
301 		{
302 			const u8 asic_key = data >> 8;
303 			u8 asic_cmd = (data & 0xff) ^ asic_key;
304 
305 			switch (asic_cmd)
306 			{
307 				case 0x9a: asic_cmd = 0x99; break; // kovshxas
308 
309 				case 0x38: asic_cmd = 0xad; break;
310 				case 0x43: asic_cmd = 0xca; break;
311 				case 0x56: asic_cmd = 0xac; break;
312 				case 0x73: asic_cmd = 0x93; break;
313 				case 0x84: asic_cmd = 0xb3; break;
314 				case 0x87: asic_cmd = 0xb1; break;
315 				case 0x89: asic_cmd = 0xb6; break;
316 				case 0x93: asic_cmd = 0x73; break;
317 				case 0xa5: asic_cmd = 0xa9; break;
318 				case 0xac: asic_cmd = 0x56; break;
319 				case 0xad: asic_cmd = 0x38; break;
320 				case 0xb1: asic_cmd = 0x87; break;
321 				case 0xb3: asic_cmd = 0x84; break;
322 				case 0xb4: asic_cmd = 0x90; break;
323 				case 0xb6: asic_cmd = 0x89; break;
324 				case 0xc5: asic_cmd = 0x8c; break;
325 				case 0xca: asic_cmd = 0x43; break;
326 				case 0xcc: asic_cmd = 0xf0; break;
327 				case 0xd0: asic_cmd = 0xe0; break;
328 				case 0xe0: asic_cmd = 0xd0; break;
329 				case 0xe7: asic_cmd = 0x70; break;
330 				case 0xed: asic_cmd = 0xcb; break;
331 				case 0xf0: asic_cmd = 0xcc; break;
332 				case 0xf1: asic_cmd = 0xf5; break;
333 				case 0xf2: asic_cmd = 0xf1; break;
334 				case 0xf4: asic_cmd = 0xf2; break;
335 				case 0xf5: asic_cmd = 0xf4; break;
336 				case 0xfc: asic_cmd = 0xc0; break;
337 				case 0xfe: asic_cmd = 0xc3; break;
338 
339 				case 0xa6: asic_cmd = 0xa9; break;
340 				case 0xaa: asic_cmd = 0x56; break;
341 				case 0xf8: asic_cmd = 0xf3; break;
342 			}
343 
344 			m_arm_type1_highlatch_68k_w = asic_cmd ^ (asic_key | (asic_key << 8));
345 		}
346 		return;
347 	}
348 }
349 
350 
init_kovshp()351 void pgm_arm_type1_state::init_kovshp()
352 {
353 	pgm_basic_init();
354 	pgm_kovshp_decrypt(machine());
355 	arm7_type1_latch_init();
356 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0008, 0x4f0009, read16smo_delegate(*this, FUNC(pgm_arm_type1_state::kovsh_fake_region_r)));
357 	m_maincpu->space(AS_PROGRAM).install_write_handler(0x500000, 0x500005, write16sm_delegate(*this, FUNC(pgm_arm_type1_state::kovshp_asic27a_write_word)));
358 }
359 
360 
361 /* bootleg inits */
362 
init_kovshxas()363 void pgm_arm_type1_state::init_kovshxas()
364 {
365 	pgm_basic_init();
366 //  pgm_kovshp_decrypt(machine());
367 	arm7_type1_latch_init();
368 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0008, 0x4f0009, read16smo_delegate(*this, FUNC(pgm_arm_type1_state::kovsh_fake_region_r)));
369 	m_maincpu->space(AS_PROGRAM).install_write_handler(0x500000, 0x500005, write16sm_delegate(*this, FUNC(pgm_arm_type1_state::kovshp_asic27a_write_word)));
370 }
371 
pgm_decode_kovlsqh2_tiles()372 void pgm_arm_type1_state::pgm_decode_kovlsqh2_tiles()
373 {
374 	u16 *src = (u16 *)(memregion("tiles")->base() + 0x180000);
375 	std::vector<u16> dst(0x800000);
376 
377 	for (int i = 0; i < 0x800000 / 2; i++)
378 	{
379 		const int j = bitswap<24>(i, 23, 22, 9, 8, 21, 18, 0, 1, 2, 3, 16, 15, 14, 13, 12, 11, 10, 19, 20, 17, 7, 6, 5, 4);
380 
381 		dst[j] = bitswap<16>(src[i], 1, 14, 8, 7, 0, 15, 6, 9, 13, 2, 5, 10, 12, 3, 4, 11);
382 	}
383 
384 	memcpy( src, &dst[0], 0x800000 );
385 }
386 
pgm_decode_kovlsqh2_sprites(u8 * src)387 void pgm_arm_type1_state::pgm_decode_kovlsqh2_sprites( u8 *src )
388 {
389 	std::vector<u8> dst(0x800000);
390 
391 	for (int i = 0; i < 0x800000; i++)
392 	{
393 		const int j = bitswap<24>(i, 23, 10, 9, 22, 19, 18, 20, 21, 17, 16, 15, 14, 13, 12, 11, 8, 7, 6, 5, 4, 3, 2, 1, 0);
394 
395 		dst[j] = src[i];
396 	}
397 
398 	memcpy( src, &dst[0], 0x800000 );
399 }
400 
pgm_decode_kovlsqh2_samples()401 void pgm_arm_type1_state::pgm_decode_kovlsqh2_samples()
402 {
403 	u8 *src = (u8 *)(memregion("ics")->base() + 0x400000);
404 
405 	for (int i = 0; i < 0x400000; i+=2) {
406 		src[i + 0x000001] = src[i + 0x400001];
407 	}
408 
409 	memcpy( src + 0x400000, src, 0x400000 );
410 }
411 
pgm_decode_kovqhsgs_program()412 void pgm_arm_type1_state::pgm_decode_kovqhsgs_program()
413 {
414 	u16 *src = (u16 *)(memregion("maincpu")->base() + 0x100000);
415 	std::vector<u16> dst(0x400000);
416 
417 	for (int i = 0; i < 0x400000 / 2; i++)
418 	{
419 		const int j = bitswap<24>(i, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 5, 4, 3, 2, 1, 0);
420 
421 		dst[j] = bitswap<16>(src[i], 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 5, 3, 2, 1, 0);
422 	}
423 
424 	memcpy( src, &dst[0], 0x400000 );
425 }
426 
pgm_decode_kovqhsgs2_program()427 void pgm_arm_type1_state::pgm_decode_kovqhsgs2_program()
428 {
429 	u16 *src = (u16 *)(memregion("maincpu")->base() + 0x100000);
430 	std::vector<u16> dst(0x400000);
431 
432 	for (int i = 0; i < 0x400000 / 2; i++)
433 	{
434 		const int j = bitswap<24>(i, 23, 22, 21, 20, 19, 16, 15, 14, 13, 12, 11, 10, 9, 8, 0, 1, 2, 3, 4, 5, 6, 18, 17, 7);
435 
436 		dst[j] = src[i];
437 	}
438 
439 	memcpy( src, &dst[0], 0x400000 );
440 }
441 
442 
init_kovlsqh2()443 void pgm_arm_type1_state::init_kovlsqh2()
444 {
445 	pgm_decode_kovqhsgs2_program();
446 	pgm_decode_kovlsqh2_tiles();
447 
448 	pgm_decode_kovlsqh2_sprites(memregion("sprcol")->base() + 0x0000000);
449 	pgm_decode_kovlsqh2_sprites(memregion("sprcol")->base() + 0x0800000);
450 	pgm_decode_kovlsqh2_sprites(memregion("sprcol")->base() + 0x1000000);
451 	pgm_decode_kovlsqh2_sprites(memregion("sprcol")->base() + 0x1800000);
452 	pgm_decode_kovlsqh2_sprites(memregion("sprcol")->base() + 0x2000000);
453 	pgm_decode_kovlsqh2_sprites(memregion("sprcol")->base() + 0x2800000);
454 	pgm_decode_kovlsqh2_sprites(memregion("sprmask")->base() + 0x0000000);
455 	pgm_decode_kovlsqh2_sprites(memregion("sprmask")->base() + 0x0800000);
456 
457 	pgm_decode_kovlsqh2_samples();
458 	pgm_basic_init();
459 	arm7_type1_latch_init();
460 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0008, 0x4f0009, read16smo_delegate(*this, FUNC(pgm_arm_type1_state::kovsh_fake_region_r)));
461 	m_maincpu->space(AS_PROGRAM).install_write_handler(0x500000, 0x500005, write16sm_delegate(*this, FUNC(pgm_arm_type1_state::kovshp_asic27a_write_word)));
462 }
463 
init_kovqhsgs()464 void pgm_arm_type1_state::init_kovqhsgs()
465 {
466 	pgm_decode_kovqhsgs_program();
467 	pgm_decode_kovlsqh2_tiles();
468 
469 	pgm_decode_kovlsqh2_sprites(memregion("sprcol")->base() + 0x0000000);
470 	pgm_decode_kovlsqh2_sprites(memregion("sprcol")->base() + 0x0800000);
471 	pgm_decode_kovlsqh2_sprites(memregion("sprcol")->base() + 0x1000000);
472 	pgm_decode_kovlsqh2_sprites(memregion("sprcol")->base() + 0x1800000);
473 	pgm_decode_kovlsqh2_sprites(memregion("sprcol")->base() + 0x2000000);
474 	pgm_decode_kovlsqh2_sprites(memregion("sprcol")->base() + 0x2800000);
475 	pgm_decode_kovlsqh2_sprites(memregion("sprmask")->base() + 0x0000000);
476 	pgm_decode_kovlsqh2_sprites(memregion("sprmask")->base() + 0x0800000);
477 
478 	pgm_decode_kovlsqh2_samples();
479 	pgm_basic_init();
480 	arm7_type1_latch_init();
481 	/* we only have a china internal ROM dumped for now.. allow region to be changed for debugging (to ensure all alt titles / regions can be seen) */
482 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0008, 0x4f0009, read16smo_delegate(*this, FUNC(pgm_arm_type1_state::kovsh_fake_region_r)));
483 }
484 
485 /*
486  in Ketsui (ket) @ 000A719C (move.w)
487 
488  if you change D0 to 0x12
489  the game will runs to "Asic27 Test" mode
490 
491  bp A71A0,1,{d0=0x12;g}
492 */
493 
arm7_type1_sim_r(offs_t offset)494 u16 pgm_arm_type1_state::arm7_type1_sim_r(offs_t offset)
495 {
496 	if (offset == 0)
497 	{
498 		u16 d = m_valueresponse & 0xffff;
499 		u16 realkey = m_valuekey >> 8;
500 		realkey |= m_valuekey;
501 		d ^= realkey;
502 		return d;
503 	}
504 	else if (offset == 1)
505 	{
506 		u16 d = m_valueresponse >> 16;
507 		u16 realkey = m_valuekey >> 8;
508 		realkey |= m_valuekey;
509 		d ^= realkey;
510 		return d;
511 	}
512 	return 0xffff;
513 }
514 
515 /* working */
command_handler_ddp3(int pc)516 void pgm_arm_type1_state::command_handler_ddp3(int pc)
517 {
518 	switch (m_ddp3lastcommand)
519 	{
520 		default:
521 			printf("%06x command %02x | %04x\n", pc, m_ddp3lastcommand, m_value0);
522 			m_valueresponse = 0x880000;
523 			break;
524 
525 		case 0x40:
526 			m_valueresponse = 0x880000;
527 			m_slots[(m_value0 >> 10) & 0x1F]=
528 				(m_slots[(m_value0 >> 5) & 0x1F]+
529 					m_slots[(m_value0 >> 0) & 0x1F]) & 0xffffff;
530 			break;
531 
532 		case 0x67: // set high bits
533 	//      printf("%s command %02x | %04x\n", machine().describe_context().c_str(), m_ddp3lastcommand, m_value0);
534 			m_valueresponse = 0x880000;
535 			m_curslots = (m_value0 & 0xff00) >> 8;
536 			m_slots[m_curslots] = (m_value0 & 0x00ff) << 16;
537 			break;
538 
539 		case 0xe5: // set low bits for operation?
540 		//  printf("%s command %02x | %04x\n", machine().describe_context().c_str(), m_ddp3lastcommand, m_value0);
541 			m_valueresponse = 0x880000;
542 			m_slots[m_curslots] |= (m_value0 & 0xffff);
543 			break;
544 
545 		case 0x8e: // read back result of operations
546 	//      printf("%s command %02x | %04x\n", machine().describe_context().c_str(), m_ddp3lastcommand, m_value0);
547 			m_valueresponse = m_slots[m_value0 & 0xff];
548 			break;
549 
550 		case 0x99: // reset?
551 			m_simregion = 0;//m_region->read();
552 			m_valuekey = 0x100;
553 			m_valueresponse = 0x00880000 | m_simregion << 8;
554 			break;
555 
556 	}
557 }
558 
559 /* preliminary */
560 
561 // should be correct, note each value only appears once
562 u8 puzzli2_level_decode[256] = {
563 	// 0  ,  1  ,  2  ,  3  ,  4  ,  5   , 6  ,  7  ,  8  ,  9  ,  a  ,  b  ,  c  ,  d  ,  e  ,  f  ,
564 	0x32, 0x3e, 0xb2, 0x37, 0x31, 0x22, 0xd6, 0x0d, 0x35, 0x5c, 0x8d, 0x3c, 0x7a, 0x5f, 0xd7, 0xac, // 0x0
565 //   0  ,  0  ,  0  ,  0  ,  0  ,  1  ,  1  ,  0  ,  1  ,  1  ,  0  ,  0  ,  0  ,  0  ,  x  ,  x  ,
566 	0x53, 0xff, 0xeb, 0x44, 0xe8, 0x11, 0x69, 0x77, 0xd9, 0x34, 0x36, 0x45, 0xa6, 0xe9, 0x1c, 0xc6, // 0x1
567 //   0  ,  0  ,  x  ,  x  ,  x  ,  0  ,  x  ,  0  ,  x  ,  0  ,  0  ,  0  ,  0  ,  x  ,  0  ,  x  ,
568 	0x3b, 0xbd, 0xad, 0x2e, 0x18, 0xdf, 0xa1, 0xab, 0xdd, 0x52, 0x57, 0xc2, 0xe5, 0x0a, 0x00, 0x6d, // 0x2
569 //   0  ,  0  ,  0  ,  1  ,  1  ,  1  ,  1  ,  x  ,  1  ,  1  ,  0  ,  0  ,  1  ,  1  ,  x  ,  0  ,
570 	0x67, 0x64, 0x15, 0x70, 0xb6, 0x39, 0x27, 0x78, 0x82, 0xd2, 0x71, 0xb9, 0x13, 0xf5, 0x93, 0x92, // 0x3
571 //   0  ,  x  ,  1  ,  1  ,  x  ,  1  ,  1  ,  1  ,  1  ,  1  ,  1  ,  1  ,  x  ,  0  ,  x  ,  x  ,
572 	0xfa, 0xe7, 0x5e, 0xb0, 0xf6, 0xaf, 0x95, 0x8a, 0x7c, 0x73, 0xf9, 0x63, 0x86, 0xcb, 0x1a, 0x56, // 0x4
573 //   0  ,  1  ,  1  ,  0  ,  0  ,  0  ,  0  ,  1  ,  1  ,  1  ,  1  ,  0  ,  1  ,  1  ,  1  ,  0  ,
574 	0xf1, 0x3a, 0xae, 0x61, 0x01, 0x29, 0x97, 0x23, 0x8e, 0x5d, 0x9a, 0x65, 0x74, 0x21, 0x20, 0x40, // 0x5
575 //   0  ,  1  ,  1  ,  1  ,  1  ,  0  ,  x  ,  x  ,  x  ,  0  ,  0  ,  1  ,  1  ,  1  ,  1  ,  1  ,
576 	0xd3, 0x05, 0xa2, 0xe1, 0xbc, 0x9e, 0x1e, 0x10, 0x14, 0x0c, 0x88, 0x9c, 0xec, 0x38, 0xb5, 0x9d, // 0x6
577 //   1  ,  0  ,  0  ,  x  ,  1  ,  1  ,  0  ,  0  ,  x  ,  0  ,  x  ,  0  ,  0  ,  1  ,  1  ,  1  ,
578 	0x2d, 0xf7, 0x17, 0x0e, 0x84, 0xc7, 0x7d, 0xce, 0x94, 0x16, 0x48, 0xa8, 0x81, 0x6e, 0x7b, 0xd8, // 0x7
579 //   1  ,  1  ,  1  ,  1  ,  x  ,  0  ,  x  ,  0  ,  1  ,  1  ,  1  ,  x  ,  x  ,  1  ,  1  ,  1  ,
580 	0xa7, 0x7f, 0x42, 0xe6, 0xa0, 0x2a, 0xef, 0xee, 0x24, 0xba, 0xb8, 0x7e, 0xc9, 0x2b, 0x90, 0xcc, // 0x8
581 //   1  ,  x  ,  1  ,  1  ,  1  ,  1  ,  1  ,  1  ,  0  ,  0  ,  0  ,  0  ,  0  ,  0  ,  0  ,  0  ,
582 	0x5b, 0xd1, 0xf3, 0xe2, 0x6f, 0xed, 0x9f, 0xf0, 0x4b, 0x54, 0x8c, 0x08, 0xf8, 0x51, 0x68, 0xc8, // 0x9
583 //   x  ,  0  ,  0  ,  0  ,  0  ,  0  ,  0  ,  0  ,  x  ,  0  ,  x  ,  0  ,  0  ,  0  ,  0  ,  1  ,
584 	0x03, 0x0b, 0xbb, 0xc1, 0xe3, 0x4d, 0x04, 0xc5, 0x8f, 0x09, 0x0f, 0xbf, 0x62, 0x49, 0x76, 0x59, // 0xa
585 //   1  ,  1  ,  1  ,  1  ,  1  ,  x  ,  0  ,  1  ,  1  ,  0  ,  x  ,  1  ,  1  ,  1  ,  1  ,  0  ,
586 	0x1d, 0x80, 0xde, 0x60, 0x07, 0xe0, 0x1b, 0x66, 0xa5, 0xbe, 0xcd, 0x87, 0xdc, 0xc3, 0x6b, 0x4e, // 0xb
587 //   0  ,  1  ,  1  ,  1  ,  1  ,  x  ,  0  ,  x  ,  0  ,  x  ,  0  ,  1  ,  1  ,  0  ,  1  ,  1  ,
588 	0xd0, 0xfd, 0xd4, 0x3f, 0x98, 0x96, 0x2f, 0x4c, 0xb3, 0xea, 0x2c, 0x75, 0xe4, 0xc0, 0x6c, 0x6a, // 0xc
589 //   0  ,  x  ,  1  ,  1  ,  0  ,  1  ,  1  ,  1  ,  1  ,  0  ,  1  ,  1  ,  x  ,  1  ,  1  ,  1  ,
590 	0x9b, 0xb7, 0x43, 0x8b, 0x41, 0x47, 0x02, 0xdb, 0x99, 0x3d, 0xa3, 0x79, 0x50, 0x4f, 0xb4, 0x55, // 0xd
591 //   1  ,  0  ,  0  ,  0  ,  1  ,  0  ,  0  ,  x  ,  x  ,  1  ,  1  ,  1  ,  0  ,  1  ,  1  ,  1  ,
592 	0x5a, 0x25, 0xf4, 0xca, 0x58, 0x30, 0xc4, 0x12, 0xa9, 0x46, 0xda, 0x91, 0xa4, 0xaa, 0xfc, 0x85, // 0xe
593 //   1  ,  1  ,  0  ,  1  ,  1  ,  1  ,  1  ,  0  ,  0  ,  1  ,  1  ,  1  ,  1  ,  0  ,  0  ,  x  ,
594 	0xfb, 0x89, 0x06, 0xcf, 0xfe, 0x33, 0xd5, 0x28, 0x1f, 0x19, 0x4a, 0xb1, 0x83, 0xf2, 0x72, 0x26, // 0xf
595 //   x  ,  x  ,  1  ,  1  ,  1  ,  1  ,  1  ,  1  ,  x  ,  0  ,  1  ,  1  ,  1  ,  1  ,  1  ,  1  ,
596 };
597 
598 
599 #define puzzli2_printf logerror
600 
command_handler_puzzli2(int pc)601 void pgm_arm_type1_state::command_handler_puzzli2(int pc)
602 {
603 	switch (m_ddp3lastcommand)
604 	{
605 		case 0x31:
606 		{
607 			// how is this selected? command 54?
608 
609 			/* writes the following sequence before how to play
610 			 each level has a different sequence written before it, size of sequence doesn't seem directly connected to level size (unlike the reads)
611 			 so it's probably compressed somehow as well as scrambled?  68k doesnt know in advance how big each lot of data is either, it only stops
612 			 writing when it gets a difference response from the MCU.
613 
614 			00138278: 31 00fd | (set xor table offset)
615 		UNKNOWN - related to depth / number of columns?
616 			00138278: 31 0087 | value 87, after xor is 75 (table address,value fd,f2)
617 		COLUMN 1
618 			00138278: 31 0032 | value 32, after xor is 40 (table address,value fe,72) << 4 is the number of entries in this column
619 			00138278: 31 0029 | value 29, after xor is 0f (table address,value ff,26) << 0x0f is a mask of 4 bits..
620 
621 			00138278: 31 0031 | value 31, after xor is 03 (table address,value 00,32)  -> 0x0103
622 			00138278: 31 003f | value 3f, after xor is 01 (table address,value 01,3e)  -> 0x0101
623 			00138278: 31 00b0 | value b0, after xor is 02 (table address,value 02,b2)  -> 0x0102
624 			00138278: 31 0035 | value 35, after xor is 02 (table address,value 03,37)  -> 0x0102
625 		COLUMN 2
626 			00138278: 31 0071 | value 71, after xor is 40 (table address,value 04,31) << 4 is the number of entries in this column
627 			00138278: 31 002d | value 2d, after xor is 0f (table address,value 05,22) << 0x0f is a mask of 4 bits..
628 
629 			00138278: 31 00d5 | value d5, after xor is 03 (table address,value 06,d6)  -> 0x0103
630 			00138278: 31 000d | value 0d, after xor is 00 (table address,value 07,0d)  -> 0x0100
631 			00138278: 31 0034 | value 34, after xor is 01 (table address,value 08,35)  -> 0x0101
632 			00138278: 31 0059 | value 59, after xor is 05 (table address,value 09,5c)  -> 0x0105
633 		COLUMN 3
634 			00138278: 31 00dd | value dd, after xor is 50 (table address,value 0a,8d) << 5 is the number of entries in this column
635 			00138278: 31 0023 | value 23, after xor is 1f (table address,value 0b,3c) << 0x1f is a mask of 5 bits..
636 
637 			00138278: 31 007a | value 7a, after xor is 00 (table address,value 0c,7a)  -> 0x0100
638 			00138278: 31 00f3 | value f3, after xor is 01 (table address,value fd,f2)  -> 0x0101
639 			00138278: 31 0077 | value 77, after xor is 05 (table address,value fe,72)  -> 0x0105
640 			00138278: 31 0022 | value 22, after xor is 04 (table address,value ff,26)  -> 0x0104
641 			00138278: 31 0036 | value 36, after xor is 04 (table address,value 00,32)  -> 0x0104
642 		COLUMN 4
643 			00138278: 31 002e | value 2e, after xor is 10 (table address,value 01,3e) << 1 is the number of entries in this column
644 			00138278: 31 00b3 | value b3, after xor is 01 (table address,value 02,b2) << 0x01 is a mask of 1 bit..
645 
646 			00138278: 31 0035 | value 35, after xor is 02 (table address,value 03,37)  -> 0x0102
647 		COLUMN 5
648 			00138278: 31 0041 | value 41, after xor is 70 (table address,value 04,31) << 7 is the number of entries in this column
649 			00138278: 31 005d | value 5d, after xor is 7f (table address,value 05,22) << 0x7f is a mask of 7 bits..
650 
651 			00138278: 31 00d6 | value d6, after xor is 00 (table address,value 06,d6)  -> 0x0100
652 			00138278: 31 000c | value 0c, after xor is 01 (table address,value 07,0d)  -> 0x0101
653 			00138278: 31 0036 | value 36, after xor is 03 (table address,value 08,35)  -> 0x0103
654 			00138278: 31 005e | value 5e, after xor is 02 (table address,value 09,5c)  -> 0x0102
655 			00138278: 31 0089 | value 89, after xor is 04 (table address,value 0a,8d)  -> 0x0104
656 			00138278: 31 003c | value 3c, after xor is 00 (table address,value 0b,3c)  -> 0x0100
657 			00138278: 31 007a | value 7a, after xor is 00 (table address,value 0c,7a)  -> 0x0100
658 		COLUMN 6
659 			00138278: 31 00a2 | value a2, after xor is 50 (table address,value fd,f2) << 5 is the number of entries in this column
660 			00138278: 31 006d | value 6d, after xor is 1f (table address,value fe,72) << 0x1f is a mask of 5 bits..
661 
662 			00138278: 31 0023 | value 23, after xor is 05 (table address,value ff,26)  -> 0x0105
663 			00138278: 31 0037 | value 37, after xor is 05 (table address,value 00,32)  -> 0x0105
664 			00138278: 31 003f | value 3f, after xor is 01 (table address,value 01,3e)  -> 0x0101
665 			00138278: 31 00b3 | value b3, after xor is 01 (table address,value 02,b2)  -> 0x0101
666 			00138278: 31 0034 | value 34, after xor is 03 (table address,value 03,37)  -> 0x0103
667 			 ^ (end, returning 630006 as playfield width)
668 
669 			*/
670 
671 			if (command_31_write_type==2)
672 			{
673 				puzzli2_printf("%08x: %02x %04x | ",pc, m_ddp3lastcommand, m_value0);
674 
675 				// this shouldn't apply to the stuff written on startup, only the level data..
676 
677 				if (hackcount2==0)
678 				{
679 					puzzli2_take_leveldata_value(m_value0 & 0xff);
680 
681 					hack_31_table_offset = m_value0 & 0xff;
682 					hack_31_table_offset2 = 0;
683 					hackcount2++;
684 					m_valueresponse = 0x00d20000;
685 
686 					//puzzli2_printf("(set xor table offset)\n");
687 				}
688 				else  // how do we decide end?
689 				{
690 					int end = puzzli2_take_leveldata_value(m_value0 & 0xff);
691 
692 					if (!end)
693 					{
694 						// always d2 0000 when writing doing level data
695 						// but different for the writes on startup?
696 						m_valueresponse = 0x00d20000;
697 
698 						//u8 tableaddr = (hack_31_table_offset + (hack_31_table_offset2 & 0xf)) & 0xff;
699 						//u8 xoredval = m_value0 ^ puzzli2_level_decode[tableaddr];
700 						//puzzli2_printf("value %02x, after xor is %02x (table address,value %02x,%02x)\n", m_value0, xoredval, tableaddr, puzzli2_level_decode[tableaddr]);
701 
702 						hackcount2++;
703 						hack_31_table_offset2++;
704 					}
705 					else
706 					{
707 						hackcount2 = 0;
708 
709 						// when the ARM detects the end of the stream has been reached it returns a 0x63 status with the number of columns in the data word
710 						m_valueresponse = 0x00630000 | numbercolumns;
711 
712 						//u8 tableaddr = (hack_31_table_offset + (hack_31_table_offset2 & 0xf)) & 0xff;
713 						//u8 xoredval = m_value0 ^ puzzli2_level_decode[tableaddr];
714 						//puzzli2_printf("value %02x, after xor is %02x (table address,value %02x,%02x) (end, returning %02x as playfield width)\n", m_value0, xoredval, tableaddr, puzzli2_level_decode[tableaddr], m_valueresponse);
715 					}
716 				}
717 			}
718 			else
719 			{
720 				// todo, responses when uploading the startup values are different
721 				puzzli2_printf("%08x: %02x %04x (for z80 address?)\n ",pc, m_ddp3lastcommand, m_value0);
722 
723 				m_valueresponse = 0x00d20000 | p2_31_retcounter;
724 				p2_31_retcounter++; // returns 0xc for the first one, 0x19 for the last one
725 			}
726 
727 		}
728 		break;
729 
730 		// after writing the compressed and scrambled data stream for the level (copied from ROM) with command 0x31
731 		// the game expects to read back a fully formed level structure from the ARM
732 		case 0x13:
733 		{
734 			puzzli2_printf("%08x: %02x %04x (READ LEVEL DATA) | ",pc, m_ddp3lastcommand, m_value0);
735 
736 			// this is the how to play screen, correctly returned with current code
737 			/*
738 			u16 retvals[61] =
739 			{ 0x0008, // depth (-2?)
740 			  0x0103, 0x0101, 0x0102, 0x0102, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // first column
741 			  0x0103, 0x0100, 0x0101, 0x0105, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
742 			  0x0100, 0x0101, 0x0105, 0x0104, 0x0104, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
743 			  0x0102, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
744 			  0x0100, 0x0101, 0x0103, 0x0102, 0x0104, 0x0100 ,0x0100, 0x0000, 0x0000, 0x0000,
745 			  0x0105, 0x0105, 0x0101, 0x0101, 0x0103, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000  // last column
746 			};
747 			*/
748 
749 
750 			u16* leveldata = &level_structure[0][0];
751 			if (hackcount==0)
752 			{
753 				m_valueresponse = 0x002d0000 | ((depth>>4)+1); // this *seems* to come from upper bits of the first real value written to the device during the level stream (verify, seems wrong for some levels because you get a black bar on the bottom of the screen, but might be bad xors)
754 				puzzli2_printf("level depth returning %08x\n", m_valueresponse );
755 			}
756 			else if (hackcount<((10*numbercolumns)+1))
757 			{
758 				m_valueresponse = 0x002d0000 | leveldata[hackcount-1];
759 				puzzli2_printf("level data returning %08x\n", m_valueresponse );
760 			}
761 			else
762 			{
763 				hackcount=0;
764 				m_valueresponse = 0x00740054;  // 0x0074 0054 is returned after how to play reads above.. where does 0x54 come from?
765 				puzzli2_printf("END returning %08x\n", m_valueresponse );
766 
767 			}
768 
769 			hackcount++;
770 
771 
772 			// 2d seems to be used when there is more data available
773 			// 74 seems to be used when there isn't.. (end of buffer reached?)
774 			// 2d or 74! (based on?)
775 
776 		}
777 		break;
778 
779 
780 
781 		case 0x38: // Reset
782 			puzzli2_printf("%08x: %02x %04x (RESET)\n",pc, m_ddp3lastcommand, m_value0);
783 			m_simregion = m_region->read();
784 			m_valueresponse = 0x780000 | m_simregion<<8; // this must also return the cart region or the game will act in odd ways when inserting a coin on continue, or during the game on later levels
785 			m_valuekey = 0x100;
786 			m_puzzli_54_trigger = 0;
787 
788 		break;
789 
790 
791 
792 
793 		// 47 and 52 are used to get the images during the intro sequence, different each loop
794 		// also some other gfx?
795 		// logic here seems correct, not sure where the 0x19 and 0x5 etc. come from tho!
796 		case 0x47:
797 			puzzli2_printf("%08x: %02x %04x (GFX OFF PART 1)\n",pc, m_ddp3lastcommand, m_value0);
798 
799 			hack_47_value = m_value0;
800 
801 			//hack_47_value = ((m_value0 & 0x0700) >> 8) * 0x19;
802 			//hack_47_value +=((m_value0 & 0x0007) >> 0) * 0x05;
803 			if (m_value0 & 0xf0f0) puzzli2_printf("unhandled 0x47 bits %04x\n", m_value0);
804 
805 			//puzzli2_printf("0x47 value was %04x - using %04x\n", m_value0, hack_47_value);
806 
807 			m_valueresponse = 0x00740047;
808 
809 		break;
810 
811 		case 0x52:
812 			puzzli2_printf("%08x: %02x %04x (GFX OFF PART 2)\n",pc, m_ddp3lastcommand, m_value0);
813 
814 			//puzzli2_printf("which %04x\n", m_value0);
815 			if (m_value0 & 0xfff0) puzzli2_printf("unhandled 0x52 bits %04x\n", m_value0);
816 
817 			// it writes a value of 0x0000 then expects to read back like
818 			// this for the lower part of the game backgrounds
819 			if (m_value0 == 0x0000)
820 			{
821 				int val = ((hack_47_value & 0x0f00) >> 8) * 0x19;
822 				m_valueresponse = 0x00740000 | (val & 0xffff);
823 			}
824 			else
825 			{
826 				int val = ((hack_47_value & 0x0f00) >> 8) * 0x19;
827 				val +=((hack_47_value & 0x000f) >> 0) * 0x05;
828 				val += m_value0 & 0x000f;
829 				m_valueresponse = 0x00740000 | (val & 0xffff);
830 
831 			}
832 
833 
834 
835 		break;
836 
837 
838 
839 		case 0x61: // ??
840 			puzzli2_printf("%08x: %02x %04x\n",pc, m_ddp3lastcommand, m_value0);
841 
842 			// this command is written before the values used to decrypt the z80 addresses (assumed) are uploaded with command 31
843 			command_31_write_type = 1;
844 
845 			m_valueresponse = 0x36 << 16;
846 			p2_31_retcounter = 0xc;
847 		break;
848 
849 		case 0x41: // ASIC status?
850 			puzzli2_printf("%08x: %02x %04x (UNK)\n",pc, m_ddp3lastcommand, m_value0);
851 
852 			// this command is written after the values used to decrypt the z80 addresses (assumed) are uploaded with command 31
853 			command_31_write_type = 0;
854 
855 			//m_valueresponse = 0x74 << 16;
856 			m_valueresponse = 0x740061;
857 		break;
858 
859 		case 0x54: // ??
860 			puzzli2_printf("%08x: %02x %04x\n",pc, m_ddp3lastcommand, m_value0);
861 
862 			// this command is written before uploading the compressed level data stream with command 31
863 
864 			command_31_write_type = 2;
865 			stage = -1;
866 			m_puzzli_54_trigger = 1;
867 			hackcount2 = 0;
868 			hackcount = 0;
869 			m_valueresponse = 0x36 << 16;
870 
871 			//  clear the return structure
872 			for (auto & elem : level_structure)
873 				for (int rows=0;rows<10;rows++)
874 					elem[rows] = 0x0000;
875 
876 		break;
877 
878 	/*
879 
880 	puzzli2 on startup (00148a84)         puzzli2s on startup (0014cf58)
881 
882 	    (001489f6: 61 0202  0014ceca: 61 0202)
883 	                                           always
884 	    : 31 004e a6f7 | : 31 | 0051 14c9       + 26DD2
885 	    : 31 279e 534f | : 31 | 27a0 c121
886 	    : 31 ab5c a7cf | : 31 | ab5f 15a1
887 	    : 31 145f 7054 | : 31 | 1461 de26
888 	    : 31 85a0 7b7f | : 31 | 85a2 e951
889 	    : 31 7003 c5ab | : 31 | 7006 337d
890 	    : 31 456d f3aa | : 31 | 4570 617c
891 
892 	    (00148b34: 41 e2bb  0014d008: 41 706d)
893 
894 	    actual values needed       always
895 	    0x001694a8 / 0x0019027a  + 26DD2
896 	    0x0016cfae / 0x00193D80
897 	    0x0016ebf2 / 0x001959c4
898 	    0x0016faa8 / 0x0019687a
899 	    0x00174416 / 0x0019b1e8
900 
901 	    0x00166178 / 0x0018cf4a
902 	    0x00166e72 / 0x0018dc44
903 
904 	     as you can see the difference between the values written is always 26dd2, as is the difference between offsets expected
905 	     this makes it impossible to know which value is for which address without further tests!
906 
907 
908 	*/
909 
910 		// I think the values returned here must be connected to the values written to command 31 on startup
911 		// 63/67 are used on startup to get the z80 music at least
912 		case 0x63: // used as a read address by the 68k code (related to previous uploaded values like cave?) should point at a table of ~0x80 in size? seems to use values as further pointers?
913 			puzzli2_printf("%08x: %02x %04x (Z80 ADDR PART 1)\n",pc, m_ddp3lastcommand, m_value0);
914 
915 			if (!strcmp(machine().system().name,"puzzli2"))
916 			{
917 				if (m_value0 == 0x0000)
918 				{
919 					m_valueresponse = 0x001694a8;
920 				}
921 				else if (m_value0 == 0x0001)
922 				{
923 					m_valueresponse = 0x0016cfae;
924 				}
925 				else if (m_value0 == 0x0002)
926 				{
927 					m_valueresponse = 0x0016ebf2; // right for puzzli2 , wrong for puzzli2s, probably calculated from the writes then?
928 				}
929 				else if (m_value0 == 0x0003) // before 'cast' screen
930 				{
931 					m_valueresponse = 0x0016faa8;
932 				}
933 				else if (m_value0 == 0x0004) // 2 player demo
934 				{
935 					m_valueresponse = 0x00174416;
936 				}
937 				else
938 				{
939 					puzzli2_printf("unk case x63\n");
940 					m_valueresponse = 0x00600000; // wrong
941 
942 				}
943 			}
944 			else // puzzli2 super
945 			{
946 				if (m_value0 == 0x0000)
947 				{
948 					m_valueresponse = 0x19027a;
949 				}
950 				else if (m_value0 == 0x0001)
951 				{
952 					m_valueresponse = 0x193D80;
953 				}
954 				else if (m_value0 == 0x0002)
955 				{
956 					m_valueresponse = 0x1959c4;
957 				}
958 				else if (m_value0 == 0x0003)
959 				{
960 					m_valueresponse = 0x19687a;
961 				}
962 				else if (m_value0 == 0x0004)
963 				{
964 					m_valueresponse = 0x19b1e8;
965 				}
966 				else
967 				{
968 					puzzli2_printf("unk case x63\n");
969 					m_valueresponse = 0x00600000; // wrong
970 				}
971 			}
972 		break;
973 
974 		case 0x67: // used as a read address by the 68k code (related to previous uploaded values like cave?) directly reads ~0xDBE from the address..
975 			puzzli2_printf("%08x: %02x %04x (Z80 ADDR PART 2)\n",pc, m_ddp3lastcommand, m_value0);
976 
977 			if (!strcmp(machine().system().name,"puzzli2"))
978 			{
979 				if ( (m_value0 == 0x0000) || (m_value0 == 0x0001) || (m_value0 == 0x0002) || (m_value0 == 0x0003) )
980 				{
981 					m_valueresponse = 0x00166178; // right for puzzli2 , wrong for puzzli2s, probably calculated from the writes then?
982 				}
983 				else if ( m_value0 == 0x0004 ) // 2 player demo
984 				{
985 					m_valueresponse = 0x00166e72;
986 				}
987 				else
988 				{
989 					puzzli2_printf("unk case x67\n");
990 					m_valueresponse = 0x00400000; // wrong
991 				}
992 			}
993 			else // puzzli2 super
994 			{
995 				if ((m_value0 == 0x0000) || (m_value0 == 0x0001) || (m_value0 == 0x0002) ||  (m_value0 == 0x0003))
996 				{
997 					m_valueresponse = 0x18cf4a;
998 				}
999 				else if ( m_value0 == 0x0004 ) // 2 player demo
1000 				{
1001 					m_valueresponse = 0x0018dc44;
1002 				}
1003 				else
1004 				{
1005 					puzzli2_printf("unk case x67\n");
1006 					m_valueresponse = 0x00600000; // wrong
1007 				}
1008 			}
1009 		break;
1010 
1011 		default:
1012 			puzzli2_printf("%08x: %02x %04x\n",pc, m_ddp3lastcommand, m_value0);
1013 
1014 			m_valueresponse = 0x74 << 16;
1015 		break;
1016 	}
1017 }
1018 
py2k2_sprite_offset(u16 base,u16 pos)1019 static u32 py2k2_sprite_offset(u16 base, u16 pos)
1020 {
1021 	u16 ret = 0;
1022 	u16 offset = (base * 16) + (pos & 0xf);
1023 
1024 	switch (base & ~0x3f)
1025 	{
1026 		case 0x000: ret = bitswap<16>(offset ^ 0x0030, 15, 14, 13, 12, 11, 10, 0, 2, 3, 9, 5, 4, 8, 7, 6, 1); break;
1027 		case 0x040: ret = bitswap<16>(offset ^ 0x03c0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 1, 2, 0, 5, 3, 4); break;
1028 		case 0x080: ret = bitswap<16>(offset ^ 0x0000, 15, 14, 13, 12, 11, 10, 0, 3, 4, 6, 8, 7, 5, 9, 2, 1); break;
1029 		case 0x0c0: ret = bitswap<16>(offset ^ 0x0001, 15, 14, 13, 12, 11, 10, 6, 5, 4, 3, 2, 1, 9, 8, 7, 0); break;
1030 		case 0x100: ret = bitswap<16>(offset ^ 0x0030, 15, 14, 13, 12, 11, 10, 0, 2, 3, 9, 5, 4, 8, 7, 6, 1); break;
1031 		case 0x140: ret = bitswap<16>(offset ^ 0x01c0, 15, 14, 13, 12, 11, 10, 2, 8, 7, 6, 4, 3, 5, 9, 0, 1); break;
1032 		case 0x180: ret = bitswap<16>(offset ^ 0x0141, 15, 14, 13, 12, 11, 10, 4, 8, 2, 6, 1, 7, 9, 5, 3, 0); break;
1033 		case 0x1c0: ret = bitswap<16>(offset ^ 0x0090, 15, 14, 13, 12, 11, 10, 5, 3, 7, 2, 1, 4, 0, 9, 8, 6); break;
1034 		case 0x200: ret = bitswap<16>(offset ^ 0x02a1, 15, 14, 13, 12, 11, 10, 9, 1, 7, 8, 5, 6, 2, 4, 3, 0); break;
1035 		case 0x240: ret = bitswap<16>(offset ^ 0x0000, 15, 14, 13, 12, 11, 10, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4); break;
1036 		case 0x280: ret = bitswap<16>(offset ^ 0x02a1, 15, 14, 13, 12, 11, 10, 9, 1, 7, 8, 5, 6, 2, 4, 3, 0); break;
1037 		case 0x2c0: ret = bitswap<16>(offset ^ 0x0000, 15, 14, 13, 12, 11, 10, 0, 3, 4, 6, 8, 7, 5, 9, 2, 1); break;
1038 		case 0x300: ret = bitswap<16>(offset ^ 0x03c0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 1, 2, 0, 5, 3, 4); break;
1039 		case 0x340: ret = bitswap<16>(offset ^ 0x0030, 15, 14, 13, 12, 11, 10, 0, 2, 3, 9, 5, 4, 8, 7, 6, 1); break;
1040 		case 0x380: ret = bitswap<16>(offset ^ 0x0001, 15, 14, 13, 12, 11, 10, 6, 5, 4, 3, 2, 1, 9, 8, 7, 0); break;
1041 		case 0x3c0: ret = bitswap<16>(offset ^ 0x0090, 15, 14, 13, 12, 11, 10, 5, 3, 7, 2, 1, 4, 0, 9, 8, 6); break;
1042 		case 0x400: ret = bitswap<16>(offset ^ 0x02a1, 15, 14, 13, 12, 11, 10, 9, 1, 7, 8, 5, 6, 2, 4, 3, 0); break;
1043 		case 0x440: ret = bitswap<16>(offset ^ 0x03c0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 1, 2, 0, 5, 3, 4); break;
1044 		case 0x480: ret = bitswap<16>(offset ^ 0x0141, 15, 14, 13, 12, 11, 10, 4, 8, 2, 6, 1, 7, 9, 5, 3, 0); break;
1045 		case 0x4c0: ret = bitswap<16>(offset ^ 0x01c0, 15, 14, 13, 12, 11, 10, 2, 8, 7, 6, 4, 3, 5, 9, 0, 1); break;
1046 		case 0x500: ret = bitswap<16>(offset ^ 0x0141, 15, 14, 13, 12, 11, 10, 4, 8, 2, 6, 1, 7, 9, 5, 3, 0); break;
1047 		case 0x540: ret = bitswap<16>(offset ^ 0x0030, 15, 14, 13, 12, 11, 10, 0, 2, 3, 9, 5, 4, 8, 7, 6, 1); break;
1048 		case 0x580: ret = bitswap<16>(offset ^ 0x03c0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 1, 2, 0, 5, 3, 4); break;
1049 		case 0x5c0: ret = bitswap<16>(offset ^ 0x0090, 15, 14, 13, 12, 11, 10, 5, 3, 7, 2, 1, 4, 0, 9, 8, 6); break;
1050 		case 0x600: ret = bitswap<16>(offset ^ 0x0000, 15, 14, 13, 12, 11, 10, 0, 3, 4, 6, 8, 7, 5, 9, 2, 1); break;
1051 		case 0x640: ret = bitswap<16>(offset ^ 0x0000, 15, 14, 13, 12, 11, 10, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5); break;
1052 	}
1053 
1054 	if (offset >= 0xce80/2 && offset <= 0xceff/2) ret -= 0x0100;
1055 	if (offset >= 0xcf00/2 && offset <= 0xcf7f/2) ret += 0x0100;
1056 
1057 	return ret;
1058 }
1059 
1060 /* preliminary */
command_handler_py2k2(int pc)1061 void pgm_arm_type1_state::command_handler_py2k2(int pc)
1062 {
1063 	switch (m_ddp3lastcommand)
1064 	{
1065 		case 0x30:
1066 			m_valueresponse = py2k2_sprite_offset(m_py2k2_sprite_base, m_py2k2_sprite_pos++);
1067 		break;
1068 		case 0x32:
1069 			m_py2k2_sprite_base = m_value0;
1070 			m_py2k2_sprite_pos = 0;
1071 			m_valueresponse = py2k2_sprite_offset(m_py2k2_sprite_base, m_py2k2_sprite_pos++);
1072 		break;
1073 		case 0xba:
1074 			m_valueresponse = m_py2k2_prev_base;
1075 			m_py2k2_prev_base = m_value0;
1076 		break;
1077 		case 0x99: // reset?
1078 			m_py2k2_prev_base = m_value0;
1079 			m_simregion = m_region->read();
1080 			m_valuekey = 0x100;
1081 			m_valueresponse = 0x00880000 | m_simregion<<8;
1082 		break;
1083 		case 0xc0:
1084 			puzzli2_printf("%06x command %02x | %04x\n", pc, m_ddp3lastcommand, m_value0);
1085 			m_valueresponse = 0x880000;
1086 			break;
1087 		case 0xc3:
1088 			m_valueresponse = 0x904000 + ((m_extra_ram[0xc0] + (m_value0 * 0x40)) * 4);
1089 		break;
1090 		case 0xd0:
1091 			m_valueresponse = 0xa01000 + (m_value0 * 0x20);
1092 		break;
1093 		case 0xdc:
1094 			m_valueresponse = 0xa00800 + (m_value0 * 0x40);
1095 		break;
1096 		case 0xe0:
1097 			m_valueresponse = 0xa00000 + ((m_value0 & 0x1f) * 0x40);
1098 		break;
1099 		case 0xcb: // Background layer 'x' select (pgm3in1, same as kov)
1100 			m_valueresponse = 0x880000;
1101 		break;
1102 		case 0xcc: // Background layer offset (pgm3in1, same as kov)
1103 		{
1104 			int y = m_value0;
1105 			if (y & 0x400) y = -(0x400 - (y & 0x3ff));
1106 			m_valueresponse = 0x900000 + ((m_extra_ram[0xcb] + (y * 0x40)) * 4);
1107 		}
1108 		break;
1109 		case 0x33:
1110 		case 0x34:
1111 		case 0x35:
1112 		case 0x37:
1113 		case 0x38:
1114 		default:
1115 			puzzli2_printf("%06x command %02x | %04x\n", pc, m_ddp3lastcommand, m_value0);
1116 			m_valueresponse = 0x880000;
1117 			break;
1118 	}
1119 }
1120 
1121 /* preliminary */
1122 
1123 
1124 static const int pstar_ba[0x1E]={
1125 	0x02,0x00,0x00,0x01,0x00,0x03,0x00,0x00, //0
1126 	0x02,0x00,0x06,0x00,0x22,0x04,0x00,0x03, //8
1127 	0x00,0x00,0x06,0x00,0x20,0x07,0x00,0x03, //10
1128 	0x00,0x21,0x01,0x00,0x00,0x63
1129 };
1130 
1131 static const int pstar_b0[0x10]={
1132 	0x09,0x0A,0x0B,0x00,0x01,0x02,0x03,0x04,
1133 	0x05,0x06,0x07,0x08,0x00,0x00,0x00,0x00
1134 };
1135 
1136 static const int pstar_ae[0x10]={
1137 	0x5D,0x86,0x8C ,0x8B,0xE0,0x8B,0x62,0xAF,
1138 	0xB6,0xAF,0x10A,0xAF,0x00,0x00,0x00,0x00
1139 };
1140 
1141 static const int pstar_a0[0x10]={
1142 	0x02,0x03,0x04,0x05,0x06,0x01,0x0A,0x0B,
1143 	0x0C,0x0D,0x0E,0x09,0x00,0x00,0x00,0x00,
1144 };
1145 
1146 static const int pstar_9d[0x10]={
1147 	0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1148 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1149 };
1150 
1151 static const int pstar_90[0x10]={
1152 	0x0C,0x10,0x0E,0x0C,0x00,0x00,0x00,0x00,
1153 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
1154 };
1155 static const int pstar_8c[0x23]={
1156 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1157 	0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,
1158 	0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,
1159 	0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,
1160 	0x03,0x03,0x03
1161 };
1162 
1163 static const int pstar_80[0x1a3]={
1164 	0x03,0x03,0x04,0x04,0x04,0x04,0x05,0x05,
1165 	0x05,0x05,0x06,0x06,0x03,0x03,0x04,0x04,
1166 	0x05,0x05,0x05,0x05,0x06,0x06,0x07,0x07,
1167 	0x03,0x03,0x04,0x04,0x05,0x05,0x05,0x05,
1168 	0x06,0x06,0x07,0x07,0x06,0x06,0x06,0x06,
1169 	0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,
1170 	0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,
1171 	0x07,0x07,0x08,0x08,0x05,0x05,0x05,0x05,
1172 	0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,
1173 	0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,
1174 	0x09,0x09,0x09,0x09,0x07,0x07,0x07,0x07,
1175 	0x07,0x08,0x08,0x08,0x08,0x09,0x09,0x09,
1176 	0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,
1177 	0x08,0x08,0x09,0x09,0x05,0x05,0x06,0x06,
1178 	0x06,0x07,0x07,0x08,0x08,0x08,0x08,0x09,
1179 	0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,
1180 	0x08,0x09,0x09,0x09,0x06,0x06,0x07,0x03,
1181 	0x07,0x06,0x07,0x07,0x08,0x07,0x05,0x04,
1182 	0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,
1183 	0x06,0x06,0x06,0x06,0x03,0x04,0x04,0x04,
1184 	0x04,0x05,0x05,0x06,0x06,0x06,0x06,0x07,
1185 	0x04,0x04,0x05,0x05,0x06,0x06,0x06,0x06,
1186 	0x06,0x07,0x07,0x08,0x05,0x05,0x06,0x07,
1187 	0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
1188 	0x05,0x05,0x05,0x07,0x07,0x07,0x07,0x07,
1189 	0x07,0x08,0x08,0x08,0x08,0x08,0x09,0x09,
1190 	0x09,0x09,0x03,0x04,0x04,0x05,0x05,0x05,
1191 	0x06,0x06,0x07,0x07,0x07,0x07,0x08,0x08,
1192 	0x08,0x09,0x09,0x09,0x03,0x04,0x05,0x05,
1193 	0x04,0x03,0x04,0x04,0x04,0x05,0x05,0x04,
1194 	0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
1195 	0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,
1196 	0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03,
1197 	0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,
1198 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1199 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1200 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1201 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1202 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1203 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1204 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1205 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1206 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1207 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1208 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1209 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1210 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1211 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1212 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1213 	0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
1214 	0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
1215 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1216 	0x00,0x00,0x00
1217 };
1218 
command_handler_pstars(int pc)1219 void pgm_arm_type1_state::command_handler_pstars(int pc)
1220 {
1221 	switch (m_ddp3lastcommand)
1222 	{
1223 		case 0x99:
1224 			m_simregion = m_region->read();
1225 			m_valuekey = 0x100;
1226 			m_valueresponse = 0x00880000 | m_simregion<<8;
1227 			break;
1228 
1229 		case 0xe0:
1230 			m_valueresponse = 0xa00000 + (m_value0 << 6);
1231 			break;
1232 
1233 		case 0xdc:
1234 			m_valueresponse = 0xa00800 + (m_value0 << 6);
1235 			break;
1236 
1237 		case 0xd0:
1238 			m_valueresponse = 0xa01000 + (m_value0 << 5);
1239 			break;
1240 
1241 		case 0xb1:
1242 			m_pstar_b1_value = m_value0;
1243 			m_valueresponse = 0x890000;
1244 			break;
1245 
1246 		case 0xbf:
1247 			m_valueresponse = m_pstar_b1_value * m_value0;
1248 			break;
1249 
1250 		case 0xc1: //TODO:TIMER  0,1,2,FIX TO 0 should be OK?
1251 			m_valueresponse = 0;
1252 			break;
1253 
1254 		case 0xce: //TODO:TIMER  0,1,2
1255 			m_pstar_ce_value = m_value0;
1256 			m_valueresponse=0x890000;
1257 			break;
1258 
1259 		case 0xcf: //TODO:TIMER  0,1,2
1260 			m_extra_ram[m_pstar_ce_value] = m_value0;
1261 			m_valueresponse = 0x890000;
1262 			break;
1263 
1264 		case 0xe7:
1265 			m_pstar_e7_value = (m_value0 >> 12) & 0xf;
1266 			m_slots[m_pstar_e7_value] &= 0xffff;
1267 			m_slots[m_pstar_e7_value] |= (m_value0 & 0xff) << 16;
1268 			m_valueresponse = 0x890000;
1269 			break;
1270 
1271 		case 0xe5:
1272 			m_slots[m_pstar_e7_value] &= 0xff0000;
1273 			m_slots[m_pstar_e7_value] |= m_value0;
1274 			m_valueresponse = 0x890000;
1275 			break;
1276 
1277 		case 0xf8: //@73C
1278 			m_valueresponse = m_slots[m_value0 & 0xf] & 0xffffff;
1279 			break;
1280 
1281 		case 0xba:
1282 			m_valueresponse = pstar_ba[m_value0];
1283 			break;
1284 
1285 		case 0xb0:
1286 			m_valueresponse = pstar_b0[m_value0];
1287 			break;
1288 
1289 		case 0xae:
1290 			m_valueresponse = pstar_ae[m_value0];
1291 			break;
1292 
1293 		case 0xa0:
1294 			m_valueresponse = pstar_a0[m_value0];
1295 			break;
1296 
1297 		case 0x9d:
1298 			m_valueresponse = pstar_9d[m_value0];
1299 			break;
1300 
1301 		case 0x90:
1302 			m_valueresponse = pstar_90[m_value0];
1303 			break;
1304 
1305 		case 0x8c:
1306 			m_valueresponse = pstar_8c[m_value0];
1307 			break;
1308 
1309 		case 0x80:
1310 			m_valueresponse = pstar_80[m_value0];
1311 			break;
1312 
1313 		default:
1314 			m_valueresponse = 0x890000;
1315 			logerror("PSTARS PC(%06x) UNKNOWN %4X %4X\n", pc, m_value1, m_value0);
1316 	}
1317 }
1318 
1319 /* Old KOV and bootlegs sim ... really these should be read out... */
1320 
1321 static const u8 kov_BATABLE[0x40] = {
1322 	0x00,0x29,0x2c,0x35,0x3a,0x41,0x4a,0x4e,0x57,0x5e,0x77,0x79,0x7a,0x7b,0x7c,0x7d,
1323 	0x7e,0x7f,0x80,0x81,0x82,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x90,
1324 	0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9e,0xa3,0xd4,0xa9,0xaf,0xb5,0xbb,0xc1
1325 };
1326 
1327 static const u8 kov_B0TABLE[16] = { 2, 0, 1, 4, 3 }; // Maps char portraits to tables
1328 
1329 
command_handler_kov(int pc)1330 void pgm_arm_type1_state::command_handler_kov(int pc)
1331 {
1332 	switch (m_ddp3lastcommand)
1333 	{
1334 		case 0x67: // unknown or status check?
1335 		case 0x8e:
1336 		case 0xa3:
1337 		case 0x33: // kovsgqyz (a3)
1338 		case 0x3a: // kovplus
1339 		case 0xc5: // kovplus
1340 			m_valueresponse = 0x880000;
1341 		break;
1342 
1343 		case 0x99: // Reset
1344 			m_simregion = m_region->read();
1345 			m_valueresponse = 0x880000 | m_simregion<<8;
1346 			m_valuekey = 0x100;
1347 		break;
1348 
1349 		case 0x9d: // Sprite palette offset
1350 			m_valueresponse = 0xa00000 + ((m_value0 & 0x1f) * 0x40);
1351 		break;
1352 
1353 		case 0xb0: // Read from data table
1354 			m_valueresponse = kov_B0TABLE[m_value0 & 0x0f];
1355 		break;
1356 
1357 		case 0xb4: // Copy slot 'a' to slot 'b'
1358 		case 0xb7: // kovsgqyz (b4)
1359 		{
1360 			m_valueresponse = 0x880000;
1361 
1362 			if (m_value0 == 0x0102) m_value0 = 0x0100; // why?
1363 
1364 			m_slots[(m_value0 >> 8) & 0x0f] = m_slots[(m_value0 >> 0) & 0x0f];
1365 		}
1366 		break;
1367 
1368 		case 0xba: // Read from data table
1369 			m_valueresponse = kov_BATABLE[m_value0 & 0x3f];
1370 		break;
1371 
1372 		case 0xc0: // Text layer 'x' select
1373 			m_valueresponse = 0x880000;
1374 			m_kov_c0_value = m_value0;
1375 		break;
1376 
1377 		case 0xc3: // Text layer offset
1378 			m_valueresponse = 0x904000 + ((m_kov_c0_value + (m_value0 * 0x40)) * 4);
1379 		break;
1380 
1381 		case 0xcb: // Background layer 'x' select
1382 			m_valueresponse = 0x880000;
1383 			m_kov_cb_value = m_value0;
1384 		break;
1385 
1386 		case 0xcc: // Background layer offset
1387 		{
1388 			int y = m_value0;
1389 			if (y & 0x400) y = -(0x400 - (y & 0x3ff));
1390 			m_valueresponse = 0x900000 + ((m_kov_cb_value + (y * 0x40)) * 4);
1391 		}
1392 		break;
1393 
1394 		case 0xd0: // Text palette offset
1395 		case 0xcd: // kovsgqyz (d0)
1396 			m_valueresponse = 0xa01000 + (m_value0 * 0x20);
1397 		break;
1398 
1399 		case 0xd6: // Copy slot to slot 0
1400 			m_valueresponse = 0x880000;
1401 			m_slots[0] = m_slots[m_value0 & 0x0f];
1402 		break;
1403 
1404 		case 0xdc: // Background palette offset
1405 		case 0x11: // kovsgqyz (dc)
1406 			m_valueresponse = 0xa00800 + (m_value0 * 0x40);
1407 		break;
1408 
1409 		case 0xe0: // Sprite palette offset
1410 		case 0x9e: // kovsgqyz (e0)
1411 			m_valueresponse = 0xa00000 + ((m_value0 & 0x1f) * 0x40);
1412 		break;
1413 
1414 		case 0xe5: // Write slot (low)
1415 		{
1416 			m_valueresponse = 0x880000;
1417 
1418 			s32 sel = (m_curslots >> 12) & 0x0f;
1419 			m_slots[sel] = (m_slots[sel] & 0x00ff0000) | ((m_value0 & 0xffff) <<  0);
1420 		}
1421 		break;
1422 
1423 		case 0xe7: // Write slot (and slot select) (high)
1424 		{
1425 			m_valueresponse = 0x880000;
1426 			m_curslots = m_value0;
1427 
1428 			s32 sel = (m_curslots >> 12) & 0x0f;
1429 			m_slots[sel] = (m_slots[sel] & 0x0000ffff) | ((m_value0 & 0x00ff) << 16);
1430 		}
1431 		break;
1432 
1433 		case 0xf0: // Some sort of status read?
1434 			m_valueresponse = 0x00c000;
1435 		break;
1436 
1437 		case 0xf8: // Read slot
1438 		case 0xab: // kovsgqyz (f8)
1439 			m_valueresponse = m_slots[m_value0 & 0x0f] & 0x00ffffff;
1440 		break;
1441 
1442 		case 0xfc: // Adjust damage level to char experience level
1443 			m_valueresponse = (m_value0 * m_kov_fe_value) >> 6;
1444 		break;
1445 
1446 		case 0xfe: // Damage level adjust
1447 			m_valueresponse = 0x880000;
1448 			m_kov_fe_value = m_value0;
1449 		break;
1450 
1451 		default:
1452 			m_valueresponse = 0x880000;
1453 //                  logerror("Unknown ASIC27 command: %2.2x data: %4.4x\n", (data ^ m_valuekey) & 0xff, m_value0);
1454 		break;
1455 	}
1456 }
1457 
1458 
1459 /* Oriental Legend Super Plus ARM simulation */
1460 
1461 static const int oldsplus_80[0x5]={
1462 	0xbb8,0x1770,0x2328,0x2ee0,0xf4240
1463 };
1464 
1465 static const int oldsplus_fc[0x20]={
1466 	0x00,0x00,0x0a,0x3a,0x4e,0x2e,0x03,0x40,
1467 	0x33,0x43,0x26,0x2c,0x00,0x00,0x00,0x00,
1468 	0x00,0x00,0x44,0x4d,0xb,0x27,0x3d,0x0f,
1469 	0x37,0x2b,0x02,0x2f,0x15,0x45,0x0e,0x30
1470 };
1471 
1472 static const int oldsplus_a0[0x20]={
1473 	0x000,0x023,0x046,0x069,0x08c,0x0af,0x0d2,0x0f5,
1474 	0x118,0x13b,0x15e,0x181,0x1a4,0x1c7,0x1ea,0x20d,
1475 	0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,
1476 	0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,
1477 };
1478 
1479 static const int oldsplus_90[0x7]={
1480 	0x50,0xa0,0xc8,0xf0,0x190,0x1f4,0x258
1481 };
1482 
1483 static const int oldsplus_5e[0x20]={
1484 	0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03,
1485 	0x02,0x02,0x02,0x01,0x01,0x01,0x01,0x01,
1486 	0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,
1487 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
1488 };
1489 
1490 static const int oldsplus_b0[0xe0]={
1491 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1492 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1493 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1494 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1495 
1496 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1497 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1498 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1499 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1500 
1501 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1502 	0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,
1503 	0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
1504 	0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,
1505 
1506 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1507 	0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
1508 	0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,
1509 	0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
1510 
1511 	0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,
1512 	0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
1513 	0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,
1514 	0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,
1515 
1516 	0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1517 	0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1518 	0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
1519 	0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
1520 
1521 	0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,
1522 	0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,
1523 	0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,
1524 	0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f
1525 };
1526 
1527 static const int oldsplus_ae[0xe0]={
1528 	0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
1529 	0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
1530 	0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
1531 	0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
1532 
1533 	0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
1534 	0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
1535 	0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
1536 	0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
1537 
1538 	0x1E,0x1F,0x20,0x21,0x22,0x23,0x23,0x23,
1539 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1540 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1541 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1542 
1543 	0x1F,0x20,0x21,0x22,0x23,0x23,0x23,0x23,
1544 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1545 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1546 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1547 
1548 	0x20,0x21,0x22,0x23,0x23,0x23,0x23,0x23,
1549 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1550 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1551 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1552 
1553 	0x21,0x22,0x23,0x23,0x23,0x23,0x23,0x23,
1554 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1555 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1556 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1557 
1558 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1559 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1560 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
1561 	0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23
1562 };
1563 
1564 static const int oldsplus_ba[0x4]={
1565 	0x3138,0x2328,0x1C20,0x1518
1566 };
1567 
1568 static const int oldsplus_9d[0x111]={
1569 	0x0000,0x0064,0x00c8,0x012c,0x0190,0x01f4,0x0258,0x02bc,
1570 	0x02f8,0x0334,0x0370,0x03ac,0x03e8,0x0424,0x0460,0x049c,
1571 	0x04d8,0x0514,0x0550,0x058c,0x05c8,0x0604,0x0640,0x06bc,
1572 	0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
1573 	0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x0000,
1574 	0x0064,0x00c8,0x012c,0x0190,0x01f4,0x0258,0x02bc,0x0302,
1575 	0x0348,0x038e,0x03d4,0x041a,0x0460,0x04a6,0x04ec,0x0532,
1576 	0x0578,0x05be,0x0604,0x064a,0x0690,0x06d6,0x06bc,0x06bc,
1577 	0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
1578 	0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x0000,0x0064,
1579 	0x00c8,0x012c,0x0190,0x01f4,0x0258,0x02bc,0x0316,0x0370,
1580 	0x03ca,0x0424,0x047e,0x04d8,0x0532,0x058c,0x05e6,0x0640,
1581 	0x069a,0x06f4,0x074e,0x07a8,0x0802,0x06bc,0x06bc,0x06bc,
1582 	0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
1583 	0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x0000,0x0064,0x00c8,
1584 	0x012c,0x0190,0x01f4,0x0258,0x02bc,0x032a,0x0398,0x0406,
1585 	0x0474,0x04e2,0x0550,0x05be,0x062c,0x069a,0x0708,0x0776,
1586 	0x07e4,0x0852,0x08c0,0x092e,0x06bc,0x06bc,0x06bc,0x06bc,
1587 	0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
1588 	0x06bc,0x06bc,0x06bc,0x06bc,0x0000,0x0064,0x00c8,0x012c,
1589 	0x0190,0x01f4,0x0258,0x02bc,0x0348,0x03d4,0x0460,0x04ec,
1590 	0x0578,0x0604,0x0690,0x071c,0x07a8,0x0834,0x08c0,0x094c,
1591 	0x09d8,0x0a64,0x0af0,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
1592 	0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
1593 	0x06bc,0x06bc,0x06bc,0x0000,0x0064,0x00c8,0x012c,0x0190,
1594 	0x01f4,0x0258,0x02bc,0x0384,0x044c,0x0514,0x05dc,0x06a4,
1595 	0x076c,0x0834,0x08fc,0x09c4,0x0a8c,0x0b54,0x0c1c,0x0ce4,
1596 	0x0dac,0x0e74,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
1597 	0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
1598 	0x06bc,0x06bc,0x0000,0x0064,0x00c8,0x012c,0x0190,0x01f4,
1599 	0x0258,0x02bc,0x030c,0x035c,0x03ac,0x03fc,0x044c,0x049c,
1600 	0x04ec,0x053c,0x058c,0x05dc,0x062c,0x067c,0x06cc,0x071c,
1601 	0x076c,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
1602 	0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
1603 	0x06bc
1604 };
1605 
1606 static const int oldsplus_8c[0x20]={
1607 	0x0032,0x0032,0x0064,0x0096,0x0096,0x00fa,0x012c,0x015e,
1608 	0x0032,0x0064,0x0096,0x00c8,0x00c8,0x012c,0x015e,0x0190,
1609 	0x0064,0x0096,0x00c8,0x00fa,0x00fa,0x015e,0x0190,0x01c2,
1610 	0x0096,0x00c8,0x00fa,0x012c,0x012c,0x0190,0x01c2,0x01f4
1611 };
1612 
1613 
command_handler_oldsplus(int pc)1614 void pgm_arm_type1_state::command_handler_oldsplus(int pc)
1615 {
1616 	switch (m_ddp3lastcommand)
1617 	{
1618 		case 0x88:
1619 			m_simregion = m_region->read();
1620 			m_valuekey = 0x100;
1621 			m_valueresponse = 0x00990000 | m_simregion<<8;
1622 
1623 			break;
1624 
1625 		case 0xd0:
1626 			m_valueresponse = 0xa01000 + (m_value0 << 5);
1627 			break;
1628 
1629 		case 0xc0:
1630 			m_valueresponse = 0xa00000 + (m_value0 << 6);
1631 			break;
1632 
1633 		case 0xc3:
1634 			m_valueresponse = 0xa00800 + (m_value0 << 6);
1635 			break;
1636 
1637 		case 0x36:
1638 			m_extra_ram[0x36] = m_value0;
1639 			m_valueresponse = 0x990000;
1640 			break;
1641 
1642 		case 0x33:
1643 			m_extra_ram[0x33] = m_value0;
1644 			m_valueresponse = 0x990000;
1645 			break;
1646 
1647 		case 0x35:
1648 			m_extra_ram[0x36] += m_value0;
1649 			m_valueresponse = 0x990000;
1650 			break;
1651 
1652 		case 0x37:
1653 			m_extra_ram[0x33] += m_value0;
1654 			m_valueresponse = 0x990000;
1655 			break;
1656 
1657 		case 0x34:
1658 			m_valueresponse = m_extra_ram[0x36];
1659 			break;
1660 
1661 		case 0x38:
1662 			m_valueresponse = m_extra_ram[0x33];
1663 			break;
1664 
1665 		case 0x80:
1666 			m_valueresponse = oldsplus_80[m_value0];
1667 			break;
1668 
1669 		case 0xe7:
1670 			m_extra_ram[0xe7] = m_value0;
1671 			m_valueresponse = 0x990000;
1672 			break;
1673 
1674 		case 0xe5:
1675 			switch (m_extra_ram[0xe7])
1676 			{
1677 				case 0xb000:
1678 					m_slots[0xb] = m_value0;
1679 					m_slots[0xc] = 0;
1680 					break;
1681 
1682 				case 0xc000:
1683 					m_slots[0xc] = m_value0;
1684 					break;
1685 
1686 				case 0xd000:
1687 					m_slots[0xd] = m_value0;
1688 					break;
1689 
1690 				case 0xf000:
1691 					m_slots[0xf] = m_value0;
1692 					break;
1693 			}
1694 			m_valueresponse = 0x990000;
1695 			break;
1696 
1697 		case 0xf8:
1698 			m_valueresponse = m_slots[m_value0];
1699 			break;
1700 
1701 		case 0xfc:
1702 			m_valueresponse = oldsplus_fc[m_value0];
1703 			break;
1704 
1705 		case 0xc5:
1706 			m_slots[0xd] --;
1707 			m_valueresponse = 0x990000;
1708 			break;
1709 
1710 		case 0xd6:
1711 			m_slots[0xb] ++;
1712 			m_valueresponse = 0x990000;
1713 			break;
1714 
1715 		case 0x3a:
1716 			m_slots[0xf] = 0;
1717 			m_valueresponse = 0x990000;
1718 			break;
1719 
1720 		case 0xf0:
1721 			m_extra_ram[0xf0] = m_value0;
1722 			m_valueresponse = 0x990000;
1723 			break;
1724 
1725 		case 0xed:
1726 			m_valueresponse = m_value0 << 0x6;
1727 			m_valueresponse += m_extra_ram[0xf0];
1728 			m_valueresponse = m_valueresponse << 0x2;
1729 			m_valueresponse += 0x900000;
1730 			break;
1731 
1732 		case 0xe0:
1733 			m_extra_ram[0xe0] = m_value0;
1734 			m_valueresponse = 0x990000;
1735 			break;
1736 
1737 		case 0xdc:
1738 			m_valueresponse = m_value0 << 0x6;
1739 			m_valueresponse += m_extra_ram[0xe0];
1740 			m_valueresponse = m_valueresponse << 0x2;
1741 			m_valueresponse += 0x904000;
1742 			break;
1743 
1744 		case 0xcb:
1745 			m_valueresponse =  0xc000;
1746 			break;
1747 
1748 		case 0xa0:
1749 			m_valueresponse = oldsplus_a0[m_value0];
1750 			break;
1751 
1752 		case 0xba:
1753 			m_valueresponse = oldsplus_ba[m_value0];
1754 			break;
1755 
1756 		case 0x5e:
1757 			m_valueresponse = oldsplus_5e[m_value0];
1758 			break;
1759 
1760 		case 0xb0:
1761 			m_valueresponse = oldsplus_b0[m_value0];
1762 			break;
1763 
1764 		case 0xae:
1765 			m_valueresponse = oldsplus_ae[m_value0];
1766 			break;
1767 
1768 		case 0x9d:
1769 			m_valueresponse = oldsplus_9d[m_value0];
1770 			break;
1771 
1772 		case 0x90:
1773 			m_valueresponse = oldsplus_90[m_value0];
1774 			break;
1775 
1776 		case 0x8c:
1777 			m_valueresponse = oldsplus_8c[m_value0];
1778 			break;
1779 
1780 		default:
1781 			m_valueresponse = 0x990000;
1782 			printf("%06X: oldsplus_UNKNOWN W CMD %X  VAL %X\n", pc,m_value1,m_value0);
1783 			break;
1784 	}
1785 }
1786 
arm7_type1_sim_w(offs_t offset,u16 data)1787 void pgm_arm_type1_state::arm7_type1_sim_w(offs_t offset, u16 data)
1788 {
1789 	const int pc = m_maincpu->pc();
1790 
1791 	if (offset == 0)
1792 	{
1793 		m_value0 = data;
1794 		return;
1795 	}
1796 	else if (offset == 1)
1797 	{
1798 		u16 realkey;
1799 		if ((data >> 8) == 0xff)
1800 			m_valuekey = 0xff00;
1801 		realkey = m_valuekey >> 8;
1802 		realkey |= m_valuekey;
1803 		{
1804 			m_valuekey += 0x0100;
1805 			m_valuekey &= 0xff00;
1806 			if (m_valuekey == 0xff00)
1807 				m_valuekey =  0x0100;
1808 		}
1809 		data ^= realkey;
1810 		m_value1 = data;
1811 		m_value0 ^= realkey;
1812 
1813 		m_ddp3lastcommand = m_value1 & 0xff;
1814 
1815 		(this->*arm_sim_handler)(pc);
1816 	}
1817 	else if (offset == 2)
1818 	{
1819 	}
1820 }
1821 
arm7_type1_sim_protram_r(offs_t offset)1822 u16 pgm_arm_type1_state::arm7_type1_sim_protram_r(offs_t offset)
1823 {
1824 	if (offset == 4)
1825 		return m_simregion;
1826 
1827 	return 0x0000;
1828 }
1829 
pstars_arm7_type1_sim_protram_r(offs_t offset)1830 u16 pgm_arm_type1_state::pstars_arm7_type1_sim_protram_r(offs_t offset)
1831 {
1832 	if (offset == 4)        //region
1833 		return m_region->read();
1834 	else if (offset >= 0x10)  //timer
1835 	{
1836 		const u16 val = m_extra_ram[offset - 0x10];
1837 		if (!machine().side_effects_disabled())
1838 		{
1839 			logerror("PSTARS ACCESS COUNTER %6X\n", val);
1840 			m_extra_ram[offset - 0x10]--;
1841 		}
1842 		return val;
1843 	}
1844 	return 0x0000;
1845 }
1846 
1847 
init_ddp3()1848 void pgm_arm_type1_state::init_ddp3()
1849 {
1850 	pgm_basic_init(false);
1851 	pgm_py2k2_decrypt(machine()); // yes, it's the same as photo y2k2
1852 	arm_sim_handler = &pgm_arm_type1_state::command_handler_ddp3;
1853 	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x500000, 0x500005, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_r)), write16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_w)));
1854 }
1855 
init_ket()1856 void pgm_arm_type1_state::init_ket()
1857 {
1858 	pgm_basic_init(false);
1859 	pgm_ket_decrypt(machine());
1860 	arm_sim_handler = &pgm_arm_type1_state::command_handler_ddp3;
1861 	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x400000, 0x400005, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_r)), write16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_w)));
1862 }
1863 
init_espgal()1864 void pgm_arm_type1_state::init_espgal()
1865 {
1866 	pgm_basic_init(false);
1867 	pgm_espgal_decrypt(machine());
1868 	arm_sim_handler = &pgm_arm_type1_state::command_handler_ddp3;
1869 	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x400000, 0x400005, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_r)), write16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_w)));
1870 }
1871 
1872 
count_bits(u16 value)1873 int count_bits(u16 value)
1874 {
1875 	int count = 0;
1876 	for (int i = 0; i < 16; i++)
1877 	{
1878 		int bit = (value >> i) & 1;
1879 
1880 		if (bit) count++;
1881 	}
1882 
1883 	return count;
1884 }
1885 
get_position_of_bit(u16 value,int bit_wanted)1886 int get_position_of_bit(u16 value, int bit_wanted)
1887 {
1888 	int count = 0;
1889 	for (int i = 0; i < 16; i++)
1890 	{
1891 		int bit = (value >> i) & 1;
1892 
1893 		if (bit) count++;
1894 
1895 		if (count==(bit_wanted+1))
1896 			return i;
1897 	}
1898 
1899 	return -1;
1900 }
1901 
puzzli2_take_leveldata_value(u8 datvalue)1902 int pgm_arm_type1_state::puzzli2_take_leveldata_value(u8 datvalue)
1903 {
1904 	if (stage == -1)
1905 	{
1906 		entries_left = 0;
1907 		currentcolumn = 0;
1908 		currentrow = 0;
1909 		num_entries = 0;
1910 		full_entry = 0;
1911 		prev_tablloc = 0;
1912 		numbercolumns = 0;
1913 		depth = 0;
1914 		m_row_bitmask = 0;
1915 
1916 		puzzli2_printf("%02x <- table offset\n", datvalue);
1917 		tableoffs = datvalue;
1918 		tableoffs2 = 0;
1919 		stage = 0;
1920 	}
1921 	else
1922 	{
1923 		u8 rawvalue = datvalue;
1924 		u8 tableloc = (tableoffs+tableoffs2) & 0xff;
1925 		rawvalue ^= puzzli2_level_decode[tableloc];
1926 
1927 		tableoffs2++;
1928 		tableoffs2 &= 0xf;
1929 
1930 		if (stage == 0)
1931 		{
1932 			stage = 1;
1933 
1934 			// this seems to be the first thing returned back when reading the level structure always seems to be 0x8 or 0x7, makes sense, levels would be too difficult otherwise ;-) (actually puzzli2 seems to have one specifying 5 unless it's a decrypt table error?!)
1935 			depth = (rawvalue & 0xf0);
1936 			numbercolumns = (rawvalue & 0x0f);
1937 			numbercolumns++;
1938 
1939 			puzzli2_printf("%02x <- Sizes (level depth %01x) (number of columns %01x)", rawvalue, depth>>4, numbercolumns);
1940 
1941 			if ((depth != 0x80) && (depth != 0x70) && (depth != 0x50))
1942 				fatalerror("depth isn't 0x5, 0x7 or 0x8");
1943 
1944 			// it seems to use this to specify the number of columns, ie how many data structures follow, so that the ARM knows when to send back the 'finished' flag.
1945 			// it also gets returned at the end with said flag
1946 			if ((numbercolumns != 0x6) && (numbercolumns != 0x7) && (numbercolumns != 0x8))
1947 				fatalerror("number of columns specified isn't 6,7, or 8");
1948 
1949 			puzzli2_printf("\n");
1950 
1951 		}
1952 		else if (stage == 1)
1953 		{
1954 			puzzli2_printf("%02x <- Number of Entries for this Column (and upper mask) (column is %d) (xor table location is %02x) ", rawvalue, currentcolumn, tableloc);
1955 			stage = 2;
1956 			entries_left = (rawvalue >> 4);
1957 			m_row_bitmask = (rawvalue & 0x0f)<<8;
1958 
1959 			full_entry = rawvalue;
1960 			prev_tablloc = tableloc;
1961 
1962 			num_entries = entries_left;
1963 
1964 			if (num_entries == 0x00)
1965 			{
1966 				puzzli2_printf("0 entries for this column?"); // seems a valid condition based on the data
1967 			}
1968 
1969 			puzzli2_printf("\n");
1970 		}
1971 		else if (stage == 2)
1972 		{
1973 			puzzli2_printf("%02x <- Mask value equal to number of entries (xor table location is %02x)", rawvalue, tableloc);
1974 			stage = 3;
1975 
1976 			m_row_bitmask |= rawvalue;
1977 
1978 			int num_mask_bits = count_bits(m_row_bitmask);
1979 
1980 			if (num_mask_bits != num_entries)
1981 				puzzli2_printf(" error - number of mask bits != number of entries - ");
1982 
1983 			//
1984 			if (entries_left == 0)
1985 			{
1986 				// for 0 entries skip back to state 1 instead of 3, because there is nothing following
1987 				stage = 1;
1988 				currentcolumn++;
1989 				currentrow = 0;
1990 				m_row_bitmask = 0;
1991 
1992 				coverage[tableloc] = 1;
1993 				if (rawvalue != 0)
1994 				{
1995 					puzzli2_printf(" invalid mask after 00 length?");
1996 					// attempt to correct the table
1997 					//new_puzzli2_level_decode[tableloc] = new_puzzli2_level_decode[tableloc] ^ rawvalue;
1998 
1999 				}
2000 				coverage[prev_tablloc] = 1;
2001 				if (full_entry != 0)
2002 				{
2003 					puzzli2_printf(" previous value wasn't 0x00");
2004 				}
2005 
2006 				if (currentcolumn == numbercolumns)
2007 				{
2008 					return 1;
2009 				}
2010 
2011 			}
2012 			else
2013 			{
2014 				if (num_entries> 0xa)
2015 				{
2016 					puzzli2_printf(" more than 10 entries?");
2017 				}
2018 				else
2019 				{
2020 					// this isn't a strict rule
2021 					// the mask is used so they can specify spaces between elements too without storing the 00 bytes
2022 					coverage[tableloc] = 1;
2023 
2024 					int desired_mask = 0;
2025 
2026 					if (num_entries == 0x00) desired_mask = 0x00;
2027 					if (num_entries == 0x01) desired_mask = 0x01;
2028 					if (num_entries == 0x02) desired_mask = 0x03;
2029 					if (num_entries == 0x03) desired_mask = 0x07;
2030 					if (num_entries == 0x04) desired_mask = 0x0f;
2031 					if (num_entries == 0x05) desired_mask = 0x1f;
2032 					if (num_entries == 0x06) desired_mask = 0x3f;
2033 					if (num_entries == 0x07) desired_mask = 0x7f;
2034 					if (num_entries == 0x08) desired_mask = 0xff;
2035 					if (num_entries == 0x09) desired_mask = 0xff;
2036 					if (num_entries == 0x0a) desired_mask = 0xff;
2037 
2038 					if (rawvalue != desired_mask)
2039 					{
2040 						puzzli2_printf(" possible wrong mask?");
2041 					}
2042 
2043 				}
2044 
2045 			}
2046 
2047 			puzzli2_printf("\n");
2048 
2049 		}
2050 		else if (stage == 3)
2051 		{
2052 			u16 object_value;
2053 
2054 			// return values
2055 			// 0x0100 = normal fish
2056 			// 0x0120 = fish in bubble
2057 			// 0x0140 = fish in egg
2058 			// 0x0160 = buggy fish in egg (displayed as normal fish)
2059 			// 0x0180 = fish on hook
2060 			// 0x01a0 = fish on hook (uncatchable)
2061 			// 0x01c0 - fish on hook (uncatchable)
2062 			// 0x01e0 - fish on hook (uncatchable)
2063 
2064 			// fish values
2065 			// 100 101 102 103 104 105 106 107 108 normal
2066 			// 110 - renders as a flashing fish you can't catch? glitches game?
2067 			// 111 - repeat of other fish type you can't catch...
2068 
2069 			if (rawvalue <= 0x10) // regular fish
2070 			{
2071 				int fishtype = rawvalue;
2072 				puzzli2_printf("%02x <- fish type %d", rawvalue, fishtype);
2073 				object_value = 0x0100 + fishtype;
2074 				// 0x110 is a flashy fish? might be glitchy and need a special number..
2075 			}
2076 			else if (rawvalue <= 0x21) // fish in bubbles
2077 			{
2078 				int fishtype = rawvalue - 0x11;
2079 				puzzli2_printf("%02x <- fish in bubble %d", rawvalue, fishtype);
2080 				object_value = 0x0120 + fishtype;
2081 				// 0x130 is a flashy fish? might be glitchy and need a special number..
2082 			}
2083 			else if (rawvalue <= 0x32) // fish in eggs
2084 			{
2085 				int fishtype = rawvalue - 0x22;
2086 				puzzli2_printf("%02x <- fish in egg %d", rawvalue, fishtype);
2087 				object_value = 0x0140 + fishtype;
2088 				// 0x150 is a flashy fish? might be glitchy and need a special number..
2089 
2090 			}
2091 			else if (rawvalue <= 0x43) // fish on hook cases, seem to be base 0x180
2092 			{
2093 				int fishtype = rawvalue - 0x33;
2094 				puzzli2_printf("%02x <- fish on hook %d", rawvalue, fishtype);
2095 				object_value = 0x0180 + fishtype;
2096 				// 0x190 is a flashy fish? might be glitchy and need a special number..
2097 
2098 			}
2099 			////////////////////// special objects follow
2100 			else if (rawvalue == 0xd0) {object_value = 0x0200; puzzli2_printf("%02x <- generic bubbles", rawvalue);}
2101 
2102 			else if (rawvalue == 0xe0) {object_value = 0x8000; puzzli2_printf("%02x <- solid middle", rawvalue);}
2103 			else if (rawvalue == 0xe1) {object_value = 0x8020; puzzli2_printf("%02x <- solid top slant down", rawvalue);} // solid slant top down
2104 			else if (rawvalue == 0xe2) {object_value = 0x8040; puzzli2_printf("%02x <- solid top slant up", rawvalue);} // solid slant top up
2105 			else if (rawvalue == 0xe3) {object_value = 0x8060; puzzli2_printf("%02x <- solid bottom slant up", rawvalue);}
2106 			else if (rawvalue == 0xe4) {object_value = 0x8080; puzzli2_printf("%02x <- solid bottom slant down", rawvalue);} // sold slant bottom up
2107 
2108 			else                     {object_value = 0xffff; puzzli2_printf("%02x <- unknown object", rawvalue);}
2109 
2110 			puzzli2_printf("  (xor table location is %02x)\n",tableloc);
2111 
2112 			if (object_value == 0xffff)
2113 			{
2114 				object_value = 0x110;
2115 				popmessage("unknown object type %02x\n", rawvalue);
2116 			}
2117 
2118 			const int realrow = get_position_of_bit(m_row_bitmask, currentrow);
2119 
2120 			if (realrow != -1)
2121 				level_structure[currentcolumn][realrow] = object_value;
2122 
2123 			currentrow++;
2124 
2125 			entries_left--;
2126 			if (entries_left == 0)
2127 			{
2128 				stage = 1;
2129 				currentcolumn++;
2130 				currentrow = 0;
2131 				m_row_bitmask = 0;
2132 
2133 				if (currentcolumn == numbercolumns)
2134 				{
2135 					return 1;
2136 				}
2137 
2138 			}
2139 		}
2140 
2141 	}
2142 
2143 	return 0;
2144 }
2145 
2146 
2147 
init_puzzli2()2148 void pgm_arm_type1_state::init_puzzli2()
2149 {
2150 	pgm_basic_init();
2151 
2152 	pgm_puzzli2_decrypt(machine());
2153 	arm_sim_handler = &pgm_arm_type1_state::command_handler_puzzli2;
2154 	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x500000, 0x500005, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_r)), write16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_w)));
2155 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0000, 0x4f003f, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_protram_r)));
2156 	m_irq4_disabled = 1; // // doesn't like this irq?? - seems to be RTC related
2157 
2158 	hackcount = 0;
2159 	hackcount2 = 0;
2160 	hack_47_value = 0;
2161 	hack_31_table_offset = 0;
2162 
2163 //#define PUZZLI2_LEVEL_STRUCTURE_LOG
2164 #ifdef PUZZLI2_LEVEL_STRUCTURE_LOG
2165 	u8 *src2 = (u8 *) (machine().root_device().memregion("maincpu")->base());
2166 
2167 	int offset;
2168 	int limit;
2169 	for (int i = 0; i < 256; i++)
2170 		coverage[i] = 0;
2171 
2172 	if (!strcmp(machine().system().name,"puzzli2"))
2173 	{
2174 		offset = 0x17ab66;
2175 			limit = 476;
2176 	}
2177 	else
2178 	{
2179 			offset = 0x16c3ca;
2180 			limit = 500;
2181 	}
2182 
2183 
2184 
2185 
2186 	for (int i = 0; i < limit; i++)
2187 	{
2188 		u32 val1 = (src2[offset+1]<<24) | (src2[offset+0] << 16) | (src2[offset+3]<<8) | (src2[offset+2] << 0);
2189 		offset += 4;
2190 		u32 val2 = (src2[offset+1]<<24) | (src2[offset+0] << 16) | (src2[offset+3]<<8) | (src2[offset+2] << 0);
2191 
2192 
2193 		printf("(%d) data range %08x %08x\n", i, val1, val2);
2194 
2195 		int x = 0;
2196 
2197 		stage = -1;
2198 
2199 		for (x = val1; x < val2; x++)
2200 		{
2201 			int end = puzzli2_take_leveldata_value(src2[x^1]);
2202 
2203 			if (end)
2204 			{
2205 				printf("--- ended at %08x (val 2 was %08x)\n",x ,val2);
2206 
2207 				if ( (val2-x) > 2 )
2208 				{
2209 					fatalerror("ended even earlier than padding byte\n");
2210 				}
2211 				else if ( (val2-x) == 2)
2212 				{
2213 					printf("ended with padding byte\n");
2214 				}
2215 				else if ( (val2-x) == 1)
2216 				{
2217 					printf("ended normally\n");
2218 				}
2219 				else // can't happen
2220 				{
2221 					fatalerror("ended after marker?!\n");
2222 				}
2223 
2224 				x = val2;
2225 			}
2226 
2227 		}
2228 
2229 		printf("total number of valid columns was %02x\n", currentcolumn);
2230 
2231 		if ((currentcolumn != 0x6) && (currentcolumn != 0x7) && (currentcolumn != 0x8))  // 5 is suspicious
2232 			fatalerror("invalid number of columns?\n");
2233 
2234 		if (numbercolumns != currentcolumn)
2235 			fatalerror("mismatch in number of columns vs specified amount\n");
2236 
2237 		printf("\n");
2238 
2239 
2240 	}
2241 
2242 
2243 #endif
2244 
2245 #if 0
2246 	if (!strcmp(machine().system().name,"puzzli2"))
2247 	{
2248 	u8 *src3 = (u8 *) (machine().root_device().memregion("maincpu")->base());
2249 	printf("how to play data pointer %02x %02x %02x %02x\n", src3[0x17b28e ^1], src3[0x17b28f ^1], src3[0x17b290 ^1], src3[0x17b291 ^1]);
2250 	src3[0x17b28e ^1] = 0x00;
2251 	src3[0x17b28f ^1] = 0x11;
2252 	src3[0x17b290 ^1] = 0x42;
2253 	src3[0x17b291 ^1] = 0x40;
2254 	}
2255 
2256 
2257 	pgm_puzzli2_decrypt(machine());
2258 
2259 	{
2260 		u8 *ROM = (u8*)memregion("maincpu")->base();
2261 
2262 		FILE *fp;
2263 		char filename[256];
2264 		sprintf(filename,"trojan_%s", machine().system().name);
2265 		fp=fopen(filename, "w+b");
2266 		if (fp)
2267 		{
2268 			fwrite(ROM+0x100000, 0x200000, 1, fp);
2269 			fclose(fp);
2270 		}
2271 	}
2272 
2273 
2274 	pgm_puzzli2_decrypt(machine());
2275 #endif
2276 }
2277 
init_py2k2()2278 void pgm_arm_type1_state::init_py2k2()
2279 {
2280 	pgm_basic_init();
2281 	pgm_py2k2_decrypt(machine());
2282 	arm_sim_handler = &pgm_arm_type1_state::command_handler_py2k2;
2283 	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x500000, 0x500005, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_r)), write16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_w)));
2284 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0000, 0x4f003f, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_protram_r)));
2285 
2286 	m_py2k2_sprite_pos = 0;
2287 	m_py2k2_sprite_base = 0;
2288 	m_py2k2_prev_base = 0;
2289 	save_item(NAME(m_py2k2_sprite_pos));
2290 	save_item(NAME(m_py2k2_sprite_base));
2291 	save_item(NAME(m_py2k2_prev_base));
2292 }
2293 
init_pgm3in1()2294 void pgm_arm_type1_state::init_pgm3in1()
2295 {
2296 	pgm_basic_init();
2297 	pgm_decrypt_pgm3in1(machine());
2298 	arm_sim_handler = &pgm_arm_type1_state::command_handler_py2k2;
2299 	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x500000, 0x500005,read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_r)), write16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_w)));
2300 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0000, 0x4f003f, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_protram_r)));
2301 	m_irq4_disabled = 1; // // doesn't like this irq??
2302 }
2303 
init_pstar()2304 void pgm_arm_type1_state::init_pstar()
2305 {
2306 	pgm_basic_init();
2307 	pgm_pstar_decrypt(machine());
2308 	arm7_type1_latch_init();
2309 
2310 	m_pstar_e7_value = 0;
2311 	m_pstar_b1_value = 0;
2312 	m_pstar_ce_value = 0;
2313 	m_extra_ram[0] = 0;
2314 	m_extra_ram[1] = 0;
2315 	m_extra_ram[2] = 0;
2316 	memset(m_slots, 0, 16 * sizeof(u32));
2317 
2318 	arm_sim_handler = &pgm_arm_type1_state::command_handler_pstars;
2319 	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x500000, 0x500005, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_r)), write16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_w)));
2320 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0000, 0x4f003f, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::pstars_arm7_type1_sim_protram_r)));
2321 
2322 	save_item(NAME(m_pstar_e7_value));
2323 	save_item(NAME(m_pstar_b1_value));
2324 	save_item(NAME(m_pstar_ce_value));
2325 	save_item(NAME(m_extra_ram));
2326 }
2327 
init_kov()2328 void pgm_arm_type1_state::init_kov()
2329 {
2330 	pgm_basic_init();
2331 	pgm_kov_decrypt(machine());
2332 	arm7_type1_latch_init();
2333 	m_curslots = 0;
2334 	m_kov_c0_value = 0;
2335 	m_kov_cb_value = 0;
2336 	m_kov_fe_value = 0;
2337 	arm_sim_handler = &pgm_arm_type1_state::command_handler_kov;
2338 	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x500000, 0x500005, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_r)), write16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_w)));
2339 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0000, 0x4f003f, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_protram_r)));
2340 }
2341 
init_kovboot()2342 void pgm_arm_type1_state::init_kovboot()
2343 {
2344 	pgm_basic_init();
2345 //  pgm_kov_decrypt(machine());
2346 	arm7_type1_latch_init();
2347 	m_curslots = 0;
2348 	m_kov_c0_value = 0;
2349 	m_kov_cb_value = 0;
2350 	m_kov_fe_value = 0;
2351 	arm_sim_handler = &pgm_arm_type1_state::command_handler_kov;
2352 	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x500000, 0x500005, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_r)), write16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_w)));
2353 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0000, 0x4f003f, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_protram_r)));
2354 
2355 }
2356 
init_oldsplus()2357 void pgm_arm_type1_state::init_oldsplus()
2358 {
2359 	pgm_basic_init();
2360 	pgm_oldsplus_decrypt(machine());
2361 	arm7_type1_latch_init();
2362 	memset(m_extra_ram, 0, 0x100 * sizeof(u16));
2363 	memset(m_slots, 0, 0x100 * sizeof(u32));
2364 	arm_sim_handler = &pgm_arm_type1_state::command_handler_oldsplus;
2365 	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x500000, 0x500005, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_r)), write16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_w)));
2366 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x4f0000, 0x4f003f, read16sm_delegate(*this, FUNC(pgm_arm_type1_state::arm7_type1_sim_protram_r)));
2367 	save_item(NAME(m_extra_ram));
2368 }
2369 
2370 INPUT_PORTS_START( photoy2k )
2371 	PORT_INCLUDE ( pgm )
2372 
2373 	PORT_START("RegionHack")    /* Region - supplied by protection device */
2374 	PORT_CONFNAME( 0x00ff, 0x00ff, DEF_STR( Region ) )
2375 	PORT_CONFSETTING(      0x0000, DEF_STR( Taiwan ) )
2376 	PORT_CONFSETTING(      0x0001, DEF_STR( China ) )
2377 	PORT_CONFSETTING(      0x0002, "Japan (Alta license)" )
2378 	PORT_CONFSETTING(      0x0003, DEF_STR( World ) )
2379 	PORT_CONFSETTING(      0x0004, DEF_STR( Korea ) )
2380 	PORT_CONFSETTING(      0x0005, DEF_STR( Hong_Kong ) )
2381 	PORT_CONFSETTING(      0x00ff, "Untouched" ) // don't hack the region
2382 INPUT_PORTS_END
2383 
2384 INPUT_PORTS_START( photoy2kj )
2385 	PORT_INCLUDE ( pgm )
2386 
2387 	PORT_START("RegionHack")    /* Region - supplied by protection device */
2388 	PORT_CONFNAME( 0x00ff, 0x0002, DEF_STR( Region ) )
2389 	PORT_CONFSETTING(      0x0000, DEF_STR( Taiwan ) )
2390 	PORT_CONFSETTING(      0x0001, DEF_STR( China ) )
2391 	PORT_CONFSETTING(      0x0002, "Japan (Alta license)" )
2392 	PORT_CONFSETTING(      0x0003, DEF_STR( World ) )
2393 	PORT_CONFSETTING(      0x0004, DEF_STR( Korea ) )
2394 	PORT_CONFSETTING(      0x0005, DEF_STR( Hong_Kong ) )
2395 	PORT_CONFSETTING(      0x00ff, "Untouched" ) // don't hack the region
2396 INPUT_PORTS_END
2397 
2398 INPUT_PORTS_START( kovsh )
2399 	PORT_INCLUDE ( pgm )
2400 
2401 	PORT_START("RegionHack")    /* Region - supplied by protection device */
2402 	PORT_CONFNAME( 0x00ff, 0x00ff, DEF_STR( Region ) )
2403 	PORT_CONFSETTING(      0x0000, DEF_STR( China ) )
2404 	PORT_CONFSETTING(      0x0001, DEF_STR( Taiwan ) )
2405 	PORT_CONFSETTING(      0x0002, "Japan (Alta license)" )
2406 	PORT_CONFSETTING(      0x0003, DEF_STR( Korea ) )
2407 	PORT_CONFSETTING(      0x0004, DEF_STR( Hong_Kong ) )
2408 	PORT_CONFSETTING(      0x0005, DEF_STR( World ) )
2409 	PORT_CONFSETTING(      0x00ff, "Untouched" ) // don't hack the region
2410 INPUT_PORTS_END
2411 
2412 
2413 
2414 INPUT_PORTS_START( sango )
2415 	PORT_INCLUDE ( pgm )
2416 
2417 	PORT_MODIFY("Region")   /* Region - supplied by protection device */
2418 	PORT_CONFNAME( 0x000f, 0x0005, DEF_STR( Region ) )
2419 	PORT_CONFSETTING(      0x0000, DEF_STR( China ) )
2420 	PORT_CONFSETTING(      0x0001, DEF_STR( Taiwan ) )
2421 	PORT_CONFSETTING(      0x0002, "Japan (Alta license)" )
2422 	PORT_CONFSETTING(      0x0003, DEF_STR( Korea ) )
2423 	PORT_CONFSETTING(      0x0004, DEF_STR( Hong_Kong ) )
2424 	PORT_CONFSETTING(      0x0005, DEF_STR( World ) )
2425 INPUT_PORTS_END
2426 
2427 INPUT_PORTS_START( sango_ch )
2428 	PORT_INCLUDE ( pgm )
2429 
2430 	PORT_MODIFY("Region")   /* Region - supplied by protection device */
2431 	PORT_CONFNAME( 0x000f, 0x0000, DEF_STR( Region ) )
2432 	PORT_CONFSETTING(      0x0000, DEF_STR( China ) )
2433 	PORT_CONFSETTING(      0x0001, DEF_STR( Taiwan ) )
2434 	PORT_CONFSETTING(      0x0002, "Japan (Alta license)" )
2435 	PORT_CONFSETTING(      0x0003, DEF_STR( Korea ) )
2436 	PORT_CONFSETTING(      0x0004, DEF_STR( Hong_Kong ) )
2437 	PORT_CONFSETTING(      0x0005, DEF_STR( World ) )
2438 INPUT_PORTS_END
2439 
2440 
2441 INPUT_PORTS_START( oldsplus )
2442 	PORT_INCLUDE ( pgm )
2443 
2444 	PORT_MODIFY("Region")   /* Region - supplied by protection device */
2445 	PORT_CONFNAME( 0x000f, 0x0001, DEF_STR( Region ) )
2446 	PORT_CONFSETTING(      0x0001, DEF_STR( China ) )
2447 	PORT_CONFSETTING(      0x0002, DEF_STR( Japan ) )
2448 	PORT_CONFSETTING(      0x0003, DEF_STR( Korea ) )
2449 	PORT_CONFSETTING(      0x0004, DEF_STR( Hong_Kong ) )
2450 	PORT_CONFSETTING(      0x0005, DEF_STR( World ) )
2451 	PORT_CONFSETTING(      0x0006, DEF_STR( Taiwan ) )
2452 INPUT_PORTS_END
2453 
2454 INPUT_PORTS_START( pstar )
2455 	PORT_INCLUDE ( pgm )
2456 
2457 	PORT_MODIFY("Region")   /* Region - supplied by protection device */
2458 	PORT_CONFNAME( 0x000f, 0x0005, DEF_STR( Region ) )
2459 	PORT_CONFSETTING(      0x0000, DEF_STR( China ) )
2460 	PORT_CONFSETTING(      0x0001, DEF_STR( Taiwan ) )
2461 	PORT_CONFSETTING(      0x0002, "Japan (Alta license)" )
2462 	PORT_CONFSETTING(      0x0003, DEF_STR( Korea ) )
2463 	PORT_CONFSETTING(      0x0004, DEF_STR( Hong_Kong ) )
2464 	PORT_CONFSETTING(      0x0005, DEF_STR( World ) )
2465 INPUT_PORTS_END
2466 
2467 INPUT_PORTS_START( py2k2 )
2468 	PORT_INCLUDE ( pgm )
2469 
2470 	PORT_MODIFY("Region")   /* Region - supplied by protection device */
2471 	PORT_CONFNAME( 0x000f, 0x0003, DEF_STR( Region ) )
2472 	PORT_CONFSETTING(      0x0000, DEF_STR( Taiwan ) )
2473 	PORT_CONFSETTING(      0x0001, DEF_STR( China ) )
2474 	PORT_CONFSETTING(      0x0002, "Japan (Alta license)" )
2475 	PORT_CONFSETTING(      0x0003, DEF_STR( World ) )
2476 	PORT_CONFSETTING(      0x0004, DEF_STR( Korea ) )
2477 	PORT_CONFSETTING(      0x0005, DEF_STR( Hong_Kong ) )
2478 	PORT_CONFSETTING(      0x0006, "Singapore, Malaysia" )
2479 INPUT_PORTS_END
2480 
2481 INPUT_PORTS_START( pgm3in1 )
2482 	PORT_INCLUDE ( pgm )
2483 
2484 	PORT_MODIFY("Region")   /* Region - supplied by protection device */
2485 	PORT_CONFNAME( 0x000f, 0x0003, DEF_STR( Region ) )
2486 	PORT_CONFSETTING(      0x0000, DEF_STR( China ) )
2487 	PORT_CONFSETTING(      0x0001, DEF_STR( Taiwan ) )
2488 	PORT_CONFSETTING(      0x0002, DEF_STR( Hong_Kong ) )
2489 	PORT_CONFSETTING(      0x0003, DEF_STR( World ) )
2490 INPUT_PORTS_END
2491 
2492 
2493 INPUT_PORTS_START( puzzli2 )
2494 	PORT_INCLUDE ( pgm )
2495 
2496 	PORT_MODIFY("Region")   /* Region - supplied by protection device */
2497 	PORT_CONFNAME( 0x000f, 0x0005, DEF_STR( Region ) )
2498 	PORT_CONFSETTING(      0x0000, DEF_STR( Taiwan ) )
2499 	PORT_CONFSETTING(      0x0001, DEF_STR( China ) )
2500 	PORT_CONFSETTING(      0x0002, "Japan (Alta license)" )
2501 	PORT_CONFSETTING(      0x0003, DEF_STR( Korea ) )
2502 	PORT_CONFSETTING(      0x0004, DEF_STR( Hong_Kong ) )
2503 	PORT_CONFSETTING(      0x0005, DEF_STR( World ) )
2504 INPUT_PORTS_END
2505 
2506 
2507 // CAVE PCB has some input differs; no 3P/4P inputs
2508 INPUT_PORTS_START( espgal )
2509 	PORT_INCLUDE ( pgm )
2510 
2511 	PORT_MODIFY("P3P4")
2512 	PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNKNOWN )  // unused
2513 
2514 	PORT_MODIFY("Service")
2515 	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_SERVICE2 ) PORT_NAME("Test")
2516 	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Service")
2517 	PORT_BIT( 0x0ccc, IP_ACTIVE_LOW, IPT_UNKNOWN )  // unused
2518 
2519 	PORT_MODIFY("DSW")
2520 	PORT_SERVICE_DIPLOC( 0x0001, IP_ACTIVE_LOW, "SW1:1" )
2521 	PORT_DIPUNKNOWN_DIPLOC( 0x0002, IP_ACTIVE_LOW, "SW1:2" )
2522 	PORT_DIPUNKNOWN_DIPLOC( 0x0004, IP_ACTIVE_LOW, "SW1:3" )
2523 	PORT_DIPUNKNOWN_DIPLOC( 0x0008, IP_ACTIVE_LOW, "SW1:4" )
2524 	PORT_DIPUNKNOWN_DIPLOC( 0x0010, IP_ACTIVE_LOW, "SW1:5" )
2525 	PORT_DIPUNKNOWN_DIPLOC( 0x0020, IP_ACTIVE_LOW, "SW1:6" )
2526 	PORT_DIPUNKNOWN_DIPLOC( 0x0040, IP_ACTIVE_LOW, "SW1:7" )
2527 	PORT_DIPUNKNOWN_DIPLOC( 0x0080, IP_ACTIVE_LOW, "SW1:8" )
2528 INPUT_PORTS_END
2529 
2530 
2531 INPUT_PORTS_START( ddp3 ) // No button 4
2532 	PORT_INCLUDE ( espgal )
2533 
2534 	PORT_MODIFY("Service")
2535 	PORT_BIT( 0x0300, IP_ACTIVE_LOW, IPT_UNKNOWN )  // unused
2536 INPUT_PORTS_END
2537