1 /***************************************************************************
2
3 machine.c
4
5 Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
6 I/O ports)
7
8 The Glob protection description:
9
10 The Glob is designed to run on modified Pacman hardware. It contains
11 two graphics ROMs at 5E and 5F, but contains code ROMs on a daughterboard
12 similar in concept to Ms. Pacman. However, these code ROMs are decrypted
13 through additional circuitry. The daughterboard was encased in epoxy.
14
15 Here's a description of the protection as best as I can give it.
16
17 1) The decrypted D0 bit fed to the CPU is simply an inversion of the
18 D5 bit from the code ROMs.
19 2) The decrypted D1 bit fed to the CPU is simply an inversion of the
20 D2 bit from the code ROMs.
21 3) The other 6 data bits are decrypted by a 10H8 PAL. The PAL also
22 takes as input a 4-bit counter. The counter is incremented and
23 decremented as follows:
24 - the Z-80 command IN($xx) where xx is an odd number decrements the
25 counter; an even number increments the counter.
26 Ex: IN($64) would increment the counter, IN($6B) would decrement
27 the counter.
28 4) The PAL output also contains the two ROM enable lines used to enable
29 the two encrypted code ROMs. As long as the system is working
30 correctly, these ROMs will always be enabled.
31
32 As it so happens, only four counter values are ever used, which is
33 fortunate because the PAL only contains signals to enable the ROMs for
34 those four counter values. The valid counter values are $8, $9, $A, and
35 $B. The counter's intial value is $A, which is set by jumpers on the
36 daughterboard. Following is a description of the resulting decryptions
37 for these four counter states.
38
39 COUNTER ENCRYPTED DECRYPTED
40 VALUE VALUE
41
42 DDDDDDDD DDDDDDDD
43 76543210 76543210
44
45 Counter = 8: abcdefgh EAhBDgFC
46 Counter = 9: abcdefgh FAgeDBFC
47 Counter = A: abcdefgh EHDBagFC
48 Counter = B: abcdefgh GHDEaBFC
49
50 In the above diagram, capital letters represent inverted bits. Notice
51 that bits D2 and D5 are the same independent of counter state, this is
52 because these bits are not decrypted by the PAL.
53
54
55 In the code below, all four of these decryption patterns are used to
56 decrypt the entire code ROMs before execution. This is done for speed,
57 since we can then just bankswitch between the decrypted code sets on
58 each IN($xx) command, as opposed to dynamically decrypting every byte.
59
60 - Mike Balfour (mab22@po.cwru.edu)
61
62 ***************************************************************************/
63
64 #include "driver.h"
65
66 void pacman_init_machine(void);
67
68 static int counter=0;
69
70
theglob_decrypt_rom_8(void)71 static void theglob_decrypt_rom_8(void)
72 {
73 int oldbyte,inverted_oldbyte,newbyte;
74 int mem;
75 unsigned char *RAM;
76
77 RAM = memory_region(REGION_CPU1);
78
79
80 for (mem=0;mem<0x4000;mem++)
81 {
82 oldbyte = RAM[mem];
83 inverted_oldbyte = ~oldbyte;
84
85 /* Note: D2 is inverted and connected to D1, D5 is inverted and
86 connected to D0. The other six data bits are converted by a
87 PAL10H8 driven by the counter. */
88 newbyte = 0;
89
90 /* Direct inversion */
91 newbyte = (inverted_oldbyte & 0x04) >> 1;
92 newbyte |= (inverted_oldbyte & 0x20) >> 5;
93 /* PAL */
94 newbyte |= (oldbyte & 0x01) << 5;
95 newbyte |= (oldbyte & 0x02) << 1;
96 newbyte |= (inverted_oldbyte & 0x08) << 4;
97 newbyte |= (inverted_oldbyte & 0x10) >> 1;
98 newbyte |= (inverted_oldbyte & 0x40) >> 2;
99 newbyte |= (inverted_oldbyte & 0x80) >> 1;
100
101 RAM[mem + 0x10000] = newbyte;
102 }
103
104 return;
105 }
106
107
theglob_decrypt_rom_9(void)108 static void theglob_decrypt_rom_9(void)
109 {
110 int oldbyte,inverted_oldbyte,newbyte;
111 int mem;
112 unsigned char *RAM;
113
114 RAM = memory_region(REGION_CPU1);
115
116 for (mem=0;mem<0x4000;mem++)
117 {
118 oldbyte = RAM[mem];
119 inverted_oldbyte = ~oldbyte;
120
121 /* Note: D2 is inverted and connected to D1, D5 is inverted and
122 connected to D0. The other six data bits are converted by a
123 PAL10H8 driven by the counter. */
124 newbyte = 0;
125
126 /* Direct inversion */
127 newbyte = (inverted_oldbyte & 0x04) >> 1;
128 newbyte |= (inverted_oldbyte & 0x20) >> 5;
129 /* PAL */
130 newbyte |= (oldbyte & 0x01) << 5;
131 newbyte |= (inverted_oldbyte & 0x02) << 6;
132 newbyte |= (oldbyte & 0x08) << 1;
133 newbyte |= (inverted_oldbyte & 0x10) >> 1;
134 newbyte |= (inverted_oldbyte & 0x40) >> 4;
135 newbyte |= (inverted_oldbyte & 0x80) >> 1;
136
137 RAM[mem + 0x14000] = newbyte;
138 }
139
140 return;
141 }
142
theglob_decrypt_rom_A(void)143 static void theglob_decrypt_rom_A(void)
144 {
145 int oldbyte,inverted_oldbyte,newbyte;
146 int mem;
147 unsigned char *RAM;
148
149 RAM = memory_region(REGION_CPU1);
150
151 for (mem=0;mem<0x4000;mem++)
152 {
153 oldbyte = RAM[mem];
154 inverted_oldbyte = ~oldbyte;
155
156 /* Note: D2 is inverted and connected to D1, D5 is inverted and
157 connected to D0. The other six data bits are converted by a
158 PAL10H8 driven by the counter. */
159 newbyte = 0;
160
161 /* Direct inversion */
162 newbyte = (inverted_oldbyte & 0x04) >> 1;
163 newbyte |= (inverted_oldbyte & 0x20) >> 5;
164 /* PAL */
165 newbyte |= (inverted_oldbyte & 0x01) << 6;
166 newbyte |= (oldbyte & 0x02) << 1;
167 newbyte |= (inverted_oldbyte & 0x08) << 4;
168 newbyte |= (inverted_oldbyte & 0x10) << 1;
169 newbyte |= (inverted_oldbyte & 0x40) >> 2;
170 newbyte |= (oldbyte & 0x80) >> 4;
171
172 RAM[mem + 0x18000] = newbyte;
173 }
174
175 return;
176 }
177
theglob_decrypt_rom_B(void)178 static void theglob_decrypt_rom_B(void)
179 {
180 int oldbyte,inverted_oldbyte,newbyte;
181 int mem;
182 unsigned char *RAM;
183
184 RAM = memory_region(REGION_CPU1);
185
186 for (mem=0;mem<0x4000;mem++)
187 {
188 oldbyte = RAM[mem];
189 inverted_oldbyte = ~oldbyte;
190
191 /* Note: D2 is inverted and connected to D1, D5 is inverted and
192 connected to D0. The other six data bits are converted by a
193 PAL10H8 driven by the counter. */
194 newbyte = 0;
195
196 /* Direct inversion */
197 newbyte = (inverted_oldbyte & 0x04) >> 1;
198 newbyte |= (inverted_oldbyte & 0x20) >> 5;
199 /* PAL */
200 newbyte |= (inverted_oldbyte & 0x01) << 6;
201 newbyte |= (inverted_oldbyte & 0x02) << 6;
202 newbyte |= (oldbyte & 0x08) << 1;
203 newbyte |= (inverted_oldbyte & 0x10) << 1;
204 newbyte |= (inverted_oldbyte & 0x40) >> 4;
205 newbyte |= (oldbyte & 0x80) >> 4;
206
207 RAM[mem + 0x1C000] = newbyte;
208 }
209
210 return;
211 }
212
213
READ_HANDLER(theglob_decrypt_rom)214 READ_HANDLER( theglob_decrypt_rom )
215 {
216 unsigned char *RAM = memory_region(REGION_CPU1);
217
218 if (offset & 0x01)
219 {
220 counter = counter - 1;
221 if (counter < 0)
222 counter = 0x0F;
223 }
224 else
225 {
226 counter = (counter + 1) & 0x0F;
227 }
228
229 switch(counter)
230 {
231 case 0x08: cpu_setbank (1, &RAM[0x10000]); break;
232 case 0x09: cpu_setbank (1, &RAM[0x14000]); break;
233 case 0x0A: cpu_setbank (1, &RAM[0x18000]); break;
234 case 0x0B: cpu_setbank (1, &RAM[0x1C000]); break;
235 default:
236 //logerror("Invalid counter = %02X\n",counter);
237 break;
238 }
239
240 return 0;
241 }
242
243
theglob_init_machine(void)244 void theglob_init_machine(void)
245 {
246 unsigned char *RAM = memory_region(REGION_CPU1);
247
248 /* While the PAL supports up to 16 decryption methods, only four
249 are actually used in the PAL. Therefore, we'll take a little
250 memory overhead and decrypt the ROMs using each method in advance. */
251 theglob_decrypt_rom_8();
252 theglob_decrypt_rom_9();
253 theglob_decrypt_rom_A();
254 theglob_decrypt_rom_B();
255
256 /* The initial state of the counter is 0x0A */
257 counter = 0x0A;
258 cpu_setbank (1, &RAM[0x18000]);
259
260 pacman_init_machine();
261 }
262