71cfa3ae746ecb70b4a1ae60a81347a4ff27249a
[dragonfly.git] / sys / dev / misc / syscons / dragon / dragon_saver.c
1 /*-
2  * Copyright (c) 2000 Chiharu Shibata
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
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: src/sys/modules/syscons/dragon/dragon_saver.c,v 1.1.2.1 2003/05/11 01:17:02 murray Exp $
29  * $DragonFly: src/sys/dev/misc/syscons/dragon/dragon_saver.c,v 1.3 2003/08/15 08:32:30 dillon Exp $
30  */
31
32 #include        <sys/param.h>
33 #include        <sys/systm.h>
34 #include        <sys/kernel.h>
35 #include        <sys/module.h>
36 #include        <sys/syslog.h>
37 #include        <sys/consio.h>
38 #include        <sys/fbio.h>
39
40 #include        <sys/random.h>
41
42 #include        <dev/video/fb/fbreg.h>
43 #include        <dev/video/fb/splashreg.h>
44 #include        "../syscons.h"
45
46 #define SAVER_NAME       "dragon_saver"
47
48 static u_char   *vid;
49 static int      blanked;
50
51 #ifdef PC98
52 #define VIDEO_MODE      M_PC98_EGC640x400
53 #define VIDEO_MODE_NAME "M_PC98_EGC640x400"
54 #define SCRW    640
55 #define SCRH    400
56 #else
57 #define VIDEO_MODE      M_VGA_CG320
58 #define VIDEO_MODE_NAME "M_VGA_CG320"
59 #define SCRW    320
60 #define SCRH    200
61 #endif
62 #define ORDER   13
63 #define CURVE   3
64 #define OUT     100
65
66 static int      cur_x, cur_y;
67 static int      curve;
68 static u_char   dragon_pal[3*256];      /* zero-filled by the compiler */
69
70 static __inline int
71 gpset(int x, int y, int val)
72 {
73         if (x < 0 || y < 0 || SCRW <= x || SCRH <= y) {
74                 return 0;
75         }
76 #ifdef PC98
77         vid[(x + y * SCRW) >> 3] = (0x80 >> (x & 7));   /* write new dot */
78 #else
79         vid[x + y * SCRW] = val;
80 #endif
81         return 1;
82 }
83
84 static int
85 gdraw(int dx, int dy, int val)
86 {
87         int     i;
88         int     set = 0;
89
90 #ifdef PC98
91         outb(0x7c, 0xcc);       /* GRCG on & RMW mode(disable planeI,G) */
92         outb(0x7e, (val & 1) ? 0xff: 0);        /* tile B */
93         outb(0x7e, (val & 2) ? 0xff: 0);        /* tile R */
94 #endif
95         if (dx != 0) {
96                 i = cur_x;
97                 cur_x += dx;
98                 if (dx < 0) {
99                         i += dx;
100                         dx = -dx;
101                 }
102                 /* horizontal line */
103                 for (; dx >= 0; --dx, ++i) {
104                         set |= gpset(i, cur_y, val);
105                 } 
106         }
107         else {  /* dy != 0 */
108                 i = cur_y;
109                 cur_y += dy;
110                 if (dy < 0) {
111                         i += dy;
112                         dy = -dy;
113                 }
114                 /* vertical line */
115                 for (; dy >= 0; --dy, ++i) {
116                         set |= gpset(cur_x, i, val);
117                 } 
118         }
119 #ifdef PC98
120         outb(0x7c, 0);          /* GRCG off */
121 #endif
122         return set;
123 }
124
125 static void
126 gcls(void)
127 {
128 #ifdef PC98
129         outb(0x7c, 0x80);       /* GRCG on & TDW mode */
130         outb(0x7e, 0);                  /* tile B */
131         outb(0x7e, 0);                  /* tile R */
132         outb(0x7e, 0);                  /* tile G */
133         outb(0x7e, 0);                  /* tile I */
134
135         fillw(0, vid, 0x8000);
136
137         outb(0x7c, 0);  /* GRCG off */
138 #else
139         bzero(vid, SCRW*SCRH);
140 #endif
141 }
142
143 static void
144 dragon_update(video_adapter_t *adp)
145 {
146         static int      i, p, q;
147         static int      order, mul, out;
148         static int      org_x, org_y;
149         static int      dx, dy;
150         static unsigned char    fold[1 << (ORDER - 3)];
151 #define GET_FOLD(x)     (fold[(x) >> 3]  &  (1 << ((x) & 7)))
152 #define SET_FOLD(x)     (fold[(x) >> 3] |=  (1 << ((x) & 7)))
153 #define CLR_FOLD(x)     (fold[(x) >> 3] &= ~(1 << ((x) & 7)))
154         int     tmp;
155
156         if (curve > CURVE) {
157                 gcls();
158
159                 /* set palette of each curves */
160                 for (tmp = 0; tmp < 3*CURVE; ++tmp) {
161                         dragon_pal[3+tmp] = (u_char)random(); 
162                 }
163                 load_palette(adp, dragon_pal);
164
165                 mul = ((random() & 7) + 1) * (SCRW / 320);
166                 org_x = random() % SCRW; org_y = random() % SCRH;
167
168                 curve = 0;
169                 order = ORDER;
170         }
171
172         if (order >= ORDER) {
173                 ++curve;
174
175                 cur_x = org_x; cur_y = org_y;
176
177                 switch (curve) {
178                 case 1:
179                         dx = 0; dy = mul;
180                         break;
181                 case 2:
182                         dx = mul; dy = 0;
183                         break;
184                 case 3:
185                         dx = 0; dy = -mul;
186                         break;
187                 }
188                 (void)gdraw(dx, dy, curve); out = 0;
189
190                 order = 0;
191                 q = p = 0; i = q + 1;
192         }
193
194         if (i > q) {
195                 SET_FOLD(p); q = p * 2;
196
197                 ++order;
198                 i = p; p = q + 1;
199         }
200
201         if (GET_FOLD(q-i) != 0) {
202                 CLR_FOLD(i);
203                 tmp = dx; dx =  dy; dy = -tmp;  /* turn right */
204         }
205         else {
206                 SET_FOLD(i);
207                 tmp = dx; dx = -dy; dy =  tmp;  /* turn left */
208         }
209         if (gdraw(dx, dy, curve)) {
210                 out = 0;
211         }
212         else {
213                 if (++out > OUT) {
214                         order = ORDER;  /* force to terminate this curve */
215                 }
216         }
217         ++i;
218 }
219
220 static int
221 dragon_saver(video_adapter_t *adp, int blank)
222 {
223         int pl;
224
225         if (blank) {
226                 /* switch to graphics mode */
227                 if (blanked <= 0) {
228                         pl = splhigh();
229                         set_video_mode(adp, VIDEO_MODE);
230                         vid = (u_char *)adp->va_window;
231                         curve = CURVE + 1;
232                         ++blanked;
233                         splx(pl);
234                 }
235
236                 /* update display */
237                 dragon_update(adp);
238         }
239         else {
240                 blanked = 0;
241         }
242         return 0;
243 }
244
245 static int
246 dragon_init(video_adapter_t *adp)
247 {
248         video_info_t info;
249
250         /* check that the console is capable of running in 320x200x256 */
251         if (get_mode_info(adp, VIDEO_MODE, &info)) {
252                 log(LOG_NOTICE,
253                     "%s: the console does not support " VIDEO_MODE_NAME "\n",
254                     SAVER_NAME);
255                 return ENODEV;
256         }
257
258         blanked = 0;
259         return 0;
260 }
261
262 static int
263 dragon_term(video_adapter_t *adp)
264 {
265         return 0;
266 }
267
268 static scrn_saver_t dragon_module = {
269         SAVER_NAME,
270         dragon_init,
271         dragon_term,
272         dragon_saver,
273         NULL,
274 };
275
276 SAVER_MODULE(dragon_saver, dragon_module);