summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/315-5838_317-0229_comp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/315-5838_317-0229_comp.c')
-rw-r--r--src/mame/machine/315-5838_317-0229_comp.c343
1 files changed, 343 insertions, 0 deletions
diff --git a/src/mame/machine/315-5838_317-0229_comp.c b/src/mame/machine/315-5838_317-0229_comp.c
new file mode 100644
index 00000000000..22cac97cb79
--- /dev/null
+++ b/src/mame/machine/315-5838_317-0229_comp.c
@@ -0,0 +1,343 @@
+/* Sega Compression (and possibly encryption) device
+
+ 315-5838 - Decathlete (ST-V)
+ 317-0229 - Dead or Alive (Model 2A)
+
+ Package Type: TQFP100
+
+ This appears to be a dual channel compression chip, used in 1996, predating the 5881.
+ Decathlete uses it to compress ALL the game graphics, Dead or Alive uses it for a
+ dumb security check, decompressing a single string.
+
+ Dead of Alive only uses a single channel, and has the source data in RAM, not ROM.
+ This is similar to how some 5881 games were set up, with the ST-V versions decrypting
+ data directly from ROM and the Model 2 ones using a RAM source buffer.
+
+*/
+
+#include "emu.h"
+#include "machine/315-5838_317-0229_comp.h"
+
+extern const device_type SEGA315_5838_COMP = &device_creator<sega_315_5838_comp_device>;
+
+
+sega_315_5838_comp_device::sega_315_5838_comp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, SEGA315_5838_COMP, "Sega 315-5838 / 317-0029 Compression (Encryption?)", tag, owner, clock, "SEGA315_5838", __FILE__)
+{
+}
+
+
+
+void sega_315_5838_comp_device::device_start()
+{
+ m_decathlt_lastcount = 0;
+ m_decathlt_prot_uploadmode = 0;
+ m_decathlt_prot_uploadoffset = 0;
+}
+
+void sega_315_5838_comp_device::device_reset()
+{
+ memset(m_decathlt_protregs, 0, sizeof(m_decathlt_protregs));
+ m_decathlt_lastcount = 0;
+ m_decathlt_prot_uploadmode = 0;
+ m_decathlt_prot_uploadoffset = 0;
+ m_decathlt_part = 1;
+
+ m_protstate = 0;
+}
+
+
+/**************************
+*
+* Decathlete
+*
+**************************/
+
+READ32_MEMBER( sega_315_5838_comp_device::decathlt_prot_r )
+{
+ // the offsets written to the protection device definitely only refer to 2 of the roms
+ // it's a fair assumption to say that only those 2 are connected to the protection device
+ UINT8 *ROM = (UINT8 *)memregion(":abus")->base()+0x1000000;
+ UINT32 *fake0 = (UINT32*)memregion( ":fake0" )->base();
+
+ if (offset==2)
+ {
+ UINT32 retvalue = 0xffff;
+
+ switch (m_decathlt_protregs[0])
+ {
+ default:
+ retvalue = ROM[(m_decathlt_protregs[0]*2)-2];
+ retvalue <<= 8;
+ retvalue |= ROM[((m_decathlt_protregs[0]+1)*2)+1-2];
+ retvalue <<= 8;
+ retvalue |= ROM[((m_decathlt_protregs[0]+1)*2)-2];
+ retvalue <<= 8;
+ retvalue |= ROM[((m_decathlt_protregs[0]+2)*2)+1-2];
+ m_decathlt_lastcount++;
+ logerror("read addr %08x, blah_r %08x - read count count %08x\n", m_decathlt_protregs[0], retvalue, m_decathlt_lastcount*4);
+ m_decathlt_protregs[0]+=2;
+ return retvalue;
+
+ case 0x03228e4:
+ if (fake0) retvalue = fake0[(((0x20080/4)+m_decathlt_lastcount))];
+ m_decathlt_lastcount++;
+ return retvalue;
+
+ case 0x00a9f3a:
+ if (fake0) retvalue = fake0[(((0x00000/4)+m_decathlt_lastcount))];
+ m_decathlt_lastcount++;
+ return retvalue;
+
+ case 0x0213ab4:
+ if (fake0) retvalue = fake0[(((0x40000/4)+m_decathlt_lastcount))];
+ m_decathlt_lastcount++;
+ return retvalue;
+
+ case 0x01efaf0:
+ if (fake0) retvalue = fake0[(((0x60000/4)+m_decathlt_lastcount))];
+ m_decathlt_lastcount++;
+ return retvalue;
+
+ case 0x033f16c:
+ case 0x038929c:
+
+
+
+ case 0x00de05a:
+ case 0x0334258:
+ case 0x019fb82:
+ case 0x033dbf6:
+ case 0x0011ac6:
+ case 0x00060dc:
+ case 0x0000002:
+ case 0x0008c90:
+ case 0x035cdc8:
+ case 0x0327960:
+ case 0x0329b8c:
+ case 0x00d6e92:
+ case 0x000081e:
+ case 0x00035d6:
+ case 0x00089a6:
+ case 0x03315f4:
+ case 0x0023fe0:
+ case 0x001e290:
+ case 0x0026e86:
+ case 0x0012494:
+ case 0x001b35a:
+ case 0x0018424:
+
+ return retvalue;
+ }
+
+
+ }
+ else
+ {
+ logerror("%06x Decathlete prot R offset %04x mask %08x regs %08x, %08x, %08x, %08x\n", safe_pc(), offset, mem_mask, m_decathlt_protregs[0], m_decathlt_protregs[1], m_decathlt_protregs[2], m_decathlt_protregs[3]);
+ }
+
+ return m_decathlt_protregs[offset];
+}
+
+
+void sega_315_5838_comp_device::write_prot_data(UINT32 data, UINT32 mem_mask, int offset, int which)
+{
+
+ printf("write_prot_data %08x %08x %08x\n", offset, data, mem_mask);
+
+ m_decathlt_protregs[offset] = (data&mem_mask)|(m_decathlt_protregs[offset]&~mem_mask);
+// m_decathlt_protregs[0] = 0x0c00000/4;
+
+ if (offset==0) // seems to set a source address
+ {
+ m_decathlt_part ^=1;
+
+ //if (m_decathlt_part==0) logerror("%d, last read count was %06x\n",which, m_decathlt_lastcount*4);
+ m_decathlt_lastcount = 0;
+ if (m_decathlt_part==1) logerror("%d Decathlete prot W offset %04x data %08x, %08x, >>> regs %08x <<<<, %08x, %08x, %08x\n",which, offset, data, m_decathlt_protregs[0], m_decathlt_protregs[0]*4, m_decathlt_protregs[1], m_decathlt_protregs[2], m_decathlt_protregs[3]);
+ }
+
+ if (offset==1) // uploads 2 tables...
+ {
+ if (mem_mask==0xffff0000)
+ {
+ if (data == 0x80000000)
+ {
+ // logerror("changed to upload mode 1\n");
+ m_decathlt_prot_uploadmode = 1;
+ m_decathlt_prot_uploadoffset = 0;
+ }
+ else if (data == 0x80800000)
+ {
+ // logerror("changed to upload mode 2\n");
+ m_decathlt_prot_uploadmode = 2;
+ m_decathlt_prot_uploadoffset = 0;
+ }
+ else
+ {
+ // logerror("unknown upload mode\n");
+ m_decathlt_prot_uploadmode = 2;
+ m_decathlt_prot_uploadoffset = 0;
+ }
+
+// logerror("ARGH! %08x %08x\n",mem_mask,data);
+ }
+ else if (mem_mask==0x0000ffff)
+ {
+ if (m_decathlt_prot_uploadmode==1)
+ {
+ if (m_decathlt_prot_uploadoffset>=24)
+ {
+ // logerror("upload mode 1 error, too big\n");
+ return;
+ }
+
+ //logerror("uploading table 1 %04x %04x\n",m_decathlt_prot_uploadoffset, data&0xffff);
+ m_decathlt_prottable1[m_decathlt_prot_uploadoffset]=data&0xffff;
+ m_decathlt_prot_uploadoffset++;
+
+ printf("table 1 %04x\n", data & 0xffff);
+
+ {
+ /* 0x18 (24) values in this table, rom data is 0x1800000 long, maybe it has
+ something to do with that? or 24-address b its?
+
+ uploaded values appear to be 12-bit, some are repeated
+ */
+
+ {
+ FILE* fp;
+ if (which==1) fp = fopen("table1x","wb");
+ else fp = fopen("table1","wb");
+
+ {
+ fwrite(&m_decathlt_prottable1,24,2,fp);
+ }
+ fclose(fp);
+ }
+ }
+
+ }
+ else if (m_decathlt_prot_uploadmode==2)
+ {
+ if (m_decathlt_prot_uploadoffset>=128)
+ {
+ //logerror("upload mode 2 error, too big\n");
+ return;
+ }
+
+ //logerror("uploading table 2 %04x %04x\n",m_decathlt_prot_uploadoffset, data&0xffff);
+ m_decathlt_prottable2[m_decathlt_prot_uploadoffset]=data&0xffff;
+ m_decathlt_prot_uploadoffset++;
+
+ printf("dictionary %04x\n", data & 0xffff);
+
+
+ {
+ /* the table uploaded here is a 256 byte table with 256 unique values, remaps something? */
+
+ {
+ FILE* fp;
+ if (which==1) fp = fopen("table2x","wb");
+ else fp = fopen("table2","wb");
+
+ {
+ fwrite(&m_decathlt_prottable2,128,2,fp);
+ }
+ fclose(fp);
+ }
+ }
+ }
+ else
+ {
+ // logerror("unknown upload mode!\n");
+ }
+ }
+ }
+
+ if (offset>1)
+ {
+ // logerror("higher offset write\n");
+ }
+
+}
+
+WRITE32_MEMBER( sega_315_5838_comp_device::decathlt_prot1_w )
+{
+ write_prot_data(data,mem_mask, offset, 0);
+
+}
+
+WRITE32_MEMBER( sega_315_5838_comp_device::decathlt_prot2_w )
+{
+ write_prot_data(data,mem_mask, offset, 1);
+
+
+}
+
+void sega_315_5838_comp_device::install_decathlt_protection()
+{
+ /* It uploads 2 tables here, then performs what looks like a number of transfers, setting
+ a source address of some kind (scrambled?) and then making many reads from a single address */
+
+ //todo, install these in the driver, they differ between games
+ cpu_device* cpu = (cpu_device*)machine().device(":maincpu");
+
+
+ cpu->space(AS_PROGRAM).install_readwrite_handler(0x37FFFF0, 0x37FFFFF, read32_delegate(FUNC(sega_315_5838_comp_device::decathlt_prot_r), this), write32_delegate(FUNC(sega_315_5838_comp_device::decathlt_prot1_w), this));
+ /* It accesses the device at this address too, with different tables, for the game textures, should it just act like a mirror, or a secondary device? */
+ cpu->space(AS_PROGRAM).install_readwrite_handler(0x27FFFF0, 0x27FFFFF, read32_delegate(FUNC(sega_315_5838_comp_device::decathlt_prot_r), this), write32_delegate(FUNC(sega_315_5838_comp_device::decathlt_prot2_w), this));
+}
+
+
+READ32_MEMBER(sega_315_5838_comp_device::doa_prot_r)
+{
+ UINT32 retval = 0;
+
+ if (offset == 0x7ff8/4)
+ {
+ retval = m_protram[m_protstate+1] | m_protram[m_protstate]<<8;
+ m_protstate+=2;
+ printf("doa_prot_read %08x %08x %08x\n", offset*4, retval, mem_mask);
+ }
+ else if (offset == 0x400c/4) // todo, is this actually part of the protection? it's in the address range, but decathlete doesn't have it afaik.
+ {
+ m_prot_a = !m_prot_a;
+ if (m_prot_a)
+ retval = 0xffff;
+ else
+ retval = 0xfff0;
+ }
+ else
+ {
+ printf("doa_prot_read %08x %08x %08x\n", offset*4, retval, mem_mask);
+ logerror("Unhandled Protection READ @ %x mask %x (PC=%x)\n", offset, mem_mask, space.device().safe_pc());
+ }
+
+ return retval;
+}
+
+
+WRITE32_MEMBER(sega_315_5838_comp_device::doa_prot_w)
+{
+ printf("doa_prot_w %08x %08x %08x\n", offset*4, data, mem_mask);
+
+ if (offset == 0x7ff2 / 4)
+ {
+ if (data == 0)
+ {
+ m_protstate = 0;
+ strcpy((char *)m_protram, " TECMO LTD. DEAD OR ALIVE 1996.10.22 VER. 1.00"); // this is the single decompressed string DOA needs
+ }
+ }
+ else logerror("Unhandled Protection WRITE %x @ %x mask %x (PC=%x)\n", data, offset, mem_mask, space.device().safe_pc());
+}
+
+
+void sega_315_5838_comp_device::install_doa_protection()
+{
+ //todo, install these in the driver, they differ between games
+ cpu_device* cpu = (cpu_device*)machine().device(":maincpu");
+ cpu->space(AS_PROGRAM).install_readwrite_handler(0x01d80000, 0x01dfffff, read32_delegate(FUNC(sega_315_5838_comp_device::doa_prot_r), this), write32_delegate(FUNC(sega_315_5838_comp_device::doa_prot_w), this));
+} \ No newline at end of file