VLDP-HW

Terminology

As it stands today, the VLDP-HW solution consists of two parts:

The controller

The media server

These two parts communicate via a serial cable running at 115200 bits per second.

The Controller

This consists of a PCB with an Atmel AVR microcontroller on it, along with RCA video input and output jacks, and interfaces matching the laserdisc players that are being replaced. Its job is to communicate with original arcade game hardware (such as a Dragon's Lair PCB) and mimic the original laserdisc player's behavior which it (the controller) is replacing.

AVR Fuse Bits

Just for future reference, when hooking up an AVR to an external crystal, the fuse bit setting should be:
Full Swing, Crystal Oscillator (and I prefer slowly rising power just to be safe). See the AVR datasheet for details about what these settings mean. Remember to disable the clock divider that is shipped by default (CLKDIV).

The media server

This consists of a typical linux-based PC running a stripped-down version of DAPHNE that will listen for commands on the serial port and display fields/frames and play audio as it receives commands. The speed of the PC will be more than adequate to present the video and audio at the full speed of the original laserdisc player, and any track/field can be skipped to out of sequence in order to support tricky requirements for games such as Firefox.

Enabled s-video on Beagleboard xM

There is a lot of conflicting documentation about how to enable s-video mode on the beagle broad.

Here is the current method I use until I can find a more permanent method:

Plug in a serial port to the beagleboard and fire up a term program at 115200 bps, 8N1.

Boot the beagle broad.

the serial port will show boot up information and allow you to interrupt the boot process

Exception to the above rule

The media server will send 2 length bytes and 2 XOR bytes instead of 1 and 1. This is because the media server may need to send a packet larger than 255 bytes. These 16-bit values will be in little endian format.

So for example, a complete "packet" from media server to controller might look like this:

0001 00 FE FF 00E1 F0

Typical Flow

The controller upon startup will load its previous settings from EEPROM and immediately begin emulating a laserdisc player so that the arcade hardware has something to talk to. If it has no settings in its EEPROM, then it will default to emulating a LD-V1000 using a laserdisc with a 2:2 VBI pattern. The controller will begin sending commands over the serial port to the media server, which will initially be lost while the media server boots. However, this is okay because the media server is designed to be tolerant of missed/dropped commands.

Meanwhile, the media server will be booting up. Once it finishes booting, it must send a S)tatus command to the controller to see what settings the controller is currently using. If the controller is found to be using the same settings as the media server, the media server will just start processing commands sent from the controller. This is the typical use case. If the media server finds that the controller is using different settings, then the media server will send a H)ello command which contains new information about which laserdisc player to emulate and what type of VBI patterns the emulated disc should have.

Commands from controller to media server

Each command starts with an ASCII letter and proceeds with one or more bytes.

Command letter

Name

Description

Example

B

Blank Screen

A single ASCII 'B' will indicate to make the screen black, to simulate original behavior during seeking.

D

Disc switch request

The D will be followed by a single byte, which is the disc id of the disc that controller wishes media server to change to. This command must be idempotent.

E

Error log message

Same format as regular log command.

None, too lazy

F

Show Field

The F will be followed by 4 bytes in little-endian format representing which absolute field to display with the top two bits indicating audio muting. The absolute field is computed by multiplying the track number by 2 and adding the relative field (will either be 0 for top or 1 for bottom). The field should be displayed during the next vsync on the media server. Audio, if enabled, should be played when the field is displayed. Assuming the media server's video is outputting at 60 Hz, once it gets in sync with the controller it should render a smooth stream of fields and audio because new field commands will be coming in between every field. NOTE: it doesn't matter that the media will be in effect lagged by 1 field, because the user won't notice. The main problem to avoid is displaying the wrong fields because the user will notice that. The audio bits (top two bits) are 0: both channels muted, 1: only left channel, 2: only right channel, 3: both channels active.

Just like the F command but accepts an additional byte on the end which corresponds to which text overlay ID to display. If the text overlay ID has not been received (due to a corrupted/dropped command), the media server must respond with a 'T' response so that the controller can re-send the text information.

H

Hello

The H byte will be sent alone and is used to tell the media server that the controller has just rebooted and may need to have its settings checked.

L

Log Message

The L will be followed by an ASCII string containing a log message from the controller to the media server. Since the controller's only way to communicate to the outside world is through the serial port, it will log messages through the media server.

Sends a 32-bit little endian build number so that media server knows whether to update the firmware of the controller or not. The lower 16-bits are the CRC of the current AVR firmware (little endian).

n

build Number from AUX AVR

Same as N, but comes from the AUX AVR, not the main AVR. A -1 may be returned instead of the build number to indicate the the AUX AVR is not currently available (if a serial player is active, the AUX AVR can't be running because it shares the same USART)

S

Settings Message

This sends back a byte with the value of 0x13 (version id corresponding to the information presented here in this wiki), followed by the 2-byte "persistent" identifier that the media server sent with the last hello command (see hello command described below). If there is no previous record of this, then two 0's will be sent instead. After this will be one byte to indicate the controller's DIAGNOSE state (0 is off, non-0 is on), followed one byte to indicate the controller's active laserdisc player (corresponding to the LDP type values in the HELLO packet), followed by one byte to indicate whether laserdisc player auto-detection is enabled (0 is disabled, non-zero is enabled), followed by one byte to indicate the disc id of the active disc (0 if not available), followed by the 2-byte "dynamic" identifier that the media server sent with the last hello command (0 if none). The active laserdisc player may be either the auto-detected player or the manually selected player.

(none, too lazy hehe)

T

Change LDP-1450 text overlay settings

The T is followed by an arbitrary (but unique) ID byte, a byte offset indicating which byte of the buffer to start at (usually 0), a byte indicating X coordinate, a byte indicating Y coordinate, a byte indicating the LDP-1450 text 'mode', and then 32 bytes containing the actual buffer. Note that the text won't actually be displayed by this command; the 'G' command will display the text. The ID is only used so that the media server can detect whether it has missed the most recent text overlay command from the controller.

X

Log byte sent to Dexter from game hardware

The X is followed by a single byte. This is used to log I/O between Dexter and game hardware.

Y

Log byte sent from Dexter to game hardware.

The Y is followed by a single byte. This is used to log I/O between Dexter and game hardware.

z

AUX AVR request firmware page

This is in the exact same format as the Z command from the bootloader section that requests a page. The only difference is that this command is being passed through the controller from the AUX AVR to the media server.

Commands from media server to controller

Each command is a single ASCII letter (for now).

Command letter

Name

Description

A

change Active disc

The ASCII 'A' byte will be followed by a single byte indicating the new active disc's ID. (this is needed in case controller wants an active disc that the media server doesn't have)

H

Hello (Apply new settings)

The ASCII 'H' byte will be followed by new settings for the controller, detailed below.

D

Disc switch response

The ASCII 'D' byte followed by one byte indicating the disc id that was requested to change to, followed by one byte indicating success or failure (1 is success, 0 is failure). Should be throttled by media server so as to only send every .5 seconds or something.

The ASCII 'O' byte followed by the 32-bit field number that is the next field with a stop code. This is because the AVR doesn't have enough RAM to pre-cache all of this info so it must be sent as needed.

p

Send firmware page to AUX AVR

This is in the exact same format as the 'P' command from the bootloader section. The only difference is that this is to be passed through to the AUX AVR.

S

Request current settings

Requests from the controller which settings it is currently using. This is so the media server knows 1) the version of the serial protocol that the controller is using and 2) configurable settings that the controller is using such as the current laserdisc player type.

T

Request most recent text overlay command be re-sent

The media server has received a G command with a unique ID that it has not received, thus indicating that a former T command was dropped due to data corruption and needs to be re-sent. The controller will resend the most recent T command when it receives this.

Z

Force firmware update

Tells controller to go into firmware update mode (ie run the boot loader, see below).

The media server's Hello command

1 byte indicating whether these settings should be written to the controller's EEPROM+RAM or just stored to the controller's RAM. 0 = store only to RAM, non-zero = store to both EEPROM+RAM.

2 byte arbitrary "persistent" identifier (probably a checksum) chosen by the media server which will be returned when the media server requests a status. This allows the media server to determine whether or not to re-send settings to the controller.

1 byte indicating which type of laserdisc player to emulate

1 LD-V1000 Standard

2 LD-V1000 Badlands modified version

3 PR-7820

4 VP931 (Firefox)

5 PR-8210

6 PR-8210A

7 VP932 (Dragon's Lair euro)

8 VP-380 (Dragon's Lair 2 euro)

9 Simutrek (Cube Quest)

10 LD-V8000

11 LDP-1450

12 LDP-1000A

13 VIP9500SG (Astron Belt)

0 means 'none', which is a valid scenario when auto-detection is enabled.

1 byte indicating laserdisc player behavior

Bit 0 is clear if disc spin-up delay is authentic, or 1 is spin-up time is minimal

Bit 1 is clear if seek delay is authentic, or 1 if seek delay is minimal

Bit 2 is clear if screen should go blank during seeks or 1 if screen should hold its last frame during seeks

Bit 3 is set if diagnostics mode is enabled or clear if disabled

Bit 4 is clear is video signal should NOT be muted during searching (default behavior), or set if video signal should be muted during seeking (MACH 3 required behavior). May be ignored for some laserdisc player modes signal but must be muted for PR-8210.

Bit 5 is clear if baud rate should be 9600, and set if baud rate should be 4800. Only applies to serial LDPs and probably only matters for LDP-1450 mode where Time Traveler requires 4800 baud. Will be ignored for non-serial player modes.

Bit 6 is clear if laserdisc player type auto-detection is disabled, or set if enabled.

Bit 7 is clear if disc is NTSC or 1 if disc is PAL

All other bits are reserved and should be 0

1 byte indicating auto-detect strategy for this disc type

0x00 No suggestions

< 0x80 means that the disc can only be used with one player type, and thats type corresponds to the laserdisc player types listed above

0x81 LD-V1000/PR-7820

1 byte indicating the disc Id of the default disc (0 if not available)

9 bytes indicating which non-default discs (by disc Id) are available to be switched to (0 for none)

1 byte that is always 0 (conserves Dexter limited RAM by null terminating the array of available players)

2 byte arbitrary "dynamic" identifier (probably a checksum) chosen by the media server which will be returned when the media server requests a status. This allows the media server to determine whether or not to re-send settings to the controller.

Arbitrary number of bytes containing the compacted VBI data which is described below:

The VBI data of each laserdisc is can usually be described by a few simple patterns and thus compacted down to a small number of bytes.

The first bytes of the compact VBI data will be:

Offset

Description

0

Version identifier (will always be 0 for now)

1

The number of "pattern entries" needed to describe the entire VBI. As it will only be a byte, that means only 255 entries are possible. Typical cases show that only 3-5 entries are needed for each disc.

2-5

The total number of fields that the VBI patterns represents, in little-endian format.

After these bytes, 1 or more "pattern entries" will follow. Each entry is 12 bytes long:

4 bytes describing the picture number that corresponds to the start of the pattern. This number can be negative! (signed, little endian)

1 byte describing the pattern itself.

0=no change

1=2:2 pattern

2=2:2 pattern atari styled

3=2:3 pattern

4=lead-in pattern

5=lead-out pattern

6=repeating zeroes

7=repeating picture number

2 bytes describing stop-codes and chapter numbers. Bit 15 is reserved [should be 0], it used to represent stop codes but this quickly became problematic so I ditched the idea. Bit 14, if set, means this entry has a chapter number associated with it that will continue the duration of the entry. The lower bits (bits 0-bit 13) are the chapter number. If bit 14 is clear, it means there is no chapter number regardless of whether the pattern is "no change". In other words, if a chapter exists, it must always be specified for every entry. This 2-byte value is little endian.

1 byte indicating the pattern offset. 0 means there is no offset. For 2:2 patterns, this can be a 0 or a 1. For 2:3 patterns this can be a 0, 1, 2, 3, or 4. A non-zero offset means that the pattern will start later than at its usual beginning. For example, of the pattern would've been "PicNum0 Empty PicNum1 Empty" for a 2:2 pattern, and the offset was 1, then the pattern would instead be "Empty PicNum1 Empty PicNum2".

Messages from controller to VBI injector

Message letter

Name

Description

Example

M

Mute video signal

Mutes video signal (for PR-8210 mode, MACH 3 requires it). Should be sent every field that the video signal is to be muted to protect against dropped packets. Sending a VBI update will implicitly unmute the video signal.

N

Build number request

Requests 32-bit little endian firmware build number from AUX AVR.

S

Set stand by line

[deprecated] Takes a 1 byte argument. If non-zero, the PR-8210A STAND BY line will be raised (if controlled by the AUX AVR, which is true is of rev 3b). If 0, stand by will be lowered. Should be sent every field during seek/spin-up to protect against dropped packets. Sending a VBI update will implicitly lower the stand by. This side effect is justified because we have to plan for and protect against dropped packets.

s

PR-8210A search begin or continue

Initiates or continues predictable PR-8210A search behavior where the stand by line is toggled and no VBI data is injected. Will be terminated by a VBI update. The reason that this command is idempotent is to protect against dropped packets.

0x56 (V)

VBI Update

[deprecated] This will always be 11 bytes. The first byte contains data about the field and the white flag. Bit 0 will be set if white flag is enabled. Bit 1 will be set if this data is for the bottom field, clear if the top. The rest of the bits are ignored and should be 0. The next 3 bytes represent line 16's data in big endian format (can be changed to little endian if this is more optimal). The next 3 bytes represent line 17's data, and the next 3 bytes represent line 18's data.

Newer/better version of the VBI update packet. The first byte contains bits that each have their own meaning. Bit 0 will be set if white flag is enabled. Bit 1 will be set if this data is for the bottom field, clear if the top. Bit 2 will be set if the disc is paused. Bit 3 will be set if the proceeding number is a picture number. Bit 4 will be set if the proceeding number is a chapter number (picture number bit takes precedence). The rest of the bits are ignored and should be 0. The next 2 bytes represent picture number in unsigned binary format (0-65535) or chapter number in unsigned binary format, or undefined/ignored if the preceding picture number and chapter number bits are both 0.

Messages from VBI injector to controller

Byte indicating type of data

Name

Description

Example

L

Log message

String from VBI injector AVR to be logged

N

Build number response

32-bit little endian build number.

Serial Communications of Bootloader

When the bootloader boots (hehe), it will check the value of the last 16-bit word of the EEPROM. If it is 0xBEEF, the bootloader will assume that the last attempt to program the application succeeded and will boot the application. If this word is not found, the bootloader will assume that the last attempt to program the application failed and will enter the programming state.

If the application wants to force a reprogram, it has simply to erase these in the EEPROM, then call the bootloader.

The programming state

Memory is programmed one page at a time. The size of the page depends on the type of AVR.

For the 328p, the page address size is 6 bits (where each address is pointing to a word, not a byte). One page is 128 bytes (see 26.8.16 of datasheet), or 64 words. The 328p has 256 total pages (32k). The 328p's EEPROM size is 1k.

For the 644p, the page address size of 7 bits (where each address is pointing to a word, not a byte). The 644p has 256 total pages where each page is 256 bytes (64k). The 644p's EEPROM size is 2k.

Communication

Communication protocol follows the same format as between the media server and controller. Max packet length from boot loader is 8-bits, max packet length to boot loader is 16-bits (packet length will be indicated by 16-bit little endian value). This is because the packet size on the 644p is 256 bytes so we can't stay within 8-bit boundaries.

Message from boot loader

Command letter

Name

Description

L

Log message

Packet will be an arbitrary ASCII string sent from the bootloader to provide visibility into what's going on.

Z (uppercase)

Page request

First byte is the version of this protocol (00). Next byte is the bit size of the page (for example, 7 for 328p, 8 for 644p). Next two bytes are the index of the page (16-bit little endian), starting with 0x0000. It will send this also to indicate that the last page received was corrupt and should be resent. If no data is received after a timeout period, last request may be re-sent.

Sending pages to boot loader

Command letter

Name

Description

P

Send a complete page

Sends 2 bytes (little endian) indicating which page is being sent, followed by the full page worth of data.

What done looks like

When the boot loader successfully receives all the pages, it will:

- set the token at the back of the EEPROM to 0xBEEF
- boot the application

Notice that it does not indicate that it has successfully received all the pages. This is because of the possibility of the communication being corrupt over the serial communication system and thus not being able to rely on it being delivered anyway.

The peer talking to the boot loader should assume that any other valid communication received that is not part of the bootloader's protocol means that programming succeeded and the firmware has been booted.

Philips VP931

Pin-Out

Pin

Description

9

Ground

10

RDEN' (in) "RDEN lets the CPU know that the host wants to read data, and sets a latch for the player's data bus outputs (so the output is valid for as long as the host keeps RDEN active"

11

DAV (out)

12

DAV' (out)

13

OPRT' (out) [always low, connected through a resistor and transistor to vcc]

14

DATA0

15

DATA1

16

DATA2

17

DATA3

18

DATA4

19

DATA5

20

DATA6

21

DATA7

22

WREN' (in)

23

DAK (out)

24

RESET' (in)

25

5V - As far I can tell, Firefox, Freedom Fighter (dedicated), and Freedom Fighter (prototype) all leave this pin unconnected.

Timing Diagrams

Caveat: These are from an unknown source and should be compared against observed behavior from real hardware.

The game board will not try to communicate to the LDP unless it knows the LDP is connected and turned on. How it knows it is connected is via the OPRT (Operational) signal, which is an active low open collector input on the LDP. Make sure that the OPRT signal is connected.

A quick way to check to see if the game thinks that the LDP is connected is to disconnect the video cable from the LDP while the communications cable is still connected. The game should watchdog reset and the video should go out of sync. This happens because the game uses the sync from the LDP video for video timing (when the LDP is connected) and if vsync is out by around 3ms or times-out (no video) the game resets.

If you have the signals wired properly (at least OPRT and ground) and the game does not reset with no LDP video connected then check the voltage level of OPRT. If it is +5V the problem is with your LDP (TR6112). If it is 0V then check for 0V on pin 15 on the buffer at 7J on the game CPU PCB. If it is 0V then the buffer is faulty otherwise you have wired OPRT wrong or there is a bad connection somewhere.

If everything above checks out okay then make sure you have the communications signals between the game and the LDP wired correctly. Make sure the reset signal is connected to the LDP as the LDP CPU can crash when the game boots or if it resets. If it still doesn't work then there is either a problem with your game PCB (7J, 6H, 7H, or 2F) or with your LDP (IC6206, IC6207, IC6208, or the processor is not running/crashed).

Firefox/General I/O

Reading

For the top field, the VP-931 sends data about 3/4 of the way through line 22 (so not long after parsing the picture number from lines 17-18). For bottom field, it's about 3/4 of the way through line 287. These may fluctuate and are just what I observed for two fields. The point is that they happen not long after the picture number has been parsed from the VBI.

The DAV' line goes low to indicate that data is available but it does not put anything on the bus.

When RDEN' goes low, then the VP-931 will simultaneously 1) put the new data byte on the bus and 2) set DAV' to high. This is the only time when the bus will have stable data. IMPORTANT: On a real VP-931, the RDEN' line is connected to the enable pin of a LS374 which means that the data will be put on the bus almost immediately. Firefox exploits this fact by lowering RDEN' and immediately reading from the bus (see E4BB and E4BE in the Firefox ROM). Dexter does not have the luxury of being able to respond this quickly, so probably would need to have the data on the bus before lowering DAV'.Firefox seems to rely heavily on DAV' going high as soon as RDEN' goes low (see disassembly below) so this is something that Dexter must support.

The game sets RDEN' to high shortly thereafter (about 3 uS), to indicate that the data has been safely read.

After a small period of time (about 3uS after RDEN' has gone high), DAV' will go low again to indicate that another byte is available.

This sequence iterates 6 times (6 bytes are sent).

NOTE : Firefox does one extra read even when DAV' is high (ie it reads 7 bytes, see E4C7 in the firefox ROM as shown below). As the RDEN' line is tied to a LS374, the data bus will be written to by the VP-931, although the data's meaning is probably undefined and unreliable.

NOTE #2 : Firefox does not ever check to make sure that DAV' has gone high and assumes that it has gone high as soon as RDEN' went low (see E4B7 in the disassembly).

Writing

The game sets WREN' to low, then puts data on the bus.

The VP-931 then sets DAK to low (this is accomplished via a 74LS279, so it happens almost instantly; within 0.1uS).

After DAK goes low, the game raises WREN'. This is how the byte actually gets stored to the VP-931 because WREN' is connected internally to the clock of an LS374 inside the VP-931. DAK seems to stay low for a minimum of 10uS, but can stay low for as much as 20uS (it seems to vary). This means that Firefox and Freedom Fighter can't be too picky about when this signal ends.

The VP-931 appears to lower DAV' after receiving a byte in order to echo the received byte back. Firefox politely lowers RDEN' and reads this byte (which sets DAV') but ignores its value (see E67C and E67F). Freedom Fighter, however, seems to ignore trying to read and DAV' just stays low. I don't know when DAV' goes high again (ie when the VP-931 gives up) but I would assume it is around the next vsync. (this would be a good thing to capture!)

NOTE : Firefox performs one spurious read before it begins writing. This is because Firefox's loop that writes the 3 command bytes does the read (to acknowledge DAV') before the write. The value read is completely ignored and DAV' does not even need to go low during the command phase for Firefox to operate properly.

NOTE #2 : As with reading, Firefox expects DAK to instantly go low when WREN' goes low. It will then spend some time waiting for DAK to go high again. See E692-E69A. It eventually will time out if DAK doesn't go high in a timely manner (see E69C).

Data bus:
The bus seems to be "floating" if RDEN' and WREN' are both inactive.

Status data

The first 3 bytes read are the VBI data (ie picture number, for example, but may include stuff like lead-in).
The next 3 bytes are some kind of status code. There is no documentation for this, so one must reverse engineer:

02 00 10 : Powering up (using MAME as the source)

04 00 00 : Playing normally (confirmed on real player)

04 00 01 : Lead in (confirmed on real player)

04 00 10 : Unknown (MAME as the source during spin-up)

04 00 33 : Unknown (seen from MAME during lead-in)

04 00 37 : Unknown (seen from MAME during spin-up/lead-in)

05 00 00 : Seek complete, may also mean paused (confirmed on real player, only shows for one field if autoplay-after-search is enabled)

08 00 00 : Seeking (confirmed on real player)

08 60 00 : Seeking when close to target, may mean that current position is behind the target (confirmed on real player)

08 70 00 : Seeking when close to target, may mean that current position is ahead of the target (confirmed on real player)

NOTE: While MAME does (partially?) emulate the VP-931, its accuracy is unknown, so any values obtained from MAME should be verified independently if possible.

NOTE #2: While seeking, the VP-931 does report VBI data that it parses along the way.

The firefox ROM gives a small clue about what these mean:

ROM:E62D lda DQ_STA ; if JMPing or power up, then no lock to disk
ROM:E62F anda #$A ; bit 1 and 3 indicate JMP/power-up but I am not sure which is which
ROM:E631 beq loc_E635
ROM:E633 clr DQ_LCK ; 0 = cannot lock to disc, 1 = can lock to disc

DQ_STA refers to the first status byte following the VBI data from line 18. This means that bit 3 and 1 of the first status byte are set if the disc is jumping or powering up. Using MAME as reference, it would seem that bit 1 is powering up and bit 3 is seeking.

Seeking

We have captured the behavior of a real VP-931 when performing a seek. The target frame is 30,000 and the player was ahead of 30,000 and playing when the seek was initiated.

First, F3 00 00 is sent to the player.

The player's first response is 00 00 00 08 00 00

The player's second response is AB 25 90 08 00 00 (it was near frame 32590 in this example)

The next responses were the VBI picture number approaching FB 00 00 (frame 30,000) with the status still being 08 00 00

As the player got close (FB 01 31, frame 30131), the status changed to 08 70 00 which seems to means that we are close to the target and ahead of the target.

Subsequent updates still showed 08 70 00 until the player returned AA 99 98 (alternate field of frame 29998) with a status of 08 60 00 which seems to mean that we are close to the target but behind the target.

Next status update is FB 00 00 (frame 30,000) with a status of 05 00 00 which seems to mean either 'seek complete' and/or 'disc paused'. I didn't do any seeks that keep the disc paused so I cannot settle this ambiguity at this time.

Next status update is AB 00 00 (frame 30,000 second field) with a status of 04 00 00 (normal play status).

Skipping using seeking (Firefox attract mode)

Firefox uses seeking to essentially do skipping during its attract mode. By using a modified version of MAME, we can see what the real VP931 may send as its status during this time.

This is a known spot where Firefox does a "skip" :

Phase

Value

Status

a82155 040000

Cmd

f02246

Status

000000 086000

Status

f82246 050000

Cmd

000000

Status

a82246 040000

Firefox will only send two commands to the VP931, either a GOTO+PLAY command or a skip 1 track backward command.

If performing a GOTO+PLAY while on the first field (which is actually the bottom field due to the way the disc is arranged), it will skip to 1 picture number beyond what is requested. This is because the VP931 will land on the field before the field that has the requested picture number. For example, if the VP931 had reported manchester codes of F8 00 01 and Firefox wanted to skip to picture number 10, it would issue a F0 00 11 command (skip to picture number 11) and the VP931's next manchester code report would be A8 00 10 followed by F8 00 11. This probably means that the VP931 performs an internal track jump in these situations which causes it to land 1 field early.

If skipping from an alt field (which is the top field), it will skip to the actual requested picture number and the VP931 would land in the right place. If the disc is supposed to be paused, it will skip backward 1 track if on the alternate field or just send the default play command if on the first field.

Writing to the player

The VP-931 will echo back commands sent to it. It does this by lowering DAV' shortly after raising DAK. Firefox obediently will lower RDEN' when this happens (in fact, any time DAV' is lowered, because it is interrupt driven). Freedom Fighter, however, does not perform a read here. The result is that DAV' stays low. Subsequent writes still work properly.

A closer look:

The Freedom Fighter PIF ROM seems to not only be aware of this behavior, but seems to rely on it.

I initially thought it would be MASTER_XTAL/2 for the previous equation but tests showed it was /8. I still don't know why.

To convert milliseconds to current NTSC line number, do:

double dLine = (dMilliseconds / 16.6833) * 262.5;

LD-V1000 Pin-Out

LD-V1000 Pin

Description

1

A0

2

A1

3

A2

4

A3

7

Command Strobe

11

Status Strobe

12

GND

13

DIO5

14

DIO6

15

DIO7

16

DIO8

17

Enter Signal (must be connected or dragon's lair will not boot)

18

GND

19

GND

20

GND

21

GND

22

GND

23

GND

24

GND

25

GND

modifying MAME to get logging information

MAME emulates the LD-V1000 using the actual ROM so it may be instructive to observe the behavior of mame's emulated ld-v1000 from time to time.
Note that MAME's emulation may have problems so it should not be exclusively relied upon.

Open ld-v1000.c in the mame src code and change the following two #defines:

#define LOG_STATUS_CHANGES 1
#define LOG_COMMANDS 1

Then just run with the -debug option specified from the command line and the dlair.c driver will also spit out status reads.

Philips VP-932

Molex Pin

Description

1

DTR

2

GND

3

TXD

4

RXD

5

GND

6

CTS

Interface is simple and partially reverse engineered.

Shaun Wood says:

Get command from CPU
wait for CTS low
set DTR low
receive data
set DTR high

ENTER' (low means that the PR-7820 is being sent a byte on the data bus)

12

GND

13

DIO5

14

DIO6

15

DIO7

16

DIO8

17

INT/EXT' (receives external commands when low)

18

GND

19

GND

20

GND

21

GND

22

GND

23

GND

24

GND

The ready line pulses low every field while the disc is stopped, paused, or playing. The ready line is held high with no pulsing during disc spin-up and searches.

Each pulse lasts about 20uS and happens about 3 ms after the field starts as seen in this capture.

A quick n' dirty way to emulate the PR-7820 is to hold READY' low when the player is not busy searching. This is good enough for Dragon's Lair but not accurate.

Dragon's Lair sends a search command and then waits for READY' to go low to discover when the search has completed (ie it does not wait for READY' to go high first). Therefore, READY' needs to go high quickly after a search command is received.

LD-V1000/PR-7820 extended commands and 'super' mode

LD-V1000 extended commands

Command

Name

Description

Returns

0x90

Hello

Tests for the presence of this extended command set. On Dexter, it will return a version number in the lower nibble and 0xA in the upper nibble. Will always return a result even if the player is busy searching or disc swapping.

The current version (0xA2 at the time of this writing).

0x91

Query all images

Queries Dexter for all available laserdisc images which Dexter can switch to. If received during a seek or a disc change, this command is ignored.

An array of disc identifiers as single bytes which is null terminated. Disc IDs are here: http://www.daphne-emu.com/ldimage/discids.php . Example of what could get returned: 0x12 0x10 0x34 0x00 (8 16 52 00 decimal, which is dragon's lair, DL2, space ace). If no laserdisc image is available, it will just return a 00.

0x92

Query active image

Query Dexter for the active disc image. If received during a seek or a disc change, this command is ignored.

Single byte indicating the active disc image. If no laserdisc image is active, it will just return a 00.

0x93 [new image id]

Switch to new image

Behaves like a seek command but instead of seeking to a new frame, it switches to a new disc. When the switch begins, the screen will go blank and stay blank even after the switch has completed. After the switch has completed, play and seek commands can be sent to resume normal operation. If the 'get current frame' command is issued while in this state, the returned frame number is undefined. If any other 'switch to new image' commands come in before the first command has completed, they are ignored.

0x50 during transition to new disc, 0x90 on error, 0xD0 on success

0x94

Enable/disable laserdisc player spin-up delay

Behaves like the audio enable/disable commands 0xF4 or 0xFC. The caller must pass in a number to indicate whether spin-up delay will be enabled or disabled. A number of 0 means to disable spin-up delay. A non-zero number enables spin-up delay. Passing in 0x94 without passing in a number first will be interpreted as a 0. The default is to be enabled. Examples: 0x3F 0x94 [to disable] 0x0F 0x94 [to enable]

Does not affect status

0x95

Enable/disable laserdisc player seek delay

Same as 0x94 except for seek delay instead of spin-up delay.

Does not affect status

0x9D

Disable super mode (see below)

On next vsync, super mode will be disabled and either LD-V1000 or PR-7820 mode will be active again (depending on what was active before super mode became enabled).

N/A

0x9E

Enable super mode (see below)

On next vsync, super mode will be enabled.

N/A

PR-7820 extended commands

Command

Name

Description

Returns

0x9E

Enable super mode (see below)

On next vsync, super mode will be enabled.

N/A

Super Mode

Super mode aka Universal mode is a new custom I/O protocol that is compatible with Dragon's Lair boardsets that are either configured for PR-7820 or LD-V1000 modes. Unlike these aforementioned modes, 'super mode' only uses two control wires for communication instead of three (pins 7 and 17 on the centronics 24 connector, with pin 11 being ignored). It also operates much faster than either PR-7820 or LD-V1000 mode.

Super mode is 100% compatible with the Dexter LD-V1000 command set (including the extended LD-V1000 commands) except that 0xFF (NO ENTRY) never needs to be sent. The status code will always be in a 'ready' state (with high bit set) except when it is busy spinning up the disc or searching to a frame.

Unlike LD-V1000 mode, super mode does not have a concept of a command strobe but instead uses implicit timing rules for communication (explained below).

Communication Flow

The game hardware must wait to receive a status byte from the laserdisc player before it may send any commands. Once it receives a status byte, it may start sending one or more commands. It may continue to send an indefinite number of commands as long as these commands are sent faster than 8ms apart from each other. Once the next vsync occurs and the laserdisc player has not received a command for 8ms, it will resume sending status bytes every field until it receives the next command. This pattern continues indefinitely.

The laserdisc player always drives pin 7 and the game hardware always drives pin 17. Pin 7 is active low and pin 17 is active high (for historical reasons; pin 7 is usually high and pin 17 is usually low).

Here is how the timing/handshaking works:

Step

Phase

Event

1

Status

On the next vsync, if no command has been received for 8ms, laserdisc player puts status byte on data lines and lowers pin 7 (in that order).

2

Status

Laserdisc player waits ~25 uS (same length as ld-v1000 cmd and status strobes)

3

Status

Laserdisc player stops driving data lines and raises pin 7 (in that order); this is so that laserdisc player and game hardware are never driving data lines at the same time.

4

Command

Game hardware (if it wishes to send a command) immediately puts command byte on data lines and raises pin 17 (in that order). If the game hardware does not wish to send a command, go to step 1.

5

Command

Laserdisc player lowers pin 7 to acknowledge command receipt. Game hardware should wait for this.

Laserdisc player raises pin 7 to acknowledge game hardware. Game hardware should wait for this.

8

Command

Go to step 4.

The command phase ends (and status phase begins) when the next vsync occurs and a command has not been sent for 8ms.

DB25 serial port pin-out

NOTES

Direction is from a PC to a modem (DTE to DCE)

The only DB25 pins that are typically used (based on observing which pins are swapped for a DB25 null modem cable) are 2, 3, 4, 5, 6, 7, 8, and 20.

Pin

Name

Direction

Corresponding DB9 pin

1

GND (Shield)

2

TXD

out

3

3

RXD

in

2

4

RTS

out

7

5

CTS

in

8

6

Data Set Ready (DSR)

in

6

7

GND

5

8

Carrier Detect (CD)

in

1

9

10

11

Select Transmit Channel

out

12

Secondary Carrier Detect

in

13

Secondary Clear To Send

in

14

Secondary Transmit Data

out

15

Transmission Signal Element Timing (TCK)

in (verify)

16

Secondary Receive Data

in

17

Receiver Signal Element Timing (RCK)

in (verify)

18

Local Loop Control

out

19

Secondary Request to Send

out

20

Data Terminal Ready (DTR)

out

4

21

Remote Loop Control

out

22

Ring Indicator

in

9

23

Data signal rate selector

out

24

Transmit signal element timing (XCK)

out

25

Test Indicator

in

PR-8210 interface

Every command starts with the pattern 0, 0, 1, followed by 5 bits (the actual command), followed by 0, 0 at the end.

Commands are sent serially over a wire. The wire is held at 5V when there is no communication and when a command is ready to be sent, the wire is pulled low to GROUND to initiate one PULSE. The wire is supposed to be held low for 260 microseconds (from PR-8210A service manual, page 37).

MACH 3: violates this by rapidly alternating between high and low during this 260 microsecond period.
Cobra Command (Cliff Hanger PR-8210 conversion): is compliant.
Cliff Hanger: We don't know yet

To determine which bit is being sent, one must observe the space of time between these pulses.

Space of time between falling edge of two adjacent pulses

Interpretation

1.05 milliseconds

0 bit

2.11 milliseconds

1 bit

More than 3 milliseconds (just a guess)

End of message

Cobra command has at least 7 milliseconds between the last pulse of a command and the first pulse of the next. MACH 3 can have up to nearly 50 milliseconds.

PR-8210 Remote Control Unit

The "DVA 8210 REMOTE CONTROL UNIT" does not seem to use "END OF COMMAND" separators. Pressing a button quickly will result in 3 of the same command being sent. Holding down a button will spam the command over and over again. So elapsed time may also serve as a separator but I have no idea what the official elapsed time is.

MACH 3 notes

From the owner's manual, page 17 and 18:
The frame number stripper is U10 on the Color/Sync board.
A potentiometer, R202, adjusts the comparator voltage level. (visible inspection and schematics suggest that it's actually R204 that is the pot, as R202 looks like a resistor) This tells me that it's okay the Raspberry Pi's voltage of 0.3V for black and 1.3V for white because this R202 can be adjusted to compensate.
U10 also (supposedly) receives VSYNC and HSYNC although from the schematics it does not appear to use HSYNC to count up to a specific line (ie line 17/18).
Also, picture number will only be present on the odd (top) field which is pretty standard.
Output of the stripper is sent to J7 and then to interface board and appears to be a TTL version of the manchester coding.
Game's test mode is used to adjust R202 so that it works reliably.
Some pretty technical details of frame decoder on page 19.

From schematics, U10 is a 75107A Dual line receivers/drivers integrated circuit. From a very quick skim of a schematic I found, this appears to do nothing more than convert the manchester-coded line (such as line17 or 18) to TTL levels (from 0.3V/1.3V output by the raspberry pi and our injector board) and then hand that off to another piece of hardware. I could be wrong about this.

Hardware to decode each frame number bit is on interface board (labeled as "frame # decoder" on schematic). Once a bit is decoded, it is shifted into three 8-bit flip flops. Additional hardware detects whether the frame number is valid or not before exposing it to the cpu. The frame decoder will parse the first line that includes a white voltage level (on the mach 3 disc, this will always be line 17 for the top field because the white flag is never used; on something like the raspberry pi, this could be put on a line later than line 17 and the mach 3 hardware should still pick it up).

The Disc Ready Flag (page 18 and 19) will be high when VSYNC (from the laserdisc player) is received within a 16 ms period of time. So it seems that vsync must be removed for some time for a search to be recognized.

Conclusion: As Warren has long argued, I see nothing in the MACH 3 hardware that cares about which line number the frame number comes in on (although hsync pulses could be counted and I am just not seeing it), nor at what point on a given line the manchester code starts. It seems that the picture number _could_ potentially be stored on the first two visible lines of each field (necessary because JPEG is 4:2:0) and MACH 3 would pick it up.

Additional thoughts from Warren:

I think I understand how MACH3's frame decoder works now... and I think it *will* work with VBI on the first visible line, as long as *nothing* appears before it. It doesn't decode every line of field. Flip-flop U9 enables the comparator on the first HSYNC after VSYNC. When the comparator first outputs a logic high, this sends a clock pulse to the flip-flop, which causes it to disable the comparator after the next HSYNC. So it is assuming that it will not receive a high output from the comparator until it gets to the line with the VBI data. This means it doesn't care what line the VBI data is on, only that it is the first line that has white on it. To put it more succinctly... only the first line of each field that contains white is sent to the frame decoder. I just looked at the UvT cap I made on an LD-V1000 at Dave's last month. The 1000 suppresses the VBI lines above 17, so the frame data is indeed the first thing at white level. Assuming the PR-8210 works the same way, this means our injector should NOT include the white flag line.

Service mode video from Teo

Cliff Hanger notes

<Warren_O> I also looked at the Goal to Go schematics, and I believe the Cliff/GtG hardware *does* count lines, and *will* need VBI on line 17. I don't quite follow everything that it's doing but it has a 4-bit counter (74LS161) and a lot of logic gates controlling the shift registers and latches. Interestingly, it does not have a level adjustment like MACK3, but it is AC coupled, so the Pi's 0.3V offset shouldn't matter. well, *probably* won't matter :)

Sony LDP-1450

I've confirmed that this player won't accept commands unless DTR is enabled. When I say "won't accept commands", I mean that instead of returning 0xA after each byte, it returns 0xB.

It doesn't seem to care if flow control (CTS/RTS) is enabled or disabled.

Digits

When the player wants digits, it will take the last N digits that it wants. For example, if it wants a 5 digit frame number and you enter in 6 digits, it will take the last 5 digits. If it wants 2 digits and you enter 3, it will take the last 2. And so on.

The SEARCH command

The input after the search command (43) seems strict. Trying to send a PLAY (3a) command after a 43 resulted in a 0B being returned and "INVALID KEY" being displayed on the "index".

The REPEAT command

As the LDM-G1000 manual says, commands that affect playback speed do not cancel a REPEAT. These includes 3a (fwd 1X), 4f (still), and 3d (multispeed).

Commands that do cancel REPEAT include 43 (search) and 56 (clear all). I haven't found any other commands (so far) that will cancel repeat.

Undocumented repeat quirk: if REPEAT starts playing forward (for example, from frame 12000) and playback direction is changed (by playing in reverse) and passes beyond the initial starting point, it counts as an iteration and the disc will begin playing forward again. if no iterations are left, it pauses on the frame _before_ the start frame. (ie pauses on 11999 instead of 12000).

44 3a ... is valid, as are other commands to change the playback speed. However, it appears that only forward commands are valid (reverse not) at this point. 44 4a is invalid.

44 3c .. is valid. the multispeed setting is preserved across repeat loops.

More quirky: 44 3d [frame number] 3a [repeat iterations] 40 will start repeating at 1x forward. The 3a can cancel the 3d, just like it can without being part of a repeat command.

Undocumented quirks

The multispeed commands 0x3d and 0x4d will start playing the disc at 1/7X before receiving their arguments for the actual desired speed. For example, if I send a 0x3d, the disc will play at 1/7X forward, and then if I sent a 0x32 (2) and 0x40 then the disc will start playing at 1/2X.

3d can be canceled by sending a 3a (and probably other commands like still or play in reverse). In other words, 3d 3a is valid.

Time Traveler

BJZ's game was set to 4800 baud, not 9600 baud. I don't know whether this is typical of all Time Travelers (I hope it is consistent otherwise that is going to be a big pain for the end user to configure Dexter). It does seem to send a 0x41 at 4800 baud which shows up as something else at 9600 baud so maybe we can put in some auto-detection to save the user some pain. By the way, it is a pretty big pain to get to the laserdisc player. You have to open up the back panel and then open up a small black box inside the back section to get at the player.

Dexter ALG multi-ROM hack

To support Shaun Wood's ALG multi-ROM, Dexter will do the following when entering LDP-1450 mode:

Read LD-V1000 pin 17. If it is floating or high, do nothing. If it is being held low, read the LD-V1000 data lines and attempt to switch laserdisc images based on the following table:

0x7f

Mad Dog

0xf7

Mad Dog 2

0xbf

Johnny Rock

0xfb

Gallagher's Gallery

0xdf

Space Pirates

0xfd

Crime Patrol

0xef

Crime Patrol 2

0xfe

Last Bounty Hunder

Personas

Ed Jones

Ed Jones was a young boy during the early 80's when arcade games were at their peak. Laserdisc games, in particular, left a deep impression on him which has never really gone away. As a boy he yearned to be in the arcade, watching others play the laserdisc games which were too expensive for him to afford. Now that he has a decent job, he longs to relive his childhood memories by attempting to recreate the atmosphere of the arcades he used to love. He also is interested in sharing this experience with his friends. If money were no object, he would have his own arcade filled with classic games from his childhood and he would regularly host parties in this arcade for his friends to see what Ed's childhood was like and why he loves it so much. He is very busy and does not have time to fix broken games. He needs his games to "just work" and look just like they did when he was a child: brand new.

Mitch Smith

Mitch also grew up in the early 80's and fondly remembers the arcades. He is painfully aware that arcade games do not last forever and is greatly concerned about his memories becoming lost forever. Therefore, he feels a deep sense to preserve them. Any time a new arcade ROM is dumped, he makes it a point to get it and to store it. To him, it doesn't matter whether a ROM is playable or otherwise usable; he collects all data relating to his past as insurance against it becoming lost forever. He is much like the custodian of a museum, trying to preserve everything as precisely and exactly as it was. He understands that if he can archive content from the arcade era, he is contributing to the effort to preserve it. He takes comfort in this sense of doing his part to help the effort. He very rarely, if ever, plays the games that he collects. (Example: One who goes to the effort to seed complete MAME ROM sets over bit torrent)

Lester Black

Lester is a tech support guru for a small business. His job primarily involves fixing other people's computer problems which he is very good at. He has plenty of spare time. However, he lives in a small apartment which has limited space. One of his favorite things to do is to tinker with the few arcade games he has managed to cram into his apartment. He isn't too concerned about the games being completely original; in fact, one of his favorite hobbies is to tinker with and modify the games. He has replaced the crusty old sound system in one of his games with a new state of the art sound system so that it sounds better than the original did. He has also installed a battery in one of his games so that it remembers high scores, a feat that the original never did.

Evan Holmes

Evan can build just about anything. He's also quite good at restoring broken-down things. One of his favorite things to do is take old broken arcade games and restore them so they look like new. The worse the shape he gets these "project" games in, the better. He takes satisfaction in showing people "before" and "after" pictures of his work. Once he is done restoring something, he is really done; he moves on to a new project rather than enjoying his finished work. For him, the joy is in the challenge of the restoration. Evan is also pretty fussy about how his finished projects look. They need to look really, really good. If he has to choose between a crappy set of original side art or a flawless reproduction set, he will choose the latter every time.

Interface Considerations

Target Audience

"If you want to achieve product-satisfaction level of 50%, you cannot do it by making a large population 50% happy with your product. You can only accomplish it by singling out 50% of the people and striving to make them 100% happy. It goes further than that. You can create an even bigger success by targeting 10% of your market and working to make them 100% ecstatic. It might seem counter-intuitive, but designing for a single user is the most effective way to satisfy a broad population." --The Inmates Are Running the Asylum page 126.