-
Notifications
You must be signed in to change notification settings - Fork 18
/
chiptext.c
4151 lines (3790 loc) · 108 KB
/
chiptext.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// this file generates text lines from chip writes
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "stdtype.h"
#include "stdbool.h"
typedef struct chip_count
{
UINT32 SN76496;
UINT32 YM2413;
UINT32 YM2612;
UINT32 YM2151;
UINT32 SegaPCM;
UINT32 RF5C68;
UINT32 YM2203;
UINT32 YM2608;
UINT32 YM2610;
UINT32 YM3812;
UINT32 YM3526;
UINT32 Y8950;
UINT32 YMF262;
UINT32 YMF278B;
UINT32 YMF271;
UINT32 YMZ280B;
UINT32 RF5C164;
UINT32 PWM;
UINT32 AY8910;
UINT32 GBDMG;
UINT32 NESAPU;
UINT32 MultiPCM;
UINT32 UPD7759;
UINT32 OKIM6258;
UINT32 OKIM6295;
UINT32 K051649;
UINT32 K054539;
UINT32 HuC6280;
UINT32 C140;
UINT32 K053260;
UINT32 Pokey;
UINT32 QSound;
UINT32 SCSP;
UINT32 WSwan;
UINT32 VSU;
UINT32 SAA1099;
UINT32 ES5503;
UINT32 ES5506;
UINT32 X1_010;
UINT32 C352;
UINT32 GA20;
UINT32 Mikey;
} CHIP_CNT;
static const char* ONOFF_STR[0x02] = {"On", "Off"};
static const char* ENABLE_STRS[0x02] = {"Enable", "Disable"};
static const char* NOTE_STRS[0x0C] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
static const char* T6W28_PORT[0x02] = {"L/T", "R/N"};
static const char* SN76496_NOISE_TYPE[0x04] = {"Periodic", "White"};
static const char* SN76496_NOISE_FREQ[0x04] = {"High (6927Hz)", "Med (3463Hz)", "Low (1731Hz)", "Ch 2"};
/*static const char* YM2413_INS_NAMES[0x10] = {"User instrument", "Violin", "Guitar", "Piano", "Flute",
"Clarinet", "Oboe", "Trumpet", "Organ", "Horn", "Synthesizer", "Harpsichord",
"Vibraphone", "Synthesizer Bass", "Acoustic Bass", "Electric Guitar"};
static const char* YM2413_RHYTHM_NAMES[0x05] = {"High Hat", "Cymbal", "Tom-Tom", "Snare Drum",
"Bass Drum"};*/
static const char* YM2151_WAVE_FORM[0x04] = {"Sawtooth", "Square", "Triangle", "Random Noise"};
static const UINT32 dt2_tab[0x04] = {0, 384, 500, 608};
static const char* YMZ280B_MODES[0x04] = {"Unknown", "ADPCM", "PCM8", "PCM16"};
static const char* OPN_LFOFreqs[0x08]= {"3.98", "5.56", "6.02", "6.37", "6.88", "9.63", "48.1", "72.2"};
//static const double PI = 3.1415926535897932;
//static const double PI_HLF = PI / 2;
static const char* PWM_PORTS[0x06] = {"Control Reg", "Cycle Reg", "Left Ch", "Right Ch", "Both Ch", "Invalid"};
static const char* YDT_RAMTYPE[0x04] = {"RAM (1-bit)", "ROM", "RAM (8-bit)", "ROM (invalid)"};
static const char* ADDR_2S_STR[0x02] = {"Low", "High"};
static const char* ADDR_3S_STR[0x03] = {"Low", "Mid", "High"};
#define OPN_TYPE_SSG 0x01 // SSG support
#define OPN_TYPE_LFOPAN 0x02 // OPN type LFO and PAN
#define OPN_TYPE_6CH 0x04 // FM 6CH / 3CH
#define OPN_TYPE_DAC 0x08 // YM2612's DAC device
#define OPN_TYPE_ADPCM 0x10 // two ADPCM units
#define OPN_TYPE_2610 0x20 // bogus flag to differentiate 2608 from 2610
#define OPN_TYPE_YM2203 (OPN_TYPE_SSG)
#define OPN_TYPE_YM2608 (OPN_TYPE_SSG | OPN_TYPE_LFOPAN | OPN_TYPE_6CH | OPN_TYPE_ADPCM)
#define OPN_TYPE_YM2610 (OPN_TYPE_SSG | OPN_TYPE_LFOPAN | OPN_TYPE_6CH | OPN_TYPE_ADPCM | OPN_TYPE_2610)
#define OPN_TYPE_YM2612 (OPN_TYPE_DAC | OPN_TYPE_LFOPAN | OPN_TYPE_6CH)
#define OPN_YM2203 0x00
#define OPN_YM2608 0x01
#define OPN_YM2610 0x02
#define OPN_YM2612 0x03
static const char FMOPN_TYPES[0x04] = {OPN_TYPE_YM2203, OPN_TYPE_YM2608, OPN_TYPE_YM2610,
OPN_TYPE_YM2612};
#define OPL_TYPE_WAVESEL 0x01 // waveform select
#define OPL_TYPE_ADPCM 0x02 // DELTA-T ADPCM unit
#define OPL_TYPE_KEYBOARD 0x04 // keyboard interface
#define OPL_TYPE_IO 0x08 // I/O port
#define OPL_TYPE_OPL3 0x10 // OPL3 Mode
#define OPL_TYPE_OPL4 0x20 // OPL4 Mode
#define OPL_TYPE_YM3526 (0)
#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM | OPL_TYPE_KEYBOARD | OPL_TYPE_IO)
#define OPL_TYPE_YMF262 (OPL_TYPE_YM3812 | OPL_TYPE_OPL3)
#define OPL_TYPE_YMF278 (OPL_TYPE_YMF262 | OPL_TYPE_OPL4)
#define OPL_YM3526 0x00
#define OPL_YM3812 0x01
#define OPL_Y8950 0x02
#define OPL_YMF262 0x03
#define OPL_YMF278 0x04
static const char FMOPL_TYPES[0x05] = {OPL_TYPE_YM3526, OPL_TYPE_YM3812, OPL_TYPE_Y8950,
OPL_TYPE_YMF262, OPL_TYPE_YMF278};
#define NR10 0x00
#define NR11 0x01
#define NR12 0x02
#define NR13 0x03
#define NR14 0x04
#define NR21 0x06
#define NR22 0x07
#define NR23 0x08
#define NR24 0x09
#define NR30 0x0A
#define NR31 0x0B
#define NR32 0x0C
#define NR33 0x0D
#define NR34 0x0E
#define NR41 0x10
#define NR42 0x11
#define NR43 0x12
#define NR44 0x13
#define NR50 0x14
#define NR51 0x15
#define NR52 0x16
static const float GB_WAVE_DUTY[4] = {12.5f, 25.0f, 50.0f, 75.0f}; // in %
static const char* GB_NOISE_MODE[0x02] = {"Counter", "Consecutive"};
#define APU_WRA0 0x00
#define APU_WRA1 0x01
#define APU_WRA2 0x02
#define APU_WRA3 0x03
#define APU_WRB0 0x04
#define APU_WRB1 0x05
#define APU_WRB2 0x06
#define APU_WRB3 0x07
#define APU_WRC0 0x08
#define APU_WRC2 0x0A
#define APU_WRC3 0x0B
#define APU_WRD0 0x0C
#define APU_WRD2 0x0E
#define APU_WRD3 0x0F
#define APU_WRE0 0x10
#define APU_WRE1 0x11
#define APU_WRE2 0x12
#define APU_WRE3 0x13
#define APU_SMASK 0x15
#define APU_IRQCTRL 0x17
static const int dpcm_clocks[16] = {428, 380, 340, 320, 286, 254, 226, 214,
190, 160, 142, 128, 106, 85, 72, 54};
#define AUDF1_C 0x00
#define AUDC1_C 0x01
#define AUDF2_C 0x02
#define AUDC2_C 0x03
#define AUDF3_C 0x04
#define AUDC3_C 0x05
#define AUDF4_C 0x06
#define AUDC4_C 0x07
#define AUDCTL_C 0x08
#define STIMER_C 0x09
#define SKREST_C 0x0A
#define POTGO_C 0x0B
#define SEROUT_C 0x0D
#define IRQEN_C 0x0E
#define SKCTL_C 0x0F
static const int okim6258_dividers[4] = {1024, 768, 512, 512};
static const UINT8 okim6295_voltbl[0x10] =
{ 0x20, 0x16, 0x10, 0x0B, 0x08, 0x06, 0x04, 0x03,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const int multipcm_val2chan[] =
{
0, 1, 2, 3, 4, 5, 6, -1,
7, 8, 9,10,11,12,13, -1,
14,15,16,17,18,19,20, -1,
21,22,23,24,25,26,27, -1,
};
static const char* OPX_SYNC_TYPES[0x04] = {"4op FM", "2x 2op FM", "3op FM + PCM", "PCM"};
static const float OPX_PCM_DBVol[0x10] =
{ 0.0f, 2.5f, 6.0f, 8.5f, 12.0f, 14.5f, 18.1f, 20.6f,
24.1f, 26.6f, 30.1f, 32.6f, 36.1f, 96.1f, 96.1f, 96.1f};
static const char* ES5503_MODES[0x04] = {"Free-Run", "One-Shot", "Sync", "Swap"};
static const char* K054539_SAMPLE_MODES[0x04] = {"8-bit PCM", "16-bit PCM", "4-bit DPCM", "unknown"};
typedef struct ymf278b_chip
{
UINT8 smplH[24]; // high bit of the sample ID
} YMF278B_DATA;
typedef struct ymf271_chip
{
UINT8 group_sync[12];
} YMF271_DATA;
typedef struct okim6295_chip
{
UINT8 Command;
} OKIM6295_DATA;
typedef struct multipcm_chip
{
INT8 Slot;
UINT8 Address;
} MULTIPCM_DATA;
typedef struct upd7759_chip
{
bool HasROM;
} UPD7759_DATA;
typedef struct es5506_chip
{
UINT8 Mode; // 00 = ES5505, 01 - ES5506
union
{
UINT8 d8[4];
UINT32 d32;
} latch;
} ES5506_DATA;
typedef struct wswan_chip
{
bool pcmEnable;
} WSWAN_DATA;
static void opn_write(char* TempStr, UINT8 Mode, UINT8 Port, UINT8 Register,
UINT8 Data);
static void rf5cxx_reg_write(char* TempStr, UINT8 Register, UINT8 Data);
static void opl_write(char* TempStr, UINT8 Mode, UINT8 Port, UINT8 Register,
UINT8 Data);
static void ay8910_part_write(char* TempStr, UINT8 Register, UINT8 Data);
static void ymf271_write_fm_reg(char* TempStr, UINT8 Register, UINT8 Data);
static void ymf271_write_fm(char* TempStr, UINT8 Port, UINT8 Register, UINT8 Data);
static void FM_ADPCMAWrite(char* TempStr, UINT8 Register, UINT8 Data);
static void YM_DELTAT_ADPCM_Write(char* TempStr, UINT8 Register, UINT8 Data);
static void multipcm_WriteSlot(char* TempStr, INT8 Slot, UINT8 Register, UINT8 Data);
static char WriteStr[0x100];
static char RedirectStr[0x100];
static char* ChipStr;
static CHIP_CNT ChpCnt;
static UINT8 ChpCur;
static YMF278B_DATA CacheYMF278B[0x02];
static YMF271_DATA CacheYMF271[0x02];
static OKIM6295_DATA CacheOKI6295[0x02];
static MULTIPCM_DATA CacheMultiPCM[0x02];
static UPD7759_DATA CacheUPD7759[0x02];
static ES5506_DATA CacheES5506[0x02];
static WSWAN_DATA CacheWSwan[0x02];
void InitChips(UINT32 ChipCntSize, UINT32* ChipCounts)
{
memset(&ChpCnt, 0x00, sizeof(CHIP_CNT));
memcpy(&ChpCnt, ChipCounts, sizeof(UINT32) * ChipCntSize);
memset(CacheYMF278B, 0x00, sizeof(YMF278B_DATA) * 0x02);
memset(CacheYMF271, 0x00, sizeof(YMF271_DATA) * 0x02);
memset(CacheOKI6295, 0x00, sizeof(OKIM6295_DATA) * 0x02);
memset(CacheMultiPCM, 0x00, sizeof(MULTIPCM_DATA) * 0x02);
memset(CacheUPD7759, 0x00, sizeof(UPD7759_DATA) * 0x02);
memset(CacheES5506, 0x00, sizeof(ES5506_DATA) * 0x02);
memset(CacheWSwan, 0x00, sizeof(WSWAN_DATA) * 0x02);
CacheOKI6295[0].Command = 0xFF;
CacheOKI6295[1].Command = 0xFF;
ChpCur = 0x00;
ChipStr = RedirectStr + 0xF0;
return;
}
void SetChip(UINT8 ChipID)
{
ChpCur = ChipID;
return;
}
INLINE const char* OnOff(UINT32 Value)
{
return ONOFF_STR[Value ? 0x00 : 0x01];
}
INLINE const char* Enable(UINT32 Value)
{
return ENABLE_STRS[Value ? 0x00 : 0x01];
}
INLINE UINT8 YM2151_Note(UINT8 FNum, UINT8 Block)
{
UINT8 NoteVal;
if (FNum > 0xF)
return 0xFF; // Invalid FNum
if (Block > 0x07)
Block = 0x07;
if (! ((FNum & 0x03) == 0x03))
{
NoteVal = FNum >> 2;
NoteVal = NoteVal * 3 + (FNum & 0x03);
NoteVal = 61 + NoteVal;
}
else
{
NoteVal = 0xFF;
}
if (NoteVal == 0xFF)
return 0xFF;
return NoteVal + (Block - 0x04) * 12;
}
INLINE UINT32 GetChipName(UINT8 ChipType, const char** RetName)
{
const char* ChipName;
UINT32 ChipCnt;
switch(ChipType)
{
case 0x00: // SN76496 / T6W28
if (ChpCnt.SN76496 & 0x80000000)
ChipName = "T6W28";
else
ChipName = "SN76496";
ChipCnt = ChpCnt.SN76496;
break;
case 0x01:
ChipName = "YM2413";
ChipCnt = ChpCnt.YM2413;
break;
case 0x02:
ChipName = "YM2612";
ChipCnt = ChpCnt.YM2612;
break;
case 0x03:
ChipName = "YM2151";
ChipCnt = ChpCnt.YM2151;
break;
case 0x04:
ChipName = "SegaPCM";
ChipCnt = ChpCnt.SegaPCM;
break;
case 0x05:
ChipName = "RF5C68";
ChipCnt = ChpCnt.RF5C68;
break;
case 0x06:
ChipName = "YM2203";
ChipCnt = ChpCnt.YM2203;
break;
case 0x07:
ChipName = "YM2608";
ChipCnt = ChpCnt.YM2608;
break;
case 0x08: // YM2610
ChipName = (ChpCnt.YM2610 & 0x80000000) ? "YM2610B" : "YM2610";
ChipCnt = ChpCnt.YM2610;
break;
case 0x09:
ChipName = "YM3812";
ChipCnt = ChpCnt.YM3812;
break;
case 0x0A:
ChipName = "YM3526";
ChipCnt = ChpCnt.YM3526;
break;
case 0x0B:
ChipName = "Y8950";
ChipCnt = ChpCnt.Y8950;
break;
case 0x0C:
ChipName = "YMF262";
ChipCnt = ChpCnt.YMF262;
break;
case 0x0D:
ChipName = "YMF278B";
ChipCnt = ChpCnt.YMF278B;
break;
case 0x0E:
ChipName = "YMF271";
ChipCnt = ChpCnt.YMF271;
break;
case 0x0F:
ChipName = "YMZ280B";
ChipCnt = ChpCnt.YMZ280B;
break;
case 0x10:
ChipName = "RF5C164";
ChipCnt = ChpCnt.RF5C164;
break;
case 0x11:
ChipName = "PWM";
ChipCnt = ChpCnt.PWM;
break;
case 0x12:
ChipName = "AY8910";
ChipCnt = ChpCnt.AY8910;
break;
case 0x13:
ChipName = "GB DMG";
ChipCnt = ChpCnt.GBDMG;
break;
case 0x14:
ChipName = "NES APU";
ChipCnt = ChpCnt.NESAPU;
break;
case 0x15:
ChipName = "MultiPCM";
ChipCnt = ChpCnt.MultiPCM;
break;
case 0x16:
ChipName = "UPD7759";
ChipCnt = ChpCnt.UPD7759;
break;
case 0x17:
ChipName = "OKIM6258";
ChipCnt = ChpCnt.OKIM6258;
break;
case 0x18:
ChipName = "OKIM6295";
ChipCnt = ChpCnt.OKIM6295;
break;
case 0x19:
ChipName = "K051649";
ChipCnt = ChpCnt.K051649;
break;
case 0x1A:
ChipName = "K054539";
ChipCnt = ChpCnt.K054539;
break;
case 0x1B:
ChipName = "HuC6280";
ChipCnt = ChpCnt.HuC6280;
break;
case 0x1C:
ChipName = "C140";
ChipCnt = ChpCnt.C140;
break;
case 0x1D:
ChipName = "K053260";
ChipCnt = ChpCnt.K053260;
break;
case 0x1E:
ChipName = "Pokey";
ChipCnt = ChpCnt.Pokey;
break;
case 0x1F:
ChipName = "QSound";
ChipCnt = ChpCnt.QSound;
break;
case 0x20:
ChipName = "SCSP";
ChipCnt = ChpCnt.SCSP;
break;
case 0x21:
ChipName = "WSwan";
ChipCnt = ChpCnt.WSwan;
break;
case 0x22:
ChipName = "VSU";
ChipCnt = ChpCnt.VSU;
break;
case 0x23:
ChipName = "SAA1099";
ChipCnt = ChpCnt.SAA1099;
break;
case 0x24:
ChipName = "ES5503";
ChipCnt = ChpCnt.ES5503;
break;
case 0x25:
ChipName = "ES5506";
ChipCnt = ChpCnt.ES5506;
break;
case 0x26:
ChipName = "X1-010";
ChipCnt = ChpCnt.X1_010;
break;
case 0x27:
ChipName = "C352";
ChipCnt = ChpCnt.C352;
break;
case 0x28:
ChipName = "GA20";
ChipCnt = ChpCnt.GA20;
break;
case 0x29:
ChipName = "Mikey";
ChipCnt = ChpCnt.Mikey;
break;
default:
ChipName = "Unknown";
ChipCnt = 0x00;
break;
}
*RetName = ChipName;
return ChipCnt;
}
INLINE void WriteChipID(UINT8 ChipType)
{
const char* ChipName;
UINT32 ChipCnt;
UINT32 NameLen;
ChipCnt = GetChipName(ChipType, &ChipName);
switch(ChipType)
{
case 0x00: // SN76496/T6W28
if (ChpCnt.SN76496 & 0x80000000)
{
sprintf(ChipStr, "%s %s:\t", ChipName, T6W28_PORT[ChpCur]);
return;
}
break;
}
ChipCnt &= ~0x80000000;
if (ChipCnt <= 0x01)
NameLen = sprintf(ChipStr, "%s:", ChipName);
else
NameLen = sprintf(ChipStr, "%s #%u:", ChipName, ChpCur);
if (NameLen < 8)
NameLen += sprintf(&ChipStr[NameLen], "%*s", 8 - NameLen, "");
strcat(ChipStr, "\t");
return;
}
void GetFullChipName(char* TempStr, UINT8 ChipType)
{
const char* ChipName;
UINT32 ChipCnt;
UINT8 CurChip;
CurChip = ChpCur | (ChipType >> 7);
ChipType &= 0x7F;
ChipCnt = GetChipName(ChipType, &ChipName);
switch(ChipType)
{
case 0x00: // SN76496/T6W28
if (ChpCnt.SN76496 & 0x80000000)
{
ChipCnt = 0x01;
}
break;
}
ChipCnt &= ~0x80000000;
if (ChipCnt <= 0x01)
sprintf(TempStr, "%s:", ChipName);
else
sprintf(TempStr, "%s #%u:", ChipName, CurChip);
return;
}
static UINT8 GetLogVolPercent(UINT8 VolLevel, UINT8 Steps_6db, UINT8 Silent)
{
float TempVol;
if (VolLevel >= Silent)
return 0;
TempVol = (float)pow(2.0, -1.0 * VolLevel / Steps_6db);
return (UINT8)(100 * TempVol + 0.5f);
}
static UINT8 GetDBTblPercent(UINT8 VolLevel, const float* DBTable, UINT8 Silent)
{
float TempVol;
if (VolLevel >= Silent)
return 0;
TempVol = (float)pow(2.0, -DBTable[VolLevel] / 6.0f);
return (UINT8)(100 * TempVol + 0.5f);
}
void GGStereo(char* TempStr, UINT8 Data)
{
const char CH_CHARS[4] = {'0', '1', '2', 'N'};
UINT8 CurChn;
UINT32 StrPos;
UINT8 ChnEn;
// Format:
// Bit 76543210
// L/R LLLLRRRR
// Ch 32103210
WriteChipID(0x00);
sprintf(TempStr, "%sGG Stereo: ", ChipStr);
StrPos = strlen(TempStr);
for (CurChn = 0x00; CurChn < 0x08; CurChn ++)
{
ChnEn = Data & (0x01 << (CurChn ^ 0x04));
TempStr[StrPos] = ChnEn ? CH_CHARS[CurChn & 0x03] : '-';
StrPos ++;
}
TempStr[StrPos] = 0x00;
return;
}
void sn76496_write(char* TempStr, UINT8 Command)
{
UINT8 CurChn;
UINT8 CurData;
WriteChipID(0x00);
if (! (Command & 0x80))
{
CurData = Command & 0x7F;
sprintf(TempStr, "%sData: %02X", ChipStr, CurData);
}
else
{
CurChn = (Command & 0x60) >> 5;
CurData = Command & 0x0F;
switch(Command & 0xF0)
{
case 0x80:
case 0xA0:
case 0xC0:
sprintf(TempStr, "%sLatch/Data: Tone Ch %u -> 0x%03X", ChipStr, CurChn, CurData);
break;
case 0xE0:
sprintf(WriteStr, "%s, %s", SN76496_NOISE_TYPE[(Command & 0x04) >> 2],
SN76496_NOISE_FREQ[Command & 0x03]);
sprintf(TempStr, "%sNoise Type: %u - %s", ChipStr, CurData, WriteStr);
break;
case 0x90:
case 0xB0:
case 0xD0:
case 0xF0:
sprintf(TempStr, "%sLatch/Data: Volume Ch %u -> 0x%01X = %u%%",
ChipStr, CurChn, CurData, GetLogVolPercent(CurData & 0x0F, 0x03, 0x0F));
break;
}
}
return;
}
void ym2413_write(char* TempStr, UINT8 Register, UINT8 Data)
{
WriteChipID(0x01);
sprintf(TempStr, "%sReg 0x%02X Data 0x%02X", ChipStr, Register, Data);
return;
}
static void opn_write(char* TempStr, UINT8 Mode, UINT8 Port, UINT8 Register,
UINT8 Data)
{
UINT16 RegVal;
UINT8 Channel;
UINT8 Slot;
float TempSng;
UINT8 TempByt;
RegVal = (Port << 8) | Register;
if ((RegVal & 0x1F0) == 0x000 && (FMOPN_TYPES[Mode] & OPN_TYPE_SSG))
{
ay8910_part_write(WriteStr, Register, Data);
sprintf(TempStr, "SSG: %s", WriteStr);
}
else if ((RegVal & 0x1F0) == 0x020)
{
// write a OPN mode register 0x20-0x2F
switch(Register)
{
case 0x21: // Test
sprintf(TempStr, "Test Register");
break;
case 0x22: // LFO FREQ (YM2608/YM2610/YM2610B/YM2612)
if (! (FMOPN_TYPES[Mode] & OPN_TYPE_LFOPAN))
goto WriteRegData;
if (Data & 0x08) // LFO enabled ?
sprintf(TempStr, "Low Frequency Oscillator: %s Hz",
OPN_LFOFreqs[Data & 0x07]);
else
sprintf(TempStr, "Low Frequency Oscillator: Disable");
break;
case 0x24: // timer A High 8
sprintf(TempStr, "Timer A MSB: %02X", Data);
break;
case 0x25: // timer A Low 2
sprintf(TempStr, "Timer A LSB: %02X", Data & 0x03);
break;
case 0x26: // timer B
sprintf(TempStr, "Timer B: %02X", Data);
break;
case 0x27: // mode, timer control
sprintf(TempStr, "CSM Mode: %s", Enable(Data & 0x80));
sprintf(TempStr, "%s, 3 Slot Mode: %s", TempStr, Enable(Data & 0x40));
sprintf(TempStr, "%s, Enable Timer: %c%c, Timer IRQ Enable: %c%c, Reset Timer Status: %c%c",
TempStr,
(Data & 0x01) ? 'A' : '-', (Data & 0x02) ? 'B' : '-',
(Data & 0x04) ? 'A' : '-', (Data & 0x08) ? 'B' : '-',
(Data & 0x10) ? 'A' : '-', (Data & 0x20) ? 'B' : '-');
break;
case 0x28: // key on / off
Channel = Data & 0x03;
if (Channel == 0x03)
{
sprintf(TempStr, "Key On/Off: Invalid Channel");
break;
}
if ((Data & 0x04) && (FMOPN_TYPES[Mode] & OPN_TYPE_6CH))
Channel += 3;
sprintf(TempStr, "Channel %u Key On/Off: ", Channel);
sprintf(TempStr, "%sSlot1 %s, Slot2 %s, Slot3 %s, Slot4 %s", TempStr,
OnOff(Data & 0x10), OnOff(Data & 0x20), OnOff(Data & 0x40),
OnOff(Data & 0x80));
break;
case 0x29: // SCH,xx,xxx,EN_ZERO,EN_BRDY,EN_EOS,EN_TB,EN_TA
if (Mode != OPN_YM2608)
goto WriteRegData;
sprintf(TempStr, "%s Mode (%u FM channels), IRQ Mask: 0x%02X",
(Data & 0x80) ? "OPNA" : "OPN", (Data & 0x80) ? 6 : 3, Data & 0x1F);
break;
case 0x2A: // DAC data (YM2612)
if (! (FMOPN_TYPES[Mode] & OPN_TYPE_DAC))
goto WriteRegData;
sprintf(TempStr, "DAC = %02X", Data);
break;
case 0x2B: // DAC Sel (YM2612)
if (! (FMOPN_TYPES[Mode] & OPN_TYPE_DAC))
goto WriteRegData;
// b7 = dac enable
sprintf(TempStr, "DAC %s", Enable(Data & 0x80));
break;
case 0x2C: // DAC Test Register (YM2612)
if (! (FMOPN_TYPES[Mode] & OPN_TYPE_DAC))
goto WriteRegData;
sprintf(TempStr, "DAC Test Register: Special DAC Mode %s", Enable(Data & 0x20));
break;
default:
goto WriteRegData;
}
}
else if (Register >= 0x30)
{
Channel = (Register & 0x03);
if (Channel == 0x03) // 0xX3,0xX7,0xXB,0xXF
{
sprintf(TempStr, "Invalid Channel");
return;
}
if (Port)
Channel += 3;
Slot = (Register & 0x0C) >> 2;
switch(Register & 0xF0)
{
case 0x30: // DET , MUL
sprintf(WriteStr, "Detune: %u", (Data & 0x70) >> 4);
if (Data & 0x0F)
TempSng = (float)(Data & 0x0F);
else
TempSng = 0.5f;
sprintf(WriteStr, "%s, Multiple: Freq * %.1f", WriteStr, TempSng);
break;
case 0x40: // TL
sprintf(WriteStr, "Total Level: 0x%02X = %u%%",
Data & 0x7F, GetLogVolPercent(Data & 0x7F, 0x08, 0xFF));
break;
case 0x50: // KS, AR
sprintf(WriteStr, "Attack Rate: %02X, Key Scale: 1 / %01X",
(Data & 0x1F) >> 0, (~Data & 0xC0) >> 6);
break;
case 0x60: // bit7 = AM ENABLE, DR
if (FMOPN_TYPES[Mode] & OPN_TYPE_LFOPAN)
sprintf(WriteStr, "Amplitude Modulation: %s, ", Enable(Data & 0x80));
else
strcpy(WriteStr, "");
sprintf(WriteStr, "%sDecay Rate: %02X", WriteStr,
Data & 0x1F);
break;
case 0x70: // SR
sprintf(WriteStr, "Sustain Rate: %02X",
Data & 0x1F);
break;
case 0x80: // SL, RR
sprintf(WriteStr, "Sustain Level: %01X, Release Rate: %01X",
(Data & 0xF0) >> 4, (Data & 0x0F) >> 0);
break;
case 0x90: // SSG-EG
//SLOT->ssg = v&0x0f;
//SLOT->ssgn = (v&0x04)>>1; // bit 1 in ssgn = attack
sprintf(WriteStr, "SSG-EG Flags: Envelope %s, Attack %s, Alternate %s, Hold %s",
OnOff(Data & 0x08), OnOff(Data & 0x04), OnOff(Data & 0x02),
OnOff(Data & 0x01));
break;
case 0xA0:
switch(Register & 0x0C)
{
case 0x00: // 0xa0-0xa2 : FNUM1
/*{
UINT32 fn = (((UINT32)( (OPN->ST.fn_h)&7))<<8) + v;
UINT8 blk = OPN->ST.fn_h>>3;
// keyscale code
CH->kcode = (blk<<2) | opn_fktable[fn >> 7];
// phase increment counter
CH->fc = OPN->fn_table[fn*2]>>(7-blk);
// store fnum in clear form for LFO PM calculations
CH->block_fnum = (blk<<11) | fn;
}*/
sprintf(WriteStr, "F-Num (set) LSB = %02X", Data);
break;
case 0x04: // 0xa4-0xa6 : FNUM2,BLK
//OPN->ST.fn_h = v&0x3f;
sprintf(WriteStr, "F-Num (prepare) MSB = %01X, Octave %u", Data & 0x07,
(Data & 0x38) >> 3);
break;
case 0x08: // 0xa8-0xaa : 3CH FNUM1
if (Port)
goto WriteRegData;
/*UINT32 fn = (((UINT32)(OPN->SL3.fn_h&7))<<8) + v;
UINT8 blk = OPN->SL3.fn_h>>3;
// keyscale code
OPN->SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
// phase increment counter
OPN->SL3.fc[c] = OPN->fn_table[fn*2]>>(7-blk);
OPN->SL3.block_fnum[c] = (blk<<11) | fn;
(OPN->P_CH)[2].SLOT[SLOT1].Incr=-1;*/
sprintf(WriteStr, "F-Num Op %u (set) LSB = %02X", Channel, Data);
Channel = 2;
break;
case 0x0C: // 0xac-0xae : 3CH FNUM2,BLK
if (Port)
goto WriteRegData;
//OPN->SL3.fn_h = v&0x3f;
sprintf(WriteStr, "F-Num Op %u (prepare) MSB = %01X, Octave %u", Channel,
Data & 0x07, (Data & 0x38) >> 3);
Channel = 2;
break;
}
break;
case 0xB0:
switch(Register & 0x0C)
{
case 0x00: // 0xb0-0xb2 : FB,ALGO
TempByt = (Data & 0x38) >> 3;
if (TempByt == 0)
strcpy(TempStr, "none");
else if (TempByt < 5) // 1 = PI/16, 4 = PI/2
sprintf(TempStr, "PI / %u", 32 >> TempByt);
else
sprintf(TempStr, "%u x PI", 1 << (TempByt - 5));
sprintf(WriteStr, "Feedback: %s, Algorithm: %u", TempStr, Data & 0x07);
break;
case 0x04: // 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608)
if (! (FMOPN_TYPES[Mode] & OPN_TYPE_LFOPAN))
goto WriteRegData;
// b0-2 PMS
//CH->pms = (v & 7) * 32; // CH->pms = PM depth * 32 (index in lfo_pm_table)
// b4-5 AMS
//CH->ams = lfo_ams_depth_shift[(v>>4) & 0x03];
// PAN : b7 = L, b6 = R
/*OPN->pan[ c*2 ] = (v & 0x80) ? ~0 : 0;
OPN->pan[ c*2+1 ] = (v & 0x40) ? ~0 : 0;*/
sprintf(WriteStr, "PMS: 0x%01X, AMS: 0x%01X, Stereo: %c%c", Data & 0x07,
(Data & 0x30) >> 4, (Data & 0x80) ? 'L' : '-',
(Data & 0x40) ? 'R' : '-');
break;
default:
goto WriteRegData;
}
break;
default:
goto WriteRegData;
}
if (Register < 0xA0)
sprintf(TempStr, "Ch %u Slot %u %s", Channel, Slot, WriteStr);
else
sprintf(TempStr, "Ch %u %s", Channel, WriteStr);
}
else if (FMOPN_TYPES[Mode] & OPN_TYPE_ADPCM)
{
if (FMOPN_TYPES[Mode] & OPN_TYPE_2610)
{
// YM2610 Mode
if ((RegVal & 0x1F0) == 0x010)
{
if (RegVal >= 0x1C)
goto WriteRegData;
YM_DELTAT_ADPCM_Write(TempStr, Register & 0x0F, Data);
}
else if ((RegVal & 0x1F0) >= 0x100 && (RegVal & 0x1F0) < 0x130)
{
FM_ADPCMAWrite(TempStr, Register, Data);
}
else
{
goto WriteRegData;
}
}
else
{
// YM2608 Mode
if ((RegVal & 0x1F0) == 0x010)
{
FM_ADPCMAWrite(TempStr, Register & 0x0F, Data);
}
else if ((RegVal & 0x1F0) == 0x100)
{
YM_DELTAT_ADPCM_Write(TempStr, Register & 0x0F, Data);
}
else
{
goto WriteRegData;
}
}
}
else
{
goto WriteRegData;
}
return;
WriteRegData:
if (! (FMOPN_TYPES[Mode] & OPN_TYPE_6CH) || ! Port)
sprintf(TempStr, "Reg 0x%02X Data 0x%02X", Register, Data);
else
sprintf(TempStr, "Reg 0x%01X%02X Data 0x%02X", Port, Register, Data);
return;
}
void ym2612_write(char* TempStr, UINT8 Port, UINT8 Register, UINT8 Data)
{
WriteChipID(0x02);
opn_write(RedirectStr, OPN_YM2612, Port, Register, Data);
sprintf(TempStr, "%s%s", ChipStr, RedirectStr);
return;
}
void ym2151_write(char* TempStr, UINT8 Register, UINT8 Data)
{
UINT8 Channel;
UINT8 Operator;
WriteChipID(0x03);
//sprintf(TempStr, "%sReg 0x%02X Data 0x%02X", ChipStr, Register, Data);
if (Register < 0x20)
{
switch(Register)
{
case 0x01: // LFO reset(bit 1), Test Register (other bits)