2 Skelton for retropc emulator
\r
4 Author : Takeda.Toshiya
\r
10 #include "sn76489an.h"
\r
14 #define NOISE_FB 0x4000
\r
15 #define NOISE_DST_TAP 1
\r
16 #define NOISE_SRC_TAP 2
\r
18 // SN76489A, SN76496
\r
19 #define NOISE_FB 0x10000
\r
20 #define NOISE_DST_TAP 4
\r
21 #define NOISE_SRC_TAP 8
\r
23 #define NOISE_MODE ((regs[6] & 4) ? 1 : 0)
\r
25 void SN76489AN::initialize()
\r
31 void SN76489AN::reset()
\r
33 for(int i = 0; i < 4; i++) {
\r
37 ch[i].signal = false;
\r
39 for(int i = 0; i < 8; i += 2) {
\r
41 regs[i + 1] = 0x0f; // volume = 0
\r
43 noise_gen = NOISE_FB;
\r
44 ch[3].signal = false;
\r
47 void SN76489AN::write_io8(uint32 addr, uint32 data)
\r
50 index = (data >> 4) & 7;
\r
54 case 0: case 2: case 4:
\r
56 regs[index] = (regs[index] & 0x3f0) | (data & 0x0f);
\r
57 ch[c].period = regs[index] ? regs[index] : 0x400;
\r
60 case 1: case 3: case 5: case 7:
\r
61 // tone / noise : volume
\r
62 regs[index] = data & 0x0f;
\r
63 ch[c].volume = volume_table[data & 0x0f];
\r
66 // noise : frequency, mode
\r
69 ch[3].period = (data == 3) ? (ch[2].period << 1) : (1 << (data + 5));
\r
71 noise_gen = NOISE_FB;
\r
72 ch[3].signal = false;
\r
78 switch(index & 0x07) {
\r
79 case 0: case 2: case 4:
\r
81 regs[index] = (regs[index] & 0x0f) | (((uint16)data << 4) & 0x3f0);
\r
82 ch[c].period = regs[index] ? regs[index] : 0x400;
\r
84 // update noise shift frequency
\r
85 if(index == 4 && (regs[6] & 3) == 3) {
\r
86 ch[3].period = ch[2].period << 1;
\r
93 void SN76489AN::write_signal(int id, uint32 data, uint32 mask)
\r
95 if(id == SIG_SN76489AN_MUTE) {
\r
96 mute = ((data & mask) != 0);
\r
97 } else if(id == SIG_SN76489AN_DATA) {
\r
99 } else if(id == SIG_SN76489AN_CS) {
\r
100 bool next = ((data & mask) != 0);
\r
102 if(!(cs = next) && !we) {
\r
106 } else if(id == SIG_SN76489AN_CS) {
\r
107 bool next = ((data & mask) != 0);
\r
114 } else if(id == SIG_SN76489AN_WE) {
\r
115 bool next = ((data & mask) != 0);
\r
125 void SN76489AN::mix(int32* buffer, int cnt)
\r
130 for(int i = 0; i < cnt; i++) {
\r
132 for(int j = 0; j < 4; j++) {
\r
133 if(!ch[j].volume) {
\r
136 ch[j].count -= diff;
\r
137 if(ch[j].count < 0) {
\r
138 ch[j].count += ch[j].period << 8;
\r
140 if(((noise_gen & NOISE_DST_TAP) ? 1 : 0) ^ (((noise_gen & NOISE_SRC_TAP) ? 1 : 0) * NOISE_MODE)) {
\r
142 noise_gen |= NOISE_FB;
\r
146 ch[3].signal = ((noise_gen & 1) != 0);
\r
148 ch[j].signal = !ch[j].signal;
\r
151 vol += ch[j].signal ? ch[j].volume : -ch[j].volume;
\r
153 *buffer++ += vol; // L
\r
154 *buffer++ += vol; // R
\r
158 void SN76489AN::init(int rate, int clock, int volume)
\r
161 double vol = volume;
\r
162 for(int i = 0; i < 15; i++) {
\r
163 volume_table[i] = (int)vol;
\r
164 vol /= 1.258925412;
\r
166 volume_table[15] = 0;
\r
167 diff = 16 * clock / rate;
\r