Document:    CINEMU.DOC
Version:     1.0, for use with CINEMU.EXE Version 1.0a 
Date:        4/16/97
Author:      Zonn Moore
(To obtain this document without HTML formatting, i.e. plain text, click here.)

Overview

This document describes the options availale in the ".INI" files used by the Cinematronics Emulator CINEMU.

By using a layout similar to that used by "Windows" configuration files I hope to make the learning curve as small as possible.

The format is simple:

There are currently four sections, each containing their own options.

The sections are:

[CPU]
Sets up jumpers and ROM image names needed by the CPU.
[Video]
Sets up jumpers and logic needed to handle the different video modes available on the Cinematronics hardware.
[Inputs]
Maps a logical name to an input or inputs. This section maps input names to an associated input pattern.
[KeyMapping]
Maps keyboard scan codes to the above inputs. As many keys as desired may be mapped to a single input name.

Section Details

[CPU] Options

JMI = [Yes | No]

Default: Yes

This option enables or disables the Jump on Minus jumper that can be found on the Rev K Cinematronics boards, but can exist as a jumper wire on earlier revision.

Without this jumper the CPU instruction becomes a JEI (Jump on external input). The only game I know of that uses the external input is: Tailgunner. It's used to read the DAC comparators when determining the current position of an analog joystick.

I've read some discusions about the game Space War(s) use of this instruction as a non-banked jump instruction. The only image of Space War I have, came from a Vectorbeam Space War cocktail. I was never able to find any use of the JMI instruction in this image. Since there is no pullup on the external input, without an additional mod, it would be a bit reckless to depend on this as a "jump always instruction". (TTL devices do float high, but still...) It is possible that changes were made by Cinematronics, during the Cinematronics vs Vectorbeam days, to distinguish the images from each other. For this reason it's probably best to use the "JMI=No" option when running "Space Wars" images. Though if you're interested in plugging the Space War roms into a StarCastle board, use the Vectorbeam "Space War" image. This worked fine for me, with the JMI jumper in place, on a Star Castle board. (I didn't burn new ROMs but merely swap the masked parts to a Star Castle board.) Be sure to turn all your option switches off!

BTW: The images I've seen floating around the Net match my Vectorbeam Space War images.


Speed = [Standard | Spacewar | Full]

Default: Standard

This sets the speed of the emulator. On my first pass on emulation I actually counted machine cycles, including waits states. It worked nicely but upon discovering that every game uses the WAI instruction to time itself, I was able to speed up execution by timing games, using only the WAI instruction.

This caused a slight problem since the games Space War and Star Hawk find a little extra CPU time by executing the WAI half as often as the other games, I must therefor wait twice as long. Set Space War and Star Hawk to the "SpaceWar" setting, all others to "Standard". "Full" is for those running 386's or possibly a 486 with a slow video card. If your game appears to be running at half speed, try setting the speed to "Full", this runs the game at the fastest speed the emulator is capable of going. It's also fun to attempt to play Star Castle on a 586 133mhz on this setting -- just a bit out of control.

Note: The technique I use to allow for zero flickering of vector emulation requires the speed of the VGA monitor refresh rate to be faster than the speed of the Cinematronics hardware's refresh. This isn't usually a problem since the Cinematronics uses a 38hz refresh, and I've never heard of even a CGA monitor refreshing at that rate. On the other hand when you run the emulator at full speed it's possible for higher end machines to update at a *much* faster refresh rate than most VGA screens. At which point there will be aliasing, where a previous screen is replaced with a new one before the previous one was completely drawn. The result will be much flickering...


MemSize = [4k | 8k | 16k | 32k]

Default: 8k

Used to set the size of the game images. This size is the size of all ROM images added together. It allows the emulator to account for the different paging techniques used by the different size games. It also determines the extensions used when reading the ROM images. (See also "RomImages=").


Inputs = xxxx

Where: xxxx = A hex number indicating the initial state of the CPU inputs.

Default: FFFF

The default 'open' state of a Cinematronics input is 1 (high). In most cases the games expect all the inputs to go high when no button is being pressed. On some games (Solar Quest, Tailgunner) some of inputs unused by the control panel are used as extensions to the CPU switches. This parameter allows you to effectively place jumpers on the control panel's PCB board located near the control panel on most games. Solar Quest uses jumpers here to set the difficulty level of the game. Tailgunner uses a jumper on the control panel to indicate a Digital Joystick is being used in the place of an Analog Joystick.


Switches = xxxxxxx

Where: xxxxxxx = Seven binary digits indicating whether a switch is on (1) or off (0).

All seven switches must always be given. If a game does not use a particular switch it should be set to off (0). This is especially true for Space War, that uses some of the switch inputs as control panel inputs.


RomImages = [x:][\][path\]romimage

Standard DOS path that points to the ROM images. The value 'romimage' is the root filename only. The extensions are assumed by the emulator using the following defaults (based on 'MemSize='):

MemSize=4K
   romimage.T7                  ; 2048 byte ROM image
   romimage.P7                  ;  "    "    "    "

MemSize=8K
   romimage.U7                  ; 2048 byte ROM image
   romimage.T7                  ;  "    "    "    "
   romimage.R7	                ;  "    "    "    "
   romimage.P7                  ;  "    "    "    "

MemSize=16K
   romimage.U7                  ; 4096 byte ROM image
   romimage.T7                  ;  "    "    "    "
   romimage.R7	                ;  "    "    "    "
   romimage.P7                  ;  "    "    "    "

MemSize=32K
   romimage.U1A                 ; 4096 byte ROM image
   romimage.U1B                 ;  "    "    "    "
   romimage.U2A	                ;  "    "    "    "
   romimage.U2B                 ;  "    "    "    "
   romimage.U3A                 ;  "    "    "    "
   romimage.U3B	                ;  "    "    "    "
   romimage.U4A                 ;  "    "    "    "
   romimage.U4B                 ;  "    "    "    "
The variable 'romimage' should be replaced by the name of the ROM images for your game.

[CPU]
 MemSize=16k
 Eg: RomImages=C:\CINEROMS\solar

Would indicate to CINEMU that the files:

   C:\CINEROMS\solar.u7
   C:\CINEROMS\solar.t7
   C:\CINEROMS\solar.r7
   C:\CINEROMS\solar.p7

should be read.


[Video] Options

WinSize = MinX, MinY, MaxX, MaxY

Where:

MinX = The lower X limit of the Cinematronics window to be displayed in the VGA screen. (Left edge of screen).

MinY = The lower Y limit of the Cinematronics window to be displayed in the VGA screen. (*BOTTOM* edge of screen).

MaxX = The upper X limit of the Cinematronics window to be displayed in the VGA screen. (Right edge of screen).

MaxY = The upper Y limit of the Cinematronics window to be displayed in the VGA screen. (*UPPER* edge of screen).

The "standard" built into the Cinematronics hardware was a screen whose starting and ending vectors could start or end any where on a 1024x768 grid, with the origin (0,0) being in the lower left hand corner of the screen. Like a graph, as opposed to the standard layout of most bitmapped graphic screens.

Yet most games start and end somewhere beyond these points. In some cases (SpaceWar) this was probably done on purpose to make "flying things" go halfway off the screen on one side, before wrapping around to halfway on the screen on the opposite side.

In other cases it seemed to be a matter of how the development monitor, used to write the game, was "calibrated". Since messing with the X and Y size controls on the Vectorbeam monitor can throw the 1024x768 all out of whack.

These parameters were created to allow individual adjustment for each game and not just pick a Happy Medium somewhere.

Negative values are allowed in the MinX and MinY settings. Defining a larger window (smaller Min values, and larger Max values), will shrink more of the Cinematronics screen into the VGA screen. Reminder: the MaxY value refers to the *TOP* of the screen.


Monitor = [BiLevel | 16Level | 64Level | Color]

Indicates what type of monitor the game is expecting.

BiLevel - The standard monitor that allows a Bright and a Normal value for each vector drawn, and up to 9 levels of intensities for single points.

16Level - 16 intensity levels are available for vectors and single points. (Used only by Sundance.)

64Level - 64 intensity levels are available for vectors and single points. (Used only by Solar Quest.)

Color - 4096 colors available for vectors and single points. (Used by War of the Worlds and Boxing Bugs.)


Twinkle = [1 - 10]

Set the "Twinkle" level of stars. Since the Bi-Level monitor supports multiple intensities for stars, this sets the level at which point a star switches from dim to bright. Space War uses 9, while Star Castle uses 8.


Rotate = [Yes | No]

A 'Yes' rotates the screen 90 degrees clockwise, shrinks the Cinematronics X axis to fit the VGA's Y axis, and shrinks the Cinematronics Y axis proportionatly.

Also adds an offset to bring the image to the center of the screen.


FlipX = [Yes | No]

Make the VGAs X-axis a mirror image of the real image. This is done AFTER rotation (if requested by setting 'Rotate=Yes').

FlipY = [Yes | No]

Make the VGAs Y-axis a mirror image of the real image. This is done AFTER rotation (if requested by setting 'Rotate=Yes').


Brightness = Red%,Green%,Blue%

Contrast = Red%,Green%,Blue%

On all 'intensity' based monitor settings (Bi-Level, 16Level and 64Level), 'Brightness=' sets the RGB values for the "Brightest" value displayed, and 'Contrast=' sets the RGB values for the "Dimmest" value displayed (not including black, which is always black).

The values are given in percentages of maximum. 100% indicating full intensity, and 0% indicating black. Don't include the '%' on the parameter line.

On monitors with more than two intensities, the intermediate values will be evenly spaced between these two values.


[Inputs]

This section is used solely to described inputs to the CPU.

Any character string may be assigned as an input (up to 32 characters), and up to 32 inputs my be assigned. The names assigned here will be referenced later in the [KeyMapping] section.

The bit mapped patterns following the assigned Input name are not as confusing as they first appear.

First it should be noted that all inputs to the CPU are normally pulled high and a keypress causes a '1' to change to a '0' value. That being said, the values following the assigned Input names, are Hexidecimal representations of masks that manipulate the state of the CPU's inputs.

The 1st column is the value OR'd with the CPU inputs when a key is pressed.

The 2nd column is the value AND'd with the CPU inputs when a key is pressed.

The 3rd column is the value OR'd with the CPU inputs when a key is released.

The 4th column is the value AND'd with the CPU inputs when a key is released.

Starting at the RIGHT most bit and working our way left:

The lower 16 bits map directly into the 16 inputs of the CPU. Bit-0 maps to input 0,... Bit-15 maps to input 15. Bit-16 through Bit-22 map to the CPU switches.

Bit 23 maps to the Coin Dropped indicator. This bit should only be zero by the given masks. It will be reset by the CPU when it polls this bit looking for coins. Becuase of the auto repeat mode of the PC keyboards, this bit is usually cleared upon release of a key, if you setup this bit to work on the pressing of a key, the auto repeat feature will rack up credits real fast!

The top 8 bits are internally defined by me. Well for now only bit 24 is, and is used to indicate the break key has been pressed. You should leave the other bits alone.

By clearing more than one bit on a keypress, you can simulated the pressing of two keys at once. This is how Barrier is mapped to allow player 1 and player 2 to use the key pad as the movement control pad.

Also this layout allows the setting and reseting of any repeatable pattern of bits, which allows it to simulate the 10 to 4 multiplexors used in Sundance.

None of these inputs have any effect on anything unless they are mapped to a key in the section [KeyMapping].


[KeyMapping]

Every option defined under [KeyMapping] must also be defined under the [Inputs] section. It is the [KeyMapping] section that maps each of the previously defined inputs to a key on the keyboard. The format is simply:

InputName = xx

Where 'xx' is the hexidecimal value representing the scan code assigned to a key on the keyboard.

Since there are a zillion different type of keyboards available, and I wasn't the least be interested in finding each one and documenting the scan codes it uses, I slapped together a simple program that display the scan code of each key pressed. It's called SCANCODE.EXE.

Running SCANCODE also lets you see if the combination of keys you want to use can be pressed simultaneously. To remove the "ghost" key effect of matrixed keyboards, most keyboards do not allow unlimited pressing of keys. The keys that may be simultaneaously pressed is dependent upon how each keyboard is internally wired. Obviously were not talking any kind of standard here.

You'll also notice the if you press many keys, fast, you can overun the keyboard's hardware buffer, and a key may appear to be stuck. This would also appear stuck to the emulator (as it would to any program). So don't press many keys, fast, and overun the keyboard! Since tapping the stuck key unsticks it, this isn't normally a problem.

To assign keys to inputs: Run SCANCODE, write down the scan codes of the keys you want to use, place a line in the .INI file under the section [KeyMapping] that maps the scan code to a previously defined input.

A single input may be assigned to multiple keys.

Example:


[Inputs]		; assign CPU input values

; Upon pressing of a key, set Bit-0 to 0. Upon releasing set it back to a '1'
;
;	Press OR,   Press AND,   Release OR,   Release AND

 Inp0 = 00000000,   FFFFFFFE,    00000001,     FFFFFFFF

[KeyMapping]

; By running SCANCODE we find the 's scancode is 39

 Inp0 = 39		; Make the CPU input 0 go, low each time the
                        ; SPACE bar is pressed, and 1 when it's released

Fini!