static void datasette_internal_reset(void) { int mode = current_image ? current_image->mode : notape_mode; DBG(("datasette_internal_reset (mode:%d)", mode)); if (mode == DATASETTE_CONTROL_START || mode == DATASETTE_CONTROL_FORWARD || mode == DATASETTE_CONTROL_REWIND) { alarm_unset(datasette_alarm); datasette_alarm_pending = 0; } datasette_control(DATASETTE_CONTROL_STOP); if (current_image != NULL) { if (!autostart_ignore_reset) { tap_seek_start(current_image); } current_image->cycle_counter = 0; } datasette_counter_offset = 0; datasette_long_gap_pending = 0; datasette_long_gap_elapsed = 0; datasette_last_direction = 0; motor_stop_clk = 0; datasette_update_ui_counter(); fullwave = 0; }
void datasette_reset_counter(void) { if (current_image == NULL) return; datasette_counter_offset = (1000 + (int) (DS_G * (sqrt((current_image->cycle_counter / (datasette_cycles_per_second / 8.0) * ds_c1) + ds_c2)- ds_c3))) % 1000; datasette_update_ui_counter(); }
static void datasette_read_bit(CLOCK offset, void *data) { double speed_of_tape = DS_V_PLAY; int direction = 1; long gap; alarm_unset(datasette_alarm); datasette_alarm_pending = 0; if (current_image == NULL) return; /* check for delay of motor stop */ if (motor_stop_clk > 0 && maincpu_clk >= motor_stop_clk) { motor_stop_clk = 0; ui_display_tape_motor_status(0); datasette_motor = 0; } if (!datasette_motor) return; switch (current_image->mode) { case DATASETTE_CONTROL_START: direction = 1; speed_of_tape = DS_V_PLAY; if (!datasette_long_gap_pending) datasette_trigger_flux_change(fullwave); break; case DATASETTE_CONTROL_FORWARD: direction = 1; speed_of_tape = DS_RPS_FAST / DS_G * sqrt(4 * PI * DS_D * DS_V_PLAY / datasette_cycles_per_second * 8 * current_image->cycle_counter + 4 * PI * PI * DS_R * DS_R); break; case DATASETTE_CONTROL_REWIND: direction = -1; speed_of_tape = DS_RPS_FAST / DS_G * sqrt(4 * PI * DS_D * DS_V_PLAY / datasette_cycles_per_second * 8 * (current_image->cycle_counter_total - current_image->cycle_counter) + 4 * PI * PI * DS_R * DS_R); break; case DATASETTE_CONTROL_RECORD: case DATASETTE_CONTROL_STOP: return; default: log_error(datasette_log, "Unknown datasette mode."); return; } if (direction + datasette_last_direction == 0) { /* the direction changed; read the gap from file, but use use only the elapsed gap */ gap = datasette_read_gap(direction); datasette_long_gap_pending = datasette_long_gap_elapsed; datasette_long_gap_elapsed = gap - datasette_long_gap_elapsed; } if (datasette_long_gap_pending) { gap = datasette_long_gap_pending; datasette_long_gap_pending = 0; } else { gap = datasette_read_gap(direction); if (gap) datasette_long_gap_elapsed = 0; } if (!gap) { datasette_control(DATASETTE_CONTROL_STOP); return; } if (gap > DATASETTE_MAX_GAP) { datasette_long_gap_pending = gap - DATASETTE_MAX_GAP; gap = DATASETTE_MAX_GAP; } datasette_long_gap_elapsed += gap; datasette_last_direction = direction; if (direction > 0) current_image->cycle_counter += gap / 8; else current_image->cycle_counter -= gap / 8; gap -= offset; if (gap > 0) { alarm_set(datasette_alarm, maincpu_clk + (CLOCK)(gap * (DS_V_PLAY / speed_of_tape))); datasette_alarm_pending = 1; } else { /* If the offset is geater than the gap to the next flux change, the change happend during DMA. Schedule it now. */ alarm_set(datasette_alarm, maincpu_clk); datasette_alarm_pending = 1; } datasette_update_ui_counter(); }