/***************************************************************************

  machine.c

  Street Heat runs on the same type board as theglobp. It features 4 decryption algorythms
that can be implemented sequentially using the IN command. See machine\theglobp.c for more
details.  The advantage of this is weak sections can be isolated.  The key that contains the
text is obviously easily broken as is the boot section.  The remaining 2 keys are not used
much which means there's not much data to look at.  Knowing the last command in a section
will be IN is enough of a clue to break it though.

  This system is fairly effective in preventing decrypted roms.  Certain key addresses are
read in all 4 states. That is easily patched, but in at least some of the games encrypted
program code is read in the wrong key as data and used as sound data.  A
plaintext version of the roms produces things like 30 second long coinup sounds.

  - David Widel (d_widel@hotmail.com)

***************************************************************************/

#include "driver.h"
#include "includes/dkong.h"

static void strtheat_decrypt_rom_8(void)
{
	int oldbyte,inverted_oldbyte,newbyte;
	int mem;
	UINT8 *RAM;

	RAM = memory_region(REGION_CPU1);


	for (mem=0;mem<0x4000;mem++)
	{
		oldbyte = RAM[mem];
		inverted_oldbyte = ~oldbyte;

		/*  Note: D2 is inverted and connected to D1, D5 is inverted and
            connected to D0.  The other six data bits are converted by a
            PAL10H8 driven by the counter. */
		newbyte = 0;

		/*  start  c  */
		newbyte  = (inverted_oldbyte & 0x80) >> 3;
		newbyte |= (inverted_oldbyte & 0x40) >> 0;
		newbyte |= (inverted_oldbyte & 0x20) >> 5;
		newbyte |= (inverted_oldbyte & 0x10) >> 2;
		newbyte |= (inverted_oldbyte & 0x08) >> 0;
		newbyte |= (inverted_oldbyte & 0x04) >> 1;
		newbyte |= (oldbyte & 0x02) << 4;
		newbyte |= (oldbyte & 0x01) << 7;

		RAM[mem + 0x10000] = newbyte;
	}
}

static void strtheat_decrypt_rom_9(void)
{
	int oldbyte,inverted_oldbyte,newbyte;
	int mem;
	UINT8 *RAM;

	RAM = memory_region(REGION_CPU1);

	for (mem=0;mem<0x4000;mem++)
	{
		oldbyte = RAM[mem];
		inverted_oldbyte = ~oldbyte;

		/*  Note: D2 is inverted and connected to D1, D5 is inverted and
            connected to D0.  The other six data bits are converted by a
            PAL10H8 driven by the counter. */
		newbyte = 0;

		/*   d  */
		newbyte  = (oldbyte & 0x80) >> 5;
		newbyte |= (inverted_oldbyte & 0x40) << 0;
		newbyte |= (inverted_oldbyte & 0x20) >> 5;
		newbyte |= (inverted_oldbyte & 0x10) << 1;
		newbyte |= (inverted_oldbyte & 0x08) << 0;
		newbyte |= (inverted_oldbyte & 0x04) >> 1;
		newbyte |= (inverted_oldbyte & 0x02) << 3;
		newbyte |= (oldbyte & 0x01) << 7;

		RAM[mem + 0x14000] = newbyte;
	}
}

static void strtheat_decrypt_rom_A(void)
{
	int oldbyte,inverted_oldbyte,newbyte;
	int mem;
	UINT8 *RAM;

	RAM = memory_region(REGION_CPU1);

	for (mem=0;mem<0x4000;mem++)
	{
		oldbyte = RAM[mem];
		inverted_oldbyte = ~oldbyte;

		/*  Note: D2 is inverted and connected to D1, D5 is inverted and
            connected to D0.  The other six data bits are converted by a
            PAL10H8 driven by the counter. */
		newbyte = 0;

		/* DAHF bGcE   dis B   */
		newbyte  = (inverted_oldbyte & 0x80) >> 3;
		newbyte |= (inverted_oldbyte & 0x40) << 1;
		newbyte |= (inverted_oldbyte & 0x20) >> 5;
		newbyte |= (inverted_oldbyte & 0x10) >> 2;
		newbyte |= (oldbyte & 0x08) << 3;
		newbyte |= (inverted_oldbyte & 0x04) >> 1;
		newbyte |= (oldbyte & 0x02) << 4;
		newbyte |= (inverted_oldbyte & 0x01) << 3;

		RAM[mem + 0x18000] = newbyte;
	}
}

static void strtheat_decrypt_rom_B(void)
{
	int oldbyte,inverted_oldbyte,newbyte;
	int mem;
	UINT8 *RAM;

	RAM = memory_region(REGION_CPU1);

	for (mem=0;mem<0x4000;mem++)
	{
		oldbyte = RAM[mem];
		inverted_oldbyte = ~oldbyte;

		/*  Note: D2 is inverted and connected to D1, D5 is inverted and
            connected to D0.  The other six data bits are converted by a
            PAL10H8 driven by the counter. */
		newbyte = 0;

		/*  a  ascii fAHCbGDE  */
		newbyte  = (oldbyte & 0x80) >> 5;
		newbyte |= (inverted_oldbyte & 0x40) << 1;
		newbyte |= (inverted_oldbyte & 0x20) >> 5;
		newbyte |= (inverted_oldbyte & 0x10) << 1;
		newbyte |= (oldbyte & 0x08) << 3;
		newbyte |= (inverted_oldbyte & 0x04) >> 1;
		newbyte |= (inverted_oldbyte & 0x02) << 3;
		newbyte |= (inverted_oldbyte & 0x01) << 3;

		RAM[mem + 0x1C000] = newbyte;
	}
}

static READ8_HANDLER( strtheat_inputport_0_r )
{
	if(readinputport(3) & 0x40)
	{
		/* Joystick inputs */
		return readinputport(0);
	}
	else
	{
		/* Steering Wheel inputs */
		return (readinputport(0) & ~3) | (readinputport(4) & 3);
	}
}

static READ8_HANDLER( strtheat_inputport_1_r )
{
	if(readinputport(3) & 0x40)
	{
		/* Joystick inputs */
		return readinputport(1);
	}
	else
	{
		/* Steering Wheel inputs */
		return (readinputport(1) & ~3) | (readinputport(5) & 3);
	}
}

DRIVER_INIT( strtheat )
{

	memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x0000, 0x3fff, 0, 0, SMH_BANK1 );

	/* While the PAL supports up to 16 decryption methods, only four
        are actually used in the PAL.  Therefore, we'll take a little
        memory overhead and decrypt the ROMs using each method in advance. */
	strtheat_decrypt_rom_8();
	strtheat_decrypt_rom_9();
	strtheat_decrypt_rom_A();
	strtheat_decrypt_rom_B();

	/* custom handlers supporting Joystick or Steering Wheel */
	memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x7c00, 0x7c00, 0, 0, strtheat_inputport_0_r);
	memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x7c80, 0x7c80, 0, 0, strtheat_inputport_1_r);
}
