1 /*************************************************************************
2 
3   Operation Wolf C-Chip Protection
4   ================================
5 
6   The C-Chip (Taito TC0030CMD) is an unidentified mask programmed
7   microcontroller of some sort with 64 pins used for copy protection.
8   It probably has about 2k of ROM and 8k of RAM.  The simulation in this file
9   is verified from the unprotected prototype game and the observed behaviour
10   of the real pcb running.  It should give 100% accurate gameplay.  The bootleg
11   Operation Wolf uses a Z80 and custom program to replace the c-chip.  However
12   it's clear that bootlegger done the minimum to make the game work, with both
13   major and minor differences to the original game, which are outlined below.
14 
15   Operation Wolf has interesting software architecture.  Unlike most games of this
16   era which have a simple main loop and linear code flow, Operation Wolf
17   implements a co-operative threading model where routines run in 68K user mode
18   until giving up their timeslice and a supervisor mode scheduler picks the next
19   thread to run.  There are 32 thread slots, and each enemy in game run as its
20   own thread/object as well as a thread for coins, scrolling the level, level
21   specific gameplay and so on.  The code is very robust when creating threads,
22   for example if there are no free slots, the creating thread just spins until
23   a slot frees up.  The rest of the game just keeps on playing in the background.
24   Another interesting detail is that a thread can give up it's timeslice for more
25   than 1 frame - this makes it really easy to implement timed events.  The 'WARNING'
26   text at the end of level 2 is handled by a thread that prints to screen, then just
27   waits a second before spawning the boss enemy thread.
28 
29   Each level in the game implements its own logic thread and often sub-threads -
30   this is the major difference between the protected game and the bootleg - the bootleg
31   mostly implements the parts that are generic between all levels rather than all of
32   the details.  The biggest single area the bootleg did not implement revolves
33   around location 0x5f in the shared c-chip RAM.  The original code sets up a thread
34   that just waits for this value to become non-zero.  It then jumps to a set of
35   functions defined in a look-up table (that can then spawn further threads).  There
36   are 10 non-null functions tied to this routine.
37 
38   1:  Enemy spawn for level 7 (first 'Located' cut-scene)
39   2:  Enemy spawn for level 8 (second 'Located' cut-scene) - zoom in helicopters
40   3:  Enemy spawn for level 9 (third 'Located' cut-scene)
41   4:  Boss & hostage sequence for level 2
42   5:  Enemy spawn when less than 45 enemies in level 2 (paratrooper drop-down)
43   6:  Enemy spawn when less than 25 enemies in level 2
44   7:  Enemy spawn when 0 men left in levels 2,4,5,6
45   8:  Enemy spawn when 0 men left in level 3
46   9:  Enemy spawn when 0 men left in level 1
47   10:  Special explosion animation when level 4 (Powder Dump) is completed
48 
49   The bootleg also misses some other details, for example in level 5 the c-chip
50   sets a flag when all men are destroyed (not vehicles) and this triggers the 68K
51   to scroll the screen vertically to focus on the remaining helicopter enemies.
52 
53   The 'Enemy has located you' cut-scenes appear 'randomly' between levels in the
54   original game, but are deliberately disabled in the bootleg.  The exact formula
55   for determining if the cut-scene appears is '(frameCount & levelNumber)==0'.
56   See code at 0x2D68 for this logic.
57 
58 
59   Interesting memory locations shared by cchip/68k:
60 
61   0a/xx - copy of 3a0000
62   28/14 - dip switch A (written by 68k at start)
63   2a/15 - dip switch B (written by 68k at start)
64   2c/ ???      (mapped to $982,A5) [word] in prototype)
65   2e/          (mapped to $984,A5) [word] in prototype)
66   58/2c         m_cchip_ram[0x2c] = 0x31;
67   ee/77         m_cchip_ram[0x77] = 0x05;
68   4a/25         m_cchip_ram[0x25] = 0x0f;
69   4c/26         m_cchip_ram[0x26] = 0x0b;
70   36/1b - Current level number (1-6)
71   38/1c - Number of men remaining in level
72   3c/1e - Number of helicopters remaining in level
73   3e/1f - Number of tanks remaining in level
74   40/20 - Number of boats remaining in level
75   42/21 - Hostages in plane (last level)
76   44/22 - Hostages remaining (last level)/Hostages saved (2nd last level)
77   4e/27 - Set to 1 when final boss is destroyed
78   64/32 - Set to 1 by cchip when level complete (no more enemies remaining)
79   68/34 - Game state (0=attract mode, 1=intro, 2=in-game, 3=end-screen)
80   69/xx - variable mapped from ($980,A5) [byte] in prototype
81   6B/xx - variable mapped from ($981,A5) [byte] in prototype
82   A6/xx - variable mapped from ($d6e,A5) [word] in prototype
83   A8/54 - ?
84   xx/51/52 - Used by cchip to signal change in credit level to 68k
85   xx/53 - Credit count
86   EA/75 - Set to 1 to trigger end of game boss
87   EC/76 - used near above
88   xx/7a - Used to trigger level data select command
89 
90   Notes on bootleg c-chip compared to original:
91     Bootleg cchip forces english language mode
92     Bootleg forces round 4 in attract mode
93     Bootleg doesn't support service switch
94     If you die after round 6 then the bootleg fails to reset the difficulty
95       for the next game.
96 	The bootleg does not contain data for the 3 mini-levels ('Enemy has located you'),
97 	  instead it prevents them running by writing 0 to location 70 in the shared memory.
98 	The bootleg does not play the special powder magazine (level 4) animation.
99 	The bootleg does not vertically scroll the screen when all men killed in level 5
100 	The bootleg does not update the enemy spawn tables at various points.
101 
102   Notes by bmcphail@vcmame.net
103 
104 *************************************************************************/
105 
106 #include "driver.h"
107 #include "state.h"
108 
109 static UINT8 current_bank=0;
110 static UINT8 current_cmd=0;
111 static UINT8* cchip_ram=0;
112 static UINT8 cchip_last_7a=0;
113 static UINT8 cchip_last_04=0;
114 static UINT8 cchip_last_05=0;
115 static UINT8 cchip_coins_for_credit_a=1;
116 static UINT8 cchip_credit_for_coin_b=2;
117 static UINT8 cchip_coins=0;
118 static UINT8 c588=0, c589=0, c58a=0; /* These variables derived from the bootleg */
119 static UINT8 triggeredLevel1b; /* These variables derived from comparison to unprotection version */
120 static UINT8 triggeredLevel2;
121 static UINT8 triggeredLevel2b;
122 static UINT8 triggeredLevel2c;
123 static UINT8 triggeredLevel3b;
124 static UINT8 triggeredLevel13b;
125 static UINT8 triggeredLevel4;
126 static UINT8 triggeredLevel5;
127 static UINT8 triggeredLevel7;
128 static UINT8 triggeredLevel8;
129 static UINT8 triggeredLevel9;
130 
131 static const UINT16 level_data_00[] = {
132 	0x0480, 0x1008, 0x0300,   0x5701, 0x0001, 0x0010,
133 	0x0480, 0x1008, 0x0300,   0x5701, 0x0001, 0x002b,
134 	0x0780, 0x0009, 0x0300,   0x4a01, 0x0004, 0x0020,
135 	0x0780, 0x1208, 0x0300,   0x5d01, 0x0004, 0x0030,
136 	0x0780, 0x0209, 0x0300,   0x4c01, 0x0004, 0x0038,
137 	0x0780, 0x0309, 0x0300,   0x4d01, 0x0004, 0x0048,
138 	0x0980, 0x1108, 0x0300,   0x5a01, 0xc005, 0x0018,
139 	0x0980, 0x0109, 0x0300,   0x4b01, 0xc005, 0x0028,
140 	0x0b80, 0x020a, 0x0000,   0x6401, 0x8006, 0x0004,
141 	0x0c80, 0x010b, 0x0000,   0xf201, 0x8006, 0x8002,
142 	0x0b80, 0x020a, 0x0000,   0x6401, 0x8006, 0x0017,
143 	0x0c80, 0x010b, 0x0000,   0xf201, 0x8006, 0x8015,
144 	0x0b80, 0x020a, 0x0000,   0x6401, 0x0007, 0x0034,
145 	0x0c80, 0x010b, 0x0000,   0xf201, 0x0007, 0x8032,
146 	0x0b80, 0x020a, 0x0000,   0x6401, 0x8006, 0x803e,
147 	0x0c80, 0x010b, 0x0000,   0xf201, 0x8006, 0x803d,
148 	0x0b80, 0x100a, 0x0000,   0x6001, 0x0007, 0x0008,
149 	0x0b80, 0x100a, 0x0000,   0x6001, 0x0007, 0x000b,
150 	0x0b80, 0x100a, 0x0000,   0x6001, 0x0007, 0x001b,
151 	0x0b80, 0x100a, 0x0000,   0x6001, 0x0007, 0x001e,
152 	0x0b80, 0x100a, 0x0000,   0x6001, 0x8007, 0x0038,
153 	0x0b80, 0x100a, 0x0000,   0x6001, 0x8007, 0x003b,
154 	0x0b80, 0x100a, 0x0000,   0x6001, 0x0007, 0x8042,
155 	0x0b80, 0x100a, 0x0000,   0x6001, 0x0007, 0x8045,
156 	0x0c80, 0x000b, 0x0000,   0xf101, 0x800b, 0x8007,
157 	0x0c80, 0x000b, 0x0000,   0xf101, 0x800b, 0x801a,
158 	0x0c80, 0x000b, 0x0000,   0xf101, 0x000c, 0x8037,
159 	0x0c80, 0x000b, 0x0000,   0xf101, 0x800b, 0x0042,
160 	0x0c80, 0xd04b, 0x0000,   0xf301, 0x8006, 0x8009,
161 	0x0c80, 0xd04b, 0x0000,   0xf301, 0x8006, 0x801c,
162 	0x0c80, 0xd04b, 0x0000,   0xf301, 0x8006, 0x0044,
163 	0x0c80, 0x030b, 0x0000,   0xf401, 0x0008, 0x0028,
164 	0x0c80, 0x030b, 0x0000,   0xf401, 0x0008, 0x804b,
165 	0x0c00, 0x040b, 0x0000,   0xf501, 0x0008, 0x8026,
166 	0xffff
167 };
168 
169 static const UINT16 level_data_01[] = {
170 	0x0780, 0x0209, 0x0300,   0x4c01, 0x0004, 0x0010,
171 	0x0780, 0x0209, 0x0300,   0x4c01, 0x4004, 0x0020,
172 	0x0780, 0x0309, 0x0300,   0x4d01, 0xe003, 0x0030,
173 	0x0780, 0x0309, 0x0300,   0x4d01, 0x8003, 0x0040,
174 	0x0780, 0x0209, 0x0300,   0x4c01, 0x8004, 0x0018,
175 	0x0780, 0x0309, 0x0300,   0x4d01, 0xc003, 0x0028,
176 	0x0b80, 0x000b, 0x0000,   0x0b02, 0x8009, 0x0029,
177 	0x0b80, 0x0409, 0x0000,   0x0f02, 0x8008, 0x8028,
178 	0x0b80, 0x040a, 0x0000,   0x3502, 0x000a, 0x8028,
179 	0x0b80, 0x050a, 0x0000,   0x1002, 0x8006, 0x8028,
180 	0x0b80, 0x120a, 0x0000,   0x3602, 0x0008, 0x004d,
181 	0x0b80, 0x120a, 0x0000,   0x3602, 0x0008, 0x004f,
182 	0x0b80, 0x120a, 0x0000,   0x3602, 0x0008, 0x0001,
183 	0x0b80, 0x120a, 0x0000,   0x3602, 0x0008, 0x0003,
184 	0x0b80, 0x130a, 0x0000,   0x3a02, 0x0007, 0x0023,
185 	0x0b80, 0x130a, 0x0000,   0x3a02, 0x0007, 0x8025,
186 	0x0b80, 0x130a, 0x0000,   0x3a02, 0x8009, 0x0023,
187 	0x0b80, 0x130a, 0x0000,   0x3a02, 0x8009, 0x8025,
188 	0x0b80, 0x140a, 0x0000,   0x3e02, 0x0007, 0x000d,
189 	0x0b80, 0x140a, 0x0000,   0x3e02, 0x0007, 0x800f,
190 	0x0b80, 0x000b, 0x0000,   0x0102, 0x0007, 0x804e,
191 	0x0b80, 0xd24b, 0x0000,   0x0302, 0x0007, 0x000e,
192 	0x0b80, 0x000b, 0x0000,   0x0402, 0x8006, 0x0020,
193 	0x0b80, 0xd34b, 0x0000,   0x0502, 0x8006, 0x0024,
194 	0x0b80, 0x000b, 0x0000,   0x0602, 0x8009, 0x0001,
195 	0x0b80, 0xd44b, 0x0000,   0x0702, 0x800b, 0x800b,
196 	0x0b80, 0xd54b, 0x0000,   0x0802, 0x800b, 0x000e,
197 	0x0b80, 0x000b, 0x0000,   0x0902, 0x800b, 0x0010,
198 	0x0b80, 0x000b, 0x0000,   0x0a02, 0x0009, 0x0024,
199 	0x0b80, 0xd64b, 0x0000,   0x0c02, 0x000c, 0x8021,
200 	0x0b80, 0x000b, 0x0000,   0x0d02, 0x000c, 0x0025,
201 	0x0b80, 0x000b, 0x0000,   0x0e02, 0x8009, 0x004e,
202 	0x0b80, 0x000b, 0x0300,   0x4e01, 0x8006, 0x8012,
203 	0x0b80, 0x000b, 0x0300,   0x4e01, 0x0007, 0x8007,
204 	0xffff
205 };
206 
207 static const UINT16 level_data_02[] = {
208 	0x0480, 0x000b, 0x0300,   0x4501, 0x0001, 0x0018,
209 	0x0480, 0x000b, 0x0300,   0x4501, 0x2001, 0x0030,
210 	0x0780, 0x1208, 0x0300,   0x5d01, 0x0004, 0x0010,
211 	0x0780, 0x1208, 0x0300,   0x5d01, 0x2004, 0x001c,
212 	0x0780, 0x1208, 0x0300,   0x5d01, 0xe003, 0x0026,
213 	0x0780, 0x1208, 0x0300,   0x5d01, 0x8003, 0x0034,
214 	0x0780, 0x1208, 0x0300,   0x5d01, 0x3004, 0x0040,
215 	0x0780, 0x010c, 0x0300,   0x4601, 0x4004, 0x0022,
216 	0x0780, 0x010c, 0x0300,   0x4601, 0x6004, 0x0042,
217 	0x0780, 0x000c, 0x0500,   0x7b01, 0x800b, 0x0008,
218 	0x0780, 0x010c, 0x0300,   0x4601, 0x2004, 0x0008,
219 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
220 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
221 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
222 	0x0b80, 0x000b, 0x0000,   0x1902, 0x000b, 0x0004,
223 	0x0b80, 0x000b, 0x0000,   0x1a02, 0x0009, 0x8003,
224 	0x0b80, 0x000b, 0x0000,   0x1902, 0x000b, 0x000c,
225 	0x0b80, 0x000b, 0x0000,   0x1a02, 0x0009, 0x800b,
226 	0x0b80, 0x000b, 0x0000,   0x1902, 0x000b, 0x001c,
227 	0x0b80, 0x000b, 0x0000,   0x1a02, 0x0009, 0x801b,
228 	0x0b80, 0x000b, 0x0000,   0x1902, 0x000b, 0x002c,
229 	0x0b80, 0x000b, 0x0000,   0x1a02, 0x0009, 0x802b,
230 	0x0b80, 0x000b, 0x0000,   0x1902, 0x000b, 0x0044,
231 	0x0b80, 0x000b, 0x0000,   0x1a02, 0x0009, 0x8043,
232 	0x0b80, 0x000b, 0x0000,   0x1902, 0x000b, 0x004c,
233 	0x0b80, 0x000b, 0x0000,   0x1a02, 0x0009, 0x804b,
234 	0x0b80, 0x020c, 0x0300,   0x4801, 0xa009, 0x0010,
235 	0x0b80, 0x020c, 0x0300,   0x4801, 0xa009, 0x0028,
236 	0x0b80, 0x020c, 0x0300,   0x4801, 0xa009, 0x0036,
237 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
238 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
239 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
240 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
241 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
242 	0xffff
243 };
244 
245 static const UINT16 level_data_03[] = {
246 	0x0480, 0x000b, 0x0300,   0x4501, 0x0001, 0x0018,
247 	0x0480, 0x000b, 0x0300,   0x4501, 0x2001, 0x002b,
248 	0x0780, 0x010c, 0x0300,   0x4601, 0x0004, 0x000d,
249 	0x0780, 0x000c, 0x0500,   0x7b01, 0x800b, 0x0020,
250 	0x0780, 0x010c, 0x0300,   0x4601, 0x2004, 0x0020,
251 	0x0780, 0x010c, 0x0300,   0x4601, 0x8003, 0x0033,
252 	0x0780, 0x010c, 0x0300,   0x4601, 0x0004, 0x003c,
253 	0x0780, 0x010c, 0x0300,   0x4601, 0xd003, 0x0045,
254 	0x0780, 0x000c, 0x0500,   0x7b01, 0x900b, 0x0041,
255 	0x0780, 0x010c, 0x0300,   0x4601, 0x3004, 0x0041,
256 	0x0b80, 0x020c, 0x0300,   0x4801, 0x0007, 0x0000,
257 	0x0b80, 0x410a, 0x0000,   0x2b02, 0xe006, 0x4049,
258 	0x0b80, 0x020c, 0x0300,   0x4801, 0x8007, 0x000b,
259 	0x0b80, 0x000b, 0x0000,   0x2702, 0x800a, 0x8005,
260 	0x0b80, 0x000b, 0x0000,   0x1e02, 0x0008, 0x800e,
261 	0x0b80, 0x000b, 0x0000,   0x1f02, 0x8007, 0x0011,
262 	0x0b80, 0x000b, 0x0000,   0x2802, 0x000b, 0x0012,
263 	0x0b80, 0x000b, 0x0000,   0x2002, 0x0007, 0x8015,
264 	0x0b80, 0x000b, 0x0000,   0x2102, 0x0007, 0x801b,
265 	0x0b80, 0x000b, 0x0000,   0x2902, 0x800a, 0x001a,
266 	0x0b80, 0x000b, 0x0000,   0x2202, 0x8007, 0x001e,
267 	0x0b80, 0x000b, 0x0000,   0x1e02, 0x0008, 0x0025,
268 	0x0b80, 0x000b, 0x0000,   0x2302, 0x8007, 0x802c,
269 	0x0b80, 0x000b, 0x0000,   0x2802, 0x000b, 0x8028,
270 	0x0b80, 0x020c, 0x0300,   0x4801, 0x0007, 0x0030,
271 	0x0b80, 0x400a, 0x0000,   0x2e02, 0x4007, 0x002d,
272 	0x0b80, 0x000b, 0x0000,   0x2702, 0x800a, 0x8035,
273 	0x0b80, 0x020c, 0x0300,   0x4801, 0x8007, 0x0022,
274 	0x0b80, 0x000b, 0x0000,   0x2402, 0x8007, 0x0047,
275 	0x0b80, 0x000b, 0x0000,   0x2a02, 0x800a, 0x004b,
276 	0x0b80, 0x000b, 0x0000,   0x2502, 0x0007, 0x804b,
277 	0x0b80, 0x000b, 0x0000,   0x2602, 0x0007, 0x004e,
278 	0x0b80, 0x020c, 0x0300,   0x4801, 0x0007, 0x8043,
279 	0x0b80, 0x020c, 0x0300,   0x4801, 0x8007, 0x803d,
280 	0xffff
281 };
282 
283 static const UINT16 level_data_04[] = {
284 	0x0780, 0x0209, 0x0300,   0x4c01, 0x0004, 0x0010,
285 	0x0780, 0x0209, 0x0300,   0x4c01, 0x4004, 0x0020,
286 	0x0780, 0x0309, 0x0300,   0x4d01, 0xe003, 0x0030,
287 	0x0780, 0x0309, 0x0300,   0x4d01, 0x8003, 0x0040,
288 	0x0780, 0x0209, 0x0300,   0x4c01, 0x8004, 0x0018,
289 	0x0780, 0x0309, 0x0300,   0x4d01, 0xc003, 0x0028,
290 	0x0780, 0x000b, 0x0300,   0x5601, 0x8004, 0x0008,
291 	0x0780, 0x000b, 0x0300,   0x5601, 0x8004, 0x0038,
292 	0x0780, 0x000b, 0x0300,   0x5501, 0x8004, 0x0048,
293 	0x0980, 0x0509, 0x0f00,   0x0f01, 0x4005, 0x4007,
294 	0x0980, 0x0509, 0x0f00,   0x0f01, 0x4005, 0x4037,
295 	0x0b80, 0x030a, 0x0000,   0x1302, 0x8006, 0x0040,
296 	0x0b80, 0x110a, 0x0000,   0x1502, 0x8008, 0x8048,
297 	0x0b80, 0x110a, 0x0000,   0x1502, 0x8008, 0x8049,
298 	0x0b80, 0x000b, 0x0000,   0xf601, 0x0007, 0x8003,
299 	0x0b80, 0x000b, 0x0000,   0xf701, 0x0007, 0x0005,
300 	0x0b80, 0x000b, 0x0000,   0xf901, 0x0007, 0x8008,
301 	0x0b80, 0x000b, 0x0000,   0xf901, 0x0007, 0x0010,
302 	0x0b80, 0x000b, 0x0000,   0xfa01, 0x0007, 0x8013,
303 	0x0b80, 0x000b, 0x0000,   0xf801, 0x800b, 0x800b,
304 	0x0b80, 0x000b, 0x0000,   0x0002, 0x800b, 0x801a,
305 	0x0b80, 0x000b, 0x0000,   0xf901, 0x0007, 0x8017,
306 	0x0b80, 0x000b, 0x0000,   0xfa01, 0x0007, 0x001b,
307 	0x0b80, 0x000b, 0x0000,   0xf801, 0x800b, 0x0013,
308 	0x0b80, 0x000b, 0x0000,   0x4202, 0x800b, 0x0016,
309 	0x0b80, 0x000b, 0x0000,   0xfb01, 0x8007, 0x8020,
310 	0x0b80, 0x000b, 0x0000,   0xf601, 0x0007, 0x8023,
311 	0x0b80, 0x000b, 0x0000,   0x4202, 0x800b, 0x800e,
312 	0x0b80, 0x000b, 0x0000,   0x4302, 0x800b, 0x801d,
313 	0x0b80, 0x000b, 0x0000,   0xf701, 0x0007, 0x0025,
314 	0x0b80, 0x000b, 0x0000,   0xfd01, 0x8006, 0x003f,
315 	0x0b80, 0x000b, 0x0000,   0xfe01, 0x0007, 0x0046,
316 	0x0b80, 0x000b, 0x0000,   0xff01, 0x8007, 0x8049,
317 	0x0b80, 0x000b, 0x0000,   0xfc01, 0x8009, 0x0042,
318 	0xffff
319 };
320 
321 static const UINT16 level_data_05[] = {
322 	0x0480, 0x1008, 0x0300,   0x5701, 0x0001, 0x0010,
323 	0x0480, 0x1008, 0x0300,   0x5701, 0x0001, 0x002b,
324 	0x0780, 0x0009, 0x0300,   0x4a01, 0x0004, 0x0020,
325 	0x0780, 0x1208, 0x0300,   0x5d01, 0x0004, 0x0030,
326 	0x0780, 0x0209, 0x0300,   0x4c01, 0x0004, 0x0038,
327 	0x0780, 0x0309, 0x0300,   0x4d01, 0x0004, 0x0048,
328 	0x0980, 0x1108, 0x0300,   0x5a01, 0xc005, 0x0018,
329 	0x0980, 0x0109, 0x0300,   0x4b01, 0xc005, 0x0028,
330 	0x0b80, 0x020a, 0x0000,   0x6401, 0x8006, 0x0004,
331 	0x0c80, 0x010b, 0x0000,   0xf201, 0x8006, 0x8002,
332 	0x0b80, 0x020a, 0x0000,   0x6401, 0x8006, 0x0017,
333 	0x0c80, 0x010b, 0x0000,   0xf201, 0x8006, 0x8015,
334 	0x0b80, 0x020a, 0x0000,   0x6401, 0x0007, 0x0034,
335 	0x0c80, 0x010b, 0x0000,   0xf201, 0x0007, 0x8032,
336 	0x0b80, 0x020a, 0x0000,   0x6401, 0x8006, 0x803e,
337 	0x0c80, 0x010b, 0x0000,   0xf201, 0x8006, 0x803d,
338 	0x0b80, 0x100a, 0x0000,   0x6001, 0x0007, 0x0008,
339 	0x0b80, 0x100a, 0x0000,   0x6001, 0x0007, 0x000b,
340 	0x0b80, 0x100a, 0x0000,   0x6001, 0x0007, 0x001b,
341 	0x0b80, 0x100a, 0x0000,   0x6001, 0x0007, 0x001e,
342 	0x0b80, 0x100a, 0x0000,   0x6001, 0x8007, 0x0038,
343 	0x0b80, 0x100a, 0x0000,   0x6001, 0x8007, 0x003b,
344 	0x0b80, 0x100a, 0x0000,   0x6001, 0x0007, 0x8042,
345 	0x0b80, 0x100a, 0x0000,   0x6001, 0x0007, 0x8045,
346 	0x0c80, 0x000b, 0x0000,   0xf101, 0x800b, 0x8007,
347 	0x0c80, 0x000b, 0x0000,   0xf101, 0x800b, 0x801a,
348 	0x0c80, 0x000b, 0x0000,   0xf101, 0x000c, 0x8037,
349 	0x0c80, 0x000b, 0x0000,   0xf101, 0x800b, 0x0042,
350 	0x0c80, 0xd04b, 0x0000,   0xf301, 0x8006, 0x8009,
351 	0x0c80, 0xd04b, 0x0000,   0xf301, 0x8006, 0x801c,
352 	0x0c80, 0xd04b, 0x0000,   0xf301, 0x8006, 0x0044,
353 	0x0c80, 0x030b, 0x0000,   0xf401, 0x0008, 0x0028,
354 	0x0c80, 0x030b, 0x0000,   0xf401, 0x0008, 0x804b,
355 	0x0c00, 0x040b, 0x0000,   0xf501, 0x0008, 0x8026,
356 	0xffff
357 };
358 
359 static const UINT16 level_data_06[] = {
360 	0x0000, 0x1008, 0x0300,   0x5701, 0x0001, 0x0010,
361 	0x0000, 0x1008, 0x0300,   0x5701, 0x0001, 0x002b,
362 	0x0000, 0x0000, 0x0000,   0x0000, 0x0000, 0x0000,
363 	0x0700, 0x0009, 0x0300,   0x4a01, 0x0004, 0x0020,
364 	0x0700, 0x1208, 0x0300,   0x5d01, 0x0004, 0x0030,
365 	0x0700, 0x0209, 0x0300,   0x4c01, 0x0004, 0x0038,
366 	0x0700, 0x0309, 0x0300,   0x4d01, 0x0004, 0x0048,
367 	0x0900, 0x1108, 0x0300,   0x5a01, 0xc005, 0x0018,
368 	0x0900, 0x0109, 0x0300,   0x4b01, 0xc005, 0x0028,
369 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
370 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
371 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
372 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
373 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
374 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
375 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
376 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
377 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
378 	0x0980, 0xdb4c, 0x0000,   0x3202, 0x0006, 0x0004,
379 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
380 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
381 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
382 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
383 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
384 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
385 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
386 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
387 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
388 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
389 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
390 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
391 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
392 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
393 	0x0000, 0x000b, 0x0000,   0x0000, 0x0018, 0x0000,
394 	0xffff
395 };
396 
397 static const UINT16 level_data_07[] = {
398 	0x0480, 0x000b, 0x0300,   0x4501, 0x0001, 0x0001,
399 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
400 	0x0780, 0x0109, 0x0300,   0x4a01, 0x0004, 0x0004,
401 	0x0780, 0x0009, 0x0300,   0x4a01, 0x0004, 0x000d,
402 	0x0780, 0x000c, 0x0500,   0x7b01, 0x000c, 0x0005,
403 	0x0780, 0x000c, 0x0540,   0x7b01, 0x000c, 0x0005,
404 	0x0780, 0x010c, 0x0300,   0x4601, 0x0005, 0x0005,
405 	0x0780, 0x000c, 0x0500,   0x7b01, 0x800b, 0xc00d,
406 	0x0780, 0x000c, 0x0540,   0x7b01, 0x800b, 0xc00d,
407 	0x0780, 0x010c, 0x0300,   0x4601, 0x8004, 0xc00d,
408 	0x0900, 0x0109, 0x0340,   0x4b01, 0x2006, 0x400c,
409 	0x0780, 0x020c, 0x0300,   0x4801, 0x8007, 0x0008,
410 	0x0780, 0x020c, 0x0300,   0x4801, 0x4007, 0xc00b,
411 	0x0980, 0x0109, 0x0300,   0x4b01, 0xc006, 0x8007,
412 	0x0980, 0x0109, 0x0300,   0x4b01, 0x8007, 0x8008,
413 	0x0980, 0x0109, 0x0300,   0x4b01, 0xc006, 0x800c,
414 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
415 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
416 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
417 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
418 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
419 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
420 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
421 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
422 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
423 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
424 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
425 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
426 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
427 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
428 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
429 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
430 	0xffff
431 };
432 
433 static const UINT16 level_data_08[] = {
434 	0xffff
435 };
436 
437 static const UINT16 level_data_09[] = {
438 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
439 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
440 	0x0780, 0x0109, 0x0300,   0x4a01, 0x8003, 0x8003,
441 	0x0780, 0x0009, 0x0300,   0x4a01, 0x0004, 0x800e,
442 	0x0780, 0x000c, 0x0500,   0x7b01, 0x000c, 0x0005,
443 	0x0780, 0x000c, 0x0540,   0x7b01, 0x000c, 0x0005,
444 	0x0780, 0x010c, 0x0300,   0x4601, 0x0005, 0x0005,
445 	0x0780, 0x000c, 0x0500,   0x7b01, 0x800b, 0xc00d,
446 	0x0780, 0x000c, 0x0540,   0x7b01, 0x800b, 0xc00d,
447 	0x0780, 0x010c, 0x0300,   0x4601, 0x8004, 0xc00d,
448 	0x0900, 0x0109, 0x0340,   0x4b01, 0x2006, 0x400c,
449 	0x0780, 0x020c, 0x0300,   0x4801, 0x8007, 0x0008,
450 	0x0780, 0x020c, 0x0300,   0x4801, 0x4007, 0xc00b,
451 	0x0980, 0x0109, 0x0300,   0x4b01, 0xc006, 0x8007,
452 	0x0980, 0x0109, 0x0300,   0x4b01, 0x8007, 0x8008,
453 	0x0980, 0x0109, 0x0300,   0x4b01, 0xc006, 0x800c,
454 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
455 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
456 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
457 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
458 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
459 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
460 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
461 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
462 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
463 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
464 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
465 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
466 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
467 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
468 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
469 	0x0000, 0x0000, 0x0000,   0xf001, 0x0000, 0x0000,
470 	0xffff
471 };
472 
473 static const UINT16 *const level_data_lookup[] =
474 {
475 	level_data_00,
476 	level_data_01,
477 	level_data_02,
478 	level_data_03,
479 	level_data_04,
480 	level_data_05,
481 	level_data_06,
482 	level_data_07,
483 	level_data_08,
484 	level_data_09
485 };
486 
487 
timer_callback(int param)488 static void timer_callback(int param)
489 {
490 /* Level data command */
491 	if (current_cmd == 0xf5)
492 	{
493         int const level = cchip_ram[0x1b] % 10;
494         UINT16 const *const level_data = level_data_lookup[level];
495 	 	unsigned i = 0;
496 
497         /* The c-chip data is stored as a series of 3 word sets, delimited by 0xffff */
498         memset(cchip_ram + 0x200, 0, 0x200);
499         for (i = 0; (i < 0x200) && (level_data[i] != 0xffff); i += 3)
500 		{
501 			cchip_ram[0x200 + i*2 + 0] = level_data[i]>>8;
502 			cchip_ram[0x200 + i*2 + 1] = level_data[i]&0xff;
503 			cchip_ram[0x200 + i*2 + 2] = level_data[i+1]>>8;
504 			cchip_ram[0x200 + i*2 + 3] = level_data[i+1]&0xff;
505 			cchip_ram[0x200 + i*2 + 4] = level_data[i+2]>>8;
506 			cchip_ram[0x200 + i*2 + 5] = level_data[i+2]&0xff;
507 		}
508 
509 		/* The bootleg cchip writes 0 to these locations - we can probably assume the real one
510 		does similar as this is just zeroing out work variables used in the level.
511 		*/
512 		cchip_ram[0x0] = 0;
513 		cchip_ram[0x76] = 0;
514 		cchip_ram[0x75] = 0;
515 		cchip_ram[0x74] = 0;
516 		cchip_ram[0x72] = 0;
517 		cchip_ram[0x71] = 0;
518 		/* cchip_ram[0x70] = 0; The bootleg writes this to disable mini-levels.  The real c-chip does not do this. */
519 		cchip_ram[0x66] = 0;
520 		cchip_ram[0x2b] = 0;
521 		cchip_ram[0x30] = 0;
522 		cchip_ram[0x31] = 0;
523 		cchip_ram[0x32] = 0;
524 		cchip_ram[0x27] = 0;
525 		c588 = 0;
526 		c589 = 0;
527 		c58a = 0;
528 		triggeredLevel1b = 0;
529 		triggeredLevel13b = 0;
530 		triggeredLevel2 = 0;
531 		triggeredLevel2b = 0;
532 		triggeredLevel2c = 0;
533 		triggeredLevel3b = 0;
534 		triggeredLevel4 = 0;
535 		triggeredLevel5 = 0;
536 		triggeredLevel7 = 0;
537 		triggeredLevel8 = 0;
538 		triggeredLevel9 = 0;
539 
540 		cchip_ram[0x1a] = 0;
541 		cchip_ram[0x7a] = 1; /* Signal command complete */
542 
543 	}
544 
545 	current_cmd = 0;
546 }
547 
updateDifficulty(int mode)548 static void updateDifficulty(int mode)
549 {
550 	/* The game is made up of 6 rounds, when you complete the
551 	sixth you return to the start but with harder difficulty.
552 	*/
553 	if (mode==0)
554 	{
555 		switch (cchip_ram[0x15]&3) /* Dipswitch B */
556 		{
557 		case 3:
558 			cchip_ram[0x2c]=0x31;
559 			cchip_ram[0x77]=0x05;
560 			cchip_ram[0x25]=0x0f;
561 			cchip_ram[0x26]=0x0b;
562 			break;
563 		case 0:
564 			cchip_ram[0x2c]=0x20;
565 			cchip_ram[0x77]=0x06;
566 			cchip_ram[0x25]=0x07;
567 			cchip_ram[0x26]=0x03;
568 			break;
569 		case 1:
570 			cchip_ram[0x2c]=0x31;
571 			cchip_ram[0x77]=0x05;
572 			cchip_ram[0x25]=0x0f;
573 			cchip_ram[0x26]=0x0b;
574 			break;
575 		case 2:
576 			cchip_ram[0x2c]=0x3c;
577 			cchip_ram[0x77]=0x04;
578 			cchip_ram[0x25]=0x13;
579 			cchip_ram[0x26]=0x0f;
580 			break;
581 		}
582 	}
583 	else
584 	{
585 		switch (cchip_ram[0x15]&3) /* Dipswitch B */
586 		{
587 		case 3:
588 			cchip_ram[0x2c]=0x46;
589 			cchip_ram[0x77]=0x5;
590 			cchip_ram[0x25]=0x11;
591 			cchip_ram[0x26]=0xe;
592 			break;
593 		case 0:
594 			cchip_ram[0x2c]=0x30;
595 			cchip_ram[0x77]=0x6;
596 			cchip_ram[0x25]=0xb;
597 			cchip_ram[0x26]=0x3;
598 			break;
599 		case 1:
600 			cchip_ram[0x2c]=0x3a;
601 			cchip_ram[0x77]=0x5;
602 			cchip_ram[0x25]=0xf;
603 			cchip_ram[0x26]=0x9;
604 			break;
605 		case 2:
606 			cchip_ram[0x2c]=0x4c;
607 			cchip_ram[0x77]=0x4;
608 			cchip_ram[0x25]=0x19;
609 			cchip_ram[0x26]=0x11;
610 			break;
611 		};
612 	}
613 }
614 
615 /*************************************
616  *
617  * Writes to C-Chip - Important Bits
618  *
619  *************************************/
620 
WRITE16_HANDLER(opwolf_cchip_status_w)621 WRITE16_HANDLER( opwolf_cchip_status_w )
622 {
623 	/* This is written once after the C-Chip init is complete (and passes)
624 	We use it to setup some initial state (it's not clear if the real
625 	c-chip sets this here, or if it's as a side-effect of the other
626 	init sequence data).
627 	*/
628 
629 	cchip_ram[0x3d]=1;
630 	cchip_ram[0x7a]=1;
631 	updateDifficulty(0);
632 }
633 
WRITE16_HANDLER(opwolf_cchip_bank_w)634 WRITE16_HANDLER( opwolf_cchip_bank_w )
635 {
636 	current_bank=data&7;
637 }
638 
WRITE16_HANDLER(opwolf_cchip_data_w)639 WRITE16_HANDLER( opwolf_cchip_data_w )
640 {
641 	cchip_ram[(current_bank * 0x400) + offset]=data&0xff;
642 
643 	if (current_bank == 0)
644 	{
645 		/* Dip switch A is written here by the 68k - precalculate the coinage values */
646 		if (offset == 0x14)
647 		{
648 			switch (data&0x30)
649 			{
650 			case 0x00: cchip_coins_for_credit_a=4; break;
651 			case 0x10: cchip_coins_for_credit_a=3; break;
652 			case 0x20: cchip_coins_for_credit_a=2; break;
653 			case 0x30: cchip_coins_for_credit_a=1; break;
654 			}
655 
656 			switch (data&0xc0)
657 			{
658 			case 0x00: cchip_credit_for_coin_b=6; break;
659 			case 0x40: cchip_credit_for_coin_b=4; break;
660 			case 0x80: cchip_credit_for_coin_b=3; break;
661 			case 0xc0: cchip_credit_for_coin_b=2; break;
662 			}
663 		}
664 
665 		/* Dip switch B */
666 		if (offset == 0x15)
667 		{
668 			updateDifficulty(0);
669 		}
670 	}
671 }
672 
673 
674 /*************************************
675  *
676  * Reads from C-Chip
677  *
678  *************************************/
679 
READ16_HANDLER(opwolf_cchip_status_r)680 READ16_HANDLER( opwolf_cchip_status_r )
681 {
682 	/*
683         Bit 0x4 = Error signal
684         Bit 0x1 = Ready signal
685     */
686 	return 0x1; /* Return 0x5 for C-Chip error */
687 }
688 
READ16_HANDLER(opwolf_cchip_data_r)689 READ16_HANDLER( opwolf_cchip_data_r )
690 {
691 	return cchip_ram[(current_bank * 0x400) + offset];
692 }
693 
694 /*************************************
695  *
696  * C-Chip Tick
697  *
698  *************************************/
699 
cchip_timer(int dummy)700 static void cchip_timer(int dummy)
701 {
702 	/* Update input ports, these are used by both the 68k directly and by the c-chip */
703 	cchip_ram[0x4]=input_port_0_word_r(0,0);
704 	cchip_ram[0x5]=input_port_1_word_r(0,0);
705 
706 	/* Update coins - cchip handles coinage according to dipswitch A */
707 	if (cchip_ram[0x4]!=cchip_last_04)
708 	{
709 		/* Coin slot A */
710 		if (cchip_ram[0x4]&1)
711 		{
712 			cchip_coins++;
713 			if (cchip_coins >= cchip_coins_for_credit_a)
714 			{
715 				cchip_ram[0x53]++;
716 				cchip_ram[0x51]=0x55;
717 				cchip_ram[0x52]=0x55;
718 				cchip_coins=0;
719 			}
720 			coin_counter_w(0, 1);
721 		}
722 
723 		/* Coin slot B */
724 		if (cchip_ram[0x4]&2)
725 		{
726 			cchip_ram[0x53]+=cchip_credit_for_coin_b;
727 			cchip_ram[0x51]=0x55;
728 			cchip_ram[0x52]=0x55;
729 			coin_counter_w(1, 1);
730 		}
731 
732 		if (cchip_ram[0x53]>9)
733 			cchip_ram[0x53]=9;
734 	}
735 	cchip_last_04=cchip_ram[0x4];
736 
737 	/* Service switch */
738 	if (cchip_ram[0x5]!=cchip_last_05)
739 	{
740 		if ((cchip_ram[0x5]&4)==0)
741 		{
742 			cchip_ram[0x53]++;
743 			cchip_ram[0x51]=0x55;
744 			cchip_ram[0x52]=0x55;
745 		}
746 	}
747 	cchip_last_05=cchip_ram[0x5];
748 
749 	/* Cchip handles coin lockout (68k flags error if more than 9 coins) */
750 	coin_lockout_w(1, cchip_ram[0x53]==9);
751 	coin_lockout_w(0, cchip_ram[0x53]==9);
752 	coin_counter_w(0, 0);
753 	coin_counter_w(1, 0);
754 
755 	/* These variables are cleared every frame during attract mode and the intro. */
756 	if (cchip_ram[0x34] < 2)
757 	{
758 		updateDifficulty(0);
759 		cchip_ram[0x76] = 0;
760 		cchip_ram[0x75] = 0;
761 		cchip_ram[0x74] = 0;
762 		cchip_ram[0x72] = 0;
763 		cchip_ram[0x71] = 0;
764 		cchip_ram[0x70] = 0;
765 		cchip_ram[0x66] = 0;
766 		cchip_ram[0x2b] = 0;
767 		cchip_ram[0x30] = 0;
768 		cchip_ram[0x31] = 0;
769 		cchip_ram[0x32] = 0;
770 		cchip_ram[0x27] = 0;
771 		c588 = 0;
772 		c589 = 0;
773 		c58a = 0;
774 	}
775 
776 	/* The unprotected Operation Wolf (prototype) shows the game sets up a special thread function specific to each level of the game.
777 	This includes the end of level check as different levels have different rules.  In the protected version this logic is moved
778 	to the c-chip, so we simulate it here.
779 	*/
780 	if (cchip_ram[0x1c] == 0 && cchip_ram[0x1d] == 0 && cchip_ram[0x1e] == 0 && cchip_ram[0x1f] == 0 && cchip_ram[0x20] == 0)
781 	{
782 		/* Special handling for end of level 6 */
783 		if (cchip_ram[0x1b] == 0x6)
784 		{
785 			/* Don't signal end of level until final boss is destroyed */
786 			if (cchip_ram[0x27] == 0x1)
787 				cchip_ram[0x32] = 1;
788 		}
789 		/* Level 2 - Boss check - cross-referenced from logic at 0x91CE in OpWolfP
790 		When all enemies are destroyed c-chip signals function 4 in the level function table, which
791 		starts the 'WARNING' sequences for the boss.
792 		*/
793 		else if (cchip_ram[0x1b] == 0x2)
794 		{
795 			if (triggeredLevel2==0 && cchip_ram[0x5f]==0) /* Don't write unless 68K is ready (0 at 0x5f) */
796 		    {
797  			    cchip_ram[0x5f] = 4; /* 0xBE at 68K side */
798 				triggeredLevel2=1;
799 			}
800 
801 			/* When the level 2 boss has been defeated the 68K will write 0xff to $ff0ba.l - this should signal
802 			the c-chip to start the end of level routine.  See code at 0xC370 in OpWolf and 0x933e in OpWolfP
803 			*/
804 			if (triggeredLevel2 && cchip_ram[0x5d]!=0)
805 			{
806 			/* Signal end of level */
807  			cchip_ram[0x32] = 1;
808 			cchip_ram[0x5d] = 0; /* acknowledge 68K command */
809 			}
810 		}
811 		else if (cchip_ram[0x1b] == 0x4)
812 		{
813 			cchip_ram[0x32] = 1;
814 
815 		/* When level 4 (powder magazine) is complete the c-chip triggers an explosion animation. */
816 			if (triggeredLevel4==0 && cchip_ram[0x5f]==0) /* Don't write unless 68K is ready (0 at 0x5f)) */
817 			{
818 				cchip_ram[0x5f]=10;
819 			    triggeredLevel4=1;
820 			}
821 		}
822 		else
823 		{
824 			/* Signal end of level */
825 			cchip_ram[0x32] = 1;
826 		}
827 	}
828 
829 	/* When all men are destroyed (not necessarily vehicles) the enemy look up table changes
830 	Reference functions around 0x96A4 in the unprotected prototype.
831     Level 1 has a specific table.
832 	Level 3 has an additional flag set
833 	*/
834 	if (cchip_ram[0x1c] == 0 && cchip_ram[0x1d] == 0)
835 	{
836 		/* Compare code at 0x96DC in prototype with 0xC3A2 in protected version */
837 		if (cchip_ram[0x1b] == 0x1 && triggeredLevel1b==0 && cchip_ram[0x5f]==0) /* Don't write unless 68K is ready (0 at 0x5f)) */
838 		{
839 			cchip_ram[0x5f]=7;
840 			triggeredLevel1b=1;
841 		}
842 
843 		/* Compare code at 0x96BC in prototype with 0xC3B2 in protected version */
844 		if (cchip_ram[0x1b] == 0x3 && triggeredLevel3b==0 && cchip_ram[0x5f]==0) /* Don't write unless 68K is ready (0 at 0x5f)) */
845 		{
846 			cchip_ram[0x5f]=8;
847 			triggeredLevel3b=1;
848 		}
849 
850 		/* Compare code at 0x96BC in prototype with 0xC3C8 in protected version */
851 		if ((cchip_ram[0x1b] != 0x1 && cchip_ram[0x1b] != 0x3) && triggeredLevel13b==0 && cchip_ram[0x5f]==0) /* Don't write unless 68K is ready (0 at 0x5f)) */
852 		{
853 			cchip_ram[0x5f]=9;
854 			triggeredLevel13b=1;
855 		}
856 	}
857 
858 	/*-------------------------------------------------------------------------------------------------
859 	Level 2.  On level 2 specifically when there are less than 45 men left the enemy lookup table is
860 	switched.  This drops down a wave of paratroopers.  When there are less than 25 men left the lookup
861 	table is switched again.
862 	See code at 0xC37A and 0xc390 in protected version against 0x9648 in prototype.
863 	*/
864 	if (cchip_ram[0x1b] == 0x2)
865 	{
866 		/* (Note:  it's correct that 25 decimal is represented as 0x25 in hex here). */
867 		int numMen=(cchip_ram[0x1d]<<8) + cchip_ram[0x1c];
868 		if (numMen<0x25 && triggeredLevel2b==1 && triggeredLevel2c==0 && cchip_ram[0x5f]==0) /* Don't write unless 68K is ready (0 at 0x5f)) */
869 		{
870 			cchip_ram[0x5f]=6;
871 			triggeredLevel2c=1;
872 		}
873 
874 		/* (Note:  it's correct that 45 decimal is represented as 0x45 in hex here). */
875 		if (numMen<0x45 && triggeredLevel2b==0 && cchip_ram[0x5f]==0) /* Don't write unless 68K is ready (0 at 0x5f)) */
876 		{
877 			cchip_ram[0x5f]=5;
878 			triggeredLevel2b=1;
879 		}
880 	}
881 
882 	/*-------------------------------------------------------------------------------------------------
883 	Level 5
884 	*/
885 	if (cchip_ram[0x1b] == 0x5)
886 	{
887 		/* When all men are destroyed (not necessarily vehicles), the c-chip writes 1 to location
888 		0x2f to spawn a thread that scrolls the screen upwards to focus on the helicopter
889 		enemies.  The 68K acknowledges this by writing 2 to 0x2f.
890 		See code at 0x4ED6 in prototype and 0x687e in original.
891 		*/
892 		if (cchip_ram[0x1c] == 0 && cchip_ram[0x1d] == 0 && triggeredLevel5==0)
893 		{
894 			cchip_ram[0x2f] = 1;
895 			triggeredLevel5 = 1;
896 		}
897 	}
898 
899 	/*-------------------------------------------------------------------------------------------------
900 	Level 6
901 	*/
902 	if (cchip_ram[0x1b] == 0x6)
903 	{
904 		/* Check for triggering final helicopter (end boss) */
905 		if (c58a == 0)
906 		{
907 			if ((cchip_ram[0x72] & 0x7f) >= 8 && cchip_ram[0x74] == 0 && cchip_ram[0x1c] == 0 && cchip_ram[0x1d] == 0 && cchip_ram[0x1f] == 0)
908 			{
909 				cchip_ram[0x30] = 1;
910 				cchip_ram[0x74] = 1;
911 				c58a = 1;
912 			}
913 		}
914 
915 		if (cchip_ram[0x1a] == 0x90)
916 			cchip_ram[0x74] = 0;
917 
918 		if (c58a != 0)
919 		{
920 			if (c589 == 0 && cchip_ram[0x27] == 0 && cchip_ram[0x75] == 0 && cchip_ram[0x1c] == 0 && cchip_ram[0x1d] == 0 && cchip_ram[0x1e] == 0 && cchip_ram[0x1f] == 0)
921 			{
922 				cchip_ram[0x31] = 1;
923 				cchip_ram[0x75] = 1;
924 				c589 = 1;
925 			}
926 		}
927 
928 		if (cchip_ram[0x2b] == 0x1)
929 		{
930 			cchip_ram[0x2b] = 0;
931 
932 			if (cchip_ram[0x30] == 0x1)
933 			{
934 				if (cchip_ram[0x1a] != 0x90)
935 					cchip_ram[0x1a]--;
936 			}
937 
938 			if (cchip_ram[0x72] == 0x9)
939 			{
940 				if (cchip_ram[0x76] != 0x4)
941 				{
942 					cchip_ram[0x76] = 3;
943 				}
944 			}
945 			else
946 			{
947 				/* This timer is derived from the bootleg rather than the real board, I'm not 100% sure about it */
948 				c588 |= 0x80;
949 
950 				cchip_ram[0x72] = c588;
951 				c588++;
952 
953 				cchip_ram[0x1a]--;
954 				cchip_ram[0x1a]--;
955 				cchip_ram[0x1a]--;
956 			}
957 		}
958 
959 		/* Update difficulty settings */
960 		if (cchip_ram[0x76] == 0)
961 		{
962 			cchip_ram[0x76] = 1;
963 			updateDifficulty(1);
964 		}
965 	}
966 
967 	/*-------------------------------------------------------------------------------------------------
968 	Start of level 7 - should trigger '1' in level thread table (compare 0xC164 in protected to 0x9468 in unprotected) */
969 	if (cchip_ram[0x1b] == 0x7 && triggeredLevel7==0 && cchip_ram[0x5f]==0) /* Don't write unless 68K is ready (0 at 0x5f)) */
970 	{
971 		triggeredLevel7 = 1;
972 		cchip_ram[0x5f] = 1;
973 	}
974 
975 	/*-------------------------------------------------------------------------------------------------
976 	Start of level 8 - should trigger '2' in level thread table (compare 0xC18E in protected to 0x9358 in unprotected)
977 	This controls the 'zoom in helicopters' enemy
978 	*/
979 	if (cchip_ram[0x1b] == 0x8 && triggeredLevel8==0 && cchip_ram[0x5f]==0) /* Don't write unless 68K is ready (0 at 0x5f)) */
980 	{
981 		triggeredLevel8 = 1;
982 		cchip_ram[0x5f] = 2;
983 	}
984 
985 	/*-------------------------------------------------------------------------------------------------
986 	Start of level 9 - should trigger '3' in level thread table (compare 0xC1B0 in protected to 0x9500 in unprotected)
987 	This controls the 'zoom in helicopters' enemy
988 	*/
989 	if (cchip_ram[0x1b] == 0x9 && triggeredLevel9==0 && cchip_ram[0x5f]==0) /* Don't write unless 68K is ready (0 at 0x5f)) */
990 	{
991 		triggeredLevel9 = 1;
992 		cchip_ram[0x5f] = 3;
993 	}
994 
995 	if (cchip_ram[0xe] == 1)
996 	{
997 		cchip_ram[0xe] = 0xfd;
998 		cchip_ram[0x61] = 0x04;
999 	}
1000 
1001 	/* Access level data command (address 0xf5 goes from 1 -> 0) */
1002 	if (cchip_ram[0x7a] == 0 && cchip_last_7a != 0 && current_cmd != 0xf5)
1003 	{
1004 		/* Simulate time for command to execute (exact timing unknown, this is close) */
1005 		current_cmd = 0xf5;
1006 		timer_set(TIME_IN_CYCLES(80000,0), 0, timer_callback);
1007 	}
1008 	cchip_last_7a = cchip_ram[0x7a];
1009 
1010 	/* This seems to some kind of periodic counter - results are expected
1011 	by the 68k when the counter reaches 0xa
1012 	*/
1013 	if (cchip_ram[0x7f] == 0xa)
1014 	{
1015 		cchip_ram[0xfe] = 0xf7;
1016 		cchip_ram[0xff] = 0x6e;
1017 	}
1018 
1019 	/* These are set every frame */
1020 	cchip_ram[0x64] = 0;
1021 	cchip_ram[0x66] = 0;
1022 }
1023 
1024 
1025 
1026 /*************************************
1027  *
1028  * C-Chip State Saving
1029  *
1030  *************************************/
1031 
opwolf_cchip_init(void)1032 void opwolf_cchip_init(void)
1033 {
1034 	cchip_ram=auto_malloc(0x400 * 8);
1035 
1036 	state_save_register_UINT8("opwolf", 0, "cc_bank", &current_bank, 1);
1037 	state_save_register_UINT8("opwolf", 0, "cc_data", &current_cmd, 1);
1038 	state_save_register_UINT8("opwolf", 0, "7a", &cchip_last_7a, 1);
1039 	state_save_register_UINT8("opwolf", 0, "04", &cchip_last_04, 1);
1040 	state_save_register_UINT8("opwolf", 0, "05", &cchip_last_05, 1);
1041 	state_save_register_UINT8("opwolf", 0, "c588", &c588, 1);
1042 	state_save_register_UINT8("opwolf", 0, "c589", &c589, 1);
1043 	state_save_register_UINT8("opwolf", 0, "c58a", &c58a, 1);
1044 	state_save_register_UINT8("opwolf", 0, "cc", &cchip_coins, 1);
1045 	state_save_register_UINT8("opwolf", 0, "ca", &cchip_coins_for_credit_a, 1);
1046 	state_save_register_UINT8("opwolf", 0, "cb", &cchip_credit_for_coin_b, 1);
1047 	state_save_register_UINT8("opwolf", 0, "1b", &triggeredLevel1b, 1);
1048 	state_save_register_UINT8("opwolf", 0, "2",  &triggeredLevel2, 1);
1049 	state_save_register_UINT8("opwolf", 0, "2b", &triggeredLevel2b, 1);
1050 	state_save_register_UINT8("opwolf", 0, "2c", &triggeredLevel2c, 1);
1051 	state_save_register_UINT8("opwolf", 0, "3b", &triggeredLevel3b, 1);
1052 	state_save_register_UINT8("opwolf", 0, "13b",&triggeredLevel13b, 1);
1053     state_save_register_UINT8("opwolf", 0, "4",  &triggeredLevel4, 1);
1054 	state_save_register_UINT8("opwolf", 0, "5",  &triggeredLevel5, 1);
1055 	state_save_register_UINT8("opwolf", 0, "7",  &triggeredLevel7, 1);
1056 	state_save_register_UINT8("opwolf", 0, "8",  &triggeredLevel8, 1);
1057 	state_save_register_UINT8("opwolf", 0, "9",  &triggeredLevel9, 1);
1058 	state_save_register_UINT8("opwolf", 0, "cc_ram", cchip_ram, 0x400 * 8);
1059 
1060 	triggeredLevel1b = 0;
1061 	triggeredLevel2 = 0;
1062 	triggeredLevel2b = 0;
1063 	triggeredLevel2c = 0;
1064 	triggeredLevel3b = 0;
1065 	triggeredLevel13b = 0;
1066 	triggeredLevel4 = 0;
1067 	triggeredLevel5 = 0;
1068 	triggeredLevel7 = 0;
1069 	triggeredLevel8 = 0;
1070 	triggeredLevel9 = 0;
1071 	cchip_last_7a=0;
1072 	cchip_last_04=0xfc;
1073 	cchip_last_05=0xff;
1074 	cchip_coins=0;
1075 	cchip_coins_for_credit_a=1;
1076 	cchip_credit_for_coin_b=2;
1077 
1078 	timer_pulse(TIME_IN_HZ(60), 0, cchip_timer);
1079 }
1080