P
ADVANCED AHK AND JOHNNY5 CONCEPTS
INTRODUCTION
This page will look
at some
options with the AutoHotKey Script and Johnny5 that are not required
for MAME™ usage and are too detailed to explain in the main
pages of
this site. It is assumed that you will have a good
familiarity with the standard useage of Johnny5 and AHK so the
explanations here will be less detailed than the main page sections.
Most of the credit
for these
workarounds goes to papaschtroumpf (mainly) and popcorrin from BYOAC.
I haven't done a lot with this, but I have verified the basic
functionality.
The concepts can
work fairly well with either PC games or other emulators, either arcade
or console. Generally speaking, the steps to be undertaken
are as follows:
- Configure Johnny5 (or CPViewer/CPVW) to work with the
non-MAME games - the main focus of this page!!! (I recommend
having a copy of Johnny5 for each application, but this is not strictly
required, although you probably want at least one version for MAME
games and one version for non-MAME games.
- Configure the AHK script to work with Johnny5 - Briefly
covered at the start of the page, but as long as your non-MAME
application has a way to Pause the action, implementing this is fairly
straightforward. It's probably good to have a copy of the AHK
script for each application, but is not necessarily required.
- Configure your batch file to launch the AHK script and the
non-MAME game program. I don't cover this, but it is fairly
straight-forward. You will almost certainly need a different
batch file for each non-MAME application.
- Configure your front-end to launch the batch file.
You may want a copy of the front-end in a separate folder, or
not. I cover this briefly for MAMEwah and in detail for
EmuLoader. You should probably verify that you like the way
to handle this with your frontend before attempting any of the other
steps.
BASIC CONCEPTS
This page basically
divides into three sections:
- AHK Script
Concepts - Basically
there is too much (or too little) to do with the AHK Script to cover it
here. I will briefly look at some options, but for the most
part,
I won't deal very extensively with the AHK Script and it's
modifications.
- Johnny5
Concepts - The main focus of this section is how
to utilize Johnny5 with non-MAME™ games and emulators.
Basically, this is done by creating a "fake" controls.ini
file and letting Johnny read this. MAME must be installed for
Johnny5 to work properly, but all the data will be gathered from the
Johnny5 layout file and the "fake" controls.ini file.
- CPViewer/CPVW
Concepts - I will briefly cover these
because papaschtroumpf mentions them and they may be helpful .
. .
- Frontend
Concepts - This
section explains how to set up MAMEwah and EmuLoader for non-MAME
applications.
AHK SCRIPT CONCEPTS
A detailed
description of all the ways to utilize the AHK Script and possible
modifications to it is far beyond the scope of this page. I
will provide some ideas, and unfortunately, either you will likely be
able to expand these concepts to make the script do what you want, or
you won't. . . There are basically three ways of modifiying
the AHK Script (aside from completely different AHK Scripts for new
functions):
- Using The AHK
Script With Other Games or Emulators - This is
of course one of the most popular uses of the AHK Script and also one
of the easiest to implement. All it basically involves is
finding out what keys the other game or emulator uses to Pause, Resume,
and Exit, and then plugging these keys into the existing script, and
then writing a batch file to call the script and the other game or
emulator, and calling this from a frontend.
- Using The AHK
Script To Launch Other Programs Besides Johnny5 From MAME - Basically,
this consists of either adding additional key inputs to the script or
modifying the program the script calls, or both. There
are very few examples where this might be useful, but some that come to
mind are:
- Adding HotKeys to the Script to display instruction cards
or arcade control panel images from a HotKey when MAME is paused.
- Launching a spreadsheet with the project you were supposed
to be
working on when MAME is paused as the boss is walking through the
office.
- Displaying static images rather than creating them with
Johnny5 when MAME is paused.
- Launching a ScreenSaver or Jukebox program when MAME is
paused.
- Adding
Functionality To The Current Script - I
will add a practical example here: Papaschtroumpf wanted to
be
able to exit Johnny5 by pressing any key on his control panel.
If
we are using the Method 4 Script,
this can be done by adding the following code to the custom AHK script
(repeated keys will each perform the action that follows them):
- ~Up::
~Down::
~Right::
~Left::
~<additional
controls>::
If ScreenState =1
{
ScreenState=-1
BlockInput On
Send,{Escape down}{Escape up}
WinActivate,%Title%
WinRestore,%Title%
WinActivate,%Title%
WinWaitActive,%Title%
sleep 250
Send,{p down}{p up}
ScreenState=0
BlockInput Off
}
return
- The above code (inserted
into the Method 4 Script) will allow the user to
exit Johnny5 whenever the joystick is moved. Adding
additional
lines of code would allow the user to exit when any control panel key
is
depressed. (However, I am not sure what effect this might
have on
MAME performance. . .)
The
results you could
achieve with modifications to the AHK script are pretty impressive.
I have not tried it out and don't have room to post it in
detail,
but you can read about it here
(local edited mirror here).
JOHNNY5
THEORY AND LIMITATIONS
Papaschtroumpf
actually has more experience with using Johnny5 with PC games and I
will rely highly on his descriptions for the instructional part of the
text, but for now I will try to explain, for those who want to know, as
best I can why we
are able to use Johnny5 with non-MAME games. This is a
simplified example, and may not be 100% accurate, but should give you
an idea of how this is accomplished. First, this is how
Johnny5 normally works when we pass it a romname:
- Unless passed as a command-line flag, Johnny5 searches MAME
for the parent and driver of the romname. It uses this to
detemine controller file key assignments. Fortunately, if the
romname is not found, it assumes the default key assignments.
(This is the first thing we will exploit.)
- Next Johnny5 searches controls.ini for gamename, or
parentname or drivername. It uses this and the previous MAME
controller inputs to determine key mapping. In other words -
From MAME, P1 Button 1 is L Ctrl. From controls.ini, P1
Button1 is FIRE. Therefore, L Ctrl = FIRE.
Fortunately, it makes no check for whether the controls.ini
entries are valid MAME entries - (MAME does not actually support 14
game buttons for Player 1, but Johnny5 does!) (This is the
other exploit.)
- Finally, Johnny5 uses these key mappings and information
from the .lof file to place the label in the appropriate position.
I.e. L Ctrl = FIRE and the .lof has a label for L Ctrl right
over the red button so the FIRE text should go over the red button.
With this info we
can deduce the following conclusions:
- It is highly recommended
to place a second copy of Johnny5 in a separate folder for use with
non-MAME games, if not even separate copies in separate folders for
each type of
non-MAME game. There are two primary reasons for this:
First, we will be generating a customized controls.ini for
use with this method. It would be good if this file does not
have a high risk of being overwritten and lost when we happen to
download the latest update to the official file. Second, the
. lof that we want to use with non-MAME games will likely be very
different than the one we use with MAME games. The concept of
alternating play or P1 Joystick type, etc. have very little meaning and
we might well choose to ignore them. OTOH, we may well want
to use the coin and start buttons for gameplay in non-MAME games, but
the MAME layout will ignore them.
- For the concept to work,
MAME must be installed, even if no MAME games are enabled on the
computer. Ideally, this should also be a copy of MAME in a
separate directory (we will likely be defining some inputs that won't
make sense to MAME, but this doesn't hurt anything, so it is not
required to create a copy). There is no reason to install any ROMS in
this copied directory, so the disk space usage should be minimal.
- The MAME files do not need
to be modified at all unless we are using buttons other than the
standard Player 1 buttons and Player 1 joystick directionals for the
non-MAME
games. If we are using the P2 Joysticks or Buttons for
functions other than the corresponding P1 buttons, we need to modify
the default ctrlr.cfg file for MAME and possibly also the Johnny5 .lof
layout file.
- Of the MAME files, only the
default ctrlr.cfg file needs to be modified. There is no
reason to create individual romname.cfg files, and in fact, I am not
sure these would even be supported as the game would not be part of
MAME.
- Actual key assignments and
number of buttons used do
not matter and actually are intentionally ignored.
For example, let's say my buttons are labelled like this:
- and I use the default MAME
assignments in my
MAME ctrlr.cfg file and my Johnny5 .lof file. I want to set
up
Johnny5 to work with a PC game that has two buttons FIRE and BOMB.
The game uses "F" for FIRE and "B'" for BOMB and cannot be
remapped, but I want Button 7 (the blue/black button) to be FIRE and
Button 1 (the red button) to be BOMB, and plan to remap my encoder so I
can play this way. For the custom controls.ini entry, I
simply
show the game as using 7 buttons with Button 1 as BOMB and Button7 as
FIRE. This will work perfectly. The method does not
care that the game actually uses 2 buttons, not 7, nor that
the keypresses sent are "F" and "B", not "C" and "L Ctrl"!
- Changes to key assignments
will not be
automatically detected. For example, let's say I want to set
the yellow button as FIRE as opposed to the red button. With
MAME, I simply change the P1_Button1 key assignment, and Johnny5
detects the change and adjusts accordingly. With a non-MAME
game, I need to change both the key assignment in the non-MAME game (or
the custom program for the keyboard encoder), and also change the
custom controls.ini entry for the non-MAME game.
- Finally, it is possible in
some cases to take advantage of the -driver flag of Johnny5 to reduce
the number of controls.ini entries required. For example,
let's say we are making a configuration for SNES emulation using ZSNES.
It would be nice to have the program set up with all the key
combinations and tricks for Donkey Kong 2 and Donkey Kong 3, etc.but
initially, it would be better to just have a display of which buttons
were A, B, X, and Y for all ZSNES games. We can do this by
creating an entry for romname ZSNES1 in controls.ini and then launching
Johnny5 in one of the following ways:
- If our frontend supports
assigning driver
names to each entry and passing driver names to a batch file, you can
make each game use imaginary driver ZSNES1.
- You can modify the ahk
script so that it calls "Johnny5 %1 -driver ZSNES1" manually instead of
leaving off the driver parameter.
- You can modify the ahk
script so that it calls "Johnny5 ZSNES1" for these games, but passes
the romname to the emulator.
JOHNNY5
SETUP OVERVIEW
If you
don't care about the theory and just want to get on with it, the steps
to modify Johnny5 are basically as follows:
- Optionally,
copy Johnny5 to a new directory.
- Add
fake entries to controls.ini for the non-MAME games.
- Modify
MAME's default controller .cfg file if you use any buttons other than
the P1 Joystick directionals and P1 Buttons in the non-MAME game.
- Modify
Johnny5's .lof file(s) if you use any non-action (Coin, Start, Admin)
buttons as action buttons in the non-MAME game.
JOHNNY5
SETUP
The first optional,
but recommended, step to this procedure is to copy the entire c:\johnny
folder and subfolders to a new directory, for example, c:\johnnypc.
Most
of the concepts for this page came for this BYOAC
thread (local mirror from 13 Oct 05). I ended up quoting most of the thread, but
have also expanded on it and also sorted the data into the appropriate
sections.
The first
thing I did was test Popcorrin's
idea of creating a dummy entry in the controls.ini file. I
modified c:\johnnypc\data files\controls.ini and added the following
between two of the existing games:
- [testgame]
gamename=This
is a test
numPlayers=2
alternating=0
mirrored=1
tilt=0
cocktail=1
usesService=0
miscDetails=This
is only a test
P1NumButtons=3
P1Controls=8-way
Joystick+joy8way
P1_BUTTON1=Test
1
P1_BUTTON2=Testing
2
P1_BUTTON3=a
Test
Then
I ran "Johnny5 testgame"
and it displayed fine, as below (click twice to enlarge):

NOTE:
The
information below in yellow
was provided by papaschtroumpf, my comments are
in white.
I
do
have additional information, and I think I'm 95% of the way where I
want to be:
It
seems the
easiest way to do this is to add your PC games at the end of the real
controls.ini. I think I'll keep a PCcontrols.ini file that I can append
at the end of the official controls.ini whenever I download a new
version. Just like you did, I kept all the fields that appear in a
regular mame entry, maybe it's not necessary but it won't hurt. You can
even set the alternating and numplayers fields to describe the game if
you want to.
EDIT: I
recommend creating a new controls.ini in the c:\johnnypc\data files\
folder rather than c:\johnny\data files\.
You
then just
set P1NumButtons and enter the proper P1_BUTTON? labels, just like in
your example. Make sure that P1NumButtons is set to the
correct value, or
Johnny5 will ignore "extra" button labels.
I
had another
problem to solve: In my PC games, I use additional buttons
that are
either not used in MAME or are considered "admin" buttons by Johnny5
and therefore ignored by its parsing.
For
example I
may have mapped a PC game control to the "1" key, which is the Player 1
Start key for MAME, labelled "START1" in the CTRLR files.(Default
CTRLR file is C:\MAME\CFG\default.cfg). I tried
adding "START1=test" to the entry in controls.ini, but johnny5 ignores
it, even if I create a label for "KEYCODE_1" in the layout
designer.
Johnny5 seems to only match KEYCODE_? labels in the layout file to
P1_BUTTON? entries in the control.ini.
EDIT: Johnny5
also ignores Player2_ButtonX= entries in the controls.ini file, using
the P1_ButtonX entry instead.
I
managed to solve the problem with the following "hack":
I
defined my
additional buttons as P1_BUTTON10 through P1_BUTTON14 in my CTRLR file.
I don't have Internet access at home right now (typing this from work)
so I can't cut and paste what it looks like, but just look at the
definition of "P1_BUTTON1" and cut and paste it and modify the button
name to P1_BUTTON10 and change the keycode to the correct value.
Note
that's
it's OK to have multiple definitions for a single keystroke. For
example mame's START1 is mapped to the "1" key, but you can also map
"P1_BUTTON10" to the same "1" key.
EDIT: I
personally would start with P1_BUTTON11 through P1_BUTTONXX since MAME
already has a default P1_Button10 assignment (although the only game I
know that approaches that many buttons would be the Whack-A-Mole type
games and they only use nine.) To avoid confusion, I am using
P1_BUTTON10 and up in the examples.
Here
is what the added code in the c:\mame\cfg\default.cfg file should look
like (although leaving the defaults for P1_BUTTON10 is optional and I
am guessing what papaschtroumpf used for buttons 11, 12,
and 13):
- <port
type="P1_BUTTON10">
<defseq
type="standard">KEYCODE_1 OR KEYCODE_N OR
JOYCODE_1_BUTTON10</defseq>
</port>
<port
type="P1_BUTTON11">
<defseq
type="standard">KEYCODE_5</defseq>
</port>
<port
type="P1_BUTTON12">
<defseq
type="standard">KEYCODE_2</defseq>
</port>
<port
type="P1_BUTTON13">
<defseq
type="standard">KEYCODE_TAB</defseq>
</port>
<port
type="P1_BUTTON14">
<defseq
type="standard">KEYCODE_P</defseq>
</port>
etc.
I highly recommend
manually
making a chart of button assignment to panel button and saving it for
future reference, something like:
P1_BUTTON10 = Start 1
P1_BUTTON11 = Coin 1
P1_BUTTON12 = Start 2
P1_BUTTON13 = Orange button on front of control panel
etc.
You will also want
to assign
buttons for Joystick 2 and the Player 2 buttons, say P1_BUTTON15
through P1_BUTTON26. This should cause no problems for MAME,
as
2-Player games will not use more than 15 Player 1 butttons, and PC
games won't typically have any Player 2 buttons.
You might end up
with a lot of
defined fake Player 1 buttons, up to the limit of your encoder.
You might even include shifted inputs, which I think you
could
display in a different color than primary ones by customizing your
Johnny5 layout (.lof) file. One thing to consider is screen
real
estate for the PC games. The image below (click to enlarge)
was
something I worked up in Microsoft Word for Microsoft Train Simulator.
Red entries are shifted
entries. This
would be difficult to fit on a Johnny5 layout and impossible to view on
an arcade monitor. (And I left out some less often used
controls):
I
then added
the corresponding keycode labels in my Johnny5 layout file (c:\johnnypc\layouts\*.lof
file, using the layout editor function of Johnny5), for
example I added
a label for KEYCODE_1 under the picture of the Player 1 Start button
(which is now also defined as P1_BUTTON10).
NOTE: You
might want to make other customizations to your .lof file at this time.
For example, the "2-Player Simultaneous/2-Player Alternating"
field doesn't make sense for a lot of non-MAME games, so you might want
to remove it, etc.
A
(controls.ini)
entry for a game would then look something like this:
- [testgame]
gamename=This
is a test
numPlayers=1
alternating=0
mirrored=0
tilt=0
cocktail=0
usesService=0
miscDetails=This
is only a test
P1NumButtons=14
P1Controls=8-way
Joystick+joy8way
P1_BUTTON1=Fire
P1_BUTTON2=Bomb
P1_BUTTON3=Evade
P1_BUTTON4=Flare
P1_BUTTON5=Countermeasures
P1_BUTTON6=Afterburner
P1_BUTTON7=Bail
P1_BUTTON10=Map
P1_BUTTON11=Switch
View
P1_BUTTON14=Menu
The
entries
in blue show
the "regular" mame buttons and the entries in red
show the
"additional" buttons that are either unused or admin buttons in mame.
For example P1_BUTTON10 is tied to key "1" as explained above and
P1_BUTTON14 is tied to "P" on my cab.
After initially reading
this, I asked papaschtroumpf for clarification on the
following:
Okay, so I can
have a
P1_BUTTON14 and Johnny is happy with it even though MAME doesn't define
this?
Okay, I re-read
your example and that seems to be what you are saying. . .
He replied
with the yellow text below:
Yes
it
is.
As
far as
MAME is concerned, the 1 key is mapped to the START1 "event", it will
ignore the fact that 1 is also mapped to "P1_BUTTON10"
As
far as
Johnny5 is concerned, it will see that P1_BUTTON10 is mapped to the 1
key and that it has a label for KEYCODE_1 so it will display the
P1_BUTTON10 entry in the KEYCODE_1 label.
Finally Howard Casto
(aqua
text) and papaschtroumpf (yellow
text) had the following discussion. I don't completely follow
it,
but you can make Johnny5 work with the infomation provided so far, but
I thought it might be helpful:
I just want to clarify
some things:
I made Johnny5 as
generic as
possible because I had always planned on expanding it for other
uses. Johnny5 is a data translator, with a very few
exceptions,
there
are no constants in Johnny5 that prevent you from "making" other
physical
inputs. The list of possible inputs are stored and read from
a
simple text file and it looks for those inputs in the ini cfg/etc
files. It doesn't look to see if they are valid, nor does it
care. A search string is a search string.
I did this
because MAME also
supports "non-MAME" inputs. MAME outputs these extra
controls
on
a joystick/keyboard as whatever the Windows driver labels
them.
Since I have no way of knowing every possible input every odd-ball
joystick puts out, this had to be done.
To officially add
these labels
to the layout viewer simply open up the "keycode constants.txt" in the
data files folder and add them at the bottom. (I would suggest adding a
nice header like "PC Inputs Only:") This is also how you add
static labels btw, just remember to put a "*" first in the case of
static labels.
I
tried to add "START1=test" in controls.ini since START1 is one of the
official MAME controls defined in my CTRLR file for MAME.
More exactly,
it is defined as KEYCODE_1 or KEYCODE_ENTER. I think the
default for
MAME is just KEYCODE_1 but I have it set up as ENTER in my keyboard
encoder, because ENTER is commonly needed in PC Games, especially for
menu selections, which makes it fitting to be mapped to START1.
I
added a KEYCODE_ENTER label in my layout, expecting it to show up in
the generated picture but it didn't work.
I
tried to run Johnny5 with the -debug option and saw nothing in the
debug window that referenced looking for START1.
What
am I missing?
It's
quite simple
really..... Do you have START defined as Enter anywhere in
MAME? I talked about adding more physical inputs, not virtual
ones. Since none of your MAME mappings have Start1 mapped to
Enter, it has no way of knowing that you use Start1 as Enter.
And
of course, Start1 has to be somewhere in the p1controltype string setup
properly in the format. Viewers know which labels to read
from an
entry by the controltype entry at the beginning.
I
don't understand what this means, so maybe it's the problem,
but I
can't fix it until I know what you mean. Where is the
"p1controltype"
string?
In
the controls.ini of
course..... (P1Controls= )
This
entry is
always read
first and tells the viewer how many and what kinds of virtual inputs
this game uses. If the MAME constant of a label description
isn't
included, it never gets read.
To
add a
"virtual" control you have to have three things:
A
label
description in the controls.ini (P1Start=Start)
A
Virtual/Physical link tacked onto the control type string (|Player 1
Start+P1Start)
A
cfg/ctrlr/Std.ini entry that defines said virtual keys MAME constant to
a physical keyboard key (P1Start=KEYCODE_ENTER)
Please
note that
I have no clue if P1Start is a real constant, I'm just using it as an
example.
Also
note that it
doesn't have
to be a real MAME constant, it just has to be in the same name in the
cfgs and both places in the controls.ini. And of
course it
has to have a real key assigned to it in said MAME cfgs.
The
easiest way
to add "fake"
virtual inputs is to define a bunch in your std.ini which may or may
not be in your current MAME build, but will be read by the viewer if
you include one.
Cool,
thanks the the explanation. I may handle it that way since it
seems
cleaner that my "P1_BUTTON10..." hack.
Heh,
I think you are
confused......
Buttons
are a
special case.
Since
adding
1-button1..etc to
the p1controls string would be excessively long, those are
assumed. (Unless the game only uses buttons, but that's
another
story)
In
each entry
there is a
"NumberofButtons" entry. The viewer just reads how many
buttons
are counted and automatically knows the keys to search for (P#Button#=)
Now
again, some
physical key
has to be defined to that virtual key somewhere in your MAME cfgs, but
you never have to worry about it being added somewhere, just make sure
your NumberofButtons Entry matches.
Yes,
I actually figured out how that part worked (thanks to the -debug
option), which is why I was able to add extra buttons that are defined
in the MAME CTRLR file but not really used for MAME (I don't play any
10 button games.)
At this point, Johnny5
should be working well.
CPVIEWER/CPVW
CONCEPTS
NOTE:
The
information below in yellow
was provided by papaschtroumpf:
The same
basic idea works
with CPViewer: either add entries at the end of controls.ini or create
a new directory with a PCgames specific controls.ini and fill in game
entries as with Johnny5. Note however that the P1NumButtons is not
really used in CPViewer.
- [testgame]
gamename=This is a test
numPlayers=1
alternating=0
mirrored=0Unfortunately,
I am not
very familiar with MAMEwah. I have set it up and used it
previously, but it is not my frontend of choice (no offense to it or
MinWah), so I am not very familiar with it.
tilt=0
cocktail=0
usesService=0
miscDetails=This is
only a test
P1NumButtons=14
P1Controls=8-way
Joystick+joy8way
P1_BUTTON1=Fire
P1_BUTTON2=Bomb
P1_BUTTON3=Evade
P1_BUTTON4=Flare
P1_BUTTON5=Countermeasures
P1_BUTTON6=Afterburner
Again,
the
entries
in blue show the
"regular" mame buttons.
Things are handled differently in CPViewer/CPVW: the program doesn't
try to be so intelligent of mapping entries in your CTRLR file to your
layout file the way Johnny5 does. Instead it directly matches
entry
names in controls.ini to a label name in your layout. Basically if you have a
label for "P1_BUTTON1", it looks for a
corresponding "P1_BUTTON1" label in controls.ini. By default, it will also
attach the same value to the "P2_BUTTON1" in
your layout if you have added that label.
The "trick" to use here is that you can override P2_BUTTON? entries so
that they don't match the corresponding P1_BUTTON entries.
For example, if you mapped additional PC game controls to your P2
entries (I'm assuming the PC game is single player in this example),
then you can just add them in by specifying their P2_BUTTON? equivalent:
P2_BUTTON1=Cockpit Cam
P2_BUTTON2=Tail Cam
P2_BUTTON3=Wing Cam
P2_BUTTON4=Wide view
P2_BUTTON5=Zoom in
P2_BUTTON6=Zoom out
Now you may have mapped some controls to "admin" buttons on your
control panel. For example, let's say that in addition to your 2
buttons per players, you also have a player 1 start (mapped to "1"),
player 2 start (mapped to "2"), pause (mapped to "P"), mame menu
(mapped to TAB).
Your PC game may have something mapped to the 1, 2, and TAB key, so you
want to label them in CPViewer.
If you have set up
your CP for MAME, then you have told CPViewer to
create labels for P1_BUTTON1..P1_BUTTON6 and P2_BUTTON1..P2_BUTTON6.
Since CPViewer lets you define up to 8 buttons per player, you have 4
spares (2 on player 1 and 2 on player 2)
Since CPViewer doesn't really care what your buttons are, you can put a
P1_BUTTON7 label under your player start1, a P1_BUTTON8 under your
player 2 start, P2_BUTTON7 under the MAME menu/tab button, etc...
Assuming that key "1" and "2" in your PC game are mapped to "easy" and
"difficult" and TAB is used for "quicksave", you can add the following
to the game's entry in controls.ini:
P1_BUTTON7=Easy
P1_BUTTON8=Difficult
P2_BUTTON7=QuickSave
Your final controls.ini then looks like this:
- [testgame]
gamename=This is a
test
numPlayers=1
alternating=0
mirrored=0
tilt=0
cocktail=0
usesService=0
miscDetails=This is only a test
P1NumButtons=3
P1Controls=8-way
Joystick+joy8way
P1_BUTTON1=Fire
P1_BUTTON2=Bomb
P1_BUTTON3=Evadepapaschtroumpf
P1_BUTTON4=Flare
P1_BUTTON5=Countermeasures
P1_BUTTON6=Afterburner
P2_BUTTON1=Cockpit
Cam
P2_BUTTON2=Tail
Cam
P2_BUTTON3=Wing
Cam
P2_BUTTON4=Wide
view
P2_BUTTON5=Zoom
in
P2_BUTTON6=Zoom
out
P1_BUTTON7=Easy
P1_BUTTON8=Difficult
P2_BUTTON7=QuickSave
Again,
the
entries
in blue
show the
"regular" mame buttons, the entries in yellow show the
modified Player 2 Button entries, and the entries in red show the
"spare" buttons.
You are limited to a
total of 16 mappable buttons; however, which may
or may not be a limiting factor depending on how complex your control
panel is. In
my case, I have a single player cabinet with P1_Buttons only, so I have
10
spares that I can use.
The other thing to be aware of is that if you use that same layout for
MAME, you may have buttons mislabelled, for example the P1_BUTTON7 text
would show under your player 1 start with the example above, even
though pressing that button would not act as the player's 7th button.
This can be solved by using a different layout for MAME and
PC
Games.
Maybe future versions of CPViewer coud add "custom" buttons to the list
in addition to the 1-8 P1 and P2 buttons.
JCrouse from BYOAC
posted the green text below and
papaschtroumpf replied with the yellow text:
I
have made contact with the CPVW author and we are planning on some
changes. For starters, adding P3 and P4 buttons. We
will also probably
make about 12 labels per user AND a generic set of labels, probably
eight or ten, that you can use as you want. I will make a
special layout
designer specifically for the application to rid out the massive
overhead of CPViewer. The designer will still require the
.NET
framework. However, you could create the layout by
hand. I did that
over the weekend.
Also,
for some
reason CPVW, as
it is now, needs the alternating field and it must be set to either one
or two. I'm not sure why but that seems to be the way it is.
I'll
post more
news as it materializes.
I'm
not at home right now so I can't check, but I don't think it had
anything special to do with the "alternating=" line, even though I saw
your comment in your e-mail. My cab is an upright, is yours a
cocktail?
Could that be why alternating seems to matter for you but not
me? I'm not
quite sure what the viewer setup wizard does under the hood, but
cabinet style and orientation does seem to matter a lot.
Edit:
the additional buttons sound great!
EMULOADER
INTEGRATION
EmuLoader
supports batch
files directly starting with version 4.7 or above. The text
below
is written for EmuLoader 4.7.4 (16Oct05). I will
cover Z26,
MESS (for the Atari 2600, and ZSNES examples, because these are what I
have used before, and I won't cover launching AHK with them, but if you
follow these examples and the previous pages, setup should be fairly
straight-forward.
EmuLoader
officially
supports five emulators: MAME, Zinc, Daphne, AgeMAME, and
PinMAME
(not Visual Pinball). Usage with other programs is not
supported
and frankly, Ciro (the EmuLoader author) highly discourages it and will
not offer support for it. Ciro has graciously given me
permission
to document the available methods here, but I must request that you
honor his wishes and not submit E-mails to him or post questions
regarding this on the EmuLoader forum. If you run into a
particularly difficult problem, contact me and I will do my best to
sort it out.
Having
said that, EmuLoader
is a very robust program and can handle most of the challenges
required, although the implementation (manually adding games) may be
cumbersome.
NOTE: It
is probably possible to get Visual Pinball working in EmuLoader using
the methods below, the information on this page, and possibly Howard
Casto's wrappers.
The text
below is arranged
to give you a view of the processes involved before you start making
changes and then have to re-do your work. I highly recommend
reading this entire section before attempting anything!
Also, if you are just
wanting this method for console emulation, Ciro has another frontend,
Emucon Playground, which has many of the features on EmuLoader as well
as auto-generation of game lists, although I don't know if it is up to
calling batch files instead of the direct emulator, etc. The
program is currently being re-written, but should be back on a subpage
of EmuLoader's Homepage.
- Overview:
This section is intended to give you an idea of what
EmuLoader is
like so you don't waste time on it if it will not work for you.
It is not intended
as a comprehensive feature list!
- First, here is a
screenshot of EmuLoader displaying a static image from Johnny5:

- The biggest complaint most
BYOAC'ers have
with EmuLoader is that as you can see, it is a very "Windowsy"
frontend. This doesn't bother me as I have a desktop
controller
attached to a PC that is only about 95% used for gaming (when I'm not
developing web pages on it). You can run EmuLoader in
full-screen
mode and hide the task bar and image bar, and I think you can use a
background image for the gameslist, and it will lose some of the
Windows look, but it still might not be what you want for a dedicated
arcade panel.
- Officially,
EmuLoader claims to require 800x600 or better resolution, but I have
used it at 640x480 with very few problems. Anything smaller
(like
a true arcade monitor) will have problems, though.
- Navigation
is easiest with a mouse (or trackball) (or a full keyboard).
You
can scroll the gameslist with the arrow keys. Navigation keys
cannot be assigned (for instance if you used a keyboard hack with "T"
used as Up); however, the program does support some commercial
controllers (HotRod, Devastator II, etc.) which use non-standard
outputs, so if you can match one of these, that might be helpful.
- EmuLoader
supports at least .PNG, .JPG, and .GIF (and maybe .BMP?)
images.
It also support up to 15 Categories of images and up to 10
images
per category for each game. You can select how many
categories to
show and can rename them (Game Snapshots is required), and can have
different category folders for each emulator, but every emulator must
have the same number of categories and displayed description.
(For example, you can't have 10 categories for MAME and only
3
for Daphne. Also if you select only four categories, you
can't
have category 3 be Marquees for MAME and Backglass for PinMAME,
although you can display backglass images for PinMAME under the
Marquees category heading!)
- EmuLoader
will allow you to set any item (Description, Rom Name, clone of,
driver, manufacturer, resolution, etc.) for your non-supported games.
Rom Names can be any length (not just 8 characters) and
can include spaces. UPDATE: The above is
true for
EmuLoader 4.7.4, but some of the Beta's for EmuLoader 4.7 still only
supported 8 character Rom names, I am not sure when support for long
file name was officially added.
- Important Little Known
Items:
- The first thing to do
is from the EmuLoader taskbar, select the
File>Preferences>General>Games
tab and click "Use Custom Options by
default." Normally, when you press Enter or left mouse-click
on a game, EmuLoader launches the game directly, i.e. "C:\mame\mame romname"
If you press Shift-Enter or if you Shift-click, EmuLoader
will
search for a custom command line for the game, or a driver custom
command line for the game, or a game specific batch file (if enabled)
for the game, or a default batch file for the emulator, and only launch
the game regularly if none of these are found. The second
behaviour is what we want (even for normal usage) and selecting that
checkbox makes it so. I think it should have been like that
from
day one, but that's beside the point.
- This
may have changed
recently, but I don't think so. Even if it did, my suggestion
is
cheap insurance. (Also it may only apply to games added to
the
MAME or AgeMAME lists). EmuLoader typically reads the snaps
entry
in C:\mame\mame.ini to decide where to find game snapshots.
If
you specify a different folder, it changes the entry in the mame.ini
file. So if you have one version of EmuLoader for ZSNES and
one
version for MAME, they will fight with each other and you won't be able
to view snapshots in one of them after opening the other one.
The
solution is to place a copy(s) of MAME (any version) and mame.ini in
you non-supported emulator folder(s) and point EmuLoader to this
file(s) in the copy(s) of EmuLoader that you are using for
non-supported games.
- The
Lanczos filter does the best job for images containing text, IMHO ;-).
- Right-clicking
on the column headings brings up the Columns Editor where we can show
or hide columns or change their order.
- Finally,
EmuLoader has an option called "Show Command Line" under the taskbar Emulator>Show Command Line
setting. Normally, this is an annoyance (it is off by
default),
but it can be invaluable for verifying EmuLoader is sending the correct
data to launch your non-supported game.
- Setup Options:
This section details the various methods of displaying your
non-supported games in EmuLoader:
- Merged List:
It is possible (either of two ways) to add your non-supported
games to the same list as your MAME (or other games). There
are
times that this makes sense, but normally it does not. For
example, if you are one of those PokeMon (Gotta grab 'em all) rom
collectors, it will be rather difficult and annoying having 2,000 SNES
games merged in with almost 6,000 MAME games. OTOH, if you
just
want to use Chankast for sfrush because it's dog-slow in MAME and want
to add one or two other Chankast arcade style games that MAME doesn't
even support at all, it does
make sense to add them here, and would seem a little silly to have a
version of EmuLoader with only two games supported. . . The
biggest drawback to this method is that you have to have your
non-supported game images in the same folder as your supported ones,
and the same categories.
- Ignore Emulator Names:
Let's say you have EmuLoader set up with MAME, Zinc, and
Daphne.
You have no plans to add AgeMAME or PinMAME, but you would
like
to support Final Burn and Chankast. One solution is to add
Final
Burn in place of AgeMAME and Chankast in place of PinMAME.
You cannot change the labels for the emulators, but you can
change the icons used to something more appropriate. (You
would
for example browse the icons list and change the
c:\emuloader\resources\images\toolbars\emu_agemame.ico to something
representing Final Burn, without changing the icon name.)
- Separate Copies:
This is the method I prefer. You simply copy your
EmuLoader
installation to a new folder (say c:\elsnes\) and then modify EmuLoader
to support your custom gamelist. You can even do this with
the
default settings, so you have a c:\elzinc\ folder and a c:\eldaphne
folder with installs tailored to these games. The advantage
to
this is that you can customize each install (image categories, number
of categories shown) and you don't have conflicts with trying to launch
different emulators and sorting out the batch files to do so.
The
disadvantage is that as above, EmuLoader will display a MAME listing,
even though you may be using it for SNES games.
- Combination:
Basically, this is a merge of the second and third items
above.
For example, you could have an arcade installation of
EmuLoader
with MAME, Zinc, Daphne, Final Burn in place of AgeMAME, and Chankast
in place of PinMAME. And then in a different folder, you
could
have a console installation of EmuLoader with Z26 in place of MAME,
FCEUltra in place of Zinc, ZSNES in place of Daphne, Project64 in place
of AgeMAME, and MESS in place of PinMAME.
- Game Launch Options: Starting
with EmuLoader Version 4.7, EmuLoader now has two basically redundant
methods of launching games: Command Line options and Batch file
options. To make it more confusing you can also launch batch
files from Custom Command lines. You can only pass romnames
to
custom command lines, but you can pass any parameter to Batch files, so
Batch files are more flexible overall. You can also use any
combination of these for different games. Here are the
available
methods in order of priority that EmuLoader will execute them:
- Custom Command Line:
Custom Command Lines are specific to each game only.
They
carry the same format as Driver Custom Command Lines below, but don't
apply to any games other than the one they are created for.
You
can create them by right clicking on a game and selecting Custom Settings (Selected
Game)>Command Line>Set Custom Command Line or
by manually creating (or copying an existing) romname.ini file in the
c:\emuloader\resources\customcmd\emuname\ folder.
- Driver Custom Command Line:
Driver
Custom Command Lines (DCCL) are similar to Custom Command lines, but
they apply to every game using a particular driver, not just individual
games. (No, I'm not going to leave you in a Catch-22 and stop
here!) This can be a useful exploit because we can create
"fake"
emulator drivers to match our added games. For example, all
ZSNES
games can use an "snes" driver and all Z26 games can use a Z26 driver
and all MESS games can use a MESS driver. You can
create them by right clicking on a game and selecting Custom Settings (Selected
Game)>Command Line>Set Driver Custom Command
Line or by manually creating (or copying an
existing) drivername.ini file in the
c:\emuloader\resources\drvcustomcmd\emuname\ folder.
- The two essential keys
to efficiently
using driver custom command lines is knowing the command-line format
that your emulator wants, and making sure the romname in your games
list matches this format. It is also important to note that
the
only internal parameter that EmuLoader can pass to the DCCL is the
romname (which is sent by adding %S to the file) and that the Parameter
line cannot be blank. For example, if you were launching a
batch
file which did not require the romname, you could usually add a "space"
in the Parameter field and the DCCL should work.
- Now for some real
examples:
- Z26 wants the following
command line format to launch (at least on my system): c:\z26\Z26.EXE
c:\z26\Roms\romname.bin -r60 -v8 For example: c:\z26\Z26.EXE C:\z26\Roms\airseabattle.bin
-r60 -v8
- so our
c:\emuloader\resources\drvcustomcmd\mame\Z26.ini file looks like:
- Executable=c:\z26\Z26.EXE
Parameters=c:\z26\Roms\%S
-r60 -v8
- MESS (for Atari 2600
games) wants the following command line format to launch: c:\mess\mess.EXE A2600
-cart romname.zip For example: C:\mess\mess.EXE A2600
-cart breakout.zip
- so our
c:\emuloader\resources\drvcustomcmd\mame\mess.ini file looks like:
- Executable=c:\mess\mess.EXE
Parameters=A2600
-cart %S
- Finally, ZSNES wants the
following command line format to launch: c:\zsnes\ZSNESW.EXE
c:\zsnes\roms\romname.smc For example: c:\zsnes\ZSNESW.EXE C:\zsnes\roms\Air
Cavalry (U).smc
- so our
c:\emuloader\resources\drvcustomcmd\mame\snes.ini file looks like:
- Executable=c:\zsnes\ZSNESW.EXE
Parameters=c:\zsnes\roms\%S
- GameName Alternate Batch File:
In the previous sections, we learned how to use Alternate Batch Files
with EmuLoader to launch the AHK Script along with MAME. In
addition to the default.bat file for each emulator, EmuLoader also
supports a gamename.bat file in the same folder. This is
basically equvalent to the Custom Command Line feature above, but using
batch files. There is no equivalent batch file method to the
driver custom command line, but I don't know that one is really
necessary.
- Alternate Batch File: This
is what we have previously been using for launching the AHK Script and
MAME together. The only thing to note besides what was
covered in
the previous section is that you can use this feature (with different
batch files) with any of the five supported emulators.
- Default: If
none of the above entries are present, EmuLoader simply launches the
romname with the specified supported emulator.
- Adding Games to the Games
List: Okay,
now we know how to set-up EmuLoader and how to launch
the
games once they are in the gamelist, but we don't know how to get them
to show up yet. EmuLoader store these images in one of six
files
in the resources subfolder, as applicable (by emulator): mame.el,
zinc.el, daphne.el, agemame.el, pinmame.el, and cGames.el (manully
created). There are two ways to get new games to display, as
shown below:
- Manual
Editing: It is possible to manually change the
appropriate files, adding new games as desired. This
is not recommended,
because if you ever (on purpose or accidentally) recreate your games
list, you will overwrite and ultimately lose the added custom game
information. It is highly recommended that you use the
cGames.el
method below instead, or othewise save the added information so you can
re-enter it again if required.
- NOTE: Another
case where this could be useful is for fixing errors in MAME's
-listinfo/-listxml output. For example, many games that are
shown
as unplayable actually play quite well. And some games that
and
listed as playable are actually broken. You could manually
change
the appropriate value in the applicable list so that it
displayed
the game's status correctly. Again, you will want to document
or
back-up any changes you make so they can be repeated when you update
MAME (or other emulaor).
- cGames.el:
The best method of adding games is to manually create a cGames.el file
in your EmuLoader\resources\ directory and add your games there.
The file uses the same format as the other game lists, and
the
entries will not be overwritten when you update your emulators.
- Format:
The highlighted block below shows the format for any of the
games
lists. Much of the data was taken from
EmuLoader\docs\el-listformat.txt. I have no idea how to make
the "¬"
character, but you can copy and past it. One of the key
entries
is "Class" this detemines which list the game will act like it is in.
If you specify a MAME class, it will act like a MAME game and
use
the batch files and custom command line files associated with MAME.
The other important entries are:
Description - How the game appears in EmuLoader's game list
Name - Needs to match the rom or batch file name so EmuLoader can
launch the game properly
Clone - Actually the parent game - Useful because EmuLoader can be
setup to display parent images if a clone entry is not found
Driver - Important if you want to use Driver Custom Command lines.
All other entries are optional and can even be left blank, however, it
is critical
that the proper number of categories "¬'s"
are included and that each game entry ends with the trailing semicolon
(;).
- The
list below shows how some games could be added to the cGames.el file.
I have color coded the list to make it easier to follow.
Further details are available in the
EmuLoader\docs\el-listformat.txt file. Note that the version
that
I was using shows "Category" and "Version Added" entries but EmuLoader
no longer uses them. Below are the default desciption, a MAME
entry, a Zinc entry, a Daphne entry, an AgeMAME entry, a PinMAME entry,
a custom Z26 entry, a custom MESS entry, and a custom ZSNES entry, and
descriptions.
- Class¬Description¬Year¬Manufacturer¬Sound¬Frequency¬Samples¬Control Type¬Video Type¬Orientation¬Resolution¬Driver
Status¬Sound
Status¬Color
Status¬Merged¬Name¬Clone¬Category¬Version
Added¬Driver¬Media Type¬Game Size;
- 06¬1942 (set 1)¬1984¬Capcom¬1¬60.000000 Hz¬¬1¬0¬1¬224x256¬0¬0¬0¬¬1942¬¬1942.c¬0¬215552;
18¬Tetris The Grand Master
(JP 980710) ¬1998¬Capcom/Arika¬2¬60.000000 Hz¬¬1¬0¬0¬640x480¬0¬0¬0¬24¬tgmj¬¬zn.c¬0¬13238272;
22¬M.A.C.H. 3¬¬¬¬¬¬¬0¬¬¬0¬0¬0¬¬mach3¬¬¬0¬;
27¬Cherry Master II v8.41
(set 1)¬¬Dyna Electronics¬1¬60.000000 Hz¬¬9¬0¬0¬256x224¬1¬0¬0¬¬cm2v841¬¬cherrym2.c¬0¬229376;
32¬Dr. Who (L-2)¬1992¬Bally¬1¬60.000000 Hz¬0¬9¬0¬0¬320x256¬0¬0¬0¬¬dw_12¬¬¬0¬G1703936;
00¬Air Sea Battle¬1977¬Atari¬2¬60.000000 Hz¬¬9¬0¬0¬400x300¬0¬0¬0¬¬airseabattle.bin¬2600¬z26¬0¬;
00¬Breakout - Breakaway
IV¬1978¬Atari¬2¬60.000000 Hz¬¬9¬0¬0¬400x300¬0¬0¬0¬¬breakout.zip¬2600¬mess¬0¬;
00¬Air Cavalry¬19??¬???¬2¬60.000000 Hz¬¬9¬0¬0¬640x480¬0¬0¬0¬¬Air Cavalry (U).smc¬snes¬snes¬0¬;
- Class - There are 35 possible
class entries. I won't relist them all, but the important
ones are:
00 - Classic Master Raster (available) (MAME)
16 - Zinc Master (available)
20 - Daphne Master (available)
24 - AgeMAME Master (available)
30 - PinMAME Master (available)
Note that by carefully selecting categories, it would be possible (in
some cases) to filter your gameslist. Note also that
available or
unavailable simply means that EmuLoader found (or didn't find) a
romname matching the game's romname. It does not mean that
the
rom is correct or that the game is playable.
- Description - As mentioned
previously, the way the game will be displayed in EmuLoader's gamelist.
- Year - The year the game was
produced (optional).
- Manufacturer - The company
that produced the game (optional).
- Sound - 0: No Sound; 1:
Mono; 2: Stereo (optional)
- Frequency - The games video
refresh rate (optional)
- Samples - Sound samples.
I think 0: not required; 1: required (optional field)
- Control
Type - The type of control used by the game (Joystick, Trackball, etc.)
refer to documentation for a list (optional field).
- Video Type - 0: Raster; 1:
Vector (optional).
- Orientation - 0: Horizontal;
2: Vertical (optional).
- Resolution - The game's
native resolution. Note that this does not directly impact
screen size or setup.
- Driver
Status - 0: Good; 1: Preliminary 2: Imperfect; 3: Test (optional field)
- Sound
Status - Same as above.
- Color
Status - Same as above
- Merged - Not sure what this
does (optional field).
- Name - The name that will be
sent to the batch file. Fairly critical. Long names
and spaces are supported.
- Clone
- Actually the parent game. Can be useful for images as
Emuloader
will display the parent image if no clone found, so by making all
custom SNES games the same parent, you can use one cabinet image, etc.
- Driver - Useful if you
want to use Driver Custom Command Line to launch the games.
- Media Type - Not sure what
this does (optional field).
- Game Size - Size of the
game rom (optional).
- Recommendations: Using
cGames.el is usually preferable to manually modifying the games list.
It is a good idea to figure out how you want EmuLoader to
launch
the games before adding them to the list. If you are using
similar emulators (RAINE instead of MAME for instance), you can copy
and
rename mame.el to cGames.el and delete entries rather than adding them
all in. I think EmuLoder needs all of the files, but they can
be
empty (open, select all, delete, save).
- CAUTION: While
EmuLoader can handle spaces in the romname, Johnny5 cannot (see MAMEwah
comments below). Since EmuLoader allows the game description to
be independent of the romname, this is not a huge issue for EmuLoader,
but you may end up renaming your roms (and your cGames.el entries) to
remove spaces if you want to use them with Johnny5.
- Summary:
Basically
these are the steps to get EmuLoader and Johnny5 working with
non-supported programs:
- Become familiar with the non-supported program.
Determine how it need to be setup for the best display
properties, determine what keys you want to use with it and how you
want to play it on your arcade machine/control panel.
Determine what command-line parameters it needs to be passed
to launch with the desired settings.
- Modify Johnny5 to work with it (custom controls.ini file,
maybe custom layout, custom ctrlr file).
- Create an AHK Script for it.
- Set up a batch file to launch the AHK Script and the
program.
- Determine how you want the program to appear to EmuLoader:
Do you want the games merged with your MAME games?
Do you want a separate instance of EmuLoader with only custom
games? Do you want the games to appear in the list for one of
the emulators that EmuLoader support, but you don't play?
- Determine how you want to launch the games:
Custom Batch Files, Default Batch File for the supported
Emulator that you are not using, Driver Custom Command Line, etc.?
(The information on command-line parameters required and on
how you want the games to appear in EmuLoader will be useful here.)
Consider the impact of your decisions - For example, if you
want to use Modeler instead of MAME and have the Modeler games in the
same game list, you probably can't modify the alternate batch file
without affecting MAME, but you could easily use Driver Custom Command
Line and set each new game up as using the modlr driver.
- Consider how you would like to handle support files
(cabinet artwork, screenshots, etc) for the non-supported games.
- Add the games to EmuLoader, preferably by creating a
cGames.el file. When doing this, you will want to keep in
mind what you enter as Name, Clone, and Driver, depending on what the
commandline for the program requires and how you decided to launch the
game and handle support files.
- Enjoy your new creation!!!
MAMEWAH
INTEGRATION
Unfortunately,
I am not
very familiar with MAMEwah. I have set it up and used it
previously, but it is not my frontend of choice (no offense to it or
MinWah), so I am not very familiar with it. The information
in yellow
below was provided by papaschtroumpf from BYOAC and my reply
is in white:
There
is one issue that I haven't solved yet, and that's why I don't consider
this a full solution yet: the game "rom" name should not contain any
spaces:
I
use MAMEwah and have it setup to show the link name in the rom list, so
I have a game called "Tower of the Ancients.lnk" so MAMEwah passes
"Tower of the Ancients" to Johnny5 as the ROM name, but then Johnny5
only looks for a ROM named "tower".
One
way to deal with it is to make an entry in the controls.ini with a rom
name of [tower] and a game name of "Tower of the Ancients". This will
work as long as you don't have another game that also starts with the
name tower. If you have both "Tower of the Ancients" and "Tower of
Doom" then this trick won't work.
Another
way to deal with it would be to replace the spaces in the name with
underlines. This would however cause mamewah to show the game in the
game list as "Tower_of_the_Ancients" which is not too bad but not
really what we want.
I
know mamewah has a {8.3} tag for the command line, but I haven't
explored what it does. If it takes a full name and turns it into a
unique 8.3 name, we might be able to use that.
You could also do:
Tower of the
ancients.lnk
Tower1 of Doom.lnk
Tower2 of
Power.lnk
Tower3 Trouble.lnk
but that's not
perfect either. . .
OTHER
FRONTENDS
Unfortunately,
I don't have much info on setup with other frontends.
CONCLUSION
Well,
that's about all I
have to say. Hopefully this page was helpful for you.
If
you see anything major that I got wrong, know of a better way to do
this, or if you just can't get it to work, shoot me an E-mail and I will
either fix the page or try to help you out.
