diff options
Diffstat (limited to 'src/mame/old/bootleg_prot.cpp')
-rw-r--r-- | src/mame/old/bootleg_prot.cpp | 1073 |
1 files changed, 1073 insertions, 0 deletions
diff --git a/src/mame/old/bootleg_prot.cpp b/src/mame/old/bootleg_prot.cpp new file mode 100644 index 00000000000..08ff2d2eafa --- /dev/null +++ b/src/mame/old/bootleg_prot.cpp @@ -0,0 +1,1073 @@ +// license:BSD-3-Clause +// copyright-holders:S. Smith,David Haywood + +#include "emu.h" +#include "bootleg_prot.h" +#include "screen.h" + + + +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_t clock) + : device_t(mconfig, NGBOOTLEG_PROT, "NeoGeo Protection (Bootleg)", tag, owner, clock, "ngbootleg_prot", __FILE__), + kof2k3_overlay(0), + m_mainrom(nullptr), + m_fixedrom(nullptr), + m_bankdev(nullptr) +{ +} + + +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_t*sprrom, uint32_t sprrom_size) +{ + int i; + int cx_size = sprrom_size; + uint8_t *rom = sprrom; + std::vector<uint8_t> 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_t* fixed, uint32_t fixed_size, int value ) +{ + int sx_size = fixed_size; + uint8_t *rom = fixed; + int i; + + if (value == 1) + { + std::vector<uint8_t> 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_t* cpurom, uint32_t cpurom_size) +{ + int i; + std::vector<uint16_t> tmp( 0x500000 ); + uint16_t *src = (uint16_t*)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_t nBank) +{ + uint32_t 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_t *prom = (uint16_t*)m_mainrom; + COMBINE_DATA(&m_cartridge_ram2[(0x00000/2) + (offset & 0xFFFF)]); + } else { // Write S data on-the-fly + m_fixedrom[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_t *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_t* cpurom, uint32_t cpurom_size, uint8_t* fixedrom, uint32_t 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); + + // HACK: only save this at device_start (not allowed later) + if (machine().phase() <= MACHINE_PHASE_INIT) + save_pointer(NAME(m_fixedrom), 0x40000); +} + +void ngbootleg_prot_device::decrypt_kof10th(uint8_t* cpurom, uint32_t cpurom_size) +{ + int i, j; + std::vector<uint8_t> dst(0x900000); + uint8_t *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_t*)src)[0x0124/2] = 0x000d; // Enables XOR for RAM moves, forces SoftDIPs, and USA region + ((uint16_t*)src)[0x0126/2] = 0xf7a8; + + ((uint16_t*)src)[0x8bf4/2] = 0x4ef9; // Run code to change "S" data + ((uint16_t*)src)[0x8bf6/2] = 0x000d; + ((uint16_t*)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_t* cpurom, uint32_t cpurom_size) +{ + uint16_t *rom = (uint16_t*)cpurom; + std::vector<uint16_t> 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_t* cpurom, uint32_t cpurom_size) +{ + int i, j, ofst; + uint8_t *src = cpurom; + uint8_t 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_t* fixedrom, uint32_t fixedrom_size) +{ + int i; + uint8_t *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_t* audiorom, uint32_t audiorom_size) +{ + int i; + uint8_t *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_t* cpurom, uint32_t cpurom_size, uint8_t* audiorom, uint32_t audiorom_size, uint8_t* fixedrom, uint32_t 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_t *src, int size) +{ + int i, j; + static const uint8_t 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 }, + }; + + std::vector<uint8_t> 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_t* cpurom, uint32_t cpurom_size) +{ + int i,j; + + uint8_t *src = cpurom; + uint8_t 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_t* cpurom, uint32_t cpurom_size) +{ + uint8_t *src = cpurom; + std::vector<uint8_t> 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_t* sprrom, uint32_t sprrom_size, int start, int end, int bit3shift, int bit2shift, int bit1shift, int bit0shift) +{ + int i,j; + int tilesize=128; + + std::vector<uint8_t> rom(16*tilesize); // 16 tiles buffer + uint8_t* 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_t* sprrom, uint32_t 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_t* sprrom, uint32_t 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_t* sprrom, uint32_t sprrom_size, uint8_t* audiorom, uint32_t audiorom_size, uint8_t* fixedrom, uint32_t fixedrom_size) +{ + uint8_t *romdata = fixedrom; + std::vector<uint8_t> 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_t* cpurom, uint32_t cpurom_size) +{ + /* patches thanks to razoola */ + int i; + uint16_t *mem16 = (uint16_t *)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_t* fixedrom, uint32_t fixedrom_size ) +{ + int rom_size = fixedrom_size; + uint8_t *rom = fixedrom; + std::vector<uint8_t> 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_t* sprrom, uint32_t sprrom_size, uint8_t* audiorom, uint32_t audiorom_size, uint8_t* fixedrom, uint32_t fixedrom_size) +{ + uint8_t *romdata = audiorom+0x10000; + std::vector<uint8_t> 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_t* sprrom, uint32_t sprrom_size, uint8_t* audiorom, uint32_t audiorom_size ) +{ + uint8_t *romdata = audiorom+0x10000; + std::vector<uint8_t> 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_t* cpurom, uint32_t cpurom_size) +{ + /* patches thanks to razoola - same as for cthd2003*/ + int i; + uint16_t *mem16 = (uint16_t *)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_t* cpurom, uint32_t cpurom_size) +{ + uint8_t *src = cpurom+0x100000; + std::vector<uint8_t> 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_t* ymsndrom, uint32_t ymsndrom_size) +{ + int i; + uint8_t *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_t* cpurom, uint32_t cpurom_size) +{ + /* Descrambling P ROMs - Thanks to Razoola for the info */ + int i; + uint8_t *src = cpurom; + uint16_t *rom = (uint16_t*)cpurom; + + { + static const int sec[] = { 0x3, 0x8, 0x7, 0xC, 0x1, 0xA, 0x6, 0xD }; + std::vector<uint8_t> 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_t* cpurom, uint32_t cpurom_size) +{ + static const uint8_t sec[] = { + 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00 + }; + int i; + int size = cpurom_size; + uint8_t *src = cpurom; + std::vector<uint8_t> 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_t*sprrom, uint32_t sprrom_size) +{ + static const uint8_t idx_tbl[ 0x10 ] = { + 0, 1, 0, 1, 2, 3, 2, 3, 3, 4, 3, 4, 4, 5, 4, 5, + }; + static const uint8_t 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_t *src = sprrom; + std::vector<uint8_t> 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_t* cpurom, uint32_t cpurom_size) +{ + static const int sec[] = { + 0x00, 0x03, 0x02, 0x05, 0x04, 0x01 + }; + int size = cpurom_size; + uint8_t *src = cpurom; + std::vector<uint8_t> 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_t* cpurom, uint32_t cpurom_size) +{ + /* patched by the protection chip? */ + uint16_t *mem16 = (uint16_t *)cpurom; + mem16[0x0f8016/2] = 0x33c1; +} + + +/* SNK vs. CAPCOM SVC CHAOS Plus (bootleg set 2) */ + + +void ngbootleg_prot_device::svcplusa_px_decrypt(uint8_t* cpurom, uint32_t cpurom_size) +{ + int i; + static const int sec[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x00 + }; + int size = cpurom_size; + uint8_t *src = cpurom; + std::vector<uint8_t> 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_t* cpurom, uint32_t cpurom_size) +{ + static const int sec[] = { + 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00 + }; + int size = cpurom_size; + uint8_t *src = cpurom; + std::vector<uint8_t> 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_t* cpurom, uint32_t cpurom_size) +{ + /* patched by the protection chip? */ + uint16_t *mem16 = (uint16_t *)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_t* cr = (uint8_t *)m_cartridge_ram; + uint32_t address = (cr[BYTE_XOR_LE(0x1ff3)]<<16)|(cr[BYTE_XOR_LE(0x1ff2)]<<8)|cr[BYTE_XOR_LE(0x1ff1)]; + uint8_t 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_t* cr = (uint8_t *)m_cartridge_ram; + uint32_t address = (cr[BYTE_XOR_LE(0x1ff3)]<<16)|(cr[BYTE_XOR_LE(0x1ff2)]<<8)|cr[BYTE_XOR_LE(0x1ff0)]; + uint8_t 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_t* cpurom, uint32_t cpurom_size) +{ + int i; + static const uint8_t sec[] = { + 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 + }; + + int rom_size = 0x800000; + uint8_t *rom = cpurom; + std::vector<uint8_t> 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_t* cpurom, uint32_t 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_t* cpurom, uint32_t cpurom_size) +{ + std::vector<uint16_t> tmp(0x100000/2); + uint16_t*rom16 = (uint16_t*)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_t* cpurom, uint32_t 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_t* cpurom, uint32_t cpurom_size) +{ + { + uint8_t *src = cpurom; + memmove(src+0x100000, src, 0x600000); + memmove(src, src+0x700000, 0x100000); + } + + { + int ofst; + int i; + uint8_t *rom = cpurom + 0xfe000; + uint8_t *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_t*rom16 = (uint16_t*)cpurom; + kof2k3_overlay = rom16[0x58196 / 2]; + + +} + + +/* Samurai Shodown V / Samurai Spirits Zero (bootleg) */ + + +void ngbootleg_prot_device::samsho5b_px_decrypt(uint8_t* cpurom, uint32_t cpurom_size) +{ + int px_size = cpurom_size; + uint8_t *rom = cpurom; + std::vector<uint8_t> 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_t* ymsndrom, uint32_t ymsndrom_size) +{ + int vx_size = ymsndrom_size; + uint8_t *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_t* sprrom, uint32_t sprrom_size, uint8_t* audiorom, uint32_t audiorom_size) +{ + /* decrypt Z80 */ + uint8_t *rom = audiorom+0x10000; + std::vector<uint8_t> buf( 0x20000 ); + int i, j; + 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 ); +} |