~ubuntu-branches/ubuntu/lucid/sdlmame/lucid

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Cesare Falco
  • Date: 2009-11-03 17:10:15 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20091103171015-6hop4ory5lxnumpn
Tags: 0.135-0ubuntu1
* New upstream release - Closes (LP: #403212)
* debian/watch: unstable releases are no longer detected
* mame.ini: added the cheat subdirectories to cheatpath so zipped
  cheatfiles will be searched too
* renamed crsshair subdirectory to crosshair to reflect upstream change
* mame.ini: renamed references to crosshair subdirectory (see above)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 
 
3
  snessdd1.c
 
4
 
 
5
  File to handle emulation of the SNES "S-DD1" add-on chip.
 
6
 
 
7
  Based on Andreas Naive Public Domain code.
 
8
 
 
9
***************************************************************************/
 
10
 
 
11
static UINT8 sdd1_read(running_machine* machine, UINT32 addr);
 
12
 
 
13
typedef struct //Input Manager
 
14
{
 
15
        running_machine* machine;
 
16
        UINT32 byte_ptr;
 
17
        UINT8 bit_count;
 
18
} SDD1_IM;
 
19
 
 
20
static SDD1_IM* SDD1_IM_ctor(running_machine* machine)
 
21
{
 
22
        SDD1_IM* newclass = (SDD1_IM*)auto_alloc_array(machine, UINT8, sizeof(SDD1_IM));
 
23
        newclass->machine = machine;
 
24
        return newclass;
 
25
}
 
26
 
 
27
static void SDD1_IM_prepareDecomp(SDD1_IM* thisptr, UINT32 in_buf)
 
28
{
 
29
        thisptr->byte_ptr = in_buf;
 
30
        thisptr->bit_count = 4;
 
31
}
 
32
 
 
33
static UINT8 SDD1_IM_getCodeword(SDD1_IM* thisptr, const UINT8 code_len)
 
34
{
 
35
        UINT8 codeword;
 
36
 
 
37
        codeword = sdd1_read(thisptr->machine, thisptr->byte_ptr) << thisptr->bit_count;
 
38
 
 
39
        ++thisptr->bit_count;
 
40
 
 
41
        if (codeword & 0x80)
 
42
        {
 
43
                codeword |= sdd1_read(thisptr->machine, thisptr->byte_ptr + 1) >> (9 - thisptr->bit_count);
 
44
                thisptr->bit_count += code_len;
 
45
        }
 
46
 
 
47
        if (thisptr->bit_count & 0x08)
 
48
        {
 
49
                thisptr->byte_ptr++;
 
50
                thisptr->bit_count &= 0x07;
 
51
        }
 
52
 
 
53
        return codeword;
 
54
}
 
55
 
 
56
typedef struct //Golomb-Code Decoder
 
57
{
 
58
        running_machine* machine;
 
59
        SDD1_IM* IM;
 
60
} SDD1_GCD;
 
61
 
 
62
static SDD1_GCD* SDD1_GCD_ctor(running_machine* machine, SDD1_IM* associatedIM)
 
63
{
 
64
        SDD1_GCD* newclass = (SDD1_GCD*)auto_alloc_array(machine, UINT8, sizeof(SDD1_GCD));
 
65
        newclass->machine = machine;
 
66
        newclass->IM = associatedIM;
 
67
        return newclass;
 
68
}
 
69
 
 
70
static void SDD1_GCD_getRunCount(SDD1_GCD* thisptr, UINT8 code_num, UINT8* MPScount, UINT8* LPSind)
 
71
{
 
72
        const UINT8 run_count[] =
 
73
        {
 
74
                0x00, 0x00, 0x01, 0x00, 0x03, 0x01, 0x02, 0x00,
 
75
                0x07, 0x03, 0x05, 0x01, 0x06, 0x02, 0x04, 0x00,
 
76
                0x0f, 0x07, 0x0b, 0x03, 0x0d, 0x05, 0x09, 0x01,
 
77
                0x0e, 0x06, 0x0a, 0x02, 0x0c, 0x04, 0x08, 0x00,
 
78
                0x1f, 0x0f, 0x17, 0x07, 0x1b, 0x0b, 0x13, 0x03,
 
79
                0x1d, 0x0d, 0x15, 0x05, 0x19, 0x09, 0x11, 0x01,
 
80
                0x1e, 0x0e, 0x16, 0x06, 0x1a, 0x0a, 0x12, 0x02,
 
81
                0x1c, 0x0c, 0x14, 0x04, 0x18, 0x08, 0x10, 0x00,
 
82
                0x3f, 0x1f, 0x2f, 0x0f, 0x37, 0x17, 0x27, 0x07,
 
83
                0x3b, 0x1b, 0x2b, 0x0b, 0x33, 0x13, 0x23, 0x03,
 
84
                0x3d, 0x1d, 0x2d, 0x0d, 0x35, 0x15, 0x25, 0x05,
 
85
                0x39, 0x19, 0x29, 0x09, 0x31, 0x11, 0x21, 0x01,
 
86
                0x3e, 0x1e, 0x2e, 0x0e, 0x36, 0x16, 0x26, 0x06,
 
87
                0x3a, 0x1a, 0x2a, 0x0a, 0x32, 0x12, 0x22, 0x02,
 
88
                0x3c, 0x1c, 0x2c, 0x0c, 0x34, 0x14, 0x24, 0x04,
 
89
                0x38, 0x18, 0x28, 0x08, 0x30, 0x10, 0x20, 0x00,
 
90
                0x7f, 0x3f, 0x5f, 0x1f, 0x6f, 0x2f, 0x4f, 0x0f,
 
91
                0x77, 0x37, 0x57, 0x17, 0x67, 0x27, 0x47, 0x07,
 
92
                0x7b, 0x3b, 0x5b, 0x1b, 0x6b, 0x2b, 0x4b, 0x0b,
 
93
                0x73, 0x33, 0x53, 0x13, 0x63, 0x23, 0x43, 0x03,
 
94
                0x7d, 0x3d, 0x5d, 0x1d, 0x6d, 0x2d, 0x4d, 0x0d,
 
95
                0x75, 0x35, 0x55, 0x15, 0x65, 0x25, 0x45, 0x05,
 
96
                0x79, 0x39, 0x59, 0x19, 0x69, 0x29, 0x49, 0x09,
 
97
                0x71, 0x31, 0x51, 0x11, 0x61, 0x21, 0x41, 0x01,
 
98
                0x7e, 0x3e, 0x5e, 0x1e, 0x6e, 0x2e, 0x4e, 0x0e,
 
99
                0x76, 0x36, 0x56, 0x16, 0x66, 0x26, 0x46, 0x06,
 
100
                0x7a, 0x3a, 0x5a, 0x1a, 0x6a, 0x2a, 0x4a, 0x0a,
 
101
                0x72, 0x32, 0x52, 0x12, 0x62, 0x22, 0x42, 0x02,
 
102
                0x7c, 0x3c, 0x5c, 0x1c, 0x6c, 0x2c, 0x4c, 0x0c,
 
103
                0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04,
 
104
                0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
 
105
                0x70, 0x30, 0x50, 0x10, 0x60, 0x20, 0x40, 0x00,
 
106
        };
 
107
 
 
108
        UINT8 codeword = SDD1_IM_getCodeword(thisptr->IM, code_num);
 
109
 
 
110
        if (codeword & 0x80)
 
111
        {
 
112
                *LPSind = 1;
 
113
                *MPScount = run_count[codeword >> (code_num ^ 0x07)];
 
114
        }
 
115
        else
 
116
        {
 
117
                *MPScount = (1 << code_num);
 
118
        }
 
119
}
 
120
 
 
121
typedef struct // Bits Generator
 
122
{
 
123
        running_machine* machine;
 
124
        UINT8 code_num;
 
125
        UINT8 MPScount;
 
126
        UINT8 LPSind;
 
127
        SDD1_GCD* GCD;
 
128
} SDD1_BG;
 
129
 
 
130
static SDD1_BG* SDD1_BG_ctor(running_machine* machine, SDD1_GCD* associatedGCD, UINT8 code)
 
131
{
 
132
        SDD1_BG* newclass = (SDD1_BG*)auto_alloc_array(machine, UINT8, sizeof(SDD1_BG));
 
133
        newclass->machine = machine;
 
134
        newclass->code_num = code;
 
135
        newclass->GCD = associatedGCD;
 
136
        return newclass;
 
137
}
 
138
 
 
139
static void SDD1_BG_prepareDecomp(SDD1_BG* thisptr)
 
140
{
 
141
        thisptr->MPScount = 0;
 
142
        thisptr->LPSind = 0;
 
143
}
 
144
 
 
145
static UINT8 SDD1_BG_getBit(SDD1_BG* thisptr, UINT8* endOfRun)
 
146
{
 
147
        UINT8 bit;
 
148
 
 
149
        if (!(thisptr->MPScount || thisptr->LPSind))
 
150
        {
 
151
                SDD1_GCD_getRunCount(thisptr->GCD, thisptr->code_num, &(thisptr->MPScount), &(thisptr->LPSind));
 
152
        }
 
153
 
 
154
        if (thisptr->MPScount)
 
155
        {
 
156
                bit = 0;
 
157
                thisptr->MPScount--;
 
158
        }
 
159
        else
 
160
        {
 
161
                bit = 1;
 
162
                thisptr->LPSind = 0;
 
163
        }
 
164
 
 
165
        if (thisptr->MPScount || thisptr->LPSind)
 
166
        {
 
167
                (*endOfRun) = 0;
 
168
        }
 
169
        else
 
170
        {
 
171
                (*endOfRun) = 1;
 
172
        }
 
173
 
 
174
        return bit;
 
175
}
 
176
 
 
177
 
 
178
typedef struct
 
179
{
 
180
        UINT8 code_num;
 
181
        UINT8 nextIfMPS;
 
182
        UINT8 nextIfLPS;
 
183
} SDD1_PEM_state;
 
184
 
 
185
static const SDD1_PEM_state SDD1_PEM_evolution_table[33] =
 
186
{
 
187
        { 0,25,25},
 
188
        { 0, 2, 1},
 
189
        { 0, 3, 1},
 
190
        { 0, 4, 2},
 
191
        { 0, 5, 3},
 
192
        { 1, 6, 4},
 
193
        { 1, 7, 5},
 
194
        { 1, 8, 6},
 
195
        { 1, 9, 7},
 
196
        { 2,10, 8},
 
197
        { 2,11, 9},
 
198
        { 2,12,10},
 
199
        { 2,13,11},
 
200
        { 3,14,12},
 
201
        { 3,15,13},
 
202
        { 3,16,14},
 
203
        { 3,17,15},
 
204
        { 4,18,16},
 
205
        { 4,19,17},
 
206
        { 5,20,18},
 
207
        { 5,21,19},
 
208
        { 6,22,20},
 
209
        { 6,23,21},
 
210
        { 7,24,22},
 
211
        { 7,24,23},
 
212
        { 0,26, 1},
 
213
        { 1,27, 2},
 
214
        { 2,28, 4},
 
215
        { 3,29, 8},
 
216
        { 4,30,12},
 
217
        { 5,31,16},
 
218
        { 6,32,18},
 
219
        { 7,24,22}
 
220
};
 
221
 
 
222
typedef struct
 
223
{
 
224
        UINT8 status;
 
225
        UINT8 MPS;
 
226
} SDD1_PEM_ContextInfo;
 
227
 
 
228
typedef struct //Probability Estimation Module
 
229
{
 
230
        running_machine* machine;
 
231
        SDD1_PEM_ContextInfo contextInfo[32];
 
232
        SDD1_BG* BG[8];
 
233
} SDD1_PEM;
 
234
 
 
235
static SDD1_PEM* SDD1_PEM_ctor(running_machine* machine,
 
236
                                                           SDD1_BG* associatedBG0, SDD1_BG* associatedBG1,
 
237
                                                           SDD1_BG* associatedBG2, SDD1_BG* associatedBG3,
 
238
                                                           SDD1_BG* associatedBG4, SDD1_BG* associatedBG5,
 
239
                                                           SDD1_BG* associatedBG6, SDD1_BG* associatedBG7)
 
240
{
 
241
        SDD1_PEM* newclass = (SDD1_PEM*)auto_alloc_array(machine, UINT8, sizeof(SDD1_PEM));
 
242
        newclass->machine = machine;
 
243
        newclass->BG[0] = associatedBG0;
 
244
        newclass->BG[1] = associatedBG1;
 
245
        newclass->BG[2] = associatedBG2;
 
246
        newclass->BG[3] = associatedBG3;
 
247
        newclass->BG[4] = associatedBG4;
 
248
        newclass->BG[5] = associatedBG5;
 
249
        newclass->BG[6] = associatedBG6;
 
250
        newclass->BG[7] = associatedBG7;
 
251
        return newclass;
 
252
}
 
253
 
 
254
static void SDD1_PEM_prepareDecomp(SDD1_PEM* thisptr)
 
255
{
 
256
        UINT8 i;
 
257
        for(i = 0; i < 32; i++)
 
258
        {
 
259
                thisptr->contextInfo[i].status = 0;
 
260
                thisptr->contextInfo[i].MPS = 0;
 
261
        }
 
262
}
 
263
 
 
264
static UINT8 SDD1_PEM_getBit(SDD1_PEM* thisptr, UINT8 context)
 
265
{
 
266
        UINT8 endOfRun;
 
267
        UINT8 bit;
 
268
 
 
269
        SDD1_PEM_ContextInfo *pContInfo = &(thisptr->contextInfo)[context];
 
270
        UINT8 currStatus = pContInfo->status;
 
271
        const SDD1_PEM_state* pState = &(SDD1_PEM_evolution_table[currStatus]);
 
272
        UINT8 currentMPS = pContInfo->MPS;
 
273
 
 
274
        bit = SDD1_BG_getBit(thisptr->BG[pState->code_num], &endOfRun);
 
275
 
 
276
        if (endOfRun)
 
277
        {
 
278
                if (bit)
 
279
                {
 
280
                        if (!(currStatus & 0xfe))
 
281
                        {
 
282
                                (pContInfo->MPS) ^= 0x01;
 
283
                        }
 
284
                        pContInfo->status = pState->nextIfLPS;
 
285
                }
 
286
                else
 
287
                {
 
288
                        pContInfo->status = pState->nextIfMPS;
 
289
                }
 
290
        }
 
291
 
 
292
        return bit ^ currentMPS;
 
293
}
 
294
 
 
295
typedef struct
 
296
{
 
297
        running_machine* machine;
 
298
        UINT8 bitplanesInfo;
 
299
        UINT8 contextBitsInfo;
 
300
        UINT8 bit_number;
 
301
        UINT8 currBitplane;
 
302
        UINT16 prevBitplaneBits[8];
 
303
        SDD1_PEM* PEM;
 
304
} SDD1_CM;
 
305
 
 
306
static SDD1_CM* SDD1_CM_ctor(running_machine* machine, SDD1_PEM* associatedPEM)
 
307
{
 
308
        SDD1_CM* newclass = (SDD1_CM*)auto_alloc_array(machine, UINT8, sizeof(SDD1_CM));
 
309
        newclass->machine = machine;
 
310
        newclass->PEM = associatedPEM;
 
311
        return newclass;
 
312
}
 
313
 
 
314
static void SDD1_CM_prepareDecomp(SDD1_CM* thisptr, UINT32 first_byte)
 
315
{
 
316
        INT32 i = 0;
 
317
        thisptr->bitplanesInfo = sdd1_read(thisptr->machine, first_byte) & 0xc0;
 
318
        thisptr->contextBitsInfo = sdd1_read(thisptr->machine, first_byte) & 0x30;
 
319
        thisptr->bit_number = 0;
 
320
        for (i = 0; i < 8; i++)
 
321
        {
 
322
                thisptr->prevBitplaneBits[i] = 0;
 
323
        }
 
324
        switch(thisptr->bitplanesInfo)
 
325
        {
 
326
                case 0x00:
 
327
                        thisptr->currBitplane = 1;
 
328
                        break;
 
329
                case 0x40:
 
330
                        thisptr->currBitplane = 7;
 
331
                        break;
 
332
                case 0x80:
 
333
                        thisptr->currBitplane = 3;
 
334
                        break;
 
335
        }
 
336
}
 
337
 
 
338
static UINT8 SDD1_CM_getBit(SDD1_CM* thisptr)
 
339
{
 
340
        UINT8 currContext;
 
341
        UINT16 *context_bits;
 
342
        UINT8 bit = 0;
 
343
 
 
344
        switch (thisptr->bitplanesInfo)
 
345
        {
 
346
                case 0x00:
 
347
                        thisptr->currBitplane ^= 0x01;
 
348
                        break;
 
349
                case 0x40:
 
350
                        thisptr->currBitplane ^= 0x01;
 
351
                        if (!(thisptr->bit_number & 0x7f))
 
352
                        {
 
353
                                thisptr->currBitplane = ((thisptr->currBitplane + 2) & 0x07);
 
354
                        }
 
355
                        break;
 
356
                case 0x80:
 
357
                        thisptr->currBitplane ^= 0x01;
 
358
                        if (!(thisptr->bit_number & 0x7f))
 
359
                        {
 
360
                                thisptr->currBitplane ^= 0x02;
 
361
                        }
 
362
                        break;
 
363
                case 0xc0:
 
364
                        thisptr->currBitplane = thisptr->bit_number & 0x07;
 
365
                        break;
 
366
        }
 
367
 
 
368
        context_bits = &(thisptr->prevBitplaneBits)[thisptr->currBitplane];
 
369
 
 
370
        currContext = (thisptr->currBitplane & 0x01) << 4;
 
371
        switch (thisptr->contextBitsInfo)
 
372
        {
 
373
                case 0x00:
 
374
                        currContext |= ((*context_bits & 0x01c0) >> 5) | (*context_bits & 0x0001);
 
375
                        break;
 
376
                case 0x10:
 
377
                    currContext |= ((*context_bits & 0x0180) >> 5) | (*context_bits & 0x0001);
 
378
                        break;
 
379
                case 0x20:
 
380
                        currContext |= ((*context_bits & 0x00c0) >> 5) | (*context_bits & 0x0001);
 
381
                        break;
 
382
                case 0x30:
 
383
                        currContext |= ((*context_bits & 0x0180) >> 5) | (*context_bits & 0x0003);
 
384
                        break;
 
385
        }
 
386
 
 
387
        bit = SDD1_PEM_getBit(thisptr->PEM, currContext);
 
388
 
 
389
        *context_bits <<= 1;
 
390
        *context_bits |= bit;
 
391
 
 
392
        thisptr->bit_number++;
 
393
 
 
394
        return bit;
 
395
}
 
396
 
 
397
typedef struct
 
398
{
 
399
        running_machine* machine;
 
400
        UINT8 bitplanesInfo;
 
401
        UINT16 length;
 
402
        UINT8* buffer;
 
403
        SDD1_CM* CM;
 
404
} SDD1_OL;
 
405
 
 
406
static SDD1_OL* SDD1_OL_ctor(running_machine* machine, SDD1_CM* associatedCM)
 
407
{
 
408
        SDD1_OL* newclass = (SDD1_OL*)auto_alloc_array(machine, UINT8, sizeof(SDD1_OL));
 
409
        newclass->machine = machine;
 
410
        newclass->CM = associatedCM;
 
411
        return newclass;
 
412
}
 
413
 
 
414
static void SDD1_OL_prepareDecomp(SDD1_OL* thisptr, UINT32 first_byte, UINT16 out_len, UINT8 *out_buf)
 
415
{
 
416
        thisptr->bitplanesInfo = sdd1_read(thisptr->machine, first_byte) & 0xc0;
 
417
        thisptr->length = out_len;
 
418
        thisptr->buffer = out_buf;
 
419
}
 
420
 
 
421
static void SDD1_OL_launch(SDD1_OL* thisptr)
 
422
{
 
423
        UINT8 i;
 
424
        UINT8 register1 = 0, register2 = 0;
 
425
 
 
426
        switch(thisptr->bitplanesInfo)
 
427
        {
 
428
                case 0x00:
 
429
                case 0x40:
 
430
                case 0x80:
 
431
                        i = 1;
 
432
                        do
 
433
                        {       // if length == 0, we output 2^16 bytes
 
434
                                if(!i)
 
435
                                {
 
436
                                        *(thisptr->buffer++) = register2;
 
437
                                        i = ~i;
 
438
                                }
 
439
                                else
 
440
                                {
 
441
                                        for(register1 = register2 = 0, i = 0x80; i; i >>= 1)
 
442
                                        {
 
443
                                                if(SDD1_CM_getBit(thisptr->CM))
 
444
                                                {
 
445
                                                        register1 |= i;
 
446
                                                }
 
447
                                                if(SDD1_CM_getBit(thisptr->CM))
 
448
                                                {
 
449
                                                        register2 |= i;
 
450
                                                }
 
451
                                        }
 
452
                                        *(thisptr->buffer++) = register1;
 
453
                                }
 
454
                        } while(--(thisptr->length));
 
455
                        break;
 
456
                case 0xc0:
 
457
                        do
 
458
                        {
 
459
                                for(register1 = 0, i = 0x01; i; i <<= 1)
 
460
                                {
 
461
                                        if(SDD1_CM_getBit(thisptr->CM))
 
462
                                        {
 
463
                                                register1 |= i;
 
464
                                        }
 
465
                                }
 
466
                                *(thisptr->buffer++) = register1;
 
467
                        } while(--(thisptr->length));
 
468
                        break;
 
469
        }
 
470
}
 
471
 
 
472
typedef struct
 
473
{
 
474
        running_machine* machine;
 
475
        SDD1_IM* IM;
 
476
        SDD1_GCD* GCD;
 
477
        SDD1_BG* BG0;   SDD1_BG* BG1;   SDD1_BG* BG2;   SDD1_BG* BG3;
 
478
        SDD1_BG* BG4;   SDD1_BG* BG5;   SDD1_BG* BG6;   SDD1_BG* BG7;
 
479
        SDD1_PEM* PEM;
 
480
        SDD1_CM* CM;
 
481
        SDD1_OL* OL;
 
482
} SDD1emu;
 
483
 
 
484
static SDD1emu* SDD1emu_ctor(running_machine *machine)
 
485
{
 
486
        SDD1emu* newclass = (SDD1emu*)auto_alloc_array(machine, UINT8, sizeof(SDD1emu));
 
487
        newclass->machine = machine;
 
488
 
 
489
        newclass->IM = SDD1_IM_ctor(machine);
 
490
        newclass->GCD = SDD1_GCD_ctor(machine, newclass->IM);
 
491
        newclass->BG0 = SDD1_BG_ctor(machine, newclass->GCD, 0);
 
492
        newclass->BG1 = SDD1_BG_ctor(machine, newclass->GCD, 1);
 
493
        newclass->BG2 = SDD1_BG_ctor(machine, newclass->GCD, 2);
 
494
        newclass->BG3 = SDD1_BG_ctor(machine, newclass->GCD, 3);
 
495
        newclass->BG4 = SDD1_BG_ctor(machine, newclass->GCD, 4);
 
496
        newclass->BG5 = SDD1_BG_ctor(machine, newclass->GCD, 5);
 
497
        newclass->BG6 = SDD1_BG_ctor(machine, newclass->GCD, 6);
 
498
        newclass->BG7 = SDD1_BG_ctor(machine, newclass->GCD, 7);
 
499
        newclass->PEM = SDD1_PEM_ctor(machine, newclass->BG0, newclass->BG1, newclass->BG2, newclass->BG3,
 
500
                                                                                   newclass->BG4, newclass->BG5, newclass->BG6, newclass->BG7);
 
501
        newclass->CM = SDD1_CM_ctor(machine, newclass->PEM);
 
502
        newclass->OL = SDD1_OL_ctor(machine, newclass->CM);
 
503
        return newclass;
 
504
}
 
505
 
 
506
static void SDD1emu_decompress(SDD1emu* thisptr, UINT32 in_buf, UINT16 out_len, UINT8 *out_buf)
 
507
{
 
508
        SDD1_IM_prepareDecomp(thisptr->IM, in_buf);
 
509
        SDD1_BG_prepareDecomp(thisptr->BG0);
 
510
        SDD1_BG_prepareDecomp(thisptr->BG1);
 
511
        SDD1_BG_prepareDecomp(thisptr->BG2);
 
512
        SDD1_BG_prepareDecomp(thisptr->BG3);
 
513
        SDD1_BG_prepareDecomp(thisptr->BG4);
 
514
        SDD1_BG_prepareDecomp(thisptr->BG5);
 
515
        SDD1_BG_prepareDecomp(thisptr->BG6);
 
516
        SDD1_BG_prepareDecomp(thisptr->BG7);
 
517
        SDD1_PEM_prepareDecomp(thisptr->PEM);
 
518
        SDD1_CM_prepareDecomp(thisptr->CM, in_buf);
 
519
        SDD1_OL_prepareDecomp(thisptr->OL, in_buf, out_len, out_buf);
 
520
 
 
521
        SDD1_OL_launch(thisptr->OL);
 
522
}
 
523
 
 
524
typedef struct
 
525
{
 
526
        UINT8 sdd1_enable;      // channel bit-mask
 
527
        UINT8 xfer_enable;      // channel bit-mask
 
528
        UINT32 mmc[4];          // memory map controller ROM indices
 
529
 
 
530
        struct
 
531
        {
 
532
                UINT32 addr;    // $43x2-$43x4 -- DMA transfer address
 
533
                UINT16 size;    // $43x5-$43x6 -- DMA transfer size
 
534
        } dma[8];
 
535
 
 
536
        SDD1emu* sdd1emu;
 
537
        struct
 
538
        {
 
539
                UINT8 *data;    // pointer to decompressed S-DD1 data (65536 bytes)
 
540
                UINT16 offset;  // read index into S-DD1 decompression buffer
 
541
                UINT32 size;    // length of data buffer; reads decrement counter, set ready to false at 0
 
542
                UINT8 ready;    // 1 when data[] is valid; 0 to invoke sdd1emu.decompress()
 
543
        } buffer;
 
544
} _snes_sdd1_t;
 
545
 
 
546
static _snes_sdd1_t snes_sdd1;
 
547
 
 
548
static void sdd1_init(running_machine* machine)
 
549
{
 
550
        UINT8 i;
 
551
 
 
552
        snes_sdd1.sdd1_enable = 0x00;
 
553
        snes_sdd1.xfer_enable = 0x00;
 
554
 
 
555
        snes_sdd1.mmc[0] = 0 << 20;
 
556
        snes_sdd1.mmc[1] = 1 << 20;
 
557
        snes_sdd1.mmc[2] = 2 << 20;
 
558
        snes_sdd1.mmc[3] = 3 << 20;
 
559
 
 
560
        for(i = 0; i < 8; i++)
 
561
        {
 
562
                snes_sdd1.dma[i].addr = 0;
 
563
                snes_sdd1.dma[i].size = 0;
 
564
        }
 
565
 
 
566
        snes_sdd1.sdd1emu = SDD1emu_ctor(machine);
 
567
 
 
568
        snes_sdd1.buffer.data = (UINT8*)auto_alloc_array(machine, UINT8, 0x10000);
 
569
        snes_sdd1.buffer.ready = 0;
 
570
}
 
571
 
 
572
static UINT8 sdd1_mmio_read(const address_space *space, UINT32 addr)
 
573
{
 
574
        addr &= 0xffff;
 
575
 
 
576
        if((addr & 0x4380) == 0x4300)
 
577
        {
 
578
                return snes_r_io(space, addr & 0x7f);
 
579
        }
 
580
 
 
581
        switch(addr)
 
582
        {
 
583
                case 0x4804:
 
584
                        return (snes_sdd1.mmc[0] >> 20) & 7;
 
585
                        break;
 
586
                case 0x4805:
 
587
                        return (snes_sdd1.mmc[1] >> 20) & 7;
 
588
                        break;
 
589
                case 0x4806:
 
590
                        return (snes_sdd1.mmc[2] >> 20) & 7;
 
591
                        break;
 
592
                case 0x4807:
 
593
                        return (snes_sdd1.mmc[3] >> 20) & 7;
 
594
                        break;
 
595
        }
 
596
 
 
597
        return 0xff;
 
598
}
 
599
 
 
600
static void sdd1_mmio_write(const address_space *space, UINT32 addr, UINT8 data)
 
601
{
 
602
        addr &= 0xffff;
 
603
 
 
604
        if((addr & 0x4380) == 0x4300)
 
605
        {
 
606
                UINT8 channel = (addr >> 4) & 7;
 
607
                switch(addr & 15)
 
608
                {
 
609
                        case 2:
 
610
                                snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0xffff00) + (data <<  0);
 
611
                                break;
 
612
                        case 3:
 
613
                                snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0xff00ff) + (data <<  8);
 
614
                                break;
 
615
                        case 4:
 
616
                                snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0x00ffff) + (data << 16);
 
617
                                break;
 
618
 
 
619
                        case 5:
 
620
                                snes_sdd1.dma[channel].size = (snes_sdd1.dma[channel].size &   0xff00) + (data <<  0);
 
621
                                break;
 
622
                        case 6:
 
623
                                snes_sdd1.dma[channel].size = (snes_sdd1.dma[channel].size &   0x00ff) + (data <<  8);
 
624
                                break;
 
625
                }
 
626
                snes_ram[addr] = data;
 
627
                return;
 
628
        }
 
629
 
 
630
        switch(addr)
 
631
        {
 
632
                case 0x4800:
 
633
                        snes_sdd1.sdd1_enable = data;
 
634
                        break;
 
635
                case 0x4801:
 
636
                        snes_sdd1.xfer_enable = data;
 
637
                        break;
 
638
 
 
639
                case 0x4804:
 
640
                        snes_sdd1.mmc[0] = (data & 7) << 20;
 
641
                        break;
 
642
                case 0x4805:
 
643
                        snes_sdd1.mmc[1] = (data & 7) << 20;
 
644
                        break;
 
645
                case 0x4806:
 
646
                        snes_sdd1.mmc[2] = (data & 7) << 20;
 
647
                        break;
 
648
                case 0x4807:
 
649
                        snes_sdd1.mmc[3] = (data & 7) << 20;
 
650
                        break;
 
651
        }
 
652
}
 
653
 
 
654
static UINT8 sdd1_read(running_machine* machine, UINT32 addr)
 
655
{
 
656
        unsigned char *ROM = memory_region(machine, "cart");
 
657
 
 
658
        if(snes_sdd1.sdd1_enable & snes_sdd1.xfer_enable)
 
659
        {
 
660
                // at least one channel has S-DD1 decompression enabled...
 
661
                UINT32 i;
 
662
                for(i = 0; i < 8; i++)
 
663
                {
 
664
                        if(snes_sdd1.sdd1_enable & snes_sdd1.xfer_enable & (1 << i))
 
665
                        {
 
666
                                // S-DD1 always uses fixed transfer mode, so address will not change during transfer
 
667
                                if((addr + 0xc00000) == snes_sdd1.dma[i].addr)
 
668
                                {
 
669
                                        UINT8 data;
 
670
                                        if(!snes_sdd1.buffer.ready)
 
671
                                        {
 
672
                                                UINT8 temp;
 
673
                                                // first byte read for channel performs full decompression.
 
674
                                                // this really should stream byte-by-byte, but it's not necessary since the size is known
 
675
                                                snes_sdd1.buffer.offset = 0;
 
676
                                                snes_sdd1.buffer.size = snes_sdd1.dma[i].size ? snes_sdd1.dma[i].size : 65536;
 
677
 
 
678
                                                // sdd1emu calls this function; it needs to access uncompressed data;
 
679
                                                // so temporarily disable decompression mode for decompress() call.
 
680
                                                temp = snes_sdd1.sdd1_enable;
 
681
                                                snes_sdd1.sdd1_enable = 0;
 
682
                                                SDD1emu_decompress(snes_sdd1.sdd1emu, addr, snes_sdd1.buffer.size, snes_sdd1.buffer.data);
 
683
                                                snes_sdd1.sdd1_enable = temp;
 
684
 
 
685
                                                snes_sdd1.buffer.ready = 1;
 
686
                                        }
 
687
 
 
688
                                        // fetch a decompressed byte; once buffer is depleted, disable channel and invalidate buffer
 
689
                                        data = snes_sdd1.buffer.data[(UINT16)snes_sdd1.buffer.offset++];
 
690
                                        if(snes_sdd1.buffer.offset >= snes_sdd1.buffer.size)
 
691
                                        {
 
692
                                                snes_sdd1.buffer.ready = 0;
 
693
                                                snes_sdd1.xfer_enable &= ~(1 << i);
 
694
                                        }
 
695
 
 
696
                                        return data;
 
697
                                } // address matched
 
698
                        } // channel enabled
 
699
                } // channel loop
 
700
        } // S-DD1 decompressor enabled
 
701
 
 
702
        return ROM[snes_sdd1.mmc[(addr >> 20) & 3] + (addr & 0x0fffff)];
 
703
}
 
704
 
 
705
static void sdd1_reset(running_machine *machine)
 
706
{
 
707
}