diff --git a/src/devices/sound/ymz280b.cpp b/src/devices/sound/ymz280b.cpp index 570b4e64990..b777f56b89d 100644 --- a/src/devices/sound/ymz280b.cpp +++ b/src/devices/sound/ymz280b.cpp @@ -25,7 +25,7 @@ hardware currently emulated that uses external handlers. It also happens to be the only one using 16-bit PCM. - Some other drivers (eg. bishi.c, bfm_sc4/5.c) also use ROM readback. + Some other drivers (eg. bishi.cpp, bfm_sc4/5.cpp) also use ROM readback. */ @@ -40,11 +40,11 @@ #define MAX_SAMPLE_CHUNK 10000 -#define FRAC_BITS 14 -#define FRAC_ONE (1 << FRAC_BITS) -#define FRAC_MASK (FRAC_ONE - 1) +static constexpr unsigned FRAC_BITS = 9; +static constexpr unsigned FRAC_ONE = (1 << FRAC_BITS); +static constexpr unsigned FRAC_MASK = (FRAC_ONE - 1); -#define INTERNAL_BUFFER_SIZE (1 << 15) +//#define INTERNAL_BUFFER_SIZE (1 << 15) #define INTERNAL_SAMPLE_RATE (m_master_clock * 2.0) @@ -84,14 +84,14 @@ void ymz280b_device::update_irq_state() void ymz280b_device::update_step(struct YMZ280BVoice *voice) { - double frequency; + int frequency; /* compute the frequency */ if (voice->mode == 1) - frequency = m_master_clock * (double)((voice->fnum & 0x0ff) + 1) * (1.0 / 256.0); + frequency = voice->fnum & 0x0ff; else - frequency = m_master_clock * (double)((voice->fnum & 0x1ff) + 1) * (1.0 / 256.0); - voice->output_step = (uint32_t)(frequency * (double)FRAC_ONE / INTERNAL_SAMPLE_RATE); + frequency = voice->fnum & 0x1ff; + voice->output_step = frequency + 1; // ((fnum + 1) * (input clock / 384)) / 256 } @@ -165,7 +165,7 @@ static void compute_tables() ***********************************************************************************************/ -int ymz280b_device::generate_adpcm(struct YMZ280BVoice *voice, int16_t *buffer, int samples) +int ymz280b_device::generate_adpcm(struct YMZ280BVoice *voice, s16 *buffer, int samples) { int position = voice->position; int signal = voice->signal; @@ -277,7 +277,7 @@ int ymz280b_device::generate_adpcm(struct YMZ280BVoice *voice, int16_t *buffer, ***********************************************************************************************/ -int ymz280b_device::generate_pcm8(struct YMZ280BVoice *voice, int16_t *buffer, int samples) +int ymz280b_device::generate_pcm8(struct YMZ280BVoice *voice, s16 *buffer, int samples) { int position = voice->position; int val; @@ -292,7 +292,7 @@ int ymz280b_device::generate_pcm8(struct YMZ280BVoice *voice, int16_t *buffer, i val = read_byte(position / 2); /* output to the buffer, scaling by the volume */ - *buffer++ = (int8_t)val * 256; + *buffer++ = (s8)val * 256; samples--; /* next! */ @@ -315,7 +315,7 @@ int ymz280b_device::generate_pcm8(struct YMZ280BVoice *voice, int16_t *buffer, i val = read_byte(position / 2); /* output to the buffer, scaling by the volume */ - *buffer++ = (int8_t)val * 256; + *buffer++ = (s8)val * 256; samples--; /* next! */ @@ -347,7 +347,7 @@ int ymz280b_device::generate_pcm8(struct YMZ280BVoice *voice, int16_t *buffer, i ***********************************************************************************************/ -int ymz280b_device::generate_pcm16(struct YMZ280BVoice *voice, int16_t *buffer, int samples) +int ymz280b_device::generate_pcm16(struct YMZ280BVoice *voice, s16 *buffer, int samples) { int position = voice->position; int val; @@ -359,7 +359,7 @@ int ymz280b_device::generate_pcm16(struct YMZ280BVoice *voice, int16_t *buffer, while (samples) { /* fetch the current value */ - val = (int16_t)((read_byte(position / 2 + 1) << 8) + read_byte(position / 2 + 0)); + val = (s16)((read_byte(position / 2 + 1) << 8) + read_byte(position / 2 + 0)); /* output to the buffer, scaling by the volume */ *buffer++ = val; @@ -382,7 +382,7 @@ int ymz280b_device::generate_pcm16(struct YMZ280BVoice *voice, int16_t *buffer, while (samples) { /* fetch the current value */ - val = (int16_t)((read_byte(position / 2 + 1) << 8) + read_byte(position / 2 + 0)); + val = (s16)((read_byte(position / 2 + 1) << 8) + read_byte(position / 2 + 0)); /* output to the buffer, scaling by the volume */ *buffer++ = val; @@ -430,13 +430,13 @@ void ymz280b_device::sound_stream_update(sound_stream &stream, stream_sample_t * for (v = 0; v < 8; v++) { struct YMZ280BVoice *voice = &m_voice[v]; - int16_t prev = voice->last_sample; - int16_t curr = voice->curr_sample; - int16_t *curr_data = m_scratch.get(); - int32_t *ldest = lacc; - int32_t *rdest = racc; - uint32_t new_samples, samples_left; - uint32_t final_pos; + s16 prev = voice->last_sample; + s16 curr = voice->curr_sample; + s16 *curr_data = m_scratch.get(); + s32 *ldest = lacc; + s32 *rdest = racc; + u32 new_samples, samples_left; + u32 final_pos; int remaining = samples; int lvol = voice->output_left; int rvol = voice->output_right; @@ -446,7 +446,6 @@ void ymz280b_device::sound_stream_update(sound_stream &stream, stream_sample_t * { /* make sure next sound plays immediately */ voice->output_pos = FRAC_ONE; - continue; } @@ -454,7 +453,7 @@ void ymz280b_device::sound_stream_update(sound_stream &stream, stream_sample_t * /* interpolate */ while (remaining > 0 && voice->output_pos < FRAC_ONE) { - int interp_sample = (((int32_t)prev * (FRAC_ONE - voice->output_pos)) + ((int32_t)curr * voice->output_pos)) >> FRAC_BITS; + int interp_sample = (((s32)prev * (FRAC_ONE - voice->output_pos)) + ((s32)curr * voice->output_pos)) >> FRAC_BITS; *ldest++ += interp_sample * lvol; *rdest++ += interp_sample * rvol; voice->output_pos += voice->output_step; @@ -518,7 +517,7 @@ void ymz280b_device::sound_stream_update(sound_stream &stream, stream_sample_t * /* interpolate */ while (remaining > 0 && voice->output_pos < FRAC_ONE) { - int interp_sample = (((int32_t)prev * (FRAC_ONE - voice->output_pos)) + ((int32_t)curr * voice->output_pos)) >> FRAC_BITS; + int interp_sample = (((s32)prev * (FRAC_ONE - voice->output_pos)) + ((s32)curr * voice->output_pos)) >> FRAC_BITS; *ldest++ += interp_sample * lvol; *rdest++ += interp_sample * rvol; voice->output_pos += voice->output_step; @@ -571,7 +570,7 @@ void ymz280b_device::device_start() /* allocate memory */ assert(MAX_SAMPLE_CHUNK < 0x10000); - m_scratch = std::make_unique(MAX_SAMPLE_CHUNK); + m_scratch = std::make_unique(MAX_SAMPLE_CHUNK); /* state save */ save_item(NAME(m_current_register)); @@ -585,33 +584,31 @@ void ymz280b_device::device_start() save_item(NAME(m_ext_readlatch)); save_item(NAME(m_ext_mem_address_hi)); save_item(NAME(m_ext_mem_address_mid)); - for (int j = 0; j < 8; j++) - { - save_item(NAME(m_voice[j].playing), j); - save_item(NAME(m_voice[j].ended), j); - save_item(NAME(m_voice[j].keyon), j); - save_item(NAME(m_voice[j].looping), j); - save_item(NAME(m_voice[j].mode), j); - save_item(NAME(m_voice[j].fnum), j); - save_item(NAME(m_voice[j].level), j); - save_item(NAME(m_voice[j].pan), j); - save_item(NAME(m_voice[j].start), j); - save_item(NAME(m_voice[j].stop), j); - save_item(NAME(m_voice[j].loop_start), j); - save_item(NAME(m_voice[j].loop_end), j); - save_item(NAME(m_voice[j].position), j); - save_item(NAME(m_voice[j].signal), j); - save_item(NAME(m_voice[j].step), j); - save_item(NAME(m_voice[j].loop_signal), j); - save_item(NAME(m_voice[j].loop_step), j); - save_item(NAME(m_voice[j].loop_count), j); - save_item(NAME(m_voice[j].output_left), j); - save_item(NAME(m_voice[j].output_right), j); - save_item(NAME(m_voice[j].output_pos), j); - save_item(NAME(m_voice[j].last_sample), j); - save_item(NAME(m_voice[j].curr_sample), j); - save_item(NAME(m_voice[j].irq_schedule), j); - } + + save_item(STRUCT_MEMBER(m_voice, playing)); + save_item(STRUCT_MEMBER(m_voice, ended)); + save_item(STRUCT_MEMBER(m_voice, keyon)); + save_item(STRUCT_MEMBER(m_voice, looping)); + save_item(STRUCT_MEMBER(m_voice, mode)); + save_item(STRUCT_MEMBER(m_voice, fnum)); + save_item(STRUCT_MEMBER(m_voice, level)); + save_item(STRUCT_MEMBER(m_voice, pan)); + save_item(STRUCT_MEMBER(m_voice, start)); + save_item(STRUCT_MEMBER(m_voice, stop)); + save_item(STRUCT_MEMBER(m_voice, loop_start)); + save_item(STRUCT_MEMBER(m_voice, loop_end)); + save_item(STRUCT_MEMBER(m_voice, position)); + save_item(STRUCT_MEMBER(m_voice, signal)); + save_item(STRUCT_MEMBER(m_voice, step)); + save_item(STRUCT_MEMBER(m_voice, loop_signal)); + save_item(STRUCT_MEMBER(m_voice, loop_step)); + save_item(STRUCT_MEMBER(m_voice, loop_count)); + save_item(STRUCT_MEMBER(m_voice, output_left)); + save_item(STRUCT_MEMBER(m_voice, output_right)); + save_item(STRUCT_MEMBER(m_voice, output_pos)); + save_item(STRUCT_MEMBER(m_voice, last_sample)); + save_item(STRUCT_MEMBER(m_voice, curr_sample)); + save_item(STRUCT_MEMBER(m_voice, irq_schedule)); #if YMZ280B_MAKE_WAVS m_wavresample = wav_open("resamp.wav", INTERNAL_SAMPLE_RATE, 2); @@ -868,17 +865,19 @@ void ymz280b_device::write_to_register(int data) int ymz280b_device::compute_status() { - uint8_t result; + u8 result; /* force an update */ m_stream->update(); result = m_status_register; - /* clear the IRQ state */ - m_status_register = 0; - update_irq_state(); - + if (!machine().side_effects_disabled()) + { + /* clear the IRQ state */ + m_status_register = 0; + update_irq_state(); + } return result; } @@ -898,9 +897,10 @@ u8 ymz280b_device::read(offs_t offset) return 0xff; /* read from external memory */ - uint8_t ret = m_ext_readlatch; + u8 ret = m_ext_readlatch; m_ext_readlatch = read_byte(m_ext_mem_address); - m_ext_mem_address = (m_ext_mem_address + 1) & 0xffffff; + if (!machine().side_effects_disabled()) + m_ext_mem_address = (m_ext_mem_address + 1) & 0xffffff; return ret; } else @@ -924,7 +924,7 @@ void ymz280b_device::write(offs_t offset, u8 data) DEFINE_DEVICE_TYPE(YMZ280B, ymz280b_device, "ymz280b", "Yamaha YMZ280B PCMD8") -ymz280b_device::ymz280b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) +ymz280b_device::ymz280b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, YMZ280B, tag, owner, clock) , device_sound_interface(mconfig, *this) , device_rom_interface(mconfig, *this) diff --git a/src/devices/sound/ymz280b.h b/src/devices/sound/ymz280b.h index 898d952c0d2..a375f4a7ed0 100644 --- a/src/devices/sound/ymz280b.h +++ b/src/devices/sound/ymz280b.h @@ -19,7 +19,7 @@ class ymz280b_device : public device_t, public device_sound_interface, public device_rom_interface<24> { public: - ymz280b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + ymz280b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); // configuration helpers auto irq_handler() { return m_irq_handler.bind(); } @@ -45,36 +45,36 @@ private: /* struct describing a single playing ADPCM voice */ struct YMZ280BVoice { - uint8_t playing; /* 1 if we are actively playing */ - bool ended; /* indicate voice has ended in case samples_left is 0 */ + u8 playing; /* 1 if we are actively playing */ + bool ended; /* indicate voice has ended in case samples_left is 0 */ - uint8_t keyon; /* 1 if the key is on */ - uint8_t looping; /* 1 if looping is enabled */ - uint8_t mode; /* current playback mode */ - uint16_t fnum; /* frequency */ - uint8_t level; /* output level */ - uint8_t pan; /* panning */ + u8 keyon; /* 1 if the key is on */ + u8 looping; /* 1 if looping is enabled */ + u8 mode; /* current playback mode */ + u16 fnum; /* frequency */ + u8 level; /* output level */ + u8 pan; /* panning */ - uint32_t start; /* start address, in nibbles */ - uint32_t stop; /* stop address, in nibbles */ - uint32_t loop_start; /* loop start address, in nibbles */ - uint32_t loop_end; /* loop end address, in nibbles */ - uint32_t position; /* current position, in nibbles */ + u32 start; /* start address, in nibbles */ + u32 stop; /* stop address, in nibbles */ + u32 loop_start; /* loop start address, in nibbles */ + u32 loop_end; /* loop end address, in nibbles */ + u32 position; /* current position, in nibbles */ - int32_t signal; /* current ADPCM signal */ - int32_t step; /* current ADPCM step */ + s32 signal; /* current ADPCM signal */ + s32 step; /* current ADPCM step */ - int32_t loop_signal; /* signal at loop start */ - int32_t loop_step; /* step at loop start */ - uint32_t loop_count; /* number of loops so far */ + s32 loop_signal; /* signal at loop start */ + s32 loop_step; /* step at loop start */ + u32 loop_count; /* number of loops so far */ - int32_t output_left; /* output volume (left) */ - int32_t output_right; /* output volume (right) */ - int32_t output_step; /* step value for frequency conversion */ - int32_t output_pos; /* current fractional position */ - int16_t last_sample; /* last sample output */ - int16_t curr_sample; /* current sample target */ - uint8_t irq_schedule; /* 1 if the IRQ state is updated by timer */ + s32 output_left; /* output volume (left) */ + s32 output_right; /* output volume (right) */ + s32 output_step; /* step value for frequency conversion */ + s32 output_pos; /* current fractional position */ + s16 last_sample; /* last sample output */ + s16 curr_sample; /* current sample target */ + u8 irq_schedule; /* 1 if the IRQ state is updated by timer */ emu_timer *timer; }; @@ -83,31 +83,31 @@ private: void update_step(struct YMZ280BVoice *voice); void update_volumes(struct YMZ280BVoice *voice); void update_irq_state_timer_common(int voicenum); - int generate_adpcm(struct YMZ280BVoice *voice, int16_t *buffer, int samples); - int generate_pcm8(struct YMZ280BVoice *voice, int16_t *buffer, int samples); - int generate_pcm16(struct YMZ280BVoice *voice, int16_t *buffer, int samples); + int generate_adpcm(struct YMZ280BVoice *voice, s16 *buffer, int samples); + int generate_pcm8(struct YMZ280BVoice *voice, s16 *buffer, int samples); + int generate_pcm16(struct YMZ280BVoice *voice, s16 *buffer, int samples); void write_to_register(int data); int compute_status(); // internal state struct YMZ280BVoice m_voice[8]; /* the 8 voices */ - uint8_t m_current_register; /* currently accessible register */ - uint8_t m_status_register; /* current status register */ - uint8_t m_irq_state; /* current IRQ state */ - uint8_t m_irq_mask; /* current IRQ mask */ - uint8_t m_irq_enable; /* current IRQ enable */ - uint8_t m_keyon_enable; /* key on enable */ - uint8_t m_ext_mem_enable; /* external memory enable */ - uint8_t m_ext_readlatch; /* external memory prefetched data */ - uint32_t m_ext_mem_address_hi; - uint32_t m_ext_mem_address_mid; - uint32_t m_ext_mem_address; /* where the CPU can read the ROM */ + u8 m_current_register; /* currently accessible register */ + u8 m_status_register; /* current status register */ + u8 m_irq_state; /* current IRQ state */ + u8 m_irq_mask; /* current IRQ mask */ + u8 m_irq_enable; /* current IRQ enable */ + u8 m_keyon_enable; /* key on enable */ + u8 m_ext_mem_enable; /* external memory enable */ + u8 m_ext_readlatch; /* external memory prefetched data */ + u32 m_ext_mem_address_hi; + u32 m_ext_mem_address_mid; + u32 m_ext_mem_address; /* where the CPU can read the ROM */ - devcb_write_line m_irq_handler; /* IRQ callback */ + devcb_write_line m_irq_handler; /* IRQ callback */ double m_master_clock; /* master clock frequency */ sound_stream *m_stream; /* which stream are we using */ - std::unique_ptr m_scratch; + std::unique_ptr m_scratch; #if YMZ280B_MAKE_WAVS void *m_wavresample; /* resampled waveform */ #endif