Scarlet Devil Mansion

8 June 2025

June 2025 Benben Update

Ohhhh boy, has there been a lot of activity with Benben in the past six and a half weeks. Like, seriously, there’s been a LOT of work put into Benben and its support libraries since the last update. These (almost) monthly updates also seem to be becoming a tradition, so I may as well continue it with an overview of what all has been happening with Benben’s development. Let’s dive in!

Lisp Port Merged Into Trunk

The biggest news is that the Common Lisp branch has been merged into the trunk. The code is far enough along that users that power users (is that term still used?) who are comfortable compiling it from source can use it as a daily driver. There are still bugs, of course, and still work to complete, but it’s far enough along that I felt it was ready to be merged.

I’ll get back to releasing development AppImages soon, once things quiet down for me at home, and once I have an updated remote-benben program. For now, if you’re feeling brave and adventurous, you can use the Lisp Build Instructions file. This file will eventually become the wiki entry that tells you how to build Benben.

Remaining Formats Implemented

On the format front, the last few missing formats have been ported over and are now working. These are:

MIDI support is still a little shaky at the time of writing just because I haven’t tested it too much. But, it should be stable enough for general use.

Improved Relative Volume Adjustment Support (“ReplayGain”)

ReplayGain support is a bit better in Benben v0.7.0, as it’s now supported with XQAF files, and also for WavPack files. Also, Opus files with both ReplayGain tags and the format’s own internal Output Gain adjustment are properly handled.

Rendering Implemented for All Supported Formats

The rendering system has been ported over, and also improved, at least internally. Rendering files still happens in parallel, and all formats are supported.

The internal design has been overhauled so that much more code is shared between the rendering jobs and the normal playback code. In fact, the rendering code has dropped from about 2300 LOC down to 946 at the time of writing. But, also take that with a grain of salt since ~2300 lines of Crystal code isn’t necessarily equivalent to ~2300 lines of Common Lisp code. Still, it’s a dramatic reduction, and makes it a lot easier to add additional formats in the future.

Anyway, just for reference, here are all of the supported input formats in Benben v0.7.0:

Rendering to Wavpack or QOA Removed

Some of the more recent Crystal versions of Benben had the ability to render to WavPack or QOA as well as the usual WAV and Au. QOA output was originally added simply because I didn’t know of any good, general-purpose QOA encoders out there except for the reference encoder. But now that XQATool is a thing (and it’ll support output to normal QOA very soon), it doesn’t make much sense for Benben to also offer QOA output.

Similarly, WavPack is being removed because it also doesn’t make much sense to keep in Benben. The official encoder has more options, and if you have libwavpack installed, you probably also have the command line WavPack encoder at your disposal as well. You know, Unix philosophy and all that. Truth be told, I was somewhat hesitant to add it to begin with for this very reason, but it seemed like a fun idea at the time, and I did at least learn more about WavPack with it.

So, long story short, Benben v0.7.0 will only offer rendering to WAV and Au. Use XQATool for creating XQAF and QOA files, and the official WavPack encoder for making WavPack files. Playback of these formats is still fully supported.

Wad File Support

Related to formats is a completely new feature for v0.7.0: support for Doom WAD files. Basically you tell Benben to play a WAD file, and it’ll find all supported files (lumps) within it and play them. So you can do things like this:

$ benben doom.wad

$ benben scythe.wad

$ benben kill.wad

Neat, eh? This should make it a bit easier to listen to the soundtracks to Doom levels that you enjoy.

WAD files do have a few limitations, however:

So, in the end, these are the file types that are supported in WAD files:

New Output Drivers

There are now three different output “drivers” in the Common Lisp port of Benben:

The ALSA driver is the most bare bones, but is also the closest “to the hardware”, so to speak. The out123 driver is the default since it’s very fast and very robust. The ao driver is a good alternative.

Also, if you use the special “any” driver, Benben will cycle through the available drivers as-needed. This means it tries out123 first, and if that fails, it tries ao. If that fails, it’ll try alsa. If that fails, well, you’re out of luck and you probably have sound system problems outside of Benben :-P

New Config Options

The config file also got a few new additions since the last update.

Banner animations can now be selected in the config file. This is done in the ui section with the banner-anim key. Just like many of the other UI options, it can take both a string or an array of strings. When it’s a single string, then only that one animation is used. If it’s an array of strings, then a random animation from that array will be chosen each time Benben is started. Putting an animation more than once in an array increases its chance of being selected. The possible animations are: slide-in, dissolve, dissolve-from-nothing, wipe-from-left, and wipe-from-right.

There’s also a new key in the vgm section called max-file-size. This key tells Benben not to load any VGM file that’s larger than max-file-size bytes before decompression. This was added because I found myself accidentally opening compressed files a few times, which were being tested as VGMs. It should also provide some protection against “zip bomb” VGMs. The default is 62914560 (60 megabytes), which is far larger than any VGM I have in my collection¹. I intend to implement the same option for module files before release.

Speaking of modules, the modules config section now has a post-track-seconds option. This option only takes effect when the fade-out-songs option is false and a reverb unit is enabled when the song starts. What it does is append post-track-seconds seconds of silence to the end of the file, thereby allowing the reverb tails to finish playing.

Port of Remote-Benben Started

I’ve started porting the remote-benben program (the one that provides remote control of Benben via a Unix Domain Socket) from Crystal to Common Lisp. I had intended to keep it in Crystal, but some annoyances with LLVM and libgc on one of my boxes that impacted all my Crystal programs kinda ticked me off recently.

The port of remote-benben probably won’t be finished for a while since it’s kinda low priority, but it will be done in time for the Benben v0.7.0 release. And while the current code in the trunk builds, but only supports a few commands. But it’s a start! Just use the old AppImage of it for now, it’s fully compatible with the Common Lisp version of Benben.

Code of Conduct Updated

One last thing, the Code of Conduct has been updated. This is important for anyone wishing to contribute to Benben, whether it be through tickets, community interaction, code submissions, or so on. Benben’s Code of Conduct was adapted from by ~keith, and was chosen based on my desire to create a safe and equitable space, and also on my own experience as a neurodivergent individual who is uhh… well, let’s go with “rather eccentric”.

The new addition to the Code of Conduct is point number six, which covers AI-generated code. Basically, it’s not allowed in Benben. No vibe coding, no using an LLM to debug a piece of code, and so on. It’s not allowed within Benben. Now obviously I can’t control code in third-party libraries where I’m not aware that it’s AI-generated. For example, if I write bindings for libfoo to use in Benben, and the libfoo authors decide to add some LLM-generated code in the future, and I’m not aware they did, then I can’t help that. But for the code that goes into Benben itself, it must be written by a human to the best of my knowledge and the submitter’s knowledge.

I fully intend to extend this Code of Conduct to all other projects I maintain in the very near future. This means nearly all of the Lisp libraries Benben uses will also be covered by this policy. They kinda are already, but it’s more of a de facto thing at the moment.

Next Steps

At this point, the porting process is mostly complete. There’s just a few VGM chip emulators left to port and it will be feature-parity with the old Crystal version (plus some new features). This is why the old lisp-rewrite branch was merged into trunk.

Given how far along the port is, I’m now shifting my attention to the milestone goals for v0.7.0. Obviously some of these are already completed (mostly ones that made sense to do during the port, like the Minimal UI), but there are still a number of new features left to add before the new release will be ready. My plan for the coming month is to focus on these features specifically:

There are also a number of known bugs and issues in Benben’s current trunk code that I want to address:

Lastly, while not strictly related to Benben, there are a few other things that are tangentially related:

So there you have it. Plans for the coming month, and what has been happening since the end of April.