add mitzifier converter

This commit is contained in:
Persephone Bubblegum-Holidy 2025-04-19 23:28:21 -07:00
parent ab54aaead6
commit 97a2ea19f0
5 changed files with 126 additions and 5 deletions

View file

@ -47,7 +47,7 @@ namespace SSTServoPlayer
static void PlaySignal(Object sender, ElapsedEventArgs e)
{
if (index == Signals.Length)
if (index >= Signals.Length)
{
FrameTimer.Stop();
Console.WriteLine("Complete!");

82
mitzifier/Program.cs Normal file
View file

@ -0,0 +1,82 @@
using System;
using System.Collections;
using System.IO;
namespace rshw2sst
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("mitzifier RSHW converter");
if (args[0] == "help")
{
Console.WriteLine("Usage: mitzifier <file path> <output directory>\n"
+ "This will output a SST showtape for use with the Mitzi/Helen firmware and player only\n"
);
}
if (!File.Exists(args[0]))
{
Console.WriteLine("FATAL: Specified file does not exist.");
return;
}
if (!Directory.Exists(args[1])) Directory.CreateDirectory(args[1]);
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[1] + "/audio_out.wav", file.audioData);
if (file.videoData != null) File.WriteAllBytes(args[1] + "/video_out.mp4", file.videoData);
Console.WriteLine("Wrote out audio and video data.");
List<BitArray> rshwBits = new List<BitArray>();
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<string> writeOut = new List<string>();
int hfb = 0;
foreach (BitArray bits in rshwBits)
{
int frameByte = 0;
for (int i = 0; i < 19; i++)
{
if (bits.Get(targetBits[i])) frameByte += 1 << i;
}
if (frameByte > hfb) hfb = frameByte;
writeOut.Add(frameByte.ToString("X8"));
}
File.WriteAllLines(args[1] + "/signals_out.mts", writeOut.ToArray());
Console.WriteLine("Wrote out signal data.");
File.WriteAllText(args[1] + "/manifest.ini", $"; Exported by Mitzifier\nname={Path.GetFileNameWithoutExtension(args[0])} Helen/Mitzi \nvideo=video_out.mp4\naudio=audio_out.wav\ndata=signals_out.mts\nframes-per-second=60\nbits-per-frame=32");
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!");
Console.WriteLine("Highest frame byte was " + hfb.ToString("B32"));
}
public static int[] targetBits = { 168, 169, 170, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188 };
}
}

31
mitzifier/RSHWFile.cs Normal file
View file

@ -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);
}
}

11
mitzifier/rshw2sst.csproj Normal file
View file

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>
</Project>

View file

@ -87,11 +87,8 @@ namespace rshw2sst
Console.WriteLine("Loaded RSHW signal data.");
List<byte> writeOut = new List<byte>();
long bitsOut = 0;
foreach (BitArray bits in rshwBits)
{
bitsOut++;
if (bitsOut % 6 != 0) continue;
byte frameByte = 0;
Dictionary<int, byte>[] mapping = RosettaR12;
if (usingRSHW) mapping = Rosetta3St;
@ -104,7 +101,7 @@ namespace rshw2sst
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");
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=60\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!");