Next: , Previous: Test Mode, Up: Top


9 Common Pinball Library

The files in the common directory provide a library of generic pinball functions that can be reused from game to game. Some of the more important ones are described in detail in this chapter.

9.1 Coins and Pricing

FreeWPC implements a weak form of coin switch handling. It is not very robust and does not time the coins as it should.

If FREE_ONLY is defined, it will build a ROM that doesn't require coins.

9.2 Extra Balls

This module tracks lit and collected extra balls. Lit extra balls can be easy (lit until end of game) or hard (lit only until end of ball).

In the machine config file, you should tag the lamp that indicates an extra ball is lit as extra-ball, and the shoot again lamp as shoot-again. Then the lamps will automatically update for you when these APIs are called.

light_easy_extra_ball
Lights an easy extra ball.
light_hard_extra_ball
Lights a hard extra ball.
eb_light_adjustable
Lights an easy or hard extra ball, depending on the value of an adjustment.
collect_extra_ball
Call this from the switch handler of the shot that scores the extra ball.
can_award_extra_ball
Returns true if an extra ball is allowed to be lit/awarded. This consider limits of extra balls per game.

There is also an API special_award to award a special, but it does not manage any lamps automatically. It just obeys the adjustment to award whatever has been configured for special, and fires the knocker.

9.3 Tournament Mode

FreeWPC implements a tournament mode module. Note this is what newer Stern games refer to as competition mode.

Tournament mode can be enabled globally in the adjustments menu, or it can be enabled by holding down the left flipper button briefly before starting the game. A message will indicate that tournament mode has been enabled. It affects all players in the game.

Software should check the tournament_mode_enabled boolean variable to determine if tournament is in effect.

9.4 Ball Search

Machines don't need to do much to produce a working ball search function. The common code knows how to pulse all of the regular solenoids. It also knows not to fire anything marked as a motor or flasher. You can mark a solenoid in the machine description with nosearch to ignore other solenoids as well.

Machines that need to handle a particular power driver in a non-standard way (by using a template driver) should implement a ball_search event handler, and mark the associated solenoid as nosearch. The ball_search handlers will be called along with the automatic pulsing.

For example, on Funhouse, the Rudy saucer eject needs to make sure that the mouth is open before kicking.

Solenoids associated with ball devices will be skipped unless they are empty, except after several ball searches have failed. The chase ball/lost ball recovery feature is also implemented and can be enabled by menu adjustment.

Game code can call ball_search_timeout_set to set the amount of idle time that must expire before a ball search will occur. The default is 15 seconds. The timer resets anytime a playfield switch (one marked with the SW_PLAYFIELD flag) triggers. You can also manually reset it manually using ball_search_timer_reset.

9.5 Knocker Driver

Call knocker_fire to fire the knocker. If a coin meter is attached to the knocker coil, it will not be pulsed. If the machine defines a sound effect for knock, that will be played instead of pulsing a solenoid.

9.6 Adjustments

Adjustments are 8-bit variables kept in persistent storage. Each group of related adjustments is checksummed to verify integrity. Adjustments can be checked by just reading the variable; there is no special API to do so.

Machines can define their own feature adjustments in the machine config.

9.7 Audits

Audits are 16-bit variables kept in the non-volatile area of memory. They are generally incremented via the audit_increment API, which adds 1. They can also be incremented by an arbitrary value, via audit_add; or they can be assigned via audit_assign. They will not overflow if the maximum value is reached, but instead will just stop counting up.

Machines can define their own feature audits in the machine config.

9.8 Scoring

A global playfield multiplier is supported; use score_multiplier_set to change it. It is automatically set to 1 at the beginning of each ball.

Scores can be stated in two ways: as a 5-byte, binary-coded decimal value, or as an 8-bit "score code". The long values allow for arbitrary values up to 10 billion points. The short values are more compact and index a table of common score values, which are listed in the machine config.

The first set of APIs operate on arbitary BCD score buffers:

score_zero
Zeroes a score.
score_copy
Copies one score to another.
score_add
Adds one score to another.
score_sub
Subtracts one score from another.
score_mul
Multiples a score by an integer.
score_compare
Compares two scores, as memcmp would do.

The second group of APIs increment the current player's score by a fixed value.

score
Award score. The input is an 8-bit score code.
score_long
Also awards score. The input is another BCD score buffer.
score_multiple
Like score(), but also takes a multiplier argument. This multiplier and the global score multiplier are taken into account.
score_long_multiple
Like score_long and score_multiple. This is the most low-level API; all others ultimately call it.
score_long_unmultiplied
Awards score without any multipliers.

The third group of APIs, called the ladder APIs, add score according to some rule.

A fixed ladder rule tracks the current value of a shot, and defines a base value, an increment, and a maximum value.

fixed_ladder_reset
Reset the value of the rule to its base.
fixed_ladder_advance
Advance the value of the rule by the increment. The new value is checked to make sure that it does not exceed the defined maximum.
fixed_ladder_score
Add the current value of the rule to the player's score.
fixed_ladder_scorex
Add the current value of the rule, multiplied by some constant, to the player's score.
fixed_ladder_score_and_advance
Add the rule value to the player and advance it by one step.
fixed_ladder_scorex_and_advance
Add the rule value multiplied to the player and advance it by one step.

9.9 Lamp Timers

A lamp timer is a countdown timer which is tied to a playfield lamp. The amount of time remaining controls how fast the lamp flashes. When the timer reaches zero, the effect stops.

You declare a structure of type struct lamptimer_args, which names the lamp and the initial timer value, in seconds.

The lamp is modified as part of an internally generated lamp effect (meaning that it behaves just like a leff, but it does not have a lamp effect ID); thus, the basic state of the lamp is retained. While the lamp timer runs, the basic state is overriden by the effect.

lamp_timer_start
lamp_timer_find
lamp_timer_stop

9.10 Diagnostics

9.11 Score Rank

The score rank module is optional, based on the value of CONFIG_SCORE_RANK. When enabled, the system will monitor the relative changes in players' scores over the course of a multi- player game, and throw a rank_change event whenever the current player moves into a new place. It is up to each game to decide how to handle it.

9.12 Timed Modes

To write a timed mode, you need to do two things:

First, create a structure of type struct timed_mode_ops and fill out all of the required information. Use the DEFAULT_MODE macro in the initializer to set suitable values before declaring your own values. The fields are:

You must make sure that the structure and all of the functions that it references are in the same .c file, otherwise ROM paging will not work.

Second, handle several system events which affect the mode's operation:

timed_mode_music_refresh.
Call this from a music_refresh handler, passing it a pointer to the mode ops struct.
timed_mode_display_update.
Call this from a display_update handler, passing it a pointer to the mode ops struct.

From outside the mode itself, other modules call these APIs to interact with your mode. The mode ops struct is part of the public interface.

timed_mode_begin
Starts a timed mode.
timed_mode_end
Ends a timed mode immediately.
timed_mode_reset.
Resets the timer to its initial value.
timed_mode_add.
Adds to the timer.
timed_mode_get_timer.
Gets the current timer value. This should only be used by display effects. Note that timer can be zero and the mode is still running!
timed_mode_running_p
Returns true if the mode is running, for the purposes of scoring. This returns TRUE while the mode is in its grace period.
timed_mode_effect_running_p
Returns true if the mode is running, for the purposes of display and lamp effects. This return FALSE while in grace period.
timed_mode_device_running_p
Similarly, but should be used when updating devices from a device_update function.

9.13 Ball Savers

9.14 Ball Serve

The ball serve module is the preferred API for adding balls to play. It uses the ball tracking APIs to program the ball trough, but adds support for autoplunging and multiball logic.

The system supports games with autoplungers or manual plungers. Auto launch support requires that the machine defines three things: the launch button switch, the launch solenoid, and a shooter switch.

The base API serve_ball simply kicks a ball out of the trough. It also resets the valid playfield flag and refreshes background effects. This is the same call made by the game state machine during start ball.

Use serve_ball_auto instead if you want the ball to be autolaunched as soon as it is served successfully. Otherwise, it is identical to serve_ball. If a ball is served without autolaunch, it can be launched later by calling launch_ball. This happens automatically when the launch button is pressed and a ball is detected in the shooter lane.

You normally do not need to call either of those APIs, except in some rare cases.

The preferred way to start multiballs is to use set_ball_count, which sets the number of balls in play, or add_ball_count if you want to say how many balls to be added. These use serve_ball_auto to do the work. They work on manual plunger games too. Only one ball will ever be placed in the shooter at a time.

serve_ball
serve_ball_auto
launch_ball
set_ball_count
add_ball_count

9.15 Multiball Modes

Multiball modes can be implemented by defining a structure of type struct mb_mode_ops. They are modeled after the way that timed modes are constructed. Use the DEFAULT_MBMODE macro in the initializer to set suitable values before declaring your own values.

The key difference is how the mode ends; here, we examine the number of balls in play and end the mode when it reduces to 1.

9.16 Mute and Pause Mode

FreeWPC implements the Mute and Pause feature that was included in the Twilight Zone home ROM. It is optional at compile-time. The machine must have an extra-ball buyin button for it to work.

When compiled in, and the adjustment "MUTE/PAUSE" is set to YES, then pressing buyin during a game will hold the flippers, disable ball kickouts, pause timers, and turn off the background music. To continue, press the button again. It will also timeout automatically after 15 minutes.

9.17 Status Report

A default status report is builtin which shows basic game information. To activate it in a game, hold in either flipper button for about 5 seconds.

Machines can customize the report by defining their own status pages. Modules should declare a handler for the status_report event.