it is play, no error - but gaps return. and second chip now plays that was must be play first. probably that is why gaps happen - they eat each other.
set that big value from normal header, then check extraheader if this extra header have some value for 0 chip - get that value and set as for second:
about extra - i make some ugly way for get that value... ugly as always i am do
Code: Select all
;{
ProgName.s=GetFilePart(ProgramFilename())
a = CreateSemaphore_(#Null,0,1,@ProgName)
If a<>0 And GetLastError_()=#ERROR_ALREADY_EXISTS
CloseHandle_(a)
End
EndIf
;}
Enumeration
#Window
#PathString
#OpenButton
#File
#Text
#Fr01
#Fr02
#Ch1R
#Ch2R
#Ch3R
#Ch4R
#Ch1L
#Ch2L
#Ch3L
#Ch4L
#Ch1R2
#Ch2R2
#Ch3R2
#Ch4R2
#Ch1L2
#Ch2L2
#Ch3L2
#Ch4L2
#Play
#Stop
#From
EndEnumeration
XIncludeFile "SN76489 module.pb"
Structure VGMFSt
type.i
reg.a
val.u
pause.u
samplenum.a
sampleadress.i
samplesize.i
summofpauses.i
EndStructure
Global Dim VGMARR.VGMFSt(0)
Global TormozFlag = 1
Global PlThr
;{
Macro SetBit(Var, Bit)
Var | (Bit)
EndMacro
Macro ClearBit(Var, Bit)
Var & (~(Bit))
EndMacro
Macro TestBit(Var, Bit)
Bool(Var & (Bit))
EndMacro
Macro NumToBit(Num)
(1<<(Num))
EndMacro
Macro GetBits(Var, StartPos, EndPos)
((Var>>(StartPos))&(NumToBit((EndPos)-(StartPos)+1)-1))
EndMacro
;}
Procedure Play(*Value)
PlayedTicks.i = 0
PlayedUS.i = 0
CurrentUS.i = 0
StartMS.i = ElapsedMilliseconds()
start = Val(GetGadgetText(#From))
For i = start To ArraySize(VGMARR())-1
Select VGMARR(i)\type
Case 3 ; pauses
PlayedTicks + VGMARR(i)\pause
PlayedUS = PlayedTicks * 22.675736961;90.702947844;22.675736961
While (CurrentUS < PlayedUS)
Delay(1)
CurrentUS.i = (ElapsedMilliseconds() - StartMS) * 1000
Wend
Case 5 ; PSG
Write(VGMARR(i)\val)
Case 6 ; PSG
Write(VGMARR(i)\val, 1)
Case 7 ; stereo flags
GGStereoWrite(VGMARR(i)\val)
Case 8 ; stereo flags
GGStereoWrite(VGMARR(i)\val, 1)
EndSelect
If TormozFlag
Break
EndIf
Next
;silence when stop
Write(%10011111)
Write(%10111111)
Write(%11011111)
Write(%11111111)
Write(%10011111, 1)
Write(%10111111, 1)
Write(%11011111, 1)
Write(%11111111, 1)
EndProcedure
Procedure ParsePlay(*FileMem)
memsize = MemorySize(*FileMem)
;get version of vgm. ugly code? :)))
ver$ = ""
tmp = PeekA(*FileMem + 11)
ver$ = Str(GetBits(tmp, 4, 7))
ver$ + Str(GetBits(tmp, 0, 3))
tmp = PeekA(*FileMem + 10)
ver$ + Str(GetBits(tmp, 4, 7))
ver$ + Str(GetBits(tmp, 0, 3))
tmp = PeekA(*FileMem + 9)
ver$ + Str(GetBits(tmp, 4, 7))
ver$ + Str(GetBits(tmp, 0, 3))
tmp = PeekA(*FileMem + 8)
ver$ + Str(GetBits(tmp, 4, 7))
ver$ + Str(GetBits(tmp, 0, 3))
o.l = PeekL(*FileMem+$0C)
Clock(o) ; set clock per track. idk will it make effect, or not...
;Debug "frequency is " + Str(o)
If Val(ver$) < 151
ot = *FileMem + 64 ; 64 - it is vgm header. no need it yet
Else
If Val(ver$) < 171
ot = *FileMem + 192 ; 192 header from 1.51 to 1.70
Else
ot = *FileMem + 256 ; 256 header from 1.71
EndIf
;+extrahead
If PeekL(*FileMem+$BC) = 4
ot + PeekL(*FileMem+$C0) ; extra head data size
;check frequency values
If o > $40000000 ; it means dual and need to check extra
shift = PeekL(*FileMem+$C4) ; offset of "Chip Clock" sub header
If shift
chipcount = PeekB(*FileMem+$C4+shift) ; to know how many 5 bytes blocks have
If chipcount
readfrom = *FileMem+$C4+shift + 1
For i = 1 To chipcount
If PeekB(readfrom) = 0 ; 0 - it is id of SN
extrafrequency = PeekL(readfrom + 1)
Debug extrafrequency ; f..king!!!!!!!1111oneoneone
If extrafrequency
Clock($40000000 + extrafrequency, 1)
EndIf
Break
EndIf
readfrom + 5
Next
EndIf
EndIf
EndIf
EndIf
EndIf
do = *FileMem + memsize
; create array with size as filesize. array will get less size, than file, but it is ok
Dim VGMARR(memsize)
Number.a = 0
PSGvalue.a
Arrayind = 0
For i = ot To do
Number = PeekA(i)
Select Number
Case $67 ; 0x67 0x66 tt ss ss ss ss (data)
; it is big wav data block
; get size of wav data block
WavDataSize = PeekI(i + 3)
; get adress of wav data block
WavAddres = i + 7
; jump to end of wav data block
i + 6 + WavDataSize
Case $52 ; $52 - register +0
i+2
Case $53 ; $53 - register +256
i+2
Case $61 ; $61 - can range from 0 to 65535 (approx 1.49 seconds)
VGMARR(Arrayind)\type = 3
VGMARR(Arrayind)\pause = PeekU(i + 1)
If flagpausehunt
VGMARR(numforsizecount)\summofpauses + VGMARR(Arrayind)\pause
flagpausehunt = 0
EndIf
Arrayind + 1
i+2
Case $70 To $7F ; wait n+1 samples, n can range from 0 to 15.
VGMARR(Arrayind)\type = 3
VGMARR(Arrayind)\pause = ((Number - $70) + 1)
If flagpausehunt
VGMARR(numforsizecount)\summofpauses + VGMARR(Arrayind)\pause
flagpausehunt = 0
EndIf
Arrayind + 1
Case $E0 ; 0xE0 dddddddd seek to offset dddddddd (Intel byte order) in PCM data bank
;jump far
i + 4
Case $80 To $8F
flagpausehunt = 1
If Number > $80
VGMARR(Arrayind)\type = 3
VGMARR(Arrayind)\pause = (Number - $80)
VGMARR(numforsizecount)\summofpauses + VGMARR(Arrayind)\pause
Arrayind + 1
EndIf
Case $4F ; 0x4F dd Game Gear PSG stereo, write dd to port 0x06 ; dune with samples
i + 1
PSGvalue = PeekA(i)
VGMARR(Arrayind)\type = 7
VGMARR(Arrayind)\val = PSGvalue
Arrayind + 1
Case $3F ; 0x4F dd Game Gear PSG stereo, write dd to port 0x06 ; dune with samples
i + 1
PSGvalue = PeekA(i)
VGMARR(Arrayind)\type = 8
VGMARR(Arrayind)\val = PSGvalue
Arrayind + 1
;MAIN COMMAND :))
Case $50 ; 0x50 dd PSG (SN76489/SN76496) write value dd ; dune with samples
i + 1
PSGvalue = PeekA(i)
VGMARR(Arrayind)\type = 5
VGMARR(Arrayind)\val = PSGvalue
Arrayind + 1
Case $30 ; 0x50 dd PSG (SN76489/SN76496) write value dd ; dune with samples
i + 1
PSGvalue = PeekA(i)
VGMARR(Arrayind)\type = 6
VGMARR(Arrayind)\val = PSGvalue
Arrayind + 1
Case $62 ; wait 735 samples (60th of a second), a shortcut for 0x61 0xdf 0x02 ; Lego Tune
VGMARR(Arrayind)\type = 3
VGMARR(Arrayind)\pause = 735
If flagpausehunt
VGMARR(numforsizecount)\summofpauses + VGMARR(Arrayind)\pause
flagpausehunt = 0
EndIf
Arrayind + 1
Case $63 ; wait 882 samples (50th of a second), a shortcut For 0x61 0x72 0x03
VGMARR(Arrayind)\type = 3
VGMARR(Arrayind)\pause = 882
If flagpausehunt
VGMARR(numforsizecount)\summofpauses + VGMARR(Arrayind)\pause
flagpausehunt = 0
EndIf
Arrayind + 1
Case $66 ; end of sound
Debug "end"
Break
Default
;Debug "unknown command " + Hex(Number)
EndSelect
If TormozFlag
Break
EndIf
Next
If TormozFlag = 0
Play(0)
EndIf
EndProcedure
#ENABLE_GZIP = 16
; #ZLIB_VERSION = "1.2.8"
#Z_NULL = 0
#Z_OK = 0
#Z_STREAM_END = 1
#Z_FINISH = 4
#Z_BLOCK = 5
Structure Z_STREAM
*next_in.Byte
avail_in.l
total_in.l
*next_out.Byte
avail_out.l
total_out.l
*msg.Byte
*state
zalloc.l
zfree.l
opaque.l
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
PB_Alignment1.b[4]
CompilerEndIf
data_type.i
adler.l
reserved.l
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
PB_Alignment2.b[8]
CompilerEndIf
EndStructure
ImportC "zlib.lib"
zlibVersion()
inflateInit2_(*strm, windowBits.i, Version.s, strm_size)
inflate(*strm, flush.i)
inflateEnd(*strm)
deflateInit2_(*strm, level.i, method.i, windowBits.i, memlevel.i, strategy.i, Version.s, strm_size)
deflateBound(*strm, sourceLen.l)
deflate(*strm, flush.i)
deflateEnd(*strm)
EndImport : Global ZLIB_VERSION$ = PeekS(zlibVersion(), -1, #PB_Ascii)
Procedure InflatePayload(*TmpMem, windowBits.i, size.i)
Debug "запустилось"
LengthToRead = MemorySize(*TmpMem)
LengthToWrite = size;FileSize("1test.dds")
*MemoryID = AllocateMemory(LengthToWrite)
strm.Z_STREAM
strm\next_in = *TmpMem
strm\avail_in = LengthToRead
strm\next_out = *MemoryID
strm\avail_out = LengthToWrite
strm\zalloc = #Z_NULL
strm\zfree = #Z_NULL
strm\opaque = #Z_NULL
inflateInit2_(@strm, windowBits, ZLIB_VERSION$, SizeOf(Z_STREAM))
inflate(@strm, #Z_FINISH)
inflateEnd(@strm)
ProcedureReturn *MemoryID
EndProcedure
If OpenWindow(#Window, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
StringGadget(#PathString, 10, 20, 120, 20, "", #PB_String_ReadOnly)
ButtonGadget(#OpenButton, 130, 20, 50, 20, "open")
TextGadget(#Text, 10, 40, 170, 90, "WARNING! see what chips was used by this VGM. it plays only one SN76489. YM2612 is ignored. any VGM with other chips can crash programm.")
StringGadget(#From, 10, 120, 65, 20, "550")
GadgetToolTip(#From, "starts from...")
ButtonGadget(#Play, 80, 120, 50, 20, "play")
ButtonGadget(#Stop, 135, 120, 50, 20, "stop")
FrameGadget(#Fr01, 1, 158, 93, 97, "1 chip")
FrameGadget(#Fr02, 95, 158, 93, 97, "2 chip")
CheckBoxGadget(#Ch1L, 5, 170, 70, 20, "L 1Ch R")
CheckBoxGadget(#Ch2L, 5, 190, 70, 20, "L 2Ch R")
CheckBoxGadget(#Ch3L, 5, 210, 70, 20, "L 3Ch R")
CheckBoxGadget(#Ch4L, 5, 230, 70, 20, "L 4Ch R")
CheckBoxGadget(#Ch1R, 75, 170, 16, 20, "")
CheckBoxGadget(#Ch2R, 75, 190, 16, 20, "")
CheckBoxGadget(#Ch3R, 75, 210, 16, 20, "")
CheckBoxGadget(#Ch4R, 75, 230, 16, 20, "")
CheckBoxGadget(#Ch1L2, 100, 170, 70, 20, "L 1Ch R")
CheckBoxGadget(#Ch2L2, 100, 190, 70, 20, "L 2Ch R")
CheckBoxGadget(#Ch3L2, 100, 210, 70, 20, "L 3Ch R")
CheckBoxGadget(#Ch4L2, 100, 230, 70, 20, "L 4Ch R")
CheckBoxGadget(#Ch1R2, 170, 170, 16, 20, "")
CheckBoxGadget(#Ch2R2, 170, 190, 16, 20, "")
CheckBoxGadget(#Ch3R2, 170, 210, 16, 20, "")
CheckBoxGadget(#Ch4R2, 170, 230, 16, 20, "")
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
Select EventGadget()
;- Event
Case #OpenButton
If File$
StandardFile$ = GetPathPart(File$)
Else
StandardFile$ = "C:\" ;GetPathPart(ProgramFilename()); ; initial path + file
EndIf
Pattern$ = "VGM files (*.vgm)|*.vgm;*.vgz;";*.vgz|" ; set first pattern (index = 0)
Pattern = 0 ; use the second of the five possible patterns as standard
; Now we open a filerequester, you can change the pattern and will get the index after closing
File$ = OpenFileRequester("Please choose file to load", StandardFile$, Pattern$, Pattern)
If File$
;For i = #Ch1R To #Ch4L2
; SetGadgetState(i, 1)
;Next
;GGStereoWrite(255)
;GGStereoWrite(255 + 256)
SetGadgetState(#Ch2R2, 1)
SetGadgetState(#Ch2L2, 1)
GGStereoWrite(0)
GGStereoWrite(34, 1)
TormozFlag = 1
If IsThread(PlThr)
WaitThread(PlThr)
EndIf
SetGadgetText(#PathString, File$)
If ReadFile(#File, File$)
If *MemoryID
FreeMemory(*MemoryID)
*MemoryID = 0
EndIf
length = Lof(#File)
If ReadByte(#File) = $56 And ReadByte(#File) = $67 And ReadByte(#File) = $6D
;unpacked VGM
Debug "unpacked"
*MemoryID = AllocateMemory(length) ; allocate the needed memory
If *MemoryID
FileSeek(#File, 0)
ReadData(#File, *MemoryID, length) ; read all data into the memory block
EndIf
Else
Debug "packed"
;get size unpacked
FileSeek(#File, length - 4)
unpsz = ReadLong(#File)
If *TmpMem
FreeMemory(*TmpMem)
*TmpMem = 0
EndIf
*TmpMem = AllocateMemory(length) ; allocate the needed memory
If *TmpMem
FileSeek(#File, 0)
ReadData(#File, *TmpMem, length) ; read all data into the memory block
*MemoryID = InflatePayload(*TmpMem, #ENABLE_GZIP, unpsz) ;unpack
EndIf
EndIf
CloseFile(#File)
TormozFlag = 0
If *MemoryID
PlThr = CreateThread(@ParsePlay(), *MemoryID)
Else
MessageRequester("error", "cant read file")
EndIf
EndIf
EndIf
Case #Ch1R To #Ch4L
forstereo = 0
For i = #Ch1R To #Ch4L
value = GetGadgetState(i)
If value
SetBit(forstereo, NumToBit(i-#Ch1R))
Else
ClearBit(forstereo, NumToBit(i-#Ch1R))
EndIf
Next
GGStereoWrite(forstereo)
Case #Ch1R2 To #Ch4L2
forstereo = 0
For i = #Ch1R2 To #Ch4L2
value = GetGadgetState(i)
If value
SetBit(forstereo, NumToBit(i-#Ch1R2))
Else
ClearBit(forstereo, NumToBit(i-#Ch1R2))
EndIf
Next
GGStereoWrite(forstereo, 1)
Case #Play
If *MemoryID
TormozFlag = 1
If IsThread(PlThr)
WaitThread(PlThr)
EndIf
TormozFlag = 0
PlThr = CreateThread(@Play(), *MemoryID)
EndIf
Case #Stop
TormozFlag = 1
EndSelect
Case #PB_Event_CloseWindow
Quit = 1
EndSelect
Until Quit = 1
EndIf
End
he is not like when i sets 2 000 000 value.
)))) now 1 in 1 sounds as winamp do... for this cases... who knows where ValleyBell set grand piano in a bush...