I had never had to track down a short circuit this difficult before. I guess I am somewhat of a newbie in this area.
Friday, November 25, 2016
Friday, November 11, 2016
Tuesday, November 8, 2016
I made four Cliff Hanger VMB PCBs
I've been slowly acquiring Cliff Hanger hardware for research and had trouble getting my hands on the VMB board. So I borrowed one and then cloned it:
Hopefully, I can get some time soon to solder the parts onto it so it can be tested.
Hopefully, I can get some time soon to solder the parts onto it so it can be tested.
Wednesday, August 24, 2016
All Dexters now shipped!
It took me from the end of April to the end of August, but I've now shipped every Dexter unit from the Jan-Feb 2016 pre-order. Hopefully, you will agree that me that it was worth the wait. :)
I now need to focus on selling my house and moving. Once I've done this, I should have some time to sell some more Dexter units and do some Dexter+Merlin updates.
I now need to focus on selling my house and moving. Once I've done this, I should have some time to sell some more Dexter units and do some Dexter+Merlin updates.
Monday, July 25, 2016
Merlin + Dexter integration update
It sounds like after seeing Dexter and Merlin in action at California Extreme that people are really chomping at the bit to get this installed into their cabs. While I can appreciate that people are excited, I also need to be realistic about timing and estimates. Right now, I am still shipping out Dexter units (yes, still!) and then need to move to a new house (my wife has been patient with Dexter and now it's her turn to get what she wants). So I am going to estimate that I will have my pat of Dexter + Merlin integration finished by the end of 2016. Not what some people were hoping, but I prefer to give real estimates than to keep missing my dates.
Friday, July 15, 2016
Dexter article on Engadget, linked via Adafruit
This is a cool article about Dexter that has given the project some decent additional exposure: https://blog.adafruit.com/2016/07/15/using-raspberry-pi-to-replace-laserdiscs-in-arcade-cabinets-raspberrypi-piday-raspberry_pi/
Friday, June 17, 2016
Dexter orders won't be shipping next week
Hi guys,
I am taking a week off from shipping out Dexter orders. The shipping will resume on 27 June. Sorry for the delay and thanks for your patience. Hopefully people who have received their orders already can agree that it is worth the wait. :)
I am taking a week off from shipping out Dexter orders. The shipping will resume on 27 June. Sorry for the delay and thanks for your patience. Hopefully people who have received their orders already can agree that it is worth the wait. :)
Wednesday, June 8, 2016
How I fixed Dexter's Firefox problem
So Firefox was working fine with Dexter except for one thing: Firefox's built-in disc test.
I decided that I would need to study the disc test in detail to see what it was doing that Dexter was not supporting. Here is the disassembled version of the disc test (warning, it's long!!)
ROM:F238 DISK1: ; CODE XREF: ROM:EE68 P
ROM:F238 ldb #$63 ; 'c'
ROM:F23A lda <DQ_WTO ; write timeout counter
ROM:F23C bne DispWriteError
ROM:F23E jsr UNMESS
ROM:F241 bra PostWriteErrCheck ; display frame read
ROM:F243 ; ---------------------------------------------------------------------------
ROM:F243
ROM:F243 DispWriteError: ; CODE XREF: DISK1+4 j
ROM:F243 jsr NWMESS
ROM:F246
ROM:F246 PostWriteErrCheck: ; CODE XREF: DISK1+9 j
ROM:F246 ldy #PFRW20_30 ; display frame read
ROM:F24A ldu #DQ_INB ; input buffer
ROM:F24D jsr VW6DIG ; display 6 digits with zero suppression
ROM:F250 ldy #PFRW25_30 ; display frame desired
ROM:F254 ldu #DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F254 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F257 jsr VW6DIG ; display 6 digits with zero suppression
ROM:F25A lda NVRAMZ_R_BYT0 ; switches are active low
ROM:F25D anda #IN0_RightThumb
ROM:F25F beq EnableDiscReset ; turn disk reset on
ROM:F261 lda #DRSTOFF ; leave disk alone
ROM:F263 bra PostRightThumbCheck
ROM:F265 ; ---------------------------------------------------------------------------
ROM:F265
ROM:F265 EnableDiscReset: ; CODE XREF: DISK1+27 j
ROM:F265 lda #DRSTON ; turn disk reset on
ROM:F267
ROM:F267 PostRightThumbCheck: ; CODE XREF: DISK1+2B j
ROM:F267 sta DSKRST ; aka W.RSTD
ROM:F267 ; disk reset (active low) (at least 2 ms)
ROM:F26A lda <RL_DTC
ROM:F26C sta W_AULD
ROM:F26F lda <RHTCHN
ROM:F271 sta W_AURD
ROM:F274 ldb #$61 ; 'a' ; "READ ERROR"
ROM:F276 lda <DQ_RTO ; read timeout counter
ROM:F278 beq OnNoReadError ; erase "READ ERROR"
ROM:F27A
ROM:F27A DisplayReadError: ; CODE XREF: DISK1+52 j
ROM:F27A jsr NWMESS ; display "READ ERROR"
ROM:F27D bra OnError
ROM:F27F ; ---------------------------------------------------------------------------
ROM:F27F bra Disc1Return
ROM:F281 ; ---------------------------------------------------------------------------
ROM:F281
ROM:F281 OnNoReadError: ; CODE XREF: DISK1+40 j
ROM:F281 jsr UNMESS ; erase "READ ERROR"
ROM:F284 ldb #$61 ; 'a'
ROM:F286 lda <DQ_LED ; lead in if >0, lead out if >=80
ROM:F288 beq NotLeadInOrLeadOut
ROM:F28A bpl DisplayReadError ; cannot be LEAD-IN, display "READ ERROR"
ROM:F28C ldd #2 ; if we get this far, it means we encountered the LEAD-OUT area
ROM:F28F std JMPCT ; back up 2 at a time
ROM:F292 lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F292 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F294 anda #7 ; clear play forward bit
ROM:F296 sta <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F296 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F298 jmp $32JumpBack ; jump back
ROM:F29B ; ---------------------------------------------------------------------------
ROM:F29B
ROM:F29B Disc1Return: ; CODE XREF: DISK1+47 j
ROM:F29B ; DISK1+7A j ...
ROM:F29B rts
ROM:F29C ; ---------------------------------------------------------------------------
ROM:F29C
ROM:F29C NotLeadInOrLeadOut: ; CODE XREF: DISK1+50 j
ROM:F29C lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F29C ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F29E anda #7 ; ignore play forward flag
ROM:F2A0 cmpa <DQ_MFD ; manchester field in decimal as read
ROM:F2A2 bne FrameMismatch ; wrong frame was read
ROM:F2A4 ldd <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F2A4 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F2A6 cmpd <DQ_MFD+1 ; manchester field in decimal as read
ROM:F2A9 beq FrameMatch
ROM:F2AB
ROM:F2AB FrameMismatch: ; CODE XREF: DISK1+6A j
ROM:F2AB ldb #$62 ; 'b'
ROM:F2AD jsr NWMESS ; display "WRONG FRAME"
ROM:F2B0
ROM:F2B0 OnError: ; CODE XREF: DISK1+45 j
ROM:F2B0 lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F2B0 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F2B2 bpl Disc1Return ; branch if not playing forward
ROM:F2B4 lda <RL_PAS
ROM:F2B6 cmpa #$40 ; '@'
ROM:F2B8 bcs Disc1Return ; branch if skipping backward
ROM:F2BA cmpa #$C0 ; '+'
ROM:F2BC bhi Disc1Return ; branch if skipping forward
ROM:F2BE lda <RL_CNM
ROM:F2C0 cmpa #$C0 ; '+'
ROM:F2C2 lbcs OnJoystickCenteredFreeze ; branch if not playing forward-keep trying
ROM:F2C6 lbra OnPlaying ; branch in case the disk is bad here
ROM:F2C9 ; ---------------------------------------------------------------------------
ROM:F2C9
ROM:F2C9 FrameMatch: ; CODE XREF: DISK1+71 j
ROM:F2C9 ldb #$62 ; 'b'
ROM:F2CB jsr UNMESS ; erase "WRONG FRAME" message
ROM:F2CE lda <RL_PAS
ROM:F2D0 cmpa #$60 ; '`'
ROM:F2D2 bcc OnJoystickNotLeft ; branch if we are not jumping backward
ROM:F2D4 ldb NVRAMZ_R_BYT0 ; switches are active low
ROM:F2D7 andb #IN0_LeftThumb
ROM:F2D9 bne PostLeftButtonCheck ; "BACK"
ROM:F2DB lda JMPBCK ; 0 = going forward, non-zero = going backward
ROM:F2DE bne $22 ; branch if last frame we jumped backward, SO GO FORWARD THIS TIME
ROM:F2E0
ROM:F2E0 $32JumpBack: ; CODE XREF: DISK1+60 J
ROM:F2E0 ; DISK1+E5 j
ROM:F2E0 lda #$20 ; ' ' ; set joystick for no change
ROM:F2E2
ROM:F2E2 PostLeftButtonCheck: ; CODE XREF: DISK1+A1 j
ROM:F2E2 ldb #$5F ; '_' ; "BACK"
ROM:F2E4 stb JMPBCK ; flag jump backward (NON-ZERO)
ROM:F2E7 cmpa #$20 ; ' '
ROM:F2E9 bcs $25AccelJmpCounter ; branch if we need to accelerate the jump counter
ROM:F2EB cmpa #$40 ; '@'
ROM:F2ED bcs PositionDisc ; branch if we aren't changing the jump count
ROM:F2EF
ROM:F2EF DecJMPCT: ; CODE XREF: DISK1+F0 j
ROM:F2EF lda JMPCT+1
ROM:F2F2 adda #$99 ; 'Ö' ; -1 decimal
ROM:F2F4 daa
ROM:F2F5 sta JMPCT+1
ROM:F2F8 lda JMPCT
ROM:F2FB adca #$99 ; 'Ö'
ROM:F2FD daa
ROM:F2FE bcs PostUnderflowAdjust ; branch if we haven't underflowed
ROM:F300 lda #1
ROM:F302 sta JMPCT+1
ROM:F305 lda #0
ROM:F307
ROM:F307 PostUnderflowAdjust: ; CODE XREF: DISK1+C6 j
ROM:F307 sta JMPCT
ROM:F30A
ROM:F30A PositionDisc: ; CODE XREF: DISK1+B5 j
ROM:F30A jsr DISKP ; Change desired frame no matter what which will cause a skip.
ROM:F30A ; If jump count is zero, it will be adjusted to 1.
ROM:F30D bra DisplayCurOp ; display current operation
ROM:F30F ; ---------------------------------------------------------------------------
ROM:F30F
ROM:F30F OnJoystickNotLeft: ; CODE XREF: DISK1+9A j
ROM:F30F cmpa #$A0 ; 'á'
ROM:F311 bls OnJoystickNotRight
ROM:F313 ldb NVRAMZ_R_BYT0 ; switches are active low
ROM:F316 andb #IN0_LeftThumb
ROM:F318 bne PostLeftThumbCheck ; branch if button is not pressed
ROM:F31A lda JMPBCK ; 0 = going forward, non-zero = going backward
ROM:F31D beq $32JumpBack ; last frame we jumped forward, so go backward this time
ROM:F31F
ROM:F31F $22: ; CODE XREF: DISK1+A6 j
ROM:F31F lda #$D0 ; '-' ; set joystick for no change
ROM:F321
ROM:F321 PostLeftThumbCheck: ; CODE XREF: DISK1+E0 j
ROM:F321 ldb #$60 ; '`' ; "FORWARD"
ROM:F323 clr JMPBCK ; flag jumping forward
ROM:F326 cmpa #$C0 ; '+'
ROM:F328 bcs DecJMPCT
ROM:F32A cmpa #$E0 ; 'a'
ROM:F32C bcs OnNoJmpChange ; add/subtract "JMPCT" to current disk position
ROM:F32E
ROM:F32E $25AccelJmpCounter: ; CODE XREF: DISK1+B1 j
ROM:F32E lda JMPCT+1
ROM:F331 lsra
ROM:F332 lsra
ROM:F333 lsra
ROM:F334 lsra ; add ten's digit to one's digit (pseudo speedup)
ROM:F335 orcc #1
ROM:F337 adca JMPCT+1
ROM:F33A daa
ROM:F33B sta JMPCT+1
ROM:F33E lda JMPCT
ROM:F341 adca #0
ROM:F343 daa
ROM:F344 bcc loc_F34B
ROM:F346 lda #$99 ; 'Ö'
ROM:F348 sta JMPCT+1
ROM:F34B
ROM:F34B loc_F34B: ; CODE XREF: DISK1+10C j
ROM:F34B sta JMPCT
ROM:F34E
ROM:F34E OnNoJmpChange: ; CODE XREF: DISK1+F4 j
ROM:F34E jsr DISKP ; add/subtract "JMPCT" to current disk position
ROM:F351 bra DisplayCurOp ; display current operation
ROM:F353 ; ---------------------------------------------------------------------------
ROM:F353
ROM:F353 OnJoystickNotRight: ; CODE XREF: DISK1+D9 j
ROM:F353 lda <RL_CNM
ROM:F355 cmpa #$C0 ; '+'
ROM:F357 bcs OnJoystickCenteredFreeze
ROM:F359
ROM:F359 OnPlaying: ; CODE XREF: DISK1+8E j
ROM:F359 ldd #0 ; clear jmp counter
ROM:F35C std JMPCT
ROM:F35F lda FLDSYNC ; sync with disk, 0 for F, !=0 for alternate field
ROM:F362 beq ShowPlayingMessage ; branch if we're on the first field (the current frame number will not change this field)
ROM:F364 ldd #1 ; the current frame number will advance by 1 on the next field,
ROM:F364 ; so adjust our desired frame number accordingly so that we don't send any jumps
ROM:F367 std JMPCT
ROM:F36A jsr DISKA ; decimal add of JMPCT (16-bit word) to DQ_GMD
ROM:F36D
ROM:F36D ShowPlayingMessage: ; CODE XREF: DISK1+12A j
ROM:F36D ldb #$5E ; '^' ; "PLAY"
ROM:F36F lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F36F ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F371 oraa #$80 ; 'Ç'
ROM:F373 sta <DQ_GMD ; set play forward flag
ROM:F375 bra DisplayCurOp ; display current operation
ROM:F377 ; ---------------------------------------------------------------------------
ROM:F377
ROM:F377 OnJoystickCenteredFreeze: ; CODE XREF: DISK1+8A j
ROM:F377 ; DISK1+11F j
ROM:F377 lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F377 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F379 anda #7
ROM:F37B sta <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F37B ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F37D ldd #0
ROM:F380 std JMPCT ; clear jmp counter
ROM:F383 ldb #$5D ; ']' ; "FREEZE"
ROM:F385
ROM:F385 DisplayCurOp: ; CODE XREF: DISK1+D5 j
ROM:F385 ; DISK1+119 j ...
ROM:F385 jsr NWMESS ; display current operation
ROM:F388 leay 2,y ; space over to the right
ROM:F38A ldu #JMPCT
ROM:F38D jmp VW4DIG ; display 4 digits
ROM:F38D ; End of function DISK1
ROM:F38D
ROM:F390
ROM:F390 ; =============== S U B R O U T I N E =======================================
ROM:F390
ROM:F390 ; Change desired frame no matter what which will cause a skip.
ROM:F390 ; If jump count is zero, it will be adjusted to 1.
ROM:F390
ROM:F390 DISKP: ; CODE XREF: DISK1:PositionDisc P
ROM:F390 ; DISK1:OnNoJmpChange P
ROM:F390 lda JMPCT
ROM:F393 oraa JMPCT+1
ROM:F396 bne AdjustDesiredFrame
ROM:F398 inc JMPCT+1 ; counter should always be non-zero
ROM:F39B
ROM:F39B AdjustDesiredFrame: ; CODE XREF: DISKP+6 j
ROM:F39B lda JMPBCK ; 0 = going forward, non-zero = going backward
ROM:F39E beq DISKA ; branch if we are NOT jumping backward
ROM:F3A0 pshs b
ROM:F3A2 ldd #$9999
ROM:F3A5 subd JMPCT
ROM:F3A8 sta <TTEMP ; 1's complement
ROM:F3AA tfr b, a
ROM:F3AC puls b
ROM:F3AE orcc #1 ; add 1 for 2's complement
ROM:F3B0 adca <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:F3B0 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3B2 daa
ROM:F3B3 sta <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:F3B3 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3B5 lda <TTEMP
ROM:F3B7 adca <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F3B7 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3B9 daa
ROM:F3BA sta <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F3BA ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3BC lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F3BC ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3BE adca #$99 ; 'Ö'
ROM:F3C0 daa
ROM:F3C1 anda #7 ; clear play forward flag
ROM:F3C3 sta <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F3C3 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3C5 bcc ResetToFrame1 ; branch if we've underflowed, reset to frame 1
ROM:F3C7 oraa <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F3C7 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3C9 oraa <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:F3C9 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3CB bne Done ; branch if the new frame is not 000000
ROM:F3CD
ROM:F3CD ResetToFrame1: ; CODE XREF: DISKP+35 j
ROM:F3CD lda #0 ; frame 0 is not allowed, reset to frame 1
ROM:F3CF sta <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F3CF ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3D1 sta <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F3D1 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3D3 lda #1
ROM:F3D5 sta <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:F3D5 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3D7
ROM:F3D7 Done: ; CODE XREF: DISKP+3B j
ROM:F3D7 bra DISKP_DONE
ROM:F3D7 ; End of function DISKP
ROM:F3D7
ROM:F3D9
ROM:F3D9 ; =============== S U B R O U T I N E =======================================
ROM:F3D9
ROM:F3D9 ; decimal add of JMPCT (16-bit word) to DQ_GMD
ROM:F3D9
ROM:F3D9 DISKA: ; CODE XREF: DISK1+132 P
ROM:F3D9 ; DISKP+E j
ROM:F3D9 lda JMPCT+1
ROM:F3DC adda <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:F3DC ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3DE daa
ROM:F3DF sta <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:F3DF ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3E1 lda <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F3E1 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3E3 adca JMPCT
ROM:F3E6 daa
ROM:F3E7 sta <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F3E7 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3E9 lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F3E9 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3EB adca #0
ROM:F3ED anda #7 ; clear play forward flag
ROM:F3EF sta <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F3EF ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3F1
ROM:F3F1 DISKP_DONE: ; CODE XREF: DISKP:Done j
ROM:F3F1 rts
ROM:F3F1 ; End of function DISKA
I decided that I would need to study the disc test in detail to see what it was doing that Dexter was not supporting. Here is the disassembled version of the disc test (warning, it's long!!)
ROM:F238 DISK1: ; CODE XREF: ROM:EE68 P
ROM:F238 ldb #$63 ; 'c'
ROM:F23A lda <DQ_WTO ; write timeout counter
ROM:F23C bne DispWriteError
ROM:F23E jsr UNMESS
ROM:F241 bra PostWriteErrCheck ; display frame read
ROM:F243 ; ---------------------------------------------------------------------------
ROM:F243
ROM:F243 DispWriteError: ; CODE XREF: DISK1+4 j
ROM:F243 jsr NWMESS
ROM:F246
ROM:F246 PostWriteErrCheck: ; CODE XREF: DISK1+9 j
ROM:F246 ldy #PFRW20_30 ; display frame read
ROM:F24A ldu #DQ_INB ; input buffer
ROM:F24D jsr VW6DIG ; display 6 digits with zero suppression
ROM:F250 ldy #PFRW25_30 ; display frame desired
ROM:F254 ldu #DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F254 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F257 jsr VW6DIG ; display 6 digits with zero suppression
ROM:F25A lda NVRAMZ_R_BYT0 ; switches are active low
ROM:F25D anda #IN0_RightThumb
ROM:F25F beq EnableDiscReset ; turn disk reset on
ROM:F261 lda #DRSTOFF ; leave disk alone
ROM:F263 bra PostRightThumbCheck
ROM:F265 ; ---------------------------------------------------------------------------
ROM:F265
ROM:F265 EnableDiscReset: ; CODE XREF: DISK1+27 j
ROM:F265 lda #DRSTON ; turn disk reset on
ROM:F267
ROM:F267 PostRightThumbCheck: ; CODE XREF: DISK1+2B j
ROM:F267 sta DSKRST ; aka W.RSTD
ROM:F267 ; disk reset (active low) (at least 2 ms)
ROM:F26A lda <RL_DTC
ROM:F26C sta W_AULD
ROM:F26F lda <RHTCHN
ROM:F271 sta W_AURD
ROM:F274 ldb #$61 ; 'a' ; "READ ERROR"
ROM:F276 lda <DQ_RTO ; read timeout counter
ROM:F278 beq OnNoReadError ; erase "READ ERROR"
ROM:F27A
ROM:F27A DisplayReadError: ; CODE XREF: DISK1+52 j
ROM:F27A jsr NWMESS ; display "READ ERROR"
ROM:F27D bra OnError
ROM:F27F ; ---------------------------------------------------------------------------
ROM:F27F bra Disc1Return
ROM:F281 ; ---------------------------------------------------------------------------
ROM:F281
ROM:F281 OnNoReadError: ; CODE XREF: DISK1+40 j
ROM:F281 jsr UNMESS ; erase "READ ERROR"
ROM:F284 ldb #$61 ; 'a'
ROM:F286 lda <DQ_LED ; lead in if >0, lead out if >=80
ROM:F288 beq NotLeadInOrLeadOut
ROM:F28A bpl DisplayReadError ; cannot be LEAD-IN, display "READ ERROR"
ROM:F28C ldd #2 ; if we get this far, it means we encountered the LEAD-OUT area
ROM:F28F std JMPCT ; back up 2 at a time
ROM:F292 lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F292 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F294 anda #7 ; clear play forward bit
ROM:F296 sta <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F296 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F298 jmp $32JumpBack ; jump back
ROM:F29B ; ---------------------------------------------------------------------------
ROM:F29B
ROM:F29B Disc1Return: ; CODE XREF: DISK1+47 j
ROM:F29B ; DISK1+7A j ...
ROM:F29B rts
ROM:F29C ; ---------------------------------------------------------------------------
ROM:F29C
ROM:F29C NotLeadInOrLeadOut: ; CODE XREF: DISK1+50 j
ROM:F29C lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F29C ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F29E anda #7 ; ignore play forward flag
ROM:F2A0 cmpa <DQ_MFD ; manchester field in decimal as read
ROM:F2A2 bne FrameMismatch ; wrong frame was read
ROM:F2A4 ldd <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F2A4 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F2A6 cmpd <DQ_MFD+1 ; manchester field in decimal as read
ROM:F2A9 beq FrameMatch
ROM:F2AB
ROM:F2AB FrameMismatch: ; CODE XREF: DISK1+6A j
ROM:F2AB ldb #$62 ; 'b'
ROM:F2AD jsr NWMESS ; display "WRONG FRAME"
ROM:F2B0
ROM:F2B0 OnError: ; CODE XREF: DISK1+45 j
ROM:F2B0 lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F2B0 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F2B2 bpl Disc1Return ; branch if not playing forward
ROM:F2B4 lda <RL_PAS
ROM:F2B6 cmpa #$40 ; '@'
ROM:F2B8 bcs Disc1Return ; branch if skipping backward
ROM:F2BA cmpa #$C0 ; '+'
ROM:F2BC bhi Disc1Return ; branch if skipping forward
ROM:F2BE lda <RL_CNM
ROM:F2C0 cmpa #$C0 ; '+'
ROM:F2C2 lbcs OnJoystickCenteredFreeze ; branch if not playing forward-keep trying
ROM:F2C6 lbra OnPlaying ; branch in case the disk is bad here
ROM:F2C9 ; ---------------------------------------------------------------------------
ROM:F2C9
ROM:F2C9 FrameMatch: ; CODE XREF: DISK1+71 j
ROM:F2C9 ldb #$62 ; 'b'
ROM:F2CB jsr UNMESS ; erase "WRONG FRAME" message
ROM:F2CE lda <RL_PAS
ROM:F2D0 cmpa #$60 ; '`'
ROM:F2D2 bcc OnJoystickNotLeft ; branch if we are not jumping backward
ROM:F2D4 ldb NVRAMZ_R_BYT0 ; switches are active low
ROM:F2D7 andb #IN0_LeftThumb
ROM:F2D9 bne PostLeftButtonCheck ; "BACK"
ROM:F2DB lda JMPBCK ; 0 = going forward, non-zero = going backward
ROM:F2DE bne $22 ; branch if last frame we jumped backward, SO GO FORWARD THIS TIME
ROM:F2E0
ROM:F2E0 $32JumpBack: ; CODE XREF: DISK1+60 J
ROM:F2E0 ; DISK1+E5 j
ROM:F2E0 lda #$20 ; ' ' ; set joystick for no change
ROM:F2E2
ROM:F2E2 PostLeftButtonCheck: ; CODE XREF: DISK1+A1 j
ROM:F2E2 ldb #$5F ; '_' ; "BACK"
ROM:F2E4 stb JMPBCK ; flag jump backward (NON-ZERO)
ROM:F2E7 cmpa #$20 ; ' '
ROM:F2E9 bcs $25AccelJmpCounter ; branch if we need to accelerate the jump counter
ROM:F2EB cmpa #$40 ; '@'
ROM:F2ED bcs PositionDisc ; branch if we aren't changing the jump count
ROM:F2EF
ROM:F2EF DecJMPCT: ; CODE XREF: DISK1+F0 j
ROM:F2EF lda JMPCT+1
ROM:F2F2 adda #$99 ; 'Ö' ; -1 decimal
ROM:F2F4 daa
ROM:F2F5 sta JMPCT+1
ROM:F2F8 lda JMPCT
ROM:F2FB adca #$99 ; 'Ö'
ROM:F2FD daa
ROM:F2FE bcs PostUnderflowAdjust ; branch if we haven't underflowed
ROM:F300 lda #1
ROM:F302 sta JMPCT+1
ROM:F305 lda #0
ROM:F307
ROM:F307 PostUnderflowAdjust: ; CODE XREF: DISK1+C6 j
ROM:F307 sta JMPCT
ROM:F30A
ROM:F30A PositionDisc: ; CODE XREF: DISK1+B5 j
ROM:F30A jsr DISKP ; Change desired frame no matter what which will cause a skip.
ROM:F30A ; If jump count is zero, it will be adjusted to 1.
ROM:F30D bra DisplayCurOp ; display current operation
ROM:F30F ; ---------------------------------------------------------------------------
ROM:F30F
ROM:F30F OnJoystickNotLeft: ; CODE XREF: DISK1+9A j
ROM:F30F cmpa #$A0 ; 'á'
ROM:F311 bls OnJoystickNotRight
ROM:F313 ldb NVRAMZ_R_BYT0 ; switches are active low
ROM:F316 andb #IN0_LeftThumb
ROM:F318 bne PostLeftThumbCheck ; branch if button is not pressed
ROM:F31A lda JMPBCK ; 0 = going forward, non-zero = going backward
ROM:F31D beq $32JumpBack ; last frame we jumped forward, so go backward this time
ROM:F31F
ROM:F31F $22: ; CODE XREF: DISK1+A6 j
ROM:F31F lda #$D0 ; '-' ; set joystick for no change
ROM:F321
ROM:F321 PostLeftThumbCheck: ; CODE XREF: DISK1+E0 j
ROM:F321 ldb #$60 ; '`' ; "FORWARD"
ROM:F323 clr JMPBCK ; flag jumping forward
ROM:F326 cmpa #$C0 ; '+'
ROM:F328 bcs DecJMPCT
ROM:F32A cmpa #$E0 ; 'a'
ROM:F32C bcs OnNoJmpChange ; add/subtract "JMPCT" to current disk position
ROM:F32E
ROM:F32E $25AccelJmpCounter: ; CODE XREF: DISK1+B1 j
ROM:F32E lda JMPCT+1
ROM:F331 lsra
ROM:F332 lsra
ROM:F333 lsra
ROM:F334 lsra ; add ten's digit to one's digit (pseudo speedup)
ROM:F335 orcc #1
ROM:F337 adca JMPCT+1
ROM:F33A daa
ROM:F33B sta JMPCT+1
ROM:F33E lda JMPCT
ROM:F341 adca #0
ROM:F343 daa
ROM:F344 bcc loc_F34B
ROM:F346 lda #$99 ; 'Ö'
ROM:F348 sta JMPCT+1
ROM:F34B
ROM:F34B loc_F34B: ; CODE XREF: DISK1+10C j
ROM:F34B sta JMPCT
ROM:F34E
ROM:F34E OnNoJmpChange: ; CODE XREF: DISK1+F4 j
ROM:F34E jsr DISKP ; add/subtract "JMPCT" to current disk position
ROM:F351 bra DisplayCurOp ; display current operation
ROM:F353 ; ---------------------------------------------------------------------------
ROM:F353
ROM:F353 OnJoystickNotRight: ; CODE XREF: DISK1+D9 j
ROM:F353 lda <RL_CNM
ROM:F355 cmpa #$C0 ; '+'
ROM:F357 bcs OnJoystickCenteredFreeze
ROM:F359
ROM:F359 OnPlaying: ; CODE XREF: DISK1+8E j
ROM:F359 ldd #0 ; clear jmp counter
ROM:F35C std JMPCT
ROM:F35F lda FLDSYNC ; sync with disk, 0 for F, !=0 for alternate field
ROM:F362 beq ShowPlayingMessage ; branch if we're on the first field (the current frame number will not change this field)
ROM:F364 ldd #1 ; the current frame number will advance by 1 on the next field,
ROM:F364 ; so adjust our desired frame number accordingly so that we don't send any jumps
ROM:F367 std JMPCT
ROM:F36A jsr DISKA ; decimal add of JMPCT (16-bit word) to DQ_GMD
ROM:F36D
ROM:F36D ShowPlayingMessage: ; CODE XREF: DISK1+12A j
ROM:F36D ldb #$5E ; '^' ; "PLAY"
ROM:F36F lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F36F ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F371 oraa #$80 ; 'Ç'
ROM:F373 sta <DQ_GMD ; set play forward flag
ROM:F375 bra DisplayCurOp ; display current operation
ROM:F377 ; ---------------------------------------------------------------------------
ROM:F377
ROM:F377 OnJoystickCenteredFreeze: ; CODE XREF: DISK1+8A j
ROM:F377 ; DISK1+11F j
ROM:F377 lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F377 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F379 anda #7
ROM:F37B sta <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F37B ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F37D ldd #0
ROM:F380 std JMPCT ; clear jmp counter
ROM:F383 ldb #$5D ; ']' ; "FREEZE"
ROM:F385
ROM:F385 DisplayCurOp: ; CODE XREF: DISK1+D5 j
ROM:F385 ; DISK1+119 j ...
ROM:F385 jsr NWMESS ; display current operation
ROM:F388 leay 2,y ; space over to the right
ROM:F38A ldu #JMPCT
ROM:F38D jmp VW4DIG ; display 4 digits
ROM:F38D ; End of function DISK1
ROM:F38D
ROM:F390
ROM:F390 ; =============== S U B R O U T I N E =======================================
ROM:F390
ROM:F390 ; Change desired frame no matter what which will cause a skip.
ROM:F390 ; If jump count is zero, it will be adjusted to 1.
ROM:F390
ROM:F390 DISKP: ; CODE XREF: DISK1:PositionDisc P
ROM:F390 ; DISK1:OnNoJmpChange P
ROM:F390 lda JMPCT
ROM:F393 oraa JMPCT+1
ROM:F396 bne AdjustDesiredFrame
ROM:F398 inc JMPCT+1 ; counter should always be non-zero
ROM:F39B
ROM:F39B AdjustDesiredFrame: ; CODE XREF: DISKP+6 j
ROM:F39B lda JMPBCK ; 0 = going forward, non-zero = going backward
ROM:F39E beq DISKA ; branch if we are NOT jumping backward
ROM:F3A0 pshs b
ROM:F3A2 ldd #$9999
ROM:F3A5 subd JMPCT
ROM:F3A8 sta <TTEMP ; 1's complement
ROM:F3AA tfr b, a
ROM:F3AC puls b
ROM:F3AE orcc #1 ; add 1 for 2's complement
ROM:F3B0 adca <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:F3B0 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3B2 daa
ROM:F3B3 sta <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:F3B3 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3B5 lda <TTEMP
ROM:F3B7 adca <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F3B7 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3B9 daa
ROM:F3BA sta <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F3BA ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3BC lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F3BC ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3BE adca #$99 ; 'Ö'
ROM:F3C0 daa
ROM:F3C1 anda #7 ; clear play forward flag
ROM:F3C3 sta <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F3C3 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3C5 bcc ResetToFrame1 ; branch if we've underflowed, reset to frame 1
ROM:F3C7 oraa <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F3C7 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3C9 oraa <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:F3C9 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3CB bne Done ; branch if the new frame is not 000000
ROM:F3CD
ROM:F3CD ResetToFrame1: ; CODE XREF: DISKP+35 j
ROM:F3CD lda #0 ; frame 0 is not allowed, reset to frame 1
ROM:F3CF sta <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F3CF ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3D1 sta <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F3D1 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3D3 lda #1
ROM:F3D5 sta <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:F3D5 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3D7
ROM:F3D7 Done: ; CODE XREF: DISKP+3B j
ROM:F3D7 bra DISKP_DONE
ROM:F3D7 ; End of function DISKP
ROM:F3D7
ROM:F3D9
ROM:F3D9 ; =============== S U B R O U T I N E =======================================
ROM:F3D9
ROM:F3D9 ; decimal add of JMPCT (16-bit word) to DQ_GMD
ROM:F3D9
ROM:F3D9 DISKA: ; CODE XREF: DISK1+132 P
ROM:F3D9 ; DISKP+E j
ROM:F3D9 lda JMPCT+1
ROM:F3DC adda <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:F3DC ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3DE daa
ROM:F3DF sta <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:F3DF ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3E1 lda <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F3E1 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3E3 adca JMPCT
ROM:F3E6 daa
ROM:F3E7 sta <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:F3E7 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3E9 lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F3E9 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3EB adca #0
ROM:F3ED anda #7 ; clear play forward flag
ROM:F3EF sta <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:F3EF ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:F3F1
ROM:F3F1 DISKP_DONE: ; CODE XREF: DISKP:Done j
ROM:F3F1 rts
ROM:F3F1 ; End of function DISKA
I am not going to go into great detail explaining the disassembly as I've included plenty of comments. A few notes are that the left and right thumb buttons can do stuff, and then moving the controller vertically while the disc is paused (ie "frozen") will cause the disc to play forward at 1X. Both of these are undocumented as far as I can tell.
Also of note is that this disc test is relatively simple despite appearing quite complex at first glance. While the test is active, it gets called every single field and does two things:
- checks to see if the disc is on the frame number that it expects for the current field
- tells the game program what laserdisc frame is wants to be on on the next field
If the first check fails, it prints an "FR" error message on the screen. Otherwise, it just reports the desired frame and actual frame which normally will match.
My conclusion at this point was that I was not going to find my answer by studying the disc test, but would need to study the main disc routines elsewhere in the code.
After more digging, I came across the function that actually sends new commands to the laserdisc player (warning, LONG!):
ROM:E650 ; =============== S U B R O U T I N E =======================================
ROM:E650
ROM:E650 ; create commands, output to disc
ROM:E650
ROM:E650 DODKWR: ; CODE XREF: DODK+35 P
ROM:E650 ; ROM:EE6F P
ROM:E650 lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:E650 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E652 bpl OnHighBitClear
ROM:E654 jsr GenPlayCmd
ROM:E657 bra AfterCmdCreated
ROM:E659 ; ---------------------------------------------------------------------------
ROM:E659
ROM:E659 OnHighBitClear: ; CODE XREF: DODKWR+2 j
ROM:E659 lda <DQ_LED ; lead in if >0, lead out if >=80
ROM:E65B beq OnNoLeadInOrLeadOut
ROM:E65D bmi loc_E664
ROM:E65F jsr sub_E751
ROM:E662 bra loc_E667
ROM:E664 ; ---------------------------------------------------------------------------
ROM:E664
ROM:E664 loc_E664: ; CODE XREF: DODKWR+D j
ROM:E664 jsr sub_E756
ROM:E667
ROM:E667 loc_E667: ; CODE XREF: DODKWR+12 j
ROM:E667 bra AfterCmdCreated
ROM:E669 ; ---------------------------------------------------------------------------
ROM:E669
ROM:E669 OnNoLeadInOrLeadOut: ; CODE XREF: DODKWR+B j
ROM:E669 lda <FLDSYNC ; sync with disk, 0 for F, !=0 for alternate field
ROM:E66B bne OnAltField
ROM:E66D jsr CreateCmdIfOnFirstField
ROM:E670 bra AfterCmdCreated
ROM:E672 ; ---------------------------------------------------------------------------
ROM:E672
ROM:E672 OnAltField: ; CODE XREF: DODKWR+1B j
ROM:E672 jsr CreateCmdIfOnAltField
ROM:E675
ROM:E675 AfterCmdCreated: ; CODE XREF: DODKWR+7 j
ROM:E675 ; DODKWR:loc_E667 j ...
ROM:E675 orcc #$40 ; '@'
ROM:E677 inc <DQ_WTO ; write timeout counter
ROM:E679 ldx #DQ_CMD ; output command buffer
ROM:E67C
ROM:E67C Send1CmdByte: ; CODE XREF: DODKWR+51 j
ROM:E67C sta W_RDED ; writing to this location lowers RDEN' (enables it)
ROM:E67F lda R_DATD ; reading from this location grabs the data from the VP-931 and disabled the RDEN' line (raises it)
ROM:E682 lda ,x+ ; load from buffer
ROM:E684 sta DSKLATCH ; the data stored in this latch will be sent to the LDP
ROM:E687 ldd #$FF
ROM:E68A sta WRDSK ; 5 cycles (WREN' low)
ROM:E68D stb WRDSK ; 5 cycles (WREN' low)
ROM:E690 ldb #$10 ; timeout value
ROM:E692
ROM:E692 WhileDakIsLow: ; CODE XREF: DODKWR+4A j
ROM:E692 lda R_BYT2_R_DAVD ; bit 7: DAV'
ROM:E692 ; bit 6: DAK
ROM:E692 ; bit 5: OPRT'
ROM:E692 ; bits 0-4 : unconnected
ROM:E695 anda #$40 ; '@' ; isolate DAK
ROM:E697 bne DakIsHigh ; have we sent the three command bytes?
ROM:E699 decb
ROM:E69A bgt WhileDakIsLow
ROM:E69C bra PostWriteTimeoutCounterClear ; we timed out, don't clear the write timeout counter,
ROM:E69C ; or send any more command bytes
ROM:E69E ; ---------------------------------------------------------------------------
ROM:E69E
ROM:E69E DakIsHigh: ; CODE XREF: DODKWR+47 j
ROM:E69E cmpx #DQ_MFD ; have we sent the three command bytes?
ROM:E6A1 bcs Send1CmdByte
ROM:E6A3 clr <DQ_WTO ; reset write timeout counter
ROM:E6A5
ROM:E6A5 PostWriteTimeoutCounterClear: ; CODE XREF: DODKWR+4C j
ROM:E6A5 sta W_RDED ; writing to this location lowers RDEN' (enables it)
ROM:E6A8 lda R_DATD ; reading from this location grabs the data from the VP-931 and disabled the RDEN' line (raises it)
ROM:E6AB sta W_FRQCLR ; writing here clears FIRQ, allows new FIRQ
ROM:E6AE andcc #$BF ; '+'
ROM:E6B0 lda <DQ_RTO ; read timeout counter
ROM:E6B2 oraa <DQ_WTO ; write timeout counter
ROM:E6B4 anda #$80 ; 'Ç'
ROM:E6B6 beq DontResetLDP ; branch if we don't have enough errors to reset the VP-931
ROM:E6B8 inc <DQ_LCK ; 0 = cannot lock to disc, 1 = can lock to disc
ROM:E6BA lda #0
ROM:E6BC sta DSKRST ; reset the LDP
ROM:E6BF clr <DQ_RTO ; read timeout counter
ROM:E6C1 clr <DQ_WTO ; write timeout counter
ROM:E6C3 bra PostResetDecision
ROM:E6C5 ; ---------------------------------------------------------------------------
ROM:E6C5
ROM:E6C5 DontResetLDP: ; CODE XREF: DODKWR+66 j
ROM:E6C5 lda #$FF
ROM:E6C7 sta DSKRST ; aka W.RSTD
ROM:E6C7 ; disk reset (active low) (at least 2 ms)
ROM:E6CA
ROM:E6CA PostResetDecision: ; CODE XREF: DODKWR+73 j
ROM:E6CA lda R_BYT2_R_DAVD ; bit 7: DAV'
ROM:E6CA ; bit 6: DAK
ROM:E6CA ; bit 5: OPRT'
ROM:E6CA ; bits 0-4 : unconnected
ROM:E6CD anda #$20 ; ' ' ; isolate OPRT'
ROM:E6CF beq loc_E6D3 ; branch if VP-931 is plugged in
ROM:E6D1 clr <DQ_LCK ; 0 = cannot lock to disc, 1 = can lock to disc
ROM:E6D3
ROM:E6D3 loc_E6D3: ; CODE XREF: DODKWR+7F j
ROM:E6D3 lda <DQ_LCK ; 0 = cannot lock to disc, 1 = can lock to disc
ROM:E6D5 bne locret_E6DC
ROM:E6D7 lda #$FF
ROM:E6D9 sta DSKLCK_W_LCKV ; 0: lock to disk, 1: self lock
ROM:E6DC
ROM:E6DC locret_E6DC: ; CODE XREF: DODKWR+85 j
ROM:E6DC rts
ROM:E6DC ; End of function DODKWR
ROM:E6DC
ROM:E6DD
ROM:E6DD ; =============== S U B R O U T I N E =======================================
ROM:E6DD
ROM:E6DD
ROM:E6DD CreateCmdIfOnFirstField: ; CODE XREF: DODKWR+1D P
ROM:E6DD
ROM:E6DD ; FUNCTION CHUNK AT ROM:E75B SIZE 00000002 BYTES
ROM:E6DD ; FUNCTION CHUNK AT ROM:E765 SIZE 0000000C BYTES
ROM:E6DD ; FUNCTION CHUNK AT ROM:E7B0 SIZE 0000001C BYTES
ROM:E6DD
ROM:E6DD ldd <DQ_MFD+1 ; manchester field in decimal as read
ROM:E6DF subd <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:E6DF ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E6E1 bne CanWeGenPause
ROM:E6E3 lda <DQ_MFD ; manchester field in decimal as read
ROM:E6E5 suba <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:E6E5 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E6E7 bne CanWeGenPause
ROM:E6E9 jmp GenPlayCmd
ROM:E6EC ; ---------------------------------------------------------------------------
ROM:E6EC
ROM:E6EC CanWeGenPause: ; CODE XREF: CreateCmdIfOnFirstField+4 j
ROM:E6EC ; CreateCmdIfOnFirstField+A j
ROM:E6EC lda <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:E6EC ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E6EE adda #1 ; add 1 to see what would happen if we jumped back 1 track (ie paused)
ROM:E6F0 daa
ROM:E6F1 eora <DQ_MFD+2 ; manchester field in decimal as read
ROM:E6F3 bne PauseWontWork
ROM:E6F5 lda <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:E6F5 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E6F7 adca #0
ROM:E6F9 daa
ROM:E6FA eora <DQ_MFD+1 ; manchester field in decimal as read
ROM:E6FC bne PauseWontWork
ROM:E6FE lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:E6FE ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E700 adca #0
ROM:E702 daa
ROM:E703 eora <DQ_MFD ; manchester field in decimal as read
ROM:E705 bne PauseWontWork
ROM:E707 jmp GenPauseCmd ; stay where we are (jump back 1 track to do a pause)
ROM:E70A ; ---------------------------------------------------------------------------
ROM:E70A
ROM:E70A PauseWontWork: ; CODE XREF: CreateCmdIfOnFirstField+16 j
ROM:E70A ; CreateCmdIfOnFirstField+1F j ...
ROM:E70A lda <DQ_FTO ; first field (F) timeout
ROM:E70C beq OnNoFieldTimeouts
ROM:E70E jmp ClearDiscLockThenGenPlay
ROM:E711 ; ---------------------------------------------------------------------------
ROM:E711
ROM:E711 OnNoFieldTimeouts: ; CODE XREF: CreateCmdIfOnFirstField+2F j
ROM:E711 jmp CreateSearchAndPlayCmdAdd1 ; Creates a SEARCH+PLAY command (prefix 0xF...)
ROM:E711 ; End of function CreateCmdIfOnFirstField ; to the game requested frame #,
ROM:E711 ; but adds one to the request
ROM:E711 ; (so if the request frame were 36128, it would do a jump to 36129)
ROM:E714 ; ---------------------------------------------------------------------------
ROM:E714 jmp GenSeekAndPlayCmd ; create SEEK+PLAY command that jumps to the frame we want to be on
ROM:E717
ROM:E717 ; =============== S U B R O U T I N E =======================================
ROM:E717
ROM:E717
ROM:E717 CreateCmdIfOnAltField: ; CODE XREF: DODKWR:OnAltField P
ROM:E717
ROM:E717 ; FUNCTION CHUNK AT ROM:E785 SIZE 0000000F BYTES
ROM:E717
ROM:E717 ldd <DQ_MFD+1 ; manchester field in decimal as read
ROM:E719 subd <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:E719 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E71B bne DesiredAndActualPicNumsMismatch
ROM:E71D lda <DQ_MFD ; manchester field in decimal as read
ROM:E71F suba <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:E71F ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E721 bne DesiredAndActualPicNumsMismatch
ROM:E723 jmp GenPauseCmd ; stay where we are (jump back 1 track to do a pause)
ROM:E726 ; ---------------------------------------------------------------------------
ROM:E726
ROM:E726 DesiredAndActualPicNumsMismatch: ; CODE XREF: CreateCmdIfOnAltField+4 j
ROM:E726 ; CreateCmdIfOnAltField+A j
ROM:E726 lda <DQ_MFD+2 ; manchester field in decimal as read
ROM:E728 adda #1 ; add 1 to see what would happen if we just let the disc play
ROM:E728 ; (the picture number will increment on the next field)
ROM:E72A daa
ROM:E72B eora <DQ_GMD+2 ; "Games Requested Frame #" converted to decimal
ROM:E72B ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E72D bne JustPlayingIsNotGoodEnough ; if we won't get to where we need to be by just letting the disc play
ROM:E72F lda <DQ_MFD+1 ; manchester field in decimal as read
ROM:E731 adca #0
ROM:E733 daa
ROM:E734 eora <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:E734 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E736 bne JustPlayingIsNotGoodEnough ; if we won't get to where we need to be by just letting the disc play
ROM:E738 lda <DQ_MFD ; manchester field in decimal as read
ROM:E73A adca #0
ROM:E73C daa
ROM:E73D eora <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:E73D ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E73F bne JustPlayingIsNotGoodEnough ; if we won't get to where we need to be by just letting the disc play
ROM:E741 jmp GenPlayCmd
ROM:E744 ; ---------------------------------------------------------------------------
ROM:E744
ROM:E744 JustPlayingIsNotGoodEnough: ; CODE XREF: CreateCmdIfOnAltField+16 j
ROM:E744 ; CreateCmdIfOnAltField+1F j ...
ROM:E744 lda <DQ_ATO ; if we won't get to where we need to be by just letting the disc play
ROM:E746 beq JmpGenSeekAndPlayCmd
ROM:E748 jmp ClearDiscLockThenGenPlay
ROM:E74B ; ---------------------------------------------------------------------------
ROM:E74B
ROM:E74B JmpGenSeekAndPlayCmd: ; CODE XREF: CreateCmdIfOnAltField+2F j
ROM:E74B jmp GenSeekAndPlayCmd ; create SEEK+PLAY command that jumps to the frame we want to be on
ROM:E74B ; End of function CreateCmdIfOnAltField
ROM:E74B
ROM:E74B ; ---------------------------------------------------------------------------
ROM:E74E fcb $7E ; ~
ROM:E74F fcb $E7 ; t
ROM:E750 fcb $94 ; ö
ROM:E751
ROM:E751 ; =============== S U B R O U T I N E =======================================
ROM:E751
ROM:E751
ROM:E751 sub_E751: ; CODE XREF: DODKWR+F P
ROM:E751
ROM:E751 ; FUNCTION CHUNK AT ROM:E771 SIZE 0000000A BYTES
ROM:E751
ROM:E751 ldb #$90 ; 'É'
ROM:E753 jmp loc_E771
ROM:E753 ; End of function sub_E751
ROM:E753
ROM:E756
ROM:E756 ; =============== S U B R O U T I N E =======================================
ROM:E756
ROM:E756
ROM:E756 sub_E756: ; CODE XREF: DODKWR:loc_E664 P
ROM:E756
ROM:E756 ; FUNCTION CHUNK AT ROM:E77B SIZE 0000000A BYTES
ROM:E756
ROM:E756 ldb #$90 ; 'É'
ROM:E758 jmp loc_E77B
ROM:E758 ; End of function sub_E756
ROM:E758
ROM:E75B ; ---------------------------------------------------------------------------
ROM:E75B ; START OF FUNCTION CHUNK FOR CreateCmdIfOnFirstField
ROM:E75B
ROM:E75B ClearDiscLockThenGenPlay: ; CODE XREF: CreateCmdIfOnFirstField+31 J
ROM:E75B ; CreateCmdIfOnAltField+31 J
ROM:E75B clr <DQ_LCK ; 0 = cannot lock to disc, 1 = can lock to disc
ROM:E75B ; END OF FUNCTION CHUNK FOR CreateCmdIfOnFirstField
ROM:E75D
ROM:E75D ; =============== S U B R O U T I N E =======================================
ROM:E75D
ROM:E75D
ROM:E75D GenPlayCmd: ; CODE XREF: DODKWR+4 P
ROM:E75D ; CreateCmdIfOnFirstField+C J ...
ROM:E75D ldd #0
ROM:E760 std <DQ_CMD+1 ; output command buffer
ROM:E762 sta <DQ_CMD ; output command buffer
ROM:E764 rts
ROM:E764 ; End of function GenPlayCmd
ROM:E764
ROM:E765 ; ---------------------------------------------------------------------------
ROM:E765 ; START OF FUNCTION CHUNK FOR CreateCmdIfOnFirstField
ROM:E765
ROM:E765 GenPauseCmd: ; CODE XREF: CreateCmdIfOnFirstField+2A J
ROM:E765 ; CreateCmdIfOnAltField+C J
ROM:E765 lda <DQ_LCK ; stay where we are (jump back 1 track to do a pause)
ROM:E767 ldd #$F001
ROM:E76A std <DQ_CMD+1 ; output command buffer
ROM:E76C lda #0
ROM:E76E sta <DQ_CMD ; output command buffer
ROM:E770 rts
ROM:E770 ; END OF FUNCTION CHUNK FOR CreateCmdIfOnFirstField
ROM:E771 ; ---------------------------------------------------------------------------
ROM:E771 ; START OF FUNCTION CHUNK FOR sub_E751
ROM:E771
ROM:E771 loc_E771: ; CODE XREF: sub_E751+2 J
ROM:E771 clr <DQ_LCK ; 0 = cannot lock to disc, 1 = can lock to disc
ROM:E773 stb <DQ_CMD+2 ; output command buffer
ROM:E775 ldd #$E0 ; 'a'
ROM:E778 std <DQ_CMD ; output command buffer
ROM:E77A rts
ROM:E77A ; END OF FUNCTION CHUNK FOR sub_E751
ROM:E77B ; ---------------------------------------------------------------------------
ROM:E77B ; START OF FUNCTION CHUNK FOR sub_E756
ROM:E77B
ROM:E77B loc_E77B: ; CODE XREF: sub_E756+2 J
ROM:E77B clr <DQ_LCK ; 0 = cannot lock to disc, 1 = can lock to disc
ROM:E77D stb <DQ_CMD+2 ; output command buffer
ROM:E77F ldd #$F0 ; '='
ROM:E782 std <DQ_CMD ; output command buffer
ROM:E784 rts
ROM:E784 ; END OF FUNCTION CHUNK FOR sub_E756
ROM:E785 ; ---------------------------------------------------------------------------
ROM:E785 ; START OF FUNCTION CHUNK FOR CreateCmdIfOnAltField
ROM:E785
ROM:E785 GenSeekAndPlayCmd: ; CODE XREF: ROM:E714 J
ROM:E785 ; CreateCmdIfOnAltField:JmpGenSeekAndPlayCmd J
ROM:E785 clr <DQ_LCK ; create SEEK+PLAY command that jumps to the frame we want to be on
ROM:E787 ldd <DQ_GMD+1 ; "Games Requested Frame #" converted to decimal
ROM:E787 ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E789 std <DQ_CMD+1 ; output command buffer
ROM:E78B lda <DQ_GMD ; "Games Requested Frame #" converted to decimal
ROM:E78B ; The high bit of the first byte will be 1 if the disc is supposed to just be playing forward at 1X. (see E650 and F373)
ROM:E78D anda #7
ROM:E78F oraa #$F0 ; '='
ROM:E791 sta <DQ_CMD ; output command buffer
ROM:E793 rts
ROM:E793 ; END OF FUNCTION CHUNK FOR CreateCmdIfOnAltField
ROM:E793 ; ---------------------------------------------------------------------------
This isn't completely disassembled, but I learned a lot of useful info by studying this.
DODKWR ($E650) will just send a play command if the highest bit of DQ_CMD is set.
Otherwise, if disc is on the 'first field' of a laserdisc frame, go to CreateCmdIfOnFirstField ($E6DD).
Otherwise, if disc is on the 'alternate field' of a laserdisc frame, so go to CreateCmdIfOnAltField ($E717).
After the command is created, it sends the command bytes to the VP931 ($E675).
The difference between what program does on the first field vs the alternate field is pretty interesting:
- If the requested target field that program needs to seek to is the same frame number that the disc is already on,
-- AND If disc is on the first field, then a play command will be sent for the current field ($E6E9).
-- Else the disc is on the alternate field, so a jump back 1 track command will be sent ($E765). This is a fancy way of just pausing the disc.
- If the requested target field that the program needs to seek to is different from the current frame number that the disc is on,
-- AND if the disc is on the first field, then the program will issue a jump command to the target frame plus 1 (CreateSearchAndPlayCmdAdd1, $E7B0) which is pretty interesting. More on this later.
-- Else the disc is on the alternate field, so the program will issue a jump command to the target frame ($E785).
Why does the Firefox program add 1 to the target frame if jumping from the first field of a frame?
Each frame is composed of two fields. So no matter what, the next field that will be displayed MUST be an alternate field. A jump to a frame number implicitly always targets the first field of a frame. Therefore, a jump that is initiated on the first field of a frame cannot complete until the field after the next field (which is an alternate field).
The VP931's behavior in this case is to land one field before the target field. So, for example, if I was on the first field of frame 1 and I requested a jump to frame 10, the VP931 would land me on the alternate field of frame 9 first, and then take me to the first field of frame 10 next. The Firefox program knows this, so it compensates by adding 1 to the desired target frame so that instead of landing 1 frame ahead of the target (and potentially show the wrong field of the wrong frame), we land in the middle of our target frame. Or, in our example, if we were on the first field of frame 1, and we wanted to land inside frame 10, we would issue a jump to frame 11 and the VP931 would land us inside of the alternate field of frame 10. It's kind of a quirky behavior that I didn't understand until I really dug into it. Now Dexter (with the latest firmware update as of today) will properly exhibit this behavior and Firefox's disc test passes with flying colors.
Subscribe to:
Posts (Atom)