示例#1
0
        public void TestSTA()
        {
            var rom = AssembleSource($@"
                org 00h
                STA 2477h
                HLT
            ");

            var registers = new CPURegisters();

            registers.A = 0x42;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x42, state.Memory[0x2477]);
            Assert.Equal(0x42, state.Registers.A);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(7 + 13, state.Cycles);
            Assert.Equal(0x03, state.ProgramCounter);
        }
        public void TestDAD_Carry(RegisterPair pair)
        {
            var rom = AssembleSource($@"
                org 00h
                DAD {pair.GetUpperRegister()}
                HLT
            ");

            var registers = new CPURegisters()
            {
                HL     = 0xFFFE,
                [pair] = 0x0005,
            };

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x0005, state.Registers[pair]);
            Assert.Equal(0x0003, state.Registers.HL);

            Assert.False(state.Flags.Zero);
            Assert.False(state.Flags.Sign);
            Assert.False(state.Flags.Parity);
            Assert.True(state.Flags.Carry);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(7 + 10, state.Cycles);
            Assert.Equal(0x01, state.ProgramCounter);
        }
示例#3
0
        public BaseAddressingModeTests()
        {
            addressingMode = new T();

            cpuMemory    = new CPUMemory();
            cpuRegisters = new CPURegisters();
        }
示例#4
0
        public void TestDCR_M_NoFlags()
        {
            var rom = AssembleSource($@"
                org 00h
                DCR M
                HLT
            ");

            var registers = new CPURegisters()
            {
                HL = 0x2477,
            };

            var memory = new byte[16384];

            memory[0x2477] = 0x44;

            var initialState = new CPUConfig()
            {
                Registers  = registers,
                MemorySize = memory.Length,
            };

            var state = Execute(rom, memory, initialState);

            Assert.Equal(0x43, state.Memory[0x2477]);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(7 + 10, state.Cycles);
            Assert.Equal(0x01, state.ProgramCounter);
        }
示例#5
0
        public void TestDCR_NoFlags(Register sourceReg)
        {
            var rom = AssembleSource($@"
                org 00h
                DCR {sourceReg}
                HLT
            ");

            var registers = new CPURegisters()
            {
                [sourceReg] = 0x44,
            };

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x43, state.Registers[sourceReg]);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(7 + 5, state.Cycles);
            Assert.Equal(0x01, state.ProgramCounter);
        }
        public void TestDAD_SP_Carry()
        {
            var rom = AssembleSource($@"
                org 00h
                DAD SP
                HLT
            ");

            var registers = new CPURegisters()
            {
                HL = 0xFFFE,
            };

            var initialState = new CPUConfig()
            {
                Registers    = registers,
                StackPointer = 0x0005,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x0005, state.StackPointer);
            Assert.Equal(0x0003, state.Registers.HL);

            Assert.False(state.Flags.Zero);
            Assert.False(state.Flags.Sign);
            Assert.False(state.Flags.Parity);
            Assert.True(state.Flags.Carry);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(7 + 10, state.Cycles);
            Assert.Equal(0x01, state.ProgramCounter);
        }
        public void Test_ADD_A_A_SignAndParityFlags()
        {
            var rom = AssembleSource($@"
                org 00h
                ADD A, A
                HALT
            ");

            var registers = new CPURegisters();

            registers.A = 0x44;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x88, state.Registers.A);

            Assert.True(state.Flags.Sign);
            Assert.False(state.Flags.Zero);
            Assert.False(state.Flags.HalfCarry);
            Assert.True(state.Flags.ParityOverflow);
            Assert.False(state.Flags.Subtract);
            Assert.False(state.Flags.Carry);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 4, state.Cycles);
            Assert.Equal(0x01, state.Registers.PC);
        }
示例#8
0
        public void TestANA_A_ParityFlag()
        {
            var rom = AssembleSource($@"
                org 00h
                ANA A
                HLT
            ");

            var registers = new CPURegisters();

            registers.A = 0b01101100;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0b01101100, state.Registers.A);

            Assert.False(state.Flags.Zero);
            Assert.False(state.Flags.Sign);
            Assert.True(state.Flags.Parity);
            Assert.False(state.Flags.Carry);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(7 + 4, state.Cycles);
            Assert.Equal(0x01, state.ProgramCounter);
        }
示例#9
0
        public void Test_LD_A_MRR(RegisterPair registerPair)
        {
            var rom = AssembleSource($@"
                org 00h
                LD A, ({registerPair})
                HALT
            ");

            var registers = new CPURegisters();

            registers[registerPair] = 0x2477;

            var memory = new byte[16384];

            memory[0x2477] = 0x42;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, memory, initialState);

            Assert.Equal(0x42, state.Memory[0x2477]);
            Assert.Equal(0x42, state.Registers.A);
            Assert.Equal(0x2477, state.Registers[registerPair]);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 7, state.Cycles);
            Assert.Equal(0x01, state.Registers.PC);
        }
        public void TestADD_ZeroFlag(Register sourceReg)
        {
            var rom = AssembleSource($@"
                org 00h
                ADD {sourceReg}
                HLT
            ");

            var registers = new CPURegisters();

            registers.A          = 0xFE;
            registers[sourceReg] = 0x02;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x00, state.Registers.A);
            Assert.Equal(0x02, state.Registers[sourceReg]);

            Assert.True(state.Flags.Zero);
            Assert.False(state.Flags.Sign);
            Assert.True(state.Flags.Parity);
            Assert.True(state.Flags.Carry);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(7 + 4, state.Cycles);
            Assert.Equal(0x01, state.ProgramCounter);
        }
示例#11
0
        public void TestPUSH(RegisterPair pair)
        {
            var rom = AssembleSource($@"
                org 00h
                PUSH {pair.GetUpperRegister()}
                HLT
            ");

            var registers = new CPURegisters()
            {
                [pair] = 0x2477,
            };

            var initialState = new CPUConfig()
            {
                Registers    = registers,
                StackPointer = 0x3000,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x2477, state.Registers[pair]);
            Assert.Equal(0x00, state.Memory[0x3000]);
            Assert.Equal(0x24, state.Memory[0x2FFF]);
            Assert.Equal(0x77, state.Memory[0x2FFE]);
            Assert.Equal(0x2FFE, state.StackPointer);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(7 + 11, state.Cycles);
            Assert.Equal(0x01, state.ProgramCounter);
        }
示例#12
0
            /// <summary>
            /// Processes the statement with specified cpu context. Returns false if we couldn't read due to invalid memory address.
            /// </summary>
            /// <param name="cpu">The cpu.</param>
            /// <param name="parent">The parent.</param>
            /// <param name="stack">The stack.</param>
            /// <returns></returns>
            internal override bool Process(CPURegisters cpu, StatementBlock parent, List <IntPtr> stack)
            {
                if (!this.Operand1.Process(cpu, parent, stack))
                {
                    return(false);
                }
                IntPtr op1 = stack[stack.Count - 1];

                stack.RemoveAt(stack.Count - 1);

                if (!this.Operand2.Process(cpu, parent, stack))
                {
                    return(false);
                }
                IntPtr op2 = stack[stack.Count - 1];

                stack.RemoveAt(stack.Count - 1);

                ulong op2_t = Main.Is64Bit ? op2.ToUInt64() : op2.ToUInt32();

                IntPtr result = this.Operator.Func(op1, op2_t);

                stack.Add(result);
                return(true);
            }
        public void Test_LD_MNN_A()
        {
            var rom = AssembleSource($@"
                org 00h
                LD (2477h), A
                HALT
            ");

            var registers = new CPURegisters();

            registers.A = 0x42;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x42, state.Memory[0x2477]);
            Assert.Equal(0x42, state.Registers.A);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 13, state.Cycles);
            Assert.Equal(0x03, state.Registers.PC);
        }
        public void TestSTAX(Register destReg, Register destReg2)
        {
            var rom = AssembleSource($@"
                org 00h
                STAX {destReg}
                HLT
            ");

            var registers = new CPURegisters();

            registers.A         = 0x42;
            registers[destReg]  = 0x24;
            registers[destReg2] = 0x77;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x42, state.Memory[0x2477]);
            Assert.Equal(0x42, state.Registers.A);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(7 + 7, state.Cycles);
            Assert.Equal(0x01, state.ProgramCounter);
        }
示例#15
0
        public void TestDCX(RegisterPair pair)
        {
            var rom = AssembleSource($@"
                org 00h
                DCX {pair.GetUpperRegister()}
                DCX {pair.GetUpperRegister()}
                DCX {pair.GetUpperRegister()}
                HLT
            ");

            var registers = new CPURegisters()
            {
                [pair] = 0x3902,
            };

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x38FF, state.Registers[pair]);

            AssertFlagsFalse(state);

            Assert.Equal(4, state.Iterations);
            Assert.Equal(7 + (5 * 3), state.Cycles);
            Assert.Equal(0x03, state.ProgramCounter);
        }
示例#16
0
        public void Test_INC_MIY_NoFlags(int offset)
        {
            var rom = AssembleSource($@"
                org 00h
                INC (IY {(offset < 0 ? '-' : '+')} {Math.Abs(offset)})
                HALT
            ");

            var registers = new CPURegisters()
            {
                IY = 0x2477,
            };

            var memory = new byte[16384];

            memory[0x2477 + offset] = 0x42;

            var initialState = new CPUConfig()
            {
                Registers = registers, Flags = new ConditionFlags()
                {
                    Subtract = true,
                },
            };

            var state = Execute(rom, memory, initialState);

            Assert.Equal(0x43, state.Memory[0x2477 + offset]);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 23, state.Cycles);
            Assert.Equal(0x03, state.Registers.PC);
        }
示例#17
0
        /// <summary>
        /// Writes the native crash log for specified context. It does not actually treat this as a crash, it just writes out to file as if this was a crash.
        /// Warning: plugins may still treat this as a crash and modify registers or perform functions that would happen on crash!
        /// </summary>
        /// <param name="cpu">The cpu context.</param>
        /// <param name="nativeThreadId">The native thread identifier. Set int.MinValue for current thread.</param>
        /// <param name="filePath">The file path to write to (including file name). If file exists it will append.</param>
        /// <exception cref="System.ArgumentNullException">cpu</exception>
        public static bool WriteNativeCrashLog(CPURegisters cpu, int nativeThreadId, string filePath)
        {
            if (cpu == null)
            {
                throw new ArgumentNullException("cpu");
            }

            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentOutOfRangeException("filePath");
            }

            if (nativeThreadId == int.MinValue)
            {
                nativeThreadId = Memory.GetCurrentNativeThreadId();
            }

            int handled = 0;

            try
            {
                var cl = new NativeCrashLog(cpu);
                handled = cl.Write(true, filePath, true);
            }
            catch (Exception ex2)
            {
                Main.Log.Append(ex2);
            }
            return(handled > 0);
        }
示例#18
0
        public void Test_XOR_ParityFlag(Register sourceReg)
        {
            var rom = AssembleSource($@"
                org 00h
                XOR {sourceReg}
                HALT
            ");

            var registers = new CPURegisters();

            registers.A          = 0b01101101;
            registers[sourceReg] = 0b01001001;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0b00100100, state.Registers.A);
            Assert.Equal(0b01001001, state.Registers[sourceReg]);

            Assert.False(state.Flags.Sign);
            Assert.False(state.Flags.Zero);
            Assert.False(state.Flags.HalfCarry);
            Assert.True(state.Flags.ParityOverflow);
            Assert.False(state.Flags.Subtract);
            Assert.False(state.Flags.Carry);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 4, state.Cycles);
            Assert.Equal(0x01, state.Registers.PC);
        }
示例#19
0
        private static void _Hook_Disenchanting(CPURegisters ctx)
        {
            var item        = MemoryObject.FromAddress <TESForm>(Memory.ReadPointer(ctx.R14));
            var enchantment = MemoryObject.FromAddress <EffectSetting>(ctx.SI);

            float skill = 5.0f;
            var   plr   = PlayerCharacter.Instance;

            if (plr != null)
            {
                skill = plr.GetActorValue(ActorValueIndices.Enchanting);
            }

            float enchantmentValue = Memory.InvokeCdeclF(fn_Disenchant, enchantment.Address, 0);

            float xp = Formula_Disenchanting(Math.Max(0, item.GoldValue), enchantmentValue, skill);

            if (xp < 0.0f)
            {
                xp = 0.0f;
            }

            if (Settings.DebugMode > 0)
            {
                WriteToDebugFile("Disenchanting: original XP was " + ctx.XMM2f.ToString(System.Globalization.CultureInfo.InvariantCulture) + " and we replaced it with " + xp.ToString(System.Globalization.CultureInfo.InvariantCulture));
            }

            ctx.XMM2f = xp;
        }
        public void TestMVIToMemory()
        {
            var rom = AssembleSource($@"
                org 00h
                MVI M, 42h
                HLT
            ");

            var registers = new CPURegisters();

            registers[Register.H] = 0x22;
            registers[Register.L] = 0x33;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x42, state.Memory[0x2233]);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(10 + 7, state.Cycles);
            Assert.Equal(0x02, state.ProgramCounter);
        }
示例#21
0
            /// <summary>
            /// Processes the statement with specified cpu context. Returns false if we couldn't read due to invalid memory address.
            /// </summary>
            /// <param name="cpu">The cpu.</param>
            /// <param name="parent">The parent.</param>
            /// <param name="stack">The stack.</param>
            /// <returns></returns>
            internal override bool Process(CPURegisters cpu, StatementBlock parent, List <IntPtr> stack)
            {
                var ptr = this.Func(cpu);

                stack.Add(ptr);
                return(true);
            }
示例#22
0
        public void TestMOVFromRegisterToRegister(Register destReg, Register sourceReg)
        {
            var rom = AssembleSource($@"
                org 00h
                MOV {destReg}, {sourceReg}
                HLT
            ");

            var registers = new CPURegisters();

            registers[sourceReg] = 42;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(42, state.Registers[destReg]);
            Assert.Equal(42, state.Registers[sourceReg]);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(5 + 7, state.Cycles);
            Assert.Equal(0x01, state.ProgramCounter);
        }
示例#23
0
        public void TestADC_A_SignFlag()
        {
            var rom = AssembleSource($@"
                org 00h
                ADC A
                HLT
            ");

            var registers = new CPURegisters();

            registers.A = 0x44;

            var flags = new ConditionFlags()
            {
                Carry = true,
            };

            var initialState = new CPUConfig()
            {
                Registers = registers,
                Flags     = flags,
            };
            var state = Execute(rom, initialState);

            Assert.Equal(0x89, state.Registers.A);

            Assert.False(state.Flags.Zero);
            Assert.True(state.Flags.Sign);
            Assert.False(state.Flags.Parity);
            Assert.False(state.Flags.Carry);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(7 + 4, state.Cycles);
            Assert.Equal(0x01, state.ProgramCounter);
        }
示例#24
0
        private static void _Hook_Enchanting(CPURegisters ctx)
        {
            var item = MemoryObject.FromAddress <TESForm>(Memory.ReadPointer(ctx.R15));
            var soul = MemoryObject.FromAddress <TESForm>(Memory.ReadPointer(Memory.ReadPointer(ctx.BX + 0x18)));

            float skill = 5.0f;
            var   plr   = PlayerCharacter.Instance;

            if (plr != null)
            {
                skill = plr.GetActorValue(ActorValueIndices.Enchanting);
            }
            float xp = Formula_Enchanting(Math.Max(0, item.GoldValue), Math.Max(0, soul.GoldValue), skill);

            if (xp < 0.0f)
            {
                xp = 0.0f;
            }

            if (Settings.DebugMode > 0)
            {
                WriteToDebugFile("Enchanting: original XP was " + ctx.XMM2f.ToString(System.Globalization.CultureInfo.InvariantCulture) + " and we replaced it with " + xp.ToString(System.Globalization.CultureInfo.InvariantCulture));
            }

            ctx.XMM2f = xp;
        }
示例#25
0
        /// <summary>
        /// Unhandled exception filter.
        /// </summary>
        /// <param name="cpu">The cpu context.</param>
        /// <returns></returns>
        internal static bool UnhandledExceptionFilter(CPURegisters cpu)
        {
            int    handled = 0;
            string logmsg  = "Unhandled native exception occurred at " + cpu.IP.ToHexString() + CrashLog.GetAddressInModule(cpu.IP, System.Diagnostics.Process.GetCurrentProcess().Modules, " ") + " on thread " + Memory.GetCurrentNativeThreadId() + "!";

            try
            {
                var cl = new NativeCrashLog(cpu);
                handled = cl.Write(true);

                if (cl.Skipped)
                {
                    logmsg = null;
                }
            }
            catch (Exception ex2)
            {
                Main.Log.Append(ex2);
            }

            if (logmsg != null)
            {
                Log.AppendLine(logmsg);
            }

            return(handled > 0);
        }
示例#26
0
        public string GetSyntax(CPUMemory memory, CPURegisters registers, byte operand1, byte operand2)
        {
            var indexedAddress = (byte)(operand1 + registers.X);

            var address = memory[indexedAddress] | memory[(byte)(indexedAddress + 1)] << 0x08;

            return($"(${operand1:X02},X) @ {indexedAddress:X02} = {address:X04}");
        }
示例#27
0
        public ushort GetAddress(CPUMemory memory, CPURegisters registers, byte operand1, byte operand2, out bool pageBoundaryCrossed)
        {
            var address = registers.PC + (sbyte)operand1;

            pageBoundaryCrossed = (address & 0xFF00) != (registers.PC & 0xFF00);

            return((ushort)address);
        }
示例#28
0
        public string GetSyntax(CPUMemory memory, CPURegisters registers, byte operand1, byte operand2)
        {
            var address = (memory[operand1] | memory[(byte)(operand1 + 1)] << 0x08);

            var indexedAddress = (ushort)(address + registers.Y);

            return($"(${operand1:X02}),Y = {address:X04} @ {indexedAddress:X04}");
        }
示例#29
0
        public ushort GetAddress(CPUMemory memory, CPURegisters registers, byte operand1, byte operand2, out bool pageBoundaryCrossed)
        {
            var address = (operand1 | operand2 << 0x08) + registers.Y;

            pageBoundaryCrossed = (address & 0xFF00) != operand2 << 0x08;

            return((ushort)address);
        }
示例#30
0
 public Memory(Cartridge cartridge, GPU gpu, CPURegisters cpuRegisters, GPURegisters gpuRegisters, Keyboard keyboard)
 {
     this.cartridge    = cartridge;
     this.gpu          = gpu;
     this.cpuRegisters = cpuRegisters;
     this.gpuRegisters = gpuRegisters;
     this.keyboard     = keyboard;
 }
示例#31
0
        public static void SBC(CPURegisters registers, ref byte substractee,
                                    byte substractor,
                                    byte extraSub)
        {
            // Need more range for flags
              int _A = substractee;
              int _B = substractor;
              int _C = extraSub;

              registers.FH = (byte)(((_A & 0x0F) < ((_B & 0x0F) + _C)) ? 1 : 0);
              registers.FC = (byte)((_A < (_B + _C)) ? 1 : 0);

              substractee -= substractor;
              substractee -= extraSub;

              registers.FZ = (byte)((registers.A == 0) ? 1 : 0);
              registers.FN = 1;
        }