antoine-source/scsi2/AppleSCSI2.s
Antoine Vignau d29484938c Our SCSI-2 Audio Driver
What we wrote to make audio hearable on a SCSI-2 CD-ROM drive ;-)
2023-03-08 10:15:14 +01:00

1952 lines
52 KiB
ArmAsm

*
* Apple SCSI-2
*
* (c) 2018, Brutal Deluxe Software
* Antoine Vignau & Olivier Zardini
* Visit http://www.brutaldeluxe.fr/
*
xc
xc
mx %00
rel
typ DRV
dsk AppleSCSI2.l
lst off
*----------------------------
DECBUSYFLG EQU $E10068
GSOS EQU $E100A8
use 4/Int.Macs
use 4/Media.Macs
use 4/Mem.Macs
use 4/Util.Macs
mcInChapters = 1
mcInFrames = 2
mcInTime = 3
mcSDeviceType = 0
mcSPlayStatus = 1
mcSDoorStatus = 2
mcSDiscType = 3
mcSDiscSize = 4
mcSDiscSide = 5
mcSVolumeL = 6
mcSVolumeR = 7
mcSUnknown = 0
mcSLaserDisc = 1
mcSCDAudio = 2
mcSLaserCD = 3
mcSVCR = 4
mcSCamCorder = 5
mcSPlaying = 1
mcSStill = 2
mcSParked = 3
mcSDoorOpen = 1
mcSDoorclosed = 2
mcS_CLV = 1
mcS_CAV = 2
mcS_CDV = 3
mcS_CD = 4
mcSDisc3inch = 3
mcSDisc5inch = 5
mcSDisc8inch = 8
mcSDisc12inch = 12
mcSSideOne = 1
mcSSideTwo = 2
mcCInit = 1 ; init
mcCEject = 2 ; eject
mcCDisplayOn = 5 ; turn video position display on
mcCDisplayOff = 6 ; turn video position display off
mcCLockDev = 9 ; lock
mcCUnLockDev = 10 ; unlock
AudioOff = 0 ;
AudioRight = 1 ;
AudioLinR = 2 ;
AudioMinR = 3
AudioRinL = 4 ;
AudioRinLR = 5 ;
AudioReverse = 6 ;
AudioRinLMR = 7
AudioLeft = 8 ;
AudioStereo = 9 ;
AudioLinLR = 10
AudioLinLMR = 11
AudioMinL = 12
AudioMinLRinR = 13
AudioMinLLinR = 14
AudioMonaural = 15
mcUnImp = $2601
mcBadAudio = $2606
mcBadSelector = $2609
mcInvalidPort = $260b
mcInvalidParam = $2612
*----------------------------
dw $0000
dw $001B
jmp EntryStuff
dw $0100
str 'AppleSCSI2'
L0013 ADRL MCGetName
ADRL MCDStartUp
ADRL MCDShutDown
ADRL MCGetFeatures
ADRL MCPlay
ADRL MCPause
ADRL MCSendRawData
ADRL MCGetStatus
ADRL MCControl
ADRL MCScan
ADRL MCGetSpeeds
ADRL MCSpeed
ADRL MCStopAt
ADRL MCJogN
ADRL MCSearchTo
ADRL MCSearchDone
ADRL MCSearchWait
ADRL MCGetPosition
ADRL MCSetAudio
ADRL MCGetTimes
ADRL MCGetDiscTOC
ADRL MCGetDiscID
ADRL MCGetNoTracks
ADRL MCRecord
ADRL MCStop
ADRL MCWaitRawData
ADRL MCSetVolume
*----------------------------
EntryStuff PHD
PHB
PHK
PLB
TSC
SEC
SBC #$000A
TCS
INC
TCD
JMP (L0013,X)
exit20 TAX
LDA $0A,S
PHA
PLB
PLB
LDA $0C,S
TCD
LDA $12,S
STA $26,S
LDA $10,S
STA $24,S
LDA $0E,S
STA $22,S
TSC
CLC
ADC #$0014
TCS
BRL Exit0x
Exit16 TAX
LDA $0A,S
PHA
PLB
PLB
LDA $0C,S
TCD
LDA $12,S
STA $22,S
LDA $10,S
STA $20,S
LDA $0E,S
STA $1E,S
TSC
CLC
ADC #$0010
TCS
BRL Exit0x
Exit14 TAX
LDA $0A,S
PHA
PLB
PLB
LDA $0C,S
TCD
LDA $12,S
STA $20,S
LDA $10,S
STA $1E,S
LDA $0E,S
STA $1C,S
TSC
CLC
ADC #$000E
TCS
BRL Exit0x
Exit12 TAX
LDA $0A,S
PHA
PLB
PLB
LDA $0C,S
TCD
LDA $12,S
STA $1E,S
LDA $10,S
STA $1C,S
LDA $0E,S
STA $1A,S
TSC
CLC
ADC #$000C
TCS
BRL Exit0x
Exit10 TAX
LDA $0A,S
PHA
PLB
PLB
LDA $0C,S
TCD
LDA $12,S
STA $1C,S
LDA $10,S
STA $1A,S
LDA $0E,S
STA $18,S
PLA
PLA
PLA
PLA
PLA
BRL Exit0x
Exit8 TAX
LDA $0A,S
PHA
PLB
PLB
LDA $0C,S
TCD
LDA $12,S
STA $1A,S
LDA $10,S
STA $18,S
LDA $0E,S
STA $16,S
PLA
PLA
PLA
PLA
BRL Exit0x
Exit6 TAX
LDA $0A,S
PHA
PLB
PLB
LDA $0C,S
TCD
LDA $12,S
STA $18,S
LDA $10,S
STA $16,S
LDA $0E,S
STA $14,S
PLA
PLA
PLA
BRL Exit0x
Exit4 TAX
LDA $0A,S
PHA
PLB
PLB
LDA $0C,S
TCD
LDA $12,S
STA $16,S
LDA $10,S
STA $14,S
LDA $0E,S
STA $12,S
PLA
PLA
BRA Exit0x
Exit2 TAX
LDA $0A,S
PHA
PLB
PLB
LDA $0C,S
TCD
LDA $12,S
STA $14,S
LDA $10,S
STA $12,S
LDA $0E,S
STA $10,S
PLA
BRA Exit0x
Exit0 TAX
LDA $0A,S
PHA
PLB
PLB
LDA $0C,S
TCD
Exit0x TSC
CLC
ADC #$000D
TCS
TXA
PHA
JSL DECBUSYFLG
PLA
CMP #$0001
RTL
*----------------------------
MCGetName
PEA ^DriverNamStr
PEA DriverNamStr
LDA $1A,S
PHA
LDA $1A,S
PHA
LDA #$0000
PHA
LDA DriverNamStr
AND #$00FF
INC
PHA
_BlockMove
LDA #$0000
JMP Exit6
DriverNamStr STR 'MCToolkit AppleSCSI2 1.0'
ConnectPort DS $24
DriverNLen DW ConnectPort-DriverNamStr-1 ; $0017
*----------------------------
MCDStartUp
LDA BeenOpen
BEQ L0210
BRL L02A6
L0210 LDA $14,S
STA L02B7
LDA #$0000
STA L02C1
STA L0311
LDA $18,S
PHA
LDA $18,S
PHA
PEA ^ConnectPort
PEA ConnectPort
PEA $0000
PEA $0024
_BlockMove
LDA ConnectPort
AND #$00FF
SEC
ADC DriverNLen
SEP #$30
STA DriverNamStr
REP #$30
LDA ConnectPort
AND #$FF00
ORA #$0020
STA ConnectPort
LDA $18,S
PHA
LDA $18,S
PHA
PEA ^L02D8
PEA L02D8
PEA $0000
PEA $0024
_BlockMove
LDA L02D7+1
AND #$00FF
STA L02D7
BEQ L0294
LDA L02D7+2
AND #$007F
CMP #$002E
BNE L0294
JSL GSOS
DW $2020 ; GetDevNumber
ADRL L02FD
BCS L0297
LDA L0303
BRA L029A
L0294 LDA #mcInvalidPort
L0297 JMP L02A9
L029A STA MyDevID
INC BeenOpen
LDA L02C1
STA L0315
L02A6 LDA #$0000
L02A9 JMP Exit8
*----------------------------
MCDShutDown
lda #0
sta BeenOpen
jmp Exit2
*--- New data
BeenOpen DW $0000
L02B7 DW $0000
MyDevID DW $0000
DW $0000
DW $0000
DW $0008
L02C1 DW $0000
ADRL L02D5
DW $0000
ADRL $00000000
DW $0000
DW $0000
DW $0000
DW $0000
L02D5 DW $0024
L02D7 DS $01
L02D8 DS $25
L02FD DW $0002 ; Parms for GetDevNumber
ADRL L02D7 ; device name
L0303 DW $0000 ; device num
DW $0003
DW $0000
ADRL L02D7
DW $0003
DW $0001
L0311 DW $0000
DW $0005
L0315 DW $0000
DW $0004
ADRL L0325
ADRL $00000002
ADRL $00000000
L0325 DW $8000
DW $0004
DW $0000
ADRL L0337
ADRL $00000001
ADRL $00000000
L0337 DW $0000
*----------------------------
HEX2BCD
phx
pha
and #$f0
lsr
lsr
lsr
tax
lda HD,x
sta HSave
pla
and #$0f
asl
tax
sed
lda HU,x
clc
adc HSave
cld
plx
rts
*--- New data
HD dw $0000
dw $0016
dw $0032
dw $0048
dw $0064
dw $0080
dw $0090
HU dw $0000
dw $0001
dw $0002
dw $0003
dw $0004
dw $0005
dw $0006
dw $0007
dw $0008
dw $0009
dw $0010
dw $0011
dw $0012
dw $0013
dw $0014
dw $0015
HSave ds 2
*----------------------------
BCD2HEX
phx
pha
and #$0f
sta BSave
pla
and #$f0
lsr
lsr
lsr
tax
lda BD,x
clc
adc BSave
plx
rts
*--- New data
BD dw 00
dw 10
dw 20
dw 30
dw 40
dw 50
dw 60
dw 70
dw 80
dw 90
BSave ds 2
*----------------------------
getCURRENTSTATUS
lda MyDevID
sta SubDNum
jsl GSOS
dw $202D ; DStatus
adrl SubBlk
bcc getCS1
sta errCODE
rts
getCS1
*---
lda SubData+6 ; get current track
and #$ff
sta trackCURRENT
lda SubData+1 ; return Audio status
and #$ff
rts
*--- New data
errCODE ds 2 ; GS/OS error code
SubBlk DW $0005 ; Parms for DStatus
SubDNum DW $0000 ; device num
DW $8042 ; status code
ADRL SubList ; status list
ADRL 16 ; request count
ADRL $00000000 ; transfer count
SubList DW $0000
DB $42
DB $02 ; MSF
DB $40 ; SubQ
DB $01 ; CD-ROM current position data format
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
ADRL SubData
SubData ds 16
*----------------------------
getTOC
sta TOCType ; 00-40-80
stx TOCTrack ; 00-63
lda MyDevID
sta TOCDNum
jsl GSOS
dw $202D ; DStatus
adrl ReadTOCBlk
bcc getTOC1
rts
getTOC1
*--- The TOC is read now
sep #$20 ; $00: first and last tracks
lda TOCData+2
sta trackFIRST
lda TOCData+3
sta trackLAST
rep #$20
*---
lda TOCType ; $40: lead-out (end of disk)
cmp #$40
beq getTOC2
clc
rts
getTOC2 lda TOCData+3
and #$ff
asl
asl
asl ; *8
clc
adc #8 ; 4 for header & 4 to reach hours
tay
lda TOCData,y ; hour / minute
sta TOCData
lda TOCData+2,y ; second / frame
sta TOCData+2
clc
rts
*--- Old data
TOCType ds 2
*--- New data
ReadTOCBlk DW $0005 ; Parms for DStatus
TOCDNum DW $0000 ; device num
DW $8043 ; status code
ADRL TOCList ; status list
ADRL 1024 ; request count
ADRL $00000000 ; transfer count
TOCList DW $0000
DB $43
DB $02 ; in MSF
DB $00
DB $00
DB $00
TOCTrack DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
ADRL TOCData
TOCData ds 1024
*----------------------------
doSTARTSTOP
lda MyDevID
sta StopDNum
jsr getCURRENTSTATUS
bcc doSTOP1
rts
doSTOP1 ldx #0 ; stop
cmp #$11 ; Audio play in progress
beq doSTOP2
cmp #$13 ; Audio play stopped
bne doSTOP3
inx ; start
doSTOP2 stx StopFlag
jsl GSOS
dw $202E ; DControl
adrl StopBk
rts
doSTOP3 lda #0 ; exit w/no error
rts
*--- New data
StopBk DW $0005 ; Parms for DControl
StopDNum DW $0000 ; device num
DW $801b ; control code
ADRL StopList ; control list
ADRL $00000000 ; request count
ADRL $00000000 ; transfer count
StopList DW $0000
DB $1b
DB $00
DB $00
DB $00
StopFlag DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
ds 4
*----------------------------
doPAUSE
lda MyDevID
sta PauseDNum
jsr getCURRENTSTATUS
bcc doPAUSE1
rts
doPAUSE1 ldx #0 ; pause
cmp #$11 ; Audio play in progress
beq doPAUSE2
cmp #$12 ; Audio play paused
bne doPAUSE3
inx ; resume
*--- Alternate entry
doPAUSE2 stx PauseFlag
jsl GSOS
dw $202E ; DControl
adrl PauseBk
doPAUSE3 rts
*--- New data
PauseBk DW $0005 ; Parms for DControl
PauseDNum DW $0000 ; device num
DW $804b ; control code
ADRL PauseList ; control list
ADRL $00000000 ; request count
ADRL $00000000 ; transfer count
PauseList DW $0000
DB $4b
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
PauseFlag DB $00
DB $00
DB $00
DB $00
ds 4
*----------------------------
MCGetFeatures
lda #0 ; init result
sta $18,s
sta $1a,s
lda $14,s ; check if 0-9
cmp #10
bcc MCGF1
lda #mcBadSelector ; bad parameter if not
bra MCGF9
MCGF1 tax ; return handling of
lda tblFEATURES,x
and #$ff ; requested feature
sta $18,s
lda #$0000
sta $1a,s
MCGF9 jmp Exit4
*--- Data
tblFEATURES dfb $05 ; MCFTypes - Times and Chapters
dfb $00
dfb $00
dfb $00
dfb $01 ; MCFEject - yes
dfb $01 ; MCFLock - yes
dfb $01 ; MCFVDisplay - yes
dfb $00
dfb $00
dfb $01 ; MCFVolume - yes
*----------------------------
MCPlay
lda MyDevID
sta PlayDNum ; for PLAY AUDIO
lda trackTOGO ; we must jog!
bne MCPlay2
lda fgRUNFROM ; 1
ora fgRUNTO ; 2
cmp #3 ; must be 3 to accept the Run button
beq MCPlay2 ; so, do as usual
jsr getCURRENTSTATUS
bcs MCPlay9
*- If in pause, we resume and exit
cmp #$12 ; Audio play paused
bne MCPlay1
ldx #1 ; call resume
jsr doPAUSE2
bra MCPlay9 ; we exit
MCPlay1 cmp #$11 ; Audio play in progress
beq MCPlay8 ; we exit w/o error
*- If we're not already playing
MCPlay2 lda #0 ; get full TOC
tax
jsr getTOC
bcs MCPlay9
lda trackTOGO ; we must jog!
bne MCPlay4
lda fgRUNFROM ; play MSF?
ora fgRUNTO
cmp #3
bne MCPlay3 ; no
jsr MCPlayMSF
bcc MCPlay8
bcs MCPlay9
MCPlay3 lda trackFIRST ; get first and last tracks
MCPlay4 sta PlayFirst ; or trackTOGO and last tracks
lda trackLAST
sta PlayLast
stz trackTOGO ; reset track to go
jsl GSOS
dw $202E ; DControl
adrl PlayBk
bcs MCPlay9
MCPlay8 lda #0
MCPlay9 jmp Exit2
*--- Play Audio MSF because Run was pressed
MCPlayMSF
lda MyDevID
sta PlayMSFDNum ; for PLAY AUDIO MSF
stz fgRUNFROM
stz fgRUNTO
lda runFROM+1 ; MM:SS
sta fromMSF
lda runFROM+2 ; SS:FF
sta fromMSF+1
lda runTO+1 ; MM:SS
sta toMSF
lda runTO+2 ; SS:FF
sta toMSF+1
jsl GSOS
dw $202E ; DControl
adrl PlayMSFBk
rts
*--- Track data
trackFIRST ds 2 ; first track of a disk
trackLAST ds 2 ; last track of a disk
trackCURRENT ds 2 ; track the beam is on
trackTOGO ds 2 ; track to jog to
*--- New data
PlayBk DW $0005 ; Parms for DControl
PlayDNum DW $0000 ; device num
DW $8048 ; control code
ADRL PlayList ; control list
ADRL $00000000 ; request count
ADRL $00000000 ; transfer count
PlayList DW $0000
DB $48
DB $00
DB $00
DB $00
PlayFirst DB $00
DB $00
DB $00
PlayLast DB $00
DB $00
DB $00
DB $00
DB $00
ds 4
*--- Play Audio MSF block
PlayMSFBk DW $0005 ; Parms for DControl
PlayMSFDNum DW $0000 ; device num
DW $8047 ; control code
ADRL PlayMSFList ; control list
ADRL $00000000 ; request count
ADRL $00000000 ; transfer count
PlayMSFList DW $0000
DB $47
DB $00
DB $00
fromMSF DB $00 ; MM
DB $00 ; SS
DB $00 ; FF
toMSF DB $00 ; MM
DB $00 ; SS
DB $00 ; FF
DB $00
DB $00
DB $00
ds 4
*----------------------------
MCPause
jsr doPAUSE
lda #0
jmp Exit2
*----------------------------
MCSendRawData
lda #mcUnImp
jmp Exit6
*----------------------------
MCGetStatus
lda #0 ; init result
sta $18,s
lda $14,s ; which device?
cmp #mcSDeviceType
bne MCGS1
*--- device type
ldx #mcSCDAudio
bra MCGS18
*--- play status
MCGS1 cmp #mcSPlayStatus
bne MCGS2
jsr getCURRENTSTATUS
bcc MCGS11
ldx #mcSParked
lda errCODE
cmp #$002f ; device is offline
beq MCGS18
cmp #$0027 ; I/O error
beq MCGS18
bra MCGS19 ; other errors, exit
MCGS11 ldx #mcSPlaying
cmp #$11 ; audio play operation in progress
beq MCGS18
ldx #mcSStill
cmp #$12 ; paused
beq MCGS18
cmp #$13 ; stopped
beq MCGS18
cmp #$14 ; stopped due to error
beq MCGS18
*--- generic return
MCGS17 ldx #mcSUnknown
MCGS18 txa
sta $18,s
lda #$0000
MCGS19 jmp Exit4
*--- door status
MCGS2 cmp #mcSDoorStatus
beq MCGS17 ; we don't know
*--- disc type
MCGS3 cmp #mcSDiscType
bne MCGS4
jsr getCURRENTSTATUS
bcs MCGS19
ldx #mcS_CD
bra MCGS18
*--- disc size
MCGS4 cmp #mcSDiscSize
bne MCGS5
jsr getCURRENTSTATUS
bcs MCGS19
ldx #mcSDisc5inch
bra MCGS18
*--- disc side
MCGS5 cmp #mcSDiscSide
bne MCGS6
jsr getCURRENTSTATUS
bcs MCGS19
ldx #mcSSideOne
bra MCGS18
*--- left volume
MCGS6 cmp #mcSVolumeL
bne MCGS7
jsr doSENSE ; mode sense
bcs MCGS9
lda SenseData+9,y ; left volume
bra MCGS79
*--- right volume
MCGS7 cmp #mcSVolumeR
bne MCGS8
jsr doSENSE ; mode sense
bcs MCGS9
lda SenseData+11,y ; right volume
MCGS79 and #$ff ; save volume
xba ; 00FF becomes FF00
sta $18,s
lda #$0000 ; exit OK
bra MCGS9
*--- We exit
MCGS8 lda #mcBadSelector
MCGS9 jmp Exit4
*----------------------------
doSENSE
lda MyDevID
sta SenseDNum
jsl GSOS
dw $202D ; DStatus
adrl SenseBlk
pha
lda SenseData+3 ; get block descriptor length
and #$ff
clc
adc #4 ; add param header length
tay ; make it our offset
pla
rts
*--- New data
SenseBlk DW $0005 ; Parms for DStatus
SenseDNum DW $0000 ; device num
DW $801a ; status code
ADRL SenseList ; status list
ADRL 128 ; request count
ADRL $00000000 ; transfer count
SenseList DW $0000
DB $1a
DB $00
DB $0e ; current values / page E
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
ADRL SenseData
SenseData ds 128 ; mode parameter header
; page E is usually at offset 4+8
*----------------------------
SENSE2SELECT
ldx #0 ; copy the page
]lp lda SenseData,y
sta Select0E,x
iny
iny
inx
inx
cpx #16
bcc ]lp
rts
*----------------------------
doSELECT
lda MyDevID
sta SelectDNum
jsl GSOS
dw $202E ; DControl
adrl SelectBlk
rts
*--- New data
SelectBlk DW $0005 ; Parms for DControl
SelectDNum DW $0000 ; device num
DW $8015 ; status code
ADRL SelectList ; status list
ADRL 20 ; request count
ADRL $00000000 ; transfer count
SelectList DW $0000
DB $15
DB $10 ; page in SCSI-2
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
ADRL SelectData
* Must start with 4 zeroes
* Then, we have the CD-ROM parameters page
* output port 0 at +8, volume at +9
* output port 1 at +10, volume at +11
SelectData hex 00,00,00,00
Select0E hex 0e,0e,04,00,00,00,00,00
hex 01,ff,02,ff,00,00,00,00
*----------------------------
MCControl
lda MyDevID
sta EjectDNum
sta PreventDNum
lda $14,s ; over 10, we don't handle
cmp #mcCUnLockDev+1
bcc MCC1
lda #mcUnImp
jmp Exit4
*--- Init?
MCC1 cmp #mcCInit
bne MCC2
stz trackTOGO
stz fgRUNFROM
stz fgRUNTO
bra MCC98
*--- Eject?
MCC2 cmp #mcCEject
bne MCC9
jsr doUNLOCK
jsl GSOS
dw $202E ; DControl
adrl EjectBk
bra MCC99
*--- Lock device?
MCC9 cmp #mcCLockDev
bne MCC10
jsr doLOCK
bra MCC99
*--- Unlock device?
MCC10 cmp #mcCUnLockDev
bne MCC5
jsr doUNLOCK
bra MCC99
*--- Video position display on/off?
MCC5 cmp #mcCDisplayOn
beq MCC98
cmp #mcCDisplayOff
beq MCC98
lda #mcBadSelector
bra MCC99
*--- Lock/Unlock
doLOCK lda #1
bne doPREVENT
doUNLOCK lda #0
doPREVENT sta fgLOCK
jsl GSOS
dw $202E ; DControl
adrl PreventBk
rts
*--- We exit
MCC98 lda #0
MCC99 jmp Exit4
*--- New data for Eject
EjectBk DW $0005 ; Parms for DControl
EjectDNum DW $0000 ; device num
DW $0002 ; control code
ADRL $00000000 ; control list
ADRL $00000000 ; request count
ADRL $00000000 ; transfer count
*--- New data for PREVENT/ALLOW REMOVAL
PreventBk DW $0005 ; Parms for DControl
PreventDNum DW $0000 ; device num
DW $801e ; control code
ADRL PreventList ; control list
ADRL $00000000 ; request count
ADRL $00000000 ; transfer count
PreventList DW $0000
DB $1e
DB $00
DB $00
DB $00
fgLOCK DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
DB $00
ds 4
*----------------------------
MCScan
lda #$40 ; get lead-out
ldx #0
jsr getTOC
bcc MCS1
jmp Exit4
*--- Get disc range
MCS1
lda TOCData+8 ; get disk start
xba
sta scanBEGIN+2
lda TOCData+10
xba
sta scanBEGIN
lda TOCData ; get disk end
xba
sta scanEND+2
lda TOCData+2
xba
sta scanEND
*--- And the status
jsr getCURRENTSTATUS ; get status
lda SubData+8 ; get current position
xba
sta scanCURRENT+2
lda SubData+10
xba
sta scanCURRENT
*--- Now move the beast
lda $14,s ; 0: forward, <0: rewind
bpl MCSFF
jsr doREWIND ; scan backwards
bcc MCS7
bcs MCS8
MCSFF jsr doFORWARD ; scan forward
bcs MCS8 ; cannot move, exit
MCS7
lda scanCURRENT+2 ; MM HH
xba
sta runFROM ; HH MM
lda scanCURRENT ; FF SS
xba
sta runFROM+2 ; SS FF
jsr correctEND ; remove one frame
lda scanEND+2 ; MM HH
xba
sta runTO ; HH MM
lda scanEND ; FF SS
xba
sta runTO+2 ; SS FF
jsr MCPlayMSF ; move the beam and play
bra MCS9
MCS8 lda #0
MCS9 jmp Exit4
*--- Scan forward (add 10 seconds)
doFORWARD
sep #$20
lda scanCURRENT+1 ; add 10 seconds
clc
adc #10
sta scanCURRENT+1
cmp #60 ; above 59 seconds?
bcc doFORWARD5
sec
sbc #60
sta scanCURRENT+1
inc scanCURRENT+2 ; add 1 minute
lda scanCURRENT+2
cmp #100 ; above 99 minutes?
bcc doFORWARD5
lda #99
sta scanCURRENT+2
inc scanCURRENT+3 ; add 1 hour
lda scanCURRENT+3
cmp #100 ; above 99 hours?
bcc doFORWARD5
lda #99 ; force 99 hours
sta scanCURRENT+3
doFORWARD5 ; Are we above disc end?
rep #$20
lda scanCURRENT+2 ; hhmm
cmp scanEND+2
bcc doFORWARD9
lda scanCURRENT ; ssff
cmp scanEND
bcc doFORWARD9
sec ; force error
doFORWARD9 rts
*--- Scan backwards (subtract 10 seconds)
doREWIND
sep #$20
lda scanCURRENT+1 ; subtract 10 seconds
sec
sbc #10
sta scanCURRENT+1
bpl doREWIND5
clc
adc #60 ; above 60 seconds
sta scanCURRENT+1
dec scanCURRENT+2 ; subtract 1 minute
bpl doREWIND5
lda #99 ; 99 minutes
sta scanCURRENT+2
dec scanCURRENT+3 ; subtract 1 hour
bpl doREWIND5
lda #99 ; 99 hours
sta scanCURRENT+3
*--- Are we above the disc start?
doREWIND5
rep #$20
lda scanCURRENT+2
cmp #$6363 ; 9999
beq doREWIND7
lda scanBEGIN+2 ; MM HH
cmp scanCURRENT+2
bcc doREWIND9 ; <, exit
lda scanBEGIN ; FF SS
cmp scanCURRENT
bcc doREWIND9 ; <, exit
doREWIND7 sec
doREWIND9 rts
*--- Correct the end of the disc
correctEND
sep #$20
dec scanEND ; remove a frame
bpl correctEND9
lda #74 ; last frame
sta scanEND
dec scanEND+1 ; SS--
bpl correctEND9
lda #59 ; last second
sta scanEND+1
dec scanEND+2 ; MM--
bpl correctEND9
lda #99 ; last minute
sta scanEND+2
dec scanEND+3 ; HH--
bpl correctEND9
lda #99 ; last hour
sta scanEND+3
correctEND9 rep #$20
rts
*--- New data
scanBEGIN ds 4
scanCURRENT ds 4
scanEND ds 4
*----------------------------
MCGetSpeeds
lda #mcUnImp
jmp Exit6
*----------------------------
MCSpeed
lda #mcUnImp
jmp Exit4
*----------------------------
MCStopAt
stz fgRUNTO
*- Track
lda $18,s ; track?
cmp #mcInChapters
bne MCSA1
lda $14,s
sta runTO
bra MCSA8
*- Time
MCSA1 cmp #mcInTime ; or time?
beq MCSA2
lda #mcUnImp ; it is frames, error
bra MCSA9
*- Convert from BCD time
MCSA2
lda $17,s ; get hours
jsr BCD2HEX
sta runTO
lda $16,s ; get minutes
jsr BCD2HEX
sta runTO+1
lda $15,s ; get seconds
jsr BCD2HEX
sta runTO+2
lda $14,s ; get frames
jsr BCD2HEX
sta runTO+3
*--- We exit
MCSA8 lda #2 ; good init
sta fgRUNTO
lda #0 ; exit OK
MCSA9 jmp Exit8
*----------------------------
MCJogN
lda $14,s ; mcJogRepeat must exit
sta dataJOGR ; times to repeat
bne MCJ1
lda #mcInvalidParam
jmp Exit10
*--- Which UnitType?
MCJ1 lda $1a,s ; we support track
cmp #mcInChapters
beq MCJ2
lda #mcUnImp
jmp Exit10
*--- Jog in tracks
MCJ2 lda $16,s
sta dataNJOG ; number of units to jog
stz trackTOGO ; init destination track
jsr getCURRENTSTATUS
bcc MCJ3
jmp Exit10
MCJ3 lda #0
tax
jsr getTOC
bcc MCJ4
jmp Exit10
*--- Now jog
MCJ4 lda dataJOGR ; move + or -
bmi MCJ4BACK
lda trackCURRENT
clc
adc dataNJOG
sta trackTOGO ; where we must go
cmp trackLAST ; are we over
bcc MCJ4END ; the last track?
lda trackLAST
sta trackTOGO ; yes, limit to last track
MCJ4END bra MCJ8
*--- Move backwards
MCJ4BACK lda trackCURRENT
sec
sbc dataNJOG
sta trackTOGO ; where we must go
bmi MCJ5 ; are we < 0
cmp trackFIRST ; or < first track
bcs MCJ8
MCJ5 lda trackFIRST
sta trackTOGO ; yes, limit to first track
*--- We exit
MCJ8 lda #$0000
MCJ9 jmp Exit10
*--- Data
dataJOGR ds 2
dataNJOG ds 2
*----------------------------
MCSearchTo
stz fgRUNFROM
*- Track
lda $18,s ; track?
cmp #mcInChapters
bne MCST1
lda $14,s
sta runFROM
bra MCST8
*- Time
MCST1 cmp #mcInTime ; time?
beq MCST2
lda #mcUnImp ; it is frames, error
bra MCST9
*- Convert from BCD time
MCST2
lda $17,s ; get hours
jsr BCD2HEX
sta runFROM
lda $16,s ; get minutes
jsr BCD2HEX
sta runFROM+1
lda $15,s ; get seconds
jsr BCD2HEX
sta runFROM+2
lda $14,s ; get frames
jsr BCD2HEX
sta runFROM+3
*--- We exit
MCST8 lda #1 ; good init
sta fgRUNFROM
lda #$0000 ; exit OK
MCST9 jmp Exit8
*--- Data
runFROM ds 5 ; HH MM SS FF 00
runTO ds 5 ; HH MM SS FF 00
fgRUNFROM ds 2 ; we did MCSearchTo (0 or 1)
fgRUNTO ds 2 ; we did MCSearchAt (0 or 2)
; we'll run A-B if above result is 3
*----------------------------
MCSearchDone
lda #1
sta $16,s
lda #0
jmp Exit2
*----------------------------
MCSearchWait
lda #0
jmp Exit2
*----------------------------
MCGetPosition
lda #0
sta $18,s
sta $1a,s
lda $14,s ; which mcUnitType?
cmp #mcInFrames
bne MCGP2
MCGP1 lda #mcUnImp ; video frames not implemented
bne MCGP9
MCGP2 jsr getCURRENTSTATUS ; get current status
bcs MCGP9
lda $14,s
cmp #mcInChapters
bne MCGP3
lda trackCURRENT ; return current track
sta $18,s
bra MCGP8
MCGP3 cmp #mcInTime ; if not time, exit with error
bne MCGP1
lda SubData+11 ; frame
jsr HEX2BCD
sta currentPOS
lda SubData+10 ; seconds
jsr HEX2BCD
sta currentPOS+1
lda SubData+9 ; minutes
jsr HEX2BCD
sta currentPOS+2
lda SubData+8 ; hours
jsr HEX2BCD
sta currentPOS+3
lda currentPOS
sta $18,s
lda currentPOS+2
sta $1a,s
MCGP8 lda #0
MCGP9 jmp Exit4
*---
currentPOS ds 5 ; makes a BCD of the HEX position
*----------------------------
MCSetAudio
lda $14,s ; check value
cmp #AudioMonaural+1
bcc MCSAU1
lda #mcBadAudio ; not within 0-15
bra MCSAU9
MCSAU1 jsr doSENSE ; get audio values
bcs MCSAU9
jsr SENSE2SELECT
*--- Now, do the work
lda $14,s
asl
tax
sep #$20
lda tblAUDIO+1,x ; copy value for left
sta Select0E+8
lda tblAUDIO,x ; copy value for right
sta Select0E+10
rep #$20
jsr doSELECT ; send the audio values
MCSAU9 jmp Exit4
*--- New data
* High byte for left value
* Low byte for right value
tblAUDIO dw $0000 ; 0
dw $0002 ; 1
dw $0001 ; 2
dw $0003 ; 3
dw $0200 ; 4
dw $0202 ; 5
dw $0201 ; 6
dw $0203 ; 7
dw $0100 ; 8
dw $0102 ; 9
dw $0101 ; 10
dw $0103 ; 11
dw $0300 ; 12
dw $0302 ; 13
dw $0301 ; 14
dw $0303 ; 15
*----------------------------
MCGetTimes
lda #mcUnImp
jmp Exit4
*----------------------------
MCGetNoTracks
lda #0
sta $16,s ; clear result
lda #0 ; TOCType = 0
tax ; Track = 0
jsr getTOC
bcs MCGNT9
sep #$20 ; last - first + 1
lda TOCData+3
sec
sbc TOCData+2
clc
adc #1
rep #$20
and #$00ff
sta $16,s
lda #0
MCGNT9 jmp Exit2
*----------------------------
MCGetDiscTOC
lda #0 ; clear result
sta $18,s ; if track = 0
sta $1a,s
lda $14,s ; which track?
tax
bne MCGDT1
lda #mcInvalidParam
bne MCGDT9
MCGDT1 lda #0 ; TOCType = 0
jsr getTOC
bcs MCGNT9
lda #0 ; space
pha
pha
lda TOCData+8 ; HH:MM
xba
pha
lda TOCData+10 ; SS:FF
xba
pha
_MCBinToTime
pla
plx
sta $18,s
txa
sta $1a,s
lda #0
MCGDT9 jmp Exit4
*----------------------------
MCGetDiscID
LDA #mcUnImp
jmp Exit2
*----------------------------
MCRecord
lda #mcUnImp
jmp Exit2
*----------------------------
MCStop
jsr doSTARTSTOP
bcs MCStop9
lda #0
MCStop9 jmp Exit2
*----------------------------
MCWaitRawData
lda $18,s
sta $00
lda $1A,s
sta $02
lda #0
ldy #2
sta [$00],y
lda #mcUnImp
jmp Exit8
*----------------------------
MCSetVolume
*--- First, get values (because output might be different)
jsr doSENSE
bcs MCSV9
jsr SENSE2SELECT
*--- Then, copy volume
sep #$20
lda $15,s ; get right volume (high-byte only)
sta Select0E+11
lda $17,s ; get left volume (high-byte only)
sta Select0E+9
rep #$20
jsr doSELECT ; A=0 or not
MCSV9 jmp Exit6