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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#include <atari.h>
#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++;
}
|