193011Samorita/*- 293011Samorita * Copyright (c) 2000 Chiharu Shibata 393011Samorita * All rights reserved. 493011Samorita * 593011Samorita * Redistribution and use in source and binary forms, with or without 693011Samorita * modification, are permitted provided that the following conditions 793011Samorita * are met: 893011Samorita * 1. Redistributions of source code must retain the above copyright 993011Samorita * notice, this list of conditions and the following disclaimer 1093011Samorita * in this position and unchanged. 1193011Samorita * 2. Redistributions in binary form must reproduce the above copyright 1293011Samorita * notice, this list of conditions and the following disclaimer in the 1393011Samorita * documentation and/or other materials provided with the distribution. 1493011Samorita * 3. The name of the author may not be used to endorse or promote products 1593011Samorita * derived from this software without specific prior written permission. 1693011Samorita * 1793011Samorita * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1893011Samorita * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1993011Samorita * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2093011Samorita * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2193011Samorita * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2293011Samorita * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2393011Samorita * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2493011Samorita * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2593011Samorita * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2693011Samorita * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2793011Samorita * 2893011Samorita * $FreeBSD$ 2993011Samorita */ 3093011Samorita 3193011Samorita#include <sys/param.h> 3293011Samorita#include <sys/systm.h> 3393011Samorita#include <sys/kernel.h> 3493011Samorita#include <sys/module.h> 3593011Samorita#include <sys/syslog.h> 3693011Samorita#include <sys/consio.h> 3793011Samorita#include <sys/fbio.h> 3893011Samorita 3993011Samorita#include <sys/random.h> 4093011Samorita 4193011Samorita#include <dev/fb/fbreg.h> 4293011Samorita#include <dev/fb/splashreg.h> 4393011Samorita#include <dev/syscons/syscons.h> 4493011Samorita 4593011Samorita#define SAVER_NAME "dragon_saver" 4693011Samorita 4793011Samoritastatic u_char *vid; 4893011Samoritastatic int blanked; 4993011Samorita 5093011Samorita#ifdef PC98 5193011Samorita#define VIDEO_MODE M_PC98_EGC640x400 5293011Samorita#define VIDEO_MODE_NAME "M_PC98_EGC640x400" 5393011Samorita#define SCRW 640 5493011Samorita#define SCRH 400 5593011Samorita#else 5693011Samorita#define VIDEO_MODE M_VGA_CG320 5793011Samorita#define VIDEO_MODE_NAME "M_VGA_CG320" 5893011Samorita#define SCRW 320 5993011Samorita#define SCRH 200 6093011Samorita#endif 6193011Samorita#define ORDER 13 6293011Samorita#define CURVE 3 6393011Samorita#define OUT 100 6493011Samorita 6593011Samoritastatic int cur_x, cur_y; 6693011Samoritastatic int curve; 6793011Samoritastatic u_char dragon_pal[3*256]; /* zero-filled by the compiler */ 6893011Samorita 6993011Samoritastatic __inline int 7093011Samoritagpset(int x, int y, int val) 7193011Samorita{ 7293011Samorita if (x < 0 || y < 0 || SCRW <= x || SCRH <= y) { 7393011Samorita return 0; 7493011Samorita } 7593011Samorita#ifdef PC98 7693011Samorita vid[(x + y * SCRW) >> 3] = (0x80 >> (x & 7)); /* write new dot */ 7793011Samorita#else 7893011Samorita vid[x + y * SCRW] = val; 7993011Samorita#endif 8093011Samorita return 1; 8193011Samorita} 8293011Samorita 8393011Samoritastatic int 8493011Samoritagdraw(int dx, int dy, int val) 8593011Samorita{ 8693011Samorita int i; 8793011Samorita int set = 0; 8893011Samorita 8993011Samorita#ifdef PC98 9093011Samorita outb(0x7c, 0xcc); /* GRCG on & RMW mode(disable planeI,G) */ 9193011Samorita outb(0x7e, (val & 1) ? 0xff: 0); /* tile B */ 9293011Samorita outb(0x7e, (val & 2) ? 0xff: 0); /* tile R */ 9393011Samorita#endif 9493011Samorita if (dx != 0) { 9593011Samorita i = cur_x; 9693011Samorita cur_x += dx; 9793011Samorita if (dx < 0) { 9893011Samorita i += dx; 9993011Samorita dx = -dx; 10093011Samorita } 10193011Samorita /* horizontal line */ 10293011Samorita for (; dx >= 0; --dx, ++i) { 10393011Samorita set |= gpset(i, cur_y, val); 10493011Samorita } 10593011Samorita } 10693011Samorita else { /* dy != 0 */ 10793011Samorita i = cur_y; 10893011Samorita cur_y += dy; 10993011Samorita if (dy < 0) { 11093011Samorita i += dy; 11193011Samorita dy = -dy; 11293011Samorita } 11393011Samorita /* vertical line */ 11493011Samorita for (; dy >= 0; --dy, ++i) { 11593011Samorita set |= gpset(cur_x, i, val); 11693011Samorita } 11793011Samorita } 11893011Samorita#ifdef PC98 11993011Samorita outb(0x7c, 0); /* GRCG off */ 12093011Samorita#endif 12193011Samorita return set; 12293011Samorita} 12393011Samorita 12493011Samoritastatic void 12593011Samoritadragon_update(video_adapter_t *adp) 12693011Samorita{ 12793011Samorita static int i, p, q; 12893011Samorita static int order, mul, out; 12993011Samorita static int org_x, org_y; 13093011Samorita static int dx, dy; 13193011Samorita static unsigned char fold[1 << (ORDER - 3)]; 13293011Samorita#define GET_FOLD(x) (fold[(x) >> 3] & (1 << ((x) & 7))) 13393011Samorita#define SET_FOLD(x) (fold[(x) >> 3] |= (1 << ((x) & 7))) 13493011Samorita#define CLR_FOLD(x) (fold[(x) >> 3] &= ~(1 << ((x) & 7))) 13593011Samorita int tmp; 13693011Samorita 13793011Samorita if (curve > CURVE) { 138174985Swkoszek vidd_clear(adp); 13993011Samorita 14093011Samorita /* set palette of each curves */ 14193011Samorita for (tmp = 0; tmp < 3*CURVE; ++tmp) { 14293011Samorita dragon_pal[3+tmp] = (u_char)random(); 14393011Samorita } 144174985Swkoszek vidd_load_palette(adp, dragon_pal); 14593011Samorita 14693011Samorita mul = ((random() & 7) + 1) * (SCRW / 320); 14793011Samorita org_x = random() % SCRW; org_y = random() % SCRH; 14893011Samorita 14993011Samorita curve = 0; 15093011Samorita order = ORDER; 15193011Samorita } 15293011Samorita 15393011Samorita if (order >= ORDER) { 15493011Samorita ++curve; 15593011Samorita 15693011Samorita cur_x = org_x; cur_y = org_y; 15793011Samorita 15893011Samorita switch (curve) { 15993011Samorita case 1: 16093011Samorita dx = 0; dy = mul; 16193011Samorita break; 16293011Samorita case 2: 16393011Samorita dx = mul; dy = 0; 16493011Samorita break; 16593011Samorita case 3: 16693011Samorita dx = 0; dy = -mul; 16793011Samorita break; 16893011Samorita } 16993011Samorita (void)gdraw(dx, dy, curve); out = 0; 17093011Samorita 17193011Samorita order = 0; 17293011Samorita q = p = 0; i = q + 1; 17393011Samorita } 17493011Samorita 17593011Samorita if (i > q) { 17693011Samorita SET_FOLD(p); q = p * 2; 17793011Samorita 17893011Samorita ++order; 17993011Samorita i = p; p = q + 1; 18093011Samorita } 18193011Samorita 18293011Samorita if (GET_FOLD(q-i) != 0) { 18393011Samorita CLR_FOLD(i); 18493011Samorita tmp = dx; dx = dy; dy = -tmp; /* turn right */ 18593011Samorita } 18693011Samorita else { 18793011Samorita SET_FOLD(i); 18893011Samorita tmp = dx; dx = -dy; dy = tmp; /* turn left */ 18993011Samorita } 19093011Samorita if (gdraw(dx, dy, curve)) { 19193011Samorita out = 0; 19293011Samorita } 19393011Samorita else { 19493011Samorita if (++out > OUT) { 19593011Samorita order = ORDER; /* force to terminate this curve */ 19693011Samorita } 19793011Samorita } 19893011Samorita ++i; 19993011Samorita} 20093011Samorita 20193011Samoritastatic int 20293011Samoritadragon_saver(video_adapter_t *adp, int blank) 20393011Samorita{ 20493011Samorita int pl; 20593011Samorita 20693011Samorita if (blank) { 20793011Samorita /* switch to graphics mode */ 20893011Samorita if (blanked <= 0) { 20993011Samorita pl = splhigh(); 210174985Swkoszek vidd_set_mode(adp, VIDEO_MODE); 21193011Samorita vid = (u_char *)adp->va_window; 21293011Samorita curve = CURVE + 1; 21393011Samorita ++blanked; 21493011Samorita splx(pl); 21593011Samorita } 21693011Samorita 21793011Samorita /* update display */ 21893011Samorita dragon_update(adp); 21993011Samorita } 22093011Samorita else { 22193011Samorita blanked = 0; 22293011Samorita } 22393011Samorita return 0; 22493011Samorita} 22593011Samorita 22693011Samoritastatic int 22793011Samoritadragon_init(video_adapter_t *adp) 22893011Samorita{ 22993011Samorita video_info_t info; 23093011Samorita 23193011Samorita /* check that the console is capable of running in 320x200x256 */ 232174985Swkoszek if (vidd_get_info(adp, VIDEO_MODE, &info)) { 23393011Samorita log(LOG_NOTICE, 23493011Samorita "%s: the console does not support " VIDEO_MODE_NAME "\n", 23593011Samorita SAVER_NAME); 23693011Samorita return ENODEV; 23793011Samorita } 23893011Samorita 23993011Samorita blanked = 0; 24093011Samorita return 0; 24193011Samorita} 24293011Samorita 24393011Samoritastatic int 24493011Samoritadragon_term(video_adapter_t *adp) 24593011Samorita{ 24693011Samorita return 0; 24793011Samorita} 24893011Samorita 24993011Samoritastatic scrn_saver_t dragon_module = { 25093011Samorita SAVER_NAME, 25193011Samorita dragon_init, 25293011Samorita dragon_term, 25393011Samorita dragon_saver, 25493011Samorita NULL, 25593011Samorita}; 25693011Samorita 25793011SamoritaSAVER_MODULE(dragon_saver, dragon_module); 258