aboutsummaryrefslogtreecommitdiff
path: root/src/pool.c
blob: 1417a02f72b9ec2dc9fb624bbc5c538262433dcd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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++;
}