Example #1
0
        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;
            }
        }
Example #2
0
        public override short read(short addr)
        {
            long cycles = m_context.getTime(m_accessClk, m_phase);

            // > not for debug
            m_accessClk += cycles;
            if (m_optimisation != 0)
            {
                if (cycles != 0)
                {
                    m_sid.clock((int)cycles);
                }
            }
            else
            {
                while ((cycles--) != 0)
                {
                    m_sid.clock();
                }
            }
            // <
            return((short)m_sid.read(addr));
        }
Example #3
0
        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);
        }
Example #4
0
        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;
            }
        }