Friday, May 29, 2015

Dexter rev 3C PCBs have arrived!



Tuesday, May 26, 2015

Updates about Dexter's price

I think I forgot to announce this, but I've finalized the deal with Digital Leisure to sell their titles with Dexter and have updated my 'pricing' blog entry with said details.

To see that changes and/or to refresh your memory, go here.

Lord Victorino tests Thayer's Quest with Dexter in PR-7820 mode

Lord Victorino is back with another test of Dexter rev 3b.  This time he tests Thayer's Quest in PR-7820 mode.  From what I can tell, it seems to be working great, but it's hard to tell for sure from a video.

Monday, May 25, 2015

Lord Victorino tests Dragon's Lair with Dexter in PR-7820 mode


PR-7820 support is pretty much finished for Dexter.  I still need to add seek delay but this isn't really part of the PR-7820 mode specifically.  Check out Lord Victorino's test of this new mode.

Friday, May 22, 2015

Studying Thayer's Quest's LDP routines

It turns out that Thayer's Quest's LDP routines are very similar to Dragon's Lair's.  I would bet money that the assembly language code was lifted straight from Dragon's Lair F2 and modified for Thayer's Quest.

Here is Thayer's Quest's PR-7820 routine:

ROM_U33:1ED8 SendToPR7820:                           ; CODE XREF: SendToLdp+7 j
ROM_U33:1ED8                 push    hl
ROM_U33:1ED9                 ld      hl, A783PortF5Cache ; bit 5: 1 = output mode to LDP, 0 = input mode
ROM_U33:1ED9                                         ; bit 6: pin 11 (pr-7820 enter')
ROM_U33:1ED9                                         ; bit 7: pin 17 (pr-7820 int/ext', ld-v1000 enter')
ROM_U33:1EDC                 res     7, (hl)         ; lower int/ext' (ie go external)
ROM_U33:1EDE                 ld      a, (hl)
ROM_U33:1EDF                 out     (0F5h), a       ; apply changes to hardware
ROM_U33:1EE1                 ld      a, (A784CmdToSendToLdp)
ROM_U33:1EE4                 out     (0F4h), a       ; put command byte on pr-7820 data bus
ROM_U33:1EE6                 ld      hl, A783PortF5Cache ; bit 5: 1 = output mode to LDP, 0 = input mode
ROM_U33:1EE6                                         ; bit 6: pin 11 (pr-7820 enter')
ROM_U33:1EE6                                         ; bit 7: pin 17 (pr-7820 int/ext', ld-v1000 enter')
ROM_U33:1EE9                 set     5, (hl)         ; enable output mode to LDP data lines
ROM_U33:1EEB                 ld      a, (hl)
ROM_U33:1EEC                 out     (0F5h), a       ; apply changes to hardware
ROM_U33:1EEE                 res     6, (hl)         ; enable ENTER' line for pr-7820
ROM_U33:1EF0                 ld      a, (hl)
ROM_U33:1EF1                 out     (0F5h), a       ; apply changes to hardware
ROM_U33:1EF3                 call    Delay20ms       ; stalls for 20ms (confirmed on real hardware)
ROM_U33:1EF6                 ld      hl, A783PortF5Cache ; bit 5: 1 = output mode to LDP, 0 = input mode
ROM_U33:1EF6                                         ; bit 6: pin 11 (pr-7820 enter')
ROM_U33:1EF6                                         ; bit 7: pin 17 (pr-7820 int/ext', ld-v1000 enter')
ROM_U33:1EF9                 set     6, (hl)         ; disable ENTER' line
ROM_U33:1EFB                 ld      a, (hl)
ROM_U33:1EFC                 out     (0F5h), a
ROM_U33:1EFE                 call    Delay20ms       ; stalls for 20ms (confirmed on real hardware)
ROM_U33:1F01                 ld      hl, A783PortF5Cache ; bit 5: 1 = output mode to LDP, 0 = input mode
ROM_U33:1F01                                         ; bit 6: pin 11 (pr-7820 enter')
ROM_U33:1F01                                         ; bit 7: pin 17 (pr-7820 int/ext', ld-v1000 enter')
ROM_U33:1F04                 res     5, (hl)         ; go into input mode
ROM_U33:1F06                 ld      a, (hl)
ROM_U33:1F07                 out     (0F5h), a
ROM_U33:1F09                 pop     hl
ROM_U33:1F0A                 ret
ROM_U33:1F0A ; END OF FUNCTION CHUNK FOR SendToLdp


<end>

So, I've been having some problems with getting PR-7820 mode on Dexter working with Thayer's Quest.  I noticed that Thayer's Quest is sending a 'pause' command after a search finishes and this is exposing a defect in Dexter that I am working on fixing.

ROM_U33:1C57 sub_1C57:                               ; CODE XREF: ROM_U33:1BB0 p
ROM_U33:1C57                                         ; ROM_U33:1BC1 p ...
ROM_U33:1C57                 ld      (unk_A794), de
ROM_U33:1C5B                 ld      hl, unk_A791
ROM_U33:1C5E                 res     0, (hl)
ROM_U33:1C60                 call    SearchToFrame   ; convert number to BCD
ROM_U33:1C63                 call    SendPauseToLdp  ; 'FB'
ROM_U33:1C66                 ret
ROM_U33:1C66 ; End of function sub_1C57

<end>


Thursday, May 21, 2015

How to auto-detect the laserdisc player type for Dexter

One of the "killer" features I want to add to Dexter is the ability for it to auto-detect the player type that the game is configured for.  For most games, this is easy as the game only supported one laserdisc player.  For a few games like Cobra Command, this is hard because the game supported at least four different player types.  And then there's the Rick Dyer games which support the LD-V1000 and PR-7820 and it's these games that I want to discuss in this blog entry.

Detecting whether the game is configured for LD-V1000 or PR-7820 mode is a little tricky because one of the data lines is an input for one mode and an output for another mode, and I don't want Dexter to be in output mode at the same time as the game is in output mode.  Some good news is that the programmer(s) of Dragon's Lair were lazy when it came to designing their LD-V1000 code so I can use that to my advantage when coming up with a strategy.

Here is the code in Dragon's Lair that sends a byte to the LD-V1000:

ROM:0231 SendA021ToLDV1000:                      ; CODE XREF: SendA021ToLdp+15 p
ROM:0231                                         ; SendA021ToLdp+1C p
ROM:0231                 push    hl
ROM:0232                 ld      a, (A021LdpCmdByte)
ROM:0235                 ld      (E020LaserdiscData), a
ROM:0238
ROM:0238 WaitForStatusStrobeLow:                 ; CODE XREF: SendA021ToLDV1000+C j
ROM:0238                 ld      hl, C010SelCpB  ; bit 6: status strobe (for LD-V1000), not used for PR-7820
ROM:0238                                         ; bit 7: cmd strobe for LD-V1000, READY' for PR-7820
ROM:023B                 bit     6, (hl)
ROM:023D                 jp      nz, WaitForStatusStrobeLow
ROM:0240
ROM:0240 WaitForStatusStrobeHigh:                ; CODE XREF: SendA021ToLDV1000+14 j
ROM:0240                 ld      hl, C010SelCpB  ; bit 6: status strobe (for LD-V1000), not used for PR-7820
ROM:0240                                         ; bit 7: cmd strobe for LD-V1000, READY' for PR-7820
ROM:0243                 bit     6, (hl)
ROM:0245                 jp      z, WaitForStatusStrobeHigh
ROM:0248                 ld      hl, A020CurrentValOfE008 ; caches current value that has been written to E008 (since E008 cannot be read)
ROM:024B                 res     5, (hl)         ; enable output to laserdisc
ROM:024D                 res     7, (hl)         ; enable ENTER' line for LD-V1000
ROM:024F                 ld      a, (hl)
ROM:0250                 ld      (E008LoadMisc), a ; bit 5: OutDiscData', 0=enable output to laserdisc, 1=disable output
ROM:0250                                         ; bit 6: pin 11. PR-7820 ENTER (for PR-7820 only, can be disconnected on board for LD-V1000 operation)
ROM:0250                                         ; bit 7: pin 17. INT/EXT for PR-7820, ENTER for LD-V1000
ROM:0253
ROM:0253 WaitForCmdStrobeLow:                    ; CODE XREF: SendA021ToLDV1000+27 j
ROM:0253                 ld      hl, C010SelCpB  ; bit 6: status strobe (for LD-V1000), not used for PR-7820
ROM:0253                                         ; bit 7: cmd strobe for LD-V1000, READY' for PR-7820
ROM:0256                 bit     7, (hl)
ROM:0258                 jp      nz, WaitForCmdStrobeLow
ROM:025B
ROM:025B WaitForCmdStrobeHigh:                   ; CODE XREF: SendA021ToLDV1000+2F j
ROM:025B                 ld      hl, C010SelCpB  ; bit 6: status strobe (for LD-V1000), not used for PR-7820
ROM:025B                                         ; bit 7: cmd strobe for LD-V1000, READY' for PR-7820
ROM:025E                 bit     7, (hl)
ROM:0260                 jp      z, WaitForCmdStrobeHigh
ROM:0263                 ld      hl, A020CurrentValOfE008 ; caches current value that has been written to E008 (since E008 cannot be read)
ROM:0266                 set     5, (hl)         ; disable output
ROM:0268                 ld      a, (hl)
ROM:0269                 ld      (E008LoadMisc), a ; bit 5: OutDiscData', 0=enable output to laserdisc, 1=disable output
ROM:0269                                         ; bit 6: pin 11. PR-7820 ENTER (for PR-7820 only, can be disconnected on board for LD-V1000 operation)
ROM:0269                                         ; bit 7: pin 17. INT/EXT for PR-7820, ENTER for LD-V1000
ROM:026C                 pop     hl
ROM:026D                 ret
ROM:026D ; End of function SendA021ToLDV1000

<end>

Let me explain what it does.  First, it waits for the status strobe (pin 11) to go low (becomes active) and then high (becomes inactive) again.  This is because it does not want to go into output mode while the status strobe is active.  As soon as the status strobe ends (ie goes high), Dragon's Lair immediately goes into output mode, enables/lowers the LDV1000_ENTER' line (pin 17) and puts its command on the data bus. (side note: I think it would've been better if they had waited until after the command strobe started but maybe they were worried about performance)  It then waits for the command strobe (pin 7) to go low (become active) and then go high (become inactive).  Finally, it goes back into input mode.  NOTE that it never disables the LDV1000_ENTER' (pin 17) line.

Now let's examine how PR-7820 mode works:

ROM:026E SendA021ToLdpPR7820:                    ; CODE XREF: SendA021ToLdp+7 j
ROM:026E                 push    hl
ROM:026F                 ld      hl, A020CurrentValOfE008 ; caches current value that has been written to E008 (since E008 cannot be read)
ROM:0272                 res     7, (hl)         ; force INT/EXT' low
ROM:0274                 ld      a, (hl)
ROM:0275                 ld      (E008LoadMisc), a ; bit 5: OutDiscData', 0=enable output to laserdisc, 1=disable output
ROM:0275                                         ; bit 6: pin 11. PR-7820 ENTER (for PR-7820 only, can be disconnected on board for LD-V1000 operation)
ROM:0275                                         ; bit 7: pin 17. INT/EXT for PR-7820, ENTER for LD-V1000
ROM:0278                 ld      a, (A021LdpCmdByte)
ROM:027B                 ld      (E020LaserdiscData), a ; load output '374 with byte to be sent to PR-7820
ROM:027E                 ld      hl, A020CurrentValOfE008 ; caches current value that has been written to E008 (since E008 cannot be read)
ROM:0281                 res     5, (hl)         ; enable output of LDP data '374
ROM:0283                 ld      a, (hl)
ROM:0284                 ld      (E008LoadMisc), a ; bit 5: OutDiscData', 0=enable output to laserdisc, 1=disable output
ROM:0284                                         ; bit 6: pin 11. PR-7820 ENTER (for PR-7820 only, can be disconnected on board for LD-V1000 operation)
ROM:0284                                         ; bit 7: pin 17. INT/EXT for PR-7820, ENTER for LD-V1000
ROM:0287                 res     6, (hl)         ; enable ENTER' line for PR-7820 so it knows there is a command waiting
ROM:0289                 ld      a, (hl)
ROM:028A                 ld      (E008LoadMisc), a ; bit 5: OutDiscData', 0=enable output to laserdisc, 1=disable output
ROM:028A                                         ; bit 6: pin 11. PR-7820 ENTER (for PR-7820 only, can be disconnected on board for LD-V1000 operation)
ROM:028A                                         ; bit 7: pin 17. INT/EXT for PR-7820, ENTER for LD-V1000
ROM:028D                 call    MakeADelay      ; creates a delay (I haven't calculated how long)
ROM:0290                 ld      hl, A020CurrentValOfE008 ; caches current value that has been written to E008 (since E008 cannot be read)
ROM:0293                 set     6, (hl)         ; disable ENTER' line
ROM:0295                 ld      a, (hl)
ROM:0296                 ld      (E008LoadMisc), a ; bit 5: OutDiscData', 0=enable output to laserdisc, 1=disable output
ROM:0296                                         ; bit 6: pin 11. PR-7820 ENTER (for PR-7820 only, can be disconnected on board for LD-V1000 operation)
ROM:0296                                         ; bit 7: pin 17. INT/EXT for PR-7820, ENTER for LD-V1000
ROM:0299                 call    MakeADelay      ; creates a delay (I haven't calculated how long)
ROM:029C                 ld      hl, A020CurrentValOfE008 ; caches current value that has been written to E008 (since E008 cannot be read)
ROM:029F                 set     5, (hl)         ; disable output of LDP data '374
ROM:02A1                 ld      a, (hl)
ROM:02A2                 ld      (E008LoadMisc), a ; bit 5: OutDiscData', 0=enable output to laserdisc, 1=disable output
ROM:02A2                                         ; bit 6: pin 11. PR-7820 ENTER (for PR-7820 only, can be disconnected on board for LD-V1000 operation)
ROM:02A2                                         ; bit 7: pin 17. INT/EXT for PR-7820, ENTER for LD-V1000
ROM:02A5                 pop     hl
ROM:02A6                 ret
ROM:02A6 ; END OF FUNCTION CHUNK FOR SendA021ToLdp

<end>

The PR-7820 mode:

  • - Lowers/enables PR7820_INT/EXT' (pin 17)
  • - Puts command on data bus
  • - Goes into output mode
  • - Lowers/enables PR7820_ENTER' to tell the PR7820 to process the command (pin 11)
  • - Delays for a long time (I haven't measured how long, but Thayer's Quest waits for 20 ms)
  • - Raises/disables PR7820_ENTER' (pin 11)
  • - Goes into input mode
  • - NOTE : does not raise/disable PR7820_INT/EXT' (pin 17)


So what is a strategy for auto-detecting which player is plugged in?

Here's what I've come up with so far:

- Both modes lower pin 17 and keep it low so we can ignore that as it does not help us.
- PR-7820 mode treats pin 11 as an ouput while LD-V1000 reads pin 11 as an input.
- Both modes treat pin 7 as an input, but LD-V1000 will be outputting a command to the data bus while it is waiting for pin 7 to go low, while PR-7820 mode will be in input mode (see $1F9 in the ROM, I didn't post this disassembly).

So one possible algorithm to detect the player type is this:
- Enable input mode for pin 11 and enable its internal pull-up resistor.  Put pin 7 in output  mode.  Put data bus in input mode with pull-up resistors enabled on all data lines.
- Wait a long time (like the amount of time from dragon's lair powering on until it sends the first play command) for pin 11 to go low.
- If pin 11 goes low, it probably is PR-7820 mode.  Check the data bus to see if there is a command to be extra sure.
- If pin 11 hasn't gone low, go into ouput mode, lower pin 11, and quickly go back into input mode with internal pull-up enabled (enough time to simulate the status strobe).  Check to make sure that the line comes back to a high state within a reasonable amount of time.  If it doesn't come high, it probably is PR-7820 mode and Dexter and the game lowered the line at the same time (which is regrettable but I can't see an alternative).  If it comes high very quickly, it probably is still PR-7820 mode forcing the line high.  If it comes high a little slower, then it probably is LD-V1000 mode so lower pin 7 and check to see that a command is on the data bus.  If a command is present, then it is for sure LD-V1000 mode.  If the databus is still empty, it means that either it's LD-V1000 mode but we received a FF 'no entry' command or that nothing is plugged into Dexter and we have to start the test over again.
- If starting the test over again, wait less time the second iteration so that the boot delay isn't drawn out.

Wednesday, May 20, 2015

Working on PR-7820, using Thayer's Quest to test

Yep, it's my messy work area.

On my lap is my thayer's quest boardset (it wasn't working until I unscrewed the top board to troubleshoot, then it just magically started working!).  On the desk is my Dexter rev3 prototype board, my LDP sniffer board, and my logic analyzer.  Dexter is outputting to my TV which is also getting sound from the game board.  My PC monitor is showing traffic being sent to and from Dexter.

Hopefully, finishing up PR-7820 mode won't be too difficult from here on now that I've got a good way to test it.

Tuesday, May 19, 2015

Dexter rev 3C PCB sent off to fabrication plant

Applying lessons learned from 3b, I've sent off rev 3c to have four more PCBs made.  If I don't find any serious problems, the next step will be to make 20 of these PCBs and have the PCB manufacturer also assemble them as a trial run for the final product.  A looong time ago, I asked who would be interested in one of these 20 prototypes and I still have everyone's name who expressed interest.  It's been a long road but the end is in sight.

In the meantime, I am going to work on PR-7820 support next.

Monday, May 18, 2015

Lord Victorino tries out the new Dexter Manager

Lord Victorino has put together a short video showing his experience using the Dexter Manager desktop application.


Wednesday, May 13, 2015

Dexter Manager "finished" enough for people to start using it

If you have a Dexter prototype board, and you want to change which disc Dexter uses, you will want to get Dexter Manager, the app I designed to help.. well.. manage Dexter :)

I've been working on this for quite a while now and finally have it to the point where I'm ready for people to start testing/using it.  You will need a Dexter rev3 board or newer and if you only use Dexter with a single disc, it won't help you at this time.

Talk to me if you are interested in using it and I will point you in the right direction.