mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
igs017.cpp: Improved protection and decryption [Luca Elia]
- Implemented "magic" i/o as a memory map (IGS_MUX) for added flexibility - Hooked up IGS_INCDEC protection to cpoker2, tarzanc, spkrform, starzan - Implemented specific IGS_INC protection in cpoker2 - Hooked up improved IGS022 protection to lhzb2, sqlz2 - Added IGS025 string protection to lhzb2, lhzb2a, mgcs, spkrform, slqz2, starzan, tarzanc, tjsb - Palette scramble and tweaked tiles decryption in tarzanc (used also by starzan, happyskl, cpoker2) - Decrypted sprites in tarzanc and starzan (used also by happyskl) - Lamps and layout for starzan, happyskl, cpoker2 - Cleaned up/finished hopper emulation, added diplocations - Joystick inputs in mgcs - Finished inputs in spkrform. Allow hiding gambling (switching to Formosa and back) igs022.cpp: Fixes for igs017.cpp games [Luca Elia, RockyWall] - Fixed initial auto-DMA mode - Enlarged internal RAM. Added stack - Fixed command 12: Copy -> Stack Push - Added command 45: Stack Pop - Fixed command 6d opcode 1: Add Imm -> Sub Values - Added command 6d opcode 0: Add Values - Extended logging Machines promoted to working ---------------------------- Tarzan Chuang Tian Guan (China, V109C, set 1) [Luca Elia, iq_132, Ivan Vangelista, Guru, Dyq, bnathan] Super Tarzan (Italy, V100I) [Luca Elia, iq_132, Ivan Vangelista, f205v, Mirko Buffoni] Happy Skill (Italy, V611IT) [Luca Elia, Ivan Vangelista, Caius, The Dumping Union] Champion Poker 2 (V100A) [Luca Elia, Ivan Vangelista, Jorge Silva, Fernando Oliveira] Long Hu Zhengba 2 (China, set 1) [Luca Elia, RockyWall, David Haywood, iq_132, Pierpaolo Prazzoli, XingXing] Shuang Long Qiang Zhu 2 VS (China, VS203J) [Luca Elia, RockyWall, David Haywood, iq_132, Pierpaolo Prazzoli, XingXing] Clones promoted to working -------------------------- Super Poker (V100xD03) / Formosa [Luca Elia, ANY]
This commit is contained in:
parent
1d19337feb
commit
ec3cd170e7
File diff suppressed because it is too large
Load Diff
132
src/mame/layout/igsslot.lay
Normal file
132
src/mame/layout/igsslot.lay
Normal file
@ -0,0 +1,132 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
license:CC0
|
||||
-->
|
||||
<mamelayout version="2">
|
||||
<element name="L1" defstate="1">
|
||||
<rect state="1">
|
||||
<color red="0.0" green="1.0" blue="0.0" />
|
||||
</rect>
|
||||
<rect state="0">
|
||||
<color red="0.0" green="0.2" blue="0.0" />
|
||||
</rect>
|
||||
<text string="TAKE">
|
||||
<color red="0.0" green="0.0" blue="0.0" />
|
||||
<bounds x="0" y="0.1" width="1" height="0.4" />
|
||||
</text>
|
||||
<text string="STOP1">
|
||||
<color red="0.0" green="0.0" blue="0.0" />
|
||||
<bounds x="0" y="0.5" width="1" height="0.4" />
|
||||
</text>
|
||||
</element>
|
||||
|
||||
<element name="L2" defstate="1">
|
||||
<rect state="1">
|
||||
<color red="0.0" green="1.0" blue="0.0" />
|
||||
</rect>
|
||||
<rect state="0">
|
||||
<color red="0.0" green="0.2" blue="0.0" />
|
||||
</rect>
|
||||
<text string="HIGH">
|
||||
<color red="0.0" green="0.0" blue="0.0" />
|
||||
<bounds x="0" y="0.1" width="1" height="0.4" />
|
||||
</text>
|
||||
<text string="STOP2">
|
||||
<color red="0.0" green="0.0" blue="0.0" />
|
||||
<bounds x="0" y="0.5" width="1" height="0.4" />
|
||||
</text>
|
||||
</element>
|
||||
|
||||
<element name="L3" defstate="1">
|
||||
<rect state="1">
|
||||
<color red="0.0" green="1.0" blue="0.0" />
|
||||
</rect>
|
||||
<rect state="0">
|
||||
<color red="0.0" green="0.2" blue="0.0" />
|
||||
</rect>
|
||||
<text string="LOW">
|
||||
<color red="0.0" green="0.0" blue="0.0" />
|
||||
<bounds x="0" y="0.1" width="1" height="0.4" />
|
||||
</text>
|
||||
<text string="STOP3">
|
||||
<color red="0.0" green="0.0" blue="0.0" />
|
||||
<bounds x="0" y="0.5" width="1" height="0.4" />
|
||||
</text>
|
||||
</element>
|
||||
|
||||
<element name="L4" defstate="1">
|
||||
<rect state="1">
|
||||
<color red="0.0" green="1.0" blue="0.0" />
|
||||
</rect>
|
||||
<rect state="0">
|
||||
<color red="0.0" green="0.2" blue="0.0" />
|
||||
</rect>
|
||||
<text string="W-UP">
|
||||
<color red="0.0" green="0.0" blue="0.0" />
|
||||
<bounds x="0" y="0.1" width="1" height="0.4" />
|
||||
</text>
|
||||
<text string="STOP4">
|
||||
<color red="0.0" green="0.0" blue="0.0" />
|
||||
<bounds x="0" y="0.5" width="1" height="0.4" />
|
||||
</text>
|
||||
</element>
|
||||
|
||||
<element name="L5" defstate="1">
|
||||
<rect state="1">
|
||||
<color red="0.0" green="1.0" blue="0.0" />
|
||||
</rect>
|
||||
<rect state="0">
|
||||
<color red="0.0" green="0.2" blue="0.0" />
|
||||
</rect>
|
||||
<text string="BET / 2W-UP">
|
||||
<color red="0.0" green="0.0" blue="0.0" />
|
||||
<bounds x="0" y="0.1" width="1" height="0.4" />
|
||||
</text>
|
||||
<text string="STOP ALL">
|
||||
<color red="0.0" green="0.0" blue="0.0" />
|
||||
<bounds x="0" y="0.5" width="1" height="0.4" />
|
||||
</text>
|
||||
</element>
|
||||
|
||||
<element name="L6" defstate="1">
|
||||
<rect state="1">
|
||||
<color red="1.0" green="0.0" blue="0.0" />
|
||||
</rect>
|
||||
<rect state="0">
|
||||
<color red="0.3" green="0.0" blue="0.0" />
|
||||
</rect>
|
||||
<text string="HW-UP">
|
||||
<color red="0.0" green="0.0" blue="0.0" />
|
||||
<bounds x="0" y="0.1" width="1" height="0.4" />
|
||||
</text>
|
||||
<text string="START">
|
||||
<color red="0.0" green="0.0" blue="0.0" />
|
||||
<bounds x="0" y="0.5" width="1" height="0.4" />
|
||||
</text>
|
||||
</element>
|
||||
|
||||
|
||||
<view name="Button Lamps">
|
||||
<screen index="0">
|
||||
<bounds left="0" top="0" right="4" bottom="3" />
|
||||
</screen>
|
||||
<element name="lamp1" ref="L1">
|
||||
<bounds x="0.5" y="3.13" width="0.40" height="0.24" />
|
||||
</element>
|
||||
<element name="lamp2" ref="L2">
|
||||
<bounds x="1.0" y="3.13" width="0.40" height="0.24" />
|
||||
</element>
|
||||
<element name="lamp3" ref="L3">
|
||||
<bounds x="1.5" y="3.13" width="0.40" height="0.24" />
|
||||
</element>
|
||||
<element name="lamp4" ref="L4">
|
||||
<bounds x="2.0" y="3.13" width="0.40" height="0.24" />
|
||||
</element>
|
||||
<element name="lamp5" ref="L5">
|
||||
<bounds x="2.5" y="3.13" width="0.40" height="0.24" />
|
||||
</element>
|
||||
<element name="lamp6" ref="L6">
|
||||
<bounds x="3.0" y="3.13" width="0.40" height="0.24" />
|
||||
</element>
|
||||
</view>
|
||||
</mamelayout>
|
@ -1,17 +1,15 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood, ElSemi
|
||||
/*
|
||||
/************************************************************************************************************
|
||||
|
||||
IGS022 is an encrypted DMA device, most likely an MCU of some sort
|
||||
it can safely be swapped between games so doesn't appear to have
|
||||
any kind of game specific programming
|
||||
IGS022 is an encrypted DMA device, most likely an MCU of some sort.
|
||||
It can safely be swapped between games, so doesn't appear to have any kind of game specific programming.
|
||||
|
||||
*/
|
||||
************************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "igs022.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
igs022_device::igs022_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, IGS022, tag, owner, clock)
|
||||
@ -22,76 +20,86 @@ igs022_device::igs022_device(const machine_config &mconfig, const char *tag, dev
|
||||
|
||||
void igs022_device::device_start()
|
||||
{
|
||||
// Reset stuff
|
||||
std::fill(std::begin(m_kb_regs), std::end(m_kb_regs), 0);
|
||||
std::fill(std::begin(m_regs), std::end(m_regs), 0);
|
||||
|
||||
save_item(NAME(m_kb_regs));
|
||||
save_item(NAME(m_regs));
|
||||
save_item(NAME(m_stack));
|
||||
save_item(NAME(m_stack_ptr));
|
||||
}
|
||||
|
||||
void igs022_device::device_reset()
|
||||
{
|
||||
//printf("igs022_device::device_reset()");
|
||||
logerror("%s: IGS022 Reset\n", machine().describe_context());
|
||||
|
||||
std::fill(std::begin(m_regs), std::end(m_regs), 0);
|
||||
std::fill(std::begin(m_stack), std::end(m_stack), 0);
|
||||
m_stack_ptr = 0;
|
||||
|
||||
if (!m_sharedprotram)
|
||||
{
|
||||
logerror("m_sharedprotram was not set\n");
|
||||
logerror("%s: IGS022 m_sharedprotram was not set!\n", machine().describe_context());
|
||||
return;
|
||||
}
|
||||
IGS022_reset();
|
||||
|
||||
std::fill(std::begin(m_kb_regs), std::end(m_kb_regs), 0);
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
void igs022_device::IGS022_do_dma(u16 src, u16 dst, u16 size, u16 mode)
|
||||
// From IGS022 ROM to shared protection RAM
|
||||
void igs022_device::do_dma(u16 src, u16 dst, u16 size, u16 mode)
|
||||
{
|
||||
//printf("igs022_device::IGS022_do_dma\n");
|
||||
logerror("%s: IGS022 DMA src %04x, dst %04x, size %04x, mode %04x\n", machine().describe_context(), src, dst, size, mode);
|
||||
|
||||
/*
|
||||
P_SRC =0x300290 (offset from prot rom base)
|
||||
P_DST =0x300292 (words from 0x300000)
|
||||
P_SIZE=0x300294 (words)
|
||||
P_MODE=0x300296
|
||||
P_SRC = 0x300290 (offset from prot rom base)
|
||||
P_DST = 0x300292 (words from 0x300000)
|
||||
P_SIZE = 0x300294 (words)
|
||||
P_MODE = 0x300296
|
||||
|
||||
Mode 5 direct
|
||||
Mode 6 swap nibbles and bytes
|
||||
|
||||
1,2,3 table based ops
|
||||
Mode 0 plain copy
|
||||
Mode 1,2,3 rom table based ops
|
||||
Mode 4 fixed data ('IGS ') based ops
|
||||
Mode 5 swap bytes
|
||||
Mode 6 swap nibbles
|
||||
*/
|
||||
|
||||
const u16 param = mode >> 8;
|
||||
|
||||
// the initial DMA on kilbld has 0x10 set, drgw3 has 0x18 set, not sure how they affect the operation.
|
||||
if (mode & 0x00f8) printf("IGS022_do_dma mode bits %04x set\n", mode & 0x00f8);
|
||||
// the initial auto-DMA on killbld/slqz2/lhzb2 has 0x10 set, drgw3 has 0x18 set, not sure how they affect the operation.
|
||||
if (mode & 0x00f8) logerror("%s: IGS022 DMA mode bits %04x set\n", machine().describe_context(), mode & 0x00f8);
|
||||
|
||||
mode &= 0x7; // what are the other bits?
|
||||
mode &= 0x7; // what are the other bits?
|
||||
|
||||
if ((mode == 0) || (mode == 1) || (mode == 2) || (mode == 3) || (mode == 4))
|
||||
const u16 * const PROTROM = (u16 *)m_rom->base();
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
/* mode3 applies a xor from a 0x100 byte table to the data being
|
||||
transferred
|
||||
case 0: case 1: case 2: case 3: case 4:
|
||||
/*
|
||||
modes 1-3 modify the data being transferred using a 0x100 byte table stored at the start of the protection rom.
|
||||
|
||||
the table is stored at the start of the protection rom.
|
||||
The param used with the mode gives a start offset into the table.
|
||||
|
||||
the param used with the mode gives a start offset into the table
|
||||
|
||||
odd offsets cause an overflow
|
||||
Odd offsets cause an overflow.
|
||||
*/
|
||||
|
||||
const u16 *PROTROM = (u16*)m_rom->base();
|
||||
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
u16 dat2 = PROTROM[src + x];
|
||||
u16 dat = PROTROM[src + x];
|
||||
|
||||
const u8 extraoffset = param & 0xff;
|
||||
const u8* dectable = (u8*)m_rom->base(); // the basic decryption table is at the start of the mcu data rom!
|
||||
const u8 taboff = ((x * 2) + extraoffset) & 0xff; // must allow for overflow in instances of odd offsets
|
||||
u16 extraxor = ((dectable[taboff + 1]) << 8) | (dectable[taboff + 0] << 0);
|
||||
const u8 extraoffset = param & 0xff;
|
||||
const u8 * const dectable = (u8 *)m_rom->base(); // the basic decryption table is at the start of the mcu data rom!
|
||||
const u8 taboff = ((x * 2) + extraoffset) & 0xff; // must allow for overflow in instances of odd offsets
|
||||
|
||||
if (mode == 4)
|
||||
u16 extraxor = ((dectable[taboff + 1]) << 8) | (dectable[taboff + 0] << 0);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
// case 0: plain copy
|
||||
case 1: dat -= extraxor; break;
|
||||
case 2: dat += extraxor; break;
|
||||
case 3: dat ^= extraxor; break;
|
||||
case 4:
|
||||
extraxor = 0;
|
||||
|
||||
if ((x & 0x003) == 0x000) extraxor |= 0x0049; // 'I'
|
||||
if ((x & 0x003) == 0x001) extraxor |= 0x0047; // 'G'
|
||||
if ((x & 0x003) == 0x002) extraxor |= 0x0053; // 'S'
|
||||
@ -101,166 +109,301 @@ void igs022_device::IGS022_do_dma(u16 src, u16 dst, u16 size, u16 mode)
|
||||
if ((x & 0x300) == 0x100) extraxor |= 0x4700; // 'G'
|
||||
if ((x & 0x300) == 0x200) extraxor |= 0x5300; // 'S'
|
||||
if ((x & 0x300) == 0x300) extraxor |= 0x2000; // ' '
|
||||
|
||||
logerror("%s: IGS022 DMA mode 4 -> %06x | %04x (%04x)\n", machine().describe_context(), (dst + x) * 2, dat, (u16)(dat - extraxor));
|
||||
|
||||
dat -= extraxor;
|
||||
break;
|
||||
}
|
||||
|
||||
// mode == 0 plain
|
||||
if (mode == 3) dat2 ^= extraxor;
|
||||
if (mode == 2) dat2 += extraxor;
|
||||
if (mode == 1) dat2 -= extraxor;
|
||||
|
||||
if (mode == 4)
|
||||
{
|
||||
//printf("%06x | %04x (%04x)\n", (dst+x)*2, dat2, (u16)(dat2-extraxor));
|
||||
|
||||
dat2 -= extraxor;
|
||||
}
|
||||
|
||||
m_sharedprotram[dst + x] = dat2;
|
||||
m_sharedprotram[dst + x] = dat;
|
||||
}
|
||||
}
|
||||
else if (mode == 5)
|
||||
{
|
||||
/* mode 5 seems to be a byteswapped copy */
|
||||
const u16 *PROTROM = (u16*)m_rom->base();
|
||||
break;
|
||||
|
||||
case 5: // byteswapped copy
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
u16 dat = PROTROM[src + x];
|
||||
|
||||
dat = ((dat &0x00ff) << 8) | ((dat &0xff00) >> 8);
|
||||
|
||||
m_sharedprotram[dst + x] = dat;
|
||||
}
|
||||
}
|
||||
else if (mode == 6)
|
||||
{
|
||||
/* mode 6 seems to be a nibble swapped copy */
|
||||
const u16 *PROTROM = (u16*)m_rom->base();
|
||||
break;
|
||||
|
||||
case 6: // nibble swapped copy
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
u16 dat = PROTROM[src + x];
|
||||
|
||||
dat = ((dat & 0xf0f0) >> 4)|
|
||||
((dat & 0x0f0f) << 4);
|
||||
dat = ((dat & 0xf0f0) >> 4) | ((dat & 0x0f0f) << 4);
|
||||
|
||||
m_sharedprotram[dst + x] = dat;
|
||||
}
|
||||
}
|
||||
else if (mode == 7)
|
||||
{
|
||||
printf("unhandled copy mode %04x!\n", mode);
|
||||
// not used by killing blade
|
||||
/* weird mode, the params get left in memory? - maybe it's a NOP? */
|
||||
}
|
||||
else
|
||||
{
|
||||
osd_printf_debug("unhandled copy mode %04x!\n", mode);
|
||||
printf ("DMA MODE: %d, src: %4.4x, dst: %4.4x, size: %4.4x, param: %2.2x\n", mode, src, dst, size, param);
|
||||
// not used by killing blade
|
||||
/* invalid? */
|
||||
break;
|
||||
|
||||
case 7:
|
||||
logerror("%s: IGS022 DMA unhandled copy mode %04x!\n", machine().describe_context(), mode);
|
||||
// not used by killbld
|
||||
// weird mode, the params get left in memory? - maybe it's a NOP?
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("%s: IGS022 DMA unhandled copy mode!: %d, src: %04x, dst: %04x, size: %04x, param: %02x\n", machine().describe_context(), mode, src, dst, size, param);
|
||||
// not used by killbld
|
||||
// invalid?
|
||||
}
|
||||
}
|
||||
|
||||
// the internal MCU boot code automatically does this DMA
|
||||
// and puts the version # of the data rom in ram
|
||||
void igs022_device::IGS022_reset()
|
||||
void igs022_device::reset()
|
||||
{
|
||||
const u16 *PROTROM = (u16*)m_rom->base();
|
||||
const u16 * const PROTROM = (u16 *)m_rom->base();
|
||||
|
||||
// fill ram with A5 patern
|
||||
for (int i = 0; i < 0x4000/2; i++)
|
||||
// fill ram with A55A pattern
|
||||
for (int i = 0; i < 0x4000 / 2; i++)
|
||||
m_sharedprotram[i] = 0xa55a;
|
||||
|
||||
// the auto-dma
|
||||
// the initial auto-DMA
|
||||
u16 src = PROTROM[0x100 / 2];
|
||||
const u32 dst = PROTROM[0x102 / 2];
|
||||
const u16 size = PROTROM[0x104 / 2];
|
||||
u16 mode = PROTROM[0x106 / 2];
|
||||
|
||||
mode &= 0xff;
|
||||
mode = (mode >> 8) | (mode << 8);
|
||||
|
||||
src >>= 1;
|
||||
|
||||
IGS022_do_dma(src,dst,size,mode);
|
||||
do_dma(src, dst, size, mode);
|
||||
|
||||
// there is also a version ID? (or is it some kind of checksum) that is stored in the data rom, and gets copied..
|
||||
// Dragon World 3 checks it
|
||||
// Setting $3002a0 to #3 causes Dragon World 3 to skip this check
|
||||
m_sharedprotram[0x2a2/2] = PROTROM[0x114/2];
|
||||
m_sharedprotram[0x2a2 / 2] = PROTROM[0x114 / 2];
|
||||
}
|
||||
|
||||
void igs022_device::IGS022_handle_command()
|
||||
void igs022_device::push_stack(u32 data)
|
||||
{
|
||||
//printf("igs022_device::IGS022_handle_command\n");
|
||||
if (m_stack_ptr < STACK_SIZE - 1)
|
||||
++m_stack_ptr;
|
||||
|
||||
const u16 cmd = m_sharedprotram[0x200/2];
|
||||
m_stack[m_stack_ptr] = data;
|
||||
}
|
||||
|
||||
if (cmd == 0x6d) // Store values to asic ram
|
||||
u32 igs022_device::pop_stack()
|
||||
{
|
||||
const u32 data = m_stack[m_stack_ptr];
|
||||
|
||||
if (m_stack_ptr > 0)
|
||||
--m_stack_ptr;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string igs022_device::stack_as_string() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "stack:";
|
||||
|
||||
for (int i = 0; i <= m_stack_ptr; ++i)
|
||||
util::stream_format(stream, " %08x", m_stack[i]);
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
u32 igs022_device::read_reg(u16 offset)
|
||||
{
|
||||
if (offset < NUM_REGS)
|
||||
{
|
||||
const u32 p1 = (m_sharedprotram[0x298/2] << 16) | m_sharedprotram[0x29a/2];
|
||||
const u32 p2 = (m_sharedprotram[0x29c/2] << 16) | m_sharedprotram[0x29e/2];
|
||||
|
||||
if ((p2 & 0xffff) == 0x9) // Set value
|
||||
{
|
||||
const int reg = (p2 >> 16) & 0xffff;
|
||||
|
||||
if (reg & 0x300) { // 300?? killbld expects 0x200, drgw3 expects 0x100?
|
||||
m_kb_regs[reg & 0xff] = p1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((p2 & 0xffff) == 0x6) // Add value
|
||||
{
|
||||
const int src1 = (p1 >> 16) & 0xff;
|
||||
const int src2 = (p1 >> 0) & 0xff;
|
||||
const int dst = (p2 >> 16) & 0xff;
|
||||
|
||||
m_kb_regs[dst] = m_kb_regs[src2] - m_kb_regs[src1];
|
||||
}
|
||||
|
||||
if ((p2 & 0xffff) == 0x1) // Add Imm?
|
||||
{
|
||||
const int reg = (p2 >> 16) & 0xff;
|
||||
const int imm = (p1 >> 0) & 0xffff;
|
||||
|
||||
m_kb_regs[reg] += imm;
|
||||
}
|
||||
|
||||
if ((p2 & 0xffff) == 0xa) // Get value
|
||||
{
|
||||
const int reg = (p1 >> 16) & 0xFF;
|
||||
|
||||
m_sharedprotram[0x29c/2] = (m_kb_regs[reg] >> 16) & 0xffff;
|
||||
m_sharedprotram[0x29e/2] = m_kb_regs[reg] & 0xffff;
|
||||
}
|
||||
|
||||
m_sharedprotram[0x202 / 2] = 0x7c; // this mode complete?
|
||||
return m_regs[offset];
|
||||
}
|
||||
|
||||
// Is this actually what this is suppose to do? Complete guess.
|
||||
if (cmd == 0x12) // copy??
|
||||
else if (offset == 0x400)
|
||||
{
|
||||
m_sharedprotram[0x28c / 2] = m_sharedprotram[0x288 / 2];
|
||||
m_sharedprotram[0x28e / 2] = m_sharedprotram[0x28a / 2];
|
||||
|
||||
m_sharedprotram[0x202 / 2] = 0x23; // this mode complete?
|
||||
return pop_stack();
|
||||
}
|
||||
|
||||
// what do these do? write the completion byte for now...
|
||||
if (cmd == 0x45) m_sharedprotram[0x202 / 2] = 0x56;
|
||||
if (cmd == 0x5a) m_sharedprotram[0x202 / 2] = 0x4b;
|
||||
if (cmd == 0x2d) m_sharedprotram[0x202 / 2] = 0x3c;
|
||||
|
||||
if (cmd == 0x4f) // memcpy with encryption / scrambling
|
||||
else
|
||||
{
|
||||
const u16 src = m_sharedprotram[0x290 / 2] >> 1; // External mcu data is 8 bit and addressed as such
|
||||
const u32 dst = m_sharedprotram[0x292 / 2];
|
||||
const u16 size = m_sharedprotram[0x294 / 2];
|
||||
const u16 mode = m_sharedprotram[0x296 / 2];
|
||||
|
||||
IGS022_do_dma(src,dst,size,mode);
|
||||
|
||||
m_sharedprotram[0x202 / 2] = 0x5e; // this mode complete?
|
||||
return 0; // Invalid!
|
||||
}
|
||||
}
|
||||
|
||||
void igs022_device::write_reg(u16 offset, u32 data)
|
||||
{
|
||||
if (offset < NUM_REGS)
|
||||
{
|
||||
m_regs[offset] = data;
|
||||
}
|
||||
else if (offset == 0x300)
|
||||
{
|
||||
push_stack(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid!
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_DEVICE_TYPE(IGS022, igs022_device, "igs022", "IGS022")
|
||||
// What does this do? write the completion byte for now...
|
||||
void igs022_device::handle_incomplete_command(u16 cmd, u16 res)
|
||||
{
|
||||
logerror("%s: IGS022 command %04x: INCOMPLETE (NOP)\n", machine().describe_context(), cmd);
|
||||
m_sharedprotram[0x202 / 2] = res;
|
||||
}
|
||||
|
||||
void igs022_device::handle_command()
|
||||
{
|
||||
const u16 cmd = m_sharedprotram[0x200 / 2];
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case 0x12: // Push
|
||||
{
|
||||
const u32 data = (m_sharedprotram[0x288 / 2] << 16) + m_sharedprotram[0x28a / 2];
|
||||
|
||||
push_stack(data);
|
||||
|
||||
logerror("%s: IGS022 command %04x: PUSH {288, 28a} (%08x) %s\n", machine().describe_context(), cmd, data, stack_as_string());
|
||||
|
||||
m_sharedprotram[0x202 / 2] = 0x23; // this mode complete?
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2d: handle_incomplete_command(cmd, 0x3c); break; // killbld
|
||||
|
||||
// case 0x42: break; // killbld
|
||||
|
||||
case 0x45: // Pop
|
||||
{
|
||||
const u32 data = pop_stack();
|
||||
|
||||
m_sharedprotram[0x28c / 2] = (data >> 16) & 0xffff;
|
||||
m_sharedprotram[0x28e / 2] = data & 0xffff;
|
||||
|
||||
logerror("%s: IGS022 command %04x: POP {28c, 28e} (%08x) %s\n", machine().describe_context(), cmd, data, stack_as_string());
|
||||
|
||||
m_sharedprotram[0x202 / 2] = 0x56; // this mode complete?
|
||||
break;
|
||||
}
|
||||
|
||||
// case 0x47: // NOP? slqz2/lhzb2
|
||||
// break;
|
||||
|
||||
case 0x4f: // DMA from protection ROM (memcpy with encryption / scrambling)
|
||||
{
|
||||
logerror("%s: IGS022 command %04x: DMA\n", machine().describe_context(), cmd);
|
||||
|
||||
const u16 src = m_sharedprotram[0x290 / 2] >> 1; // External mcu data is 8 bit and addressed as such
|
||||
const u32 dst = m_sharedprotram[0x292 / 2];
|
||||
const u16 size = m_sharedprotram[0x294 / 2];
|
||||
const u16 mode = m_sharedprotram[0x296 / 2];
|
||||
|
||||
do_dma(src, dst, size, mode);
|
||||
|
||||
m_sharedprotram[0x202 / 2] = 0x5e; // this mode complete?
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x5a: handle_incomplete_command(cmd, 0x4b); break; // killbld, uses {284} as input
|
||||
|
||||
case 0x6d: // Set/Get values to/from ASIC RAM, arithmetic operations on them
|
||||
handle_command_6d();
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("%s: IGS022 command %04x: UNKNOWN!\n", machine().describe_context(), cmd);
|
||||
}
|
||||
}
|
||||
|
||||
// Set/Get values to/from ASIC RAM, arithmetic operations on them
|
||||
void igs022_device::handle_command_6d()
|
||||
{
|
||||
const u32 p1 = (m_sharedprotram[0x298 / 2] << 16) | m_sharedprotram[0x29a / 2];
|
||||
const u32 p2 = (m_sharedprotram[0x29c / 2] << 16) | m_sharedprotram[0x29e / 2];
|
||||
|
||||
std::stringstream stream;
|
||||
util::stream_format(stream, "%s: IGS022 command 006d: ASIC RAM %04x %04x %04x %04x ~ ", machine().describe_context(),
|
||||
(p1 >> 16) & 0xffff, (p1 >> 0) & 0xffff, (p2 >> 16) & 0xffff, (p2 >> 0) & 0xffff
|
||||
);
|
||||
|
||||
switch (p2 & 0xffff)
|
||||
{
|
||||
case 0x0: // Add values
|
||||
{
|
||||
const u16 src1 = p1 >> 16;
|
||||
const u16 src2 = p1 >> 0;
|
||||
const u16 dst = p2 >> 16;
|
||||
|
||||
const u32 data1 = read_reg(src1);
|
||||
const u32 data2 = read_reg(src2);
|
||||
const u32 res = data1 + data2;
|
||||
|
||||
write_reg(dst, res);
|
||||
|
||||
util::stream_format(stream, "ADD [%04x] = [%04x] + [%04x] (%08x)\n", dst, src1, src2, res);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1: // Sub values (src1 - src2)
|
||||
{
|
||||
const u16 src1 = p1 >> 16;
|
||||
const u16 src2 = p1 >> 0;
|
||||
const u16 dst = p2 >> 16;
|
||||
|
||||
const u32 data1 = read_reg(src1);
|
||||
const u32 data2 = read_reg(src2);
|
||||
const u32 res = data1 - data2;
|
||||
|
||||
write_reg(dst, res);
|
||||
|
||||
util::stream_format(stream, "SUB1 [%04x] = [%04x] - [%04x] (%08x)\n", dst, src1, src2, res);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x6: // Sub values (src2 - src1)
|
||||
{
|
||||
const u16 src1 = p1 >> 16;
|
||||
const u16 src2 = p1 >> 0;
|
||||
const u16 dst = p2 >> 16;
|
||||
|
||||
const u32 data1 = read_reg(src1);
|
||||
const u32 data2 = read_reg(src2);
|
||||
const u32 res = data2 - data1;
|
||||
|
||||
write_reg(dst, res);
|
||||
|
||||
util::stream_format(stream, "SUB2 [%04x] = [%04x] - [%04x] (%08x)\n", dst, src2, src1, res);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9: // Set value (Shared Protection RAM -> ASIC RAM)
|
||||
{
|
||||
const u16 dst = p2 >> 16;
|
||||
|
||||
const u32 data = p1;
|
||||
|
||||
write_reg(dst, data);
|
||||
|
||||
util::stream_format(stream, "SET [%04x] = {298, 29a} (%08x)\n", dst, data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa: // Get value (ASIC RAM -> Shared Protection RAM)
|
||||
{
|
||||
const u16 src = p1 >> 16;
|
||||
|
||||
const u32 data = m_regs[src];
|
||||
|
||||
m_sharedprotram[0x29c / 2] = (data >> 16) & 0xffff;
|
||||
m_sharedprotram[0x29e / 2] = data & 0xffff;
|
||||
|
||||
util::stream_format(stream, "GET {29c, 29e} = [%04x] (%08x)\n", src, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
logerror("%s", stream.str());
|
||||
m_sharedprotram[0x202 / 2] = 0x7c; // this mode complete?
|
||||
}
|
||||
|
||||
DEFINE_DEVICE_TYPE(IGS022, igs022_device, "igs022", "IGS022 encrypted DMA device")
|
||||
|
@ -1,33 +1,44 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood, ElSemi
|
||||
/* IGS022 */
|
||||
|
||||
#ifndef MAME_MACHINE_IGS022_H
|
||||
#define MAME_MACHINE_IGS022_H
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
class igs022_device : public device_t
|
||||
{
|
||||
public:
|
||||
igs022_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
void IGS022_handle_command();
|
||||
void handle_command();
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
u32 m_kb_regs[0x100];
|
||||
|
||||
void IGS022_do_dma(u16 src, u16 dst, u16 size, u16 mode);
|
||||
void IGS022_reset();
|
||||
|
||||
private:
|
||||
static constexpr u16 NUM_REGS = 0x300, STACK_SIZE = 0x100;
|
||||
u32 m_regs[NUM_REGS];
|
||||
u32 m_stack[STACK_SIZE];
|
||||
u8 m_stack_ptr;
|
||||
|
||||
optional_shared_ptr<u16> m_sharedprotram;
|
||||
required_memory_region m_rom;
|
||||
};
|
||||
|
||||
u32 read_reg(u16 offset);
|
||||
void write_reg(u16 offset, u32 data);
|
||||
|
||||
void push_stack(u32 data);
|
||||
u32 pop_stack();
|
||||
std::string stack_as_string() const;
|
||||
|
||||
void do_dma(u16 src, u16 dst, u16 size, u16 mode);
|
||||
void reset();
|
||||
|
||||
void handle_command_6d();
|
||||
void handle_incomplete_command(u16 cmd, u16 res);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(IGS022, igs022_device)
|
||||
|
||||
|
@ -337,7 +337,7 @@ MACHINE_RESET_MEMBER(pgm_022_025_state, dw3)
|
||||
void pgm_022_025_state::igs025_to_igs022_callback( void )
|
||||
{
|
||||
// printf("igs025_to_igs022_callback\n");
|
||||
m_igs022->IGS022_handle_command();
|
||||
m_igs022->handle_command();
|
||||
}
|
||||
|
||||
|
||||
|
@ -17268,10 +17268,11 @@ wlcc // (c) 1996
|
||||
xymg // (c) 1996
|
||||
|
||||
@source:igs017.cpp
|
||||
cpoker2 // (c) 2000?
|
||||
genius6 // (c) 1998
|
||||
genius6a // (c) 1997
|
||||
genius6b // (c) 1997
|
||||
happyskl // (c) 2001?
|
||||
happyskl // (c) 2000?
|
||||
iqblocka // (c) 1996
|
||||
iqblockf // (c) 1996
|
||||
lhzb2 // (c) 1998
|
||||
@ -17281,13 +17282,12 @@ mgdh // (c) 1997
|
||||
mgdha // (c) 1997
|
||||
sdmg2 // (c) 1997
|
||||
slqz2 // (c) 1998
|
||||
spkrform // (c) ????
|
||||
spkrform // (c) 2000?
|
||||
starzan // (c) 2000?
|
||||
tarzan // (c) 1999
|
||||
tarzana // (c) 1999
|
||||
tarzanc // (c) 1999
|
||||
tjsb // (c) 1997
|
||||
unkigs // (c) 2001?
|
||||
|
||||
@source:igspc.cpp
|
||||
eztouch // (c) 200?
|
||||
|
@ -6,7 +6,7 @@ IGS017 / IGS031 video device
|
||||
|
||||
what's the difference between IGS017 and IGS031? encryption?
|
||||
|
||||
all the known IGS017 / IGS031 games use same memory map, is the IGS017 / IGS031
|
||||
all the known IGS017 / IGS031 games use the same memory map, is the IGS017 / IGS031
|
||||
providing the interface to the 8255, or is it coincidence?
|
||||
|
||||
*/
|
||||
@ -17,7 +17,6 @@ providing the interface to the 8255, or is it coincidence?
|
||||
void igs017_igs031_device::map(address_map &map)
|
||||
{
|
||||
map(0x1000, 0x17ff).ram().share("spriteram");
|
||||
// map(0x1800, 0x1bff).ram() //.w("palette", FUNC(palette_device::write).share("palette");
|
||||
map(0x1800, 0x1bff).ram().w(FUNC(igs017_igs031_device::palram_w)).share("palram");
|
||||
map(0x1c00, 0x1fff).ram();
|
||||
|
||||
@ -29,7 +28,6 @@ void igs017_igs031_device::map(address_map &map)
|
||||
|
||||
map(0x4000, 0x5fff).ram().w(FUNC(igs017_igs031_device::fg_w)).share("fg_videoram");
|
||||
map(0x6000, 0x7fff).ram().w(FUNC(igs017_igs031_device::bg_w)).share("bg_videoram");
|
||||
|
||||
}
|
||||
|
||||
u8 igs017_igs031_device::i8255_r(offs_t offset)
|
||||
@ -260,7 +258,7 @@ void igs017_igs031_device::draw_sprite(bitmap_ind16 &bitmap, const rectangle &cl
|
||||
if (addr + dimx * dimy >= m_sprites_gfx_size)
|
||||
return;
|
||||
|
||||
/* Start drawing */
|
||||
// Start drawing
|
||||
const u16 pal = 0x100 + (color << 5);
|
||||
const u8 *source_base = &m_sprites_gfx[addr];
|
||||
const u8 transparent_color = 0x1f;
|
||||
@ -389,7 +387,7 @@ int igs017_igs031_device::debug_viewer(bitmap_ind16 &bitmap,const rectangle &cli
|
||||
popmessage("a: %08X w: %03X p: %02x-%02x-%02x",a,w,m_sprites_gfx[a/3*3+0],m_sprites_gfx[a/3*3+1],m_sprites_gfx[a/3*3+2]);
|
||||
m_debug_addr = a;
|
||||
m_debug_width = w;
|
||||
osd_sleep(osd_ticks_per_second() / 1000 * 200);
|
||||
osd_sleep(osd_ticks_per_second() / 1000 * 200 / 4);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user