ayVGM - A lite version of VGM for AY-3-8910

Page 1/3
| 2 | 3

By aoineko

Paladin (1002)

aoineko's picture

19-01-2022, 00:30

Hello,

I've discovered the VGM format a few days ago via the vgmrips.net website and its MSX music.
The principle of this format is very simple: it list all the accesses to the sound chip registers and their timings.
It is a kind of "universal" format; it generates quite large files (Konami music I ckecked are about 10 to 40K) but the big advantage is that the replayer is extremely simple and fast.
While creating a C replayer for my MSXgl library I analyzed the VGM format and saw that it was possible to optimize it a lot for the PSG.

So I created a lite version of VGM specially designed for PSG. I named it "ayVGM".
The 1st version of the format can be found here: https://github.com/aoineko-fr/MSXgl/blob/main/engine/src/ayv...
On the 30 or so Konami PSG tunes I tried, I have a size reduction of about 69%.
Now, file sizes seem usable on a mapped ROMs game for example.
So I also added to MSXgl a C player for this format and a sample program to test it.
I will convert the player to assembler one day, but for now, everything works fine.

It's cool to listen to existing VGM, but I don't have a tool to create music in ayVGM format (only a tool to convert them from VGM).
So, now the question... how to create VGM? ^^
I understood that the music on VGMrips are created from MAME which would allow to log the accesses to PSG.
Is this correct?
Has anyone tried it yet?
Do you know any other emulators or trackers that can create VGM files?

Login or register to post comments

By aoineko

Paladin (1002)

aoineko's picture

19-01-2022, 00:51

By gdx

Enlighted (6210)

gdx's picture

19-01-2022, 01:17

Interesting.

Can you make also a ayVGM player easily usable in BASIC programs?
By using the memory pages 0 and 1 for example.

By aoineko

Paladin (1002)

aoineko's picture

19-01-2022, 01:33

I'm sorry, but I really know almost nothing about BASIC and how to make the player usable from it.
If you give me more precise instructions, maybe I can do it.

BTW: Here is a link to test the sample on WebMSX.

By NetNomad

Resident (51)

NetNomad's picture

19-01-2022, 05:58

This is very cool! With openMSX I'd imagine you'll be able to log VGMs using any of the native music-making tools available on the MSX. For tools on modern PCs, Deflemask is a pretty popular VGM tracker but recently became paid. Furnace is a free clone but I'm not sure that it can export VGM files yet. For MML, MML2VGM is very powerful, with the only con being that all of the documentation is in Japanese, but I would still highly recommend it.

By Grauw

Ascended (10768)

Grauw's picture

19-01-2022, 10:31

Nice! I’ve also already gotten good size reduction results for such a format by just removing waits and using 16 commands for each PSG register. But you go a step further with the encoding, even using nibbles to get single-byte commands! And due to the table lookup for the register it probably doesn’t even affect speed all that much. Clever.

By thegeps

Paragon (1187)

thegeps's picture

19-01-2022, 11:25

Cool, waiting for an asm version Smile

By Grauw

Ascended (10768)

Grauw's picture

19-01-2022, 12:18

Some performance optimisation suggestions:

u8 val = *g_ayVGM_Pointer & 0x0F;

This could be omitted if you don’t care about writing 1’s to bit locations that are unused.

val |= 0x10;

Since the command number is odd already (cleverly chosen), and if you omit the AND earlier, you don’t need this OR.

u8 op = *g_ayVGM_Pointer >> 4;

Shifting is quite expensive, you could also do an AND 0xF0 here and adjust the CASE statements (and put the shift only in the table lookup). Then the shift will only be executed when needed, or could be eliminated entirely by having a 256-byte lookup table.

FE nn nn    End of song with loop

The current pointer is relative to the start of the song. However if you make it relative to the current song position, it simplifies the new pointer calculation to just g_ayVGM_Pointer + offset.

while(g_ayVGM_Wait == 0)

Because only wait and stop commands need to break out of the loop, this could be optimised to
if (g_ayVGM_Wait == 0) while (true) { ... }.

PSG_SetRegister(g_ayVGM_RegTable[--op], val);

A dec (--) is not a high cost, however you can eliminate it by adding a dummy 0th index to the table.

----------------------------
 Noise Period
----------------------------
	07 nn       R#7	= nn

The header here is wrong, it should say mixer settings.

By aoineko

Paladin (1002)

aoineko's picture

19-01-2022, 18:56

I took into account your suggestions to optimize the ayVGM player (see GitHub).
I just left the end of the music code because imho, it happens too infrequently to need an optimization.

Anyway, when I look at the generated assembler code, it's not so good. :-/
The next step would be to rewrite the player in assembler.
But I prefer to let the format mature a bit to see if it doesn't need some modifications before passing the player in assembler.

By aoineko

Paladin (1002)

aoineko's picture

21-01-2022, 11:33

I tried a to extend ayVGM format to include SCC data.

I get an average reduction of 63% (especially thanks to the waveforms data packing), but the resulting data is still too big to be really usable in a game (in ROM anyway).

I will keep this format for PSG data only, where there reasonable data size and lightness of the replayer make it a relevant option for a game.

By gdx

Enlighted (6210)

gdx's picture

21-01-2022, 11:46

aoineko wrote:

I'm sorry, but I really know almost nothing about BASIC and how to make the player usable from it.

No need to know the MSX-BASIC if you use DEFUSR. The DEFUSR number can determine the music number. The value in parentheses can determine the music to play or stop. (for example 0 = mute, 1 = play one time, 2 = loop, etc). A very simple player but sufficient.

Page 1/3
| 2 | 3