diff --git a/src/main/java/net/lax1dude/eaglercraft/bintools/EBPFileDecoder.java b/src/main/java/net/lax1dude/eaglercraft/bintools/EBPFileDecoder.java
new file mode 100644
index 0000000..6deffbf
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/bintools/EBPFileDecoder.java
@@ -0,0 +1,116 @@
+package net.lax1dude.eaglercraft.bintools;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.imageio.ImageIO;
+
+/**
+ * Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+public class EBPFileDecoder {
+
+ private static int getFromBits(int idxx, int bits, byte[] bytes) {
+ int startByte = idxx >> 3;
+ int endByte = (idxx + bits - 1) >> 3;
+ if(startByte == endByte) {
+ return (((int)bytes[startByte] & 0xff) >> (8 - (idxx & 7) - bits)) & ((1 << bits) - 1);
+ }else {
+ return (((((int)bytes[startByte] & 0xff) << 8) | ((int)bytes[endByte] & 0xff)) >> (16 - (idxx & 7) - bits)) & ((1 << bits) - 1);
+ }
+ }
+
+ public static void _main(String[] args) throws IOException {
+ if(args.length == 1) {
+ File input = new File(args[0]);
+ if(!input.isDirectory()) {
+ System.err.println("Error: Not a directory: " + input.getAbsolutePath());
+ System.exit(-1);
+ return;
+ }
+ File[] f = input.listFiles();
+ for(int i = 0; i < f.length; ++i) {
+ String name = f[i].getAbsolutePath();
+ if(!name.toLowerCase().endsWith(".ebp")) {
+ continue;
+ }
+ File ff = new File(name.substring(0, name.length() - 3) + "png");
+ System.out.println(f[i].getName());
+ BufferedImage img;
+ try(InputStream is = new FileInputStream(f[i])) {
+ img = read(is);
+ }
+ ImageIO.write(img, "PNG", ff);
+ }
+ }else if(args.length == 2) {
+ System.out.println("Reading input file...");
+ BufferedImage img;
+ try(InputStream is = new FileInputStream(new File(args[0]))) {
+ img = read(is);
+ }
+ File output = new File(args[1]);
+ System.out.println("Writing PNG: " + output.getAbsolutePath());
+ ImageIO.write(img, "PNG", output);
+ }else {
+ System.out.println("Usage: ebp-decode