mirror of
https://github.com/holub/mame
synced 2025-06-07 13:23:50 +03:00
- Reverse-engineered Moto Frenzy security FPGA and implemented decryption code [Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen]
New games added or promoted from NOT_WORKING status Moto Frenzy [Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen]
This commit is contained in:
parent
d881a058e4
commit
1c684345f3
@ -5,6 +5,9 @@
|
|||||||
Atari GX2 hardware
|
Atari GX2 hardware
|
||||||
|
|
||||||
driver by Aaron Giles
|
driver by Aaron Giles
|
||||||
|
|
||||||
|
Moto Frenzy protection reverse engineered by:
|
||||||
|
Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen
|
||||||
|
|
||||||
Games supported:
|
Games supported:
|
||||||
* Space Lords (1992)
|
* Space Lords (1992)
|
||||||
@ -12,7 +15,7 @@
|
|||||||
* Road Riot's Revenge Rally (1993)
|
* Road Riot's Revenge Rally (1993)
|
||||||
|
|
||||||
Known bugs:
|
Known bugs:
|
||||||
* protection devices unknown
|
* Unemulated protection for Space Lords and Road Riot's Revenge
|
||||||
|
|
||||||
****************************************************************************
|
****************************************************************************
|
||||||
|
|
||||||
@ -125,10 +128,11 @@ WRITE32_MEMBER(atarigx2_state::mo_command_w)
|
|||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
*
|
*
|
||||||
* Protection?
|
* Protection (non-working, legacy)
|
||||||
*
|
*
|
||||||
*************************************/
|
*************************************/
|
||||||
|
|
||||||
|
/* Note: Will all eventually be handled in machine/atarixga.cpp */
|
||||||
|
|
||||||
WRITE32_MEMBER(atarigx2_state::atarigx2_protection_w)
|
WRITE32_MEMBER(atarigx2_state::atarigx2_protection_w)
|
||||||
{
|
{
|
||||||
@ -143,16 +147,16 @@ WRITE32_MEMBER(atarigx2_state::atarigx2_protection_w)
|
|||||||
logerror("%06X:Protection W@%04X = %04X\n", pc, offset * 4 + 2, data);
|
logerror("%06X:Protection W@%04X = %04X\n", pc, offset * 4 + 2, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
COMBINE_DATA(&m_protection_base[offset]);
|
COMBINE_DATA(&m_protection_ram[offset]);
|
||||||
|
|
||||||
if (ACCESSING_BITS_16_31)
|
if (ACCESSING_BITS_16_31)
|
||||||
{
|
{
|
||||||
m_last_write = m_protection_base[offset] >> 16;
|
m_last_write = m_protection_ram[offset] >> 16;
|
||||||
m_last_write_offset = offset*2;
|
m_last_write_offset = offset*2;
|
||||||
}
|
}
|
||||||
if (ACCESSING_BITS_0_15)
|
if (ACCESSING_BITS_0_15)
|
||||||
{
|
{
|
||||||
m_last_write = m_protection_base[offset] & 0xffff;
|
m_last_write = m_protection_ram[offset] & 0xffff;
|
||||||
m_last_write_offset = offset*2+1;
|
m_last_write_offset = offset*2+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1138,7 +1142,7 @@ READ32_MEMBER(atarigx2_state::atarigx2_protection_r)
|
|||||||
{ 0xffffffff, 0xffff }
|
{ 0xffffffff, 0xffff }
|
||||||
};
|
};
|
||||||
|
|
||||||
UINT32 result = m_protection_base[offset];
|
UINT32 result = m_protection_ram[offset];
|
||||||
|
|
||||||
if (offset == 0x300)
|
if (offset == 0x300)
|
||||||
result |= 0x80000000;
|
result |= 0x80000000;
|
||||||
@ -1175,6 +1179,12 @@ READ32_MEMBER(atarigx2_state::atarigx2_protection_r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
READ32_MEMBER( atarigx2_state::rrreveng_prot_r )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
*
|
*
|
||||||
* Main CPU memory handlers
|
* Main CPU memory handlers
|
||||||
@ -1185,7 +1195,6 @@ static ADDRESS_MAP_START( main_map, AS_PROGRAM, 32, atarigx2_state )
|
|||||||
ADDRESS_MAP_UNMAP_HIGH
|
ADDRESS_MAP_UNMAP_HIGH
|
||||||
AM_RANGE(0x000000, 0x07ffff) AM_ROM
|
AM_RANGE(0x000000, 0x07ffff) AM_ROM
|
||||||
AM_RANGE(0xc80000, 0xc80fff) AM_RAM
|
AM_RANGE(0xc80000, 0xc80fff) AM_RAM
|
||||||
AM_RANGE(0xca0000, 0xca0fff) AM_READWRITE(atarigx2_protection_r, atarigx2_protection_w) AM_SHARE("protection_base")
|
|
||||||
AM_RANGE(0xd00000, 0xd1ffff) AM_READ(a2d_data_r)
|
AM_RANGE(0xd00000, 0xd1ffff) AM_READ(a2d_data_r)
|
||||||
AM_RANGE(0xd20000, 0xd20fff) AM_DEVREADWRITE8("eeprom", atari_eeprom_device, read, write, 0xff00ff00)
|
AM_RANGE(0xd20000, 0xd20fff) AM_DEVREADWRITE8("eeprom", atari_eeprom_device, read, write, 0xff00ff00)
|
||||||
AM_RANGE(0xd40000, 0xd40fff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
|
AM_RANGE(0xd40000, 0xd40fff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
|
||||||
@ -1459,6 +1468,8 @@ static MACHINE_CONFIG_START( atarigx2, atarigx2_state )
|
|||||||
|
|
||||||
MCFG_MACHINE_RESET_OVERRIDE(atarigx2_state,atarigx2)
|
MCFG_MACHINE_RESET_OVERRIDE(atarigx2_state,atarigx2)
|
||||||
|
|
||||||
|
MCFG_DEVICE_ADD("xga", ATARI_XGA, 0);
|
||||||
|
|
||||||
MCFG_ATARI_EEPROM_2816_ADD("eeprom")
|
MCFG_ATARI_EEPROM_2816_ADD("eeprom")
|
||||||
|
|
||||||
/* video hardware */
|
/* video hardware */
|
||||||
@ -2209,6 +2220,7 @@ ROM_END
|
|||||||
DRIVER_INIT_MEMBER(atarigx2_state,spclords)
|
DRIVER_INIT_MEMBER(atarigx2_state,spclords)
|
||||||
{
|
{
|
||||||
m_playfield_base = 0x000;
|
m_playfield_base = 0x000;
|
||||||
|
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xca0000, 0xca0fff, read32_delegate(FUNC(atarigx2_state::atarigx2_protection_r),this), write32_delegate(FUNC(atarigx2_state::atarigx2_protection_w),this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2237,22 +2249,18 @@ XMEM=68.A23*E.A22*!E.A21*68.A20 = 1101 xxxx = d0
|
|||||||
+68.A23*E.A22*!E.A21*!68.A20*68.A19 = 1100 1xxx = c80000-cfffff
|
+68.A23*E.A22*!E.A21*!68.A20*68.A19 = 1100 1xxx = c80000-cfffff
|
||||||
+!68.A23*!E.A22*!E.A21 = 000x xxxx = 000000-1fffff
|
+!68.A23*!E.A22*!E.A21 = 000x xxxx = 000000-1fffff
|
||||||
*/
|
*/
|
||||||
}
|
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xca0000, 0xca0fff, read32_delegate(FUNC(atari_xga_device::read),&(*m_xga)), write32_delegate(FUNC(atari_xga_device::write),&(*m_xga)));
|
||||||
|
|
||||||
READ32_MEMBER(atarigx2_state::rrreveng_prot_r)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DRIVER_INIT_MEMBER(atarigx2_state,rrreveng)
|
DRIVER_INIT_MEMBER(atarigx2_state,rrreveng)
|
||||||
{
|
{
|
||||||
m_playfield_base = 0x000;
|
m_playfield_base = 0x000;
|
||||||
|
|
||||||
|
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xca0000, 0xca0fff, read32_delegate(FUNC(atarigx2_state::atarigx2_protection_r),this), write32_delegate(FUNC(atarigx2_state::atarigx2_protection_w),this));
|
||||||
m_maincpu->space(AS_PROGRAM).install_read_handler(0xca0fc0, 0xca0fc3, read32_delegate(FUNC(atarigx2_state::rrreveng_prot_r),this));
|
m_maincpu->space(AS_PROGRAM).install_read_handler(0xca0fc0, 0xca0fc3, read32_delegate(FUNC(atarigx2_state::rrreveng_prot_r),this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
*
|
*
|
||||||
* Game driver(s)
|
* Game driver(s)
|
||||||
@ -2264,10 +2272,10 @@ GAME( 1992, spclordsb, spclords, atarigx2_0x400, spclords, atarigx2_state, spclo
|
|||||||
GAME( 1992, spclordsg, spclords, atarigx2_0x400, spclords, atarigx2_state, spclords, ROT0, "Atari Games", "Space Lords (rev A, German)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING )
|
GAME( 1992, spclordsg, spclords, atarigx2_0x400, spclords, atarigx2_state, spclords, ROT0, "Atari Games", "Space Lords (rev A, German)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING )
|
||||||
GAME( 1992, spclordsa, spclords, atarigx2_0x400, spclords, atarigx2_state, spclords, ROT0, "Atari Games", "Space Lords (rev A)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING )
|
GAME( 1992, spclordsa, spclords, atarigx2_0x400, spclords, atarigx2_state, spclords, ROT0, "Atari Games", "Space Lords (rev A)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING )
|
||||||
|
|
||||||
GAME( 1992, motofren, 0, atarigx2_0x200, motofren, atarigx2_state, motofren, ROT0, "Atari Games", "Moto Frenzy", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING )
|
GAME( 1992, motofren, 0, atarigx2_0x200, motofren, atarigx2_state, motofren, ROT0, "Atari Games", "Moto Frenzy", 0 )
|
||||||
GAME( 1992, motofrenmd, motofren, atarigx2_0x200, motofren, atarigx2_state, motofren, ROT0, "Atari Games", "Moto Frenzy (Mini Deluxe)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING )
|
GAME( 1992, motofrenmd, motofren, atarigx2_0x200, motofren, atarigx2_state, motofren, ROT0, "Atari Games", "Moto Frenzy (Mini Deluxe)", 0 )
|
||||||
GAME( 1992, motofrenft, motofren, atarigx2_0x200, motofren, atarigx2_state, motofren, ROT0, "Atari Games", "Moto Frenzy (Field Test Version)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING )
|
GAME( 1992, motofrenft, motofren, atarigx2_0x200, motofren, atarigx2_state, motofren, ROT0, "Atari Games", "Moto Frenzy (Field Test Version)", 0 )
|
||||||
GAME( 1992, motofrenmf, motofren, atarigx2_0x200, motofren, atarigx2_state, motofren, ROT0, "Atari Games", "Moto Frenzy (Mini Deluxe Field Test Version)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING )
|
GAME( 1992, motofrenmf, motofren, atarigx2_0x200, motofren, atarigx2_state, motofren, ROT0, "Atari Games", "Moto Frenzy (Mini Deluxe Field Test Version)", 0 )
|
||||||
|
|
||||||
GAME( 1993, rrreveng, 0, atarigx2_0x400, rrreveng, atarigx2_state, rrreveng, ROT0, "Atari Games", "Road Riot's Revenge (prototype, Sep 06, 1994)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING )
|
GAME( 1993, rrreveng, 0, atarigx2_0x400, rrreveng, atarigx2_state, rrreveng, ROT0, "Atari Games", "Road Riot's Revenge (prototype, Sep 06, 1994)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING )
|
||||||
GAME( 1993, rrrevenga, rrreveng, atarigx2_0x400, rrreveng, atarigx2_state, rrreveng, ROT0, "Atari Games", "Road Riot's Revenge (prototype, Jan 27, 1994, set 1)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING )
|
GAME( 1993, rrrevenga, rrreveng, atarigx2_0x400, rrreveng, atarigx2_state, rrreveng, ROT0, "Atari Games", "Road Riot's Revenge (prototype, Jan 27, 1994, set 1)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING )
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
#include "machine/atarigen.h"
|
#include "machine/atarigen.h"
|
||||||
|
#include "machine/atarixga.h"
|
||||||
#include "audio/atarijsa.h"
|
#include "audio/atarijsa.h"
|
||||||
#include "includes/slapstic.h"
|
|
||||||
|
|
||||||
|
|
||||||
class atarigx2_state : public atarigen_state
|
class atarigx2_state : public atarigen_state
|
||||||
@ -17,8 +17,8 @@ public:
|
|||||||
atarigx2_state(const machine_config &mconfig, device_type type, const char *tag)
|
atarigx2_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||||
: atarigen_state(mconfig, type, tag),
|
: atarigen_state(mconfig, type, tag),
|
||||||
m_jsa(*this, "jsa"),
|
m_jsa(*this, "jsa"),
|
||||||
|
m_xga(*this, "xga"),
|
||||||
m_mo_command(*this, "mo_command"),
|
m_mo_command(*this, "mo_command"),
|
||||||
m_protection_base(*this, "protection_base"),
|
|
||||||
m_playfield_tilemap(*this, "playfield"),
|
m_playfield_tilemap(*this, "playfield"),
|
||||||
m_alpha_tilemap(*this, "alpha"),
|
m_alpha_tilemap(*this, "alpha"),
|
||||||
m_rle(*this, "rle")
|
m_rle(*this, "rle")
|
||||||
@ -27,9 +27,9 @@ public:
|
|||||||
UINT16 m_playfield_base;
|
UINT16 m_playfield_base;
|
||||||
|
|
||||||
required_device<atari_jsa_iiis_device> m_jsa;
|
required_device<atari_jsa_iiis_device> m_jsa;
|
||||||
|
required_device<atari_xga_device> m_xga;
|
||||||
|
|
||||||
required_shared_ptr<UINT32> m_mo_command;
|
required_shared_ptr<UINT32> m_mo_command;
|
||||||
required_shared_ptr<UINT32> m_protection_base;
|
|
||||||
|
|
||||||
required_device<tilemap_device> m_playfield_tilemap;
|
required_device<tilemap_device> m_playfield_tilemap;
|
||||||
required_device<tilemap_device> m_alpha_tilemap;
|
required_device<tilemap_device> m_alpha_tilemap;
|
||||||
@ -41,8 +41,10 @@ public:
|
|||||||
UINT16 m_playfield_xscroll;
|
UINT16 m_playfield_xscroll;
|
||||||
UINT16 m_playfield_yscroll;
|
UINT16 m_playfield_yscroll;
|
||||||
|
|
||||||
|
// LEGACY PROTECTION
|
||||||
UINT16 m_last_write;
|
UINT16 m_last_write;
|
||||||
UINT16 m_last_write_offset;
|
UINT16 m_last_write_offset;
|
||||||
|
UINT32 m_protection_ram[0x1000];
|
||||||
|
|
||||||
virtual void update_interrupts() override;
|
virtual void update_interrupts() override;
|
||||||
virtual void scanline_update(screen_device &screen, int scanline) override;
|
virtual void scanline_update(screen_device &screen, int scanline) override;
|
||||||
|
299
src/mame/machine/atarixga.cpp
Normal file
299
src/mame/machine/atarixga.cpp
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen
|
||||||
|
/*************************************************************************
|
||||||
|
|
||||||
|
atarixga.cpp
|
||||||
|
|
||||||
|
Atari XGA encryption FPGA
|
||||||
|
|
||||||
|
**************************************************************************
|
||||||
|
|
||||||
|
Part numbers:
|
||||||
|
|
||||||
|
136094-0072 Moto Frenzy
|
||||||
|
136095-0072 Space Lords
|
||||||
|
? Road Riot's Revenge
|
||||||
|
136094-0004A Primal Rage
|
||||||
|
? T-Mek
|
||||||
|
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
#include "atarixga.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern const device_type ATARI_XGA = &device_creator<atari_xga_device>;
|
||||||
|
|
||||||
|
atari_xga_device::atari_xga_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
|
: device_t(mconfig, ATARI_XGA, "Atari XGA", tag, owner, clock, "xga", __FILE__),
|
||||||
|
m_mode(FPGA_RESET),
|
||||||
|
m_address(0),
|
||||||
|
m_ciphertext(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************
|
||||||
|
*
|
||||||
|
* Initialization
|
||||||
|
*
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
void atari_xga_device::device_start()
|
||||||
|
{
|
||||||
|
m_ram = std::make_unique<UINT16[]>(RAM_WORDS);
|
||||||
|
|
||||||
|
save_pointer(NAME(m_ram.get()), RAM_WORDS * sizeof(UINT16));
|
||||||
|
save_item(NAME(m_address));
|
||||||
|
save_item(NAME(m_ciphertext));
|
||||||
|
}
|
||||||
|
|
||||||
|
void atari_xga_device::device_reset()
|
||||||
|
{
|
||||||
|
memset(m_ram.get(), 0, RAM_WORDS * sizeof(UINT16));
|
||||||
|
m_mode = FPGA_RESET;
|
||||||
|
m_address = 0;
|
||||||
|
m_ciphertext = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************
|
||||||
|
*
|
||||||
|
* Definitions
|
||||||
|
*
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
// TODO: Add definitions for other games
|
||||||
|
// Moto Frenzy
|
||||||
|
|
||||||
|
/* key 0x10 is special, it has 15 "identical twins". */
|
||||||
|
static const UINT8 kmap[128] =
|
||||||
|
{
|
||||||
|
0x6B,0x11,0x1B,0x19,0x4B,0x50,0x17,0x09,
|
||||||
|
0x5D,0x69,0x43,0x33,0x0F,0x0C,0x28,0x3F,
|
||||||
|
0x00,0x20,0x15,0x3C,0x57,0x38,0x00,0x07,
|
||||||
|
0x49,0x25,0x61,0x2F,0x2B,0x4E,0x64,0x00,
|
||||||
|
0x45,0x41,0x6D,0x52,0x31,0x66,0x22,0x59,
|
||||||
|
0x00,0x70,0x6F,0x5B,0x46,0x6E,0x67,0x5A,
|
||||||
|
0x26,0x30,0x2C,0x65,0x21,0x3D,0x58,0x00,
|
||||||
|
0x5E,0x44,0x0D,0x40,0x6C,0x1C,0x51,0x0A,
|
||||||
|
0x35,0x2A,0x13,0x4D,0x63,0x00,0x00,0x3A,
|
||||||
|
0x00,0x48,0x54,0x24,0x60,0x1E,0x2E,0x01,
|
||||||
|
0x56,0x03,0x37,0x00,0x04,0x00,0x05,0x06,
|
||||||
|
0x00,0x55,0x1F,0x02,0x36,0x14,0x00,0x3B,
|
||||||
|
0x5F,0x0E,0x1D,0x0B,0x27,0x2D,0x3E,0x00,
|
||||||
|
0x00,0x5C,0x47,0x68,0x42,0x53,0x32,0x23,
|
||||||
|
0x4A,0x62,0x4F,0x00,0x00,0x16,0x39,0x08,
|
||||||
|
0x6A,0x34,0x10,0x29,0x12,0x1A,0x4C,0x18
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************
|
||||||
|
*
|
||||||
|
* Decryption
|
||||||
|
*
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
UINT16 atari_xga_device::ctz(UINT16 x)
|
||||||
|
{
|
||||||
|
UINT16 n = 0;
|
||||||
|
if (x == 0) return 16;
|
||||||
|
if (!(x & 0x00FF)) n += 8, x >>= 8;
|
||||||
|
if (!(x & 0x000F)) n += 4, x >>= 4;
|
||||||
|
if (!(x & 0x0003)) n += 2, x >>= 2;
|
||||||
|
if (!(x & 0x0001)) n += 1, x >>= 1;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t atari_xga_device::popcount(UINT16 x)
|
||||||
|
{
|
||||||
|
size_t count = 0;
|
||||||
|
while (x != 0)
|
||||||
|
{
|
||||||
|
count += 1;
|
||||||
|
x &= x - 1;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16 atari_xga_device::parity(UINT16 x)
|
||||||
|
{
|
||||||
|
return popcount(x) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16 atari_xga_device::lfsr1(UINT16 x)
|
||||||
|
{
|
||||||
|
UINT16 bit = parity(x & 0x8016);
|
||||||
|
return (x << 1) | bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16 atari_xga_device::lfsr2(UINT16 x)
|
||||||
|
{
|
||||||
|
UINT16 bit = parity(x & 0x002D);
|
||||||
|
return (x >> 1) | (bit << 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16 atari_xga_device::powers2(UINT8 k, UINT16 x)
|
||||||
|
{
|
||||||
|
static const UINT16 L[16] =
|
||||||
|
{
|
||||||
|
0x5E85,0xBD0B,0x2493,0x17A3,
|
||||||
|
0x2F47,0x0005,0x000B,0x0017,
|
||||||
|
0x002F,0x005E,0x00BD,0x017A,
|
||||||
|
0x02F4,0x05E8,0x0BD0,0x17A1
|
||||||
|
};
|
||||||
|
|
||||||
|
UINT16 t = (x == 16) ? (L[4] ^ L[5]) : L[x];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < k; ++i)
|
||||||
|
{
|
||||||
|
t = lfsr1(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16 atari_xga_device::decipher(UINT8 k, UINT16 c)
|
||||||
|
{
|
||||||
|
UINT16 bit, i, p = 0;
|
||||||
|
|
||||||
|
/* Only 128 keys internally, if high bit set,
|
||||||
|
then find the 7-bit "twin" by xor 0xA8. */
|
||||||
|
if (k & 0x80)
|
||||||
|
k ^= 0xA8;
|
||||||
|
|
||||||
|
k = kmap[k];
|
||||||
|
|
||||||
|
if ((c & (c - 1)) == 0)
|
||||||
|
{
|
||||||
|
return powers2(k, ctz(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bit = 0; bit < 5; ++bit)
|
||||||
|
{
|
||||||
|
if ((c >> bit) & 1)
|
||||||
|
{
|
||||||
|
p ^= powers2(k, bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bit = 5; bit < 16; ++bit)
|
||||||
|
{
|
||||||
|
if ((c >> bit) & 1)
|
||||||
|
{
|
||||||
|
p ^= powers2(k, bit + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16 x = 0x8010;
|
||||||
|
for (i = 0; i < k + 3; ++i)
|
||||||
|
{
|
||||||
|
if (x == c)
|
||||||
|
{
|
||||||
|
return (p == 1) ? 0 : lfsr2(p);
|
||||||
|
}
|
||||||
|
x = lfsr2(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************
|
||||||
|
*
|
||||||
|
* Write/Read access
|
||||||
|
*
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
WRITE32_MEMBER(atari_xga_device::write)
|
||||||
|
{
|
||||||
|
switch (m_mode)
|
||||||
|
{
|
||||||
|
case FPGA_RESET:
|
||||||
|
return;
|
||||||
|
|
||||||
|
case FPGA_SETKEY:
|
||||||
|
/* Write table to FPGA SRAM. */
|
||||||
|
if (ACCESSING_BITS_16_31)
|
||||||
|
m_ram[offset << 1] = UINT16 (data >> 16);
|
||||||
|
if (ACCESSING_BITS_0_15)
|
||||||
|
m_ram[(offset << 1) + 1] = UINT16(data & 0xFFFF);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FPGA_DECIPHER:
|
||||||
|
/* Send Ciphertext to FPGA for decryption. */
|
||||||
|
if (ACCESSING_BITS_16_31)
|
||||||
|
{
|
||||||
|
m_address = offset << 2;
|
||||||
|
m_ciphertext = UINT16(data >> 16);
|
||||||
|
}
|
||||||
|
if (ACCESSING_BITS_0_15)
|
||||||
|
{
|
||||||
|
m_address = (offset << 2) + 2;
|
||||||
|
m_ciphertext = UINT16(data & 0xFFFF);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
READ32_MEMBER(atari_xga_device::read)
|
||||||
|
{
|
||||||
|
UINT32 plaintext = 0;
|
||||||
|
|
||||||
|
switch (offset << 2)
|
||||||
|
{
|
||||||
|
case 0x0FC0:
|
||||||
|
m_mode = FPGA_RESET;
|
||||||
|
break;
|
||||||
|
case 0x0010:
|
||||||
|
m_mode = FPGA_SETKEY;
|
||||||
|
break;
|
||||||
|
case 0x0020:
|
||||||
|
m_mode = FPGA_DECIPHER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_mode == FPGA_RESET)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_mode == FPGA_DECIPHER)
|
||||||
|
{
|
||||||
|
UINT16 address = (offset << 2) - 0x400;
|
||||||
|
|
||||||
|
if (ACCESSING_BITS_0_15)
|
||||||
|
address += 2;
|
||||||
|
|
||||||
|
/* Reply with decrypted plaintext */
|
||||||
|
if (address == m_address)
|
||||||
|
{
|
||||||
|
UINT16 key_offset, key_byte;
|
||||||
|
|
||||||
|
/* Algorithm to select key byte based on offset. */
|
||||||
|
key_offset = ((((address >> 4) & 1) ^ 1) << 0)
|
||||||
|
^ ((((address >> 2) & 1) ^ 0) << 1)
|
||||||
|
^ ((((address >> 8) & 1) ^ 0) << 2)
|
||||||
|
^ ((((address >> 3) & 1) ^ 1) << 3)
|
||||||
|
^ ((((address >> 1) & 1) ^ 1) << 4)
|
||||||
|
^ ((((address >> 6) & 1) ^ 0) << 5)
|
||||||
|
^ ((((address >> 7) & 1) ^ 0) << 6)
|
||||||
|
^ ((((address >> 5) & 1) ^ 1) << 7)
|
||||||
|
^ ((((address >> 9) & 1) ^ 0) << 8)
|
||||||
|
^ ((((address >> 10) & 1) ^ 0) << 9);
|
||||||
|
key_byte = m_ram[key_offset];
|
||||||
|
|
||||||
|
/* And now for the full magic. */
|
||||||
|
plaintext = decipher(key_byte, m_ciphertext);
|
||||||
|
|
||||||
|
if (ACCESSING_BITS_16_31)
|
||||||
|
plaintext <<= 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return plaintext;
|
||||||
|
}
|
54
src/mame/machine/atarixga.h
Normal file
54
src/mame/machine/atarixga.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen
|
||||||
|
/*************************************************************************
|
||||||
|
|
||||||
|
atarixga.h
|
||||||
|
|
||||||
|
Atari XGA encryption FPGA
|
||||||
|
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __MACHINE_ATARIXGA__
|
||||||
|
#define __MACHINE_ATARIXGA__
|
||||||
|
|
||||||
|
extern const device_type ATARI_XGA;
|
||||||
|
|
||||||
|
class atari_xga_device : public device_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// construction/destruction
|
||||||
|
atari_xga_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
DECLARE_WRITE32_MEMBER(write);
|
||||||
|
DECLARE_READ32_MEMBER(read);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void device_start() override;
|
||||||
|
virtual void device_reset() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const size_t RAM_WORDS = 2048;
|
||||||
|
|
||||||
|
enum fpga_mode
|
||||||
|
{
|
||||||
|
FPGA_RESET,
|
||||||
|
FPGA_SETKEY,
|
||||||
|
FPGA_DECIPHER
|
||||||
|
};
|
||||||
|
|
||||||
|
UINT16 powers2(UINT8 k, UINT16 x);
|
||||||
|
UINT16 lfsr2(UINT16 x);
|
||||||
|
UINT16 lfsr1(UINT16 x);
|
||||||
|
UINT16 parity(UINT16 x);
|
||||||
|
size_t popcount(UINT16 x);
|
||||||
|
UINT16 ctz(UINT16 x);
|
||||||
|
UINT16 decipher(UINT8 k, UINT16 c);
|
||||||
|
|
||||||
|
fpga_mode m_mode;
|
||||||
|
UINT16 m_address; // last written address
|
||||||
|
UINT16 m_ciphertext; // last written ciphertext
|
||||||
|
std::unique_ptr<UINT16[]> m_ram; // CY7C185-45PC, only 16-Kbit used
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user