From a40bda326338d1ee2899cf225b7593ec46ed9bf8 Mon Sep 17 00:00:00 2001 From: thebrick448 Date: Tue, 17 Sep 2013 04:11:13 +0000 Subject: [PATCH] Added support for TI83 group files, and added checks to ensure the file follows the proper format. --- BizHawk.Emulation/Consoles/Calculator/TI83.cs | 122 +++++++++++++----- BizHawk.MultiClient/MainForm.MenuItems.cs | 20 +++ BizHawk.MultiClient/MainForm.cs | 8 -- 3 files changed, 109 insertions(+), 41 deletions(-) diff --git a/BizHawk.Emulation/Consoles/Calculator/TI83.cs b/BizHawk.Emulation/Consoles/Calculator/TI83.cs index ab311e398a..8431b3862a 100644 --- a/BizHawk.Emulation/Consoles/Calculator/TI83.cs +++ b/BizHawk.Emulation/Consoles/Calculator/TI83.cs @@ -630,9 +630,12 @@ namespace BizHawk.Emulation.Consoles.Calculator public Link LinkPort; public class Link { - byte[] FileData; readonly TI83 Parent; + private FileStream CurrentFile; + private int FileBytesLeft; + private byte[] VariableData; + private Action NextStep; private Queue CurrentData = new Queue(); private ushort BytesToSend; @@ -786,43 +789,94 @@ namespace BizHawk.Emulation.Consoles.Calculator } } - public void SendFileToCalc(FileStream FS) + public void SendFileToCalc(FileStream FS, bool Verify) + { + if (Verify) + VerifyFile(FS); + + FS.Seek(55, SeekOrigin.Begin); + CurrentFile = FS; + SendNextFile(); + } + + private void VerifyFile(FileStream FS) { - FS.Seek(53, SeekOrigin.Begin); + //Verify the file format. + byte[] Expected = new byte[] { 0x2a, 0x2a, 0x54, 0x49, 0x38, 0x33, 0x2a, 0x2a, 0x1a, 0x0a, 0x00 }; + byte[] Actual = new byte[11]; + + FS.Seek(0, SeekOrigin.Begin); + FS.Read(Actual, 0, 11); + + //Check the header. + for (int n = 0; n < 11; n++) + if (Expected[n] != Actual[n]) + { + FS.Close(); + throw new IOException("Invalid Header."); + } + + //Seek to the end of the comment. + FS.Seek(53, SeekOrigin.Begin); + int Size = FS.ReadByte() + FS.ReadByte() * 256; - if (FS.Length != Size + 57) - throw new FormatException("Invalid calculator file."); + if (FS.Length != Size + 57) + { + FS.Close(); + throw new IOException("Invalid file length."); + } - byte[] Header = new byte[13]; - FS.Read(Header, 0, 13); + //Verify the checksum. + ushort Checksum = 0; + for (int n = 0; n < Size; n++) + Checksum += (ushort)FS.ReadByte(); - FileData = new byte[Size - 13]; - FS.Read(FileData, 0, Size - 13); + ushort ActualChecksum = (ushort)(FS.ReadByte() + FS.ReadByte() * 256); - //Request to send the file. - CurrentData.Clear(); - - CurrentData.Enqueue(0x03); - CurrentData.Enqueue(0xC9); - - foreach (byte B in Header) - CurrentData.Enqueue(B); - - //Calculate the checksum for the command. - ushort Checksum = 0; - for (int n = 2; n < Header.Length; n++) - Checksum += Header[n]; - - CurrentData.Enqueue((byte)(Checksum % 256)); - CurrentData.Enqueue((byte)(Checksum / 256)); - - //Finalize the command. - CurrentStatus = Status.PrepareReceive; - NextStep = ReceiveReqAck; - Parent.LinkActive = true; + if (Checksum != ActualChecksum) + { + FS.Close(); + throw new IOException("Invalid Checksum."); + } } + private void SendNextFile() + { + byte[] Header = new byte[13]; + if (!CurrentFile.CanRead || CurrentFile.Read(Header, 0, 13) != 13) + { + //End of file. + CurrentFile.Close(); + return; + } + + int Size = Header[2] + Header[3] * 256; + VariableData = new byte[Size + 2]; + CurrentFile.Read(VariableData, 0, Size + 2); + + //Request to send the file. + CurrentData.Clear(); + + CurrentData.Enqueue(0x03); + CurrentData.Enqueue(0xC9); + foreach (byte B in Header) + CurrentData.Enqueue(B); + + //Calculate the checksum for the command. + ushort Checksum = 0; + for (int n = 2; n < Header.Length; n++) + Checksum += Header[n]; + + CurrentData.Enqueue((byte)(Checksum % 256)); + CurrentData.Enqueue((byte)(Checksum / 256)); + + //Finalize the command. + CurrentStatus = Status.PrepareReceive; + NextStep = ReceiveReqAck; + Parent.LinkActive = true; + } + private void ReceiveReqAck() { Parent.LinkActive = false; @@ -858,13 +912,13 @@ namespace BizHawk.Emulation.Consoles.Calculator CurrentData.Enqueue(0x15); //Add variable data. - foreach (byte B in FileData) + foreach (byte B in VariableData) CurrentData.Enqueue(B); //Calculate the checksum. ushort Checksum = 0; - for (int n = 2; n < FileData.Length; n++) - Checksum += FileData[n]; + for (int n = 2; n < VariableData.Length; n++) + Checksum += VariableData[n]; CurrentData.Enqueue((byte)(Checksum % 256)); CurrentData.Enqueue((byte)(Checksum / 256)); @@ -903,6 +957,7 @@ namespace BizHawk.Emulation.Consoles.Calculator private void OutOfMemory() { + CurrentFile.Close(); Parent.LinkActive = false; CurrentData.Clear(); @@ -932,6 +987,7 @@ namespace BizHawk.Emulation.Consoles.Calculator CurrentData.Clear(); Parent.LinkActive = false; NextStep = null; + SendNextFile(); } } } diff --git a/BizHawk.MultiClient/MainForm.MenuItems.cs b/BizHawk.MultiClient/MainForm.MenuItems.cs index ac2fad350e..ed75283ca2 100644 --- a/BizHawk.MultiClient/MainForm.MenuItems.cs +++ b/BizHawk.MultiClient/MainForm.MenuItems.cs @@ -2599,5 +2599,25 @@ namespace BizHawk.MultiClient { new RewindConfig().ShowDialog(); } + + private void loadTIFileToolStripMenuItem_Click(object sender, EventArgs e) + { + OpenFileDialog OFD = new OpenFileDialog(); + + if (OFD.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + try + { + (Global.Emulator as TI83).LinkPort.SendFileToCalc(File.OpenRead(OFD.FileName), true); + } + catch (IOException ex) + { + string Message = string.Format("Invalid file format. Reason: {0} \nForce transfer? This may cause the calculator to crash.", ex.Message); + + if (MessageBox.Show(Message, "Upload Failed", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes) + (Global.Emulator as TI83).LinkPort.SendFileToCalc(File.OpenRead(OFD.FileName), false); + } + } + } } } diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs index e794374195..666b534863 100644 --- a/BizHawk.MultiClient/MainForm.cs +++ b/BizHawk.MultiClient/MainForm.cs @@ -4201,14 +4201,6 @@ namespace BizHawk.MultiClient } } - private void loadTIFileToolStripMenuItem_Click(object sender, EventArgs e) - { - OpenFileDialog OFD = new OpenFileDialog(); - - if (OFD.ShowDialog() == System.Windows.Forms.DialogResult.OK) - (Global.Emulator as TI83).LinkPort.SendFileToCalc(File.OpenRead(OFD.FileName)); - } - private void newRamSearchToolStripMenuItem_Click(object sender, EventArgs e) { new NewRamSearch().Show();