~ubuntu-branches/debian/sid/mame/sid

« back to all changes in this revision

Viewing changes to src/mame/machine/naomibd.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Jordi Mallach, Emmanuel Kasper
  • Date: 2011-12-19 22:56:27 UTC
  • mfrom: (0.1.2)
  • Revision ID: package-import@ubuntu.com-20111219225627-ub5oga1oys4ogqzm
Tags: 0.144-1
[ Jordi Mallach ]
* Fix syntax errors in DEP5 copyright file (lintian).
* Use a versioned copyright Format specification field.
* Update Vcs-* URLs.
* Move transitional packages to the new metapackages section, and make
  them priority extra.
* Remove references to GNU/Linux and MESS sources from copyright.
* Add build variables for s390x.
* Use .xz tarballs as it cuts 4MB for the upstream sources.
* Add nplayers.ini as a patch. Update copyright file to add CC-BY-SA-3.0.

[ Emmanuel Kasper ]
* New upstream release. Closes: #651538.
* Add Free Desktop compliant png icons of various sizes taken from
  the hydroxygen iconset
* Mess is now built from a new source package, to avoid possible source
  incompatibilities between mame and the mess overlay.
* Mame-tools are not built from the mame source package anymore, but
  from the mess source package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*************************************************************************
2
 
 
3
 
    Naomi plug-in board emulator
4
 
 
5
 
    emulator by Samuele Zannoli and R. Belmont
6
 
    reverse engineering by ElSemi, Deunan Knute, Andreas Naive, Olivier Galibert, and Cah4e3
7
 
 
8
 
**************************************************************************/
 
1
#define ADDRESS_MAP_MODERN
 
2
 
 
3
#include "emu.h"
 
4
#include "naomibd.h"
 
5
#include "machine/x76f100.h"
9
6
 
10
7
/*
11
8
    Naomi ROM board info from ElSemi:
26
23
 
27
24
    To access the board using DMA, use the DMA_OFFSETL/H. DMA_COUNT is in units of 0x20 bytes. Then trigger a GDROM DMA request.
28
25
 
29
 
    Dimm board registers (add more information if you find it):
30
 
 
31
 
    Name:                   Naomi   Dimm Bd.
32
 
    NAOMI_DIMM_COMMAND    = 5f703c  14000014 (16 bit):
33
 
        if bits all 1 no dimm board present and other registers not used
34
 
        bit 15: during an interrupt is 1 if the dimm board has a command to be executed
35
 
        bit 14-9: 6 bit command number (naomi bios understands 0 1 3 4 5 6 8 9 a)
36
 
        bit 7-0: higher 8 bits of 24 bit offset parameter
37
 
    NAOMI_DIMM_OFFSETL    = 5f7040  14000018 (16 bit):
38
 
        bit 15-0: lower 16 bits of 24 bit offset parameter
39
 
    NAOMI_DIMM_PARAMETERL = 5f7044  1400001c (16 bit)
40
 
    NAOMI_DIMM_PARAMETERH = 5f7048  14000020 (16 bit)
41
 
    NAOMI_DIMM_STATUS     = 5f704c  14000024 (16 bit):
42
 
        bit 0: when 0 signal interrupt from naomi to dimm board
43
 
        bit 8: when 0 signal interrupt from dimm board to naomi
44
 
 
45
 
 
46
26
    Cartridge protection info from Deunan Knute:
47
27
 
48
28
    NAOMI cart can hold up to 256MB of data (well, 512 is possible too I guess), so the highest bits are used for other, dark and scary purposes.
69
49
    Or it could really be the last address bit to allow up to 512MB of data on a cart?
70
50
 
71
51
    Normal address starts with 0xa0000000 to enable auto-advance and standard addressing mode.
72
 
 
73
 
------------------------
74
 
 
75
 
Atomiswave ROM board specs from Cah4e3 @ http://cah4e3.wordpress.com/2009/07/26/some-atomiswave-info/
76
 
 
77
 
 AW_EPR_OFFSETL                                          Register addres: 0x5f7000
78
 
 +-------------------------------------------------------------------------------+
79
 
 |                                  bit15-0                                      |
80
 
 +-------------------------------------------------------------------------------+
81
 
 |                         EPR data offset low word                              |
82
 
 +-------------------------------------------------------------------------------+
83
 
 
84
 
 AW_EPR_OFFSETH                                          Register addres: 0x5f7004
85
 
 +-------------------------------------------------------------------------------+
86
 
 |                                  bit15-0                                      |
87
 
 +-------------------------------------------------------------------------------+
88
 
 |                          EPR data offset hi word                              |
89
 
 +-------------------------------------------------------------------------------+
90
 
 
91
 
  Both low and high words of 32-bit offset from start of EPR-ROM area. Used for
92
 
  reading header and programm code data, cannot be used for reading MPR-ROMs data.
93
 
 
94
 
 AW_MPR_RECORD_INDEX                                     Register addres: 0x5f700c
95
 
 +-------------------------------------------------------------------------------+
96
 
 |                                  bit15-0                                      |
97
 
 +-------------------------------------------------------------------------------+
98
 
 |                          File system record index                             |
99
 
 +-------------------------------------------------------------------------------+
100
 
 
101
 
  This register contains index of MPR-ROM file system record (64-bytes in size) to
102
 
  read throught DMA. Internal DMA offset register is assigned as AW_MPR_RECORD_INDEX<<6
103
 
  from start of MPR-ROM area. Size of DMA transaction not limited, it is possible
104
 
  to read any number of records or just part of it.
105
 
 
106
 
 AW_MPR_FIRST_FILE_INDEX                                 Register addres: 0x5f7010
107
 
 +-------------------------------------------------------------------------------+
108
 
 |                                  bit15-0                                      |
109
 
 +-------------------------------------------------------------------------------+
110
 
 |                           First file record index                             |
111
 
 +-------------------------------------------------------------------------------+
112
 
 
113
 
  This register assign for internal cart circuit index of record in MPR-ROM file
114
 
  system sub-area that contain information about first file of MPR-ROM files
115
 
  sub-area. Internal circuit using this record to read absolute first file offset
116
 
  from start of MPR-ROM area and calculate normal offset for each other file
117
 
  requested, since MPR-ROM file data sub-area can be assighed only with relative
118
 
  offsets from start of such sub-area.
119
 
 
120
 
 AW_MPR_FILE_OFFSETL                                     Register addres: 0x5f7014
121
 
 +-------------------------------------------------------------------------------+
122
 
 |                                  bit15-0                                      |
123
 
 +-------------------------------------------------------------------------------+
124
 
 |                         MPR file offset low word                              |
125
 
 +-------------------------------------------------------------------------------+
126
 
 
127
 
 AW_MPR_FILE_OFFSETH                                     Register addres: 0x5f7018
128
 
 +-------------------------------------------------------------------------------+
129
 
 |                                  bit15-0                                      |
130
 
 +-------------------------------------------------------------------------------+
131
 
 |                          MPR file offset hi word                              |
132
 
 +-------------------------------------------------------------------------------+
133
 
 
134
 
  Both low and high words of 32-bit relative offset from start of MPR-ROM files
135
 
  sub-area. Used by internal circuit to calculate absolute offset using data
136
 
  from AW_MPR_FIRST_FILE_INDEX register. Cannot be used for reading EPR-ROM
137
 
  data nor even MPR-ROM file system sub-area data.
138
 
 
139
 
 In short:
140
 
 
141
 
     EPR-ROM
142
 
 +--------------+ 0x00000000
143
 
 |              |
144
 
 |    HEADER    +- AW_EPR_OFFSET << 1
145
 
 |              |
146
 
 +--------------+
147
 
 |              |
148
 
 |     CODE     +- AW_EPR_OFFSET << 1
149
 
 |              |
150
 
 |              |
151
 
 +--------------+ 0x007fffff
152
 
 
153
 
     MPR-ROMS
154
 
 +--------------+ 0x00000000
155
 
 | FS_HEADER    |
156
 
 | FS_RECORD[1] +- (AW_MPR_RECORD_INDEX << 6)
157
 
 | FS_RECORD[2] |
158
 
 | FS_RECORD[3] +- (AW_MPR_FIRST_FILE_INDEX << 6)
159
 
 |     ...      |
160
 
 | FS_RECORD[N] |
161
 
 +--------------+- FS_RECORD[AW_MPR_FIRST_FILE_INDEX].FILE_ABS_OFFSET
162
 
 | FILE_0       |
163
 
 | FILE_1       +- (AW_MPR_FILE_OFFSET << 1) + FS_RECORD[AW_MPR_FIRST_FILE_INDEX].FILE_ABS_OFFSET
164
 
 |     ...      |
165
 
 | FILE_N       |
166
 
 +--------------+ 0x07ffffff
167
 
 
168
 
*/
169
 
 
170
 
// NOTE: all accesses are 16 or 32 bits wide but only 16 bits are valid
171
 
 
172
 
#include "emu.h"
173
 
#include "profiler.h"
174
 
#include "machine/x76f100.h"
175
 
#include "cdrom.h"
176
 
#include "includes/naomi.h"
177
 
#include "includes/naomibd.h"
178
 
 
179
 
#define NAOMIBD_FLAG_AUTO_ADVANCE       (8)     // address auto-advances on read
180
 
#define NAOMIBD_FLAG_SPECIAL_MODE       (4)     // used to access protection registers
181
 
#define NAOMIBD_FLAG_DMA_COMPRESSION    (2)     // 0 protection chip decompresses DMA data, 1 for normal DMA reads
182
 
 
183
 
#define NAOMIBD_PRINTF_PROTECTION       (0)     // 1 to printf protection access details
184
 
 
185
 
/*************************************
186
 
 *
187
 
 *  Structures
188
 
 *
189
 
 *************************************/
190
 
 
191
 
#define PACK_BUF_SIZE (32768)
192
 
 
193
 
enum
194
 
{
195
 
        CMD_READY = 0,
196
 
        CMD_FETCH,
197
 
        CMD_REPEAT
198
 
};
199
 
 
200
 
typedef struct _naomibd_config_table naomibd_config_table;
201
 
struct _naomibd_config_table
202
 
{
203
 
        const char *name;
204
 
        int m2m3_key;
205
 
    int m1_key;
206
 
};
207
 
 
208
 
typedef struct _naomibd_prot naomibd_prot;
209
 
struct _naomibd_prot
210
 
{
211
 
        UINT16 last_word, aux_word, pak_word, heading_word;
212
 
        UINT16 *ptr;
213
 
        int count, pak_bit, control_bits, pak_state, dec_count, pak_buf_size, pak_buf_pos;
214
 
    int pak_fetch_ofs;
215
 
    UINT8 pak_byte, cmd_byte;
216
 
    int seed;
217
 
    UINT8 pak_buf[PACK_BUF_SIZE];
218
 
 
219
 
    UINT8 *s_input;
220
 
    UINT8 s_xor[4];
221
 
    UINT8 s_dict[111];
222
 
    int s_subst, s_out_len, s_out_cnt, s_shift, s_bits, s_in_len, s_in_pos;
223
 
};
224
 
 
225
 
typedef struct _naomibd_state naomibd_state;
226
 
struct _naomibd_state
227
 
{
228
 
        UINT8                           index;                                  /* index of board */
229
 
        UINT8                           type;
230
 
        device_t *device;                               /* pointer to our containing device */
231
 
 
232
 
        UINT8 *                         memory;
233
 
        chd_file *                      gdromchd;
234
 
        UINT8 *                         picdata;
235
 
        UINT32                          rom_offset, rom_offset_flags, dma_count;
236
 
        UINT32                          dma_offset, dma_offset_flags;
237
 
        UINT32                          prot_offset, prot_key;
238
 
        UINT32                          aw_offset, aw_file_base, aw_file_offset;
239
 
 
240
 
        // live decrypt vars
241
 
        UINT32                          dc_gamekey, dc_seqkey, dc_dmakey;
242
 
        UINT8                           dc_cart_ram[256*1024];  // internal cartridge RAM
243
 
        INT32                           dc_m3_ptr;
244
 
 
245
 
        naomibd_prot            prot;
246
 
};
247
 
 
248
 
// maps protection offsets to real addresses
249
 
// format of array: encryption key, address written, address to switch out with.  if key is -1 it's ignored and address written is the match.
250
 
// if key is not -1, it's used for the match instead of the address written.
251
 
static const naomibd_config_table naomibd_translate_tbl[] =
252
 
{
253
 
        // games where on-the-fly decryption works (many of these are fully playable in MAME, just slow)
254
 
        { "18wheelr", 0x07cf54, 0 },
255
 
        { "alpilota", 0x070e41, 0 },
256
 
        { "alpiltdx", 0x070e41, 0 },
257
 
        { "capsnk", 0, 0 },
258
 
        { "capsnka", 0, 0 },
259
 
        { "crackndj", 0x1c2347, 0 },
260
 
        { "crzytaxi", 0x0d2f45, 0 },
261
 
        { "csmash", 0x103347, 0 },
262
 
        { "csmasho", 0x103347, 0 },
263
 
        { "cspike", 0x0e2010, 0 },
264
 
        { "deathcox", 0x0b64d0, 0 },
265
 
        { "derbyoc", 0x0fee35, 0 },
266
 
        { "doa2", 0x8ad01, 0 },
267
 
        { "doa2m", 0x8ad01, 0 },
268
 
        { "dybb99", 0x048a01, 0 },
269
 
        { "f355twin", 0x06efd4, 0 },
270
 
        { "f355twn2", 0x1666c6, 0 },
271
 
        { "ggram2", 0x074a61, 0 },
272
 
        { "ggx", 0x076110, 0 },
273
 
    { "gram2000", 0, 0x7f805c3f },
274
 
        { "gundmct", 0x0e8010, 0 },
275
 
        { "gwing2",  0x0b25d0, 0 },
276
 
        { "hmgeo",   0x038510, 0 },
277
 
        { "jambo",   0x0fab95, 0 },
278
 
    { "kick4csh", 0, 0x820857c9 },
279
 
    { "mvsc2", 0, 0xc18b6e7c },
280
 
        { "otrigger", 0x0fea94, 0 },
281
 
        { "pjustic", 0x0725d0, 0 },
282
 
        { "pstone", 0x0e69c1, 0 },
283
 
        { "pstone2", 0x0b8dc0, 0 },
284
 
        { "puyoda", 0x0acd40, 0 },
285
 
    { "qmegamis", 0, 0xcd9b4896 },
286
 
        { "ringout", 0x0b1e40, 0 },
287
 
        { "samba", 0x0a8b5d, 0 },
288
 
        { "samba2k", 0x1702cf, 0 },
289
 
        { "sgtetris", 0x8ae51, 0 },
290
 
    { "shootopl", 0, 0xa0f37ca7 },
291
 
    { "shootpl", 0, 0x9d8de9cd },
292
 
    { "shootplm", 0, 0x9d8de9cd },
293
 
        { "slasho", 0x1a66ca, 0 },
294
 
        { "smlg99", 0x048a01, 0 },
295
 
        { "spawn", 0x078d01, 0 },
296
 
        { "sstrkfgt", 0x132303, 0 },
297
 
        { "suchie3", 0x0368e1, 0 },
298
 
        { "toyfight", 0x02ca85, 0 },
299
 
        { "vf4cart", 0x2ef2f96, 0 },
300
 
    { "vf4evoct", 0, 0x1e5bb0cd },
301
 
    { "virnbao", 0x68b58, 0 },      // note: "virnba" set doesn't have protection
302
 
    { "vs2_2k", 0x88b08, 0 },
303
 
        { "vtennis", 0x03eb15, 0 },
304
 
        { "vtenis2c", 0, 0x2d2d4743 },
305
 
        { "vonot", 0x010715, 0 },
306
 
        { "wldkicks", 0xae2901, 0 },
307
 
        { "wwfroyal", 0x1627c3, 0 },
308
 
        { "zerogu2", 0x07c010, 0 },
309
 
        { "zombrvn", 0x012b41, 0 },
310
 
};
311
 
 
312
 
// forward declaration for decrypt function
313
 
static UINT16 block_decrypt(UINT32 game_key, UINT16 sequence_key, UINT16 counter, UINT16 data);
314
 
 
315
 
/***************************************************************************
316
 
    INLINE FUNCTIONS
317
 
***************************************************************************/
318
 
 
319
 
/*-------------------------------------------------
320
 
    get_safe_token - makes sure that the passed
321
 
    in device is, in fact, a naomibd device
322
 
-------------------------------------------------*/
323
 
 
324
 
INLINE naomibd_state *get_safe_token(device_t *device)
325
 
{
326
 
        assert(device != NULL);
327
 
        assert(device->type() == NAOMI_BOARD);
328
 
 
329
 
        return (naomibd_state *)downcast<legacy_device_base *>(device)->token();
330
 
}
331
 
 
332
 
 
333
 
 
334
 
/*************************************
335
 
 *
336
 
 *  Misc. functions
337
 
 *
338
 
 *************************************/
339
 
 
340
 
int naomibd_interrupt_callback(device_t *device, naomibd_interrupt_func callback)
341
 
{
342
 
        naomibd_config *config = (naomibd_config *)downcast<const legacy_device_base *>(device)->inline_config();
343
 
        config->interrupt = callback;
344
 
        return 0;
345
 
}
346
 
 
347
 
int naomibd_get_type(device_t *device)
348
 
{
349
 
        naomibd_state *v = get_safe_token(device);
350
 
        return v->type;
351
 
}
352
 
 
353
 
// M1 decryption/decompression
354
 
static UINT8 naomibd_m1dec_readbyte(naomibd_state *naomibd)
355
 
{
356
 
    UINT8 v = 0;
357
 
 
358
 
    switch (naomibd->prot.s_in_pos & 3)
359
 
    {
360
 
        case 0:
361
 
            v = naomibd->prot.s_input[naomibd->prot.s_in_pos + 3];
362
 
            v ^= naomibd->prot.s_input[naomibd->prot.s_in_pos + 1];
363
 
            break;
364
 
 
365
 
        case 1:
366
 
            v = naomibd->prot.s_input[naomibd->prot.s_in_pos + 1];
367
 
            v ^= naomibd->prot.s_input[naomibd->prot.s_in_pos - 1];
368
 
            break;
369
 
 
370
 
        case 2:
371
 
            v = naomibd->prot.s_input[naomibd->prot.s_in_pos - 1];
372
 
            break;
373
 
 
374
 
        case 3:
375
 
            v = naomibd->prot.s_input[naomibd->prot.s_in_pos - 3];
376
 
            break;
377
 
    }
378
 
 
379
 
    v ^= naomibd->prot.s_xor[naomibd->prot.s_in_pos & 3];
380
 
    naomibd->prot.s_in_pos++;
381
 
    return v;
382
 
}
383
 
 
384
 
static void naomibd_m1dec_storebyte (naomibd_state *naomibd, UINT8 b)
385
 
{
386
 
    if (naomibd->prot.s_subst && naomibd->prot.s_out_cnt >= 2)
387
 
    {
388
 
        b = naomibd->dc_cart_ram[naomibd->prot.s_out_cnt - 2] - b;
389
 
    }
390
 
    naomibd->dc_cart_ram[naomibd->prot.s_out_cnt] = b;
391
 
    naomibd->prot.s_out_cnt++;
392
 
 
393
 
    if (naomibd->prot.s_out_cnt >= (256*1024))
394
 
    {
395
 
        fatalerror("naomibd: M1 decode exceeds buffer size!\n");
396
 
    }
397
 
}
398
 
 
399
 
static void naomibd_m1dec_shiftin(naomibd_state *naomibd)
400
 
{
401
 
    naomibd->prot.s_shift <<= 8;
402
 
    naomibd->prot.s_shift |= naomibd_m1dec_readbyte(naomibd);
403
 
    naomibd->prot.s_bits += 8;
404
 
}
405
 
 
406
 
static void naomibd_m1_decode(naomibd_state *naomibd)
407
 
{
408
 
    int i, eos;
409
 
 
410
 
    naomibd->prot.s_xor [0] = (UINT8)naomibd->dc_dmakey;
411
 
    naomibd->prot.s_xor [1] = (UINT8)(naomibd->dc_dmakey >> 8);
412
 
    naomibd->prot.s_xor [2] = (UINT8)(naomibd->dc_dmakey >> 16);
413
 
    naomibd->prot.s_xor [3] = (UINT8)(naomibd->dc_dmakey >> 24);
414
 
 
415
 
        #if NAOMIBD_PRINTF_PROTECTION
416
 
    printf("M1 decode: dma offset %x, key %x\n", naomibd->dma_offset, naomibd->dc_dmakey);
417
 
    #endif
418
 
 
419
 
    naomibd->prot.s_input = naomibd->memory + naomibd->dma_offset;
420
 
    naomibd->prot.s_in_pos = 0;
421
 
 
422
 
    // read in the dictionary
423
 
    for (i = 0; i < 111; i++)
424
 
    {
425
 
        naomibd->prot.s_dict [i] = naomibd_m1dec_readbyte(naomibd);
426
 
    }
427
 
 
428
 
    // control bits
429
 
    naomibd->prot.s_subst = (naomibd->prot.s_dict [0] & 64) ? 1 : 0;
430
 
 
431
 
    // command stream
432
 
    naomibd->prot.s_out_cnt = 0, eos = 0;
433
 
    naomibd->prot.s_shift = 0, naomibd->prot.s_bits = 0;
434
 
    while (!eos)
435
 
    {
436
 
        int code, addr, t;
437
 
 
438
 
        if (naomibd->prot.s_bits < 2)
439
 
            naomibd_m1dec_shiftin(naomibd);
440
 
 
441
 
        code = (naomibd->prot.s_shift >> (naomibd->prot.s_bits - 2)) & 3;
442
 
        switch (code)
443
 
        {
444
 
            case 0:
445
 
                // 00-aa
446
 
                if (naomibd->prot.s_bits < 4)
447
 
                    naomibd_m1dec_shiftin(naomibd);
448
 
                addr = (naomibd->prot.s_shift >> (naomibd->prot.s_bits - 4)) & 3;
449
 
                naomibd->prot.s_bits -= 4;
450
 
                if (addr == 0)
451
 
                {
452
 
                    // quotation
453
 
                    if (naomibd->prot.s_bits < 8)
454
 
                        naomibd_m1dec_shiftin (naomibd);
455
 
                    t = (naomibd->prot.s_shift >> (naomibd->prot.s_bits - 8)) & 255;
456
 
                    naomibd->prot.s_bits -= 8;
457
 
                    naomibd_m1dec_storebyte(naomibd, t);
458
 
                    break;
459
 
                }
460
 
                naomibd_m1dec_storebyte(naomibd, naomibd->prot.s_dict [addr]);
461
 
                break;
462
 
 
463
 
                case 1:
464
 
                    if (naomibd->prot.s_bits < 5)
465
 
                        naomibd_m1dec_shiftin (naomibd);
466
 
                    t = (naomibd->prot.s_shift >> (naomibd->prot.s_bits - 3)) & 1;
467
 
                    if (t == 0)
468
 
                    {
469
 
                        // 010-aa
470
 
                        addr = (naomibd->prot.s_shift >> (naomibd->prot.s_bits - 5)) & 3;
471
 
                        addr += 4;
472
 
                        naomibd->prot.s_bits -= 5;
473
 
                    }
474
 
                    else
475
 
                    {
476
 
                        // 011-aaa
477
 
                        if (naomibd->prot.s_bits < 6)
478
 
                            naomibd_m1dec_shiftin (naomibd);
479
 
                        addr = (naomibd->prot.s_shift >> (naomibd->prot.s_bits - 6)) & 7;
480
 
                        addr += 8;
481
 
                        naomibd->prot.s_bits -= 6;
482
 
                    }
483
 
                    naomibd_m1dec_storebyte(naomibd, naomibd->prot.s_dict [addr]);
484
 
                    break;
485
 
 
486
 
                case 2:
487
 
                    if (naomibd->prot.s_bits < 7)
488
 
                        naomibd_m1dec_shiftin(naomibd);
489
 
                    // 10-aaaaa
490
 
                    addr = (naomibd->prot.s_shift >> (naomibd->prot.s_bits - 7)) & 31;
491
 
                    addr += 16;
492
 
                    naomibd->prot.s_bits -= 7;
493
 
                    naomibd_m1dec_storebyte(naomibd, naomibd->prot.s_dict [addr]);
494
 
                    break;
495
 
 
496
 
                case 3:
497
 
                    if (naomibd->prot.s_bits < 8)
498
 
                        naomibd_m1dec_shiftin(naomibd);
499
 
                    // 11-aaaaaa
500
 
                    addr = (naomibd->prot.s_shift >> (naomibd->prot.s_bits - 8)) & 63;
501
 
                    addr += 48;
502
 
                    naomibd->prot.s_bits -= 8;
503
 
                    if (addr == 111)
504
 
                    {
505
 
                        // end of stream
506
 
                        eos = 1;
507
 
                    }
508
 
                    else
509
 
                    {
510
 
                        naomibd_m1dec_storebyte(naomibd, naomibd->prot.s_dict [addr]);
511
 
                    }
512
 
                    break;
513
 
        }
514
 
    }
515
 
}
516
 
 
517
 
// Streaming M2/M3 protection and decompression
518
 
 
519
 
INLINE UINT16 naomi_bswap16(UINT16 in)
520
 
{
521
 
    return ((in>>8) | (in<<8));
522
 
}
523
 
 
524
 
static UINT16 naomibd_get_decrypted_stream(naomibd_state *naomibd)
525
 
{
526
 
        UINT16 wordn = naomi_bswap16(naomibd->prot.ptr[naomibd->prot.count++]);
527
 
 
528
 
        naomibd->prot.aux_word = block_decrypt(naomibd->dc_gamekey, naomibd->dc_seqkey, naomibd->prot.seed++, wordn);
529
 
        wordn = (naomibd->prot.last_word&~3) | (naomibd->prot.aux_word&3);
530
 
        naomibd->prot.last_word = naomibd->prot.aux_word;
531
 
 
532
 
        return wordn;
533
 
}
534
 
 
535
 
static void naomibd_init_stream(naomibd_state *naomibd)
536
 
{
537
 
        naomibd->prot.last_word = 0;
538
 
 
539
 
        naomibd->prot.control_bits = naomibd_get_decrypted_stream(naomibd);
540
 
        naomibd->prot.heading_word = naomibd_get_decrypted_stream(naomibd);
541
 
 
542
 
        if (naomibd->prot.control_bits & 2)
543
 
        {
544
 
           naomibd->prot.pak_bit = 0;
545
 
           naomibd->prot.pak_state = CMD_READY;
546
 
           naomibd->prot.dec_count = 0;
547
 
           naomibd->prot.pak_buf_size = 256 << (naomibd->prot.control_bits & 1);
548
 
           naomibd->prot.pak_buf_pos = 0;
549
 
        }
550
 
}
551
 
 
552
 
static UINT16 naomibd_get_compressed_bit(naomibd_state *naomibd)
553
 
{
554
 
   if(naomibd->prot.pak_bit == 0)
555
 
   {
556
 
       naomibd->prot.pak_bit = 15;
557
 
       naomibd->prot.pak_word = naomibd_get_decrypted_stream(naomibd);
558
 
   }
559
 
   else
560
 
   {
561
 
       naomibd->prot.pak_bit--;
562
 
       naomibd->prot.pak_word<<=1;
563
 
   }
564
 
   return naomibd->prot.pak_word >> 15;
565
 
}
566
 
 
567
 
static UINT16 naomibd_get_decompressed_stream(naomibd_state *naomibd)
568
 
{
569
 
/* node format
570
 
0xxxxxxx - next node index
571
 
1a0bbccc - end node
572
 
           a - 0 = repeat
573
 
               1 = fetch
574
 
           b - if a = 1
575
 
               00 - fetch  0
576
 
               01 - fetch  1
577
 
               11 - fetch -1
578
 
               if a = 0
579
 
               000
580
 
           c - repeat/fetch counter
581
 
               count = ccc + 1
582
 
11111111 - empty node
583
 
*/
584
 
   static UINT8 trees[9][2][32] = {
585
 
      {
586
 
         {0x01,0x10,0x0f,0x05,0xc4,0x13,0x87,0x0a,0xcc,0x81,0xce,0x0c,0x86,0x0e,0x84,0xc2,
587
 
          0x11,0xc1,0xc3,0xcf,0x15,0xc8,0xcd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
588
 
         {0xc7,0x02,0x03,0x04,0x80,0x06,0x07,0x08,0x09,0xc9,0x0b,0x0d,0x82,0x83,0x85,0xc0,
589
 
          0x12,0xc6,0xc5,0x14,0x16,0xca,0xcb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
590
 
      },
591
 
      {
592
 
         {0x02,0x80,0x05,0x04,0x81,0x10,0x15,0x82,0x09,0x83,0x0b,0x0c,0x0d,0xdc,0x0f,0xde,
593
 
          0x1c,0xcf,0xc5,0xdd,0x86,0x16,0x87,0x18,0x19,0x1a,0xda,0xca,0xc9,0x1e,0xce,0xff,},
594
 
         {0x01,0x17,0x03,0x0a,0x08,0x06,0x07,0xc2,0xd9,0xc4,0xd8,0xc8,0x0e,0x84,0xcb,0x85,
595
 
          0x11,0x12,0x13,0x14,0xcd,0x1b,0xdb,0xc7,0xc0,0xc1,0x1d,0xdf,0xc3,0xc6,0xcc,0xff,},
596
 
      },
597
 
      {
598
 
         {0xc6,0x80,0x03,0x0b,0x05,0x07,0x82,0x08,0x15,0xdc,0xdd,0x0c,0xd9,0xc2,0x14,0x10,
599
 
          0x85,0x86,0x18,0x16,0xc5,0xc4,0xc8,0xc9,0xc0,0xcc,0xff,0xff,0xff,0xff,0xff,0xff,},
600
 
         {0x01,0x02,0x12,0x04,0x81,0x06,0x83,0xc3,0x09,0x0a,0x84,0x11,0x0d,0x0e,0x0f,0x19,
601
 
          0xca,0xc1,0x13,0xd8,0xda,0xdb,0x17,0xde,0xcd,0xcb,0xff,0xff,0xff,0xff,0xff,0xff,},
602
 
      },
603
 
      {
604
 
         {0x01,0x80,0x0d,0x04,0x05,0x15,0x83,0x08,0xd9,0x10,0x0b,0x0c,0x84,0x0e,0xc0,0x14,
605
 
          0x12,0xcb,0x13,0xca,0xc8,0xc2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
606
 
         {0xc5,0x02,0x03,0x07,0x81,0x06,0x82,0xcc,0x09,0x0a,0xc9,0x11,0xc4,0x0f,0x85,0xd8,
607
 
          0xda,0xdb,0xc3,0xdc,0xdd,0xc1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
608
 
      },
609
 
      {
610
 
         {0x01,0x80,0x06,0x0c,0x05,0x81,0xd8,0x84,0x09,0xdc,0x0b,0x0f,0x0d,0x0e,0x10,0xdb,
611
 
          0x11,0xca,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
612
 
         {0xc4,0x02,0x03,0x04,0xcb,0x0a,0x07,0x08,0xd9,0x82,0xc8,0x83,0xc0,0xc1,0xda,0xc2,
613
 
          0xc9,0xc3,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
614
 
      },
615
 
      {
616
 
         {0x01,0x02,0x06,0x0a,0x83,0x0b,0x07,0x08,0x09,0x82,0xd8,0x0c,0xd9,0xda,0xff,0xff,
617
 
          0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
618
 
         {0xc3,0x80,0x03,0x04,0x05,0x81,0xca,0xc8,0xdb,0xc9,0xc0,0xc1,0x0d,0xc2,0xff,0xff,
619
 
          0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
620
 
      },
621
 
      {
622
 
         {0x01,0x02,0x03,0x04,0x81,0x07,0x08,0xd8,0xda,0xd9,0xff,0xff,0xff,0xff,0xff,0xff,
623
 
          0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
624
 
         {0xc2,0x80,0x05,0xc9,0xc8,0x06,0x82,0xc0,0x09,0xc1,0xff,0xff,0xff,0xff,0xff,0xff,
625
 
          0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
626
 
      },
627
 
      {
628
 
         {0x01,0x80,0x04,0xc8,0xc0,0xd9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
629
 
          0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
630
 
         {0xc1,0x02,0x03,0x81,0x05,0xd8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
631
 
          0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
632
 
      },
633
 
      {
634
 
         {0x01,0xd8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
635
 
          0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
636
 
         {0xc0,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
637
 
          0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,},
638
 
      },
639
 
   };
640
 
 
641
 
   UINT32 word_complete = 2;
642
 
   UINT16 wordn = 0;
643
 
 
644
 
   while(word_complete)
645
 
   {
646
 
      switch(naomibd->prot.pak_state)
647
 
      {
648
 
      case CMD_READY:
649
 
      {
650
 
         UINT32 tmp = 0;
651
 
         INT32 slot = (naomibd->prot.pak_buf_pos & (naomibd->prot.pak_buf_size-1));
652
 
         if(slot > 0)
653
 
         {
654
 
            if(slot < (naomibd->prot.pak_buf_size-7))
655
 
               slot = 1;
656
 
            else
657
 
               slot = (slot & 7) + 1;
658
 
         }
659
 
         while (!(tmp&0x80))
660
 
           if(naomibd_get_compressed_bit(naomibd))
661
 
              tmp = trees[slot][1][tmp];
662
 
           else
663
 
              tmp = trees[slot][0][tmp];
664
 
         if(tmp != 0xff)
665
 
         {
666
 
            naomibd->prot.pak_byte = (tmp&7)+1;
667
 
            if(tmp&0x40)
668
 
            {
669
 
               static INT32 cmds[4] = {0, 1, 0, -1};
670
 
               naomibd->prot.pak_fetch_ofs = cmds[(tmp&0x18)>>3];
671
 
               naomibd->prot.pak_state = CMD_FETCH;
672
 
            }
673
 
            else
674
 
            {
675
 
               UINT8 byten;
676
 
               naomibd->prot.pak_state = CMD_REPEAT;
677
 
               byten =          naomibd_get_compressed_bit(naomibd)  << 1;
678
 
               byten = (byten | naomibd_get_compressed_bit(naomibd)) << 1;
679
 
               byten = (byten | naomibd_get_compressed_bit(naomibd)) << 1;
680
 
               byten = (byten | naomibd_get_compressed_bit(naomibd)) << 1;
681
 
               byten = (byten | naomibd_get_compressed_bit(naomibd)) << 1;
682
 
               byten = (byten | naomibd_get_compressed_bit(naomibd)) << 1;
683
 
               byten = (byten | naomibd_get_compressed_bit(naomibd)) << 1;
684
 
               byten =  byten | naomibd_get_compressed_bit(naomibd);
685
 
               naomibd->prot.cmd_byte = byten;
686
 
            }
687
 
         }
688
 
         break;
689
 
      }
690
 
      case CMD_FETCH:
691
 
         naomibd->prot.cmd_byte = naomibd->prot.pak_buf[(naomibd->prot.pak_buf_pos-naomibd->prot.pak_buf_size+naomibd->prot.pak_fetch_ofs)&(PACK_BUF_SIZE-1)];
692
 
 
693
 
      case CMD_REPEAT:
694
 
         naomibd->prot.pak_buf[naomibd->prot.pak_buf_pos&(PACK_BUF_SIZE-1)]=naomibd->prot.cmd_byte;
695
 
         if(word_complete&2)
696
 
                 {
697
 
            wordn = naomibd->prot.cmd_byte << 8;
698
 
                 }
699
 
         else
700
 
                 {
701
 
            wordn = wordn | naomibd->prot.cmd_byte;
702
 
                 }
703
 
         word_complete--;
704
 
         naomibd->prot.pak_byte--;
705
 
         naomibd->prot.pak_buf_pos++;
706
 
         if(naomibd->prot.pak_byte == 0) naomibd->prot.pak_state = CMD_READY;
707
 
         break;
708
 
      }
709
 
   }
710
 
   return wordn;
711
 
}
712
 
 
713
 
// stream read protected PIO hook
714
 
//-----------------------------------------------------------
715
 
static UINT16 naomibd_get_data_stream(naomibd_state *naomibd)
716
 
{
717
 
        UINT16 wordn;
718
 
 
719
 
        if(naomibd->prot.control_bits&2)
720
 
        {
721
 
                wordn = naomibd_get_decompressed_stream(naomibd);
722
 
        }
723
 
        else
724
 
        {
725
 
                wordn = naomibd_get_decrypted_stream(naomibd);
726
 
        }
727
 
 
728
 
        return wordn;
729
 
}
730
 
 
731
 
void *naomibd_get_memory(device_t *device)
732
 
{
733
 
        naomibd_state *naomibd = get_safe_token(device);
734
 
 
735
 
    // for M1 decodes, return the buffer we'll DMA from
736
 
        if (!(naomibd->dma_offset_flags & NAOMIBD_FLAG_DMA_COMPRESSION) && (naomibd->type == ROM_BOARD) && (naomibd->dc_dmakey != 0))
737
 
    {
738
 
        // perform the M1 decode
739
 
        naomibd_m1_decode(naomibd);
740
 
 
741
 
        // return the pointer to our output buffer
742
 
        return naomibd->dc_cart_ram;
743
 
    }
744
 
 
745
 
    if (!(naomibd->dma_offset_flags & NAOMIBD_FLAG_DMA_COMPRESSION) && (naomibd->type == ROM_BOARD))
746
 
    {
747
 
        logerror("Unhandled M1 DMA with key %x, flags %x, offset %x\n", naomibd->dc_dmakey, naomibd->dma_offset_flags, naomibd->dma_offset);
748
 
    }
749
 
 
750
 
        return get_safe_token(device)->memory;
751
 
}
752
 
 
753
 
offs_t naomibd_get_dmaoffset(device_t *device)
754
 
{
755
 
        naomibd_state *naomibd = get_safe_token(device);
756
 
        offs_t result = 0;
757
 
 
758
 
        #if NAOMIBD_PRINTF_PROTECTION
759
 
        printf("DMA source %08x, flags %x\n", get_safe_token(device)->dma_offset, get_safe_token(device)->dma_offset_flags);
760
 
        #endif
761
 
 
762
 
        // if the flag is cleared that lets the protection chip go,
763
 
        // we need to handle this specially.  but not on DIMM boards or if there's no key.
764
 
        if (!(naomibd->dma_offset_flags & NAOMIBD_FLAG_DMA_COMPRESSION) && (naomibd->type == ROM_BOARD) && (naomibd->dc_dmakey != 0))
765
 
        {
766
 
        // no offset, start at the beginning of cart ram for M1 transfers
767
 
        result = 0;
768
 
        }
769
 
    else
770
 
    {
771
 
        result = get_safe_token(device)->dma_offset;
772
 
    }
773
 
 
774
 
        return result;
775
 
}
776
 
 
777
 
 
778
 
/*************************************
779
 
 *
780
 
 *  Common initialization
781
 
 *
782
 
 *************************************/
783
 
 
784
 
 
785
 
 
786
 
static void naomibd_postload(naomibd_state *v)
787
 
{
788
 
}
789
 
 
790
 
 
791
 
static void init_save_state(device_t *device)
792
 
{
793
 
        naomibd_state *v = get_safe_token(device);
794
 
 
795
 
        device->machine().save().register_postload(save_prepost_delegate(FUNC(naomibd_postload), v));
796
 
 
797
 
        /* register states */
798
 
        device->save_item(NAME(v->rom_offset));
799
 
        device->save_item(NAME(v->rom_offset_flags));
800
 
        device->save_item(NAME(v->dma_count));
801
 
        device->save_item(NAME(v->dma_offset));
802
 
        device->save_item(NAME(v->dma_offset_flags));
803
 
        device->save_item(NAME(v->prot_offset));
804
 
        device->save_item(NAME(v->prot_key));
805
 
        device->save_item(NAME(v->aw_offset));
806
 
        device->save_item(NAME(v->aw_file_base));
807
 
        device->save_item(NAME(v->aw_file_offset));
808
 
        device->save_item(NAME(v->dc_m3_ptr));
809
 
        device->save_item(NAME(v->dc_cart_ram));
810
 
    device->save_item(NAME(v->prot.last_word));
811
 
    device->save_item(NAME(v->prot.aux_word));
812
 
    device->save_item(NAME(v->prot.pak_word));
813
 
    device->save_item(NAME(v->prot.heading_word));
814
 
    device->save_item(NAME(v->prot.count));
815
 
    device->save_item(NAME(v->prot.pak_bit));
816
 
    device->save_item(NAME(v->prot.control_bits));
817
 
    device->save_item(NAME(v->prot.pak_state));
818
 
    device->save_item(NAME(v->prot.dec_count));
819
 
    device->save_item(NAME(v->prot.pak_buf_size));
820
 
    device->save_item(NAME(v->prot.pak_buf_pos));
821
 
    device->save_item(NAME(v->prot.pak_fetch_ofs));
822
 
    device->save_item(NAME(v->prot.pak_byte));
823
 
    device->save_item(NAME(v->prot.cmd_byte));
824
 
    device->save_item(NAME(v->prot.seed));
825
 
    device->save_item(NAME(v->prot.s_xor));
826
 
    device->save_item(NAME(v->prot.s_dict));
827
 
    device->save_item(NAME(v->prot.s_subst));
828
 
    device->save_item(NAME(v->prot.s_out_len));
829
 
    device->save_item(NAME(v->prot.s_out_cnt));
830
 
    device->save_item(NAME(v->prot.s_shift));
831
 
    device->save_item(NAME(v->prot.s_bits));
832
 
    device->save_item(NAME(v->prot.s_in_len));
833
 
    device->save_item(NAME(v->prot.s_in_pos));
834
 
}
835
 
 
836
 
 
837
 
 
838
 
/*************************************
839
 
 *
840
 
 *  Reset
841
 
 *
842
 
 *************************************/
843
 
 
844
 
static void soft_reset(naomibd_state *v)
845
 
{
846
 
        v->dc_m3_ptr = 0;
847
 
        v->dc_seqkey = 0;
848
 
}
849
 
 
850
 
 
851
 
 
852
 
/*************************************
853
 
 *
854
 
 *  Handlers
855
 
 *
856
 
 *************************************/
857
 
 
858
 
READ64_DEVICE_HANDLER( naomibd_r )
859
 
{
860
 
        naomibd_state *v = get_safe_token(device);
861
 
        UINT8 *ROM = (UINT8 *)v->memory;
862
 
 
863
 
        // AW board is different, shouldn't ever be read
864
 
        if (v->type == AW_ROM_BOARD)
865
 
        {
866
 
                mame_printf_debug("AW_ROM_BOARD read @ %x mask %" I64FMT "x\n", offset, mem_mask);
867
 
                return U64(0xffffffffffffffff);
868
 
        }
869
 
 
870
 
        // ROM_DATA
871
 
        if ((offset == 1) && ACCESSING_BITS_0_15)
872
 
        {
873
 
                UINT64 ret = 0;
874
 
 
875
 
                if (v->rom_offset_flags & NAOMIBD_FLAG_SPECIAL_MODE)
876
 
                {
877
 
                        // can we live-decrypt this game?
878
 
                        if (v->dc_gamekey != -1)
879
 
                        {
880
 
                                ret = (UINT64)naomibd_get_data_stream(v);
881
 
                        }
882
 
                        else
883
 
                        {
884
 
                ret = U64(0);
885
 
                        }
886
 
                }
887
 
                else
888
 
                {
889
 
                        ret = (UINT64)(ROM[v->rom_offset] | (ROM[v->rom_offset+1]<<8));
890
 
                }
891
 
 
892
 
                if (v->rom_offset_flags & NAOMIBD_FLAG_AUTO_ADVANCE)
893
 
                {
894
 
                        v->rom_offset += 2;
895
 
                }
896
 
 
897
 
                return ret;
898
 
        }
899
 
        else if ((offset == 2) && ACCESSING_BITS_32_63)
900
 
        {
901
 
                //  Actel FPGA ID, used on some games for a "special" ROM test.
902
 
                //
903
 
                //  without this (by returning 0xffff) some games will do a rom test where
904
 
                //  the IC numbers tested do not relate to the actual ROMs on the cart,
905
 
                //  and a fake 'IC1' will be tested, which returns mirrored data from the
906
 
                //  other roms in order to pass if enabled on the real hardware.
907
 
                //  (certain bios / board combinations will also cause this, so it is
908
 
                //   important that we mirror the data in the rom loading using ROM_COPY)
909
 
 
910
 
                //return (UINT64)0xffff << 32;
911
 
                return (UINT64)actel_id << 32;
912
 
        }
913
 
        else if ((offset == 7) && ACCESSING_BITS_32_47)
914
 
        {
915
 
                // 5f703c
916
 
                mame_printf_verbose("ROM: read 5f703c\n");
917
 
                return (UINT64)0xffff << 32;
918
 
        }
919
 
        else if ((offset == 8) && ACCESSING_BITS_0_15)
920
 
        {
921
 
                // 5f7040
922
 
                mame_printf_verbose("ROM: read 5f7040\n");
923
 
                return 0;
924
 
        }
925
 
        else if ((offset == 8) && ACCESSING_BITS_32_47)
926
 
        {
927
 
                // 5f7044
928
 
                mame_printf_verbose("ROM: read 5f7044\n");
929
 
                return 0;
930
 
        }
931
 
        else if ((offset == 9) && ACCESSING_BITS_0_15)
932
 
        {
933
 
                // 5f7048
934
 
                mame_printf_verbose("ROM: read 5f7048\n");
935
 
                return 0;
936
 
        }
937
 
        else if ((offset == 9) && ACCESSING_BITS_32_47)
938
 
        {
939
 
                // 5f704c
940
 
                mame_printf_verbose("ROM: read 5f704c\n");
941
 
                return (UINT64)1 << 32;
942
 
        }
943
 
        else if ((offset == 15) && ACCESSING_BITS_32_47) // boardid read
944
 
        {
945
 
                UINT64 ret;
946
 
 
947
 
                ret = device->machine().device<x76f100_device>("naomibd_eeprom")->sda_r() << 15;
948
 
 
949
 
                return ret << 32;
950
 
        }
951
 
        else
952
 
        {
953
 
                //mame_printf_verbose("%s:ROM: read mask %" I64FMT "x @ %x\n", machine.describe_context(), mem_mask, offset);
954
 
        }
955
 
 
956
 
        return U64(0xffffffffffffffff);
957
 
}
958
 
 
959
 
WRITE64_DEVICE_HANDLER( naomibd_w )
960
 
{
961
 
        naomibd_state *v = get_safe_token(device);
962
 
 
963
 
        // AW board
964
 
        if (v->type == AW_ROM_BOARD)
965
 
        {
966
 
                //printf("AW: %" I64FMT "x to ROM board @ %x (mask %" I64FMT "x)\n", data, offset, mem_mask);
967
 
 
968
 
                switch (offset)
969
 
                {
970
 
                        case 0:
971
 
                        {
972
 
                                if(ACCESSING_BITS_0_15)
973
 
                                {
974
 
                                        // EPR_OFFSETL
975
 
                                        v->aw_offset &= 0xffff0000;
976
 
                                        v->aw_offset |= (data & 0xffff);
977
 
                                        v->dma_offset = v->aw_offset*2;
978
 
                                        //printf("EPR_OFFSETL = %x, dma_offset %x\n", (UINT32)data, v->dma_offset);
979
 
                                }
980
 
                                else if(ACCESSING_BITS_32_47 || ACCESSING_BITS_32_63)
981
 
                                {
982
 
                                        // EPR_OFFSETH
983
 
                                        v->aw_offset &= 0xffff;
984
 
                                        v->aw_offset |= ((data>>16) & 0xffff0000);
985
 
                                        v->dma_offset = v->aw_offset*2;
986
 
                                        v->dma_offset_flags = NAOMIBD_FLAG_DMA_COMPRESSION|NAOMIBD_FLAG_AUTO_ADVANCE;   // force normal DMA mode
987
 
                                        //printf("EPR_OFFSETH = %x, dma_offset %x\n", (UINT32)(data>>32), v->dma_offset);
988
 
                                }
989
 
 
990
 
                        }
991
 
                        break;
992
 
 
993
 
                        case 1:
994
 
                        {
995
 
                                if(ACCESSING_BITS_32_47 || ACCESSING_BITS_32_63)
996
 
                                {
997
 
                                        // MPR_RECORD_INDEX
998
 
                                        //printf("%x to RECORD_INDEX\n", (UINT32)(data>>32));
999
 
                                        v->dma_offset = 0x1000000 + (0x40 * (data>>32));
1000
 
                                }
1001
 
                        }
1002
 
                        break;
1003
 
 
1004
 
                        case 2:
1005
 
                        {
1006
 
                                if(ACCESSING_BITS_0_15)
1007
 
                                {
1008
 
                                        UINT8 *ROM = (UINT8 *)v->memory;
1009
 
                                        UINT32 base;
1010
 
 
1011
 
                                        // MPR_FIRST_FILE_INDEX (usually 3)
1012
 
                                        base = data * 64;
1013
 
                                        v->aw_file_base = ROM[0x100000b+base]<<24 | ROM[0x100000a+base]<<16 | ROM[0x1000009+base]<<8 | ROM[0x1000008+base];
1014
 
                                        v->aw_file_base += 0x1000000;
1015
 
                                        //printf("%x to FIRST_FILE_INDEX, file_base = %x\n", (UINT32)data, v->aw_file_base);
1016
 
                                }
1017
 
                                else if(ACCESSING_BITS_32_47 || ACCESSING_BITS_32_63)
1018
 
                                {
1019
 
                                        // MPR_FILE_OFFSETL
1020
 
                                        v->aw_file_offset &= 0xffff0000;
1021
 
                                        v->aw_file_offset |= (data>>32) & 0xffff;
1022
 
                                        v->dma_offset = v->aw_file_base + (v->aw_file_offset*2);
1023
 
                                        //printf("%x to FILE_OFFSETL, file_offset %x, dma_offset %x\n", (UINT32)(data>>32), v->aw_file_offset, v->dma_offset);
1024
 
                                }
1025
 
                        }
1026
 
                        break;
1027
 
 
1028
 
                        case 3:
1029
 
                        {
1030
 
                                if(ACCESSING_BITS_0_15)
1031
 
                                {
1032
 
                                        // MPR_FILE_OFFSETH
1033
 
                                        v->aw_file_offset &= 0xffff;
1034
 
                                        v->aw_file_offset |= (data & 0xffff)<<16;
1035
 
                                        v->dma_offset = v->aw_file_base + (v->aw_file_offset*2);
1036
 
                                        //printf("%x to FILE_OFFSETH, file_offset %x, dma_offset %x\n", (UINT32)data, v->aw_file_offset, v->dma_offset);
1037
 
                                }
1038
 
                        }
1039
 
                        break;
1040
 
 
1041
 
                        default:
1042
 
                                logerror("AW: unhandled %" I64FMT "x to ROM board @ %x (mask %" I64FMT "x)\n", data, offset, mem_mask);
1043
 
                        break;
1044
 
                }
1045
 
 
 
52
*/
 
53
 
 
54
DEVICE_ADDRESS_MAP_START(submap, 16, naomi_board)
 
55
        AM_RANGE(0x00, 0x01) AM_WRITE(rom_offseth_w)
 
56
        AM_RANGE(0x02, 0x03) AM_WRITE(rom_offsetl_w)
 
57
        AM_RANGE(0x04, 0x05) AM_READWRITE(rom_data_r, rom_data_w)
 
58
        AM_RANGE(0x06, 0x07) AM_WRITE(dma_offseth_w)
 
59
        AM_RANGE(0x08, 0x09) AM_WRITE(dma_offsetl_w)
 
60
        AM_RANGE(0x0a, 0x0b) AM_WRITE(dma_count_w)
 
61
        AM_RANGE(0x3c, 0x3d) AM_WRITE(boardid_w)
 
62
        AM_RANGE(0x3e, 0x3f) AM_READ(boardid_r)
 
63
 
 
64
        AM_RANGE(0x00, 0xff) AM_READ(default_r)
 
65
ADDRESS_MAP_END
 
66
 
 
67
naomi_board::naomi_board(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
 
68
        : naomi_g1_device(mconfig, type, name, tag, owner, clock)
 
69
{
 
70
        eeprom_tag = 0;
 
71
}
 
72
 
 
73
void naomi_board::static_set_eeprom_tag(device_t &device, const char *_eeprom_tag)
 
74
{
 
75
        naomi_board &dev = downcast<naomi_board &>(device);
 
76
        dev.eeprom_tag = _eeprom_tag;
 
77
}
 
78
 
 
79
 
 
80
void naomi_board::device_start()
 
81
{
 
82
        naomi_g1_device::device_start();
 
83
 
 
84
        save_item(NAME(rom_offset));
 
85
        save_item(NAME(dma_offset));
 
86
        save_item(NAME(dma_count));
 
87
        save_item(NAME(dma_cur_offset));
 
88
        save_item(NAME(pio_ready));
 
89
        save_item(NAME(dma_ready));
 
90
 
 
91
        if(eeprom_tag)
 
92
                eeprom = machine().device<x76f100_device>(eeprom_tag);
 
93
        else
 
94
                eeprom = 0;
 
95
}
 
96
 
 
97
void naomi_board::device_reset()
 
98
{
 
99
        naomi_g1_device::device_reset();
 
100
        rom_offset = 0;
 
101
        dma_offset = 0;
 
102
        dma_cur_offset = 0;
 
103
        pio_ready = false;
 
104
        dma_ready = false;
 
105
}
 
106
 
 
107
void naomi_board::dma_get_position(UINT8 *&base, UINT32 &limit, bool to_mainram)
 
108
{
 
109
        if(!to_mainram) {
 
110
                base = 0;
 
111
                limit = 0;
1046
112
                return;
1047
113
        }
1048
114
 
1049
 
        switch(offset)
1050
 
        {
1051
 
                case 0:
1052
 
                {
1053
 
                        if(ACCESSING_BITS_0_15)
1054
 
                        {
1055
 
                                // ROM_OFFSETH
1056
 
                                v->rom_offset &= 0xffff;
1057
 
                                v->rom_offset |= (data & 0x1fff)<<16;
1058
 
                                v->rom_offset_flags = data >> 12;
1059
 
                        }
1060
 
                        if(ACCESSING_BITS_32_47)
1061
 
                        {
1062
 
                                // ROM_OFFSETL
1063
 
                                v->rom_offset &= 0xffff0000;
1064
 
                                v->rom_offset |= ((data >> 32) & 0xffff);
1065
 
                        }
1066
 
 
1067
 
                        #if NAOMIBD_PRINTF_PROTECTION
1068
 
                        printf("PIO: offset to %x\n", v->rom_offset);
1069
 
                        #endif
1070
 
                }
1071
 
                break;
1072
 
                case 1:
1073
 
                {
1074
 
                        if(ACCESSING_BITS_32_47 || ACCESSING_BITS_32_63)
1075
 
                        {
1076
 
                                // DMA_OFFSETH
1077
 
                                v->dma_offset &= 0xffff;
1078
 
                                v->dma_offset |= (data >> 16) & 0x1fff0000;
1079
 
                                v->dma_offset_flags = (data>>(28+16));
1080
 
                        }
1081
 
                        if(ACCESSING_BITS_0_15)
1082
 
                        {
1083
 
                                // ROM_DATA - used to access registers in the protection chip
1084
 
                                switch (v->rom_offset)
1085
 
                                {
1086
 
                                        case 0x1fff8:   // offset low
1087
 
                                                v->prot_offset &= 0xffff0000;
1088
 
                                                v->prot_offset |= (UINT32)data;
1089
 
                                                break;
1090
 
 
1091
 
                                        case 0x1fffa:   // offset high
1092
 
                                                v->prot_offset &= 0xffff;
1093
 
                                                v->prot_offset |= (UINT32)data<<16;
1094
 
                                                break;
1095
 
 
1096
 
                                        case 0x1fffc:   // decryption key
1097
 
                                                v->prot_key = data;
1098
 
 
1099
 
                                                #if NAOMIBD_PRINTF_PROTECTION
1100
 
                                                printf("Protection: set up read @ %x, key %x (PIO %x DMA %x) [%s]\n", v->prot_offset*2, v->prot_key, v->rom_offset, v->dma_offset, device->machine().describe_context());
1101
 
                                                #endif
1102
 
 
1103
 
                                                // if dc_gamekey isn't -1, we can live-decrypt this one
1104
 
                                                if (v->dc_gamekey != -1)
1105
 
                                                {
1106
 
                                                        UINT8 *ROM = (UINT8 *)v->memory;
1107
 
 
1108
 
                                                        v->dc_seqkey = v->prot_key;
1109
 
 
1110
 
                                                        if (v->prot_offset != 0x2000000/2)
1111
 
                                                        {
1112
 
                                                                // M2: decrypt from ROM
1113
 
                                                                v->prot.ptr = (UINT16 *)&ROM[v->prot_offset*2];
1114
 
                                                                v->prot.seed = v->prot_offset&0xffff;
1115
 
                                                        #if NAOMIBD_PRINTF_PROTECTION
1116
 
                                                        printf("M2 decrypt: gamekey %x seqkey %x length %x\n", v->dc_gamekey, v->dc_seqkey, v->dc_m3_ptr);
1117
 
                                                        #endif
1118
 
                                                        }
1119
 
                                                        else
1120
 
                                                        {
1121
 
                                                                // M3: decrypt from cart ram
1122
 
                                                                v->prot.ptr = (UINT16 *)v->dc_cart_ram;
1123
 
                                                                v->prot.seed = 0;
1124
 
                                                        #if NAOMIBD_PRINTF_PROTECTION
1125
 
                                                        printf("M3 decrypt: gamekey %x seqkey %x length %x\n", v->dc_gamekey, v->dc_seqkey, v->dc_m3_ptr);
1126
 
                                                        #endif
1127
 
                                                        }
1128
 
 
1129
 
                                                        v->prot.count = 0;
1130
 
                                                        naomibd_init_stream(v);
1131
 
 
1132
 
                                                        v->dc_m3_ptr = 0;
1133
 
                                                }
1134
 
                        #if NAOMIBD_PRINTF_PROTECTION
1135
 
                        else
1136
 
                        {
1137
 
                            printf("naomibd: protection not handled for this game\n");
1138
 
                        }
1139
 
                        #endif
1140
 
                                                break;
1141
 
 
1142
 
                                        case 0x2000000:
1143
 
                                        case 0x2020000:
1144
 
                                                v->dc_cart_ram[v->dc_m3_ptr] = (data&0xff);
1145
 
                                                v->dc_cart_ram[v->dc_m3_ptr+1] = (data>>8)&0xff;
1146
 
                                                v->dc_m3_ptr += 2;
1147
 
                                                break;
1148
 
 
1149
 
                                        default:
1150
 
                                                #if NAOMIBD_PRINTF_PROTECTION
1151
 
                                                printf("naomibd: unknown protection write %x @ %x\n", (UINT32)data, v->rom_offset);
1152
 
                                                #endif
1153
 
                                                break;
1154
 
                                }
1155
 
                        }
1156
 
                }
1157
 
                break;
1158
 
                case 2:
1159
 
                {
1160
 
                        if(ACCESSING_BITS_0_15)
1161
 
                        {
1162
 
                                // DMA_OFFSETL
1163
 
                                v->dma_offset &= 0xffff0000;
1164
 
                                v->dma_offset |= (data & 0xffff);
1165
 
                        }
1166
 
                        if(ACCESSING_BITS_32_63)
1167
 
                        {
1168
 
                                // NAOMI_DMA_COUNT
1169
 
                                v->dma_count = data >> 32;
1170
 
                        }
1171
 
                }
1172
 
                break;
1173
 
                case 7:
1174
 
                {
1175
 
                        if(ACCESSING_BITS_32_47)
1176
 
                                mame_printf_verbose("ROM: write 5f703c\n");
1177
 
                }
1178
 
                break;
1179
 
                case 8:
1180
 
                {
1181
 
                        if(ACCESSING_BITS_0_15)
1182
 
                                mame_printf_verbose("ROM: write 5f7040\n");
1183
 
                        if(ACCESSING_BITS_32_47)
1184
 
                                mame_printf_verbose("ROM: write 5f7044\n");
1185
 
                }
1186
 
                break;
1187
 
                case 9:
1188
 
                {
1189
 
                        if(ACCESSING_BITS_0_15)
1190
 
                                mame_printf_verbose("ROM: write 5f7048\n");
1191
 
                        if(ACCESSING_BITS_32_47)
1192
 
                                mame_printf_verbose("ROM: write 5f704c\n");
1193
 
                }
1194
 
                break;
1195
 
                case 15:
1196
 
                {
1197
 
                        if(ACCESSING_BITS_0_15)
1198
 
                        {
1199
 
                                x76f100_device *x76f100 = device->machine().device<x76f100_device>("naomibd_eeprom");
1200
 
                                // NAOMI_BOARDID_WRITE
1201
 
                                x76f100->cs_w((data >> 2) & 1);
1202
 
                                x76f100->rst_w((data >> 3) & 1);
1203
 
                                x76f100->scl_w((data >> 1) & 1);
1204
 
                                x76f100->sda_w((data >> 0) & 1);
1205
 
                        }
1206
 
                }
1207
 
                break;
1208
 
                default:
1209
 
                        mame_printf_verbose("%s: ROM: write %" I64FMT "x to %x, mask %" I64FMT "x\n", device->machine().describe_context(), data, offset, mem_mask);
1210
 
                        break;
1211
 
        }
1212
 
}
1213
 
 
1214
 
 
1215
 
 
1216
 
/*************************************
1217
 
 *
1218
 
 *  Load rom file from gdrom
1219
 
 *
1220
 
 *************************************/
1221
 
 
1222
 
#define FILENAME_LENGTH 24
1223
 
 
1224
 
static void load_rom_gdrom(running_machine& machine, naomibd_state *v)
1225
 
{
1226
 
//  UINT32 result;
1227
 
        cdrom_file *gdromfile;
1228
 
        UINT8 buffer[2048];
1229
 
        UINT8 *ptr;
1230
 
        UINT32 start,size,sectors,dir;
1231
 
        int pos,len,a;
1232
 
        char name[128];
1233
 
        UINT64 key;
1234
 
        UINT8* realpic; // todo, add to device
1235
 
 
1236
 
        memset(name,'\0',128);
1237
 
 
1238
 
        realpic = machine.region("pic")->base();
1239
 
 
1240
 
        if (realpic)
1241
 
        {
1242
 
                //printf("Real PIC binary found\n");
1243
 
                int i;
1244
 
                for (i=0;i<7;i++)
1245
 
                {
1246
 
                        name[i] = realpic[0x7c0+i*2];
1247
 
                }
1248
 
                for (i=0;i<7;i++)
1249
 
                {
1250
 
                        name[i+7] = realpic[0x7e0+i*2];
1251
 
                }
1252
 
        }
1253
 
        else
1254
 
        {
1255
 
                // use extracted pic data
1256
 
                logerror("This PIC key hasn't been converted to a proper PIC binary yet!\n");
1257
 
                memcpy(name, v->picdata+33, 7);
1258
 
                memcpy(name+7, v->picdata+25, 7);
1259
 
        }
1260
 
 
1261
 
        gdromfile = cdrom_open(v->gdromchd);
1262
 
        // primary volume descriptor
1263
 
        // read frame 0xb06e (frame=sector+150)
1264
 
        // dimm board firmware starts straight from this frame
1265
 
        cdrom_read_data(gdromfile, 0xb06e - 150, buffer, CD_TRACK_MODE1);
1266
 
        start=((buffer[0x8c+0] << 0) |
1267
 
                   (buffer[0x8c+1] << 8) |
1268
 
                   (buffer[0x8c+2] << 16) |
1269
 
                   (buffer[0x8c+3] << 24));
1270
 
        // path table
1271
 
        cdrom_read_data(gdromfile, start, buffer, CD_TRACK_MODE1);
1272
 
        start=((buffer[0x2+0] << 0) |
1273
 
                   (buffer[0x2+1] << 8) |
1274
 
                   (buffer[0x2+2] << 16) |
1275
 
                   (buffer[0x2+3] << 24));
1276
 
        dir = start;
1277
 
        // directory
1278
 
        cdrom_read_data(gdromfile, dir, buffer, CD_TRACK_MODE1);
1279
 
        // find data of file
1280
 
        start = 0;
1281
 
        size = 0;
1282
 
        logerror("Looking for file %s\n", name);
1283
 
        for (pos = 0;pos < 2048;pos += buffer[pos])
1284
 
        {
1285
 
                a=0;
1286
 
                if (!(buffer[pos+25] & 2))
1287
 
                {
1288
 
                        len=buffer[pos+32];
1289
 
                        for (a=0;a < FILENAME_LENGTH;a++)
1290
 
                        {
1291
 
                                if ((buffer[pos+33+a] == ';') && (name[a] == 0))
1292
 
                                {
1293
 
                                        a=FILENAME_LENGTH+1;
1294
 
                                        break;
1295
 
                                }
1296
 
                                if (buffer[pos+33+a] != name[a])
1297
 
                                        break;
1298
 
                                if (a == len)
1299
 
                                {
1300
 
                                        if (name[a] == 0)
1301
 
                                                a = FILENAME_LENGTH+1;
1302
 
                                        else
1303
 
                                                a = FILENAME_LENGTH;
1304
 
                                }
1305
 
                        }
1306
 
                }
1307
 
                if (a == FILENAME_LENGTH+1)
1308
 
                {
1309
 
                        // start sector and size of file
1310
 
                        start=((buffer[pos+2] << 0) |
1311
 
                                   (buffer[pos+3] << 8) |
1312
 
                                   (buffer[pos+4] << 16) |
1313
 
                                   (buffer[pos+5] << 24));
1314
 
                        size =((buffer[pos+10] << 0) |
1315
 
                                   (buffer[pos+11] << 8) |
1316
 
                                   (buffer[pos+12] << 16) |
1317
 
                                   (buffer[pos+13] << 24));
1318
 
 
1319
 
                        logerror("start %08x size %08x\n", start,size);
1320
 
                        break;
1321
 
                }
1322
 
                if (buffer[pos] == 0)
1323
 
                        break;
1324
 
        }
1325
 
 
1326
 
        if ((start != 0) && (size == 0x100))
1327
 
        {
1328
 
                // read file
1329
 
                cdrom_read_data(gdromfile, start, buffer, CD_TRACK_MODE1);
1330
 
                // get "rom" file name
1331
 
                memset(name,'\0', 128);
1332
 
                memcpy(name, buffer+0xc0, FILENAME_LENGTH-1);
1333
 
 
1334
 
 
1335
 
                // directory
1336
 
                cdrom_read_data(gdromfile, dir, buffer, CD_TRACK_MODE1);
1337
 
                // find data of "rom" file
1338
 
                start = 0;
1339
 
                size = 0;
1340
 
 
1341
 
                logerror("Looking for file %s\n", name);
1342
 
                for (pos = 0;pos < 2048;pos += buffer[pos])
1343
 
                {
1344
 
                        a = 0;
1345
 
                        if (!(buffer[pos+25] & 2))
1346
 
                        {
1347
 
                                len = buffer[pos+32];
1348
 
                                for (a=0;a < FILENAME_LENGTH;a++)
1349
 
                                {
1350
 
                                        if ((buffer[pos+33+a] == ';') && (name[a] == 0))
1351
 
                                        {
1352
 
                                                a=FILENAME_LENGTH+1;
1353
 
                                                break;
1354
 
                                        }
1355
 
                                        if (buffer[pos+33+a] != name[a])
1356
 
                                                break;
1357
 
                                        if (a == len)
1358
 
                                        {
1359
 
                                                if (name[a] == 0)
1360
 
                                                        a = (FILENAME_LENGTH+1);
1361
 
                                                else
1362
 
                                                        a = FILENAME_LENGTH;
1363
 
                                        }
1364
 
                                }
1365
 
                        }
1366
 
                        if (a == (FILENAME_LENGTH+1))
1367
 
                        {
1368
 
                                // start sector and size of file
1369
 
                                start=((buffer[pos+2] << 0) |
1370
 
                                           (buffer[pos+3] << 8) |
1371
 
                                           (buffer[pos+4] << 16) |
1372
 
                                           (buffer[pos+5] << 24));
1373
 
                                size =((buffer[pos+10] << 0) |
1374
 
                                           (buffer[pos+11] << 8) |
1375
 
                                           (buffer[pos+12] << 16) |
1376
 
                                           (buffer[pos+13] << 24));
1377
 
 
1378
 
                                logerror("start %08x size %08x\n", start,size);
1379
 
                                break;
1380
 
                        }
1381
 
                        if (buffer[pos] == 0)
1382
 
                                break;
1383
 
                }
1384
 
                if (start != 0)
1385
 
                {
1386
 
                        // read encrypted data into memory
1387
 
                        ptr = v->memory;
1388
 
                        sectors = (size+2047)/2048;
1389
 
                        while (sectors > 0)
1390
 
                        {
1391
 
                                cdrom_read_data(gdromfile, start, ptr, CD_TRACK_MODE1);
1392
 
                                ptr += 2048;
1393
 
                                start++;
1394
 
                                sectors--;
1395
 
                        }
1396
 
                }
1397
 
        }
1398
 
        // get des key
1399
 
        realpic = machine.region("pic")->base();
1400
 
 
1401
 
        if (realpic)
1402
 
        {
1403
 
                int i;
1404
 
                key = 0;
1405
 
                for (i=0;i<7;i++)
1406
 
                {
1407
 
                        key |= (UINT64)realpic[0x780+i*2] << (56 - i*8);
1408
 
                }
1409
 
 
1410
 
                key |= (UINT64)realpic[0x7a0];
1411
 
        }
1412
 
        else
1413
 
        {
1414
 
                key =(((UINT64)v->picdata[0x31] << 56) |
1415
 
                          ((UINT64)v->picdata[0x32] << 48) |
1416
 
                          ((UINT64)v->picdata[0x33] << 40) |
1417
 
                          ((UINT64)v->picdata[0x34] << 32) |
1418
 
                          ((UINT64)v->picdata[0x35] << 24) |
1419
 
                          ((UINT64)v->picdata[0x36] << 16) |
1420
 
                          ((UINT64)v->picdata[0x37] << 8)  |
1421
 
                          ((UINT64)v->picdata[0x29] << 0));
1422
 
        }
1423
 
 
1424
 
        logerror("key is %08x%08x\n", (UINT32)((key & 0xffffffff00000000ULL)>>32), (UINT32)(key & 0x00000000ffffffffULL));
1425
 
 
1426
 
        // decrypt loaded data
1427
 
        naomi_game_decrypt(machine, key, v->memory, size);
1428
 
        cdrom_close(gdromfile);
1429
 
}
1430
 
 
1431
 
/***************************************************************************
1432
 
    DECRYPTION EMULATION
1433
 
 
1434
 
By convention, we label the three known cart protection methods this way (using Deunan Knute's wording):
1435
 
M1: DMA read of protected ROM area
1436
 
M2: special read of ROM area which supplies decryption key first
1437
 
M3: normal read followed by write to cart's decryption buffer (up to 64kB), followed by M2 but from buffer area
1438
 
 
1439
 
Notes below refer to M2 & M3.
1440
 
 
1441
 
The encryption is done by a stream cipher operating in counter mode, which use a 16-bits internal block cipher.
1442
 
 
1443
 
There are 2 "control bits" at the start of the decrypted stream which control the mode of operation: bit #1 set to 1 means
1444
 
that the decrypted stream needs to be decompressed after being decrypted. More on this later.
1445
 
 
1446
 
The next 16-bits are part of the header (they don't belong to the plaintext), but his meaning is unclear. It has been
1447
 
conjectured that it could stablish when to "reset" the process and start processing a new stream (based on some tests
1448
 
on WWFROYAL, in which the decryption's output doesn't seem to be valid for more than some dozens of words), but some
1449
 
more testing would be needed for clarifying that.
1450
 
 
1451
 
After those 18 heading bits, we find the proper plaintext. It must be noted that, due to the initial 2 special bits,
1452
 
the 16-bits words of the plaintext are shifted 2 bits respect to the word-boundaries of the output stream of the
1453
 
internal block-cipher. So, at a given step, the internal block cipher will output 16-bits, 14 of which will go to a
1454
 
given plaintext word, and the remaining 2 to the next plaintext word.
1455
 
 
1456
 
The underlying block cipher consists of two 4-round Feistel Networks (FN): the first one takes the counter (16 bits),
1457
 
the game-key (>=26 bits) and the sequence-key (16 bits) and output a middle result (16 bits) which will act as another key
1458
 
for the second one. The second FN will take the encrypted word (16 bits), the game-key, the sequence-key and the result
1459
 
from the first FN and will output the decrypted word (16 bits).
1460
 
 
1461
 
Each round of the Feistel Networks use four substitution sboxes, each having 6 inputs and 2 outputs. The input can be the
1462
 
XOR of at most two "sources bits", being source bits the bits from the previous round and the bits from the different keys.
1463
 
 
1464
 
The underlying block cipher has the same structure than the one used by the CPS-2 (Capcom Play System 2) and,
1465
 
indeed, some of the used sboxes are exactly the same and appear in the same FN/round in both systems (this is not evident,
1466
 
as you need to apply a bitswapping and some XORs to the input & output of the sboxes to get the same values due). However,
1467
 
the key scheduling used by this implementation is much weaker than the CPS-2's one. Many s-boxes inputs are XORed with any
1468
 
key bit.
1469
 
 
1470
 
Due to the small key-length, no sophisticated attacks are needed to recover the keys; a brute-force attack knowing just
1471
 
some (encrypted word-decrypted word) pairs suffice. However, due to the weak key scheduling, it should be noted that some
1472
 
related keys can produce the same output bytes for some (short) input sequences.
1473
 
 
1474
 
The only difference in the decryption process between M2 and M3 is the initialization of the counter. In M3, the counter is
1475
 
always set to 0 at the beginning of the decryption while, in M2, the bits #1-#16 of the ciphertext's address are used
1476
 
to initialize the counter.
1477
 
 
1478
 
Due to the nature of the cipher, there are some degrees of freedom when choosing the s-boxes and keys values; by example,
1479
 
you could apply a fixed bitswapping and XOR to the keys and the decryption would remain the same as long as you change
1480
 
accordingly the s-boxes' definitions. So the order of the bits in the keys is arbitrary, and the s-boxes values have been
1481
 
chosen so as to make the key for CAPSNK equal to 0.
1482
 
 
1483
 
It can be observed that a couple of sboxes have incomplete tables (a 255 value indicate an unknown value). The recovered keys
1484
 
as of december/2010 show small randomness and big correlations, making possible that some unseen bits could make the
1485
 
decryption need those incomplete parts.
1486
 
 
1487
 
****************************************************************************************/
1488
 
 
1489
 
struct sbox
1490
 
{
1491
 
    UINT8 table[64];
1492
 
    int inputs[6];      // positions of the inputs bits, -1 means no input except from key
1493
 
    int outputs[2];     // positions of the output bits
1494
 
};
1495
 
 
1496
 
 
1497
 
static const struct sbox fn1_sboxes[4][4] =
1498
 
{
1499
 
    {   // 1st round
1500
 
        {
1501
 
            {
1502
 
                0,3,2,2,1,3,1,2,3,2,1,2,1,2,3,1,3,2,2,0,2,1,3,0,0,3,2,3,2,1,2,0,
1503
 
                2,3,1,1,2,2,1,1,1,0,2,3,3,0,2,1,1,1,1,1,3,0,3,2,1,0,1,2,0,3,1,3,
1504
 
            },
1505
 
            {3,4,5,7,-1,-1},
1506
 
            {0,4}
1507
 
        },
1508
 
 
1509
 
        {
1510
 
            {
1511
 
                2,2,2,0,3,3,0,1,2,2,3,2,3,0,2,2,1,1,0,3,3,2,0,2,0,1,0,1,2,3,1,1,
1512
 
                0,1,3,3,1,3,3,1,2,3,2,0,0,0,2,2,0,3,1,3,0,3,2,2,0,3,0,3,1,1,0,2,
1513
 
            },
1514
 
            {0,1,2,5,6,7},
1515
 
            {1,6}
1516
 
        },
1517
 
 
1518
 
        {
1519
 
            {
1520
 
                0,1,3,0,3,1,1,1,1,2,3,1,3,0,2,3,3,2,0,2,1,1,2,1,1,3,1,0,0,2,0,1,
1521
 
                1,3,1,0,0,3,2,3,2,0,3,3,0,0,0,0,1,2,3,3,2,0,3,2,1,0,0,0,2,2,3,3,
1522
 
            },
1523
 
            {0,2,5,6,7,-1},
1524
 
            {2,3}
1525
 
        },
1526
 
 
1527
 
        {
1528
 
            {
1529
 
                3,2,1,2,1,2,3,2,0,3,2,2,3,1,3,3,0,2,3,0,3,3,2,1,1,1,2,0,2,2,0,1,
1530
 
                1,3,3,0,0,3,0,3,0,2,1,3,2,1,0,0,0,1,1,2,0,1,0,0,0,1,3,3,2,0,3,3,
1531
 
            },
1532
 
            {1,2,3,4,6,7},
1533
 
            {5,7}
1534
 
        },
1535
 
    },
1536
 
    {   // 2nd round
1537
 
        {
1538
 
            {
1539
 
                3,3,1,2,0,0,2,2,2,1,2,1,3,1,1,3,3,0,0,3,0,3,3,2,1,1,3,2,3,2,1,3,
1540
 
                2,3,0,1,3,2,0,1,2,1,3,1,2,2,3,3,3,1,2,2,0,3,1,2,2,1,3,0,3,0,1,3,
1541
 
            },
1542
 
            {0,1,3,4,5,7},
1543
 
            {0,4}
1544
 
        },
1545
 
 
1546
 
        {
1547
 
            {
1548
 
                2,0,1,0,0,3,2,0,3,3,1,2,1,3,0,2,0,2,0,0,0,2,3,1,3,1,1,2,3,0,3,0,
1549
 
                3,0,2,0,0,2,2,1,0,2,3,3,1,3,1,0,1,3,3,0,0,1,3,1,0,2,0,3,2,1,0,1,
1550
 
            },
1551
 
            {0,1,3,4,6,-1},
1552
 
            {1,5}
1553
 
        },
1554
 
 
1555
 
        {
1556
 
            {
1557
 
                2,2,2,3,1,1,0,1,0,1,2,2,3,3,0,2,0,3,2,3,3,0,2,1,0,3,1,0,0,2,3,2,
1558
 
                3,2,0,3,2,0,1,0,3,3,1,1,2,2,2,0,2,1,3,1,1,1,1,2,2,2,3,0,1,3,0,0,
1559
 
            },
1560
 
            {1,2,5,6,7,-1},
1561
 
            {2,7}
1562
 
        },
1563
 
 
1564
 
        {
1565
 
            {
1566
 
                0,1,3,3,3,1,3,3,1,0,2,0,2,0,0,3,1,2,1,3,1,2,3,2,2,0,1,3,0,3,3,3,
1567
 
                0,0,0,2,1,1,2,3,2,2,3,1,1,2,0,2,0,2,1,3,1,1,3,3,1,1,3,0,2,3,0,0,
1568
 
            },
1569
 
            {2,3,4,5,6,7},
1570
 
            {3,6}
1571
 
        },
1572
 
    },
1573
 
    {   // 3rd round
1574
 
        {
1575
 
            {
1576
 
                0,0,1,0,1,0,0,3,2,0,0,3,0,1,0,2,0,3,0,0,2,0,3,2,2,1,3,2,2,1,1,2,
1577
 
                0,0,0,3,0,1,1,0,0,2,1,0,3,1,2,2,2,0,3,1,3,0,1,2,2,1,1,1,0,2,3,1,
1578
 
            },
1579
 
            {1,2,3,4,5,7},
1580
 
            {0,5}
1581
 
        },
1582
 
 
1583
 
        {
1584
 
            {
1585
 
                1,2,1,0,3,1,1,2,0,0,2,3,2,3,1,3,2,0,3,2,2,3,1,1,1,1,0,3,2,0,0,1,
1586
 
                1,0,0,1,3,1,2,3,0,0,2,3,3,0,1,0,0,2,3,0,1,2,0,1,3,3,3,1,2,0,2,1,
1587
 
            },
1588
 
            {0,2,4,5,6,7},
1589
 
            {1,6}
1590
 
        },
1591
 
 
1592
 
        {
1593
 
            {
1594
 
                0,3,0,2,1,2,0,0,1,1,0,0,3,1,1,0,0,3,0,0,2,3,3,2,3,1,2,0,0,2,3,0,
1595
 
                // unused?
1596
 
                255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1597
 
            },
1598
 
            {0,2,4,6,7,-1},
1599
 
            {2,3}
1600
 
        },
1601
 
 
1602
 
        {
1603
 
            {
1604
 
                0,0,1,0,0,1,0,2,3,3,0,3,3,2,3,0,2,2,2,0,3,2,0,3,1,0,0,3,3,0,0,0,
1605
 
                2,2,1,0,2,0,3,2,0,0,3,1,3,3,0,0,2,1,1,2,1,0,1,1,0,3,1,2,0,2,0,3,
1606
 
            },
1607
 
            {0,1,2,3,6,-1},
1608
 
            {4,7}
1609
 
        },
1610
 
    },
1611
 
    {   // 4th round
1612
 
        {
1613
 
            {
1614
 
                0,3,3,3,3,3,2,0,0,1,2,0,2,2,2,2,1,1,0,2,2,1,3,2,3,2,0,1,2,3,2,1,
1615
 
                3,2,2,3,1,0,1,0,0,2,0,1,2,1,2,3,1,2,1,1,2,2,1,0,1,3,2,3,2,0,3,1,
1616
 
            },
1617
 
            {0,1,3,4,5,6},
1618
 
            {0,5}
1619
 
        },
1620
 
 
1621
 
        {
1622
 
            {
1623
 
                0,3,0,0,2,0,3,1,1,1,2,2,2,1,3,1,2,2,1,3,2,2,3,3,0,3,1,0,3,2,0,1,
1624
 
                3,0,2,0,1,0,2,1,3,3,1,2,2,0,2,3,3,2,3,0,1,1,3,3,0,2,1,3,0,2,2,3,
1625
 
            },
1626
 
            {0,1,2,3,5,7},
1627
 
            {1,7}
1628
 
        },
1629
 
 
1630
 
        {
1631
 
            {
1632
 
                0,1,2,3,3,3,3,1,2,0,2,3,2,1,0,1,2,2,1,2,0,3,2,0,1,1,0,1,3,1,3,1,
1633
 
                3,1,0,0,1,0,0,0,0,1,2,2,1,1,3,3,1,2,3,3,3,2,3,0,2,2,1,3,3,0,2,0,
1634
 
            },
1635
 
            {2,3,4,5,6,7},
1636
 
            {2,3}
1637
 
        },
1638
 
 
1639
 
        {
1640
 
            {
1641
 
                0,2,1,1,3,2,0,3,1,0,1,0,3,2,1,1,2,2,0,3,1,0,1,2,2,2,3,3,0,0,0,0,
1642
 
                1,2,1,0,2,1,2,2,2,3,2,3,0,1,3,0,0,1,3,0,0,1,1,0,1,0,0,0,0,2,0,1,
1643
 
            },
1644
 
            {0,1,2,4,6,7},
1645
 
            {4,6}
1646
 
        },
1647
 
    },
1648
 
};
1649
 
 
1650
 
 
1651
 
static const struct sbox fn2_sboxes[4][4] =
1652
 
{
1653
 
    {   // 1st round
1654
 
        {
1655
 
            {
1656
 
                3,3,0,1,0,1,0,0,0,3,0,0,1,3,1,2,0,3,3,3,2,1,0,1,1,1,2,2,2,3,2,2,
1657
 
                2,1,3,3,1,3,1,1,0,0,1,2,0,2,2,1,1,2,3,1,2,1,3,1,2,2,0,1,3,0,2,2,
1658
 
            },
1659
 
            {1,3,4,5,6,7},
1660
 
            {0,7}
1661
 
        },
1662
 
 
1663
 
        {
1664
 
            {
1665
 
                0,2,3,2,1,1,0,0,2,1,0,3,3,0,0,0,3,2,0,2,1,1,2,1,0,0,3,1,2,2,3,1,
1666
 
                3,1,3,0,0,0,1,3,1,0,0,3,2,2,3,1,1,3,0,0,2,1,3,3,1,3,1,2,3,1,2,1,
1667
 
            },
1668
 
            {0,3,5,6,-1,-1},
1669
 
            {1,2}
1670
 
        },
1671
 
 
1672
 
        {
1673
 
            {
1674
 
                0,2,2,1,0,1,2,1,2,0,1,2,3,3,0,1,3,1,1,2,1,2,1,3,3,2,3,3,2,1,0,1,
1675
 
                0,1,0,2,0,1,1,3,2,0,3,2,1,1,1,3,2,3,0,2,3,0,2,2,1,3,0,1,1,2,2,2,
1676
 
            },
1677
 
            {0,2,3,4,7,-1},
1678
 
            {3,4}
1679
 
        },
1680
 
 
1681
 
        {
1682
 
            {
1683
 
                2,3,1,3,2,0,1,2,0,0,3,3,3,3,3,1,2,0,2,1,2,3,0,2,0,1,0,3,0,2,1,0,
1684
 
                2,3,0,1,3,0,3,2,3,1,2,0,3,1,1,2,0,3,0,0,2,0,2,1,2,2,3,2,1,2,3,1,
1685
 
            },
1686
 
            {1,2,5,6,-1,-1},
1687
 
            {5,6}
1688
 
        },
1689
 
    },
1690
 
    {   // 2nd round
1691
 
        {
1692
 
            {
1693
 
                2,3,1,3,1,0,3,3,3,2,3,3,2,0,0,3,2,3,0,3,1,1,2,3,1,1,2,2,0,1,0,0,
1694
 
                2,1,0,1,2,0,1,2,0,3,1,1,2,3,1,2,0,2,0,1,3,0,1,0,2,2,3,0,3,2,3,0,
1695
 
            },
1696
 
            {0,1,4,5,6,7},
1697
 
            {0,7}
1698
 
        },
1699
 
 
1700
 
        {
1701
 
            {
1702
 
                0,2,2,0,2,2,0,3,2,3,2,1,3,2,3,3,1,1,0,0,3,0,2,1,1,3,3,2,3,2,0,1,
1703
 
                1,2,3,0,1,0,3,0,3,1,0,2,1,2,0,3,2,3,1,2,2,0,3,2,3,0,0,1,2,3,3,3,
1704
 
            },
1705
 
            {0,2,3,6,7,-1},
1706
 
            {1,5}
1707
 
        },
1708
 
 
1709
 
        {
1710
 
            {
1711
 
                1,2,3,2,0,3,2,3,0,1,1,0,0,2,2,3,2,0,0,3,0,2,3,3,2,2,1,0,2,1,0,3,
1712
 
                1,0,2,0,1,1,0,1,0,0,1,0,3,0,3,3,2,2,0,2,1,1,1,0,3,0,1,3,2,3,2,1,
1713
 
            },
1714
 
            {2,3,4,6,7,-1},
1715
 
            {2,3}
1716
 
        },
1717
 
 
1718
 
        {
1719
 
            {
1720
 
                2,3,1,3,1,1,2,3,3,1,1,0,1,0,2,3,2,1,0,0,2,2,0,1,0,2,2,2,0,2,1,0,
1721
 
                3,1,2,3,1,3,0,2,1,0,1,0,0,1,2,2,3,2,3,1,3,2,1,1,2,0,2,1,3,3,1,0,
1722
 
            },
1723
 
            {1,2,3,4,5,6},
1724
 
            {4,6}
1725
 
        },
1726
 
    },
1727
 
    {   // 3rd round
1728
 
        {
1729
 
            {
1730
 
                0,3,0,1,0,2,3,3,1,0,1,3,2,2,1,1,3,3,3,0,2,0,2,0,0,0,2,3,1,1,0,0,
1731
 
                3,3,0,3,3,0,0,2,1,1,1,0,2,2,2,0,3,0,3,1,2,2,0,3,0,0,3,2,0,3,2,1,
1732
 
            },
1733
 
            {1,4,5,6,7,-1},
1734
 
            {0,5}
1735
 
        },
1736
 
 
1737
 
        {
1738
 
            {
1739
 
                0,3,0,1,3,0,3,1,3,2,2,2,3,0,3,2,2,1,2,2,0,3,2,2,0,0,2,1,1,3,2,3,
1740
 
                2,3,3,1,2,0,1,2,2,1,0,0,0,0,2,3,1,2,0,3,1,3,1,2,3,2,1,0,3,0,0,2,
1741
 
            },
1742
 
            {0,2,3,4,6,7},
1743
 
            {1,7}
1744
 
        },
1745
 
 
1746
 
        {
1747
 
            {
1748
 
                2,2,3,2,0,3,2,3,1,1,2,0,2,3,1,3,0,0,0,3,2,0,1,0,1,3,2,3,3,3,1,0,
1749
 
                // unused?
1750
 
                255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1751
 
            },
1752
 
            {1,2,4,7,-1,-1},
1753
 
            {2,4}
1754
 
        },
1755
 
 
1756
 
        {
1757
 
            {
1758
 
                0,2,3,1,3,1,1,0,0,1,3,0,2,1,3,3,2,0,2,1,1,2,3,3,0,0,0,2,0,2,3,0,
1759
 
                3,3,3,3,2,3,3,2,3,0,1,0,2,3,3,2,0,1,3,1,0,1,2,3,3,0,2,0,3,0,3,3,
1760
 
            },
1761
 
            {0,1,2,3,5,7},
1762
 
            {3,6}
1763
 
        },
1764
 
    },
1765
 
    {   // 4th round
1766
 
        {
1767
 
            {
1768
 
                0,1,1,0,0,1,0,2,3,3,0,1,2,3,0,2,1,0,3,3,2,0,3,0,0,2,1,0,1,0,1,3,
1769
 
                0,3,3,1,2,0,3,0,1,3,2,0,3,3,1,3,0,2,3,3,2,1,1,2,2,1,2,1,2,0,1,1,
1770
 
            },
1771
 
            {0,1,2,4,7,-1},
1772
 
            {0,5}
1773
 
        },
1774
 
 
1775
 
        {
1776
 
            {
1777
 
                2,0,0,2,3,0,2,3,3,1,1,1,2,1,1,0,0,2,1,0,0,3,1,0,0,3,3,0,1,0,1,2,
1778
 
                0,2,0,2,0,1,2,3,2,1,1,0,3,3,3,3,3,3,1,0,3,0,0,2,0,3,2,0,2,2,0,1,
1779
 
            },
1780
 
            {0,1,3,5,6,-1},
1781
 
            {1,3}
1782
 
        },
1783
 
 
1784
 
        {
1785
 
            {
1786
 
                0,1,1,2,1,3,1,1,0,0,3,1,1,1,2,0,3,2,0,1,1,2,3,3,3,0,3,0,0,2,0,3,
1787
 
                3,2,0,0,3,2,3,1,2,3,0,3,2,0,1,2,2,2,0,2,0,1,2,2,3,1,2,2,1,1,1,1,
1788
 
            },
1789
 
            {0,2,3,4,5,7},
1790
 
            {2,7}
1791
 
        },
1792
 
 
1793
 
        {
1794
 
            {
1795
 
                0,1,2,0,3,3,0,3,2,1,3,3,0,3,1,1,3,2,3,2,3,0,0,0,3,0,2,2,3,2,2,3,
1796
 
                2,2,3,1,2,3,1,2,0,3,0,2,3,1,0,0,3,2,1,2,1,2,1,3,1,0,2,3,3,1,3,2,
1797
 
            },
1798
 
            {2,3,4,5,6,7},
1799
 
            {4,6}
1800
 
        },
1801
 
    },
1802
 
};
1803
 
 
1804
 
static const int fn1_game_key_scheduling[38][2] =
1805
 
{
1806
 
    {1,29},  {1,71},  {2,4},   {2,54},  {3,8},   {4,56},  {4,73},  {5,11},
1807
 
    {6,51},  {7,92},  {8,89},  {9,9},   {9,10},  {9,39},  {9,41},  {9,58},
1808
 
    {9,59},  {9,86},  {10,90}, {11,6},  {12,64}, {13,49}, {14,44}, {15,40},
1809
 
    {16,69}, {17,15}, {18,23}, {18,43}, {19,82}, {20,81}, {21,32}, {21,61},
1810
 
    {22,5},  {23,66}, {24,13}, {24,45}, {25,12}, {25,35}
1811
 
};
1812
 
 
1813
 
static const int fn2_game_key_scheduling[34][2] =
1814
 
{
1815
 
    {0,0},   {1,3},   {2,11},  {3,20},  {4,22},  {5,23},  {6,29},  {7,38},
1816
 
    {8,39},  {9,47},  {9,55},  {9,86},  {9,87},  {9,90},  {10,50}, {10,53},
1817
 
    {11,57}, {12,59}, {13,61}, {13,64}, {14,63}, {15,67}, {16,72}, {17,83},
1818
 
    {18,88}, {19,94}, {20,35}, {21,17}, {21,92}, {22,6},  {22,11}, {23,85},
1819
 
    {24,16}, {25,25}
1820
 
};
1821
 
 
1822
 
static const int fn1_sequence_key_scheduling[20][2] =
1823
 
{
1824
 
    {0,52},  {1,34},  {2,17},  {3,36}, {4,84},  {4,88},  {5,57},  {6,48},
1825
 
    {6,68},  {7,76},  {8,83},  {9,30}, {10,22}, {10,41}, {11,38}, {12,55},
1826
 
    {13,74}, {14,19}, {14,80}, {15,26}
1827
 
};
1828
 
 
1829
 
static const int fn2_sequence_key_scheduling[16] = {77,34,8,42,36,27,69,66,13,9,79,31,49,7,24,64};
1830
 
 
1831
 
static const int fn2_middle_result_scheduling[16] = {1,10,44,68,74,78,81,95,2,4,30,40,41,51,53,58};
1832
 
 
1833
 
static int feistel_function(int input, const struct sbox* sboxes, UINT32 subkeys)
1834
 
{
1835
 
    int k,m;
1836
 
    int aux;
1837
 
    int result=0;
1838
 
 
1839
 
    for (m=0; m<4; ++m)  // 4 sboxes
1840
 
    {
1841
 
        for (k=0, aux=0; k<6; ++k)
1842
 
        {
1843
 
            if (sboxes[m].inputs[k]!=-1)
1844
 
            {
1845
 
                aux |= (BIT(input, sboxes[m].inputs[k])<<k);
1846
 
            }
1847
 
        }
1848
 
 
1849
 
        aux = sboxes[m].table[(aux^subkeys)&0x3f];
1850
 
 
1851
 
        for (k=0; k<2; ++k)
1852
 
        {
1853
 
            result |= (BIT(aux,k)<<sboxes[m].outputs[k]);
1854
 
        }
1855
 
 
1856
 
        subkeys >>=6;
1857
 
    }
1858
 
 
1859
 
    return result;
1860
 
}
1861
 
 
1862
 
/**************************
1863
 
This implementation is an "educational" version. It must be noted that it can be speed-optimized in a number of ways.
1864
 
The most evident one is to factor out the parts of the key-scheduling that must only be done once (like the game-key &
1865
 
sequence-key parts) as noted in the comments inlined in the function. More sophisticated speed-ups can be gained by
1866
 
noticing that the weak key-scheduling would allow to create some pregenerated look-up tables for doing most of the work
1867
 
of the function. Even so, it would still be pretty slow, so caching techniques could be a wiser option here.
1868
 
**************************/
1869
 
 
1870
 
static UINT16 block_decrypt(UINT32 game_key, UINT16 sequence_key, UINT16 counter, UINT16 data)
1871
 
{
1872
 
    int j;
1873
 
    int aux,aux2;
1874
 
    int A,B;
1875
 
    int middle_result;
1876
 
    UINT32 fn1_subkeys[4];
1877
 
    UINT32 fn2_subkeys[4];
1878
 
 
1879
 
    /* Game-key scheduling; this could be done just once per game at initialization time */
1880
 
    memset(fn1_subkeys,0,sizeof(UINT32)*4);
1881
 
    memset(fn2_subkeys,0,sizeof(UINT32)*4);
1882
 
 
1883
 
    for (j=0; j<38; ++j)
1884
 
    {
1885
 
        if (BIT(game_key, fn1_game_key_scheduling[j][0])!=0)
1886
 
        {
1887
 
            aux = fn1_game_key_scheduling[j][1]%24;
1888
 
            aux2 = fn1_game_key_scheduling[j][1]/24;
1889
 
            fn1_subkeys[aux2] ^= (1<<aux);
1890
 
        }
1891
 
    }
1892
 
 
1893
 
    for (j=0; j<34; ++j)
1894
 
    {
1895
 
        if (BIT(game_key, fn2_game_key_scheduling[j][0])!=0)
1896
 
        {
1897
 
            aux = fn2_game_key_scheduling[j][1]%24;
1898
 
            aux2 = fn2_game_key_scheduling[j][1]/24;
1899
 
            fn2_subkeys[aux2] ^= (1<<aux);
1900
 
        }
1901
 
    }
1902
 
    /********************************************************/
1903
 
 
1904
 
    /* Sequence-key scheduling; this could be done just once per decryption run */
1905
 
    for (j=0; j<20; ++j)
1906
 
    {
1907
 
        if (BIT(sequence_key,fn1_sequence_key_scheduling[j][0])!=0)
1908
 
        {
1909
 
            aux = fn1_sequence_key_scheduling[j][1]%24;
1910
 
            aux2 = fn1_sequence_key_scheduling[j][1]/24;
1911
 
            fn1_subkeys[aux2] ^= (1<<aux);
1912
 
        }
1913
 
    }
1914
 
 
1915
 
    for (j=0; j<16; ++j)
1916
 
    {
1917
 
        if (BIT(sequence_key,j)!=0)
1918
 
        {
1919
 
            aux = fn2_sequence_key_scheduling[j]%24;
1920
 
            aux2 = fn2_sequence_key_scheduling[j]/24;
1921
 
            fn2_subkeys[aux2] ^= (1<<aux);
1922
 
        }
1923
 
    }
1924
 
 
1925
 
    // subkeys bits 10 & 41
1926
 
    fn2_subkeys[0] ^= (BIT(sequence_key,2)<<10);
1927
 
    fn2_subkeys[1] ^= (BIT(sequence_key,4)<<17);
1928
 
    /**************************************************************/
1929
 
 
1930
 
    // First Feistel Network
1931
 
 
1932
 
    aux = BITSWAP16(counter,5,12,14,13,9,3,6,4,    8,1,15,11,0,7,10,2);
1933
 
 
1934
 
    // 1st round
1935
 
    B = aux >> 8;
1936
 
    A = (aux & 0xff) ^ feistel_function(B,fn1_sboxes[0],fn1_subkeys[0]);
1937
 
 
1938
 
    // 2nd round
1939
 
    B = B ^ feistel_function(A,fn1_sboxes[1],fn1_subkeys[1]);
1940
 
 
1941
 
    // 3rd round
1942
 
    A = A ^ feistel_function(B,fn1_sboxes[2],fn1_subkeys[2]);
1943
 
 
1944
 
    // 4th round
1945
 
    B = B ^ feistel_function(A,fn1_sboxes[3],fn1_subkeys[3]);
1946
 
 
1947
 
    middle_result = (B<<8)|A;
1948
 
 
1949
 
 
1950
 
    /* Middle-result-key sheduling */
1951
 
    for (j=0; j<16; ++j)
1952
 
    {
1953
 
        if (BIT(middle_result,j)!=0)
1954
 
        {
1955
 
            aux = fn2_middle_result_scheduling[j]%24;
1956
 
            aux2 = fn2_middle_result_scheduling[j]/24;
1957
 
            fn2_subkeys[aux2] ^= (1<<aux);
1958
 
        }
1959
 
    }
1960
 
    /*********************/
1961
 
 
1962
 
    // Second Feistel Network
1963
 
 
1964
 
    aux = BITSWAP16(data,14,3,8,12,13,7,15,4,    6,2,9,5,11,0,1,10);
1965
 
 
1966
 
    // 1st round
1967
 
    B = aux >> 8;
1968
 
    A = (aux & 0xff) ^ feistel_function(B,fn2_sboxes[0],fn2_subkeys[0]);
1969
 
 
1970
 
    // 2nd round
1971
 
    B = B ^ feistel_function(A,fn2_sboxes[1],fn2_subkeys[1]);
1972
 
 
1973
 
    // 3rd round
1974
 
    A = A ^ feistel_function(B,fn2_sboxes[2],fn2_subkeys[2]);
1975
 
 
1976
 
    // 4th round
1977
 
    B = B ^ feistel_function(A,fn2_sboxes[3],fn2_subkeys[3]);
1978
 
 
1979
 
    aux = (B<<8)|A;
1980
 
 
1981
 
    aux = BITSWAP16(aux,15,7,6,14,13,12,5,4,    3,2,11,10,9,1,0,8);
1982
 
 
1983
 
    return aux;
1984
 
}
1985
 
 
1986
 
/***************************************************************************
1987
 
    DEVICE INTERFACE
1988
 
***************************************************************************/
1989
 
 
1990
 
/*-------------------------------------------------
1991
 
    device start callback
1992
 
-------------------------------------------------*/
1993
 
 
1994
 
static DEVICE_START( naomibd )
1995
 
{
1996
 
        const naomibd_config *config = (const naomibd_config *)downcast<const legacy_device_base *>(device)->inline_config();
1997
 
        naomibd_state *v = get_safe_token(device);
1998
 
        int i;
1999
 
 
2000
 
        /* validate some basic stuff */
2001
 
        assert(device->static_config() == NULL);
2002
 
        assert(downcast<const legacy_device_base *>(device)->inline_config() != NULL);
2003
 
 
2004
 
        /* validate configuration */
2005
 
        assert(config->type >= ROM_BOARD && config->type < MAX_NAOMIBD_TYPES);
2006
 
 
2007
 
        /* store a pointer back to the device */
2008
 
        v->device = device;
2009
 
 
2010
 
    v->dc_dmakey = 0;
2011
 
 
2012
 
        for (i=0; i<ARRAY_LENGTH(naomibd_translate_tbl); i++)
2013
 
        {
2014
 
                if (!strcmp(device->machine().system().name, naomibd_translate_tbl[i].name))
2015
 
                {
2016
 
            v->dc_gamekey = naomibd_translate_tbl[i].m2m3_key;
2017
 
            v->dc_dmakey = naomibd_translate_tbl[i].m1_key;
2018
 
                        break;
2019
 
                }
2020
 
        }
2021
 
 
2022
 
        /* configure type-specific values */
2023
 
        switch (config->type)
2024
 
        {
2025
 
                case ROM_BOARD:
2026
 
                        v->memory = (UINT8 *)device->machine().region(config->regiontag)->base();
2027
 
                        break;
2028
 
 
2029
 
                case AW_ROM_BOARD:
2030
 
                        v->memory = (UINT8 *)device->machine().region(config->regiontag)->base();
2031
 
                        break;
2032
 
 
2033
 
                case DIMM_BOARD:
2034
 
                        v->memory = (UINT8 *)auto_alloc_array_clear(device->machine(), UINT8, 0x40000000); // 0x40000000 is needed for some Chihiro sets, Naomi should be less, we should pass as device param
2035
 
                        v->gdromchd = get_disk_handle(device->machine(), config->gdromregiontag);
2036
 
                        v->picdata = (UINT8 *)device->machine().region(config->picregiontag)->base();
2037
 
                        if (v->memory != NULL && v->gdromchd != NULL && v->picdata != NULL)
2038
 
                                load_rom_gdrom(device->machine(), v);
2039
 
                        break;
2040
 
 
2041
 
                default:
2042
 
                        fatalerror("Unsupported plug-in board in naomibd_start!");
2043
 
                        break;
2044
 
        }
2045
 
 
2046
 
        /* set the type */
2047
 
        v->index = device->machine().devicelist().indexof(device->type(), device->tag());
2048
 
        v->type = config->type;
2049
 
 
2050
 
        /* initialize some registers */
2051
 
        v->rom_offset = 0;
2052
 
        v->rom_offset_flags = 0;
2053
 
        v->dma_count = 0;
2054
 
        v->dma_offset = 0;
2055
 
        v->dma_offset_flags = 0;
2056
 
        v->prot_offset = 0;
2057
 
 
2058
 
        /* do a soft reset to reset everything else */
2059
 
        soft_reset(v);
2060
 
 
2061
 
        /* register for save states */
2062
 
        init_save_state(device);
2063
 
}
2064
 
 
2065
 
 
2066
 
/*-------------------------------------------------
2067
 
    device exit callback
2068
 
-------------------------------------------------*/
2069
 
 
2070
 
static DEVICE_STOP( naomibd )
2071
 
{
2072
 
        //naomibd_state *v = get_safe_token(device);
2073
 
}
2074
 
 
2075
 
 
2076
 
/*-------------------------------------------------
2077
 
    device reset callback
2078
 
-------------------------------------------------*/
2079
 
 
2080
 
static DEVICE_RESET( naomibd )
2081
 
{
2082
 
        naomibd_state *v = get_safe_token(device);
2083
 
        soft_reset(v);
2084
 
}
2085
 
 
2086
 
 
2087
 
/*-------------------------------------------------
2088
 
    device get info callback
2089
 
-------------------------------------------------*/
2090
 
 
2091
 
DEVICE_GET_INFO( naomibd )
2092
 
{
2093
 
        const naomibd_config *config = (device != NULL) ? (const naomibd_config *)downcast<const legacy_device_base *>(device)->inline_config() : NULL;
2094
 
        switch (state)
2095
 
        {
2096
 
                /* --- the following bits of info are returned as 64-bit signed integers --- */
2097
 
                case DEVINFO_INT_TOKEN_BYTES:                   info->i = sizeof(naomibd_state);                                break;
2098
 
                case DEVINFO_INT_INLINE_CONFIG_BYTES:   info->i = sizeof(naomibd_config);                               break;
2099
 
 
2100
 
                /* --- the following bits of info are returned as pointers --- */
2101
 
                case DEVINFO_PTR_ROM_REGION:                    info->romregion = NULL;                                                 break;
2102
 
                case DEVINFO_PTR_MACHINE_CONFIG:                info->machine_config = NULL;                                    break;
2103
 
 
2104
 
                /* --- the following bits of info are returned as pointers to data or functions --- */
2105
 
                case DEVINFO_FCT_START:                                 info->start = DEVICE_START_NAME(naomibd);               break;
2106
 
                case DEVINFO_FCT_STOP:                                  info->stop = DEVICE_STOP_NAME(naomibd);                 break;
2107
 
                case DEVINFO_FCT_RESET:                                 info->reset = DEVICE_RESET_NAME(naomibd);               break;
2108
 
 
2109
 
                /* --- the following bits of info are returned as NULL-terminated strings --- */
2110
 
                case DEVINFO_STR_NAME:
2111
 
                        switch (config->type)
2112
 
                        {
2113
 
                                default:
2114
 
                                case ROM_BOARD:                                 strcpy(info->s, "Naomi Rom Board");                             break;
2115
 
                                case AW_ROM_BOARD:                              strcpy(info->s, "Atomiswave Rom Board");                                break;
2116
 
                                case DIMM_BOARD:                                strcpy(info->s, "Naomi Dimm Board");                    break;
2117
 
                        }
2118
 
                        break;
2119
 
                case DEVINFO_STR_FAMILY:                                strcpy(info->s, "Naomi/Atomiswave plug-in board");                      break;
2120
 
                case DEVINFO_STR_VERSION:                               strcpy(info->s, "1.1");                                                 break;
2121
 
                case DEVINFO_STR_SOURCE_FILE:                   strcpy(info->s, __FILE__);                                              break;
2122
 
                case DEVINFO_STR_CREDITS:                               strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
2123
 
        }
2124
 
}
2125
 
 
2126
 
 
2127
 
DEFINE_LEGACY_DEVICE(NAOMI_BOARD, naomibd);
 
115
        if(!dma_ready) {
 
116
                if(!(dma_offset & 0x80000000))
 
117
                        throw emu_fatalerror("NAOMI BOARD: Unsupported, non-incrementing DMA.\n");
 
118
                board_setup_address(dma_offset, true);
 
119
                dma_cur_offset = 0;
 
120
                dma_ready = true;
 
121
        }
 
122
 
 
123
        board_get_buffer(base, limit);
 
124
        UINT32 blimit = 0x20*dma_count - dma_cur_offset;
 
125
        if(0 && limit > blimit)
 
126
                limit = blimit;
 
127
}
 
128
 
 
129
void naomi_board::dma_advance(UINT32 size)
 
130
{
 
131
        dma_cur_offset += size;
 
132
        board_advance(size);
 
133
}
 
134
 
 
135
WRITE16_MEMBER(naomi_board::rom_offseth_w)
 
136
{
 
137
        rom_offset = (rom_offset & 0x0000ffff) | (data << 16);
 
138
        pio_ready = false;
 
139
}
 
140
 
 
141
WRITE16_MEMBER(naomi_board::rom_offsetl_w)
 
142
{
 
143
        rom_offset = (rom_offset & 0xffff0000) | data;
 
144
        pio_ready = false;
 
145
}
 
146
 
 
147
READ16_MEMBER(naomi_board::rom_data_r)
 
148
{
 
149
        if(!pio_ready) {
 
150
                board_setup_address(rom_offset, false);
 
151
                pio_ready = true;
 
152
        }
 
153
 
 
154
        UINT8 *buffer;
 
155
        UINT32 size;
 
156
        UINT16 res;
 
157
        board_get_buffer(buffer, size);
 
158
        assert(size > 1);
 
159
        res = buffer[0] | (buffer[1] << 8);
 
160
        if(rom_offset & 0x80000000)
 
161
                board_advance(2);
 
162
        return res;
 
163
}
 
164
 
 
165
WRITE16_MEMBER(naomi_board::rom_data_w)
 
166
{
 
167
        board_write(rom_offset, data);
 
168
 
 
169
        if(rom_offset & 0x80000000)
 
170
                rom_offset += 2;
 
171
}
 
172
 
 
173
WRITE16_MEMBER(naomi_board::dma_offseth_w)
 
174
{
 
175
        dma_offset = (dma_offset & 0x0000ffff) | (data << 16);
 
176
        dma_ready = false;
 
177
}
 
178
 
 
179
WRITE16_MEMBER(naomi_board::dma_offsetl_w)
 
180
{
 
181
        dma_offset = (dma_offset & 0xffff0000) | data;
 
182
        dma_ready = false;
 
183
}
 
184
 
 
185
WRITE16_MEMBER(naomi_board::dma_count_w)
 
186
{
 
187
        dma_count = data;
 
188
}
 
189
 
 
190
WRITE16_MEMBER(naomi_board::boardid_w)
 
191
{
 
192
        eeprom->cs_w((data >> 2) & 1);
 
193
        eeprom->rst_w((data >> 3) & 1);
 
194
        eeprom->scl_w((data >> 1) & 1);
 
195
        eeprom->sda_w((data >> 0) & 1);
 
196
}
 
197
 
 
198
READ16_MEMBER(naomi_board::boardid_r)
 
199
{
 
200
        return eeprom->sda_r() << 15;
 
201
}
 
202
 
 
203
READ16_MEMBER(naomi_board::default_r)
 
204
{
 
205
        logerror("NAOMIBD: unmapped read at %02x\n", offset);
 
206
        return 0xffff;
 
207
}
 
208
 
 
209
void naomi_board::board_write(offs_t offset, UINT16 data)
 
210
{
 
211
        logerror("NAOMIBD: unhandled board write %08x, %04x\n", offset, data);
 
212
}
 
213