void cart_unset_alarms(void) { alarm_unset(cartridge_freeze_alarm); alarm_unset(cartridge_nmi_alarm); cart_freeze_alarm_time = CLOCK_MAX; cart_nmi_alarm_time = CLOCK_MAX; }
/*! \brief reset the ACIA */ void myacia_reset(void) { DEBUG_LOG_MESSAGE((acia.log, "reset_myacia")); acia.rs232_status_lines = 0; rs232drv_set_status(acia.fd, acia.rs232_status_lines); acia.cmd = ACIA_CMD_DEFAULT_AFTER_HW_RESET; acia.ctrl = ACIA_CTRL_DEFAULT_AFTER_HW_RESET; acia.ectrl = T232_ECTRL_DEFAULT_AFTER_HW_RESET; set_acia_ticks(); acia.status = ACIA_SR_DEFAULT_AFTER_HW_RESET; acia.in_tx = ACIA_TX_STATE_NO_TRANSMIT; if (acia.fd >= 0) { rs232drv_close(acia.fd); } acia.fd = -1; if (acia.alarm_tx) { alarm_unset(acia.alarm_tx); } if (acia.alarm_rx) { alarm_unset(acia.alarm_rx); } acia.alarm_active_tx = 0; acia.alarm_active_rx = 0; acia_set_int(acia.irq_type, acia.int_num, IK_NONE); acia.irq = 0; }
void ted_snapshot_prepare(void) { ted.fetch_clk = CLOCK_MAX; alarm_unset(ted.raster_fetch_alarm); ted.draw_clk = CLOCK_MAX; alarm_unset(ted.raster_draw_alarm); ted.raster_irq_clk = CLOCK_MAX; alarm_unset(ted.raster_irq_alarm); }
/* Make sure all the VIC-II alarms are removed. This just makes it easier to write functions for loading snapshot modules in other video chips without caring that the VIC-II alarms are dispatched when they really shouldn't be. */ void vicii_snapshot_prepare(void) { vicii.fetch_clk = CLOCK_MAX; alarm_unset(vicii.raster_fetch_alarm); vicii.draw_clk = CLOCK_MAX; alarm_unset(vicii.raster_draw_alarm); vicii.raster_irq_clk = CLOCK_MAX; alarm_unset(vicii.raster_irq_alarm); }
/* * according to Rockwell, all internal registers are cleared, except * for the Timer (1 and 2, counter and latches) and the shift register. */ void viacore_reset(via_context_t *via_context) { int i; /* clear registers */ for (i = 0; i < 4; i++) { via_context->via[i] = 0; } for (i = 4; i < 10; i++) { via_context->via[i] = 0xff; } for (i = 11; i < 16; i++) { via_context->via[i] = 0; } via_context->tal = 0xffff; via_context->t2cl = 0xff; via_context->t2ch = 0xff; via_context->tau = *(via_context->clk_ptr); via_context->tbu = *(via_context->clk_ptr); via_context->read_clk = 0; via_context->ier = 0; via_context->ifr = 0; via_context->pb7 = 0; via_context->pb7x = 0; via_context->pb7o = 0; via_context->pb7xx = 0; via_context->pb7sx = 0; via_context->shift_state = 0; /* disable vice interrupts */ via_context->tai = 0; via_context->tbi = 0; alarm_unset(via_context->t1_alarm); alarm_unset(via_context->t2_alarm); update_myviairq(via_context); via_context->oldpa = 0xff; via_context->oldpb = 0xff; via_context->ca2_state = 1; via_context->cb2_state = 1; (via_context->set_ca2)(via_context, via_context->ca2_state); /* input = high */ (via_context->set_cb2)(via_context, via_context->cb2_state); /* input = high */ if (via_context && via_context->reset) { (via_context->reset)(via_context); } via_context->enabled = 1; }
static void viacore_intt1(CLOCK offset, void *data) { via_context_t *via_context = (via_context_t *)data; #ifdef MYVIA_TIMER_DEBUG if (app_resources.debugFlag) log_message(via_context->log, "myvia timer A interrupt"); #endif if (!(via_context->via[VIA_ACR] & 0x40)) { /* one-shot mode */ #ifdef MYVIA_TIMER_DEBUG log_message(via_context->log, "MYVIA Timer A interrupt -- one-shot mode: next int won't happen"); #endif alarm_unset(via_context->t1_alarm); via_context->tai = 0; } else { /* continuous mode */ /* load counter with latch value */ via_context->tai += via_context->tal + 2; alarm_set(via_context->t1_alarm, via_context->tai); } via_context->ifr |= VIA_IM_T1; update_myviairq(via_context); /* TODO: toggle PB7? */ /*(viaier & VIA_IM_T1) ? 1:0; */ }
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; }
static void midi_suspend(void) { #ifdef DEBUG log_message(midi_log, "suspend"); #endif status = MIDI_STATUS_DEFAULT; intx = 0; if (fd_in >= 0) { mididrv_in_close(); } fd_in = -1; if (fd_out >= 0) { mididrv_out_close(); } fd_out = -1; alarm_unset(midi_alarm); alarm_active = 0; intx = 0; midi_set_int(midi_irq, midi_int_num, 0); irq = 0; }
static void epyxfastload_alarm_handler(CLOCK offset, void *data) { /* Virtual capacitor charged, disable rom */ alarm_unset(epyxrom_alarm); epyxrom_alarm_time = CLOCK_MAX; cart_config_changed_slotmain(2, 2, CMODE_READ); }
void riotcore_reset(riot_context_t *riot_context) { riot_context->riot_io[0] = 0; riot_context->riot_io[1] = 0; riot_context->riot_io[2] = 0; riot_context->riot_io[3] = 0; riot_context->read_clk = 0; alarm_unset(riot_context->alarm); riot_context->old_pa = 0xff; riot_context->old_pb = 0xff; riot_context->r_edgectrl = 0; riot_context->r_irqfl = 0; riot_context->r_irqline = 0; riot_context->set_irq(riot_context, 0, *(riot_context->clk_ptr)); riot_context->r_write_clk = *(riot_context->clk_ptr); riot_context->r_N = 255; riot_context->r_divider = 1; riot_context->r_irqen = 0; riot_context->reset(riot_context); riot_context->enabled = 1; }
static void ata_change_power_mode(ata_drive_t *drv, BYTE value) { if (drv->power == 0x00 && value != 0x00) { drv->busy |= 1; alarm_set(drv->spindle_alarm, maincpu_clk + drv->spinup_time); } if (drv->power != 0x00 && value == 0x00) { drv->busy |= 1; alarm_set(drv->spindle_alarm, maincpu_clk + drv->spindown_time); } if (value == 0x00) { drv->standby = 0; } else { drv->standby = drv->standby_max; } if (value != 0xff) { drv->pos = 0; } if (drv->standby) { alarm_set(drv->standby_alarm, maincpu_clk + 5 * drv->cycles_1s); } else { alarm_unset(drv->standby_alarm); } drv->power = value; }
static void viacore_intt1(CLOCK offset, void *data) { CLOCK rclk; via_context_t *via_context = (via_context_t *)data; rclk = *(via_context->clk_ptr) - offset; #ifdef MYVIA_TIMER_DEBUG if (app_resources.debugFlag) log_message(via_context->log, "myvia timer A interrupt"); #endif if (!(via_context->via[VIA_ACR] & 0x40)) { /* one-shot mode */ #ifdef MYVIA_TIMER_DEBUG log_message(via_context->log, "MYVIA Timer A interrupt -- one-shot mode: next int won't happen"); #endif alarm_unset(via_context->t1_alarm); via_context->tai = 0; } else { /* continuous mode */ /* load counter with latch value */ via_context->tai += via_context->tal + 2; alarm_set(via_context->t1_alarm, via_context->tai); /* Let tau also keep up with the cpu clock this should avoid "% (via_context->tal + 2)" case */ via_context->tau += via_context->tal + 2; } via_context->ifr |= VIA_IM_T1; update_myviairq_rclk(via_context, rclk); /* TODO: toggle PB7? */ /*(viaier & VIA_IM_T1) ? 1:0; */ }
static void kbdbuf_flush_alarm_triggered(CLOCK offset, void *data) { alarm_unset(kbdbuf_flush_alarm); kbdbuf_flush_alarm_time = 0; tokbdbuffer(13); removefromqueue(); }
static void epyxfastload_trigger_access(void) { /* Discharge virtual capacitor, enable rom */ alarm_unset(epyxrom_alarm); epyxrom_alarm_time = maincpu_clk + EPYX_ROM_CYCLES; alarm_set(epyxrom_alarm, epyxrom_alarm_time); cart_config_changed_slotmain(0, 0, CMODE_READ); }
static void ted_timer_t3_store_high(BYTE value) { alarm_unset(ted_t3_alarm); t3_value = (t3_start = (t3_start & 0x00ff) | (value << 8)) << 1; alarm_set(ted_t3_alarm, maincpu_clk + (t3_start == 0 ? 65536 : t3_start) * 2); t3_last_restart = maincpu_clk; t3_running = 1; }
static void joystick_latch_handler(CLOCK offset, void *data) { alarm_unset(joystick_alarm); alarm_context_update_next_pending(joystick_alarm->context); joystick_latch_matrix(offset); joystick_event_record(); }
static void ted_timer_t1_store_low(BYTE value) { alarm_unset(ted_t1_alarm); if (t1_running) { t1_value -= maincpu_clk - t1_last_restart; t1_last_restart = maincpu_clk; } t1_value = (t1_start = (t1_start & 0xff00) | value) << 1; t1_running = 0; }
static void riotcore_int_riot(CLOCK offset, void *data) { riot_context_t *riot_context = (riot_context_t *)data; /* CLOCK rclk = *(riot_context->clk_ptr) - offset; */ alarm_unset(riot_context->alarm); update_irq(riot_context, (BYTE)(riot_context->r_irqfl | 0x80)); }
static void datasette_rewind(void) { if (current_image->mode == DATASETTE_CONTROL_START || current_image->mode == DATASETTE_CONTROL_FORWARD) { alarm_unset(datasette_alarm); datasette_alarm_pending = 0; } alarm_set(datasette_alarm, maincpu_clk + 1000); datasette_alarm_pending = 1; }
void fdc_reset(unsigned int fnum, unsigned int drive_type) { fdc_t *thefdc = &fdc[fnum]; int drive1 = mk_drive1(fnum); disk_image_t *saved_image0, *saved_image1; #ifdef FDC_DEBUG log_message(fdc_log, "fdc_reset: drive %d type=%d\n",fnum, drive_type); #endif saved_image0 = fdc[fnum].realimage; saved_image1 = NULL; /* detach disk images */ if (thefdc->image) { thefdc->wps_change = 0; fdc_detach_image(thefdc->image, fnum + 8); } if (thefdc->num_drives == 2) { saved_image1 = fdc[drive1].realimage; if (fdc[drive1].image) { fdc[drive1].wps_change = 0; fdc_detach_image(fdc[drive1].image, drive1 + 8); } } if (drive_check_old(drive_type)) { thefdc->drive_type = drive_type; thefdc->num_drives = is_drive1(fnum) ? 1 : drive_check_dual(drive_type) ? 2 : 1; thefdc->fdc_state = FDC_RESET0; alarm_set(thefdc->fdc_alarm, drive_clk[fnum] + 20); } else { thefdc->drive_type = DRIVE_TYPE_NONE; alarm_unset(thefdc->fdc_alarm); thefdc->fdc_state = FDC_UNUSED; thefdc->num_drives = 0; } /* re-attach disk images */ if (saved_image0) { #ifdef FDC_DEBUG printf("ieee/fdc.c:fdc_reset dev %d type %d drive 0 re-attach image %p (drive: %p)\n", fnum+8, drive_type, saved_image0, drive_context[fnum]->drive->image); #endif fdc_attach_image(saved_image0, fnum + 8); } if (saved_image1) { #ifdef FDC_DEBUG printf("ieee/fdc.c:fdc_reset dev %d type %d drive 1 re-attach image %p (drive: %p)\n", fnum+8, drive_type, saved_image0, drive_context[drive1]->drive->image); #endif fdc_attach_image(saved_image1, drive1 + 8); } }
/* called by the Freeze Button alarm */ static void cart_freeze_alarm_triggered(CLOCK offset, void *data) { DBG(("cart_freeze_alarm_triggered\n")); alarm_unset(cartridge_freeze_alarm); cart_freeze_alarm_time = CLOCK_MAX; if (cart_freeze_allowed()) { /* c64carthooks.c */ DBG(("cart_trigger_freeze delay 3 cycles\n")); maincpu_set_nmi(cartridge_int_num, IK_NMI); cart_nmi_alarm_time = maincpu_clk + 3; alarm_set(cartridge_nmi_alarm, cart_nmi_alarm_time); } }
static void datasette_rewind(void) { int mode = current_image ? current_image->mode : notape_mode; DBG(("datasette_rewind")); if (mode == DATASETTE_CONTROL_START || mode == DATASETTE_CONTROL_FORWARD) { alarm_unset(datasette_alarm); datasette_alarm_pending = 0; } alarm_set(datasette_alarm, maincpu_clk + 1000); datasette_alarm_pending = 1; }
static void viacore_intt2(CLOCK offset, void *data) { via_context_t *via_context = (via_context_t *)data; #ifdef MYVIA_TIMER_DEBUG if (app_resources.debugFlag) log_message(via_context->log, "MYVIA timer B interrupt."); #endif alarm_unset(via_context->t2_alarm); /*int_clk[I_MYVIAT2] = 0; */ via_context->tbi = 0; via_context->ifr |= VIA_IM_T2; update_myviairq(via_context); }
/* timer reset */ void ciat_reset(ciat_t *state, CLOCK cclk) { CIAT_LOGIN(("%s reset: cclk=%d",state->name, cclk)); /* FIXME? */ state->clk = cclk; state->alarmclk = CLOCK_MAX; state->cnt = 0xffff; state->latch = 0xffff; state->state = 0; alarm_unset(state->alarm); CIAT_LOGOUT(("")); }
static void cap_trigger_access(void) { alarm_unset(stardos_alarm); stardos_alarm_time = CLOCK_MAX; if (cap_voltage < CHARGEMAXIDLE) { stardos_alarm_time = maincpu_clk + 1; alarm_set(stardos_alarm, stardos_alarm_time); } #ifdef DBGSTARDOSCC else if (dbglast != 4) { DBG(("STARDOS: charged (idle) (%d)\n", cap_voltage)); dbglast = 4; } #endif }
/*! \internal \brief Set the handshake (output) lines to the status of the cmd register This function sets the physical handshake lines accordingly to the state of the emulated ACIA cmd register. */ static void acia_set_handshake_lines(void) { switch (acia.cmd & ACIA_CMD_BITS_TRANSMITTER_MASK) { case ACIA_CMD_BITS_TRANSMITTER_NO_RTS: /* unset RTS, we are NOT ready to receive */ acia.rs232_status_lines &= ~RS232_HSO_RTS; if (acia.alarm_active_rx) { /* diable RX alarm */ acia.alarm_active_rx = 0; alarm_unset(acia.alarm_rx); } break; case ACIA_CMD_BITS_TRANSMITTER_BREAK: /* FALL THROUGH */ case ACIA_CMD_BITS_TRANSMITTER_TX_WITH_IRQ: /* FALL THROUGH */ case ACIA_CMD_BITS_TRANSMITTER_TX_WO_IRQ: /* set RTS, we are ready to receive */ acia.rs232_status_lines |= RS232_HSO_RTS; if (!acia.alarm_active_rx) { /* enable RX alarm */ acia.alarm_active_rx = 1; set_acia_ticks(); } break; } if (acia.cmd & ACIA_CMD_BITS_DTR_ENABLE_RECV_AND_IRQ) { /* set DTR, we are ready to transmit and receive */ acia.rs232_status_lines |= RS232_HSO_DTR; } else { /* unset DTR, we are NOT ready to receive or to transmit */ acia.rs232_status_lines &= ~RS232_HSO_DTR; } /* set the RTS and the DTR status */ rs232drv_set_status(acia.fd, acia.rs232_status_lines); }
void alarm_destroy(alarm_t *alarm) { alarm_context_t *context; if (alarm == NULL) return; alarm_unset(alarm); context = alarm->context; if (alarm == context->alarms) context->alarms = alarm->next; if (alarm->next != NULL) alarm->next->prev = alarm->prev; if (alarm->prev != NULL) alarm->prev->next = alarm->next; lib_free(alarm->name); lib_free(alarm); }
/*! \internal \brief Transmit (TX) alarm function This function is called when the transmit alarm fires. It checks if there is any data to send. If there is some, this data is sent to the physical RS232 device. \param offset The clock offset this alarm is executed at. The current implementation of the emulation core does not allow to guarantee that the alarm will fire exactly at the time it was scheduled at. The offset tells the alarm function how many cycles have passed since the time the alarm was scheduled to fire. Thus, (myclk - offset) yiels the clock count which the alarm was scheduled to. \param data Additional data defined in the call to alarm_new(). For the acia implementation, this is always NULL. \remark If we just transmitted a value, the alarm is re-scheduled for the time when the transmission has completed. This way, we ensure that we do not send out faster than a real ACIA could do. \todo If no transmit is in progress (in_tx == ACIA_TX_STATE_NO_TRANSMIT), it is not necessary to schedule a new alarm. */ static void int_acia_tx(CLOCK offset, void *data) { DEBUG_VERBOSE_LOG_MESSAGE((acia.log, "int_acia_tx(offset=%ld, myclk=%d", offset, myclk)); assert(data == NULL); if ((acia.in_tx == ACIA_TX_STATE_DR_WRITTEN) && (acia.fd >= 0)) { rs232drv_putc(acia.fd, acia.txdata); /* tell the status register that the transmit register is empty */ acia.status |= ACIA_SR_BITS_TRANSMIT_DR_EMPTY; /* generate an interrupt if the ACIA was programmed to generate one */ if ((acia.cmd & ACIA_CMD_BITS_TRANSMITTER_MASK) == ACIA_CMD_BITS_TRANSMITTER_TX_WITH_IRQ) { acia_set_int(acia.irq_type, acia.int_num, acia.irq_type); acia.irq = 1; } } if (acia.in_tx != ACIA_TX_STATE_NO_TRANSMIT) { /* * ACIA_TX_STATE_DR_WRITTEN is decremented to ACIA_TX_STATE_TX_STARTED * ACIA_TX_STATE_TX_STARTED is decremented to ACIA_TX_STATE_NO_TRANSMIT */ acia.in_tx--; } if (acia.in_tx != ACIA_TX_STATE_NO_TRANSMIT) { /* re-schedule alarm */ acia.alarm_clk_tx = myclk + acia.ticks; alarm_set(acia.alarm_tx, acia.alarm_clk_tx); acia.alarm_active_tx = 1; } else { alarm_unset(acia.alarm_tx); acia.alarm_active_tx = 0; } }
void vicii_irq_set_raster_line(unsigned int line) { if (line == vicii.raster_irq_line && vicii.raster_irq_clk != CLOCK_MAX) { return; } if (line < (unsigned int)vicii.screen_height) { unsigned int current_line = VICII_RASTER_Y(maincpu_clk); vicii.raster_irq_clk = (VICII_LINE_START_CLK(maincpu_clk) + VICII_RASTER_IRQ_DELAY - INTERRUPT_DELAY + (vicii.cycles_per_line * (line - current_line))); /* Raster interrupts on line 0 are delayed by 1 cycle. */ if (line == 0) { vicii.raster_irq_clk++; } if (line <= current_line) { vicii.raster_irq_clk += (vicii.screen_height * vicii.cycles_per_line); } alarm_set(vicii.raster_irq_alarm, vicii.raster_irq_clk); } else { VICII_DEBUG_RASTER(("update_raster_irq(): " "raster compare out of range ($%04X)!", line)); vicii.raster_irq_clk = CLOCK_MAX; alarm_unset(vicii.raster_irq_alarm); } VICII_DEBUG_RASTER(("update_raster_irq(): " "vicii.raster_irq_clk = %ul, " "line = $%04X, " "vicii.regs[0x1a] & 1 = %d", vicii.raster_irq_clk, line, vicii.regs[0x1a] & 1)); vicii.raster_irq_line = line; }
static void seek_alarm_handler(CLOCK offset, void *data) { pc8477_t *drv = (pc8477_t *)data; int i; for (i = 0; i < 4; i++) { if (drv->fdds[i].seek_pulses < 0) { if (fdd_track0(drv->fdds[i].fdd)) { continue; } fdd_seek_pulse(drv->fdds[i].fdd, 0); drv->fdds[i].seek_pulses++; drv->fdds[i].seeking = 1; if (drv->fdds[i].recalibrating && drv->fdds[i].seek_pulses == 0 && !fdd_track0(drv->fdds[i].fdd)) { drv->st[0] |= PC8477_ST0_EC; } break; } if (drv->fdds[i].seek_pulses > 0) { fdd_seek_pulse(drv->fdds[i].fdd, 1); drv->fdds[i].seek_pulses--; drv->fdds[i].seeking = 1; break; } } if (i == 4) { alarm_unset(drv->seek_alarm); drv->seeking_active = 0; drv->st[0] |= PC8477_ST0_SE; drv->irq = 1; } else { alarm_set(drv->seek_alarm, *drv->mycontext->clk_ptr + STEP_RATE); } }