Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - vgmcheck: extract loop and time information from VGMs

Reply to topic
Author Message
  • Joined: 31 Oct 2009
  • Posts: 5
Reply with quote
vgmcheck: extract loop and time information from VGMs
Post Posted: Mon Nov 02, 2009 2:23 am
Last edited by libertyernie on Thu Nov 05, 2009 9:48 pm; edited 1 time in total
UPDATE: version 2.0, which is very very small and coded in C. Go to post 6 for download.

(Information below preserved for posterity)

A while back, I wrote a little Linux script to help me get the loop point information from a VGM, so I could convert it to WAV and then to a special format for insertion into Super Smash Bros. Brawl (by way of hacking.) I then realized this would be useful for people working with VGMs in other ways as well, so I expanded it a bit. It now gives the total time, loop start, and loop time of a VGM, all in samples as well as minutes/seconds/hundredths of a second.
It also runs on Windows, thanks to Cygwin. The needed Cygwin apps are bundled in the zip archive. Per the GPL, I should tell you that if you want the source code to the Cygwin apps the Cygwin mirrors will have them under "release."

To use it, drag and drop a VGM/VGZ onto the .bat file (Windows) or run the .sh file from the terminal with the VGM/VGZ as an argument (Linux).

Download (Windows/Linux)
The script and everything else in the .zip file is open source, under varying licenses (see the file LICENSE for details.)

Example output (this is the Master System version of Green Hill Zone):
--Raw VGM information--
Total samples: 2329215
Total time in mm:ss: 0:52.81
Loop start: 635775
Loop start in mm:ss: 0:14.41
Loop time: 1693440
Loop time in mm:ss: 0:38.40

--For Brawl BRSTM conversion--
Loop start divisible by 14336: 645120
Loop end will then be: 2338560


Project2612 thread
  View user's profile Send private message
  • Site Admin
  • Joined: 08 Jul 2001
  • Posts: 8653
  • Location: Paris, France
Reply with quote
Post Posted: Mon Nov 02, 2009 3:37 am
( Attaching a local copy of the file )
vgmcheck-1.2.zip (1.71 MB)

  View user's profile Send private message Visit poster's website
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14745
  • Location: London
Reply with quote
Post Posted: Mon Nov 02, 2009 8:17 am
Is this analysing a logged VGM to tell you the loop points, or just lifting the data from the VGM header?

If the former, you can lift the loop and total lengths from a VGM file with this *nix one-liner:

gzip -cd "<file>" | od -l | tr '\n' ' ' | sed -e 's/  */ /g' | cut -d ' ' -f 9,12


...and presumably manipulate them from there. A C program to do the same thing would be very simple.

Edit: here's that C program. Needs zlib.

Quote
#include <zlib.h>
#include <stdio.h>

char* printtime(char* buf, int length)
{
   int mins, secs, hundredths;
   mins = length / (44100 * 60);
   length %= (44100 * 60);
   secs = length / 44100;
   length %= 44100;
   hundredths = (int)((double)length / 44100 * 100 + 0.5);
   sprintf(buf, "%d:%02d.%02d", mins, secs, hundredths);
   return buf;
}

int readInt(gzFile file)
{
   // read 4 bytes little-endian
   int b1 = gzgetc(file);
   int b2 = gzgetc(file);
   int b3 = gzgetc(file);
   int b4 = gzgetc(file);
   return b1 | b2 << 8 | b3 << 16 | b4 << 24;
}

int main(int argc, char** argv)
{
   gzFile file;
   int length;
   int looplength;
   int loopstart;
   char buffer[32];

   if (argc != 2)
   {
      printf("Usage: %s <filename>\n", argv[0]);
      return 1;
   }

   file = gzopen(argv[1], "rb");
   if (!file)
   {
      printf("Failed to open \"%s\"", argv[1]);
      return 1;
   }

   gzseek(file, 0x18, SEEK_SET);
   length = readInt(file);
   gzseek(file, 0x20, SEEK_SET);
   looplength = readInt(file);

   gzclose(file);

   loopstart = length - looplength;

   printf(
      "--Raw VGM information--\n"
      "Total samples: %d\n"
      "Total time in mm:ss: %s\n",
      length,
      printtime(buffer, length)
   );
   printf(
      "Loop start: %d\n"
      "Loop start in mm:ss: %s\n",
      loopstart,
      printtime(buffer, loopstart)
   );
   printf(
      "Loop time: %d\n"
      "Loop time in mm:ss: %s\n",
      looplength,
      printtime(buffer, looplength)
   );

   return 0;
}

It lacks error-checking and sanity-checking. It uses nearest-number rounding for the hundredths of seconds so it differs from your logic slightly; and I didn't understand the logic for the last line of the SSBB bit so I didn't bother with it.
  View user's profile Send private message Visit poster's website
  • Joined: 31 Oct 2009
  • Posts: 5
Reply with quote
Post Posted: Wed Nov 04, 2009 3:53 am
That's an extremely handy one-liner Maxim - I'll hold onto that one.
The only reason I used hexdump to get the data from the header instead of sed/od/tr/cut is that I wanted to keep the .zip file size smaller - any Unix utility I wanted to use had to be in there.
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14745
  • Location: London
Reply with quote
Post Posted: Wed Nov 04, 2009 7:52 am
The only reason I didn't use hexdump is because I didn't have it :) tr, sed etc are more common.
  View user's profile Send private message Visit poster's website
  • Joined: 31 Oct 2009
  • Posts: 5
Reply with quote
Post Posted: Thu Nov 05, 2009 9:47 pm
Here's a new version of vgmcheck based on Maxim's code. It also intergrates the SSBB bits and comes compiled for both Windows and Linux.
The .zip file contains:
*vgmcheck.c (source)
*vgmcheck (Linux binary)
*vgmcheck.exe (Windows binary)
*vgmcheck.bat (Windows batch file, for dragging and dropping .vgm files onto)
*Makefile (consists of two lines)
*README.txt (information)

HOW TO USE (from the readme)
From Windows:
*Drag and drop a .vgm/.vgz file onto vgmcheck.bat, or
*run vgmcheck.exe from a command line: "vgmcheck.exe <filename>"
From Linux:
*Run vgmcheck from a command line: "./vgmcheck <filename>"
vgmcheck-2.0.zip (46.65 KB)

  View user's profile Send private message
Reply to topic



Back to the top of this page

Back to SMS Power!