trunk/src/mame/machine/315-5838_317-0229_comp.c
| r243173 | r243174 | |
| 9 | 9 | Decathlete uses it to compress ALL the game graphics, Dead or Alive uses it for a |
| 10 | 10 | dumb security check, decompressing a single string. |
| 11 | 11 | |
| 12 | Each channel appears to be connected to a different set of ROMs, however there is |
| 13 | defintiely only 315-5838 single chip. |
| 14 | |
| 12 | 15 | Dead of Alive only uses a single channel, and has the source data in RAM, not ROM. |
| 13 | 16 | This is similar to how some 5881 games were set up, with the ST-V versions decrypting |
| 14 | 17 | data directly from ROM and the Model 2 ones using a RAM source buffer. |
| 15 | 18 | |
| 19 | Looking at the values read I don't think there is any address based encryption, for |
| 20 | example many blocks where you'd expect a zero fill start with repeating patterns |
| 21 | of 8f708f70 (different lengths) which would appear to relate to compressed 0x00 data |
| 22 | |
| 23 | read addr 0071253c, blah_r 8f708f70 - read count count 00000004 |
| 24 | read addr 00712540, blah_r 8f708f70 - read count count 00000008 |
| 25 | read addr 00712544, blah_r 8f708f70 - read count count 0000000c |
| 26 | read addr 00712548, blah_r 8f708f70 - read count count 00000010 |
| 27 | read addr 0071254c, blah_r 8f708f70 - read count count 00000014 |
| 28 | read addr 00712550, blah_r 8f708f70 - read count count 00000018 |
| 29 | read addr 00712554, blah_r 8f708f70 - read count count 0000001c |
| 30 | |
| 16 | 31 | */ |
| 17 | 32 | |
| 18 | 33 | #include "emu.h" |
| r243173 | r243174 | |
| 20 | 35 | |
| 21 | 36 | extern const device_type SEGA315_5838_COMP = &device_creator<sega_315_5838_comp_device>; |
| 22 | 37 | |
| 38 | //#define DEBUG_DATA_DUMP |
| 23 | 39 | |
| 24 | 40 | sega_315_5838_comp_device::sega_315_5838_comp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 25 | 41 | : device_t(mconfig, SEGA315_5838_COMP, "Sega 315-5838 / 317-0029 Compression (Encryption?)", tag, owner, clock, "SEGA315_5838", __FILE__) |
| r243173 | r243174 | |
| 33 | 49 | m_decathlt_lastcount = 0; |
| 34 | 50 | m_decathlt_prot_uploadmode = 0; |
| 35 | 51 | m_decathlt_prot_uploadoffset = 0; |
| 52 | |
| 53 | m_read_ch1.bind_relative_to(*owner()); |
| 54 | m_read_ch2.bind_relative_to(*owner()); |
| 36 | 55 | } |
| 37 | 56 | |
| 38 | 57 | void sega_315_5838_comp_device::device_reset() |
| r243173 | r243174 | |
| 53 | 72 | * |
| 54 | 73 | **************************/ |
| 55 | 74 | |
| 56 | | READ32_MEMBER( sega_315_5838_comp_device::decathlt_prot_r ) |
| 75 | #ifdef DEBUG_DATA_DUMP |
| 76 | FILE* tempfile; |
| 77 | #endif |
| 78 | |
| 79 | |
| 80 | READ32_MEMBER(sega_315_5838_comp_device::decathlt_prot_r) |
| 57 | 81 | { |
| 58 | | // the offsets written to the protection device definitely only refer to 2 of the roms |
| 59 | | // it's a fair assumption to say that only those 2 are connected to the protection device |
| 60 | | UINT8 *ROM = (UINT8 *)memregion(":abus")->base()+0x1000000; |
| 61 | | UINT32 *fake0 = (UINT32*)memregion( ":fake0" )->base(); |
| 82 | return genericdecathlt_prot_r(offset, mem_mask, 0); |
| 83 | } |
| 62 | 84 | |
| 85 | READ32_MEMBER(sega_315_5838_comp_device::decathlt_prot_ch2_r) |
| 86 | { |
| 87 | return genericdecathlt_prot_r(offset, mem_mask, 1); |
| 88 | } |
| 89 | |
| 90 | |
| 91 | UINT32 sega_315_5838_comp_device::genericdecathlt_prot_r(UINT32 offset, UINT32 mem_mask, int which) |
| 92 | { |
| 93 | |
| 94 | // UINT32 *fake0 = (UINT32*)memregion( ":fake0" )->base(); |
| 95 | |
| 63 | 96 | if (offset==2) |
| 64 | 97 | { |
| 65 | | UINT32 retvalue = 0xffff; |
| 98 | // UINT32 retvalue = 0xffff; |
| 66 | 99 | |
| 67 | 100 | switch (m_decathlt_protregs[0]) |
| 68 | 101 | { |
| 69 | 102 | default: |
| 70 | | retvalue = ROM[(m_decathlt_protregs[0]*2)-2]; |
| 71 | | retvalue <<= 8; |
| 72 | | retvalue |= ROM[((m_decathlt_protregs[0]+1)*2)+1-2]; |
| 73 | | retvalue <<= 8; |
| 74 | | retvalue |= ROM[((m_decathlt_protregs[0]+1)*2)-2]; |
| 75 | | retvalue <<= 8; |
| 76 | | retvalue |= ROM[((m_decathlt_protregs[0]+2)*2)+1-2]; |
| 103 | |
| 77 | 104 | m_decathlt_lastcount++; |
| 78 | | logerror("read addr %08x, blah_r %08x - read count count %08x\n", m_decathlt_protregs[0], retvalue, m_decathlt_lastcount*4); |
| 79 | | m_decathlt_protregs[0]+=2; |
| 80 | | return retvalue; |
| 81 | 105 | |
| 106 | UINT32 tempdata = 0; |
| 107 | |
| 108 | if (which == 0) |
| 109 | { |
| 110 | tempdata |= m_read_ch1(m_decathlt_protregs[0]) << 16; |
| 111 | m_decathlt_protregs[0]++; |
| 112 | tempdata |= m_read_ch1(m_decathlt_protregs[0]) << 0; |
| 113 | m_decathlt_protregs[0]++; |
| 114 | } |
| 115 | else |
| 116 | { |
| 117 | tempdata |= m_read_ch2(m_decathlt_protregs[0]) << 16; |
| 118 | m_decathlt_protregs[0]++; |
| 119 | tempdata |= m_read_ch2(m_decathlt_protregs[0]) << 0; |
| 120 | m_decathlt_protregs[0]++; |
| 121 | } |
| 122 | |
| 123 | #ifdef DEBUG_DATA_DUMP |
| 124 | //printf("read addr %08x, blah_r %08x - read count count %08x\n", m_decathlt_protregs[0]*2, tempdata, m_decathlt_lastcount*4); |
| 125 | fwrite(&tempdata, 1, 4, tempfile); |
| 126 | #else |
| 127 | logerror("read addr %08x, blah_r %08x - read count count %08x\n", m_decathlt_protregs[0]*2, tempdata, m_decathlt_lastcount*4); |
| 128 | #endif |
| 129 | |
| 130 | return tempdata; |
| 131 | #if 0 |
| 82 | 132 | case 0x03228e4: |
| 83 | 133 | if (fake0) retvalue = fake0[(((0x20080/4)+m_decathlt_lastcount))]; |
| 84 | 134 | m_decathlt_lastcount++; |
| r243173 | r243174 | |
| 128 | 178 | case 0x0018424: |
| 129 | 179 | |
| 130 | 180 | return retvalue; |
| 181 | #endif |
| 131 | 182 | } |
| 132 | 183 | |
| 133 | 184 | |
| r243173 | r243174 | |
| 156 | 207 | //if (m_decathlt_part==0) logerror("%d, last read count was %06x\n",which, m_decathlt_lastcount*4); |
| 157 | 208 | m_decathlt_lastcount = 0; |
| 158 | 209 | 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]); |
| 210 | |
| 211 | #ifdef DEBUG_DATA_DUMP |
| 212 | if (mem_mask == 0x0000ffff) |
| 213 | { |
| 214 | if (tempfile) |
| 215 | fclose(tempfile); |
| 216 | |
| 217 | char filename[256]; |
| 218 | sprintf(filename, "%d_compressed_%08x", which, m_decathlt_protregs[0] ); |
| 219 | tempfile = fopen(filename, "w+b"); |
| 220 | } |
| 221 | #endif |
| 222 | |
| 159 | 223 | } |
| 160 | 224 | |
| 161 | 225 | if (offset==1) // uploads 2 tables... |
| r243173 | r243174 | |
| 287 | 351 | |
| 288 | 352 | 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)); |
| 289 | 353 | /* 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? */ |
| 290 | | 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)); |
| 354 | cpu->space(AS_PROGRAM).install_readwrite_handler(0x27FFFF0, 0x27FFFFF, read32_delegate(FUNC(sega_315_5838_comp_device::decathlt_prot_ch2_r), this), write32_delegate(FUNC(sega_315_5838_comp_device::decathlt_prot2_w), this)); |
| 291 | 355 | } |
| 292 | 356 | |
| 293 | 357 | |
trunk/src/mame/machine/315-5838_317-0229_comp.h
| r243173 | r243174 | |
| 4 | 4 | #ifndef __SEGA315_5838_COMP__ |
| 5 | 5 | #define __SEGA315_5838_COMP__ |
| 6 | 6 | |
| 7 | | typedef device_delegate<UINT16 (UINT32)> sega_m2_read_delegate; |
| 7 | typedef device_delegate<UINT16 (UINT32)> sega_dec_read_delegate; |
| 8 | 8 | |
| 9 | 9 | extern const device_type SEGA315_5838_COMP; |
| 10 | 10 | |
| 11 | | #define MCFG_SET_5838_READ_CALLBACK( _class, _method) \ |
| 12 | | sega_315_5838_comp_device::set_read_cb(*device, sega_m2_read_delegate(&_class::_method, #_class "::" #_method, NULL, (_class *)0)); |
| 11 | #define MCFG_SET_5838_READ_CALLBACK_CH1( _class, _method) \ |
| 12 | sega_315_5838_comp_device::set_read_cb_ch1(*device, sega_m2_read_delegate(&_class::_method, #_class "::" #_method, NULL, (_class *)0)); |
| 13 | 13 | |
| 14 | #define MCFG_SET_5838_READ_CALLBACK_CH2( _class, _method) \ |
| 15 | sega_315_5838_comp_device::set_read_cb_ch2(*device, sega_m2_read_delegate(&_class::_method, #_class "::" #_method, NULL, (_class *)0)); |
| 14 | 16 | |
| 15 | 17 | class sega_315_5838_comp_device : public device_t |
| 16 | 18 | { |
| r243173 | r243174 | |
| 18 | 20 | // construction/destruction |
| 19 | 21 | sega_315_5838_comp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 20 | 22 | |
| 21 | | sega_m2_read_delegate m_read; |
| 23 | sega_dec_read_delegate m_read_ch1; |
| 24 | sega_dec_read_delegate m_read_ch2; |
| 22 | 25 | |
| 23 | | static void set_read_cb(device_t &device,sega_m2_read_delegate readcb) |
| 26 | static void set_read_cb_ch1(device_t &device,sega_dec_read_delegate readcb) |
| 24 | 27 | { |
| 25 | 28 | sega_315_5838_comp_device &dev = downcast<sega_315_5838_comp_device &>(device); |
| 26 | | dev.m_read = readcb; |
| 29 | dev.m_read_ch1 = readcb; |
| 27 | 30 | } |
| 28 | 31 | |
| 32 | static void set_read_cb_ch2(device_t &device,sega_dec_read_delegate readcb) |
| 33 | { |
| 34 | sega_315_5838_comp_device &dev = downcast<sega_315_5838_comp_device &>(device); |
| 35 | dev.m_read_ch2 = readcb; |
| 36 | } |
| 37 | |
| 29 | 38 | DECLARE_READ32_MEMBER(decathlt_prot_r); |
| 39 | DECLARE_READ32_MEMBER(decathlt_prot_ch2_r);; |
| 40 | UINT32 genericdecathlt_prot_r(UINT32 offset, UINT32 mem_mask, int which); |
| 41 | |
| 30 | 42 | void write_prot_data(UINT32 data, UINT32 mem_mask, int offset, int which); |
| 31 | 43 | DECLARE_WRITE32_MEMBER(decathlt_prot1_w); |
| 32 | 44 | DECLARE_WRITE32_MEMBER(decathlt_prot2_w); |