diff options
Diffstat (limited to 'src/pool.c')
| -rw-r--r-- | src/pool.c | 110 |
1 files changed, 110 insertions, 0 deletions
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++; +} |
