#include #include "screen.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); /* TODO: for pool 0, add whatever RAM exists between the end of the BSS and $3600. also, under-OS XL RAM if enabled. */ /* TODO: support pools 1 and up for other banks! */ } 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, *last_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; /* only steal from screens that exist */ if(screens[candidate].status == SCR_UNUSED) 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 */ l = screens[victim].line_list; while(l->next != (line_t *)END_MARKER) { last_l = l; l = l->next; } /* at the end of the loop, l is the last line before the end marker (the line we're stealing), and last_l is the line before that. */ /* make old_l the last line */ last_l->next = (line_t *)END_MARKER; /* clear out old screen data, then return the stolen line */ memclear(l->data, LINE_LEN); 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++; } void pool_reclaim_lines(char s) { line_t *p, *q; p = screens[s].line_list; while(p != (line_t *)END_MARKER) { q = p; p = p->next; } q->next = pools[screens[s].pool].free_list; pools[screens[s].pool].free_list = screens[s].line_list; /* theoretically this could be 0, but as a safety net... */ screens[s].line_list = (line_t *)END_MARKER; }