public override void _event() { long cycles; m_clk += m_period; cycles = m_clk >> 7; m_clk &= 0x7F; m_seconds++; m_eventContext.schedule(this, cycles, event_phase_t.EVENT_CLOCK_PHI1); }
private void silence() { sample = 0; m_context.cancel(sampleEvent); m_context.cancel(galwayEvent); m_context.schedule(m_xsid.xsidEvent, 0, m_phase); }
public void write(short addr, short data) { if (addr > 0x0f) { return; } regs[addr] = data; if (locked) { return; // Stop program changing time interval } // Sync up timer long cycles; cycles = m_eventContext.getTime(m_accessClk, m_phase); m_accessClk += cycles; ta -= (int)cycles; if (ta == 0) { _event(); } switch (addr) { case 0x4: ta_latch = SIDEndian.endian_16lo8(ta_latch, data); break; case 0x5: ta_latch = SIDEndian.endian_16hi8(ta_latch, data); if ((cra & 0x01) == 0) // Reload timer if stopped { ta = ta_latch; } break; case 0x0e: cra = (short)(data | 0x01); if ((data & 0x10) != 0) { cra &= (~0x10 & 0xff); ta = ta_latch; } m_eventContext.schedule(m_taEvent, (long)ta + 1, m_phase); break; default: break; } }
public override void _event() { long cycles = event_context.getTime(m_rasterClk, event_context.phase); // Cycle already executed check if (cycles == 0) { return; } long delay = 1; int cycle; // Update x raster m_rasterClk += cycles; raster_x += (int)cycles; cycle = (raster_x + 9) % xrasters; raster_x %= xrasters; switch (cycle) { case 0: { // Calculate sprite DMA short y = (short)(raster_y & 0xff); short mask = 1; sprite_expand_y ^= regs[0x17]; for (int i = 1; i < 0x10; i += 2, mask <<= 1) { if (((regs[0x15] & mask) != 0) && (y == regs[i])) { sprite_dma |= mask; sprite_mc_base[i >> 1] = 0; sprite_expand_y &= (short)(~(regs[0x17] & mask) & 0xff); } } delay = 2; if ((sprite_dma & 0x01) != 0) { addrctrl(false); } else { addrctrl(true); // No sprites before next compulsory cycle if ((sprite_dma & 0x1f) == 0) { delay = 9; } } break; } case 1: break; case 2: if ((sprite_dma & 0x02) != 0) { addrctrl(false); } break; case 3: if ((sprite_dma & 0x03) == 0) { addrctrl(true); } break; case 4: if ((sprite_dma & 0x04) != 0) { addrctrl(false); } break; case 5: if ((sprite_dma & 0x06) == 0) { addrctrl(true); } break; case 6: if ((sprite_dma & 0x08) != 0) { addrctrl(false); } break; case 7: if ((sprite_dma & 0x0c) == 0) { addrctrl(true); } break; case 8: if ((sprite_dma & 0x10) != 0) { addrctrl(false); } break; case 9: // IRQ occurred (xraster != 0) if (raster_y == (yrasters - 1)) { vblanking = true; } else { raster_y++; // Trigger raster IRQ if IRQ line reached if (raster_y == raster_irq) { trigger(MOS656X_INTERRUPT_RST); } } if ((sprite_dma & 0x18) == 0) { addrctrl(true); } break; case 10: // Vertical blank (line 0) if (vblanking) { vblanking = lp_triggered = false; raster_y = 0; // Trigger raster IRQ if IRQ in line 0 if (raster_irq == 0) { trigger(MOS656X_INTERRUPT_RST); } } if ((sprite_dma & 0x20) != 0) { addrctrl(false); } // No sprites before next compulsory cycle else if ((sprite_dma & 0xf8) == 0) { delay = 10; } break; case 11: if ((sprite_dma & 0x30) == 0) { addrctrl(true); } break; case 12: if ((sprite_dma & 0x40) != 0) { addrctrl(false); } break; case 13: if ((sprite_dma & 0x60) == 0) { addrctrl(true); } break; case 14: if ((sprite_dma & 0x80) != 0) { addrctrl(false); } break; case 15: delay = 2; if ((sprite_dma & 0xc0) == 0) { addrctrl(true); delay = 5; } break; case 16: break; case 17: delay = 2; if ((sprite_dma & 0x80) == 0) { addrctrl(true); delay = 3; } break; case 18: break; case 19: addrctrl(true); break; case 20: // Start bad line { // In line $30, the DEN bit controls if Bad Lines can occur if (raster_y == first_dma_line) { bad_lines_enabled = (ctrl1 & 0x10) != 0; } // Test for bad line condition bad_line = (raster_y >= first_dma_line) && (raster_y <= last_dma_line) && ((raster_y & 7) == y_scroll) && bad_lines_enabled; if (bad_line) { // DMA starts on cycle 23 addrctrl(false); } delay = 3; break; } case 23: { for (int i = 0; i < sprite_mc_base.Length; i++) //for (int i = 0; i < 8; i++) { if ((sprite_expand_y & (1 << i)) != 0) { sprite_mc_base[i] += 2; } } break; } case 24: { short mask = 1; for (int i = 0; i < sprite_mc_base.Length; i++, mask <<= 1) //for (int i = 0; i < 8; i++, mask <<= 1) { if ((sprite_expand_y & mask) != 0) { sprite_mc_base[i]++; } if ((sprite_mc_base[i] & 0x3f) == 0x3f) { sprite_dma &= (short)(~mask & 0xff); } } delay = 39; break; } case 63: // End DMA - Only get here for non PAL addrctrl(true); delay = xrasters - cycle; break; default: if (cycle < 23) { delay = 23 - cycle; } else if (cycle < 63) { delay = 63 - cycle; } else { delay = xrasters - cycle; } break; } event_context.schedule(this, delay - (event_context.phase == event_phase_t.EVENT_CLOCK_PHI1 ? 0 : 1), m_phase); }
internal void ta_event() { // Timer Modes long cycles; short mode = (short)(cra & 0x21); if (mode == 0x21) { if ((ta--) != 0) { return; } } cycles = event_context.getTime(m_accessClk, m_phase); m_accessClk += cycles; ta = ta_latch; ta_underflow ^= true; // toggle flipflop if ((cra & 0x08) != 0) { // one shot, stop timer A cra &= (~0x01 & 0xff); } else if (mode == 0x01) { // Reset event event_context.schedule(event_ta, (long)ta + 1, m_phase); } trigger(INTERRUPT_TA); // Handle serial port if ((cra & 0x40) != 0) { if (sdr_count != 0) { if ((--sdr_count) == 0) { trigger(INTERRUPT_SP); } } if ((sdr_count == 0) && sdr_buffered) { sdr_out = regs[SDR]; sdr_buffered = false; sdr_count = 16; // Output rate 8 bits at ta / 2 } } switch (crb & 0x61) { case 0x01: tb -= (int)cycles; break; case 0x41: case 0x61: tb_event(); break; } }