void datasette_set_tape_image(tap_t *image) { CLOCK gap; DBG(("datasette_set_tape_image (image present:%s)", image ? "yes" : "no")); current_image = image; last_tap = next_tap = 0; datasette_internal_reset(); if (image != NULL) { /* We need the length of tape for realistic counter. */ current_image->cycle_counter_total = 0; do { gap = datasette_read_gap(1); current_image->cycle_counter_total += gap / 8; } while (gap); current_image->current_file_seek_position = 0; } datasette_set_tape_sense(0); last_tap = next_tap = 0; fullwave = 0; ui_set_tape_status(current_image ? 1 : 0); }
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(); }