/// <summary> /// Reads the Cartridge ROM /// </summary> /// <param name="startAddress">The start address</param> /// <param name="length">The length to read</param> /// <returns></returns> private static byte[] RomRead(uint startAddress, int length) { CommandPacketTransmit(TransmitCommand.RomRead, startAddress, length, 0); UsbInterface.ProgressBarTimerInterval = length > MAX_ROM_SIZE / 2 ? 0x100000 : 0x80000; var time = DateTime.Now.Ticks; var data = UsbInterface.Read(length); time = DateTime.Now.Ticks - time; Console.WriteLine($"OK. speed: {GetSpeedString(data.Length, time)}"); //TODO: this should be in the main program! or at least return the time! return(data); }
/// <summary> /// Starts a ROM on the cartridge /// </summary> /// <param name="fileName">The filename (optional)</param> /// <remarks> The filename (optional) is used for creating a save file on the SD card</remarks> public static void StartRom(string fileName = "") { if (fileName.Length < 256) { var filenameBytes = Encoding.ASCII.GetBytes(fileName); Array.Resize(ref filenameBytes, 256); //The packet must be 256 bytes in length, so resize it. CommandPacketTransmit(TransmitCommand.RomStart, 0, 0, 1); UsbInterface.Write(filenameBytes); } else { throw new Exception("Filename exceeds the 256 character limit."); } }
/// <summary> /// Writes to the cartridge ROM /// </summary> /// <param name="data">The data to write</param> /// <param name="startAddress">The start address</param> /// <returns></returns> private static byte[] RomWrite(byte[] data, uint startAddress) { var length = data.Length; CommandPacketTransmit(TransmitCommand.RomWrite, startAddress, length, 0); UsbInterface.ProgressBarTimerInterval = length > 0x2000000 ? 0x100000 : 0x80000; var time = DateTime.Now.Ticks; UsbInterface.Write(data); time = DateTime.Now.Ticks - time; Console.WriteLine($"OK. speed: {GetSpeedString(data.Length, time)}"); //TODO: this should be in the main program! or at least return the time! return(data); }
/// <summary> /// Loads an FPGA RBF file /// </summary> /// <param name="filename">The filename to load</param> /// <returns></returns> public static bool LoadFpga(string filename) { var data = File.ReadAllBytes(filename); data = FixDataSize(data); CommandPacketTransmit(TransmitCommand.FpgaWrite, 0, data.Length, 0); UsbInterface.Write(data); var responseBytes = CommandPacketReceive(); if (responseBytes[4] != 0) { throw new Exception($"FPGA configuration error: 0x{BitConverter.ToString(new byte[] { responseBytes[4] })}"); } return(true); }
/// <summary> /// Receives a command response from the USB port /// </summary> /// <returns>the full response in bytes</returns> private static byte[] CommandPacketReceive() { var cmd = UsbInterface.Read(16); if (Encoding.ASCII.GetString(cmd).ToLower().StartsWith("cmd") || Encoding.ASCII.GetString(cmd).ToLower().StartsWith("RSP")) { switch ((ReceiveCommand)cmd[3]) { case ReceiveCommand.CommsReply: return(cmd); case ReceiveCommand.CommsReplyLegacy: //Certain ROM's may reply that used the old OSes without case sensitivity on the test commnad, this ensures they are handled. throw new Exception($"Outdated OS, please update to {MINIMUM_OS_VERSION} or above!"); default: throw new Exception("Unexpected response received from USB port."); } } else { throw new Exception("Corrupted response received from USB port."); } }
/// <summary> /// Transmits a command to the USB port /// </summary> /// <param name="commandType">the command to send</param> /// <param name="address">Optional</param> /// <param name="length">Optional </param> /// <param name="argument">Optional</param> private static void CommandPacketTransmit(TransmitCommand commandType, uint address = 0, int length = 0, uint argument = 0) { length /= 512; //Must take into account buffer size. var commandPacket = new List <byte>(); commandPacket.AddRange(Encoding.ASCII.GetBytes("cmd")); commandPacket.Add((byte)commandType); if (BitConverter.IsLittleEndian) { //Convert to Big Endian commandPacket.AddRange(BitConverter.GetBytes(address).Reverse()); commandPacket.AddRange(BitConverter.GetBytes(length).Reverse()); commandPacket.AddRange(BitConverter.GetBytes(argument).Reverse()); } else { commandPacket.AddRange(BitConverter.GetBytes(address)); commandPacket.AddRange(BitConverter.GetBytes(length)); commandPacket.AddRange(BitConverter.GetBytes(argument)); } UsbInterface.Write(commandPacket.ToArray()); }
private static void Main(string[] args) { try { DrawProgramHeader(); UsbInterface.Connect(); HandleArguments(args); } catch (Exception exception) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(""); Console.WriteLine($"ERROR: {exception.Message}"); Console.ResetColor(); } finally { DrawProgramFooter(); UsbInterface.ClosePort(); } }