diff options
author | 2015-09-13 08:41:44 +0200 | |
---|---|---|
committer | 2015-09-13 08:41:44 +0200 | |
commit | f88cefad27a1737c76e09d99c9fb43e173506081 (patch) | |
tree | 2d8167d03579c46e226471747eb4407bd00ed6fa /src/devices/bus/neogeo | |
parent | e92ac9e0fa8e99869894bea00589bbb526be30aa (diff) |
Move all devices into separate part of src tree (nw)
Diffstat (limited to 'src/devices/bus/neogeo')
54 files changed, 7745 insertions, 0 deletions
diff --git a/src/devices/bus/neogeo/banked_cart.c b/src/devices/bus/neogeo/banked_cart.c new file mode 100644 index 00000000000..9d0e1f06cad --- /dev/null +++ b/src/devices/bus/neogeo/banked_cart.c @@ -0,0 +1,107 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#include "emu.h" +#include "banked_cart.h" + + + +extern const device_type NEOGEO_BANKED_CART = &device_creator<neogeo_banked_cart_device>; + + +neogeo_banked_cart_device::neogeo_banked_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, NEOGEO_BANKED_CART, "NeoGeo Banked Cartridge", tag, owner, clock, "neogeo_banked_cart", __FILE__), + m_bank_cartridge(0), + m_region(0) + +{ +} + +void neogeo_banked_cart_device::postload() +{ + _set_main_cpu_bank_address(); +} + +void neogeo_banked_cart_device::device_start() +{ + save_item(NAME(m_main_cpu_bank_address)); + machine().save().register_postload(save_prepost_delegate(FUNC(neogeo_banked_cart_device::postload), this)); +} + +void neogeo_banked_cart_device::device_reset() +{ +} + + + + + + +/************************************* + * + * Main CPU banking + * + *************************************/ + +void neogeo_banked_cart_device::_set_main_cpu_bank_address(void) +{ + if (!m_region) + printf("region is null\n"); + + if (!m_bank_cartridge) + printf("bank_cartridge is null\n"); + + if (m_region && m_bank_cartridge) m_bank_cartridge->set_base(m_region + m_main_cpu_bank_address); +} + + +void neogeo_banked_cart_device::neogeo_set_main_cpu_bank_address( UINT32 bank_address ) +{ +// if (LOG_MAIN_CPU_BANKING) logerror("MAIN CPU PC %06x: neogeo_set_main_cpu_bank_address %06x\n", m_maincpu->pc(), bank_address); + + m_main_cpu_bank_address = bank_address; + + _set_main_cpu_bank_address(); +} + + +WRITE16_MEMBER(neogeo_banked_cart_device::main_cpu_bank_select_w) +{ + UINT32 bank_address; + UINT32 len = m_region_size; + + if ((len <= 0x100000) && (data & 0x07)) + logerror("PC %06x: warning: bankswitch to %02x but no banks available\n", space.device().safe_pc(), data); + else + { + bank_address = ((data & 0x07) + 1) * 0x100000; + + if (bank_address >= len) + { + logerror("PC %06x: warning: bankswitch to empty bank %02x\n", space.device().safe_pc(), data); + bank_address = 0x100000; + } + + neogeo_set_main_cpu_bank_address(bank_address); + } +} + +void neogeo_banked_cart_device::init_banks(void) +{ + /* set initial main CPU bank */ + if (m_region_size > 0x100000) + neogeo_set_main_cpu_bank_address(0x100000); + else + neogeo_set_main_cpu_bank_address(0x000000); +} + +void neogeo_banked_cart_device::install_banks(running_machine& machine, cpu_device* maincpu, UINT8* region, UINT32 region_size) +{ + maincpu->space(AS_PROGRAM).install_read_bank(0x200000, 0x2fffff, 0, 0, "cartridge"); + maincpu->space(AS_PROGRAM).install_write_handler(0x2ffff0, 0x2fffff, write16_delegate(FUNC(neogeo_banked_cart_device::main_cpu_bank_select_w),this)); + + m_bank_cartridge = machine.root_device().membank("cartridge"); + m_region = region; + m_region_size = region_size; + + init_banks(); +} diff --git a/src/devices/bus/neogeo/banked_cart.h b/src/devices/bus/neogeo/banked_cart.h new file mode 100644 index 00000000000..f81b8f5b9c9 --- /dev/null +++ b/src/devices/bus/neogeo/banked_cart.h @@ -0,0 +1,46 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#pragma once + +#ifndef __NEOGEO_BANKED_CART__ +#define __NEOGEO_BANKED_CART__ + +extern const device_type NEOGEO_BANKED_CART; + +#define MCFG_NEOGEO_BANKED_CART_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, NEOGEO_BANKED_CART, 0) + + +class neogeo_banked_cart_device : public device_t +{ +public: + // construction/destruction + neogeo_banked_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + memory_bank* m_bank_cartridge; + UINT32 m_main_cpu_bank_address; + UINT8* m_region; + UINT32 m_region_size; + + + void install_banks(running_machine& machine, cpu_device* maincpu, UINT8* region, UINT32 region_size); + WRITE16_MEMBER(main_cpu_bank_select_w); + void neogeo_set_main_cpu_bank_address(UINT32 bank_address); + void _set_main_cpu_bank_address(); + void init_banks(void); + +protected: + virtual void device_start(); + virtual void device_reset(); + void postload(); + + + +private: + + +}; + +#endif diff --git a/src/devices/bus/neogeo/bootleg_cart.c b/src/devices/bus/neogeo/bootleg_cart.c new file mode 100644 index 00000000000..45a4563f88d --- /dev/null +++ b/src/devices/bus/neogeo/bootleg_cart.c @@ -0,0 +1,378 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/*********************************************************************************************************** + + NEOGEO ROM cart emulation + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "bootleg_cart.h" + + +//------------------------------------------------- +// neogeo_bootleg_cart - constructor +//------------------------------------------------- + +const device_type NEOGEO_BOOTLEG_CART = &device_creator<neogeo_bootleg_cart>; + + +neogeo_bootleg_cart::neogeo_bootleg_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_bootleg_prot(*this, "bootleg_prot") + +{ +} + +neogeo_bootleg_cart::neogeo_bootleg_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock) + : device_t(mconfig, NEOGEO_BOOTLEG_CART, "NEOGEO Bootleg Cart", tag, owner, clock, "neogeo_rom", __FILE__), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_bootleg_prot(*this, "bootleg_prot") +{ +} + + +//------------------------------------------------- +// mapper specific start/reset +//------------------------------------------------- + +void neogeo_bootleg_cart::device_start() +{ +} + +void neogeo_bootleg_cart::device_reset() +{ +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +READ16_MEMBER(neogeo_bootleg_cart::read_rom) +{ + return m_rom[offset]; +} + +static MACHINE_CONFIG_FRAGMENT( bootleg_cart ) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") + MCFG_NGBOOTLEG_PROT_ADD("bootleg_prot") +MACHINE_CONFIG_END + +machine_config_constructor neogeo_bootleg_cart::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( bootleg_cart ); +} + + + +/* Individual cartridge types (mirror DRIVER_INIT functionality) */ + + +/************************************************* + garoubl +**************************************************/ + +const device_type NEOGEO_BOOTLEG_GAROUBL_CART = &device_creator<neogeo_bootleg_garoubl_cart>; + +neogeo_bootleg_garoubl_cart::neogeo_bootleg_garoubl_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_GAROUBL_CART, "NEOGEO BOOT garoubl Cart", tag, owner, clock, "boot_garoubl_cart", __FILE__) {} + +void neogeo_bootleg_garoubl_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_garoubl_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,2); + m_bootleg_prot->neogeo_bootleg_cx_decrypt(spr_region, spr_region_size); +} + +/************************************************* + cthd2003 +**************************************************/ + +const device_type NEOGEO_BOOTLEG_CTHD2003_CART = &device_creator<neogeo_bootleg_cthd2003_cart>; + +neogeo_bootleg_cthd2003_cart::neogeo_bootleg_cthd2003_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_CTHD2003_CART, "NEOGEO BOOT cthd2003 Cart", tag, owner, clock, "boot_cthd2003_cart", __FILE__) {} + +void neogeo_bootleg_cthd2003_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_bootleg_prot->patch_cthd2003(maincpu,m_banked_cart, cpuregion, cpuregion_size); +} + +void neogeo_bootleg_cthd2003_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->decrypt_cthd2003(spr_region, spr_region_size, audiocpu_region, audio_region_size, fix_region, fix_region_size); +} + +/******/ + +const device_type NEOGEO_BOOTLEG_CT2K3SP_CART = &device_creator<neogeo_bootleg_ct2k3sp_cart>; + +neogeo_bootleg_ct2k3sp_cart::neogeo_bootleg_ct2k3sp_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_CT2K3SP_CART, "NEOGEO BOOT ct2k3sp Cart", tag, owner, clock, "boot_ct2k3sp_cart", __FILE__) {} + +void neogeo_bootleg_ct2k3sp_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_bootleg_prot->patch_cthd2003(maincpu,m_banked_cart, cpuregion, cpuregion_size); +} + +void neogeo_bootleg_ct2k3sp_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->decrypt_ct2k3sp(spr_region, spr_region_size, audiocpu_region, audio_region_size, fix_region, fix_region_size); +} + +/******/ + +const device_type NEOGEO_BOOTLEG_CT2K3SA_CART = &device_creator<neogeo_bootleg_ct2k3sa_cart>; + +neogeo_bootleg_ct2k3sa_cart::neogeo_bootleg_ct2k3sa_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_CT2K3SA_CART, "NEOGEO BOOT ct2k3sa Cart", tag, owner, clock, "boot_ct2k3sa_cart", __FILE__) {} + +void neogeo_bootleg_ct2k3sa_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); +} + +void neogeo_bootleg_ct2k3sa_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->decrypt_ct2k3sa(spr_region, spr_region_size, audiocpu_region, audio_region_size); + m_bootleg_prot->patch_ct2k3sa(cpuregion, cpuregion_size); +} + +/************************************************* + kf10thep +**************************************************/ + +const device_type NEOGEO_BOOTLEG_KF10THEP_CART = &device_creator<neogeo_bootleg_kf10thep_cart>; + +neogeo_bootleg_kf10thep_cart::neogeo_bootleg_kf10thep_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_KF10THEP_CART, "NEOGEO BOOT kf10thep Cart", tag, owner, clock, "boot_kf10thep_cart", __FILE__) {} + +void neogeo_bootleg_kf10thep_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_kf10thep_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->kf10thep_px_decrypt(cpuregion, cpuregion_size); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region,fix_region_size,1); +} + + +/************************************************* + kf2k5uni +**************************************************/ + +const device_type NEOGEO_BOOTLEG_KF2K5UNI_CART = &device_creator<neogeo_bootleg_kf2k5uni_cart>; + +neogeo_bootleg_kf2k5uni_cart::neogeo_bootleg_kf2k5uni_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_KF2K5UNI_CART, "NEOGEO BOOT kf2k5uni Cart", tag, owner, clock, "boot_kf2k5uni_cart", __FILE__) {} + +void neogeo_bootleg_kf2k5uni_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_kf2k5uni_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->decrypt_kf2k5uni(cpuregion,cpuregion_size, audiocpu_region, audio_region_size, fix_region, fix_region_size); +} + + +/************************************************* + kf2k4se +**************************************************/ + +const device_type NEOGEO_BOOTLEG_KF2K4SE_CART = &device_creator<neogeo_bootleg_kf2k4se_cart>; + +neogeo_bootleg_kf2k4se_cart::neogeo_bootleg_kf2k4se_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_KF2K4SE_CART, "NEOGEO BOOT kf2k4se Cart", tag, owner, clock, "boot_kf2k4se_cart", __FILE__) {} + +void neogeo_bootleg_kf2k4se_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_kf2k4se_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->decrypt_kof2k4se_68k(cpuregion, cpuregion_size); +} + + + +/************************************************* + svcplus +**************************************************/ + +const device_type NEOGEO_BOOTLEG_SVCPLUS_CART = &device_creator<neogeo_bootleg_svcplus_cart>; + +neogeo_bootleg_svcplus_cart::neogeo_bootleg_svcplus_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_SVCPLUS_CART, "NEOGEO BOOT svcplus Cart", tag, owner, clock, "boot_svcplus_cart", __FILE__) {} + +void neogeo_bootleg_svcplus_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_svcplus_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->svcplus_px_decrypt(cpuregion, cpuregion_size); + m_bootleg_prot->svcboot_cx_decrypt(spr_region, spr_region_size); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size, 1); + m_bootleg_prot->svcplus_px_hack(cpuregion, cpuregion_size); +} + + +/************************************************* + svcplusaa +**************************************************/ + +const device_type NEOGEO_BOOTLEG_SVCPLUSA_CART = &device_creator<neogeo_bootleg_svcplusa_cart>; + +neogeo_bootleg_svcplusa_cart::neogeo_bootleg_svcplusa_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_SVCPLUSA_CART, "NEOGEO BOOT svcplusa Cart", tag, owner, clock, "boot_svcplusa_cart", __FILE__) {} + +void neogeo_bootleg_svcplusa_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_svcplusa_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->svcplusa_px_decrypt(cpuregion, cpuregion_size); + m_bootleg_prot->svcboot_cx_decrypt(spr_region, spr_region_size); + m_bootleg_prot->svcplus_px_hack(cpuregion, cpuregion_size); +} + +/************************************************* + samsho5b +**************************************************/ + +const device_type NEOGEO_BOOTLEG_SAMSHO5B_CART = &device_creator<neogeo_bootleg_samsho5b_cart>; + +neogeo_bootleg_samsho5b_cart::neogeo_bootleg_samsho5b_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_SAMSHO5B_CART, "NEOGEO BOOT samsho5b Cart", tag, owner, clock, "boot_samsho5b_cart", __FILE__) {} + +void neogeo_bootleg_samsho5b_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_samsho5b_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->samsho5b_px_decrypt(cpuregion, cpuregion_size); + m_bootleg_prot->samsho5b_vx_decrypt(ym_region, ym_region_size); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,1); + m_bootleg_prot->neogeo_bootleg_cx_decrypt(spr_region, spr_region_size); +} + + +/************************************************* + kof97oro +**************************************************/ + +const device_type NEOGEO_BOOTLEG_KOF97ORO_CART = &device_creator<neogeo_bootleg_kof97oro_cart>; + +neogeo_bootleg_kof97oro_cart::neogeo_bootleg_kof97oro_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_KOF97ORO_CART, "NEOGEO BOOT kof97oro Cart", tag, owner, clock, "boot_kof97oro_cart", __FILE__) {} + +void neogeo_bootleg_kof97oro_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_kof97oro_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->kof97oro_px_decode(cpuregion, cpuregion_size); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,1); + m_bootleg_prot->neogeo_bootleg_cx_decrypt(spr_region, spr_region_size); +} + + +/************************************************* + lans2004 +**************************************************/ + +const device_type NEOGEO_BOOTLEG_LANS2004_CART = &device_creator<neogeo_bootleg_lans2004_cart>; + +neogeo_bootleg_lans2004_cart::neogeo_bootleg_lans2004_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_LANS2004_CART, "NEOGEO BOOT lans2004 Cart", tag, owner, clock, "boot_lans2004_cart", __FILE__) {} + +void neogeo_bootleg_lans2004_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_lans2004_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->lans2004_decrypt_68k(cpuregion, cpuregion_size); + m_bootleg_prot->lans2004_vx_decrypt(ym_region, ym_region_size); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,1); + m_bootleg_prot->neogeo_bootleg_cx_decrypt(spr_region, spr_region_size); +} + + +/************************************************* + kof10th +**************************************************/ + +const device_type NEOGEO_BOOTLEG_KOF10TH_CART = &device_creator<neogeo_bootleg_kof10th_cart>; + +neogeo_bootleg_kof10th_cart::neogeo_bootleg_kof10th_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_KOF10TH_CART, "NEOGEO BOOT kof10th Cart", tag, owner, clock, "boot_kof10th_cart", __FILE__) {} + +void neogeo_bootleg_kof10th_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_bootleg_prot->install_kof10th_protection(maincpu,m_banked_cart, cpuregion, cpuregion_size, fixedregion, fixedregion_size); + +} + +void neogeo_bootleg_kof10th_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->decrypt_kof10th(cpuregion, cpuregion_size); +} + + + +/************************************************* + kog +**************************************************/ + +const device_type NEOGEO_BOOTLEG_KOG_CART = &device_creator<neogeo_bootleg_kog_cart>; + +neogeo_bootleg_kog_cart::neogeo_bootleg_kog_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_cart(mconfig, NEOGEO_BOOTLEG_KOG_CART, "NEOGEO BOOT kog Cart", tag, owner, clock, "boot_kog_cart", __FILE__), + m_kog_prot(*this, "kog_prot") +{} + +static MACHINE_CONFIG_FRAGMENT( kog_bootleg_cart ) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") + MCFG_NGBOOTLEG_PROT_ADD("bootleg_prot") + MCFG_KOG_PROT_ADD("kog_prot") +MACHINE_CONFIG_END + +machine_config_constructor neogeo_bootleg_kog_cart::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( kog_bootleg_cart ); +} + + +void neogeo_bootleg_kog_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_kog_prot->kog_install_protection(maincpu); +} + +void neogeo_bootleg_kog_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_kog_prot->kog_px_decrypt(cpuregion, cpuregion_size); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,1); + m_bootleg_prot->neogeo_bootleg_cx_decrypt(spr_region, spr_region_size); +} diff --git a/src/devices/bus/neogeo/bootleg_cart.h b/src/devices/bus/neogeo/bootleg_cart.h new file mode 100644 index 00000000000..a3932c25df8 --- /dev/null +++ b/src/devices/bus/neogeo/bootleg_cart.h @@ -0,0 +1,250 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#ifndef __NEOGEO_BOOTLEG_CART_H +#define __NEOGEO_BOOTLEG_CART_H + +#include "neogeo_slot.h" +#include "banked_cart.h" +#include "sma_prot.h" +#include "bootleg_prot.h" +#include "kog_prot.h" + +// ======================> neogeo_bootleg_cart + +class neogeo_bootleg_cart : public device_t, + public device_neogeo_cart_interface +{ +public: + // construction/destruction + neogeo_bootleg_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source); + neogeo_bootleg_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ16_MEMBER(read_rom); + + virtual void activate_cart(ACTIVATE_CART_PARAMS) {} + virtual void decrypt_all(DECRYPT_ALL_PARAMS) {} + virtual int get_fixed_bank_type(void) { return 0; } + + required_device<neogeo_banked_cart_device> m_banked_cart; + required_device<ngbootleg_prot_device> m_bootleg_prot; +}; + + + +// device type definition +extern const device_type NEOGEO_BOOTLEG_CART; + + +/************************************************* + GAROUBL +**************************************************/ + +class neogeo_bootleg_garoubl_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_garoubl_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_GAROUBL_CART; + + +/************************************************* + CTHD2003 +**************************************************/ + +class neogeo_bootleg_cthd2003_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_cthd2003_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_CTHD2003_CART; + +class neogeo_bootleg_ct2k3sp_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_ct2k3sp_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_CT2K3SP_CART; + +class neogeo_bootleg_ct2k3sa_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_ct2k3sa_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_CT2K3SA_CART; + + +/************************************************* + KF10THEP +**************************************************/ + +class neogeo_bootleg_kf10thep_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_kf10thep_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_KF10THEP_CART; + + +/************************************************* + KF2K5UNI +**************************************************/ + +class neogeo_bootleg_kf2k5uni_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_kf2k5uni_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_KF2K5UNI_CART; + +/************************************************* + KF2K4SE +**************************************************/ + +class neogeo_bootleg_kf2k4se_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_kf2k4se_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_KF2K4SE_CART; + + +/************************************************* + SVCPLUS +**************************************************/ + +class neogeo_bootleg_svcplus_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_svcplus_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_SVCPLUS_CART; + +/************************************************* + SVCPLUSA +**************************************************/ + +class neogeo_bootleg_svcplusa_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_svcplusa_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_SVCPLUSA_CART; + +/************************************************* + SAMSHO5B +**************************************************/ + +class neogeo_bootleg_samsho5b_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_samsho5b_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_SAMSHO5B_CART; + + +/************************************************* + KOF97ORO +**************************************************/ + +class neogeo_bootleg_kof97oro_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_kof97oro_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_KOF97ORO_CART; + + +/************************************************* + LANS2004 +**************************************************/ + +class neogeo_bootleg_lans2004_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_lans2004_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_LANS2004_CART; + +/************************************************* + KOF10TH +**************************************************/ + +class neogeo_bootleg_kof10th_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_kof10th_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_KOF10TH_CART; + + + +/************************************************* + KOG +**************************************************/ + +class neogeo_bootleg_kog_cart : public neogeo_bootleg_cart +{ +public: + neogeo_bootleg_kog_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } + + virtual machine_config_constructor device_mconfig_additions() const; + + required_device<kog_prot_device> m_kog_prot; +}; +extern const device_type NEOGEO_BOOTLEG_KOG_CART; + + + + + + + +#endif diff --git a/src/devices/bus/neogeo/bootleg_hybrid_cart.c b/src/devices/bus/neogeo/bootleg_hybrid_cart.c new file mode 100644 index 00000000000..5d677c8cc74 --- /dev/null +++ b/src/devices/bus/neogeo/bootleg_hybrid_cart.c @@ -0,0 +1,319 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/*********************************************************************************************************** + + NEOGEO ROM cart emulation + + these are bootlegs using a mix of reimplemented original features, could be further sorted + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "bootleg_hybrid_cart.h" + + +//------------------------------------------------- +// neogeo_bootleg_hybrid_hybrid_cart - constructor +//------------------------------------------------- + +const device_type NEOGEO_BOOTLEG_HYBRID_HYBRID_CART = &device_creator<neogeo_bootleg_hybrid_hybrid_cart>; + + +neogeo_bootleg_hybrid_hybrid_cart::neogeo_bootleg_hybrid_hybrid_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_bootleg_prot(*this, "bootleg_prot"), + m_cmc_prot(*this, "cmc_prot"), + m_pcm2_prot(*this, "pcm2_prot"), + m_kof2002_prot(*this, "kof2002_prot"), + m_pvc_prot(*this, "pvc_prot") +{ +} + +neogeo_bootleg_hybrid_hybrid_cart::neogeo_bootleg_hybrid_hybrid_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock) + : device_t(mconfig, NEOGEO_BOOTLEG_HYBRID_HYBRID_CART, "NEOGEO SMA Cart", tag, owner, clock, "neogeo_rom", __FILE__), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_bootleg_prot(*this, "bootleg_prot"), + m_cmc_prot(*this, "cmc_prot"), + m_pcm2_prot(*this, "pcm2_prot"), + m_kof2002_prot(*this, "kof2002_prot"), + m_pvc_prot(*this, "pvc_prot") + +{ +} + + +//------------------------------------------------- +// mapper specific start/reset +//------------------------------------------------- + +void neogeo_bootleg_hybrid_hybrid_cart::device_start() +{ +} + +void neogeo_bootleg_hybrid_hybrid_cart::device_reset() +{ +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +READ16_MEMBER(neogeo_bootleg_hybrid_hybrid_cart::read_rom) +{ + return m_rom[offset]; +} + +static MACHINE_CONFIG_FRAGMENT( bootleg_hybrid_cart ) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") + MCFG_NGBOOTLEG_PROT_ADD("bootleg_prot") + MCFG_CMC_PROT_ADD("cmc_prot") + MCFG_PCM2_PROT_ADD("pcm2_prot") + MCFG_KOF2002_PROT_ADD("kof2002_prot") + MCFG_PVC_PROT_ADD("pvc_prot") +MACHINE_CONFIG_END + +machine_config_constructor neogeo_bootleg_hybrid_hybrid_cart::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( bootleg_hybrid_cart ); +} + + + +/* Individual cartridge types (mirror DRIVER_INIT functionality) */ + + +/************************************************* + mslug3b6 +**************************************************/ + +const device_type NEOGEO_BOOTLEG_HYBRID_MSLUG3B6_CART = &device_creator<neogeo_bootleg_hybrid_mslug3b6_cart>; + +neogeo_bootleg_hybrid_mslug3b6_cart::neogeo_bootleg_hybrid_mslug3b6_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_hybrid_hybrid_cart(mconfig, NEOGEO_BOOTLEG_HYBRID_MSLUG3B6_CART, "NEOGEO BOOT mslug3b6 Cart", tag, owner, clock, "boot_mslug3b6_cart", __FILE__) {} + +void neogeo_bootleg_hybrid_mslug3b6_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_hybrid_mslug3b6_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,2); + m_cmc_prot->cmc42_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, MSLUG3_GFX_KEY); +} + +/************************************************* + kof2002b +**************************************************/ + +const device_type NEOGEO_BOOTLEG_HYBRID_KOF2002B_CART = &device_creator<neogeo_bootleg_hybrid_kof2002b_cart>; + +neogeo_bootleg_hybrid_kof2002b_cart::neogeo_bootleg_hybrid_kof2002b_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_hybrid_hybrid_cart(mconfig, NEOGEO_BOOTLEG_HYBRID_KOF2002B_CART, "NEOGEO BOOT kof2002b Cart", tag, owner, clock, "boot_kof2002b_cart", __FILE__) {} + +void neogeo_bootleg_hybrid_kof2002b_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_hybrid_kof2002b_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_kof2002_prot->kof2002_decrypt_68k(cpuregion, cpuregion_size); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 0); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_bootleg_prot->kof2002b_gfx_decrypt(spr_region,0x4000000); + m_bootleg_prot->kof2002b_gfx_decrypt(fix_region,0x20000); +} + +/***/ + +const device_type NEOGEO_BOOTLEG_HYBRID_KF2K2MP_CART = &device_creator<neogeo_bootleg_hybrid_kf2k2mp_cart>; + +neogeo_bootleg_hybrid_kf2k2mp_cart::neogeo_bootleg_hybrid_kf2k2mp_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_hybrid_hybrid_cart(mconfig, NEOGEO_BOOTLEG_HYBRID_KF2K2MP_CART, "NEOGEO BOOT kf2k2mp Cart", tag, owner, clock, "boot_kf2k2mp_cart", __FILE__) {} + +void neogeo_bootleg_hybrid_kf2k2mp_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_hybrid_kf2k2mp_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->kf2k2mp_decrypt(cpuregion, cpuregion_size); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 0); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,2); + m_cmc_prot->cmc50_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF2002_GFX_KEY); +} + +/***/ + +const device_type NEOGEO_BOOTLEG_HYBRID_KF2K2MP2_CART = &device_creator<neogeo_bootleg_hybrid_kf2k2mp2_cart>; + +neogeo_bootleg_hybrid_kf2k2mp2_cart::neogeo_bootleg_hybrid_kf2k2mp2_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_hybrid_hybrid_cart(mconfig, NEOGEO_BOOTLEG_HYBRID_KF2K2MP2_CART, "NEOGEO BOOT kf2k2mp2 Cart", tag, owner, clock, "boot_kf2k2mp2_cart", __FILE__) {} + +void neogeo_bootleg_hybrid_kf2k2mp2_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_hybrid_kf2k2mp2_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->kf2k2mp2_px_decrypt(cpuregion, cpuregion_size); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 0); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,1); + m_cmc_prot->cmc50_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF2002_GFX_KEY); +} + +/************************************************* + matrimbl +**************************************************/ + +const device_type NEOGEO_BOOTLEG_HYBRID_MATRIMBL_CART = &device_creator<neogeo_bootleg_hybrid_matrimbl_cart>; + +neogeo_bootleg_hybrid_matrimbl_cart::neogeo_bootleg_hybrid_matrimbl_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_hybrid_hybrid_cart(mconfig, NEOGEO_BOOTLEG_HYBRID_MATRIMBL_CART, "NEOGEO BOOT matrimbl Cart", tag, owner, clock, "boot_matrimbl_cart", __FILE__) {} + +void neogeo_bootleg_hybrid_matrimbl_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_hybrid_matrimbl_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_kof2002_prot->matrim_decrypt_68k(cpuregion, cpuregion_size); + m_bootleg_prot->matrimbl_decrypt(spr_region, spr_region_size, audiocpu_region,audio_region_size); + m_cmc_prot->neogeo_sfix_decrypt(spr_region, spr_region_size, fix_region, fix_region_size); /* required for text layer */ +} + +/************************************************* + ms5plus +**************************************************/ + +const device_type NEOGEO_BOOTLEG_HYBRID_MS5PLUS_CART = &device_creator<neogeo_bootleg_hybrid_ms5plus_cart>; + +neogeo_bootleg_hybrid_ms5plus_cart::neogeo_bootleg_hybrid_ms5plus_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_hybrid_hybrid_cart(mconfig, NEOGEO_BOOTLEG_HYBRID_MS5PLUS_CART, "NEOGEO BOOT ms5plus Cart", tag, owner, clock, "boot_ms5plus_cart", __FILE__) {} + +void neogeo_bootleg_hybrid_ms5plus_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_bootleg_prot->install_ms5plus_protection(maincpu,m_banked_cart); +} + +void neogeo_bootleg_hybrid_ms5plus_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->cmc50_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, MSLUG5_GFX_KEY); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 2); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,1); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region,audio_region_size); +} + +/************************************************* + svcboot +**************************************************/ + +const device_type NEOGEO_BOOTLEG_HYBRID_SVCBOOT_CART = &device_creator<neogeo_bootleg_hybrid_svcboot_cart>; + +neogeo_bootleg_hybrid_svcboot_cart::neogeo_bootleg_hybrid_svcboot_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_hybrid_hybrid_cart(mconfig, NEOGEO_BOOTLEG_HYBRID_SVCBOOT_CART, "NEOGEO BOOT svcboot Cart", tag, owner, clock, "boot_svcboot_cart", __FILE__) {} + +void neogeo_bootleg_hybrid_svcboot_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_pvc_prot->install_pvc_protection(maincpu,m_banked_cart); +} + +void neogeo_bootleg_hybrid_svcboot_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->svcboot_px_decrypt(cpuregion, cpuregion_size); + m_bootleg_prot->svcboot_cx_decrypt(spr_region, spr_region_size); +} + +/***/ + +const device_type NEOGEO_BOOTLEG_HYBRID_SVCSPLUS_CART = &device_creator<neogeo_bootleg_hybrid_svcsplus_cart>; + +neogeo_bootleg_hybrid_svcsplus_cart::neogeo_bootleg_hybrid_svcsplus_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_hybrid_hybrid_cart(mconfig, NEOGEO_BOOTLEG_HYBRID_SVCSPLUS_CART, "NEOGEO BOOT svcsplus Cart", tag, owner, clock, "boot_svcsplus_cart", __FILE__) {} + +void neogeo_bootleg_hybrid_svcsplus_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_pvc_prot->install_pvc_protection(maincpu,m_banked_cart); + +} + +void neogeo_bootleg_hybrid_svcsplus_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_bootleg_prot->svcsplus_px_decrypt(cpuregion, cpuregion_size); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,2); + m_bootleg_prot->svcboot_cx_decrypt(spr_region, spr_region_size); + m_bootleg_prot->svcsplus_px_hack(cpuregion, cpuregion_size); +} + + +/************************************************* + kf2k3bl +**************************************************/ + +const device_type NEOGEO_BOOTLEG_HYBRID_KF2K3BL_CART = &device_creator<neogeo_bootleg_hybrid_kf2k3bl_cart>; + +neogeo_bootleg_hybrid_kf2k3bl_cart::neogeo_bootleg_hybrid_kf2k3bl_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_hybrid_hybrid_cart(mconfig, NEOGEO_BOOTLEG_HYBRID_KF2K3BL_CART, "NEOGEO BOOT kf2k3bl Cart", tag, owner, clock, "boot_kf2k3bl_cart", __FILE__) {} + +void neogeo_bootleg_hybrid_kf2k3bl_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_bootleg_prot->kf2k3bl_install_protection(maincpu,m_banked_cart, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_hybrid_kf2k3bl_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->cmc50_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF2003_GFX_KEY); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 5); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,1); + +} + +const device_type NEOGEO_BOOTLEG_HYBRID_KF2K3PL_CART = &device_creator<neogeo_bootleg_hybrid_kf2k3pl_cart>; + +neogeo_bootleg_hybrid_kf2k3pl_cart::neogeo_bootleg_hybrid_kf2k3pl_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_hybrid_hybrid_cart(mconfig, NEOGEO_BOOTLEG_HYBRID_KF2K3PL_CART, "NEOGEO BOOT kf2k3pl Cart", tag, owner, clock, "boot_kf2k3pl_cart", __FILE__) {} + +void neogeo_bootleg_hybrid_kf2k3pl_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_bootleg_prot->kf2k3pl_install_protection(maincpu,m_banked_cart, cpuregion, cpuregion_size); +} + +void neogeo_bootleg_hybrid_kf2k3pl_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->cmc50_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF2003_GFX_KEY); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 5); + m_bootleg_prot->kf2k3pl_px_decrypt(cpuregion, cpuregion_size); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,1); +} + + +const device_type NEOGEO_BOOTLEG_HYBRID_KF2K3UPL_CART = &device_creator<neogeo_bootleg_hybrid_kf2k3upl_cart>; + +neogeo_bootleg_hybrid_kf2k3upl_cart::neogeo_bootleg_hybrid_kf2k3upl_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_bootleg_hybrid_hybrid_cart(mconfig, NEOGEO_BOOTLEG_HYBRID_KF2K3UPL_CART, "NEOGEO BOOT kf2k3upl Cart", tag, owner, clock, "boot_kf2k3upl_cart", __FILE__) {} + +void neogeo_bootleg_hybrid_kf2k3upl_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_bootleg_prot->kf2k3bl_install_protection(maincpu,m_banked_cart, cpuregion, cpuregion_size); + +} + +void neogeo_bootleg_hybrid_kf2k3upl_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->cmc50_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF2003_GFX_KEY); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 5); + m_bootleg_prot->kf2k3upl_px_decrypt(cpuregion, cpuregion_size); + m_bootleg_prot->neogeo_bootleg_sx_decrypt(fix_region, fix_region_size,2); +} diff --git a/src/devices/bus/neogeo/bootleg_hybrid_cart.h b/src/devices/bus/neogeo/bootleg_hybrid_cart.h new file mode 100644 index 00000000000..ace1886e840 --- /dev/null +++ b/src/devices/bus/neogeo/bootleg_hybrid_cart.h @@ -0,0 +1,192 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#ifndef __NEOGEO_BOOTLEG_HYBRID_HYBRID_CART_H +#define __NEOGEO_BOOTLEG_HYBRID_HYBRID_CART_H + +#include "neogeo_slot.h" +#include "banked_cart.h" +#include "bootleg_prot.h" +#include "pcm2_prot.h" +#include "cmc_prot.h" +#include "kof2002_prot.h" +#include "pvc_prot.h" + +// ======================> neogeo_bootleg_hybrid_hybrid_cart + +class neogeo_bootleg_hybrid_hybrid_cart : public device_t, + public device_neogeo_cart_interface +{ +public: + // construction/destruction + neogeo_bootleg_hybrid_hybrid_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source); + neogeo_bootleg_hybrid_hybrid_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ16_MEMBER(read_rom); + + virtual void activate_cart(ACTIVATE_CART_PARAMS) {} + virtual void decrypt_all(DECRYPT_ALL_PARAMS) {} + virtual int get_fixed_bank_type(void) { return 0; } + + required_device<neogeo_banked_cart_device> m_banked_cart; + required_device<ngbootleg_prot_device> m_bootleg_prot; + required_device<cmc_prot_device> m_cmc_prot; + required_device<pcm2_prot_device> m_pcm2_prot; + required_device<kof2002_prot_device> m_kof2002_prot; + required_device<pvc_prot_device> m_pvc_prot; +}; + + + +// device type definition +extern const device_type NEOGEO_BOOTLEG_HYBRID_HYBRID_CART; + + + +/************************************************* + MSLUG3B6 +**************************************************/ + +class neogeo_bootleg_hybrid_mslug3b6_cart : public neogeo_bootleg_hybrid_hybrid_cart +{ +public: + neogeo_bootleg_hybrid_mslug3b6_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_HYBRID_MSLUG3B6_CART; + + +/************************************************* + KOF2002B +**************************************************/ + +class neogeo_bootleg_hybrid_kof2002b_cart : public neogeo_bootleg_hybrid_hybrid_cart +{ +public: + neogeo_bootleg_hybrid_kof2002b_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_HYBRID_KOF2002B_CART; + +class neogeo_bootleg_hybrid_kf2k2mp_cart : public neogeo_bootleg_hybrid_hybrid_cart +{ +public: + neogeo_bootleg_hybrid_kf2k2mp_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_HYBRID_KF2K2MP_CART; + +class neogeo_bootleg_hybrid_kf2k2mp2_cart : public neogeo_bootleg_hybrid_hybrid_cart +{ +public: + neogeo_bootleg_hybrid_kf2k2mp2_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_HYBRID_KF2K2MP2_CART; + + +/************************************************* + MATRIMBL +**************************************************/ + +class neogeo_bootleg_hybrid_matrimbl_cart : public neogeo_bootleg_hybrid_hybrid_cart +{ +public: + neogeo_bootleg_hybrid_matrimbl_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 2; } +}; +extern const device_type NEOGEO_BOOTLEG_HYBRID_MATRIMBL_CART; + +/************************************************* + MS5PLUS +**************************************************/ + +class neogeo_bootleg_hybrid_ms5plus_cart : public neogeo_bootleg_hybrid_hybrid_cart +{ +public: + neogeo_bootleg_hybrid_ms5plus_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_BOOTLEG_HYBRID_MS5PLUS_CART; + +/************************************************* + SVCBOOT +**************************************************/ + +class neogeo_bootleg_hybrid_svcboot_cart : public neogeo_bootleg_hybrid_hybrid_cart +{ +public: + neogeo_bootleg_hybrid_svcboot_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_HYBRID_SVCBOOT_CART; + +class neogeo_bootleg_hybrid_svcsplus_cart : public neogeo_bootleg_hybrid_hybrid_cart +{ +public: + neogeo_bootleg_hybrid_svcsplus_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_HYBRID_SVCSPLUS_CART; + + + +/************************************************* + KF2K3BL +**************************************************/ + +class neogeo_bootleg_hybrid_kf2k3bl_cart : public neogeo_bootleg_hybrid_hybrid_cart +{ +public: + neogeo_bootleg_hybrid_kf2k3bl_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_HYBRID_KF2K3BL_CART; + +class neogeo_bootleg_hybrid_kf2k3pl_cart : public neogeo_bootleg_hybrid_hybrid_cart +{ +public: + neogeo_bootleg_hybrid_kf2k3pl_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_HYBRID_KF2K3PL_CART; + + +class neogeo_bootleg_hybrid_kf2k3upl_cart : public neogeo_bootleg_hybrid_hybrid_cart +{ +public: + neogeo_bootleg_hybrid_kf2k3upl_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_BOOTLEG_HYBRID_KF2K3UPL_CART; + + + +#endif diff --git a/src/devices/bus/neogeo/bootleg_prot.c b/src/devices/bus/neogeo/bootleg_prot.c new file mode 100644 index 00000000000..aa5ad7da084 --- /dev/null +++ b/src/devices/bus/neogeo/bootleg_prot.c @@ -0,0 +1,1066 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + +#include "emu.h" +#include "bootleg_prot.h" + + + +extern const device_type NGBOOTLEG_PROT = &device_creator<ngbootleg_prot_device>; + + +ngbootleg_prot_device::ngbootleg_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, NGBOOTLEG_PROT, "NeoGeo Protection (Bootleg)", tag, owner, clock, "ngbootleg_prot", __FILE__) +{ +} + + +void ngbootleg_prot_device::device_start() +{ + memset(m_cartridge_ram, 0x00, 0x2000); + + save_item(NAME(m_cartridge_ram)); +} + +void ngbootleg_prot_device::device_reset() +{ +} + + + +/*************************************************************************** + + Neo-Geo hardware encryption and protection used on bootleg cartridges + + Many of the NeoGeo bootlegs use their own form of encryption and + protection, presumably to make them harder for other bootleggers to + copy. This encryption often involves non-trivial scrambling of the + program roms and the games are protected using an Altera chip which + provides some kind of rom overlay, patching parts of the code. + The graphics roms are usually scrambled in a different way to the + official SNK cartridges too. + +***************************************************************************/ + +#include "emu.h" +#include "includes/neogeo.h" + + +/* General Bootleg Functions - used by more than 1 game */ + + +void ngbootleg_prot_device::neogeo_bootleg_cx_decrypt(UINT8*sprrom, UINT32 sprrom_size) +{ + int i; + int cx_size = sprrom_size; + UINT8 *rom = sprrom; + dynamic_buffer buf( cx_size ); + + memcpy( &buf[0], rom, cx_size ); + + for( i = 0; i < cx_size / 0x40; i++ ){ + memcpy( &rom[ i * 0x40 ], &buf[ (i ^ 1) * 0x40 ], 0x40 ); + } +} + + +void ngbootleg_prot_device::neogeo_bootleg_sx_decrypt(UINT8* fixed, UINT32 fixed_size, int value ) +{ + int sx_size = fixed_size; + UINT8 *rom = fixed; + int i; + + if (value == 1) + { + dynamic_buffer buf( sx_size ); + memcpy( &buf[0], rom, sx_size ); + + for( i = 0; i < sx_size; i += 0x10 ) + { + memcpy( &rom[ i ], &buf[ i + 8 ], 8 ); + memcpy( &rom[ i + 8 ], &buf[ i ], 8 ); + } + } + else if (value == 2) + { + for( i = 0; i < sx_size; i++ ) + rom[ i ] = BITSWAP8( rom[ i ], 7, 6, 0, 4, 3, 2, 1, 5 ); + } +} + + + +/* The King of Fighters '97 Oroshi Plus 2003 (bootleg) */ + +void ngbootleg_prot_device::kof97oro_px_decode(UINT8* cpurom, UINT32 cpurom_size) +{ + int i; + std::vector<UINT16> tmp( 0x500000 ); + UINT16 *src = (UINT16*)cpurom; + + for (i = 0; i < 0x500000/2; i++) { + tmp[i] = src[i ^ 0x7ffef]; + } + + memcpy (src, &tmp[0], 0x500000); +} + + +/* The King of Fighters 10th Anniversary (The King of Fighters 2002 bootleg) */ + + +/* this uses RAM based tiles for the text layer, however the implementation + is incomplete, at the moment the S data is copied from the program rom on + start-up instead */ + +void ngbootleg_prot_device::kof10thBankswitch(address_space &space, UINT16 nBank) +{ + UINT32 bank = 0x100000 + ((nBank & 7) << 20); + if (bank >= 0x700000) + bank = 0x100000; + m_bankdev->neogeo_set_main_cpu_bank_address(bank); +} + +READ16_MEMBER( ngbootleg_prot_device::kof10th_RAMB_r ) +{ + return m_cartridge_ram[offset]; +} + +READ16_MEMBER(ngbootleg_prot_device::kof10th_RAM2_r) +{ +// printf("kof10th_RAM2_r\n"); + return m_cartridge_ram2[offset]; +} + +WRITE16_MEMBER( ngbootleg_prot_device::kof10th_custom_w ) +{ + if (!m_cartridge_ram[0xFFE]) { // Write to RAM bank A + //UINT16 *prom = (UINT16*)m_mainrom; + COMBINE_DATA(&m_cartridge_ram2[(0x00000/2) + (offset & 0xFFFF)]); + } else { // Write S data on-the-fly + UINT8 *srom = m_fixedrom; + srom[offset] = BITSWAP8(data,7,6,0,4,3,2,1,5); + } +} + +WRITE16_MEMBER( ngbootleg_prot_device::kof10th_bankswitch_w ) +{ + if (offset >= 0x5F000) { + if (offset == 0x5FFF8) { // Standard bankswitch + kof10thBankswitch(space, data); + } else if (offset == 0x5FFFC && m_cartridge_ram[0xFFC] != data) { // Special bankswitch + UINT8 *src = m_mainrom; + memcpy (src + 0x10000, src + ((data & 1) ? 0x810000 : 0x710000), 0xcffff); + } + COMBINE_DATA(&m_cartridge_ram[offset & 0xFFF]); + } +} + +void ngbootleg_prot_device::install_kof10th_protection (cpu_device* maincpu, neogeo_banked_cart_device* bankdev, UINT8* cpurom, UINT32 cpurom_size, UINT8* fixedrom, UINT32 fixedrom_size) +{ + m_mainrom = cpurom; + m_fixedrom = fixedrom; + m_bankdev = bankdev; + + maincpu->space(AS_PROGRAM).install_read_handler(0x0e0000, 0x0fffff, read16_delegate(FUNC(ngbootleg_prot_device::kof10th_RAM2_r),this)); + + maincpu->space(AS_PROGRAM).install_read_handler(0x2fe000, 0x2fffff, read16_delegate(FUNC(ngbootleg_prot_device::kof10th_RAMB_r),this)); + maincpu->space(AS_PROGRAM).install_write_handler(0x200000, 0x23ffff, write16_delegate(FUNC(ngbootleg_prot_device::kof10th_custom_w),this)); + maincpu->space(AS_PROGRAM).install_write_handler(0x240000, 0x2fffff, write16_delegate(FUNC(ngbootleg_prot_device::kof10th_bankswitch_w),this)); + memcpy(m_cartridge_ram2, cpurom + 0xe0000, 0x20000); + +} + +void ngbootleg_prot_device::decrypt_kof10th(UINT8* cpurom, UINT32 cpurom_size) +{ + int i, j; + dynamic_buffer dst(0x900000); + UINT8 *src = cpurom; + + memcpy(&dst[0x000000], src + 0x700000, 0x100000); // Correct (Verified in Uni-bios) + memcpy(&dst[0x100000], src + 0x000000, 0x800000); + + for (i = 0; i < 0x900000; i++) { + j = BITSWAP24(i,23,22,21,20,19,18,17,16,15,14,13,12,11,2,9,8,7,1,5,4,3,10,6,0); + src[j] = dst[i]; + } + + // Altera protection chip patches these over P ROM + ((UINT16*)src)[0x0124/2] = 0x000d; // Enables XOR for RAM moves, forces SoftDIPs, and USA region + ((UINT16*)src)[0x0126/2] = 0xf7a8; + + ((UINT16*)src)[0x8bf4/2] = 0x4ef9; // Run code to change "S" data + ((UINT16*)src)[0x8bf6/2] = 0x000d; + ((UINT16*)src)[0x8bf8/2] = 0xf980; + +} + + +/* The King of Fighters 10th Anniversary Extra Plus (The King of Fighters 2002 bootleg) */ + + +void ngbootleg_prot_device::kf10thep_px_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + UINT16 *rom = (UINT16*)cpurom; + std::vector<UINT16> buf(0x100000/2); + + memcpy(&buf[0x000000/2], &rom[0x060000/2], 0x20000); + memcpy(&buf[0x020000/2], &rom[0x100000/2], 0x20000); + memcpy(&buf[0x040000/2], &rom[0x0e0000/2], 0x20000); + memcpy(&buf[0x060000/2], &rom[0x180000/2], 0x20000); + memcpy(&buf[0x080000/2], &rom[0x020000/2], 0x20000); + memcpy(&buf[0x0a0000/2], &rom[0x140000/2], 0x20000); + memcpy(&buf[0x0c0000/2], &rom[0x0c0000/2], 0x20000); + memcpy(&buf[0x0e0000/2], &rom[0x1a0000/2], 0x20000); + memcpy(&buf[0x0002e0/2], &rom[0x0402e0/2], 0x6a); // copy banked code to a new memory region + memcpy(&buf[0x0f92bc/2], &rom[0x0492bc/2], 0xb9e); // copy banked code to a new memory region + memcpy(rom, &buf[0], 0x100000); + + for (int i = 0xf92bc/2; i < 0xf9e58/2; i++) + { + if (rom[i+0] == 0x4eb9 && rom[i+1] == 0x0000) rom[i+1] = 0x000F; // correct JSR in moved code + if (rom[i+0] == 0x4ef9 && rom[i+1] == 0x0000) rom[i+1] = 0x000F; // correct JMP in moved code + } + rom[0x00342/2] = 0x000f; + + memmove(&rom[0x100000/2], &rom[0x200000/2], 0x600000); +} + + +/* The King of Fighters 10th Anniversary 2005 Unique (The King of Fighters 2002 bootleg) */ + + +void ngbootleg_prot_device::kf2k5uni_px_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + int i, j, ofst; + UINT8 *src = cpurom; + UINT8 dst[0x80]; + + for (i = 0; i < 0x800000; i+=0x80) + { + for (j = 0; j < 0x80; j+=2) + { + ofst = BITSWAP8(j, 0, 3, 4, 5, 6, 1, 2, 7); + memcpy(&dst[j], src + i + ofst, 2); + } + memcpy(src + i, &dst[0], 0x80); + } + + memcpy(src, src + 0x600000, 0x100000); // Seems to be the same as kof10th +} + +void ngbootleg_prot_device::kf2k5uni_sx_decrypt(UINT8* fixedrom, UINT32 fixedrom_size) +{ + int i; + UINT8 *srom = fixedrom; + + for (i = 0; i < 0x20000; i++) + srom[i] = BITSWAP8(srom[i], 4, 5, 6, 7, 0, 1, 2, 3); +} + +void ngbootleg_prot_device::kf2k5uni_mx_decrypt(UINT8* audiorom, UINT32 audiorom_size) +{ + int i; + UINT8 *mrom = audiorom; + + for (i = 0; i < 0x30000; i++) + mrom[i] = BITSWAP8(mrom[i], 4, 5, 6, 7, 0, 1, 2, 3); +} + +void ngbootleg_prot_device::decrypt_kf2k5uni(UINT8* cpurom, UINT32 cpurom_size, UINT8* audiorom, UINT32 audiorom_size, UINT8* fixedrom, UINT32 fixedrom_size) +{ + kf2k5uni_px_decrypt(cpurom, cpurom_size); + kf2k5uni_sx_decrypt(fixedrom, fixedrom_size); + kf2k5uni_mx_decrypt(audiorom, audiorom_size); +} + + +/* The King of Fighters 2002 (bootleg) */ + + +void ngbootleg_prot_device::kof2002b_gfx_decrypt(UINT8 *src, int size) +{ + int i, j; + static const UINT8 t[ 8 ][ 6 ] = + { + { 0, 8, 7, 6, 2, 1 }, + { 1, 0, 8, 7, 6, 2 }, + { 2, 1, 0, 8, 7, 6 }, + { 6, 2, 1, 0, 8, 7 }, + { 7, 6, 2, 1, 0, 8 }, + { 0, 1, 2, 6, 7, 8 }, + { 2, 1, 0, 6, 7, 8 }, + { 8, 0, 7, 6, 2, 1 }, + }; + + dynamic_buffer dst( 0x10000 ); + + for ( i = 0; i < size; i+=0x10000 ) + { + memcpy( &dst[0], src+i, 0x10000 ); + + for ( j = 0; j < 0x200; j++ ) + { + int n = (j & 0x38) >> 3; + int ofst = BITSWAP16(j, 15, 14, 13, 12, 11, 10, 9, t[n][0], t[n][1], t[n][2], 5, 4, 3, t[n][3], t[n][4], t[n][5]); + memcpy( src+i+ofst*128, &dst[j*128], 128 ); + } + } +} + + +/* The King of Fighters 2002 Magic Plus (bootleg) */ + + +void ngbootleg_prot_device::kf2k2mp_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + int i,j; + + UINT8 *src = cpurom; + UINT8 dst[0x80]; + + memmove(src, src + 0x300000, 0x500000); + + for (i = 0; i < 0x800000; i+=0x80) + { + for (j = 0; j < 0x80 / 2; j++) + { + int ofst = BITSWAP8( j, 6, 7, 2, 3, 4, 5, 0, 1 ); + memcpy(dst + j * 2, src + i + ofst * 2, 2); + } + memcpy(src + i, dst, 0x80); + } +} + + +/* The King of Fighters 2002 Magic Plus II (bootleg) */ + + +void ngbootleg_prot_device::kf2k2mp2_px_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + UINT8 *src = cpurom; + dynamic_buffer dst(0x600000); + + memcpy (&dst[0x000000], &src[0x1C0000], 0x040000); + memcpy (&dst[0x040000], &src[0x140000], 0x080000); + memcpy (&dst[0x0C0000], &src[0x100000], 0x040000); + memcpy (&dst[0x100000], &src[0x200000], 0x400000); + memcpy (&src[0x000000], &dst[0x000000], 0x600000); +} + + +/* Crouching Tiger Hidden Dragon 2003 (bootleg of King of Fighters 2001) */ + + +/* descrambling information from razoola */ +void ngbootleg_prot_device::cthd2003_neogeo_gfx_address_fix_do(UINT8* sprrom, UINT32 sprrom_size, int start, int end, int bit3shift, int bit2shift, int bit1shift, int bit0shift) +{ + int i,j; + int tilesize=128; + + dynamic_buffer rom(16*tilesize); // 16 tiles buffer + UINT8* realrom = sprrom + start*tilesize; + + for (i = 0; i < (end-start)/16; i++) { + for (j = 0; j < 16; j++) { + int offset = (((j&1)>>0)<<bit0shift) + +(((j&2)>>1)<<bit1shift) + +(((j&4)>>2)<<bit2shift) + +(((j&8)>>3)<<bit3shift); + + memcpy(&rom[j*tilesize], realrom+offset*tilesize, tilesize); + } + memcpy(realrom,&rom[0],tilesize*16); + realrom+=16*tilesize; + } +} + +void ngbootleg_prot_device::cthd2003_neogeo_gfx_address_fix(UINT8* sprrom, UINT32 sprrom_size, int start, int end) +{ + cthd2003_neogeo_gfx_address_fix_do(sprrom, sprrom_size, start+512*0, end+512*0, 0,3,2,1); + cthd2003_neogeo_gfx_address_fix_do(sprrom, sprrom_size, start+512*1, end+512*1, 1,0,3,2); + cthd2003_neogeo_gfx_address_fix_do(sprrom, sprrom_size, start+512*2, end+512*2, 2,1,0,3); + // skip 3 & 4 + cthd2003_neogeo_gfx_address_fix_do(sprrom, sprrom_size, start+512*5, end+512*5, 0,1,2,3); + cthd2003_neogeo_gfx_address_fix_do(sprrom, sprrom_size, start+512*6, end+512*6, 0,1,2,3); + cthd2003_neogeo_gfx_address_fix_do(sprrom, sprrom_size, start+512*7, end+512*7, 0,2,3,1); +} + +void ngbootleg_prot_device::cthd2003_c(UINT8* sprrom, UINT32 sprrom_size, int pow) +{ + int i; + + for (i=0; i<=192; i+=8) + cthd2003_neogeo_gfx_address_fix(sprrom, sprrom_size, i*512,i*512+512); + + for (i=200; i<=392; i+=8) + cthd2003_neogeo_gfx_address_fix(sprrom, sprrom_size, i*512,i*512+512); + + for (i=400; i<=592; i+=8) + cthd2003_neogeo_gfx_address_fix(sprrom, sprrom_size, i*512,i*512+512); + + for (i=600; i<=792; i+=8) + cthd2003_neogeo_gfx_address_fix(sprrom, sprrom_size, i*512,i*512+512); + + for (i=800; i<=992; i+=8) + cthd2003_neogeo_gfx_address_fix(sprrom, sprrom_size, i*512,i*512+512); + + for (i=1000; i<=1016; i+=8) + cthd2003_neogeo_gfx_address_fix(sprrom, sprrom_size, i*512,i*512+512); +} + +void ngbootleg_prot_device::decrypt_cthd2003(UINT8* sprrom, UINT32 sprrom_size, UINT8* audiorom, UINT32 audiorom_size, UINT8* fixedrom, UINT32 fixedrom_size) +{ + UINT8 *romdata = fixedrom; + dynamic_buffer tmp(8*128*128); + + memcpy(&tmp[8*0*128], romdata+8*0*128, 8*32*128); + memcpy(&tmp[8*32*128], romdata+8*64*128, 8*32*128); + memcpy(&tmp[8*64*128], romdata+8*32*128, 8*32*128); + memcpy(&tmp[8*96*128], romdata+8*96*128, 8*32*128); + memcpy(romdata, &tmp[0], 8*128*128); + + romdata = audiorom+0x10000; + memcpy(&tmp[8*0*128], romdata+8*0*128, 8*32*128); + memcpy(&tmp[8*32*128], romdata+8*64*128, 8*32*128); + memcpy(&tmp[8*64*128], romdata+8*32*128, 8*32*128); + memcpy(&tmp[8*96*128], romdata+8*96*128, 8*32*128); + memcpy(romdata, &tmp[0], 8*128*128); + + memcpy(romdata-0x10000,romdata,0x10000); + + cthd2003_c(sprrom, sprrom_size, 0); +} + +WRITE16_MEMBER( ngbootleg_prot_device::cthd2003_bankswitch_w ) +{ + int bankaddress; + static const int cthd2003_banks[8] = + { + 1,0,1,0,1,0,3,2, + }; + if (offset == 0) + { + bankaddress = 0x100000 + cthd2003_banks[data&7]*0x100000; + m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress); + } +} + +void ngbootleg_prot_device::patch_cthd2003(cpu_device* maincpu, neogeo_banked_cart_device* bankdev, UINT8* cpurom, UINT32 cpurom_size) +{ + /* patches thanks to razoola */ + int i; + UINT16 *mem16 = (UINT16 *)cpurom; + + /* special ROM banking handler */ + maincpu->space(AS_PROGRAM).install_write_handler(0x2ffff0, 0x2fffff, write16_delegate(FUNC(ngbootleg_prot_device::cthd2003_bankswitch_w),this)); + m_bankdev = bankdev; + + // theres still a problem on the character select screen but it seems to be related to cpu core timing issues, + // overclocking the 68k prevents it. + + // fix garbage on s1 layer over everything + mem16[0xf415a/2] = 0x4ef9; + mem16[0xf415c/2] = 0x000f; + mem16[0xf415e/2] = 0x4cf2; + // Fix corruption in attract mode before title screen + for (i=0x1ae290/2;i < 0x1ae8d0/2; i=i+1) + { + mem16[i] = 0x0000; + } + + // Fix for title page + for (i=0x1f8ef0/2;i < 0x1fa1f0/2; i=i+2) + { + mem16[i] -= 0x7000; + mem16[i+1] -= 0x0010; + } + + // Fix for green dots on title page + for (i=0xac500/2;i < 0xac520/2; i=i+1) + { + mem16[i] = 0xFFFF; + } + // Fix for blanks as screen change level end clear + mem16[0x991d0/2] = 0xdd03; + mem16[0x99306/2] = 0xdd03; + mem16[0x99354/2] = 0xdd03; + mem16[0x9943e/2] = 0xdd03; +} + + +/* Crouching Tiger Hidden Dragon 2003 Super Plus (bootleg of King of Fighters 2001) */ + + +void ngbootleg_prot_device::ct2k3sp_sx_decrypt( UINT8* fixedrom, UINT32 fixedrom_size ) +{ + int rom_size = fixedrom_size; + UINT8 *rom = fixedrom; + dynamic_buffer buf( rom_size ); + int i; + int ofst; + + memcpy( &buf[0], rom, rom_size ); + + for( i = 0; i < rom_size; i++ ){ + ofst = BITSWAP24( (i & 0x1ffff), 23, 22, 21, 20, 19, 18, 17, 3, + 0, 1, 4, 2, 13, 14, 16, 15, + 5, 6, 11, 10, 9, 8, 7, 12 ); + + ofst += (i >> 17) << 17; + + rom[ i ] = buf[ ofst ]; + } + + memcpy( &buf[0], rom, rom_size ); + + memcpy( &rom[ 0x08000 ], &buf[ 0x10000 ], 0x8000 ); + memcpy( &rom[ 0x10000 ], &buf[ 0x08000 ], 0x8000 ); + memcpy( &rom[ 0x28000 ], &buf[ 0x30000 ], 0x8000 ); + memcpy( &rom[ 0x30000 ], &buf[ 0x28000 ], 0x8000 ); +} + +void ngbootleg_prot_device::decrypt_ct2k3sp(UINT8* sprrom, UINT32 sprrom_size, UINT8* audiorom, UINT32 audiorom_size, UINT8* fixedrom, UINT32 fixedrom_size) +{ + UINT8 *romdata = audiorom+0x10000; + dynamic_buffer tmp(8*128*128); + memcpy(&tmp[8*0*128], romdata+8*0*128, 8*32*128); + memcpy(&tmp[8*32*128], romdata+8*64*128, 8*32*128); + memcpy(&tmp[8*64*128], romdata+8*32*128, 8*32*128); + memcpy(&tmp[8*96*128], romdata+8*96*128, 8*32*128); + memcpy(romdata, &tmp[0], 8*128*128); + + memcpy(romdata-0x10000,romdata,0x10000); + ct2k3sp_sx_decrypt(fixedrom, fixedrom_size); + cthd2003_c(sprrom,sprrom_size,0); +} + + +/* Crouching Tiger Hidden Dragon 2003 Super Plus alternate (bootleg of King of Fighters 2001) */ + + +void ngbootleg_prot_device::decrypt_ct2k3sa(UINT8* sprrom, UINT32 sprrom_size, UINT8* audiorom, UINT32 audiorom_size ) +{ + UINT8 *romdata = audiorom+0x10000; + dynamic_buffer tmp(8*128*128); + memcpy(&tmp[8*0*128], romdata+8*0*128, 8*32*128); + memcpy(&tmp[8*32*128], romdata+8*64*128, 8*32*128); + memcpy(&tmp[8*64*128], romdata+8*32*128, 8*32*128); + memcpy(&tmp[8*96*128], romdata+8*96*128, 8*32*128); + memcpy(romdata, &tmp[0], 8*128*128); + + memcpy(romdata-0x10000,romdata,0x10000); + cthd2003_c(sprrom,sprrom_size, 0); +} + +void ngbootleg_prot_device::patch_ct2k3sa(UINT8* cpurom, UINT32 cpurom_size) +{ + /* patches thanks to razoola - same as for cthd2003*/ + int i; + UINT16 *mem16 = (UINT16 *)cpurom; + + // theres still a problem on the character select screen but it seems to be related to cpu core timing issues, + // overclocking the 68k prevents it. + + // fix garbage on s1 layer over everything + mem16[0xf415a/2] = 0x4ef9; + mem16[0xf415c/2] = 0x000f; + mem16[0xf415e/2] = 0x4cf2; + + // Fix corruption in attract mode before title screen + for (i=0x1ae290/2;i < 0x1ae8d0/2; i=i+1) + { + mem16[i] = 0x0000; + } + + // Fix for title page + for (i=0x1f8ef0/2;i < 0x1fa1f0/2; i=i+2) + { + mem16[i] -= 0x7000; + mem16[i+1] -= 0x0010; + } + + // Fix for green dots on title page + for (i=0xac500/2;i < 0xac520/2; i=i+1) + { + mem16[i] = 0xFFFF; + } + // Fix for blanks as screen change level end clear + mem16[0x991d0/2] = 0xdd03; + mem16[0x99306/2] = 0xdd03; + mem16[0x99354/2] = 0xdd03; + mem16[0x9943e/2] = 0xdd03; +} + + +/* King of Fighters Special Edition 2004 (bootleg of King of Fighters 2002) */ + + +void ngbootleg_prot_device::decrypt_kof2k4se_68k(UINT8* cpurom, UINT32 cpurom_size) +{ + UINT8 *src = cpurom+0x100000; + dynamic_buffer dst(0x400000); + int i; + static const int sec[] = {0x300000,0x200000,0x100000,0x000000}; + memcpy(&dst[0],src,0x400000); + + for(i = 0; i < 4; ++i) + { + memcpy(src+i*0x100000,&dst[sec[i]],0x100000); + } +} + + +/* Lansquenet 2004 (Shock Troopers - 2nd Squad bootleg) */ + + +void ngbootleg_prot_device::lans2004_vx_decrypt(UINT8* ymsndrom, UINT32 ymsndrom_size) +{ + int i; + UINT8 *rom = ymsndrom; + for (i = 0; i < 0xA00000; i++) + rom[i] = BITSWAP8(rom[i], 0, 1, 5, 4, 3, 2, 6, 7); +} + +void ngbootleg_prot_device::lans2004_decrypt_68k(UINT8* cpurom, UINT32 cpurom_size) +{ + /* Descrambling P ROMs - Thanks to Razoola for the info */ + int i; + UINT8 *src = cpurom; + UINT16 *rom = (UINT16*)cpurom; + + { + static const int sec[] = { 0x3, 0x8, 0x7, 0xC, 0x1, 0xA, 0x6, 0xD }; + dynamic_buffer dst(0x600000); + + for (i = 0; i < 8; i++) + memcpy (&dst[i * 0x20000], src + sec[i] * 0x20000, 0x20000); + + memcpy (&dst[0x0BBB00], src + 0x045B00, 0x001710); + memcpy (&dst[0x02FFF0], src + 0x1A92BE, 0x000010); + memcpy (&dst[0x100000], src + 0x200000, 0x400000); + memcpy (src, &dst[0], 0x600000); + } + + for (i = 0xBBB00/2; i < 0xBE000/2; i++) { + if ((((rom[i]&0xFFBF)==0x4EB9) || ((rom[i]&0xFFBF)==0x43B9)) && (rom[i+1]==0x0000)) { + rom[i + 1] = 0x000B; + rom[i + 2] += 0x6000; + } + } + + /* Patched by protection chip (Altera) ? */ + rom[0x2D15C/2] = 0x000B; + rom[0x2D15E/2] = 0xBB00; + rom[0x2D1E4/2] = 0x6002; + rom[0x2EA7E/2] = 0x6002; + rom[0xBBCD0/2] = 0x6002; + rom[0xBBDF2/2] = 0x6002; + rom[0xBBE42/2] = 0x6002; +} + + +/* Metal Slug 5 Plus (bootleg) */ + + +READ16_MEMBER( ngbootleg_prot_device::mslug5_prot_r ) +{ + logerror("PC %06x: access protected\n",space.device().safe_pc()); + return 0xa0; +} + +WRITE16_MEMBER( ngbootleg_prot_device::ms5plus_bankswitch_w ) +{ + int bankaddress; + logerror("offset: %06x PC %06x: set banking %04x\n",offset,space.device().safe_pc(),data); + if ((offset == 0)&&(data == 0xa0)) + { + bankaddress=0xa0; + m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress); + logerror("offset: %06x PC %06x: set banking %04x\n\n",offset,space.device().safe_pc(),bankaddress); + } + else if(offset == 2) + { + data=data>>4; + //data=data&7; + bankaddress=data*0x100000; + m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress); + logerror("offset: %06x PC %06x: set banking %04x\n\n",offset,space.device().safe_pc(),bankaddress); + } +} + +void ngbootleg_prot_device::install_ms5plus_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev) +{ + // special ROM banking handler / additional protection + maincpu->space(AS_PROGRAM).install_readwrite_handler(0x2ffff0, 0x2fffff,read16_delegate(FUNC(ngbootleg_prot_device::mslug5_prot_r),this), write16_delegate(FUNC(ngbootleg_prot_device::ms5plus_bankswitch_w),this)); + m_bankdev = bankdev; + +} + + +/* SNK vs. CAPCOM SVC CHAOS (bootleg) */ + + +void ngbootleg_prot_device::svcboot_px_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + static const UINT8 sec[] = { + 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00 + }; + int i; + int size = cpurom_size; + UINT8 *src = cpurom; + dynamic_buffer dst( size ); + int ofst; + for( i = 0; i < size / 0x100000; i++ ){ + memcpy( &dst[ i * 0x100000 ], &src[ sec[ i ] * 0x100000 ], 0x100000 ); + } + for( i = 0; i < size / 2; i++ ){ + ofst = BITSWAP8( (i & 0x0000ff), 7, 6, 1, 0, 3, 2, 5, 4 ); + ofst += (i & 0xffff00); + memcpy( &src[ i * 2 ], &dst[ ofst * 2 ], 0x02 ); + } +} + +void ngbootleg_prot_device::svcboot_cx_decrypt(UINT8*sprrom, UINT32 sprrom_size) +{ + static const UINT8 idx_tbl[ 0x10 ] = { + 0, 1, 0, 1, 2, 3, 2, 3, 3, 4, 3, 4, 4, 5, 4, 5, + }; + static const UINT8 bitswap4_tbl[ 6 ][ 4 ] = { + { 3, 0, 1, 2 }, + { 2, 3, 0, 1 }, + { 1, 2, 3, 0 }, + { 0, 1, 2, 3 }, + { 3, 2, 1, 0 }, + { 3, 0, 2, 1 }, + }; + int i; + int size = sprrom_size; + UINT8 *src = sprrom; + dynamic_buffer dst( size ); + int ofst; + memcpy( &dst[0], src, size ); + for( i = 0; i < size / 0x80; i++ ){ + int idx = idx_tbl[ (i & 0xf00) >> 8 ]; + int bit0 = bitswap4_tbl[ idx ][ 0 ]; + int bit1 = bitswap4_tbl[ idx ][ 1 ]; + int bit2 = bitswap4_tbl[ idx ][ 2 ]; + int bit3 = bitswap4_tbl[ idx ][ 3 ]; + ofst = BITSWAP8( (i & 0x0000ff), 7, 6, 5, 4, bit3, bit2, bit1, bit0 ); + ofst += (i & 0xfffff00); + memcpy( &src[ i * 0x80 ], &dst[ ofst * 0x80 ], 0x80 ); + } +} + + +/* SNK vs. CAPCOM SVC CHAOS Plus (bootleg set 1) */ + + +void ngbootleg_prot_device::svcplus_px_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + static const int sec[] = { + 0x00, 0x03, 0x02, 0x05, 0x04, 0x01 + }; + int size = cpurom_size; + UINT8 *src = cpurom; + dynamic_buffer dst( size ); + int i; + int ofst; + memcpy( &dst[0], src, size ); + for( i = 0; i < size / 2; i++ ){ + ofst = BITSWAP24( (i & 0xfffff), 0x17, 0x16, 0x15, 0x14, 0x13, 0x00, 0x01, 0x02, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x10, 0x11, 0x12 ); + ofst ^= 0x0f0007; + ofst += (i & 0xff00000); + memcpy( &src[ i * 0x02 ], &dst[ ofst * 0x02 ], 0x02 ); + } + memcpy( &dst[0], src, size ); + for( i = 0; i < 6; i++ ){ + memcpy( &src[ i * 0x100000 ], &dst[ sec[ i ] * 0x100000 ], 0x100000 ); + } +} + +void ngbootleg_prot_device::svcplus_px_hack(UINT8* cpurom, UINT32 cpurom_size) +{ + /* patched by the protection chip? */ + UINT16 *mem16 = (UINT16 *)cpurom; + mem16[0x0f8016/2] = 0x33c1; +} + + +/* SNK vs. CAPCOM SVC CHAOS Plus (bootleg set 2) */ + + +void ngbootleg_prot_device::svcplusa_px_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + int i; + static const int sec[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x00 + }; + int size = cpurom_size; + UINT8 *src = cpurom; + dynamic_buffer dst( size ); + memcpy( &dst[0], src, size ); + for( i = 0; i < 6; i++ ){ + memcpy( &src[ i * 0x100000 ], &dst[ sec[ i ] * 0x100000 ], 0x100000 ); + } +} + + +/* SNK vs. CAPCOM SVC CHAOS Super Plus (bootleg) */ + + +void ngbootleg_prot_device::svcsplus_px_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + static const int sec[] = { + 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00 + }; + int size = cpurom_size; + UINT8 *src = cpurom; + dynamic_buffer dst( size ); + int i; + int ofst; + memcpy( &dst[0], src, size ); + for( i = 0; i < size / 2; i++ ){ + ofst = BITSWAP16( (i & 0x007fff), 0x0f, 0x00, 0x08, 0x09, 0x0b, 0x0a, 0x0c, 0x0d, + 0x04, 0x03, 0x01, 0x07, 0x06, 0x02, 0x05, 0x0e ); + + ofst += (i & 0x078000); + ofst += sec[ (i & 0xf80000) >> 19 ] << 19; + memcpy( &src[ i * 2 ], &dst[ ofst * 2 ], 0x02 ); + } +} + +void ngbootleg_prot_device::svcsplus_px_hack(UINT8* cpurom, UINT32 cpurom_size) +{ + /* patched by the protection chip? */ + UINT16 *mem16 = (UINT16 *)cpurom; + mem16[0x9e90/2] = 0x000f; + mem16[0x9e92/2] = 0xc9c0; + mem16[0xa10c/2] = 0x4eb9; + mem16[0xa10e/2] = 0x000e; + mem16[0xa110/2] = 0x9750; +} + + +/* The King of Fighters 2003 (bootleg set 1) */ + + +READ16_MEMBER( ngbootleg_prot_device::kof2003_r) +{ + return m_cartridge_ram[offset]; +} + +READ16_MEMBER(ngbootleg_prot_device::kof2003_overlay_r) // hack? +{ + return kof2k3_overlay; +} + +WRITE16_MEMBER( ngbootleg_prot_device::kof2003_w ) +{ + data = COMBINE_DATA(&m_cartridge_ram[offset]); + if (offset == 0x1ff0/2 || offset == 0x1ff2/2) { + UINT8* cr = (UINT8 *)m_cartridge_ram; + UINT32 address = (cr[BYTE_XOR_LE(0x1ff3)]<<16)|(cr[BYTE_XOR_LE(0x1ff2)]<<8)|cr[BYTE_XOR_LE(0x1ff1)]; + UINT8 prt = cr[BYTE_XOR_LE(0x1ff2)]; + + cr[BYTE_XOR_LE(0x1ff0)] = 0xa0; + cr[BYTE_XOR_LE(0x1ff1)] &= 0xfe; + cr[BYTE_XOR_LE(0x1ff3)] &= 0x7f; + m_bankdev->neogeo_set_main_cpu_bank_address(address+0x100000); + + kof2k3_overlay = (prt & 0x00ff) | (kof2k3_overlay & 0xff00); + } +} + +WRITE16_MEMBER( ngbootleg_prot_device::kof2003p_w ) +{ + data = COMBINE_DATA(&m_cartridge_ram[offset]); + if (offset == 0x1ff0/2 || offset == 0x1ff2/2) { + UINT8* cr = (UINT8 *)m_cartridge_ram; + UINT32 address = (cr[BYTE_XOR_LE(0x1ff3)]<<16)|(cr[BYTE_XOR_LE(0x1ff2)]<<8)|cr[BYTE_XOR_LE(0x1ff0)]; + UINT8 prt = cr[BYTE_XOR_LE(0x1ff2)]; + + cr[BYTE_XOR_LE(0x1ff0)] &= 0xfe; + cr[BYTE_XOR_LE(0x1ff3)] &= 0x7f; + m_bankdev->neogeo_set_main_cpu_bank_address(address+0x100000); + + kof2k3_overlay = (prt & 0x00ff) | (kof2k3_overlay & 0xff00); + } +} + +void ngbootleg_prot_device::kf2k3bl_px_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + int i; + static const UINT8 sec[] = { + 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 + }; + + int rom_size = 0x800000; + UINT8 *rom = cpurom; + dynamic_buffer buf( rom_size ); + memcpy( &buf[0], rom, rom_size ); + + for( i = 0; i < rom_size / 0x100000; i++ ){ + memcpy( &rom[ i * 0x100000 ], &buf[ sec[ i ] * 0x100000 ], 0x100000 ); + } +} + +void ngbootleg_prot_device::kf2k3bl_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev, UINT8* cpurom, UINT32 cpurom_size) +{ + m_mainrom = cpurom; + + maincpu->space(AS_PROGRAM).install_read_handler(0x58196, 0x58197, read16_delegate(FUNC(ngbootleg_prot_device::kof2003_overlay_r),this) ); + + maincpu->space(AS_PROGRAM).install_readwrite_handler(0x2fe000, 0x2fffff, read16_delegate(FUNC(ngbootleg_prot_device::kof2003_r),this), write16_delegate(FUNC(ngbootleg_prot_device::kof2003_w),this) ); + m_bankdev = bankdev; + +} + + +/* The King of Fighters 2004 Plus / Hero (The King of Fighters 2003 bootleg) */ + + +void ngbootleg_prot_device::kf2k3pl_px_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + std::vector<UINT16> tmp(0x100000/2); + UINT16*rom16 = (UINT16*)cpurom; + int j; + int i; + + for (i = 0;i < 0x700000/2;i+=0x100000/2) + { + memcpy(&tmp[0],&rom16[i],0x100000); + for (j = 0;j < 0x100000/2;j++) + rom16[i+j] = tmp[BITSWAP24(j,23,22,21,20,19,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)]; + } + + /* patched by Altera protection chip on PCB */ + rom16[0xf38ac/2] = 0x4e75; + + kof2k3_overlay = rom16[0x58196 / 2]; +} + +void ngbootleg_prot_device::kf2k3pl_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev, UINT8* cpurom, UINT32 cpurom_size) +{ + m_mainrom = cpurom; + maincpu->space(AS_PROGRAM).install_readwrite_handler(0x2fe000, 0x2fffff, read16_delegate(FUNC(ngbootleg_prot_device::kof2003_r),this), write16_delegate(FUNC(ngbootleg_prot_device::kof2003p_w),this) ); + m_bankdev = bankdev; +} + + +/* The King of Fighters 2004 Ultra Plus (The King of Fighters 2003 bootleg) */ + + +void ngbootleg_prot_device::kf2k3upl_px_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + { + UINT8 *src = cpurom; + memmove(src+0x100000, src, 0x600000); + memmove(src, src+0x700000, 0x100000); + } + + { + int ofst; + int i; + UINT8 *rom = cpurom + 0xfe000; + UINT8 *buf = cpurom + 0xd0610; + + for( i = 0; i < 0x2000 / 2; i++ ){ + ofst = (i & 0xff00) + BITSWAP8( (i & 0x00ff), 7, 6, 0, 4, 3, 2, 1, 5 ); + memcpy( &rom[ i * 2 ], &buf[ ofst * 2 ], 2 ); + } + } + + UINT16*rom16 = (UINT16*)cpurom; + kof2k3_overlay = rom16[0x58196 / 2]; + + +} + + +/* Samurai Shodown V / Samurai Spirits Zero (bootleg) */ + + +void ngbootleg_prot_device::samsho5b_px_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + int px_size = cpurom_size; + UINT8 *rom = cpurom; + dynamic_buffer buf( px_size ); + int ofst; + int i; + + memcpy( &buf[0], rom, px_size ); + + for( i = 0; i < px_size / 2; i++ ){ + ofst = BITSWAP8( (i & 0x000ff), 7, 6, 5, 4, 3, 0, 1, 2 ); + ofst += (i & 0xfffff00); + ofst ^= 0x060005; + + memcpy( &rom[ i * 2 ], &buf[ ofst * 2 ], 0x02 ); + } + + memcpy( &buf[0], rom, px_size ); + + memcpy( &rom[ 0x000000 ], &buf[ 0x700000 ], 0x100000 ); + memcpy( &rom[ 0x100000 ], &buf[ 0x000000 ], 0x700000 ); +} + + +void ngbootleg_prot_device::samsho5b_vx_decrypt(UINT8* ymsndrom, UINT32 ymsndrom_size) +{ + int vx_size = ymsndrom_size; + UINT8 *rom = ymsndrom; + int i; + + for( i = 0; i < vx_size; i++ ) + rom[ i ] = BITSWAP8( rom[ i ], 0, 1, 5, 4, 3, 2, 6, 7 ); +} + + +/* Matrimelee / Shin Gouketsuji Ichizoku Toukon (bootleg) */ + + +#define MATRIMBLZ80( i ) ( i^(BITSWAP8(i&0x3,4,3,1,2,0,7,6,5)<<8) ) + +void ngbootleg_prot_device::matrimbl_decrypt(UINT8* sprrom, UINT32 sprrom_size, UINT8* audiorom, UINT32 audiorom_size) +{ + /* decrypt Z80 */ + UINT8 *rom = audiorom+0x10000; + dynamic_buffer buf( 0x20000 ); + int i, j=0; + memcpy( &buf[0], rom, 0x20000 ); + for( i=0x00000; i<0x20000; i++ ) + { + if ( i&0x10000 ) + { + if ( i&0x800 ) + { + j=MATRIMBLZ80( i ); + j=j^0x10000; + } + else + { + j=MATRIMBLZ80(( i^0x01 )); + } + } + else + { + if ( i&0x800 ) + { + j=MATRIMBLZ80(( i^0x01 )); + j=j^0x10000; + } + else + { + j=MATRIMBLZ80( i ); + } + } + rom[ j ]=buf[ i ]; + } + memcpy( rom-0x10000, rom, 0x10000 ); + + /* decrypt gfx */ + cthd2003_c(sprrom,sprrom_size, 0 ); +} diff --git a/src/devices/bus/neogeo/bootleg_prot.h b/src/devices/bus/neogeo/bootleg_prot.h new file mode 100644 index 00000000000..6ad1f257845 --- /dev/null +++ b/src/devices/bus/neogeo/bootleg_prot.h @@ -0,0 +1,98 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + +#pragma once + +#include "banked_cart.h" + +#ifndef __NGBOOTLEG_PROT__ +#define __NGBOOTLEG_PROT__ + +extern const device_type NGBOOTLEG_PROT; + +#define MCFG_NGBOOTLEG_PROT_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, NGBOOTLEG_PROT, 0) + + +class ngbootleg_prot_device : public device_t +{ +public: + // construction/destruction + ngbootleg_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + void neogeo_bootleg_cx_decrypt(UINT8*sprrom, UINT32 sprrom_size); + void neogeo_bootleg_sx_decrypt(UINT8* fixed, UINT32 fixed_size, int value); + void kof97oro_px_decode(UINT8* cpurom, UINT32 cpurom_size); + void kof10thBankswitch(address_space &space, UINT16 nBank); + DECLARE_READ16_MEMBER(kof10th_RAM2_r); + DECLARE_READ16_MEMBER(kof10th_RAMB_r); + DECLARE_WRITE16_MEMBER(kof10th_custom_w); + DECLARE_WRITE16_MEMBER(kof10th_bankswitch_w); + void install_kof10th_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev, UINT8* cpurom, UINT32 cpurom_size, UINT8* fixedrom, UINT32 fixedrom_size); + void decrypt_kof10th(UINT8* cpurom, UINT32 cpurom_size); + void kf10thep_px_decrypt(UINT8* cpurom, UINT32 cpurom_size); + void kf2k5uni_px_decrypt(UINT8* cpurom, UINT32 cpurom_size); + void kf2k5uni_sx_decrypt(UINT8* fixedrom, UINT32 fixedrom_size); + void kf2k5uni_mx_decrypt(UINT8* audiorom, UINT32 audiorom_size); + void decrypt_kf2k5uni(UINT8* cpurom, UINT32 cpurom_size, UINT8* audiorom, UINT32 audiorom_size, UINT8* fixedrom, UINT32 fixedrom_size); + void kof2002b_gfx_decrypt(UINT8 *src, int size); + void kf2k2mp_decrypt(UINT8* cpurom, UINT32 cpurom_size); + void kf2k2mp2_px_decrypt(UINT8* cpurom, UINT32 cpurom_size); + void cthd2003_neogeo_gfx_address_fix_do(UINT8* sprrom, UINT32 sprrom_size, int start, int end, int bit3shift, int bit2shift, int bit1shift, int bit0shift); + void cthd2003_neogeo_gfx_address_fix(UINT8* sprrom, UINT32 sprrom_size, int start, int end); + void cthd2003_c(UINT8* sprrom, UINT32 sprrom_size, int pow); + void decrypt_cthd2003(UINT8* sprrom, UINT32 sprrom_size, UINT8* audiorom, UINT32 audiorom_size, UINT8* fixedrom, UINT32 fixedrom_size); + DECLARE_WRITE16_MEMBER(cthd2003_bankswitch_w); + void patch_cthd2003(cpu_device* maincpu, neogeo_banked_cart_device* bankdev, UINT8* cpurom, UINT32 cpurom_size); + void ct2k3sp_sx_decrypt(UINT8* fixedrom, UINT32 fixedrom_size); + void decrypt_ct2k3sp(UINT8* sprrom, UINT32 sprrom_size, UINT8* audiorom, UINT32 audiorom_size, UINT8* fixedrom, UINT32 fixedrom_size); + void decrypt_ct2k3sa(UINT8* sprrom, UINT32 sprrom_size, UINT8* audiorom, UINT32 audiorom_size); + void patch_ct2k3sa(UINT8* cpurom, UINT32 cpurom_size); + void decrypt_kof2k4se_68k(UINT8* cpurom, UINT32 cpurom_size); + void lans2004_vx_decrypt(UINT8* ymsndrom, UINT32 ymsndrom_size); + void lans2004_decrypt_68k(UINT8* cpurom, UINT32 cpurom_size); + DECLARE_READ16_MEMBER(mslug5_prot_r); + DECLARE_WRITE16_MEMBER(ms5plus_bankswitch_w); + void install_ms5plus_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev); + void svcboot_px_decrypt(UINT8* cpurom, UINT32 cpurom_size); + void svcboot_cx_decrypt(UINT8*sprrom, UINT32 sprrom_size); + void svcplus_px_decrypt(UINT8* cpurom, UINT32 cpurom_size); + void svcplus_px_hack(UINT8* cpurom, UINT32 cpurom_size); + void svcplusa_px_decrypt(UINT8* cpurom, UINT32 cpurom_size); + void svcsplus_px_decrypt(UINT8* cpurom, UINT32 cpurom_size); + void svcsplus_px_hack(UINT8* cpurom, UINT32 cpurom_size); + DECLARE_READ16_MEMBER(kof2003_r); + DECLARE_WRITE16_MEMBER(kof2003_w); + DECLARE_WRITE16_MEMBER(kof2003p_w); + DECLARE_READ16_MEMBER(kof2003_overlay_r); + void kf2k3bl_px_decrypt(UINT8* cpurom, UINT32 cpurom_size); + void kf2k3bl_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev, UINT8* cpurom, UINT32 cpurom_size); + void kf2k3pl_px_decrypt(UINT8* cpurom, UINT32 cpurom_size); + void kf2k3pl_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev, UINT8* cpurom, UINT32 cpurom_size); + UINT16 kof2k3_overlay; + + void kf2k3upl_px_decrypt(UINT8* cpurom, UINT32 cpurom_size); + void samsho5b_px_decrypt(UINT8* cpurom, UINT32 cpurom_size); + void samsho5b_vx_decrypt(UINT8* ymsndrom, UINT32 ymsndrom_size); + void matrimbl_decrypt(UINT8* sprrom, UINT32 sprrom_size, UINT8* audiorom, UINT32 audiorom_size); + + UINT16 m_cartridge_ram[0x1000]; // bootlegs + + // for kof10th + UINT8* m_mainrom; + UINT8* m_fixedrom; + neogeo_banked_cart_device* m_bankdev; + UINT16 m_cartridge_ram2[0x10000]; + +protected: + virtual void device_start(); + virtual void device_reset(); + + + +private: + + +}; + +#endif diff --git a/src/devices/bus/neogeo/cmc_cart.c b/src/devices/bus/neogeo/cmc_cart.c new file mode 100644 index 00000000000..c528366b717 --- /dev/null +++ b/src/devices/bus/neogeo/cmc_cart.c @@ -0,0 +1,223 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/*********************************************************************************************************** + + NEOGEO ROM cart emulation + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "cmc_cart.h" + + +//------------------------------------------------- +// neogeo_cmc_cart - constructor +//------------------------------------------------- + +const device_type NEOGEO_CMC_CART = &device_creator<neogeo_cmc_cart>; + + +neogeo_cmc_cart::neogeo_cmc_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_cmc_prot(*this, "cmc_prot") + +{ +} + +neogeo_cmc_cart::neogeo_cmc_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock) + : device_t(mconfig, NEOGEO_CMC_CART, "NEOGEO SMA Cart", tag, owner, clock, "neogeo_rom", __FILE__), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_cmc_prot(*this, "cmc_prot") +{ +} + + +//------------------------------------------------- +// mapper specific start/reset +//------------------------------------------------- + +void neogeo_cmc_cart::device_start() +{ +} + +void neogeo_cmc_cart::device_reset() +{ +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +READ16_MEMBER(neogeo_cmc_cart::read_rom) +{ + return m_rom[offset]; +} + +static MACHINE_CONFIG_FRAGMENT( cmc_cart ) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") + MCFG_CMC_PROT_ADD("cmc_prot") +MACHINE_CONFIG_END + +machine_config_constructor neogeo_cmc_cart::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( cmc_cart ); +} + + + +/* Individual cartridge types (mirror DRIVER_INIT functionality) */ + +/************************************************* + Zupapa +**************************************************/ + +const device_type NEOGEO_CMC_ZUPAPA_CART = &device_creator<neogeo_cmc_zupapa_cart>; + +neogeo_cmc_zupapa_cart::neogeo_cmc_zupapa_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_cmc_cart(mconfig, NEOGEO_CMC_ZUPAPA_CART, "NEOGEO CMC zupapa Cart", tag, owner, clock, "cmc_zupapa_cart", __FILE__) {} + +void neogeo_cmc_zupapa_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, ZUPAPA_GFX_KEY); +} + + +/************************************************* + Zupapa +**************************************************/ + +const device_type NEOGEO_CMC_MSLUG3H_CART = &device_creator<neogeo_cmc_mslug3h_cart>; + +neogeo_cmc_mslug3h_cart::neogeo_cmc_mslug3h_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_cmc_cart(mconfig, NEOGEO_CMC_MSLUG3H_CART, "NEOGEO CMC mslug3h Cart", tag, owner, clock, "cmc_mslug3h_cart", __FILE__) {} + +void neogeo_cmc_mslug3h_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, MSLUG3_GFX_KEY); +} + + +/************************************************* + Ganryu +**************************************************/ + +const device_type NEOGEO_CMC_GANRYU_CART = &device_creator<neogeo_cmc_ganryu_cart>; + +neogeo_cmc_ganryu_cart::neogeo_cmc_ganryu_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_cmc_cart(mconfig, NEOGEO_CMC_GANRYU_CART, "NEOGEO CMC ganryu Cart", tag, owner, clock, "cmc_ganryu_cart", __FILE__) {} + +void neogeo_cmc_ganryu_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, GANRYU_GFX_KEY); +} + + +/************************************************* + S1945P +**************************************************/ + +const device_type NEOGEO_CMC_S1945P_CART = &device_creator<neogeo_cmc_s1945p_cart>; + +neogeo_cmc_s1945p_cart::neogeo_cmc_s1945p_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_cmc_cart(mconfig, NEOGEO_CMC_S1945P_CART, "NEOGEO CMC s1945p Cart", tag, owner, clock, "cmc_s1945p_cart", __FILE__) {} + +void neogeo_cmc_s1945p_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, S1945P_GFX_KEY); +} + +/************************************************* + PREISLE2 +**************************************************/ + +const device_type NEOGEO_CMC_PREISLE2_CART = &device_creator<neogeo_cmc_preisle2_cart>; + +neogeo_cmc_preisle2_cart::neogeo_cmc_preisle2_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_cmc_cart(mconfig, NEOGEO_CMC_PREISLE2_CART, "NEOGEO CMC preisle2 Cart", tag, owner, clock, "cmc_preisle2_cart", __FILE__) {} + +void neogeo_cmc_preisle2_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, PREISLE2_GFX_KEY); +} + +/************************************************* + BANGBEAD +**************************************************/ + +const device_type NEOGEO_CMC_BANGBEAD_CART = &device_creator<neogeo_cmc_bangbead_cart>; + +neogeo_cmc_bangbead_cart::neogeo_cmc_bangbead_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_cmc_cart(mconfig, NEOGEO_CMC_BANGBEAD_CART, "NEOGEO CMC bangbead Cart", tag, owner, clock, "cmc_bangbead_cart", __FILE__) {} + +void neogeo_cmc_bangbead_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, BANGBEAD_GFX_KEY); +} + +/************************************************* + NITD +**************************************************/ + +const device_type NEOGEO_CMC_NITD_CART = &device_creator<neogeo_cmc_nitd_cart>; + +neogeo_cmc_nitd_cart::neogeo_cmc_nitd_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_cmc_cart(mconfig, NEOGEO_CMC_NITD_CART, "NEOGEO CMC nitd Cart", tag, owner, clock, "cmc_nitd_cart", __FILE__) {} + +void neogeo_cmc_nitd_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, NITD_GFX_KEY); +} + + +/************************************************* + SENGOKU3 +**************************************************/ + +const device_type NEOGEO_CMC_SENGOKU3_CART = &device_creator<neogeo_cmc_sengoku3_cart>; + +neogeo_cmc_sengoku3_cart::neogeo_cmc_sengoku3_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_cmc_cart(mconfig, NEOGEO_CMC_SENGOKU3_CART, "NEOGEO CMC sengoku3 Cart", tag, owner, clock, "cmc_sengoku3_cart", __FILE__) {} + +void neogeo_cmc_sengoku3_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, SENGOKU3_GFX_KEY); +} + +/************************************************* + KOF99K +**************************************************/ + +const device_type NEOGEO_CMC_KOF99K_CART = &device_creator<neogeo_cmc_kof99k_cart>; + +neogeo_cmc_kof99k_cart::neogeo_cmc_kof99k_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_cmc_cart(mconfig, NEOGEO_CMC_KOF99K_CART, "NEOGEO CMC kof99k Cart", tag, owner, clock, "cmc_kof99k_cart", __FILE__) {} + +void neogeo_cmc_kof99k_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF99_GFX_KEY); +} + + +/************************************************* + KOF2001 +**************************************************/ + +const device_type NEOGEO_CMC_KOF2001_CART = &device_creator<neogeo_cmc_kof2001_cart>; + +neogeo_cmc_kof2001_cart::neogeo_cmc_kof2001_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_cmc_cart(mconfig, NEOGEO_CMC_KOF2001_CART, "NEOGEO CMC kof2001 Cart", tag, owner, clock, "cmc_kof2001_cart", __FILE__) {} + +void neogeo_cmc_kof2001_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF2001_GFX_KEY); +} + +/************************************************* + KOF2000N +**************************************************/ + +const device_type NEOGEO_CMC_KOF2000N_CART = &device_creator<neogeo_cmc_kof2000n_cart>; + +neogeo_cmc_kof2000n_cart::neogeo_cmc_kof2000n_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_cmc_cart(mconfig, NEOGEO_CMC_KOF2000N_CART, "NEOGEO CMC kof2000n Cart", tag, owner, clock, "cmc_kof2000n_cart", __FILE__) {} + +void neogeo_cmc_kof2000n_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF2000_GFX_KEY); +} diff --git a/src/devices/bus/neogeo/cmc_cart.h b/src/devices/bus/neogeo/cmc_cart.h new file mode 100644 index 00000000000..2e07e29c93f --- /dev/null +++ b/src/devices/bus/neogeo/cmc_cart.h @@ -0,0 +1,191 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#ifndef __NEOGEO_CMC_CART_H +#define __NEOGEO_CMC_CART_H + +#include "neogeo_slot.h" +#include "banked_cart.h" +#include "sma_prot.h" +#include "cmc_prot.h" + +// ======================> neogeo_cmc_cart + +class neogeo_cmc_cart : public device_t, + public device_neogeo_cart_interface +{ +public: + // construction/destruction + neogeo_cmc_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source); + neogeo_cmc_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ16_MEMBER(read_rom); + + virtual void activate_cart(ACTIVATE_CART_PARAMS) { m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); } + virtual void decrypt_all(DECRYPT_ALL_PARAMS) {} + virtual int get_fixed_bank_type(void) { return 0; } + + required_device<neogeo_banked_cart_device> m_banked_cart; + required_device<cmc_prot_device> m_cmc_prot; +}; + + + +// device type definition +extern const device_type NEOGEO_CMC_CART; + + +/************************************************* + ZUPAPA +**************************************************/ + +class neogeo_cmc_zupapa_cart : public neogeo_cmc_cart +{ +public: + neogeo_cmc_zupapa_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_CMC_ZUPAPA_CART; + +/************************************************* + MSLUG3H +**************************************************/ + +class neogeo_cmc_mslug3h_cart : public neogeo_cmc_cart +{ +public: + neogeo_cmc_mslug3h_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_CMC_MSLUG3H_CART; + + +/************************************************* + GANRYU +**************************************************/ + +class neogeo_cmc_ganryu_cart : public neogeo_cmc_cart +{ +public: + neogeo_cmc_ganryu_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_CMC_GANRYU_CART; + +/************************************************* + S1945P +**************************************************/ + +class neogeo_cmc_s1945p_cart : public neogeo_cmc_cart +{ +public: + neogeo_cmc_s1945p_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_CMC_S1945P_CART; + + +/************************************************* + PREISLE2 +**************************************************/ + +class neogeo_cmc_preisle2_cart : public neogeo_cmc_cart +{ +public: + neogeo_cmc_preisle2_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_CMC_PREISLE2_CART; + +/************************************************* + BANGBEAD +**************************************************/ + +class neogeo_cmc_bangbead_cart : public neogeo_cmc_cart +{ +public: + neogeo_cmc_bangbead_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_CMC_BANGBEAD_CART; + + +/************************************************* + NITD +**************************************************/ + +class neogeo_cmc_nitd_cart : public neogeo_cmc_cart +{ +public: + neogeo_cmc_nitd_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_CMC_NITD_CART; + +/************************************************* + SENGOKU3 +**************************************************/ + +class neogeo_cmc_sengoku3_cart : public neogeo_cmc_cart +{ +public: + neogeo_cmc_sengoku3_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_CMC_SENGOKU3_CART; + +/************************************************* + KOF99K +**************************************************/ + +class neogeo_cmc_kof99k_cart : public neogeo_cmc_cart +{ +public: + neogeo_cmc_kof99k_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_CMC_KOF99K_CART; + +/************************************************* + KOF2001 +**************************************************/ + +class neogeo_cmc_kof2001_cart : public neogeo_cmc_cart +{ +public: + neogeo_cmc_kof2001_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_CMC_KOF2001_CART; + +/************************************************* + KOF2000N +**************************************************/ + +class neogeo_cmc_kof2000n_cart : public neogeo_cmc_cart +{ +public: + neogeo_cmc_kof2000n_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 2; } +}; +extern const device_type NEOGEO_CMC_KOF2000N_CART; + + + +#endif diff --git a/src/devices/bus/neogeo/cmc_prot.c b/src/devices/bus/neogeo/cmc_prot.c new file mode 100644 index 00000000000..f4ccc1ecada --- /dev/null +++ b/src/devices/bus/neogeo/cmc_prot.c @@ -0,0 +1,789 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + +#include "emu.h" +#include "cmc_prot.h" + + + +extern const device_type CMC_PROT = &device_creator<cmc_prot_device>; + + +cmc_prot_device::cmc_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, CMC_PROT, "NeoGeo Protection (CMC)", tag, owner, clock, "cmc_prot", __FILE__) +{ +} + + +void cmc_prot_device::device_start() +{ +} + +void cmc_prot_device::device_reset() +{ +} + + + + + + + +/*************************************************************************** + +NeoGeo 'C' ROM encryption + +Starting with KOF99, all NeoGeo games have encrypted graphics. Additionally +to that, the data for the front text layer, which was previously stored in +a separate ROM, is stored at the end of the tile data. + +The encryption is one of the nastiest implementation of a XOR scheme ever +seen, involving 9 seemingly uncorrelated 256-byte tables. All known games use +the same tables except KOF2000 and MS4 which use a different set. + +The 32 data bits of every longword are decrypted in a single step (one byte at +a time), but the values to use for the xor are determined in a convoluted way. +It's actually so convoluted that it's too difficult to describe - please refer +to the source below. +Suffice to say that bytes are handled in couples (0&3 and 1&2), and the two xor +values are taken from three tables, the indexes inside the tables depending on +bits 0-7 and 8-15 of the address, in one case further xored through the table +used in step 5) below. Additionally, the bytes in a couple can be swapped, +depending either on bit 8 of the address, or on bit 16 xored with the table +used in step 4) below. + +The 24 address bits are encrypted in five steps. Each step xors 8 bits with a +value taken from a different table; the index inside the table depends on 8 +other bits. +0) xor bits 0-7 with a fixed value that changes from game to game +1) xor bits 8-15 depending on bits 16-23 +2) xor bits 8-15 depending on bits 0-7 +3) xor bits 16-23 depending on bits 0-7 +4) xor bits 16-23 depending on bits 8-15 +5) xor bits 0-7 depending on bits 8-15 + +Each step acts on the current value, so e.g. step 4) uses bits 8-15 as modified +by step 2). + +[Note: the table used in step 1) is currently incomplete due to lack of data to +analyze] + + +There are two major weaknesses in this encryption algorithm, that exposed it to +a known plaintext attack. + +The first weakness is that the data xor depends on the address inside the +encrypted ROM instead that on the decrypted address; together with the high +concentration of 0x00 and 0xFF in the decrypted data (more than 60% of the +total), this exposed easily recognizable patterns in the encrypted data, which +could be exploited with some simple statistical checks. The deviousness of the +xor scheme was the major difficulty. + +The second weakness is that the address scrambling works on 32-bit words. Since +there are a large number of 32-bit values that appear only once in the whole +encrypted ROM space, this means that once the xor layer was broken, a large +table of encrypted-decrypted address correspondencies could be built and +analyzed, quickly leading to the algorithm. + +***************************************************************************/ + +static const UINT8 kof99_type0_t03[256] = +{ + 0xfb, 0x86, 0x9d, 0xf1, 0xbf, 0x80, 0xd5, 0x43, 0xab, 0xb3, 0x9f, 0x6a, 0x33, 0xd9, 0xdb, 0xb6, + 0x66, 0x08, 0x69, 0x88, 0xcc, 0xb7, 0xde, 0x49, 0x97, 0x64, 0x1f, 0xa6, 0xc0, 0x2f, 0x52, 0x42, + 0x44, 0x5a, 0xf2, 0x28, 0x98, 0x87, 0x96, 0x8a, 0x83, 0x0b, 0x03, 0x61, 0x71, 0x99, 0x6b, 0xb5, + 0x1a, 0x8e, 0xfe, 0x04, 0xe1, 0xf7, 0x7d, 0xdd, 0xed, 0xca, 0x37, 0xfc, 0xef, 0x39, 0x72, 0xda, + 0xb8, 0xbe, 0xee, 0x7f, 0xe5, 0x31, 0x78, 0xf3, 0x91, 0x9a, 0xd2, 0x11, 0x19, 0xb9, 0x09, 0x4c, + 0xfd, 0x6d, 0x2a, 0x4d, 0x65, 0xa1, 0x89, 0xc7, 0x75, 0x50, 0x21, 0xfa, 0x16, 0x00, 0xe9, 0x12, + 0x74, 0x2b, 0x1e, 0x4f, 0x14, 0x01, 0x70, 0x3a, 0x4e, 0x3f, 0xf5, 0xf4, 0x1d, 0x3d, 0x15, 0x27, + 0xa7, 0xff, 0x45, 0xe0, 0x6e, 0xf9, 0x54, 0xc8, 0x48, 0xad, 0xa5, 0x0a, 0xf6, 0x2d, 0x2c, 0xe2, + 0x68, 0x67, 0xd6, 0x85, 0xb4, 0xc3, 0x34, 0xbc, 0x62, 0xd3, 0x5f, 0x84, 0x06, 0x5b, 0x0d, 0x95, + 0xea, 0x5e, 0x9e, 0xd4, 0xeb, 0x90, 0x7a, 0x05, 0x81, 0x57, 0xe8, 0x60, 0x2e, 0x20, 0x25, 0x7c, + 0x46, 0x0c, 0x93, 0xcb, 0xbd, 0x17, 0x7e, 0xec, 0x79, 0xb2, 0xc2, 0x22, 0x41, 0xb1, 0x10, 0xac, + 0xa8, 0xbb, 0x9b, 0x82, 0x4b, 0x9c, 0x8b, 0x07, 0x47, 0x35, 0x24, 0x56, 0x8d, 0xaf, 0xe6, 0x26, + 0x40, 0x38, 0xc4, 0x5d, 0x1b, 0xc5, 0xd1, 0x0f, 0x6c, 0x7b, 0xb0, 0xe3, 0xa3, 0x23, 0x6f, 0x58, + 0xc1, 0xba, 0xcf, 0xd7, 0xa2, 0xe7, 0xd0, 0x63, 0x5c, 0xf8, 0x73, 0xa0, 0x13, 0xdc, 0x29, 0xcd, + 0xc9, 0x76, 0xae, 0x8f, 0xe4, 0x59, 0x30, 0xaa, 0x94, 0x1c, 0x3c, 0x0e, 0x55, 0x92, 0x77, 0x32, + 0xc6, 0xce, 0x18, 0x36, 0xdf, 0xa9, 0x8c, 0xd8, 0xa4, 0xf0, 0x3b, 0x51, 0x4a, 0x02, 0x3e, 0x53, +}; + + +static const UINT8 kof99_type0_t12[256] = +{ + 0x1f, 0xac, 0x4d, 0xcd, 0xca, 0x70, 0x02, 0x6b, 0x18, 0x40, 0x62, 0xb2, 0x3f, 0x9b, 0x5b, 0xef, + 0x69, 0x68, 0x71, 0x3b, 0xcb, 0xd4, 0x30, 0xbc, 0x47, 0x72, 0x74, 0x5e, 0x84, 0x4c, 0x1b, 0xdb, + 0x6a, 0x35, 0x1d, 0xf5, 0xa1, 0xb3, 0x87, 0x5d, 0x57, 0x28, 0x2f, 0xc4, 0xfd, 0x24, 0x26, 0x36, + 0xad, 0xbe, 0x61, 0x63, 0x73, 0xaa, 0x82, 0xee, 0x29, 0xd0, 0xdf, 0x8c, 0x15, 0xb5, 0x96, 0xf3, + 0xdd, 0x7e, 0x3a, 0x37, 0x58, 0x7f, 0x0c, 0xfc, 0x0b, 0x07, 0xe8, 0xf7, 0xf4, 0x14, 0xb8, 0x81, + 0xb6, 0xd7, 0x1e, 0xc8, 0x85, 0xe6, 0x9d, 0x33, 0x60, 0xc5, 0x95, 0xd5, 0x55, 0x00, 0xa3, 0xb7, + 0x7d, 0x50, 0x0d, 0xd2, 0xc1, 0x12, 0xe5, 0xed, 0xd8, 0xa4, 0x9c, 0x8f, 0x2a, 0x4f, 0xa8, 0x01, + 0x52, 0x83, 0x65, 0xea, 0x9a, 0x6c, 0x44, 0x4a, 0xe2, 0xa5, 0x2b, 0x46, 0xe1, 0x34, 0x25, 0xf8, + 0xc3, 0xda, 0xc7, 0x6e, 0x48, 0x38, 0x7c, 0x78, 0x06, 0x53, 0x64, 0x16, 0x98, 0x3c, 0x91, 0x42, + 0x39, 0xcc, 0xb0, 0xf1, 0xeb, 0x13, 0xbb, 0x05, 0x32, 0x86, 0x0e, 0xa2, 0x0a, 0x9e, 0xfa, 0x66, + 0x54, 0x8e, 0xd3, 0xe7, 0x19, 0x20, 0x77, 0xec, 0xff, 0xbd, 0x6d, 0x43, 0x23, 0x03, 0xab, 0x75, + 0x3d, 0xcf, 0xd1, 0xde, 0x92, 0x31, 0xa7, 0x45, 0x4b, 0xc2, 0x97, 0xf9, 0x7a, 0x88, 0xd9, 0x1c, + 0xe9, 0xe4, 0x10, 0xc9, 0x22, 0x2d, 0x90, 0x76, 0x17, 0x79, 0x04, 0x51, 0x1a, 0x5a, 0x5f, 0x2c, + 0x21, 0x6f, 0x3e, 0xe0, 0xf0, 0xbf, 0xd6, 0x94, 0x0f, 0x80, 0x11, 0xa0, 0x5c, 0xa9, 0x49, 0x2e, + 0xce, 0xaf, 0xa6, 0x9f, 0x7b, 0x99, 0xb9, 0xb4, 0xe3, 0xfb, 0xf6, 0x27, 0xf2, 0x93, 0xfe, 0x08, + 0x67, 0xae, 0x09, 0x89, 0xdc, 0x4e, 0xc6, 0xc0, 0x8a, 0xb1, 0x59, 0x8b, 0x41, 0x56, 0x8d, 0xba, +}; + + +static const UINT8 kof99_type1_t03[256] = +{ + 0xa9, 0x17, 0xaf, 0x0d, 0x34, 0x6e, 0x53, 0xb6, 0x7f, 0x58, 0xe9, 0x14, 0x5f, 0x55, 0xdb, 0xd4, + 0x42, 0x80, 0x99, 0x59, 0xa8, 0x3a, 0x57, 0x5d, 0xd5, 0x6f, 0x4c, 0x68, 0x35, 0x46, 0xa6, 0xe7, + 0x7b, 0x71, 0xe0, 0x93, 0xa2, 0x1f, 0x64, 0x21, 0xe3, 0xb1, 0x98, 0x26, 0xab, 0xad, 0xee, 0xe5, + 0xbb, 0xd9, 0x1e, 0x2e, 0x95, 0x36, 0xef, 0x23, 0x79, 0x45, 0x04, 0xed, 0x13, 0x1d, 0xf4, 0x85, + 0x96, 0xec, 0xc2, 0x32, 0xaa, 0x7c, 0x15, 0xd8, 0xda, 0x92, 0x90, 0x9d, 0xb7, 0x56, 0x6a, 0x66, + 0x41, 0xfc, 0x00, 0xf6, 0x50, 0x24, 0xcf, 0xfb, 0x11, 0xfe, 0x82, 0x48, 0x9b, 0x27, 0x1b, 0x67, + 0x4e, 0x84, 0x69, 0x97, 0x6d, 0x8c, 0xd2, 0xba, 0x74, 0xf9, 0x8f, 0xa5, 0x54, 0x5c, 0xcd, 0x73, + 0x07, 0xd1, 0x01, 0x09, 0xf1, 0x19, 0x3b, 0x5e, 0x87, 0x30, 0x76, 0xcc, 0xc0, 0x5a, 0xa7, 0x49, + 0x22, 0xfa, 0x16, 0x02, 0xdf, 0xa4, 0xff, 0xb3, 0x75, 0x33, 0xbd, 0x88, 0x2f, 0xcb, 0x2a, 0x44, + 0xb8, 0xbf, 0x1c, 0x0f, 0x81, 0x10, 0x43, 0xb4, 0xc8, 0x7e, 0x9a, 0x25, 0xea, 0x83, 0x4b, 0x38, + 0x7a, 0xd7, 0x3d, 0x1a, 0x4f, 0x62, 0x51, 0xc9, 0x47, 0x0e, 0xce, 0x3f, 0xc7, 0x4d, 0x2c, 0xa1, + 0x86, 0xb9, 0xc5, 0xca, 0xdd, 0x6b, 0x70, 0x6c, 0x91, 0x9c, 0xbe, 0x0a, 0x9f, 0xf5, 0x94, 0xbc, + 0x18, 0x2b, 0x60, 0x20, 0x29, 0xf7, 0xf2, 0x28, 0xc4, 0xa0, 0x0b, 0x65, 0xde, 0x8d, 0x78, 0x12, + 0x3e, 0xd0, 0x77, 0x08, 0x8b, 0xae, 0x05, 0x31, 0x3c, 0xd6, 0xa3, 0x89, 0x06, 0xdc, 0x52, 0x72, + 0xb0, 0xb5, 0x37, 0xd3, 0xc3, 0x8a, 0xc6, 0xf0, 0xc1, 0x61, 0xfd, 0x4a, 0x5b, 0x7d, 0x9e, 0xf3, + 0x63, 0x40, 0x2d, 0xe8, 0xb2, 0xe6, 0x39, 0x03, 0xeb, 0x8e, 0xe1, 0x0c, 0xe4, 0xe2, 0xf8, 0xac, +}; + + +static const UINT8 kof99_type1_t12[256] = +{ + 0xea, 0xe6, 0x5e, 0xa7, 0x8e, 0xac, 0x34, 0x03, 0x30, 0x97, 0x52, 0x53, 0x76, 0xf2, 0x62, 0x0b, + 0x0a, 0xfc, 0x94, 0xb8, 0x67, 0x36, 0x11, 0xbc, 0xae, 0xca, 0xfa, 0x15, 0x04, 0x2b, 0x17, 0xc4, + 0x3e, 0x5b, 0x59, 0x01, 0x57, 0xe2, 0xba, 0xb7, 0xd1, 0x3f, 0xf0, 0x6a, 0x9c, 0x2a, 0xcb, 0xa9, + 0xe3, 0x2c, 0xc0, 0x0f, 0x46, 0x91, 0x8a, 0xd0, 0x98, 0xc5, 0xa6, 0x1b, 0x96, 0x29, 0x12, 0x09, + 0x63, 0xed, 0xe0, 0xa2, 0x86, 0x77, 0xbe, 0xe5, 0x65, 0xdb, 0xbd, 0x50, 0xb3, 0x9d, 0x1a, 0x4e, + 0x79, 0x0c, 0x00, 0x43, 0xdf, 0x3d, 0x54, 0x33, 0x8f, 0x89, 0xa8, 0x7b, 0xf9, 0xd5, 0x27, 0x82, + 0xbb, 0xc2, 0x8c, 0x47, 0x88, 0x6b, 0xb4, 0xc3, 0xf8, 0xaa, 0x06, 0x1e, 0x83, 0x7d, 0x05, 0x78, + 0x85, 0xf6, 0x6e, 0x2e, 0xec, 0x5a, 0x31, 0x45, 0x38, 0x14, 0x16, 0x8b, 0x02, 0xe4, 0x4f, 0xb0, + 0xbf, 0xab, 0xa4, 0x9e, 0x48, 0x60, 0x19, 0x35, 0x08, 0xde, 0xdd, 0x66, 0x90, 0x51, 0xcc, 0xa3, + 0xaf, 0x70, 0x9b, 0x75, 0x95, 0x49, 0x6c, 0x64, 0x72, 0x7e, 0x44, 0xa0, 0x73, 0x25, 0x68, 0x55, + 0x1f, 0x40, 0x7a, 0x74, 0x0e, 0x8d, 0xdc, 0x1c, 0x71, 0xc8, 0xcf, 0xd7, 0xe8, 0xce, 0xeb, 0x32, + 0x3a, 0xee, 0x07, 0x61, 0x4d, 0xfe, 0x5c, 0x7c, 0x56, 0x2f, 0x2d, 0x5f, 0x6f, 0x9f, 0x81, 0x22, + 0x58, 0x4b, 0xad, 0xda, 0xb9, 0x10, 0x18, 0x23, 0xe1, 0xf3, 0x6d, 0xe7, 0xe9, 0x28, 0xd6, 0xd8, + 0xf4, 0x4c, 0x39, 0x21, 0xb2, 0x84, 0xc1, 0x24, 0x26, 0xf1, 0x93, 0x37, 0xc6, 0x4a, 0xcd, 0x20, + 0xc9, 0xd9, 0xc7, 0xb1, 0xff, 0x99, 0xd4, 0x5d, 0xb5, 0xa1, 0x87, 0x0d, 0x69, 0x92, 0x13, 0x80, + 0xd2, 0xd3, 0xfd, 0x1d, 0xf5, 0x3b, 0xa5, 0x7f, 0xef, 0x9a, 0xb6, 0x42, 0xfb, 0x3c, 0xf7, 0x41, +}; + + +/* underlined values are wrong (not enough evidence, FF fill in kof99 and garou) */ +/* they correspond to tiles 7d000-7efff */ +static const UINT8 kof99_address_8_15_xor1[256] = +{ + 0x00, 0xb1, 0x1e, 0xc5, 0x3d, 0x40, 0x45, 0x5e, 0xf2, 0xf8, 0x04, 0x63, 0x36, 0x87, 0x88, 0xbf, + 0xab, 0xcc, 0x78, 0x08, 0xdd, 0x20, 0xd4, 0x35, 0x09, 0x8e, 0x44, 0xae, 0x33, 0xa9, 0x9e, 0xcd, + 0xb3, 0xe5, 0xad, 0x41, 0xda, 0xbe, 0xf4, 0x16, 0x57, 0x2e, 0x53, 0x67, 0xaf, 0xdb, 0x8a, 0xd8, + 0x34, 0x17, 0x3c, 0x01, 0x55, 0x73, 0xcf, 0xe3, 0xe8, 0xc7, 0x0d, 0xe9, 0xa3, 0x13, 0x0c, 0xf6, + 0x90, 0x4e, 0xfb, 0x97, 0x6d, 0x5f, 0xa8, 0x71, 0x11, 0xfc, 0xd1, 0x95, 0x81, 0xba, 0x8c, 0x1b, + 0x39, 0xfe, 0xa2, 0x15, 0xa6, 0x52, 0x4d, 0x5b, 0x59, 0xa5, 0xe0, 0x96, 0xd9, 0x8f, 0x7b, 0xed, + 0x29, 0xd3, 0x1f, 0x0e, 0xec, 0x23, 0x0f, 0xb8, 0x6c, 0x6f, 0x7d, 0x18, 0x46, 0xd6, 0xe4, 0xb5, + 0x9a, 0x79, 0x02, 0xf5, 0x03, 0xc0, 0x60, 0x66, 0x5c, 0x2f, 0x76, 0x85, 0x9d, 0x54, 0x1a, 0x6a, + 0x28, 0xce, 0x7f, 0x7c, 0x91, 0x99, 0x4c, 0x83, 0x3e, 0xb4, 0x1d, 0x05, 0xc1, 0xc3, 0xd7, 0x47, + 0xde, 0xbc, 0x62, 0x6e, 0x86, 0x14, 0x80, 0x77, 0xeb, 0xf3, 0x07, 0x31, 0x56, 0xd2, 0xc2, 0xc6, + 0x6b, 0xdc, 0xfd, 0x22, 0x92, 0xf0, 0x06, 0x51, 0x2d, 0x38, 0xe6, 0xa0, 0x25, 0xdf, 0xd5, 0x2c, + 0x1c, 0x94, 0x12, 0x9c, 0xb0, 0x9b, 0xc4, 0x0b, 0xc8, 0xd0, 0xf7, 0x30, 0xcb, 0x27, 0xfa, 0x7a, + 0x10, 0x61, 0xaa, 0xa4, 0x70, 0xb7, 0x2a, 0x5a, 0xc9, 0xf1, 0x0a, 0x49, 0x65, 0xee, 0x69, 0x4b, + 0x3a, 0x8d, 0x32, 0x5d, 0x68, 0xb9, 0x9f, 0x75, 0x19, 0x3f, 0xac, 0x37, 0x4f, 0xe7, 0x93, 0x89, + 0x7e, 0x4a, 0x3b, 0xea, 0x74, 0x72, 0x43, 0xbd, 0x24, 0xef, 0xb6, 0xff, 0x64, 0x58, 0x84, 0x8b, + 0xa7, 0xbb, 0xb2, 0xe1, 0x26, 0x2b, 0x50, 0xca, 0x21, 0xf9, 0x98, 0xa1, 0xe2, 0x42, 0x82, 0x48, +// ^^^^ ^^^^ ^^^^ ^^^^ +}; + + +static const UINT8 kof99_address_8_15_xor2[256] = +{ + 0x9b, 0x9d, 0xc1, 0x3d, 0xa9, 0xb8, 0xf4, 0x6f, 0xf6, 0x25, 0xc7, 0x47, 0xd5, 0x97, 0xdf, 0x6b, + 0xeb, 0x90, 0xa4, 0xb2, 0x5d, 0xf5, 0x66, 0xb0, 0xb9, 0x8b, 0x93, 0x64, 0xec, 0x7b, 0x65, 0x8c, + 0xf1, 0x43, 0x42, 0x6e, 0x45, 0x9f, 0xb3, 0x35, 0x06, 0x71, 0x96, 0xdb, 0xa0, 0xfb, 0x0b, 0x3a, + 0x1f, 0xf8, 0x8e, 0x69, 0xcd, 0x26, 0xab, 0x86, 0xa2, 0x0c, 0xbd, 0x63, 0xa5, 0x7a, 0xe7, 0x6a, + 0x5f, 0x18, 0x9e, 0xbf, 0xad, 0x55, 0xb1, 0x1c, 0x5c, 0x03, 0x30, 0xc6, 0x37, 0x20, 0xe3, 0xc9, + 0x52, 0xe8, 0xee, 0x4f, 0x01, 0x70, 0xc4, 0x77, 0x29, 0x2a, 0xba, 0x53, 0x12, 0x04, 0x7d, 0xaf, + 0x33, 0x8f, 0xa8, 0x4d, 0xaa, 0x5b, 0xb4, 0x0f, 0x92, 0xbb, 0xed, 0xe1, 0x2f, 0x50, 0x6c, 0xd2, + 0x2c, 0x95, 0xd9, 0xf9, 0x98, 0xc3, 0x76, 0x4c, 0xf2, 0xe4, 0xe5, 0x2b, 0xef, 0x9c, 0x49, 0xb6, + 0x31, 0x3b, 0xbc, 0xa1, 0xca, 0xde, 0x62, 0x74, 0xea, 0x81, 0x00, 0xdd, 0xa6, 0x46, 0x88, 0x3f, + 0x39, 0xd6, 0x23, 0x54, 0x24, 0x4a, 0xd8, 0xdc, 0xd7, 0xd1, 0xcc, 0xbe, 0x57, 0x7c, 0xda, 0x44, + 0x61, 0xce, 0xd3, 0xd4, 0xe9, 0x28, 0x80, 0xe0, 0x56, 0x8a, 0x09, 0x05, 0x9a, 0x89, 0x1b, 0xf7, + 0xf3, 0x99, 0x6d, 0x5e, 0x48, 0x91, 0xc0, 0xd0, 0xc5, 0x79, 0x78, 0x41, 0x59, 0x21, 0x2e, 0xff, + 0xc2, 0x4b, 0x38, 0x83, 0x32, 0xe6, 0xe2, 0x7f, 0x1e, 0x17, 0x58, 0x1d, 0x1a, 0xfa, 0x85, 0x82, + 0x94, 0xc8, 0x72, 0x7e, 0xb7, 0xac, 0x0e, 0xfc, 0xfd, 0x16, 0x27, 0x75, 0x8d, 0xcb, 0x08, 0xfe, + 0x0a, 0x02, 0x0d, 0x36, 0x11, 0x22, 0x84, 0x40, 0x34, 0x3e, 0x2d, 0x68, 0x5a, 0xa7, 0x67, 0xae, + 0x87, 0x07, 0x10, 0x60, 0x14, 0x73, 0x3c, 0x51, 0x19, 0xa3, 0xb5, 0xcf, 0x13, 0xf0, 0x15, 0x4e, +}; + + +static const UINT8 kof99_address_16_23_xor1[256] = +{ + 0x00, 0x5f, 0x03, 0x52, 0xce, 0xe3, 0x7d, 0x8f, 0x6b, 0xf8, 0x20, 0xde, 0x7b, 0x7e, 0x39, 0xbe, + 0xf5, 0x94, 0x18, 0x78, 0x80, 0xc9, 0x7f, 0x7a, 0x3e, 0x63, 0xf2, 0xe0, 0x4e, 0xf7, 0x87, 0x27, + 0x69, 0x6c, 0xa4, 0x1d, 0x85, 0x5b, 0xe6, 0x44, 0x25, 0x0c, 0x98, 0xc7, 0x01, 0x02, 0xa3, 0x26, + 0x09, 0x38, 0xdb, 0xc3, 0x1e, 0xcf, 0x23, 0x45, 0x68, 0x76, 0xd6, 0x22, 0x5d, 0x5a, 0xae, 0x16, + 0x9f, 0xa2, 0xb5, 0xcd, 0x81, 0xea, 0x5e, 0xb8, 0xb9, 0x9d, 0x9c, 0x1a, 0x0f, 0xff, 0xe1, 0xe7, + 0x74, 0xaa, 0xd4, 0xaf, 0xfc, 0xc6, 0x33, 0x29, 0x5c, 0xab, 0x95, 0xf0, 0x19, 0x47, 0x59, 0x67, + 0xf3, 0x96, 0x60, 0x1f, 0x62, 0x92, 0xbd, 0x89, 0xee, 0x28, 0x13, 0x06, 0xfe, 0xfa, 0x32, 0x6d, + 0x57, 0x3c, 0x54, 0x50, 0x2c, 0x58, 0x49, 0xfb, 0x17, 0xcc, 0xef, 0xb2, 0xb4, 0xf9, 0x07, 0x70, + 0xc5, 0xa9, 0xdf, 0xd5, 0x3b, 0x86, 0x2b, 0x0d, 0x6e, 0x4d, 0x0a, 0x90, 0x43, 0x31, 0xc1, 0xf6, + 0x88, 0x0b, 0xda, 0x53, 0x14, 0xdc, 0x75, 0x8e, 0xb0, 0xeb, 0x99, 0x46, 0xa1, 0x15, 0x71, 0xc8, + 0xe9, 0x3f, 0x4a, 0xd9, 0x73, 0xe5, 0x7c, 0x30, 0x77, 0xd3, 0xb3, 0x4b, 0x37, 0x72, 0xc2, 0x04, + 0x97, 0x08, 0x36, 0xb1, 0x3a, 0x61, 0xec, 0xe2, 0x1c, 0x9a, 0x8b, 0xd1, 0x1b, 0x2e, 0x9e, 0x8a, + 0xd8, 0x41, 0xe4, 0xc4, 0x40, 0x2f, 0xad, 0xc0, 0xb6, 0x84, 0x51, 0x66, 0xbb, 0x12, 0xe8, 0xdd, + 0xcb, 0xbc, 0x6f, 0xd0, 0x11, 0x83, 0x56, 0x4c, 0xca, 0xbf, 0x05, 0x10, 0xd7, 0xba, 0xfd, 0xed, + 0x8c, 0x0e, 0x4f, 0x3d, 0x35, 0x91, 0xb7, 0xac, 0x34, 0x64, 0x2a, 0xf1, 0x79, 0x6a, 0x9b, 0x2d, + 0x65, 0xf4, 0x42, 0xa0, 0x8d, 0xa7, 0x48, 0x55, 0x21, 0x93, 0x24, 0xd2, 0xa6, 0xa5, 0xa8, 0x82, +}; + + +static const UINT8 kof99_address_16_23_xor2[256] = +{ + 0x29, 0x97, 0x1a, 0x2c, 0x0b, 0x94, 0x3e, 0x75, 0x01, 0x0d, 0x1b, 0xe1, 0x4d, 0x38, 0x39, 0x8f, + 0xe7, 0xd0, 0x60, 0x90, 0xb2, 0x0f, 0xbb, 0x70, 0x1f, 0xe6, 0x5b, 0x87, 0xb4, 0x43, 0xfd, 0xf5, + 0xf6, 0xf9, 0xad, 0xc0, 0x98, 0x17, 0x9f, 0x91, 0x15, 0x51, 0x55, 0x64, 0x6c, 0x18, 0x61, 0x0e, + 0xd9, 0x93, 0xab, 0xd6, 0x24, 0x2f, 0x6a, 0x3a, 0x22, 0xb1, 0x4f, 0xaa, 0x23, 0x48, 0xed, 0xb9, + 0x88, 0x8b, 0xa3, 0x6b, 0x26, 0x4c, 0xe8, 0x2d, 0x1c, 0x99, 0xbd, 0x5c, 0x58, 0x08, 0x50, 0xf2, + 0x2a, 0x62, 0xc1, 0x72, 0x66, 0x04, 0x10, 0x37, 0x6e, 0xfc, 0x44, 0xa9, 0xdf, 0xd4, 0x20, 0xdd, + 0xee, 0x41, 0xdb, 0x73, 0xde, 0x54, 0xec, 0xc9, 0xf3, 0x4b, 0x2e, 0xae, 0x5a, 0x4a, 0x5e, 0x47, + 0x07, 0x2b, 0x76, 0xa4, 0xe3, 0x28, 0xfe, 0xb0, 0xf0, 0x02, 0x06, 0xd1, 0xaf, 0x42, 0xc2, 0xa5, + 0xe0, 0x67, 0xbf, 0x16, 0x8e, 0x35, 0xce, 0x8a, 0xe5, 0x3d, 0x7b, 0x96, 0xd7, 0x79, 0x52, 0x1e, + 0xa1, 0xfb, 0x9b, 0xbe, 0x21, 0x9c, 0xe9, 0x56, 0x14, 0x7f, 0xa0, 0xe4, 0xc3, 0xc4, 0x46, 0xea, + 0xf7, 0xd2, 0x1d, 0x31, 0x0a, 0x5f, 0xeb, 0xa2, 0x68, 0x8d, 0xb5, 0xc5, 0x74, 0x0c, 0xdc, 0x82, + 0x80, 0x09, 0x19, 0x95, 0x71, 0x9a, 0x11, 0x57, 0x77, 0x4e, 0xc6, 0xff, 0x12, 0x03, 0xa7, 0xc7, + 0xf4, 0xc8, 0xb6, 0x7a, 0x59, 0x36, 0x3c, 0x53, 0xe2, 0x69, 0x8c, 0x25, 0x05, 0x45, 0x63, 0xf8, + 0x34, 0x89, 0x33, 0x3f, 0x85, 0x27, 0xbc, 0x65, 0xfa, 0xa8, 0x6d, 0x84, 0x5d, 0xba, 0x40, 0x32, + 0x30, 0xef, 0x83, 0x13, 0xa6, 0x78, 0xcc, 0x81, 0x9e, 0xda, 0xca, 0xd3, 0x7e, 0x9d, 0x6f, 0xcd, + 0xb7, 0xb3, 0xd8, 0xcf, 0x3b, 0x00, 0x92, 0xb8, 0x86, 0xac, 0x49, 0x7c, 0xf1, 0xd5, 0xcb, 0x7d, +}; + + +static const UINT8 kof99_address_0_7_xor[256] = +{ + 0x74, 0xad, 0x5d, 0x1d, 0x9e, 0xc3, 0xfa, 0x4e, 0xf7, 0xdb, 0xca, 0xa2, 0x64, 0x36, 0x56, 0x0c, + 0x4f, 0xcf, 0x43, 0x66, 0x1e, 0x91, 0xe3, 0xa5, 0x58, 0xc2, 0xc1, 0xd4, 0xb9, 0xdd, 0x76, 0x16, + 0xce, 0x61, 0x75, 0x01, 0x2b, 0x22, 0x38, 0x55, 0x50, 0xef, 0x6c, 0x99, 0x05, 0xe9, 0xe8, 0xe0, + 0x2d, 0xa4, 0x4b, 0x4a, 0x42, 0xae, 0xba, 0x8c, 0x6f, 0x93, 0x14, 0xbd, 0x71, 0x21, 0xb0, 0x02, + 0x15, 0xc4, 0xe6, 0x60, 0xd7, 0x44, 0xfd, 0x85, 0x7e, 0x78, 0x8f, 0x00, 0x81, 0xf1, 0xa7, 0x3b, + 0xa0, 0x10, 0xf4, 0x9f, 0x39, 0x88, 0x35, 0x62, 0xcb, 0x19, 0x31, 0x11, 0x51, 0xfb, 0x2a, 0x20, + 0x45, 0xd3, 0x7d, 0x92, 0x1b, 0xf2, 0x09, 0x0d, 0x97, 0xa9, 0xb5, 0x3c, 0xee, 0x5c, 0xaf, 0x7b, + 0xd2, 0x3a, 0x49, 0x8e, 0xb6, 0xcd, 0xd9, 0xde, 0x8a, 0x29, 0x6e, 0xd8, 0x0b, 0xe1, 0x69, 0x87, + 0x1a, 0x96, 0x18, 0xcc, 0xdf, 0xe7, 0xc5, 0xc7, 0xf8, 0x52, 0xc9, 0xf0, 0xb7, 0xe5, 0x33, 0xda, + 0x67, 0x9d, 0xa3, 0x03, 0x0e, 0x72, 0x26, 0x79, 0xe2, 0xb8, 0xfc, 0xaa, 0xfe, 0xb4, 0x86, 0xc8, + 0xd1, 0xbc, 0x12, 0x08, 0x77, 0xeb, 0x40, 0x8d, 0x04, 0x25, 0x4d, 0x5a, 0x6a, 0x7a, 0x2e, 0x41, + 0x65, 0x1c, 0x13, 0x94, 0xb2, 0x63, 0x28, 0x59, 0x5e, 0x9a, 0x30, 0x07, 0xc6, 0xbf, 0x17, 0xf5, + 0x0f, 0x89, 0xf3, 0x1f, 0xea, 0x6d, 0xb3, 0xc0, 0x70, 0x47, 0xf9, 0x53, 0xf6, 0xd6, 0x54, 0xed, + 0x6b, 0x4c, 0xe4, 0x8b, 0x83, 0x24, 0x90, 0xb1, 0x7c, 0xbb, 0x73, 0xab, 0xd5, 0x2f, 0x5f, 0xec, + 0x9c, 0x2c, 0xa8, 0x34, 0x46, 0x37, 0x27, 0xa1, 0x0a, 0x06, 0x80, 0x68, 0x82, 0x32, 0x84, 0xff, + 0x48, 0xac, 0x7f, 0x3f, 0x95, 0xdc, 0x98, 0x9b, 0xbe, 0x23, 0x57, 0x3e, 0x5b, 0xd0, 0x3d, 0xa6, +}; + + +static const UINT8 kof2000_type0_t03[256] = +{ + 0x10, 0x61, 0xf1, 0x78, 0x85, 0x52, 0x68, 0xe3, 0x12, 0x0d, 0xfa, 0xf0, 0xc9, 0x36, 0x5e, 0x3d, + 0xf9, 0xa6, 0x01, 0x2e, 0xc7, 0x84, 0xea, 0x2b, 0x6d, 0x14, 0x38, 0x4f, 0x55, 0x1c, 0x9d, 0xa7, + 0x7a, 0xc6, 0xf8, 0x9a, 0xe6, 0x42, 0xb5, 0xed, 0x7d, 0x3a, 0xb1, 0x05, 0x43, 0x4a, 0x22, 0xfd, + 0xac, 0xa4, 0x31, 0xc3, 0x32, 0x76, 0x95, 0x9e, 0x7e, 0x88, 0x8e, 0xa2, 0x97, 0x18, 0xbe, 0x2a, + 0xf5, 0xd6, 0xca, 0xcc, 0x72, 0x3b, 0x87, 0x6c, 0xde, 0x75, 0xd7, 0x21, 0xcb, 0x0b, 0xdd, 0xe7, + 0xe1, 0x65, 0xaa, 0xb9, 0x44, 0xfb, 0x66, 0x15, 0x1a, 0x3c, 0x98, 0xcf, 0x8a, 0xdf, 0x37, 0xa5, + 0x2f, 0x67, 0xd2, 0x83, 0xb6, 0x6b, 0xfc, 0xe0, 0xb4, 0x7c, 0x08, 0xdc, 0x93, 0x30, 0xab, 0xe4, + 0x19, 0xc2, 0x8b, 0xeb, 0xa0, 0x0a, 0xc8, 0x03, 0xc0, 0x4b, 0x64, 0x71, 0x86, 0x9c, 0x9b, 0x16, + 0x79, 0xff, 0x70, 0x09, 0x8c, 0xd0, 0xf6, 0x53, 0x07, 0x73, 0xd4, 0x89, 0xb3, 0x00, 0xe9, 0xfe, + 0xec, 0x8f, 0xbc, 0xb2, 0x1e, 0x5d, 0x11, 0x35, 0xa9, 0x06, 0x59, 0x9f, 0xc1, 0xd3, 0x7b, 0xf2, + 0xc5, 0x77, 0x4e, 0x39, 0x20, 0xd5, 0x6a, 0x82, 0xda, 0x45, 0xf3, 0x33, 0x81, 0x23, 0xba, 0xe2, + 0x1d, 0x5f, 0x5c, 0x51, 0x49, 0xae, 0x8d, 0xc4, 0xa8, 0xf7, 0x1f, 0x0f, 0x34, 0x28, 0xa1, 0xd9, + 0x27, 0xd8, 0x4c, 0x2c, 0xbf, 0x91, 0x3e, 0x69, 0x57, 0x41, 0x25, 0x0c, 0x5a, 0x90, 0x92, 0xb0, + 0x63, 0x6f, 0x40, 0xaf, 0x74, 0xb8, 0x2d, 0x80, 0xbb, 0x46, 0x94, 0xe5, 0x29, 0xee, 0xb7, 0x1b, + 0x96, 0xad, 0x13, 0x0e, 0x58, 0x99, 0x60, 0x4d, 0x17, 0x26, 0xce, 0xe8, 0xdb, 0xef, 0x24, 0xa3, + 0x6e, 0x7f, 0x54, 0x3f, 0x02, 0xd1, 0x5b, 0x50, 0x56, 0x48, 0xf4, 0xbd, 0x62, 0x47, 0x04, 0xcd, +}; + + +static const UINT8 kof2000_type0_t12[256] = +{ + 0xf4, 0x28, 0xb4, 0x8f, 0xfa, 0xeb, 0x8e, 0x54, 0x2b, 0x49, 0xd1, 0x76, 0x71, 0x47, 0x8b, 0x57, + 0x92, 0x85, 0x7c, 0xb8, 0x5c, 0x22, 0xf9, 0x26, 0xbc, 0x5b, 0x6d, 0x67, 0xae, 0x5f, 0x6f, 0xf5, + 0x9f, 0x48, 0x66, 0x40, 0x0d, 0x11, 0x4e, 0xb2, 0x6b, 0x35, 0x15, 0x0f, 0x18, 0x25, 0x1d, 0xba, + 0xd3, 0x69, 0x79, 0xec, 0xa8, 0x8c, 0xc9, 0x7f, 0x4b, 0xdb, 0x51, 0xaf, 0xca, 0xe2, 0xb3, 0x81, + 0x12, 0x5e, 0x7e, 0x38, 0xc8, 0x95, 0x01, 0xff, 0xfd, 0xfb, 0xf2, 0x74, 0x62, 0x14, 0xa5, 0x98, + 0xa6, 0xda, 0x80, 0x53, 0xe8, 0x56, 0xac, 0x1b, 0x52, 0xd0, 0xf1, 0x45, 0x42, 0xb6, 0x1a, 0x4a, + 0x3a, 0x99, 0xfc, 0xd2, 0x9c, 0xcf, 0x31, 0x2d, 0xdd, 0x86, 0x2f, 0x29, 0xe1, 0x03, 0x19, 0xa2, + 0x41, 0x33, 0x83, 0x90, 0xc1, 0xbf, 0x0b, 0x08, 0x3d, 0xd8, 0x8d, 0x6c, 0x39, 0xa0, 0xe3, 0x55, + 0x02, 0x50, 0x46, 0xe6, 0xc3, 0x82, 0x36, 0x13, 0x75, 0xab, 0x27, 0xd7, 0x1f, 0x0a, 0xd4, 0x89, + 0x59, 0x4f, 0xc0, 0x5d, 0xc6, 0xf7, 0x88, 0xbd, 0x3c, 0x00, 0xef, 0xcd, 0x05, 0x1c, 0xaa, 0x9b, + 0xed, 0x7a, 0x61, 0x17, 0x93, 0xfe, 0x23, 0xb9, 0xf3, 0x68, 0x78, 0xf6, 0x5a, 0x7b, 0xe0, 0xe4, + 0xa3, 0xee, 0x16, 0x72, 0xc7, 0x3b, 0x8a, 0x37, 0x2a, 0x70, 0xa9, 0x2c, 0x21, 0xf8, 0x24, 0x09, + 0xce, 0x20, 0x9e, 0x06, 0x87, 0xc5, 0x04, 0x64, 0x43, 0x7d, 0x4d, 0x10, 0xd6, 0xa4, 0x94, 0x4c, + 0x60, 0xde, 0xdf, 0x58, 0xb1, 0x44, 0x3f, 0xb0, 0xd9, 0xe5, 0xcb, 0xbb, 0xbe, 0xea, 0x07, 0x34, + 0x73, 0x6a, 0x77, 0xf0, 0x9d, 0x0c, 0x2e, 0x0e, 0x91, 0x9a, 0xcc, 0xc2, 0xb7, 0x63, 0x97, 0xd5, + 0xdc, 0xc4, 0x32, 0xe7, 0x84, 0x3e, 0x30, 0xa1, 0x1e, 0xb5, 0x6e, 0x65, 0xe9, 0xad, 0xa7, 0x96, +}; + + +static const UINT8 kof2000_type1_t03[256] = +{ + 0x9a, 0x2f, 0xcc, 0x4e, 0x40, 0x69, 0xac, 0xca, 0xa5, 0x7b, 0x0a, 0x61, 0x91, 0x0d, 0x55, 0x74, + 0xcd, 0x8b, 0x0b, 0x80, 0x09, 0x5e, 0x38, 0xc7, 0xda, 0xbf, 0xf5, 0x37, 0x23, 0x31, 0x33, 0xe9, + 0xae, 0x87, 0xe5, 0xfa, 0x6e, 0x5c, 0xad, 0xf4, 0x76, 0x62, 0x9f, 0x2e, 0x01, 0xe2, 0xf6, 0x47, + 0x8c, 0x7c, 0xaa, 0x98, 0xb5, 0x92, 0x51, 0xec, 0x5f, 0x07, 0x5d, 0x6f, 0x16, 0xa1, 0x1d, 0xa9, + 0x48, 0x45, 0xf0, 0x6a, 0x9c, 0x1e, 0x11, 0xa0, 0x06, 0x46, 0xd5, 0xf1, 0x73, 0xed, 0x94, 0xf7, + 0xc3, 0x57, 0x1b, 0xe0, 0x97, 0xb1, 0xa4, 0xa7, 0x24, 0xe7, 0x2b, 0x05, 0x5b, 0x34, 0x0c, 0xb8, + 0x0f, 0x9b, 0xc8, 0x4d, 0x5a, 0xa6, 0x86, 0x3e, 0x14, 0x29, 0x84, 0x58, 0x90, 0xdb, 0x2d, 0x54, + 0x9d, 0x82, 0xd4, 0x7d, 0xc6, 0x67, 0x41, 0x89, 0xc1, 0x13, 0xb0, 0x9e, 0x81, 0x6d, 0xa8, 0x59, + 0xbd, 0x39, 0x8e, 0xe6, 0x25, 0x8f, 0xd9, 0xa2, 0xe4, 0x53, 0xc5, 0x72, 0x7e, 0x36, 0x4a, 0x4f, + 0x52, 0xc2, 0x22, 0x2a, 0xce, 0x3c, 0x21, 0x2c, 0x00, 0xd7, 0x75, 0x8a, 0x27, 0xee, 0x43, 0xfe, + 0xcb, 0x6b, 0xb9, 0xa3, 0x78, 0xb7, 0x85, 0x02, 0x20, 0xd0, 0x83, 0xc4, 0x12, 0xf9, 0xfd, 0xd8, + 0x79, 0x64, 0x3a, 0x49, 0x03, 0xb4, 0xc0, 0xf2, 0xdf, 0x15, 0x93, 0x08, 0x35, 0xff, 0x70, 0xdd, + 0x28, 0x6c, 0x0e, 0x04, 0xde, 0x7a, 0x65, 0xd2, 0xab, 0x42, 0x95, 0xe1, 0x3f, 0x3b, 0x7f, 0x66, + 0xd1, 0x8d, 0xe3, 0xbb, 0x1c, 0xfc, 0x77, 0x1a, 0x88, 0x18, 0x19, 0x68, 0x1f, 0x56, 0xd6, 0xe8, + 0xb6, 0xbc, 0xd3, 0xea, 0x3d, 0x26, 0xb3, 0xc9, 0x44, 0xdc, 0xf3, 0x32, 0x30, 0xef, 0x96, 0x4c, + 0xaf, 0x17, 0xf8, 0xfb, 0x60, 0x50, 0xeb, 0x4b, 0x99, 0x63, 0xba, 0xb2, 0x71, 0xcf, 0x10, 0xbe, +}; + + +static const UINT8 kof2000_type1_t12[256] = +{ + 0xda, 0xa7, 0xd6, 0x6e, 0x2f, 0x5e, 0xf0, 0x3f, 0xa4, 0xce, 0xd3, 0xfd, 0x46, 0x2a, 0xac, 0xc9, + 0xbe, 0xeb, 0x9f, 0xd5, 0x3c, 0x61, 0x96, 0x11, 0xd0, 0x38, 0xca, 0x06, 0xed, 0x1b, 0x65, 0xe7, + 0x23, 0xdd, 0xd9, 0x05, 0xbf, 0x5b, 0x5d, 0xa5, 0x95, 0x00, 0xec, 0xf1, 0x01, 0xa9, 0xa6, 0xfc, + 0xbb, 0x54, 0xe3, 0x2e, 0x92, 0x58, 0x0a, 0x7b, 0xb6, 0xcc, 0xb1, 0x5f, 0x14, 0x35, 0x72, 0xff, + 0xe6, 0x52, 0xd7, 0x8c, 0xf3, 0x43, 0xaf, 0x9c, 0xc0, 0x4f, 0x0c, 0x42, 0x8e, 0xef, 0x80, 0xcd, + 0x1d, 0x7e, 0x88, 0x3b, 0x98, 0xa1, 0xad, 0xe4, 0x9d, 0x8d, 0x2b, 0x56, 0xb5, 0x50, 0xdf, 0x66, + 0x6d, 0xd4, 0x60, 0x09, 0xe1, 0xee, 0x4a, 0x47, 0xf9, 0xfe, 0x73, 0x07, 0x89, 0xa8, 0x39, 0xea, + 0x82, 0x9e, 0xcf, 0x26, 0xb2, 0x4e, 0xc3, 0x59, 0xf2, 0x3d, 0x9a, 0xb0, 0x69, 0xf7, 0xbc, 0x34, + 0xe5, 0x36, 0x22, 0xfb, 0x57, 0x71, 0x99, 0x6c, 0x83, 0x30, 0x55, 0xc2, 0xbd, 0xf4, 0x77, 0xe9, + 0x76, 0x97, 0xa0, 0xe0, 0xb9, 0x86, 0x6b, 0xa3, 0x84, 0x67, 0x1a, 0x70, 0x02, 0x5a, 0x41, 0x5c, + 0x25, 0x81, 0xaa, 0x28, 0x78, 0x4b, 0xc6, 0x64, 0x53, 0x16, 0x4d, 0x8b, 0x20, 0x93, 0xae, 0x0f, + 0x94, 0x2c, 0x3a, 0xc7, 0x62, 0xe8, 0xc4, 0xdb, 0x04, 0xc5, 0xfa, 0x29, 0x48, 0xd1, 0x08, 0x24, + 0x0d, 0xe2, 0xd8, 0x10, 0xb4, 0x91, 0x8a, 0x13, 0x0e, 0xdc, 0xd2, 0x79, 0xb8, 0xf8, 0xba, 0x2d, + 0xcb, 0xf5, 0x7d, 0x37, 0x51, 0x40, 0x31, 0xa2, 0x0b, 0x18, 0x63, 0x7f, 0xb3, 0xab, 0x9b, 0x87, + 0xf6, 0x90, 0xde, 0xc8, 0x27, 0x45, 0x7c, 0x1c, 0x85, 0x68, 0x33, 0x19, 0x03, 0x75, 0x15, 0x7a, + 0x1f, 0x49, 0x8f, 0x4c, 0xc1, 0x44, 0x17, 0x12, 0x6f, 0x32, 0xb7, 0x3e, 0x74, 0x1e, 0x21, 0x6a, +}; + + +static const UINT8 kof2000_address_8_15_xor1[256] = +{ + 0xfc, 0x9b, 0x1c, 0x35, 0x72, 0x53, 0xd6, 0x7d, 0x84, 0xa4, 0xc5, 0x93, 0x7b, 0xe7, 0x47, 0xd5, + 0x24, 0xa2, 0xfa, 0x19, 0x0c, 0xb1, 0x8c, 0xb9, 0x9d, 0xd8, 0x59, 0x4f, 0x3c, 0xb2, 0x78, 0x4a, + 0x2a, 0x96, 0x9a, 0xf1, 0x1f, 0x22, 0xa8, 0x5b, 0x67, 0xa3, 0x0f, 0x00, 0xfb, 0xdf, 0xeb, 0x0a, + 0x57, 0xb8, 0x25, 0xd7, 0xf0, 0x6b, 0x0b, 0x31, 0x95, 0x23, 0x2d, 0x5c, 0x27, 0xc7, 0xf4, 0x55, + 0x1a, 0xf7, 0x74, 0xbe, 0xd3, 0xac, 0x3d, 0xc1, 0x7f, 0xbd, 0x28, 0x01, 0x10, 0xe5, 0x09, 0x37, + 0x1e, 0x58, 0xaf, 0x17, 0xf2, 0x16, 0x30, 0x92, 0x36, 0x68, 0xe6, 0xd4, 0xea, 0xb7, 0x75, 0x54, + 0x77, 0x41, 0xb4, 0x8d, 0xe0, 0xf3, 0x51, 0x03, 0xa9, 0xe8, 0x66, 0xab, 0x29, 0xa5, 0xed, 0xcb, + 0xd1, 0xaa, 0xf5, 0xdb, 0x4c, 0x42, 0x97, 0x8a, 0xae, 0xc9, 0x6e, 0x04, 0x33, 0x85, 0xdd, 0x2b, + 0x6f, 0xef, 0x12, 0x21, 0x7a, 0xa1, 0x5a, 0x91, 0xc8, 0xcc, 0xc0, 0xa7, 0x60, 0x3e, 0x56, 0x2f, + 0xe4, 0x71, 0x99, 0xc2, 0xa0, 0x45, 0x80, 0x65, 0xbb, 0x87, 0x69, 0x81, 0x73, 0xca, 0xf6, 0x46, + 0x43, 0xda, 0x26, 0x7e, 0x8f, 0xe1, 0x8b, 0xfd, 0x50, 0x79, 0xba, 0xc6, 0x63, 0x4b, 0xb3, 0x8e, + 0x34, 0xe2, 0x48, 0x14, 0xcd, 0xe3, 0xc4, 0x05, 0x13, 0x40, 0x06, 0x6c, 0x88, 0xb0, 0xe9, 0x1b, + 0x4d, 0xf8, 0x76, 0x02, 0x44, 0x94, 0xcf, 0x32, 0xfe, 0xce, 0x3b, 0x5d, 0x2c, 0x89, 0x5f, 0xdc, + 0xd2, 0x9c, 0x6a, 0xec, 0x18, 0x6d, 0x0e, 0x86, 0xff, 0x5e, 0x9e, 0xee, 0x11, 0xd0, 0x49, 0x52, + 0x4e, 0x61, 0x90, 0x0d, 0xc3, 0x39, 0x15, 0x83, 0xb5, 0x62, 0x3f, 0x70, 0x7c, 0xad, 0x20, 0xbf, + 0x2e, 0x08, 0x1d, 0xf9, 0xb6, 0xa6, 0x64, 0x07, 0x82, 0x38, 0x98, 0x3a, 0x9f, 0xde, 0xbc, 0xd9, +}; + + +static const UINT8 kof2000_address_8_15_xor2[256] = +{ + 0x00, 0xbe, 0x06, 0x5a, 0xfa, 0x42, 0x15, 0xf2, 0x3f, 0x0a, 0x84, 0x93, 0x4e, 0x78, 0x3b, 0x89, + 0x32, 0x98, 0xa2, 0x87, 0x73, 0xdd, 0x26, 0xe5, 0x05, 0x71, 0x08, 0x6e, 0x9b, 0xe0, 0xdf, 0x9e, + 0xfc, 0x83, 0x81, 0xef, 0xb2, 0xc0, 0xc3, 0xbf, 0xa7, 0x6d, 0x1b, 0x95, 0xed, 0xb9, 0x3e, 0x13, + 0xb0, 0x47, 0x9c, 0x7a, 0x24, 0x41, 0x68, 0xd0, 0x36, 0x0b, 0xb5, 0xc2, 0x67, 0xf7, 0x54, 0x92, + 0x1e, 0x44, 0x86, 0x2b, 0x94, 0xcc, 0xba, 0x23, 0x0d, 0xca, 0x6b, 0x4c, 0x2a, 0x9a, 0x2d, 0x8b, + 0xe3, 0x52, 0x29, 0xf0, 0x21, 0xbd, 0xbb, 0x1f, 0xa3, 0xab, 0xf8, 0x46, 0xb7, 0x45, 0x82, 0x5e, + 0xdb, 0x07, 0x5d, 0xe9, 0x9d, 0x1a, 0x48, 0xce, 0x91, 0x12, 0xd4, 0xee, 0xa9, 0x39, 0xf1, 0x18, + 0x2c, 0x22, 0x8a, 0x7e, 0x34, 0x4a, 0x8c, 0xc1, 0x14, 0xf3, 0x20, 0x35, 0xd9, 0x96, 0x33, 0x77, + 0x9f, 0x76, 0x7c, 0x90, 0xc6, 0xd5, 0xa1, 0x5b, 0xac, 0x75, 0xc7, 0x0c, 0xb3, 0x17, 0xd6, 0x99, + 0x56, 0xa6, 0x3d, 0x1d, 0xb1, 0x2e, 0xd8, 0xbc, 0x2f, 0xde, 0x60, 0x55, 0x6c, 0x40, 0xcd, 0x43, + 0xff, 0xad, 0x38, 0x79, 0x51, 0xc8, 0x0e, 0x5f, 0xc4, 0x66, 0xcb, 0xa8, 0x7d, 0xa4, 0x3a, 0xea, + 0x27, 0x7b, 0x70, 0x8e, 0x5c, 0x19, 0x0f, 0x80, 0x6f, 0x8f, 0x10, 0xf9, 0x49, 0x85, 0x69, 0x7f, + 0xeb, 0x1c, 0x01, 0x65, 0x37, 0xa5, 0x28, 0xe4, 0x6a, 0x03, 0x04, 0xd1, 0x31, 0x11, 0x30, 0xfb, + 0x88, 0x97, 0xd3, 0xf6, 0xc5, 0x4d, 0xf5, 0x3c, 0xe8, 0x61, 0xdc, 0xd2, 0xb4, 0xb8, 0xa0, 0xae, + 0x16, 0x25, 0x02, 0x09, 0xfe, 0xcf, 0x53, 0x63, 0xaf, 0x59, 0xf4, 0xe1, 0xec, 0xd7, 0xe7, 0x50, + 0xe2, 0xc9, 0xaa, 0x4b, 0x8d, 0x4f, 0xe6, 0x64, 0xda, 0x74, 0xb6, 0x72, 0x57, 0x62, 0xfd, 0x58, +}; + + +static const UINT8 kof2000_address_16_23_xor1[256] = +{ + 0x45, 0x9f, 0x6e, 0x2f, 0x28, 0xbc, 0x5e, 0x6d, 0xda, 0xb5, 0x0d, 0xb8, 0xc0, 0x8e, 0xa2, 0x32, + 0xee, 0xcd, 0x8d, 0x48, 0x8c, 0x27, 0x14, 0xeb, 0x65, 0xd7, 0xf2, 0x93, 0x99, 0x90, 0x91, 0xfc, + 0x5f, 0xcb, 0xfa, 0x75, 0x3f, 0x26, 0xde, 0x72, 0x33, 0x39, 0xc7, 0x1f, 0x88, 0x79, 0x73, 0xab, + 0x4e, 0x36, 0x5d, 0x44, 0xd2, 0x41, 0xa0, 0x7e, 0xa7, 0x8b, 0xa6, 0xbf, 0x03, 0xd8, 0x86, 0xdc, + 0x2c, 0xaa, 0x70, 0x3d, 0x46, 0x07, 0x80, 0x58, 0x0b, 0x2b, 0xe2, 0xf0, 0xb1, 0xfe, 0x42, 0xf3, + 0xe9, 0xa3, 0x85, 0x78, 0xc3, 0xd0, 0x5a, 0xdb, 0x1a, 0xfb, 0x9d, 0x8a, 0xa5, 0x12, 0x0e, 0x54, + 0x8f, 0xc5, 0x6c, 0xae, 0x25, 0x5b, 0x4b, 0x17, 0x02, 0x9c, 0x4a, 0x24, 0x40, 0xe5, 0x9e, 0x22, + 0xc6, 0x49, 0x62, 0xb6, 0x6b, 0xbb, 0xa8, 0xcc, 0xe8, 0x81, 0x50, 0x47, 0xc8, 0xbe, 0x5c, 0xa4, + 0xd6, 0x94, 0x4f, 0x7b, 0x9a, 0xcf, 0xe4, 0x59, 0x7a, 0xa1, 0xea, 0x31, 0x37, 0x13, 0x2d, 0xaf, + 0x21, 0x69, 0x19, 0x1d, 0x6f, 0x16, 0x98, 0x1e, 0x08, 0xe3, 0xb2, 0x4d, 0x9b, 0x7f, 0xa9, 0x77, + 0xed, 0xbd, 0xd4, 0xd9, 0x34, 0xd3, 0xca, 0x09, 0x18, 0x60, 0xc9, 0x6a, 0x01, 0xf4, 0xf6, 0x64, + 0xb4, 0x3a, 0x15, 0xac, 0x89, 0x52, 0x68, 0x71, 0xe7, 0x82, 0xc1, 0x0c, 0x92, 0xf7, 0x30, 0xe6, + 0x1c, 0x3e, 0x0f, 0x0a, 0x67, 0x35, 0xba, 0x61, 0xdd, 0x29, 0xc2, 0xf8, 0x97, 0x95, 0xb7, 0x3b, + 0xe0, 0xce, 0xf9, 0xd5, 0x06, 0x76, 0xb3, 0x05, 0x4c, 0x04, 0x84, 0x3c, 0x87, 0x23, 0x63, 0x7c, + 0x53, 0x56, 0xe1, 0x7d, 0x96, 0x1b, 0xd1, 0xec, 0x2a, 0x66, 0xf1, 0x11, 0x10, 0xff, 0x43, 0x2e, + 0xdf, 0x83, 0x74, 0xf5, 0x38, 0x20, 0xfd, 0xad, 0xc4, 0xb9, 0x55, 0x51, 0xb0, 0xef, 0x00, 0x57, +}; + + +static const UINT8 kof2000_address_16_23_xor2[256] = +{ + 0x00, 0xb8, 0xf0, 0x34, 0xca, 0x21, 0x3c, 0xf9, 0x01, 0x8e, 0x75, 0x70, 0xec, 0x13, 0x27, 0x96, + 0xf4, 0x5b, 0x88, 0x1f, 0xeb, 0x4a, 0x7d, 0x9d, 0xbe, 0x02, 0x14, 0xaf, 0xa2, 0x06, 0xc6, 0xdb, + 0x35, 0x6b, 0x74, 0x45, 0x7b, 0x29, 0xd2, 0xfe, 0xb6, 0x15, 0xd0, 0x8a, 0xa9, 0x2d, 0x19, 0xf6, + 0x5e, 0x5a, 0x90, 0xe9, 0x11, 0x33, 0xc2, 0x47, 0x37, 0x4c, 0x4f, 0x59, 0xc3, 0x04, 0x57, 0x1d, + 0xf2, 0x63, 0x6d, 0x6e, 0x31, 0x95, 0xcb, 0x3e, 0x67, 0xb2, 0xe3, 0x98, 0xed, 0x8d, 0xe6, 0xfb, + 0xf8, 0xba, 0x5d, 0xd4, 0x2a, 0xf5, 0x3b, 0x82, 0x05, 0x16, 0x44, 0xef, 0x4d, 0xe7, 0x93, 0xda, + 0x9f, 0xbb, 0x61, 0xc9, 0x53, 0xbd, 0x76, 0x78, 0x52, 0x36, 0x0c, 0x66, 0xc1, 0x10, 0xdd, 0x7a, + 0x84, 0x69, 0xcd, 0xfd, 0x58, 0x0d, 0x6c, 0x89, 0x68, 0xad, 0x3a, 0xb0, 0x4b, 0x46, 0xc5, 0x03, + 0xb4, 0xf7, 0x30, 0x8c, 0x4e, 0x60, 0x73, 0xa1, 0x8b, 0xb1, 0x62, 0xcc, 0xd1, 0x08, 0xfc, 0x77, + 0x7e, 0xcf, 0x56, 0x51, 0x07, 0xa6, 0x80, 0x92, 0xdc, 0x0b, 0xa4, 0xc7, 0xe8, 0xe1, 0xb5, 0x71, + 0xea, 0xb3, 0x2f, 0x94, 0x18, 0xe2, 0x3d, 0x49, 0x65, 0xaa, 0xf1, 0x91, 0xc8, 0x99, 0x55, 0x79, + 0x86, 0xa7, 0x26, 0xa0, 0xac, 0x5f, 0xce, 0x6a, 0x5c, 0xf3, 0x87, 0x8f, 0x12, 0x1c, 0xd8, 0xe4, + 0x9b, 0x64, 0x2e, 0x1e, 0xd7, 0xc0, 0x17, 0xbc, 0xa3, 0xa8, 0x9a, 0x0e, 0x25, 0x40, 0x41, 0x50, + 0xb9, 0xbf, 0x28, 0xdf, 0x32, 0x54, 0x9e, 0x48, 0xd5, 0x2b, 0x42, 0xfa, 0x9c, 0x7f, 0xd3, 0x85, + 0x43, 0xde, 0x81, 0x0f, 0x24, 0xc4, 0x38, 0xae, 0x83, 0x1b, 0x6f, 0x7c, 0xe5, 0xff, 0x1a, 0xd9, + 0x3f, 0xb7, 0x22, 0x97, 0x09, 0xe0, 0xa5, 0x20, 0x23, 0x2c, 0x72, 0xd6, 0x39, 0xab, 0x0a, 0xee, +}; + + +static const UINT8 kof2000_address_0_7_xor[256] = +{ + 0x26, 0x48, 0x06, 0x9b, 0x21, 0xa9, 0x1b, 0x76, 0xc9, 0xf8, 0xb4, 0x67, 0xe4, 0xff, 0x99, 0xf7, + 0x15, 0x9e, 0x62, 0x00, 0x72, 0x4d, 0xa0, 0x4f, 0x02, 0xf1, 0xea, 0xef, 0x0b, 0xf3, 0xeb, 0xa6, + 0x93, 0x78, 0x6f, 0x7c, 0xda, 0xd4, 0x7b, 0x05, 0xe9, 0xc6, 0xd6, 0xdb, 0x50, 0xce, 0xd2, 0x01, + 0xb5, 0xe8, 0xe0, 0x2a, 0x08, 0x1a, 0xb8, 0xe3, 0xf9, 0xb1, 0xf4, 0x8b, 0x39, 0x2d, 0x85, 0x9c, + 0x55, 0x73, 0x63, 0x40, 0x38, 0x96, 0xdc, 0xa3, 0xa2, 0xa1, 0x25, 0x66, 0x6d, 0x56, 0x8e, 0x10, + 0x0f, 0x31, 0x1c, 0xf5, 0x28, 0x77, 0x0a, 0xd1, 0x75, 0x34, 0xa4, 0xfe, 0x7d, 0x07, 0x51, 0x79, + 0x41, 0x90, 0x22, 0x35, 0x12, 0xbb, 0xc4, 0xca, 0xb2, 0x1f, 0xcb, 0xc8, 0xac, 0xdd, 0xd0, 0x0d, + 0xfc, 0xc5, 0x9d, 0x14, 0xbc, 0x83, 0xd9, 0x58, 0xc2, 0x30, 0x9a, 0x6a, 0xc0, 0x0c, 0xad, 0xf6, + 0x5d, 0x74, 0x7f, 0x2f, 0xbd, 0x1d, 0x47, 0xd5, 0xe6, 0x89, 0xcf, 0xb7, 0xd3, 0x59, 0x36, 0x98, + 0xf0, 0xfb, 0x3c, 0xf2, 0x3f, 0xa7, 0x18, 0x82, 0x42, 0x5c, 0xab, 0xba, 0xde, 0x52, 0x09, 0x91, + 0xaa, 0x61, 0xec, 0xd7, 0x95, 0x23, 0xcd, 0x80, 0xa5, 0x68, 0x60, 0x27, 0x71, 0xe1, 0x2c, 0x2e, + 0x8d, 0x2b, 0x57, 0x65, 0xbf, 0xc1, 0x19, 0xc7, 0x49, 0x64, 0x88, 0x4a, 0xcc, 0x20, 0x4e, 0xd8, + 0x3b, 0x4c, 0x13, 0x5f, 0x9f, 0xbe, 0x5e, 0x6e, 0xfd, 0xe2, 0xfa, 0x54, 0x37, 0x0e, 0x16, 0x7a, + 0x6c, 0x33, 0xb3, 0x70, 0x84, 0x7e, 0xc3, 0x04, 0xb0, 0xae, 0xb9, 0x81, 0x03, 0x29, 0xdf, 0x46, + 0xe5, 0x69, 0xe7, 0x24, 0x92, 0x5a, 0x4b, 0x5b, 0x94, 0x11, 0x3a, 0x3d, 0x87, 0xed, 0x97, 0xb6, + 0x32, 0x3e, 0x45, 0xaf, 0x1e, 0x43, 0x44, 0x8c, 0x53, 0x86, 0x6b, 0xee, 0xa8, 0x8a, 0x8f, 0x17, +}; + + + +void cmc_prot_device::decrypt(UINT8 *r0, UINT8 *r1, + UINT8 c0, UINT8 c1, + const UINT8 *table0hi, + const UINT8 *table0lo, + const UINT8 *table1, + int base, + int invert) +{ + UINT8 tmp,xor0,xor1; + + tmp = table1[(base & 0xff) ^ address_0_7_xor[(base >> 8) & 0xff]]; + xor0 = (table0hi[(base >> 8) & 0xff] & 0xfe) | (tmp & 0x01); + xor1 = (tmp & 0xfe) | (table0lo[(base >> 8) & 0xff] & 0x01); + + if (invert) + { + *r0 = c1 ^ xor0; + *r1 = c0 ^ xor1; + } + else + { + *r0 = c0 ^ xor0; + *r1 = c1 ^ xor1; + } +} + + +void cmc_prot_device::neogeo_gfx_decrypt(UINT8* rom, UINT32 rom_size, int extra_xor) +{ + int rpos; + + + dynamic_buffer buf(rom_size); + + // Data xor + for (rpos = 0;rpos < rom_size/4;rpos++) + { + decrypt(&buf[4*rpos+0], &buf[4*rpos+3], rom[4*rpos+0], rom[4*rpos+3], type0_t03, type0_t12, type1_t03, rpos, (rpos>>8) & 1); + decrypt(&buf[4*rpos+1], &buf[4*rpos+2], rom[4*rpos+1], rom[4*rpos+2], type0_t12, type0_t03, type1_t12, rpos, ((rpos>>16) ^ address_16_23_xor2[(rpos>>8) & 0xff]) & 1); + } + + // Address xor + for (rpos = 0;rpos < rom_size/4;rpos++) + { + int baser; + + baser = rpos; + + baser ^= extra_xor; + + baser ^= address_8_15_xor1[(baser >> 16) & 0xff] << 8; + baser ^= address_8_15_xor2[baser & 0xff] << 8; + baser ^= address_16_23_xor1[baser & 0xff] << 16; + baser ^= address_16_23_xor2[(baser >> 8) & 0xff] << 16; + baser ^= address_0_7_xor[(baser >> 8) & 0xff]; + + + if (rom_size == 0x3000000) /* special handling for preisle2 */ + { + if (rpos < 0x2000000/4) + baser &= (0x2000000/4)-1; + else + baser = 0x2000000/4 + (baser & ((0x1000000/4)-1)); + } + else if (rom_size == 0x6000000) /* special handling for kf2k3pcb */ + { + if (rpos < 0x4000000/4) + baser &= (0x4000000/4)-1; + else + baser = 0x4000000/4 + (baser & ((0x1000000/4)-1)); + } + else /* Clamp to the real rom size */ + baser &= (rom_size/4)-1; + + rom[4*rpos+0] = buf[4*baser+0]; + rom[4*rpos+1] = buf[4*baser+1]; + rom[4*rpos+2] = buf[4*baser+2]; + rom[4*rpos+3] = buf[4*baser+3]; + } +} + + +/* the S data comes from the end of the C data */ +void cmc_prot_device::neogeo_sfix_decrypt(UINT8* rom, UINT32 rom_size, UINT8* fixed, UINT32 fixed_size) +{ + int i; + int tx_size = fixed_size; + UINT8 *src = rom+rom_size-tx_size; + UINT8 *dst = fixed; + + for (i = 0;i < tx_size;i++) + dst[i] = src[(i & ~0x1f) + ((i & 7) << 2) + ((~i & 8) >> 2) + ((i & 0x10) >> 4)]; +} + + +/* CMC42 protection chip */ +void cmc_prot_device::kof99_neogeo_gfx_decrypt(UINT8* rom, UINT32 rom_size, UINT8* fixed, UINT32 fixed_size, int extra_xor) +{ + type0_t03 = kof99_type0_t03; + type0_t12 = kof99_type0_t12; + type1_t03 = kof99_type1_t03; + type1_t12 = kof99_type1_t12; + address_8_15_xor1 = kof99_address_8_15_xor1; + address_8_15_xor2 = kof99_address_8_15_xor2; + address_16_23_xor1 = kof99_address_16_23_xor1; + address_16_23_xor2 = kof99_address_16_23_xor2; + address_0_7_xor = kof99_address_0_7_xor; + neogeo_gfx_decrypt(rom, rom_size, extra_xor); + neogeo_sfix_decrypt(rom, rom_size, fixed, fixed_size); +} + + +/* CMC50 protection chip */ +void cmc_prot_device::kof2000_neogeo_gfx_decrypt(UINT8* rom, UINT32 rom_size, UINT8* fixed, UINT32 fixed_size, int extra_xor) +{ + type0_t03 = kof2000_type0_t03; + type0_t12 = kof2000_type0_t12; + type1_t03 = kof2000_type1_t03; + type1_t12 = kof2000_type1_t12; + address_8_15_xor1 = kof2000_address_8_15_xor1; + address_8_15_xor2 = kof2000_address_8_15_xor2; + address_16_23_xor1 = kof2000_address_16_23_xor1; + address_16_23_xor2 = kof2000_address_16_23_xor2; + address_0_7_xor = kof2000_address_0_7_xor; + neogeo_gfx_decrypt(rom, rom_size, extra_xor); + neogeo_sfix_decrypt(rom, rom_size, fixed, fixed_size); +} + + +/* CMC42 protection chip */ +void cmc_prot_device::cmc42_neogeo_gfx_decrypt(UINT8* rom, UINT32 rom_size, UINT8* fixed, UINT32 fixed_size, int extra_xor) +{ + type0_t03 = kof99_type0_t03; + type0_t12 = kof99_type0_t12; + type1_t03 = kof99_type1_t03; + type1_t12 = kof99_type1_t12; + address_8_15_xor1 = kof99_address_8_15_xor1; + address_8_15_xor2 = kof99_address_8_15_xor2; + address_16_23_xor1 = kof99_address_16_23_xor1; + address_16_23_xor2 = kof99_address_16_23_xor2; + address_0_7_xor = kof99_address_0_7_xor; + neogeo_gfx_decrypt(rom, rom_size, extra_xor); +} + + +/* CMC50 protection chip */ +void cmc_prot_device::cmc50_neogeo_gfx_decrypt(UINT8* rom, UINT32 rom_size, UINT8* fixed, UINT32 fixed_size, int extra_xor) +{ + type0_t03 = kof2000_type0_t03; + type0_t12 = kof2000_type0_t12; + type1_t03 = kof2000_type1_t03; + type1_t12 = kof2000_type1_t12; + address_8_15_xor1 = kof2000_address_8_15_xor1; + address_8_15_xor2 = kof2000_address_8_15_xor2; + address_16_23_xor1 = kof2000_address_16_23_xor1; + address_16_23_xor2 = kof2000_address_16_23_xor2; + address_0_7_xor = kof2000_address_0_7_xor; + neogeo_gfx_decrypt(rom, rom_size, extra_xor); +} + + + +/*************************************************************************** + +NeoGeo 'M' ROM encryption + CMC50 protection chip + +***************************************************************************/ + + +static const UINT8 m1_address_8_15_xor[256] = +{ + 0x0a, 0x72, 0xb7, 0xaf, 0x67, 0xde, 0x1d, 0xb1, 0x78, 0xc4, 0x4f, 0xb5, 0x4b, 0x18, 0x76, 0xdd, + 0x11, 0xe2, 0x36, 0xa1, 0x82, 0x03, 0x98, 0xa0, 0x10, 0x5f, 0x3f, 0xd6, 0x1f, 0x90, 0x6a, 0x0b, + 0x70, 0xe0, 0x64, 0xcb, 0x9f, 0x38, 0x8b, 0x53, 0x04, 0xca, 0xf8, 0xd0, 0x07, 0x68, 0x56, 0x32, + 0xae, 0x1c, 0x2e, 0x48, 0x63, 0x92, 0x9a, 0x9c, 0x44, 0x85, 0x41, 0x40, 0x09, 0xc0, 0xc8, 0xbf, + 0xea, 0xbb, 0xf7, 0x2d, 0x99, 0x21, 0xf6, 0xba, 0x15, 0xce, 0xab, 0xb0, 0x2a, 0x60, 0xbc, 0xf1, + 0xf0, 0x9e, 0xd5, 0x97, 0xd8, 0x4e, 0x14, 0x9d, 0x42, 0x4d, 0x2c, 0x5c, 0x2b, 0xa6, 0xe1, 0xa7, + 0xef, 0x25, 0x33, 0x7a, 0xeb, 0xe7, 0x1b, 0x6d, 0x4c, 0x52, 0x26, 0x62, 0xb6, 0x35, 0xbe, 0x80, + 0x01, 0xbd, 0xfd, 0x37, 0xf9, 0x47, 0x55, 0x71, 0xb4, 0xf2, 0xff, 0x27, 0xfa, 0x23, 0xc9, 0x83, + 0x17, 0x39, 0x13, 0x0d, 0xc7, 0x86, 0x16, 0xec, 0x49, 0x6f, 0xfe, 0x34, 0x05, 0x8f, 0x00, 0xe6, + 0xa4, 0xda, 0x7b, 0xc1, 0xf3, 0xf4, 0xd9, 0x75, 0x28, 0x66, 0x87, 0xa8, 0x45, 0x6c, 0x20, 0xe9, + 0x77, 0x93, 0x7e, 0x3c, 0x1e, 0x74, 0xf5, 0x8c, 0x3e, 0x94, 0xd4, 0xc2, 0x5a, 0x06, 0x0e, 0xe8, + 0x3d, 0xa9, 0xb2, 0xe3, 0xe4, 0x22, 0xcf, 0x24, 0x8e, 0x6b, 0x8a, 0x8d, 0x84, 0x4a, 0xd2, 0x91, + 0x88, 0x79, 0x57, 0xa5, 0x0f, 0xcd, 0xb9, 0xac, 0x3b, 0xaa, 0xb3, 0xd1, 0xee, 0x31, 0x81, 0x7c, + 0xd7, 0x89, 0xd3, 0x96, 0x43, 0xc5, 0xc6, 0xc3, 0x69, 0x7f, 0x46, 0xdf, 0x30, 0x5b, 0x6e, 0xe5, + 0x08, 0x95, 0x9b, 0xfb, 0xb8, 0x58, 0x0c, 0x61, 0x50, 0x5d, 0x3a, 0xa2, 0x29, 0x12, 0xfc, 0x51, + 0x7d, 0x1a, 0x02, 0x65, 0x54, 0x5e, 0x19, 0xcc, 0xdc, 0xdb, 0x73, 0xed, 0xad, 0x59, 0x2f, 0xa3, +}; + +static const UINT8 m1_address_0_7_xor[256] = +{ + 0xf4, 0xbc, 0x02, 0xf7, 0x2c, 0x3d, 0xe8, 0xd9, 0x50, 0x62, 0xec, 0xbd, 0x53, 0x73, 0x79, 0x61, + 0x00, 0x34, 0xcf, 0xa2, 0x63, 0x28, 0x90, 0xaf, 0x44, 0x3b, 0xc5, 0x8d, 0x3a, 0x46, 0x07, 0x70, + 0x66, 0xbe, 0xd8, 0x8b, 0xe9, 0xa0, 0x4b, 0x98, 0xdc, 0xdf, 0xe2, 0x16, 0x74, 0xf1, 0x37, 0xf5, + 0xb7, 0x21, 0x81, 0x01, 0x1c, 0x1b, 0x94, 0x36, 0x09, 0xa1, 0x4a, 0x91, 0x30, 0x92, 0x9b, 0x9a, + 0x29, 0xb1, 0x38, 0x4d, 0x55, 0xf2, 0x56, 0x18, 0x24, 0x47, 0x9d, 0x3f, 0x80, 0x1f, 0x22, 0xa4, + 0x11, 0x54, 0x84, 0x0d, 0x25, 0x48, 0xee, 0xc6, 0x59, 0x15, 0x03, 0x7a, 0xfd, 0x6c, 0xc3, 0x33, + 0x5b, 0xc4, 0x7b, 0x5a, 0x05, 0x7f, 0xa6, 0x40, 0xa9, 0x5d, 0x41, 0x8a, 0x96, 0x52, 0xd3, 0xf0, + 0xab, 0x72, 0x10, 0x88, 0x6f, 0x95, 0x7c, 0xa8, 0xcd, 0x9c, 0x5f, 0x32, 0xae, 0x85, 0x39, 0xac, + 0xe5, 0xd7, 0xfb, 0xd4, 0x08, 0x23, 0x19, 0x65, 0x6b, 0xa7, 0x93, 0xbb, 0x2b, 0xbf, 0xb8, 0x35, + 0xd0, 0x06, 0x26, 0x68, 0x3e, 0xdd, 0xb9, 0x69, 0x2a, 0xb2, 0xde, 0x87, 0x45, 0x58, 0xff, 0x3c, + 0x9e, 0x7d, 0xda, 0xed, 0x49, 0x8c, 0x14, 0x8e, 0x75, 0x2f, 0xe0, 0x6e, 0x78, 0x6d, 0x20, 0xd2, + 0xfa, 0x2d, 0x51, 0xcc, 0xc7, 0xe7, 0x1d, 0x27, 0x97, 0xfc, 0x31, 0xdb, 0xf8, 0x42, 0xe3, 0x99, + 0x5e, 0x83, 0x0e, 0xb4, 0x2e, 0xf6, 0xc0, 0x0c, 0x4c, 0x57, 0xb6, 0x64, 0x0a, 0x17, 0xa3, 0xc1, + 0x77, 0x12, 0xfe, 0xe6, 0x8f, 0x13, 0x71, 0xe4, 0xf9, 0xad, 0x9f, 0xce, 0xd5, 0x89, 0x7e, 0x0f, + 0xc2, 0x86, 0xf3, 0x67, 0xba, 0x60, 0x43, 0xc9, 0x04, 0xb3, 0xb0, 0x1e, 0xb5, 0xc8, 0xeb, 0xa5, + 0x76, 0xea, 0x5c, 0x82, 0x1a, 0x4f, 0xaa, 0xca, 0xe1, 0x0b, 0x4e, 0xcb, 0x6a, 0xef, 0xd1, 0xd6, +}; + + +/* The CMC50 hardware does a checksum of the first 64kb of the M1 rom, + ,and uses this checksum as the basis of the key with which to decrypt + the rom */ + +UINT16 cmc_prot_device::generate_cs16(UINT8 *rom, int size) +{ + UINT16 cs16; + int i; + cs16 = 0x0000; + for (i=0;i<size;i++ ) + { + cs16 += rom[i]; + } + return cs16&0xFFFF; +} + + +int cmc_prot_device::m1_address_scramble(int address, UINT16 key) +{ + int block; + int aux; + + const int p1[8][16] = { + {15,14,10,7,1,2,3,8,0,12,11,13,6,9,5,4}, + {7,1,8,11,15,9,2,3,5,13,4,14,10,0,6,12}, + {8,6,14,3,10,7,15,1,4,0,2,5,13,11,12,9}, + {2,8,15,9,3,4,11,7,13,6,0,10,1,12,14,5}, + {1,13,6,15,14,3,8,10,9,4,7,12,5,2,0,11}, + {11,15,3,4,7,0,9,2,6,14,12,1,8,5,10,13}, + {10,5,13,8,6,15,1,14,11,9,3,0,12,7,4,2}, + {9,3,7,0,2,12,4,11,14,10,5,8,15,13,1,6}, + }; + + block = (address>>16)&7; + aux = address&0xffff; + + aux ^= BITSWAP16(key,12,0,2,4,8,15,7,13,10,1,3,6,11,9,14,5); + aux = BITSWAP16(aux, + p1[block][15],p1[block][14],p1[block][13],p1[block][12], + p1[block][11],p1[block][10],p1[block][9],p1[block][8], + p1[block][7],p1[block][6],p1[block][5],p1[block][4], + p1[block][3],p1[block][2],p1[block][1],p1[block][0]); + aux ^= m1_address_0_7_xor[(aux>>8)&0xff]; + aux ^= m1_address_8_15_xor[aux&0xff]<<8; + aux = BITSWAP16(aux, 7,15,14,6,5,13,12,4,11,3,10,2,9,1,8,0); + + return (block<<16)|aux; +} + + +void cmc_prot_device::neogeo_cmc50_m1_decrypt(UINT8* romcrypt, UINT32 romcrypt_size, UINT8* romaudio, UINT32 romaudio_size) +{ + UINT8* rom = romcrypt; + size_t rom_size = 0x80000; + UINT8* rom2 = romaudio; + + dynamic_buffer buffer(rom_size); + + UINT32 i; + + UINT16 key=generate_cs16(rom,0x10000); + + //printf("key %04x\n",key); + + for (i=0; i<rom_size; i++) + { + buffer[i] = rom[m1_address_scramble(i,key)]; + } + + memcpy(rom,&buffer[0],rom_size); + + memcpy(rom2,rom,0x10000); + memcpy(rom2+0x10000,rom,0x80000); + + #if 0 + { + FILE *fp; + const char *gamename = machine().system().name; + char filename[256]; + sprintf(filename, "%s_m1.dump", gamename); + + fp=fopen(filename, "w+b"); + if (fp) + { + fwrite(rom, rom_size, 1, fp); + fclose(fp); + } + } + #endif + + + #if 0 + { + FILE *fp; + const char *gamename = machine().system().name; + char filename[256]; + sprintf(filename, "%s_m1extra.dump", gamename); + + fp=fopen(filename, "w+b"); + if (fp) + { + fwrite(&rom[0xf800], 0x800, 1, fp); + fclose(fp); + } + } + #endif +} diff --git a/src/devices/bus/neogeo/cmc_prot.h b/src/devices/bus/neogeo/cmc_prot.h new file mode 100644 index 00000000000..8660c3bf3ed --- /dev/null +++ b/src/devices/bus/neogeo/cmc_prot.h @@ -0,0 +1,87 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#pragma once + +#ifndef __CMC_PROT__ +#define __CMC_PROT__ + +extern const device_type CMC_PROT; + +#define MCFG_CMC_PROT_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, CMC_PROT, 0) + +// cmc42 +#define KOF99_GFX_KEY (0x00) +#define GAROU_GFX_KEY (0x06) +#define MSLUG3_GFX_KEY (0xad) +#define ZUPAPA_GFX_KEY (0xbd) +#define GANRYU_GFX_KEY (0x07) +#define S1945P_GFX_KEY (0x05) +#define PREISLE2_GFX_KEY (0x9f) +#define BANGBEAD_GFX_KEY (0xf8) +#define NITD_GFX_KEY (0xff) +#define SENGOKU3_GFX_KEY (0xfe) + +// cmc50 +#define KOF2000_GFX_KEY (0x00) +#define KOF2001_GFX_KEY (0x1e) +#define MSLUG4_GFX_KEY (0x31) +#define ROTD_GFX_KEY (0x3f) +#define PNYAA_GFX_KEY (0x2e) +#define KOF2002_GFX_KEY (0xec) +#define MATRIM_GFX_KEY (0x6a) +#define SAMSHO5_GFX_KEY (0x0f) +#define SAMSHO5SP_GFX_KEY (0x0d) +#define MSLUG5_GFX_KEY (0x19) +#define SVC_GFX_KEY (0x57) +#define KOF2003_GFX_KEY (0x9d) +#define JOCKEYGP_GFX_KEY (0xac) + + +class cmc_prot_device : public device_t +{ +public: + // construction/destruction + cmc_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + void decrypt(UINT8 *r0, UINT8 *r1, + UINT8 c0, UINT8 c1, + const UINT8 *table0hi, + const UINT8 *table0lo, + const UINT8 *table1, + int base, + int invert); + + void neogeo_gfx_decrypt(UINT8* rom, UINT32 rom_size, int extra_xor); + void neogeo_sfix_decrypt(UINT8* rom, UINT32 rom_size, UINT8* fixed, UINT32 fixed_size); + void kof99_neogeo_gfx_decrypt(UINT8* rom, UINT32 rom_size, UINT8* fixed, UINT32 fixed_size, int extra_xor); + void kof2000_neogeo_gfx_decrypt(UINT8* rom, UINT32 rom_size, UINT8* fixed, UINT32 fixed_size, int extra_xor); + void cmc42_neogeo_gfx_decrypt(UINT8* rom, UINT32 rom_size, UINT8* fixed, UINT32 fixed_size, int extra_xor); + void cmc50_neogeo_gfx_decrypt(UINT8* rom, UINT32 rom_size, UINT8* fixed, UINT32 fixed_size, int extra_xor); + + UINT16 generate_cs16(UINT8 *rom, int size); + int m1_address_scramble(int address, UINT16 key); + void neogeo_cmc50_m1_decrypt(UINT8* romcrypt, UINT32 romcrypt_size, UINT8* romaudio, UINT32 romaudio_size); + +protected: + virtual void device_start(); + virtual void device_reset(); + + const UINT8 *type0_t03; + const UINT8 *type0_t12; + const UINT8 *type1_t03; + const UINT8 *type1_t12; + const UINT8 *address_8_15_xor1; + const UINT8 *address_8_15_xor2; + const UINT8 *address_16_23_xor1; + const UINT8 *address_16_23_xor2; + const UINT8 *address_0_7_xor; + +private: + + +}; + +#endif diff --git a/src/devices/bus/neogeo/fatfury2_cart.c b/src/devices/bus/neogeo/fatfury2_cart.c new file mode 100644 index 00000000000..047ca79a2eb --- /dev/null +++ b/src/devices/bus/neogeo/fatfury2_cart.c @@ -0,0 +1,75 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/*********************************************************************************************************** + + NEOGEO ROM cart emulation + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "fatfury2_cart.h" + + +//------------------------------------------------- +// neogeo_fatfury2_cart - constructor +//------------------------------------------------- + +const device_type NEOGEO_FATFURY2_CART = &device_creator<neogeo_fatfury2_cart>; + + +neogeo_fatfury2_cart::neogeo_fatfury2_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_neogeo_cart_interface( mconfig, *this ), + m_banked_cart(*this, "banked_cart"), + m_fatfury2_prot(*this, "fatfury2_prot") +{ +} + +neogeo_fatfury2_cart::neogeo_fatfury2_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock) + : device_t(mconfig, NEOGEO_FATFURY2_CART, "NEOGEO Fatal Fury 2 Cart", tag, owner, clock, "neogeo_rom", __FILE__), + device_neogeo_cart_interface( mconfig, *this ), + m_banked_cart(*this, "banked_cart"), + m_fatfury2_prot(*this, "fatfury2_prot") +{ +} + + +//------------------------------------------------- +// mapper specific start/reset +//------------------------------------------------- + +void neogeo_fatfury2_cart::device_start() +{ +} + +void neogeo_fatfury2_cart::device_reset() +{ +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +READ16_MEMBER(neogeo_fatfury2_cart::read_rom) +{ + return m_rom[offset]; +} + +static MACHINE_CONFIG_FRAGMENT( fatfury2_cart ) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") + MCFG_FATFURY2_PROT_ADD("fatfury2_prot") + +MACHINE_CONFIG_END + +machine_config_constructor neogeo_fatfury2_cart::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( fatfury2_cart ); +} + +void neogeo_fatfury2_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_fatfury2_prot->fatfury2_install_protection(maincpu, m_banked_cart); +} diff --git a/src/devices/bus/neogeo/fatfury2_cart.h b/src/devices/bus/neogeo/fatfury2_cart.h new file mode 100644 index 00000000000..1356d130bf9 --- /dev/null +++ b/src/devices/bus/neogeo/fatfury2_cart.h @@ -0,0 +1,41 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#ifndef __NEOGEO_FATFURY2_CART_H +#define __NEOGEO_FATFURY2_CART_H + +#include "neogeo_slot.h" +#include "banked_cart.h" +#include "fatfury2_prot.h" + +// ======================> neogeo_fatfury2_cart + +class neogeo_fatfury2_cart : public device_t, + public device_neogeo_cart_interface +{ +public: + // construction/destruction + neogeo_fatfury2_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source); + neogeo_fatfury2_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ16_MEMBER(read_rom); + + virtual void activate_cart(ACTIVATE_CART_PARAMS); + + required_device<neogeo_banked_cart_device> m_banked_cart; + required_device<fatfury2_prot_device> m_fatfury2_prot; + +}; + + + +// device type definition +extern const device_type NEOGEO_FATFURY2_CART; + + +#endif diff --git a/src/devices/bus/neogeo/fatfury2_prot.c b/src/devices/bus/neogeo/fatfury2_prot.c new file mode 100644 index 00000000000..07e483dbc44 --- /dev/null +++ b/src/devices/bus/neogeo/fatfury2_prot.c @@ -0,0 +1,110 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + +#include "emu.h" +#include "fatfury2_prot.h" + + + +extern const device_type FATFURY2_PROT = &device_creator<fatfury2_prot_device>; + + +fatfury2_prot_device::fatfury2_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, FATFURY2_PROT, "NeoGeo Protection (Fatal Fury 2)", tag, owner, clock, "fatfury2_prot", __FILE__) +{ +} + + +void fatfury2_prot_device::device_start() +{ + save_item(NAME(m_fatfury2_prot_data)); +} + +void fatfury2_prot_device::device_reset() +{ +} + + + +/************************ Fatal Fury 2 *************************/ + +READ16_MEMBER( fatfury2_prot_device::fatfury2_protection_16_r ) +{ + UINT16 res = m_fatfury2_prot_data >> 24; + + switch (offset) + { + case 0x55550/2: + case 0xffff0/2: + case 0x00000/2: + case 0xff000/2: + case 0x36000/2: + case 0x36008/2: + return res; + + case 0x36004/2: + case 0x3600c/2: + return ((res & 0xf0) >> 4) | ((res & 0x0f) << 4); + + default: + logerror("unknown protection read at pc %06x, offset %08x\n", space.device().safe_pc(), offset << 1); + return 0; + } +} + + +WRITE16_MEMBER( fatfury2_prot_device::fatfury2_protection_16_w ) +{ + switch (offset) + { + case 0x11112/2: /* data == 0x1111; expects 0xff000000 back */ + m_fatfury2_prot_data = 0xff000000; + break; + + case 0x33332/2: /* data == 0x3333; expects 0x0000ffff back */ + m_fatfury2_prot_data = 0x0000ffff; + break; + + case 0x44442/2: /* data == 0x4444; expects 0x00ff0000 back */ + m_fatfury2_prot_data = 0x00ff0000; + break; + + case 0x55552/2: /* data == 0x5555; read back from 55550, ffff0, 00000, ff000 */ + m_fatfury2_prot_data = 0xff00ff00; + break; + + case 0x56782/2: /* data == 0x1234; read back from 36000 *or* 36004 */ + m_fatfury2_prot_data = 0xf05a3601; + break; + + case 0x42812/2: /* data == 0x1824; read back from 36008 *or* 3600c */ + m_fatfury2_prot_data = 0x81422418; + break; + + case 0x55550/2: + case 0xffff0/2: + case 0xff000/2: + case 0x36000/2: + case 0x36004/2: + case 0x36008/2: + case 0x3600c/2: + m_fatfury2_prot_data <<= 8; + break; + + default: + logerror("unknown protection write at pc %06x, offset %08x, data %02x\n", space.device().safe_pc(), offset, data); + break; + } +} + + +void fatfury2_prot_device::fatfury2_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev) +{ + /* the protection involves reading and writing addresses in the */ + /* 0x2xxxxx range. There are several checks all around the code. */ + maincpu->space(AS_PROGRAM).install_readwrite_handler(0x200000, 0x2fffff, read16_delegate(FUNC(fatfury2_prot_device::fatfury2_protection_16_r),this), write16_delegate(FUNC(fatfury2_prot_device::fatfury2_protection_16_w),this)); + m_bankdev = bankdev; + + m_fatfury2_prot_data = 0; + +} diff --git a/src/devices/bus/neogeo/fatfury2_prot.h b/src/devices/bus/neogeo/fatfury2_prot.h new file mode 100644 index 00000000000..2abe9c92da6 --- /dev/null +++ b/src/devices/bus/neogeo/fatfury2_prot.h @@ -0,0 +1,42 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + +#pragma once + +#ifndef __FATFURY2_PROT__ +#define __FATFURY2_PROT__ + +#include "banked_cart.h" + +extern const device_type FATFURY2_PROT; + +#define MCFG_FATFURY2_PROT_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, FATFURY2_PROT, 0) + + +class fatfury2_prot_device : public device_t +{ +public: + // construction/destruction + fatfury2_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + DECLARE_READ16_MEMBER( fatfury2_protection_16_r ); + DECLARE_WRITE16_MEMBER( fatfury2_protection_16_w ); + void fatfury2_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev); + + + neogeo_banked_cart_device* m_bankdev; + UINT32 m_fatfury2_prot_data; + +protected: + virtual void device_start(); + virtual void device_reset(); + + + +private: + + +}; + +#endif diff --git a/src/devices/bus/neogeo/kof2002_cart.c b/src/devices/bus/neogeo/kof2002_cart.c new file mode 100644 index 00000000000..9726bd34b4b --- /dev/null +++ b/src/devices/bus/neogeo/kof2002_cart.c @@ -0,0 +1,157 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/*********************************************************************************************************** + + NEOGEO ROM cart emulation + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "kof2002_cart.h" + + +//------------------------------------------------- +// neogeo_kof2002_cart - constructor +//------------------------------------------------- + +const device_type NEOGEO_KOF2002_CART = &device_creator<neogeo_kof2002_cart>; + + +neogeo_kof2002_cart::neogeo_kof2002_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_cmc_prot(*this, "cmc_prot"), + m_pcm2_prot(*this, "pcm2_prot"), + m_kof2002_prot(*this, "kof2002_prot") +{ +} + +neogeo_kof2002_cart::neogeo_kof2002_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock) + : device_t(mconfig, NEOGEO_KOF2002_CART, "NEOGEO KOF2002 Cart", tag, owner, clock, "neogeo_rom", __FILE__), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_cmc_prot(*this, "cmc_prot"), + m_pcm2_prot(*this, "pcm2_prot"), + m_kof2002_prot(*this, "kof2002_prot") +{ +} + + +//------------------------------------------------- +// mapper specific start/reset +//------------------------------------------------- + +void neogeo_kof2002_cart::device_start() +{ +} + +void neogeo_kof2002_cart::device_reset() +{ +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +READ16_MEMBER(neogeo_kof2002_cart::read_rom) +{ + return m_rom[offset]; +} + +static MACHINE_CONFIG_FRAGMENT( kof2002_cart ) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") + MCFG_CMC_PROT_ADD("cmc_prot") + MCFG_PCM2_PROT_ADD("pcm2_prot") + MCFG_KOF2002_PROT_ADD("kof2002_prot") +MACHINE_CONFIG_END + +machine_config_constructor neogeo_kof2002_cart::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( kof2002_cart ); +} + + + +/* Individual cartridge types (mirror DRIVER_INIT functionality) */ + +/************************************************* + KOF2002 +**************************************************/ + +const device_type NEOGEO_KOF2002_KOF2002_CART = &device_creator<neogeo_kof2002_kof2002_cart>; + +neogeo_kof2002_kof2002_cart::neogeo_kof2002_kof2002_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_kof2002_cart(mconfig, NEOGEO_KOF2002_KOF2002_CART, "NEOGEO Kof2002-type kof2002 Cart", tag, owner, clock, "k2k_k2k_cart", __FILE__) {} + +void neogeo_kof2002_kof2002_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_kof2002_prot->kof2002_decrypt_68k(cpuregion, cpuregion_size); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF2002_GFX_KEY); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 0); + +} + +const device_type NEOGEO_KOF2002_KF2K2PLS_CART = &device_creator<neogeo_kof2002_kf2k2pls_cart>; + +neogeo_kof2002_kf2k2pls_cart::neogeo_kof2002_kf2k2pls_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_kof2002_cart(mconfig, NEOGEO_KOF2002_KF2K2PLS_CART, "NEOGEO Kof2002-type kof2002plus Cart", tag, owner, clock, "k2k_k2kpls_cart", __FILE__) {} + +void neogeo_kof2002_kf2k2pls_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_kof2002_prot->kof2002_decrypt_68k(cpuregion, cpuregion_size); + m_cmc_prot->cmc50_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF2002_GFX_KEY); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region,audio_region_size); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 0); +} + + +/************************************************* + MATRIM +**************************************************/ + +const device_type NEOGEO_KOF2002_MATRIM_CART = &device_creator<neogeo_kof2002_matrim_cart>; + +neogeo_kof2002_matrim_cart::neogeo_kof2002_matrim_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_kof2002_cart(mconfig, NEOGEO_KOF2002_MATRIM_CART, "NEOGEO Kof2002-type matrim Cart", tag, owner, clock, "k2k_matrim_cart", __FILE__) {} + +void neogeo_kof2002_matrim_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_kof2002_prot->matrim_decrypt_68k(cpuregion, cpuregion_size); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, MATRIM_GFX_KEY); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 1); + +} + +/************************************************* + SAMSHO5 +**************************************************/ + +const device_type NEOGEO_KOF2002_SAMSHO5_CART = &device_creator<neogeo_kof2002_samsho5_cart>; + +neogeo_kof2002_samsho5_cart::neogeo_kof2002_samsho5_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_kof2002_cart(mconfig, NEOGEO_KOF2002_SAMSHO5_CART, "NEOGEO Kof2002-type Samsho5 Cart", tag, owner, clock, "k2k_ss5_cart", __FILE__) {} + +void neogeo_kof2002_samsho5_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_kof2002_prot->samsho5_decrypt_68k(cpuregion, cpuregion_size); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, SAMSHO5_GFX_KEY); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 4); +} + +/************************************************* + SAMSHO5SP +**************************************************/ + +const device_type NEOGEO_KOF2002_SAMSHO5SP_CART = &device_creator<neogeo_kof2002_samsho5sp_cart>; + +neogeo_kof2002_samsho5sp_cart::neogeo_kof2002_samsho5sp_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_kof2002_cart(mconfig, NEOGEO_KOF2002_SAMSHO5SP_CART, "NEOGEO Kof2002-type Samsho5sp Cart", tag, owner, clock, "k2k_ss5s_cart", __FILE__) {} + +void neogeo_kof2002_samsho5sp_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_kof2002_prot->samsh5sp_decrypt_68k(cpuregion, cpuregion_size); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, SAMSHO5SP_GFX_KEY); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 6); +} diff --git a/src/devices/bus/neogeo/kof2002_cart.h b/src/devices/bus/neogeo/kof2002_cart.h new file mode 100644 index 00000000000..7d995c88adc --- /dev/null +++ b/src/devices/bus/neogeo/kof2002_cart.h @@ -0,0 +1,111 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#ifndef __NEOGEO_KOF2002_CART_H +#define __NEOGEO_KOF2002_CART_H + +#include "neogeo_slot.h" +#include "banked_cart.h" +#include "pcm2_prot.h" +#include "cmc_prot.h" +#include "kof2002_prot.h" + +// ======================> neogeo_kof2002_cart + +class neogeo_kof2002_cart : public device_t, + public device_neogeo_cart_interface +{ +public: + // construction/destruction + neogeo_kof2002_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source); + neogeo_kof2002_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ16_MEMBER(read_rom); + + virtual void activate_cart(ACTIVATE_CART_PARAMS) { m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); } + virtual void decrypt_all(DECRYPT_ALL_PARAMS) {} + virtual int get_fixed_bank_type(void) { return 0; } + + required_device<neogeo_banked_cart_device> m_banked_cart; + required_device<cmc_prot_device> m_cmc_prot; + required_device<pcm2_prot_device> m_pcm2_prot; + required_device<kof2002_prot_device> m_kof2002_prot; + +}; + + + +// device type definition +extern const device_type NEOGEO_KOF2002_CART; + + +/************************************************* + KOF2002 +**************************************************/ + +class neogeo_kof2002_kof2002_cart : public neogeo_kof2002_cart +{ +public: + neogeo_kof2002_kof2002_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_KOF2002_KOF2002_CART; + +class neogeo_kof2002_kf2k2pls_cart : public neogeo_kof2002_cart +{ +public: + neogeo_kof2002_kf2k2pls_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_KOF2002_KF2K2PLS_CART; + + + +/************************************************* + MATRIM +**************************************************/ + +class neogeo_kof2002_matrim_cart : public neogeo_kof2002_cart +{ +public: + neogeo_kof2002_matrim_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 2; } +}; +extern const device_type NEOGEO_KOF2002_MATRIM_CART; + +/************************************************* + SAMSHO5 +**************************************************/ + +class neogeo_kof2002_samsho5_cart : public neogeo_kof2002_cart +{ +public: + neogeo_kof2002_samsho5_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_KOF2002_SAMSHO5_CART; + +/************************************************* + SAMSHO5SP +**************************************************/ + +class neogeo_kof2002_samsho5sp_cart : public neogeo_kof2002_cart +{ +public: + neogeo_kof2002_samsho5sp_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_KOF2002_SAMSHO5SP_CART; + + +#endif diff --git a/src/devices/bus/neogeo/kof2002_prot.c b/src/devices/bus/neogeo/kof2002_prot.c new file mode 100644 index 00000000000..f234602a0c2 --- /dev/null +++ b/src/devices/bus/neogeo/kof2002_prot.c @@ -0,0 +1,83 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + +#include "emu.h" +#include "kof2002_prot.h" + + + +extern const device_type KOF2002_PROT = &device_creator<kof2002_prot_device>; + + +kof2002_prot_device::kof2002_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, KOF2002_PROT, "NeoGeo Protection (KOF2002)", tag, owner, clock, "kof2002_prot", __FILE__) +{ +} + + +void kof2002_prot_device::device_start() +{ +} + +void kof2002_prot_device::device_reset() +{ +} + + +/* kof2002, matrim, samsho5, samsh5sp have some simple block swapping */ +void kof2002_prot_device::kof2002_decrypt_68k(UINT8* cpurom, UINT32 cpurom_size) +{ + int i; + static const int sec[]={0x100000,0x280000,0x300000,0x180000,0x000000,0x380000,0x200000,0x080000}; + UINT8 *src = cpurom+0x100000; + dynamic_buffer dst(0x400000); + memcpy( &dst[0], src, 0x400000 ); + for( i=0; i<8; ++i ) + { + memcpy( src+i*0x80000, &dst[sec[i]], 0x80000 ); + } +} + + +void kof2002_prot_device::matrim_decrypt_68k(UINT8* cpurom, UINT32 cpurom_size) +{ + int i; + static const int sec[]={0x100000,0x280000,0x300000,0x180000,0x000000,0x380000,0x200000,0x080000}; + UINT8 *src = cpurom+0x100000; + dynamic_buffer dst(0x400000); + memcpy( &dst[0], src, 0x400000); + for( i=0; i<8; ++i ) + { + memcpy( src+i*0x80000, &dst[sec[i]], 0x80000 ); + } +} + + +void kof2002_prot_device::samsho5_decrypt_68k(UINT8* cpurom, UINT32 cpurom_size) +{ + int i; + static const int sec[]={0x000000,0x080000,0x700000,0x680000,0x500000,0x180000,0x200000,0x480000,0x300000,0x780000,0x600000,0x280000,0x100000,0x580000,0x400000,0x380000}; + UINT8 *src = cpurom; + dynamic_buffer dst(0x800000); + + memcpy( &dst[0], src, 0x800000 ); + for( i=0; i<16; ++i ) + { + memcpy( src+i*0x80000, &dst[sec[i]], 0x80000 ); + } +} + + +void kof2002_prot_device::samsh5sp_decrypt_68k(UINT8* cpurom, UINT32 cpurom_size) +{ + int i; + static const int sec[]={0x000000,0x080000,0x500000,0x480000,0x600000,0x580000,0x700000,0x280000,0x100000,0x680000,0x400000,0x780000,0x200000,0x380000,0x300000,0x180000}; + UINT8 *src = cpurom; + dynamic_buffer dst(0x800000); + + memcpy( &dst[0], src, 0x800000 ); + for( i=0; i<16; ++i ) + { + memcpy( src+i*0x80000, &dst[sec[i]], 0x80000 ); + } +} diff --git a/src/devices/bus/neogeo/kof2002_prot.h b/src/devices/bus/neogeo/kof2002_prot.h new file mode 100644 index 00000000000..b0abde55809 --- /dev/null +++ b/src/devices/bus/neogeo/kof2002_prot.h @@ -0,0 +1,38 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#pragma once + +#ifndef __KOF2002_PROT__ +#define __KOF2002_PROT__ + +extern const device_type KOF2002_PROT; + +#define MCFG_KOF2002_PROT_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, KOF2002_PROT, 0) + + +class kof2002_prot_device : public device_t +{ +public: + // construction/destruction + kof2002_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + void kof2002_decrypt_68k(UINT8* cpurom, UINT32 cpurom_size); + void matrim_decrypt_68k(UINT8* cpurom, UINT32 cpurom_size); + void samsho5_decrypt_68k(UINT8* cpurom, UINT32 cpurom_size); + void samsh5sp_decrypt_68k(UINT8* cpurom, UINT32 cpurom_size); + +protected: + virtual void device_start(); + virtual void device_reset(); + + + +private: + + +}; + +#endif diff --git a/src/devices/bus/neogeo/kof98_cart.c b/src/devices/bus/neogeo/kof98_cart.c new file mode 100644 index 00000000000..6314522e4ff --- /dev/null +++ b/src/devices/bus/neogeo/kof98_cart.c @@ -0,0 +1,80 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/*********************************************************************************************************** + + NEOGEO ROM cart emulation + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "kof98_cart.h" + + +//------------------------------------------------- +// neogeo_kof98_cart - constructor +//------------------------------------------------- + +const device_type NEOGEO_KOF98_CART = &device_creator<neogeo_kof98_cart>; + + +neogeo_kof98_cart::neogeo_kof98_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_neogeo_cart_interface( mconfig, *this ), + m_banked_cart(*this, "banked_cart"), + m_kof98_prot(*this, "kof98_prot") +{ +} + +neogeo_kof98_cart::neogeo_kof98_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock) + : device_t(mconfig, NEOGEO_KOF98_CART, "NEOGEO KOF98 Cart", tag, owner, clock, "neogeo_rom", __FILE__), + device_neogeo_cart_interface( mconfig, *this ), + m_banked_cart(*this, "banked_cart"), + m_kof98_prot(*this, "kof98_prot") +{ +} + + +//------------------------------------------------- +// mapper specific start/reset +//------------------------------------------------- + +void neogeo_kof98_cart::device_start() +{ +} + +void neogeo_kof98_cart::device_reset() +{ +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +READ16_MEMBER(neogeo_kof98_cart::read_rom) +{ + return m_rom[offset]; +} + +static MACHINE_CONFIG_FRAGMENT( kof98_cart ) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") + MCFG_KOF98_PROT_ADD("kof98_prot") + +MACHINE_CONFIG_END + +machine_config_constructor neogeo_kof98_cart::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( kof98_cart ); +} + +void neogeo_kof98_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_kof98_prot->kof98_decrypt_68k(cpuregion, cpuregion_size); +} + +void neogeo_kof98_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_kof98_prot->install_kof98_protection(maincpu); +} diff --git a/src/devices/bus/neogeo/kof98_cart.h b/src/devices/bus/neogeo/kof98_cart.h new file mode 100644 index 00000000000..f0054d8c4bd --- /dev/null +++ b/src/devices/bus/neogeo/kof98_cart.h @@ -0,0 +1,41 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#ifndef __NEOGEO_KOF98_CART_H +#define __NEOGEO_KOF98_CART_H + +#include "neogeo_slot.h" +#include "banked_cart.h" +#include "kof98_prot.h" + +// ======================> neogeo_kof98_cart + +class neogeo_kof98_cart : public device_t, + public device_neogeo_cart_interface +{ +public: + // construction/destruction + neogeo_kof98_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source); + neogeo_kof98_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ16_MEMBER(read_rom); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual void activate_cart(ACTIVATE_CART_PARAMS); + + required_device<neogeo_banked_cart_device> m_banked_cart; + required_device<kof98_prot_device> m_kof98_prot; + +}; + + + +// device type definition +extern const device_type NEOGEO_KOF98_CART; + + +#endif diff --git a/src/devices/bus/neogeo/kof98_prot.c b/src/devices/bus/neogeo/kof98_prot.c new file mode 100644 index 00000000000..fefe7c190d3 --- /dev/null +++ b/src/devices/bus/neogeo/kof98_prot.c @@ -0,0 +1,141 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#include "emu.h" +#include "kof98_prot.h" + + + +extern const device_type KOF98_PROT = &device_creator<kof98_prot_device>; + + +kof98_prot_device::kof98_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, KOF98_PROT, "NeoGeo Protection (KOF98)", tag, owner, clock, "kof98_prot", __FILE__) +{ +} + + +void kof98_prot_device::device_start() +{ +} + +void kof98_prot_device::device_reset() +{ + kof98_prot_state = 0; +} + + +/* Kof98 uses an early encryption, quite different from the others */ +void kof98_prot_device::kof98_decrypt_68k(UINT8* cpurom, UINT32 cpurom_size) +{ + UINT8 *src = cpurom; + dynamic_buffer dst(0x200000); + int i, j, k; + static const UINT32 sec[]={0x000000,0x100000,0x000004,0x100004,0x10000a,0x00000a,0x10000e,0x00000e}; + static const UINT32 pos[]={0x000,0x004,0x00a,0x00e}; + + memcpy( &dst[0], src, 0x200000); + for( i=0x800; i<0x100000; i+=0x200 ) + { + for( j=0; j<0x100; j+=0x10 ) + { + for( k=0; k<16; k+=2) + { + memcpy( &src[i+j+k], &dst[ i+j+sec[k/2]+0x100 ], 2 ); + memcpy( &src[i+j+k+0x100], &dst[ i+j+sec[k/2] ], 2 ); + } + if( i >= 0x080000 && i < 0x0c0000) + { + for( k=0; k<4; k++ ) + { + memcpy( &src[i+j+pos[k]], &dst[i+j+pos[k]], 2 ); + memcpy( &src[i+j+pos[k]+0x100], &dst[i+j+pos[k]+0x100], 2 ); + } + } + else if( i >= 0x0c0000 ) + { + for( k=0; k<4; k++ ) + { + memcpy( &src[i+j+pos[k]], &dst[i+j+pos[k]+0x100], 2 ); + memcpy( &src[i+j+pos[k]+0x100], &dst[i+j+pos[k]], 2 ); + } + } + } + memcpy( &src[i+0x000000], &dst[i+0x000000], 2 ); + memcpy( &src[i+0x000002], &dst[i+0x100000], 2 ); + memcpy( &src[i+0x000100], &dst[i+0x000100], 2 ); + memcpy( &src[i+0x000102], &dst[i+0x100100], 2 ); + } + memmove( &src[0x100000], &src[0x200000], 0x400000 ); + + UINT16* mem16 = (UINT16*)cpurom; + m_default_rom[0] = mem16[0x100 / 2]; + m_default_rom[1] = mem16[0x102 / 2]; + + +} + + +/************************ King of Fighters 98******************* + The encrypted set has a rom overlay feature, checked at + various points in the game. + Boards used: NEO-MVS PROGSF1 (1998.6.17) / NEO-MVS PROGSF1E (1998.6.18) + The boards have an ALTERA chip (EPM7128SQC100-15) which is tied to 242-P1 +***************************************************************/ + +READ16_MEMBER(kof98_prot_device::kof98_prot_r) +{ + if (kof98_prot_state == 1) + { + if (!offset) + return 0x00c2; + else + return 0x00fd; + } + if (kof98_prot_state == 2) + { + if (!offset) + return 0x4e45; + else + return 0x4f2d; + } + + if (!offset) + return m_default_rom[0]; + else + return m_default_rom[1]; + + // never executed + //return 0xffff; +} + +WRITE16_MEMBER( kof98_prot_device::kof98_prot_w ) +{ + /* info from razoola */ + switch (data) + { + case 0x0090: + logerror ("%06x kof98 - protection 0x0090x\n", space.device().safe_pc()); + kof98_prot_state = 1; + break; + + case 0x00f0: + logerror ("%06x kof98 - protection 0x00f0x\n", space.device().safe_pc()); + kof98_prot_state = 2; + break; + + default: // 00aa is written, but not needed? + logerror ("%06x kof98 - unknown protection write %04x\n", space.device().safe_pc(), data); + break; + } +} + + +void kof98_prot_device::install_kof98_protection(cpu_device* maincpu) +{ + /* when 0x20aaaa contains 0x0090 (word) then 0x100 (normally the neogeo header) should return 0x00c200fd worked out using real hw */ + maincpu->space(AS_PROGRAM).install_read_handler(0x00100, 0x00103, read16_delegate(FUNC(kof98_prot_device::kof98_prot_r),this)); + + maincpu->space(AS_PROGRAM).install_write_handler(0x20aaaa, 0x20aaab, write16_delegate(FUNC(kof98_prot_device::kof98_prot_w),this)); +} diff --git a/src/devices/bus/neogeo/kof98_prot.h b/src/devices/bus/neogeo/kof98_prot.h new file mode 100644 index 00000000000..bdd634cbb04 --- /dev/null +++ b/src/devices/bus/neogeo/kof98_prot.h @@ -0,0 +1,40 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#pragma once + +#ifndef __KOF98_PROT__ +#define __KOF98_PROT__ + +extern const device_type KOF98_PROT; + +#define MCFG_KOF98_PROT_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, KOF98_PROT, 0) + + +class kof98_prot_device : public device_t +{ +public: + // construction/destruction + kof98_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + void kof98_decrypt_68k(UINT8* cpurom, UINT32 cpurom_size); + void install_kof98_protection(cpu_device* maincpu); + DECLARE_WRITE16_MEMBER(kof98_prot_w); + DECLARE_READ16_MEMBER(kof98_prot_r); + int kof98_prot_state; + UINT16 m_default_rom[2]; + +protected: + virtual void device_start(); + virtual void device_reset(); + + + +private: + + +}; + +#endif diff --git a/src/devices/bus/neogeo/kog_prot.c b/src/devices/bus/neogeo/kog_prot.c new file mode 100644 index 00000000000..d3caaff3e15 --- /dev/null +++ b/src/devices/bus/neogeo/kog_prot.c @@ -0,0 +1,118 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#include "emu.h" +#include "kog_prot.h" + + + +extern const device_type KOG_PROT = &device_creator<kog_prot_device>; + + +kog_prot_device::kog_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, KOG_PROT, "NeoGeo Protection (King of Gladiator)", tag, owner, clock, "kog_prot", __FILE__), + m_jumper(*this, "JUMPER") +{ +} + + +void kog_prot_device::device_start() +{ +} + +void kog_prot_device::device_reset() +{ +} + +READ16_MEMBER(kog_prot_device::read_jumper) +{ + return ioport("JUMPER")->read(); +} + +void kog_prot_device::kog_install_protection(cpu_device* maincpu) +{ + /* overlay cartridge ROM */ + maincpu->space(AS_PROGRAM).install_read_handler(0x0ffffe, 0x0fffff, read16_delegate(FUNC(kog_prot_device::read_jumper), this)); +} + + +/* The King of Gladiator (The King of Fighters '97 bootleg) */ + + +/* The protection patching here may be incomplete + Thanks to Razoola for the info */ + +void kog_prot_device::kog_px_decrypt(UINT8* cpurom, UINT32 cpurom_size) +{ + /* the protection chip does some *very* strange things to the rom */ + UINT8 *src = cpurom; + dynamic_buffer dst( 0x600000 ); + UINT16 *rom = (UINT16 *)cpurom; + int i; + static const int sec[] = { 0x3, 0x8, 0x7, 0xC, 0x1, 0xA, 0x6, 0xD }; + + for (i = 0; i < 8; i++){ + memcpy (&dst[i * 0x20000], src + sec[i] * 0x20000, 0x20000); + } + + memcpy (&dst[0x0007A6], src + 0x0407A6, 0x000006); + memcpy (&dst[0x0007C6], src + 0x0407C6, 0x000006); + memcpy (&dst[0x0007E6], src + 0x0407E6, 0x000006); + memcpy (&dst[0x090000], src + 0x040000, 0x004000); + memcpy (&dst[0x100000], src + 0x200000, 0x400000); + memcpy (src, &dst[0], 0x600000); + + for (i = 0x90000/2; i < 0x94000/2; i++){ + if (((rom[i]&0xFFBF) == 0x4EB9 || rom[i] == 0x43F9) && !rom[i + 1]) + rom[i + 1] = 0x0009; + + if (rom[i] == 0x4EB8) + rom[i] = 0x6100; + } + + rom[0x007A8/2] = 0x0009; + rom[0x007C8/2] = 0x0009; + rom[0x007E8/2] = 0x0009; + rom[0x93408/2] = 0xF168; + rom[0x9340C/2] = 0xFB7A; + rom[0x924AC/2] = 0x0009; + rom[0x9251C/2] = 0x0009; + rom[0x93966/2] = 0xFFDA; + rom[0x93974/2] = 0xFFCC; + rom[0x93982/2] = 0xFFBE; + rom[0x93990/2] = 0xFFB0; + rom[0x9399E/2] = 0xFFA2; + rom[0x939AC/2] = 0xFF94; + rom[0x939BA/2] = 0xFF86; + rom[0x939C8/2] = 0xFF78; + rom[0x939D4/2] = 0xFA5C; + rom[0x939E0/2] = 0xFA50; + rom[0x939EC/2] = 0xFA44; + rom[0x939F8/2] = 0xFA38; + rom[0x93A04/2] = 0xFA2C; + rom[0x93A10/2] = 0xFA20; + rom[0x93A1C/2] = 0xFA14; + rom[0x93A28/2] = 0xFA08; + rom[0x93A34/2] = 0xF9FC; + rom[0x93A40/2] = 0xF9F0; + rom[0x93A4C/2] = 0xFD14; + rom[0x93A58/2] = 0xFD08; + rom[0x93A66/2] = 0xF9CA; + rom[0x93A72/2] = 0xF9BE; + +} + + +static INPUT_PORTS_START( kog ) + /* a jumper on the pcb overlays a ROM address, very strange but that's how it works. */ + PORT_START("JUMPER") + PORT_DIPNAME( 0x0001, 0x0001, "Title Language" ) PORT_DIPLOCATION("CART-JUMPER:1") + PORT_DIPSETTING( 0x0001, DEF_STR( English ) ) + PORT_DIPSETTING( 0x0000, "Non-English" ) + PORT_BIT( 0x00fe, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED ) +INPUT_PORTS_END + +ioport_constructor kog_prot_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( kog ); +} diff --git a/src/devices/bus/neogeo/kog_prot.h b/src/devices/bus/neogeo/kog_prot.h new file mode 100644 index 00000000000..c14b6d919d0 --- /dev/null +++ b/src/devices/bus/neogeo/kog_prot.h @@ -0,0 +1,40 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#pragma once + +#ifndef __KOG_PROT__ +#define __KOG_PROT__ + +extern const device_type KOG_PROT; + +#define MCFG_KOG_PROT_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, KOG_PROT, 0) + + +class kog_prot_device : public device_t +{ +public: + // construction/destruction + kog_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + void kog_install_protection(cpu_device* maincpu); + void kog_px_decrypt(UINT8* cpurom, UINT32 cpurom_size); + READ16_MEMBER(read_jumper); + + required_ioport m_jumper; + +protected: + virtual void device_start(); + virtual void device_reset(); + virtual ioport_constructor device_input_ports() const; + + + +private: + + +}; + +#endif diff --git a/src/devices/bus/neogeo/mslugx_cart.c b/src/devices/bus/neogeo/mslugx_cart.c new file mode 100644 index 00000000000..d6bd6388864 --- /dev/null +++ b/src/devices/bus/neogeo/mslugx_cart.c @@ -0,0 +1,75 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/*********************************************************************************************************** + + NEOGEO ROM cart emulation + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "mslugx_cart.h" + + +//------------------------------------------------- +// neogeo_mslugx_cart - constructor +//------------------------------------------------- + +const device_type NEOGEO_MSLUGX_CART = &device_creator<neogeo_mslugx_cart>; + + +neogeo_mslugx_cart::neogeo_mslugx_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_neogeo_cart_interface( mconfig, *this ), + m_banked_cart(*this, "banked_cart"), + m_mslugx_prot(*this, "mslugx_prot") +{ +} + +neogeo_mslugx_cart::neogeo_mslugx_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock) + : device_t(mconfig, NEOGEO_MSLUGX_CART, "NEOGEO Metal Slug X Cart", tag, owner, clock, "neogeo_rom", __FILE__), + device_neogeo_cart_interface( mconfig, *this ), + m_banked_cart(*this, "banked_cart"), + m_mslugx_prot(*this, "mslugx_prot") +{ +} + + +//------------------------------------------------- +// mapper specific start/reset +//------------------------------------------------- + +void neogeo_mslugx_cart::device_start() +{ +} + +void neogeo_mslugx_cart::device_reset() +{ +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +READ16_MEMBER(neogeo_mslugx_cart::read_rom) +{ + return m_rom[offset]; +} + +static MACHINE_CONFIG_FRAGMENT( mslugx_cart ) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") + MCFG_MSLUGX_PROT_ADD("mslugx_prot") + +MACHINE_CONFIG_END + +machine_config_constructor neogeo_mslugx_cart::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( mslugx_cart ); +} + +void neogeo_mslugx_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_mslugx_prot->mslugx_install_protection(maincpu); +} diff --git a/src/devices/bus/neogeo/mslugx_cart.h b/src/devices/bus/neogeo/mslugx_cart.h new file mode 100644 index 00000000000..70d25d2338a --- /dev/null +++ b/src/devices/bus/neogeo/mslugx_cart.h @@ -0,0 +1,41 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#ifndef __NEOGEO_MSLUGX_CART_H +#define __NEOGEO_MSLUGX_CART_H + +#include "neogeo_slot.h" +#include "banked_cart.h" +#include "mslugx_prot.h" + +// ======================> neogeo_mslugx_cart + +class neogeo_mslugx_cart : public device_t, + public device_neogeo_cart_interface +{ +public: + // construction/destruction + neogeo_mslugx_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source); + neogeo_mslugx_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ16_MEMBER(read_rom); + + virtual void activate_cart(ACTIVATE_CART_PARAMS); + + required_device<neogeo_banked_cart_device> m_banked_cart; + required_device<mslugx_prot_device> m_mslugx_prot; + +}; + + + +// device type definition +extern const device_type NEOGEO_MSLUGX_CART; + + +#endif diff --git a/src/devices/bus/neogeo/mslugx_prot.c b/src/devices/bus/neogeo/mslugx_prot.c new file mode 100644 index 00000000000..567f308414c --- /dev/null +++ b/src/devices/bus/neogeo/mslugx_prot.c @@ -0,0 +1,95 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#include "emu.h" +#include "mslugx_prot.h" + + + +extern const device_type MSLUGX_PROT = &device_creator<mslugx_prot_device>; + + +mslugx_prot_device::mslugx_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, MSLUGX_PROT, "NeoGeo Protection (Metal Slug X)", tag, owner, clock, "mslugx_prot", __FILE__) +{ +} + + +void mslugx_prot_device::device_start() +{ + save_item(NAME(m_mslugx_command)); + save_item(NAME(m_mslugx_counter)); +} + +void mslugx_prot_device::device_reset() +{ +} + + + + +/************************ Metal Slug X ************************* + Board used: NEO-MVS PROGEOP (1999.2.2) + The board has an ALTERA chip (EPM7128SQC100-15) which is tied to 250-P1 + Also found is a QFP144 chip labeled with 0103 - function unknown +***************************************************************/ + +WRITE16_MEMBER( mslugx_prot_device::mslugx_protection_16_w ) +{ + switch (offset) + { + case 0x0/2: // start new read? + m_mslugx_command = 0; + break; + + case 0x2/2: // command? These are pulsed with data and then 0 + case 0x4/2: + m_mslugx_command |= data; + break; + + case 0x6/2: // finished? + break; + + case 0xa/2: // init? + m_mslugx_counter = 0; + m_mslugx_command = 0; + break; + + default: + logerror("unknown protection write at pc %06x, offset %08x, data %02x\n", space.device().safe_pc(), offset << 1, data); + break; + } +} + + +READ16_MEMBER( mslugx_prot_device::mslugx_protection_16_r ) +{ + UINT16 res = 0; + + switch (m_mslugx_command) + { + case 0x0001: { // $3bdc(?) and $3c30 (Register D7) + res = (space.read_byte(0xdedd2 + ((m_mslugx_counter >> 3) & 0xfff)) >> (~m_mslugx_counter & 0x07)) & 1; + m_mslugx_counter++; + } + break; + + case 0x0fff: { // All other accesses (Register D2) + INT32 select = space.read_word(0x10f00a) - 1; // How should this be calculated? + res = (space.read_byte(0xdedd2 + ((select >> 3) & 0x0fff)) >> (~select & 0x07)) & 1; + } + break; + + default: + logerror("unknown protection read at pc %06x, offset %08x\n", space.device().safe_pc(), offset << 1); + break; + } + + return res; +} + + +void mslugx_prot_device::mslugx_install_protection(cpu_device* maincpu) +{ + maincpu->space(AS_PROGRAM).install_readwrite_handler(0x2fffe0, 0x2fffef, read16_delegate(FUNC(mslugx_prot_device::mslugx_protection_16_r),this), write16_delegate(FUNC(mslugx_prot_device::mslugx_protection_16_w),this)); + +} diff --git a/src/devices/bus/neogeo/mslugx_prot.h b/src/devices/bus/neogeo/mslugx_prot.h new file mode 100644 index 00000000000..dabd8425503 --- /dev/null +++ b/src/devices/bus/neogeo/mslugx_prot.h @@ -0,0 +1,41 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#pragma once + +#ifndef __MSLUGX_PROT__ +#define __MSLUGX_PROT__ + +extern const device_type MSLUGX_PROT; + +#define MCFG_MSLUGX_PROT_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, MSLUGX_PROT, 0) + + +class mslugx_prot_device : public device_t +{ +public: + // construction/destruction + mslugx_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + + DECLARE_WRITE16_MEMBER( mslugx_protection_16_w ); + DECLARE_READ16_MEMBER( mslugx_protection_16_r ); + void mslugx_install_protection(cpu_device* maincpu); + + UINT16 m_mslugx_counter; + UINT16 m_mslugx_command; + +protected: + virtual void device_start(); + virtual void device_reset(); + + + +private: + + +}; + +#endif diff --git a/src/devices/bus/neogeo/neogeo_carts.c b/src/devices/bus/neogeo/neogeo_carts.c new file mode 100644 index 00000000000..8f9d62037b4 --- /dev/null +++ b/src/devices/bus/neogeo/neogeo_carts.c @@ -0,0 +1,97 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + /********************************************************************** + +**********************************************************************/ + +#include "neogeo_carts.h" + +SLOT_INTERFACE_START(neogeo_cart) + /* Standard cart with banking */ + SLOT_INTERFACE_INTERNAL("rom", NEOGEO_ROM) + + /* Custom MslugX protection*/ + SLOT_INTERFACE_INTERNAL("rom_mslugx", NEOGEO_MSLUGX_CART) + /* Custom Fatal Fury 2 protection */ + SLOT_INTERFACE_INTERNAL("rom_fatfur2", NEOGEO_FATFURY2_CART) + /* Custom KOF98 protection */ + SLOT_INTERFACE_INTERNAL("rom_kof98", NEOGEO_KOF98_CART) + + /* These use SMA for prg + CMC42 for gfx */ + SLOT_INTERFACE_INTERNAL("rom_sma", NEOGEO_SMA_CART) + SLOT_INTERFACE_INTERNAL("rom_sma_kof99", NEOGEO_SMA_KOF99_CART) + SLOT_INTERFACE_INTERNAL("rom_sma_garou", NEOGEO_SMA_GAROU_CART) + SLOT_INTERFACE_INTERNAL("rom_sma_garouh", NEOGEO_SMA_GAROUH_CART) + SLOT_INTERFACE_INTERNAL("rom_sma_mslug3", NEOGEO_SMA_MSLUG3_CART) + /* These use SMA for prg + CMC50 for gfx (& audiocpu) */ + SLOT_INTERFACE_INTERNAL("rom_sma_kof2000", NEOGEO_SMA_KOF2000_CART) + /* only CMC42 for gfx */ + SLOT_INTERFACE_INTERNAL("rom_cmc_zupapa", NEOGEO_CMC_ZUPAPA_CART) + SLOT_INTERFACE_INTERNAL("rom_cmc_mslug3h", NEOGEO_CMC_MSLUG3H_CART) + SLOT_INTERFACE_INTERNAL("rom_cmc_ganryu", NEOGEO_CMC_GANRYU_CART) + SLOT_INTERFACE_INTERNAL("rom_cmc_s1945p", NEOGEO_CMC_S1945P_CART) + SLOT_INTERFACE_INTERNAL("r_cmc_preisle2", NEOGEO_CMC_PREISLE2_CART) + SLOT_INTERFACE_INTERNAL("r_cmc_bangbead", NEOGEO_CMC_BANGBEAD_CART) + SLOT_INTERFACE_INTERNAL("rom_cmc_nitd", NEOGEO_CMC_NITD_CART) + SLOT_INTERFACE_INTERNAL("r_cmc_sengoku3", NEOGEO_CMC_SENGOKU3_CART) + SLOT_INTERFACE_INTERNAL("r_cmc_kof99k", NEOGEO_CMC_KOF99K_CART) + /* only CMC50 for gfx (& audiocpu) */ + SLOT_INTERFACE_INTERNAL("r_cmc_kof2001", NEOGEO_CMC_KOF2001_CART) + SLOT_INTERFACE_INTERNAL("r_cmc_kof2000n", NEOGEO_CMC_KOF2000N_CART) + /* CMC50 for gfx (& audiocpu) + NEOPCM2 for YM scramble */ + SLOT_INTERFACE_INTERNAL("r_pc2_mslug4", NEOGEO_PCM2_MSLUG4_CART) + SLOT_INTERFACE_INTERNAL("r_pc2_rotd", NEOGEO_PCM2_ROTD_CART) + SLOT_INTERFACE_INTERNAL("r_pc2_pnyaa", NEOGEO_PCM2_PNYAA_CART) + SLOT_INTERFACE_INTERNAL("r_ms4plus", NEOGEO_PCM2_MS4PLUS_CART) // regular encryption but external S1 rom + + /* CMC50 for gfx (& audiocpu) + NEOPCM2 for YM scramble + additonal prg scramble */ + SLOT_INTERFACE_INTERNAL("r_k2_kof2002", NEOGEO_KOF2002_KOF2002_CART) + SLOT_INTERFACE_INTERNAL("r_k2_matrim", NEOGEO_KOF2002_MATRIM_CART) + SLOT_INTERFACE_INTERNAL("r_k2_samsh5", NEOGEO_KOF2002_SAMSHO5_CART) + SLOT_INTERFACE_INTERNAL("r_k2_sams5s", NEOGEO_KOF2002_SAMSHO5SP_CART) + SLOT_INTERFACE_INTERNAL("r_kf2k2pls", NEOGEO_KOF2002_KF2K2PLS_CART) // regular encryption but external S1 rom + + /* CMC50 for gfx (& audiocpu) + NEOPCM2 for YM scramble + PVC protection/encryption */ + SLOT_INTERFACE_INTERNAL("r_pv_mslug5", NEOGEO_PVC_MSLUG5_CART) + SLOT_INTERFACE_INTERNAL("r_pv_svc", NEOGEO_PVC_SVC_CART) + SLOT_INTERFACE_INTERNAL("r_pv_kf2k3", NEOGEO_PVC_KOF2003_CART) + SLOT_INTERFACE_INTERNAL("r_pv_kf2k3h", NEOGEO_PVC_KOF2003H_CART) + + /* 100% bootleg logic */ + SLOT_INTERFACE_INTERNAL("r_garoubl", NEOGEO_BOOTLEG_GAROUBL_CART) + SLOT_INTERFACE_INTERNAL("r_cthd2003", NEOGEO_BOOTLEG_CTHD2003_CART) + SLOT_INTERFACE_INTERNAL("r_cthd2003sp", NEOGEO_BOOTLEG_CT2K3SP_CART) + SLOT_INTERFACE_INTERNAL("r_cthd2003sa", NEOGEO_BOOTLEG_CT2K3SA_CART) + SLOT_INTERFACE_INTERNAL("r_kf10thep", NEOGEO_BOOTLEG_KF10THEP_CART) + SLOT_INTERFACE_INTERNAL("r_kf2k5uni", NEOGEO_BOOTLEG_KF2K5UNI_CART) + SLOT_INTERFACE_INTERNAL("r_kf2k4se", NEOGEO_BOOTLEG_KF2K4SE_CART) + SLOT_INTERFACE_INTERNAL("r_svcplus", NEOGEO_BOOTLEG_SVCPLUS_CART) + SLOT_INTERFACE_INTERNAL("r_svcplusa", NEOGEO_BOOTLEG_SVCPLUSA_CART) + SLOT_INTERFACE_INTERNAL("r_samsho5b", NEOGEO_BOOTLEG_SAMSHO5B_CART) + SLOT_INTERFACE_INTERNAL("r_kof97oro", NEOGEO_BOOTLEG_KOF97ORO_CART) // missing from softlist? + SLOT_INTERFACE_INTERNAL("r_lans2004", NEOGEO_BOOTLEG_LANS2004_CART) + SLOT_INTERFACE_INTERNAL("r_kof10th", NEOGEO_BOOTLEG_KOF10TH_CART) + SLOT_INTERFACE_INTERNAL("r_kog", NEOGEO_BOOTLEG_KOG_CART) + + /* mixed original and bootleg logic */ + SLOT_INTERFACE_INTERNAL("r_mslug3b6", NEOGEO_BOOTLEG_HYBRID_MSLUG3B6_CART) + SLOT_INTERFACE_INTERNAL("r_kof2002b", NEOGEO_BOOTLEG_HYBRID_KOF2002B_CART) + SLOT_INTERFACE_INTERNAL("r_kf2k2mp", NEOGEO_BOOTLEG_HYBRID_KF2K2MP_CART) + SLOT_INTERFACE_INTERNAL("r_kf2k2mp2", NEOGEO_BOOTLEG_HYBRID_KF2K2MP2_CART) + + SLOT_INTERFACE_INTERNAL("r_matrimbl", NEOGEO_BOOTLEG_HYBRID_MATRIMBL_CART) + SLOT_INTERFACE_INTERNAL("r_ms5plus", NEOGEO_BOOTLEG_HYBRID_MS5PLUS_CART) + SLOT_INTERFACE_INTERNAL("r_svcboot", NEOGEO_BOOTLEG_HYBRID_SVCBOOT_CART) + SLOT_INTERFACE_INTERNAL("r_svcsplus", NEOGEO_BOOTLEG_HYBRID_SVCSPLUS_CART) + + SLOT_INTERFACE_INTERNAL("r_kf2k3bl", NEOGEO_BOOTLEG_HYBRID_KF2K3BL_CART) + SLOT_INTERFACE_INTERNAL("r_kf2k3pl", NEOGEO_BOOTLEG_HYBRID_KF2K3PL_CART) + SLOT_INTERFACE_INTERNAL("r_kf2k3upl", NEOGEO_BOOTLEG_HYBRID_KF2K3UPL_CART) + + + + + + + +SLOT_INTERFACE_END diff --git a/src/devices/bus/neogeo/neogeo_carts.h b/src/devices/bus/neogeo/neogeo_carts.h new file mode 100644 index 00000000000..f6925b96e98 --- /dev/null +++ b/src/devices/bus/neogeo/neogeo_carts.h @@ -0,0 +1,30 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/********************************************************************** + +**********************************************************************/ + +#pragma once + +#ifndef __NEOGEO_CARTS_H__ +#define __NEOGEO_CARTS_H__ + +#include "emu.h" + +#include "rom.h" +#include "banked_cart.h" +#include "mslugx_cart.h" +#include "sma_cart.h" +#include "cmc_cart.h" +#include "pcm2_cart.h" +#include "kof2002_cart.h" +#include "pvc_cart.h" +#include "fatfury2_cart.h" +#include "kof98_cart.h" +#include "bootleg_cart.h" +#include "bootleg_hybrid_cart.h" + +// supported devices +SLOT_INTERFACE_EXTERN(neogeo_cart); + +#endif // __NEOGEO_CARTS_H__ diff --git a/src/devices/bus/neogeo/neogeo_helper.c b/src/devices/bus/neogeo/neogeo_helper.c new file mode 100644 index 00000000000..fdbd9ba7203 --- /dev/null +++ b/src/devices/bus/neogeo/neogeo_helper.c @@ -0,0 +1,66 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + +#include "emu.h" +#include "neogeo_helper.h" + +static UINT32 get_region_mask(UINT8* rgn, UINT32 rgn_size) +{ + UINT32 mask; + UINT32 len; + UINT32 bit; + + mask = 0xffffffff; + + len = rgn_size; + + for (bit = 0x80000000; bit != 0; bit >>= 1) + { + if ((len * 2 - 1) & bit) + break; + + mask >>= 1; + } + + return mask; +} + +UINT32 neogeohelper_optimize_sprite_data(std::vector<UINT8> &spritegfx, UINT8* region_sprites, UINT32 region_sprites_size) +{ + /* convert the sprite graphics data into a format that + allows faster blitting */ + UINT8 *src; + UINT8 *dest; + + UINT32 mask = get_region_mask(region_sprites, region_sprites_size); + + spritegfx.resize(mask + 1); + UINT32 spritegfx_address_mask = mask; + + src = region_sprites; + dest = &spritegfx[0]; + + for (unsigned i = 0; i < region_sprites_size; i += 0x80, src += 0x80) + { + for (unsigned y = 0; y < 0x10; y++) + { + for (unsigned x = 0; x < 8; x++) + { + *(dest++) = (((src[0x43 | (y << 2)] >> x) & 0x01) << 3) | + (((src[0x41 | (y << 2)] >> x) & 0x01) << 2) | + (((src[0x42 | (y << 2)] >> x) & 0x01) << 1) | + (((src[0x40 | (y << 2)] >> x) & 0x01) << 0); + } + + for (unsigned x = 0; x < 8; x++) + { + *(dest++) = (((src[0x03 | (y << 2)] >> x) & 0x01) << 3) | + (((src[0x01 | (y << 2)] >> x) & 0x01) << 2) | + (((src[0x02 | (y << 2)] >> x) & 0x01) << 1) | + (((src[0x00 | (y << 2)] >> x) & 0x01) << 0); + } + } + } + + return spritegfx_address_mask; +} diff --git a/src/devices/bus/neogeo/neogeo_helper.h b/src/devices/bus/neogeo/neogeo_helper.h new file mode 100644 index 00000000000..3d125f7fd62 --- /dev/null +++ b/src/devices/bus/neogeo/neogeo_helper.h @@ -0,0 +1,4 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + +extern UINT32 neogeohelper_optimize_sprite_data(std::vector<UINT8> &spritegfx, UINT8* region_sprites, UINT32 region_sprites_size); diff --git a/src/devices/bus/neogeo/neogeo_intf.c b/src/devices/bus/neogeo/neogeo_intf.c new file mode 100644 index 00000000000..92f7ba5be19 --- /dev/null +++ b/src/devices/bus/neogeo/neogeo_intf.c @@ -0,0 +1,33 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + +#include "emu.h" +#include "neogeo_intf.h" + +//------------------------------------------------- +// device_neogeo_cart_interface - constructor +//------------------------------------------------- + +device_neogeo_cart_interface::device_neogeo_cart_interface(const machine_config &mconfig, device_t &device) + : device_slot_card_interface(mconfig, device) + /* + m_rom(NULL), + m_fixed(NULL), + m_sprites(NULL), + m_sprites_optimized(NULL), + m_audio(NULL), + m_ym(NULL), + m_ymdelta(NULL), + m_audiocrypt(NULL) + */ +{ +} + + +//------------------------------------------------- +// ~device_neogeo_cart_interface - destructor +//------------------------------------------------- + +device_neogeo_cart_interface::~device_neogeo_cart_interface() +{ +} diff --git a/src/devices/bus/neogeo/neogeo_intf.h b/src/devices/bus/neogeo/neogeo_intf.h new file mode 100644 index 00000000000..5c6947ff52d --- /dev/null +++ b/src/devices/bus/neogeo/neogeo_intf.h @@ -0,0 +1,78 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + +#ifndef __NEOGEO_INTF_H +#define __NEOGEO_INTF_H + +// ======================> device_neogeo_cart_interface + +#define DECRYPT_ALL_PARAMS \ + UINT8* cpuregion, UINT32 cpuregion_size,UINT8* spr_region, UINT32 spr_region_size,UINT8* fix_region, UINT32 fix_region_size,UINT8* ym_region, UINT32 ym_region_size,UINT8* ymdelta_region, UINT32 ymdelta_region_size,UINT8* audiocpu_region, UINT32 audio_region_size, UINT8* audiocrypt_region, UINT32 audiocrypt_region_size + +#define ACTIVATE_CART_PARAMS \ + running_machine& machine, cpu_device* maincpu, UINT8* cpuregion, UINT32 cpuregion_size, UINT8* fixedregion, UINT32 fixedregion_size + +class device_neogeo_cart_interface : public device_slot_card_interface +{ +public: + // construction/destruction + device_neogeo_cart_interface(const machine_config &mconfig, device_t &device); + virtual ~device_neogeo_cart_interface(); + + // reading from ROM + virtual DECLARE_READ16_MEMBER(read_rom) { return 0xffff; } + virtual void activate_cart(ACTIVATE_CART_PARAMS) { }; + virtual void decrypt_all(DECRYPT_ALL_PARAMS) { }; + virtual int get_fixed_bank_type(void) { return 0; } + + void rom_alloc(UINT32 size) { m_rom.resize(size/sizeof(UINT16)); } + UINT16* get_rom_base() { return &m_rom[0]; } + UINT32 get_rom_size() { return m_rom.size()*sizeof(UINT16); } + + void fixed_alloc(UINT32 size) { m_fixed.resize(size); } + UINT8* get_fixed_base() { return &m_fixed[0]; } + UINT32 get_fixed_size() { return m_fixed.size(); } + + void audio_alloc(UINT32 size) { m_audio.resize(size); } + UINT8* get_audio_base() { return &m_audio[0]; } + UINT32 get_audio_size() { return m_audio.size(); } + + void audiocrypt_alloc(UINT32 size) { m_audiocrypt.resize(size); } + UINT8* get_audiocrypt_base() { return &m_audiocrypt[0]; } + UINT32 get_audiocrypt_size() { return m_audiocrypt.size(); } + + void sprites_alloc(UINT32 size) { m_sprites.resize(size); } + UINT8* get_sprites_base() { return &m_sprites[0]; } + UINT32 get_sprites_size() { return m_sprites.size(); } + UINT8* get_sprites_optimized() { return &m_sprites_optimized[0]; } + UINT32 get_sprites_addrmask() { return m_sprite_gfx_address_mask; } + std::vector<UINT8>& get_sprites_optimized_arr() { return m_sprites_optimized; } + + void ym_alloc(UINT32 size) { m_ym.resize(size); } + UINT8* get_ym_base() { return &m_ym[0]; } + UINT32 get_ym_size() { return m_ym.size(); } + + void ymdelta_alloc(UINT32 size) { m_ymdelta.resize(size); } + UINT8* get_ymdelta_base() { return &m_ymdelta[0]; } + UINT32 get_ymdelta_size() { return m_ymdelta.size(); } + + std::vector<UINT16> m_rom; + std::vector<UINT8> m_fixed; + std::vector<UINT8> m_sprites; + std::vector<UINT8> m_sprites_optimized; + std::vector<UINT8> m_audio; + std::vector<UINT8> m_ym; + std::vector<UINT8> m_ymdelta; + + UINT32 m_sprite_gfx_address_mask; + + + +protected: + // internal state + std::vector<UINT8> m_audiocrypt; + + +}; + +#endif diff --git a/src/devices/bus/neogeo/neogeo_slot.c b/src/devices/bus/neogeo/neogeo_slot.c new file mode 100644 index 00000000000..0c8fa80887e --- /dev/null +++ b/src/devices/bus/neogeo/neogeo_slot.c @@ -0,0 +1,222 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/*********************************************************************************************************** + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "neogeo_slot.h" + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +const device_type NEOGEO_CART_SLOT = &device_creator<neogeo_cart_slot_device>; + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// neogeo_cart_slot_device - constructor +//------------------------------------------------- +neogeo_cart_slot_device::neogeo_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock) : + device_t(mconfig, NEOGEO_CART_SLOT, "NeoGeo Cartridge Slot", tag, owner, clock, "neogeo_cart_slot", __FILE__), + device_image_interface(mconfig, *this), + device_slot_interface(mconfig, *this), + m_cart(0) +{ +} + + +//------------------------------------------------- +// neogeo_cart_slot_device - destructor +//------------------------------------------------- + +neogeo_cart_slot_device::~neogeo_cart_slot_device() +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void neogeo_cart_slot_device::device_start() +{ + m_cart = dynamic_cast<device_neogeo_cart_interface *>(get_card_device()); +} + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void neogeo_cart_slot_device::device_config_complete() +{ + // set brief and instance name + update_names(); +} + + + +/*------------------------------------------------- + call load + -------------------------------------------------*/ + + +bool neogeo_cart_slot_device::call_load() +{ + if (m_cart) + { + UINT16 *ROM; + UINT8* ROM8; + UINT32 len; + + if (software_entry() != NULL) + { + // create memory regions + len = get_software_region_length("maincpu"); + m_cart->rom_alloc(len); ROM = m_cart->get_rom_base(); + memcpy(ROM, get_software_region("maincpu"), len); + + len = get_software_region_length("fixed"); + m_cart->fixed_alloc(len); ROM8 = m_cart->get_fixed_base(); + memcpy(ROM8, get_software_region("fixed"), len); + + if (get_software_region("audiocpu") != NULL) + { + len = get_software_region_length("audiocpu"); + m_cart->audio_alloc(len + 0x10000); ROM8 = m_cart->get_audio_base(); + memcpy(ROM8, get_software_region("audiocpu"), len); + memcpy(ROM8 + 0x10000, get_software_region("audiocpu"), len); // avoid reloading in XML, should just improve banking instead tho? + } + + len = get_software_region_length("ymsnd"); + m_cart->ym_alloc(len); ROM8 = m_cart->get_ym_base(); + memcpy(ROM8, get_software_region("ymsnd"), len); + + if (get_software_region("ymsnd.deltat") != NULL) + { + len = get_software_region_length("ymsnd.deltat"); + m_cart->ymdelta_alloc(len); ROM8 = m_cart->get_ymdelta_base(); + memcpy(ROM8, get_software_region("ymsnd.deltat"), len); + } + else + { + // ensure there is no delta-t region + } + + + len = get_software_region_length("sprites"); + m_cart->sprites_alloc(len); ROM8 = m_cart->get_sprites_base(); + memcpy(ROM8, get_software_region("sprites"), len); + + if (get_software_region("audiocrypt") != NULL) // encrypted Z80 code + { + len = get_software_region_length("audiocrypt"); + m_cart->audiocrypt_alloc(len); ROM8 = m_cart->get_audiocrypt_base(); + memcpy(ROM8, get_software_region("audiocrypt"), len); + // allocate the audiocpu region to decrypt data into + m_cart->audio_alloc(len + 0x10000); + } + + m_cart->decrypt_all( + (UINT8*)m_cart->get_rom_base(), m_cart->get_rom_size(), + m_cart->get_sprites_base(), m_cart->get_sprites_size(), + m_cart->get_fixed_base(), m_cart->get_fixed_size(), + m_cart->get_ym_base(), m_cart->get_ym_size(), + m_cart->get_ymdelta_base(), m_cart->get_ymdelta_size(), + m_cart->get_audio_base(), m_cart->get_audio_size(), + m_cart->get_audiocrypt_base(), m_cart->get_audiocrypt_size()); + + + // create optimized sprite cache + m_cart->m_sprite_gfx_address_mask = neogeohelper_optimize_sprite_data(m_cart->get_sprites_optimized_arr(), m_cart->get_sprites_base(), m_cart->get_sprites_size()); + + + return IMAGE_INIT_PASS; + } + } + + return IMAGE_INIT_PASS; +} + +void neogeo_cart_slot_device::setup_memory_banks(running_machine &machine) +{ + UINT16* base16 = get_rom_base(); + UINT32 size = get_rom_size(); + machine.memory().region_free(":maincpu"); + machine.memory().region_alloc(":maincpu",size,2, ENDIANNESS_BIG); + memcpy(memregion(":maincpu")->base(),(UINT8*)base16,size); + + UINT8* base = get_audio_base(); + size = get_audio_size(); + machine.memory().region_free(":audiocpu"); + machine.memory().region_alloc(":audiocpu",size,1, ENDIANNESS_LITTLE); + memcpy(memregion(":audiocpu")->base(),base,size); + + + base = get_ym_base(); + size = get_ym_size(); + + machine.memory().region_free(":ymsnd"); + machine.memory().region_alloc(":ymsnd",size,1, ENDIANNESS_LITTLE); + memcpy(memregion(":ymsnd")->base(),base,size); + + + base = get_ymdelta_base(); + size = get_ymdelta_size(); + machine.memory().region_free(":ymsnd.deltat"); + + if(base) + { + machine.memory().region_alloc(":ymsnd.deltat",size,1, ENDIANNESS_LITTLE); + memcpy(memregion(":ymsnd.deltat")->base(),base,size); + } + + +} + +/*------------------------------------------------- + call_unload + -------------------------------------------------*/ + +void neogeo_cart_slot_device::call_unload() +{ +} + +/*------------------------------------------------- + call softlist load + -------------------------------------------------*/ + +bool neogeo_cart_slot_device::call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry) +{ + load_software_part_region(*this, swlist, swname, start_entry ); + return TRUE; +} + + +/*------------------------------------------------- + get default card software + -------------------------------------------------*/ + +void neogeo_cart_slot_device::get_default_card_software(std::string &result) +{ + software_get_default_slot(result, "rom"); +} + +/*------------------------------------------------- + read + -------------------------------------------------*/ + +READ16_MEMBER(neogeo_cart_slot_device::read_rom) +{ + if (m_cart) + return m_cart->read_rom(space, offset, mem_mask); + else + return 0xffff; +} diff --git a/src/devices/bus/neogeo/neogeo_slot.h b/src/devices/bus/neogeo/neogeo_slot.h new file mode 100644 index 00000000000..3020a7045a9 --- /dev/null +++ b/src/devices/bus/neogeo/neogeo_slot.h @@ -0,0 +1,87 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#ifndef __NEOGEO_SLOT_H +#define __NEOGEO_SLOT_H + +#include "neogeo_intf.h" +#include "neogeo_helper.h" + +/*************************************************************************** + TYPE DEFINITIONS + ***************************************************************************/ + +// ======================> neogeo_cart_slot_device + +class neogeo_cart_slot_device : public device_t, + public device_image_interface, + public device_slot_interface +{ +public: + // construction/destruction + neogeo_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock); + virtual ~neogeo_cart_slot_device(); + + // device-level overrides + virtual void device_start(); + virtual void device_config_complete(); + + // image-level overrides + virtual bool call_load(); + virtual void call_unload(); + virtual bool call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry); + + virtual iodevice_t image_type() const { return IO_CARTSLOT; } + virtual bool is_readable() const { return 1; } + virtual bool is_writeable() const { return 0; } + virtual bool is_creatable() const { return 0; } + virtual bool must_be_loaded() const { return 0; } + virtual bool is_reset_on_load() const { return 1; } + virtual const option_guide *create_option_guide() const { return NULL; } + virtual const char *image_interface() const { return "neo_cart"; } + virtual const char *file_extensions() const { return "bin"; } + + // slot interface overrides + virtual void get_default_card_software(std::string &result); + + // reading and writing + virtual DECLARE_READ16_MEMBER(read_rom); + + UINT16* get_rom_base() { if (m_cart) { return m_cart->get_rom_base(); } else { return 0; } } + UINT32 get_rom_size() { if (m_cart) { return m_cart->get_rom_size(); } else { return 0; } } + UINT8* get_fixed_base() { if (m_cart) { return m_cart->get_fixed_base(); } else { return 0; } } + UINT32 get_fixed_size() { if (m_cart) { return m_cart->get_fixed_size(); } else { return 0; } } + UINT8* get_sprites_base() { if (m_cart) { return m_cart->get_sprites_base(); } else { return 0; } } + UINT32 get_sprites_size() { if (m_cart) { return m_cart->get_sprites_size(); } else { return 0; } } + UINT8* get_sprites_optimized() { if (m_cart) { return m_cart->get_sprites_optimized(); } else { return 0; } } + UINT32 get_sprites_addrmask() { if (m_cart) { return m_cart->get_sprites_addrmask(); } else { return 0; } } + UINT8* get_audio_base() { if (m_cart) { return m_cart->get_audio_base(); } else { return 0; } } + UINT32 get_audio_size() { if (m_cart) { return m_cart->get_audio_size(); } else { return 0; } } + UINT8* get_ym_base() { if (m_cart) { return m_cart->get_ym_base(); } else { return 0; } } + UINT32 get_ym_size() { if (m_cart) { return m_cart->get_ym_size(); } else { return 0; } } + UINT8* get_ymdelta_base() { if (m_cart) { return m_cart->get_ymdelta_base(); } else { return 0; } } + UINT32 get_ymdelta_size() { if (m_cart) { return m_cart->get_ymdelta_size(); } else { return 0; } } + int get_fixed_bank_type(void) { if (m_cart) { return m_cart->get_fixed_bank_type(); } else { return 0; } } + + void activate_cart(ACTIVATE_CART_PARAMS) { if (m_cart) m_cart->activate_cart(machine, maincpu, cpuregion, cpuregion_size, fixedregion, fixedregion_size); } + void setup_memory_banks(running_machine &machine); + + +private: + device_neogeo_cart_interface* m_cart; +}; + + +// device type definition +extern const device_type NEOGEO_CART_SLOT; + + +/*************************************************************************** + DEVICE CONFIGURATION MACROS + ***************************************************************************/ + +#define MCFG_NEOGEO_CARTRIDGE_ADD(_tag,_slot_intf,_def_slot) \ + MCFG_DEVICE_ADD(_tag, NEOGEO_CART_SLOT, 0) \ + MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) + + +#endif diff --git a/src/devices/bus/neogeo/pcm2_cart.c b/src/devices/bus/neogeo/pcm2_cart.c new file mode 100644 index 00000000000..04eede0ebe9 --- /dev/null +++ b/src/devices/bus/neogeo/pcm2_cart.c @@ -0,0 +1,135 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/*********************************************************************************************************** + + NEOGEO ROM cart emulation + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "pcm2_cart.h" + + +//------------------------------------------------- +// neogeo_pcm2_cart - constructor +//------------------------------------------------- + +const device_type NEOGEO_PCM2_CART = &device_creator<neogeo_pcm2_cart>; + + +neogeo_pcm2_cart::neogeo_pcm2_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_cmc_prot(*this, "cmc_prot"), + m_pcm2_prot(*this, "pcm2_prot") +{ +} + +neogeo_pcm2_cart::neogeo_pcm2_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock) + : device_t(mconfig, NEOGEO_PCM2_CART, "NEOGEO PCM2 Cart", tag, owner, clock, "neogeo_rom", __FILE__), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_cmc_prot(*this, "cmc_prot"), + m_pcm2_prot(*this, "pcm2_prot") +{ +} + + +//------------------------------------------------- +// mapper specific start/reset +//------------------------------------------------- + +void neogeo_pcm2_cart::device_start() +{ +} + +void neogeo_pcm2_cart::device_reset() +{ +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +READ16_MEMBER(neogeo_pcm2_cart::read_rom) +{ + return m_rom[offset]; +} + +static MACHINE_CONFIG_FRAGMENT( pcm2_cart ) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") + MCFG_CMC_PROT_ADD("cmc_prot") + MCFG_PCM2_PROT_ADD("pcm2_prot") +MACHINE_CONFIG_END + +machine_config_constructor neogeo_pcm2_cart::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( pcm2_cart ); +} + + + +/* Individual cartridge types (mirror DRIVER_INIT functionality) */ + +/************************************************* + MSLUG4 +**************************************************/ + +const device_type NEOGEO_PCM2_MSLUG4_CART = &device_creator<neogeo_pcm2_mslug4_cart>; + +neogeo_pcm2_mslug4_cart::neogeo_pcm2_mslug4_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_pcm2_cart(mconfig, NEOGEO_PCM2_MSLUG4_CART, "NEOGEO PCM2 mslug4 Cart", tag, owner, clock, "p2_mslug4_cart", __FILE__) {} + +void neogeo_pcm2_mslug4_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, MSLUG4_GFX_KEY); + m_pcm2_prot->neo_pcm2_snk_1999(ym_region, ym_region_size, 8); + +} + + +const device_type NEOGEO_PCM2_MS4PLUS_CART = &device_creator<neogeo_pcm2_ms4plus_cart>; + +neogeo_pcm2_ms4plus_cart::neogeo_pcm2_ms4plus_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_pcm2_cart(mconfig, NEOGEO_PCM2_MS4PLUS_CART, "NEOGEO PCM2 ms4plus Cart", tag, owner, clock, "p2_ms4plus_cart", __FILE__) {} + +void neogeo_pcm2_ms4plus_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->cmc50_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, MSLUG4_GFX_KEY); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region,audio_region_size); + m_pcm2_prot->neo_pcm2_snk_1999(ym_region, ym_region_size, 8); +} + + +/************************************************* + ROTD +**************************************************/ + +const device_type NEOGEO_PCM2_ROTD_CART = &device_creator<neogeo_pcm2_rotd_cart>; + +neogeo_pcm2_rotd_cart::neogeo_pcm2_rotd_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_pcm2_cart(mconfig, NEOGEO_PCM2_ROTD_CART, "NEOGEO PCM2 rotd Cart", tag, owner, clock, "p2_rotd_cart", __FILE__) {} + +void neogeo_pcm2_rotd_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, ROTD_GFX_KEY); + m_pcm2_prot->neo_pcm2_snk_1999(ym_region, ym_region_size, 16); + +} + +/************************************************* + PNYAA +**************************************************/ + +const device_type NEOGEO_PCM2_PNYAA_CART = &device_creator<neogeo_pcm2_pnyaa_cart>; + +neogeo_pcm2_pnyaa_cart::neogeo_pcm2_pnyaa_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_pcm2_cart(mconfig, NEOGEO_PCM2_PNYAA_CART, "NEOGEO PCM2 pnyaa Cart", tag, owner, clock, "p2_pnyaa_cart", __FILE__) {} + +void neogeo_pcm2_pnyaa_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, PNYAA_GFX_KEY); + m_pcm2_prot->neo_pcm2_snk_1999(ym_region, ym_region_size, 4); +} diff --git a/src/devices/bus/neogeo/pcm2_cart.h b/src/devices/bus/neogeo/pcm2_cart.h new file mode 100644 index 00000000000..5cbb31656fc --- /dev/null +++ b/src/devices/bus/neogeo/pcm2_cart.h @@ -0,0 +1,98 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#ifndef __NEOGEO_PCM2_CART_H +#define __NEOGEO_PCM2_CART_H + +#include "neogeo_slot.h" +#include "banked_cart.h" +#include "pcm2_prot.h" +#include "cmc_prot.h" + +// ======================> neogeo_pcm2_cart + +class neogeo_pcm2_cart : public device_t, + public device_neogeo_cart_interface +{ +public: + // construction/destruction + neogeo_pcm2_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source); + neogeo_pcm2_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ16_MEMBER(read_rom); + + virtual void activate_cart(ACTIVATE_CART_PARAMS) { m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); } + virtual void decrypt_all(DECRYPT_ALL_PARAMS) {} + virtual int get_fixed_bank_type(void) { return 0; } + + required_device<neogeo_banked_cart_device> m_banked_cart; + required_device<cmc_prot_device> m_cmc_prot; + required_device<pcm2_prot_device> m_pcm2_prot; +}; + + + +// device type definition +extern const device_type NEOGEO_PCM2_CART; + + +/************************************************* + MSLUG4 +**************************************************/ + +class neogeo_pcm2_mslug4_cart : public neogeo_pcm2_cart +{ +public: + neogeo_pcm2_mslug4_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_PCM2_MSLUG4_CART; + +class neogeo_pcm2_ms4plus_cart : public neogeo_pcm2_cart +{ +public: + neogeo_pcm2_ms4plus_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 0; } +}; +extern const device_type NEOGEO_PCM2_MS4PLUS_CART; + + + +/************************************************* + ROTD +**************************************************/ + +class neogeo_pcm2_rotd_cart : public neogeo_pcm2_cart +{ +public: + neogeo_pcm2_rotd_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_PCM2_ROTD_CART; + + +/************************************************* + PNYAA +**************************************************/ + +class neogeo_pcm2_pnyaa_cart : public neogeo_pcm2_cart +{ +public: + neogeo_pcm2_pnyaa_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_PCM2_PNYAA_CART; + + + + +#endif diff --git a/src/devices/bus/neogeo/pcm2_prot.c b/src/devices/bus/neogeo/pcm2_prot.c new file mode 100644 index 00000000000..6ee156712e9 --- /dev/null +++ b/src/devices/bus/neogeo/pcm2_prot.c @@ -0,0 +1,88 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#include "emu.h" +#include "pcm2_prot.h" + + + +extern const device_type PCM2_PROT = &device_creator<pcm2_prot_device>; + + +pcm2_prot_device::pcm2_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, PCM2_PROT, "NeoGeo Protection (NEOPCM2)", tag, owner, clock, "pcm2_prot", __FILE__) +{ +} + + +void pcm2_prot_device::device_start() +{ +} + +void pcm2_prot_device::device_reset() +{ +} + +/*************************************************************************** + +NeoGeo 'V' (PCM) ROM encryption + NEOPCM2 chip + +***************************************************************************/ + +/* Neo-Pcm2 Drivers for Encrypted V Roms */ +void pcm2_prot_device::neo_pcm2_snk_1999(UINT8* ymrom, UINT32 ymsize, int value) +{ /* thanks to Elsemi for the NEO-PCM2 info */ + UINT16 *rom = (UINT16 *)ymrom; + int size = ymsize; + int i, j; + + if( rom != NULL ) + { /* swap address lines on the whole ROMs */ + std::vector<UINT16> buffer(value / 2); + + for( i = 0; i < size / 2; i += ( value / 2 ) ) + { + memcpy( &buffer[0], &rom[ i ], value ); + for( j = 0; j < (value / 2); j++ ) + { + rom[ i + j ] = buffer[ j ^ (value/4) ]; + } + } + } +} + + +/* the later PCM2 games have additional scrambling */ +void pcm2_prot_device::neo_pcm2_swap(UINT8* ymrom, UINT32 ymsize, int value) +{ + static const UINT32 addrs[7][2]={ + {0x000000,0xa5000}, + {0xffce20,0x01000}, + {0xfe2cf6,0x4e001}, + {0xffac28,0xc2000}, + {0xfeb2c0,0x0a000}, + {0xff14ea,0xa7001}, + {0xffb440,0x02000}}; + static const UINT8 xordata[7][8]={ + {0xf9,0xe0,0x5d,0xf3,0xea,0x92,0xbe,0xef}, + {0xc4,0x83,0xa8,0x5f,0x21,0x27,0x64,0xaf}, + {0xc3,0xfd,0x81,0xac,0x6d,0xe7,0xbf,0x9e}, + {0xc3,0xfd,0x81,0xac,0x6d,0xe7,0xbf,0x9e}, + {0xcb,0x29,0x7d,0x43,0xd2,0x3a,0xc2,0xb4}, + {0x4b,0xa4,0x63,0x46,0xf0,0x91,0xea,0x62}, + {0x4b,0xa4,0x63,0x46,0xf0,0x91,0xea,0x62}}; + + dynamic_buffer buf(0x1000000); + int i, j, d; + UINT8* src = ymrom; + memcpy(&buf[0],src,0x1000000); + for (i=0;i<0x1000000;i++) + { + j=BITSWAP24(i,23,22,21,20,19,18,17,0,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,16); + j=j^addrs[value][1]; + d=((i+addrs[value][0])&0xffffff); + src[j]=buf[d]^xordata[value][j&0x7]; + } +} diff --git a/src/devices/bus/neogeo/pcm2_prot.h b/src/devices/bus/neogeo/pcm2_prot.h new file mode 100644 index 00000000000..7920b745970 --- /dev/null +++ b/src/devices/bus/neogeo/pcm2_prot.h @@ -0,0 +1,36 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#pragma once + +#ifndef __PCM2_PROT__ +#define __PCM2_PROT__ + +extern const device_type PCM2_PROT; + +#define MCFG_PCM2_PROT_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, PCM2_PROT, 0) + + +class pcm2_prot_device : public device_t +{ +public: + // construction/destruction + pcm2_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + void neo_pcm2_snk_1999(UINT8* ymrom, UINT32 ymsize, int value); + void neo_pcm2_swap(UINT8* ymrom, UINT32 ymsize, int value); + +protected: + virtual void device_start(); + virtual void device_reset(); + + + +private: + + +}; + +#endif diff --git a/src/devices/bus/neogeo/pvc_cart.c b/src/devices/bus/neogeo/pvc_cart.c new file mode 100644 index 00000000000..ee587724b7f --- /dev/null +++ b/src/devices/bus/neogeo/pvc_cart.c @@ -0,0 +1,139 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/*********************************************************************************************************** + + NEOGEO ROM cart emulation + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "pvc_cart.h" + + +//------------------------------------------------- +// neogeo_pvc_cart - constructor +//------------------------------------------------- + +const device_type NEOGEO_PVC_CART = &device_creator<neogeo_pvc_cart>; + + +neogeo_pvc_cart::neogeo_pvc_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_cmc_prot(*this, "cmc_prot"), + m_pcm2_prot(*this, "pcm2_prot"), + m_pvc_prot(*this, "pvc_prot") +{ +} + +neogeo_pvc_cart::neogeo_pvc_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock) + : device_t(mconfig, NEOGEO_PVC_CART, "NEOGEO PCM2 Cart", tag, owner, clock, "neogeo_rom", __FILE__), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_cmc_prot(*this, "cmc_prot"), + m_pcm2_prot(*this, "pcm2_prot"), + m_pvc_prot(*this, "pvc_prot") +{ +} + + +//------------------------------------------------- +// mapper specific start/reset +//------------------------------------------------- + +void neogeo_pvc_cart::device_start() +{ +} + +void neogeo_pvc_cart::device_reset() +{ +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +READ16_MEMBER(neogeo_pvc_cart::read_rom) +{ + return m_rom[offset]; +} + +static MACHINE_CONFIG_FRAGMENT( pvc_cart ) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") + MCFG_CMC_PROT_ADD("cmc_prot") + MCFG_PCM2_PROT_ADD("pcm2_prot") + MCFG_PVC_PROT_ADD("pvc_prot") +MACHINE_CONFIG_END + +machine_config_constructor neogeo_pvc_cart::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( pvc_cart ); +} + + + +/* Individual cartridge types (mirror DRIVER_INIT functionality) */ + +/************************************************* + MSLUG5 +**************************************************/ + +const device_type NEOGEO_PVC_MSLUG5_CART = &device_creator<neogeo_pvc_mslug5_cart>; + +neogeo_pvc_mslug5_cart::neogeo_pvc_mslug5_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_pvc_cart(mconfig, NEOGEO_PVC_MSLUG5_CART, "NEOGEO PCM2 mslug5 Cart", tag, owner, clock, "p2_mslug5_cart", __FILE__) {} + +void neogeo_pvc_mslug5_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_pvc_prot->mslug5_decrypt_68k(cpuregion, cpuregion_size); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 2); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, MSLUG5_GFX_KEY); +} + +/************************************************* + SVC +**************************************************/ + +const device_type NEOGEO_PVC_SVC_CART = &device_creator<neogeo_pvc_svc_cart>; + +neogeo_pvc_svc_cart::neogeo_pvc_svc_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_pvc_cart(mconfig, NEOGEO_PVC_SVC_CART, "NEOGEO PCM2 svc Cart", tag, owner, clock, "p2_svc_cart", __FILE__) {} + +void neogeo_pvc_svc_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_pvc_prot->svc_px_decrypt(cpuregion, cpuregion_size); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 3); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, SVC_GFX_KEY); +} + + +/************************************************* + KOF2003 +**************************************************/ + +const device_type NEOGEO_PVC_KOF2003_CART = &device_creator<neogeo_pvc_kof2003_cart>; + +neogeo_pvc_kof2003_cart::neogeo_pvc_kof2003_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_pvc_cart(mconfig, NEOGEO_PVC_KOF2003_CART, "NEOGEO PCM2 kof2003 Cart", tag, owner, clock, "p2_kof2003_cart", __FILE__) {} + +void neogeo_pvc_kof2003_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_pvc_prot->kof2003_decrypt_68k(cpuregion, cpuregion_size); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 5); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF2003_GFX_KEY); +} + +const device_type NEOGEO_PVC_KOF2003H_CART = &device_creator<neogeo_pvc_kof2003h_cart>; + +neogeo_pvc_kof2003h_cart::neogeo_pvc_kof2003h_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_pvc_cart(mconfig, NEOGEO_PVC_KOF2003H_CART, "NEOGEO PCM2 kof2003h Cart", tag, owner, clock, "p2_kof2003h_cart", __FILE__) {} + +void neogeo_pvc_kof2003h_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_pvc_prot->kof2003h_decrypt_68k(cpuregion, cpuregion_size); + m_pcm2_prot->neo_pcm2_swap(ym_region, ym_region_size, 5); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF2003_GFX_KEY); +} diff --git a/src/devices/bus/neogeo/pvc_cart.h b/src/devices/bus/neogeo/pvc_cart.h new file mode 100644 index 00000000000..e3e409081c4 --- /dev/null +++ b/src/devices/bus/neogeo/pvc_cart.h @@ -0,0 +1,108 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#ifndef __NEOGEO_PVC_CART_H +#define __NEOGEO_PVC_CART_H + +#include "neogeo_slot.h" +#include "banked_cart.h" +#include "pcm2_prot.h" +#include "cmc_prot.h" +#include "pvc_prot.h" + +// ======================> neogeo_pvc_cart + +class neogeo_pvc_cart : public device_t, + public device_neogeo_cart_interface +{ +public: + // construction/destruction + neogeo_pvc_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source); + neogeo_pvc_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ16_MEMBER(read_rom); + + virtual void activate_cart(ACTIVATE_CART_PARAMS) + { + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_pvc_prot->install_pvc_protection(maincpu,m_banked_cart); + } + + virtual void decrypt_all(DECRYPT_ALL_PARAMS) {} + virtual int get_fixed_bank_type(void) { return 0; } + + required_device<neogeo_banked_cart_device> m_banked_cart; + required_device<cmc_prot_device> m_cmc_prot; + required_device<pcm2_prot_device> m_pcm2_prot; + required_device<pvc_prot_device> m_pvc_prot; + +}; + + + +// device type definition +extern const device_type NEOGEO_PVC_CART; + + +/************************************************* + MSLUG5 +**************************************************/ + +class neogeo_pvc_mslug5_cart : public neogeo_pvc_cart +{ +public: + neogeo_pvc_mslug5_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_PVC_MSLUG5_CART; + +/************************************************* + SVC +**************************************************/ + +class neogeo_pvc_svc_cart : public neogeo_pvc_cart +{ +public: + neogeo_pvc_svc_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 2; } +}; +extern const device_type NEOGEO_PVC_SVC_CART; + + +/************************************************* + KOF2003 +**************************************************/ + +class neogeo_pvc_kof2003_cart : public neogeo_pvc_cart +{ +public: + neogeo_pvc_kof2003_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 2; } +}; +extern const device_type NEOGEO_PVC_KOF2003_CART; + + +/************************************************* + KOF2003H +**************************************************/ + +class neogeo_pvc_kof2003h_cart : public neogeo_pvc_cart +{ +public: + neogeo_pvc_kof2003h_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 2; } +}; +extern const device_type NEOGEO_PVC_KOF2003H_CART; + + + +#endif diff --git a/src/devices/bus/neogeo/pvc_prot.c b/src/devices/bus/neogeo/pvc_prot.c new file mode 100644 index 00000000000..95b8cfeb770 --- /dev/null +++ b/src/devices/bus/neogeo/pvc_prot.c @@ -0,0 +1,316 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#include "emu.h" +#include "pvc_prot.h" + + + +extern const device_type PVC_PROT = &device_creator<pvc_prot_device>; + + +pvc_prot_device::pvc_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, PVC_PROT, "NeoGeo Protection (PVC)", tag, owner, clock, "pvc_prot", __FILE__) +{ +} + + +void pvc_prot_device::device_start() +{ + save_item(NAME(m_cartridge_ram)); +} + +void pvc_prot_device::device_reset() +{ +} + + + + +/************************ PVC Protection *********************** + mslug5, svcchaos, kof2003 +***************************************************************/ + +void pvc_prot_device::pvc_write_unpack_color() +{ + UINT16 pen = m_cartridge_ram[0xff0]; + + UINT8 b = ((pen & 0x000f) << 1) | ((pen & 0x1000) >> 12); + UINT8 g = ((pen & 0x00f0) >> 3) | ((pen & 0x2000) >> 13); + UINT8 r = ((pen & 0x0f00) >> 7) | ((pen & 0x4000) >> 14); + UINT8 s = (pen & 0x8000) >> 15; + + m_cartridge_ram[0xff1] = (g << 8) | b; + m_cartridge_ram[0xff2] = (s << 8) | r; +} + + +void pvc_prot_device::pvc_write_pack_color() +{ + UINT16 gb = m_cartridge_ram[0xff4]; + UINT16 sr = m_cartridge_ram[0xff5]; + + m_cartridge_ram[0xff6] = ((gb & 0x001e) >> 1) | + ((gb & 0x1e00) >> 5) | + ((sr & 0x001e) << 7) | + ((gb & 0x0001) << 12) | + ((gb & 0x0100) << 5) | + ((sr & 0x0001) << 14) | + ((sr & 0x0100) << 7); +} + + +void pvc_prot_device::pvc_write_bankswitch( address_space &space ) +{ + UINT32 bankaddress; + + bankaddress = ((m_cartridge_ram[0xff8] >> 8)|(m_cartridge_ram[0xff9] << 8)); + m_cartridge_ram[0xff8] = (m_cartridge_ram[0xff8] & 0xfe00) | 0x00a0; + m_cartridge_ram[0xff9] &= 0x7fff; + m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress + 0x100000); +} + + +READ16_MEMBER( pvc_prot_device::pvc_prot_r ) +{ + return m_cartridge_ram[offset]; +} + + +WRITE16_MEMBER( pvc_prot_device::pvc_prot_w ) +{ + COMBINE_DATA(&m_cartridge_ram[offset] ); + if (offset == 0xff0) + pvc_write_unpack_color(); + else if(offset >= 0xff4 && offset <= 0xff5) + pvc_write_pack_color(); + else if(offset >= 0xff8) + pvc_write_bankswitch(space); +} + + +void pvc_prot_device::install_pvc_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev) +{ + m_bankdev = bankdev; + maincpu->space(AS_PROGRAM).install_readwrite_handler(0x2fe000, 0x2fffff, read16_delegate(FUNC(pvc_prot_device::pvc_prot_r),this), write16_delegate(FUNC(pvc_prot_device::pvc_prot_w),this)); +} + + + + +/* kf2k3pcb, kof2003, kof2003h, mslug5 and svc have updated P rom scramble */ +void pvc_prot_device::mslug5_decrypt_68k(UINT8* rom, UINT32 size) +{ + static const UINT8 xor1[ 0x20 ] = { 0xc2, 0x4b, 0x74, 0xfd, 0x0b, 0x34, 0xeb, 0xd7, 0x10, 0x6d, 0xf9, 0xce, 0x5d, 0xd5, 0x61, 0x29, 0xf5, 0xbe, 0x0d, 0x82, 0x72, 0x45, 0x0f, 0x24, 0xb3, 0x34, 0x1b, 0x99, 0xea, 0x09, 0xf3, 0x03 }; + static const UINT8 xor2[ 0x20 ] = { 0x36, 0x09, 0xb0, 0x64, 0x95, 0x0f, 0x90, 0x42, 0x6e, 0x0f, 0x30, 0xf6, 0xe5, 0x08, 0x30, 0x64, 0x08, 0x04, 0x00, 0x2f, 0x72, 0x09, 0xa0, 0x13, 0xc9, 0x0b, 0xa0, 0x3e, 0xc2, 0x00, 0x40, 0x2b }; + int i; + int ofst; + int rom_size = 0x800000; + dynamic_buffer buf( rom_size ); + + for( i = 0; i < 0x100000; i++ ) + { + rom[ i ] ^= xor1[ (BYTE_XOR_LE(i) % 0x20) ]; + } + for( i = 0x100000; i < 0x800000; i++ ) + { + rom[ i ] ^= xor2[ (BYTE_XOR_LE(i) % 0x20) ]; + } + + for( i = 0x100000; i < 0x0800000; i += 4 ) + { + UINT16 rom16; + rom16 = rom[BYTE_XOR_LE(i+1)] | rom[BYTE_XOR_LE(i+2)]<<8; + rom16 = BITSWAP16( rom16, 15, 14, 13, 12, 10, 11, 8, 9, 6, 7, 4, 5, 3, 2, 1, 0 ); + rom[BYTE_XOR_LE(i+1)] = rom16&0xff; + rom[BYTE_XOR_LE(i+2)] = rom16>>8; + } + memcpy( &buf[0], rom, rom_size ); + for( i = 0; i < 0x0100000 / 0x10000; i++ ) + { + ofst = (i & 0xf0) + BITSWAP8( (i & 0x0f), 7, 6, 5, 4, 1, 0, 3, 2 ); + memcpy( &rom[ i * 0x10000 ], &buf[ ofst * 0x10000 ], 0x10000 ); + } + for( i = 0x100000; i < 0x800000; i += 0x100 ) + { + ofst = (i & 0xf000ff) + ((i & 0x000f00) ^ 0x00700) + (BITSWAP8( ((i & 0x0ff000) >> 12), 5, 4, 7, 6, 1, 0, 3, 2 ) << 12); + memcpy( &rom[ i ], &buf[ ofst ], 0x100 ); + } + memcpy( &buf[0], rom, rom_size ); + memcpy( &rom[ 0x100000 ], &buf[ 0x700000 ], 0x100000 ); + memcpy( &rom[ 0x200000 ], &buf[ 0x100000 ], 0x600000 ); +} + + +void pvc_prot_device::svc_px_decrypt(UINT8* rom, UINT32 size) +{ + static const UINT8 xor1[ 0x20 ] = { 0x3b, 0x6a, 0xf7, 0xb7, 0xe8, 0xa9, 0x20, 0x99, 0x9f, 0x39, 0x34, 0x0c, 0xc3, 0x9a, 0xa5, 0xc8, 0xb8, 0x18, 0xce, 0x56, 0x94, 0x44, 0xe3, 0x7a, 0xf7, 0xdd, 0x42, 0xf0, 0x18, 0x60, 0x92, 0x9f }; + static const UINT8 xor2[ 0x20 ] = { 0x69, 0x0b, 0x60, 0xd6, 0x4f, 0x01, 0x40, 0x1a, 0x9f, 0x0b, 0xf0, 0x75, 0x58, 0x0e, 0x60, 0xb4, 0x14, 0x04, 0x20, 0xe4, 0xb9, 0x0d, 0x10, 0x89, 0xeb, 0x07, 0x30, 0x90, 0x50, 0x0e, 0x20, 0x26 }; + int i; + int ofst; + int rom_size = 0x800000; + dynamic_buffer buf( rom_size ); + + for( i = 0; i < 0x100000; i++ ) + { + rom[ i ] ^= xor1[ (BYTE_XOR_LE(i) % 0x20) ]; + } + for( i = 0x100000; i < 0x800000; i++ ) + { + rom[ i ] ^= xor2[ (BYTE_XOR_LE(i) % 0x20) ]; + } + + for( i = 0x100000; i < 0x0800000; i += 4 ) + { + UINT16 rom16; + rom16 = rom[BYTE_XOR_LE(i+1)] | rom[BYTE_XOR_LE(i+2)]<<8; + rom16 = BITSWAP16( rom16, 15, 14, 13, 12, 10, 11, 8, 9, 6, 7, 4, 5, 3, 2, 1, 0 ); + rom[BYTE_XOR_LE(i+1)] = rom16&0xff; + rom[BYTE_XOR_LE(i+2)] = rom16>>8; + } + memcpy( &buf[0], rom, rom_size ); + for( i = 0; i < 0x0100000 / 0x10000; i++ ) + { + ofst = (i & 0xf0) + BITSWAP8( (i & 0x0f), 7, 6, 5, 4, 2, 3, 0, 1 ); + memcpy( &rom[ i * 0x10000 ], &buf[ ofst * 0x10000 ], 0x10000 ); + } + for( i = 0x100000; i < 0x800000; i += 0x100 ) + { + ofst = (i & 0xf000ff) + ((i & 0x000f00) ^ 0x00a00) + (BITSWAP8( ((i & 0x0ff000) >> 12), 4, 5, 6, 7, 1, 0, 3, 2 ) << 12); + memcpy( &rom[ i ], &buf[ ofst ], 0x100 ); + } + memcpy( &buf[0], rom, rom_size ); + memcpy( &rom[ 0x100000 ], &buf[ 0x700000 ], 0x100000 ); + memcpy( &rom[ 0x200000 ], &buf[ 0x100000 ], 0x600000 ); +} + + +void pvc_prot_device::kf2k3pcb_decrypt_68k(UINT8* rom, UINT32 size) +{ + static const UINT8 xor2[ 0x20 ] = { 0xb4, 0x0f, 0x40, 0x6c, 0x38, 0x07, 0xd0, 0x3f, 0x53, 0x08, 0x80, 0xaa, 0xbe, 0x07, 0xc0, 0xfa, 0xd0, 0x08, 0x10, 0xd2, 0xf1, 0x03, 0x70, 0x7e, 0x87, 0x0b, 0x40, 0xf6, 0x2a, 0x0a, 0xe0, 0xf9 }; + int i; + int ofst; + int rom_size = 0x900000; + dynamic_buffer buf( rom_size ); + + for (i = 0; i < 0x100000; i++) + { + rom[ 0x800000 + i ] ^= rom[ 0x100002 | i ]; + } + for( i = 0x100000; i < 0x800000; i++ ) + { + rom[ i ] ^= xor2[ (BYTE_XOR_LE(i) % 0x20) ]; + } + for( i = 0x100000; i < 0x800000; i += 4 ) + { + UINT16 rom16; + rom16 = rom[BYTE_XOR_LE(i+1)] | rom[BYTE_XOR_LE(i+2)]<<8; + rom16 = BITSWAP16( rom16, 15, 14, 13, 12, 4, 5, 6, 7, 8, 9, 10, 11, 3, 2, 1, 0 ); + rom[BYTE_XOR_LE(i+1)] = rom16&0xff; + rom[BYTE_XOR_LE(i+2)] = rom16>>8; + } + for( i = 0; i < 0x0100000 / 0x10000; i++ ) + { + ofst = (i & 0xf0) + BITSWAP8( (i & 0x0f), 7, 6, 5, 4, 1, 0, 3, 2 ); + memcpy( &buf[ i * 0x10000 ], &rom[ ofst * 0x10000 ], 0x10000 ); + } + for( i = 0x100000; i < 0x900000; i += 0x100 ) + { + ofst = (i & 0xf000ff) + ((i & 0x000f00) ^ 0x00300) + (BITSWAP8( ((i & 0x0ff000) >> 12), 4, 5, 6, 7, 1, 0, 3, 2 ) << 12); + memcpy( &buf[ i ], &rom[ ofst ], 0x100 ); + } + memcpy (&rom[0x000000], &buf[0x000000], 0x100000); + memcpy (&rom[0x100000], &buf[0x800000], 0x100000); + memcpy (&rom[0x200000], &buf[0x100000], 0x700000); +} + + +void pvc_prot_device::kof2003_decrypt_68k(UINT8* rom, UINT32 size) +{ + static const UINT8 xor1[0x20] = { 0x3b, 0x6a, 0xf7, 0xb7, 0xe8, 0xa9, 0x20, 0x99, 0x9f, 0x39, 0x34, 0x0c, 0xc3, 0x9a, 0xa5, 0xc8, 0xb8, 0x18, 0xce, 0x56, 0x94, 0x44, 0xe3, 0x7a, 0xf7, 0xdd, 0x42, 0xf0, 0x18, 0x60, 0x92, 0x9f }; + static const UINT8 xor2[0x20] = { 0x2f, 0x02, 0x60, 0xbb, 0x77, 0x01, 0x30, 0x08, 0xd8, 0x01, 0xa0, 0xdf, 0x37, 0x0a, 0xf0, 0x65, 0x28, 0x03, 0xd0, 0x23, 0xd3, 0x03, 0x70, 0x42, 0xbb, 0x06, 0xf0, 0x28, 0xba, 0x0f, 0xf0, 0x7a }; + int i; + int ofst; + int rom_size = 0x900000; + dynamic_buffer buf( rom_size ); + + for (i = 0; i < 0x100000; i++) + { + rom[ 0x800000 + i ] ^= rom[ 0x100002 | i ]; + } + for( i = 0; i < 0x100000; i++) + { + rom[ i ] ^= xor1[ (BYTE_XOR_LE(i) % 0x20) ]; + } + for( i = 0x100000; i < 0x800000; i++) + { + rom[ i ] ^= xor2[ (BYTE_XOR_LE(i) % 0x20) ]; + } + for( i = 0x100000; i < 0x800000; i += 4) + { + UINT16 rom16; + rom16 = rom[BYTE_XOR_LE(i+1)] | rom[BYTE_XOR_LE(i+2)]<<8; + rom16 = BITSWAP16( rom16, 15, 14, 13, 12, 5, 4, 7, 6, 9, 8, 11, 10, 3, 2, 1, 0 ); + rom[BYTE_XOR_LE(i+1)] = rom16&0xff; + rom[BYTE_XOR_LE(i+2)] = rom16>>8; + } + for( i = 0; i < 0x0100000 / 0x10000; i++ ) + { + ofst = (i & 0xf0) + BITSWAP8((i & 0x0f), 7, 6, 5, 4, 0, 1, 2, 3); + memcpy( &buf[ i * 0x10000 ], &rom[ ofst * 0x10000 ], 0x10000 ); + } + for( i = 0x100000; i < 0x900000; i += 0x100) + { + ofst = (i & 0xf000ff) + ((i & 0x000f00) ^ 0x00800) + (BITSWAP8( ((i & 0x0ff000) >> 12), 4, 5, 6, 7, 1, 0, 3, 2 ) << 12); + memcpy( &buf[ i ], &rom[ ofst ], 0x100 ); + } + memcpy (&rom[0x000000], &buf[0x000000], 0x100000); + memcpy (&rom[0x100000], &buf[0x800000], 0x100000); + memcpy (&rom[0x200000], &buf[0x100000], 0x700000); +} + + +void pvc_prot_device::kof2003h_decrypt_68k(UINT8* rom, UINT32 size) +{ + static const UINT8 xor1[0x20] = { 0xc2, 0x4b, 0x74, 0xfd, 0x0b, 0x34, 0xeb, 0xd7, 0x10, 0x6d, 0xf9, 0xce, 0x5d, 0xd5, 0x61, 0x29, 0xf5, 0xbe, 0x0d, 0x82, 0x72, 0x45, 0x0f, 0x24, 0xb3, 0x34, 0x1b, 0x99, 0xea, 0x09, 0xf3, 0x03 }; + static const UINT8 xor2[0x20] = { 0x2b, 0x09, 0xd0, 0x7f, 0x51, 0x0b, 0x10, 0x4c, 0x5b, 0x07, 0x70, 0x9d, 0x3e, 0x0b, 0xb0, 0xb6, 0x54, 0x09, 0xe0, 0xcc, 0x3d, 0x0d, 0x80, 0x99, 0x87, 0x03, 0x90, 0x82, 0xfe, 0x04, 0x20, 0x18 }; + int i; + int ofst; + int rom_size = 0x900000; + dynamic_buffer buf( rom_size ); + + for (i = 0; i < 0x100000; i++) + { + rom[ 0x800000 + i ] ^= rom[ 0x100002 | i ]; + } + for( i = 0; i < 0x100000; i++) + { + rom[ i ] ^= xor1[ (BYTE_XOR_LE(i) % 0x20) ]; + } + for( i = 0x100000; i < 0x800000; i++) + { + rom[ i ] ^= xor2[ (BYTE_XOR_LE(i) % 0x20) ]; + } + for( i = 0x100000; i < 0x800000; i += 4) + { + UINT16 rom16; + rom16 = rom[BYTE_XOR_LE(i+1)] | rom[BYTE_XOR_LE(i+2)]<<8; + rom16 = BITSWAP16( rom16, 15, 14, 13, 12, 10, 11, 8, 9, 6, 7, 4, 5, 3, 2, 1, 0 ); + rom[BYTE_XOR_LE(i+1)] = rom16&0xff; + rom[BYTE_XOR_LE(i+2)] = rom16>>8; + } + for( i = 0; i < 0x0100000 / 0x10000; i++ ) + { + ofst = (i & 0xf0) + BITSWAP8((i & 0x0f), 7, 6, 5, 4, 1, 0, 3, 2); + memcpy( &buf[ i * 0x10000 ], &rom[ ofst * 0x10000 ], 0x10000 ); + } + for( i = 0x100000; i < 0x900000; i += 0x100) + { + ofst = (i & 0xf000ff) + ((i & 0x000f00) ^ 0x00400) + (BITSWAP8( ((i & 0x0ff000) >> 12), 6, 7, 4, 5, 0, 1, 2, 3 ) << 12); + memcpy( &buf[ i ], &rom[ ofst ], 0x100 ); + } + memcpy (&rom[0x000000], &buf[0x000000], 0x100000); + memcpy (&rom[0x100000], &buf[0x800000], 0x100000); + memcpy (&rom[0x200000], &buf[0x100000], 0x700000); +} diff --git a/src/devices/bus/neogeo/pvc_prot.h b/src/devices/bus/neogeo/pvc_prot.h new file mode 100644 index 00000000000..794783cc4dd --- /dev/null +++ b/src/devices/bus/neogeo/pvc_prot.h @@ -0,0 +1,50 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + +#pragma once + +#include "banked_cart.h" + +#ifndef __PVC_PROT__ +#define __PVC_PROT__ + +extern const device_type PVC_PROT; + +#define MCFG_PVC_PROT_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, PVC_PROT, 0) + + +class pvc_prot_device : public device_t +{ +public: + // construction/destruction + pvc_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + void pvc_write_unpack_color(); + void pvc_write_pack_color(); + void pvc_write_bankswitch(address_space &space); + DECLARE_READ16_MEMBER(pvc_prot_r); + DECLARE_WRITE16_MEMBER(pvc_prot_w); + void install_pvc_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev); + neogeo_banked_cart_device* m_bankdev; + + UINT16 m_cartridge_ram[0x1000]; + + void mslug5_decrypt_68k(UINT8* rom, UINT32 size); + void svc_px_decrypt(UINT8* rom, UINT32 size); + void kf2k3pcb_decrypt_68k(UINT8* rom, UINT32 size); + void kof2003_decrypt_68k(UINT8* rom, UINT32 size); + void kof2003h_decrypt_68k(UINT8* rom, UINT32 size); + +protected: + virtual void device_start(); + virtual void device_reset(); + + + +private: + + +}; + +#endif diff --git a/src/devices/bus/neogeo/rom.c b/src/devices/bus/neogeo/rom.c new file mode 100644 index 00000000000..085e68edec2 --- /dev/null +++ b/src/devices/bus/neogeo/rom.c @@ -0,0 +1,70 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/*********************************************************************************************************** + + NEOGEO ROM cart emulation + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "rom.h" + + +//------------------------------------------------- +// neogeo_rom_device - constructor +//------------------------------------------------- + +const device_type NEOGEO_ROM = &device_creator<neogeo_rom_device>; + + +neogeo_rom_device::neogeo_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_neogeo_cart_interface( mconfig, *this ), + m_banked_cart(*this, "banked_cart") +{ +} + +neogeo_rom_device::neogeo_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock) + : device_t(mconfig, NEOGEO_ROM, "NEOGEO ROM Carts", tag, owner, clock, "neogeo_rom", __FILE__), + device_neogeo_cart_interface( mconfig, *this ), + m_banked_cart(*this, "banked_cart") +{ +} + + +//------------------------------------------------- +// mapper specific start/reset +//------------------------------------------------- + +void neogeo_rom_device::device_start() +{ +} + +void neogeo_rom_device::device_reset() +{ +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +READ16_MEMBER(neogeo_rom_device::read_rom) +{ + return m_rom[offset]; +} + +static MACHINE_CONFIG_FRAGMENT( banked_cart ) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") +MACHINE_CONFIG_END + +machine_config_constructor neogeo_rom_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( banked_cart ); +} + +void neogeo_rom_device::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); +} diff --git a/src/devices/bus/neogeo/rom.h b/src/devices/bus/neogeo/rom.h new file mode 100644 index 00000000000..9394a7ec5bd --- /dev/null +++ b/src/devices/bus/neogeo/rom.h @@ -0,0 +1,38 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#ifndef __NEOGEO_ROM_H +#define __NEOGEO_ROM_H + +#include "neogeo_slot.h" +#include "banked_cart.h" + +// ======================> neogeo_rom_device + +class neogeo_rom_device : public device_t, + public device_neogeo_cart_interface +{ +public: + // construction/destruction + neogeo_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source); + neogeo_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ16_MEMBER(read_rom); + + virtual void activate_cart(ACTIVATE_CART_PARAMS); + + required_device<neogeo_banked_cart_device> m_banked_cart; +}; + + + +// device type definition +extern const device_type NEOGEO_ROM; + + +#endif diff --git a/src/devices/bus/neogeo/sbp_prot.c b/src/devices/bus/neogeo/sbp_prot.c new file mode 100644 index 00000000000..a286bbbb88e --- /dev/null +++ b/src/devices/bus/neogeo/sbp_prot.c @@ -0,0 +1,86 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#include "emu.h" +#include "sbp_prot.h" + + + +extern const device_type SBP_PROT = &device_creator<sbp_prot_device>; + + +sbp_prot_device::sbp_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, SBP_PROT, "NeoGeo Protection (Super Bubble Pop)", tag, owner, clock, "sbp_prot", __FILE__) +{ +} + + +void sbp_prot_device::device_start() +{ +} + +void sbp_prot_device::device_reset() +{ +} + + + +READ16_MEMBER( sbp_prot_device::sbp_lowerrom_r ) +{ + UINT16* rom = (UINT16*)m_mainrom; + UINT16 origdata = rom[(offset+(0x200/2))]; + UINT16 data = BITSWAP16(origdata, 11,10,9,8,15,14,13,12,3,2,1,0,7,6,5,4); + int realoffset = 0x200+(offset*2); + logerror("sbp_lowerrom_r offset %08x data %04x\n", realoffset, data ); + + // there is actually data in the rom here already, maybe we should just return it 'as is' + if (realoffset==0xd5e) return origdata; + + return data; +} + +WRITE16_MEMBER( sbp_prot_device::sbp_lowerrom_w ) +{ + int realoffset = 0x200+(offset*2); + + // the actual data written is just pulled from the end of the rom, and unused space + // maybe this is just some kind of watchdog for the protection device and it doesn't + // matter? + if (realoffset == 0x1080) + { + if (data==0x4e75) + { + return; + } + else if (data==0xffff) + { + return; + } + } + + printf("sbp_lowerrom_w offset %08x data %04x\n", realoffset, data ); +} + + +void sbp_prot_device::sbp_install_protection(cpu_device* maincpu, UINT8* cpurom, UINT32 cpurom_size) +{ + m_mainrom = cpurom; + + // there seems to be a protection device living around here.. + // if you nibble swap the data in the rom the game will boot + // there are also writes to 0x1080.. + // + // other stuff going on as well tho, the main overlay is still missing, and p1 inputs don't work + maincpu->space(AS_PROGRAM).install_read_handler(0x00200, 0x001fff, read16_delegate(FUNC(sbp_prot_device::sbp_lowerrom_r), this)); + maincpu->space(AS_PROGRAM).install_write_handler(0x00200, 0x001fff, write16_delegate(FUNC(sbp_prot_device::sbp_lowerrom_w), this)); + + /* the game code clears the text overlay used ingame immediately after writing it.. why? protection? sloppy code that the hw ignores? imperfect emulation? */ + { + UINT16* rom = (UINT16*)cpurom; + + rom[0x2a6f8 / 2] = 0x4e71; + rom[0x2a6fa / 2] = 0x4e71; + rom[0x2a6fc / 2] = 0x4e71; + } +} diff --git a/src/devices/bus/neogeo/sbp_prot.h b/src/devices/bus/neogeo/sbp_prot.h new file mode 100644 index 00000000000..7aa5ebb67da --- /dev/null +++ b/src/devices/bus/neogeo/sbp_prot.h @@ -0,0 +1,40 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#pragma once + +#ifndef __SBP_PROT__ +#define __SBP_PROT__ + +extern const device_type SBP_PROT; + +#define MCFG_SBP_PROT_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, SBP_PROT, 0) + + +class sbp_prot_device : public device_t +{ +public: + // construction/destruction + sbp_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + + UINT8* m_mainrom; + + void sbp_install_protection(cpu_device* maincpu, UINT8* cpurom, UINT32 cpurom_size); + DECLARE_WRITE16_MEMBER(sbp_lowerrom_w); + DECLARE_READ16_MEMBER(sbp_lowerrom_r); + +protected: + virtual void device_start(); + virtual void device_reset(); + + + +private: + + +}; + +#endif diff --git a/src/devices/bus/neogeo/sma_cart.c b/src/devices/bus/neogeo/sma_cart.c new file mode 100644 index 00000000000..61e07b962f3 --- /dev/null +++ b/src/devices/bus/neogeo/sma_cart.c @@ -0,0 +1,177 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +/*********************************************************************************************************** + + NEOGEO ROM cart emulation + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "sma_cart.h" + + +//------------------------------------------------- +// neogeo_sma_cart - constructor +//------------------------------------------------- + +const device_type NEOGEO_SMA_CART = &device_creator<neogeo_sma_cart>; + + +neogeo_sma_cart::neogeo_sma_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_sma_prot(*this, "sma_prot"), + m_cmc_prot(*this, "cmc_prot") + +{ +} + +neogeo_sma_cart::neogeo_sma_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock) + : device_t(mconfig, NEOGEO_SMA_CART, "NEOGEO SMA Cart", tag, owner, clock, "neogeo_rom", __FILE__), + device_neogeo_cart_interface(mconfig, *this), + m_banked_cart(*this, "banked_cart"), + m_sma_prot(*this, "sma_prot"), + m_cmc_prot(*this, "cmc_prot") +{ +} + + +//------------------------------------------------- +// mapper specific start/reset +//------------------------------------------------- + +void neogeo_sma_cart::device_start() +{ +} + +void neogeo_sma_cart::device_reset() +{ +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +READ16_MEMBER(neogeo_sma_cart::read_rom) +{ + return m_rom[offset]; +} + +static MACHINE_CONFIG_FRAGMENT( sma_cart ) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") + MCFG_SMA_PROT_ADD("sma_prot") + MCFG_CMC_PROT_ADD("cmc_prot") +MACHINE_CONFIG_END + +machine_config_constructor neogeo_sma_cart::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( sma_cart ); +} + + + +/* Individual cartridge types (mirror DRIVER_INIT functionality) */ + +/************************************************* + KOF 99 +**************************************************/ + +const device_type NEOGEO_SMA_KOF99_CART = &device_creator<neogeo_sma_kof99_cart>; + +neogeo_sma_kof99_cart::neogeo_sma_kof99_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_sma_cart(mconfig, NEOGEO_SMA_KOF99_CART, "NEOGEO SMA Kof99 Cart", tag, owner, clock, "sma_kof99_cart", __FILE__) {} + +void neogeo_sma_kof99_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_sma_prot->kof99_decrypt_68k(cpuregion); + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF99_GFX_KEY); +} + +void neogeo_sma_kof99_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_sma_prot->kof99_install_protection(maincpu, m_banked_cart); +} + + + + +/************************************************* + Garou +**************************************************/ + +const device_type NEOGEO_SMA_GAROU_CART = &device_creator<neogeo_sma_garou_cart>; + +neogeo_sma_garou_cart::neogeo_sma_garou_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_sma_cart(mconfig, NEOGEO_SMA_GAROU_CART, "NEOGEO SMA Garou Cart", tag, owner, clock, "sma_garou_cart", __FILE__) {} + +void neogeo_sma_garou_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_sma_prot->garou_decrypt_68k(cpuregion); + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, GAROU_GFX_KEY); +} + +void neogeo_sma_garou_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_sma_prot->garou_install_protection(maincpu, m_banked_cart); +} + +const device_type NEOGEO_SMA_GAROUH_CART = &device_creator<neogeo_sma_garouh_cart>; + +neogeo_sma_garouh_cart::neogeo_sma_garouh_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_sma_cart(mconfig, NEOGEO_SMA_GAROU_CART, "NEOGEO SMA Garou (alt) Cart", tag, owner, clock, "sma_garouh_cart", __FILE__) {} + +void neogeo_sma_garouh_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_sma_prot->garouh_decrypt_68k(cpuregion); + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, GAROU_GFX_KEY); +} + +void neogeo_sma_garouh_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_sma_prot->garouh_install_protection(maincpu, m_banked_cart); +} + + +/************************************************* + Metal Slug 3 +**************************************************/ + +const device_type NEOGEO_SMA_MSLUG3_CART = &device_creator<neogeo_sma_mslug3_cart>; + +neogeo_sma_mslug3_cart::neogeo_sma_mslug3_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_sma_cart(mconfig, NEOGEO_SMA_MSLUG3_CART, "NEOGEO SMA Mslug3 Cart", tag, owner, clock, "sma_mslug3_cart", __FILE__) {} + +void neogeo_sma_mslug3_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_sma_prot->mslug3_decrypt_68k(cpuregion); + m_cmc_prot->kof99_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, MSLUG3_GFX_KEY); +} + +void neogeo_sma_mslug3_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_sma_prot->mslug3_install_protection(maincpu, m_banked_cart); +} + +/************************************************* + KOF2000 +**************************************************/ + +const device_type NEOGEO_SMA_KOF2000_CART = &device_creator<neogeo_sma_kof2000_cart>; + +neogeo_sma_kof2000_cart::neogeo_sma_kof2000_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : neogeo_sma_cart(mconfig, NEOGEO_SMA_KOF2000_CART, "NEOGEO SMA KOF2000 Cart", tag, owner, clock, "sma_kof2000_cart", __FILE__) {} + +void neogeo_sma_kof2000_cart::decrypt_all(DECRYPT_ALL_PARAMS) +{ + m_sma_prot->kof2000_decrypt_68k(cpuregion); + m_cmc_prot->neogeo_cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size); + m_cmc_prot->kof2000_neogeo_gfx_decrypt(spr_region, spr_region_size, fix_region, fix_region_size, KOF2000_GFX_KEY); +} + +void neogeo_sma_kof2000_cart::activate_cart(ACTIVATE_CART_PARAMS) +{ + m_banked_cart->install_banks(machine, maincpu, cpuregion, cpuregion_size); + m_sma_prot->kof2000_install_protection(maincpu, m_banked_cart); +} diff --git a/src/devices/bus/neogeo/sma_cart.h b/src/devices/bus/neogeo/sma_cart.h new file mode 100644 index 00000000000..d0b0fb64432 --- /dev/null +++ b/src/devices/bus/neogeo/sma_cart.h @@ -0,0 +1,112 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#ifndef __NEOGEO_SMA_CART_H +#define __NEOGEO_SMA_CART_H + +#include "neogeo_slot.h" +#include "banked_cart.h" +#include "sma_prot.h" +#include "cmc_prot.h" + +// ======================> neogeo_sma_cart + +class neogeo_sma_cart : public device_t, + public device_neogeo_cart_interface +{ +public: + // construction/destruction + neogeo_sma_cart(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT16 clock, const char *shortname, const char *source); + neogeo_sma_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT16 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ16_MEMBER(read_rom); + + virtual void activate_cart(ACTIVATE_CART_PARAMS) {} + virtual void decrypt_all(DECRYPT_ALL_PARAMS) {} + virtual int get_fixed_bank_type(void) { return 0; } + + required_device<neogeo_banked_cart_device> m_banked_cart; + required_device<sma_prot_device> m_sma_prot; + required_device<cmc_prot_device> m_cmc_prot; +}; + + + +// device type definition +extern const device_type NEOGEO_SMA_CART; + + +/************************************************* + KOF 99 +**************************************************/ + +class neogeo_sma_kof99_cart : public neogeo_sma_cart +{ +public: + neogeo_sma_kof99_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_SMA_KOF99_CART; + +/************************************************* + Garou +**************************************************/ + +class neogeo_sma_garou_cart : public neogeo_sma_cart +{ +public: + neogeo_sma_garou_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_SMA_GAROU_CART; + +class neogeo_sma_garouh_cart : public neogeo_sma_cart +{ +public: + neogeo_sma_garouh_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_SMA_GAROUH_CART; + +/************************************************* + Metal Slug 3 +**************************************************/ + +class neogeo_sma_mslug3_cart : public neogeo_sma_cart +{ +public: + neogeo_sma_mslug3_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 1; } +}; +extern const device_type NEOGEO_SMA_MSLUG3_CART; + + +/************************************************* + KOF2000 +**************************************************/ + +class neogeo_sma_kof2000_cart : public neogeo_sma_cart +{ +public: + neogeo_sma_kof2000_cart(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual void activate_cart(ACTIVATE_CART_PARAMS); + virtual void decrypt_all(DECRYPT_ALL_PARAMS); + virtual int get_fixed_bank_type(void) { return 2; } +}; +extern const device_type NEOGEO_SMA_KOF2000_CART; + + +#endif diff --git a/src/devices/bus/neogeo/sma_prot.c b/src/devices/bus/neogeo/sma_prot.c new file mode 100644 index 00000000000..5fe723375a0 --- /dev/null +++ b/src/devices/bus/neogeo/sma_prot.c @@ -0,0 +1,462 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood +#include "emu.h" +#include "sma_prot.h" + + + +extern const device_type SMA_PROT = &device_creator<sma_prot_device>; + + +sma_prot_device::sma_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, SMA_PROT, "NeoGeo SMA Cartridge", tag, owner, clock, "sma_prot", __FILE__) +{ +} + + +void sma_prot_device::device_start() +{ + save_item(NAME(m_sma_rng)); +} + +void sma_prot_device::device_reset() +{ + reset_sma_rng(); +} + + + + + +/************************ SMA Protection************************ + thanks to Razoola +***************************************************************/ + +WRITE16_MEMBER( sma_prot_device::kof99_bankswitch_w ) +{ + int bankaddress; + static const int bankoffset[64] = + { + 0x000000, 0x100000, 0x200000, 0x300000, + 0x3cc000, 0x4cc000, 0x3f2000, 0x4f2000, + 0x407800, 0x507800, 0x40d000, 0x50d000, + 0x417800, 0x517800, 0x420800, 0x520800, + 0x424800, 0x524800, 0x429000, 0x529000, + 0x42e800, 0x52e800, 0x431800, 0x531800, + 0x54d000, 0x551000, 0x567000, 0x592800, + 0x588800, 0x581800, 0x599800, 0x594800, + 0x598000, /* rest not used? */ + }; + + /* unscramble bank number */ + data = + (((data>>14)&1)<<0)+ + (((data>> 6)&1)<<1)+ + (((data>> 8)&1)<<2)+ + (((data>>10)&1)<<3)+ + (((data>>12)&1)<<4)+ + (((data>> 5)&1)<<5); + + bankaddress = 0x100000 + bankoffset[data]; + m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress); +} + + +WRITE16_MEMBER( sma_prot_device::garou_bankswitch_w ) +{ + /* thanks to Razoola and Mr K for the info */ + int bankaddress; + static const int bankoffset[64] = + { + 0x000000, 0x100000, 0x200000, 0x300000, // 00 + 0x280000, 0x380000, 0x2d0000, 0x3d0000, // 04 + 0x2f0000, 0x3f0000, 0x400000, 0x500000, // 08 + 0x420000, 0x520000, 0x440000, 0x540000, // 12 + 0x498000, 0x598000, 0x4a0000, 0x5a0000, // 16 + 0x4a8000, 0x5a8000, 0x4b0000, 0x5b0000, // 20 + 0x4b8000, 0x5b8000, 0x4c0000, 0x5c0000, // 24 + 0x4c8000, 0x5c8000, 0x4d0000, 0x5d0000, // 28 + 0x458000, 0x558000, 0x460000, 0x560000, // 32 + 0x468000, 0x568000, 0x470000, 0x570000, // 36 + 0x478000, 0x578000, 0x480000, 0x580000, // 40 + 0x488000, 0x588000, 0x490000, 0x590000, // 44 + 0x5d0000, 0x5d8000, 0x5e0000, 0x5e8000, // 48 + 0x5f0000, 0x5f8000, 0x600000, /* rest not used? */ + }; + + /* unscramble bank number */ + data = + (((data>> 5)&1)<<0)+ + (((data>> 9)&1)<<1)+ + (((data>> 7)&1)<<2)+ + (((data>> 6)&1)<<3)+ + (((data>>14)&1)<<4)+ + (((data>>12)&1)<<5); + + bankaddress = 0x100000 + bankoffset[data]; + m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress); +} + + +WRITE16_MEMBER( sma_prot_device::garouh_bankswitch_w ) +{ + /* thanks to Razoola and Mr K for the info */ + int bankaddress; + static const int bankoffset[64] = + { + 0x000000, 0x100000, 0x200000, 0x300000, // 00 + 0x280000, 0x380000, 0x2d0000, 0x3d0000, // 04 + 0x2c8000, 0x3c8000, 0x400000, 0x500000, // 08 + 0x420000, 0x520000, 0x440000, 0x540000, // 12 + 0x598000, 0x698000, 0x5a0000, 0x6a0000, // 16 + 0x5a8000, 0x6a8000, 0x5b0000, 0x6b0000, // 20 + 0x5b8000, 0x6b8000, 0x5c0000, 0x6c0000, // 24 + 0x5c8000, 0x6c8000, 0x5d0000, 0x6d0000, // 28 + 0x458000, 0x558000, 0x460000, 0x560000, // 32 + 0x468000, 0x568000, 0x470000, 0x570000, // 36 + 0x478000, 0x578000, 0x480000, 0x580000, // 40 + 0x488000, 0x588000, 0x490000, 0x590000, // 44 + 0x5d8000, 0x6d8000, 0x5e0000, 0x6e0000, // 48 + 0x5e8000, 0x6e8000, 0x6e8000, 0x000000, // 52 + 0x000000, 0x000000, 0x000000, 0x000000, // 56 + 0x000000, 0x000000, 0x000000, 0x000000, // 60 + }; + + /* unscramble bank number */ + data = + (((data>> 4)&1)<<0)+ + (((data>> 8)&1)<<1)+ + (((data>>14)&1)<<2)+ + (((data>> 2)&1)<<3)+ + (((data>>11)&1)<<4)+ + (((data>>13)&1)<<5); + + bankaddress = 0x100000 + bankoffset[data]; + m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress); +} + + +WRITE16_MEMBER( sma_prot_device::mslug3_bankswitch_w ) +{ + /* thanks to Razoola and Mr K for the info */ + int bankaddress; + static const int bankoffset[64] = + { + 0x000000, 0x020000, 0x040000, 0x060000, // 00 + 0x070000, 0x090000, 0x0b0000, 0x0d0000, // 04 + 0x0e0000, 0x0f0000, 0x120000, 0x130000, // 08 + 0x140000, 0x150000, 0x180000, 0x190000, // 12 + 0x1a0000, 0x1b0000, 0x1e0000, 0x1f0000, // 16 + 0x200000, 0x210000, 0x240000, 0x250000, // 20 + 0x260000, 0x270000, 0x2a0000, 0x2b0000, // 24 + 0x2c0000, 0x2d0000, 0x300000, 0x310000, // 28 + 0x320000, 0x330000, 0x360000, 0x370000, // 32 + 0x380000, 0x390000, 0x3c0000, 0x3d0000, // 36 + 0x400000, 0x410000, 0x440000, 0x450000, // 40 + 0x460000, 0x470000, 0x4a0000, 0x4b0000, // 44 + 0x4c0000, /* rest not used? */ + }; + + /* unscramble bank number */ + data = + (((data>>14)&1)<<0)+ + (((data>>12)&1)<<1)+ + (((data>>15)&1)<<2)+ + (((data>> 6)&1)<<3)+ + (((data>> 3)&1)<<4)+ + (((data>> 9)&1)<<5); + + bankaddress = 0x100000 + bankoffset[data]; + m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress); +} + + +WRITE16_MEMBER( sma_prot_device::kof2000_bankswitch_w ) +{ + /* thanks to Razoola and Mr K for the info */ + int bankaddress; + static const int bankoffset[64] = + { + 0x000000, 0x100000, 0x200000, 0x300000, // 00 + 0x3f7800, 0x4f7800, 0x3ff800, 0x4ff800, // 04 + 0x407800, 0x507800, 0x40f800, 0x50f800, // 08 + 0x416800, 0x516800, 0x41d800, 0x51d800, // 12 + 0x424000, 0x524000, 0x523800, 0x623800, // 16 + 0x526000, 0x626000, 0x528000, 0x628000, // 20 + 0x52a000, 0x62a000, 0x52b800, 0x62b800, // 24 + 0x52d000, 0x62d000, 0x52e800, 0x62e800, // 28 + 0x618000, 0x619000, 0x61a000, 0x61a800, // 32 + }; + + /* unscramble bank number */ + data = + (((data>>15)&1)<<0)+ + (((data>>14)&1)<<1)+ + (((data>> 7)&1)<<2)+ + (((data>> 3)&1)<<3)+ + (((data>>10)&1)<<4)+ + (((data>> 5)&1)<<5); + + bankaddress = 0x100000 + bankoffset[data]; + m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress); +} + + +READ16_MEMBER( sma_prot_device::prot_9a37_r ) +{ + return 0x9a37; +} + + +/* information about the sma random number generator provided by razoola */ +/* this RNG is correct for KOF99, other games might be different */ + +READ16_MEMBER( sma_prot_device::sma_random_r ) +{ + UINT16 old = m_sma_rng; + + UINT16 newbit = ((m_sma_rng >> 2) ^ + (m_sma_rng >> 3) ^ + (m_sma_rng >> 5) ^ + (m_sma_rng >> 6) ^ + (m_sma_rng >> 7) ^ + (m_sma_rng >>11) ^ + (m_sma_rng >>12) ^ + (m_sma_rng >>15)) & 1; + + m_sma_rng = (m_sma_rng << 1) | newbit; + + return old; +} + + +void sma_prot_device::reset_sma_rng() +{ + m_sma_rng = 0x2345; +} + + +void sma_prot_device::sma_install_random_read_handler(cpu_device* maincpu, int addr1, int addr2 ) +{ + maincpu->space(AS_PROGRAM).install_read_handler(addr1, addr1 + 1, read16_delegate(FUNC(sma_prot_device::sma_random_r),this)); + maincpu->space(AS_PROGRAM).install_read_handler(addr2, addr2 + 1, read16_delegate(FUNC(sma_prot_device::sma_random_r),this)); +} + + +void sma_prot_device::kof99_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev) +{ + maincpu->space(AS_PROGRAM).install_write_handler(0x2ffff0, 0x2ffff1, write16_delegate(FUNC(sma_prot_device::kof99_bankswitch_w),this)); + maincpu->space(AS_PROGRAM).install_read_handler(0x2fe446, 0x2fe447, read16_delegate(FUNC(sma_prot_device::prot_9a37_r),this)); + m_bankdev = bankdev; + + sma_install_random_read_handler(maincpu, 0x2ffff8, 0x2ffffa); +} + + +void sma_prot_device::garou_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev) +{ + maincpu->space(AS_PROGRAM).install_write_handler(0x2fffc0, 0x2fffc1, write16_delegate(FUNC(sma_prot_device::garou_bankswitch_w),this)); + maincpu->space(AS_PROGRAM).install_read_handler(0x2fe446, 0x2fe447, read16_delegate(FUNC(sma_prot_device::prot_9a37_r),this)); + m_bankdev = bankdev; + + sma_install_random_read_handler(maincpu, 0x2fffcc, 0x2ffff0); +} + + +void sma_prot_device::garouh_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev) +{ + maincpu->space(AS_PROGRAM).install_write_handler(0x2fffc0, 0x2fffc1, write16_delegate(FUNC(sma_prot_device::garouh_bankswitch_w),this)); + maincpu->space(AS_PROGRAM).install_read_handler(0x2fe446, 0x2fe447, read16_delegate(FUNC(sma_prot_device::prot_9a37_r),this)); + m_bankdev = bankdev; + + sma_install_random_read_handler(maincpu, 0x2fffcc, 0x2ffff0); +} + + +void sma_prot_device::mslug3_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev) +{ + maincpu->space(AS_PROGRAM).install_write_handler(0x2fffe4, 0x2fffe5, write16_delegate(FUNC(sma_prot_device::mslug3_bankswitch_w),this)); + maincpu->space(AS_PROGRAM).install_read_handler(0x2fe446, 0x2fe447, read16_delegate(FUNC(sma_prot_device::prot_9a37_r),this)); + m_bankdev = bankdev; + +// sma_install_random_read_handler(maincpu, 0x2ffff8, 0x2ffffa); +} + + +void sma_prot_device::kof2000_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev) +{ + maincpu->space(AS_PROGRAM).install_write_handler(0x2fffec, 0x2fffed, write16_delegate(FUNC(sma_prot_device::kof2000_bankswitch_w),this)); + maincpu->space(AS_PROGRAM).install_read_handler(0x2fe446, 0x2fe447, read16_delegate(FUNC(sma_prot_device::prot_9a37_r),this)); + m_bankdev = bankdev; + + sma_install_random_read_handler(maincpu, 0x2fffd8, 0x2fffda); +} + + + +/* kof99, garou, garouh, mslug3 and kof2000 have and SMA chip which contains program code and decrypts the 68k roms */ +void sma_prot_device::kof99_decrypt_68k(UINT8* base) +{ + UINT16 *rom; + int i,j; + + rom = (UINT16 *)(base + 0x100000); + /* swap data lines on the whole ROMs */ + for (i = 0;i < 0x800000/2;i++) + { + rom[i] = BITSWAP16(rom[i],13,7,3,0,9,4,5,6,1,12,8,14,10,11,2,15); + } + + /* swap address lines for the banked part */ + for (i = 0;i < 0x600000/2;i+=0x800/2) + { + UINT16 buffer[0x800/2]; + memcpy(buffer,&rom[i],0x800); + for (j = 0;j < 0x800/2;j++) + { + rom[i+j] = buffer[BITSWAP24(j,23,22,21,20,19,18,17,16,15,14,13,12,11,10,6,2,4,9,8,3,1,7,0,5)]; + } + } + + /* swap address lines & relocate fixed part */ + rom = (UINT16 *)base; + for (i = 0;i < 0x0c0000/2;i++) + { + rom[i] = rom[0x700000/2 + BITSWAP24(i,23,22,21,20,19,18,11,6,14,17,16,5,8,10,12,0,4,3,2,7,9,15,13,1)]; + } +} + + +void sma_prot_device::garou_decrypt_68k(UINT8* base) +{ + UINT16 *rom; + int i,j; + + /* thanks to Razoola and Mr K for the info */ + rom = (UINT16 *)(base + 0x100000); + /* swap data lines on the whole ROMs */ + for (i = 0;i < 0x800000/2;i++) + { + rom[i] = BITSWAP16(rom[i],13,12,14,10,8,2,3,1,5,9,11,4,15,0,6,7); + } + + /* swap address lines & relocate fixed part */ + rom = (UINT16 *)base; + for (i = 0;i < 0x0c0000/2;i++) + { + rom[i] = rom[0x710000/2 + BITSWAP24(i,23,22,21,20,19,18,4,5,16,14,7,9,6,13,17,15,3,1,2,12,11,8,10,0)]; + } + + /* swap address lines for the banked part */ + rom = (UINT16 *)(base + 0x100000); + for (i = 0;i < 0x800000/2;i+=0x8000/2) + { + UINT16 buffer[0x8000/2]; + memcpy(buffer,&rom[i],0x8000); + for (j = 0;j < 0x8000/2;j++) + { + rom[i+j] = buffer[BITSWAP24(j,23,22,21,20,19,18,17,16,15,14,9,4,8,3,13,6,2,7,0,12,1,11,10,5)]; + } + } +} + + +void sma_prot_device::garouh_decrypt_68k(UINT8* base) +{ + UINT16 *rom; + int i,j; + + /* thanks to Razoola and Mr K for the info */ + rom = (UINT16 *)(base + 0x100000); + /* swap data lines on the whole ROMs */ + for (i = 0;i < 0x800000/2;i++) + { + rom[i] = BITSWAP16(rom[i],14,5,1,11,7,4,10,15,3,12,8,13,0,2,9,6); + } + + /* swap address lines & relocate fixed part */ + rom = (UINT16 *)base; + for (i = 0;i < 0x0c0000/2;i++) + { + rom[i] = rom[0x7f8000/2 + BITSWAP24(i,23,22,21,20,19,18,5,16,11,2,6,7,17,3,12,8,14,4,0,9,1,10,15,13)]; + } + + /* swap address lines for the banked part */ + rom = (UINT16 *)(base + 0x100000); + for (i = 0;i < 0x800000/2;i+=0x8000/2) + { + UINT16 buffer[0x8000/2]; + memcpy(buffer,&rom[i],0x8000); + for (j = 0;j < 0x8000/2;j++) + { + rom[i+j] = buffer[BITSWAP24(j,23,22,21,20,19,18,17,16,15,14,12,8,1,7,11,3,13,10,6,9,5,4,0,2)]; + } + } +} + + +void sma_prot_device::mslug3_decrypt_68k(UINT8* base) +{ + UINT16 *rom; + int i,j; + + /* thanks to Razoola and Mr K for the info */ + rom = (UINT16 *)(base + 0x100000); + /* swap data lines on the whole ROMs */ + for (i = 0;i < 0x800000/2;i++) + { + rom[i] = BITSWAP16(rom[i],4,11,14,3,1,13,0,7,2,8,12,15,10,9,5,6); + } + + /* swap address lines & relocate fixed part */ + rom = (UINT16 *)base; + for (i = 0;i < 0x0c0000/2;i++) + { + rom[i] = rom[0x5d0000/2 + BITSWAP24(i,23,22,21,20,19,18,15,2,1,13,3,0,9,6,16,4,11,5,7,12,17,14,10,8)]; + } + + /* swap address lines for the banked part */ + rom = (UINT16 *)(base + 0x100000); + for (i = 0;i < 0x800000/2;i+=0x10000/2) + { + UINT16 buffer[0x10000/2]; + memcpy(buffer,&rom[i],0x10000); + for (j = 0;j < 0x10000/2;j++) + { + rom[i+j] = buffer[BITSWAP24(j,23,22,21,20,19,18,17,16,15,2,11,0,14,6,4,13,8,9,3,10,7,5,12,1)]; + } + } +} + + +void sma_prot_device::kof2000_decrypt_68k(UINT8* base) +{ + UINT16 *rom; + int i,j; + + /* thanks to Razoola and Mr K for the info */ + rom = (UINT16 *)(base + 0x100000); + /* swap data lines on the whole ROMs */ + for (i = 0;i < 0x800000/2;i++) + { + rom[i] = BITSWAP16(rom[i],12,8,11,3,15,14,7,0,10,13,6,5,9,2,1,4); + } + + /* swap address lines for the banked part */ + for (i = 0;i < 0x63a000/2;i+=0x800/2) + { + UINT16 buffer[0x800/2]; + memcpy(buffer,&rom[i],0x800); + for (j = 0;j < 0x800/2;j++) + { + rom[i+j] = buffer[BITSWAP24(j,23,22,21,20,19,18,17,16,15,14,13,12,11,10,4,1,3,8,6,2,7,0,9,5)]; + } + } + + /* swap address lines & relocate fixed part */ + rom = (UINT16 *)base; + for (i = 0;i < 0x0c0000/2;i++) + { + rom[i] = rom[0x73a000/2 + BITSWAP24(i,23,22,21,20,19,18,8,4,15,13,3,14,16,2,6,17,7,12,10,0,5,11,1,9)]; + } +} diff --git a/src/devices/bus/neogeo/sma_prot.h b/src/devices/bus/neogeo/sma_prot.h new file mode 100644 index 00000000000..271e1248f4d --- /dev/null +++ b/src/devices/bus/neogeo/sma_prot.h @@ -0,0 +1,58 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + + +#pragma once + +#include "banked_cart.h" + +#ifndef __SMA_PROT__ +#define __SMA_PROT__ + +extern const device_type SMA_PROT; + +#define MCFG_SMA_PROT_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, SMA_PROT, 0) + + +class sma_prot_device : public device_t +{ +public: + // construction/destruction + sma_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + + DECLARE_WRITE16_MEMBER( kof99_bankswitch_w ); + DECLARE_WRITE16_MEMBER( garou_bankswitch_w ); + DECLARE_WRITE16_MEMBER( garouh_bankswitch_w ); + DECLARE_WRITE16_MEMBER( mslug3_bankswitch_w ); + DECLARE_WRITE16_MEMBER( kof2000_bankswitch_w ); + DECLARE_READ16_MEMBER( prot_9a37_r ); + DECLARE_READ16_MEMBER( sma_random_r ); + void reset_sma_rng(); + void sma_install_random_read_handler(cpu_device* maincpu, int addr1, int addr2 ); + void kof99_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev); + void garou_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev); + void garouh_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev); + void mslug3_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev); + void kof2000_install_protection(cpu_device* maincpu, neogeo_banked_cart_device* bankdev); + neogeo_banked_cart_device* m_bankdev; + void kof99_decrypt_68k(UINT8* base); + void garou_decrypt_68k(UINT8* base); + void garouh_decrypt_68k(UINT8* base); + void mslug3_decrypt_68k(UINT8* base); + void kof2000_decrypt_68k(UINT8* base); + + UINT16 m_sma_rng; +protected: + virtual void device_start(); + virtual void device_reset(); + + + +private: + + +}; + +#endif |