Mercurial > repos > blastem
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 } |