1
/***************************************************************************
5
Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
8
The Glob protection description:
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.
15
Here's a description of the protection as best as I can give it.
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
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.
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.
39
COUNTER ENCRYPTED DECRYPTED
45
Counter = 8: abcdefgh EAhBDgFC
46
Counter = 9: abcdefgh FAgeDBFC
47
Counter = A: abcdefgh EHDBagFC
48
Counter = B: abcdefgh GHDEaBFC
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.
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.
60
- Mike Balfour (mab22@po.cwru.edu)
62
***************************************************************************/
65
#include "includes/pacman.h"
68
static void theglobp_decrypt_rom_8(running_machine &machine)
70
int oldbyte,inverted_oldbyte,newbyte;
74
RAM = machine.region("maincpu")->base();
77
for (mem=0;mem<0x4000;mem++)
80
inverted_oldbyte = ~oldbyte;
82
/* Note: D2 is inverted and connected to D1, D5 is inverted and
83
connected to D0. The other six data bits are converted by a
84
PAL10H8 driven by the counter. */
87
/* Direct inversion */
88
newbyte = (inverted_oldbyte & 0x04) >> 1;
89
newbyte |= (inverted_oldbyte & 0x20) >> 5;
91
newbyte |= (oldbyte & 0x01) << 5;
92
newbyte |= (oldbyte & 0x02) << 1;
93
newbyte |= (inverted_oldbyte & 0x08) << 4;
94
newbyte |= (inverted_oldbyte & 0x10) >> 1;
95
newbyte |= (inverted_oldbyte & 0x40) >> 2;
96
newbyte |= (inverted_oldbyte & 0x80) >> 1;
98
RAM[mem + 0x10000] = newbyte;
105
static void theglobp_decrypt_rom_9(running_machine &machine)
107
int oldbyte,inverted_oldbyte,newbyte;
111
RAM = machine.region("maincpu")->base();
113
for (mem=0;mem<0x4000;mem++)
116
inverted_oldbyte = ~oldbyte;
118
/* Note: D2 is inverted and connected to D1, D5 is inverted and
119
connected to D0. The other six data bits are converted by a
120
PAL10H8 driven by the counter. */
123
/* Direct inversion */
124
newbyte = (inverted_oldbyte & 0x04) >> 1;
125
newbyte |= (inverted_oldbyte & 0x20) >> 5;
127
newbyte |= (oldbyte & 0x01) << 5;
128
newbyte |= (inverted_oldbyte & 0x02) << 6;
129
newbyte |= (oldbyte & 0x08) << 1;
130
newbyte |= (inverted_oldbyte & 0x10) >> 1;
131
newbyte |= (inverted_oldbyte & 0x40) >> 4;
132
newbyte |= (inverted_oldbyte & 0x80) >> 1;
134
RAM[mem + 0x14000] = newbyte;
140
static void theglobp_decrypt_rom_A(running_machine &machine)
142
int oldbyte,inverted_oldbyte,newbyte;
146
RAM = machine.region("maincpu")->base();
148
for (mem=0;mem<0x4000;mem++)
151
inverted_oldbyte = ~oldbyte;
153
/* Note: D2 is inverted and connected to D1, D5 is inverted and
154
connected to D0. The other six data bits are converted by a
155
PAL10H8 driven by the counter. */
158
/* Direct inversion */
159
newbyte = (inverted_oldbyte & 0x04) >> 1;
160
newbyte |= (inverted_oldbyte & 0x20) >> 5;
162
newbyte |= (inverted_oldbyte & 0x01) << 6;
163
newbyte |= (oldbyte & 0x02) << 1;
164
newbyte |= (inverted_oldbyte & 0x08) << 4;
165
newbyte |= (inverted_oldbyte & 0x10) << 1;
166
newbyte |= (inverted_oldbyte & 0x40) >> 2;
167
newbyte |= (oldbyte & 0x80) >> 4;
169
RAM[mem + 0x18000] = newbyte;
175
static void theglobp_decrypt_rom_B(running_machine &machine)
177
int oldbyte,inverted_oldbyte,newbyte;
181
RAM = machine.region("maincpu")->base();
183
for (mem=0;mem<0x4000;mem++)
186
inverted_oldbyte = ~oldbyte;
188
/* Note: D2 is inverted and connected to D1, D5 is inverted and
189
connected to D0. The other six data bits are converted by a
190
PAL10H8 driven by the counter. */
193
/* Direct inversion */
194
newbyte = (inverted_oldbyte & 0x04) >> 1;
195
newbyte |= (inverted_oldbyte & 0x20) >> 5;
197
newbyte |= (inverted_oldbyte & 0x01) << 6;
198
newbyte |= (inverted_oldbyte & 0x02) << 6;
199
newbyte |= (oldbyte & 0x08) << 1;
200
newbyte |= (inverted_oldbyte & 0x10) << 1;
201
newbyte |= (inverted_oldbyte & 0x40) >> 4;
202
newbyte |= (oldbyte & 0x80) >> 4;
204
RAM[mem + 0x1C000] = newbyte;
211
READ8_HANDLER( theglobp_decrypt_rom )
213
pacman_state *state = space->machine().driver_data<pacman_state>();
216
state->m_counter = (state->m_counter - 1) & 0x0F;
220
state->m_counter = (state->m_counter + 1) & 0x0F;
223
switch(state->m_counter)
225
case 0x08: memory_set_bank (space->machine(), "bank1", 0); break;
226
case 0x09: memory_set_bank (space->machine(), "bank1", 1); break;
227
case 0x0A: memory_set_bank (space->machine(), "bank1", 2); break;
228
case 0x0B: memory_set_bank (space->machine(), "bank1", 3); break;
230
logerror("Invalid counter = %02X\n",state->m_counter);
238
MACHINE_START( theglobp )
240
pacman_state *state = machine.driver_data<pacman_state>();
241
UINT8 *RAM = machine.region("maincpu")->base();
243
/* While the PAL supports up to 16 decryption methods, only four
244
are actually used in the PAL. Therefore, we'll take a little
245
memory overhead and decrypt the ROMs using each method in advance. */
246
theglobp_decrypt_rom_8(machine);
247
theglobp_decrypt_rom_9(machine);
248
theglobp_decrypt_rom_A(machine);
249
theglobp_decrypt_rom_B(machine);
251
memory_configure_bank(machine, "bank1", 0, 4, &RAM[0x10000], 0x4000);
253
state_save_register_global(machine, state->m_counter);
257
MACHINE_RESET( theglobp )
259
pacman_state *state = machine.driver_data<pacman_state>();
260
/* The initial state of the counter is 0x0A */
261
state->m_counter = 0x0A;
262
memory_set_bank(machine, "bank1", 2);