static TUI_MENU_CALLBACK(datasette_callback) { if (been_activated) { datasette_control((int)param); } return NULL; }
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; }
inline static void bit_write(void) { CLOCK write_time; BYTE write_gap; write_time = maincpu_clk - last_write_clk; last_write_clk = maincpu_clk; /* C16 TAPs use half the machine clock as base cycle */ if (machine_class == VICE_MACHINE_PLUS4) { write_time = write_time / 2; } if (write_time < (CLOCK)7) { return; } if (write_time < (CLOCK)(255 * 8 + 7)) { write_gap = (BYTE)(write_time / (CLOCK)8); if (fwrite(&write_gap, 1, 1, current_image->fd) < 1) { datasette_control(DATASETTE_CONTROL_STOP); return; } current_image->current_file_seek_position++; } else { write_gap = 0; if (fwrite(&write_gap, 1, 1, current_image->fd) != 1) { log_debug("datasette bit_write failed."); } current_image->current_file_seek_position++; if (current_image->version >= 1) { BYTE long_gap[3]; int bytes_written; long_gap[0] = (BYTE)(write_time & 0xff); long_gap[1] = (BYTE)((write_time >> 8) & 0xff); long_gap[2] = (BYTE)((write_time >> 16) & 0xff); write_time &= 0xffffff; bytes_written = (int)fwrite(long_gap, 1, 3, current_image->fd); current_image->current_file_seek_position += bytes_written; if (bytes_written < 3) { datasette_control(DATASETTE_CONTROL_STOP); return; } } }
void uidatasette_command(HWND hwnd, WPARAM wparam) { switch (wparam) { case IDM_DATASETTE_SETTINGS: uidatasette_settings_dialog(hwnd); break; case IDM_DATASETTE_CONTROL_STOP: datasette_control(DATASETTE_CONTROL_STOP); break; case IDM_DATASETTE_CONTROL_START: datasette_control(DATASETTE_CONTROL_START); break; case IDM_DATASETTE_CONTROL_FORWARD: datasette_control(DATASETTE_CONTROL_FORWARD); break; case IDM_DATASETTE_CONTROL_REWIND: datasette_control(DATASETTE_CONTROL_REWIND); break; case IDM_DATASETTE_CONTROL_RECORD: datasette_control(DATASETTE_CONTROL_RECORD); break; case IDM_DATASETTE_CONTROL_RESET: datasette_control(DATASETTE_CONTROL_RESET); break; case IDM_DATASETTE_RESET_COUNTER: datasette_control(DATASETTE_CONTROL_RESET_COUNTER); break; } }
void ui_datasette_tape_action_cb(GtkWidget *widget, gpointer data) { int val = GPOINTER_TO_INT(data); if (val >= DATASETTE_CONTROL_STOP && val <= DATASETTE_CONTROL_RESET_COUNTER) { datasette_control(val); } else { fprintf(stderr, "Got an impossible Datasette Control action, code %ld (valid range %d-%d)\n", (long)val, DATASETTE_CONTROL_STOP, DATASETTE_CONTROL_RESET_COUNTER); } }
static void advance_pressplayontape(void) { switch (check("PRESS PLAY ON TAPE", AUTOSTART_NOWAIT_BLINK)) { case YES: autostartmode = AUTOSTART_LOADINGTAPE; datasette_control(DATASETTE_CONTROL_START); break; case NO: autostart_disable(); break; case NOT_YET: break; } }
inline static void bit_write(void) { CLOCK write_time; BYTE write_gap; write_time = maincpu_clk - last_write_clk; last_write_clk = maincpu_clk; if (write_time < (CLOCK)7) return; if (write_time < (CLOCK)(255 * 8 + 7)) { write_gap = (BYTE)(write_time / (CLOCK)8); if (fwrite(&write_gap, 1, 1, current_image->fd) < 1) { datasette_control(DATASETTE_CONTROL_STOP); return; } current_image->current_file_seek_position++; } else { write_gap = 0; fwrite(&write_gap, 1, 1, current_image->fd); current_image->current_file_seek_position++; if (current_image->version >= 1) { BYTE long_gap[3]; int bytes_written; long_gap[0] = (BYTE)(write_time & 0xff); long_gap[1] = (BYTE)((write_time >> 8) & 0xff); long_gap[2] = (BYTE)((write_time >> 16) & 0xff); write_time &= 0xffffff; bytes_written = fwrite(long_gap, 1, 3, current_image->fd); current_image->current_file_seek_position += bytes_written; if (bytes_written < 3) { datasette_control(DATASETTE_CONTROL_STOP); return; } } }
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(); }
static MRESULT EXPENTRY pm_datasette(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { switch (msg) { case WM_INITDLG: { int val; WinSendMsg(hwnd, WM_COUNTER, (void*)ui_status.lastTapeCounter, 0); WinSendMsg(hwnd, WM_TAPESTAT, (void*)ui_status.lastTapeCtrlStat, (void*)ui_status.lastTapeStatus); WinShowDlg(hwnd, SS_SPIN, ui_status.lastTapeMotor && ui_status.lastTapeStatus); resources_get_int("DatasetteResetWithCPU", &val); WinCheckButton(hwnd, CB_RESETWCPU, val); resources_get_int("DatasetteZeroGapDelay", &val); WinSetDlgSpinVal(hwnd, SPB_DELAY, (val/100)); resources_get_int("DatasetteSpeedTuning", &val); WinSetDlgSpinVal(hwnd, SPB_GAP, val); } break; case WM_COUNTER: WinSetDlgSpinVal(hwnd, SPB_COUNT, (ULONG)mp1); return FALSE; case WM_TAPESTAT: WinEnableControl(hwnd, PB_RECORD, mp2 && (int)mp1!=DATASETTE_CONTROL_RECORD); WinEnableControl(hwnd, PB_REWIND, mp2 && (int)mp1!=DATASETTE_CONTROL_REWIND); WinEnableControl(hwnd, PB_STOP, mp2 && (int)mp1!=DATASETTE_CONTROL_STOP); WinEnableControl(hwnd, PB_START, mp2 && (int)mp1!=DATASETTE_CONTROL_START); WinEnableControl(hwnd, PB_FORWARD, mp2 && (int)mp1!=DATASETTE_CONTROL_FORWARD); WinEnableControl(hwnd, PB_RESET, mp2!=0); WinEnableControl(hwnd, PB_RESETCNT, mp2!=0); WinEnableControl(hwnd, SPB_COUNT, mp2!=0); if (!mp2) WinShowDlg(hwnd, SS_SPIN, 0); return FALSE; case WM_SPINNING: WinShowDlg(hwnd, SS_SPIN, mp1 && mp2); return FALSE; case WM_COMMAND: switch (LONGFROMMP(mp1)) { case PB_STOP: case PB_START: case PB_FORWARD: case PB_REWIND: case PB_RECORD: case PB_RESET: case PB_RESETCNT: datasette_control(LONGFROMMP(mp1)&0xf); return FALSE; case PB_TATTACH: ViceFileDialog(hwnd, 0x0201, FDS_OPEN_DIALOG); return FALSE; case PB_TDETACH: tape_image_detach(1); return FALSE; } break; case WM_CONTROL: switch (SHORT1FROMMP(mp1)) { case CB_RESETWCPU: toggle("DatasetteResetWithCPU"); break; case SPB_DELAY: if (SHORT2FROMMP(mp1)==SPBN_ENDSPIN) { const ULONG val = WinGetSpinVal((HWND)mp2); resources_set_int("DatasetteZeroGapDelay", val*100); } break; case SPB_GAP: if (SHORT2FROMMP(mp1)==SPBN_ENDSPIN) { const ULONG val = WinGetSpinVal((HWND)mp2); resources_set_int("DatasetteSpeedTuning", val); } break; } break; } return WinDefDlgProc (hwnd, msg, mp1, mp2); }
/* Dispatch all the pending keyboard commands. */ void kbd_flush_commands(void) { int i; if (num_queued_commands == 0) { return; } for (i = 0; i < num_queued_commands; i++) { switch (command_queue[i].type) { case KCMD_HARD_RESET: vsync_suspend_speed_eval(); machine_trigger_reset(MACHINE_RESET_MODE_HARD); break; case KCMD_RESET: vsync_suspend_speed_eval(); machine_trigger_reset(MACHINE_RESET_MODE_SOFT); break; case KCMD_RESTORE_PRESSED: machine_set_restore_key(1); break; case KCMD_RESTORE_RELEASED: machine_set_restore_key(0); break; case KCMD_FREEZE: if (freeze_function != NULL) { freeze_function(); } break; case KCMD_FLIP_NEXT: fliplist_attach_head(8, 1); break; case KCMD_FLIP_PREVIOUS: fliplist_attach_head(8, 0); break; case KCMD_FLIP_ADD: fliplist_add_image(8); break; case KCMD_FLIP_REMOVE: fliplist_remove(-1, NULL); break; case KCMD_TOGGLE_WARP: resources_toggle("WarpMode", NULL); break; case KCMD_MENU: interrupt_maincpu_trigger_trap(menu_trap, (void *)command_queue[i].data); break; case KCMD_TOGGLE_STATUSBAR: if (statusbar_enabled()) { resources_set_int("ShowStatusbar", STATUSBAR_MODE_OFF); } else { resources_set_int("ShowStatusbar", STATUSBAR_MODE_ON); } break; case KCMD_DATASETTE_START: datasette_control(DATASETTE_CONTROL_START); break; case KCMD_DATASETTE_STOP: datasette_control(DATASETTE_CONTROL_STOP); break; case KCMD_DATASETTE_FORWARD: datasette_control(DATASETTE_CONTROL_FORWARD); break; case KCMD_DATASETTE_REWIND: datasette_control(DATASETTE_CONTROL_REWIND); break; case KCMD_DATASETTE_RECORD: datasette_control(DATASETTE_CONTROL_RECORD); break; default: log_error(LOG_DEFAULT, "Unknown keyboard command %d.", (int)command_queue[i].type); } } num_queued_commands = 0; }
static UI_CALLBACK(ui_datasette_control) { int command = vice_ptr_to_int(UI_MENU_CB_PARAM); datasette_control(command); }