comparison ym2612.c @ 1902:32a3aa7b4a45

Fix YM2612 busy flag timing
author Michael Pavone <pavone@retrodev.com>
date Mon, 24 Feb 2020 20:06:29 -0800
parents e77f7a7c79a5
children 8312e574100a
comparison
equal deleted inserted replaced
1901:5433252329fb 1902:32a3aa7b4a45
19 #else 19 #else
20 #define dfprintf 20 #define dfprintf
21 #define dfopen(var, fname, mode) 21 #define dfopen(var, fname, mode)
22 #endif 22 #endif
23 23
24 #define BUSY_CYCLES_ADDRESS 17 24 #define BUSY_CYCLES 32
25 #define BUSY_CYCLES_DATA_LOW 83
26 #define BUSY_CYCLES_DATA_HIGH 47
27 #define OP_UPDATE_PERIOD 144 25 #define OP_UPDATE_PERIOD 144
28 26
29 #define BIT_TIMERA_ENABLE 0x1 27 #define BIT_TIMERA_ENABLE 0x1
30 #define BIT_TIMERB_ENABLE 0x2 28 #define BIT_TIMERB_ENABLE 0x2
31 #define BIT_TIMERA_OVEREN 0x4 29 #define BIT_TIMERA_OVEREN 0x4
118 } 116 }
119 117
120 void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock) 118 void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock)
121 { 119 {
122 render_audio_adjust_clock(context->audio, master_clock, context->clock_inc * NUM_OPERATORS); 120 render_audio_adjust_clock(context->audio, master_clock, context->clock_inc * NUM_OPERATORS);
121 }
122
123 void ym_adjust_cycles(ym2612_context *context, uint32_t deduction)
124 {
125 context->current_cycle -= deduction;
126 if (context->write_cycle != CYCLE_NEVER && context->write_cycle >= deduction) {
127 context->write_cycle -= deduction;
128 } else {
129 context->write_cycle = CYCLE_NEVER;
130 }
131 if (context->busy_start != CYCLE_NEVER && context->busy_start >= deduction) {
132 context->busy_start -= deduction;
133 } else {
134 context->busy_start = CYCLE_NEVER;
135 }
123 } 136 }
124 137
125 #ifdef __ANDROID__ 138 #ifdef __ANDROID__
126 #define log2(x) (log(x)/log(2)) 139 #define log2(x) (log(x)/log(2))
127 #endif 140 #endif
171 { 184 {
172 static uint8_t registered_finalize; 185 static uint8_t registered_finalize;
173 dfopen(debug_file, "ym_debug.txt", "w"); 186 dfopen(debug_file, "ym_debug.txt", "w");
174 memset(context, 0, sizeof(*context)); 187 memset(context, 0, sizeof(*context));
175 context->clock_inc = clock_div * 6; 188 context->clock_inc = clock_div * 6;
189 context->busy_cycles = BUSY_CYCLES * context->clock_inc;
176 context->audio = render_audio_source(master_clock, context->clock_inc * NUM_OPERATORS, 2); 190 context->audio = render_audio_source(master_clock, context->clock_inc * NUM_OPERATORS, 2);
177 191
178 //some games seem to expect that the LR flags start out as 1 192 //some games seem to expect that the LR flags start out as 1
179 for (int i = 0; i < NUM_CHANNELS; i++) { 193 for (int i = 0; i < NUM_CHANNELS; i++) {
180 if (options & YM_OPT_WAVE_LOG) { 194 if (options & YM_OPT_WAVE_LOG) {
633 context->current_op = 0; 647 context->current_op = 0;
634 ym_output_sample(context); 648 ym_output_sample(context);
635 } 649 }
636 650
637 } 651 }
638 if (context->current_cycle >= context->write_cycle + (context->busy_cycles * context->clock_inc / 6)) {
639 context->status &= 0x7F;
640 context->write_cycle = CYCLE_NEVER;
641 }
642 //printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle); 652 //printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle);
643 } 653 }
644 654
645 void ym_address_write_part1(ym2612_context * context, uint8_t address) 655 void ym_address_write_part1(ym2612_context * context, uint8_t address)
646 { 656 {
647 //printf("address_write_part1: %X\n", address); 657 //printf("address_write_part1: %X\n", address);
648 context->selected_reg = address; 658 context->selected_reg = address;
649 context->selected_part = 0; 659 context->selected_part = 0;
650 context->write_cycle = context->current_cycle;
651 context->busy_cycles = BUSY_CYCLES_ADDRESS;
652 context->status |= 0x80;
653 } 660 }
654 661
655 void ym_address_write_part2(ym2612_context * context, uint8_t address) 662 void ym_address_write_part2(ym2612_context * context, uint8_t address)
656 { 663 {
657 //printf("address_write_part2: %X\n", address); 664 //printf("address_write_part2: %X\n", address);
658 context->selected_reg = address; 665 context->selected_reg = address;
659 context->selected_part = 1; 666 context->selected_part = 1;
660 context->write_cycle = context->current_cycle;
661 context->busy_cycles = BUSY_CYCLES_ADDRESS;
662 context->status |= 0x80;
663 } 667 }
664 668
665 static uint8_t fnum_to_keycode[] = { 669 static uint8_t fnum_to_keycode[] = {
666 //F11 = 0 670 //F11 = 0
667 0,0,0,0,0,0,0,1, 671 0,0,0,0,0,0,0,1,
766 return inc; 770 return inc;
767 } 771 }
768 772
769 void ym_data_write(ym2612_context * context, uint8_t value) 773 void ym_data_write(ym2612_context * context, uint8_t value)
770 { 774 {
775 context->write_cycle = context->current_cycle;
776 context->busy_start = context->current_cycle + context->clock_inc;
777
771 if (context->selected_reg >= YM_REG_END) { 778 if (context->selected_reg >= YM_REG_END) {
772 return; 779 return;
773 } 780 }
774 if (context->selected_part) { 781 if (context->selected_part) {
775 if (context->selected_reg < YM_PART2_START) { 782 if (context->selected_reg < YM_PART2_START) {
1106 break; 1113 break;
1107 } 1114 }
1108 } 1115 }
1109 } 1116 }
1110 } 1117 }
1111 1118 }
1112 context->write_cycle = context->current_cycle; 1119
1113 context->busy_cycles = context->selected_reg < 0xA0 ? BUSY_CYCLES_DATA_LOW : BUSY_CYCLES_DATA_HIGH; 1120 uint8_t ym_read_status(ym2612_context * context, uint32_t cycle)
1114 context->status |= 0x80; 1121 {
1115 } 1122 uint8_t status = context->status;
1116 1123 if (cycle >= context->busy_start && cycle < context->busy_start + context->busy_cycles) {
1117 uint8_t ym_read_status(ym2612_context * context) 1124 status |= 0x80;
1118 { 1125 }
1119 return context->status; 1126 return status;
1120 } 1127 }
1121 1128
1122 void ym_print_channel_info(ym2612_context *context, int channel) 1129 void ym_print_channel_info(ym2612_context *context, int channel)
1123 { 1130 {
1124 ym_channel *chan = context->channels + channel; 1131 ym_channel *chan = context->channels + channel;
1226 save_int8(buf, context->status); 1233 save_int8(buf, context->status);
1227 save_int8(buf, context->selected_reg); 1234 save_int8(buf, context->selected_reg);
1228 save_int8(buf, context->selected_part); 1235 save_int8(buf, context->selected_part);
1229 save_int32(buf, context->current_cycle); 1236 save_int32(buf, context->current_cycle);
1230 save_int32(buf, context->write_cycle); 1237 save_int32(buf, context->write_cycle);
1231 save_int32(buf, context->busy_cycles); 1238 save_int32(buf, context->busy_start);
1232 } 1239 }
1233 1240
1234 void ym_deserialize(deserialize_buffer *buf, void *vcontext) 1241 void ym_deserialize(deserialize_buffer *buf, void *vcontext)
1235 { 1242 {
1236 ym2612_context *context = vcontext; 1243 ym2612_context *context = vcontext;
1301 context->status = load_int8(buf); 1308 context->status = load_int8(buf);
1302 context->selected_reg = load_int8(buf); 1309 context->selected_reg = load_int8(buf);
1303 context->selected_part = load_int8(buf); 1310 context->selected_part = load_int8(buf);
1304 context->current_cycle = load_int32(buf); 1311 context->current_cycle = load_int32(buf);
1305 context->write_cycle = load_int32(buf); 1312 context->write_cycle = load_int32(buf);
1306 context->busy_cycles = load_int32(buf); 1313 context->busy_start = load_int32(buf);
1307 } 1314 }