Ejemplo n.º 1
0
        public BgControlRegister(GameboyAdvance gba, LcdController lcd, int bgNumber, UInt32 address)
        {
            this.lcd      = lcd;
            this.bgNumber = bgNumber;

            MemoryRegister8WithSetHook r0 = new MemoryRegister8WithSetHook(gba.Memory, address, true, true);
            MemoryRegister8WithSetHook r1 = new MemoryRegister8WithSetHook(gba.Memory, address + 1, true, true);

            register = new MemoryRegister16(gba.Memory, address, true, true, r0, r1);

            r0.OnSet = (oldValue, newValue) =>
            {
                lcd.Bg[bgNumber].CacheRenderData();
            };

            r1.OnSet = (oldValue, newValue) =>
            {
                // This *should* be 0x1F but it breaks bg on mario kart track 1. Hopefully we can just get rid of tilemap reset and be done with this
                //if ((oldValue & 0x1F) != (newValue & 0x1F))
                {
                    // THIS HAS GOT TO GO! Mario Kart canes it!
                    lcd.Bg[bgNumber].TileMap.Reset();
                }

                lcd.Bg[bgNumber].CacheRenderData();
            };
        }
Ejemplo n.º 2
0
Archivo: Cpu.cs Proyecto: Y2JB/Y2Gba
        public Cpu(GameboyAdvance gba)
        {
            this.Gba            = gba;
            Memory              = gba.Memory;
            InstructionPipeline = new UInt32[Pipeline_Size];
            CalculateArmDecodeLookUpTable();
            CalculateThumbDecodeLookUpTable();
            RegisterConditionalHandlers();

            MemoryRegister8WithSetHook r0 = new MemoryRegister8WithSetHook(gba.Memory, 0x4000204, true, true);
            MemoryRegister8WithSetHook r1 = new MemoryRegister8WithSetHook(gba.Memory, 0x4000205, true, true);

            waitStateControlRegister = new MemoryRegister16(gba.Memory, 0x4000204, true, true, r0, r1);

            Action <byte, byte> waitStateSet = (oldValue, newValue) =>
            {
                //Always make sure Bit 15 is 0 and Read-Only in GBA mode
                //memory_map[WAITCNT + 1] &= ~0x80;

                ushort waitControl = (ushort)(waitStateControlRegister.Value & ~0x80);

                //Determine first access cycles (Non-Sequential)
                switch ((waitControl >> 2) & 0x3)
                {
                case 0x0: nonSequentialAccessTime = 4; break;

                case 0x1: nonSequentialAccessTime = 3; break;

                case 0x2: nonSequentialAccessTime = 2; break;

                case 0x3: nonSequentialAccessTime = 8; break;
                }

                //Determine second access cycles (Sequential)
                switch ((waitControl >> 4) & 0x1)
                {
                case 0x0: sequentialAccessTime = 2; break;

                case 0x1: sequentialAccessTime = 1; break;
                }
            };

            r0.OnSet = waitStateSet;
            r1.OnSet = waitStateSet;
        }
Ejemplo n.º 3
0
        public DisplayControlRegister(GameboyAdvance gba, LcdController lcd)
        {
            this.lcd = lcd;

            MemoryRegister8WithSetHook r0 = new MemoryRegister8WithSetHook(gba.Memory, 0x4000000, true, true);
            MemoryRegister8            r1 = new MemoryRegister8(gba.Memory, 0x4000001, true, true);

            register = new MemoryRegister16(gba.Memory, 0x4000000, true, true, r0, r1);

            r0.OnSet = (oldValue, newValue) =>
            {
                // BgMode changed?
                if ((oldValue & 0x07) != (newValue & 0x07))
                {
                    lcd.Bg[0].CacheRenderData();
                    lcd.Bg[1].CacheRenderData();
                    lcd.Bg[2].CacheRenderData();
                    lcd.Bg[3].CacheRenderData();
                }
            };
        }
Ejemplo n.º 4
0
        public GbaTimer(Timers timers, GameboyAdvance gba, int timerNumber)
        {
            this.timers      = timers;
            this.gba         = gba;
            this.timerNumber = timerNumber;

            FiresOnCycle = 0xFFFFFFFF;

            UInt32 baseAddr = (UInt32)(0x4000100 + (timerNumber * 4));

            TimerValueRegister r0 = new TimerValueRegister(gba, this, gba.Memory, baseAddr);
            TimerValueRegister r1 = new TimerValueRegister(gba, this, gba.Memory, baseAddr + 1);

            TimerValueRegister = new MemoryRegister16(gba.Memory, baseAddr, true, false, r0, r1);

            ReloadValue = new MemoryRegister16(gba.Memory, baseAddr, false, true);

            baseAddr = (UInt32)(0x4000102 + (timerNumber * 4));
            MemoryRegister8WithSetHook reg    = new MemoryRegister8WithSetHook(gba.Memory, baseAddr, true, true);
            MemoryRegister8            unused = new MemoryRegister8(gba.Memory, baseAddr + 1, true, true);

            TimerControlRegister = new MemoryRegister16(gba.Memory, baseAddr, true, true, reg, unused);
            reg.OnSet            = (oldValue, newValue) =>
            {
                CalculateWhichCycleTheTimerWillFire();
                timers.CalculateWhenToNextUpdate();

                // When a timer is enabled, it reloads it's starting value. When it is disabled it just maintains its current values
                bool wasEnabled = ((oldValue & 0x80) != 0);
                bool enabled    = ((newValue & 0x80) != 0);
                if (wasEnabled == false && enabled)
                {
                    startCycle = gba.Cpu.Cycles;

                    timers.ScheduledUpdate();
                    TimerValue = ReloadValue.Value;
                }
            };
        }
Ejemplo n.º 5
0
        public AffineScrollRegister(Memory memory, UInt32 address, bool readable, bool writeable) :
            base()
        {
            MemoryRegister8WithSetHook r0 = new MemoryRegister8WithSetHook(memory, address, false, true);
            MemoryRegister8WithSetHook r1 = new MemoryRegister8WithSetHook(memory, address + 1, false, true);
            MemoryRegister8WithSetHook r2 = new MemoryRegister8WithSetHook(memory, address + 2, false, true);
            AffineNegRegister          r3 = new AffineNegRegister(memory, address + 3, false, true);

            MemoryRegister16 loWord = new MemoryRegister16(memory, address, false, true, r0, r1);
            MemoryRegister16 hiWord = new MemoryRegister16(memory, address + 2, false, true, r2, r3);

            // Whenever a byte of this register is changed, we update the cached value
            // TODO: I don't understand the performance cost of 'capturing' the Value call here....
            Action <byte, byte> updateAction = (oldValue, newValue) => { CachedValue = (int)Value; };

            r0.OnSet = updateAction;
            r1.OnSet = updateAction;
            r2.OnSet = updateAction;
            r3.OnSet = updateAction;

            LoWord = loWord;
            HiWord = hiWord;
        }
Ejemplo n.º 6
0
        public DmaControlRegister(GameboyAdvance gba, DmaChannel channel, UInt32 address)
        {
            this.channel = channel;

            MemoryRegister8            r0 = new MemoryRegister8(gba.Memory, address, true, true);
            MemoryRegister8WithSetHook r1 = new MemoryRegister8WithSetHook(gba.Memory, address + 1, true, true);

            register = new MemoryRegister16(gba.Memory, address, true, true, r0, r1);

            r1.OnSet = (oldValue, newValue) =>
            {
                bool oldEnable = ((oldValue & 0x80) != 0);
                bool newEnable = ((newValue & 0x80) != 0);
                if (oldEnable == false && newEnable == true)
                {
                    // Dma transfers take 2 cycles to start
                    channel.DelayTransfer          = 2;
                    channel.ScheduledUpdateOnCycle = gba.Cpu.Cycles + 2;

                    gba.Scheduler.RefreshSchedule();
                }
            };
        }