summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteffen Winterfeldt <wfeldt@opensuse.org>2004-03-15 08:51:06 +0000
committerSteffen Winterfeldt <wfeldt@opensuse.org>2004-03-15 08:51:06 +0000
commit0de4ac28074290e470c2b55e26a0f4cdf232db5c (patch)
treebfecc1aabb297695e8377451f0944c43d45fa6c3
- created repository
-rw-r--r--COPYING341
-rw-r--r--Makefile46
-rw-r--r--README662
-rw-r--r--addblack.c173
-rwxr-xr-xbin/add_text54
-rwxr-xr-xbin/po2h161
-rwxr-xr-xbin/rm_text63
-rwxr-xr-xbin/txt2po179
-rwxr-xr-xbin/txtinc39
-rw-r--r--bin2c.c37
-rw-r--r--bincode.asm10079
-rw-r--r--getx11font.c712
-rwxr-xr-xhelp2txt78
-rwxr-xr-xkeytab80
-rw-r--r--kroete.inc100
-rwxr-xr-xmk_vocabulary144
-rw-r--r--mkbootmsg.c1897
-rw-r--r--modplay.inc1141
-rw-r--r--modplay_defines.inc92
-rw-r--r--themes/SuSE/16x16.fontbin0 -> 6147 bytes
-rw-r--r--themes/SuSE/Makefile54
-rw-r--r--themes/SuSE/background.pcxbin0 -> 16110 bytes
-rw-r--r--themes/SuSE/boot.config26
-rw-r--r--themes/SuSE/bsplash.inc95
-rw-r--r--themes/SuSE/button.inc116
-rw-r--r--themes/SuSE/common.inc1282
-rw-r--r--themes/SuSE/dia_dud.inc59
-rw-r--r--themes/SuSE/dia_help.inc44
-rw-r--r--themes/SuSE/dia_install.inc290
-rw-r--r--themes/SuSE/dia_lang.inc90
-rw-r--r--themes/SuSE/dia_profile.inc139
-rw-r--r--themes/SuSE/dia_splash.inc90
-rw-r--r--themes/SuSE/dia_video.inc192
-rw-r--r--themes/SuSE/happysuse.modbin0 -> 9204 bytes
-rw-r--r--themes/SuSE/help-boot.cs.html113
-rw-r--r--themes/SuSE/help-boot.en.html141
-rw-r--r--themes/SuSE/help-boot.sk.html137
-rw-r--r--themes/SuSE/help-install.en.html404
-rw-r--r--themes/SuSE/help.inc697
-rw-r--r--themes/SuSE/install.config24
-rw-r--r--themes/SuSE/keytables.inc263
-rw-r--r--themes/SuSE/kroete.databin0 -> 16384 bytes
-rw-r--r--themes/SuSE/locale.inc62
-rw-r--r--themes/SuSE/main.inc221
-rw-r--r--themes/SuSE/panel.inc120
-rw-r--r--themes/SuSE/po/Makefile14
-rw-r--r--themes/SuSE/po/README24
-rwxr-xr-xthemes/SuSE/po/bin/add_text54
-rwxr-xr-xthemes/SuSE/po/bin/po2txt154
-rwxr-xr-xthemes/SuSE/po/bin/rm_text63
-rw-r--r--themes/SuSE/po/bootloader.pot229
-rw-r--r--themes/SuSE/po/cs.po244
-rw-r--r--themes/SuSE/po/de.po242
-rw-r--r--themes/SuSE/po/sk.po243
-rw-r--r--themes/SuSE/splash.pcxbin0 -> 28663 bytes
-rw-r--r--themes/SuSE/system.inc263
-rw-r--r--themes/SuSE/window.inc637
-rw-r--r--themes/SuSE/xmenu.inc258
-rwxr-xr-xtst21
-rw-r--r--utf8/UTF-8-demo.txt212
-rw-r--r--utf8/font1
-rw-r--r--utf8/font21
-rw-r--r--utf8/font31
-rw-r--r--utf8/font41
-rw-r--r--utf8/font51
-rw-r--r--utf8/uf11
-rw-r--r--utf8/uf21
-rw-r--r--utf8/uf31
-rw-r--r--utf8/utf_sample1
69 files changed, 23404 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..1609d96
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,341 @@
+----------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1c48b35
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,46 @@
+CC = gcc
+CFLAGS = -g -Wall -O2 -fomit-frame-pointer
+X11LIBS = /usr/X11/lib
+THEMES = $(wildcard themes/*)
+# LIBFILES = happysuse.mod system.inc
+
+.PHONY: all themes clean install
+
+all: bin2c mkbootmsg bincode getx11font addblack
+
+getx11font: getx11font.c
+ $(CC) $(CFLAGS) -L$(X11LIBS) $< -lX11 -o $@
+
+mkbootmsg: mkbootmsg.c vocabulary.h bincode.h
+ $(CC) $(CFLAGS) $< -o $@
+
+addblack: addblack.c
+ $(CC) $(CFLAGS) $< -o $@
+
+bincode: bincode.asm vocabulary.inc modplay_defines.inc modplay.inc kroete.inc
+ nasm -f bin -O10 -o $@ -l $(@).lst $<
+
+bincode.h: bincode bin2c
+ ./bin2c bincode >bincode.h
+
+bin2c: bin2c.c
+ $(CC) $(CFLAGS) $< -o $@
+
+vocabulary.inc: mk_vocabulary
+ ./mk_vocabulary -a >$@
+
+vocabulary.h: mk_vocabulary
+ ./mk_vocabulary -c >$@
+
+install: all
+ install -d -m 755 $(DESTDIR)/usr/sbin $(DESTDIR)/usr/share/gfxboot
+ install -m 755 mkbootmsg getx11font help2txt $(DESTDIR)/usr/sbin
+# install -m 644 $(LIBFILES) $(DESTDIR)/usr/share/gfxboot
+ cp -a themes $(DESTDIR)/usr/share/gfxboot
+
+clean: themes
+ @rm -f mkbootmsg bincode getx11font addblack bincode.h bin2c *.lst vocabulary.inc vocabulary.h *~
+
+themes:
+ @for i in $(THEMES) ; do make -C $$i BINDIR=../../ $(MAKECMDGOALS) ; done
+
diff --git a/README b/README
new file mode 100644
index 0000000..73ae10f
--- /dev/null
+++ b/README
@@ -0,0 +1,662 @@
+Overview
+========
+
+ To make a graphical boot screen you need a PCX image and a config file.
+ Optionally you might want a font file, but that is not really necessary as
+ you can simply use standard BIOS fonts.
+
+ The config file is actually a program written in a Postscript-like
+ language that is run right after the boot manager entered graphics mode.
+ You must program everything related to graphics output in it. That does
+ even include drawing the background picture and setting the palette.
+
+ Font files have a special format. Create them using 'getx11font'.
+
+ The font must not exceed a size of 32x32.
+
+ If you have written a suitable config file, create a syslinux/lilo message file
+ using mkbootmsg:
+
+ mkbootmsg -c my_boot_configfile gfx_bootmessage
+
+ Debugging this config file is rather tedious. In doing so, 'mkbootmsg -v'
+ might give you some information. Or try the 'dtrace' command (see language
+ reference below).
+
+Language Reference
+==================
+
+ Comments start with '%' and extend to the end of line.
+
+ To include some other source file, do:
+
+ %% include file
+
+ Numbers are always 32 bit signed integer. Numerical and string constants
+ are given in a C-like way (_not_ as in Postscript). Examples:
+
+ 123
+ 0x4567
+ "Hi there\n"
+ '\033'
+
+ But: chars have values in the range 0 ... 255.
+
+ Logical operations return values of type 'bool'. They are _not_ identical
+ with integers. There are no pre-defines constants 'true' and 'false'. But
+ you can define them yourself if you need them, e.g.: '/true 0 0 eq def'.
+
+ Variable/constants/function names can consist of everything except
+ whitespace.
+
+ - Callback functions
+ Communication with lilo/syslinux is done via callback functions. You are
+ responsible to assign useful actions to these.
+ See config file examples for more documentation.
+
+ o KeyEvent
+ Called if a key is pressed.
+
+ o MenuInit
+ Should draw the boot menu.
+
+ o InfoBoxInit
+ Show a message box (e.g. error messages).
+
+ o InfoBoxDone
+ Hide the message box.
+
+ o ProgressInit
+ Initialize the progress bar (not yet available in lilo).
+
+ o ProgressDone
+ Hide the progress bar.
+
+ o ProgressUpdate
+ Advance the progress bar.
+
+ o PasswordInit
+ Show password dialog.
+
+ o PasswordDone
+ Hide password dialog.
+
+ o Timeout
+ Timeout counter; called every 18.3th second until the timeout occurs.
+
+ o Timer
+ Called every 18.3th second regardless of timeout.
+
+ - {
+ Start code definition.
+
+ stack: ( ) --> ( proc_1 )
+
+ Example:
+ /f { 10 mul } def
+
+ - }
+ Finish code definition.
+
+ stack: ( ) --> ( )
+
+ Example:
+ /f { 10 mul } def
+
+ - [
+ Start of an array.
+
+ stack: ( ) --> ( array_start )
+
+ Example:
+ [ 1 2 3 ]
+
+ - ]
+ End of an array (completes an array definition).
+
+ stack: ( array_start obj_1 obj_2 ... ) --> ( array_1 )
+ % array_1[0] is obj_1, array_1[1] is obj_2, etc.
+
+ Example:
+ [ 1 2 3 ]
+
+ - abs
+ Absolute value.
+
+ stack: ( int_1 ) --> ( int_2 ) % int_2 = abs(int_1)
+
+ - add
+
+ stack: ( int_1 int_2 ) --> ( int_3 ) % int_3 = int_1 + int_2
+ stack: ( string_1 int_1 ) --> ( string_2 ) % string_2 = string_1 + int_1
+
+ - and
+
+ stack: ( int_1 int_2 ) --> ( int_3 ) % int_3 = int_1 & int_2
+ stack: ( bool_1 bool_2 ) --> ( bool_3 ) % bool_3 = bool_1 && bool_2
+
+ - array
+ Create an empty array.
+
+ stack: ( int_1 ) --> ( array_1 )
+ % array_1 is an array with int_1 elements
+
+ - bootloader
+
+ stack: ( ) --> ( int_1 )
+ % int_1: 0 = lilo, 1 = syslinux
+
+ - currentcolor
+ Returns current drawing color.
+
+ stack: ( ) --> ( int_1 )
+
+ - currentfont
+ Returns current font.
+
+ stack: ( ) --> ( int_1 )
+
+ - currentpoint
+ Return current cursor position.
+
+ stack: ( ) --> ( int_1 int_2 )
+ % int_1: x pos, int_2: y pos
+
+ - def
+ Defines a word.
+
+ stack: ( key value ) --> ( )
+ % key is defined as value
+
+ Examples:
+ % constants
+ /x 55 def
+ % functions
+ /f { 10 mul } def
+
+ - div
+
+ stack: ( int_1 int_2 ) --> ( int_3 ) % int_3 = int_1 / int_2
+
+ - dtrace
+ Turn on trace mode (cf. 'trace') and show debug info in the upper left
+ screen corner (might not be visible on some graphics cards).
+
+ stack: ( ) --> ( )
+
+ - dup
+ Duplicate tos.
+
+ stack: ( obj_1 ) --> ( obj_1 obj_1 )
+
+ - edit.done
+ Restore input field background.
+
+ stack: ( array_1 ) --> ( )
+ % for array_1, see edit.init
+
+ - edit.hidecursor
+ Hide cursor in input field.
+
+ stack: ( array_1 ) --> ( )
+ % for array_1, see edit.init
+
+ - edit.init
+ Setup and show an editable input field.
+
+ stack: ( array_1 string_1 ) --> ( )
+ % the input field is initialized with string_1.
+ % array_1 must be a 8-dimensional array:
+ % [ x_pos, y_pos, screen_area, text_buf, text_buf_size, 0, 0, 0 ]
+ % screen_area holds the background pixmap for the input field and
+ % indirectly determines the size of the field. See 'savescreen' on
+ % how to create such a pixmap.
+ % text_buf is a string and should be large enough to hold
+ % text_buf_size chars.
+ % The last 3 elements are needed internally.
+
+ - edit.input
+ Do some input action.
+
+ stack: ( array_1 int_1 ) --> ( )
+ % for array_1, see edit.init
+ % int_1, bits 15-8: scancode; int_1, bits 7-0: ascii
+
+ - edit.showcursor
+ Show cursor in input field.
+
+ stack: ( array_1 ) --> ( )
+ % for array_1, see edit.init
+
+ - eq
+ Compare.
+
+ stack: ( int_1 int_2 ) --> ( bool_1 ) % bool_1 = int_1 == int_2
+ stack: ( string_1 string_2 ) --> ( bool_1 ) % bool_1 = string_1 eq string_2
+ stack: ( obj_1 obj_2 ) --> ( bool_1 ) % bool_1 = true if obj_1 and obj_2 are identical
+
+ - exch
+ Swap the top two stack elements.
+
+ stack: ( obj_1 obj_2 ) --> ( obj_2 obj_1 )
+
+ - exit
+ Leave loop/repeat/for loops.
+
+ stack: ( ) --> ( )
+ Example:
+ % leave if counter == 56
+ 0 1 100 { 56 eq { exit } if } for
+
+ - fillmode
+ Set fillmode used by 'fillrect'.
+
+ stack: ( int_1 int_2 int_3 ) --> ( )
+ % int_3 == 0: copy
+ % int_3 == 1: add
+ % int_1, int_2 color values
+
+ - fillrect
+ Fill a rectangle; drawing mode is set by 'fillmode'.
+
+ stack: ( int_1 int_2 ) --> ( )
+ % int_1: width, int_2: height.
+
+ - fontsize
+ Returns current fontsize.
+
+ stack: ( ) --> ( int_1 int_2 )
+ % int_1: font width, int_2: font height
+
+ - for
+ Typical 'for' loop.
+
+ stack: ( int_1 int_2 int_3 proc_1 )
+ % int_1: start value, int_2: step size, int_3: end value (inclusive)
+ % every time proc_1 is executed, the current counter is put
+ % on the stack
+
+ Example:
+ 0 1 4 { } for
+ % leaves ( 0 1 2 3 4 ) on the stack
+
+ - free
+ Free malloc'ed memory.
+ Note: memory management is not implemented. You must do it currently all
+ by yourself using 'malloc' and 'free'. Arrays defined via 'array' should
+ also be free'ed. It does not harm, however, to free objects that were not
+ malloc'ed ('free' does nothing, then).
+
+ stack: ( string_1 ) --> ( )
+ stack: ( array_1 ) --> ( )
+
+ - ge
+ Compare.
+
+ stack: ( int_1 int_2 ) --> ( bool_1 ) % bool_1 = int_1 >= int_2
+ stack: ( string_1 string_2 ) --> ( bool_1 ) % bool_1 = string_1 ge string_2
+
+ - get
+ Return a array/string element.
+
+ stack: ( array_1 int_1 ) --> ( obj_1 ) % obj_1 = array_1[int_1]
+ stack: ( string_1 int_1 ) --> ( int_2 ) % int2 = string_1[int_1]
+
+ - getpalette
+ Return palette values for a color.
+
+ stack: ( int_1 ) --> ( int_2 )
+ % int_1: color
+ % int_2: rgb value for color
+ % (bits 23-16 red, bits 15-8 green, bits 7-0 blue)
+
+ - getpixel
+ Read pixel from current drawing position.
+
+ stack: ( ) --> ( int_1 )
+
+ - gt
+ Compare.
+
+ stack: ( int_1 int_2 ) --> ( bool_1 ) % bool_1 = int_1 > int_2
+ stack: ( string_1 string_2 ) --> ( bool_1 ) % bool_1 = string_1 gt string_2
+
+ - if
+ Typical 'if'.
+
+ stack: ( bool_1 proc_1 ) --> ( )
+ % execute proc_1 if bool_1 is true
+
+ Example:
+ 10 4 gt { "Greater!" show } if
+
+ - ifelse
+ Typical 'if'/'else'
+
+ stack: ( bool_1 proc_1 proc_2 )
+ % execute proc_1 if bool_1 is true otherwise proc_2
+
+ Example:
+ 10 4 gt { "Greater!" } { "Smaller!" } show ifelse
+
+ - image
+ Draw part of the image (image was given via '%% image ...').
+
+ stack: ( int_1 int_2 int_3 int_4 ) --> ( )
+ % int_1, int_2: position in image
+ % int_3, int_4: width, height
+
+ Example:
+ % redraw the whole screen
+ 0 0 moveto
+ 0 0 screen.size image
+
+ - image.colors
+ Return number of image colors.
+
+ stack: ( ) --> ( int_1 )
+
+ - le
+ Compare.
+
+ stack: ( int_1 int_2 ) --> ( bool_1 ) % bool_1 = int_1 <= int_2
+ stack: ( string_1 string_2 ) --> ( bool_1 ) % bool_1 = string_1 le string_2
+
+ - length
+ Return array/string size.
+ Note: returns the actual length of the (0 terminated) string, _not_
+ the size of the memory area allocated for it.
+
+ stack: ( array_1 ) --> ( int_1 )
+ stack: ( string_1 ) --> ( int_1 )
+
+ - lineto
+ Draw a line.
+
+ stack: ( int_1 int_2 )
+ % int_1, int_2: x, y line end
+
+ Example:
+ 0 0 moveto
+ 200 100 lineto
+
+ - loadpalette
+ Activate the image palette.
+
+ stack: ( ) --> ( )
+
+ - loop
+ Typical 'loop'.
+
+ stack: ( proc_1 )
+ % proc_1 is executed forever (use 'exit' to break leave it)
+
+ Example:
+ % loop until x == 56
+ /x 0 def { /x x 1 add def x 56 eq { exit } if } loop
+
+ - lt
+ Compare.
+
+ stack: ( int_1 int_2 ) --> ( bool_1 ) % bool_1 = int_1 < int_2
+ stack: ( string_1 string_2 ) --> ( bool_1 ) % bool_1 = string_1 lt string_2
+
+ - malloc
+ Malloc some memory (cf. 'free').
+
+ stack: ( int_1 ) --> ( string_1 )
+ % Note: string_1 is initialized with 0
+
+ - max
+
+ stack: ( int_1 int_2 ) --> ( int_3 ) % int_3 = max(int_1, int_2)
+
+ - min
+
+ stack: ( int_1 int_2 ) --> ( int_3 ) % int_3 = min(int_1, int_2)
+
+ - mod
+
+ stack: ( int_1 int_2 ) --> ( int_3 ) % int_3 = int_1 mod int_2
+
+ - mod.load
+ Asssign mod file to player.
+
+ stack: ( int_1 int_2 ) --> ( )
+ % int_1: player (0 .. 3)
+ % int_2: mod file
+
+ - mod.play
+ Play mod.
+
+ stack: ( int_1 int_2 ) --> ( )
+ % int_1: player (0 .. 3)
+ % int_2: start of song
+
+ - mod.playsample
+
+ stack: ( int_1 int_2 int_3 int_4 ) --> ( )
+ % int_1: player (0 .. 3)
+ % int_2: channel number
+ % int_3: sample number
+ % int_4: pitch
+
+ - moveto
+ Set current drawing position.
+
+ stack ( int_1 int_2 ) --> ( )
+ % int_1, int_2: x, y
+
+ Example:
+ 200 100 moveto
+ "Hello" show
+
+ - mul
+
+ stack: ( int_1 int_2 ) --> ( int_3 ) % int_3 = int_1 * int_2
+
+ - ne
+ Compare.
+
+ stack: ( int_1 int_2 ) --> ( bool_1 ) % bool_1 = int_1 != int_2
+ stack: ( string_1 string_2 ) --> ( bool_1 ) % bool_1 = string_1 ne string_2
+ stack: ( obj_1 obj_2 ) --> ( bool_1 ) % bool_1 = false if obj_1 and obj_2 are identical
+
+ - neg
+
+ stack: ( int_1 ) --> ( int_2 ) % int_2 = -int_1
+
+ - not
+
+ stack: ( bool_1 ) --> ( bool_2 ) % bool_2 = !bool_1
+
+ - or
+
+ stack: ( int_1 int_2 ) --> ( int_3 ) % int_3 = int_1 | int_2
+ stack: ( bool_1 bool_2 ) --> ( bool_3 ) % bool_3 = bool_1 || bool_2
+
+ - over
+
+ stack: ( obj_1 obj_2 ) --> ( obj_1 obj_2 obj_1 )
+
+ - pop
+ Remove tos.
+
+ stack: ( obj_1 ) --> ( )
+
+ - put
+ Set a array/string element.
+ Note: string size is not checked!
+
+ stack: ( array_1 int_1 obj_1 ) --> ( ) % array_1[int_1] = obj_1
+ stack: ( string_1 int_1 int_2 ) --> ( ) % string_1[int_1] = int_2
+
+ - putpixel
+ Set a pixel.
+
+ stack: ( ) --> ()
+
+ - repeat
+ Typical 'repeat'.
+
+ stack: ( int_1 proc_1 )
+ % run proc_1 int_1 times
+
+ Example:
+ % print "XXXXX"
+ 5 { "X" show } repeat
+
+ - restorescreen
+ Restore screen area.
+
+ stack: ( string_1 ) --> ( )
+ % string_1 should be created by 'savescreen'
+
+ - return
+ Leave the current function.
+
+ stack: ( ) --> ( )
+
+ - rmoveto
+ Set current drawing position relative to current position.
+
+ stack ( int_1 int_2 ) --> ( )
+ % int_1, int_2: x, y
+
+ Example:
+ 200 100 rmoveto
+ "Hello" show
+
+ - roll
+ Rotate stack elements.
+
+ stack: ( obj_1 ... obj_n int_1 int_2 ) --> ( obj_1' ... obj_n' )
+ % int_1: number of elements to rotate (== n)
+ % int_2: amount
+ % 1' = (1 + int_2) mod int_1
+ % n' = (n + int_2) mod int_1
+
+ - rot
+ Rotate upper tree stack elements.
+ Equivalent to "3 -1 roll".
+
+ - savescreen
+ Save a screen area.
+
+ stack: ( int_1 int_2 ) --> ( string_1 )
+ % int_1, int_2: width, height
+ % string_1 is automatically malloc'ed but must manually be free'ed
+
+ - screen.size
+ Return screen size.
+
+ stack: ( ) --> ( int_1 int_2 )
+ % int_1, int_2: width, height
+
+ - setcolor
+ Set drawing color.
+
+ stack: ( int_1 ) --> ( )
+ % int_1: color
+
+ - setfont
+ Set text font.
+
+ stack: ( int_1 ) --> ( )
+ % int_1: font
+
+ - setpalette
+ Set palette.
+
+ stack: ( int_1 int_2 ) --> ( )
+ % int_1: color
+ % int_2: rgb value, (bits 23-16 red, bits 15-8 green, bits 7-0 blue)
+
+ - settintcolor
+
+ stack: ( int_1 int_2 ) --> ( )
+ % int_1: rgb value
+
+ - settransparentcolor
+ Set transparent color for 'image' operator.
+
+ stack: ( int_1 ) --> ( )
+ % int_1: color
+
+ - shl
+
+ stack: ( int_1 int_2 ) --> ( int_3 ) % int_3 = int_1 << int_2
+
+ - show
+ Print text.
+
+ stack: ( string_1 ) --> ( );
+ % print string_1
+
+ - shr
+
+ stack: ( int_1 int_2 ) --> ( int_3 ) % int_3 = int_1 >> int_2
+
+ - snprintf
+ C-style snprintf.
+ Note the reversed argument order!
+
+ stack: ( obj_1 ... obj_n string_1 int_1 string_2 ) --> ( )
+
+ Example:
+ /buf 100 malloc def
+ 10 5 "Hi, %d > %d\n" 100 buf snprintf
+ % sets buf to "Hi, 10 > 5\n"
+
+ - sound.done
+ Turn off sound completely.
+
+ stack: ( ) --> ( )
+
+ - sound.getvolume
+ Return current volume.
+
+ stack: ( ) --> ( int_1 )
+
+ - sound.setvolume
+ Set sound volume.
+
+ stack: ( int_1 ) --> ( )
+ % int_1: volume (0 .. 100)
+
+ - strstr
+ Find string_2 in string_1. Returns the offset of string_2 + 1 or 0, if it
+ was not found.
+
+ stack: ( string_1 string_2 ) --> ( int_1 )
+
+ Example:
+ "abcd" "c" strstr
+ % returns 3
+
+ - strsize
+ Returns the size of the string in pixel (using the current font).
+
+ stack: ( string_1 ) --> ( int_1 int_2 )
+ % int_1, int_2: width, height
+
+ - sub
+
+ stack: ( int_1 int_2 ) --> ( int_3 ) % int_3 = int_1 - int_2
+ stack: ( string_1 int_1 ) --> ( string_2 ) % string_2 = string_1 - int_1
+
+ - tint
+
+ stack: ( int_1 int_2 int_3 ) --> ( )
+
+ - trace
+ Enter single step mode. Waits for a keypress after every instruction.
+ Leave this mode by pressing Esc.
+
+ stack: ( ) --> ( )
+
+ - xor
+
+ stack: ( int_1 int_2 ) --> ( int_3 ) % int_3 = int_1 ^ int_2
+ stack: ( bool_1 bool_2 ) --> ( bool_3 ) % bool_3 = bool_1 ^^ bool_2
+
diff --git a/addblack.c b/addblack.c
new file mode 100644
index 0000000..95e793f
--- /dev/null
+++ b/addblack.c
@@ -0,0 +1,173 @@
+/*
+ * add black as color #0 to a pcx file
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <ctype.h>
+
+typedef struct {
+ unsigned size;
+ unsigned char *data;
+ unsigned real_size;
+} file_data_t;
+
+void help(void);
+file_data_t read_file(char *name);
+int is_pcx(file_data_t *fd);
+void write_data(file_data_t *fd, char *name);
+void add_data(file_data_t *d, void *buffer, unsigned size);
+void add_black(file_data_t *new, file_data_t *old);
+
+file_data_t pcx_old = {};
+file_data_t pcx_new = {};
+
+int main(int argc, char **argv)
+{
+ if(argc != 3) return 1;
+
+ pcx_old = read_file(argv[1]);
+
+ if(!is_pcx(&pcx_old)) return 2;
+
+ add_black(&pcx_new, &pcx_old);
+
+ write_data(&pcx_new, argv[2]);
+
+ return 0;
+}
+
+
+file_data_t read_file(char *name)
+{
+ file_data_t fd = { };
+ FILE *f;
+
+ if(!name) return fd;
+
+ f = fopen(name, "r");
+ if(!f) { perror(name); return fd; }
+
+ if(fseek(f, 0, SEEK_END)) {
+ perror(name);
+ exit(30);
+ }
+
+ fd.size = fd.real_size = ftell(f);
+
+ if(fseek(f, 0, SEEK_SET)) {
+ perror(name);
+ exit(30);
+ }
+
+ if(fd.size) {
+ fd.data = malloc(fd.size);
+ if(!fd.data) {
+ fprintf(stderr, "malloc failed\n");
+ exit(30);
+ }
+ }
+
+ if(fread(fd.data, 1, fd.size, f) != fd.size) {
+ perror(name);
+ exit(30);
+ }
+
+ fclose(f);
+
+ return fd;
+}
+
+
+int is_pcx(file_data_t *fd)
+{
+ if(!fd->data || fd->size < 0x381) return 0;
+ if(
+ fd->data[0] != 10 ||
+ fd->data[1] != 5 ||
+ fd->data[2] != 1 ||
+ fd->data[3] != 8 ||
+ fd->data[fd->size - 0x301] != 12
+ ) return 0;
+
+ return 1;
+}
+
+
+void write_data(file_data_t *fd, char *name)
+{
+ FILE *f;
+
+ if(!fd->size) return;
+
+ f = strcmp(name, "-") ? fopen(name, "w") : stdout;
+
+ if(!f) {
+ perror(name);
+ return;
+ }
+
+ if(fwrite(fd->data, fd->size, 1, f) != 1) {
+ perror(name); exit(3);
+ }
+
+ fclose(f);
+}
+
+
+void add_data(file_data_t *d, void *buffer, unsigned size)
+{
+ if(!size || !d || !buffer) return;
+
+ if(d->size + size > d->real_size) {
+ d->real_size = d->size + size + 0x1000;
+ d->data = realloc(d->data, d->real_size);
+ if(!d->data) d->real_size = 0;
+ }
+
+ if(d->size + size <= d->real_size) {
+ memcpy(d->data + d->size, buffer, size);
+ d->size += size;
+ }
+ else {
+ fprintf(stderr, "Oops, out of memory? Aborted.\n");
+ exit(10);
+ }
+}
+
+
+void add_black(file_data_t *new, file_data_t *old)
+{
+ int i, size;
+ unsigned char black[4] = { 12, 0, 0, 0 };
+ unsigned char *src = old->data + 0x80;
+ unsigned char c[1];
+
+ add_data(new, old->data, 0x80);
+ size = old->size - 0x381;
+
+ for(i = 0; i < size; i++) {
+ if(src[i] < 0xbf) {
+ *c = src[i] + 1;
+ add_data(new, c, 1);
+ }
+ else if(src[i] == 0xbf) {
+ *c = 0xc1;
+ add_data(new, c, 1);
+ *c = 0xc0;
+ add_data(new, c, 1);
+ }
+ else {
+ add_data(new, src + i, 1);
+ i++;
+ *c = src[i] + 1;
+ add_data(new, c, 1);
+ }
+ }
+
+ add_data(new, black, 4);
+ add_data(new, old->data + old->size - 0x300, 0x300 - 3);
+}
+
diff --git a/bin/add_text b/bin/add_text
new file mode 100755
index 0000000..61857c7
--- /dev/null
+++ b/bin/add_text
@@ -0,0 +1,54 @@
+#! /usr/bin/perl
+
+# add a new text to *.po files
+
+die "usage: add_text [-c comment] id text_line1 text_line2 ... \nexample:\n add_text MENU_LANG Language\n" if @ARGV < 2;
+
+if($ARGV[0] eq '-c') {
+ shift;
+ $comment = shift;
+}
+
+$id = shift;
+@texts = @ARGV;
+
+$id =~ s/^TXT_//;
+
+$_ = join '', @texts;
+
+push @l, "# $comment\n" if $comment;
+push @l, "#. TXT_$id\n";
+push @l, "#, c-format\n" if /%/;
+
+if(@texts == 1) {
+ push @l, "msgid \"$texts[0]\"\n"
+}
+else {
+ push @l, "msgid \"\"\n";
+ for (@texts) { push @l, "\"$_\"\n" }
+}
+
+push @l, "msgstr \"\"\n";
+push @l, "\n";
+
+print @l;
+
+print STDERR "Should this entry be added to all *.po files? [Y/n]\n";
+
+$_ = <STDIN>;
+
+chomp;
+
+$_ = "\L$_";
+
+exit unless $_ eq '' || $_ eq 'y';
+
+print "ok\n";
+
+for $f ("linuxrc.pot", <*.po>) {
+ if(open F, ">>$f") {
+ print F @l;
+ close F;
+ }
+}
+
diff --git a/bin/po2h b/bin/po2h
new file mode 100755
index 0000000..7184ebd
--- /dev/null
+++ b/bin/po2h
@@ -0,0 +1,161 @@
+#! /usr/bin/perl
+
+# convert *.po files to *.txt files suitable for linuxrc
+# usage: po2h file.po >file.h
+# Note: en.po ist treated specially!
+
+sub read_texts;
+sub join_msg;
+
+for $lang (@ARGV) {
+ $lang = 'en' if $lang eq 'linuxrc.pot';
+ $lang =~ s/\.po$//;
+ read_texts $lang;
+}
+
+
+sub read_texts
+{
+ local $_;
+
+ my ($lang, @f, $txt, $context, $t, $p, $ids, $file);
+
+ $lang = shift;
+
+ $file = "$lang.po";
+ $file = 'linuxrc.pot' if $lang eq 'en';
+
+ if($lang eq 'en') {
+ $ids = 1;
+ }
+
+ open F, $file;
+ @f = (<F>);
+ close F;
+
+ $_ = $lang;
+ s/.*\///;
+ print "/*\n * This file is generated automatically. Editing it is pointless.\n */\n\n";
+ print "static text_t txt_${_}_atm [] =\n{\n";
+
+ for (@f) {
+ if(/^\s*#\.\s*(TXT_\S+)/) {
+ if($txt) {
+ @msgstr = @msgid if $ids || join_msg(\@msgstr) eq "";
+ printf "{ %-25s", "$txt,";
+ $p = pop @msgstr;
+ for $t (@msgstr) {
+ printf "%s\n%-27s", $t, "";
+ }
+ printf "%-56s},\n", $p;
+ }
+
+ $txt = $1;
+
+ push @txts, $txt;
+
+ undef @msgid;
+ undef @msgstr;
+ undef $context;
+ next;
+ }
+
+ next if /^\s*#.*|^\s*$/;
+
+ if(/^\s*msgid\s*(\".*\")\s*$/) {
+ push @msgid, $1 unless $1 eq '""';
+ $context = 1;
+ next;
+ }
+
+ if(/^\s*msgstr\s*(\".*\")\s*$/) {
+ push @msgstr, $1 unless $1 eq '""';
+ $context = 2;
+ next;
+ }
+
+ if(/^\s*(\".*\")\s*$/) {
+ if($context == 1) {
+ push @msgid, $1;
+ }
+ elsif($context == 2) {
+ push @msgstr, $1;
+ }
+ else {
+ die "format oops in ${lang}.po: $_"
+ }
+ }
+ }
+
+ if($txt) {
+ printf "{ %-25s", "$txt,";
+ @msgstr = @msgid if $ids || join_msg(\@msgstr) eq "";
+ $p = pop @msgstr;
+ for $t (@msgstr) {
+ printf "%s\n%-27s", $t, "";
+ }
+ printf "%-56s}\n", $p;
+ }
+
+ print "};\n";
+
+ if($ids) {
+ open W, ">text_textids.h";
+ print W "/*\n * This file is generated automatically. Editing it is pointless.\n */\n\n";
+ print W "enum textid_t {\n";
+ $p = pop @txts;
+ for (@txts) { print W " $_,\n" }
+ print W " $p\n};\n";
+ close W;
+ }
+ else {
+ open F, "text_textids.h";
+ for (<F>) {
+ if(/\s+(TXT_.+?)(\s|,)/) {
+ $txt_ref{$1} = undef;
+ }
+ }
+ close F;
+ for (@txts) {
+ $txt_list{$_}++;
+ $txt_multi{$_} = 1 if $txt_list{$_} > 1;
+ }
+ for (@txts) {
+ $txt_unknown{$_} = 1 unless exists $txt_ref{$_};
+ }
+ for (keys %txt_ref) {
+ $txt_miss{$_} = 1 unless exists $txt_list{$_};
+ }
+
+ if(defined(%txt_miss) || defined(%txt_unknown) || defined(%txt_multi)) {
+ print STDERR "$lang:\n";
+ for (sort keys %txt_miss) {
+ print STDERR " missing: $_\n"
+ }
+ for (sort keys %txt_unknown) {
+ print STDERR " unknown: $_\n"
+ }
+ for (sort keys %txt_multi) {
+ print STDERR " multi: $_\n"
+ }
+ }
+ }
+
+}
+
+
+sub join_msg
+{
+ local $_;
+ my ($s, $msg, $m);
+
+ $msg = shift;
+
+ for $s (@{$msg}) {
+ $_ = $s;
+ s/^\"(.*)\"$/$1/;
+ $m .= $_;
+ }
+
+ return $m;
+}
diff --git a/bin/rm_text b/bin/rm_text
new file mode 100755
index 0000000..c3a871e
--- /dev/null
+++ b/bin/rm_text
@@ -0,0 +1,63 @@
+#! /usr/bin/perl
+
+# remove a text from *.po files
+
+sub drop;
+
+die "usage: rm_text id\n" if @ARGV != 1;
+
+$id = shift;
+$id = "TXT_$id" unless $id =~ /^TXT_/;
+
+mkdir old, 0755;
+
+for $f ("linuxrc.pot", <*.po>) {
+ if(open F, $f) {
+ @f = <F>;
+ close F;
+
+ ( $new, $old ) = drop @f;
+ if(open F, ">>old/$f") {
+ print F @$old;
+ close F;
+
+ open F, ">$f";
+ print F @$new;
+ close F;
+ }
+ }
+}
+
+
+sub drop
+{
+ local $_;
+ my (@f, @g, $drop_it, @d);
+
+ for (@_) {
+ push @g, $_;
+ $drop_it = 1 if /^#\.\s*${id}\s*$/;
+ if(/^\s*$/) {
+ if($drop_it) {
+ push @d, @g;
+ }
+ else {
+ push @f, @g;
+ }
+ undef $drop_it;
+ undef @g;
+ }
+ }
+
+ if(@g) {
+ if($drop_it) {
+ push @d, @g;
+ }
+ else {
+ push @f, @g;
+ }
+ }
+
+ return ( \@f, \@d );
+}
+
diff --git a/bin/txt2po b/bin/txt2po
new file mode 100755
index 0000000..59e3b21
--- /dev/null
+++ b/bin/txt2po
@@ -0,0 +1,179 @@
+#! /usr/bin/perl
+
+# convert old linuxrc *.txt files to *.po files
+
+sub read_texts;
+sub join_msg;
+
+%pmap = (
+ "brasil", "pt_BR",
+ "breton", "br",
+ "czech", "cs",
+ "dutch", "nl",
+ "english", "en",
+ "french", "fr",
+ "german", "de",
+ "greek", "el",
+ "hungarian", "hu",
+ "indonesia", "id",
+ "italian", "it",
+ "polish", "pl",
+ "portuguese", "pt",
+ "romanian", "ro",
+ "russian", "ru",
+ "slovak", "sk",
+ "spanish", "es"
+);
+
+%po2lang = (
+ "pt_BR", "Brasil",
+ "br", "Breton",
+ "cs", "Czech",
+ "nl", "Dutch",
+ "en", "LANGUAGE",
+ "fr", "French",
+ "de", "German",
+ "el", "Hellenic",
+ "hu", "Hungarian",
+ "id", "Indonesian",
+ "it", "Italian",
+ "pl", "Polish",
+ "pt", "Portugese",
+ "ro", "Romanian",
+ "ru", "Russian",
+ "sk", "Slovak",
+ "es", "Spanish"
+);
+
+%po2charset = (
+ "pt_BR", "iso-8859-1",
+ "br", "iso-8859-1",
+ "cs", "iso-8859-2",
+ "nl", "iso-8859-1",
+ "en", "ascii",
+ "fr", "iso-8859-1",
+ "de", "iso-8859-1",
+ "el", "iso-8859-7",
+ "hu", "iso-8859-2",
+ "id", "iso-8859-1",
+ "it", "iso-8859-1",
+ "pl", "iso-8859-2",
+ "pt", "iso-8859-1",
+ "ro", "iso-8859-2",
+ "ru", "koi8-r",
+ "sk", "iso-8859-2",
+ "es", "iso-8859-1"
+);
+
+read_texts "english", 1;
+
+for $lang (@ARGV) {
+ $lang =~ s/\.txt$//;
+ read_texts $lang;
+}
+
+
+sub read_texts
+{
+ local $_;
+
+ my ($lang, @f, %txt, $txt, $t, $ids);
+
+ $lang = shift;
+ $ids = shift;
+
+ open F, "${lang}.txt";
+ @f = (<F>);
+ close F;
+
+ for (@f) {
+ s/^\{?\s*//;
+ next if /^\}|^static|^\s*$/;
+ if(s/^(TXT_\S+?),\s*//) {
+ $txt = $1;
+ push @txts, $txt if $ids;
+ }
+ s/\s*(\},?)?\s*$//;
+ if(!/^\".*\"$/) {
+ die "format error in $lang.txt:\n$txt: >>$_<<\n"
+ }
+ push @{$txt{$txt}}, $_;
+# print "$txt: >>$_<<\n"
+ }
+
+ if($ids) {
+ %txt_en = %txt;
+ }
+ else {
+ $f = $pmap{$lang} ? "$pmap{$lang}.po" : "$lang.po";
+ $f = "linuxrc.pot" if $lang eq 'english';
+ open W, ">$f";
+
+ print W "# $po2lang{$pmap{$lang}} translations for linuxrc.\n";
+ print W "# Copyright (C) 2001 SuSE GmbH.\n#\n";
+ print W "msgid \"\"\n";
+ print W "msgstr \"\"\n";
+ print W "\"Project-Id-Version: linuxrc\\n\"\n";
+ print W "\"PO-Revision-Date: 2001-08-03 12:00+0200\\n\"\n";
+ print W "\"Last-Translator: FULL NAME <EMAIL\@ADDRESS>\\n\"\n";
+ print W "\"Language-Team: $po2lang{$pmap{$lang}} <i18n\@suse.de>\\n\"\n";
+ print W "\"MIME-Version: 1.0\\n\"\n";
+ print W "\"Content-Type: text/plain; charset=$po2charset{$pmap{$lang}}\\n\"\n";
+ print W "\"Content-Transfer-Encoding: 8bit\\n\"\n\n";
+
+ for (@txts) {
+ print W "#. $_\n";
+ $x = join_msg $txt_en{$_};
+ if($x =~ /%/) {
+ print W "#, c-format\n";
+ }
+
+ if(@{$txt_en{$_}} == 1) {
+ print W "msgid ${$txt_en{$_}}[0]\n"
+ }
+ else {
+ print W "msgid \"\"\n";
+ for $t (@{$txt_en{$_}}) {
+ print W "$t\n"
+ }
+ }
+
+ if(join_msg($txt{$_}) eq join_msg($txt_en{$_})) {
+ print W "msgstr \"\"\n";
+ }
+ else {
+ if(@{$txt{$_}} == 1) {
+ print W "msgstr ${$txt{$_}}[0]\n"
+ }
+ else {
+ print W "msgstr \"\"\n";
+ for $t (@{$txt{$_}}) {
+ print W "$t\n"
+ }
+ }
+ }
+ print W "\n"
+ }
+ close W;
+ }
+
+}
+
+
+sub join_msg
+{
+ local $_;
+ my ($s, $msg, $m);
+
+ $msg = shift;
+
+ for $s (@{$msg}) {
+ $_ = $s;
+ s/^\"(.*)\"$/$1/;
+ $m .= $_;
+ }
+
+ return $m;
+}
+
+
diff --git a/bin/txtinc b/bin/txtinc
new file mode 100755
index 0000000..b6395b2
--- /dev/null
+++ b/bin/txtinc
@@ -0,0 +1,39 @@
+#! /usr/bin/perl
+
+# make some include files for linuxrc
+
+map { s/^(.*\/)?([^\/]+)\.po/$2/ } @ARGV;
+
+open W, ">text_inc.h";
+print W "/*\n * This file is generated automatically. Editing it is pointless.\n */\n\n";
+for (@ARGV) {
+ print W "#ifdef TRANS_$_\n#include \"po/$_.h\"\n#endif\n\n"
+}
+close W;
+
+open W, ">text_array.h";
+print W "/*\n * This file is generated automatically. Editing it is pointless.\n */\n\n";
+print W "static alltexts_t alltexts_arm [] = {\n";
+@list = ( "en", grep { $_ ne en} @ARGV);
+
+for ($i = 0 ; $i < @list; $i++) {
+ print W "#ifdef TRANS_$list[$i]\n";
+ print W " { lang_$list[$i], LANG_ENTRY(txt_$list[$i]_atm) },\n";
+ print W "#endif\n"
+}
+print W "};\n";
+close W;
+
+open W, ">text_langids.h";
+print W "/*\n * This file is generated automatically. Editing it is pointless.\n */\n\n";
+print W "/* lang_undef _must_ be 0 */\n\n";
+print W "enum langid_t {\n";
+
+@list = ( "undef", @ARGV );
+for ($i = 0 ; $i < @list; $i++) {
+ print W " lang_$list[$i]";
+ print W $i + 1 == @list ? "\n" : ",\n";
+}
+print W "};\n";
+close W;
+
diff --git a/bin2c.c b/bin2c.c
new file mode 100644
index 0000000..86b836a
--- /dev/null
+++ b/bin2c.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+ int i, j = 0;
+ FILE *f;
+
+ if(argc > 1) {
+ if(!(f = fopen(argv[1], "r"))) {
+ perror(argv[1]);
+ return 1;
+ }
+ }
+ else {
+ fprintf(stderr, "usage: bin2c file\n");
+ return 2;
+ }
+
+ printf("unsigned char %s_data[] = {\n", argv[1]);
+
+ while((i = fgetc(f)) != EOF) {
+ i = i & 0xff;
+ if(!j++) {
+ printf(" ");
+ }
+ else {
+ printf(",%s", (j & 7) != 1 ? "" : "\n ");
+ }
+ printf(" 0x%02x", i);
+ }
+
+ printf("\n};\n");
+
+ return 0;
+}
+
diff --git a/bincode.asm b/bincode.asm
new file mode 100644
index 0000000..935bed4
--- /dev/null
+++ b/bincode.asm
@@ -0,0 +1,10079 @@
+%define debug 1
+
+%include "vocabulary.inc"
+%include "modplay_defines.inc"
+
+; some type definitions from mkbootmsg.c
+; struct file_header_t
+fh_magic_id equ 0
+fh_version equ 4
+fh_res_1 equ 5
+fh_res_2 equ 6
+fh_file_entries equ 7
+fh_bincode equ 8
+fh_bincode_size equ 12
+fh_bincode_crc equ 16
+fh_dict equ 20
+fh_code equ 24
+fh_code_size equ 28
+sizeof_file_header_t equ 32
+
+
+; font file header definition
+; struct font_header_t
+foh_magic equ 0
+foh_entries equ 4
+foh_height equ 6
+foh_line_height equ 7
+sizeof_font_header_t equ 8
+
+; char data header definition
+; struct char_header_t
+ch_ofs equ 0
+ch_c equ 2
+ch_size equ 4
+sizeof_char_header_t equ 8 ; must be 8, otherwise change find_char
+
+; struct file_raw_t
+fi_raw_data equ 0
+fi_raw_size equ 4
+sizeof_file_raw_t equ 8
+
+; struct playlist
+pl_file equ 0 ; actually file index + 1
+pl_loop equ 1
+pl_res1 equ 2
+pl_res2 equ 3
+pl_start equ 4
+pl_current equ 8
+pl_end equ 12
+sizeof_playlist equ 16
+playlist_entries equ 4
+
+; struct link
+li_label equ 0
+li_text equ 2
+li_x equ 4
+li_row equ 6
+sizeof_link equ 8 ; search for 'sizeof_link'!
+link_entries equ 64
+
+; enum_type_t
+t_none equ 0
+t_int equ 1
+t_unsigned equ 2
+t_bool equ 3
+t_string equ 4
+t_code equ 5
+t_ret equ 6
+t_prim equ 7
+t_sec equ 8
+t_dict_idx equ 9
+t_array equ 10
+t_end equ 11
+t_ptr equ 12
+
+t_if equ t_code + 10h
+t_loop equ t_code + 20h
+t_repeat equ t_code + 30h
+t_for equ t_code + 40h
+t_forall equ t_code + 50h
+t_exit equ t_code + 60h
+
+
+param_stack_size equ 1000
+ret_stack_size equ 1000
+
+; various error codes
+pserr_ok equ 0
+pserr_nocode equ 1
+pserr_invalid_opcode equ 2
+pserr_pstack_underflow equ 3
+pserr_pstack_overflow equ 4
+pserr_rstack_underflow equ 5
+pserr_rstack_overflow equ 6
+pserr_invalid_dict equ 7
+pserr_wrong_arg_types equ 8
+pserr_div_by_zero equ 9
+pserr_invalid_rstack_entry equ 0ah
+pserr_invalid_range equ 0bh
+pserr_invalid_exit equ 0ch
+pserr_invalid_image_size equ 0dh
+pserr_no_memory equ 0eh
+pserr_invalid_data equ 0fh
+pserr_nop equ 10h
+pserr_invalid_dict_entry equ 200h
+pserr_invalid_prim equ 201h
+
+keyBS equ 08h
+keyLeft equ 4bh ; scan code
+keyRight equ 4dh ; scan code
+keyHome equ 47h ; scan code
+keyEnd equ 4fh ; scan code
+keyDel equ 53h ; scan code
+
+max_text_rows equ 128
+
+ section .text
+
+; jmp table to interface functions
+jt_init dw gfx_init
+jt_done dw gfx_done
+jt_input dw gfx_input
+jt_menu_init dw gfx_menu_init
+jt_infobox_init dw gfx_infobox_init
+jt_infobox_done dw gfx_infobox_done
+jt_progress_init dw gfx_progress_init
+jt_progress_done dw gfx_progress_done
+jt_progress_update dw gfx_progress_update
+jt_progress_limit dw gfx_progress_limit
+jt_password_init dw gfx_password_init
+jt_password_done dw gfx_password_done
+
+ align 4, db 0
+; the memory area we are working with
+mem dd 0 ; (lin) data start address
+mem_free dd 0 ; (lin) start of free area for malloc
+mem_max dd 0 ; (lin) end address
+mem_archive dd 0 ; (lin) archive start address (0 -> none), ends at mem_free
+
+vbe_buffer dd 0 ; (seg:ofs) buffer for vbe calls
+vbe_mode_list dd 0 ; (seg:ofs) list with vbe modes
+infobox_buffer dd 0 ; (lin) temp buffer for InfoBox messages
+
+pscode_start dd 0 ; (lin)
+pscode_size dd 0
+pscode_instr dd 0 ; (lin) current instruction (rel. to pscode_start)
+pscode_next_instr dd 0 ; (lin) next instruction
+; for debugging only
+pscode_next_break dd 0 ; (lin) break at this instruction
+pscode_eval dd 0 ; opcode from exec instruction
+pscode_error_arg_0 dd 0
+pscode_error_arg_1 dd 0
+pscode_arg dd 0 ; current arg
+pscode_error dw 0 ; error code (if any)
+pscode_type db 0 ; current instr type
+
+ align 4, db 0
+dict dd 0 ; seg:ofs
+dict_size dw 0 ; dict entries
+
+boot_cs dw 0 ; seg
+boot_sysconfig dw 0 ; ofs
+
+pstack dd 0 ; (seg:ofs)
+pstack_size dw 0 ; entries
+pstack_ptr dw 0
+rstack dd 0 ; (seg:ofs)
+rstack_size dw 0 ; entries
+rstack_ptr dw 0
+
+
+image dd 0 ; (lin) current image
+image_width dw 0
+image_height dw 0
+image_data dd 0 ; (seg:ofs)
+image_pal dd 0 ; (seg:ofs)
+image_type db 0 ; 0:no image, 1: pcx, 2:jpeg
+
+pcx_line_starts dd 0 ; (lin) table of line starts
+
+screen_width dw 0
+screen_height dw 0
+screen_line_len dd 0
+
+setpixel dw setpixel_8 ; function that sets one pixel
+setpixel_a dw setpixel_a_8 ; function that sets one pixel
+setpixel_t dw setpixel_8 ; function that sets one pixel
+setpixel_ta dw setpixel_a_8 ; function that sets one pixel
+getpixel dw getpixel_8 ; function that gets one pixel
+
+
+transp dd 0 ; transparency
+
+; 0..100h
+brightness dw 100h
+
+ align 4, db 0
+; current font description
+font dd 0 ; (seg:ofs) to font header
+font_entries dw 0 ; chars in font
+font_height dw 0
+font_line_height dw 0
+
+; current char description
+chr_bitmap dw 0 ; ofs rel. to [font]
+chr_x_ofs dw 0
+chr_y_ofs dw 0
+chr_real_width dw 0
+chr_real_height dw 0
+chr_width dw 0
+
+utf8_buf times 8 db 0
+
+; pointer to currently active palette (3*100h bytes)
+gfx_pal dd 0 ; (seg:ofs)
+; pointer to tmp area (3*100h bytes)
+gfx_pal_tmp dd 0 ; (seg:ofs)
+; number of fixed pal values
+pals dw 0
+
+; the current gfx mode
+gfx_mode dw 3
+; != 0 if we're using a vbe mode (hi byte of gfx_mode)
+vbe_active equ gfx_mode + 1
+pixel_bits db 0 ; pixel size (8 or 16)
+color_bits db 0 ; color bits (8, 15 or 16)
+pixel_bytes dd 0 ; pixel size in bytes
+
+; segment address of writeable window
+window_seg_w dw 0
+; segment address of readable window
+; if 0 -> gfx_window_seg_w is rw
+window_seg_r dw 0
+; ganularity units per window
+window_inc db 0
+; currently mapped window
+mapped_window db 0
+
+; cursor position
+gfx_cur equ $ ; both x & y
+gfx_cur_x dw 0
+gfx_cur_y dw 0 ; must follow gfx_cur_x
+gfx_width dw 0
+gfx_height dw 0
+line_wrap dw 0
+
+; clip region (incl)
+clip_l dw 0 ; left, incl
+clip_r dw 0 ; right, excl
+clip_t dw 0 ; top, incl
+clip_b dw 0 ; bottom, excl
+
+line_x0 dd 0
+line_y0 dd 0
+line_x1 dd 0
+line_y1 dd 0
+line_tmp dd 0
+
+ align 4, db 0
+gfx_color dd 0 ; current color
+gfx_color0 dd 0 ; color #0 (normal color))
+gfx_color1 dd 0 ; color #1 (highlight color)
+gfx_color2 dd 0 ; color #2 (link color)
+gfx_color3 dd 0 ; color #3 (selected link color)
+transparent_color dw -1
+char_eot dd 0 ; 'end of text' char
+last_label dw 0 ; ofs, seg = [row_start_seg]
+page_title dw 0 ; ofs, seg = [row_start_seg]
+max_rows dw 0 ; max. number of text rows
+cur_row dw 0 ; current text row (0 based)
+cur_row2 dw 0 ; dto, only durig formatting
+start_row dw 0 ; start row for text output
+cur_link dw 0 ; link count
+sel_link dw 0 ; selected link
+txt_state db 0 ; bit 0: 1 = skip text
+ ; bit 1: 1 = text formatting only
+run_idle db 0
+
+ align 2, db 0
+row_start_seg dw 0
+row_start_ofs times max_text_rows dw 0
+
+ ; note: link_list relies on row_start_seg
+link_list times sizeof_link * link_entries db 0
+
+; currently used tint color (call load_palette to make changes visible)
+gfx_cs_tint_r db 0
+gfx_cs_tint_g db 0
+gfx_cs_tint_b db 0
+gfx_cs_r db 0
+gfx_cs_g db 0
+gfx_cs_b db 0
+
+
+ ; max label size: 32
+label_buf times 35 db 0
+
+; buffer for number conversions
+num_buf times 23h db 0
+num_buf_end db 0
+
+; temp data for printf
+tmp_write_data times 10h dd 0
+tmp_write_num dw 0
+tmp_write_sig db 0
+tmp_write_cnt db 0
+tmp_write_pad db 0
+
+pf_gfx db 0
+pf_gfx_err dw 0
+ align 4, db 0
+pf_gfx_buf dd 0
+pf_gfx_max dd 0
+pf_gfx_cnt dd 0
+
+ align 4, db 0
+input_timeout_start dd 0
+input_timeout dd 0
+
+progress_max dd 0
+progress_current dd 0
+
+edit_x dw 0
+edit_y dw 0
+edit_width dw 0
+edit_height dw 0
+edit_bg dd 0 ; (seg:ofs)
+edit_buf dd 0 ; (seg:ofs)
+edit_buf_len dw 0
+edit_buf_ptr dw 0
+edit_cursor dw 0
+edit_shift dw 0
+edit_y_ofs dw 0
+
+kbd_status dw 0
+
+
+sound_buf_size equ 8*1024
+
+ align 4, db 0
+sound_x dd 0
+sound_old_int8 dd 0
+sound_old_61 db 0
+sound_61 db 0
+sound_cnt0 dw 0
+sound_timer0 dw 0
+sound_timer1 dw 0
+sound_vol db 0
+sound_ok db 0
+sound_int_active db 0
+sound_playing db 0
+sound_sample dd 0
+sound_buf dd 0 ; (seg:ofs)
+sound_start dw 0 ; rel. to sound_buf
+sound_end dw 0 ; rel. to sound_buf
+playlist times playlist_entries * sizeof_playlist db 0
+mod_buf dd 0 ; (seg:ofs)
+int8_count dd 0
+cycles_per_tt dd 0
+cycles_per_int dd 0
+next_int dd 0,0
+
+ align 4, db 0
+; temporary vars
+tmp_var_0 dd 0
+tmp_var_1 dd 0
+tmp_var_2 dd 0
+tmp_var_3 dd 0
+
+; gdt for pm switch
+pm_cs equ 8
+pm_ss equ 10h
+pm_ds equ 18h
+pm_es equ 20h
+
+ align 4
+pm_gdt dw pm_gdt_size-1 ; gdt descriptor
+ dd 0 ; for lgdt instruction
+ dw 0
+pm_gdt_cs dd 0000ffffh ; 64k code segment
+ dd 00009b00h
+pm_gdt_ss dd 0000ffffh ; 64k data segment
+ dd 00009300h
+pm_gdt_ds dd 0000ffffh ; 64k data segment
+ dd 00009300h
+pm_gdb_es dd 0000ffffh ; 4GB data segment, start at 0
+ dd 008f9300h
+pm_gdt_size equ $-pm_gdt
+
+
+%if debug
+; debug texts
+dmsg_01 db 'Memory: %p - %p, img data at %p', 10, 0
+dmsg_02 db 'Image: %u x %u (real: %u x %u)', 10, 0
+dmsg_03 db 'addr 0x%05x, size 0x%05x+4, %s', 10, 0
+dmsg_04 db 'oops: 0x%05x > 0x%05x', 10, 0
+dmsg_05 db 'oops: 0 size block', 10, 0
+dmsg_06 db 'addr 0x%05x', 10, 0
+dmsg_07 db 'free', 0
+dmsg_08 db 'used', 0
+dmsg_09 db 'current dictionary', 10, 0
+dmsg_10 db ' %2u: type %u, val 0x%x', 10, 0
+
+%endif
+
+single_step db 0
+show_debug_info db 0
+
+hello db 10, 'Initializing gfx code...', 10, 0
+msg_10 db '|ip %4x: %8x.%x |', 10, 0
+msg_11 db '|%2x: %8x.%2x', 0
+msg_12 db '| : ', 0
+msg_13 db '/----pstk------------rstk-------\', 10, 0
+msg_14 db '|-------------------------------|', 10, 0
+msg_15 db '\-------------------------------/', 10, 0
+msg_16 db '|', 10, 0
+msg_17 db '|err %3x |', 10, 0
+msg_18 db '|err %3x: %8x |', 10, 0
+msg_19 db '|err %3x: %8x %8x |', 10, 0
+msg_20 db '|ip %4x: %8x.%x %8x.%x |', 10, 0
+
+ align 2, db 0
+ ; prim_function entries
+ prim_jump_table
+
+; menu entry descriptor
+menu_entries equ 0
+menu_default equ 2 ; seg:ofs
+menu_ent_list equ 6 ; seg:ofs
+menu_ent_size equ 10
+menu_arg_list equ 12 ; seg:ofs
+menu_arg_size equ 16
+sizeof_menu_desc equ 18
+
+; framebuffer mode list
+fb_mode equ 0 ; word
+fb_width equ 2 ; word
+fb_height equ 4 ; word, must follow fb_width
+fb_bits equ 6 ; byte
+fb_ok equ 7 ; monitor supports it
+sizeof_fb_entry equ 8
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Some macros.
+;
+%macro pf_arg_uchar 2
+ and dword [tmp_write_data + %1 * 4],byte 0
+ mov [tmp_write_data + %1 * 4],%2
+%endmacro
+
+%macro pf_arg_ushort 2
+ and word [tmp_write_data + %1 * 4 + 2],byte 0
+ mov [tmp_write_data + %1 * 4],%2
+%endmacro
+
+%macro pf_arg_uint 2
+ mov [tmp_write_data + %1 * 4],%2
+%endmacro
+
+%macro pf_arg_char 2
+ push eax
+ movsx eax,%2
+ mov [tmp_write_data + %1 * 4],eax
+ pop eax
+%endmacro
+
+%macro pf_arg_short 2
+ push eax
+ movsx eax,%2
+ mov [tmp_write_data + %1 * 4],eax
+ pop eax
+%endmacro
+
+%macro pf_arg_int 2
+ mov [tmp_write_data + %1 * 4],%2
+%endmacro
+
+%macro lin2segofs 3
+ push %1
+ call lin2so
+ pop %3
+ pop %2
+%endmacro
+
+%macro segofs2lin 3
+ push %1
+ push %2
+ call so2lin
+ pop %3
+%endmacro
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Interface functions.
+;
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Initialize something.
+;
+; eax memory start
+; ebx free memory start
+; ecx memory end
+; dx boot loader code segment
+; si gfx_sysconfig offset
+; edi file archive start, if any (ends at ebx)
+;
+; return:
+; CF error
+;
+gfx_init:
+ push fs
+ push es
+ push ds
+
+ push cs
+ pop ds
+
+ cld
+
+ mov [mem],eax
+ mov [mem_free],ebx
+ mov [mem_max],ecx
+ mov [mem_archive],edi
+ mov [boot_cs],dx
+ mov [boot_sysconfig],si
+
+ ; init malloc memory chain
+
+ ; align 4
+ mov eax,[mem_free]
+ add eax,3
+ and eax,~3
+ mov [mem_free],eax
+
+ push eax
+ call lin2so
+ pop bx
+ pop es
+ mov edx,[mem_max]
+ sub edx,eax
+ mov [es:bx],edx
+
+%if debug
+ mov si,hello
+ call printf
+%endif
+
+ ; get initial keyboard state
+ push byte 0
+ pop es
+ push word [es:417h]
+ pop word [kbd_status]
+
+%if debug
+ mov eax,[mem]
+ pf_arg_uint 0,eax
+ mov eax,[mem_max]
+ pf_arg_uint 1,eax
+ mov eax,[mem_free]
+ pf_arg_uint 2,eax
+
+ mov si,dmsg_01
+ call printf
+%endif
+
+ call dict_init
+ jc gfx_init_90
+
+ call stack_init
+ jc gfx_init_90
+
+ mov eax,[mem]
+ lin2segofs eax,es,si
+ add eax,[es:si+fh_code]
+ mov [pscode_start],eax
+ mov eax,[es:si+fh_code_size]
+ mov [pscode_size],eax
+
+ ; now the ps interpreter is ready to run
+
+ ; alloc memory for palette data
+ call pal_init
+
+ mov eax,100h
+ call calloc
+ cmp eax,byte 1
+ jc gfx_init_90
+ mov [infobox_buffer],eax
+
+ mov eax,200h
+ call calloc
+ cmp eax,byte 1
+ jc gfx_init_90
+ push eax
+ call lin2so
+ pop dword [vbe_buffer]
+
+ mov eax,200h
+ call calloc
+ cmp eax,byte 1
+ jc gfx_init_90
+ push eax
+ call lin2so
+ pop dword [vbe_mode_list]
+
+ ; ok, we've done it, now continue the setup
+
+%if 0
+ call dump_malloc
+ call get_key
+%endif
+
+ ; run global code
+ xor eax,eax
+ mov [pstack_ptr],ax
+ mov [rstack_ptr],ax
+ call run_pscode
+ jc gfx_init_60
+
+ ; check for true/false on stack
+ ; (empty stack == true)
+
+ xor cx,cx
+ call get_pstack_tos
+ jc gfx_init_80
+ cmp dl,t_bool
+ jnz gfx_init_70
+ cmp eax,byte 1
+ jz gfx_init_90
+ jmp gfx_init_70
+
+gfx_init_60:
+ call ps_status_info
+ call get_key
+gfx_init_70:
+ push cs
+ call gfx_done
+ stc
+ jmp gfx_init_90
+gfx_init_80:
+ clc
+
+gfx_init_90:
+ pop ds
+ pop es
+ pop fs
+ retf
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Do something.
+gfx_done:
+ push fs
+ push es
+ push ds
+
+ push cs
+ pop ds
+ cld
+
+ call sound_done
+
+ mov ax,3
+ int 10h
+
+ pop ds
+ pop es
+ pop fs
+ retf
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; [boot_cs]:di buffer ( 0 --> no buffer )
+; cx buffer size
+; ax timeout value (0 --> no timeout)
+; return:
+; eax action (1, 2: textmode, boot)
+; ebx selected menu entry (-1: none)
+;
+gfx_input:
+ push fs
+ push es
+ push ds
+
+ push di
+ push cx
+
+ push cs
+ pop ds
+ cld
+
+ movzx eax,ax
+ mov [input_timeout],eax
+ mov [input_timeout_start],eax
+
+ call clear_kbd_queue
+
+gfx_input_20:
+ call get_key_to
+ and dword [input_timeout],byte 0 ; disable timeout
+
+ push eax
+ mov cx,cb_KeyEvent
+ call get_dict_entry
+ pop ecx
+ jc gfx_input_90
+
+ cmp dl,t_code
+ stc
+ jnz gfx_input_90
+
+ push eax
+ xchg eax,ecx
+ mov word [pstack_ptr],1
+ mov dl,t_int
+ xor cx,cx
+ call set_pstack_tos
+ mov word [rstack_ptr],1
+ xor cx,cx
+ mov dl,t_code
+ stc
+ sbb eax,eax
+ call set_rstack_tos
+ pop eax
+
+ call run_pscode
+ jnc gfx_input_50
+
+ call ps_status_info
+ call get_key
+ stc
+ jmp gfx_input_90
+
+gfx_input_50:
+ mov cx,2
+ call get_pstack_tos
+ jc gfx_input_90
+ cmp dl,t_string
+ stc
+ jnz gfx_input_90
+
+ pop cx
+ pop di
+ push di
+ push cx
+
+ or di,di
+ jz gfx_input_70
+ or cx,cx
+ jz gfx_input_70
+
+ lin2segofs eax,fs,si
+ mov es,[boot_cs]
+gfx_input_60:
+ fs lodsb
+ stosb
+ or al,al
+ loopnz gfx_input_60
+ mov byte [es:di-1],0
+
+gfx_input_70:
+ mov cx,1
+ call get_pstack_tos
+ jc gfx_input_90
+ cmp dl,t_int
+ stc
+ jnz gfx_input_90
+
+ xor cx,cx
+ push eax
+ call get_pstack_tos
+ pop ebx
+ jc gfx_input_90
+ cmp dl,t_int
+ stc
+ jnz gfx_input_90
+
+ or eax,eax
+ jz gfx_input_20
+
+gfx_input_90:
+ pop cx
+ pop di
+
+ pop ds
+ pop es
+ pop fs
+ retf
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; es:si menu description
+;
+gfx_menu_init:
+ push fs
+ push es
+ push ds
+
+ push cs
+ pop ds
+
+ push es
+ pop fs
+
+ cld
+
+gfx_menu_init_20:
+ push si
+ movzx eax,word [fs:si+menu_entries]
+ push ax
+ imul ax,ax,5
+ add ax,2
+ push eax
+ call calloc
+ mov [tmp_var_2],eax
+ pop eax
+ call calloc
+ mov [tmp_var_1],eax
+ pop cx
+ pop si
+ or eax,[tmp_var_2]
+ jz gfx_menu_init_90
+
+ push cx
+
+ lin2segofs dword [tmp_var_1],es,bx
+ mov [es:bx],cx
+ add bx,2
+ push dword [fs:si+menu_ent_list]
+ call so2lin
+ pop edi
+gfx_menu_init_40:
+ mov byte [es:bx],t_string
+ mov [es:bx+1],edi
+ add bx,5
+ movzx eax,word [fs:si+menu_ent_size]
+ add edi,eax
+ loop gfx_menu_init_40
+
+ pop cx
+
+ lin2segofs dword [tmp_var_2],es,bx
+ mov [es:bx],cx
+ add bx,2
+ push dword [fs:si+menu_arg_list]
+ call so2lin
+ pop edi
+gfx_menu_init_50:
+ mov byte [es:bx],t_string
+ mov [es:bx+1],edi
+ add bx,5
+ movzx eax,word [fs:si+menu_arg_size]
+ add edi,eax
+ loop gfx_menu_init_50
+
+ push dword [fs:si+menu_default]
+ call so2lin
+ pop dword [tmp_var_3]
+
+ mov cx,cb_MenuInit
+ call get_dict_entry
+ jc gfx_menu_init_90
+
+ cmp dl,t_code
+ stc
+ jnz gfx_menu_init_90
+
+ push eax
+
+ mov word [pstack_ptr],3
+
+ mov eax,[tmp_var_1]
+ mov dl,t_array
+ mov cx,2
+ call set_pstack_tos
+
+ mov eax,[tmp_var_2]
+ mov dl,t_array
+ mov cx,1
+ call set_pstack_tos
+
+ mov eax,[tmp_var_3]
+ mov dl,t_string
+ xor cx,cx
+ call set_pstack_tos
+
+ mov word [rstack_ptr],1
+ xor cx,cx
+ mov dl,t_code
+ stc
+ sbb eax,eax
+ call set_rstack_tos
+
+ pop eax
+
+ call run_pscode
+ jnc gfx_menu_init_90
+
+ call ps_status_info
+ call get_key
+ stc
+
+gfx_menu_init_90:
+ pop ds
+ pop es
+ pop fs
+ retf
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; [boot_cs]:si info text 1
+; [boot_cs]:di info text 2 (may be 0 --> no text 2)
+; al 0/1 info/error
+;
+gfx_infobox_init:
+ push fs
+ push es
+ push ds
+
+ push cs
+ pop ds
+ cld
+
+ push ax
+
+ mov cx,100h-1
+ mov fs,[boot_cs]
+
+ lin2segofs dword [infobox_buffer],es,bp
+ or si,si
+ jz gfx_infobox_init_40
+gfx_infobox_init_20:
+ fs lodsb
+ mov [es:bp],al
+ inc bp
+ or al,al
+ loopnz gfx_infobox_init_20
+ or cx,cx
+ jz gfx_infobox_init_40
+ mov si,di
+ or si,si
+ jz gfx_infobox_init_40
+ inc cx
+ dec bp
+gfx_infobox_init_25:
+ fs lodsb
+ mov [es:bp],al
+ inc bp
+ or al,al
+ loopnz gfx_infobox_init_25
+gfx_infobox_init_40:
+ mov byte [es:bp-1],0
+
+ mov cx,cb_InfoBoxInit
+ call get_dict_entry
+
+ pop bx
+
+ jc gfx_infobox_init_90
+
+ cmp dl,t_code
+ stc
+ jnz gfx_infobox_init_90
+
+ push eax
+
+ mov word [pstack_ptr],2
+
+ movzx eax,bl
+ mov dl,t_int
+ xor cx,cx
+ call set_pstack_tos
+
+ mov eax,[infobox_buffer]
+ mov dl,t_string
+ mov cx,1
+ call set_pstack_tos
+
+ mov word [rstack_ptr],1
+ xor cx,cx
+ mov dl,t_code
+ stc
+ sbb eax,eax
+ call set_rstack_tos
+
+ pop eax
+ call run_pscode
+ jnc gfx_infobox_init_90
+
+ call ps_status_info
+ call get_key
+ stc
+
+gfx_infobox_init_90:
+ pop ds
+ pop es
+ pop fs
+ retf
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+gfx_infobox_done:
+ push fs
+ push es
+ push ds
+
+ push cs
+ pop ds
+ cld
+
+ mov cx,cb_InfoBoxDone
+ call get_dict_entry
+ jc gfx_infobox_done_90
+
+ cmp dl,t_code
+ stc
+ jnz gfx_infobox_done_90
+
+ push eax
+ mov word [pstack_ptr],0
+ mov word [rstack_ptr],1
+ xor cx,cx
+ mov dl,t_code
+ stc
+ sbb eax,eax
+ call set_rstack_tos
+
+ pop eax
+ call run_pscode
+ jnc gfx_infobox_done_90
+
+ call ps_status_info
+ call get_key
+ stc
+
+gfx_infobox_done_90:
+ pop ds
+ pop es
+ pop fs
+ retf
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; eax max
+; [boot_cs]:si kernel name
+;
+gfx_progress_init:
+ push fs
+ push es
+ push ds
+
+ push cs
+ pop ds
+ cld
+
+ mov [progress_max],eax
+ and dword [progress_current],byte 0
+
+ mov cx,cb_ProgressInit
+ push si
+ call get_dict_entry
+ pop si
+ jc gfx_progress_init_90
+
+ cmp dl,t_code
+ stc
+ jnz gfx_progress_init_90
+
+ push eax
+ mov word [pstack_ptr],1
+
+ segofs2lin word [boot_cs],si,eax
+ mov dl,t_string
+ xor cx,cx
+ call set_pstack_tos
+
+ mov word [rstack_ptr],1
+ xor cx,cx
+ mov dl,t_code
+ stc
+ sbb eax,eax
+ call set_rstack_tos
+
+ pop eax
+ call run_pscode
+ jnc gfx_progress_init_90
+
+ call ps_status_info
+ call get_key
+ stc
+
+gfx_progress_init_90:
+ pop ds
+ pop es
+ pop fs
+ retf
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+gfx_progress_done:
+ push fs
+ push es
+ push ds
+
+ push cs
+ pop ds
+ cld
+
+ mov cx,cb_ProgressDone
+ call get_dict_entry
+ jc gfx_progress_done_90
+
+ cmp dl,t_code
+ stc
+ jnz gfx_progress_done_90
+
+ push eax
+ mov word [pstack_ptr],0
+ mov word [rstack_ptr],1
+ xor cx,cx
+ mov dl,t_code
+ stc
+ sbb eax,eax
+ call set_rstack_tos
+
+ pop eax
+ call run_pscode
+ jnc gfx_progress_done_90
+
+ call ps_status_info
+ call get_key
+ stc
+
+gfx_progress_done_90:
+ pop ds
+ pop es
+ pop fs
+ retf
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+gfx_progress_update:
+ push fs
+ push es
+ push ds
+
+ push cs
+ pop ds
+ cld
+
+ add [progress_current],eax
+
+ mov cx,cb_ProgressUpdate
+ call get_dict_entry
+ jc gfx_progress_update_90
+
+ cmp dl,t_code
+ stc
+ jnz gfx_progress_update_90
+
+ push eax
+ mov word [pstack_ptr],2
+
+ mov eax,[progress_current]
+ mov dl,t_int
+ xor cx,cx
+ call set_pstack_tos
+
+ mov eax,[progress_max]
+ mov dl,t_int
+ mov cx,1
+ call set_pstack_tos
+
+ mov word [rstack_ptr],1
+ xor cx,cx
+ mov dl,t_code
+ stc
+ sbb eax,eax
+ call set_rstack_tos
+
+ pop eax
+ call run_pscode
+ jnc gfx_progress_update_90
+
+ call ps_status_info
+ call get_key
+ stc
+
+gfx_progress_update_90:
+ pop ds
+ pop es
+ pop fs
+ retf
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+gfx_progress_limit:
+ push ds
+
+ push cs
+ pop ds
+ mov [progress_max],eax
+ mov [progress_current],edx
+
+ pop ds
+ retf
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; [boot_cs]:si password
+; [boot_cs]:di image name
+;
+gfx_password_init:
+ push fs
+ push es
+ push ds
+
+ push cs
+ pop ds
+ cld
+
+ mov cx,cb_PasswordInit
+ push si
+ push di
+ call get_dict_entry
+ pop di
+ pop si
+ jc gfx_password_init_90
+
+ cmp dl,t_code
+ stc
+ jnz gfx_password_init_90
+
+ push eax
+
+ mov word [pstack_ptr],2
+
+ segofs2lin word [boot_cs],si,eax
+ mov dl,t_string
+ xor cx,cx
+ push di
+ call set_pstack_tos
+ pop di
+
+ segofs2lin word [boot_cs],di,eax
+ mov dl,t_string
+ mov cx,1
+ call set_pstack_tos
+
+ mov word [rstack_ptr],1
+ xor cx,cx
+ mov dl,t_code
+ stc
+ sbb eax,eax
+ call set_rstack_tos
+
+ pop eax
+ call run_pscode
+ jnc gfx_password_init_90
+
+gfx_password_init_80:
+ call ps_status_info
+ call get_key
+ stc
+
+gfx_password_init_90:
+ pop ds
+ pop es
+ pop fs
+ retf
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; [boot_cs]:si password
+;
+gfx_password_done:
+ push fs
+ push es
+ push ds
+
+ push cs
+ pop ds
+ cld
+
+ mov cx,cb_PasswordDone
+ push si
+ call get_dict_entry
+ pop si
+ jc gfx_password_done_90
+
+ cmp dl,t_code
+ stc
+ jnz gfx_password_done_90
+
+ push eax
+
+ mov word [pstack_ptr],1
+
+ segofs2lin word [boot_cs],si,eax
+ mov dl,t_string
+ xor cx,cx
+ call set_pstack_tos
+
+ mov word [rstack_ptr],1
+ xor cx,cx
+ mov dl,t_code
+ stc
+ sbb eax,eax
+ call set_rstack_tos
+
+ pop eax
+ call run_pscode
+ jc gfx_password_done_80
+
+ xor cx,cx
+ call get_pstack_tos
+ jc gfx_password_done_90
+ cmp dl,t_bool
+ stc
+ jnz gfx_password_done_90
+
+ cmp eax,byte 1
+ jmp gfx_password_done_90
+
+gfx_password_done_80:
+ call ps_status_info
+ call get_key
+ stc
+
+gfx_password_done_90:
+ pop ds
+ pop es
+ pop fs
+ retf
+
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Internal functions.
+;
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+timeout:
+ mov cx,cb_Timeout
+ call get_dict_entry
+ jc timeout_90
+
+ cmp dl,t_code
+ stc
+ jnz timeout_90
+
+ push eax
+ mov word [pstack_ptr],2
+
+ mov cx,1
+ mov dl,t_int
+ mov eax,[input_timeout_start]
+ call set_pstack_tos
+
+ xor cx,cx
+ mov dl,t_int
+ mov eax,[input_timeout]
+ call set_pstack_tos
+
+ mov word [rstack_ptr],1
+ xor cx,cx
+ mov dl,t_code
+ stc
+ sbb eax,eax
+ call set_rstack_tos
+
+ pop eax
+ call run_pscode
+ jnc timeout_90
+
+ call ps_status_info
+ call get_key
+ stc
+
+timeout_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; eax time
+;
+timer:
+ mov cx,cb_Timer
+ push eax
+ call get_dict_entry
+ pop ebx
+ jc timer_90
+
+ cmp dl,t_code
+ stc
+ jnz timer_90
+
+ push eax
+ mov word [pstack_ptr],1
+
+ xor cx,cx
+ mov dl,t_int
+ xchg eax,ebx
+ call set_pstack_tos
+
+ mov word [rstack_ptr],1
+ xor cx,cx
+ mov dl,t_code
+ stc
+ sbb eax,eax
+ call set_rstack_tos
+
+ pop eax
+ call run_pscode
+ jnc timer_90
+
+ call ps_status_info
+ call get_key
+ stc
+
+timer_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Initialize parameter & return stack.
+;
+; return:
+; CY error
+;
+stack_init:
+ mov ax,param_stack_size
+ mov [pstack_size],ax
+ and word [pstack_ptr],byte 0
+ mov eax,param_stack_size * 5
+ call calloc
+ cmp eax,byte 1
+ jc stack_init_90
+ push eax
+ call lin2so
+ pop dword [pstack]
+
+ mov ax,ret_stack_size
+ mov [rstack_size],ax
+ and word [rstack_ptr],byte 0
+ mov eax,ret_stack_size * 5
+ call calloc
+ cmp eax,byte 1
+ jc stack_init_90
+ push eax
+ call lin2so
+ pop dword [rstack]
+stack_init_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Read a pstack entry.
+;
+; cx index
+;
+; return:
+; eax value
+; dl type
+; cx index
+; CF error
+;
+get_pstack_entry:
+ les bx,[pstack]
+ xor eax,eax
+ mov dl,al
+ cmp [pstack_size],cx
+ jb get_pstack_entry_90
+ mov ax,5
+ mul cx
+ add bx,ax
+ mov dl,[es:bx]
+ mov eax,[es:bx+1]
+get_pstack_entry_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Write a pstack entry.
+;
+; cx index
+; eax value
+; dl type
+;
+; return:
+; cx index
+; CF error
+;
+set_pstack_entry:
+ les bx,[pstack]
+ cmp [pstack_size],cx
+ jb set_pstack_entry_90
+ push eax
+ push dx
+ mov ax,5
+ mul cx
+ add bx,ax
+ pop dx
+ mov [es:bx],dl
+ pop dword [es:bx+1]
+set_pstack_entry_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Read pstack tos (no pop).
+;
+; cx index (rel. to tos, 0 = tos)
+;
+; return:
+; eax value
+; dl type
+; cx index (absolute)
+; CF error
+;
+get_pstack_tos:
+ mov ax,[pstack_ptr]
+ sub ax,1
+ jc get_pstack_tos_90
+ sub ax,cx
+ jc get_pstack_tos_90
+ xchg ax,cx
+ call get_pstack_entry
+get_pstack_tos_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Write pstack tos (no push).
+;
+; cx index (rel. to tos, 0 = tos)
+; eax value
+; dl type
+;
+; return:
+; cx index (absolute)
+; CF error
+;
+set_pstack_tos:
+ mov bx,[pstack_ptr]
+ sub bx,1
+ jc set_pstack_tos_90
+ sub bx,cx
+ jc set_pstack_tos_90
+ xchg bx,cx
+ call set_pstack_entry
+set_pstack_tos_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Rotate pstack up (cx-1'th element becomes tos).
+;
+; cx values to rotate (counted from tos)
+;
+; return:
+; CF error
+;
+rot_pstack_up:
+ or cx,cx
+ jz rot_pstack_up_90
+ les di,[pstack]
+ mov ax,[pstack_ptr]
+ sub ax,cx
+ jb rot_pstack_up_90
+ cmp cx,byte 1
+ jz rot_pstack_up_90
+ add di,ax
+ shl ax,2
+ add di,ax
+ dec cx
+ mov ax,cx
+ shl ax,2
+ add cx,ax
+ mov ebx,[es:di]
+ mov dl,[es:di+4]
+ lea si,[di+5]
+ es rep movsb
+ mov [es:di],ebx
+ mov [es:di+4],dl
+ clc
+rot_pstack_up_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Rotate pstack down (1st element becomes tos).
+;
+; cx values to rotate (counted from tos)
+;
+; return:
+; CF error
+;
+rot_pstack_down:
+ or cx,cx
+ jz rot_pstack_down_90
+ les di,[pstack]
+ mov ax,[pstack_ptr]
+ cmp ax,cx
+ jb rot_pstack_down_90
+ cmp cx,byte 1
+ jz rot_pstack_down_90
+ add di,ax
+ shl ax,2
+ add di,ax
+ dec di
+ lea si,[di-5]
+ dec cx
+ mov ax,cx
+ shl ax,2
+ add cx,ax
+ mov ebx,[es:si+1]
+ mov dl,[es:si+5]
+ std
+ es rep movsb
+ cld
+ mov [es:si+1],ebx
+ mov [es:si+5],dl
+ clc
+rot_pstack_down_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Read a rstack entry.
+;
+; cx index
+;
+; return:
+; eax value
+; dl type
+; cx index
+; CF error
+;
+get_rstack_entry:
+ les bx,[rstack]
+ xor eax,eax
+ mov dl,al
+ cmp [rstack_size],cx
+ jb get_rstack_entry_90
+ mov ax,5
+ mul cx
+ add bx,ax
+ mov dl,[es:bx]
+ mov eax,[es:bx+1]
+get_rstack_entry_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Write a rstack entry.
+;
+; cx index
+; eax value
+; dl type
+;
+; return:
+; cx index
+; CF error
+;
+set_rstack_entry:
+ les bx,[rstack]
+ cmp [rstack_size],cx
+ jb set_rstack_entry_90
+ push eax
+ push dx
+ mov ax,5
+ mul cx
+ add bx,ax
+ pop dx
+ mov [es:bx],dl
+ pop dword [es:bx+1]
+set_rstack_entry_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Read rstack tos (no pop).
+;
+; cx index (rel. to tos, 0 = tos)
+;
+; return:
+; eax value
+; dl type
+; cx index (absolute)
+; CF error
+;
+get_rstack_tos:
+ mov ax,[rstack_ptr]
+ sub ax,1
+ jc get_rstack_tos_90
+ sub ax,cx
+ jc get_rstack_tos_90
+ xchg ax,cx
+ call get_rstack_entry
+get_rstack_tos_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Write rstack tos (no push).
+;
+; cx index (rel. to tos, 0 = tos)
+; eax value
+; dl type
+;
+; return:
+; cx index (absolute)
+; CF error
+;
+set_rstack_tos:
+ mov bx,[rstack_ptr]
+ sub bx,1
+ jc set_rstack_tos_90
+ sub bx,cx
+ jc set_rstack_tos_90
+ xchg bx,cx
+ call set_rstack_entry
+set_rstack_tos_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Setup initial dictionary.
+;
+; return:
+; CY error
+;
+dict_init:
+ push fs
+ mov eax,[mem]
+ lin2segofs eax,es,si
+ mov ecx,[es:si+fh_dict]
+ cmp ecx,byte 1
+ jc dict_init_90
+ add eax,ecx
+ lin2segofs eax,es,si
+ xor eax,eax
+ es lodsw
+ mov [dict_size],ax
+ ; the dictionary should fit in 64k
+ cmp ax,0fff0h/5
+ cmc
+ jc dict_init_90
+
+ ; p_none is not part of the default dict
+ cmp ax,cb_functions + prim_functions - 1
+ jb dict_init_90
+
+ imul eax,eax,5
+ push es
+ push si
+ call calloc
+ pop si
+ pop es
+ cmp eax,byte 1
+ jc dict_init_90
+
+ push eax
+ call lin2so
+ pop dword [dict]
+
+ ; add default functions
+
+ lfs bx,[dict]
+ add bx,cb_functions * 5
+ xor cx,cx
+ inc cx
+dict_init_20:
+ mov byte [fs:bx],t_prim
+ mov [fs:bx+1],cx
+ add bx,5
+ inc cx
+ cmp cx,prim_functions
+ jb dict_init_20
+
+ ; add user defined things
+
+ es lodsw
+ or ax,ax
+ jz dict_init_80
+ cmp [dict_size],ax
+ jb dict_init_90
+ lfs bx,[dict]
+ xchg ax,cx
+dict_init_50:
+ es lodsw
+ cmp ax,[dict_size]
+ cmc
+ jc dict_init_90
+ mov di,5
+ mul di
+ xchg ax,di
+ es lodsb
+ mov [fs:bx+di],al
+ es lodsd
+ mov [fs:bx+di+1],eax
+ dec cx
+ jnz dict_init_50
+
+dict_init_80:
+ clc
+dict_init_90:
+ pop fs
+ ret
+
+%if debug
+
+dump_dict:
+ mov si,dmsg_09
+ call printf
+
+ xor cx,cx
+dump_dict_20:
+ call get_dict_entry
+ jc dump_dict_90
+ pf_arg_ushort 0,cx
+ pf_arg_uchar 1,dl
+ pf_arg_uint 2,eax
+ mov si,dmsg_10
+ pusha
+ call printf
+ popa
+
+ inc cx
+ cmp cx,[dict_size]
+ jb dump_dict_20
+dump_dict_90:
+ ret
+
+%endif
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Read a dictionary entry.
+;
+; cx index
+;
+; return:
+; eax value
+; dl type
+; cx index
+; CF error
+;
+get_dict_entry:
+ les bx,[dict]
+ xor eax,eax
+ mov dl,al
+ cmp [dict_size],cx
+ jb get_dict_entry_90
+ mov ax,5
+ mul cx
+ add bx,ax
+ mov dl,[es:bx]
+ mov eax,[es:bx+1]
+get_dict_entry_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Write a dictionary entry.
+;
+; cx index
+; eax value
+; dl type
+;
+; return:
+; cx index
+; CF error
+;
+set_dict_entry:
+ les bx,[dict]
+ cmp [dict_size],cx
+ jb set_dict_entry_90
+ push eax
+ push dx
+ mov ax,5
+ mul cx
+ add bx,ax
+ pop dx
+ mov [es:bx],dl
+ pop dword [es:bx+1]
+set_dict_entry_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Get some memory.
+;
+; eax memory size
+;
+; return:
+; eax linear address (0 if the request failed)
+; memory is initialized with 0
+;
+calloc:
+ push eax
+ call malloc
+ pop ecx
+ or eax,eax
+ jz calloc_90
+ push eax
+ lin2segofs eax,es,di
+ xor eax,eax
+ add ecx,byte 3
+ shr ecx,2
+ rep stosd
+ pop eax
+calloc_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Get some memory.
+;
+; eax memory size
+;
+; return:
+; eax linear address (0 if the request failed)
+;
+malloc:
+ xor ebp,ebp
+ ; only in 4-byte chunks
+ add eax,3
+ and eax,~3
+ jz malloc_90
+ add eax,4
+ mov ebx,[mem_free]
+
+malloc_20:
+ lin2segofs ebx,es,si
+ mov ecx,[es:si]
+ test cl,1
+ jnz malloc_60
+ and cl,~3
+ cmp ecx,eax
+ jb malloc_70
+ ; mark as occupied
+ or byte [es:si],1
+ lea ebp,[ebx+4]
+ mov edi,ecx
+ sub edi,eax
+ cmp edi,byte 8
+ jb malloc_90
+
+ add ebx,eax
+ or al,1
+ mov [es:si],eax
+ lin2segofs ebx,es,si
+ mov [es:si],edi
+
+ jmp malloc_90
+malloc_60:
+ and cl,~3
+malloc_70:
+ add ebx,ecx
+ cmp ebx,[mem_max]
+ jb malloc_20
+malloc_90:
+ xchg ebp,eax
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Free memory.
+;
+; eax linear address
+;
+free:
+ or eax,eax
+ jz free_90
+ test al,3
+ jnz free_90
+
+ ; extended memory
+ cmp eax,100000h
+ jae xfree
+
+ sub eax,4
+
+ mov ebx,[mem_free]
+ mov ecx,ebx
+free_10:
+ cmp eax,ebx
+ jnz free_70
+
+ lin2segofs ebx,es,si
+ test byte [es:si],1
+ jz free_90
+
+ cmp ecx,ebx ; first block?
+ jz free_30
+
+ lin2segofs ecx,es,si
+ mov edx,[es:si]
+ test dl,1
+ jnz free_30 ; prev block is used
+
+ and dl,~3 ; prev block is free -> join them
+ push es
+ lin2segofs ebx,es,di
+ add edx,[es:di]
+ and dl,~3
+ pop es
+ mov [es:si],edx
+ mov ebx,ecx
+
+free_30:
+ mov edx,ebx
+ lin2segofs ebx,es,si
+ and byte [es:si],~1 ; mark block as free
+ add edx,[es:si]
+ and dl,~3
+ cmp edx,[mem_max] ; last block?
+ jae free_90
+
+ lin2segofs edx,es,si
+ mov edx,[es:si]
+ test dl,1
+ jnz free_90 ; next block is used
+
+ and dl,~3 ; next block is free -> join them
+ lin2segofs ebx,es,si
+ add [es:si],edx
+ jmp free_90
+
+free_70:
+ mov ecx,ebx
+ lin2segofs ebx,es,si
+ add ebx,[es:si]
+ and bl,~3
+ cmp ebx,[mem_max]
+ jb free_10
+free_90:
+ ret
+
+
+%if debug
+; dump memory chain
+dump_malloc:
+ pushad
+ mov ebx,[mem_free]
+
+dump_malloc_30:
+ lin2segofs ebx,es,si
+ mov ecx,[es:si]
+
+ pushad
+ mov ax,dmsg_07
+ test cl,1
+ jz dump_malloc_40
+ mov ax,dmsg_08
+dump_malloc_40:
+ pf_arg_ushort 2,ax
+ and cl,~3
+ sub ecx,4
+ pf_arg_uint 0,ebx
+ pf_arg_uint 1,ecx
+ mov si,dmsg_03
+ call printf
+ popad
+
+ and ecx,byte ~3
+ mov si,dmsg_05
+ jz dump_malloc_80
+
+ add ebx,ecx
+ cmp ebx,[mem_max]
+ jz dump_malloc_90
+ jb dump_malloc_30
+
+ pf_arg_uint 0,ebx
+ pf_arg_uint 1,edi
+ mov si,dmsg_04
+dump_malloc_80:
+ call printf
+dump_malloc_90:
+ popad
+ ret
+%endif
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; return:
+; ebp total free memory
+; edi largest free block
+;
+memsize:
+ xor ebp,ebp
+ xor edi,edi
+ mov ebx,[mem_free]
+memsize_30:
+ lin2segofs ebx,es,si
+ mov ecx,[es:si]
+
+ mov al,cl
+ and ecx,byte ~3
+ jz memsize_90
+ test al,1
+ jnz memsize_50
+
+ lea eax,[ecx-4]
+ add ebp,eax
+ cmp eax,edi
+ jb memsize_50
+ mov edi,eax
+memsize_50:
+ add ebx,ecx
+ cmp ebx,[mem_max]
+ jb memsize_30
+memsize_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Get some memory (taken from extended memory).
+;
+; eax memory size
+;
+; return:
+; eax linear address (0 if the request failed)
+;
+; !!! Currently a fake; it's just called _once_ anyway. !!!
+xmalloc:
+ ; 2 - 3 MB, to avoid A20 handling
+ mov eax,200000h
+
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Free memory (extended memory area).
+;
+; eax linear address
+;
+xfree:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Switch to protected mode.
+;
+; return:
+; CF error (can't switch)
+;
+real_to_pm:
+ cli
+ pushad
+
+ segofs2lin ds,word pm_gdt,dword [pm_gdt+2]
+
+ mov eax,9b00000h
+ mov ax,cs
+ ; patch jmp instruction for later
+ mov [pm_to_real_20-2],ax
+ shl eax,4
+ mov [pm_gdt_cs+2],eax
+
+ mov eax,9300000h
+ mov ax,ss
+ shl eax,4
+ mov [pm_gdt_ss+2],eax
+
+ mov eax,9300000h
+ mov ax,ds
+ shl eax,4
+ mov [pm_gdt_ds+2],eax
+
+ mov eax,cr0
+ test al,1 ; in prot mode (maybe vm86)?
+ stc
+ jnz real_to_pm_90
+ or al,1
+
+ o32 lgdt [pm_gdt]
+
+ mov cr0,eax
+
+ jmp pm_cs:real_to_pm_20
+real_to_pm_20:
+
+ mov ax,pm_ss
+ mov ss,ax
+
+ mov ax,pm_ds
+ mov ds,ax
+
+ mov ax,pm_es
+ mov es,ax
+ mov fs,ax
+ mov gs,ax
+
+ clc
+real_to_pm_90:
+ popad
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Switch to real mode.
+;
+pm_to_real:
+ pushad
+
+ mov eax,cr0
+ and al,~1
+ mov cr0,eax
+
+ jmp 0:pm_to_real_20
+pm_to_real_20:
+
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov fs,ax
+ mov gs,ax
+
+ mov eax,[pm_gdt_ss+2]
+ shr eax,4
+ mov ss,ax
+
+ popad
+ sti
+ ret
+
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Find out size of memory block.
+;
+; eax lin. address
+;
+; return:
+; eax size
+;
+find_mem_size:
+ mov edx,[pscode_start]
+ cmp eax,edx
+ jb find_mem_size_10
+ add edx,[pscode_size]
+ cmp eax,edx
+ jae find_mem_size_10
+
+ ; string constant
+
+ lin2segofs eax,es,di
+ mov cx,0ffffh
+ sub cx,di
+ movzx edx,cx
+ mov al,0
+ repnz scasb
+ xor eax,eax
+ jnz find_mem_size_90
+ sub dx,cx
+ mov eax,edx
+ jmp find_mem_size_90
+
+find_mem_size_10:
+ cmp eax,[mem_free]
+ jb find_mem_size_40
+ cmp eax,[mem_max]
+ jae find_mem_size_40
+
+ ; malloc area
+
+ mov ebx,[mem_free]
+
+find_mem_size_20:
+ lin2segofs ebx,es,si
+ mov ecx,[es:si]
+ and ecx,~3
+ lea edx,[ebx+ecx]
+
+ cmp eax,edx
+ jae find_mem_size_30
+
+ test byte [es:si],1
+ jz find_mem_size_80
+
+ sub eax,ebx
+ cmp eax,4
+ jb find_mem_size_80 ; within header
+
+ sub ecx,eax
+ xchg eax,ecx
+ jmp find_mem_size_90
+
+find_mem_size_30:
+ mov ebx,edx
+ cmp ebx,[mem_max]
+ jb find_mem_size_20
+ jmp find_mem_size_80
+
+find_mem_size_40:
+ mov ebp,[mem_archive]
+ or ebp,ebp
+ jz find_mem_size_70
+ cmp eax,ebp
+ jb find_mem_size_70
+ cmp eax,[mem_free]
+ jae find_mem_size_70
+
+ ; cpio archive area
+
+find_mem_size_50:
+ mov ecx,[mem_free]
+ sub ecx,26
+ cmp ebp,ecx
+ jae find_mem_size_80
+
+ lin2segofs ebp,es,bx
+ cmp word [es:bx],71c7h
+ jnz find_mem_size_80
+
+ movzx ecx,word [es:bx+20] ; file name size
+ inc cx
+ and cx,~1 ; align
+
+ lea ecx,[ecx+ebp+26] ; data start
+
+ cmp eax,ecx
+ jb find_mem_size_80 ; within header area
+
+ mov edx,[es:bx+22] ; data size
+ rol edx,16 ; strange word order
+
+ mov ebp,edx
+ inc ebp
+ and ebp,byte ~1 ; align
+ add ebp,ecx ; next record
+
+ add ecx,edx
+
+ cmp eax,ebp
+ jae find_mem_size_50
+
+ sub ecx,eax
+ jb find_mem_size_80 ; within alignment area
+
+ xchg eax,ecx
+ jmp find_mem_size_90
+
+find_mem_size_70:
+
+ ; some other area
+
+find_mem_size_80:
+ xor eax,eax
+
+find_mem_size_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Find file.
+;
+; eax file name (lin)
+;
+; return:
+; eax file start (lin)
+;
+; Note: use find_mem_size to find out the file size
+;
+find_file:
+ lin2segofs eax,fs,si
+ mov ebp,[mem_archive]
+ or ebp,ebp
+ jz find_file_80
+find_file_20:
+ lin2segofs ebp,es,bx
+ cmp word [es:bx],71c7h
+ jnz find_file_80
+ mov cx,[es:bx+20] ; file name size (incl. final 0)
+ movzx edx,cx
+ inc dx
+ and dx,~1 ; align
+ lea ebp,[ebp+edx+26] ; points to data start
+ lea di,[bx+26]
+ or cx,cx
+ jz find_file_50
+ push si
+ fs rep cmpsb
+ pop si
+ jnz find_file_50
+ xchg eax,ebp
+ jmp find_file_90
+find_file_50:
+ mov ecx,[es:bx+22] ; data size
+ rol ecx,16 ; strange word order
+ inc ecx
+ and ecx,byte ~1 ; align
+ add ebp,ecx
+ mov ecx,ebp
+ add ecx,26
+ cmp ecx,[mem_free]
+ jb find_file_20
+find_file_80:
+ xor eax,eax
+find_file_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Set graphics mode.
+;
+; [gfx_mode] graphics mode (either vbe or normal mode number)
+; [vbe_buffer] buffer for vbe info
+;
+; return:
+; CF error
+;
+set_mode:
+ push es
+ mov ax,[gfx_mode]
+ test ah,ah
+ jnz set_mode_20
+ int 10h
+ mov word [window_seg_w],0a000h
+ and word [window_seg_r],byte 0
+ mov byte [mapped_window],0
+
+ mov al,[gfx_mode]
+ cmp al,13h
+ jnz set_mode_102
+ ; 320x200, 8 bit
+ mov word [screen_width],320
+ mov word [screen_height],200
+ mov word [screen_line_len],320
+ mov byte [pixel_bits],8
+ mov byte [pixel_bytes],1
+ call mode_init
+set_mode_102:
+ jmp set_mode_90
+set_mode_20:
+ les di,[vbe_buffer]
+ mov ax,4f00h
+ and dword [es:di],byte 0
+ push di ; you never know...
+ int 10h
+ pop di
+ cmp ax,4fh
+ jnz set_mode_80
+ mov ax,4f01h
+ mov cx,[gfx_mode]
+ push di
+ int 10h
+ pop di
+ cmp ax,4fh
+ jnz set_mode_80
+
+ push word [es:di+10h]
+ pop word [screen_line_len]
+
+ push word [es:di+12h]
+ pop word [screen_width]
+ push word [es:di+14h]
+ pop word [screen_height]
+
+ mov al,[es:di+1bh] ; color mode (aka memory model)
+ mov ah,[es:di+19h] ; color depth
+ mov dh,ah
+ cmp al,6 ; direct color
+ jnz set_mode_30
+ sub dh,[es:di+25h] ; reserved color bits
+ jmp set_mode_40
+set_mode_30:
+ cmp al,4 ; PL 8
+ mov ah,8
+ mov dh,ah
+ jz set_mode_40
+ mov ah,0
+set_mode_40:
+ cmp ah,8
+ jz set_mode_45
+ cmp ah,16
+ jz set_mode_45
+ cmp ah,32
+ jnz set_mode_80
+set_mode_45:
+
+ mov [pixel_bits],ah
+ shr ah,3
+ mov [pixel_bytes],ah
+ mov [color_bits],dh
+
+ call mode_init
+
+ ; we check if win A is readable _and_ writable; if not, we want
+ ; at least a writable win A and a readable win B
+ ; other, even more silly variations are not supported
+
+ mov ax,[es:di+8] ; win seg A
+ mov bx,[es:di+10] ; win seg B
+
+ or ax,ax
+ jz set_mode_80
+ mov [window_seg_w],ax
+ and word [window_seg_r],byte 0
+ mov dx,[es:di+2] ; win A/B attributes
+ and dx,707h
+ cmp dl,7
+ jz set_mode_50 ; win A is rw
+
+ or bx,bx
+ jz set_mode_80
+ mov [window_seg_r],bx
+ mov cx,dx
+ and dx,305h
+ cmp dx,305h
+ jz set_mode_50 ; win A is w, win B is r
+
+ and cx,503h
+ cmp cx,503h
+ jnz set_mode_80
+ ; win A is r, win B is w
+ mov [window_seg_r],ax
+ mov [window_seg_w],bx
+set_mode_50:
+ mov ax,[es:di+6] ; win size (in kb)
+ cmp ax,64
+ jb set_mode_80 ; at least 64k
+ xor dx,dx
+ mov bx,[es:di+4] ; granularity (in kb)
+ or bx,bx
+ jz set_mode_80
+ div bx
+ or dx,dx
+ jnz set_mode_80
+ or ax,ax
+ jz set_mode_80
+ mov [window_inc],al
+ mov byte [mapped_window],0ffh
+ mov ax,4f02h
+ mov bx,[gfx_mode]
+ int 10h
+ cmp ax,4fh
+ jnz set_mode_80
+ mov al,0
+ call set_win
+ jmp set_mode_90
+set_mode_80:
+ and word [gfx_mode],byte 0
+ stc
+set_mode_90
+ pop es
+ ret
+
+
+mode_init:
+ mov word [setpixel],setpixel_8
+ mov word [setpixel_a],setpixel_a_8
+ mov word [setpixel_t],setpixel_8
+ mov word [setpixel_ta],setpixel_a_8
+ mov word [getpixel],getpixel_8
+ cmp byte [pixel_bits],8
+ jz mode_init_90
+ cmp byte [pixel_bits],16
+ jnz mode_init_10
+ mov word [setpixel],setpixel_16
+ mov word [setpixel_a],setpixel_a_16
+ mov word [setpixel_t],setpixel_t_16
+ mov word [setpixel_ta],setpixel_ta_16
+ mov word [getpixel],getpixel_16
+ jmp mode_init_90
+mode_init_10:
+ cmp byte [pixel_bits],32
+ jnz mode_init_90
+ mov word [setpixel],setpixel_32
+ mov word [setpixel_a],setpixel_a_32
+ mov word [setpixel_t],setpixel_t_32
+ mov word [setpixel_ta],setpixel_ta_32
+ mov word [getpixel],getpixel_32
+mode_init_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Find graphics mode.
+;
+; edx width
+; ecx height
+; eax color bits
+; [vbe_buffer] buffer for vbe info
+;
+; return:
+; eax mode number
+; CF 1 = not found
+;
+find_mode:
+ push es
+
+ mov [tmp_write_data],dx
+ mov [tmp_write_data+2],cx
+ mov [tmp_write_data+4],ax
+
+ lfs si,[vbe_mode_list]
+ cmp word [fs:si],0
+ jnz find_mode_40
+
+ ; ok, get list first
+
+ les di,[vbe_buffer]
+ mov ax,4f00h
+ and dword [es:di],byte 0
+ push di
+ int 10h
+ pop di
+ cmp ax,4fh
+ jnz find_mode_30
+ lfs si,[es:di+0eh]
+ les di,[vbe_mode_list]
+ mov cx,0ffh
+find_mode_10:
+ fs lodsw
+ stosw
+ cmp ax,0ffffh
+ jz find_mode_20
+ dec cx
+ jnz find_mode_10
+ mov word [es:di],0ffffh
+find_mode_20:
+ lfs si,[vbe_mode_list]
+ cmp word [fs:si],0
+ jnz find_mode_40
+ ; make sure it's not 0; mode 1 is the same as mode 0
+ mov byte [fs:si],1
+ jmp find_mode_40
+find_mode_30:
+ lfs si,[vbe_mode_list]
+ mov word [fs:si],0ffffh
+find_mode_40:
+ fs lodsw
+ cmp ax,0ffffh
+ jz find_mode_80
+ xchg ax,cx
+ les di,[vbe_buffer]
+ mov ax,4f01h
+ push fs
+ push si
+ push di
+ push cx
+ int 10h
+ pop cx
+ pop di
+ pop si
+ pop fs
+ cmp ax,4fh
+ jnz find_mode_40
+
+ test byte [es:di],1 ; mode supported?
+ jz find_mode_40
+
+ mov eax,[es:di+12h] ; size
+ cmp eax,[tmp_write_data]
+ jnz find_mode_40
+
+ mov dl,[es:di+1bh] ; color mode (aka memory model)
+ mov dh,[es:di+19h] ; color depth
+
+ cmp dl,6 ; direct color
+ jnz find_mode_60
+ cmp dh,32
+ jz find_mode_70
+ sub dh,[es:di+25h] ; reserved color bits
+ jmp find_mode_70
+find_mode_60:
+ cmp dl,4 ; PL8
+ jnz find_mode_40
+ mov dh,8
+find_mode_70:
+ cmp dh,[tmp_write_data+4]
+ jnz find_mode_40
+
+ movzx eax,cx
+ jmp find_mode_90
+
+find_mode_80:
+ stc
+find_mode_90:
+ pop es
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Activate an image from file.
+;
+; eax: lin ptr to image
+;
+; return:
+; CY: error
+;
+image_init:
+ push eax
+ lin2segofs eax,es,bx
+ cmp dword [es:bx],0801050ah
+ jnz image_init_90
+
+ mov cx,[es:bx+8]
+ inc cx
+ jz image_init_80
+ mov dx,[es:bx+10]
+ inc dx
+ jz image_init_80
+
+ push eax
+ push cx
+ push dx
+ push bx
+ push es
+ call find_mem_size
+ pop es
+ pop bx
+ pop dx
+ pop cx
+ pop edi
+
+ cmp eax,381h
+ jb image_init_80
+
+ lea esi,[eax+edi-301h]
+ lin2segofs esi,fs,si
+
+ cmp byte [fs:si],12
+ jnz image_init_80
+
+ mov byte [image_type],1 ; pcx
+
+ mov [image],edi
+ mov [image_width],cx
+ mov [image_height],dx
+
+ lea ax,[bx+80h]
+ mov [image_data],ax
+ mov [image_data+2],es
+
+ inc si
+ mov [image_pal],si
+ mov [image_pal+2],fs
+
+ call parse_img
+
+ lfs si,[image_pal]
+ les di,[gfx_pal]
+
+ mov cx,300h
+ push cx
+ fs rep movsb
+ pop cx
+
+ xor ax,ax
+ mov dx,cx
+ dec di
+ std
+ repz scasb
+ cld
+ setnz al
+ sub dx,cx
+ sub dx,ax
+ xchg ax,dx
+ xor dx,dx
+ mov cx,3
+ div cx
+ sub ax,100h
+ neg ax
+ mov [pals],ax
+
+ clc
+ jmp image_init_90
+
+image_init_80:
+ stc
+image_init_90:
+ pop eax
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Convert 32bit linear address to seg:ofs.
+;
+; dword [esp + 2]: linear address
+;
+; return:
+; dword [esp + 2]: seg:ofs
+;
+; Notes:
+; - changes no regs
+;
+lin2so:
+ push eax
+ mov eax,[esp + 6]
+ shr eax,4
+ mov [esp + 8],ax
+ and word [esp + 6],byte 0fh
+ pop eax
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Convert seg:ofs to 32bit linear address.
+;
+; dword [esp + 2]: seg:ofs
+;
+; return:
+; dword [esp + 2]: linear address
+;
+; Notes:
+; - changes no regs
+;
+so2lin:
+ push eax
+ movzx eax,word [esp + 8]
+ and word [esp + 8],byte 0
+ shl eax,4
+ add [esp + 6],eax
+ pop eax
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Write text to console.
+;
+; si text (ACSIIZ)
+;
+printf:
+ mov byte [tmp_write_cnt],0
+printf_10:
+ call pf_next_char
+ or al,al
+ jz printf_90
+ cmp al,'%'
+ jnz printf_70
+ mov byte [tmp_write_pad],' '
+ call pf_next_char
+ dec si
+ cmp al,'0'
+ jnz printf_20
+ mov [tmp_write_pad],al
+printf_20:
+ call get_number
+ mov [tmp_write_num],cx
+ call pf_next_char
+ or al,al
+ jz printf_90
+ cmp al,'%'
+ jz printf_70
+
+ cmp al,'s'
+ jnz printf_30
+
+ push si
+
+ call pf_next_arg
+ cmp byte [pf_gfx],0
+ jz printf_25
+ push es
+ lin2segofs eax,es,si
+ call write_str
+ pop es
+ jmp printf_27
+printf_25:
+ xchg ax,si
+ call write_str
+printf_27:
+ sub cx,[tmp_write_num]
+ neg cx
+ mov al,' '
+ call write_chars
+ pop si
+ jmp printf_10
+
+printf_30:
+ cmp al,'u'
+ jnz printf_35
+
+ mov dx,10
+printf_31:
+ push si
+ call pf_next_arg
+ or dh,dh
+ jz printf_34
+ test eax,eax
+ jns printf_34
+ neg eax
+ push eax
+ mov al,'-'
+ call write_char
+ pop eax
+printf_34:
+ mov cl,[tmp_write_num]
+ mov ch,[tmp_write_pad]
+ call number
+ cmp byte [pf_gfx],0
+ jz printf_345
+ push es
+ push ds
+ pop es
+ call write_str
+ pop es
+ jmp printf_347
+printf_345:
+ call write_str
+printf_347:
+ pop si
+ jmp printf_10
+
+printf_35:
+ cmp al,'x'
+ jnz printf_36
+
+printf_35a:
+ mov dx,10h
+ jmp printf_31
+
+printf_36:
+ cmp al,'d'
+ jnz printf_37
+printf_36a:
+ mov dx,10ah
+ jmp printf_31
+
+printf_37:
+ cmp al,'i'
+ jz printf_36a
+
+ cmp al,'p'
+ jnz printf_40
+ mov al,'0'
+ call write_char
+ mov al,'x'
+ call write_char
+ jmp printf_35a
+
+printf_40:
+ cmp al,'c'
+ jnz printf_45
+
+ push si
+ call pf_next_arg
+ call write_char
+ pop si
+ jmp printf_10
+printf_45:
+
+ ; more ...
+
+
+printf_70:
+ call write_char
+ jmp printf_10
+printf_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; get next char for printf
+;
+; either from ds:si or es:si
+;
+pf_next_char:
+ xor eax,eax
+ cmp byte [pf_gfx],0
+ jz pf_next_char_50
+ es ; ok, this _is_ evil code...
+pf_next_char_50:
+ lodsb
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; return next printf arg
+;
+; return:
+; eax arg
+;
+; changes no regs
+;
+pf_next_arg:
+ cmp byte [pf_gfx],0
+ jz pf_next_arg_50
+ push es
+ pushad
+ xor cx,cx
+ call get_pstack_tos
+ mov [tmp_write_data],eax
+ jnc pf_next_arg_20
+ and dword [tmp_write_data],byte 0
+ cmp word [pf_gfx_err],byte 0
+ jnz pf_next_arg_20
+ mov word [pf_gfx_err],pserr_pstack_underflow
+ jmp pf_next_arg_30
+pf_next_arg_20:
+ dec word [pstack_ptr]
+pf_next_arg_30:
+ popad
+ pop es
+ mov eax,[tmp_write_data]
+ jmp pf_next_arg_90
+pf_next_arg_50:
+ push si
+ mov al,[tmp_write_cnt]
+ cbw
+ inc byte [tmp_write_cnt]
+ shl ax,2
+ mov si,ax
+ mov eax,[si+tmp_write_data]
+ pop si
+pf_next_arg_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; si text
+;
+; return:
+; cx length
+;
+write_str:
+ xor cx,cx
+write_str_10:
+ call pf_next_char
+ cmp byte [pf_gfx],0
+ jz write_str_40
+ call is_eot
+ jmp write_str_50
+write_str_40:
+ or al,al
+write_str_50:
+ jz write_str_90
+ call write_char
+ inc cx
+ jmp write_str_10
+write_str_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; al char
+; cx count (must be > 0)
+;
+write_chars:
+ cmp cx,0
+ jle write_chars_90
+ call write_char
+ dec cx
+ jmp write_chars
+write_chars_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; al char
+;
+write_char:
+ push es
+ pushad
+ cmp byte [pf_gfx],0
+ jz write_char_50
+ mov ebx,[pf_gfx_cnt]
+ inc ebx
+ cmp ebx,[pf_gfx_max]
+ jae write_char_90 ; leave room for final 0!
+ mov [pf_gfx_cnt],ebx
+ add ebx,[pf_gfx_buf]
+ dec ebx
+ lin2segofs ebx,es,di
+ mov ah,0
+ mov [es:di],ax
+ jmp write_char_90
+write_char_50:
+ cmp al,0ah
+ jnz write_char_60
+ push ax
+ mov al,0dh
+ mov bx,7
+ mov ah,0eh
+ int 10h
+ pop ax
+write_char_60:
+ mov bx,7
+ mov ah,0eh
+ int 10h
+
+write_char_90:
+ popad
+ pop es
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Convert string to number.
+;
+; si string
+;
+; return:
+; cx number
+; si points past number
+; CY not a number
+;
+get_number:
+
+ xor cx,cx
+ mov ah,1
+get_number_10:
+ call pf_next_char
+ or al,al
+ jz get_number_90
+ sub al,'0'
+ jb get_number_90
+ cmp al,9
+ ja get_number_90
+ cbw
+ imul cx,cx,10
+ add cx,ax
+ jmp get_number_10
+get_number_90:
+ dec si
+ shr ah,1
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Convert a number to string.
+;
+; eax number
+; cl field size
+; ch padding char
+; dl base
+;
+; return:
+; si string
+;
+number:
+ push es
+
+ push ds
+ pop es
+ mov di,num_buf
+ push ax
+ push cx
+ mov al,ch
+ mov cx,num_buf_end - num_buf
+ rep stosb
+ pop cx
+ pop ax
+ mov ch,0
+ movzx ebx,dl
+number_10:
+ xor edx,edx
+ div ebx
+ cmp dl,9
+ jbe number_20
+ add dl,27h
+number_20:
+ add dl,'0'
+ dec di
+ mov [di],dl
+ or eax,eax
+ jz number_30
+ cmp di,num_buf
+ ja number_10
+number_30:
+ mov si,di
+ or cx,cx
+ jz number_90
+ cmp cl,num_buf_end - num_buf
+ jae number_90
+ mov si,num_buf_end
+ sub si,cx
+number_90:
+ pop es
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ps_status_info:
+ xor dx,dx
+ call cons_xy
+
+ mov si,msg_13
+ call printf
+
+ mov cx,4
+ps_status_info_10:
+ push cx
+
+ call get_pstack_tos
+ jc ps_status_info_20
+ pf_arg_ushort 0,cx
+ pf_arg_uchar 2,dl
+ pf_arg_uint 1,eax
+ mov si,msg_11
+ jmp ps_status_info_30
+ps_status_info_20:
+ mov si,msg_12
+ps_status_info_30:
+ call printf
+
+ pop cx
+ push cx
+
+ call get_rstack_tos
+ jc ps_status_info_40
+ pf_arg_ushort 0,cx
+ pf_arg_uchar 2,dl
+ pf_arg_uint 1,eax
+ mov si,msg_11
+ jmp ps_status_info_50
+ps_status_info_40:
+ mov si,msg_12
+ps_status_info_50:
+ call printf
+
+ mov si,msg_16
+ call printf
+
+ pop cx
+ dec cx
+ jge ps_status_info_10
+
+ mov si,msg_14
+ call printf
+
+ mov eax,[pscode_error_arg_0]
+ pf_arg_uint 1,eax
+ mov eax,[pscode_error_arg_1]
+ pf_arg_uint 2,eax
+ mov ax,[pscode_error]
+ pf_arg_ushort 0,ax
+ mov si,msg_17
+ cmp ax,100h
+ jb ps_status_info_60
+ mov si,msg_18
+ cmp ax,200h
+ jb ps_status_info_60
+ mov si,msg_19
+ps_status_info_60:
+ call printf
+
+ mov eax,[pscode_instr]
+ pf_arg_uint 0,eax
+ mov eax,[pscode_arg]
+ pf_arg_uint 1,eax
+ mov eax,[pscode_error_arg_0]
+ pf_arg_uint 3,eax
+ mov eax,[pscode_error_arg_1]
+ pf_arg_uint 4,eax
+ mov al,[pscode_type]
+ pf_arg_uchar 2,al
+
+ mov si,msg_10
+ cmp al,t_sec
+ jnz ps_status_info_70
+ mov si,msg_20
+ps_status_info_70:
+ call printf
+
+ mov si,msg_15
+ call printf
+
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Read a key (blocking).
+;
+; return:
+; eax key
+;
+get_key:
+ mov ah,10h
+ int 16h
+ and eax,0ffffh
+ push es
+ push word 0
+ pop es
+ mov ecx,[es:417h-2]
+ xor cx,cx
+ add eax,ecx
+ pop es
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Read a key, return 0 if timed out
+;
+; return:
+; eax key (or 0)
+get_key_to:
+ call get_time
+ xchg eax,edx
+get_key_to_20:
+ mov ah,11h
+ int 16h
+ jnz get_key_to_60
+ cmp byte [run_idle],0
+ jz get_key_to_25
+ call idle
+get_key_to_25:
+ push es
+ push byte 0
+ pop es
+ mov ax,[es:417h]
+ pop es
+ cmp ax,[kbd_status]
+ mov [kbd_status],ax
+ jz get_key_to_30
+ xor ax,ax
+ jmp get_key_to_60
+
+get_key_to_30:
+ call get_time
+ cmp edx,eax
+ jz get_key_to_20
+
+ push eax
+ call timer
+ pop edx
+
+ mov eax,[input_timeout]
+ or eax,eax
+ jz get_key_to_20
+
+ dec dword [input_timeout]
+ pushf
+ push edx
+ call timeout
+ pop edx
+ popf
+ jnz get_key_to_20
+
+ xor eax,eax
+ jmp get_key_to_90
+
+get_key_to_60:
+ pushf
+ cmp dword [input_timeout],byte 0
+ jz get_key_to_70
+ and dword [input_timeout],byte 0
+ call timeout
+get_key_to_70:
+ popf
+ jnz get_key_to_80
+ mov ax,[kbd_status]
+ shl eax,16
+ mov ah,0ffh
+ jmp get_key_to_90
+get_key_to_80:
+ call get_key
+get_key_to_90:
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+clear_kbd_queue:
+ mov ah,11h
+ int 16h
+ jz clear_kbd_queue_90
+ mov ah,10h
+ int 16h
+ jmp clear_kbd_queue
+clear_kbd_queue_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+get_time:
+ push cx
+ push dx
+ xor ax,ax
+ int 1ah
+ push cx
+ push dx
+ pop eax
+ pop dx
+ pop cx
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Set console cursor position.
+;
+; dh row
+; dl column
+;
+; return:
+;
+cons_xy:
+ mov bh,0
+ mov ah,2
+ int 10h
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+idle_data dd 0
+idle_data2 dd 0
+
+%include "kroete.inc"
+
+idle:
+ push es
+ push fs
+ push gs
+ pushad
+
+ les si,[idle_data]
+ mov bx,[idle_data2]
+ call kroete
+
+ popad
+ pop gs
+ pop fs
+ pop es
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Execute ps code.
+;
+; eax start address, relative to
+;
+; return:
+; CF error
+;
+run_pscode:
+ mov [pscode_instr],eax
+ mov [pscode_next_instr],eax
+ mov dword [pscode_next_break],-1
+ and word [pscode_error],byte 0
+ mov dword [pscode_eval],-1
+
+ cmp [pscode_size],eax
+ mov bp,pserr_nocode
+ jb run_pscode_90
+run_pscode_10:
+ mov eax,[pscode_next_instr]
+ mov [pscode_instr],eax
+ cmp eax,-1 ; -1 is special: stop there
+ mov bp,pserr_ok
+ jz run_pscode_90
+ mov ecx,-1
+ xchg ecx,[pscode_eval]
+ cmp ecx,[pscode_eval]
+ jz run_pscode_15
+ ; run opcode from exec instruction
+ mov ebx,eax
+ mov dl,t_sec
+ mov eax,ecx
+ jmp run_pscode_455
+run_pscode_15:
+ mov ebx,eax
+ add eax,[pscode_start]
+ lin2segofs eax,es,si
+ es lodsb
+ xor ecx,ecx
+ mov cl,al
+ and al,0fh
+ shr cl,4
+ mov ah,cl
+
+ and cl,7
+ xor edx,edx
+
+ cmp cl,0
+ jz run_pscode_20
+
+ mov dl,[es:si]
+ cmp cl,1
+ jz run_pscode_20
+
+ mov dx,[es:si]
+ cmp cl,2
+ jz run_pscode_20
+
+ mov edx,[es:si]
+ and edx,0ffffffh
+ cmp cl,3
+ jz run_pscode_20
+
+ mov edx,[es:si]
+run_pscode_20:
+ stc
+ adc ebx,ecx ; ebx+ecx+1
+ mov edi,ebx
+ add edi,[pscode_start]
+
+ test ah,8
+ jz run_pscode_30
+ add ebx,edx
+run_pscode_30:
+ cmp [pscode_size],ebx
+ mov bp,pserr_nocode
+ jb run_pscode_90
+
+ ; fix up signed integer
+ cmp al,t_int
+ jnz run_pscode_40
+ cmp ah,0
+ jz run_pscode_40
+ cmp ah,4
+ jae run_pscode_40
+ shl ah,3
+ mov cl,20h
+ sub cl,ah
+ shl edx,cl
+ sar edx,cl
+run_pscode_40:
+
+ cmp al,t_string
+ jnz run_pscode_45
+ mov edx,edi
+run_pscode_45:
+ xchg eax,edx
+
+run_pscode_455:
+
+ ; dl: opcode
+ ; eax: instr arg
+ ; ebx: next instruction
+
+ ; remember them
+ mov [pscode_type],dl
+ mov [pscode_arg],eax
+ mov [pscode_next_instr],ebx
+
+ cmp dl,t_sec
+ jnz run_pscode_46
+
+ ; look it up in the dictionary, then continue
+ xchg ax,cx
+ call get_dict_entry
+ mov bp,pserr_invalid_dict
+ jc run_pscode_90
+
+ movzx edx,dl
+ mov [pscode_error_arg_0],eax
+ mov [pscode_error_arg_1],edx
+
+run_pscode_46:
+ pushad
+ cmp byte [show_debug_info],0
+ jz run_pscode_47
+ call ps_status_info
+run_pscode_47:
+ mov eax,[pscode_next_break]
+ cmp eax,[pscode_instr]
+ jz run_pscode_475
+ cmp byte [single_step],0
+ jz run_pscode_48
+run_pscode_475:
+ mov byte [single_step],1
+ call get_key
+ cmp ah,1 ; ESC
+ jnz run_pscode_477
+ mov byte [single_step],0
+ mov byte [show_debug_info],0
+ jmp run_pscode_48
+run_pscode_477:
+ cmp ah,0fh ; Tab
+ jnz run_pscode_48
+ mov byte [single_step],0
+ mov eax,[pscode_next_instr]
+ mov [pscode_next_break],eax
+run_pscode_48:
+ popad
+
+ ; actually do something
+ cmp dl,t_none
+ jz run_pscode_50
+ cmp dl,t_int
+ jz run_pscode_50
+ cmp dl,t_unsigned
+ jz run_pscode_50
+ cmp dl,t_bool
+ jz run_pscode_50
+ cmp dl,t_string
+ jz run_pscode_50
+ cmp dl,t_dict_idx
+ jz run_pscode_50
+ cmp dl,t_ptr
+ jz run_pscode_50
+ cmp dl,t_array
+ jnz run_pscode_52
+run_pscode_50:
+ ; t_none, t_int, t_bool, t_unsigned, t_string, t_code, t_dict_idx, t_array, t_ptr
+
+ cmp dl,t_unsigned
+ jnz run_pscode_51
+ mov dl,t_int ; always use t_int
+run_pscode_51:
+ mov cx,[pstack_ptr]
+ cmp cx,[pstack_size]
+ mov bp,pserr_pstack_overflow
+ jae run_pscode_80
+ inc word [pstack_ptr]
+
+ xor cx,cx
+ call set_pstack_tos
+ jc run_pscode_90
+ jmp run_pscode_10
+
+run_pscode_52:
+ cmp dl,t_prim
+ jnz run_pscode_53
+
+ cmp eax,prim_functions
+ mov bp,pserr_invalid_prim
+ jae run_pscode_80
+ xchg ax,si
+ add si,si
+ mov ax,[si+jt_p_none]
+ or ax,ax ; implemented?
+ jz run_pscode_80
+
+ call ax
+ jc run_pscode_90
+ jmp run_pscode_10
+
+run_pscode_53:
+ cmp dl,t_code
+ jnz run_pscode_54
+
+ ; branch
+ xchg eax,[pscode_next_instr]
+
+ ; Check if we should just leave a mark on the
+ ; pstack or actually execute the code.
+ ; Maybe 2 different types (say: t_code, t_mark) would be better?
+ cmp byte [pscode_type],t_sec
+ jnz run_pscode_50
+
+ mov cx,[rstack_ptr]
+ cmp cx,[rstack_size]
+ mov bp,pserr_rstack_overflow
+ jae run_pscode_80
+ inc word [rstack_ptr]
+
+ xor cx,cx
+ call set_rstack_tos
+ jc run_pscode_90
+ jmp run_pscode_10
+
+run_pscode_54:
+ cmp dl,t_ret
+ jnz run_pscode_70
+
+ xor cx,cx
+ call get_rstack_tos
+ jnc run_pscode_55
+ mov bp,pserr_rstack_underflow
+ jc run_pscode_90
+; ; treat this case as 'end'
+; mov bp,pserr_ok
+; clc
+; jmp run_pscode_90
+run_pscode_55:
+ mov bp,pserr_invalid_rstack_entry
+ cmp dl,t_code
+ jz run_pscode_68
+ cmp dl,t_if ; if
+ jz run_pscode_68
+ cmp dl,t_loop ; loop
+ jz run_pscode_69
+ cmp dl,t_repeat ; repeat
+ jz run_pscode_65
+ cmp dl,t_for ; for
+ jz run_pscode_62
+ cmp dl,t_forall ; forall
+ jnz run_pscode_80
+
+ ; forall
+ cmp word [rstack_ptr],byte 5
+ mov bp,pserr_rstack_underflow
+ jc run_pscode_90
+
+ mov cx,1
+ call get_rstack_tos ; count
+ cmp dl,t_int
+ jnz run_pscode_66
+
+ mov cx,2
+ push eax
+ call get_rstack_tos ; length
+ pop esi
+ cmp dl,t_int
+ jnz run_pscode_66
+
+ mov cx,3
+ push eax
+ push esi
+ call get_rstack_tos ; string/array
+ pop esi
+ pop ecx
+ cmp dl,t_array
+ jz run_pscode_57
+ cmp dl,t_string
+ jz run_pscode_57
+ cmp dl,t_ptr
+ jnz run_pscode_66
+
+run_pscode_57:
+ ; dl,eax: string/array
+ ; esi: count
+ ; ecx: length
+
+ inc esi
+ cmp esi,ecx
+ jae run_pscode_64
+
+ push dx
+ mov cx,1
+ mov dl,t_int
+ push eax
+ push esi
+ mov eax,esi
+ call set_rstack_tos
+ pop eax
+ pop ecx
+ pop dx
+
+ xchg dl,dh
+ call p_get
+ mov bp,pserr_invalid_range
+ jc run_pscode_80
+
+ mov cx,[pstack_ptr]
+ cmp cx,[pstack_size]
+ jae run_pscode_80
+ inc word [pstack_ptr]
+ xor cx,cx
+ call set_pstack_tos
+ jc run_pscode_90
+
+ xor cx,cx
+ call get_rstack_tos
+ jmp run_pscode_69
+
+
+run_pscode_62:
+ ; for
+ cmp word [rstack_ptr],byte 5
+ mov bp,pserr_rstack_underflow
+ jc run_pscode_90
+
+ mov cx,2
+ call get_rstack_tos ; step
+ cmp dl,t_int
+ jnz run_pscode_66
+ mov cx,1
+ push eax
+ call get_rstack_tos ; limit
+ pop esi
+ cmp dl,t_int
+ jnz run_pscode_66
+ push eax
+ mov cx,3
+ push esi
+ call get_rstack_tos ; counter
+ pop esi
+ cmp dl,t_int
+ pop ecx
+ jnz run_pscode_66
+ add eax,esi
+ or esi,esi
+ push eax
+ js run_pscode_63
+ xchg eax,ecx
+run_pscode_63:
+ cmp eax,ecx
+ pop eax
+ jl run_pscode_64
+
+ mov cx,3
+ push eax
+ call set_rstack_tos
+ pop eax
+ mov cx,[pstack_ptr]
+ cmp cx,[pstack_size]
+ jae run_pscode_80
+ inc word [pstack_ptr]
+ xor cx,cx
+ mov dl,t_int
+ call set_pstack_tos
+ jc run_pscode_90
+ xor cx,cx
+ call get_rstack_tos
+ jmp run_pscode_69
+run_pscode_64:
+ mov cx,4
+ call get_rstack_tos
+ sub word [rstack_ptr],byte 5
+ jmp run_pscode_69
+
+
+run_pscode_65:
+ ; repeat
+ cmp word [rstack_ptr],byte 3
+ mov bp,pserr_rstack_underflow
+ jc run_pscode_90
+ push eax
+ mov cx,1
+ call get_rstack_tos
+ pop ebx
+ cmp dl,t_int
+run_pscode_66:
+ mov bp,pserr_invalid_rstack_entry
+ jnz run_pscode_80
+ dec eax
+ jz run_pscode_67
+ mov cx,1
+ push ebx
+ call set_rstack_tos
+ pop eax
+ jmp run_pscode_69
+run_pscode_67:
+ mov cx,2
+ call get_rstack_tos
+ sub word [rstack_ptr],byte 2
+
+run_pscode_68:
+ dec word [rstack_ptr]
+run_pscode_69:
+ mov [pscode_next_instr],eax
+
+ jmp run_pscode_10
+
+run_pscode_70:
+
+%if 0
+; Using undefined values has been legalized.
+; See run_pscode_51 above...
+;
+ cmp dl,t_none
+ mov bp,pserr_nop
+ jz run_pscode_80
+%endif
+
+ cmp dl,t_sec
+ mov bp,pserr_invalid_dict_entry
+ jz run_pscode_80
+
+ cmp dl,t_end
+ mov bp,pserr_ok
+ jz run_pscode_90
+
+ ; illegal opcode
+ mov bp,pserr_invalid_opcode
+run_pscode_80:
+ stc
+run_pscode_90:
+ mov [pscode_error],bp
+ ret
+
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; dl tos type
+; return:
+; eax tos
+; dl actual tos types (even if CF is set)
+; CF error
+;
+get_1arg:
+ xor eax,eax
+ cmp word [pstack_ptr],byte 1
+ mov bp,pserr_pstack_underflow
+ jc get_1arg_90
+ push dx
+ xor cx,cx
+ call get_pstack_tos
+ pop bx
+ ; ignore type check if t_none was requested
+ cmp bl,t_none
+ jz get_1arg_90
+ cmp bl,dl
+ jz get_1arg_90
+ mov bp,pserr_wrong_arg_types
+ stc
+get_1arg_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; dl tos type
+; dh tos + 1 type
+; return:
+; eax tos
+; ecx tos + 1
+; dx actual tos types (even if CF is set)
+; CF error
+;
+get_2args:
+ xor eax,eax
+ xor ecx,ecx
+ mov bx,dx
+ xor dx,dx
+ cmp word [pstack_ptr],byte 2
+ mov bp,pserr_pstack_underflow
+ jc get_2args_90
+ push bx
+ inc cx
+ call get_pstack_tos
+ push dx
+ push eax
+ xor cx,cx
+ call get_pstack_tos
+ pop ecx
+ pop bx
+ mov dh,bl
+ pop bx
+
+ ; ignore type check if t_none was requested
+ cmp bh,t_none
+ jnz get_2args_50
+ mov bh,dh
+get_2args_50:
+ cmp bl,t_none
+ jnz get_2args_60
+ mov bl,dl
+get_2args_60:
+ cmp bx,dx
+ jz get_2args_90
+ mov bp,pserr_wrong_arg_types
+get_2args_80:
+ stc
+get_2args_90:
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Our primary functions.
+;
+prim_astart:
+ mov ax,[pstack_ptr]
+ inc ax
+ cmp [pstack_size],ax
+ mov bp,pserr_pstack_overflow
+ jb prim_astart_90
+ mov [pstack_ptr],ax
+ mov dl,t_prim
+ mov eax,(jt_p_astart - jt_p_none) / 2 ; we need just some mark
+ xor cx,cx
+ call set_pstack_tos
+prim_astart_90:
+ ret
+
+
+prim_aend:
+ xor cx,cx
+prim_aend_10:
+ push cx
+ call get_pstack_tos
+ pop cx
+ mov bp,pserr_pstack_underflow
+ jc prim_aend_90
+ inc cx
+ cmp dl,t_prim
+ jnz prim_aend_10
+ cmp eax,(jt_p_astart - jt_p_none) / 2
+ jnz prim_aend_10
+
+ dec cx
+ push cx
+ mov ax,5
+ mul cx
+ inc ax
+ inc ax
+ movzx eax,ax
+ call calloc
+ pop cx
+ or eax,eax
+ mov bp,pserr_no_memory
+ stc
+ jz prim_aend_90
+
+ push cx
+ push eax
+
+ lin2segofs eax,es,di
+ mov [es:di],cx
+ inc di
+ inc di
+
+prim_aend_40:
+ sub cx,1
+ jc prim_aend_60
+
+ push es
+ push di
+ push cx
+ call get_pstack_tos
+ pop cx
+ pop di
+ pop es
+
+ mov [es:di],dl
+ mov [es:di+1],eax
+ add di,5
+ jmp prim_aend_40
+
+prim_aend_60:
+
+ pop eax
+ pop cx
+ sub [pstack_ptr],cx
+ mov dl,t_array
+ xor cx,cx
+ call set_pstack_tos
+prim_aend_90:
+ ret
+
+
+prim_get:
+ mov dx,t_int + (t_array << 8)
+ call get_2args
+ jnc prim_get_10
+ cmp dx,t_int + (t_string << 8)
+ jz prim_get_10
+ cmp dx,t_int + (t_ptr << 8)
+ stc
+ jnz prim_get_90
+prim_get_10:
+ call p_get
+ jc prim_get_90
+
+ dec word [pstack_ptr]
+ xor cx,cx
+ call set_pstack_tos
+prim_get_90:
+ ret
+
+
+; dh, ecx obj
+; eax index
+; Return:
+; dl, eax element
+; CF 0/1 ok/not ok
+;
+p_get:
+ cmp dh,t_array
+ jz p_get_50
+ cmp dh,t_string
+ jz p_get_10
+ cmp dh,t_ptr
+ stc
+ jnz p_get_90
+p_get_10:
+ add ecx,eax
+ lin2segofs ecx,es,di
+ mov dl,t_int
+ movzx eax,byte [es:di]
+ jmp p_get_80
+p_get_50:
+ lin2segofs ecx,es,di
+ mov bp,pserr_invalid_range
+ cmp ax,[es:di]
+ cmc
+ jc p_get_90
+
+ add di,ax
+ add ax,ax
+ add ax,ax
+ add di,ax
+
+ mov dl,[es:di+2]
+ mov eax,[es:di+3]
+p_get_80:
+ clc
+p_get_90:
+ ret
+
+prim_put:
+ mov bp,pserr_pstack_underflow
+ cmp word [pstack_ptr],byte 3
+ jc prim_put_90
+
+ mov bp,pserr_wrong_arg_types
+ mov cx,2
+ call get_pstack_tos
+ mov dh,0
+ push dx
+ push eax
+ mov dx,t_none + (t_int << 8)
+ call get_2args
+ pop ebx
+ pop bp
+ shl edx,16
+ mov dx,bp
+ rol edx,8
+ cmp dx,t_int + (t_array << 8)
+ jz prim_put_50
+ cmp edx,t_int + (t_string << 8) + (t_int << 24)
+ jz prim_put_30
+ cmp edx,t_int + (t_ptr << 8) + (t_int << 24)
+ stc
+ mov bp,pserr_wrong_arg_types
+ jnz prim_put_90
+prim_put_30:
+ add ebx,ecx
+ lin2segofs ebx,es,di
+ mov [es:di],al
+ jmp prim_put_80
+prim_put_50:
+ shr edx,24
+ lin2segofs ebx,es,di
+
+ cmp cx,[es:di]
+ cmc
+ mov bp,pserr_invalid_range
+ jc prim_put_90
+
+ add di,cx
+ add cx,cx
+ add cx,cx
+ add di,cx
+
+ mov [es:di+2],dl
+ mov [es:di+3],eax
+
+prim_put_80:
+ sub word [pstack_ptr],byte 3
+prim_put_90:
+ ret
+
+
+prim_length:
+ mov dl,t_none
+ call get_1arg
+ jc prim_length_90
+ call get_length
+ jc prim_length_90
+ xor cx,cx
+ mov dl,t_int
+ call set_pstack_tos
+prim_length_90:
+ ret
+
+
+; dl, eax obj
+; Return:
+; eax length
+; CF 0/1 ok/not ok
+;
+get_length:
+ cmp dl,t_ptr
+ jz get_length_10
+ lin2segofs eax,es,si
+ cmp dl,t_array
+ jz get_length_20
+ cmp dl,t_string
+ jz get_length_30
+ stc
+ jmp get_length_90
+get_length_10:
+ call find_mem_size
+ jmp get_length_80
+get_length_20:
+ movzx eax,word [es:si]
+ jmp get_length_80
+get_length_30:
+ xor cx,cx
+ xor eax,eax
+get_length_40:
+ es lodsb
+ call is_eot
+ loopnz get_length_40 ; max 64k length
+ not cx
+ movzx eax,cx
+get_length_80:
+ clc
+get_length_90:
+ ret
+
+
+prim_array:
+ mov dl,t_int
+ call get_1arg
+ jc prim_array_90
+ cmp eax,(0fff0h-2)/5
+ cmc
+ mov bp,pserr_invalid_range
+ jc prim_array_90
+ push ax
+ mov cx,5
+ mul cx
+ inc ax
+ inc ax
+ call calloc
+ pop cx
+ or eax,eax
+ stc
+ mov bp,pserr_no_memory
+ jz prim_array_90
+
+ lin2segofs eax,es,di
+ mov [es:di],cx
+
+ xor cx,cx
+ mov dl,t_array
+ call set_pstack_tos
+prim_array_90:
+ ret
+
+
+prim_pop:
+ cmp word [pstack_ptr],byte 1
+ mov bp,pserr_pstack_underflow
+ jc prim_pop_90
+ dec word [pstack_ptr]
+prim_pop_90:
+ ret
+
+prim_dup:
+ mov cx,[pstack_ptr]
+ cmp cx,[pstack_size]
+ cmc
+ mov bp,pserr_pstack_overflow
+ jb prim_dup_90
+ xor cx,cx
+ call get_pstack_tos
+ mov bp,pserr_pstack_underflow
+ jc prim_dup_90
+ mov cx,0
+ inc word [pstack_ptr]
+ call set_pstack_tos
+prim_dup_90:
+ ret
+
+
+prim_over:
+ mov cx,[pstack_ptr]
+ cmp cx,[pstack_size]
+ cmc
+ mov bp,pserr_pstack_overflow
+ jb prim_over_90
+ mov cx,1
+ call get_pstack_tos
+ mov bp,pserr_pstack_underflow
+ jc prim_over_90
+ mov cx,0
+ inc word [pstack_ptr]
+ call set_pstack_tos
+prim_over_90:
+ ret
+
+
+prim_index:
+ mov dl,t_int
+ call get_1arg
+ jc prim_index_90
+
+ movzx edx,word [pstack_ptr]
+ sub edx,2
+ jc prim_index_90
+ cmp edx,eax
+ mov bp,pserr_pstack_underflow
+ jc prim_index_90
+
+ inc ax
+ xchg ax,cx
+ call get_pstack_tos
+ xor cx,cx
+ call set_pstack_tos
+prim_index_90:
+ ret
+
+
+prim_exec:
+ mov dl,t_dict_idx
+ call pr_setobj_or_none
+ mov [pscode_eval],eax
+ ret
+
+
+prim_add:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jnc prim_add_50
+ cmp dx,t_int + (t_string << 8)
+ jz prim_add_50
+ cmp dx,t_int + (t_ptr << 8)
+ stc
+ jnz prim_add_90
+prim_add_50:
+ add eax,ecx
+ dec word [pstack_ptr]
+ xor cx,cx
+ mov dl,dh
+ call set_pstack_tos
+prim_add_90:
+ ret
+
+
+prim_sub:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jnc prim_sub_50
+ cmp dx,t_int + (t_string << 8)
+ jz prim_sub_50
+ cmp dx,t_int + (t_ptr << 8)
+ stc
+ jnz prim_sub_90
+prim_sub_50:
+ xchg eax,ecx
+ sub eax,ecx
+ dec word [pstack_ptr]
+ xor cx,cx
+ mov dl,dh
+ call set_pstack_tos
+prim_sub_90:
+ ret
+
+prim_mul:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_mul_90
+ imul ecx
+ dec word [pstack_ptr]
+ xor cx,cx
+ mov dl,t_int
+ call set_pstack_tos
+prim_mul_90:
+ ret
+
+
+prim_div:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_div_90
+ or eax,eax
+ stc
+ mov bp,pserr_div_by_zero
+ jz prim_div_90
+ xchg eax,ecx
+ cdq
+ idiv ecx
+ dec word [pstack_ptr]
+ xor cx,cx
+ mov dl,t_int
+ call set_pstack_tos
+prim_div_90:
+ ret
+
+
+prim_mod:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_mod_90
+ or eax,eax
+ stc
+ mov bp,pserr_div_by_zero
+ jz prim_div_90
+ xchg eax,ecx
+ cdq
+ idiv ecx
+ xchg eax,edx
+ dec word [pstack_ptr]
+ xor cx,cx
+ mov dl,t_int
+ call set_pstack_tos
+prim_mod_90:
+ ret
+
+prim_neg:
+ mov dl,t_int
+ call get_1arg
+ jc prim_neg_90
+ neg eax
+ xor cx,cx
+ call set_pstack_tos
+prim_neg_90:
+ ret
+
+prim_abs:
+ mov dl,t_int
+ call get_1arg
+ jc prim_abs_90
+ or eax,eax
+ jns prim_abs_50
+ neg eax
+prim_abs_50:
+ xor cx,cx
+ call set_pstack_tos
+prim_abs_90:
+ ret
+
+prim_min:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_min_90
+ cmp eax,ecx
+ jle prim_min_50
+ xchg eax,ecx
+prim_min_50:
+ dec word [pstack_ptr]
+ xor cx,cx
+ call set_pstack_tos
+prim_min_90:
+ ret
+
+prim_max:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_max_90
+ cmp eax,ecx
+ jge prim_max_50
+ xchg eax,ecx
+prim_max_50:
+ dec word [pstack_ptr]
+ xor cx,cx
+ call set_pstack_tos
+prim_max_90:
+ ret
+
+plog_args:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jnc plog_args_90
+ cmp dx,t_int + (t_bool << 8)
+ jz plog_args_20
+ cmp dx,t_bool + (t_int << 8)
+ jz plog_args_20
+ cmp dx,t_bool + (t_bool << 8)
+ jz plog_args_20
+ stc
+ pop ax
+ jmp plog_args_90
+plog_args_20:
+ mov dl,t_bool
+ or eax,eax
+ setnz al
+ movzx eax,al
+ or ecx,ecx
+ setnz cl
+ movzx ecx,cl
+plog_args_90:
+ ret
+
+
+prim_and:
+ call plog_args
+ and eax,ecx
+prim_and_50:
+ dec word [pstack_ptr]
+ xor cx,cx
+ call set_pstack_tos
+ ret
+
+prim_or:
+ call plog_args
+ or eax,ecx
+ jmp prim_and_50
+
+prim_xor:
+ call plog_args
+ xor eax,ecx
+ jmp prim_and_50
+
+prim_not:
+ xor cx,cx
+ call get_pstack_tos
+ jc prim_not_90
+ cmp dl,t_int
+ jz prim_not_50
+ cmp dl,t_bool
+ mov bp,pserr_wrong_arg_types
+ stc
+ jnz prim_not_90
+ xor al,1
+ not eax
+prim_not_50:
+ not eax
+ xor cx,cx
+ call set_pstack_tos
+prim_not_90:
+ ret
+
+
+prim_shl:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_shl_90
+ xchg eax,ecx
+ shl eax,cl
+ cmp ecx,byte 20h
+ jb prim_shl_50
+ xor eax,eax
+prim_shl_50:
+ dec word [pstack_ptr]
+ xor cx,cx
+ call set_pstack_tos
+prim_shl_90:
+ ret
+
+
+prim_shr:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_shr_90
+ xchg eax,ecx
+ cmp ecx,byte 20h
+ jb prim_shr_50
+ mov cl,1fh
+prim_shr_50:
+ sar eax,cl
+ dec word [pstack_ptr]
+ xor cx,cx
+ call set_pstack_tos
+prim_shr_90:
+ ret
+
+
+prim_def:
+ mov dx,t_none + (t_dict_idx << 8)
+ call get_2args
+ jc prim_def_90
+ cmp dl,t_sec
+ mov bp,pserr_wrong_arg_types
+ stc
+ jz prim_def_90
+ ; note: cx is index
+ call set_dict_entry
+ mov bp,pserr_invalid_dict
+ jc prim_def_90
+ sub word [pstack_ptr],byte 2
+prim_def_90:
+ ret
+
+
+prim_if:
+ mov dx,t_code + (t_bool << 8)
+ call get_2args
+ jnc prim_if_20
+ cmp dh,t_int
+ jz prim_if_20
+ cmp dh,t_none
+ jz prim_if_20
+ mov cl,1 ; all pointer, strings, arrays are 'true'
+ cmp dh,t_ptr
+ jz prim_if_20
+ cmp dh,t_string
+ jz prim_if_20
+ cmp dh,t_array
+ jnz prim_if_80
+prim_if_20:
+ sub word [pstack_ptr],byte 2
+ or ecx,ecx
+ jz prim_if_90
+
+ ; branch
+ xchg eax,[pscode_next_instr]
+
+ mov cx,[rstack_ptr]
+ cmp cx,[rstack_size]
+ mov bp,pserr_rstack_overflow
+ jae prim_if_80
+ inc word [rstack_ptr]
+
+ xor cx,cx
+ mov dl,t_if ; mark as 'if' block
+ call set_rstack_tos
+ jnc prim_if_90
+
+prim_if_80:
+ stc
+prim_if_90:
+ ret
+
+
+prim_ifelse:
+ mov cx,2
+ call get_pstack_tos
+ jc prim_ifelse_90
+ mov bp,pserr_wrong_arg_types
+ cmp dl,t_bool
+ jz prim_ifelse_10
+ cmp dl,t_int
+ jz prim_ifelse_10
+ cmp dl,t_none
+ jz prim_ifelse_10
+ mov al,1 ; all pointer, strings, arrays are 'true'
+ cmp dl,t_ptr
+ jz prim_ifelse_10
+ cmp dl,t_string
+ jz prim_ifelse_10
+ cmp dl,t_array
+ jnz prim_ifelse_80
+prim_ifelse_10:
+ push eax
+ mov dx,t_code + (t_code << 8)
+ call get_2args
+ pop ebx
+ jc prim_ifelse_90
+
+ sub word [pstack_ptr],byte 3
+ or ebx,ebx
+ jz prim_ifelse_20
+ xchg dl,dh
+ xchg eax,ecx
+prim_ifelse_20:
+ ; branch
+ xchg eax,[pscode_next_instr]
+
+ mov cx,[rstack_ptr]
+ cmp cx,[rstack_size]
+ mov bp,pserr_rstack_overflow
+ jae prim_ifelse_80
+ inc word [rstack_ptr]
+
+ xor cx,cx
+ mov dl,t_if ; mark as 'if' block
+ call set_rstack_tos
+ jnc prim_ifelse_90
+
+prim_ifelse_80:
+ stc
+prim_ifelse_90:
+ ret
+
+
+
+; compare 2 strings
+; return:
+; cl, al last compared chars (if !=)
+; edx length of identical parts
+pcmp_str:
+ push fs
+ lin2segofs eax,fs,si
+ lin2segofs ecx,es,di
+
+ xor ecx,ecx
+ xor eax,eax
+ xor edx,edx
+pcmp_str_20:
+ mov ah,al
+ mov ch,cl
+ mov al,[fs:si]
+ mov cl,[es:di]
+ cmp al,cl
+ jnz pcmp_str_50
+ or al,al
+ jz pcmp_str_50
+ or cl,cl
+ jz pcmp_str_50
+ inc si
+ jnz pcmp_str_30
+ mov bx,fs
+ add bx,1000h
+ mov fs,bx
+pcmp_str_30:
+ inc di
+ jnz pcmp_str_40
+ mov bx,es
+ add bx,1000h
+ mov es,bx
+pcmp_str_40:
+ inc edx
+ cmp edx,1 << 20 ; avoid infinite loop
+ jb pcmp_str_20
+pcmp_str_50:
+ pop fs
+ ret
+
+
+pcmp_args:
+ ; integer
+ mov dx,t_int + (t_int << 8)
+ push bx
+ call get_2args
+ pop bx
+ jnc pcmp_args_90
+
+ ; strings
+ cmp dx,t_string + (t_string << 8)
+ jz pcmp_args_60
+
+ ; two identical objects
+ cmp dl,dh
+ jz pcmp_args_90
+
+ cmp bl,1
+ jc pcmp_args_80
+
+ cmp eax,ecx
+ jnz pcmp_args_90
+ mov al,dl
+ mov cl,dh
+ jmp pcmp_args_90
+
+pcmp_args_60:
+ call pcmp_str
+
+ jmp pcmp_args_90
+pcmp_args_80:
+ pop ax ; skip last return
+pcmp_args_90:
+ ret
+
+pcmp_true:
+ mov dl,t_bool
+ mov eax,1
+ dec word [pstack_ptr]
+ xor cx,cx
+ call set_pstack_tos
+ ret
+
+pcmp_false:
+ mov dl,t_bool
+ mov eax,0
+ dec word [pstack_ptr]
+ xor cx,cx
+ call set_pstack_tos
+ ret
+
+prim_eq:
+ mov bl,1
+ call pcmp_args
+ cmp ecx,eax
+ jz pcmp_true
+ jmp pcmp_false
+
+prim_ne:
+ mov bl,1
+ call pcmp_args
+ cmp ecx,eax
+ jnz pcmp_true
+ jmp pcmp_false
+
+prim_gt:
+ mov bl,0
+ call pcmp_args
+ cmp ecx,eax
+ jg pcmp_true
+ jmp pcmp_false
+
+prim_ge:
+ mov bl,0
+ call pcmp_args
+ cmp ecx,eax
+ jge pcmp_true
+ jmp pcmp_false
+
+prim_lt:
+ mov bl,0
+ call pcmp_args
+ cmp ecx,eax
+ jl pcmp_true
+ jmp pcmp_false
+
+prim_le:
+ mov bl,0
+ call pcmp_args
+ cmp ecx,eax
+ jle pcmp_true
+ jmp pcmp_false
+
+
+prim_exch:
+ mov cx,2
+ call rot_pstack_up
+ mov bp,pserr_pstack_underflow
+ ret
+
+
+prim_rot:
+ mov cx,3
+ call rot_pstack_up
+ mov bp,pserr_pstack_underflow
+ ret
+
+
+prim_roll:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_roll_90
+ or ecx,ecx
+ jz prim_roll_90
+ movzx edx,word [pstack_ptr]
+ sub edx,2
+ cmp edx,ecx
+ mov bp,pserr_pstack_underflow
+ jc prim_roll_90
+ cdq
+ idiv ecx
+ sub word [pstack_ptr],byte 2
+ ; ecx is max. 14 bit
+ or dx,dx
+ jz prim_roll_90
+ js prim_roll_50
+prim_roll_40:
+ push dx
+ push cx
+ call rot_pstack_down
+ pop cx
+ pop dx
+ dec dx
+ jnz prim_roll_40
+ jmp prim_roll_90
+prim_roll_50:
+ neg dx
+prim_roll_60:
+ push dx
+ push cx
+ call rot_pstack_up
+ pop cx
+ pop dx
+ dec dx
+ jnz prim_roll_60
+ clc
+prim_roll_90:
+ ret
+
+prim_dtrace:
+ mov byte [single_step],1
+ mov byte [show_debug_info],1
+ ret
+
+prim_trace:
+ mov byte [single_step],1
+ mov byte [show_debug_info],0
+ ret
+
+prim_return:
+ xor cx,cx
+prim_return_10:
+ push cx
+ call get_rstack_tos
+ pop cx
+ mov bp,pserr_rstack_underflow
+ jc prim_return_90
+ inc cx
+ cmp dl,t_code
+ jnz prim_return_10 ; skip if, loop, repeat, for, forall
+
+ sub [rstack_ptr],cx
+ mov [pscode_next_instr],eax
+prim_return_90:
+ ret
+
+
+prim_exit:
+ xor cx,cx
+prim_exit_10:
+ push cx
+ call get_rstack_tos
+ pop cx
+ mov bp,pserr_rstack_underflow
+ jc prim_exit_90
+ inc cx
+ cmp dl,t_loop ; loop
+ jz prim_exit_60
+ cmp dl,t_repeat ; repeat
+ jz prim_exit_40
+ cmp dl,t_for ; for
+ jz prim_exit_30
+ cmp dl,t_forall ; forall
+ jnz prim_exit_10
+prim_exit_30:
+ inc cx
+ inc cx
+prim_exit_40:
+ inc cx
+prim_exit_60:
+ push cx
+ call get_rstack_tos
+ pop cx
+ cmp dl,t_code
+ jz prim_exit_80
+ cmp dl,t_exit
+ mov bp,pserr_invalid_rstack_entry
+ stc
+ jnz prim_exit_90
+
+prim_exit_80:
+ inc cx
+ sub [rstack_ptr],cx
+ mov [pscode_next_instr],eax
+prim_exit_90:
+ ret
+
+prim_loop:
+ xor cx,cx
+ call get_pstack_tos
+ cmp dl,t_code
+ mov bp,pserr_wrong_arg_types
+ stc
+ jnz prim_loop_90
+
+ dec word [pstack_ptr]
+
+ ; branch
+ xchg eax,[pscode_next_instr]
+
+ mov cx,[rstack_size]
+ sub cx,[rstack_ptr]
+ cmp cx,3
+ mov bp,pserr_rstack_overflow
+ jb prim_loop_90
+ add word [rstack_ptr],byte 2
+
+ mov dl,t_exit
+ mov cx,1
+ call set_rstack_tos
+ xor cx,cx
+ mov dl,t_loop ; mark as 'loop' block
+ mov eax,[pscode_next_instr]
+ call set_rstack_tos
+prim_loop_90:
+ ret
+
+
+prim_repeat:
+ mov dx,t_code + (t_int << 8)
+ call get_2args
+ jc prim_repeat_90
+
+ sub word [pstack_ptr],byte 2
+
+ or ecx,ecx
+ jz prim_repeat_90
+
+ mov bp,pserr_invalid_range
+ stc
+ js prim_repeat_90
+
+ ; branch
+ xchg eax,[pscode_next_instr]
+
+ mov dx,[rstack_size]
+ sub dx,[rstack_ptr]
+ cmp dx,4
+ mov bp,pserr_rstack_overflow
+ jb prim_repeat_90
+ add word [rstack_ptr],byte 3
+
+ push eax
+ xchg eax,ecx
+ mov dl,t_int
+ mov cx,1
+ call set_rstack_tos
+ pop eax
+ mov cx,2
+ mov dl,t_exit
+ call set_rstack_tos
+ xor cx,cx
+ mov dl,t_repeat ; mark as 'repeat' block
+ mov eax,[pscode_next_instr]
+ call set_rstack_tos
+prim_repeat_90:
+ ret
+
+
+prim_for:
+ mov bp,pserr_pstack_underflow
+ cmp word [pstack_ptr],byte 4
+ jc prim_for_90
+ mov cx,3
+ call get_pstack_tos
+ cmp dl,t_int
+ stc
+ mov bp,pserr_wrong_arg_types
+ jnz prim_for_90
+ mov cx,2
+ push bp
+ push eax
+ call get_pstack_tos
+ pop edi
+ pop bp
+ cmp dl,t_int
+ stc
+ jnz prim_for_90
+
+ mov dx,t_code + (t_int << 8)
+ push eax
+ push edi
+ call get_2args
+ pop edi
+ pop esi
+ jc prim_for_90
+
+ ; don't remove start value!
+ sub word [pstack_ptr],byte 3
+
+ ; branch
+ xchg eax,[pscode_next_instr]
+
+ mov dx,[rstack_size]
+ sub dx,[rstack_ptr]
+ cmp dx,6
+ mov bp,pserr_rstack_overflow
+ jb prim_for_90
+ add word [rstack_ptr],byte 5
+
+ push ecx
+ push esi
+ push edi
+
+ mov dl,t_exit
+ mov cx,4
+ call set_rstack_tos
+
+ pop eax
+ mov dl,t_int
+ mov cx,3
+ call set_rstack_tos
+
+ pop eax
+ mov dl,t_int
+ mov cx,2
+ call set_rstack_tos
+
+ pop eax
+ mov dl,t_int
+ mov cx,1
+ call set_rstack_tos
+
+ xor cx,cx
+ mov dl,t_for ; mark as 'for' block
+ mov eax,[pscode_next_instr]
+ call set_rstack_tos
+prim_for_90:
+ ret
+
+
+prim_forall:
+ mov dx,t_code + (t_array << 8)
+ call get_2args
+ jnc prim_forall_30
+ cmp dl,t_code
+ stc
+ jnz prim_forall_90
+ cmp dh,t_string
+ jz prim_forall_30
+ cmp dh,t_ptr
+ jz prim_forall_30
+ cmp dh,t_none
+ stc
+ jnz prim_forall_90
+
+ ; nothing to do
+prim_forall_20:
+ sub word [pstack_ptr],2
+ clc
+ jmp prim_forall_90
+
+prim_forall_30:
+ push eax ; code
+ push ecx ; string/array
+ xchg dl,dh
+ push dx
+ xchg eax,ecx
+ call get_length
+ pop dx
+ pop ecx
+ pop ebx
+
+ mov bp,pserr_invalid_range
+ jc prim_forall_90
+
+ or eax,eax ; length == 0
+ jz prim_forall_20
+
+ sub word [pstack_ptr],2
+
+ ; branch
+ xchg ebx,[pscode_next_instr]
+
+ mov si,[rstack_size]
+ sub si,[rstack_ptr]
+ cmp si,6
+ mov bp,pserr_rstack_overflow
+ jb prim_forall_90
+ add word [rstack_ptr],5
+
+ push ecx
+ push dx
+ push eax
+
+ mov dl,t_exit
+ xchg eax,ebx
+ mov cx,4
+ call set_rstack_tos ; code
+
+ pop eax
+ mov dl,t_int
+ mov cx,2
+ call set_rstack_tos ; length
+
+ pop dx
+ pop eax
+ push eax
+ push dx
+ mov cx,3
+ call set_rstack_tos ; string/array
+
+ xor eax,eax
+ mov dl,t_int
+ mov cx,1
+ call set_rstack_tos ; count
+
+ xor cx,cx
+ mov dl,t_forall ; mark as 'forall' block
+ mov eax,[pscode_next_instr]
+ call set_rstack_tos
+
+ pop dx
+ pop ecx
+ xchg dl,dh
+ xor eax,eax
+ call p_get
+ mov bp,pserr_invalid_range
+ jc prim_forall_90
+
+ jmp pr_getobj
+
+prim_forall_90:
+ ret
+
+
+prim_gettype:
+ mov dl,t_none
+ call get_1arg
+ jc prim_gettype_90
+ movzx eax,dl
+ mov dl,t_int
+ xor cx,cx
+ call set_pstack_tos
+prim_gettype_90:
+ ret
+
+
+prim_settype:
+ mov dx,t_int + (t_none << 8)
+ call get_2args
+ jc prim_settype_90
+ mov dl,al
+ and al,15
+ xchg eax,ecx
+ dec word [pstack_ptr]
+ xor cx,cx
+ call set_pstack_tos
+prim_settype_90:
+ ret
+
+
+prim_screensize:
+ mov ax,[pstack_ptr]
+ inc ax
+ inc ax
+ cmp [pstack_size],ax
+ mov bp,pserr_pstack_overflow
+ jb prim_screensize_90
+ mov [pstack_ptr],ax
+ mov dl,t_int
+ movzx eax,word [screen_width]
+ mov cx,1
+ call set_pstack_tos
+ mov dl,t_int
+ movzx eax,word [screen_height]
+ xor cx,cx
+ call set_pstack_tos
+prim_screensize_90:
+ ret
+
+
+prim_imagesize:
+ mov ax,[pstack_ptr]
+ inc ax
+ inc ax
+ cmp [pstack_size],ax
+ mov bp,pserr_pstack_overflow
+ jb prim_imagesize_90
+ mov [pstack_ptr],ax
+ mov dl,t_int
+ movzx eax,word [image_width]
+ mov cx,1
+ call set_pstack_tos
+ mov dl,t_int
+ movzx eax,word [image_height]
+ xor cx,cx
+ call set_pstack_tos
+prim_imagesize_90:
+ ret
+
+
+prim_imagecolors:
+ movzx eax,word [pals]
+ jmp pr_getint
+
+
+prim_setcolor:
+ call pr_setint
+ mov [gfx_color0],eax
+ call setcolor
+ ret
+
+
+prim_currentcolor:
+ mov eax,[gfx_color0]
+ jmp pr_getint
+
+
+prim_moveto:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_moveto_90
+ sub word [pstack_ptr],byte 2
+ mov [gfx_cur_x],cx
+ mov [gfx_cur_y],ax
+prim_moveto_90:
+ ret
+
+
+prim_rmoveto:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_rmoveto_90
+ sub word [pstack_ptr],byte 2
+ add [gfx_cur_x],cx
+ add [gfx_cur_y],ax
+ clc
+prim_rmoveto_90:
+ ret
+
+
+prim_currentpoint:
+ mov ax,[pstack_ptr]
+ inc ax
+ inc ax
+ cmp [pstack_size],ax
+ mov bp,pserr_pstack_overflow
+ jb prim_currentpoint_90
+ mov [pstack_ptr],ax
+ mov dl,t_int
+ movzx eax,word [gfx_cur_x]
+ mov cx,1
+ call set_pstack_tos
+ mov dl,t_int
+ movzx eax,word [gfx_cur_y]
+ xor cx,cx
+ call set_pstack_tos
+prim_currentpoint_90:
+ ret
+
+
+prim_lineto:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_lineto_90
+
+ mov [line_x1],ecx
+ mov [line_y1],eax
+ push cx
+ push ax
+ movsx eax,word [gfx_cur_x]
+ mov [line_x0],eax
+ movsx eax,word [gfx_cur_y]
+ mov [line_y0],eax
+ call line
+ pop word [gfx_cur_y]
+ pop word [gfx_cur_x]
+
+ sub word [pstack_ptr],byte 2
+prim_lineto_90:
+ ret
+
+
+prim_putpixel:
+ call goto_xy
+ call screen_segs
+ call [setpixel_t]
+ clc
+ ret
+
+
+prim_getpixel:
+ call goto_xy
+ call screen_seg_r
+ mov si,di
+ xor eax,eax
+ call [getpixel]
+ jmp pr_getint
+
+
+prim_setfont:
+ call pr_setptr_or_none
+ call font_init
+ ret
+
+
+prim_currentfont:
+ push dword [font]
+ call so2lin
+ pop eax
+ jmp pr_getptr_or_none
+
+
+prim_fontheight:
+ movzx eax,word [font_height]
+ jmp pr_getint
+
+
+prim_setimage:
+ call pr_setptr_or_none
+ call image_init
+ ret
+
+
+prim_currentimage:
+ mov eax,[image]
+ jmp pr_getptr_or_none
+
+
+prim_settransparency:
+ call pr_setint
+ mov [transp],eax
+ ret
+
+
+prim_currenttransparency:
+ mov eax,[transp]
+ jmp pr_getint
+
+
+prim_show:
+ mov dl,t_string
+ call get_1arg
+ jc prim_show_90
+ dec word [pstack_ptr]
+ lin2segofs eax,es,si
+ mov bx,[start_row]
+ or bx,bx
+ jz prim_show_50
+ cmp bx,[cur_row2]
+ jae prim_show_90
+ add bx,bx
+ mov si,[bx + row_start_ofs]
+ mov es,[row_start_seg]
+prim_show_50:
+ call text_xy
+ clc
+prim_show_90:
+ ret
+
+
+prim_strsize:
+ mov dl,t_string
+ call get_1arg
+ jc prim_strsize_90
+ dec word [pstack_ptr]
+ lin2segofs eax,es,si
+ call str_size
+
+ mov ax,[pstack_ptr]
+ inc ax
+ inc ax
+ cmp [pstack_size],ax
+ mov bp,pserr_pstack_overflow
+ jb prim_strsize_90
+ mov [pstack_ptr],ax
+ push dx
+ movzx eax,cx
+ mov dl,t_int
+ mov cx,1
+ call set_pstack_tos
+ pop ax
+ mov dl,t_int
+ movzx eax,ax
+ xor cx,cx
+ call set_pstack_tos
+prim_strsize_90:
+ ret
+
+
+prim_image:
+ mov bp,pserr_pstack_underflow
+ cmp word [pstack_ptr],byte 4
+ jc prim_image_90
+ mov cx,3
+ call get_pstack_tos
+ cmp dl,t_int
+ stc
+ mov bp,pserr_wrong_arg_types
+ jnz prim_image_90
+ mov [line_x0],eax
+ mov cx,2
+ push bp
+ call get_pstack_tos
+ pop bp
+ cmp dl,t_int
+ stc
+ jnz prim_image_90
+ mov [line_y0],eax
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_image_90
+
+ sub word [pstack_ptr],byte 4
+
+ ; clip image width
+ ; note: image height is handled in draw_image
+ mov edx,[line_x0]
+ add edx,ecx
+ movzx ebx,word [image_width]
+ sub edx,ebx
+ jle prim_image_40
+ sub ecx,edx
+prim_image_40:
+
+ cmp ecx,byte 0
+ jle prim_image_90
+ cmp eax,byte 0
+ jz prim_image_90
+ mov [line_x1],ecx
+ mov [line_y1],eax
+ push dword [gfx_cur]
+ call draw_image
+ pop dword [gfx_cur]
+
+ clc
+prim_image_90:
+ ret
+
+
+prim_loadpalette:
+ mov cx,100h
+ xor dx,dx
+ call load_palette
+ clc
+ ret
+
+prim_tint:
+ mov bp,pserr_pstack_underflow
+ cmp word [pstack_ptr],byte 3
+ jc prim_tint_90
+ mov bp,pserr_wrong_arg_types
+ mov cx,2
+ call get_pstack_tos
+ cmp dl,t_int
+ stc
+ jnz prim_tint_90
+ push ax
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ pop dx
+ jc prim_tint_90
+
+ sub word [pstack_ptr],byte 3
+
+ xchg ax,bx
+
+ push cx
+ push bx
+ call tint
+ pop dx
+ pop cx
+
+ call load_palette
+ clc
+prim_tint_90:
+ ret
+
+
+prim_settintcolor:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_settintcolor_90
+
+ sub word [pstack_ptr],byte 2
+
+ mov [gfx_cs_tint_b],al
+ mov [gfx_cs_tint_g],ah
+ shr eax,16
+ mov [gfx_cs_tint_r],al
+ mov [gfx_cs_b],cl
+ mov [gfx_cs_g],ch
+ shr ecx,16
+ mov [gfx_cs_r],cl
+
+ clc
+
+prim_settintcolor_90:
+ ret
+
+
+prim_setpalette:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_setpalette_90
+
+ sub word [pstack_ptr],byte 2
+
+ cmp ecx,100h
+ jae prim_setpalette_90
+
+ push cx
+ les di,[gfx_pal]
+ add di,cx
+ add di,cx
+ add di,cx
+ mov [es:di+2],al
+ mov [es:di+1],ah
+ shr eax,16
+ mov [es:di],al
+ pop dx
+ mov cx,1
+ call load_palette
+
+ clc
+
+prim_setpalette_90:
+ ret
+
+
+prim_getpalette:
+ mov dl,t_int
+ call get_1arg
+ jc prim_getpalette_90
+
+ xchg eax,ecx
+ xor eax,eax
+ cmp ecx,100h
+ jae prim_getpalette_50
+
+ les di,[gfx_pal]
+ add di,cx
+ add di,cx
+ add di,cx
+ mov al,[es:di]
+ shl eax,16
+ mov ah,[es:di+1]
+ mov al,[es:di+2]
+prim_getpalette_50:
+ mov dl,t_int
+ xor cx,cx
+ call set_pstack_tos
+prim_getpalette_90:
+ ret
+
+
+prim_settransparentcolor:
+ call pr_setint
+ mov [transparent_color],ax
+ ret
+
+
+prim_savescreen:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_savescreen_90
+ push ax
+ push cx
+ mul ecx
+ mul dword [pixel_bytes]
+ pop dx
+ pop cx
+ mov bp,pserr_invalid_image_size
+ add eax,4
+ jc prim_savescreen_90
+ cmp eax,1 << 20
+ cmc
+ jc prim_savescreen_90
+ push cx
+ push dx
+ call malloc
+ pop dx
+ pop cx
+ or eax,eax
+ jz prim_savescreen_50
+ lin2segofs eax,es,di
+ mov [es:di],dx
+ mov [es:di+2],cx
+ add di,4
+ push eax
+ call save_bg
+ pop eax
+prim_savescreen_50:
+ dec word [pstack_ptr]
+ xor cx,cx
+ mov dl,t_ptr
+ or eax,eax
+ jnz prim_savescreen_70
+ mov dl,t_none
+prim_savescreen_70:
+ call set_pstack_tos
+prim_savescreen_90:
+ ret
+
+
+prim_restorescreen:
+ mov dl,t_ptr
+ call get_1arg
+ jnc prim_restorescreen_20
+ cmp dl,t_none
+ stc
+ jnz prim_restorescreen_90
+
+ jmp prim_restorescreen_80
+
+prim_restorescreen_20:
+ cmp eax,100000h
+ jb prim_restorescreen_50
+
+ call real_to_pm
+ jc prim_restorescreen_80
+
+ mov dx,[es:eax]
+ mov cx,[es:eax+2]
+
+ call pm_to_real
+
+ mov bx,dx
+ imul bx,[pixel_bytes]
+ lea edi,[eax+4]
+
+ call xrestore_bg
+
+ jmp prim_restorescreen_80
+prim_restorescreen_50:
+ lin2segofs eax,es,di
+ mov dx,[es:di]
+ mov cx,[es:di+2]
+ add di,4
+ mov bx,dx
+ imul bx,[pixel_bytes]
+ call restore_bg
+prim_restorescreen_80:
+ dec word [pstack_ptr]
+ clc
+prim_restorescreen_90:
+ ret
+
+
+prim_malloc:
+ mov dl,t_int
+ call get_1arg
+ jc prim_malloc_90
+ call calloc
+ or eax,eax
+ stc
+ mov bp,pserr_no_memory
+ jz prim_malloc_90
+ xor cx,cx
+ mov dl,t_ptr
+ call set_pstack_tos
+prim_malloc_90:
+ ret
+
+
+prim_free:
+ mov dl,t_string
+ call get_1arg
+ jnc prim_free_10
+ cmp dl,t_ptr
+ jz prim_free_10
+ cmp dl,t_none
+ jz prim_free_50
+ cmp dl,t_array
+ stc
+ jnz prim_free_90
+prim_free_10:
+ call free
+prim_free_50:
+ dec word [pstack_ptr]
+ clc
+prim_free_90:
+ ret
+
+
+prim_memsize:
+ mov ax,[pstack_ptr]
+ inc ax
+ inc ax
+ cmp [pstack_size],ax
+ mov bp,pserr_pstack_overflow
+ jb prim_memsize_90
+ mov [pstack_ptr],ax
+ call memsize
+ mov dl,t_int
+ xchg eax,ebp
+ push edi
+ mov cx,1
+ call set_pstack_tos
+ pop eax
+ mov dl,t_int
+ xor cx,cx
+ call set_pstack_tos
+prim_memsize_90:
+ ret
+
+prim_dumpmem:
+%if debug
+ call dump_malloc
+%endif
+ ret
+
+
+prim_fillrect:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_fillrect_90
+ mov dx,cx
+ mov cx,ax
+ mov eax,[gfx_color]
+ call fill_rect
+ sub word [pstack_ptr],byte 2
+prim_fillrect_90:
+ ret
+
+
+prim_snprintf:
+ mov bp,pserr_pstack_underflow
+ cmp word [pstack_ptr],byte 3
+ jc prim_snprintf_90
+ mov bp,pserr_wrong_arg_types
+ mov cx,2
+ call get_pstack_tos
+ cmp dl,t_string
+ stc
+ jnz prim_snprintf_90
+ push eax
+ mov dx,t_string + (t_int << 8)
+ call get_2args
+ pop ebx
+ jc prim_snprintf_90
+
+ sub word [pstack_ptr],byte 3
+
+ mov [pf_gfx_buf],eax
+ mov [pf_gfx_max],ecx
+ and dword [pf_gfx_cnt],byte 0
+ and word [pf_gfx_err],byte 0
+
+ or ecx,ecx
+ jz prim_snprintf_40
+ ; clear buffer in case we have to print _nothing_
+ lin2segofs eax,es,di
+ mov byte [es:di],0
+prim_snprintf_40:
+
+ lin2segofs ebx,es,si
+
+ mov byte [pf_gfx],1
+ call printf
+ mov byte [pf_gfx],0
+
+ mov bp,[pf_gfx_err]
+ cmp bp,byte 0
+prim_snprintf_90:
+ ret
+
+
+prim_editinit:
+ mov dx,t_string + (t_array << 8)
+ call get_2args
+ jc prim_editinit_90
+
+ lin2segofs ecx,es,si
+ push es
+ push si
+ push eax
+ call edit_get_params
+ pop eax
+ pop ecx
+ mov bp,pserr_invalid_data
+ jc prim_editinit_90
+
+ push dword [gfx_cur]
+ push ecx
+ lin2segofs eax,es,si
+ call edit_init
+ pop si
+ pop es
+ pop dword [gfx_cur]
+
+ call edit_put_params
+
+ sub word [pstack_ptr],byte 2
+prim_editinit_90:
+ ret
+
+
+prim_editdone:
+ mov dx,t_array
+ call get_1arg
+ jc prim_editdone_90
+
+ lin2segofs eax,es,si
+ call edit_get_params
+ mov bp,pserr_invalid_data
+ jc prim_editdone_90
+
+ push word [edit_x]
+ pop word [gfx_cur_x]
+ push word [edit_y]
+ pop word [gfx_cur_y]
+ mov dx,[edit_width]
+ mov cx,[edit_height]
+ les di,[edit_bg]
+ add di,4
+ mov bx,dx
+ imul bx,[pixel_bytes]
+ call restore_bg
+
+ sub word [pstack_ptr],byte 1
+prim_editdone_90:
+ ret
+
+
+prim_editshowcursor:
+ mov dx,t_array
+ call get_1arg
+ jc prim_editshowcursor_90
+
+ lin2segofs eax,es,si
+ call edit_get_params
+ mov bp,pserr_invalid_data
+ jc prim_editshowcursor_90
+
+ push dword [gfx_cur]
+ call edit_show_cursor
+ pop dword [gfx_cur]
+
+ sub word [pstack_ptr],byte 1
+prim_editshowcursor_90:
+ ret
+
+
+prim_edithidecursor:
+ mov dx,t_array
+ call get_1arg
+ jc prim_edithidecursor_90
+
+ lin2segofs eax,es,si
+ call edit_get_params
+ mov bp,pserr_invalid_data
+ jc prim_edithidecursor_90
+
+ push dword [gfx_cur]
+ call edit_hide_cursor
+ pop dword [gfx_cur]
+
+ sub word [pstack_ptr],byte 1
+prim_edithidecursor_90:
+ ret
+
+
+prim_editinput:
+ mov dx,t_int + (t_array << 8)
+ call get_2args
+ jc prim_editinput_90
+
+ lin2segofs ecx,es,si
+ push es
+ push si
+ push eax
+ call edit_get_params
+ pop eax
+ pop ecx
+ mov bp,pserr_invalid_data
+ jc prim_editinput_90
+
+ push dword [gfx_cur]
+ push ecx
+ push eax
+ call edit_hide_cursor
+ pop eax
+ call edit_input
+ call edit_show_cursor
+ pop si
+ pop es
+ pop dword [gfx_cur]
+
+ call edit_put_params
+
+ sub word [pstack_ptr],byte 2
+prim_editinput_90:
+ ret
+
+
+prim_updatedisk:
+ call pr_setint
+ mov es,[boot_cs]
+ mov si,[boot_sysconfig]
+ mov [es:si+1],al
+ ret
+
+
+prim_bootloader:
+ mov es,[boot_cs]
+ mov si,[boot_sysconfig]
+ movzx eax,byte [es:si]
+ jmp pr_getint
+
+
+prim_bootdrive:
+ mov es,[boot_cs]
+ mov si,[boot_sysconfig]
+ movzx eax,byte [es:si+5]
+ jmp pr_getint
+
+
+prim_reloadfs:
+ call pr_setint
+ mov es,[boot_cs]
+ mov si,[boot_sysconfig]
+ mov [es:si+6],al
+ ret
+
+
+prim_usernote:
+ mov es,[boot_cs]
+ mov si,[boot_sysconfig]
+ movzx eax,byte [es:si+7]
+ jmp pr_getint
+
+
+prim_getinfo:
+ mov dl,t_int
+ call get_1arg
+ jc prim_getinfo_90
+ mov dl,t_int
+ mov es,[boot_cs]
+ mov si,[boot_sysconfig]
+ shl ax,2
+ add si,ax
+ mov eax,[es:si+12]
+ xor cx,cx
+ call set_pstack_tos
+prim_getinfo_90:
+ ret
+
+
+prim_getbyte:
+ mov dl,t_ptr
+ call get_1arg
+ jc prim_getbyte_90
+ lin2segofs eax,es,bx
+ movzx eax,byte [es:bx]
+ mov dl,t_int
+ xor cx,cx
+ call set_pstack_tos
+prim_getbyte_90:
+ ret
+
+
+prim_putbyte:
+ mov dx,t_int + (t_ptr << 8)
+ call get_2args
+ jc prim_putbyte_90
+ lin2segofs ecx,es,bx
+ mov [es:bx],al
+ sub word [pstack_ptr],byte 2
+prim_putbyte_90:
+ ret
+
+
+prim_getdword:
+ mov dl,t_ptr
+ call get_1arg
+ jc prim_getdword_90
+ lin2segofs eax,es,bx
+ mov eax,[es:bx]
+ mov dl,t_int
+ xor cx,cx
+ call set_pstack_tos
+prim_getdword_90:
+ ret
+
+
+prim_putdword:
+ mov dx,t_int + (t_ptr << 8)
+ call get_2args
+ jc prim_putdword_90
+ lin2segofs ecx,es,bx
+ mov [es:bx],eax
+ sub word [pstack_ptr],byte 2
+prim_putdword_90:
+ ret
+
+
+prim_findfile:
+ mov dl,t_string
+ call get_1arg
+ jc prim_findfile_90
+ call find_file
+ mov dl,t_ptr
+ or eax,eax
+ jnz prim_findfile_20
+ mov dl,t_none
+prim_findfile_20:
+ xor cx,cx
+ call set_pstack_tos
+prim_findfile_90:
+ ret
+
+
+prim_setmode:
+ mov dl,t_int
+ call get_1arg
+ jz prim_setmode_30
+ cmp dl,t_none
+ stc
+ jnz prim_setmode_90
+ xor eax,eax
+ mov cx,ax
+ jmp prim_setmode_80
+prim_setmode_30:
+ xchg [gfx_mode],ax
+ push ax
+ call set_mode
+ pop ax
+ jnc prim_setmode_60
+ xchg [gfx_mode],ax
+ call set_mode
+ stc
+prim_setmode_60:
+ sbb eax,eax
+ inc eax
+
+ mov cx,[screen_width]
+ mov [clip_r],cx
+
+ mov cx,[screen_height]
+ mov [clip_b],cx
+
+ xor cx,cx
+
+ mov [clip_l],cx
+ mov [clip_t],cx
+
+prim_setmode_80:
+ mov dl,t_bool
+ call set_pstack_tos
+prim_setmode_90:
+ ret
+
+
+prim_currentmode:
+ movzx eax,word [gfx_mode]
+ jmp pr_getint
+
+
+prim_findmode:
+ mov bp,pserr_pstack_underflow
+ cmp word [pstack_ptr],byte 3
+ jc prim_findmode_90
+
+ mov bp,pserr_wrong_arg_types
+ mov cx,2
+ call get_pstack_tos
+ cmp dl,t_int
+ stc
+ jnz prim_findmode_90
+ push eax
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ pop edx
+ jc prim_findmode_90
+
+ ; eax: color
+ ; ecx: height
+ ; edx: width
+
+ call find_mode
+ jnc prim_findmode_50
+
+ mov dl,t_none
+ xor eax,eax
+
+ jmp prim_findmode_60
+
+prim_findmode_50:
+ mov dl,t_int
+
+prim_findmode_60:
+ sub word [pstack_ptr],byte 2
+
+ xor cx,cx
+ call set_pstack_tos
+
+prim_findmode_90:
+ ret
+
+
+prim_colorbits:
+ movzx eax,byte [color_bits]
+ jmp pr_getint
+
+
+prim_eject:
+ mov dl,t_int
+ call get_1arg
+ jc prim_eject_90
+ mov dl,al
+ mov ax,4600h
+ int 13h
+ xor cx,cx
+ mov dl,t_int
+ movzx eax,ah
+ call set_pstack_tos
+prim_eject_90:
+ ret
+
+
+prim_poweroff:
+ mov ax,5300h
+ xor bx,bx
+ int 15h
+ jc prim_poweroff_90
+ mov ax,5304h
+ xor bx,bx
+ int 15h
+ mov ax,5301h
+ xor bx,bx
+ int 15h
+ jc prim_poweroff_90
+ mov ax,530eh
+ xor bx,bx
+ mov cx,102h
+ int 15h
+ jc prim_poweroff_90
+ mov ax,5307h
+ mov cx,3
+ mov bx,1
+ int 15h
+prim_poweroff_90:
+ clc
+ ret
+
+
+prim_strstr:
+ mov dx,t_string + (t_string << 8)
+ call get_2args
+ jc prim_strstr_90
+
+ xor ebx,ebx
+
+prim_strstr_20:
+ push eax
+ push ecx
+
+ push ebx
+ call pcmp_str
+ pop ebx
+
+ jz prim_strstr_50
+
+ or al,al
+ jnz prim_strstr_30
+
+ or edx,edx
+ jnz prim_strstr_50
+
+prim_strstr_30:
+
+ or cl,cl
+ jz prim_strstr_40
+
+ pop ecx
+ pop eax
+
+ inc ecx
+ inc ebx
+ jmp prim_strstr_20
+
+prim_strstr_40
+ xor ebx,ebx
+ jmp prim_strstr_60
+prim_strstr_50:
+ inc ebx
+prim_strstr_60:
+ add esp,2*4
+ xchg eax,ebx
+ dec word [pstack_ptr]
+ xor cx,cx
+ mov dl,t_int
+ call set_pstack_tos
+
+prim_strstr_90:
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; sound primitives
+
+prim_soundgetvolume:
+ mov ax,[pstack_ptr]
+ inc ax
+ cmp [pstack_size],ax
+ mov bp,pserr_pstack_overflow
+ jb prim_sgv_90
+ mov [pstack_ptr],ax
+ mov dl,t_int
+ movzx eax,byte [sound_vol]
+ xor cx,cx
+ call set_pstack_tos
+prim_sgv_90:
+ ret
+
+prim_soundsetvolume:
+ mov dl,t_int
+ call get_1arg
+ jc prim_ssv_90
+ dec word [pstack_ptr]
+ or eax,eax
+ jns prim_ssv_30
+ xor eax,eax
+prim_ssv_30:
+ cmp eax,100
+ jl prim_ssv_50
+ mov ax,100
+prim_ssv_50:
+ or eax,eax
+ jns prim_ssv_60
+ xor ax,ax
+prim_ssv_60:
+ mov [sound_vol],al
+ call mod_setvolume
+ clc
+prim_ssv_90:
+ ret
+
+prim_soundgetsamplerate:
+ mov ax,[pstack_ptr]
+ inc ax
+ cmp [pstack_size],ax
+ mov bp,pserr_pstack_overflow
+ jb prim_sgsr_90
+ mov [pstack_ptr],ax
+ mov dl,t_int
+ movzx eax,byte [sound_sample]
+ xor cx,cx
+ call set_pstack_tos
+prim_sgsr_90:
+ ret
+
+prim_soundsetsamplerate:
+ mov dl,t_int
+ call get_1arg
+ jc prim_sssr_90
+ dec word [pstack_ptr]
+ push eax
+ call sound_init
+ pop eax
+ call sound_setsample
+ clc
+prim_sssr_90:
+ ret
+
+
+prim_soundplay:
+
+
+ call sound_init
+ jc prim_splay_80
+prim_splay_80:
+ clc
+prim_splay_90:
+ ret
+
+
+prim_sounddone:
+ call sound_done
+ clc
+ ret
+
+
+%if 0
+prim_soundtest:
+ mov dl,t_int
+ call get_1arg
+ jc prim_stest_90
+ dec word [pstack_ptr]
+
+ mov [sound_x],eax
+ call sound_test
+ clc
+prim_stest_90:
+ ret
+%endif
+
+prim_modload:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_modload_90
+ sub word [pstack_ptr],byte 2
+ xchg eax,ecx
+
+ ; ecx file
+ ; eax player
+
+ push dword [mem]
+ call lin2so
+ pop bx
+ pop es
+ cmp cl,[es:bx+fh_file_entries]
+ cmc
+ jc prim_modload_80
+
+ xor esi,esi
+
+ imul dx,cx,sizeof_file_raw_t
+ add si,dx
+
+ add si,sizeof_file_header_t
+ add esi,[mem]
+
+ push esi
+ call lin2so
+ pop si
+ pop es
+
+ mov ebx,[es:si+fi_raw_data]
+ add ebx,[mem]
+
+ ; ebx: mod file
+ ; eax: player
+
+ push eax
+ push ebx
+ call sound_init
+ pop ebx
+ pop eax
+ jc prim_modload_80
+
+ push ebx
+ call lin2so
+ pop di
+ pop es
+
+ call mod_load
+
+prim_modload_80:
+ clc
+prim_modload_90:
+ ret
+
+
+prim_modplay:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_modplay_90
+ sub word [pstack_ptr],byte 2
+ xchg eax,ecx
+
+ ; ecx start
+ ; eax player
+
+ cmp byte [sound_ok],0
+ jz prim_modplay_90
+
+ mov bx,cx
+ call mod_play
+
+ clc
+prim_modplay_90:
+ ret
+
+
+prim_modplaysample:
+ mov bp,pserr_pstack_underflow
+ cmp word [pstack_ptr],byte 4
+ jc prim_modps_90
+ mov bp,pserr_wrong_arg_types
+
+ mov cx,3
+ call get_pstack_tos
+ cmp dl,t_int
+ stc
+ jnz prim_modps_90
+
+ mov cx,2
+ push ax
+ call get_pstack_tos
+ pop bx
+ cmp dl,t_int
+ stc
+ jnz prim_modps_90
+
+ mov dx,t_int + (t_int << 8)
+ push bx
+ push ax
+ call get_2args
+ pop bx
+ pop dx
+ jc prim_modps_90
+
+ sub word [pstack_ptr],byte 4
+
+ xchg ax,dx
+
+ ; 1: ax
+ ; 2: bx
+ ; 3: cx
+ ; 4: dx
+
+ cmp byte [sound_ok],0
+ jz prim_modps_90
+
+ call mod_playsample
+
+ clc
+prim_modps_90:
+ ret
+
+
+%if 0
+prim_numtest:
+ mov dl,t_int
+ call get_1arg
+ jc prim_numtest_90
+
+ mov eax,[tmp_var_0 + 4*eax]
+
+ mov dl,t_int
+ xor cx,cx
+ call set_pstack_tos
+
+ clc
+prim_numtest_90:
+ ret
+%endif
+
+
+prim_settextwrap:
+ call pr_setint
+ mov [line_wrap],ax
+ ret
+
+
+prim_currenttextwrap:
+ movzx eax,word [line_wrap]
+ jmp pr_getint
+
+
+prim_seteotchar:
+ call pr_setint
+ mov [char_eot],eax
+ ret
+
+
+prim_currenteotchar:
+ mov eax,[char_eot]
+ jmp pr_getint
+
+
+prim_setmaxrows:
+ call pr_setint
+ mov [max_rows],ax
+ ret
+
+
+prim_currentmaxrows:
+ movzx eax,word [max_rows]
+ jmp pr_getint
+
+
+prim_formattext:
+ mov dl,t_string
+ call get_1arg
+ jc prim_formattext_90
+ dec word [pstack_ptr]
+ push eax
+ xor ax,ax
+ mov cx,max_text_rows
+ mov di,row_start_ofs
+ push ds
+ pop es
+ rep stosw
+ mov cx,link_entries * sizeof_link
+ mov di,link_list
+ rep stosb
+ pop eax
+ lin2segofs eax,es,si
+ or byte [txt_state],2
+ call text_xy
+ and byte [txt_state],~2
+ clc
+prim_formattext_90:
+ ret
+
+
+prim_gettextrows:
+ movzx eax,word [cur_row2]
+ jmp pr_getint
+
+
+prim_setstartrow:
+ call pr_setint
+ mov [start_row],ax
+ ret
+
+
+prim_getlinks:
+ movzx eax,word [cur_link]
+ jmp pr_getint
+
+
+prim_settextcolors:
+ mov bp,pserr_pstack_underflow
+ cmp word [pstack_ptr],byte 4
+ jc prim_settextcolors_90
+ mov cx,3
+ call get_pstack_tos
+ cmp dl,t_int
+ stc
+ mov bp,pserr_wrong_arg_types
+ jnz prim_settextcolors_90
+ mov [gfx_color0],eax
+ mov [gfx_color],eax
+ mov cx,2
+ push bp
+ call get_pstack_tos
+ pop bp
+ cmp dl,t_int
+ stc
+ jnz prim_settextcolors_90
+ mov [gfx_color1],eax
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_settextcolors_90
+
+ sub word [pstack_ptr],byte 4
+
+ mov [gfx_color2],ecx
+ mov [gfx_color3],eax
+
+ clc
+prim_settextcolors_90:
+ ret
+
+
+prim_currenttextcolors:
+ mov ax,[pstack_ptr]
+ add ax,4
+ cmp [pstack_size],ax
+ mov bp,pserr_pstack_overflow
+ jb prim_currenttextcolors_90
+ mov [pstack_ptr],ax
+ mov dl,t_int
+ mov eax,[gfx_color3]
+ xor cx,cx
+ call set_pstack_tos
+ mov dl,t_int
+ mov eax,[gfx_color2]
+ mov cx,1
+ call set_pstack_tos
+ mov dl,t_int
+ mov eax,[gfx_color1]
+ mov cx,2
+ call set_pstack_tos
+ mov dl,t_int
+ mov eax,[gfx_color0]
+ mov cx,3
+ call set_pstack_tos
+prim_currenttextcolors_90:
+ ret
+
+
+prim_setlink:
+ call pr_setint
+ mov dx,[cur_link]
+ cmp ax,dx
+ jae prim_setlink_90
+ mov [sel_link],ax
+prim_setlink_90:
+ ret
+
+
+prim_currentlink:
+ movzx eax,word [sel_link]
+ jmp pr_getint
+
+
+;
+; label, text, x, row
+prim_getlink:
+ mov dl,t_int
+ call get_1arg
+ jc prim_getlink_90
+ mov bp,pserr_invalid_range
+ cmp ax,[cur_link]
+ cmc
+ jc prim_getlink_90
+ xchg ax,di
+ shl di,3 ; sizeof_link = 8
+ add di,link_list
+ mov ax,[pstack_ptr]
+ add ax,3
+ cmp [pstack_size],ax
+ mov bp,pserr_pstack_overflow
+ jb prim_getlink_90
+ mov [pstack_ptr],ax
+ mov dl,t_string
+ segofs2lin ds, word label_buf,eax
+ mov cx,3
+ call set_pstack_tos
+ mov dl,t_string
+ segofs2lin word [row_start_seg],word [di+li_text],eax
+ mov cx,2
+ call set_pstack_tos
+ mov dl,t_int
+ movzx eax,word [di+li_x]
+ mov cx,1
+ call set_pstack_tos
+ mov dl,t_int
+ movzx eax,word [di+li_row]
+ xor cx,cx
+ call set_pstack_tos
+
+ mov es,[row_start_seg]
+ mov si,[di+li_label]
+ mov di,label_buf
+ mov cx,32 ; sizeof buf
+prim_getlink_50:
+ es lodsb
+ cmp al,13h
+ jz prim_getlink_60
+ or al,al
+ jz prim_getlink_60
+ mov [di],al
+ inc di
+ loop prim_getlink_50
+prim_getlink_60:
+ mov byte [di],0
+ clc
+prim_getlink_90:
+ ret
+
+
+prim_lineheight:
+ movzx eax,word [font_line_height]
+ jmp pr_getint
+
+
+prim_currenttitle:
+ segofs2lin word [row_start_seg],word [page_title],eax
+ mov dl,t_string
+ jmp pr_getobj
+
+
+prim_xsavescreen:
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ jc prim_xsavescreen_90
+ push ax
+ push cx
+ mul ecx
+ pop dx
+ pop cx
+ mov bp,pserr_invalid_image_size
+ add eax,4
+ jc prim_xsavescreen_90
+ cmp eax,1 << 20
+ cmc
+ jc prim_xsavescreen_90
+ push cx
+ push dx
+ call xmalloc
+ pop dx
+ pop cx
+ or eax,eax
+ stc
+ mov bp,pserr_no_memory
+ jz prim_xsavescreen_90
+
+ call real_to_pm
+ jc prim_xsavescreen_50
+
+ mov [es:eax],dx
+ mov [es:eax+2],cx
+
+ call pm_to_real
+
+ push eax
+ lea edi,[eax+4]
+ call xsave_bg
+ pop eax
+
+prim_xsavescreen_50:
+ dec word [pstack_ptr]
+ xor cx,cx
+ mov dl,t_ptr
+ call set_pstack_tos
+prim_xsavescreen_90:
+ ret
+
+
+prim_videomodes:
+ mov ax,[pstack_ptr]
+ inc ax
+ cmp [pstack_size],ax
+ mov bp,pserr_pstack_overflow
+ jb prim_videomodes_90
+ mov [pstack_ptr],ax
+
+ mov es,[boot_cs]
+ mov si,[boot_sysconfig]
+ movzx cx,byte [es:si+4]
+ mov si,[es:si+2]
+ xor eax,eax
+ or cx,cx
+ jz prim_videomodes_40
+prim_videomodes_20:
+ cmp byte [es:si+fb_bits],0
+ jz prim_videomodes_40
+ add si,sizeof_fb_entry
+ inc eax
+ loop prim_videomodes_20
+prim_videomodes_40:
+ mov dl,t_int
+ xor cx,cx
+ call set_pstack_tos
+prim_videomodes_90:
+ ret
+
+
+;
+; mode, width, height, ok
+prim_getvideomode:
+ mov dl,t_int
+ call get_1arg
+ jc prim_getvm_90
+ mov bp,pserr_invalid_range
+ mov fs,[boot_cs]
+ mov si,[boot_sysconfig]
+ movzx ecx,byte [fs:si+4]
+ cmp eax,ecx
+ cmc
+ jc prim_getvm_90
+ imul di,ax,sizeof_fb_entry
+ add di,[fs:si+2]
+
+ mov ax,[pstack_ptr]
+ add ax,3
+ cmp [pstack_size],ax
+ mov bp,pserr_pstack_overflow
+ jb prim_getvm_90
+ mov [pstack_ptr],ax
+
+ mov dl,t_int
+ movzx eax,word [fs:di+fb_mode]
+ mov cx,3
+ call set_pstack_tos
+
+ mov dl,t_int
+ movzx eax,word [fs:di+fb_width]
+ mov cx,2
+ call set_pstack_tos
+
+ mov dl,t_int
+ movzx eax,word [fs:di+fb_height]
+ mov cx,1
+ call set_pstack_tos
+
+ mov dl,t_int
+ movzx eax,byte [fs:di+fb_ok]
+ xor cx,cx
+ call set_pstack_tos
+prim_getvm_90:
+ ret
+
+
+prim_usleep:
+ call pr_setint
+
+ mov ecx,54944/2
+ add eax,ecx
+ add ecx,ecx
+ xor edx,edx
+ div ecx
+ or eax,eax
+ jz prim_usleep_90
+ mov ecx,eax
+ push ecx
+ call get_time
+ pop ecx
+ add ecx,eax
+prim_usleep_20:
+ push ecx
+ call get_time
+ pop ecx
+ cmp eax,ecx
+ jbe prim_usleep_20
+prim_usleep_90:
+ ret
+
+
+prim_time:
+ call get_time
+ jmp pr_getint
+
+
+prim_setbrightness:
+ call pr_setint
+ mov [brightness],ax
+ ret
+
+prim_currentbrightness:
+ movzx eax,word [brightness]
+ jmp pr_getint
+
+
+prim_fadein:
+ mov dx,t_int + (t_string << 8)
+ call get_2args
+ jc prim_get_90
+
+ sub word [pstack_ptr],byte 2
+
+ lin2segofs ecx,es,bx
+ call fade_in
+
+ clc
+prim_fadein_90:
+ ret
+
+
+prim_fade:
+ mov bp,pserr_pstack_underflow
+ cmp word [pstack_ptr],byte 3
+ jc prim_fade_90
+ mov bp,pserr_wrong_arg_types
+ mov cx,2
+ call get_pstack_tos
+ cmp dl,t_string
+ stc
+ jnz prim_fade_90
+ push eax
+ mov dx,t_int + (t_int << 8)
+ call get_2args
+ pop edx
+ jc prim_fade_90
+
+ sub word [pstack_ptr],byte 3
+
+ mov bp,ax
+ mov ax,cx
+ lin2segofs edx,es,bx
+ call fade_one
+
+ clc
+prim_fade_90:
+ ret
+
+
+prim_idle:
+ mov dx,t_int + (t_ptr << 8)
+ call get_2args
+ jnc prim_idle_10
+ cmp dx,t_int + (t_none << 8)
+ stc
+ jnz prim_idle_90
+prim_idle_10:
+ sub word [pstack_ptr],byte 2
+ mov byte [run_idle],0
+ cmp dh,t_none ; undef
+ jz prim_idle_90
+ push ecx
+ call lin2so
+ pop dword [idle_data]
+ mov [idle_data2],eax
+ mov byte [run_idle],1
+ clc
+prim_idle_90:
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Helper function that covers common cases.
+
+; return eax as ptr on stack, returns undef if eax = 0
+pr_getptr_or_none:
+ mov dl,t_ptr
+ or eax,eax
+ jnz pr_getobj
+ mov dl,t_none
+ jmp pr_getobj
+
+; return eax as integer on stack
+pr_getint:
+ mov dl,t_int
+
+; return eax as dl on stack
+pr_getobj:
+ mov cx,[pstack_ptr]
+ inc cx
+ cmp [pstack_size],cx
+ mov bp,pserr_pstack_overflow
+ jc pr_getobj_90
+ mov [pstack_ptr],cx
+ xor cx,cx
+ call set_pstack_tos
+pr_getobj_90:
+ ret
+
+
+; get ptr from stack as eax; if it is undef, don't return to function
+pr_setptr_or_none:
+ mov dl,t_ptr
+
+; get obj from stack as eax; if it is undef, don't return to function
+pr_setobj_or_none:
+ call get_1arg
+ jnc pr_setobj_20
+ cmp dl,t_none
+ stc
+ jnz pr_setobj_10
+ dec word [pstack_ptr]
+ clc
+ jmp pr_setobj_10
+
+; get integer from stack as eax
+pr_setint:
+ mov dl,t_int
+
+; get object with type dl from stack as eax
+pr_setobj:
+ call get_1arg
+ jnc pr_setobj_20
+pr_setobj_10:
+ pop ax ; don't return to function that called us
+ ret
+pr_setobj_20:
+ dec word [pstack_ptr]
+ pop cx ; put link to clc on stack
+ push word pr_setobj_30
+ jmp cx
+pr_setobj_30:
+ clc
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+;
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; ensure the cursor is always within the visible area
+;
+edit_align:
+ mov cx,[edit_width]
+ mov dx,cx
+ shr dx,1
+ mov ax,[edit_cursor]
+ sub ax,[edit_shift]
+ cmp ax,dx
+ jg edit_align_50
+
+ sub ax,5 ; still 5 pixel away?
+ jge edit_align_90
+ add [edit_shift],ax
+ jge edit_align_90
+ and word [edit_shift],byte 0
+ jmp edit_align_90
+edit_align_50:
+ sub cx,ax
+ sub cx,byte 5 ; still 5 pixel away?
+ jge edit_align_90
+ sub [edit_shift],cx
+edit_align_90:
+ ret
+
+
+
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; es:bx string
+; si ptr to char (rel. to es:bx)
+;
+; return:
+; si points to prev char
+;
+; Changes no other regs.
+;
+utf8_prev:
+ push ax
+ or si,si
+ jz utf8_prev_90
+utf8_prev_50:
+ dec si
+ jz utf8_prev_90
+ mov al,[es:bx+si]
+ shr al,6
+ cmp al,2
+ jz utf8_prev_50
+utf8_prev_90:
+ pop ax
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; es:bx string
+; si ptr to char (rel. to es:bx)
+;
+; return:
+; si points to next char
+;
+; Changes no other regs.
+;
+utf8_next:
+ push ax
+ cmp byte [es:bx+si],0
+ jz utf8_next_90
+utf8_next_50:
+ inc si
+ mov al,[es:bx+si]
+ shr al,6
+ cmp al,2
+ jz utf8_next_50
+utf8_next_90:
+ pop ax
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; eax key (bits 0-23: key, 24-31: scan code)
+;
+edit_input:
+ mov edx,eax
+ shr edx,24
+ and eax,1fffffh
+ les si,[edit_buf]
+ mov bx,si
+
+ dec si
+edit_input_10:
+ inc si
+ cmp byte [es:si],0
+ jnz edit_input_10
+ mov cx,si
+ sub cx,bx
+ ; cx: string length
+
+ mov si,[edit_buf_ptr]
+
+ cmp dl,keyLeft
+ jnz edit_input_20
+ mov di,si
+ call utf8_prev
+ cmp di,si
+ jz edit_input_90
+ mov [edit_buf_ptr],si
+ jmp edit_input_80
+edit_input_20:
+ cmp dl,keyRight
+ jnz edit_input_21
+ mov di,si
+ call utf8_next
+ cmp di,si
+ jz edit_input_90
+ mov [edit_buf_ptr],si
+ jmp edit_input_80
+edit_input_21:
+ cmp dl,keyEnd
+ jnz edit_input_22
+ cmp byte [es:bx+si],0
+ jz edit_input_90
+ mov [edit_buf_ptr],cx
+ jmp edit_input_80
+edit_input_22:
+ cmp dl,keyHome
+ jnz edit_input_23
+ or si,si
+ jz edit_input_90
+ and word [edit_buf_ptr],byte 0
+ jmp edit_input_80
+edit_input_23:
+ cmp dl,keyDel
+ jnz edit_input_30
+edit_input_24:
+ mov di,si
+ call utf8_next
+ cmp di,si
+ jz edit_input_90
+edit_input_25:
+ mov al,[es:bx+si]
+ mov [es:bx+di],al
+ inc si
+ inc di
+ or al,al
+ jnz edit_input_25
+ jmp edit_input_80
+edit_input_30:
+ cmp eax,keyBS
+ jnz edit_input_35
+ mov di,si
+ call utf8_prev
+ cmp di,si
+ jz edit_input_90
+ mov [edit_buf_ptr],si
+ jmp edit_input_24
+edit_input_35:
+
+ cmp eax,20h
+ jb edit_input_90
+
+ ; reject chars we can't display
+ pusha
+ push es
+ call char_width
+ or cx,cx
+ pop es
+ popa
+ jz edit_input_90
+
+ push cx
+ push bx
+ push si
+ call utf8_enc
+ pop si
+ pop bx
+ pop ax
+
+ mov dx,[edit_buf_len]
+ sub dx,ax
+ sub dx,cx
+ jb edit_input_90
+ cmp dx,1
+ jb edit_input_90
+ sub ax,[edit_buf_ptr]
+ add [edit_buf_ptr],cx
+
+ ; ax: bytes to copy (excl. final 0)
+ ; cx: utf8 size
+
+ push si
+ add si,ax
+ mov di,si
+ add di,cx
+ inc ax
+edit_input_70:
+ mov dl,[es:bx+si]
+ mov [es:bx+di],dl
+ dec si
+ dec di
+ dec ax
+ jnz edit_input_70
+ pop si
+
+ mov di,utf8_buf
+edit_input_75:
+ mov al,[di]
+ mov [es:bx+si],al
+ inc di
+ inc si
+ dec cx
+ jnz edit_input_75
+
+edit_input_80:
+ mov si,[edit_buf_ptr]
+ mov al,0
+ xchg al,[es:bx+si]
+ push ax
+ push si
+ push bx
+ push es
+ mov si,bx
+ call str_size
+ pop es
+ pop bx
+ pop si
+ pop ax
+ xchg al,[es:bx+si]
+ mov [edit_cursor],cx
+
+ call edit_align
+
+ call edit_redraw
+edit_input_90:
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+edit_redraw:
+ mov ax,[edit_x]
+ sub ax,[edit_shift]
+ mov [gfx_cur_x],ax
+ mov ax,[edit_y]
+ add ax,[edit_y_ofs]
+ mov [gfx_cur_y],ax
+
+ les si,[edit_buf]
+edit_redraw_20:
+ call utf8_dec
+ or eax,eax
+ jz edit_redraw_50
+ push si
+ push es
+ call edit_char
+ pop es
+ pop si
+ jmp edit_redraw_20
+edit_redraw_50:
+ mov ax,[edit_x]
+ add ax,[edit_width]
+ sub ax,[gfx_cur_x]
+ jle edit_redraw_90
+
+ push word [edit_y]
+ pop word [gfx_cur_y]
+ mov dx,ax
+ imul ax,[pixel_bytes]
+ mov cx,[edit_height]
+ mov bx,[edit_width]
+ imul bx,[pixel_bytes]
+ les di,[edit_bg]
+ add di,4
+ add di,bx
+ sub di,ax
+ call restore_bg
+edit_redraw_90:
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Write char at current cursor position.
+;
+; eax char
+; [edit_bg] background pixmap
+;
+; return:
+; cursor position gets advanced
+;
+edit_char:
+ push fs
+
+ push word [clip_r]
+ push word [clip_l]
+
+ push eax
+
+ mov cx,[edit_x]
+ mov [clip_l],cx
+ add cx,[edit_width]
+ mov [clip_r],cx
+
+ call find_char
+
+ cmp byte [chr_width],0
+ jz edit_char_80
+
+ les di,[edit_bg]
+ mov bx,[edit_width]
+ imul bx,[pixel_bytes]
+ add di,4
+ mov ax,[edit_y_ofs]
+ imul bx
+ add di,ax
+ mov cx,[gfx_cur_x]
+ sub cx,[edit_x]
+ imul cx,[pixel_bytes]
+ add di,cx
+
+ mov dx,[chr_width]
+ mov cx,[font_height]
+
+ call restore_bg
+
+edit_char_80:
+ pop eax
+
+ call char_xy
+
+ pop word [clip_l]
+ pop word [clip_r]
+
+edit_char_90:
+ pop fs
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+edit_hide_cursor:
+ les di,[edit_bg]
+ add di,4
+ mov ax,[edit_cursor]
+ sub ax,[edit_shift]
+ mov cx,ax
+ imul cx,[pixel_bytes]
+ add di,cx
+ add ax,[edit_x]
+ mov [gfx_cur_x],ax
+ push word [edit_y]
+ pop word [gfx_cur_y]
+ mov cx,[edit_height]
+ mov dx,1
+ mov bx,[edit_width]
+ imul bx,[pixel_bytes]
+ call restore_bg
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+edit_show_cursor:
+ call screen_segs
+
+ mov ax,[edit_cursor]
+ sub ax,[edit_shift]
+ add ax,[edit_x]
+ mov [gfx_cur_x],ax
+ push word [edit_y]
+ pop word [gfx_cur_y]
+ mov cx,[edit_height]
+edit_show_cursor_10:
+ push cx
+ call goto_xy
+ call [setpixel_t]
+ pop cx
+ inc word [gfx_cur_y]
+ loop edit_show_cursor_10
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; es:si initial text
+;
+edit_init:
+ push fs
+ push es
+ pop fs
+ xor cx,cx
+ mov [edit_shift],cx
+ les di,[edit_buf]
+edit_init_10:
+ fs lodsb
+ or al,al
+ jz edit_init_20
+ stosb
+ inc cx
+ cmp cx,[edit_buf_len]
+ jb edit_init_10
+ dec cx
+ dec di
+edit_init_20:
+ mov byte [es:di],0
+ mov [edit_buf_ptr],cx
+
+ mov si,[edit_buf]
+ call str_size
+ mov [edit_cursor],cx
+
+ call edit_align
+
+ call edit_redraw
+ call edit_show_cursor
+edit_init_90:
+ pop fs
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; es:si parameter array
+;
+; note: no consistency checks done, es:si _must_ point to
+; a valid array
+;
+edit_put_params:
+ push word [edit_buf_ptr]
+ pop word [es:si+2+5*5+1]
+
+ push word [edit_cursor]
+ pop word [es:si+2+5*6+1]
+
+ push word [edit_shift]
+ pop word [es:si+2+5*7+1]
+
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; es:si parameter array
+;
+; return:
+; CF invalid data
+;
+edit_get_params:
+ es lodsw
+ cmp ax,8
+ jc edit_get_params_90
+
+ cmp byte [es:si+5*0],t_int
+ jnz edit_get_params_80
+ push word [es:si+5*0+1]
+ pop word [edit_x]
+
+ cmp byte [es:si+5*1],t_int
+ jnz edit_get_params_80
+ push word [es:si+5*1+1]
+ pop word [edit_y]
+
+ cmp byte [es:si+5*2],t_ptr
+ jnz edit_get_params_80
+ push dword [es:si+5*2+1]
+ call lin2so
+ pop dword [edit_bg]
+
+ cmp byte [es:si+5*3],t_string
+ jnz edit_get_params_80
+ push dword [es:si+5*3+1]
+ call lin2so
+ pop dword [edit_buf]
+
+ cmp byte [es:si+5*4],t_int
+ jnz edit_get_params_80
+ push word [es:si+5*4+1]
+ pop word [edit_buf_len]
+
+ cmp byte [es:si+5*5],t_int
+ jnz edit_get_params_80
+ push word [es:si+5*5+1]
+ pop word [edit_buf_ptr]
+
+ cmp byte [es:si+5*6],t_int
+ jnz edit_get_params_80
+ push word [es:si+5*6+1]
+ pop word [edit_cursor]
+
+ cmp byte [es:si+5*7],t_int
+ jnz edit_get_params_80
+ push word [es:si+5*7+1]
+ pop word [edit_shift]
+
+ les si,[edit_bg]
+ es lodsw
+ mov [edit_width],ax
+ es lodsw
+ mov [edit_height],ax
+
+ mov cx,[font_height]
+ sub ax,cx
+ sar ax,1
+ mov [edit_y_ofs],ax
+
+ cmp word [edit_buf_len],byte 2 ; at least 1 char
+ jc edit_get_params_90
+
+ movzx eax,word [edit_width]
+ movzx ecx,word [edit_height]
+ mul ecx
+ cmp eax,10000h-20
+ jae edit_get_params_80 ; to large: max 64k
+
+ clc
+ jmp edit_get_params_90
+
+edit_get_params_80:
+ stc
+edit_get_params_90:
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; basic graphics functions
+;
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; map next window segment
+;
+inc_winseg:
+ push ax
+ mov al,[cs:mapped_window]
+ inc al
+ call set_win
+ pop ax
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; map window segment
+;
+; al = window segment
+;
+set_win:
+ cmp byte [cs:vbe_active],0
+ jz set_win_90
+ cmp [cs:mapped_window],al
+ jz set_win_90
+ pusha
+ mov [cs:mapped_window],al
+ mov ah,[cs:window_inc]
+ mul ah
+ xchg ax,dx
+ mov ax,4f05h
+ xor bx,bx
+ cmp word [cs:window_seg_r],0
+ jz set_win_50
+ pusha
+ inc bx
+ int 10h
+ popa
+set_win_50:
+ int 10h
+ popa
+set_win_90:
+ ret
+
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Go to current cursor position.
+;
+; return:
+; di offset
+; correct gfx segment is mapped
+;
+; Notes:
+; - changes no regs other than di
+; - does not require ds == cs
+;
+goto_xy:
+ push ax
+ push dx
+ mov ax,[cs:gfx_cur_y]
+ mov di,[cs:gfx_cur_x]
+ imul di,[pixel_bytes]
+ mul word [cs:screen_line_len]
+ add ax,di
+ adc dx,0
+ push ax
+ xchg ax,dx
+ call set_win
+ pop di
+ pop dx
+ pop ax
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Set active color.
+;
+; eax color
+;
+; return:
+; [gfx_color] color
+;
+; Changed registers: eax
+;
+setcolor:
+ call encode_color
+ mov [gfx_color],eax
+ ret
+
+
+encode_color:
+ cmp byte [pixel_bits],16
+ jnz encode_color_90
+ push edx
+ xor edx,edx
+ shl eax,8
+ shld edx,eax,5
+ shl eax,8
+ shld edx,eax,6
+ shl eax,8
+ shld edx,eax,5
+ mov eax,edx
+ pop edx
+encode_color_90:
+ ret
+
+
+; ax palette index
+;
+; return:
+; eax color
+;
+pal_to_color:
+ push fs
+ push si
+ lfs si,[gfx_pal]
+ add si,ax
+ add si,ax
+ add si,ax
+ mov eax,[fs:si]
+ bswap eax
+ shr eax,8
+ pop si
+ pop fs
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; draw a line
+;
+line:
+ xor eax,eax
+ xor ebx,ebx
+ inc ax
+ inc bx
+ mov esi,[line_x1]
+ sub esi,[line_x0]
+ jns line_10
+ neg esi
+ neg eax
+line_10:
+ mov ebp,[line_y1]
+ sub ebp,[line_y0]
+ jns line_20
+ neg ebp
+ neg ebx
+line_20:
+ call screen_segs
+
+ xchg eax,ecx
+ mov eax,[screen_line_len]
+ imul ebx
+ xchg eax,edx
+
+ mov eax,[line_y0]
+ push edx
+ imul dword [screen_line_len]
+ pop edx
+ xchg eax,edi
+
+ mov eax,[line_x0]
+ imul eax,[pixel_bytes]
+
+ add edi,eax
+
+ cmp byte [pixel_bytes],1
+ jbe line_25
+ cmp byte [pixel_bytes],2
+ jz line_23
+ shl dword [line_x0],2
+ shl dword [line_x1],2
+ shl ecx,2
+ jmp line_25
+line_23:
+ shl dword [line_x0],1
+ shl dword [line_x1],1
+ shl ecx,1
+line_25:
+
+ ; es -> window
+ ; edi -> address
+ ; ecx -> d_x
+ ; edx -> d_y
+
+ cmp esi,ebp
+ jl hline_40
+
+ or esi,esi
+ jz line_60
+
+ mov [line_tmp],esi
+ shr esi,1
+ neg esi
+
+ mov eax,[line_x1]
+ sub [line_x0],eax
+
+line_30:
+ call line_pp
+
+ add edi,ecx
+ add [line_x0],ecx
+ jz line_60
+ add esi,ebp
+ jnc line_30
+ sub esi,[line_tmp]
+ add edi,edx
+ jmp line_30
+
+hline_40:
+ or ebp,ebp
+ jz line_60
+
+ mov [line_tmp],ebp
+ shr ebp,1
+ neg ebp
+
+ mov eax,[line_y1]
+ sub [line_y0],eax
+
+line_50:
+ call line_pp
+
+ add edi,edx
+ add [line_y0],ebx
+ jz line_60
+ add ebp,esi
+ jnc line_50
+ sub ebp,[line_tmp]
+ add edi,ecx
+ jmp line_50
+line_60:
+ ; now draw final point
+
+ mov eax,[line_y1]
+ imul dword [screen_line_len]
+ add eax,[line_x1]
+ xchg eax,edi
+
+ call line_pp
+
+ ret
+
+line_pp:
+ mov eax,edi
+ shr eax,16
+ call set_win
+ jmp [setpixel_t]
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Set pixel at es:di.
+;
+setpixel_8:
+ mov al,[gfx_color]
+
+setpixel_a_8:
+ mov [es:di],al
+ ret
+
+setpixel_16:
+ mov ax,[gfx_color]
+
+setpixel_a_16:
+ mov [es:di],ax
+ ret
+
+setpixel_32:
+ mov eax,[gfx_color]
+
+setpixel_a_32:
+ mov [es:di],eax
+ ret
+
+
+; with transparency
+setpixel_t_16:
+ mov ax,[gfx_color]
+
+setpixel_ta_16:
+ mov [es:di],ax
+ ret
+
+setpixel_t_32:
+ mov eax,[gfx_color]
+
+setpixel_ta_32:
+ cmp word [transp],0
+ jz setpixel_a_32
+ push ecx
+ mov ecx,[fs:di]
+ ror ecx,16
+ ror eax,16
+ call add_transp
+ rol ecx,8
+ rol eax,8
+ call add_transp
+ rol ecx,8
+ rol eax,8
+ call add_transp
+ mov [es:di],ecx
+ pop ecx
+ ret
+
+; cl, al -> cl
+add_transp:
+ push eax
+ push ecx
+ movzx eax,al
+ movzx ecx,cl
+ sub ecx,eax
+ imul ecx,[transp]
+ sar ecx,8
+ add ecx,eax
+ cmp ecx,0
+ jge add_transp_10
+ mov cl,0
+ jmp add_transp_20
+add_transp_10:
+ cmp ecx,100h
+ jb add_transp_20
+ mov cl,0ffh
+add_transp_20:
+ mov [esp],cl
+ pop ecx
+ pop eax
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Get pixel from fs:si.
+;
+getpixel_8:
+ mov al,[fs:si]
+ ret
+
+getpixel_16:
+ mov ax,[fs:si]
+ ret
+
+getpixel_32:
+ mov eax,[fs:si]
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Initialize font.
+;
+; eax linear ptr to font header
+;
+font_init:
+ lin2segofs eax,es,bx
+ cmp dword [es:bx+foh_magic],0d2828e07h ; magic
+ jnz font_init_90
+ mov ax,[es:bx+foh_entries]
+ mov dl,[es:bx+foh_height]
+ mov dh,[es:bx+foh_line_height]
+ or ax,ax
+ jz font_init_90
+ or dx,dx
+ jz font_init_90
+ mov [font_entries],ax
+ mov [font_height],dl
+ mov [font_line_height],dh
+ push es
+ push bx
+ pop dword [font]
+font_init_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Write a string. '\n' is a line break.
+;
+; es:si ASCIIZ string
+;
+; return:
+; cursor position gets advanced
+;
+; special chars:
+; char_eot same as \x00
+; \x10 back to normal
+; \x11 set alternative text color (gfx_color1)
+; \x12 label start, no text output
+; \x13 set link text color (gfx_color2); typically label end
+; \x14 start page description
+;
+text_xy:
+ xor eax,eax
+ mov [last_label],ax
+ mov [cur_row],ax
+ and [txt_state],byte ~1
+
+ test byte [txt_state],2
+ jz text_xy_05
+ mov [row_start_seg],es
+ mov [row_start_ofs],si
+ mov [cur_row2],ax
+ mov [cur_link],ax
+ mov [sel_link],ax
+ mov [page_title],ax
+ push si
+ call utf8_dec
+ pop si
+ call is_eot
+ jz text_xy_05
+ inc word [cur_row2]
+text_xy_05:
+ push word [gfx_cur_x]
+text_xy_10:
+ mov di,si
+ call utf8_dec
+
+ call is_eot
+ jz text_xy_90
+
+ cmp word [line_wrap],byte 0
+ jz text_xy_60
+
+ call is_space
+ jnz text_xy_60
+
+ push si
+ mov si,di
+ call word_width
+ pop si
+ add cx,[gfx_cur_x]
+ cmp cx,[line_wrap]
+ jbe text_xy_60
+text_xy_30:
+ call is_space
+ jnz text_xy_50
+
+ mov di,si
+ call utf8_dec
+
+ call is_eot
+ jz text_xy_90
+ jmp text_xy_30
+text_xy_50:
+ mov si,di
+ jmp text_xy_65
+text_xy_60:
+ cmp eax,0ah
+ jnz text_xy_70
+text_xy_65:
+ mov ax,[font_line_height]
+ add [gfx_cur_y],ax
+ pop ax
+ push ax
+ mov [gfx_cur_x],ax
+ inc word [cur_row]
+ mov dx,[max_rows]
+ mov ax,[cur_row]
+ or dx,dx
+ jz text_xy_67
+ cmp ax,dx
+ jae text_xy_90
+text_xy_67:
+ test byte [txt_state],2
+ jz text_xy_10
+ cmp ax,max_text_rows
+ jae text_xy_10
+ mov [cur_row2],ax
+ inc word [cur_row2]
+ add ax,ax
+ xchg ax,bx
+ mov [row_start_ofs + bx],si
+ jmp text_xy_10
+text_xy_70:
+ push si
+ push es
+ cmp eax,1fh
+ jae text_xy_80
+ call text_special
+ jmp text_xy_81
+text_xy_80:
+ test byte [txt_state],1
+ jnz text_xy_81
+ call char_xy
+text_xy_81:
+ pop es
+ pop si
+ jmp text_xy_10
+text_xy_90:
+ pop ax
+ push dword [gfx_color0]
+ pop dword [gfx_color]
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Handle special chars.
+;
+; eax char
+; es:si ptr to next char
+;
+text_special:
+ cmp eax,10h
+ jnz text_special_20
+
+ and byte [txt_state],~1
+ push eax
+ mov eax,[gfx_color0]
+ call setcolor
+ pop eax
+ jmp text_special_90
+text_special_20:
+ cmp eax,11h
+ jnz text_special_30
+
+ and byte [txt_state],~1
+ push eax
+ mov eax,[gfx_color1]
+ call setcolor
+ pop eax
+ jmp text_special_90
+text_special_30:
+ cmp eax,12h
+ jnz text_special_40
+
+ or byte [txt_state],1
+ mov [last_label],si
+
+ jmp text_special_90
+text_special_40:
+ cmp eax,13h
+ jnz text_special_50
+
+ and byte [txt_state],~1
+
+ ; check for selected link
+ mov bx,[sel_link]
+ shl bx,3 ; sizeof_link = 8
+ mov dx,[bx+link_list+li_text]
+ cmp si,dx
+
+ push eax
+ mov eax,[gfx_color3]
+ jz text_special_45
+ mov eax,[gfx_color2]
+text_special_45:
+ call setcolor
+ pop eax
+
+ test byte [txt_state],2
+ jz text_special_90
+
+ mov bx,[cur_link]
+ cmp bx,link_entries
+ jae text_special_90
+ inc word [cur_link]
+ shl bx,3 ; sizeof_link = 8
+ add bx,link_list
+ push word [last_label]
+ pop word [bx+li_label]
+ mov [bx+li_text],si
+ push word [gfx_cur_x]
+ pop word [bx+li_x]
+ mov dx,[cur_row2]
+ sub dx,1 ; 0-- -> 0
+ adc dx,0
+ mov [bx+li_row],dx
+
+ jmp text_special_90
+text_special_50:
+ cmp eax,14h
+ jnz text_special_60
+
+ mov [page_title],si
+
+ jmp text_special_90
+text_special_60:
+
+
+text_special_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; string width until end of next word
+;
+; es:si ASCIIZ string
+;
+; return:
+; cx width
+;
+word_width:
+ push es
+ push si
+ push ax
+
+ xor dx,dx
+ mov bl,0
+
+word_width_10:
+ call utf8_dec
+
+word_width_20:
+ call is_eot
+ jz word_width_90
+
+ cmp eax,0ah
+ jz word_width_90
+
+ cmp eax,12h
+ jnz word_width_30
+ mov bl,1
+word_width_30:
+ cmp eax,10h
+ jz word_width_40
+ cmp eax,13h
+ jnz word_width_50
+word_width_40:
+ mov bl,0
+word_width_50:
+
+ or bl,bl
+ jnz word_width_70
+
+ push eax
+ push bx
+ push dx
+ push si
+ push es
+ call char_width
+ pop es
+ pop si
+ pop dx
+ pop bx
+ pop eax
+
+ add dx,cx
+
+word_width_70:
+ call is_space
+ jz word_width_10
+
+ call utf8_dec
+
+ call is_space
+ jnz word_width_20
+
+word_width_90:
+ mov cx,dx
+
+ pop ax
+ pop si
+ pop es
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Test for white space (space or tab).
+;
+; eax char
+;
+; return:
+; ZF 0 = no, 1 = yes
+;
+is_space:
+ cmp eax,20h
+ jz is_space_90
+ cmp eax,9
+is_space_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Test for end of text.
+;
+; eax char
+;
+; return:
+; ZF 0 = no, 1 = yes
+;
+is_eot:
+ or eax,eax
+ jz is_eot_90
+ cmp eax,[char_eot]
+is_eot_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Get string dimensions (in pixel).
+;
+; es:si ASCIIZ string
+;
+; return:
+; cx width
+; dx height
+;
+str_size:
+ xor cx,cx
+ xor dx,dx
+str_size_20:
+ push cx
+ push dx
+ call str_len
+ xchg ax,cx
+ pop dx
+ pop cx
+ cmp ax,cx
+ jb str_size_40
+ mov cx,ax
+str_size_40:
+ inc dx
+
+ ; suppress final line break
+ call utf8_dec
+ cmp eax,0ah
+ jnz str_size_60
+ cmp byte [es:si],0
+ jz str_size_80
+str_size_60:
+ or eax,eax
+ jz str_size_80
+ cmp eax,[char_eot]
+ jz str_size_80
+ jmp str_size_20
+str_size_80:
+ dec dx
+ mov ax,[font_line_height]
+ mul dx
+ mov dx,[font_height]
+ add dx,ax
+str_size_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Get string length (in pixel).
+; *** Use str_size instead. ***
+;
+; es:si ASCIIZ string
+;
+; return:
+; cx width
+; es:si points to string end or line break
+;
+; notes:
+; - stops at linebreak ('\n')
+;
+str_len:
+ xor cx,cx
+str_len_10:
+ mov di,si
+ call utf8_dec
+ or eax,eax
+ jz str_len_70
+ cmp eax,[char_eot]
+ jz str_len_70
+ cmp eax,0ah
+ jz str_len_70
+ push cx
+ push si
+ push es
+ call char_width
+ pop es
+ pop si
+ pop ax
+ add cx,ax
+ jmp str_len_10
+str_len_70:
+ mov si,di
+ ret
+
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Decode next utf8 char.
+;
+; es:si string
+;
+; return:
+; eax char (invalid char: 0)
+;
+; Note: changes only: eax, si
+;
+utf8_dec:
+ xor eax,eax
+ es lodsb
+ cmp al,80h
+ jb utf8_dec_90
+
+ push cx
+ push edx
+
+ xor edx,edx
+ xor cx,cx
+ mov dl,al
+
+ cmp al,0c0h ; invalid
+ jb utf8_dec_70
+
+ inc cx ; 2 bytes
+ and dl,1fh
+ cmp al,0e0h
+ jb utf8_dec_10
+
+ inc cx ; 3 bytes
+ and dl,0fh
+ cmp al,0f0h
+ jb utf8_dec_10
+
+ inc cx ; 4 bytes
+ and dl,7
+ cmp al,0f8h
+ jb utf8_dec_10
+
+ inc cx ; 5 bytes
+ and dl,3
+ cmp al,0fch
+ jb utf8_dec_10
+
+ inc cx ; 6 bytes
+ and dl,1
+ cmp al,0feh
+ jae utf8_dec_70
+utf8_dec_10:
+ es lodsb
+ cmp al,80h
+ jb utf8_dec_70
+ cmp al,0c0h
+ jae utf8_dec_70
+ and al,3fh
+ shl edx,6
+ or dl,al
+ dec cx
+ jnz utf8_dec_10
+ xchg eax,edx
+ jmp utf8_dec_80
+
+utf8_dec_70:
+ xor eax,eax
+utf8_dec_80:
+ pop edx
+ pop cx
+
+utf8_dec_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Encode utf8 char.
+;
+; eax char
+;
+; return:
+; cx length
+; utf8_buf char
+;
+utf8_enc:
+ mov si,utf8_buf
+ xor cx,cx
+ xor dx,dx
+
+ cmp eax,80h
+ jae utf8_enc_10
+ mov [si],al
+ inc si
+ jmp utf8_enc_80
+utf8_enc_10:
+ inc cx
+ cmp eax,800h
+ jae utf8_enc_20
+ shl eax,21
+ mov dl,6
+ shld edx,eax,5
+ shl eax,5
+ jmp utf8_enc_60
+utf8_enc_20:
+ inc cx
+ cmp eax,10000h
+ jae utf8_enc_30
+ shl eax,16
+ mov dl,0eh
+ shld edx,eax,4
+ shl eax,4
+ jmp utf8_enc_60
+utf8_enc_30:
+ inc cx
+ cmp eax,200000h
+ jae utf8_enc_40
+ shl eax,11
+ mov dl,1eh
+ shld edx,eax,3
+ shl eax,3
+ jmp utf8_enc_60
+utf8_enc_40
+ inc cx
+ cmp eax,4000000h
+ jae utf8_enc_50
+ shl eax,6
+ mov dl,3eh
+ shld edx,eax,2
+ shl eax,2
+ jmp utf8_enc_60
+utf8_enc_50:
+ inc cx
+ shl eax,1
+ mov dl,7eh
+ shld edx,eax,1
+ add eax,eax
+utf8_enc_60:
+ mov bx,cx
+ mov [si],dl
+ inc si
+utf8_enc_70:
+ mov dl,2
+ shld edx,eax,6
+ shl eax,6
+ mov [si],dl
+ inc si
+ dec bx
+ jnz utf8_enc_70
+utf8_enc_80:
+ mov byte [si],0
+ inc cx
+utf8_enc_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Write a char at the current cursor position.
+;
+; eax char
+;
+; return:
+; cursor position gets advanced
+;
+char_xy:
+ cmp eax,1fh ; \x1f looks like a space, but isn't
+ jnz char_xy_10
+ mov al,' '
+char_xy_10:
+ call find_char
+ jc char_xy_90
+
+ test byte [txt_state],2 ; don't actually write
+ jnz char_xy_80
+
+ push word [gfx_cur_x]
+ push word [gfx_cur_y]
+
+ mov cx,[chr_x_ofs]
+ add [gfx_cur_x],cx
+
+ mov dx,[chr_y_ofs]
+ add [gfx_cur_y],dx
+
+ call goto_xy
+
+ call screen_segs
+
+ lgs si,[font]
+ add si,[chr_bitmap]
+
+ cmp byte [chr_real_width],0
+ jz char_xy_70
+ cmp byte [chr_real_height],0
+ jz char_xy_70
+
+ xor dx,dx
+ xor bp,bp
+
+char_xy_20:
+ xor cx,cx
+char_xy_30:
+ bt [gs:si],bp
+ jnc char_xy_40
+ mov ax,[gfx_cur_x]
+ add ax,cx
+ cmp ax,[clip_r]
+ jge char_xy_40
+ cmp ax,[clip_l]
+ jl char_xy_40
+ call [setpixel_t]
+char_xy_40:
+ inc bp
+ add di,[pixel_bytes]
+ jnc char_xy_50
+ call inc_winseg
+char_xy_50:
+ inc cx
+ cmp cx,[chr_real_width]
+ jnz char_xy_30
+
+ mov ax,[screen_line_len]
+ mov bx,[chr_real_width]
+ imul bx,[pixel_bytes]
+ sub ax,bx
+ add di,ax
+ jnc char_xy_60
+ call inc_winseg
+char_xy_60:
+ inc dx
+ cmp dx,[chr_real_height]
+ jnz char_xy_20
+
+char_xy_70:
+
+ pop word [gfx_cur_y]
+ pop word [gfx_cur_x]
+
+char_xy_80:
+ mov cx,[chr_width]
+ add [gfx_cur_x],cx
+
+char_xy_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Look for char in font.
+;
+; eax char
+;
+; return:
+; CF 0 = found, 1 = not found
+; [chr_*] updated
+;
+find_char:
+ and eax,1fffffh
+ cmp dword [font],byte 0
+ stc
+ jz find_char_90
+
+ les bx,[font]
+ add bx,sizeof_font_header_t
+ mov cx,[font_entries]
+
+find_char_20:
+ mov si,cx
+ shr si,1
+
+ shl si,3
+ mov edx,[es:bx+si+ch_c]
+ and edx,1fffffh ; 21 bits
+ cmp eax,edx
+
+ jz find_char_80
+
+ jl find_char_50
+
+ add bx,si
+ test cl,1
+ jz find_char_50
+ add bx,sizeof_char_header_t
+find_char_50:
+ shr cx,1
+ jnz find_char_20
+
+ stc
+ jmp find_char_90
+
+find_char_80:
+ mov dx,[es:bx+si+ch_ofs]
+ mov [chr_bitmap],dx
+ mov edx,[es:bx+si+ch_size]
+
+ shr edx,5
+ mov cl,dl
+ and cl,01fh
+ mov [chr_x_ofs],cl
+
+ shr edx,5
+ mov cl,dl
+ and cl,01fh
+ mov [chr_y_ofs],cl
+
+ shr edx,5
+ mov cl,dl
+ and cl,01fh
+ mov [chr_real_width],cl
+
+ shr edx,5
+ mov cl,dl
+ and cl,01fh
+ mov [chr_real_height],cl
+
+ shr edx,5
+ mov cl,dl
+ and cl,01fh
+ mov [chr_width],cl
+
+ clc
+find_char_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Get char width.
+;
+; eax char
+;
+; return:
+; eax char
+; cx char width
+;
+char_width:
+ push eax
+ cmp eax,1fh ; \x1f looks like a space, but isn't
+ jnz char_width_10
+ mov al,' '
+char_width_10:
+ call find_char
+ mov cx,0
+ jc char_width_90
+ mov cx,[chr_width]
+char_width_90:
+ pop eax
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Draw part of an image.
+;
+draw_image:
+ push gs
+ push fs
+
+ mov es,[window_seg_w]
+
+ lin2segofs dword [pcx_line_starts],gs,bp
+
+ mov ax,[line_y0]
+ cmp ax,[image_height]
+ jae draw_image_90
+
+ mov bx,ax
+ add ax,[line_y1] ; length!
+ sub ax,[image_height]
+ jbe draw_image_10
+ sub [line_y1],ax
+draw_image_10:
+ shl bx,2
+ add bp,bx
+
+draw_image_20:
+ call goto_xy
+
+ lfs si,[gs:bp]
+
+ mov cx,[line_x0]
+ neg cx
+
+ ; draw one line
+draw_image_30:
+ fs lodsb
+
+ mov ah,0
+ cmp al,0c0h
+ jb draw_image_70
+
+ ; repeat count
+
+ and ax,3fh
+ mov dx,ax
+ fs lodsb
+
+ add cx,dx
+ js draw_image_80
+ jnc draw_image_40
+ mov dx,cx
+
+draw_image_40:
+ mov bx,cx
+ sub bx,[line_x1]
+ jle draw_image_50
+ sub dx,bx
+draw_image_50:
+ or dx,dx
+ jz draw_image_80
+ dec dx
+ cmp ax,[transparent_color]
+ jz draw_image_55
+ cmp byte [pixel_bytes],1
+ jbe draw_image_54
+ push ax
+ call pal_to_color
+ call encode_color
+ call [setpixel_a]
+ pop ax
+ jmp draw_image_55
+draw_image_54:
+ mov [es:di],al
+draw_image_55:
+ add di,[pixel_bytes]
+ jnc draw_image_50
+ call inc_winseg
+ jmp draw_image_50
+
+draw_image_70:
+ inc cx
+ cmp cx,byte 0
+ jle draw_image_80
+ cmp ax,[transparent_color]
+ jz draw_image_75
+ cmp byte [pixel_bytes],1
+ jbe draw_image_74
+ call pal_to_color
+ call encode_color
+ call [setpixel_a]
+ jmp draw_image_75
+draw_image_74:
+ mov [es:di],al
+draw_image_75:
+ add di,[pixel_bytes]
+ jnc draw_image_80
+ call inc_winseg
+draw_image_80:
+ cmp cx,[line_x1]
+ jl draw_image_30
+
+ inc word [gfx_cur_y]
+
+ add bp,4
+ dec word [line_y1]
+ jnz draw_image_20
+
+draw_image_90:
+ pop fs
+ pop gs
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Get some memory for palette data
+;
+pal_init:
+ mov eax,300h
+ call calloc
+ push eax
+ call lin2so
+ pop dword [gfx_pal]
+ or eax,eax
+ stc
+ jz pal_init_90
+ mov eax,300h
+ call calloc
+ push eax
+ call lin2so
+ pop dword [gfx_pal_tmp]
+ or eax,eax
+ stc
+ jz pal_init_90
+ clc
+pal_init_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Load palette data.
+;
+; cx number of palettes
+; dx start
+;
+load_palette:
+ push fs
+
+ cmp byte [pixel_bytes],1
+ ja load_palette_90
+
+ cmp dx,100h
+ jae load_palette_90
+
+ mov ax,dx
+ add ax,cx
+ sub ax,100h
+ jbe load_palette_10
+ sub cx,ax
+load_palette_10:
+ or cx,cx
+ jz load_palette_90
+
+ mov ax,dx
+ add ax,dx
+ add ax,dx
+
+ push dx
+ push cx
+
+ ; vga function wants 6 bit values
+
+ lfs si,[gfx_pal]
+ les di,[gfx_pal_tmp]
+ add si,ax
+ add di,ax
+
+ imul cx,cx,3
+ mov dx,di
+ push dx
+load_palette_50:
+ fs lodsb
+ mov ah,0
+ mul word [brightness]
+ shr ax,10
+ stosb
+ loop load_palette_50
+
+ pop dx
+ pop cx
+ pop bx
+
+
+%if 0
+ mov si,dx
+ mov dx,3dah
+ cli
+load_palette_60:
+ in al,dx
+ test al,8
+ jnz load_palette_60
+load_palette_70:
+ in al,dx
+ test al,8
+ jz load_palette_70
+ cli
+ imul cx,cx,3
+ mov dx,3c8h
+ xchg ax,bx
+ out dx,al
+ inc dx
+ es rep outsb
+ sti
+%else
+ mov ax,1012h
+ int 10h
+%endif
+
+load_palette_90:
+ pop fs
+ ret
+
+
+; es:bx colors
+; ax ref color
+;
+fade_in:
+ xor bp,bp
+
+fade_in_20:
+ push bx
+ push ax
+
+ mov dx,3dah
+fade_in_30:
+ in al,dx
+ test al,8
+ jnz fade_in_30
+fade_in_40:
+ in al,dx
+ test al,8
+ jz fade_in_40
+
+ pop ax
+ pop bx
+
+ push bx
+ push ax
+ call fade_one
+ pop ax
+ pop bx
+
+ add bp,4
+
+ cmp bp,100h
+ jbe fade_in_20
+
+ ret
+
+
+; es:bx colors
+; ax ref color
+; bp step (0 - 100h)
+;
+fade_one:
+ push fs
+
+ lfs si,[gfx_pal]
+ mov di,si
+ imul ax,ax,3
+ add di,ax
+
+ mov dx,3c8h
+ xor cx,cx
+fade_one_30:
+ cmp byte [es:bx],0
+ jz fade_one_70
+
+ mov al,cl
+ out dx,al
+
+ inc dx
+
+ mov al,[fs:di]
+ mov ah,[fs:si]
+ call fade_it
+ shr al,2
+ out dx,al
+
+ mov al,[fs:di+1]
+ mov ah,[fs:si+1]
+ call fade_it
+ shr al,2
+ out dx,al
+
+ mov al,[fs:di+2]
+ mov ah,[fs:si+2]
+ call fade_it
+ shr al,2
+ out dx,al
+
+ dec dx
+fade_one_70:
+ inc bx
+ add si,3
+ inc cx
+ cmp cx,100h
+ jb fade_one_30
+
+fade_one_90:
+ pop fs
+ ret
+
+
+; al old color
+; ah new color
+; bp step (0 - 100h)
+;
+; return:
+; al color
+fade_it:
+ push cx
+ push dx
+ push bp
+
+ push ax
+ movzx ax,ah
+ mul bp
+ mov cx,ax
+ sub bp,100h
+ neg bp
+ pop ax
+ mov ah,0
+ mul bp
+ add ax,cx
+ mov al,ah
+
+ pop bp
+ pop dx
+ pop cx
+ ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+parse_img:
+ push fs
+ mov eax,[pcx_line_starts]
+ or eax,eax
+ jz parse_img_10
+ call free
+parse_img_10:
+ movzx eax,word [image_height]
+ shl eax,2
+ call calloc
+ or eax,eax
+ stc
+ mov [pcx_line_starts],eax
+ jz parse_img_90
+ lin2segofs eax,es,di
+ lfs si,[image_data]
+
+ xor dx,dx ; y count
+
+parse_img_20:
+ xor cx,cx ; x count
+ mov [es:di],si
+ mov [es:di+2],fs
+ add di,4
+parse_img_30:
+ fs lodsb
+ cmp al,0c0h
+ jb parse_img_40
+ and ax,3fh
+ inc si
+ add cx,ax
+ dec cx
+parse_img_40:
+ inc cx
+ cmp cx,[image_width]
+ jb parse_img_30
+ stc
+ jnz parse_img_90 ; no decoding break at line end?
+
+ ; normalize fs:si
+ mov bp,si
+ and si,0fh
+ shr bp,4
+ mov ax,fs
+ add ax,bp
+ mov fs,ax
+
+ inc dx
+ cmp dx,[image_height]
+ jb parse_img_20
+
+parse_img_90:
+ pop fs
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; cx colors
+; dx src
+; bx dst
+;
+tint:
+ push fs
+
+ ; ensure we don't exceed bounds
+ cmp dx,100h
+ jae tint_90
+ cmp bx,100h
+ jae tint_90
+
+ mov ax,dx
+ cmp dx,bx
+ jae tint_10
+ mov ax,bx
+tint_10:
+ add ax,cx
+ sub ax,100h
+ jb tint_20
+ sub cx,ax
+tint_20:
+ or cx,cx
+ jz tint_90
+
+ lfs si,[gfx_pal]
+ les di,[gfx_pal_tmp]
+
+ imul ax,dx,3
+ add si,dx
+ imul ax,bx,3
+ add di,ax
+ imul cx,cx,3
+ push ax
+ push cx
+
+ xor bx,bx
+
+tint_40:
+ movzx ax,byte [gfx_cs_r + bx]
+ fs movzx bp,byte [si]
+ inc si
+ sub ax,bp
+ push bp
+ movzx dx,byte [gfx_cs_tint_r + bx]
+ imul dx
+ mov bp,0ffh ; 100
+ idiv bp
+ pop bp
+ add ax,bp
+ jns tint_50
+ xor ax,ax
+tint_50:
+ or ah,ah
+ jz tint_60
+ mov ax,0ffh
+tint_60:
+ stosb
+ inc bx
+ cmp bx,3
+ jb tint_70
+ xor bx,bx
+tint_70:
+ loop tint_40
+
+ pop cx
+ pop ax
+
+ lfs si,[gfx_pal_tmp]
+ les di,[gfx_pal]
+
+ add di,ax
+ add si,ax
+ fs rep movsb
+tint_90:
+ pop fs
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Clip drawing area.
+;
+; [gfx_cur_x] left border
+; [gfx_cur_y] top border
+; [gfx_width] width
+; [gfx_height] height
+;
+; return:
+; CF 1 = empty area
+; If CF = 0 Area adjusted to fit within [clip_*].
+; If CF = 1 Undefined values in [gfx_*].
+;
+; Changed registers: -
+;
+clip_it:
+ pusha
+
+ mov ax,[gfx_cur_x]
+ mov dx,[gfx_width]
+ mov cx,[clip_l]
+ add dx,ax
+
+ sub ax,cx
+ jge clip_it_10
+ add [gfx_width],ax
+ mov [gfx_cur_x],cx
+clip_it_10:
+ sub dx,[clip_r]
+ jl clip_it_20
+ sub [gfx_width],dx
+clip_it_20:
+ cmp word [gfx_width],0
+ jg clip_it_30
+ mov word [gfx_width],0
+ stc
+ jmp clip_it_90
+clip_it_30:
+
+ mov ax,[gfx_cur_y]
+ mov dx,[gfx_height]
+ mov cx,[clip_t]
+ add dx,ax
+
+ sub ax,cx
+ jge clip_it_40
+ add [gfx_height],ax
+ mov [gfx_cur_y],cx
+clip_it_40:
+ sub dx,[clip_b]
+ jl clip_it_50
+ sub [gfx_height],dx
+clip_it_50:
+ cmp word [gfx_height],0
+ jg clip_it_90
+ mov word [gfx_height],0
+ stc
+
+clip_it_90:
+ popa
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; save a screen region
+;
+; dx,cx = width, height
+; es:di = buffer
+;
+save_bg:
+ push fs
+
+ push es
+ push di
+
+ call goto_xy
+
+ call screen_seg_r
+
+ mov si,di
+ pop di
+ pop es
+
+ or cx,cx
+ jz save_bg_90
+ or dx,dx
+ jz save_bg_90
+
+ imul dx,[pixel_bytes]
+
+save_bg_20:
+ push dx
+save_bg_30:
+ mov al,[fs:si]
+ inc si
+ jnz save_bg_40
+ call inc_winseg
+save_bg_40:
+ mov [es:di],al
+ inc di
+ jnz save_bg_50
+ mov bp,es
+ add bp,1000h
+ mov es,bp
+save_bg_50:
+ dec dx
+ jnz save_bg_30
+ pop dx
+ mov ax,[screen_line_len]
+ sub ax,dx
+ add si,ax
+ jnc save_bg_60
+ call inc_winseg
+save_bg_60:
+ dec cx
+ jnz save_bg_20
+
+save_bg_90:
+ pop fs
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Restore a screen region.
+;
+; dx,cx width, height
+; bx bytes per line
+; es:di buffer
+;
+; Does not change cursor positon.
+;
+restore_bg:
+ push fs
+
+ push dword [gfx_cur]
+
+ mov [gfx_width],dx
+ mov [gfx_height],cx
+
+ mov ax,[gfx_cur_x]
+ mov cx,[gfx_cur_y]
+
+ call clip_it
+ jc restore_bg_90
+
+ sub ax,[gfx_cur_x]
+ neg ax
+ mul word [pixel_bytes]
+ movzx ebp,ax
+
+ sub cx,[gfx_cur_y]
+ neg cx
+ movzx ecx,cx
+ movzx ebx,bx
+ imul ecx,ebx
+ add ecx,ebp
+
+ push es
+ push di
+ call so2lin
+ add [esp],ecx
+ call lin2so
+ pop di
+ pop es
+
+ mov dx,[gfx_width]
+ mov cx,[gfx_height]
+
+ push es
+ push di
+
+ call goto_xy
+
+ call screen_seg_w
+
+ pop si
+ pop fs
+
+ imul dx,[pixel_bytes]
+
+restore_bg_20:
+ push dx
+restore_bg_30:
+ mov al,[fs:si]
+ inc si
+ jnz restore_bg_40
+ mov bp,fs
+ add bp,1000h
+ mov fs,bp
+restore_bg_40:
+ mov [es:di],al
+ inc di
+ jnz restore_bg_50
+ call inc_winseg
+restore_bg_50:
+ dec dx
+ jnz restore_bg_30
+ pop dx
+ mov ax,[screen_line_len]
+ sub ax,dx
+ add di,ax
+ jnc restore_bg_60
+ call inc_winseg
+restore_bg_60:
+ mov ax,bx
+ sub ax,dx
+ add si,ax
+ jnc restore_bg_70
+ mov bp,fs
+ add bp,1000h
+ mov fs,bp
+restore_bg_70:
+ dec cx
+ jnz restore_bg_20
+
+restore_bg_90:
+ pop dword [gfx_cur]
+
+ pop fs
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Save a screen region to extended memory.
+;
+; dx,cx width, height
+; edi buffer (linear address)
+;
+xsave_bg:
+ push edi
+
+ call goto_xy
+ mov ax,[window_seg_w]
+ cmp word [window_seg_r],byte 0
+ jz xsave_bg_10
+ mov ax,[window_seg_r]
+xsave_bg_10:
+ segofs2lin ax,di,esi
+
+ pop edi
+
+ or cx,cx
+ jz xsave_bg_90
+ or dx,dx
+ jz xsave_bg_90
+
+ call real_to_pm
+
+xsave_bg_20:
+ push dx
+xsave_bg_30:
+ mov al,[es:esi]
+ inc si
+ jnz xsave_bg_40
+ call pm_to_real
+ call inc_winseg
+ call real_to_pm
+xsave_bg_40:
+ mov [es:edi],al
+ inc edi
+ dec dx
+ jnz xsave_bg_30
+ pop dx
+ mov ax,[screen_line_len]
+ sub ax,dx
+ add si,ax
+ jnc xsave_bg_60
+ call pm_to_real
+ call inc_winseg
+ call real_to_pm
+xsave_bg_60:
+ dec cx
+ jnz xsave_bg_20
+
+ call pm_to_real
+
+xsave_bg_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Restore a screen region from extended memory.
+;
+; dx,cx width, height
+; bx bytes per line
+; edi buffer (linear address)
+;
+; note:
+; bx must be >= dx
+;
+; Does not change cursor positon.
+;
+xrestore_bg:
+ push dword [gfx_cur]
+
+ mov [gfx_width],dx
+ mov [gfx_height],cx
+
+ call clip_it
+ jc restore_bg_90
+
+ mov dx,[gfx_width]
+ mov cx,[gfx_height]
+
+ push edi
+
+ call goto_xy
+ segofs2lin word [window_seg_w],di,edi
+
+ pop esi
+
+ or cx,cx
+ jz xrestore_bg_90
+ or dx,dx
+ jz xrestore_bg_90
+
+ call real_to_pm
+
+xrestore_bg_20:
+ push dx
+xrestore_bg_30:
+ mov al,[es:esi]
+ inc esi
+ mov [es:edi],al
+ inc di
+ jnz xrestore_bg_50
+ call pm_to_real
+ call inc_winseg
+ call real_to_pm
+xrestore_bg_50:
+ dec dx
+ jnz xrestore_bg_30
+ pop dx
+ mov ax,[screen_line_len]
+ sub ax,dx
+ add di,ax
+ jnc xrestore_bg_60
+ call pm_to_real
+ call inc_winseg
+ call real_to_pm
+xrestore_bg_60:
+ movzx eax,bx
+ sub ax,dx
+ add esi,eax
+ dec cx
+ jnz xrestore_bg_20
+
+ call pm_to_real
+
+xrestore_bg_90:
+ pop dword [gfx_cur]
+
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Load screen segments. Write segment to es, read segment to fs.
+;
+; Modified registers: -
+;
+screen_segs:
+ call screen_seg_w
+ jmp screen_seg_r
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Load write segment to es.
+;
+; Modified registers: -
+;
+screen_seg_w:
+ mov es,[window_seg_w]
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Load read segment to fs.
+;
+; Modified registers: -
+;
+screen_seg_r:
+ cmp word [window_seg_r],0
+ jz screen_seg_r_10
+ mov fs,[window_seg_r]
+ ret
+screen_seg_r_10:
+ mov fs,[window_seg_w]
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; draw a filled rectangle
+;
+; dx, cx = width, height
+; eax color
+; bh,bl = bh -> bl
+; bp = drawing mode
+; 0: move, 1: add, 2,3: dto, except for bh (bh->bl)
+;
+fill_rect:
+ mov [gfx_width],dx
+ mov [gfx_height],cx
+
+ call clip_it
+ jc fill_rect_90
+
+ mov dx,[gfx_width]
+ mov cx,[gfx_height]
+
+ call goto_xy
+
+ call screen_segs
+
+ mov bp,[screen_line_len]
+ push dx
+ mov ax,dx
+ xor dx,dx
+ mul word [pixel_bytes]
+ sub bp,ax
+ pop dx
+
+fill_rect_20:
+ mov bx,dx
+fill_rect_30:
+ call [setpixel_t]
+ add di,[pixel_bytes]
+ jnc fill_rect_60
+ call inc_winseg
+fill_rect_60:
+ dec bx
+ jnz fill_rect_30
+
+ add di,bp
+ jnc fill_rect_80
+ call inc_winseg
+fill_rect_80:
+ dec cx
+ jnz fill_rect_20
+
+fill_rect_90:
+ ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+new_int8:
+ pushad
+ push ds
+ push es
+ push fs
+ push gs
+
+ push cs
+ pop ds
+
+ mov al,20h
+ out 20h,al
+
+ inc dword [int8_count]
+
+ cmp byte [sound_playing],0
+ jnz new_int8_10
+
+ mov ax,[sound_timer1]
+ out 40h,al
+ mov al,ah
+ out 40h,al
+
+ jmp new_int8_90
+
+new_int8_10:
+
+%if 0
+ rdtsc
+ mov esi,[next_int]
+ mov edi,[next_int + 4]
+ sub esi,eax
+ sbb edi,edx
+ jnc new_int8_20
+
+ xor eax,eax
+ xor edx,edx
+ sub eax,esi
+ sbb edx,edi
+
+ mov [tmp_var_0],eax
+ mov [tmp_var_1],edx
+%endif
+
+new_int8_20:
+ rdtsc
+ mov edi,edx
+ mov esi,eax
+
+ sub eax,[next_int]
+ sbb edx,[next_int + 4]
+ jb new_int8_20
+
+ add esi,[cycles_per_int]
+ adc edi,0
+ mov [next_int],esi
+ mov [next_int + 4],edi
+
+ mov si,[sound_start]
+ cmp si,[sound_end]
+ jz new_int8_25
+
+ les bx,[sound_buf]
+ mov dl,[es:bx+si]
+
+ cmp dl,0ffh
+ jz new_int8_22
+
+ mov al,[sound_61]
+ out 61h,al
+ and al,0xfe
+ out 61h,al
+
+ mov al,dl
+ out 42h,al
+
+new_int8_22:
+ inc si
+ cmp si,sound_buf_size
+ jb new_int8_23
+ xor si,si
+new_int8_23:
+
+ mov [sound_start],si
+
+new_int8_25:
+ mov ax,[sound_timer1]
+ out 40h,al
+ mov al,ah
+ out 40h,al
+
+ mov ax,[sound_timer0]
+ or ax,ax
+ jz new_int8_30
+ add [sound_cnt0],ax
+ jnc new_int8_40
+new_int8_30:
+ push word 40h
+ pop es
+ inc dword [es:6ch]
+new_int8_40:
+
+ cmp byte [sound_int_active],0
+ jnz new_int8_90
+
+ mov byte [sound_int_active],1
+
+ sti
+
+ mov ax,[sound_end]
+ sub ax,[sound_start]
+ jnc new_int8_60
+ add ax,sound_buf_size
+new_int8_60:
+ cmp ax,160
+ jae new_int8_80
+ call mod_get_samples
+
+new_int8_80:
+
+ mov byte [sound_int_active],0
+new_int8_90:
+
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ popad
+
+ iret
+
+sound_init:
+ cmp byte [sound_ok],0
+ jnz sound_init_90
+
+ call chk_tsc
+ jc sound_init_90
+
+ mov eax,ar_sizeof
+ call calloc
+ cmp eax,byte 1
+ jc sound_init_90
+ push eax
+ call lin2so
+ pop dword [mod_buf]
+
+ call mod_init
+
+ mov eax,sound_buf_size
+ call calloc
+ cmp eax,byte 1
+ jc sound_init_90
+ push eax
+ call lin2so
+ pop dword [sound_buf]
+
+ xor eax,eax
+ mov [int8_count],eax
+ mov [sound_start],ax
+ mov [sound_end],ax
+ mov [sound_playing],al
+ mov [sound_int_active],al
+
+ push ds
+ pop es
+ mov di,playlist
+ mov cx,playlist_entries * sizeof_playlist
+ rep stosb
+
+ pushf
+ cli
+
+ in al,61h
+ mov [sound_old_61],al
+ or al,3
+ mov [sound_61],al
+
+ mov al,92h
+ out 43h,al
+
+ mov al,30h
+ out 43h,al
+
+ xor ax,ax
+ out 40h,al
+ out 40h,al
+
+ push word 0
+ pop es
+
+ push dword [es:8*4]
+ pop dword [sound_old_int8]
+
+ push cs
+ push word new_int8
+ pop dword [es:8*4]
+
+ popf
+
+ mov eax,[int8_count]
+sound_init_40:
+ cmp eax,[int8_count]
+ jz sound_init_40
+
+ rdtsc
+
+ mov edi,edx
+ mov esi,eax
+
+ mov eax,[int8_count]
+ add eax,4
+sound_init_50:
+ cmp eax,[int8_count]
+ jnz sound_init_50
+
+ rdtsc
+
+ sub eax,esi
+ sbb edx,edi
+
+ shrd eax,edx,18
+ adc eax,0
+ mov [cycles_per_tt],eax
+
+ mov [tmp_var_0],eax
+ mov [tmp_var_1],edx
+
+ mov eax,16000
+ call sound_setsample
+
+ xor eax,eax
+ mov [next_int],eax
+ mov [next_int + 4],eax
+
+ mov byte [sound_ok],1
+sound_init_90:
+ ret
+
+
+sound_done:
+ cmp byte [sound_ok],0
+ jz sound_done_90
+
+ pushf
+ cli
+
+ mov al,[sound_old_61]
+ out 61h,al
+
+ mov al,36h
+ out 43h,al
+
+ xor ax,ax
+ out 40h,al
+ out 40h,al
+
+ mov [sound_timer0],ax
+ mov [sound_timer1],ax
+ mov [sound_cnt0],ax
+ mov [sound_playing],al
+
+ push word 0
+ pop es
+
+ push dword [sound_old_int8]
+ pop dword [es:8*4]
+
+ mov byte [sound_ok],0
+
+ popf
+
+ push dword [mod_buf]
+ call so2lin
+ pop eax
+ call free
+
+ push dword [sound_buf]
+ call so2lin
+ pop eax
+ call free
+
+sound_done_90:
+ ret
+
+
+; eax: new sample rate
+sound_setsample:
+ cmp eax,20
+ jae sound_setsample_20
+ mov eax,20
+sound_setsample_20:
+ cmp eax,18000
+ jbe sound_setsample_50
+ mov eax,18000
+sound_setsample_50:
+ mov [sound_sample],eax
+ xchg eax,ecx
+ mov eax,1193180
+ xor edx,edx
+ div ecx
+ mov [sound_timer0],ax
+ push eax
+ mul dword [cycles_per_tt]
+ mov [cycles_per_int],eax
+
+ mov [tmp_var_2],eax
+
+ pop eax
+
+ ; 5/4 faster
+ imul eax,eax,4
+ mov ecx,5
+ div ecx
+
+ mov [sound_timer1],ax
+ mov [tmp_var_3],eax
+
+ pushf
+ cli
+ out 40h,al
+ mov al,ah
+ out 40h,al
+ popf
+sound_setsample_90:
+ ret
+
+%if 0
+sound_test:
+ cmp dword [sound_x],0
+ jz sound_test_80
+
+ call sound_init
+ jc sound_test_90
+
+ mov eax,16000
+ call sound_setsample
+
+ mov byte [sound_playing],1
+
+ jmp sound_test_90
+
+
+
+sound_test_80:
+ call sound_done
+sound_test_90:
+ ret
+%endif
+
+
+; mod player
+%include "modplay.inc"
+
+
+mod_init:
+ push ds
+ push dword [mod_buf]
+ pop si
+ pop ds
+ call init
+ clc
+ pop ds
+ ret
+
+mod_load:
+ push ds
+ push dword [mod_buf]
+ pop si
+ pop ds
+ call loadmod
+ pop ds
+ ret
+
+mod_play:
+ push ds
+ push dword [mod_buf]
+ pop si
+ pop ds
+ call playmod
+ pop ds
+ mov byte [sound_playing],1
+ ret
+
+mod_playsample:
+ push ds
+ push dword [mod_buf]
+ pop si
+ pop ds
+ call playsamp
+ pop ds
+ mov byte [sound_playing],1
+ ret
+
+mod_get_samples:
+ push ds
+ push dword [mod_buf]
+ pop si
+ pop ds
+ call play
+ mov dl,[si]
+ add si,ar_samps
+ push ds
+ pop fs
+ pop ds
+
+ ; dl: 0/1 --> play nothing/play
+ sub dl,1
+
+ mov cx,num_samples
+ les bx,[sound_buf]
+ mov di,[sound_end]
+ cld
+
+mod_get_samples_20:
+
+ fs lodsb
+ or al,dl ; 0ffh if we play nothing
+ mov [es:bx+di],al
+ inc di
+ cmp di,sound_buf_size
+ jb mod_get_samples_50
+ xor di,di
+
+mod_get_samples_50:
+
+ dec cx
+ jnz mod_get_samples_20
+ mov [sound_end],di
+
+mod_get_samples_90:
+ ret
+
+mod_setvolume:
+ cmp byte [sound_ok],0
+ jz mod_setvolume_90
+ push ds
+ push dword [mod_buf]
+ pop si
+ pop ds
+
+ mov dx,ax
+ xor ax,ax
+ or dx,dx
+ jz mod_setvolume_50
+ sub ax,1
+ sbb dx,0
+ mov bx,100
+ div bx
+mod_setvolume_50:
+ mov bx,ax
+ xor ax,ax
+ mov cx,ax
+ dec ax
+ call setvol
+
+ pop ds
+mod_setvolume_90:
+ ret
+
+
+; see if we have a time stamp counter
+chk_tsc:
+ mov ecx,1 << 21
+ pushfd
+ pushfd
+ pop eax
+ xor eax,ecx
+ push eax
+ popfd
+ pushfd
+ pop edx
+ popfd
+ xor eax,edx
+ cmp eax,ecx
+ stc
+ jz chk_tsc_90
+ mov eax,1
+ cpuid
+ test dl,1 << 4
+ jnz chk_tsc_90
+ stc
+chk_tsc_90:
+ ret
+
+
diff --git a/getx11font.c b/getx11font.c
new file mode 100644
index 0000000..b0d4116
--- /dev/null
+++ b/getx11font.c
@@ -0,0 +1,712 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <iconv.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#define MAGIC 0xd2828e07
+
+struct option options[] = {
+ { "verbose", 0, NULL, 'v' },
+ { "font", 1, NULL, 'f' },
+ { "add", 1, NULL, 'a' },
+ { "add-text", 1, NULL, 't' },
+ { "add-charset", 1, NULL, 'c' },
+ { "line-height", 1, NULL, 'l' },
+ { "prop", 1, NULL, 'p' },
+ { "test", 0, NULL, 999 },
+ { }
+};
+
+typedef struct {
+ unsigned size;
+ unsigned char *data;
+ unsigned real_size;
+} file_data_t;
+
+typedef struct {
+ uint32_t magic;
+ uint16_t entries;
+ uint8_t height;
+ uint8_t line_height;
+} font_header_t;
+
+typedef struct {
+ uint16_t ofs;
+ uint16_t c;
+ uint32_t size;
+} char_header_t;
+
+typedef struct {
+ char *name;
+ XFontStruct *x;
+ unsigned used:1; /* font actually used */
+} font_t;
+
+typedef struct char_data_s {
+ struct char_data_s* next;
+ unsigned ok:1; /* char exists */
+ int c; /* char (utf32) */
+ int index; /* array index for font */
+ font_t *font; /* pointer to font */
+ int width; /* char width */
+ int height; /* char (actually font) height */
+ unsigned char *bitmap; /* char bitmap, width x height */
+ int x_ofs;
+ int y_ofs;
+ int real_width;
+ int real_height;
+ char_header_t head;
+} char_data_t;
+
+int opt_verbose = 0;
+char *opt_file;
+int opt_test = 0;
+int opt_line_height = 0;
+int opt_prop = 0;
+int opt_spacing = 0;
+int opt_space_width = 0;
+
+file_data_t font = {};
+
+font_t font_list[16];
+int fonts;
+
+char_data_t *char_list;
+
+static char_data_t *add_char(int c);
+static char_data_t *find_char(int c);
+static void dump_char(char_data_t *cd);
+static void dump_char_list(void);
+static void sort_char_list(void);
+static int char_sort(const void *a, const void *b);
+static void locate_char(char_data_t *cd);
+static int char_index(XFontStruct *xfont, int c);
+static int empty_row(char_data_t *cd, int row);
+static int empty_column(char_data_t *cd, int column);
+static void add_bbox(char_data_t *cd);
+static void make_prop(char_data_t *cd);
+static void encode_chars(font_header_t *fh);
+static void add_data(file_data_t *d, void *buffer, unsigned size);
+static void write_data(char *name);
+
+int main(int argc, char **argv)
+{
+ Display *display;
+ XGCValues gcv;
+ GC gc1, gc2;
+ Pixmap pixmap;
+ XImage *xi;
+ XChar2b xc;
+ int i, j, k, font_width, font_height;
+ char *str, *str1;
+ char_data_t *cd;
+ iconv_t ic = (iconv_t) -1, ic2;
+ char obuf[4], ibuf[6];
+ char obuf2[4*0x100], ibuf2[0x100];
+ char *obuf_ptr, *ibuf_ptr;
+ size_t obuf_left, ibuf_left;
+ FILE *f;
+ font_header_t fh;
+ unsigned char uc;
+
+ opterr = 0;
+
+ while((i = getopt_long(argc, argv, "a:f:c:l:p:t:v", options, NULL)) != -1) {
+ switch(i) {
+ case 'f':
+ if(fonts < sizeof font_list / sizeof *font_list) {
+ font_list[fonts++].name = optarg;
+ }
+ break;
+
+ case 'a':
+ str = optarg;
+ if(sscanf(str, "%i - %i%n", &i, &j, &k) == 2 && k == strlen(str)) {
+ if(i < 0 || j < 0 || j < i || j - i >= 0x10000) {
+ fprintf(stderr, "invalid char range spec: %s\n", str);
+ return 1;
+ }
+ while(i <= j) add_char(i++);
+ }
+ else {
+ i = strtol(str, &str1, 0);
+ if(*str1 || i < 0) {
+ fprintf(stderr, "invalid char number: %s\n", str);
+ return 1;
+ }
+ add_char(i);
+ }
+ break;
+
+ case 'l':
+ str = optarg;
+ i = strtol(str, &str1, 0);
+ if(*str1 || i < 0) {
+ fprintf(stderr, "invalid line height: %s\n", str);
+ return 1;
+ }
+ opt_line_height = i;
+ break;
+
+ case 'p':
+ str = optarg;
+ if(sscanf(str, "%i , %i%n", &i, &j, &k) == 2 && k == strlen(str)) {
+ opt_prop = 1;
+ opt_spacing = i;
+ opt_space_width = j;
+ }
+ else {
+ fprintf(stderr, "invalid spec: %s\n", str);
+ return 1;
+ }
+ break;
+
+ case 'c':
+ ic2 = iconv_open("utf32le", optarg);
+ if(ic2 == (iconv_t) -1) {
+ fprintf(stderr, "don't know char set %s\ntry 'iconv --list'\n", optarg);
+ return 1;
+ }
+ ibuf_ptr = ibuf2;
+ ibuf_left = sizeof ibuf2;
+ obuf_ptr = obuf2;
+ obuf_left = sizeof obuf2;
+ for(j = 0; j < sizeof ibuf2; j++) ibuf2[j] = j;
+ iconv(ic2, &ibuf_ptr, &ibuf_left, &obuf_ptr, &obuf_left);
+ for(str = obuf2; str < obuf_ptr; str += 4) {
+ i = *(int *) str;
+ if(i >= 0x20) add_char(i);
+ }
+ iconv_close(ic2);
+ break;
+
+ case 't':
+ if(ic == (iconv_t) -1) {
+ ic = iconv_open("utf32le", "utf8");
+ if(ic == (iconv_t) -1) {
+ fprintf(stderr, "can't convert utf8 data\n");
+ return 1;
+ }
+ }
+ if((f = fopen(optarg, "r"))) {
+ int ok;
+
+ ibuf_left = 0;
+ while((i = fread(ibuf + ibuf_left, 1, sizeof ibuf - ibuf_left, f)) > 0) {
+ // fprintf(stderr, "ibuf_left = %d, fread = %d\n", ibuf_left, i);
+ ibuf_ptr = ibuf;
+ ibuf_left += i;
+ do {
+ obuf_ptr = obuf;
+ obuf_left = sizeof obuf;
+ k = iconv(ic, &ibuf_ptr, &ibuf_left, &obuf_ptr, &obuf_left);
+ // fprintf(stderr, "k = %d, errno = %d, ibuf_left = %d, obuf_left = %d\n", k, errno, ibuf_left, obuf_left);
+ if(k >= 0 || (k == -1 && errno == E2BIG)) {
+ ok = 1;
+ if(!obuf_left) {
+ i = *(int *) obuf;
+ if(i >= 0x20) {
+ // fprintf(stderr, "add char 0x%x\n", i);
+ add_char(i);
+ }
+ }
+ }
+ else {
+ ok = 0;
+ }
+ }
+ while(ok && ibuf_left);
+ if(k == -1 && errno == EILSEQ) {
+ perror("iconv");
+ return 1;
+ }
+ if(ibuf_left) {
+ memcpy(ibuf, ibuf + sizeof ibuf - ibuf_left, ibuf_left);
+ }
+ }
+ fclose(f);
+ }
+ else {
+ perror(optarg);
+ return 1;
+ }
+ break;
+
+ case 'v':
+ opt_verbose++;
+ break;
+
+ case 999:
+ opt_test++;
+ break;
+ }
+ }
+
+ argc -= optind; argv += optind;
+
+ if(argc != 1) {
+ fprintf(stderr,
+ "Usage: getx11font [options] fontfile\n"
+ "Build font for boot loader using X11 fonts.\n"
+ " -a, --add=first[-last]\n\tAdd chars from this range.\n"
+ " -c, --add-charset=charset\n\tAdd all chars from this charset.\n"
+ " -f, --font=X11_font_spec\n\tUse this font.\n"
+ " -h, --help\n\tShow this help text.\n"
+ " -l, --line-height=n\n\tSet line height (default: font height).\n"
+ " -p, --prop=n1,n2\n\tFake proportionally spaced Font.\n\tn1: spacing between chars; n2: space (char U+0020) width\n"
+ " -t, --add-text=samplefile\n\tAdd all chars used in this file. File must be UTF-8 encoded.\n"
+ " -v, --verbose\n\tDump font info.\n"
+ );
+ return 1;
+ }
+
+ opt_file = argv[0];
+
+ if(ic != (iconv_t) -1) iconv_close(ic);
+
+ /* use default char list */
+ if(!char_list) for(i = 0x20; i <= 0x7f; i++) add_char(i);
+
+ /* default font */
+ if(!fonts) font_list[fonts++].name = "fixed";
+
+ sort_char_list();
+
+ if(!(display = XOpenDisplay(getenv("DISPLAY")))) {
+ return fprintf(stderr, "unable to open display\n"), 2;
+ }
+
+ /* open all fonts */
+ for(i = 0; i < fonts; i++) {
+ if(!(font_list[i].x = XLoadQueryFont(display, font_list[i].name))) {
+ fprintf(stderr, "Warning: no such font: %s\n", font_list[i].name);
+ }
+ }
+
+ /* look for chars in fonts */
+ for(cd = char_list; cd; cd = cd->next) locate_char(cd);
+
+ /* get font heigth */
+ for(font_height = 0, i = 0; i < fonts; i++) {
+ if(font_list[i].used) {
+ j = font_list[i].x->max_bounds.ascent + font_list[i].x->max_bounds.descent;
+ if(j > font_height) font_height = j;
+ }
+ }
+
+ /* get font width */
+ for(font_width = 0, cd = char_list; cd; cd = cd->next) {
+ if(cd->width > font_width) font_width = cd->width;
+ /* char height = font height */
+ cd->height = font_height;
+ }
+
+ printf("Font Size: %d x %d", font_width, font_height);
+ if(opt_line_height && opt_line_height != font_height) {
+ printf(", Line Height: %d", opt_line_height);
+ }
+ printf("\n");
+
+ if(font_width > 32 || font_height > 32) {
+ fprintf(stderr, "Font size too large (max 32 x 32).\n");
+ return 8;
+ }
+
+ if(!font_width || !font_height) {
+ fprintf(stderr, "Strange font.\n");
+ return 8;
+ }
+
+ /* now, render all chars */
+
+ pixmap = XCreatePixmap(display, DefaultRootWindow(display), font_width, font_height, 1);
+
+ gcv.background = gcv.foreground = 0;
+ gcv.fill_style = FillSolid;
+
+ gc1 = XCreateGC(display, pixmap, GCForeground | GCBackground | GCFillStyle, &gcv);
+ gcv.foreground = 1;
+ gc2 = XCreateGC(display, pixmap, GCForeground | GCBackground | GCFillStyle, &gcv);
+
+ for(cd = char_list; cd; cd = cd->next) {
+ if(!cd->ok) continue;
+ xc.byte1 = cd->c >> 8;
+ xc.byte2 = cd->c;
+
+ XSetFont(display, gc2, cd->font->x->fid);
+
+ XFillRectangle(display, pixmap, gc1, 0, 0, font_width, font_height);
+ XDrawImageString16(display, pixmap, gc2, 0, cd->font->x->max_bounds.ascent, &xc, 1);
+
+ xi = XGetImage(display, pixmap, 0, 0, font_width, font_height, 1, XYPixmap);
+
+ cd->bitmap = calloc(cd->height * cd->width, 1);
+ for(k = 0, j = 0; j < cd->height; j++) {
+ for(i = 0; i < cd->width; i++) {
+ cd->bitmap[k++] = XGetPixel(xi, i, j);
+ }
+ }
+
+ XDestroyImage(xi);
+ }
+
+ XFreePixmap(display, pixmap);
+ XFreeGC(display, gc2);
+ XFreeGC(display, gc1);
+
+ XCloseDisplay(display);
+
+ for(cd = char_list; cd; cd = cd->next) add_bbox(cd);
+
+ if(opt_prop) {
+ for(cd = char_list; cd; cd = cd->next) make_prop(cd);
+ }
+
+ encode_chars(&fh);
+
+ for(i = j = 0, cd = char_list; cd; cd = cd->next) {
+ if(!cd->ok) {
+ printf(i ? ", " : "Missing Chars: ");
+ printf("0x%04x", cd->c);
+ i = 1;
+ }
+ }
+ if(i) printf("\n");
+
+ add_data(&font, &fh, sizeof fh);
+ for(cd = char_list; cd; cd = cd->next) {
+ if(!cd->ok) continue;
+ add_data(&font, &cd->head, sizeof cd->head);
+ }
+
+ i = 0;
+ for(cd = char_list; cd; cd = cd->next) {
+ if(!cd->ok) continue;
+ k = cd->real_width * cd->real_height;
+ for(uc = 0, i = j = 0; i < k; i++, j++) {
+ if(j == 8) {
+ add_data(&font, &uc, 1);
+ uc = 0;
+ j = 0;
+ }
+ if(cd->bitmap[i]) uc += (1 << j);
+ }
+ if(j) add_data(&font, &uc, 1);
+ }
+
+ if(opt_verbose) dump_char_list();
+
+ write_data(opt_file);
+
+ return 0;
+}
+
+
+char_data_t *add_char(int c)
+{
+ char_data_t *cd;
+
+ if((cd = find_char(c))) return cd;
+
+ cd = calloc(1, sizeof *cd);
+ cd->c = c;
+ cd->next = char_list;
+
+ return char_list = cd;
+}
+
+
+char_data_t *find_char(int c)
+{
+ char_data_t *cd;
+
+ for(cd = char_list; cd; cd = cd->next) {
+ if(cd->c == c) return cd;
+ }
+
+ return NULL;
+}
+
+
+void dump_char(char_data_t *cd)
+{
+ int i, j;
+ unsigned char *p;
+
+ if(!cd || !cd->ok) return;
+
+ printf(
+ "Char 0x%04x\n Font: %s\n Size: %d x %d\n",
+ cd->c, cd->font->name, cd->width, cd->height
+ );
+
+ if(cd->bitmap) {
+ printf(
+ " Bitmap: %d x %d\n Offset: %d x %d\n",
+ cd->real_width, cd->real_height, cd->x_ofs, cd->y_ofs
+ );
+ p = cd->bitmap;
+ for(j = 0; j < cd->height; j++) {
+ printf(" |");
+ if(j < cd->y_ofs || j >= cd->y_ofs + cd->real_height) {
+ for(i = 0; i < cd->width; i++) printf(".");
+ }
+ else {
+ for(i = 0; i < cd->width; i++) {
+ if(i < cd->x_ofs || i >= cd->x_ofs + cd->real_width) {
+ printf(".");
+ }
+ else {
+ printf("%c", *p++ ? '#' : ' ');
+ }
+ }
+ }
+ printf("|\n");
+ }
+ }
+
+}
+
+
+void dump_char_list()
+{
+ char_data_t *cd;
+
+ for(cd = char_list; cd; cd = cd->next) {
+ dump_char(cd);
+ }
+}
+
+
+void sort_char_list()
+{
+ char_data_t *cd;
+ unsigned u, len;
+ char_data_t **c_list;
+
+ for(len = 0, cd = char_list; cd; cd = cd->next) len++;
+
+ if(!len) return;
+
+ c_list = calloc(len + 1, sizeof *c_list);
+
+ for(u = 0, cd = char_list; cd; cd = cd->next, u++) c_list[u] = cd;
+
+ qsort(c_list, len, sizeof *c_list, char_sort);
+
+ for(u = 0; u < len; u++) {
+ c_list[u]->next = c_list[u + 1];
+ }
+
+ char_list = *c_list;
+
+ free(c_list);
+}
+
+
+int char_sort(const void *a, const void *b)
+{
+ return (*(char_data_t **) a)->c - (*(char_data_t **) b)->c;
+}
+
+
+void locate_char(char_data_t *cd)
+{
+ int i, j;
+ XCharStruct *xc;
+
+ for(i = 0; i < fonts; i++) {
+ if((j = char_index(font_list[i].x, cd->c)) >= 0) {
+ xc = font_list[i].x->per_char ? font_list[i].x->per_char + j : &(font_list[i].x->max_bounds);
+ if(xc && xc->width) {
+ cd->index = j;
+ cd->font = font_list + i;
+ cd->width = xc->width;
+ cd->ok = 1;
+ font_list[i].used = 1;
+ break;
+ }
+ }
+ }
+}
+
+
+int char_index(XFontStruct *xfont, int c)
+{
+ int i;
+
+ if(!xfont || (c & ~0xffff)) return -1;
+
+ if(!xfont->min_byte1 && !xfont->max_byte1) {
+ i = c - xfont->min_char_or_byte2;
+ if(i > (int) xfont->max_char_or_byte2) i = -1;
+ }
+ else {
+ i = ((c >> 8) - xfont->min_byte1)
+ * (xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
+ + (c & 0xff) - xfont->min_char_or_byte2;
+ }
+
+ return i;
+}
+
+
+int empty_row(char_data_t *cd, int row)
+{
+ unsigned char *p1, *p2;
+
+ p2 = (p1 = cd->bitmap + row * cd->real_width) + cd->real_width;
+ while(p1 < p2) if(*p1++) return 0;
+
+ return 1;
+}
+
+
+int empty_column(char_data_t *cd, int col)
+{
+ int i;
+ unsigned char *p;
+
+ for(p = cd->bitmap + col, i = 0; i < cd->real_height; i++, p += cd->real_width) {
+ if(*p) return 0;
+ }
+
+ return 1;
+}
+
+
+void add_bbox(char_data_t *cd)
+{
+ int i;
+ unsigned char *p1, *p2;
+
+ if(!cd->ok) return;
+
+ cd->real_width = cd->width;
+ cd->real_height = cd->height;
+
+ if(opt_test) return;
+
+ while(cd->real_height && empty_row(cd, cd->real_height - 1)) cd->real_height--;
+
+ while(cd->real_height && empty_row(cd, 0)) {
+ cd->real_height--;
+ cd->y_ofs++;
+ memcpy(cd->bitmap, cd->bitmap + cd->real_width, cd->real_width * cd->real_height);
+ }
+
+ while(cd->real_width && empty_column(cd, cd->real_width - 1)) {
+ cd->real_width--;
+ p2 = (p1 = cd->bitmap + cd->real_width) + 1;
+ for(i = 1; i < cd->real_height; i++, p1 += cd->real_width, p2 += cd->real_width + 1) {
+ memcpy(p1, p2, cd->real_width);
+ }
+ }
+
+ while(cd->real_width && empty_column(cd, 0)) {
+ cd->real_width--;
+ cd->x_ofs++;
+ p2 = (p1 = cd->bitmap) + 1;
+ for(i = 0; i < cd->real_height; i++, p1 += cd->real_width, p2 += cd->real_width + 1) {
+ memcpy(p1, p2, cd->real_width);
+ }
+ }
+}
+
+
+/*
+ * Fake proprtionally spaced font from fixed size font.
+ */
+void make_prop(char_data_t *cd)
+{
+ if(!cd->ok) return;
+
+ cd->x_ofs = opt_spacing;
+ cd->width = cd->x_ofs + (cd->real_width ?: opt_space_width);
+}
+
+
+void encode_chars(font_header_t *fh)
+{
+ int ofs;
+ char_data_t *cd;
+
+ memset(fh, 0, sizeof *fh);
+ fh->magic = MAGIC;
+ fh->height = char_list->height;
+ fh->line_height = opt_line_height ?: fh->height;
+
+ ofs = sizeof *fh;
+
+ for(cd = char_list; cd; cd = cd->next) if(cd->ok) fh->entries++;
+
+ ofs += fh->entries * sizeof cd->head;
+
+ for(cd = char_list; cd; cd = cd->next) {
+ if(!cd->ok) continue;
+ memset(&cd->head, 0, sizeof cd->head);
+ cd->head.ofs = ofs;
+ cd->head.c = cd->c;
+ cd->head.size =
+ (((cd->c >> 16) & 0x1f) << 0) +
+ ((cd->x_ofs & 0x1f) << 5) +
+ ((cd->y_ofs & 0x1f) << 10) +
+ ((cd->real_width & 0x1f) << 15) +
+ ((cd->real_height & 0x1f) << 20) +
+ ((cd->width & 0x1f) << 25);
+ ofs += (cd->real_width * cd->real_height + 7) >> 3;
+ }
+}
+
+
+void add_data(file_data_t *d, void *buffer, unsigned size)
+{
+ if(!size || !d || !buffer) return;
+
+ if(d->size + size > d->real_size) {
+ d->real_size = d->size + size + 0x1000;
+ d->data = realloc(d->data, d->real_size);
+ if(!d->data) d->real_size = 0;
+ }
+
+ if(d->size + size <= d->real_size) {
+ memcpy(d->data + d->size, buffer, size);
+ d->size += size;
+ }
+ else {
+ fprintf(stderr, "Oops, out of memory? Aborted.\n");
+ exit(10);
+ }
+}
+
+
+void write_data(char *name)
+{
+ FILE *f;
+
+ f = strcmp(name, "-") ? fopen(name, "w") : stdout;
+
+ if(!f) {
+ perror(name);
+ return;
+ }
+
+ if(fwrite(font.data, font.size, 1, f) != 1) {
+ perror(name); exit(3);
+ }
+
+ fclose(f);
+}
+
+
diff --git a/help2txt b/help2txt
new file mode 100755
index 0000000..8a8b6c9
--- /dev/null
+++ b/help2txt
@@ -0,0 +1,78 @@
+#! /usr/bin/perl
+
+sub nospaces;
+
+if(!@ARGV) {
+ print "Usage: help2txt help_file\n" .
+ "Converts a help file from HTML to the format used by the boot loader.\n";
+ exit;
+}
+
+while(<>) {
+ s/\s*<\/?(hr|body|html|h\d+)\s*>//g;
+ s/\s*<!.*?>\s*//g;
+ s/<(em|strong)>/\x11/g;
+ s/<\/(em|strong)>/\x10/g;
+ while(/<a\s/) {
+ if(s/\<a\s+name=\"([^"]+)\">([^<]*)<\/a>\s*/\x04\x12$1\x14$2\x10/) {
+ if($anchor{$1}) {
+ die "line $.: anchor \"$1\" already exists\n";
+ }
+ else {
+ $anchor{$1} = 1;
+ }
+ die "line $.: label \"$1\" too long (max. 32)\n" if length $1 > 32;
+ }
+ elsif(s/<a\s+href=\"#([^"]+)\">([^<]*)<\/a>/"\x12" . $1 . "\x13" . nospaces($2) . "\x10"/e) {
+ $ref{$1}++;
+ die "line $.: label \"$1\" too long (max. 32)\n" if length $1 > 32;
+ }
+ else {
+ die "line $.: invalid 'A' element\n";
+ }
+ }
+
+ $txt .= $_;
+}
+
+$txt =~ s/\n( +)(?!\n)/"\n<!" . length($1) . ">"/seg;
+$txt =~ s/\s+/ /sg;
+$txt =~ s/\s*<br>\s*/\n/sg;
+$txt =~ s/<!(\d+)>/" " x $1/seg;
+$txt =~ s/(\x14.*?\x10)\s*/$1/sg;
+$txt =~ s/\s*(\x04|$)/$1/sg;
+
+print $txt, "\x00";
+
+$ref{help}++;
+
+for (keys %anchor) {
+ if(!$ref{$_}) {
+ $err = 1;
+ print STDERR "\"$_\" never referenced\n"
+ }
+}
+
+for (keys %ref) {
+ if(!$anchor{$_}) {
+ $err = 1;
+ print STDERR "\"$_\" never defined\n"
+ }
+}
+
+warn "*** inconsistencies detected ***\n" if $err;
+
+
+# \x1f looks like a space but is not a space. This is useful
+# to prevent automatic line breaks.
+sub nospaces
+{
+ local $_;
+
+ $_ = shift;
+
+ s/\s/\x1f/g;
+
+ $_
+}
+
diff --git a/keytab b/keytab
new file mode 100755
index 0000000..fcab7ed
--- /dev/null
+++ b/keytab
@@ -0,0 +1,80 @@
+#! /usr/bin/perl
+
+use Encode;
+use Getopt::Long;
+
+sub get_table;
+sub do_enc;
+
+$opt_all = 0;
+$opt_enc = undef;
+
+GetOptions(
+ 'all' => \$opt_all,
+ 'enc=s' => \$opt_enc
+);
+
+$keytable = shift;
+
+@us_map{get_table "us"} = () unless $opt_all;
+@map = get_table $keytable;
+
+for (keys %us_map) {
+ delete $us_map{$_} if /\[\s*0x56/;
+}
+
+
+print "/keymap.$keytable [\n";
+for (@map) {
+ print $_ unless exists $us_map{$_};
+}
+print "] def\n";
+
+
+sub get_table
+{
+ local $_;
+ my ($kt, $map_idx, @map, @psmap, $x, $n, $s, $a);
+
+ $kt = shift;
+
+ open F, "loadkeys -m $kt |";
+ while(<F>) {
+ $map_idx = 0 if /u_short/;
+ if(/u_short\s+plain_map\[/) { $map_idx = 1; $key_idx = 0 }
+ if(/u_short\s+shift_map\[/) { $map_idx = 2; $key_idx = 0 }
+ if(/u_short\s+altgr_map\[/) { $map_idx = 3; $key_idx = 0 }
+ if($map_idx) {
+ while(/(0xf\S{3}),/g) {
+ $x = $1;
+ $map[$key_idx][0] = $key_idx;
+ $map[$key_idx][$map_idx] = hex($x) & 0xff if $x =~ /0xf[0b]/;
+ $key_idx++;
+ }
+ }
+ }
+ close F;
+
+ for (@map) {
+ ($n, $s, $a) = ($_->[1], $_->[2], $_->[3]);
+ $a = 0 if $a == $n || $a == $s;
+ if($n || $s || $a) {
+ push @psmap, sprintf(" [ 0x%02x 0x%02x 0x%02x 0x%02x ]\n", $_->[0], do_enc($n), do_enc($s), do_enc($a));
+ }
+ }
+
+ @psmap;
+}
+
+
+sub do_enc
+{
+ my ($c);
+
+ $c = shift;
+
+ return $c unless $opt_enc;
+
+ return unpack("V", encode("utf32le", decode($opt_enc, chr($c))));
+}
+
diff --git a/kroete.inc b/kroete.inc
new file mode 100644
index 0000000..8f2d939
--- /dev/null
+++ b/kroete.inc
@@ -0,0 +1,100 @@
+; es:si pointer to data
+; bx == 0 forward != 0 backward
+kroete:
+ mov fs,[window_seg_w]
+ mov ax,[window_seg_r]
+ or ax,ax
+ jnz sul1
+ mov ax,[window_seg_w]
+sul1: mov gs,ax
+ mov di,[cs:screen_width]
+ shr di,1
+ imul di,[cs:pixel_bytes]
+ mov ax,[cs:screen_height]
+ shr ax,1
+ mul word [cs:screen_line_len]
+ add di,ax
+ adc dx,byte 0
+ mov ax,dx
+ call set_win
+ call kr_getpixel
+ or bx,bx
+ jnz sul3
+ lea bp,[si+16384]
+sul: mov bl,[es:si]
+ rol bl,2
+ call doit
+ rol bl,2
+ call doit
+ rol bl,2
+ call doit
+ rol bl,2
+ call doit
+ inc si
+ cmp si,bp
+ jnz sul
+ call kr_putpixel
+ ret
+sul3: lea bp,[si-1]
+ add si,16383
+sul4: mov bl,[es:si]
+ xor bl,0xaa
+ call doit
+ ror bl,2
+ call doit
+ ror bl,2
+ call doit
+ ror bl,2
+ call doit
+ dec si
+ cmp si,bp
+ jnz sul4
+ call kr_putpixel
+ ret
+doit:
+ push ecx
+ call kr_getpixel
+ mov edx,ecx
+ pop ecx
+ call kr_putpixel
+ mov ecx,edx
+ mov dl,bl
+ and dl,3
+ jnz doit1
+ sub di,[cs:pixel_bytes]
+ jnc doit4
+doit5: sbb al,0
+ jmp set_win
+doit1: dec dl
+ jnz doit2
+ sub di,[cs:screen_line_len]
+ jc doit5
+doit4: ret
+doit2: dec dl
+ jnz doit3
+ add di,[cs:pixel_bytes]
+ jnc doit4
+doit6: adc al,0
+ jmp set_win
+doit3: add di,[cs:screen_line_len]
+ jc doit6
+ ret
+
+kr_getpixel:
+ cmp byte [cs:pixel_bytes],1
+ ja kr_getpixel_10
+ mov cl,[fs:di]
+ ret
+kr_getpixel_10:
+ mov cx,[fs:di]
+ ret
+
+kr_putpixel:
+ cmp byte [cs:pixel_bytes],1
+ ja kr_putpixel_10
+ mov [gs:di],cl
+ ret
+kr_putpixel_10:
+ mov [gs:di],cx
+ ret
+
diff --git a/mk_vocabulary b/mk_vocabulary
new file mode 100755
index 0000000..b335598
--- /dev/null
+++ b/mk_vocabulary
@@ -0,0 +1,144 @@
+#! /usr/bin/perl
+
+# Ensure that both mkbootmsg.c & bincode.asm talk about the same thing.
+
+@callback = qw (
+ KeyEvent MenuInit InfoBoxInit InfoBoxDone
+ ProgressInit ProgressDone ProgressUpdate
+ PasswordInit PasswordDone
+ Timeout Timer
+);
+
+@primary = qw (
+ [ ] def if ifelse loop repeat for forall exit return array get put length
+ dup pop exch rot roll over index exec
+ add sub mul div mod neg abs min max and or xor not shl shr
+ eq ne gt ge lt le
+ trace dtrace
+ malloc free memsize dumpmem
+ gettype settype
+ screen.size image.colors
+ moveto currentpoint lineto setcolor currentcolor putpixel getpixel
+ setfont currentfont fontheight strsize show
+ image loadpalette tint settintcolor setpalette getpalette
+ settransparentcolor
+ savescreen restorescreen
+ fillrect
+ snprintf
+ edit.init edit.done edit.input edit.showcursor edit.hidecursor
+ updatedisk rmoveto bootloader
+ strstr
+
+ sound.getvolume sound.setvolume
+ sound.getsamplerate sound.setsamplerate
+ sound.play sound.done
+ mod.load mod.play mod.playsample
+
+ settextwrap currenttextwrap
+ seteotchar currenteotchar
+ settextcolors currenttextcolors
+ setmaxrows currentmaxrows
+ formattext
+ gettextrows setstartrow
+ getlinks
+ setlink currentlink
+ getlink
+ lineheight
+ currenttitle
+
+ videomodes getvideomode
+ xsavescreen
+
+ usleep
+ time
+ setbrightness currentbrightness
+ fadein fade
+ idle
+ image.size
+
+ bootdrive reloadfs usernote eject poweroff
+
+ getinfo
+
+ getbyte putbyte getdword putdword
+ findfile
+
+ setmode currentmode findmode
+ colorbits
+
+ setimage currentimage
+
+ settransparency currenttransparency
+
+);
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+sub canon_name;
+
+if($ARGV[0] eq '-a') {
+ printf "cb_functions\t\tequ %u\n", @callback + 0;
+ printf "prim_functions\t\tequ %u\n\n", @primary + 3;
+
+ $i = 0;
+ for (@callback) {
+ $c = canon_name $_;
+ $s = "";
+ $s .= "\t" if length $c < 3;
+ $s .= "\t" if length $c < 11;
+ print "cb_$c$s\tequ $i\n";
+ $i++;
+ }
+
+ print "\n%macro\t\t\tprim_jump_table 0\n";
+ print "jt_p_none\t\tdw 0\t\t\t; 00h\njt_p_code\t\tdw 0\t\t\t; 01h\njt_p_ret\t\tdw 0\t\t\t; 02h\n";
+ $i = 3;
+ for (@primary) {
+ $c = canon_name $_;
+ $s = "";
+ $s .= "\t" if length $c < 3;
+ $s .= "\t" if length $c < 11;
+ $t = "";
+ $t .= "\t" if length $_ < 8;
+ print "jt_p_$c$s\tdw prim_$c$t\t; ";
+ printf "%02xh\n", $i++
+ }
+ print "%endmacro\n"
+}
+
+if($ARGV[0] eq '-c') {
+ print "typedef enum {\n";
+ print " p_none,\n p_code,\n p_ret";
+ for (@primary) { $c = canon_name $_; print ",\n p_$c" }
+ print "\n} prim_t;\n\n";
+
+ print "struct {\n type_t type;\n unsigned value;\n char *name;\n} prim_names[] = {\n";
+
+ for (@callback) {
+ print " { t_none, 0, \"$_\" },\n"
+ }
+
+ print " { t_prim, p_code, \"{\" },\n";
+ print " { t_prim, p_ret, \"{\" }";
+
+ for (@primary) {
+ $c = canon_name $_;
+ print ",\n { t_prim, p_$c, \"$_\" }"
+ }
+
+ print "\n};\n"
+}
+
+
+sub canon_name
+{
+ local $_ = shift;
+
+ $_ = 'astart' if $_ eq '[';
+ $_ = 'aend' if $_ eq ']';
+ tr/.//d;
+
+ return $_
+}
+
+
diff --git a/mkbootmsg.c b/mkbootmsg.c
new file mode 100644
index 0000000..2fac4fd
--- /dev/null
+++ b/mkbootmsg.c
@@ -0,0 +1,1897 @@
+/*
+ * Create a boot loader graphics file.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <ctype.h>
+#include <iconv.h>
+
+#include "bincode.h"
+
+#define MAGIC 0xb2d97f00
+#define VERSION 5
+#define DICT_SIZE 1000
+
+#define MAX_INCLUDE 10
+
+typedef struct {
+ uint32_t magic_id;
+ uint8_t version;
+ uint8_t res_1;
+ uint8_t res_2;
+ uint8_t res_3;
+ uint32_t bincode;
+ uint32_t bincode_size;
+ uint32_t bincode_crc;
+ uint32_t dict;
+ uint32_t code;
+ uint32_t code_size;
+} file_header_t;
+
+typedef struct {
+ unsigned size;
+ unsigned char *data;
+ unsigned real_size;
+ unsigned char *ptr;
+ char *name;
+ int line;
+} file_data_t;
+
+struct option options[] = {
+ { "config", 1, NULL, 'c' },
+ { "info", 0, NULL, 'i' },
+ { "log", 0, NULL, 'l' },
+ { "help", 0, NULL, 'h' },
+ { }
+};
+
+// max. 16
+// Keep in sync with bincode.asm!
+typedef enum {
+ t_none, t_int, t_unsigned, t_bool, t_string, t_code, t_ret, t_prim,
+ t_sec, t_dict_idx, t_array, t_end, t_ptr,
+ t_skip = 15 /* special, for internal use */
+} type_t;
+
+// for log file
+static char *type_name[16] = {
+ "none", "int", "uint", "bool", "str", "code", "ret", "prim",
+ "sec", "dict", "arr", "end", "ptr", "", "", ""
+};
+
+typedef struct {
+ char *name;
+ type_t type;
+ int line;
+ int del, ref, ref_idx, ref_ind, def, def_idx, def_ind, ref0, ref0_idx;
+ union {
+ unsigned u;
+ unsigned char *p;
+ } value;
+} dict_t;
+
+typedef struct {
+ char *name;
+ type_t type;
+ unsigned ofs;
+ unsigned size;
+ int line, incl_level;
+ union {
+ unsigned u;
+ unsigned char *p;
+ } value;
+ unsigned char *enc;
+} code_t;
+
+void help(void);
+file_data_t read_file(char *name);
+int is_pcx(file_data_t *fd);
+void fix_pal(unsigned char *pal, unsigned shade1, unsigned shade2, unsigned char *rgb);
+void write_data(char *name);
+void add_data(file_data_t *d, void *buffer, unsigned size);
+code_t *new_code(void);
+dict_t *new_dict(void);
+unsigned number(char *value);
+void hexdump(file_data_t *fd, unsigned ofs, int len);
+void show_info(char *name);
+int get_hex(char *s, int len, unsigned *val);
+char *utf32_to_utf8(int u8);
+char *next_word(char **ptr);
+void parse_comment(char *comment, file_data_t *incl);
+int find_in_dict(char *name);
+int translate(int pass);
+void encode_dict(void);
+void parse_config(char *name, char *log_file);
+void optimize_dict(FILE *lf);
+unsigned skip_code(unsigned pos);
+unsigned next_code(unsigned pos);
+int optimize_code(FILE *lf);
+int optimize_code1(FILE *lf);
+int optimize_code2(FILE *lf);
+int optimize_code3(FILE *lf);
+int optimize_code4(FILE *lf);
+int optimize_code5(FILE *lf);
+int optimize_code6(FILE *lf);
+int optimize_code7(FILE *lf);
+void log_dict(FILE *lf);
+void log_code(FILE *lf);
+void log_cline(FILE *lf);
+void decompile(unsigned char *data, unsigned size);
+
+/* dummy function to make ld fail */
+extern void wrong_struct_size(void);
+
+int config_ok = 0;
+
+file_header_t header = {};
+
+file_data_t pscode = {};
+file_data_t dict_file = {};
+
+dict_t *dict = NULL;
+unsigned dict_size = 0;
+unsigned dict_max_size = 0;
+
+code_t *code = NULL;
+unsigned code_size = 0;
+unsigned code_max_size = 0;
+
+int number_err = 0;
+// current config line
+int line = 1;
+
+int verbose = 0;
+int optimize = 0;
+int opt_force = 0;
+
+char *lib_path[2] = { NULL, "/usr/share/gfxboot" };
+
+// initial vocabulary (note: "{" & "}" are special)
+#include "vocabulary.h"
+
+int main(int argc, char **argv)
+{
+ int i;
+ char *config_file = NULL, *log_file = NULL;
+ int opt_info = 0;
+
+ if(sizeof (file_header_t) != 32) {
+ fprintf(stderr, "file_header_t has wrong size: %d\n", sizeof (file_header_t));
+ wrong_struct_size();
+ return 1;
+ }
+
+ opterr = 0;
+
+ while((i = getopt_long(argc, argv, "c:fhiL:l:Ov", options, NULL)) != -1) {
+ switch(i) {
+ case 'c':
+ config_file = optarg;
+ break;
+
+ case 'f':
+ opt_force = 1;
+ break;
+
+ case 'i':
+ opt_info = 1;
+ break;
+
+ case 'l':
+ log_file = optarg;
+ break;
+
+ case 'L':
+ lib_path[0] = optarg;
+ break;
+
+ case 'O':
+ optimize = 1;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ default:
+ help();
+ return 0;
+ }
+ }
+
+ argc -= optind; argv += optind;
+
+ if(config_file && argc == 1) {
+ parse_config(config_file, log_file);
+ write_data(*argv);
+ return 0;
+ }
+
+ if(opt_info && argc == 1) {
+ show_info(*argv);
+ return 0;
+ }
+
+ help();
+
+ return 1;
+}
+
+
+void help()
+{
+ fprintf(stderr, "%s",
+ "mkbootmsg: Usage mkbootmsg [options] out_file\n"
+ " Options are:\n"
+ " -c config_file, --config config_file\n"
+ " Create a boot message file using this configuration.\n"
+ " -l log_file, --log log_file\n"
+ " Write log to this file.\n"
+ " -i, --info\n"
+ " Show info about file.\n"
+ " -L\n"
+ " Search path for file read.\n"
+ " -O\n"
+ " Optimize code.\n"
+ " -h, --help\n"
+ " Show this text.\n"
+ );
+}
+
+
+file_data_t read_file(char *name)
+{
+ file_data_t fd = { };
+ FILE *f;
+ unsigned u;
+ char *s;
+
+ if(!name) return fd;
+
+ f = fopen(name, "r");
+ if(!f) {
+ for(u = 0; u < sizeof lib_path / sizeof *lib_path; u++) {
+ if(lib_path[u]) {
+ asprintf(&s, "%s/%s", lib_path[u], name);
+ f = fopen(s, "r");
+ if(f) {
+ fd.name = s;
+ break;
+ }
+ else {
+ free(s);
+ }
+ }
+ }
+ }
+ else {
+ fd.name = strdup(name);
+ }
+
+ if(!f) { perror(name); return fd; }
+
+ if(fseek(f, 0, SEEK_END)) {
+ perror(name);
+ exit(30);
+ }
+
+ fd.size = fd.real_size = ftell(f);
+
+ if(fseek(f, 0, SEEK_SET)) {
+ perror(name);
+ exit(30);
+ }
+
+ if(fd.size) {
+ fd.ptr = fd.data = malloc(fd.size);
+ if(!fd.data) {
+ fprintf(stderr, "malloc failed\n");
+ exit(30);
+ }
+ }
+
+ if(fread(fd.data, 1, fd.size, f) != fd.size) {
+ perror(name);
+ exit(30);
+ }
+
+ fclose(f);
+
+ return fd;
+}
+
+
+int is_pcx(file_data_t *fd)
+{
+ if(!fd->data || fd->size < 0x381) return 0;
+ if(
+ fd->data[0] != 10 ||
+ fd->data[1] != 5 ||
+ fd->data[2] != 1 ||
+ fd->data[3] != 8 ||
+ fd->data[fd->size - 0x301] != 12
+ ) return 0;
+
+ return 1;
+}
+
+
+void write_data(char *name)
+{
+ FILE *f;
+ unsigned ofs;
+ file_data_t fd = {};
+
+ f = strcmp(name, "-") ? fopen(name, "w") : stdout;
+
+ if(!f) {
+ perror(name);
+ return;
+ }
+
+ // first, fix all offsets
+
+ ofs = sizeof header;
+
+ header.bincode = ofs;
+ header.bincode_size = sizeof bincode_data;
+ ofs += sizeof bincode_data;
+
+ if(dict_file.data) {
+ header.dict = ofs;
+ ofs += dict_file.size;
+ }
+
+ if(pscode.data) {
+ header.code = ofs;
+ header.code_size = pscode.size;
+ ofs += pscode.size;
+ }
+
+ // then, put everything together
+
+ add_data(&fd, &header, sizeof header);
+
+ add_data(&fd, bincode_data, sizeof bincode_data);
+
+ add_data(&fd, dict_file.data, dict_file.size);
+
+ add_data(&fd, pscode.data, pscode.size);
+
+ // now write everything
+
+ if(fwrite(fd.data, fd.size, 1, f) != 1) {
+ perror(name); exit(3);
+ }
+
+ fclose(f);
+}
+
+
+void add_data(file_data_t *d, void *buffer, unsigned size)
+{
+ ssize_t ofs = 0;
+
+ if(!size || !d || !buffer) return;
+
+ if(d->ptr && d->data) ofs = d->ptr - d->data;
+
+ if(d->size + size > d->real_size) {
+ d->real_size = d->size + size + 0x1000;
+ d->data = realloc(d->data, d->real_size);
+ if(!d->data) d->real_size = 0;
+ }
+
+ if(d->size + size <= d->real_size) {
+ memcpy(d->data + d->size, buffer, size);
+ d->size += size;
+ }
+ else {
+ fprintf(stderr, "Oops, out of memory? Aborted.\n");
+ exit(10);
+ }
+
+ if(d->ptr && d->data) d->ptr = d->data + ofs;
+}
+
+
+code_t *new_code()
+{
+ if(code_size >= code_max_size) {
+ code_max_size += 10;
+ code = realloc(code, code_max_size * sizeof * code);
+ memset(code + code_size, 0, (code_max_size - code_size) * sizeof * code);
+ }
+
+ return code + code_size++;
+}
+
+
+
+dict_t *new_dict()
+{
+ if(dict_size >= dict_max_size) {
+ dict_max_size += 10;
+ dict = realloc(dict, dict_max_size * sizeof *dict);
+ memset(dict + dict_size, 0, (dict_max_size - dict_size) * sizeof *dict);
+ }
+
+ return dict + dict_size++;
+}
+
+
+unsigned number(char *value)
+{
+ char *s;
+ unsigned u;
+
+ u = strtoul(value, &s, 0);
+
+ if(*s) {
+ fprintf(stderr, "Line %d: \"%s\" is not a number\n", line, value);
+ exit(1);
+ }
+
+ return u;
+}
+
+
+void hexdump(file_data_t *fd, unsigned ofs, int len)
+{
+ unsigned u, p;
+ char s[17];
+ char ind[] = " ";
+ int i;
+
+ if(!len || !fd) return;
+
+ if(len < 0 || ofs + len > fd->size) {
+ printf("invalid data range: %d bytes at 0x%x\n", len, ofs);
+ }
+
+ p = ofs;
+ u = ofs & ~0xf;
+
+ memset(s, ' ', 16);
+ s[16] = 0;
+
+ if(u < p) {
+ printf("%s%05x ", ind, u);
+ i = (p - u) * 3;
+ if(i > 8 * 3) i++;
+ while(i--) printf(" ");
+ }
+
+ while(p < ofs + len) {
+ s[p & 15] = (fd->data[p] >= 0x20 && fd->data[p] <= 0x7e) ? fd->data[p] : '.';
+ if(!(p & 15)) {
+ printf("%s%05x ", ind, p);
+ }
+ if(!(p & 7) && (p & 15)) printf(" ");
+ printf("%02x ", fd->data[p]);
+ if(!(++p & 15)) {
+ printf(" %s\n", s);
+ }
+ }
+
+ if(p & 15) {
+ s[p & 15] = 0;
+ if(!(p & 8)) printf(" ");
+ printf("%*s %s\n", 3 * (16 - (p & 15)), "", s);
+ }
+
+
+}
+
+
+void show_info(char *name)
+{
+ unsigned ofs = 0;
+ file_data_t fd;
+ unsigned u;
+
+ fd = read_file(name);
+
+ if(fd.size >= sizeof header) {
+ memcpy(&header, fd.data, sizeof header);
+ ofs += sizeof header;
+ }
+
+ if(header.magic_id != MAGIC) {
+ fprintf(stderr, "No mkbootmsg file.\n");
+ return;
+ }
+
+ if(header.version != VERSION) {
+ fprintf(stderr, "Version %u not supported.\n", header.version);
+ return;
+ }
+
+ if(header.bincode && header.bincode_size) {
+ printf("%u bytes ia32 code:\n", header.bincode_size);
+ if(verbose >= 2) hexdump(&fd, header.bincode, header.bincode_size);
+ printf("\n");
+ }
+
+ if(header.dict && header.code) {
+ u = header.code - header.dict;
+ printf("dictionary: %d bytes at 0x%x:\n", u, header.dict);
+ hexdump(&fd, header.dict, u);
+ printf("\n");
+ }
+
+ if(header.code && header.code_size) {
+ printf("%u bytes code:\n", header.code_size);
+ if(verbose >= 1) hexdump(&fd, header.code, header.code_size);
+ printf("\n");
+ decompile(fd.data + header.code, header.code_size);
+ printf("\n");
+ }
+}
+
+
+/*
+ * Convert hex number of excatly len bytes.
+ */
+int get_hex(char *s, int len, unsigned *val)
+{
+ unsigned u;
+ char s2[len + 1];
+
+ if(!s || !len) return 0;
+ strncpy(s2, s, len);
+ s2[len] = 0;
+
+ u = strtoul(s2, &s, 16);
+ if(!*s) {
+ if(val) *val = u;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+char *utf32_to_utf8(int u8)
+{
+ static char buf[16];
+ static iconv_t ic = (iconv_t) -1;
+ char *ibuf, *obuf;
+ size_t obuf_left, ibuf_left;
+ int i;
+
+ *buf = 0;
+
+ if(ic == (iconv_t) -1) {
+ ic = iconv_open("utf8", "utf32le");
+ if(ic == (iconv_t) -1) {
+ fprintf(stderr, "Error: can't convert utf8 data.\n");
+ exit(1);
+ }
+ }
+
+ ibuf = (char *) &u8;
+ obuf = buf;
+ ibuf_left = 4;
+ obuf_left = sizeof buf - 1;
+
+ i = iconv(ic, &ibuf, &ibuf_left, &obuf, &obuf_left);
+
+ if(i >= 0) {
+ i = sizeof buf - 1 - obuf_left;
+ buf[i] = 0;
+ }
+ else {
+ fprintf(stderr, "Warning: failed to convert 0x%x to utf8.\n", u8);
+ }
+
+ return buf;
+}
+
+
+char *next_word(char **ptr)
+{
+ char *s, *start, *utf8;
+ int is_str, is_comment;
+ static char word[1024];
+ int i, n;
+ char qc = 0;
+
+ s = *ptr;
+
+ *word = 0;
+
+ while(isspace(*s)) if(*s++ == '\n') line++;
+
+ if(!*s) {
+ *ptr = s;
+ return word;
+ }
+
+ start = s;
+
+ qc = *start;
+ is_str = qc == '"' || qc == '\'' ? 1 : 0;
+ is_comment = qc == '%' ? 1 : 0;
+
+ if(is_comment) {
+ while(*s && *s != '\n') s++;
+ }
+ else if(is_str) {
+ *word = *s++;
+ for(n = 1; n < sizeof word - 1; n++) {
+ if(!*s) break;
+ if(*s == qc) { s++; break; }
+ if(*s == '\\') {
+ s++;
+ switch(*s) {
+ case 0:
+ word[n++] = '\\';
+ break;
+
+ case 'n':
+ word[n] = '\n';
+ break;
+
+ case 't':
+ word[n] = '\t';
+ break;
+
+ case '0':
+ if(
+ s[0] >= '0' && s[0] <= '7' &&
+ s[1] >= '0' && s[1] <= '7' &&
+ s[2] >= '0' && s[2] <= '7'
+ ) {
+ word[n] = ((s[0] - '0') << 6) + ((s[1] - '0') << 3) + (s[2] - '0');
+ s += 2;
+ }
+ else {
+ word[n] = *s;
+ }
+ break;
+
+ case 'x':
+ if(get_hex(s + 1, 2, &i)) {
+ s += 2;
+ word[n] = i;
+ }
+ else {
+ word[n++] = '\\';
+ word[n] = *s;
+ }
+ break;
+
+ case 'u':
+ if(get_hex(s + 1, 4, &i)) {
+ s += 4;
+ utf8 = utf32_to_utf8(i);
+ while(*utf8) word[n++] = *utf8++;
+ n--;
+ }
+ else {
+ word[n++] = '\\';
+ word[n] = *s;
+ }
+ break;
+
+ case 'U':
+ if(get_hex(s + 1, 8, &i)) {
+ s += 8;
+ utf8 = utf32_to_utf8(i);
+ while(*utf8) word[n++] = *utf8++;
+ n--;
+ }
+ else {
+ word[n++] = '\\';
+ word[n] = *s;
+ }
+ break;
+
+ default:
+ word[n] = *s;
+ }
+ s++;
+ }
+ else {
+ word[n] = *s++;
+ }
+ }
+ word[n] = 0;
+ }
+ else {
+ while(!isspace(*s)) s++;
+ }
+
+ if(!is_str) {
+ n = s - start;
+ if(n >= sizeof word) n = sizeof word - 1;
+ strncpy(word, start, n);
+ word[n] = 0;
+ }
+
+ *ptr = s;
+
+ return word;
+}
+
+
+void parse_comment(char *comment, file_data_t *incl)
+{
+ char t[5][100];
+ int n;
+
+ n = sscanf(comment, " %99s %99s %99s %99s %99s", t[0], t[1], t[2], t[3], t[4]);
+
+ if(!n) return;
+
+ if(n == 2 && !strcmp(t[0], "include")) {
+ *incl = read_file(t[1]);
+ if(!incl->data) exit(18);
+ add_data(incl, "", 1);
+ fprintf(stderr, "Including \"%s\"\n", incl->name);
+ return;
+ }
+}
+
+
+int find_in_dict(char *name)
+{
+ int i;
+
+ for(i = 0; i < dict_size; i++) {
+ if(dict[i].name && !strcmp(name, dict[i].name)) return i;
+ }
+
+ return -1;
+}
+
+
+unsigned usize(unsigned u)
+{
+ if(u >> 24) return 4;
+ if(u >> 16) return 3;
+ if(u >> 8) return 2;
+ if(u) return 1;
+
+ return 0;
+}
+
+
+unsigned isize(int i)
+{
+ if(i == 0) return 0;
+ if(i >= -0x80 && i <= 0x7f) return 1;
+ if(i >= -0x8000 && i <= 0x7fff) return 2;
+ if(i >= -0x800000 && i <= 0x7fffff) return 3;
+
+ return 4;
+}
+
+
+int translate(int pass)
+{
+ int i;
+ code_t *c;
+ unsigned u0, u1, u2;
+ unsigned ofs = 0;
+ int changed = 0;
+
+ if(pass == 0) {
+ changed = 1;
+ for(i = 0; i < code_size; i++) {
+ c = code + i;
+
+ c->ofs = ofs;
+
+ switch(c->type) {
+ case t_skip:
+ c->size = 0;
+ break;
+
+ case t_int:
+ case t_unsigned:
+ u0 = isize(c->value.u);
+ u1 = usize(c->value.u);
+ u2 = u0;
+ if(u1 < u0) {
+ c->type = t_unsigned;
+ u2 = u1;
+ }
+ c->size = u2 + 1;
+ c->enc = malloc(c->size);
+ c->enc[0] = c->type + (u2 << 4);
+ if(u2) memcpy(c->enc + 1, &c->value.u, u2);
+ break;
+
+ case t_string:
+ u1 = strlen(c->value.p) + 1;
+ u0 = usize(u1);
+ c->size = u1 + u0 + 1;
+ c->enc = malloc(c->size);
+ c->enc[0] = c->type + (u0 << 4) + 0x80;
+ memcpy(c->enc + 1, &u1, u0);
+ memcpy(c->enc + 1 + u0, c->value.p, u1);
+ break;
+
+ case t_code:
+ c->size = 5;
+ break;
+
+ case t_ret:
+ case t_end:
+ c->size = 1;
+ c->enc = malloc(c->size);
+ c->enc[0] = c->type;
+ break;
+
+ case t_none:
+ case t_bool:
+ case t_sec:
+ case t_prim:
+ case t_dict_idx:
+ u0 = usize(c->value.u);
+ c->size = u0 + 1;
+ c->enc = malloc(c->size);
+ c->enc[0] = c->type + (u0 << 4);
+ if(u0) memcpy(c->enc + 1, &c->value.u, u0);
+ break;
+
+ default:
+ fprintf(stderr, "Internal oops %d: type %d not allowed\n", __LINE__, c->type);
+ exit(8);
+ }
+
+ ofs += c->size;
+ }
+ }
+ else {
+ for(i = 0; i < code_size; i++) {
+ c = code + i;
+
+ if(c->ofs != ofs) changed = 1;
+ c->ofs = ofs;
+
+ if(c->type == t_code) {
+ u0 = c->value.u;
+ if(u0 >= code_size) {
+ fprintf(stderr, "Internal error %d\n", __LINE__);
+ exit(11);
+ }
+ u1 = usize(code[u0].ofs);
+ if(c->size != u1 + 1) changed = 1;
+ c->size = u1 + 1;
+ if(c->enc) free(c->enc);
+ c->enc = malloc(c->size);
+ c->enc[0] = c->type + (u1 << 4);
+ if(u1) memcpy(c->enc + 1, &code[u0].ofs, u1);
+ }
+
+ ofs += c->size;
+ }
+ }
+
+ return changed;
+}
+
+
+void encode_dict()
+{
+ unsigned u;
+ int i;
+
+ if(dict_size == 0 || dict_size > 0xffff) {
+ fprintf(stderr, "Internal oops %d\n", __LINE__);
+ exit(6);
+ }
+
+ add_data(&dict_file, &dict_size, 4);
+
+ u = 0;
+
+ for(i = 0; i < dict_size; i++) {
+ if(dict[i].type == t_none || dict[i].type == t_prim) continue;
+ add_data(&dict_file, &i, 2);
+ add_data(&dict_file, &dict[i].type, 1);
+ add_data(&dict_file, &dict[i].value.u, 4);
+ u++;
+ }
+
+ dict_file.data[2] = u;
+ dict_file.data[3] = u >> 8;
+}
+
+
+void parse_config(char *name, char *log_file)
+{
+ char *word;
+ file_data_t cfg[MAX_INCLUDE];
+ file_data_t incl;
+ int i, j;
+ unsigned u;
+ dict_t *d;
+ code_t *c, *c1;
+ char *s;
+ FILE *lf = NULL;
+ int incl_level = 0;
+
+ cfg[incl_level] = read_file(name);
+ add_data(&cfg[incl_level], "", 1);
+
+ if(!cfg[incl_level].ptr || !*cfg[incl_level].ptr) {
+ fprintf(stderr, "Empty config file!\n");
+ exit(1);
+ }
+
+ if(log_file && *log_file) lf = fopen(log_file, "w");
+
+ header.magic_id = MAGIC;
+ header.version = VERSION;
+
+ // setup initial vocabulary
+ for(i = 0; i < sizeof prim_names / sizeof *prim_names; i++) {
+ d = new_dict();
+ d->type = prim_names[i].type;
+ d->value.u = prim_names[i].value;
+ d->name = prim_names[i].name;
+ }
+
+ while(*cfg[incl_level].ptr || incl_level) {
+ if(!*cfg[incl_level].ptr) {
+ incl_level--;
+ line = cfg[incl_level].line;
+ }
+ word = next_word((char **) &cfg[incl_level].ptr);
+ if(!word || !*word) continue;
+
+ if(word[0] == '%') {
+ if(word[1] == '%') {
+ incl.ptr = NULL;
+ parse_comment(word + 2, &incl);
+ if(incl.ptr) {
+ if(incl_level == MAX_INCLUDE - 1) {
+ fprintf(stderr, "Error: include level exceeded\n");
+ exit(17);
+ }
+ else {
+ cfg[incl_level].line = line;
+ cfg[++incl_level] = incl;
+ line = 1;
+ }
+ }
+ }
+ continue;
+ }
+
+ if(verbose >= 2) printf(">%s< (%d)\n", word, line);
+
+ c = new_code();
+ c->line = line;
+ c->incl_level = incl_level;
+
+ if(*word == '"') {
+ c->type = t_string;
+ c->value.p = strdup(word + 1);
+ }
+ else if(*word == '\'') {
+ c->type = t_int;
+ c->value.u = word[1];
+ asprintf(&c->name, "%s'", word);
+ }
+ else if(*word == '/') {
+ c->name = strdup(word + 1);
+
+ c->type = t_dict_idx;
+
+ if((i = find_in_dict(word + 1)) == -1) {
+ d = new_dict();
+ d->type = t_none;
+ d->value.u = 1; // mark as defined
+ d->name = strdup(word + 1);
+ c->value.u = dict_size - 1;
+ }
+ else {
+ if(dict[i].type == t_none && !dict[i].value.u) {
+ dict[i].value.u = 1; // mark as defined
+ }
+ c->value.u = i;
+ }
+ }
+ else if(!strcmp(word, "{")) {
+ c->type = t_code;
+ c->name = strdup(word);
+ }
+ else if(!strcmp(word, "}")) {
+ c->type = t_ret;
+ c->name = strdup(word);
+ for(c1 = c; c1 >= code; c1--) {
+ if(c1->type == t_code && !c1->value.u) {
+ // point _after_ "}"
+ c1->value.u = c - code + 1;
+ break;
+ }
+ }
+ if(c1 < code) {
+ fprintf(stderr, "Syntax error: no matching \"{\" for \"}\" in line %d\n", line);
+ exit(10);
+ }
+ }
+ else {
+ c->name = strdup(word);
+
+ i = find_in_dict(word);
+
+ if(i == -1) {
+ u = strtoul(word, &s, 0);
+ if(*s) {
+ d = new_dict();
+ d->type = t_none;
+ d->name = strdup(word);
+ c->type = t_sec;
+ c->value.u = dict_size - 1;
+ }
+ else {
+ c->type = t_int;
+ c->value.u = u;
+ }
+ }
+ else {
+ c->type = t_sec;
+ c->value.u = i;
+ }
+ }
+ }
+
+ // add a final 'end'
+ c = new_code();
+ c->type = t_end;
+ c->name = "end";
+
+ // check vocabulary
+ for(i = j = 0; i < dict_size; i++) {
+ if(
+ dict[i].type == t_none && !dict[i].value.u &&
+ i >= sizeof prim_names / sizeof *prim_names /* callback functions need not be defined */
+ ) {
+ if(!j) fprintf(stderr, "Undefined words:");
+ else fprintf(stderr, ",");
+ fprintf(stderr, " %s", dict[i].name);
+ j = 1;
+ }
+ }
+ if(j) {
+ fprintf(stderr, "\n");
+ if(!opt_force) exit(10);
+ }
+
+ if(optimize) {
+ if(lf) fprintf(lf, "# searching for unused code:\n");
+ for(i = 0; i < 64; i++) {
+ if(verbose && lf) fprintf(lf, "# pass %d\n", i + 1);
+ if(!optimize_code(lf)) break;
+ }
+ if(lf) fprintf(lf, "# %d optimization passes\n", i + 1);
+ if(i) {
+ if(lf) fprintf(lf, "# searching for unused dictionary entries:\n");
+ optimize_dict(lf);
+ }
+ }
+
+ // now translate to byte code
+ for(i = 0; i < 20; i++) {
+ if(!translate(i)) break;
+ }
+ if(lf) fprintf(lf, "# %d encoding passes\n", i + 1);
+ if(i == 20) {
+ fprintf(stderr, "Oops, code translation does not converge.\n");
+ exit(7);
+ }
+
+ // store it
+ for(i = 0; i < code_size; i++) {
+ if((!code[i].enc || !code[i].size) && code[i].type != t_skip) {
+ fprintf(stderr, "Internal oops %d\n", __LINE__);
+ exit(8);
+ }
+ add_data(&pscode, code[i].enc, code[i].size);
+ }
+
+ // now encode the dictionary
+ encode_dict();
+
+ log_code(lf);
+ log_dict(lf);
+
+ if(lf) fclose(lf);
+}
+
+
+/*
+ * Remove deleted dictionary entries.
+ */
+void optimize_dict(FILE *lf)
+{
+ int i;
+ int old_ofs, new_ofs;
+
+ for(old_ofs = new_ofs = 0; old_ofs < dict_size; old_ofs++) {
+ if(dict[old_ofs].del) continue;
+ if(old_ofs != new_ofs) {
+ if(verbose && lf) fprintf(lf, "# rename %d -> %d\n", old_ofs, new_ofs);
+ dict[new_ofs] = dict[old_ofs];
+ for(i = 0; i < code_size; i++) {
+ if(
+ (
+ code[i].type == t_sec ||
+ code[i].type == t_dict_idx
+ ) &&
+ code[i].value.u == old_ofs
+ ) {
+ code[i].value.u = new_ofs;
+ }
+ }
+ }
+ new_ofs++;
+ }
+ if(lf && new_ofs != old_ofs) {
+ fprintf(lf, "# new dictionary size %d (%d - %d)\n", new_ofs, old_ofs, old_ofs - new_ofs);
+ }
+
+ dict_size = new_ofs;
+}
+
+
+/*
+ * Skip deleted code.
+ */
+unsigned skip_code(unsigned pos)
+{
+ while(pos < code_size && code[pos].type == t_skip) pos++;
+
+ return pos;
+}
+
+
+/*
+ * Return next instruction.
+ */
+unsigned next_code(unsigned pos)
+{
+ if((pos + 1) >= code_size) return pos;
+
+ return skip_code(++pos);
+}
+
+
+int optimize_code(FILE *lf)
+{
+ unsigned i;
+ int changed, ind = 0;
+ code_t *c;
+
+ for(i = 0; i < dict_size; i++) {
+ dict[i].def = dict[i].def_idx =
+ dict[i].ref = dict[i].ref_idx =
+ dict[i].ref0 = dict[i].ref0_idx = 0;
+ }
+
+ for(i = 0; i < code_size; i++) {
+ c = code + i;
+
+ switch(c->type) {
+ case t_code:
+ ind++;
+ break;
+
+ case t_ret:
+ if(!ind) {
+ fprintf(stderr, "Warning: nesting error at line %d\n", c->line);
+ }
+ ind--;
+ break;
+
+ case t_sec:
+ if(c->value.u < dict_size) {
+ dict[c->value.u].ref++;
+ dict[c->value.u].ref_idx = i;
+ dict[c->value.u].ref_ind = ind;
+ if(ind == 0 && !dict[c->value.u].ref0) {
+ dict[c->value.u].ref0 = 1;
+ dict[c->value.u].ref0_idx = i;
+ }
+ }
+ break;
+
+ case t_dict_idx:
+ if(c->value.u < dict_size) {
+ dict[c->value.u].def++;
+ dict[c->value.u].def_idx = i;
+ dict[c->value.u].def_ind = ind;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ changed = 1;
+
+ optimize_code1(lf) ||
+ optimize_code2(lf) ||
+ optimize_code3(lf) ||
+ optimize_code4(lf) ||
+ optimize_code5(lf) ||
+ optimize_code6(lf) ||
+ optimize_code7(lf) ||
+ (changed = 0);
+
+ return changed;
+}
+
+
+/*
+ * Find references to primary words.
+ */
+int optimize_code1(FILE *lf)
+{
+ unsigned i, j;
+ int changed = 0;
+ code_t *c;
+
+ for(i = 0; i < dict_size; i++) {
+ if(
+ i < sizeof prim_names / sizeof *prim_names &&
+ !dict[i].del &&
+ dict[i].def == 0 &&
+ dict[i].ref &&
+ dict[i].type == t_prim
+ ) {
+ if(verbose && lf) fprintf(lf, "# replacing %s\n", dict[i].name);
+ for(j = 0; j < code_size; j++) {
+ c = code + j;
+ if(c->type == t_sec && c->value.u == i) {
+ c->type = dict[i].type;
+ c->value.u = dict[i].value.u;
+ }
+ }
+
+ changed = 1;
+ }
+ }
+
+ return changed;
+}
+
+
+/*
+ * Remove things like
+ *
+ * /foo 123 def
+ * /foo "abc" def
+ * /foo /bar def
+ *
+ * if foo is unused.
+ */
+int optimize_code2(FILE *lf)
+{
+ unsigned i, j;
+ int changed = 0;
+ code_t *c0, *c1, *c2;
+
+ for(i = 0; i < dict_size; i++) {
+ if(
+ i >= sizeof prim_names / sizeof *prim_names &&
+ !dict[i].del &&
+ !dict[i].ref &&
+ dict[i].def == 1 &&
+ dict[i].type == t_none
+ ) {
+ c0 = code + (j = dict[i].def_idx);
+ c1 = code + (j = next_code(j));
+ c2 = code + (j = next_code(j));
+
+ if(
+ c0->type == t_dict_idx &&
+ c0->value.u == i &&
+ (
+ c1->type == t_none ||
+ c1->type == t_int ||
+ c1->type == t_unsigned ||
+ c1->type == t_bool ||
+ c1->type == t_string ||
+ c1->type == t_dict_idx ||
+ c1->type == t_ptr
+ ) &&
+ c2->type == t_prim &&
+ c2->value.u == p_def
+ ) {
+ if(verbose && lf) fprintf(lf, "# defined but unused: %s (index %d)\n", dict[i].name, i);
+ if(verbose && lf) fprintf(lf, "# deleting code: %d - %d\n", dict[i].def_idx, j);
+ c0->type = c1->type = c2->type = t_skip;
+ dict[i].del = 1;
+
+ changed = 1;
+ }
+ }
+ }
+
+ return changed;
+}
+
+
+/*
+ * Remove things like
+ *
+ * /foo { ... } def
+ *
+ * if foo is unused.
+ */
+int optimize_code3(FILE *lf)
+{
+ unsigned i, j, k;
+ int changed = 0;
+ code_t *c0, *c1;
+
+ for(i = 0; i < dict_size; i++) {
+ if(
+ i >= sizeof prim_names / sizeof *prim_names &&
+ !dict[i].del &&
+ !dict[i].ref &&
+ dict[i].def == 1 &&
+ dict[i].type == t_none
+ ) {
+ c0 = code + (j = dict[i].def_idx);
+ c1 = code + next_code(j);
+
+ if(c1 == c0) continue;
+
+ if(
+ c0->type == t_dict_idx &&
+ c0->value.u == i &&
+ c1->type == t_code &&
+ code[j = skip_code(c1->value.u)].type == t_prim &&
+ code[j].value.u == p_def &&
+ j > dict[i].def_idx
+ ) {
+ if(verbose && lf) fprintf(lf, "# defined but unused: %s (index %d)\n", dict[i].name, i);
+ if(verbose && lf) fprintf(lf, "# deleting code: %d - %d\n", dict[i].def_idx, j);
+ for(k = dict[i].def_idx; k <= j; k++) code[k].type = t_skip;
+ dict[i].del = 1;
+
+ changed = 1;
+ }
+ }
+ }
+
+ return changed;
+}
+
+
+
+/*
+ * Find unused dictionary entries.
+ */
+int optimize_code4(FILE *lf)
+{
+ unsigned i;
+ int changed = 0;
+
+ for(i = 0; i < dict_size; i++) {
+ if(
+ i >= sizeof prim_names / sizeof *prim_names &&
+ !dict[i].del &&
+ !dict[i].ref &&
+ !dict[i].def
+ ) {
+ if(verbose && lf) fprintf(lf, "# unused: %s (index %d)\n", dict[i].name, i);
+
+ dict[i].del = 1;
+
+ changed = 1;
+ }
+ }
+
+ return changed;
+}
+
+
+/*
+ * Replace references to constant global vars.
+ */
+int optimize_code5(FILE *lf)
+{
+ unsigned i, j, k;
+ int changed = 0;
+ code_t *c, *c0, *c1, *c2;
+ char *s;
+
+ for(i = 0; i < dict_size; i++) {
+ if(
+ i >= sizeof prim_names / sizeof *prim_names &&
+ !dict[i].del &&
+ dict[i].def == 1 &&
+ dict[i].def_ind == 0 &&
+ (
+ !dict[i].ref0 ||
+ dict[i].ref0_idx > dict[i].def_idx
+ ) &&
+ dict[i].type == t_none
+ ) {
+ c0 = code + (j = dict[i].def_idx);
+ c1 = code + (j = next_code(j));
+ c2 = code + (j = next_code(j));
+
+ if(
+ c0->type == t_dict_idx &&
+ c0->value.u == i &&
+ (
+ c1->type == t_none ||
+ c1->type == t_int ||
+ c1->type == t_unsigned ||
+ c1->type == t_bool
+ ) &&
+ c2->type == t_prim &&
+ c2->value.u == p_def
+ ) {
+ if(verbose && lf) fprintf(lf, "# global constant: %s (index %d)\n", dict[i].name, i);
+ if(verbose && lf) fprintf(lf, "# replacing %s with %s\n", dict[i].name, c1->name);
+ for(k = 0; k < code_size; k++) {
+ c = code + k;
+ if(c->type == t_sec && c->value.u == i) {
+ c->type = c1->type;
+ c->value = c1->value;
+ if(c->type == t_int || c->type == t_unsigned) {
+ asprintf(&s, "%s # %s", c1->name, c->name);
+ free(c->name);
+ c->name = s;
+ }
+ else if(c->type == t_bool) {
+ asprintf(&s, "%s # %s", c->value.u ? "true" : "false", c->name);
+ free(c->name);
+ c->name = s;
+ }
+ else if(c->type == t_none) {
+ asprintf(&s, ".undef # %s", c->name);
+ free(c->name);
+ c->name = s;
+ }
+ }
+ }
+
+ dict[i].del = 1;
+
+ if(verbose && lf) fprintf(lf, "# deleting code: %d - %d\n", dict[i].def_idx, j);
+ c0->type = c1->type = c2->type = t_skip;
+
+ changed = 1;
+ }
+ }
+ }
+
+ return changed;
+}
+
+
+/*
+ * Find .undef.
+ */
+int optimize_code6(FILE *lf)
+{
+ unsigned i, j;
+ int changed = 0;
+ code_t *c0, *c1, *c2;
+ char *s;
+
+ for(i = 0; i < code_size; i++) {
+ c0 = code + i;
+ c1 = code + (j = next_code(i));
+ c2 = code + (j = next_code(j));
+ if(
+ c0->type == t_int && c0->value.u == 0 &&
+ c1->type == t_int && c1->value.u == 0 &&
+ c2->type == t_prim &&
+ c2->value.u == p_settype
+ ) {
+ c0->type = t_none;
+ c0->value.u = 0;
+ asprintf(&s, ".undef # %s", c0->name);
+ free(c0->name);
+ c0->name = s;
+
+ if(verbose && lf) fprintf(lf, "# constant expression: .undef (at %d)\n", i);
+ if(verbose && lf) fprintf(lf, "# deleting code: %d - %d\n", i + 1, j);
+ c1->type = c2->type = t_skip;
+
+ changed = 1;
+ }
+ }
+
+ return changed;
+}
+
+
+/*
+ * Find constant boolean expr.
+ */
+int optimize_code7(FILE *lf)
+{
+ unsigned i, j;
+ int changed = 0;
+ code_t *c0, *c1, *c2;
+ char *s;
+
+ for(i = 0; i < code_size; i++) {
+ c0 = code + i;
+ c1 = code + (j = next_code(i));
+ c2 = code + (j = next_code(j));
+ if(
+ c0->type == t_int && c0->value.u == 0 &&
+ c1->type == t_int && c1->value.u == 0 &&
+ c2->type == t_prim &&
+ (c2->value.u == p_eq || c2->value.u == p_ne)
+ ) {
+ c0->type = t_bool;
+ c0->value.u = c0->value.u == c1->value.u ? 1 : 0;
+ if(c2->value.u == p_ne) c0->value.u ^= 1;
+ asprintf(&s, "%s # %s", c0->value.u ? "true" : "false", c0->name);
+ free(c0->name);
+ c0->name = s;
+
+ if(verbose && lf) fprintf(lf, "# constant expression: %d:%d (at %d)\n", c0->type, c0->value.u, i);
+ if(verbose && lf) fprintf(lf, "# deleting code: %d - %d\n", i + 1, j);
+ c1->type = c2->type = t_skip;
+
+ changed = 1;
+ }
+ }
+
+ return changed;
+}
+
+
+void log_dict(FILE *lf)
+{
+ int i, j;
+
+ if(!lf) return;
+
+ fputc('\n', lf);
+ log_cline(lf);
+ fprintf(lf, "# dictionary: %d entries\n", dict_size);
+ log_cline(lf);
+ for(i = 0; i < dict_size; i++) {
+ fprintf(lf, "%5d%*s", i, 12 + (verbose ? 7 : 0), "");
+ fprintf(lf, "%-6s ", type_name[dict[i].type & 15]);
+ if(dict[i].type == t_string) {
+ j = fprintf(lf, "\"%s\"", dict[i].value.p);
+ }
+ else {
+ j = fprintf(lf, "0x%x", dict[i].value.u);
+ }
+ if(j > 24) j = 24;
+ fprintf(lf, "%*s", 25 - j, "");
+ fprintf(lf, "%s\n", dict[i].name ? dict[i].name : "\"\"");
+ }
+}
+
+
+void log_code(FILE *lf)
+{
+ int i, j, l, line = 0, incl_level = 0;
+ int ind = 0;
+ char *s;
+
+ if(!lf) return;
+
+ for(i = j = 0; i < code_size; i++) {
+ if(code[i].type == t_skip) j++;
+ }
+
+ fputc('\n', lf);
+ log_cline(lf);
+ fprintf(lf, "# code: %d entries (%d - %d)\n", code_size - j, code_size, j);
+ log_cline(lf);
+ for(i = 0; i < code_size; i++) {
+ if(code[i].type == t_skip && !verbose) continue;
+ if((line != code[i].line || incl_level != code[i].incl_level) && code[i].line) {
+ line = code[i].line;
+ incl_level = code[i].incl_level;
+ fprintf(lf, "%5d", line);
+ if(incl_level) {
+ fprintf(lf, " %d ", incl_level);
+ }
+ else {
+ fprintf(lf, " ");
+ }
+ }
+ else {
+ fprintf(lf, "%9s", "");
+ }
+ if(verbose) fprintf(lf, "%5d ", i);
+ if(code[i].size) {
+ fprintf(lf, "0x%04x ", code[i].ofs);
+ }
+ else {
+ fprintf(lf, "%*s", 8, "");
+ }
+ fprintf(lf, "%-6s", type_name[code[i].type & 15]);
+ l = code[i].enc ? code[i].size : 0;
+ if(l > 8) l = 8;
+ for(j = 0; j < l; j++) {
+ fprintf(lf, " %02x", code[i].enc[j]);
+ }
+ if(
+ (
+ code[i].type == t_ret ||
+ (code[i].type == t_sec && !strcmp(code[i].name, "]"))
+ ) &&
+ ind > 0
+ ) ind -= 2;
+ fprintf(lf, "%*s", 3 * (8 - l) + 2 + ind, "");
+ if(code[i].type == t_skip) fprintf(lf, "# ");
+ if(
+ code[i].type == t_code ||
+ (code[i].type == t_sec && !strcmp(code[i].name, "["))
+ ) ind += 2;
+ if(code[i].type == t_string) {
+ fprintf(lf, "\"");
+ s = code[i].value.p;
+ while(*s) {
+ if(*s >= 0 && *s < 0x20) {
+ if(*s == '\n') {
+ fprintf(lf, "\\n");
+ }
+ else if(*s == '\t') {
+ fprintf(lf, "\\t");
+ }
+ else {
+ fprintf(lf, "\\x%02x", (unsigned char) *s);
+ }
+ }
+ else {
+ fprintf(lf, "%c", *s);
+ }
+ s++;
+ }
+ fprintf(lf, "\"");
+ }
+ else {
+ fprintf(lf,
+ "%s%s",
+ code[i].type == t_dict_idx ? "/" : "",
+ code[i].name ? code[i].name : ""
+ );
+ }
+
+ // while we're here, just do a consistency check
+ if(
+ code[i].type == t_sec &&
+ (
+ !code[i].name ||
+ strcmp(code[i].name, dict[code[i].value.u].name)
+ )
+ ) {
+ fprintf(stderr, "Internal oops %d: broken dictionary\n", __LINE__);
+ exit(19);
+ }
+
+ if(code[i].enc && code[i].size > 8) {
+ for(j = 8; j < code[i].size; j++) {
+ if(j & 7) {
+ fprintf(lf, " ");
+ }
+ else {
+ fprintf(lf, "\n%*s", 24 + (verbose ? 7 : 0), "");
+ }
+ fprintf(lf, "%02x", code[i].enc[j]);
+ }
+ }
+ fprintf(lf, "\n");
+ }
+}
+
+
+void log_cline(FILE *lf)
+{
+ int i = 78;
+
+ fputc('#', lf);
+ while(i--) fputc('-', lf);
+ fputc('\n', lf);
+}
+
+
+char *add_to_line(char *s)
+{
+ static char buf[10240] = {};
+ static int ind = 0;
+ static int first = 1;
+
+ if(!s) {
+ if(first) return "";
+ return buf;
+ }
+
+ if(strlen(buf) + strlen(s) >= sizeof buf - 1) {
+ fprintf(stderr, "Oops, buffer overflow %d\n", __LINE__);
+ exit(5);
+ }
+
+ if(!strcmp(s, "{")) ind += 2;
+ if(!strcmp(s, "}")) ind -= 2;
+ if(ind < 0) ind = 0;
+
+ if(!*s) {
+ sprintf(buf, "%*s", ind, "");
+ first = 1;
+ return buf;
+ }
+
+ if(first) {
+ if(!strcmp(s, "}")) {
+ sprintf(buf, "%*s", ind, "");
+ }
+ }
+ else {
+ strcat(buf, " ");
+ }
+
+ strcat(buf, s);
+
+ first = 0;
+
+ return buf;
+}
+
+void decompile(unsigned char *data, unsigned size)
+{
+ int i, j, idx = 0;
+ unsigned u, val, uc;
+ unsigned inst_size;
+ dict_t *d;
+ unsigned type;
+ char *s, buf[1024];
+ unsigned char *p;
+
+ // setup initial vocabulary
+ for(i = 0; i < sizeof prim_names / sizeof *prim_names; i++) {
+ d = new_dict();
+ d->type = prim_names[i].type;
+ d->value.u = prim_names[i].value;
+ d->name = prim_names[i].name;
+ }
+
+ for(i = 0; i < size; i += inst_size, idx++) {
+ u = (data[i] >> 4) & 7;
+ val = 0;
+ if(u >= 1) val = data[i + 1];
+ if(u >= 2) val += data[i + 2] << 8;
+ if(u >= 3) val += data[i + 3] << 16;
+ if(u >= 4) val += data[i + 4] << 24;
+ inst_size = 1 + u;
+ if((data[i] >> 4) & 8) {
+ inst_size += val;
+ }
+
+ if(i + inst_size > size) {
+ printf("Oops: bounds exceeded: %u > %u\n", i + inst_size, size);
+ return;
+ }
+
+ if(verbose >= 1) {
+ printf("%% %04x:", i);
+ for(j = 0; j < inst_size; j++) {
+ printf(" %02x", data[i + j]);
+ }
+ printf("\n");
+ }
+
+ switch((type = data[i] & 0x0f)) {
+ case t_code:
+ s = add_to_line("{");
+ printf("%s\n", s);
+ add_to_line("");
+ break;
+
+ case t_ret:
+ s = add_to_line(NULL);
+ if(*s) printf("%s\n", s);
+ add_to_line("");
+ add_to_line("}");
+ break;
+
+ case t_end:
+ uc = *add_to_line(NULL);
+ s = add_to_line("end");
+ if(uc) {
+ printf("%s\n", s);
+ }
+ else {
+ printf("%s\n\n", s);
+ }
+ add_to_line("");
+ break;
+
+ case t_int:
+ // expand sign bit
+ switch(u) {
+ case 1:
+ if(val & 0x80) val |= ~0xff;
+ break;
+ case 2:
+ if(val & 0x8000) val |= ~0xffff;
+ break;
+ case 3:
+ if(val & 0x800000) val |= ~0xffffff;
+ break;
+ }
+
+ case t_unsigned:
+ sprintf(buf, "%d", val);
+ add_to_line(buf);
+ break;
+
+ case t_string:
+ buf[0] = '"';
+ for(j = 1, p = data + i + u + 1; *p && j < sizeof buf - 10; p++) {
+ if(*p == '\n') {
+ buf[j++] = '\\';
+ buf[j++] = 'n';
+ }
+ else if(*p < 0x20 || *p >= 0x7f) {
+ buf[j++] = '\\';
+ buf[j++] = 'x';
+ uc = *p >> 4;
+ uc += uc > 9 ? 'a' - 10 : '0';
+ buf[j++] = uc;
+ uc = *p & 0xf;
+ uc += uc > 9 ? 'a' - 10 : '0';
+ buf[j++] = uc;
+ }
+ else {
+ buf[j++] = *p;
+ }
+ }
+ buf[j++] = '"';
+ buf[j] = 0;
+ s = add_to_line(buf);
+ break;
+
+ case t_sec:
+ if(val < dict_size && dict[val].name) {
+ sprintf(buf, "%s", dict[val].name);
+ }
+ else {
+ sprintf(buf, "name_%d", val);
+ }
+ s = add_to_line(buf);
+ printf("%s\n", s);
+ add_to_line("");
+ break;
+
+ case t_dict_idx:
+ if(val < dict_size && dict[val].name) {
+ sprintf(buf, "/%s", dict[val].name);
+ }
+ else {
+ sprintf(buf, "/name_%d", val);
+ }
+ add_to_line(buf);
+ break;
+
+ default:
+ fprintf(stderr, "Oops %d: type %d not allowed\n", __LINE__, type);
+ exit(8);
+ }
+ }
+}
+
+
diff --git a/modplay.inc b/modplay.inc
new file mode 100644
index 0000000..4a5e253
--- /dev/null
+++ b/modplay.inc
@@ -0,0 +1,1141 @@
+; MOD player (c) 2002 mls
+;
+; generates samples for 11000 HZ
+; bpm always 125
+
+
+%if 0
+ call init
+ sti
+ call loadmod
+ sti
+ call play
+ sti
+ call playmod
+ sti
+ call playsamp
+ sti
+ call setvol
+ sti
+ call getvol
+ sti
+ call getstate
+ sti
+ call stop
+ sti
+%endif
+
+; pl_loadmod - configure a mod player
+; ds:si start of player
+; es:di start of mod
+; si,di must be reasonable small ;)
+pl_loadmod:
+ pushad
+ push si
+ add si, pl_state
+ xor ax, ax
+ mov cx, pl_sizeof - pl_state
+sm1: mov [si], al
+ inc si
+ loop sm1
+ pop si
+ mov [si + pl_seg], es
+ mov dx, si
+ mov cx, 4
+ push si
+ add si, pl_channs
+sm10: mov [si + ch_player], dx
+ add si, ch_sizeof
+ loop sm10
+ pop si
+ mov dx, 32
+ mov eax, [es:di + 0x438]
+ cmp eax, 'CHN4'
+ jz sm2
+ cmp eax, 'M.K.'
+ jz sm2
+ cmp eax, 'M&K!'
+ jz sm2
+ cmp eax, 'FLT4'
+ jz sm2
+ mov dl, 16
+sm2: add di, 20 + 22
+ mov [si + pl_sampinfo], di
+ sub di, 22 + 30
+ mov cx, dx
+ imul cx, 30
+ add di, cx
+ mov al, [es:di]
+ mov [si + pl_songlen], al
+ inc di
+ inc di
+ mov [si + pl_song], di
+ xor bx, bx
+ mov cx, 128
+sm5: mov al, [es:di]
+ inc di
+ cmp bl, al
+ jge sm4
+ mov bl, al
+sm4: loop sm5
+ inc bl
+ cmp dl, 32
+ jnz sm6
+ add di, 4
+sm6: mov [si + pl_patterns], di
+ mov cx, bx
+sm7: add di, 64 * 16
+ loop sm7
+ mov [si + pl_speed], byte 6
+ mov [si + pl_effpos], byte 6
+ mov [si + pl_loaded], byte 1
+ mov cx, dx
+ dec cx
+ mov dx, es
+ mov bx, di
+ mov di, [si + pl_sampinfo]
+ add si, pl_sampd + 2
+sm9: push bx
+ shr bx, 4
+ add dx, bx
+ pop bx
+ and bx, 0x000f
+ mov [si], bx
+ mov [si + 2 * 32], dx
+ mov ax, [es:di]
+ xchg al, ah
+ add bx, ax
+ adc dx, 0
+ add bx, ax
+ adc dx, 0
+ add si, 2
+ add di, 30
+ loop sm9
+ popad
+ ret
+
+; pl_play - play modfile
+; ds:si start of player
+; es:di buffer to add samples
+pl_play:
+ pushad
+ push es
+ push di
+
+ call fixvol
+
+ mov ax, [si + pl_state]
+ or ax, ax
+ jz p3
+ dec ax
+ jnz near p1
+
+ ; run effects
+ push si
+ add si, pl_channs
+ mov cx, 4
+p31: mov ax, [si + ch_effect]
+ or ax, ax
+ jz p30
+ call doeff
+ call norm
+p30: add si, ch_sizeof
+ loop p31
+ pop si
+
+ inc word [si + pl_effpos]
+ mov ax, [si + pl_effpos]
+ cmp ax, [si + pl_speed]
+ jb near p1
+
+ ; advance note
+ xor ax, ax
+ mov [si + pl_effpos], ax
+ mov bx, [si + pl_nextsongnum]
+ mov [si + pl_songnum], bx
+ mov cx, [si + pl_songlen]
+ cmp bx, cx
+ jb p2
+p3: mov [si + pl_state], ax
+ pop di
+ pop es
+ popad
+ ret
+p2: mov dx, [si + pl_nextnotenum]
+ mov [si + pl_notenum], dx
+ cmp dx, 64
+ jnb p3
+ inc dx
+ cmp dl, 64
+ jb p4
+ xor dl, dl
+ inc bx
+ cmp bx, cx
+ jb p5
+ xor bx, bx
+p5: mov [si + pl_nextsongnum], bx
+p4: mov [si + pl_nextnotenum], dx
+
+ ; interpret events for each channel
+ mov bx, [si + pl_songnum]
+ mov es, [si + pl_seg]
+ add bx, [si + pl_song]
+ mov bl, [es:bx]
+ cmp bl, 0x80
+ jb p11
+ xor bl, bl
+p11: xor bh, bh
+ shl bx, 6
+ add bx, [si + pl_notenum]
+ shl bx, 4
+ add bx, [si + pl_patterns]
+
+ mov di, [si + pl_sampinfo]
+ push si
+ add si, pl_channs
+
+ mov cx, 4
+p18: mov ah, [es:bx]
+ and ah, 0x10
+ mov al, [es:bx + 2]
+ shr al, 4
+ or al, ah
+ jz p16
+ call setsamp
+p16: mov ah, [es:bx]
+ and ah, 0x0f;
+ mov al, [es:bx + 1]
+ or ax, ax
+ jz p17
+ mov [si + ch_pitchgoal], ax
+ mov dl, [es:bx + 2]
+ inc dl
+ or dl, 0xf2
+ cmp dl, 0xf6
+ jz p17
+ mov [si + ch_pitch], ax
+ xor ax, ax
+ mov [si + ch_pointer], ax
+ mov [si + ch_pointer8], ax
+ mov ax, [si + ch_send]
+ mov [si + ch_end], ax
+p17: xor ax, ax
+ mov [si + ch_effect], ax
+ mov dl, [es:bx + 3]
+ mov al, [es:bx + 2]
+ and al, 0x0f
+ or dl, al
+ jz p29
+ push di
+ mov di, [si + ch_player]
+ mov dl, [es:bx + 3]
+ xor dh, dh
+ call effects
+ pop di
+p29: call norm
+ add si, ch_sizeof
+ add bx, 4
+ dec cx
+ jnz near p18
+ pop si
+
+ ; prepare playing of each channel
+p1: push si
+ add si, pl_channs
+ mov cx, 4
+p10: mov ax, [si + ch_end]
+ or ax, ax
+ jnz p6
+p8: mov [si + ch_start], ax
+ mov [si + ch_startseg], ax
+ jmp p7
+p6: mov ax, [si + ch_pitch]
+ or ax, ax
+ jz p8
+ mov bx, [si + ch_samp]
+ or bx, bx
+ jz p8
+ mov dx, si
+ pop si
+ push si
+ add bx, bx
+ add si, bx
+ mov bx, [si + pl_sampd]
+ mov si, [si + pl_sampdseg]
+ xchg si, dx
+ mov [si + ch_start], bx
+ mov [si + ch_startseg], dx
+ mov dx, [si + ch_finetune]
+ add dx, dx
+ jz p9
+ mov dx, [cs: fttab]
+ mul dx
+ shl ax, 1
+ mov ax, dx
+ adc ax, ax
+p9: mov bx, ax
+ mov ax, 57213
+ xor dx, dx
+ div bx
+ mov [si + ch_step], ah
+ mov [si + ch_step8], al
+p7: add si, ch_sizeof
+ loop p10
+ pop si
+
+ ; now generate 320 samples for each channel
+ pop di
+ pop es
+ add si, pl_channs
+ mov ax, 320
+p21: push ax
+ mov cx, 4
+p20: mov bx, [si + ch_startseg]
+ or bx, bx
+ jz near p22
+ push es
+ mov es, bx
+ mov bx, [si + ch_start]
+ mov ax, [si + ch_pointer]
+ add bx, ax
+ movsx dx, [es:bx]
+ shl dx, 2
+ inc ax
+ cmp ax, [si + ch_end]
+ jnb p23
+ inc bx
+ movsx ax, [es:bx]
+ push cx
+ mov cx, [si + ch_pointer8]
+ or cx, cx
+ jz p24
+ sar dx, 2
+ imul ax, cx
+ neg cl
+ imul dx, cx
+ add dx, ax
+ sar dx, 6
+p24: pop cx
+p23: pop es
+ imul dx, [si + ch_volume]
+ sar dx, 2
+ push si
+ mov si, [si + ch_player]
+ movzx eax, word [si + pl_volume]
+ pop si
+ movsx edx, dx
+ imul edx
+ sar eax, 16
+ add ax, word [es:di]
+ jno p40
+ mov ax, 32767
+ js p40
+ inc ax
+p40: mov [es:di], ax
+ mov bx, [si + ch_pointer8]
+ mov ax, [si + ch_pointer]
+ add bl, [si + ch_step8]
+ adc ax, [si + ch_step]
+ mov [si + ch_pointer8], bl
+ cmp ax, [si + ch_end]
+ jb p25
+ mov ax, [si + ch_roff]
+ mov bx, [si + ch_rend]
+ mov [si + ch_end], bx
+ or bx, bx
+ jnz p25
+ mov [si + ch_startseg], bx
+p25: mov [si + ch_pointer], ax
+p22: add si, ch_sizeof
+ dec cx
+ jnz near p20
+ add di, 2
+ sub si, ch_sizeof * 4
+ pop ax
+ dec ax
+ jnz near p21
+ sub si, pl_channs
+ mov ax, [si + pl_state]
+ dec ax
+ jz p50
+ add si, pl_channs
+ mov cx, 4
+p51: mov ax, [si + ch_startseg]
+ or ax, ax
+ jnz p50
+ add si, ch_sizeof
+ loop p51
+ sub si, ch_sizeof * 4 + pl_channs
+ mov [si + pl_state], ax
+p50: popad
+ ret
+
+fttab: dw 32768, 32532, 32298, 32066
+ dw 31835, 31606, 31378, 31153
+ dw 34716, 34466, 34219, 33972
+ dw 33728, 33485, 33244, 33005
+
+; norm - normalize channel values
+; ds:si start of chanel
+norm: push ax
+ mov ax, [si + ch_volume]
+ or ax, ax
+ jns n1
+ xor ax, ax
+n1: cmp ax, 64
+ jb n2
+ mov ax, 64
+n2: mov [si + ch_volume], ax
+ mov ax, [si + ch_pitch]
+ or ax, ax
+ jnb n3
+ xor ax, ax
+ mov [si + ch_pitch], ax
+n3: pop ax
+ ret
+
+arptab: dw 0, 61858, 58386, 55109
+ dw 52016, 49097, 46341, 43740
+ dw 41285, 38968, 36781, 34716
+ dw 32768, 30929, 29193, 27554
+
+; effects - interpret effect
+; ax effect
+; dx arg
+; ds:di start of player
+; ds:si start of chanel
+;
+; trashes ax, dx
+effects:
+ or al, al
+ jnz e1
+ mov [si + ch_arpindex], ax
+ mov ax, [si + ch_pitch]
+ mov [si + ch_arp], ax
+ push dx
+ push ax
+ shr dl, 4
+ jz e1b
+ push bx
+ mov bx, dx
+ add bl, bl
+ mov dx, [cs: arptab + bx]
+ pop bx
+ mul dx
+ mov ax, dx
+e1b: mov [si + ch_arp + 2], ax
+ pop ax
+ pop dx
+ and dl, 0x0f
+ jz e1a
+ push bx
+ mov bx, dx
+ add bl, bl
+ mov dx, [cs: arptab + bx]
+ pop bx
+ mul dx
+ mov ax, dx
+e1a: mov [si + ch_arp + 4], ax
+ mov [si + ch_effect], byte EFF_ARP
+ ret
+e1: cmp al, 1
+ jnz e2
+ neg dx
+ jmp e3
+e2: cmp al, 2
+ jnz e4
+e3: or dl, dl
+ jz e5
+ mov [si + ch_slide], dx
+e5: mov [si + ch_effect], byte EFF_SLIDE
+ ret
+e4: cmp al, 3
+ jnz e6
+ or dl, dl
+ jz e7
+ mov [si + ch_pitchrate], dx
+e7: mov [si + ch_effect], byte EFF_PORTA
+ ret
+e6: cmp al, 4
+ jnz e8
+ mov ax, dx
+ shr ax, 4
+ jz e9
+ mov [si + ch_vibrate], ax
+e9: and dl, 0x0f
+ jz e10
+ mov [si + ch_vibdepth], dx
+e10: mov [si + ch_effect], byte EFF_VIBRA
+ ret
+e8: cmp al, 5
+ jnz e11
+ mov [si + ch_effect], byte EFF_PORTASLIDE
+ jmp e12
+e11: cmp al, 6
+ jnz e13
+ mov [si + ch_effect], byte EFF_VIBRASLIDE
+ jmp e12
+e13: cmp al, 9
+ jnz e14
+ mov ax, [si + ch_samp]
+ or al, al
+ jz e15
+ xor ax, ax
+ mov [si + ch_pointer8], ax
+ mov ax, [si + ch_send]
+ mov [si + ch_end], ax
+ shl dx, 8
+ cmp dx, ax
+ jb e16
+ sub dx, ax
+ mov ax, [si + ch_rend]
+ mov [si + ch_end], ax
+ sub ax, [si + ch_roff]
+ jz e17
+e18: cmp dx, ax
+ jb e17
+ sub dx, ax
+ jmp e18
+e17: add dx, [si + ch_roff]
+e16: mov [si + ch_pointer], dx
+e15: ret
+e14: cmp al, 10
+ jnz e19
+ mov [si + ch_effect], byte EFF_SLIDEVOL
+e12: mov ax, dx
+ and dl, 0x0f
+ jz e20
+ neg dx
+ jmp e21
+e20: mov dx, ax
+ shr dl, 4
+e21: mov [si + ch_volumerate], dx
+ ret
+e19: cmp al, 11
+ jnz e22
+ mov [di + pl_nextsongnum], dx
+ xor dx, dx
+ mov [di + pl_nextnotenum], dx
+ ret
+e22: cmp al, 12
+ jnz e23
+ mov [si + ch_volume], dx
+ ret
+e23: cmp al, 13
+ jnz e24
+ mov ax, dx
+ shr al, 4
+ imul ax, 10
+ and dx, 0x0f
+ add dx, ax
+ mov [di + pl_nextnotenum], dx
+ mov dx, [di + pl_songnum]
+ inc dx
+ mov ax, [di + pl_songlen]
+ cmp dx, ax
+ jb e25
+ xor dx, dx
+e25: mov [di + pl_nextsongnum], dx
+ ret
+e24: cmp al, 15
+ jnz e27
+ cmp dl, 32
+ jnb e26
+ mov [di + pl_speed], dx
+e26: ret
+e27: cmp al, 14
+ jnz e26
+ mov al, dl
+ shr al, 4
+ and dl, 0x0f
+ cmp al, 1
+ jnz e28
+e30: add [si + ch_pitch], dx
+ ret
+e28: cmp al, 2
+ jnz e29
+ neg dx
+ jmp e30
+e29: cmp al, 5
+ jnz e31
+ mov [si + ch_finetune], dx
+ ret
+e31: cmp al, 6
+ jnz e32
+ or dl, dl
+ jnz e33
+ mov dx, [di + pl_notenum]
+ mov [di + pl_loop_notenum], dx
+ ret
+e33: mov ax, [di + pl_loop_counter]
+ or ax, ax
+ jnz e34
+ mov ax, dx
+ inc ax
+e34: dec ax
+ mov [di + pl_loop_counter], ax
+ jz e35
+ mov dx, [di + pl_loop_notenum]
+ mov [di + pl_nextnotenum], dx
+e35: ret
+e32: cmp al, 9
+ jnz e36
+ mov [si + ch_retrig], dx
+ mov [si + ch_current], dx
+ mov [si + ch_effect], byte EFF_RETRIG
+ ret
+e36: cmp al, 10
+ jnz e37
+e39: add [si + ch_volume], dx
+ ret
+e37: cmp al, 11
+ jnz e38
+ neg dx
+ jmp e39
+e38: cmp al, 12
+ jnz e40
+ mov [si + ch_retrig], dx
+ mov [si + ch_effect], byte EFF_CUT
+ ret
+e40: cmp al, 13
+ jnz e41
+ mov [si + ch_current], dx
+ mov dx, [si + ch_samp]
+ mov [si + ch_latesamp], dx
+ xor dx, dx
+ mov [si + ch_samp], dx
+ mov [si + ch_effect], byte EFF_LATESTART
+ ret
+e41: cmp al, 14
+ jnz e42
+ inc dx
+ imul dx, [di + pl_speed]
+ sub [di + pl_effpos], dx
+e42: ret
+
+vibtab: dw 0, 50, 100, 149, 196, 241, 284, 325
+ dw 362, 396, 426, 452, 473, 490, 502, 510
+ dw 512, 510, 502, 490, 473, 452, 426, 396
+ dw 362, 325, 284, 241, 196, 149, 100, 50
+ dw 0, -49, -99,-148,-195,-240,-283,-324
+ dw -361,-395,-425,-451,-472,-489,-501,-509
+ dw -511,-509,-501,-489,-472,-451,-425,-395
+ dw -361,-324,-283,-240, -195,-148,-99, -49
+
+; doeff - apply channel effect
+; ax effect
+; ds:si start of chanel
+;
+; trashes ax, bx
+doeff:
+ bt ax, 3
+ jnc d1
+ mov bx, [si + ch_volumerate]
+ add [si + ch_volume], bx
+ sub al, 8
+d1: cmp al, EFF_ARP
+ jnz d2
+ mov bx, [si + ch_arpindex]
+ inc bl
+ cmp bl, 3
+ jb d3
+ xor bl, bl
+d3: mov [si + ch_arpindex], bl
+ add bl, bl
+ mov ax, [si + ch_arp + bx]
+ mov [si + ch_pitch], ax
+ ret
+d2: cmp al, EFF_SLIDE
+ jnz d4
+ mov ax, [si + ch_slide]
+ add [si + ch_pitch], ax
+ ret
+d4: cmp al, EFF_PORTA
+ jnz d5
+ mov ax, [si + ch_pitch]
+ mov bx, [si + ch_pitchgoal]
+ cmp ax, bx
+ jnb d6
+ add ax, [si + ch_pitchrate]
+ cmp ax, bx
+ jb d7
+d8: mov ax, bx
+d7: mov [si + ch_pitch], ax
+ ret
+d6: sub ax, [si + ch_pitchrate]
+ cmp ax, bx
+ jb d8
+ jmp d7
+d5: cmp al, EFF_VIBRA
+ jnz d9
+ mov bx, [si + ch_viboffset]
+ add bx, [si + ch_vibrate]
+ and bx, 0x3f
+ mov [si + ch_viboffset], bx
+ add bx, bx
+ mov ax, [cs: vibtab + bx]
+ imul ax, [si + ch_vibdepth]
+ sar ax, 8
+ add ax, [si + ch_pitchgoal]
+ mov [si + ch_pitch], ax
+d12: ret
+d9: cmp al, EFF_RETRIG
+ jnz d10
+ dec word [si + ch_current]
+ jz d11
+ jns d12
+d11: mov ax, [si + ch_retrig]
+ mov [si + ch_current], ax
+ mov ax, [si + ch_send]
+ mov [si + ch_end], ax
+ xor ax, ax
+ mov [si + ch_pointer], ax
+ mov [si + ch_pointer8], ax
+ ret
+d10: cmp al, EFF_CUT
+ jnz d13
+ mov ax, [si + ch_retrig]
+ jz d14
+ dec word [si + ch_retrig]
+ jnz d14
+ xor ax, ax
+ mov [si + ch_volume], ax
+d14: ret
+d13: cmp al, EFF_LATESTART
+ jnz d14
+ dec word [si + ch_current]
+ jz d15
+ jns d14
+d15: call d11
+ mov [si + ch_current], ax
+ mov [si + ch_effect], ax
+ mov ax, [si + ch_latesamp]
+ mov [si + ch_samp], ax
+ ret
+
+; fixvol - fixup volume
+; ds:si start of volblock
+fixvol:
+ push ax
+ push bx
+ mov ax, [si + vo_volume]
+ mov bx, [si + vo_volumegoal]
+ cmp ax, bx
+ jz vo3
+ jnb vo1
+ add ax, [si + vo_volumerate]
+ jc vohit
+ cmp ax, bx
+ jb vo2
+vohit: mov ax, bx
+vo2: mov [si + vo_volume], ax
+vo3: pop bx
+ pop ax
+ ret
+vo1: sub ax, [si + vo_volumerate]
+ jc vohit
+ cmp ax, bx
+ jb vohit
+ jmp vo2
+
+; vo_setvol - set volume
+; ds:si start of volblock
+; ax goal
+; bx rate 0=immediate 50=one sec
+vo_setvol:
+ mov [si + vo_volumegoal], ax
+ or bx, bx
+ jnz sv1
+ mov [si + vo_volume], ax
+ mov [si + vo_volumerate], bx
+ ret
+sv1: push ax
+ xor ax, ax
+ not ax
+ push dx
+ div bx
+ pop dx
+ mov [si + vo_volumerate], ax
+ pop ax
+ ret
+
+; getvol - get volume
+; ds:si start of volblock
+vo_getvol:
+ mov ax, [si + vo_volume]
+ ret
+
+; pl_playmod - play a modfile
+; ds:si start of player
+; ax start of song
+pl_playmod:
+ cmp [si + pl_loaded], byte 1
+ jz pm0
+ ret
+pm0: xor bx, bx
+ mov [si + pl_state], bx
+ mov [si + pl_speed], byte 6
+ mov [si + pl_effpos], byte 6
+ mov [si + pl_nextsongnum], ax
+ mov [si + pl_nextnotenum], bx
+ call clearchans
+ inc bx
+ mov [si + pl_state], bx
+ ret
+
+; pl_playsamp - play a sample
+; ds:si start of player
+; ax channel number
+; bx sample number
+; cx pitch
+pl_playsamp:
+ cmp [si + pl_loaded], byte 1
+ jz ps0
+ ret
+ps0: push ax
+ mov ax, [si + pl_state]
+ dec ax
+ dec ax
+ jz ps1
+ call clearchans
+ps1: pop ax
+ pusha
+ push es
+ mov es, [si + pl_seg]
+ mov di, [si + pl_sampinfo]
+ add si, pl_channs
+ imul ax, ch_sizeof
+ add si, ax
+ xor ax, ax
+ mov [si + ch_startseg], ax
+ mov [si + ch_effect], ax
+ mov [si + ch_pointer], ax
+ mov [si + ch_pointer8], ax
+ mov [si + ch_pitch], cx
+ mov ax, bx
+ or ax, ax
+ jz ps2
+ call setsamp
+ps2: pop es
+ mov ax, [si + ch_send]
+ mov [si + ch_end], ax
+ popa
+ mov [si + pl_state], byte 2
+ ret
+
+; pl_getstate - get state of player
+; ds:si start of player
+pl_getstate:
+ mov ax, [si + pl_state]
+ ret
+
+; pl_getstate - get state of player
+; ds:si start of player
+pl_stop:
+ mov [si + pl_state], byte 0
+ ret
+
+; clearchans - stop all channels
+; si start of player
+clearchans:
+ push si
+ push cx
+ push ax
+ xor ax, ax
+ add si, pl_channs
+ mov cx, 4
+cc1: mov [si + ch_startseg], ax
+ mov [si + ch_effect], ax
+ add si, ch_sizeof
+ loop cc1
+ pop ax
+ pop cx
+ pop si
+ ret
+
+; setsamp - start a sample
+; si start of channel
+; es:di start of sampinfo
+; ax sample number
+;
+; trashes ax, dx
+setsamp:
+ xor ah, ah
+ mov [si + ch_samp], ax
+ dec ax
+ imul ax, 30
+ push bx
+ mov bx, ax
+ mov ax, [es:di + bx]
+ xchg ah, al
+ add ax, ax
+ mov [si + ch_send], ax
+ mov ax, [es:di + bx + 4]
+ xchg ah, al
+ add ax, ax
+ mov [si + ch_roff], ax
+ mov dx, [es:di + bx + 6]
+ xchg dh, dl
+ add dx, dx
+ mov [si + ch_rend], dx
+ add ax, dx
+ mov dx, [si + ch_send]
+ dec ax
+ dec ax
+ cmp ax, dx
+ jna ss13
+ shr word [si + ch_roff], 1
+ss13: mov ax, [si + ch_roff]
+ add ax, [si + ch_rend]
+ cmp dx, [si + ch_roff]
+ jnb ss14
+ss16 xor ax, ax
+ mov [si + ch_roff], ax
+ss14: cmp dx, ax
+ jnb ss15
+ mov ax, dx
+ss15: mov [si + ch_rend], ax
+ dec ax
+ dec ax
+ jz ss16
+ mov al, [es:di + bx + 2]
+ mov [si + ch_finetune], al
+ mov al, [es:di + bx + 3]
+ mov [si + ch_volume], al
+ pop bx
+ ret
+
+; the big picture: four mod players
+
+; init - initiaize everything
+; ds:si start of area
+init:
+ pushad
+ push si
+ xor ax, ax
+ mov cx, ar_sizeof
+ii1: mov [si], al
+ inc si
+ loop ii1
+ pop si
+ not ax
+ xor bx, bx
+ push si
+ add si, ar_players
+ mov cx, 4
+ii2: call vo_setvol
+ add si, pl_sizeof
+ loop ii2
+ pop si
+ add si, ar_volume
+ mov ax, 32767
+ call vo_setvol
+ popad
+ ret
+
+; setpl - get player offset
+; ax player no.
+setpl:
+ add si, ar_players
+ imul ax, pl_sizeof
+ add si, ax
+ ret
+
+; loadmod - load a mod into one of the players
+; ds:si start of area
+; es:di start of mod
+; ax player no.
+loadmod:
+ push si
+ call setpl
+ call pl_loadmod
+ pop si
+ ret
+
+; playmod - play a modfile
+; ds:si start of area
+; ax player no.
+; bx start of song
+playmod:
+ push si
+ call setpl
+ mov ax, bx
+ call pl_playmod
+ pop si
+ ret
+
+; playsamp - play a sample
+; ds:si start of area
+; ax player no.
+; bx channel number
+; cx sample number
+; dx pitch
+playsamp:
+ push si
+ call setpl
+ mov ax, bx
+ mov bx, cx
+ mov cx, dx
+ call pl_playsamp
+ pop si
+ ret
+
+; getstate - get state of player
+; ds:si start of area
+; ax player no.
+getstate:
+ push si
+ call setpl
+ call pl_getstate
+ pop si
+ ret
+
+; stop - stop a player
+; ds:si start of area
+; ax player no.
+stop:
+ push si
+ call setpl
+ call pl_stop
+ pop si
+ ret
+
+pctab:
+ db 64, 64, 64, 64, 64, 64, 64, 64
+ db 64, 64, 63, 63, 63, 63, 63, 63
+ db 63, 63, 63, 63, 63, 63, 62, 62
+ db 62, 62, 62, 62, 62, 62, 62, 62
+ db 61, 61, 61, 61, 61, 61, 61, 61
+ db 61, 60, 60, 60, 60, 60, 60, 60
+ db 60, 60, 60, 59, 59, 59, 59, 59
+ db 59, 59, 59, 59, 59, 58, 58, 58
+ db 58, 58, 58, 58, 58, 58, 58, 57
+ db 57, 57, 57, 57, 57, 57, 57, 57
+ db 57, 56, 56, 56, 56, 56, 56, 56
+ db 56, 55, 55, 55, 55, 55, 54, 54
+ db 54, 54, 53, 53, 53, 53, 52, 52
+ db 52, 51, 51, 50, 50, 49, 49, 48
+ db 48, 47, 46, 45, 44, 43, 42, 41
+ db 40, 39, 38, 37, 36, 35, 34, 33
+ db 32, 31, 30, 29, 28, 27, 26, 25
+ db 24, 23, 22, 21, 20, 19, 18, 17
+ db 17, 16, 16, 15, 15, 14, 14, 13
+ db 13, 13, 12, 12, 12, 12, 11, 11
+ db 11, 11, 10, 10, 10, 10, 10, 9
+ db 9, 9, 9, 9, 9, 9, 9, 9
+ db 8, 8, 8, 8, 8, 8, 8, 8
+ db 8, 8, 8, 8, 7, 7, 7, 7
+ db 7, 7, 7, 6, 6, 6, 6, 6
+ db 6, 6, 6, 6, 6, 6, 5, 5
+ db 5, 5, 5, 5, 5, 5, 5, 5
+ db 4, 4, 4, 4, 4, 4, 4, 4
+ db 4, 4, 3, 3, 3, 3, 3, 3
+ db 3, 3, 3, 3, 2, 2, 2, 2
+ db 2, 2, 2, 2, 2, 1, 1, 1
+ db 1, 1, 1, 1, 1, 1, 1, 1
+
+; play - generate samples
+; ds:si start of area
+play:
+ pushad
+ push es
+ push si
+ xor ax, ax
+ mov cx, ar_volume
+ap1: mov [si], al
+ inc si
+ loop ap1
+ call fixvol
+ pop si
+ push si
+ add si, ar_ssamps
+ mov di, si
+ push ds
+ pop es
+ mov cx, ar_sizeof - ar_ssamps
+ap2: mov [si], al
+ inc si
+ loop ap2
+ pop si
+ push si
+ mov cx, 4
+ xor bx, bx
+ add si, ar_players
+ap4: mov ax, [si + pl_state]
+ or ax, ax
+ jz ap3
+ call pl_play
+ mov ax, [si + pl_volume]
+ or ax, ax
+ jz ap3
+ mov bl, 1
+ap3: add si, pl_sizeof
+ loop ap4
+ pop si
+ movzx eax, word [si + ar_volume]
+ or ax, ax
+ jz ap5
+ mov [si + ar_hassamp], bl
+ mov cx, 320
+ xor bx, bx
+ap6: movsx edx, word [si + bx + ar_ssamps]
+ imul edx, eax
+
+ sar edx, 16-2
+
+ cmp edx,32767
+ jl ap7
+ mov edx,32767
+ap7:
+ cmp edx,-32768
+ jg ap8
+ mov edx,-32768
+
+ap8:
+ add dh, 128
+ push bx
+ xor bx, bx
+ mov bl, dh
+ mov dl, [cs: pctab + bx]
+ pop bx
+ mov [si + ar_samps], dl
+ inc si
+ inc bx
+ loop ap6
+ap5: pop es
+ popad
+ ret
+
+; setvol - set volume
+; ds:si start of area
+; ax player no.
+; bx goal
+; cx rate 0=immediate 50=one sec
+setvol:
+ push si
+ call setplvl
+ mov ax, bx
+ mov bx, cx
+ call vo_setvol
+ pop si
+ ret
+
+; getvol - get volume
+; ds:si start of area
+; ax player no.
+getvol:
+ push si
+ call setplvl
+ call vo_getvol
+ pop si
+ ret
+
+; setplvl - get volume offset
+; ax player no.
+setplvl:
+ or ax, ax
+ js av1
+ jmp setpl
+av1: add si, ar_volume
+ ret
+
diff --git a/modplay_defines.inc b/modplay_defines.inc
new file mode 100644
index 0000000..cb440b9
--- /dev/null
+++ b/modplay_defines.inc
@@ -0,0 +1,92 @@
+; MOD player (c) 2002 mls
+;
+; generates samples for 11000 HZ
+; bpm always 125
+
+STATE_OFF equ 0
+STATE_PLAY equ 1
+STATE_SAMPLE equ 2
+
+; struct volume
+vo_volume equ 0
+vo_volumegoal equ vo_volume + 2
+vo_volumerate equ vo_volumegoal + 2
+vo_sizeof equ vo_volumerate + 2
+
+; struct channel
+ch_samp equ 0
+ch_startseg equ ch_samp + 2
+ch_pitch equ ch_startseg + 2
+ch_finetune equ ch_pitch + 2
+ch_volume equ ch_finetune + 2
+
+ch_start equ ch_volume + 2
+ch_pointer equ ch_start + 2
+ch_pointer8 equ ch_pointer + 2
+ch_end equ ch_pointer8 + 2
+ch_send equ ch_end + 2
+ch_roff equ ch_send + 2
+ch_rend equ ch_roff + 2
+ch_step equ ch_rend + 2
+ch_step8 equ ch_step + 2
+
+ch_slide equ ch_step8 + 2
+ch_vibrate equ ch_slide + 2
+ch_viboffset equ ch_vibrate + 2
+ch_vibdepth equ ch_viboffset + 2
+ch_pitchgoal equ ch_vibdepth + 2
+ch_pitchrate equ ch_pitchgoal + 2
+ch_volumerate equ ch_pitchrate + 2
+ch_arpindex equ ch_volumerate + 2
+ch_arp equ ch_arpindex + 2
+ch_current equ ch_arp + 3 * 2
+ch_retrig equ ch_current + 2
+ch_latesamp equ ch_retrig + 2
+ch_effect equ ch_latesamp + 2
+ch_player equ ch_effect + 2
+ch_sizeof equ ch_player + 2
+
+; struct player
+pl_volume equ 0
+pl_state equ pl_volume + vo_sizeof
+pl_songlen equ pl_state + 2
+pl_speed equ pl_songlen + 2
+pl_effpos equ pl_speed + 2
+pl_nextsongnum equ pl_effpos + 2
+pl_nextnotenum equ pl_nextsongnum + 2
+pl_songnum equ pl_nextnotenum + 2
+pl_notenum equ pl_songnum + 2
+pl_loop_notenum equ pl_notenum + 2
+pl_loop_counter equ pl_loop_notenum + 2
+pl_seg equ pl_loop_counter + 2
+pl_song equ pl_seg + 2
+pl_patterns equ pl_song + 2
+pl_sampinfo equ pl_patterns + 2
+pl_sampd equ pl_sampinfo + 2
+pl_sampdseg equ pl_sampd + 2 * 32
+pl_channs equ pl_sampdseg + 2 * 32
+pl_loaded equ pl_channs + 4 * ch_sizeof
+pl_sizeof equ pl_loaded + 2
+
+EFF_ARP equ 1
+EFF_SLIDE equ 2
+EFF_PORTA equ 3
+EFF_VIBRA equ 4
+EFF_RETRIG equ 5
+EFF_CUT equ 6
+EFF_LATESTART equ 7
+EFF_SLIDEVOL equ 8
+EFF_PORTASLIDE equ 8 + 3
+EFF_VIBRASLIDE equ 8 + 4
+
+ ; _must_ be 320
+num_samples equ 320
+
+; struct area
+ar_hassamp equ 0
+ar_samps equ ar_hassamp + 1
+ar_volume equ ar_samps + num_samples + 1
+ar_players equ ar_volume + vo_sizeof
+ar_ssamps equ ar_players + pl_sizeof * 4
+ar_sizeof equ ar_ssamps + num_samples * 2
+
diff --git a/themes/SuSE/16x16.font b/themes/SuSE/16x16.font
new file mode 100644
index 0000000..5bd9fd8
--- /dev/null
+++ b/themes/SuSE/16x16.font
Binary files differ
diff --git a/themes/SuSE/Makefile b/themes/SuSE/Makefile
new file mode 100644
index 0000000..9d02750
--- /dev/null
+++ b/themes/SuSE/Makefile
@@ -0,0 +1,54 @@
+HELP2TXT = $(BINDIR)help2txt
+MKBOOTMSG = $(BINDIR)mkbootmsg
+BFLAGS = -O -v -L ../..
+INCLUDES = $(wildcard *.inc)
+HELPBOOT = help-boot.en.txt help-boot.cs.txt help-boot.sk.txt
+HELPINST = help-install.en.txt
+TRANSL = texts.en texts.cs texts.de texts.sk
+
+FILES_INST = init $(TRANSL) help.en \
+ 16x16.font kroete.data background.pcx splash.pcx
+FILES_BOOT = init $(TRANSL) help.en help.cs help.sk 16x16.font background.pcx
+
+%.txt: %.html
+ $(HELP2TXT) $< >$@
+
+.PHONY: all themes clean po
+
+all: themes
+
+po:
+ make -C po
+
+themes: boot install
+
+boot install: po
+
+boot: boot.config $(INCLUDES) $(HELPBOOT)
+ @mkdir -p $@
+ @cp -a po/texts.* .
+ $(MKBOOTMSG) $(BFLAGS) -l $@/log -c $< init
+ @cp help-$@.en.txt help.en
+ @cp help-$@.cs.txt help.cs
+ @cp help-$@.sk.txt help.sk
+ @echo $(FILES_BOOT) | sed -e 's/ /\n/g' | cpio --quiet -o >$@/message
+ @mv init help.en help.cs help.sk $@
+ @mv texts.* $@
+
+install: install.config $(INCLUDES) $(HELPINST)
+ @mkdir -p $@
+ @cp -a po/texts.* .
+ $(MKBOOTMSG) $(BFLAGS) -l $@/log -c $< init
+# @echo de >lang
+ @cp help-$@.en.txt help.en
+# @cp help-$@.de.txt help.de
+ @echo $(FILES_INST) | sed -e 's/ /\n/g' | cpio --quiet -o >$@/bootlogo
+ @mv init help.en $@
+ @mv texts.* $@
+# @rm -f lang
+
+clean:
+ make -C po clean
+ rm -f *.txt *~
+ rm -rf boot install
+
diff --git a/themes/SuSE/background.pcx b/themes/SuSE/background.pcx
new file mode 100644
index 0000000..7c72530
--- /dev/null
+++ b/themes/SuSE/background.pcx
Binary files differ
diff --git a/themes/SuSE/boot.config b/themes/SuSE/boot.config
new file mode 100644
index 0000000..9897c06
--- /dev/null
+++ b/themes/SuSE/boot.config
@@ -0,0 +1,26 @@
+%% include system.inc
+
+% no splash
+/bsplash.show { } def
+/bsplash.done { } def
+
+%% include common.inc
+
+%% include po/text.inc
+%% include window.inc
+%% include button.inc
+%% include help.inc
+%% include main.inc
+%% include xmenu.inc
+%% include dia_video.inc
+%% include dia_splash.inc
+%% include dia_lang.inc
+%% include dia_dud.inc
+%% include dia_help.inc
+%% include dia_profile.inc
+%% include dia_install.inc
+%% include panel.inc
+%% include keytables.inc
+%% include locale.inc
+
+
diff --git a/themes/SuSE/bsplash.inc b/themes/SuSE/bsplash.inc
new file mode 100644
index 0000000..2f1f4da
--- /dev/null
+++ b/themes/SuSE/bsplash.inc
@@ -0,0 +1,95 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Boot loader splash code.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Some global vars.
+
+% Boot loader splash areas to uncover.
+%
+/bsplash.areas [
+ [ 0 130 640 220 true ]
+ [ 20 20 50 100 false ]
+ [ 120 30 150 30 false ]
+ [ 330 80 140 30 false ]
+ [ 420 20 170 30 false ]
+ [ 30 420 110 40 false ]
+ [ 130 370 160 40 false ]
+ [ 310 440 160 30 false ]
+ [ 470 380 140 60 false ]
+] def
+
+% start value
+/rand.start time def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Generate pseudo random number.
+% Good enough for boot loader splash screen.
+%
+% ( ) ==> ( int )
+%
+/rand {
+ rand.start 59 mul 97 add 0x7fffffff and
+ /rand.start over def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show boot loader splash.
+%
+% ( ) ==> ( )
+%
+/bsplash.show {
+ currentimage
+
+ "splash.pcx" findfile setimage loadpalette
+ /max_image_colors max_image_colors image.colors max def
+
+% 7 0xffffff setpalette
+% 0 0 moveto 0 0 image.size image
+
+ % center image
+ image.size screen.size exch 4 -1 roll sub 2 div 3 1 roll exch sub 2 div
+ /bsplash.y exch def
+ /bsplash.x exch def
+
+ bsplash.areas 0 get
+ dup 0 get over 1 get moveto currentpoint bsplash.x bsplash.y rmoveto
+ 2 index 2 get 3 index 3 get 5 -1 roll pop image
+ 500000 usleep
+
+ {
+ bsplash.areas rand over length mod get
+ dup 4 get {
+ pop
+ } {
+ dup 0 get over 1 get moveto currentpoint bsplash.x bsplash.y rmoveto
+ 2 index 2 get 3 index 3 get 5 -1 roll 4 true put image
+ 50000 usleep
+ } ifelse
+
+ true
+ 0 1 bsplash.areas length 1 sub {
+ bsplash.areas exch get 4 get and
+ } for
+ { exit } if
+ } loop
+
+ setimage
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Just wait.
+%
+% ( ) ==> ( )
+%
+/bsplash.done {
+ 3000000 usleep
+} def
+
+
diff --git a/themes/SuSE/button.inc b/themes/SuSE/button.inc
new file mode 100644
index 0000000..3f88054
--- /dev/null
+++ b/themes/SuSE/button.inc
@@ -0,0 +1,116 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% button handling
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Button templates.
+%
+% [ x y width height label selected hotkey action ]
+%
+/button.ok { [ 0 0 85 25 txt_ok false 0 0 ] } def
+/button.cancel { [ 0 0 85 25 txt_cancel false keyEsc 0 ] } def
+/button.reboot { [ 0 0 85 25 txt_reboot false 0 0 ] } def
+/button.continue { [ 0 0 85 25 txt_continue false 0 0 ] } def
+/button.eject { [ 0 0 85 25 "Eject" false 0 0 ] } def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Set default button.
+%
+% ( button ) => ( button )
+%
+/button.default {
+ dup 5 true put
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Make it _not_ the default button.
+%
+% ( button ) => ( button )
+%
+/button.notdefault {
+ dup 5 false put
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Set button position.
+%
+% ( button x y ) ==> ( button )
+%
+/button.moveto {
+ rot dup 0 5 -1 roll put exch over 1 rot put
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Assign action to button.
+%
+% ( button action ) => ( button )
+%
+/button.setaction {
+ over 7 rot put
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Draw button.
+%
+% ( button ) ==> ( )
+%
+/button.show {
+ /bt.x over 0 get def
+ /bt.y over 1 get def
+ /bt.width over 2 get def
+ /bt.height over 3 get def
+ /bt.text over 4 get def
+ /bt.default exch 5 get def
+
+ bt.text strsize
+ bt.height sub neg 2 div /bt.y.textofs exch def
+ bt.width sub neg 2 div /bt.x.textofs exch def
+
+ bt.x bt.y moveto
+ currentpoint currentpoint currentpoint
+
+ currentpoint bt.width bt.height window.current .color.bg get setcolor fillrect moveto
+
+ bt.default {
+ black black
+ } {
+ window.current .color.bg get dup
+ } ifelse
+ bt.width bt.height drawborder
+ moveto 1 1 rmoveto white black bt.width 2 sub bt.height 2 sub drawborder
+ moveto
+ % 2 2 rmoveto white black bt.width 4 sub bt.height 4 sub drawborder
+
+ window.current .color.fg get setcolor
+ moveto bt.x.textofs bt.y.textofs rmoveto bt.text show
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Press button.
+%
+% ( button ) ==> ( )
+%
+/button.press {
+ /bt.x over 0 get def
+ /bt.y over 1 get def
+ /bt.width over 2 get def
+ /bt.height exch 3 get def
+
+ bt.x 3 add bt.y 3 add moveto
+ bt.width 7 sub bt.height 7 sub savescreen
+ 1 1 rmoveto dup restorescreen free
+
+ bt.x 1 add bt.y 1 add moveto black white bt.width 2 sub bt.height 2 sub drawborder
+ % bt.x 2 add bt.y 2 add moveto black white bt.width 4 sub bt.height 4 sub drawborder
+} def
+
+
diff --git a/themes/SuSE/common.inc b/themes/SuSE/common.inc
new file mode 100644
index 0000000..d3d85a6
--- /dev/null
+++ b/themes/SuSE/common.inc
@@ -0,0 +1,1282 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Main part.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% input event handling
+%
+% ( key ) ==> ( input_buffer menu_entry 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.buf buildcmdline 2 return } if
+
+ debug 4 ge {
+ % print keycode somewhere
+ -1 settransparentcolor
+ black setcolor
+ 500 0 moveto dup print " " print
+ } if
+
+ dup 0xff00 and 16 shl over 0xff and dup 0xe0 eq { pop 0 } if add /key exch def
+ 16 shr 0xffff and /keystat exch def
+
+ key
+
+ config.keymap { mapkey } if
+
+ dup 0xffffff and dup { exch } if pop
+
+ % for tests
+ dup keyShiftF1 eq { pop 0x00e4 } if
+ dup keyShiftF2 eq { pop 0x16d6 } if
+ dup keyShiftF3 eq { pop 0x8db3 } if
+
+ debug 4 ge {
+ % print mapped key somewhere
+ -1 settransparentcolor
+ black setcolor
+ 500 20 moveto dup print " " print
+ } if
+
+ % some special keys
+ debug.input
+
+ % put key through normal input queue
+ window.input
+
+ pop
+
+ window.action actExit eq {
+ /window.action actNothing def
+ "" -1 1 return
+ } if
+
+ window.action actCloseInfo eq {
+ /window.action actNothing def
+ "" -1 3 return
+ } if
+
+ window.action actPassword eq {
+ /window.action actNothing def
+ password.buf -1 3 return
+ } if
+
+ window.action actStart eq {
+ /window.action actNothing def
+ boot.buf buildcmdline 2 return
+ } if
+
+ window.action actRedraw eq {
+ /window.action actNothing def
+ main.redraw
+ } if
+
+ window.action actRedrawPanel eq {
+ /window.action actNothing def
+ panel.show
+ } if
+
+ window.action actInstallOK eq {
+ /window.action actNothing def
+ install.ok
+ } if
+
+ window.action actInstallCancel eq {
+ /window.action actNothing def
+ install.cancel
+ } if
+
+ boot.buf menu.entry 0
+} def
+
+
+/bc.cmd 256 string def
+
+% ( option_string ) ==> ( cmdline menu_entry )
+%
+% grub:
+% just return
+%
+% syslinux & lilo:
+% check if the commmand line starts with the current kernel name or
+% "linux"; if not, put the kernel name in front of the command line. (This
+% is to keep compatibility with the old scheme requiring the user to write
+% the kernel name explicitly.)
+%
+/buildcmdline {
+ menu.entry 0 lt { -1 return } if
+ menu.entry menu.texts length ge { -1 return } if
+
+ /bc.opts exch def
+ /bc.kernel menu.texts menu.entry get def
+
+ grub {
+
+ /bc.addkernel false def
+
+ } {
+
+ /bc.addkernel true def
+
+ [ bc.kernel "linux" ] 0 over length 1 sub 1 exch {
+ over exch get
+
+ bc.opts over eq {
+ /bc.addkernel false def
+ } {
+ bc.opts over strstr 1 eq {
+ bc.opts over length get ' ' eq {
+ /bc.addkernel false def
+ } if
+ } if
+ } ifelse
+
+ pop
+
+ bc.addkernel not { exit } if
+
+ } for
+
+ pop
+
+ % special case: option is identical to label
+ bc.kernel "apic" eq { /bc.addkernel true def } if
+
+ } ifelse
+
+ bc.addkernel {
+ alt.kernel "" ne { alt.kernel } { bc.kernel } ifelse
+ "%s " bc.cmd sprintf
+ } {
+ bc.cmd 0 0 put
+ } ifelse
+
+ cmdline.hidden "" ne {
+ cmdline.hidden "%s " bc.cmd dup length add sprintf
+ } if
+
+ syslinux {
+ xmenu.video 0 get 0 eq {
+ "textmode=1 " bc.cmd dup length add sprintf
+ } if
+ video.modes.list xmenu.video 0 get get 0 get dup {
+ "vga=0x%x " bc.cmd dup length add sprintf
+ } {
+ pop
+ } ifelse
+ } if
+
+ do_driverupdate {
+ "dud=1 " bc.cmd dup length add sprintf
+ } if
+
+ % add splash only if an entry already exists
+ bc.cmd "splash" bootopt.find dup .undef ne {
+ % remove existing entry
+ dup skipnonspaces skipspaces strcpy pop
+
+ % append new entry
+ xmenu.splash .xm_current get splash.options exch get
+ "%s " bc.cmd dup length add sprintf
+ } {
+ pop
+ } ifelse
+
+ xmenu.profile {
+ profile.options xmenu.profile .xm_current get get dup "" ne {
+ "%s " bc.cmd dup length add sprintf
+ } { pop } ifelse
+ } if
+
+ xmenu.install {
+ install.option "" ne {
+ install.option "%s " bc.cmd dup length add sprintf
+ } if
+ } if
+
+ bc.opts "%s " bc.cmd dup length add sprintf
+
+ bc.cmd dropspaces
+
+ debug 3 ge {
+ 0 0 moveto black setcolor
+ bc.cmd print "<< (press ESC) " print trace
+ } if
+
+ bc.cmd menu.entry
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% ( menu_entries_array cmdline_args_array defaultentry ) == > ( )
+/MenuInit {
+ bsplash.done
+
+ 0 setcolor 0 0 moveto screen.size fillrect loadpalette
+ init
+
+ /menu.entry -1 def
+
+ /menu.dentry exch def
+ /menu.args exch def
+ /menu.texts exch def
+
+ window.main
+ dup window.init
+ window.show
+
+% fadein_logo
+
+ syslinux usernote 0 ne and {
+ dvd_popup
+ } if
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Setup boot option input field.
+%
+% ( ) == > ( )
+%
+/bootoptions.init {
+ window.current .color.fg get setcolor
+ window.current .ed.font get setfont
+ boot.ed edit.hidecursor
+ menu.args menu.entry get
+ menu.texts menu.entry get
+ bootpromptmap
+ dup
+ boot.ed exch edit.init
+ "" ne { boot.ed ' ' edit.input } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Split command line into hidden and normal part.
+%
+% ( cmdline_args menu_text ) == > ( new_cmdline_args )
+%
+% alt.kernel is set if a different kernel should be used (this feature should
+% no longer be needed).
+%
+/bootpromptmap {
+ /alt.kernel "" def
+
+% syslinux {
+% dup "apic" eq { pop pop "apic" /alt.kernel "linux" def return } if
+% } if
+ pop
+
+ /cmdline exch def
+
+ cmdline "showopts" getoption
+ dup "" eq {
+ cmdline.shown 0 0 put
+ pop cmdline "%s" 256 cmdline.shown snprintf
+ cmdline.hidden 0 0 put
+ } {
+ "showopts" length add skipspaces
+ "%s" 256 cmdline.shown snprintf
+ cmdline "%s" 256 cmdline.hidden snprintf
+ cmdline.hidden "showopts" getoption 0 0 put
+ } ifelse
+
+ cmdline.shown dropspaces
+ cmdline.hidden dropspaces
+
+ cmdline.shown
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Skip leading non-spaces.
+%
+% ( string ) ==> ( string )
+%
+/skipnonspaces {
+ { dup 0 get dup 0 ne exch ' ' ne and { 1 add } { exit } ifelse } loop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Skip leading spaces.
+%
+% ( string ) ==> ( string )
+%
+/skipspaces {
+ { dup 0 get ' ' eq { 1 add } { exit } ifelse } loop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Drop spaces at string end.
+% Modifies string!
+%
+% ( string ) ==> ( )
+%
+/dropspaces {
+ dup length
+ dup 0 eq {
+ pop pop
+ } {
+ 1 sub
+ -1 0 {
+ over over get ' ' eq { over exch 0 put } { pop exit } ifelse
+ } for
+ pop
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Test if string[ofs-1]/string[ofs] is a word boundary.
+%
+% ( string ofs ) ==> ( true|false )
+%
+% boundary is either space/non-space or non-space/(space|'=')
+%
+/iswordboundary {
+ dup 0 eq { pop pop true return } if
+
+ add dup 1 sub 0 get exch 0 get
+
+ over ' ' eq over ' ' gt and { pop pop true return } if
+ over ' ' gt over dup ' ' eq exch dup '=' eq exch 0 eq or or and { pop pop true return } if
+
+ pop pop false
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Get boot option.
+%
+% ( cmdline option_name ) ==> ( option_start )
+%
+/getoption {
+ /go.name exch def
+ /go.cmdline exch def
+ /go.pos 0 def
+ {
+ go.cmdline go.pos add go.name strstr dup {
+ 1 sub /go.pos exch def
+
+ go.cmdline go.pos iswordboundary
+ go.cmdline go.pos go.name length add iswordboundary
+ and {
+ go.cmdline go.pos add exit
+ } {
+ /go.pos go.pos 1 add def
+ } ifelse
+ } {
+ pop "" exit
+ } ifelse
+ } loop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+/redrawmenu {
+ menu.visible.entries menu.texts length lt menu.scrollbar and {
+ /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
+
+ lightgray 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 currentpoint 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
+ currentfont exch font.large setfont show setfont
+ /y y menu.item.height add def
+ } for
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% ( entry status ) ==> ( )
+%
+% status:
+% false not selected
+% true 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
+
+ currentpoint
+ menu.status {
+ menu.bar.color
+ setcolor menu.bar.width menu.bar.height fillrect
+ } {
+ currentpoint menu.bar.width menu.bar.height image
+ } ifelse
+ moveto
+
+ menu.text.xofs menu.text.yofs rmoveto
+ menu.status {
+ menu.text.select
+ } {
+ menu.text.normal
+ } ifelse
+ setcolor
+ menu.texts menu.idx get menuitemmap
+ currentfont exch font.large setfont show setfont
+
+ menu.status {
+ % init boot options
+ keepbootoptions .undef eq { bootoptions.init } if
+
+ % set help context
+ "main" help.setcontext
+ menu.texts menu.idx get
+ dup help.findpage "" eq {
+ pop
+ } {
+ help.setcontext
+ } ifelse
+ } if
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% ( text errorcode ) ==> ( )
+% errorcode:
+% 0 normal info
+% 1 fatal error
+% 2 missing kernel
+% 3 disk change
+% 4 disk change failed
+%
+
+/info.tmpmsg 127 string def
+
+/InfoBoxInit {
+ /info.type exch def
+ /info.msg exch def
+
+ window.dialog
+
+ info.type 1 eq {
+ dup .title.bg red put
+ dup .title txt_error_title put
+ dup .buttons
+ [
+ button.reboot button.default actCloseInfo button.setaction
+ ] put
+ } {
+ dup .title txt_info_title put
+ dup .buttons
+ [
+ button.ok button.default actCloseInfo button.setaction
+% button.cancel button.notdefault actCloseInfo button.setaction
+ ] put
+ } ifelse
+
+ syslinux
+ info.type 2 eq and
+ usernote 0 ne and {
+ txt_dvd_warning info.msg
+ over length info.msg length 1 add add "%s%s" exch
+ dup string dup /info.msg exch def snprintf
+ } if
+
+ syslinux info.type 3 eq and {
+ dup .title txt_change_disk_title put
+ 0 getinfo 1 add txt_insert_disk info.tmpmsg sprintf
+ /info.msg info.tmpmsg def
+ } if
+
+ syslinux info.type 4 eq and {
+ dup .title txt_change_disk_title put
+ 1 getinfo 15 not and {
+ 0 getinfo 1 add
+ txt_insert_disk3 info.tmpmsg sprintf
+ } {
+ 0 getinfo 1 add 1 getinfo 1 add
+ txt_insert_disk2 info.tmpmsg sprintf
+ } ifelse
+ /info.msg info.tmpmsg def
+ } if
+
+ dup .text info.msg put
+
+ dup window.init
+ window.show
+
+} def
+
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+% progress bar code
+
+
+% Show percentage of progress bar.
+%
+% ( percentage ) ==> ( )
+%
+/progress.percent {
+ 0 max 100 min % so people don't ask silly questions...
+ "100%" strsize over neg progress.text.x add progress.text.y moveto
+ window.current .color.bg get setcolor
+ fillrect
+
+ "%3u%%" 8 dup string dup 5 1 roll snprintf
+
+ dup strsize pop neg progress.text.x add progress.text.y moveto
+ window.current .color.fg get setcolor
+ dup show
+ free
+
+} def
+
+
+% Show n-th progress bar symbol.
+%
+% ( n ) ==> ( )
+%
+/progress.sym.show {
+ /progress.sym.current exch def
+
+ progress.bar.x progress.bar.y moveto
+ progress.sym.width progress.sym.current 1 sub mul 1 add 1 rmoveto
+ progress.sym.width 2 sub
+ progress.bar.height 2 sub
+ loading_color setcolor
+ fillrect
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% ( kernel_name ) ==> ( )
+/ProgressInit {
+ /progress.kname exch def
+
+ boot.ed edit.hidecursor
+
+ /dia window.dialog def
+
+ dia .width.min 330 put
+ dia .position 10 put
+
+ dia .title txt_load_kernel_title put
+ dia .text
+ progress.kname "memtest" eq {
+ txt_load_memtest
+ } {
+ txt_load_kernel
+ } ifelse
+ put
+
+ dia window.init
+ dia window.show
+
+ % now add progress bar
+
+ dia .x get dia .y get moveto
+ dia .text.x get dia .text.y get 28 add rmoveto
+
+ /progress.bar.height 19 def
+ /progress.bar.width dia .width get 60 sub def
+
+ /progress.sym.width 10 def
+ /progress.bar.width
+ progress.bar.width progress.sym.width div
+ /progress.syms over def progress.sym.width mul
+ def
+
+ currentpoint over 1 sub over 2 sub moveto
+ black white progress.bar.width 2 add progress.bar.height 4 add drawborder
+
+ /progress.bar.y exch def
+ /progress.bar.x exch def
+
+ /progress.text.x progress.bar.x progress.bar.width 37 add add def
+ /progress.text.y progress.bar.y progress.bar.height fontheight sub 2 div add def
+
+ /progress.sym.current 0 def
+
+ 0 progress.percent
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% ( ) ==> ( )
+/ProgressDone {
+ window.done
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% ( max current ) ==> ( )
+/ProgressUpdate {
+ over over 100 mul exch 1 max div progress.percent
+
+ progress.syms mul progress.syms 2 div add exch 1 max div
+
+ 0 max progress.syms min
+
+ dup progress.sym.current gt {
+ progress.sym.current 1 add over 1 exch {
+ progress.sym.show
+ } for
+ } if
+ pop
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% ( timeout time ) ==> ( )
+/Timeout {
+ % first time
+ timeout.time .undef eq { timeout.init } if
+
+ dup /timeout.time exch def
+
+ over sub neg timeout.symbols mul exch div
+
+ dup timeout.current eq { pop return } if
+
+ /timeout.last timeout.current def
+ /timeout.current exch def
+
+ timeout.current timeout.symbols ge {
+ timeout.x timeout.time.y moveto
+ currentpoint timeout.dx timeout.symbols mul fontheight image
+ 0 1 timeout.symbols 1 sub {
+ timeout.clear { 2 } { 1 } ifelse drawtsymbol
+ } for
+ } {
+ timeout.time.x timeout.time.y moveto
+ currentpoint currentpoint 100 fontheight image
+ moveto
+ white setcolor
+ timeout.time 10 mul 150 add 182 div "%ds" 64 timeout.buf snprintf timeout.buf show
+ timeout.last 1 timeout.current {
+ 1 sub dup 0 ge {
+ 1 drawtsymbol
+ } if
+ } for
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% draw a timeout symbol
+% ( index status ) ==> ()
+%
+% status: 0: init, 1: clear, 2: set
+%
+/drawtsymbol {
+ /timeout.status exch def
+ dup timeout.dx mul timeout.x add exch
+ timeout.dy mul timeout.y add
+ moveto currentpoint
+ timeout.status 2 eq {
+ currentpoint timeout.size image
+ } {
+ timeout.status 0 eq {
+ pop pop
+ } {
+ 0 462 timeout.size image
+ } ifelse
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% ( time ) ==> ( )
+% /Timer { pop } def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% ( label correct_password ) ==> ( )
+%
+/PasswordInit {
+ /password.key exch def pop
+
+ /dia window.dialog def
+
+ dia .title txt_password_title put
+ dia .text txt_password put
+ dia .buttons
+ [ button.ok button.default actPassword button.setaction ]
+ put
+
+ dia window.init
+ dia window.show
+
+ % add input field
+
+ % show only '*'
+ % dia .ed.font dia .font get 0x80 or put
+
+ dia .x get dia .y get moveto
+ dia .text.x get dia .text.y get 30 add rmoveto
+
+ /password.ed.width dia .width get 20 sub def
+ /password.ed.height dia .ed.font get setfont fontheight 2 add def
+
+ currentpoint over 1 sub over 2 sub moveto
+ black white password.ed.width password.ed.height 4 add drawborder
+ moveto
+
+ black setcolor
+
+ dia .ed [
+ currentpoint
+ password.ed.width password.ed.height savescreen
+ password.buf
+ password.buf.size
+ 0
+ 0
+ 0
+ ] put
+
+ dia .ed get "" edit.init
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% ( password ) ==> ( error )
+%
+% error:
+% true password ok
+% false wrong password
+%
+% ****** FIXME: test result seems to be unused
+%
+/PasswordDone {
+
+ password.key eq
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% ( text ) == > ( new_text )
+/menuitemmap {
+ dup "memtest" eq over "memtest86" eq or { pop txt_memtest return } if
+ syslinux {
+ dup "linux" eq { pop txt_install return } if
+ dup "failsafe" eq { pop txt_safe_install return } if
+ dup "noacpi" eq { pop txt_noacpi_install return } if
+ dup "manual" eq { pop txt_manual_install return } if
+ dup "rescue" eq { pop txt_rescue return } if
+ dup "hwcheck" eq { pop "Hardware Check" return } if
+ dup "harddisk" eq { pop txt_boot_harddisk return } if
+ dup "eval" eq { pop "LiveEval" return } if
+ } {
+ dup "linux" eq { pop "Linux" return } if
+ dup "failsafe" eq { pop txt_safe_linux return } if
+ dup "windows" eq { pop "Windows" return } if
+ } ifelse
+} 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
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% ( color0 color1 color2 width height ) ==> ( )
+% draw frame with shadow
+% color0: upper left, color1: lower right, color2: shadow
+/drawborder3 {
+ 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.col2 exch 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
+
+ db.col2 -1 ne {
+ db.col2 setcolor
+ 1 1 rmoveto
+ db.x1 1 add db.y1 1 add lineto
+ db.x1 1 add db.y0 1 add lineto
+ } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% center text
+% ( text width height ) ==> ( )
+/centertext {
+ 3 -1 roll strsize
+ 4 2 roll
+ 4 1 roll exch 4 1 roll sub 2 div neg 3 1 roll sub 2 div neg
+} def
+
+
+/fadeout_logo {
+ /cols 256 malloc def
+
+ 0 1 255 { cols exch 0 put } for
+
+ 10 1 150 {
+ 10 1 100 {
+ over exch moveto getpixel
+ cols exch 1 put
+ } for
+ pop
+ } for
+ cols 10 10 moveto getpixel 0 fade
+} def
+
+/fadein_logo {
+ cols 10 10 moveto getpixel fadein
+} def
+
+
+% Allocate and define a new color.
+%
+% ( palette ) ==> ( color )
+%
+/newcolor {
+ colorbits 8 le {
+ newcolor.count .undef eq { /newcolor.count 0 def } if
+ max_image_colors newcolor.count add
+ dup rot setpalette
+ /newcolor.count newcolor.count 1 add def
+ } if
+ def
+} def
+
+
+/init {
+ 0 0 moveto currentpoint clip.size image
+
+ % set default language
+ "lang" findfile dup {
+ /tmp over length 1 add string def
+ tmp exch {
+ dup ' ' eq over '\n' eq or { pop pop exit } if
+ over exch 0 exch put
+ 1 add
+ } forall
+ tmp setlang pop
+ } {
+ pop
+ "en" setlang pop
+ } ifelse
+
+ font.large setfont
+
+ /menu.text.xofs 10 def
+ /menu.text.yofs 2 def
+ /menu.item.height fontheight dup 3 div add def
+ /menu.bar.height fontheight menu.text.yofs dup add add def
+
+ font.normal setfont
+
+ /menu.text.normal white def
+ /menu.text.select white def
+ /boot.text.options white def
+ /boot.text.normal white def
+ /infobox.bg lightgray def
+ /infobox.text.normal black def
+ /frame.darkcolor grayb5 def
+ /frame.lightcolor graye8 def
+ /frame.shadowcolor mediumblue def
+
+ /menu.bar.color fn_color def
+
+ /frame1.pos { 160 100 } def
+ /frame1.size { 320 195 } def
+ /frame2.pos { 10 410 } def
+ /frame2.size { 620 25 } def
+ /frame3.pos { 10 386 } def
+ /frame3.size { 124 25 } def
+ /frame4.pos { 560 62 } def
+ /frame4.size { 22 264 } def
+
+ /menu.start.x frame1.pos pop 10 add def
+ /menu.start.y frame1.pos exch pop 12 add def
+
+ /menu.bar.width frame1.size pop 20 sub def
+ /menu.max.entries 8 def
+ /menu.scrollbar false def
+
+ /boot.buf.size 256 def
+ /boot.buf boot.buf.size string def
+
+ /ms.size { 22 22 } def
+ /ms.up { 0 480 } def
+ /ms.down { 23 480 } def
+
+ % password buffer
+ /password.buf.size 32 def
+ /password.buf password.buf.size string def
+
+ /update.text txt_dud_ready def
+ /update.pos { 260 383 } def
+
+ frame1.pos moveto prog_frame_color dup prog_frame_color2 frame1.size drawborder3
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Some special debug & test keys.
+%
+% ( key_in ) ==> ( key_out )
+%
+/debug.input {
+% dup keyShiftF4 eq {
+% 0 0 moveto
+% 16 string dup dup "1234" ">%s<" 2 index sprintf show free
+% pop 0
+% } if
+
+ dup keyF7 eq syslinux and {
+ "kroete.data" findfile kroete.dir idle
+ /kroete.dir kroete.dir 1 xor def
+ pop 0
+ } if
+
+ dup keyF8 eq syslinux and {
+ .undef 0 idle
+ pop 0
+ } if
+
+ dup keyShiftF3 eq syslinux and debug 3 ge and {
+ currentcolor black setcolor
+ currentpoint 0 0 moveto
+ "eject " print bootdrive eject print
+ moveto setcolor
+ pop 0
+ } if
+
+ dup keyShiftF5 eq syslinux and debug 3 ge and {
+ currentcolor black setcolor
+ currentpoint 100 0 moveto
+ bootdrive print
+ moveto setcolor
+ pop 0
+ } if
+
+ dup keyShiftF8 eq debug 3 ge and {
+ currentcolor black setcolor currentpoint 300 0 moveto
+ memsize print "/" print print " " print
+ moveto setcolor
+ pop 0
+ } if
+
+ dup keyShiftF9 eq debug 3 ge and {
+ pop 0
+ } if
+
+ dup keyShiftF10 eq {
+ /debug debug 1 add def ""
+ pop 0
+ } if
+
+ dup keyShiftF11 eq {
+ currenttransparency 0x10 sub 0 max settransparency
+ pop 0
+ } if
+
+ dup keyF11 eq {
+
+ 0 1 479 {
+ 0 1 639 {
+ over moveto
+ currentpoint 3 div 8 shl exch 3 div add setcolor
+ putpixel
+ } for
+ pop
+ } for
+
+ pop 0
+ } if
+
+ dup keyShiftF12 eq {
+ currenttransparency 0x10 add 0x100 min settransparency
+ pop 0
+ } if
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show exit popup.
+%
+% ( ) ==> ( )
+%
+/exit_popup {
+ window.dialog
+
+ dup .title txt_exit_title put
+ dup .text txt_exit_dialog put
+ dup .buttons [
+ button.ok button.default actExit button.setaction
+ button.cancel button.notdefault actNothing button.setaction
+ ] put
+ dup window.init
+ window.show
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show help window.
+%
+% ( ) ==> ( )
+%
+/show_help {
+ window.help
+
+ dup window.init
+ window.show
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show dvd popup.
+%
+% ( ) ==> ( )
+%
+/dvd_popup {
+ window.dialog
+
+ dup .title txt_dvd_warning_title put
+ dup .text txt_dvd_warning2 put
+ dup .buttons [
+% button.eject button.default actEject actNoClose or button.setaction
+ button.continue button.default actNothing button.setaction
+ ] put
+ dup window.init
+ window.show
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show "power off" popup.
+%
+% ( ) ==> ( )
+%
+/power_off {
+ window.dialog
+
+ dup .title txt_power_off_title put
+ dup .text txt_power_off put
+ dup .buttons [
+ button.ok button.notdefault actPowerOff actNoClose or button.setaction
+ button.cancel button.default actNothing button.setaction
+ ] put
+ dup window.init
+ window.show
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Initialize timeout indicator.
+%
+% ( ) ==> ( )
+%
+/timeout.init {
+ /timeout.current -1 def
+ /timeout.x 160 def
+ /timeout.y 340 def
+ /timeout.dx 1 def
+ /timeout.dy 0 def
+ /timeout.symbols 320 def
+ /timeout.clear true def
+ /timeout.size { 1 18 } def
+ /timeout.buf 64 string def
+
+ timeout.x timeout.y moveto
+ prog_frame_color dup
+ timeout.dx timeout.symbols mul timeout.size exch pop
+ drawborder
+
+ timeout.x timeout.y 20 sub moveto
+ white setcolor
+ "booting in " show
+ currentpoint /timeout.time.y exch def /timeout.time.x exch def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Search for option in cmdline.
+% Returns .undef if not found.
+%
+% ( cmdline option_name ) ==> ( option_start )
+%
+/bootopt.find {
+ /bo.opt exch def
+ /bo.cmdline exch def
+
+ {
+ bo.cmdline bo.opt strstr
+ dup {
+ dup 1 eq {
+ true
+ } {
+ dup 2 sub bo.cmdline exch get ' ' eq
+ } ifelse
+
+ {
+ bo.cmdline over bo.opt length add 1 sub get
+ dup '=' eq
+ over ' ' eq or
+ exch 0 eq or
+ } {
+ false
+ } ifelse
+
+ bo.cmdline rot add exch
+
+ {
+ 1 sub exit
+ } {
+ /bo.cmdline exch def
+ } ifelse
+ } {
+ pop
+ .undef exit
+ } ifelse
+ } loop
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Global variables.
+%
+
+/clip.size { 640 480 } def
+
+640 480 8 findmode setmode not { false return } if
+% 800 600 8 findmode setmode not { false return } if
+
+"background.pcx" findfile setimage loadpalette
+/max_image_colors image.colors def
+
+% 7 dup 0xffffff setpalette setcolor
+
+bsplash.show
+
+% color & font definitions must be global
+
+/black 0x000000 newcolor
+/white 0xffffff newcolor
+/mediumblue 0x566eb2 newcolor
+/mediumblue2 0x768cc5 newcolor
+/lightblue 0xd0d0ff newcolor
+/lightblue2 0x2a73d3 newcolor
+/darkgray 0x4c4c4c newcolor
+/grayb5 0xb5b5b5 newcolor
+/lightgray 0xececf4 newcolor
+/graye8 0xe8e8e8 newcolor
+/blue 0x0000a0 newcolor
+/yellow 0xffff20 newcolor
+/red 0xc00000 newcolor
+/somered 0xe6373a newcolor
+/loading_color 0x23449c newcolor
+/green 0x009000 newcolor
+/fn_color 0x33449c newcolor
+/fn_color2 0x53a53f newcolor
+/prog_frame_color lightblue def
+/prog_frame_color2 0x364c65 newcolor
+/dud_color 0x006f64 newcolor
+
+/font.normal "16x16.font" findfile def
+/font.large font.normal def
+
+/cmdline.hidden 256 string def
+/cmdline.shown 256 string def
+
+/kroete.dir 0 def
+
+/debug 0 def
+
+
diff --git a/themes/SuSE/dia_dud.inc b/themes/SuSE/dia_dud.inc
new file mode 100644
index 0000000..6772e28
--- /dev/null
+++ b/themes/SuSE/dia_dud.inc
@@ -0,0 +1,59 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Driver update dialog.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show driver update.
+%
+% ( ) => ( )
+%
+/panel.dud {
+ do_driverupdate .undef eq {
+ /do_driverupdate 1 def
+ 1 updatedisk
+ black setcolor
+ currentfont font.normal setfont
+ update.pos moveto currentpoint
+ prog_frame_color dup prog_frame_color2
+ update.text strsize 6 add exch 16 add exch
+ drawborder3
+ moveto 8 3 rmoveto update.text white setcolor show
+ setfont
+ }
+ {
+ /do_driverupdate .undef def
+ 0 updatedisk
+ update.pos moveto currentpoint
+ update.text strsize 7 add exch 17 add exch
+ image
+ } ifelse
+
+ "driverupdate" help.setcontext
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Return width of driver update entry.
+%
+% ( ) => ( width )
+%
+/panel.dud.width {
+ txt_driver_update strsize pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Redraw panel entry.
+%
+% ( panel ) => ( )
+%
+/panel.dud.update {
+ panel.text.moveto
+
+ txt_driver_update show
+} def
+
+
diff --git a/themes/SuSE/dia_help.inc b/themes/SuSE/dia_help.inc
new file mode 100644
index 0000000..cb8cd24
--- /dev/null
+++ b/themes/SuSE/dia_help.inc
@@ -0,0 +1,44 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Panel help entry.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show help window.
+%
+% ( ) => ( )
+%
+/panel.help {
+ help.context "opt" eq {
+ findbootoption
+ help.mapcontext
+ dup help.findpage
+ "" eq { pop } { help.setcontext } ifelse
+ } if
+ show_help
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Return width of help entry.
+%
+% ( ) => ( width )
+%
+/panel.help.width {
+ txt_help strsize pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Redraw panel entry.
+%
+% ( panel ) => ( )
+%
+/panel.help.update {
+ panel.text.moveto
+
+ txt_help show
+} def
+
+
diff --git a/themes/SuSE/dia_install.inc b/themes/SuSE/dia_install.inc
new file mode 100644
index 0000000..ad3d2b6
--- /dev/null
+++ b/themes/SuSE/dia_install.inc
@@ -0,0 +1,290 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Install mode selection dialog.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Some global vars.
+%
+/install.last 0 def
+
+/install.option 255 string def
+
+% install types
+/.inst_cdrom 0 def
+/.inst_slp 1 def
+/.inst_ftp 2 def
+/.inst_nfs 3 def
+/.inst_smb 4 def
+/.inst_hd 5 def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Build install mode list.
+%
+% ( ) ==> ( )
+%
+/install.init {
+ /xmenu.install .xm_size array def
+
+ /xmenu xmenu.install def
+
+ xmenu .xm_current 0 put
+
+ % see install types (.inst_*)
+ xmenu .xm_list [ "CD-ROM" "SLP" "FTP" "NFS" "SMB" txt_harddisk ] put
+
+ pmenu.init
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Update install mode.
+%
+% ( ) ==> ( )
+%
+/install.update {
+ /xmenu xmenu.install def
+
+ xmenu .xm_current get dup .inst_cdrom eq exch .inst_slp eq or {
+ /install.last xmenu .xm_current get def
+
+ install.option install.last .inst_cdrom eq { "" } { "install=slp" } ifelse strcpy
+
+ /window.action actRedrawPanel def
+
+ pmenu.update
+ } {
+ install.dialog
+ }
+ ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show install menu.
+%
+% ( ) => ( )
+%
+/panel.install {
+ "install_src" help.setcontext
+
+ window.xmenu
+ dup .xmenu xmenu.install put
+ dup .xmenu.update /install.update put
+ dup window.init
+ window.show
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Return width of panel entry.
+%
+% ( ) => ( width )
+%
+/panel.install.width {
+ /xmenu xmenu.install def
+
+ pmenu.width
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Redraw panel entry.
+%
+% ( panel ) => ( )
+%
+/panel.install.update {
+ /xmenu xmenu.install def
+
+ pmenu.panel.update
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+/install.dialog {
+
+ /dia window.dialog def
+
+ xmenu .xm_current get
+
+ dup .inst_hd eq {
+ input.dialog.hd {
+ /dia input.dialog.hd def
+ } {
+ /input.dialog.hd window.dialog def
+ /dia input.dialog.hd def
+
+ dia .dont_free 1 put
+
+ dia .title txt_harddisk_title put
+ dia .text "" put
+
+ % Must all be of same size!
+ dia .ed.list 2 array put
+ dia .ed.buffer.list [ 63 string 127 string ] put
+ dia .ed.text.list [ txt_hd_diskdevice txt_directory ] put
+
+ dia .ed.focus 0 put
+ } ifelse
+ } if
+
+ dup .inst_ftp eq {
+ input.dialog.ftp {
+ /dia input.dialog.ftp def
+ } {
+ /input.dialog.ftp window.dialog def
+ /dia input.dialog.ftp def
+
+ dia .dont_free 1 put
+
+ dia .title txt_ftp_title put
+ dia .text "" put
+
+ % Must all be of same size!
+ dia .ed.list 4 array put
+ dia .ed.buffer.list [ 63 string 127 string 31 string 31 string ] put
+ dia .ed.text.list [ txt_server txt_directory txt_user1 txt_password ] put
+
+ dia .ed.focus 0 put
+ } ifelse
+ } if
+
+ dup .inst_nfs eq {
+ input.dialog.nfs {
+ /dia input.dialog.nfs def
+ } {
+ /input.dialog.nfs window.dialog def
+ /dia input.dialog.nfs def
+
+ dia .dont_free 1 put
+
+ dia .title txt_nfs_title put
+ dia .text "" put
+
+ % Must all be of same size!
+ dia .ed.list 2 array put
+ dia .ed.buffer.list [ 63 string 127 string ] put
+ dia .ed.text.list [ txt_server txt_directory ] put
+
+ dia .ed.focus 0 put
+ } ifelse
+ } if
+
+ dup .inst_smb eq {
+ input.dialog.smb {
+ /dia input.dialog.smb def
+ } {
+ /input.dialog.smb window.dialog def
+ /dia input.dialog.smb def
+
+ dia .dont_free 1 put
+
+ dia .title txt_smb_title put
+ dia .text "" put
+
+ % Must all be of same size!
+ dia .ed.list 4 array put
+ dia .ed.buffer.list [ 63 string 127 string 31 string 31 string ] put
+ dia .ed.text.list [ txt_server txt_directory txt_user2 txt_password ] put
+
+ dia .ed.focus 0 put
+ } ifelse
+ } if
+
+ pop
+
+ dia .ed.width 240 put
+
+ dia .buttons [
+ button.ok button.default actInstallOK actNoClose or button.setaction
+ button.cancel button.notdefault actInstallCancel button.setaction
+ ] put
+
+ dia window.init
+ dia window.show
+
+} def
+
+
+
+/install.ok {
+ /xmenu xmenu.install def
+
+ window.done
+
+ /install.last xmenu .xm_current get def
+
+ /window.action actRedrawPanel def
+
+ pmenu.update
+
+ xmenu .xm_current get
+
+ dup .inst_hd eq {
+ input.dialog.hd .ed.buffer.list get
+ dup 1 get dup 0 get '/' eq { 1 add } if
+ exch 0 get dup 0 get '/' eq { 1 add } if
+ "install=hd://%s/%s" install.option sprintf
+ } if
+
+ dup .inst_ftp eq {
+ input.dialog.ftp .ed.buffer.list get
+
+ "install=ftp://" install.option sprintf
+
+ % add user name & password
+ dup 2 get "" ne {
+ dup 2 get "%s" install.option dup length add sprintf
+ dup 3 get "" ne {
+ dup 3 get ":%s" install.option dup length add sprintf
+ } if
+ "@" install.option dup length add sprintf
+ } if
+
+ dup 1 get exch 0 get "%s/%s" install.option dup length add sprintf
+ } if
+
+ dup .inst_nfs eq {
+ input.dialog.nfs .ed.buffer.list get
+ dup 1 get dup 0 get '/' eq { 1 add } if
+ exch 0 get
+ "install=nfs://%s/%s" install.option sprintf
+ } if
+
+ dup .inst_smb eq {
+ input.dialog.smb .ed.buffer.list get
+
+ "install=smb://" install.option sprintf
+
+ % add user name & password
+ dup 2 get "" ne {
+ dup 2 get "%s" install.option dup length add sprintf
+ dup 3 get "" ne {
+ dup 3 get ":%s" install.option dup length add sprintf
+ } if
+ "@" install.option dup length add sprintf
+ } if
+
+ dup 1 get exch 0 get "%s/%s" install.option dup length add sprintf
+ } if
+
+ pop
+
+} def
+
+
+/install.cancel {
+ /xmenu xmenu.install def
+
+ xmenu .xm_current install.last put
+
+% /window.action actRedrawPanel def
+% pmenu.update
+} def
+
diff --git a/themes/SuSE/dia_lang.inc b/themes/SuSE/dia_lang.inc
new file mode 100644
index 0000000..90d816e
--- /dev/null
+++ b/themes/SuSE/dia_lang.inc
@@ -0,0 +1,90 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Language selection dialog.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Build language list.
+%
+% ( ) ==> ( )
+%
+/keytable.init {
+ /tmp.kt [ keymaps { 1 get } forall ] def
+
+ /xmenu.keytable .xm_size array def
+
+ /xmenu xmenu.keytable def
+
+ xmenu .xm_current keymaps.default put
+ xmenu .xm_list tmp.kt put
+
+ % start with current lang
+
+ /tmp.kt 0 def
+ keymaps {
+ 0 get config.lang eq { xmenu .xm_current tmp.kt put exit } if
+ /tmp.kt tmp.kt 1 add def
+ } forall
+
+ pmenu.init
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Update language.
+%
+% ( ) ==> ( )
+%
+/keytable.update {
+ /xmenu xmenu.keytable def
+
+ keymaps xmenu .xm_current get get 0 get setlang { /window.action actRedraw def } if
+ /config.keymap keymaps xmenu .xm_current get get 2 get def
+
+ % Why? --> see dia_install.inc; same there.
+ window.action actRedraw eq { pmenu.update } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show language menu.
+%
+% ( ) => ( )
+%
+/panel.keytable {
+ "keytable" help.setcontext
+
+ window.xmenu
+ dup .xmenu xmenu.keytable put
+ dup .xmenu.update /keytable.update put
+ dup window.init
+ window.show
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Return width of panel entry.
+%
+% ( ) => ( width )
+%
+/panel.keytable.width {
+ /xmenu xmenu.keytable def
+
+ pmenu.width
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Redraw panel entry.
+%
+% ( panel ) => ( )
+%
+/panel.keytable.update {
+ /xmenu xmenu.keytable def
+
+ pmenu.panel.update
+} def
+
+
diff --git a/themes/SuSE/dia_profile.inc b/themes/SuSE/dia_profile.inc
new file mode 100644
index 0000000..61c2e24
--- /dev/null
+++ b/themes/SuSE/dia_profile.inc
@@ -0,0 +1,139 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Profile selection dialog.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Some global vars.
+%
+
+% fallback if we can't parse "profiles"
+/profile.options [ "" ] def
+/profile.items [ "Broken Profiles" ] def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Parse "profiles" file.
+%
+% ( ) ==> ( )
+%
+/profile.parsedata {
+ /pf.tmp.datalen profile.data length def
+ /pf.tmp.str profile.data cvs def
+
+ /profile.default 0 def
+
+ pf.tmp.datalen 0 eq { return } if
+ pf.tmp.str pf.tmp.datalen 1 sub get '\n' ne { return } if
+
+ '\n' seteotchar
+
+ /profile.items [
+
+ /pf.tmp.len 0 def
+ /pf.tmp.cnt 0 def
+ {
+ pf.tmp.str pf.tmp.len add strdup
+ dup dup length 0 put
+ /pf.tmp.len over length 1 add pf.tmp.len add def
+
+ dup 0 get '*' eq { 1 add /profile.default pf.tmp.cnt def } if
+
+ pf.tmp.len pf.tmp.datalen ge { exit } if
+
+ /pf.tmp.cnt inc
+ } loop
+
+ ] def
+
+ ' ' seteotchar
+
+ /profile.options [
+
+ profile.items {
+ dup length add
+ dup 0 0 put
+ 1 add
+ } forall
+
+ ] def
+
+ 0 seteotchar
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Build profile list.
+%
+% ( ) ==> ( )
+%
+/profile.init {
+ /xmenu.profile .xm_size array def
+ /xmenu xmenu.profile def
+
+ profile.parsedata
+
+ xmenu .xm_current profile.default put
+ xmenu .xm_list profile.items put
+
+ pmenu.init
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Update profile.
+%
+% ( ) ==> ( )
+%
+/profile.update {
+ /xmenu xmenu.profile def
+
+ /window.action actRedrawPanel def
+
+ pmenu.update
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show profile menu.
+%
+% ( ) => ( )
+%
+/panel.profile {
+ "profile" help.setcontext
+
+ window.xmenu
+ dup .xmenu xmenu.profile put
+ dup .xmenu.update /profile.update put
+ dup window.init
+ window.show
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Return width of panel entry.
+%
+% ( ) => ( width )
+%
+/panel.profile.width {
+ /xmenu xmenu.profile def
+
+ pmenu.width
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Redraw panel entry.
+%
+% ( panel ) => ( )
+%
+/panel.profile.update {
+ /xmenu xmenu.profile def
+
+ pmenu.panel.update
+} def
+
+
diff --git a/themes/SuSE/dia_splash.inc b/themes/SuSE/dia_splash.inc
new file mode 100644
index 0000000..9083d06
--- /dev/null
+++ b/themes/SuSE/dia_splash.inc
@@ -0,0 +1,90 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Splash mode selection dialog.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Some global vars.
+%
+/splash.default 2 def
+
+/splash.options [
+ "splash=0"
+ "splash=verbose"
+ "splash=silent"
+] def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Build splash list.
+%
+% ( ) ==> ( )
+%
+/splash.init {
+ /xmenu.splash .xm_size array def
+
+ /xmenu xmenu.splash def
+
+ xmenu .xm_current splash.default put
+ xmenu .xm_list [ "Native" "Verbose" "Silent" ] put
+
+ pmenu.init
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Update splash mode.
+%
+% ( ) ==> ( )
+%
+/splash.update {
+ /xmenu xmenu.splash def
+
+ /window.action actRedrawPanel def
+
+ pmenu.update
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show splash menu.
+%
+% ( ) => ( )
+%
+/panel.splash {
+ "startup" help.setcontext
+
+ window.xmenu
+ dup .xmenu xmenu.splash put
+ dup .xmenu.update /splash.update put
+ dup window.init
+ window.show
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Return width of panel entry.
+%
+% ( ) => ( width )
+%
+/panel.splash.width {
+ /xmenu xmenu.splash def
+
+ pmenu.width
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Redraw panel entry.
+%
+% ( panel ) => ( )
+%
+/panel.splash.update {
+ /xmenu xmenu.splash def
+
+ pmenu.panel.update
+} def
+
+
diff --git a/themes/SuSE/dia_video.inc b/themes/SuSE/dia_video.inc
new file mode 100644
index 0000000..73f4c12
--- /dev/null
+++ b/themes/SuSE/dia_video.inc
@@ -0,0 +1,192 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Video mode selection dialog.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Some global vars.
+%
+% We have kernel splash images for at least these sizes.
+/video.splashsizes [
+ 640 480
+ 800 600
+ 1024 768
+ 1280 1024
+] def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Create sort key for video modes.
+%
+% ( vm_index ) ==> ( sort_index )
+%
+/vmsortindex {
+ video.modes.list exch get
+ dup
+ 1 get 16 shl
+ exch 2 get add
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Swap video mode entries.
+% (Helper for video mode sorting.)
+%
+% ( vm_index_1 vm_index_2 ) ==> ( )
+%
+/vmsortexch {
+ over video.modes.list exch get
+ over video.modes.list exch get
+ video.modes.list
+ 5 -1 roll rot put
+ video.modes.list 3 1 roll put
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Check if we have a splash in that resolution.
+%
+% ( video_mode_list_entry ) ==> ( true|false )
+%
+/video.havesplash {
+ false exch
+
+ 0 2 video.splashsizes length 1 sub {
+ over over over
+ 2 get rot 1 get rot video.splashsizes exch get eq
+ rot 1 add video.splashsizes exch get rot eq and
+ { exch pop true exch exit } if
+ } for
+
+ pop
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Build video mode list.
+%
+% ( ) ==> ( )
+%
+/video.init {
+ /xmenu.video .xm_size array def
+
+ /xmenu xmenu.video def
+
+ videomodes 1 add dup array /video.modes.text exch def array /video.modes.list exch def
+ xmenu .xm_list video.modes.text put
+
+ % add text mode entry
+
+ % [ mode width height supported ]
+ video.modes.list 0 [ 0 0 0 1 ] put
+
+ videomodes 0 gt {
+ 0 1 videomodes 1 sub {
+ video.modes.list exch [ over getvideomode ] exch 1 add exch put
+ } for
+ } if
+
+ % sort video.modes.list
+
+ video.modes.list length 1 gt {
+ 0 1 video.modes.list length 2 sub {
+ dup 1 add 1 video.modes.list length 1 sub {
+ over vmsortindex over vmsortindex gt {
+ over over vmsortexch
+ } if
+ pop
+ } for
+ pop
+ } for
+ } if
+
+ % create mode strings
+
+ 0 1 video.modes.list length 1 sub {
+ video.modes.text exch
+ dup video.modes.list exch get
+ dup 1 get 0 eq {
+ pop "Text Mode" put
+ } {
+ 32 string dup rot
+ dup 2 get exch 1 get
+ "%d x %d" 32 5 -1 roll snprintf
+ put
+ } ifelse
+ } for
+
+ % select first mode
+ xmenu .xm_current 0 put
+
+ % select largest mode the monitor supports
+
+ 0 1 video.modes.list length 1 sub {
+ video.modes.list over get
+ dup 3 get 0 gt exch video.havesplash and {
+ xmenu .xm_current rot put
+ } {
+ pop
+ } ifelse
+ } for
+
+ pmenu.init
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Update video mode.
+%
+% ( ) ==> ( )
+%
+/video.update {
+ /xmenu xmenu.video def
+
+ /window.action actRedrawPanel def
+
+ pmenu.update
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show video menu.
+%
+% ( ) => ( )
+%
+/panel.video {
+ "videomode" help.setcontext
+
+ window.xmenu
+ dup .xmenu xmenu.video put
+ dup .xmenu.update /video.update put
+ dup window.init
+ window.show
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Return width of video entry.
+%
+% ( ) => ( width )
+%
+/panel.video.width {
+ /xmenu xmenu.video def
+
+ pmenu.width
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Redraw panel entry.
+%
+% ( panel ) => ( )
+%
+/panel.video.update {
+ /xmenu xmenu.video def
+
+ pmenu.panel.update
+} def
+
+
diff --git a/themes/SuSE/happysuse.mod b/themes/SuSE/happysuse.mod
new file mode 100644
index 0000000..9efbefe
--- /dev/null
+++ b/themes/SuSE/happysuse.mod
Binary files differ
diff --git a/themes/SuSE/help-boot.cs.html b/themes/SuSE/help-boot.cs.html
new file mode 100644
index 0000000..1872a93
--- /dev/null
+++ b/themes/SuSE/help-boot.cs.html
@@ -0,0 +1,113 @@
+<html><body>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="help">Používání nápovědy</a></h3>
+
+Nápověda zavaděče je citlivá na obsah. Poskytuje informace o zvolené nabídce nebo pokud editujete parametry jádra, snaží se poskytnout informace o dané volbě.<br>
+<br>
+Navigační klávesy<br><br>
+
+ <em>Up Arrow</em>: návrat na předešlý odkaz<br>
+ <em>Down Arrow</em>: přechod na následující odkaz<br>
+ <em>Left Arrow</em>, <em>Backspace</em>: návrat k předešlému tématu<br>
+ <em>Right Arrow</em>, <em>Enter</em>, <em>Space</em>: přejít na označený odkaz<br>
+ <em>Page Up</em>: o stránku nahoru<br>
+ <em>Page Down</em>: o stránku dolů<br>
+ <em>Home</em>: přechod na začátek stránky<br>
+ <em>End</em>: přechod na konec stránky<br>
+ <em>Esc</em>: ukončení nápovědy<br>
+
+<br>Návrat do <a href="#opt">startovací nabídky</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="startup">Splash Mode Selection</a></h3>
+
+Splash režim můžete měnit pomocí klávesy <em>F3</em>. Použít můžete také parametr jádra <a href="#o_splash">splash</a>.<br>
+<br>
+<em>native</em> vypne splash screen (stejně jako splash=0)<br>
+<br>
+<em>silent</em> zakryje všechna hlášení jádra a zobrazí místo toho animaci znázorňující pokrok při stratu nebo ukončení systému<br>
+<br>
+<em>verbose</em> Zobrazí hlášení jádra na grafickém pozadí<br>
+
+<br>Návrat do <a href="#opt">startovací nabídky</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="keytable">Výběr klávesové mapy</a></h3>
+
+Stisknutím klávesy <em>F2</em> získáte seznam klávesových map.<br><br>
+
+Tato volba je zatím experimentální a nemusí vždy fungovat.
+(Proto není <em>F2</em> v zobrazené nabídce.)
+
+<br><br>Návrat do <a href="#opt">startovací nabídky</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="opt">Parametry</a></h3>
+
+ <a href="#o_splash">splash</a> -- ovládá splash screen<br>
+ <a href="#o_apm">apm</a> -- nastavení správy napájení<br>
+ <a href="#o_acpi">acpi</a> -- advanced configuration and power interface<br>
+ <a href="#o_ide">ide</a> -- ovládání IDE subsystému<br>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_splash">Parametry jádra: splash</a></h3>
+
+Splash screen je obrázek znázorňující průběh spouštění a vypínání.<br>
+<br>
+<em>splash=0</em><br>
+Splash screen je vypnutý. Tato volba je velmi užitečná pro staré monitory a v případě problémů.<br>
+<br>
+<em>splash=verbose</em><br> Splash screen je puštěný, ale stále vidíte hlášení jádra.<br>
+<br>
+<em>splash=silent</em><br>
+Splash screen je puštěný a zcela zakrývá hlášení jádra.<br>
+<br>
+Návrat do <a href="#opt">startovací nabídky</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_apm">Parametry jádra: apm</a></h3>
+
+APM je jedním ze standardů správy napájení používaných na současných počítačích. Obvykle je používán například pro uspání na disk u notebooků a také je odpovědný za vypnutí počítače po ukončení operačního systému. APM je závislé na správně fungujícím BIOSu. V případě poškození BIOSu by měla být funkce APM omezena. Z toho důvodu můžete APM vypnout parametrem:<br><br>
+
+ <em>apm=off</em> -- kompletní vypnutí APM<br><br>
+
+Některé velmi nové počítače místo APM používají
+<a href="#o_acpi">ACPI</a>.
+
+<br><br>Návrat do <a href="#opt">startovací nabídky</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_acpi">Parametry jádra: acpi</a></h3>
+
+ACPI (Advanced Configuration and Power Interface) je standard definující nastavení napájení a správu zařízení mezi operačním systémem a BIOSem. Ve výchozím nastavení je <em>acpi</em> zapnuto v případě, že jde o BIOS vydaný po roce 2000. Nejčastěji používané nastavení:<br>
+<br>
+ <em>pci=noacpi</em> -- nepoužívat ACPI k předávání PCI přerušení
+ <em>acpi=oldboot</em> -- aktivní zůstane pouze ta část ACPI, která je potřebná pro start systému<br>
+ <em>acpi=off</em> -- vypnutí ACPI<br>
+ <em>acpi=force</em> -- zapnutí ACPI i pro BIOS vydaný před rokem 2000<br>
+<br>
+Na nových počítačích nahrazuje starší <a href="#o_apm">apm</a> systém.
+
+
+<br><br>Návrat do <a href="#opt">startovací nabídky</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_ide">Parametry jádra: ide</a></h3>
+
+IDE je na rozdíl od SCSI obvykle používáno na pracovních stanicích.
+V případě výskytu problémů s IDE systémem můžete použít parametr: <br><br>
+
+ <em>ide=nodma</em> -- Vypnutí DMA pro všechna IDE zařízení<br>
+
+
+
+<br><br>Návrat do <a href="#opt">startovací nabídky</a>.
+
+</body></html>
diff --git a/themes/SuSE/help-boot.en.html b/themes/SuSE/help-boot.en.html
new file mode 100644
index 0000000..fd07d53
--- /dev/null
+++ b/themes/SuSE/help-boot.en.html
@@ -0,0 +1,141 @@
+<html><body>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="help">Using the Help System</a></h3>
+
+The boot loader online help is context sensitive. It gives information
+about the selected menu item or, if you are editing boot options,
+it tries to look up information about the option in which the cursor is
+positioned.<br>
+<br>
+Navigation Keys<br><br>
+
+ <em>Up Arrow</em>: highlight previous link<br>
+ <em>Down Arrow</em>: highlight next link<br>
+ <em>Left Arrow</em>, <em>Backspace</em>: return to previous topic<br>
+ <em>Right Arrow</em>, <em>Enter</em>, <em>Space</em>: follow link<br>
+ <em>Page Up</em>: scroll up one page<br>
+ <em>Page Down</em>: scroll down one page<br>
+ <em>Home</em>: go to page start<br>
+ <em>End</em>: go to page end<br>
+ <em>Esc</em>: leave help<br>
+
+<br>Return to <a href="#opt">Boot Options</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="startup">Splash Mode Selection</a></h3>
+
+<em>F3</em> lets you change the splash screen mode. You can
+use the <a href="#o_splash">splash</a> kernel option directly, if you prefer.<br>
+<br>
+<em>native</em> turns the splash screen off (same as splash=0)<br>
+<br>
+<em>silent</em> suppresses all kernel and boot messages and shows a progress
+bar instead<br>
+<br>
+<em>verbose</em> shows nice picture and kernel and boot messages<br>
+
+<br>Return to <a href="#opt">Boot Options</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="keytable">Language and Keyboard Layout Selection</a></h3>
+
+Press <em>F2</em> to change language and keyboard layout the boot loader uses.
+
+<br><br>Return to <a href="#opt">Boot Options</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="profile">Choose Profile</a></h3>
+
+Press <em>F4</em> to select a profile. Your system will be started using the
+configuration saved in this profile.
+
+<br><br>Return to <a href="#opt">Boot Options</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="opt">Boot Options</a></h3>
+
+ <a href="#o_splash">splash</a> -- influence the behavior of the splash screen<br>
+ <a href="#o_apm">apm</a> -- toggle power management<br>
+ <a href="#o_acpi">acpi</a> -- advanced configuration and power interface<br>
+ <a href="#o_ide">ide</a> -- control the IDE subsystem<br>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_splash">Kernel Options: splash</a></h3>
+
+The splash screen is the picture shown during system start-up.<br>
+<br>
+<em>splash=0</em><br>
+The splash screen is switched off. This may be useful
+with very old monitors or if some error occurs.<br>
+<br>
+<em>splash=verbose</em><br> Activates splash, kernel and boot messages are
+still shown.<br>
+<br>
+<em>splash=silent</em><br>
+Activates splash, but no messages. Instead a progress bar is drawn.<br>
+<br>
+Return to <a href="#opt">Boot Options</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_apm">Kernel Options: apm</a></h3>
+
+APM is one of the two power management strategies used on current
+computers. It is mainly used with laptops for functions like suspend
+to disk, but it may also be responsible for switching off the
+computer after power down. APM relies on a correct working BIOS. If
+the BIOS is broken, APM may have only limited use or even prevent the
+computer from working. Therefore, it may be switched off with the
+parameter<br><br>
+
+ <em>apm=off</em> -- switch off APM completely<br><br>
+
+Some very new computers may benefit more from the newer
+<a href="#o_acpi">ACPI</a>.
+
+<br><br>Return to <a href="#opt">Boot Options</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_acpi">Kernel Options: acpi</a></h3>
+
+ACPI (Advanced Configuration and Power Interface) is a
+standard that defines power and configuration management interfaces
+between an operating system and the BIOS. By default, <em>acpi</em> is
+switched on when a BIOS is detected that is newer than from year
+2000. There are several commonly
+used parameters to control the behavior of ACPI:<br>
+<br>
+ <em>pci=noacpi</em> -- do not use ACPI to route PCI interrupts
+ <em>acpi=oldboot</em> -- only the parts of ACPI that are relevant
+for booting remain activated<br>
+ <em>acpi=off</em> -- switch off ACPI completely<br>
+ <em>acpi=force</em> -- switch on ACPI even if your BIOS is dated
+before 2000<br>
+<br>
+Especially on new computers, it replaces the old
+<a href="#o_apm">apm</a> system.
+
+
+<br><br>Return to <a href="#opt">Boot Options</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_ide">Kernel Options: ide</a></h3>
+
+IDE is, unlike SCSI, commonly used in most desktop workstations.
+To circumvent some hardware problems that occur with IDE systems, use the
+kernel parameter: <br><br>
+
+ <em>ide=nodma</em> -- switch off dma for IDE drives<br>
+
+
+
+<br><br>Return to <a href="#opt">Boot Options</a>.
+
+</body></html>
diff --git a/themes/SuSE/help-boot.sk.html b/themes/SuSE/help-boot.sk.html
new file mode 100644
index 0000000..56ba7c2
--- /dev/null
+++ b/themes/SuSE/help-boot.sk.html
@@ -0,0 +1,137 @@
+<html><body>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="help">Použitie pomocníka</a></h3>
+
+Pomocník pre správcu štartu je kontextový. Poskytuje informácie
+o vybranej položke menu alebo sa v prípade, že opravujete voľby
+štartu, snaží o zobrazenie informácií o voľbe, na ktorej je
+práve kurzor.<br>
+<br>
+Navigácia klávesnicou<br><br>
+
+ <em>Šipka hore</em>: vybrať predchádzajúci odkaz<br>
+ <em>Šipka dolu</em>: vybrať nasledujúci odkaz<br>
+ <em>Šipka vľavo</em>, <em>Backspace</em>: návrat na prechádzajúci článok<br>
+ <em>Šipka vpravo</em>, <em>Enter</em>, <em>Space</em>: zobraziť odkaz<br>
+ <em>Page Up</em>: posunúť text o jednu stránku hore<br>
+ <em>Page Down</em>: posunúť text o jednu stránku dolu<br>
+ <em>Home</em>: prejsť na začiatok stránky<br>
+ <em>End</em>: prejsť na koniec stránky<br>
+ <em>Esc</em>: ukončiť pomocníka<br>
+
+<br>Návrat na <a href="#opt">Voľby štartu</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="startup">Výber režimu zobrazenia štartu</a></h3>
+
+<em>F2</em> umožňuje zmeniť režim zobrazenia počas štartu
+systému. Ak chcete, môžete priamo použiť voľbu jadra <a href="#o_splash">splash</a>.<br>
+<br>
+<em>native</em> bude zobrazovať všetky správy jadra a štartu systému (rovnaké
+ako splash=0)<br>
+<br>
+<em>silent</em> zabráni zobrazeniu všetkých správ od jadra
+a štartu systému. Namiesto nich zobrazí pruh priebehu<br>
+<br>
+<em>verbose</em> zobrazí obrázok a správy jadra a štartu systému<br>
+
+<br>Návrat na <a href="#opt">Voľby štartu</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="keytable">Výber rozloženia klávesnice</a></h3>
+
+Stlačením <em>F9</em> sa zobrazí zoznam podporovaných
+klávesníc.<br><br>
+
+Toto je experimentálna funkcia a nemusí fungovať správne.
+(Preto nie je <em>F9</em> zobrazené.)
+
+<br><br>Návrat na <a href="#opt">Voľby štartu</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="opt">Voľby štartu</a></h3>
+
+ <a href="#o_splash">splash</a> -- ovplyvňuje zobrazovanie informácií počas štartu<br>
+ <a href="#o_apm">apm</a> -- prepne správu napájania<br>
+ <a href="#o_acpi">acpi</a> -- pokročilé rozhranie nastavenia a správy napájania (Advanced Configuration and Power Interface)<br>
+ <a href="#o_ide">ide</a> -- ovládanie IDE systému<br>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_splash">Voľby jadra: splash</a></h3>
+
+Splash je obrázok zobrazený pri štarte systému.<br>
+<br>
+<em>splash=0</em><br>
+Obrázok je vypnutý. To sa môže hodiť na veľmi
+starých monitoroch alebo v prípade, že sa vyskytne
+nejaká chyba.<br>
+<br>
+<em>splash=verbose</em><br> Aktivuje obrázok, ale správy
+o štarte jadra a systému sa budú zobrazovať.<br>
+<br>
+<em>splash=silent</em><br>
+Aktivuje obrázok, ale bez správ. Namiesto nich sa zobrazí pruh
+priebehu.<br>
+
+<br>Návrat na <a href="#opt">Voľby štartu</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_apm">Voľby jadra: apm</a></h3>
+
+APM je jedna z dvoch technológií pre správu napájania
+pre súčasné počítače. Používa sa hlavne na prenosných
+počítačoch na uspávanie, ale dokáže aj vypnúť počítač.
+APM vyžaduje správne fungujúci BIOS. Ak je BIOS
+nesprávny, APM môže fungovať iba čiastočne alebo dokonca
+počítač môže prestať fungovať. V tom prípade budete možno
+musieť APM vypnúť pomocou parametra<br><br>
+
+ <em>apm=off</em> -- úplne vypnúť APM<br><br>
+
+Niektore nové počítač môžu využiť novšiu technológiu
+<a href="#o_acpi">ACPI</a>.
+
+<br><br>Návrat na <a href="#opt">Voľby štartu</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_acpi">Voľby jadra: acpi</a></h3>
+
+ACPI (Advanced Configuration and Power Interface) je štandard,
+ktorý definuje rozhrania pre správu napájania a nastavenia počítača
+medzi BIOSom operačným systémom. Štandardne sa <em>acpi</em>
+zapne, ak je BIOS novší než z roku 2000. Pre chovanie ACPI
+existuje niekoľko často používaných parametrov:<br>
+<br>
+ <em>pci=noacpi</em> -- nepoužívať ACPI pre správu prerušení PCI
+ <em>acpi=oldboot</em> -- aktivovať iba časti ACPI, ktoré sa týkajú
+ štartu systému<br>
+ <em>acpi=off</em> -- vypnúť ACPI úplne<br>
+ <em>acpi=force</em> -- zapnúť ACPI aj v prípade, že je BIOS starší
+ než z roku 2000<br>
+<br>
+Hlavne na nových počítačoch nahradzuje systém
+<a href="#o_apm">apm</a>.
+
+
+<br><br>Návrat na <a href="#opt">Voľby štartu</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_ide">Voľby jadra: ide</a></h3>
+
+IDE je rozhranie diskov často používané v pracovných staniciach.
+Aby sa zabránilo niektorým problémom s IDE zariadeniami, použite
+parameter jadra: <br><br>
+
+ <em>ide=nodma</em> -- vypne DMA pre IDE zariadenia<br>
+
+
+<br><br>Návrat na <a href="#opt">Voľby štartu</a>
+
+</body></html>
diff --git a/themes/SuSE/help-install.en.html b/themes/SuSE/help-install.en.html
new file mode 100644
index 0000000..836358e
--- /dev/null
+++ b/themes/SuSE/help-install.en.html
@@ -0,0 +1,404 @@
+<html><body>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="main">Boot Loader Help</a></h3>
+Welcome to <em>SUSE LINUX 9.1</em><br><br>
+
+Use this menu to select the desired function. If you have
+problems navigating in this help system, press
+<em>F1</em> to enter the <a href="#help">description</a> of the help
+system. The main functions in this menu are:<br><br>
+
+<a href="#harddisk">Boot from Hard Disk</a>: This selection will not do
+anything to the system. It only starts a previously installed
+operating system.<br><br>
+
+<a href="#linux">Installation</a>:
+This installation mode works on most machines. If you experience a
+system freeze during boot or problems with detection of your hardware
+components, such as disk controllers or network cards, try one of the
+following installation options. <br><br>
+
+<a href="#noacpi">Installation -- ACPI Disabled</a>: Many of the
+currently-sold computers have incomplete or faulty ACPI
+implementations. This selection disables ACPI support in the
+kernel, but still enables many performance features, like DMA for IDE
+hard disks. <br><br>
+
+<a href="#failsafe">Installation -- Safe Settings</a>: If you were not
+successful with <em>Installation</em>, this selection might
+solve the issue.<br><br>
+
+<a href="#manual">Manual Installation</a>: This item is intended for
+experts. Use this
+option to have the most possible control. Also use it to load extra modules,
+for example, before starting the Rescue
+System.<br><br>
+
+<a href="#rescue">Rescue System</a>: This boot image starts a small
+Linux system in RAM. This is useful if the system does not start properly.
+After booting this system, log in as root. <br><br>
+
+<a href="#memtest">Memory Test</a>: Memory testing is useful for more than
+checking installation of new memory modules. It is a stress test
+for a big part of your computer system and may indicate hardware
+problems. <br><br>
+
+<a href="#opt">Boot Options</a>: The boot options may change the
+behavior of your system completely. They are settings for
+the kernel.<br><br>
+
+<a href="#help">F1 Help</a>: This is context sensitive. It will
+show different screens depending on the active element of the
+boot screen. There is also a description of this help system
+available.<br><br>
+
+<a href="#videomode">F2 Video Mode</a>: Here, choose between
+different screen resolutions while installing. If you encounter
+problems with the graphical installation, the <em>text mode</em> may
+be a work-around for you.<br><br>
+
+<a href="#install_src">F3 Installation Source</a>: Choose the
+installation source.<br><br>
+
+<a href="#keytable">F4 Language</a>: Set language and keyboard mapping
+used by the boot loader.<br><br>
+
+<a href="#startup">F5 Kernel Startup</a>: Normally, you won't see
+any kernel messages. Use <em>F5</em> to change that.<br><br>
+
+<a href="#driverupdate">F6 Driver Update</a>: For very new machines, a
+driver update may be needed to install the system.<br><br>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="help">Using the Help System</a></h3>
+
+The boot loader online help is context sensitive. It gives information
+about the selected menu item or, if you are editing boot options,
+it tries to look up information about the option in which the cursor is
+positioned.<br>
+<br>
+Navigation Keys<br><br>
+
+ <em>Up Arrow</em>: highlight previous link<br>
+ <em>Down Arrow</em>: highlight next link<br>
+ <em>Left Arrow</em>, <em>Backspace</em>: return to previous topic<br>
+ <em>Right Arrow</em>, <em>Enter</em>, <em>Space</em>: follow link<br>
+ <em>Page Up</em>: scroll up one page<br>
+ <em>Page Down</em>: scroll down one page<br>
+ <em>Home</em>: go to page start<br>
+ <em>End</em>: go to page end<br>
+ <em>Esc</em>: leave help<br>
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="driverupdate">Driver Update</a></h3>
+
+If you need a driver update floppy or CD-ROM, press <em>F6</em>. The
+boot loader asks you to insert the driver update medium after
+loading the Linux kernel.<br><br>
+
+A driver update is typically a floppy with new versions of hardware
+drivers or bug fixes needed during installation.
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="videomode">Video Mode Selection</a></h3>
+
+Press <em>F2</em> to get the list of video modes your graphics card
+supports. The highest mode your monitor can display is preselected.<br><br>
+
+It is possible that your monitor cannot be detected automatically. In that
+case, select your preferred mode manually.<br><br>
+
+If your system has problems with the graphics card during the
+installation, the <em>text mode</em> may be a usable work-around.
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="startup">Splash Mode Selection</a></h3>
+
+<em>F5</em> lets you change the splash screen mode. You can
+use the <a href="#o_splash">splash</a> kernel option directly, if you prefer.<br>
+<br>
+<em>native</em> turns the splash screen off (same as splash=0)<br>
+<br>
+<em>verbose</em> shows nice picture and kernel and boot messages<br>
+<br>
+<em>silent</em> suppresses all kernel and boot messages and shows a progress
+bar instead<br>
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="keytable">Language and Keyboard Layout Selection</a></h3>
+
+Press <em>F4</em> to change language and keyboard layout the boot loader uses.
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="install_src">Installation Source</a></h3>
+
+Press <em>F3</em> to choose an installation source.<br><br>
+
+This is the same as using the <a href="#o_install">install</a>
+boot option.
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="linux">Installation</a></h3>
+
+Select <em>Installation</em> to start the default installation. The
+<a href="#opt">boot options</a> entered are used in the
+start-up. This item activates many features of commonly available
+hardware. <br><br>
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="harddisk">Boot from Hard Disk</a></h3>
+
+Select <em>Boot Installed OS</em> to start the system installed on
+your local hard disk. This system must be installed properly, because
+only the MBR (Master Boot Record) on the first hard disk is started.
+The device ID of the first hard disk is provided by the BIOS of
+the computer. <br><br>
+
+Use this if you forgot to remove the CD or DVD from your
+drive and want to start the computer from the hard disk.<br><br>
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="noacpi">Installation -- ACPI Disabled</a></h3>
+
+In SuSE Linux, the ACPI support of the developer kernel 2.5 is already
+available for the stable 2.4 kernel. Very new hardware sometimes
+requires ACPI to control the interrupt handling. ACPI completely
+replaces the old APM system. <br><br>
+
+Select <em>Installation -- ACPI Disabled</em> if you encounter
+problems during boot of the kernel. Known problems with machines that
+have problems with ACPI are:
+<br><br>
+
+ * kernel freezes when booting<br>
+ * PCI Cards are not detected or initialized properly<br><br>
+
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="failsafe">Installation -- Safe Settings</a></h3>
+
+Select <em>Installation -- Safe Settings</em> if you encounter hangs
+while installing or irreproducible errors. This option disables DMA
+for IDE drives and all power management features.
+See also the kernel options for <a href="#o_apm">apm</a>,
+<a href="#o_acpi">acpi</a> and <a href="#o_ide">ide</a>.
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="manual">Manual Installation</a></h3>
+
+<em>Manual Installation</em> enables the professional to tune several
+installation parameters before installing a system or booting the
+<a href="#rescue">Rescue System</a>. This is intended for expert use
+only.
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="rescue">Rescue System</a></h3>
+
+The <em>Rescue System</em> is a small RAM disk base system. From there,
+it is possible to make all kinds of changes to an installed system. Because
+only low-level tools are available in this system, it is intended for
+experts.<br><br>
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="memtest">Memory Test</a></h3>
+
+The included <em>Memory Test</em> provides good possibilities to
+stress test the hardware of a system. Its main purpose is to detect
+broken RAM, but it also stresses many other parts of the system. <br>
+
+There is no guarantee that the memory is good if no errors are
+found, although most of memory defects will be found.<br>
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="opt">Boot Options</a></h3>
+
+There are two types of boot options available. First, there are
+options that affect the installer. Second, there are kernel
+options. Some of the more common options are: <br><br>
+a) installer options<br>
+<br>
+ <a href="#o_install">install</a> -- select an installation source<br>
+ <a href="#network">network options</a> -- the network options<br>
+ <a href="#o_vnc">vnc options</a> -- options for installation via VNC
+<br><br>
+b) kernel options<br>
+<br>
+ <a href="#o_splash">splash</a> -- influence the behavior of the splash screen<br>
+ <a href="#o_apm">apm</a> -- toggle power management<br>
+ <a href="#o_acpi">acpi</a> -- advanced configuration and power interface<br>
+ <a href="#o_ide">ide</a> -- control the IDE subsystem<br>
+
+<br><br>Return to <a href="#main">Start Page</a>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_install">Installer Options: install</a></h3>
+
+By default, the local CD-ROMs are searched for the installation source.
+For a network install, select the
+<em>install</em> option. Possible installation protocols are<br>
+ * FTP<br>
+ * NFS<br>
+ * HTTP<br>
+The syntax to use is just like standard URLs. For example,
+if your server is found at 192.168.0.1 and you want to do an NFS-based
+install from the directory /install on this server, specify
+the source as follows:<br><br>
+
+ <em>install=nfs://192.168.0.1/install</em><br><br>
+
+The network card will either be configured with <em>dhcp</em> or you
+must specify the parameters yourself as described in the
+<a href="#network">network options</a>.<br>
+
+<br><br>Return to <a href="#opt">Boot Options</a>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_splash">Kernel Options: splash</a></h3>
+
+
+The splash screen is the picture shown during system start-up.<br>
+<br>
+<em>splash=0</em><br><br> The splash screen is switched off. This may be useful
+with very old monitors or if some error occurs.<br>
+<br>
+<em>splash=verbose</em><br><br> Activates splash, kernel and boot messages are
+still shown.<br>
+<br>
+<em>splash=silent</em><br><br>
+Activates splash, but no messages. Instead a progress bar is drawn.<br>
+<br>
+Return to <a href="#opt">Boot Options</a>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="network">Installer Options: Network Options</a></h3>
+
+It is possible to configure the network interface right now. The
+hardware will be detected later by YaST2. The minimum set of options
+to configure your network card consists of host IP and netmask. For
+example:<br><br>
+
+ <em>hostip=192.168.0.10 netmask=255.255.255.0</em><br>
+<br>
+or in a shorter form:<br><br>
+
+ <em>hostip=192.168.0.10/24</em><br>
+<br>
+
+If you specified a <a href="#o_install">network-based install</a> and do
+not specify both of these options, the installer tries to configure
+the network interface with <em>dhcp</em>. If you need a default
+gateway, specify this with the option <em>gateway</em>. For
+example:<br><br>
+
+ <em>gateway=192.168.0.8</em><br>
+
+<br><br>Return to <a href="#opt">Boot Options</a>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_vnc">Installer Options: vnc</a></h3>
+
+To enable the VNC installation, specify the
+parameters vnc and vncpassword:<br><br>
+
+ <em>vnc=1 vncpassword=example</em><br><br>
+
+The VNC server will be started and you may control YaST2 over any VNC
+client from a remote system.<br>
+
+<br><br>Return to <a href="#opt">Boot Options</a>.
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_apm">Kernel Options: apm</a></h3>
+
+APM is one of the two power management strategies used on current
+computers. It is mainly used with laptops for functions like suspend
+to disk, but it may also be responsible for switching off the
+computer after power down. APM relies on a correct working BIOS. If
+the BIOS is broken, APM may have only limited use or even prevent the
+computer from working. Therefore, it may be switched off with the
+parameter<br><br>
+
+ <em>apm=off</em> -- switch off APM completely<br><br>
+
+Some very new computers may take more advantage from the newer
+<a href="#o_acpi">ACPI</a>.
+
+
+<br><br>Return to <a href="#opt">Boot Options</a>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_acpi">Kernel Options: acpi</a></h3>
+
+ACPI (Advanced Configuration and Power Interface) is a
+standard that defines power and configuration management interfaces
+between an operating system and the BIOS. By default, <em>acpi</em> is
+switched on when a BIOS is detected that is newer than from year
+2000. There are several commonly
+used parameters to control the behavior of ACPI:<br>
+<br>
+ <em>pci=noacpi</em> -- do not use ACPI to route PCI interrupts
+ <em>acpi=oldboot</em> -- only the parts of ACPI that are relevant
+for booting remain activated<br>
+ <em>acpi=off</em> -- switch off ACPI completely<br>
+ <em>acpi=force</em> -- switch on ACPI even if your BIOS is dated
+before 2000<br>
+<br>
+Especially on new computers, it replaces the old
+<a href="#o_apm">apm</a> system.
+
+
+<br><br>Return to <a href="#opt">Boot Options</a>
+
+<hr><!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<h3><a name="o_ide">Kernel Options: ide</a></h3>
+
+IDE is, unlike SCSI, commonly used in most desktop workstations.
+To circumvent some hardware problems that occur with IDE systems, use the
+kernel parameter: <br><br>
+
+ <em>ide=nodma</em> -- switch off DMA for IDE drives<br>
+
+
+
+<br><br>Return to <a href="#opt">Boot Options</a>.
+
+</body></html>
diff --git a/themes/SuSE/help.inc b/themes/SuSE/help.inc
new file mode 100644
index 0000000..fda1137
--- /dev/null
+++ b/themes/SuSE/help.inc
@@ -0,0 +1,697 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% help system
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+% global vars used by help system
+
+
+/help.context "main" def
+
+/help.light white def
+/help.dark black def
+/help.font font.normal def
+/help.normal.bg lightgray def
+/help.normal.fg black def
+/help.highlight.fg green def
+/help.link.fg blue def
+/help.link.selected.fg white def
+/help.link.selected.bg blue def
+
+/help.x 80 def
+/help.y 50 def
+/help.width 480 def
+/help.height 322 def
+
+/help.text.x help.x 10 add def
+/help.text.y help.y 30 add def
+
+/help.text.width help.width 20 sub def
+/help.text.height help.height help.text.y sub help.y add 4 sub def
+/help.text.rightmargin help.text.x help.text.width add def
+
+/help.title.x help.x 10 add def
+/help.title.y help.y 3 add def
+/help.title.height 20 def
+/help.title.font font.normal def
+
+% /help.title.bg 0x299dcd newcolor
+% for dialogs, too
+/title.bg 0x317db4 newcolor
+% /title.bg 0x2d9e6b newcolor
+% /title.bg 0x2c9f84 newcolor
+% /title.bg 0x36b74e newcolor
+
+/help.hist.page 16 array def
+/help.hist.startrow help.hist.page length array def
+/help.hist.selectedlink help.hist.page length array def
+
+
+% for boot option lookup
+/bo.opt.max 32 def
+/bo.opt bo.opt.max 3 add string def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Map help context.
+%
+% ( context ) ==> ( new_context )
+%
+/help.mapcontext {
+ dup "o_vncpassword" eq { pop "o_vnc" } if
+ dup "o_hostip" eq { pop "network" } if
+ dup "o_netmask" eq { pop "network" } if
+ dup "o_gateway" eq { pop "network" } if
+ dup "o_pci" eq { pop "o_acpi" } if
+
+ syslinux not {
+ % only help, startup, keytable and option pages
+ dup "o_" strstr 1 ne {
+ dup "help" ne
+ over "startup" ne and
+ over "keytable" ne and
+ over "profile" ne and { pop "opt" } if
+ } if
+ } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Set help context.
+%
+% ( context ) ==> ( )
+%
+/help.setcontext {
+ help.mapcontext /help.context exch def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Find boot option the cursor is positioned at.
+%
+% ( ) ==> ( option )
+%
+/findbootoption {
+ /bo.buf boot.ed 3 get def
+ /bo.len boot.ed 4 get def
+ /bo.pos boot.ed 5 get def
+
+ {
+ bo.pos 0 eq { exit } if
+ bo.buf bo.pos 1 sub get ' ' le { exit } if
+ /bo.pos bo.pos 1 sub def
+ } loop
+
+ /bo.buf bo.buf bo.pos add def
+
+ bo.buf 0 get ' ' le { "" return } if
+
+ % "o_" + option name is the help text label
+ "o_" 3 bo.opt snprintf
+
+ 0 1 bo.opt.max 1 sub {
+ dup
+ bo.buf exch get
+ dup ' ' le over '=' eq or { pop pop exit } if
+ over bo.opt 2 add exch rot put
+ bo.opt 3 add exch 0 put
+ } for
+
+ bo.opt
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Find help page.
+%
+% returns help page or empty string if no page was found
+%
+% ( label ) ==> ( help_text )
+%
+/help.findpage {
+ dup length 3 add dup string
+ "\x12%s\x14"
+ 3 1 roll dup 5 1 roll snprintf
+ help.getmessages over strstr
+ dup { help.getmessages exch 1 sub add } { pop "" } ifelse
+ exch free
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Find help page.
+%
+% returns n-th help page or empty string if no page was found
+%
+% ( n ) ==> ( help_text )
+%
+/help.findpagebyindex {
+ help.getmessages exch
+ {
+ dup "\x04" strstr
+ dup { add } { pop pop "" exit } ifelse
+ } repeat
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Init & display help page.
+%
+% ( help_text start_row selected_link ) ==> ( )
+%
+/help.initpage {
+ /help.selectedlink exch def
+ /help.startrow exch def
+
+ /help.currenttext over def
+
+ title.bg setcolor
+ help.x 1 add help.y 1 add moveto
+ help.width 2 sub help.title.height 1 sub fillrect
+
+ help.text.x help.text.y moveto
+ currentmaxrows 0 setmaxrows exch formattext setmaxrows
+
+ white setcolor
+ currenteotchar 16 seteotchar
+ help.title.x help.title.y moveto currenttitle
+ currentfont help.title.font setfont exch show setfont
+ seteotchar
+
+ getlinks { help.selectedlink setlink } if
+
+ help.updatepage
+
+ % 500 0 moveto gettextrows print
+ % 400 0 moveto getlinks print
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Redraw help page.
+%
+% ( ) ==> ( )
+%
+/help.updatepage {
+ help.normal.bg setcolor
+ help.text.x help.text.y moveto
+ help.text.width help.text.height fillrect
+
+ help.normal.fg help.highlight.fg help.link.fg help.link.selected.fg settextcolors
+
+ help.startrow setstartrow
+
+ help.text.x help.text.y moveto
+ help.currenttext show
+
+ 0 setstartrow
+
+ true help.selectedlink help.redrawlink
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Used to iterate over all help pages (for debugging).
+%
+% get the n-th page starting from current pos
+%
+% ( n ) ==> ( help_text )
+%
+/help.test {
+ help.test.cnt add
+ dup 1 lt { pop 1 } if
+ /help.test.cnt over def
+ help.findpagebyindex
+ dup "" eq {
+ % one page back
+ pop help.test.cnt 1 sub /help.test.cnt over def
+ help.findpagebyindex
+ } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Redraw link.
+%
+% selected: true or false.
+%
+% ( selected n ) ==> ( )
+%
+%
+/help.redrawlink {
+ getlinks 0 eq { pop pop return } if
+ getlink
+ dup help.startrow lt
+ over help.startrow help.text.rows add ge or {
+ 5 { pop } repeat return
+ } if
+ help.startrow sub lineheight mul help.text.y add
+ moveto
+ rot
+
+ 16 seteotchar
+
+ {
+ currenttextcolors 4 1 roll pop pop pop
+ help.link.selected.bg
+ } {
+ currenttextcolors 4 2 roll pop pop pop
+ help.normal.bg
+ } ifelse
+
+ setcolor over currentpoint rot strsize fillrect moveto
+
+ setcolor show
+
+ 4 seteotchar
+
+ pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Select n-th link.
+%
+% ( n ) ==> ( )
+%
+/help.selectlink {
+ help.selectedlink over eq {
+ pop
+ } {
+ % deselect old link
+ false help.selectedlink help.redrawlink
+
+ /help.selectedlink over dup setlink def
+
+ % select link
+ true exch help.redrawlink
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Select first visible link.
+%
+% No screen update if 'update' is false.
+%
+% ( update ) ==> ( )
+%
+/help.sel.firstlink {
+ getlinks {
+ 0 1 getlinks 1 sub {
+ dup
+ getlink 4 1 roll pop pop pop
+ dup help.startrow help.text.rows add ge {
+ pop pop exit
+ } if
+ dup help.startrow ge {
+ pop
+ over { help.selectlink } { /help.selectedlink exch dup setlink def } ifelse
+ exit
+ } if
+ pop pop
+ } for
+ } if
+ pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Select last visible link.
+%
+% No screen update if 'update' is false.
+%
+% ( update ) ==> ( )
+%
+/help.sel.lastlink {
+ getlinks {
+ getlinks 1 sub -1 0 {
+ dup
+ getlink 4 1 roll pop pop pop
+ dup help.startrow lt {
+ pop pop exit
+ } if
+ dup help.startrow help.text.rows add lt {
+ pop
+ over { help.selectlink } { /help.selectedlink exch dup setlink def } ifelse
+ exit
+ } if
+ pop pop
+ } for
+ } if
+ pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Push current help context to history.
+%
+% ( ) ==> ( )
+%
+/help.add2history {
+ help.hist.index help.hist.page length lt {
+ help.hist.page help.hist.index help.currenttext put
+ help.hist.startrow help.hist.index help.startrow put
+ help.hist.selectedlink help.hist.index help.selectedlink put
+ /help.hist.index help.hist.index 1 add def
+ } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Follow currently selected link.
+%
+% ( ) ==> ( )
+%
+/help.followlink {
+ getlinks {
+ help.selectedlink getlink pop pop pop
+ help.add2history
+ help.findpage
+ dup "" eq {
+ pop
+ } {
+ 0 0 help.initpage
+ } ifelse
+ } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Go back to previous page.
+%
+% ( ) ==> ( )
+%
+/help.prevlink {
+ help.hist.index 0 gt {
+ /help.hist.index help.hist.index 1 sub def
+ help.hist.page help.hist.index get
+ help.hist.startrow help.hist.index get
+ help.hist.selectedlink help.hist.index get
+ help.initpage
+ } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Scroll a page down.
+%
+% ( ) ==> ( )
+%
+/help.key.pagedown {
+ help.startrow
+ gettextrows help.text.rows gt {
+ pop
+ gettextrows help.text.rows sub
+ help.startrow help.text.rows add
+ min
+ } if
+
+ dup help.startrow eq {
+ pop
+ true help.sel.lastlink
+ } {
+ /help.startrow exch def
+ false help.sel.firstlink
+ help.updatepage
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Scroll a page up.
+%
+% ( ) ==> ( )
+%
+/help.key.pageup {
+ help.startrow
+ gettextrows help.text.rows gt {
+ pop
+ 0
+ help.startrow help.text.rows sub
+ max
+ } if
+
+ dup help.startrow eq {
+ pop
+ true help.sel.firstlink
+ } {
+ /help.startrow exch def
+ false help.sel.firstlink
+ help.updatepage
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Go to page start.
+%
+% ( ) ==> ( )
+%
+/help.key.home {
+ help.startrow 0 eq {
+ true help.sel.firstlink
+ } {
+ /help.startrow 0 def
+ false help.sel.firstlink
+ help.updatepage
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Go to page end.
+%
+% ( ) ==> ( )
+%
+/help.key.end {
+ gettextrows help.text.rows sub 0 max
+ dup help.startrow eq {
+ pop
+ true help.sel.lastlink
+ } {
+ /help.startrow exch def
+ false help.sel.lastlink
+ help.updatepage
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Next link or scroll down.
+%
+% ( ) ==> ( )
+%
+/help.key.down {
+ help.selectedlink getlinks 1 sub lt {
+ help.selectedlink 1 add getlink 4 1 roll pop pop pop
+ dup help.startrow help.text.rows add lt {
+ % link visible
+ pop help.selectedlink 1 add help.selectlink
+ return
+ } {
+ help.startrow help.text.rows add eq {
+ % link visible after scrolling down
+ /help.selectedlink help.selectedlink 1 add dup setlink def
+ } if
+ } ifelse
+ } if
+
+ % scroll down
+
+ help.startrow help.text.rows add gettextrows lt {
+ /help.startrow help.startrow 1 add def
+ help.updatepage
+ } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Previous link or scroll up.
+%
+% ( ) ==> ( )
+%
+/help.key.up {
+ help.selectedlink 0 gt {
+ help.selectedlink 1 sub getlink 4 1 roll pop pop pop
+ % row
+ dup help.startrow ge {
+ % link visible
+ pop help.selectedlink 1 sub help.selectlink
+ return
+ } {
+ help.startrow 1 sub eq {
+ % link visible after scrolling up
+ /help.selectedlink help.selectedlink 1 sub dup setlink def
+ } if
+ } ifelse
+ } if
+
+ % scroll up
+
+ help.startrow 0 gt {
+ /help.startrow help.startrow 1 sub def
+ help.updatepage
+ } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Handle keyboard input.
+%
+% ( key_in ) ==> ( key_out )
+%
+/help.input {
+ dup 0 eq { return } if
+
+ dup keyEsc eq { /window.action actNothing def window.done } if
+ dup keyCtrlDown eq { 1 help.test 0 0 help.initpage } if
+ dup keyCtrlUp eq { -1 help.test 0 0 help.initpage } if
+ dup keyDown eq { help.key.down } if
+ dup keyUp eq { help.key.up } if
+ dup keyPgDown eq { help.key.pagedown } if
+ dup keyPgUp eq { help.key.pageup } if
+ dup keyHome eq { help.key.home } if
+ dup keyEnd eq { help.key.end } if
+ dup keyRight eq { help.followlink } if
+ dup keyEnter eq { help.followlink } if
+ dup 0xff and ' ' eq { help.followlink } if
+ dup keyLeft eq { help.prevlink } if
+ dup 0xff and '\x08' eq { help.prevlink } if
+ dup keyF1 eq {
+ "help" help.findpage
+ dup help.currenttext eq {
+ pop
+ } {
+ help.add2history
+ 0 0 help.initpage
+ } ifelse
+ } if
+% dup keyF9 eq {
+% /help.font help.font 8 add 10 mod def help.reinit
+% help.currenttext help.startrow help.selectedlink help.initpage
+% } if
+ pop 0
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Recalculate some sizes and redraw help screen.
+%
+% ( ) ==> ( )
+%
+/help.reinit {
+ help.normal.bg setcolor
+ help.x help.y moveto
+ help.width help.height fillrect
+
+ help.x 1 add help.y 1 add help.title.height add moveto
+ help.dark help.light
+ help.width 2 sub help.height 2 sub help.title.height sub
+ drawborder
+
+ help.font setfont
+
+ /help.text.rows help.text.height lineheight div def
+ help.text.rows setmaxrows
+
+ help.text.rightmargin settextwrap
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Initialize help window.
+%
+% ( window ) ==> ( )
+%
+/help.init {
+ /help.tmp exch def
+
+ help.x 1 sub help.y 1 sub moveto
+ help.light help.dark
+ help.width 2 add help.height 2 add
+ over over
+
+ % just for testing: lilo has enough low memory
+ lilo { savescreen } { xsavescreen } ifelse
+
+ help.tmp .saved rot put
+ drawborder
+
+ help.reinit
+
+ 4 seteotchar
+
+ /help.hist.index 0 def
+
+ /help.test.cnt 1 def
+
+ help.context help.findpage 0 0 help.initpage
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Draw help window.
+%
+% ( window ) ==> ( )
+%
+/help.show {
+ window.push
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Close current help window.
+%
+% ( ) ==> ( )
+%
+/help.done {
+ 0 settextwrap
+ 0 seteotchar
+ 0 setmaxrows
+} def
+
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Create new help window.
+%
+% ( ) ==> ( window )
+%
+/window.help {
+ widget.size array
+ dup .type t_help put
+
+ dup .x help.x put
+ dup .y help.y put
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Find help texts.
+%
+% ( ) ==> ( start_of_help_messages )
+%
+/help.getmessages {
+
+ help.messages .undef eq {
+ % find help texts
+ /help.messages
+ 16 string dup config.lang "help.%s" 2 index sprintf
+ findfile exch free
+ dup .undef eq { pop "help.en" findfile } if
+ dup .undef eq { pop "" } if
+ cvs
+ def
+ } if
+
+ help.messages
+
+} def
+
+
diff --git a/themes/SuSE/install.config b/themes/SuSE/install.config
new file mode 100644
index 0000000..6824e0a
--- /dev/null
+++ b/themes/SuSE/install.config
@@ -0,0 +1,24 @@
+%% include system.inc
+%% include bsplash.inc
+
+%% include common.inc
+
+
+%% include po/text.inc
+%% include window.inc
+%% include button.inc
+%% include help.inc
+%% include main.inc
+%% include xmenu.inc
+%% include dia_video.inc
+%% include dia_splash.inc
+%% include dia_lang.inc
+%% include dia_dud.inc
+%% include dia_help.inc
+%% include dia_profile.inc
+%% include dia_install.inc
+%% include panel.inc
+%% include keytables.inc
+%% include locale.inc
+
+
diff --git a/themes/SuSE/keytables.inc b/themes/SuSE/keytables.inc
new file mode 100644
index 0000000..a69ef31
--- /dev/null
+++ b/themes/SuSE/keytables.inc
@@ -0,0 +1,263 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Keyboard mappings.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% keymap layout (diff to us map):
+%
+% key_code, plain, shift, altgr
+%
+
+/keymap.cs [
+ [ 0x02 0x2b 0x31 0x00 ]
+ [ 0x03 0x11b 0x32 0x00 ]
+ [ 0x04 0x161 0x33 0x00 ]
+ [ 0x05 0x10d 0x34 0x00 ]
+ [ 0x06 0x159 0x35 0x00 ]
+ [ 0x07 0x17e 0x36 0x00 ]
+ [ 0x08 0xfd 0x37 0x00 ]
+ [ 0x09 0xe1 0x38 0x00 ]
+ [ 0x0a 0xed 0x39 0x00 ]
+ [ 0x0b 0xe9 0x30 0x00 ]
+ [ 0x0c 0x3d 0x25 0x2d ]
+ [ 0x0d 0x00 0x00 0x3d ]
+ [ 0x15 0x7a 0x5a 0x79 ]
+ [ 0x1a 0xfa 0x2f 0x5b ]
+ [ 0x1b 0x29 0x28 0x5d ]
+ [ 0x27 0x16f 0x22 0x3b ]
+ [ 0x28 0xa7 0x21 0x27 ]
+ [ 0x29 0x60 0x3b 0x00 ]
+ [ 0x2c 0x79 0x59 0x7a ]
+ [ 0x2e 0x63 0x43 0x00 ]
+ [ 0x33 0x2c 0x3f 0x00 ]
+ [ 0x34 0x2e 0x3a 0x00 ]
+ [ 0x35 0x2d 0x5f 0x2f ]
+ [ 0x56 0x7c 0x00 0x3c ]
+] def
+
+
+/keymap.de [
+ [ 0x03 0x32 0x22 0xb2 ]
+ [ 0x04 0x33 0xa7 0xb3 ]
+ [ 0x06 0x35 0x25 0x00 ]
+ [ 0x07 0x36 0x26 0x00 ]
+ [ 0x08 0x37 0x2f 0x7b ]
+ [ 0x09 0x38 0x28 0x5b ]
+ [ 0x0a 0x39 0x29 0x5d ]
+ [ 0x0b 0x30 0x3d 0x7d ]
+ [ 0x0c 0xdf 0x3f 0x5c ]
+ [ 0x0d 0x27 0x60 0x00 ]
+ [ 0x10 0x71 0x51 0x40 ]
+ [ 0x12 0x65 0x45 0x20ac ]
+ [ 0x15 0x7a 0x5a 0x00 ]
+ [ 0x1a 0xfc 0xdc 0x00 ]
+ [ 0x1b 0x2b 0x2a 0x7e ]
+ [ 0x27 0xf6 0xd6 0x00 ]
+ [ 0x28 0xe4 0xc4 0x00 ]
+ [ 0x29 0x5e 0xb0 0x00 ]
+ [ 0x2b 0x23 0x27 0x00 ]
+ [ 0x2c 0x79 0x59 0x00 ]
+ [ 0x32 0x6d 0x4d 0xb5 ]
+ [ 0x33 0x2c 0x3b 0x00 ]
+ [ 0x34 0x2e 0x3a 0x00 ]
+ [ 0x35 0x2d 0x5f 0x00 ]
+ [ 0x56 0x3c 0x3e 0x7c ]
+] def
+
+
+/keymap.es [
+ [ 0x02 0x31 0x21 0x7c ]
+ [ 0x03 0x32 0x22 0x40 ]
+ [ 0x04 0x33 0xb7 0x23 ]
+ [ 0x05 0x34 0x24 0x7e ]
+ [ 0x06 0x35 0x25 0x00 ]
+ [ 0x07 0x36 0x26 0xac ]
+ [ 0x08 0x37 0x2f 0x7b ]
+ [ 0x09 0x38 0x28 0x5b ]
+ [ 0x0a 0x39 0x29 0x5d ]
+ [ 0x0b 0x30 0x3d 0x7d ]
+ [ 0x0c 0x27 0x3f 0x5c ]
+ [ 0x0d 0xa1 0xbf 0x7e ]
+ [ 0x1a 0x00 0x00 0x5b ]
+ [ 0x1b 0x2b 0x2a 0x5d ]
+ [ 0x27 0xf1 0xd1 0x00 ]
+ [ 0x28 0x00 0x00 0x7b ]
+ [ 0x29 0xba 0xaa 0x5c ]
+ [ 0x2b 0xe7 0xc7 0x7d ]
+ [ 0x2e 0x63 0x43 0x00 ]
+ [ 0x33 0x2c 0x3b 0x00 ]
+ [ 0x34 0x2e 0x3a 0x00 ]
+ [ 0x35 0x2d 0x5f 0x00 ]
+ [ 0x56 0x3c 0x3e 0x00 ]
+] def
+
+
+/keymap.fr [
+ [ 0x02 0x26 0x31 0x00 ]
+ [ 0x03 0x7b 0x32 0x7e ]
+ [ 0x04 0x22 0x33 0x23 ]
+ [ 0x05 0x27 0x34 0x7b ]
+ [ 0x06 0x28 0x35 0x5b ]
+ [ 0x07 0x2d 0x36 0x7c ]
+ [ 0x08 0x7d 0x37 0x60 ]
+ [ 0x09 0x5f 0x38 0x5c ]
+ [ 0x0a 0x2f 0x39 0x5e ]
+ [ 0x0b 0x40 0x30 0x00 ]
+ [ 0x0c 0x29 0x5d 0x00 ]
+ [ 0x0d 0x3d 0x2b 0x7d ]
+ [ 0x10 0x61 0x41 0x00 ]
+ [ 0x11 0x7a 0x5a 0x00 ]
+ [ 0x1a 0x5e 0x3c 0x00 ]
+ [ 0x1b 0x24 0x3e 0x7e ]
+ [ 0x1e 0x71 0x51 0x00 ]
+ [ 0x27 0x6d 0x4d 0x00 ]
+ [ 0x28 0x7c 0x25 0x00 ]
+ [ 0x29 0x2a 0x7e 0x00 ]
+ [ 0x2b 0x2a 0x23 0x00 ]
+ [ 0x2c 0x77 0x57 0x00 ]
+ [ 0x2e 0x63 0x43 0x00 ]
+ [ 0x32 0x2c 0x3f 0x00 ]
+ [ 0x33 0x3b 0x2e 0x00 ]
+ [ 0x34 0x3a 0x2f 0x00 ]
+ [ 0x35 0x21 0x5c 0x00 ]
+ [ 0x56 0x3c 0x3e 0x7c ]
+] def
+
+
+/keymap.it [
+ [ 0x03 0x32 0x22 0x00 ]
+ [ 0x04 0x33 0xa3 0x00 ]
+ [ 0x06 0x35 0x25 0x00 ]
+ [ 0x07 0x36 0x26 0x00 ]
+ [ 0x08 0x37 0x2f 0x00 ]
+ [ 0x09 0x38 0x28 0x7b ]
+ [ 0x0a 0x39 0x29 0x7d ]
+ [ 0x0b 0x30 0x3d 0x7e ]
+ [ 0x0c 0x27 0x3f 0x60 ]
+ [ 0x0d 0xec 0x5e 0xed ]
+ [ 0x1a 0xe8 0xe9 0x5b ]
+ [ 0x1b 0x2b 0x2a 0x5d ]
+ [ 0x27 0xf2 0xe7 0x40 ]
+ [ 0x28 0xe0 0xb0 0x23 ]
+ [ 0x29 0x5c 0x7c 0x00 ]
+ [ 0x2b 0xf9 0xa7 0xfa ]
+ [ 0x2e 0x63 0x43 0x00 ]
+ [ 0x33 0x2c 0x3b 0x00 ]
+ [ 0x34 0x2e 0x3a 0x00 ]
+ [ 0x35 0x2d 0x5f 0x00 ]
+ [ 0x56 0x3c 0x3e 0x00 ]
+] def
+
+
+/keymap.jp [
+ [ 0x03 0x32 0x22 0x00 ]
+ [ 0x06 0x35 0x25 0x00 ]
+ [ 0x07 0x36 0x26 0x00 ]
+ [ 0x08 0x37 0x27 0x00 ]
+ [ 0x09 0x38 0x28 0x00 ]
+ [ 0x0a 0x39 0x29 0x00 ]
+ [ 0x0b 0x30 0x7e 0x00 ]
+ [ 0x0c 0x2d 0x3d 0x00 ]
+ [ 0x0d 0x5e 0x7e 0x00 ]
+ [ 0x1a 0x40 0x60 0x00 ]
+ [ 0x1b 0x5b 0x7b 0x00 ]
+ [ 0x27 0x3b 0x2b 0x00 ]
+ [ 0x28 0x3a 0x2a 0x00 ]
+ [ 0x29 0x1b 0x1b 0x00 ]
+ [ 0x2b 0x5d 0x7d 0x00 ]
+ [ 0x2e 0x63 0x43 0x00 ]
+ [ 0x56 0x3c 0x3e 0x00 ]
+ [ 0x59 0x5c 0x5f 0x00 ]
+ [ 0x5c 0x20 0x20 0x00 ]
+ [ 0x5e 0x20 0x20 0x00 ]
+ [ 0x7c 0x5c 0x7c 0x00 ]
+] def
+
+/keymap.ru [
+ [ 0x06 0x35 0x25 0x00 ]
+ [ 0x08 0x37 0x26 0x00 ]
+ [ 0x09 0x38 0x2a 0x00 ]
+ [ 0x0a 0x39 0x28 0x00 ]
+ [ 0x0b 0x30 0x29 0x00 ]
+ [ 0x0c 0x2d 0x5f 0x00 ]
+ [ 0x0f 0x09 0x09 0x00 ]
+ [ 0x10 0x71 0x51 0x439 ]
+ [ 0x11 0x77 0x57 0x446 ]
+ [ 0x12 0x65 0x45 0x443 ]
+ [ 0x13 0x72 0x52 0x43a ]
+ [ 0x14 0x74 0x54 0x435 ]
+ [ 0x15 0x79 0x59 0x43d ]
+ [ 0x16 0x75 0x55 0x433 ]
+ [ 0x17 0x69 0x49 0x448 ]
+ [ 0x18 0x6f 0x4f 0x449 ]
+ [ 0x19 0x70 0x50 0x437 ]
+ [ 0x1a 0x5b 0x7b 0x445 ]
+ [ 0x1b 0x5d 0x7d 0x5b ]
+ [ 0x1e 0x61 0x41 0x444 ]
+ [ 0x1f 0x73 0x53 0x44b ]
+ [ 0x20 0x64 0x44 0x432 ]
+ [ 0x21 0x66 0x46 0x430 ]
+ [ 0x22 0x67 0x47 0x43f ]
+ [ 0x23 0x68 0x48 0x440 ]
+ [ 0x24 0x6a 0x4a 0x43e ]
+ [ 0x25 0x6b 0x4b 0x43b ]
+ [ 0x26 0x6c 0x4c 0x434 ]
+ [ 0x27 0x3b 0x3a 0x436 ]
+ [ 0x28 0x27 0x22 0x44d ]
+ [ 0x2c 0x7a 0x5a 0x44f ]
+ [ 0x2d 0x78 0x58 0x447 ]
+ [ 0x2e 0x63 0x43 0x441 ]
+ [ 0x2f 0x76 0x56 0x43c ]
+ [ 0x30 0x62 0x42 0x438 ]
+ [ 0x31 0x6e 0x4e 0x442 ]
+ [ 0x32 0x6d 0x4d 0x44c ]
+ [ 0x33 0x2c 0x3c 0x431 ]
+ [ 0x34 0x2e 0x3e 0x44e ]
+ [ 0x56 0x3c 0x3e 0x7c ]
+] def
+
+
+/keymap.sk [
+ [ 0x02 0x31 0x21 0x2b ]
+ [ 0x03 0x32 0x40 0x13e ]
+ [ 0x04 0x33 0x23 0x161 ]
+ [ 0x05 0x34 0x24 0x10d ]
+ [ 0x06 0x35 0x25 0x165 ]
+ [ 0x07 0x36 0x5e 0x17e ]
+ [ 0x08 0x37 0x26 0xfd ]
+ [ 0x09 0x38 0x2a 0xe1 ]
+ [ 0x0a 0x39 0x28 0xed ]
+ [ 0x0b 0x30 0x29 0xe9 ]
+ [ 0x0c 0x2d 0x5f 0x3d ]
+ [ 0x15 0x7a 0x5a 0x00 ]
+ [ 0x1a 0x5b 0x7b 0xfa ]
+ [ 0x1b 0x5d 0x7d 0xe4 ]
+ [ 0x27 0x3b 0x3a 0xf4 ]
+ [ 0x28 0x27 0x22 0xa7 ]
+ [ 0x2b 0x5c 0x7c 0x148 ]
+ [ 0x2c 0x79 0x59 0x00 ]
+ [ 0x2e 0x63 0x43 0x00 ]
+ [ 0x35 0x2f 0x3f 0x2d ]
+ [ 0x56 0x3c 0x3e 0x7c ]
+] def
+
+
+% must not be empty
+/keymaps [
+ [ "cs" "\u010ce\u0161tina" keymap.cs ]
+ [ "en" "English" .undef ]
+ [ "fr" "Fran\u00e7ais" keymap.fr ]
+ [ "de" "Deutsch" keymap.de ]
+ [ "it" "Italiano" keymap.it ]
+ [ "jp" "\u65e5\u672c\u8a9e" keymap.jp ]
+ [ "ru" "\u0420\u0443\u0441\u0441\u043a\u0438\u0439" keymap.ru ]
+ [ "sk" "Sloven\u010dina" keymap.sk ]
+ [ "es" "Espa\u00f1ol" keymap.es ]
+] def
+
+% default entry
+/keymaps.default 1 def
+
+
diff --git a/themes/SuSE/kroete.data b/themes/SuSE/kroete.data
new file mode 100644
index 0000000..448764b
--- /dev/null
+++ b/themes/SuSE/kroete.data
Binary files differ
diff --git a/themes/SuSE/locale.inc b/themes/SuSE/locale.inc
new file mode 100644
index 0000000..d56d8a2
--- /dev/null
+++ b/themes/SuSE/locale.inc
@@ -0,0 +1,62 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Handle translations.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Set language.
+%
+% ( language ) ==> ( true|false )
+%
+/setlang {
+ config.lang over eq { pop false return } if
+
+ /config.lang exch def
+
+ /help.messages .undef def
+
+ findtexts
+
+ true
+} def
+
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Find texts for current language.
+%
+% ( ) ==> ( )
+%
+/findtexts {
+ 16 string dup config.lang "texts.%s" 2 index sprintf findfile exch free
+ dup .undef eq {
+ config.lang length 2 gt {
+ pop 16 string
+ dup config.lang 1 get config.lang 0 get "texts.%c%c" 3 index sprintf findfile exch free
+ dup {
+ /config.lang 2 string
+ config.lang 1 get config.lang 0 get "%c%c" 3 index sprintf
+ def
+ } if
+ } if
+ } if
+ dup .undef eq { pop "texts.en" findfile } if
+ dup .undef eq { pop 0 cvp } if
+ cvs
+ /ft.len over cvp length def
+ /ft.str exch def
+ /ft.pos 0 def
+
+ texts {
+ ft.pos ft.str length add ft.len lt {
+ ft.str def
+ /ft.str ft.str dup length 1 add /ft.pos over ft.pos add def add def
+ } {
+ "No Texts!" def
+ } ifelse
+ } forall
+} def
+
+
diff --git a/themes/SuSE/main.inc b/themes/SuSE/main.inc
new file mode 100644
index 0000000..3c0adfe
--- /dev/null
+++ b/themes/SuSE/main.inc
@@ -0,0 +1,221 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Main menu (boot entry + boot options + panel).
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Create new main window.
+%
+% ( ) ==> ( window )
+%
+/window.main {
+ widget.size array
+ dup .type t_main put
+ dup .font font.normal put
+ dup .ed.font font.normal put
+ dup .color.fg boot.text.normal put
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Initialize main window.
+%
+% ( window ) ==> ( )
+%
+/main.init {
+ pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Redraw main window.
+% (E.g. after selecting a new language.)
+%
+% ( window ) ==> ( )
+%
+/main.redraw {
+ boot.text.options setcolor
+ window.current .font get setfont
+ frame3.pos moveto
+ currentpoint 200 fontheight image
+ txt_bootoptions show
+
+ redrawmenu
+ /keepbootoptions 1 def
+ menu.entry true MenuSelect
+ /keepbootoptions .undef def
+
+ panel.show
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Draw main window.
+%
+% ( window ) ==> ( )
+%
+/main.show {
+ window.push
+
+ /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
+
+ frame2.pos moveto prog_frame_color dup prog_frame_color2 frame2.size drawborder3
+
+ menu.visible.entries menu.texts length lt menu.scrollbar and {
+ /menu.bar.width frame1.size pop frame4.size pop sub def
+
+ -1 settransparentcolor
+
+ frame4.pos moveto black dup frame4.size drawborder
+ frame4.pos moveto
+ ms.up ms.size image
+ frame4.pos moveto frame4.size exch pop 0 exch ms.size exch pop 0 add sub rmoveto
+ ms.down ms.size image
+
+ /menu.sb.x frame4.pos pop 1 add def
+ /menu.sb.y frame4.pos exch pop 22 add def
+ /menu.sb.width frame4.size pop 2 sub def
+ /menu.sb.height frame4.size exch pop 22 2 mul 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.text.options setcolor
+
+ window.current .font get setfont
+
+ frame3.pos moveto
+ txt_bootoptions show
+
+ /boot.ed.width frame2.size pop 10 sub def
+ /boot.ed.height fontheight 2 add def
+
+ /boot.ed [
+ frame2.pos exch 5 add exch 4 add
+ over over moveto boot.ed.width boot.ed.height savescreen
+ boot.buf
+ boot.buf.size
+ 0
+ 0
+ 0
+ ] def
+
+ window.current .ed boot.ed put
+
+ redrawmenu
+ menu.entry true MenuSelect
+
+ % find default splash mode
+ 0 1 splash.options length 1 sub {
+ splash.options over get menu.args menu.entry get exch strstr {
+ /splash.default exch def
+ } {
+ pop
+ } ifelse
+ } for
+
+ panel.init
+
+ "main" help.setcontext
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Handle keyboard input.
+%
+% ( key_in ) ==> ( key_out )
+%
+/main.input {
+ dup 0 eq { return } if
+
+ % handle panel entries
+ panel.input
+
+ dup keyF10 eq {
+ power_off
+ pop 0
+ } if
+
+ dup keyEsc eq { exit_popup pop 0 } if
+
+ dup keyEnter eq {
+ /window.action actStart def
+ pop 0
+ } if
+
+ dup keyUp eq {
+ menu.entry 0 gt {
+ menu.entry false MenuSelect
+ menu.entry menu.shift eq {
+ /menu.shift menu.shift 1 sub def redrawmenu
+ } if
+ /menu.entry menu.entry 1 sub def
+ menu.entry true MenuSelect
+ } if
+ pop 0
+ } if
+
+ dup keyDown eq {
+ menu.entry menu.texts length 1 sub lt {
+ menu.entry false 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 true MenuSelect
+ } if
+ pop 0
+ } if
+
+ dup keyPgUp eq {
+ menu.entry 0 gt {
+ menu.entry false MenuSelect
+ /menu.entry 0 def
+ menu.shift 0 ne {
+ /menu.shift 0 def redrawmenu
+ } if
+ menu.entry true MenuSelect
+ } if
+ pop 0
+ } if
+
+ dup keyPgDown eq {
+ menu.entry menu.texts length 1 sub lt {
+ menu.entry false 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 true MenuSelect
+ } if
+ pop 0
+ } if
+
+ dup 0 ne {
+ "opt" help.setcontext
+ } if
+
+} def
+
+
diff --git a/themes/SuSE/panel.inc b/themes/SuSE/panel.inc
new file mode 100644
index 0000000..d952353
--- /dev/null
+++ b/themes/SuSE/panel.inc
@@ -0,0 +1,120 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Panel handling.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Some global vars.
+%
+/panel.text.y 461 def
+/panel.font font.normal def
+/panel.normal black def
+/panel.high fn_color def
+/panel.bg lightgray def
+/panel.border white def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Init panel.
+%
+% ( ) ==> ( )
+%
+/panel.init {
+
+ % define panel layout
+ /panel [
+
+ % [ key x label show_func width_func update_func init_func ]
+
+ [ keyF1 0 "F1" /panel.help /panel.help.width /panel.help.update .undef ]
+
+ syslinux {
+
+ [ keyF2 0 "F2" /panel.video /panel.video.width /panel.video.update /video.init ]
+ [ keyF3 0 "F3" /panel.install /panel.install.width /panel.install.update /install.init ]
+ [ keyF4 0 "F4" /panel.keytable /panel.keytable.width /panel.keytable.update /keytable.init ]
+ [ keyF5 0 "F5" /panel.splash /panel.splash.width /panel.splash.update /splash.init ]
+ [ keyF6 0 "F6" /panel.dud /panel.dud.width /panel.dud.update .undef ]
+
+ } {
+
+ [ keyF2 0 "F2" /panel.keytable /panel.keytable.width /panel.keytable.update /keytable.init ]
+ [ keyF3 0 "F3" /panel.splash /panel.splash.width /panel.splash.update /splash.init ]
+ "profiles" findfile dup {
+ /profile.data exch def
+ [ keyF4 0 "F4" /panel.profile /panel.profile.width /panel.profile.update /profile.init ]
+ } { pop } ifelse
+
+ } ifelse
+
+ ] def
+
+ % initialize all
+ panel { 6 get dup .undef ne { exec } { pop } ifelse } forall
+
+ panel.show
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show panel.
+%
+% ( ) ==> ( )
+%
+/panel.show {
+ panel.font setfont
+
+ panel.bg setcolor
+ 0 panel.text.y 5 sub moveto currentpoint
+ clip.size panel.text.y 5 sub sub fillrect
+ moveto
+ panel.border setcolor
+ currentpoint exch pop clip.size pop 1 sub exch
+ lineto
+
+ % don't change xmenu
+ /xmenu xmenu
+
+ /panel.x 0 def
+ panel { dup {
+ dup 1 panel.x put
+ dup 4 get exec over 2 get strsize pop add 20 add panel.x add /panel.x exch def
+ dup 5 get exec
+ } { pop } ifelse } forall
+
+ def
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Handle keyboard input.
+%
+% ( key_in ) ==> ( key_out )
+%
+/panel.input {
+ panel { dup {
+ dup 0 get 2 index eq { 3 get exec pop 0 exit } { pop } ifelse
+ } { pop } ifelse } forall
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Draw panel entry label and move to text field.
+%
+% ( panel ) => ( )
+%
+/panel.text.moveto {
+ /panel.tmp.x over 1 get 10 add def
+ /panel.tmp.F exch 2 get def
+
+ panel.tmp.x panel.text.y moveto
+ panel.high setcolor panel.tmp.F show
+ panel.normal setcolor
+
+ 6 0 rmoveto
+} def
+
+
diff --git a/themes/SuSE/po/Makefile b/themes/SuSE/po/Makefile
new file mode 100644
index 0000000..d0f0914
--- /dev/null
+++ b/themes/SuSE/po/Makefile
@@ -0,0 +1,14 @@
+POFILES = $(wildcard *.po)
+TEXTS = $(addprefix texts.,$(basename $(wildcard *.po)))
+
+all: text.inc $(TEXTS)
+
+texts.%: %.po text.inc
+ bin/po2txt $< >$@
+
+# texts.en uses msgids from bootloader.pot
+texts.en text.inc: bootloader.pot
+ bin/po2txt $< >texts.en
+
+clean:
+ rm -f text.inc texts.* *~
diff --git a/themes/SuSE/po/README b/themes/SuSE/po/README
new file mode 100644
index 0000000..a27800a
--- /dev/null
+++ b/themes/SuSE/po/README
@@ -0,0 +1,24 @@
+boot loader translations
+------------------------
+
+o How do I add a new text?
+
+ - Use the gfxboot/po/bin/add_text script; example:
+
+ add_text help 'Help'
+
+ This will define txt_help; the 'txt_' prefix is optional.
+
+o How do I remove a text that's no longer needed?
+
+ - Use the gfxboot/po/bin/rm_text script; example:
+
+ rm_text help
+
+ This will remove txt_help; the removed lines are stored in the 'old'
+ directory.
+
+o How do I add a new language?
+
+ - Copy bootloader.pot to <lang>.po. Remember to get <lang>.po translated.
+
diff --git a/themes/SuSE/po/bin/add_text b/themes/SuSE/po/bin/add_text
new file mode 100755
index 0000000..0dd99b1
--- /dev/null
+++ b/themes/SuSE/po/bin/add_text
@@ -0,0 +1,54 @@
+#! /usr/bin/perl
+
+# add a new text to *.po files
+
+die "usage: add_text [-c comment] id text_line1 text_line2 ... \nexample:\n add_text MENU_LANG Language\n" if @ARGV < 2;
+
+if($ARGV[0] eq '-c') {
+ shift;
+ $comment = shift;
+}
+
+$id = shift;
+@texts = @ARGV;
+
+$id =~ s/^txt_//;
+
+$_ = join '', @texts;
+
+push @l, "# $comment\n" if $comment;
+push @l, "#. txt_$id\n";
+push @l, "#, c-format\n" if /%/;
+
+if(@texts == 1) {
+ push @l, "msgid \"$texts[0]\"\n"
+}
+else {
+ push @l, "msgid \"\"\n";
+ for (@texts) { push @l, "\"$_\"\n" }
+}
+
+push @l, "msgstr \"\"\n";
+push @l, "\n";
+
+print @l;
+
+print STDERR "Should this entry be added to all *.po files? [Y/n]\n";
+
+$_ = <STDIN>;
+
+chomp;
+
+$_ = "\L$_";
+
+exit unless $_ eq '' || $_ eq 'y';
+
+print "ok\n";
+
+for $f ("bootloader.pot", <*.po>) {
+ if(open F, ">>$f") {
+ print F @l;
+ close F;
+ }
+}
+
diff --git a/themes/SuSE/po/bin/po2txt b/themes/SuSE/po/bin/po2txt
new file mode 100755
index 0000000..1003cae
--- /dev/null
+++ b/themes/SuSE/po/bin/po2txt
@@ -0,0 +1,154 @@
+#! /usr/bin/perl
+
+# convert *.po files to texts.* files suitable for gfxboot
+# usage: po2txt lang.po >texts.lang
+# Note: en.po ist treated specially!
+
+sub read_texts;
+sub join_msg;
+
+for $lang (@ARGV) {
+ $lang = 'en' if $lang eq 'bootloader.pot';
+ $lang =~ s/\.po$//;
+ read_texts $lang;
+}
+
+
+sub read_texts
+{
+ local $_;
+
+ my ($lang, @f, $txt, $context, $t, $p, $ids, $file);
+
+ $lang = shift;
+
+ $file = "$lang.po";
+ $file = 'bootloader.pot' if $lang eq 'en';
+
+ if($lang eq 'en') {
+ $ids = 1;
+ }
+
+ open F, $file;
+ @f = (<F>);
+ close F;
+
+ $_ = $lang;
+ s/.*\///;
+
+ for (@f) {
+ if(/^\s*#\.\s*(txt_\S+)/) {
+ if($txt) {
+ @msgstr = @msgid if $ids || join_msg(\@msgstr) eq "";
+ $txts{$txt} = join_msg(\@msgstr);
+ }
+
+ $txt = $1;
+
+ undef @msgid;
+ undef @msgstr;
+ undef $context;
+ next;
+ }
+
+ next if /^\s*#.*|^\s*$/;
+
+ if(/^\s*msgid\s*(\".*\")\s*$/) {
+ push @msgid, $1 unless $1 eq '""';
+ $context = 1;
+ next;
+ }
+
+ if(/^\s*msgstr\s*(\".*\")\s*$/) {
+ push @msgstr, $1 unless $1 eq '""';
+ $context = 2;
+ next;
+ }
+
+ if(/^\s*(\".*\")\s*$/) {
+ if($context == 1) {
+ push @msgid, $1;
+ }
+ elsif($context == 2) {
+ push @msgstr, $1;
+ }
+ else {
+ die "format oops in ${lang}.po: $_"
+ }
+ }
+ }
+
+ if($txt) {
+ @msgstr = @msgid if $ids || join_msg(\@msgstr) eq "";
+ $txts{$txt} = join_msg(\@msgstr);
+ }
+
+ @txts = sort keys %txts;
+
+ for (@txts) {
+ $txt = $txts{$_};
+ $txt =~ s/\\\\/\\/g;
+ $txt =~ s/\\n/\n/g;
+ print "$txt\x00"
+ }
+
+ if($ids) {
+ open W, ">text.inc";
+ print W "%\n% This file is generated automatically. Editing it is pointless.\n%\n\n";
+ print W "/texts [\n";
+ $p = pop @txts;
+ for (@txts) { print W " /$_\n" }
+ print W " /$p\n] def\n";
+ close W;
+ }
+ else {
+ open F, "text.inc";
+ for (<F>) {
+ if(/\s+\/(txt_\S+)/) {
+ $txt_ref{$1} = undef;
+ }
+ }
+ close F;
+ for (@txts) {
+ $txt_list{$_}++;
+ $txt_multi{$_} = 1 if $txt_list{$_} > 1;
+ }
+ for (@txts) {
+ $txt_unknown{$_} = 1 unless exists $txt_ref{$_};
+ }
+ for (keys %txt_ref) {
+ $txt_miss{$_} = 1 unless exists $txt_list{$_};
+ }
+
+ if(defined(%txt_miss) || defined(%txt_unknown) || defined(%txt_multi)) {
+ print STDERR "$lang:\n";
+ for (sort keys %txt_miss) {
+ print STDERR " missing: $_\n"
+ }
+ for (sort keys %txt_unknown) {
+ print STDERR " unknown: $_\n"
+ }
+ for (sort keys %txt_multi) {
+ print STDERR " multi: $_\n"
+ }
+ }
+ }
+
+}
+
+
+sub join_msg
+{
+ local $_;
+ my ($s, $msg, $m);
+
+ $msg = shift;
+
+ for $s (@{$msg}) {
+ $_ = $s;
+ s/^\"(.*)\"$/$1/;
+ $m .= $_;
+ }
+
+ return $m;
+}
diff --git a/themes/SuSE/po/bin/rm_text b/themes/SuSE/po/bin/rm_text
new file mode 100755
index 0000000..9b96555
--- /dev/null
+++ b/themes/SuSE/po/bin/rm_text
@@ -0,0 +1,63 @@
+#! /usr/bin/perl
+
+# remove a text from *.po files
+
+sub drop;
+
+die "usage: rm_text id\n" if @ARGV != 1;
+
+$id = shift;
+$id = "txt_$id" unless $id =~ /^txt_/;
+
+mkdir old, 0755;
+
+for $f ("bootloader.pot", <*.po>) {
+ if(open F, $f) {
+ @f = <F>;
+ close F;
+
+ ( $new, $old ) = drop @f;
+ if(open F, ">>old/$f") {
+ print F @$old;
+ close F;
+
+ open F, ">$f";
+ print F @$new;
+ close F;
+ }
+ }
+}
+
+
+sub drop
+{
+ local $_;
+ my (@f, @g, $drop_it, @d);
+
+ for (@_) {
+ push @g, $_;
+ $drop_it = 1 if /^#\.\s*${id}\s*$/;
+ if(/^\s*$/) {
+ if($drop_it) {
+ push @d, @g;
+ }
+ else {
+ push @f, @g;
+ }
+ undef $drop_it;
+ undef @g;
+ }
+ }
+
+ if(@g) {
+ if($drop_it) {
+ push @d, @g;
+ }
+ else {
+ push @f, @g;
+ }
+ }
+
+ return ( \@f, \@d );
+}
+
diff --git a/themes/SuSE/po/bootloader.pot b/themes/SuSE/po/bootloader.pot
new file mode 100644
index 0000000..8e94aa6
--- /dev/null
+++ b/themes/SuSE/po/bootloader.pot
@@ -0,0 +1,229 @@
+# LANGUAGE translations for boot loader
+# Copyright (C) 2004 SUSE LINUX AG
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: bootloader\n"
+"PO-Revision-Date: 2004-03-01 12:00+0200\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <i18n@suse.de>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# ok button label
+#. txt_ok
+msgid "OK"
+msgstr ""
+
+# cancel button label
+#. txt_cancel
+msgid "Cancel"
+msgstr ""
+
+# reboot button label
+#. txt_reboot
+msgid "Reboot"
+msgstr ""
+
+# continue button label
+#. txt_continue
+msgid "Continue"
+msgstr ""
+
+#. txt_install
+msgid "Installation"
+msgstr ""
+
+#. txt_manual_install
+msgid "Manual Installation"
+msgstr ""
+
+#. txt_noacpi_install
+msgid "Installation - ACPI Disabled"
+msgstr ""
+
+#. txt_safe_install
+msgid "Installation - Safe Settings"
+msgstr ""
+
+#. txt_safe_linux
+msgid "Linux - Safe Settings"
+msgstr ""
+
+#. txt_boot_harddisk
+msgid "Boot from Hard Disk"
+msgstr ""
+
+#. txt_rescue
+msgid "Rescue System"
+msgstr ""
+
+#. txt_memtest
+msgid "Memory Test"
+msgstr ""
+
+#. txt_bootoptions
+msgid "Boot Options"
+msgstr ""
+
+# window title for exit dialog
+#. txt_exit_title (see txt_exit_dialog)
+msgid "Good bye..."
+msgstr ""
+
+#. txt_exit_dialog
+msgid ""
+"You are leaving the graphical boot menu and\n"
+"starting the text mode interface."
+msgstr ""
+
+#. txt_help
+msgid "Help"
+msgstr ""
+
+# window title for kernel loading (see txt_load_kernel)
+#. txt_load_kernel_title
+msgid "Starting..."
+msgstr ""
+
+# Keep the three newlines!
+#. txt_load_kernel
+msgid "Loading Linux Kernel\n\n\n"
+msgstr ""
+
+# Keep the three newlines!
+#. txt_load_memtest
+msgid "Loading memtest86\n\n\n"
+msgstr ""
+
+# info box title
+#. txt_info_title
+msgid "Boot loader"
+msgstr ""
+
+# error box title
+#. txt_error_title
+msgid "I/O error"
+msgstr ""
+
+# boot disk change dialog title
+#. txt_change_disk_title
+msgid "Change Boot Disk"
+msgstr ""
+
+#. txt_insert_disk
+#, c-format
+msgid "Please insert Boot Disk %u."
+msgstr ""
+
+#. txt_insert_disk2
+#, c-format
+msgid ""
+"This is Boot Disk %u.\n"
+"Please insert Boot Disk %u."
+msgstr ""
+
+#. txt_insert_disk3
+#, c-format
+msgid ""
+"This is not a SUSE LINUX 9.1 Boot Disk.\n"
+"Please insert Boot Disk %u."
+msgstr ""
+
+# password dialog title
+#. txt_password_title
+msgid "Password"
+msgstr ""
+
+# Keep the newlines and spaces after ':'!
+#. txt_password
+msgid "Please enter your password: \n\n\n"
+msgstr ""
+
+#. txt_dud_ready
+msgid "Please get your Driver Update Floppy ready."
+msgstr ""
+
+# dvd warning title
+#. txt_dvd_warning_title
+msgid "You're almost there..."
+msgstr ""
+
+# Keep the newlines!
+#. txt_dvd_warning
+msgid ""
+"\n\nIt appears that the system booted from the second side of the DVD.\n"
+"If so, turn the DVD over and try again."
+msgstr ""
+
+#. txt_dvd_warning2
+msgid ""
+"This is a two-sided DVD. You have booted from the second side.\n\n"
+"Please turn the DVD over, then continue."
+msgstr ""
+
+# power off dialog title
+#. txt_power_off_title
+msgid "Power off"
+msgstr ""
+
+#. txt_power_off
+msgid "Do you want to halt the system now?"
+msgstr ""
+
+#. txt_driver_update
+msgid "Driver Update"
+msgstr ""
+
+# menu entry for hard disk installation
+#. txt_harddisk
+msgid "Hard Disk"
+msgstr ""
+
+# dialog title for hard disk installation
+#. txt_harddisk_title
+msgid "Hard Disk Installation"
+msgstr ""
+
+#. txt_hd_diskdevice
+msgid "Disk Device (scan all disks if empty)\n"
+msgstr ""
+
+#. txt_directory
+msgid "Directory\n"
+msgstr ""
+
+# dialog title for ftp installation
+#. txt_ftp_title
+msgid "FTP Installation"
+msgstr ""
+
+#. txt_server
+msgid "Server\n"
+msgstr ""
+
+#. txt_password
+msgid "Password\n"
+msgstr ""
+
+# label for ftp user input
+#. txt_user1
+msgid "User (anonymous login if empty)\n"
+msgstr ""
+
+# dialog title for nfs installation
+#. txt_nfs_title
+msgid "NFS Installation"
+msgstr ""
+
+# label for smb user input
+#. txt_user2
+msgid "User (using \"guest\" if empty)\n"
+msgstr ""
+
+# dialog title for smb installation
+#. txt_smb_title
+msgid "SMB (Windows Share) Installation"
+msgstr ""
+
diff --git a/themes/SuSE/po/cs.po b/themes/SuSE/po/cs.po
new file mode 100644
index 0000000..c0e09dc
--- /dev/null
+++ b/themes/SuSE/po/cs.po
@@ -0,0 +1,244 @@
+# translation of bootloader.po to cs_CZ
+# LANGUAGE translations for boot loader
+# Copyright (C) 2004 SUSE LINUX AG
+# Klara Cihlarova <koty@seznam.cz>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: bootloader\n"
+"PO-Revision-Date: 2004-03-08 11:03+0100\n"
+"Last-Translator: Klara Cihlarova <koty@seznam.cz>\n"
+"Language-Team: cs_CZ <suse@suse.cz>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.3\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+# ok button label
+#. txt_ok
+msgid "OK"
+msgstr "OK"
+
+# cancel button label
+#. txt_cancel
+msgid "Cancel"
+msgstr "Zrušit"
+
+# reboot button label
+#. txt_reboot
+msgid "Reboot"
+msgstr "Restartovat"
+
+# continue button label
+#. txt_continue
+msgid "Continue"
+msgstr "Pokračovat"
+
+#. txt_install
+msgid "Installation"
+msgstr "Instalace"
+
+#. txt_manual_install
+msgid "Manual Installation"
+msgstr "Ruční instalace"
+
+#. txt_noacpi_install
+msgid "Installation - ACPI Disabled"
+msgstr "Instalace - bez ACPI"
+
+#. txt_safe_install
+msgid "Installation - Safe Settings"
+msgstr "Instalace - bezpečné nastavení"
+
+#. txt_safe_linux
+msgid "Linux - Safe Settings"
+msgstr "Linux - bezpečné nastavení"
+
+#. txt_boot_harddisk
+msgid "Boot from Hard Disk"
+msgstr "Spustit z disku"
+
+#. txt_rescue
+msgid "Rescue System"
+msgstr "Záchranný systém"
+
+#. txt_memtest
+msgid "Memory Test"
+msgstr "Test paměti"
+
+#. txt_bootoptions
+msgid "Boot Options"
+msgstr "Parametry startu"
+
+# window title for exit dialog
+#. txt_exit_title (see txt_exit_dialog)
+msgid "Good bye..."
+msgstr "Na shledanou..."
+
+#. txt_exit_dialog
+msgid ""
+"You are leaving the graphical boot menu and\n"
+"starting the text mode interface."
+msgstr ""
+"Opouštíte grafickou startovací nabídku\n"
+"a spouštíte textový režim."
+
+#. txt_help
+msgid "Help"
+msgstr "Nápověda"
+
+# window title for kernel loading (see txt_load_kernel)
+#. txt_load_kernel_title
+msgid "Starting..."
+msgstr "Startuji..."
+
+# Keep the three newlines!
+#. txt_load_kernel
+msgid "Loading Linux kernel\n\n\n"
+msgstr "Zavádím linuxové jádro\n\n\n"
+
+# Keep the three newlines!
+#. txt_load_memtest
+msgid "Loading memtest86\n\n\n"
+msgstr "Zavádím memtest86\n\n\n"
+
+# info box title
+#. txt_info_title
+msgid "Boot loader"
+msgstr "Zavaděč"
+
+# error box title
+#. txt_error_title
+msgid "I/O error"
+msgstr "Chyba I/O"
+
+# boot disk change dialog title
+#. txt_change_disk_title
+msgid "Change Boot Disk"
+msgstr "Změnit startovací disk"
+
+#. txt_insert_disk
+#, c-format
+msgid "Please insert Boot Disk %u."
+msgstr "Vložte disk %u."
+
+#. txt_insert_disk2
+#, c-format
+msgid ""
+"This is Boot Disk %u.\n"
+"Please insert Boot Disk %u."
+msgstr ""
+"Toto je disk %u.\n"
+"Vložte prosím disk %u."
+
+#. txt_insert_disk3
+#, c-format
+msgid ""
+"This is not a SUSE LINUX 9.1 Boot Disk.\n"
+"Please insert Boot Disk %u."
+msgstr ""
+"Toto není startovací disk SUSE LINUXu 9.1.\n"
+"Vložte startovací disk %u."
+
+# password dialog title
+#. txt_password_title
+msgid "Password"
+msgstr "Heslo"
+
+# Keep the newlines and spaces after ':'!
+#. txt_password
+msgid "Please enter your password: \n\n\n"
+msgstr "Prosím zadejte heslo: \n\n\n"
+
+#. txt_dud_ready
+msgid "Please get your Driver Update Floppy ready."
+msgstr "Připravte si disketu s ovladači."
+
+# dvd warning title
+#. txt_dvd_warning_title
+msgid "You're almost there..."
+msgstr ""
+
+# Keep the newlines!
+#. txt_dvd_warning
+msgid ""
+"\n\nIt appears that the system booted from the second side of the DVD.\n"
+"If so, turn the DVD over and try again."
+msgstr ""
+"\n\nToto se obvykle stává, když chcete systém spouštět z druhé strany DVD."
+"\n"
+"Obraťte DVD a opakujte akci."
+
+#. txt_dvd_warning2
+msgid ""
+"This is a two-sided DVD. You have booted from the second side.\n\n"
+"Please turn the DVD over, then continue."
+msgstr ""
+"Toto je oboustranné DVD. Spouštíte systém z druhé strany DVD.\n\n"
+"Obraťte prosím DVD a pokračujte."
+
+# power off dialog title
+#. txt_power_off_title
+msgid "Power off"
+msgstr "Vypnout"
+
+#. txt_power_off
+msgid "Do you want to halt the system now?"
+msgstr "Chcete nyní vypnout systém?"
+
+#. txt_driver_update
+msgid "Driver Update"
+msgstr ""
+
+# menu entry for hard disk installation
+#. txt_harddisk
+msgid "Hard Disk"
+msgstr ""
+
+# dialog title for hard disk installation
+#. txt_harddisk_title
+msgid "Hard Disk Installation"
+msgstr ""
+
+#. txt_hd_diskdevice
+msgid "Disk Device (scan all disks if empty)\n"
+msgstr ""
+
+#. txt_directory
+msgid "Directory\n"
+msgstr ""
+
+# dialog title for ftp installation
+#. txt_ftp_title
+msgid "FTP Installation"
+msgstr ""
+
+#. txt_server
+msgid "Server\n"
+msgstr ""
+
+#. txt_password
+msgid "Password\n"
+msgstr ""
+
+# label for ftp user input
+#. txt_user1
+msgid "User (anonymous login if empty)\n"
+msgstr ""
+
+# dialog title for nfs installation
+#. txt_nfs_title
+msgid "NFS Installation"
+msgstr ""
+
+# label for smb user input
+#. txt_user2
+msgid "User (using \"guest\" if empty)\n"
+msgstr ""
+
+# dialog title for smb installation
+#. txt_smb_title
+msgid "SMB (Windows Share) Installation"
+msgstr ""
+
diff --git a/themes/SuSE/po/de.po b/themes/SuSE/po/de.po
new file mode 100644
index 0000000..43e18b9
--- /dev/null
+++ b/themes/SuSE/po/de.po
@@ -0,0 +1,242 @@
+# translation of de.po to German
+# LANGUAGE translations for boot loader
+# Copyright (C) 2004 SUSE LINUX AG
+# Antje Faber <afaber@suse.de>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: de\n"
+"PO-Revision-Date: 2004-03-09 18:37GMT\n"
+"Last-Translator: Antje Faber <afaber@suse.de>\n"
+"Language-Team: German <i18n@suse.de>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.0.2\n"
+
+# ok button label
+#. txt_ok
+msgid "OK"
+msgstr "Ok"
+
+# cancel button label
+#. txt_cancel
+msgid "Cancel"
+msgstr "Verwerfen"
+
+# reboot button label
+#. txt_reboot
+msgid "Reboot"
+msgstr "Neustart"
+
+# continue button label
+#. txt_continue
+msgid "Continue"
+msgstr "Fortfahren"
+
+#. txt_install
+msgid "Installation"
+msgstr "Installation"
+
+#. txt_manual_install
+msgid "Manual Installation"
+msgstr "Manuelle Installation"
+
+#. txt_noacpi_install
+msgid "Installation - ACPI Disabled"
+msgstr "Installation - ACPI deaktiviert"
+
+#. txt_safe_install
+msgid "Installation - Safe Settings"
+msgstr "Installation - Sichere Einstellungen"
+
+#. txt_safe_linux
+msgid "Linux - Safe Settings"
+msgstr "Linux - Sichere Einstellungen"
+
+#. txt_boot_harddisk
+msgid "Boot from Hard Disk"
+msgstr "Von Festplatte booten"
+
+#. txt_rescue
+msgid "Rescue System"
+msgstr "Rettungssystem"
+
+#. txt_memtest
+msgid "Memory Test"
+msgstr "Speichertest"
+
+#. txt_bootoptions
+msgid "Boot Options"
+msgstr "Bootoptionen"
+
+# window title for exit dialog
+#. txt_exit_title (see txt_exit_dialog)
+msgid "Good bye..."
+msgstr "Tschüs..."
+
+#. txt_exit_dialog
+msgid ""
+"You are leaving the graphical boot menu and\n"
+"starting the text mode interface."
+msgstr ""
+"Sie verlassen das grafische Bootmenü und\n"
+"kommen in den Textmodus."
+
+#. txt_help
+msgid "Help"
+msgstr "Hilfe"
+
+# window title for kernel loading (see txt_load_kernel)
+#. txt_load_kernel_title
+msgid "Starting..."
+msgstr "Starten..."
+
+# Keep the three newlines!
+#. txt_load_kernel
+msgid "Loading Linux Kernel\n\n\n"
+msgstr "Laden des Linux-Kernels\n\n\n"
+
+# Keep the three newlines!
+#. txt_load_memtest
+msgid "Loading memtest86\n\n\n"
+msgstr "Laden von memtest86\n\n\n"
+
+# info box title
+#. txt_info_title
+msgid "Boot loader"
+msgstr "Bootloader"
+
+# error box title
+#. txt_error_title
+msgid "I/O error"
+msgstr "E/A-Fehler"
+
+# boot disk change dialog title
+#. txt_change_disk_title
+msgid "Change Boot Disk"
+msgstr "Bootdiskette wechseln"
+
+#. txt_insert_disk
+#, c-format
+msgid "Please insert Boot Disk %u."
+msgstr "Legen Sie Bootdiskette %u ein."
+
+#. txt_insert_disk2
+#, c-format
+msgid ""
+"This is Boot Disk %u.\n"
+"Please insert Boot Disk %u."
+msgstr ""
+"Dies ist die Bootdiskette %u.\n"
+"Legen Sie die Bootdiskette %u ein."
+
+#. txt_insert_disk3
+#, c-format
+msgid ""
+"This is not a SUSE LINUX 9.1 Boot Disk.\n"
+"Please insert Boot Disk %u."
+msgstr ""
+"Dies ist keine SUSE LINUX 9.1-Bootdiskette.\n"
+"Legen Sie die Bootdiskette %u ein."
+
+# password dialog title
+#. txt_password_title
+msgid "Password"
+msgstr "Passwort"
+
+# Keep the newlines and spaces after ':'!
+#. txt_password
+msgid "Please enter your password: \n\n\n"
+msgstr "Bitte geben Sie Ihr Passwort ein: \n\n\n"
+
+#. txt_dud_ready
+msgid "Please get your Driver Update Floppy ready."
+msgstr "Halten Sie Ihre Treiber-Update-Diskette bereit."
+
+# dvd warning title
+#. txt_dvd_warning_title
+msgid "You're almost there..."
+msgstr "Sie haben es fast geschafft."
+
+# Keep the newlines!
+#. txt_dvd_warning
+msgid ""
+"\n\nIt appears that the system booted from the second side of the DVD.\n"
+"If so, turn the DVD over and try again."
+msgstr ""
+"\n\nEs scheint, dass das System von der zweiten Seite der DVD gestartet wurde.\n"
+"Falls dies zutrifft, drehen Sie die DVD um, und versuchen Sie es erneut."
+
+#. txt_dvd_warning2
+msgid ""
+"This is a two-sided DVD. You have booted from the second side.\n\n"
+"Please turn the DVD over, then continue."
+msgstr ""
+"Dies ist eine zweiseitige DVD. Sie haben von der zweiten Seite gebootet.\n\n"
+"Drehen Sie die DVD um, und fahren Sie dann fort."
+
+# power off dialog title
+#. txt_power_off_title
+msgid "Power off"
+msgstr "Ausschalten"
+
+#. txt_power_off
+msgid "Do you want to halt the system now?"
+msgstr "Wollen Sie das System nun anhalten?"
+
+#. txt_driver_update
+msgid "Driver Update"
+msgstr "Treiber-Update"
+
+# menu entry for hard disk installation
+#. txt_harddisk
+msgid "Hard Disk"
+msgstr "Festplatte"
+
+# dialog title for hard disk installation
+#. txt_harddisk_title
+msgid "Hard Disk Installation"
+msgstr "Festplatten-Installation"
+
+#. txt_hd_diskdevice
+msgid "Disk Device (scan all disks if empty)\n"
+msgstr "Plattengerät (Platten scannen, falls leer)\n"
+
+#. txt_directory
+msgid "Directory\n"
+msgstr "Verzeichnis\n"
+
+# dialog title for ftp installation
+#. txt_ftp_title
+msgid "FTP Installation"
+msgstr "FTP-Installation"
+
+#. txt_server
+msgid "Server\n"
+msgstr "Server\n"
+
+#. txt_password
+msgid "Password\n"
+msgstr "Passwort\n"
+
+# label for ftp user input
+#. txt_user1
+msgid "User (anonymous login if empty)\n"
+msgstr "Benutzer (anonymous-Anmeldung, falls leer)\n"
+
+# dialog title for nfs installation
+#. txt_nfs_title
+msgid "NFS Installation"
+msgstr "NFS-Installation"
+
+# label for smb user input
+#. txt_user2
+msgid "User (using \"guest\" if empty)\n"
+msgstr "Benutzer (\"guest\" verwenden, falls leer)\n"
+
+# dialog title for smb installation
+#. txt_smb_title
+msgid "SMB (Windows Share) Installation"
+msgstr "SMB (Windows Share)-Installation"
+
diff --git a/themes/SuSE/po/sk.po b/themes/SuSE/po/sk.po
new file mode 100644
index 0000000..0d03090
--- /dev/null
+++ b/themes/SuSE/po/sk.po
@@ -0,0 +1,243 @@
+# translation of bootloader.po to
+# LANGUAGE translations for boot loader
+# Copyright (C) 2004 SUSE LINUX AG
+# , 2004.
+# , 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: bootloader\n"
+"PO-Revision-Date: 2004-03-08 08:51+0100\n"
+"Last-Translator: \n"
+"Language-Team: <sk@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.3\n"
+
+# ok button label
+#. txt_ok
+msgid "OK"
+msgstr "OK"
+
+# cancel button label
+#. txt_cancel
+msgid "Cancel"
+msgstr "Zrušiť"
+
+# reboot button label
+#. txt_reboot
+msgid "Reboot"
+msgstr "Reštartovať"
+
+# continue button label
+#. txt_continue
+msgid "Continue"
+msgstr "Pokračovať"
+
+#. txt_install
+msgid "Installation"
+msgstr "Inštalácia"
+
+#. txt_manual_install
+msgid "Manual Installation"
+msgstr "Manuálna inštalácia"
+
+#. txt_noacpi_install
+msgid "Installation - ACPI Disabled"
+msgstr "Inštalácia - ACPI vypnuté"
+
+#. txt_safe_install
+msgid "Installation - Safe Settings"
+msgstr "Inštalácia - Bezpečné nastavenie"
+
+#. txt_safe_linux
+msgid "Linux - Safe Settings"
+msgstr "Linux - Bezpečné nastavenie"
+
+#. txt_boot_harddisk
+msgid "Boot from Hard Disk"
+msgstr "Spustiť systém z pevného disku"
+
+#. txt_rescue
+msgid "Rescue System"
+msgstr "Záchranný systém"
+
+#. txt_memtest
+msgid "Memory Test"
+msgstr "Test pamäti"
+
+#. txt_bootoptions
+msgid "Boot Options"
+msgstr "Možnosti štartu"
+
+# window title for exit dialog
+#. txt_exit_title (see txt_exit_dialog)
+msgid "Good bye..."
+msgstr "Dovidenia..."
+
+#. txt_exit_dialog
+msgid ""
+"You are leaving the graphical boot menu and\n"
+"starting the text mode interface."
+msgstr ""
+"Opúšťate grafické menu štartu a spúšťate\n"
+"textové používateľské rozhranie."
+
+#. txt_help
+msgid "Help"
+msgstr "Pomocník"
+
+# window title for kernel loading (see txt_load_kernel)
+#. txt_load_kernel_title
+msgid "Starting..."
+msgstr "Spúšťam..."
+
+# Keep the three newlines!
+#. txt_load_kernel
+msgid "Loading Linux kernel\n\n\n"
+msgstr "Načítavam jadro Linuxu\n\n\n"
+
+# Keep the three newlines!
+#. txt_load_memtest
+msgid "Loading memtest86\n\n\n"
+msgstr "Načítavam memtest86\n\n\n"
+
+# info box title
+#. txt_info_title
+msgid "Boot loader"
+msgstr "Správca štartu"
+
+# error box title
+#. txt_error_title
+msgid "I/O error"
+msgstr "Chyba V/V"
+
+# boot disk change dialog title
+#. txt_change_disk_title
+msgid "Change Boot Disk"
+msgstr "Zmena štartovacej diskety"
+
+#. txt_insert_disk
+#, c-format
+msgid "Please insert Boot Disk %u."
+msgstr "Prosím, vložte štartovaciu disketu %u."
+
+#. txt_insert_disk2
+#, c-format
+msgid ""
+"This is Boot Disk %u.\n"
+"Please insert Boot Disk %u."
+msgstr ""
+"Toto je disketa %u.\n"
+"Prosím, vložte disketu %u."
+
+#. txt_insert_disk3
+#, c-format
+msgid ""
+"This is not a SUSE LINUX 9.1 Boot Disk.\n"
+"Please insert Boot Disk %u."
+msgstr ""
+"Toto nie je štartovacia disketa SUSE LINUX 9.1.\n"
+"Prosím, vložte štartovaciu disketu %u."
+
+# password dialog title
+#. txt_password_title
+msgid "Password"
+msgstr "Heslo"
+
+# Keep the newlines and spaces after ':'!
+#. txt_password
+msgid "Please enter your password: \n\n\n"
+msgstr "Prosím, zadajte heslo: \n\n\n"
+
+#. txt_dud_ready
+msgid "Please get your Driver Update Floppy ready."
+msgstr "Prosím, pripravte si disketu s aktualizovanými ovládačmi."
+
+# dvd warning title
+#. txt_dvd_warning_title
+msgid "You're almost there..."
+msgstr "Už to skoro bude..."
+
+# Keep the newlines!
+#. txt_dvd_warning
+msgid ""
+"\n\nIt appears that the system booted from the second side of the DVD.\n"
+"If so, turn the DVD over and try again."
+msgstr ""
+"\n\nVyzerá to, že ste systém spustili z druhej strany DVD.\n"
+"Ak to tak je, otočte DVD médium a skúste to znovu."
+
+#. txt_dvd_warning2
+msgid ""
+"This is a two-sided DVD. You have booted from the second side.\n\n"
+"Please turn the DVD over, then continue."
+msgstr ""
+"Toto je obojstranné médium DVD. Systém ste spustili z druhej strany.\n\n"
+"Prosím, otočte médium a potom pokračujte."
+
+# power off dialog title
+#. txt_power_off_title
+msgid "Power off"
+msgstr "Vypnúť"
+
+#. txt_power_off
+msgid "Do you want to halt the system now?"
+msgstr "Chcete teraz počítač vypnúť?"
+
+#. txt_driver_update
+msgid "Driver Update"
+msgstr ""
+
+# menu entry for hard disk installation
+#. txt_harddisk
+msgid "Hard Disk"
+msgstr ""
+
+# dialog title for hard disk installation
+#. txt_harddisk_title
+msgid "Hard Disk Installation"
+msgstr ""
+
+#. txt_hd_diskdevice
+msgid "Disk Device (scan all disks if empty)\n"
+msgstr ""
+
+#. txt_directory
+msgid "Directory\n"
+msgstr ""
+
+# dialog title for ftp installation
+#. txt_ftp_title
+msgid "FTP Installation"
+msgstr ""
+
+#. txt_server
+msgid "Server\n"
+msgstr ""
+
+#. txt_password
+msgid "Password\n"
+msgstr ""
+
+# label for ftp user input
+#. txt_user1
+msgid "User (anonymous login if empty)\n"
+msgstr ""
+
+# dialog title for nfs installation
+#. txt_nfs_title
+msgid "NFS Installation"
+msgstr ""
+
+# label for smb user input
+#. txt_user2
+msgid "User (using \"guest\" if empty)\n"
+msgstr ""
+
+# dialog title for smb installation
+#. txt_smb_title
+msgid "SMB (Windows Share) Installation"
+msgstr ""
+
diff --git a/themes/SuSE/splash.pcx b/themes/SuSE/splash.pcx
new file mode 100644
index 0000000..cf35ae6
--- /dev/null
+++ b/themes/SuSE/splash.pcx
Binary files differ
diff --git a/themes/SuSE/system.inc b/themes/SuSE/system.inc
new file mode 100644
index 0000000..54df9d8
--- /dev/null
+++ b/themes/SuSE/system.inc
@@ -0,0 +1,263 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Some basic definitions.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% some key codes
+/keyEsc 0x0000001b def
+/keyEnter 0x0000000d def
+/keyTab 0x00000009 def
+/keyF1 0x3b000000 def
+/keyF2 0x3c000000 def
+/keyF3 0x3d000000 def
+/keyF4 0x3e000000 def
+/keyF5 0x3f000000 def
+/keyF6 0x40000000 def
+/keyF7 0x41000000 def
+/keyF8 0x42000000 def
+/keyF9 0x43000000 def
+/keyF10 0x44000000 def
+/keyF11 0x85000000 def
+/keyF12 0x86000000 def
+/keyHome 0x47000000 def
+/keyUp 0x48000000 def
+/keyPgUp 0x49000000 def
+/keyLeft 0x4b000000 def
+/keyRight 0x4d000000 def
+/keyEnd 0x4f000000 def
+/keyDown 0x50000000 def
+/keyPgDown 0x51000000 def
+/keyIns 0x52000000 def
+/keyDel 0x53000000 def
+/keyShiftF1 0x54000000 def
+/keyShiftF2 0x55000000 def
+/keyShiftF3 0x56000000 def
+/keyShiftF4 0x57000000 def
+/keyShiftF5 0x58000000 def
+/keyShiftF6 0x59000000 def
+/keyShiftF7 0x5a000000 def
+/keyShiftF8 0x5b000000 def
+/keyShiftF9 0x5c000000 def
+/keyShiftF10 0x5d000000 def
+/keyShiftF11 0x87000000 def
+/keyShiftF12 0x88000000 def
+/keyCtrlF1 0x5e000000 def
+/keyCtrlF2 0x5f000000 def
+/keyCtrlF3 0x60000000 def
+/keyCtrlF4 0x61000000 def
+/keyCtrlF5 0x62000000 def
+/keyCtrlF6 0x63000000 def
+/keyCtrlF7 0x64000000 def
+/keyCtrlF8 0x65000000 def
+/keyCtrlF9 0x66000000 def
+/keyCtrlF10 0x67000000 def
+/keyAltF1 0x68000000 def
+/keyAltF2 0x69000000 def
+/keyAltF3 0x6a000000 def
+/keyAltF4 0x6b000000 def
+/keyAltF5 0x6c000000 def
+/keyAltF6 0x6d000000 def
+/keyAltF7 0x6e000000 def
+/keyAltF8 0x6f000000 def
+/keyAltF9 0x70000000 def
+/keyAltF10 0x71000000 def
+/keyCtrlLeft 0x73000000 def
+/keyCtrlRight 0x74000000 def
+/keyCtrlEnd 0x75000000 def
+/keyCtrlDown 0x76000000 def
+/keyCtrlHome 0x76000000 def
+/keyCtrlUp 0x84000000 def
+/keyStatus 0xff000000 def
+
+/statusAlt 0x0208 def
+/statusAltL 0x0200 def
+/statusAltR 0x0008 def
+/statusCtrl 0x0104 def
+/statusShift 0x0003 def
+
+% boot loader
+/lilo bootloader 0 eq def
+/syslinux bootloader 1 eq def
+/grub bootloader 2 eq def
+
+% bool values
+/true 0 0 eq def
+/false 0 0 ne def
+
+% type values
+/t_none 0 def
+/t_int 1 def
+/t_unsigned 2 def
+/t_bool 3 def
+/t_string 4 def
+/t_code 5 def
+/t_ret 6 def
+/t_prim 7 def
+/t_sec 8 def
+/t_dict_idx 9 def
+/t_array 10 def
+/t_end 11 def
+/t_ptr 12 def
+
+/.value { t_int settype } def
+/.undef 0 t_none settype def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Print string (for debugging).
+%
+% ( string ) ==> ( )
+%
+/string.print {
+ dup
+ currentpoint currentpoint 5 -1 roll strsize image moveto
+ show
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Print number (for debugging).
+%
+% ( number ) ==> ( )
+%
+/number.print {
+ 32 string
+ exch over
+ "%08x" exch sprintf
+ dup string.print
+ free
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Print obj (for debugging).
+%
+% ( obj ) ==> ( )
+%
+/obj.print {
+ 64 string
+ exch dup
+ .value exch gettype
+ "%x:%08x" 3 index sprintf
+ dup string.print
+ free
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Print (for debugging).
+%
+% ( obj ) ==> ( )
+%
+/print {
+ dup gettype t_int eq { number.print return } if
+ dup gettype t_string eq { string.print return } if
+ obj.print
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Convert object to pointer.
+%
+% ( obj ) ==> ( ptr )
+%
+/cvp { t_ptr settype } def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Convert object to string.
+%
+% ( obj ) ==> ( string )
+%
+/cvs { t_string settype } def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Arguments like snprintf.
+%
+% ( obj_1 ... obj_n string_1 string_2 ) ==> ( )
+%
+/sprintf {
+ dup cvp length exch snprintf
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Allocate new string.
+%
+% ( size ) ==> ( string )
+/string {
+ 1 add malloc cvs
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Increment variable.
+%
+% ( dict_ref ) ==> ( )
+%
+/inc {
+ dup exec 1 add def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Copy src to dst.
+%
+% Watch overlapping src & dst!
+%
+% ( dst src ) ==> ( dst )
+%
+/strcpy {
+ "%s" 2 index sprintf
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Duplicate string.
+%
+% ( string ) ==> ( string )
+%
+/strdup {
+ dup length string exch strcpy
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Test for AltGr.
+%
+% ( ) ==> ( bool )
+%
+/is_altGr {
+ keystat statusAltR and 0 ne keystat statusAltL and 0 eq and
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Keyboard mapping.
+%
+% ( key ) ==> ( key )
+%
+/mapkey {
+ dup 24 shr 0xff and /key.code exch def
+ is_altGr {
+ % bios is too smart...
+ key.code 0x78 ge key.code 0x83 le and { /key.code key.code 0x76 sub def } if
+ } if
+ 0 1 config.keymap length 1 sub {
+ config.keymap exch get
+ dup 0 get key.code eq {
+ 1
+ keystat statusShift and { pop 2 } if
+ is_altGr { pop 3 } if
+ get
+ exch pop
+ } {
+ pop
+ } ifelse
+ } for
+} def
+
+
diff --git a/themes/SuSE/window.inc b/themes/SuSE/window.inc
new file mode 100644
index 0000000..6af0d47
--- /dev/null
+++ b/themes/SuSE/window.inc
@@ -0,0 +1,637 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% window code
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% public words:
+%
+% window.dialog ( ) ==> ( window )
+% - create a new dialog
+%
+% window.init ( window ) ==> ( )
+% - initialize window
+%
+% window.show ( window ) ==> ( )
+% - draw window
+%
+% window.current ( ) ==> ( window )
+% - the top level window
+%
+% window.action ( ) ==> ( action )
+% - recent window action
+%
+% window.input ( key_in ) ==> ( key_out )
+% - handle keyboard input
+%
+% window.done ( ) ==> ( )
+% - close top level window
+%
+%
+% constants:
+% - window.action
+% actNothing - do nothing
+% actExit - leave boot menu
+% actCloseInfo - close info window
+% actPassword - password entered
+% actStart - boot kernel
+% actEject - eject CD
+% actPowerOff - turn computer off
+% actRedraw - redraw everything
+% actNoClose - don't close dialog (it's a flag)
+%
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% window related global variables
+%
+
+% all open windows are stacked here
+/window.list 8 array def
+/window.list.index 0 def
+
+% the top level window
+% /window.current
+
+% action selected by closing window
+/window.action actNothing def
+
+% window field definitions
+/widget.size 0 def
+/newfield { widget.size def /widget.size widget.size 1 add def } def
+
+/.type newfield
+/.x newfield
+/.y newfield
+/.width newfield
+/.height newfield
+/.width.min newfield
+/.position newfield
+/.color.fg newfield
+/.color.bg newfield
+/.font newfield
+/.saved newfield
+/.title newfield
+/.title.fg newfield
+/.title.bg newfield
+/.title.height newfield
+/.text newfield
+/.text.x newfield
+/.text.y newfield
+/.buttons newfield
+/.button.y newfield
+/.ed newfield
+/.ed.font newfield
+/.ed.list newfield
+/.ed.buffer.list newfield
+/.ed.text.list newfield
+/.ed.width newfield
+/.ed.focus newfield
+/.xmenu newfield
+/.xmenu.update newfield
+/.dont_free newfield
+
+% window types
+/t_dialog 100 def
+/t_help 101 def
+/t_main 102 def
+/t_xmenu 103 def
+
+% actions
+/actNothing 0 def
+/actExit 1 def
+/actCloseInfo 2 def
+/actPassword 3 def
+/actStart 4 def
+/actEject 5 def
+/actPowerOff 6 def
+/actRedraw 7 def
+/actRedrawPanel 8 def
+/actInstallOK 9 def
+/actInstallCancel 10 def
+/actNoClose 0x100 def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Create new dialog window.
+%
+% ( ) ==> ( window )
+%
+/window.dialog {
+ widget.size array
+ dup .type t_dialog put
+ dup .position 8 put % centered at 8/10 of screen height
+ dup .x 0 put
+ dup .y 0 put
+ dup .width.min 0 put
+ dup .color.fg black put
+ dup .color.bg lightgray put
+ dup .font font.normal put
+ dup .title.fg white put
+ dup .title.bg title.bg put
+ dup .title.height help.title.height put
+ dup .text.x 12 put
+ dup .text.y help.title.height 10 add put
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Handle keyboard input.
+%
+% ( key_in ) ==> ( key_out )
+%
+/window.input {
+ window.current .undef ne {
+ window.current .type get
+ dup t_dialog eq { exch dialog.input exch } if
+ dup t_help eq { exch help.input exch } if
+ dup t_main eq { exch main.input exch } if
+ dup t_xmenu eq { exch xmenu.input exch } if
+ pop
+
+ % maybe there is an editable input field
+ dup 0 ne {
+ window.current .ed get .undef ne {
+ window.current .ed.font get setfont
+ window.current .color.fg get setcolor
+ window.current .ed get exch edit.input
+ 0
+ } if
+ } if
+
+ % only top level window gets input
+ pop 0
+
+ } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Initialize window.
+%
+% ( window ) ==> ( )
+%
+/window.init {
+ dup .type get
+ dup t_dialog eq { pop dialog.init return } if
+ dup t_help eq { pop help.init return } if
+ dup t_main eq { pop main.init return } if
+ dup t_xmenu eq { pop xmenu.init return } if
+ pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show window.
+%
+% ( window ) ==> ( )
+%
+/window.show {
+ dup .type get
+ dup t_dialog eq { pop dialog.show return } if
+ dup t_help eq { pop help.show return } if
+ dup t_main eq { pop main.show return } if
+ dup t_xmenu eq { pop xmenu.show return } if
+ pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Add window to list.
+%
+% ( window ) ==> ( )
+%
+/window.push {
+ window.list.index window.list length ge { pop return } if
+ /window.current over def
+ window.list window.list.index rot put
+ /window.list.index window.list.index 1 add def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Remove window from list.
+%
+% ( ) ==> ( window )
+%
+/window.pop {
+ window.list.index 0 eq { .undef return } if
+ /window.list.index window.list.index 1 sub def
+ window.list window.list.index get
+ window.list window.list.index .undef put
+ /window.current
+ window.list.index 0 eq { .undef } { window.list window.list.index 1 sub get } ifelse
+ def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Close top level window.
+%
+% ( ) ==> ( )
+%
+/window.done {
+ window.current .undef ne {
+ window.current dup .type get
+ dup t_help eq { help.done } if
+ pop
+ % restore saved background and free bg image
+ dup .saved get .undef ne {
+ dup .x get 1 sub over .y get 1 sub moveto
+ dup .saved get dup restorescreen free
+ dup .saved .undef put
+ } if
+ % free input field memory
+ dup .ed get .undef ne {
+ dup .ed get 2 get free % background
+ dup .ed get free
+ dup .ed .undef put
+ } if
+ pop
+ % remove it from window list
+ window.pop
+ % free buttons & button list
+ dup .buttons get
+ dup .undef ne {
+ dup length 0 gt {
+ dup length 1 sub 0 1 rot {
+ over exch get free
+ } for
+ } if
+ } if
+ free
+ % free window
+ dup .dont_free get { pop } { free } ifelse
+ } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Handle keyboard input.
+%
+% ( key_in ) ==> ( key_out )
+%
+/dialog.input {
+ dup 0 eq { return } if
+
+ /window.buttons window.current .buttons get def
+
+ window.buttons .undef ne { window.buttons length {
+
+ dup keyEnter eq {
+ window.buttons window.findselected
+ over over get 7 get /window.action exch def get
+ dup button.press 100000 usleep
+ window.action actNoClose and {
+ window.action dialog.specialaction { button.show } if
+ } {
+ pop window.done
+ } ifelse
+ pop 0
+ } if
+
+ window.current .ed.list get {
+ dup keyDown eq {
+ window.current .ed.focus get
+ window.current .ed.list get over get edit.hidecursor
+
+ 1 add window.current .ed.list get length mod
+ window.current .ed.focus 2 index put
+ window.current .ed.list get exch get edit.showcursor
+ pop 0
+ } if
+
+ dup keyUp eq {
+ window.current .ed.focus get
+ window.current .ed.list get over get edit.hidecursor
+
+ 1 sub window.current .ed.list get length exch over add exch mod
+ window.current .ed.focus 2 index put
+ window.current .ed.list get exch get edit.showcursor
+ pop 0
+ } if
+
+ dup keyTab eq {
+ window.findselected 1 add window.buttons length mod
+ window.selectbutton
+ pop 0
+ } if
+
+ } {
+ dup keyTab eq over keyRight eq or over keyDown eq or {
+ window.findselected 1 add window.buttons length mod
+ window.selectbutton
+ pop 0
+ } if
+
+ dup keyLeft eq over keyUp eq or {
+ window.findselected window.buttons length 1 sub add window.buttons length mod
+ window.selectbutton
+ pop 0
+ } if
+ } ifelse
+
+ dup window.findkey dup 0 ge {
+ window.buttons exch
+ over over get 7 get /window.action exch def get
+ dup button.press 100000 usleep
+ window.action actNoClose and {
+ window.action dialog.specialaction { button.show } if
+ } {
+ pop window.done
+ } ifelse
+ pop 0
+ } {
+ pop
+ } ifelse
+
+ } if } if
+
+
+ % maybe there are input fields
+ dup 0 ne {
+ window.current .ed.list get dup {
+ window.current .ed.font get setfont
+ window.current .color.fg get setcolor
+
+ window.current .ed.focus get get exch edit.input
+ 0
+ } { pop } ifelse
+ } if
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Find selected button.
+%
+% ( ) ==> ( button_idx )
+%
+/window.findselected {
+ 0
+ 0 1 window.buttons length 1 sub {
+ dup
+ window.buttons exch get 5 get
+ {
+ exch pop exit
+ } {
+ pop
+ } ifelse
+ } for
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Find button for key.
+%
+% ( key ) ==> ( button_idx )
+%
+% button_idx = -1 if not found
+%
+/window.findkey {
+ /window.key exch def
+ -1
+ window.key 0 eq { return } if
+ 0 1 window.buttons length 1 sub {
+ dup
+ window.buttons exch get 6 get window.key eq
+ {
+ exch pop exit
+ } {
+ pop
+ } ifelse
+ } for
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Select button.
+%
+% ( button_idx ) ==> ( )
+%
+/window.selectbutton {
+ window.findselected
+ over over eq {
+ pop pop
+ } {
+ window.buttons exch get button.notdefault button.show
+ window.buttons exch get button.default button.show
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Initialize dialog window.
+%
+% ( window ) ==> ( )
+%
+/dialog.init {
+ /dialog.tmp exch def
+
+ dialog.tmp .font get setfont
+
+ dialog.tmp .text get dup "" ne { strsize } { pop 0 0 } ifelse
+ /dialog.height exch dialog.tmp .text.y get 10 add add def
+ /dialog.width exch dialog.tmp .text.x get 1 add 2 mul add dialog.tmp .width.min get max def
+
+ /dialog.width dialog.tmp .title get strsize pop dialog.tmp .text.x get 1 add 2 mul add dialog.width max def
+
+ dialog.tmp .ed.text.list get dup {
+ /dialog.width
+ dialog.tmp .ed.width get dialog.tmp .text.x get 1 add 2 mul add 8 add dialog.width max
+ def
+ {
+ strsize
+ /dialog.height exch dialog.height add def
+ /dialog.width exch dialog.tmp .text.x get 1 add 2 mul add dialog.width max def
+ } forall
+ } { pop } ifelse
+
+ dialog.tmp .ed.buffer.list get dup {
+ length lineheight 10 add mul /dialog.height exch dialog.height add def
+ } { pop } ifelse
+
+ /window.buttons dialog.tmp .buttons get def
+
+ /dialog.button.y dialog.height 5 add def
+
+ window.buttons .undef ne { window.buttons length {
+ /dialog.height window.buttons 0 get 3 get dialog.button.y add 8 add def
+ } if } if
+
+ /dialog.y screen.size exch pop dialog.tmp .position get mul 10 div dialog.height sub 2 div def
+
+ window.buttons .undef ne { window.buttons length {
+ 10
+ 0 1 window.buttons length 1 sub {
+ window.buttons exch get
+ dup 1 dialog.button.y dialog.y add put
+ 2 get 10 add add
+ } for
+
+ dialog.width max /dialog.width exch def
+ } if } if
+
+ /dialog.x screen.size pop dialog.width sub 2 div def
+
+ window.buttons .undef ne { window.buttons length {
+ % calculate button x positions
+ dialog.width 0
+ 0 1 window.buttons length 1 sub {
+ window.buttons exch get 2 get add
+ } for
+ sub window.buttons length 1 add div
+ dialog.x over add
+ 0 1 window.buttons length 1 sub {
+ window.buttons exch get
+ over over 0 rot put
+ 2 get add over add
+ } for
+ pop pop
+ } if } if
+
+ % store values
+
+ dialog.tmp
+ dup .x dialog.x put
+ dup .y dialog.y put
+ dup .width dialog.width put
+ dup .height dialog.height put
+ .button.y dialog.button.y put
+
+ /dialog.tmp .undef def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Draw dialog window.
+%
+% ( window ) ==> ( )
+%
+/dialog.show {
+ /dialog.tmp exch def
+
+ % put into list early, so drawing functions can access it there
+ dialog.tmp window.push
+
+ % now start drawing
+
+ dialog.tmp .x get 1 sub dialog.tmp .y get 1 sub moveto
+ white black
+ dialog.tmp .width get 2 add dialog.tmp .height get 2 add
+ over over
+ dialog.tmp .ed.list get { xsavescreen } { savescreen } ifelse dialog.tmp .saved rot put
+ drawborder
+
+ dialog.tmp .color.bg get setcolor
+ dialog.tmp .x get dialog.tmp .y get moveto
+ dialog.tmp .width get dialog.tmp .height get fillrect
+
+ dialog.tmp .title.bg get setcolor
+ dialog.tmp .x get 1 add dialog.tmp .y get 1 add moveto
+ dialog.tmp .width get 2 sub dialog.tmp .title.height get 1 sub fillrect
+
+ dialog.tmp .x get 10 add dialog.tmp .y get 3 add moveto
+ dialog.tmp .title.fg get setcolor
+ dialog.tmp .title get show
+
+ dialog.tmp .color.fg get setcolor
+ dialog.tmp .x get dialog.tmp .y get moveto
+ dialog.tmp .text.x get dialog.tmp .text.y get rmoveto
+ dialog.tmp .text get show
+
+ dialog.tmp .ed.text.list get dup {
+ /dialog.tmp.idx 0 def
+ {
+ show
+ dialog.tmp .ed.buffer.list get dialog.tmp.idx get
+
+ dup {
+
+ 3 7 rmoveto
+
+ /dialog.tmp.buf dialog.tmp .ed.list get dialog.tmp.idx get def
+
+ dialog.tmp.buf {
+ /dialog.tmp.doinit false def
+ } {
+ /dialog.tmp.doinit true def
+ /dialog.tmp.buf [
+ currentpoint
+ dialog.tmp .ed.width get fontheight 2 add savescreen
+ 0 0
+ 0 0 0
+ ] def
+ } ifelse
+
+ dialog.tmp.buf 3 2 index put
+ dialog.tmp.buf 4 rot cvp length put
+
+ dialog.tmp .ed.list get dialog.tmp.idx dialog.tmp.buf put
+
+ currentcolor
+ currentpoint over 1 sub over 2 sub moveto
+ black white dialog.tmp .ed.width get 2 add fontheight 4 add drawborder
+ moveto -3 lineheight 10 add 7 sub rmoveto
+ setcolor
+
+ dialog.tmp.doinit {
+ dialog.tmp.buf "" edit.init
+ } {
+ % we really need a redraw function...
+ dialog.tmp.buf dup 3 get edit.init
+ } ifelse
+ dialog.tmp .ed.focus get dialog.tmp.idx ne { dialog.tmp.buf edit.hidecursor } if
+
+ } { pop } ifelse
+
+ /dialog.tmp.idx inc
+ } forall
+ } { pop } ifelse
+
+ dialog.tmp .buttons get .undef ne { dialog.tmp .buttons get length {
+ 0 1 dialog.tmp .buttons get length 1 sub {
+ dialog.tmp .buttons get exch get button.show
+ } for
+ } if } if
+
+ /dialog.tmp .undef def
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Do something without closing the window.
+%
+% ( action ) ==> ( true|false )
+%
+% Returns whether the window still exists.
+%
+/dialog.specialaction {
+ actNoClose not and
+
+ true exch
+
+ dup actEject eq {
+ bootdrive eject pop
+ } if
+
+ dup actPowerOff eq {
+ poweroff
+ } if
+
+ dup actInstallOK eq {
+ install.ok
+ exch not exch
+ } if
+
+% dup actInstallCancel eq {
+% install.cancel
+% exch not exch
+% } if
+
+ pop
+} def
+
+
diff --git a/themes/SuSE/xmenu.inc b/themes/SuSE/xmenu.inc
new file mode 100644
index 0000000..e8fa819
--- /dev/null
+++ b/themes/SuSE/xmenu.inc
@@ -0,0 +1,258 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% List dialog handling.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Some global vars.
+%
+/xmenu.vspace 4 def
+/xmenu.hspace 12 def
+/xmenu.light white def
+/xmenu.dark black def
+/xmenu.font font.normal def
+/xmenu.normal.bg lightgray def
+/xmenu.normal.fg black def
+/xmenu.selected.fg white def
+/xmenu.selected.bg 0x6c6c6c newcolor
+
+
+% xmenu layout
+%
+% [ selected_entry string_list x y panel_x ]
+%
+/.xm_current 0 def % selected entry
+/.xm_list 1 def % string list
+/.xm_x 2 def % menu x pos
+/.xm_y 3 def % menu y pos
+/.xm_width 4 def % menu width
+/.xm_height 5 def % menu height
+/.xm_panel_x 6 def % panel entry x pos
+/.xm_panel_width 7 def % panel entry width
+/.xm_panel_height 8 def % panel entry height
+/.xm_size 9 def % xmenu size
+
+
+% short hands
+/xmenu.x { xmenu .xm_x get } def
+/xmenu.y { xmenu .xm_y get } def
+/xmenu.width { xmenu .xm_width get } def
+/xmenu.height { xmenu .xm_height get } def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Create new xmenu.
+%
+% ( ) ==> ( window )
+%
+/window.xmenu {
+ widget.size array
+ dup .type t_xmenu put
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Handle keyboad input.
+%
+% ( key_in ) ==> ( key_out )
+%
+/xmenu.input {
+ dup 0 eq { return } if
+
+ dup keyEsc eq {
+ xmenu 0 xmenu.oldentry put
+ window.done
+ pop 0
+ } if
+
+ dup keyEnter eq {
+ window.current .xmenu.update get
+ window.done
+ exec
+ pop 0
+ } if
+
+ dup keyDown eq {
+ xmenu 0 get 1 add xmenu.select
+ pop 0
+ } if
+
+ dup keyUp eq {
+ xmenu 0 get 1 sub xmenu.select
+ pop 0
+ } if
+
+ dup keyF1 eq {
+ show_help
+ pop 0
+ } if
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Calculate menu sizes.
+%
+% ( ) ==> ( )
+%
+/xmenu.sizes {
+ /xmenu.lheight xmenu.font setfont fontheight xmenu.vspace dup add add def
+
+ xmenu .xm_height
+ xmenu .xm_list get length xmenu.lheight mul
+ put
+
+ xmenu .xm_width
+ 0 xmenu .xm_list get { strsize pop max } forall xmenu.hspace 2 mul add
+ put
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Init and show menu.
+%
+% ( window ) ==> ( )
+%
+% xmenu: [ selected_entry [ text0 text1 ... ] x y ]
+%
+/xmenu.init {
+ /xmenu over .xmenu get def
+
+ xmenu.sizes
+
+ xmenu.x 1 sub xmenu.y 1 sub moveto
+ xmenu.light xmenu.dark
+ xmenu.width 2 add xmenu.height 2 add
+ over over savescreen /xmenu.saved exch def
+ drawborder
+
+ 0 1 xmenu .xm_list get length 1 sub { xmenu.viewentry } for
+
+ /xmenu.oldentry xmenu .xm_current get def
+
+ dup .x xmenu.x put
+ dup .y xmenu.y put
+ .saved xmenu.saved put
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Draw xmenu.
+%
+% ( window ) ==> ( )
+%
+/xmenu.show {
+ window.push
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Draw single entry.
+%
+% ( entry ) ==> ( )
+%
+/xmenu.viewentry {
+ xmenu.font setfont
+
+ dup xmenu.lheight mul xmenu.y add /xmenu.pos.y exch def
+
+ xmenu.x xmenu.pos.y moveto
+ dup xmenu .xm_current get eq { xmenu.selected.bg } { xmenu.normal.bg } ifelse
+ setcolor xmenu.width xmenu.lheight fillrect
+
+ dup xmenu .xm_current get eq { xmenu.selected.fg } { xmenu.normal.fg } ifelse setcolor
+ xmenu.x xmenu.hspace add xmenu.pos.y xmenu.vspace add moveto
+ xmenu .xm_list get over get show
+
+ dup xmenu .xm_current get eq {
+ xmenu.x xmenu.pos.y moveto
+ xmenu.dark xmenu.light xmenu.width xmenu.lheight drawborder
+ } if
+
+ pop
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Select menu entry.
+%
+% ( new_entry ) ==> ( )
+%
+/xmenu.select {
+ dup 0 lt { xmenu .xm_list get length add } if
+ dup xmenu .xm_list get length ge { xmenu .xm_list get length sub } if
+
+ xmenu .xm_current get over xmenu .xm_current rot put
+ xmenu.viewentry
+ xmenu.viewentry
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Panel/xmenu helper function.
+%
+% ( ) => ( )
+%
+/pmenu.panel.update {
+ panel.text.moveto
+
+ xmenu .xm_panel_x currentpoint pop xmenu.hspace sub put
+ xmenu .xm_x xmenu .xm_panel_x get put
+
+ pmenu.update
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Panel/xmenu helper function.
+%
+% ( ) => ( width )
+%
+/pmenu.width {
+ % Use this instead of the line below and remove the actRedrawPanel
+ % things if you want fixed size panel entries.
+
+ % xmenu .xm_panel_width get xmenu.hspace 2 mul sub
+
+ xmenu .xm_list get xmenu .xm_current get get strsize pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Panel/xmenu helper function.
+%
+% ( ) => ( )
+%
+/pmenu.update {
+ xmenu .xm_panel_x get xmenu.hspace add panel.text.y moveto
+ xmenu .xm_panel_width get xmenu.hspace sub xmenu .xm_panel_height get
+ panel.bg setcolor fillrect
+
+ panel.normal setcolor
+ panel.font setfont
+ xmenu .xm_panel_x get xmenu.hspace add
+ panel.text.y
+ moveto
+ xmenu .xm_list get xmenu .xm_current get get show
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Panel/xmenu helper function.
+%
+% ( ) => ( )
+%
+/pmenu.init {
+ xmenu.sizes
+
+ xmenu .xm_y panel.text.y 1 sub xmenu.height sub put
+ xmenu .xm_panel_width xmenu.width put
+ xmenu .xm_panel_height fontheight put
+} def
+
+
diff --git a/tst b/tst
new file mode 100755
index 0000000..e4d8ede
--- /dev/null
+++ b/tst
@@ -0,0 +1,21 @@
+#! /bin/sh
+
+what=$1
+theme=$2
+
+[ "$theme" ] || theme=SuSE
+
+if [ ! "$what" -o ! -x ~/gfxtest/tst.$what ] ; then
+ echo "usage: tst what"
+ exit
+fi
+
+make BINDIR=../../ -C themes/$theme || exit
+
+file=themes/$theme/boot/message
+[ "$what" = install -o "$what" = install3 -o "$what" = cdrom ] && file=themes/$theme/install/bootlogo
+
+cp $file ~/gfxtest/bootlogo
+cd ~/gfxtest/
+./tst.$what
+
diff --git a/utf8/UTF-8-demo.txt b/utf8/UTF-8-demo.txt
new file mode 100644
index 0000000..bfb9ec8
--- /dev/null
+++ b/utf8/UTF-8-demo.txt
@@ -0,0 +1,212 @@
+
+UTF-8 encoded sample plain-text file
+‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+Markus Kuhn [ˈmaʳkʊs kuːn] <http://www.cl.cam.ac.uk/~mgk25/> — 2002-07-25
+
+
+The ASCII compatible UTF-8 encoding used in this plain-text file
+is defined in Unicode, ISO 10646-1, and RFC 2279.
+
+
+Using Unicode/UTF-8, you can write in emails and source code things such as
+
+Mathematics and sciences:
+
+ ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ⎧⎡⎛┌─────┐⎞⎤⎫
+ ⎪⎢⎜│a²+b³ ⎟⎥⎪
+ ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β), ⎪⎢⎜│───── ⎟⎥⎪
+ ⎪⎢⎜⎷ c₈ ⎟⎥⎪
+ ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⎨⎢⎜ ⎟⎥⎬
+ ⎪⎢⎜ ∞ ⎟⎥⎪
+ ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (⟦A⟧ ⇔ ⟪B⟫), ⎪⎢⎜ ⎲ ⎟⎥⎪
+ ⎪⎢⎜ ⎳aⁱ-bⁱ⎟⎥⎪
+ 2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm ⎩⎣⎝i=1 ⎠⎦⎭
+
+Linguistics and dictionaries:
+
+ ði ıntəˈnæʃənəl fəˈnɛtık əsoʊsiˈeıʃn
+ Y [ˈʏpsilɔn], Yen [jɛn], Yoga [ˈjoːgɑ]
+
+APL:
+
+ ((V⍳V)=⍳⍴V)/V←,V ⌷←⍳→⍴∆∇⊃‾⍎⍕⌈
+
+Nicer typography in plain text files:
+
+ ╔══════════════════════════════════════════╗
+ ║ ║
+ ║ • ‘single’ and “double” quotes ║
+ ║ ║
+ ║ • Curly apostrophes: “We’ve been here” ║
+ ║ ║
+ ║ • Latin-1 apostrophe and accents: '´` ║
+ ║ ║
+ ║ • ‚deutsche‘ „Anführungszeichen“ ║
+ ║ ║
+ ║ • †, ‡, ‰, •, 3–4, —, −5/+5, ™, … ║
+ ║ ║
+ ║ • ASCII safety test: 1lI|, 0OD, 8B ║
+ ║ ╭─────────╮ ║
+ ║ • the euro symbol: │ 14.95 € │ ║
+ ║ ╰─────────╯ ║
+ ╚══════════════════════════════════════════╝
+
+Combining characters:
+
+ STARGΛ̊TE SG-1, a = v̇ = r̈, a⃑ ⊥ b⃑
+
+Greek (in Polytonic):
+
+ The Greek anthem:
+
+ Σὲ γνωρίζω ἀπὸ τὴν κόψη
+ τοῦ σπαθιοῦ τὴν τρομερή,
+ σὲ γνωρίζω ἀπὸ τὴν ὄψη
+ ποὺ μὲ βία μετράει τὴ γῆ.
+
+ ᾿Απ᾿ τὰ κόκκαλα βγαλμένη
+ τῶν ῾Ελλήνων τὰ ἱερά
+ καὶ σὰν πρῶτα ἀνδρειωμένη
+ χαῖρε, ὦ χαῖρε, ᾿Ελευθεριά!
+
+ From a speech of Demosthenes in the 4th century BC:
+
+ Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι,
+ ὅταν τ᾿ εἰς τὰ πράγματα ἀποβλέψω καὶ ὅταν πρὸς τοὺς
+ λόγους οὓς ἀκούω· τοὺς μὲν γὰρ λόγους περὶ τοῦ
+ τιμωρήσασθαι Φίλιππον ὁρῶ γιγνομένους, τὰ δὲ πράγματ᾿
+ εἰς τοῦτο προήκοντα, ὥσθ᾿ ὅπως μὴ πεισόμεθ᾿ αὐτοὶ
+ πρότερον κακῶς σκέψασθαι δέον. οὐδέν οὖν ἄλλο μοι δοκοῦσιν
+ οἱ τὰ τοιαῦτα λέγοντες ἢ τὴν ὑπόθεσιν, περὶ ἧς βουλεύεσθαι,
+ οὐχὶ τὴν οὖσαν παριστάντες ὑμῖν ἁμαρτάνειν. ἐγὼ δέ, ὅτι μέν
+ ποτ᾿ ἐξῆν τῇ πόλει καὶ τὰ αὑτῆς ἔχειν ἀσφαλῶς καὶ Φίλιππον
+ τιμωρήσασθαι, καὶ μάλ᾿ ἀκριβῶς οἶδα· ἐπ᾿ ἐμοῦ γάρ, οὐ πάλαι
+ γέγονεν ταῦτ᾿ ἀμφότερα· νῦν μέντοι πέπεισμαι τοῦθ᾿ ἱκανὸν
+ προλαβεῖν ἡμῖν εἶναι τὴν πρώτην, ὅπως τοὺς συμμάχους
+ σώσομεν. ἐὰν γὰρ τοῦτο βεβαίως ὑπάρξῃ, τότε καὶ περὶ τοῦ
+ τίνα τιμωρήσεταί τις καὶ ὃν τρόπον ἐξέσται σκοπεῖν· πρὶν δὲ
+ τὴν ἀρχὴν ὀρθῶς ὑποθέσθαι, μάταιον ἡγοῦμαι περὶ τῆς
+ τελευτῆς ὁντινοῦν ποιεῖσθαι λόγον.
+
+ Δημοσθένους, Γ´ ᾿Ολυνθιακὸς
+
+Georgian:
+
+ From a Unicode conference invitation:
+
+ გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო
+ კონფერენციაზე დასასწრებად, რომელიც გაიმართება 10-12 მარტს,
+ ქ. მაინცში, გერმანიაში. კონფერენცია შეჰკრებს ერთად მსოფლიოს
+ ექსპერტებს ისეთ დარგებში როგორიცაა ინტერნეტი და Unicode-ი,
+ ინტერნაციონალიზაცია და ლოკალიზაცია, Unicode-ის გამოყენება
+ ოპერაციულ სისტემებსა, და გამოყენებით პროგრამებში, შრიფტებში,
+ ტექსტების დამუშავებასა და მრავალენოვან კომპიუტერულ სისტემებში.
+
+Russian:
+
+ From a Unicode conference invitation:
+
+ Зарегистрируйтесь сейчас на Десятую Международную Конференцию по
+ Unicode, которая состоится 10-12 марта 1997 года в Майнце в Германии.
+ Конференция соберет широкий круг экспертов по вопросам глобального
+ Интернета и Unicode, локализации и интернационализации, воплощению и
+ применению Unicode в различных операционных системах и программных
+ приложениях, шрифтах, верстке и многоязычных компьютерных системах.
+
+Thai (UCS Level 2):
+
+ Excerpt from a poetry on The Romance of The Three Kingdoms (a Chinese
+ classic 'San Gua'):
+
+ [----------------------------|------------------------]
+ ๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่
+ สิบสองกษัตริย์ก่อนหน้าแลถัดไป สององค์ไซร้โง่เขลาเบาปัญญา
+ ทรงนับถือขันทีเป็นที่พึ่ง บ้านเมืองจึงวิปริตเป็นนักหนา
+ โฮจิ๋นเรียกทัพทั่วหัวเมืองมา หมายจะฆ่ามดชั่วตัวสำคัญ
+ เหมือนขับไสไล่เสือจากเคหา รับหมาป่าเข้ามาเลยอาสัญ
+ ฝ่ายอ้องอุ้นยุแยกให้แตกกัน ใช้สาวนั้นเป็นชนวนชื่นชวนใจ
+ พลันลิฉุยกุยกีกลับก่อเหตุ ช่างอาเพศจริงหนาฟ้าร้องไห้
+ ต้องรบราฆ่าฟันจนบรรลัย ฤๅหาใครค้ำชูกู้บรรลังก์ ฯ
+
+ (The above is a two-column text. If combining characters are handled
+ correctly, the lines of the second column should be aligned with the
+ | character above.)
+
+Ethiopian:
+
+ Proverbs in the Amharic language:
+
+ ሰማይ አይታረስ ንጉሥ አይከሰስ።
+ ብላ ካለኝ እንደአባቴ በቆመጠኝ።
+ ጌጥ ያለቤቱ ቁምጥና ነው።
+ ደሀ በሕልሙ ቅቤ ባይጠጣ ንጣት በገደለው።
+ የአፍ ወለምታ በቅቤ አይታሽም።
+ አይጥ በበላ ዳዋ ተመታ።
+ ሲተረጉሙ ይደረግሙ።
+ ቀስ በቀስ፥ ዕንቁላል በእግሩ ይሄዳል።
+ ድር ቢያብር አንበሳ ያስር።
+ ሰው እንደቤቱ እንጅ እንደ ጉረቤቱ አይተዳደርም።
+ እግዜር የከፈተውን ጉሮሮ ሳይዘጋው አይድርም።
+ የጎረቤት ሌባ፥ ቢያዩት ይስቅ ባያዩት ያጠልቅ።
+ ሥራ ከመፍታት ልጄን ላፋታት።
+ ዓባይ ማደሪያ የለው፥ ግንድ ይዞ ይዞራል።
+ የእስላም አገሩ መካ የአሞራ አገሩ ዋርካ።
+ ተንጋሎ ቢተፉ ተመልሶ ባፉ።
+ ወዳጅህ ማር ቢሆን ጨርስህ አትላሰው።
+ እግርህን በፍራሽህ ልክ ዘርጋ።
+
+Runes:
+
+ ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ
+
+ (Old English, which transcribed into Latin reads 'He cwaeth that he
+ bude thaem lande northweardum with tha Westsae.' and means 'He said
+ that he lived in the northern land near the Western Sea.')
+
+Braille:
+
+ ⡌⠁⠧⠑ ⠼⠁⠒ ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌
+
+ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠙⠑⠁⠙⠒ ⠞⠕ ⠃⠑⠛⠔ ⠺⠊⠹⠲ ⡹⠻⠑ ⠊⠎ ⠝⠕ ⠙⠳⠃⠞
+ ⠱⠁⠞⠑⠧⠻ ⠁⠃⠳⠞ ⠹⠁⠞⠲ ⡹⠑ ⠗⠑⠛⠊⠌⠻ ⠕⠋ ⠙⠊⠎ ⠃⠥⠗⠊⠁⠇ ⠺⠁⠎
+ ⠎⠊⠛⠝⠫ ⠃⠹ ⠹⠑ ⠊⠇⠻⠛⠹⠍⠁⠝⠂ ⠹⠑ ⠊⠇⠻⠅⠂ ⠹⠑ ⠥⠝⠙⠻⠞⠁⠅⠻⠂
+ ⠁⠝⠙ ⠹⠑ ⠡⠊⠑⠋ ⠍⠳⠗⠝⠻⠲ ⡎⠊⠗⠕⠕⠛⠑ ⠎⠊⠛⠝⠫ ⠊⠞⠲ ⡁⠝⠙
+ ⡎⠊⠗⠕⠕⠛⠑⠰⠎ ⠝⠁⠍⠑ ⠺⠁⠎ ⠛⠕⠕⠙ ⠥⠏⠕⠝ ⠰⡡⠁⠝⠛⠑⠂ ⠋⠕⠗ ⠁⠝⠹⠹⠔⠛ ⠙⠑
+ ⠡⠕⠎⠑ ⠞⠕ ⠏⠥⠞ ⠙⠊⠎ ⠙⠁⠝⠙ ⠞⠕⠲
+
+ ⡕⠇⠙ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
+
+ ⡍⠔⠙⠖ ⡊ ⠙⠕⠝⠰⠞ ⠍⠑⠁⠝ ⠞⠕ ⠎⠁⠹ ⠹⠁⠞ ⡊ ⠅⠝⠪⠂ ⠕⠋ ⠍⠹
+ ⠪⠝ ⠅⠝⠪⠇⠫⠛⠑⠂ ⠱⠁⠞ ⠹⠻⠑ ⠊⠎ ⠏⠜⠞⠊⠊⠥⠇⠜⠇⠹ ⠙⠑⠁⠙ ⠁⠃⠳⠞
+ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ ⡊ ⠍⠊⠣⠞ ⠙⠁⠧⠑ ⠃⠑⠲ ⠔⠊⠇⠔⠫⠂ ⠍⠹⠎⠑⠇⠋⠂ ⠞⠕
+ ⠗⠑⠛⠜⠙ ⠁ ⠊⠕⠋⠋⠔⠤⠝⠁⠊⠇ ⠁⠎ ⠹⠑ ⠙⠑⠁⠙⠑⠌ ⠏⠊⠑⠊⠑ ⠕⠋ ⠊⠗⠕⠝⠍⠕⠝⠛⠻⠹
+ ⠔ ⠹⠑ ⠞⠗⠁⠙⠑⠲ ⡃⠥⠞ ⠹⠑ ⠺⠊⠎⠙⠕⠍ ⠕⠋ ⠳⠗ ⠁⠝⠊⠑⠌⠕⠗⠎
+ ⠊⠎ ⠔ ⠹⠑ ⠎⠊⠍⠊⠇⠑⠆ ⠁⠝⠙ ⠍⠹ ⠥⠝⠙⠁⠇⠇⠪⠫ ⠙⠁⠝⠙⠎
+ ⠩⠁⠇⠇ ⠝⠕⠞ ⠙⠊⠌⠥⠗⠃ ⠊⠞⠂ ⠕⠗ ⠹⠑ ⡊⠳⠝⠞⠗⠹⠰⠎ ⠙⠕⠝⠑ ⠋⠕⠗⠲ ⡹⠳
+ ⠺⠊⠇⠇ ⠹⠻⠑⠋⠕⠗⠑ ⠏⠻⠍⠊⠞ ⠍⠑ ⠞⠕ ⠗⠑⠏⠑⠁⠞⠂ ⠑⠍⠏⠙⠁⠞⠊⠊⠁⠇⠇⠹⠂ ⠹⠁⠞
+ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
+
+ (The first couple of paragraphs of "A Christmas Carol" by Dickens)
+
+Compact font selection example text:
+
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789
+ abcdefghijklmnopqrstuvwxyz £©µÀÆÖÞßéöÿ
+ –—‘“”„†•…‰™œŠŸž€ ΑΒΓΔΩαβγδω АБВГДабвгд
+ ∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi�⑀₂ἠḂӥẄɐː⍎אԱა
+
+Greetings in various languages:
+
+ Hello world, Καλημέρα κόσμε, コンニチハ
+
+Box drawing alignment tests: █
+ ▉
+ ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳
+ ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳
+ ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳
+ ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳
+ ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎
+ ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏
+ ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ ▗▄▖▛▀▜ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█
+ ▝▀▘▙▄▟
diff --git a/utf8/font b/utf8/font
new file mode 100644
index 0000000..9645f71
--- /dev/null
+++ b/utf8/font
@@ -0,0 +1 @@
+./getx11font -v -l 18 -p 2,4 -a 0x20-0xff -a 0x20ac --add-text utf8/utf_sample -f `cat utf8/uf1` -f `cat utf8/uf2` themes/SuSE/16x16.font
diff --git a/utf8/font2 b/utf8/font2
new file mode 100644
index 0000000..9cdd46d
--- /dev/null
+++ b/utf8/font2
@@ -0,0 +1 @@
+./getx11font -v -l 18 -p 2,4 -c latin1 -c latin2 -a 0x20ac -t utf8/utf_sample -f `cat utf8/uf1` -f `cat utf8/uf2` themes/SuSE/16x16.font
diff --git a/utf8/font3 b/utf8/font3
new file mode 100644
index 0000000..1b67453
--- /dev/null
+++ b/utf8/font3
@@ -0,0 +1 @@
+./getx11font -v -l 18 -p 2,4 -c ISO-8859-15 -c ISO-8859-2 -t utf8/utf_sample -f `cat utf8/uf1` -f `cat utf8/uf2` 16x16.font
diff --git a/utf8/font4 b/utf8/font4
new file mode 100644
index 0000000..3ace17d
--- /dev/null
+++ b/utf8/font4
@@ -0,0 +1 @@
+./getx11font -v -l 18 -p 2,4 -c koi8-r -c ISO-8859-15 -c ISO-8859-2 -t utf8/utf_sample -f `cat utf8/uf1` -f `cat utf8/uf2` 16x16.font
diff --git a/utf8/font5 b/utf8/font5
new file mode 100644
index 0000000..e7fb252
--- /dev/null
+++ b/utf8/font5
@@ -0,0 +1 @@
+./getx11font -v -l 18 -p 2,4 -c koi8-r -c ISO-8859-15 -c ISO-8859-2 -t utf8/utf_sample -t themes/SuSE/install/log -f `cat utf8/uf1` -f `cat utf8/uf2` 16x16.font
diff --git a/utf8/uf1 b/utf8/uf1
new file mode 100644
index 0000000..f194bb3
--- /dev/null
+++ b/utf8/uf1
@@ -0,0 +1 @@
+-efont-fixed-medium-r-normal--16-160-75-75-c-80-iso10646-1
diff --git a/utf8/uf2 b/utf8/uf2
new file mode 100644
index 0000000..c802b78
--- /dev/null
+++ b/utf8/uf2
@@ -0,0 +1 @@
+-efont-fixed-medium-r-normal--16-160-75-75-c-160-iso10646-1
diff --git a/utf8/uf3 b/utf8/uf3
new file mode 100644
index 0000000..a32ebc7
--- /dev/null
+++ b/utf8/uf3
@@ -0,0 +1 @@
+-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso10646-1
diff --git a/utf8/utf_sample b/utf8/utf_sample
new file mode 100644
index 0000000..aa411f5
--- /dev/null
+++ b/utf8/utf_sample
@@ -0,0 +1 @@
+ᚻᛖ睡不足の