1 // license:BSD-3-Clause
2 // copyright-holders:S. Smith,David Haywood,Fabio Priuli
3 
4 
5 #include "emu.h"
6 #include "prot_kof98.h"
7 
8 DEFINE_DEVICE_TYPE(NG_KOF98_PROT, kof98_prot_device, "ng_kof98_prot", "Neo Geo KoF 98 Protection")
9 
10 
kof98_prot_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)11 kof98_prot_device::kof98_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
12 	device_t(mconfig, NG_KOF98_PROT, tag, owner, clock),
13 	m_prot_state(0)
14 {
15 }
16 
17 
device_start()18 void kof98_prot_device::device_start()
19 {
20 	save_item(NAME(m_prot_state));
21 }
22 
device_reset()23 void kof98_prot_device::device_reset()
24 {
25 }
26 
27 
28 /* Kof98 uses an early encryption, quite different from the others */
decrypt_68k(uint8_t * cpurom,uint32_t cpurom_size)29 void kof98_prot_device::decrypt_68k(uint8_t* cpurom, uint32_t cpurom_size)
30 {
31 	uint8_t *src = cpurom;
32 	std::vector<uint8_t> dst(0x200000);
33 	int i, j, k;
34 	static const uint32_t sec[]={ 0x000000, 0x100000, 0x000004, 0x100004, 0x10000a, 0x00000a, 0x10000e, 0x00000e };
35 	static const uint32_t pos[]={ 0x000, 0x004, 0x00a, 0x00e };
36 
37 	memcpy(&dst[0], src, 0x200000);
38 	for (i = 0x800; i < 0x100000; i += 0x200)
39 	{
40 		for (j = 0; j < 0x100; j += 0x10)
41 		{
42 			for (k = 0; k < 16; k += 2)
43 			{
44 				memcpy(&src[i+j+k],       &dst[i+j+sec[k/2]+0x100], 2);
45 				memcpy(&src[i+j+k+0x100], &dst[i+j+sec[k/2]],       2);
46 			}
47 			if (i >= 0x080000 && i < 0x0c0000)
48 			{
49 				for (k = 0; k < 4; k++)
50 				{
51 					memcpy(&src[i+j+pos[k]],       &dst[i+j+pos[k]],       2);
52 					memcpy(&src[i+j+pos[k]+0x100], &dst[i+j+pos[k]+0x100], 2);
53 				}
54 			}
55 			else if (i >= 0x0c0000)
56 			{
57 				for (k = 0; k < 4; k++)
58 				{
59 					memcpy(&src[i+j+pos[k]],       &dst[i+j+pos[k]+0x100], 2);
60 					memcpy(&src[i+j+pos[k]+0x100], &dst[i+j+pos[k]],       2);
61 				}
62 			}
63 		}
64 		memcpy(&src[i+0x000000], &dst[i+0x000000], 2);
65 		memcpy(&src[i+0x000002], &dst[i+0x100000], 2);
66 		memcpy(&src[i+0x000100], &dst[i+0x000100], 2);
67 		memcpy(&src[i+0x000102], &dst[i+0x100100], 2);
68 	}
69 	memmove(&src[0x100000], &src[0x200000], 0x400000);
70 
71 	uint16_t* mem16 = (uint16_t*)cpurom;
72 	m_default_rom[0] = mem16[0x100/2];
73 	m_default_rom[1] = mem16[0x102/2];
74 }
75 
76 
77 /************************ King of Fighters 98*******************
78   The encrypted set has a rom overlay feature, checked at
79   various points in the game.
80   Boards used: NEO-MVS PROGSF1 (1998.6.17) / NEO-MVS PROGSF1E (1998.6.18)
81   The boards have an ALTERA chip (EPM7128SQC100-15) which is tied to 242-P1
82 ***************************************************************/
83 
protection_r(offs_t offset)84 uint16_t kof98_prot_device::protection_r(offs_t offset)
85 {
86 	if (m_prot_state == 1)
87 	{
88 		if (!offset)
89 			return 0x00c2;
90 		else
91 			return 0x00fd;
92 	}
93 	if (m_prot_state == 2)
94 	{
95 		if (!offset)
96 			return 0x4e45;
97 		else
98 			return 0x4f2d;
99 	}
100 
101 	if (!offset)
102 		return m_default_rom[0];
103 	else
104 		return m_default_rom[1];
105 }
106 
107 
108 /* when 0x20aaaa contains 0x0090 (word) then 0x100 (normally the neogeo header) should return 0x00c200fd worked out using real hw */
protection_w(uint16_t data)109 void kof98_prot_device::protection_w(uint16_t data)
110 {
111 	/* info from razoola */
112 	switch (data)
113 	{
114 	case 0x0090:
115 		logerror ("%s kof98 - protection 0x0090x\n", machine().describe_context());
116 		m_prot_state = 1;
117 		break;
118 
119 	case 0x00f0:
120 		logerror ("%s kof98 - protection 0x00f0x\n", machine().describe_context());
121 		m_prot_state = 2;
122 		break;
123 
124 	default: // 00aa is written, but not needed?
125 		logerror ("%s kof98 - unknown protection write %04x\n", machine().describe_context(), data);
126 		break;
127 	}
128 }
129