
Black Display Driver 'use of' Document (version 2.0)

The Black Display Driver was written by Chris Leathley (Black) for Visual
Pinball by Randy Davis.

I can be contacted on leathley@bigpond.com or visit my home page at
www.users.bigpond.com/leathley

IMPORTANT NOTICE
----------------
This code is public domain but I do ask you acknowledge me if you use it in
your table.  The script can be modified by yourself but any modified
scripts are to remain with you and NOT reposted as enhancements
to the display driver.

I hope this document helps a lot of people understand how to implement and use
the Black Display Driver.  Examples are given and I also suggest looking at
the 'Black Knight 2000' or 'Fish Frenzy' script code for more examples or play
with the test table supplied with this release.  If you are new at programming
for visual pinball then I suggest 'Fish Frenzy' as it is a lot simpler in
operation.



Things to Consider if you are to use the Black Display Driver
-------------------------------------------------------------

The display driver was designed to emulate the displays used by Williams
pinball on their system 7 and system 11 games.  Though a lot of the effects
are fairly generic for general use in any table.

The Display driver basically handles static screens with a transitional effect
to put the screen on the display.  It currently is purely designed to support 2
lines of 16 characters.  In general williams style, these 2 lines are stacked
vertically but there is no reason why this has to be kept. The character count
can be changed if desired by changing a constant in the script but to make it
handle more or less lines would be more complicated. If you need it to support
a single line or more than 2 lines (ie 4) then it will need to modified which
requires more knowledge of Visual Basic Script and How the Display driver
works at a low level (something this document doesn't describe)

The limitations of the first version of the driver have been removed and
it is now possible to have any sort of combination of effects.

The Display driver looks the best with the Williams Pinball font as this is
fully fixed width.  There is no reason why any other font can be used but
scrolling effects will look bad if a non fixed width font is used.

The Number conversion routines have been designed to use the williams pinball
font to embed commas into the displayed number. ie. 500,000  is converted into
6 numerical characters and not 7 (the 0, will use a character which has a
comma embedded into it)



About the Williams PinBall Font
-------------------------------

The WilliamsPinball font was based on the 'transponder' font but that wasn't
100% fixed width and I needed something which was and also supported the comma
as part of the segment. By using a fixed width font I can get nice smooth
scrolling effects and the letters are always drawn in the same place no matter
what letter it is.  It took quiet a few days to get this font looking right
and I basically started from scratch as the original transponder font was
quick badly done.

The font uses the following codes

A-Z for uppercase A-Z (dah) without the embedded comma a-z for Uppercase A-Z
but with the embedded comma 0-9 for numbers without the embedded comma
chr(192) - chr(201) for numbers with the embedded comma plus the usual extra
symbols.  ie []/@^*()-+=\_' there is one special character ` which is used for
the Williams backarrow (something I use in my high score entry code)

The font looks best at a pitch of 22 (or 32 if you want something real big)
and with font smoothing turned on. (via a setting under display in the
windows control panel)



Upgrading Information
---------------------

If you are using version 1.1 of the display driver there are a few minor
changes to make to your table.

DisplayInit() now has 3 parameters

'gpBallsPerGame' has been renamed to 'BallsPerGame'

Effect Numbers are now defined as constants to make readability of your script
slightly better.

dcCHARSPERLINE contains the number of characters per display line to handle.
If you have smaller and larger requirements then modify this constant.



Implementing the Display Driver into a new table
-----------------------------------------------

Table Elements
--------------

Create a text box with the name 'TextBoxTop' which has a width of 295 and a
height of 40. Ensure that the alignment is TextAlighLeft.  Click on the Font
button and select the 'pinball.ttf' font, with a size of 22.  If you want to
use the font in Italic mode then make the text box width slightly wider or
part of the display will be clipped off (this is generally the last word in
the display).  There is nothing I can do about this and the problem isn't with
Visual Pinball is with the Windows Canvas API which is clipping the text
correctly.  Anyway back the plot..

Create the same as above but for a text box called 'TextBoxBottom'

Create 2 timers somewhere on the board called 'DisplayTimer' and
'DisplayEffectTimer'. Ensure that they are not enabled.


Script Elements
---------------

At the top of your script add the following line.

' include functions from the Black Display Driver
ExecuteGlobal CreateObject("Scripting.FileSystemObject").OpenTextFile("BlackDisplayDriver_v2.vbs", 1).ReadAll

Ensure that the 'BlackDisplayDriver_v2.vbs' file included in this release is
in the same directory as your table

In the Table init function place in the following 2 lines of script with
initalises the display driver, clears the text boxes and ensures that
everything is ready for use

Sub Table1_Init() ...
        ' initalise the display driver
        DisplayInit 25, 4, 2
        ...
End Sub

The 3 Parameters for Display Init are as follows;

        25      Time (in Milliseconds) between each frame of an effect.
                25 is the default and gives a nice smooth scroll
                20 is a good value is you want a little more pace
                I wouldn't make it much lower than that.

        4       Number of effect frames for the slow blink (more of this later)
                That means that it takes 4 * 25ms (in this example) for
                each blink phase.  So it turns on blinking text for 100ms
                and then off for 100ms.

        2       Number of effect frames for the fast blink. Same rules as
                above only at this second rate.


A global variables called Score (ie. Dim Score) is used to contain the current
score to be displayed. If you are making a multi-player game then ensure that
the current active play has his score copied into the Score variable.

Now in my standard score display screen I display the ball number on the
second line (as per Williams standard).  To do this I have the following 2
variables

Dim BallsPerGame
Dim BallsRemaining

'BallsPerGame' is generally set to 3 (or 5) in the Table1_init() function.

At the start of a new game then I set BallsRemaining to BallsPerGame eg,
        BallsRemaining = BallsPerGame
and this gets decremented by 1 each time a ball is lost (goes down the drain)
(if you support extra-balls then you wouldn't decrement it if the next ball is
an extra ball.

You don't have to use these variables but if you don't or want to change the
look of the score screen then you will have to modify the display score script



Use of the Display Driver in your game
--------------------------------------

The Display driver uses a queue to allow screens to be remembered and drawn in
the sequence they where put into a queue.  This allows the actual game script
to just give it a screen and not have to worry about drawing it and when it is
drawn.  It is important to remember that once a display has been put into the
queue there is no way to remove it unless you 'flush' the queue which removes
ALL the displays.

The follow API functions are used to control the display driver

DisplayFlushQueue()
DisplayScore()
DisplayScoreNow()
DisplayQueueScreen()
DisplayScoreQueue()

and the following support functions can be used for number conversion

FormatScore
FormatScore1M
FormatScore1K

The Display driver will display each screen in the queue in the sequence it
was put into the queue, with the transition effect(s) for that screen.  Once
all the screens in the queue have been processed then the display driver will
either restart from the beginning of the queue again, or automatically flush
the queue and display the default score screen.

The score screen has the lowest priority.  it is only displayed if the queue
is empty.

Any new screens put into the queue take effect immediately if the queue is
empty



DisplayFlushQueue()
-------------------

This function will immediately empty (flush) the queue and stop any more
updates of the display. (this includes reverting back to the standard score
screen)

This function should never really be used on its own and should be followed by
either DisplayScore() or DisplayQueueScreen() to ensure that the display
driver has something to go on with.

DisplayFlushQueue() is generally used in the game when an important screen has
to be displayed immediately and not queued up for display at a later time.  For
example.  When a ball is lost down the drain, then you will most likely want
to do a bonus screen immediately and not have to wait for the other displays
(if any) to be processed before the bonus screen is put up.



DisplayScore()
--------------

This function displays the default score screen (score and ball number) if the
queue is empty.  If the queue is not empty then this function will not change
the display

The Standard screen is (assuming 16 characters) is
'        0       '
'          BALL x'

This allows displaying scores upto 1 billion.  As mentioned before the score
is displayed with the 'WilliamsPinball' font in mind so the score is modified
to included segments with comma embedded into them.



DisplayScoreNow()
-----------------

This function effectivly (and does) call DisplayFlushQueue() which will empty
the queue and then call DisplayScore() which displays the default score
screen.

I can't really see much use for this function but I'm sure somebody will use
it..



DisplayQueueScreen()
--------------------
DisplayQueueScreen(Text1,
                   Text2,
                   EffectOnT1,
                   EffectOnT2,
                   DelayT2,
                   TimeOn,
                   bFlush,
                   Sound)

Now for the complex one ;-)

This function has several parameters (Text1, Text2, EffectOnT1, EffectOnT2,
DelayT2, TimeOn, bFlush, Sound) which must be specified to instruct the
display driver how to process this display

** Text1 and Text2 are 2 16 character strings which are to be displayed.
either of these 2 parameters can be set to "-" which instructs the display
driver not to touch the line (this will be explained a bit more later on)
If these strings are not 16 characters a warning message box will be displayed
letting you know of this oversight. ;-)

** EffectOnT1, EffectOnT2 contains the transitional effects code, these are

eNone             - Display the Line immediately
eScrollLeft       - scroll the line on from the right
                    (moving in a left direction)
                    Current text will scroll with the next text
eScrollRight      - scroll the line on from the left
                    (moving in the right direction ;-)
                    Current text will scroll with the next text
eBlink            - The Entire Line will Blink at the slow blink speed
eScrollOut        - Scroll the Line out from middle to the edges
eScrollIn         - Scroll the Line in from the edges to the middle
eScrollLeftOver   - scroll on from the right (over current text)
eScrollRightOver  - scroll on from the left (over current text)
eBlinkFast        - The Entire Line will Blink at the fast blink speed
eTrailIn          - Trail in towards the middle
                    (useful for only characters in the middle)
                    (ie Multiplier Screens)
eBlinkMask        - Blinks only non space text in text line over current text
                    line (slow speed)
eBlinkMaskFast    - Blinks only non space text in text line over current text
                    line (slow speed)

There are no limitations of combination of effects but please not that the
effect is for the entire line.  Each line can have a different effect applied
to it.

If the Effect speed is set to 25 milliseconds it will takes 400 milliseconds
to scroll the text line onto the display (16 * 25 = 400) or halve that if the
effect is a ScrollIn or ScrollOut effect.  This is important to remember if
you need precise timing in your game.  If you don't then wipe this from you
mind (I know I have ;-)

** DelayT2 contains the delay (in characters) to use between scrolling the top
line and the bottom line.  For example.  Most williams games scroll in the
high scores from the left to the right with a small delay between the 2 lines.
This value is given in characters which means that a value of say 4 will start
scrolling in the second line after 4 characters have been scrolled on the top
line.

** TimeOn.  The time in milliseconds this screen is held before moving to the
next display in the queue.  If the effect is a Blink, then this is the time
the text blinks for.

** bFlush.  Instructs the display driver to flush the queue if this is the
LAST display in the queue.  Valid values are TRUE or FALSE.  Generally during
a game you will always specify TRUE as you will want to display to revert back
to the default score screen when your effect screen has finished.  During the
Attract mode though you will want it to be FALSE as you will want the attract
mode displays to automatically restart when they have finished.  this allows
you to only put the displays in once and not have to worry about the driver
running out of things to do.

Note, this flag is only looked at if it is the last display in the queue.  so
if you put in 2 displays with the value of TRUE for both of them, the second
display is still processed even though the first one tells the driver to flush
the queue.  You must call DisplayFlushQueue() to purposely flush the queue.

** Sound.  The sound file to play when this screen is first processed. This
allows corresponding sounds to be sync'd up with the appropriate display (ie a
bonus sound or something).

Some Examples (taken from Black Knight 2000)...


DisplayQueueScreen "  BLACK KNIGHT  ", "      2000      ", eNone, eNone, 0, 2000, TRUE, ""

Will display "  BLACK KNIGHT  " on the top line and "      2000      " on the
bottom line for 2 seconds (or 2000 milliseconds) before reverting back to
the default score screen.  No sound is played.


DisplayQueueScreen "   SKYWAY LIT   ", " FOR 1 MILLION  ", eBlink, eBlink, 0, 1500, TRUE, "WilliamsError"

Will blink the 2 display lines for 1500 milliseconds and play the
WilliamsError sound (in my case this is the bing-bing-bing sound or alert
sound)


DisplayQueueScreen " BALL 1 LOCKED  ", "                ", eScrollLeft, eScrollLeft, 0, 2000, TRUE, ""

will scroll the Text onto the display moving from right to left and hold the
display for 2 seconds.  Not that this scrolling scrolls the existing text on
the display is scrolled off.  This is why I specify a completely blank link.
it will scroll the bottom line off leaving a blank line


DisplayQueueScreen "TABLE CONVERSION", " CHRIS LEATHLEY ", eScrollRight, eScrollLeft, 0, 2000, TRUE, ""
DisplayQueueScreen "                ", "                ", eScrollRight, eScrollLeft, 0, 100, TRUE, ""

will scroll in the top line --> and the bottom line <--, pause for 2 second
and then scroll the line off replacing it with a blank display.  remember that
the effects applies only to drawing a screen.  There are no off effects as
such.


DisplayQueueScreen "  BALL LOCKED   ", "  CHALLENGE ME  ", eScrollLeft, eScrollLeft, 0, 200, TRUE, ""
DisplayQueueScreen "-",                "  CHALLENGE ME  ", eBlink, eBlink, 0, 1000000, TRUE, ""

This will scroll on the first display onto the screen (right to left), pause
for 200 milliseconds before blinking the second line (for a VERY long time).
The "-" for the fist line means that it is not touched. This display is used
when I lock a ball in challenge mode and it blink the text until the player
releases the new ball put into the shooters lane (ie I call
DisplayFlushQueue() when it leaves the shooters lane and hits the first
trigger)


DisplayQueueScreen "KNIGHT CHALLENGE", " WAR = MILLION  ", eNone, eNone, 0, 10, TRUE, ""
DisplayQueueScreen "-",                "       MILLION  ", eNone, eBlinkMask, 0, 2000, TRUE, ""

Will Display the first screen with no effect and then blink only "MILLION" on
the second line for 2 seconds.  eBlinkMask will only flash non-space text
in the text line and doesn't touch the text underneath.



DisplayScoreQueue()
-------------------

Allows the default score screen to be scrolled back onto the display

** EffectOnT1, EffectOnT2 contains the transitional effects code. these are
the same as DisplayQueueScreen()

This function is used for fast short scrollers and allows the effect to
continue on.

ie.
DisplayQueueScreen "-", "  ** NO WAY **  ", eScrollLeft, eScrollLeft, 0, 15, FALSE, ""
DisplayScoreQueue eScrollLeft, eScrollLeft

will scroll "  ** NO WAY **  " on the second line, which expires after 15
milliseconds (basically immediately).  The score screen is then scrolled in to
replace the "  ** NO WAY **  ".  Gives the impression of "  ** NO WAY **  "
quickly scrolling across the screen



FormatScore() and FormatScore1M()
---------------------------------
FormatScore(Num)
FormatScore1M(Num)

Will return a string of the number passed in.  Note that the string will be
returned so it can be drawn by the 'WilliamsPinball' font.  if you are not
going to use this font then I suggest you don't use these functions or you
modify them for your own purposes.

FormatScore() will return a string of 9 characters allows numbers of upto 1
billion to be displayed.  The number will be right justified and comma split
if greater than 1000

FormatScore() will return a string of 6 characters allows numbers of upto 1
million to be displayed.  The number will be right justified and comma split
if greater than 1000

example;

DisplayQueueScreen "GREATEST HEREOES", "                ", eScrollLeft, eScrollLeft, 0, 2000, FALSE, ""
DisplayQueueScreen "1> "&gsHighScore1Name&" "&FormatScore(gsHighScore1), "2> "&gsHighScore2Name&" "&FormatScore(gsHighScore2), eScrollLeft, eScrollLeft, 6, 2000, FALSE, ""
DisplayQueueScreen "3> "&gsHighScore3Name&" "&FormatScore(gsHighScore3), "4> "&gsHighScore4Name&" "&FormatScore(gsHighScore4), eScrollLeft, eScrollLeft, 6, 2000, FALSE, ""

The gsHighScore1Name and gsHighScore1 (and Score2) are my variables which
contain the high score name (3 charactors) and score

The Text string for these displays looks a little complex as it has to be made
up by appending (&) several string together.  It is best to keep the total
string length to 16. the string is made up using the following rules "1> XXX
#########".  there is a small delay between scrolling on score 1 and score 2
(and the same for score 3 and 4).



FormatScore1K()
---------------
FormatScore1K(Num, bZero, bComma)

Will return a string or 3 characters of the number passed in (allows numbers
of upto 1 thousand to be displayed. The number will be right justified

** Num - Number to be converted
** bZero - Wether to zero fill the number (if used in the game script this
will always be FALSE (this function is used by the other 2 number conversion
functions)
** bComma - wether to draw the last digit with a comma (as above will be
FALSE for in-game script use)

FormatScore1K(10, FALSE, FALSE) will return " 10"

FormatScore1K(1, TRUE, FALSE)   will return "001"

