Deleted Added
sdiff udiff text old ( 50477 ) new ( 56043 )
full compact
1/*-
2 * Copyright (c) 1997 Sandro Sigala, Brescia, Italy.
3 * Copyright (c) 1997 Chris Shenton
4 * Copyright (c) 1995 S ren Schmidt
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in this position and unchanged.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/dev/syscons/daemon/daemon_saver.c 50477 1999-08-28 01:08:13Z peter $
29 */
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/module.h>
34#include <sys/malloc.h>
35#include <sys/kernel.h>
36#include <sys/sysctl.h>
37#include <sys/consio.h>
38#include <sys/fbio.h>
39
40#include <machine/pc/display.h>
41
42#include <dev/fb/fbreg.h>
43#include <dev/fb/splashreg.h>
44#include <dev/syscons/syscons.h>
45
46#define DAEMON_MAX_WIDTH 32
47#define DAEMON_MAX_HEIGHT 19
48
49static char *message;
50static int messagelen;
51static int blanked;
52
53/* Who is the author of this ASCII pic? */
54
55static char *daemon_pic[] = {
56 " , ,",
57 " /( )`",
58 " \\ \\___ / |",
59 " /- _ `-/ '",
60 " (/\\/ \\ \\ /\\",
61 " / / | ` \\",
62 " O O ) / |",
63 " `-^--'`< '",
64 " (_.) _ ) /",
65 " `.___/` /",
66 " `-----' /",
67 "<----. __ / __ \\",
68 "<----|====O)))==) \\) /====",
69 "<----' `--' `.__,' \\",
70 " | |",
71 " \\ / /\\",
72 " ______( (_ / \\______/",
73 " ,' ,-----' |",
74 " `--{__________)",
75 NULL
76};
77
78static char *daemon_attr[] = {
79 " R R",
80 " RR RR",
81 " R RRRR R R",
82 " RR W RRR R",
83 " RWWW W R RR",
84 " W W W R R",
85 " B B W R R",
86 " WWWWWWRR R",
87 " RRRR R R R",
88 " RRRRRRR R",
89 " RRRRRRR R",
90 "YYYYYY RR R RR R",
91 "YYYYYYYYYYRRRRYYR RR RYYYY",
92 "YYYYYY RRRR RRRRRR R",
93 " R R",
94 " R R RR",
95 " CCCCCCR RR R RRRRRRRR",
96 " CC CCCCCCC C",
97 " CCCCCCCCCCCCCCC",
98 NULL
99};
100
101/*
102 * Reverse a graphics character, or return unaltered if no mirror;
103 * should do alphanumerics too, but I'm too lazy. <cshenton@it.hq.nasa.gov>
104 */
105
106static char
107xflip_symbol(char symbol)
108{
109 static const char lchars[] = "`'(){}[]\\/<>";
110 static const char rchars[] = "'`)(}{][/\\><";
111 int pos;
112
113 for (pos = 0; lchars[pos] != '\0'; pos++)
114 if (lchars[pos] == symbol)
115 return rchars[pos];
116
117 return symbol;
118}
119
120static void
121clear_daemon(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
122 int xlen, int ylen)
123{
124 int y;
125
126 if (xlen <= 0)
127 return;
128 for (y = yoff; y < ylen; y++) {
129 sc_vtb_erase(&sc->cur_scp->scr,
130 (ypos + y)*sc->cur_scp->xsize + xpos + xoff,
131 xlen - xoff,
132 sc->scr_map[0x20], (FG_LIGHTGREY | BG_BLACK) << 8);
133 }
134}
135
136static void
137draw_daemon(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
138 int xlen, int ylen)
139{
140 int x, y;
141 int px;
142 int attr;
143
144 for (y = yoff; y < ylen; y++) {
145 if (dxdir < 0)
146 px = xoff;
147 else
148 px = DAEMON_MAX_WIDTH - xlen;
149 if (px >= strlen(daemon_pic[y]))
150 continue;
151 for (x = xoff; (x < xlen) && (daemon_pic[y][px] != '\0'); x++, px++) {
152 switch (daemon_attr[y][px]) {
153#ifndef PC98
154 case 'R': attr = (FG_LIGHTRED|BG_BLACK)<<8; break;
155 case 'Y': attr = (FG_YELLOW|BG_BLACK)<<8; break;
156 case 'B': attr = (FG_LIGHTBLUE|BG_BLACK)<<8; break;
157 case 'W': attr = (FG_LIGHTGREY|BG_BLACK)<<8; break;
158 case 'C': attr = (FG_CYAN|BG_BLACK)<<8; break;
159 default: attr = (FG_WHITE|BG_BLACK)<<8; break;
160#else /* PC98 */
161 case 'R': attr = (FG_RED|BG_BLACK)<<8; break;
162 case 'Y': attr = (FG_BROWN|BG_BLACK)<<8; break;
163 case 'B': attr = (FG_BLUE|BG_BLACK)<<8; break;
164 case 'W': attr = (FG_LIGHTGREY|BG_BLACK)<<8; break;
165 case 'C': attr = (FG_CYAN|BG_BLACK)<<8; break;
166 default: attr = (FG_LIGHTGREY|BG_BLACK)<<8; break;
167#endif /* PC98 */
168 }
169 if (dxdir < 0) { /* Moving left */
170 sc_vtb_putc(&sc->cur_scp->scr,
171 (ypos + y)*sc->cur_scp->xsize
172 + xpos + x,
173 sc->scr_map[daemon_pic[y][px]],
174 attr);
175 } else { /* Moving right */
176 sc_vtb_putc(&sc->cur_scp->scr,
177 (ypos + y)*sc->cur_scp->xsize
178 + xpos + DAEMON_MAX_WIDTH
179 - px - 1,
180 sc->scr_map[xflip_symbol(daemon_pic[y][px])],
181 attr);
182 }
183 }
184 }
185}
186
187static void
188clear_string(sc_softc_t *sc, int xpos, int ypos, int xoff, char *s, int len)
189{
190 if (len <= 0)
191 return;
192 sc_vtb_erase(&sc->cur_scp->scr,
193 ypos*sc->cur_scp->xsize + xpos + xoff, len - xoff,
194 sc->scr_map[0x20], (FG_LIGHTGREY | BG_BLACK) << 8);
195}
196
197static void
198draw_string(sc_softc_t *sc, int xpos, int ypos, int xoff, char *s, int len)
199{
200 int x;
201
202 for (x = xoff; x < len; x++) {
203 sc_vtb_putc(&sc->cur_scp->scr,
204 ypos*sc->cur_scp->xsize + xpos + x,
205 sc->scr_map[s[x]], (FG_LIGHTGREEN | BG_BLACK) << 8);
206 }
207}
208
209static int
210daemon_saver(video_adapter_t *adp, int blank)
211{
212 static int txpos = 10, typos = 10;
213 static int txdir = -1, tydir = -1;
214 static int dxpos = 0, dypos = 0;
215 static int dxdir = 1, dydir = 1;
216 static int moved_daemon = 0;
217 static int xoff, yoff, toff;
218 static int xlen, ylen, tlen;
219 sc_softc_t *sc;
220 scr_stat *scp;
221 int min, max;
222
223 sc = sc_find_softc(adp, NULL);
224 if (sc == NULL)
225 return EAGAIN;
226 scp = sc->cur_scp;
227
228 if (blank) {
229 if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
230 return EAGAIN;
231 if (blanked == 0) {
232#ifdef PC98
233 if (epson_machine_id == 0x20) {
234 outb(0x43f, 0x42);
235 outb(0x0c17, inb(0xc17) & ~0x08);
236 outb(0x43f, 0x40);
237 }
238#endif /* PC98 */
239 /* clear the screen and set the border color */
240 sc_vtb_clear(&scp->scr, sc->scr_map[0x20],
241 (FG_LIGHTGREY | BG_BLACK) << 8);
242 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
243 set_border(scp, 0);
244 xlen = ylen = tlen = 0;
245 }
246 if (blanked++ < 2)
247 return 0;
248 blanked = 1;
249
250 clear_daemon(sc, dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
251 clear_string(sc, txpos, typos, toff, (char *)message, tlen);
252
253 if (++moved_daemon) {
254 /*
255 * The daemon picture may be off the screen, if
256 * screen size is chagened while the screen
257 * saver is inactive. Make sure the origin of
258 * the picture is between min and max.
259 */
260 if (scp->xsize <= DAEMON_MAX_WIDTH) {
261 /*
262 * If the screen width is too narrow, we
263 * allow part of the picture go off
264 * the screen so that the daemon won't
265 * flip too often.
266 */
267 min = scp->xsize - DAEMON_MAX_WIDTH - 10;
268 max = 10;
269 } else {
270 min = 0;
271 max = scp->xsize - DAEMON_MAX_WIDTH;
272 }
273 if (dxpos <= min) {
274 dxpos = min;
275 dxdir = 1;
276 } else if (dxpos >= max) {
277 dxpos = max;
278 dxdir = -1;
279 }
280
281 if (scp->ysize <= DAEMON_MAX_HEIGHT) {
282 min = scp->ysize - DAEMON_MAX_HEIGHT - 10;
283 max = 10;
284 } else {
285 min = 0;
286 max = scp->ysize - DAEMON_MAX_HEIGHT;
287 }
288 if (dypos <= min) {
289 dypos = min;
290 dydir = 1;
291 } else if (dypos >= max) {
292 dypos = max;
293 dydir = -1;
294 }
295
296 moved_daemon = -1;
297 dxpos += dxdir; dypos += dydir;
298
299 /* clip the picture */
300 xoff = 0;
301 xlen = DAEMON_MAX_WIDTH;
302 if (dxpos + xlen <= 0)
303 xlen = 0;
304 else if (dxpos < 0)
305 xoff = -dxpos;
306 if (dxpos >= scp->xsize)
307 xlen = 0;
308 else if (dxpos + xlen > scp->xsize)
309 xlen = scp->xsize - dxpos;
310 yoff = 0;
311 ylen = DAEMON_MAX_HEIGHT;
312 if (dypos + ylen <= 0)
313 ylen = 0;
314 else if (dypos < 0)
315 yoff = -dypos;
316 if (dypos >= scp->ysize)
317 ylen = 0;
318 else if (dypos + ylen > scp->ysize)
319 ylen = scp->ysize - dypos;
320 }
321
322 if (scp->xsize <= messagelen) {
323 min = scp->xsize - messagelen - 10;
324 max = 10;
325 } else {
326 min = 0;
327 max = scp->xsize - messagelen;
328 }
329 if (txpos <= min) {
330 txpos = min;
331 txdir = 1;
332 } else if (txpos >= max) {
333 txpos = max;
334 txdir = -1;
335 }
336 if (typos <= 0) {
337 typos = 0;
338 tydir = 1;
339 } else if (typos >= scp->ysize - 1) {
340 typos = scp->ysize - 1;
341 tydir = -1;
342 }
343 txpos += txdir; typos += tydir;
344
345 toff = 0;
346 tlen = messagelen;
347 if (txpos + tlen <= 0)
348 tlen = 0;
349 else if (txpos < 0)
350 toff = -txpos;
351 if (txpos >= scp->xsize)
352 tlen = 0;
353 else if (txpos + tlen > scp->xsize)
354 tlen = scp->xsize - txpos;
355
356 draw_daemon(sc, dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
357 draw_string(sc, txpos, typos, toff, (char *)message, tlen);
358 } else {
359#ifdef PC98
360 if (epson_machine_id == 0x20) {
361 outb(0x43f, 0x42);
362 outb(0x0c17, inb(0xc17) | 0x08);
363 outb(0x43f, 0x40);
364 }
365#endif /* PC98 */
366 blanked = 0;
367 }
368 return 0;
369}
370
371static int
372daemon_init(video_adapter_t *adp)
373{
374 messagelen = strlen(hostname) + 3 + strlen(ostype) + 1 +
375 strlen(osrelease);
376 message = malloc(messagelen + 1, M_DEVBUF, M_WAITOK);
377 sprintf(message, "%s - %s %s", hostname, ostype, osrelease);
378 blanked = 0;
379 return 0;
380}
381
382static int
383daemon_term(video_adapter_t *adp)
384{
385 free(message, M_DEVBUF);
386 return 0;
387}
388
389static scrn_saver_t daemon_module = {
390 "daemon_saver", daemon_init, daemon_term, daemon_saver, NULL,
391};
392
393SAVER_MODULE(daemon_saver, daemon_module);