Last active
January 21, 2020 10:53
-
-
Save Enichan/a5e808a65c3d8854c5639b15b7a1d20b to your computer and use it in GitHub Desktop.
Takes a byte[] array with binary data, and outputs that to the .p8 pico 8 cartridge format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
public class P8Writer { | |
public const int RomSize = 0x4300; | |
private byte[] data; | |
private StringBuilder str; | |
public P8Writer(byte[] data) { | |
this.data = data; | |
} | |
public string Write() { | |
str = new StringBuilder(); | |
str.Append(@"pico-8 cartridge // http://www.pico-8.com | |
version 16 | |
__lua__ | |
-- data cartridge | |
"); | |
if (data.Length > 0) { | |
var gfx = new byte[0x2000]; | |
Buffer.BlockCopy(data, 0, gfx, 0, Math.Min(gfx.Length, data.Length)); | |
WriteGfx(gfx); | |
} | |
if (data.Length > 0x3000) { | |
var gff = new byte[0x100]; | |
Buffer.BlockCopy(data, 0x3000, gff, 0, Math.Min(gff.Length, data.Length - 0x3000)); | |
WriteGff(gff); | |
} | |
if (data.Length > 0x2000) { | |
var map = new byte[0x1000]; | |
Buffer.BlockCopy(data, 0x2000, map, 0, Math.Min(map.Length, data.Length - 0x2000)); | |
WriteMap(map); | |
} | |
if (data.Length > 0x3200) { | |
var sfx = new byte[0x1100]; | |
Buffer.BlockCopy(data, 0x3200, sfx, 0, Math.Min(sfx.Length, data.Length - 0x3200)); | |
WriteSfx(sfx); | |
} | |
if (data.Length > 0x3100) { | |
var music = new byte[0x100]; | |
Buffer.BlockCopy(data, 0x3100, music, 0, Math.Min(music.Length, data.Length - 0x3100)); | |
WriteMusic(music); | |
} | |
if (data.Length > 0x4300) { | |
throw new Exception("Data won't fit!"); | |
} | |
return str.ToString(); | |
} | |
private void WriteGfx(byte[] data) { | |
str.AppendLine("__gfx__"); | |
for (int i = 0, o = 0; i < 128; i++) { | |
for (int j = 0; j < 64; j++, o++) { | |
str.Append(Reverse(data[o].ToString("x2"))); | |
} | |
str.AppendLine(); | |
} | |
} | |
private string Reverse(string s) { | |
var str = new StringBuilder(); | |
for (int i = s.Length - 1; i >= 0; i--) { | |
str.Append(s[i]); | |
} | |
return str.ToString(); | |
} | |
private void WriteGff(byte[] data) { | |
str.AppendLine("__gff__"); | |
for (int i = 0, o = 0; i < 2; i++) { | |
for (int j = 0; j < 128; j++, o++) { | |
str.Append(data[o].ToString("x2")); | |
} | |
str.AppendLine(); | |
} | |
} | |
private void WriteMap(byte[] data) { | |
str.AppendLine("__map__"); | |
for (int i = 0, o = 0; i < 32; i++) { | |
for (int j = 0; j < 128; j++, o++) { | |
str.Append(data[o].ToString("x2")); | |
} | |
str.AppendLine(); | |
} | |
} | |
private void WriteSfx(byte[] data) { | |
str.AppendLine("__sfx__"); | |
for (int i = 0, o = 0; i < 64; i++) { | |
str.Append(data[o + 64].ToString("x2")); // editor mode | |
str.Append(data[o + 65].ToString("x2")); // speed | |
str.Append(data[o + 66].ToString("x2")); // loop start | |
str.Append(data[o + 67].ToString("x2")); // loop end | |
for (int j = 0; j < 32; j++, o += 2) { | |
// first byte | |
var pitch = data[o] & 0x3F; // 00111111 | |
var waveform1 = (data[o] & 0x40) >> 6; // 01000000 | |
var waveform2 = (data[o] & 0x80) >> 7; // 10000000 | |
// second byte | |
var waveform3 = data[o + 1] & 0x1; // 00000001 | |
var volume = (data[o + 1] & 0xE) >> 1; // 00001110 | |
var effect = (data[o + 1] & 0x70) >> 4; // 01110000 | |
var custom = (data[o + 1] & 0x80) >> 7; // 10000000 | |
// 0x?? - pitch | |
str.Append(pitch.ToString("x2")); | |
// 0x? - waveform | |
var waveform = waveform1 | (waveform2 << 1) | (waveform3 << 2) | (custom << 3); | |
str.Append(waveform.ToString("x1")); | |
// 0x? - volume | |
str.Append(volume.ToString("x1")); | |
// 0x? - effect | |
str.Append(effect.ToString("x1")); | |
} | |
str.AppendLine(); | |
o += 4; | |
} | |
} | |
private void WriteMusic(byte[] data) { | |
str.AppendLine("__music__"); | |
for (int i = 0, o = 0; i < 64; i++, o += 4) { | |
byte flags = 0; | |
if ((data[o] & 128) != 0) { | |
data[o] &= 0x7F; | |
flags |= 1; | |
} | |
if ((data[o + 1] & 128) != 0) { | |
data[o + 1] &= 0x7F; | |
flags |= 2; | |
} | |
if ((data[o + 2] & 128) != 0) { | |
data[o + 2] &= 0x7F; | |
flags |= 4; | |
} | |
if ((data[o + 3] & 128) != 0) { | |
data[o + 3] &= 0x7F; | |
flags |= 8; | |
} | |
str.AppendFormat("{0} {1}{2}{3}{4}", | |
flags.ToString("x2"), data[o].ToString("x2"), data[o + 1].ToString("x2"), data[o + 2].ToString("x2"), data[o + 3].ToString("x2")); | |
str.AppendLine(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment