diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..74b6220 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*/*/bin/ +*/*/obj/ +*/bin/ +*/obj/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8ff9a07 --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2025 Persephone (KawaiiZenbo) Bubblegum-Holiday + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/PC2SSTPlayer/INIFile.cs b/PC2SSTPlayer/INIFile.cs new file mode 100644 index 0000000..41cf682 --- /dev/null +++ b/PC2SSTPlayer/INIFile.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace SSTServoPlayer +{ + public class INIFile + { + public Dictionary Data { get; set; } + + public INIFile(Dictionary data) + { + Data = data; + } + + public static INIFile Load(string inPath) + { + Dictionary outData = new Dictionary(); + string[] rawFile = File.ReadAllLines(inPath); + foreach (string line in rawFile) + { + if (line.StartsWith(";") || line.Trim() == "") continue; + outData.Add(line.Split("=")[0].Trim(), line.Split("=")[1].Trim()); + } + return new INIFile(outData); + } + } +} diff --git a/PC2SSTPlayer/PC2SSTPlayer.csproj b/PC2SSTPlayer/PC2SSTPlayer.csproj new file mode 100644 index 0000000..0438bed --- /dev/null +++ b/PC2SSTPlayer/PC2SSTPlayer.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/PC2SSTPlayer/Program.cs b/PC2SSTPlayer/Program.cs new file mode 100644 index 0000000..d144f7f --- /dev/null +++ b/PC2SSTPlayer/Program.cs @@ -0,0 +1,67 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.IO.Ports; +using System.Text; +using System.Timers; + +namespace SSTServoPlayer +{ + public class Program + { + static INIFile Config; + static string PathPrefix="/"; + static byte[] Signals; + static SerialPort port = null; + static System.Timers.Timer FrameTimer; + static long index = 0; + static int frameSkip = 6; + + static void Main(string[] args) + { + Config = INIFile.Load(args[0]); + PathPrefix = Path.GetFullPath(args[0]).Replace("manifest.ini", ""); + Signals = File.ReadAllBytes(PathPrefix+Config.Data["data"]); + port = new SerialPort(args[1], 9600, Parity.None, 8, StopBits.One); + port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); + port.Open(); + FrameTimer = new System.Timers.Timer((1000d/double.Parse(Config.Data["frames-per-second"]))*frameSkip); + FrameTimer.Elapsed += PlaySignal; + FrameTimer.AutoReset = true; + + PlayAudio(); + FrameTimer.Start(); + Console.ReadLine(); + port.Close(); + } + + private static void port_DataReceived(object sender, SerialDataReceivedEventArgs e) + { + Console.Write(port.ReadExisting()); + } + + static void PlayAudio() + { + Process.Start("mpv", PathPrefix+Config.Data["audio"]); + } + + static void PlaySignal(Object sender, ElapsedEventArgs e) + { + if (index == Signals.Length) + { + FrameTimer.Stop(); + Console.WriteLine("Complete!"); + return; + } + byte b = Signals[index]; + + byte byte1 = (byte)(64 | ((b & 8) | (b & 4) | (b & 2) | (b & 1))); + byte byte2 = (byte)(64 | (((b & 128) | (b & 64) | (b & 32) | (b & 16)) >> 4)); + port.Write(((char)byte1).ToString()); + port.Write(((char)byte2).ToString()); + //port.Write(((char)b).ToString()); + //Console.WriteLine(byte1.ToString("B8") + " " + byte2.ToString("B8")); + index+=frameSkip; + } + } +} diff --git a/PinkConnection2-Firmware-Servo-GuestStar/PinkConnection2-Firmware-Servo-GuestStar.ino b/PinkConnection2-Firmware-Servo-GuestStar/PinkConnection2-Firmware-Servo-GuestStar.ino new file mode 100644 index 0000000..7429856 --- /dev/null +++ b/PinkConnection2-Firmware-Servo-GuestStar/PinkConnection2-Firmware-Servo-GuestStar.ino @@ -0,0 +1,104 @@ +// PINKCONNECTION2 Client Program for Helen Henny/Chuck E./Guest Star Cyberamic Servo + +#include +#include + +Servo servoChannel[8]; +byte onDegrees[8] = { 90, 0, 0, 0, 0, 0, 0, 0 }; // these are incomplete, i need to tune them when i get the servos in +byte offDegrees[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +int byte1 = 0; +int byte2 = 0; + +void setup() { + servoChannel[0].attach(2); + servoChannel[1].attach(3); + servoChannel[2].attach(4); + servoChannel[3].attach(5); + servoChannel[4].attach(6); + servoChannel[5].attach(7); + servoChannel[6].attach(8); + servoChannel[7].attach(9); + pinMode(A0, OUTPUT); + pinMode(A1, OUTPUT); + pinMode(A2, OUTPUT); + pinMode(A3, OUTPUT); + pinMode(A4, OUTPUT); + pinMode(A5, OUTPUT); + pinMode(10, OUTPUT); + pinMode(11, OUTPUT); + for (int i = 0; i < 8; i++) servoChannel[i].write(offDegrees[i]); + Serial.begin(9600); +} + +void loop() { + if (Serial.available() > 1) { + byte1 = Serial.read(); + byte2 = Serial.read(); + if ((byte1 & 64) && (byte2 & 64)) + if (byte1 & 1) { + servoChannel[0].write(onDegrees[0]); + digitalWrite(A0, 1); + } else { + servoChannel[0].write(offDegrees[0]); + digitalWrite(A0, 0); + } + + if (byte1 & 2) { + servoChannel[1].write(onDegrees[1]); + digitalWrite(A1, 1); + } else { + servoChannel[1].write(offDegrees[1]); + digitalWrite(A1, 0); + } + + if (byte1 & 4) { + servoChannel[2].write(onDegrees[2]); + digitalWrite(A2, 1); + } else { + servoChannel[2].write(offDegrees[2]); + digitalWrite(A2, 0); + } + + if (byte1 & 8) { + servoChannel[2].write(onDegrees[3]); + digitalWrite(A3, 1); + } else { + servoChannel[2].write(offDegrees[3]); + digitalWrite(A3, 0); + } + + if (byte2 & 1) { + servoChannel[4].write(onDegrees[4]); + digitalWrite(A4, 1); + } else { + servoChannel[4].write(offDegrees[4]); + digitalWrite(A4, 0); + } + + if (byte2 & 2) { + servoChannel[4].write(onDegrees[5]); + digitalWrite(A5, 1); + } else { + servoChannel[4].write(offDegrees[5]); + digitalWrite(A5, 0); + } + + if (byte2 & 4) { + servoChannel[6].write(onDegrees[6]); + digitalWrite(10, 1); + } else { + servoChannel[6].write(offDegrees[6]); + digitalWrite(10, 0); + } + + if (byte2 & 8) { + servoChannel[7].write(onDegrees[7]); + digitalWrite(11, 1); + } else { + servoChannel[7].write(offDegrees[7]); + digitalWrite(11, 0); + } + + } +} diff --git a/PinkConnection2-TestApp/PinkConnection2-TestApp.Gtk/PinkConnection2-TestApp.Gtk.csproj b/PinkConnection2-TestApp/PinkConnection2-TestApp.Gtk/PinkConnection2-TestApp.Gtk.csproj new file mode 100644 index 0000000..534afb7 --- /dev/null +++ b/PinkConnection2-TestApp/PinkConnection2-TestApp.Gtk/PinkConnection2-TestApp.Gtk.csproj @@ -0,0 +1,17 @@ + + + + WinExe + net8.0 + PinkConnection2_TestApp.Gtk + + + + + + + + + + + diff --git a/PinkConnection2-TestApp/PinkConnection2-TestApp.Gtk/Program.cs b/PinkConnection2-TestApp/PinkConnection2-TestApp.Gtk/Program.cs new file mode 100644 index 0000000..60cdf2a --- /dev/null +++ b/PinkConnection2-TestApp/PinkConnection2-TestApp.Gtk/Program.cs @@ -0,0 +1,14 @@ +using System; +using Eto.Forms; + +namespace PinkConnection2_TestApp.Gtk +{ + class Program + { + [STAThread] + public static void Main(string[] args) + { + new Application(Eto.Platforms.Gtk).Run(new MainForm()); + } + } +} diff --git a/PinkConnection2-TestApp/PinkConnection2-TestApp.Mac/Icon.icns b/PinkConnection2-TestApp/PinkConnection2-TestApp.Mac/Icon.icns new file mode 100644 index 0000000..8f385bb Binary files /dev/null and b/PinkConnection2-TestApp/PinkConnection2-TestApp.Mac/Icon.icns differ diff --git a/PinkConnection2-TestApp/PinkConnection2-TestApp.Mac/Info.plist b/PinkConnection2-TestApp/PinkConnection2-TestApp.Mac/Info.plist new file mode 100644 index 0000000..61ebaa2 --- /dev/null +++ b/PinkConnection2-TestApp/PinkConnection2-TestApp.Mac/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleName + PinkConnection2-TestApp + CFBundleIdentifier + me.kawaiizenbo.PinkConnection2-TestApp + CFBundleShortVersionString + 1.0 + LSMinimumSystemVersion + 10.15 + CFBundleDevelopmentRegion + en + NSHumanReadableCopyright + + CFBundleIconFile + Icon.icns + + diff --git a/PinkConnection2-TestApp/PinkConnection2-TestApp.Mac/PinkConnection2-TestApp.Mac.csproj b/PinkConnection2-TestApp/PinkConnection2-TestApp.Mac/PinkConnection2-TestApp.Mac.csproj new file mode 100644 index 0000000..106e10a --- /dev/null +++ b/PinkConnection2-TestApp/PinkConnection2-TestApp.Mac/PinkConnection2-TestApp.Mac.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + PinkConnection2_TestApp.Mac + + osx-x64;osx-arm64 + + + + + + + + + + + diff --git a/PinkConnection2-TestApp/PinkConnection2-TestApp.Mac/Program.cs b/PinkConnection2-TestApp/PinkConnection2-TestApp.Mac/Program.cs new file mode 100644 index 0000000..77932fe --- /dev/null +++ b/PinkConnection2-TestApp/PinkConnection2-TestApp.Mac/Program.cs @@ -0,0 +1,14 @@ +using System; +using Eto.Forms; + +namespace PinkConnection2_TestApp.Mac +{ + class Program + { + [STAThread] + public static void Main(string[] args) + { + new Application(Eto.Platforms.Mac64).Run(new MainForm()); + } + } +} diff --git a/PinkConnection2-TestApp/PinkConnection2-TestApp.Wpf/PinkConnection2-TestApp.Wpf.csproj b/PinkConnection2-TestApp/PinkConnection2-TestApp.Wpf/PinkConnection2-TestApp.Wpf.csproj new file mode 100644 index 0000000..2c5fc3c --- /dev/null +++ b/PinkConnection2-TestApp/PinkConnection2-TestApp.Wpf/PinkConnection2-TestApp.Wpf.csproj @@ -0,0 +1,17 @@ + + + + WinExe + net8.0-windows + PinkConnection2_TestApp.Wpf + + + + + + + + + + + diff --git a/PinkConnection2-TestApp/PinkConnection2-TestApp.Wpf/Program.cs b/PinkConnection2-TestApp/PinkConnection2-TestApp.Wpf/Program.cs new file mode 100644 index 0000000..7459017 --- /dev/null +++ b/PinkConnection2-TestApp/PinkConnection2-TestApp.Wpf/Program.cs @@ -0,0 +1,14 @@ +using System; +using Eto.Forms; + +namespace PinkConnection2_TestApp.Wpf +{ + class Program + { + [STAThread] + public static void Main(string[] args) + { + new Application(Eto.Platforms.Wpf).Run(new MainForm()); + } + } +} diff --git a/PinkConnection2-TestApp/PinkConnection2-TestApp/MainForm.cs b/PinkConnection2-TestApp/PinkConnection2-TestApp/MainForm.cs new file mode 100644 index 0000000..f893f7a --- /dev/null +++ b/PinkConnection2-TestApp/PinkConnection2-TestApp/MainForm.cs @@ -0,0 +1,105 @@ +using System; +using System.IO.Ports; + +using Eto.Forms; +using Eto.Drawing; + +namespace PinkConnection2_TestApp +{ + public class MainForm : Form + { + SerialPort port = null; + byte b = 0; + + TextBox CommandTextBox = new TextBox { MaxLength = 2 }; + DropDown SerialPortDropDown = new DropDown(); + + public MainForm() + { + Title = "PinkConnection2 Test App"; + Size = new Size(480, 300); + Maximizable = false; + Resizable = false; + + foreach (string s in SerialPort.GetPortNames()) + { + SerialPortDropDown.Items.Add(s); + } + SerialPortDropDown.SelectedValueChanged += (sender, e) => selectSerialPort(); + + DynamicLayout layout = new DynamicLayout { DefaultSpacing = new Size(10, 10), DefaultPadding = new Padding(5, 5, 5, 5) }; + + layout.BeginVertical(); + layout.BeginHorizontal(); + layout.Add(new Label { Text = "Serial Port" }); + layout.EndHorizontal(); + + layout.BeginHorizontal(); + layout.Add(SerialPortDropDown, true); + layout.EndHorizontal(); + layout.EndVertical(); + + layout.BeginVertical(); + layout.BeginHorizontal(); + layout.Add(new Label { Text = "Channels" }); + layout.EndHorizontal(); + + layout.BeginHorizontal(); + layout.Add(new Button { Text = "Channel 1", Command = new Command((sender, e) => { if ((b&1)==1) b-=1; else b+=1; sendFrame(); }) }, true); + layout.Add(new Button { Text = "Channel 2", Command = new Command((sender, e) => { if ((b&2)==2) b-=2; else b+=2; sendFrame(); }) }, true); + layout.Add(new Button { Text = "Channel 3", Command = new Command((sender, e) => { if ((b&4)==4) b-=4; else b+=4; sendFrame(); }) }, true); + layout.Add(new Button { Text = "Channel 4", Command = new Command((sender, e) => { if ((b&8)==8) b-=8; else b+=8; sendFrame(); }) }, true); + layout.EndHorizontal(); + + layout.BeginHorizontal(); + layout.Add(new Button { Text = "Channel 5", Command = new Command((sender, e) => { if ((b&16)==16) b-=16; else b+=16; sendFrame(); }) }, true); + layout.Add(new Button { Text = "Channel 6", Command = new Command((sender, e) => { if ((b&32)==32) b-=32; else b+=32; sendFrame(); }) }, true); + layout.Add(new Button { Text = "Channel 7", Command = new Command((sender, e) => { if ((b&64)==64) b-=64; else b+=64; sendFrame(); }) }, true); + layout.Add(new Button { Text = "Channel 8", Command = new Command((sender, e) => { if ((b&128)==128) b-=128; else b+=128; sendFrame(); }) }, true); + layout.EndHorizontal(); + layout.EndVertical(); + + layout.BeginVertical(); + layout.BeginHorizontal(); + layout.Add(new Label { Text = "Send Command" }); + layout.EndHorizontal(); + + layout.BeginHorizontal(); + layout.Add(CommandTextBox, true); + layout.Add(new Button { Text = "Send", Command = new Command((sender, e) => sendRawSafe()) }); + layout.EndHorizontal(); + layout.EndVertical(); + + layout.BeginVertical(); + layout.Add(null, true); + layout.EndVertical(); + + Content = layout; + } + + void sendFrame() + { + byte byte1 = (byte)(64 | ((b & 8) | (b & 4) | (b & 2) | (b & 1))); + byte byte2 = (byte)(64 | (((b & 128) | (b & 64) | (b & 32) | (b & 16)) >> 4)); + port.Write(((char)byte1).ToString()); + port.Write(((char)byte2).ToString()); + } + + void sendRawSafe() + { + if (CommandTextBox.Text.Length != 2) + { + MessageBox.Show("Command Length must not be less than 2"); + return; + } + port.Write(CommandTextBox.Text); + } + + void selectSerialPort() + { + if (port != null) port.Close(); + port = new SerialPort((string)SerialPortDropDown.SelectedKey, 9600, Parity.None, 8, StopBits.One); + port.Open(); + } + } +} diff --git a/PinkConnection2-TestApp/PinkConnection2-TestApp/PinkConnection2-TestApp.csproj b/PinkConnection2-TestApp/PinkConnection2-TestApp/PinkConnection2-TestApp.csproj new file mode 100644 index 0000000..5400071 --- /dev/null +++ b/PinkConnection2-TestApp/PinkConnection2-TestApp/PinkConnection2-TestApp.csproj @@ -0,0 +1,13 @@ + + + + netstandard2.0 + PinkConnection2_TestApp + + + + + + + + diff --git a/PinkConnection2-TestApp/build_linux.sh b/PinkConnection2-TestApp/build_linux.sh new file mode 100755 index 0000000..8ab2542 --- /dev/null +++ b/PinkConnection2-TestApp/build_linux.sh @@ -0,0 +1,2 @@ +cd PinkConnection2-TestApp.Gtk +dotnet build diff --git a/PinkConnection2-TestApp/build_mac.sh b/PinkConnection2-TestApp/build_mac.sh new file mode 100755 index 0000000..cfb329a --- /dev/null +++ b/PinkConnection2-TestApp/build_mac.sh @@ -0,0 +1,2 @@ +cd PinkConnection2-TestApp.Mac +dotnet build diff --git a/PinkConnection2-TestApp/build_windows.bat b/PinkConnection2-TestApp/build_windows.bat new file mode 100644 index 0000000..3755ca0 --- /dev/null +++ b/PinkConnection2-TestApp/build_windows.bat @@ -0,0 +1,3 @@ +@ECHO OFF +cd PinkConnection2-TestApp.Wpf +dotnet build diff --git a/rshw2sst/Program.cs b/rshw2sst/Program.cs new file mode 100644 index 0000000..fa5641e --- /dev/null +++ b/rshw2sst/Program.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections; +using System.IO; + +namespace rshw2sst +{ + public class Program + { + static bool usingRSHW = false; + static int charaIndex = 0; + + public static void Main(string[] args) + { + Console.WriteLine("RSHW and CSHW Data Converter"); + if (args[0] == "help") + { + Console.WriteLine("Usage: rshw2sst \n" + + "This will output a SST Showtape for 1 Cyberamic Character\n" + + "If an RSHW file is used, it will convert the bits according to Rosetta\n" + ); + } + if (!File.Exists(args[0])) + { + Console.WriteLine("FATAL: Specified file does not exist."); + return; + } + switch (Path.GetExtension(args[0]).ToLower()) + { + case ".rshw": + usingRSHW = true; + break; + case ".cshw": + usingRSHW = false; + break; + default: + Console.WriteLine("FATAL: Only RSHW and CSHW files are supported."); + return; + } + switch (args[1].ToLower()) + { + case "chuck": + charaIndex = 0; + break; + case "helen": + charaIndex = 1; + break; + case "munch": + charaIndex = 2; + break; + case "jasper": + charaIndex = 3; + break; + case "pasqually": + charaIndex = 4; + break; + case "bella": + Console.WriteLine("you wish!!!"); + return; + default: + Console.WriteLine("FATAL: Invalid character."); + return; + } + if (!Directory.Exists(args[2])) Directory.CreateDirectory(args[2]); + RSHWFile file = RSHWLoader.Load(args[0]); + if (file.signalData == null) + { + Console.WriteLine("FATAL: This file contains no signal data."); + return; + } + if (file.audioData != null) File.WriteAllBytes(args[2] + "/audio_out.wav", file.audioData); + if (file.videoData != null) File.WriteAllBytes(args[2] + "/video_out.mp4", file.videoData); + Console.WriteLine("Wrote out audio and video data."); + + List rshwBits = new List(); + int countlength = 0; + if (file.signalData[0] != 0) + { + countlength = 1; + BitArray bit = new BitArray(300); + rshwBits.Add(bit); + } + for (int i = 0; i < file.signalData.Length; i++) + { + if (file.signalData[i] == 0) + { + countlength += 1; + BitArray bit = new BitArray(300); + rshwBits.Add(bit); + } + else + { + rshwBits[countlength - 1].Set(file.signalData[i], true); + } + } + Console.WriteLine("Loaded RSHW signal data."); + + List writeOut = new List(); + long bitsOut = 0; + foreach (BitArray bits in rshwBits) + { + bitsOut++; + if (bitsOut % 6 != 0) continue; + byte frameByte = 0; + Dictionary[] mapping = RosettaR12; + if (usingRSHW) mapping = Rosetta3St; + foreach (KeyValuePair movement in mapping[charaIndex]) + { + if (bits.Get(movement.Key)) frameByte += movement.Value; + } + writeOut.Add(frameByte); + } + File.WriteAllBytes(args[2] + "/signals_out.sts", writeOut.ToArray()); + Console.WriteLine("Wrote out signal data."); + + File.WriteAllText(args[2] + "/manifest.ini", $"; Exported by RSHW2SST\nname={Path.GetFileNameWithoutExtension(args[0])} {args[1]}\nvideo=video_out.mp4\naudio=audio_out.wav\ndata=signals_out.sts\nframes-per-second=10\nbits-per-frame=8"); + Console.WriteLine("Wrote out manifest."); + if (file.videoData == null) Console.WriteLine("Warning: Video data was blank, you will need to add the file manually."); + Console.WriteLine("Complete!"); + } + + public static Dictionary[] Rosetta3St = + { + new Dictionary + { {1, 1}, {8, 2}, {7, 4}, {6, 8}, {5, 16}, {4, 32}, {2, 64}, {19, 128} }, // chuck + new Dictionary + { {185, 1}, {180, 2}, {179, 4}, {178, 8}, {184, 16}, {183, 32}, {181, 64}, {169, 128} }, // helen + new Dictionary + { {45, 1}, {55, 2}, {54, 4}, {44, 8}, {43, 16}, {41, 32}, {60, 64}, {59, 128} }, // munch + new Dictionary + { {166, 1}, {158, 2}, {157, 4}, {156, 8}, {153, 16}, {152, 32}, {151, 64}, {163, 128} }, // jasper + new Dictionary + { {30, 1}, {21, 2}, {25, 4}, {29, 8}, {28, 16}, {26, 32}, {31, 64}, {35, 128} } // pasqually + }; + + public static Dictionary[] RosettaR12 = + { + new Dictionary + { {1, 1}, {4, 2}, {3, 4}, {2, 8}, {5, 16}, {8, 32}, {6, 64}, {7, 128} }, // chuck + new Dictionary + { {65, 1}, {68, 2}, {67, 4}, {66, 8}, {69, 16}, {72, 32}, {70, 64}, {71, 128} }, // helen + new Dictionary + { {49, 1}, {51, 2}, {50, 4}, {53, 8}, {56, 16}, {54, 32}, {55, 64}, {52, 128} }, // munch + new Dictionary + { {17, 1}, {20, 2}, {19, 4}, {18, 8}, {21, 16}, {24, 32}, {22, 64}, {23, 128} }, // jasper + new Dictionary + { {33, 1}, {35, 2}, {34, 4}, {37, 8}, {40, 16}, {38, 32}, {39, 64}, {36, 128} } // pasqually + }; + } +} diff --git a/rshw2sst/RSHWFile.cs b/rshw2sst/RSHWFile.cs new file mode 100644 index 0000000..d155ddf --- /dev/null +++ b/rshw2sst/RSHWFile.cs @@ -0,0 +1,31 @@ +using System.IO; +using System.Reflection; +using System.Runtime.Serialization.Formatters.Binary; + +sealed class AntiUnityBinder : System.Runtime.Serialization.SerializationBinder +{ + public override Type BindToType(string assemblyName, string typeName) + { + return Type.GetType(String.Format("RSHWFile, " + Assembly.GetExecutingAssembly().FullName)); + } +} + +[System.Serializable] +public class RSHWFile +{ + public byte[]? audioData { get; set; } + public int[]? signalData { get; set; } + public byte[]? videoData { get; set; } +} + +public class RSHWLoader +{ + public static RSHWFile Load(string path) + { + BinaryFormatter formatter = new BinaryFormatter(); + formatter.Binder = new AntiUnityBinder(); + FileStream stream = File.OpenRead(path); + return (RSHWFile)formatter.Deserialize(stream); + } +} + diff --git a/rshw2sst/rshw2sst.csproj b/rshw2sst/rshw2sst.csproj new file mode 100644 index 0000000..0586f06 --- /dev/null +++ b/rshw2sst/rshw2sst.csproj @@ -0,0 +1,11 @@ + + + + Exe + net8.0 + enable + enable + true + + +