private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) { if (Environment.GetCommandLineArgs().Length != 1) { ILoader loader = new BinaryLoader(); Container container = null; try { container = loader.Load(Environment.GetCommandLineArgs()[1]); } catch (Exception) { this.ShowMessageAsync("Impossible de lire le fichier selectionner", Environment.GetCommandLineArgs()[1]); } if (container != null) { MainControl.Content = new GameModeSelection(container, this); } else { MainControl.Content = new Home(this); } } else { MainControl.Content = new Home(this); } }
private void UseSaveButton_OnClick(object sender, RoutedEventArgs e) { ILoader loader = new BinaryLoader(); const string directorySaveName = "Save"; var fullSavePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" + directorySaveName; if (!Directory.Exists(fullSavePath)) { Directory.CreateDirectory(fullSavePath); } var openFileDialog = new OpenFileDialog { Filter = loader.Filter(), InitialDirectory = fullSavePath }; if (openFileDialog.ShowDialog() != true) { return; } var container = loader.Load(openFileDialog.FileName); _mainWindow.MainControl.Content = new Home(_mainWindow, container); }
public void LoadBinary(string fileName, out ushort loadedAtAddress, ushort?forceLoadAddress = null) { BinaryLoader.Load( Mem, fileName, out loadedAtAddress, out int _, forceLoadAddress); }
private Computer SetupEmulator(EmulatorConfig emulatorConfig) { Debug.WriteLine($"Loading 6502 machine code binary file."); Debug.WriteLine($"{emulatorConfig.ProgramBinaryFile}"); if (!File.Exists(emulatorConfig.ProgramBinaryFile)) { Debug.WriteLine($"File does not exist."); throw new Exception($"Cannot find 6502 binary file: {emulatorConfig.ProgramBinaryFile}"); } var enableBankSwitching = emulatorConfig.Memory.MemoryBanks.EnableMemoryBanks; var mem = new Memory(enableBankSwitching: enableBankSwitching); if (enableBankSwitching) { // Add additional memory banks for memory segment 1 (0x2000) and up (segment 0 cannot have multiple banks) for (byte memorySegmentNumber = 1; memorySegmentNumber < mem.MemorySegments.Count; memorySegmentNumber++) { // By default each segment has one bank when Memory is created above. // Thus we add the specified BanksPerSegment-1 new banks to each segment. for (int i = 0; i < emulatorConfig.Memory.MemoryBanks.BanksPerSegment - 1; i++) { // Add additional memory banks for segment. Memory in those will be blank (0x00). mem.AddMemorySegmentBank(memorySegmentNumber); } } } BinaryLoader.Load( mem, emulatorConfig.ProgramBinaryFile, out ushort loadedAtAddress, out int fileLength); // Initialize emulator with CPU, memory, and execution parameters var computerBuilder = new ComputerBuilder(); computerBuilder .WithCPU() .WithStartAddress(loadedAtAddress) .WithMemory(mem) .WithExecOptions(options => { // Emulator will stop executing when a BRK instruction is reached. options.ExecuteUntilInstruction = emulatorConfig.StopAtBRK?OpCodeId.BRK:null; }); var computer = computerBuilder.Build(); return(computer); }
public static VtkModel Load(string filePath) { VtkFileFormat format; using (var reader = new StreamReader(filePath, Encoding.ASCII)) { reader.ReadLine(); reader.ReadLine(); var line = reader.ReadLine().Trim(); if (line == "ASCII") { format = VtkFileFormat.Ascii; } else if (line == "BINARY") { format = VtkFileFormat.Binary; } else { throw new Exception("invalid vtk format."); } } using (var stream = new FileStream(filePath, FileMode.Open)) { if (format == VtkFileFormat.Binary) { using (var loader = new BinaryLoader(stream)) { return(loader.Load()); } } else { using (var loader = new AsciiLoader(stream)) { return(loader.Load()); } } } }
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) { if (Environment.GetCommandLineArgs().Length != 1) { ILoader loader = new BinaryLoader(); Container container = null; try { container = loader.Load(Environment.GetCommandLineArgs()[1]); } catch (Exception) { this.ShowMessageAsync("Its not possible to read the selected file", Environment.GetCommandLineArgs()[1]); } MainControl.Content = container != null ? new Home(this, container) : new Home(this, new Container()); } else { MainControl.Content = new Home(this, new Container()); } }
public static void Run() { Console.WriteLine($"--------------------------------------------------------"); Console.WriteLine($"Run 6502 code that multiplies two 16 bit signed numbers."); Console.WriteLine($"--------------------------------------------------------"); string prgFileName = "../.cache/ConsoleTestPrograms/AssemblerSource/multiply_2_16bit_numbers.prg"; Console.WriteLine(""); Console.WriteLine($"Loading binary into emulator memory..."); var mem = BinaryLoader.Load( prgFileName, out ushort loadedAtAddress); Console.WriteLine($"Loading done."); Console.WriteLine(""); Console.WriteLine($"Data & code load address: {loadedAtAddress.ToHex(), 10} ({loadedAtAddress})"); Console.WriteLine($"Code start address: {loadedAtAddress.ToHex(), 10} ({loadedAtAddress})"); ushort valA = 1337; ushort valB = 42; Console.WriteLine(""); Console.WriteLine($"Multiply {valA.ToDecimalAndHex()} with {valB.ToDecimalAndHex()}"); ushort sourceAddressA = 0xd000; ushort sourceAddressB = 0xd002; ushort resultAddress = 0xd004; mem[(ushort)(sourceAddressA + 0)] = valA.Lowbyte(); mem[(ushort)(sourceAddressA + 1)] = valA.Highbyte(); mem[(ushort)(sourceAddressB + 0)] = valB.Lowbyte(); mem[(ushort)(sourceAddressB + 1)] = valB.Highbyte(); Console.WriteLine(""); Console.WriteLine($"Value A set memory location {sourceAddressA.ToHex()}"); Console.WriteLine($"{((ushort)(sourceAddressA + 0)).ToHex()} : {mem[(ushort)(sourceAddressA + 0)].ToHex()}"); Console.WriteLine($"{((ushort)(sourceAddressA + 1)).ToHex()} : {mem[(ushort)(sourceAddressA + 1)].ToHex()}"); Console.WriteLine($"Value B set memory location {sourceAddressB.ToHex()}"); Console.WriteLine($"{((ushort)(sourceAddressB + 0)).ToHex()} : {mem[(ushort)(sourceAddressB + 0)].ToHex()}"); Console.WriteLine($"{((ushort)(sourceAddressB + 1)).ToHex()} : {mem[(ushort)(sourceAddressB + 1)].ToHex()}"); // Initialize CPU, set PC to start position var computerBuilder = new ComputerBuilder(); computerBuilder .WithCPU() .WithStartAddress(loadedAtAddress) .WithMemory(mem) .WithInstructionExecutedEventHandler( (s, e) => Console.WriteLine($"{e.CPU.PC.ToHex()}: {e.CPU.ExecState.LastOpCode.Value.ToOpCodeId()}")) .WithExecOptions(options => { options.ExecuteUntilInstruction = OpCodeId.BRK; }); var computer = computerBuilder.Build(); Console.WriteLine(""); Console.WriteLine("Running 6502 multiplication routine..."); computer.Run(); Console.WriteLine(""); Console.WriteLine("Done."); Console.WriteLine(""); Console.WriteLine($"Result stored at {resultAddress.ToHex()}:"); Console.WriteLine($"{((ushort)(resultAddress + 0)).ToHex()} : {mem[(ushort)(resultAddress + 0)].ToHex()}"); Console.WriteLine($"{((ushort)(resultAddress + 1)).ToHex()} : {mem[(ushort)(resultAddress + 1)].ToHex()}"); Console.WriteLine(""); ushort result = mem.FetchWord(resultAddress); Console.WriteLine($"Result:"); Console.WriteLine($"{valA.ToDecimalAndHex()} * {valB.ToDecimalAndHex()} = {result.ToDecimalAndHex()}"); }
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."); } }
public static void Run() { Console.Clear(); string prgFileName = "../../.cache/Examples/ConsoleTestPrograms/AssemblerSource/hostinteraction_scroll_text.prg"; Console.WriteLine($"Loading 6502 machine code binary file."); Console.WriteLine($"{prgFileName}"); if (!File.Exists(prgFileName)) { Console.WriteLine($"File does not exist."); return; } var mem = BinaryLoader.Load( prgFileName, out ushort loadedAtAddress, out int fileLength); // Initialize emulator with CPU, memory, and execution parameters var computerBuilder = new ComputerBuilder(); computerBuilder .WithCPU() .WithStartAddress(loadedAtAddress) .WithMemory(mem) // .WithInstructionExecutedEventHandler( // (s, e) => Console.WriteLine(OutputGen.GetLastInstructionDisassembly(e.CPU, e.Mem))) .WithExecOptions(options => { options.ExecuteUntilInstruction = OpCodeId.BRK; // Emulator will stop executing when a BRK instruction is reached. }); var computer = computerBuilder.Build(); // The shared memory location in the emulator that the 6502 program writes to to update screen. // 80 columns and 25 rows, 1 byte per character = 2000 (0x07d0) bytes const ushort SCREEN_MEM = 0x1000; const int SCREEN_MEM_COLS = 80; // const int SCREEN_MEM_ROWS = 25; const ushort SCREEN_REFRESH_STATUS = 0xf000; const int SCREEN_REFRESH_STATUS_HOST_REFRESH_BIT = 0; const int SCREEN_REFRESH_STATUS_EMULATOR_DONE_BIT = 1; Console.WriteLine(""); Console.WriteLine("Screen being updated indirectly by 6502 machine code running emulator!"); Console.WriteLine(""); bool cont = true; while (cont) { // Set emulator Refresh bit (maybe controlled by host frame counter in future?) // Emulator will wait until this bit is set until "redrawing" new data into memory mem.SetBit(SCREEN_REFRESH_STATUS, SCREEN_REFRESH_STATUS_HOST_REFRESH_BIT); bool shouldExecuteEmulator = true; while (shouldExecuteEmulator) { // Execute a number of instructions computer.Run(new ExecOptions { MaxNumberOfInstructions = 10 }); shouldExecuteEmulator = !mem.IsBitSet(SCREEN_REFRESH_STATUS, SCREEN_REFRESH_STATUS_EMULATOR_DONE_BIT); } RenderRow(mem, SCREEN_MEM, SCREEN_MEM_COLS); //RenderScreen(mem, SCREEN_MEM, SCREEN_MEM_COLS, SCREEN_MEM_ROWS); // Clear the flag that the emulator set to indicate it's done. mem.ClearBit(SCREEN_REFRESH_STATUS, SCREEN_REFRESH_STATUS_EMULATOR_DONE_BIT); bool shouldExecuteHost = true; while (shouldExecuteHost) { Thread.Sleep(80); // Control speed of screen update shouldExecuteHost = false; } } Console.WriteLine($"Execution stopped"); Console.WriteLine($"CPU state: {OutputGen.GetProcessorState(computer.CPU)}"); Console.WriteLine($"Stats: {computer.CPU.ExecState.InstructionsExecutionCount} instruction(s) processed, and used {computer.CPU.ExecState.CyclesConsumed} cycles."); }
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); } }