Recent posts

#11
In Development / Re: Revenge of the Lemmings - ...
Last post by Proxima - April 08, 2026, 01:31:00 AM
A tiebreaker will not be needed. As I said, the poll isn't binding, it's just to gauge where community opinion lies. If opinions are split, that just means I can follow my own judgement.
#12
In Development / Re: Revenge of the Lemmings - ...
Last post by mobius - April 08, 2026, 01:11:03 AM
if a tie breaker is needed I could change my vote...

As I look over the levels I went through back then I'm reminded of how many good and how many not so good levels there were... as I mentioned before I initially was going to include levels that were present in other large packs but people at the time were against it. I feel like the pack should represent the best of the community, not sure it always does that based on some of the decisions I made; for example I wanted to get as many authors in the pack as possible. Which again seems a bad decision in hindsight, if some of those levels weren't quite as good as ones that got removed.

And as another example; Clam specifically made his 5th pack for this project [not this iteration of it but back in around 2008]. Of course I tried fitting those levels into the early rank of the first version and a lot of people said they felt wonky/too difficult for the first rank.
#13
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!
#14
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.
#15
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...
#16
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.
#17
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.
#18
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.
#19
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...
#20
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.