Noob's investigation of VGM and DMF and SMD audio drivers

For everything that's not in any way related to PureBasic. General chat etc...
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Noob's investigation of VGM

Post by wilbert »

I added the GGStereoWrite procedure to set what channel where to play.
If you want to try, update also the code part that takes care of the windows waveout since it renders stereo samples now.
Windows (x64)
Raspberry Pi OS (Arm64)
SeregaZ
Enthusiast
Enthusiast
Posts: 617
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Noob's investigation of VGM

Post by SeregaZ »

2016-09-22 02:23:20 ValleyBell about PCM on the PSG - rarely anyone uses it
2016-09-22 02:23:59 ValleyBell and I don't think there is any game that combines music and PCM.
2016-09-22 02:24:19 ValleyBell i.e. you either get music on the PSG - *or* you get PCM voice samples
2016-09-22 02:25:11 ValleyBell (at least that's the case for Master System/Game Gear - MD games usually don't bother with PCM on the PSG at all due to the YM2612 DAC, but of course there is that one exception)
and i am not get that - you are already make support for second chip? i need + 256 for second chip?

Code: Select all

      Case $30 ; 0x50	dd	PSG (SN76489/SN76496) write value dd ;
        i + 1
        PSGvalue = PeekA(i)
        VGMARR(Arrayind)\type = 6
        VGMARR(Arrayind)\val = PSGvalue + 256
        Arrayind + 1
1 1111 1111
1 - chip bit
1111 - L side of 0, 1, 2, 3 channels
1111 - R side of 0, 1, 2, 3

same for write?

i make this + 256... bit it start sound some strange :)

i am go to eat something, then return and make this code with checkboxes for channels.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Noob's investigation of VGM

Post by wilbert »

SeregaZ wrote:and i am not get that - you are already make support for second chip? i need + 256 for second chip?
Yes, that should work for both GGStereoWrite and Write (hopefully) :wink:

But you also have to enable the second chip if you want to use it by setting a clock value with bit 30 set, like this ...

Code: Select all

Clock($40000000 | 3579545)
Windows (x64)
Raspberry Pi OS (Arm64)
SeregaZ
Enthusiast
Enthusiast
Posts: 617
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Noob's investigation of VGM

Post by SeregaZ »

dont understand how to make this second chip work...
https://www.dropbox.com/s/wtf69je6goi1e ... t.zip?dl=1 (i attach zlib - stole code from one topic at this forum :))


and i attach Rydeen.vgz - when you start song, it sound tone "tone tone tone", but original it is train "noise noise noise". when you wait until train sound will come - reopen that track, from this moment this starts "tone tone" is change into "noise" as they must be. i dont know where my mistake :) or not my? :))))

and stereo command not full for window part - i mean now when you load song - it turnon all by default. VGM can turn off some channel, but window will still have switchers on checkbox - i am not go into stereo function and not make change for changing state of checkboxes functional.
SeregaZ
Enthusiast
Enthusiast
Posts: 617
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Noob's investigation of VGM

Post by SeregaZ »

one my mistake is captured :)
Structure VGMFSt
type.i
reg.a
val.u...
it was val.a - but need val.u

now channels is shutdown fine, but second chip play some wrong anyway. it have some gaps. probably that clock i set incorrect...

Code: Select all

 
    ;Clock(3579545)
    Clock($40000000 | 3579545)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Noob's investigation of VGM

Post by wilbert »

SeregaZ wrote:and i attach Rydeen.vgz - when you start song, it sound tone "tone tone tone", but original it is train "noise noise noise". when you wait until train sound will come - reopen that track, from this moment this starts "tone tone" is change into "noise" as they must be. i dont know where my mistake :) or not my? :))))
I think it has to do with the initial state of the chip. It was very hard to spot the problem. It might be fixed now (updated version).
Windows (x64)
Raspberry Pi OS (Arm64)
SeregaZ
Enthusiast
Enthusiast
Posts: 617
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Noob's investigation of VGM

Post by SeregaZ »

about "spot" - maybe it is connected with noise channel, where 3 or 7 value means get frequency from 2 channel. but system think, if 2 channel have some value - it need to play. but volume at this moment must be 15 = silence for second channel.

did you fix my val.a into val.u and hear how it plays? i hear gaps, when shutdown all channels for 1 chip. 2 chip play with this gaps. how to i need set correct clock? probably i set it at wrong place...
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Noob's investigation of VGM

Post by wilbert »

SeregaZ wrote:did you fix my val.a into val.u and hear how it plays? i hear gaps, when shutdown all channels for 1 chip. 2 chip play with this gaps. how to i need set correct clock? probably i set it at wrong place...
I tried. I don't know what you think is wrong.
It sounds kind of okay to me :?
Windows (x64)
Raspberry Pi OS (Arm64)
SeregaZ
Enthusiast
Enthusiast
Posts: 617
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Noob's investigation of VGM

Post by SeregaZ »

did you shutdown first chip? unicode and thread safe?
Image
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Noob's investigation of VGM

Post by wilbert »

SeregaZ wrote:did you shutdown first chip? unicode and thread safe?
Image
Your picture doesn't show but yes, I did ran it in unicode and thread safe mode.
I posted a little modified version of my module but I don't think that will make the difference when it comes to what you are talking about.
Windows (x64)
Raspberry Pi OS (Arm64)
SeregaZ
Enthusiast
Enthusiast
Posts: 617
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Noob's investigation of VGM

Post by SeregaZ »

now plays fine :) no gaps. but... i can hear difference sound at 2 channel of 2 chip. winamp play is a little lower i think. more deeper sound. i am not sure - maybe all track have different high, but this 2 channel of 2 chip i can hear it more clear. maybe this formula is count wrong?

Code: Select all

                        Input clock (Hz) (3579545)
   Frequency (Hz) = ----------------------------------
                     2 x register value x divider (16)
one more - what do you think, if PSG_Init() command will have a few params?
PSG_Init(chip1freq.i, chip2freq.i=0)
when you set only one freq - system know, that he must play only 1 chip, if both params turn on - use both. or even that way:

PSG_Init(#PAL) or PSG_Init(#NTSC) or PSG_Init(#PAL, #PAL) or PSG_Init(#NTSC, #NTSC)
where:
#NTSC = 3579545
#PAL = 3546893

i set start play position, and turn on only that 2 channel for 2 chip. and you need change path to your file in: XIncludeFile "SN76489 module.pb" (in that file both your parts of code core and window part)

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) ;Write2?
      ;  ;Write(VGMARR(i)\val)
        
      Case 7 ; stereo flags
        GGStereoWrite(VGMARR(i)\val)
        
    EndSelect
    
    If TormozFlag      
      Break
    EndIf 
    
  Next
  
  ;silence when stop
  Write(%10011111)
  Write(%10111111)
  Write(%11011111)
  Write(%11111111)
  
  Write(%110011111)
  Write(%110111111)
  Write(%111011111)
  Write(%111111111)
  
EndProcedure

Procedure ParsePlay(*FileMem)
  
  memsize = MemorySize(*FileMem)  
  
  o.l = PeekL(*FileMem+$0C)
  
  Clock(o) ; set clock per track. idk will it make effect, or not...
  Debug "frequency is " + Str(o)

  ;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))

  If Val(ver$) < 151
    ot = *FileMem + 64      ; 64 - it is vgm header. no need it yet
  Else
    ot = *FileMem + 256
  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 = 7
        VGMARR(Arrayind)\val = PSGvalue + 256
        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 = 5
        VGMARR(Arrayind)\val = PSGvalue + 256
        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 + 256)
              
              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 + 256)
            
          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 
ops. it cant be constant. VGM have different values, not exactly NTSC of PAL values. probably it will need to set by VGM's, not by Init command.

for that train track it is 1077741824
SeregaZ
Enthusiast
Enthusiast
Posts: 617
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Noob's investigation of VGM

Post by SeregaZ »

1077741824 - $40000000 = 4 000 000 = that is problem. winamp cheating. he play 4 000 000 as 3 579 545. that is why winamp plays lower, than we have.

i have cursed this vgm.
2016-09-24 02:40:31 ValleyBell Super Locomotive is a completely different story from "normal" Dual-PSG VGMs
2016-09-24 02:41:00 ValleyBell It uses the VGM's extra header to emulate one PSG chip at 4 MHz and another one at 2 MHz.
SeregaZ
Enthusiast
Enthusiast
Posts: 617
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Noob's investigation of VGM

Post by SeregaZ »

i am not understand how to get that extra header value.
Image

and how change main header size. basic it is 256, but sience 1.70 version of VGM it can be variable becouse this extra header.
Header Size is the size of the extra header. It has to be 4 or larger, depending in the needed offsets.

Then there are two offsets that point to extra header data for:

additional Chip Clocks for second chips
user-defined chip volumes
Chip Clock Header

1 byte - Entry Count (chips with extra clocks) [5 bytes - List Entry 1] [5 bytes - List Entry 2] ...

Each list entry has the format: 1 byte - Chip ID (chip order follows the header) 4 bytes - clock for second chip of the type above


Chip Volume Header

1 byte - Entry Count (chips with user-defined volumes) [4 bytes - List Entry 1] [4 bytes - List Entry 2] ...

Each list entry has the format: 1 byte - Chip ID (chip order follows the header)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Noob's investigation of VGM

Post by wilbert »

I had to rewrite a lot to implement the ability to set a different frequency for both chips.
Hopefully everything still works. :shock:

I'll look into the VGM file format.
Last edited by wilbert on Wed May 31, 2017 2:58 pm, edited 1 time in total.
Windows (x64)
Raspberry Pi OS (Arm64)
Joris
Addict
Addict
Posts: 885
Joined: Fri Oct 16, 2009 10:12 am
Location: BE

Re: Noob's investigation of VGM

Post by Joris »

Excuse me but ...

If I got it right, this is all about controlling Texas and Yamaha sound-chips ?
How do you send PB-code to these ?
Wherein are they placed ?
Is that VGM format limited to these two (older) chips ?

Thanks.
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
Post Reply