Jump to content

Recommended Posts

My bad. Here's the output using Tursi's converter. I just don't know what's going on here... I've converted these to decimal but it hasn't made things much clearer to me.

 

0x00000027,0xCA
0x00000027,0xA0
0x00000027,0xA0
0x00000027,0x80
0x0000001F,0x80
0x0000001F,0x64
0x0000001F,0x64
0x0000001F,0x50
0x0000001F,0x50
0x0000001F,0x40
0x0000001F,0x40
0x0000001F,0x32
0x0000001F,0x28
0x0000001F,0x28
0x0000001F,0x20
0x0000001F,0x20
0x0000001F,0x18
0x0000001F,0x18
0x0000001F,0x14
0x0000001F,0x14
0x0000001F,0x10
0x0000001F,0x10
0x0000001F,0x0C
0x0000001F,0x0C
0x0000001F,0x0A
0x0000001F,0x00
0x0000001F,0x00

 

59 minutes ago, Jess Ragan said:

My bad. Here's the output using Tursi's converter. I just don't know what's going on here... I've converted these to decimal but it hasn't made things much clearer to me.

 

0x00000027,0xCA
0x00000027,0xA0
0x00000027,0xA0
0x00000027,0x80
0x0000001F,0x80
0x0000001F,0x64
0x0000001F,0x64
0x0000001F,0x50
0x0000001F,0x50
0x0000001F,0x40
0x0000001F,0x40
0x0000001F,0x32
0x0000001F,0x28
0x0000001F,0x28
0x0000001F,0x20
0x0000001F,0x20
0x0000001F,0x18
0x0000001F,0x18
0x0000001F,0x14
0x0000001F,0x14
0x0000001F,0x10
0x0000001F,0x10
0x0000001F,0x0C
0x0000001F,0x0C
0x0000001F,0x0A
0x0000001F,0x00
0x0000001F,0x00

 

The second column is the frequency, but I cannot make sense of the left column.

 

The file formats are all documented in the VGMComp2.pdf that's included in the zip (or directly at the download page). At the very end there is an example sequence of the minimum steps to compress a file for the SN, I'll refer back to that again in a moment.

 

In this case, this is a single channel dump. There's metadata in the filename that is important for parsing it - but we can assume that it's 60hz - every one is 1/60th of a second. What's not entirely clear is whether it's a tone or a noise - only the filename identifies that.

 

The first column is the frequency shift rate (IMPORTANT: even if it's noise!). The second column is the volume as an 8-bit ratio (where 0x00 is mute, and 0xff is maximum volume). Noise frequencies have extra flags for periodic and retrigger, but I don't see any here so you can look up the docs if you need them.

 

When you extract a VGM, the toolset writes every channel separately, and preserves as much detail as possible so they are easy to manipulate. When you are ready to play on the SN, you need to adapt the data to fit.

 

You can do this manually - assuming the shift rates are all legal (001 to 3ff). You can divide the volume by 16 and flip it to get the valid range, but I already have a tool in there to do all this for you (and it will map the volume to the logarithmic scale the real chip uses, and clip invalid tones).

 

You already used vgm_psg2psg.exe to extract the VGM. (This reads SN PSG data from a VGM file). In your case you got 1 channel, but you can get all four depending on the music.

 

To prepare it for SN playback, use prepare4sn.exe. This takes in 4 channels (three tone channels and a noise channel) and outputs a combined file with everything processed to be legal on the SN -- shift rates are verified and enforced, noise shift rates are determined and mapped to the correct noise type, and volumes are mapped into the valid range. The output file is very similar to the one you are looking at, except all four channels are on a single line.

 

For example:

0x000B4,0x4,0x000D6,0x5,0x003FF,0x7,0x00004,0x5

 

Frequency, volume, frequency, volume, frequency, volume, noise type, volume - ready to throw at the chip.

 

In your case, you only have one channel, but you can still use it. Use:

 

prepare4sn.exe mytune.vgm_ton00.60hz - - - mytune.snpsg

 

The "-" means "no input on this channel", so there are three. The output is whatever name you want, but I like "snpsg" to remind me this is processed for the SN sound chip. Feel free to throw a ".txt" on there if it makes it easier to read. ;)

 

The output looks like so:

 

D:\work\TI\vgmcomp2\test>prepare4SN.exe x.vgm_ton00.60hz - - - x.snpsg
VGMComp2 PSG Prep Tool - v20240414

Opened tone channel 0: x.vgm_ton00.60hz
Channel 1 (tone) free
Channel 2 (tone) free
Channel 3 (noise) free
Imported 27 rows
0 custom noises (non-lossy)
0 tones moved   (non-lossy)
0 mutes mapped  (non-lossy)
0 tones clipped (lossy)
0 noises mapped (lossy)
** DONE **

 

In that case, your lines will look like this:

 

0x00027,0x1,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x00027,0x2,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x00027,0x2,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x00027,0x3,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0x3,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0x4,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0x4,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0x5,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0x5,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0x6,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0x6,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0x7,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0x8,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0x8,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0x9,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0x9,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0xA,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0xA,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0xB,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0xB,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0xC,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0xC,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0xD,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0xD,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0xE,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0xF,0x00001,0xF,0x00001,0xF,0x00005,0xF
0x0001F,0xF,0x00001,0xF,0x00001,0xF,0x00005,0xF

 

All your data is in the first two columns - note how the volumes are now the correct values for the SN sound chip. Since you know the rest of the data is empty, you can ignore it.

 

Note that although there are 5 nibbles displayed in the tone, that's to leave room for internal flags. You only need to care about the last four - two bytes. (One byte for the noise channel).

 

To play it back, you need to add the command nibbles for the channel you want to play. (My compressor doesn't store that nibble to aid compression). And, unfortunately, the SN requires you to "swizzle" the nibbles. So once you have the bytes (I don't know what your sound code looks like, in C you can just write to "SOUND" if it's set up appropriately), so:

 

const unsigned char myTone[] = {
0x00,0x27,0x1,
0x00,0x27,0x2,
0x00,0x27,0x2,
0x00,0x27,0x3,
0x00,0x1F,0x3,
0x00,0x1F,0x4,
0x00,0x1F,0x4,
0x00,0x1F,0x5,
0x00,0x1F,0x5,
0x00,0x1F,0x6,
0x00,0x1F,0x6,
0x00,0x1F,0x7,
0x00,0x1F,0x8,
0x00,0x1F,0x8,
0x00,0x1F,0x9,
0x00,0x1F,0x9,
0x00,0x1F,0xA,
0x00,0x1F,0xA,
0x00,0x1F,0xB,
0x00,0x1F,0xB,
0x00,0x1F,0xC,
0x00,0x1F,0xC,
0x00,0x1F,0xD,
0x00,0x1F,0xD,
0x00,0x1F,0xE,
0x00,0x1F,0xF,
0x00,0x1F,0xF
};

// note, assuming sound chip is at SOUND and a function "waitnmi()" exists for timing
void playtone() {
    unsigned char *pTone = myTone;
    int bytesleft = sizeof(myTone);
    unsigned int val;
    
    while (bytesleft > 0) {
        // wait for an NMI to happen for 60hz timing
        waitnmi();
        
        // handle frequency bytes - some manipulation is required
        val = ((unsigned int)(*(pTone))<<8) | (*(pTone+1));     // read two bytes into int, MSB first
        SOUND = 0x80 | (val&0xf);    // command nibble and least significant nibble of value
        SOUND = (val>>4)&0xff;       // two most significant nibbles of value
        
        // and the volume
        SOUND = 0x90 | *(pTone+2);  // command nibble and volume value (MUST be 0-F)
        
        // next row
        pTone += 3;
        bytesleft -= 3;
    }
}

 

Hopefully you can extract the missing knowledge from this. Note that this format is intended for two things:

- to be input for the compression tool

- to be easy to read and manipulate

 

It's NOT intended to be a playback format. As you can see, there is a lot of redundancy and storing every 60hz tick makes the data much larger than it would otherwise need to be. You CAN do this, though... but it'd be better to use the file as input to some other tool that packs in a format you find easier to play.

 

Not sure about the quip that I seem unwilling to help. I'm not willing to rewrite my tools for you, nor to deep dive into the web page generator (which I did not write), but otherwise I think I've stepped in where asked! ;)

 

Posted (edited)

Just to beat a dead horse, this data takes 81 bytes to store.

 

The compressor doesn't really suit short sounds, although if you packed a lot of them into one file it might help. But you might consider the TI sound list format, which will at least give you a really basic RLE compression.

 

vgmcomp2.exe compresses this one sound to 62 bytes. Playback is handled through the included libcolecovgm2:

D:\work\TI\vgmcomp2\test>..\release\vgmcomp2.exe -sn x.snpsg s.sbf
VGMComp2 Compression Tool - v20210901

- Skipping streams 1 and 5 due to no audio
- Skipping streams 2 and 6 due to no audio
- Skipping streams 3 and 7 due to no audio
Got 27 rows... Successful!

1 songs (0.450000 seconds) compressed to 62 bytes (137.778000 bytes/second @ 60hz)

** DONE **

Better examples of the conversion library capabilities are seen in Super Space Acer and my Thunder Force 3 Tribute.

 

 

psg2soundlist.exe packs this sound to 57 bytes.

D:\work\TI\vgmcomp2\test>..\release\psg2soundlist.exe x.snpsg x.tilist.bin
VGMComp VGM Test Output - v20240511
Reading TONE channel 0 from x.snpsg... read 27 lines
Reading TONE channel 1 from x.snpsg... read 27 lines
Reading TONE channel 2 from x.snpsg... read 27 lines
Reading NOISE channel 3 from x.snpsg... read 27 lines
0 custom noises (non-lossy)
0 tones moved   (non-lossy)
0 mutes mapped  (non-lossy)
0 tones clipped (lossy)
0 noises mapped (lossy)
Going to write TI Sound List format binary file 'x.tilist.bin'
- Wrote 57 bytes
** DONE **
03 91 87 02 01 01 92 02 01 93 01 02 8F 01 01 01 
94 02 01 95 02 01 96 02 01 97 01 01 98 02 01 99 
02 01 9A 02 01 9B 02 01 9C 02 01 9D 02 01 9E 01 
01 9F 02 04 9F BF DF FF 00

 

The TI soundlist format is very simple:

 

- number of bytes to load (ie: 3)

- actual bytes to send to sound chip - no swizzling (ie: 91, 87, 02)

- number of frames to wait until the next load (ie: 1)

 

Repeat until number frames to wait is 0.

 

Note: You'll have to re-download if you want to use psg2soundlist, I had to fix a bug while testing this here. ;)

 

Anyway, I know you have other options, but these are the options my tools spit out.

 

Edited by Tursi

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...