]> 4ch.mooo.com Git - 16.git/commitdiff
imfplay and vgmtest are both broken ><. but bcexmmtest.exe works!
authorsparky4 <sparky4@cock.li>
Sat, 19 Aug 2017 00:43:36 +0000 (19:43 -0500)
committersparky4 <sparky4@cock.li>
Sat, 19 Aug 2017 00:43:36 +0000 (19:43 -0500)
src/imfplay.c
src/lib/vgmsnd/VGMFile.h [new file with mode: 0755]
src/lib/vgmsnd/imf2vgm.c [new file with mode: 0755]

index 1895d77d70fdb523f5d11511d5ed270891b1092d..697b6d3611e7f3d7940223948a5f91b58b0756a4 100755 (executable)
@@ -19,7 +19,7 @@
 #include "src/lib/16_mm.h"
 #include "src/lib/16_hc.h"
 #include "src/lib/16_dbg.h"
-//#include "src/lib/16_sd.h"
+#include "src/lib/16_sd.h"
 
 // #include <stdio.h>
 // #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
diff --git a/src/lib/vgmsnd/VGMFile.h b/src/lib/vgmsnd/VGMFile.h
new file mode 100755 (executable)
index 0000000..29c4ad4
--- /dev/null
@@ -0,0 +1,152 @@
+#ifndef __VGMFILE_H__
+#define __VGMFILE_H__
+
+// Header file for VGM file handling
+
+typedef struct _vgm_file_header
+{
+       UINT32 fccVGM;
+       UINT32 lngEOFOffset;
+       UINT32 lngVersion;
+       UINT32 lngHzPSG;
+       UINT32 lngHzYM2413;
+       UINT32 lngGD3Offset;
+       UINT32 lngTotalSamples;
+       UINT32 lngLoopOffset;
+       UINT32 lngLoopSamples;
+       UINT32 lngRate;
+       UINT16 shtPSG_Feedback;
+       UINT8 bytPSG_SRWidth;
+       UINT8 bytPSG_Flags;
+       UINT32 lngHzYM2612;
+       UINT32 lngHzYM2151;
+       UINT32 lngDataOffset;
+       UINT32 lngHzSPCM;
+       UINT32 lngSPCMIntf;
+       UINT32 lngHzRF5C68;
+       UINT32 lngHzYM2203;
+       UINT32 lngHzYM2608;
+       UINT32 lngHzYM2610;
+       UINT32 lngHzYM3812;
+       UINT32 lngHzYM3526;
+       UINT32 lngHzY8950;
+       UINT32 lngHzYMF262;
+       UINT32 lngHzYMF278B;
+       UINT32 lngHzYMF271;
+       UINT32 lngHzYMZ280B;
+       UINT32 lngHzRF5C164;
+       UINT32 lngHzPWM;
+       UINT32 lngHzAY8910;
+       UINT8 bytAYType;
+       UINT8 bytAYFlag;
+       UINT8 bytAYFlagYM2203;
+       UINT8 bytAYFlagYM2608;
+       UINT8 bytVolumeModifier;
+       UINT8 bytReserved2;
+       INT8 bytLoopBase;
+       UINT8 bytLoopModifier;
+       UINT32 lngHzGBDMG;
+       UINT32 lngHzNESAPU;
+       UINT32 lngHzMultiPCM;
+       UINT32 lngHzUPD7759;
+       UINT32 lngHzOKIM6258;
+       UINT8 bytOKI6258Flags;
+       UINT8 bytK054539Flags;
+       UINT8 bytC140Type;
+       UINT8 bytReservedFlags;
+       UINT32 lngHzOKIM6295;
+       UINT32 lngHzK051649;
+       UINT32 lngHzK054539;
+       UINT32 lngHzHuC6280;
+       UINT32 lngHzC140;
+       UINT32 lngHzK053260;
+       UINT32 lngHzPokey;
+       UINT32 lngHzQSound;
+       UINT32 lngHzSCSP;
+//     UINT32 lngHzOKIM6376;
+       //UINT8 bytReserved[0x04];
+       UINT32 lngExtraOffset;
+       UINT32 lngHzWSwan;
+       UINT32 lngHzVSU;
+       UINT32 lngHzSAA1099;
+       UINT32 lngHzES5503;
+       UINT32 lngHzES5506;
+       UINT8 bytES5503Chns;
+       UINT8 bytES5506Chns;
+       UINT8 bytC352ClkDiv;
+       UINT8 bytESReserved;
+       UINT32 lngHzX1_010;
+       UINT32 lngHzC352;
+       UINT32 lngHzGA20;
+} VGM_HEADER;
+typedef struct _vgm_header_extra
+{
+       UINT32 DataSize;
+       UINT32 Chp2ClkOffset;
+       UINT32 ChpVolOffset;
+} VGM_HDR_EXTRA;
+typedef struct _vgm_extra_chip_data32
+{
+       UINT8 Type;
+       UINT32 Data;
+} VGMX_CHIP_DATA32;
+typedef struct _vgm_extra_chip_data16
+{
+       UINT8 Type;
+       UINT8 Flags;
+       UINT16 Data;
+} VGMX_CHIP_DATA16;
+typedef struct _vgm_extra_chip_extra32
+{
+       UINT8 ChipCnt;
+       VGMX_CHIP_DATA32* CCData;
+} VGMX_CHP_EXTRA32;
+typedef struct _vgm_extra_chip_extra16
+{
+       UINT8 ChipCnt;
+       VGMX_CHIP_DATA16* CCData;
+} VGMX_CHP_EXTRA16;
+typedef struct _vgm_header_extra_data
+{
+       VGMX_CHP_EXTRA32 Clocks;
+       VGMX_CHP_EXTRA16 Volumes;
+} VGM_EXTRA;
+
+#define VOLUME_MODIF_WRAP      0xC0
+typedef struct _vgm_gd3_tag
+{
+       UINT32 fccGD3;
+       UINT32 lngVersion;
+       UINT32 lngTagLength;
+       wchar_t* strTrackNameE;
+       wchar_t* strTrackNameJ;
+       wchar_t* strGameNameE;
+       wchar_t* strGameNameJ;
+       wchar_t* strSystemNameE;
+       wchar_t* strSystemNameJ;
+       wchar_t* strAuthorNameE;
+       wchar_t* strAuthorNameJ;
+       wchar_t* strReleaseDate;
+       wchar_t* strCreator;
+       wchar_t* strNotes;
+} GD3_TAG;
+typedef struct _vgm_pcm_bank_data
+{
+       UINT32 DataSize;
+       UINT8* Data;
+       UINT32 DataStart;
+} VGM_PCM_DATA;
+typedef struct _vgm_pcm_bank
+{
+       UINT32 BankCount;
+       VGM_PCM_DATA* Bank;
+       UINT32 DataSize;
+       UINT8* Data;
+       UINT32 DataPos;
+       UINT32 BnkPos;
+} VGM_PCM_BANK;
+
+#define FCC_VGM        0x206D6756      // 'Vgm '
+#define FCC_GD3        0x20336447      // 'Gd3 '
+
+#endif // __VGMFILE_H__
diff --git a/src/lib/vgmsnd/imf2vgm.c b/src/lib/vgmsnd/imf2vgm.c
new file mode 100755 (executable)
index 0000000..7d7c683
--- /dev/null
@@ -0,0 +1,302 @@
+// imf2vgm.c - IMF -> VGM Converter
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "stdtype.h"
+#include "VGMFile.h"
+#include "common.h"
+
+
+static UINT8 OpenIMFFile(const char* FileName);
+static void WriteVGMFile(const char* FileName);
+static void ConvertIMF2VGM(void);
+
+
+UINT8 IMFType;
+UINT16 IMFRate;
+VGM_HEADER VGMHead;
+UINT32 IMFDataLen;
+UINT8* IMFData;
+UINT32 IMFPos;
+UINT32 IMFDataStart;
+UINT32 IMFDataEnd;
+UINT32 VGMDataLen;
+UINT8* VGMData;
+UINT32 VGMPos;
+char FileBase[0x100];
+UINT8 LoopOn;
+
+int main(int argc, char* argv[])
+{
+       int argbase;
+       int ErrVal;
+       char FileName[0x100];
+       UINT16 ForceHz;
+       UINT8 ForceType;
+       
+       printf("IMF to VGM Converter\n--------------------\n\n");
+       
+       ErrVal = 0;
+       argbase = 1;
+       ForceHz = 0;
+       ForceType = 0xFF;
+       LoopOn = 0x00;
+       
+       while(argbase < argc && argv[argbase][0] == '-')
+       {
+               if (! stricmp(argv[argbase], "-help"))
+               {
+                       printf("Usage: imf2vgm [-Loop] [-Hz###] [-Type#] Input.imf [Output.vgm]\n");
+                       printf("\n");
+                       printf("Loop: Makes the song loop from beginning to end.\n");
+                       printf("Hz:   There are 3 known speeds: 280, 560 and 700\n");
+                       printf("      560 is default for .imf, 700 for .wlf files\n");
+                       printf("Type: Can be 0 (no header) or 1 (header with 2-byte file size)\n");
+                       return 0;
+               }
+               else if (! stricmp(argv[argbase], "-Loop"))
+               {
+                       LoopOn = 0x01;
+                       argbase ++;
+               }
+               else if (! strnicmp(argv[argbase], "-Hz", 3))
+               {
+                       ForceHz = (UINT16)strtoul(argv[argbase] + 3, NULL, 0);
+                       argbase ++;
+               }
+               else if (! strnicmp(argv[argbase], "-Type", 5))
+               {
+                       ForceType = (UINT8)strtoul(argv[argbase] + 5, NULL, 0);
+                       if (ForceType >= 0x02)
+                       {
+                               printf("Error: Type must be either 0 or 1!\n");
+                               return 2;
+                       }
+                       argbase ++;
+               }
+               else
+               {
+                       break;
+               }
+       }
+       
+       printf("File Name:\t");
+       if (argc <= argbase + 0)
+       {
+               ReadFilename(FileName, sizeof(FileName));
+       }
+       else
+       {
+               strcpy(FileName, argv[argbase + 0]);
+               printf("%s\n", FileName);
+       }
+       if (! strlen(FileName))
+               return 0;
+       
+       if (OpenIMFFile(FileName))
+       {
+               printf("Error opening the file!\n");
+               ErrVal = 1;
+               goto EndProgram;
+       }
+       printf("\n");
+       
+       if (ForceHz)
+               IMFRate = ForceHz;
+       if (ForceType < 0xFF)
+               IMFType = ForceType;
+       ConvertIMF2VGM();
+       
+       if (argc > argbase + 1)
+               strcpy(FileName, argv[argbase + 1]);
+       else
+               strcpy(FileName, "");
+       if (FileName[0] == '\0')
+       {
+               strcpy(FileName, FileBase);
+               strcat(FileName, ".vgm");
+       }
+       WriteVGMFile(FileName);
+       
+       free(IMFData);
+       free(VGMData);
+       
+EndProgram:
+       DblClickWait(argv[0]);
+       
+       return ErrVal;
+}
+
+static UINT8 OpenIMFFile(const char* FileName)
+{
+       FILE* hFile;
+       UINT16 TempSht;
+       char* TempPnt;
+       
+       hFile = fopen(FileName, "rb");
+       if (hFile == NULL)
+               return 0xFF;
+       
+       fseek(hFile, 0x00, SEEK_END);
+       IMFDataLen = ftell(hFile);
+       
+       // Read Data
+       IMFData = (UINT8*)malloc(IMFDataLen);
+       if (IMFData == NULL)
+               goto OpenErr;
+       fseek(hFile, 0x00, SEEK_SET);
+       IMFDataLen = fread(IMFData, 0x01, IMFDataLen, hFile);
+       
+       fclose(hFile);
+       
+       memcpy(&TempSht, &IMFData[0x00], 0x02);
+       if (! TempSht)
+               IMFType = 0x00;
+       else
+               IMFType = 0x01;
+       
+       strcpy(FileBase, FileName);
+       TempPnt = strrchr(FileBase, '.');
+       if (TempPnt != NULL)
+       {
+               *TempPnt = 0x00;
+               TempPnt ++;
+       }
+       else
+       {
+               TempPnt = FileBase + strlen(FileBase);
+       }
+       if (! stricmp(TempPnt, "wlf"))
+               IMFRate = 700;
+       else
+               IMFRate = 560;
+       
+       return 0x00;
+
+OpenErr:
+
+       fclose(hFile);
+       return 0x80;
+}
+
+static void WriteVGMFile(const char* FileName)
+{
+       FILE* hFile;
+       
+       hFile = fopen(FileName, "wb");
+       fwrite(VGMData, 0x01, VGMDataLen, hFile);
+       fclose(hFile);
+       
+       printf("File written.\n");
+       
+       return;
+}
+
+static void ConvertIMF2VGM(void)
+{
+       UINT16 CurDelay;
+       UINT32 CurTick;
+       UINT16 HalfRate;
+       UINT64 TempTick;
+       UINT32 VGMSmplL;
+       UINT32 VGMSmplC;
+       UINT32 SmplVal;
+       
+       VGMDataLen = sizeof(VGM_HEADER) + IMFDataLen * 0x02;
+       VGMData = (UINT8*)malloc(VGMDataLen);
+       
+       printf("IMF Type: %u, IMF Playback Rate: %u Hz\n", IMFType, IMFRate);
+       
+       memcpy(&CurDelay, &IMFData[0x00], 0x02);
+       if (IMFType == 0x00)
+       {
+               IMFDataStart = 0x0000;
+               IMFDataEnd = IMFDataLen;
+       }
+       else //if (IMFType == 0x01)
+       {
+               IMFDataStart = 0x0002;
+               IMFDataEnd = IMFDataStart + CurDelay;
+       }
+       
+       // Generate VGM Header
+       memset(&VGMHead, 0x00, sizeof(VGM_HEADER));
+       VGMHead.fccVGM = FCC_VGM;
+       VGMHead.lngVersion = 0x00000151;
+       VGMHead.lngRate = IMFRate;
+       VGMHead.lngDataOffset = 0x80;
+       VGMHead.lngHzYM3812 = 3579545;
+       
+       // Convert data
+       IMFPos = IMFDataStart;
+       VGMPos = VGMHead.lngDataOffset;
+       CurTick = 0;
+       VGMSmplL = 0;
+       HalfRate = IMFRate / 2; // for correct rounding
+       while(IMFPos < IMFDataEnd)
+       {
+               if (VGMPos >= VGMDataLen - 0x08)
+               {
+                       VGMDataLen += 0x8000;
+                       VGMData = (UINT8*)realloc(VGMData, VGMDataLen);
+               }
+               VGMData[VGMPos + 0x00] = 0x5A;
+               VGMData[VGMPos + 0x01] = IMFData[IMFPos + 0x00];        // register
+               VGMData[VGMPos + 0x02] = IMFData[IMFPos + 0x01];        // data
+               VGMPos += 0x03;
+               
+               memcpy(&CurDelay, &IMFData[IMFPos + 0x02], 0x02);
+               CurTick += CurDelay;
+               TempTick = (UINT64)CurTick * 44100 + HalfRate;
+               VGMSmplC = (UINT32)(TempTick / IMFRate);
+               IMFPos += 0x04;
+               
+               if (VGMSmplL < VGMSmplC)
+               {
+                       SmplVal = VGMSmplC - VGMSmplL;
+                       while(SmplVal)
+                       {
+                               if (SmplVal <= 0xFFFF)
+                                       CurDelay = (UINT16)SmplVal;
+                               else
+                                       CurDelay = 0xFFFF;
+                               
+                               if (VGMPos >= VGMDataLen - 0x08)
+                               {
+                                       VGMDataLen += 0x8000;
+                                       VGMData = (UINT8*)realloc(VGMData, VGMDataLen);
+                               }
+                               VGMData[VGMPos + 0x00] = 0x61;
+                               memcpy(&VGMData[VGMPos + 0x01], &CurDelay, 0x02);
+                               VGMPos += 0x03;
+                               SmplVal -= CurDelay;
+                       }
+                       VGMSmplL = VGMSmplC;
+               }
+       }
+       VGMData[VGMPos] = 0x66;
+       VGMPos += 0x01;
+       
+       VGMDataLen = VGMPos;
+       VGMHead.lngEOFOffset = VGMDataLen;
+       VGMHead.lngTotalSamples = VGMSmplL;
+       if (LoopOn)
+       {
+               VGMHead.lngLoopOffset = VGMHead.lngDataOffset;
+               VGMHead.lngLoopSamples = VGMHead.lngTotalSamples;
+       }
+       
+       SmplVal = VGMHead.lngDataOffset;
+       if (SmplVal > sizeof(VGM_HEADER))
+               SmplVal = sizeof(VGM_HEADER);
+       VGMHead.lngEOFOffset -= 0x04;
+       if (VGMHead.lngLoopOffset)
+               VGMHead.lngLoopOffset -= 0x1C;
+       VGMHead.lngDataOffset -= 0x34;
+       memcpy(&VGMData[0x00], &VGMHead, SmplVal);
+       
+       return;
+}