comparison ym2612.c @ 362:b7c3facee762

YM2612 WIP update
author Mike Pavone <pavone@retrodev.com>
date Mon, 27 May 2013 22:19:11 -0700
parents cc39629e8d06
children 62177cc39049
comparison
equal deleted inserted replaced
361:946ae3749260 362:b7c3facee762
4 #include "ym2612.h" 4 #include "ym2612.h"
5 5
6 #define BUSY_CYCLES 17 6 #define BUSY_CYCLES 17
7 #define TIMERA_UPDATE_PERIOD 144 7 #define TIMERA_UPDATE_PERIOD 144
8 8
9 #define REG_TIMERA_HIGH 0x03 // 0x24 9 enum {
10 #define REG_TIMERA_LOW 0x04 // 0x25 10 REG_TIMERA_HIGH = 0x24,
11 #define REG_TIMERB 0x05 // 0x26 11 REG_TIMERA_LOW,
12 #define REG_TIME_CTRL 0x06 // 0x27 12 REG_TIMERB,
13 #define REG_DAC 0x0A // 0x2A 13 REG_TIME_CTRL,
14 #define REG_DAC_ENABLE 0x0B // 0x2B 14 REG_KEY_ONOFF,
15 15 REG_DAC = 0x2A,
16 //offset to add to "shared" regs when looking for them in Part I 16 REG_DAC_ENABLE,
17 #define REG_SHARED 0x10 17
18 18 REG_DETUNE_MULT = 0x30,
19 19 REG_TOTAL_LEVEL = 0x40,
20 #define REG_ALG_FEEDBACK (0xB0-0x30) 20 REG_ATTACK_KS = 0x50,
21 #define REG_ATTACK_KS (0x50-0x30) 21 REG_DECAY_AM = 0x60,
22 #define REG_DECAY_AM (0x60-0x30) 22 REG_SUSTAIN_RATE = 0x70,
23 #define REG_SUSTAIN_RATE (0x70-0x30) 23 REG_S_LVL_R_RATE = 0x80,
24 24
25 REG_FNUM_LOW = 0xA0,
26 REG_BLOCK_FNUM_H = 0xA4,
27 REG_FNUM_LOW_CH3 = 0xA8,
28 REG_BLOCK_FN_CH3 = 0xAC,
29 REG_ALG_FEEDBACK = 0xB0,
30 REG_LR_AMS_PMS = 0xB4
31 };
25 32
26 #define BIT_TIMERA_ENABLE 0x1 33 #define BIT_TIMERA_ENABLE 0x1
27 #define BIT_TIMERB_ENABLE 0x2 34 #define BIT_TIMERB_ENABLE 0x2
28 #define BIT_TIMERA_OVEREN 0x4 35 #define BIT_TIMERA_OVEREN 0x4
29 #define BIT_TIMERB_OVEREN 0x8 36 #define BIT_TIMERB_OVEREN 0x8
50 //According to Nemesis, real hardware only uses a 256 entry table for the fractional part 57 //According to Nemesis, real hardware only uses a 256 entry table for the fractional part
51 //and uses the whole part as a shift amount. 58 //and uses the whole part as a shift amount.
52 #define POW_TABLE_SIZE (1 << 13) 59 #define POW_TABLE_SIZE (1 << 13)
53 uint16_t pow_table[POW_TABLE_SIZE]; 60 uint16_t pow_table[POW_TABLE_SIZE];
54 61
62 uint16_t rate_table_base[] = {
63 //main portion
64 0,1,0,1,0,1,0,1,
65 0,1,0,1,1,1,0,1,
66 0,1,1,1,0,1,1,1,
67 0,1,1,1,1,1,1,1,
68 //top end
69 1,1,1,1,1,1,1,1,
70 1,1,1,2,1,1,1,2,
71 1,2,1,2,1,2,1,2,
72 1,2,2,2,1,2,2,2,
73 };
74
75 uint16_t rate_table[64];
76
77 #define MAX_ENVELOPE 0xFFC
78
55 79
56 uint16_t round_fixed_point(double value, int dec_bits) 80 uint16_t round_fixed_point(double value, int dec_bits)
57 { 81 {
58 return value * (1 << dec_bits) + 0.5; 82 return value * (1 << dec_bits) + 0.5;
59 } 83 }
60 84
61 void ym_init(ym2612_context * context) 85 void ym_init(ym2612_context * context)
62 { 86 {
63 memset(context, 0, sizeof(*context)); 87 memset(context, 0, sizeof(*context));
88 for (int i = 0; i < NUM_OPERATORS; i++) {
89 context->operators[i].envelope = MAX_ENVELOPE;
90 context->operators[i].env_phase = PHASE_RELEASE;
91 }
64 if (!did_tbl_init) { 92 if (!did_tbl_init) {
65 //populate sine table 93 //populate sine table
66 for (int32_t i = 0; i < 512; i++) { 94 for (int32_t i = 0; i < 512; i++) {
67 double sine = sin( ((double)(i*2+1) / SINE_TABLE_SIZE) * M_PI_2 ); 95 double sine = sin( ((double)(i*2+1) / SINE_TABLE_SIZE) * M_PI_2 );
68 96
79 } else { 107 } else {
80 tmp >>= shift; 108 tmp >>= shift;
81 } 109 }
82 pow_table[i] = tmp; 110 pow_table[i] = tmp;
83 } 111 }
112 //populate envelope generator rate table, from small base table
113 for (int rate = 0; rate < 64; rate++) {
114 for (int cycle = 0; cycle < 7; cycle++) {
115 uint16_t value;
116 if (rate < 3) {
117 value = 0;
118 } else if (value >= 60) {
119 value = 8;
120 } else if (value < 8) {
121 value = rate_table_base[((rate & 6) == 6 ? 16 : 8) + cycle];
122 } else if (value < 48) {
123 value = rate_table_base[(rate & 0x3) * 8 + cycle];
124 } else {
125 value = rate_table_base[32 + (rate & 0x3) * 8 + cycle] << (rate >> 2);
126 }
127 }
128 }
84 } 129 }
85 } 130 }
86 131
87 void ym_run(ym2612_context * context, uint32_t to_cycle) 132 void ym_run(ym2612_context * context, uint32_t to_cycle)
88 { 133 {
134 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle);
135 //TODO: Fix channel update order OR remap channels in register write
89 for (; context->current_cycle < to_cycle; context->current_cycle += 6) { 136 for (; context->current_cycle < to_cycle; context->current_cycle += 6) {
90 uint32_t update_cyc = context->current_cycle % 144; 137 uint32_t update_cyc = context->current_cycle % 144;
91 //Update timers at beginning of 144 cycle period 138 //Update timers at beginning of 144 cycle period
92 if (!update_cyc && context->part1_regs[REG_TIME_CTRL] & BIT_TIMERA_ENABLE) { 139 if (!update_cyc && context->timer_control & BIT_TIMERA_ENABLE) {
93 if (context->timer_a) { 140 if (context->timer_a) {
94 context->timer_a--; 141 context->timer_a--;
95 } else { 142 } else {
96 if (context->part1_regs[REG_TIME_CTRL] & BIT_TIMERA_OVEREN) { 143 if (context->timer_control & BIT_TIMERA_OVEREN) {
97 context->status |= BIT_STATUS_TIMERA; 144 context->status |= BIT_STATUS_TIMERA;
98 } 145 }
99 context->timer_a = (context->part1_regs[REG_TIMERA_HIGH] << 2) | (context->part1_regs[REG_TIMERA_LOW] & 0x3); 146 context->timer_a = context->timer_a_load;
100 } 147 }
101 if (context->part1_regs[REG_TIME_CTRL] & BIT_TIMERB_ENABLE) { 148 if (context->timer_control & BIT_TIMERB_ENABLE) {
102 uint32_t b_cyc = (context->current_cycle / 144) % 16; 149 uint32_t b_cyc = (context->current_cycle / 144) % 16;
103 if (!b_cyc) { 150 if (!b_cyc) {
104 if (context->timer_b) { 151 if (context->timer_b) {
105 context->timer_b--; 152 context->timer_b--;
106 } else { 153 } else {
107 if (context->part1_regs[REG_TIME_CTRL] & BIT_TIMERB_OVEREN) { 154 if (context->timer_control & BIT_TIMERB_OVEREN) {
108 context->status |= BIT_STATUS_TIMERB; 155 context->status |= BIT_STATUS_TIMERB;
109 } 156 }
110 context->timer_b = context->part1_regs[REG_TIMERB]; 157 context->timer_b = context->timer_b_load;
111 } 158 }
112 } 159 }
113 } 160 }
114 } 161 }
115 //Update Envelope Generator 162 //Update Envelope Generator
116 if (update_cyc == 0 || update_cyc == 72) { 163 if (update_cyc == 0 || update_cyc == 72) {
117 uint32_t env_cyc = context->current_cycle / 72; 164 uint32_t env_cyc = context->current_cycle / 72;
118 uint32_t op = env_cyc % 24; 165 uint32_t op = env_cyc % 24;
119 env_cyc /= 24; 166 env_cyc /= 24;
167 ym_operator * operator = context->operators + op;
168 ym_channel * channel = context->channels + op/4;
120 uint8_t rate; 169 uint8_t rate;
121 switch(context->env_phase[op]) 170 for(;;) {
122 { 171 rate = operator->rates[operator->env_phase];
123 case PHASE_ATTACK: 172 if (rate) {
124 rate = (op < 3 ? context->part1_regs[REG_SHARED + REG_ATTACK_KS + op] : context->part2_regs[REG_ATTACK_KS + op - 3]) & 0x1F; 173 uint8_t ks = channel->keycode >> operator->key_scaling;;
125 break; 174 rate = rate*2 + ks;
126 case PHASE_DECAY: 175 if (rate > 63) {
127 rate = (op < 3 ? context->part1_regs[REG_SHARED + REG_DECAY_AM + op] : context->part2_regs[REG_DECAY_AM + op - 3]) & 0x1F; 176 rate = 63;
128 break; 177 }
129 case PHASE_SUSTAIN: 178 }
130 rate = (op < 3 ? context->part1_regs[REG_SHARED + REG_SUSTAIN_RATE + op] : context->part2_regs[REG_SUSTAIN_RATE + op - 3]) & 0x1F; 179 //Deal with "infinite" rates
131 break; 180 //It's possible this should be handled in key-on as well
132 case PHASE_RELEASE: 181 if (rate == 63 && operator->env_phase < PHASE_SUSTAIN) {
133 rate = (op < 3 ? context->part1_regs[REG_SHARED + REG_DECAY_AM + op] : context->part2_regs[REG_DECAY_AM + op - 3]) << 1 & 0x1E | 1; 182 if (operator->env_phase == PHASE_ATTACK) {
134 break; 183 operator->env_phase = PHASE_DECAY;
135 } 184 operator->envelope = operator->total_level;
136 if (rate) { 185 } else {
137 //apply key scaling 186 operator->env_phase = PHASE_SUSTAIN;
138 uint8_t shift = (op < 3 ? 187 operator->envelope = operator->sustain_level;
139 context->part1_regs[REG_SHARED + REG_ATTACK_KS + op] : 188 }
140 context->part2_regs[REG_ATTACK_KS + op - 3] 189 } else {
141 ) >> 6; 190 break;
142 uint8_t ks = context->keycode[op] >> (3 - shift); 191 }
143 rate = rate*2 + ks; 192 }
144 if (rate > 63) { 193 uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0;
145 rate = 63; 194 if (!(env_cyc & ((1 << cycle_shift) - 1))) {
146 } 195 uint32_t update_cycle = env_cyc >> cycle_shift & 0x7;
147 } 196 //envelope value is 10-bits, but it will be used as a 4.8 value
148 } 197 uint16_t envelope_inc = rate_table[rate * 8 + update_cycle] << 2;
198 if (operator->env_phase == PHASE_ATTACK) {
199 //this can probably be optimized to a single shift rather than a multiply + shift
200 operator->envelope += (~operator->envelope * envelope_inc) >> 4;
201 operator->envelope &= MAX_ENVELOPE;
202 if (operator->envelope <= operator->total_level) {
203 operator->envelope = operator->total_level;
204 operator->env_phase = PHASE_DECAY;
205 }
206 } else {
207 operator->envelope += envelope_inc;
208 //clamp to max attenuation value
209 if (operator->envelope > MAX_ENVELOPE) {
210 operator->envelope = MAX_ENVELOPE;
211 }
212 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) {
213 operator->envelope = operator->sustain_level;
214 operator->env_phase = PHASE_SUSTAIN;
215 }
216 }
217
218
219 }
220 }
221
149 //Update Phase Generator 222 //Update Phase Generator
150 uint32_t channel = update_cyc / 24; 223 uint32_t channel = update_cyc / 24;
151 if (channel != 6 || !(context->part1_regs[REG_DAC_ENABLE] & 0x80)) { 224 if (channel != 5 || !context->dac_enable) {
152 uint32_t op = (update_cyc) / 6; 225 uint32_t op = (update_cyc) / 6;
153 uint8_t alg; 226 //printf("updating operator %d of channel %d\n", op, channel);
154 if (op < 3) { 227 ym_operator * operator = context->operators + op;
155 alg = context->part1_regs[REG_SHARED + REG_ALG_FEEDBACK + op] & 0x7; 228 ym_channel * chan = context->channels + channel;
156 } else { 229 //TODO: Modulate phase by LFO if necessary
157 alg = context->part2_regs[REG_ALG_FEEDBACK + op-3] & 0x7; 230 operator->phase_counter += operator->phase_inc;
158 } 231 uint16_t phase = operator->phase_counter >> 10 & 0x3FF;
159 context->phase_counter[op] += context->phase_inc[op]; 232 switch (op % 4)
160 uint16_t phase = context->phase_counter[op] >> 10 & 0x3FF; 233 {
161 //TODO: Modulate phase if necessary 234 case 0://Operator 1
162 uint16_t output = pow_table[sine_table[phase & 0x1FF] + context->envelope[op]]; 235 //TODO: Feedback
236 break;
237 case 1://Operator 3
238 switch(chan->algorithm)
239 {
240 case 0:
241 case 2:
242 //modulate by operator 2
243 phase += context->operators[op+1].output >> 4;
244 break;
245 case 1:
246 //modulate by operator 1+2
247 phase += (context->operators[op-1].output + context->operators[op+1].output) >> 4;
248 break;
249 case 5:
250 //modulate by operator 1
251 phase += context->operators[op-1].output >> 4;
252 }
253 break;
254 case 2://Operator 2
255 if (chan->algorithm != 1 && chan->algorithm != 2 || chan->algorithm != 7) {
256 //modulate by Operator 1
257 phase += context->operators[op-2].output >> 4;
258 }
259 break;
260 case 3://Operator 4
261 switch(chan->algorithm)
262 {
263 case 0:
264 case 1:
265 case 4:
266 //modulate by operator 3
267 phase += context->operators[op-2].output >> 4;
268 break;
269 case 2:
270 //modulate by operator 1+3
271 phase += (context->operators[op-3].output + context->operators[op-2].output) >> 4;
272 break;
273 case 3:
274 //modulate by operator 2+3
275 phase += (context->operators[op-1].output + context->operators[op-2].output) >> 4;
276 break;
277 case 5:
278 //modulate by operator 1
279 phase += context->operators[op-3].output >> 4;
280 break;
281 }
282 break;
283 }
284 //printf("sine_table[%X] + %X = %X, sizeof(pow_table)/sizeof(*pow_table) = %X\n", phase & 0x1FF, operator->envelope, sine_table[phase & 0x1FF] + operator->envelope, sizeof(pow_table)/ sizeof(*pow_table));
285 uint16_t output = pow_table[sine_table[phase & 0x1FF] + operator->envelope];
163 if (phase & 0x200) { 286 if (phase & 0x200) {
164 output = -output; 287 output = -output;
165 } 288 }
166 context->op_out[op] = output; 289 operator->output = output;
167 //Update the channel output if we've updated all operators 290 //Update the channel output if we've updated all operators
168 if (op % 4 == 3) { 291 if (op % 4 == 3) {
169 if (alg < 4) { 292 if (chan->algorithm < 4) {
170 context->channel_out[channel] = context->op_out[channel * 4 + 3]; 293 chan->output = operator->output;
171 } else if(alg == 4) { 294 } else if(chan->algorithm == 4) {
172 context->channel_out[channel] = context->op_out[channel * 4 + 3] + context->op_out[channel * 4 + 1]; 295 chan->output = operator->output + context->operators[channel * 4 + 1].output;
173 } else { 296 } else {
174 output = 0; 297 output = 0;
175 for (uint32_t op = ((alg == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) { 298 for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) {
176 output += context->op_out[op]; 299 output += context->operators[op].output;
177 } 300 }
178 context->channel_out[channel] = output; 301 chan->output = output;
179 } 302 }
180 } 303 }
181 } 304 //puts("operator update done");
182 305 }
183 } 306 }
184 if (context->current_cycle >= context->write_cycle + BUSY_CYCLES) { 307 if (context->current_cycle >= context->write_cycle + BUSY_CYCLES) {
185 context->status &= 0x7F; 308 context->status &= 0x7F;
186 } 309 }
310 //printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle);
187 } 311 }
188 312
189 void ym_address_write_part1(ym2612_context * context, uint8_t address) 313 void ym_address_write_part1(ym2612_context * context, uint8_t address)
190 { 314 {
191 if (address >= 0x21 && address < 0xB7) { 315 context->selected_reg = address;
192 context->selected_reg = context->part1_regs + address - 0x21; 316 context->selected_part = 0;
317 }
318
319 void ym_address_write_part2(ym2612_context * context, uint8_t address)
320 {
321 context->selected_reg = address;
322 context->selected_part = 1;
323 }
324
325 uint8_t fnum_to_keycode[] = {
326 //F11 = 0
327 0,0,0,0,0,0,0,1,
328 //F11 = 1
329 2,3,3,3,3,3,3,3
330 };
331
332 //table courtesy of Nemesis
333 uint32_t detune_table[][4] = {
334 {0, 0, 1, 2}, //0 (0x00)
335 {0, 0, 1, 2}, //1 (0x01)
336 {0, 0, 1, 2}, //2 (0x02)
337 {0, 0, 1, 2}, //3 (0x03)
338 {0, 1, 2, 2}, //4 (0x04)
339 {0, 1, 2, 3}, //5 (0x05)
340 {0, 1, 2, 3}, //6 (0x06)
341 {0, 1, 2, 3}, //7 (0x07)
342 {0, 1, 2, 4}, //8 (0x08)
343 {0, 1, 3, 4}, //9 (0x09)
344 {0, 1, 3, 4}, //10 (0x0A)
345 {0, 1, 3, 5}, //11 (0x0B)
346 {0, 2, 4, 5}, //12 (0x0C)
347 {0, 2, 4, 6}, //13 (0x0D)
348 {0, 2, 4, 6}, //14 (0x0E)
349 {0, 2, 5, 7}, //15 (0x0F)
350 {0, 2, 5, 8}, //16 (0x10)
351 {0, 3, 6, 8}, //17 (0x11)
352 {0, 3, 6, 9}, //18 (0x12)
353 {0, 3, 7,10}, //19 (0x13)
354 {0, 4, 8,11}, //20 (0x14)
355 {0, 4, 8,12}, //21 (0x15)
356 {0, 4, 9,13}, //22 (0x16)
357 {0, 5,10,14}, //23 (0x17)
358 {0, 5,11,16}, //24 (0x18)
359 {0, 6,12,17}, //25 (0x19)
360 {0, 6,13,19}, //26 (0x1A)
361 {0, 7,14,20}, //27 (0x1B)
362 {0, 8,16,22}, //28 (0x1C)
363 {0, 8,16,22}, //29 (0x1D)
364 {0, 8,16,22}, //30 (0x1E)
365 {0, 8,16,22}
366 }; //31 (0x1F)
367
368 void ym_update_phase_inc(ym2612_context * context, ym_operator * operator, uint32_t op)
369 {
370 uint32_t chan_num = op / 4;
371 //printf("ym_update_phase_inc | channel: %d, op: %d\n", chan_num, op);
372 //base frequency
373 ym_channel * channel = context->channels + chan_num;
374 uint32_t inc = channel->fnum;
375 if (!channel->block) {
376 inc >> 1;
193 } else { 377 } else {
194 context->selected_reg = NULL; 378 inc << (channel->block-1);
195 } 379 }
196 } 380 //detune
197 381 uint32_t detune = detune_table[channel->keycode][operator->detune & 0x3];
198 void ym_address_write_part2(ym2612_context * context, uint8_t address) 382 if (operator->detune & 0x40) {
199 { 383 inc -= detune;
200 if (address >= 0x30 && address < 0xB7) { 384 //this can underflow, mask to 17-bit result
201 context->selected_reg = context->part1_regs + address - 0x30; 385 inc &= 0x1FFFF;
202 } else { 386 } else {
203 context->selected_reg = NULL; 387 inc += detune;
388 }
389 //multiple
390 if (operator->multiple) {
391 inc *= operator->multiple;
392 } else {
393 //0.5
394 inc >>= 1;
204 } 395 }
205 } 396 }
206 397
207 void ym_data_write(ym2612_context * context, uint8_t value) 398 void ym_data_write(ym2612_context * context, uint8_t value)
208 { 399 {
209 if (context->selected_reg && !(context->status & 0x80)) { 400 if (context->selected_reg < 0x21 || context->selected_reg > 0xB6 || (context->selected_reg < 0x30 && context->selected_part)) {
210 *context->selected_reg = value; 401 return;
211 context->write_cycle = context->current_cycle; 402 }
212 context->selected_reg = NULL;//TODO: Verify this 403 //printf("write to reg %X in part %d\n", context->selected_reg, context->selected_part+1);
213 } 404 if (context->selected_reg < 0x30) {
405 //Shared regs
406 switch (context->selected_reg)
407 {
408 //TODO: Test reg and LFO
409 case REG_TIMERA_HIGH:
410 context->timer_a_load &= 0x3;
411 context->timer_a_load |= value << 2;
412 break;
413 case REG_TIMERA_LOW:
414 context->timer_a_load &= 0xFFFC;
415 context->timer_a_load |= value & 0x3;
416 break;
417 case REG_TIMERB:
418 context->timer_b_load = value;
419 break;
420 case REG_TIME_CTRL:
421 context->timer_control = value;
422 break;
423 case REG_KEY_ONOFF: {
424 uint8_t channel = value & 0x7;
425 if (channel < NUM_CHANNELS) {
426 for (uint8_t op = channel * 4, bit = 0x10; op < (channel + 1) * 4; op++, bit <<= 1) {
427 if (value & bit) {
428 //printf("Key On for operator %d in channel %d\n", op, channel);
429 context->operators[op].phase_counter = 0;
430 context->operators[op].env_phase = PHASE_ATTACK;
431 context->operators[op].envelope = MAX_ENVELOPE;
432 } else {
433 //printf("Key Off for operator %d in channel %d\n", op, channel);
434 context->operators[op].env_phase = PHASE_RELEASE;
435 }
436 }
437 }
438 break;
439 }
440 case REG_DAC:
441 if (context->dac_enable) {
442 context->channels[5].output = (((int16_t)value) - 0x80) << 6;
443 }
444 break;
445 case REG_DAC_ENABLE:
446 context->dac_enable = value & 0x80;
447 break;
448 }
449 } else if (context->selected_reg < 0xA0) {
450 //part
451 uint8_t op = context->selected_part ? (NUM_OPERATORS/2) : 0;
452 //channel in part
453 if ((context->selected_reg & 0x3) != 0x3) {
454 op += 4 * (context->selected_reg & 0x3);
455 //operator in channel
456 switch (context->selected_reg & 0xC)
457 {
458 case 0:
459 break;
460 case 4:
461 op += 2;
462 break;
463 case 8:
464 op += 1;
465 break;
466 case 0xC:
467 op += 3;
468 break;
469 }
470 //printf("write targets operator %d (%d of channel %d)\n", op, op % 4, op / 4);
471 ym_operator * operator = context->operators + op;
472 switch (context->selected_reg & 0xF0)
473 {
474 case REG_DETUNE_MULT:
475 operator->detune = value >> 4 & 0x7;
476 operator->multiple = value & 0xF;
477 ym_update_phase_inc(context, operator, op);
478 break;
479 case REG_TOTAL_LEVEL:
480 operator->total_level = (value & 0x7F) << 5;
481 break;
482 case REG_ATTACK_KS:
483 operator->key_scaling = value >> 6;
484 operator->rates[PHASE_ATTACK] = value & 0x1F;
485 break;
486 case REG_DECAY_AM:
487 //TODO: AM flag for LFO
488 operator->rates[PHASE_DECAY] = value & 0x1F;
489 break;
490 case REG_SUSTAIN_RATE:
491 operator->rates[PHASE_SUSTAIN] = value & 0x1F;
492 break;
493 case REG_S_LVL_R_RATE:
494 operator->rates[PHASE_RELEASE] = (value & 0xF) << 1 | 1;
495 operator->sustain_level = value & 0xF0 << 4;
496 break;
497 }
498 }
499 } else {
500 uint8_t channel = context->selected_reg & 0x3;
501 if (channel != 3) {
502 if (context->selected_part) {
503 channel += 3;
504 }
505 //printf("write targets channel %d\n", channel);
506 switch (context->selected_reg & 0xFC)
507 {
508 case REG_FNUM_LOW:
509 context->channels[channel].block = context->channels[channel].block_fnum_latch >> 3 & 0x7;
510 context->channels[channel].fnum = (context->channels[channel].block_fnum_latch & 0x7) << 8 | value;
511 context->channels[channel].keycode = context->channels[channel].block << 2 | fnum_to_keycode[context->channels[channel].fnum >> 7];
512 ym_update_phase_inc(context, context->operators + channel*4, channel*4);
513 ym_update_phase_inc(context, context->operators + channel*4+1, channel*4+1);
514 ym_update_phase_inc(context, context->operators + channel*4+2, channel*4+2);
515 ym_update_phase_inc(context, context->operators + channel*4+3, channel*4+3);
516 break;
517 case REG_BLOCK_FNUM_H:{
518 context->channels[channel].block_fnum_latch = value;
519 break;
520 }
521 //TODO: Channel 3 special/CSM modes
522 case REG_ALG_FEEDBACK:
523 context->channels[channel].algorithm = value & 0x7;
524 context->channels[channel].feedback = value >> 3 & 0x7;
525 break;
526 case REG_LR_AMS_PMS:
527 context->channels[channel].pms = value & 0x7;
528 context->channels[channel].ams = value >> 4 & 0x3;
529 context->channels[channel].lr = value & 0xC0;
530 break;
531 }
532 }
533 }
534
535 context->write_cycle = context->current_cycle;
536 context->selected_reg = 0;//TODO: Verify this
214 } 537 }
215 538
216 uint8_t ym_read_status(ym2612_context * context) 539 uint8_t ym_read_status(ym2612_context * context)
217 { 540 {
218 return context->status; 541 return context->status;