xref: /freebsd/sys/dev/syscons/dragon/dragon_saver.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
181b60c73SAkio Morita /*-
2*718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
3*718cf2ccSPedro F. Giffuni  *
481b60c73SAkio Morita  * Copyright (c) 2000 Chiharu Shibata
581b60c73SAkio Morita  * All rights reserved.
681b60c73SAkio Morita  *
781b60c73SAkio Morita  * Redistribution and use in source and binary forms, with or without
881b60c73SAkio Morita  * modification, are permitted provided that the following conditions
981b60c73SAkio Morita  * are met:
1081b60c73SAkio Morita  * 1. Redistributions of source code must retain the above copyright
1181b60c73SAkio Morita  *    notice, this list of conditions and the following disclaimer
1281b60c73SAkio Morita  *    in this position and unchanged.
1381b60c73SAkio Morita  * 2. Redistributions in binary form must reproduce the above copyright
1481b60c73SAkio Morita  *    notice, this list of conditions and the following disclaimer in the
1581b60c73SAkio Morita  *    documentation and/or other materials provided with the distribution.
1681b60c73SAkio Morita  * 3. The name of the author may not be used to endorse or promote products
1781b60c73SAkio Morita  *    derived from this software without specific prior written permission.
1881b60c73SAkio Morita  *
1981b60c73SAkio Morita  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2081b60c73SAkio Morita  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2181b60c73SAkio Morita  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2281b60c73SAkio Morita  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2381b60c73SAkio Morita  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2481b60c73SAkio Morita  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2581b60c73SAkio Morita  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2681b60c73SAkio Morita  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2781b60c73SAkio Morita  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2881b60c73SAkio Morita  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2981b60c73SAkio Morita  */
3081b60c73SAkio Morita 
3181b60c73SAkio Morita #include	<sys/param.h>
3281b60c73SAkio Morita #include	<sys/systm.h>
3381b60c73SAkio Morita #include	<sys/kernel.h>
3481b60c73SAkio Morita #include	<sys/module.h>
3581b60c73SAkio Morita #include	<sys/syslog.h>
3681b60c73SAkio Morita #include	<sys/consio.h>
3781b60c73SAkio Morita #include	<sys/fbio.h>
3881b60c73SAkio Morita 
3981b60c73SAkio Morita #include	<sys/random.h>
4081b60c73SAkio Morita 
4181b60c73SAkio Morita #include	<dev/fb/fbreg.h>
4281b60c73SAkio Morita #include	<dev/fb/splashreg.h>
4381b60c73SAkio Morita #include	<dev/syscons/syscons.h>
4481b60c73SAkio Morita 
4581b60c73SAkio Morita #define SAVER_NAME	 "dragon_saver"
4681b60c73SAkio Morita 
4781b60c73SAkio Morita static u_char	*vid;
4881b60c73SAkio Morita static int	blanked;
4981b60c73SAkio Morita 
5081b60c73SAkio Morita #define	VIDEO_MODE	M_VGA_CG320
5181b60c73SAkio Morita #define	VIDEO_MODE_NAME	"M_VGA_CG320"
5281b60c73SAkio Morita #define	SCRW	320
5381b60c73SAkio Morita #define	SCRH	200
5481b60c73SAkio Morita #define	ORDER	13
5581b60c73SAkio Morita #define	CURVE	3
5681b60c73SAkio Morita #define	OUT	100
5781b60c73SAkio Morita 
5881b60c73SAkio Morita static int	cur_x, cur_y;
5981b60c73SAkio Morita static int	curve;
6081b60c73SAkio Morita static u_char	dragon_pal[3*256];	/* zero-filled by the compiler */
6181b60c73SAkio Morita 
6281b60c73SAkio Morita static __inline int
gpset(int x,int y,int val)6381b60c73SAkio Morita gpset(int x, int y, int val)
6481b60c73SAkio Morita {
6581b60c73SAkio Morita 	if (x < 0 || y < 0 || SCRW <= x || SCRH <= y) {
6681b60c73SAkio Morita 		return 0;
6781b60c73SAkio Morita 	}
6881b60c73SAkio Morita 	vid[x + y * SCRW] = val;
6981b60c73SAkio Morita 	return 1;
7081b60c73SAkio Morita }
7181b60c73SAkio Morita 
7281b60c73SAkio Morita static int
gdraw(int dx,int dy,int val)7381b60c73SAkio Morita gdraw(int dx, int dy, int val)
7481b60c73SAkio Morita {
7581b60c73SAkio Morita 	int	i;
7681b60c73SAkio Morita 	int	set = 0;
7781b60c73SAkio Morita 
7881b60c73SAkio Morita 	if (dx != 0) {
7981b60c73SAkio Morita 		i = cur_x;
8081b60c73SAkio Morita 		cur_x += dx;
8181b60c73SAkio Morita 		if (dx < 0) {
8281b60c73SAkio Morita 			i += dx;
8381b60c73SAkio Morita 			dx = -dx;
8481b60c73SAkio Morita 		}
8581b60c73SAkio Morita 		/* horizontal line */
8681b60c73SAkio Morita 		for (; dx >= 0; --dx, ++i) {
8781b60c73SAkio Morita 			set |= gpset(i, cur_y, val);
8881b60c73SAkio Morita 		}
8981b60c73SAkio Morita 	}
9081b60c73SAkio Morita 	else {	/* dy != 0 */
9181b60c73SAkio Morita 		i = cur_y;
9281b60c73SAkio Morita 		cur_y += dy;
9381b60c73SAkio Morita 		if (dy < 0) {
9481b60c73SAkio Morita 			i += dy;
9581b60c73SAkio Morita 			dy = -dy;
9681b60c73SAkio Morita 		}
9781b60c73SAkio Morita 		/* vertical line */
9881b60c73SAkio Morita 		for (; dy >= 0; --dy, ++i) {
9981b60c73SAkio Morita 			set |= gpset(cur_x, i, val);
10081b60c73SAkio Morita 		}
10181b60c73SAkio Morita 	}
10281b60c73SAkio Morita 	return set;
10381b60c73SAkio Morita }
10481b60c73SAkio Morita 
10581b60c73SAkio Morita static void
dragon_update(video_adapter_t * adp)10681b60c73SAkio Morita dragon_update(video_adapter_t *adp)
10781b60c73SAkio Morita {
10881b60c73SAkio Morita 	static int	i, p, q;
10981b60c73SAkio Morita 	static int	order, mul, out;
11081b60c73SAkio Morita 	static int	org_x, org_y;
11181b60c73SAkio Morita 	static int	dx, dy;
11281b60c73SAkio Morita 	static unsigned char	fold[1 << (ORDER - 3)];
11381b60c73SAkio Morita #define	GET_FOLD(x)	(fold[(x) >> 3]  &  (1 << ((x) & 7)))
11481b60c73SAkio Morita #define	SET_FOLD(x)	(fold[(x) >> 3] |=  (1 << ((x) & 7)))
11581b60c73SAkio Morita #define	CLR_FOLD(x)	(fold[(x) >> 3] &= ~(1 << ((x) & 7)))
11681b60c73SAkio Morita 	int	tmp;
11781b60c73SAkio Morita 
11881b60c73SAkio Morita 	if (curve > CURVE) {
1199336e069SWojciech A. Koszek 		vidd_clear(adp);
12081b60c73SAkio Morita 
12181b60c73SAkio Morita 		/* set palette of each curves */
12281b60c73SAkio Morita 		for (tmp = 0; tmp < 3*CURVE; ++tmp) {
12381b60c73SAkio Morita 			dragon_pal[3+tmp] = (u_char)random();
12481b60c73SAkio Morita 		}
1259336e069SWojciech A. Koszek 		vidd_load_palette(adp, dragon_pal);
12681b60c73SAkio Morita 
12781b60c73SAkio Morita 		mul = ((random() & 7) + 1) * (SCRW / 320);
12881b60c73SAkio Morita 		org_x = random() % SCRW; org_y = random() % SCRH;
12981b60c73SAkio Morita 
13081b60c73SAkio Morita 		curve = 0;
13181b60c73SAkio Morita 		order = ORDER;
13281b60c73SAkio Morita 	}
13381b60c73SAkio Morita 
13481b60c73SAkio Morita 	if (order >= ORDER) {
13581b60c73SAkio Morita 		++curve;
13681b60c73SAkio Morita 
13781b60c73SAkio Morita 		cur_x = org_x; cur_y = org_y;
13881b60c73SAkio Morita 
13981b60c73SAkio Morita 		switch (curve) {
14081b60c73SAkio Morita 		case 1:
14181b60c73SAkio Morita 			dx = 0; dy = mul;
14281b60c73SAkio Morita 			break;
14381b60c73SAkio Morita 		case 2:
14481b60c73SAkio Morita 			dx = mul; dy = 0;
14581b60c73SAkio Morita 			break;
14681b60c73SAkio Morita 		case 3:
14781b60c73SAkio Morita 			dx = 0; dy = -mul;
14881b60c73SAkio Morita 			break;
14981b60c73SAkio Morita 		}
15081b60c73SAkio Morita 		(void)gdraw(dx, dy, curve); out = 0;
15181b60c73SAkio Morita 
15281b60c73SAkio Morita 		order = 0;
15381b60c73SAkio Morita 		q = p = 0; i = q + 1;
15481b60c73SAkio Morita 	}
15581b60c73SAkio Morita 
15681b60c73SAkio Morita 	if (i > q) {
15781b60c73SAkio Morita 		SET_FOLD(p); q = p * 2;
15881b60c73SAkio Morita 
15981b60c73SAkio Morita 		++order;
16081b60c73SAkio Morita 		i = p; p = q + 1;
16181b60c73SAkio Morita 	}
16281b60c73SAkio Morita 
16381b60c73SAkio Morita 	if (GET_FOLD(q-i) != 0) {
16481b60c73SAkio Morita 		CLR_FOLD(i);
16581b60c73SAkio Morita 		tmp = dx; dx =  dy; dy = -tmp;	/* turn right */
16681b60c73SAkio Morita 	}
16781b60c73SAkio Morita 	else {
16881b60c73SAkio Morita 		SET_FOLD(i);
16981b60c73SAkio Morita 		tmp = dx; dx = -dy; dy =  tmp;	/* turn left */
17081b60c73SAkio Morita 	}
17181b60c73SAkio Morita 	if (gdraw(dx, dy, curve)) {
17281b60c73SAkio Morita 		out = 0;
17381b60c73SAkio Morita 	}
17481b60c73SAkio Morita 	else {
17581b60c73SAkio Morita 		if (++out > OUT) {
17681b60c73SAkio Morita 			order = ORDER;	/* force to terminate this curve */
17781b60c73SAkio Morita 		}
17881b60c73SAkio Morita 	}
17981b60c73SAkio Morita 	++i;
18081b60c73SAkio Morita }
18181b60c73SAkio Morita 
18281b60c73SAkio Morita static int
dragon_saver(video_adapter_t * adp,int blank)18381b60c73SAkio Morita dragon_saver(video_adapter_t *adp, int blank)
18481b60c73SAkio Morita {
18581b60c73SAkio Morita 	int pl;
18681b60c73SAkio Morita 
18781b60c73SAkio Morita 	if (blank) {
18881b60c73SAkio Morita 		/* switch to graphics mode */
18981b60c73SAkio Morita 		if (blanked <= 0) {
19081b60c73SAkio Morita 			pl = splhigh();
1919336e069SWojciech A. Koszek 			vidd_set_mode(adp, VIDEO_MODE);
19281b60c73SAkio Morita 			vid = (u_char *)adp->va_window;
19381b60c73SAkio Morita 			curve = CURVE + 1;
19481b60c73SAkio Morita 			++blanked;
19581b60c73SAkio Morita 			splx(pl);
19681b60c73SAkio Morita 		}
19781b60c73SAkio Morita 
19881b60c73SAkio Morita 		/* update display */
19981b60c73SAkio Morita 		dragon_update(adp);
20081b60c73SAkio Morita 	}
20181b60c73SAkio Morita 	else {
20281b60c73SAkio Morita 		blanked = 0;
20381b60c73SAkio Morita 	}
20481b60c73SAkio Morita 	return 0;
20581b60c73SAkio Morita }
20681b60c73SAkio Morita 
20781b60c73SAkio Morita static int
dragon_init(video_adapter_t * adp)20881b60c73SAkio Morita dragon_init(video_adapter_t *adp)
20981b60c73SAkio Morita {
21081b60c73SAkio Morita 	video_info_t info;
21181b60c73SAkio Morita 
21281b60c73SAkio Morita 	/* check that the console is capable of running in 320x200x256 */
2139336e069SWojciech A. Koszek 	if (vidd_get_info(adp, VIDEO_MODE, &info)) {
21481b60c73SAkio Morita 		log(LOG_NOTICE,
21581b60c73SAkio Morita 		    "%s: the console does not support " VIDEO_MODE_NAME "\n",
21681b60c73SAkio Morita 		    SAVER_NAME);
21781b60c73SAkio Morita 		return ENODEV;
21881b60c73SAkio Morita 	}
21981b60c73SAkio Morita 
22081b60c73SAkio Morita 	blanked = 0;
22181b60c73SAkio Morita 	return 0;
22281b60c73SAkio Morita }
22381b60c73SAkio Morita 
22481b60c73SAkio Morita static int
dragon_term(video_adapter_t * adp)22581b60c73SAkio Morita dragon_term(video_adapter_t *adp)
22681b60c73SAkio Morita {
22781b60c73SAkio Morita 	return 0;
22881b60c73SAkio Morita }
22981b60c73SAkio Morita 
23081b60c73SAkio Morita static scrn_saver_t dragon_module = {
23181b60c73SAkio Morita 	SAVER_NAME,
23281b60c73SAkio Morita 	dragon_init,
23381b60c73SAkio Morita 	dragon_term,
23481b60c73SAkio Morita 	dragon_saver,
23581b60c73SAkio Morita 	NULL,
23681b60c73SAkio Morita };
23781b60c73SAkio Morita 
23881b60c73SAkio Morita SAVER_MODULE(dragon_saver, dragon_module);
239