diff --git a/README.md b/README.md index 5b4fc82..defb923 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,8 @@ pio device monitor ## Still Alive demo +![Still Alive demo running on the EL512.256-H](docs/images/still_alive.jpg) + A recreation of Portal's ending: timed song text typed into a console on the left, credits scrolling top right, ASCII art bottom right. The text, timing, art and credits in `src/still_alive/imported.h` come from diff --git a/docs/images/still_alive.jpg b/docs/images/still_alive.jpg new file mode 100644 index 0000000..91a18df Binary files /dev/null and b/docs/images/still_alive.jpg differ diff --git a/src/still_alive/imported.h b/src/still_alive/imported.h index 2ae0338..0990fd1 100644 --- a/src/still_alive/imported.h +++ b/src/still_alive/imported.h @@ -389,16 +389,16 @@ static const LyricStep LYRICS[] = { {18130, 2710, STEP_NEWLINE, ART_KEEP, "my satisfaction."}, {22970, 1760, STEP_NEWLINE, 1, "Aperture Science"}, {26830, 1570, STEP_NEWLINE, ART_KEEP, "We do what we must"}, - {28600, 750, 0, ART_KEEP, "because"}, + {28600, 750, 0, ART_KEEP, "because "}, {29550, 710, STEP_NEWLINE, ART_KEEP, "we can."}, - {31930, 1550, 0, ART_KEEP, "For the good"}, + {31930, 1550, 0, ART_KEEP, "For the good "}, {33480, 1530, STEP_NEWLINE, ART_KEEP, "of all of us."}, {35289, 1741, STEP_NEWLINE, 6, "Except the ones who are dead."}, {37030, 400, STEP_NEWLINE, ART_KEEP, ""}, {37430, 1858, STEP_NEWLINE, 1, "But there's no sense crying"}, {39298, 1782, STEP_NEWLINE, ART_KEEP, "over every mistake."}, {41280, 1985, STEP_NEWLINE, ART_KEEP, "You just keep on trying"}, - {43275, 1366, 0, ART_KEEP, "till you run out of"}, + {43275, 1366, 0, ART_KEEP, "till you run out of "}, {44641, 400, STEP_NEWLINE, ART_KEEP, "cake."}, {45227, 1970, STEP_NEWLINE, 5, "And the Science gets done."}, {47197, 1970, STEP_NEWLINE, ART_KEEP, "And you make a neat gun."}, @@ -410,22 +410,22 @@ static const LyricStep LYRICS[] = { {55477, 0, STEP_NEWLINE, ART_KEEP, ""}, {58487, 0, STEP_NEWLINE, ART_KEEP, ""}, {58547, 1917, STEP_NEWLINE, ART_KEEP, "I'm not even angry."}, - {62832, 697, 0, ART_KEEP, "I'm being"}, - {63529, 650, 0, ART_KEEP, "so"}, - {64179, 906, 0, ART_KEEP, "sincere"}, + {62832, 697, 0, ART_KEEP, "I'm being "}, + {63529, 650, 0, ART_KEEP, "so "}, + {64179, 906, 0, ART_KEEP, "sincere "}, {65085, 1115, STEP_NEWLINE, ART_KEEP, "right now."}, - {67825, 650, 0, ART_KEEP, "Even"}, - {68475, 1347, 0, ART_KEEP, "though you"}, - {69822, 488, 0, 8, "broke"}, + {67825, 650, 0, ART_KEEP, "Even "}, + {68475, 1347, 0, ART_KEEP, "though you "}, + {69822, 488, 0, 8, "broke "}, {70310, 998, STEP_NEWLINE, ART_KEEP, "my heart."}, - {71308, 325, 0, ART_KEEP, "And"}, - {71633, 488, 0, ART_KEEP, "killed"}, + {71308, 325, 0, ART_KEEP, "And "}, + {71633, 488, 0, ART_KEEP, "killed "}, {72121, 557, STEP_NEWLINE, ART_KEEP, "me."}, {74678, 1649, STEP_NEWLINE, 3, "And tore me to pieces."}, - {78649, 1440, 0, ART_KEEP, "And threw every piece"}, - {80091, 580, 0, ART_KEEP, "into"}, + {78649, 1440, 0, ART_KEEP, "And threw every piece "}, + {80091, 580, 0, ART_KEEP, "into "}, {81066, 882, STEP_NEWLINE, 11, "a fire."}, - {83597, 1400, 0, ART_KEEP, "As they burned"}, + {83597, 1400, 0, ART_KEEP, "As they burned "}, {84997, 1509, STEP_NEWLINE, ART_KEEP, "it hurt because"}, {86831, 1625, STEP_NEWLINE, 9, "I was so happy for you!"}, {88897, 2067, STEP_NEWLINE, ART_KEEP, "Now these points of data"}, @@ -435,7 +435,7 @@ static const LyricStep LYRICS[] = { {96884, 2113, STEP_NEWLINE, 3, "So I'm GLaD. I got burned."}, {98997, 2020, STEP_NEWLINE, 5, "Think of all the things we learned"}, {101017, 1556, STEP_NEWLINE, 1, "for the people who are"}, - {102573, 395, 0, ART_KEEP, "still"}, + {102573, 395, 0, ART_KEEP, "still "}, {102968, 1440, STEP_NEWLINE, ART_KEEP, "alive."}, {106008, 0, STEP_CLEAR, ART_KEEP, ""}, {106008, 450, STEP_NEWLINE, ART_KEEP, "Forms FORM-55551-6:"}, @@ -443,22 +443,22 @@ static const LyricStep LYRICS[] = { {107768, 0, STEP_NEWLINE, ART_KEEP, ""}, {108428, 2200, STEP_NEWLINE, ART_KEEP, "One last thing:"}, {110628, 0, STEP_NEWLINE, ART_KEEP, ""}, - {110678, 1324, 0, ART_KEEP, "Go ahead and leave"}, + {110678, 1324, 0, ART_KEEP, "Go ahead and leave "}, {112002, 627, STEP_NEWLINE, ART_KEEP, "me."}, - {114417, 534, 0, ART_KEEP, "I think"}, - {114951, 1184, 0, ART_KEEP, "I prefer"}, - {116135, 1022, 0, ART_KEEP, "to stay"}, + {114417, 534, 0, ART_KEEP, "I think "}, + {114951, 1184, 0, ART_KEEP, "I prefer "}, + {116135, 1022, 0, ART_KEEP, "to stay "}, {117157, 232, 0, ART_KEEP, "in"}, {117389, 882, STEP_NEWLINE, ART_KEEP, "side."}, {119701, 511, 0, ART_KEEP, "May"}, {120212, 2972, STEP_NEWLINE, ART_KEEP, "be you'll find someone else"}, {123184, 1254, STEP_NEWLINE, ART_KEEP, "to help you."}, - {126690, 511, 0, ART_KEEP, "Maybe"}, - {127201, 325, 0, 7, "Black"}, + {126690, 511, 0, ART_KEEP, "Maybe "}, + {127201, 325, 0, 7, "Black "}, {127526, 998, 0, ART_KEEP, "Mesa"}, {128524, 2183, STEP_NEWLINE, ART_KEEP, "..."}, - {130707, 1440, 0, ART_KEEP, "THAT WAS A JOKE."}, - {133168, 279, 0, ART_KEEP, "FAT"}, + {130707, 1440, 0, ART_KEEP, "THAT WAS A JOKE. "}, + {133168, 279, 0, ART_KEEP, "FAT "}, {133447, 859, STEP_NEWLINE, ART_KEEP, "CHANCE."}, {135699, 1486, 0, ART_KEEP, "Anyway"}, {137185, 1765, STEP_NEWLINE, 2, ", this cake is great."}, @@ -470,7 +470,7 @@ static const LyricStep LYRICS[] = { {149167, 2043, STEP_NEWLINE, 5, "I've experiments to run."}, {151210, 2020, STEP_NEWLINE, 3, "There is research to be done."}, {153230, 1625, STEP_NEWLINE, 1, "On the people who are"}, - {154855, 348, 0, ART_KEEP, "still"}, + {154855, 348, 0, ART_KEEP, "still "}, {155203, 1440, STEP_NEWLINE, ART_KEEP, "alive."}, {156843, 0, STEP_CLEAR, ART_KEEP, ""}, {156953, 0, STEP_NEWLINE, ART_KEEP, ""}, @@ -532,8 +532,8 @@ static const LyricStep LYRICS[] = { {283939, 0, STEP_NEWLINE, ART_KEEP, ""}, {284939, 5000, STEP_NEWLINE, ART_KEEP, "// Getting Faster and Faster //"}, {290939, 2000, STEP_NEWLINE, ART_KEEP, "... I just said this is a simple game."}, - {293439, 500, 0, ART_KEEP, "Actually,"}, - {294939, 3500, 0, ART_KEEP, "THIS IS NOT A GAME."}, + {293439, 500, 0, ART_KEEP, "Actually, "}, + {294939, 3500, 0, ART_KEEP, "THIS IS NOT A GAME. "}, }; static constexpr size_t LYRIC_COUNT = sizeof(LYRICS) / sizeof(LYRICS[0]); diff --git a/tools/import_still_alive.py b/tools/import_still_alive.py index 14547f6..ec21f57 100644 --- a/tools/import_still_alive.py +++ b/tools/import_still_alive.py @@ -96,7 +96,9 @@ def parse_steps(page, art_ids): end = screens[i + 1].start() if i + 1 < len(screens) else len(page) body = page[screen.end():end] steps.append((base, len(steps), 0, "STEP_CLEAR", "ART_KEEP", "")) - for tag in re.finditer(r"<(span|br)\b[^>]*>", body): + # Group 2 is the whitespace after the element: a browser renders it as one + # space between spans on the same line ("because" + "we can"). + for tag in re.finditer(r"<(span|br)\b[^>]*>(?:)?(\s*)", body): t = tag.group(0) if tag.group(1) == "br": offset = attr(t, "data-show-offset") @@ -107,6 +109,8 @@ def parse_steps(page, art_ids): if text is None or attr(t, "data-start") is None: continue flags = "STEP_NEWLINE" if attr(t, "data-append-br") == "true" else "0" + if flags == "0" and tag.group(2) and not text.endswith(" "): + text += " " art = attr(t, "data-asciiart") art_id = "ART_KEEP" if art is None else ("ART_NONE" if art == "clear" else str(art_ids.get(art, 0))) steps.append((base + int(attr(t, "data-start")), len(steps),