From fd1b06c2ed25937f367d0257b18ced9d012c2cba Mon Sep 17 00:00:00 2001 From: tema5002 Date: Sat, 20 Jun 2026 19:38:20 +0300 Subject: [PATCH 1/6] Amiga Going Ball demo recreation --- halyde/apps/boing.lua | 585 ++++++++++++++++++++++++++++++++++++++++++ lib/event.lua | 10 +- lib/raster.lua | 68 ++--- 3 files changed, 623 insertions(+), 40 deletions(-) create mode 100644 halyde/apps/boing.lua diff --git a/halyde/apps/boing.lua b/halyde/apps/boing.lua new file mode 100644 index 0000000..a1fc9ae --- /dev/null +++ b/halyde/apps/boing.lua @@ -0,0 +1,585 @@ +local raster = require("raster") +local event = require("event") + +local color_table = { + 0xAAAAAA, 0x666666, 0xFF0000, 0xFF0000, 0xFFDDDD, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, + 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, + 0xAA00AA, 0x660066, 0xFF0000, 0xFF0000, 0xFFDDDD, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, + 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000 +} + +local ball_bitplanes = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0xff80, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x001f, 0xffff, 0xfc00, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x00f8, 0x007f, 0xffff, 0xff80, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0fe6, 0x03ff, 0xffff, 0xfff0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xfd1b, 0x980f, 0xffff, 0xfffc, 0x0000, 0x0000, + 0x0000, 0x0000, 0x000f, 0xc14e, 0xb410, 0xffff, 0xffff, 0x8000, 0x0000, + 0x0000, 0x0000, 0x00fc, 0x927a, 0xe92a, 0x7fff, 0xffff, 0xf000, 0x0000, + 0x0000, 0x0000, 0x00c5, 0x09db, 0xa26f, 0x6fff, 0xffff, 0xfe00, 0x0000, + 0x0000, 0x0000, 0x01d0, 0x46ee, 0xc4d2, 0x0fff, 0xffff, 0xff80, 0x0000, + 0x0000, 0x0000, 0x0bba, 0x3bbd, 0x99b2, 0xd5bf, 0xffff, 0xffc0, 0x0000, + 0x0000, 0x0000, 0x0d76, 0x5ef6, 0x3324, 0xd57f, 0xffff, 0xffe0, 0x0000, + 0x0000, 0x0000, 0x5dec, 0x8fdc, 0x4665, 0xd55f, 0xffff, 0xfff0, 0x0000, + 0x0000, 0x0000, 0xab99, 0x18f8, 0x8ccd, 0x9455, 0xffff, 0xfff8, 0x0000, + 0x0000, 0x0002, 0xd772, 0x3103, 0x19c9, 0x96aa, 0xffff, 0xfffc, 0x0000, + 0x0000, 0x000d, 0xaecc, 0x6238, 0x3199, 0x96aa, 0x6fff, 0xfffe, 0x0000, + 0x0000, 0x001a, 0xbd98, 0xc673, 0x8399, 0xb695, 0x97ff, 0xffff, 0x8000, + 0x0000, 0x006d, 0x7331, 0x8c73, 0x1b39, 0xb255, 0xbbff, 0xffff, 0xc000, + 0x0000, 0x00d2, 0xe663, 0x18e7, 0x30f3, 0x324a, 0x9dff, 0xffff, 0xe000, + 0x0000, 0x0fa5, 0xccc3, 0x31ce, 0x31c3, 0x324b, 0xebff, 0xffff, 0xf000, + 0x0000, 0x1917, 0xb986, 0x23ce, 0x618c, 0x336d, 0x71ff, 0xffff, 0xf800, + 0x0000, 0x1ade, 0x670c, 0x639c, 0x639c, 0xc325, 0xa8ff, 0xffff, 0xfc00, + 0x0000, 0x32a3, 0xce18, 0xc73c, 0xc319, 0xcf26, 0xf37f, 0xffff, 0xfe00, + 0x0000, 0x35a6, 0x7c31, 0x8e38, 0xc719, 0xccf2, 0xd5df, 0xffff, 0xff00, + 0x0000, 0x6946, 0xc463, 0x1e71, 0x8739, 0x8ccf, 0x7a6f, 0xffff, 0xff00, + 0x0000, 0xcacc, 0xc707, 0x1c71, 0x8e31, 0x9ccc, 0x6d37, 0xffff, 0xff80, + 0x0000, 0xd69d, 0x8e7e, 0x38e3, 0x0e33, 0x98cc, 0xcd4b, 0xffff, 0xff80, + 0x0001, 0x9599, 0x8e73, 0xb9e3, 0x1c73, 0x98cc, 0xc9b7, 0xffff, 0xffc0, + 0x0001, 0xad33, 0x1ce3, 0x81c6, 0x1c63, 0x98cc, 0xc92b, 0xffff, 0xffc0, + 0x0003, 0x4b33, 0x1ce7, 0x0dc6, 0x3c63, 0x18cc, 0xc92b, 0xffff, 0xffe0, + 0x0003, 0x5666, 0x39c7, 0x1c4c, 0x38e7, 0x18cc, 0xccaa, 0x3fff, 0xffe0, + 0x0006, 0x96e6, 0x39ce, 0x1872, 0x78c7, 0x19cc, 0xc495, 0x3fff, 0xfff0, + 0x000d, 0x2ccc, 0x738e, 0x38f3, 0xb0c7, 0x19cc, 0xc495, 0x1fff, 0xfff0, + 0x000d, 0x5dcc, 0x739c, 0x30e7, 0x89c7, 0x39ce, 0xc495, 0x1fff, 0xfff0, + 0x001a, 0x5b98, 0xe71c, 0x71e7, 0x0f8e, 0x31ce, 0x64d4, 0xffff, 0xfff8, + 0x001a, 0xbb18, 0xe738, 0x71cf, 0x1e4e, 0x31ce, 0x64ca, 0x8fff, 0xfff8, + 0x0008, 0xb731, 0xce38, 0xe1ce, 0x1c71, 0x31ce, 0x664a, 0x8fff, 0xfffc, + 0x000a, 0xf631, 0xce78, 0xe38e, 0x3cf1, 0xf1ce, 0x664a, 0x77ff, 0xfffc, + 0x000a, 0x9e63, 0x9c71, 0xc39e, 0x3ce3, 0xc9ce, 0x6649, 0x47ff, 0xfffe, + 0x000a, 0x9063, 0x9cf1, 0xc71c, 0x38e3, 0x8ece, 0x6261, 0x5fff, 0xfffe, + 0x0004, 0x9327, 0x38e3, 0x873c, 0x78e3, 0x9e36, 0x6265, 0x1bff, 0xffff, + 0x0015, 0x933f, 0x39e3, 0x8e38, 0x79e3, 0x9c30, 0x6264, 0x23ff, 0xffff, + 0x0015, 0x3339, 0xb1c7, 0x8e38, 0xf1c7, 0x9c71, 0x9324, 0xafff, 0xffff, + 0x0015, 0x2639, 0x83c7, 0x0c78, 0xf1c7, 0x1c61, 0x9f30, 0x8dff, 0xffff, + 0x0015, 0x2671, 0x8d8f, 0x1c70, 0xe3c7, 0x3c63, 0x9cf2, 0x91ff, 0xffff, + 0x0015, 0x2673, 0x8c76, 0x1871, 0xe38f, 0x3863, 0x1cce, 0x16ff, 0xffff, + 0x0009, 0x2673, 0x1c71, 0x38f1, 0xe38e, 0x38e3, 0x38cd, 0xc6ff, 0xffff, + 0x000b, 0x2673, 0x1861, 0xf0e1, 0xc78e, 0x78c3, 0x39cd, 0xbbff, 0xffff, + 0x000b, 0x6663, 0x18e3, 0xc9e3, 0xc70e, 0x70c7, 0x399d, 0xb47f, 0xffff, + 0x000b, 0x6c67, 0x18e3, 0x8ec3, 0xc71e, 0x71c6, 0x3999, 0xb4ff, 0xffff, + 0x004b, 0x6ce7, 0x38e3, 0x9e27, 0x871c, 0x71c6, 0x3199, 0x34ff, 0xffff, + 0x002b, 0x6ce7, 0x30c3, 0x9c38, 0x4f1c, 0xf1c6, 0x339b, 0x2cff, 0xfffe, + 0x0012, 0x6ce6, 0x31c7, 0x9c78, 0x761c, 0xe186, 0x739b, 0x6aff, 0xfffe, + 0x0016, 0x4cc6, 0x31c7, 0x1c70, 0xf13c, 0xe38e, 0x739b, 0x69ff, 0xfffe, + 0x0096, 0xccce, 0x3187, 0x3c70, 0xe1d8, 0xe38c, 0x733b, 0x69ff, 0xfffe, + 0x00e6, 0xd8ce, 0x718f, 0x3871, 0xe3c1, 0xe38c, 0x6333, 0x69ff, 0xfffe, + 0x0068, 0xd9ce, 0x618e, 0x38f1, 0xc386, 0xc30c, 0x6732, 0x69ff, 0xfffe, + 0x0071, 0x198e, 0x638e, 0x78e1, 0xc78e, 0x271c, 0x6732, 0x59ff, 0xfffe, + 0x0074, 0x219c, 0x630e, 0x70e3, 0xc70c, 0x3898, 0xe732, 0x55ff, 0xfffe, + 0x0034, 0xa61c, 0xe31e, 0x71e3, 0x871c, 0x78f8, 0xc732, 0x55ff, 0xfffe, + 0x0038, 0x866c, 0xc31c, 0x71c7, 0x8f18, 0x71e4, 0xce72, 0x55ff, 0xfffe, + 0x003a, 0x9263, 0xc71c, 0xf1c7, 0x0e38, 0xf1c7, 0x0e66, 0xd5ff, 0xfffe, + 0x001a, 0x1323, 0x261c, 0xe3c7, 0x1e38, 0xe3ce, 0x7664, 0xd5ff, 0xfffe, + 0x001c, 0x5323, 0x393c, 0xe38f, 0x1c70, 0xe38e, 0x71e4, 0xb3ff, 0xfffc, + 0x0015, 0x4323, 0x39d8, 0xe38e, 0x1c71, 0xc79c, 0xe304, 0xabff, 0xfffc, + 0x0015, 0x0933, 0x39c1, 0xe38e, 0x3ce1, 0xc71c, 0xe33b, 0xabff, 0xfff8, + 0x000f, 0x2933, 0x39c6, 0xc79e, 0x38e3, 0x8f39, 0xc636, 0x6bff, 0xfff8, + 0x000a, 0xa933, 0x39c6, 0x3b1c, 0x39c3, 0x8e39, 0xc676, 0x97ff, 0xfff0, + 0x000a, 0xa993, 0x39c6, 0x383c, 0x79c7, 0x0e73, 0x8c6c, 0xafff, 0xfff0, + 0x0007, 0x9591, 0x39ce, 0x30d8, 0x73c7, 0x1c73, 0x8ccd, 0x2fff, 0xffe0, + 0x0005, 0x5491, 0xb9cc, 0x71c4, 0xf386, 0x1ce7, 0x19db, 0x5fff, 0xffe0, + 0x0005, 0x5491, 0x99cc, 0x7187, 0x678e, 0x38e7, 0x1992, 0x9fff, 0xffe0, + 0x0002, 0xd491, 0x998c, 0x718e, 0x1b0c, 0x39ce, 0x33b4, 0xbfff, 0xffc0, + 0x0001, 0x2a99, 0x998c, 0x638e, 0x389c, 0x71ce, 0x3325, 0x7fff, 0xffc0, + 0x0000, 0x9249, 0x998c, 0x631c, 0x31f8, 0x739c, 0x6669, 0x7fff, 0xff80, + 0x0000, 0x4849, 0x998c, 0xe31c, 0x71c4, 0xe39c, 0x665a, 0xffff, 0xff80, + 0x0000, 0x26b9, 0x998c, 0xe718, 0x63cf, 0x0738, 0xccd4, 0xffff, 0xff00, + 0x0000, 0x095f, 0x999c, 0xc638, 0xe38e, 0x3f38, 0xd8b5, 0xffff, 0xff00, + 0x0000, 0x065b, 0x1998, 0xc630, 0xc71c, 0x71b1, 0x9969, 0xffff, 0xfe00, + 0x0000, 0x032f, 0x6198, 0xce71, 0xc73c, 0xe301, 0xb153, 0xffff, 0xfe00, + 0x0000, 0x01d5, 0xa619, 0xcc61, 0x8e38, 0xc61c, 0x32d7, 0xffff, 0xfc00, + 0x0000, 0x02e7, 0xb279, 0x8c63, 0x9c71, 0xcc39, 0x82a7, 0xffff, 0xf800, + 0x0000, 0x0112, 0xd367, 0x9cc3, 0x1ce3, 0x9873, 0x3baf, 0xffff, 0xe000, + 0x0000, 0x0085, 0x5b26, 0x78c7, 0x39e7, 0x30e6, 0x748f, 0xffff, 0xc000, + 0x0000, 0x004b, 0xe926, 0x6186, 0x39ce, 0x619d, 0xe96f, 0xffff, 0x8000, + 0x0000, 0x001c, 0xad26, 0x664e, 0x739c, 0x6333, 0xa6df, 0xffff, 0x0000, + 0x0000, 0x000e, 0xd5a6, 0xcefc, 0x6718, 0xc667, 0x4b7f, 0xfffe, 0x0000, + 0x0000, 0x0004, 0xd4b6, 0xcce3, 0xe739, 0x8cce, 0xb6ff, 0xfff8, 0x0000, + 0x0000, 0x000d, 0x2ab4, 0xcdc6, 0x3e73, 0x19bd, 0x6bff, 0xfff0, 0x0000, + 0x0000, 0x0003, 0x6a94, 0xd9cc, 0x63e6, 0x3374, 0xb7ff, 0xffe0, 0x0000, + 0x0000, 0x0000, 0xd954, 0xdb98, 0xc60c, 0x4eeb, 0x5fff, 0xffc0, 0x0000, + 0x0000, 0x0000, 0x36d5, 0xd331, 0x1860, 0x99d6, 0x7fff, 0xff00, 0x0000, + 0x0000, 0x0000, 0x0d85, 0x9662, 0x31ce, 0xf7ba, 0xffff, 0xfe00, 0x0000, + 0x0000, 0x0000, 0x0313, 0xa6cc, 0x473b, 0x1eb3, 0xffff, 0xf800, 0x0000, + 0x0000, 0x0000, 0x00c1, 0x4d99, 0x9cec, 0x42e7, 0xffff, 0xe000, 0x0000, + 0x0000, 0x0000, 0x0030, 0x7722, 0x7362, 0x087f, 0xffff, 0x8000, 0x0000, + 0x0000, 0x0000, 0x000c, 0xa185, 0xcb90, 0x81ff, 0xfffc, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0003, 0x0fef, 0x2e49, 0x1fff, 0xfff0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0803, 0x7281, 0xffff, 0xff80, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0038, 0x481f, 0xffff, 0xfe00, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xf100, 0x007f, 0xf800, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x00fe, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0f7b, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf7ec, 0x3ff0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x000f, 0x7e70, 0xc4ff, 0x8000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x00f7, 0xe383, 0x0fcd, 0xa000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x057e, 0x0e1c, 0x3f8f, 0x9800, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1a60, 0x78f0, 0xff1c, 0xde00, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x2cc3, 0xc3c1, 0xfe3c, 0xeb80, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xd187, 0xdf07, 0xfc38, 0xe7e0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0001, 0x660f, 0xf01f, 0xf879, 0xe798, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0006, 0xcc1f, 0xe0ff, 0xf0f1, 0xe798, 0x0000, 0x0000, 0x0000, + 0x0000, 0x001b, 0x187f, 0xc1ff, 0xe1f1, 0xe7cd, 0x0000, 0x0000, 0x0000, + 0x0000, 0x002e, 0x30ff, 0x83c1, 0xc1e1, 0xe7cc, 0xa000, 0x0000, 0x0000, + 0x0000, 0x00dc, 0xc1ff, 0x0783, 0xe3e1, 0xc7e6, 0xd000, 0x0000, 0x0000, + 0x0000, 0x0171, 0x83fe, 0x0f83, 0xe3c1, 0xc3e6, 0x5800, 0x0000, 0x0000, + 0x0000, 0x06e3, 0x07fc, 0x1f07, 0xc0c3, 0xc3f3, 0x2c00, 0x0000, 0x0000, + 0x0000, 0x0bc6, 0x0ffc, 0x3e0f, 0xc1f3, 0xc3f3, 0x3500, 0x0000, 0x0000, + 0x0000, 0x1198, 0x3ff8, 0x3c0f, 0x81ff, 0xc3f1, 0x9a80, 0x0000, 0x0000, + 0x0000, 0x13e0, 0x7ff0, 0x7c1f, 0x83ff, 0x03f9, 0xcd40, 0x0000, 0x0000, + 0x0000, 0x23c3, 0xffe0, 0xf83f, 0x03fe, 0x0ff8, 0xc5a0, 0x0000, 0x0000, + 0x0000, 0x27c7, 0x9fc1, 0xf03f, 0x07fe, 0x0f3c, 0xe6c0, 0x0000, 0x0000, + 0x0000, 0x4f87, 0x0783, 0xe07e, 0x07fe, 0x0f0c, 0x6360, 0x0000, 0x0000, + 0x0000, 0x8f0f, 0x07c7, 0xe07e, 0x0ffe, 0x1f0f, 0x71b0, 0x0000, 0x0000, + 0x0000, 0x9f1e, 0x0f8f, 0xc0fc, 0x0ffc, 0x1f0f, 0x0198, 0x0000, 0x0000, + 0x0001, 0x1e1e, 0x0f83, 0xc1fc, 0x1ffc, 0x1f0f, 0x0fda, 0x0000, 0x0000, + 0x0001, 0x3e3c, 0x1f03, 0xf1f8, 0x1ffc, 0x1f0f, 0x0fcd, 0x0000, 0x0000, + 0x0002, 0x7c3c, 0x1f07, 0xfff8, 0x3ffc, 0x1f0f, 0x0fcc, 0x8000, 0x0000, + 0x0002, 0x7878, 0x3e07, 0xffb0, 0x3ff8, 0x1f0f, 0x0fcc, 0x8000, 0x0000, + 0x0004, 0xf8f8, 0x3e0f, 0xff82, 0x7ff8, 0x1e0f, 0x07e6, 0x8000, 0x0000, + 0x0009, 0xf0f0, 0x7c0f, 0xff03, 0xfff8, 0x1e0f, 0x07e6, 0x4000, 0x0000, + 0x0009, 0xe1f0, 0x7c1f, 0xff07, 0xf7f8, 0x3e0f, 0x07e6, 0x4000, 0x0000, + 0x0013, 0xe3e0, 0xf81f, 0xfe07, 0xf1f0, 0x3e0f, 0x87e7, 0x4000, 0x0000, + 0x0013, 0xc3e0, 0xf83f, 0xfe0f, 0xe070, 0x3e0f, 0x87f3, 0x2000, 0x0000, + 0x002f, 0xc7c1, 0xf03f, 0xfe0f, 0xe07e, 0x3e0f, 0x87f3, 0x2000, 0x0000, + 0x002c, 0x87c1, 0xf07f, 0xfc0f, 0xc0fe, 0x3e0f, 0x87f3, 0xa800, 0x0000, + 0x002c, 0xef83, 0xe07f, 0xfc1f, 0xc0fc, 0x0e0f, 0x87f1, 0x9000, 0x0000, + 0x002c, 0xe383, 0xe0ff, 0xf81f, 0xc0fc, 0x0f0f, 0x83f9, 0x9000, 0x0000, + 0x0028, 0xe3e7, 0xc0ff, 0xf83f, 0x80fc, 0x1fff, 0x83f9, 0xd400, 0x0000, + 0x0059, 0xe3ff, 0xc1ff, 0xf03f, 0x81fc, 0x1fff, 0x83f8, 0xcc00, 0x0000, + 0x0059, 0xc3fe, 0x01ff, 0xf03f, 0x01f8, 0x1ffe, 0x13f8, 0xc800, 0x0000, + 0x0059, 0xc7fe, 0x03ff, 0xf07f, 0x01f8, 0x1ffe, 0x1ffc, 0xea00, 0x0000, + 0x0059, 0xc7fe, 0x0fff, 0xe07f, 0x03f8, 0x3ffc, 0x1f3c, 0xe600, 0x0000, + 0x0059, 0xc7fc, 0x0f87, 0xe07e, 0x03f0, 0x3ffc, 0x1f0c, 0x6500, 0x0000, + 0x0051, 0xc7fc, 0x1f81, 0xc0fe, 0x03f0, 0x3ffc, 0x3f0e, 0x7500, 0x0000, + 0x0053, 0xc7fc, 0x1f81, 0xc0fe, 0x07f0, 0x7ffc, 0x3e0e, 0x3200, 0x0000, + 0x0053, 0x87fc, 0x1f03, 0xf1fc, 0x07f0, 0x7ff8, 0x3e1e, 0x3e80, 0x0000, + 0x0053, 0x8ff8, 0x1f03, 0xf0fc, 0x07e0, 0x7ff8, 0x3e1e, 0x3e00, 0x0000, + 0x0093, 0x8ff8, 0x3f03, 0xe038, 0x07e0, 0x7ff8, 0x3e1e, 0x3e00, 0x0000, + 0x00b3, 0x8ff8, 0x3f03, 0xe03f, 0xcfe0, 0xfff8, 0x3c1c, 0x3e00, 0x0000, + 0x00a3, 0x8ff8, 0x3e07, 0xe07f, 0xffe0, 0xfff8, 0x7c1c, 0x7c00, 0x0000, + 0x00a7, 0x8ff8, 0x3e07, 0xe07f, 0xfec0, 0xfff0, 0x7c1c, 0x7d00, 0x0000, + 0x00a7, 0x0ff0, 0x3e07, 0xc07f, 0xfe00, 0xfff0, 0x7c3c, 0x7c00, 0x0000, + 0x00b7, 0x1ff0, 0x7e0f, 0xc07f, 0xfc01, 0xfff0, 0x7c3c, 0x7c00, 0x0000, + 0x00ff, 0x1ff0, 0x7e0f, 0xc0ff, 0xfc07, 0xfff0, 0x783c, 0x7c00, 0x0000, + 0x005e, 0x1ff0, 0x7c0f, 0x80ff, 0xf80f, 0xdfe0, 0x783c, 0x7c00, 0x0000, + 0x005f, 0x3fe0, 0x7c0f, 0x80ff, 0xf80f, 0xc0e0, 0xf83c, 0x7800, 0x0000, + 0x003f, 0x3860, 0xfc1f, 0x81ff, 0xf81f, 0x80e0, 0xf83c, 0x7800, 0x0000, + 0x002f, 0x1870, 0xfc1f, 0x81ff, 0xf01f, 0x81f8, 0xf07c, 0x7800, 0x0000, + 0x002f, 0x1c7c, 0xf81f, 0x01ff, 0xf03f, 0x01f8, 0x3078, 0xf800, 0x0000, + 0x001f, 0x9c3c, 0x381f, 0x03ff, 0xe03f, 0x03f0, 0x7878, 0xf800, 0x0000, + 0x0017, 0x9c3c, 0x3f3f, 0x03ff, 0xe07f, 0x03f0, 0x7ff8, 0xf800, 0x0000, + 0x001f, 0x8c3c, 0x3fff, 0x03ff, 0xe07e, 0x07e0, 0xfff8, 0xf000, 0x0000, + 0x001f, 0xce3c, 0x3ffe, 0x03ff, 0xc0fe, 0x07e0, 0xffc3, 0xf000, 0x0000, + 0x000b, 0xce3c, 0x3ff8, 0x07ff, 0xc0fc, 0x0fc1, 0xffc7, 0xb000, 0x0000, + 0x000f, 0xce3c, 0x3ff8, 0x3fff, 0xc1fc, 0x0fc1, 0xff87, 0x1800, 0x0000, + 0x000f, 0xce1c, 0x3ff8, 0x3fff, 0x81f8, 0x0f83, 0xff8f, 0x3000, 0x0000, + 0x0005, 0xe61e, 0x3ff0, 0x3f1f, 0x83f8, 0x1f83, 0xff0e, 0x3000, 0x0000, + 0x0007, 0xe71e, 0x3ff0, 0x7e07, 0x03f8, 0x1f07, 0xfe1c, 0x6000, 0x0000, + 0x0007, 0xe71e, 0x1ff0, 0x7e07, 0x87f0, 0x3f07, 0xfe1c, 0xe000, 0x0000, + 0x0003, 0xe71e, 0x1ff0, 0x7e0f, 0xe3f0, 0x3e0f, 0xfc38, 0xc000, 0x0000, + 0x0002, 0xf31e, 0x1ff0, 0x7c0f, 0xc0e0, 0x7e0f, 0xfc39, 0x8000, 0x0000, + 0x0001, 0x5b8e, 0x1ff0, 0x7c1f, 0xc1e0, 0x7c1f, 0xf871, 0x8000, 0x0000, + 0x0000, 0xad8e, 0x1ff0, 0xfc1f, 0x81fc, 0xfc1f, 0xf863, 0x0000, 0x0000, + 0x0000, 0x54fe, 0x1ff0, 0xf81f, 0x83ff, 0xf83f, 0xf0e7, 0x0000, 0x0000, + 0x0000, 0x2278, 0x1fe0, 0xf83f, 0x03ff, 0xc03f, 0xe0c6, 0x0000, 0x0000, + 0x0000, 0x137c, 0x1fe0, 0xf83f, 0x07ff, 0x81ff, 0xe18e, 0x0000, 0x0000, + 0x0000, 0x09bc, 0x7fe0, 0xf07e, 0x07ff, 0x03ff, 0xc19c, 0x0000, 0x0000, + 0x0000, 0x049e, 0x3861, 0xf07e, 0x0fff, 0x07e0, 0xc318, 0x0000, 0x0000, + 0x0000, 0x054e, 0x3c61, 0xf07c, 0x1ffe, 0x0fc1, 0xe338, 0x0000, 0x0000, + 0x0000, 0x02a7, 0x1c79, 0xe0fc, 0x1ffc, 0x1f83, 0xc230, 0x0000, 0x0000, + 0x0000, 0x0157, 0x9c38, 0x60f8, 0x3ff8, 0x3f07, 0x87f0, 0x0000, 0x0000, + 0x0000, 0x00a3, 0x8e38, 0x79f8, 0x3ff0, 0x7e1e, 0x0f80, 0x0000, 0x0000, + 0x0000, 0x0049, 0xce38, 0x7fb0, 0x7fe0, 0x7c3c, 0x3f00, 0x0000, 0x0000, + 0x0000, 0x0024, 0xe638, 0xff00, 0x7fe0, 0xf878, 0x7c00, 0x0000, 0x0000, + 0x0000, 0x0012, 0xe738, 0xff03, 0xffc1, 0xf0f0, 0xf800, 0x0000, 0x0000, + 0x0000, 0x000c, 0x7338, 0xfe07, 0xcf83, 0xe1c1, 0xf000, 0x0000, 0x0000, + 0x0000, 0x0003, 0x7318, 0xfe0f, 0x8307, 0xc387, 0xc000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xdd98, 0xfc1f, 0x07cf, 0x8f0f, 0x8000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x3799, 0xfc3e, 0x1f87, 0x1e1f, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0db9, 0xf87c, 0x3e0f, 0xf83c, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x033b, 0xf8f0, 0x783f, 0xe0f8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x00cd, 0x91e1, 0xe0ff, 0x83f0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0032, 0xbbc3, 0x83fc, 0x0c40, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x000c, 0xb1c6, 0x0fe0, 0xe100, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0003, 0x4ff0, 0x3f8e, 0x1000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0802, 0xfcf1, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0038, 0x6f90, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xfd00, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x00ec, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0fbc, 0xf800, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf9f0, 0x3ff0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x000f, 0x8f80, 0xfb1f, 0x8000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x00f8, 0xfc03, 0xf1ce, 0xa000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0687, 0xf01f, 0xc3f1, 0xd800, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1c7f, 0x80ff, 0x07e0, 0xea00, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x30fc, 0x03fe, 0x1fc0, 0xf2c0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xe1f8, 0x5ff8, 0x3fc0, 0xf9b0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0001, 0x87f0, 0xffe0, 0x7f81, 0xf9ec, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0007, 0x0fe1, 0xff00, 0xff01, 0xf8e3, 0x0000, 0x0000, 0x0000, + 0x0000, 0x001c, 0x1f83, 0xfe03, 0xfe01, 0xf8f1, 0xc000, 0x0000, 0x0000, + 0x0000, 0x0030, 0x3f0f, 0xfc01, 0xfe01, 0xf8f0, 0xf000, 0x0000, 0x0000, + 0x0000, 0x00e0, 0xfe1f, 0xf803, 0xfc01, 0xf8f8, 0xf800, 0x0000, 0x0000, + 0x0000, 0x0181, 0xfc3f, 0xf003, 0xfc01, 0xfc78, 0x6c00, 0x0000, 0x0000, + 0x0000, 0x0703, 0xf87f, 0xe007, 0xff03, 0xfc7c, 0x3600, 0x0000, 0x0000, + 0x0000, 0x0c07, 0xf0ff, 0xc00f, 0xfe03, 0xfc7c, 0x3a00, 0x0000, 0x0000, + 0x0000, 0x1e1f, 0xc1ff, 0xc00f, 0xfe0f, 0xfc7e, 0x1d00, 0x0000, 0x0000, + 0x0000, 0x1cff, 0x87ff, 0x801f, 0xfc1f, 0xfc3e, 0x0e80, 0x0000, 0x0000, + 0x0000, 0x3cfc, 0x0fff, 0x003f, 0xfc1f, 0xf03f, 0x0640, 0x0000, 0x0000, + 0x0000, 0x39f8, 0x1ffe, 0x003f, 0xf81f, 0xf03f, 0x0760, 0x0000, 0x0000, + 0x0000, 0x71f8, 0x07fc, 0x007f, 0xf83f, 0xf00f, 0x83b0, 0x0000, 0x0000, + 0x0000, 0xf3f0, 0x07f8, 0x007f, 0xf03f, 0xe00f, 0x81d8, 0x0000, 0x0000, + 0x0000, 0xe7e0, 0x0ff0, 0x00ff, 0xf03f, 0xe00f, 0xf1ec, 0x0000, 0x0000, + 0x0001, 0xe7e0, 0x0ffc, 0x01ff, 0xe07f, 0xe00f, 0xf1e4, 0x0000, 0x0000, + 0x0001, 0xcfc0, 0x1ffc, 0x01ff, 0xe07f, 0xe00f, 0xf1f2, 0x0000, 0x0000, + 0x0003, 0x8fc0, 0x1ff8, 0x0fff, 0xc07f, 0xe00f, 0xf1f1, 0x0000, 0x0000, + 0x0003, 0x9f80, 0x3ff8, 0x1fff, 0xc0ff, 0xe00f, 0xf0f0, 0xc000, 0x0000, + 0x0007, 0x1f00, 0x3ff0, 0x1ffd, 0x80ff, 0xe00f, 0xf8f8, 0xc000, 0x0000, + 0x000e, 0x3f00, 0x7ff0, 0x3ffc, 0x00ff, 0xe00f, 0xf8f8, 0x6000, 0x0000, + 0x000e, 0x7e00, 0x7fe0, 0x3ff8, 0x01ff, 0xc00f, 0xf8f8, 0x6000, 0x0000, + 0x001c, 0x7c00, 0xffe0, 0x7ff8, 0x01ff, 0xc00f, 0xf8f8, 0x6000, 0x0000, + 0x001c, 0xfc00, 0xffc0, 0x7ff0, 0x007f, 0xc00f, 0xf8fc, 0x3000, 0x0000, + 0x0030, 0xf801, 0xffc0, 0xfff0, 0x007f, 0xc00f, 0xf87c, 0x3000, 0x0000, + 0x0030, 0xf801, 0xff80, 0xfff0, 0x00ff, 0xc00f, 0xf87c, 0x3000, 0x0000, + 0x0030, 0xf003, 0xff81, 0xffe0, 0x00ff, 0xf00f, 0xf87e, 0x1800, 0x0000, + 0x0030, 0xfc03, 0xff01, 0xffe0, 0x00ff, 0xf00f, 0xfc7e, 0x1800, 0x0000, + 0x0030, 0xfc27, 0xff03, 0xffc0, 0x00ff, 0xe03f, 0xfc7e, 0x1800, 0x0000, + 0x0061, 0xfc3f, 0xfe03, 0xffc0, 0x01ff, 0xe03f, 0xfc7f, 0x0800, 0x0000, + 0x0061, 0xfc3f, 0xfe07, 0xffc0, 0x01ff, 0xe07f, 0xec3f, 0x0c00, 0x0000, + 0x0061, 0xf83f, 0xfc07, 0xff80, 0x01ff, 0xe07f, 0xe03f, 0x0c00, 0x0000, + 0x0061, 0xf87f, 0xf00f, 0xff80, 0x03ff, 0xc07f, 0xe03f, 0x0400, 0x0000, + 0x0061, 0xf87f, 0xf007, 0xff80, 0x03ff, 0xc07f, 0xe00f, 0x8600, 0x0000, + 0x0061, 0xf87f, 0xe001, 0xff00, 0x03ff, 0xc0ff, 0xc00f, 0x8600, 0x0000, + 0x0063, 0xf87f, 0xe001, 0xff00, 0x07ff, 0x80ff, 0xc00f, 0xc300, 0x0000, + 0x0063, 0xf87f, 0xe003, 0xfe00, 0x07ff, 0x80ff, 0xc01f, 0xc700, 0x0000, + 0x0063, 0xf07f, 0xe003, 0xff00, 0x07ff, 0x81ff, 0xc01f, 0xc700, 0x0000, + 0x00e3, 0xf0ff, 0xc003, 0xffc0, 0x07ff, 0x81ff, 0xc01f, 0xc700, 0x0000, + 0x00c3, 0xf0ff, 0xc003, 0xffc0, 0x4fff, 0x01ff, 0xc01f, 0xcf00, 0x0000, + 0x00c3, 0xf0ff, 0xc007, 0xff80, 0x7fff, 0x01ff, 0x801f, 0x8f00, 0x0000, + 0x00c7, 0xf0ff, 0xc007, 0xff80, 0xffff, 0x03ff, 0x801f, 0x8e00, 0x0000, + 0x00c7, 0xf0ff, 0xc007, 0xff80, 0xffff, 0x03ff, 0x803f, 0x8e00, 0x0000, + 0x00c7, 0xe0ff, 0x800f, 0xff81, 0xfffe, 0x03ff, 0x803f, 0x8e00, 0x0000, + 0x00cf, 0xe1ff, 0x800f, 0xff01, 0xfff8, 0x03ff, 0x803f, 0x8e00, 0x0000, + 0x0067, 0xe1ff, 0x800f, 0xff01, 0xfff0, 0x07ff, 0x803f, 0x9e00, 0x0000, + 0x0067, 0xc1ff, 0x800f, 0xff03, 0xfff0, 0x00ff, 0x003f, 0x9e00, 0x0000, + 0x0027, 0xc07f, 0x001f, 0xfe03, 0xffe0, 0x00ff, 0x003f, 0x9e00, 0x0000, + 0x0033, 0xe07f, 0x001f, 0xfe07, 0xffe0, 0x01ff, 0x007f, 0x9e00, 0x0000, + 0x0033, 0xe07f, 0x001f, 0xfe07, 0xffc0, 0x01ff, 0xc07f, 0x1e00, 0x0000, + 0x0013, 0xe03f, 0xc01f, 0xfc07, 0xffc0, 0x03ff, 0x807f, 0x1e00, 0x0000, + 0x0019, 0xe03f, 0xc13f, 0xfc0f, 0xff80, 0x03ff, 0x81ff, 0x3c00, 0x0000, + 0x0019, 0xf03f, 0xc1ff, 0xfc0f, 0xff80, 0x07ff, 0x03ff, 0x3c00, 0x0000, + 0x0019, 0xf03f, 0xc1ff, 0xfc0f, 0xff00, 0x07ff, 0x03fc, 0x3c00, 0x0000, + 0x000d, 0xf03f, 0xc1ff, 0xf81f, 0xff00, 0x0ffe, 0x07f8, 0x3c00, 0x0000, + 0x000c, 0xf03f, 0xc1ff, 0xc01f, 0xfe00, 0x0ffe, 0x07f8, 0x1c00, 0x0000, + 0x000c, 0xf01f, 0xc1ff, 0xc03f, 0xfe00, 0x0ffc, 0x0ff0, 0x3800, 0x0000, + 0x0006, 0xf81f, 0xc1ff, 0xc01f, 0xfc00, 0x1ffc, 0x0ff0, 0x3800, 0x0000, + 0x0006, 0x781f, 0xc1ff, 0x8007, 0xfc00, 0x1ff8, 0x1fe0, 0x7000, 0x0000, + 0x0006, 0x781f, 0xe1ff, 0x8007, 0xf800, 0x3ff8, 0x1fe0, 0xf000, 0x0000, + 0x0003, 0x781f, 0xe1ff, 0x800f, 0xfc00, 0x3ff0, 0x3fc0, 0xe000, 0x0000, + 0x0003, 0x3c1f, 0xe1ff, 0x800f, 0xff00, 0x7ff0, 0x3fc1, 0xc000, 0x0000, + 0x0001, 0x9c0f, 0xe1ff, 0x801f, 0xfe00, 0x7fe0, 0x7f81, 0xc000, 0x0000, + 0x0000, 0xce0f, 0xe1ff, 0x001f, 0xfe04, 0xffe0, 0x7f83, 0x8000, 0x0000, + 0x0000, 0x673f, 0xe1ff, 0x001f, 0xfc0f, 0xffc0, 0xff07, 0x8000, 0x0000, + 0x0000, 0x339f, 0xe1ff, 0x003f, 0xfc0f, 0xffc0, 0xff07, 0x0000, 0x0000, + 0x0000, 0x1b9f, 0xe1ff, 0x003f, 0xf81f, 0xfe01, 0xfe0f, 0x0000, 0x0000, + 0x0000, 0x0dcf, 0x81ff, 0x007f, 0xf83f, 0xfc01, 0xfe1e, 0x0000, 0x0000, + 0x0000, 0x06e7, 0xc07e, 0x007f, 0xf03f, 0xf800, 0xfc1c, 0x0000, 0x0000, + 0x0000, 0x0677, 0xc07e, 0x007f, 0xe07f, 0xf001, 0xfc3c, 0x0000, 0x0000, + 0x0000, 0x033b, 0xe07e, 0x00ff, 0xe0ff, 0xe003, 0xfc38, 0x0000, 0x0000, + 0x0000, 0x0199, 0xe03f, 0x80ff, 0xc1ff, 0xc007, 0xf8f8, 0x0000, 0x0000, + 0x0000, 0x00cd, 0xf03f, 0x81ff, 0xc1ff, 0x801f, 0xf1f0, 0x0000, 0x0000, + 0x0000, 0x006e, 0xf03f, 0x87ff, 0x83ff, 0x803f, 0xc7e0, 0x0000, 0x0000, + 0x0000, 0x0037, 0xf83f, 0x0fff, 0x87ff, 0x007f, 0x8f80, 0x0000, 0x0000, + 0x0000, 0x001b, 0x783f, 0x0ffc, 0x07fe, 0x00ff, 0x3f00, 0x0000, 0x0000, + 0x0000, 0x000f, 0xbc3f, 0x0ff8, 0x0ffc, 0x01fe, 0x7c00, 0x0000, 0x0000, + 0x0000, 0x0003, 0xbc1f, 0x1ff0, 0x03f8, 0x03f8, 0xf800, 0x0000, 0x0000, + 0x0000, 0x0000, 0xee1f, 0x1fe0, 0x07f0, 0x0ff3, 0xe000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x3b1e, 0x1fc0, 0x1ff8, 0x1fe7, 0x8000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0ede, 0x1f80, 0x3ff0, 0xffdf, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x03ac, 0x3f00, 0x7fc3, 0xff3c, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x00ee, 0x1e01, 0xff0f, 0xfcf8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0039, 0x3c03, 0xfc7f, 0xf060, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x000e, 0x3e07, 0xf3ff, 0x0100, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0003, 0x77ff, 0xcff0, 0x1000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x09fc, 0x7f01, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0008, 0x7010, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0500, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x000f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x003f, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x01ff, 0xc7f0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0fff, 0x030f, 0x8000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xfffc, 0x01f0, 0xe000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0707, 0xffe0, 0x03f9, 0xe800, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1f9f, 0xff00, 0x07ff, 0xf200, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x3f03, 0xfc00, 0x1fff, 0x0c80, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xfe00, 0x6000, 0x3fff, 0x0020, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0001, 0xf800, 0xfc00, 0x7ffe, 0x01c8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0007, 0xf001, 0xff80, 0xfffe, 0x00fe, 0x0000, 0x0000, 0x0000, + 0x0000, 0x001f, 0xe003, 0xffe3, 0xfffe, 0x00fe, 0x0000, 0x0000, 0x0000, + 0x0000, 0x003f, 0xc00f, 0xffff, 0xfffe, 0x00ff, 0x3000, 0x0000, 0x0000, + 0x0000, 0x00ff, 0x001f, 0xfffc, 0x1ffe, 0x00ff, 0x1800, 0x0000, 0x0000, + 0x0000, 0x01fe, 0x003f, 0xfffc, 0x03fe, 0x007f, 0x8c00, 0x0000, 0x0000, + 0x0000, 0x07fc, 0x007f, 0xfff8, 0x003c, 0x007f, 0xc600, 0x0000, 0x0000, + 0x0000, 0x03f8, 0x00ff, 0xfff0, 0x000c, 0x007f, 0xc300, 0x0000, 0x0000, + 0x0000, 0x0060, 0x01ff, 0xfff0, 0x000f, 0x007f, 0xe180, 0x0000, 0x0000, + 0x0000, 0x00f0, 0x07ff, 0xffe0, 0x001f, 0xf03f, 0xf0c0, 0x0000, 0x0000, + 0x0000, 0x00ff, 0x0fff, 0xffc0, 0x001f, 0xfc3f, 0xf860, 0x0000, 0x0000, + 0x0000, 0x01ff, 0xffff, 0xffc0, 0x001f, 0xffff, 0xf860, 0x0000, 0x0000, + 0x0000, 0x01ff, 0xfbff, 0xff80, 0x003f, 0xfff3, 0xfc30, 0x0000, 0x0000, + 0x0000, 0x03ff, 0xf83f, 0xff80, 0x003f, 0xfff0, 0xfe18, 0x0000, 0x0000, + 0x0000, 0x07ff, 0xf00f, 0xff00, 0x003f, 0xfff0, 0x0e0c, 0x0000, 0x0000, + 0x0000, 0x07ff, 0xf000, 0x3e00, 0x007f, 0xfff0, 0x0106, 0x0000, 0x0000, + 0x0000, 0x0fff, 0xe000, 0x0e00, 0x007f, 0xfff0, 0x01e3, 0x0000, 0x0000, + 0x0000, 0x0fff, 0xe000, 0x0e00, 0x007f, 0xfff0, 0x01ff, 0x8000, 0x0000, + 0x0000, 0x1fff, 0xc000, 0x1fc0, 0x00ff, 0xfff0, 0x00ff, 0x0000, 0x0000, + 0x0000, 0x1fff, 0xc000, 0x1ffe, 0x00ff, 0xfff0, 0x00ff, 0x0000, 0x0000, + 0x0000, 0x3fff, 0x8000, 0x3fff, 0xc0ff, 0xfff0, 0x00ff, 0x8000, 0x0000, + 0x0000, 0x7fff, 0x8000, 0x3fff, 0xf9ff, 0xfff0, 0x00ff, 0x8000, 0x0000, + 0x0000, 0x7fff, 0x0000, 0x7fff, 0xffff, 0xfff0, 0x00ff, 0x8000, 0x0000, + 0x0000, 0xffff, 0x0000, 0x7fff, 0xffbf, 0xfff0, 0x00ff, 0xc000, 0x0000, + 0x003c, 0xfffe, 0x0000, 0xffff, 0xff80, 0xfff0, 0x007f, 0xc000, 0x0000, + 0x003f, 0x7ffe, 0x0000, 0xffff, 0xff00, 0x3ff0, 0x007f, 0xc000, 0x0000, + 0x003f, 0x0ffc, 0x0001, 0xffff, 0xff00, 0x07f0, 0x007f, 0xe000, 0x0000, + 0x003f, 0x03fc, 0x0001, 0xffff, 0xff00, 0x00f0, 0x007f, 0xe000, 0x0000, + 0x003f, 0x0038, 0x0003, 0xffff, 0xff00, 0x0038, 0x007f, 0xe000, 0x0000, + 0x007e, 0x0038, 0x0003, 0xffff, 0xfe00, 0x003e, 0x007f, 0xf000, 0x0000, + 0x007e, 0x003f, 0xc007, 0xffff, 0xfe00, 0x007f, 0xf03f, 0xf000, 0x0000, + 0x007e, 0x003f, 0xf007, 0xffff, 0xfe00, 0x007f, 0xfc3f, 0xf000, 0x0000, + 0x007e, 0x007f, 0xfe0f, 0xffff, 0xfc00, 0x007f, 0xffff, 0xf800, 0x0000, + 0x007e, 0x007f, 0xffff, 0xffff, 0xfc00, 0x007f, 0xfff3, 0xf800, 0x0000, + 0x007e, 0x007f, 0xfffe, 0xffff, 0xfc00, 0x00ff, 0xfff0, 0x7800, 0x0000, + 0x007c, 0x007f, 0xfffe, 0x3fff, 0xf800, 0x00ff, 0xfff0, 0x0c00, 0x0000, + 0x007c, 0x007f, 0xfffc, 0x07ff, 0xf800, 0x00ff, 0xffe0, 0x0700, 0x0000, + 0x007c, 0x007f, 0xfffc, 0x00ff, 0xf800, 0x01ff, 0xffe0, 0x0780, 0x0000, + 0x00fc, 0x00ff, 0xfffc, 0x001f, 0xf800, 0x01ff, 0xffe0, 0x0780, 0x0000, + 0x00fc, 0x00ff, 0xfffc, 0x0000, 0x7000, 0x01ff, 0xffe0, 0x0f80, 0x0000, + 0x00fc, 0x00ff, 0xfff8, 0x0000, 0x7800, 0x01ff, 0xffe0, 0x0f00, 0x0000, + 0x00f8, 0x00ff, 0xfff8, 0x0000, 0xff00, 0x03ff, 0xffe0, 0x0f00, 0x0000, + 0x0078, 0x00ff, 0xfff8, 0x0000, 0xffe0, 0x03ff, 0xffc0, 0x0f00, 0x0000, + 0x0008, 0x00ff, 0xfff0, 0x0001, 0xfff8, 0x03ff, 0xffc0, 0x0f00, 0x0000, + 0x000e, 0x01ff, 0xfff0, 0x0001, 0xffff, 0x03ff, 0xffc0, 0x0f00, 0x0000, + 0x0007, 0xc1ff, 0xfff0, 0x0001, 0xffff, 0xe7ff, 0xffc0, 0x1f00, 0x0000, + 0x0007, 0xf9ff, 0xfff0, 0x0003, 0xffff, 0xff7f, 0xffc0, 0x1e00, 0x0000, + 0x0007, 0xffff, 0xffe0, 0x0003, 0xffff, 0xff1f, 0xffc0, 0x1e00, 0x0000, + 0x0003, 0xff8f, 0xffe0, 0x0007, 0xffff, 0xfe03, 0xff80, 0x1e00, 0x0000, + 0x0003, 0xff80, 0xffe0, 0x0007, 0xffff, 0xfe00, 0x3f80, 0x1e00, 0x0000, + 0x0003, 0xffc0, 0x1fe0, 0x0007, 0xffff, 0xfc00, 0x0780, 0x1e00, 0x0000, + 0x0001, 0xffc0, 0x01c0, 0x000f, 0xffff, 0xfc00, 0x0180, 0x3e00, 0x0000, + 0x0001, 0xffc0, 0x01e0, 0x000f, 0xffff, 0xf800, 0x03e0, 0x3c00, 0x0000, + 0x0001, 0xffc0, 0x01f8, 0x000f, 0xffff, 0xf800, 0x03ff, 0x3c00, 0x0000, + 0x0001, 0xffc0, 0x01ff, 0x001f, 0xffff, 0xf000, 0x07ff, 0xfc00, 0x0000, + 0x0000, 0xffc0, 0x01ff, 0xfc1f, 0xffff, 0xf000, 0x07ff, 0xe000, 0x0000, + 0x0000, 0xffe0, 0x01ff, 0xff3f, 0xffff, 0xf000, 0x0fff, 0xc000, 0x0000, + 0x0000, 0xffe0, 0x01ff, 0xffff, 0xffff, 0xe000, 0x0fff, 0xc000, 0x0000, + 0x0000, 0x7fe0, 0x01ff, 0xfffb, 0xffff, 0xe000, 0x1fff, 0x8000, 0x0000, + 0x0000, 0x7fe0, 0x01ff, 0xfff8, 0x7fff, 0xc000, 0x1fff, 0x0000, 0x0000, + 0x0000, 0x7fe0, 0x01ff, 0xfff0, 0x03ff, 0xc000, 0x3fff, 0x0000, 0x0000, + 0x0003, 0xbfe0, 0x01ff, 0xfff0, 0x007f, 0x8000, 0x3ffe, 0x0000, 0x0000, + 0x0001, 0xe7f0, 0x01ff, 0xffe0, 0x001f, 0x8000, 0x7ffe, 0x0000, 0x0000, + 0x0000, 0xf1f0, 0x01ff, 0xffe0, 0x0007, 0x0000, 0x7ffc, 0x0000, 0x0000, + 0x0000, 0x7830, 0x01ff, 0xffe0, 0x000f, 0xe000, 0xfff8, 0x0000, 0x0000, + 0x0000, 0x3c1e, 0x01ff, 0xffc0, 0x000f, 0xf800, 0xfff8, 0x0000, 0x0000, + 0x0000, 0x1c1f, 0x81ff, 0xffc0, 0x001f, 0xffc1, 0xfff0, 0x0000, 0x0000, + 0x0000, 0x0e0f, 0xf9ff, 0xff80, 0x003f, 0xfff1, 0xffe0, 0x0000, 0x0000, + 0x0000, 0x0707, 0xffff, 0xff80, 0x003f, 0xffff, 0xffe0, 0x0000, 0x0000, + 0x0000, 0x0787, 0xff9f, 0xff80, 0x007f, 0xfffe, 0x1fc0, 0x0000, 0x0000, + 0x0000, 0x03c3, 0xff81, 0xff00, 0x00ff, 0xfffc, 0x01c0, 0x0000, 0x0000, + 0x0000, 0x01e1, 0xffc0, 0x1f00, 0x01ff, 0xfff8, 0x00c0, 0x0000, 0x0000, + 0x0000, 0x00f1, 0xffc0, 0x0600, 0x01ff, 0xffe0, 0x01f0, 0x0000, 0x0000, + 0x0000, 0x0070, 0xffc0, 0x07c0, 0x03ff, 0xffc0, 0x07e0, 0x0000, 0x0000, + 0x0000, 0x0038, 0xffc0, 0x0ff0, 0x07ff, 0xff80, 0x0f80, 0x0000, 0x0000, + 0x0000, 0x001c, 0x7fc0, 0x0fff, 0x07ff, 0xff00, 0x3f00, 0x0000, 0x0000, + 0x0000, 0x0000, 0x3fc0, 0x0fff, 0xffff, 0xfe00, 0x7c00, 0x0000, 0x0000, + 0x0000, 0x0000, 0x7fe0, 0x1fff, 0xfcff, 0xfc00, 0xf800, 0x0000, 0x0000, + 0x0000, 0x0000, 0x13e0, 0x1fff, 0xf83f, 0xf003, 0xe000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0460, 0x1fff, 0xe007, 0xe007, 0x8000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0110, 0x1fff, 0xc000, 0xc01f, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x004e, 0x3fff, 0x8003, 0xf03c, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0017, 0xfffe, 0x000f, 0xfff8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0005, 0xc3fc, 0x007f, 0xff80, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0xc038, 0x03ff, 0xfe00, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x87f8, 0x0fff, 0xe000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x07ff, 0x7ffe, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0007, 0x8fe0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000 +} + +--local SCREEN_W = 336 +--local SCREEN_H = 216 +local SCREEN_W = 320 +local SCREEN_H = 200 +local function l(x1, y1, x2, y2, c) + raster.drawLine(x1-8, y1-8, x2-8, y2-8, c) +end +local function g(x, y) + return raster.get(x-8, y-8) +end +local function s(x, y, c) + raster.set(x-8, y-8, c) +end +local BALL_W = 144 +local BALL_H = 100 +local ONE_PLANE_LEN = BALL_W * BALL_H / 16 + +local function ball() + local color_cycle = 2 + local pos = { x = 0.0, y = 0.0 } + local scroll = { x = -1, y = -1 } + local pixel_index = {} + local is_shadow = {} + local this = {} + function this.pos() + return -pos.x + 77, -pos.y + end + function this.step() + pos.x = pos.x + scroll.x + if pos.x <= -95 or pos.x >= 95 then scroll.x = -scroll.x end + local adj = scroll.y + if pos.y > -10.0 then adj = adj * 1.0 + elseif pos.y > -30.0 then adj = adj * 2.0 + elseif pos.y > -60.0 then adj = adj * 3.0 + else adj = adj * 4.0 end + pos.y = pos.y + adj + if pos.y <= -100 or pos.y >= 0 then scroll.y = -scroll.y end + end + local function orderbits(value) + local result = 0 + for i = 0, 15 do + if (value >> i) & 1 == 1 then + result = result | (1 << (15 - i)) + end + end + return result + end + function this.decode() + for y = 0, BALL_H - 1 do + for x = 0, BALL_W - 1 do + local pos = y * BALL_W + x + local offset = pos // 16 + local bitpos = pos % 16 + + local value = 0 + for plane = 0, 3 do + local word = orderbits(ball_bitplanes[offset + plane * ONE_PLANE_LEN + 1]) + if (word & (1 << bitpos)) ~= 0 then + value = value | (1 << plane) + end + end + + if (value == 1) then + is_shadow[pos + 1] = true + pixel_index[pos + 1] = 0 + else + is_shadow[pos + 1] = false + pixel_index[pos + 1] = value + end + end + end + end + function this.cycle_palette() + if scroll.x > 0 then color_cycle = color_cycle - 1 + else color_cycle = color_cycle + 1 end + + if color_cycle == -1 then color_cycle = 13 + elseif color_cycle == 14 then color_cycle = 0 end + + for i = 0, 6 do + if color_cycle + i < 14 then + color_table[color_cycle + i + 3] = 0xFFFFFF + color_table[color_cycle + i + 19] = 0xFFFFFF + else + color_table[color_cycle + i - 11] = 0xFFFFFF + color_table[color_cycle + i + 5] = 0xFFFFFF + end + end + for i = 7, 13 do + if color_cycle + i < 14 then + color_table[color_cycle + i + 3] = 0xFF0000 + color_table[color_cycle + i + 19] = 0xFF0000 + else + color_table[color_cycle + i - 11] = 0xFF0000 + color_table[color_cycle + i + 5] = 0xFF0000 + end + end + if scroll.x > -1 then + color_table[color_cycle + 3] = 0xFFDDDD + color_table[color_cycle + 19] = 0xFFDDDD + elseif color_cycle + 6 < 14 then + color_table[color_cycle + 9] = 0xFFDDDD + color_table[color_cycle + 25] = 0xFFDDDD + else + color_table[color_cycle - 5] = 0xFFDDDD + color_table[color_cycle + 11] = 0xFFDDDD + end + end + function this.draw(x, y, shadow) + for oy = 0, BALL_H - 1 do + for ox = 0, BALL_W - 1 do + local pos = oy * BALL_W + ox + 1 + if shadow then + if is_shadow[pos] then + local c = g(ox+x, oy+y) + if c == 0xAAAAAA then s(ox+x, oy+y, 0x666666) end + end + else + local idx = pixel_index[pos] + if idx ~= 0 then + local c = color_table[idx + 1] + s(ox+x, oy+y, c) + end + end + end + end + end + return this +end + +function draw_background() + raster.clear() + + local lc = color_table[17] + + local k = 20 + for j = 48, 300, 16 do + l(j, 0, j, 192, lc) + l(j, 192, k, 215, lc) + k = k + 20 + end + for j = 0, 200, 16 do + l(48, j, 288, j, lc) + end + l(45, 194, 291, 194, lc) + l(41, 197, 295, 197, lc) + l(37, 201, 300, 201, lc) + l(30, 207, 308, 207, lc) + l(20, 215, 319, 215, lc) +end + +local b = ball() +b.decode() +raster.init(SCREEN_W/2, SCREEN_H/4, color_table[1]) +local i = 0 +while true do + i = i + 1 + draw_background() + b.cycle_palette() + b.step() + local x, y = b.pos() + b.draw(x, y, true) + b.draw(x, y) + raster.update() + + if event.pull("key_down", 0.01) then + break + end +end + +raster.free() +terminal.clear() \ No newline at end of file diff --git a/lib/event.lua b/lib/event.lua index 61b1399..81b3af6 100644 --- a/lib/event.lua +++ b/lib/event.lua @@ -47,15 +47,13 @@ function event.pull(...) end end - -- Check if we've timed out - if timeout and computer.uptime() >= startTime + timeout then - return nil -- Timed out, return nil + if timeout ~= nil and computer.uptime() >= startTime + timeout then + return nil end - -- Yield to allow other processes to run and more events to be added - if timeout and timeout > 0 then + if timeout == nil then coroutine.yield() - elseif not timeout then + elseif timeout > 0 then coroutine.yield() end end diff --git a/lib/raster.lua b/lib/raster.lua index cff96a8..9d18975 100644 --- a/lib/raster.lua +++ b/lib/raster.lua @@ -39,7 +39,7 @@ function raster.init(width, height, bgcolor) raster.charHeight = height width, height = raster.units.charToBraille(width, height) - + bgcolor = bgcolor or raster.defaultBackgroundColor if bgcolor~=0 then for i=1,width*height do @@ -204,29 +204,29 @@ end function raster.drawLine(x1, y1, x2, y2, color) x1, y1, x2, y2 = math.floor(x1), math.floor(y1), math.floor(x2), math.floor(y2) - + local dx = math.abs(x2 - x1) local dy = math.abs(y2 - y1) - + local sx = x1 < x2 and 1 or -1 local sy = y1 < y2 and 1 or -1 - + local err = dx - dy - + while true do raster.set(x1, y1, color) - + if x1 == x2 and y1 == y2 then break end - + local e2 = 2 * err - + if e2 > -dy then err = err - dy x1 = x1 + sx end - + if e2 < dx then err = err + dx y1 = y1 + sy @@ -266,7 +266,7 @@ function raster.drawCircle(xc, yc, radius, color) local x = 0 local y = radius local d = 3 - 2 * radius - + while y >= x do -- Draw 8 symmetric points raster.set(xc + x, yc + y, color) @@ -277,7 +277,7 @@ function raster.drawCircle(xc, yc, radius, color) raster.set(xc - y, yc + x, color) raster.set(xc + y, yc - x, color) raster.set(xc - y, yc - x, color) - + if d < 0 then d = d + 4 * x + 6 else @@ -291,22 +291,22 @@ end function raster.drawEllipse(x1, y1, x2, y2, color) if x1 > x2 then x1, x2 = x2, x1 end if y1 > y2 then y1, y2 = y2, y1 end - + local xc = math.floor((x1 + x2) / 2) local yc = math.floor((y1 + y2) / 2) - + local a = math.floor((x2 - x1) / 2) local b = math.floor((y2 - y1) / 2) - + if a <= 0 or b <= 0 then return end - + if a == b then raster.drawCircle(xc, yc, a, color) return end - + if a <= 1 and b <= 1 then raster.set(xc, yc, color) return @@ -321,21 +321,21 @@ function raster.drawEllipse(x1, y1, x2, y2, color) end return end - + local x = 0 local y = b local a2 = a * a local b2 = b * b - + local d1 = b2 - (a2 * b) + (0.25 * a2) local dx = 2 * b2 * x local dy = 2 * a2 * y - + while dx < dy do raster.set(xc + x, yc + y, color) raster.set(xc - x, yc + y, color) raster.set(xc + x, yc - y, color) - + if d1 < 0 then x = x + 1 dx = dx + (2 * b2) @@ -348,15 +348,15 @@ function raster.drawEllipse(x1, y1, x2, y2, color) d1 = d1 + dx - dy + b2 end end - + local d2 = b2 * (x + 0.5) * (x + 0.5) + a2 * (y - 1) * (y - 1) - a2 * b2 - + while y >= 0 do raster.set(xc + x, yc + y, color) raster.set(xc - x, yc + y, color) raster.set(xc + x, yc - y, color) raster.set(xc - x, yc - y, color) - + if d2 > 0 then y = y - 1 dy = dy - (2 * a2) @@ -374,17 +374,17 @@ end function raster.fillCircle(x, y, r, color) x, y = math.floor(x + 0.5), math.floor(y + 0.5) r = math.floor(r + 0.5) - + if r <= 0 then return end - + local minX, maxX = x - r, x + r local minY, maxY = y - r, y + r - + for py = minY, maxY do for px = minX, maxX do local dx, dy = px - x, py - y local distSquared = dx*dx + dy*dy - + if distSquared <= r*r then raster.set(px, py, color) end @@ -395,33 +395,33 @@ end function raster.fillEllipse(x1, y1, x2, y2, color) local centerX = (x1 + x2) / 2 local centerY = (y1 + y2) / 2 - + local a = math.abs(x2 - x1) / 2 local b = math.abs(y2 - y1) / 2 - + centerX = math.floor(centerX + 0.5) centerY = math.floor(centerY + 0.5) a = math.floor(a + 0.5) b = math.floor(b + 0.5) - + if a <= 0 or b <= 0 then return end - + if a == b then raster.fillCircle(centerX, centerY, a, color) return end - + local minX = centerX - a local maxX = centerX + a local minY = centerY - b local maxY = centerY + b - + for y = minY, maxY do for x = minX, maxX do local dx = x - centerX local dy = y - centerY local value = (dx*dx)/(a*a) + (dy*dy)/(b*b) - + if value <= 1 then raster.set(x, y, color) end From 166744a828b9d02b6cc5a53c5d1e08dc502a42e5 Mon Sep 17 00:00:00 2001 From: tema5002 Date: Sun, 21 Jun 2026 17:12:35 +0000 Subject: [PATCH 2/6] I am a moron --- halyde/kernel/modules/terminal.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/halyde/kernel/modules/terminal.lua b/halyde/kernel/modules/terminal.lua index 28c6918..81e986d 100644 --- a/halyde/kernel/modules/terminal.lua +++ b/halyde/kernel/modules/terminal.lua @@ -505,10 +505,10 @@ function module.init() if byte >= 0x20 and byte <= 0x7F then table.insert(writeBuf, string.char(byte)) cursor.x = cursor.x + 1 - check_wrap_and_scroll() - if cursor.y ~= writeBufY or #writeBuf >= 32 then + if cursor.x > width then _PUBLIC.terminal.flush() end + check_wrap_and_scroll() elseif byte >= 0xC2 and byte <= 0xDF then current_codepoint = (byte & 0x1F) bytes_remaining = 1 @@ -524,10 +524,10 @@ function module.init() if bytes_remaining == 0 then table.insert(writeBuf, utf8.char(current_codepoint)) cursor.x = cursor.x + 1 - check_wrap_and_scroll() - if cursor.y ~= writeBufY or #writeBuf >= 32 then + if cursor.x > width then _PUBLIC.terminal.flush() end + check_wrap_and_scroll() current_codepoint = 0 end else From b3a2ed22588236ed2ac10f8a66de0f4073a86e61 Mon Sep 17 00:00:00 2001 From: tema5002 Date: Sun, 21 Jun 2026 17:17:35 +0000 Subject: [PATCH 3/6] Update halyde/kernel/modules/terminal.lua --- halyde/kernel/modules/terminal.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/halyde/kernel/modules/terminal.lua b/halyde/kernel/modules/terminal.lua index 81e986d..5fd5386 100644 --- a/halyde/kernel/modules/terminal.lua +++ b/halyde/kernel/modules/terminal.lua @@ -508,7 +508,7 @@ function module.init() if cursor.x > width then _PUBLIC.terminal.flush() end - check_wrap_and_scroll() + check_wrap_and_scroll() elseif byte >= 0xC2 and byte <= 0xDF then current_codepoint = (byte & 0x1F) bytes_remaining = 1 @@ -589,8 +589,6 @@ function module.init() local text = options.defaultText or "" - _G._PUBLIC.terminal.flush() - local historyIdx if options.readHistoryType then if not readHistory[options.readHistoryType] then @@ -609,6 +607,7 @@ function module.init() local cur = unicode.len(text)+1 if options.prefix then _PUBLIC.terminal.write(options.prefix) end + _G._PUBLIC.terminal.flush() local startX, startY = cursor.x, cursor.y local fg, bg = gpu.getForeground(), gpu.getBackground() local cursorBlink = true From a9ecbccf2e2da4cfb1e778816424c3777bfff0ce Mon Sep 17 00:00:00 2001 From: tema5002 Date: Mon, 22 Jun 2026 22:10:48 +0300 Subject: [PATCH 4/6] The last cutting-edge commit out of the lot making the terminal a lot nicer --- halyde/kernel/modules/terminal.lua | 800 +++++++++++++++-------------- 1 file changed, 409 insertions(+), 391 deletions(-) diff --git a/halyde/kernel/modules/terminal.lua b/halyde/kernel/modules/terminal.lua index 5fd5386..1651087 100644 --- a/halyde/kernel/modules/terminal.lua +++ b/halyde/kernel/modules/terminal.lua @@ -22,21 +22,21 @@ function module.init() local readHistory = {} function _PUBLIC.terminal.getHistory(id) - checkArg(1,id,"string") + checkArg(1, id, "string") return table.copy(readHistory[id]) end - function _PUBLIC.terminal.setHistory(id,hist) - checkArg(1,id,"string") - checkArg(2,hist,"table") - for i=1,#hist do - hist[i]=tostring(hist[i]) + function _PUBLIC.terminal.setHistory(id, hist) + checkArg(1, id, "string") + checkArg(2, hist, "table") + for i = 1, #hist do + hist[i] = tostring(hist[i]) end - readHistory[id]=hist + readHistory[id] = hist end - function _PUBLIC.terminal.addToHistory(id,hist) - checkArg(1,id,"string") - checkArg(2,hist,"string") - table.insert(readHistory[id],hist) + function _PUBLIC.terminal.addToHistory(id, hist) + checkArg(1, id, "string") + checkArg(2, hist, "string") + table.insert(readHistory[id], hist) end local function getColorPalette(depth) @@ -66,7 +66,7 @@ function module.init() end if depth == 4 then return { - -- Closest colors to the 4 bit OC pallete + -- Closest colors to the 4 bit OC palette -- Better than outright failure ["dark"] = { [0] = 0x000000, -- black @@ -146,27 +146,20 @@ function module.init() local cursor = { x = 1, y = 1, X = nil, Y = nil } -- X and Y are managed by ESC s and ESC u local printState = 0 -- 0:none 1:in ESC 2:in CSI - local color = { - FG = ANSIColorPalette["bright"][7], BG = ANSIColorPalette["dark"][0], - fg = nil, bg = nil, reverse = false - } - color.fg = color.FG - color.bg = color.BG + local DEFAULT_FG = ANSIColorPalette["bright"][7] -- TODO make configurable + local DEFAULT_BG = ANSIColorPalette["dark"][0] + local fg = DEFAULT_FG + local bg = DEFAULT_BG + local gpuFg = nil + local gpuBg = nil + local reverse = false local current_codepoint = 0 local bytes_remaining = 0 local seq = {} - local writeBuf = {} - - local function update_gpu_colors() - if color.reverse then - gpu.setForeground(color.bg) - gpu.setBackground(color.fg) - else - gpu.setForeground(color.fg) - gpu.setBackground(color.bg) - end - end + local writeBuf = "" + local bufStartX = 1 + local bufStartY = 1 local width, height = gpu.getResolution() @@ -174,29 +167,60 @@ function module.init() return width, height end - gpu.setForeground(color.fg) - gpu.setBackground(color.bg) - - local function scroll() - if gpu.copy(1, 2, width, height - 1, 0, -1) then - gpu.setForeground(color.FG) - gpu.setBackground(color.BG) - gpu.fill(1, height, width, 1, " ") - gpu.setForeground(color.fg) - gpu.setBackground(color.bg) - cursor.y = height + local function update_gpu_colors() + if reverse then + if gpuBg ~= fg then gpu.setBackground(fg) gpuBg = fg end + if gpuFg ~= bg then gpu.setForeground(bg) gpuFg = bg end + else + if gpuBg ~= bg then gpu.setBackground(bg) gpuBg = bg end + if gpuFg ~= fg then gpu.setForeground(fg) gpuFg = fg end end end + local function scroll(n) + if n <= 0 then return end + if writeBuf ~= "" then + update_gpu_colors() + gpu.set(bufStartX, bufStartY, writeBuf) + writeBuf = "" + end + local keep = height - n + if keep > 0 then + gpu.copy(1, n + 1, width, keep, 0, -n) + end + if gpuBg ~= bg then + gpu.setBackground(bg) + gpuBg = bg + end + gpu.fill(1, keep + 1, width, n, " ") + cursor.y = cursor.y - n + if cursor.y > height then cursor.y = height end + if cursor.y < 1 then cursor.y = 1 end + end + local function check_wrap_and_scroll() if cursor.x > width then cursor.x = 1 cursor.y = cursor.y + 1 end + scroll(cursor.y - height) + end - while cursor.y > height do - scroll() + -- must be called before any operation that moves the cursor or changes colors!!!!!!! + local function flush() + if writeBuf == "" then return end + update_gpu_colors() + gpu.set(bufStartX, bufStartY, writeBuf) + writeBuf = "" + end + + local function buf_append(s, len) + if writeBuf == "" then + bufStartX = cursor.x + bufStartY = cursor.y end + writeBuf = writeBuf .. s + cursor.x = cursor.x + len end local function exec_csi() @@ -226,117 +250,84 @@ function module.init() end end - local function get_param(idx, default) - if idx <= #params and params[idx] ~= nil then - return params[idx] - end - return default - end - - if op == 0x48 or op == 0x66 then - local row = get_param(1, 1) - local col = get_param(2, 1) - cursor.y = row - cursor.x = col - if cursor.x < 1 then cursor.x = 1 end - if cursor.y < 1 then cursor.y = 1 end - if cursor.x > width then cursor.x = width end - if cursor.y > height then cursor.y = height end - return - end - + -- TODO maybe use a lookup table like this? + -- local thing = things[op] + -- if thing ~= nil then thing() end if op == 0x41 then - local n = get_param(1, 1) - cursor.y = cursor.y - n + flush() + cursor.y = cursor.y - (params[1] or 1) if cursor.y < 1 then cursor.y = 1 end - return - end - - if op == 0x42 then - local n = get_param(1, 1) - cursor.y = cursor.y + n + elseif op == 0x42 then + flush() + cursor.y = cursor.y + (params[1] or 1) if cursor.y > height then cursor.y = height end - return - end - - if op == 0x43 then - local n = get_param(1, 1) - cursor.x = cursor.x + n + elseif op == 0x43 then + flush() + cursor.x = cursor.x + (params[1] or 1) if cursor.x > width then cursor.x = width end - return - end - - if op == 0x44 then - local n = get_param(1, 1) - cursor.x = cursor.x - n + elseif op == 0x44 then + flush() + cursor.x = cursor.x - (params[1] or 1) if cursor.x < 1 then cursor.x = 1 end - return - end - - if op == 0x47 then - local col = get_param(1, 1) - cursor.x = col + elseif op == 0x47 or op == 0x60 then + flush() + cursor.x = params[1] or 1 if cursor.x < 1 then cursor.x = 1 end if cursor.x > width then cursor.x = width end - return - end - - if op == 0x4a then - local mode = get_param(1, 0) - + elseif op == 0x48 or op == 0x66 then + flush() + cursor.y = params[1] or 1 + cursor.x = params[2] or 1 + if cursor.x < 1 then cursor.x = 1 end + if cursor.y < 1 then cursor.y = 1 end + if cursor.x > width then cursor.x = width end + if cursor.y > height then cursor.y = height end + elseif op == 0x4a then + flush() + local mode = params[1] or 0 + update_gpu_colors() if mode == 0 then - update_gpu_colors() - gpu.fill(cursor.x, cursor.y, width - cursor.x + 1, height - cursor.y + 1, " ") + gpu.fill(cursor.x, cursor.y, width - cursor.x + 1, 1, " ") + if cursor.y < height then + gpu.fill(1, cursor.y + 1, width, height - cursor.y, " ") + end elseif mode == 1 then - update_gpu_colors() - gpu.fill(1, 1, cursor.x, cursor.y, " ") + if cursor.y > 1 then + gpu.fill(1, 1, width, cursor.y - 1, " ") + end + gpu.fill(1, cursor.y, cursor.x, 1, " ") elseif mode == 2 then - update_gpu_colors() gpu.fill(1, 1, width, height, " ") cursor.x = 1 cursor.y = 1 end - return - end - - if op == 0x4b then - local mode = get_param(1, 0) - + elseif op == 0x4b then + flush() + local mode = params[1] or 0 + update_gpu_colors() if mode == 0 then - update_gpu_colors() gpu.fill(cursor.x, cursor.y, width - cursor.x + 1, 1, " ") elseif mode == 1 then - update_gpu_colors() gpu.fill(1, cursor.y, cursor.x, 1, " ") elseif mode == 2 then - update_gpu_colors() gpu.fill(1, cursor.y, width, 1, " ") end - return - end - - if op == 0x60 then - local col = get_param(1, 1) - cursor.x = col - if cursor.x < 1 then cursor.x = 1 end - if cursor.x > width then cursor.x = width end - return - end - - if op == 0x64 then - local row = get_param(1, 1) - cursor.y = row - if cursor.y < 1 then cursor.y = 1 end - if cursor.y > height then cursor.y = height end - return - end - - if op == 0x6d then + elseif op == 0x64 then + flush() + cursor.y = params[1] or 1 + if cursor.y < 1 then + cursor.y = 1 + end + if cursor.y > height then + cursor.y = height + end + elseif op == 0x6d then + flush() local j = 1 local function parse_extended_color() - local mode = get_param(j + 1, -1) + local mode = params[j + 1] or -1 if mode == 5 then - local idx = get_param(j + 2, 0) + local idx = params[j + 2] or 0 j = j + 2 if idx < 8 then return ANSIColorPalette["dark"][idx] @@ -353,9 +344,9 @@ function module.init() return (v << 16) | (v << 8) | v end elseif mode == 2 then - local r = get_param(j + 2, 0) - local g = get_param(j + 3, 0) - local b = get_param(j + 4, 0) + local r = params[j + 2] or 0 + local g = params[j + 3] or 0 + local b = params[j + 4] or 0 j = j + 4 return (r << 16) | (g << 8) | b end @@ -363,10 +354,9 @@ function module.init() end if #params == 0 then - color.reverse = false - color.fg = color.FG - color.bg = color.BG - update_gpu_colors() + reverse = false + fg = DEFAULT_FG + bg = DEFAULT_BG return end @@ -374,192 +364,207 @@ function module.init() local p = params[j] or 0 if p == 0 then - color.reverse = false - color.fg = color.FG - color.bg = color.BG - elseif p == 1 then - elseif p == 2 then - elseif p == 3 then - elseif p == 4 then - elseif p == 5 or p == 6 then + reverse = false + fg = DEFAULT_FG + bg = DEFAULT_BG + --elseif p == 1 then + --elseif p == 2 then + --elseif p == 3 then + --elseif p == 4 then + --elseif p == 5 or p == 6 then elseif p == 7 then - color.reverse = true + reverse = true elseif p == 8 then - color.fg = color.bg - elseif p == 9 then - elseif p == 21 then - elseif p == 22 then - elseif p == 23 then - elseif p == 24 then - elseif p == 25 then + fg = bg + --elseif p == 9 then + --elseif p == 21 then + --elseif p == 22 then + --elseif p == 23 then + --elseif p == 24 then + --elseif p == 25 then elseif p == 27 then - color.reverse = false + reverse = false elseif p == 28 then - color.fg = color.FG - elseif p == 29 then + fg = DEFAULT_FG + --elseif p == 29 then elseif 30 <= p and p <= 37 then - color.fg = ANSIColorPalette["dark"][p - 30] + fg = ANSIColorPalette["dark"][p - 30] elseif p == 38 then local c = parse_extended_color() - if c then color.fg = c end + if c then + fg = c + end elseif p == 39 then - color.fg = color.FG + fg = DEFAULT_FG elseif 40 <= p and p <= 47 then - color.bg = ANSIColorPalette["dark"][p - 40] + bg = ANSIColorPalette["dark"][p - 40] elseif p == 48 then local c = parse_extended_color() - if c then color.bg = c end + if c then + bg = c + end elseif p == 49 then - color.bg = color.BG - elseif p == 58 then - parse_extended_color() - elseif p == 59 then + bg = DEFAULT_BG elseif 90 <= p and p <= 97 then - color.fg = ANSIColorPalette["bright"][p - 90] + fg = ANSIColorPalette["bright"][p - 90] elseif 100 <= p and p <= 107 then - color.bg = ANSIColorPalette["bright"][p - 100] + bg = ANSIColorPalette["bright"][p - 100] end j = j + 1 end - update_gpu_colors() - return - end - - if op == 0x73 then + elseif op == 0x73 then + flush() cursor.X = cursor.x cursor.Y = cursor.y - return - end - - if op == 0x75 then + elseif op == 0x75 then + flush() if cursor.X and cursor.Y then cursor.x = cursor.X cursor.y = cursor.Y - if cursor.x < 1 then cursor.x = 1 end - if cursor.y < 1 then cursor.y = 1 end - if cursor.x > width then cursor.x = width end - if cursor.y > height then cursor.y = height end - end - return - end - end - - function _G._PUBLIC.terminal.writec(byte) - if byte == 0x1b then - _PUBLIC.terminal.flush() - printState = 1 - seq = {} - return - end - - if printState == 1 then - if byte == 0x5b then - printState = 2 - else - printState = 0 - end - return - end - - if printState == 2 then - table.insert(seq, byte) - if 0x40 <= byte and byte <= 0x7e then - exec_csi() - printState = 0 - seq = {} - end - return - end - - if byte == 0xa then - _PUBLIC.terminal.flush() - cursor.y = cursor.y + 1 - cursor.x = 1 - check_wrap_and_scroll() - return - end - - if byte == 0xd then - _PUBLIC.terminal.flush() - cursor.x = 1 - return - end - - if byte == 0x8 then - _PUBLIC.terminal.flush() - if cursor.x > 1 then - cursor.x = cursor.x - 1 - end - return - end - - if byte == 0x9 then - _PUBLIC.terminal.flush() - cursor.x = ((cursor.x - 1) // 8) * 8 + 9 - if cursor.x < 1 then cursor.x = 1 end - if cursor.x > width then cursor.x = width end - return - end - - if byte >= 0x20 and byte <= 0x7F then - table.insert(writeBuf, string.char(byte)) - cursor.x = cursor.x + 1 - if cursor.x > width then - _PUBLIC.terminal.flush() - end - check_wrap_and_scroll() - elseif byte >= 0xC2 and byte <= 0xDF then - current_codepoint = (byte & 0x1F) - bytes_remaining = 1 - elseif byte >= 0xE0 and byte <= 0xEF then - current_codepoint = (byte & 0x0F) - bytes_remaining = 2 - elseif byte >= 0xF0 and byte <= 0xF7 then - current_codepoint = (byte & 0x07) - bytes_remaining = 3 - elseif byte >= 0x80 and byte <= 0xBF and bytes_remaining > 0 then - current_codepoint = (current_codepoint << 6) | (byte & 0x3F) - bytes_remaining = bytes_remaining - 1 - if bytes_remaining == 0 then - table.insert(writeBuf, utf8.char(current_codepoint)) - cursor.x = cursor.x + 1 + if cursor.x < 1 then + cursor.x = 1 + end + if cursor.y < 1 then + cursor.y = 1 + end if cursor.x > width then - _PUBLIC.terminal.flush() + cursor.x = width + end + if cursor.y > height then + cursor.y = height end - check_wrap_and_scroll() - current_codepoint = 0 end - else - current_codepoint = 0 - bytes_remaining = 0 end end function _G._PUBLIC.terminal.write(text) text = tostring(text) - for i = 1, #text do - _PUBLIC.terminal.writec(string.byte(text, i)) + local len = #text + local i = 1 + + while i <= len do + local byte = string.byte(text, i) + + if byte == 0x1b then + printState = 1 + seq = {} + i = i + 1 + elseif printState == 1 then + printState = byte == 0x5b and 2 or 0 + i = i + 1 + elseif printState == 2 then + table.insert(seq, byte) + if 0x40 <= byte and byte <= 0x7e then + exec_csi() + printState = 0 + seq = {} + end + i = i + 1 + elseif byte == 0xa then + flush() + cursor.y = cursor.y + 1 + cursor.x = 1 + check_wrap_and_scroll() + bufStartX = cursor.x + bufStartY = cursor.y + i = i + 1 + elseif byte == 0xd then + flush() + cursor.x = 1 + bufStartX = 1 + bufStartY = cursor.y + i = i + 1 + elseif byte == 0x8 then + flush() + if cursor.x > 1 then cursor.x = cursor.x - 1 end + i = i + 1 + elseif byte == 0x9 then + flush() + cursor.x = ((cursor.x - 1) // 8) * 8 + 9 + if cursor.x > width then cursor.x = width end + i = i + 1 + elseif byte >= 0x20 and byte <= 0x7E then + local j = i + 1 + while j <= len do + local b = string.byte(text, j) + if b < 0x20 or b > 0x7E then break end + j = j + 1 + end + local runLen = j - i + local space = width - cursor.x + 1 + + if runLen <= space then + buf_append(text:sub(i, j - 1), runLen) + if cursor.x > width then + flush() + cursor.x = 1 + cursor.y = cursor.y + 1 + check_wrap_and_scroll() + bufStartX = cursor.x + bufStartY = cursor.y + end + i = j + else + buf_append(text:sub(i, i + space - 1), space) + flush() + cursor.x = 1 + cursor.y = cursor.y + 1 + check_wrap_and_scroll() + bufStartX = cursor.x + bufStartY = cursor.y + i = i + space + end + elseif byte >= 0xC2 and byte <= 0xDF then + current_codepoint = (byte & 0x1F) + bytes_remaining = 1 + i = i + 1 + elseif byte >= 0xE0 and byte <= 0xEF then + current_codepoint = (byte & 0x0F) + bytes_remaining = 2 + i = i + 1 + elseif byte >= 0xF0 and byte <= 0xF7 then + current_codepoint = (byte & 0x07) + bytes_remaining = 3 + i = i + 1 + elseif byte >= 0x80 and byte <= 0xBF and bytes_remaining > 0 then + current_codepoint = (current_codepoint << 6) | (byte & 0x3F) + bytes_remaining = bytes_remaining - 1 + if bytes_remaining == 0 then + buf_append(unicode.char(current_codepoint), 1) + if cursor.x > width then + flush() + cursor.x = 1 + cursor.y = cursor.y + 1 + check_wrap_and_scroll() + bufStartX = cursor.x + bufStartY = cursor.y + end + current_codepoint = 0 + end + i = i + 1 + else + current_codepoint = 0 + bytes_remaining = 0 + i = i + 1 + end end end + function _G._PUBLIC.terminal.flush() + flush() + end + function _G._PUBLIC.terminal.clear() + flush() update_gpu_colors() gpu.fill(1, 1, width, height, " ") - writeBuf = {} cursor.x = 1 cursor.y = 1 end - function _G._PUBLIC.terminal.flush() - if #writeBuf == 0 then return end - update_gpu_colors() - gpu.set(cursor.x - #writeBuf, cursor.y, table.concat(writeBuf)) - writeBuf = {} - end - function _G.print(...) - local args = {...} + local args = { ... } local stringArgs = {} for _, arg in pairs(args) do if type(arg) == "table" then @@ -592,8 +597,8 @@ function module.init() local historyIdx if options.readHistoryType then if not readHistory[options.readHistoryType] then - readHistory[options.readHistoryType] = {text} - elseif readHistory[options.readHistoryType][#readHistory[options.readHistoryType] ] ~= text then + readHistory[options.readHistoryType] = { text } + elseif readHistory[options.readHistoryType][#readHistory[options.readHistoryType]] ~= text then table.insert(readHistory[options.readHistoryType], text) end historyIdx = #readHistory[options.readHistoryType] @@ -602,209 +607,222 @@ function module.init() local function updateHistory() if not options.readHistoryType then return end if historyIdx ~= #readHistory[options.readHistoryType] then return end - readHistory[options.readHistoryType][historyIdx]=text + readHistory[options.readHistoryType][historyIdx] = text end - local cur = unicode.len(text)+1 + local cur = unicode.len(text) + 1 if options.prefix then _PUBLIC.terminal.write(options.prefix) end - _G._PUBLIC.terminal.flush() + flush() local startX, startY = cursor.x, cursor.y - local fg, bg = gpu.getForeground(), gpu.getBackground() local cursorBlink = true + local function checkScroll(y) - for i=1,y-height do - scrollDown() - startY=startY-1 + if y > height then + local n = y - height + scroll(n) + startY = startY - n + y = height end - return math.min(y,height) + return y end + local function set(index, character, invertedColors) -- HACK: Currently, this will uncensor all spaces in the inputted text. - if character==nil or character=="" then return end + if character == nil or character == "" then return end if options.censor then character = character:gsub("[^ ]", options.censor) end if invertedColors then - gpu.setForeground(bg) - gpu.setBackground(fg) + if gpuFg ~= bg then gpu.setForeground(bg); gpuFg = bg end + if gpuBg ~= fg then gpu.setBackground(fg); gpuBg = fg end else - gpu.setForeground(fg) - gpu.setBackground(bg) + if gpuFg ~= fg then gpu.setForeground(fg); gpuFg = fg end + if gpuBg ~= bg then gpu.setBackground(bg); gpuBg = bg end end - index=startX+index-1 - local setX, setY = (index-1)%width+1, startY+((index-1)//width+1)-1 + index = startX + index - 1 + local setX = (index - 1) % width + 1 + local setY = startY + ((index - 1) // width) setY = checkScroll(setY) - gpu.set(setX,setY,unicode.sub(character,1,width-setX+1)) - for i=1,math.ceil((#character+setX-1)/width)+1 do - gpu.set(1,setY+i,unicode.sub(character,2-setX+i*width,width+i*width-setX)) - setY = checkScroll(setY) + local firstLen = width - setX + 1 + gpu.set(setX, setY, unicode.sub(character, 1, firstLen)) + local charLen = unicode.len(character) + if charLen > firstLen then + local offset = firstLen + 1 + while offset <= charLen do + setY = setY + 1 + setY = checkScroll(setY) + local segEnd = offset + width - 1 + gpu.set(1, setY, unicode.sub(character, offset, segEnd)) + offset = segEnd + 1 + end end end - local function strDef(a,b) - if #a==0 then return b end + + local function strDef(a, b) + if #a == 0 then return b end return a end - local function curPos(cur) - return unicode.wlen(unicode.sub(text,1,cur-1))+1 + local function curPos(c) + return unicode.wlen(unicode.sub(text, 1, c - 1)) + 1 end local function add(chr) - if type(chr)~="string" or #chr==0 then return end - if unicode.len(text)>=options.maxChars then return end - if options.maxChars= options.maxChars then + return + end + if options.maxChars < math.huge then + chr = unicode.sub(chr, 1, options.maxChars - unicode.len(text)) + end + text = unicode.sub(text, 1, cur - 1) .. chr .. unicode.sub(text, cur) + set(curPos(cur), chr, false) + cur = math.min(cur + unicode.len(chr), options.maxChars + 1) + set(curPos(cur), strDef(unicode.sub(text, cur, cur), " "), true) cursorBlink = true - set(curPos(cur+1),unicode.sub(text,cur+1),false) + set(curPos(cur + 1), unicode.sub(text, cur + 1), false) end local function moveCur(dir) - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),false) - cur=math.max(math.min(cur+dir,unicode.len(text)+1),1) - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true) + set(curPos(cur), strDef(unicode.sub(text, cur, cur), " "), false) + cur = math.max(math.min(cur + dir, unicode.len(text) + 1), 1) + set(curPos(cur), strDef(unicode.sub(text, cur, cur), " "), true) cursorBlink = true end local function isLetter(chr) - return not string.find("\x09 :@-./_~?&=%+#",chr,1,true) + return not string.find("\x09 :@-./_~?&=%+#", chr, 1, true) end - local function nextCur(dir,chr,icur) - if icur==nil then icur=cur end - local next = math.max(math.min(icur+dir,unicode.len(text)+1),1) - if chr then return unicode.sub(text,next,next) end + local function nextCur(dir, chr, icur) + if icur == nil then icur = cur end + local next = math.max(math.min(icur + dir, unicode.len(text) + 1), 1) + if chr then return unicode.sub(text, next, next) end return next end local function curAfterWord(dir) local ncur = cur - while nextCur(dir,false,ncur)~=ncur and isLetter(nextCur(dir,true,ncur))==(dir==1) do - ncur=nextCur(dir,false,ncur) + while nextCur(dir, false, ncur) ~= ncur and isLetter(nextCur(dir, true, ncur)) == (dir == 1) do + ncur = nextCur(dir, false, ncur) end - while nextCur(dir,false,ncur)~=ncur and isLetter(nextCur(dir,true,ncur))==(dir==-1) do - ncur=nextCur(dir,false,ncur) + while nextCur(dir, false, ncur) ~= ncur and isLetter(nextCur(dir, true, ncur)) == (dir == -1) do + ncur = nextCur(dir, false, ncur) end return ncur end local function moveWord(dir) - if nextCur(dir)==cur then return end - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),false) - cur=curAfterWord(dir) - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true) + if nextCur(dir) == cur then return end + set(curPos(cur), strDef(unicode.sub(text, cur, cur), " "), false) + cur = curAfterWord(dir) + set(curPos(cur), strDef(unicode.sub(text, cur, cur), " "), true) cursorBlink = true end local function deleteWord(dir) local after = curAfterWord(dir) local lenb = unicode.wlen(text) - if dir==1 then - text=unicode.sub(text,1,cur-1)..unicode.sub(text,after) - set(curPos(cur+1),unicode.sub(text,cur+1)..string.rep(" ",lenb-unicode.wlen(text)+1),false) - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true) + if dir == 1 then + text = unicode.sub(text, 1, cur - 1) .. unicode.sub(text, after) + set(curPos(cur + 1), unicode.sub(text, cur + 1) .. string.rep(" ", lenb - unicode.wlen(text) + 1), false) + set(curPos(cur), strDef(unicode.sub(text, cur, cur), " "), true) else - text = unicode.sub(text,1,after-1)..unicode.sub(text,cur) - cur=after - set(curPos(cur+1),unicode.sub(text,cur+1)..string.rep(" ",lenb-unicode.wlen(text)+1),false) - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true) + text = unicode.sub(text, 1, after - 1) .. unicode.sub(text, cur) + cur = after + set(curPos(cur + 1), unicode.sub(text, cur + 1) .. string.rep(" ", lenb - unicode.wlen(text) + 1), false) + set(curPos(cur), strDef(unicode.sub(text, cur, cur), " "), true) end updateHistory() cursorBlink = true end local function isLine(chr) - return chr=="\n" or chr=="\r" + return chr == "\n" or chr == "\r" end - --[[ gpu.set(startX,startY,unicode.sub(text,1,width-startX)) - for i=1,(#text+startX)//width-1 do - gpu.set(startX,startY+i,unicode.sub(text,1+i*width,width-startX+i*width)) - end ]] - set(1,text,false) - set(curPos(cur)," ",true) + + set(1, text, false) + set(curPos(cur), " ", true) local function reprint(new) - set(1,new..string.rep(" ",unicode.wlen(text)-unicode.wlen(new)+1),false) - cur=unicode.len(new)+1 - text=new - set(curPos(cur)," ",true) + set(1, new .. string.rep(" ", unicode.wlen(text) - unicode.wlen(new) + 1), false) + cur = unicode.len(new) + 1 + text = new + set(curPos(cur), " ", true) end - while true do - local args = {event.pull("key_down", "clipboard", 0.5)} + local args = { event.pull("key_down", "clipboard", 0.5) } local ctrlDown = _PUBLIC.keyboard.getCtrlDown() if args and args[1] == "key_down" and args[4] then local key = _PUBLIC.keyboard.keys[args[4]] - if key=="up" and options.readHistoryType then - historyIdx=math.max(historyIdx-1,1) + if key == "up" and options.readHistoryType then + historyIdx = math.max(historyIdx - 1, 1) reprint(readHistory[options.readHistoryType][historyIdx]) - elseif key=="down" and options.readHistoryType then - historyIdx=math.min(historyIdx+1,#readHistory[options.readHistoryType]) + elseif key == "down" and options.readHistoryType then + historyIdx = math.min(historyIdx + 1, #readHistory[options.readHistoryType]) reprint(readHistory[options.readHistoryType][historyIdx]) - elseif key=="left" and ctrlDown then + elseif key == "left" and ctrlDown then moveWord(-1) - elseif key=="right" and ctrlDown then + elseif key == "right" and ctrlDown then moveWord(1) - elseif key=="left" then + elseif key == "left" then moveCur(-1) - elseif key=="right" then + elseif key == "right" then moveCur(1) - elseif key=="home" then + elseif key == "home" then moveCur(-math.huge) - elseif key=="end" then + elseif key == "end" then moveCur(math.huge) - elseif key=="back" and ctrlDown then + elseif key == "back" and ctrlDown then deleteWord(-1) - elseif key=="delete" and ctrlDown then + elseif key == "delete" and ctrlDown then deleteWord(1) - elseif key=="back" and cur>1 then - text=unicode.sub(text,1,cur-2)..unicode.sub(text,cur) - cur=cur-1 - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true) + elseif key == "back" and cur > 1 then + text = unicode.sub(text, 1, cur - 2) .. unicode.sub(text, cur) + cur = cur - 1 + set(curPos(cur), strDef(unicode.sub(text, cur, cur), " "), true) cursorBlink = true - set(curPos(cur)+1,unicode.sub(text,cur+1).." ",false) + set(curPos(cur) + 1, unicode.sub(text, cur + 1) .. " ", false) updateHistory() - elseif key=="delete" then - text = unicode.sub(text,1,cur-1)..unicode.sub(text,cur+1) - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true) + elseif key == "delete" then + text = unicode.sub(text, 1, cur - 1) .. unicode.sub(text, cur + 1) + set(curPos(cur), strDef(unicode.sub(text, cur, cur), " "), true) cursorBlink = true - if cur<=unicode.len(text) then - set(curPos(cur+1),unicode.sub(text,cur+1).." ",false) + if cur <= unicode.len(text) then + set(curPos(cur + 1), unicode.sub(text, cur + 1) .. " ", false) end updateHistory() - elseif key=="enter" then - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),false) + elseif key == "enter" then + set(curPos(cur), strDef(unicode.sub(text, cur, cur), " "), false) break - elseif not (args[3]<32 or (args[3]>0x7F and args[3]<=0x9F)) then + elseif not (args[3] < 32 or (args[3] > 0x7F and args[3] <= 0x9F)) then add(unicode.char(args[3]) or " ") updateHistory() end - elseif args and args[1]=="clipboard" then + elseif args and args[1] == "clipboard" then local clip = args[3] - if not args[3] then goto continue end - while isLine(unicode.sub(clip,1,1)) do clip=unicode.sub(clip,2) end - while isLine(unicode.sub(clip,-1)) do clip=unicode.sub(clip,1,-2) end + if not clip then goto continue end + while isLine(unicode.sub(clip, 1, 1)) do clip = unicode.sub(clip, 2) end + while isLine(unicode.sub(clip, -1)) do clip = unicode.sub(clip, 1, -2) end add(clip) updateHistory() else - cursorBlink=not cursorBlink - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),cursorBlink) + cursorBlink = not cursorBlink + set(curPos(cur), strDef(unicode.sub(text, cur, cur), " "), cursorBlink) end ::continue:: end if options.readHistoryType then - if readHistory[options.readHistoryType][#readHistory[options.readHistoryType]]=="" then - table.remove(readHistory[options.readHistoryType],#readHistory[options.readHistoryType]) + if readHistory[options.readHistoryType][#readHistory[options.readHistoryType]] == "" then + table.remove(readHistory[options.readHistoryType], #readHistory[options.readHistoryType]) end - if historyIdx<#readHistory[options.readHistoryType] then - -- table.remove(readHistory[options.readHistoryType],historyIdx) - table.insert(readHistory[options.readHistoryType],text) + if historyIdx < #readHistory[options.readHistoryType] then + table.insert(readHistory[options.readHistoryType], text) end while #readHistory[options.readHistoryType] > 50 do table.remove(readHistory[options.readHistoryType], 1) end end - cursor.x=1 - cursor.y=cursor.y+math.ceil((unicode.wlen(text)+startX-1)/width) - if cursor.y>height then scroll() end - + cursor.x = 1 + cursor.y = cursor.y + math.ceil((unicode.wlen(text) + startX - 1) / width) + if cursor.y > height then + scroll(cursor.y - height) + end return text end end From b5c08512ec32f2babb81e4d5dc342a892507cc92 Mon Sep 17 00:00:00 2001 From: mcplayer3 <219271061+mcplayer3@users.noreply.github.com> Date: Sat, 20 Jun 2026 22:19:36 +1000 Subject: [PATCH 5/6] Started to add custom colour palettes I have literally no idea why it wont work but if anyone picks this up you'll know it works when the old Halyde colours show up # Conflicts: # halyde/kernel/modules/terminal.lua --- halyde/config/generate/terminal.json | 1 + halyde/config/terminal.json | 24 +++++++++++++++++++++ halyde/kernel/modules/terminal.lua | 31 +++++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 halyde/config/generate/terminal.json create mode 100644 halyde/config/terminal.json diff --git a/halyde/config/generate/terminal.json b/halyde/config/generate/terminal.json new file mode 100644 index 0000000..2d43851 --- /dev/null +++ b/halyde/config/generate/terminal.json @@ -0,0 +1 @@ +{"palette":{"dark":{"0":"171421","1":"c01c28","2":"26a269","3":"a2734c","4":"12488b","5":"a347ba","6":"2aa1b3","7":"d0cfcc"},"bright":{"0":"5e5c64","1":"f66151","2":"33d17a","3":"e9ad0c","4":"2a7bde","5":"c061cb","6":"33c7de","7":"ffffff"}}} \ No newline at end of file diff --git a/halyde/config/terminal.json b/halyde/config/terminal.json new file mode 100644 index 0000000..a647b59 --- /dev/null +++ b/halyde/config/terminal.json @@ -0,0 +1,24 @@ +{ + "palette": { + "dark": { + "0": "0x0f0f0f", + "1": "0xcc2424", + "2": "0x339280", + "3": "0x996d00", + "4": "0x004980", + "5": "0x9949c0", + "6": "0x33b6c0", + "7": "0xc3c3c3" + }, + "bright": { + "0": "0x666d80", + "1": "0xff6d40", + "2": "0x33db80", + "3": "0xffb600", + "4": "0x336dff", + "5": "0xcc6dc0", + "6": "0x33dbc0", + "7": "0xffffff" + } + } +} \ No newline at end of file diff --git a/halyde/kernel/modules/terminal.lua b/halyde/kernel/modules/terminal.lua index 1651087..37415b6 100644 --- a/halyde/kernel/modules/terminal.lua +++ b/halyde/kernel/modules/terminal.lua @@ -15,6 +15,8 @@ function module.init() local serialize = require("serialize") local unicode = require("unicode") local event = require("event") + local fs = require("filesystem") + local json = require("json") local component = require("component") local gpu = component.gpu @@ -39,6 +41,19 @@ function module.init() table.insert(readHistory[id], hist) end + if not fs.exists("/halyde/config/terminal.json") then + fs.copy("/halyde/config/generate/terminal.json", "/halyde/config/terminal.json") + end + local config = "" + local tmpdata + local handle = fs.open("/halyde/config/terminal.json") + repeat + tmpdata = handle:read(math.huge) + config = config .. (tmpdata or "") + until not tmpdata + config = json.decode(config) + require("log").terminal.info("Loaded config file: " .. serialize(config, " ")) + local function getColorPalette(depth) if depth == 1 then return { @@ -91,7 +106,16 @@ function module.init() } end if depth == 8 then - return { + local palette = {["dark"] = {}, ["bright"] = {}} + for i = 0, 7 do + palette["dark"][i] = tonumber(config.palette.dark[tostring(i)], 16) + end + for i = 0, 7 do + palette["bright"][i] = tonumber(config.palette.bright[tostring(i)], 16) + end + require("log").terminal.info("Set color palette: " .. serialize(palette)) + return palette + --[[ return { ["dark"] = { [0] = 0x0f0f0f, -- black [1] = 0xcc2424, -- dark red @@ -112,7 +136,7 @@ function module.init() [6] = 0x33dbc0, -- cyan [7] = 0xffffff -- white } - } + } ]] end --[[ Original color palette: { @@ -146,8 +170,9 @@ function module.init() local cursor = { x = 1, y = 1, X = nil, Y = nil } -- X and Y are managed by ESC s and ESC u local printState = 0 -- 0:none 1:in ESC 2:in CSI - local DEFAULT_FG = ANSIColorPalette["bright"][7] -- TODO make configurable + local DEFAULT_FG = ANSIColorPalette["bright"][7] local DEFAULT_BG = ANSIColorPalette["dark"][0] + require("log").terminal.info("FG and BG: " .. DEFAULT_FG .. " " .. DEFAULT_BG) local fg = DEFAULT_FG local bg = DEFAULT_BG local gpuFg = nil From 260ee180154c3ea0d2b5b84236a25de8b2064cc1 Mon Sep 17 00:00:00 2001 From: tema5002 Date: Wed, 24 Jun 2026 18:26:18 +0300 Subject: [PATCH 6/6] acidentally messed up mcplayers changes :( also fuck you your code sucks ok sorry that was probably rude but still go fu --- halyde/kernel/modules/terminal.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/halyde/kernel/modules/terminal.lua b/halyde/kernel/modules/terminal.lua index 37415b6..b0087eb 100644 --- a/halyde/kernel/modules/terminal.lua +++ b/halyde/kernel/modules/terminal.lua @@ -52,7 +52,7 @@ function module.init() config = config .. (tmpdata or "") until not tmpdata config = json.decode(config) - require("log").terminal.info("Loaded config file: " .. serialize(config, " ")) + require("log").terminal.info("Loaded config file: " .. serialize(config)) local function getColorPalette(depth) if depth == 1 then @@ -108,12 +108,12 @@ function module.init() if depth == 8 then local palette = {["dark"] = {}, ["bright"] = {}} for i = 0, 7 do - palette["dark"][i] = tonumber(config.palette.dark[tostring(i)], 16) + palette["dark"][i] = tonumber(config.palette.dark[tostring(i)]) end for i = 0, 7 do - palette["bright"][i] = tonumber(config.palette.bright[tostring(i)], 16) + palette["bright"][i] = tonumber(config.palette.bright[tostring(i)]) end - require("log").terminal.info("Set color palette: " .. serialize(palette)) + require("log").terminal.info("Set color palette: " .. serialize(palette, nil)) return palette --[[ return { ["dark"] = {