2 Skelton for retropc emulator
4 Origin : Neko Project 2
5 Author : Takeda.Toshiya
14 static const uint16 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
27 datareg = maskreg = 0;
28 memset(ch, 0, sizeof(ch));
33 void TMS3631::write_signal(int id, uint32 data, uint32 mask)
35 if(id == SIG_TMS3631_ENVELOP1) {
36 envelop1 = (envelop1 & ~mask) | (data & mask);
37 } else if(id == SIG_TMS3631_ENVELOP2) {
38 envelop2 = (envelop2 & ~mask) | (data & mask);
39 } else if(id == SIG_TMS3631_DATAREG) {
41 data = (datareg & ~mask) | (data & mask);
43 if(!(datareg & 0x80)) {
47 ch[channel].freq = freq_table[data & 0x3f];
49 } else if(!(data & 0x40) && (datareg & 0x40)) {
51 channel = (channel + 1) & 7;
55 } else if(id == SIG_TMS3631_MASKREG) {
56 maskreg = (maskreg & ~mask) | (data & mask);
60 void TMS3631::mix(int32* buffer, int cnt)
63 for(int i = 0; i < cnt; i++) {
65 for(int j = 0; j < 2; j++) {
66 if((maskreg & (1 << j)) && ch[j].freq != 0) {
67 for(int k = 0; k < 4; k++) {
68 ch[j].count += ch[j].freq;
69 data += (ch[j].count & 0x10000) ? 1 : -1;
73 int vol_l = data * vol;
74 int vol_r = data * vol;
75 for(int j = 2; j < 5; j++) {
76 if((maskreg & (1 << j)) && ch[j].freq != 0) {
77 for(int k = 0; k < 4; k++) {
78 ch[j].count += ch[j].freq;
79 vol_l += feet[(ch[j].count >> 16) & 15];
83 for(int j = 5; j < 8; j++) {
84 if((maskreg & (1 << j)) && ch[j].freq != 0) {
85 for(int k = 0; k < 4; k++) {
86 ch[j].count += ch[j].freq;
87 vol_r += feet[(ch[j].count >> 16) & 15];
91 *buffer++ += apply_volume(vol_l, volume_l); // L
92 *buffer++ += apply_volume(vol_r, volume_r); // R
96 void TMS3631::set_volume(int ch, int decibel_l, int decibel_r)
98 volume_l = decibel_to_volume(decibel_l);
99 volume_r = decibel_to_volume(decibel_r);
102 void TMS3631::init(int rate, int volume)
105 for(int i = 0; i < 64; i++) {
106 freq_table[i] = (uint32)((double)np2_freq_table[i] * 11025.0 / (double)rate / 2.0 + 0.5);
108 for(int i = 0; i < 16; i++) {
110 for(int j = 0; j < 4; j++) {
111 data += (volume / 8) * ((i & (1 << j)) ? 1 : -1);
118 #define STATE_VERSION 1
120 void TMS3631::save_state(FILEIO* state_fio)
122 state_fio->FputUint32(STATE_VERSION);
123 state_fio->FputInt32(this_device_id);
125 state_fio->FputUint8(envelop1);
126 state_fio->FputUint8(envelop2);
127 state_fio->FputUint8(datareg);
128 state_fio->FputUint8(maskreg);
129 state_fio->Fwrite(ch, sizeof(ch), 1);
130 state_fio->FputUint8(channel);
131 state_fio->FputBool(set_key);
134 bool TMS3631::load_state(FILEIO* state_fio)
136 if(state_fio->FgetUint32() != STATE_VERSION) {
139 if(state_fio->FgetInt32() != this_device_id) {
142 envelop1 = state_fio->FgetUint8();
143 envelop2 = state_fio->FgetUint8();
144 datareg = state_fio->FgetUint8();
145 maskreg = state_fio->FgetUint8();
146 state_fio->Fread(ch, sizeof(ch), 1);
147 channel = state_fio->FgetUint8();
148 set_key = state_fio->FgetBool();