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); 277