private static bool InitializeSerialPort() { Console.WriteLine("Waiting for Everdrive64 USB to be connected"); while (FindDevice.FindFdtiUsbDevices().Where(p => p.nodeDescription == "FT245R USB FIFO").Count() == 0) { Thread.Sleep(100); } var testPacket = new CommandPacket(CommandPacket.Command.TestConnection); foreach (var device in FindDevice.FindFdtiUsbDevices().Where(p => p.nodeDescription == "FT245R USB FIFO")) { try { IoPort = new SerialPortStream(device.nodeComportName); IoPort.WriteTimeout = 500; IoPort.ReadTimeout = 500; IoPort.Open(); testPacket.Send(IoPort); IoPort.Read(receiveBuffer, 0, 512); //should be 4 if not 512 //ReadResponse(port, 4); //expect RSPk if (receiveBuffer[3] == (char)'k' && receiveBuffer[4] == (char)'3') //(Unofficial OS EDV3) { Console.WriteLine("Connected to EverDrive64 V3 on port: {0}", device.nodeComportName); switch ((char)receiveBuffer[5]) { case 'p': Console.WriteLine("PAL region detected"); break; case 'n': Console.WriteLine("NTSC region detected"); break; case 'm': Console.WriteLine("MPAL region detected"); break; default: Console.WriteLine("Unknown region detected"); break; } return(true); } if (receiveBuffer[3] == 107) //k { Console.WriteLine("Connected to EverDrive64 on port: {0}", device.nodeComportName); return(true); } } catch (Exception ex) { Console.WriteLine("error: {0}", ex.ToString()); } } return(false); }
public static void TakeScreenshot(SerialPortStream IoPort, string filename) { //TODO: Is there a better way to receive the current resolution from the ED64! var resPacket = new CommandPacket(CommandPacket.Command.ScreenResolution); resPacket.Send(IoPort); var resReceiveBuffer = new byte[512]; IoPort.Read(resReceiveBuffer, 0, 512); var width = BitConverter.ToUInt16(resReceiveBuffer, 0); var height = BitConverter.ToUInt16(resReceiveBuffer, 2); var picturePacket = new CommandPacket(CommandPacket.Command.Picture); picturePacket.Send(IoPort); var dataSize = width * height * 2; //Colour Data(2 bytes) var imageSize = width * height * 3; //Colour Data(3 bytes) var receiveBuffer = new List <byte>(); int bytesRead = 0; int i = 0; while (i < (dataSize)) { //I think we should be using a memory stream? //currently doing it one by one, otherwise we miss stuff! var tempBuffer = new byte[1]; var tempRead = IoPort.Read(tempBuffer, 0, 1); if (tempRead == 1) { receiveBuffer.AddRange(tempBuffer); } bytesRead += tempRead; i++; } Console.WriteLine($" Read Bytes: {bytesRead}"); var bmpHeader = new byte[54] { 0x42, 0x4D, //(BM) 0x36, 0x10, 0x0E, 0x00, //(File size) 0x00, 0x00, //(reserved) 0x00, 0x00, //(reserved) 0x36, 0x00, 0x00, 0x00, //(offset = header size + info header size 54 bytes) //BITMAPINFOHEADER 0x28, 0x00, 0x00, 0x00, //(Length = 40 bytes) 0x80, 0x02, 0x00, 0x00, //(Bitmap width signed int = 640) 0x20, 0xFE, 0xFF, 0xFF, //(Bitmap height signed int = -480 for "topdown") 0x01, 0x00, //(number of colour planes MUST BE 1) 0x18, 0x00, //(number of bits per pixel = 24) 0x00, 0x00, 0x00, 0x00, //(compression) 0x00, 0x10, 0x0E, 0x00, //(image size) 0x00, 0x00, 0x00, 0x00, //(horizontal res) 3790 0x00, 0x00, 0x00, 0x00, //(vertical res) 3800 0x00, 0x00, 0x00, 0x00, //(number of colours) 0x00, 0x00, 0x00, 0x00 //(number of important colours) }; //filesize = imagesize + 54 //generally it is not used, but we will set it just incase! var filesize = imageSize + 54; bmpHeader[2] = (byte)(filesize & 0xff); bmpHeader[3] = (byte)(filesize >> 8); bmpHeader[4] = 0; bmpHeader[5] = 0; //image width (using short as the max res is 640) bmpHeader[18] = (byte)(width & 0xff); bmpHeader[19] = (byte)(width >> 8); bmpHeader[20] = 0; bmpHeader[21] = 0; //negitive height for "top-down" bitmap (using short as the max res is 480) var topdownHeight = height * -1; bmpHeader[22] = (byte)(topdownHeight & 0xff); bmpHeader[23] = (byte)(topdownHeight >> 8); bmpHeader[24] = 0xff; bmpHeader[25] = 0xff; //imagesize //generally it is not used, but we will set it just incase! bmpHeader[34] = (byte)(imageSize & 0xff); bmpHeader[35] = (byte)(imageSize >> 8); bmpHeader[36] = 0; bmpHeader[37] = 0; var imageData = new List <byte>(); imageData.AddRange(bmpHeader); using (BinaryReader stream = new BinaryReader(new MemoryStream(receiveBuffer.ToArray()))) { for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { var colour = stream.ReadBytes(2); int red = (colour[0] & 0xf8); int green = ((colour[0] & 0x07) << 5) | ((colour[1] & 0xc0) >> 3); int blue = (colour[1] & 0x3e) << 2; imageData.Add((byte)blue); imageData.Add((byte)green); imageData.Add((byte)red); } } } using (var fs = new FileStream(filename, FileMode.OpenOrCreate)) { fs.Write(imageData.ToArray(), 0, imageData.Count); } Console.WriteLine("Screenshot taken!"); }
private static void Main(string[] args) { Console.WriteLine("****************************************"); Console.WriteLine("EverDrive64 USB Tools V{0}", Assembly.GetExecutingAssembly().GetName().Version.ToString()); Console.WriteLine("****************************************"); if (args.Length != 0 && !string.IsNullOrEmpty(args[0])) { if (InitializeSerialPort()) { Console.WriteLine("Preparing ROM for flash cart..."); //TODO: detect file type is correct, if not convert //var file = RomConverter.RomConverter.ConvertFile(args[0].ToString(), RomConverter.RomConverter.RomType.v64); var file = args[0].ToString(); if (!string.IsNullOrEmpty(file)) { WriteRom(file); Console.WriteLine("Booting ROM on flash cart..."); var startPacket = new CommandPacket(CommandPacket.Command.StartRom); startPacket.Send(IoPort); } else { Console.WriteLine("File conversion failed"); } } else { Console.WriteLine("No response received"); } } else { if (InitializeSerialPort()) { Console.WriteLine(@"Menu:"); Console.WriteLine(@"1) Take a screenshot."); Console.WriteLine(@"2) Copy ROM to ED64 and Start ROM"); Console.WriteLine(@"'E') Exit"); Console.WriteLine(@"'?') Help"); var exit = false; while (!exit) { var key = Console.ReadKey(); switch (key.KeyChar) { case '1': Screenshot.TakeScreenshot(IoPort, $"screenshot-{DateTime.Now.ToString("yyyy-dd-MM-HH-mm-ss")}.bmp"); break; case '2': Console.WriteLine("Enter full path to ROM:"); var file = Console.ReadLine(); WriteRom(file); Console.WriteLine("Booting ROM on flash cart..."); var startPacket = new CommandPacket(CommandPacket.Command.StartRom); startPacket.Send(IoPort); break; case 'E': exit = true; break; case '?': Console.WriteLine(@"Send and start a ROM through the commandline e.g. ""loader.exe c:\mycart.v64""."); break; default: Console.WriteLine("Invalid Input..."); break; } } } } if (IoPort.IsOpen) { IoPort.Close(); } Console.WriteLine("Press any key to exit."); Console.ReadLine(); }
public static void WriteRom(string fileName) { int fileLength = 0; byte[] fileArray; using (FileStream fileStream = File.OpenRead(fileName)) { fileLength = (int)fileStream.Length; if ((long)(fileLength / CHUNK_64KB * CHUNK_64KB) != fileStream.Length) //65536 { fileLength = (int)(fileStream.Length / CHUNK_64KB * CHUNK_64KB + CHUNK_64KB); } fileArray = new byte[fileLength]; fileStream.Read(fileArray, 0, (int)fileStream.Length); } Console.WriteLine("File Size: " + fileLength); if (fileLength < CHUNK_2MB) //needs filling { Console.WriteLine("Preparing space (zero fill) for ROM on flash cart"); var fillPacket = new CommandPacket(CommandPacket.Command.Fill); fillPacket.Send(IoPort); IoPort.Read(receiveBuffer, 0, 512); if (receiveBuffer[3] != 107) { Console.WriteLine("Zero fill failed, exiting"); fileArray = null; return; } else { Console.WriteLine("Zero fill succeeded"); } } var writePacket = new CommandPacket(CommandPacket.Command.WriteRom); var commandInfo = new byte[4]; commandInfo[0] = 0; //offset commandInfo[1] = 0; //offset commandInfo[2] = (byte)(fileArray.Length / 512 >> 8); commandInfo[3] = (byte)(fileArray.Length / 512); writePacket.body(commandInfo); writePacket.Send(IoPort); Console.WriteLine("Sending ROM to flash cart..."); DateTime now = DateTime.Now; for (int l = 0; l < fileArray.Length; l += CHUNK_32KB) { if (l == CHUNK_32MB) { Console.WriteLine("Sending next 32MB chunk"); commandInfo[0] = 0x40; //64 (offset 32MB) commandInfo[1] = 0; commandInfo[2] = (byte)((fileArray.Length - CHUNK_32MB) / 512 >> 8); commandInfo[3] = (byte)((fileArray.Length - CHUNK_32MB) / 512); writePacket.body(commandInfo); writePacket.Send(IoPort); } //TODO: why does the test code work but the real code not? //TEST code byte[] test = new byte[CHUNK_32KB]; Array.Copy(fileArray, l, test, 0, CHUNK_32KB); IoPort.Write(test, 0, test.Length); // TEST code //IoPort.Write(fileArray, l, CHUNK_32KB); if (l % CHUNK_512KB == 0) { Console.WriteLine("Sent 512KB chunk: {0} to {1} of {2}", l, l + CHUNK_512KB, fileArray.Length); } } Console.WriteLine("File sent."); Console.WriteLine("Elapsed time: {0}ms", (DateTime.Now - now).TotalMilliseconds); fileArray = null; }