Exemplo n.º 1
0
        public void Run()
        {
            Console.WriteLine($"------------------------------------------------------------------");
            Console.WriteLine($"Run 6502 functional test program with decimal tests disabled");
            Console.WriteLine("Functional test downloaded and compiled from:");
            Console.WriteLine($"------------------------------------------------------------------");

            Console.WriteLine($"Downloading functional test source code from");
            Console.WriteLine("https://github.com/Klaus2m5/6502_65C02_functional_tests");
            Console.WriteLine($"Modifying it to set source code line 'disable_decimal = 0' to 'disable_decimal = 1'");
            Console.WriteLine($"And compiling it to a binary that can be loaded into the 6502 emulator...");

            // Set the download directory to the same directory where current application runs in.
            var currentAssemblyLocation = System.Reflection.Assembly.GetEntryAssembly().Location;
            var downloadDir             = System.IO.Path.GetDirectoryName(currentAssemblyLocation);

            var functionalTestBinary = _functionalTestCompiler.Get6502FunctionalTestBinary(
                disableDecimalTests: true,
                downloadDir: downloadDir
                );

            Console.WriteLine($"Download and compilation complete.");
            Console.WriteLine($"Binary location (as well as .lst file):");
            Console.WriteLine($"{functionalTestBinary}");

            // There is no 2 byte header in the 6502_functional_test.bin file.
            // It's supposed to be loaded to memory at 0x0000, and started at 0x0400
            Console.WriteLine("");
            Console.WriteLine($"Loading binary into emulator memory...");
            ushort loadAddress  = 0x000A;
            ushort startAddress = 0x0400;

            var mem = BinaryLoader.Load(
                functionalTestBinary,
                out ushort loadedAtAddress,
                out int fileLength,
                forceLoadAddress: loadAddress);

            Console.WriteLine($"Loading done.");

            // The rest of the bytes are considered the code
            Console.WriteLine("");
            Console.WriteLine($"Data & code load address:  {loadAddress.ToHex(), 10} ({loadAddress})");
            Console.WriteLine($"Code+data length (bytes):  0x{fileLength, -8:X8} ({fileLength})");
            Console.WriteLine($"Code start address:        {startAddress.ToHex(), 10} ({startAddress})");

            //Console.WriteLine("Press Enter to start");
            //Console.ReadLine();

            // Initialize CPU, set PC to start position
            var computerBuilder = new ComputerBuilder();

            computerBuilder
            .WithCPU()
            .WithStartAddress(0x400)
            .WithMemory(mem)
            //.WithInstructionAboutToBeExecutedEventHandler(OnInstructionToBeExecuted)
            .WithInstructionExecutedEventHandler(OnInstructionExecuted)
            .WithUnknownInstructionEventHandler(OnUnknownOpCodeDetected)
            .WithExecOptions(options =>
            {
                options.ExecuteUntilExecutedInstructionAtPC = 0x336d;
                // A successful run has about 26765880 instructions (the version that was run 2021-02-06, that may change)
                // We increase to almost double, and will exit if not finished then.
                options.MaxNumberOfInstructions           = 50000000;
                options.UnknownInstructionThrowsException = false;
            });

            var computer = computerBuilder.Build();

            Console.WriteLine("");
            Console.WriteLine($"If test logic succeeds, the test program will reach a specific memory location: {computer.DefaultExecOptions.ExecuteUntilExecutedInstructionAtPC.Value.ToHex()}, and the emulator will then stop processing.");
            Console.WriteLine($"If test logic fails, the test program will loop forever at the location the error was found. The emulator will try executing a maximum #instructions {computer.DefaultExecOptions.MaxNumberOfInstructions.Value} before giving up.");
            Console.WriteLine($"If unknown opcode is found, it's logged and ignored, and processing continues on next instruction.");

            // Execute program
            Console.WriteLine("");
            Console.WriteLine("Starting code execution...");

            computer.Run();

            Console.WriteLine("");
            Console.WriteLine("Code execution done.");

            var cpu       = computer.CPU;
            var execState = cpu.ExecState;

            Console.WriteLine("");
            Console.WriteLine($"Last instruction:                  {OutputGen.BuildInstructionString(computer.CPU, computer.Mem, computer.CPU.ExecState.PCBeforeLastOpCodeExecuted.Value)}");
            Console.WriteLine($"CPU state:                         {OutputGen.GetProcessorState(computer.CPU)}");
            Console.WriteLine($"Total # CPU instructions executed: {execState.InstructionsExecutionCount}");
            Console.WriteLine($"Total # CPU cycles consumed:       {execState.CyclesConsumed}");

            Console.WriteLine("");
            // Evaluate success/failure
            if (cpu.PC == computer.DefaultExecOptions.ExecuteUntilExecutedInstructionAtPC.Value)
            {
                Console.WriteLine($"Success!");
                Console.WriteLine($"PC reached expected success memory location: {computer.DefaultExecOptions.ExecuteUntilExecutedInstructionAtPC.Value.ToHex()}");
            }
            else
            {
                Console.WriteLine($"Probably failure");
                Console.WriteLine($"The emulator executer a maximum #instructions {computer.DefaultExecOptions.MaxNumberOfInstructions.Value}, and did not manage to get PC to the configured success location: {computer.DefaultExecOptions.ExecuteUntilExecutedInstructionAtPC.Value.ToHex()}");
                Console.WriteLine($"The functional test program would end in a forever-loop on the same memory location if it fails.");
                Console.WriteLine($"Verify the last PC location against the functional test program's .lst file to find out which logic test failed.");
            }
        }
Exemplo n.º 2
0
        public void Can_Run_6502_Functional_Test_Program_With_Decimal_Mode_Disabled_Successfully()
        {
            // Arrange
            var functionalTestCompiler = new FunctionalTestCompiler(NullLogger <FunctionalTestCompiler> .Instance);
            var functionalTestBinary   = functionalTestCompiler.Get6502FunctionalTestBinary(disableDecimalTests: true);

            // There is no 2 byte header in the 6502_functional_test.bin file.
            // It's supposed to be loaded to memory at 0x0000, and started at 0x0400
            ushort loadAddress  = 0x000A;
            ushort startAddress = 0x0400;

            var mem = BinaryLoader.Load(
                functionalTestBinary,
                out ushort loadedAtAddress,
                out int fileLength,
                forceLoadAddress: loadAddress);

            _output.WriteLine($"Data & code load  address: {loadAddress.ToHex(), 10} ({loadAddress})");
            _output.WriteLine($"Code+data length (bytes):  0x{fileLength, -8:X8} ({fileLength})");
            _output.WriteLine($"Code start address:        {startAddress.ToHex(), 10} ({startAddress})");

            var computerBuilder = new ComputerBuilder();

            computerBuilder
            .WithCPU()
            .WithStartAddress(startAddress)
            .WithMemory(mem)
            .WithExecOptions(options =>
            {
                // A successful run has about 26765880 instructions (the version that was run 2021-02-06, that may change)
                // We increase to almost double, and will exit if not finished then.
                options.MaxNumberOfInstructions             = 50000000;
                options.ExecuteUntilExecutedInstructionAtPC = 0x336d;
                options.UnknownInstructionThrowsException   = false;
            });

            var computer = computerBuilder.Build();

            var execOptions = computer.DefaultExecOptions;

            _output.WriteLine($"If test logic succeeds, the test program will reach a specific memory location: {execOptions.ExecuteUntilExecutedInstructionAtPC.Value.ToHex()}, and the emulator will then stop processing.");
            _output.WriteLine($"If test logic fails, the test program will loop forever at the location the error was found. The emulator will try executing a maximum #instructions {execOptions.MaxNumberOfInstructions.Value} before giving up.");
            _output.WriteLine($"If unknown opcode is found, it's logged and ignored, and processing continues on next instruction.");

            // Act
            computer.Run();

            // Assert
            var cpu       = computer.CPU;
            var execState = cpu.ExecState;

            _output.WriteLine($"CPU last PC:                       {cpu.PC.ToHex()}");
            _output.WriteLine($"CPU last opcode:                   {execState.LastOpCode.Value.ToOpCodeId()} ({execState.LastOpCode.Value.ToHex()})");
            _output.WriteLine($"Total # CPU instructions executed: {execState.InstructionsExecutionCount}");
            _output.WriteLine($"Total # CPU cycles consumed:       {execState.CyclesConsumed}");

            if (cpu.PC == computer.DefaultExecOptions.ExecuteUntilExecutedInstructionAtPC.Value)
            {
                _output.WriteLine($"Success. PC reached expected success memory location: {computer.DefaultExecOptions.ExecuteUntilExecutedInstructionAtPC.Value.ToHex()}");
                Assert.True(true);
            }
            else
            {
                _output.WriteLine($"Probably failure. The emulator executer a maximum #instructions {computer.DefaultExecOptions.MaxNumberOfInstructions.Value}, and did not manage to get PC to the configured success location: {computer.DefaultExecOptions.ExecuteUntilExecutedInstructionAtPC.Value.ToHex()}");
                _output.WriteLine($"The functional test program would end in a forever-loop on the same memory location if it fails.");
                _output.WriteLine($"Verify the last PC location against the functional test program's .lst file to find out which logic test failed.");
                Assert.True(false);
            }
        }