aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2026-04-07 06:14:30 -0400
committerB. Watson <urchlay@slackware.uk>2026-04-07 06:14:38 -0400
commit55220e41c17b8e9dd140f1c770d4885e317d160b (patch)
tree7a66c445b2af2511b8ac7a7ade804718d0379df5
parent965524520500cc6a81dddb95ca427cb1a6830f96 (diff)
downloadfujinet-chat-55220e41c17b8e9dd140f1c770d4885e317d160b.tar.gz
Shave a few bytes from complete.c. 6991 bytes free.
-rw-r--r--doc/dynamic-screens.txt104
-rw-r--r--src/complete.c32
2 files changed, 79 insertions, 57 deletions
diff --git a/doc/dynamic-screens.txt b/doc/dynamic-screens.txt
index 63d2f7c..065f28c 100644
--- a/doc/dynamic-screens.txt
+++ b/doc/dynamic-screens.txt
@@ -102,8 +102,8 @@ Line - 42 bytes of memory that store 40 characters (one GR.0 line) of
(bottom-most points to the 2nd-to-bottom, etc, and the top one in
a screen points to the End Marker). Lines in the free list are also
stored as a linked list, associated with the pool, not any screen.
- A single line cannot cross a 4K boundary, because ANTIC wouldn't
- be able to display it properly.
+ Lines can cross 4K boundaries because they're not directly displayed
+ by ANTIC.
Free Line - a line that isn't being used by any screen. All the
free lines in a pool are a linked list: initializing the pool
@@ -212,42 +212,31 @@ and add the screen's line count to the pool's free line count.
Displaying the screen:
-All the screens share the same display list, which lives in main memory.
-
-The display list has an LMS for every line. The top 23 lines are for
-the screen, the bottom two are the status bar or edit box (always the
-same address; stored in main menory).
-
-The LMS operands get set like so:
+All the screens share the same display list, which lives in main
+memory. This display list is 23 lines of GR.0 text, with an LMS at the
+top, and 2 lines at the bottom which are either the edit box (2 GR.0
+lines) or the status bar (one GR.0 line, one GR.1). The top LMS points
+to a 920-byte (23 line) buffer in main (non-bankable) memory. This
+buffer gets line data copied to it from the screen's lines.
Switch to the screen's bank, then...
-Starting at the screen's 'head' line, and the last LMS (bottom of
-23-line area of the DL), walk the linked list of lines (which are in
-bottom-first order) and the display list (backwards).
-
-If we're scrolled up, just keep walking as many lines as we're
-scrolled up (e.g. 23 for one chunk).
+Starting at the screen's 'head' line, walk the linked list [scroll
+height] times (0 if we're not scrolled up, 23 if we're scrolled up
+one chunk, etc). This brings us to the first line that should be
+displayed.
When we've walked to the first (bottom-most) line to display (which will
-be the 'head' one, if we weren't scrolled back), write its address as
-the current LMS's 16-bit operand, then move on to the next line
-and the next LMS...
-
-Repeat until we hit the end of the screen (the line count), or we
-hit 23 LMSes. At this point, we're done.
+be the 'head' one, if we weren't scrolled back), copy its data to the
+bottom line of the buffer, then move on to the next line of the screen
+and the next line of the buffer.
-Ideally, we'll double-buffer the display list (2 of them, one
-displaying while the other's being rewritten), and switch to the newly
-modified one during the next VBLANK (just update SDLSTL/H and let
-the OS do it). Note that we *don't* have to deal with banking in the
-display list: we can only show one screen at a time, so we don't need
-to bankswitch.
-
-Switching screens, or scrolling back the current screen, will require
-rebuilding the display list. There's no need to rebuild it every
-frame (there'll be a 'dirty' flag that gets set when switching or
-scrolling).
+Repeat until we've done 23 lines. Remember that the last (oldest,
+topmost) line of the screen points to the end marker, which points
+to itself. If we're scrolled up past the last real line, we just get
+copies of the marker line data in the top lines of the buffer (which
+will likely consist of an inverse ~ and 39 blanks, at least during
+testing, so we can see it).
Scrolling the screen up (or down) is just a matter of setting the
screen's scroll height. It should *never* be set higher than the
@@ -258,8 +247,28 @@ one chunk will show lines 1 to 7 at the bottom, then the rest of the
display (the top 2/3s or so) will all be the End Marker line, which
appears blank. At that point, it won't be possible to scroll again:
We're at 23, adding another 23 would exceed the height of 30 lines,
-so the attempt is just ignored).
-
+so the attempt is just ignored.
+
+One wrinkle: while writing new text to the current-displayed screen,
+when scroll height is 0 (we're not scrolled back), both the screen's
+line and the bottom line of the buffer need to get the data written to
+them. This avoids recopying the whole 23-line screen to the buffer on
+every printed character (which would be painfully slow). We won't have
+to recreate the whole buffer until we reach the end of the line.
+
+Refreshing the buffer involves writing 960 bytes to it, so it won't be
+all that fast, but it'll be faster than the current fixed-screen code
+(which scrolls 50 or 73 lines every time, 2000 or 2920 bytes, even in
+screens that aren't currently displayed).
+
+It would potentially be faster to do without the buffer, and just have
+a DL with an LMS for each line... but then we'd be displaying screen
+memory straight from extended banks, and we'd have to have some fancy
+synchronization going on when we're displaying a screen in one bank
+and writing to one that lives in another bank (would have to copy data
+only during the time ANTIC isn't reading screen memory). I may revisit
+this at some point, but using a buffer in main memory is much simpler
+(though it costs about 1K).
Memory layouts for typical machine sizes...
@@ -340,6 +349,13 @@ Milestones: things that will have to happen to make this a reality.
6. Add support for more banks (detection and use).
+TODO: should there be a way to move a screen from one pool to another?
+Imagine, user with 128K opens a bunch of screens, then happens to
+close all the ones in e.g. bank 2. The screens in banks 0/1/3/4 are
+still competing for lines, and we have a whole empty bank we don't
+use until another screen gets opened... it would be an expensive
+operation, and when exactly would we check for it?
+
Rest of the file is C structs that define the stuff above. This is
just hypothetical code (final implementation may look different).
@@ -352,7 +368,8 @@ just hypothetical code (final implementation may look different).
/* with 512K, we get one screen per pool.
with 256K, up to 2 screens per pool.
with 128K, up to 4.
- with 64K, we only get 1 large pool and a couple small ones.
+ with 64K, we only get 1 large pool.
+ with 48K, we only get 1 pool.
*/
#define MAX_SCREENS 32
@@ -369,17 +386,19 @@ typedef struct line_s {
typedef struct {
char title[25];
char status;
- char pool;
+ char pool; /* this could be a pool_t * instead */
int line_count; /* can be above 255 */
- int scrollback_pos;
line_t *line_list; /* head of a linked list */
+ int scrollback_pos; /* also can be >255 */
} screen_t;
screen_t screens[MAX_SCREENS]; /* array is 1023 bytes */
typedef struct {
- u16 start; /* 0 = not in use */
- u16 end;
+ // I don't think we even need these:
+ // u16 start; /* 0 = not in use */
+ // u16 end;
+ char screen_count; /* maybe set to $ff for "not in use" */
u8 bank; /* probably this is just the PORTB value */
line_t *free_list; /* when this is null, the pool has no free lines */
} pool_t;
@@ -389,8 +408,7 @@ typedef struct {
will live in the config segment. */
pool_t pools[MAX_POOLS];
-/* this function is responsible for counting the usable lines (the ones
- that don't cross a 4K boundary) and arranging them in a linked list
- that includes all the usable ones. I suppose it should bzero() the
- memory first. */
+/* this function is responsible for counting the lines and arranging
+ them in a linked list. it zeroes the 40 character bytes in each
+ line and sets the other 2 as a pointer to the next. */
void add_pool(u8 bank, u16 start, u16 end);
diff --git a/src/complete.c b/src/complete.c
index e76def1..fa3a240 100644
--- a/src/complete.c
+++ b/src/complete.c
@@ -54,12 +54,16 @@ char match(const char *p, const char *q) {
len = strlen(p);
if(!len) return 0;
+ return strneq_i(p, q, len);
+
+ /*
while(len--) {
if(lcase(*p) != lcase(*q))
return 0;
p++, q++;
}
return 1;
+ */
}
void scrape_nick(char *p) {
@@ -95,25 +99,25 @@ void scrape_nick(char *p) {
list[pm_nick_pos][0] = 0;
}
-void find_chan_nicks(void) {
- signed char i;
+void scrape_lines(signed char count, u8 **addr) {
char *p;
-
- add_to = comp_chan_nicks;
- pm_nick_pos = 0;
-
- for(i = 22; i >= 0; i--) {
- p = screen_bot_addrs[scr_current] + 40 * i;
+ while(count >= 0) {
+ p = addr[scr_current] + 40 * count;
scrape_nick(p);
if(pm_nick_pos == MAX_PM_NICKS)
return;
+ count--;
}
- for(i = 24; i >= 0; i--) {
- scrape_nick(p);
- p = screen_top_addrs[scr_current] + 40 * i;
- if(pm_nick_pos == MAX_PM_NICKS)
- return;
- }
+}
+
+void find_chan_nicks(void) {
+ add_to = comp_chan_nicks;
+ pm_nick_pos = 0;
+
+ scrape_lines(22, screen_bot_addrs);
+ if(pm_nick_pos == MAX_PM_NICKS)
+ return;
+ scrape_lines(24, screen_top_addrs);
}
void comp_complete_done(void) {