Recent posts

#21
Help & Guides / RegEx Dictionary
Last post by WillLem - April 08, 2026, 12:35:52 AM
Here's a dictionary of RegEx commands / expressions which you might find useful if you do a lot of level editing using Notepad++ or similar.

1. Look for "maxReleaseRate = n" where "n" is anything other than 99
maxReleaseRate\s*=\s*(?!99\b)\d+

I'll add to this as necessary. If you wish to contribute anything, please do!
#22
Lemmini / Re: [RetroLemmini] DoveLems
Last post by WillLem - April 08, 2026, 12:11:46 AM
DoveLems for RetroLemmini is now available!

Get the latest version of DoveLems here.
#23
Quote from: WillLem on April 07, 2026, 10:39:10 PMAlways happy to accept help wherever offered! It's good to not have to always figure these things out on my own :)

Besides, I figured that some re-rendering prevention guard is what was needed. You helped pin it down to exactly where the guard needed to be - this is much appreciated!
I am SO happy to hear this.
I vigorously follow your commits at;
https://github.com/Willicious/SuperLemmixEditor/commits/master/SLXEditor
and must admit; these may seem some small changes but I really think the editor is becoming such a robust and bulletproof piece of software. This excites me very much while at the same time brining me serenity. I don't know if you experience similar feelings whenever you improve or fix something with your own software...

Thanks for everything...
#24
SuperLemmix Bugs & Suggestions / Re: BUG: Editor crashes when m...
Last post by WillLem - April 07, 2026, 10:39:10 PM
Quote from: roltemurto on April 07, 2026, 09:18:38 PMI hope I don't overstep my boundaries by doing this but I just want to be helpful.

Always happy to accept help wherever offered! It's good to not have to always figure these things out on my own :)

Besides, I figured that some re-rendering prevention guard is what was needed. You helped pin it down to exactly where the guard needed to be - this is much appreciated!

Quote from: roltemurto on April 07, 2026, 09:18:38 PMFix 1 — Re-entrancy guard on ResetLevelImage

Prevent NLEditForm_Resize from triggering a render if one is already in progress

Fixed in SLXEditor commit 8e46406.

Quote from: roltemurto on April 07, 2026, 09:18:38 PMFix 2 — Ensure UnlockBits is always called in BmpModify.DrawOn

The existing DrawOn method almost certainly does LockBits without a try/finally guarantee on UnlockBits. If any exception occurs mid-render, the bitmap stays locked forever for the lifetime of the object. Fix the locking pattern:

Fixed in SLXEditor commit 7f24239.

Quote from: roltemurto on April 07, 2026, 09:18:38 PMFix 3 (optional hardening) — Debounce resize events

Resize events can fire dozens of times per second during a resolution change. Even with the re-entrancy guard, it is worth debouncing to avoid hammering the renderer immediately after wake:

Went ahead with this one as well, but made the interval 50ms so it feels a bit snappier.

Implemented in SLXEditor commit 5cecf63.
#25
SuperLemmix Bugs & Suggestions / Re: BUG: Editor crashes when m...
Last post by roltemurto - April 07, 2026, 09:18:38 PM
Quote from: WillLem on April 07, 2026, 03:45:11 PMNot sure exactly why the exception occurred though. Maybe more resolution-specific guards need to be in place.

I hope I don't overstep my boundaries by doing this but I just want to be helpful.
So I gave the errors to an AI and explained the situation.
Here's how it diagnosed it and came up with possible solutions;


Diagnosis

Root cause: System.InvalidOperationException: Bitmap region is already locked.

The call stack is:

NLEditForm_Resize → ResetLevelImage → CombineLayers → CreateLevelImageFromLayers → BmpModify.DrawOn → Bitmap.LockBits
When the monitor is turned off via DisplayPort, Windows triggers a resolution/display change, which causes the WinForms window to receive a WM_WINDOWPOSCHANGED message. This fires OnResizeNLEditForm_Resize. The problem is that the renderer was already in the middle of a rendering operation (with a bitmap locked via LockBits) when this resize event fired — either from a concurrent render or from a prior render that didn't properly call UnlockBits before the resize interrupted it.

This is a re-entrancy / double-lock bug: Bitmap.LockBits is called on a bitmap that still has an active lock, either because:
  • A previous render was interrupted mid-flight and UnlockBits was never called (e.g. due to an earlier exception), or
  • The resize event fires while a render is already running (re-entrant call).



Solution

There are two complementary fixes that should both be applied.

Fix 1 — Re-entrancy guard on ResetLevelImage

Prevent NLEditForm_Resize from triggering a render if one is already in progress:

// In SLXEditForm:
private bool _isRendering = false;

private void ResetLevelImage()
{
    if (_isRendering) return;  // Guard against re-entrant calls
    _isRendering = true;
    try
    {
        // ... existing ResetLevelImage body ...
    }
    finally
    {
        _isRendering = false;
    }
}

This is the most important fix. It prevents a resize event from launching a new render while one is already running.



Fix 2 — Ensure UnlockBits is always called in BmpModify.DrawOn

The existing DrawOn method almost certainly does LockBits without a try/finally guarantee on UnlockBits. If any exception occurs mid-render, the bitmap stays locked forever for the lifetime of the object. Fix the locking pattern:

// In BmpModify.DrawOn — wrap the LockBits/UnlockBits pair in try/finally:
BitmapData bmpData = null;
try
{
    bmpData = origBmp.LockBits(rect, ImageLockMode.ReadOnly, origBmp.PixelFormat);
    // ... pixel operations ...
}
finally
{
    if (bmpData != null)
        origBmp.UnlockBits(bmpData);
}

Do the same for newBmp if it is also locked in that method. This ensures that even if an exception fires partway through a render, the lock is always released and future renders won't see a pre-locked bitmap.



Fix 3 (optional hardening) — Debounce resize events

Resize events can fire dozens of times per second during a resolution change. Even with the re-entrancy guard, it is worth debouncing to avoid hammering the renderer immediately after wake:

private System.Windows.Forms.Timer _resizeDebounce;

private void NLEditForm_Resize(object sender, EventArgs e)
{
    if (_resizeDebounce == null)
    {
        _resizeDebounce = new System.Windows.Forms.Timer { Interval = 150 };
        _resizeDebounce.Tick += (s, _) =>
        {
            _resizeDebounce.Stop();
            ResetLevelImage();
        };
    }
    _resizeDebounce.Stop();
    _resizeDebounce.Start();
}

This collapses a burst of resize events into a single render call 150ms after the last one.



Summary

FixWhat it addresses
Re-entrancy guard (_isRendering)Stops a second render from starting while one is in progress
try/finally around LockBitsGuarantees unlock even if a render throws mid-way
Resize debounceReduces needless render thrash during resolution changes

Fix 1 alone would have prevented this specific crash. Fix 2 prevents the "permanently locked bitmap" failure mode that makes Fix 1 necessary in the first place. Fix 3 is polish.
#26
SuperLemmix Bugs & Suggestions / Re: [+][SUG][ED] Create more w...
Last post by WillLem - April 07, 2026, 08:49:48 PM
Vastly improved the Pieces List today.

Optimised general performance (particularly relevant for levels with lots of pieces), added a hints label and made the dialog smaller horizontally so that it takes up less screen real estate:

Preview


One thing to note is that, if using the arrow buttons to push/pull the pieces through the layers, a piece will occasionally jump several places in the list. At first I thought this was a bug, but it's actually due to the way that indexing is handled. A piece will always be pushed to the lowest possible/necessary (or pulled to the highest possible/necessary) to achieve the desired effect; since it doesn't need to manually move one step behind or in front of any pieces that don't intersect with it, it skips over those pieces and lands at the next available index.

This isn't really an issue. just something to be aware of. The selected piece(s) is/are always tracked when moving them around the list anyway.
#27
NeoLemmix Levels / Re: MASTER-88 (Amiga Classic) ...
Last post by Guigui - April 07, 2026, 05:30:49 PM
Oh ok, I could clear the level. It turns out it is not symmetrical afeter all. Once again needs to place builders pixel perfect, or am I missing something.

I love how you have to build over existing bridges on the right side to gain just enough height for the end.

I still cant get the under 3 minutes talisman though, this climber worker is just too slow, and I dont know how to use those 2 extra bashers to gain time...
#28
SuperLemmix Bugs & Suggestions / Re: BUG: Editor crashes when m...
Last post by WillLem - April 07, 2026, 03:45:11 PM
It appears to have been triggered by the form resizing. Your instincts are likely correct: if the resolution change occurs on wake, that could trigger a form resize.

Not sure exactly why the exception occurred though. Maybe more resolution-specific guards need to be in place.

Good to know that no data was lost, that's fortunate.
#29
In Development / Re: Cheapo Copycat Lemmings (N...
Last post by kaywhyn - April 07, 2026, 12:43:54 PM
Great, looking forward to seeing what you make of this excellent level pack and porting it over from Cheapo to modern NL! :thumbsup: And thank you for linking to my Cheapo Copycat Lemmings videos! ;) Yes, feel free to reference them if necessary while remaking the levels in L1 styles
#30
In Development / Re: Revenge of the Lemmings - ...
Last post by kaywhyn - April 07, 2026, 12:40:06 PM
Quote from: Proxima on April 04, 2026, 12:42:28 PMLem Dunk is possible to save all but one. It would almost certainly be possible to save 100% if the trapdoor order were 1 - 3 - 2, haven't verified this yet.

However, this depends on the RR being 25 in NeoLemmix, which is slower than the slowest possible RR in other engines, so that's something we would have to change anyway.

Ah, didn't notice the 25RR for the level in the v4.0 RotL pack.


Quote from: Proxima on April 04, 2026, 12:42:28 PMWillLem voted for keeping the Mazu / Clam / IS levels (and Betcha can't save is by IS) so I'm pretty sure he does want it considered for v5  :P
Quote from: WillLem on April 04, 2026, 01:44:58 PMThe lists I posted are just there to document my favourites, really. Of course I'd like to see them included, but I'm equally happy to leave level selection entirely up to Proxima; I'll ultimately back whatever he decides upon, even if it means some of my picks don't make the cut.


You were saying? :P

QuoteIt's a very tricky question, exactly how far it's okay to change other people's levels. As mobius listed in his post above, in v4 he changed a few levels to 10-of-all that weren't originally, and on the one hand, that is changing them from the author's intent, but on the other hand, the pack benefits from having some easy levels to start with. So I'd love to hear more people's opinions on what to do with those levels, and with the start of the pack in general.

This is a tricky one indeed. On the one hand, I definitely think the pack can do with having these easy X-of-everything levels at the start, but on the other hand, it does feel a bit strange to me with them being modified levels of the authors from their original intent. If the decision is fine for the pack to have repeats, then sure, keep the X-of-everything version of the harder repeat, I guess. If we don't want repeats, then I guess put the skill tutorial levels instead. It really can go either way quite honestly, and I don't have a strong preference for either one, though I think I'm leaning more towards the X-of-everything route, and I'm not saying that because I myself won't be making skill tutorial levels for my upcoming Lemmings Memories pack :P

QuoteI am completely against changing levels just to make 100% possible. That you can't save 100% on every level has always been part of the game. "Betcha can't save" is designed so that saving even one is difficult, and that shouldn't be messed with.

Completely agree here with both points, even the first one despite how I generally go for save all's as much as possible :P It's not L2 anyway, where it's been proven that it's possible to save all on all 120 levels of the game and even then it's still possible to get gold if you lose some depending on the level/tribe. I digress though.

My own level list and thoughts on the picks/preferences of those who posted still to come. Maybe at the end of the week or so.