Category Archives: Chiptune
an old player revisited
Ten years after my first sc68 web port I thought it might be time to update the code base to the latest sc68 dev version. This new version supposedly has improved SNDH playback capabilities and I used the occasion to play with WEBGL and also add a visualization of the emulation’s internal voice streams. A live demo can be found here: http://www.wothke.ch/webSC68
PS: I updated PlayMOD to now also use this version.
software archaeology/puzzle..
This was the first time that I’ve tried my luck at reverse engineering a Windows *.exe with the goal of porting the respective functionality to the Web. Matter-of-factly it was a rather pointless (who needs another old music player in 2022?) but fun undertaking, that gave me a pretext to play with some new tools and refresh my “code reviewing” skills. The hobby project had one clear win condition: The result would either work perfectly or the project would end as a humiliating defeat..
To come to the point: the project was a success that can be tried out here: www.wothke.ch/webIXS

But lets take a step back shall we? “IXSPlayer Version 1.20” was originally created by the no longer existing “Shortcut Software Development BV” about 20 years ago.
The music player belongs into the “Impulse Tracker” family but what sets it apart is the way by which it generates the used audio sample data. At the time it must have looked like a promising idea to save the limited Internet bandwidth by using the smallest music files possible.. and via compression and audio synthesis this player uses ridiculously small song files that are only a few thousand bytes long (see status information in the player widget). For comparison: mp3 files are typically several million bytes (megabytes) long.
As we now know, Internet bandwidth was about to evolve quite dramatically and only a few year later, people could not care less how many megabytes some silly TikTok or Youtube video might be wasting. So ultimately the idea with the micro music-files finally did not get much traction.
Music files for this player can be found on the Internet (see modland.com). In the modland.com collection respective files are listed under “Ixalance”. I am therefore also using that name here.
The only *.ixs format player that Shortcut Software ever seem to have released to the public is a small Win32 demo-executable:

This demo player obviously only works on Windows. It only plays one song at a time (in an endless loop). And there is a flaw in its “generated cache-file naming” which may cause songs to load the wrong files and then not play correctly.
I had gotten in touch with the original developers to check if they might provide me with the source code of their player (so that I could adapt it for use on the Web – like I had already done for various other music formats in my playMOD hobby project). But unfortunately those program sources seem to have been lost over the years. The above Windows *.exe was indeed the only thing left. So that is what I used as a base for my reverse engineering.
Greetings go to the Rogier, Maarten, Jurjen and Patrick who had created the original player at “Shortcut Software Development BV”. Thank you for letting me use this reverse engineered version of your code.
Non-software engineers can safely stop reading here 🙂 All others might find useful information for their future reverse engineering projects below.
Stage 1
The original developers had told me that the player had been an “ImpulseTracker” based design and that it had been written mostly in C++. This sounded promising since C/C++ can be cross compiled quite easily to JavaScript/WebAssembly using Emscripten. I therefore set out to find some decompiler that might allow me to transform the x86 machine code from the *.exe back to its “original” C++ form. To make it short: If you want to do this kind of thing professionally you should probably buy IDAPro – or as a hobbyist like me you can try your luck with Ghidra and the free demo of IDAPro as a supplement (other tools like boomerang, cutter, exe2c, retdec, etc seem to be a waste of time).
What to expect?
A tool like Ghirda has a sound understanding of different calling conventions used by typical C/C++ compilers (__fastcall, __stdcall, __thiscall). Based on the stack manipulations performed in the machine code this allows it to correctly identify the signatures of the used C/C++ functions 95% of the time (Ghidra struggles when FPU related functions are involved but that can be fixed by manual intervention, i.e. overriding the automatically detected function signatures). Obviously respective tools also know most of the instruction set of the used CPU/FPU which in this case allowed Ghidra to translate most of the x86 gibberish back into a more human readable C form:

With no knowledge about the used data structures that code is still quite far from the C code that this will eventually turn out to be:

The decompiled code will often be a low-level representation of what the machine code does – rather than what the original C abstraction might have been, e.g. though technically correct the below code:

in the original C program would probably rather have read:

Similarly the “1:1” mapping of the optimized machine code:

must still be manually transformed to its “original” form:

Most importantly in order to get meaningful decompiler output it is indispensable to find out what the used data structures are.
But before diving into that jigsaw puzzle it makes sense to narrow down the workspace: In my case I knew that I was looking for IXS music player logic – while most of the executable was probably made up of uninteresting/standard VisualStudio/MFC code (some of which Ghidra was able to automatically identify). String constants compiled into the code then allowed me to identify/sort out additional 3rd party APIs. (The relative position of stuff within an excutable is useful to get an idea of what belongs together.)

After a tedious sorting/tagging process, the result was a set of functions that *probably* belong to IXS library that I am looking for – and that I could now export as a (still incomplete) “C-program” at the click of a button (since Ghidra does not seem to be suitable for an iterative process there was no point to do that just yet).
Time to identify data structures
I had been tempted to presume that virtual function tables should be one aspect of C++ code that can be easily identified in the machine code – but it seems I was mistaken. Even the additional “ooanalizer” tool – that seemed to be promising at first – mostly discovered useless CMenu (etc) classes – but none of the stuff that I was looking for (its extremely slow running “expert system” approach seems to be incapable to reliably search the memory for arrays that point to existing functions.. something that I had to do manually as a fallback).
At this point IDAPro’s debugger also comes in handy: When dealing with virtual function calls a simple breakpoint quickly eliminates any doubt regarding where that call might be going (this is quite crucial when dealing with Ghidra’s flawed stack calculations whenever virtual function calls are involved ).
The fact that I knew that the code was probably “Impulse Tracker based” obviously helped: When seeing an “alloc” of 557 bytes the chance of it not being an “ITInstrument” is just very slim (luckily there is a specification of the respective “Impulse Tracker” file format). Memory allocation/initalization code per se is a good place to look for the data structures used in a program.
At this point you may not know what the variables mean, but you already know what types they are – and offsets used to access data start to make sense.
Once the modelling of the data structures and the “list of the interesting functions” is reasonably complete, it is time to switch gears and enter the next development stage (it will be inevitable to come back to Ghidra from time to time to clarify open issues and it helps if variable/function names perserve some kind of postfix that allows to match them to the original decompiler output during the later development stages). But not before I mention some Ghidra pitfalls:
Ghidra pitfalls
Most of the time Ghidra works pretty well and I would not have been able to do this project without it. But there are instances where the decompiler fails miserably (I am no Ghidra expert and there might be “power user” workarounds that I am just not aware of.):
In some instances you don’t get around looking at the filthy x86 opcodes one by one (something I had hoped to avoid) to figure out manually what some piece of code actually should be doing:

The above shows the original x86 code on the left and Ghidra’s decompiler output on the right. The code seems to use LOGE2 and LOG2E constants and “f2xml” and “fscale” operations – which are known to be used in “C math pow()” implementations. But what seems to be plausible code at first glance is just total garbage – since Ghidra completely ignores the “fyl2x” operation which is actually quite important here.
Another weak point are arrays which are used as a local variable in some function. Ghidra may turn what was originally a 100 bytes array into a local “int” variable and then happily use those 4 bytes as an “arraybuffer” to poke array accesses into random memory locations. (As a workaround it helps to manually override the function’s stackframe definition. Eventhough this has problems of its own, like Ghidra introducing additional shadow vars for some of the data that is already explicitly defined in the stackframe.)
In general, Ghidra’s calculations with regard to pointers into a function’s stack frame (i.e. its “local vars”) leave a lot to be desired (Let’s say function A (among other local variables) has an array and it wants to pass a pointer to that array to a function B that it is calling.). Here the array address calculated by Ghidra is often just wrong. (Again IDAPro’s debugger comes in as a life saver to figure out what those offsets really should be. It seems save to presume that IDAPro is the far superior tool in this regard. But I guess you get what you pay for..)
Ghirda seems to be out of its depth when stuff is “simultaneously” processed on the CPU and on the FPU – and the decompiled code may then perform operations out of order – which obviously leads to unusable results.
Similarly Ghidra seems to completly ignore the calling conventions declared in virtual function tables. Consequently all its stack position calculations may be completly incorrect after a virtual function call.
Finally Ghidra’s logic seems to go totally bananas when a function allocates aligned stack memory via __alloca_probe.
Stage 2
The now exported “C program” from stage 1 is now ready to become an actually functioning program. At this point I obviously want to make as little changes as possible to the respective code: In order to not add additional bugs to the problems that undoubtedly already are present in the exported code. Also there isn’t any point to start cleaning up yet since there is a high risk that additional “program exports” may still be needed which then would require time consuming code merging.
So the first goal is to get the original multi-threaded MM-driver based player to work – like in the original player, just without the UI. That thing has been originally built using Microsaft’s C compiler and libs? Then that’s exactly what I’ll be using. And this tactic actually worked well: still slightly flawed at first but I got the exported code to actually produce audio for the first time.
Since I am aiming for a single-threaded Web environment, the multi-threading and Microsaft specific APIs have to go next: Standard POSIX APIs are available on Linux and they will be available in the final Emscripten environment as well. Therefore a simple single-threaded Linux command line player that just writes the audio to a file is the next logical step.
The code now works fine on Windows as well as in the Linux version. I am confident that the exported code has sufficiently stabilized and it is time for a cleanup (until now everything was still in one big *.h and one big *.c file – as exported by Ghidra). This is the moment where you want to have an IDE with decent refactoring support. Since I am an old fan of IntelliJ, I decided to try the trial version of CLion for the occasion. And though I found the “smart” auto-completion features of their editor rather annoying, the refactoring worked well (and the UI crap can be turned off somewhere in the settings).
Stage 3
But will it also work on the Web? Obviously it won’t! Intel processors are very lenient with regard to their memory alignment requirements, i.e. an Intel processor does not care what memory address it reads a 4-byte “int” from. And this is the platform that the exported program had been originally designed for. The processors of many other manufacturers are more restrictive and require a respective address to be “aligned”, i.e. the address for a 4-byte “int” then must be an integer divisible by 4. The Emscripten environment that I am targeting here shares this requirement. All relevant memory access operations must consequently be cleaned up accordingly – once that cleanup is done the code actually runs correctly in a Web browser.
Feeding the IXS player output to something that actually plays audio in a browser (see WebAudio) requires additional JavaScript glue code: I already have my respective infrastructure from earlier hobby projects and this part is therefore largely copy/paste that I will not elaborate on here.
But one extra bit of work is still needed: The IXS player generates the data for its instruments whenever a song is first loaded and that operation is somethat slow/expensive and blocking a browser tab for several seconds just isn’t polite. But one solution that “modern” browsers propose is the Worker API that allows to do stuff asynchronously in a separate background thread. This means that the orginal program must be split into two parts that then run completely independently and only talk to each other via asynchronous messaging. Finally there is the browser’s “DB feature” that allows to persistently cache the results of the expensive calculation so that it doesn’t even need to be repeated the next time the same song is played. So that’s what I do: Worker asynchronously fills the DB with respective data if necessary and the Player pulls the data from the DB and triggers the Worker when needed. Bingo! (All that remains to be done now is for the Google Chrome clowns to fix their browser and make sure that it isn’t their DB that blocks the bloody browser.. it just isn’t polite!)
webSID-Pi
In previous posts I had documented some “Raspberry Pi 4B” related ramblings and this post here may clarify why I was interested in that device in the first place.
It’s been some years that I’d created a C64/SID music emulator for the Web called webSID (see https://bitbucket.org/wothke/websid). I still have somewhat fond childhood memories of my respective 80ies home computer which had started my career in software engineering (particularly memories of its signature music creation capabilities).
If you have ever written any sort of music hardware emulation you are certainly well aware that there is absolutely no shortage of “fanboys” that know exactly what some original hardware sounded like and who are happy to tell you that your pretentious emulation sounds egregiously wrong. In the case of the SID sound chip, the manufacturer MOS had produced various models (6581 vs 8580) and revisions (of those models) that had different hardware designs (and production tolerances related differences) affecting the chip’s actual audio output. Consequently the opinions of “fanboys” here tend to be somewhat useless, since they may well be based on one particular chip revision.
Obviously the only authoritative reference is the use of the actual SID sound chips. One way to go about testing respective chips would be to use an old C64. However this approach has some obvious drawbacks: By today’s standards the respective hardware is an extremely slow piece of garbage and it takes forever to even load/run the minuscule programs. Respective 40 year old hardware components (power supply, CPU, PLA and VIC II chips) are prone to die and are more and more difficult to find replacements for. Different songs may require an NTSC or a PAL version C64 (affecting the used clock rate and the behavior of the VIC II chip). Different SID models require different hardware environments, e.g. different supply voltages (9V vs 12V) was well as different filter capacitors.
Given that my webSID emulation already covers all the required runtime environments I decided to ditch the respective non-SID legacy hardware and connect the SID chips directly to a “Raspberry Pi 4B” and drive it via the available GPIO pins.
The below image shows my respective prototype board. The design is actually fairly simple: The SID chip is dropped into the prototyping socket in the center. A boostconverter (red PCB) is used to create the 9V or 12V supply for the SID chip based on the Pi’s 5V. The filter capacitors suitable for the used SID model are plugged in (see green caps between SID and the boostconverter). (I had originally also used a hardwired 1 MHz crystal oscillator but later replaced it with the Pi’s built-in clock signal generator.)

The main problem with running a SID chip from a C64 emulation on a Raspberry PI is that the available operating system is not meant for realtime applications: By default various processes used by the OS are preemptively scheduled to run on the available CPU cores.
Ideally you would want to let the emulation step through the ~1Mhz clock cycles of the emulated C64 hardware one by one in realtime, and you’d have to somehow synchronize that processing with the actual processing speed of the Raspberry (though the overhead for synchronizing each 1MHz cycle would be excessive). The processing cost of different cycles also might vary, and though fast enough on average, sporadic peaks might potentially exceed the available time window for some of the cycles.
Fortunately for practical SID playback purposes the timing constraints can be somewhat relaxed: All of the SID’s timing is directly driven via the Pi’s hardware clock signal and when SID registers are updated respective player routines usually expect to make updates with 50Hz to maybe 200Hz frequency. Even if an update is slightly out of sync, it will usually not be noticeable here. The most timing critical interaction comes from songs that use the C64 CPU to trigger SID changes for the purpose of playing digi-samples. Respective samples may then be played (worst case) with a frequency of about 30kHz (meaning that updates should then ideally occur every 33 micros, i.e. there is some margin as compared to the ~1 micro clock timing).
I decided to go for a two-threaded buffered design: One CPU core is reserved for the emulation thread that generates a batch of SID updates (with respective target timestamps) for the next time window. And a second CPU core is dedicated to a playback thread that consumes the output of the emulation thread and that polls for the current time to perform the SID updates when the time is right.
As a first attempt I configured the program to run exclusively in user space and it actually ran good enough for regular SID songs. Unfortunately the preemtive multi-tasking used by the Linux OS causes timing glitches that are quite noticable in songs that use “digi-samples” tricks.
I tried to limit undesirable interference effects from other programs by isolating use of the relevant CPUs (see isolcpus, rcu_nocbs, rcu_nocb_poll and nohz_full) but unfortunately the remaining 100Hz “arch_timer” IRQs still seem to prevent a clean playback.
As a workaround I then created a kernel module for the playback thread and that version indeed plays nicely without any glitches. But eventhough the respective version may sometimes run fine for multiple minutes, there still seems to be some part of the kernel that sporadically crashes the system – probably due to the “playback” thread completely blocking “its” dedicated CPU core. The test results suggest that this problem might be fixed if the component that triggers the crash can be identified and disabled. Unfortunately I am not familiar with the respective Linux kernel implementation and I currently don’t feel like looking for that needle in the haystack. (Please let me know in case you have an idea how I might hack the kernel to work around the issue.)
Here the results created by the respective programs:
PS: More information on this project can be found here: https://bitbucket.org/wothke/websid/src/master/raspi/
PlayMOD online chiptune music player
My voyage into the realm of legacy computer music had originally started with my webSID music player and later continued with my extended webUADE version of the uade Amiga music emulator.
I still have fond childhood memories of my respective C64 and Amiga home computers since these devices ultimately triggered my career in software engineering. Whereas most of the capabilities of respective 40 years old home computers obviously look quite lacking from today’s perspective, their audio features have aged rather gracefully and I feel that the audio stuff is much better suited to preserve the nostalgia – e.g. as compared to the blocky pixel graphics or underwhelming computing power.
I later learned that even though the above devices where obviously the best that ever existed (cough), other people share similar nostalgia but with regard to other devices. In many cases emulators for respective devices already existed on some platform and all that was missing were respective ports so that it would be possible to use them on a Web page. Since this is basically the same thing that I had already done for my webSID and webUADE players I started to also port some of the existing 3rd party emulators (many of which I somewhat enhanced in the process).
Over the years the number of respective JavaScript/WebAssembly based music emulators in my toolbox has grown to around 30 and it was time to put them to good use: PlayMOD combines all of “my” Web emulators within one UI to provide “all-in-one” online browsing and music playback for some of the largest “legacy computer music” collections available on the Internet:
The modland.com collection contains about 455’000 music files from various legacy home computer and game consoles and the vgmrips.net collection adds another 62’000 primarily arcade system songs. The PlayMOD project derives its name from “module files” (MOD) music – which signifies computer music that has been created using some kind of tracker software (the term “tracker” goes back to Karsten Obarski’s Ultimate SoundTracker on the Commodore Amiga from 1987). However, in addition to actual MOD-files the used collections also provide a large number of other music formats, e.g. many of the older stuff would be usually referred to as “chiptune music” today. You may use the Basics tab directly on the PlayMOD page for more background information.
When looking for a MOD or chiptune player, PlayMOD provides the best coverage available due to its combined use of different emulators/player engines. PlayMOD is probably the only comprehensive cross-platform online player in existence today.
There are hundreds of different legacy music file formats involved and the emulators available in PlayMOD currently allow to play more than 99.9% of what is available in the two collections. This avoids having to manually find and install a suitable player for each exotic format (which otherwise may be a tedious task, and a player may not even exist for the platform of your choice, e.g. see Ixalance).
The PlayMOD web page allows to browse the folder/files available in the respective collections but it does not host any of the music files. In order to play a song, the user’s browser will directly retrieve the selected file from the respective collections (see links above) and then play it. Consequently the page will only be able to play the music while the ‘modland’ and ‘vgmrips’ servers are available.
The respective modland and vgmrips collections document the evolution of computer music during the past 40+ years. Having everything consolidated in one place allows to easily compare the capabilities of respective legacy sound systems (e.g. by comparing how the compositions of the same composer sounded on different platforms) or to just indulge in reminiscences.

The PlayMOD user interface is based on the design/codebase originally created by JCH for his DeepSID. I wasn’t keen on creating a UI from scratch so I am glad that I could reuse JCH’s already existing stuff – eventhough it had to be heavily modified. The PlayMOD UI is still in a prototype/proof-of concept stage and the quality of the used meta data (e.g. composer information) leaves a lot to be desired due to it having been automatically generated based on questionable quality raw data.
Obviously, legacy computer music could also be preserved by just creating some recording from the original hardware, and as can be seen on youtube, many people already use that approach. Indeed the approach of using an emulator will not always be as accurate as the use of the original HW (on the other hand recordings may suffer from lossy data compression – a problem that an emulation does not have). As compared to the original music files, recordings may use up much more memory and consequently network bandwidth, but today that isn’t the issue that it might have been 10 years ago. However emulation avoids the additional recording/publishing step and new music files can immediately be listened to – without having to wait for somebody with the suitable infrastructure to provide such a recording. (There actually are still “scenes” where people create new music for legacy systems today.)
From a “legacy computer music preservation” perspective the emulation approach also has the benefit that it not only preserves the end result but also the steps taken to achieve it. It allows for interactions that would not be possible with a simple recording. (Mileage may vary depending on the “original” music file format.)
Example: The “Scope” tab in the below screenshot shows the output of the different channels that some “Farbrausch V2” song internally uses to create its stereo output, i.e. an emulation approach allows to look at the “magic” that is happening behind the scenes.

Similarly a respective emulation could still be tweaked during playback, e.g. by turning certain features on/off, or by using different chip models.
part three..
And to complete the trilogy here another bit of fractal fun (in case your PC is not equipped with a fast enough graphics accelerator you can find a video recording here: https://youtu.be/PzTwOfoZp0E):
the beauty of numbers..
I just did a little revival of my old WebGL fractal stuff. The two below screens use the latest version of my Commodore C64 emulator to play two fitting music creations by Markus Klein.
vu meters?
Just a little experiment for how to synchronize visualization of additional data streams with the the playback of WebAudio music: The music samples are generated on the fly using a ScriptProcessorNode emulating some legacy AtariST. In addition to the stereo output the respective ScriptProcessorNode also generates three streams containing “playback volume” for the AtariST’s internal sound-chip voices:
just for fun a more psychedelic WebGL based rendering of the same data (the WebGL here combines an orbit trap fractal with an inverse distortion, and the “music volume” is used to parameterize the rendering):
unaligned “packed structs”…
are certainly not a good idea if a program is supposed to be portable. Unfortunately that is exactly what ZXTune is using to parse the different binary music files.
“One of the rules of packed structs is that you have to access them directly through the packed struct type. In other words, you can’t, in general, take the address of a packed field and then access the field through that pointer, because the pointer type won’t reflect the packed attribute.” (sunfishcode)
Unfortunately ZXTune used boost::array instances within the various packed structs.. Problem: when methods are invoked on boost::array (or std::array, etc). The ‘this’ argument to the boost::array functions may be misaligned, but the boost::array functions themselves don’t know this.
On CPUs which don’t mind unaligned memory access you may get away within without realizing that there is a problem.. and in this case it was my attempt to cross-compile the program using Emscripten that revealed the issue. Not wanting to rewrite too much of the foreign code I opted for a quick-fix: replacing the boost::array with a built-in array fixed the immediate problem…
Naturally a clean implementation should better refrain from depending on unaligned memory access at all… not all the CPUs are as forgiving as Emscripten.
(click on the below image for a live demo).
AdLibido – the wonders of early PC music ;-)
It was back “in the old days” and I remember my relief when some day I found out that all PCs were not necessarily mute: Thanks to some “walking frame” called “AdLib” they could actually make sounds… and a bit later things became pretty neat with the rise of Sound Blaster…
AdPlug plays sound data, originally created for the AdLib (OPL2) and Sound Blaster (Dual OPL2/OPL3) audio boards, directly from its original format on top of an emulator.
My latest bit of Xmas tinkering is a HTML5/WebAudio version of AdPlug (Thanks to Simon Peter and the other authors of AdPlug.). For a live demo click on the below image..
update: The respective page has meanwhile been updated and the used link therefore no longer corresponds to the original screenshot (you’ll need a browser with WEBGL support to use it).
after all those years..
To complete the set of chip-music emulators, here my WebAudio version of SC68 – an AtariST Â music emulator (that plays files like *.sc68 or *.sndh).
Even tough I had done some programming on the MegaST 4 back in the 90ies, I have to admit that at the time I had not realized that the machine had anything resembling a sound chip. Those were the days of 68k assembler, DSP machine code and GFA-Basic.. and we were just doing a Paintbox software for the “CHILI” frame-grabber and real-time video-effects extension card… 🙂
But it seems the ST not only did have a MIDI interface but also a built-in sound chip…
Thanks to Photon Storm for sponsoring this little project.
update: The respective page has meanwhile been updated and the used link therefore no longer corresponds to the original screenshot (you’ll need a browser with WEBGL support to use it).






