If you make a working version you can test it and compare it with the result from this app which is working.
DiscId calculator
http://webplaza.pt.lu/public/vigatol/discidcalc/
Here's a screenshot:


Code: Select all
#Win_Main = 0
#Button_0 = 0
#ListIcon_0 = 1
#Text_0 = 2
#Track = 22
#TrackStart = 36
#TrackLength = 40
Structure toc
min.l
sec.l
frame.l
EndStructure
Dim cdtoc.toc(100)
Dim trackNum$(99)
Procedure.l read_cdtoc_from_drive(files2read$)
trackCount.l = 0
trackNum.l = 0
; --> count tracks
While files2read$
trackNum$(trackCount) = files2read$
files2read$ = NextSelectedFileName()
trackCount + 1
Wend
; --> Sort the file names in ascending order
SortArray(trackNum$(), 0)
; --> Our file names are at the end of our array
; --> with null filenames being first after sorting
; --> do the math to get the first .cda file (Track01.cda)
For track = 100 - trackCount To 99
; --> Open file for reading
ReadFile(0, trackNum$(track))
; --> Seek to track byte
FileSeek(#Track)
track$ = RSet(Str(ReadByte()&$FF), 2, "0")
; --> Seek to track start info
FileSeek(#TrackStart)
; --> Add leading zeros to track start info
trackBeginFrame$ = RSet(Str(ReadByte()&$FF), 2, "0")
trackBeginSeconds$ = RSet(Str(ReadByte()&$FF), 2, "0")
trackBeginMinutes$ = RSet(Str(ReadByte()&$FF), 2, "0")
; --> Seek to track length info
FileSeek(#TrackLength)
; --> Add leading zeros to track length info
trackLengthFrame$ = RSet(Str(ReadByte()&$FF), 2, "0")
trackLengthSeconds$ = RSet(Str(ReadByte()&$FF), 2, "0")
trackLengthMinutes$ = RSet(Str(ReadByte()&$FF), 2, "0")
; --> Close file
CloseFile(0)
; --> Do math to get track end info
trackEndMinutes = Val(trackBeginMinutes$) + Val(trackLengthMinutes$)
If trackEndMinutes >= 60
trackEndMinutes - 60
EndIf
; --> 60 seconds = 1 minute so make adjustments as needed
trackEndSeconds = Val(trackBeginSeconds$) + Val(trackLengthSeconds$)
If trackEndSeconds >= 60
trackEndSeconds - 60
trackEndMinutes + 1
EndIf
; --> 75 frames = 1 second so make adjustments as needed
trackEndFrames = Val(trackBeginFrame$) + Val(trackLengthFrame$)
If trackEndFrames >= 75
trackEndFrames - 75
trackEndSeconds + 1
EndIf
; --> Fill track end info with 0's
trackEndFrames$ = RSet(Str(trackEndFrames), 2, "0")
trackEndSeconds$ = RSet(Str(trackEndSeconds), 2, "0")
trackEndMinutes$ = RSet(Str(trackEndMinutes), 2, "0")
; --> Fill in the cdtoc for returning DiscID
cdtoc(trackNum)\min = Val(trackBeginMinutes$)
cdtoc(trackNum)\sec = Val(trackBeginSeconds$)
cdtoc(trackNum)\frame = Val(trackBeginFrame$)
trackNum + 1
; --> Add info to ListIconGadget
AddGadgetItem(#ListIcon_0, -1, track$ + Chr(10) + trackBeginMinutes$ + ":" + trackBeginSeconds$ + "." + trackBeginFrame$ + Chr(10) + trackLengthMinutes$ + ":" + trackLengthSeconds$ + "." + trackLengthFrame$ + Chr(10) + trackEndMinutes$ + ":" + trackEndSeconds$ + "." + trackEndFrames$)
files2read$ = NextSelectedFileName()
Next track
; --> This is the lead out
cdtoc(trackNum)\min = Val(trackEndMinutes$)
cdtoc(trackNum)\sec = Val(trackEndSeconds$)
cdtoc(trackNum)\frame = Val(trackEndFrames$)
ProcedureReturn trackCount
EndProcedure
Procedure.l cddb_sum(n)
ret.l = 0
While n > 0
ret = ret + (n % 10)
n = n / 10
Wend
ProcedureReturn ret
EndProcedure
Procedure.s cddb_discid(tot_trks)
t.l = 0
n.l = 0
i.l = 0
While i < tot_trks
n + cddb_sum((cdtoc(i)\min * 60) + cdtoc(i)\sec)
i+1
Wend
t = ((cdtoc(tot_trks)\min * 60) + cdtoc(tot_trks)\sec) - ((cdtoc(0)\min * 60) + cdtoc(0)\sec)
Debug t
ProcedureReturn Hex(n % $FF << 24 | t << 8 | tot_trks)
EndProcedure
ofPattern$ = "Audio (*.cda)|*.cda"
; ***********************************
; --> Change path to your cdrom drive
cdromDrive$ - "F:\"
; ***********************************
If OpenWindow( #Win_Main, 10, 10, 370, 400, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Read .CDA") And CreateGadgetList(WindowID(#Win_Main))
ButtonGadget(#Button_0, 5, 5, 100, 20, "Select CDA Files")
TextGadget(#Text_0, 130, 10, 200, 20, "DiscID: ")
HideGadget(#Text_0, 1)
ListIconGadget(#ListIcon_0, 5, 35, 360, 360, "Track", 50, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
AddGadgetColumn(#ListIcon_0, 1, "Start", 100)
AddGadgetColumn(#ListIcon_0, 2, "Duration", 100)
AddGadgetColumn(#ListIcon_0, 3, "End", 100)
Repeat
event = WaitWindowEvent()
Select event
Case #PB_EventGadget
Select EventGadgetID()
Case #Button_0
SetGadgetText(#Text_0, "")
HideGadget(#Text_0, 1)
cdaFiles$ = OpenFileRequester("Select .CDA files to read", cdromDrive$, ofPattern$, 0, #PB_Requester_MultiSelection)
If cdaFiles$ <> ""
serial$ = ""
tot_trks = read_cdtoc_from_drive(cdaFiles$)
SetGadgetText(#Text_0, "DiscID: " + cddb_discid(tot_trks))
HideGadget(#Text_0, 0)
EndIf
EndSelect
EndSelect
Until event = #PB_Event_CloseWindow
EndIf
EndCode: Select all
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ASPI32\Parameters]
"ExcludeMiniports"=""
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ASPI32]
"ErrorControl"=dword:00000001
"Start"=dword:00000002
"Type"=dword:00000001
I'm planning on cleaning and optimizing the code this week. I also plan to add the ASPI version as well. Once it's done and working flawlessly, feel free to send it to freedb.org.GeoTrail wrote:Maybe you could change the code abit so it will autodetect the cd drive and automatically add all audio files if there are any?
This may shorten your work:Sparkie wrote:@GeoTrail - This will probably take me more than a few days to complete.
Code: Select all
Structure TOCTRACK
Reserved.b
CTL.b ; indicates the attributes of the track
ADR.b ; type of information encoded in the QSub-channel of the block
trackNumber.b ; Track Number, 1 based. $AA ~ start of lead-out
Reserved2.b
addr.b[4] ; adress of first block or LBA of track start
EndStructure
Structure TOC
TOCLength.w ; size of TOC
firstTrack.b ; first track number
lastTrack.b ; last track before lead-out
tracks.TOCTRACK[100] ; infos on each track
EndStructure
;
; ReadTOC()
;
Procedure.l ReadTOC(adapter.b, target.b, lun.b, *toc.TOC)
srbExec.SRB_ExecSCSICmd
hEventSRB.l = CreateEvent_(#NULL, #TRUE, #FALSE, #NULL)
ZeroMemory_(@srbExec, SizeOf(SRB_ExecSCSICmd))
srbExec\SRB_Cmd = #SC_EXEC_SCSI_CMD
srbExec\SRB_HaId = adapter
srbExec\SRB_Target = target
srbExec\SRB_Lun = lun
srbExec\SRB_Flags = #SRB_DIR_IN | #SRB_EVENT_NOTIFY
srbExec\SRB_BufLen = $324
srbExec\SRB_BufPointer = *toc
srbExec\SRB_SenseLen = $0E
srbExec\SRB_CDBLen = $0A
srbExec\SRB_PostProc = hEventSRB
srbExec\CDBByte[0] = $43
srbExec\CDBByte[7] = $03
srbExec\CDBByte[8] = $24
ResetEvent_(hEventSRB)
status = CallCFunctionFast(*SendASPI32Command, @srbExec)
If status = #SS_PENDING
WaitForSingleObject_(hEventSRB, 4000)
EndIf
CloseHandle_(hEventSRB)
If srbExec\SRB_Status <> #SS_COMP
; handle error here
ProcedureReturn #SS_ERR
EndIf
ProcedureReturn #SS_COMP
EndProcedure