Completed - Link - GitHub
Technologies Used: TypeScript, Obsidian
I use Obsidian for note-taking, and often use tags for things like Jira tickets. I created this plugin to allow me to use tags as links, and open their associated pages with a hotkey.


sent is a tool written in C that runs presentations that are written in a simple, plaintext format.
Unfortunately it only works on Linux X11-based platforms, and often work environments are Windows-based, so I created this tool in Rust as a multi-platform alternative. It supports the same file format and works in much the same way, but it has a few new features that the original lacks.

I switched all my devices and servers to using NixOS as their operating system. This has numerous benefits - all changes are tracked in Git, I can rollback changes that didn't go well, and I can have multiple versions of the same software installed simultaneously without issues.
It also includes my Neovim configuration, which I switched to about a year and a half later. This is a constantly-evolving setup.


A Hashcat module for cracking SponsorBlock IDs, created to help a friend with solving some administrative issues.
It runs on the GPU, cracking them in a similar way to password hashes.


A trust-based SPA website for tracking and managing devices used within a business, with multiple assignable locations and LDAP-based user authentication.
I designed it to be as simple to use as possible, requiring only one button press to re-assign a device. It also includes several checks to limit user error.
It's also designed to be as maintenance-free as possible, and the entire column setup is able to be edited and re-arranged without making code changes.

A Rust library client for interacting with SponsorBlock. I wrote this so that Radium could get the sponsor information for videos that it played in voice chats, to skip those segments automatically.

A small command-line tool to easily swap out file configurations using symbolic links, minimising the room for mistakes. It uses a config file that specifies all possible configurations and which files they should be swapped between. It's designed for situations where you regularly have to swap between sets of files in the same location, like for testing.

A Discord bot that I wrote for private use so that I could play music in voice chats after the Groovy bot died.
Later on, its features were expanded so that it could support dice-rolling for D&D.

Made using the Kiara 1 Dawn HDRI from Poly Haven. Done over a few days.
It started because I wanted to make a nice custom 60% keyboard model, but I did that within a few hours and decided to make it into a full render.
I soon found that the keyboard wasn't visually interesting enough on it's own, so I decided to add in some kind of snack. That snack ended up
becoming the focal point of the image, stealing the spotlight from the keyboard.
The honey was a great opportunity to practice fluid simulation - I had the simulation emitter animated moving back and forth in a way like one
might drizzle a sauce on something, and then picked a frame of the honey sim that looked good. The crackers were also simulated just dropping on the plate,
to give them the feeling of sitting naturally. The curtains in the background were handled in a similar way. I animated them being moved into place and ran a cloth simulation to get a really
natural look.
This is my second-ever render, done in Blender with the Cycles renderer. The artwork on the keyboard is the famous Japanese woodblock print The Great Wave off Kanagawa by Hokusai.

Made using the Veranda HDRI and Brown Planks #5 from Poly Haven. Done in a few hours or so, and my first real foray into making a render.

This project took months of work and was done with the logistical assistance of someone else, but the tool itself was made entirely by me.
NUS Ripper is a tool for, given a list of Nintendo DSi title IDs and file names: downloading, decrypting, and datting them for archival. This project
doesn't enable piracy of any kind, and was made entirely for the purpose of creating a single, really solid DAT for DSi titles.
A DAT is basically a standardized collection of data for a given system or set of titles. This includes high-level information about things
like languages and titles, and low-level information like hashes for each file of a game. Aside from simply preserving game metadata (not actual game
files), it exists to allow people to verify their collections of games are correct and clean.
This was made for the No-Intro database, one such database for cartridge-based system datting.

Originally made as part of the NUS Ripper project. In the NUS Ripper project, a part of the work was to clean and normalize the oft-mismatched and messy titles
from game publishers for submission to the No-Intro database.
This cleaning involved romanizing Japanese, Chinese, and Korean text. Romanization is the process of converting text written in a different
alphabet into a Latin alphabet - the kind you're reading right now. A good example of this would be converting “どうぶつのもり” into
“Dōbutsu no Mori” - it's not translation, since it didn't become English, but the process makes it pronounceable to English readers.
I could have perhaps gone with someone else's library for the task or made some quick code to do it as part of the NUS Ripper project,
but instead I opted to make it it's own specialized library, and this is the result. I still plan to add additional languages and romanization systems
in the future, but at the moment it already supports Japanese katakana, hiragana, and Kanji, Chinese Hànzì, Korean Hangeul and Hanja, and Russian.
For each romanization system and language I researched the language & system (for days in some cases) to make sure I had a solid understanding of how
exactly the everything worked, to make the romanizations as accurate as possible.
I love this project - it gives me an excuse to learn more about linguistics and individual languages, and it's really satisfying inputting some
text in a language you can't even pronounce, and getting readable, pronounceable text out the other side.
Another really nice thing about working on this project was that it gave me an opportunity to get some solid practice in with learning CI/CD, and how to set them up efficiently.

I use a skin called PinkyBlue for a synth called
Serum, but I also use another synth called
Sylenth and I wanted it to match.
As a result, I chose to make my own version of the skin for Sylenth. About two weeks later, this is what I'd made.
Because it uses assets from someone else's skin (since I made it for myself and was more concerned with consistency than distributability),
I can't make it available in any way without their permission.
That said, I am very happy with it and it is serving me well. Every panel, knob, light, and switch of the synth has been re-skinned to
match the Serum skin as closely as possible while still feeling like Sylenth.

Steganography is the practice of hiding data within other data. In this case, it's hiding data within images. This tool makes it
easy to hide any file within any png image, as long as the image has enough room to be able to store the file.
It allows for plenty of configuration and makes it easy to decide how to balance storage space within the image with how discreet you
want the modification to be.
It's also built to work with different algorithms for storage of the data, and designed to be extensible if I (or anyone else)
choose to add new ones.
Because images are often manipulated and edited, it would be easy to encounter data corruption with this use case.
As a result, I implemented Bose-Chaudhuri-Hocquenghem error-correcting codes
as an optional feature to make the solution more robust.
These allow it to not only detect if there are any errors in the result, but provided it hasn't been sufficiently corrupted,
allow the errors to be corrected.

A plugin for KeePass Password Safe that facilitates the storage and
viewing of pattern-based passwords like the ones used on some Android phones.
I made it because I wanted to be able to store the pattern password for the launcher on my phone.
To store a pattern in KeePass, there's a context menu option in KeePass for it attached to every password entry.
Once clicked, a little matrix appears where you enter the node order. It automatically highlights duplicate
node entries and the whole process is quick.
To view a stored pattern, there's a second context menu option that opens a simple little window that draws out the pattern slowly
for you to copy or learn.

A plugin that facilitates synchronization between KeePass Password Safe and Backblaze B2.

In high school, every year my school participated in
Skills Ontario competitions, where all kinds of trades and skills
were put to the test. One of the competitions they had was for Robotics, and the robotics club worked on robots for it every year. From the first
year I took part onwards, there was also an autonomous robot aspect to the competition. This was the part I mainly worked on.
This was my last year in high school, and my best bot. I wrote all the code and my computer science teacher and I did all the work on this
robot, affectionately named Charlie.
The provincial competition took place from to ,
and for one of the days I wasn't even able to be there for my robot's runs because I also competed in the programming competition on the same
day.
Despite that, Charlie achieved a near-perfect score and I came in second in the province in programming.
The actual challenge was to move the coloured blocks to their same-coloured pad entirely autonomously (no remote-control - the robot had to do it
all on it's own). The robot had to start on the black pad, and there were six different layouts for the positions of the blocks. On each day of the
competition, a die would be rolled and that would be the layout to be used that day.
Work on the robot started September 2018, and went right up to the day of the competition. It made use of a camera for centering on blocks and pads
for pickup & drop-off, four line sensors on the bottom to center itself on lines, two ultrasonic (distance) sensors for accurately moving specific
distances repeatably, and an encoder for every motor for controlled movement and turns.
That big white ring around the camera is a camping ring light that we re-purposed and modded to be able to trigger from code.
This was because we had a lot of issues with calibration and keeping lighting consistent, so it was helpful to have access to a local light source.
If you'd like to see the source code, you can find it here.

A library I worked on in lieu of classwork in school that enables beginners to make 2D games easily and quickly in
Processing, in a similar manner to
Greenfoot.
It splits the work between two main classes - World and Actor. The World acts like a scene/environment,
and the Actor plays the role of individual items/elements. The library provides support for movement, collisions, sprite-drawing at runtime,
input detection, different sprite resizing modes, z-indexing, and more.
In addition, every single class, method, and property is documented and the
complete documentation is freely available.

In high school, as most do, I loved snow days. Usually we would get a few a year, but the way the school board had set it up it required going to
a special website and checking to see if the buses for your region were cancelled for the day.
While not a particularly arduous process, it was still a pain and I didn't want to have to check all the time.
My solution was simple. I set up an automated script on my server to run every day from November through April (months where there was any chance
of a snow day) and it would wait randomly for up to ten minutes. This way it would look like a normal person checking the website. It then checked the
page for a cancellation.
If it found that buses were cancelled, my server would send me an email with a special subject line, and log the day. I then set up my phone to
check for that subject line, and loudly notify me if it got it. This way, anytime there was a snow day I knew without having to check, and I could go back
to sleep.
A nice side effect of running this tool is that I now have a log of every snow day for the duration of my high school career, which I find pretty
cool because I like collecting data.

A font I made for a game of mine several years ago, because I couldn't find any I liked that were available at no cost.
I did it in 4 hours or so using the free tool BitFontMaker 2.
When I finished it, I put it up as royalty-free and free to use.
Used in the wonderful little game A Short Hike.
As of writing this, it's over 300,000 downloads.

This is still an ongoing pet project, but for years I've had a Raspberry Pi 3 Model B I run as a local intranet server.
It hosts a wide variety of tools and services I have made for myself and my family over the years - to name a few, a database of recipes, a
database of links (kind of like bookmarks, but independent of a browser), a local media centre, a note system, a printing utility that prints straight
from the webpage instead of having to fuss around with any printers, file dead drops between devices, game utilities, a snow day checker, and more.
The server also fetches the current weather once an hour, with current tempaerature displayed in the unit the family member is most comfortable with.
The weather information is cached on the server, so it all works without takign additional time to load or making unnecessary requests of the weather
API.
In addition to all that, it also hosts a Pi-Hole installation for network-level ad blocking and
custom local domain names.

This is a simple game I completed in a week (±½) for Science in Grade 10. It's a simple endless runner style game, except
every time you hit an obstacle it asks you a chemistry-themed question. If you get it correct you can keep going, but if you get it wrong it's
game-over.
There're several question categories, then within them multiple questions per category. Every question is entirely randomly generated.
From the content of the question (elements, symbols, diagrams) to the answers to the order of the answers to the question categories themselves,
every single question is procedurally generated from scratch.
For the questions involving specific elements, the game works from
a built-in database of all
elements on the Periodic Table with their categories (metals, non-metals, etc.), atomic numbers, symbols, and ionization numbers, etc. to create
valid questions and answers that require actual Grade 10 chemistry knowledge to solve.
If you'd like to play it, the link to do so is here.

Still one of the projects I'm most fond of. It took me about eight months from start to finish, and I made it when I was twelve years old or so.
It's a complete game, made almost entirely by me (code, art, models, maps, gameplay, audio).
It features: three maps, five turret types, six guns, and six enemy types. The only thing it's truly missing is animations, but at the time
that was beyond the scope of my little game and I'm not updating it now because I want to leave it exactly as it was.
Another reason I'm really proud of it is because this project was the project where I taught myself many of the foundational concepts
I still use today in programming, as well as some really cool stuff like enemy AI and pathfinding algorithms.