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