Exemple #1
0
        public MEM(ARM7TDMI cpu)
        {
            this.cpu = cpu;
            this.bus = cpu.bus;

            this.BIOS      = new BIOSSection(cpu);
            this.IO        = cpu.IO;
            this.VRAM      = new VRAMSection(cpu.IO);
            this.GamePak_L = new cROMSection(this, false);
            this.GamePak_H = new cROMSection(this, true);
            this.Backup    = new BackupSection(cpu.DMAChannels[3]);

            this.MemorySections = new IMemorySection[16]
            {
                this.BIOS,
                this.UnusedSection,
                this.eWRAM,
                this.iWRAM,
                this.IO,
                this.PAL,
                this.VRAM,
                this.OAM,

                this.GamePak_L,
                this.GamePak_H,
                this.GamePak_L,
                this.GamePak_H,
                this.GamePak_L,
                this.GamePak_H,
                this.Backup,
                this.Backup
            };
        }
Exemple #2
0
 public static int DivArm(uint[] r, ARM7TDMI cpu)
 {
     /* Manually decompiled from the BIOS (0x3a8) */
     r[3] = r[0];
     r[0] = r[1];
     r[1] = r[3];
     return(3 + Div(r, cpu));
 }
Exemple #3
0
        public static int ArcTan(uint[] r, ARM7TDMI cpu)
        {
            /*
             * Manually decompiled from the BIOS (0x474)
             * Cycles are all 1 cycle per instruction, except mul, I assume 2 cycles per mul (average?)
             * */
            int cycles = 0;

            r[1]    = r[0] * r[0];
            r[1]    = (uint)(((int)r[1]) >> 14); // asr
            r[1]    = (uint)-(int)r[1];
            cycles += 4;

            r[3]    = 0xa9;
            r[3]   *= r[1];
            r[3]    = (uint)(((int)r[3]) >> 14); // asr
            r[3]   += 0x390;
            cycles += 5;

            r[3]   *= r[1];
            r[3]    = (uint)(((int)r[3]) >> 14); // asr
            r[3]   += 0x91c;                     // 2 adds
            cycles += 5;

            r[3]   *= r[1];
            r[3]    = (uint)(((int)r[3]) >> 14); // asr
            r[3]   += 0xfb6;                     // 2 adds
            cycles += 5;

            r[3]   *= r[1];
            r[3]    = (uint)(((int)r[3]) >> 14); // asr
            r[3]   += 0x16aa;                    // 2 adds
            cycles += 5;

            r[3]   *= r[1];
            r[3]    = (uint)(((int)r[3]) >> 14); // asr
            r[3]   += 0x2081;                    // 2 adds
            cycles += 5;

            r[3]   *= r[1];
            r[3]    = (uint)(((int)r[3]) >> 14); // asr
            r[3]   += 0x3651;                    // 2 adds
            cycles += 5;

            r[3]   *= r[1];
            r[3]    = (uint)(((int)r[3]) >> 14); // asr
            r[3]   += 0xa2f9;                    // 2 adds
            cycles += 5;

            r[0]   *= r[3];
            r[0]    = (uint)(((int)r[0]) >> 16); // asr
            cycles += 3;
            return(cycles);
        }
Exemple #4
0
        public APU(ARM7TDMI cpu, Scheduler.Scheduler scheduler)
        {
            this.Channels = new Channel[] { sq1, sq2, wave, noise };

            this.FIFO[0] = this.FIFOA = new FIFOChannel(cpu, 0x0400_00a0);
            this.FIFO[1] = this.FIFOB = new FIFOChannel(cpu, 0x0400_00a4);

            // initial APU events
            scheduler.Push(new Event(FrameSequencerPeriod, this.TickFrameSequencer));
            foreach (Channel ch in this.Channels)
            {
                scheduler.Push(new Event(ch.Period, ch.Tick));
            }
            scheduler.Push(new Event(SamplePeriod, this.ProvideSample));
        }
Exemple #5
0
        public GBA(ushort[] display)
        {
            this.cpu = new ARM7TDMI(this, this.EventQueue);
            this.IO  = this.cpu.IO;
            this.mem = this.cpu.mem;
            this.bus = this.cpu.bus;

            this.apu = new APU(this.cpu, this.EventQueue);
            this.ppu = new PPU(this, display, this.IO);

            this.mem.Init(this.ppu);
            this.IO.Init(this.ppu, this.bus);
            this.IO.Layout(this.cpu, this.apu);

            // this.mem.UseNormattsBIOS();

            this.display = display;
#if THREADED_RENDERING
            this.RenderThread = new Thread(() => ppu.Mainloop());
#endif
        }
Exemple #6
0
 public FIFOChannel(ARM7TDMI cpu, int FIFODATAAddr)
 {
     this.cpu          = cpu;
     this.FIFODATAAddr = FIFODATAAddr;
 }
Exemple #7
0
 public BUS(ARM7TDMI cpu)
 {
     this.cpu = cpu;
 }
Exemple #8
0
        public void Layout(ARM7TDMI cpu, APU apu)
        {
            // ========================== LCD Registers ==========================
            this.Storage[0x00] = this.Storage[0x01] = this.DISPCNT;
            this.Storage[0x02] = this.Storage[0x03] = new DefaultRegister();  // green swap
            this.Storage[0x04] = this.Storage[0x05] = this.DISPSTAT;
            this.Storage[0x06] = this.Storage[0x07] = this.VCOUNT;

            this.Storage[0x08] = this.Storage[0x09] = this.BGCNT[0];
            this.Storage[0x0a] = this.Storage[0x0b] = this.BGCNT[1];
            this.Storage[0x0c] = this.Storage[0x0d] = this.BGCNT[2];
            this.Storage[0x0e] = this.Storage[0x0f] = this.BGCNT[3];

            this.Storage[0x10] = this.Storage[0x11] = this.BGHOFS[0];
            this.Storage[0x12] = this.Storage[0x13] = this.BGVOFS[0];
            this.Storage[0x14] = this.Storage[0x15] = this.BGHOFS[1];
            this.Storage[0x16] = this.Storage[0x17] = this.BGVOFS[1];
            this.Storage[0x18] = this.Storage[0x19] = this.BGHOFS[2];
            this.Storage[0x1a] = this.Storage[0x1b] = this.BGVOFS[2];
            this.Storage[0x1c] = this.Storage[0x1d] = this.BGHOFS[3];
            this.Storage[0x1e] = this.Storage[0x1f] = this.BGVOFS[3];

            this.Storage[0x20] = this.Storage[0x21] = this.BG2PA;
            this.Storage[0x22] = this.Storage[0x23] = this.BG2PB;
            this.Storage[0x24] = this.Storage[0x25] = this.BG2PC;
            this.Storage[0x26] = this.Storage[0x27] = this.BG2PD;

            this.Storage[0x28] = this.Storage[0x29] = this.BG2X.lower;
            this.Storage[0x2a] = this.Storage[0x2b] = this.BG2X.upper;
            this.Storage[0x2c] = this.Storage[0x2d] = this.BG2Y.lower;
            this.Storage[0x2e] = this.Storage[0x2f] = this.BG2Y.upper;

            this.Storage[0x30] = this.Storage[0x31] = this.BG3PA;
            this.Storage[0x32] = this.Storage[0x33] = this.BG3PB;
            this.Storage[0x34] = this.Storage[0x35] = this.BG3PC;
            this.Storage[0x36] = this.Storage[0x37] = this.BG3PD;

            this.Storage[0x38] = this.Storage[0x39] = this.BG3X.lower;
            this.Storage[0x3a] = this.Storage[0x3b] = this.BG3X.upper;
            this.Storage[0x3c] = this.Storage[0x3d] = this.BG3Y.lower;
            this.Storage[0x3e] = this.Storage[0x3f] = this.BG3Y.upper;

            this.Storage[0x40] = this.Storage[0x41] = this.WINH[0];
            this.Storage[0x42] = this.Storage[0x43] = this.WINH[1];

            this.Storage[0x44] = this.Storage[0x45] = this.WINV[0];
            this.Storage[0x46] = this.Storage[0x47] = this.WINV[1];

            this.Storage[0x48] = this.Storage[0x49] = this.WININ;
            this.Storage[0x4a] = this.Storage[0x4b] = this.WINOUT;

            this.Storage[0x4c] = this.Storage[0x4d] = this.MOSAIC;
            this.Storage[0x4e] = this.Storage[0x4f] = this.MasterZeroRegister;  // unused MOSAIC bits, lower half readable

            this.Storage[0x50] = this.Storage[0x51] = this.BLDCNT;
            this.Storage[0x52] = this.Storage[0x53] = this.BLDALPHA;
            this.Storage[0x54] = this.Storage[0x55] = this.BLDY;
            this.Storage[0x56] = this.Storage[0x57] = this.MasterZeroRegister;  // lower half readable

            for (int i = 0x58; i < 0x60; i += 4)
            {
                this.Storage[i]     = this.Storage[i + 1] = this.MasterUnusedRegister.lower;
                this.Storage[i + 2] = this.Storage[i + 3] = this.MasterUnusedRegister.upper;
            }

            // ========================== Sound Registers ==========================
            this.Storage[0x60] = this.Storage[0x61] = new SquareCNT_L(apu.sq1);
            this.Storage[0x62] = this.Storage[0x63] = new SquareCNT_H(apu.sq1);
            this.Storage[0x64] = this.Storage[0x65] = new SquareCNT_X(apu.sq1);
            this.Storage[0x66] = this.Storage[0x67] = this.MasterUnusedRegister.upper;

            this.Storage[0x68] = this.Storage[0x69] = new SquareCNT_H(apu.sq2);
            this.Storage[0x6a] = this.Storage[0x6b] = this.MasterUnusedRegister.upper;
            this.Storage[0x6c] = this.Storage[0x6d] = new SquareCNT_X(apu.sq2);
            this.Storage[0x6e] = this.Storage[0x6f] = this.MasterUnusedRegister.upper;

            this.Storage[0x70] = this.Storage[0x71] = new WaveCNT_L(apu.wave);
            this.Storage[0x72] = this.Storage[0x73] = new WaveCNT_H(apu.wave);
            this.Storage[0x74] = this.Storage[0x75] = new WaveCNT_X(apu.wave);
            this.Storage[0x76] = this.Storage[0x77] = this.MasterUnusedRegister.upper;

            this.Storage[0x78] = this.Storage[0x79] = new NoiseCNT_L(apu.noise);
            this.Storage[0x7a] = this.Storage[0x7b] = this.MasterUnusedRegister.upper;
            this.Storage[0x7c] = this.Storage[0x7d] = new NoiseCNT_H(apu.noise);
            this.Storage[0x7e] = this.Storage[0x7f] = this.MasterUnusedRegister.upper;

            this.Storage[0x80] = this.Storage[0x81] = new SOUNDCNT_L(apu);
            this.Storage[0x82] = this.Storage[0x83] = new SOUNDCNT_H(apu, cpu.Timers[0], cpu.Timers[1]);
            this.Storage[0x84] = this.Storage[0x85] = new SOUNDCNT_X(apu);
            this.Storage[0x86] = this.Storage[0x87] = this.MasterUnusedRegister.upper;
            this.Storage[0x88] = this.Storage[0x89] = new DefaultRegister();  // SOUNDBIAS (unnecessary?)

            this.Storage[0x8a] = this.Storage[0x8b] = this.MasterUnusedRegister.lower;
            this.Storage[0x8c] = this.Storage[0x8d] = this.MasterUnusedRegister.upper;
            this.Storage[0x8e] = this.Storage[0x8f] = this.MasterUnusedRegister.lower;

            for (int i = 0; i < 0x10; i += 2)
            {
                this.Storage[0x90 + i] = this.Storage[0x91 + i] = new WAVE_RAM(apu.wave, i);
            }

            this.Storage[0xa0] = this.Storage[0xa1] = new FIFO_Data(apu.FIFOA, cpu.bus, true);
            this.Storage[0xa2] = this.Storage[0xa3] = new FIFO_Data(apu.FIFOA, cpu.bus, false);
            this.Storage[0xa4] = this.Storage[0xa5] = new FIFO_Data(apu.FIFOB, cpu.bus, true);
            this.Storage[0xa6] = this.Storage[0xa7] = new FIFO_Data(apu.FIFOB, cpu.bus, false);

            for (int i = 0xa8; i < 0xb0; i += 4)
            {
                this.Storage[i]     = this.Storage[i + 1] = this.MasterUnusedRegister.lower;
                this.Storage[i + 2] = this.Storage[i + 3] = this.MasterUnusedRegister.upper;
            }

            // ======================= DMA Transfer Channels =======================
            this.Storage[0xb0] = this.Storage[0xb1] = cpu.DMAChannels[0].DMASAD.lower;
            this.Storage[0xb2] = this.Storage[0xb3] = cpu.DMAChannels[0].DMASAD.upper;
            this.Storage[0xb4] = this.Storage[0xb5] = cpu.DMAChannels[0].DMADAD.lower;
            this.Storage[0xb6] = this.Storage[0xb7] = cpu.DMAChannels[0].DMADAD.upper;
            this.Storage[0xb8] = this.Storage[0xb9] = cpu.DMAChannels[0].DMACNT_L;
            this.Storage[0xba] = this.Storage[0xbb] = cpu.DMAChannels[0].DMACNT_H;

            this.Storage[0xbc] = this.Storage[0xbd] = cpu.DMAChannels[1].DMASAD.lower;
            this.Storage[0xbe] = this.Storage[0xbf] = cpu.DMAChannels[1].DMASAD.upper;
            this.Storage[0xc0] = this.Storage[0xc1] = cpu.DMAChannels[1].DMADAD.lower;
            this.Storage[0xc2] = this.Storage[0xc3] = cpu.DMAChannels[1].DMADAD.upper;
            this.Storage[0xc4] = this.Storage[0xc5] = cpu.DMAChannels[1].DMACNT_L;
            this.Storage[0xc6] = this.Storage[0xc7] = cpu.DMAChannels[1].DMACNT_H;

            this.Storage[0xc8] = this.Storage[0xc9] = cpu.DMAChannels[2].DMASAD.lower;
            this.Storage[0xca] = this.Storage[0xcb] = cpu.DMAChannels[2].DMASAD.upper;
            this.Storage[0xcc] = this.Storage[0xcd] = cpu.DMAChannels[2].DMADAD.lower;
            this.Storage[0xce] = this.Storage[0xcf] = cpu.DMAChannels[2].DMADAD.upper;
            this.Storage[0xd0] = this.Storage[0xd1] = cpu.DMAChannels[2].DMACNT_L;
            this.Storage[0xd2] = this.Storage[0xd3] = cpu.DMAChannels[2].DMACNT_H;

            this.Storage[0xd4] = this.Storage[0xd5] = cpu.DMAChannels[3].DMASAD.lower;
            this.Storage[0xd6] = this.Storage[0xd7] = cpu.DMAChannels[3].DMASAD.upper;
            this.Storage[0xd8] = this.Storage[0xd9] = cpu.DMAChannels[3].DMADAD.lower;
            this.Storage[0xda] = this.Storage[0xdb] = cpu.DMAChannels[3].DMADAD.upper;
            this.Storage[0xdc] = this.Storage[0xdd] = cpu.DMAChannels[3].DMACNT_L;
            this.Storage[0xde] = this.Storage[0xdf] = cpu.DMAChannels[3].DMACNT_H;

            for (int i = 0xe0; i < 0x100; i += 4)
            {
                this.Storage[i]     = this.Storage[i + 1] = this.MasterUnusedRegister.lower;
                this.Storage[i + 2] = this.Storage[i + 3] = this.MasterUnusedRegister.upper;
            }

            // ========================== Timer Registers ==========================
            this.Storage[0x100] = this.Storage[0x101] = cpu.Timers[0].Data;
            this.Storage[0x102] = this.Storage[0x103] = cpu.Timers[0].Control;

            this.Storage[0x104] = this.Storage[0x105] = cpu.Timers[1].Data;
            this.Storage[0x106] = this.Storage[0x107] = cpu.Timers[1].Control;

            this.Storage[0x108] = this.Storage[0x109] = cpu.Timers[2].Data;
            this.Storage[0x10a] = this.Storage[0x10b] = cpu.Timers[2].Control;

            this.Storage[0x10c] = this.Storage[0x10d] = cpu.Timers[3].Data;
            this.Storage[0x10e] = this.Storage[0x10f] = cpu.Timers[3].Control;

            for (int i = 0x110; i < 0x120; i += 4)
            {
                this.Storage[i]     = this.Storage[i + 1] = this.MasterUnusedRegister.lower;
                this.Storage[i + 2] = this.Storage[i + 3] = this.MasterUnusedRegister.upper;
            }

            // ============================ SIO (1) ============================
            this.Storage[0x120] = this.Storage[0x121] = this.SIODATA32.lower;  // shared
            this.Storage[0x122] = this.Storage[0x123] = this.SIODATA32.upper;  // shared
            this.Storage[0x124] = this.Storage[0x125] = new DefaultRegister();
            this.Storage[0x126] = this.Storage[0x127] = new DefaultRegister();
            this.Storage[0x128] = this.Storage[0x129] = this.SIOCNT;
            this.Storage[0x12a] = this.Storage[0x12b] = this.SIODATA8;  // shared

            this.Storage[0x012c] = this.Storage[0x012d] = this.MasterUnusedRegister.lower;
            this.Storage[0x012e] = this.Storage[0x012f] = this.MasterUnusedRegister.upper;

            // =========================== Keypad Input ========================
            this.Storage[0x0130] = this.Storage[0x0131] = this.KEYINPUT;
            this.Storage[0x0132] = this.Storage[0x0133] = this.KEYCNT;

            // ============================ SIO (2) ============================
            this.Storage[0x134] = this.Storage[0x135] = this.RCNT;

            this.Storage[0x136] = this.Storage[0x137] = this.MasterUnusedRegister.upper;  // note offset!
            for (int i = 0x0138; i < 0x140; i += 4)
            {
                this.Storage[i]     = this.Storage[i + 1] = this.MasterUnusedRegister.lower;
                this.Storage[i + 2] = this.Storage[i + 3] = this.MasterUnusedRegister.upper;
            }

            this.Storage[0x140] = this.Storage[0x141] = new DefaultRegister();

            for (int i = 0x0142; i < 0x150; i += 4)
            {
                this.Storage[i]     = this.Storage[i + 1] = this.MasterUnusedRegister.lower;
                this.Storage[i + 2] = this.Storage[i + 3] = this.MasterUnusedRegister.upper;
            }

            this.Storage[0x150] = this.Storage[0x151] = new DefaultRegister();
            this.Storage[0x152] = this.Storage[0x153] = new DefaultRegister();
            this.Storage[0x154] = this.Storage[0x155] = new DefaultRegister();
            this.Storage[0x156] = this.Storage[0x157] = new DefaultRegister();
            this.Storage[0x158] = this.Storage[0x159] = new DefaultRegister();

            this.Storage[0x15a] = this.Storage[0x15b] = this.MasterZeroRegister;
            for (int i = 0x015c; i < 0x200; i += 4)
            {
                this.Storage[i]     = this.Storage[i + 1] = this.MasterUnusedRegister.lower;
                this.Storage[i + 2] = this.Storage[i + 3] = this.MasterUnusedRegister.upper;
            }

            // ========== Interrupt, Waitstate and Power-Down Control ===========
            this.Storage[0x0200] = this.Storage[0x0201] = this.IE;
            this.Storage[0x0202] = this.Storage[0x0203] = this.IF;
            this.Storage[0x0204] = this.Storage[0x0205] = this.WAITCNT;

            this.Storage[0x0206] = this.Storage[0x0207] = this.MasterZeroRegister;
            this.Storage[0x0208] = this.Storage[0x0209] = this.IME;
            this.Storage[0x020a] = this.Storage[0x020b] = this.MasterZeroRegister;

            for (int i = 0x20c; i < 0x300; i += 4)
            {
                this.Storage[i]     = this.Storage[i + 1] = this.MasterUnusedRegister.lower;
                this.Storage[i + 2] = this.Storage[i + 3] = this.MasterUnusedRegister.upper;
            }

            this.Storage[0x0300] = this.Storage[0x0301] = this.HALTCNT;
            this.Storage[0x0302] = this.Storage[0x0303] = this.MasterZeroRegister;

            for (int i = 0x304; i < 0x400; i += 4)
            {
                this.Storage[i]     = this.Storage[i + 1] = this.MasterUnusedRegister.lower;
                this.Storage[i + 2] = this.Storage[i + 3] = this.MasterUnusedRegister.upper;
            }

            for (int i = 0; i < 0x400; i++)
            {
                if (this.Storage[i] is null)
                {
                    this.Error(i.ToString("x4") + " in IORAM not initialized");
                    Console.ReadKey();
                }
            }

            this.InitLCD();
        }
Exemple #9
0
        static int CpuSet(uint[] r, ARM7TDMI cpu)
        {
            int cycles = 0;

            bool FixedSource = (r[2] & 0x0100_0000) > 0;
            bool DataSize    = (r[2] & 0x0400_0000) > 0; // 0: 16 bit, 1: 32 bit
            uint UnitCount   = (r[2] & 0x00f_ffff);

            if (DataSize)
            {
                if (FixedSource)
                {
                    r[3]    = cpu.mem.GetWordAt(r[0]);
                    r[0]   += 4;
                    cycles += 2;
                }

                while (UnitCount-- > 0)
                {
                    if (FixedSource)
                    {
                        // uses STMIA r1!
                        cpu.mem.SetWordAt(r[1], r[3]);
                        r[1]   += 4;
                        cycles += 4;  // branch and instruction fetch, load/store value is in InstructionCycles
                    }
                    else
                    {
                        // uses LDMIA/STMIA rx!
                        r[3]  = cpu.mem.GetWordAt(r[0]);
                        r[0] += 4;
                        cpu.mem.SetWordAt(r[1], r[3]);
                        r[1]   += 4;
                        cycles += 6;  // branch and instruction fetch, load/store value is in InstructionCycles
                    }
                }
            }
            else
            {
                if (FixedSource)
                {
                    r[3]    = cpu.mem.GetHalfWordAt(r[0]);
                    cycles += 2;
                }

                r[5] = 0;
                while (UnitCount-- > 0)
                {
                    if (FixedSource)
                    {
                        cpu.mem.SetHalfWordAt(r[1] + r[5], (ushort)r[3]);
                        r[5]   += 2;
                        cycles += 4;
                    }
                    else
                    {
                        r[3] = cpu.mem.GetHalfWordAt(r[0] + r[5]);
                        cpu.mem.SetHalfWordAt(r[1] + r[5], (ushort)r[3]);
                        r[5]   += 2;
                        cycles += 4;
                    }
                }
            }

            return(cycles);
        }
Exemple #10
0
        public static int Sqrt(uint[] r, ARM7TDMI cpu)
        {
            int  cycles    = 0;
            uint pushed_r4 = r[4];

            /*
             * Manually decompiled from the BIOS (0x404)
             * Cycles are calculated from the ASM (S/N/I all 1 cycle in the BIOS/stack)
             */
            r[12] = r[0];
            r[1]  = 1;

            cycles += 5;

            /* Set r[1] to the smallest power of 2 greater than or equal to sqrt(r[0]) (initial guess) */
            while (r[1] < r[0])
            {
                r[0]  >>= 1;
                r[1]  <<= 1;
                cycles += 6;
            }
            cycles += 6;  // account for first loop

            bool temp;

            do
            {
                r[0] = r[12];
                r[4] = r[1];
                r[3] = 0;

                /* Set r[2] to r[1] times the highest power of 2 such that r[2] <= r[0] */
                r[2] = r[1];

                cycles += 4;
                do
                {
                    temp = r[2] < (r[0] >> 1);
                    if (r[2] <= (r[0] >> 1))
                    {
                        r[2] <<= 1;
                    }

                    cycles += 5;
                }while (temp);

                /* Set r[3] so that r[3] * r[1] is the highest multiple of r[1] less than r[0] */
                do
                {
                    uint carry = (uint)((r[2] <= r[0]) ? 1 : 0);
                    r[3] += r[3] + carry;
                    if (carry == 1)
                    {
                        r[0] -= r[2];
                    }

                    temp = r[2] != r[1];
                    if (temp)
                    {
                        r[2] >>= 1;
                    }

                    cycles += 8;
                }while (temp);

                /* new average */
                r[1]  += r[3];
                r[1] >>= 1;

                cycles += 6;
            }while (r[4] > r[1]);

            r[0] = r[4];
            r[4] = pushed_r4;

            cycles += 8;
            return(cycles);
        }
Exemple #11
0
        public static int Div(uint[] r, ARM7TDMI cpu)
        {
            /* Manually decompiled from the BIOS (0x3b4) */
            int cycles = 0;

            r[3] = r[1] & 0x8000_0000;                                  // 1 cycle
            if ((r[1] & 0x8000_0000) > 0)
            {
                r[1] = (uint)-r[1];                             // 1 cycle
            }
            r[12] = r[3] ^ r[0];                                // 1 cycle
            if ((r[0] & 0x8000_0000) > 0)
            {
                r[0] = (uint)-r[0];                             // 1 cycle
            }
            r[2]    = r[1];                                     // 1 cycle
            cycles += 5;

            // LAB_000003c8
            bool loop;

            do
            {
                loop = r[2] < (r[0] >> 1);                              // 1 cycle
                if (r[2] <= (r[0] >> 1))
                {
                    r[2] <<= 1;                                 // 1 cycle
                }
                cycles += 5;
            }while (loop); // 3 cycles
            cycles -= 3;   // correct for one branch not taken

            // LAB_000003d4
            uint carry;

            do
            {
                carry = (uint)(r[2] <= r[0] ? 1 : 0);                   // 1 cycle
                r[3] += r[3] + carry;                                   // 1 cycle
                if (carry == 1)
                {
                    r[0] -= r[2];                                       // 1 cycle
                }
                loop = r[2] != r[1];                                    // 1 cycle
                if (loop)
                {
                    r[2] >>= 1;                                         // 1 cycle
                }
                cycles += 8;
            }while (loop);                 // 3 cycles
            cycles -= 3;                   // correct for one branch not taken

            r[1] = r[0];                   // 1 cycle
            r[0] = r[3];                   // 1 cycle

            if ((r[12] & 0x8000_0000) > 0) // 1 cycle
            {
                r[0] = (uint)-r[0];        // 1 cycle
                r[1] = (uint)-r[1];        // 1 cycle
            }
            r[12] <<= 1;
            cycles += 5;
            return(cycles);
        }
Exemple #12
0
        public static int ArcTan2(uint[] r, ARM7TDMI cpu)
        {
            /*
             * Manually decompiled from the BIOS (0x04fc)
             * Cycles are all 1 cycle per instruction
             * */
            int cycles = 0;

            void FUN_03b4(uint[] r)
            {
                r[3] = 0x3b4;
                // also account for assignment of r3 and branches
                cycles += Div(r, cpu) + 3;
            }

            void FUN_0470(uint[] r)
            {
                r[3] = 0x474;
                // also account for assignment of r3 and branches
                cycles += ArcTan(r, cpu) + 3;
            }

            //  PUSH r[4], r[5], r[6], r[7], lr
            //  We came from the SWI handler, so lr is always 0x170
            uint pushed_r4 = r[4], pushed_r5 = r[5], pushed_r6 = r[6], pushed_r7 = r[7], pushed_lr = 0x170;

            cycles += 7;

            if (r[1] != 0)
            {
                cycles += 3;
                //  LAB_510:
                if (r[0] != 0)
                {
                    cycles += 3;
                    //  LAB_524:
                    r[2] = r[0] << 14;  //  2 ops
                    r[3] = r[1] << 14;  //  2 ops
                    r[4] = (uint)-r[0];
                    r[5] = (uint)-r[1];
                    r[6] = 0x4000;  //  2 ops
                    r[7] = 0x8000;  //  (r[6] lsl 1)

                    cycles += 9;
                    if ((int)r[1] < 0)
                    {
                        cycles += 3;
                        //  LAB_572:
                        if ((int)r[0] > 0)
                        {
                            cycles += 3;
                            //  LAB_58a:
                            if ((int)r[0] < (int)r[5])
                            {
                                cycles += 3;
                                //  LAB_57a:
                                r[0] = r[2];
                                FUN_03b4(r);
                                FUN_0470(r);
                                r[6] += r[7];
                                r[0]  = r[6] - r[0];
                                //  LAB_59e ...
                                cycles += 3;
                            }
                            else
                            {
                                cycles += 3;
                                // else omitted in asm with branch LAB_59e
                                r[1] = r[0];
                                r[0] = r[3];
                                FUN_03b4(r);
                                FUN_0470(r);
                                r[7] += r[7];
                                r[0] += r[7];
                                //  LAB_59e ...
                                cycles += 4;
                            }
                        }
                        else if ((int)r[4] > (int)r[5])
                        {
                            cycles += 5;
                            // else omitted in asm with branch LAB_59e
                            //  LAB_562:
                            r[1] = r[0];
                            r[0] = r[3];
                            FUN_03b4(r);
                            FUN_0470(r);
                            r[0] += r[7];
                            // LAB_59e ...
                            cycles += 3;
                        }
                        else
                        {
                            cycles += 7;  // _with_ branch
                            // else omitted in asm with branch LAB_59e
                            // LAB_57a
                            r[0] = r[2];
                            FUN_03b4(r);
                            FUN_0470(r);
                            r[6] += r[7];
                            r[0]  = r[6] - r[0];
                            // LAB_59e ...
                            cycles += 3;
                        }
                    }
                    else if ((int)r[0] < 0)
                    {
                        cycles += 5;
                        // else omitted in asm with branch LAB_59e
                        //  LAB_55e:
                        if ((int)r[4] < (int)r[1])
                        {
                            cycles += 3;
                            //  LAB_550:
                            r[0] = r[2];
                            FUN_03b4(r);
                            FUN_0470(r);
                            r[0] = r[6] - r[0];
                            //  LAB_59e ...
                            cycles += 2;
                        }
                        else
                        {
                            cycles += 3;  // no branch
                            // else omitted in asm with branch LAB_59e
                            //  LAB_562:
                            r[1] = r[0];
                            r[0] = r[3];
                            FUN_03b4(r);
                            FUN_0470(r);
                            r[0] += r[7];
                            //  LAB_59e ...
                            cycles += 3;
                        }
                    }
                    else if ((int)r[0] < (int)r[1])
                    {
                        cycles += 7;
                        // else omitted in asm with branch LAB_59e
                        //  LAB_550:
                        r[0] = r[2];
                        FUN_03b4(r);
                        FUN_0470(r);
                        r[0] = r[6] - r[0];
                        //  LAB_59e ...
                        cycles += 2;
                    }
                    else
                    {
                        cycles += 7;  // no branch
                        // else omitted in asm with branch LAB_59e
                        r[1] = r[0];
                        r[0] = r[3];

                        FUN_03b4(r);
                        FUN_0470(r);
                        //  LAB_59e ...
                        cycles += 2;
                    }
                }
                else if ((int)r[1] < 0)
                {
                    cycles += 5;
                    // else omitted in asm with branch LAB_59e
                    //  LAB_51e:
                    r[0] = 0xc000;  //  with LSL
                    //  LAB_59e ...
                    cycles += 2;
                }
                else
                {
                    cycles += 5;   // no branch
                    // else omitted in asm with branch LAB_59e
                    r[0] = 0x4000; //  with LSL
                    //  LAB_59e ...
                    cycles += 2;
                }
            }
            else if ((int)r[0] < 0)
            {
                cycles += 5;
                // else omitted in asm with branch LAB_59e
                //  LAB_50a:
                r[0] = 0x8000;  //  with LSL
                //  LAB_59e ...
                cycles += 2;
            }
            else
            {
                cycles += 5;  // no branch
                // else omitted in asm with branch LAB_59e
                r[0] = 0;
                //  LAB_59e ...
                cycles += 1;
            }


            //  LAB_59e:
            cycles += 2;  // branch in general
            //  POP r[4], r[5], r[6], r[7]
            r[4]    = pushed_r4;
            r[5]    = pushed_r5;
            r[6]    = pushed_r6;
            r[7]    = pushed_r7;
            cycles += 7;
            //  POP r[3]
            r[3]    = pushed_lr;
            cycles += 3;
            //  bx (return)

            cycles += 2;
            return(cycles);
        }
Exemple #13
0
 public cTMCNT_L(ARM7TDMI cpu)
 {
     this.cpu = cpu;
 }