mame/src/mame/machine/opwolf.c
2007-12-18 08:09:03 +00:00

752 lines
24 KiB
C

/*************************************************************************
Operation Wolf C-Chip Protection
================================
The C-Chip (Taito TC0030CMD) is an unidentified mask programmed
microcontroller of some sort with 64 pins. It probably has
about 2k of ROM and 8k of RAM.
Interesting memory locations shared by cchip/68k:
14 - dip switch A (written by 68k at start)
15 - dip switch B (written by 68k at start)
1b - Current level number (1-6)
1c - Number of men remaining in level
1e - Number of helicopters remaining in level
1f - Number of tanks remaining in level
20 - Number of boats remaining in level
21 - Hostages in plane (last level)
22 - Hostages remaining (last level)/Hostages saved (2nd last level)#
27 - Set to 1 when final boss is destroyed
32 - Set to 1 by cchip when level complete (no more enemies remaining)
34 - Game state (0=attract mode, 1=intro, 2=in-game, 3=end-screen)
51/52 - Used by cchip to signal change in credit level to 68k
53 - Credit count
75 - Set to 1 to trigger end of game boss
7a - Used to trigger level data select command
Notes on bootleg c-chip:
Bootleg cchip forces english language mode
Bootleg forces round 4 in attract mode
Bootleg doesn't support service switch
If you die after round 6 then the bootleg fails to reset the difficulty
for the next game.
*************************************************************************/
#include "driver.h"
/* Select how coinage data is initialised in opwolf_cchip_data_w : 0 = user-defined in function - 1 = automatic */
#define OPWOLF_READ_COINAGE_FROM_ROM 1
/* List of possible regions */
enum {
OPWOLF_REGION_BAD=0,
OPWOLF_REGION_JAPAN,
OPWOLF_REGION_US,
OPWOLF_REGION_WORLD,
OPWOLF_REGION_OTHER
};
extern int opwolf_region;
static UINT8 current_bank=0;
static UINT8 current_cmd=0;
static UINT8* cchip_ram=0;
static UINT8 cchip_last_7a=0;
static UINT8 cchip_last_04=0;
static UINT8 cchip_last_05=0;
static UINT8 cchip_coins_for_credit[2]={1,1};
static UINT8 cchip_credits_for_coin[2]={1,1};
static UINT8 cchip_coins[2]={0,0};
static UINT8 c588=0, c589=0, c58a=0; // These variables derived from the bootleg
static const UINT16 level_data_00[0xcc] =
{
0x0480,0x1008,0x0300,0x5701,0x0001,0x0010,0x0480,0x1008,
0x0300,0x5701,0x0001,0x002b,0x0780,0x0009,0x0300,0x4a01,
0x0004,0x0020,0x0780,0x1208,0x0300,0x5d01,0x0004,0x0030,
0x0780,0x0209,0x0300,0x4c01,0x0004,0x0038,0x0780,0x0309,
0x0300,0x4d01,0x0004,0x0048,0x0980,0x1108,0x0300,0x5a01,
0xc005,0x0018,0x0980,0x0109,0x0300,0x4b01,0xc005,0x0028,
0x0b80,0x020a,0x0000,0x6401,0x8006,0x0004,0x0c80,0x010b,
0x0000,0xf201,0x8006,0x8002,0x0b80,0x020a,0x0000,0x6401,
0x8006,0x0017,0x0c80,0x010b,0x0000,0xf201,0x8006,0x8015,
0x0b80,0x020a,0x0000,0x6401,0x0007,0x0034,0x0c80,0x010b,
0x0000,0xf201,0x0007,0x8032,0x0b80,0x020a,0x0000,0x6401,
0x8006,0x803e,0x0c80,0x010b,0x0000,0xf201,0x8006,0x803d,
0x0b80,0x100a,0x0000,0x6001,0x0007,0x0008,0x0b80,0x100a,
0x0000,0x6001,0x0007,0x000b,0x0b80,0x100a,0x0000,0x6001,
0x0007,0x001b,0x0b80,0x100a,0x0000,0x6001,0x0007,0x001e,
0x0b80,0x100a,0x0000,0x6001,0x8007,0x0038,0x0b80,0x100a,
0x0000,0x6001,0x8007,0x003b,0x0b80,0x100a,0x0000,0x6001,
0x0007,0x8042,0x0b80,0x100a,0x0000,0x6001,0x0007,0x8045,
0x0c80,0x000b,0x0000,0xf101,0x800b,0x8007,0x0c80,0x000b,
0x0000,0xf101,0x800b,0x801a,0x0c80,0x000b,0x0000,0xf101,
0x000c,0x8037,0x0c80,0x000b,0x0000,0xf101,0x800b,0x0042,
0x0c80,0xd04b,0x0000,0xf301,0x8006,0x8009,0x0c80,0xd04b,
0x0000,0xf301,0x8006,0x801c,0x0c80,0xd04b,0x0000,0xf301,
0x8006,0x0044,0x0c80,0x030b,0x0000,0xf401,0x0008,0x0028,
0x0c80,0x030b,0x0000,0xf401,0x0008,0x804b,0x0c00,0x040b,
0x0000,0xf501,0x0008,0x8026
};
static const UINT16 level_data_01[0xcc] =
{
0x0780,0x0209,0x0300,0x4c01,0x0004,0x0010,0x0780,0x0209,
0x0300,0x4c01,0x4004,0x0020,0x0780,0x0309,0x0300,0x4d01,
0xe003,0x0030,0x0780,0x0309,0x0300,0x4d01,0x8003,0x0040,
0x0780,0x0209,0x0300,0x4c01,0x8004,0x0018,0x0780,0x0309,
0x0300,0x4d01,0xc003,0x0028,0x0b80,0x000b,0x0000,0x0b02,
0x8009,0x0029,0x0b80,0x0409,0x0000,0x0f02,0x8008,0x8028,
0x0b80,0x040a,0x0000,0x3502,0x000a,0x8028,0x0b80,0x050a,
0x0000,0x1002,0x8006,0x8028,0x0b80,0x120a,0x0000,0x3602,
0x0008,0x004d,0x0b80,0x120a,0x0000,0x3602,0x0008,0x004f,
0x0b80,0x120a,0x0000,0x3602,0x0008,0x0001,0x0b80,0x120a,
0x0000,0x3602,0x0008,0x0003,0x0b80,0x130a,0x0000,0x3a02,
0x0007,0x0023,0x0b80,0x130a,0x0000,0x3a02,0x0007,0x8025,
0x0b80,0x130a,0x0000,0x3a02,0x8009,0x0023,0x0b80,0x130a,
0x0000,0x3a02,0x8009,0x8025,0x0b80,0x140a,0x0000,0x3e02,
0x0007,0x000d,0x0b80,0x140a,0x0000,0x3e02,0x0007,0x800f,
0x0b80,0x000b,0x0000,0x0102,0x0007,0x804e,0x0b80,0xd24b,
0x0000,0x0302,0x0007,0x000e,0x0b80,0x000b,0x0000,0x0402,
0x8006,0x0020,0x0b80,0xd34b,0x0000,0x0502,0x8006,0x0024,
0x0b80,0x000b,0x0000,0x0602,0x8009,0x0001,0x0b80,0xd44b,
0x0000,0x0702,0x800b,0x800b,0x0b80,0xd54b,0x0000,0x0802,
0x800b,0x000e,0x0b80,0x000b,0x0000,0x0902,0x800b,0x0010,
0x0b80,0x000b,0x0000,0x0a02,0x0009,0x0024,0x0b80,0xd64b,
0x0000,0x0c02,0x000c,0x8021,0x0b80,0x000b,0x0000,0x0d02,
0x000c,0x0025,0x0b80,0x000b,0x0000,0x0e02,0x8009,0x004e,
0x0b80,0x0609,0x0300,0x4e01,0x8006,0x8012,0x0b80,0x0609,
0x0300,0x4e01,0x0007,0x8007
};
static const UINT16 level_data_02[0xcc] =
{
0x0480,0x000b,0x0300,0x4501,0x0001,0x0018,0x0480,0x000b,
0x0300,0x4501,0x2001,0x0030,0x0780,0x1208,0x0300,0x5d01,
0x0004,0x0010,0x0780,0x1208,0x0300,0x5d01,0x2004,0x001c,
0x0780,0x1208,0x0300,0x5d01,0xe003,0x0026,0x0780,0x1208,
0x0300,0x5d01,0x8003,0x0034,0x0780,0x1208,0x0300,0x5d01,
0x3004,0x0040,0x0780,0x010c,0x0300,0x4601,0x4004,0x0022,
0x0780,0x010c,0x0300,0x4601,0x6004,0x0042,0x0780,0x000c,
0x0500,0x7b01,0x800b,0x0008,0x0780,0x010c,0x0300,0x4601,
0x2004,0x0008,0x0000,0x0000,0x0000,0xf001,0x0000,0x0000,
0x0000,0x0000,0x0000,0xf001,0x0000,0x0000,0x0000,0x0000,
0x0000,0xf001,0x0000,0x0000,0x0b80,0x000b,0x0000,0x1902,
0x000b,0x0004,0x0b80,0x000b,0x0000,0x1a02,0x0009,0x8003,
0x0b80,0x000b,0x0000,0x1902,0x000b,0x000c,0x0b80,0x000b,
0x0000,0x1a02,0x0009,0x800b,0x0b80,0x000b,0x0000,0x1902,
0x000b,0x001c,0x0b80,0x000b,0x0000,0x1a02,0x0009,0x801b,
0x0b80,0x000b,0x0000,0x1902,0x000b,0x002c,0x0b80,0x000b,
0x0000,0x1a02,0x0009,0x802b,0x0b80,0x000b,0x0000,0x1902,
0x000b,0x0044,0x0b80,0x000b,0x0000,0x1a02,0x0009,0x8043,
0x0b80,0x000b,0x0000,0x1902,0x000b,0x004c,0x0b80,0x000b,
0x0000,0x1a02,0x0009,0x804b,0x0b80,0x020c,0x0300,0x4801,
0xa009,0x0010,0x0b80,0x020c,0x0300,0x4801,0xa009,0x0028,
0x0b80,0x020c,0x0300,0x4801,0xa009,0x0036,0x0000,0x0000,
0x0000,0xf001,0x0000,0x0000,0x0000,0x0000,0x0000,0xf001,
0x0000,0x0000,0x0000,0x0000,0x0000,0xf001,0x0000,0x0000,
0x0000,0x0000,0x0000,0xf001,0x0000,0x0000,0x0000,0x0000,
0x0000,0xf001,0x0000,0x0000
};
static const UINT16 level_data_03[0xcc] =
{
0x0480,0x000b,0x0300,0x4501,0x0001,0x0018,0x0480,0x000b,
0x0300,0x4501,0x2001,0x002b,0x0780,0x010c,0x0300,0x4601,
0x0004,0x000d,0x0780,0x000c,0x0500,0x7b01,0x800b,0x0020,
0x0780,0x010c,0x0300,0x4601,0x2004,0x0020,0x0780,0x010c,
0x0300,0x4601,0x8003,0x0033,0x0780,0x010c,0x0300,0x4601,
0x0004,0x003c,0x0780,0x010c,0x0300,0x4601,0xd003,0x0045,
0x0780,0x000c,0x0500,0x7b01,0x900b,0x0041,0x0780,0x010c,
0x0300,0x4601,0x3004,0x0041,0x0b80,0x020c,0x0300,0x4801,
0x0007,0x0000,0x0b80,0x410a,0x0000,0x2b02,0xe006,0x4049,
0x0b80,0x020c,0x0300,0x4801,0x8007,0x000b,0x0b80,0x000b,
0x0000,0x2702,0x800a,0x8005,0x0b80,0x000b,0x0000,0x1e02,
0x0008,0x800e,0x0b80,0x000b,0x0000,0x1f02,0x8007,0x0011,
0x0b80,0x000b,0x0000,0x2802,0x000b,0x0012,0x0b80,0x000b,
0x0000,0x2002,0x0007,0x8015,0x0b80,0x000b,0x0000,0x2102,
0x0007,0x801b,0x0b80,0x000b,0x0000,0x2902,0x800a,0x001a,
0x0b80,0x000b,0x0000,0x2202,0x8007,0x001e,0x0b80,0x000b,
0x0000,0x1e02,0x0008,0x0025,0x0b80,0x000b,0x0000,0x2302,
0x8007,0x802c,0x0b80,0x000b,0x0000,0x2802,0x000b,0x8028,
0x0b80,0x020c,0x0300,0x4801,0x0007,0x0030,0x0b80,0x400a,
0x0000,0x2e02,0x4007,0x002d,0x0b80,0x000b,0x0000,0x2702,
0x800a,0x8035,0x0b80,0x020c,0x0300,0x4801,0x8007,0x0022,
0x0b80,0x000b,0x0000,0x2402,0x8007,0x0047,0x0b80,0x000b,
0x0000,0x2a02,0x800a,0x004b,0x0b80,0x000b,0x0000,0x2502,
0x0007,0x804b,0x0b80,0x000b,0x0000,0x2602,0x0007,0x004e,
0x0b80,0x020c,0x0300,0x4801,0x0007,0x8043,0x0b80,0x020c,
0x0300,0x4801,0x8007,0x803d
};
static const UINT16 level_data_04[0xcc] =
{
0x0780,0x0209,0x0300,0x4c01,0x0004,0x0010,0x0780,0x0209,
0x0300,0x4c01,0x4004,0x0020,0x0780,0x0309,0x0300,0x4d01,
0xe003,0x0030,0x0780,0x0309,0x0300,0x4d01,0x8003,0x0040,
0x0780,0x0209,0x0300,0x4c01,0x8004,0x0018,0x0780,0x0309,
0x0300,0x4d01,0xc003,0x0028,0x0780,0x000b,0x0300,0x5601,
0x8004,0x0008,0x0780,0x000b,0x0300,0x5601,0x8004,0x0038,
0x0780,0x000b,0x0300,0x5501,0x8004,0x0048,0x0980,0x0509,
0x0f00,0x0f01,0x4005,0x4007,0x0980,0x0509,0x0f00,0x0f01,
0x4005,0x4037,0x0b80,0x030a,0x0000,0x1302,0x8006,0x0040,
0x0b80,0x110a,0x0000,0x1502,0x8008,0x8048,0x0b80,0x110a,
0x0000,0x1502,0x8008,0x8049,0x0b80,0x000b,0x0000,0xf601,
0x0007,0x8003,0x0b80,0x000b,0x0000,0xf701,0x0007,0x0005,
0x0b80,0x000b,0x0000,0xf901,0x0007,0x8008,0x0b80,0x000b,
0x0000,0xf901,0x0007,0x0010,0x0b80,0x000b,0x0000,0xfa01,
0x0007,0x8013,0x0b80,0x000b,0x0000,0xf801,0x800b,0x800b,
0x0b80,0x000b,0x0000,0x0002,0x800b,0x801a,0x0b80,0x000b,
0x0000,0xf901,0x0007,0x8017,0x0b80,0x000b,0x0000,0xfa01,
0x0007,0x001b,0x0b80,0x000b,0x0000,0xf801,0x800b,0x0013,
0x0b80,0x000b,0x0000,0x4202,0x800b,0x0016,0x0b80,0x000b,
0x0000,0xfb01,0x8007,0x8020,0x0b80,0x000b,0x0000,0xf601,
0x0007,0x8023,0x0b80,0x000b,0x0000,0x4202,0x800b,0x800e,
0x0b80,0x000b,0x0000,0x4302,0x800b,0x801d,0x0b80,0x000b,
0x0000,0xf701,0x0007,0x0025,0x0b80,0x000b,0x0000,0xfd01,
0x8006,0x003f,0x0b80,0x000b,0x0000,0xfe01,0x0007,0x0046,
0x0b80,0x000b,0x0000,0xff01,0x8007,0x8049,0x0b80,0x000b,
0x0000,0xfc01,0x8009,0x0042
};
static const UINT16 level_data_05[0xcc] =
{
0x0480,0x1008,0x0300,0x5701,0x0001,0x0010,0x0480,0x1008,
0x0300,0x5701,0x0001,0x002b,0x0780,0x0009,0x0300,0x4a01,
0x0004,0x0020,0x0780,0x1208,0x0300,0x5d01,0x0004,0x0030,
0x0780,0x0209,0x0300,0x4c01,0x0004,0x0038,0x0780,0x0309,
0x0300,0x4d01,0x0004,0x0048,0x0980,0x1108,0x0300,0x5a01,
0xc005,0x0018,0x0980,0x0109,0x0300,0x4b01,0xc005,0x0028,
0x0b80,0x020a,0x0000,0x6401,0x8006,0x0004,0x0c80,0x010b,
0x0000,0xf201,0x8006,0x8002,0x0b80,0x020a,0x0000,0x6401,
0x8006,0x0017,0x0c80,0x010b,0x0000,0xf201,0x8006,0x8015,
0x0b80,0x020a,0x0000,0x6401,0x0007,0x0034,0x0c80,0x010b,
0x0000,0xf201,0x0007,0x8032,0x0b80,0x020a,0x0000,0x6401,
0x8006,0x803e,0x0c80,0x010b,0x0000,0xf201,0x8006,0x803d,
0x0b80,0x100a,0x0000,0x6001,0x0007,0x0008,0x0b80,0x100a,
0x0000,0x6001,0x0007,0x000b,0x0b80,0x100a,0x0000,0x6001,
0x0007,0x001b,0x0b80,0x100a,0x0000,0x6001,0x0007,0x001e,
0x0b80,0x100a,0x0000,0x6001,0x8007,0x0038,0x0b80,0x100a,
0x0000,0x6001,0x8007,0x003b,0x0b80,0x100a,0x0000,0x6001,
0x0007,0x8042,0x0b80,0x100a,0x0000,0x6001,0x0007,0x8045,
0x0c80,0x000b,0x0000,0xf101,0x800b,0x8007,0x0c80,0x000b,
0x0000,0xf101,0x800b,0x801a,0x0c80,0x000b,0x0000,0xf101,
0x000c,0x8037,0x0c80,0x000b,0x0000,0xf101,0x800b,0x0042,
0x0c80,0xd04b,0x0000,0xf301,0x8006,0x8009,0x0c80,0xd04b,
0x0000,0xf301,0x8006,0x801c,0x0c80,0xd04b,0x0000,0xf301,
0x8006,0x0044,0x0c80,0x030b,0x0000,0xf401,0x0008,0x0028,
0x0c80,0x030b,0x0000,0xf401,0x0008,0x804b,0x0c00,0x040b,
0x0000,0xf501,0x0008,0x8026
};
static const UINT16 level_data_06[0xcc] =
{
0x0000,0x1008,0x0300,0x5701,0x0001,0x0010,0x0000,0x1008,
0x0300,0x5701,0x0001,0x002b,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0700,0x0009,0x0300,0x4a01,0x0004,0x0020,
0x0700,0x1208,0x0300,0x5d01,0x0004,0x0030,0x0700,0x0209,
0x0300,0x4c01,0x0004,0x0038,0x0700,0x0309,0x0300,0x4d01,
0x0004,0x0048,0x0900,0x1108,0x0300,0x5a01,0xc005,0x0018,
0x0900,0x0109,0x0300,0x4b01,0xc005,0x0028,0x0000,0x000b,
0x0000,0x0000,0x0018,0x0000,0x0000,0x000b,0x0000,0x0000,
0x0018,0x0000,0x0000,0x000b,0x0000,0x0000,0x0018,0x0000,
0x0000,0x000b,0x0000,0x0000,0x0018,0x0000,0x0000,0x000b,
0x0000,0x0000,0x0018,0x0000,0x0000,0x000b,0x0000,0x0000,
0x0018,0x0000,0x0000,0x000b,0x0000,0x0000,0x0018,0x0000,
0x0000,0x000b,0x0000,0x0000,0x0018,0x0000,0x0000,0x000b,
0x0000,0x0000,0x0018,0x0000,0x0980,0xdb4c,0x0000,0x3202,
0x0006,0x0004,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x8002,
0x0b80,0x0609,0x0300,0x4e01,0x5006,0x8003,0x0b80,0x0609,
0x0300,0x4e01,0x5006,0x8004,0x0b80,0x0609,0x0300,0x4e01,
0x5006,0x0008,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0010,
0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0012,0x0b80,0x0609,
0x0300,0x4e01,0x5006,0x0014,0x0b80,0x0609,0x0300,0x4e01,
0x5006,0x0016,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0018,
0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0020,0x0b80,0x0609,
0x0300,0x4e01,0x5006,0x0023,0x0b80,0x0609,0x0300,0x4e01,
0x5006,0x0030,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0038,
0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0040,0x0b80,0x0609,
0x0300,0x4e01,0x5006,0x0042
};
static const UINT16 *const level_data_lookup[] =
{
level_data_00,
level_data_01,
level_data_02,
level_data_03,
level_data_04,
level_data_05,
level_data_06,
};
static TIMER_CALLBACK( opwolf_timer_callback )
{
// Level data command
if (current_cmd==0xf5)
{
int level=cchip_ram[0x1b];
const UINT16* level_data=level_data_lookup[level];
int i=0;
for (i=0; i<0xcc; i++)
{
cchip_ram[0x200 + i*2 + 0]=level_data[i]>>8;
cchip_ram[0x200 + i*2 + 1]=level_data[i]&0xff;
}
// The bootleg cchip writes 0 to these locations - hard to tell what the real one writes
cchip_ram[0x0]=0;
cchip_ram[0x76]=0;
cchip_ram[0x75]=0;
cchip_ram[0x74]=0;
cchip_ram[0x72]=0;
cchip_ram[0x71]=0;
cchip_ram[0x70]=0;
cchip_ram[0x66]=0;
cchip_ram[0x2b]=0;
cchip_ram[0x30]=0;
cchip_ram[0x31]=0;
cchip_ram[0x32]=0;
cchip_ram[0x27]=0;
c588=0;
c589=0;
c58a=0;
cchip_ram[0x1a]=0;
cchip_ram[0x7a]=1; // Signal command complete
}
current_cmd=0;
}
static void updateDifficulty(int mode)
{
// The game is made up of 6 rounds, when you complete the
// sixth you return to the start but with harder difficulty.
if (mode==0)
{
switch (cchip_ram[0x15]&3) // Dipswitch B
{
case 3:
cchip_ram[0x2c]=0x31;
cchip_ram[0x77]=0x05;
cchip_ram[0x25]=0x0f;
cchip_ram[0x26]=0x0b;
break;
case 0:
cchip_ram[0x2c]=0x20;
cchip_ram[0x77]=0x06;
cchip_ram[0x25]=0x07;
cchip_ram[0x26]=0x03;
break;
case 1:
cchip_ram[0x2c]=0x31;
cchip_ram[0x77]=0x05;
cchip_ram[0x25]=0x0f;
cchip_ram[0x26]=0x0b;
break;
case 2:
cchip_ram[0x2c]=0x3c;
cchip_ram[0x77]=0x04;
cchip_ram[0x25]=0x13;
cchip_ram[0x26]=0x0f;
break;
}
}
else
{
switch (cchip_ram[0x15]&3) // Dipswitch B
{
case 3:
cchip_ram[0x2c]=0x46;
cchip_ram[0x77]=0x05;
cchip_ram[0x25]=0x11;
cchip_ram[0x26]=0x0e;
break;
case 0:
cchip_ram[0x2c]=0x30;
cchip_ram[0x77]=0x06;
cchip_ram[0x25]=0x0b;
cchip_ram[0x26]=0x03;
break;
case 1:
cchip_ram[0x2c]=0x3a;
cchip_ram[0x77]=0x05;
cchip_ram[0x25]=0x0f;
cchip_ram[0x26]=0x09;
break;
case 2:
cchip_ram[0x2c]=0x4c;
cchip_ram[0x77]=0x04;
cchip_ram[0x25]=0x19;
cchip_ram[0x26]=0x11;
break;
};
}
}
/*************************************
*
* Writes to C-Chip - Important Bits
*
*************************************/
WRITE16_HANDLER( opwolf_cchip_status_w )
{
// This is written once after the C-Chip init is complete (and passes)
// We use it to setup some initial state (it's not clear if the real
// c-chip sets this here, or if it's as a side-effect of the other
// init sequence data).
cchip_ram[0x3d]=1;
cchip_ram[0x7a]=1;
updateDifficulty(0);
}
WRITE16_HANDLER( opwolf_cchip_bank_w )
{
current_bank=data&7;
}
WRITE16_HANDLER( opwolf_cchip_data_w )
{
cchip_ram[(current_bank * 0x400) + offset]=data&0xff;
// if (offset!=0x64 && offset!=0x65 && offset!=0x66 && offset!=0x67 && offset!=0x68 && offset!=0x69)
// logerror("%08x: opwolf c write %04x %04x\n", activecpu_get_pc(), offset,data);
if (current_bank == 0)
{
// Dip switch A is written here by the 68k - precalculate the coinage values
// Shouldn't we directly read the values from the ROM area ?
if (offset == 0x14)
{
#if OPWOLF_READ_COINAGE_FROM_ROM
UINT16* rom=(UINT16*)memory_region(REGION_CPU1);
UINT32 coin_table[2]={0,0};
UINT8 coin_offset[2];
int slot;
if ((opwolf_region == OPWOLF_REGION_JAPAN) || (opwolf_region == OPWOLF_REGION_US))
{
coin_table[0] = 0x03ffce;
coin_table[1] = 0x03ffce;
}
if ((opwolf_region == OPWOLF_REGION_WORLD) || (opwolf_region == OPWOLF_REGION_OTHER))
{
coin_table[0] = 0x03ffde;
coin_table[1] = 0x03ffee;
}
coin_offset[0] = 12 - (4 * ((data & 0x30) >> 4));
coin_offset[1] = 12 - (4 * ((data & 0xc0) >> 6));
for (slot=0; slot<2; slot++)
{
if (coin_table[slot])
{
cchip_coins_for_credit[slot] = rom[(coin_table[slot] + coin_offset[slot] + 0) / 2] & 0xff;
cchip_credits_for_coin[slot] = rom[(coin_table[slot] + coin_offset[slot] + 2) / 2] & 0xff;
}
}
#else
if ((opwolf_region == OPWOLF_REGION_JAPAN) || (opwolf_region == OPWOLF_REGION_US))
{
switch (data&0x30) /* table at 0x03ffce.w - 4 * 2 words (coins for credits first) - inverted order */
{
case 0x00: cchip_coins_for_credit[0]=2; cchip_credits_for_coin[0]=3; break;
case 0x10: cchip_coins_for_credit[0]=2; cchip_credits_for_coin[0]=1; break;
case 0x20: cchip_coins_for_credit[0]=1; cchip_credits_for_coin[0]=2; break;
case 0x30: cchip_coins_for_credit[0]=1; cchip_credits_for_coin[0]=1; break;
}
switch (data&0xc0) /* table at 0x03ffce.w - 4 * 2 words (coins for credits first) - inverted order */
{
case 0x00: cchip_coins_for_credit[1]=2; cchip_credits_for_coin[1]=3; break;
case 0x40: cchip_coins_for_credit[1]=2; cchip_credits_for_coin[1]=1; break;
case 0x80: cchip_coins_for_credit[1]=1; cchip_credits_for_coin[1]=2; break;
case 0xc0: cchip_coins_for_credit[1]=1; cchip_credits_for_coin[1]=1; break;
}
}
if ((opwolf_region == OPWOLF_REGION_WORLD) || (opwolf_region == OPWOLF_REGION_OTHER))
{
switch (data&0x30) /* table at 0x03ffde.w - 4 * 2 words (coins for credits first) - inverted order */
{
case 0x00: cchip_coins_for_credit[0]=4; cchip_credits_for_coin[0]=1; break;
case 0x10: cchip_coins_for_credit[0]=3; cchip_credits_for_coin[0]=1; break;
case 0x20: cchip_coins_for_credit[0]=2; cchip_credits_for_coin[0]=1; break;
case 0x30: cchip_coins_for_credit[0]=1; cchip_credits_for_coin[0]=1; break;
}
switch (data&0xc0) /* table at 0x03ffee.w - 4 * 2 words (coins for credits first) - inverted order */
{
case 0x00: cchip_coins_for_credit[1]=1; cchip_credits_for_coin[1]=6; break;
case 0x40: cchip_coins_for_credit[1]=1; cchip_credits_for_coin[1]=4; break;
case 0x80: cchip_coins_for_credit[1]=1; cchip_credits_for_coin[1]=3; break;
case 0xc0: cchip_coins_for_credit[1]=1; cchip_credits_for_coin[1]=2; break;
}
}
#endif
}
// Dip switch B
if (offset == 0x15)
{
updateDifficulty(0);
}
}
}
/*************************************
*
* Reads from C-Chip
*
*************************************/
READ16_HANDLER( opwolf_cchip_status_r )
{
/*
Bit 0x4 = Error signal
Bit 0x1 = Ready signal
*/
return 0x1; /* Return 0x5 for C-Chip error */
}
READ16_HANDLER( opwolf_cchip_data_r )
{
// if (offset!=0x7f && offset!=0x1c && offset!=0x1d && offset!=0x1e && offset!=0x1f && offset!=0x20 && activecpu_get_pc()!=0xc18 && activecpu_get_pc()!=0xc2e && activecpu_get_pc()!=0xc9e && offset!=0x50 && offset!=0x51 && offset!=0x52 && offset!=0x53 && offset!=0x5 && offset!=0x13 && offset!=0x79 && offset!=0x12 && offset!=0x34)
// logerror("%08x: opwolf c read %04x (bank %04x)\n", activecpu_get_pc(), offset, current_bank);
return cchip_ram[(current_bank * 0x400) + offset];
}
/*************************************
*
* C-Chip Tick
*
*************************************/
static TIMER_CALLBACK( cchip_timer )
{
// Update input ports, these are used by both the 68k directly and by the c-chip
cchip_ram[0x4]=readinputportbytag("IN0");
cchip_ram[0x5]=readinputportbytag("IN1");
// Coin slots
if (cchip_ram[0x4]!=cchip_last_04)
{
int slot=-1;
if (cchip_ram[0x4]&1) slot=0;
if (cchip_ram[0x4]&2) slot=1;
if (slot != -1)
{
cchip_coins[slot]++;
if (cchip_coins[slot] >= cchip_coins_for_credit[slot])
{
cchip_ram[0x53]+=cchip_credits_for_coin[slot];
cchip_ram[0x51]=0x55;
cchip_ram[0x52]=0x55;
cchip_coins[slot]-=cchip_coins_for_credit[slot];
}
coin_counter_w(slot, 1);
}
if (cchip_ram[0x53]>9)
cchip_ram[0x53]=9;
}
cchip_last_04=cchip_ram[0x4];
// Service switch
if (cchip_ram[0x5]!=cchip_last_05)
{
if ((cchip_ram[0x5]&4)==0)
{
cchip_ram[0x53]++;
cchip_ram[0x51]=0x55;
cchip_ram[0x52]=0x55;
}
}
cchip_last_05=cchip_ram[0x5];
// Cchip handles coin lockout (68k flags error if more than 9 coins)
coin_lockout_w(1, cchip_ram[0x53]==9);
coin_lockout_w(0, cchip_ram[0x53]==9);
coin_counter_w(0, 0);
coin_counter_w(1, 0);
// Special handling for last level
if (cchip_ram[0x1b]==0x6)
{
// Check for triggering final helicopter (end boss)
if (c58a==0)
{
if ((cchip_ram[0x72]&0x7f) >= 8 && cchip_ram[0x74]==0 && cchip_ram[0x1c]==0 && cchip_ram[0x1d]==0 && cchip_ram[0x1f]==0)
{
cchip_ram[0x30]=1;
cchip_ram[0x74]=1;
c58a=1;
}
}
if (cchip_ram[0x1a]==0x90)
cchip_ram[0x74]=0;
if (c58a!=0)
{
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)
{
cchip_ram[0x31]=1;
cchip_ram[0x75]=1;
c589=1;
}
}
if (cchip_ram[0x2b]==0x1)
{
cchip_ram[0x2b]=0;
if (cchip_ram[0x30]==0x1)
{
if (cchip_ram[0x1a]!=0x90)
cchip_ram[0x1a]--;
}
if (cchip_ram[0x72]==0x9)
{
if (cchip_ram[0x76]!=0x4)
{
cchip_ram[0x76]=3;
}
}
else
{
// This timer is derived from the bootleg rather than the real board, I'm not 100% sure about it
c588|=0x80;
cchip_ram[0x72]=c588;
c588++;
cchip_ram[0x1a]--;
cchip_ram[0x1a]--;
cchip_ram[0x1a]--;
}
}
// Update difficulty settings
if (cchip_ram[0x76]==0)
{
cchip_ram[0x76]=1;
updateDifficulty(1);
}
}
// These variables are cleared every frame during attract mode and the intro.
if (cchip_ram[0x34] < 2)
{
updateDifficulty(0);
cchip_ram[0x76]=0;
cchip_ram[0x75]=0;
cchip_ram[0x74]=0;
cchip_ram[0x72]=0;
cchip_ram[0x71]=0;
cchip_ram[0x70]=0;
cchip_ram[0x66]=0;
cchip_ram[0x2b]=0;
cchip_ram[0x30]=0;
cchip_ram[0x31]=0;
cchip_ram[0x32]=0;
cchip_ram[0x27]=0;
c588=0;
c589=0;
c58a=0;
}
// Check for level completion (all enemies destroyed)
if (cchip_ram[0x1c] == 0 && cchip_ram[0x1d] == 0 && cchip_ram[0x1e] == 0 && cchip_ram[0x1f] == 0 && cchip_ram[0x20] == 0)
{
// Special handling for end of level 6
if (cchip_ram[0x1b]==0x6)
{
// Don't signal end of level until final boss is destroyed
if (cchip_ram[0x27]==0x1)
cchip_ram[0x32]=1;
}
else
{
// Signal end of level
cchip_ram[0x32]=1;
}
}
if (cchip_ram[0xe] == 1)
{
cchip_ram[0xe]=0xfd;
cchip_ram[0x61]=0x04;
}
// Access level data command (address 0xf5 goes from 1 -> 0)
if (cchip_ram[0x7a]==0 && cchip_last_7a!=0 && current_cmd!=0xf5)
{
// Simulate time for command to execute (exact timing unknown, this is close)
current_cmd=0xf5;
timer_set(ATTOTIME_IN_CYCLES(80000,0), NULL, 0, opwolf_timer_callback);
}
cchip_last_7a=cchip_ram[0x7a];
// This seems to some kind of periodic counter - results are expected
// by the 68k when the counter reaches 0xa
if (cchip_ram[0x7f]==0xa)
{
cchip_ram[0xfe]=0xf7;
cchip_ram[0xff]=0x6e;
}
// These are set every frame
cchip_ram[0x64]=0;
cchip_ram[0x66]=0;
}
/*************************************
*
* C-Chip State Saving
*
*************************************/
void opwolf_cchip_init(void)
{
cchip_ram=auto_malloc(0x400 * 8);
state_save_register_global(current_bank);
state_save_register_global(current_cmd);
state_save_register_global(cchip_last_7a);
state_save_register_global(cchip_last_04);
state_save_register_global(cchip_last_05);
state_save_register_global(c588);
state_save_register_global(c589);
state_save_register_global(c58a);
state_save_register_global(cchip_coins[0]);
state_save_register_global(cchip_coins[1]);
state_save_register_global(cchip_coins_for_credit[0]);
state_save_register_global(cchip_credits_for_coin[0]);
state_save_register_global(cchip_coins_for_credit[1]);
state_save_register_global(cchip_credits_for_coin[1]);
state_save_register_global_pointer(cchip_ram, 0x400 * 8);
cchip_last_7a=0;
cchip_last_04=0xfc;
cchip_last_05=0xff;
cchip_coins[0]=0;
cchip_coins[1]=0;
cchip_coins_for_credit[0]=1;
cchip_credits_for_coin[0]=1;
cchip_coins_for_credit[1]=1;
cchip_credits_for_coin[1]=1;
timer_pulse(ATTOTIME_IN_HZ(60), NULL, 0, cchip_timer);
}