VOGONS


First post, by agovtman

User metadata
Rank Newbie
Rank
Newbie

I have created a fork of Nuked-OPL3 that performs much better (1.4x-2.2x faster) with the exact same output accuracy.

Nuked-OPL3-fast

I noticed a while back that Nuked-OPL3 does a lot of extra work it doesn't need to do inside the hot loop, like using function dispatches to compute stuff that could be computed inline or just precomputed into a LUT, etc. Moreover, Nuked-OPL3 is often the single heaviest user of CPU time in emulators that use it, so it was a productive target for optimization. I got to messing around, found even more optimizations I could make, and ended up with a version of Nuked-OPL3 that produces exactly identical output to the original, but is as much as 2.2x faster!

I have offered to NukeYKT to merge these changes upstream, but they do some "clever" things (in the pejorative sense: opaque, tricky, weird) that he might not want to drag into his codebase, so for now it exists as an independent fork.

This is a drop-in replacement for Nuked v1.8, and has already been adopted by dosbox-staging, libADLMIDI, and 86box. dosbox-x looks to be ready to merge it imminently, too.

If your project uses Nuked-OPL3, try switching to my -fast fork and run some performance profiling and see the difference for yourself!

PS: I have gotten Nuked-OPL3-fast running in realtime on an overclocked RPi Pico 2!

Reply 1 of 4, by M-HT

User metadata
Rank Member
Rank
Member

You can use _BitScanForward for the envelope timer on MSVC like this:

#if defined(__GNUC__) || defined(__clang__)
shift = (uint8_t)__builtin_ctz(eg_timer_low);
#elif defined(_MSC_VER)
unsigned long index;
_BitScanForward(&index, eg_timer_low);
shift = (uint8_t)index;
#else
while (((eg_timer_low >> shift) & 1) == 0)
{
shift++;
}
#endif

Reply 2 of 4, by tcaud

User metadata
Rank Newbie
Rank
Newbie
agovtman wrote on 2026-06-02, 04:04:
I have created a fork of Nuked-OPL3 that performs much better (1.4x-2.2x faster) with the exact same output accuracy. […]
Show full quote

I have created a fork of Nuked-OPL3 that performs much better (1.4x-2.2x faster) with the exact same output accuracy.

Nuked-OPL3-fast

I noticed a while back that Nuked-OPL3 does a lot of extra work it doesn't need to do inside the hot loop, like using function dispatches to compute stuff that could be computed inline or just precomputed into a LUT, etc. Moreover, Nuked-OPL3 is often the single heaviest user of CPU time in emulators that use it, so it was a productive target for optimization. I got to messing around, found even more optimizations I could make, and ended up with a version of Nuked-OPL3 that produces exactly identical output to the original, but is as much as 2.2x faster!

I have offered to NukeYKT to merge these changes upstream, but they do some "clever" things (in the pejorative sense: opaque, tricky, weird) that he might not want to drag into his codebase, so for now it exists as an independent fork.

This is a drop-in replacement for Nuked v1.8, and has already been adopted by dosbox-staging, libADLMIDI, and 86box. dosbox-x looks to be ready to merge it imminently, too.

If your project uses Nuked-OPL3, try switching to my -fast fork and run some performance profiling and see the difference for yourself!

PS: I have gotten Nuked-OPL3-fast running in realtime on an overclocked RPi Pico 2!

The meme took root a decade ago that inline code should be avoided because compilers would get imminently better and would handle inlining/vector ops/other common optimizations better and faster than people. And they did in cases habitually encountered in IT and engineering... not so much elsewhere. Thanks for making the fork.

Reply 3 of 4, by agovtman

User metadata
Rank Newbie
Rank
Newbie
M-HT wrote on 2026-06-11, 21:47:

You can use _BitScanForward for the envelope timer on MSVC like this:

Fascinating. I had no idea. Will look into more of these MSVC secrets. Thanks.

tcaud wrote on 2026-06-12, 07:27:

The meme took root a decade ago that inline code should be avoided because compilers would get imminently better and would handle inlining/vector ops/other common optimizations better and faster than people. And they did in cases habitually encountered in IT and engineering... not so much elsewhere. Thanks for making the fork.

Well, to be fair, some compilers do gainsay some of my force-inlines because they Know Better™, and IIRC most of the performance improvement came from places other than force-inlining stuff, but... Yeah, people took "compilers are so good these days you don't need to" etc. a little too far.

Reply 4 of 4, by leileilol

User metadata
Rank l33t++
Rank
l33t++

Yeah i've never believed that gcc vectorizing / mtune worship. I still had to do manual unrolls when making PCem's voodoo filter with a big LUT to get it faster. Engoo had nested macro duff devices to draw a colored lightmap surfacecache faster, and that outpaces qrustyquake on the same CPU (Qrustyquake cleaned up a lot of code, unified a bunch of loops and has similar features to Engoo, so it's the only modern software port I can compare to - and gcc ain't helping it much)

apsosig.png
long live PCem
FUCK "AI". It is a tool of fascism. We do not need it. We do not use it.