Skip to content

Commit

Permalink
Discard FM commands in source VGM
Browse files Browse the repository at this point in the history
  • Loading branch information
sverx committed Feb 11, 2023
1 parent a35a89c commit 0d3da67
Showing 1 changed file with 62 additions and 52 deletions.
114 changes: 62 additions & 52 deletions tools/src/vgm2psg.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#define VGM_GGSTEREO 0x4F
#define VGM_PSGFOLLOWS 0x50
#define VGM_FMFOLLOWS 0x51
#define VGM_FRAMESKIP_NTSC 0x62
#define VGM_FRAMESKIP_PAL 0x63
#define VGM_SAMPLESKIP 0x61
Expand Down Expand Up @@ -50,7 +51,7 @@ void decLoopOffset(int n) {

void incLoopOffset(void) {
loop_offset++;
}
}


int checkLoopOffset(void) { // returns 1 when loop_offset becomes 0
Expand All @@ -64,7 +65,7 @@ void init_frame(int initial_state) {
if ((!initial_state) || // set to FALSE
((initial_state) && (!is_sfx)) || // or set to TRUE if it's not a SFX
((initial_state) && (is_sfx) && (active[i]))) { // or set to TRUE if it's a SFX and the chn is active
volume_change[i]=initial_state;
volume_change[i]=initial_state;
freq_change[i]=initial_state;
hi_freq_change[i]=initial_state;
}
Expand All @@ -86,7 +87,7 @@ void add_command (unsigned char c) {
}
} else { // it's a data (not a latch)
chn=(lastlatch&0x60)>>5;
typ=(lastlatch&0x10)>>4;
typ=(lastlatch&0x10)>>4;
if (typ==1) {
volume[chn]=c&0x0F;
volume_change[chn]=TRUE;
Expand All @@ -95,8 +96,8 @@ void add_command (unsigned char c) {
hi_freq_change[chn]=TRUE;
freq[chn]=(freq[chn]&0x000F)|((c&0x3F)<<4);
freq_change[chn]=TRUE;
}
}
}
}
}

void dump_frame(void) {
Expand All @@ -111,14 +112,14 @@ void dump_frame(void) {
fputc(c,fOUT);
}
}

if (volume_change[i]) {
c=0x90|(i<<5)|(volume[i]&0x0F); // latch channel 0-2 volume
fputc(c,fOUT);
}

}

if (freq_change[3]) {
c=(freq[i]&0x07)|0xE0; // latch channel 3 (noise)
fputc(c,fOUT);
Expand All @@ -135,7 +136,7 @@ void dump_pause(void) {
if (pause_len>0) {
while (pause_len>MAX_WAIT) {
fputc(PSG_WAIT+MAX_WAIT,fOUT); // write PSG_WAIT+7 to file
pause_len-=MAX_WAIT+1; // skip MAX_WAIT+1
pause_len-=MAX_WAIT+1; // skip MAX_WAIT+1
}
if (pause_len>0)
fputc(PSG_WAIT+(pause_len-1),fOUT); // write PSG_WAIT+[0 to 7] to file, don't do it if 0
Expand All @@ -154,7 +155,7 @@ void found_frame(void) {
if (pause_started)
dump_pause();
frame_started=TRUE;

pause_started=FALSE;
pause_len=0;
}
Expand Down Expand Up @@ -188,9 +189,9 @@ int main (int argc, char *argv[]) {
int first_byte=TRUE;
unsigned int file_signature,frame_rate;
int sample_divider=735; // NTSC (default)

printf ("*** Sverx's VGM to PSG converter ***\n");

if ((argc<3) || (argc>4)) {
printf ("Usage: vgm2psg inputfile.VGM outputfile.PSG [2|3|23]\n");
printf (" the optional third parameter specifies which channel(s) should be active,\n");
Expand All @@ -200,11 +201,11 @@ int main (int argc, char *argv[]) {
printf (" - 23 means the SFX is using both channels\n");
return (1);
}

if (argc==4) {
for (i=0;i<CHANNELS;i++)
active[i]=0;

for (i=0;i<strlen(argv[3]);i++) {
switch (argv[3][i]) {
case '2':
Expand All @@ -218,80 +219,89 @@ int main (int argc, char *argv[]) {
is_sfx=TRUE;
printf ("Info: SFX conversion on channel(s): %s%s\n",active[2]?"2":"",active[3]?"3":"");
}

init_frame(TRUE);

fIN=gzopen(argv[1],"rb");
if (!fIN) {
printf("Fatal: can't open input VGM file\n");
return(1);
}

gzread (fIN,&file_signature, 4);
if (file_signature!=0x206d6756) { // check for 'Vgm ' file signature
printf("Fatal: input file doesn't seem a valid VGM/VGZ file\n");
return(1);
}

gzseek(fIN,VGM_HEADER_FRAMERATE,SEEK_SET); // seek to FRAMERATE in the VGM header
gzread (fIN,&frame_rate, 4); // read frame_rate

if (frame_rate==60) {
printf ("Info: NTSC (60Hz) VGM detected\n");
printf ("Info: NTSC (60Hz) VGM detected\n");
} else if (frame_rate==50) {
printf ("Info: PAL (50Hz) VGM detected\n");
sample_divider=882; // PAL!
} else {
printf ("Warning: unknown frame rate, assuming NTSC (60Hz)\n");
printf ("Warning: unknown frame rate, assuming NTSC (60Hz)\n");
}

gzseek(fIN,VGM_HEADER_LOOPPOINT,SEEK_SET); // seek to LOOPPOINT in the VGM header
gzread (fIN,&loop_offset, 4); // read loop_offset

gzseek(fIN,VGM_DATA_OFFSET,SEEK_SET); // seek to DATAOFFSET in the VGM header
gzread (fIN,&data_offset, 4); // read data_offset

if (data_offset) {
gzseek(fIN,VGM_DATA_OFFSET+data_offset,SEEK_SET); // skip VGM header
data_offset=VGM_DATA_OFFSET+data_offset;
} else {
gzseek(fIN,VGM_OLD_HEADERSIZE,SEEK_SET); // skip 'old' VGM header
data_offset=VGM_OLD_HEADERSIZE;
}

if (loop_offset!=0) {
printf ("Info: loop point at 0x%08x\n",loop_offset);
loop_offset=loop_offset+VGM_HEADER_LOOPPOINT-data_offset;
} else {
printf ("Info: no loop point defined\n");
loop_offset=-1; // make it negative so that won't happen
}

fOUT=fopen(argv[2],"wb");
if (!fOUT) {
printf("Fatal: can't write to output PSG file\n");
return(1);
}

while ((!leave) && (!gzeof(fIN))) {
c=gzgetc(fIN);
decLoopOffset(1);
if (checkLoopOffset()) writeLoopMarker();

switch (c) {

case VGM_GGSTEREO: // stereo data byte follows
// BETA: this is simply DISCARDED atm
c=gzgetc(fIN);
printf("Warning: GameGear stereo info discarded\n");
decLoopOffset(1);
if (checkLoopOffset()) writeLoopMarker();
break;


case VGM_FMFOLLOWS:
// discard this!
c=gzgetc(fIN);
c=gzgetc(fIN);
printf("Warning: FM chip write discarded\n");
decLoopOffset(2);
if (checkLoopOffset()) writeLoopMarker();
break;

case VGM_PSGFOLLOWS: // PSG byte follows

c=gzgetc(fIN);

if (c&0x80) {
lastlatch=c; // latch value
latched_chn=(c&0x60)>>5; // isolate chn number
Expand All @@ -300,50 +310,50 @@ int main (int argc, char *argv[]) {
}

if ((!is_sfx) || (active[latched_chn])) { // output only if on an active channel

found_frame();

if ((first_byte) && ((c&0x80)==0)) {
add_command(lastlatch);
printf("Warning: added missing latch command in frame start\n");
}
add_command(c);
first_byte=FALSE;
}

decLoopOffset(1);
if (checkLoopOffset()) writeLoopMarker();
break;

case VGM_FRAMESKIP_NTSC:
case VGM_FRAMESKIP_PAL:

// frame skip, now count how many
found_pause();

fs=1;
do {
c=gzgetc(fIN);
if ((c==VGM_FRAMESKIP_NTSC) || (c==VGM_FRAMESKIP_PAL)) fs++;
decLoopOffset(1);
} while ((fs<MAX_WAIT) && ((c==VGM_FRAMESKIP_NTSC) || (c==VGM_FRAMESKIP_PAL)) && (!checkLoopOffset()));

if ((c!=VGM_FRAMESKIP_NTSC) && (c!=VGM_FRAMESKIP_PAL)) {
gzungetc(c,fIN);
incLoopOffset();
}

pause_len+=fs;
if (checkLoopOffset()) writeLoopMarker();

first_byte=TRUE;

break;

case VGM_SAMPLESKIP: // sample skip, now count how many

found_pause();

c=gzgetc(fIN);
ss=c;
c=gzgetc(fIN);
Expand All @@ -356,23 +366,23 @@ int main (int argc, char *argv[]) {
}

pause_len+=fs;

decLoopOffset(2);
if (checkLoopOffset()) writeLoopMarker();

first_byte=TRUE;

break;


case VGM_ENDOFDATA: // end of data
leave=1;
decLoopOffset(1);
if (checkLoopOffset()) writeLoopMarker();
empty_data();
fputc(PSG_ENDOFDATA,fOUT);
break;

default:
printf("Fatal: found unknown char 0x%02x\n",c);
leave=1;
Expand All @@ -381,10 +391,10 @@ int main (int argc, char *argv[]) {
}

}

gzclose (fIN);
fclose (fOUT);

if (!fatal) {
printf ("Info: conversion complete\n");
return(0);
Expand Down

0 comments on commit 0d3da67

Please sign in to comment.