diff --git a/codegen/Broma/CMakeLists.txt b/codegen/Broma/CMakeLists.txt
deleted file mode 100644
index 4470187a..00000000
--- a/codegen/Broma/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
-project(Broma LANGUAGES C CXX)
-
-add_library(Broma ${CMAKE_CURRENT_SOURCE_DIR}/src/broma.cpp)
-
-target_compile_features(Broma PRIVATE cxx_std_17)
-
-target_include_directories(Broma PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
-
-target_compile_definitions(Broma PUBLIC TAO_PEGTL_GHC_FILESYSTEM=1)
-
-target_link_libraries(Broma taocpp::pegtl ghc_filesystem)
\ No newline at end of file
diff --git a/codegen/Broma/include/ast.hpp b/codegen/Broma/include/ast.hpp
deleted file mode 100644
index 36a562ee..00000000
--- a/codegen/Broma/include/ast.hpp
+++ /dev/null
@@ -1,138 +0,0 @@
-#include <string>
-#include <vector>
-#include <variant>
-#include <map>
-#include <algorithm>
-#include <iostream>
-
-enum class Platform {
-	Mac,
-	iOS,
-	Windows,
-	Android
-};
-
-struct PlatformNumber {
-	size_t mac = 0;
-	size_t ios = 0;
-	size_t win = 0;
-	size_t android = 0;
-};
-
-struct Type {
-	bool is_struct = false;
-	std::string name;
-
-	bool operator==(Type const& t) const {
-		return name == t.name;
-	}
-};
-
-enum class FunctionType {
-	Normal,
-	Ctor,
-	Dtor
-};
-
-struct FunctionBegin {
-	Type ret;
-	FunctionType type = FunctionType::Normal;
-	std::vector<std::pair<Type, std::string>> args;
-	bool is_const = false;
-	bool is_virtual = false;
-	bool is_static = false;
-	std::string docs;
-	std::string name;
-
-	inline bool operator==(FunctionBegin const& f) const {
-		if (name != f.name || is_const != f.is_const || args.size() != f.args.size())
-			return false;
-
-		for (size_t i = 0; i < args.size(); ++i) {
-			if (!(args[i].first == f.args[i].first))
-				return false;
-		}
-
-		std::cout << f.ret.name << " " << f.name << "\n";
-
-		return true;
-	}
-};
-
-struct MemberField {
-	std::string name;
-	Type type;
-	size_t count = 0;
-};
-
-struct PadField {
-	PlatformNumber amount;
-};
-
-struct FunctionBindField {
-	FunctionBegin beginning;
-	PlatformNumber binds;
-};
-
-struct OutOfLineField {
-	FunctionBegin beginning;
-	std::string inner;
-};
-
-struct InlineField {
-	std::string inner;
-};
-
-struct Class;
-struct Field {
-	size_t field_id;
-	std::string parent;
-	std::variant<InlineField, OutOfLineField, FunctionBindField, PadField, MemberField> inner;
-
-	template <typename T>
-	T* get_as() {
-		return std::get_if<T>(&inner);
-	}
-
-	template <typename T>
-	T const* get_as() const {
-		return std::get_if<T>(&inner);
-	}
-
-	inline FunctionBegin* get_fn() {
-		if (auto fn = get_as<OutOfLineField>()) {
-			return &fn->beginning;
-		} else if (auto fn = get_as<FunctionBindField>()) {
-			return &fn->beginning;
-		} else return nullptr;
-	}
-};
-
-struct Class {
-	std::string name;
-	std::vector<std::string> superclasses;
-	std::vector<std::string> depends;
-	std::vector<Field> fields;
-
-	inline bool operator==(Class const& c) const {
-		return name == c.name;
-	}
-	inline bool operator==(std::string const& n) const {
-		return name == n;
-	}
-};
-
-struct Root {
-	std::vector<Class> classes;
-
-	inline Class* operator[](std::string const& name) {
-		auto it = std::find_if(classes.begin(), classes.end(), [name](Class& cls) {
-		        return cls.name == name;
-		});
-
-		if (it == classes.end())
-			return nullptr;
-
-		return &*it;
-	}
-};
diff --git a/codegen/Broma/include/broma.hpp b/codegen/Broma/include/broma.hpp
deleted file mode 100644
index b348fd6f..00000000
--- a/codegen/Broma/include/broma.hpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "ast.hpp"
-
-namespace broma {
-	Root parse_file(std::string const& fname);
-}
\ No newline at end of file
diff --git a/codegen/Broma/src/attribute.hpp b/codegen/Broma/src/attribute.hpp
deleted file mode 100644
index bd61ceb2..00000000
--- a/codegen/Broma/src/attribute.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#pragma once
-
-#include <tao/pegtl.hpp>
-using namespace tao::pegtl;
-
-#include "basic_components.hpp"
-#include "state.hpp"
-
-namespace broma {
-	template <typename Name, typename ...Parse>
-	struct basic_attribute : seq<
-			Name,
-			one<'('>,
-
-			if_then_else<
-				at<one<')'>>,
-				success,
-				seq<Parse...>
-			>,
-
-			one<')'>
-		> {};
-
-	struct docs_attribute : basic_attribute<TAO_PEGTL_KEYWORD("docs"), string_literal> {};
-	struct depends_attribute : basic_attribute<TAO_PEGTL_KEYWORD("depends"), tagged_rule<depends_attribute, qualified>> {};
-
-	struct attribute : 
-		if_must<ascii::string<'[', '['>, 
-			sor<docs_attribute, depends_attribute>,
-			ascii::string<']', ']'>
-		> {};
-
-	template <>
-	struct run_action<tagged_rule<depends_attribute, qualified>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_class.depends.push_back(input.string());
-		}
-	};
-} // namespace broma
\ No newline at end of file
diff --git a/codegen/Broma/src/basic_components.hpp b/codegen/Broma/src/basic_components.hpp
deleted file mode 100644
index b8b89028..00000000
--- a/codegen/Broma/src/basic_components.hpp
+++ /dev/null
@@ -1,68 +0,0 @@
-#pragma once
-
-#include <tao/pegtl.hpp>
-using namespace tao::pegtl;
-
-namespace broma {
-	struct comment : 
-		disable<sor<
-			seq<ascii::string<'/', '/'>, until<eolf>>,
-			seq<ascii::string<'/', '*'>, until<seq<ascii::string<'*', '/'>>>>
-		>> {};
-
-	struct ignore : sor<comment, one<'\n', '\t', '\r', ' '>> {};
-
-	struct sep : star<ignore> {};
-	struct whitespace : plus<ignore> {};
-
-	template <typename ...Args>
-	struct pad_space : seq<Args..., whitespace> {};
-
-	template <typename ...Args>
-	struct rpad_space : seq<whitespace, Args...> {};
-
-	template <typename R, typename ...S>
-	struct if_then_must : if_then_else<R, must<S...>, seq<S...>> {};
-
-	template <char Quote>
-	struct basic_literal : if_must<one<Quote>, until<one<Quote>>> {};
-	struct string_literal : sor<basic_literal<'"'>, basic_literal<'\''>> {};
-
-	struct brace_end;
-	struct brace_start : seq<one<'{'>, brace_end> {};
-	struct brace_end : until<one<'}'>, sor<string_literal, brace_start, any>> {};
-
-	struct template_end;
-	struct template_start : seq<one<'<'>, template_end> {};
-	struct template_end : until<one<'>'>, sor<string_literal, template_start, any>> {};
-
-	template <typename T, typename ...Args>
-	struct tagged_rule : seq<Args...> {};
-
-	template <typename T>
-	struct rule_begin : success {};
-
-	#define $named_rule(name, ...) tagged_rule<TAO_PEGTL_INTERNAL_STRING(ascii::string, name), __VA_ARGS__>
-
-	#define $keyword(name) struct keyword_##name : TAO_PEGTL_KEYWORD(#name) {}
-
-	$keyword(const);
-	$keyword(static);
-	$keyword(virtual);
-	$keyword(inline);
-	$keyword(class);
-	$keyword(struct);
-	$keyword(unsigned);
-	$keyword(mac);
-	$keyword(win);
-	$keyword(ios);
-	$keyword(android);
-	$keyword(PAD);
-
-	struct qualified : list<seq<identifier, opt<template_start>>, ascii::string<':', ':'>>  {};
-
-	// point of no return: '0x'
-	struct hex : if_must<ascii::string<'0', 'x'>, plus<ascii::xdigit>> {};
-
-	struct platform : sor<keyword_mac, keyword_win, keyword_ios, keyword_android> {};
-} // namespace broma
diff --git a/codegen/Broma/src/bind.hpp b/codegen/Broma/src/bind.hpp
deleted file mode 100644
index c9318fa9..00000000
--- a/codegen/Broma/src/bind.hpp
+++ /dev/null
@@ -1,83 +0,0 @@
-#pragma once
-
-#include <tao/pegtl.hpp>
-using namespace tao::pegtl;
-
-#include "basic_components.hpp"
-#include "state.hpp"
-#include <sstream>
-
-namespace broma {
-	struct bind :
-		seq<rule_begin<bind>, opt_must<
-			one<'='>,
-			sep, 
-			list<opt<
-				sep,
-				sor<keyword_mac, keyword_win, keyword_ios, keyword_android>,
-				sep,
-				tagged_rule<bind, hex>
-			>, one<','>>,
-			sep
-		>, one<';'>> {};
-
-	template <>
-	struct run_action<rule_begin<bind>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_bind = PlatformNumber();
-		}
-	};
-
-	template <>
-	struct run_action<tagged_rule<bind, hex>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			size_t out = std::stoul(input.string(), nullptr, 16);
-
-			switch (scratch->wip_bind_platform) {
-				case Platform::Mac:
-					scratch->wip_bind.mac = out;
-					break;
-				case Platform::iOS:
-					scratch->wip_bind.ios = out;
-					break;
-				case Platform::Windows:
-					scratch->wip_bind.win = out;
-					break;
-				case Platform::Android:
-					scratch->wip_bind.android = out;
-					break;
-			}
-		}
-	};
-
-	template <>
-	struct run_action<keyword_mac> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_bind_platform = Platform::Mac;
-		}
-	};
-	template <>
-	struct run_action<keyword_ios> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_bind_platform = Platform::iOS;
-		}
-	};
-	template <>
-	struct run_action<keyword_win> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_bind_platform = Platform::Windows;
-		}
-	};
-	template <>
-	struct run_action<keyword_android> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_bind_platform = Platform::Android;
-		}
-	};
-} // namespace broma
\ No newline at end of file
diff --git a/codegen/Broma/src/broma.cpp b/codegen/Broma/src/broma.cpp
deleted file mode 100644
index d3434774..00000000
--- a/codegen/Broma/src/broma.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-#include <tao/pegtl.hpp>
-#include <iostream>
-
-#include "attribute.hpp"
-#include "basic_components.hpp"
-#include "function.hpp"
-#include "member.hpp"
-#include "state.hpp"
-#include "post_process.hpp"
-#include "preprocessor.hpp"
-
-using namespace tao::pegtl;
-
-namespace broma {
-	struct inline_expr : 
-		if_must<
-			keyword_inline,
-			if_then_else<
-				at<rematch<until<eolf>, until<one<'{'>>>>,
-				until<brace_start>,
-				until<eolf>
-			>
-		> {};
-
-	template <>
-	struct run_action<inline_expr> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			InlineField inf;
-			inf.inner = input.string();
-
-			scratch->wip_field.inner = inf;
-		}
-	};
-
-	struct field : sor<inline_expr, pad_expr, member_expr, bind_expr, ool_expr> {};
-
-	template <>
-	struct run_action<field> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_field.parent = scratch->wip_class.name;
-			static size_t index = 0;
-			scratch->wip_field.field_id = index++;
-			scratch->wip_class.fields.push_back(scratch->wip_field);
-		}
-	};
-
-
-	struct class_statement : 
-		seq<
-			opt<attribute>,
-			sep,
-			must<keyword_class>,
-			whitespace,
-			must<$named_rule("class name", qualified)>,
-			sep,
-			opt_must<
-				one<':'>,
-				sep,
-				list<seq<
-					sep,
-					$named_rule("superclass", qualified),
-					sep
-				>, one<','>>
-			>,
-			one<'{'>,
-			sep,
-			until<one<'}'>, sep, must<field>, sep>
-		> {};
-
-	template <>
-	struct run_action<$named_rule("superclass", qualified)> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			if (scratch->wip_class.name == input.string())
-				throw parse_error("Class subclasses itself", input.position());
-
-			scratch->wip_class.superclasses.push_back(input.string());
-			scratch->wip_class.depends.push_back(input.string());
-		}
-	};
-
-	template <>
-	struct run_action<$named_rule("class name", qualified)> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_class.name = input.string();
-
-			if (std::find(root->classes.begin(), root->classes.end(), input.string()) != root->classes.end()) {
-				scratch->errors.push_back(parse_error("Class duplicate!", input.position()));
-			}
-		}
-	};
-
-
-	template <>
-	struct run_action<class_statement> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			root->classes.push_back(std::move(scratch->wip_class));
-			//std::cout << "class end\n";
-			scratch->wip_class = Class();
-		}
-	};
-
-	struct root_grammar : until<eof, sep, must<sor<include_expr, class_statement>>, sep> {};
-
-	Root parse_file(std::string const& fname) {
-		file_input<> input(fname);
-
-		Root root;
-		ScratchData scratch;
-		parse<must<root_grammar>, run_action>(input, &root, &scratch);
-		post_process(root);
-
-		if (scratch.errors.size()) {
-			std::cerr << "[Broma] errors found on parsing: \n";
-
-			for (auto& e : scratch.errors) {
-				std::cerr << "\t" << e.what() << "\n";
-			}
-
-			//abort();
-		}
-
-		return root;
-	}
-} // namespace broma
diff --git a/codegen/Broma/src/function.hpp b/codegen/Broma/src/function.hpp
deleted file mode 100644
index 8a80236c..00000000
--- a/codegen/Broma/src/function.hpp
+++ /dev/null
@@ -1,152 +0,0 @@
-#pragma once
-
-#include <tao/pegtl.hpp>
-using namespace tao::pegtl;
-
-#include "basic_components.hpp"
-#include "attribute.hpp"
-#include "type.hpp"
-#include "bind.hpp"
-#include "state.hpp"
-
-namespace broma {
-	struct function_begin :
-		seq<rule_begin<function_begin>, opt<attribute>, sep, sor<
-			// ctor, dtor
-			seq<
-				$named_rule("structor", success),
-				opt<pad_space<keyword_virtual>>,
-				opt<tagged_rule<function_begin, one<'~'>>>,
-				tagged_rule<function_begin, identifier>,
-				arg_list
-			>,
-
-			// not ctor, dtor
-			if_then_must<
-				sor<keyword_static, keyword_virtual>,
-				$named_rule("fn_normal", success),
-				sep,
-				tagged_rule<function_begin, type>,
-				sep,
-				tagged_rule<function_begin, identifier>, 
-				arg_list,
-				sep,
-				opt<tagged_rule<function_begin, keyword_const>>
-			>
-		>> {};
-
-	template <>
-	struct run_action<rule_begin<function_begin>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_fn_begin = FunctionBegin();
-		}
-	};
-
-	template <>
-	struct run_action<function_begin> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			for (auto& f : scratch->wip_class.fields) {
-				if (auto fn = f.get_fn()) {
-					if (*fn == scratch->wip_fn_begin) {
-						scratch->errors.push_back(parse_error("Function duplicate!", input.position()));
-					}
-				}
-			}
-		}
-	};
-
-	template <>
-	struct run_action<tagged_rule<function_begin, identifier>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_fn_begin.name = input.string();
-
-			if (scratch->wip_fn_begin.type == FunctionType::Dtor)
-				scratch->wip_fn_begin.name = "~" + scratch->wip_fn_begin.name;
-		}
-	};
-
-	template <>
-	struct run_action<tagged_rule<function_begin, keyword_const>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_fn_begin.is_const = true;
-		}
-	};
-
-	template <>
-	struct run_action<tagged_rule<function_begin, type>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_fn_begin.ret = scratch->wip_type;
-		}
-	};
-
-	template <>
-	struct run_action<$named_rule("fn_normal", success)> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_fn_begin.type = FunctionType::Normal;
-		}
-	};
-
-	template <>
-	struct run_action<$named_rule("structor", success)> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_fn_begin.type = FunctionType::Ctor;
-		}
-	};
-
-	template <>
-	struct run_action<keyword_static> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_fn_begin.is_static = true;
-		}
-	};
-
-	template <>
-	struct run_action<tagged_rule<function_begin, one<'~'>>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_fn_begin.type = FunctionType::Dtor;
-		}
-	};
-
-	template <>
-	struct run_action<keyword_virtual> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_fn_begin.is_virtual = true;
-		}
-	};
-
-	struct ool_expr : seq<function_begin, sep, tagged_rule<ool_expr, brace_start>> {};
-
-	template <>
-	struct run_action<tagged_rule<ool_expr, brace_start>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			OutOfLineField f;
-			f.beginning = scratch->wip_fn_begin;
-			f.inner = input.string();
-			scratch->wip_field.inner = f;
-		}
-	};
-
-	struct bind_expr : seq<function_begin, sep, bind> {};
-
-	template <>
-	struct run_action<bind_expr> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			FunctionBindField f;
-			f.beginning = scratch->wip_fn_begin;
-			f.binds = scratch->wip_bind;
-			scratch->wip_field.inner = f;
-		}
-	};
-} // namespace broma
\ No newline at end of file
diff --git a/codegen/Broma/src/member.hpp b/codegen/Broma/src/member.hpp
deleted file mode 100644
index 7a9a8b96..00000000
--- a/codegen/Broma/src/member.hpp
+++ /dev/null
@@ -1,68 +0,0 @@
-#pragma once
-
-#include <tao/pegtl.hpp>
-using namespace tao::pegtl;
-
-#include "type.hpp"
-#include "bind.hpp"
-#include "state.hpp"
-
-namespace broma {
-	struct member_expr : 
-		seq<
-			rule_begin<member_expr>,
-			type,
-			whitespace,
-			tagged_rule<member_expr, identifier>,
-			sep,
-			opt<array>,
-			sep,
-			one<';'>
-		> {};
-
-	template <>
-	struct run_action<rule_begin<member_expr>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			MemberField f;
-			scratch->wip_field.inner = f;
-		}
-	};
-
-	template <>
-	struct run_action<tagged_rule<member_expr, identifier>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_field.get_as<MemberField>()->name = input.string();
-		}
-	};
-
-	template <>
-	struct run_action<member_expr> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_field.get_as<MemberField>()->type = scratch->wip_type;
-		}
-	};
-
-	struct pad_expr : seq<keyword_PAD, sep, bind> {};
-
-	template <>
-	struct run_action<keyword_PAD> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			PadField f;
-			PlatformNumber p;
-			scratch->wip_field.inner = f;
-			scratch->wip_bind = p;
-		}
-	};
-
-	template <>
-	struct run_action<pad_expr> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_field.get_as<PadField>()->amount = scratch->wip_bind;
-		}
-	};
-} // namespace broma
diff --git a/codegen/Broma/src/post_process.hpp b/codegen/Broma/src/post_process.hpp
deleted file mode 100644
index aa4f7c03..00000000
--- a/codegen/Broma/src/post_process.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include "state.hpp"
-#include <algorithm>
-#include <iostream>
-
-namespace broma {
-    inline void sortClass(Class cls, Root& root, std::vector<Class>& output) {
-        root.classes.erase(std::remove(root.classes.begin(), root.classes.end(), cls), root.classes.end());
-        for (auto name : cls.depends) {
-            if (root[name])
-                sortClass(*root[name], root, output);
-        }
-        output.push_back(cls);
-    }
-
-    inline void post_process(Root& root) {
-        std::vector<Class> out;
-
-        while (root.classes.size())
-            sortClass(root.classes[0], root, out);
-
-        root.classes = out;
-    }
-}
\ No newline at end of file
diff --git a/codegen/Broma/src/preprocessor.hpp b/codegen/Broma/src/preprocessor.hpp
deleted file mode 100644
index 403aa433..00000000
--- a/codegen/Broma/src/preprocessor.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "basic_components.hpp"
-#include "state.hpp"
-
-namespace broma {
-	struct include_name : until<at<one<'>'>>> {};
-
-	struct include_expr : seq<ascii::string<'#', 'i', 'n', 'c', 'l', 'u', 'd', 'e'>, sep, one<'<'>, include_name, one<'>'>> {};
-
-	struct root_grammar;
-
-	template <>
-	struct run_action<include_name> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			file_input<> file_input(input.string());
-
-			parse<root_grammar, broma::run_action>(file_input, root, scratch);
-		}
-	};
-} // namespace broma
diff --git a/codegen/Broma/src/state.hpp b/codegen/Broma/src/state.hpp
deleted file mode 100644
index 0ebabc4b..00000000
--- a/codegen/Broma/src/state.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include <tao/pegtl.hpp>
-#include <ast.hpp>
-
-namespace broma {
-	template <typename Rule>
-	struct run_action {};
-
-	struct ScratchData {
-		Class wip_class;
-		Field wip_field;
-		PlatformNumber wip_bind;
-		Platform wip_bind_platform;
-		Type wip_type;
-		FunctionBegin wip_fn_begin;
-
-		std::vector<tao::pegtl::parse_error> errors;
-	};
-} // namespace broma
diff --git a/codegen/Broma/src/type.hpp b/codegen/Broma/src/type.hpp
deleted file mode 100644
index 7e499639..00000000
--- a/codegen/Broma/src/type.hpp
+++ /dev/null
@@ -1,103 +0,0 @@
-#pragma once
-
-#include <tao/pegtl.hpp>
-using namespace tao::pegtl;
-
-#include "basic_components.hpp"
-#include "state.hpp"
-
-namespace broma {
-	struct type_content : 
-		if_then_must<
-			pad_space<sor<keyword_const, keyword_struct>>,
-
-			sor<pad_space<keyword_const>, pad_space<keyword_struct>, success>,
-
-			if_then_else<pad_space<keyword_unsigned>, opt<qualified>, qualified>,
-
-			opt<rpad_space<keyword_const>>,
-			star<seq<sep, one<'&', '*'>>>
-		> {};
-
-	struct type : seq<rule_begin<type>, sep, type_content> {};
-
-	template <>
-	struct run_action<rule_begin<type>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_type = Type();
-		}
-	};
-
-	template <>
-	struct run_action<keyword_struct> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_type.is_struct = true;
-		}
-	};
-
-	template <>
-	struct run_action<type_content> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_type.name = input.string();
-		}
-	};
-
-	struct array : if_must<one<'['>, tagged_rule<array, plus<ascii::digit>>, one<']'>> {};
-
-	template <>
-	struct run_action<tagged_rule<array, plus<ascii::digit>>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_field.get_as<MemberField>()->count = std::stoul(input.string(), nullptr, 10);
-		}
-	};
-
-	struct arg_name : opt<identifier> {};
-	struct arg_list : 
-		seq<
-			rule_begin<arg_list>,
-			one<'('>,
-			if_then_else<
-				at<one<')'>>,
-				success,
-				list<seq<
-					sep,
-					tagged_rule<arg_list, type>,
-					sep,
-					arg_name,
-					sep
-				>, one<','>>
-			>,
-			one<')'>
-		> {};
-
-	template <>
-	struct run_action<rule_begin<arg_list>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_fn_begin.args.clear();
-		}
-	};
-
-	template <>
-	struct run_action<tagged_rule<arg_list, type>> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			scratch->wip_fn_begin.args.push_back({scratch->wip_type, ""});
-		}
-	};
-
-	template <>
-	struct run_action<arg_name> {
-		template <typename T>
-		static void apply(T& input, Root* root, ScratchData* scratch) {
-			if (input.string() == "")
-				scratch->wip_fn_begin.args.back().second = std::string("p") + std::to_string(scratch->wip_fn_begin.args.size() - 1);
-			else
-				scratch->wip_fn_begin.args.back().second = input.string();
-		}
-	};
-} // namespace broma
diff --git a/codegen/CMakeLists.txt b/codegen/CMakeLists.txt
index 8ca25975..f0257203 100644
--- a/codegen/CMakeLists.txt
+++ b/codegen/CMakeLists.txt
@@ -4,10 +4,7 @@ project(Codegen LANGUAGES C CXX)
 include(../cmake/CPM.cmake)
 
 CPMAddPackage("gh:fmtlib/fmt#9.1.0")
-CPMAddPackage("gh:gulrak/filesystem#3e5b930")
-CPMAddPackage("gh:matcool/PEGTL#8faeb5d")
-
-add_subdirectory(Broma)
+CPMAddPackage("gh:camila314/Broma#1.0.0")
 
 file(GLOB SOURCES
 	${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
@@ -16,7 +13,7 @@ file(GLOB SOURCES
 add_executable(${PROJECT_NAME} ${SOURCES})
 target_compile_features(Codegen PUBLIC cxx_std_17)
 
-target_link_libraries(Codegen PRIVATE fmt::fmt Broma ghc_filesystem)
+target_link_libraries(Codegen PRIVATE fmt::fmt Broma)
 target_include_directories(Codegen PRIVATE 
 	${CMAKE_CURRENT_SOURCE_DIR}/src
 )
diff --git a/loader/include/Geode/loader/Loader.hpp b/loader/include/Geode/loader/Loader.hpp
index 2f2c7f83..7aff8f64 100644
--- a/loader/include/Geode/loader/Loader.hpp
+++ b/loader/include/Geode/loader/Loader.hpp
@@ -17,7 +17,7 @@ namespace geode {
         std::string reason;
     };
 
-    class InternalLoader;
+    class LoaderImpl;
 
     class GEODE_DLL Loader {
     private:
@@ -59,7 +59,7 @@ namespace geode {
         bool isModLoaded(std::string const& id) const;
         Mod* getLoadedMod(std::string const& id) const;
         std::vector<Mod*> getAllMods();
-        Mod* getInternalMod();
+        Mod* getModImpl();
         void updateAllDependencies();
         std::vector<InvalidGeodeFile> getFailedMods() const;
 
@@ -79,7 +79,7 @@ namespace geode {
 
         bool didLastLaunchCrash() const;
 
-        friend class InternalLoader;
+        friend class LoaderImpl;
 
         friend Mod* takeNextLoaderMod();
     };
diff --git a/loader/include/Geode/loader/Mod.hpp b/loader/include/Geode/loader/Mod.hpp
index 3e957209..7025de87 100644
--- a/loader/include/Geode/loader/Mod.hpp
+++ b/loader/include/Geode/loader/Mod.hpp
@@ -33,7 +33,7 @@ namespace geode {
 
     GEODE_HIDDEN Mod* takeNextLoaderMod();
 
-    class InternalMod;
+    class ModImpl;
 
     /**
      * @class Mod
@@ -344,7 +344,7 @@ namespace geode {
          */
         ModJson getRuntimeInfo() const;
 
-        friend class InternalMod;
+        friend class ModImpl;
     };
 
     /**
diff --git a/loader/src/hooks/LoadingLayer.cpp b/loader/src/hooks/LoadingLayer.cpp
index a9cd02c5..ecabff42 100644
--- a/loader/src/hooks/LoadingLayer.cpp
+++ b/loader/src/hooks/LoadingLayer.cpp
@@ -3,7 +3,7 @@
 #include <Geode/utils/cocos.hpp>
 #include <array>
 #include <fmt/format.h>
-#include <loader/InternalLoader.hpp>
+#include <loader/LoaderImpl.hpp>
 
 USE_GEODE_NAMESPACE();
 
@@ -36,7 +36,7 @@ struct CustomLoadingLayer : Modify<CustomLoadingLayer, LoadingLayer> {
         ));
 
         // verify loader resources
-        if (!InternalLoader::get()->verifyLoaderResources()) {
+        if (!LoaderImpl::get()->verifyLoaderResources()) {
             m_fields->m_updatingResources = true;
             this->setUpdateText("Downloading Resources");
         }
@@ -61,7 +61,7 @@ struct CustomLoadingLayer : Modify<CustomLoadingLayer, LoadingLayer> {
                 this->loadAssets();
             },
             [&](UpdateFailed const& error) {
-                InternalLoader::get()->platformMessageBox(
+                LoaderImpl::get()->platformMessageBox(
                     "Error updating resources",
                     error + ".\n"
                     "You will have to install resources manually by downloading resources.zip "
diff --git a/loader/src/hooks/MenuLayer.cpp b/loader/src/hooks/MenuLayer.cpp
index 56311768..889568e5 100644
--- a/loader/src/hooks/MenuLayer.cpp
+++ b/loader/src/hooks/MenuLayer.cpp
@@ -10,7 +10,7 @@
 #include <Geode/ui/Notification.hpp>
 #include <Geode/ui/Popup.hpp>
 #include <Geode/utils/cocos.hpp>
-#include <loader/InternalMod.hpp>
+#include <loader/ModImpl.hpp>
 
 USE_GEODE_NAMESPACE();
 
@@ -102,7 +102,7 @@ struct CustomMenuLayer : Modify<CustomMenuLayer, MenuLayer> {
                 "Send",
                 [](auto, bool btn2) {
                     if (btn2) {
-                        geode::openIssueReportPopup(InternalMod::get());
+                        geode::openIssueReportPopup(Mod::get());
                     }
                 },
                 false
diff --git a/loader/src/hooks/update.cpp b/loader/src/hooks/update.cpp
index e0f31d8f..80f90399 100644
--- a/loader/src/hooks/update.cpp
+++ b/loader/src/hooks/update.cpp
@@ -1,4 +1,4 @@
-#include <loader/InternalLoader.hpp>
+#include <loader/LoaderImpl.hpp>
 
 USE_GEODE_NAMESPACE();
 
@@ -6,7 +6,7 @@ USE_GEODE_NAMESPACE();
 
 struct FunctionQueue : Modify<FunctionQueue, CCScheduler> {
     void update(float dt) {
-        InternalLoader::get()->executeGDThreadQueue();
+        LoaderImpl::get()->executeGDThreadQueue();
         return CCScheduler::update(dt);
     }
 };
diff --git a/loader/src/ids/EditLevelLayer.cpp b/loader/src/ids/EditLevelLayer.cpp
new file mode 100644
index 00000000..6c7d94aa
--- /dev/null
+++ b/loader/src/ids/EditLevelLayer.cpp
@@ -0,0 +1,69 @@
+#include <Geode/modify/EditLevelLayer.hpp>
+#include <Geode/Bindings.hpp>
+#include <Geode/utils/cocos.hpp>
+#include "AddIDs.hpp"
+
+USE_GEODE_NAMESPACE();
+
+$register_ids(EditLevelLayer) {
+    setIDs(this, 0,
+        "background",
+        "bottom-left-art",
+        "bottom-right-art",
+        "level-name-background",
+        "level-name-input",
+        "description-background",
+        "description-input",
+        "description-text-area",
+        "level-action-menu",
+        "level-length",
+        "level-song",
+        "level-verified",
+        "version-label",
+        "level-id-label",
+        "right-side-menu",
+        "back-button-menu",
+        "info-button-menu"
+    );
+
+    if (auto menu = this->getChildByID("level-action-menu")) {
+        setIDs(menu, 0,
+            "edit-button",
+            "play-button",
+            "share-button"
+        );
+    }
+
+    if (auto menu = this->getChildByID("right-side-menu")) {
+        setIDs(menu, 0,
+            "delete-button",
+            "help-button",
+            "duplicate-button",
+            "move-to-top-button",
+            "folder-button"
+        );
+
+        detachAndCreateMenu(menu,
+            "folder-menu",
+            ColumnLayout::create(),
+            menu->getChildByID("folder-button")
+        );
+    }
+
+    if (auto menu = this->getChildByID("back-button-menu"))
+        setIDSafe(menu, 0, "back-button");
+
+    if (auto menu = this->getChildByID("info-button-menu"))
+        setIDSafe(menu, 0, "info-button");
+}
+
+class $modify(EditLevelLayer) {
+    bool init(GJGameLevel* l) {
+        if (!EditLevelLayer::init(l))
+            return false;
+        
+        NodeIDs::get()->provide(this);
+
+        return true;
+    }
+};
diff --git a/loader/src/ids/EditorUI.cpp b/loader/src/ids/EditorUI.cpp
index 47be54e2..994cb774 100644
--- a/loader/src/ids/EditorUI.cpp
+++ b/loader/src/ids/EditorUI.cpp
@@ -1,4 +1,4 @@
-#include <Geode/Modify.hpp>
+#include <Geode/modify/EditorUI.hpp>
 #include <Geode/Bindings.hpp>
 #include <Geode/utils/cocos.hpp>
 #include "AddIDs.hpp"
diff --git a/loader/src/ids/GJGarageLayer.cpp b/loader/src/ids/GJGarageLayer.cpp
index 0cda6a38..3d3be698 100644
--- a/loader/src/ids/GJGarageLayer.cpp
+++ b/loader/src/ids/GJGarageLayer.cpp
@@ -1,4 +1,4 @@
-#include <Geode/Modify.hpp>
+#include <Geode/modify/GJGarageLayer.hpp>
 #include <Geode/Bindings.hpp>
 #include <Geode/utils/cocos.hpp>
 #include "AddIDs.hpp"
diff --git a/loader/src/ids/LevelSettingsLayer.cpp b/loader/src/ids/LevelSettingsLayer.cpp
index 875127c8..2d0be165 100644
--- a/loader/src/ids/LevelSettingsLayer.cpp
+++ b/loader/src/ids/LevelSettingsLayer.cpp
@@ -6,71 +6,75 @@
 USE_GEODE_NAMESPACE();
 
 $register_ids(LevelSettingsLayer) {
+	bool startPos = m_mainLayer->getChildrenCount() < 10;
+
+	if (startPos) {
+		setIDSafe(m_mainLayer, 0, "back-button");
+	}
+
 	if (auto menu = getChildOfType<CCMenu>(m_mainLayer, 0)) {
 		menu->setID("song-select-menu");
 
-		setIDs(menu, 0,
-			"bg-color-button",
-			"g-color-button",
-			"g2-color-button",
-			"line-color-button",
-			"obj-color-button",
-			"more-color-button",
-			"3dl-color-button",
-			"bg-quick-edit-button",
-			"g-quick-edit-button",
-			"g2-quick-edit-button",
-			"line-quick-edit-button",
-			"cube-button",
-			"ship-button",
-			"ball-button",
-			"ufo-button",
-			"wave-button",
-			"robot-button",
-			"spider-button",
-			"background-select-button",
-			"ground-select-button",
-			"mini-toggle",
-			"dual-toggle",
-			"font-button",
-			"ok-button",
-			"2-player-toggle",
-			"2-player-help-button",
-			"prev-song-button",
-			"next-song-button",
-			"normal-song-button",
-			"custom-song-button",
-			"select-custom-song-button",
-			"new-song-button",
-			"half-speed-button",
-			"normal-speed-button",
-			"2x-speed-button",
-			"3x-speed-button",
-			"4x-speed-button"
-		);
-
-		detachAndCreateMenu(
-			this,
-			"color-button-menu",
-			RowLayout::create(),
-			menu->getChildByID("bg-color-button"),
-			menu->getChildByID("g-color-button"),
-			menu->getChildByID("g2-color-button"),
-			menu->getChildByID("line-color-button"),
-			menu->getChildByID("obj-color-button"),
-			menu->getChildByID("3dl-color-button"),
-			menu->getChildByID("more-color-button")
-		);
-
-		detachAndCreateMenu(
-			this,
-			"color-quick-edit-menu",
-			RowLayout::create(),
-			menu->getChildByID("bg-quick-edit-button"),
-			menu->getChildByID("g-quick-edit-button"),
-			menu->getChildByID("g2-quick-edit-button"),
-			menu->getChildByID("line-quick-edit-button")
-		);
+		if (startPos) {
+			setIDs(menu, 0,
+				"cube-button",
+				"ship-button",
+				"ball-button",
+				"ufo-button",
+				"wave-button",
+				"robot-button",
+				"spider-button",
+				"mini-toggle",
+				"dual-toggle",
+				"ok-button",
+				"flip-gravity-toggle",
+				"half-speed-button",
+				"normal-speed-button",
+				"2x-speed-button",
+				"3x-speed-button",
+				"4x-speed-button"
+			);
+		} else {
+			setIDs(menu, 0,
+				"bg-color-button",
+				"g-color-button",
+				"g2-color-button",
+				"line-color-button",
+				"obj-color-button",
+				"more-color-button",
+				"3dl-color-button",
+				"bg-quick-edit-button",
+				"g-quick-edit-button",
+				"g2-quick-edit-button",
+				"line-quick-edit-button",
+				"cube-button",
+				"ship-button",
+				"ball-button",
+				"ufo-button",
+				"wave-button",
+				"robot-button",
+				"spider-button",
+				"background-select-button",
+				"ground-select-button",
+				"mini-toggle",
+				"dual-toggle",
+				"font-button",
+				"ok-button",
+				"2-player-toggle",
+				"2-player-help-button",
+				"prev-song-button",
+				"next-song-button",
+				"normal-song-button",
+				"custom-song-button",
+				"select-custom-song-button",
+				"new-song-button",
+				"half-speed-button",
+				"normal-speed-button",
+				"2x-speed-button",
+				"3x-speed-button",
+				"4x-speed-button"
+			);
+		}
 
 		detachAndCreateMenu(
 			this,
@@ -85,14 +89,6 @@ $register_ids(LevelSettingsLayer) {
 			menu->getChildByID("spider-button")
 		);
 
-		detachAndCreateMenu(
-			this,
-			"scenery-selection-menu",
-			ColumnLayout::create(),
-			menu->getChildByID("background-select-button"),
-			menu->getChildByID("ground-select-button")
-		);
-
 		detachAndCreateMenu(
 			this,
 			"right-toggle-menu",
@@ -101,21 +97,6 @@ $register_ids(LevelSettingsLayer) {
 			menu->getChildByID("dual-toggle")
 		);
 
-		detachAndCreateMenu(
-			this,
-			"font-button-menu",
-			RowLayout::create()->setAlignment(Alignment::End),
-			menu->getChildByID("font-button")
-		);
-
-		detachAndCreateMenu(
-			this,
-			"2-player-menu",
-			ColumnLayout::create(),
-			menu->getChildByID("2-player-help-button"),
-			menu->getChildByID("2-player-toggle")
-		);
-
 		detachAndCreateMenu(
 			this,
 			"speed-selection-menu",
@@ -126,6 +107,61 @@ $register_ids(LevelSettingsLayer) {
 			menu->getChildByID("3x-speed-button"),
 			menu->getChildByID("4x-speed-button")
 		);
+
+		if (startPos) {
+			detachAndCreateMenu(
+				this,
+				"flip-gravity-menu",
+				ColumnLayout::create(),
+				menu->getChildByID("flip-gravity-toggle")
+			);
+		} else {
+			detachAndCreateMenu(
+				this,
+				"color-button-menu",
+				RowLayout::create(),
+				menu->getChildByID("bg-color-button"),
+				menu->getChildByID("g-color-button"),
+				menu->getChildByID("g2-color-button"),
+				menu->getChildByID("line-color-button"),
+				menu->getChildByID("obj-color-button"),
+				menu->getChildByID("3dl-color-button"),
+				menu->getChildByID("more-color-button")
+			);
+
+			detachAndCreateMenu(
+				this,
+				"color-quick-edit-menu",
+				RowLayout::create(),
+				menu->getChildByID("bg-quick-edit-button"),
+				menu->getChildByID("g-quick-edit-button"),
+				menu->getChildByID("g2-quick-edit-button"),
+				menu->getChildByID("line-quick-edit-button")
+			);
+
+			detachAndCreateMenu(
+				this,
+				"scenery-selection-menu",
+				ColumnLayout::create(),
+				menu->getChildByID("background-select-button"),
+				menu->getChildByID("ground-select-button")
+			);
+
+			detachAndCreateMenu(
+				this,
+				"2-player-menu",
+				ColumnLayout::create(),
+				menu->getChildByID("2-player-help-button"),
+				menu->getChildByID("2-player-toggle")
+			);
+
+			detachAndCreateMenu(
+				this,
+				"font-button-menu",
+				RowLayout::create()->setAlignment(Alignment::End),
+				menu->getChildByID("font-button")
+			);
+		}
 	}
 
 	setIDs(m_mainLayer, 2,
@@ -156,7 +192,7 @@ class $modify(LevelSettingsLayer) {
         if (!LevelSettingsLayer::init(levelSettings, editor))
             return false;
         
-        NodeIDs::get()->provide(this);
+        //NodeIDs::get()->provide(this);
 
         return true;
     }
diff --git a/loader/src/ids/PauseLayer.cpp b/loader/src/ids/PauseLayer.cpp
new file mode 100644
index 00000000..fa6d3622
--- /dev/null
+++ b/loader/src/ids/PauseLayer.cpp
@@ -0,0 +1,78 @@
+#include <Geode/modify/PauseLayer.hpp>
+#include <Geode/Bindings.hpp>
+#include <Geode/utils/cocos.hpp>
+#include "AddIDs.hpp"
+
+USE_GEODE_NAMESPACE();
+
+$register_ids(PauseLayer) {
+	setIDs(this, 0,
+		"background",
+		"level-name",
+
+		"normal-progress-bar",
+		"practice-progress-bar",
+		"normal-progress-label",
+		"practice-progress-label",
+		"normal-mode-label",
+		"practice-mode-label",
+
+		"center-button-menu",
+
+		"auto-retry-label",
+		"auto-checkpoints-label",
+		"show-progress-bar-label"
+	);
+
+	if (auto menu = this->getChildByID("center-button-menu")) {
+		int start_idx = 0;
+
+		if (menu->getChildrenCount() == 5) {
+			setIDSafe(menu, 0, "edit-button");
+			start_idx = 1;
+		}
+
+		setIDs(menu, start_idx,
+			"practice-button",
+			"play-button",
+			"exit-button"
+		);
+
+		if (menu->getChildrenCount() == 4)
+			setIDSafe(menu, start_idx + 3, "retry-button");
+	}
+
+	// Record toggle on mobile
+	if (auto label = typeinfo_cast<CCLabelBMFont*>(getChild(this, 12))) {
+		setIDSafe(this, 12, "record-label");
+	}
+
+	if (auto menu = getChildOfType<CCMenu>(this, 1)) {
+		menu->setID("toggle-menu");
+
+		setIDs(menu, 0,
+			"auto-retry-toggle",
+			"auto-checkpoints-toggle",
+			"show-progress-bar-toggle"
+		);
+
+		if (menu->getChildrenCount() == 4)
+			setIDSafe(menu, 3, "record-toggle");
+	}
+
+
+	setIDs(this, this->getChildrenCount() - 4,
+		"music-slider",
+		"sfx-slider",
+		"music-label",
+		"sfx-label"
+	);
+}
+
+class $modify(PauseLayer) {
+    void customSetup() {
+        PauseLayer::customSetup();
+        
+        NodeIDs::get()->provide(this);
+    }
+};
diff --git a/loader/src/ids/UILayer.cpp b/loader/src/ids/UILayer.cpp
index 07832777..648f95a3 100644
--- a/loader/src/ids/UILayer.cpp
+++ b/loader/src/ids/UILayer.cpp
@@ -1,4 +1,4 @@
-#include <Geode/Modify.hpp>
+#include <Geode/modify/UILayer.hpp>
 #include <Geode/Bindings.hpp>
 #include <Geode/utils/cocos.hpp>
 #include "AddIDs.hpp"
diff --git a/loader/src/loader/Hook.cpp b/loader/src/loader/Hook.cpp
index 72188dac..670f0db4 100644
--- a/loader/src/loader/Hook.cpp
+++ b/loader/src/loader/Hook.cpp
@@ -5,7 +5,7 @@
 #include <Geode/utils/ranges.hpp>
 #include <vector>
 // #include <hook/hook.hpp>
-#include "InternalMod.hpp"
+#include "ModImpl.hpp"
 
 #include <Geode/hook-core/Hook.hpp>
 
diff --git a/loader/src/loader/Loader.cpp b/loader/src/loader/Loader.cpp
index 0285ee0b..449b867a 100644
--- a/loader/src/loader/Loader.cpp
+++ b/loader/src/loader/Loader.cpp
@@ -1,4 +1,4 @@
-#include "InternalLoader.hpp"
+#include "LoaderImpl.hpp"
 
 USE_GEODE_NAMESPACE();
 
@@ -83,8 +83,8 @@ std::vector<Mod*> Loader::getAllMods() {
     return m_impl->getAllMods();
 }
 
-Mod* Loader::getInternalMod() {
-    return m_impl->getInternalMod();
+Mod* Loader::getModImpl() {
+    return m_impl->getModImpl();
 }
 
 void Loader::updateAllDependencies() {
diff --git a/loader/src/loader/InternalLoader.cpp b/loader/src/loader/LoaderImpl.cpp
similarity index 92%
rename from loader/src/loader/InternalLoader.cpp
rename to loader/src/loader/LoaderImpl.cpp
index 98df6efe..f2d0f75c 100644
--- a/loader/src/loader/InternalLoader.cpp
+++ b/loader/src/loader/LoaderImpl.cpp
@@ -1,5 +1,5 @@
 
-#include "InternalLoader.hpp"
+#include "LoaderImpl.hpp"
 #include <cocos2d.h>
 #include <Geode/loader/Dirs.hpp>
 #include <Geode/loader/IPC.hpp>
@@ -10,7 +10,7 @@
 #include <Geode/utils/map.hpp>
 #include <Geode/utils/ranges.hpp>
 #include <Geode/utils/web.hpp>
-#include "InternalMod.hpp"
+#include "ModImpl.hpp"
 #include <about.hpp>
 #include <crashlog.hpp>
 #include <fmt/format.h>
@@ -24,7 +24,7 @@
 
 USE_GEODE_NAMESPACE();
 
-Loader::Impl* InternalLoader::get() {
+Loader::Impl* LoaderImpl::get() {
     return Loader::get()->m_impl.get();
 }
 
@@ -105,7 +105,7 @@ void Loader::Impl::updateResources() {
     log::debug("Adding resources");
 
     // add own spritesheets
-    this->updateModResources(InternalMod::get());
+    this->updateModResources(Mod::get());
 
     // add mods' spritesheets
     for (auto const& [_, mod] : m_mods) {
@@ -117,8 +117,8 @@ std::vector<Mod*> Loader::Impl::getAllMods() {
     return map::values(m_mods);
 }
 
-Mod* Loader::Impl::getInternalMod() {
-    return InternalMod::get();
+Mod* Loader::Impl::getModImpl() {
+    return Mod::get();
 }
 
 std::vector<InvalidGeodeFile> Loader::Impl::getFailedMods() const {
@@ -155,20 +155,20 @@ bool Loader::Impl::isModVersionSupported(VersionInfo const& version) {
 Result<> Loader::Impl::saveData() {
     // save mods' data
     for (auto& [id, mod] : m_mods) {
-        InternalMod::get()->setSavedValue("should-load-" + id, mod->isEnabled());
+        Mod::get()->setSavedValue("should-load-" + id, mod->isEnabled());
         auto r = mod->saveData();
         if (!r) {
             log::warn("Unable to save data for mod \"{}\": {}", mod->getID(), r.unwrapErr());
         }
     }
     // save loader data
-    GEODE_UNWRAP(InternalMod::get()->saveData());
+    GEODE_UNWRAP(Mod::get()->saveData());
     
     return Ok();
 }
 
 Result<> Loader::Impl::loadData() {
-    auto e = InternalMod::get()->loadData();
+    auto e = Mod::get()->loadData();
     if (!e) {
         log::warn("Unable to load loader settings: {}", e.unwrapErr());
     }
@@ -199,7 +199,7 @@ Result<Mod*> Loader::Impl::loadModFromInfo(ModInfo const& info) {
     }
 
     m_mods.insert({ info.id, mod });
-    mod->m_impl->m_enabled = InternalMod::get()->getSavedValue<bool>(
+    mod->m_impl->m_enabled = Mod::get()->getSavedValue<bool>(
         "should-load-" + info.id, true
     );
 
@@ -466,7 +466,7 @@ bool Loader::Impl::platformConsoleOpen() const {
 void Loader::Impl::downloadLoaderResources() {
     auto version = this->getVersion().toString();
     auto tempResourcesZip = dirs::getTempDir() / "new.zip";
-    auto resourcesDir = dirs::getGeodeResourcesDir() / InternalMod::get()->getID();
+    auto resourcesDir = dirs::getGeodeResourcesDir() / Mod::get()->getID();
 
     web::AsyncWebRequest()
         .join("update-geode-loader-resources")
@@ -506,7 +506,7 @@ bool Loader::Impl::verifyLoaderResources() {
     }
 
     // geode/resources/geode.loader
-    auto resourcesDir = dirs::getGeodeResourcesDir() / InternalMod::get()->getID();
+    auto resourcesDir = dirs::getGeodeResourcesDir() / Mod::get()->getID();
 
     // if the resources dir doesn't exist, then it's probably incorrect
     if (!(
@@ -595,7 +595,8 @@ void Loader::Impl::provideNextMod(Mod* mod) {
 
 Mod* Loader::Impl::takeNextMod() {
     if (!m_nextMod) {
-        return InternalMod::get();
+        this->setupInternalMod();
+        m_nextMod = Mod::sharedMod<>;
     }
     auto ret = m_nextMod;
     return ret;
diff --git a/loader/src/loader/InternalLoader.hpp b/loader/src/loader/LoaderImpl.hpp
similarity index 97%
rename from loader/src/loader/InternalLoader.hpp
rename to loader/src/loader/LoaderImpl.hpp
index dfed875b..f9957308 100644
--- a/loader/src/loader/InternalLoader.hpp
+++ b/loader/src/loader/LoaderImpl.hpp
@@ -9,7 +9,7 @@
 #include <Geode/utils/Result.hpp>
 #include <Geode/utils/map.hpp>
 #include <Geode/utils/ranges.hpp>
-#include "InternalMod.hpp"
+#include "ModImpl.hpp"
 #include <about.hpp>
 #include <crashlog.hpp>
 #include <mutex>
@@ -100,7 +100,7 @@ namespace geode {
         bool isModLoaded(std::string const& id) const;
         Mod* getLoadedMod(std::string const& id) const;
         std::vector<Mod*> getAllMods();
-        Mod* getInternalMod();
+        Mod* getModImpl();
         void updateAllDependencies();
         std::vector<InvalidGeodeFile> getFailedMods() const;
 
@@ -125,9 +125,11 @@ namespace geode {
 
         bool isReadyToHook() const;
         void addInternalHook(Hook* hook, Mod* mod);
+
+        void setupInternalMod();
     };
 
-    class InternalLoader {
+    class LoaderImpl {
     public:
         static Loader::Impl* get();
     };
diff --git a/loader/src/loader/Log.cpp b/loader/src/loader/Log.cpp
index 7dcf3cdd..c9204b71 100644
--- a/loader/src/loader/Log.cpp
+++ b/loader/src/loader/Log.cpp
@@ -1,4 +1,4 @@
-#include "InternalLoader.hpp"
+#include "LoaderImpl.hpp"
 
 #include <Geode/loader/Dirs.hpp>
 #include <Geode/loader/Log.hpp>
@@ -190,7 +190,7 @@ void Logger::setup() {
 void Logger::_push(Log&& log) {
     std::string logStr = log.toString(true);
 
-    InternalLoader::get()->logConsoleMessage(logStr);
+    LoaderImpl::get()->logConsoleMessage(logStr);
     s_logStream << logStr << std::endl;
 
     s_logs.emplace_back(std::forward<Log>(log));
diff --git a/loader/src/loader/Mod.cpp b/loader/src/loader/Mod.cpp
index 9060e358..749113e5 100644
--- a/loader/src/loader/Mod.cpp
+++ b/loader/src/loader/Mod.cpp
@@ -1,5 +1,5 @@
 #include <Geode/loader/Mod.hpp>
-#include "InternalMod.hpp"
+#include "ModImpl.hpp"
 
 USE_GEODE_NAMESPACE();
 
diff --git a/loader/src/loader/InternalMod.cpp b/loader/src/loader/ModImpl.cpp
similarity index 96%
rename from loader/src/loader/InternalMod.cpp
rename to loader/src/loader/ModImpl.cpp
index abe1619a..b0de1ef1 100644
--- a/loader/src/loader/InternalMod.cpp
+++ b/loader/src/loader/ModImpl.cpp
@@ -1,5 +1,5 @@
-#include "InternalMod.hpp"
-#include "InternalLoader.hpp"
+#include "ModImpl.hpp"
+#include "LoaderImpl.hpp"
 #include "about.hpp"
 
 #include <Geode/loader/Dirs.hpp>
@@ -14,7 +14,7 @@
 
 USE_GEODE_NAMESPACE();
 
-Mod::Impl* InternalMod::getImpl(Mod* mod)  {
+Mod::Impl* ModImpl::getImpl(Mod* mod)  {
     return mod->m_impl.get();
 }
 
@@ -285,12 +285,12 @@ Result<> Mod::Impl::loadBinary() {
         return Err("Mod has unresolved dependencies");
     }
 
-    InternalLoader::get()->provideNextMod(this->m_self);
+    LoaderImpl::get()->provideNextMod(this->m_self);
 
     GEODE_UNWRAP(this->loadPlatformBinary());
     m_binaryLoaded = true;
 
-    InternalLoader::get()->releaseNextMod();
+    LoaderImpl::get()->releaseNextMod();
 
     ModStateEvent(this->m_self, ModEventType::Loaded).post();
 
@@ -402,7 +402,7 @@ Result<> Mod::Impl::uninstall() {
 }
 
 bool Mod::Impl::isUninstalled() const {
-    return this->m_self != InternalMod::get() && !ghc::filesystem::exists(m_info.path);
+    return this->m_self != Mod::get() && !ghc::filesystem::exists(m_info.path);
 }
 
 // Dependencies
@@ -490,7 +490,7 @@ Result<> Mod::Impl::disableHook(Hook* hook) {
 }
 
 Result<Hook*> Mod::Impl::addHook(Hook* hook) {
-    if (InternalLoader::get()->isReadyToHook()) {
+    if (LoaderImpl::get()->isReadyToHook()) {
         auto res = this->enableHook(hook);
         if (!res) {
             delete hook;
@@ -498,7 +498,7 @@ Result<Hook*> Mod::Impl::addHook(Hook* hook) {
         }
     }
     else {
-        InternalLoader::get()->addInternalHook(hook, this->m_self);
+        LoaderImpl::get()->addInternalHook(hook, this->m_self);
     }
 
     return Ok(hook);
@@ -630,12 +630,12 @@ static constexpr char const* SUPPORT_INFO = R"MD(
 You can support our work by sending <cp>**catgirl pictures**</c> to [HJfod](https://youtu.be/LOHSF9MmBDw) :))
 )MD";
 
-static ModInfo getInternalModInfo() {
+static ModInfo getModImplInfo() {
     try {
         auto json = ModJson::parse(LOADER_MOD_JSON);
         auto infoRes = ModInfo::create(json);
         if (infoRes.isErr()) {
-            InternalLoader::get()->platformMessageBox(
+            LoaderImpl::get()->platformMessageBox(
                 "Fatal Internal Error",
                 "Unable to parse loader mod.json: \"" + infoRes.unwrapErr() +
                     "\"\n"
@@ -651,7 +651,7 @@ static ModInfo getInternalModInfo() {
         return info;
     }
     catch (std::exception& e) {
-        InternalLoader::get()->platformMessageBox(
+        LoaderImpl::get()->platformMessageBox(
             "Fatal Internal Error",
             "Unable to parse loader mod.json: \"" + std::string(e.what()) +
                 "\"\n"
@@ -662,16 +662,13 @@ static ModInfo getInternalModInfo() {
     }
 }
 
-Mod* InternalMod::get() {
+void Loader::Impl::setupInternalMod() {
     auto& mod = Mod::sharedMod<>;
-    if (mod) return mod;
-
-    mod = new Mod(getInternalModInfo());
+    if (mod) return;
+    mod = new Mod(getModImplInfo());
 
     auto setupRes = mod->m_impl->setup();
     if (!setupRes) {
         log::error("Failed to setup internal mod! ({})", setupRes.unwrapErr());
-        return mod;
     }
-    return mod;
 }
\ No newline at end of file
diff --git a/loader/src/loader/InternalMod.hpp b/loader/src/loader/ModImpl.hpp
similarity index 99%
rename from loader/src/loader/InternalMod.hpp
rename to loader/src/loader/ModImpl.hpp
index ed0d8c4e..2d38d027 100644
--- a/loader/src/loader/InternalMod.hpp
+++ b/loader/src/loader/ModImpl.hpp
@@ -120,7 +120,7 @@ namespace geode {
         ModJson getRuntimeInfo() const;
     };
 
-    class InternalMod : public Mod {
+    class ModImpl : public Mod {
     public:
         static Mod* get();
 
diff --git a/loader/src/main.cpp b/loader/src/main.cpp
index 7b34ba46..04d8b051 100644
--- a/loader/src/main.cpp
+++ b/loader/src/main.cpp
@@ -1,5 +1,5 @@
 #include "../core/Core.hpp"
-#include "loader/InternalLoader.hpp"
+#include "loader/LoaderImpl.hpp"
 
 #include <Geode/loader/IPC.hpp>
 #include <Geode/loader/Loader.hpp>
@@ -7,7 +7,7 @@
 #include <Geode/loader/Mod.hpp>
 #include <Geode/loader/Setting.hpp>
 #include <Geode/loader/SettingEvent.hpp>
-#include <loader/InternalMod.hpp>
+#include <loader/ModImpl.hpp>
 #include <array>
 
 USE_GEODE_NAMESPACE();
@@ -114,7 +114,7 @@ $execute {
     });
 
     listenForIPC("loader-info", [](IPCEvent* event) -> nlohmann::json {
-        return Loader::get()->getInternalMod()->getModInfo();
+        return Loader::get()->getModImpl()->getModInfo();
     });
 
     listenForIPC("list-mods", [](IPCEvent* event) -> nlohmann::json {
@@ -129,8 +129,8 @@ $execute {
 
         if (!dontIncludeLoader) {
             res.push_back(
-                includeRunTimeInfo ? Loader::get()->getInternalMod()->getRuntimeInfo() :
-                                    Loader::get()->getInternalMod()->getModInfo().toJSON()
+                includeRunTimeInfo ? Loader::get()->getModImpl()->getRuntimeInfo() :
+                                    Loader::get()->getModImpl()->getModInfo().toJSON()
             );
         }
 
@@ -146,7 +146,7 @@ int geodeEntry(void* platformData) {
     // setup internals
 
     if (!geode::core::hook::initialize()) {
-        InternalLoader::get()->platformMessageBox(
+        LoaderImpl::get()->platformMessageBox(
             "Unable to load Geode!",
             "There was an unknown fatal error setting up "
             "internal tools and Geode can not be loaded. "
@@ -156,19 +156,19 @@ int geodeEntry(void* platformData) {
     }
 
     // set up loader, load mods, etc.
-    if (!InternalLoader::get()->setup()) {
-        InternalLoader::get()->platformMessageBox(
+    if (!LoaderImpl::get()->setup()) {
+        LoaderImpl::get()->platformMessageBox(
             "Unable to Load Geode!",
             "There was an unknown fatal error setting up "
             "the loader and Geode can not be loaded."
         );
-        InternalLoader::get()->reset();
+        LoaderImpl::get()->reset();
         return 1;
     }
 
     log::debug("Set up loader");
 
-    if (InternalMod::get()->getSettingValue<bool>("show-platform-console")) {
+    if (Mod::get()->getSettingValue<bool>("show-platform-console")) {
         Loader::get()->openPlatformConsole();
     }
 
diff --git a/loader/src/platform/ios/InternalLoader.cpp b/loader/src/platform/ios/LoaderImpl.cpp
similarity index 89%
rename from loader/src/platform/ios/InternalLoader.cpp
rename to loader/src/platform/ios/LoaderImpl.cpp
index 8b5f7557..514fe9e5 100644
--- a/loader/src/platform/ios/InternalLoader.cpp
+++ b/loader/src/platform/ios/LoaderImpl.cpp
@@ -1,11 +1,11 @@
-#include <loader/InternalLoader.hpp>
+#include <loader/LoaderImpl.hpp>
 
 #ifdef GEODE_IS_IOS
 
     #include <Geode/loader/Dirs.hpp>
     #include <Geode/loader/Loader.hpp>
     #include <Geode/loader/Log.hpp>
-    #include <loader/InternalMod.hpp>
+    #include <loader/ModImpl.hpp>
     #include <iostream>
     #include <pwd.h>
     #include <sys/types.h>
diff --git a/loader/src/platform/ios/InternalMod.cpp b/loader/src/platform/ios/ModImpl.cpp
similarity index 96%
rename from loader/src/platform/ios/InternalMod.cpp
rename to loader/src/platform/ios/ModImpl.cpp
index 61d32f21..f7538c40 100644
--- a/loader/src/platform/ios/InternalMod.cpp
+++ b/loader/src/platform/ios/ModImpl.cpp
@@ -3,7 +3,7 @@
 #ifdef GEODE_IS_IOS
 
     #include <Geode/loader/Mod.hpp>
-    #include <loader/InternalMod.hpp>
+    #include <loader/ModImpl.hpp>
     #include <dlfcn.h>
 
 USE_GEODE_NAMESPACE();
diff --git a/loader/src/platform/mac/InternalLoader.cpp b/loader/src/platform/mac/LoaderImpl.cpp
similarity index 90%
rename from loader/src/platform/mac/InternalLoader.cpp
rename to loader/src/platform/mac/LoaderImpl.cpp
index 4dee6225..ad266500 100644
--- a/loader/src/platform/mac/InternalLoader.cpp
+++ b/loader/src/platform/mac/LoaderImpl.cpp
@@ -1,8 +1,8 @@
 #include <Geode/loader/IPC.hpp>
 #include <Geode/loader/Log.hpp>
 #include <iostream>
-#include <loader/InternalLoader.hpp>
-#include <loader/InternalMod.hpp>
+#include <loader/LoaderImpl.hpp>
+#include <loader/ModImpl.hpp>
 
 #ifdef GEODE_IS_MACOS
 
@@ -36,7 +36,7 @@ CFDataRef msgPortCallback(CFMessagePortRef port, SInt32 messageID, CFDataRef dat
 
     std::string cdata(reinterpret_cast<char const*>(CFDataGetBytePtr(data)), CFDataGetLength(data));
 
-    std::string reply = InternalLoader::get()->processRawIPC(port, cdata);
+    std::string reply = LoaderImpl::get()->processRawIPC(port, cdata);
     return CFDataCreate(NULL, (UInt8 const*)reply.data(), reply.size());
 }
 
diff --git a/loader/src/platform/mac/InternalMod.cpp b/loader/src/platform/mac/ModImpl.cpp
similarity index 96%
rename from loader/src/platform/mac/InternalMod.cpp
rename to loader/src/platform/mac/ModImpl.cpp
index c91f4c96..ac5d4aa0 100644
--- a/loader/src/platform/mac/InternalMod.cpp
+++ b/loader/src/platform/mac/ModImpl.cpp
@@ -3,7 +3,7 @@
 #ifdef GEODE_IS_MACOS
 
     #include <Geode/loader/Mod.hpp>
-    #include <loader/InternalMod.hpp>
+    #include <loader/ModImpl.hpp>
     #include <dlfcn.h>
 
 USE_GEODE_NAMESPACE();
diff --git a/loader/src/platform/windows/InternalLoader.cpp b/loader/src/platform/windows/LoaderImpl.cpp
similarity index 91%
rename from loader/src/platform/windows/InternalLoader.cpp
rename to loader/src/platform/windows/LoaderImpl.cpp
index 65fa6015..a433646a 100644
--- a/loader/src/platform/windows/InternalLoader.cpp
+++ b/loader/src/platform/windows/LoaderImpl.cpp
@@ -1,8 +1,8 @@
 #include <Geode/loader/IPC.hpp>
 #include <Geode/loader/Log.hpp>
-#include <loader/InternalMod.hpp>
+#include <loader/ModImpl.hpp>
 #include <iostream>
-#include <loader/InternalLoader.hpp>
+#include <loader/LoaderImpl.hpp>
 
 USE_GEODE_NAMESPACE();
 
@@ -49,7 +49,7 @@ void ipcPipeThread(HANDLE pipe) {
     if (ReadFile(pipe, buffer, sizeof(buffer) - 1, &read, nullptr)) {
         buffer[read] = '\0';
 
-        std::string reply = InternalLoader::get()->processRawIPC((void*)pipe, buffer);
+        std::string reply = LoaderImpl::get()->processRawIPC((void*)pipe, buffer);
 
         DWORD written;
         WriteFile(pipe, reply.c_str(), reply.size(), &written, nullptr);
diff --git a/loader/src/platform/windows/InternalMod.cpp b/loader/src/platform/windows/ModImpl.cpp
similarity index 98%
rename from loader/src/platform/windows/InternalMod.cpp
rename to loader/src/platform/windows/ModImpl.cpp
index c0c51e4d..4075ee62 100644
--- a/loader/src/platform/windows/InternalMod.cpp
+++ b/loader/src/platform/windows/ModImpl.cpp
@@ -3,7 +3,7 @@
 #ifdef GEODE_IS_WINDOWS
 
 #include <Geode/loader/Mod.hpp>
-#include <loader/InternalMod.hpp>
+#include <loader/ModImpl.hpp>
 
 USE_GEODE_NAMESPACE();
 
diff --git a/loader/src/ui/internal/GeodeUI.cpp b/loader/src/ui/internal/GeodeUI.cpp
index bf24db94..806566a3 100644
--- a/loader/src/ui/internal/GeodeUI.cpp
+++ b/loader/src/ui/internal/GeodeUI.cpp
@@ -74,7 +74,7 @@ CCNode* geode::createDefaultLogo(CCSize const& size) {
 
 CCNode* geode::createModLogo(Mod* mod, CCSize const& size) {
     CCNode* spr = nullptr;
-    if (mod == Loader::get()->getInternalMod()) {
+    if (mod == Loader::get()->getModImpl()) {
         spr = CCSprite::createWithSpriteFrameName("geode-logo.png"_spr);
     }
     else {
diff --git a/loader/src/ui/internal/info/ModInfoPopup.cpp b/loader/src/ui/internal/info/ModInfoPopup.cpp
index 6d28a74c..d19eab75 100644
--- a/loader/src/ui/internal/info/ModInfoPopup.cpp
+++ b/loader/src/ui/internal/info/ModInfoPopup.cpp
@@ -21,7 +21,7 @@
 #include <Geode/utils/casts.hpp>
 #include <Geode/utils/ranges.hpp>
 #include <Geode/utils/web.hpp>
-#include <loader/InternalLoader.hpp>
+#include <loader/LoaderImpl.hpp>
 
 static constexpr int const TAG_CONFIRM_UNINSTALL = 5;
 static constexpr int const TAG_DELETE_SAVEDATA = 6;
@@ -323,7 +323,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) {
         disableBtnSpr->setColor({150, 150, 150});
     }
 
-    if (mod != Loader::get()->getInternalMod()) {
+    if (mod != Loader::get()->getModImpl()) {
         auto uninstallBtnSpr = ButtonSprite::create(
             "Uninstall", "bigFont.fnt", "GJ_button_05.png", .6f
         );
diff --git a/loader/src/ui/internal/list/ModListCell.cpp b/loader/src/ui/internal/list/ModListCell.cpp
index 551e3f26..bd4106f6 100644
--- a/loader/src/ui/internal/list/ModListCell.cpp
+++ b/loader/src/ui/internal/list/ModListCell.cpp
@@ -8,7 +8,7 @@
 #include <Geode/binding/FLAlertLayer.hpp>
 #include <Geode/binding/StatsCell.hpp>
 #include <Geode/ui/GeodeUI.hpp>
-#include <loader/InternalLoader.hpp>
+#include <loader/LoaderImpl.hpp>
 #include "../info/TagNode.hpp"
 #include "../info/DevProfilePopup.hpp"