OSDN Git Service

[VM][WIP] Apply some devices merging upstream 2018-10-05.This still not build.WIP.
[csp-qt/common_source_project-fm7.git] / source / src / vm / tms3631.cpp
1 /*
2         Skelton for retropc emulator
3
4         Origin : Neko Project 2
5         Author : Takeda.Toshiya
6         Date   : 2015.09.29-
7
8         [ TMS3631 ]
9 */
10
11 #include "tms3631.h"
12
13 // from tms3631c.c
14 static const uint16_t np2_freq_table[] = {
15         0,      0x051B, 0x0569, 0x05BB, 0x0613, 0x066F, 0x06D1,
16                 0x0739, 0x07A7, 0x081B, 0x0897, 0x091A, 0x09A4, 0,0,0,
17         0,      0x0A37, 0x0AD3, 0x0B77, 0x0C26, 0x0CDF, 0x0DA3,
18                 0x0E72, 0x0F4E, 0x1037, 0x112E, 0x1234, 0x1349, 0,0,0,
19         0,      0x146E, 0x15A6, 0x16EF, 0x184C, 0x19BE, 0x1B46,
20                 0x1CE5, 0x1E9D, 0x206F, 0x225D, 0x2468, 0x2692, 0,0,0,
21         0,      0x28DD, 0x2B4C, 0x2DDF, 0x3099, 0x337D, 0x368D,
22                 0x39CB, 0x3D3B, 0x40DF, 0x44BA, 0x48D1, 0x4D25, 0x51BB, 0,0
23 };
24
25 void TMS3631::reset()
26 {
27         datareg = maskreg = 0;
28         memset(ch, 0, sizeof(ch));
29         channel = 0;
30         set_key = false;
31 }
32
33 void TMS3631::write_signal(int id, uint32_t data, uint32_t mask)
34 {
35         if(id == SIG_TMS3631_ENVELOP1) {
36                 touch_sound();
37                 envelop1 = (envelop1 & ~mask) | (data & mask);
38         } else if(id == SIG_TMS3631_ENVELOP2) {
39                 touch_sound();
40                 envelop2 = (envelop2 & ~mask) | (data & mask);
41         } else if(id == SIG_TMS3631_DATAREG) {
42                 // from board14.c
43                 touch_sound();
44                 data = (datareg & ~mask) | (data & mask);
45                 if(data & 0x80) {
46                         if(!(datareg & 0x80)) {
47                                 set_key = true;
48                                 channel = 0;
49                         } else if(set_key) {
50                                 ch[channel].freq = freq_table[data & 0x3f];
51                                 set_key = false;
52                         } else if(!(data & 0x40) && (datareg & 0x40)) {
53                                 set_key = true;
54                                 channel = (channel + 1) & 7;
55                         }
56                 }
57                 datareg = data;
58         } else if(id == SIG_TMS3631_MASKREG) {
59                 touch_sound();
60                 maskreg = (maskreg & ~mask) | (data & mask);
61         }
62 }
63
64 void TMS3631::mix(int32_t* buffer, int cnt)
65 {
66         // from tms3631g.c
67         for(int i = 0; i < cnt; i++) {
68                 int data = 0;
69                 for(int j = 0; j < 2; j++) {
70                         if((maskreg & (1 << j)) && ch[j].freq != 0) {
71                                 for(int k = 0; k < 4; k++) {
72                                         ch[j].count += ch[j].freq;
73                                         data += (ch[j].count & 0x10000) ? 1 : -1;
74                                 }
75                         }
76                 }
77                 int vol_l = data * vol;
78                 int vol_r = data * vol;
79                 for(int j = 2; j < 5; j++) {
80                         if((maskreg & (1 << j)) && ch[j].freq != 0) {
81                                 for(int k = 0; k < 4; k++) {
82                                         ch[j].count += ch[j].freq;
83                                         vol_l += feet[(ch[j].count >> 16) & 15];
84                                 }
85                         }
86                 }
87                 for(int j = 5; j < 8; j++) {
88                         if((maskreg & (1 << j)) && ch[j].freq != 0) {
89                                 for(int k = 0; k < 4; k++) {
90                                         ch[j].count += ch[j].freq;
91                                         vol_r += feet[(ch[j].count >> 16) & 15];
92                                 }
93                         }
94                 }
95                 *buffer++ += apply_volume(vol_l, volume_l); // L
96                 *buffer++ += apply_volume(vol_r, volume_r); // R
97         }
98 }
99
100 void TMS3631::set_volume(int ch, int decibel_l, int decibel_r)
101 {
102         volume_l = decibel_to_volume(decibel_l);
103         volume_r = decibel_to_volume(decibel_r);
104 }
105
106 void TMS3631::initialize_sound(int rate, int volume)
107 {
108         // from tms3631c.c
109         for(int i = 0; i < 64; i++) {
110                 freq_table[i] = (uint32_t)((double)np2_freq_table[i] * 11025.0 / (double)rate / 2.0 + 0.5);
111         }
112         for(int i = 0; i < 16; i++) {
113                 int data = 0;
114                 for(int j = 0; j < 4; j++) {
115                         data += (volume / 8) * ((i & (1 << j)) ? 1 : -1);
116                 }
117                 feet[i] = data;
118         }
119         vol = volume / 8;
120 }
121
122 #define STATE_VERSION   1
123
124 bool TMS3631::process_state(FILEIO* state_fio, bool loading)
125 {
126         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
127                 return false;
128         }
129         if(!state_fio->StateCheckInt32(this_device_id)) {
130                 return false;
131         }
132         state_fio->StateUint8(envelop1);
133         state_fio->StateUint8(envelop2);
134         state_fio->StateUint8(datareg);
135         state_fio->StateUint8(maskreg);
136 //      state_fio->StateBuffer(ch, sizeof(ch), 1);
137         for(int i = 0; i < 8; i++) {
138                 state_fio->StateUint32(ch[i].freq);
139                 state_fio->StateUint32(ch[i].count);
140         }
141
142         state_fio->StateUint8(channel);
143         state_fio->StateBool(set_key);
144         return true;
145 }