# HG changeset patch # User Michael Pavone # Date 1582785637 28800 # Node ID 8312e574100a76a6220fa95c3d62c8e077f0f2cc # Parent 62166274e6c0b3299dd2031769032e243e399bdb Implement selectable YM2612/YM3834 invalid status port behavior diff -r 62166274e6c0 -r 8312e574100a genesis.c --- a/genesis.c Tue Feb 25 20:03:04 2020 -0800 +++ b/genesis.c Wed Feb 26 22:40:37 2020 -0800 @@ -875,7 +875,7 @@ value = gen->zram[location & 0x1FFF]; } else if (location < 0x6000) { sync_sound(gen, context->current_cycle); - value = ym_read_status(gen->ym, context->current_cycle); + value = ym_read_status(gen->ym, context->current_cycle, location); } else { value = 0xFF; } @@ -988,7 +988,7 @@ z80_context * context = vcontext; genesis_context * gen = context->system; sync_sound(gen, context->Z80_CYCLE); - return ym_read_status(gen->ym, context->Z80_CYCLE); + return ym_read_status(gen->ym, context->Z80_CYCLE, location); } static uint8_t z80_read_bank(uint32_t location, void * vcontext) @@ -1420,6 +1420,10 @@ render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); gen->ym = malloc(sizeof(ym2612_context)); + char *fm = tern_find_ptr_default(model, "fm", "discrete 2612"); + if (!strcmp(fm + strlen(fm) -4, "3834")) { + system_opts |= YM_OPT_3834; + } ym_init(gen->ym, gen->master_clock, MCLKS_PER_YM, system_opts); gen->psg = malloc(sizeof(psg_context)); diff -r 62166274e6c0 -r 8312e574100a ym2612.c --- a/ym2612.c Tue Feb 25 20:03:04 2020 -0800 +++ b/ym2612.c Wed Feb 26 22:40:37 2020 -0800 @@ -133,6 +133,12 @@ } else { context->busy_start = CYCLE_NEVER; } + if (context->last_status_cycle != CYCLE_NEVER && context->last_status_cycle >= deduction) { + context->last_status_cycle -= deduction; + } else { + context->last_status = 0; + context->last_status_cycle = CYCLE_NEVER; + } } #ifdef __ANDROID__ @@ -188,6 +194,9 @@ context->clock_inc = clock_div * 6; context->busy_cycles = BUSY_CYCLES * context->clock_inc; context->audio = render_audio_source(master_clock, context->clock_inc * NUM_OPERATORS, 2); + //TODO: pick a randomish high initial value and lower it over time + context->invalid_status_decay = 225000 * context->clock_inc; + context->status_address_mask = (options & YM_OPT_3834) ? 0 : 3; //some games seem to expect that the LR flags start out as 1 for (int i = 0; i < NUM_CHANNELS; i++) { @@ -1117,13 +1126,25 @@ } } -uint8_t ym_read_status(ym2612_context * context, uint32_t cycle) +uint8_t ym_read_status(ym2612_context * context, uint32_t cycle, uint32_t port) { - uint8_t status = context->status; - if (cycle >= context->busy_start && cycle < context->busy_start + context->busy_cycles) { - status |= 0x80; + uint8_t status; + port &= context->status_address_mask; + if (port) { + if (context->last_status_cycle != CYCLE_NEVER && cycle - context->last_status_cycle > context->invalid_status_decay) { + context->last_status = 0; + } + status = context->last_status; + } else { + status = context->status; + if (cycle >= context->busy_start && cycle < context->busy_start + context->busy_cycles) { + status |= 0x80; + } + context->last_status = status; + context->last_status_cycle = cycle; } return status; + } void ym_print_channel_info(ym2612_context *context, int channel) @@ -1236,6 +1257,9 @@ save_int32(buf, context->current_cycle); save_int32(buf, context->write_cycle); save_int32(buf, context->busy_start); + save_int32(buf, context->last_status_cycle); + save_int32(buf, context->invalid_status_decay); + save_int8(buf, context->last_status); } void ym_deserialize(deserialize_buffer *buf, void *vcontext) @@ -1311,4 +1335,12 @@ context->current_cycle = load_int32(buf); context->write_cycle = load_int32(buf); context->busy_start = load_int32(buf); + if (buf->size > buf->cur_pos) { + context->last_status_cycle = load_int32(buf); + context->invalid_status_decay = load_int32(buf); + context->last_status = load_int8(buf); + } else { + context->last_status = context->status; + context->last_status_cycle = context->write_cycle; + } } diff -r 62166274e6c0 -r 8312e574100a ym2612.h --- a/ym2612.h Tue Feb 25 20:03:04 2020 -0800 +++ b/ym2612.h Wed Feb 26 22:40:37 2020 -0800 @@ -16,6 +16,7 @@ #define NUM_OPERATORS (4*NUM_CHANNELS) #define YM_OPT_WAVE_LOG 1 +#define YM_OPT_3834 2 typedef struct { int16_t *mod_src[2]; @@ -72,6 +73,9 @@ uint32_t write_cycle; uint32_t busy_start; uint32_t busy_cycles; + uint32_t last_status_cycle; + uint32_t invalid_status_decay; + uint32_t status_address_mask; int32_t volume_mult; int32_t volume_div; ym_operator operators[NUM_OPERATORS]; @@ -97,6 +101,7 @@ uint8_t lfo_pm_step; uint8_t csm_keyon; uint8_t status; + uint8_t last_status; uint8_t selected_reg; uint8_t selected_part; uint8_t part1_regs[YM_PART1_REGS]; @@ -139,7 +144,7 @@ void ym_address_write_part1(ym2612_context * context, uint8_t address); void ym_address_write_part2(ym2612_context * context, uint8_t address); void ym_data_write(ym2612_context * context, uint8_t value); -uint8_t ym_read_status(ym2612_context * context, uint32_t cycle); +uint8_t ym_read_status(ym2612_context * context, uint32_t cycle, uint32_t port); uint8_t ym_load_gst(ym2612_context * context, FILE * gstfile); uint8_t ym_save_gst(ym2612_context * context, FILE * gstfile); void ym_print_channel_info(ym2612_context *context, int channel);