1
/***************************************************************************
5
File to handle emulation of the SNES "S-DD1" add-on chip.
7
Based on Andreas Naive Public Domain code.
9
***************************************************************************/
11
static UINT8 sdd1_read(running_machine* machine, UINT32 addr);
13
typedef struct //Input Manager
15
running_machine* machine;
20
static SDD1_IM* SDD1_IM_ctor(running_machine* machine)
22
SDD1_IM* newclass = (SDD1_IM*)auto_alloc_array(machine, UINT8, sizeof(SDD1_IM));
23
newclass->machine = machine;
27
static void SDD1_IM_prepareDecomp(SDD1_IM* thisptr, UINT32 in_buf)
29
thisptr->byte_ptr = in_buf;
30
thisptr->bit_count = 4;
33
static UINT8 SDD1_IM_getCodeword(SDD1_IM* thisptr, const UINT8 code_len)
37
codeword = sdd1_read(thisptr->machine, thisptr->byte_ptr) << thisptr->bit_count;
43
codeword |= sdd1_read(thisptr->machine, thisptr->byte_ptr + 1) >> (9 - thisptr->bit_count);
44
thisptr->bit_count += code_len;
47
if (thisptr->bit_count & 0x08)
50
thisptr->bit_count &= 0x07;
56
typedef struct //Golomb-Code Decoder
58
running_machine* machine;
62
static SDD1_GCD* SDD1_GCD_ctor(running_machine* machine, SDD1_IM* associatedIM)
64
SDD1_GCD* newclass = (SDD1_GCD*)auto_alloc_array(machine, UINT8, sizeof(SDD1_GCD));
65
newclass->machine = machine;
66
newclass->IM = associatedIM;
70
static void SDD1_GCD_getRunCount(SDD1_GCD* thisptr, UINT8 code_num, UINT8* MPScount, UINT8* LPSind)
72
const UINT8 run_count[] =
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,
108
UINT8 codeword = SDD1_IM_getCodeword(thisptr->IM, code_num);
113
*MPScount = run_count[codeword >> (code_num ^ 0x07)];
117
*MPScount = (1 << code_num);
121
typedef struct // Bits Generator
123
running_machine* machine;
130
static SDD1_BG* SDD1_BG_ctor(running_machine* machine, SDD1_GCD* associatedGCD, UINT8 code)
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;
139
static void SDD1_BG_prepareDecomp(SDD1_BG* thisptr)
141
thisptr->MPScount = 0;
145
static UINT8 SDD1_BG_getBit(SDD1_BG* thisptr, UINT8* endOfRun)
149
if (!(thisptr->MPScount || thisptr->LPSind))
151
SDD1_GCD_getRunCount(thisptr->GCD, thisptr->code_num, &(thisptr->MPScount), &(thisptr->LPSind));
154
if (thisptr->MPScount)
165
if (thisptr->MPScount || thisptr->LPSind)
185
static const SDD1_PEM_state SDD1_PEM_evolution_table[33] =
226
} SDD1_PEM_ContextInfo;
228
typedef struct //Probability Estimation Module
230
running_machine* machine;
231
SDD1_PEM_ContextInfo contextInfo[32];
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)
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;
254
static void SDD1_PEM_prepareDecomp(SDD1_PEM* thisptr)
257
for(i = 0; i < 32; i++)
259
thisptr->contextInfo[i].status = 0;
260
thisptr->contextInfo[i].MPS = 0;
264
static UINT8 SDD1_PEM_getBit(SDD1_PEM* thisptr, UINT8 context)
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;
274
bit = SDD1_BG_getBit(thisptr->BG[pState->code_num], &endOfRun);
280
if (!(currStatus & 0xfe))
282
(pContInfo->MPS) ^= 0x01;
284
pContInfo->status = pState->nextIfLPS;
288
pContInfo->status = pState->nextIfMPS;
292
return bit ^ currentMPS;
297
running_machine* machine;
299
UINT8 contextBitsInfo;
302
UINT16 prevBitplaneBits[8];
306
static SDD1_CM* SDD1_CM_ctor(running_machine* machine, SDD1_PEM* associatedPEM)
308
SDD1_CM* newclass = (SDD1_CM*)auto_alloc_array(machine, UINT8, sizeof(SDD1_CM));
309
newclass->machine = machine;
310
newclass->PEM = associatedPEM;
314
static void SDD1_CM_prepareDecomp(SDD1_CM* thisptr, UINT32 first_byte)
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++)
322
thisptr->prevBitplaneBits[i] = 0;
324
switch(thisptr->bitplanesInfo)
327
thisptr->currBitplane = 1;
330
thisptr->currBitplane = 7;
333
thisptr->currBitplane = 3;
338
static UINT8 SDD1_CM_getBit(SDD1_CM* thisptr)
341
UINT16 *context_bits;
344
switch (thisptr->bitplanesInfo)
347
thisptr->currBitplane ^= 0x01;
350
thisptr->currBitplane ^= 0x01;
351
if (!(thisptr->bit_number & 0x7f))
353
thisptr->currBitplane = ((thisptr->currBitplane + 2) & 0x07);
357
thisptr->currBitplane ^= 0x01;
358
if (!(thisptr->bit_number & 0x7f))
360
thisptr->currBitplane ^= 0x02;
364
thisptr->currBitplane = thisptr->bit_number & 0x07;
368
context_bits = &(thisptr->prevBitplaneBits)[thisptr->currBitplane];
370
currContext = (thisptr->currBitplane & 0x01) << 4;
371
switch (thisptr->contextBitsInfo)
374
currContext |= ((*context_bits & 0x01c0) >> 5) | (*context_bits & 0x0001);
377
currContext |= ((*context_bits & 0x0180) >> 5) | (*context_bits & 0x0001);
380
currContext |= ((*context_bits & 0x00c0) >> 5) | (*context_bits & 0x0001);
383
currContext |= ((*context_bits & 0x0180) >> 5) | (*context_bits & 0x0003);
387
bit = SDD1_PEM_getBit(thisptr->PEM, currContext);
390
*context_bits |= bit;
392
thisptr->bit_number++;
399
running_machine* machine;
406
static SDD1_OL* SDD1_OL_ctor(running_machine* machine, SDD1_CM* associatedCM)
408
SDD1_OL* newclass = (SDD1_OL*)auto_alloc_array(machine, UINT8, sizeof(SDD1_OL));
409
newclass->machine = machine;
410
newclass->CM = associatedCM;
414
static void SDD1_OL_prepareDecomp(SDD1_OL* thisptr, UINT32 first_byte, UINT16 out_len, UINT8 *out_buf)
416
thisptr->bitplanesInfo = sdd1_read(thisptr->machine, first_byte) & 0xc0;
417
thisptr->length = out_len;
418
thisptr->buffer = out_buf;
421
static void SDD1_OL_launch(SDD1_OL* thisptr)
424
UINT8 register1 = 0, register2 = 0;
426
switch(thisptr->bitplanesInfo)
433
{ // if length == 0, we output 2^16 bytes
436
*(thisptr->buffer++) = register2;
441
for(register1 = register2 = 0, i = 0x80; i; i >>= 1)
443
if(SDD1_CM_getBit(thisptr->CM))
447
if(SDD1_CM_getBit(thisptr->CM))
452
*(thisptr->buffer++) = register1;
454
} while(--(thisptr->length));
459
for(register1 = 0, i = 0x01; i; i <<= 1)
461
if(SDD1_CM_getBit(thisptr->CM))
466
*(thisptr->buffer++) = register1;
467
} while(--(thisptr->length));
474
running_machine* machine;
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;
484
static SDD1emu* SDD1emu_ctor(running_machine *machine)
486
SDD1emu* newclass = (SDD1emu*)auto_alloc_array(machine, UINT8, sizeof(SDD1emu));
487
newclass->machine = machine;
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);
506
static void SDD1emu_decompress(SDD1emu* thisptr, UINT32 in_buf, UINT16 out_len, UINT8 *out_buf)
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);
521
SDD1_OL_launch(thisptr->OL);
526
UINT8 sdd1_enable; // channel bit-mask
527
UINT8 xfer_enable; // channel bit-mask
528
UINT32 mmc[4]; // memory map controller ROM indices
532
UINT32 addr; // $43x2-$43x4 -- DMA transfer address
533
UINT16 size; // $43x5-$43x6 -- DMA transfer size
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()
546
static _snes_sdd1_t snes_sdd1;
548
static void sdd1_init(running_machine* machine)
552
snes_sdd1.sdd1_enable = 0x00;
553
snes_sdd1.xfer_enable = 0x00;
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;
560
for(i = 0; i < 8; i++)
562
snes_sdd1.dma[i].addr = 0;
563
snes_sdd1.dma[i].size = 0;
566
snes_sdd1.sdd1emu = SDD1emu_ctor(machine);
568
snes_sdd1.buffer.data = (UINT8*)auto_alloc_array(machine, UINT8, 0x10000);
569
snes_sdd1.buffer.ready = 0;
572
static UINT8 sdd1_mmio_read(const address_space *space, UINT32 addr)
576
if((addr & 0x4380) == 0x4300)
578
return snes_r_io(space, addr & 0x7f);
584
return (snes_sdd1.mmc[0] >> 20) & 7;
587
return (snes_sdd1.mmc[1] >> 20) & 7;
590
return (snes_sdd1.mmc[2] >> 20) & 7;
593
return (snes_sdd1.mmc[3] >> 20) & 7;
600
static void sdd1_mmio_write(const address_space *space, UINT32 addr, UINT8 data)
604
if((addr & 0x4380) == 0x4300)
606
UINT8 channel = (addr >> 4) & 7;
610
snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0xffff00) + (data << 0);
613
snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0xff00ff) + (data << 8);
616
snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0x00ffff) + (data << 16);
620
snes_sdd1.dma[channel].size = (snes_sdd1.dma[channel].size & 0xff00) + (data << 0);
623
snes_sdd1.dma[channel].size = (snes_sdd1.dma[channel].size & 0x00ff) + (data << 8);
626
snes_ram[addr] = data;
633
snes_sdd1.sdd1_enable = data;
636
snes_sdd1.xfer_enable = data;
640
snes_sdd1.mmc[0] = (data & 7) << 20;
643
snes_sdd1.mmc[1] = (data & 7) << 20;
646
snes_sdd1.mmc[2] = (data & 7) << 20;
649
snes_sdd1.mmc[3] = (data & 7) << 20;
654
static UINT8 sdd1_read(running_machine* machine, UINT32 addr)
656
unsigned char *ROM = memory_region(machine, "cart");
658
if(snes_sdd1.sdd1_enable & snes_sdd1.xfer_enable)
660
// at least one channel has S-DD1 decompression enabled...
662
for(i = 0; i < 8; i++)
664
if(snes_sdd1.sdd1_enable & snes_sdd1.xfer_enable & (1 << i))
666
// S-DD1 always uses fixed transfer mode, so address will not change during transfer
667
if((addr + 0xc00000) == snes_sdd1.dma[i].addr)
670
if(!snes_sdd1.buffer.ready)
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;
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;
685
snes_sdd1.buffer.ready = 1;
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)
692
snes_sdd1.buffer.ready = 0;
693
snes_sdd1.xfer_enable &= ~(1 << i);
700
} // S-DD1 decompressor enabled
702
return ROM[snes_sdd1.mmc[(addr >> 20) & 3] + (addr & 0x0fffff)];
705
static void sdd1_reset(running_machine *machine)