diff options
| -rw-r--r-- | doc/dynamic-screens.txt | 17 | ||||
| -rw-r--r-- | font_dl.asm | 110 | ||||
| -rw-r--r-- | src/addrs.c | 51 | ||||
| -rw-r--r-- | src/addrs.h | 26 | ||||
| -rw-r--r-- | src/cmd.c | 8 | ||||
| -rw-r--r-- | src/complete.c | 24 | ||||
| -rw-r--r-- | src/irc.c | 32 | ||||
| -rw-r--r-- | src/main.c | 39 | ||||
| -rw-r--r-- | src/pool.c | 110 | ||||
| -rw-r--r-- | src/pool.h | 76 | ||||
| -rw-r--r-- | src/screen.c | 152 | ||||
| -rw-r--r-- | src/screen.h | 16 |
12 files changed, 378 insertions, 283 deletions
diff --git a/doc/dynamic-screens.txt b/doc/dynamic-screens.txt index 065f28c..f6a0c89 100644 --- a/doc/dynamic-screens.txt +++ b/doc/dynamic-screens.txt @@ -305,6 +305,8 @@ Milestones: things that will have to happen to make this a reality. code for size, though, it's going to be replaced. See doc/diet.txt for details/progress on this. + Status: ongoing, but done enough for now. + 2. Split the code/BSS/etc into high and low segments, so it lives from $2000 to $3FFF (low, 8K) and $8000 to $BFFF (high, 16K). This puts the primary screen memory area right where the XE bankswitching @@ -320,6 +322,8 @@ Milestones: things that will have to happen to make this a reality. code', the cc65 stack, and the BSS. Everything else will be in a 'high code' (and possibly 'high BSS') segment, from $8000 to $BFFF. + Status: DONE! + 3. Rip out all the existing screen code and replace it with a simplified form of the new scheme. To start with, only 1-5 pools in bank 0, but the display list modification code can be completed. The rest of @@ -328,7 +332,13 @@ Milestones: things that will have to happen to make this a reality. defining new hotkeys for screen numbers above 7, and making the status bar variable sized (show only the number of screens we have enough RAM for, based on the minimum size being 23 or 46 - lines). + lines). Better yet, don't even show the inactive or unused (grey + dot or number) at all, which would free up a color register. + Figure out some way to handle having more screen numbers than we + could fit in a GR.1 line. 2 lines? Use a GR.0 line (what, PMG and a + DLI for the colors? rather not)? + + Status: barely started... 4. Learn more than I currently know about bankswitching (I know the 130XE, but what's the difference between a Rambo and a Compy Shop @@ -369,7 +379,7 @@ just hypothetical code (final implementation may look different). with 256K, up to 2 screens per pool. with 128K, up to 4. with 64K, we only get 1 large pool. - with 48K, we only get 1 pool. + with 48K, we only get 1 pool. */ #define MAX_SCREENS 32 @@ -399,6 +409,9 @@ typedef struct { // u16 start; /* 0 = not in use */ // u16 end; char screen_count; /* maybe set to $ff for "not in use" */ + // int line_count; /* maybe better to use line count instead of + screen count to decide which pool to create + new screens in? */ 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; diff --git a/font_dl.asm b/font_dl.asm index f89e682..31e80f8 100644 --- a/font_dl.asm +++ b/font_dl.asm @@ -2,87 +2,24 @@ *= $3400 .incbin "font.dat" -; shoehorn the transmit & receive buffers here - *= $3800 -rx_buf ; 512 bytes - *= $3a00 -tx_buf ; 512 bytes - *= $3c00 -scr_vis_buf ; not used yet - - *= $4000 -; screen RAM starts at the XE bankswitching window! -; 7 double-height screens, 50 lines each. -scr0_top - *= * + 1000 -scr1_top - *= * + 1000 -scr2_top - *= * + 1000 -edbox_only_dlist - -; can't cross a 4K boundary... - *= $5000 -scr3_top - *= * + 1000 -scr4_top - *= * + 1000 -scr5_top - *= * + 1000 -scr6_top - - *= $6000 -scr0_bot - *= * + 1000 -scr1_bot - *= * + 1000 -scr2_bot - *= * + 1000 - - *= $7000 -scr3_bot - *= * + 1000 -scr4_bot - *= * + 1000 -scr5_bot - *= * + 1000 -scr6_bot - - *= * + 1000 -dlist_top - *= * + 48 -dlist_bot - *= * + 48 - - *= dlist_top ; used when scrolled up - .byte $70, $70, $30 ; 2 8-line blanks, 1 4-line blank - .byte $42 ; LMS GR.0 -dl_top_lms - .word scr0_top - .byte $02, $02, $02, $02, $02, $02, $02, $02 - .byte $02, $02, $02, $02, $02, $02, $02, $02 - .byte $02, $02, $02, $02, $02, $02, $02, $02 ; 24 GR.0 lines - .byte $41 ; JVB - .word dlist_top - - *= dlist_bot ; used when not scrolled up + *= $3360 +dlist_vis .byte $70, $70, $30 ; 2 8-line blanks, 1 4-line blank .byte $42 ; LMS GR.0 dl_bot_lms - .word scr0_bot + .word scr_vis_buf .byte $02, $02, $02, $02, $02, $02, $02, $02 .byte $02, $02, $02, $02, $02, $02, $02, $02 .byte $02, $02, $02, $02, $02, $02 ; 22 GR.0 lines .byte $00 .byte $42 ; LMS GR.0 dl_status_lms - .word scr0_bot+920 ; line 23 + .word status_box ; line 23 .byte $06 ; one GR.1 line .byte $41 ; JVB - .word dlist_bot -topbot_dlist_done + .word dlist_vis - *= edbox_only_dlist +edbox_only_dlist .byte $70, $70, $30 ; 2 8-line blanks, 1 4-line blank .byte $70, $70, $70, $70, $70, $70, $70, $70 .byte $42 @@ -90,8 +27,39 @@ topbot_dlist_done .byte $02, $02, $02, $02, $02 .byte $00 .byte $42 - .word $a798 ; status_box from addrs.c + .word status_box ; status_box from addrs.c .byte $06 ; GR.1 .byte $41 .word edbox_only_dlist -edbox_dlist_done + +status_box + .rept 60 + .byte 0 + .endr + +status_box_end = status_box + 60 + +; $3400 - $37ff is the font! + +; shoehorn the transmit & receive buffers here + *= $3800 +rx_buf ; 512 bytes + *= $3a00 +tx_buf ; 512 bytes + *= $3c00 +scr_vis_buf ; not used yet + *= $3fa0 +end_marker ; a line_t (42 bytes) + .byte <end_marker ; points to + .byte >end_marker ; itself! + .byte $fe ; inverse ~ + .rept 39 + .byte 0 ; rest of the line is nulls (look like spaces) + .endr + + *= $4000 +; screen RAM starts at the XE bankswitching window! +scr_main_mem + + *= $7fff +scr_main_mem_end diff --git a/src/addrs.c b/src/addrs.c index fd3c8a4..7813cd7 100644 --- a/src/addrs.c +++ b/src/addrs.c @@ -1,56 +1,19 @@ #include "addrs.h" -u8 *dlist_top = u8p(DLIST_TOP_ADDR); -u8 *dlist_bot = u8p(DLIST_BOT_ADDR); - -u16 *dlist_top_lms = u16p(0x7fa4); -u16 *dlist_bot_lms = u16p(0x7fd4); -u16 *dlist_status_lms = u16p(0x7fee); -u8 *dlist_last_line = u8p(0x7ff0); - u8 *edbox_only_dlist = u8p(0x4bb8); -/* 1000 bytes (25 40-char lines) apiece. */ -u8 *screen_top_addrs[7] = { - u8p(0x4000), - u8p(0x43e8), - u8p(0x47d0), - u8p(0x5000), - u8p(0x53e8), - u8p(0x57d0), - u8p(0x5bb8) -}; - -/* 1000 bytes (25 40-char lines) apiece. */ -u8 *screen_bot_addrs[7] = { - u8p(0x6000), - u8p(0x63e8), - u8p(0x67d0), - u8p(0x7000), - u8p(0x73e8), - u8p(0x77d0), - u8p(0x7bb8) -}; - -/* 40 bytes (1 line), third from the bottom of each _bot_addr */ -u8 *screen_lastlines[7] = { - u8p(0x6370), - u8p(0x6758), - u8p(0x6b40), - u8p(0x7370), - u8p(0x7758), - u8p(0x7b40), - u8p(0x7f28) -}; - /* 60 bytes, 1 GR.0 line and 1 GR.1 line. also 20 more bytes filler. this is the bottom 2 lines of screen 0. screens 1-6 actually have 80 bytes of free RAM at the bottom (2 unused lines), for now at least. */ -u8 *status_box = (u8 *)0x6398; +u8 *status_box = (u8 *)0x339f; /* 1 byte, leftmost column of GR.1 line at bottom */ -u8 *ind_net_status = (u8 *)0x63c0; +u8 *ind_net_status = (u8 *)0x33c7; /* 1 byte, 2nd column of GR.1 line at bottom */ -u8 *ind_act_status = (u8 *)0x63c1; +u8 *ind_act_status = (u8 *)0x33c8; + +u16 *dlist_status_lms = (u16 *)0x337e; + +u8 *dlist_last_line = (u8 *)0x3380; diff --git a/src/addrs.h b/src/addrs.h index a7b6755..e13e648 100644 --- a/src/addrs.h +++ b/src/addrs.h @@ -1,20 +1,19 @@ #define FONT_ADDR_HI 0x34 -#define DLIST_TOP_ADDR 0x7fa0 -#define DLIST_BOT_ADDR 0x7fd0 +// #define DLIST_TOP_ADDR 0x7fa0 +// #define DLIST_BOT_ADDR 0x7fd0 +#define DLIST_VIS 0x3360 #define EDBOX_ADDR 0x0600 +#define END_MARKER 0x3fa0 +#define SCR_VIS_BUF 0x3c00 +#define SCR_MAIN_MEM 0x4000 +#define SCR_MAIN_END 0x7fff +#define SCR_LOW_END 0x1fff #define u8 unsigned char #define u8p(x) ((unsigned char *)x) #define u16 unsigned int #define u16p(x) ((unsigned int *)x) -/* dlist_bot is the main one, dlist_top is used when - scrolled back. */ -extern u8 *dlist_top, *dlist_bot; - -extern u16 *dlist_top_lms; -extern u16 *dlist_bot_lms; - /* points to either edit_box or status_box */ extern u16 *dlist_status_lms; @@ -25,15 +24,6 @@ extern u8 *dlist_last_line; /* display list for Start+E (show only edbox) mode. */ extern u8 *edbox_only_dlist; -/* used for scrollback */ -extern u8 *screen_top_addrs[7]; - -/* normal (non-scrollback) display */ -extern u8 *screen_bot_addrs[7]; - -/* address of last line of _bot, where printing actually happens */ -extern u8 *screen_lastlines[7]; - /* bottom 2 lines, shared by all screens */ extern u8 *status_box; @@ -138,7 +138,7 @@ static void mass_join(char scr) { do { arg2 = nextarg(arg1); if(scr) { - scr_create(arg1, 1); + scr_create(arg1); } join_arg1(); arg1 = arg2; @@ -340,7 +340,7 @@ static void do_color(void) { static void do_query(void) { do { arg2 = nextarg(arg1); - if(scr_create(arg1, 1) == 0xff) { + if(scr_create(arg1) == 0xff) { err_marker(); scr_print_current("Query: all screens in use\n"); return; @@ -447,8 +447,8 @@ void cmd_rejoin_chans(void) { char i; for(i = 2; i < MAX_SCREENS; i++) { - if(scr_names[i][0] == '#') { - arg1 = scr_names[i]; + if(screens[i].title[0] == '#') { + arg1 = screens[i].title; join_arg1(); } } diff --git a/src/complete.c b/src/complete.c index fd889b2..9faa52c 100644 --- a/src/complete.c +++ b/src/complete.c @@ -101,25 +101,17 @@ void scrape_nick(char *p) { list[pm_nick_pos][0] = 0; } -void scrape_lines(signed char count, u8 **addr) { - char *p; - while(count >= 0) { - p = addr[scr_current] + 40 * count; - scrape_nick(p); - if(pm_nick_pos == MAX_PM_NICKS) - return; - count--; - } -} - void find_chan_nicks(void) { + line_t *l; + 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); + for(l = screens[scr_current].line_list; l != (line_t *)END_MARKER; l = l->next) { + scrape_nick(l->data); + if(pm_nick_pos == MAX_PM_NICKS) + return; + } } void comp_complete_done(void) { @@ -153,7 +145,7 @@ void comp_start(void) { } else if(scr_current == SCR_PRIV) { p = last_pm_nick; list = comp_pm_nicks; - } else if(scr_names[scr_current][0] == '#') { + } else if(screens[scr_current].title[0] == '#') { find_chan_nicks(); list = comp_chan_nicks; if(pm_nick_pos) p = comp_chan_nicks[pm_nick_pos - 1]; @@ -361,7 +361,7 @@ static void do_forward_chan(void) { if(msg_argcount > 2 && msg_args[1][0] == '#' && msg_args[2][0] == '#') { s = scr_getbyname(msg_args[1]); if(s) - strncpy(scr_names[s], msg_args[2], 31); + strncpy(screens[s].title, msg_args[2], 31); } do_catchall(1); } @@ -423,7 +423,7 @@ static void do_numeric(void) { hide_motd = 0; if(need_rejoin) { cmd_rejoin_chans(); - if(scr_names[2][0] == '#') + if(screens[2].title[0] == '#') scr_display(2); need_rejoin = 0; } @@ -551,8 +551,8 @@ static void dispatch_msg(void) { } if(scr_active != scr_current) { - if(scr_status[scr_active] < new_scr_status) { - scr_status[scr_active] = new_scr_status; + if(screens[scr_active].status < new_scr_status) { + screens[scr_active].status = new_scr_status; scr_show_status(scr_current); } } @@ -760,11 +760,11 @@ static void scrollback() { while(!keypress()) irc_read(); c = kgetc(); - if(c == '-') { - scr_scrollback_bonus(); + while(c == '-') { + scr_scrollback(); while(!keypress()) irc_read(); - kgetc(); + c = kgetc(); } scr_end_scrollback(); } @@ -778,14 +778,14 @@ static void hunt_screen(signed char dir) { s = MAX_SCREENS - 1; if(s == MAX_SCREENS) s = 0; - } while(scr_status[s] == SCR_UNUSED); + } while(screens[s].status == SCR_UNUSED); scr_display(s); } static char *get_cur(void) { - if((scr_current > 1) && (scr_names[scr_current][0] == '#')) - return scr_names[scr_current]; + if((scr_current > 1) && (screens[scr_current].title[0] == '#')) + return screens[scr_current].title; else return 0; } @@ -841,7 +841,7 @@ char find_scr_with_status(char status) { signed char i; for(i = MAX_SCREENS - 1; i != -1; i--) { - if(scr_status[i] == status) { + if(screens[i].status == status) { return i; } } @@ -872,10 +872,10 @@ void list_screens(void) { scr_putc_active(i + '1'); bold(); scr_putc_active(':'); - if(scr_status[i] == SCR_UNUSED) + if(screens[i].status == SCR_UNUSED) scr_print_active("<unused>"); else - scr_print_active(scr_names[i]); + scr_print_active(screens[i].title); scr_eol_active(); } } @@ -909,7 +909,7 @@ void start_keystroke(char c) { if(c >= '1' && c <= '7') { s = c - '1'; if(s != scr_current) { - if(scr_status[s] != SCR_UNUSED) { + if(screens[s].status != SCR_UNUSED) { scr_prev = scr_current; scr_display(s); } @@ -947,11 +947,11 @@ void start_keystroke(char c) { case 'q': if(scr_current == SCR_PRIV && *last_pm_nick) { scr_prev = scr_current; - scr_create(last_pm_nick, 1); + scr_create(last_pm_nick); *last_pm_nick = 0; } else if(scr_current == SCR_SERVER && *last_chan) { scr_prev = scr_current; - scr_create(last_chan, 1); + scr_create(last_chan); *last_chan = 0; } return; @@ -84,8 +84,8 @@ void init_channels(void) { for(i = 0; i < MAX_SCREENS - 2; i++) { if(config.channels[i][0]) { - scr_status[i + 2] = SCR_INACTIVE; - strcpy(scr_names[i + 2], config.channels[i]); + screens[i + 2].status = SCR_INACTIVE; + strcpy(screens[i + 2].title, config.channels[i]); } } } @@ -114,18 +114,25 @@ void reconnect(void) { } void main(void) { - bell_type = config.alert_type; /* TODO: have bell.s read staight from the struct */ - - edbox_clear(); - - while(1) { - if(fn_connect()) { - ind_net_idle(); - irc_register(); - irc_loop(); - } - OS.atract = 0; - fn_disconnect(); - reconnect(); - } + bell_type = config.alert_type; /* TODO: have bell.s read staight from the struct */ + + edbox_clear(); + + #if 0 + scr_activate(0); + scr_print_active("line one\n"); + scr_print_active("line two\n"); +hang: goto hang; + #else + while(1) { + if(fn_connect()) { + ind_net_idle(); + irc_register(); + irc_loop(); + } + OS.atract = 0; + fn_disconnect(); + reconnect(); + } + #endif } diff --git a/src/pool.c b/src/pool.c new file mode 100644 index 0000000..1417a02 --- /dev/null +++ b/src/pool.c @@ -0,0 +1,110 @@ +#include <atari.h> +#include "pool.h" +#include "addrs.h" +#include "memclear.h" + +screen_t screens[MAX_SCREENS]; +pool_t pools[MAX_POOLS]; + +void init_pools(void) { + char p; + + pools[0].screen_count = 0; + pools[0].free_list = (line_t *)END_MARKER; + + for(p = 1; p < MAX_POOLS; p++) + pools[p].screen_count = POOL_UNUSED; + + add_to_pool(0, SCR_MAIN_MEM, SCR_MAIN_END); + + if((u16)OS.memlo < SCR_LOW_END - sizeof(pool_t)) + add_to_pool(0, (u16)OS.memlo, SCR_LOW_END); +} + +void add_to_pool(char p, u16 start, u16 end) { + line_t *l; + + end -= sizeof(line_t); + + l = (line_t *)start; + + while(l <= (line_t *)end) { + memclear(l, sizeof(line_t)); + l->next = pools[p].free_list; + pools[p].free_list = l; + l++; + } +} + +char get_smallest_pool(void) { + char p, r; + u16 min; + + min = 0xffff; + r = 0; + + for(p = 0; p < MAX_POOLS; p++) { + if(pools[p].screen_count = POOL_UNUSED) + continue; /* maybe break here instead */ + if(pools[p].screen_count < min) { + min = pools[p].screen_count; + r = p; + } + } + return r; +} + +line_t *steal_line(char s) { + line_t *l; + char candidate, victim; + u16 maxheight; + + victim = s; + maxheight = 0; + + for(candidate = 0; candidate < MAX_SCREENS; candidate++) { + /* only steal from the same pool */ + if(screens[candidate].pool != screens[s].pool) + continue; + /* steal from the screen with the most lines */ + if(screens[candidate].line_count > maxheight) { + maxheight = screens[candidate].line_count; + victim = candidate; + } + } + + /* find 2nd to last line of the victim screen */ + for(l = screens[victim].line_list; l->next->next != (line_t *)END_MARKER; l = l->next) + ; + + /* prepend last line to screen s */ + l->next->next = screens[s].line_list; + screens[s].line_list = l->next; + memclear(screens[s].line_list->data, LINE_LEN); + + l->next = (line_t *)END_MARKER; + + return l; +} + +line_t *find_line(char s) { + line_t *p; + + p = pools[screens[s].pool].free_list; + if(p != (line_t *)END_MARKER) { + pools[screens[s].pool].free_list = p->next; + return p; + } + + /* free_list was null, pool is full */ + return steal_line(s); +} + +void add_line(char s) { + line_t *p; + + p = find_line(s); + p->next = screens[s].line_list; + screens[s].line_list = p; + screens[s].line_count++; +} diff --git a/src/pool.h b/src/pool.h new file mode 100644 index 0000000..ba7e60f --- /dev/null +++ b/src/pool.h @@ -0,0 +1,76 @@ +#include "addrs.h" + +void init_pools(void); + +/* if each pool is 16K, that's 512K, not bad. however, overhead. maybe + limit this to something like 20 (128K extended = 16, plus the big + pool in main bank, plus the potential smaller pools at MEMLO and + $d800. */ +#define MAX_POOLS 32 + +/* 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. + with 48K, we only get 1 pool. +*/ +// #define MAX_SCREENS 32 +// for now anyway: +#define MAX_SCREENS 10 + +/* if a pool is not in use, its screen_count will be this. */ +#define POOL_UNUSED 0xff + +/* length of a line in bytes. this will eventually be 80 for + xep-80 support. */ +#define LINE_LEN 40 + +/* 42 bytes per line */ +typedef struct line_s { + struct line_s *next; + char data[LINE_LEN]; +} line_t; + +/* the end marker line is a line_t, but it lives outside of any pool and + has a 'next' pointer that points to itself. */ + +/* sizeof(screen_t) is 33 bytes... */ +typedef struct { + char title[25]; + char status; + char pool; /* this could be a pool_t * instead */ + unsigned int line_count; /* can be above 255 */ + line_t *line_list; /* head of a linked list */ + unsigned int scrollback_pos; /* also can be >255 */ +} screen_t; + +extern screen_t screens[MAX_SCREENS]; /* array is 1023 bytes */ + +typedef struct { + // 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" */ + /* int line_count; // maybe better to use line count instead of + screen count to decide which pool to create + new screens in? */ + char bank; /* probably this is just the PORTB value */ + line_t *free_list; /* when this is null, the pool has no free lines */ +} pool_t; + +/* this array is sizeof(pool) * 9, so 288 bytes */ +/* the code that builds this array (detects extended ram too), + will live in the config segment. */ +extern pool_t pools[MAX_POOLS]; + +/* 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_to_pool(char p, u16 start, u16 end); + +/* returns the index into pools[] of the pool with the smallest + screen_count. */ +char get_smallest_pool(void); + +/* add a line to a screen */ +void add_line(char s); diff --git a/src/screen.c b/src/screen.c index e2ed12c..5d64ee4 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1,7 +1,6 @@ #include <atari.h> #include <string.h> -#include "addrs.h" #include "screen.h" #include "edbox.h" #include "indic8.h" @@ -14,16 +13,12 @@ area for extra scrollback. */ unsigned int *bonus_addrs = (unsigned int *)0xd4; /* aka FR0 */ -char scr_status[MAX_SCREENS]; - /* the screen that's currently displaying */ char scr_current; /* the screen that's currently being written to */ char scr_active; -char scr_names[7][32]; - static char xpos; void scr_waitvcount_116(void) { @@ -31,71 +26,49 @@ void scr_waitvcount_116(void) { /* NOP */; } -static void scr_clear(char s) { - if(bonus_addrs[s]) { - memclear(bonus_addrs[s], 1000); - strcpy(bonus_addrs[s], "This is bonus scrollback!"); - } - memclear(screen_top_addrs[s], 1000); - memclear(screen_bot_addrs[s], 1000); - memclear(scr_names[s], 32); -} - -static void scr_scroll(char s) { - if(bonus_addrs[s]) { - memmove(bonus_addrs[s], bonus_addrs[s] + 40, 960); - memmove(bonus_addrs[s] + 960, screen_top_addrs[s], 40); - } - memmove(screen_top_addrs[s], screen_top_addrs[s] + 40, 960); - memmove(screen_top_addrs[s] + 960, screen_bot_addrs[s], 40); - memmove(screen_bot_addrs[s], screen_bot_addrs[s] + 40, 920); - memclear(screen_lastlines[s], 40); -} - void scr_init(void) { int i; OS.sdmctl = 0; /* disappear the screen */ scr_waitvcount_116(); - *SDLST = DLIST_BOT_ADDR; + *SDLST = DLIST_VIS; OS.chbas = FONT_ADDR_HI; + init_pools(); + for(i = 0; i < MAX_SCREENS; i++) { - scr_clear(i); - scr_status[i] = SCR_UNUSED; + screens[i].status = SCR_UNUSED; } - strcpy(scr_names[0], "[server]"); - strcpy(scr_names[1], "[private]"); - scr_status[0] = scr_status[1] = SCR_INACTIVE; + scr_create("[server]"); + scr_create("[private]"); OS.sdmctl = 0x22; /* show the screen again */ scr_display(0); } -char scr_create(const char *name, char display) { - int i; +char scr_create(const char *name) { + char pool, i; /* don't create a duplicate screen */ if( (i = scr_getbyname(name)) ) return i; + pool = get_smallest_pool(); for(i = 0; i < MAX_SCREENS; i++) { - if(scr_status[i] == SCR_UNUSED) { - strcpy(scr_names[i], name); - scr_status[i] = SCR_INACTIVE; - if(display) { - scr_display(i); - } else { - scr_display(scr_current); - } + if(screens[i].status == SCR_UNUSED) { + pools[pool].screen_count++; + strcpy(screens[i].title, name); + screens[i].status = SCR_INACTIVE; + screens[i].pool = pool; + screens[i].line_list = (line_t *)END_MARKER; + screens[i].line_count = screens[i].scrollback_pos = 0; return i; } } - // scr_print_current("Can't create window (all in use)\n"); return 0xff; } @@ -104,66 +77,77 @@ void scr_destroy(char s) { if(s < 2 || s >= MAX_SCREENS) return; - scr_status[s] = SCR_UNUSED; - scr_names[s][0] = 0; - if(scr_current == s) - scr_display(0); - scr_clear(s); + // pool_reclaim_lines(screens[s].pool, screens[s].line_list); + pools[screens[s].pool].screen_count--; + + screens[s].title[0] = 0; + screens[s].status = SCR_UNUSED; + screens[s].pool = POOL_UNUSED; + screens[s].line_list = 0; + screens[s].line_count = screens[s].scrollback_pos = 0; +} + +void render_vis_buf(void) { + line_t *line; + u8 *vis; + int cnt; + + line = screens[scr_current].line_list; + + /* skip lines before the current scroll position */ + for(cnt = 0; cnt < screens[scr_current].scrollback_pos; cnt++) + line = line->next; + + /* point at bottom line of visbuf */ + vis = (u8 *)(SCR_VIS_BUF + LINE_LEN * (SCR_VIS_HEIGHT - 1)); + for(cnt = 0; cnt < SCR_VIS_HEIGHT; cnt++) { + memcpy(vis, line->data, LINE_LEN); + line = line->next; + vis -= LINE_LEN; + } } void scr_display(char s) { if(s >= MAX_SCREENS) return; - /* leave this out, for testing - if(scr_status[s] == SCR_UNUSED) + if(screens[s].status == SCR_UNUSED) return; - */ - scr_status[s] = SCR_INACTIVE; + screens[s].status = SCR_INACTIVE; scr_current = s; scr_waitvcount_116(); - *dlist_bot_lms = (u16)screen_bot_addrs[s]; + render_vis_buf(); scr_show_status(s); } -void scr_scrollback_bonus(void) { - if(bonus_addrs[scr_current]) { - scr_waitvcount_116(); - *dlist_top_lms = (u16)bonus_addrs[scr_current]; - } -} - void scr_scrollback(void) { - // OS.color2 = 0; - scr_waitvcount_116(); - *dlist_top_lms = (u16)screen_top_addrs[scr_current]; - *SDLST = (u16)dlist_top; + if(screens[scr_current].scrollback_pos <= screens[scr_current].line_count) { + screens[scr_current].scrollback_pos += SCR_VIS_HEIGHT; + scr_display(scr_current); + } } void scr_end_scrollback(void) { - // OS.color2 = 192; - scr_waitvcount_116(); - *SDLST = (u16)dlist_bot; + screens[scr_current].scrollback_pos = 0; + scr_display(scr_current); } void scr_show_status(char s) { int i; char *p, sc; - status_box[0] = s + 177; /* inverse number */ + status_box[0] = (s % 10) + 177; /* inverse number */ status_box[1] = ':'; - strncpy(status_box + 2, scr_names[s], 32); + strncpy(status_box + 2, screens[s].title, 32); - p = status_box + 53; /* up against the right border */ + p = status_box + 43; /* one space past the 2nd indicator */ - // *p++ = '<'; - // *p++ = 0xbc; // color2, maybe use? for(i = 0; i < MAX_SCREENS; i++) { - sc = i + '1'; - switch(scr_status[i]) { + sc = (i % 10) + '1'; + switch(screens[i].status) { case SCR_INACTIVE: /* color0 */ break; case SCR_ACTIVE: /* color1 */ @@ -176,12 +160,10 @@ void scr_show_status(char s) { sc |= 0xc0; break; default: - sc = '.'; + continue; /* don't show anything for unused */ } *p++ = sc; } - // *p++ = '>'; - // *p++ = 0xbe; if(!edbox_visible) { scr_waitvcount_116(); @@ -200,7 +182,7 @@ char scr_getbyname(const char *name) { if(!name) return 0; for(i = 2; i < MAX_SCREENS; i++) { - if(streq_i(name, scr_names[i])) + if(streq_i(name, screens[i].title)) return i; } @@ -223,6 +205,9 @@ void scr_eol_current(void) { if we're going to ever support utf-8, decode it here... also, 0x16 is supposed to be reverse video. not widely used/supported. eventually, this will be rewritten in asm anyway. */ +/* FIXME: There is a hidden assumption here: that a sequence of scr_putc(), + up to the \n that ends it, will all be sent to the same screen. + This is because there's only one xpos variable... */ void scr_putc(char s, char c) { u8 *dest; static char bold = 0; @@ -234,16 +219,17 @@ void scr_putc(char s, char c) { bold = 0; if(!xpos) return; - xpos = 40; + xpos = LINE_LEN; + if(s == scr_current) render_vis_buf(); return; } - if(xpos == 40) { - scr_scroll(s); + if(xpos == 0 || xpos == LINE_LEN) { + add_line(s); xpos = 0; } - dest = screen_lastlines[s] + xpos; + dest = screens[s].line_list->data + xpos; if(c & 0x80) { /* utf-8 (or maybe latin-1), we don't support it yet */ @@ -314,7 +300,7 @@ void scr_activate(char s) { } char *scr_get_cur_name(void) { - char *r = scr_names[scr_current]; + char *r = screens[scr_current].title; if(*r) return r; else diff --git a/src/screen.h b/src/screen.h index 76f82c9..e0aad31 100644 --- a/src/screen.h +++ b/src/screen.h @@ -1,9 +1,8 @@ #include "addrs.h" +#include "pool.h" -#define MAX_SCREENS 7 #define LINE_SIZE 40 -#define SCREEN_SIZE 920 -#define BOTTOM_LINE_OFFS 880 +#define SCR_VIS_HEIGHT 23 #define SCR_UNUSED 0 #define SCR_INACTIVE 1 @@ -23,15 +22,6 @@ extern char scr_current; /* the screen that's currently being written to */ extern char scr_active; -/* which screens are "active". the screen being displayed is - never active. any screen that's not visible that's had anything - written to it gets marked active. switching the display to an - active screen clears its active flag. */ -extern char scr_status[MAX_SCREENS]; - -/* names (channel or query). should be treated as read-only by callers. */ -extern char scr_names[7][32]; - /* call before using any of the other functions. sets up the display list, clears all screen memory, selects screen 0 for display. */ @@ -44,7 +34,7 @@ void scr_init(void); if display is true, the new screen displays. otherwise it's created "in the background". */ -char scr_create(const char *name, char display); +char scr_create(const char *name); /* destroys a screen (frees up its slot). */ void scr_destroy(char s); |
