예제 #1
0
        public static void check_irp()
        {
            UInt16 irpmask = (UInt16)GBRegs.Sect_keypad.KEYCNT.read();

            if ((irpmask & 0x4000) > 0)
            {
                if ((irpmask & 0x8000) > 0) // logical and -> all mentioned
                {
                    irpmask &= 0x3FF;
                    UInt16 newvalue = (UInt16)((~value) & irpmask);
                    if (newvalue == irpmask)
                    {
                        IRP.set_irp_bit(IRP.IRPMASK_Keypad);
                    }
                }
                else // logical or -> at least one
                {
                    irpmask &= 0x3FF;
                    UInt16 newvalue = (UInt16)((~value) & irpmask);
                    newvalue &= 0x3FF;
                    if (newvalue > 0)
                    {
                        IRP.set_irp_bit(IRP.IRPMASK_Keypad);
                    }
                }
            }
        }
예제 #2
0
        public static void work()
        {
            if (start)
            {
                serialcnt += CPU.newticks;

                if ((!hispeed && serialcnt >= 64) || (hispeed && serialcnt >= 8))
                {
                    if (hispeed)
                    {
                        serialcnt -= 8;
                    }
                    else
                    {
                        serialcnt -= 64;
                    }
                    bitcount++;
                    if (bitcount == bits)
                    {
                        if (IRP_enable)
                        {
                            IRP.set_irp_bit(IRP.IRPMASK_Serial);
                        }
                        GBRegs.Sect_serial.SIOCNT.mask(0xDF7F);
                        start = false;
                    }
                }
            }
        }
예제 #3
0
        private static void nextline()
        {
            line++;
            if (line == 228)
            {
                line = 0;
            }
            GBRegs.Sect_display.VCOUNT.write(line);

            if (line == GBRegs.Sect_display.DISPSTAT_V_Count_Setting.read())
            {
                if (GBRegs.Sect_display.DISPSTAT_V_Counter_IRQ_Enable.on())
                {
                    IRP.set_irp_bit(IRP.IRPMASK_LCD_V_Counter_Match);
                }
                GBRegs.Sect_display.DISPSTAT_V_Counter_flag.write(1);
            }
            else
            {
                GBRegs.Sect_display.DISPSTAT_V_Counter_flag.write(0);
            }
        }
예제 #4
0
        public static void write_gbreg(UInt32 adr, UInt32 value, bool dwaccess)
        {
            if (adr == GBRegs.Sect_display.DISPCNT.address)
            {
                GPU.dispcnt_write();
            }
            if (adr == GBRegs.Sect_display.DISPSTAT.address)
            {
                GPU_Timing.dispstat_write();
            }
            else if (adr == GBRegs.Sect_display.BG2RefX.address)
            {
                GPU.refpoint_update_2x_new();
            }
            else if (adr == GBRegs.Sect_display.BG2RefX.address + 2)
            {
                GPU.refpoint_update_2x_new();
            }
            else if (adr == GBRegs.Sect_display.BG2RefY.address)
            {
                GPU.refpoint_update_2y_new();
            }
            else if (adr == GBRegs.Sect_display.BG2RefY.address + 2)
            {
                GPU.refpoint_update_2y_new();
            }
            else if (adr == GBRegs.Sect_display.BG3RefX.address)
            {
                GPU.refpoint_update_3x_new();
            }
            else if (adr == GBRegs.Sect_display.BG3RefX.address + 2)
            {
                GPU.refpoint_update_3x_new();
            }
            else if (adr == GBRegs.Sect_display.BG3RefY.address)
            {
                GPU.refpoint_update_3y_new();
            }
            else if (adr == GBRegs.Sect_display.BG3RefY.address + 2)
            {
                GPU.refpoint_update_3y_new();
            }

            else if (adr >= GBRegs.Sect_sound.SOUND1CNT_L.address && adr < GBRegs.Sect_sound.FIFO_A.address)
            {
                Sound.set_soundreg(adr);
            }

            else if (adr == GBRegs.Sect_sound.FIFO_A.address)
            {
                SoundDMA.fill_fifo(0, value, dwaccess);
            }
            else if (adr == GBRegs.Sect_sound.FIFO_B.address)
            {
                SoundDMA.fill_fifo(1, value, dwaccess);
            }

            else if (adr == GBRegs.Sect_serial.SIOCNT.address)
            {
                Serial.write_SIOCNT(BitConverter.ToUInt16(GBRegs.data, (int)GBRegs.Sect_serial.SIOCNT.address));
            }

            else if (adr == GBRegs.Sect_timer.TM0CNT_L.address)
            {
                Timer.set_reload(0);
            }
            else if (adr == GBRegs.Sect_timer.TM0CNT_L.address + 2)
            {
                Timer.set_settings(0);
            }
            else if (adr == GBRegs.Sect_timer.TM1CNT_L.address)
            {
                Timer.set_reload(1);
            }
            else if (adr == GBRegs.Sect_timer.TM1CNT_L.address + 2)
            {
                Timer.set_settings(1);
            }
            else if (adr == GBRegs.Sect_timer.TM2CNT_L.address)
            {
                Timer.set_reload(2);
            }
            else if (adr == GBRegs.Sect_timer.TM2CNT_L.address + 2)
            {
                Timer.set_settings(2);
            }
            else if (adr == GBRegs.Sect_timer.TM3CNT_L.address)
            {
                Timer.set_reload(3);
            }
            else if (adr == GBRegs.Sect_timer.TM3CNT_L.address + 2)
            {
                Timer.set_settings(3);
            }

            else if (adr == GBRegs.Sect_dma.DMA0CNT_H.address + 2)
            {
                DMA.set_settings(0);
            }
            else if (adr == GBRegs.Sect_dma.DMA1CNT_H.address + 2)
            {
                DMA.set_settings(1);
            }
            else if (adr == GBRegs.Sect_dma.DMA2CNT_H.address + 2)
            {
                DMA.set_settings(2);
            }
            else if (adr == GBRegs.Sect_dma.DMA3CNT_H.address + 2)
            {
                DMA.set_settings(3);
            }

            else if (adr == GBRegs.Sect_keypad.KEYINPUT.address)
            {
                Joypad.set_reg();
            }

            else if (adr == GBRegs.Sect_system.IME.address)
            {
                IRP.update_IME(BitConverter.ToUInt16(GBRegs.data, (int)GBRegs.Sect_system.IME.address));
            }
            else if (adr == GBRegs.Sect_system.IE.address)
            {
                IRP.update_IE();
            }
            else if (adr == GBRegs.Sect_system.IF.address + 2)
            {
                IRP.clear_irp_bits();
            }

            else if (adr == GBRegs.Sect_system.WAITCNT.address)
            {
                BusTiming.update(BitConverter.ToUInt16(GBRegs.data, (int)GBRegs.Sect_system.WAITCNT.address));
            }
            else if (adr == GBRegs.Sect_system.POSTFLG.address & value == 1)
            {
            }
            else if (adr == GBRegs.Sect_system.HALTCNT.address && !gameboy.loading_state)
            {
                if ((GBRegs.Sect_system.HALTCNT.read() & 0x80) == 0x80)
                {
                    CPU.stop = true;
                }
                else
                {
                    CPU.halt = true;
                }
            }
        }
예제 #5
0
        public static void work()
        {
            // must save here, as dma may reset to zero
            int cputicks = CPU.newticks;

            for (uint i = 0; i < 4; i++)
            {
                if (timers[i].startnow)
                {
                    timers[i].startnow = false;
                    timers[i].value    = timers[i].reload;
                    timers[i].retval   = (UInt16)timers[i].value;
                }
                else if (timers[i].on || timers[i].stopnow)
                {
                    timers[i].stopnow = false;

                    if (!timers[i].countup || i == 0)
                    {
                        if (timers[i].prescale == 1)
                        {
                            timers[i].value += cputicks;
                        }
                        else
                        {
                            timers[i].prescalevalue += cputicks;
                            while (timers[i].prescalevalue >= timers[i].prescale)
                            {
                                timers[i].prescalevalue -= timers[i].prescale;
                                timers[i].value         += 1;
                            }
                        }
                    }

                    while (timers[i].value >= 0x10000)
                    {
                        timers[i].value -= 0x10000;
                        timers[i].value += timers[i].reload;

                        if (i < 2)
                        {
                            SoundDMA.timer_overflow(i);
                        }

                        if (i < 3 && timers[i + 1].countup)
                        {
                            timers[i + 1].value++;
                            timers[i + 1].retval = (UInt16)timers[i].value;
                        }

                        if (timers[i].irp_on)
                        {
                            IRP.set_irp_bit(timers[i].irpmask);
                        }
                    }

                    if (!timers[i].countup)
                    {
                        timers[i].retval = (UInt16)timers[i].value;
                    }
                }
            }
        }
예제 #6
0
        public static void work()
        {
            cycles += CPU.newticks;

            bool runagain = true;

            while (runagain)
            {
                runagain = false;

                switch (gpustate)
                {
                case GPUState.VISIBLE:
                    if (cycles >= 1008)     // 960 is drawing time
                    {
                        runagain = true;
                        cycles  -= 1008;
                        gpustate = GPUState.HBLANK;
                        GBRegs.Sect_display.DISPSTAT_H_Blank_flag.write(1);
                        DMA.new_hblank = true;
                        if (GBRegs.Sect_display.DISPSTAT_H_Blank_IRQ_Enable.on())
                        {
                            IRP.set_irp_bit(IRP.IRPMASK_LCD_H_Blank);
                        }
                        old_dispstat = GBRegs.data[4];

                        GPU.once_per_hblank();
                        GPU.next_line(line);
                    }
                    break;

                case GPUState.HBLANK:
                    if (cycles >= 224)     // 272
                    {
                        runagain = true;
                        cycles  -= 224;
                        nextline();

                        GBRegs.Sect_display.DISPSTAT_H_Blank_flag.write(0);
                        DMA.new_hblank = false;
                        if (line < 160)
                        {
                            gpustate = GPUState.VISIBLE;
                        }
                        else
                        {
                            gpustate = GPUState.VBLANK;
                            GPU.refpoint_update_all();
                            Cheats.apply_cheats();
                            GBRegs.Sect_display.DISPSTAT_V_Blank_flag.write(1);
                            DMA.new_vblank = true;
                            if (GBRegs.Sect_display.DISPSTAT_V_Blank_IRQ_Enable.on())
                            {
                                IRP.set_irp_bit(IRP.IRPMASK_LCD_V_Blank);
                            }
                        }
                        old_dispstat = GBRegs.data[4];
                    }
                    break;

                case GPUState.VBLANK:
                    if (cycles >= 1008)
                    {
                        runagain = true;
                        cycles  -= 1008;
                        gpustate = GPUState.VBLANKHBLANK;
                        GBRegs.Sect_display.DISPSTAT_H_Blank_flag.write(1);
                        //DMA.new_hblank = true; //!!! don't do here!
                        if (GBRegs.Sect_display.DISPSTAT_H_Blank_IRQ_Enable.on())
                        {
                            IRP.set_irp_bit(IRP.IRPMASK_LCD_H_Blank);     // Note that no H-Blank interrupts are generated within V-Blank period. Really?
                        }
                        old_dispstat = GBRegs.data[4];
                    }
                    break;

                case GPUState.VBLANKHBLANK:
                    if (cycles >= 224)
                    {
                        runagain = true;
                        cycles  -= 224;
                        nextline();
                        GBRegs.Sect_display.DISPSTAT_H_Blank_flag.write(0);
                        DMA.new_hblank = false;
                        GPU.once_per_hblank();
                        if (line == 0)
                        {
                            gpio.framecount++;
                            gpio.update_time();
                            gpustate = GPUState.VISIBLE;
                            //GPU.next_line(line);
                            GBRegs.Sect_display.DISPSTAT_V_Blank_flag.write(0);
                            DMA.new_vblank = false;
                        }
                        else
                        {
                            gpustate = GPUState.VBLANK;
                            if (line == 227)
                            {
                                //GBRegs.Sect_display.DISPSTAT_V_Blank_flag.write(0);
                            }
                        }
                        old_dispstat = GBRegs.data[4];
                    }
                    break;
                }
            }
        }
예제 #7
0
        public static void work()
        {
            dma_active = false;
            delayed    = false;

            for (int i = 0; i < 4; i++)
            {
                if (DMAs[i].dMA_Enable)
                {
                    if (DMAs[i].waiting)
                    {
                        check_run(i);
                    }

                    if (DMAs[i].waitTicks > 0)
                    {
                        if (CPU.newticks >= DMAs[i].waitTicks)
                        {
                            DMAs[i].running   = true;
                            DMAs[i].waitTicks = 0;
                        }
                        else
                        {
                            DMAs[i].waitTicks -= CPU.newticks;
                        }
                    }

                    if (DMAs[i].running)
                    {
                        // remember for timing
                        UInt32 sm = Math.Min(15, DMAs[i].addr_source >> 24);
                        UInt32 dm = Math.Min(15, DMAs[i].addr_target >> 24);

                        // eeprom hack
                        cpuDmaCount = (int)DMAs[i].fullcount;

                        dma_active = true;

                        if (DMAs[i].dMA_Transfer_Type)
                        {
                            UInt32 value;
                            if (DMAs[i].addr_source >= 0x02000000)
                            {
                                value = Memory.read_dword(DMAs[i].addr_source);
                                if (!Memory.unreadable)
                                {
                                    last_dma_value   = value;
                                    last_dma_index   = i;
                                    CPU.op_since_dma = 0;
                                }
                                value = last_dma_value;
                            }
                            else
                            {
                                value = last_dma_value;
                            }
                            Memory.write_dword(DMAs[i].addr_target, value);

                            if (DMAs[i].source_Adr_Control == 0 || DMAs[i].source_Adr_Control == 3 || (DMAs[i].addr_source >= 0x08000000 && DMAs[i].addr_source < 0x0E000000))
                            {
                                DMAs[i].addr_source += 4;
                            }
                            else if (DMAs[i].source_Adr_Control == 1)
                            {
                                DMAs[i].addr_source -= 4;
                            }

                            if (DMAs[i].dest_Addr_Control == 0 || (DMAs[i].dest_Addr_Control == 3 && DMAs[i].dMA_Start_Timing != 3))
                            {
                                DMAs[i].addr_target += 4;
                            }
                            else if (DMAs[i].dest_Addr_Control == 1)
                            {
                                DMAs[i].addr_target -= 4;
                            }
                        }
                        else
                        {
                            UInt16 value;
                            if (DMAs[i].addr_source >= 0x02000000)
                            {
                                UInt32 newvalue = Memory.read_word(DMAs[i].addr_source) & 0xFFFF;
                                if (!Memory.unreadable)
                                {
                                    last_dma_value   = (UInt32)newvalue | ((UInt32)newvalue << 16);
                                    last_dma_index   = i;
                                    CPU.op_since_dma = 0;
                                }
                                value = (UInt16)last_dma_value;
                            }
                            else
                            {
                                value = (UInt16)last_dma_value;
                            }
                            value = (UInt16)last_dma_value;
                            Memory.write_word(DMAs[i].addr_target, value);

                            if (DMAs[i].source_Adr_Control == 0 || DMAs[i].source_Adr_Control == 3 || (DMAs[i].addr_source >= 0x08000000 && DMAs[i].addr_source < 0x0E000000))
                            {
                                DMAs[i].addr_source += 2;
                            }
                            else if (DMAs[i].source_Adr_Control == 1)
                            {
                                DMAs[i].addr_source -= 2;
                            }

                            if (DMAs[i].dest_Addr_Control == 0 || (DMAs[i].dest_Addr_Control == 3 && DMAs[i].dMA_Start_Timing != 3))
                            {
                                DMAs[i].addr_target += 2;
                            }
                            else if (DMAs[i].dest_Addr_Control == 1)
                            {
                                DMAs[i].addr_target -= 2;
                            }
                        }

                        debug_dmatranfers++;

                        DMAs[i].count--;

                        // calc timing
                        int ticks;
                        if (DMAs[i].first)
                        {
                            if (DMAs[i].dMA_Transfer_Type)
                            {
                                ticks = 4 + BusTiming.memoryWait32[sm & 15] + BusTiming.memoryWaitSeq32[dm & 15];
                            }
                            else
                            {
                                ticks = 4 + BusTiming.memoryWait[sm & 15] + BusTiming.memoryWaitSeq[dm & 15];
                            }
                            DMAs[i].first = false;
                        }
                        else
                        {
                            if (DMAs[i].dMA_Transfer_Type)
                            {
                                ticks = 2 + BusTiming.memoryWaitSeq32[sm & 15] + BusTiming.memoryWaitSeq32[dm & 15];
                            }
                            else
                            {
                                ticks = 2 + BusTiming.memoryWaitSeq[sm & 15] + BusTiming.memoryWaitSeq[dm & 15];
                            }
                        }
                        CPU.newticks       += ticks;
                        DMAs[i].totalTicks += ticks;

                        if (DMAs[i].count == 0)
                        {
                            DMAs[i].running = false;

                            if (DMAs[i].iRQ_on)
                            {
                                switch (i)
                                {
                                case 0: IRP.set_irp_bit(IRP.IRPMASK_DMA_0); break;

                                case 1: IRP.set_irp_bit(IRP.IRPMASK_DMA_1); break;

                                case 2: IRP.set_irp_bit(IRP.IRPMASK_DMA_2); break;

                                case 3: IRP.set_irp_bit(IRP.IRPMASK_DMA_3); break;
                                }
                            }

                            if (DMAs[i].dMA_Repeat && DMAs[i].dMA_Start_Timing != 0)
                            {
                                DMAs[i].waiting = true;
                                if (DMAs[i].dMA_Start_Timing == 3 && (i == 1 || i == 2))
                                {
                                    DMAs[i].count = 4;
                                }
                                else
                                {
                                    DMAs[i].count = DMAs[i].CNT_L.read();
                                    if (DMAs[i].dest_Addr_Control == 3)
                                    {
                                        DMAs[i].addr_target = DMAs[i].DAD.read();
                                        switch (i)
                                        {
                                        case 0: DMAs[i].addr_target &= 0x07FFFFFF; break;

                                        case 1: DMAs[i].addr_target &= 0x07FFFFFF; break;

                                        case 2: DMAs[i].addr_target &= 0x07FFFFFF; break;

                                        case 3: DMAs[i].addr_target &= 0x0FFFFFFF; break;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                DMAs[i].DMA_Enable.write(0);
                                DMAs[i].dMA_Enable = false;
                            }

#if DEBUG
                            //if (CPU.traclist_ptr > 0 && !DMAs[i].skipdebugout)
                            //{
                            //    CPU.Tracelist[CPU.traclist_ptr - 1].thumbmode = 3;
                            //    CPU.Tracelist[CPU.traclist_ptr - 1].memory01 = (UInt32) DMAs[i].totalTicks;
                            //    CPU.Tracelist[CPU.traclist_ptr - 1].memory02 = DMAs[i].addr_source_save;
                            //}
                            DMAs[i].skipdebugout = false;
#endif
                        }

                        break;
                    }
                }
            }

            new_hblank = false;
            new_vblank = false;
        }