void speaker_sound_device::device_reset() { int i; m_level = 0; for (i = 0; i < FILTER_LENGTH; i++) m_composed_volume[i] = 0; m_composed_sample_index = 0; m_last_update_time = machine().time(); m_channel_sample_period = HZ_TO_ATTOSECONDS(machine().sample_rate()); m_channel_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(m_channel_sample_period); m_interm_sample_period = m_channel_sample_period / RATE_MULTIPLIER; m_interm_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(m_interm_sample_period); m_channel_last_sample_time = m_channel->sample_time(); m_channel_next_sample_time = m_channel_last_sample_time + attotime(0, m_channel_sample_period); m_next_interm_sample_time = m_channel_last_sample_time + attotime(0, m_interm_sample_period); m_interm_sample_index = 0; m_prevx = m_prevy = 0.0; }
static void configure_screen(crtc6845_state *chip, int postload) { if (chip->intf) { /* compute the screen sizes */ UINT16 horiz_total = (chip->horiz_total + 1) * chip->intf->hpixels_per_column; UINT16 vert_total = (chip->vert_total + 1) * (chip->max_ras_addr + 1) + chip->vert_total_adj; /* determine the visible area, avoid division by 0 */ UINT16 max_x = chip->horiz_disp * chip->intf->hpixels_per_column - 1; UINT16 max_y = chip->vert_disp * (chip->max_ras_addr + 1) - 1; /* update only if screen parameters changed, unless we are coming here after loading the saved state */ if (postload || (horiz_total != chip->last_horiz_total) || (vert_total != chip->last_vert_total) || (max_x != chip->last_max_x) || (max_y != chip->last_max_y)) { /* update the screen only if we have valid data */ if ((chip->horiz_total > 0) && (max_x < horiz_total) && (chip->vert_total > 0) && (max_y < vert_total)) { rectangle visarea; attoseconds_t refresh = HZ_TO_ATTOSECONDS(chip->intf->clock) * (chip->horiz_total + 1) * vert_total; visarea.min_x = 0; visarea.min_y = 0; visarea.max_x = max_x; visarea.max_y = max_y; if (LOG) logerror("CRTC6845 config screen: HTOTAL: %x VTOTAL: %x MAX_X: %x MAX_Y: %x FPS: %f\n", horiz_total, vert_total, max_x, max_y, 1 / ATTOSECONDS_TO_DOUBLE(refresh)); video_screen_configure(chip->intf->scrnum, horiz_total, vert_total, &visarea, refresh); chip->has_valid_parameters = TRUE; } else chip->has_valid_parameters = FALSE; chip->last_horiz_total = horiz_total; chip->last_vert_total = vert_total; chip->last_max_x = max_x; chip->last_max_y = max_y; update_timer(chip); } } }
inline void crt9007_device::recompute_parameters() { // check that necessary registers have been loaded if (!HAS_VALID_PARAMETERS) return; // screen dimensions int horiz_pix_total = CHARACTERS_PER_HORIZONTAL_PERIOD * m_hpixels_per_column; int vert_pix_total = SCAN_LINES_PER_FRAME; // refresh rate attoseconds_t refresh = HZ_TO_ATTOSECONDS(clock()) * horiz_pix_total * vert_pix_total; // horizontal sync m_hsync_start = 0; m_hsync_end = HORIZONTAL_SYNC_WIDTH * m_hpixels_per_column; // visible line time m_vlt_start = HORIZONTAL_DELAY * m_hpixels_per_column; m_vlt_end = (HORIZONTAL_DELAY + CHARACTERS_PER_DATA_ROW) * m_hpixels_per_column; m_vlt_bottom = VERTICAL_DELAY + (VISIBLE_DATA_ROWS_PER_FRAME * SCAN_LINES_PER_DATA_ROW) - 1; // data row boundary m_drb_bottom = VERTICAL_DELAY + (VISIBLE_DATA_ROWS_PER_FRAME * SCAN_LINES_PER_DATA_ROW) - SCAN_LINES_PER_DATA_ROW; // vertical sync m_vsync_start = 0; m_vsync_end = VERTICAL_SYNC_WIDTH; // visible area rectangle visarea; visarea.set(m_hsync_end, horiz_pix_total - 1, m_vsync_end, vert_pix_total - 1); if (LOG) { logerror("CRT9007 '%s' Screen: %u x %u @ %f Hz\n", tag(), horiz_pix_total, vert_pix_total, 1 / ATTOSECONDS_TO_DOUBLE(refresh)); logerror("CRT9007 '%s' Visible Area: (%u, %u) - (%u, %u)\n", tag(), visarea.min_x, visarea.min_y, visarea.max_x, visarea.max_y); } m_screen->configure(horiz_pix_total, vert_pix_total, visarea, refresh); m_hsync_timer->adjust(m_screen->time_until_pos(0, 0)); m_vsync_timer->adjust(m_screen->time_until_pos(0, 0)); m_vlt_timer->adjust(m_screen->time_until_pos(0, m_vlt_start), 1); m_drb_timer->adjust(m_screen->time_until_pos(0, 0)); }
inline void upd3301_device::recompute_parameters() { int horiz_pix_total = (m_h + m_z) * m_width; int vert_pix_total = (m_l + m_v) * m_r; attoseconds_t refresh = HZ_TO_ATTOSECONDS(clock()) * horiz_pix_total * vert_pix_total; rectangle visarea; visarea.set(0, (m_h * m_width) - 1, 0, (m_l * m_r) - 1); if (LOG) { if (LOG) logerror("UPD3301 '%s' Screen: %u x %u @ %f Hz\n", tag(), horiz_pix_total, vert_pix_total, 1 / ATTOSECONDS_TO_DOUBLE(refresh)); if (LOG) logerror("UPD3301 '%s' Visible Area: (%u, %u) - (%u, %u)\n", tag(), visarea.min_x, visarea.min_y, visarea.max_x, visarea.max_y); } m_screen->configure(horiz_pix_total, vert_pix_total, visarea, refresh); update_hrtc_timer(0); update_vrtc_timer(0); }
void crtc_ega_device::recompute_parameters(bool postload) { UINT16 hsync_on_pos, hsync_off_pos, vsync_on_pos, vsync_off_pos; /* compute the screen sizes */ UINT16 horiz_pix_total = (m_horiz_char_total + 2) * m_hpixels_per_column; UINT16 vert_pix_total = m_vert_total + 1; /* determine the visible area, avoid division by 0 */ UINT16 max_visible_x = ( m_horiz_disp + 1 ) * m_hpixels_per_column - 1; UINT16 max_visible_y = m_vert_disp_end; /* determine the syncing positions */ int horiz_sync_char_width = ( m_horiz_retr_end + 1 ) - ( m_horiz_retr_start & 0x1f ); int vert_sync_pix_width = m_vert_retr_end - ( m_vert_retr_start & 0x0f ); if (horiz_sync_char_width <= 0) horiz_sync_char_width += 0x10; if (vert_sync_pix_width <= 0) vert_sync_pix_width += 0x10; hsync_on_pos = m_horiz_retr_start * m_hpixels_per_column; hsync_off_pos = hsync_on_pos + (horiz_sync_char_width * m_hpixels_per_column); vsync_on_pos = m_vert_retr_start; /* + 1 ?? */ vsync_off_pos = vsync_on_pos + vert_sync_pix_width; if (hsync_off_pos > horiz_pix_total) hsync_off_pos = horiz_pix_total; if (vsync_off_pos > vert_pix_total) vsync_off_pos = vert_pix_total; if ( vsync_on_pos >= vsync_off_pos ) { vsync_on_pos = vsync_off_pos - 2; } /* update only if screen parameters changed, unless we are coming here after loading the saved state */ if (postload || (horiz_pix_total != m_horiz_pix_total) || (vert_pix_total != m_vert_pix_total) || (max_visible_x != m_max_visible_x) || (max_visible_y != m_max_visible_y) || (hsync_on_pos != m_hsync_on_pos) || (vsync_on_pos != m_vsync_on_pos) || (hsync_off_pos != m_hsync_off_pos) || (vsync_off_pos != m_vsync_off_pos)) { /* update the screen if we have valid data */ if ((horiz_pix_total > 0) && (max_visible_x < horiz_pix_total) && (vert_pix_total > 0) && (max_visible_y < vert_pix_total) && (hsync_on_pos <= horiz_pix_total) && (vsync_on_pos <= vert_pix_total) && (hsync_on_pos != hsync_off_pos)) { attoseconds_t refresh = HZ_TO_ATTOSECONDS(m_clock) * (m_horiz_char_total + 2) * vert_pix_total; rectangle visarea(0, max_visible_x, 0, max_visible_y); if (LOG) logerror("CRTC_EGA config screen: HTOTAL: 0x%x VTOTAL: 0x%x MAX_X: 0x%x MAX_Y: 0x%x HSYNC: 0x%x-0x%x VSYNC: 0x%x-0x%x Freq: %ffps\n", horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, hsync_on_pos, hsync_off_pos - 1, vsync_on_pos, vsync_off_pos - 1, 1 / ATTOSECONDS_TO_DOUBLE(refresh)); if ( m_screen != NULL ) m_screen->configure(horiz_pix_total, vert_pix_total, visarea, refresh); m_has_valid_parameters = true; } else { m_has_valid_parameters = false; if (LOG) logerror("CRTC_EGA bad config screen: HTOTAL: 0x%x VTOTAL: 0x%x MAX_X: 0x%x MAX_Y: 0x%x HSYNC: 0x%x-0x%x VSYNC: 0x%x-0x%x\n", horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, hsync_on_pos, hsync_off_pos - 1, vsync_on_pos, vsync_off_pos - 1); } m_horiz_pix_total = horiz_pix_total; m_vert_pix_total = vert_pix_total; m_max_visible_x = max_visible_x; m_max_visible_y = max_visible_y; m_hsync_on_pos = hsync_on_pos; m_hsync_off_pos = hsync_off_pos; m_vsync_on_pos = vsync_on_pos; m_vsync_off_pos = vsync_off_pos; } }
void speaker_sound_device::device_start() { int i; double x; m_channel = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate(), this); m_level = 0; for (i = 0; i < FILTER_LENGTH; i++) m_composed_volume[i] = 0; m_composed_sample_index = 0; m_last_update_time = machine().time(); m_channel_sample_period = HZ_TO_ATTOSECONDS(machine().sample_rate()); m_channel_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(m_channel_sample_period); m_interm_sample_period = m_channel_sample_period / RATE_MULTIPLIER; m_interm_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(m_interm_sample_period); m_channel_last_sample_time = m_channel->sample_time(); m_channel_next_sample_time = m_channel_last_sample_time + attotime(0, m_channel_sample_period); m_next_interm_sample_time = m_channel_last_sample_time + attotime(0, m_interm_sample_period); m_interm_sample_index = 0; m_prevx = m_prevy = 0.0; /* Note: To avoid time drift due to floating point inaccuracies, * it is good if the speaker time synchronizes itself with the stream timing regularly. */ /* Compute filter kernel; */ /* (Done for each device though the data is shared... * No problem really, but should be done as part of system init if I knew how) */ #if 1 /* This is an approximated sinc (a perfect sinc makes an ideal low-pass filter). * FILTER_STEP determines the cutoff frequency, * which should be below the Nyquist freq, i.e. half the sample rate. * Smaller step => kernel extends in time domain => lower cutoff freq * In this case, with sinc, filter step PI corresponds to the Nyq. freq. * Since we do not get a perfect filter => must lower the cutoff freq some more. * For example, step PI/(2*RATE_MULTIPLIER) corresponds to cutoff freq = sample rate / 4; * With -samplerate 48000, cutoff freq is ca 12kHz while the Nyq. freq is 24kHz. * With -samplerate 96000, cutoff freq is ca 24kHz while the Nyq. freq is 48kHz. * For a steeper, more efficient filter, increase FILTER_LENGTH at the expense of CPU usage. */ #define FILTER_STEP (M_PI / 2 / RATE_MULTIPLIER) /* Distribute symmetrically on x axis; center has x=0 if length is odd */ for (i = 0, x = (0.5 - FILTER_LENGTH / 2.) * FILTER_STEP; i < FILTER_LENGTH; i++, x += FILTER_STEP) { if (x == 0) m_ampl[i] = 1; else m_ampl[i] = sin(x) / x; } #else /* Trivial average filter with poor frequency cutoff properties; * First zero (frequency where amplification=0) = sample rate / filter length * Cutoff frequency approx <= first zero / 2 */ for (i = 0, i < FILTER_LENGTH; i++) m_ampl[i] = 1; #endif save_item(NAME(m_level)); save_item(NAME(m_composed_volume)); save_item(NAME(m_composed_sample_index)); save_item(NAME(m_channel_last_sample_time)); save_item(NAME(m_interm_sample_index)); save_item(NAME(m_last_update_time)); save_item(NAME(m_prevx)); save_item(NAME(m_prevy)); machine().save().register_postload(save_prepost_delegate(FUNC(speaker_sound_device::speaker_postload), this)); }
static void recompute_parameters(crtc_ega_t *crtc_ega, int postload) { if (crtc_ega->intf != NULL) { UINT16 hsync_on_pos, hsync_off_pos, vsync_on_pos, vsync_off_pos; /* compute the screen sizes */ UINT16 horiz_pix_total = (crtc_ega->horiz_char_total + 5) * crtc_ega->hpixels_per_column; UINT16 vert_pix_total = crtc_ega->vert_total + 1; /* determine the visible area, avoid division by 0 */ UINT16 max_visible_x = ( crtc_ega->horiz_disp + 1 ) * crtc_ega->hpixels_per_column - 1; UINT16 max_visible_y = crtc_ega->vert_disp_end; /* determine the syncing positions */ int horiz_sync_char_width = ( crtc_ega->horiz_retr_end + 1 ) - ( crtc_ega->horiz_retr_start & 0x1f ); int vert_sync_pix_width = crtc_ega->vert_retr_end - ( crtc_ega->vert_retr_start & 0x0f ); if (horiz_sync_char_width <= 0) horiz_sync_char_width += 0x10; if (vert_sync_pix_width <= 0) vert_sync_pix_width += 0x10; hsync_on_pos = crtc_ega->horiz_retr_start * crtc_ega->hpixels_per_column; hsync_off_pos = hsync_on_pos + (horiz_sync_char_width * crtc_ega->hpixels_per_column); vsync_on_pos = crtc_ega->vert_retr_start; /* + 1 ?? */ vsync_off_pos = vsync_on_pos + vert_sync_pix_width; /* the Commodore PET computers program a horizontal synch pulse that extends past the scanline width. I assume that the real device will clamp it */ if (hsync_off_pos > horiz_pix_total) hsync_off_pos = horiz_pix_total; if (vsync_off_pos > vert_pix_total) vsync_off_pos = vert_pix_total; /* update only if screen parameters changed, unless we are coming here after loading the saved state */ if (postload || (horiz_pix_total != crtc_ega->horiz_pix_total) || (vert_pix_total != crtc_ega->vert_pix_total) || (max_visible_x != crtc_ega->max_visible_x) || (max_visible_y != crtc_ega->max_visible_y) || (hsync_on_pos != crtc_ega->hsync_on_pos) || (vsync_on_pos != crtc_ega->vsync_on_pos) || (hsync_off_pos != crtc_ega->hsync_off_pos) || (vsync_off_pos != crtc_ega->vsync_off_pos)) { /* update the screen if we have valid data */ if ((horiz_pix_total > 0) && (max_visible_x < horiz_pix_total) && (vert_pix_total > 0) && (max_visible_y < vert_pix_total) && (hsync_on_pos <= horiz_pix_total) && (vsync_on_pos <= vert_pix_total) && (hsync_on_pos != hsync_off_pos)) { rectangle visarea; attoseconds_t refresh = HZ_TO_ATTOSECONDS(crtc_ega->clock) * (crtc_ega->horiz_char_total + 1) * vert_pix_total; visarea.min_x = 0; visarea.min_y = 0; visarea.max_x = max_visible_x; visarea.max_y = max_visible_y; if (LOG) logerror("CRTC_EGA config screen: HTOTAL: 0x%x VTOTAL: 0x%x MAX_X: 0x%x MAX_Y: 0x%x HSYNC: 0x%x-0x%x VSYNC: 0x%x-0x%x Freq: %ffps\n", horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, hsync_on_pos, hsync_off_pos - 1, vsync_on_pos, vsync_off_pos - 1, 1 / ATTOSECONDS_TO_DOUBLE(refresh)); crtc_ega->screen->configure(horiz_pix_total, vert_pix_total, visarea, refresh); crtc_ega->has_valid_parameters = TRUE; } else crtc_ega->has_valid_parameters = FALSE; crtc_ega->horiz_pix_total = horiz_pix_total; crtc_ega->vert_pix_total = vert_pix_total; crtc_ega->max_visible_x = max_visible_x; crtc_ega->max_visible_y = max_visible_y; crtc_ega->hsync_on_pos = hsync_on_pos; crtc_ega->hsync_off_pos = hsync_off_pos; crtc_ega->vsync_on_pos = vsync_on_pos; crtc_ega->vsync_off_pos = vsync_off_pos; update_de_changed_timer(crtc_ega); update_hsync_changed_timers(crtc_ega); update_vsync_changed_timers(crtc_ega); update_vblank_changed_timers(crtc_ega); } } }
static void recompute_parameters(mc6845_t *mc6845, int postload) { if (mc6845->intf != NULL) { UINT16 hsync_on_pos, hsync_off_pos, vsync_on_pos, vsync_off_pos; /* compute the screen sizes */ UINT16 horiz_pix_total = (mc6845->horiz_char_total + 1) * mc6845->hpixels_per_column; UINT16 vert_pix_total = (mc6845->vert_char_total + 1) * (mc6845->max_ras_addr + 1) + mc6845->vert_total_adj; /* determine the visible area, avoid division by 0 */ UINT16 max_visible_x = mc6845->horiz_disp * mc6845->hpixels_per_column - 1; UINT16 max_visible_y = mc6845->vert_disp * (mc6845->max_ras_addr + 1) - 1; /* determine the syncing positions */ UINT8 horiz_sync_char_width = mc6845->sync_width & 0x0f; UINT8 vert_sync_pix_width = supports_vert_sync_width[mc6845->device_type] ? (mc6845->sync_width >> 4) & 0x0f : 0x10; if (horiz_sync_char_width == 0) horiz_sync_char_width = 0x10; if (vert_sync_pix_width == 0) vert_sync_pix_width = 0x10; /* determine the transparent update cycle time, 1 update every 4 character clocks */ mc6845->upd_time = attotime::from_hz(mc6845->clock) * (4 * mc6845->hpixels_per_column); hsync_on_pos = mc6845->horiz_sync_pos * mc6845->hpixels_per_column; hsync_off_pos = hsync_on_pos + (horiz_sync_char_width * mc6845->hpixels_per_column); vsync_on_pos = mc6845->vert_sync_pos * (mc6845->max_ras_addr + 1); vsync_off_pos = vsync_on_pos + vert_sync_pix_width; /* the Commodore PET computers program a horizontal synch pulse that extends past the scanline width. I assume that the real device will clamp it */ if (hsync_off_pos > horiz_pix_total) hsync_off_pos = horiz_pix_total; if (vsync_off_pos > vert_pix_total) vsync_off_pos = vert_pix_total; /* update only if screen parameters changed, unless we are coming here after loading the saved state */ if (postload || (horiz_pix_total != mc6845->horiz_pix_total) || (vert_pix_total != mc6845->vert_pix_total) || (max_visible_x != mc6845->max_visible_x) || (max_visible_y != mc6845->max_visible_y) || (hsync_on_pos != mc6845->hsync_on_pos) || (vsync_on_pos != mc6845->vsync_on_pos) || (hsync_off_pos != mc6845->hsync_off_pos) || (vsync_off_pos != mc6845->vsync_off_pos)) { /* update the screen if we have valid data */ if ((horiz_pix_total > 0) && (max_visible_x < horiz_pix_total) && (vert_pix_total > 0) && (max_visible_y < vert_pix_total) && (hsync_on_pos <= horiz_pix_total) && (vsync_on_pos <= vert_pix_total) && (hsync_on_pos != hsync_off_pos)) { rectangle visarea; attoseconds_t refresh = HZ_TO_ATTOSECONDS(mc6845->clock) * (mc6845->horiz_char_total + 1) * vert_pix_total; visarea.min_x = 0; visarea.min_y = 0; visarea.max_x = max_visible_x; visarea.max_y = max_visible_y; if (LOG) logerror("M6845 config screen: HTOTAL: 0x%x VTOTAL: 0x%x MAX_X: 0x%x MAX_Y: 0x%x HSYNC: 0x%x-0x%x VSYNC: 0x%x-0x%x Freq: %ffps\n", horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, hsync_on_pos, hsync_off_pos - 1, vsync_on_pos, vsync_off_pos - 1, 1 / ATTOSECONDS_TO_DOUBLE(refresh)); if ( mc6845->screen != NULL ) mc6845->screen->configure(horiz_pix_total, vert_pix_total, visarea, refresh); mc6845->has_valid_parameters = TRUE; } else mc6845->has_valid_parameters = FALSE; mc6845->horiz_pix_total = horiz_pix_total; mc6845->vert_pix_total = vert_pix_total; mc6845->max_visible_x = max_visible_x; mc6845->max_visible_y = max_visible_y; mc6845->hsync_on_pos = hsync_on_pos; mc6845->hsync_off_pos = hsync_off_pos; mc6845->vsync_on_pos = vsync_on_pos; mc6845->vsync_off_pos = vsync_off_pos; } }
static DEVICE_START( speaker ) { speaker_state *sp = get_safe_token(device); const speaker_interface *intf = (const speaker_interface *) device->static_config(); int i; double x; sp->channel = device->machine().sound().stream_alloc(*device, 0, 1, device->machine().sample_rate(), sp, speaker_sound_update); if (intf != NULL) { assert(intf->num_level > 1); assert(intf->levels != NULL); sp->num_levels = intf->num_level; sp->levels = intf->levels; } else { sp->num_levels = 2; sp->levels = default_levels; } sp->level = 0; for (i = 0; i < FILTER_LENGTH; i++) sp->composed_volume[i] = 0; sp->composed_sample_index = 0; sp->last_update_time = device->machine().time(); sp->channel_sample_period = HZ_TO_ATTOSECONDS(device->machine().sample_rate()); sp->channel_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(sp->channel_sample_period); sp->interm_sample_period = sp->channel_sample_period / RATE_MULTIPLIER; sp->interm_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(sp->interm_sample_period); sp->channel_last_sample_time = sp->channel->sample_time(); sp->channel_next_sample_time = sp->channel_last_sample_time + attotime(0, sp->channel_sample_period); sp->next_interm_sample_time = sp->channel_last_sample_time + attotime(0, sp->interm_sample_period); sp->interm_sample_index = 0; /* Note: To avoid time drift due to floating point inaccuracies, * it is good if the speaker time synchronizes itself with the stream timing regularly. */ /* Compute filter kernel; */ /* (Done for each device though the data is shared... * No problem really, but should be done as part of system init if I knew how) */ #if 1 /* This is an approximated sinc (a perfect sinc makes an ideal low-pass filter). * FILTER_STEP determines the cutoff frequency, * which should be below the Nyquist freq, i.e. half the sample rate. * Smaller step => kernel extends in time domain => lower cutoff freq * In this case, with sinc, filter step PI corresponds to the Nyq. freq. * Since we do not get a perfect filter => must lower the cutoff freq some more. * For example, step PI/(2*RATE_MULTIPLIER) corresponds to cutoff freq = sample rate / 4; * With -samplerate 48000, cutoff freq is ca 12kHz while the Nyq. freq is 24kHz. * With -samplerate 96000, cutoff freq is ca 24kHz while the Nyq. freq is 48kHz. * For a steeper, more efficient filter, increase FILTER_LENGTH at the expense of CPU usage. */ #define FILTER_STEP (M_PI / 2 / RATE_MULTIPLIER) /* Distribute symmetrically on x axis; center has x=0 if length is odd */ for (i = 0, x = (0.5 - FILTER_LENGTH / 2.) * FILTER_STEP; i < FILTER_LENGTH; i++, x += FILTER_STEP) { if (x == 0) ampl[i] = 1; else ampl[i] = sin(x) / x; } #else /* Trivial average filter with poor frequency cutoff properties; * First zero (frequency where amplification=0) = sample rate / filter length * Cutoff frequency approx <= first zero / 2 */ for (i = 0, i < FILTER_LENGTH; i++) ampl[i] = 1; #endif }
void mc6845_device::recompute_parameters(bool postload) { UINT16 hsync_on_pos, hsync_off_pos, vsync_on_pos, vsync_off_pos; UINT16 video_char_height = m_max_ras_addr + 1; // fix garbage at the bottom of the screen (eg victor9k) // Would be useful for 'interlace and video' mode support... // UINT16 frame_char_height = (MODE_INTERLACE_AND_VIDEO ? m_max_ras_addr / 2 : m_max_ras_addr) + 1; /* compute the screen sizes */ UINT16 horiz_pix_total = (m_horiz_char_total + 1) * m_hpixels_per_column; UINT16 vert_pix_total = (m_vert_char_total + 1) * video_char_height + m_vert_total_adj; /* determine the visible area, avoid division by 0 */ UINT16 max_visible_x = m_horiz_disp * m_hpixels_per_column - 1; UINT16 max_visible_y = m_vert_disp * video_char_height - 1; /* determine the syncing positions */ UINT8 horiz_sync_char_width = m_sync_width & 0x0f; UINT8 vert_sync_pix_width = m_supports_vert_sync_width ? (m_sync_width >> 4) & 0x0f : 0x10; if (horiz_sync_char_width == 0) horiz_sync_char_width = 0x10; if (vert_sync_pix_width == 0) vert_sync_pix_width = 0x10; /* determine the transparent update cycle time, 1 update every 4 character clocks */ m_upd_time = attotime::from_hz(m_clock) * (4 * m_hpixels_per_column); hsync_on_pos = m_horiz_sync_pos * m_hpixels_per_column; hsync_off_pos = hsync_on_pos + (horiz_sync_char_width * m_hpixels_per_column); vsync_on_pos = m_vert_sync_pos * video_char_height; vsync_off_pos = vsync_on_pos + vert_sync_pix_width; // the Commodore PET computers have a non-standard 20kHz monitor which // requires a wider HSYNC pulse that extends past the scanline width if (hsync_off_pos > horiz_pix_total) hsync_off_pos = horiz_pix_total; if (vsync_on_pos > vert_pix_total) vsync_on_pos = vert_pix_total; if (vsync_off_pos > vert_pix_total) vsync_off_pos = vert_pix_total; /* update only if screen parameters changed, unless we are coming here after loading the saved state */ if (postload || (horiz_pix_total != m_horiz_pix_total) || (vert_pix_total != m_vert_pix_total) || (max_visible_x != m_max_visible_x) || (max_visible_y != m_max_visible_y) || (hsync_on_pos != m_hsync_on_pos) || (vsync_on_pos != m_vsync_on_pos) || (hsync_off_pos != m_hsync_off_pos) || (vsync_off_pos != m_vsync_off_pos)) { /* update the screen if we have valid data */ if ((horiz_pix_total > 0) && (max_visible_x < horiz_pix_total) && (vert_pix_total > 0) && (max_visible_y < vert_pix_total) && (hsync_on_pos <= horiz_pix_total) && (vsync_on_pos <= vert_pix_total) && (hsync_on_pos != hsync_off_pos)) { rectangle visarea; attoseconds_t refresh = HZ_TO_ATTOSECONDS(m_clock) * (m_horiz_char_total + 1) * vert_pix_total; // This doubles the vertical resolution, required for 'interlace and video' mode support. // Tested and works for super80v, which was designed with this in mind (choose green or monochrome colour in config switches). // However it breaks some other drivers (apricot,a6809,victor9k,bbc(mode7)). // So, it is commented out for now. // Also, the mode-register change needs to be added to the changed-parameter tests above. if (MODE_INTERLACE_AND_VIDEO) { //max_visible_y *= 2; //vert_pix_total *= 2; } if(m_show_border_area) visarea.set(0, horiz_pix_total-1, 0, vert_pix_total-1); else visarea.set(0 + m_visarea_adjust_min_x, max_visible_x + m_visarea_adjust_max_x, 0 + m_visarea_adjust_min_y, max_visible_y + m_visarea_adjust_max_y); if (LOG) logerror("M6845 config screen: HTOTAL: 0x%x VTOTAL: 0x%x MAX_X: 0x%x MAX_Y: 0x%x HSYNC: 0x%x-0x%x VSYNC: 0x%x-0x%x Freq: %ffps\n", horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, hsync_on_pos, hsync_off_pos - 1, vsync_on_pos, vsync_off_pos - 1, 1 / ATTOSECONDS_TO_DOUBLE(refresh)); if ( m_screen != NULL ) m_screen->configure(horiz_pix_total, vert_pix_total, visarea, refresh); if(!m_reconfigure_cb.isnull()) m_reconfigure_cb(horiz_pix_total, vert_pix_total, visarea, refresh); m_has_valid_parameters = true; } else m_has_valid_parameters = false; m_horiz_pix_total = horiz_pix_total; m_vert_pix_total = vert_pix_total; m_max_visible_x = max_visible_x; m_max_visible_y = max_visible_y; m_hsync_on_pos = hsync_on_pos; m_hsync_off_pos = hsync_off_pos; m_vsync_on_pos = vsync_on_pos; m_vsync_off_pos = vsync_off_pos; m_line_counter = 0; } }