1
/************************************************************************
5
Copyright (c) 2003-2009 John Weidman, Kris Bleakley, Lancer, Nach,
6
z80 gaiden, and Jonas Quinn
8
This code is released by ZSNES Team under GNU General Public License
9
version 2 as published by the Free Software Foundation.
10
The implementation below is released under the MAME license for use
11
in MAME, MESS and derivatives by permission of the authors.
13
************************************************************************/
15
static UINT16 DSP3_DataROM[1024];
17
static void(*SetDSP3)(void);
18
static void DSP3_Command(void);
20
static UINT16 DSP3_DR;
21
static UINT16 DSP3_SR;
22
static UINT16 DSP3_MemoryIndex;
24
static void DSP3_Reset(void)
28
SetDSP3 = &DSP3_Command;
31
#ifdef UNUSED_FUNCTION
32
void DSP3_MemorySize(void)
35
SetDSP3 = &DSP3_Reset;
39
static void DSP3_TestMemory(void)
42
SetDSP3 = &DSP3_Reset;
45
static void DSP3_DumpDataROM(void)
47
DSP3_DR = DSP3_DataROM[DSP3_MemoryIndex++];
48
if (DSP3_MemoryIndex == 1024)
49
SetDSP3 = &DSP3_Reset;
52
static void DSP3_MemoryDump(void)
55
SetDSP3 = &DSP3_DumpDataROM;
59
static INT16 DSP3_WinLo;
60
static INT16 DSP3_WinHi;
62
static void DSP3_OP06(void)
64
DSP3_WinLo = (UINT8)(DSP3_DR);
65
DSP3_WinHi = (UINT8)(DSP3_DR >> 8);
69
static void DSP3_OP03(void)
71
INT16 Lo = (UINT8)(DSP3_DR);
72
INT16 Hi = (UINT8)(DSP3_DR >> 8);
73
INT16 Ofs = (DSP3_WinLo * Hi << 1) + (Lo << 1);
75
SetDSP3 = &DSP3_Reset;
78
static INT16 DSP3_AddLo;
79
static INT16 DSP3_AddHi;
81
static void DSP3_OP07_B(void)
83
INT16 Ofs = (DSP3_WinLo * DSP3_AddHi << 1) + (DSP3_AddLo << 1);
85
SetDSP3 = &DSP3_Reset;
88
static void DSP3_OP07_A(void)
90
INT16 Lo = (UINT8)(DSP3_DR);
91
INT16 Hi = (UINT8)(DSP3_DR >> 8);
93
if (Lo & 1) Hi += (DSP3_AddLo & 1);
99
DSP3_AddLo += DSP3_WinLo;
101
if (DSP3_AddLo >= DSP3_WinLo)
102
DSP3_AddLo -= DSP3_WinLo;
105
DSP3_AddHi += DSP3_WinHi;
107
if (DSP3_AddHi >= DSP3_WinHi)
108
DSP3_AddHi -= DSP3_WinHi;
110
DSP3_DR = DSP3_AddLo | (DSP3_AddHi << 8) | ((DSP3_AddHi >> 8) & 0xff);
111
SetDSP3 = &DSP3_OP07_B;
114
static void DSP3_OP07(void)
116
UINT32 dataOfs = ((DSP3_DR << 1) + 0x03b2) & 0x03ff;
118
DSP3_AddHi = DSP3_DataROM[dataOfs];
119
DSP3_AddLo = DSP3_DataROM[dataOfs + 1];
121
SetDSP3 = &DSP3_OP07_A;
125
static UINT16 DSP3_Codewords;
126
static UINT16 DSP3_Outwords;
127
static UINT16 DSP3_Symbol;
128
static UINT16 DSP3_BitCount;
129
static UINT16 DSP3_Index;
130
static UINT16 DSP3_Codes[512];
131
static UINT16 DSP3_BitsLeft;
132
static UINT16 DSP3_ReqBits;
133
static UINT16 DSP3_ReqData;
134
static UINT16 DSP3_BitCommand;
135
static UINT8 DSP3_BaseLength;
136
static UINT16 DSP3_BaseCodes;
137
static UINT16 DSP3_BaseCode;
138
static UINT8 DSP3_CodeLengths[8];
139
static UINT16 DSP3_CodeOffsets[8];
140
static UINT16 DSP3_LZCode;
141
static UINT8 DSP3_LZLength;
143
static UINT16 DSP3_X;
144
static UINT16 DSP3_Y;
146
static void DSP3_Coordinate(void)
154
if (DSP3_DR == 0xffff)
183
static UINT8 DSP3_Bitmap[8];
184
static UINT8 DSP3_Bitplane[8];
185
static UINT16 DSP3_BMIndex;
186
static UINT16 DSP3_BPIndex;
187
static UINT16 DSP3_Count;
189
static void DSP3_Convert_A(void)
191
if (DSP3_BMIndex < 8)
193
DSP3_Bitmap[DSP3_BMIndex++] = (UINT8) (DSP3_DR);
194
DSP3_Bitmap[DSP3_BMIndex++] = (UINT8) (DSP3_DR >> 8);
196
if (DSP3_BMIndex == 8)
199
for (i=0; i < 8; i++)
200
for (j=0; j < 8; j++)
202
DSP3_Bitplane[j] <<= 1;
203
DSP3_Bitplane[j] |= (DSP3_Bitmap[i] >> j) & 1;
211
if (DSP3_BMIndex == 8)
213
if (DSP3_BPIndex == 8)
215
if (!DSP3_Count) DSP3_Reset();
220
DSP3_DR = DSP3_Bitplane[DSP3_BPIndex++];
221
DSP3_DR |= DSP3_Bitplane[DSP3_BPIndex++] << 8;
226
static void DSP3_Convert(void)
228
DSP3_Count = DSP3_DR;
230
SetDSP3 = &DSP3_Convert_A;
233
static UINT8 DSP3_GetBits(UINT8 Count)
237
DSP3_BitsLeft = Count;
249
if (DSP3_ReqData & 0x8000) DSP3_ReqBits++;
255
} while (DSP3_BitsLeft);
260
static void DSP3_Decode_Data(void)
266
DSP3_ReqData = DSP3_DR;
276
if (DSP3_LZCode == 1)
278
if (!DSP3_GetBits(1))
289
if (DSP3_LZCode == 2)
291
if (!DSP3_GetBits(DSP3_LZLength))
296
if (!DSP3_Outwords) SetDSP3 = &DSP3_Reset;
299
DSP3_DR = DSP3_ReqBits;
303
if (DSP3_BaseCode == 0xffff)
305
if (!DSP3_GetBits(DSP3_BaseLength))
308
DSP3_BaseCode = DSP3_ReqBits;
311
if (!DSP3_GetBits(DSP3_CodeLengths[DSP3_BaseCode]))
314
DSP3_Symbol = DSP3_Codes[DSP3_CodeOffsets[DSP3_BaseCode] + DSP3_ReqBits];
315
DSP3_BaseCode = 0xffff;
317
if (DSP3_Symbol & 0xff00)
319
DSP3_Symbol += 0x7f02;
326
SetDSP3 = &DSP3_Reset;
330
DSP3_DR = DSP3_Symbol;
333
static void DSP3_Decode_Tree(void)
337
DSP3_ReqData = DSP3_DR;
356
while (DSP3_BaseCodes)
358
if (!DSP3_GetBits(3))
363
DSP3_CodeLengths[DSP3_Index] = (UINT8) DSP3_ReqBits;
364
DSP3_CodeOffsets[DSP3_Index] = DSP3_Symbol;
367
DSP3_Symbol += 1 << DSP3_ReqBits;
371
DSP3_BaseCode = 0xffff;
374
SetDSP3 = &DSP3_Decode_Data;
375
if (DSP3_BitCount) DSP3_Decode_Data();
378
static void DSP3_Decode_Symbols(void)
380
DSP3_ReqData = DSP3_DR;
385
if (DSP3_BitCommand == 0xffff)
387
if (!DSP3_GetBits(2)) return;
388
DSP3_BitCommand = DSP3_ReqBits;
391
switch (DSP3_BitCommand)
395
if (!DSP3_GetBits(9)) return;
396
DSP3_Symbol = DSP3_ReqBits;
406
if (!DSP3_GetBits(1)) return;
407
DSP3_Symbol += 2 + DSP3_ReqBits;
412
if (!DSP3_GetBits(4)) return;
413
DSP3_Symbol += 4 + DSP3_ReqBits;
418
DSP3_BitCommand = 0xffff;
420
DSP3_Codes[DSP3_Index++] = DSP3_Symbol;
423
} while (DSP3_Codewords);
429
SetDSP3 = &DSP3_Decode_Tree;
430
if (DSP3_BitCount) DSP3_Decode_Tree();
433
static void DSP3_Decode_A(void)
435
DSP3_Outwords = DSP3_DR;
436
SetDSP3 = &DSP3_Decode_Symbols;
441
DSP3_BitCommand = 0xffff;
445
static void DSP3_Decode(void)
447
DSP3_Codewords = DSP3_DR;
448
SetDSP3 = &DSP3_Decode_A;
452
// Opcodes 1E/3E bit-perfect to 'dsp3-intro' log
453
// src: adapted from SD Gundam X/G-Next
458
static INT16 op1e_terrain[0x2000];
459
static INT16 op1e_cost[0x2000];
460
static INT16 op1e_weight[0x2000];
462
static INT16 op1e_cell;
463
static INT16 op1e_turn;
464
static INT16 op1e_search;
469
static INT16 op1e_min_radius;
470
static INT16 op1e_max_radius;
472
static INT16 op1e_max_search_radius;
473
static INT16 op1e_max_path_radius;
475
static INT16 op1e_lcv_radius;
476
static INT16 op1e_lcv_steps;
477
static INT16 op1e_lcv_turns;
479
static void DSP3_OP3E(void)
481
op3e_x = (UINT8)(DSP3_DR & 0x00ff);
482
op3e_y = (UINT8)((DSP3_DR & 0xff00)>>8);
486
op1e_terrain[ DSP3_DR ] = 0x00;
487
op1e_cost[ DSP3_DR ] = 0xff;
488
op1e_weight[ DSP3_DR ] = 0;
490
op1e_max_search_radius = 0;
491
op1e_max_path_radius = 0;
494
static void DSP3_OP1E_A(void);
495
static void DSP3_OP1E_A1(void);
496
static void DSP3_OP1E_A2(void);
497
static void DSP3_OP1E_A3(void);
499
static void DSP3_OP1E_B(void);
500
static void DSP3_OP1E_B1(void);
501
static void DSP3_OP1E_B2(void);
503
static void DSP3_OP1E_C(void);
504
static void DSP3_OP1E_C1(void);
505
static void DSP3_OP1E_C2(void);
507
static void DSP3_OP1E_D( INT16, INT16 *, INT16 * );
508
static void DSP3_OP1E_D1( INT16 move, INT16 *lo, INT16 *hi );
510
static void DSP3_OP1E(void)
514
op1e_min_radius = (UINT8)(DSP3_DR & 0x00ff);
515
op1e_max_radius = (UINT8)((DSP3_DR & 0xff00)>>8);
517
if( op1e_min_radius == 0 )
520
if( op1e_max_search_radius >= op1e_min_radius )
521
op1e_min_radius = op1e_max_search_radius+1;
523
if( op1e_max_radius > op1e_max_search_radius )
524
op1e_max_search_radius = op1e_max_radius;
526
op1e_lcv_radius = op1e_min_radius;
527
op1e_lcv_steps = op1e_min_radius;
535
for( lcv = 0; lcv < op1e_min_radius; lcv++ )
536
DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y );
541
static void DSP3_OP1E_A(void)
545
if( op1e_lcv_steps == 0 ) {
548
op1e_lcv_steps = op1e_lcv_radius;
553
for( lcv = 0; lcv < op1e_lcv_radius; lcv++ )
554
DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y );
557
if( op1e_lcv_radius > op1e_max_radius ) {
561
op1e_lcv_radius = op1e_min_radius;
562
op1e_lcv_steps = op1e_min_radius;
567
for( lcv = 0; lcv < op1e_min_radius; lcv++ )
568
DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y );
571
if( op1e_lcv_turns == 0 ) {
574
SetDSP3 = &DSP3_OP1E_B;
578
DSP3_DR = (UINT8)(op1e_x) | ((UINT8)(op1e_y)<<8);
584
SetDSP3 = &DSP3_OP1E_A1;
587
static void DSP3_OP1E_A1(void)
590
SetDSP3 = &DSP3_OP1E_A2;
593
static void DSP3_OP1E_A2(void)
595
op1e_terrain[ op1e_cell ] = (UINT8)(DSP3_DR & 0x00ff);
598
SetDSP3 = &DSP3_OP1E_A3;
601
static void DSP3_OP1E_A3(void)
603
op1e_cost[ op1e_cell ] = (UINT8)(DSP3_DR & 0x00ff);
605
if( op1e_lcv_radius == 1 ) {
606
if( op1e_terrain[ op1e_cell ] & 1 ) {
607
op1e_weight[ op1e_cell ] = 0xff;
609
op1e_weight[ op1e_cell ] = op1e_cost[ op1e_cell ];
613
op1e_weight[ op1e_cell ] = 0xff;
616
DSP3_OP1E_D( (INT16)(op1e_turn+2), &op1e_x, &op1e_y );
624
static void DSP3_OP1E_B(void)
634
SetDSP3 = &DSP3_OP1E_C;
638
static void DSP3_OP1E_B1(void)
640
while( op1e_lcv_radius < op1e_max_radius ) {
646
while( op1e_lcv_turns ) {
647
op1e_lcv_steps = op1e_lcv_radius;
649
while( op1e_lcv_steps ) {
650
DSP3_OP1E_D1( op1e_turn, &op1e_x, &op1e_y );
652
if( 0 <= op1e_y && op1e_y < DSP3_WinHi &&
653
0 <= op1e_x && op1e_x < DSP3_WinLo ) {
654
DSP3_DR = (UINT8)(op1e_x) | ((UINT8)(op1e_y)<<8);
658
if( op1e_cost[ op1e_cell ] < 0x80 &&
659
op1e_terrain[ op1e_cell ] < 0x40 ) {
661
} // end cell perimeter
668
if( op1e_turn == 0 ) op1e_turn = 6;
671
} // end circle search
674
} // end radius search
678
static void DSP3_OP1E_B2(void)
692
DSP3_OP1E_D1( lcv_turns, &x, &y );
694
DSP3_DR = (UINT8)(x) | ((UINT8)(y)<<8);
699
if( 0 <= y && y < DSP3_WinHi &&
700
0 <= x && x < DSP3_WinLo ) {
702
if( op1e_terrain[ cell ] < 0x80 || op1e_weight[ cell ] == 0 ) {
703
if( op1e_weight[ cell ] < path ) {
704
path = op1e_weight[ cell ];
713
op1e_weight[ op1e_cell ] = path + op1e_cost[ op1e_cell ];
718
static void DSP3_OP1E_C(void)
722
op1e_min_radius = (UINT8)(DSP3_DR & 0x00ff);
723
op1e_max_radius = (UINT8)((DSP3_DR & 0xff00)>>8);
725
if( op1e_min_radius == 0 )
728
if( op1e_max_path_radius >= op1e_min_radius )
729
op1e_min_radius = op1e_max_path_radius+1;
731
if( op1e_max_radius > op1e_max_path_radius )
732
op1e_max_path_radius = op1e_max_radius;
734
op1e_lcv_radius = op1e_min_radius;
735
op1e_lcv_steps = op1e_min_radius;
743
for( lcv = 0; lcv < op1e_min_radius; lcv++ )
744
DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y );
750
static void DSP3_OP1E_C1(void)
754
if( op1e_lcv_steps == 0 ) {
757
op1e_lcv_steps = op1e_lcv_radius;
762
for( lcv = 0; lcv < op1e_lcv_radius; lcv++ )
763
DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y );
766
if( op1e_lcv_radius > op1e_max_radius ) {
770
op1e_lcv_radius = op1e_min_radius;
771
op1e_lcv_steps = op1e_min_radius;
776
for( lcv = 0; lcv < op1e_min_radius; lcv++ )
777
DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y );
780
if( op1e_lcv_turns == 0 ) {
783
SetDSP3 = &DSP3_Reset;
787
DSP3_DR = (UINT8)(op1e_x) | ((UINT8)(op1e_y)<<8);
793
SetDSP3 = &DSP3_OP1E_C2;
797
static void DSP3_OP1E_C2(void)
799
DSP3_DR = op1e_weight[ op1e_cell ];
801
DSP3_OP1E_D( (INT16)(op1e_turn+2), &op1e_x, &op1e_y );
805
SetDSP3 = &DSP3_OP1E_C1;
809
static void DSP3_OP1E_D( INT16 move, INT16 *lo, INT16 *hi )
811
UINT32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff;
815
DSP3_AddHi = DSP3_DataROM[dataOfs];
816
DSP3_AddLo = DSP3_DataROM[dataOfs + 1];
821
if (Lo & 1) Hi += (DSP3_AddLo & 1);
827
DSP3_AddLo += DSP3_WinLo;
829
if (DSP3_AddLo >= DSP3_WinLo)
830
DSP3_AddLo -= DSP3_WinLo;
833
DSP3_AddHi += DSP3_WinHi;
835
if (DSP3_AddHi >= DSP3_WinHi)
836
DSP3_AddHi -= DSP3_WinHi;
843
static void DSP3_OP1E_D1( INT16 move, INT16 *lo, INT16 *hi )
845
//UINT32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff;
849
const unsigned short HiAdd[] = {
850
0x00, 0xFF, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00,
851
0x00, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00
853
const unsigned short LoAdd[] = {
854
0x00, 0x00, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x00
858
DSP3_AddHi = HiAdd[ move + 8 ];
860
DSP3_AddHi = HiAdd[ move + 0 ];
861
DSP3_AddLo = LoAdd[ move ];
866
if (Lo & 1) Hi += (DSP3_AddLo & 1);
876
static void DSP3_OP10(void)
878
if( DSP3_DR == 0xffff ) {
886
#ifdef UNUSED_FUNCTION
887
static void DSP3_OP0C_A(void)
892
SetDSP3 = &DSP3_Reset;
896
static void DSP3_OP0C(void)
901
//SetDSP3 = &DSP3_OP0C_A;
902
SetDSP3 = &DSP3_Reset;
906
static void DSP3_OP1C_C(void)
910
SetDSP3 = &DSP3_Reset;
914
static void DSP3_OP1C_B(void)
920
SetDSP3 = &DSP3_OP1C_C;
924
static void DSP3_OP1C_A(void)
928
SetDSP3 = &DSP3_OP1C_B;
932
static void DSP3_OP1C(void)
936
SetDSP3 = &DSP3_OP1C_A;
940
static void DSP3_Command(void)
946
case 0x02: SetDSP3 = &DSP3_Coordinate; break;
947
case 0x03: SetDSP3 = &DSP3_OP03; break;
948
case 0x06: SetDSP3 = &DSP3_OP06; break;
949
case 0x07: SetDSP3 = &DSP3_OP07; return;
950
case 0x0c: SetDSP3 = &DSP3_OP0C; break;
951
case 0x0f: SetDSP3 = &DSP3_TestMemory; break;
952
case 0x10: SetDSP3 = &DSP3_OP10; break;
953
case 0x18: SetDSP3 = &DSP3_Convert; break;
954
case 0x1c: SetDSP3 = &DSP3_OP1C; break;
955
case 0x1e: SetDSP3 = &DSP3_OP1E; break;
956
case 0x1f: SetDSP3 = &DSP3_MemoryDump; break;
957
case 0x38: SetDSP3 = &DSP3_Decode; break;
958
case 0x3e: SetDSP3 = &DSP3_OP3E; break;
968
static void DSP3_write( UINT16 dsp3_address, UINT8 dsp3_byte )
970
if (dsp3_address < 0xC000)
974
DSP3_DR = (DSP3_DR & 0xff00) + dsp3_byte;
982
DSP3_DR = (DSP3_DR & 0xff00) + dsp3_byte;
985
DSP3_DR = (DSP3_DR & 0x00ff) + (dsp3_byte << 8);
992
static UINT8 DSP3_read( UINT16 dsp3_address )
995
if (dsp3_address < 0xC000)
999
value = (UINT8) DSP3_DR;
1007
value = (UINT8) (DSP3_DR);
1010
value = (UINT8) (DSP3_DR >> 8);
1018
value = (UINT8) DSP3_SR;
1024
static void InitDSP3( running_machine *machine )
1027
UINT8 *dspin = memory_region(machine, "addons");
1031
// expand the DSP-3 data ROM
1032
for (i = 0; i < 2048; i+=2)
1034
DSP3_DataROM[i/2] = dspin[0x800 + i] << 8 | dspin[0x800 + i + 1];