Menu screens are coming along, including a live preview of the next level. Sticking to original graphics doesn't mean that you can't put those extra pixels that you get on a modern display to work...
This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.
Show posts Menu
Quote from: Simon on November 02, 2026, 09:06:31 PMAnd you've reverse-engineered parts of DOS L1 yourself. We believe that Lemmix and ccexplore's descriptions replicate DOS L1 exactly, but it's always possible that there are bugs that we haven't found even after 20 years of Lemmix.

Quote from: Simon on November 02, 2026, 09:06:31 PMStill, I'll see how much modern convenience, replay fine-control, ... you'll add.
Quote from: Simon on November 02, 2026, 09:06:31 PMYou show VGA level graphics with the EGA skill panel and information bar. Is that intentional?

Walking, falling and all kinds of "death by terrain" are now working and match frame-to-frame with the original.
Quote from: Mindless on March 22, 2026, 10:35:33 PMArrows can also be edited to be black (mimicking the Sega Genesis style of arrows).
If you're curious you can find the project at https://github.com/DirtyHairy/rustlings
On my actual copy of lemmings, the code for the next level depends on the percentage of lemmings rescued when completing the current one, and all different codes generated this way work. In addition, there is a variable (that I called "salt" in the listing below), the lowest 4 bit of which are encoded in the code. All different salts generate valid codes, and restoring a code also restores the salt, so subsequent codes will encode the same value. Or, in other words, if you enter a code for a different percentage you'll get the same codes for the next levels, but if you enter a code with a different salt you'll get a different set of codes.// rating: 0 .. 4
// level: 0 .. 29
// percentage: 0 .. 100
// salt: 0 .. 0x0f
function codeFor(rating, level, percentage = 100, salt = 0x00) {
const secret = "AJHLDHBBCJ".split("").map((x) => x.charCodeAt(0));
const levelIndex = 30 * rating + level;
const code = new Array(10).fill(" ".charCodeAt(0));
code[0] = ((levelIndex & 0x01) << 3) | secret[0] | ((salt & 0x01) << 1) | ((percentage & 0x01) << 2);
code[1] = ((levelIndex & 0x02) << 1) | secret[1] | ((percentage & 0x02) >> 1);
code[2] = (levelIndex & 0x04) | secret[2] | ((percentage & 0x04) >> 1) | ((salt & 0x02) >> 1);
code[3] = ((levelIndex & 0x08) >> 3) | secret[3] | ((percentage & 0x08) >> 2);
code[4] = ((levelIndex & 0x10) >> 3) | secret[4] | ((percentage & 0x10) >> 1) | ((salt & 0x04) >> 2);
code[5] = ((levelIndex & 0x20) >> 5) | secret[5] | ((percentage & 0x20) >> 3) | ((salt & 0x08) >> 2);
code[6] = ((levelIndex & 0xc0) >> 4) | secret[6] | ((percentage & 0x40) >> 6);
code[7] = (levelIndex & 0xf) + secret[7];
code[8] = (levelIndex >> 4) + secret[8];
code[9] =
((code[0] + code[1] + code[2] + code[3] + code[4] + code[5] + code[6] + code[7] + code[8]) & 0xf) + secret[9];
for (let i = 7 - (levelIndex & 0x07); i > -1; i--) {
const tmp = code[6];
code[6] = code[5];
code[5] = code[4];
code[4] = code[3];
code[3] = code[2];
code[2] = code[1];
code[1] = code[0];
code[0] = tmp;
}
return code.map((x) => String.fromCharCode(x)).join("");
}
// rating and level both zero based
function codeFor(rating, level) {
const secret = "AJHLDHBBCJ".split("").map((x) => x.charCodeAt(0));
const percentage = 100;
const levelIndex = 30 * rating + level;
const code = new Array(10).fill(" ".charCodeAt(0));
code[0] = ((levelIndex & 0x01) << 3) | secret[0] | ((percentage & 0x01) << 2);
code[1] = ((levelIndex & 0x02) << 1) | secret[1] | ((percentage & 0x02) >> 1);
code[2] = (levelIndex & 0x04) | secret[2] | ((percentage & 0x04) >> 1);
code[3] = ((levelIndex & 0x08) >> 3) | secret[3] | ((percentage & 0x08) >> 2);
code[4] = ((levelIndex & 0x10) >> 3) | secret[4] | ((percentage & 0x10) >> 1);
code[5] = ((levelIndex & 0x20) >> 5) | secret[5] | ((percentage & 0x20) >> 3);
code[6] = ((levelIndex & 0xc0) >> 4) | secret[6] | ((percentage & 0x40) >> 6);
code[7] = (levelIndex & 0xf) + secret[7];
code[8] = (levelIndex >> 4) + secret[8];
code[9] =
((code[0] + code[1] + code[2] + code[3] + code[4] + code[5] + code[6] + code[7] + code[8]) & 0xf) + secret[9];
for (let i = 7 - (levelIndex & 0x07); i > -1; i--) {
const tmp = code[6];
code[6] = code[5];
code[5] = code[4];
code[4] = code[3];
code[3] = code[2];
code[2] = code[1];
code[1] = code[0];
code[0] = tmp;
}
return code.map((x) => String.fromCharCode(x)).join("");
}