Eyecandy: Turn your computer into an expensive lava lamp.

Morning Star

Initial Release Date
July 14, 1990
Color Palette
4/18b and 8/18b
Max Resolution
640x480
License Status
Public Domain (Source Available)
Codebase
x86 Assembly
Platform(s)
MS-DOS
Author(s)
Christopher Antos and D. Finkbeiner

Description

Morning Star renders lightning bolts, bouncing sets of lines, or Sierpinski's triangles on a VGA display.

I am ... the bright Morning Star

Morning Star started as a simpler bouncing lines program, known as VGAMoire. Though VGAMoire had fairly simple output, it had sophisticated MS-DOS screensaver functionality:

Morning Star improved upon VGAMoire by:

Upon graduating the University of Michigan, Christopher Antos made Morning Star and VGAMoire public domain, and released their source code. I've been unable to find the Morning Star source, but did find VGAMoire v1.4b's source in it's archive.

VGAMoire and some modules of Morning Star, like many other line bouncers, take a fairly simplified approach to drawing each set of lines, only drawing 2 lines per update: a black line to erase the line drawn X steps back (40 by default); and a line of the next color. Since the full set of lines isn't updated each time it performs quickly, but the simple erasure method used overwrites parts of lines not intended for deletion causing subtle black artifacts.

There is an unrelated program from March 8, 1989, also known as VGAMoire, that renders static MoirΓ© pattern images. Besides it's name, it appears to be completely unrelated to Christopher Antos's VGAMoire.

Operation and Options

Morning Star is intended to be a MS-DOS screensaver, and normally will only start up after a set timeout. It can be configured or launched immediately via hotkeys.

Saver Modules

Morning Star provides eight screensaver modules, and a ninth that selects from the other modules at random at set intervals.

Blanker

Simply blanks the screen. Appears to have no configuration, but has this odd text in it's configuration panel.

LIST resource
====
a. is very useful.
b. was hard to get working.
c. is really cool.
d. could get me sued for look--and-feel violations.
e. is the most flexible resource.
Lightning

Draws a jagged flashing line similar to lightning. It provides only one option, Frequency, with two settings: Often, and Frightening.

This module is a bit disappointing. The lightning is always just a single line, never branching into multiple leaders as seen with lightning normally.

Moire

Draws bouncing, rainbow colored lines with optional kaleidescope-like mirroring, often producing MoirΓ© patterns. It provides a number of options:

Points

Draws a snake-like design of rainbow colored moving points. It provides a number of options:

Sierpinski β–²

Draws a bouncing/rotating Sierpinski triangle in rotating colors. D.Finkbeiner is also credited here. It provides a few options:

Sierpinski II

Draws a bouncing/rotating Sierpinski triangle in rotating colors, preserving the six prior iterations. D.Finkbeiner is also credited here. It provides a few options:

Triangle

Draws a bouncing, rainbow colored set of triangles. It provides a number of options:

Wraparound

Draws a Lissajous-like pattern of bouncing lines, pauses, and then draws another. D.Finkbeiner is also credited here. It provides a few options:

Video Modes

Allows one to set the video mode used: 640x480x4b or 320x200x8b.

Video

Screenshots

ScreenshotScreenshotScreenshotScreenshotScreenshotScreenshotScreenshotScreenshotScreenshotScreenshotScreenshotScreenshotScreenshotScreenshotScreenshotScreenshotScreenshot

Downloads

Documentation

Morning Star
                          MORNING STAR REFERENCE CARD
                          ===========================


                       Morning Star by Christopher Antos
                  Copyright (c) 1990-1993, All Rights Reserved



 -- COMMAND LINE OPTIONS ------------------------------------------------------

        /I      this option must be used to install Morning Star into memory.
        /U      this option is used to uninstall Morning Star from memory.
        /T      use this option to view the current settings.
        /Y      use this option to install Morning Star without using EMS
                memory; Morning Star will not be able to run saver modules to
                draw designs, though.

        /-      disables Morning Star from automatically engaging; hotkeys
                still work, though.
        /+      reenables automatically engaging after the time limit has
                expired; NOTE that /- and /+ are nestable, ie, if you use /-
                twice, you must use /+ twice to enable Morning Star.
        /D      disable Morning Star completely; even hotkeys don't work.
        /E      reenable Morning Star (after using /D).

        /S      save a copy of the current settings.
        /R      restore settings from a saved copy.
        /R-     forget all saved settings.


    The following switches can be turned OFF by following them with a minus
    sign (-).  Options with a star (*) next to them are ON by default.

        /B      blanking only; never draw the design, just blank the screen.
        /F      fade out to blank when blanking the screen.
        /G  *   Ghost mode (see section "Ghost Mode").
        /H      alternate method of blanking the screen; some VGA cards require
                this option to work correctly.
        /M  *   watch for mouse movement or clicks and restore the screen.
        /P      enable password protection; screen will not restore until the
                correct password is entered and [Enter] is pressed.
        /V      watch for video activity and restore the screen; usually this
                is not necessary.

        /Wn     sets time limit to n minutes; Morning Star waits until n
                minutes have passed without any activity and then engages.
        /Zn     set which COM ports to watch; COM ports recognized are 1-4, use
                0 to clear the list of ports to watch, eg. /Z1 watches port 1
                and whatever other ports were already being watched, /Z01
                watches only port 1.

 -- HOTKEYS -------------------------------------------------------------------

        [LeftShift]-[RightShift]  -  engage Morning Star.
        [Ctrl]-[Alt]-[<]          -  turn Morning Star off (hear one beep).
        [Ctrl]-[Alt]-[>]          -  turn Morning Star on (hear two beeps).
        [Ctrl]-[Alt]-[/]          -  pop up control panel.

 -- CONTROL PANEL -------------------------------------------------------------

        The control panel can only pop up in text mode.  Use the mouse to
        change settings, or use the keyboard.

            MOUSE:      Left button  - select something.
                        Right button - close the control panel.

            KEYBOARD:   [Tab]        - jump to next control (eg. button,
                                       list box, etc).
                        [Esc]        - close the control panel.
                        [Space]      - select something.

        Use the control panel to change Morning Star's settings, the settings
        for individual saver modules, to select which saver module to run, and
        which video driver to use.

 -- MSCONFIG ------------------------------------------------------------------

        Use the program MSCONFIG.EXE to change the default settings and change
        the password.  MSCONFIG creates a configuration file (MORNSTAR.INI)
        which belongs in the same directory where you keep MORNSTAR.COM.  Note
        that Morning Star and VGA Moire can share the same configuration file!

 -- GHOST MODE ----------------------------------------------------------------

        Thanks to a friend in Arizona (Gary Dobbins), Morning Star has a
        special new mode which makes it compatible with modem redialers and
        also with networks.  Morning Star will allow DOS programs to continue
        processing even while it is drawing designs.  It draws bits and pieces
        of the designs during the time when other programs are idle.  This
        means that you can leave Morning Star on while your terminal program is
        dialing and it will draw designs until your modem connects to another
        computer.  Then it will restore the screen for you.  Once you are
        connected, however, it will only blank the screen to avoid interfering
        with high-speed file transfers.

 -- IMPORTANT NOTES -----------------------------------------------------------

    **  Never install or remove Morning Star from a menu system.  Always do it
        from the DOS prompt (you can use a batch file if you want to) or in
        your AUTOEXEC.BAT file.

    **  Morning Star does not work in conjunction with Windows.  It
        automatically disables itself to avoid crashing Windows.

    **  The first time you install Morning Star (or if it cannot find the
        configuration file), it will pop up the control panel to let you pick
        a video driver.

    **  Morning Star *requires* EMS memory in order to run saver modules and
        draw designs.  It only takes 9k of normal memory, but reserves 80k of
        EMS memory.  When it engages, it tries to allocate even more EMS
        memory, but it frees this memory when it is done with it.
        VGA Moire does not use EMS memory, but uses 24k of normal memory.

    **  If you have a modem and Morning Star is watching the COM port to which
        it is connected, you will see the border color flash whenever the phone
        rings.  Now you can wear headphones while working on your computer and
        still "hear" the phone when it rings!

    **  DESQview - Morning Star may be incompatible with DESQview.  However,
        try setting it to ignore the mouse and always blank the screen (use
        options /M- /B).

    **  SuperVGA - Some SuperVGA cards (particularly those with Tseng Labs
        chips) are *NOT* 100% IBM compatible, and there may be minor problems
        when restoring the screen (eg. in Word for DOS, the background colors
        may blink).

    **  GAMES - Most games are incompatible with screen savers.  We recommend
        turning off Morning Star (use the control panel or option /D) before
        running video games.

Readme
                               IMPORTANT NOTICE
                              ==================


I recently graduated from the University of Michigan with a BS in Computer
Science, and I have accepted a job with a major software firm.  As a result, I
will be unable to provide further support for my shareware programs.  This
means I will also be unable to develop new versions.  I am officially
releasing Morning Star and VGA Moire into the Public Domain as copyrighted
products.  They may be freely distributed, for free.


Because I will be unable to provide support services, from now on I will no
longer mail disks out, nor will I accept registration fees.  Thank you to all
of you who have registered and helped put me through college and to get the
job I now have.


Please ignore any references the documentation may still have to registering
and licensing fees, as I can no longer accept them.


At the same time, I am going to distribute the source code to both programs.
Anyone who is familiar with 80x86 assembly language will be able to examine,
modify, enhance, etc, the programs.  The source code will be available on some
popular Internet anonymous FTP sites (except that right now, hard drive space
seems to be a limitation on these FTP sites, so it may be a while before the
source code gets up there).


Thank you,
Christopher Antos
VGAMoire 1.4b.asm
;------ VGAMoire --------------------------------------------------------------
;
;       A text mode screen saver which saves the text display and draws a
;       pretty, moving graphic design on the screen.
;
;   οΏ½οΏ½οΏ½
;   οΏ½   moiοΏ½re (mwοΏ½r, mοΏ½r) n. [Fr, watered silk < MOHAIR] a fabric, esp. silk,
;   οΏ½      rayon, or acetate, having a watered, or wavy, pattern.
;   οΏ½                 _            _
;   οΏ½   moiοΏ½rοΏ½ (mwοΏ½r ra', mοΏ½-; mοΏ½r'a) adj. [Fr, pp. of /moirer/, to
;   οΏ½      water < /moire/: see prec.] having a watered, or wavy, pattern,
;   οΏ½      as certain fabrics, stamps, or metal surfaces --n.  1 a watered
;   οΏ½      pattern pressed into cloth, etc. with engraved rollers  2 MOIRE
;   οΏ½οΏ½οΏ½
;    οΏ½οΏ½οΏ½οΏ½οΏ½οΏ½οΏ½οΏ½οΏ½οΏ½ From Webster's New World Dictionary, Third College Edition,
;               Copyright (C) 1988 by Simon & Schuster, Inc.
;
;------ CREDITS ---------------------------------------------------------------
;
;       Moire pattern generator for the VGA.
;       Written by Christopher Antos, July 1990.
;       Copyright (C) 1990 by Christopher Antos.
;
;       Inspired by seeing MAGIC for Windows.  Also inspired by a lack of
;       intelligent, small, pretty screen savers that restored the video and
;       mouse states correctly.
;
;       Linedraw routines are from "Programmer's Guide to PC & PS/2 Video
;       Systems", from Microsoft Press.
;
;       If you have any questions or comments, please contact me at:
;
;               Christopher Antos
;               2115 Windsor Drive
;               Ann Arbor, MI  48103-5652
;               (313)663-7912
;
;       I'm not too picky about people using this source code.  It is not,
;       however, public domain.  It is copyrighted.  If you use this source
;       code at all, then you are using the program, and should feel obligated
;       to send a donation just as if you were using the program itself.  See
;       the documentation for more information.
;
;------ COMPILING -------------------------------------------------------------
;
;       VGAMoire is written for Turbo Assembler 2.0 and uses "SMART" mode for
;       maximum code optimization.
;
;       To compile:
;
;               tasm /zi vgamoire
;               tlink /v /s /l vgamoire
;               del vgamoire.obj
;               tdstrip -s -c vgamoire
;
;       This creates the excutable file, VGAMOIRE.COM; the debugger symbol
;       table file, VGAMOIRE.TDS; and the map file, VGAMOIRE.MAP.
;
;------ PLANS FOR REVISION ----------------------------------------------------
;
;       - Display new settings when N is used.
;       - Possibly some more code compaction.
;       - Possibly rearrange routines and only keep large routines (ie,
;         character RAM save/restore routines) resident if they will be used.
;       - Possibly implement XMS support, if in demand enough.
;
;------ VERSION HISTORY -------------------------------------------------------
;
;       v1.0    7/14/90
;               οΏ½       Original version.
;               οΏ½       Details:
;                         - Works with monochrome or color VGA cards only.
;                           VGAMoire will not work on EGA or MCGA, but it
;                           should work on just about any VGA card.  It uses
;                           the VGA 640x480x16 mode 12h, and uses 15 colors.
;                           It directly accesses the video DAC color registers
;                           and reprograms them to display different colors.
;                         - Will not work in graphics modes.  It is highly
;                           unlikely this will change, though someday, if
;                           the idea is popular and in demand enough, support
;                           *may* be added to save the graphics screen to EMS,
;                           allowing VGAMoire to be able to work even in
;                           graphics modes (though it still would conflict with
;                           most games or other "poorly behaved" programs).  I
;                           just don't see the point in it, especially since
;                           graphical applications are leaning towards
;                           Microsoft Windows as a standard.  Real-mode DOS
;                           TSRs like VGAMoire would not function, anyhow.
;                         - Does not beep if it times out in graphics mode, but
;                           beeps any other time it cannot pop up, including
;                           if the user hits Ctrl-Alt-Shift while in graphics
;                           mode.
;                         - Respects serial (and some parallel) communications,
;                           and restarts its countdown while any data transfer
;                           is going on.  It will not break carrier when it
;                           pops up or down (unless the remote host times out).
;                         - Saves and restores the complete mouse state.
;                         - Restores the display when mouse movement or a
;                           keypress is detected.  Note that VGAMoire suspends
;                           the current process.  It is NOT a background
;                           process.
;                         - With EMS memory installed, VGAMoire can save the
;                           *entire* video state, including the character
;                           generator RAM.  If this feature is not used, or EMS
;                           memory is not available, then VGAMoire just saves
;                           and restores the video mode, page, cursor positions
;                           (for each of the 8 video pages), and the cursor
;                           shape.  It will reset the screen to 25 lines.  No
;                           video data is lost besides the character generator
;                           RAM and the screen size.
;                           NOTE:  saving the character generator RAM adds an
;                           extra 64k to the total EMS memory that VGAMoire
;                           uses, in order to save all 8 character generator
;                           RAM banks (at 8k each).
;                         - VGAMoire should never pop up when it might damage
;                           the system or cause errors.  It monitors a number
;                           of I/O interrupts and restarts its countdown if any
;                           I/O is detected.  If you need an ABSOLUTE guarantee
;                           that it will not disrupt the system during a vital
;                           operation, you can turn it off by pressing
;                           Ctrl-Alt-E (press Ctrl-Alt-B to turn it on again).
;                           If you press Ctrl-Alt-Shift to pop VGAMoire up, it
;                           WILL pop up, even if a vital system operation is in
;                           progress (eg, disk I/O).  Because this can cause
;                           errors or even crash the system, you should be
;                           careful about when you pop VGAMoire up manually.
;                           The only times VGAMoire will not pop up is if the
;                           display is in a graphics mode or if you are using
;                           EMS and there is an error while trying to use EMS.
;                         - Cannot (as yet) detect mouse movement except when
;                           popped up, so mouse movement will not restart the
;                           countdown.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
;       v1.1    8/2/90
;               οΏ½       Now deallocates its environment block.
;               οΏ½       Can now select how many character generator RAM blocks
;                       to save, from 1 to 8.  Allocates an extra one EMS page
;                       (16k) per every two character generator RAM blocks that
;                       are saved, so to save 1 or 2 blocks, it takes 16k of
;                       EMS; for 3 or 4, it takes 32k; etc.
;               οΏ½       At Karen's request, VGAMoire can now mirror the
;                       pattern in one of four ways:  no mirror, horizontally,
;                       vertically, or both horizontally and vertically.
;               οΏ½       Now detects both mouse movement and mouse button
;                       activity and will reset its countdown.  A new option
;                       has also been added to disable this feature, in case
;                       a mouse is not present or an old mouse driver causes
;                       problems with this feature.
;               οΏ½       Bug fix:  might not have worked correctly before if no
;                       mouse driver were installed (it might have allocated
;                       an unpredictably-too-large block of memory).
;               οΏ½       Bug fix:  when only using conventional memory, the
;                       keyboard would lock up once a key was pressed to
;                       return from the moire design.  I don't remember quite
;                       what I did to fix it, although I know I tried a number
;                       of things.
;               οΏ½       Now only keeps one color set resident.  When a color
;                       set is picked, it is copied to the resident copy's
;                       run-time colorset array (assuming we are changing the
;                       color set for the resident copy.  It does the same
;                       thing the first time it is installed, except that of
;                       course it copies the selected color set into the main
;                       run-time colorset array).
;               οΏ½       Frost colors added.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
;       v1.2    8/7/90
;               οΏ½       Bug fix:  forgot to use a CS: segment override when
;                       determining how many font blocks to save/restore, and
;                       the result was that essentially no fonts were restored.
;                       VGAMoire now restores fonts correctly.
;               οΏ½       Also, to avoid some nasty screen flickering during
;                       some of the special video accesses, we disable the
;                       video display while operating on video memory, and
;                       then reenable it after we're done screwing with video
;                       memory (only when starting up the moire design or
;                       returning to text mode).
;               οΏ½       Before, we only redefined 15 colors.  It occured to me
;                       that VGAMoire should also reprogram the color
;                       definition for BLACK, to make sure that the black is
;                       really black.  This is necessary because there are a
;                       number of programs out that play with the VGA palette,
;                       and we can't assume that black is really black--we've
;                       got to MAKE it be black.  The whole purpose of VGAMoire
;                       is to prevent the monitor from burning out!  If the
;                       background were always, oh, say WHITE, then VGAMoire
;                       wouldn't be much use, now would it?  So, anyway, we
;                       took care of that possibility in this version.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
;       v1.3    8/14/90
;               οΏ½       OOPS!  I apologize.  I made a stupid error.
;                       The [N] option didn't work right.
;                       Sigh.  This should now be a solid version, w/o
;                       version changes for a while.  Sigh.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
;       v1.4    9/4/90
;               οΏ½       Improved mouse state saving and restoring.  Works
;                       even with programs making very sophisticated use of
;                       the mouse driver (for instance, Norton Advanced
;                       Utilities 5.0).
;               οΏ½       New method of reading the keyboard and mouse while
;                       the screen saver is working.  This ensures that
;                       VGAMoire doesn't receive any "false alerts" and
;                       refuse to pop up even when it's supposed to.
;               οΏ½       VGAMoire will now blank out the screen if a graphics
;                       mode is active.  The moire design will not appear, but
;                       at least VGAMoire can still function as a screen saver
;                       even in graphics modes.  Special care was taken so that
;                       THE PROGRAM CAN STILL RUN IN THE BACKGROUND WHILE THE
;                       SCREEN IS BLANKED OUT.  The screen will come back if
;                       VGAMoire detects any activity--mouse, keyboard, serial
;                       communications, parallel communications (via int 17h),
;                       video activity (via int 10h), or disk activity.  It
;                       can be configured to blank the screen in text mode,
;                       too.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
;       v1.4b   9/21/90
;               οΏ½       Source code was reorganized to facilitate future
;                       support for video cards besides the VGA.  Enough
;                       people indicated an interest that I decided to
;                       look into adding support for MDA, CGA, MCGA, EGA,
;                       VGA, Hercules, and InColor cards.  Note that this is
;                       NOT a guarantee for support, just a guarantee I'll
;                       look into it!  Even if I do add support for multiple
;                       cards, not all of the above cards may be implemented.
;               οΏ½       Improved video state save/restore routines mean that
;                       the entire video state is always saved and restored,
;                       even if EMS memory is not used.  If a non-standard RAM
;                       font is loaded and active, and the [Fn] option is not
;                       in effect, then the display will revert to the 8x16
;                       ROM font.  If one of the ROM fonts was being used
;                       before VGAMoire took over, then that font will be
;                       restored.
;                    ** This also remedies a problem with MS Word (or any
;                       program that used bright background colors) when the
;                       [E] option was not used.  Before, VGAMoire was unable
;                       restore the bright mode, but now it does.
;               οΏ½       Bug fix:  I forgot to use a CS: segment override when
;                       dereferencing the "useEMS" flag when popping up
;                       VGAMoire.  In most situations, this meant VGAMoire
;                       would nuke any data a program had in the EMS page
;                       frame (OOPS!).  This has been fixed.
;
;------------------------------------------------------------------------------


LOCALS                                  ;allow local labels in procedures (@@xxx)
SMART                                   ;enable maximum code optimization


__DeallocateEnvironment         equ     1       ;1=kill env. block, 0=keep env. block so map pgms can ID us


VERSION         equ     '1.4b'                  ;current version of VGAMoire
DATE            equ     'September 1990'        ;date of this version


MaxRev          equ     6               ;max times an endpoint direction can reverse before a new random velocity is picked--must be at least 1
MaxLines        equ     50              ;maximum number of lines in the moire pattern




cseg    segment para    public  'CODE'
        assume  cs:cseg,ds:cseg,ss:nothing,es:nothing
        org 100h



main    proc    near
        jmp     setup                   ;go to end of program
main    endp



oldmx           dw      0               ;old mouse x-coordinate
oldmy           dw      0               ;old mouse y-coordinate
mouse           db      1               ;flag:  1=check mouse, 0=ignore mouse
delay           db      0               ;delay factor
mirror          db      0               ;mirror setting
length          db      20              ;number of lines in the moire pattern
colorspeed      db      1               ;# of lines to draw before changing color
wait            dw      0               ;number of int 08h's to wait before popping up
buffersize      dw      1000h           ;size of video text save buffer
mousesize       dw      0800h           ;size of mouse state save buffer
fontblocks      db      0               ;number of font RAM blocks to save (0=no font saving, 1-8=that many blocks)
onoff           db      1               ;onoff:  1=on, 0=off
useEMS          db      0               ;useEMS:  1=yes, 0=no
EMShandle       dw      ?               ;our EMS block's handle
counter         dw      0               ;count since a key was pressed etc.
videomode       db      ?               ;previous video mode
storetext       dw      ?               ;where to store text (default for conventional memory)
textbuff        dw      ?               ;store address of text buffer
keybuff         dw      0               ;keyboard buffer
gonow           db      0               ;delay when Ctrl-Alt-Shift is pressed
colorwait       db      0               ;countdown to changing color
curcolor        db      1               ;color of current line
gfxmode         db      0               ;flag:  non-zero indicates we are performing a cop-out version of a screen saver because we're in graphics mode
gfxcopout       db      0               ;flag:  non-zero means always do the cop-out, never draw the moire design
gfxinstalled    db      0               ;flag:  was this copy of VGAMoire installed with the [Bn] option?
timeout         db      1               ;popped up because:  0 if ctrl-alt-shift was hit, 1 if timed out
blackcolor      db      0,0,0           ;video DAC color definition for black
colorset        label   byte            ;run-time array holding color set for moire design--color reg values are loaded in at install time, or these defaults are used
                db      63,  0,  0      ;color #1       [red]
                db      63, 30,  0      ;
                db      63, 45,  0      ;
                db      63, 63,  0      ;               [yellow]
                db      42, 63,  0      ;
                db       0, 63,  0      ;               [green]
                db       0, 63, 42      ;
                db       0, 63, 63      ;               [cyan]
                db       0, 45, 63      ;
                db       0, 31, 63      ;
                db       0,  0, 63      ;               [blue]
                db      30,  0, 63      ;
                db      45,  0, 63      ;
                db      63,  0, 63      ;               [violet]
                db      63,  0, 47      ;color #15
maxcolor        db      15              ;highest defined color number
index           dw      0               ;index to last line in moire pattern
; current line endpoint data
; data for each coordinate is grouped so loop at [revdir] works w/offsets
xv1             dw      ?               ;x1 endpoint velocity
x1              dw      ?               ;endpoint of current line
x1rev           db      MaxRev          ;times endpoint direction has reversed
xv2             dw      ?               ;x2 endpoint velocity
x2              dw      ?               ;endpoint of current line
x2rev           db      MaxRev          ;times endpoint direction has reversed
yv1             dw      ?               ;y1 endpoint velocity
y1              dw      ?               ;endpoint of current line
y1rev           db      MaxRev          ;times endpoint direction has reversed
yv2             dw      ?               ;y2 endpoint velocity
y2              dw      ?               ;endpoint of current line
y2rev           db      MaxRev          ;times endpoint direction has reversed
switchdir       dw      0               ;# lines to draw before changing to new random velocities
linesx1         dw      MaxLines dup (?)        ;arrays holding endpoints of last MaxLines lines
linesy1         dw      MaxLines dup (?)
linesx2         dw      MaxLines dup (?)
linesy2         dw      MaxLines dup (?)
old08h          dw      ?               ;hold addresses of original interrupts
                dw      ?
old09h          dw      ?
                dw      ?
old10h          dw      ?
                dw      ?
old13h          dw      ?
                dw      ?
;old14h          dw      ?
                 dw      ?
old17h          dw      ?
                dw      ?
int10hOK        db      0               ;0 if we should reset [counter] on calls to int 10h -- while our program is running, this is 0ffh (-1)
sax             dw      ?               ;saves ax
sbx             dw      ?               ;saves bx
scx             dw      ?               ;saves cx
sdx             dw      ?               ;saves dx
sdi             dw      ?               ;saves di
ssi             dw      ?               ;saves si
sbp             dw      ?               ;saves bp
ses             dw      ?               ;saves es
sds             dw      ?               ;saves ds
sip             dw      ?               ;saves ip
scs             dw      ?               ;saves cs
sfl             dw      ?               ;saves flags
sax2            dw      ?               ;saves ax in our08h
sbx2            dw      ?               ;saves bx in out08h
scx2            dw      ?               ;saves cx in our08h
sdx2            dw      ?               ;saves dx in our08h
sds2            dw      ?               ;saves ds in out08h



reset   proc    near                    ;resets countdown, restores screen if in "gfx cop-out" mode
        push    cs:[wait]
        pop     cs:[counter]
        cmp     cs:[gfxmode],0
        je      @@done
        mov     cs:[gfxmode],0
        xor     al,al                   ;restore screen if gfx cop-out mode was active
        call    refresh
@@done:
        ret
reset   endp



our08h  proc    near                    ;our int 08h handler
        cmp     cs:[gonow],0            ;gonow > 0 if Ctrl-Alt-Shift was pressed
        jz      @@deccnt
        dec     cs:[gonow]              ;subtract 1 from gonow if it is > 0
        jg      @@deccnt
        mov     cs:[counter],1          ;if gonow=0 set counter=1 to trigger fireworks
@@deccnt:
        dec     cs:[counter]            ;decrement counter
        jz      @@moire                 ;if counter = 0 draw moire pattern
        jg      @@checkMS
        inc     cs:[counter]            ;if counter was 0 set it 0 again
@@checkMS:
        cmp     cs:[mouse],0
        je      @@chain
        mov     cs:[sds2],ds            ;save ds
        push    cs
        pop     ds                      ;set up addressability
        mov     [sax2],ax               ;save ax
        mov     [sbx2],bx               ;save bx
        mov     [scx2],cx               ;save cx
        mov     [sdx2],dx               ;save dx
        mov     ax,3
        xor     bx,bx                   ;in case no mouse driver, zero all regs that would hold return values
        xor     cx,cx
        xor     dx,dx
        int     33h
        cmp     bx,0                    ;is mouse button pressed
        jne     @@reset
        cmp     cx,[oldmx]
        jne     @@reset
        cmp     dx,[oldmy]
        je      @@doneMS
@@reset:
        mov     [oldmx],cx
        mov     [oldmy],dx
        call    reset                   ;reset countdown
@@doneMS:
        mov     dx,[sdx2]
        mov     cx,[scx2]
        mov     bx,[sbx2]
        mov     ax,[sax2]
        mov     ds,[sds2]
@@chain:
        jmp     DWord Ptr cs:[old08h]   ;chain to old int 08h handler
@@moire:
        mov     cs:[sds],ds             ;save ds first, so we can
        push    cs                      ;  point ds to us to crunch code by
        pop     ds                      ;  avoiding segment overrides
        mov     [sax],ax                ;save ax
        mov     [sbx],bx                ;save bx
        mov     [scx],cx                ;save cx
        mov     [sdx],dx                ;save dx
        mov     [sdi],di                ;save di
        mov     [ssi],si                ;save si
        mov     [sbp],bp                ;save bp
        mov     [ses],es                ;save es
        pop     [sip]                   ;save ip
        pop     [scs]                   ;save cs
        pop     [sfl]                   ;save flags
        push    [sfl]                   ;push flags back on stack
        push    cs                      ;push new cs on stack
        mov     cx,offset runthis       ;return to here
        push    cx                      ;save offset of runthis
        jmp     @@chain                 ;return to do int 8
our08h  endp



our09h  proc    near                    ;process keyboard interrupt
        push    ax                      ;save ax
        push    es                      ;save ds
        mov     es,cs:[keybuff]         ;set es = 0
        mov     al,byte ptr es:[417h]   ;get keyboard status byte
        pop     es
        and     al,0fh                  ;mask off top 4 bits
        cmp     al,12                   ;if Ctrl-Alt is pressed
        jg      @@signal                ;if Ctrl-Alt-Shift is pressed
        jnz     @@chain
        in      al,60h                  ;get extended key code
        cmp     al,18                   ;is it Ctrl-Alt-E
        jnz     @@enable
        mov     cs:[onoff],0            ;turn off screen saver
@@enable:
        cmp     al,48                   ;is key Ctrl-Alt-B
        jnz     @@chain
        mov     cs:[onoff],1            ;turn on screen saver
        jmp     @@chain
@@signal:
        mov     cs:[gonow],6            ;delay half a second then invoke screen saver
        mov     cs:[timeout],0          ;say we're popping up because of user request (ctrl-alt-shift)
@@chain:
        call    reset                   ;reset countdown
        pop     ax                      ;restore ax
        jmp     DWord Ptr cs:[old09h]   ;chain to old int 09h handler
our09h  endp



our10h  proc    near                    ;new video interrupt
        cmp     ax,0caffh               ;CA are my initials - check if we're installed
        jne     @@norm10h
        mov     bx,cs                   ;return our PSP
        mov     ax,0faceh               ;return code
        iret
@@norm10h:
        cmp     cs:[int10hOK],0         ;is it us requesting an interrupt
        jne     @@pass                  ;if so, don't reset counter, or we'll exit!
        call    reset                   ;reset countdown
        @@pass:
        jmp     DWord Ptr cs:[old10h]   ;chain to old int 10h handler
our10h  endp



our13h  proc    near                    ;new disk drive interrupt
        call    reset                   ;reset countdown
        jmp     DWord Ptr cs:[old13h]   ;chain to old int 13h handler
our13h  endp



;our14h  proc    near                    ;new modem interrupt
;        call    reset                   ;reset countdown
;        jmp     DWord Ptr cs:[old14h]   ;chain to old int 14h handler
;our14h  endp



our17h  proc    near                    ;new printer interrupt
        call    reset                   ;reset countdown
        jmp     DWord Ptr cs:[old17h]   ;chain to old int 17h handler
our17h  endp



;------------------------------------------------------------------------------
;
;       CARD-SPECIFIC CODE
;
;       any include file used here must declare the following items so it
;       can link itself with this VGAMOIRE.ASM module:
;
;               SETCOLORS       (macro) sets the colors
;               STORE           (macro) stores the current video state
;               SETMODE         (macro) sets the graphics mode
;               RESTORE         (macro) restores the saved video state
;               Line10          (proc)  draws a line in graphics mode
;
;               MinBound        equ     [minimum endpoint velocity]
;               MaxBound        equ     [maximum endpoint velocity]
;
;               MaxX            dw      [maximum x coordinate]
;               MaxY            dw      [maximum y coordinate]
;
include vga.inc
;
;------------------------------------------------------------------------------



getbuf  proc    near
        cmp     cs:[useEMS],0
        jz      @@done
        mov     ah,47h                  ;save page map
        mov     dx,cs:[EMShandle]
        int     67h
        or      ah,ah
        jnz     @@error
        mov     ah,44h                  ;map our logical pages to physical page frame
        mov     al,cs:[useEMS]          ;al=number of pages we reserved
        dec     al                      ;al=number of highest logical page
@@maploop:
        push    ax
        xor     bh,bh
        mov     bl,al                   ;map logical page to same physical page number
        mov     dx,cs:[EMShandle]
        int     67h
        or      ah,ah
        jnz     @@error3                ;@@error3 makes sure to pop ax, too
        pop     ax
        or      al,al
        jz      @@getframe
        dec     al
        jmp     @@maploop
@@getframe:
        mov     ah,41h                  ;get page frame address
        int     67h
        or      ah,ah
        jnz     @@error2
        mov     cs:[storetext],bx
@@done:
        clc                             ;success
        ret
@@error3:
        pop     ax
@@error2:
        call    freebuf                 ;uh, oh, better restore page map...
@@error:
        stc                             ;failure
        ret
getbuf  endp



freebuf proc    near
        cmp     cs:[useEMS],0
        jz      @@done
        mov     ah,48h                  ;restore page map
        mov     dx,cs:[EMShandle]
        int     67h
        or      ah,ah
@@done:
        ret
freebuf endp



rndcnt          dw      ?               ;ceiling of random number range
seed            dw      ?               ;seed for random number generator
aval            equ     2743            ;for pseudorandom generator
cval            equ     5923            ;for pseudorandom generator
rnum            dw      rval            ;number of times the generator was used
rval            equ     200             ;how high rnum can get before getting a new seed and reseting rnum

rnd     proc    near                    ;return pseudorandom number in range [0,rndcnt], uses a standard algorithm
        push    cx
        push    dx
        inc     [rnum]
        cmp     [rnum],rval             ;is it time to get a new seed
        jl      @@getrnd
        push    es
        push    bx
        xor     ax,ax
        mov     es,ax
        mov     bx,46ch
        push    es:[bx]                 ;read timer
        pop     [seed]                  ;store it to seed
        mov     [rnum],ax
        pop     bx
        pop     es
@@getrnd:
        mov     ax,[seed]               ;seed = (seed*aval + cval) mod mval
        mov     cx,aval
        mul     cx
        add     ax,cval
        mov     [seed],ax
        xor     dx,dx
        mov     cx,[rndcnt]
        inc     cx
        or      cx,cx
        jz      @@nomod                 ;if modulus 65536 (which is effectively mod 0 and thusly divide-by-zero because we're using word values)
        div     cx
        mov     ax,dx                   ;ax in [0,rndcnt]
@@nomod:                                ;jump point if rndcnt=65535 to avoid divide by zero interrupt
        pop     dx
        pop     cx
        ret
rnd     endp



randvel proc    near                    ;pick a random endpoint velocity
;       ARGS:   none
;       RETS:   ax = velocity
        mov     rndcnt,MaxBound*2       ;random number range [0,MaxBound*2]
@@rv1:
        call    rnd                     ;get random number in ax
        sub     ax,MaxBound             ;ax in [-MaxBound,MaxBound]
        cmp     ax,MinBound
        jb      @@rv1
        cmp     ax,-MinBound
        ja      @@rv1
        ret                             ;return w/ax
randvel endp



getcoords       proc    near            ;load coordinates into regs
        cmp     [curcolor],0
        je      @@erase
        mov     ax,[y2]
        mov     bx,[x2]
        mov     cx,[y1]
        mov     dx,[x1]
        ret
@@erase:
        mov     di,[index]              ;get index to last line in moire pattern
        shl     di,1                    ;convert to word index
        mov     ax,linesy2[di]
        mov     bx,linesx2[di]
        mov     cx,linesy1[di]
        mov     dx,linesx1[di]
        ret
getcoords       endp



doline  proc    near                    ;draw a line from dx,cx to bx,ax
        push    word ptr [curcolor]     ;pass parameters for line to Line10
        push    ax
        push    bx
        push    cx
        push    dx
        call    Line10
        ret
doline  endp



alllines        proc    near            ;draw all lines, including mirroring
        call    getcoords
        call    doline                  ;draw normal first line
        test    [mirror],1              ;mirror right/left?
        jz      @@noRL
        call    getcoords
        neg     bx
        add     bx,[MaxX]
        neg     dx
        add     dx,[MaxX]
        call    doline
@@noRL:
        test    [mirror],2              ;mirror top/bottom?
        jz      @@noTB
        call    getcoords
        neg     ax
        add     ax,[MaxY]
        neg     cx
        add     cx,[MaxY]
        call    doline
@@noTB:
        cmp     [mirror],3              ;mirror left/right/top/bottom?
        jne     @@noBTH
        call    getcoords
        neg     ax
        add     ax,[MaxY]
        neg     cx
        add     cx,[MaxY]
        neg     bx
        add     bx,[MaxX]
        neg     dx
        add     dx,[MaxX]
        call    doline
@@noBTH:
        ret
alllines        endp



drawmoire       proc    near            ;draw moire pattern
        mov     [counter],0             ;zero the counter to avoid "false alerts"
        ; reset tables holding old line coordinates
        push    cs
        pop     es
        mov     di,offset linesx1
        mov     cx,MaxLines*4           ;full table size (4 coordinates per line)
        mov     ax,-1
        rep     stosw                   ;set all elements in tables to -1 (word size)
        ; get random directions, velocities, and coordinates to start the pattern
        mov     [rndcnt],400
        call    rnd
        add     ax,200
        mov     [switchdir],ax          ;store new # of lines to draw before randomly changing endpoint velocities
        mov     di,(offset xv2 - offset xv1)*4  ;di is offset
randir:
        or      di,di
        jz      ranex
        sub     di,(offset xv2 - offset xv1)
        cmp     di,(offset xv2 - offset xv1)*2  ;is it doing x or y?
        jb      dox
        mov     cx,[MaxY]
        jmp     doxy
dox:
        mov     cx,[MaxX]
doxy:
        call    randvel                 ;get random endpoint velocity
        mov     xv1[di],ax              ;store it
        mov     [rndcnt],cx
        call    rnd                     ;pick random endpoint coordinate
        mov     x1[di],ax               ;store it
        jmp     randir
ranex:

di1:
        cmp     [delay],0               ;if no delay factor requested
        jz      de1
        push    cx                      ;save cx
        mov     ch,[delay]              ;set cx = 100h * delay
        xor     cl,cl
de0:
        cmp     [counter],0             ;do this to waste time
        cmp     [counter],0
        loop    de0                     ;repeat cx times
        pop     cx                      ;restore cs
de1:
        cmp     [counter],0             ;if a key was pressed counter > 0
        jng     di4
        jmp     ex1
di4:

        ; is it time to randomly switch directions yet?
        cmp     [switchdir],0
        jnz     @@sdex
        mov     [rndcnt],400            ;pick new random number of lines to draw before changing velocities
        call    rnd
        add     ax,200                  ;ax in [200,600]
        mov     [switchdir],ax          ;store new limit
        mov     di,(offset xv2 - offset xv1)*4  ;di is offset & counter in one
@@sd1:
        or      di,di
        jz      @@sdex
        sub     di,(offset xv2 - offset xv1)
        call    randvel                 ;pick a random velocity
        mov     xv1[di],ax              ;ax in [-MaxBound,-MinBound] or [MinBound,MaxBound]
        jmp     @@sd1
@@sdex:
        dec     [switchdir]

        ; reverse directions if hit edges of screen -- loop crunches 4 essentially duplicate blocks of code into one
        mov     di,(offset xv2 - offset xv1)*4  ;di is offset & counter in one
revdir:
        or      di,di
        jz      revex
        sub     di,(offset xv2 - offset xv1)
        mov     ax,x1[di]
        add     ax,xv1[di]
        cmp     di,(offset xv2 - offset xv1)*2  ;is it checking x or y?
        jb      checkx
        cmp     ax,[MaxY]
        jmp     checkxy
checkx:
        cmp     ax,[MaxX]
checkxy:
        jbe     revdir
        cmp     x1rev[di],0             ;has xv_ reversed directions too many times?
        jnz     rd1
        mov     [rndcnt],MaxRev-1       ;pick new random limit for how many times to reverse
        call    rnd
        inc     al
        mov     x1rev[di],al            ;store new limit
        call    randvel                 ;pick a random velocity
        mov     bx,xv1[di]              ;grab current velocity value
        mov     bl,ah
        and     bx,1000000010000000b    ;compare signs (directions) of current and new values of velocities
        cmp     bh,bl
        je      rb20
        neg     ax                      ;if different, make same
rb20:
        mov     xv1[di],ax              ;ax in [-MaxBound,-MinBound] or [MinBound,MaxBound]
rd1:
        dec     x1rev[di]
        neg     xv1[di]                 ;reverse the direction
        jmp     revdir
revex:

        mov     di,[index]              ;get index into saved line positions
        shl     di,1                    ;convert to word index
        mov     ax,[x1]
        mov     linesx1[di],ax          ;put x1 into array
        mov     ax,[x2]
        mov     linesx2[di],ax          ;put x2 into array
        mov     ax,[y1]
        mov     linesy1[di],ax          ;put y1 into array
        mov     ax,[y2]
        mov     linesy2[di],ax          ;put y2 into array
        ; increment index - this gives us the line to erase
        inc     [index]                 ;index = index+1
        xor     ah,ah
        mov     al,[length]
        cmp     [index],ax              ;is it time to wrap around
        jl      nw1
        xor     ax,ax
        mov     [index],ax              ;reset index to 0
nw1:
        ; get color
        cmp     [colorwait],0           ;is it time to change color
        ja      @@samecolor             ;if not, jump
        mov     al,[colorspeed]
        mov     [colorwait],al
        mov     al,[maxcolor]
        cmp     [curcolor],al
        jb      @@nowrap
        mov     [curcolor],0            ;wrap around
@@nowrap:
        inc     [curcolor]              ;get next color
@@samecolor:
        dec     [colorwait]             ;get closer to time to change color
        mov     ax,[yv2]
        add     [y2],ax                 ;add yv2 to y2
        mov     ax,[xv2]
        add     [x2],ax                 ;add xv2 to x2
        mov     ax,[yv1]
        add     [y1],ax                 ;add yv1 to y1
        mov     ax,[xv1]
        add     [x1],ax                 ;add xv1 to x1
        call    alllines                ;draw lines, including mirroring
        ; erase last line(s)
        mov     di,[index]              ;get index to last line in moire pattern
        shl     di,1                    ;convert to word index
        cmp     linesx1[di],-1          ;is there really a line to erase yet
        je      di2
        push    word ptr [curcolor]     ;save current color value
        mov     [curcolor],0            ;color for erasing
        call    alllines                ;clear last line(s) in pattern, including mirroring
        pop     ax
        mov     [curcolor],al           ;restore current color
di2:
        jmp     di1                     ;next iteration
ex1:
;        mov     dx,3ceh                 ;dx = graphics controller port address
;        xor     ax,ax                   ;restore set/reset register
;        out     dx,ax
;        inc     ax                      ;restore enable set/reset register
;        out     dx,ax
;        mov     al,3                    ;data rotate/func select register #
;        out     dx,ax
;        mov     ax,0ff08h               ;restore bit mask register
;        out     dx,ax
        ret
drawmoire       endp



moire   proc    near
        ; store text video screen
        cmp     [gfxcopout],0           ;if gfx cop-out mode is set to "always", then jump to the cop-out routine
        jne     @@gfxcopout
        mov     [textbuff],TextBufferSeg+800h   ;address of text
        mov     es,[keybuff]            ;set es = 0
        mov     bl,byte ptr es:[449h]   ;get byte at 449h
        cmp     bl,4                    ;what video mode are we in
        jl      @@go                    ;if we are in text mode, go!
        cmp     bl,7                    ;are we at mode 7, possibly ega
        jz      @@mono
@@gfxcopout:
        mov     al,1                    ;in graphics mode, so just blank the screen
        call    refresh
        mov     [gfxmode],1             ;set flag that we're doing our graphics mode cop-out version of a screen saver
        ret                             ;return to previous program
@@gofail:
        jmp     @@fail                  ;jump point if something goes wrong
@@mono:
        mov     [textbuff],TextBufferSeg        ;set textbuff to b000h if mono
@@go:
        mov     al,1                    ;disable screen refresh (avoid flickering during mode change, etc)
        call    refresh
        call    getbuf                  ;set up EMS page map if using EMS
        jc      @@gofail                ;if we can't
        mov     ax,2                    ;hide pointer, in case it's showing
        int     33h
        push    es
        mov     ax,16h                  ;save mouse state
        push    [storetext]             ;get segment of save buffer
        pop     es
        mov     dx,[buffersize]         ;offset past stored video screen
        int     33h
        mov     ax,21h                  ;reset the mouse
        int     33h
        pop     es
        mov     bl,byte ptr es:[449h]   ;save video mode
        mov     [videomode],bl
        STORE                           ;[macro] save current video state
        call    freebuf                 ;restore EMS page map (if using EMS)
        SETMODE                         ;[macro] sets the graphics video mode
        push    cs                      ;set ds = cs
        pop     ds
        SETCOLORS                       ;[macro] set new video DAC color registers
        xor     al,al                   ;reenable video refresh (the BIOS should have taken care of this when we set the graphics mode, but we do it, too, just in case)
        call    refresh
        call    drawmoire               ;draw moire pattern
        mov     al,1                    ;disable screen refresh (avoid flickering during mode change, etc)
        call    refresh
        push    cs
        pop     ds
        xor     ah,ah                   ;reset to saved mode
        mov     al,[videomode]          ;  must do this, even if we're restoring the video state afterwards, otherwise the
        int     10h                     ;  mouse driver thinks we're still in gfx mode and the mouse pointer gets mangled.
        mov     al,1                    ;disable screen refresh (avoid flickering during mode change, etc)
        call    refresh
        RESTORE                         ;[macro] restore saved video state
@@done:
        xor     al,al                   ;reenable video refresh
        call    refresh
        push    cs
        pop     ds
        call    reset                   ;reset the countdown
        ret
@@fail:
        cmp     [timeout],0             ;if failed but we timed out, don't do anything
        jnz     @@done
        mov     ah,0eh
        mov     al,7                    ;cheapie way to sound a bell
        xor     bx,bx
        int     10h
        jmp     @@done
moire   endp



runthis proc    near                    ;run graphics then restore to program
        mov     ax,cs                   ;set ds = cs
        mov     ds,ax
        not     [int10hOK]              ;tell our int 10h handler we're calling it
        cmp     [onoff],0               ;was VGAMoire turned off
        jz      @@nope
        call    moire                   ;save screen, draw moire pattern, restore screen
@@nope:
        mov     ax,[sax]                ;restore ax
        mov     bx,[sbx]                ;restore bx
        mov     cx,[scx]                ;restore cx
        mov     dx,[sdx]                ;restore dx
        mov     di,[sdi]                ;restore di
        mov     si,[ssi]                ;restore si
        mov     bp,[sbp]                ;restore bp
        mov     es,[ses]                ;restore es
        push    [sfl]                   ;put flags on stack
        push    [scs]                   ;put cs on stack
        push    [sip]                   ;put ip on stack
        mov     ds,[sds]                ;restore ds
        not     cs:[int10hOK]           ;tell our int 10h handler to reset [counter] on int requests
        mov     cs:[timeout],1          ;reset timeout indicator to say true timeout, not ctrl-alt-shift hit
        iret                            ;return to previous program
runthis endp



        align   16                      ;paragraph aligned so we can store just a segment address
EndOfResident   label   byte



_mypsp          dw      ?

deinstall       proc    near
;       This could be done by simply deallocating our PSP block and environment
;       block (if not deallocated at installation), but this is more
;       "well-behaved", in that if a DOS extender allocates an extra info block
;       per program, this will also deallocate that block, because it simply
;       deallocates anything that belongs to us.
;       This isn't resident code, so we might as well take the extra effort.
        mov     ax,0caffh               ;are we installed yet
        int     10h
        cmp     ax,0faceh
        je      @@deinstall
        mov     ah,9                    ;if not, print error message and abort
        mov     dx,offset nomsg
        int     21h
        mov     ax,4c01h
        int     21h
@@deinstall:
        mov     cs:[_mypsp],bx          ;save the PSP of the resident copy
        mov     es,bx
        mov     bl,es:[useEMS]          ;find out if resident copy is using EMS
        mov     cs:[useEMS],bl
        mov     bx,es:[EMShandle]       ;get EMS handle resident copy is using
        mov     cs:[EMShandle],bx
        mov     ax,3508h                ;check if another program covered us
        int     21h
        mov     ax,es
        cmp     ax,cs:[_mypsp]
        jne     @@yousureb
        cmp     bx,offset our08h
        jne     @@yousureb
        mov     ax,3509h
        int     21h
        mov     ax,es
        cmp     ax,cs:[_mypsp]
        jne     @@yousureb
        cmp     bx,offset our09h
        jne     @@yousureb
        mov     ax,3510h
        int     21h
        mov     ax,es
        cmp     ax,cs:[_mypsp]
        jne     @@yousureb
        cmp     bx,offset our10h
        jne     @@yousureb
        mov     ax,3513h
        int     21h
        mov     ax,es
        cmp     ax,cs:[_mypsp]
        jne     @@yousureb
        cmp     bx,offset our13h
        jne     @@yousureb
;        mov     ax,3514h
;        int     21h
;        mov     ax,es
;        cmp     ax,cs:[_mypsp]
;        jne     @@yousureb
;        cmp     bx,offset our14h
;        jne     @@yousureb
        mov     ax,3517h
        int     21h
        mov     ax,es
        cmp     ax,cs:[_mypsp]
        jne     @@yousureb
        cmp     bx,offset our17h
        jne     @@yousureb
        jmp     @@yessure
        @@yousureb:
        jmp     @@yousure
        @@yessure:
        mov     bx,cs:[_mypsp]
        mov     es,bx
        mov     dx,word ptr es:[old08h]         ; get old 8h vector
        mov     ds,word ptr es:[old08h+2]
        mov     ax,2508h                        ; restore old 8h vector
        int     21h
        mov     dx,word ptr es:[old09h]         ; get old 9h vector
        mov     ds,word ptr es:[old09h+2]
        mov     ax,2509h                        ; restore old 9h vector
        int     21h
        mov     dx,word ptr es:[old10h]         ; get old 10h vector
        mov     ds,word ptr es:[old10h+2]
        mov     ax,2510h                        ; restore old 10h vector
        int     21h
        mov     dx,word ptr es:[old13h]         ; get old 13h vector
        mov     ds,word ptr es:[old13h+2]
        mov     ax,2513h                        ; restore old 13h vector
        int     21h
;        mov     dx,word ptr es:[old14h]         ; get old 14h vector
;        mov     ds,word ptr es:[old14h+2]
;        mov     ax,2514h                        ; restore old 14h vector
;        int     21h
        mov     dx,word ptr es:[old17h]         ; get old 17h vector
        mov     ds,word ptr es:[old17h+2]
        mov     ax,2517h                        ; restore old 17h vector
        int     21h
        push    cs
        pop     ds
        mov     ah,52h
        int     21h
        mov     ax,word ptr es:[bx-2]
        mov     es,ax
        @@looptop:
        cmp     byte ptr es:[0],4dh
        jne     @@end
        mov     ax,word ptr es:[1]
        cmp     ax,word ptr cs:[_mypsp]
        jne     @@notourblock
        push    es
        mov     ax,es
        inc     ax
        mov     es,ax
        mov     ah,49h
        int     21h
        pop     es
        @@notourblock:
        mov     cx,word ptr es:[3]
        inc     cx
        mov     ax,es
        add     ax,cx
        mov     es,ax
        jmp     @@looptop
        @@end:
        cmp     cs:[useEMS],0
        jz      @@noEMS
        mov     ah,45h                  ;release resident copy's EMS block, if present
        mov     dx,cs:[EMShandle]
        int     67h                     ;if there was an error, it's out of our hands
        @@noEMS:
        mov     ah,9                    ;print deinstallation msg
        mov     dx,offset demsg
        int     21h
        mov     ax,4c00h
        int     21h
        @@yousure:
        mov     dx,offset suremsg
        call    @@str29
        @@getch:
        mov     ah,8
        int     21h
        cmp     al,'y'
        je      @@dok
        cmp     al,'Y'
        je      @@dok
        cmp     al,'n'
        je      @@dok
        cmp     al,'N'
        je      @@dok
        cmp     al,27
        je      @@dok
        jmp     @@getch
        @@dok:
        push    ax
        cmp     al,27
        je      @@nopr
        int     29h                     ;undocumented character output routine
        @@nopr:
        mov     al,13                   ;go to next line
        int     29h
        mov     al,10
        int     29h
        pop     ax
        cmp     al,'y'
        je      @@yes
        cmp     al,'Y'
        je      @@yes
        mov     dx,offset stilmsg
        call    @@str29
        pop     es
        pop     di
        mov     ax,4c01h                ;exit, return ERRORLEVEL 1
        int     21h
        @@yes:
        jmp     @@yessure
        @@str29:
        mov     di,dx
        @@sloop:                        ;output routine emulates int 21h fnc 9h
        mov     al,cs:[di]
        inc     di
        cmp     al,'$'
        je      @@sexit
        int     29h                     ;undocumented character output routine
        jmp     @@sloop
        @@sexit:
        ret
deinstall       endp



newopts proc    near
        push    ax
        push    bx
        push    dx
        mov     ax,0caffh               ;are we installed yet
        int     10h                     ;returns bx=resident PSP if installed, and ax=0faceh
        cmp     ax,0faceh
        je      @@setnew
        mov     ah,9                    ;if not, print error message and abort
        mov     dx,offset nomsg
        int     21h
        mov     ax,4c01h
        int     21h
@@setnew:
        mov     es,bx                   ;set up to write subsequent params to resident copy
        pop     dx
        pop     bx
        pop     ax
        ret
newopts endp



setminutes      proc    near
        call    finddigit               ;convert string to digit
        jc      @@done
        cmp     cl,30                   ;make sure it is less than 30 minutes
        ja      @@done
        mov     ax,444h                 ;multiply digit by 444h
        mul     cx
        mov     es:[wait],ax            ;save, this is # of int 8's performed in x mins
@@done:
        ret
setminutes      endp



setdelay        proc    near
        call    finddigit               ;convert string to digit
        jc      @@done
        mov     es:[delay],cl           ;save digit as a delay factor
@@done:
        ret
setdelay        endp



setlines        proc    near
        call    finddigit               ;get digit
        jc      @@done
        cmp     cl,MaxLines             ;was number less than MaxLines
        ja      @@done
        mov     es:[length],cl          ;save number of lines
@@done:
        ret
setlines        endp



setpages        proc    near
        call    finddigit               ;get value specified
        jc      @@done
        cmp     cl,8                    ;if greater than 8 ignore it
        ja      @@done
        mov     ax,1000h
        xor     ch,ch
        mul     cx                      ;number of bytes to save = 1000h * cx = ax
        mov     [buffersize],ax         ;save number of bytes to save
@@done:
        ret
setpages        endp



setEMS  proc    near
        mov     cs:[useEMS],1
        ret
setEMS  endp



setsavfon       proc    near
        call    finddigit               ;get value specified
        jc      @@done
        cmp     cl,8                    ;if greater than 8 ignore it
        ja      @@done
        mov     cs:[fontblocks],cl
@@done:
        ret
setsavfon       endp



setvidact       proc    near
        call    finddigit               ;get value specified
        jc      @@done
        cmp     cl,2                    ;if greater than 2 ignore it
        ja      @@done
        dec     cl
        mov     es:[int10hOK],cl        ;set video activity monitor
@@done:
        ret
setvidact       endp



setmouse        proc    near
        call    finddigit               ;get value specified
        jc      @@done
        cmp     cl,2                    ;if greater than 2 ignore it
        ja      @@done
        dec     cl
        mov     es:[mouse],cl           ;set mouse activity monitor
@@done:
        ret
setmouse        endp



setblank        proc    near
        cmp     es:[gfxinstalled],0     ;was VGAMoire installed with the [Bn] option?
        jne     @@done                  ;yep, tough luck, can't change it then
        call    finddigit               ;get value specified
        jc      @@done
        cmp     cl,2                    ;if greater than 2 ignore it
        ja      @@done
        dec     cl
        mov     es:[gfxcopout],cl       ;set blank mode (graphics "cop-out" mode)
        mov     cs:[gfxinstalled],cl    ;set [gfxinstalled] to 1 if B2 is used
@@done:
        ret
setblank        endp



setmirror       proc    near
        call    finddigit               ;get value specified
        jc      @@done
        cmp     cl,4                    ;if greater than 4 ignore it
        ja      @@done
        dec     cl
        mov     es:[mirror],cl          ;set mirror setting
@@done:
        ret
setmirror       endp



setspeed        proc    near
        call    finddigit               ;get value specified
        jc      @@done
        mov     es:[colorspeed],cl      ;store speed
@@done:
        ret
setspeed        endp



setcolor        proc    near
        call    finddigit               ;get value specified
        jc      @@done
        cmp     cl,numsets              ;if greater than number of color sets we know of, ignore it
        ja      @@done
        push    di                      ;save di & si
        push    si
        mov     si,offset rainbow       ;get base address of color sets
        dec     cl                      ;zero-based for indexing
        xor     ah,ah
        mov     al,cl
        mov     cl,(15*3)+1             ;calc offset from [rainbow] to color set
        mul     cl
        add     si,ax                   ;calc pointer to color set to use
        mov     cx,(15*3)+1             ;number of colors to copy + maxcolor descriptor
        mov     di,offset colorset      ; es:di -> location of colorset array (where to copy to)
        rep     movsb                   ;copy color set from list of color sets into the run-time array
        pop     si
        pop     di                      ;restore di & si
@@done:
        ret
setcolor        endp



seton   proc    near
        mov     es:[onoff],1
        ret
seton   endp



setoff  proc    near
        mov     es:[onoff],0
        ret
setoff  endp



getEMS  proc    near
        push    di
        push    si
        mov     ax,3567h                ;test for presense of EMS
        int     21h                     ;returns es=segment ptr
        mov     di,10                   ;es:di -> byte at offset 10 in device header
        mov     si,offset emmname
        mov     cx,8
        cld
        repz    cmpsb                   ;compare strings
        jz      @@EMSthere
        mov     ah,9                    ;print message saying no EMS m.m.
        mov     dx,offset noEMS
        int     21h
        jmp     @@error
@@EMSthere:
        mov     ah,46h                  ;get version, if lower than 3.0, can't use (actually, it might work, but since i'm not sure...)
        int     67h
        cmp     al,30h
        jae     @@EMS30
        mov     ah,9                    ;print message saying we need at least EMS 3.0
        mov     dx,offset EMS30
        int     21h
        jmp     @@error
@@EMS30:
        mov     ah,43h                  ;allocate an EMS handle to use
        mov     bx,1
        cmp     cs:[buffersize],3000h   ;three vid pages or less, just one EMS page
        jbe     @@getpages
        inc     bx
        cmp     cs:[buffersize],7000h   ;seven or less, two EMS pages
        jbe     @@getpages
        inc     bx                      ;eight vid pages needs three EMS pages
@@getpages:
        mov     cs:[useEMS],bl          ;store number of pages we're allocating for video text save area
        cmp     cs:[fontblocks],0       ;should we save character RAM also
        jz      @@nochr
        xor     dh,dh
        mov     dl,cs:[fontblocks]      ;how many font blocks do we need to save
        inc     dl                      ;round up and
        shr     dl,1                    ;  convert to EMS pages
        add     bx,dx                   ;add in pages for font RAM
@@nochr:
        int     67h
        or      ah,ah
        jz      @@gotEMS
        mov     ah,9                    ;error allocating EMS, so just use conventional
        mov     dx,offset EMSerr
        int     21h
        jmp     @@error
@@gotEMS:
        mov     cs:[EMShandle],dx
        mov     ah,46h                  ;get version, if 4.0 or higher, we're going to name our block
        int     67h
        cmp     al,40h
        jb      @@done
        mov     ax,5301h                ;give our handle a name
        mov     dx,cs:[EMShandle]
        mov     si,offset EMSname
        int     67h
@@done:
        pop     si
        pop     di
        ret
@@error:
        mov     ah,9                    ;say we'll use conventional memory instead
        mov     dx,offset cnvmsg
        int     21h
        mov     cs:[useEMS],0
        mov     cs:[fontblocks],0       ;can't save fonts anymore!!
        jmp     @@done
emmname db      'EMMXXXX0'
EMSname db      'VGAMoire'
noEMS   db      'EMS memory manager not found.',13,10,'$'
EMS30   db      'VGAMoire requires EMS 3.0 or higher.',13,10,'$'
EMSerr  db      'Error allocating EMS memory.',13,10,'$'
cnvmsg  db      'Using conventional memory instead.',13,10,'$'
getEMS  endp



reznew          db      0               ;flag:  are we setting new params for resident copy

setup   proc    near                    ;main procedure for setting up program
        mov     ah,9                    ;print id string
        mov     dx,offset msg
        int     21h
        ; process the command line
        mov     di,80h                  ;set si and di to command tail
        mov     si,81h
@@nextchr:
        lodsb                           ;get next character
        cmp     al,' '                  ;is it a whitespace, space or tab or enter
        jz      @@nextchr
        cmp     al,9
        jz      @@nextchr
        cmp     al,0dh                  ;if enter quit processing
        jz      @@endln
        dec     si                      ;adjust si
        xor     al,al                   ;mark end of string with 0
        stosb
@@getchr:
        lodsb                           ;get character
        cmp     al,' '                  ;is it a whitespace
        jz      @@nextchr
        cmp     al,9
        jz      @@nextchr
        cmp     al,0dh
        jz      @@endln
        cmp     al,'a'                  ;is the character a small letter
        jl      @@storchr
        cmp     al,'z'
        jg      @@storchr
        and     al,223                  ;if so capitalize it
        cmp     al,'N'                  ;send new params?
        jne     @@storchr
        mov     [reznew],1
@@storchr:
        stosb                           ;store character again
        jmp     @@getchr
@@endln:
        xor     ax,ax                   ;put double zero in tail to mark end of buffer
        stosw
        cmp     [reznew],1              ;should we set options for resident copy?
        jne     @@parse
        call    newopts
@@parse:
        ; parse the command line and act on parameters
        mov     si,80h                  ;start reading here
        cmp     word ptr [si+1],'?'     ;was '?' input
        jnz     @@findnull
        mov     ah,9                    ;then print message describing switches
        mov     dx,offset usage
        int     21h
        mov     ax,4c00h                ;and quit with error level 0
        int     21h
@@findnull:
        lodsb                           ;read character until we get a 0
        or      al,al
        jnz     @@findnull
        cmp     byte ptr [si],al        ;is next character a 0, are we finished ?
        jnz     @@continue
        jmp     @@donepar
@@continue:
        lodsb                           ;get character
        xor     bp,bp                   ;compare to valid options
@@nextone:
        mov     ah,cs:[bp + offset options]
        or      ah,ah
        jz      @@findnull
        cmp     ah,al
        je      @@gotone
        inc     bp
        jmp     @@nextone
@@gotone:
        shl     bp,1                    ;convert to word index
        call    word ptr cs:[bp + offset optaddr]
        jmp     @@findnull
@@donepar:
        cmp     [useEMS],0
        jnz     @@possiblefont
        mov     [fontblocks],0
@@possiblefont:
;        push    cs
;        pop     es
        cmp     [reznew],0
        jz      @@start
        ; -- possible enhancement: display current settings before exitting
        mov     ah,9                    ;display msg that params have been updated
        mov     dx,offset newmsg
        int     21h
        mov     ax,4c00h
        int     21h
@@start:
        ; start the moire pattern without going resident
        call    noresident
        cmp     [useEMS],0
        jz      @@noEMS
        call    getEMS
@@noEMS:
        mov     ax,0caffh               ;are we installed yet
        int     10h
        cmp     ax,0faceh
        jne     @@storevec
        mov     ah,9                    ;if so, print error message and abort
        mov     dx,offset ainmsg
        int     21h
        mov     ax,4c01h
        int     21h
@@storevec:
        ; store interrupt vectors
        mov     ax,3508h                ;save int 08h vector
        int     21h
        mov     word ptr [old08h],bx
        mov     word ptr [old08h+2],es
        mov     ah,25h                  ;install our int 08h
        mov     dx,offset our08h
        int     21h
        mov     ax,3509h                ;save int 09h vector
        int     21h
        mov     word ptr [old09h],bx
        mov     word ptr [old09h+2],es
        mov     ah,25h                  ;install our int 09h
        mov     dx,offset our09h
        int     21h
        mov     ax,3510h                ;save int 10h vector
        int     21h
        mov     word ptr [old10h],bx
        mov     word ptr [old10h+2],es
        mov     ah,25h                  ;install our int 10h
        mov     dx,offset our10h
        int     21h
        mov     ax,3513h                ;save int 13h vector
        int     21h
        mov     word ptr [old13h],bx
        mov     word ptr [old13h+2],es
        mov     ah,25h                  ;install our int 13h
        mov     dx,offset our13h
        int     21h
;        mov     ax,3514h                ;save int 14h vector
;        int     21h
;        mov     word ptr [old14h],bx
;        mov     word ptr [old14h+2],es
;        mov     ah,25h                  ;install our int 14h
;        mov     dx,offset our14h
;        int     21h
        mov     ax,3517h                ;save int 17h vector
        int     21h
        mov     word ptr [old17h],bx
        mov     word ptr [old17h+2],es
        mov     ah,25h                  ;install our int 17h
        mov     dx,offset our17h
        int     21h
if __DeallocateEnvironment
        mov     ax,word ptr ds:[2ch]    ; deallocate our environment block
        mov     es,ax
        mov     ah,49h
        int     21h
endif
        mov     ah,9                    ;print install message
        mov     dx,offset inmsg
        int     21h
        ; set up and install VGAMoire
        push    [wait]                  ;set counter = wait
        pop     [counter]
        xor     dx,dx
        cmp     [useEMS],0
        jnz     @@yesEMS
        mov     [storetext],cs          ;make pointer to video save area
        mov     ax,offset EndOfResident
        mov     cl,4
        shr     ax,cl
        add     [storetext],ax          ;got new address for conventional memory video save buffer
        xor     bx,bx                   ;set bx=0 in case no mouse driver!!!
        mov     ax,15h                  ;find size of mouse state buffer
        int     33h
        mov     [mousesize],bx          ;store size of mouse buffer
        push    bx
;+*VGA
        mov     ax,1c00h                ;get size of video state save buffer
        mov     cx,7
        int     10h
        mov     cl,6                    ;multiple by 64
        shl     bx,cl
        mov     dx,bx
;-*VGA
        pop     bx
        cmp     [gfxcopout],0           ;if gfx cop-out mode is in effect, don't reserve any memory
        jne     @@yesEMS
        add     dx,[buffersize]         ;plus space to reserve for text buffer
        add     dx,bx                   ;and for mouse state buffer
@@yesEMS:
        add     dx,offset EndOfResident ;actual program code to reserve
        inc     dx                      ;for int 27h, dx = (offset last_byte) + 1
        int     27h
setup endp



finddigit       proc    near            ;convert string to digit
        xor     ax,ax                   ;set ax = 0 = cx, bx = 10
        mov     bx,10
        mov     cx,ax
@@nextdigit:
        lodsb                           ;get next character
        or      al,al                   ;are we at end
        jz      @@done
        cmp     al,'9'                  ;was character bigger than 9
        jg      @@fail
        sub     al,'0'                  ;or less than zero
        jl      @@fail
        xchg    ax,cx                   ;cx = cx * 10 + ax
        mul     bx
        add     cx,ax
        or      ch,ch                   ;is cx > 255
        jz      @@nextdigit
@@fail:
        dec     si                      ;return with failure
        stc
        ret
@@done:
        or      cx,cx                   ;is cx = 0 then return failure
        jz      @@fail
        dec     si                      ;return with success
        clc
        ret
finddigit       endp



;memprob         db      'Memory allocation error.',13,10,'$'

noresident      proc    near            ;run graphics w/o staying resident
        cmp     [wait],0                ;was wait time specified
        jz      nr1
        ret                             ;if so, return and install
nr1:
;        mov     ah,4ah                  ;free unneeded memory
;        mov     bx,sp
;        mov     cl,4
;        shr     bx,cl
;        inc     bx                      ;extra paragraph
;        push    cs
;        pop     es
;        int     21h
;        jnc     @@nonres_ok
;        mov     ah,9
;        mov     dx,offset memprob
;        int     21h
;        mov     ax,4c01h
;        int     21h
;@@nonres_ok:
        mov     [buffersize],8000h      ;save all video text RAM
        cmp     [useEMS],0
        jz      @@noEMS1
        call    getEMS
@@noEMS1:
        mov     [wait],444h             ;give wait a value so we don't loop endlessly!
        mov     [counter],444h
        cmp     [useEMS],0
        jnz     @@yesEMS
        mov     [storetext],cs          ;make our video save buffer be after all important code
        mov     ax,offset EndOfNonresident
        mov     cl,4
        shr     ax,cl
        add     [storetext],ax          ;got new address for conventional memory video save buffer
        @@yesEMS:
        mov     ax,3509h                ;save int 09h vector
        int     21h
        mov     word ptr [old09h],bx
        mov     word ptr [old09h+2],es
        mov     ax,2509h                ;install our int 09h
        mov     dx,offset our09h
        int     21h
        mov     ax,3508h                ;save int 08h vector
        int     21h
        mov     word ptr [old08h],bx
        mov     word ptr [old08h+2],es
        mov     ax,2508h                ;install our int 08h
        mov     dx,offset our08h
        int     21h
        push    es                      ;timer-based pause loop
        mov     es,[keybuff]
        mov     bx,46ch
        mov     cx,es:[bx]              ;read timer
@@tryagain:
        mov     dx,es:[bx]              ;read timer
        sub     dx,cx                   ;find difference
        test    dx,8000h                ;negative?
        jz      @@pos
        neg     dx                      ;take absolute value
@@pos:
        cmp     dx,3                    ;wait a smidgen
        jb      @@tryagain
        pop     es
        mov     [timeout],1
        mov     [counter],1
        @@untildone:
        cmp     [counter],10            ;wait until counter gets reset (ie, mouse or keyboard activity)
        jb      @@untildone
        mov     ax,2508h                ;restore old int 08h handler
        mov     dx,word ptr [old08h]    ;  (don't need to use a CS: override yet)
        mov     ds,word ptr [old08h+2]
        int     21h
        mov     ax,2509h                ;restore old int 09h handler
        mov     dx,word ptr cs:[old09h] ;  (from here on we need CS: overrides)
        mov     ds,word ptr cs:[old09h+2]
        int     21h
        push    cs                      ;restore DS: addressability
        pop     ds
        cmp     [useEMS],0
        jz      @@noEMS2
        mov     ah,45h                  ;release EMS block, if present
        mov     dx,[EMShandle]
        int     67h                     ;if there was an error, it's out of our hands
        @@noEMS2:
        mov     ax,4c00h                ;exit, errorlevel 0
        int     21h
noresident endp



        align   16                      ;paragraph aligned so we can just store a segment address
EndOfNonresident        label   byte



options         db      'BCDEFLMPRSUVW-+',0
optaddr         label   word
                dw      setblank
                dw      setcolor
                dw      setdelay
                dw      setEMS
                dw      setsavfon
                dw      setlines
                dw      setmouse
                dw      setpages
                dw      setmirror
                dw      setspeed
                dw      deinstall
                dw      setvidact
                dw      setminutes
                dw      setoff
                dw      seton

msg             db      13,10
                db      'VGAMoire ',VERSION,',  by Christopher Antos,  ',DATE,',  (C)1990',13,10,'$'
inmsg           db      '++ VGAMoire now installed.',13,10,'$'
nomsg           db      '** VGAMoire has not been installed yet.',13,10,'$'
ainmsg          db      '** VGAMoire is already installed.',13,10
                db      '   Use VGAMOIRE U to deinstall.',13,10
                db      '   Use VGAMOIRE N to set new parameters.',13,10,'$'
demsg           db      '-- VGAMoire now deinstalled.',13,10,'$'
suremsg         db      13,10
                db      'Another program has captured VGAMoire''s interrupt vectors.',13,10
                db      'Deinstalling VGAMoire may cause a system crash.',13,10
                db      'Are you sure you want to deinstall VGAMoire? $'
stilmsg         db      '** VGAMoire is still installed.',13,10,'$'
newmsg          db      '++ New parameters sent to resident VGAMoire.',13,10,'$'
usage           db      13,10
                db      'Usage:  VGAMOIRE [Bn] [Cn] [Dn] [E] [Fn] [Ln] [Mn] [N]',13,10
                db      '                 [Pn] [Rn] [Sn] [U] [Vn] [Wn] [-] [+]',13,10
                db      10
                db      'Summary of options:                      * = invalid if used with [N]',13,10
                db      '  Bn    blank:  1-graphics, 2-always     Pn  * save <n> video pages (1-8)',13,10
                db      '  Cn    colors:  1-rainbow, 2-fire,      Rn    mirror:  1-none, 2-H, 3-V, 4-H/V',13,10
                db      '        3-frost, 4-pastel                Sn    color speed:  (1-255)',13,10
                db      '  Dn    delay:  (1-255)                  U     uninstall',13,10
                db      '  E   * use EMS                          Vn    video:  1-monitor, 2-ignore',13,10
                db      '  Fn  * save <n> font blocks (1-8)       Wn    wait <n> minutes (1-30)',13,10
                db      '  Ln    lines:  (1-50)                   -     turn off',13,10
                db      '  Mn    mouse:  1-monitor, 2-ignore      +     turn on',13,10
                db      '  N     send options to resident copy    ',13,10
                db      10
                db      '    Press Ctrl-Alt-Shift to pop up screen saver.  The screen saver may be',13,10
                db      '    disabled by pressing Ctrl-Alt-E and reenabled by pressing Ctrl-Alt-B.',13,10
                db      '    Use  VGAMOIRE - N  to turn off resident copy (or  + N  to turn back on).',13,10
                db      '$'



numsets         equ     5               ;number of color sets defined

; R,G,B values for video DAC color registers

rainbow         db      63,  0,  0      ;color #1       [red]
                db      63, 30,  0      ;
                db      63, 45,  0      ;
                db      63, 63,  0      ;               [yellow]
                db      42, 63,  0      ;
                db       0, 63,  0      ;               [green]
                db       0, 63, 42      ;
                db       0, 63, 63      ;               [cyan]
                db       0, 45, 63      ;
                db       0, 31, 63      ;
                db       0,  0, 63      ;               [blue]
                db      30,  0, 63      ;
                db      45,  0, 63      ;
                db      63,  0, 63      ;               [violet]
                db      63,  0, 47      ;color #15
                db      15

fire            db      63,  0,  0      ;color #1       [red]
                db      63,  7,  0
                db      63, 13,  0
                db      63, 22,  0
                db      63, 27,  0
                db      63, 32,  0
                db      63, 36,  0
                db      63, 42,  0
                db      63, 48,  0
                db      63, 52,  0
                db      63, 58,  0
                db      63, 63,  0      ;color #13      [yellow]
                db      63, 49,  0
                db      63, 40,  0
                db      63, 30,  0
                db      15

frost           db      63, 21, 63      ;color #1       [purple]
                db      52, 21, 63
                db      42, 21, 63
                db      31, 21, 63
                db      21, 21, 63      ;color #5       [blue]
                db      21, 29, 63
                db      21, 38, 63
                db      21, 46, 63
                db      21, 54, 63
                db      21, 63, 63      ;color #10      [cyan]
                db      35, 63, 63
                db      49, 63, 63
                db      63, 63, 63      ;color #13      [white]
                db      63, 49, 63
                db      63, 35, 63
                db      15

pastel          db      63, 47, 47      ;color #1       [red]
                db      63, 50, 47      ;
                db      63, 54, 47      ;
                db      63, 58, 47      ;
                db      63, 63, 47      ;               [orange]
                db      59, 63, 47      ;
                db      55, 63, 47      ;               [yellow]
                db      47, 63, 49      ;
                db      47, 63, 58      ;               [green]
                db      47, 62, 63      ;
                db      47, 57, 63      ;               [cyan]
                db      47, 50, 63      ;
                db      51, 47, 63      ;
                db      58, 47, 63      ;               [violet]
                db      63, 47, 57      ;color #15
                db      15

test            db      63, 63, 63      ;
                db      33, 33, 33      ;
                db      63, 63, 63      ;
                db      33, 33, 33      ;
                db      63, 63, 63      ;
                db      33, 33, 33      ;
                db      63, 63, 63      ;
                db      63, 63, 63      ;
                db      33, 33, 33      ;
                db      63, 63, 63      ;
                db      33, 33, 33      ;
                db      63, 63, 63      ;
                db       0,  0,  0      ;
                db       0,  0,  0      ;
                db       0,  0,  0      ;
                db      12

cseg    ends



public  EMS30
public  EMSerr
public  EMShandle
public  EMSname
public  EndOfNonresident
public  EndOfResident
public  MaxLines
public  MaxRev
public  _mypsp
public  ainmsg
public  alllines
public  aval
public  blackcolor
public  buffersize
public  checkx
public  checkxy
public  cnvmsg
public  colorset
public  colorspeed
public  colorwait
public  counter
public  curcolor
public  cval
public  de0
public  de1
public  deinstall
public  delay
public  demsg
public  di1
public  di2
public  di4
public  doline
public  dox
public  doxy
public  drawmoire
public  emmname
public  ex1
public  finddigit
public  fire
public  fontblocks
public  freebuf
public  frost
public  getEMS
public  getbuf
public  getcoords
public  gfxcopout
public  gfxinstalled
public  gfxmode
public  gonow
public  index
public  inmsg
public  int10hOK
public  keybuff
public  length
public  linesx1
public  linesx2
public  linesy1
public  linesy2
public  main
public  maxcolor
public  mirror
public  moire
public  mouse
public  mousesize
public  msg
public  newmsg
public  newopts
public  noEMS
public  nomsg
public  noresident
public  nr1
public  numsets
public  nw1
public  old08h
public  old09h
public  old10h
public  old13h
public  old17h
public  oldmx
public  oldmy
public  onoff
public  optaddr
public  options
public  our08h
public  our09h
public  our10h
public  our13h
public  our17h
public  pastel
public  rainbow
public  randir
public  randvel
public  ranex
public  rb20
public  rd1
public  reset
public  revdir
public  revex
public  reznew
public  rnd
public  rndcnt
public  rnum
public  runthis
public  rval
public  sax
public  sax2
public  sbp
public  sbx
public  sbx2
public  scs
public  scx
public  scx2
public  sdi
public  sds
public  sds2
public  sdx
public  sdx2
public  seed
public  ses
public  setEMS
public  setblank
public  setcolor
public  setdelay
public  setlines
public  setminutes
public  setmirror
public  setmouse
public  setoff
public  seton
public  setpages
public  setsavfon
public  setspeed
public  setup
public  setvidact
public  sfl
public  sip
public  ssi
public  stilmsg
public  storetext
public  suremsg
public  switchdir
public  textbuff
public  timeout
public  usage
public  useEMS
public  videomode
public  wait
public  x1
public  x1rev
public  x2
public  x2rev
public  xv1
public  xv2
public  y1
public  y1rev
public  y2
public  y2rev
public  yv1
public  yv2



        end     main

;______ EOF ___________________________________________________________________
VGAMoire 1.8

        ════════════════════════════════════════════════════════════════


                                 VGAMOIRE v1.8
                              by Christopher Antos
                  Copyright (C) 1990,1991 by Christopher Antos


                                   March 1992


            moiβ”‚re (mwΓ€r, mΓ΄r) n. [Fr, watered silk < MOHAIR] a
                fabric, esp. silk, rayon, or acetate, having a
                watered, or wavy, pattern.
                          _            _
            moiβ”‚rβ€š (mwΓ€r ra', mΓ΄-; mΓ΄r'a) adj. [Fr, pp. of /moirer/,
                to water < /moire/: see prec.] having a watered, or
                wavy, pattern, as certain fabrics, stamps, or metal
                surfaces --n.  1 a watered pattern pressed into
                cloth, etc. with engraved rollers  2 MOIRE

            ─── From Webster's New World Dictionary, Third College
                Edition, Copyright (C) 1988 by Simon & Schuster, Inc.


        ════════════════════════════════════════════════════════════════


                             Questions or Comments?


        Please write to:        Christopher Antos
                                2115 Windsor Drive
                                Ann Arbor, Michigan
                                        48103-5652


        Or send EMail to "Christopher_Antos@um.cc.umich.edu"
                      or "antos@engin.umich.edu"


        ════════════════════════════════════════════════════════════════




        Please write and make suggestions, complaints, compliments, or
        even ask questions.  Thank you!




        ─────── CONTENTS ───────────────────────────────────────────────
                Registering VGAMoire
                Release Notes
                Introduction
                Installing VGAMoire
                Using VGAMoire's Features
                Uninstalling VGAMoire
                Examples
                Known Conflicts
                Version History Summary
        ────────────────────────────────────────────────────────────────




        ═══════ REGISTERING VGAMOIRE ═══════════════════════════════════


        This program is not free, nor is it in the Public Domain.  It is
        a ShareWare program.  This means that you can try it out for a
        reasonable length of time.  If it useful to you, or you like it,
        you must register it.  To do this, print out the file
        REGISTER.TXT and follow the instructions within it.

        VGAMoire is a very high quality screen saver.  If you can find a
        better one for a lower price, I'd like to know (seriously!).  It
        has features the commercial competition can't even claim to
        match.  I put a lot of time and energy into this product, and I
        believe anyone with a VGA graphics adapter cannot help but
        benefit from using VGAMoire.

        So, please fill out the registration form (in REGISTER.TXT) and
        register today!  You will be notified of any future releases
        when they are made available.




        ═══════ RELEASE NOTES ══════════════════════════════════════════


        I am preparing to release a new, vastly improved version (and
        rewritten nearly from scratch) of this screen saver.  The new
        product is called Morning Star and uses "saver modules".  A
        saver module is a small program which draws a particular design.
        Morning Star lets you choose which saver module to use.  It can
        even switch randomly between different saver modules, adding
        some sparkle to the screen.  Because Morning Star uses a very
        large amount of memory, it unfortunately requires EMS memory.
        This allows it to keep all of its data in EMS memory and only
        use less than 8k of conventional memory, to avoid interfering
        with other applications.  Morning Star will also support
        multiple video cards. However, the first release will probably
        only include a VGA video driver.  Later updates will provide
        support for other video cards.


        If you have a third-party (non-IBM) SuperVGA adapter, please see
        the "Known Conflicts" section for information on a possible
        problem between VGAMoire and your video adapter card.  This
        release, VGAMoire v1.8, provides solutions to many of the
        problems caused by bugs in the Tseng Labs VGA chip. The fixes
        will allow VGAMoire to work much better on almost all VGA
        displays, whether IBM, ATi, Tseng Labs, or another manufacturer.




        ═══════ INTRODUCTION ═══════════════════════════════════════════


        You've probably seen a lot of other screen savers, and you're
        probably not very impressed.  Many are boring and just blank out
        the screen--which can even be annoying, because sometimes it's
        hard to tell if the machine or the monitor are even on!  Other
        screen savers may save the display in memory and draw a moving
        design until a key is pressed.  I have yet to see any other
        screen saver that saves the FULL display configuration and
        restores it.  Other popular screen savers have a number of tiny
        but very annoying flaws (eg, they might not save the cursor
        shape, maybe they don't hide the mouse pointer or save the mouse
        driver state, perhaps they can't use EMS, they may only save up
        to four video pages, they probably can't restore the screen
        properly unless it is in 25-line text mode, etc...)

        I decided it was time to write a screen saver that restored the
        screen COMPLETELY.  Enter VGAMoire.  The moire pattern design
        was inspired by Magic! (for Microsoft Windows) and Moire (for
        the Macintosh), two other well-known screen savers.  VGAMoire
        has enjoyed a large amount of success, but many users suggested
        other designs and support for video cards besides VGA.  During
        the past year, I've been hard at work on Morning Star, a new,
        much improved version of VGAMoire (I had to change the name
        because Morning Star can do other designs besides the moire, and
        because Morning Star works on video cards besides the VGA).
        Morning Star is not yet ready to be released, but it's getting
        close!


                Summary of Features:
                ~~~~~~~~~~~~~~~~~~~

                o   can use EMS memory, if any is available!
                o   allows options to be changed while it is resident!
                o   is Windows-aware! 
                o   is mouse-aware!
                o   can wait up to 30 minutes, then activate!
                o   is telecommunications-aware!
                o   is disk-I/O-aware!
                o   can be turned on/off from the keyboard or batch
                        files!
                o   certain aspects of the moire design can be
                        configured by the user!
                o   will not interfere with DOS!
                o   is DESQview compatible!




        ═══════ INSTALLING VGAMOIRE ════════════════════════════════════


                NOTE:  If at any time you have trouble with VGAMoire,
                       first check in the "Known Conflicts" section to
                       see if your problem is described there!

        You can install VGAMoire from the DOS prompt, or from your
        AUTOEXEC.BAT file.  

        Once VGAMoire is installed, you can pop up the screen saver
        manually by pressing the hotkey (the default is Ctrl-Alt-Shift),
        or you can let the machine idle for the specified amount of time
        and let the screen saver automatically pop up.  You can press
        Ctrl-Alt-E to disable the screen saver (though you can still
        manually pop it up).  Pressing Ctrl-Alt-B will reenable the
        screen saver.  

                NOTE:  some SuperVGA cards have extended text modes (eg.
                       100, 120, 132 columns as opposed to just 80).
                       Some cards are not fully IBM compatible in these
                       extended text modes, so for compatibility's sake,
                       VGAMoire only blanks the screen in these modes
                       (just as it does in graphics modes).

        VGAMoire will not become resident unless you specify how many
        minutes it should wait before popping up.  This allows you to
        try out different options without actually installing VGAMoire.
        VGAMoire also checks to see whether it has already been
        installed.  If it has, it will display an error message and will
        not load a second copy into memory.  This prevents you from
        accidentally wasting memory.

        To install VGAMoire (without specifying any options), type:

                VGAMOIRE W<n>

        where <n> is the number of minutes to count down before popping
        up.  If you do not use the [Wn] option, VGAMoire will generate
        its moire design until you press a key or move the mouse.  It
        will not install itself in memory, though.

        VGAMoire will pop up after the computer has sat idling for the
        specified number of minutes.  You can force it to pop up on
        demand by pressing the Ctrl, Alt, and Shift keys together (you
        only need to use one Shift key, and it can be either one).  This
        Ctrl-Alt-Shift hotkey works regardless of whether VGAMoire has
        been turned off or not.  This feature exists so that you can
        still manually pop up the screen saver if you have disabled
        VGAMoire (presumably because its "safety detection" methods do
        not work reliably in conjunction with a particular application).
        You can also instruct VGAMoire to use a different hotkey than
        the Ctrl-Alt-Shift combination.  See the [Kc] option for more
        information on using your own hotkey.

                NOTE:  VGAMoire should not be loaded above any
                       application programs. In other words, the
                       computer may have a heart attack if you load
                       VGAMoire (or any memory-resident utility, for
                       that matter) from a DOS shell.


        MEMORY USAGE ───────────────────────────────────────────────────

        VGAMoire can use different kinds of memory in different ways.
        When you install VGAMoire, it will take slightly under 5k of
        conventional memory, where the main screen saver code resides,
        plus an amount of memory which depends upon which installation
        options are given.

        If you have EMS memory and choose to use it, VGAMoire will only
        take 5k of conventional DOS memory and will store all of its
        data in EMS memory.  The data is between 16k and 112k in size,
        depending on how you configure VGAMoire.

        If EMS memory is NOT used (ie, if only conventional memory is
        utilized), then VGAMoire will store its data in conventional
        memory.  The data is between 16k and 112k in size, depending on
        how VGAMoire is configured.  It is a good idea to use EMS memory
        if possible, or at least to minimize the amount of conventional
        DOS memory that VGAMoire uses.

        If you are really tight on memory and just want a simple but
        intelligent screen blanker, the you can use the [B1] and [O0]
        (that's an uppercase "O" and a zero) options together.  This
        will make VGAMoire only use slightly under 4k of conventional
        DOS memory, but it will not be able to draw the moire design.




        ═══════ USING VGAMOIRE'S FEATURES ══════════════════════════════


        To see a list of the command line options that VGAMoire accepts,
        you can type:

                VGAMOIRE ?

        at the DOS prompt.  The list will look like this:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ VGAMoire 1.8,  by Christopher Antos,  March 1992,  (C)1990-1992              β”‚
β”‚                                                                              β”‚
β”‚ Syntax:  VGAMOIRE [ options ]                                                β”‚
β”‚   Options must be separated by spaces, slashes, or tabs.                     β”‚
β”‚                                                                              β”‚
β”‚ Summary of options:                      * = invalid if used with [N]        β”‚
β”‚   Bn    blank: 0=graphics, 1=always      Pn    save <n> video pages [1..8]   β”‚
β”‚   Cn    color sets: [1..5]               Rn    mirror: 0=none,1=horiz,2=vert,β”‚
β”‚   Dn    delay: [0..255]                        3=horiz+vert,4=diagonal       β”‚
β”‚   E   * use EMS                          Sn    color speed: [1..255]         β”‚
β”‚   Fn    save <n> font blocks [0..8]      U     uninstall                     β”‚
β”‚   Kc    hotkey                           Vn    video: 0=ignore, 1=monitor    β”‚
β”‚   Ln    lines: [1..50]                   Wn    wait <n> minutes [1..30]      β”‚
β”‚   Mn    mouse: 0=ignore, 1=monitor       Zc    COM ports to monitor          β”‚
β”‚   N     send options to resident copy    -     turn off                      β”‚
β”‚   On    fadeout: 0=don't, 1=fade         +     turn on                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

        When installing VGAMoire, you can specify any of these
        parameters to customize how VGAMoire behaves.  Each will be
        discussed separately, along with some tips and tricks on
        combining certain options (any of the options may be used with
        any of the other options, except as noted).

        To use an option, specify it on the command line.  Be sure to
        put a space between different options, and do NOT put a space
        between an option letter and the value you are setting it to. Do
        not type the brackets that are used in the documentation.  They
        are only used to easily distinguish options from other text.

                Correct:        VGAMOIRE C1 M1
                Wrong:          VGAMOIRE C1M1
                Wrong:          VGAMOIRE C 1 M 1


        ─── THE OPTIONS ────────────────────────────────────────────────

        [Bn]    If VGAMoire times out while the display is in a graphics
                mode, VGAMoire will just blank the screen and allow the
                current application to continue processing.  As soon as
                any key is pressed or the mouse is moved, VGAMoire will
                restore the screen.  If you want VGAMoire to do this
                with text screens, too, instead of drawing the moire
                design, you can use this option.  Example:

                        VGAMOIRE B1

                This tells VGAMoire to always blank the screen instead
                of drawing the moire design.  To allow VGAMoire to draw
                the design again, use B0 instead of B1.

  SPECIAL NOTE: If VGAMoire is installed with both the B1 and O0
                options, it will only take about 4k of conventional DOS
                memory.  If it is installed with B1 but not with O0,
                then it will take 4.7k.  This way, you can force it to
                be a real memory miser, in case you are really low on
                memory or don't have EMS.  It will not allocate any
                memory -- neither conventional nor EMS (not even if the
                [E] option is used) -- for a save buffer, and it will
                not be able to draw the moire design at all unless it is
                uninstalled and reinstalled without the B1 option.


        [Cn]    VGAMoire has several different color sets it can use.
                VGAMoire reprograms the VGA's color registers to produce
                non-standard colors, thus giving truer, better, and more
                colors than otherwise possible.  Example:

                        VGAMOIRE C3

                This would tell VGAMoire to use "frosty" colors to draw
                the moire pattern.  Below is a list of possible color
                sets:

                                C1 - Rainbow
                                C2 - Fire
                                C3 - Frost
                                C4 - Pastel
                                C5 - Glowing red


        [Dn]    VGAMoire is a very fast program because it uses highly
                optimized assembly language routines (the whole program
                is written in assembly language) to directly access the
                VGA hardware, instead of using ROM BIOS function calls
                to do the job.  On most computers that have VGA cards
                (except maybe some slow ATs or XTs), you will want to
                slow down the design.  You can specify a delay value in
                the range of 0 (fast) to 255 (very slow).  Example:

                        VGAMOIRE D35

                On 16MHz PS/2 Model 70's, a good delay value to use is
                usually about 35 or 40, but of course it depends on your
                taste.


        [E]     If you have EMS memory, you can tell VGAMoire to make
                good use of it.  VGAMoire will store all of its data in
                EMS memory, leaving much more RAM free for your normal
                DOS applications.  VGAMoire is compatible with EMS 3.1
                and higher (it even names its EMS handle under EMS 4.0
                and higher).  Example:

                        VGAMOIRE E

                Note that the [E] option cannot be used with the [N]
                option (which will be explained later).  Also note that
                VGAMoire reserves the total amount of EMS that it will
                use AT THE TIME IT IS INSTALLED.  To stop using EMS, you
                must uninstall VGAMoire and then reinstall it.


        [Fn]    This option tells VGAMoire to save and restore the VGA
                character generator RAM and the complete video state.
                You can specify how many font blocks to save and restore
                (from 0 to 8).  If you need this feature at all, saving
                just one font block will generally be enough.  Example:

                        VGAMOIRE F1

                Using this feature allows VGAMoire to correctly save and
                restore even such non-standard video modes as 60-line
                displays or 33-line displays.  Otherwise, VGAMoire can
                save all the information except the current character
                fonts and the screen size (changing the screen size
                requires loading an alternate font, so the two are
                really inseparable).  Saving fonts is a real memory
                guzzler, and I recommend only saving one font block, if
                any.

                If you are using EMS memory, you can change the number
                of font blocks to save by using the [Fn] option with the
                [N] option.


        [Kc]    This option allows you to set your own hotkey to pop up
                the screen saver.  You can use any combination of the
                Alt/Ctrl/Shift keys and one "normal" key.  You can set
                it to distinguish between the left and right Shift keys,
                or you can have it treat them the same.

                The syntax of this option is very simple.  First, of
                course, comes the "K".  After the "K", just type the
                names of the keys you want to use, surrounding each
                key's name with squigly brackets ("{}").  Examples:

                  1)    VGAMOIRE K{CTRL}{RIGHTSHIFT}{S}
                        This instructs VGAMoire to use Ctrl-RightShift-S
                        as the hotkey.

                  2)    VGAMOIRE K{ALT}{SHIFT}
                        This tells VGAMoire to use the Alt key and
                        either of the two Shift keys as the hotkey.

                  3)    VGAMOIRE K{CTRL}{F12}
                        This sets Ctrl-F12 as the hotkey.

                It is also possible to completely disable the hotkey:

                        VGAMOIRE K

                This disables the hotkey, so that it is impossible to
                manually pop up the screen saver.  To reenable the
                hotkey, just select a different hotkey.


                ──── LIST OF VALID KEYS ────────────────────────────────

                    {ALT}        - the Alt key
                    {CTRL}       - the Ctrl key
                    {LEFTSHIFT}  - the left Shift key
                    {RIGHTSHIFT} - the right Shift key
                    {SHIFT}      - either Shift key


                ──── LIST OF VALID "NORMAL" KEYS ───────────────────────

                    {A}..{Z}     - the letter keys
                    {F1}..{F12}  - the function keys
                    {0}..{9}     - number keys (NOT the numeric keypad!)


                        NOTE:  if you forget what the current hotkey is,
                               just type "VGAMOIRE ?" at the DOS prompt,
                               and if VGAMoire has been installed yet,
                               it will tell you what the current hotkey
                               is.


        [Ln]    You can make the moire pattern have up to 50 lines in
                it.  The default is 25 lines.  Example:

                        VGAMOIRE L40

                This would make VGAMoire generate a 40 line moire
                pattern.  You must tell VGAMoire to use at least one
                line (any less wouldn't really make much sense, now
                would it?).


        [Mn]    If you are experiencing trouble and either do not have a
                mouse, or have an old mouse driver, try using this
                feature before giving up.  This determines whether or
                not VGAMoire monitor the mouse hardware for activity (by
                default, VGAMoire will constantly monitor the mouse for
                any activity and restart the countdown if it detects
                any).  Example:

                        VGAMOIRE M0

                This tells VGAMoire to ignore any mouse activity
                (VGAMoire simply doesn't bother to monitor the mouse at
                all).  To tell VGAMoire to resume monitoring the mouse,
                you can use M1 instead of M0.


        [On]    VGAMoire can make the screen fade to black before
                drawing the design (or when blanking the screen).  The
                current application can even continue processing while
                the screen is fading out.  You can configure it not to,
                though, if you wish.  Example:

                        VGAMOIRE O0

                This tells VGAMoire not to make the screen fade out.
                You can tell VGAMoire to re-enable screen fading by
                using the O1 option (the default setting).  Note that if
                VGAMoire detects any activity while it is dimming the
                screen, it will restore the palette and will not blank
                the screen or draw the design.


        [Pn]    The VGA card has 8 video text pages, although DOS and
                most of the IBM programs only use page 0 (some programs
                draw screens on other pages and then transfer them to
                page 0 to make it seem as though they are drawing the
                display at lightning speeds).  You can use the [Pn]
                option to indicate how many video pages you wish to
                save.  VGAMoire saves however many pages you tell it to,
                starting with page zero (the pages are numbered 0
                through 7).  If you use the 50-line mode ever, you
                should probably save at least 2 pages.  Example:

                        VGAMOIRE P2

                This tells VGAMoire to save 2 video pages when it
                switches to graphics mode to draw the moire pattern.
                This option can be used with the [N] option if you are
                using Expanded Memory (see the [E] option).  Otherwise,
                to change the number of video pages that are saved, you
                must uninstall VGAMoire and then reinstall it.

                        NOTE:  if you use the NNANSI.SYS display driver
                               (or certain other "improved ANSI display
                               drivers"), you should be aware that it
                               can scroll the screen at a very high
                               speed by modifying the starting location
                               of the screen display buffer.  If you use
                               this feature of your display driver, you
                               should either tell VGAMoire to save all 8
                               video pages or tell your display driver
                               to scroll text the "old-fashioned way".

                        NOTE:  if you use a program that allows more
                               than 25 lines on the screen, you should
                               save at least two video pages, and if you
                               use a program which allows more than 50
                               lines, you need to save at least 3 video
                               pages.


        [Rn]    This controls how VGAMoire mirrors the pattern.  By
                default, VGAMoire doesn't mirror it at all.  You can
                instruct the screen saver to mirror the design
                horizontally, vertically, both horizontally and
                vertically together, or diagonally.  Example:

                        VGAMOIRE R2

                This would cause VGAMoire to mirror the pattern
                vertically (top-to-bottom).  Use [R0] to not mirror at
                all, [R1] to mirror horizontally, [R2] to mirror
                vertically, [R3] to mirror both horizontally and
                vertically together, or [R4] to mirror diagonally.


        [Sn]    By default, VGAMoire changes colors each time it draws a
                new line.  If you're using a large number of lines, or
                if the colors are changing more quickly than you'd like,
                you can make them change slower.  Example:

                        VGAMOIRE S3

                This would make VGAMoire change colors after every third
                line.  You can use any number in the range 1 to 255.  If
                you were using only 5 lines, and you wanted it to look
                like the pattern were slowly glowing, you might use a
                value of 10 or 12 with the [Sn] option.


        [U]     This lets you uninstall VGAMoire.  Please see the
                section "Uninstalling VGAMoire" for more information.


        [Vn]    Some programs which use the video BIOS to write to the
                screen  may confuse VGAMoire into never timing out.  If
                this happens, you can use this option to force VGAMoire
                to ignore video activity.  Example:

                        VGAMOIRE V0

                This tells VGAMoire to ignore any video activity.  To
                make VGAMoire resume watching for video activity, use V1
                instead of V0.


        [Wn]    As I demonstrated in the "Installation" section, you can
                specify a number of minutes to count down (Wait) before
                popping up the moire pattern.  VGAMoire can count down
                anywhere from 1 to 30 minutes.  Example:

                        VGAMOIRE W4

                This instructs the screen saver to count down four
                minutes before taking over and drawing the moire
                pattern.  Remember:  if you do not specify a number of
                minutes to count down (it must be a valid value to be
                recognized), VGAMoire will not become resident but will
                display its pattern until you press a key or move the
                mouse.


        [Zc]    VGAMoire can now monitor the COM ports directly for
                activity! If the Carrier Detect signal (for
                telecommunications) is present, VGAMoire will only blank
                the screen (allowing the telecommunications program to
                keep processing in the background).  If the Carrier is
                lost (or is just acquired), then VGAMoire will restore
                the screen.  In addition, VGAMoire will flash the border
                color when the phone rings (provided you have a modem
                attached to your computer and the phone line)!  I find
                this quite useful, because sometimes I wear headphones
                and can't hear the phone ring.

                You can tell VGAMoire which COM ports to monitor by
                using the [Zc] option.  To turn off COM port monitoring,
                use Z0:

                        VGAMOIRE Z0

                To specify a port(s) to monitor, give the port numbers:

                        VGAMOIRE Z12

                This would monitor COM1 and COM2 for activity.  If you
                want to turn off monitoring for a specific port, put a
                minus sign before its number:

                        VGAMOIRE Z-1

                This would turn off monitoring for COM1, but would not
                affect monitoring for other COM ports.


        [N]     Once VGAMoire is resident, you cannot switch back and
                forth between using EMS memory or conventional memory
                (the [E] option).  To switch, you must uninstall and
                then reinstall VGAMoire.  However, any of the other
                options may be changed even once VGAMoire is resident.
                To change them, just use the [N] option somewhere on the
                command line.  Example:

                        VGAMOIRE W2 N D30

                This changes the number of minutes that VGAMoire counts
                down before popping up to 2 minutes, and changes the
                delay value to 30.  No other options are changed.


        [-]     VGAMoire can be disabled from DOS with the [-] option.
                This allows batch files to turn off VGAMoire and then
                later turn it back on.  Examples:

                  1)    VGAMOIRE - N
                        This turns the RESIDENT COPY of VGAMoire off
                        (because the [N] option is used along with the
                        [-] option).

                  2)    VGAMOIRE - W4
                        This would install VGAMoire and set the
                        countdown at four minutes, but would also turn
                        VGAMoire off as it was being installed.  For
                        VGAMoire to be able to pop up, it would have to
                        be later turned on, which we will discuss next.


        [+]     To turn VGAMoire back on, use this command:

                        VGAMOIRE + N

                This turns the RESIDENT COPY of VGAMoire on (because the
                [N] option is used with the [+] option).  Using the [+]
                makes no sense unless the [N] option is used also,
                because VGAMoire defaults to being "on".  You don't need
                to do anything to install VGAMoire as "on".

                        NOTE:  the [-] and [+] options maintain a
                               counter, so they may successfully be
                               nested within batch files.




        ═══════ UNINSTALLING VGAMOIRE ══════════════════════════════════


        VGAMoire can uninstall itself and give both conventional and EMS
        memory it was using back to DOS.  Example:

                VGAMOIRE U

        The [U] option, just like any of the other options, can be used
        from the DOS prompt or from in a batch file.  If another program
        has taken over the interrupt vectors that VGAMoire captured,
        then VGAMoire will tell you and ask if you really want to
        uninstall it.  You can press 'N', 'Y', or ESC. If you hit 'N' or
        ESC, VGAMoire will print a message saying that it is still
        installed.  If you choose to uninstall it anyway, VGAMoire will
        try to uninstall itself.  This may result in a system crash,
        depending on what is loaded above VGAMoire.  You can allow
        VGAMoire to uninstall itself cleanly by uninstalling whatever is
        in memory above it first.  If the system does crash, just reboot
        (or turn the computer off).  Note that the system may not crash
        immediately.




        ═══════ EXAMPLES ═══════════════════════════════════════════════


        Here are some examples for installing VGAMoire:

                VGAMOIRE W4 P8 E F8 D40 S3 C1 L50 R3

        This tells VGAMoire to become resident and count down four
        minutes before popping up.  It will save all eight video pages
        in EMS memory, and will also save all eight character generator
        RAM blocks.  The delay to slow down the moire pattern is set to
        40 (the delay value is not an absolute measure of time, but
        rather is relative to CPU speed).  VGAMoire will change color
        every three lines, use rainbow colors, and will draw a moire
        pattern consisting of 50 lines.  Finally, it will mirror both
        horizontally and vertically.  This could be called the "full
        featured" installation, because it makes use of each of the
        special VGAMoire options.  It also uses the least conventional
        memory (3.8k) and the most EMS memory (112k).


        A less impressive configuration might be this:

                VGAMOIRE W4 P2 S3 C1 L20 D50

        This would again count down four minutes, but only save two
        video pages.  It would not use EMS memory, so it would take a
        total of about 12.8k of conventional memory.  It would change
        color every third line, use rainbow colors, and only draw 20
        lines in the moire pattern.  It would use a delay value of 50
        (again, the delay is arbitrarily relative to the CPU speed and
        follows a roughly linear graph of speed decrease as the delay
        value increases).


        Following is a sample batch file to disable VGAMoire before
        executing an application and then reenable it when the
        application returns to DOS:

                APP1.BAT
                ──────────────────────────────────────────────
                @ECHO OFF
                \TOOLS\VGAMOIRE N - >NUL
                CD\[GAME_DIR]
                [GAME]
                \TOOLS\VGAMOIRE N + >NUL


        Following is a sample batch file to make VGAMoire just blank the
        screen (instead of drawing the moire design) and allow the
        program to continue operating in the background (the screen will
        come back if any activity is detected--mouse, keyboard, disk,
        etc.  The batch file then executes an application. When the
        application is done, VGAMoire is reset so that it will draw the
        moire design again:

                APPBLANK.BAT
                ──────────────────────────────────────────────
                @ECHO OFF
                \TOOLS\VGAMOIRE N B0 >NUL
                CD\[APP_DIR]
                [APPLICATION]
                \TOOLS\VGAMOIRE N B1 >NUL




        ═══════ KNOWN CONFLICTS ════════════════════════════════════════

        ─── TELECOMMUNICATIONS ─────────────────────────────────────────

        It is reported that ProComm PLUS 2.0 has difficultly coexisting
        with VGAMoire.  We do not currently have any way to make them
        coexist.  VGAMoire recognizes when a modem has a CARRIER signal,
        but is cannot detect if a terminal program is auto-redialing.

        Use the previous sample batch file (APPBLANK.BAT) to run your
        telecommunication program, so that VGAMoire will only blank the
        screen and not suspend telecommunications by drawing the moire
        design.


        ─── DOS 4.0 and 5.0 ────────────────────────────────────────────

        To use VGAMoire with the DOSSHELL menu program, you will have to
        do one of two things.  If your AUTOEXEC.BAT or CONFIG.SYS file
        loads a mouse driver into memory, then you can edit the
        DOSSHELL.BAT file and make VGAMoire work with it perfectly
        (instructions are given below).  If you do not load a mouse
        driver into memory, but still want to use the mouse in DOSSHELL,
        then you have no choice but to configure VGAMoire not to monitor
        the mouse, otherwise DOSSHELL will have severe trouble
        responding when you press the mouse button.  Aside from this,
        VGAMoire is fully compatible with DOS 4.0 and 5.0.

        If you load a mouse driver into memory before using DOSSHELL,
        then you can simply edit one line in your DOSSHELL.BAT file to
        let DOSSHELL know this.  By default, DOSSHELL uses its own mouse
        driver, which is incompatible with the software standard for
        mouse drivers (I don't understand why Microsoft/IBM did it this
        way--it seems pretty stupid, to me).  What you need to do is use
        a file editor (eg: QEdit, EMacs, VEDIT, or even EDLIN) to modify
        the line that begins with "@SHELLC" (it will probably be a very
        long line).  Find where it says "/MOS:xxxxxxxx.DRV" and just
        remove that part of the line (the xxxxxxxx's may vary depending
        on your system).  This tells DOSSHELL that you have your own
        mouse driver installed, and that it should make use of it.

        For example, this is the DOSSHELL.BAT file that the DOS 4.0
        installation program created for me on my IBM PS/2 Model 70:

                @SHELLB DOSSHELL
                @IF ERRORLEVEL 255 GOTO END
                :COMMON
                @BREAK=OFF
                @SHELLC /MOS:PCIBMDRV.MOS/TRAN/COLOR/DOS/MENU/MUL/SND...
                        .../MEU:SHELL.MEU/CLR:SHELL.CLR/PROMPT/MAINT...
                        .../EXIT/SWAP/DATE
                :END
                @BREAK=ON

        To make VGAMoire work with DOSSHELL, delete the part that says
        "/MOS:....MOS" so that it looks like this:

                @SHELLB DOSSHELL
                @IF ERRORLEVEL 255 GOTO END
                :COMMON
                @BREAK=OFF
                @SHELLC /TRAN/COLOR/DOS/MENU/MUL/SND/MEU:SHELL.MEU...
                        .../CLR:SHELL.CLR/PROMPT/MAINT/EXIT/SWAP/DATE
                :END
                @BREAK=ON


        ─── GAMES ──────────────────────────────────────────────────────

        Many commercial games are not "well-behaved" programs, in that
        they take over certain parts of the operating system and just
        don't respect other programs.  With some games, VGAMoire might
        work perfectly, but with most it won't.  Usually, if the screen
        blanks while you are playing a game, you can try either hitting
        one of the Shift keys or moving the mouse.  If this does not
        restore the screen, you may have to reboot.

        For games that VGAMoire doesn't get along well with, you should
        disable VGAMoire before starting the game (see the "APP1.BAT"
        example in the "Examples" section).  You can also manually
        disable VGAMoire before playing the game by using the Ctrl-Alt-E
        hotkey.  Press Ctrl-Alt-B after you have finished with the game,
        to reenable VGAMoire.


        ─── MICE ───────────────────────────────────────────────────────

        VGAMoire is only mouse-sensitive with Microsoft-compatible mice;
        it cannot recognize Mouse Systems mice unless they are in
        Microsoft emulation mode (Logitech and most other popular mice
        should work fine--if the mouse has a Microsoft emulation mode,
        make sure you are using it, though).


        ─── MICROSOFT WORD ─────────────────────────────────────────────

        VGAMoire works fine with Microsoft Word, but with some SVGA
        video cards, the screen may be restored with blinking text on
        it.  This is a problem with some SVGA cards, and is not
        VGAMoire's fault, but we're looking for a solution.


        ─── SUPER-VGA ADAPTERS ─────────────────────────────────────────

        Some SVGA video cards (especially those based on the Tseng Labs
        chip) are NOT fully 100% IBM VGA compatible, even though they
        may claim to be.  VGAMoire tries its best to work correctly on
        such cards, but there may be some minor problems in restoring
        the screen after drawing the moire design.  Some cards may not
        be able to blank the screen, either.


        ─── MULTITASKING SYSTEMS ───────────────────────────────────────
        (such as DESQview, TopView, VM/386)

        Multitasking is hard to accomplish, and some multitasking
        systems will be able to run VGAMoire while others will not.  If
        your system is not described below, you will have to determine
        if VGAMoire can be run and, if so, how it must be configured.

        DESQview  -  VGAMoire is compatible with DESQview.  HOWEVER, YOU
                     MUST SET IT TO ALWAYS DO SCREEN BLANKING AND TO
                     IGNORE THE MOUSE, which you do by using the B0 and
                     M0 options (take a look at the "APPBLANK.BAT" batch
                     file in the "Examples" section).

        TopView   -  We have not had the opportunity to test VGAMoire
                     with TopView, but we believe it will behave under
                     TopView the same way as under DESQview.  On that
                     assumption, you should follow the directions for
                     DESQview (outlined above) for TopView, DESQview,
                     and any other similar multitasking software.

        VM/386    -  VM/386 works on a different principle than most
                     other multitasking systems.  VGAMoire works
                     perfectly with VM/386, but you must install
                     VGAMoire in each virtual machine that you want a
                     screen saver to be active in.  So, if you have four
                     VMs running, you will need to install VGAMoire in
                     each of the four VMs.  You should NOT install
                     VGAMoire before starting VM/386; install it in the
                     VMs, not in the VM Manager!  (This holds true for
                     nearly any TSR program with VM/386).


        ─── PRINT SPOOLERS ─────────────────────────────────────────────
        (or some programs taking a long time to print)

        You may experience problems with VGAMoire when using a print
        spooler (such as DMP or DOS PRINT).  VGAMoire may take over
        while the spooler is sending data to the printer (depending on
        how it sends the data).  The spooler should resume without any
        complications as soon as VGAMoire returns control to the current
        program (if you experience problems, be sure to let me know, so
        I can work on fixing them!).  If you want your spooler to be
        able to print data even once VGAMoire decides to activate
        itself, then you must use the [B1] option (see the description
        of the [Bn] option for more information).  Otherwise, printing
        will resume when VGAMoire is done drawing its moire pattern.




        ═══════ VERSION HISTORY SUMMARY ════════════════════════════════


        ─── v1.0 ─────────────────────────────────────────── 7/14/90 ───

                *  Original version.

        ─── v1.1 ──────────────────────────────────────────── 8/2/90 ───

                *  Deallocates the environment block to conserve memory.
                *  Support added to save/restore RAM fonts (w/EMS only).
                *  Mirroring feature added.
                *  Improved mouse sensitivity.
              >>>  Possible bug if no mouse driver was installed--fixed.
              >>>  Bug where keyboard locked up if no EMS memory
                   used--fixed.
                *  Only keeps one color set resident--saves memory.
                *  Frost colors added.

        ─── v1.2 ──────────────────────────────────────────── 8/7/90 ───

                *  Blanks the screen while changing modes, to avoid ugly
                   screen flicker.
                *  Now makes sure color register 0 (black) is really set
                   to black.
              >>>  Bug in restoring fonts made us never restore
                   fonts--fixed.

        ─── v1.3 ─────────────────────────────────────────── 8/13/90 ───

              >>>  The [N] option got broken in v1.2--now fixed.

        ─── v1.4 ──────────────────────────────────────────── 9/4/90 ───

                *  Better mouse state save/restore.
                *  Better sensitivity to keyboard and mouse.
                *  Graphics mode blanking added.

        ─── v1.4b ────────────────────────────────────────── 9/21/90 ───

                *  Source code reorganized so I can try adding support
                   for other video cards (no guarantees...).
                *  Improved video state save/restore.
              >>>  EMS-related bug fixed.

        ─── v1.5 ──────────────────────────────────────────── 1/3/91 ───

                *  Increased stability due to improved interrupt
                   monitoring and stack context switching.
                *  Now DESQview compatible!
                *  [-] and [+] options now maintain a counter.
                *  The popup hotkey works even if VGAMoire is
                   turned off.
                *  Glowing red colors added.
                *  Can make the screen fade to black.
                *  Can deallocate itself even from High RAM.
                *  Now has diagonal mirroring feature.
                *  Can select a custom hotkey.
                *  The parameters have been slightly changed.
                *  No longer beeps if it can't pop up (beeping could
                   cause a system crash under certain conditions).
              >>>  Using our own stack fixed some "mysterious" crash
                   bugs.
              >>>  Screen blanking bug fixed (sometimes crashed after
                   restoring the screen).
              >>>  [Mn] option was reversed, now works right.

        ─── v1.6i ────────────────────────────────────────── 4/18/91 ───

                *  Telecommunications support added:
                     o  Monitors Carrier signal on given COM ports.
                     o  If CD is present, only blanks screen.
                     o  If CD is present, ignores disk and video
                        activity.
                *  If VGAMoire is off hotkey is hit, only blanks the
                   screen.
                *  Border color flashes when phone rings (if a modem is
                   connected).
                *  The moire pattern fades in, too.
              >>>  Bug fix:  custom hotkeys only worked right if they
                   were limited to combinations of Ctrl, Alt, and the
                   Shift keys.
              >>>  Bug fix:  fixed problem which could cause potential
                   DOS instability and eventual crash.

        ─── v1.6TL ───────────────────────────────────────── 8/16/91 ───

                *  Better support added for VGAs which aren't 100% IBM
                   VGA compatible.
                *  Font blocks can now be saved in conventional memory,
                   as well as EMS memory.

        ─── v1.7 ─────────────────────────────────────────── 3/19/92 ───

                *  Now disables itself while Windows is running!

        ─── v1.8 ─────────────────────────────────────────── 3/30/92 ───

                *  OOPS!  Sorry, everyone.  Version 1.7 had a bug
                   which made it lock up as soon as you installed
                   it.  Thousands of apologies!!




        ════════════════════════════════════════════════════════════════


        I hope you find VGAMoire useful.  Thank you for your support.


                                        Christopher Antos


        ════════════════════════════════════════════════════════════════
VGAMoire 2.0
                          VGA MOIRE 2.0 REFERENCE CARD
                          ============================


                      VGA Moire v2.0 by Christopher Antos
                  Copyright (c) 1990-1993, All Rights Reserved



 -- COMMAND LINE OPTIONS ------------------------------------------------------

        /I      this option must be used to install VGA Moire into memory.
        /U      this option is used to uninstall VGA Moire from memory.
        /T      use this option to view the current settings.

        /-      disables VGA Moire from automatically engaging; hotkeys still
                work, though.
        /+      reenables automatically engaging after the time limit has
                expired; NOTE that /- and /+ are nestable, ie, if you use /-
                twice, you must use /+ twice to enable VGA Moire.
        /D      disable VGA Moire completely; even hotkeys don't work.
        /E      reenable VGA Moire (after using /D).

        /S      save a copy of the current settings.
        /R      restore settings from a saved copy.
        /R-     forget all saved settings.

        /Ln     set delay factor for line-drawing speed to n (0..1000).


    The following switches can be turned OFF by following them with a minus
    sign (-).  Options with a star (*) next to them are ON by default.

        /B      blanking only; never draw the design, just blank the screen.
        /F      fade out to blank when blanking the screen.
        /G  *   Ghost mode (see section "Ghost Mode").
        /H      alternate method of blanking the screen; some VGA cards require
                this option to work correctly.
        /M  *   watch for mouse movement or clicks and restore the screen.
        /P      enable password protection; screen will not restore until the
                correct password is entered and [Enter] is pressed.
        /V      watch for video activity and restore the screen; usually this
                is not necessary.

        /Wn     sets time limit to n minutes; VGA Moire waits until n minutes
                have passed without any activity and then engages.
        /Zn     set which COM ports to watch; COM ports recognized are 1-4, use
                0 to clear the list of ports to watch, eg. /Z1 watches port 1
                and whatever other ports were already being watched, /Z01
                watches only port 1.

 -- HOTKEYS -------------------------------------------------------------------

        [LeftShift]-[RightShift]  -  engage VGA Moire.
        [Ctrl]-[Alt]-[<]          -  turn VGA Moire off (hear one beep).
        [Ctrl]-[Alt]-[>]          -  turn VGA Moire on (hear two beeps).

 -- MSCONFIG ------------------------------------------------------------------

        Use the program MSCONFIG.EXE to change the default settings and change
        the password.  MSCONFIG creates a configuration file (MORNSTAR.INI)
        which belongs in the same directory where you keep VGAMOIRE.COM.

 -- GHOST MODE ----------------------------------------------------------------

        Thanks to a friend in Arizona (Gary Dobbins), VGA Moire has a special
        new mode which makes it compatible with modem redialers and also with
        networks.  VGA Moire will allow DOS programs to continue processing
        even while it is drawing the moire design.  It draws bits and pieces
        of the moire design during the time when other programs are idle.
        This means that you can leave VGA Moire on while your terminal program
        is dialing and it will draw the moire design until your modem connects
        to another computer.  Then it will restore the screen for you.  Once
        you are connected, however, it will only blank the screen to avoid
        interfering with high-speed file transfers.

 -- IMPORTANT NOTES -----------------------------------------------------------

    **  Never install or remove VGA Moire from a menu system.  Always do it
        from the DOS prompt (you can use a batch file if you want to) or in
        your AUTOEXEC.BAT file.

    **  VGA Moire does not work in conjunction with Windows.  It automatically
        disables itself to avoid crashing Windows.

    **  If you have a modem and VGA Moire is watching the COM port to which it
        is connected, you will see the border color flash whenever the phone
        rings.  Now you can wear headphones while working on your computer and
        still "hear" the phone when it rings!

    **  DESQview - To use VGA Moire with DESQview, set it to ignore the mouse
        and always blank the screen (use options /M- /B).

    **  SuperVGA - Some SuperVGA cards (particularly those with Tseng Labs
        chips) are *NOT* 100% IBM compatible, and there may be minor problems
        when restoring the screen (eg. in Word for DOS, the background colors
        may blink).

    **  GAMES - Most games are incompatible with screen savers.  We recommend
        turning off VGA Moire (use option /D) before running video games.

Discussion