%% image penguins.pcx 640 480 %% font font_10x20 fixed_10x20 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % Configuration script for the "Penguins" boot screen. % % Copyright (C) 2001-2002, Raphael Quinet % % This program is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2 of the License, or % (at your option) any later version. % % This program is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with this program; if not, write to the Free Software % Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. % % Revision history: % 2001-11-15 - (xray-blue.config) file derived from xray-green.config % 2002-01-04 - file derived from xray-blue.config % 2002-01-05 - keystrokes can influence penguins, added timeout message % 2002-01-10 - adjusted the speed of the penguins % % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % This script is based on those included in SuSE 7.2 and SuSE 7.3, modified % by Raphael Quinet. The walking penguins were extracted from the program % "xpenguins" (http://xpenguins.seul.org/), which had borrowed them from the % game "Pingus" (http://pingus.seul.org/). The original "walker" was created % by Joel Fauche , the "tumbler" was created by Craig % Timpany , the "reader" and the "superpenguin" were % created by Rob Gietema , Robin Hogan % and Brian Chu . % % Requires a patched version of lilo (version 21.6 or greater) that supports % graphical boot screens and callbacks for events. For more information, see: % http://www.gamers.org/~quinet/lilo/. % % Use mkbootmsg to compile this script: % /usr/sbin/mkbootmsg -c penguins.config penguins.boot % Make sure that the image file and the font file listed at the top of this % script are available when you run mkbootmsg. % % To install it and use it as a new boot screen, copy it in /boot (as root): % cp penguins.boot /boot % then insert the following line in /etc/lilo.conf: % message = /boot/penguins.boot % and finally run lilo to install it: % /sbin/lilo -v % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % some useful constants % % some key codes /keyEsc 0x011b def /keyEnter 0x1c0d def /keyUp 0x4800 def /keyDown 0x5000 def /keyPgUp 0x4900 def /keyPgDown 0x5100 def /keyF1 0x3b00 def /keyF2 0x3c00 def /keyF3 0x3d00 def /keyF4 0x3e00 def /keyF5 0x3f00 def /keyF6 0x4000 def /keyF7 0x4100 def /keyF8 0x4200 def /keyF9 0x4300 def /keyF10 0x4400 def /keyStatus 0xff00 def /statusAlt 0x0208 def /statusCtrl 0x0104 def /statusShift 0x0003 def % bios fonts /vga_8x8 1 def /vga_8x12 3 def /vga_8x16 5 def /true 0 0 eq def /false 0 0 ne def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % Compatibility with SuSE 7.2 (rmoveto was not supported in older mkbootmsg) % % ( dx dy ) => ( ) % /myrmoveto { currentpoint rot add rot rot add exch moveto } def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % input event handling % % ( key ) ==> ( input_buffer action ) % % key % bit 0-7 ascii % bit 8-15 scan code % bit 16-32 status bits (ctrl, shift...) % % action % 0: ok, stay in input loop % 1: switch to text mode % 2: start linux % /KeyEvent { % timeout dup 0 eq { boot.ed 3 get 2 return } if dup 0xffff and /key exch def 16 shr 0xffff and /keystat exch def infobox.active { "" 3 return } if password.active { password.ed 3 get key keyEsc eq { 3 return } if key keyEnter eq { 3 return } if infobox.text.normal setcolor password.ed key edit.input 0 return } if % text buffer boot.ed 3 get key 0 eq { 0 return } if key keyEsc eq { 1 return } if key keyEnter eq { 2 return } if % any key reverses the direction of the walking X-Mas penguin /penguin.xmas.dx penguin.xmas.dx neg def % F1 calls the super penguin key keyF1 eq { penguin.fall.y 0 le penguin.super.frame 0 lt and { /penguin.super.frame 0 def /penguin.fall.y penguin.fall.ymax def } if } if % F2 causes the walking penguin to start reading key keyF2 eq { /penguin.read.timer -200 def } if % F3 reverses the direction of the walking penguin key keyF3 eq { /penguin.walk.dx penguin.walk.dx neg def } if key keyUp eq { menu.entry 0 gt { menu.entry 0 MenuSelect menu.entry menu.shift eq { /menu.shift menu.shift 1 sub def redrawmenu } if /menu.entry menu.entry 1 sub def menu.entry 1 MenuSelect boot.text.color setcolor boot.ed edit.hidecursor boot.ed menu.texts menu.entry get edit.init boot.ed ' ' edit.input } if 0 return } if key keyDown eq { menu.entry menu.texts length 1 sub lt { menu.entry 0 MenuSelect menu.visible.entries menu.entry menu.shift sub sub 1 eq { /menu.shift menu.shift 1 add def redrawmenu } if /menu.entry menu.entry 1 add def menu.entry 1 MenuSelect boot.text.color setcolor boot.ed edit.hidecursor boot.ed menu.texts menu.entry get edit.init boot.ed ' ' edit.input } if 0 return } if key keyPgUp eq { menu.entry 0 gt { menu.entry 0 MenuSelect /menu.entry 0 def menu.shift 0 ne { /menu.shift 0 def redrawmenu } if menu.entry 1 MenuSelect boot.text.color setcolor boot.ed edit.hidecursor boot.ed menu.texts menu.entry get edit.init boot.ed ' ' edit.input } if 0 return } if key keyPgDown eq { menu.entry menu.texts length 1 sub lt { menu.entry 0 MenuSelect /menu.entry menu.texts length 1 sub def menu.texts length menu.visible.entries sub dup menu.shift ne { /menu.shift exch def redrawmenu } { pop } ifelse menu.entry 1 MenuSelect boot.text.color setcolor boot.ed edit.hidecursor boot.ed menu.texts menu.entry get edit.init boot.ed ' ' edit.input } if 0 return } if boot.text.color setcolor boot.ed key edit.input 0 } def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % ( array defaultentry ) == > ( ) /MenuInit { /menu.dentry exch def /menu.texts exch def /menu.shift 0 def /menu.visible.entries menu.texts length menu.max.entries min def % get index of default entry /menu.entry 0 def 0 1 menu.texts length 1 sub { dup menu.texts exch get menu.dentry eq { /menu.entry exch def exit } { pop } ifelse } for menu.entry menu.visible.entries sub 0 ge { /menu.shift menu.entry menu.texts length menu.visible.entries sub min def } if -1 -1 0 fillmode frame.fill1.color setcolor % draw a scrollbar if necessary menu.visible.entries menu.texts length lt { -1 -1 0 fillmode -1 settransparentcolor scrollbar.color setcolor scrollbar.pos moveto scrollbar.size fillrect % the two arrows are hidden below the screen at (630, 540) and (630, 557) scrollbar.pos moveto 630 540 10 13 image scrollbar.pos scrollbar.size exch pop add 13 sub moveto 630 557 10 13 image scrollbar.pos moveto frame.color dup scrollbar.size drawborder /menu.sb.x scrollbar.pos pop 1 add def /menu.sb.y scrollbar.pos exch pop 13 add def /menu.sb.width scrollbar.size pop 2 sub def /menu.sb.height scrollbar.size exch pop 26 sub def menu.sb.x menu.sb.y 1 sub moveto menu.sb.x menu.sb.width add menu.sb.y 1 sub lineto menu.sb.x menu.sb.y menu.sb.height add moveto menu.sb.x menu.sb.width add menu.sb.y menu.sb.height add lineto } if boot.options.color setcolor boot.options.pos moveto "Boot options:" show /boot.ed [ boot.text.pos exch 10 add exch 2 add over over moveto boot.ed.width boot.ed.height savescreen boot.buf boot.buf.size 0 0 0 ] def boot.text.color setcolor boot.ed menu.texts menu.entry get edit.init boot.ed ' ' edit.input redrawmenu menu.entry 1 MenuSelect % display the box "Hit any key to cancel timeout" msg.timeout.x msg.timeout.y moveto msg.timeout.src.x msg.timeout.src.y msg.timeout.src.w msg.timeout.src.h image } def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % ( ) == > ( ) % /redrawmenu { % draw a scrollbar if necessary menu.visible.entries menu.texts length lt { /menu.vsb.height1 menu.shift menu.sb.height mul menu.texts length div def /menu.vsb.height3 menu.texts length menu.visible.entries menu.shift add sub menu.sb.height mul menu.texts length div def -1 -1 0 fillmode scrollbar.color setcolor menu.sb.x menu.sb.y menu.vsb.height1 add moveto menu.sb.width menu.sb.height menu.vsb.height1 menu.vsb.height3 add sub fillrect menu.vsb.height1 0 ne { menu.sb.x menu.sb.y moveto currentpoint menu.sb.width menu.vsb.height1 image } if menu.vsb.height3 0 ne { menu.sb.x menu.sb.y menu.sb.height menu.vsb.height3 sub add moveto currentpoint menu.sb.width menu.vsb.height3 image } if } if menu.text.normal setcolor /x menu.start.x def /y menu.start.y def 0 1 menu.visible.entries 1 sub { x y moveto x y menu.bar.width menu.bar.height image x menu.text.xofs add y menu.text.yofs add moveto menu.texts exch menu.shift add get menuitemmap show /y y menu.item.height add def } for } def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % ( entry status ) ==> ( ) % % status: % 0 not selected % 1 selected % /MenuSelect { /menu.status exch def /menu.idx over def menu.shift sub menu.item.height mul menu.start.y add menu.start.x exch moveto -1 -1 0 fillmode currentpoint menu.status 0 eq { currentpoint menu.bar.width menu.bar.height image } { menu.bar.color setcolor menu.bar.width menu.bar.height fillrect } ifelse moveto menu.text.xofs menu.text.yofs myrmoveto menu.status 0 eq { menu.text.normal } { menu.text.select } ifelse setcolor menu.texts menu.idx get menuitemmap show } def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % ( text errorcode ) ==> ( ) % errorcode: % 0 normal info % 1 fatal error % /InfoBoxInit { /infobox.active true def 0 eq { "Press a key to continue." } { "Press a key to reboot." } ifelse /infobox.ktext exch def /infobox.text exch def /infobox.width infobox.ktext strsize pop infobox.text strsize pop max 40 add def /infobox.height infobox.ktext strsize exch pop infobox.text strsize exch pop add 40 add def /infobox.x screen.size pop infobox.width sub 2 div def infobox.x infobox.y moveto /infobox.save infobox.width infobox.height savescreen def infobox.bg setcolor -1 -1 0 fillmode infobox.width infobox.height fillrect white black infobox.width infobox.height drawborder infobox.text.normal setcolor infobox.text infobox.x 20 add infobox.y 13 add moveto show infobox.x infobox.width infobox.ktext strsize pop sub 2 div add infobox.y infobox.height add infobox.ktext strsize exch pop sub 10 sub moveto currentpoint infobox.ktext show exch pop 7 sub infobox.x 35 add exch 6 { over } repeat frame.darkcolor setcolor moveto exch infobox.width 70 sub add exch lineto frame.lightcolor setcolor 1 add moveto 1 add exch infobox.width 70 sub add exch lineto } def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % ( ) ==> ( ) /InfoBoxDone { /infobox.active false def infobox.x infobox.y moveto infobox.save dup restorescreen free /infobox.save 0 def } def /infobox.active false def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % Timeout is called 18.2 times per second until the timeout occurs % (time counts down from timeout to 0). % % ( timeout time ) ==> ( ) % /Timeout { dup 0 gt { % falling penguin (timeout) % draw the penguin over sub neg penguin.fall.ymax mul exch div /penguin.fall.y over def penguin.fall.x exch moveto penguin.fall.src.x penguin.fall.frame penguin.fall.src.w mul add penguin.fall.src.y penguin.fall.src.w penguin.fall.src.h image % next frame /penguin.fall.frame penguin.fall.frame 1 add dup penguin.fall.frmax ge { pop 0 } if def } { % end of timeout pop pop % hide the box "Hit any key to cancel timeout" msg.timeout.x msg.timeout.y moveto msg.timeout.x msg.timeout.y msg.timeout.src.w msg.timeout.src.h image % the flying penguin takes off /penguin.super.frame 0 def } ifelse } def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % Timer is called 18.2 times per second (regardless of timeout) % It is used to animate several elements by copying hidden parts of % the image onto the screen. % % ( time ) ==> ( ) % /Timer { 2 mod 0 eq { % --- walking penguin (at the bottom of the screen) % for the read timer, add 2 + index of menu entry penguin.read.timer 2 add menu.entry add /penguin.read.timer over def 0 lt { % the penguin is reading, not walking penguin.walk.x penguin.walk.y moveto penguin.read.src.x penguin.read.frame penguin.walk.src.w mul add penguin.read.src.y penguin.walk.src.w penguin.walk.src.h image % next frame /penguin.read.frame penguin.read.frame 1 add dup penguin.read.frmax ge { pop 0 } if def } { % unfortunately, I didn't leave enough room between the frames at the % bottom of the screen, so some pixels are not correctly erased during % the animation if dx > 3 ==> it is necessary to copy an empty part % of the image over that area in order to erase these remaining bits penguin.walk.dx 0 ge { penguin.walk.x 2 sub penguin.walk.y moveto } { penguin.walk.x penguin.walk.src.w add 1 sub penguin.walk.y moveto } ifelse penguin.walk.src.x penguin.walk.src.y 2 penguin.walk.src.h image % draw the penguin penguin.walk.x penguin.walk.y moveto penguin.walk.src.x penguin.walk.frame penguin.walk.src.w mul add penguin.walk.src.y penguin.walk.dx 0 ge { penguin.walk.src.h add } if penguin.walk.src.w penguin.walk.src.h image % next frame /penguin.walk.frame penguin.walk.frame 1 add dup penguin.walk.frmax ge { pop 0 } if def % move the penguin /penguin.walk.x penguin.walk.x penguin.walk.dx add def penguin.walk.x penguin.walk.xmax gt penguin.walk.x penguin.walk.xmin lt or { /penguin.walk.dx penguin.walk.dx neg def /penguin.walk.x penguin.walk.x penguin.walk.dx add def } if penguin.read.timer 600 gt { /penguin.read.timer -200 def } if } ifelse } { % --- walking X-Mas penguin (on top of the menu) % draw the penguin penguin.xmas.x penguin.xmas.y moveto penguin.xmas.src.x penguin.xmas.frame penguin.xmas.src.w mul add penguin.xmas.dx 0 lt { penguin.xmas.src.y } { penguin.xmas.src.y penguin.xmas.src.h add } ifelse penguin.xmas.src.w penguin.xmas.src.h image % next frame /penguin.xmas.frame penguin.xmas.frame 1 add dup penguin.xmas.frmax ge { pop 0 } if def % move the penguin /penguin.xmas.x penguin.xmas.x penguin.xmas.dx add def penguin.xmas.x penguin.xmas.xmax gt penguin.xmas.x penguin.xmas.xmin lt or { /penguin.xmas.dx penguin.xmas.dx neg def /penguin.xmas.x penguin.xmas.x penguin.xmas.dx add def % allow the other to resume walking if it is currently reading penguin.read.timer -30 lt { /penguin.read.timer -30 def } if } if } ifelse % --- flying super penguin (replaces the falling penguin when frame >= 0) penguin.super.frame 0 ge { % draw the penguin penguin.fall.x penguin.fall.y moveto penguin.super.src.x penguin.super.src.y penguin.super.frame penguin.super.src.h mul add penguin.super.src.w penguin.super.src.h image % next frame /penguin.super.frame penguin.super.frame 1 add dup penguin.super.frmax ge { pop 0 } if def % move the penguin /penguin.fall.y penguin.fall.y penguin.super.dy add def penguin.fall.y 0 le { /penguin.super.frame -1 def % restore the original image where the penguin was penguin.fall.x 0 moveto penguin.fall.x 0 penguin.fall.src.w penguin.fall.ymax image } if } if } def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % ( label correct_password ) ==> ( ) % /PasswordInit { /password.key exch def pop /password.active true def password.x password.y moveto /password.save password.width password.height savescreen def infobox.bg setcolor -1 -1 0 fillmode password.width password.height fillrect white black password.width password.height drawborder infobox.text.normal setcolor password.x 20 add password.y 20 add moveto "Password: " show currentpoint exch 10 add exch over 1 sub over 2 sub moveto black white password.ed.width password.ed.height 4 add drawborder moveto infobox.text.normal setcolor /password.ed [ currentpoint password.ed.width password.ed.height savescreen password.buf password.buf.size 0 0 0 ] def % show only '*' currentfont 0x80 or setfont password.ed "" edit.init } def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % ( password ) ==> ( error ) % % error: % true password ok % false wrong password % /PasswordDone { /password.active false def % make font visible again currentfont 0x7f and setfont password.x password.y moveto password.save dup restorescreen free password.key eq } def /password.active false def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % Map the name of the menu item to a fancier name if possible. % % ( text ) == > ( new_text ) % /menuitemmap { dup "linux" eq { pop "Linux" return } if dup "failsafe" eq { pop "Linux - Safe Settings" return } if dup "textmode" eq { pop "Linux - Text Mode" return } if dup "oldlinux" eq { pop "Old Linux" return } if dup "test" eq { pop "Test" return } if dup "suse" eq { pop "SuSE" return } if dup "redhat" eq { pop "Red Hat" return } if dup "debian" eq { pop "Debian" return } if dup "dos" eq { pop "MS-DOS" return } if dup "esoe" eq { pop "Windows - ESOE" return } if dup "esde" eq { pop "Windows - ESDE" return } if dup "windows" eq over "win" eq or { pop "Windows" return } if dup "windows95" eq over "win95" eq or { pop "Windows 95" return } if dup "windows98" eq over "win98" eq or { pop "Windows 98" return } if dup "windowsme" eq over "winme" eq or { pop "Windows ME" return } if dup "windowsnt" eq over "winnt" eq or { pop "Windows NT" return } if dup "windows2k" eq over "win2k" eq or { pop "Windows 2000" return } if dup "windows2000" eq over "win2000" eq or { pop "Windows 2000" return } if dup "windowsxp" eq over "winxp" eq or { pop "Windows XP" return } if dup "memtest86" eq over "memtest" eq or { pop "Memory Test" return } if } def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % ( color0 color1 width height ) ==> ( ) /drawborder { currentpoint /db.y0 exch def /db.x0 exch def /db.y1 exch 1 sub db.y0 add def /db.x1 exch 1 sub db.x0 add def /db.col1 exch def /db.col0 exch def db.x0 db.y1 moveto db.col0 setcolor db.x0 db.y0 lineto db.x1 db.y0 lineto db.col1 setcolor db.x1 db.y1 lineto db.x0 db.y1 lineto } def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % allocate and define a new color % ( palette ) ==> ( color ) /newcolor { image.colors newcolor.count add dup rot setpalette /newcolor.count newcolor.count 1 add def def } def /newcolor.count 0 def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - loadpalette 0 0 moveto 0 0 screen.size image font_10x20 1 add setfont /menu.text.xofs 10 def /menu.text.yofs 2 def /menu.item.height fontsize exch pop dup 2 div add def /infobox.y 160 def /black 0x000000 newcolor /white 0xffffff newcolor /menu.text.normal white def /menu.text.select white def /menu.bar.color 0x14c8dc newcolor /scrollbar.color menu.bar.color def /frame.color 0x636363 newcolor /frame.fill1.color 0xb5b5c6 newcolor /frame.fill2.color frame.color def /frame.darkcolor 0xb5b5a5 newcolor /frame.lightcolor 0xd6d6c6 newcolor /infobox.bg frame.fill1.color def /infobox.text.normal black def /boot.options.color white def /boot.text.color menu.bar.color def /menu.start.x 181 def /menu.start.y 119 def /menu.bar.width 279 def /menu.bar.height fontsize exch pop menu.text.yofs dup add add def /menu.max.entries 7 def /scrollbar.pos { 465 99 } def /scrollbar.size { 10 241 } def /boot.options.pos { 10 450 } def /boot.text.pos { 120 447 } def /boot.ed.width 435 def /boot.ed.height fontsize exch pop 2 add def /boot.buf.size 100 def /boot.buf boot.buf.size malloc def /password.width 250 def /password.height 60 def /password.y 200 def /password.x screen.size pop password.width sub 2 div def /password.buf.size 32 def /password.buf password.buf.size malloc def /password.ed.width 120 def /password.ed.height fontsize exch pop 2 add def /msg.timeout.x 490 def /msg.timeout.y 10 def /msg.timeout.src.x 500 def /msg.timeout.src.y 480 def /msg.timeout.src.w 104 def /msg.timeout.src.h 60 def /penguin.walk.xmin 94 def /penguin.walk.xmax 555 def /penguin.walk.x 94 def /penguin.walk.y 402 def /penguin.walk.dx 4 def /penguin.walk.frame 0 def /penguin.walk.frmax 8 def /penguin.walk.src.x 0 def /penguin.walk.src.y 480 def /penguin.walk.src.w 30 def /penguin.walk.src.h 30 def /penguin.read.timer 0 def % if < 0, then the walking penguin is reading /penguin.read.frame 0 def /penguin.read.frmax 4 def /penguin.read.src.x 500 def /penguin.read.src.y 540 def /penguin.xmas.xmin 165 def /penguin.xmas.xmax 445 def /penguin.xmas.x 305 def /penguin.xmas.y 44 def /penguin.xmas.dx -4 def /penguin.xmas.frame 0 def /penguin.xmas.frmax 8 def /penguin.xmas.src.x 240 def /penguin.xmas.src.y 480 def /penguin.xmas.src.w 32 def /penguin.xmas.src.h 44 def /penguin.fall.ymax 394 def % fall from 0 to ymax, speed given by timeout /penguin.fall.x 603 def /penguin.fall.y 0 def /penguin.fall.frame 0 def /penguin.fall.frmax 8 def /penguin.fall.src.x 0 def /penguin.fall.src.y 540 def /penguin.fall.src.w 30 def /penguin.fall.src.h 30 def /penguin.super.dy -4 def % uses x and y from penguin.fall /penguin.super.frame -1 def % if >= 0, then the super penguin is flying /penguin.super.frmax 2 def /penguin.super.src.x 610 def /penguin.super.src.y 480 def /penguin.super.src.w 30 def /penguin.super.src.h 30 def % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -