[
  {
    "path": ".gitattributes",
    "content": "*.dsp text eol=crlf\n*.dsw text eol=crlf\n*.sln text eol=crlf\n*.vcxproj* text eol=crlf\n"
  },
  {
    "path": ".gitignore",
    "content": "##################\n## Visual Studio 6\n##################\n\n# Build results\n[Dd]ebug/\n[Rr]elease/\n*.exe\n*.dll\n\n# Object files\n*.ilk\n*.obj\n*.pch\n*.pdb\n*.sbr\n*.tmp\n\n# Project cache files\n*.aps\n*.ncb\n*.opt\n*.sdf\n*.suo\n*.user\n\nThumbs.db\nehthumbs.db\nDesktop.ini\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: c\n\ncache: ccache\n\nbefore_install:\n  - cd VGMPlay\n  - if [[ \"$TRAVIS_OS_NAME\" == \"osx\" ]]; then brew update       ; fi\n  - if [[ \"$TRAVIS_OS_NAME\" == \"osx\" ]]; then brew install libao; fi\n  - if [[ \"$TRAVIS_OS_NAME\" == \"osx\" ]]; then brew install ccache; fi\n  - if [[ \"$TRAVIS_OS_NAME\" == \"osx\" ]]; then sed -i .bak 's/MACOSX = 0/MACOSX = 1/g' Makefile; fi\n\nos:\n  - linux\n  - osx\n\ncompiler:\n  - gcc\n\naddons:\n  apt:\n    packages:\n      - make \n      - gcc \n      - zlib1g-dev \n      - libao-dev\n      - libdbus-1-dev\n\nscript:\n  - make\n"
  },
  {
    "path": "README.md",
    "content": "# VGMPlay [![Build Status](https://travis-ci.org/vgmrips/vgmplay.svg?branch=master)](https://travis-ci.org/vgmrips/vgmplay)\n\nThe official and always up-to-date player for all [VGM](https://en.wikipedia.org/wiki/VGM_(file_format)) files.\n\nIn the future, the existing VGMPlay will be replaced by [libvgm](https://github.com/ValleyBell/libvgm), which is currently in development.\n\n## Contact\n\n* [VGMRips Forums](http://vgmrips.net/forum/index.php)\n* IRC: irc.digibase.ca #vgmrips\n\n## Compile VGMPlay under Windows\n\n### Using MS Visual Studio 6.0:\n\n1. Open `VGMPlay.dsw`.\n2. Build the project.\n3. Done.\n\n### Using later versions of MS Visual Studio:\n\n1. Open `VGMPlay.vcxproj`.\n2. Build the project.\n3. Done.\n\n### Using MinGW/MSYS:\n\n1. open MSYS and run `make WINDOWS=1` in VGMPlay's folder.\n2. Done.\n\nNote: You can compile it without MSYS, but you need to manually create\nthe OBJDIRS paths (or make them use the backslash '\\'), because mkdir fails\nat paths with a forward slash.\n\n## Compile VGMPlay under Linux\n\n1. [optional step] If you have libao installed, you can edit the \nMakefile to make VGMPlay use `libao` instead of `OSS`.\n2. run `make` in VGMPlay's folder\n3. Done. Optionally `sudo make install` and `sudo make play_install`.\n\n### Building on Ubuntu (16.04)\n\n#### Requirements\n\nThe following packages are needed in order to compile the binaries\n\n```sh\nsudo apt-get install make gcc zlib1g-dev libao-dev libdbus-1-dev\n```\n\n#### Building\n\n```sh\nmake\n```\n\n## Compile VGMPlay under macOS\n\n1. install libao by executing the line `brew install libao`\n2. run `make install MACOSX=1 DISABLE_HWOPL_SUPPORT=1` in VGMPlay's folder \n(Alternatively edit the Makefile to set those constants and just run `make`.)\n3. Done.\n\nThanks to grauw for macOS compilation instructions.\n\n## Compile VGMPlay under Android\n1. Install [Termux](https://github.com/termux/termux-app) on [F-Droid](https://f-droid.org/en/packages/com.termux/) or [GitHub](https://github.com/termux/termux-app/releases). Do not download Termux from Play Store for security and depreciation reasons\n2. Open Termux and do `pkg update`\n3. When you do pkg update, do `pkg install clang dbus git libao make pkg-config -y`\n4. After the installation is done, do `git clone https://github.com/vgmrips/vgmplay`\n5. After Done Cloning, do `cd vgmplay/VGMPlay`\n6. And then do `make`\n"
  },
  {
    "path": "VGMPlay/.gitignore",
    "content": "/obj\n/vgm2pcm\n/vgmplay\n/vgm2wav\nvgmplay.desktop\n"
  },
  {
    "path": "VGMPlay/ChipMapper.c",
    "content": "// ChipMapper.c - Handles Chip Write (including OPL Hardware Support)\n\n#include <stdio.h>\n#include <string.h>\n#include <math.h>\n#include \"stdbool.h\"\n\n//#define DISABLE_HW_SUPPORT\t// disable support for OPL hardware\n#ifdef __NetBSD__\t// Thanks to nextvolume\n#warning \"Disabling OPL Mapper functionality, current code does not work on NetBSD\"\n#define DISABLE_HW_SUPPORT\t// Current code does not work on NetBSD\n#endif\n\n#ifdef WIN32\n\n#include <conio.h>\n#include <windows.h>\t// for QueryPerformance###\n\n#else\n\n#ifndef DISABLE_HW_SUPPORT\n#include <unistd.h>\n#ifdef __APPLE__\n#include <architecture/i386/io.h>\n#else\n#include <sys/io.h>\n#endif\n#endif\t// DISABLE_HW_SUPPORT\n\n#include <time.h>\n#endif\n\n#ifdef __APPLE__\n#define ioperm(x,y,z)\n#define outb(x,y)\n#define inb(x)\n#endif\n\n#include \"chips/mamedef.h\"\n\n#include \"chips/ChipIncl.h\"\n\n#ifndef DISABLE_HW_SUPPORT\nunsigned char OpenPortTalk(void);\nvoid ClosePortTalk(void);\n\n#ifdef WIN32\n\nvoid outportb(unsigned short PortAddress, unsigned char byte);\nunsigned char inportb(unsigned short PortAddress);\n\n#endif\t// WIN32\n#endif\t// DISABLE_HW_SUPPORT\n\n#include \"ChipMapper.h\"\n\n#ifndef DISABLE_HW_SUPPORT\nINLINE UINT8 OPL_HW_GetStatus(void);\nINLINE void OPL_HW_WaitDelay(INT64 StartTime, float Delay);\n\n// SN76496 OPL Translaton\nvoid start_sn76496_opl(UINT8 ChipID, int clock, int stereo);\nvoid sn76496_write_opl(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid sn76496_stereo_opl(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid sn76496_refresh_t6w28_opl(UINT8 ChipID);\n\n// YM2413 OPL Translaton\nvoid start_ym2413_opl(UINT8 ChipID);\nvoid ym2413_w_opl(UINT8 ChipID, offs_t offset, UINT8 data);\n\n// Meka YM2413 OPL Translation\nint     FM_OPL_Init             (void *userdata);\nvoid    FM_OPL_Close            (void);\nvoid    FM_OPL_Write            (int Register, int Value);\n\n// AY8910 OPL Translation\nvoid ay8910_write_opl(UINT8 ChipID, UINT8 r, UINT8 v);\nvoid start_ay8910_opl(UINT8 ChipID, int clock, UINT8 chip_type);\n\n\nextern UINT8 OPL_MODE;\nextern UINT8 OPL_CHIPS;\n\nextern bool WINNT_MODE;\nextern UINT16 FMPort;\nextern UINT8 PlayingMode;\nextern bool FMBreakFade;\nextern bool FMOPL2Pan;\nextern float FinalVol;\n\n#ifdef WIN32\n#define INP_9X\t\t_inp\n#define OUTP_9X\t\t_outp\n#define INP_NT\t\tinportb\n#define OUTP_NT\t\toutportb\n#endif\n\n// Delays in usec (Port Reads - or microsec)\n#define DELAY_OPL2_REG\t 3.3f\n#define DELAY_OPL2_DATA\t23.0f\n#define DELAY_OPL3_REG\t 0.0f\n//#define DELAY_OPL3_DATA\t 0.28f\t// fine for ISA cards (like SoundBlaster 16)\n#define DELAY_OPL3_DATA\t 13.3f\t// required for PCI cards (CMI8738)\n#ifdef WIN32\nINT64 HWusTime;\n#endif\n\n#define YM2413_EC_DEFAULT\t0x00\n#define YM2413_EC_MEKA\t\t0x01\n\n\ntypedef struct chip_mapping_info\n{\n\tUINT8 ChipType;\n\tUINT8 ChipID;\n\tUINT8 RegBase;\n\tUINT8 ChnBase;\n\tUINT32 ChipOpt[0x10];\n} CHIP_MAP;\n\nUINT8 ChipCount = 0x00;\nUINT8 SelChip;\nUINT8 ChipArr[0x100];\nCHIP_MAP ChipMap[0x10];\nbool RegChnUsage[0x20];\nUINT8 OPLReg[0x200];\nUINT8 OPLRegBak[0x200];\nUINT8 OPLRegForce[0x200];\nbool SkipMode = false;\nbool OpenedFM = false;\n#endif\t// DISABLE_HW_SUPPORT\nUINT8 YM2413_EMU_CORE;\n\nUINT32 OptArr[0x10];\n\n#ifndef WIN32\nunsigned char OpenPortTalk(void)\n{\n#ifndef DISABLE_HW_SUPPORT\n\tint retval;\n\t\n\tretval = ioperm(FMPort, 0x04, 1);\n\t\n\treturn retval & 0xFF;\n#else\n\treturn 0xFF;\t// not supported\n#endif\n}\n\nvoid ClosePortTalk(void)\n{\n#ifndef DISABLE_HW_SUPPORT\n\tioperm(FMPort, 0x04, 0);\n#endif\n\t\n\treturn;\n}\n\n#elif defined(DISABLE_HW_SUPPORT)\n\nunsigned char OpenPortTalk(void)\n{\n\treturn 0xFF;\t// not supported\n}\n\nvoid ClosePortTalk(void)\n{\n\treturn;\n}\n#endif\t// WIN32\n\nvoid open_fm_option(UINT8 ChipType, UINT8 OptType, UINT32 OptVal)\n{\n\tOptArr[OptType & 0x0F] = OptVal;\n\t\n\treturn;\n}\n\nvoid opl_chip_reset(void)\n{\n#ifndef DISABLE_HW_SUPPORT\n\tUINT16 Reg;\n\tfloat FnlVolBak;\n\t\n\tFnlVolBak = FinalVol;\n\tFinalVol = 1.0f;\n\tmemset(OPLRegForce, 0x01, 0x200);\n\t\n\tOPL_HW_WriteReg(0x105, 0x01);\t// OPL3 Enable\n\tOPL_HW_WriteReg(0x001, 0x20);\t// Test Register\n\tOPL_HW_WriteReg(0x002, 0x00);\t// Timer 1\n\tOPL_HW_WriteReg(0x003, 0x00);\t// Timer 2\n\tOPL_HW_WriteReg(0x004, 0x00);\t// IRQ Mask Clear\n\tOPL_HW_WriteReg(0x104, 0x00);\t// 4-Op-Mode Disable\n\tOPL_HW_WriteReg(0x008, 0x00);\t// Keyboard Split\n\t\n\t// make sure all internal calulations finish sound generation\n\tfor (Reg = 0x00; Reg < 0x09; Reg ++)\n\t{\n\t\tOPL_HW_WriteReg(0x0C0 | Reg, 0x00);\t// silence all notes (OPL3)\n\t\tOPL_HW_WriteReg(0x1C0 | Reg, 0x00);\n\t}\n\tfor (Reg = 0x00; Reg < 0x16; Reg ++)\n\t{\n\t\tif ((Reg & 0x07) >= 0x06)\n\t\t\tcontinue;\n\t\tOPL_HW_WriteReg(0x040 | Reg, 0x3F);\t// silence all notes (OPL2)\n\t\tOPL_HW_WriteReg(0x140 | Reg, 0x3F);\n\t\t\n\t\tOPL_HW_WriteReg(0x080 | Reg, 0xFF);\t// set Sustain/Release Rate to FASTEST\n\t\tOPL_HW_WriteReg(0x180 | Reg, 0xFF);\n\t\tOPL_HW_WriteReg(0x060 | Reg, 0xFF);\n\t\tOPL_HW_WriteReg(0x160 | Reg, 0xFF);\n\t\t\n\t\tOPL_HW_WriteReg(0x020 | Reg, 0x00);\t// NULL the rest\n\t\tOPL_HW_WriteReg(0x120 | Reg, 0x00);\n\t\t\n\t\tOPL_HW_WriteReg(0x0E0 | Reg, 0x00);\n\t\tOPL_HW_WriteReg(0x1E0 | Reg, 0x00);\n\t}\n\tOPL_HW_WriteReg(0x0BD, 0x00);\t// Rhythm Mode\n\tfor (Reg = 0x00; Reg < 0x09; Reg ++)\n\t{\n\t\tOPL_HW_WriteReg(0x0B0 | Reg, 0x00);\t// turn all notes off (-> Release Phase)\n\t\tOPL_HW_WriteReg(0x1B0 | Reg, 0x00);\n\t\tOPL_HW_WriteReg(0x0A0 | Reg, 0x00);\n\t\tOPL_HW_WriteReg(0x1A0 | Reg, 0x00);\n\t}\n\t\n\t// although this would be a more proper reset, it sometimes produces clicks\n\t/*for (Reg = 0x020; Reg <= 0x0FF; Reg ++)\n\t\tOPL_HW_WriteReg(Reg, 0x00);\n\tfor (Reg = 0x120; Reg <= 0x1FF; Reg ++)\n\t\tOPL_HW_WriteReg(Reg, 0x00);*/\n\t\n\t// Now do a proper reset of all other registers.\n\tfor (Reg = 0x040; Reg < 0x0A0; Reg ++)\n\t{\n\t\tif ((Reg & 0x07) >= 0x06 || (Reg & 0x1F) >= 0x18)\n\t\t\tcontinue;\n\t\tOPL_HW_WriteReg(0x000 | Reg, 0x00);\n\t\tOPL_HW_WriteReg(0x100 | Reg, 0x00);\n\t}\n\tfor (Reg = 0x00; Reg < 0x09; Reg ++)\n\t{\n\t\tOPL_HW_WriteReg(0x0C0 | Reg, 0x30);\t// must be 30 to make OPL2 VGMs sound on OPL3\n\t\tOPL_HW_WriteReg(0x1C0 | Reg, 0x30);\t// if they don't send the C0 reg\n\t}\n\t\n\tmemset(OPLRegForce, 0x01, 0x200);\n\tFinalVol = FnlVolBak;\n#endif\t// DISABLE_HW_SUPPORT\n\t\n\treturn;\n}\n\nvoid open_real_fm(void)\n{\n#ifndef DISABLE_HW_SUPPORT\n\tUINT8 CurChip;\n\tCHIP_MAP* CurMap;\n\tUINT8 CurC2;\n\tbool OldSM;\n\t\n\t//SkipMode = false;\n\tOldSM = SkipMode;\n\topl_chip_reset();\n\tOpenedFM = true;\n\t\n\tfor (CurChip = 0x00; CurChip < ChipCount; CurChip ++)\n\t{\n\t\tSelChip = CurChip;\n\t\tCurMap = ChipMap + SelChip;\n\t\tswitch(CurMap->ChipType)\n\t\t{\n\t\tcase 0x00:\t// SN76496 and T6W28\n\t\t\tif (CurMap->ChipOpt[0x0F] & 0x80000000)\n\t\t\t{\n\t\t\t\t// Avoid Bugs\n\t\t\t\tCurMap->RegBase = (CurMap->ChipOpt[0x0F] >> 8) & 0xFF;\n\t\t\t\tCurMap->ChnBase = (CurMap->ChipOpt[0x0F] >> 0) & 0xFF;\n\t\t\t}\n\t\t\t\n\t\t\tstart_sn76496_opl(CurMap->ChipID, CurMap->ChipOpt[0x00], CurMap->ChipOpt[0x05]);\n\t\t\tif (CurMap->ChipOpt[0x00] & 0x80000000)\n\t\t\t{\n\t\t\t\t// Set up T6W28\n\t\t\t\tfor (CurC2 = 0x00; CurC2 < CurChip; CurC2 ++)\n\t\t\t\t{\n\t\t\t\t\tif (ChipMap[CurC2].ChipType == CurMap->ChipType)\n\t\t\t\t\t{\n\t\t\t\t\t\tCurMap->ChipOpt[0x0F] = 0x80000000 |\n\t\t\t\t\t\t\t\t\t\t\t\t(CurMap->RegBase << 8) | (CurMap->ChnBase << 0);\n\t\t\t\t\t\tCurMap->RegBase = ChipMap[CurC2].RegBase;\n\t\t\t\t\t\tCurMap->ChnBase = ChipMap[CurC2].ChnBase;\n\t\t\t\t\t\tsn76496_refresh_t6w28_opl(ChipMap[CurC2].ChipID);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 0x01:\t// YM2413\n\t\t\tswitch(YM2413_EMU_CORE)\n\t\t\t{\n\t\t\tcase YM2413_EC_DEFAULT:\n\t\t\t\tstart_ym2413_opl(CurMap->ChipID);\n\t\t\t\tbreak;\n\t\t\tcase YM2413_EC_MEKA:\n\t\t\t\tFM_OPL_Init(NULL);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 0x09:\t// YM3812\n\t\t\tbreak;\n\t\tcase 0x0A:\t// YM3526\n\t\t\tbreak;\n\t\tcase 0x0B:\t// Y8950\n\t\t\tbreak;\n\t\tcase 0x0C:\t// YMF262\n\t\t\tbreak;\n\t\tcase 0x0D:\t// YMF278B\n\t\t\tbreak;\n\t\tcase 0x12:\t// AY8910\n\t\t\tstart_ay8910_opl(CurMap->ChipID, CurMap->ChipOpt[0x00], CurMap->ChipOpt[0x01]);\n\t\t\tbreak;\n\t\t}\n\t}\n#endif\t// DISABLE_HW_SUPPORT\n\n\treturn;\n}\n\nvoid setup_real_fm(UINT8 ChipType, UINT8 ChipID)\n{\n#ifndef DISABLE_HW_SUPPORT\n\tCHIP_MAP* CurMap;\n\tUINT8 CurChip;\n\tUINT8 CurSet;\n\tUINT8 CurChn;\n\tbool ExitLoop;\n\t\n\tSelChip = ChipCount;\n\tChipArr[(ChipType << 1) | (ChipID & 0x01)] = SelChip;\n\tCurMap = ChipMap + SelChip;\n\tCurMap->ChipType = ChipType;\n\tCurMap->ChipID = ChipID & 0x7F;\n\t\n\tswitch(ChipType)\n\t{\n\tcase 0x00:\t// SN76496 and T6W28\n\tcase 0x12:\t// AY8910\n\t\tExitLoop = false;\n\t\tfor (CurSet = 0x00; CurSet < 0x02; CurSet ++)\n\t\t{\n\t\t\tfor (CurChn = 0x00; CurChn < 0x09; CurChn ++)\n\t\t\t{\n\t\t\t\tif (! RegChnUsage[(CurSet << 4) | CurChn])\n\t\t\t\t{\n\t\t\t\t\tExitLoop = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (ExitLoop)\n\t\t\t\tbreak;\n\t\t}\n\t\tCurSet %= 0x02;\n\t\tCurChn %= 0x09;\n\t\t\n\t\tCurMap->RegBase = CurSet;\n\t\tCurMap->ChnBase = CurChn;\n\t\tmemcpy(CurMap->ChipOpt, OptArr, 0x10 * sizeof(UINT32));\n\t\tCurMap->ChipOpt[0x0F] = 0x00;\n\t\tif (ChipType == 0x00)\n\t\t{\n\t\t\tfor (CurChn = 0x00; CurChn < 0x04; CurChn ++)\n\t\t\t{\n\t\t\t\tRegChnUsage[(CurMap->RegBase << 4) | (CurMap->ChnBase + CurChn)] = true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (CurChn = 0x00; CurChn < 0x03; CurChn ++)\n\t\t\t{\n\t\t\t\tRegChnUsage[(CurMap->RegBase << 4) | (CurMap->ChnBase + CurChn)] = true;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase 0x01:\t// YM2413\n\t\tCurMap->RegBase = 0x00;\n\t\tCurMap->ChnBase = 0x00;\n\t\t\n\t\tfor (CurChip = 0x00; CurChip < SelChip; CurChip ++)\n\t\t{\n\t\t\tif (ChipMap[CurChip].ChipType == 0x01)\n\t\t\t{\n\t\t\t\tCurMap->RegBase = 0x01;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tChipMap[CurChip].RegBase = 0x01;\n\t\t}\n\t\tfor (CurChn = 0x00; CurChn < 0x09; CurChn ++)\n\t\t{\n\t\t\tRegChnUsage[(CurMap->RegBase << 4) | CurChn] = true;\n\t\t}\n\t\tbreak;\n\tcase 0x09:\t// YM3812\n\t\tfor (CurSet = 0x00; CurSet < 0x02; CurSet ++)\n\t\t{\n\t\t\tif (! RegChnUsage[(CurSet << 4) | 0x00])\n\t\t\t\tbreak;\n\t\t}\n\t\tCurSet %= 0x02;\n\t\tCurMap->RegBase = CurSet;\n\t\tCurMap->ChnBase = 0x00;\n\t\tbreak;\n\tcase 0x0A:\t// YM3526\n\t\tfor (CurSet = 0x00; CurSet < 0x02; CurSet ++)\n\t\t{\n\t\t\tif (! RegChnUsage[(CurSet << 4) | 0x00])\n\t\t\t\tbreak;\n\t\t}\n\t\tCurSet %= 0x02;\n\t\tCurMap->RegBase = CurSet;\n\t\tCurMap->ChnBase = 0x00;\n\t\tbreak;\n\tcase 0x0B:\t// Y8950\n\t\tfor (CurSet = 0x00; CurSet < 0x02; CurSet ++)\n\t\t{\n\t\t\tif (! RegChnUsage[(CurSet << 4) | 0x00])\n\t\t\t\tbreak;\n\t\t}\n\t\tCurSet %= 0x02;\n\t\tCurMap->RegBase = CurSet;\n\t\tCurMap->ChnBase = 0x00;\n\t\tbreak;\n\tcase 0x0C:\t// YMF262\n\t\tCurMap->RegBase = 0x00;\n\t\tCurMap->ChnBase = 0x00;\n\t\tbreak;\n\tcase 0x0D:\t// YMF278B\n\t\tCurMap->RegBase = 0x00;\n\t\tCurMap->ChnBase = 0x00;\n\t\tbreak;\n\t}\n\tChipCount ++;\n#endif\t// DISABLE_HW_SUPPORT\n\t\n\treturn;\n}\n\nvoid close_real_fm(void)\n{\n#ifndef DISABLE_HW_SUPPORT\n\tUINT8 CurChip;\n\tUINT8 CurChn;\n\tUINT8 CurOp;\n\tUINT16 Reg;\n\tUINT8 RegOp;\n\tbool SoftFade;\n\t\n\tSoftFade = (FMBreakFade && FinalVol > 0.01f);\n\tfor (CurChip = 0x00; CurChip < 0x02; CurChip ++)\n\t{\n\t\tfor (CurChn = 0x00; CurChn < 0x09; CurChn ++)\n\t\t{\n\t\t\t// Make sure that the ReleaseRate takes effect ...\n\t\t\tfor (CurOp = 0x00; CurOp < 0x02; CurOp ++)\n\t\t\t{\n\t\t\t\tif (! CurOp && ! (OPLReg[(CurChip << 8) | (0xC0 | CurChn)] & 0x01))\n\t\t\t\t\tcontinue;\n\t\t\t\t\n\t\t\t\tRegOp = (CurChn / 0x03) * 0x08 | (CurChn % 0x03) + (CurOp * 0x03);\n\t\t\t\tReg = (CurChip << 8) | 0x80 | RegOp;\n\t\t\t\tif (SoftFade)\n\t\t\t\t{\n\t\t\t\t\tif ((OPLReg[Reg] & 0x0F) < 0x03)\t// Force a soft fading\n\t\t\t\t\t\tOPL_HW_WriteReg(Reg, (OPLReg[Reg] & 0xF0) | 0x04);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// stop sound immediately after Note-Off\n\t\t\t\t\tOPL_HW_WriteReg(Reg, (OPLReg[Reg] & 0xF0) | 0x0F);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// ... and turn off all notes.\n\t\t\tif (SoftFade)\n\t\t\t{\n\t\t\t\t// soft way (turn off and let fade)\n\t\t\t\tReg = (CurChip << 8) | (0xB0 | CurChn);\n\t\t\t\tOPL_HW_WriteReg(Reg, OPLReg[Reg] & ~0x20);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// hard way (turn off and set frequency to zero)\n\t\t\t\tReg = (CurChip << 8) | (0xA0 | CurChn);\n\t\t\t\tOPL_HW_WriteReg(Reg | 0x00, 0x00);\t// A0 - Frequency LSB\n\t\t\t\tOPL_HW_WriteReg(Reg | 0x10, 0x00);\t// B0 - Frequency MSB / Block / Key On\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Set Values that are compatible with Windows' FM Driver\n\t\tOPL_HW_WriteReg(0x104, 0x00);\t// 4-Op-Mode Disable\n\t\tOPL_HW_WriteReg(0x001, 0x00);\t// Wave Select Disable\n\t\tOPL_HW_WriteReg(0x002, 0x00);\t// Timer 1\n\t\tOPL_HW_WriteReg(0x003, 0x00);\t// Timer 2\n\t\tOPL_HW_WriteReg(0x004, 0x00);\t// IRQ mask clear\n\t\tOPL_HW_WriteReg(0x008, 0x00);\t// Keyboard Split\n\t\tOPL_HW_WriteReg(0x0BD, 0xC0);\t// Rhythm Mode\n\t}\n\tOpenedFM = false;\n\tChipCount = 0x00;\n\tmemset(RegChnUsage, 0x00, sizeof(bool) * 0x20);\n#endif\t// DISABLE_HW_SUPPORT\n\t\n\treturn;\n}\n\nvoid chip_reg_write(UINT8 ChipType, UINT8 ChipID,\n\t\t\t\t\tUINT8 Port, UINT8 Offset, UINT8 Data)\n{\n#ifndef DISABLE_HW_SUPPORT\n\tbool ModeFM;\n\tUINT8 CurChip;\n\t\n\tswitch(PlayingMode)\n\t{\n\tcase 0x00:\n\t\tModeFM = false;\n\t\tbreak;\n\tcase 0x01:\n\t\tModeFM = true;\n\t\tbreak;\n\tcase 0x02:\n\t\tModeFM = false;\n\t\tfor (CurChip = 0x00; CurChip < ChipCount; CurChip ++)\n\t\t{\n\t\t\tif (ChipMap[CurChip].ChipType == ChipType &&\n\t\t\t\tChipMap[CurChip].ChipID == ChipID)\n\t\t\t{\n\t\t\t\tModeFM = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t}\n\t\n\tif (! ModeFM)\n\t{\n#endif\t// DISABLE_HW_SUPPORT\n\t\tswitch(ChipType)\n\t\t{\n\t\tcase 0x00:\t// SN76496\n\t\t\tsn764xx_w(ChipID, Port, Data);\n\t\t\tbreak;\n\t\tcase 0x01:\t// YM2413\n\t\t\tym2413_w(ChipID, 0x00, Offset);\n\t\t\tym2413_w(ChipID, 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x02:\t// YM2612\n\t\t\tym2612_w(ChipID, (Port << 1) | 0x00, Offset);\n\t\t\tym2612_w(ChipID, (Port << 1) | 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x03:\t// YM2151\n\t\t\tym2151_w(ChipID, 0x00, Offset);\n\t\t\tym2151_w(ChipID, 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x04:\t// SegaPCM\n\t\t\tbreak;\n\t\tcase 0x05:\t// RF5C68\n\t\t\trf5c68_w(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x06:\t// YM2203\n\t\t\tym2203_w(ChipID, 0x00, Offset);\n\t\t\tym2203_w(ChipID, 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x07:\t// YM2608\n\t\t\tym2608_w(ChipID, (Port << 1) | 0x00, Offset);\n\t\t\tym2608_w(ChipID, (Port << 1) | 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x08:\t// YM2610/YM2610B\n\t\t\tym2610_w(ChipID, (Port << 1) | 0x00, Offset);\n\t\t\tym2610_w(ChipID, (Port << 1) | 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x09:\t// YM3812\n\t\t\tym3812_w(ChipID, 0x00, Offset);\n\t\t\tym3812_w(ChipID, 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x0A:\t// YM3526\n\t\t\tym3526_w(ChipID, 0x00, Offset);\n\t\t\tym3526_w(ChipID, 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x0B:\t// Y8950\n\t\t\ty8950_w(ChipID, 0x00, Offset);\n\t\t\ty8950_w(ChipID, 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x0C:\t// YMF262\n\t\t\tymf262_w(ChipID, (Port << 1) | 0x00, Offset);\n\t\t\tymf262_w(ChipID, (Port << 1) | 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x0D:\t// YMF278B\n\t\t\tymf278b_w(ChipID, (Port << 1) | 0x00, Offset);\n\t\t\tymf278b_w(ChipID, (Port << 1) | 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x0E:\t// YMF271\n\t\t\tymf271_w(ChipID, (Port << 1) | 0x00, Offset);\n\t\t\tymf271_w(ChipID, (Port << 1) | 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x0F:\t// YMZ280B\n\t\t\tymz280b_w(ChipID, 0x00, Offset);\n\t\t\tymz280b_w(ChipID, 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x10:\t// RF5C164\n\t\t\trf5c164_w(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x11:\t// PWM\n\t\t\tpwm_chn_w(ChipID, Port, (Offset << 8) | (Data << 0));\n\t\t\tbreak;\n\t\tcase 0x12:\t// AY8910\n\t\t\tayxx_w(ChipID, 0x00, Offset);\n\t\t\tayxx_w(ChipID, 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x13:\t// GameBoy\n\t\t\tgb_sound_w(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x14:\t// NES APU\n\t\t\tnes_w(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x15:\t// MultiPCM\n\t\t\tmultipcm_w(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x16:\t// UPD7759\n\t\t\tupd7759_write(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x17:\t// OKIM6258\n\t\t\tokim6258_write(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x18:\t// OKIM6295\n\t\t\tokim6295_w(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x19:\t// K051649 / SCC1\n\t\t\tk051649_w(ChipID, (Port << 1) | 0x00, Offset);\n\t\t\tk051649_w(ChipID, (Port << 1) | 0x01, Data);\n\t\t\tbreak;\n\t\tcase 0x1A:\t// K054539\n\t\t\tk054539_w(ChipID, (Port << 8) | (Offset << 0), Data);\n\t\t\tbreak;\n\t\tcase 0x1B:\t// HuC6280\n\t\t\tc6280_w(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x1C:\t// C140\n\t\t\tc140_w(ChipID, (Port << 8) | (Offset << 0), Data);\n\t\t\tbreak;\n\t\tcase 0x1D:\t// K053260\n\t\t\tk053260_w(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x1E:\t// Pokey\n\t\t\tpokey_w(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x1F:\t// QSound\n\t\t\tqsound_w(ChipID, 0x00, Port);\t// Data MSB\n\t\t\tqsound_w(ChipID, 0x01, Offset);\t// Data LSB\n\t\t\tqsound_w(ChipID, 0x02, Data);\t// Register\n\t\t\tbreak;\n\t\tcase 0x20:\t// YMF292/SCSP\n\t\t\tscsp_w(ChipID, (Port << 8) | (Offset << 0), Data);\n\t\t\tbreak;\n\t\tcase 0x21:\t// WonderSwan\n\t\t\tws_audio_port_write(ChipID, 0x80 | Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x22:\t// VSU\n\t\t\tVSU_Write(ChipID, (Port << 8) | (Offset << 0), Data);\n\t\t\tbreak;\n\t\tcase 0x23:\t// SAA1099\n\t\t\tsaa1099_control_w(ChipID, 0, Offset);\n\t\t\tsaa1099_data_w(ChipID, 0, Data);\n\t\t\tbreak;\n\t\tcase 0x24:\t// ES5503\n\t\t\tes5503_w(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x25:\t// ES5506\n\t\t\tif (Port & 0x80)\n\t\t\t\tes550x_w16(ChipID, Port & 0x7F, (Offset << 8) | (Data << 0));\n\t\t\telse\n\t\t\t\tes550x_w(ChipID, Port, Data);\n\t\t\tbreak;\n\t\tcase 0x26:\t// X1-010\n\t\t\tseta_sound_w(ChipID, (Port << 8) | (Offset << 0), Data);\n\t\t\tbreak;\n\t\tcase 0x27:\t// C352\n\t\t\tc352_w(ChipID, Port, (Offset << 8) | (Data << 0));\n\t\t\tbreak;\n\t\tcase 0x28:\t// GA20\n\t\t\tirem_ga20_w(ChipID, Offset, Data);\n\t\t\tbreak;\n//\t\tcase 0x##:\t// OKIM6376\n//\t\t\tbreak;\n\t\t}\n#ifndef DISABLE_HW_SUPPORT\n\t}\n\telse\n\t{\n\t\tif (! OpenedFM)\n\t\t\treturn;\n\t\t\n\t\tSelChip = ChipArr[(ChipType << 1) | (ChipID & 0x01)];\n\t\tswitch(ChipType)\n\t\t{\n\t\tcase 0x00:\t// SN76496\n\t\t\tswitch(Port)\n\t\t\t{\n\t\t\tcase 0x00:\n\t\t\t\tsn76496_write_opl(ChipID, 0x00, Data);\n\t\t\t\tbreak;\n\t\t\tcase 0x01:\n\t\t\t\tsn76496_stereo_opl(ChipID, 0x00, Data);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 0x01:\t// YM2413\n\t\t\tswitch(YM2413_EMU_CORE)\n\t\t\t{\n\t\t\tcase YM2413_EC_DEFAULT:\n\t\t\t\tym2413_w_opl(ChipID, 0x00, Offset);\n\t\t\t\tym2413_w_opl(ChipID, 0x01, Data);\n\t\t\t\tbreak;\n\t\t\tcase YM2413_EC_MEKA:\n\t\t\t\tFM_OPL_Write(Offset, Data);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 0x09:\t// YM3812\n\t\t\tif ((Offset & 0xF0) == 0xC0 && (! FMOPL2Pan || ! (Data & 0x30)))\n\t\t\t\tData |= 0x30;\n\t\t\telse if ((Offset & 0xF0) == 0xE0)\n\t\t\t\tData &= 0xF3;\n\t\t\tOPL_RegMapper((ChipID << 8) | Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x0A:\t// YM3526\n\t\t\tif ((Offset & 0xF0) == 0xC0 && (! FMOPL2Pan || ! (Data & 0x30)))\n\t\t\t\tData |= 0x30;\n\t\t\telse if ((Offset & 0xF0) == 0xE0)\n\t\t\t\tData &= 0xF0;\n\t\t\tOPL_RegMapper((ChipID << 8) | Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x0B:\t// Y8950\n\t\t\tif (Offset == 0x07 || (Offset >= 0x09 && Offset <= 0x17))\n\t\t\t\tbreak;\n\t\t\tif ((Offset & 0xF0) == 0xC0 && (! FMOPL2Pan || ! (Data & 0x30)))\n\t\t\t\tData |= 0x30;\n\t\t\telse if ((Offset & 0xF0) == 0xE0)\n\t\t\t\tData &= 0xF0;\n\t\t\tOPL_RegMapper((ChipID << 8) | Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x0C:\t// YMF262\n\t\t\tOPL_RegMapper((Port << 8) | Offset, Data);\n\t\t\tbreak;\n\t\tcase 0x12:\t// AY8910\n\t\t\tay8910_write_opl(ChipID, Offset, Data);\n\t\t\tbreak;\n\t\t}\n\t}\n#endif\t// DISABLE_HW_SUPPORT\n\treturn;\n}\n\nvoid OPL_Hardware_Detecton(void)\n{\n#ifndef DISABLE_HW_SUPPORT\n\tUINT8 Status1;\n\tUINT8 Status2;\n#ifdef WIN32\n\t//LARGE_INTEGER TempQud1;\n\t//LARGE_INTEGER TempQud2;\n\tLARGE_INTEGER TempQudFreq;\n\t//__int64 TempQudMid;\n\t\n\tHWusTime = 0;\n\tif (! WINNT_MODE)\n\t\tStatus1 = 0x00;\n\telse\n#endif\n\t\tStatus1 = OpenPortTalk();\n\t\n\tif (Status1)\n\t{\n\t\tOPL_MODE = 0x00;\n\t\tprintf(\"Error opening FM Port! Permission denied!\\n\");\n\t\tgoto FinishDetection;\n\t}\n\t\n\tOPL_MODE = 0x02;\t// must be set to activate OPL2-Delays\n\t\n\t// OPL2 Detection\n\tOPL_HW_WriteReg(0x04, 0x60);\n\tOPL_HW_WriteReg(0x04, 0x80);\n\tStatus1 = OPL_HW_GetStatus();\n\tStatus1 &= 0xE0;\n\t\n\tOPL_HW_WriteReg(0x02, 0xFF);\n\tOPL_HW_WriteReg(0x04, 0x21);\n\tOPL_HW_WaitDelay(0, 80);\n\t\n\tStatus2 = OPL_HW_GetStatus();\n\tStatus2 &= 0xE0;\n\t\n\tOPL_HW_WriteReg(0x04, 0x60);\n\tOPL_HW_WriteReg(0x04, 0x80);\n\t\n\tif (! ((Status1 == 0x00) && (Status2 == 0xC0)))\n\t{\n\t\t// Detection failed\n\t\tOPL_MODE = 0x00;\n\t\tprintf(\"No OPL Chip detected!\\n\");\n\t\tgoto FinishDetection;\n\t}\n\t\n\t// OPL3 Detection\n\tStatus1 = OPL_HW_GetStatus();\n\tStatus1 &= 0x06;\n\tif (! Status1)\n\t{\n\t\tOPL_MODE = 0x03;\n\t\tOPL_CHIPS = 0x01;\n\t\tprintf(\"OPL 3 Chip found.\\n\");\n\t\tgoto FinishDetection;\n\t}\n\t\n\t// OPL2 Dual Chip Detection\n\tOPL_HW_WriteReg(0x104, 0x60);\n\tOPL_HW_WriteReg(0x104, 0x80);\n\tStatus1 = OPL_HW_GetStatus();\n\tStatus1 &= 0xE0;\n\t\n\tOPL_HW_WriteReg(0x102, 0xFF);\n\tOPL_HW_WriteReg(0x104, 0x21);\n\tOPL_HW_WaitDelay(0, 80);\n\t\n\tStatus2 = OPL_HW_GetStatus();\n\tStatus2 &= 0xE0;\n\t\n\tOPL_HW_WriteReg(0x104, 0x60);\n\tOPL_HW_WriteReg(0x104, 0x80);\n\t\n\tif ((Status1 == 0x00) && (Status2 == 0xC0))\n\t{\n\t\tOPL_CHIPS = 0x02;\n\t\tprintf(\"Dual OPL 2 Chip found.\\n\");\n\t}\n\telse\n\t{\n\t\tOPL_CHIPS = 0x01;\n\t\tprintf(\"OPL 2 Chip found.\\n\");\n\t}\n\t\nFinishDetection:\n#ifdef WIN32\n\t// note CPU time needed for 1 us\n\tQueryPerformanceFrequency(&TempQudFreq);\n\tHWusTime = TempQudFreq.QuadPart / 1000000;\n\t\n\t/*QueryPerformanceCounter(&TempQud1);\n\tOPL_HW_GetStatus();\n\tQueryPerformanceCounter(&TempQud2);\n\tTempQudMid = TempQud2.QuadPart - TempQud1.QuadPart;\n\t\n\tQueryPerformanceCounter(&TempQud1);\n\tOPL_HW_GetStatus();\n\tQueryPerformanceCounter(&TempQud2);\n\tTempQudMid += TempQud2.QuadPart - TempQud1.QuadPart;\n\t\n\tHWusTime = TempQudMid / 2;\n\tprintf(\"Port Read Cycles: %I64u\\tMSec Cycles: %I64u\\n\", HWusTime,\n\t\t\tTempQudFreq.QuadPart / 1000);\n\tprintf(\"us per ms: %I64u\\n\", TempQudFreq.QuadPart / (HWusTime * 1000));\n\tHWusTime = TempQudFreq.QuadPart / 1000000;*/\n\t\n\tif (WINNT_MODE)\n#endif\n\t\tClosePortTalk();\n#endif\t// DISABLE_HW_SUPPORT\n\t\n\treturn;\n}\n\n#ifndef DISABLE_HW_SUPPORT\nINLINE UINT8 OPL_HW_GetStatus(void)\n{\n\tUINT8 RetStatus;\n\t\n#ifdef WIN32\n\tswitch(WINNT_MODE)\n\t{\n\tcase false:\t// Windows 95/98/ME\n\t\tRetStatus = INP_9X(FMPort);\n\t\tbreak;\n\tcase true:\t// Windows NT/2000/XP/...\n\t\tRetStatus = INP_NT(FMPort);\n\t\tbreak;\n\t}\n#else\n\tRetStatus = inb(FMPort);\n#endif\n\t\n\treturn RetStatus;\n}\n\nINLINE void OPL_HW_WaitDelay(INT64 StartTime, float Delay)\n{\n#ifdef WIN32\n\tLARGE_INTEGER CurTime;\n\tINT64 EndTime;\n\tUINT16 CurUS;\n\t\n\t// waits Delay us\n\tif (HWusTime)\n\t{\n\t\tOPL_HW_GetStatus();\t// read once, just to be safe\n\t\tEndTime = (INT64)(StartTime + HWusTime * Delay);\n\t\tdo\n\t\t{\n\t\t\tQueryPerformanceCounter(&CurTime);\n\t\t} while(CurTime.QuadPart < EndTime);\n\t}\n\telse if (Delay >= 1.0f)\n\t{\n\t\tfor (CurUS = 0x00; CurUS < Delay; CurUS ++)\n\t\t\tOPL_HW_GetStatus();\n\t}\n\telse\n\t{\n\t\tOPL_HW_GetStatus();\t// read once, just to be safe\n\t}\n\n#else\n\n\tstruct timespec NanoTime;\n\t\n\tOPL_HW_GetStatus();\t// read once, then wait should work\n\tif (Delay >= 1.0f)\n\t\tDelay -= 1.0f;\n\t\n\t// waits Delay us\n\tNanoTime.tv_sec = 0;\n\t// xx-- nsec should be 1000 * Delay, but somehow the resulting Delay is too short --xx\n\tNanoTime.tv_nsec = 1000 * Delay;\n\tnanosleep(&NanoTime, NULL);\n#endif\n\t\n\treturn;\n}\n#endif\t// DISABLE_HW_SUPPORT\n\nvoid OPL_HW_WriteReg(UINT16 Reg, UINT8 Data)\n{\n#ifndef DISABLE_HW_SUPPORT\n\tUINT16 Port;\n#ifdef WIN32\n\tLARGE_INTEGER StartTime;\n#endif\n\tUINT8 DataOld;\n\tUINT8 OpNum;\n\tUINT8 TempVol;\n\tfloat TempSng;\n\t\n\tReg &= 0x01FF;\n\t\n\tif (SkipMode)\n\t{\n\t\tOPLReg[Reg] = Data;\n\t\treturn;\n\t}\n\t\n\t// Register = Rhythm Control and RhmythmOn-Bit changed\n\t// -> set/reset Modulator Volume of Channels 7 and 8 (Volume for HH/CYM)\n\tif (Reg == 0x0BD && (OPLReg[Reg] ^ Data) & 0x20 && FinalVol != 1.0f)\n\t{\n\t\tOPLReg[Reg] = Data;\n\t\tOPLRegForce[Reg] = 0x01;\n\t\t\n\t\tOPL_HW_WriteReg(0x51, OPLReg[0x51]);\t// Ch 7 Mod TL\n\t\tOPL_HW_WriteReg(0x52, OPLReg[0x52]);\t// Ch 8 Mod TL\n\t}\n\t\n\tDataOld = Data;\n\tif ((Reg & 0xE0) == 0x40)\n\t{\n\t\tOpNum = (Reg & 0x07) / 0x03;\t// Modulator 0x00, Carrier 0x01\n\t\tTempVol = ((Reg & 0x18) >> 3) * 0x03 + ((Reg & 0x07) % 0x03);\n\t\t\n\t\tif ((OPLReg[(Reg & 0x100) | 0xC0 | TempVol] & 0x01))\n\t\t\tOpNum = 0x01;\t// Additive Syntheses - affects final volume\n\t\tif (! (Reg & 0x100) && TempVol >= 0x07 && (OPLReg[0xBD] & 0x20))\n\t\t\tOpNum = 0x01;\t// used as Volume for Rhythm: Hi-Hat / Cymbal\n\t\tif (OpNum == 0x01 && FinalVol != 1.0f)\n\t\t{\n\t\t\tTempVol = Data & 0x3F;\n\t\t\tTempSng = (float)pow(2.0, -TempVol / 8.0);\n\t\t\tTempSng *= FinalVol;\n\t\t\tif (TempSng > 0.0f)\n\t\t\t\tTempSng = (float)(-8.0 * log(TempSng) / log(2.0));\n\t\t\telse\n\t\t\t\tTempSng = 64.0f;\n\t\t\tif (TempSng < 0.0f)\n\t\t\t\tTempVol = 0x00;\n\t\t\telse if (TempSng >= 64.0f)\n\t\t\t\tTempVol = 0x3F;\n\t\t\telse\n\t\t\t\tTempVol = (UINT8)TempSng;\n\t\t\t\n\t\t\tData = (Data & 0xC0) | TempVol;\n\t\t}\n\t}\n\tif (Data == DataOld && Data == OPLReg[Reg] && ! OPLRegForce[Reg])\n\t\treturn;\t// only write neccessary registers (avoid spamming)\n\tOPLReg[Reg] = DataOld;\n\tOPLRegForce[Reg] = (Data != DataOld) ? 0x01 : 0x00;\t// force next write\n\t\n\tPort = (Reg & 0x100) ? (FMPort + 0x02) : (FMPort + 0x00);\n\t\n\t// 1. Set Register\n\t// 2. wait some time (short delay)\n\t// 3. Write Data\n\t// 4. wait some time (long delay)\n#ifdef WIN32\n\tQueryPerformanceCounter(&StartTime);\n\tif (! WINNT_MODE)\t// Windows 95/98/ME\n\t\tOUTP_9X(Port + 0x00, Reg & 0xFF);\n\telse\t\t\t\t// Windows NT/2000/XP/...\n\t\tOUTP_NT(Port + 0x00, Reg & 0xFF);\n\tswitch(OPL_MODE)\n\t{\n\tcase 0x02:\n\t\tOPL_HW_WaitDelay(StartTime.QuadPart, DELAY_OPL2_REG);\n\t\tbreak;\n\tcase 0x03:\n\t\tOPL_HW_WaitDelay(StartTime.QuadPart, DELAY_OPL3_REG);\n\t\tbreak;\n\t}\n#else\n\toutb(Reg & 0xFF, Port + 0x00);\n\tswitch(OPL_MODE)\n\t{\n\tcase 0x02:\n\t\tOPL_HW_WaitDelay(0, DELAY_OPL2_REG);\n\t\tbreak;\n\tcase 0x03:\n\t\tOPL_HW_WaitDelay(0, DELAY_OPL3_REG);\n\t\tbreak;\n\t}\n#endif\t// WIN32\n\t\n#ifdef WIN32\n\tQueryPerformanceCounter(&StartTime);\n\tif (! WINNT_MODE)\t// Windows 95/98/ME\n\t\tOUTP_9X(Port + 0x01, Data);\n\telse\t\t\t\t// Windows NT/2000/XP/...\n\t\tOUTP_NT(Port + 0x01, Data);\n\tswitch(OPL_MODE)\n\t{\n\tcase 0x02:\n\t\tOPL_HW_WaitDelay(StartTime.QuadPart, DELAY_OPL2_DATA);\n\t\tbreak;\n\tcase 0x03:\n\t\tOPL_HW_WaitDelay(StartTime.QuadPart, DELAY_OPL3_DATA);\n\t\tbreak;\n\t}\n#else\n\toutb(Data, Port + 0x01);\n\tswitch(OPL_MODE)\n\t{\n\tcase 0x02:\n\t\tOPL_HW_WaitDelay(0, DELAY_OPL2_DATA);\n\t\tbreak;\n\tcase 0x03:\n\t\tOPL_HW_WaitDelay(0, DELAY_OPL3_DATA);\n\t\tbreak;\n\t}\n#endif\t// WIN32\n#endif\t// DISABLE_HW_SUPPORT\n\t\n\treturn;\n}\n\nvoid OPL_RegMapper(UINT16 Reg, UINT8 Data)\n{\n#ifndef DISABLE_HW_SUPPORT\n\tUINT16 NewReg;\n\tUINT8 RegType;\n\tUINT8 Grp;\n\tUINT8 Chn;\n\tUINT8 Slot;\n\tUINT8 RegOp;\n\t\n\tswitch(Reg & 0xE0)\n\t{\n\tcase 0x00:\n\t\tRegType = 0x00;\n\t\tbreak;\n\tcase 0x20:\n\tcase 0x40:\n\tcase 0x60:\n\tcase 0x80:\n\tcase 0xE0:\n\t\tif ((Reg & 0x07) < 0x06 && ! ((Reg & 0x18) == 0x18))\n\t\t\tRegType = 0x01;\n\t\telse\n\t\t\tRegType = 0x00;\n\t\tbreak;\n\tcase 0xA0:\n\t\tif ((Reg & 0x0F) < 0x09)\n\t\t\tRegType = 0x02;\n\t\telse\n\t\t\tRegType = 0x00;\n\t\tbreak;\n\tcase 0xC0:\n\t\tif ((Reg & 0x1F) < 0x09)\n\t\t\tRegType = 0x02;\n\t\telse\n\t\t\tRegType = 0x00;\n\t\tbreak;\n\t}\n\t\n\tGrp = (Reg & 0x100) >> 8;\n\tswitch(RegType)\n\t{\n\tcase 0x01:\n\t\tChn = ((Reg & 0x18) >> 3) * 0x03 + ((Reg & 0x07) % 0x03);\n\t\tSlot = (Reg & 0x07) / 0x03;\n\t\tbreak;\n\tcase 0x02:\n\t\tChn = Reg & 0x0F;\n\t\tbreak;\n\t}\n\t\n\tGrp += ChipMap[SelChip].RegBase;\tGrp %= 0x02;\n\tChn += ChipMap[SelChip].ChnBase;\tChn %= 0x09;\n\t\n\tswitch(RegType)\n\t{\n\tcase 0x00:\n\t\tNewReg = (Grp << 8) | (Reg & 0xFF);\n\t\tbreak;\n\tcase 0x01:\n\t\tRegOp = (Chn / 0x03) * 0x08 | ((Slot * 0x03) + (Chn % 0x03));\n\t\tNewReg = (Grp << 8) | (Reg & 0xE0) | RegOp;\n\t\tbreak;\n\tcase 0x02:\n\t\tNewReg = (Grp << 8) | (Reg & 0xF0) | Chn;\n\t\tbreak;\n\t}\n\t\n\tOPL_HW_WriteReg(NewReg, Data);\n#endif\t// DISABLE_HW_SUPPORT\n\t\n\treturn;\n}\n\nvoid RefreshVolume()\n{\n#ifndef DISABLE_HW_SUPPORT\n\tUINT8 CurChip;\n\tUINT8 CurChn;\n\tUINT16 RegVal;\n\t\n\tfor (CurChip = 0x00; CurChip < 0x02; CurChip ++)\n\t{\n\t\tfor (CurChn = 0x00; CurChn < 0x09; CurChn ++)\n\t\t{\n\t\t\tRegVal = (CurChip << 8) | 0x40 | (CurChn / 0x03) * 0x08 | (CurChn % 0x03);\n\t\t\tOPL_HW_WriteReg(RegVal + 0x00, OPLReg[RegVal + 0x00]);\n\t\t\tOPL_HW_WriteReg(RegVal + 0x03, OPLReg[RegVal + 0x03]);\n\t\t}\n\t}\n\t\n\treturn;\n#endif\n}\n\nvoid StartSkipping(void)\n{\n#ifndef DISABLE_HW_SUPPORT\n\tif (SkipMode)\n\t\treturn;\n\t\n\tSkipMode = true;\n\tmemcpy(OPLRegBak, OPLReg, 0x200);\n#endif\n\t\n\treturn;\n}\n\nvoid StopSkipping(void)\n{\n#ifndef DISABLE_HW_SUPPORT\n\tUINT16 Reg;\n\tUINT16 OpReg;\n\tUINT8 RRBuffer[0x40];\n\t\n\tif (! SkipMode)\n\t\treturn;\n\t\n\tSkipMode = false;\n\t\n\t// At first, turn all notes off that need it\n\tmemcpy(RRBuffer + 0x00, &OPLReg[0x080], 0x20);\n\tmemcpy(RRBuffer + 0x20, &OPLReg[0x180], 0x20);\n\tfor (Reg = 0xB0; Reg < 0xB9; Reg ++)\n\t{\n\t\tOpReg = Reg & 0x0F;\n\t\tOpReg = (OpReg / 3) * 0x08 + (OpReg % 3);\n\t\tif (! (OPLReg[0x100 | Reg] & 0x20))\n\t\t{\n\t\t\tOPL_HW_WriteReg(0x180 + OpReg, (OPLReg[0x180 + OpReg] & 0xF0) | 0x0F);\n\t\t\tOPL_HW_WriteReg(0x183 + OpReg, (OPLReg[0x183 + OpReg] & 0xF0) | 0x0F);\n\t\t\tOPLRegForce[0x180 + OpReg] |= 0x01;\n\t\t\tOPLRegForce[0x183 + OpReg] |= 0x01;\n\t\t\t\n\t\t\tOPLRegForce[0x100 | Reg] |= (OPLReg[0x100 | Reg] != OPLRegBak[0x100 | Reg]);\n\t\t\tOPL_HW_WriteReg(0x100 | Reg, OPLReg[0x100 | Reg]);\n\t\t}\n\t\tif (! (OPLReg[0x000 | Reg] & 0x20))\n\t\t{\n\t\t\tOPL_HW_WriteReg(0x080 + OpReg, (OPLReg[0x080 + OpReg] & 0xF0) | 0x0F);\n\t\t\tOPL_HW_WriteReg(0x083 + OpReg, (OPLReg[0x083 + OpReg] & 0xF0) | 0x0F);\n\t\t\tOPLRegForce[0x080 + OpReg] |= 0x01;\n\t\t\tOPLRegForce[0x083 + OpReg] |= 0x01;\n\t\t\t\n\t\t\tOPLRegForce[0x000 | Reg] |= (OPLReg[0x000 | Reg] != OPLRegBak[0x000 | Reg]);\n\t\t\tOPL_HW_WriteReg(0x000 | Reg, OPLReg[0x000 | Reg]);\n\t\t}\n\t}\n\tmemcpy(&OPLReg[0x080], RRBuffer + 0x00, 0x20);\n\tmemcpy(&OPLReg[0x180], RRBuffer + 0x20, 0x20);\n\t\n\t// Now the actual save restore.\n\tReg = 0x105;\t// OPL3 Enable/Disable - this must be the very first thing sent\n\tOPLRegForce[Reg] |= (OPLReg[Reg] != OPLRegBak[Reg]);\n\tOPL_HW_WriteReg(Reg, OPLReg[Reg]);\n\t\n\t// Registers 0x00 to 0x1F and 0x100 to 0x11F MUST be sent first\n\tfor (Reg = 0x00; Reg < 0x20; Reg ++)\n\t{\n\t\t// Write Port 1 first, so that Port 0 writes override them, if OPL3 mode is disabled\n\t\tOPLRegForce[0x100 | Reg] |= (OPLReg[0x100 | Reg] != OPLRegBak[0x100 | Reg]);\n\t\tOPL_HW_WriteReg(0x100 | Reg, OPLReg[0x100 | Reg]);\n\t\tOPLRegForce[0x000 | Reg] |= (OPLReg[0x000 | Reg] != OPLRegBak[0x000 | Reg]);\n\t\tOPL_HW_WriteReg(0x000 | Reg, OPLReg[0x000 | Reg]);\n\t}\n\t\n\tReg = 0x200;\n\tdo\n\t{\n\t\tReg --;\n\t\tOPLRegForce[Reg] |= (OPLReg[Reg] != OPLRegBak[Reg]);\n\t\tOPL_HW_WriteReg(Reg, OPLReg[Reg]);\n\t\t\n\t\tif ((Reg & 0xFF) == 0xC0)\n\t\t\tReg -= 0x20;\t// Skip the frequency-registers\n\t\tif ((Reg & 0xFF) == 0x20)\n\t\t\tReg -= 0x20;\t// Skip the registers that are already sent\n\t} while(Reg);\n\t\n\tfor (Reg = 0xA0; Reg < 0xC0; Reg ++)\n\t{\n\t\t// Writing to BA/BB on my YMF744 is like writing to B8/B9, so I need to filter such\n\t\t// writes out.\n\t\tif ((Reg & 0x0F) >= 0x09)\n\t\t\tcontinue;\n\t\tOPLRegForce[0x100 | Reg] |= (OPLReg[0x100 | Reg] != OPLRegBak[0x100 | Reg]);\n\t\tOPL_HW_WriteReg(0x100 | Reg, OPLReg[0x100 | Reg]);\n\t\tOPLRegForce[0x000 | Reg] |= (OPLReg[0x000 | Reg] != OPLRegBak[0x000 | Reg]);\n\t\tOPL_HW_WriteReg(0x000 | Reg, OPLReg[0x000 | Reg]);\n\t}\n\t\n\tReg = 0x0BD;\t// Rhythm Register / Vibrato/Tremolo Depth\n\tOPLRegForce[Reg] |= (OPLReg[Reg] != OPLRegBak[Reg]);\n\tOPL_HW_WriteReg(Reg, OPLReg[Reg]);\n#endif\n\t\n\treturn;\n}\n\nvoid ym2413opl_set_emu_core(UINT8 Emulator)\n{\n\tYM2413_EMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/ChipMapper.h",
    "content": "void open_fm_option(UINT8 ChipType, UINT8 OptType, UINT32 OptVal);\nvoid opl_chip_reset(void);\nvoid open_real_fm(void);\nvoid reset_real_fm(void);\nvoid setup_real_fm(UINT8 ChipType, UINT8 ChipID);\nvoid close_real_fm(void);\nvoid chip_reg_write(UINT8 ChipType, UINT8 ChipID, UINT8 Port, UINT8 Offset, UINT8 Data);\nvoid OPL_Hardware_Detecton(void);\nvoid OPL_HW_WriteReg(UINT16 Reg, UINT8 Data);\nvoid OPL_RegMapper(UINT16 Reg, UINT8 Data);\nvoid RefreshVolume(void);\nvoid StartSkipping(void);\nvoid StopSkipping(void);\nvoid ym2413opl_set_emu_core(UINT8 Emulator);\n"
  },
  {
    "path": "VGMPlay/Makefile",
    "content": "########################\n#\n# VGMPlay Makefile\n# (for GNU Make 3.81)\n#\n########################\n\n# TODO: Make this look less horrible.\n\n# (notice that you can just pass these as arguments when running make)\n\n# set to 1 if you build on Windows using MinGW.\nifndef WINDOWS\nWINDOWS = 0\nendif\n\n# set to 1 if you build on Mac OSX\nifndef MACOSX\nMACOSX = 0\nendif\n\nifeq ($(WINDOWS), 1)\n# no libAO for Windows\nUSE_LIBAO = 0\nendif\nifeq ($(MACOSX), 1)\n# Mac OSX requires libAO\nUSE_LIBAO = 1\nendif\n\n# disable Hardware OPL Support [enabled by default]\nifndef DISABLE_HWOPL_SUPPORT\nDISABLE_HWOPL_SUPPORT = 1\nendif\n\n# set to 1 if you want to use libao instead of OSS for sound streaming under Linux [enabled by default]\nifndef USE_LIBAO\nUSE_LIBAO = 1\nendif\n\n# set to 1 for debug builds\nifndef DEBUG\nDEBUG = 0\nendif\n\n# set to 1 for swprintf fix on older MinGW versions\nifndef OLD_SWPRINTF\nOLD_SWPRINTF = 0\nendif\n\n# Byte Order\n#   0 = undefined (use endian-safe code, might be slightly slower)\n#   1 = Little Endian (Intel) [default]\n#   2 = Big Endian (Motorola)\nifndef BYTE_ORDER\nBYTE_ORDER = 1\nendif\n\n# set to 0 to compile without dbus support on linux\nifndef USE_DBUS\nUSE_DBUS = 1\nendif\n\nifeq ($(WINDOWS), 1)\nUSE_DBUS = 0\nendif\nifeq ($(MACOSX), 1)\nUSE_DBUS = 0\nendif\n\nCC = gcc\nifndef PREFIX\nPREFIX = /usr/local\n#PREFIX = $(HOME)/.local\nendif\nMANPREFIX = $(PREFIX)/share/man\n\n# -- VGMPlay specific Compile Flags --\nMAINFLAGS := -DCONSOLE_MODE -DADDITIONAL_FORMATS -DSET_CONSOLE_TITLE\nifeq ($(WINDOWS), 1)\n# MinGW defines __WINDOWS__, Visual Studio defines WIN32\nMAINFLAGS += -DWIN32\nendif\nifeq ($(OLD_SWPRINTF), 1)\nMAINFLAGS += -DOLD_SWPRINTF\nendif\nifeq ($(USE_LIBAO), 1)\nMAINFLAGS += -DUSE_LIBAO\nendif\nEMUFLAGS := -DENABLE_ALL_CORES\n\n# -- Byte Order Optimizations --\nifeq ($(BYTE_ORDER), 1)\n# Intel Byte Order\nMAINFLAGS += -DVGM_LITTLE_ENDIAN\nEMUFLAGS += -DVGM_LITTLE_ENDIAN\nelse\nifeq ($(BYTE_ORDER), 2)\n# Motorola Byte Order\nMAINFLAGS += -DVGM_BIG_ENDIAN\nEMUFLAGS += -DVGM_BIG_ENDIAN\nelse\n# undefined byte order\nendif\nendif\n\nifeq ($(DISABLE_HWOPL_SUPPORT), 1)\nMAINFLAGS += -DDISABLE_HW_SUPPORT\nendif\n\n\nifeq ($(DEBUG), 0)\n# -- General Compile Flags --\nCFLAGS := -O3 -g0 -Wno-unused-variable -Wno-unused-value -Wno-unused-but-set-variable $(CFLAGS)\nelse\nCFLAGS := -g -Wall $(CFLAGS)\nendif\n# libm (math library) and libz (zlib)\nLDFLAGS := -lm -lz $(LDFLAGS)\n\nifeq ($(WINDOWS), 1)\n# for Windows, add kernel32 and winmm (Multimedia APIs)\nLDFLAGS += -lkernel32 -lwinmm\nelse\t# if UNIX\nifeq ($(MACOSX), 1)\n# You might want to include additional paths using -I/some/path here,\n# in case some libraries (like libao) can't be found.\n#CFLAGS += -I/some/path\nelse\n# for Linux, add librt (clock stuff) and libpthread (threads)\nLDFLAGS += -lrt -lpthread -pthread\n\n#DBus\nifeq ($(USE_DBUS), 1)\nCFLAGS += $(shell pkg-config --cflags dbus-1) -std=c99\nLDFLAGS += $(shell pkg-config --libs dbus-1)\nMAINFLAGS += -DUSE_DBUS\nendif\n\nendif\nMAINFLAGS += -pthread -DSHARE_PREFIX=\\\"$(PREFIX)\\\"\nendif\n\nifeq ($(USE_LIBAO), 1)\nLDFLAGS += -lao\nendif\n\n# add Library Path, if defined\nifdef LD_LIBRARY_PATH\nLDFLAGS += -L $(LD_LIBRARY_PATH)\nendif\n\nSRC = .\nOBJ = obj\nEMUSRC = $(SRC)/chips\nEMUOBJ = $(OBJ)/chips\n\nOBJDIRS = \\\n\t$(OBJ) \\\n\t$(EMUOBJ)\nMAINOBJS = \\\n\t$(OBJ)/VGMPlay.o \\\n\t$(OBJ)/VGMPlay_AddFmts.o \\\n\t$(OBJ)/Stream.o \\\n\t$(OBJ)/ChipMapper.o\nifeq ($(WINDOWS), 1)\nifeq ($(DISABLE_HWOPL_SUPPORT), 0)\nMAINOBJS += $(OBJ)/pt_ioctl.o\nendif\nendif\nEMUOBJS = \\\n\t$(EMUOBJ)/262intf.o \\\n\t$(EMUOBJ)/2151intf.o \\\n\t$(EMUOBJ)/2203intf.o \\\n\t$(EMUOBJ)/2413intf.o \\\n\t$(EMUOBJ)/2608intf.o \\\n\t$(EMUOBJ)/2610intf.o \\\n\t$(EMUOBJ)/2612intf.o \\\n\t$(EMUOBJ)/3526intf.o \\\n\t$(EMUOBJ)/3812intf.o \\\n\t$(EMUOBJ)/8950intf.o \\\n\t$(EMUOBJ)/adlibemu_opl2.o \\\n\t$(EMUOBJ)/adlibemu_opl3.o \\\n\t$(EMUOBJ)/ay8910.o \\\n\t$(EMUOBJ)/ay_intf.o \\\n\t$(EMUOBJ)/c140.o \\\n\t$(EMUOBJ)/c352.o \\\n\t$(EMUOBJ)/c6280.o \\\n\t$(EMUOBJ)/c6280intf.o \\\n\t$(EMUOBJ)/dac_control.o \\\n\t$(EMUOBJ)/es5503.o \\\n\t$(EMUOBJ)/es5506.o \\\n\t$(EMUOBJ)/emu2149.o \\\n\t$(EMUOBJ)/emu2413.o \\\n\t$(EMUOBJ)/fm2612.o \\\n\t$(EMUOBJ)/fm.o \\\n\t$(EMUOBJ)/fmopl.o \\\n\t$(EMUOBJ)/gb.o \\\n\t$(EMUOBJ)/iremga20.o \\\n\t$(EMUOBJ)/k051649.o \\\n\t$(EMUOBJ)/k053260.o \\\n\t$(EMUOBJ)/k054539.o \\\n\t$(EMUOBJ)/multipcm.o \\\n\t$(EMUOBJ)/nes_apu.o \\\n\t$(EMUOBJ)/nes_intf.o \\\n\t$(EMUOBJ)/np_nes_apu.o \\\n\t$(EMUOBJ)/np_nes_dmc.o \\\n\t$(EMUOBJ)/np_nes_fds.o \\\n\t$(EMUOBJ)/okim6258.o \\\n\t$(EMUOBJ)/okim6295.o \\\n\t$(EMUOBJ)/Ootake_PSG.o \\\n\t$(EMUOBJ)/opll.o \\\n\t$(EMUOBJ)/opm.o \\\n\t$(EMUOBJ)/panning.o \\\n\t$(EMUOBJ)/pokey.o \\\n\t$(EMUOBJ)/pwm.o \\\n\t$(EMUOBJ)/qsound_ctr.o \\\n\t$(EMUOBJ)/qsound_mame.o \\\n\t$(EMUOBJ)/qsound_intf.o \\\n\t$(EMUOBJ)/rf5c68.o \\\n\t$(EMUOBJ)/saa1099.o \\\n\t$(EMUOBJ)/segapcm.o \\\n\t$(EMUOBJ)/scd_pcm.o \\\n\t$(EMUOBJ)/scsp.o \\\n\t$(EMUOBJ)/scspdsp.o \\\n\t$(EMUOBJ)/sn76489.o \\\n\t$(EMUOBJ)/sn76496.o \\\n\t$(EMUOBJ)/sn764intf.o \\\n\t$(EMUOBJ)/upd7759.o \\\n\t$(EMUOBJ)/vsu.o \\\n\t$(EMUOBJ)/ws_audio.o \\\n\t$(EMUOBJ)/x1_010.o \\\n\t$(EMUOBJ)/ym2151.o \\\n\t$(EMUOBJ)/ym2413.o \\\n\t$(EMUOBJ)/ym2612.o \\\n\t$(EMUOBJ)/ym3438.o \\\n\t$(EMUOBJ)/ymdeltat.o \\\n\t$(EMUOBJ)/ymf262.o \\\n\t$(EMUOBJ)/ymf271.o \\\n\t$(EMUOBJ)/ymf278b.o \\\n\t$(EMUOBJ)/ymz280b.o \\\n\t$(EMUOBJ)/ay8910_opl.o \\\n\t$(EMUOBJ)/sn76496_opl.o \\\n\t$(EMUOBJ)/ym2413hd.o \\\n\t$(EMUOBJ)/ym2413_opl.o\nVGMPLAY_OBJS = \\\n\t$(OBJ)/VGMPlayUI.o\n\nifeq ($(USE_DBUS), 1)\n\tVGMPLAY_OBJS += $(OBJ)/dbus.o\nelse ifeq ($(WINDOWS), 1)\n\tVGMPLAY_OBJS += $(OBJ)/mmkeys_Win.o $(OBJ)/dbus_stub.o\nelse\n\tVGMPLAY_OBJS += $(OBJ)/mmkeys_stub.o $(OBJ)/dbus_stub.o\nendif\n\nVGM2PCM_OBJS = \\\n\t$(OBJ)/vgm2pcm.o\nVGM2WAV_OBJS = \\\n\t$(OBJ)/vgm2wav.o\nEXTRA_OBJS = $(VGMPLAY_OBJS) $(VGM2PCM_OBJS) $(VGM2WAV_OBJS)\n\n\nall:\tvgmplay vgm2pcm vgm2wav\n\nvgmplay:\t$(EMUOBJS) $(MAINOBJS) $(VGMPLAY_OBJS)\nifneq ($(WINDOWS), 1)\nifneq ($(MACOSX), 1)\n\t@echo Generating xdg desktop entry\n\t@sed \"s/@BIN_PATH@/$(subst /,\\/,$(DESTDIR)$(PREFIX)/bin/)/\" xdg/vgmplay.desktop.in > xdg/vgmplay.desktop\nendif\nendif\n\t@echo Linking vgmplay ...\n\t@$(CC) $(VGMPLAY_OBJS) $(MAINOBJS) $(EMUOBJS) $(LDFLAGS) -o vgmplay\n\t@echo Done.\n\nvgm2pcm:\t$(EMUOBJS) $(MAINOBJS) $(VGM2PCM_OBJS)\n\t@echo Linking vgm2pcm ...\n\t@$(CC) $(VGM2PCM_OBJS) $(MAINOBJS) $(EMUOBJS) $(LDFLAGS) -o vgm2pcm\n\t@echo Done.\n\nvgm2wav:\t$(EMUOBJS) $(MAINOBJS) $(VGM2WAV_OBJS)\n\t@echo Linking vgm2wav ...\n\t@$(CC) $(VGM2WAV_OBJS) $(MAINOBJS) $(EMUOBJS) $(LDFLAGS) -o vgm2wav\n\t@echo Done.\n\n# compile the chip-emulator c-files\n$(EMUOBJ)/%.o:\t$(EMUSRC)/%.c\n\t@echo Compiling $< ...\n\t@mkdir -p $(@D)\n\t@$(CC) $(CFLAGS) $(EMUFLAGS) -c $< -o $@\n\n# compile the main c-files\n$(OBJ)/%.o:\t$(SRC)/%.c\n\t@echo Compiling $< ...\n\t@mkdir -p $(@D)\n\t@$(CC) $(CFLAGS) $(MAINFLAGS) -c $< -o $@\n\nclean:\n\t@rm -f xdg/vgmplay.desktop\n\t@echo Deleting object files ...\n\t@rm -f $(MAINOBJS) $(EMUOBJS) $(EXTRA_OBJS)\n\t@echo Deleting executable files ...\n\t@rm -f vgmplay vgm2pcm vgm2wav\n\t@echo Done.\n\n# Thanks to ZekeSulastin and nextvolume for the install and uninstall routines.\ninstall:\tall\n\tinstall -m 755 vgmplay $(DESTDIR)$(PREFIX)/bin/vgmplay\n\tinstall -m 755 vgm2pcm $(DESTDIR)$(PREFIX)/bin/vgm2pcm\n\tinstall -m 755 vgm2wav $(DESTDIR)$(PREFIX)/bin/vgm2wav\n\tmkdir -m 755 -p $(DESTDIR)$(MANPREFIX)/man1\n\tinstall -m 644 vgmplay.1 $(DESTDIR)$(MANPREFIX)/man1/vgmplay.1\n\tmkdir -m 755 -p $(DESTDIR)$(PREFIX)/share/vgmplay\n\tinstall -m 644 VGMPlay.ini $(DESTDIR)$(PREFIX)/share/vgmplay/vgmplay.ini\nifneq ($(WINDOWS), 1)\nifneq ($(MACOSX), 1)\n\txdg-icon-resource install --novendor --size 128 xdg/icons/vgmplay-128.png vgmplay\n\txdg-icon-resource install --novendor --size 64 xdg/icons/vgmplay-64.png vgmplay\n\txdg-icon-resource install --novendor --size 32 xdg/icons/vgmplay-32.png vgmplay\n\txdg-icon-resource install --novendor --size 16 xdg/icons/vgmplay-16.png vgmplay\n\txdg-mime install --novendor xdg/vgmplay-mime.xml\n\txdg-desktop-menu install --novendor xdg/vgmplay.desktop\nifeq ($(DISABLE_HWOPL_SUPPORT), 0)\n\tsetcap CAP_SYS_RAWIO+ep $(DESTDIR)$(PREFIX)/bin/vgmplay || true\nendif\nendif\nendif\n\n# install ROMs\nrom_install:\n\tinstall -m 644 yrw801.rom $(DESTDIR)$(PREFIX)/share/vgmplay/yrw801.rom\n\n\n# Install the \"vgm-player\" wrapper\nplay_install:\tinstall\n\tinstall -m 755 vgm-player $(DESTDIR)$(PREFIX)/bin/vgm-player\n\nuninstall:\n\trm -f $(DESTDIR)$(PREFIX)/bin/vgmplay\n\trm -f $(DESTDIR)$(PREFIX)/bin/vgm2pcm\n\trm -f $(DESTDIR)$(PREFIX)/bin/vgm2wav\n\trm -f $(DESTDIR)$(PREFIX)/bin/vgm-player\n\trm -f $(DESTDIR)$(MANPREFIX)/man1/vgmplay.1\n\trm -rf $(DESTDIR)$(PREFIX)/share/vgmplay\n\n.PHONY: all clean install uninstall\n"
  },
  {
    "path": "VGMPlay/PortTalk_IOCTL.h",
    "content": "/******************************************************************************/\n/*                                                                            */\n/*                    PortTalk Driver for Windows NT/2000/XP                  */\n/*                        Version 2.0, 12th January 2002                      */\n/*                          http://www.beyondlogic.org                        */\n/*                                                                            */\n/* Copyright  2002 Craig Peacock. Craig.Peacock@beyondlogic.org              */\n/* Any publication or distribution of this code in source form is prohibited  */\n/* without prior written permission of the copyright holder. This source code */\n/* is provided \"as is\", without any guarantee made as to its suitability or   */\n/* fitness for any particular use. Permission is herby granted to modify or   */\n/* enhance this sample code to produce a derivative program which may only be */\n/* distributed in compiled object form only.                                  */\n/******************************************************************************/\n\n#define PORTTALK_TYPE 40000 /* 32768-65535 are reserved for customers */\n\n// The IOCTL function codes from 0x800 to 0xFFF are for customer use.\n\n#define IOCTL_IOPM_RESTRICT_ALL_ACCESS \\\n    CTL_CODE(PORTTALK_TYPE, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)\n\n#define IOCTL_IOPM_ALLOW_EXCUSIVE_ACCESS \\\n    CTL_CODE(PORTTALK_TYPE, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)\n\n#define IOCTL_SET_IOPM \\\n    CTL_CODE(PORTTALK_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS)\n\n#define IOCTL_ENABLE_IOPM_ON_PROCESSID \\\n    CTL_CODE(PORTTALK_TYPE, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS)\n\n#define IOCTL_READ_PORT_UCHAR \\\n    CTL_CODE(PORTTALK_TYPE, 0x904, METHOD_BUFFERED, FILE_ANY_ACCESS)\n\n#define IOCTL_WRITE_PORT_UCHAR \\\n    CTL_CODE(PORTTALK_TYPE, 0x905, METHOD_BUFFERED, FILE_ANY_ACCESS)\n\n"
  },
  {
    "path": "VGMPlay/Stream.c",
    "content": "// Stream.c: C Source File for Sound Output\n//\n\n// Thanks to nextvolume for NetBSD support\n#define _GNU_SOURCE\n#include <stdio.h>\n#include \"stdbool.h\"\n#include <stdlib.h>\n\n#ifdef WIN32\n#include <windows.h>\n#ifdef USE_LIBAO\n#error \"Sorry, but this doesn't work yet!\"\n#endif // USE_LIBAO\n#else\n#include <unistd.h>\n#include <limits.h>\n#include <sys/ioctl.h>\n#include <fcntl.h>\n\n#ifdef USE_LIBAO\n#include <ao/ao.h>\n#else\n#ifdef __NetBSD__\n#include <sys/audioio.h>\n#elif defined(__linux__)\n#include <linux/soundcard.h>\n#endif // __NETBSD__\n#endif // USE_LIBAO\n\n#endif // WIN32\n\n#include \"chips/mamedef.h\"\t// for UINT8 etc.\n#include \"VGMPlay.h\"\t// neccessary for VGMPlay_Intf.h\n#include \"VGMPlay_Intf.h\"\n#include \"Stream.h\"\n\n#ifndef WIN32\ntypedef struct\n{\n\tUINT16 wFormatTag;\n\tUINT16 nChannels;\n\tUINT32 nSamplesPerSec;\n\tUINT32 nAvgBytesPerSec;\n\tUINT16 nBlockAlign;\n\tUINT16 wBitsPerSample;\n\tUINT16 cbSize;\n} WAVEFORMATEX;\t// from MSDN Help\n\n#define WAVE_FORMAT_PCM\t0x0001\n\n#endif\n\n#ifdef WIN32\nstatic DWORD WINAPI WaveOutThread(void* Arg);\nstatic void BufCheck(void);\n#else\nvoid WaveOutCallbackFnc(void);\n#endif\n\nUINT16 AUDIOBUFFERU = AUDIOBUFFERS;\t\t// used AudioBuffers\n\nWAVEFORMATEX WaveFmt;\nextern UINT32 SampleRate;\nextern volatile bool PauseThread;\nvolatile bool StreamPause;\nextern bool ThreadPauseEnable;\nextern volatile bool ThreadPauseConfrm;\n\nUINT32 BlockLen;\n#ifdef WIN32\nstatic HWAVEOUT hWaveOut;\nstatic WAVEHDR WaveHdrOut[AUDIOBUFFERS];\nstatic HANDLE hWaveOutThread;\n//static DWORD WaveOutCallbackThrID;\n#else\nstatic INT32 hWaveOut;\n#endif\nstatic bool WaveOutOpen;\nUINT32 BUFFERSIZE;\t// Buffer Size in Bytes\nUINT32 SMPL_P_BUFFER;\nstatic char BufferOut[AUDIOBUFFERS][BUFSIZE_MAX];\nstatic volatile bool CloseThread;\n\n\nbool SoundLog;\nstatic FILE* hFile;\nUINT32 SndLogLen;\n\nUINT32 BlocksSent;\nUINT32 BlocksPlayed;\n\nchar SoundLogFile[MAX_PATH];\n\n#ifdef USE_LIBAO\nao_device* dev_ao;\n#endif\n\nINLINE int fputLE32(UINT32 Value, FILE* hFile)\n{\n#ifdef VGM_LITTLE_ENDIAN\n\treturn fwrite(&Value, 0x04, 1, hFile);\n#else\n\tint RetVal;\n\tint ResVal;\n\t\n\tRetVal = fputc((Value & 0x000000FF) >>  0, hFile);\n\tRetVal = fputc((Value & 0x0000FF00) >>  8, hFile);\n\tRetVal = fputc((Value & 0x00FF0000) >> 16, hFile);\n\tRetVal = fputc((Value & 0xFF000000) >> 24, hFile);\n\tResVal = (RetVal != EOF) ? 0x04 : 0x00;\n\treturn ResVal;\n#endif\n}\n\nINLINE int fputLE16(UINT16 Value, FILE* hFile)\n{\n#ifdef VGM_LITTLE_ENDIAN\n\treturn fwrite(&Value, 0x02, 1, hFile);\n#else\n\tint RetVal;\n\tint ResVal;\n\t\n\tRetVal = fputc((Value & 0x00FF) >> 0, hFile);\n\tRetVal = fputc((Value & 0xFF00) >> 8, hFile);\n\tResVal = (RetVal != EOF) ? 0x02 : 0x00;\n\treturn ResVal;\n#endif\n}\n\nUINT8 SaveFile(UINT32 FileLen, const void* TempData)\n{\n\t//char ResultStr[0x100];\n\tUINT32 DataLen;\n\t\n\tif (TempData == NULL)\n\t{\n\t\tswitch(FileLen)\n\t\t{\n\t\tcase 0x00000000:\n\t\t\tif (hFile != NULL)\n\t\t\t\treturn 0xD0;\t// file already open\n\t\t\t\n\t\t\tSndLogLen = 0;\n\t\t\thFile = fopen(SoundLogFile,\"wb\");\n\t\t\tif (hFile == NULL)\n\t\t\t\treturn 0xFF;\t// Save Error\n\t\t\tfseek(hFile, 0x00000000, SEEK_SET);\n\t\t\tfputLE32(0x46464952, hFile);\t// 'RIFF'\n\t\t\tfputLE32(0x00000000, hFile);\t// RIFF chunk length (dummy)\n\t\t\t\n\t\t\tfputLE32(0x45564157, hFile);\t// 'WAVE'\n\t\t\tfputLE32(0x20746D66, hFile);\t// 'fmt '\n\t\t\tDataLen = 0x00000010;\n\t\t\tfputLE32(DataLen, hFile);\t\t// format chunk legth\n\t\t\t\n#ifdef VGM_LITTLE_ENDIAN\n\t\t\tfwrite(&WaveFmt, DataLen, 1, hFile);\n#else\n\t\t\tfputLE16(WaveFmt.wFormatTag,\t\thFile);\t// 0x00\n\t\t\tfputLE16(WaveFmt.nChannels,\t\t\thFile);\t// 0x02\n\t\t\tfputLE32(WaveFmt.nSamplesPerSec,\thFile);\t// 0x04\n\t\t\tfputLE32(WaveFmt.nAvgBytesPerSec,\thFile);\t// 0x08\n\t\t\tfputLE16(WaveFmt.nBlockAlign,\t\thFile);\t// 0x0C\n\t\t\tfputLE16(WaveFmt.wBitsPerSample,\thFile);\t// 0x0E\n\t\t\t//fputLE16(WaveFmt.cbSize, hFile);\t\t\t// 0x10 (DataLen is 0x10, so leave this out)\n#endif\n\t\t\t\n\t\t\tfputLE32(0x61746164, hFile);\t// 'data'\n\t\t\tfputLE32(0x00000000, hFile);\t// data chunk length (dummy)\n\t\t\tbreak;\n\t\tcase 0xFFFFFFFF:\n\t\t\tif (hFile == NULL)\n\t\t\t\treturn 0x80;\t// no file opened\n\t\t\t\n\t\t\tDataLen = SndLogLen * SAMPLESIZE;\n\t\t\t\n\t\t\tfseek(hFile, 0x0028, SEEK_SET);\n\t\t\tfputLE32(DataLen, hFile);\t\t\t// data chunk length\n\t\t\tfseek(hFile, 0x0004, SEEK_SET);\n\t\t\tfputLE32(DataLen + 0x24, hFile);\t// RIFF chunk length\n\t\t\tfclose(hFile);\n\t\t\thFile = NULL;\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (hFile == NULL)\n\t\t\treturn 0x80;\t// no file opened\n\t\t\n\t\t//fseek(hFile, 0x00000000, SEEK_END);\n\t\t//TempVal[0x0] = ftell(hFile);\n\t\t//TempVal[0x1] = fwrite(TempData, 1, FileLen, hFile);\n#ifdef VGM_LITTLE_ENDIAN\n\t\tSndLogLen += fwrite(TempData, SAMPLESIZE, FileLen, hFile);\n#else\n\t\t{\n\t\t\tUINT32 CurSmpl;\n\t\t\tconst UINT16* SmplData;\n\t\t\t\n\t\t\tSmplData = (UINT16*)TempData;\n\t\t\tDataLen = SAMPLESIZE * FileLen / 0x02;\n\t\t\tfor (CurSmpl = 0x00; CurSmpl < DataLen; CurSmpl ++)\n\t\t\t\tSndLogLen += fputLE16(SmplData[CurSmpl], hFile);\n\t\t}\n#endif\n\t\t//sprintf(ResultStr, \"Position:\\t%d\\nBytes written:\\t%d\\nFile Length:\\t%u\\nPointer:\\t%p\",\n\t\t//\t\tTempVal[0], TempVal[1], FileLen, TempData);\n\t\t//AfxMessageBox(ResultStr);\n\t}\n\t\n\treturn 0x00;\n}\n\nUINT8 SoundLogging(UINT8 Mode)\n{\n\tUINT8 RetVal;\n\t\n\tRetVal = (UINT8)SoundLog;\n\tswitch(Mode)\n\t{\n\tcase 0x00:\n\t\tSoundLog = false;\n\t\tbreak;\n\tcase 0x01:\n\t\tSoundLog = true;\n\t\tif (WaveOutOpen && hFile == NULL)\n\t\t\tSaveFile(0x00000000, NULL);\n\t\tbreak;\n\tcase 0xFF:\n\t\tbreak;\n\tdefault:\n\t\tRetVal = 0xA0;\n\t\tbreak;\n\t}\n\t\n\treturn RetVal;\n}\n\nUINT8 StartStream(UINT8 DeviceID)\n{\n\tUINT32 RetVal;\n#ifdef USE_LIBAO\n\tao_sample_format ao_fmt;\n#else\n#ifdef WIN32\n\tUINT16 Cnt;\n\tHANDLE WaveOutThreadHandle;\n\tDWORD WaveOutThreadID;\n\t//char TestStr[0x80];\n#elif defined(__NetBSD__)\n\tstruct audio_info AudioInfo;\n#else\n\tUINT32 ArgVal;\n#endif\n#endif\t// ! USE_LIBAO\n\t\n\tif (WaveOutOpen)\n\t\treturn 0xD0;\t// Thread is already active\n\t\n\t// Init Audio\n\tWaveFmt.wFormatTag = WAVE_FORMAT_PCM;\n\tWaveFmt.nChannels = 2;\n\tWaveFmt.nSamplesPerSec = SampleRate;\n\tWaveFmt.wBitsPerSample = 16;\n\tWaveFmt.nBlockAlign = WaveFmt.wBitsPerSample * WaveFmt.nChannels / 8;\n\tWaveFmt.nAvgBytesPerSec = WaveFmt.nSamplesPerSec * WaveFmt.nBlockAlign;\n\tWaveFmt.cbSize = 0;\n\tif (DeviceID == 0xFF)\n\t\treturn 0x00;\n\t\n#if defined(WIN32) || defined(USE_LIBAO)\n\tBUFFERSIZE = SampleRate / 100 * SAMPLESIZE;\n\tif (BUFFERSIZE > BUFSIZE_MAX)\n\t\tBUFFERSIZE = BUFSIZE_MAX;\n#else\n\tBUFFERSIZE = 1 << BUFSIZELD;\n#endif\n\tSMPL_P_BUFFER = BUFFERSIZE / SAMPLESIZE;\n\tif (AUDIOBUFFERU > AUDIOBUFFERS)\n\t\tAUDIOBUFFERU = AUDIOBUFFERS;\n\t\n\tPauseThread = true;\n\tThreadPauseConfrm = false;\n\tCloseThread = false;\n\tStreamPause = false;\n\t\n#ifndef USE_LIBAO\n#ifdef WIN32\n\tThreadPauseEnable = true;\n\tWaveOutThreadHandle = CreateThread(NULL, 0x00, &WaveOutThread, NULL, 0x00,\n\t\t\t\t\t\t\t\t\t\t&WaveOutThreadID);\n\tif(WaveOutThreadHandle == NULL)\n\t\treturn 0xC8;\t\t// CreateThread failed\n\tCloseHandle(WaveOutThreadHandle);\n\t\n\tRetVal = waveOutOpen(&hWaveOut, ((UINT)DeviceID - 1), &WaveFmt, 0x00, 0x00, CALLBACK_NULL);\n\tif(RetVal != MMSYSERR_NOERROR)\n#else\n\tThreadPauseEnable = false;\n#ifdef __NetBSD__\n\thWaveOut = open(\"/dev/audio\", O_WRONLY);\n#else\n\thWaveOut = open(\"/dev/dsp\", O_WRONLY);\n#endif\n\tif (hWaveOut < 0)\n#endif\n#else\t// ifdef USE_LIBAO\n\tao_initialize();\n\t\n\tThreadPauseEnable = false;\n\tao_fmt.bits = WaveFmt.wBitsPerSample;\n\tao_fmt.rate = WaveFmt.nSamplesPerSec;\n\tao_fmt.channels = WaveFmt.nChannels;\n\tao_fmt.byte_format = AO_FMT_NATIVE;\n\tao_fmt.matrix = NULL;\n\t\n\tdev_ao = ao_open_live(ao_default_driver_id(), &ao_fmt, NULL);\n\tif (dev_ao == NULL)\n#endif\n\t{\n\t\tCloseThread = true;\n\t\treturn 0xC0;\t\t// waveOutOpen failed\n\t}\n\tWaveOutOpen = true;\n\t\n\t//sprintf(TestStr, \"Buffer 0,0:\\t%p\\nBuffer 0,1:\\t%p\\nBuffer 1,0:\\t%p\\nBuffer 1,1:\\t%p\\n\",\n\t//\t\t&BufferOut[0][0], &BufferOut[0][1], &BufferOut[1][0], &BufferOut[1][1]);\n\t//AfxMessageBox(TestStr);\n#ifndef USE_LIBAO\n#ifdef WIN32\n\tfor (Cnt = 0x00; Cnt < AUDIOBUFFERU; Cnt ++)\n\t{\n\t\tWaveHdrOut[Cnt].lpData = BufferOut[Cnt];\t// &BufferOut[Cnt][0x00];\n\t\tWaveHdrOut[Cnt].dwBufferLength = BUFFERSIZE;\n\t\tWaveHdrOut[Cnt].dwBytesRecorded = 0x00;\n\t\tWaveHdrOut[Cnt].dwUser = 0x00;\n\t\tWaveHdrOut[Cnt].dwFlags = 0x00;\n\t\tWaveHdrOut[Cnt].dwLoops = 0x00;\n\t\tWaveHdrOut[Cnt].lpNext = NULL;\n\t\tWaveHdrOut[Cnt].reserved = 0x00;\n\t\tRetVal = waveOutPrepareHeader(hWaveOut, &WaveHdrOut[Cnt], sizeof(WAVEHDR));\n\t\tWaveHdrOut[Cnt].dwFlags |= WHDR_DONE;\n\t}\n#elif defined(__NetBSD__)\n\tAUDIO_INITINFO(&AudioInfo);\n\t\n\tAudioInfo.mode = AUMODE_PLAY;\n\tAudioInfo.play.sample_rate = WaveFmt.nSamplesPerSec;\n\tAudioInfo.play.channels = WaveFmt.nChannels;\n\tAudioInfo.play.precision = WaveFmt.wBitsPerSample;\n\tAudioInfo.play.encoding = AUDIO_ENCODING_SLINEAR;\n\t\n\tRetVal = ioctl(hWaveOut, AUDIO_SETINFO, &AudioInfo);\n\tif (RetVal)\n\t\tprintf(\"Error setting audio information!\\n\");\n#else\n\tArgVal = (AUDIOBUFFERU << 16) | BUFSIZELD;\n\tRetVal = ioctl(hWaveOut, SNDCTL_DSP_SETFRAGMENT, &ArgVal);\n\tif (RetVal)\n\t\tprintf(\"Error setting Fragment Size!\\n\");\n\tArgVal = AFMT_S16_NE;\n\tRetVal = ioctl(hWaveOut, SNDCTL_DSP_SETFMT, &ArgVal);\n\tif (RetVal)\n\t\tprintf(\"Error setting Format!\\n\");\n\tArgVal = WaveFmt.nChannels;\n\tRetVal = ioctl(hWaveOut, SNDCTL_DSP_CHANNELS, &ArgVal);\n\tif (RetVal)\n\t\tprintf(\"Error setting Channels!\\n\");\n\tArgVal = WaveFmt.nSamplesPerSec;\n\tRetVal = ioctl(hWaveOut, SNDCTL_DSP_SPEED, &ArgVal);\n\tif (RetVal)\n\t\tprintf(\"Error setting Sample Rate!\\n\");\n#endif\n#endif\t// USE_LIBAO\n\t\n\tif (SoundLog)\n\t\tSaveFile(0x00000000, NULL);\n\t\n\tPauseThread = false;\n\t\n\treturn 0x00;\n}\n\nUINT8 StopStream(void)\n{\n\tUINT32 RetVal;\n#ifdef WIN32\n\tUINT16 Cnt;\n#endif\n\t\n\tif (! WaveOutOpen)\n\t\treturn 0xD8;\t// Thread is not active\n\t\n\tCloseThread = true;\n#ifdef WIN32\n\tfor (Cnt = 0; Cnt < 100; Cnt ++)\n\t{\n\t\tSleep(1);\n\t\tif (hWaveOutThread == NULL)\n\t\t\tbreak;\n\t}\n#endif\n\tif (hFile != NULL)\n\t\tSaveFile(0xFFFFFFFF, NULL);\n\tWaveOutOpen = false;\n\t\n#ifndef USE_LIBAO\n#ifdef WIN32\n\tRetVal = waveOutReset(hWaveOut);\n\tfor (Cnt = 0x00; Cnt < AUDIOBUFFERU; Cnt ++)\n\t\tRetVal = waveOutUnprepareHeader(hWaveOut, &WaveHdrOut[Cnt], sizeof(WAVEHDR));\n\t\n\tRetVal = waveOutClose(hWaveOut);\n\tif(RetVal != MMSYSERR_NOERROR)\n\t\treturn 0xC4;\t\t// waveOutClose failed  -- but why ???\n#else\n\tclose(hWaveOut);\n#endif\n#else\t// ifdef USE_LIBAO\n\tao_close(dev_ao);\n\t\n\tao_shutdown();\n#endif\n\t\n\treturn 0x00;\n}\n\nvoid PauseStream(bool PauseOn)\n{\n\tUINT32 RetVal;\n\t\n\tif (! WaveOutOpen)\n\t\treturn;\t// Thread is not active\n\t\n#ifdef WIN32\n\tswitch(PauseOn)\n\t{\n\tcase true:\n\t\tRetVal = waveOutPause(hWaveOut);\n\t\tbreak;\n\tcase false:\n\t\tRetVal = waveOutRestart(hWaveOut);\n\t\tbreak;\n\t}\n\tStreamPause = PauseOn;\n#else\n\tPauseThread = PauseOn;\n#endif\n\t\n\treturn;\n}\n\n//UINT32 FillBuffer(WAVE_16BS* Buffer, UINT32 BufferSize)\n// moved to VGMPlay.c\n\n#ifdef WIN32\n\nstatic DWORD WINAPI WaveOutThread(void* Arg)\n{\n#ifdef NDEBUG\n\tUINT32 RetVal;\n#endif\n\tUINT16 CurBuf;\n\tWAVE_16BS* TempBuf;\n\tUINT32 WrtSmpls;\n\t//char TestStr[0x80];\n\tbool DidBuffer;\t// a buffer was processed\n\t\n\thWaveOutThread = GetCurrentThread();\n#ifdef NDEBUG\n\tRetVal = SetThreadPriority(hWaveOutThread, THREAD_PRIORITY_TIME_CRITICAL);\n\tif (! RetVal)\n\t{\n\t\t// Error by setting priority\n\t\t// try a lower priority, because too low priorities cause sound stuttering\n\t\tRetVal = SetThreadPriority(hWaveOutThread, THREAD_PRIORITY_HIGHEST);\n\t}\n#endif\n\t\n\tBlocksSent = 0x00;\n\tBlocksPlayed = 0x00;\n\twhile(! CloseThread)\n\t{\n\t\twhile(PauseThread && ! CloseThread && ! (StreamPause && DidBuffer))\n\t\t{\n\t\t\tThreadPauseConfrm = true;\n\t\t\tSleep(1);\n\t\t}\n\t\tif (CloseThread)\n\t\t\tbreak;\n\t\t\n\t\tBufCheck();\n\t\tDidBuffer = false;\n\t\tfor (CurBuf = 0x00; CurBuf < AUDIOBUFFERU; CurBuf ++)\n\t\t{\n\t\t\tif (WaveHdrOut[CurBuf].dwFlags & WHDR_DONE)\n\t\t\t{\n\t\t\t\tTempBuf = (WAVE_16BS*)WaveHdrOut[CurBuf].lpData;\n\t\t\t\t\n\t\t\t\tif (WaveHdrOut[CurBuf].dwUser & 0x01)\n\t\t\t\t\tBlocksPlayed ++;\n\t\t\t\telse\n\t\t\t\t\tWaveHdrOut[CurBuf].dwUser |= 0x01;\n\t\t\t\t\n\t\t\t\tWrtSmpls = FillBuffer(TempBuf, SMPL_P_BUFFER);\n\t\t\t\t\n\t\t\t\tWaveHdrOut[CurBuf].dwBufferLength = WrtSmpls * SAMPLESIZE;\n\t\t\t\twaveOutWrite(hWaveOut, &WaveHdrOut[CurBuf], sizeof(WAVEHDR));\n\t\t\t\tif (SoundLog && hFile != NULL)\n\t\t\t\t\tSaveFile(WrtSmpls, TempBuf);\n\t\t\t\t\n\t\t\t\tDidBuffer = true;\n\t\t\t\tBlocksSent ++;\n\t\t\t\tBufCheck();\n\t\t\t\t//CurBuf = 0x00;\n\t\t\t\t//break;\n\t\t\t}\n\t\t\tif (CloseThread)\n\t\t\t\tbreak;\n\t\t}\n\t\tSleep(1);\n\t}\n\t\n\thWaveOutThread = NULL;\n\treturn 0x00000000;\n}\n\nstatic void BufCheck(void)\n{\n\tUINT16 CurBuf;\n\t\n\tfor (CurBuf = 0x00; CurBuf < AUDIOBUFFERU; CurBuf ++)\n\t{\n\t\tif (WaveHdrOut[CurBuf].dwFlags & WHDR_DONE)\n\t\t{\n\t\t\tif (WaveHdrOut[CurBuf].dwUser & 0x01)\n\t\t\t{\n\t\t\t\tWaveHdrOut[CurBuf].dwUser &= ~0x01;\n\t\t\t\tBlocksPlayed ++;\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn;\n}\n\n#else\t// #ifndef WIN32\n\nvoid WaveOutLinuxCallBack(void)\n{\n\tUINT32 RetVal;\n\tUINT16 CurBuf;\n\tWAVE_16BS* TempBuf;\n\tUINT32 WrtSmpls;\n\t\n\tif (! WaveOutOpen)\n\t\treturn;\t// Device not opened\n\t\n\tCurBuf = BlocksSent % AUDIOBUFFERU;\n\tTempBuf = (WAVE_16BS*)BufferOut[CurBuf];\n\t\n\tWrtSmpls = FillBuffer(TempBuf, SMPL_P_BUFFER);\n\t\n#ifndef USE_LIBAO\n\tRetVal = write(hWaveOut, TempBuf, WrtSmpls * SAMPLESIZE);\n#else\n\tRetVal = ao_play(dev_ao, (char*)TempBuf, WrtSmpls * SAMPLESIZE);\n#endif\n\tif (SoundLog && hFile != NULL)\n\t\tSaveFile(WrtSmpls, TempBuf);\n\tBlocksSent ++;\n\tBlocksPlayed ++;\n\t\n\treturn;\n}\n\n#endif\n"
  },
  {
    "path": "VGMPlay/Stream.h",
    "content": "// Stream.h: Header File for constants and structures related to Sound Output\n//\n\n#ifdef WIN32\n#include <mmsystem.h>\n#else\n#define MAX_PATH\tPATH_MAX\n#endif\n\n#define SAMPLESIZE\t\tsizeof(WAVE_16BS)\n#define BUFSIZE_MAX\t\t0x1000\t\t// Maximum Buffer Size in Bytes\n#ifndef WIN32\n#define BUFSIZELD\t\t11\t\t\t// Buffer Size\n#endif\n#define AUDIOBUFFERS\t200\t\t\t// Maximum Buffer Count\n//\tWindows:\tBUFFERSIZE = SampleRate / 100 * SAMPLESIZE (44100 / 100 * 4 = 1764)\n//\t\t\t\t1 Audio-Buffer = 10 msec, Min: 5\n//\t\t\t\tWin95- / WinVista-safe: 500 msec\n//\tLinux:\t\tBUFFERSIZE = 1 << BUFSIZELD (1 << 11 = 2048)\n//\t\t\t\t1 Audio-Buffer = 11.6 msec\n\nUINT8 SaveFile(UINT32 FileLen, const void* TempData);\nUINT8 SoundLogging(UINT8 Mode);\nUINT8 StartStream(UINT8 DeviceID);\nUINT8 StopStream(void);\nvoid PauseStream(bool PauseOn);\n"
  },
  {
    "path": "VGMPlay/VGMFile.h",
    "content": "// Header file for VGM file handling\n\ntypedef struct _vgm_file_header\n{\n\tUINT32 fccVGM;\n\tUINT32 lngEOFOffset;\n\tUINT32 lngVersion;\n\tUINT32 lngHzPSG;\n\tUINT32 lngHzYM2413;\n\tUINT32 lngGD3Offset;\n\tUINT32 lngTotalSamples;\n\tUINT32 lngLoopOffset;\n\tUINT32 lngLoopSamples;\n\tUINT32 lngRate;\n\tUINT16 shtPSG_Feedback;\n\tUINT8 bytPSG_SRWidth;\n\tUINT8 bytPSG_Flags;\n\tUINT32 lngHzYM2612;\n\tUINT32 lngHzYM2151;\n\tUINT32 lngDataOffset;\n\tUINT32 lngHzSPCM;\n\tUINT32 lngSPCMIntf;\n\tUINT32 lngHzRF5C68;\n\tUINT32 lngHzYM2203;\n\tUINT32 lngHzYM2608;\n\tUINT32 lngHzYM2610;\n\tUINT32 lngHzYM3812;\n\tUINT32 lngHzYM3526;\n\tUINT32 lngHzY8950;\n\tUINT32 lngHzYMF262;\n\tUINT32 lngHzYMF278B;\n\tUINT32 lngHzYMF271;\n\tUINT32 lngHzYMZ280B;\n\tUINT32 lngHzRF5C164;\n\tUINT32 lngHzPWM;\n\tUINT32 lngHzAY8910;\n\tUINT8 bytAYType;\n\tUINT8 bytAYFlag;\n\tUINT8 bytAYFlagYM2203;\n\tUINT8 bytAYFlagYM2608;\n\tUINT8 bytVolumeModifier;\n\tUINT8 bytReserved2;\n\tINT8 bytLoopBase;\n\tUINT8 bytLoopModifier;\n\tUINT32 lngHzGBDMG;\n\tUINT32 lngHzNESAPU;\n\tUINT32 lngHzMultiPCM;\n\tUINT32 lngHzUPD7759;\n\tUINT32 lngHzOKIM6258;\n\tUINT8 bytOKI6258Flags;\n\tUINT8 bytK054539Flags;\n\tUINT8 bytC140Type;\n\tUINT8 bytReservedFlags;\n\tUINT32 lngHzOKIM6295;\n\tUINT32 lngHzK051649;\n\tUINT32 lngHzK054539;\n\tUINT32 lngHzHuC6280;\n\tUINT32 lngHzC140;\n\tUINT32 lngHzK053260;\n\tUINT32 lngHzPokey;\n\tUINT32 lngHzQSound;\n\tUINT32 lngHzSCSP;\n//\tUINT32 lngHzOKIM6376;\n\t//UINT8 bytReserved[0x04];\n\tUINT32 lngExtraOffset;\n\tUINT32 lngHzWSwan;\n\tUINT32 lngHzVSU;\n\tUINT32 lngHzSAA1099;\n\tUINT32 lngHzES5503;\n\tUINT32 lngHzES5506;\n\tUINT8 bytES5503Chns;\n\tUINT8 bytES5506Chns;\n\tUINT8 bytC352ClkDiv;\n\tUINT8 bytESReserved;\n\tUINT32 lngHzX1_010;\n\tUINT32 lngHzC352;\n\tUINT32 lngHzGA20;\n} VGM_HEADER;\ntypedef struct _vgm_header_extra\n{\n\tUINT32 DataSize;\n\tUINT32 Chp2ClkOffset;\n\tUINT32 ChpVolOffset;\n} VGM_HDR_EXTRA;\ntypedef struct _vgm_extra_chip_data32\n{\n\tUINT8 Type;\n\tUINT32 Data;\n} VGMX_CHIP_DATA32;\ntypedef struct _vgm_extra_chip_data16\n{\n\tUINT8 Type;\n\tUINT8 Flags;\n\tUINT16 Data;\n} VGMX_CHIP_DATA16;\ntypedef struct _vgm_extra_chip_extra32\n{\n\tUINT8 ChipCnt;\n\tVGMX_CHIP_DATA32* CCData;\n} VGMX_CHP_EXTRA32;\ntypedef struct _vgm_extra_chip_extra16\n{\n\tUINT8 ChipCnt;\n\tVGMX_CHIP_DATA16* CCData;\n} VGMX_CHP_EXTRA16;\ntypedef struct _vgm_header_extra_data\n{\n\tVGMX_CHP_EXTRA32 Clocks;\n\tVGMX_CHP_EXTRA16 Volumes;\n} VGM_EXTRA;\n\n#define VOLUME_MODIF_WRAP\t0xC0\ntypedef struct _vgm_gd3_tag\n{\n\tUINT32 fccGD3;\n\tUINT32 lngVersion;\n\tUINT32 lngTagLength;\n\twchar_t* strTrackNameE;\n\twchar_t* strTrackNameJ;\n\twchar_t* strGameNameE;\n\twchar_t* strGameNameJ;\n\twchar_t* strSystemNameE;\n\twchar_t* strSystemNameJ;\n\twchar_t* strAuthorNameE;\n\twchar_t* strAuthorNameJ;\n\twchar_t* strReleaseDate;\n\twchar_t* strCreator;\n\twchar_t* strNotes;\n} GD3_TAG;\ntypedef struct _vgm_pcm_bank_data\n{\n\tUINT32 DataSize;\n\tUINT8* Data;\n\tUINT32 DataStart;\n} VGM_PCM_DATA;\ntypedef struct _vgm_pcm_bank\n{\n\tUINT32 BankCount;\n\tVGM_PCM_DATA* Bank;\n\tUINT32 DataSize;\n\tUINT8* Data;\n\tUINT32 DataPos;\n\tUINT32 BnkPos;\n} VGM_PCM_BANK;\n\n#define FCC_VGM\t0x206D6756\t// 'Vgm '\n#define FCC_GD3\t0x20336447\t// 'Gd3 '\n"
  },
  {
    "path": "VGMPlay/VGMPlay.c",
    "content": "// VGMPlay.c: C Source File of the Main Executable\n//\n\n// Line Size:\t96 Chars\n// Tab Size:\t4 Spaces\n\n/*3456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456\n0000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999*/\n\n// Mixer Muting ON:\n//\t\tMixer's FM Volume is set to 0 or Mute\t-> absolutely muted\n//\t\t(sometimes it can take some time to get the Mixer Control under Windows)\n// Mixer Muting OFF:\n//\t\tFM Volume is set to 0 through commands\t-> very very low volume level ~0.4%\n//\t\t(faster way)\n//#define MIXER_MUTING\n\n// These defines enable additional features.\n//\tADDITIONAL_FORMATS enables CMF and DRO support.\n//\tCONSOLE_MODE switches between VGMPlay and in_vgm mode.\n//\tin_vgm mode can also be used for custom players.\n//\n//#define ADDITIONAL_FORMATS\n//#define CONSOLE_MODE\n//#define VGM_LITTLE_ENDIAN\t// enable optimizations for Little Endian systems\n//#define VGM_BIG_ENDIAN\t// enable optimizations for Big Endian systems\n\n#define _GNU_SOURCE\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <wchar.h>\n#include \"stdbool.h\"\n#include <math.h>\t// for pow()\n\n#ifdef WIN32\n#ifndef NO_WCHAR_FILENAMES\n// includes for manual wide-character ZLib open\n#include <fcntl.h>\t// for _O_RDONLY and _O_BINARY\n#include <io.h>\t\t// for _wopen and _close\n#endif\n\n#include <conio.h>\t// for _inp()\n#include <windows.h>\n#else\t//ifdef UNIX\n#include <limits.h>\t\t// for PATH_MAX\n#include <pthread.h>\t// for pthread functions\n\n// (suitable?) Apple substitute for clock_gettime()\n//#ifdef __MACH__\n#if 0\t// not required in Mac OS X 10.12 and later\n#include <mach/mach_time.h>\n#define CLOCK_REALTIME\t0\n#define CLOCK_MONOTONIC\t0\nint clock_gettime(int clk_id, struct timespec *t)\n{\n\tmach_timebase_info_data_t timebase;\n\tmach_timebase_info(&timebase);\n\tuint64_t time;\n\ttime = mach_absolute_time();\n\tdouble nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);\n\tdouble seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);\n\tt->tv_sec = seconds;\n\tt->tv_nsec = nseconds;\n\treturn 0;\n}\n#else\n#include <time.h>\t\t// for clock_gettime()\n#endif\n\n#include <unistd.h>\t\t// for usleep()\n\n#define MAX_PATH\tPATH_MAX\n#define\tSleep(msec)\tusleep(msec * 1000)\n\n#undef MIXER_MUTING\t\t// I didn't get the Mixer Control to work under Linux\n\n#ifdef MIXER_MUTING\n#include <sys/ioctl.h>\n#include <fcntl.h>\n#include <linux/soundcard.h>\n#endif\n#endif\t// WIN32/UNIX\n\n#include <zlib.h>\n\n#include \"chips/mamedef.h\"\n\n// integer types for fast integer calculation\n// the bit number is unused (it's an orientation)\n#define FUINT8\tunsigned int\n#define FUINT16\tunsigned int\n\n#include \"VGMPlay.h\"\n#include \"VGMPlay_Intf.h\"\n#ifdef CONSOLE_MODE\n#include \"Stream.h\"\n#endif\n\n#include \"chips/ChipIncl.h\"\n\nunsigned char OpenPortTalk(void);\nvoid ClosePortTalk(void);\n\n#include \"ChipMapper.h\"\n\ntypedef void (*strm_func)(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\ntypedef struct chip_audio_attributes CAUD_ATTR;\nstruct chip_audio_attributes\n{\n\tUINT32 SmpRate;\n\tUINT16 Volume;\n\tUINT8 ChipType;\n\tUINT8 ChipID;\t\t// 0 - 1st chip, 1 - 2nd chip, etc.\n\t// Resampler Type:\n\t//\t00 - Old\n\t//\t01 - Upsampling\n\t//\t02 - Copy\n\t//\t03 - Downsampling\n\tUINT8 Resampler;\n\tstrm_func StreamUpdate;\n\tUINT32 SmpP;\t\t// Current Sample (Playback Rate)\n\tUINT32 SmpLast;\t\t// Sample Number Last\n\tUINT32 SmpNext;\t\t// Sample Number Next\n\tWAVE_32BS LSmpl;\t// Last Sample\n\tWAVE_32BS NSmpl;\t// Next Sample\n\tCAUD_ATTR* Paired;\n};\n\ntypedef struct chip_audio_struct\n{\n\tCAUD_ATTR SN76496;\n\tCAUD_ATTR YM2413;\n\tCAUD_ATTR YM2612;\n\tCAUD_ATTR YM2151;\n\tCAUD_ATTR SegaPCM;\n\tCAUD_ATTR RF5C68;\n\tCAUD_ATTR YM2203;\n\tCAUD_ATTR YM2608;\n\tCAUD_ATTR YM2610;\n\tCAUD_ATTR YM3812;\n\tCAUD_ATTR YM3526;\n\tCAUD_ATTR Y8950;\n\tCAUD_ATTR YMF262;\n\tCAUD_ATTR YMF278B;\n\tCAUD_ATTR YMF271;\n\tCAUD_ATTR YMZ280B;\n\tCAUD_ATTR RF5C164;\n\tCAUD_ATTR PWM;\n\tCAUD_ATTR AY8910;\n\tCAUD_ATTR GameBoy;\n\tCAUD_ATTR NES;\n\tCAUD_ATTR MultiPCM;\n\tCAUD_ATTR UPD7759;\n\tCAUD_ATTR OKIM6258;\n\tCAUD_ATTR OKIM6295;\n\tCAUD_ATTR K051649;\n\tCAUD_ATTR K054539;\n\tCAUD_ATTR HuC6280;\n\tCAUD_ATTR C140;\n\tCAUD_ATTR K053260;\n\tCAUD_ATTR Pokey;\n\tCAUD_ATTR QSound;\n\tCAUD_ATTR SCSP;\n\tCAUD_ATTR WSwan;\n\tCAUD_ATTR VSU;\n\tCAUD_ATTR SAA1099;\n\tCAUD_ATTR ES5503;\n\tCAUD_ATTR ES5506;\n\tCAUD_ATTR X1_010;\n\tCAUD_ATTR C352;\n\tCAUD_ATTR GA20;\n//\tCAUD_ATTR OKIM6376;\n} CHIP_AUDIO;\n\ntypedef struct chip_aud_list CA_LIST;\nstruct chip_aud_list\n{\n\tCAUD_ATTR* CAud;\n\tCHIP_OPTS* COpts;\n\tCA_LIST* next;\n};\n\ntypedef struct daccontrol_data\n{\n\tbool Enable;\n\tUINT8 Bank;\n} DACCTRL_DATA;\n\ntypedef struct pcmbank_table\n{\n\tUINT8 ComprType;\n\tUINT8 CmpSubType;\n\tUINT8 BitDec;\n\tUINT8 BitCmp;\n\tUINT16 EntryCount;\n\tvoid* Entries;\n} PCMBANK_TBL;\n\n\n// Function Prototypes (prototypes in comments are defined in VGMPlay_Intf.h)\n//void VGMPlay_Init(void);\n//void VGMPlay_Init2(void);\n//void VGMPlay_Deinit(void);\n//char* FindFile(const char* FileName)\n\nINLINE UINT16 ReadLE16(const UINT8* Data);\nINLINE UINT16 ReadBE16(const UINT8* Data);\nINLINE UINT32 ReadLE24(const UINT8* Data);\nINLINE UINT32 ReadLE32(const UINT8* Data);\nINLINE int gzgetLE16(gzFile hFile, UINT16* RetValue);\nINLINE int gzgetLE32(gzFile hFile, UINT32* RetValue);\nstatic UINT32 gcd(UINT32 x, UINT32 y);\n//void PlayVGM(void);\n//void StopVGM(void);\n//void RestartVGM(void);\n//void PauseVGM(bool Pause);\n//void SeekVGM(bool Relative, INT32 PlayBkSamples);\n//void RefreshMuting(void);\n//void RefreshPanning(void);\n//void RefreshPlaybackOptions(void);\n\n//UINT32 GetGZFileLength(const char* FileName);\n//UINT32 GetGZFileLengthW(const wchar_t* FileName);\nstatic UINT32 GetGZFileLength_Internal(FILE* hFile);\n//bool OpenVGMFile(const char* FileName);\nstatic bool OpenVGMFile_Internal(gzFile hFile, UINT32 FileSize);\nstatic void ReadVGMHeader(gzFile hFile, VGM_HEADER* RetVGMHead);\nstatic UINT8 ReadGD3Tag(gzFile hFile, UINT32 GD3Offset, GD3_TAG* RetGD3Tag);\nstatic void ReadChipExtraData32(UINT32 StartOffset, VGMX_CHP_EXTRA32* ChpExtra);\nstatic void ReadChipExtraData16(UINT32 StartOffset, VGMX_CHP_EXTRA16* ChpExtra);\n//void CloseVGMFile(void);\n//void FreeGD3Tag(GD3_TAG* TagData);\nstatic wchar_t* MakeEmptyWStr(void);\nstatic wchar_t* ReadWStrFromFile(gzFile hFile, UINT32* FilePos, UINT32 EOFPos);\n//UINT32 GetVGMFileInfo(const char* FileName, VGM_HEADER* RetVGMHead, GD3_TAG* RetGD3Tag);\nstatic UINT32 GetVGMFileInfo_Internal(gzFile hFile, UINT32 FileSize,\n\t\t\t\t\t\t\t\t\t  VGM_HEADER* RetVGMHead, GD3_TAG* RetGD3Tag);\nINLINE UINT32 MulDivRound(UINT64 Number, UINT64 Numerator, UINT64 Denominator);\n//UINT32 CalcSampleMSec(UINT64 Value, UINT8 Mode);\n//UINT32 CalcSampleMSecExt(UINT64 Value, UINT8 Mode, VGM_HEADER* FileHead);\n//const char* GetChipName(UINT8 ChipID);\n//const char* GetAccurateChipName(UINT8 ChipID, UINT8 SubType);\n//UINT32 GetChipClock(VGM_HEADER* FileHead, UINT8 ChipID, UINT8* RetSubType);\nstatic UINT16 GetChipVolume(VGM_HEADER* FileHead, UINT8 ChipID, UINT8 ChipNum, UINT8 ChipCnt);\n\nstatic void RestartPlaying(void);\nstatic void Chips_GeneralActions(UINT8 Mode);\n\nINLINE INT32 SampleVGM2Pbk_I(INT32 SampleVal);\t// inline functions\nINLINE INT32 SamplePbk2VGM_I(INT32 SampleVal);\n//INT32 SampleVGM2Playback(INT32 SampleVal);\t\t// non-inline functions\n//INT32 SamplePlayback2VGM(INT32 SampleVal);\nstatic UINT8 StartThread(void);\nstatic UINT8 StopThread(void);\n#if defined(WIN32) && defined(MIXER_MUTING)\nstatic bool GetMixerControl(void);\n#endif\nstatic bool SetMuteControl(bool mute);\n\nstatic void InterpretFile(UINT32 SampleCount);\nstatic void AddPCMData(UINT8 Type, UINT32 DataSize, const UINT8* Data);\n//INLINE FUINT16 ReadBits(UINT8* Data, UINT32* Pos, FUINT8* BitPos, FUINT8 BitsToRead);\nstatic bool DecompressDataBlk(VGM_PCM_DATA* Bank, UINT32 DataSize, const UINT8* Data);\nstatic UINT8 GetDACFromPCMBank(void);\nstatic UINT8* GetPointerFromPCMBank(UINT8 Type, UINT32 DataPos);\nstatic void ReadPCMTable(UINT32 DataSize, const UINT8* Data);\nstatic void InterpretVGM(UINT32 SampleCount);\n#ifdef ADDITIONAL_FORMATS\nextern void InterpretOther(UINT32 SampleCount);\n#endif\n\nstatic void GeneralChipLists(void);\nstatic void SetupResampler(CAUD_ATTR* CAA);\nstatic void ChangeChipSampleRate(void* DataPtr, UINT32 NewSmplRate);\n\nINLINE INT16 Limit2Short(INT32 Value);\nstatic void null_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nstatic void dual_opl2_stereo(UINT8 ChipID, stream_sample_t **outputs, int samples);\nstatic void ResampleChipStream(CA_LIST* CLst, WAVE_32BS* RetSample, UINT32 Length);\nstatic INT32 RecalcFadeVolume(void);\n//UINT32 FillBuffer(WAVE_16BS* Buffer, UINT32 BufferSize)\n\n#ifdef WIN32\nDWORD WINAPI PlayingThread(void* Arg);\n#else\nUINT64 TimeSpec2Int64(const struct timespec* ts);\nvoid* PlayingThread(void* Arg);\n#endif\n\n\n// Options Variables\nUINT32 SampleRate;\t// Note: also used by some sound cores to determinate the chip sample rate\n\nUINT32 VGMMaxLoop;\nUINT32 VGMPbRate;\t// in Hz, ignored if this value or VGM's lngRate Header value is 0\n#ifdef ADDITIONAL_FORMATS\nextern UINT32 CMFMaxLoop;\n#endif\nUINT32 FadeTime;\nUINT32 PauseTime;\t// current Pause Time\n\nfloat VolumeLevel;\nbool SurroundSound;\nUINT8 HardStopOldVGMs;\nbool FadeRAWLog;\n//bool FullBufFill;\t// Fill Buffer until it's full\nbool PauseEmulate;\n\nbool DoubleSSGVol;\n\nUINT8 ResampleMode;\t// 00 - HQ both, 01 - LQ downsampling, 02 - LQ both\nUINT8 CHIP_SAMPLING_MODE;\nINT32 CHIP_SAMPLE_RATE;\n\nUINT16 FMPort;\nbool FMForce;\n//bool FMAccurate;\nbool FMBreakFade;\nfloat FMVol;\nbool FMOPL2Pan;\n\nCHIPS_OPTION ChipOpts[0x02];\n\nUINT8 OPL_MODE;\nUINT8 OPL_CHIPS;\n#ifdef WIN32\nbool WINNT_MODE;\n#endif\n\nstream_sample_t* DUMMYBUF[0x02] = {NULL, NULL};\n\nchar* AppPaths[8];\n\nbool AutoStopSkip;\n\nUINT8 FileMode;\nVGM_HEADER VGMHead;\nVGM_HDR_EXTRA VGMHeadX;\nVGM_EXTRA VGMH_Extra;\nUINT32 VGMDataLen;\nUINT8* VGMData;\nGD3_TAG VGMTag;\n\n#define PCM_BANK_COUNT\t0x40\nVGM_PCM_BANK PCMBank[PCM_BANK_COUNT];\nPCMBANK_TBL PCMTbl;\nUINT8 DacCtrlUsed;\nUINT8 DacCtrlUsg[0xFF];\nDACCTRL_DATA DacCtrl[0xFF];\n\n#ifdef WIN32\nHANDLE hPlayThread;\n#else\npthread_t hPlayThread;\n#endif\nbool PlayThreadOpen;\nvolatile bool PauseThread;\nstatic volatile bool CloseThread;\nbool ThreadPauseEnable;\nvolatile bool ThreadPauseConfrm;\nbool ThreadNoWait;\t// don't reset the timer\n\nCHIP_AUDIO ChipAudio[0x02];\nCAUD_ATTR CA_Paired[0x02][0x03];\nfloat MasterVol;\n\nCA_LIST ChipListBuffer[0x200];\nCA_LIST* ChipListAll;\t// all chips needed for playback (in general)\nCA_LIST* ChipListPause;\t// all chips needed for EmulateWhilePaused\n//CA_LIST* ChipListOpt;\t// ChipListAll minus muted chips\nCA_LIST* CurChipList;\t// pointer to Pause or All [Opt]\n\n#define SMPL_BUFSIZE\t0x100\nstatic INT32* StreamBufs[0x02];\n\n#ifdef MIXER_MUTING\n\n#ifdef WIN32\nHMIXER hmixer;\nMIXERCONTROL mixctrl;\n#else\nint hmixer;\nUINT16 mixer_vol;\n#endif\n\n#else\t//#ifndef MIXER_MUTING\nfloat VolumeBak;\n#endif\n\nUINT32 VGMPos;\nINT32 VGMSmplPos;\nINT32 VGMSmplPlayed;\nINT32 VGMSampleRate;\nstatic UINT32 VGMPbRateMul;\nstatic UINT32 VGMPbRateDiv;\nstatic UINT32 VGMSmplRateMul;\nstatic UINT32 VGMSmplRateDiv;\nstatic UINT32 PauseSmpls;\nbool VGMEnd;\nbool EndPlay;\nbool PausePlay;\nbool FadePlay;\nbool ForceVGMExec;\nUINT8 PlayingMode;\nbool UseFM;\nUINT32 PlayingTime;\nUINT32 FadeStart;\nUINT32 VGMMaxLoopM;\nUINT32 VGMCurLoop;\nfloat VolumeLevelM;\nfloat FinalVol;\nbool ResetPBTimer;\n\nstatic bool Interpreting;\n\n#ifdef CONSOLE_MODE\nextern bool ErrorHappened;\nextern UINT8 CmdList[0x100];\n#endif\n\nUINT8 IsVGMInit;\nUINT16 Last95Drum;\t// for optvgm debugging\nUINT16 Last95Max;\t// for optvgm debugging\nUINT32 Last95Freq;\t// for optvgm debugging\n\nvoid VGMPlay_Init(void)\n{\n\tUINT8 CurChip;\n\tUINT8 CurCSet;\n\tUINT8 CurChn;\n\tCHIP_OPTS* TempCOpt;\n\tCAUD_ATTR* TempCAud;\n\t\n\tSampleRate = 44100;\n\tFadeTime = 5000;\n\tPauseTime = 0;\n\t\n\tHardStopOldVGMs = 0x00;\n\tFadeRAWLog = false;\n\tVolumeLevel = 1.0f;\n\t//FullBufFill = false;\n\tFMPort = 0x0000;\n\tFMForce = false;\n\t//FMAccurate = false;\n\tFMBreakFade = false;\n\tFMVol = 0.0f;\n\tFMOPL2Pan = false;\n\tSurroundSound = false;\n\tVGMMaxLoop = 0x02;\n\tVGMPbRate = 0;\n#ifdef ADDITIONAL_FORMATS\n\tCMFMaxLoop = 0x01;\n#endif\n\tResampleMode = 0x00;\n\tCHIP_SAMPLING_MODE = 0x00;\n\tCHIP_SAMPLE_RATE = 0x00000000;\n\tPauseEmulate = false;\n\tDoubleSSGVol = false;\n\t\n\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t{\n\t\tTempCAud = (CAUD_ATTR*)&ChipAudio[CurCSet];\n\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, TempCAud ++)\n\t\t{\n\t\t\tTempCOpt = (CHIP_OPTS*)&ChipOpts[CurCSet] + CurChip;\n\t\t\t\n\t\t\tTempCOpt->Disabled = false;\n\t\t\tTempCOpt->EmuCore = 0x00;\n\t\t\tTempCOpt->SpecialFlags = 0x00;\n\t\t\tTempCOpt->ChnCnt = 0x00;\n\t\t\tTempCOpt->ChnMute1 = 0x00;\n\t\t\tTempCOpt->ChnMute2 = 0x00;\n\t\t\tTempCOpt->ChnMute3 = 0x00;\n\t\t\tTempCOpt->Panning = NULL;\n\t\t\t\n\t\t\t// Set up some important fields to prevent in_vgm from crashing\n\t\t\t// when clicking on Muting checkboxes after init.\n\t\t\tTempCAud->ChipType = 0xFF;\n\t\t\tTempCAud->ChipID = CurCSet;\n\t\t\tTempCAud->Paired = NULL;\n\t\t}\n\t\tChipOpts[CurCSet].GameBoy.SpecialFlags = 0x0003;\n\t\t// default options, 0x8000 skips the option write and keeps NSFPlay's default values\n\t\t// TODO: Is this really necessary??\n\t\tChipOpts[CurCSet].NES.SpecialFlags = 0x8000 |\n\t\t\t\t\t\t\t\t\t\t(0x00 << 12) | (0x3B << 4) | (0x01 << 2) | (0x03 << 0);\n\t\tChipOpts[CurCSet].SCSP.SpecialFlags = 0x0001;\t// bypass SCSP DSP\n\t\t\n\t\tTempCAud = CA_Paired[CurCSet];\n\t\tfor (CurChip = 0x00; CurChip < 0x03; CurChip ++, TempCAud ++)\n\t\t{\n\t\t\tTempCAud->ChipType = 0xFF;\n\t\t\tTempCAud->ChipID = CurCSet;\n\t\t\tTempCAud->Paired = NULL;\n\t\t}\n\t\t\n\t\t// currently the only chips with Panning support are\n\t\t// SN76496 and YM2413, it should be not a problem that it's hardcoded.\n\t\tTempCOpt = (CHIP_OPTS*)&ChipOpts[CurCSet].SN76496;\n\t\tTempCOpt->ChnCnt = 0x04;\n\t\tTempCOpt->Panning = (INT16*)malloc(sizeof(INT16) * TempCOpt->ChnCnt);\n\t\tfor (CurChn = 0x00; CurChn < TempCOpt->ChnCnt; CurChn ++)\n\t\t\tTempCOpt->Panning[CurChn] = 0x00;\n\t\t\n\t\tTempCOpt = (CHIP_OPTS*)&ChipOpts[CurCSet].YM2413;\n\t\tTempCOpt->ChnCnt = 0x0E;\t// 0x09 + 0x05\n\t\tTempCOpt->Panning = (INT16*)malloc(sizeof(INT16) * TempCOpt->ChnCnt);\n\t\tfor (CurChn = 0x00; CurChn < TempCOpt->ChnCnt; CurChn ++)\n\t\t\tTempCOpt->Panning[CurChn] = 0x00;\n\t}\n\t\n\tfor (CurChn = 0; CurChn < 8; CurChn ++)\n\t\tAppPaths[CurChn] = NULL;\n\tAppPaths[0] = \"\";\n\t\n\tFileMode = 0xFF;\n\t\n\tPausePlay = false;\n\t\n#ifdef _DEBUG\n\tif (sizeof(CHIP_AUDIO) != sizeof(CAUD_ATTR) * CHIP_COUNT)\n\t{\n\t\tfprintf(stderr, \"Fatal Error! ChipAudio structure invalid!\\n\");\n\t\tgetchar();\n\t\texit(-1);\n\t}\n\tif (sizeof(CHIPS_OPTION) != sizeof(CHIP_OPTS) * CHIP_COUNT)\n\t{\n\t\tfprintf(stderr, \"Fatal Error! ChipOpts structure invalid!\\n\");\n\t\tgetchar();\n\t\texit(-1);\n\t}\n#endif\n\t\n\treturn;\n}\n\nvoid VGMPlay_Init2(void)\n{\n\t// has to be called after the configuration is loaded\n\t\n\tif (FMPort)\n\t{\n#if defined(WIN32) && defined(_MSC_VER)\n\t\t__try\n\t\t{\n\t\t\t// should work well with WinXP Compatibility Mode\n\t\t\t_inp(FMPort);\n\t\t\tWINNT_MODE = false;\n\t\t}\n\t\t__except(EXCEPTION_EXECUTE_HANDLER)\n\t\t{\n\t\t\tWINNT_MODE = true;\n\t\t}\n#endif\n\t\t\n\t\tif (! OPL_MODE)\t// OPL not forced\n\t\t\tOPL_Hardware_Detecton();\n\t\tif (! OPL_MODE)\t// no OPL chip found\n\t\t\tFMPort = 0x0000;\t// disable FM\n\t}\n\tif (FMPort)\n\t{\n\t\t// prepare FM Hardware Access and open MIDI Mixer\n#ifdef WIN32\n#ifdef MIXER_MUTING\n\t\tmixerOpen(&hmixer, 0x00, 0x00, 0x00, 0x00);\n\t\tGetMixerControl();\n#endif\n\t\t\n\t\tif (WINNT_MODE)\n\t\t{\n\t\t\tif (OpenPortTalk())\n\t\t\t\treturn;\n\t\t}\n#else\t//#ifndef WIN32\n#ifdef MIXER_MUTING\n\t\thmixer = open(\"/dev/mixer\", O_RDWR);\n#endif\n\t\t\n\t\tif (OpenPortTalk())\n\t\t\treturn;\n#endif\n\t}\n\t\n\tStreamBufs[0x00] = (INT32*)malloc(SMPL_BUFSIZE * sizeof(INT32));\n\tStreamBufs[0x01] = (INT32*)malloc(SMPL_BUFSIZE * sizeof(INT32));\n\t\n\tif (CHIP_SAMPLE_RATE <= 0)\n\t\tCHIP_SAMPLE_RATE = SampleRate;\n\tPlayingMode = 0xFF;\n\t\n\treturn;\n}\n\nvoid VGMPlay_Deinit(void)\n{\n\tUINT8 CurChip;\n\tUINT8 CurCSet;\n\tCHIP_OPTS* TempCOpt;\n\t\n\tif (FMPort)\n\t{\n#ifdef MIXER_MUTING\n#ifdef WIN32\n\t\tmixerClose(hmixer);\n#else\n\t\tclose(hmixer);\n#endif\n#endif\n\t}\n\t\n\tfree(StreamBufs[0x00]);\tStreamBufs[0x00] = NULL;\n\tfree(StreamBufs[0x01]);\tStreamBufs[0x01] = NULL;\n\t\n\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t{\n\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++)\n\t\t{\n\t\t\tTempCOpt = (CHIP_OPTS*)&ChipOpts[CurCSet] + CurChip;\n\t\t\t\n\t\t\tif (TempCOpt->Panning != NULL)\n\t\t\t{\n\t\t\t\tfree(TempCOpt->Panning);\tTempCOpt->Panning = NULL;\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn;\n}\n\n// Note: Caller must free the returned string.\nchar* FindFile(const char* FileName)\n{\n\tchar* FullName;\n\tchar** CurPath;\n\tUINT32 NameLen;\n\tUINT32 PathLen;\n\tUINT32 FullLen;\n\tFILE* hFile;\n\t\n\tNameLen = strlen(FileName);\n\t//printf(\"Find File: %s\\n\", FileName);\n\t\n\t// go to end of the list + get size of largest path\n\t// (The first entry has the lowest priority.)\n\tPathLen = 0;\n\tCurPath = AppPaths;\n\twhile(*CurPath != NULL)\n\t{\n\t\tFullLen = strlen(*CurPath);\n\t\tif (FullLen > PathLen)\n\t\t\tPathLen = FullLen;\n\t\tCurPath ++;\n\t}\n\tCurPath --;\n\tFullLen = PathLen + NameLen;\n\tFullName = (char*)malloc(FullLen + 1);\n\t\n\thFile = NULL;\n\tfor (; CurPath >= AppPaths; CurPath --)\n\t{\n\t\tstrcpy(FullName, *CurPath);\n\t\tstrcat(FullName, FileName);\n\t\t\n\t\t//printf(\"Trying path: %s\\n\", FullName);\n\t\thFile = fopen(FullName, \"r\");\n\t\tif (hFile != NULL)\n\t\t\tbreak;\n\t}\n\t\n\tif (hFile != NULL)\n\t{\n\t\tfclose(hFile);\n\t\t//printf(\"Success!\\n\");\n\t\treturn FullName;\t// The caller has to free the string.\n\t}\n\telse\n\t{\n\t\tfree(FullName);\n\t\t//printf(\"Fail!\\n\");\n\t\treturn NULL;\n\t}\n}\n\nchar* FindFile_List(const char** FileNameList)\n{\n\tchar* FullName;\n\tconst char** CurFile;\n\tchar** CurPath;\n\tchar* PathPtr;\n\tUINT32 NameLen;\n\tUINT32 PathLen;\n\tUINT32 FullLen;\n\tFILE* hFile;\n\t\n\tNameLen = 0;\n\tCurFile = FileNameList;\n\twhile(*CurFile != NULL)\n\t{\n\t\tFullLen = strlen(*CurFile);\n\t\tif (FullLen > NameLen)\n\t\t\tNameLen = FullLen;\n\t\tCurFile ++;\n\t}\n\t\n\t// go to end of the list + get size of largest path\n\t// (The first entry has the lowest priority.)\n\tPathLen = 0;\n\tCurPath = AppPaths;\n\twhile(*CurPath != NULL)\n\t{\n\t\tFullLen = strlen(*CurPath);\n\t\tif (FullLen > PathLen)\n\t\t\tPathLen = FullLen;\n\t\tCurPath ++;\n\t}\n\tCurPath --;\n\tFullLen = PathLen + NameLen;\n\tFullName = (char*)malloc(FullLen + 1);\n\t\n\thFile = NULL;\n\twhile(CurPath >= AppPaths)\n\t{\n\t\tstrcpy(FullName, *CurPath);\n\t\tPathPtr = FullName + strlen(FullName);\n\t\tCurFile = FileNameList;\n\t\twhile(*CurFile != NULL)\n\t\t{\n\t\t\tstrcpy(PathPtr, *CurFile);\n\t\t\t\n\t\t\t//printf(\"Trying path: %s\\n\", FullName);\n\t\t\thFile = fopen(FullName, \"r\");\n\t\t\tif (hFile != NULL)\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tCurFile ++;\n\t\t}\n\t\tif (hFile != NULL)\n\t\t\tbreak;\n\t\t\n\t\tCurPath --;\n\t}\n\t\n\tif (hFile != NULL)\n\t{\n\t\tfclose(hFile);\n\t\t//printf(\"Success!\\n\");\n\t\treturn FullName;\t// The caller has to free the string.\n\t}\n\telse\n\t{\n\t\tfree(FullName);\n\t\t//printf(\"Fail!\\n\");\n\t\treturn NULL;\n\t}\n}\n\n\nINLINE UINT16 ReadLE16(const UINT8* Data)\n{\n\t// read 16-Bit Word (Little Endian/Intel Byte Order)\n#ifdef VGM_LITTLE_ENDIAN\n\treturn *(UINT16*)Data;\n#else\n\treturn (Data[0x01] << 8) | (Data[0x00] << 0);\n#endif\n}\n\nINLINE UINT16 ReadBE16(const UINT8* Data)\n{\n\t// read 16-Bit Word (Big Endian/Motorola Byte Order)\n#ifdef VGM_BIG_ENDIAN\n\treturn *(UINT16*)Data;\n#else\n\treturn (Data[0x00] << 8) | (Data[0x01] << 0);\n#endif\n}\n\nINLINE UINT32 ReadLE24(const UINT8* Data)\n{\n\t// read 24-Bit Word (Little Endian/Intel Byte Order)\n#ifdef VGM_LITTLE_ENDIAN\n\treturn\t(*(UINT32*)Data) & 0x00FFFFFF;\n#else\n\treturn\t(Data[0x02] << 16) | (Data[0x01] <<  8) | (Data[0x00] <<  0);\n#endif\n}\n\nINLINE UINT32 ReadLE32(const UINT8* Data)\n{\n\t// read 32-Bit Word (Little Endian/Intel Byte Order)\n#ifdef VGM_LITTLE_ENDIAN\n\treturn\t*(UINT32*)Data;\n#else\n\treturn\t(Data[0x03] << 24) | (Data[0x02] << 16) |\n\t\t\t(Data[0x01] <<  8) | (Data[0x00] <<  0);\n#endif\n}\n\nINLINE int gzgetLE16(gzFile hFile, UINT16* RetValue)\n{\n#ifdef VGM_LITTLE_ENDIAN\n\treturn gzread(hFile, RetValue, 0x02);\n#else\n\tint RetVal;\n\tUINT8 Data[0x02];\n\t\n\tRetVal = gzread(hFile, Data, 0x02);\n\t*RetValue =\t(Data[0x01] << 8) | (Data[0x00] << 0);\n\treturn RetVal;\n#endif\n}\n\nINLINE int gzgetLE32(gzFile hFile, UINT32* RetValue)\n{\n#ifdef VGM_LITTLE_ENDIAN\n\treturn gzread(hFile, RetValue, 0x04);\n#else\n\tint RetVal;\n\tUINT8 Data[0x04];\n\t\n\tRetVal = gzread(hFile, Data, 0x04);\n\t*RetValue =\t(Data[0x03] << 24) | (Data[0x02] << 16) |\n\t\t\t\t(Data[0x01] <<  8) | (Data[0x00] <<  0);\n\treturn RetVal;\n#endif\n}\n\nstatic UINT32 gcd(UINT32 x, UINT32 y)\n{\n\tUINT32 shift;\n\tUINT32 diff;\n\t\n\t// Thanks to Wikipedia for this algorithm\n\t// http://en.wikipedia.org/wiki/Binary_GCD_algorithm\n\tif (! x || ! y)\n\t\treturn x | y;\n\t\n\tfor (shift = 0; ((x | y) & 1) == 0; shift ++)\n\t{\n\t\tx >>= 1;\n\t\ty >>= 1;\n\t}\n\t\n\twhile((x & 1) == 0)\n\t\tx >>= 1;\n\t\n\tdo\n\t{\n\t\twhile((y & 1) == 0)\n\t\t\ty >>= 1;\n\t\t\n\t\tif (x < y)\n\t\t{\n\t\t\ty -= x;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdiff = x - y;\n\t\t\tx = y;\n\t\t\ty = diff;\n\t\t}\n\t\ty >>= 1;\n\t} while(y);\n\t\n\treturn x << shift;\n}\n\nvoid PlayVGM(void)\n{\n\tUINT8 CurChip;\n\tUINT8 FMVal;\n\tINT32 TempSLng;\n\t\n\tif (PlayingMode != 0xFF)\n\t\treturn;\n\t\n\t//PausePlay = false;\n\tFadePlay = false;\n\tMasterVol = 1.0f;\n\tForceVGMExec = false;\n\tAutoStopSkip = false;\n\tFadeStart = 0;\n\tForceVGMExec = true;\n\tPauseThread = true;\n\t\n\t// FM Check\n\tFMVal = 0x00;\n\tif (FMPort)\n\t{\n\t\t// check usage of devices that use the FM port, and ones that don't use it\n\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++)\n\t\t{\n\t\t\tif (! GetChipClock(&VGMHead, CurChip, NULL))\n\t\t\t\tcontinue;\n\t\t\t\n\t\t\t// supported chips are:\n\t\t\t//\tSN76496 (0x00, special behaviour), YM2413 (0x01)\n\t\t\t//\tYM3812 (0x09), YM3526 (0x0A), Y8950 (0x0B), YMF262 (0x0C)\n\t\t\tif (CurChip == 0x00 || CurChip == 0x12)\n\t\t\t\t\t\t\t\t\t// The SN76496 and AY8910 have a special state because of\n\t\t\t\tFMVal |= 0x04;\t\t// bad FM emulation and fast software emulation.\n\t\t\telse if (CurChip == 0x01 || (CurChip >= 0x09 && CurChip <= 0x0C))\n\t\t\t\tFMVal |= 0x02;\n\t\t\telse\n\t\t\t\tFMVal |= 0x01;\n\t\t}\n\t\t\n\t\tif (! FMForce)\n\t\t{\n\t\t\tif (FMVal & 0x01)\t// one or more software emulators used?\n\t\t\t\tFMVal &= ~0x02;\t// use only software emulation\n\t\t\t\n\t\t\tif (FMVal == 0x04)\n\t\t\t\tFMVal = 0x01;\t// FM SN76496 emulaton is bad\n\t\t\telse if ((FMVal & 0x05) == 0x05)\n\t\t\t\tFMVal &= ~0x04;\t// prefer software SN76496 instead of unsynced output\n\t\t}\n\t\tFMVal = (FMVal & ~0x04) | ((FMVal & 0x04) >> 1);\n\t}\n\tswitch(FMVal)\n\t{\n\tcase 0x00:\n\tcase 0x01:\n\t\tPlayingMode = 0x00;\t// Normal Mode\n\t\tbreak;\n\tcase 0x02:\n\t\tPlayingMode = 0x01;\t// FM only Mode\n\t\tbreak;\n\tcase 0x03:\n\t\tPlayingMode = 0x02;\t// Normal/FM mixed Mode (NOT in sync, Hardware is a lot faster)\n\t\t//PlayingMode = 0x00;\t// Force Normal Mode until I get them in sync - Mixed Mode\n\t\t\t\t\t\t\t\t// sounds terrible\n\t\tbreak;\n\t}\n\tUseFM = (PlayingMode > 0x00);\n\t\n\tif (VGMHead.bytVolumeModifier <= VOLUME_MODIF_WRAP)\n\t\tTempSLng = VGMHead.bytVolumeModifier;\n\telse if (VGMHead.bytVolumeModifier == (VOLUME_MODIF_WRAP + 0x01))\n\t\tTempSLng = VOLUME_MODIF_WRAP - 0x100;\n\telse\n\t\tTempSLng = VGMHead.bytVolumeModifier - 0x100;\n\tVolumeLevelM = (float)(VolumeLevel * pow(2.0, TempSLng / (double)0x20));\n\tif (UseFM)\n\t{\n\t\tif (FMVol > 0.0f)\n\t\t\tVolumeLevelM = FMVol;\n\t\telse if (FMVol < 0.0f)\n\t\t\tVolumeLevelM *= -FMVol;\n\t}\n\tFinalVol = VolumeLevelM;\n\t\n\tif (! VGMMaxLoop)\n\t{\n\t\tVGMMaxLoopM = 0x00;\n\t}\n\telse\n\t{\n\t\tTempSLng = (VGMMaxLoop * VGMHead.bytLoopModifier + 0x08) / 0x10 - VGMHead.bytLoopBase;\n\t\tVGMMaxLoopM = (TempSLng >= 0x01) ? TempSLng : 0x01;\n\t}\n\t\n\tif (! VGMPbRate || ! VGMHead.lngRate)\n\t{\n\t\tVGMPbRateMul = 1;\n\t\tVGMPbRateDiv = 1;\n\t}\n\telse\n\t{\n\t\t// I prefer small Multiplers and Dividers, as they're used very often\n\t\tTempSLng = gcd(VGMHead.lngRate, VGMPbRate);\n\t\tVGMPbRateMul = VGMHead.lngRate / TempSLng;\n\t\tVGMPbRateDiv = VGMPbRate / TempSLng;\n\t}\n\tVGMSmplRateMul = SampleRate * VGMPbRateMul;\n\tVGMSmplRateDiv = VGMSampleRate * VGMPbRateDiv;\n\t// same as above - to speed up the VGM <-> Playback calculation\n\tTempSLng = gcd(VGMSmplRateMul, VGMSmplRateDiv);\n\tVGMSmplRateMul /= TempSLng;\n\tVGMSmplRateDiv /= TempSLng;\n\t\n\tPlayingTime = 0;\n\tEndPlay = false;\n\t\n\tVGMPos = VGMHead.lngDataOffset;\n\tVGMSmplPos = 0;\n\tVGMSmplPlayed = 0;\n\tVGMEnd = false;\n\tVGMCurLoop = 0x00;\n\tPauseSmpls = (PauseTime * SampleRate + 500) / 1000;\n\tif (VGMPos >= VGMHead.lngEOFOffset)\n\t\tVGMEnd = true;\n\t\n#ifdef CONSOLE_MODE\n\tmemset(CmdList, 0x00, 0x100 * sizeof(UINT8));\n#endif\n\t\n\tif (! PauseEmulate)\n\t{\n\t\tswitch(PlayingMode)\n\t\t{\n\t\tcase 0x00:\n\t\t\t//PauseStream(PausePlay);\n\t\t\tbreak;\n\t\tcase 0x01:\n\t\t\t//PauseThread = PausePlay;\n\t\t\tSetMuteControl(PausePlay);\n\t\t\tbreak;\n\t\tcase 0x02:\n\t\t\t//PauseStream(PausePlay);\n\t\t\tSetMuteControl(PausePlay);\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tChips_GeneralActions(0x00);\t// Start chips\n\t// also does Reset (0x01), Muting Mask (0x10) and Panning (0x20)\n\t\n\tif (UseFM)\n\t{\n\t\t// TODO: get FirstInit working\n\t\t//if (! FirstInit)\n\t\t{\n\t\t\tStartSkipping();\t// don't apply OPL Reset to make Track changes smooth\n\t\t\tAutoStopSkip = true;\n\t\t}\n\t\topen_real_fm();\n\t}\n\t\n\tswitch(PlayingMode)\n\t{\n\tcase 0x00:\t// the application controls the playback thread\n\t\tbreak;\n\tcase 0x01:\t// FM Playback needs an independent thread\n\t\tResetPBTimer = false;\n\t\tif (StartThread())\n\t\t{\n\t\t\tfprintf(stderr, \"Error starting Playing Thread!\\n\");\n\t\t\treturn;\n\t\t}\n#ifdef CONSOLE_MODE\n\t\tPauseStream(true);\n#endif\n\t\tbreak;\n\tcase 0x02:\t// like Mode 0x00, but Hardware is also controlled (not synced)\n\t\tbreak;\n\t}\n\t\n\tLast95Drum = 0xFFFF;\n\tLast95Freq = 0;\n\tLast95Max = 0xFFFF;\n\tIsVGMInit = true;\n\tInterpreting = false;\n\tInterpretFile(0);\n\tIsVGMInit = false;\n\t\n\tPauseThread = false;\n\tAutoStopSkip = true;\n\tForceVGMExec = false;\n\t\n\treturn;\n}\n\nvoid StopVGM(void)\n{\n\tif (PlayingMode == 0xFF)\n\t\treturn;\n\t\n\tif (! PauseEmulate)\n\t{\n\t\tif (UseFM && PausePlay)\n\t\t\tSetMuteControl(false);\n\t}\n\t\n\tswitch(PlayingMode)\n\t{\n\tcase 0x00:\n\t\tbreak;\n\tcase 0x01:\n\t\tStopThread();\n\t\t/*if (SmoothTrackChange)\n\t\t{\n\t\t\tif (ThreadPauseEnable)\n\t\t\t{\n\t\t\t\tThreadPauseConfrm = false;\n\t\t\t\tPauseThread = true;\n\t\t\t\twhile(! ThreadPauseConfrm)\n\t\t\t\t\tSleep(1);\t// Wait until the Thread is finished\n\t\t\t}\n\t\t}*/\n\t\tbreak;\n\tcase 0x02:\n\t\tbreak;\n\t}\n\t\n\tChips_GeneralActions(0x02);\t// Stop chips\n\tif (UseFM)\n\t\tclose_real_fm();\n\tPlayingMode = 0xFF;\n\t\n\treturn;\n}\n\nvoid RestartVGM(void)\n{\n\tif (PlayingMode == 0xFF || ! VGMSmplPlayed)\n\t\treturn;\n\t\n\tRestartPlaying();\n\t\n\treturn;\n}\n\nvoid PauseVGM(bool Pause)\n{\n\tif (PlayingMode == 0xFF || Pause == PausePlay)\n\t\treturn;\n\t\n\t// now uses a temporary variable to avoid gaps (especially with DAC Stream Controller)\n\tif (! PauseEmulate)\n\t{\n\t\tif (Pause && ThreadPauseEnable)\n\t\t{\n\t\t\tThreadPauseConfrm = false;\n\t\t\tPauseThread = true;\n\t\t}\n\t\tswitch(PlayingMode)\n\t\t{\n\t\tcase 0x00:\n#ifdef CONSOLE_MODE\n\t\t\tPauseStream(Pause);\n#endif\n\t\t\tbreak;\n\t\tcase 0x01:\n\t\t\tThreadNoWait = false;\n\t\t\tSetMuteControl(Pause);\n\t\t\tbreak;\n\t\tcase 0x02:\n#ifdef CONSOLE_MODE\n\t\t\tPauseStream(Pause);\n#endif\n\t\t\tSetMuteControl(Pause);\n\t\t\tbreak;\n\t\t}\n\t\tif (Pause && ThreadPauseEnable)\n\t\t{\n\t\t\twhile(! ThreadPauseConfrm)\n\t\t\t\tSleep(1);\t// Wait until the Thread is finished\n\t\t}\n\t\tPauseThread = Pause;\n\t}\n\tPausePlay = Pause;\n\t\n\treturn;\n}\n\nvoid SeekVGM(bool Relative, INT32 PlayBkSamples)\n{\n\tINT32 Samples;\n\tUINT32 LoopSmpls;\n\t\n\tif (PlayingMode == 0xFF || (Relative && ! PlayBkSamples))\n\t\treturn;\n\t\n\tLoopSmpls = VGMCurLoop * SampleVGM2Pbk_I(VGMHead.lngLoopSamples);\n\tif (! Relative)\n\t\tSamples = PlayBkSamples - (LoopSmpls + VGMSmplPlayed);\n\telse\n\t\tSamples = PlayBkSamples;\n\t\n\tThreadNoWait = false;\n\tPauseThread = true;\n\tif (UseFM)\n\t\tStartSkipping();\n\tif (Samples < 0)\n\t{\n\t\tSamples = LoopSmpls + VGMSmplPlayed + Samples;\n\t\tif (Samples < 0)\n\t\t\tSamples = 0;\n\t\tRestartPlaying();\n\t}\n\t\n\tForceVGMExec = true;\n\tInterpretFile(Samples);\n\tForceVGMExec = false;\n#ifdef CONSOLE_MODE\n\tif (FadePlay && FadeStart)\n\t\tFadeStart += Samples;\n#endif\n\tif (UseFM)\n\t\tStopSkipping();\n\tPauseThread = PausePlay;\n\t\n\treturn;\n}\n\nvoid RefreshMuting(void)\n{\n\tChips_GeneralActions(0x10);\t// set muting mask\n\t\n\treturn;\n}\n\nvoid RefreshPanning(void)\n{\n\tChips_GeneralActions(0x20);\t// set panning\n\t\n\treturn;\n}\n\nvoid RefreshPlaybackOptions(void)\n{\n\tINT32 TempVol;\n\tUINT8 CurChip;\n\tCHIP_OPTS* TempCOpt1;\n\tCHIP_OPTS* TempCOpt2;\n\t\n\tif (VGMHead.bytVolumeModifier <= VOLUME_MODIF_WRAP)\n\t\tTempVol = VGMHead.bytVolumeModifier;\n\telse if (VGMHead.bytVolumeModifier == (VOLUME_MODIF_WRAP + 0x01))\n\t\tTempVol = VOLUME_MODIF_WRAP - 0x100;\n\telse\n\t\tTempVol = VGMHead.bytVolumeModifier - 0x100;\n\tVolumeLevelM = (float)(VolumeLevel * pow(2.0, TempVol / (double)0x20));\n\tif (UseFM)\n\t{\n\t\tif (FMVol > 0.0f)\n\t\t\tVolumeLevelM = FMVol;\n\t\telse if (FMVol < 0.0f)\n\t\t\tVolumeLevelM *= -FMVol;\n\t}\n\tFinalVol = VolumeLevelM * MasterVol * MasterVol;\n\t\n\t//PauseSmpls = (PauseTime * SampleRate + 500) / 1000;\n\t\n\tif (PlayingMode == 0xFF)\n\t{\n\t\tTempCOpt1 = (CHIP_OPTS*)&ChipOpts[0x00];\n\t\tTempCOpt2 = (CHIP_OPTS*)&ChipOpts[0x01];\n\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, TempCOpt1 ++, TempCOpt2 ++)\n\t\t{\n\t\t\tTempCOpt2->EmuCore = TempCOpt1->EmuCore;\n\t\t\tTempCOpt2->SpecialFlags = TempCOpt1->SpecialFlags;\n\t\t}\n\t}\n\t\n\treturn;\n}\n\n\nUINT32 GetGZFileLength(const char* FileName)\n{\n\tFILE* hFile;\n\tUINT32 FileSize;\n\t\n\thFile = fopen(FileName, \"rb\");\n\tif (hFile == NULL)\n\t\treturn 0xFFFFFFFF;\n\t\n\tFileSize = GetGZFileLength_Internal(hFile);\n\t\n\tfclose(hFile);\n\treturn FileSize;\n}\n\n#ifndef NO_WCHAR_FILENAMES\nUINT32 GetGZFileLengthW(const wchar_t* FileName)\n{\n\tFILE* hFile;\n\tUINT32 FileSize;\n\t\n\thFile = _wfopen(FileName, L\"rb\");\n\tif (hFile == NULL)\n\t\treturn 0xFFFFFFFF;\n\t\n\tFileSize = GetGZFileLength_Internal(hFile);\n\t\n\tfclose(hFile);\n\treturn FileSize;\n}\n#endif\n\nstatic UINT32 GetGZFileLength_Internal(FILE* hFile)\n{\n\tUINT32 FileSize;\n\tUINT16 gzHead;\n\tsize_t RetVal;\n\t\n\tRetVal = fread(&gzHead, 0x02, 0x01, hFile);\n\tif (RetVal >= 1)\n\t{\n\t\tgzHead = ReadBE16((UINT8*)&gzHead);\n\t\tif (gzHead != 0x1F8B)\n\t\t{\n\t\t\tRetVal = 0;\t// no .gz signature - treat as normal file\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// .gz File\n\t\t\tfseek(hFile, -4, SEEK_END);\n\t\t\t// Note: In the error case it falls back to fseek/ftell.\n\t\t\tRetVal = fread(&FileSize, 0x04, 0x01, hFile);\n#ifndef VGM_LITTLE_ENDIAN\n\t\t\tFileSize = ReadLE32((UINT8*)&FileSize);\n#endif\n\t\t}\n\t}\n\tif (RetVal <= 0)\n\t{\n\t\t// normal file\n\t\tfseek(hFile, 0x00, SEEK_END);\n\t\tFileSize = ftell(hFile);\n\t}\n\t\n\treturn FileSize;\n}\n\nbool OpenVGMFile(const char* FileName)\n{\n\tgzFile hFile;\n\tUINT32 FileSize;\n\tbool RetVal;\n\t\n\tFileSize = GetGZFileLength(FileName);\n\t\n\thFile = gzopen(FileName, \"rb\");\n\tif (hFile == NULL)\n\t\treturn false;\n\t\n\tRetVal = OpenVGMFile_Internal(hFile, FileSize);\n\t\n\tgzclose(hFile);\n\treturn RetVal;\n}\n\n#ifndef NO_WCHAR_FILENAMES\nbool OpenVGMFileW(const wchar_t* FileName)\n{\n\tgzFile hFile;\n\tUINT32 FileSize;\n\tbool RetVal;\n#if ZLIB_VERNUM < 0x1270\n\tint fDesc;\n\t\n\tFileSize = GetGZFileLengthW(FileName);\n\t\n\tfDesc = _wopen(FileName, _O_RDONLY | _O_BINARY);\n\thFile = gzdopen(fDesc, \"rb\");\n\tif (hFile == NULL)\n\t{\n\t\t_close(fDesc);\n\t\treturn false;\n\t}\n#else\n\tFileSize = GetGZFileLengthW(FileName);\n\t\n\thFile = gzopen_w(FileName, \"rb\");\n\tif (hFile == NULL)\n\t\treturn false;\n#endif\n\t\n\tRetVal = OpenVGMFile_Internal(hFile, FileSize);\n\t\n\tgzclose(hFile);\n\treturn RetVal;\n}\n#endif\n\nstatic bool OpenVGMFile_Internal(gzFile hFile, UINT32 FileSize)\n{\n\tUINT32 fccHeader;\n\tUINT32 CurPos;\n\tUINT32 HdrLimit;\n\t\n\t//gzseek(hFile, 0x00, SEEK_SET);\n\tgzrewind(hFile);\n\tgzgetLE32(hFile, &fccHeader);\n\tif (fccHeader != FCC_VGM)\n\t\treturn false;\n\t\n\tif (FileMode != 0xFF)\n\t\tCloseVGMFile();\n\t\n\tFileMode = 0x00;\n\tVGMDataLen = FileSize;\n\t\n\tgzseek(hFile, 0x00, SEEK_SET);\n\t//gzrewind(hFile);\n\tReadVGMHeader(hFile, &VGMHead);\n\tif (VGMHead.fccVGM != FCC_VGM)\n\t{\n\t\tfprintf(stderr, \"VGM signature matched on the first read, but not on the second one!\\n\");\n\t\tfprintf(stderr, \"This is a known zlib bug where gzseek fails. Please install a fixed zlib.\\n\");\n\t\treturn false;\n\t}\n\t\n\tVGMSampleRate = 44100;\n\tif (! VGMDataLen)\n\t\tVGMDataLen = VGMHead.lngEOFOffset;\n\tif (! VGMHead.lngEOFOffset || VGMHead.lngEOFOffset > VGMDataLen)\n\t{\n\t\tfprintf(stderr, \"Warning! Invalid EOF Offset 0x%02X! (should be: 0x%02X)\\n\",\n\t\t\t\tVGMHead.lngEOFOffset, VGMDataLen);\n\t\tVGMHead.lngEOFOffset = VGMDataLen;\n\t}\n\tif (VGMHead.lngLoopOffset && ! VGMHead.lngLoopSamples)\n\t{\n\t\t// 0-Sample-Loops causes the program to hangs in the playback routine\n\t\tfprintf(stderr, \"Warning! Ignored Zero-Sample-Loop!\\n\");\n\t\tVGMHead.lngLoopOffset = 0x00000000;\n\t}\n\tif (VGMHead.lngDataOffset < 0x00000040)\n\t{\n\t\tfprintf(stderr, \"Warning! Invalid Data Offset 0x%02X!\\n\", VGMHead.lngDataOffset);\n\t\tVGMHead.lngDataOffset = 0x00000040;\n\t}\n\t\n\tmemset(&VGMHeadX, 0x00, sizeof(VGM_HDR_EXTRA));\n\tmemset(&VGMH_Extra, 0x00, sizeof(VGM_EXTRA));\n\t\n\t// Read Data\n\tVGMDataLen = VGMHead.lngEOFOffset;\n\tVGMData = (UINT8*)malloc(VGMDataLen);\n\tif (VGMData == NULL)\n\t\treturn false;\n\t//gzseek(hFile, 0x00, SEEK_SET);\n\tgzrewind(hFile);\n\tgzread(hFile, VGMData, VGMDataLen);\n\t\n\t// Read Extra Header Data\n\tif (VGMHead.lngExtraOffset)\n\t{\n\t\tUINT32* TempPtr;\n\t\t\n\t\tCurPos = VGMHead.lngExtraOffset;\n\t\tTempPtr = (UINT32*)&VGMHeadX;\n\t\t// Read Header Size\n\t\tVGMHeadX.DataSize = ReadLE32(&VGMData[CurPos]);\n\t\tif (VGMHeadX.DataSize > sizeof(VGM_HDR_EXTRA))\n\t\t\tVGMHeadX.DataSize = sizeof(VGM_HDR_EXTRA);\n\t\tHdrLimit = CurPos + VGMHeadX.DataSize;\n\t\tCurPos += 0x04;\n\t\tTempPtr ++;\n\t\t\n\t\t// Read all relative offsets of this header and make them absolute.\n\t\tfor (; CurPos < HdrLimit; CurPos += 0x04, TempPtr ++)\n\t\t{\n\t\t\t*TempPtr = ReadLE32(&VGMData[CurPos]);\n\t\t\tif (*TempPtr)\n\t\t\t\t*TempPtr += CurPos;\n\t\t}\n\t\t\n\t\tReadChipExtraData32(VGMHeadX.Chp2ClkOffset, &VGMH_Extra.Clocks);\n\t\tReadChipExtraData16(VGMHeadX.ChpVolOffset, &VGMH_Extra.Volumes);\n\t}\n\t\n\t// Read GD3 Tag\n\tHdrLimit = ReadGD3Tag(hFile, VGMHead.lngGD3Offset, &VGMTag);\n\tif (HdrLimit == 0x10)\n\t{\n\t\tVGMHead.lngGD3Offset = 0x00000000;\n\t\t//return false;\n\t}\n\tif (! VGMHead.lngGD3Offset)\n\t{\n\t\t// replace all NULL pointers with empty strings\n\t\tVGMTag.strTrackNameE = MakeEmptyWStr();\n\t\tVGMTag.strTrackNameJ = MakeEmptyWStr();\n\t\tVGMTag.strGameNameE = MakeEmptyWStr();\n\t\tVGMTag.strGameNameJ = MakeEmptyWStr();\n\t\tVGMTag.strSystemNameE = MakeEmptyWStr();\n\t\tVGMTag.strSystemNameJ = MakeEmptyWStr();\n\t\tVGMTag.strAuthorNameE = MakeEmptyWStr();\n\t\tVGMTag.strAuthorNameJ = MakeEmptyWStr();\n\t\tVGMTag.strReleaseDate = MakeEmptyWStr();\n\t\tVGMTag.strCreator = MakeEmptyWStr();\n\t\tVGMTag.strNotes = MakeEmptyWStr();\n\t}\n\t\n\treturn true;\n}\n\nstatic void ReadVGMHeader(gzFile hFile, VGM_HEADER* RetVGMHead)\n{\n\tVGM_HEADER CurHead;\n\tUINT32 CurPos;\n\tUINT32 HdrLimit;\n\t\n\tgzread(hFile, &CurHead, sizeof(VGM_HEADER));\n#ifndef VGM_LITTLE_ENDIAN\n\t{\n\t\tUINT8* TempPtr;\n\t\t\n\t\t// Warning: Lots of pointer casting ahead!\n\t\tfor (CurPos = 0x00; CurPos < sizeof(VGM_HEADER); CurPos += 0x04)\n\t\t{\n\t\t\tTempPtr = (UINT8*)&CurHead + CurPos;\n\t\t\tswitch(CurPos)\n\t\t\t{\n\t\t\tcase 0x28:\n\t\t\t\t// 0x28\t[16-bit] SN76496 Feedback Mask\n\t\t\t\t// 0x2A\t[ 8-bit] SN76496 Shift Register Width\n\t\t\t\t// 0x2B\t[ 8-bit] SN76496 Flags\n\t\t\t\t*(UINT16*)TempPtr = ReadLE16(TempPtr);\n\t\t\t\tbreak;\n\t\t\tcase 0x78:\t// 78-7B [8-bit] AY8910 Type/Flags\n\t\t\tcase 0x7C:\t// 7C-7F [8-bit] Volume/Loop Modifiers\n\t\t\tcase 0x94:\t// 94-97 [8-bit] various flags\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// everything else is 32-bit\n\t\t\t\t*(UINT32*)TempPtr = ReadLE32(TempPtr);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\t\n\t// Header preperations\n\tif (CurHead.lngVersion < 0x00000101)\n\t{\n\t\tCurHead.lngRate = 0;\n\t}\n\tif (CurHead.lngVersion < 0x00000110)\n\t{\n\t\tCurHead.shtPSG_Feedback = 0x0000;\n\t\tCurHead.bytPSG_SRWidth = 0x00;\n\t\tCurHead.lngHzYM2612 = CurHead.lngHzYM2413;\n\t\tCurHead.lngHzYM2151 = CurHead.lngHzYM2413;\n\t}\n\tif (CurHead.lngVersion < 0x00000150)\n\t{\n\t\tCurHead.lngDataOffset = 0x00000000;\n\t// If I would aim to be very strict, I would uncomment these few lines,\n\t// but I sometimes use v1.51 Flags with v1.50 for better compatibility.\n\t// (Some hyper-strict players refuse to play v1.51 files, even if there's\n\t//  no new chip used.)\n\t//}\n\t//if (CurHead.lngVersion < 0x00000151)\n\t//{\n\t\tCurHead.bytPSG_Flags = 0x00;\n\t\tCurHead.lngHzSPCM = 0x0000;\n\t\tCurHead.lngSPCMIntf = 0x00000000;\n\t\t// all others are zeroed by memset\n\t}\n\t\n\tif (CurHead.lngHzPSG)\n\t{\n\t\tif (! CurHead.shtPSG_Feedback)\n\t\t\tCurHead.shtPSG_Feedback = 0x0009;\n\t\tif (! CurHead.bytPSG_SRWidth)\n\t\t\tCurHead.bytPSG_SRWidth = 0x10;\n\t}\n\t\n\t// relative -> absolute addresses\n\tif (CurHead.lngEOFOffset)\n\t\tCurHead.lngEOFOffset += 0x00000004;\n\tif (CurHead.lngGD3Offset)\n\t\tCurHead.lngGD3Offset += 0x00000014;\n\tif (CurHead.lngLoopOffset)\n\t\tCurHead.lngLoopOffset += 0x0000001C;\n\t\n\tif (CurHead.lngVersion < 0x00000150)\n\t\tCurHead.lngDataOffset = 0x0000000C;\n\t//if (CurHead.lngDataOffset < 0x0000000C)\n\t//\tCurHead.lngDataOffset = 0x0000000C;\n\tif (CurHead.lngDataOffset)\n\t\tCurHead.lngDataOffset += 0x00000034;\n\t\n\tCurPos = CurHead.lngDataOffset;\n\t// should actually check v1.51 (first real usage of DataOffset)\n\t// v1.50 is checked to support things like the Volume Modifiers in v1.50 files\n\tif (CurHead.lngVersion < 0x00000150 /*0x00000151*/)\n\t\tCurPos = 0x40;\n\tif (! CurPos)\n\t\tCurPos = 0x40;\n\tHdrLimit = sizeof(VGM_HEADER);\n\tif (HdrLimit > CurPos)\n\t\tmemset((UINT8*)&CurHead + CurPos, 0x00, HdrLimit - CurPos);\n\t\n\tif (! CurHead.bytLoopModifier)\n\t\tCurHead.bytLoopModifier = 0x10;\n\t\n\tif (CurHead.lngExtraOffset)\n\t{\n\t\tCurHead.lngExtraOffset += 0xBC;\n\t\t\n\t\tCurPos = CurHead.lngExtraOffset;\n\t\tif (CurPos < HdrLimit)\n\t\t\tmemset((UINT8*)&CurHead + CurPos, 0x00, HdrLimit - CurPos);\n\t}\n\t\n\tif (CurHead.lngGD3Offset >= CurHead.lngEOFOffset)\n\t\tCurHead.lngGD3Offset = 0x00;\n\tif (CurHead.lngLoopOffset >= CurHead.lngEOFOffset)\n\t\tCurHead.lngLoopOffset = 0x00;\n\tif (CurHead.lngDataOffset >= CurHead.lngEOFOffset)\n\t\tCurHead.lngDataOffset = 0x40;\n\tif (CurHead.lngExtraOffset >= CurHead.lngEOFOffset)\n\t\tCurHead.lngExtraOffset = 0x00;\n\t\n\t*RetVGMHead = CurHead;\n\treturn;\n}\n\nstatic UINT8 ReadGD3Tag(gzFile hFile, UINT32 GD3Offset, GD3_TAG* RetGD3Tag)\n{\n\tUINT32 CurPos;\n\tUINT32 TempLng;\n\tUINT8 ResVal;\n\t\n\tResVal = 0x00;\n\t\n\t// Read GD3 Tag\n\tif (GD3Offset)\n\t{\n\t\tgzseek(hFile, GD3Offset, SEEK_SET);\n\t\tgzgetLE32(hFile, &TempLng);\n\t\tif (TempLng != FCC_GD3)\n\t\t{\n\t\t\tGD3Offset = 0x00000000;\n\t\t\tResVal = 0x10;\t// invalid GD3 offset\n\t\t}\n\t}\n\t\n\tif (RetGD3Tag == NULL)\n\t\treturn ResVal;\n\t\n\tif (! GD3Offset)\n\t{\n\t\tRetGD3Tag->fccGD3 = 0x00000000;\n\t\tRetGD3Tag->lngVersion = 0x00000000;\n\t\tRetGD3Tag->lngTagLength = 0x00000000;\n\t\tRetGD3Tag->strTrackNameE = NULL;\n\t\tRetGD3Tag->strTrackNameJ = NULL;\n\t\tRetGD3Tag->strGameNameE = NULL;\n\t\tRetGD3Tag->strGameNameJ = NULL;\n\t\tRetGD3Tag->strSystemNameE = NULL;\n\t\tRetGD3Tag->strSystemNameJ = NULL;\n\t\tRetGD3Tag->strAuthorNameE = NULL;\n\t\tRetGD3Tag->strAuthorNameJ = NULL;\n\t\tRetGD3Tag->strReleaseDate = NULL;\n\t\tRetGD3Tag->strCreator = NULL;\n\t\tRetGD3Tag->strNotes = NULL;\n\t}\n\telse\n\t{\n\t\t//CurPos = GD3Offset;\n\t\t//gzseek(hFile, CurPos, SEEK_SET);\n\t\t//CurPos += gzgetLE32(hFile, &RetGD3Tag->fccGD3);\n\t\t\n\t\tCurPos = GD3Offset + 0x04;\t\t// Save some back seeking, yay!\n\t\tRetGD3Tag->fccGD3 = TempLng;\t// (That costs lots of CPU in .gz files.)\n\t\tCurPos += gzgetLE32(hFile, &RetGD3Tag->lngVersion);\n\t\tCurPos += gzgetLE32(hFile, &RetGD3Tag->lngTagLength);\n\t\t\n\t\tTempLng = CurPos + RetGD3Tag->lngTagLength;\n\t\tRetGD3Tag->strTrackNameE =\tReadWStrFromFile(hFile, &CurPos, TempLng);\n\t\tRetGD3Tag->strTrackNameJ =\tReadWStrFromFile(hFile, &CurPos, TempLng);\n\t\tRetGD3Tag->strGameNameE =\tReadWStrFromFile(hFile, &CurPos, TempLng);\n\t\tRetGD3Tag->strGameNameJ =\tReadWStrFromFile(hFile, &CurPos, TempLng);\n\t\tRetGD3Tag->strSystemNameE =\tReadWStrFromFile(hFile, &CurPos, TempLng);\n\t\tRetGD3Tag->strSystemNameJ =\tReadWStrFromFile(hFile, &CurPos, TempLng);\n\t\tRetGD3Tag->strAuthorNameE =\tReadWStrFromFile(hFile, &CurPos, TempLng);\n\t\tRetGD3Tag->strAuthorNameJ =\tReadWStrFromFile(hFile, &CurPos, TempLng);\n\t\tRetGD3Tag->strReleaseDate =\tReadWStrFromFile(hFile, &CurPos, TempLng);\n\t\tRetGD3Tag->strCreator =\t\tReadWStrFromFile(hFile, &CurPos, TempLng);\n\t\tRetGD3Tag->strNotes =\t\tReadWStrFromFile(hFile, &CurPos, TempLng);\n\t}\n\t\n\treturn ResVal;\n}\n\nstatic void ReadChipExtraData32(UINT32 StartOffset, VGMX_CHP_EXTRA32* ChpExtra)\n{\n\tUINT32 CurPos;\n\tUINT8 CurChp;\n\tVGMX_CHIP_DATA32* TempCD;\n\t\n\tif (! StartOffset || StartOffset >= VGMDataLen)\n\t{\n\t\tChpExtra->ChipCnt = 0x00;\n\t\tChpExtra->CCData = NULL;\n\t\treturn;\n\t}\n\t\n\tCurPos = StartOffset;\n\tChpExtra->ChipCnt = VGMData[CurPos];\n\tif (ChpExtra->ChipCnt)\n\t\tChpExtra->CCData = (VGMX_CHIP_DATA32*)malloc(sizeof(VGMX_CHIP_DATA32) *\n\t\t\t\t\t\t\t\t\t\t\t\t\tChpExtra->ChipCnt);\n\telse\n\t\tChpExtra->CCData = NULL;\n\tCurPos ++;\n\t\n\tfor (CurChp = 0x00; CurChp < ChpExtra->ChipCnt; CurChp ++)\n\t{\n\t\tTempCD = &ChpExtra->CCData[CurChp];\n\t\tTempCD->Type = VGMData[CurPos + 0x00];\n\t\tTempCD->Data = ReadLE32(&VGMData[CurPos + 0x01]);\n\t\tCurPos += 0x05;\n\t}\n\t\n\treturn;\n}\n\nstatic void ReadChipExtraData16(UINT32 StartOffset, VGMX_CHP_EXTRA16* ChpExtra)\n{\n\tUINT32 CurPos;\n\tUINT8 CurChp;\n\tVGMX_CHIP_DATA16* TempCD;\n\t\n\tif (! StartOffset || StartOffset >= VGMDataLen)\n\t{\n\t\tChpExtra->ChipCnt = 0x00;\n\t\tChpExtra->CCData = NULL;\n\t\treturn;\n\t}\n\t\n\tCurPos = StartOffset;\n\tChpExtra->ChipCnt = VGMData[CurPos];\n\tif (ChpExtra->ChipCnt)\n\t\tChpExtra->CCData = (VGMX_CHIP_DATA16*)malloc(sizeof(VGMX_CHIP_DATA16) *\n\t\t\t\t\t\t\t\t\t\t\t\t\tChpExtra->ChipCnt);\n\telse\n\t\tChpExtra->CCData = NULL;\n\tCurPos ++;\n\t\n\tfor (CurChp = 0x00; CurChp < ChpExtra->ChipCnt; CurChp ++)\n\t{\n\t\tTempCD = &ChpExtra->CCData[CurChp];\n\t\tTempCD->Type = VGMData[CurPos + 0x00];\n\t\tTempCD->Flags = VGMData[CurPos + 0x01];\n\t\tTempCD->Data = ReadLE16(&VGMData[CurPos + 0x02]);\n\t\tCurPos += 0x04;\n\t}\n\t\n\treturn;\n}\n\nvoid CloseVGMFile(void)\n{\n\tif (FileMode == 0xFF)\n\t\treturn;\n\t\n\tVGMHead.fccVGM = 0x00;\n\tfree(VGMH_Extra.Clocks.CCData);\t\tVGMH_Extra.Clocks.CCData = NULL;\n\tfree(VGMH_Extra.Volumes.CCData);\tVGMH_Extra.Volumes.CCData = NULL;\n\tfree(VGMData);\tVGMData = NULL;\n\t\n\tif (FileMode == 0x00)\n\tFreeGD3Tag(&VGMTag);\n\t\n\tFileMode = 0xFF;\n\t\n\treturn;\n}\n\nvoid FreeGD3Tag(GD3_TAG* TagData)\n{\n\tif (TagData == NULL)\n\t\treturn;\n\t\n\tTagData->fccGD3 = 0x00;\n\tfree(TagData->strTrackNameE);\tTagData->strTrackNameE = NULL;\n\tfree(TagData->strTrackNameJ);\tTagData->strTrackNameJ = NULL;\n\tfree(TagData->strGameNameE);\tTagData->strGameNameE = NULL;\n\tfree(TagData->strGameNameJ);\tTagData->strGameNameJ = NULL;\n\tfree(TagData->strSystemNameE);\tTagData->strSystemNameE = NULL;\n\tfree(TagData->strSystemNameJ);\tTagData->strSystemNameJ = NULL;\n\tfree(TagData->strAuthorNameE);\tTagData->strAuthorNameE = NULL;\n\tfree(TagData->strAuthorNameJ);\tTagData->strAuthorNameJ = NULL;\n\tfree(TagData->strReleaseDate);\tTagData->strReleaseDate = NULL;\n\tfree(TagData->strCreator);\t\tTagData->strCreator = NULL;\n\tfree(TagData->strNotes);\t\tTagData->strNotes = NULL;\n\t\n\treturn;\n}\n\nstatic wchar_t* MakeEmptyWStr(void)\n{\n\twchar_t* Str;\n\t\n\tStr = (wchar_t*)malloc(0x01 * sizeof(wchar_t));\n\tStr[0x00] = L'\\0';\n\t\n\treturn Str;\n}\n\nstatic wchar_t* ReadWStrFromFile(gzFile hFile, UINT32* FilePos, UINT32 EOFPos)\n{\n\t// Note: Works with Windows (16-bit wchar_t) as well as Linux (32-bit wchar_t)\n\tUINT32 CurPos;\n\twchar_t* TextStr;\n\twchar_t* TempStr;\n\tUINT32 StrLen;\n\tUINT16 UnicodeChr;\n\t\n\tCurPos = *FilePos;\n\tif (CurPos >= EOFPos)\n\t\treturn NULL;\n\tTextStr = (wchar_t*)malloc((EOFPos - CurPos) / 0x02 * sizeof(wchar_t));\n\tif (TextStr == NULL)\n\t\treturn NULL;\n\t\n\tif ((UINT32)gztell(hFile) != CurPos)\n\t\tgzseek(hFile, CurPos, SEEK_SET);\n\tTempStr = TextStr - 1;\n\tStrLen = 0x00;\n\tdo\n\t{\n\t\tTempStr ++;\n\t\tgzgetLE16(hFile, &UnicodeChr);\n\t\t*TempStr = (wchar_t)UnicodeChr;\n\t\tCurPos += 0x02;\n\t\tStrLen ++;\n\t\tif (CurPos >= EOFPos)\n\t\t{\n\t\t\t*TempStr = L'\\0';\n\t\t\tbreak;\n\t\t}\n\t} while(*TempStr != L'\\0');\n\t\n\tTextStr = (wchar_t*)realloc(TextStr, StrLen * sizeof(wchar_t));\n\t*FilePos = CurPos;\n\t\n\treturn TextStr;\n}\n\nUINT32 GetVGMFileInfo(const char* FileName, VGM_HEADER* RetVGMHead, GD3_TAG* RetGD3Tag)\n{\n\tgzFile hFile;\n\tUINT32 FileSize;\n\tUINT32 RetVal;\n\t\n\tFileSize = GetGZFileLength(FileName);\n\t\n\thFile = gzopen(FileName, \"rb\");\n\tif (hFile == NULL)\n\t\treturn 0x00;\n\t\n\tRetVal = GetVGMFileInfo_Internal(hFile, FileSize, RetVGMHead, RetGD3Tag);\n\t\n\tgzclose(hFile);\n\treturn RetVal;\n}\n\n#ifndef NO_WCHAR_FILENAMES\nUINT32 GetVGMFileInfoW(const wchar_t* FileName, VGM_HEADER* RetVGMHead, GD3_TAG* RetGD3Tag)\n{\n\tgzFile hFile;\n\tUINT32 FileSize;\n\tUINT32 RetVal;\n#if ZLIB_VERNUM < 0x1270\n\tint fDesc;\n\t\n\tFileSize = GetGZFileLengthW(FileName);\n\t\n\tfDesc = _wopen(FileName, _O_RDONLY | _O_BINARY);\n\thFile = gzdopen(fDesc, \"rb\");\n\tif (hFile == NULL)\n\t{\n\t\t_close(fDesc);\n\t\treturn 0x00;\n\t}\n#else\n\tFileSize = GetGZFileLengthW(FileName);\n\t\n\thFile = gzopen_w(FileName, \"rb\");\n\tif (hFile == NULL)\n\t\treturn 0x00;\n#endif\n\t\n\tRetVal = GetVGMFileInfo_Internal(hFile, FileSize, RetVGMHead, RetGD3Tag);\n\t\n\tgzclose(hFile);\n\treturn RetVal;\n}\n#endif\n\nstatic UINT32 GetVGMFileInfo_Internal(gzFile hFile, UINT32 FileSize,\n\t\t\t\t\t\t\t\t\t  VGM_HEADER* RetVGMHead, GD3_TAG* RetGD3Tag)\n{\n\t// this is a copy-and-paste from OpenVGM, just a little stripped\n\tUINT32 fccHeader;\n\tUINT32 TempLng;\n\tVGM_HEADER TempHead;\n\t\n\t//gzseek(hFile, 0x00, SEEK_SET);\n\tgzrewind(hFile);\n\tgzgetLE32(hFile, &fccHeader);\n\tif (fccHeader != FCC_VGM)\n\t\treturn 0x00;\n\t\n\tif (RetVGMHead == NULL && RetGD3Tag == NULL)\n\t\treturn FileSize;\n\t\n\t//gzseek(hFile, 0x00, SEEK_SET);\n\tgzrewind(hFile);\n\tReadVGMHeader(hFile, &TempHead);\n\t\n\tif (! TempHead.lngEOFOffset || TempHead.lngEOFOffset > FileSize)\n\t\tTempHead.lngEOFOffset = FileSize;\n\tif (TempHead.lngDataOffset < 0x00000040)\n\t\tTempHead.lngDataOffset = 0x00000040;\n\t\n\t/*if (TempHead.lngGD3Offset)\n\t{\n\t\tgzseek(hFile, TempHead.lngGD3Offset, SEEK_SET);\n\t\tgzgetLE32(hFile, &fccHeader);\n\t\tif (fccHeader != FCC_GD3)\n\t\t\tTempHead.lngGD3Offset = 0x00000000;\n\t\t\t//return 0x00;\n\t}*/\n\t\n\tif (RetVGMHead != NULL)\n\t\t*RetVGMHead = TempHead;\n\t\n\t// Read GD3 Tag\n\tif (RetGD3Tag != NULL)\n\t\tTempLng = ReadGD3Tag(hFile, TempHead.lngGD3Offset, RetGD3Tag);\n\t\n\treturn FileSize;\n}\n\nINLINE UINT32 MulDivRound(UINT64 Number, UINT64 Numerator, UINT64 Denominator)\n{\n\treturn (UINT32)((Number * Numerator + Denominator / 2) / Denominator);\n}\n\nUINT32 CalcSampleMSec(UINT64 Value, UINT8 Mode)\n{\n\t// Mode:\n\t//\tBit 0 (01):\tCalculation Mode\n\t//\t\t\t\t0 - Sample2MSec\n\t//\t\t\t\t1 - MSec2Sample\n\t//\tBit 1 (02):\tCalculation Samlpe Rate\n\t//\t\t\t\t0 - current playback rate\n\t//\t\t\t\t1 - 44.1 KHz (VGM native)\n\tUINT32 SmplRate;\n\tUINT32 PbMul;\n\tUINT32 PbDiv;\n\tUINT32 RetVal;\n\t\n\tif (! (Mode & 0x02))\n\t{\n\t\tSmplRate = SampleRate;\n\t\tPbMul = 1;\n\t\tPbDiv = 1;\n\t}\n\telse\n\t{\n\t\tSmplRate = VGMSampleRate;\n\t\tPbMul = VGMPbRateMul;\n\t\tPbDiv = VGMPbRateDiv;\n\t}\n\t\n\tswitch(Mode & 0x01)\n\t{\n\tcase 0x00:\n\t\tRetVal = MulDivRound(Value, (UINT64)1000 * PbMul, (UINT64)SmplRate * PbDiv);\n\t\tbreak;\n\tcase 0x01:\n\t\tRetVal = MulDivRound(Value, (UINT64)SmplRate * PbDiv, (UINT64)1000 * PbMul);\n\t\tbreak;\n\t}\n\t\n\treturn RetVal;\n}\n\nUINT32 CalcSampleMSecExt(UINT64 Value, UINT8 Mode, VGM_HEADER* FileHead)\n{\n\t// Note: This function was NOT tested with non-VGM formats!\n\t\n\t// Mode: see function above\n\tUINT32 SmplRate;\n\tUINT32 PbMul;\n\tUINT32 PbDiv;\n\tUINT32 RetVal;\n\t\n\tif (! (Mode & 0x02))\n\t{\n\t\tSmplRate = SampleRate;\n\t\tPbMul = 1;\n\t\tPbDiv = 1;\n\t}\n\telse\n\t{\n\t\t// TODO: make it work for non-VGM formats\n\t\t// (i.e. get VGMSampleRate information from FileHead)\n\t\t//\n\t\t// But currently GetVGMFileInfo doesn't support them, it doesn't matter either way\n\t\tSmplRate = 44100;\n\t\tif (! VGMPbRate || ! FileHead->lngRate)\n\t\t{\n\t\t\tPbMul = 1;\n\t\t\tPbDiv = 1;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tPbMul = FileHead->lngRate;\n\t\t\tPbDiv = VGMPbRate;\n\t\t}\n\t}\n\t\n\tswitch(Mode & 0x01)\n\t{\n\tcase 0x00:\n\t\tRetVal = MulDivRound(Value, 1000 * PbMul, SmplRate * PbDiv);\n\t\tbreak;\n\tcase 0x01:\n\t\tRetVal = MulDivRound(Value, SmplRate * PbDiv, 1000 * PbMul);\n\t\tbreak;\n\t}\n\t\n\treturn RetVal;\n}\n\n#if 0\nstatic UINT32 EncryptChipName(void* DstBuf, const void* SrcBuf, UINT32 Length)\n{\n\t// using nineko's awesome encryption algorithm\n\t// http://forums.sonicretro.org/index.php?showtopic=25300\n\t// based on C code by sasuke\n\tconst UINT8* SrcPos;\n\tUINT8* DstPos;\n\tUINT32 CurPos;\n\tUINT8 CryptShift;\t// Src Bit/Dst Byte\n\tUINT8 PlainShift;\t// Src Byte/Dst Bit\n\t\n\tif (Length & 0x07)\n\t\treturn 0x00;\t// Length MUST be a multiple of 8\n\t\n\tSrcPos = (const UINT8*)SrcBuf;\n\tDstPos = (UINT8*)DstBuf;\n\tfor (CurPos = 0; CurPos < Length; CurPos += 8, SrcPos += 8, DstPos += 8)\n\t{\n\t\tfor (CryptShift = 0; CryptShift < 8; CryptShift ++)\n\t\t{\n\t\t\tDstPos[CryptShift] = 0x00;\n\t\t\tfor (PlainShift = 0; PlainShift < 8; PlainShift ++)\n\t\t\t{\n\t\t\t\tif (SrcPos[PlainShift] & (1 << CryptShift))\n\t\t\t\t\tDstPos[CryptShift] |= (1 << PlainShift);\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn Length;\n}\n#endif\n\nconst char* GetChipName(UINT8 ChipID)\n{\n\tconst char* CHIP_STRS[CHIP_COUNT] = \n\t{\t\"SN76496\", \"YM2413\", \"YM2612\", \"YM2151\", \"SegaPCM\", \"RF5C68\", \"YM2203\", \"YM2608\",\n\t\t\"YM2610\", \"YM3812\", \"YM3526\", \"Y8950\", \"YMF262\", \"YMF278B\", \"YMF271\", \"YMZ280B\",\n\t\t\"RF5C164\", \"PWM\", \"AY8910\", \"GameBoy\", \"NES APU\", \"YMW258\", \"uPD7759\", \"OKIM6258\",\n\t\t\"OKIM6295\", \"K051649\", \"K054539\", \"HuC6280\", \"C140\", \"K053260\", \"Pokey\", \"QSound\",\n\t\t\"SCSP\", \"WSwan\", \"VSU\", \"SAA1099\", \"ES5503\", \"ES5506\", \"X1-010\", \"C352\",\n\t\t\"GA20\"};\n\t\n\t/*if (ChipID == 0x21)\n\t{\n\t\tstatic char TempStr[0x08];\n\t\tUINT32 TempData[2];\n\t\t\n\t\t//EncryptChipName(TempData, \"WSwan\", 0x08);\n\t\tTempData[0] = 0x1015170F;\n\t\tTempData[1] = 0x001F1C07;\n\t\tEncryptChipName(TempStr, TempData, 0x08);\n\t\treturn TempStr;\t// \"WSwan\"\n\t}*/\n\t\n\tif (ChipID < CHIP_COUNT)\n\t\treturn CHIP_STRS[ChipID];\n\telse\n\t\treturn NULL;\n}\n\nconst char* GetAccurateChipName(UINT8 ChipID, UINT8 SubType)\n{\n\tconst char* RetStr;\n\t\n\tif ((ChipID & 0x7F) >= CHIP_COUNT)\n\t\treturn NULL;\n\t\n\tRetStr = NULL;\n\tswitch(ChipID & 0x7F)\n\t{\n\tcase 0x00:\n\t\tif (! (ChipID & 0x80))\n\t\t{\n\t\t\tswitch(SubType)\n\t\t\t{\n\t\t\tcase 0x01:\n\t\t\t\tRetStr = \"SN76489\";\n\t\t\t\tbreak;\n\t\t\tcase 0x02:\n\t\t\t\tRetStr = \"SN76489A\";\n\t\t\t\tbreak;\n\t\t\tcase 0x03:\n\t\t\t\tRetStr = \"SN76494\";\n\t\t\t\tbreak;\n\t\t\tcase 0x04:\n\t\t\t\tRetStr = \"SN76496\";\n\t\t\t\tbreak;\n\t\t\tcase 0x05:\n\t\t\t\tRetStr = \"SN94624\";\n\t\t\t\tbreak;\n\t\t\tcase 0x06:\n\t\t\t\tRetStr = \"SEGA PSG\";\n\t\t\t\tbreak;\n\t\t\tcase 0x07:\n\t\t\t\tRetStr = \"NCR8496\";\n\t\t\t\tbreak;\n\t\t\tcase 0x08:\n\t\t\t\tRetStr = \"PSSJ-3\";\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tRetStr = \"SN76496\";\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tRetStr = \"T6W28\";\n\t\t}\n\t\tbreak;\n\tcase 0x01:\n\t\tif (ChipID & 0x80)\n\t\t\tRetStr = \"VRC7\";\n\t\tbreak;\n\tcase 0x02:\n\t\tif (! (ChipID & 0x80))\n\t\t\tRetStr = \"YM2612\";\n\t\telse\n\t\t\tRetStr = \"YM3438\";\n\t\tbreak;\n\tcase 0x04:\n\t\tRetStr = \"Sega PCM\";\n\t\tbreak;\n\tcase 0x08:\n\t\tif (! (ChipID & 0x80))\n\t\t\tRetStr = \"YM2610\";\n\t\telse\n\t\t\tRetStr = \"YM2610B\";\n\t\tbreak;\n\tcase 0x12:\t// AY8910\n\t\tswitch(SubType)\n\t\t{\n\t\tcase 0x00:\n\t\t\tRetStr = \"AY-3-8910\";\n\t\t\tbreak;\n\t\tcase 0x01:\n\t\t\tRetStr = \"AY-3-8912\";\n\t\t\tbreak;\n\t\tcase 0x02:\n\t\t\tRetStr = \"AY-3-8913\";\n\t\t\tbreak;\n\t\tcase 0x03:\n\t\t\tRetStr = \"AY8930\";\n\t\t\tbreak;\n\t\tcase 0x04:\n\t\t\tRetStr = \"AY-3-8914\";\n\t\t\tbreak;\n\t\tcase 0x10:\n\t\t\tRetStr = \"YM2149\";\n\t\t\tbreak;\n\t\tcase 0x11:\n\t\t\tRetStr = \"YM3439\";\n\t\t\tbreak;\n\t\tcase 0x12:\n\t\t\tRetStr = \"YMZ284\";\n\t\t\tbreak;\n\t\tcase 0x13:\n\t\t\tRetStr = \"YMZ294\";\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase 0x13:\n\t\tRetStr = \"GB DMG\";\n\t\tbreak;\n\tcase 0x14:\n\t\tif (! (ChipID & 0x80))\n\t\t\tRetStr = \"NES APU\";\n\t\telse\n\t\t\tRetStr = \"NES APU + FDS\";\n\t\tbreak;\n\tcase 0x19:\n\t\tif (! (ChipID & 0x80))\n\t\t\tRetStr = \"K051649\";\n\t\telse\n\t\t\tRetStr = \"K052539\";\n\t\tbreak;\n\tcase 0x1C:\n\t\tswitch(SubType)\n\t\t{\n\t\tcase 0x00:\n\t\tcase 0x01:\n\t\t\tRetStr = \"C140\";\n\t\t\tbreak;\n\t\tcase 0x02:\n\t\t\tRetStr = \"C219\";\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase 0x21:\n\t\tRetStr = \"WonderSwan\";\n\t\tbreak;\n\tcase 0x22:\n\t\tRetStr = \"VSU-VUE\";\n\t\tbreak;\n\tcase 0x25:\n\t\tif (! (ChipID & 0x80))\n\t\t\tRetStr = \"ES5505\";\n\t\telse\n\t\t\tRetStr = \"ES5506\";\n\t\tbreak;\n\tcase 0x28:\n\t\tRetStr = \"Irem GA20\";\n\t\tbreak;\n\t}\n\t// catch all default-cases\n\tif (RetStr == NULL)\n\t\tRetStr = GetChipName(ChipID & 0x7F);\n\t\n\treturn RetStr;\n}\n\nUINT32 GetChipClock(VGM_HEADER* FileHead, UINT8 ChipID, UINT8* RetSubType)\n{\n\tUINT32 Clock;\n\tUINT8 SubType;\n\tUINT8 CurChp;\n\tbool AllowBit31;\n\t\n\tSubType = 0x00;\n\tAllowBit31 = 0x00;\n\tswitch(ChipID & 0x7F)\n\t{\n\tcase 0x00:\n\t\tClock = FileHead->lngHzPSG;\n\t\tAllowBit31 = 0x01;\t// T6W28 Mode\n\t\tif (RetSubType != NULL && ! (Clock & 0x80000000))\t// The T6W28 is handled differently.\n\t\t{\n\t\t\tswitch(FileHead->bytPSG_SRWidth)\n\t\t\t{\n\t\t\tcase 0x0F:\t//  0x4000\n\t\t\t\tif (FileHead->bytPSG_Flags & 0x08)\t// Clock Divider == 1?\n\t\t\t\t\tSubType = 0x05;\t// SN94624\n\t\t\t\telse\n\t\t\t\t\tSubType = 0x01;\t// SN76489\n\t\t\t\tbreak;\n\t\t\tcase 0x10:\t//  0x8000\n\t\t\t\tif (FileHead->shtPSG_Feedback == 0x0009)\n\t\t\t\t\tSubType = 0x06;\t// SEGA PSG\n\t\t\t\telse if (FileHead->shtPSG_Feedback == 0x0022)\n\t\t\t\t{\n\t\t\t\t\tif (FileHead->bytPSG_Flags & 0x10)\t// if Tandy noise mode enabled\n\t\t\t\t\t\tSubType = (FileHead->bytPSG_Flags & 0x02) ? 0x07 : 0x08;\t// NCR8496 / PSSJ-3\n\t\t\t\t\telse\n\t\t\t\t\t\tSubType = 0x07;\t// NCR8496\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0x11:\t// 0x10000\n\t\t\t\tif (FileHead->bytPSG_Flags & 0x08)\t// Clock Divider == 1?\n\t\t\t\t\tSubType = 0x03;\t// SN76494\n\t\t\t\telse\n\t\t\t\t\tSubType = 0x02;\t// SN76489A/SN76496\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/*\n\t\t\t\t\t\t\t\t FbMask  Noise Taps  Negate Stereo Dv Freq0\t\tFb\tSR\tFlags\n\t\t\t\t01 SN76489\t\t 0x4000, 0x01, 0x02, TRUE,  FALSE, 8, TRUE\t\t03\t0F\t07 (02|04|00|01) [unverified]\n\t\t\t\t02 SN76489A\t\t0x10000, 0x04, 0x08, FALSE, FALSE, 8, TRUE\t\t0C\t11\t05 (00|04|00|01)\n\t\t\t\t03 SN76494\t\t0x10000, 0x04, 0x08, FALSE, FALSE, 1, TRUE\t\t0C\t11\t0D (00|04|08|01)\n\t\t\t\t04 SN76496\t\t0x10000, 0x04, 0x08, FALSE, FALSE, 8, TRUE\t\t0C\t11\t05 (00|04|00|01) [same as SN76489A]\n\t\t\t\t05 SN94624\t\t 0x4000, 0x01, 0x02, TRUE,  FALSE, 1, TRUE\t\t03\t0F\t0F (02|04|08|01) [unverified, SN76489A without /8]\n\t\t\t\t06 GameGear PSG\t 0x8000, 0x01, 0x08, TRUE,  TRUE,  8, FALSE\t\t09\t10\t02 (02|00|00|00)\n\t\t\t\t06 SEGA VDP PSG\t 0x8000, 0x01, 0x08, TRUE,  FALSE, 8, FALSE\t\t09\t10\t06 (02|04|00|00)\n\t\t\t\t07 NCR8496\t\t 0x8000, 0x02, 0x20, TRUE,  FALSE, 8, TRUE\t\t22\t10\t07 (02|04|00|01)\n\t\t\t\t08 PSSJ-3\t\t 0x8000, 0x02, 0x20, FALSE, FALSE, 8, TRUE\t\t22\t10\t05 (00|04|00|01)\n\t\t\t\t01 U8106\t\t 0x4000, 0x01, 0x02, TRUE,  FALSE, 8, TRUE\t\t03\t0F\t07 (02|04|00|01) [unverified, same as SN76489]\n\t\t\t\t02 Y2404\t\t0x10000, 0x04, 0x08, FALSE, FALSE; 8, TRUE\t\t0C\t11\t05 (00|04|00|01) [unverified, same as SN76489A]\n\t\t\t\t-- T6W28\t\t0x10000, 0x04, 0x08, ????,  FALSE, 8, ????\t\t0C\t11\t?? (??|??|00|01) [It IS stereo, but not in GameGear way].\n\t\t\t*/\n\t\t}\n\t\tbreak;\n\tcase 0x01:\n\t\tClock = FileHead->lngHzYM2413;\n\t\tAllowBit31 = 0x01;\t// VRC7 Mode\n\t\tbreak;\n\tcase 0x02:\n\t\tClock = FileHead->lngHzYM2612;\n\t\tAllowBit31 = 0x01;\t// YM3438 Mode\n\t\tbreak;\n\tcase 0x03:\n\t\tClock = FileHead->lngHzYM2151;\n\t\tbreak;\n\tcase 0x04:\n\t\tClock = FileHead->lngHzSPCM;\n\t\tbreak;\n\tcase 0x05:\n\t\tif (ChipID & 0x80)\n\t\t\treturn 0;\n\t\tClock = FileHead->lngHzRF5C68;\n\t\tbreak;\n\tcase 0x06:\n\t\tClock = FileHead->lngHzYM2203;\n\t\tbreak;\n\tcase 0x07:\n\t\tClock = FileHead->lngHzYM2608;\n\t\tbreak;\n\tcase 0x08:\n\t\tClock = FileHead->lngHzYM2610;\n\t\tAllowBit31 = 0x01;\t// YM2610B Mode\n\t\tbreak;\n\tcase 0x09:\n\t\tClock = FileHead->lngHzYM3812;\n\t\tAllowBit31 = 0x01;\t// Dual OPL2, panned to the L/R speakers\n\t\tbreak;\n\tcase 0x0A:\n\t\tClock = FileHead->lngHzYM3526;\n\t\tbreak;\n\tcase 0x0B:\n\t\tClock = FileHead->lngHzY8950;\n\t\tbreak;\n\tcase 0x0C:\n\t\tClock = FileHead->lngHzYMF262;\n\t\tbreak;\n\tcase 0x0D:\n\t\tClock = FileHead->lngHzYMF278B;\n\t\tbreak;\n\tcase 0x0E:\n\t\tClock = FileHead->lngHzYMF271;\n\t\tbreak;\n\tcase 0x0F:\n\t\tClock = FileHead->lngHzYMZ280B;\n\t\tbreak;\n\tcase 0x10:\n\t\tif (ChipID & 0x80)\n\t\t\treturn 0;\n\t\tClock = FileHead->lngHzRF5C164;\n\t\tAllowBit31 = 0x01;\t// hack for Cosmic Fantasy Stories\n\t\tbreak;\n\tcase 0x11:\n\t\tif (ChipID & 0x80)\n\t\t\treturn 0;\n\t\tClock = FileHead->lngHzPWM;\n\t\tbreak;\n\tcase 0x12:\n\t\tClock = FileHead->lngHzAY8910;\n\t\tSubType = FileHead->bytAYType;\n\t\tbreak;\n\tcase 0x13:\n\t\tClock = FileHead->lngHzGBDMG;\n\t\tbreak;\n\tcase 0x14:\n\t\tClock = FileHead->lngHzNESAPU;\n\t\tAllowBit31 = 0x01;\t// FDS Enable\n\t\tbreak;\n\tcase 0x15:\n\t\tClock = FileHead->lngHzMultiPCM;\n\t\tbreak;\n\tcase 0x16:\n\t\tClock = FileHead->lngHzUPD7759;\n\t\tAllowBit31 = 0x01;\t// Master/Slave Bit\n\t\tbreak;\n\tcase 0x17:\n\t\tClock = FileHead->lngHzOKIM6258;\n\t\tbreak;\n\tcase 0x18:\n\t\tClock = FileHead->lngHzOKIM6295;\n\t\tAllowBit31 = 0x01;\t// Pin 7 State\n\t\tbreak;\n\tcase 0x19:\n\t\tClock = FileHead->lngHzK051649;\n\t\tAllowBit31 = 0x01;\t// SCC/SCC+ Bit\n\t\tbreak;\n\tcase 0x1A:\n\t\tClock = FileHead->lngHzK054539;\n\t\tbreak;\n\tcase 0x1B:\n\t\tClock = FileHead->lngHzHuC6280;\n\t\tbreak;\n\tcase 0x1C:\n\t\tClock = FileHead->lngHzC140;\n\t\tSubType = FileHead->bytC140Type;\n\t\tbreak;\n\tcase 0x1D:\n\t\tClock = FileHead->lngHzK053260;\n\t\tbreak;\n\tcase 0x1E:\n\t\tClock = FileHead->lngHzPokey;\n\t\tbreak;\n\tcase 0x1F:\n\t\tif (ChipID & 0x80)\n\t\t\treturn 0;\n\t\tClock = FileHead->lngHzQSound;\n\t\tbreak;\n\tcase 0x20:\n\t\tClock = FileHead->lngHzSCSP;\n\t\tbreak;\n\tcase 0x21:\n\t\tClock = FileHead->lngHzWSwan;\n\t\tbreak;\n\tcase 0x22:\n\t\tClock = FileHead->lngHzVSU;\n\t\tbreak;\n\tcase 0x23:\n\t\tClock = FileHead->lngHzSAA1099;\n\t\tbreak;\n\tcase 0x24:\n\t\tClock = FileHead->lngHzES5503;\n\t\tbreak;\n\tcase 0x25:\n\t\tClock = FileHead->lngHzES5506;\n\t\tAllowBit31 = 0x01;\t// ES5505/5506 switch\n\t\tbreak;\n\tcase 0x26:\n\t\tClock = FileHead->lngHzX1_010;\n\t\tbreak;\n\tcase 0x27:\n\t\tClock = FileHead->lngHzC352;\n\t\tAllowBit31 = 0x01;\t// disable rear channels\n\t\tbreak;\n\tcase 0x28:\n\t\tClock = FileHead->lngHzGA20;\n\t\tbreak;\n\tdefault:\n\t\treturn 0;\n\t}\n\tif (ChipID & 0x80)\n\t{\n\t\tVGMX_CHP_EXTRA32* TempCX;\n\t\t\n\t\tif (! (Clock & 0x40000000))\n\t\t\treturn 0;\n\t\t\n\t\tChipID &= 0x7F;\n\t\tTempCX = &VGMH_Extra.Clocks;\n\t\tfor (CurChp = 0x00; CurChp < TempCX->ChipCnt; CurChp ++)\n\t\t{\n\t\t\tif (TempCX->CCData[CurChp].Type == ChipID)\n\t\t\t{\n\t\t\t\tif (TempCX->CCData[CurChp].Data)\n\t\t\t\t\tClock = TempCX->CCData[CurChp].Data;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif (RetSubType != NULL)\n\t\t*RetSubType = SubType;\n\tif (AllowBit31)\n\t\treturn Clock & 0xBFFFFFFF;\n\telse\n\t\treturn Clock & 0x3FFFFFFF;\n}\n\nstatic UINT16 GetChipVolume(VGM_HEADER* FileHead, UINT8 ChipID, UINT8 ChipNum, UINT8 ChipCnt)\n{\n\t// ChipID: ID of Chip\n\t//\t\tBit 7 - Is Paired Chip\n\t// ChipNum: chip number (0 - first chip, 1 - second chip)\n\t// ChipCnt: chip volume divider (number of used chips)\n\tconst UINT16 CHIP_VOLS[CHIP_COUNT] =\n\t{\t0x80, 0x200/*0x155*/, 0x100, 0x100, 0x180, 0xB0, 0x100, 0x80,\t// 00-07\n\t\t0x80, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x98,\t\t\t// 08-0F\n\t\t0x80, 0xE0/*0xCD*/, 0x100, 0xC0, 0x100, 0x40, 0x11E, 0x1C0,\t\t// 10-17\n\t\t0x100/*110*/, 0xA0, 0x100, 0x100, 0x100, 0xB3, 0x100, 0x100,\t// 18-1F\n\t\t0x20, 0x100, 0x100, 0x100, 0x40, 0x20, 0x100, 0x40,\t\t\t// 20-27\n\t\t0x280};\n\tUINT16 Volume;\n\tUINT8 CurChp;\n\tVGMX_CHP_EXTRA16* TempCX;\n\tVGMX_CHIP_DATA16* TempCD;\n\t\n\tVolume = CHIP_VOLS[ChipID & 0x7F];\n\tswitch(ChipID)\n\t{\n\tcase 0x00:\t// SN76496\n\t\t// if T6W28, set Volume Divider to 01\n\t\tif (GetChipClock(&VGMHead, (ChipID << 7) | ChipID, NULL) & 0x80000000)\n\t\t{\n\t\t\t// The T6W28 consists of 2 \"half\" chips.\n\t\t\tChipNum = 0x01;\n\t\t\tChipCnt = 0x01;\n\t\t}\n\t\tbreak;\n\tcase 0x18:\t// OKIM6295\n\t\t// CP System 1 patch\n\t\tif (VGMTag.strSystemNameE != NULL && ! wcsncmp(VGMTag.strSystemNameE, L\"CP\", 0x02))\n\t\t\tVolume = 110;\n\t\tbreak;\n\tcase 0x86:\t// YM2203's AY\n\t\tVolume /= 2;\n\t\tbreak;\n\tcase 0x87:\t// YM2608's AY\n\t\t// The YM2608 outputs twice as loud as the YM2203 here.\n\t\t//Volume *= 1;\n\t\tbreak;\n\tcase 0x88:\t// YM2610's AY\n\t\t//Volume *= 1;\n\t\tbreak;\n\t}\n\tif (ChipCnt > 1)\n\t\tVolume /= ChipCnt;\n\t\n\tTempCX = &VGMH_Extra.Volumes;\n\tTempCD = TempCX->CCData;\n\tfor (CurChp = 0x00; CurChp < TempCX->ChipCnt; CurChp ++, TempCD ++)\n\t{\n\t\tif (TempCD->Type == ChipID && (TempCD->Flags & 0x01) == ChipNum)\n\t\t{\n\t\t\t// Bit 15 - absolute/relative volume\n\t\t\t//\t0 - absolute\n\t\t\t//\t1 - relative (0x0100 = 1.0, 0x80 = 0.5, etc.)\n\t\t\tif (TempCD->Data & 0x8000)\n\t\t\t\tVolume = (Volume * (TempCD->Data & 0x7FFF) + 0x80) >> 8;\n\t\t\telse\n\t\t\t{\n\t\t\t\tVolume = TempCD->Data;\n\t\t\t\tif ((ChipID & 0x80) && DoubleSSGVol)\n\t\t\t\t\tVolume *= 2;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\treturn Volume;\n}\n\n\nstatic void RestartPlaying(void)\n{\n\tbool OldPThread;\n\t\n\tOldPThread = PauseThread;\n\tif (ThreadPauseEnable)\n\t{\n\t\tThreadNoWait = false;\n\t\tThreadPauseConfrm = false;\n\t\tPauseThread = true;\n\t\twhile(! ThreadPauseConfrm)\n\t\t\tSleep(1);\t// Wait until the Thread is finished\n\t}\n\tInterpreting = true;\t// Avoid any Thread-Call\n\t\n\tVGMPos = VGMHead.lngDataOffset;\n\tVGMSmplPos = 0;\n\tVGMSmplPlayed = 0;\n\tVGMEnd = false;\n\tEndPlay = false;\n\tVGMCurLoop = 0x00;\n\tPauseSmpls = (PauseTime * SampleRate + 500) / 1000;\n\t\n\tChips_GeneralActions(0x01);\t// Reset Chips\n\t// also does Muting Mask (0x10) and Panning (0x20)\n\t\n\tif (UseFM)\n\t{\n\t\topen_real_fm();\t// reset OPL chip and reload settings\n\t\tStartSkipping();\n\t\tAutoStopSkip = true;\n\t}\n\t\n\tLast95Drum = 0xFFFF;\n\tLast95Freq = 0;\n\tInterpreting = false;\n\tForceVGMExec = true;\n\tIsVGMInit = true;\n\tInterpretFile(0);\n\tIsVGMInit = false;\n\tForceVGMExec = false;\n#ifndef CONSOLE_MODE\n\tFadePlay = false;\n\tMasterVol = 1.0f;\n\tFadeStart = 0;\n\tFinalVol = VolumeLevelM;\n\tPlayingTime = 0;\n#endif\n\tPauseThread = OldPThread;\n\t\n\treturn;\n}\n\nstatic void Chips_GeneralActions(UINT8 Mode)\n{\n\tUINT32 AbsVol;\n\t//UINT16 ChipVol;\n\tCAUD_ATTR* CAA;\n\tCHIP_OPTS* COpt;\n\tUINT8 ChipCnt;\n\tUINT8 CurChip;\n\tUINT8 CurCSet;\t// Chip Set\n\tUINT32 MaskVal;\n\tUINT32 ChipClk;\n\t\n\tswitch(Mode)\n\t{\n\tcase 0x00:\t// Start Chips\n\t\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t\t{\n\t\t\tCAA = (CAUD_ATTR*)&ChipAudio[CurCSet];\n\t\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, CAA ++)\n\t\t\t{\n\t\t\t\tCAA->SmpRate = 0x00;\n\t\t\t\tCAA->Volume = 0x00;\n\t\t\t\tCAA->ChipType = 0xFF;\n\t\t\t\tCAA->ChipID = CurCSet;\n\t\t\t\tCAA->Resampler = 0x00;\n\t\t\t\tCAA->StreamUpdate = &null_update;\n\t\t\t\tCAA->Paired = NULL;\n\t\t\t}\n\t\t\tCAA = CA_Paired[CurCSet];\n\t\t\tfor (CurChip = 0x00; CurChip < 0x03; CurChip ++, CAA ++)\n\t\t\t{\n\t\t\t\tCAA->SmpRate = 0x00;\n\t\t\t\tCAA->Volume = 0x00;\n\t\t\t\tCAA->ChipType = 0xFF;\n\t\t\t\tCAA->ChipID = CurCSet;\n\t\t\t\tCAA->Resampler = 0x00;\n\t\t\t\tCAA->StreamUpdate = &null_update;\n\t\t\t\tCAA->Paired = NULL;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Initialize Sound Chips\n\t\tAbsVol = 0x00;\n\t\tif (VGMHead.lngHzPSG)\n\t\t{\n\t\t\t//ChipVol = UseFM ? 0x00 : 0x80;\n\t\t\tsn764xx_set_emu_core(ChipOpts[0x00].SN76496.EmuCore);\n\t\t\tChipOpts[0x01].SN76496.EmuCore = ChipOpts[0x00].SN76496.EmuCore;\n\t\t\t\n\t\t\tChipCnt = (VGMHead.lngHzPSG & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].SN76496;\n\t\t\t\tCAA->ChipType = 0x00;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tChipClk &= ~0x80000000;\n\t\t\t\tChipClk |= VGMHead.lngHzPSG & ((CurChip & 0x01) << 31);\n\t\t\t\tif (! UseFM)\n\t\t\t\t{\n\t\t\t\t\tCAA->SmpRate = device_start_sn764xx(CurChip, ChipClk,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tVGMHead.bytPSG_SRWidth,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tVGMHead.shtPSG_Feedback,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(VGMHead.bytPSG_Flags & 0x02) >> 1,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(VGMHead.bytPSG_Flags & 0x04) >> 2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(VGMHead.bytPSG_Flags & 0x08) >> 3,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(VGMHead.bytPSG_Flags & 0x01) >> 0);\n\t\t\t\t\tCAA->StreamUpdate = &sn764xx_stream_update;\n\t\t\t\t\t\n\t\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\t\tif (! CurChip || ! (ChipClk & 0x80000000))\n\t\t\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\topen_fm_option(CAA->ChipType, 0x00, ChipClk);\n\t\t\t\t\topen_fm_option(CAA->ChipType, 0x01, VGMHead.bytPSG_SRWidth);\n\t\t\t\t\topen_fm_option(CAA->ChipType, 0x02, VGMHead.shtPSG_Feedback);\n\t\t\t\t\topen_fm_option(CAA->ChipType, 0x04, (VGMHead.bytPSG_Flags & 0x02) >> 1);\n\t\t\t\t\topen_fm_option(CAA->ChipType, 0x05, (VGMHead.bytPSG_Flags & 0x04) >> 2);\n\t\t\t\t\topen_fm_option(CAA->ChipType, 0x06, (VGMHead.bytPSG_Flags & 0x08) >> 3);\n\t\t\t\t\topen_fm_option(CAA->ChipType, 0x07, (VGMHead.bytPSG_Flags & 0x01) >> 0);\n\t\t\t\t\tsetup_real_fm(CAA->ChipType, CurChip);\n\t\t\t\t\t\n\t\t\t\t\tCAA->SmpRate = 0x00000000;\n\t\t\t\t\tCAA->Volume = 0x0000;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (VGMHead.lngHzPSG & 0x80000000)\n\t\t\t\tChipCnt = 0x01;\n\t\t}\n\t\tif (VGMHead.lngHzYM2413)\n\t\t{\n\t\t\t//ChipVol = UseFM ? 0x00 : 0x200/*0x155*/;\n\t\t\tif (! UseFM)\n\t\t\t\tym2413_set_emu_core(ChipOpts[0x00].YM2413.EmuCore);\n\t\t\telse\n\t\t\t\tym2413opl_set_emu_core(ChipOpts[0x00].YM2413.EmuCore);\n\t\t\tChipOpts[0x01].YM2413.EmuCore = ChipOpts[0x00].YM2413.EmuCore;\n\t\t\t\n\t\t\tChipCnt = (VGMHead.lngHzYM2413 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].YM2413;\n\t\t\t\tCAA->ChipType = 0x01;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tif (! UseFM)\n\t\t\t\t{\n\t\t\t\t\tCAA->SmpRate = device_start_ym2413(CurChip, ChipClk);\n\t\t\t\t\tCAA->StreamUpdate = &ym2413_stream_update;\n\t\t\t\t\t\n\t\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\t\t// WHY has this chip such a low volume???\n\t\t\t\t\t//AbsVol += (CAA->Volume + 1) * 3 / 4;\n\t\t\t\t\tAbsVol += CAA->Volume / 2;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsetup_real_fm(CAA->ChipType, CurChip);\n\t\t\t\t\t\n\t\t\t\t\tCAA->SmpRate = 0x00000000;\n\t\t\t\t\tCAA->Volume = 0x0000;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzYM2612)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tym2612_set_emu_core(ChipOpts[0x00].YM2612.EmuCore);\n\t\t\tym2612_set_options((UINT8)ChipOpts[0x00].YM2612.SpecialFlags);\n\t\t\tChipOpts[0x01].YM2612.EmuCore = ChipOpts[0x00].YM2612.EmuCore;\n\t\t\tChipOpts[0x01].YM2612.SpecialFlags = ChipOpts[0x00].YM2612.SpecialFlags;\n\t\t\tChipCnt = (VGMHead.lngHzYM2612 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].YM2612;\n\t\t\t\tCAA->ChipType = 0x02;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_ym2612(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &ym2612_stream_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzYM2151)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tym2151_set_emu_core(ChipOpts[0x00].YM2151.EmuCore);\n\t\t\tChipCnt = (VGMHead.lngHzYM2151 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].YM2151;\n\t\t\t\tCAA->ChipType = 0x03;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_ym2151(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &ym2151_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzSPCM)\n\t\t{\n\t\t\t//ChipVol = 0x180;\n\t\t\tChipCnt = (VGMHead.lngHzSPCM & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].SegaPCM;\n\t\t\t\tCAA->ChipType = 0x04;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_segapcm(CurChip, ChipClk, VGMHead.lngSPCMIntf);\n\t\t\t\tCAA->StreamUpdate = &SEGAPCM_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzRF5C68)\n\t\t{\n\t\t\t//ChipVol = 0xB0;\t// that's right according to MAME, but it's almost too loud\n\t\t\tChipCnt = 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].RF5C68;\n\t\t\t\tCAA->ChipType = 0x05;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_rf5c68(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &rf5c68_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzYM2203)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tym2203_set_ay_emu_core(ChipOpts[0x00].YM2203.EmuCore);\n\t\t\tChipOpts[0x01].YM2203.EmuCore = ChipOpts[0x00].YM2203.EmuCore;\n\t\t\tChipOpts[0x01].YM2203.SpecialFlags = ChipOpts[0x00].YM2203.SpecialFlags;\n\t\t\t\n\t\t\tChipCnt = (VGMHead.lngHzYM2203 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].YM2203;\n\t\t\t\tCOpt = &ChipOpts[CurChip].YM2203;\n\t\t\t\tCAA->ChipType = 0x06;\n\t\t\t\tCAA->Paired = &CA_Paired[CurChip][0x00];\n\t\t\t\tCAA->Paired->ChipType = 0x80 | CAA->ChipType;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_ym2203(CurChip, ChipClk, COpt->SpecialFlags & 0x01,\n\t\t\t\t\t\t\t\t\t\t\t\t\tVGMHead.bytAYFlagYM2203,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(int*)&CAA->Paired->SmpRate);\n\t\t\t\tCAA->StreamUpdate = &ym2203_stream_update;\n\t\t\t\tCAA->Paired->StreamUpdate = &ym2203_stream_update_ay;\n\t\t\t\tym2203_set_srchg_cb(CurChip, &ChangeChipSampleRate, CAA, CAA->Paired);\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tCAA->Paired->Volume = GetChipVolume(&VGMHead, CAA->Paired->ChipType,\n\t\t\t\t\t\t\t\t\t\t\t\t\tCurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume + CAA->Paired->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzYM2608)\n\t\t{\n\t\t\t//ChipVol = 0x80;\n\t\t\tym2608_set_ay_emu_core(ChipOpts[0x00].YM2608.EmuCore);\n\t\t\tChipOpts[0x01].YM2608.EmuCore = ChipOpts[0x00].YM2608.EmuCore;\n\t\t\tChipOpts[0x01].YM2608.SpecialFlags = ChipOpts[0x00].YM2608.SpecialFlags;\n\t\t\t\n\t\t\tChipCnt = (VGMHead.lngHzYM2608 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].YM2608;\n\t\t\t\tCOpt = &ChipOpts[CurChip].YM2608;\n\t\t\t\tCAA->ChipType = 0x07;\n\t\t\t\tCAA->Paired = &CA_Paired[CurChip][0x01];\n\t\t\t\tCAA->Paired->ChipType = 0x80 | CAA->ChipType;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_ym2608(CurChip, ChipClk, COpt->SpecialFlags & 0x01,\n\t\t\t\t\t\t\t\t\t\t\t\t\tVGMHead.bytAYFlagYM2608,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(int*)&CAA->Paired->SmpRate);\n\t\t\t\tCAA->StreamUpdate = &ym2608_stream_update;\n\t\t\t\tCAA->Paired->StreamUpdate = &ym2608_stream_update_ay;\n\t\t\t\tym2608_set_srchg_cb(CurChip, &ChangeChipSampleRate, CAA, CAA->Paired);\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tCAA->Paired->Volume = GetChipVolume(&VGMHead, CAA->Paired->ChipType,\n\t\t\t\t\t\t\t\t\t\t\t\t\tCurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume + CAA->Paired->Volume;\n\t\t\t\t//CAA->Volume = ChipVol;\n\t\t\t\t//CAA->Paired->Volume = ChipVol * 2;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzYM2610)\n\t\t{\n\t\t\t//ChipVol = 0x80;\n\t\t\tym2610_set_ay_emu_core(ChipOpts[0x00].YM2610.EmuCore);\n\t\t\tChipOpts[0x01].YM2610.EmuCore = ChipOpts[0x00].YM2610.EmuCore;\n\t\t\tChipOpts[0x01].YM2610.SpecialFlags = ChipOpts[0x00].YM2610.SpecialFlags;\n\t\t\t\n\t\t\tChipCnt = (VGMHead.lngHzYM2610 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].YM2610;\n\t\t\t\tCOpt = &ChipOpts[CurChip].YM2610;\n\t\t\t\tCAA->ChipType = 0x08;\n\t\t\t\tCAA->Paired = &CA_Paired[CurChip][0x02];\n\t\t\t\tCAA->Paired->ChipType = 0x80 | CAA->ChipType;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_ym2610(CurChip, ChipClk, COpt->SpecialFlags & 0x01,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(int*)&CAA->Paired->SmpRate);\n\t\t\t\tCAA->StreamUpdate = (ChipClk & 0x80000000) ? ym2610b_stream_update :\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tym2610_stream_update;\n\t\t\t\tCAA->Paired->StreamUpdate = &ym2610_stream_update_ay;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tCAA->Paired->Volume = GetChipVolume(&VGMHead, CAA->Paired->ChipType,\n\t\t\t\t\t\t\t\t\t\t\t\t\tCurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume + CAA->Paired->Volume;\n\t\t\t\t//CAA->Volume = ChipVol;\n\t\t\t\t//CAA->Paired->Volume = ChipVol * 2;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzYM3812)\n\t\t{\n\t\t\t//ChipVol = UseFM ? 0x00 : 0x100;\n\t\t\tym3812_set_emu_core(ChipOpts[0x00].YM3812.EmuCore);\n\t\t\tChipOpts[0x01].YM3812.EmuCore = ChipOpts[0x00].YM3812.EmuCore;\n\t\t\t\n\t\t\tChipCnt = (VGMHead.lngHzYM3812 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].YM3812;\n\t\t\t\tCAA->ChipType = 0x09;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tif (! UseFM)\n\t\t\t\t{\n\t\t\t\t\tCAA->SmpRate = device_start_ym3812(CurChip, ChipClk);\n\t\t\t\t\tCAA->StreamUpdate = (ChipClk & 0x80000000) ? dual_opl2_stereo :\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tym3812_stream_update;\n\t\t\t\t\t\n\t\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\t\tif (! CurChip || ! (ChipClk & 0x80000000))\n\t\t\t\t\t\tAbsVol += CAA->Volume * 2;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsetup_real_fm(CAA->ChipType, CurChip);\n\t\t\t\t\t\n\t\t\t\t\tCAA->SmpRate = 0x00000000;\n\t\t\t\t\tCAA->Volume = 0x0000;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzYM3526)\n\t\t{\n\t\t\t//ChipVol = UseFM ? 0x00 : 0x100;\n\t\t\tChipCnt = (VGMHead.lngHzYM3526 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].YM3526;\n\t\t\t\tCAA->ChipType = 0x0A;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tif (! UseFM)\n\t\t\t\t{\n\t\t\t\t\tCAA->SmpRate = device_start_ym3526(CurChip, ChipClk);\n\t\t\t\t\tCAA->StreamUpdate = &ym3526_stream_update;\n\t\t\t\t\t\n\t\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\t\tAbsVol += CAA->Volume * 2;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsetup_real_fm(CAA->ChipType, CurChip);\n\t\t\t\t\t\n\t\t\t\t\tCAA->SmpRate = 0x00000000;\n\t\t\t\t\tCAA->Volume = 0x0000;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzY8950)\n\t\t{\n\t\t\t//ChipVol = UseFM ? 0x00 : 0x100;\n\t\t\tChipCnt = (VGMHead.lngHzY8950 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].Y8950;\n\t\t\t\tCAA->ChipType = 0x0B;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tif (! UseFM)\n\t\t\t\t{\n\t\t\t\t\tCAA->SmpRate = device_start_y8950(CurChip, ChipClk);\n\t\t\t\t\tCAA->StreamUpdate = &y8950_stream_update;\n\t\t\t\t\t\n\t\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\t\tAbsVol += CAA->Volume * 2;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsetup_real_fm(CAA->ChipType, CurChip);\n\t\t\t\t\t\n\t\t\t\t\tCAA->SmpRate = 0x00000000;\n\t\t\t\t\tCAA->Volume = 0x0000;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzYMF262)\n\t\t{\n\t\t\t//ChipVol = UseFM ? 0x00 : 0x100;\n\t\t\tymf262_set_emu_core(ChipOpts[0x00].YMF262.EmuCore);\n\t\t\tChipOpts[0x01].YMF262.EmuCore = ChipOpts[0x00].YMF262.EmuCore;\n\t\t\t\n\t\t\tChipCnt = (VGMHead.lngHzYMF262 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].YMF262;\n\t\t\t\tCAA->ChipType = 0x0C;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tif (! UseFM)\n\t\t\t\t{\n\t\t\t\t\tCAA->SmpRate = device_start_ymf262(CurChip, ChipClk);\n\t\t\t\t\tCAA->StreamUpdate = &ymf262_stream_update;\n\t\t\t\t\t\n\t\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\t\tAbsVol += CAA->Volume * 2;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsetup_real_fm(CAA->ChipType, CurChip);\n\t\t\t\t\t\n\t\t\t\t\tCAA->SmpRate = 0x00000000;\n\t\t\t\t\tCAA->Volume = 0x0000;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzYMF278B)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tChipCnt = (VGMHead.lngHzYMF278B & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].YMF278B;\n\t\t\t\tCAA->ChipType = 0x0D;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_ymf278b(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &ymf278b_pcm_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\t//good as long as it only uses WaveTable Synth\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzYMF271)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tChipCnt = (VGMHead.lngHzYMF271 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].YMF271;\n\t\t\t\tCAA->ChipType = 0x0E;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_ymf271(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &ymf271_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzYMZ280B)\n\t\t{\n\t\t\t//ChipVol = 0x98;\n\t\t\tChipCnt = (VGMHead.lngHzYMZ280B & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].YMZ280B;\n\t\t\t\tCAA->ChipType = 0x0F;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_ymz280b(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &ymz280b_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += (CAA->Volume * 0x20 / 0x13);\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzRF5C164)\n\t\t{\n\t\t\t//ChipVol = 0x80;\n\t\t\tChipCnt = 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].RF5C164;\n\t\t\t\tCAA->ChipType = 0x10;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_rf5c164(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &rf5c164_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume * 2;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzPWM)\n\t\t{\n\t\t\t//ChipVol = 0xE0;\t// 0xCD\n\t\t\tChipCnt = 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].PWM;\n\t\t\t\tCAA->ChipType = 0x11;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_pwm(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &pwm_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzAY8910)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tayxx_set_emu_core(ChipOpts[0x00].AY8910.EmuCore);\n\t\t\tChipOpts[0x01].AY8910.EmuCore = ChipOpts[0x00].AY8910.EmuCore;\n\t\t\t\n\t\t\tChipCnt = (VGMHead.lngHzAY8910 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].AY8910;\n\t\t\t\tCAA->ChipType = 0x12;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tif (! UseFM)\n\t\t\t\t{\n\t\t\t\t\tCAA->SmpRate = device_start_ayxx(CurChip, ChipClk,\n\t\t\t\t\t\t\t\t\t\t\t\t\tVGMHead.bytAYType, VGMHead.bytAYFlag);\n\t\t\t\t\tCAA->StreamUpdate = &ayxx_stream_update;\n\t\t\t\t\t\n\t\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\t\tAbsVol += CAA->Volume * 2;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\topen_fm_option(CAA->ChipType, 0x00, ChipClk);\n\t\t\t\t\topen_fm_option(CAA->ChipType, 0x01, VGMHead.bytAYType);\n\t\t\t\t\topen_fm_option(CAA->ChipType, 0x02, VGMHead.bytAYFlag);\n\t\t\t\t\tsetup_real_fm(CAA->ChipType, CurChip);\n\t\t\t\t\t\n\t\t\t\t\tCAA->SmpRate = 0x00000000;\n\t\t\t\t\tCAA->Volume = 0x0000;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzGBDMG)\n\t\t{\n\t\t\t//ChipVol = 0xC0;\n\t\t\tgameboy_sound_set_options((UINT8)ChipOpts[0x00].GameBoy.SpecialFlags);\n\t\t\tChipOpts[0x01].GameBoy.SpecialFlags = ChipOpts[0x00].GameBoy.SpecialFlags;\n\t\t\t\n\t\t\tChipCnt = (VGMHead.lngHzGBDMG & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].GameBoy;\n\t\t\t\tCAA->ChipType = 0x13;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_gameboy_sound(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &gameboy_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume * 2;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzNESAPU)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tnes_set_emu_core(ChipOpts[0x00].NES.EmuCore);\n\t\t\tnes_set_options(ChipOpts[0x00].NES.SpecialFlags);\n\t\t\tChipOpts[0x01].NES.EmuCore = ChipOpts[0x00].NES.EmuCore;\n\t\t\tChipOpts[0x01].NES.SpecialFlags = ChipOpts[0x00].NES.SpecialFlags;\n\t\t\t\n\t\t\tChipCnt = (VGMHead.lngHzNESAPU & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].NES;\n\t\t\t\tCAA->ChipType = 0x14;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_nes(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &nes_stream_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume * 2;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzMultiPCM)\n\t\t{\n\t\t\t//ChipVol = 0x40;\n\t\t\tChipCnt = (VGMHead.lngHzMultiPCM & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].MultiPCM;\n\t\t\t\tCAA->ChipType = 0x15;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_multipcm(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &MultiPCM_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume * 4;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzUPD7759)\n\t\t{\n\t\t\t//ChipVol = 0x11E;\n\t\t\tChipCnt = (VGMHead.lngHzUPD7759 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].UPD7759;\n\t\t\t\tCAA->ChipType = 0x16;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_upd7759(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &upd7759_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzOKIM6258)\n\t\t{\n\t\t\t//ChipVol = 0x1C0;\n\t\t\tokim6258_set_options(ChipOpts[0x00].OKIM6258.SpecialFlags);\n\t\t\tChipOpts[0x01].OKIM6258.SpecialFlags = ChipOpts[0x00].OKIM6258.SpecialFlags;\n\t\t\t\n\t\t\tChipCnt = (VGMHead.lngHzOKIM6258 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].OKIM6258;\n\t\t\t\tCAA->ChipType = 0x17;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_okim6258(CurChip, ChipClk,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(VGMHead.bytOKI6258Flags & 0x03) >> 0,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(VGMHead.bytOKI6258Flags & 0x04) >> 2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t(VGMHead.bytOKI6258Flags & 0x08) >> 3);\n\t\t\t\tCAA->StreamUpdate = &okim6258_update;\n\t\t\t\tokim6258_set_srchg_cb(CurChip, &ChangeChipSampleRate, CAA);\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume * 2;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzOKIM6295)\n\t\t{\n\t\t\t/*// Use the System Tag to decide between normal and CP System volume level.\n\t\t\t// I know, this is very hackish, but ATM there's no better solution.\n\t\t\tif (VGMTag.strSystemNameE != NULL && ! wcsncmp(VGMTag.strSystemNameE, L\"CP\", 0x02))\n\t\t\t\tChipVol = 110;\n\t\t\telse\n\t\t\t\tChipVol = 0x100;*/\n\t\t\tChipCnt = (VGMHead.lngHzOKIM6295 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].OKIM6295;\n\t\t\t\tCAA->ChipType = 0x18;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_okim6295(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &okim6295_update;\n\t\t\t\tokim6295_set_srchg_cb(CurChip, &ChangeChipSampleRate, CAA);\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume * 2;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzK051649)\n\t\t{\n\t\t\t//ChipVol = 0xA0;\n\t\t\tChipCnt = (VGMHead.lngHzK051649 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].K051649;\n\t\t\t\tCAA->ChipType = 0x19;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_k051649(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &k051649_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzK054539)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tChipCnt = (VGMHead.lngHzK054539 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].K054539;\n\t\t\t\tCAA->ChipType = 0x1A;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_k054539(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &k054539_update;\n\t\t\t\tk054539_init_flags(CurChip, VGMHead.bytK054539Flags);\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzHuC6280)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tc6280_set_emu_core(ChipOpts[0x00].HuC6280.EmuCore);\n\t\t\tChipOpts[0x01].HuC6280.EmuCore = ChipOpts[0x00].HuC6280.EmuCore;\n\t\t\t\n\t\t\tChipCnt = (VGMHead.lngHzHuC6280 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].HuC6280;\n\t\t\t\tCAA->ChipType = 0x1B;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_c6280(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &c6280_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzC140)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tChipCnt = (VGMHead.lngHzC140 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].C140;\n\t\t\t\tCAA->ChipType = 0x1C;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_c140(CurChip, ChipClk, VGMHead.bytC140Type);\n\t\t\t\tCAA->StreamUpdate = &c140_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzK053260)\n\t\t{\n\t\t\t//ChipVol = 0xB3;\n\t\t\tChipCnt = (VGMHead.lngHzK053260 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].K053260;\n\t\t\t\tCAA->ChipType = 0x1D;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_k053260(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &k053260_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzPokey)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tChipCnt = (VGMHead.lngHzPokey & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].Pokey;\n\t\t\t\tCAA->ChipType = 0x1E;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_pokey(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &pokey_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzQSound)\n\t\t{\n\t\t\tqsound_set_emu_core(ChipOpts[0x00].QSound.EmuCore);\n\t\t\tChipOpts[0x01].QSound.EmuCore = ChipOpts[0x00].QSound.EmuCore;\n\t\t\t\n\t\t\t//ChipVol = 0x100;\n\t\t\tChipCnt = (VGMHead.lngHzQSound & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].QSound;\n\t\t\t\tCAA->ChipType = 0x1F;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_qsound(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &qsound_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzSCSP)\n\t\t{\n\t\t\tscsp_set_options((UINT8)ChipOpts[0x00].SCSP.SpecialFlags);\n\t\t\tChipOpts[0x01].SCSP.SpecialFlags = ChipOpts[0x00].SCSP.SpecialFlags;\n\t\t\t\n\t\t\t//ChipVol = 0x20;\n\t\t\tChipCnt = (VGMHead.lngHzSCSP & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].SCSP;\n\t\t\t\tCAA->ChipType = 0x20;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_scsp(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &SCSP_Update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume * 8;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzWSwan)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tChipCnt = (VGMHead.lngHzWSwan & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].WSwan;\n\t\t\t\tCAA->ChipType = 0x21;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = ws_audio_init(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &ws_audio_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzVSU)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tChipCnt = (VGMHead.lngHzVSU & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].VSU;\n\t\t\t\tCAA->ChipType = 0x22;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_vsu(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &vsu_stream_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzSAA1099)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tChipCnt = (VGMHead.lngHzSAA1099 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].SAA1099;\n\t\t\t\tCAA->ChipType = 0x23;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_saa1099(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &saa1099_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzES5503)\n\t\t{\n\t\t\t//ChipVol = 0x40;\n\t\t\tChipCnt = (VGMHead.lngHzES5503 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].ES5503;\n\t\t\t\tCAA->ChipType = 0x24;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_es5503(CurChip, ChipClk, VGMHead.bytES5503Chns);\n\t\t\t\tCAA->StreamUpdate = &es5503_pcm_update;\n\t\t\t\tes5503_set_srchg_cb(CurChip, &ChangeChipSampleRate, CAA);\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume * 8;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzES5506)\n\t\t{\n\t\t\t//ChipVol = 0x20;\n\t\t\tChipCnt = (VGMHead.lngHzES5506 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].ES5506;\n\t\t\t\tCAA->ChipType = 0x25;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_es5506(CurChip, ChipClk, VGMHead.bytES5506Chns);\n\t\t\t\tCAA->StreamUpdate = &es5506_update;\n\t\t\t\tes5506_set_srchg_cb(CurChip, &ChangeChipSampleRate, CAA);\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume * 16;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzX1_010)\n\t\t{\n\t\t\t//ChipVol = 0x100;\n\t\t\tChipCnt = (VGMHead.lngHzX1_010 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].X1_010;\n\t\t\t\tCAA->ChipType = 0x26;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_x1_010(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &seta_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzC352)\n\t\t{\n\t\t\tc352_set_options((UINT8)ChipOpts[0x00].C352.SpecialFlags);\n\t\t\tChipOpts[0x01].C352.SpecialFlags = ChipOpts[0x00].C352.SpecialFlags;\n\t\t\t\n\t\t\t//ChipVol = 0x40;\n\t\t\tChipCnt = (VGMHead.lngHzC352 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].C352;\n\t\t\t\tCAA->ChipType = 0x27;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_c352(CurChip, ChipClk, VGMHead.bytC352ClkDiv * 4);\n\t\t\t\tCAA->StreamUpdate = &c352_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume * 8;\n\t\t\t}\n\t\t}\n\t\tif (VGMHead.lngHzGA20)\n\t\t{\n\t\t\t//ChipVol = 0x280;\n\t\t\tChipCnt = (VGMHead.lngHzGA20 & 0x40000000) ? 0x02 : 0x01;\n\t\t\tfor (CurChip = 0x00; CurChip < ChipCnt; CurChip ++)\n\t\t\t{\n\t\t\t\tCAA = &ChipAudio[CurChip].GA20;\n\t\t\t\tCAA->ChipType = 0x28;\n\t\t\t\t\n\t\t\t\tChipClk = GetChipClock(&VGMHead, (CurChip << 7) | CAA->ChipType, NULL);\n\t\t\t\tCAA->SmpRate = device_start_iremga20(CurChip, ChipClk);\n\t\t\t\tCAA->StreamUpdate = &IremGA20_update;\n\t\t\t\t\n\t\t\t\tCAA->Volume = GetChipVolume(&VGMHead, CAA->ChipType, CurChip, ChipCnt);\n\t\t\t\tAbsVol += CAA->Volume;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Initialize DAC Control and PCM Bank\n\t\tDacCtrlUsed = 0x00;\n\t\t//memset(DacCtrlUsg, 0x00, 0x01 * 0xFF);\n\t\tfor (CurChip = 0x00; CurChip < 0xFF; CurChip ++)\n\t\t{\n\t\t\tDacCtrl[CurChip].Enable = false;\n\t\t}\n\t\t//memset(DacCtrl, 0x00, sizeof(DACCTRL_DATA) * 0xFF);\n\t\t\n\t\tmemset(PCMBank, 0x00, sizeof(VGM_PCM_BANK) * PCM_BANK_COUNT);\n\t\tmemset(&PCMTbl, 0x00, sizeof(PCMBANK_TBL));\n\t\t\n\t\t// Reset chips\n\t\tChips_GeneralActions(0x01);\n\t\t\n\t\twhile(AbsVol < 0x200 && AbsVol)\n\t\t{\n\t\t\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t\t\t{\n\t\t\t\tCAA = (CAUD_ATTR*)&ChipAudio[CurCSet];\n\t\t\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, CAA ++)\n\t\t\t\t\tCAA->Volume *= 2;\n\t\t\t\tCAA = CA_Paired[CurCSet];\n\t\t\t\tfor (CurChip = 0x00; CurChip < 0x03; CurChip ++, CAA ++)\n\t\t\t\t\tCAA->Volume *= 2;\n\t\t\t}\n\t\t\tAbsVol *= 2;\n\t\t}\n\t\twhile(AbsVol > 0x300)\n\t\t{\n\t\t\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t\t\t{\n\t\t\t\tCAA = (CAUD_ATTR*)&ChipAudio[CurCSet];\n\t\t\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, CAA ++)\n\t\t\t\t\tCAA->Volume /= 2;\n\t\t\t\tCAA = CA_Paired[CurCSet];\n\t\t\t\tfor (CurChip = 0x00; CurChip < 0x03; CurChip ++, CAA ++)\n\t\t\t\t\tCAA->Volume /= 2;\n\t\t\t}\n\t\t\tAbsVol /= 2;\n\t\t}\n\t\t\n\t\t// Initialize Resampler\n\t\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t\t{\n\t\t\tCAA = (CAUD_ATTR*)&ChipAudio[CurCSet];\n\t\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, CAA ++)\n\t\t\t\tSetupResampler(CAA);\n\t\t\t\n\t\t\tCAA = CA_Paired[CurCSet];\n\t\t\tfor (CurChip = 0x00; CurChip < 0x03; CurChip ++, CAA ++)\n\t\t\t\tSetupResampler(CAA);\n\t\t}\n\t\t\n\t\tGeneralChipLists();\n\t\tbreak;\n\tcase 0x01:\t// Reset chips\n\t\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t\t{\n\t\t\n\t\tCAA = (CAUD_ATTR*)&ChipAudio[CurCSet];\n\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, CAA ++)\n\t\t{\n\t\t\tif (CAA->ChipType == 0xFF)\t// chip unused\n\t\t\t\tcontinue;\n\t\t\telse if (CAA->ChipType == 0x00 && ! UseFM)\n\t\t\t\tdevice_reset_sn764xx(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x01 && ! UseFM)\n\t\t\t\tdevice_reset_ym2413(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x02)\n\t\t\t\tdevice_reset_ym2612(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x03)\n\t\t\t\tdevice_reset_ym2151(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x04)\n\t\t\t\tdevice_reset_segapcm(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x05)\n\t\t\t\tdevice_reset_rf5c68(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x06)\n\t\t\t\tdevice_reset_ym2203(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x07)\n\t\t\t\tdevice_reset_ym2608(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x08)\n\t\t\t\tdevice_reset_ym2610(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x09)\n\t\t\t{\n\t\t\t\tif (! UseFM)\n\t\t\t\t{\n\t\t\t\t\tdevice_reset_ym3812(CurCSet);\n\t\t\t\t}\n\t\t\t\tif (FileMode == 0x01)\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x09, CurCSet, 0x00, 0x01, 0x20);\t// Enable Waveform Select\n\t\t\t\t\tchip_reg_write(0x09, CurCSet, 0x00, 0xBD, 0xC0);\t// Disable Rhythm Mode\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (CAA->ChipType == 0x0A && ! UseFM)\n\t\t\t\tdevice_reset_ym3526(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x0B && ! UseFM)\n\t\t\t\tdevice_reset_y8950(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x0C)\n\t\t\t{\n\t\t\t\tif (! UseFM)\n\t\t\t\t{\n\t\t\t\t\tdevice_reset_ymf262(CurCSet);\n\t\t\t\t}\n\t\t\t\tif (FileMode >= 0x01)\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x0C, CurCSet, 0x01, 0x05, 0x01);\t// Enable OPL3-Mode\n\t\t\t\t\tchip_reg_write(0x0C, CurCSet, 0x00, 0xBD, 0xC0);\t// Disable Rhythm Mode\n\t\t\t\t\tchip_reg_write(0x0C, CurCSet, 0x01, 0x04, 0x00);\t// Disable 4-Op-Mode\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (CAA->ChipType == 0x0D)\n\t\t\t\tdevice_reset_ymf278b(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x0E)\n\t\t\t\tdevice_reset_ymf271(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x0F)\n\t\t\t\tdevice_reset_ymz280b(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x10)\n\t\t\t\tdevice_reset_rf5c164(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x11)\n\t\t\t\tdevice_reset_pwm(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x12 && ! UseFM)\n\t\t\t\tdevice_reset_ayxx(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x13)\n\t\t\t\tdevice_reset_gameboy_sound(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x14)\n\t\t\t\tdevice_reset_nes(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x15)\n\t\t\t\tdevice_reset_multipcm(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x16)\n\t\t\t\tdevice_reset_upd7759(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x17)\n\t\t\t\tdevice_reset_okim6258(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x18)\n\t\t\t\tdevice_reset_okim6295(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x19)\n\t\t\t\tdevice_reset_k051649(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x1A)\n\t\t\t\tdevice_reset_k054539(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x1B)\n\t\t\t\tdevice_reset_c6280(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x1C)\n\t\t\t\tdevice_reset_c140(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x1D)\n\t\t\t\tdevice_reset_k053260(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x1E)\n\t\t\t\tdevice_reset_pokey(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x1F)\n\t\t\t\tdevice_reset_qsound(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x20)\n\t\t\t\tdevice_reset_scsp(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x21)\n\t\t\t\tws_audio_reset(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x22)\n\t\t\t\tdevice_reset_vsu(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x23)\n\t\t\t\tdevice_reset_saa1099(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x24)\n\t\t\t\tdevice_reset_es5503(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x25)\n\t\t\t\tdevice_reset_es5506(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x26)\n\t\t\t\tdevice_reset_x1_010(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x27)\n\t\t\t\tdevice_reset_c352(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x28)\n\t\t\t\tdevice_reset_iremga20(CurCSet);\n\t\t}\t// end for CurChip\n\t\t\n\t\t}\t// end for CurCSet\n\t\t\n\t\tChips_GeneralActions(0x10);\t// set muting mask\n\t\tChips_GeneralActions(0x20);\t// set panning\n\t\t\n\t\tfor (CurChip = 0x00; CurChip < DacCtrlUsed; CurChip ++)\n\t\t{\n\t\t\tCurCSet = DacCtrlUsg[CurChip];\n\t\t\tdevice_reset_daccontrol(CurCSet);\n\t\t\t//DacCtrl[CurCSet].Enable = false;\n\t\t}\n\t\t//DacCtrlUsed = 0x00;\n\t\t//memset(DacCtrlUsg, 0x00, 0x01 * 0xFF);\n\t\t\n\t\tfor (CurChip = 0x00; CurChip < PCM_BANK_COUNT; CurChip ++)\n\t\t{\n\t\t\t// reset PCM Bank, but not the data\n\t\t\t// (this way I don't need to decompress the data again when restarting)\n\t\t\tPCMBank[CurChip].DataPos = 0x00000000;\n\t\t\tPCMBank[CurChip].BnkPos = 0x00000000;\n\t\t}\n\t\tPCMTbl.EntryCount = 0x00;\n\t\tbreak;\n\tcase 0x02:\t// Stop chips\n\t\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t\t{\n\t\t\n\t\tCAA = (CAUD_ATTR*)&ChipAudio[CurCSet];\n\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, CAA ++)\n\t\t{\n\t\t\tif (CAA->ChipType == 0xFF)\t// chip unused\n\t\t\t\tcontinue;\n\t\t\telse if (CAA->ChipType == 0x00 && ! UseFM)\n\t\t\t\tdevice_stop_sn764xx(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x01 && ! UseFM)\n\t\t\t\tdevice_stop_ym2413(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x02)\n\t\t\t\tdevice_stop_ym2612(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x03)\n\t\t\t\tdevice_stop_ym2151(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x04)\n\t\t\t\tdevice_stop_segapcm(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x05)\n\t\t\t\tdevice_stop_rf5c68(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x06)\n\t\t\t\tdevice_stop_ym2203(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x07)\n\t\t\t\tdevice_stop_ym2608(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x08)\n\t\t\t\tdevice_stop_ym2610(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x09 && ! UseFM)\n\t\t\t\tdevice_stop_ym3812(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x0A && ! UseFM)\n\t\t\t\tdevice_stop_ym3526(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x0B && ! UseFM)\n\t\t\t\tdevice_stop_y8950(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x0C && ! UseFM)\n\t\t\t\tdevice_stop_ymf262(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x0D)\n\t\t\t\tdevice_stop_ymf278b(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x0E)\n\t\t\t\tdevice_stop_ymf271(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x0F)\n\t\t\t\tdevice_stop_ymz280b(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x10)\n\t\t\t\tdevice_stop_rf5c164(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x11)\n\t\t\t\tdevice_stop_pwm(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x12 && ! UseFM)\n\t\t\t\tdevice_stop_ayxx(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x13)\n\t\t\t\tdevice_stop_gameboy_sound(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x14)\n\t\t\t\tdevice_stop_nes(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x15)\n\t\t\t\tdevice_stop_multipcm(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x16)\n\t\t\t\tdevice_stop_upd7759(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x17)\n\t\t\t\tdevice_stop_okim6258(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x18)\n\t\t\t\tdevice_stop_okim6295(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x19)\n\t\t\t\tdevice_stop_k051649(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x1A)\n\t\t\t\tdevice_stop_k054539(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x1B)\n\t\t\t\tdevice_stop_c6280(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x1C)\n\t\t\t\tdevice_stop_c140(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x1D)\n\t\t\t\tdevice_stop_k053260(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x1E)\n\t\t\t\tdevice_stop_pokey(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x1F)\n\t\t\t\tdevice_stop_qsound(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x20)\n\t\t\t\tdevice_stop_scsp(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x21)\n\t\t\t\tws_audio_done(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x22)\n\t\t\t\tdevice_stop_vsu(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x23)\n\t\t\t\tdevice_stop_saa1099(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x24)\n\t\t\t\tdevice_stop_es5503(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x25)\n\t\t\t\tdevice_stop_es5506(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x26)\n\t\t\t\tdevice_stop_x1_010(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x27)\n\t\t\t\tdevice_stop_c352(CurCSet);\n\t\t\telse if (CAA->ChipType == 0x28)\n\t\t\t\tdevice_stop_iremga20(CurCSet);\n\t\t\t\n\t\t\tCAA->ChipType = 0xFF;\t// mark as \"unused\"\n\t\t}\t// end for CurChip\n\t\t\n\t\t}\t// end for CurCSet\n\t\t\n\t\tfor (CurChip = 0x00; CurChip < DacCtrlUsed; CurChip ++)\n\t\t{\n\t\t\tCurCSet = DacCtrlUsg[CurChip];\n\t\t\tdevice_stop_daccontrol(CurCSet);\n\t\t\tDacCtrl[CurCSet].Enable = false;\n\t\t}\n\t\tDacCtrlUsed = 0x00;\n\t\t\n\t\tfor (CurChip = 0x00; CurChip < PCM_BANK_COUNT; CurChip ++)\n\t\t{\n\t\t\tfree(PCMBank[CurChip].Bank);\n\t\t\tfree(PCMBank[CurChip].Data);\n\t\t}\n\t\t//memset(PCMBank, 0x00, sizeof(VGM_PCM_BANK) * PCM_BANK_COUNT);\n\t\tfree(PCMTbl.Entries);\n\t\t//memset(&PCMTbl, 0x00, sizeof(PCMBANK_TBL));\n\t\tbreak;\n\tcase 0x10:\t// Set Muting Mask\n\t\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t\t{\n\t\t\n\t\tCAA = (CAUD_ATTR*)&ChipAudio[CurCSet];\n\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, CAA ++)\n\t\t{\n\t\t\tif (CAA->ChipType == 0xFF)\t// chip unused\n\t\t\t\tcontinue;\n\t\t\telse if (CAA->ChipType == 0x00 && ! UseFM)\n\t\t\t\tsn764xx_set_mute_mask(CurCSet, ChipOpts[CurCSet].SN76496.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x01 && ! UseFM)\n\t\t\t\tym2413_set_mute_mask(CurCSet, ChipOpts[CurCSet].YM2413.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x02)\n\t\t\t\tym2612_set_mute_mask(CurCSet, ChipOpts[CurCSet].YM2612.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x03)\n\t\t\t\tym2151_set_mute_mask(CurCSet, ChipOpts[CurCSet].YM2151.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x04)\n\t\t\t\tsegapcm_set_mute_mask(CurCSet, ChipOpts[CurCSet].SegaPCM.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x05)\n\t\t\t\trf5c68_set_mute_mask(CurCSet, ChipOpts[CurCSet].RF5C68.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x06)\n\t\t\t\tym2203_set_mute_mask(CurCSet, ChipOpts[CurCSet].YM2203.ChnMute1,\n\t\t\t\t\t\t\t\t\tChipOpts[CurCSet].YM2203.ChnMute3);\n\t\t\telse if (CAA->ChipType == 0x07)\n\t\t\t{\n\t\t\t\tMaskVal  = (ChipOpts[CurCSet].YM2608.ChnMute1 & 0x3F) << 0;\n\t\t\t\tMaskVal |= (ChipOpts[CurCSet].YM2608.ChnMute2 & 0x7F) << 6;\n\t\t\t\tym2608_set_mute_mask(CurCSet, MaskVal, ChipOpts[CurCSet].YM2608.ChnMute3);\n\t\t\t}\n\t\t\telse if (CAA->ChipType == 0x08)\n\t\t\t{\n\t\t\t\tMaskVal  = (ChipOpts[CurCSet].YM2610.ChnMute1 & 0x3F) << 0;\n\t\t\t\tMaskVal |= (ChipOpts[CurCSet].YM2610.ChnMute2 & 0x7F) << 6;\n\t\t\t\tym2610_set_mute_mask(CurCSet, MaskVal, ChipOpts[CurCSet].YM2610.ChnMute3);\n\t\t\t}\n\t\t\telse if (CAA->ChipType == 0x09 && ! UseFM)\n\t\t\t\tym3812_set_mute_mask(CurCSet, ChipOpts[CurCSet].YM3812.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x0A && ! UseFM)\n\t\t\t\tym3526_set_mute_mask(CurCSet, ChipOpts[CurCSet].YM3526.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x0B && ! UseFM)\n\t\t\t\ty8950_set_mute_mask(CurCSet, ChipOpts[CurCSet].Y8950.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x0C && ! UseFM)\n\t\t\t\tymf262_set_mute_mask(CurCSet, ChipOpts[CurCSet].YMF262.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x0D)\n\t\t\t\tymf278b_set_mute_mask(CurCSet, ChipOpts[CurCSet].YMF278B.ChnMute1,\n\t\t\t\t\t\t\t\t\t\tChipOpts[CurCSet].YMF278B.ChnMute2);\n\t\t\telse if (CAA->ChipType == 0x0E)\n\t\t\t\tymf271_set_mute_mask(CurCSet, ChipOpts[CurCSet].YMF271.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x0F)\n\t\t\t\tymz280b_set_mute_mask(CurCSet, ChipOpts[CurCSet].YMZ280B.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x10)\n\t\t\t\trf5c164_set_mute_mask(CurCSet, ChipOpts[CurCSet].RF5C164.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x11)\n\t\t\t\t;\t// PWM - nothing to mute\n\t\t\telse if (CAA->ChipType == 0x12 && ! UseFM)\n\t\t\t\tayxx_set_mute_mask(CurCSet, ChipOpts[CurCSet].AY8910.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x13)\n\t\t\t\tgameboy_sound_set_mute_mask(CurCSet, ChipOpts[CurCSet].GameBoy.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x14)\n\t\t\t\tnes_set_mute_mask(CurCSet, ChipOpts[CurCSet].NES.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x15)\n\t\t\t\tmultipcm_set_mute_mask(CurCSet, ChipOpts[CurCSet].MultiPCM.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x16)\n\t\t\t\t;\t// UPD7759 - nothing to mute\n\t\t\telse if (CAA->ChipType == 0x17)\n\t\t\t\t;\t// OKIM6258 - nothing to mute\n\t\t\telse if (CAA->ChipType == 0x18)\n\t\t\t\tokim6295_set_mute_mask(CurCSet, ChipOpts[CurCSet].OKIM6295.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x19)\n\t\t\t\tk051649_set_mute_mask(CurCSet, ChipOpts[CurCSet].K051649.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x1A)\n\t\t\t\tk054539_set_mute_mask(CurCSet, ChipOpts[CurCSet].K054539.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x1B)\n\t\t\t\tc6280_set_mute_mask(CurCSet, ChipOpts[CurCSet].HuC6280.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x1C)\n\t\t\t\tc140_set_mute_mask(CurCSet, ChipOpts[CurCSet].C140.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x1D)\n\t\t\t\tk053260_set_mute_mask(CurCSet, ChipOpts[CurCSet].K053260.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x1E)\n\t\t\t\tpokey_set_mute_mask(CurCSet, ChipOpts[CurCSet].Pokey.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x1F)\n\t\t\t\tqsound_set_mute_mask(CurCSet, ChipOpts[CurCSet].QSound.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x20)\n\t\t\t\tscsp_set_mute_mask(CurCSet, ChipOpts[CurCSet].SCSP.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x21)\n\t\t\t\tws_set_mute_mask(CurCSet, ChipOpts[CurCSet].WSwan.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x22)\n\t\t\t\tvsu_set_mute_mask(CurCSet, ChipOpts[CurCSet].VSU.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x23)\n\t\t\t\tsaa1099_set_mute_mask(CurCSet, ChipOpts[CurCSet].SAA1099.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x24)\n\t\t\t\tes5503_set_mute_mask(CurCSet, ChipOpts[CurCSet].ES5503.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x25)\n\t\t\t\tes5506_set_mute_mask(CurCSet, ChipOpts[CurCSet].ES5506.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x26)\n\t\t\t\tx1_010_set_mute_mask(CurCSet, ChipOpts[CurCSet].X1_010.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x27)\n\t\t\t\tc352_set_mute_mask(CurCSet, ChipOpts[CurCSet].C352.ChnMute1);\n\t\t\telse if (CAA->ChipType == 0x28)\n\t\t\t\tiremga20_set_mute_mask(CurCSet, ChipOpts[CurCSet].GA20.ChnMute1);\n\t\t}\t// end for CurChip\n\t\t\n\t\t}\t// end for CurCSet\n\t\tbreak;\n\tcase 0x20:\t// Set Panning\n\t\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t\t{\n\t\t\n\t\tCAA = (CAUD_ATTR*)&ChipAudio[CurCSet];\n\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, CAA ++)\n\t\t{\n\t\t\tif (CAA->ChipType == 0xFF)\t// chip unused\n\t\t\t\tcontinue;\n\t\t\telse if (CAA->ChipType == 0x00 && ! UseFM)\n\t\t\t\tsn764xx_set_panning(CurCSet, ChipOpts[CurCSet].SN76496.Panning);\n\t\t\telse if (CAA->ChipType == 0x01 && ! UseFM)\n\t\t\t\tym2413_set_panning(CurCSet, ChipOpts[CurCSet].YM2413.Panning);\n\t\t}\t// end for CurChip\n\t\t\n\t\t}\t// end for CurCSet\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\nINLINE INT32 SampleVGM2Pbk_I(INT32 SampleVal)\n{\n\treturn (INT32)((INT64)SampleVal * VGMSmplRateMul / VGMSmplRateDiv);\n}\n\nINLINE INT32 SamplePbk2VGM_I(INT32 SampleVal)\n{\n\treturn (INT32)((INT64)SampleVal * VGMSmplRateDiv / VGMSmplRateMul);\n}\n\nINT32 SampleVGM2Playback(INT32 SampleVal)\n{\n\treturn (INT32)((INT64)SampleVal * VGMSmplRateMul / VGMSmplRateDiv);\n}\n\nINT32 SamplePlayback2VGM(INT32 SampleVal)\n{\n\treturn (INT32)((INT64)SampleVal * VGMSmplRateDiv / VGMSmplRateMul);\n}\n\nstatic UINT8 StartThread(void)\n{\n#ifdef WIN32\n\tHANDLE PlayThreadHandle;\n\tDWORD PlayThreadID;\n\t//char TestStr[0x80];\n\t\n\tif (PlayThreadOpen)\n\t\treturn 0xD0;\t// Thread is already active\n\t\n\tPauseThread = true;\n\tThreadNoWait = false;\n\tThreadPauseConfrm = false;\n\tCloseThread = false;\n\tThreadPauseEnable = true;\n\t\n\tPlayThreadHandle = CreateThread(NULL, 0x00, &PlayingThread, NULL, 0x00, &PlayThreadID);\n\tif (PlayThreadHandle == NULL)\n\t\treturn 0xC8;\t\t// CreateThread failed\n\tCloseHandle(PlayThreadHandle);\n\t\n\tPlayThreadOpen = true;\n\t//PauseThread = false;\tis done after File Init\n\t\n\treturn 0x00;\n#else\n\tUINT32 RetVal;\n\t\n\tPauseThread = true;\n\tThreadNoWait = false;\n\tThreadPauseConfrm = false;\n\tCloseThread = false;\n\tThreadPauseEnable = true;\n\t\n\tRetVal = pthread_create(&hPlayThread, NULL, &PlayingThread, NULL);\n\tif (RetVal)\n\t\treturn 0xC8;\t\t// CreateThread failed\n\t\n\tPlayThreadOpen = true;\n\t\n\treturn 0x00;\n#endif\n}\n\nstatic UINT8 StopThread(void)\n{\n#ifdef WIN32\n\tUINT16 Cnt;\n#endif\n\t\n\tif (! PlayThreadOpen)\n\t\treturn 0xD8;\t// Thread is not active\n\t\n#ifdef WIN32\n\tCloseThread = true;\n\tfor (Cnt = 0; Cnt < 100; Cnt ++)\n\t{\n\t\tSleep(1);\n\t\tif (hPlayThread == NULL)\n\t\t\tbreak;\n\t}\n#else\n\tCloseThread = true;\n\tpthread_join(hPlayThread, NULL);\n#endif\n\tPlayThreadOpen = false;\n\tThreadPauseEnable = false;\n\t\n\treturn 0x00;\n}\n\n#if defined(WIN32) && defined(MIXER_MUTING)\n//static bool GetMixerControl(HMIXEROBJ hmixer, MIXERCONTROL* mxc)\nstatic bool GetMixerControl(void)\n{\n\t// This function attempts to obtain a mixer control. Returns True if successful.\n\tMIXERLINECONTROLS mxlc;\n\tMIXERLINE mxl;\n\tHGLOBAL hmem;\n\tMMRESULT RetVal;\n\t\n\tmxl.cbStruct = sizeof(MIXERLINE);\n\tmxl.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;\n\t// Obtain a line corresponding to the component type\n\tRetVal = mixerGetLineInfo((HMIXEROBJ)hmixer, &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE);\n\tif (RetVal != MMSYSERR_NOERROR)\n\t\treturn false;\n\t\n\tmxlc.cbStruct = sizeof(MIXERLINECONTROLS);\n\tmxlc.dwLineID = mxl.dwLineID;\n\tmxlc.dwControlID = MIXERCONTROL_CONTROLTYPE_MUTE;\n\tmxlc.cControls = 1;\n\tmxlc.cbmxctrl = sizeof(MIXERCONTROL);\n\t\n\t// Allocate a buffer for the control\n\thmem = GlobalAlloc(0x40, sizeof(MIXERCONTROL));\n\tmxlc.pamxctrl = (MIXERCONTROL*)GlobalLock(hmem);\n\tmixctrl.cbStruct = sizeof(MIXERCONTROL);\n\t\n\t// Get the control\n\tRetVal = mixerGetLineControls((HMIXEROBJ)hmixer, &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);\n\tif (RetVal != MMSYSERR_NOERROR)\n\t{\n\t\tGlobalFree(hmem);\n\t\treturn false;\n\t}\n\t\n\t// Copy the control into the destination structure\n\t//memcpy(mixctrl, mxlc.pamxctrl, sizeof(MIXERCONTROL));\n\tmixctrl = *mxlc.pamxctrl;\n\tGlobalFree(hmem);\n\t\n\treturn true;\n}\n#endif\n\n//static bool SetMuteControl(HMIXEROBJ hmixer, MIXERCONTROL* mxc, bool mute)\nstatic bool SetMuteControl(bool mute)\n{\n#ifdef MIXER_MUTING\n\n#ifdef WIN32\n\tMIXERCONTROLDETAILS mxcd;\n\tMIXERCONTROLDETAILS_UNSIGNED vol;\n\tHGLOBAL hmem;\n\tMMRESULT RetVal;\n\t\n\tmxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);\n\tmxcd.dwControlID = mixctrl.dwControlID;\n\tmxcd.cChannels = 1;\n\tmxcd.cMultipleItems = 0;\n\tmxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);\n\t\n\thmem = GlobalAlloc(0x40, sizeof(MIXERCONTROLDETAILS_UNSIGNED));\n\tmxcd.paDetails = GlobalLock(hmem);\n\tvol.dwValue = mute;\n\t\n\tmemcpy(mxcd.paDetails, &vol, sizeof(MIXERCONTROLDETAILS_UNSIGNED));\n\tRetVal = mixerSetControlDetails((HMIXEROBJ)hmixer, &mxcd, MIXER_SETCONTROLDETAILSF_VALUE);\n\tGlobalFree(hmem);\n\t\n\tif (RetVal != MMSYSERR_NOERROR)\n\t\treturn false;\n\t\n\treturn true;\n#else\n\tUINT16 mix_vol;\n\tint RetVal;\n\t\n\tioctl(hmixer, MIXER_READ(SOUND_MIXER_SYNTH), &mix_vol);\n\tif (mix_vol)\n\t\tmixer_vol = mix_vol;\n\tmix_vol = mute ? 0x0000: mixer_vol;\n\t\n\tRetVal = ioctl(hmixer, MIXER_WRITE(SOUND_MIXER_SYNTH), &mix_vol);\n\t\n\treturn ! RetVal;\n#endif\n\n#else\t//#indef MIXER_MUTING\n\tfloat TempVol;\n\t\n\tTempVol = MasterVol;\n\tif (TempVol > 0.0f)\n\t\tVolumeBak = TempVol;\n\t\n\tMasterVol = mute ? 0.0f : VolumeBak;\n\tFinalVol = VolumeLevelM * MasterVol * MasterVol;\n\tRefreshVolume();\n\t\n\treturn true;\n#endif\n}\n\n\n\nstatic void InterpretFile(UINT32 SampleCount)\n{\n\tUINT32 TempLng;\n\tUINT8 CurChip;\n\t\n\t//if (Interpreting && SampleCount == 1)\n\t//\treturn;\n\twhile(Interpreting)\n\t\tSleep(1);\n\t\n\tif (DacCtrlUsed && SampleCount > 1)\t// handle skipping\n\t{\n\t\tfor (CurChip = 0x00; CurChip < DacCtrlUsed; CurChip ++)\n\t\t{\n\t\t\tdaccontrol_update(DacCtrlUsg[CurChip], SampleCount - 1);\n\t\t}\n\t}\n\t\n\tInterpreting = true;\n\tif (! FileMode)\n\t\tInterpretVGM(SampleCount);\n#ifdef ADDITIONAL_FORMATS\n\telse\n\t\tInterpretOther(SampleCount);\n#endif\n\t\n\tif (DacCtrlUsed && SampleCount)\n\t{\n\t\t// calling this here makes \"Emulating while Paused\" nicer\n\t\tfor (CurChip = 0x00; CurChip < DacCtrlUsed; CurChip ++)\n\t\t{\n\t\t\tdaccontrol_update(DacCtrlUsg[CurChip], 1);\n\t\t}\n\t}\n\t\n\tif (UseFM && FadePlay)\n\t{\n\t\t//TempLng = PlayingTime % (SampleRate / 5);\n\t\t//if (! TempLng)\n\t\tTempLng = PlayingTime / (SampleRate / 5) -\n\t\t\t\t\t(PlayingTime + SampleCount) / (SampleRate / 5);\n\t\tif (TempLng)\n\t\t\tRefreshVolume();\n\t}\n\tif (AutoStopSkip && SampleCount)\n\t{\n\t\tStopSkipping();\n\t\tAutoStopSkip = false;\n\t\tResetPBTimer = true;\n\t}\n\t\n\tif (! PausePlay || ForceVGMExec)\n\t\tVGMSmplPlayed += SampleCount;\n\tPlayingTime += SampleCount;\n\t\n\t//if (FadePlay && ! FadeTime)\n\t//\tEndPlay = true;\n\t\n\tInterpreting = false;\n\t\n\treturn;\n}\n\nstatic void AddPCMData(UINT8 Type, UINT32 DataSize, const UINT8* Data)\n{\n\tUINT32 CurBnk;\n\tVGM_PCM_BANK* TempPCM;\n\tVGM_PCM_DATA* TempBnk;\n\tUINT32 BankSize;\n\tbool RetVal;\n\tUINT8 BnkType;\n\tUINT8 CurDAC;\n\t\n\tBnkType = Type & 0x3F;\n\tif (BnkType >= PCM_BANK_COUNT || VGMCurLoop)\n\t\treturn;\n\t\n\tif (Type == 0x7F)\n\t{\n\t\tReadPCMTable(DataSize, Data);\n\t\treturn;\n\t}\n\t\n\tTempPCM = &PCMBank[BnkType];\n\tTempPCM->BnkPos ++;\n\tif (TempPCM->BnkPos <= TempPCM->BankCount)\n\t\treturn;\t// Speed hack for restarting playback (skip already loaded blocks)\n\tCurBnk = TempPCM->BankCount;\n\tTempPCM->BankCount ++;\n\tif (Last95Max != 0xFFFF)\n\t\tLast95Max = TempPCM->BankCount;\n\tTempPCM->Bank = (VGM_PCM_DATA*)realloc(TempPCM->Bank,\n\t\t\t\t\t\t\t\t\t\t\tsizeof(VGM_PCM_DATA) * TempPCM->BankCount);\n\t\n\tif (! (Type & 0x40))\n\t\tBankSize = DataSize;\n\telse\n\t\tBankSize = ReadLE32(&Data[0x01]);\n\tTempPCM->Data = realloc(TempPCM->Data, TempPCM->DataSize + BankSize);\n\tTempBnk = &TempPCM->Bank[CurBnk];\n\tTempBnk->DataStart = TempPCM->DataSize;\n\tif (! (Type & 0x40))\n\t{\n\t\tTempBnk->DataSize = DataSize;\n\t\tTempBnk->Data = TempPCM->Data + TempBnk->DataStart;\n\t\tmemcpy(TempBnk->Data, Data, DataSize);\n\t}\n\telse\n\t{\n\t\tTempBnk->Data = TempPCM->Data + TempBnk->DataStart;\n\t\tRetVal = DecompressDataBlk(TempBnk, DataSize, Data);\n\t\tif (! RetVal)\n\t\t{\n\t\t\tTempBnk->Data = NULL;\n\t\t\tTempBnk->DataSize = 0x00;\n\t\t\t//return;\n\t\t\tgoto RefreshDACStrm;\t// sorry for the goto, but I don't want to copy-paste the code\n\t\t}\n\t}\n\tif (BankSize != TempBnk->DataSize)\n\t\tfprintf(stderr, \"Error reading Data Block! Data Size conflict!\\n\");\n\tTempPCM->DataSize += BankSize;\n\t\n\t// realloc may've moved the Bank block, so refresh all DAC Streams\nRefreshDACStrm:\n\tfor (CurDAC = 0x00; CurDAC < DacCtrlUsed; CurDAC ++)\n\t{\n\t\tif (DacCtrl[DacCtrlUsg[CurDAC]].Bank == BnkType)\n\t\t\tdaccontrol_refresh_data(DacCtrlUsg[CurDAC], TempPCM->Data, TempPCM->DataSize);\n\t}\n\t\n\treturn;\n}\n\n/*INLINE FUINT16 ReadBits(UINT8* Data, UINT32* Pos, FUINT8* BitPos, FUINT8 BitsToRead)\n{\n\tFUINT8 BitReadVal;\n\tUINT32 InPos;\n\tFUINT8 InVal;\n\tFUINT8 BitMask;\n\tFUINT8 InShift;\n\tFUINT8 OutBit;\n\tFUINT16 RetVal;\n\t\n\tInPos = *Pos;\n\tInShift = *BitPos;\n\tOutBit = 0x00;\n\tRetVal = 0x0000;\n\twhile(BitsToRead)\n\t{\n\t\tBitReadVal = (BitsToRead >= 8) ? 8 : BitsToRead;\n\t\tBitsToRead -= BitReadVal;\n\t\tBitMask = (1 << BitReadVal) - 1;\n\t\t\n\t\tInShift += BitReadVal;\n\t\tInVal = (Data[InPos] << InShift >> 8) & BitMask;\n\t\tif (InShift >= 8)\n\t\t{\n\t\t\tInShift -= 8;\n\t\t\tInPos ++;\n\t\t\tif (InShift)\n\t\t\t\tInVal |= (Data[InPos] << InShift >> 8) & BitMask;\n\t\t}\n\t\t\n\t\tRetVal |= InVal << OutBit;\n\t\tOutBit += BitReadVal;\n\t}\n\t\n\t*Pos = InPos;\n\t*BitPos = InShift;\n\treturn RetVal;\n}\n\nstatic void DecompressDataBlk(VGM_PCM_DATA* Bank, UINT32 DataSize, const UINT8* Data)\n{\n\tUINT8 ComprType;\n\tUINT8 BitDec;\n\tFUINT8 BitCmp;\n\tUINT8 CmpSubType;\n\tUINT16 AddVal;\n\tUINT32 InPos;\n\tUINT32 OutPos;\n\tFUINT16 InVal;\n\tFUINT16 OutVal;\n\tFUINT8 ValSize;\n\tFUINT8 InShift;\n\tFUINT8 OutShift;\n\tUINT8* Ent1B;\n\tUINT16* Ent2B;\n\t//UINT32 Time;\n\t\n\t//Time = GetTickCount();\n\tComprType = Data[0x00];\n\tBank->DataSize = ReadLE32(&Data[0x01]);\n\tBitDec = Data[0x05];\n\tBitCmp = Data[0x06];\n\tCmpSubType = Data[0x07];\n\tAddVal = ReadLE16(&Data[0x08]);\n\t\n\tswitch(ComprType)\n\t{\n\tcase 0x00:\t// n-Bit compression\n\t\tif (CmpSubType == 0x02)\n\t\t{\n\t\t\tEnt1B = (UINT8*)PCMTbl.Entries;\n\t\t\tEnt2B = (UINT16*)PCMTbl.Entries;\n\t\t\tif (! PCMTbl.EntryCount)\n\t\t\t{\n\t\t\t\tfprintf(stderr, \"Error loading table-compressed data block! No table loaded!\\n\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse if (BitDec != PCMTbl.BitDec || BitCmp != PCMTbl.BitCmp)\n\t\t\t{\n\t\t\t\tfprintf(stderr, \"Warning! Data block and loaded value table incompatible!\\n\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t\n\t\tValSize = (BitDec + 7) / 8;\n\t\tInPos = 0x0A;\n\t\tInShift = 0;\n\t\tOutShift = BitDec - BitCmp;\n\t\t\n\t\tfor (OutPos = 0x00; OutPos < Bank->DataSize; OutPos += ValSize)\n\t\t{\n\t\t\tif (InPos >= DataSize)\n\t\t\t\tbreak;\n\t\t\tInVal = ReadBits(Data, &InPos, &InShift, BitCmp);\n\t\t\tswitch(CmpSubType)\n\t\t\t{\n\t\t\tcase 0x00:\t// Copy\n\t\t\t\tOutVal = InVal + AddVal;\n\t\t\t\tbreak;\n\t\t\tcase 0x01:\t// Shift Left\n\t\t\t\tOutVal = (InVal << OutShift) + AddVal;\n\t\t\t\tbreak;\n\t\t\tcase 0x02:\t// Table\n\t\t\t\tswitch(ValSize)\n\t\t\t\t{\n\t\t\t\tcase 0x01:\n\t\t\t\t\tOutVal = Ent1B[InVal];\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x02:\n\t\t\t\t\tOutVal = Ent2B[InVal];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmemcpy(&Bank->Data[OutPos], &OutVal, ValSize);\n\t\t}\n\t\tbreak;\n\t}\n\t\n\t//Time = GetTickCount() - Time;\n\t//printf(\"Decompression Time: %u\\n\", Time);\n\t\n\treturn;\n}*/\n\nstatic bool DecompressDataBlk(VGM_PCM_DATA* Bank, UINT32 DataSize, const UINT8* Data)\n{\n\tUINT8 ComprType;\n\tUINT8 BitDec;\n\tFUINT8 BitCmp;\n\tUINT8 CmpSubType;\n\tUINT16 AddVal;\n\tconst UINT8* InPos;\n\tconst UINT8* InDataEnd;\n\tUINT8* OutPos;\n\tconst UINT8* OutDataEnd;\n\tFUINT16 InVal;\n\tFUINT16 OutVal;\n\tFUINT8 ValSize;\n\tFUINT8 InShift;\n\tFUINT8 OutShift;\n\tUINT8* Ent1B;\n\tUINT16* Ent2B;\n#if defined(_DEBUG) && defined(WIN32)\n\tUINT32 Time;\n#endif\n\t\n\t// ReadBits Variables\n\tFUINT8 BitsToRead;\n\tFUINT8 BitReadVal;\n\tFUINT8 InValB;\n\tFUINT8 BitMask;\n\tFUINT8 OutBit;\n\t\n\t// Variables for DPCM\n\tUINT16 OutMask;\n\t\n#if defined(_DEBUG) && defined(WIN32)\n\tTime = GetTickCount();\n#endif\n\tComprType = Data[0x00];\n\tBank->DataSize = ReadLE32(&Data[0x01]);\n\t\n\tswitch(ComprType)\n\t{\n\tcase 0x00:\t// n-Bit compression\n\t\tBitDec = Data[0x05];\n\t\tBitCmp = Data[0x06];\n\t\tCmpSubType = Data[0x07];\n\t\tAddVal = ReadLE16(&Data[0x08]);\n\t\tEnt1B = NULL;\n\t\tEnt2B = NULL;\n\t\t\n\t\tif (CmpSubType == 0x02)\n\t\t{\n\t\t\tEnt1B = (UINT8*)PCMTbl.Entries;\t// Big Endian note: Those are stored in LE and converted when reading.\n\t\t\tEnt2B = (UINT16*)PCMTbl.Entries;\n\t\t\tif (! PCMTbl.EntryCount)\n\t\t\t{\n\t\t\t\tBank->DataSize = 0x00;\n\t\t\t\tfprintf(stderr, \"Error loading table-compressed data block! No table loaded!\\n\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse if (BitDec != PCMTbl.BitDec || BitCmp != PCMTbl.BitCmp)\n\t\t\t{\n\t\t\t\tBank->DataSize = 0x00;\n\t\t\t\tfprintf(stderr, \"Warning! Data block and loaded value table incompatible!\\n\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\t\n\t\tValSize = (BitDec + 7) / 8;\n\t\tInPos = Data + 0x0A;\n\t\tInDataEnd = Data + DataSize;\n\t\tInShift = 0;\n\t\tOutShift = BitDec - BitCmp;\n\t\tOutDataEnd = Bank->Data + Bank->DataSize;\n\t\tOutVal = 0x0000;\n\t\t\n\t\tfor (OutPos = Bank->Data; OutPos < OutDataEnd && InPos < InDataEnd; OutPos += ValSize)\n\t\t{\n\t\t\t//InVal = ReadBits(Data, InPos, &InShift, BitCmp);\n\t\t\t// inlined - is 30% faster\n\t\t\tOutBit = 0x00;\n\t\t\tInVal = 0x0000;\n\t\t\tBitsToRead = BitCmp;\n\t\t\twhile(BitsToRead)\n\t\t\t{\n\t\t\t\tBitReadVal = (BitsToRead >= 8) ? 8 : BitsToRead;\n\t\t\t\tBitsToRead -= BitReadVal;\n\t\t\t\tBitMask = (1 << BitReadVal) - 1;\n\t\t\t\t\n\t\t\t\tInShift += BitReadVal;\n\t\t\t\tInValB = (*InPos << InShift >> 8) & BitMask;\n\t\t\t\tif (InShift >= 8)\n\t\t\t\t{\n\t\t\t\t\tInShift -= 8;\n\t\t\t\t\tInPos ++;\n\t\t\t\t\tif (InShift)\n\t\t\t\t\t\tInValB |= (*InPos << InShift >> 8) & BitMask;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tInVal |= InValB << OutBit;\n\t\t\t\tOutBit += BitReadVal;\n\t\t\t}\n\t\t\t\n\t\t\tswitch(CmpSubType)\n\t\t\t{\n\t\t\tcase 0x00:\t// Copy\n\t\t\t\tOutVal = InVal + AddVal;\n\t\t\t\tbreak;\n\t\t\tcase 0x01:\t// Shift Left\n\t\t\t\tOutVal = (InVal << OutShift) + AddVal;\n\t\t\t\tbreak;\n\t\t\tcase 0x02:\t// Table\n\t\t\t\tswitch(ValSize)\n\t\t\t\t{\n\t\t\t\tcase 0x01:\n\t\t\t\t\tOutVal = Ent1B[InVal];\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x02:\n#ifdef VGM_LITTLE_ENDIAN\n\t\t\t\t\tOutVal = Ent2B[InVal];\n#else\n\t\t\t\t\tOutVal = ReadLE16((UINT8*)&Ent2B[InVal]);\n#endif\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n#ifdef VGM_LITTLE_ENDIAN\n\t\t\t//memcpy(OutPos, &OutVal, ValSize);\n\t\t\tif (ValSize == 0x01)\n\t\t\t\t*((UINT8*)OutPos) = (UINT8)OutVal;\n\t\t\telse //if (ValSize == 0x02)\n\t\t\t\t*((UINT16*)OutPos) = (UINT16)OutVal;\n#else\n\t\t\tif (ValSize == 0x01)\n\t\t\t{\n\t\t\t\t*OutPos = (UINT8)OutVal;\n\t\t\t}\n\t\t\telse //if (ValSize == 0x02)\n\t\t\t{\n\t\t\t\tOutPos[0x00] = (UINT8)((OutVal & 0x00FF) >> 0);\n\t\t\t\tOutPos[0x01] = (UINT8)((OutVal & 0xFF00) >> 8);\n\t\t\t}\n#endif\n\t\t}\n\t\tbreak;\n\tcase 0x01:\t// Delta-PCM\n\t\tBitDec = Data[0x05];\n\t\tBitCmp = Data[0x06];\n\t\tOutVal = ReadLE16(&Data[0x08]);\n\t\t\n\t\tEnt1B = (UINT8*)PCMTbl.Entries;\n\t\tEnt2B = (UINT16*)PCMTbl.Entries;\n\t\tif (! PCMTbl.EntryCount)\n\t\t{\n\t\t\tBank->DataSize = 0x00;\n\t\t\tfprintf(stderr, \"Error loading table-compressed data block! No table loaded!\\n\");\n\t\t\treturn false;\n\t\t}\n\t\telse if (BitDec != PCMTbl.BitDec || BitCmp != PCMTbl.BitCmp)\n\t\t{\n\t\t\tBank->DataSize = 0x00;\n\t\t\tfprintf(stderr, \"Warning! Data block and loaded value table incompatible!\\n\");\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\tValSize = (BitDec + 7) / 8;\n\t\tOutMask = (1 << BitDec) - 1;\n\t\tInPos = Data + 0x0A;\n\t\tInDataEnd = Data + DataSize;\n\t\tInShift = 0;\n\t\tOutShift = BitDec - BitCmp;\n\t\tOutDataEnd = Bank->Data + Bank->DataSize;\n\t\tAddVal = 0x0000;\n\t\t\n\t\tfor (OutPos = Bank->Data; OutPos < OutDataEnd && InPos < InDataEnd; OutPos += ValSize)\n\t\t{\n\t\t\t//InVal = ReadBits(Data, InPos, &InShift, BitCmp);\n\t\t\t// inlined - is 30% faster\n\t\t\tOutBit = 0x00;\n\t\t\tInVal = 0x0000;\n\t\t\tBitsToRead = BitCmp;\n\t\t\twhile(BitsToRead)\n\t\t\t{\n\t\t\t\tBitReadVal = (BitsToRead >= 8) ? 8 : BitsToRead;\n\t\t\t\tBitsToRead -= BitReadVal;\n\t\t\t\tBitMask = (1 << BitReadVal) - 1;\n\t\t\t\t\n\t\t\t\tInShift += BitReadVal;\n\t\t\t\tInValB = (*InPos << InShift >> 8) & BitMask;\n\t\t\t\tif (InShift >= 8)\n\t\t\t\t{\n\t\t\t\t\tInShift -= 8;\n\t\t\t\t\tInPos ++;\n\t\t\t\t\tif (InShift)\n\t\t\t\t\t\tInValB |= (*InPos << InShift >> 8) & BitMask;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tInVal |= InValB << OutBit;\n\t\t\t\tOutBit += BitReadVal;\n\t\t\t}\n\t\t\t\n\t\t\tswitch(ValSize)\n\t\t\t{\n\t\t\tcase 0x01:\n\t\t\t\tAddVal = Ent1B[InVal];\n\t\t\t\tOutVal += AddVal;\n\t\t\t\tOutVal &= OutMask;\n\t\t\t\t*((UINT8*)OutPos) = (UINT8)OutVal;\n\t\t\t\tbreak;\n\t\t\tcase 0x02:\n#ifdef VGM_LITTLE_ENDIAN\n\t\t\t\tAddVal = Ent2B[InVal];\n\t\t\t\tOutVal += AddVal;\n\t\t\t\tOutVal &= OutMask;\n\t\t\t\t*((UINT16*)OutPos) = (UINT16)OutVal;\n#else\n\t\t\t\tAddVal = ReadLE16((UINT8*)&Ent2B[InVal]);\n\t\t\t\tOutVal += AddVal;\n\t\t\t\tOutVal &= OutMask;\n\t\t\t\tOutPos[0x00] = (UINT8)((OutVal & 0x00FF) >> 0);\n\t\t\t\tOutPos[0x01] = (UINT8)((OutVal & 0xFF00) >> 8);\n#endif\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tfprintf(stderr, \"Error: Unknown data block compression!\\n\");\n\t\treturn false;\n\t}\n\t\n#if defined(_DEBUG) && defined(WIN32)\n\tTime = GetTickCount() - Time;\n\tfprintf(stderr, \"Decompression Time: %u\\n\", Time);\n#endif\n\t\n\treturn true;\n}\n\nstatic UINT8 GetDACFromPCMBank(void)\n{\n\t// for YM2612 DAC data only\n\t/*VGM_PCM_BANK* TempPCM;\n\tUINT32 CurBnk;*/\n\tUINT32 DataPos;\n\t\n\t/*TempPCM = &PCMBank[0x00];\n\tDataPos = TempPCM->DataPos;\n\tfor (CurBnk = 0x00; CurBnk < TempPCM->BankCount; CurBnk ++)\n\t{\n\t\tif (DataPos < TempPCM->Bank[CurBnk].DataSize)\n\t\t{\n\t\t\tif (TempPCM->DataPos < TempPCM->DataSize)\n\t\t\t\tTempPCM->DataPos ++;\n\t\t\treturn TempPCM->Bank[CurBnk].Data[DataPos];\n\t\t}\n\t\tDataPos -= TempPCM->Bank[CurBnk].DataSize;\n\t}\n\treturn 0x80;*/\n\t\n\tDataPos = PCMBank[0x00].DataPos;\n\tif (DataPos >= PCMBank[0x00].DataSize)\n\t\treturn 0x80;\n\t\n\tPCMBank[0x00].DataPos ++;\n\treturn PCMBank[0x00].Data[DataPos];\n}\n\nstatic UINT8* GetPointerFromPCMBank(UINT8 Type, UINT32 DataPos)\n{\n\tif (Type >= PCM_BANK_COUNT)\n\t\treturn NULL;\n\t\n\tif (DataPos >= PCMBank[Type].DataSize)\n\t\treturn NULL;\n\t\n\treturn &PCMBank[Type].Data[DataPos];\n}\n\nstatic void ReadPCMTable(UINT32 DataSize, const UINT8* Data)\n{\n\tUINT8 ValSize;\n\tUINT32 TblSize;\n\t\n\tPCMTbl.ComprType = Data[0x00];\n\tPCMTbl.CmpSubType = Data[0x01];\n\tPCMTbl.BitDec = Data[0x02];\n\tPCMTbl.BitCmp = Data[0x03];\n\tPCMTbl.EntryCount = ReadLE16(&Data[0x04]);\n\t\n\tValSize = (PCMTbl.BitDec + 7) / 8;\n\tTblSize = PCMTbl.EntryCount * ValSize;\n\t\n\tPCMTbl.Entries = realloc(PCMTbl.Entries, TblSize);\n\tmemcpy(PCMTbl.Entries, &Data[0x06], TblSize);\n\t\n\tif (DataSize < 0x06 + TblSize)\n\t\tfprintf(stderr, \"Warning! Bad PCM Table Length!\\n\");\n\t\n\treturn;\n}\n\n#define CHIP_CHECK(name)\t(ChipAudio[CurChip].name.ChipType != 0xFF)\nstatic void InterpretVGM(UINT32 SampleCount)\n{\n\tINT32 SmplPlayed;\n\tUINT8 Command;\n\tUINT8 TempByt;\n\tUINT16 TempSht;\n\tUINT32 TempLng;\n\tVGM_PCM_BANK* TempPCM;\n\tVGM_PCM_DATA* TempBnk;\n\tUINT32 ROMSize;\n\tUINT32 DataStart;\n\tUINT32 DataLen;\n\tconst UINT8* ROMData;\n\tUINT8 CurChip;\n\tconst UINT8* VGMPnt;\n\t\n\tif (VGMEnd)\n\t\treturn;\n\tif (PausePlay && ! ForceVGMExec)\n\t\treturn;\n\t\n\tSmplPlayed = SamplePbk2VGM_I(VGMSmplPlayed + SampleCount);\n\twhile(VGMSmplPos <= SmplPlayed)\n\t{\n\t\tCommand = VGMData[VGMPos + 0x00];\n\t\tif (Command >= 0x70 && Command <= 0x8F)\n\t\t{\n\t\t\tswitch(Command & 0xF0)\n\t\t\t{\n\t\t\tcase 0x70:\n\t\t\t\tVGMSmplPos += (Command & 0x0F) + 0x01;\n\t\t\t\tbreak;\n\t\t\tcase 0x80:\n\t\t\t\tTempByt = GetDACFromPCMBank();\n\t\t\t\tif (VGMHead.lngHzYM2612)\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x02, 0x00, 0x00, 0x2A, TempByt);\n\t\t\t\t}\n\t\t\t\tVGMSmplPos += (Command & 0x0F);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tVGMPos += 0x01;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tVGMPnt = &VGMData[VGMPos];\n\t\t\t\n\t\t\t// Cheat Mode (to use 2 instances of 1 chip)\n\t\t\tCurChip = 0x00;\n\t\t\tswitch(Command)\n\t\t\t{\n\t\t\tcase 0x30:\n\t\t\t\tif (VGMHead.lngHzPSG & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand += 0x20;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0x3F:\n\t\t\t\tif (VGMHead.lngHzPSG & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand += 0x10;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xA1:\n\t\t\t\tif (VGMHead.lngHzYM2413 & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand -= 0x50;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xA2:\n\t\t\tcase 0xA3:\n\t\t\t\tif (VGMHead.lngHzYM2612 & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand -= 0x50;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xA4:\n\t\t\t\tif (VGMHead.lngHzYM2151 & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand -= 0x50;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xA5:\n\t\t\t\tif (VGMHead.lngHzYM2203 & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand -= 0x50;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xA6:\n\t\t\tcase 0xA7:\n\t\t\t\tif (VGMHead.lngHzYM2608 & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand -= 0x50;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xA8:\n\t\t\tcase 0xA9:\n\t\t\t\tif (VGMHead.lngHzYM2610 & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand -= 0x50;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xAA:\n\t\t\t\tif (VGMHead.lngHzYM3812 & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand -= 0x50;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xAB:\n\t\t\t\tif (VGMHead.lngHzYM3526 & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand -= 0x50;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xAC:\n\t\t\t\tif (VGMHead.lngHzY8950 & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand -= 0x50;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xAE:\n\t\t\tcase 0xAF:\n\t\t\t\tif (VGMHead.lngHzYMF262 & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand -= 0x50;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xAD:\n\t\t\t\tif (VGMHead.lngHzYMZ280B & 0x40000000)\n\t\t\t\t{\n\t\t\t\t\tCommand -= 0x50;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tswitch(Command)\n\t\t\t{\n\t\t\tcase 0x66:\t// End Of File\n\t\t\t\tif (VGMHead.lngLoopOffset)\n\t\t\t\t{\n\t\t\t\t\tVGMPos = VGMHead.lngLoopOffset;\n\t\t\t\t\tVGMSmplPos -= VGMHead.lngLoopSamples;\n\t\t\t\t\tVGMSmplPlayed -= SampleVGM2Pbk_I(VGMHead.lngLoopSamples);\n\t\t\t\t\tSmplPlayed = SamplePbk2VGM_I(VGMSmplPlayed + SampleCount);\n\t\t\t\t\tVGMCurLoop ++;\n\t\t\t\t\t\n\t\t\t\t\tif (VGMMaxLoopM && VGMCurLoop >= VGMMaxLoopM)\n\t\t\t\t\t{\n#ifndef CONSOLE_MODE\n\t\t\t\t\t\tif (! FadePlay)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFadeStart = SampleVGM2Pbk_I(VGMHead.lngTotalSamples +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(VGMCurLoop - 1) * VGMHead.lngLoopSamples);\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\tFadePlay = true;\n\t\t\t\t\t}\n\t\t\t\t\tif (FadePlay && ! FadeTime)\n\t\t\t\t\t\tVGMEnd = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (VGMHead.lngTotalSamples != (UINT32)VGMSmplPos)\n\t\t\t\t\t{\n#ifdef CONSOLE_MODE\n\t\t\t\t\t\tfprintf(stderr, \"Warning! Header Samples: %u\\t Counted Samples: %u\\n\",\n\t\t\t\t\t\t\t\tVGMHead.lngTotalSamples, VGMSmplPos);\n\t\t\t\t\t\tErrorHappened = true;\n#endif\n\t\t\t\t\t\tVGMHead.lngTotalSamples = VGMSmplPos;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (HardStopOldVGMs)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (VGMHead.lngVersion < 0x150 ||\n\t\t\t\t\t\t\t(VGMHead.lngVersion == 0x150 && HardStopOldVGMs == 0x02))\n\t\t\t\t\t\tChips_GeneralActions(0x01); // reset all chips, for instant silence\n\t\t\t\t\t}\n\t\t\t\t\tVGMEnd = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0x62:\t// 1/60s delay\n\t\t\t\tVGMSmplPos += 735;\n\t\t\t\tVGMPos += 0x01;\n\t\t\t\tbreak;\n\t\t\tcase 0x63:\t// 1/50s delay\n\t\t\t\tVGMSmplPos += 882;\n\t\t\t\tVGMPos += 0x01;\n\t\t\t\tbreak;\n\t\t\tcase 0x61:\t// xx Sample Delay\n\t\t\t\tTempSht = ReadLE16(&VGMPnt[0x01]);\n\t\t\t\tVGMSmplPos += TempSht;\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0x50:\t// SN76496 write\n\t\t\t\tif (CHIP_CHECK(SN76496))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x00, CurChip, 0x00, 0x00, VGMPnt[0x01]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x02;\n\t\t\t\tbreak;\n\t\t\tcase 0x51:\t// YM2413 write\n\t\t\t\tif (CHIP_CHECK(YM2413))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x01, CurChip, 0x00, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0x52:\t// YM2612 write port 0\n\t\t\tcase 0x53:\t// YM2612 write port 1\n\t\t\t\tif (CHIP_CHECK(YM2612))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x02, CurChip, Command & 0x01, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0x67:\t// PCM Data Stream\n\t\t\t\tTempByt = VGMPnt[0x02];\n\t\t\t\tTempLng = ReadLE32(&VGMPnt[0x03]);\n\t\t\t\tif (TempLng & 0x80000000)\n\t\t\t\t{\n\t\t\t\t\tTempLng &= 0x7FFFFFFF;\n\t\t\t\t\tCurChip = 0x01;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tswitch(TempByt & 0xC0)\n\t\t\t\t{\n\t\t\t\tcase 0x00:\t// Database Block\n\t\t\t\tcase 0x40:\n\t\t\t\t\tAddPCMData(TempByt, TempLng, &VGMPnt[0x07]);\n\t\t\t\t\t/*switch(TempByt)\n\t\t\t\t\t{\n\t\t\t\t\tcase 0x00:\t// YM2612 PCM Database\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x01:\t// RF5C68 PCM Database\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x02:\t// RF5C164 PCM Database\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}*/\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x80:\t// ROM/RAM Dump\n\t\t\t\t\tif (VGMCurLoop)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tROMSize = ReadLE32(&VGMPnt[0x07]);\n\t\t\t\t\tDataStart = ReadLE32(&VGMPnt[0x0B]);\n\t\t\t\t\tDataLen = TempLng - 0x08;\n\t\t\t\t\tROMData = &VGMPnt[0x0F];\n\t\t\t\t\tswitch(TempByt)\n\t\t\t\t\t{\n\t\t\t\t\tcase 0x80:\t// SegaPCM ROM\n\t\t\t\t\t\tif (! CHIP_CHECK(SegaPCM))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tsega_pcm_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x81:\t// YM2608 DELTA-T ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(YM2608))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tym2608_write_data_pcmrom(CurChip, 0x02, ROMSize, DataStart, DataLen,\n\t\t\t\t\t\t\t\t\t\t\t\tROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x82:\t// YM2610 ADPCM ROM Image\n\t\t\t\t\tcase 0x83:\t// YM2610 DELTA-T ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(YM2610))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tTempByt = 0x01 + (TempByt - 0x82);\n\t\t\t\t\t\tym2610_write_data_pcmrom(CurChip, TempByt, ROMSize, DataStart, DataLen,\n\t\t\t\t\t\t\t\t\t\t\t\tROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x84:\t// YMF278B ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(YMF278B))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tymf278b_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x85:\t// YMF271 ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(YMF271))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tymf271_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x86:\t// YMZ280B ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(YMZ280B))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tymz280b_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x87:\t// YMF278B RAM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(YMF278B))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tymf278b_write_ram(CurChip, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x88:\t// Y8950 DELTA-T ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(Y8950) || PlayingMode == 0x01)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\ty8950_write_data_pcmrom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x89:\t// MultiPCM ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(MultiPCM))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tmultipcm_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x8A:\t// UPD7759 ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(UPD7759))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tupd7759_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x8B:\t// OKIM6295 ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(OKIM6295))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tokim6295_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x8C:\t// K054539 ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(K054539))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tk054539_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x8D:\t// C140 ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(C140))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tc140_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x8E:\t// K053260 ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(K053260))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tk053260_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x8F:\t// QSound ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(QSound))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tqsound_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x90:\t// ES5506 ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(ES5506))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tes5506_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x91:\t// X1-010 ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(X1_010))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tx1_010_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x92:\t// C352 ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(C352))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tc352_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x93:\t// GA20 ROM Image\n\t\t\t\t\t\tif (! CHIP_CHECK(GA20))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tiremga20_write_rom(CurChip, ROMSize, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t//\tcase 0x8C:\t// OKIM6376 ROM Image\n\t\t\t\t//\t\tif (! CHIP_CHECK(OKIM6376))\n\t\t\t\t//\t\t\tbreak;\n\t\t\t\t//\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0xC0:\t// RAM Write\n\t\t\t\t\tif (! (TempByt & 0x20))\n\t\t\t\t\t{\n\t\t\t\t\t\tDataStart = ReadLE16(&VGMPnt[0x07]);\n\t\t\t\t\t\tDataLen = TempLng - 0x02;\n\t\t\t\t\t\tROMData = &VGMPnt[0x09];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tDataStart = ReadLE32(&VGMPnt[0x07]);\n\t\t\t\t\t\tDataLen = TempLng - 0x04;\n\t\t\t\t\t\tROMData = &VGMPnt[0x0B];\n\t\t\t\t\t}\n\t\t\t\t\tswitch(TempByt)\n\t\t\t\t\t{\n\t\t\t\t\tcase 0xC0:\t// RF5C68 RAM Database\n\t\t\t\t\t\tif (! CHIP_CHECK(RF5C68))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\trf5c68_write_ram(CurChip, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0xC1:\t// RF5C164 RAM Database\n\t\t\t\t\t\tif (! CHIP_CHECK(RF5C164))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\trf5c164_write_ram(CurChip, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0xC2:\t// NES APU RAM\n\t\t\t\t\t\tif (! CHIP_CHECK(NES))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tnes_write_ram(CurChip, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0xE0:\t// SCSP RAM\n\t\t\t\t\t\tif (! CHIP_CHECK(SCSP))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tscsp_write_ram(CurChip, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0xE1:\t// ES5503 RAM\n\t\t\t\t\t\tif (! CHIP_CHECK(ES5503))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tes5503_write_ram(CurChip, DataStart, DataLen, ROMData);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x07 + TempLng;\n\t\t\t\tbreak;\n\t\t\tcase 0xE0:\t// Seek to PCM Data Bank Pos\n\t\t\t\tPCMBank[0x00].DataPos = ReadLE32(&VGMPnt[0x01]);\n\t\t\t\tVGMPos += 0x05;\n\t\t\t\tbreak;\n\t\t\tcase 0x31:\t// Set AY8910 stereo mask\n\t\t\t\tTempByt = VGMPnt[0x01];\n\t\t\t\tTempLng = TempByt & 0x3F;\n\t\t\t\tCurChip = (TempByt & 0x80)? 1: 0;\n\t\t\t\tif (TempByt & 0x40)\n\t\t\t\t\tym2203_set_stereo_mask_ay(CurChip, TempLng);\n\t\t\t\telse\n\t\t\t\t\tayxx_set_stereo_mask(CurChip, TempLng);\n\t\t\t\tVGMPos += 0x02;\n\t\t\t\tbreak;\n\t\t\tcase 0x4F:\t// GG Stereo\n\t\t\t\tif (CHIP_CHECK(SN76496))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x00, CurChip, 0x01, 0x00, VGMPnt[0x01]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x02;\n\t\t\t\tbreak;\n\t\t\tcase 0x54:\t// YM2151 write\n\t\t\t\tif (CHIP_CHECK(YM2151))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x03, CurChip, 0x01, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\t//VGMSmplPos += 80;\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xC0:\t// Sega PCM memory write\n\t\t\t\tTempSht = ReadLE16(&VGMPnt[0x01]);\n\t\t\t\tCurChip = (TempSht & 0x8000) >> 15;\n\t\t\t\tif (CHIP_CHECK(SegaPCM))\n\t\t\t\t{\n\t\t\t\t\tsega_pcm_w(CurChip, TempSht & 0x7FFF, VGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xB0:\t// RF5C68 register write\n\t\t\t\tif (CHIP_CHECK(RF5C68))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x05, CurChip, 0x00, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xC1:\t// RF5C164 memory write\n\t\t\t\tif (CHIP_CHECK(RF5C68))\n\t\t\t\t{\n\t\t\t\t\tTempSht = ReadLE16(&VGMPnt[0x01]);\n\t\t\t\t\trf5c68_mem_w(CurChip, TempSht, VGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0x55:\t// YM2203\n\t\t\t\tif (CHIP_CHECK(YM2203))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x06, CurChip, 0x00, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0x56:\t// YM2608 write port 0\n\t\t\tcase 0x57:\t// YM2608 write port 1\n\t\t\t\tif (CHIP_CHECK(YM2608))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x07, CurChip, Command & 0x01, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0x58:\t// YM2610 write port 0\n\t\t\tcase 0x59:\t// YM2610 write port 1\n\t\t\t\tif (CHIP_CHECK(YM2610))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x08, CurChip, Command & 0x01, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0x5A:\t// YM3812 write\n\t\t\t\tif (CHIP_CHECK(YM3812))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0x5B:\t// YM3526 write\n\t\t\t\tif (CHIP_CHECK(YM3526))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x0A, CurChip, 0x00, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0x5C:\t// Y8950 write\n\t\t\t\tif (CHIP_CHECK(Y8950))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x0B, CurChip, 0x00, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0x5E:\t// YMF262 write port 0\n\t\t\tcase 0x5F:\t// YMF262 write port 1\n\t\t\t\tif (CHIP_CHECK(YMF262))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x0C, CurChip, Command & 0x01, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0x5D:\t// YMZ280B write\n\t\t\t\tif (CHIP_CHECK(YMZ280B))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x0F, CurChip, 0x00, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xD0:\t// YMF278B write\n\t\t\t\tif (CHIP_CHECK(YMF278B))\n\t\t\t\t{\n\t\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\t\tchip_reg_write(0x0D, CurChip, VGMPnt[0x01] & 0x7F, VGMPnt[0x02], VGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xD1:\t// YMF271 write\n\t\t\t\tif (CHIP_CHECK(YMF271))\n\t\t\t\t{\n\t\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\t\tchip_reg_write(0x0E, CurChip, VGMPnt[0x01] & 0x7F, VGMPnt[0x02], VGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xB1:\t// RF5C164 register write\n\t\t\t\tif (CHIP_CHECK(RF5C164))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x10, CurChip, 0x00, VGMPnt[0x01], VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xC2:\t// RF5C164 memory write\n\t\t\t\tif (CHIP_CHECK(RF5C164))\n\t\t\t\t{\n\t\t\t\t\tTempSht = ReadLE16(&VGMPnt[0x01]);\n\t\t\t\t\trf5c164_mem_w(CurChip, TempSht, VGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xB2:\t// PWM channel write\n\t\t\t\tif (CHIP_CHECK(PWM))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x11, CurChip, (VGMPnt[0x01] & 0xF0) >> 4,\n\t\t\t\t\t\t\t\t\tVGMPnt[0x01] & 0x0F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0x68:\t// PCM RAM write\n\t\t\t\tCurChip = (VGMPnt[0x02] & 0x80) >> 7;\n\t\t\t\tTempByt =  VGMPnt[0x02] & 0x7F;\n\t\t\t\t\n\t\t\t\tDataStart = ReadLE24(&VGMPnt[0x03]);\n\t\t\t\tTempLng = ReadLE24(&VGMPnt[0x06]);\n\t\t\t\tDataLen = ReadLE24(&VGMPnt[0x09]);\n\t\t\t\tif (! DataLen)\n\t\t\t\t\tDataLen += 0x01000000;\n\t\t\t\tROMData = GetPointerFromPCMBank(TempByt, DataStart);\n\t\t\t\tif (ROMData == NULL)\n\t\t\t\t{\n\t\t\t\t\tVGMPos += 0x0C;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tswitch(TempByt)\n\t\t\t\t{\n\t\t\t\tcase 0x01:\n\t\t\t\t\tif (! CHIP_CHECK(RF5C68))\n\t\t\t\t\t\tbreak;\n\t\t\t\t\trf5c68_write_ram(CurChip, TempLng, DataLen, ROMData);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x02:\n\t\t\t\t\tif (! CHIP_CHECK(RF5C164))\n\t\t\t\t\t\tbreak;\n\t\t\t\t\trf5c164_write_ram(CurChip, TempLng, DataLen, ROMData);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x06:\n\t\t\t\t\tif (! CHIP_CHECK(SCSP))\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tscsp_write_ram(CurChip, TempLng, DataLen, ROMData);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x07:\n\t\t\t\t\tif (! CHIP_CHECK(NES))\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tLast95Drum = DataStart / DataLen - 1;\n\t\t\t\t\tLast95Max = PCMBank[TempByt].DataSize / DataLen;\n\t\t\t\t\tnes_write_ram(CurChip, TempLng, DataLen, ROMData);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x0C;\n\t\t\t\tbreak;\n\t\t\tcase 0xA0:\t// AY8910 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(AY8910))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x12, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xB3:\t// GameBoy DMG write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(GameBoy))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x13, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xB4:\t// NES APU write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(NES))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x14, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xB5:\t// MultiPCM write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(MultiPCM))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x15, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xC3:\t// MultiPCM memory write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(MultiPCM))\n\t\t\t\t{\n\t\t\t\t\tTempSht = ReadLE16(&VGMPnt[0x02]);\n\t\t\t\t\tmultipcm_bank_write(CurChip, VGMPnt[0x01] & 0x7F, TempSht);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xB6:\t// UPD7759 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(UPD7759))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x16, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xB7:\t// OKIM6258 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(OKIM6258))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x17, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xB8:\t// OKIM6295 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(OKIM6295))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x18, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xD2:\t// SCC1 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(K051649))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x19, CurChip, VGMPnt[0x01] & 0x7F, VGMPnt[0x02],\n\t\t\t\t\t\t\t\t\tVGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xD3:\t// K054539 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(K054539))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x1A, CurChip, VGMPnt[0x01] & 0x7F, VGMPnt[0x02],\n\t\t\t\t\t\t\t\t\tVGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xB9:\t// HuC6280 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(HuC6280))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x1B, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xD4:\t// C140 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(C140))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x1C, CurChip, VGMPnt[0x01] & 0x7F, VGMPnt[0x02],\n\t\t\t\t\t\t\t\t\tVGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xBA:\t// K053260 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(K053260))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x1D, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xBB:\t// Pokey write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(Pokey))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x1E, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xC4:\t// QSound write\n\t\t\t\tif (CHIP_CHECK(QSound))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x1F, CurChip, VGMPnt[0x01], VGMPnt[0x02], VGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xC5:\t// YMF292/SCSP write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(SCSP))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x20, CurChip, VGMPnt[0x01] & 0x7F, VGMPnt[0x02],\n\t\t\t\t\t\t\t\t\tVGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xBC:\t// WonderSwan write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(WSwan))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x21, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xC6:\t// WonderSwan memory write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(WSwan))\n\t\t\t\t{\n\t\t\t\t\tTempSht = ReadBE16(&VGMPnt[0x01]) & 0x7FFF;\n\t\t\t\t\tws_write_ram(CurChip, TempSht, VGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xC7:\t// VSU write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(VSU))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x22, CurChip, VGMPnt[0x01] & 0x7F, VGMPnt[0x02],\n\t\t\t\t\t\t\t\t\tVGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xBD:\t// SAA1099 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(SAA1099))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x23, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xD5:\t// ES5503 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(ES5503))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x24, CurChip, VGMPnt[0x01] & 0x7F, VGMPnt[0x02],\n\t\t\t\t\t\t\t\t\tVGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xBE:\t// ES5506 write (8-bit data)\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(ES5506))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x25, CurChip, VGMPnt[0x01] & 0x7F, 0x00, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0xD6:\t// ES5506 write (16-bit data)\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(ES5506))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x25, CurChip, 0x80 | (VGMPnt[0x01] & 0x7F),\n\t\t\t\t\t\t\t\t\tVGMPnt[0x02], VGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n\t\t\tcase 0xC8:\t// X1-010 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(X1_010))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x26, CurChip, VGMPnt[0x01] & 0x7F, VGMPnt[0x02],\n\t\t\t\t\t\t\t\t\tVGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n#if 0\t// for ctr's WIP rips\n\t\t\tcase 0xC9:\t// C352 write\n\t\t\t\tCurChip = 0x00;\n\t\t\t\tif (CHIP_CHECK(C352))\n\t\t\t\t{\n\t\t\t\t\tif (VGMPnt[0x01] == 0x03 && VGMPnt[0x02] == 0xFF && VGMPnt[0x03] == 0xFF)\n\t\t\t\t\t\tc352_w(CurChip, 0x202, 0x0020);\n\t\t\t\t\telse\n\t\t\t\t\t\tchip_reg_write(0x27, CurChip, VGMPnt[0x01], VGMPnt[0x02],\n\t\t\t\t\t\t\t\t\t\tVGMPnt[0x03]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x04;\n\t\t\t\tbreak;\n#endif\n\t\t\tcase 0xE1:\t// C352 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(C352))\n\t\t\t\t{\n\t\t\t\t\tTempSht = ((VGMPnt[0x01] & 0x7F) << 8) | (VGMPnt[0x02] << 0);\n\t\t\t\t\tc352_w(CurChip, TempSht, (VGMPnt[0x03] << 8) | VGMPnt[0x04]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x05;\n\t\t\t\tbreak;\n\t\t\tcase 0xBF:\t// GA20 write\n\t\t\t\tCurChip = (VGMPnt[0x01] & 0x80) >> 7;\n\t\t\t\tif (CHIP_CHECK(GA20))\n\t\t\t\t{\n\t\t\t\t\tchip_reg_write(0x28, CurChip, 0x00, VGMPnt[0x01] & 0x7F, VGMPnt[0x02]);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x03;\n\t\t\t\tbreak;\n\t\t\tcase 0x90:\t// DAC Ctrl: Setup Chip\n\t\t\t\tCurChip = VGMPnt[0x01];\n\t\t\t\tif (CurChip == 0xFF)\n\t\t\t\t{\n\t\t\t\t\tVGMPos += 0x05;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (! DacCtrl[CurChip].Enable)\n\t\t\t\t{\n\t\t\t\t\tdevice_start_daccontrol(CurChip);\n\t\t\t\t\tdevice_reset_daccontrol(CurChip);\n\t\t\t\t\tDacCtrl[CurChip].Enable = true;\n\t\t\t\t\tDacCtrlUsg[DacCtrlUsed] = CurChip;\n\t\t\t\t\tDacCtrlUsed ++;\n\t\t\t\t}\n\t\t\t\tTempByt = VGMPnt[0x02];\t// Chip Type\n\t\t\t\tTempSht = ReadBE16(&VGMPnt[0x03]);\n\t\t\t\tdaccontrol_setup_chip(CurChip, TempByt & 0x7F, (TempByt & 0x80) >> 7, TempSht);\n\t\t\t\tVGMPos += 0x05;\n\t\t\t\tbreak;\n\t\t\tcase 0x91:\t// DAC Ctrl: Set Data\n\t\t\t\tCurChip = VGMPnt[0x01];\n\t\t\t\tif (CurChip == 0xFF || ! DacCtrl[CurChip].Enable)\n\t\t\t\t{\n\t\t\t\t\tVGMPos += 0x05;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tDacCtrl[CurChip].Bank = VGMPnt[0x02];\n\t\t\t\tif (DacCtrl[CurChip].Bank >= PCM_BANK_COUNT)\n\t\t\t\t\tDacCtrl[CurChip].Bank = 0x00;\n\t\t\t\t\n\t\t\t\tTempPCM = &PCMBank[DacCtrl[CurChip].Bank];\n\t\t\t\tLast95Max = TempPCM->BankCount;\n\t\t\t\tdaccontrol_set_data(CurChip, TempPCM->Data, TempPCM->DataSize,\n\t\t\t\t\t\t\t\t\tVGMPnt[0x03], VGMPnt[0x04]);\n\t\t\t\tVGMPos += 0x05;\n\t\t\t\tbreak;\n\t\t\tcase 0x92:\t// DAC Ctrl: Set Freq\n\t\t\t\tCurChip = VGMPnt[0x01];\n\t\t\t\tif (CurChip == 0xFF || ! DacCtrl[CurChip].Enable)\n\t\t\t\t{\n\t\t\t\t\tVGMPos += 0x06;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tTempLng = ReadLE32(&VGMPnt[0x02]);\n\t\t\t\tLast95Freq = TempLng;\n\t\t\t\tdaccontrol_set_frequency(CurChip, TempLng);\n\t\t\t\tVGMPos += 0x06;\n\t\t\t\tbreak;\n\t\t\tcase 0x93:\t// DAC Ctrl: Play from Start Pos\n\t\t\t\tCurChip = VGMPnt[0x01];\n\t\t\t\tif (CurChip == 0xFF || ! DacCtrl[CurChip].Enable ||\n\t\t\t\t\t! PCMBank[DacCtrl[CurChip].Bank].BankCount)\n\t\t\t\t{\n\t\t\t\t\tVGMPos += 0x0B;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tDataStart = ReadLE32(&VGMPnt[0x02]);\n\t\t\t\tLast95Drum = 0xFFFF;\n\t\t\t\tTempByt = VGMPnt[0x06];\n\t\t\t\tDataLen = ReadLE32(&VGMPnt[0x07]);\n\t\t\t\tdaccontrol_start(CurChip, DataStart, TempByt, DataLen);\n\t\t\t\tVGMPos += 0x0B;\n\t\t\t\tbreak;\n\t\t\tcase 0x94:\t// DAC Ctrl: Stop immediately\n\t\t\t\tCurChip = VGMPnt[0x01];\n\t\t\t\tif (! DacCtrl[CurChip].Enable)\n\t\t\t\t{\n\t\t\t\t\tVGMPos += 0x02;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tLast95Drum = 0xFFFF;\n\t\t\t\tif (CurChip < 0xFF)\n\t\t\t\t{\n\t\t\t\t\tdaccontrol_stop(CurChip);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfor (CurChip = 0x00; CurChip < 0xFF; CurChip ++)\n\t\t\t\t\t\tdaccontrol_stop(CurChip);\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x02;\n\t\t\t\tbreak;\n\t\t\tcase 0x95:\t// DAC Ctrl: Play Block (small)\n\t\t\t\tCurChip = VGMPnt[0x01];\n\t\t\t\tif (CurChip == 0xFF || ! DacCtrl[CurChip].Enable ||\n\t\t\t\t\t! PCMBank[DacCtrl[CurChip].Bank].BankCount)\n\t\t\t\t{\n\t\t\t\t\tVGMPos += 0x05;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tTempPCM = &PCMBank[DacCtrl[CurChip].Bank];\n\t\t\t\tTempSht = ReadLE16(&VGMPnt[0x02]);\n\t\t\t\tLast95Drum = TempSht;\n\t\t\t\tLast95Max = TempPCM->BankCount;\n\t\t\t\tif (TempSht >= TempPCM->BankCount)\n\t\t\t\t\tTempSht = 0x00;\n\t\t\t\tTempBnk = &TempPCM->Bank[TempSht];\n\t\t\t\t\n\t\t\t\tTempByt = DCTRL_LMODE_BYTES |\n\t\t\t\t\t\t\t(VGMPnt[0x04] & 0x10) |\t\t\t// Reverse Mode\n\t\t\t\t\t\t\t((VGMPnt[0x04] & 0x01) << 7);\t// Looping\n\t\t\t\tdaccontrol_start(CurChip, TempBnk->DataStart, TempByt, TempBnk->DataSize);\n\t\t\t\tVGMPos += 0x05;\n\t\t\t\tbreak;\n\t\t\tdefault:\n#ifdef CONSOLE_MODE\n\t\t\t\tif (! CmdList[Command])\n\t\t\t\t{\n\t\t\t\t\tfprintf(stderr, \"Unknown command: %02hhX\\n\", Command);\n\t\t\t\t\tCmdList[Command] = true;\n\t\t\t\t}\n#endif\n\t\t\t\t\n\t\t\t\tswitch(Command & 0xF0)\n\t\t\t\t{\n\t\t\t\tcase 0x00:\n\t\t\t\tcase 0x10:\n\t\t\t\tcase 0x20:\n\t\t\t\t\tVGMPos += 0x01;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x30:\n\t\t\t\t\tVGMPos += 0x02;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x40:\n\t\t\t\tcase 0x50:\n\t\t\t\tcase 0xA0:\n\t\t\t\tcase 0xB0:\n\t\t\t\t\tVGMPos += 0x03;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0xC0:\n\t\t\t\tcase 0xD0:\n\t\t\t\t\tVGMPos += 0x04;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0xE0:\n\t\t\t\tcase 0xF0:\n\t\t\t\t\tVGMPos += 0x05;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tVGMEnd = true;\n\t\t\t\t\tEndPlay = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (VGMPos >= VGMHead.lngEOFOffset)\n\t\t\tVGMEnd = true;\n\t\t\n\t\tif (VGMEnd)\n\t\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\n\nstatic void GeneralChipLists(void)\n{\n\t// Generate Chip List for playback loop\n\tUINT16 CurBufIdx;\n\tCA_LIST* CLstOld;\n\tCA_LIST* CLst;\n\tCA_LIST* CurLst;\n\tUINT8 CurChip;\n\tUINT8 CurCSet;\n\tCAUD_ATTR* CAA;\n\t\n\tChipListAll = NULL;\n\tChipListPause = NULL;\n\t//ChipListOpt = NULL;\n\t\n\t// generate list of all chips that are used in the current VGM\n\tCurBufIdx = 0x00;\n\tCLstOld = NULL;\n\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++)\n\t{\n\t\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t\t{\n\t\t\tCAA = (CAUD_ATTR*)&ChipAudio[CurCSet] + CurChip;\n\t\t\tif (CAA->ChipType != 0xFF)\n\t\t\t{\n\t\t\t\tCLst = &ChipListBuffer[CurBufIdx];\n\t\t\t\tCurBufIdx ++;\n\t\t\t\tif (CLstOld == NULL)\n\t\t\t\t\tChipListAll = CLst;\n\t\t\t\telse\n\t\t\t\t\tCLstOld->next = CLst;\n\t\t\t\t\n\t\t\t\tCLst->CAud = CAA;\n\t\t\t\tCLst->COpts = (CHIP_OPTS*)&ChipOpts[CurCSet] + CurChip;\n\t\t\t\tCLstOld = CLst;\n\t\t\t}\n\t\t}\n\t}\n\tif (CLstOld != NULL)\n\t\tCLstOld->next = NULL;\n\t\n\t// Go through the chip list and copy all chips to a new list, except for a few\n\t// selected ones.\n\tCLstOld = NULL;\n\tCurLst = ChipListAll;\n\twhile(CurLst != NULL)\n\t{\n\t\t// don't emulate the RF5Cxx chips when paused+emulated\n\t\tif (CurLst->CAud->ChipType != 0x05 && CurLst->CAud->ChipType != 0x10)\n\t\t{\n\t\t\tCLst = &ChipListBuffer[CurBufIdx];\n\t\t\tCurBufIdx ++;\n\t\t\tif (CLstOld == NULL)\n\t\t\t\tChipListPause = CLst;\n\t\t\telse\n\t\t\t\tCLstOld->next = CLst;\n\t\t\t\n\t\t\t*CLst = *CurLst;\n\t\t\tCLstOld = CLst;\n\t\t}\n\t\tCurLst = CurLst->next;\n\t}\n\tif (CLstOld != NULL)\n\t\tCLstOld->next = NULL;\n\t\n\treturn;\n}\n\nstatic void SetupResampler(CAUD_ATTR* CAA)\n{\n\tif (! CAA->SmpRate)\n\t{\n\t\tCAA->Resampler = 0xFF;\n\t\treturn;\n\t}\n\t\n\tif (CAA->SmpRate < SampleRate)\n\t\tCAA->Resampler = 0x01;\n\telse if (CAA->SmpRate == SampleRate)\n\t\tCAA->Resampler = 0x02;\n\telse if (CAA->SmpRate > SampleRate)\n\t\tCAA->Resampler = 0x03;\n\tif (CAA->Resampler == 0x01 || CAA->Resampler == 0x03)\n\t{\n\t\tif (ResampleMode == 0x02 || (ResampleMode == 0x01 && CAA->Resampler == 0x03))\n\t\t\tCAA->Resampler = 0x00;\n\t}\n\t\n\tCAA->SmpP = 0x00;\n\tCAA->SmpLast = 0x00;\n\tCAA->SmpNext = 0x00;\n\tCAA->LSmpl.Left = 0x00;\n\tCAA->LSmpl.Right = 0x00;\n\tif (CAA->Resampler == 0x01)\n\t{\n\t\t// Pregenerate first Sample (the upsampler is always one too late)\n\t\tCAA->StreamUpdate(CAA->ChipID, StreamBufs, 1);\n\t\tCAA->NSmpl.Left = StreamBufs[0x00][0x00];\n\t\tCAA->NSmpl.Right = StreamBufs[0x01][0x00];\n\t}\n\telse\n\t{\n\t\tCAA->NSmpl.Left = 0x00;\n\t\tCAA->NSmpl.Right = 0x00;\n\t}\n\t\n\treturn;\n}\n\nstatic void ChangeChipSampleRate(void* DataPtr, UINT32 NewSmplRate)\n{\n\tCAUD_ATTR* CAA = (CAUD_ATTR*)DataPtr;\n\t\n\tif (CAA->SmpRate == NewSmplRate)\n\t\treturn;\n\t\n\t// quick and dirty hack to make sample rate changes work\n\tCAA->SmpRate = NewSmplRate;\n\tif (CAA->SmpRate < SampleRate)\n\t\tCAA->Resampler = 0x01;\n\telse if (CAA->SmpRate == SampleRate)\n\t\tCAA->Resampler = 0x02;\n\telse if (CAA->SmpRate > SampleRate)\n\t\tCAA->Resampler = 0x03;\n\tCAA->SmpP = 1;\n\tCAA->SmpNext -= CAA->SmpLast;\n\tCAA->SmpLast = 0x00;\n\t\n\treturn;\n}\n\n\nINLINE INT16 Limit2Short(INT32 Value)\n{\n\tINT32 NewValue;\n\t\n\tNewValue = Value;\n\tif (NewValue < -0x8000)\n\t\tNewValue = -0x8000;\n\tif (NewValue > 0x7FFF)\n\t\tNewValue = 0x7FFF;\n\t\n\treturn (INT16)NewValue;\n}\n\nstatic void null_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tmemset(outputs[0x00], 0x00, sizeof(stream_sample_t) * samples);\n\tmemset(outputs[0x01], 0x00, sizeof(stream_sample_t) * samples);\n\t\n\treturn;\n}\n\nstatic void dual_opl2_stereo(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tym3812_stream_update(ChipID, outputs, samples);\n\t\n\t// Dual-OPL with Stereo\n\tif (ChipID & 0x01)\n\t\tmemset(outputs[0x00], 0x00, sizeof(stream_sample_t) * samples);\t// Mute Left Chanel\n\telse\n\t\tmemset(outputs[0x01], 0x00, sizeof(stream_sample_t) * samples);\t// Mute Right Chanel\n\t\n\treturn;\n}\n\n// I recommend 11 bits as it's fast and accurate\n#define FIXPNT_BITS\t\t11\n#define FIXPNT_FACT\t\t(1 << FIXPNT_BITS)\n#if (FIXPNT_BITS <= 11)\n\ttypedef UINT32\tSLINT;\t// 32-bit is a lot faster\n#else\n\ttypedef UINT64\tSLINT;\n#endif\n#define FIXPNT_MASK\t\t(FIXPNT_FACT - 1)\n\n#define getfriction(x)\t((x) & FIXPNT_MASK)\n#define getnfriction(x)\t((FIXPNT_FACT - (x)) & FIXPNT_MASK)\n#define fpi_floor(x)\t((x) & ~FIXPNT_MASK)\n#define fpi_ceil(x)\t\t((x + FIXPNT_MASK) & ~FIXPNT_MASK)\n#define fp2i_floor(x)\t((x) / FIXPNT_FACT)\n#define fp2i_ceil(x)\t((x + FIXPNT_MASK) / FIXPNT_FACT)\n\nstatic void ResampleChipStream(CA_LIST* CLst, WAVE_32BS* RetSample, UINT32 Length)\n{\n\tCAUD_ATTR* CAA;\n\tINT32* CurBufL;\n\tINT32* CurBufR;\n\tINT32* StreamPnt[0x02];\n\tUINT32 InBase;\n\tUINT32 InPos;\n\tUINT32 InPosNext;\n\tUINT32 OutPos;\n\tUINT32 SmpFrc;\t// Sample Friction\n\tUINT32 InPre;\n\tUINT32 InNow;\n\tSLINT InPosL;\n\tINT64 TempSmpL;\n\tINT64 TempSmpR;\n\tINT32 TempS32L;\n\tINT32 TempS32R;\n\tINT32 SmpCnt;\t// must be signed, else I'm getting calculation errors\n\tINT32 CurSmpl;\n\tUINT64 ChipSmpRate;\n\t\n\tCAA = CLst->CAud;\n\tCurBufL = StreamBufs[0x00];\n\tCurBufR = StreamBufs[0x01];\n\t\n\t// This Do-While-Loop gets and resamples the chip output of one or more chips.\n\t// It's a loop to support the AY8910 paired with the YM2203/YM2608/YM2610.\n\tdo\n\t{\n\t\tswitch(CAA->Resampler)\n\t\t{\n\t\tcase 0x00:\t// old, but very fast resampler\n\t\t\tCAA->SmpLast = CAA->SmpNext;\n\t\t\tCAA->SmpP += Length;\n\t\t\tCAA->SmpNext = (UINT32)((UINT64)CAA->SmpP * CAA->SmpRate / SampleRate);\n\t\t\tif (CAA->SmpLast >= CAA->SmpNext)\n\t\t\t{\n\t\t\t\tRetSample->Left += CAA->LSmpl.Left * CAA->Volume;\n\t\t\t\tRetSample->Right += CAA->LSmpl.Right * CAA->Volume;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tSmpCnt = CAA->SmpNext - CAA->SmpLast;\n\t\t\t\t\n\t\t\t\tCAA->StreamUpdate(CAA->ChipID, StreamBufs, SmpCnt);\n\t\t\t\t\n\t\t\t\tif (SmpCnt == 1)\n\t\t\t\t{\n\t\t\t\t\tRetSample->Left += CurBufL[0x00] * CAA->Volume;\n\t\t\t\t\tRetSample->Right += CurBufR[0x00] * CAA->Volume;\n\t\t\t\t\tCAA->LSmpl.Left = CurBufL[0x00];\n\t\t\t\t\tCAA->LSmpl.Right = CurBufR[0x00];\n\t\t\t\t}\n\t\t\t\telse if (SmpCnt == 2)\n\t\t\t\t{\n\t\t\t\t\tRetSample->Left += (CurBufL[0x00] + CurBufL[0x01]) * CAA->Volume >> 1;\n\t\t\t\t\tRetSample->Right += (CurBufR[0x00] + CurBufR[0x01]) * CAA->Volume >> 1;\n\t\t\t\t\tCAA->LSmpl.Left = CurBufL[0x01];\n\t\t\t\t\tCAA->LSmpl.Right = CurBufR[0x01];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tTempS32L = CurBufL[0x00];\n\t\t\t\t\tTempS32R = CurBufR[0x00];\n\t\t\t\t\tfor (CurSmpl = 0x01; CurSmpl < SmpCnt; CurSmpl ++)\n\t\t\t\t\t{\n\t\t\t\t\t\tTempS32L += CurBufL[CurSmpl];\n\t\t\t\t\t\tTempS32R += CurBufR[CurSmpl];\n\t\t\t\t\t}\n\t\t\t\t\tRetSample->Left += TempS32L * CAA->Volume / SmpCnt;\n\t\t\t\t\tRetSample->Right += TempS32R * CAA->Volume / SmpCnt;\n\t\t\t\t\tCAA->LSmpl.Left = CurBufL[SmpCnt - 1];\n\t\t\t\t\tCAA->LSmpl.Right = CurBufR[SmpCnt - 1];\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 0x01:\t// Upsampling\n\t\t\tChipSmpRate = CAA->SmpRate;\n\t\t\tInPosL = (SLINT)(FIXPNT_FACT * CAA->SmpP * ChipSmpRate / SampleRate);\n\t\t\tInPre = (UINT32)fp2i_floor(InPosL);\n\t\t\tInNow = (UINT32)fp2i_ceil(InPosL);\n\t\t\t/*if (InNow - CAA->SmpNext >= SMPL_BUFSIZE)\n\t\t\t{\n\t\t\t\tfprintf(stderr, \"Sample Buffer Overflow!\\n\");\n#ifdef _DEBUG\n\t\t\t\t*(char*)NULL = 0;\n#endif\n\t\t\t\tCAA->SmpLast = 0;\n\t\t\t\tCAA->SmpNext = 0;\n\t\t\t\tCAA->SmpP = 0;\n\t\t\t\tbreak;\n\t\t\t}*/\n\t\t\t\n\t\t\tCurBufL[0x00] = CAA->LSmpl.Left;\n\t\t\tCurBufR[0x00] = CAA->LSmpl.Right;\n\t\t\tCurBufL[0x01] = CAA->NSmpl.Left;\n\t\t\tCurBufR[0x01] = CAA->NSmpl.Right;\n\t\t\tStreamPnt[0x00] = &CurBufL[0x02];\n\t\t\tStreamPnt[0x01] = &CurBufR[0x02];\n\t\t\tCAA->StreamUpdate(CAA->ChipID, StreamPnt, InNow - CAA->SmpNext);\n\t\t\t\n\t\t\tInBase = FIXPNT_FACT + (UINT32)(InPosL - (SLINT)CAA->SmpNext * FIXPNT_FACT);\n\t\t\t/*if (fp2i_floor(InBase) >= SMPL_BUFSIZE)\n\t\t\t{\n\t\t\t\tfprintf(stderr, \"Sample Buffer Overflow!\\n\");\n#ifdef _DEBUG\n\t\t\t\t*(char*)NULL = 0;\n#endif\n\t\t\t\tCAA->SmpLast = 0;\n\t\t\t\tCAA->SmpP = 0;\n\t\t\t\tbreak;\n\t\t\t}*/\n\t\t\tSmpCnt = FIXPNT_FACT;\n\t\t\tCAA->SmpLast = InPre;\n\t\t\tCAA->SmpNext = InNow;\n\t\t\tfor (OutPos = 0x00; OutPos < Length; OutPos ++)\n\t\t\t{\n\t\t\t\tInPos = InBase + (UINT32)(FIXPNT_FACT * OutPos * ChipSmpRate / SampleRate);\n\t\t\t\t\n\t\t\t\tInPre = fp2i_floor(InPos);\n\t\t\t\tInNow = fp2i_ceil(InPos);\n\t\t\t\tSmpFrc = getfriction(InPos);\n\t\t\t\t\n\t\t\t\t// Linear interpolation\n\t\t\t\tTempSmpL = ((INT64)CurBufL[InPre] * (FIXPNT_FACT - SmpFrc)) +\n\t\t\t\t\t\t\t((INT64)CurBufL[InNow] * SmpFrc);\n\t\t\t\tTempSmpR = ((INT64)CurBufR[InPre] * (FIXPNT_FACT - SmpFrc)) +\n\t\t\t\t\t\t\t((INT64)CurBufR[InNow] * SmpFrc);\n\t\t\t\tRetSample[OutPos].Left += (INT32)(TempSmpL * CAA->Volume / SmpCnt);\n\t\t\t\tRetSample[OutPos].Right += (INT32)(TempSmpR * CAA->Volume / SmpCnt);\n\t\t\t}\n\t\t\tCAA->LSmpl.Left = CurBufL[InPre];\n\t\t\tCAA->LSmpl.Right = CurBufR[InPre];\n\t\t\tCAA->NSmpl.Left = CurBufL[InNow];\n\t\t\tCAA->NSmpl.Right = CurBufR[InNow];\n\t\t\tCAA->SmpP += Length;\n\t\t\tbreak;\n\t\tcase 0x02:\t// Copying\n\t\t\tCAA->SmpNext = CAA->SmpP * CAA->SmpRate / SampleRate;\n\t\t\tCAA->StreamUpdate(CAA->ChipID, StreamBufs, Length);\n\t\t\t\n\t\t\tfor (OutPos = 0x00; OutPos < Length; OutPos ++)\n\t\t\t{\n\t\t\t\tRetSample[OutPos].Left += CurBufL[OutPos] * CAA->Volume;\n\t\t\t\tRetSample[OutPos].Right += CurBufR[OutPos] * CAA->Volume;\n\t\t\t}\n\t\t\tCAA->SmpP += Length;\n\t\t\tCAA->SmpLast = CAA->SmpNext;\n\t\t\tbreak;\n\t\tcase 0x03:\t// Downsampling\n\t\t\tChipSmpRate = CAA->SmpRate;\n\t\t\tInPosL = (SLINT)(FIXPNT_FACT * (CAA->SmpP + Length) * ChipSmpRate / SampleRate);\n\t\t\tCAA->SmpNext = (UINT32)fp2i_ceil(InPosL);\n\t\t\t\n\t\t\tCurBufL[0x00] = CAA->LSmpl.Left;\n\t\t\tCurBufR[0x00] = CAA->LSmpl.Right;\n\t\t\tStreamPnt[0x00] = &CurBufL[0x01];\n\t\t\tStreamPnt[0x01] = &CurBufR[0x01];\n\t\t\tCAA->StreamUpdate(CAA->ChipID, StreamPnt, CAA->SmpNext - CAA->SmpLast);\n\t\t\t\n\t\t\tInPosL = (SLINT)(FIXPNT_FACT * CAA->SmpP * ChipSmpRate / SampleRate);\n\t\t\t// I'm adding 1.0 to avoid negative indexes\n\t\t\tInBase = FIXPNT_FACT + (UINT32)(InPosL - (SLINT)CAA->SmpLast * FIXPNT_FACT);\n\t\t\tInPosNext = InBase;\n\t\t\tfor (OutPos = 0x00; OutPos < Length; OutPos ++)\n\t\t\t{\n\t\t\t\t//InPos = InBase + (UINT32)(FIXPNT_FACT * OutPos * ChipSmpRate / SampleRate);\n\t\t\t\tInPos = InPosNext;\n\t\t\t\tInPosNext = InBase + (UINT32)(FIXPNT_FACT * (OutPos+1) * ChipSmpRate / SampleRate);\n\t\t\t\t\n\t\t\t\t// first frictional Sample\n\t\t\t\tSmpFrc = getnfriction(InPos);\n\t\t\t\tif (SmpFrc)\n\t\t\t\t{\n\t\t\t\t\tInPre = fp2i_floor(InPos);\n\t\t\t\t\tTempSmpL = (INT64)CurBufL[InPre] * SmpFrc;\n\t\t\t\t\tTempSmpR = (INT64)CurBufR[InPre] * SmpFrc;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tTempSmpL = TempSmpR = 0x00;\n\t\t\t\t}\n\t\t\t\tSmpCnt = SmpFrc;\n\t\t\t\t\n\t\t\t\t// last frictional Sample\n\t\t\t\tSmpFrc = getfriction(InPosNext);\n\t\t\t\tInPre = fp2i_floor(InPosNext);\n\t\t\t\tif (SmpFrc)\n\t\t\t\t{\n\t\t\t\t\tTempSmpL += (INT64)CurBufL[InPre] * SmpFrc;\n\t\t\t\t\tTempSmpR += (INT64)CurBufR[InPre] * SmpFrc;\n\t\t\t\t\tSmpCnt += SmpFrc;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// whole Samples in between\n\t\t\t\t//InPre = fp2i_floor(InPosNext);\n\t\t\t\tInNow = fp2i_ceil(InPos);\n\t\t\t\tSmpCnt += (InPre - InNow) * FIXPNT_FACT;\t// this is faster\n\t\t\t\twhile(InNow < InPre)\n\t\t\t\t{\n\t\t\t\t\tTempSmpL += (INT64)CurBufL[InNow] * FIXPNT_FACT;\n\t\t\t\t\tTempSmpR += (INT64)CurBufR[InNow] * FIXPNT_FACT;\n\t\t\t\t\t//SmpCnt ++;\n\t\t\t\t\tInNow ++;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tRetSample[OutPos].Left += (INT32)(TempSmpL * CAA->Volume / SmpCnt);\n\t\t\t\tRetSample[OutPos].Right += (INT32)(TempSmpR * CAA->Volume / SmpCnt);\n\t\t\t}\n\t\t\t\n\t\t\tCAA->LSmpl.Left = CurBufL[InPre];\n\t\t\tCAA->LSmpl.Right = CurBufR[InPre];\n\t\t\tCAA->SmpP += Length;\n\t\t\tCAA->SmpLast = CAA->SmpNext;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tCAA->SmpP += SampleRate;\n\t\t\tbreak;\t// do absolutely nothing\n\t\t}\n\t\t\n\t\tif (CAA->SmpLast >= CAA->SmpRate)\n\t\t{\n\t\t\tCAA->SmpLast -= CAA->SmpRate;\n\t\t\tCAA->SmpNext -= CAA->SmpRate;\n\t\t\tCAA->SmpP -= SampleRate;\n\t\t}\n\t\t\n\t\tCAA = CAA->Paired;\n\t} while(CAA != NULL);\n\t\n\treturn;\n}\n\nstatic INT32 RecalcFadeVolume(void)\n{\n\tfloat TempSng;\n\t\n\tif (FadePlay)\n\t{\n\t\tif (! FadeStart)\n\t\t\tFadeStart = PlayingTime;\n\t\t\n\t\tTempSng = (PlayingTime - FadeStart) / (float)SampleRate;\n\t\tMasterVol = 1.0f - TempSng / (FadeTime * 0.001f);\n\t\tif (MasterVol < 0.0f)\n\t\t{\n\t\t\tMasterVol = 0.0f;\n\t\t\t//EndPlay = true;\n\t\t\tVGMEnd = true;\n\t\t}\n\t\tFinalVol = VolumeLevelM * MasterVol * MasterVol;\n\t}\n\t\n\treturn (INT32)(0x100 * FinalVol + 0.5f);\n}\n\nUINT32 FillBuffer(WAVE_16BS* Buffer, UINT32 BufferSize)\n{\n\tUINT32 CurSmpl;\n\tWAVE_32BS TempBuf;\n\tINT32 CurMstVol;\n\tUINT32 RecalcStep;\n\tCA_LIST* CurCLst;\n\t\n\t//memset(Buffer, 0x00, sizeof(WAVE_16BS) * BufferSize);\n\t\n\tRecalcStep = FadePlay ? SampleRate / 44100 : 0;\n\tCurMstVol = RecalcFadeVolume();\n\t\n\tif (Buffer == NULL)\n\t{\n\t\t//for (CurSmpl = 0x00; CurSmpl < BufferSize; CurSmpl ++)\n\t\t//\tInterpretFile(1);\n\t\tInterpretFile(BufferSize);\n\t\t\n\t\tif (FadePlay && ! FadeStart)\n\t\t{\n\t\t\tFadeStart = PlayingTime;\n\t\t\tRecalcStep = FadePlay ? SampleRate / 100 : 0;\n\t\t}\n\t\t//if (RecalcStep && ! (CurSmpl % RecalcStep))\n\t\tif (RecalcStep)\n\t\t\tCurMstVol = RecalcFadeVolume();\n\t\t\n\t\tif (VGMEnd)\n\t\t{\n\t\t\tif (PauseSmpls <= BufferSize)\n\t\t\t{\n\t\t\t\tPauseSmpls = 0;\n\t\t\t\tEndPlay = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tPauseSmpls -= BufferSize;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn BufferSize;\n\t}\n\t\n\tCurChipList = (VGMEnd || PausePlay) ? ChipListPause : ChipListAll;\n\t\n\tfor (CurSmpl = 0x00; CurSmpl < BufferSize; CurSmpl ++)\n\t{\n\t\tInterpretFile(1);\n\t\t\n\t\t// Sample Structures\n\t\t//\t00 - SN76496\n\t\t//\t01 - YM2413\n\t\t//\t02 - YM2612\n\t\t//\t03 - YM2151\n\t\t//\t04 - SegaPCM\n\t\t//\t05 - RF5C68\n\t\t//\t06 - YM2203\n\t\t//\t07 - YM2608\n\t\t//\t08 - YM2610/YM2610B\n\t\t//\t09 - YM3812\n\t\t//\t0A - YM3526\n\t\t//\t0B - Y8950\n\t\t//\t0C - YMF262\n\t\t//\t0D - YMF278B\n\t\t//\t0E - YMF271\n\t\t//\t0F - YMZ280B\n\t\t//\t10 - RF5C164\n\t\t//\t11 - PWM\n\t\t//\t12 - AY8910\n\t\t//\t13 - GameBoy\n\t\t//\t14 - NES APU\n\t\t//\t15 - MultiPCM\n\t\t//\t16 - UPD7759\n\t\t//\t17 - OKIM6258\n\t\t//\t18 - OKIM6295\n\t\t//\t19 - K051649\n\t\t//\t1A - K054539\n\t\t//\t1B - HuC6280\n\t\t//\t1C - C140\n\t\t//\t1D - K053260\n\t\t//\t1E - Pokey\n\t\t//\t1F - QSound\n\t\t//\t20 - YMF292/SCSP\n\t\t//\t21 - WonderSwan\n\t\t//\t22 - VSU\n\t\t//\t23 - SAA1099\n\t\t//\t24 - ES5503\n\t\t//\t25 - ES5506\n\t\t//\t26 - X1-010\n\t\t//\t27 - C352\n\t\t//\t28 - GA20\n\t\tTempBuf.Left = 0x00;\n\t\tTempBuf.Right = 0x00;\n\t\tCurCLst = CurChipList;\n\t\twhile(CurCLst != NULL)\n\t\t{\n\t\t\tif (! CurCLst->COpts->Disabled)\n\t\t\t{\n\t\t\t\tResampleChipStream(CurCLst, &TempBuf, 1);\n\t\t\t}\n\t\t\tCurCLst = CurCLst->next;\n\t\t}\n\t\t\n\t\t// ChipData << 9 [ChipVol] >> 5 << 8 [MstVol] >> 11  ->  9-5+8-11 = <<1\n\t\tTempBuf.Left = ((TempBuf.Left >> 5) * CurMstVol) >> 11;\n\t\tTempBuf.Right = ((TempBuf.Right >> 5) * CurMstVol) >> 11;\n\t\tif (SurroundSound)\n\t\t\tTempBuf.Right *= -1;\n\t\tBuffer[CurSmpl].Left = Limit2Short(TempBuf.Left);\n\t\tBuffer[CurSmpl].Right = Limit2Short(TempBuf.Right);\n\t\t\n\t\tif (FadePlay && ! FadeStart)\n\t\t{\n\t\t\tFadeStart = PlayingTime;\n\t\t\tRecalcStep = FadePlay ? SampleRate / 100 : 0;\n\t\t}\n\t\tif (RecalcStep && ! (CurSmpl % RecalcStep))\n\t\t\tCurMstVol = RecalcFadeVolume();\n\t\t\n\t\tif (VGMEnd)\n\t\t{\n\t\t\tif (! PauseSmpls)\n\t\t\t{\n\t\t\t\t//if (! FullBufFill)\n\t\t\t\tif (! EndPlay)\n\t\t\t\t{\n\t\t\t\t\tEndPlay = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse //if (PauseSmpls)\n\t\t\t{\n\t\t\t\tPauseSmpls --;\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn CurSmpl;\n}\n\n#ifdef WIN32\nDWORD WINAPI PlayingThread(void* Arg)\n{\n\tLARGE_INTEGER CPUFreq;\n\tLARGE_INTEGER TimeNow;\n\tLARGE_INTEGER TimeLast;\n\tUINT64 TimeDiff;\n\tUINT64 SampleTick;\n\tUINT64 Ticks;\n\tBOOL RetVal;\n\t\n\thPlayThread = GetCurrentThread();\n#ifndef _DEBUG\n\tRetVal = SetThreadPriority(hPlayThread, THREAD_PRIORITY_TIME_CRITICAL);\n#else\n\tRetVal = SetThreadPriority(hPlayThread, THREAD_PRIORITY_ABOVE_NORMAL);\n#endif\n\tif (! RetVal)\n\t{\n\t\t// Error by setting priority\n\t}\n\t\n\tQueryPerformanceFrequency(&CPUFreq);\n\tQueryPerformanceCounter(&TimeNow);\n\tTimeLast = TimeNow;\n\tSampleTick = CPUFreq.QuadPart / SampleRate;\n\t\n\twhile (! CloseThread)\n\t{\n\t\twhile(PlayingMode != 0x01 && ! CloseThread)\n\t\t\tSleep(1);\n\t\t\n\t\tif (! PauseThread)\n\t\t{\n\t\t\tTimeDiff = TimeNow.QuadPart - TimeLast.QuadPart;\n\t\t\tif (TimeDiff >= SampleTick)\n\t\t\t{\n\t\t\t\tTicks = TimeDiff * SampleRate / CPUFreq.QuadPart;\n\t\t\t\tif (Ticks > SampleRate / 2)\n\t\t\t\t\tTicks = SampleRate / 50;\n\t\t\t\tFillBuffer(NULL, (UINT32)Ticks);\n\t\t\t\tif (! ResetPBTimer)\n\t\t\t\t{\n\t\t\t\t\tTimeLast = TimeNow;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tQueryPerformanceCounter(&TimeLast);\n\t\t\t\t\tTimeLast.QuadPart -= TimeDiff;\n\t\t\t\t\tResetPBTimer = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// I tried to make sample-accurate replaying through Hardware FM\n\t\t\t// to make PSG-PCM clear, but it didn't work\n\t\t\t//if (! FMAccurate)\n\t\t\tSleep(1);\n\t\t\t//else\n\t\t\t//\tSleep(0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tThreadPauseConfrm = true;\n\t\t\tif (! ThreadNoWait)\n\t\t\t\tTimeLast = TimeNow;\n\t\t\tSleep(1);\n\t\t}\n\t\tQueryPerformanceCounter(&TimeNow);\n\t}\n\t\n\thPlayThread = NULL;\n\treturn 0x00000000;\n}\n#else\nUINT64 TimeSpec2Int64(const struct timespec* ts)\n{\n\treturn (UINT64)ts->tv_sec * 1000000000 + ts->tv_nsec;\n}\n\nvoid* PlayingThread(void* Arg)\n{\n\tUINT64 CPUFreq;\n\tUINT64 TimeNow;\n\tUINT64 TimeLast;\n\tUINT64 TimeDiff;\n\tUINT64 SampleTick;\n\tUINT64 Ticks;\n\tstruct timespec TempTS;\n\tint RetVal;\n\t\n\t//RetVal = clock_getres(CLOCK_MONOTONIC, &TempTS);\n\t//CPUFreq = TimeSpec2Int64(&TempTS);\n\tCPUFreq = 1000000000;\n\tRetVal = clock_gettime(CLOCK_MONOTONIC, &TempTS);\n\tTimeNow = TimeSpec2Int64(&TempTS);\n\tTimeLast = TimeNow;\n\tSampleTick = CPUFreq / SampleRate;\n\t\n\twhile (! CloseThread)\n\t{\n\t\twhile(PlayingMode != 0x01 && ! CloseThread)\n\t\t\tSleep(1);\n\t\t\n\t\tif (! PauseThread)\n\t\t{\n\t\t\tTimeDiff = TimeNow - TimeLast;\n\t\t\tif (TimeDiff >= SampleTick)\n\t\t\t{\n\t\t\t\tTicks = TimeDiff * SampleRate / CPUFreq;\n\t\t\t\tif (Ticks > SampleRate / 2)\n\t\t\t\t\tTicks = SampleRate / 50;\n\t\t\t\tFillBuffer(NULL, (UINT32)Ticks);\n\t\t\t\tif (! ResetPBTimer)\n\t\t\t\t{\n\t\t\t\t\tTimeLast = TimeNow;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tRetVal = clock_gettime(CLOCK_MONOTONIC, &TempTS);\n\t\t\t\t\tTimeLast = TimeSpec2Int64(&TempTS) - TimeDiff;\n\t\t\t\t\tResetPBTimer = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//if (! FMAccurate)\n\t\t\tSleep(1);\n\t\t\t//else\n\t\t\t//\tSleep(0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tThreadPauseConfrm = true;\n\t\t\tif (ThreadNoWait)\n\t\t\t\tTimeLast = TimeNow;\n\t\t\tSleep(1);\n\t\t}\n\t\tRetVal = clock_gettime(CLOCK_MONOTONIC, &TempTS);\n\t\tTimeNow = TimeSpec2Int64(&TempTS);\n\t}\n\t\n\treturn NULL;\n}\n#endif\n"
  },
  {
    "path": "VGMPlay/VGMPlay.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"VGMPlay\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** NICHT BEARBEITEN **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=VGMPlay - Win32 Debug\r\n!MESSAGE Dies ist kein gltiges Makefile. Zum Erstellen dieses Projekts mit NMAKE\r\n!MESSAGE verwenden Sie den Befehl \"Makefile exportieren\" und fhren Sie den Befehl\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"VGMPlay.mak\".\r\n!MESSAGE \r\n!MESSAGE Sie knnen beim Ausfhren von NMAKE eine Konfiguration angeben\r\n!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"VGMPlay.mak\" CFG=\"VGMPlay - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Fr die Konfiguration stehen zur Auswahl:\r\n!MESSAGE \r\n!MESSAGE \"VGMPlay - Win32 Release\" (basierend auf  \"Win32 (x86) Console Application\")\r\n!MESSAGE \"VGMPlay - Win32 Debug\" (basierend auf  \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"Release\"\r\n# PROP BASE Intermediate_Dir \"Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"Release\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /Yu\"stdafx.h\" /FD /c\r\n# ADD CPP /nologo /MD /W3 /GX /Ox /Ot /Og /Oi /Ob2 /I \"zlib\" /D \"NDEBUG\" /D \"WIN32_LEAN_AND_MEAN\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"VGM_LITTLE_ENDIAN\" /D \"ENABLE_ALL_CORES\" /D \"CONSOLE_MODE\" /D \"ADDITIONAL_FORMATS\" /D \"SET_CONSOLE_TITLE\" /FD /c\r\n# SUBTRACT CPP /Oa /Ow /YX /Yc /Yu\r\n# ADD BASE RSC /l 0x407 /d \"NDEBUG\"\r\n# ADD RSC /l 0x407 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 msvcrt.lib oldnames.lib kernel32.lib user32.lib advapi32.lib winmm.lib zdll.lib /nologo /subsystem:console /machine:I386 /nodefaultlib /libpath:\"zlib\"\r\n# Begin Special Build Tool\r\nSOURCE=\"$(InputPath)\"\r\nPostBuild_Cmds=..\\vgm2txt\\HiddenMsg.exe Release\\VGMPlay.exe\r\n# End Special Build Tool\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"Debug\"\r\n# PROP BASE Intermediate_Dir \"Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"Debug\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /Yu\"stdafx.h\" /FD /GZ /c\r\n# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I \"zlib\" /D \"_DEBUG\" /D \"WIN32_LEAN_AND_MEAN\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"VGM_LITTLE_ENDIAN\" /D \"ENABLE_ALL_CORES\" /D \"CONSOLE_MODE\" /D \"ADDITIONAL_FORMATS\" /D \"SET_CONSOLE_TITLE\" /FR /FD /GZ /c\r\n# SUBTRACT CPP /YX /Yc /Yu\r\n# ADD BASE RSC /l 0x407 /d \"_DEBUG\"\r\n# ADD RSC /l 0x407 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 msvcrtd.lib oldnames.lib kernel32.lib user32.lib advapi32.lib winmm.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib /libpath:\"zlib\"\r\n# SUBTRACT LINK32 /profile /map\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"VGMPlay - Win32 Release\"\r\n# Name \"VGMPlay - Win32 Debug\"\r\n# Begin Group \"Quellcodedateien\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\dbus_stub.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\mmkeys_Win.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\pt_ioctl.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Stream.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\VGMPlay.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\VGMPlay_AddFmts.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\VGMPlayUI.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header-Dateien\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\dbus.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\mmkeys.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\PortTalk_IOCTL.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Stream.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=\".\\XMasFiles\\SWJ-SQRC01_1C.h\"\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\VGMFile.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\VGMPlay.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\VGMPlay_Intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\XMasFiles\\XMasBonus.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Ressourcendateien\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# Begin Group \"SoundCore\"\r\n\r\n# PROP Default_Filter \"c;h;cpp\"\r\n# Begin Group \"FM OPL Chips\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2413intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2413intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\262intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\262intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\3526intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /W1 /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n# ADD CPP /W1\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\3526intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\3812intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /W1 /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n# ADD CPP /W1\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\3812intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\8950intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /W1 /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n# ADD CPP /W1\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\8950intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\adlibemu.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\adlibemu_opl2.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\adlibemu_opl3.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\emu2413.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\emu2413.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\emutypes.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\fmopl.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\fmopl.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\opl.c\r\n# PROP Exclude_From_Build 1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\opl.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\opll.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\opll.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\vrc7tone.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2413.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2413.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymf262.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymf262.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymf278b.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymf278b.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"FM OPN Chips\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2203intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2203intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2608intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2608intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2610intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2610intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2612intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2612intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\fm.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\fm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\fm2612.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2612.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2612.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym3438.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym3438.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"FM OPx Chips\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2151intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2151intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\opm.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\opm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scsp.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scsp.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scspdsp.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scspdsp.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scsplfo.c\r\n# PROP Exclude_From_Build 1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2151.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2151.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymf271.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymf271.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"PCM Chips\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c140.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c140.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c352.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c352.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\es5503.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\es5503.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\es5506.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\es5506.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\iremga20.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\iremga20.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\k053260.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\k053260.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\k054539.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\k054539.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\multipcm.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\multipcm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\okim6258.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\okim6258.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\okim6295.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\okim6295.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\pwm.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\pwm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\qsound_ctr.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\qsound_ctr.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\qsound_intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\qsound_intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\qsound_mame.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\qsound_mame.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\rf5c68.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\rf5c68.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scd_pcm.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scd_pcm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\segapcm.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\segapcm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\upd7759.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\upd7759.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\x1_010.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\x1_010.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymdeltat.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymdeltat.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymz280b.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /W1 /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n# ADD CPP /W1\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymz280b.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"OPL Mapper\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ay8910_opl.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn76496_opl.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2413_opl.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /W1 /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2413hd.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /W1 /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2413hd.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"PSG Chips\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ay8910.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ay8910.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ay_intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ay_intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c6280.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c6280.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c6280intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c6280intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\emu2149.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\emu2149.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\gb.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\gb.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\k051649.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\k051649.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\Ootake_PSG.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\Ootake_PSG.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\pokey.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\pokey.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\saa1099.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\saa1099.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn76489.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn76489.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn76496.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn76496.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn764intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn764intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\vsu.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\vsu.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ws_audio.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ws_audio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ws_initialIo.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"NES Chips\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\nes_apu.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\nes_apu.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\nes_defs.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\nes_intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\nes_intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\np_nes_apu.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\np_nes_apu.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\np_nes_dmc.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\np_nes_dmc.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\np_nes_fds.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\np_nes_fds.h\r\n# End Source File\r\n# End Group\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ChipIncl.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\ChipMapper.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\ChipMapper.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\dac_control.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\dac_control.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\mamedef.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\panning.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\panning.h\r\n# End Source File\r\n# End Group\r\n# Begin Source File\r\n\r\nSOURCE=.\\ReadMe.txt\r\n# End Source File\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "VGMPlay/VGMPlay.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\r\n# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELSCHT WERDEN!\r\n\r\n###############################################################################\r\n\r\nProject: \"VGMPlay\"=\".\\VGMPlay.dsp\" - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nGlobal:\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<3>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\n"
  },
  {
    "path": "VGMPlay/VGMPlay.h",
    "content": "// Header File for structures and constants used within VGMPlay.c\n\n#include \"VGMFile.h\"\n\n#define VGMPLAY_VER_STR\t\"0.40.9.1\"\n//#define APLHA\n//#define BETA\n#define VGM_VER_STR\t\t\"1.71b\"\n#define VGM_VER_NUM\t\t0x170\n\n#define CHIP_COUNT\t0x29\ntypedef struct chip_options\n{\n\tbool Disabled;\n\tUINT8 EmuCore;\n\tUINT8 ChnCnt;\n\t// Special Flags:\n\t//\tYM2612:\tBit 0 - DAC Highpass Enable, Bit 1 - SSG-EG Enable\n\t//\tYM-OPN:\tBit 0 - Disable AY8910-Part\n\tUINT16 SpecialFlags;\n\t\n\t// Channel Mute Mask - 1 Channel is represented by 1 bit\n\tUINT32 ChnMute1;\n\t// Mask 2 - used by YMF287B for OPL4 Wavetable Synth and by YM2608/YM2610 for PCM\n\tUINT32 ChnMute2;\n\t// Mask 3 - used for the AY-part of some OPN-chips\n\tUINT32 ChnMute3;\n\n\tINT16* Panning;\n} CHIP_OPTS;\ntypedef struct chips_options\n{\n\tCHIP_OPTS SN76496;\n\tCHIP_OPTS YM2413;\n\tCHIP_OPTS YM2612;\n\tCHIP_OPTS YM2151;\n\tCHIP_OPTS SegaPCM;\n\tCHIP_OPTS RF5C68;\n\tCHIP_OPTS YM2203;\n\tCHIP_OPTS YM2608;\n\tCHIP_OPTS YM2610;\n\tCHIP_OPTS YM3812;\n\tCHIP_OPTS YM3526;\n\tCHIP_OPTS Y8950;\n\tCHIP_OPTS YMF262;\n\tCHIP_OPTS YMF278B;\n\tCHIP_OPTS YMF271;\n\tCHIP_OPTS YMZ280B;\n\tCHIP_OPTS RF5C164;\n\tCHIP_OPTS PWM;\n\tCHIP_OPTS AY8910;\n\tCHIP_OPTS GameBoy;\n\tCHIP_OPTS NES;\n\tCHIP_OPTS MultiPCM;\n\tCHIP_OPTS UPD7759;\n\tCHIP_OPTS OKIM6258;\n\tCHIP_OPTS OKIM6295;\n\tCHIP_OPTS K051649;\n\tCHIP_OPTS K054539;\n\tCHIP_OPTS HuC6280;\n\tCHIP_OPTS C140;\n\tCHIP_OPTS K053260;\n\tCHIP_OPTS Pokey;\n\tCHIP_OPTS QSound;\n\tCHIP_OPTS SCSP;\n\tCHIP_OPTS WSwan;\n\tCHIP_OPTS VSU;\n\tCHIP_OPTS SAA1099;\n\tCHIP_OPTS ES5503;\n\tCHIP_OPTS ES5506;\n\tCHIP_OPTS X1_010;\n\tCHIP_OPTS C352;\n\tCHIP_OPTS GA20;\n//\tCHIP_OPTS OKIM6376;\n} CHIPS_OPTION;\n"
  },
  {
    "path": "VGMPlay/VGMPlay.ini",
    "content": "; VGMPlay Configuration File\n; --------------------------\n;\n; Default Values are usually 0 (False for boolean ones)\n; Boolean Values are:\n;\tFalse / 0\n;\tTrue / 1\n\n[General]\n; Default Sample Rate: 44100\nSampleRate = 48000\n; If you set PlaybackRate to 50, some songs will play slower, like on a PAL console.\n; If you set it to 60, some songs may play faster, like PAL games on a NTSC console.\nPlaybackRate = 0\n\n; double the volume of the YM2xxx SSG, if it gets overridden by a VGM's header.\n; This option will be removed once all VGMs on vgmrips are fixed.\nDoubleSSGVol = True\n\n; Display Japanese GD3 Tag if available\n; Most western Windows systems won't be able to display Japanese characters in the normal console,\n; so use at own risk. (Linux doesn't have this problem.)\nPreferJapTag = False\n\n; Default Fade Time: 5000\nFadeTime = 8000\n; In-Playlist Fade Time: for all looping tracks in a playlist (except the last one)\n; Setting this to 0 simulate a Song-Medley without gaps.\n; Default Fade Time in Playlist: 2000\nFadeTimePL = 0\nJinglePause = 1000\n\n; enforce silence at the end of old VGMs (version <1.50), enable to fix hanging notes in playlists\nHardStopOld = False\n; Fade RAW logs from emulators (VGMs without Creator-Tag) so that they don't\n; end abruptly at the full volume level but at 33%\nFadeRAWLogs = False\n; Default Volume: 1.0 (of course)\nVolume = 1.0\n\n; Log Sound to Wave: 0 - no logging, 1 - log only, 2 - play and log\nLogSound = 0\n\n; Maximum Loops before fading\n; Default: 0x02 (0x01 for CMF)\nMaxLoops = 0x02\nMaxLoopsCMF = 0x01\n\n; Resampling Mode:\n;\t0 - always high quality resampler (default)\n;\t1 - HQ resampler for upsampling, LQ resampler for downsampling (recommend for slow machines)\n;\t2 - always low quality resampler (very fast)\nResamplingMode = 0\n; Chip Sample Mode:\n;\t0 - Native (default)\n;\t1 - use highest sampling rate (native or the one below)\n;\t2 - use always the sampling rate below (CPU friendly)\n;\t3 - use native sample rate for FM chips and highest sampling rate for all others\nChipSmplMode = 3\n; Default Chip Sample Rate: 0 (results in value of Playback SampleRate)\nChipSmplRate = 0\n\n; [Windows only] waveOut device ID to use (0 = default/Wave Mapper)\nOutputDevice = 0\n; Force Audio Buffer Number (1 Buffer = 10 ms, Minimum is 4, Maximum is 200)\n; higher values result in greater delays while seeking (and pausing with EmulatePause On)\n; set this to 50 or 100 if the sound is choppy\n; 0 results in 10 for Windows 98/ME/2000/XP/7,\n; 50 for Windows 95 and 20 for Windows Vista\nAudioBuffers = 0\n; \"Surround\" Sound - inverts the waveform of the right channel to create a pseudo surround effect\n; use only with headphones!!\nSurroundSound = False\n; Emulate during Pause: continue to generate sound while playback is paused\nEmulatePause = False\n; Shows the last data block played with DAC Stream Command 95. Useful for debugging.\n;\t0 - don't show\n;\t1 - show data block ID only\n;\t2 - show data block ID + frequency\n;\t3 - show data block ID + frequency in KHz\nShowStreamCmds = 3\n\n; --- FM Hardware Section Start ---\n; Hardware FM Port (in hex, usually 220 or 388)\nFMPort = 0\n; Force FM Mode, even if only the SN76496 is used, also enables Mixed Mode (Hardware FM + Software Emulator)\nFMForce = False\n; Makes some FM-Voices fading on track-end instead of instant silencing them\nFMSoftStop = True\n; Overrides Volume setting, if FM hardware is used\n; Possible values:\n;\t= 0 - don't override (default)\n;\t> 0 - override Volume setting and VGM Volume Modifier\n;\t< 0 - multiply with volume\nFMVolume = 1.0\n; allow OPL3 panning commands in OPL 1/2 data (default: False)\nFMOPL2Pan = True\n; --- FM Hardware Section End ---\n\n\n; Chip Options\n; ------------\n; - Disabled = False/True\n;\tdisable the emulation of the current chip\n; - EmulatorType = 0 / 1 / ...\n;\t0 is recommend/default, 1+ are alternative emulation cores\n; - MuteMask = 0\n;\tmute channels by setting the muting bitmask\n; - MuteCh? = False/True\n;\tmute channel ?\n; - Mutexxx = False/True\n;\tmute channel with the name xxx (e.g. DAC, DT, BD, ...)\n\n[SN76496]\nDisabled = False\n; EmulatorType: 0 - MAME, 1 - Maxim\nEmulatorType = 0x00\n; Channels: 4 (0-3)\n\n[YM2413]\nDisabled = False\n; FMPort = 0:\n;\tEmulatorType: 0 - EMU2413, 1 - MAME, 2 - Nuked OPLL\n; FMPort != 0:\n;\tEmulatorType: 0 - Valley Bell Custom, 1 - Meka\nEmulatorType = 0x00\n; Channels: 14 (0-8, BD, SD, TOM, TC, HH)\n\n[YM2612]\nDisabled = False\n; EmulatorType: 0 - MAME (Genesis Plus GX), 1 - Nuked OPN2, 2 - Gens\nEmulatorType = 0x00\n; MAME: if on, the chip updates its left/right channel alternatively, creating a nice pseudo-stereo effect\n; Note: If you emulate at a set sample rate, this option halves it.\nPseudoStereo = False\n; Gens: DAC Highpass-Filter (sometimes sounds good, but sometimes it generates a terrible noise)\nDACHighpass = False\n; Gens: SSG-EG Enable (very buggy)\nSSG-EG = False\n; Nuked OPN2 chip type: 0 - YM2612 with Mega Drive model 1 filter simulation\n;                       1 - ASIC YM3438, 2 - Discrete YM3438, 3 - YM2612\nNukedType = 0x00\n; Channels: 7 (0-5, DAC)\n\n[YM2151]\nDisabled = False\n; EmulatorType: 0 - MAME, 1 - Nuked OPM\nEmulatorType = 0x00\n; Channels: 8 (0-7)\n\n[SegaPCM]\nDisabled = False\n; Channels: 16 (0-15)\n\n[RF5C68]\nDisabled = False\n; Channels: 8 (0-7)\n\n[YM2203]\nDisabled = False\n; AY/YM2149 EmulatorType: 0 - EMU2149, 1 - MAME\nEmulatorType = 0x00\n; disable the AY8910-part to speed up loading\nDisableAY = False\n; Channels: 3 (0-2)\n\n[YM2608]\nDisabled = False\nEmulatorType = 0x00\nDisableAY = False\n; Channels: 6 FM (0-5) + 6 ADPCM (0-5) + 1 Delta-T\n; Use MuteMask_FM, MuteMask_PCM (Delta-T is Ch6), MuteFMCh, MutePCMCh and MuteDT\n\n[YM2610]\nDisabled = False\nEmulatorType = 0x00\nDisableAY = False\n; Channels: 6 FM (0-5) + 6 ADPCM (0-5) + 1 Delta-T\n; Use MuteMask_FM, MuteMask_PCM (Delta-T is Ch6), MuteFMCh, MutePCMCh and MuteDT\n\n[YM3812]\nDisabled = False\n; EmulatorType: 0 - DOSBox (AdLibEmu), 1 - MAME\nEmulatorType = 0x00\n; Channels: 14 (0-8, BD, SD, TOM, TC, HH)\n\n[YM3526]\nDisabled = False\n; Channels: 14 (0-8, BD, SD, TOM, TC, HH)\n\n[Y8950]\nDisabled = False\n; Channels: 15 (0-8, BD, SD, TOM, TC, HH, DT)\n\n[YMF262]\nDisabled = False\n; EmulatorType: 0 - DOSBox (AdLibEmu), 1 - MAME\nEmulatorType = 0x00\n; Channels: 23 (0-17, BD, SD, TOM, TC, HH)\n\n[YMF278B]\nDisabled = False\n; Channels: 23 FM (0-17, BD, SD, TOM, TC, HH) + 24 WaveTable (0-23)\n; Use MuteMask_FM, MuteMask_WT, MuteFMCh and MuteWTCh\n\n[YMF271]\nDisabled = False\n; Channels: 12 (0-11)\n\n[YMZ280B]\nDisabled = False\n; Channels: 8 (0-7)\n\n[RF5C164]\nDisabled = False\n; Channels: 8 (0-7)\n\n[PWM]\nDisabled = False\n; Channels: none (it just has left and right)\n\n[AY8910]\nDisabled = False\n; EmulatorType: 0 - EMU2149, 1 - MAME\nEmulatorType = 0x00\n; Channels: 3 (0-2)\n\n[GameBoy]\nDisabled = False\n; double the volume of the Wave Channel (sounds better, but may be less accurate and seems to sound distorted sometimes, like nezplay++)\nBoostWaveChn = True\n; Channels: 4 (0-3)\n\n[NES APU]\nDisabled = False\n; EmulatorType: 0 - NSFPlay, 1 - MAME\nEmulatorType = 0x00\n; Channels: 6 (0-5 = Square 1, Square 2, Triangle, Noise, DPCM, FDS)\n\n; Options (NSFPlay cores only)\n; -------\n; APU/DMC Options (2 bits, default: 0x03)\n;   0x01 - OPT_UNMUTE_ON_RESET (enable all channels by default after reset)\n;   0x02 - OPT_NONLINEAR_MIXER\nSharedOpts = 0x03\n; APU Options (2 bits, default: 0x01)\n;   0x01 - OPT_PHASE_REFRESH\n;   0x02 - OPT_DUTY_SWAP\nAPUOpts = 0x01\n; DMC Options (6 bits, default: 0x3B)\n;   0x01 - OPT_ENABLE_4011\n;   0x02 - OPT_ENABLE_PNOISE\n;   0x04 - OPT_DPCM_ANTI_CLICK (nullify register 4011 writes, keeps DPCM limits correctly)\n;   0x08 - OPT_RANDOMIZE_NOISE\n;   0x10 - OPT_TRI_MUTE (stops Triangle wave if set to freq = 0, processes it at a very high rate else)\n;   0x20 - OPT_TRI_NULL (VB custom, always makes Triangle return to null-level when stopping)\nDMCOpts = 0x3B\n; FDS Options (1 bit, default: 0x00)\n;   0x01 - OPT_4085_RESET (reset modulation phase on 4085 writes)\nFDSOpts = 0x00\n\n[YMW258]\nDisabled = False\n; Channels: 28 (0-27)\n\n[uPD7759]\nDisabled = False\n; Channels: none (actually 1)\n\n[OKIM6258]\nDisabled = False\n; enables internal 10-bit processing (original MESS behaviour)\n; The comments in the code say something about 10-bit and 12-bit DAC, but that's not what the code does.\nEnable10Bit = False\n; Channels: none (actually 1)\n\n[OKIM6295]\nDisabled = False\n; Channels: 4 (0-3)\n\n[K051649]\n; also known as SCC1\nDisabled = False\n; Channels: 5 (0-4)\n\n[K054539]\nDisabled = False\n; Channels: 8 (0-7)\n\n[HuC6280]\nDisabled = False\n; EmulatorType: 0 - Ootake, 1 - MAME (sounds brighter, lacks LFO)\nEmulatorType = 0x00\n; Channels: 6 (0-5)\n\n[C140]\nDisabled = False\n; Channels: 24 (0-23)\n\n[K053260]\nDisabled = False\n; Channels: 4 (0-3)\n\n[Pokey]\nDisabled = False\n; Channels: 4 (0-3)\n\n[QSound]\nDisabled = False\n; EmulatorType: 0 - superctr custom (Based on real DSP code, featuring QSound effects),\n;               1 - MAME (old HLE, higher sample rate)\nEmulatorType = 0x00\n; Channels: 16 (0-15)\n\n[SCSP]\nDisabled = False\n; Skip all DSP calculations, huge speedup (the DSP doesn't work correctly right now anyway) (default: True)\nBypassDSP = True\n; Channels: 32 (0-31)\n\n[WSwan]\nDisabled = False\n; Channels: 4 (0-3)\n\n[VSU]\nDisabled = False\n; Channels: 6 (0-5)\n\n[SAA1099]\nDisabled = False\n; Channels: 6 (0-5)\n\n[ES5503]\nDisabled = False\n; Channels: 32 (0-31)\n\n[ES5506]\nDisabled = False\n; Channels: 32 (0-31)\n\n[X1-010]\nDisabled = False\n; Channels: 16 (0-15)\n\n[C352]\nDisabled = False\n; disable rear channels (disregarding the rear enable/disable setting in VGMs)\nDisableRear = False\n; Channels: 32 (0-31)\n\n[GA20]\nDisabled = False\n; Channels: 4 (0-3)\n"
  },
  {
    "path": "VGMPlay/VGMPlay.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 11.00\r\n# Visual Studio 2010\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"VGMPlay\", \"VGMPlay.vcxproj\", \"{8519237F-1B46-4C8A-994C-58D218182F2C}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Win32 = Debug|Win32\r\n\t\tDebug|x64 = Debug|x64\r\n\t\tRelease|Win32 = Release|Win32\r\n\t\tRelease|x64 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{8519237F-1B46-4C8A-994C-58D218182F2C}.Debug|Win32.ActiveCfg = Debug|Win32\r\n\t\t{8519237F-1B46-4C8A-994C-58D218182F2C}.Debug|Win32.Build.0 = Debug|Win32\r\n\t\t{8519237F-1B46-4C8A-994C-58D218182F2C}.Debug|x64.ActiveCfg = Debug|x64\r\n\t\t{8519237F-1B46-4C8A-994C-58D218182F2C}.Debug|x64.Build.0 = Debug|x64\r\n\t\t{8519237F-1B46-4C8A-994C-58D218182F2C}.Release|Win32.ActiveCfg = Release|Win32\r\n\t\t{8519237F-1B46-4C8A-994C-58D218182F2C}.Release|Win32.Build.0 = Release|Win32\r\n\t\t{8519237F-1B46-4C8A-994C-58D218182F2C}.Release|x64.ActiveCfg = Release|x64\r\n\t\t{8519237F-1B46-4C8A-994C-58D218182F2C}.Release|x64.Build.0 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "VGMPlay/VGMPlay.txt",
    "content": "VGM Player - Readme\n==========\n\nGeneral\n=======\nUsage: Drop a file on the executable or open the program and type the filename.\n\nSupported files types are:\n- Video Game Music Files (*.vgm, *.vgz)\n- Creative Music Files (*.cmf)\n- DosBox RAW OPL Log Files (*.dro)\n- Playlist files (*.m3u)\n\nSupported chips\n---------------\n- SN76496** (Sega PSG) and T6W28** (NeoGeo Pocket custom)\n- YM2413* (OPLL)\n- YM2612 (OPN2)\n- YM2151 (OPM)\n- SegaPCM\n- RF5C68\n- YM2203 (OPN)\n- YM2608 (OPNA)\n- YM2610/B (OPNB)\n- YM3812* (OPL2)\n- YM3526* (OPL)\n- Y8950* (MSX AUDIO)\n- YMF262* (OP3)\n- YMF278B (OPL4) !\n- YMF271 (OPLX)\n- YMZ280B\n- RF5C164 (Sega MegaCD PCM)\n- PWM (from Sega 32x)\n- AY8910 (MSX PSG)\n- GameBoy DMG\n- NES APU (incl. FDS)\n- YMW258 (MultiPCM)\n- UPD7759\n- OKI6258 (Sharp X68000 ADPCM)\n- OKI6295\n- K051649\n- K054539\n- HuC6280 (PC Engine)\n- Namco C140\n- K053260\n- Pokey (Atari)\n- QSound\n- SCSP (Saturn Custom Sound Processor, YMF292-F)\n- WonderSwan\n- Virtual Boy VSU\n- SAA1099\n- ESS5503\n- ESS5505/6\n- Seta X1-010\n- Namco C352\n- Irem GA20\n\n\n* This chip can be emulated via OPL Hardware (like Soundblaster sound cards).\n** OPL hardware emulation is available, but software emulation is prefered. Hardware emulation is used if another chip activates HW emulation or FMForce is True.\n! For some songs you need a sample ROM, called yrw801.rom, to make playback work. Place it in the directory of VGMPlay.exe.\n\nOPL hardware emulation can be enabled by setting the \"FMPort\"-entry in the ini-file.\nIf you want to use FM Hardware under Windows NT/2000/XP/... you have to install PortTalk.\nPortTalk Website: http://www.beyondlogic.org/porttalk/porttalk.htm\nUnder Linux the program must have root rights to use Hardware FM.\n\nIt's possible to write Wave-Files by editing the \"LogSound\"-line in the ini-file.\nBatch conversions are possible by opening a playlist.\nFM Hardware can't be logged to Wave files.\n\nKeys\n----\nYou can use the following keys during playback:\nSpace - Pause\nCursor Left/Right - Seek 5 seconds backward/forward\nCtrl + Cursor Left/Right - Seek 1 minute backward/forward\nESC/Q - Quit the program\nF - Fade out\nR - Restart current Track\nPageUp/B - Previous Track\nPageDown/N - Next Track\n\nNote: All keys also work during silent sound logging.\n\n\nSystem Reqiurements\n===================\nIt depends on the files you want to play.\n\nMinimum Reqiurements\n--------------------\nSoftware Emulation:\n\n166 MHz should be enough for SN76496 + YM2612.\nFor chips with 12+ FM channels you need probably need at least 700 MHz.\n16 MB RAM (plus a size of the VGM you want to play, so for a 100 MB vgm, you need ~110 MB RAM)\n\nThat allows you to play VGMs with up to 2x FM, 2x PSG or FM + PSG + PCM.\nIt's NOT enough for YMF271 emulation.\nThe YMF262 is equal to 2x FM. The YMF278B is Wavetable + YMF262 (with the latter one disabled if unused).\n\nHardware FM Playback:\n\n486 with 33 MHz? - I dunno\nOn my PII 233 MHz FM Playback takes 3.5% CPU at a maximum.\n\n\nBugs\n====\nPauseEmulation is disabled under Linux unless FM Hardware is used.\n\nUnder Linux you have to double-tap ESC to quit the program (or just press Q). I haven't yet found a way around it.\n\nSometimes MAME's sound cores tend to sound strange. I already fixed some, but it's not my fault.\n\nUbuntu might refuse to run (or maybe compile) VGMPlay correctly. If so, it either crashes upon opening a vgm file or doesn't open the sound device. (and the ini-file, too. VGMs are opened for some reason.)\nUsing Wine with the Windows-version of VGMPlay should work.\n\nIt runs fine on openSUSE. (I compile and test it regularly with 12.3 64-bit. Older version were successfully tested with 11.1 32-bit and 11.4 64-bit)\nIt also ran fine on the Debian system at university.\n\n\nComments\n========\nIf you want to set some options, open the ini-file. It's well commented.\n\nThe T6W28 doesn't use MAME's T6W28 core. Instead I modified the SN76496 core to emulate the T6W28 with 2 SN76496 chips.\n\nThe SN76496 OPL emulation is okay, but it's impossible to get the noise sound right.\n\nEMU2413 Emulator was added, because sometimes the one of MAME sounds strange.\nI added the Gens YM2612 core for the same reason (before I fixed MAME's YM2612 core).\n\nI haven't yet found a player that supports all three version of dro files.\nP.S.: AdPlug now seems to support them.\n\nSome may be wondering, how someone can have the idea to implement OPL Hardware support. Here a more or less small story:\nI like CMF MIDI files, but I was unable to listen to them while doing other things on my computer in Windows 95. It was impossible to listen to them unter Windows 2000. When I found AdPlug, the CMF support was bad and I started to make my VGM Player play CMF files. Debugging wasn't nice - a Pentium2 233MHz isn't stong enough for a Software OPL Emulator in Debug Mode. The OPL2-Port option in AdPlug was interesting (I have a Soundblaster 16) and showed me the power of PortTalk.\nMy MIDI-FM Player that got OPL-Hardware-Support earlier than my VGM Player, because playing usual MIDI files requires a lot more debugging than playing simple VGM files. When it was working in my MIDI player, I implemented OPL-Hardware-Support into VGMPlay. Of course the first working chips were OPL/OPL2/OPL3. I remembered that Meka had OPL-Support, too and wrote my OPLL->OPL-Mapper. It sounded quite good, but I was unable to get the PSG and the YM2413 of Space Harrier Theme in sync. So a PSG->OPL-Mapper followed. Later I ported Meka's OPL Mapper, because I liked the bass of some Phantasy Star tunes.\n\n\nCredits\n=======\nThis program was written by Valley Bell.\n\n- Special thanks to ctr for major contributions in general.\n- almost all software emulators are from MAME (http://mamedev.org)\n- EMU2413 and Gens YM2612 were ported from Maxim's in_vgm\n- the YMF278B core was ported from openMSX\n- zlib compression by Jean-loup Gailly and Mark Adler is used\n- all custom OPL Mappers were written using MAME software emulators and the OPL2/3 programming guides by Jeffrey S. Lee and Vladimir Arnost\n- one YM2413 OPL Mapper was ported from MEKA.\n- the RF5C164 and PWM cores were ported from Gens/GS\n- the MAME YM2612 core was fixed with the help of Blargg's MAME YM2612 fix and Genesis Plus GX' YM2612 core\n- AdLibEmu (OPL2 and OPL3 core) was ported from DOSBox\n- The default HuC6280 core is from Ootake.\n- EMU2149, the alternative NES APU core and the NES FDS core were ported from rainwarrior's NSFPlay.\n- the WonderSwan core was ported from in_wsr\n- Virtual Boy VSU core was ported from vbjin and originates from mednafen\n- Thanks to grauw for patches that make it work properly on Mac OS X.\n- ctr for writing the new C352 sound core.\n"
  },
  {
    "path": "VGMPlay/VGMPlay.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug|Win32\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|Win32\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Debug|x64\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|x64\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"ChipMapper.h\" />\r\n    <ClInclude Include=\"chips\\2151intf.h\" />\r\n    <ClInclude Include=\"chips\\2203intf.h\" />\r\n    <ClInclude Include=\"chips\\2413intf.h\" />\r\n    <ClInclude Include=\"chips\\2608intf.h\" />\r\n    <ClInclude Include=\"chips\\2610intf.h\" />\r\n    <ClInclude Include=\"chips\\2612intf.h\" />\r\n    <ClInclude Include=\"chips\\262intf.h\" />\r\n    <ClInclude Include=\"chips\\3526intf.h\" />\r\n    <ClInclude Include=\"chips\\3812intf.h\" />\r\n    <ClInclude Include=\"chips\\8950intf.h\" />\r\n    <ClInclude Include=\"chips\\adlibemu.h\" />\r\n    <ClInclude Include=\"chips\\ay8910.h\" />\r\n    <ClInclude Include=\"chips\\ay_intf.h\" />\r\n    <ClInclude Include=\"chips\\c140.h\" />\r\n    <ClInclude Include=\"chips\\c352.h\" />\r\n    <ClInclude Include=\"chips\\c6280.h\" />\r\n    <ClInclude Include=\"chips\\c6280intf.h\" />\r\n    <ClInclude Include=\"chips\\ChipIncl.h\" />\r\n    <ClInclude Include=\"chips\\dac_control.h\" />\r\n    <ClInclude Include=\"chips\\emu2149.h\" />\r\n    <ClInclude Include=\"chips\\emu2413.h\" />\r\n    <ClInclude Include=\"chips\\emutypes.h\" />\r\n    <ClInclude Include=\"chips\\es5503.h\" />\r\n    <ClInclude Include=\"chips\\es5506.h\" />\r\n    <ClInclude Include=\"chips\\fm.h\" />\r\n    <ClInclude Include=\"chips\\fmopl.h\" />\r\n    <ClInclude Include=\"chips\\gb.h\" />\r\n    <ClInclude Include=\"chips\\iremga20.h\" />\r\n    <ClInclude Include=\"chips\\k051649.h\" />\r\n    <ClInclude Include=\"chips\\k053260.h\" />\r\n    <ClInclude Include=\"chips\\k054539.h\" />\r\n    <ClInclude Include=\"chips\\mamedef.h\" />\r\n    <ClInclude Include=\"chips\\multipcm.h\" />\r\n    <ClInclude Include=\"chips\\nes_apu.h\" />\r\n    <ClInclude Include=\"chips\\nes_defs.h\" />\r\n    <ClInclude Include=\"chips\\nes_intf.h\" />\r\n    <ClInclude Include=\"chips\\np_nes_apu.h\" />\r\n    <ClInclude Include=\"chips\\np_nes_dmc.h\" />\r\n    <ClInclude Include=\"chips\\np_nes_fds.h\" />\r\n    <ClInclude Include=\"chips\\okim6258.h\" />\r\n    <ClInclude Include=\"chips\\okim6295.h\" />\r\n    <ClInclude Include=\"chips\\Ootake_PSG.h\" />\r\n    <ClInclude Include=\"chips\\opl.h\" />\r\n    <ClInclude Include=\"chips\\opll.h\" />\r\n    <ClInclude Include=\"chips\\opm.h\" />\r\n    <ClInclude Include=\"chips\\panning.h\" />\r\n    <ClInclude Include=\"chips\\pokey.h\" />\r\n    <ClInclude Include=\"chips\\pwm.h\" />\r\n    <ClInclude Include=\"chips\\qsound_ctr.h\" />\r\n    <ClInclude Include=\"chips\\qsound_intf.h\" />\r\n    <ClInclude Include=\"chips\\qsound_mame.h\" />\r\n    <ClInclude Include=\"chips\\rf5c68.h\" />\r\n    <ClInclude Include=\"chips\\saa1099.h\" />\r\n    <ClInclude Include=\"chips\\scd_pcm.h\" />\r\n    <ClInclude Include=\"chips\\scsp.h\" />\r\n    <ClInclude Include=\"chips\\scspdsp.h\" />\r\n    <ClInclude Include=\"chips\\segapcm.h\" />\r\n    <ClInclude Include=\"chips\\sn76489.h\" />\r\n    <ClInclude Include=\"chips\\sn76496.h\" />\r\n    <ClInclude Include=\"chips\\sn764intf.h\" />\r\n    <ClInclude Include=\"chips\\upd7759.h\" />\r\n    <ClInclude Include=\"chips\\vrc7tone.h\" />\r\n    <ClInclude Include=\"chips\\vsu.h\" />\r\n    <ClInclude Include=\"chips\\ws_audio.h\" />\r\n    <ClInclude Include=\"chips\\ws_initialIo.h\" />\r\n    <ClInclude Include=\"chips\\x1_010.h\" />\r\n    <ClInclude Include=\"chips\\ym2151.h\" />\r\n    <ClInclude Include=\"chips\\ym2413.h\" />\r\n    <ClInclude Include=\"chips\\ym2413hd.h\" />\r\n    <ClInclude Include=\"chips\\ym2612.h\" />\r\n    <ClInclude Include=\"chips\\ym3438.h\" />\r\n    <ClInclude Include=\"chips\\ymdeltat.h\" />\r\n    <ClInclude Include=\"chips\\ymf262.h\" />\r\n    <ClInclude Include=\"chips\\ymf271.h\" />\r\n    <ClInclude Include=\"chips\\ymf278b.h\" />\r\n    <ClInclude Include=\"chips\\ymz280b.h\" />\r\n    <ClInclude Include=\"dbus.h\" />\r\n    <ClInclude Include=\"mmkeys.h\" />\r\n    <ClInclude Include=\"PortTalk_IOCTL.h\" />\r\n    <ClInclude Include=\"Stream.h\" />\r\n    <ClInclude Include=\"VGMFile.h\" />\r\n    <ClInclude Include=\"VGMPlay.h\" />\r\n    <ClInclude Include=\"VGMPlay_Intf.h\" />\r\n    <ClInclude Include=\"XMasFiles\\SWJ-SQRC01_1C.h\" />\r\n    <ClInclude Include=\"XMasFiles\\XMasBonus.h\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"ChipMapper.c\" />\r\n    <ClCompile Include=\"chips\\2151intf.c\" />\r\n    <ClCompile Include=\"chips\\2203intf.c\" />\r\n    <ClCompile Include=\"chips\\2413intf.c\" />\r\n    <ClCompile Include=\"chips\\2608intf.c\" />\r\n    <ClCompile Include=\"chips\\2610intf.c\" />\r\n    <ClCompile Include=\"chips\\2612intf.c\" />\r\n    <ClCompile Include=\"chips\\262intf.c\" />\r\n    <ClCompile Include=\"chips\\3526intf.c\" />\r\n    <ClCompile Include=\"chips\\3812intf.c\" />\r\n    <ClCompile Include=\"chips\\8950intf.c\" />\r\n    <ClCompile Include=\"chips\\adlibemu_opl2.c\" />\r\n    <ClCompile Include=\"chips\\adlibemu_opl3.c\" />\r\n    <ClCompile Include=\"chips\\ay8910.c\" />\r\n    <ClCompile Include=\"chips\\ay8910_opl.c\" />\r\n    <ClCompile Include=\"chips\\ay_intf.c\" />\r\n    <ClCompile Include=\"chips\\c140.c\" />\r\n    <ClCompile Include=\"chips\\c352.c\" />\r\n    <ClCompile Include=\"chips\\c6280.c\" />\r\n    <ClCompile Include=\"chips\\c6280intf.c\" />\r\n    <ClCompile Include=\"chips\\dac_control.c\" />\r\n    <ClCompile Include=\"chips\\emu2149.c\" />\r\n    <ClCompile Include=\"chips\\emu2413.c\" />\r\n    <ClCompile Include=\"chips\\es5503.c\" />\r\n    <ClCompile Include=\"chips\\es5506.c\" />\r\n    <ClCompile Include=\"chips\\fm.c\" />\r\n    <ClCompile Include=\"chips\\fm2612.c\" />\r\n    <ClCompile Include=\"chips\\fmopl.c\" />\r\n    <ClCompile Include=\"chips\\gb.c\" />\r\n    <ClCompile Include=\"chips\\iremga20.c\" />\r\n    <ClCompile Include=\"chips\\k051649.c\" />\r\n    <ClCompile Include=\"chips\\k053260.c\" />\r\n    <ClCompile Include=\"chips\\k054539.c\" />\r\n    <ClCompile Include=\"chips\\multipcm.c\" />\r\n    <ClCompile Include=\"chips\\nes_apu.c\" />\r\n    <ClCompile Include=\"chips\\nes_intf.c\" />\r\n    <ClCompile Include=\"chips\\np_nes_apu.c\" />\r\n    <ClCompile Include=\"chips\\np_nes_dmc.c\" />\r\n    <ClCompile Include=\"chips\\np_nes_fds.c\" />\r\n    <ClCompile Include=\"chips\\okim6258.c\" />\r\n    <ClCompile Include=\"chips\\okim6295.c\" />\r\n    <ClCompile Include=\"chips\\Ootake_PSG.c\" />\r\n    <ClCompile Include=\"chips\\opl.c\">\r\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</ExcludedFromBuild>\r\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">true</ExcludedFromBuild>\r\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">true</ExcludedFromBuild>\r\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">true</ExcludedFromBuild>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\opll.c\" />\r\n    <ClCompile Include=\"chips\\opm.c\" />\r\n    <ClCompile Include=\"chips\\panning.c\" />\r\n    <ClCompile Include=\"chips\\pokey.c\" />\r\n    <ClCompile Include=\"chips\\pwm.c\" />\r\n    <ClCompile Include=\"chips\\qsound_ctr.c\" />\r\n    <ClCompile Include=\"chips\\qsound_intf.c\" />\r\n    <ClCompile Include=\"chips\\qsound_mame.c\" />\r\n    <ClCompile Include=\"chips\\rf5c68.c\" />\r\n    <ClCompile Include=\"chips\\saa1099.c\" />\r\n    <ClCompile Include=\"chips\\scd_pcm.c\" />\r\n    <ClCompile Include=\"chips\\scsp.c\" />\r\n    <ClCompile Include=\"chips\\scspdsp.c\" />\r\n    <ClCompile Include=\"chips\\scsplfo.c\">\r\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</ExcludedFromBuild>\r\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">true</ExcludedFromBuild>\r\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">true</ExcludedFromBuild>\r\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">true</ExcludedFromBuild>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\segapcm.c\" />\r\n    <ClCompile Include=\"chips\\sn76489.c\" />\r\n    <ClCompile Include=\"chips\\sn76496.c\" />\r\n    <ClCompile Include=\"chips\\sn76496_opl.c\" />\r\n    <ClCompile Include=\"chips\\sn764intf.c\" />\r\n    <ClCompile Include=\"chips\\upd7759.c\" />\r\n    <ClCompile Include=\"chips\\vsu.c\" />\r\n    <ClCompile Include=\"chips\\ws_audio.c\" />\r\n    <ClCompile Include=\"chips\\x1_010.c\" />\r\n    <ClCompile Include=\"chips\\ym2151.c\" />\r\n    <ClCompile Include=\"chips\\ym2413.c\" />\r\n    <ClCompile Include=\"chips\\ym2413hd.c\" />\r\n    <ClCompile Include=\"chips\\ym2413_opl.c\" />\r\n    <ClCompile Include=\"chips\\ym2612.c\" />\r\n    <ClCompile Include=\"chips\\ym3438.c\" />\r\n    <ClCompile Include=\"chips\\ymdeltat.c\" />\r\n    <ClCompile Include=\"chips\\ymf262.c\" />\r\n    <ClCompile Include=\"chips\\ymf271.c\" />\r\n    <ClCompile Include=\"chips\\ymf278b.c\" />\r\n    <ClCompile Include=\"chips\\ymz280b.c\" />\r\n    <ClCompile Include=\"dbus_stub.c\" />\r\n    <ClCompile Include=\"mmkeys_Win.c\" />\r\n    <ClCompile Include=\"pt_ioctl.c\" />\r\n    <ClCompile Include=\"Stream.c\" />\r\n    <ClCompile Include=\"VGMPlay.c\" />\r\n    <ClCompile Include=\"VGMPlayUI.c\" />\r\n    <ClCompile Include=\"VGMPlay_AddFmts.c\" />\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <VCProjectVersion>15.0</VCProjectVersion>\r\n    <ProjectGuid>{8519237F-1B46-4C8A-994C-58D218182F2C}</ProjectGuid>\r\n    <Keyword>Win32Proj</Keyword>\r\n    <RootNamespace>VGMPlay</RootNamespace>\r\n    <WindowsTargetPlatformVersion>7.0</WindowsTargetPlatformVersion>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v100</PlatformToolset>\r\n    <CharacterSet>MultiByte</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <PlatformToolset>v100</PlatformToolset>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>MultiByte</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v100</PlatformToolset>\r\n    <CharacterSet>MultiByte</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <PlatformToolset>v100</PlatformToolset>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>MultiByte</CharacterSet>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\">\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"Shared\">\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <IncludePath>$(ProjectDir)zlib;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(ProjectDir)zlib;$(LibraryPath)</LibraryPath>\r\n    <OutDir>$(SolutionDir)$(Configuration)_Win32\\</OutDir>\r\n    <IntDir>$(Configuration)_Win32\\</IntDir>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <IncludePath>$(ProjectDir)zlib;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(ProjectDir)zlib;$(LibraryPath)</LibraryPath>\r\n    <OutDir>$(SolutionDir)$(Configuration)_Win64\\</OutDir>\r\n    <IntDir>$(Configuration)_Win64\\</IntDir>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <IncludePath>$(ProjectDir)zlib;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(ProjectDir)zlib;$(LibraryPath)</LibraryPath>\r\n    <OutDir>$(SolutionDir)$(Configuration)_Win32\\</OutDir>\r\n    <IntDir>$(Configuration)_Win32\\</IntDir>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <IncludePath>$(ProjectDir)zlib;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(ProjectDir)zlib;$(LibraryPath)</LibraryPath>\r\n    <OutDir>$(SolutionDir)$(Configuration)_Win64\\</OutDir>\r\n    <IntDir>$(Configuration)_Win64\\</IntDir>\r\n  </PropertyGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <Optimization>Disabled</Optimization>\r\n      <PreprocessorDefinitions>VGM_LITTLE_ENDIAN;ENABLE_ALL_CORES;CONSOLE_MODE;ADDITIONAL_FORMATS;SET_CONSOLE_TITLE;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;winmm.lib;zdll.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <Optimization>Disabled</Optimization>\r\n      <PreprocessorDefinitions>VGM_LITTLE_ENDIAN;ENABLE_ALL_CORES;CONSOLE_MODE;ADDITIONAL_FORMATS;SET_CONSOLE_TITLE;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;winmm.lib;zlibstat64d.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <PreprocessorDefinitions>VGM_LITTLE_ENDIAN;ENABLE_ALL_CORES;CONSOLE_MODE;ADDITIONAL_FORMATS;SET_CONSOLE_TITLE;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;winmm.lib;zdll.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <PreprocessorDefinitions>VGM_LITTLE_ENDIAN;ENABLE_ALL_CORES;CONSOLE_MODE;ADDITIONAL_FORMATS;SET_CONSOLE_TITLE;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;winmm.lib;zlibstat64.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\">\r\n  </ImportGroup>\r\n</Project>"
  },
  {
    "path": "VGMPlay/VGMPlay.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <Filter Include=\"Quelldateien\">\r\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\r\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"Headerdateien\">\r\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\r\n      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"Ressourcendateien\">\r\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\r\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"SoundCore\">\r\n      <UniqueIdentifier>{d92e176a-b6da-4926-ac77-9285e175b450}</UniqueIdentifier>\r\n      <Extensions>c;h;cpp</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"SoundCore\\FM OPN Chips\">\r\n      <UniqueIdentifier>{7b8c14e4-98d2-494e-8eeb-102684e2b0d8}</UniqueIdentifier>\r\n      <Extensions>c;h</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"SoundCore\\FM OPx Chips\">\r\n      <UniqueIdentifier>{b7d46055-4043-4069-8dfd-cd0614f24cb8}</UniqueIdentifier>\r\n      <Extensions>c;h</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"SoundCore\\PCM Chips\">\r\n      <UniqueIdentifier>{5f79bd0e-fae5-4188-8c92-06c81891c82c}</UniqueIdentifier>\r\n      <Extensions>c;h</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"SoundCore\\OPL Mapper\">\r\n      <UniqueIdentifier>{a8502cef-6a14-45a9-b505-818f39601a20}</UniqueIdentifier>\r\n      <Extensions>c;h</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"SoundCore\\PSG Chips\">\r\n      <UniqueIdentifier>{b0a32a39-96e4-4b81-92ca-fff506eb2b1e}</UniqueIdentifier>\r\n      <Extensions>c;h</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"SoundCore\\NES Chips\">\r\n      <UniqueIdentifier>{c2ae641c-5a5a-41d2-8a54-e5caa03cd919}</UniqueIdentifier>\r\n      <Extensions>c;h</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"SoundCore\\FM OPL Chips\">\r\n      <UniqueIdentifier>{8e35abaa-f8c4-43f7-8fe0-e17fefb8c132}</UniqueIdentifier>\r\n      <Extensions>c;h</Extensions>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"PortTalk_IOCTL.h\">\r\n      <Filter>Headerdateien</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Stream.h\">\r\n      <Filter>Headerdateien</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"VGMFile.h\">\r\n      <Filter>Headerdateien</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"VGMPlay.h\">\r\n      <Filter>Headerdateien</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"VGMPlay_Intf.h\">\r\n      <Filter>Headerdateien</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"XMasFiles\\SWJ-SQRC01_1C.h\">\r\n      <Filter>Headerdateien</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"XMasFiles\\XMasBonus.h\">\r\n      <Filter>Headerdateien</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ChipIncl.h\">\r\n      <Filter>SoundCore</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\dac_control.h\">\r\n      <Filter>SoundCore</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\mamedef.h\">\r\n      <Filter>SoundCore</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\panning.h\">\r\n      <Filter>SoundCore</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ChipMapper.h\">\r\n      <Filter>SoundCore</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\2413intf.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\262intf.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\adlibemu.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\emu2413.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\emutypes.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\fmopl.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\opl.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ym2413.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ymf262.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ymf278b.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\vrc7tone.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\3526intf.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\3812intf.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\8950intf.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\2203intf.h\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\2608intf.h\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\2610intf.h\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\2612intf.h\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\fm.h\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ym2612.h\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ym3438.h\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\2151intf.h\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\scsp.h\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\scspdsp.h\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ym2151.h\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ymf271.h\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\c140.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\c352.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\es5503.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\es5506.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\iremga20.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\k053260.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\k054539.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\multipcm.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\okim6258.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\okim6295.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\pwm.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\qsound_ctr.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\qsound_intf.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\qsound_mame.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\rf5c68.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\scd_pcm.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\segapcm.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\upd7759.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\x1_010.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ymdeltat.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ymz280b.h\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ym2413hd.h\">\r\n      <Filter>SoundCore\\OPL Mapper</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ay_intf.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ay8910.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\c6280.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\c6280intf.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\emu2149.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\gb.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\k051649.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\Ootake_PSG.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\pokey.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\saa1099.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\sn76489.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\sn76496.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\sn764intf.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\vsu.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ws_audio.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\ws_initialIo.h\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\nes_apu.h\">\r\n      <Filter>SoundCore\\NES Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\nes_defs.h\">\r\n      <Filter>SoundCore\\NES Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\nes_intf.h\">\r\n      <Filter>SoundCore\\NES Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\np_nes_apu.h\">\r\n      <Filter>SoundCore\\NES Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\np_nes_dmc.h\">\r\n      <Filter>SoundCore\\NES Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\np_nes_fds.h\">\r\n      <Filter>SoundCore\\NES Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"dbus.h\">\r\n      <Filter>Headerdateien</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"mmkeys.h\">\r\n      <Filter>Headerdateien</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\opll.h\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"chips\\opm.h\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"pt_ioctl.c\">\r\n      <Filter>Quelldateien</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Stream.c\">\r\n      <Filter>Quelldateien</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"VGMPlay.c\">\r\n      <Filter>Quelldateien</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"VGMPlay_AddFmts.c\">\r\n      <Filter>Quelldateien</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"VGMPlayUI.c\">\r\n      <Filter>Quelldateien</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\dac_control.c\">\r\n      <Filter>SoundCore</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\panning.c\">\r\n      <Filter>SoundCore</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ChipMapper.c\">\r\n      <Filter>SoundCore</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\2413intf.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\262intf.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\adlibemu_opl2.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\adlibemu_opl3.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\emu2413.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\fmopl.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\opl.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ym2413.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ymf262.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ymf278b.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\3526intf.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\3812intf.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\8950intf.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\2203intf.c\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\2608intf.c\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\2610intf.c\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\2612intf.c\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\fm.c\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\fm2612.c\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ym2612.c\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ym3438.c\">\r\n      <Filter>SoundCore\\FM OPN Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\2151intf.c\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\scsp.c\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\scspdsp.c\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\scsplfo.c\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ym2151.c\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ymf271.c\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\c140.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\c352.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\es5503.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\es5506.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\iremga20.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\k053260.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\k054539.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\multipcm.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\okim6258.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\okim6295.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\pwm.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\qsound_ctr.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\qsound_intf.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\qsound_mame.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\rf5c68.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\scd_pcm.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\segapcm.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\upd7759.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\x1_010.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ymdeltat.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ymz280b.c\">\r\n      <Filter>SoundCore\\PCM Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ay8910_opl.c\">\r\n      <Filter>SoundCore\\OPL Mapper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\sn76496_opl.c\">\r\n      <Filter>SoundCore\\OPL Mapper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ym2413_opl.c\">\r\n      <Filter>SoundCore\\OPL Mapper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ym2413hd.c\">\r\n      <Filter>SoundCore\\OPL Mapper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ay_intf.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ay8910.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\c6280.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\c6280intf.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\emu2149.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\gb.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\k051649.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\Ootake_PSG.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\pokey.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\saa1099.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\sn76489.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\sn76496.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\sn764intf.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\vsu.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\ws_audio.c\">\r\n      <Filter>SoundCore\\PSG Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\nes_apu.c\">\r\n      <Filter>SoundCore\\NES Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\nes_intf.c\">\r\n      <Filter>SoundCore\\NES Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\np_nes_apu.c\">\r\n      <Filter>SoundCore\\NES Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\np_nes_dmc.c\">\r\n      <Filter>SoundCore\\NES Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\np_nes_fds.c\">\r\n      <Filter>SoundCore\\NES Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"dbus_stub.c\">\r\n      <Filter>Quelldateien</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"mmkeys_Win.c\">\r\n      <Filter>Quelldateien</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\opll.c\">\r\n      <Filter>SoundCore\\FM OPL Chips</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"chips\\opm.c\">\r\n      <Filter>SoundCore\\FM OPx Chips</Filter>\r\n    </ClCompile>\r\n  </ItemGroup>\r\n</Project>"
  },
  {
    "path": "VGMPlay/VGMPlayUI.c",
    "content": "// VGMPlayUI.c: C Source File for the Console User Interface\n\n// Note: In order to make MS VC6 NOT crash when using fprintf with stdout, stderr, etc.\n//\t\t if linked to msvcrt.lib, the following project setting is important:\n//\t\t C/C++ -> Code Generation -> Runtime libraries: Multithreaded DLL\n\n#define _GNU_SOURCE\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <stdarg.h>\n#include <wchar.h>\n#include <ctype.h>\t// for toupper\n#include <locale.h>\t// for setlocale\n#include \"stdbool.h\"\n#include <math.h>\n\n#ifdef WIN32\n#include <conio.h>\n#include <windows.h>\n#else\n#include <limits.h>\t// for PATH_MAX\n#include <termios.h>\n#include <unistd.h>\t// for STDIN_FILENO and usleep()\n#include <sys/time.h>\t// for struct timeval in _kbhit()\n#include <signal.h> // for signal()\n#include <sys/select.h> // for select()\n\n#define\tSleep(msec)\tusleep(msec * 1000)\n#define _vsnwprintf\tvswprintf\n#endif\n\n#define printerr(x)\tfprintf(stderr, x)\n\n#include \"chips/mamedef.h\"\n\n#include \"Stream.h\"\n#include \"VGMPlay.h\"\n#include \"VGMPlay_Intf.h\"\n#include \"mmkeys.h\"\n#include \"dbus.h\"\n\n#ifdef XMAS_EXTRA\n#include \"XMasFiles/XMasBonus.h\"\n#endif\n#ifdef WS_DEMO\n#include \"XMasFiles/SWJ-SQRC01_1C.h\"\n#endif\n\n#ifndef WIN32\nvoid WaveOutLinuxCallBack(void);\n#endif\n\n#ifdef WIN32\n#define DIR_CHR\t\t'\\\\'\n#define DIR_STR\t\t\"\\\\\"\n#define QMARK_CHR\t'\\\"'\n#else\n#define DIR_CHR\t\t'/'\n#define DIR_STR\t\t\"/\"\n#define QMARK_CHR\t'\\''\n\n#ifndef SHARE_PREFIX\n#define SHARE_PREFIX\t\"/usr/local\"\n#endif\n\n#endif\n\n#define APP_NAME\t\"VGM Player\"\n#define APP_NAME_L\tL\"VGM Player\"\n\n\nint main(int argc, char* argv[]);\nstatic void RemoveNewLines(char* String);\nstatic void RemoveQuotationMarks(char* String);\nchar* GetLastDirSeparator(const char* FilePath);\nstatic bool IsAbsolutePath(const char* FilePath);\nstatic char* GetFileExtension(const char* FilePath);\nstatic void StandardizeDirSeparators(char* FilePath);\n#ifdef WIN32\nstatic void WinNT_Check(void);\n#endif\nstatic char* GetAppFileName(void);\nstatic void cls(void);\n#ifndef WIN32\nstatic void changemode(bool);\nstatic int _kbhit(void);\nstatic int _getch(void);\n#endif\nstatic INT8 stricmp_u(const char *string1, const char *string2);\nstatic INT8 strnicmp_u(const char *string1, const char *string2, size_t count);\nstatic void ReadOptions(const char* AppName);\nstatic bool GetBoolFromStr(const char* TextStr);\n#if defined(XMAS_EXTRA) || defined(WS_DEMO)\nstatic bool XMas_Extra(char* FileName, bool Mode);\n#endif\n#ifndef WIN32\nstatic void ConvertCP1252toUTF8(char** DstStr, const char* SrcStr);\n#endif\nstatic bool OpenPlayListFile(const char* FileName);\nstatic bool OpenMusicFile(const char* FileName);\nextern bool OpenVGMFile(const char* FileName);\nextern bool OpenOtherFile(const char* FileName);\n\nstatic void wprintc(const wchar_t* format, ...);\nstatic void PrintChipStr(UINT8 ChipID, UINT8 SubType, UINT32 Clock);\nconst wchar_t* GetTagStrEJ(const wchar_t* EngTag, const wchar_t* JapTag);\nstatic void ShowVGMTag(void);\n\nstatic void MMKey_Event(UINT8 event);\nstatic void PlayVGM_UI(void);\nINLINE INT8 sign(double Value);\nINLINE long int Round(double Value);\nINLINE double RoundSpecial(double Value, double RoundTo);\nstatic void PrintMinSec(UINT32 SamplePos, UINT32 SmplRate);\n\n\n// Options Variables\nextern UINT32 SampleRate;\t// Note: also used by some sound cores to\n\t\t\t\t\t\t\t//       determinate the chip sample rate\n\nextern UINT32 VGMPbRate;\nextern UINT32 VGMMaxLoop;\nextern UINT32 CMFMaxLoop;\nUINT32 FadeTimeN;\t// normal fade time\nUINT32 FadeTimePL;\t// in-playlist fade time\nextern UINT32 FadeTime;\nUINT32 PauseTimeJ;\t// Pause Time for Jingles\nUINT32 PauseTimeL;\t// Pause Time for Looping Songs\nextern UINT32 PauseTime;\nstatic UINT8 Show95Cmds;\n\nextern float VolumeLevel;\nextern bool SurroundSound;\nextern UINT8 HardStopOldVGMs;\nextern bool FadeRAWLog;\nstatic UINT8 LogToWave;\n//extern bool FullBufFill;\nextern bool PauseEmulate;\nextern bool DoubleSSGVol;\nstatic UINT16 ForceAudioBuf;\nstatic UINT8 OutputDevID;\n\nextern UINT8 ResampleMode;\t// 00 - HQ both, 01 - LQ downsampling, 02 - LQ both\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\n\nextern UINT16 FMPort;\nextern bool UseFM;\nextern bool FMForce;\n//extern bool FMAccurate;\nextern bool FMBreakFade;\nextern float FMVol;\nextern bool FMOPL2Pan;\n\nextern CHIPS_OPTION ChipOpts[0x02];\n\n\nextern bool ThreadPauseEnable;\nextern volatile bool ThreadPauseConfrm;\nextern bool ThreadNoWait;\t// don't reset the timer\nextern UINT16 AUDIOBUFFERU;\nextern UINT32 SMPL_P_BUFFER;\nextern char SoundLogFile[MAX_PATH];\n\nextern UINT8 OPL_MODE;\nextern UINT8 OPL_CHIPS;\n//extern bool WINNT_MODE;\nUINT8 NEED_LARGE_AUDIOBUFS;\n\nextern char* AppPaths[8];\nstatic char AppPathBuffer[MAX_PATH * 2];\n\nstatic char PLFileBase[MAX_PATH];\nchar PLFileName[MAX_PATH];\nUINT32 PLFileCount;\nstatic char** PlayListFile;\nUINT32 CurPLFile;\nstatic UINT8 NextPLCmd;\nUINT8 PLMode;\t// set to 1 to show Playlist text\nstatic bool FirstInit;\nextern bool AutoStopSkip;\n\nstatic UINT8 lastMMEvent = 0x00;\n\nchar VgmFileName[MAX_PATH];\nstatic UINT8 FileMode;\nextern VGM_HEADER VGMHead;\nextern UINT32 VGMDataLen;\nextern UINT8* VGMData;\nextern GD3_TAG VGMTag;\nstatic bool PreferJapTag;\n\nextern volatile bool PauseThread;\nstatic bool StreamStarted;\n\nextern float MasterVol;\n\nextern UINT32 VGMPos;\nextern INT32 VGMSmplPos;\nextern INT32 VGMSmplPlayed;\nextern INT32 VGMSampleRate;\nextern UINT32 BlocksSent;\nextern UINT32 BlocksPlayed;\nstatic bool IsRAWLog;\nextern bool EndPlay;\nextern bool PausePlay;\nextern bool FadePlay;\nextern bool ForceVGMExec;\nextern UINT8 PlayingMode;\n\nextern UINT32 PlayingTime;\n\nextern UINT32 FadeStart;\nextern UINT32 VGMMaxLoopM;\nextern UINT32 VGMCurLoop;\nextern float VolumeLevelM;\nbool ErrorHappened;\t// used by VGMPlay.c and VGMPlay_AddFmts.c\nextern float FinalVol;\nextern bool ResetPBTimer;\n\n#ifndef WIN32\nstatic struct termios oldterm;\nstatic bool termmode;\n#endif\nstatic volatile bool sigint = false;\n\nUINT8 CmdList[0x100];\n\n//extern UINT8 DISABLE_YMZ_FIX;\nextern UINT8 IsVGMInit;\nextern UINT16 Last95Drum;\t// for optvgm debugging\nextern UINT16 Last95Max;\t// for optvgm debugging\nextern UINT32 Last95Freq;\t// for optvgm debugging\n\nstatic bool PrintMSHours;\n\n#ifdef WIN32\nstatic BOOL WINAPI signal_handler(DWORD dwCtrlType)\n{\n\tswitch(dwCtrlType)\n\t{\n\tcase CTRL_C_EVENT:\t\t// Ctrl + C\n\tcase CTRL_CLOSE_EVENT:\t// close console window via X button\n\tcase CTRL_BREAK_EVENT:\t// Ctrl + Break\n\t\tsigint = true;\n\t\treturn TRUE;\n\tcase CTRL_LOGOFF_EVENT:\n\tcase CTRL_SHUTDOWN_EVENT:\n\t\treturn FALSE;\n\t}\n\treturn FALSE;\n}\n#else\nstatic void signal_handler(int signal)\n{\n\tif(signal == SIGINT || signal == SIGTERM || signal == SIGHUP)\n\t\tsigint = true;\n}\n#endif\n\nint main(int argc, char* argv[])\n{\n\tint argbase;\n\tint ErrRet;\n\tchar* AppName;\n#if defined(XMAS_EXTRA) || defined(WS_DEMO)\n\tbool XMasEnable;\n#endif\n\tchar* AppPathPtr;\n\tconst char* StrPtr;\n\tconst char* FileExt;\n\tUINT8 CurPath;\n\tUINT32 ChrPos;\n\tchar* DispFileName;\n\t\n\t// set locale to \"current system locale\"\n\t// (makes Unicode characters (like umlauts) work under Linux and fixes some\n\t//  Unicode -> ANSI conversions)\n\tsetlocale(LC_CTYPE, \"\");\n\t\n#ifndef WIN32\n\ttcgetattr(STDIN_FILENO, &oldterm);\n\ttermmode = false;\n\tsignal(SIGINT, signal_handler);\n\tsignal(SIGTERM, signal_handler);\n\tsignal(SIGHUP, signal_handler);\n#else\n\tSetConsoleCtrlHandler(signal_handler, TRUE);\n#endif\n\t\n\tif (argc > 1)\n\t{\n\t\tif (! stricmp_u(argv[1], \"-v\") || ! stricmp_u(argv[1], \"--version\"))\n\t\t{\n\t\t\tprintf(\"VGMPlay %s\"\n#if defined(APLHA)\n\t\t\t\t\t\" alpha\"\n#elif defined(BETA)\n\t\t\t\t\t\" beta\"\n#endif\n\t\t\t\t\t\", supports VGM %s\\n\", VGMPLAY_VER_STR, VGM_VER_STR);\n\t\t\treturn 0;\n\t\t}\n\t}\n\t\n#ifdef SET_CONSOLE_TITLE\n#ifdef WIN32\n\tSetConsoleTitle(APP_NAME);\t\t\t// Set Windows Console Title\n#else\n\tprintf(\"\\x1B]0;%s\\x07\", APP_NAME);\t// Set xterm/rxvt Terminal Title\n#endif\n#endif\n\t\n\tprintf(APP_NAME);\n#ifdef XMAS_EXTRA\n\tprintf(\" - XMas Release\");\n#endif\n\tprintf(\"\\n----------\\n\");\n\t\n\t//if (argv[0x00] == NULL)\n\t//\tprintf(\"Argument \\\"Application-Name\\\" is NULL!\\n\");\n\t\n\t// Warning! It's dangerous to use Argument 0!\n\t// AppName may be \"vgmplay\" instead of \"vgmplay.exe\"\n\t\n\tVGMPlay_Init();\n\t\n\t// Note: Paths are checked from last to first.\n\tCurPath = 0x00;\n\tAppPathPtr = AppPathBuffer;\n#ifndef WIN32\n\t// Path 1: global share directory\n\tAppPaths[CurPath] = SHARE_PREFIX \"/share/vgmplay/\";\n\tCurPath ++;\n#endif\n\t\n\t// Path 2: exe's directory\n\tAppName = GetAppFileName();\t// \"C:\\VGMPlay\\VGMPlay.exe\"\n\t// Note: GetAppFileName always returns native directory separators.\n\tStrPtr = strrchr(AppName, DIR_CHR);\n\tif (StrPtr != NULL)\n\t{\n\t\tChrPos = StrPtr + 1 - AppName;\n\t\tstrncpy(AppPathPtr, AppName, ChrPos);\n\t\tAppPathPtr[ChrPos] = 0x00;\t// \"C:\\VGMPlay\\\"\n\t\tAppPaths[CurPath] = AppPathPtr;\n\t\tCurPath ++;\n\t\tAppPathPtr += ChrPos + 1;\n\t}\n\t\n#ifndef WIN32\n\t// Path 3: home directory\n\tStrPtr = getenv(\"XDG_CONFIG_HOME\");\n\tif (StrPtr != NULL && StrPtr[0] == '\\0')\n\t{\n\t\tstrcpy(AppPathPtr, StrPtr);\n\t}\n\telse\n\t{\n\t\tStrPtr = getenv(\"HOME\");\n\t\tif (StrPtr != NULL)\n\t\t\tstrcpy(AppPathPtr, StrPtr);\n\t\telse\n\t\t\tstrcpy(AppPathPtr, \"\");\n\t\tstrcat(AppPathPtr, \"/.config\");\n\t}\n\tstrcat(AppPathPtr, \"/vgmplay/\");\n\tAppPaths[CurPath] = AppPathPtr;\n\tCurPath ++;\n\tAppPathPtr += strlen(AppPathPtr) + 1;\n#endif\n\t\n\t// Path 4: working directory (\"\\0\")\n\tAppPathPtr[0] = '\\0';\n\tAppPaths[CurPath] = AppPathPtr;\n\tCurPath ++;\n\t\n#if 0\t// set to 1 to print all selected search paths\n\tCurPath = 0;\n\twhile(AppPaths[CurPath] != NULL)\n\t{\n\t\tprintf(\"Path %u: %s\\n\", CurPath + 1, AppPaths[CurPath]);\n\t\tCurPath ++;\n\t}\n#endif\n\t\n\tReadOptions(AppName);\n\tVGMPlay_Init2();\n\n\tMultimediaKeyHook_Init();\n\tMultimediaKeyHook_SetCallback(&MMKey_Event);\n\t\n\tErrRet = 0;\n\targbase = 0x01;\n\twhile(argbase < argc)\n\t{\n\t\tif (! strnicmp_u(argv[argbase], \"-LogSound:\", 10))\n\t\t{\n\t\t\tLogToWave = (UINT8)strtoul(argv[argbase] + 10, NULL, 0);\n\t\t\targbase ++;\n\t\t}\n\t\telse if (! strnicmp_u(argv[argbase], \"-DeviceId:\", 10))\n\t\t{\n\t\t\tOutputDevID = (UINT8)strtoul(argv[argbase] + 10, NULL, 0);\n\t\t\targbase ++;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tprintf(\"\\nFile Name:\\t\");\n\tif (argc <= argbase)\n\t{\n#ifdef WIN32\n\t\tINT32 OldCP;\n\t\t\n\t\tOldCP = GetConsoleCP();\n\t\t\n\t\t// Set the Console Input Codepage to ANSI.\n\t\t// The Output Codepage must be left at OEM, else the displayed characters are wrong.\n\t\tChrPos = GetACP();\n\t\tErrRet = SetConsoleCP(ChrPos);\t\t\t// set input codepage\n\t\t//ErrRet = SetConsoleOutputCP(ChrPos);\t// set output codepage (would be a bad idea)\n\t\t\n\t\tStrPtr = fgets(VgmFileName, MAX_PATH, stdin);\n\t\tif (StrPtr == NULL)\n\t\t\tVgmFileName[0] = '\\0';\n\t\t\n\t\t// Playing with the console font resets the Console Codepage to OEM, so I have to\n\t\t// convert the file name in this case.\n\t\tif (GetConsoleCP() == GetOEMCP())\n\t\t\tOemToChar(VgmFileName, VgmFileName);\t// OEM -> ANSI conversion\n\t\t\n\t\t// This fixes the display of non-ANSI characters.\n\t\tErrRet = SetConsoleCP(OldCP);\n\t\t\n\t\t// This codepage stuff drives me insane.\n\t\t// Debug and Release build behave differently - WHAT??\n\t\t//\n\t\t// There a list of behaviours.\n\t\t// Debug and Release were tested by dropping a file on it and via Visual Studio.\n\t\t//\n\t\t// Input CP 850, Output CP 850\n\t\t//\tDebug build:\tDynamite D³x\n\t\t//\tRelease build:\tDynamite Düx\n\t\t// Input CP 1252, Output CP 850\n\t\t//\tDebug build:\tDynamite D³x\n\t\t//\tRelease build:\tDynamite D³x\n\t\t// Input CP 850, Output CP 1252\n\t\t//\tDebug build:\tDynamite D³x [tag display wrong]\n\t\t//\tRelease build:\tDynamite Düx [tag display wrong]\n\t\t// Input CP 1252, Output CP 1252\n\t\t//\tDebug build:\tDynamite D³x [tag display wrong]\n\t\t//\tRelease build:\tDynamite D³x [tag display wrong]\n#else\n\t\tfflush(stdout);\n\t\twhile(1)\n\t\t{\n\t\t\tfd_set fds;\n\t\t\tFD_ZERO(&fds);\n\t\t\tFD_SET(fileno(stdin), &fds);\n\t\t\tstruct timeval tv = {0, 10};\n\t\t\tint sel_ret = select(1, &fds, NULL, NULL, &tv);\n\t\t\tif(sel_ret == -1)\n\t\t\t\tbreak;\n\t\t\telse if(!sel_ret)\n\t\t\t{\n\t\t\t\tDBus_ReadWriteDispatch();\n\t\t\t\t// If ^C has been pressed, quit immediately\n\t\t\t\tif(sigint)\n\t\t\t\t{\n\t\t\t\t\tprintf(\"\\n\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tStrPtr = fgets(VgmFileName, MAX_PATH, stdin);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (StrPtr == NULL)\n\t\t\tVgmFileName[0] = '\\0';\n#endif\n\t\t\n\t\tRemoveNewLines(VgmFileName);\n\t\tRemoveQuotationMarks(VgmFileName);\n\t}\n\telse\n\t{\n\t\t// The argument should already use the ANSI codepage.\n\t\tstrcpy(VgmFileName, argv[argbase]);\n\t\tDispFileName = GetLastDirSeparator(VgmFileName);\n\t\tif(DispFileName && strlen(DispFileName) > 2)\n\t\t\tDispFileName++;\n\t\telse\n\t\t\tDispFileName = VgmFileName;\n\t\tprintf(\"%s\\n\", DispFileName);\n\t}\n\tif (! strlen(VgmFileName))\n\t\tgoto ExitProgram;\n\tStandardizeDirSeparators(VgmFileName);\n\t\n#if defined(XMAS_EXTRA) || defined(WS_DEMO)\n\tXMasEnable = XMas_Extra(VgmFileName, 0x00);\n#endif\n\t\n#if 0\n\t{\t// Print hex characters of file name (for vgm-player script debugging)\n\t\tconst char* CurChr;\n\t\t\n#ifdef WIN32\n\t\tprintf(\"Input CP: %d, Output CP: %d\\n\", GetConsoleCP(), GetConsoleOutputCP());\n#endif\n\t\tprintf(\"VgmFileName: \");\n\t\t\n\t\tCurChr = VgmFileName;\n\t\twhile(*CurChr != '\\0')\n\t\t{\n\t\t\tprintf(\"%02X \", (UINT8)*CurChr);\n\t\t\tCurChr ++;\n\t\t}\n\t\tprintf(\"%02X\\n\", (UINT8)*CurChr);\n\t\t_getch();\n\t}\n#endif\n#if 0\n\t{\t// strip spaces and \\n (fixed bugs with vgm-player script with un-7z)\n\t\tchar* CurChr;\n\t\t\n\t\t// trim \\n and spaces off\n\t\tCurChr = strchr(VgmFileName, '\\n');\n\t\tif (CurChr != NULL)\n\t\t\t*CurChr = '\\0';\n\t\tCurChr = VgmFileName + strlen(VgmFileName) - 1;\n\t\twhile(CurChr > VgmFileName && *CurChr == ' ')\n\t\t\t*(CurChr --) = '\\0';\n\t}\n#endif\n\t\n\tFirstInit = true;\n\tStreamStarted = false;\n\tFileExt = GetFileExtension(VgmFileName);\n\tif (FileExt == NULL || stricmp_u(FileExt, \"m3u\"))\n\t\tPLMode = 0x00;\n\telse\n\t\tPLMode = 0x01;\n\n\tlastMMEvent = 0x00;\n\tif (! PLMode)\n\t{\n\t\tPLFileCount = 0x00;\n\t\tCurPLFile = 0x00;\n\t\t// no Play List File\n\t\tif (! OpenMusicFile(VgmFileName))\n\t\t{\n\t\t\tprinterr(\"Error opening the file!\\n\");\n\t\t\tif (argv[0][1] == ':')\n\t\t\t\t_getch();\n\t\t\tErrRet = 1;\n\t\t\tgoto ExitProgram;\n\t\t}\n\t\tprintf(\"\\n\");\n\t\t\n\t\tErrorHappened = false;\n\t\tFadeTime = FadeTimeN;\n\t\tPauseTime = PauseTimeL;\n\t\tPrintMSHours = (VGMHead.lngTotalSamples >= 158760000);\t// 44100 smpl * 60 sec * 60 min\n\t\tShowVGMTag();\n\t\tNextPLCmd = 0x80;\n\t\tPlayVGM_UI();\n\t\t\n\t\tCloseVGMFile();\n\t}\n\telse\n\t{\n\t\tstrcpy(PLFileName, VgmFileName);\n\t\tif (! OpenPlayListFile(PLFileName))\n\t\t{\n\t\t\tprinterr(\"Error opening the playlist!\\n\");\n\t\t\tif (argv[0][1] == ':')\n\t\t\t\t_getch();\n\t\t\tErrRet = 1;\n\t\t\tgoto ExitProgram;\n\t\t}\n\t\t\n\t\tfor (CurPLFile = 0x00; CurPLFile < PLFileCount; CurPLFile ++)\n\t\t{\n\t\t\tcls();\n\t\t\tprintf(APP_NAME);\n\t\t\tprintf(\"\\n----------\\n\");\n\t\t\tprintf(\"\\nPlaylist File:\\t%s\\n\", PLFileName);\n\t\t\tprintf(\"Playlist Entry:\\t%u / %u\\n\", CurPLFile + 1, PLFileCount);\n\t\t\tprintf(\"File Name:\\t%s\\n\", PlayListFile[CurPLFile]);\n\n\t\t\tif (IsAbsolutePath(PlayListFile[CurPLFile]))\n\t\t\t{\n\t\t\t\tstrcpy(VgmFileName, PlayListFile[CurPLFile]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstrcpy(VgmFileName, PLFileBase);\n\t\t\t\tstrcat(VgmFileName, PlayListFile[CurPLFile]);\n\t\t\t}\n\t\t\t\n\t\t\tif (! OpenMusicFile(VgmFileName))\n\t\t\t{\n\t\t\t\tprintf(\"Error opening the file!\\n\");\n\t\t\t\t_getch();\n\t\t\t\twhile(_kbhit())\n\t\t\t\t\t_getch();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tprintf(\"\\n\");\n\t\t\t\n\t\t\tErrorHappened = false;\n\t\t\tif (CurPLFile < PLFileCount - 1)\n\t\t\t\tFadeTime = FadeTimePL;\n\t\t\telse\n\t\t\t\tFadeTime = FadeTimeN;\n\t\t\tPauseTime = VGMHead.lngLoopOffset ? PauseTimeL : PauseTimeJ;\n\t\t\tPrintMSHours = (VGMHead.lngTotalSamples >= 158760000);\n\t\t\tShowVGMTag();\n\t\t\tNextPLCmd = 0x00;\n\t\t\tPlayVGM_UI();\n\t\t\tCloseVGMFile();\n\t\t\tif (ErrorHappened)\n\t\t\t{\n\t\t\t\tif (_kbhit())\n\t\t\t\t\t_getch();\n\t\t\t\t_getch();\n\t\t\t\tErrorHappened = false;\n\t\t\t}\n\t\t\tif (NextPLCmd == 0xFF)\n\t\t\t\tbreak;\n\t\t\telse if (NextPLCmd == 0x01)\n\t\t\t\tCurPLFile -= 0x02;\t// Jump to last File (-2 + 1 = -1)\n\t\t}\n\t}\n\t\n\tif (ErrorHappened && argv[0][1] == ':')\n\t{\n\t\tif (_kbhit())\n\t\t\t_getch();\n\t\t_getch();\n\t}\n\t\n#ifdef _DEBUG\n\tprintf(\"Press any key ...\");\n\t_getch();\n#endif\n\t\nExitProgram:\n#if defined(XMAS_EXTRA) || defined(WS_DEMO)\n\tif (XMasEnable)\n\t\tXMas_Extra(VgmFileName, 0x01);\n#endif\n#ifndef WIN32\n\tchangemode(false);\n#ifdef SET_CONSOLE_TITLE\n//\tprintf(\"\\x1B]0;${USER}@${HOSTNAME}: ${PWD/$HOME/~}\\x07\", APP_NAME);\t// Reset xterm/rxvt Terminal Title\n#endif\n#endif\n\tMultimediaKeyHook_Deinit();\n\tVGMPlay_Deinit();\n\tfree(AppName);\n\t\n\treturn ErrRet;\n}\n\nstatic void RemoveNewLines(char* String)\n{\n\tchar* StrPtr;\n\t\n\tStrPtr = String + strlen(String) - 1;\n\twhile(StrPtr >= String && (UINT8)*StrPtr < 0x20)\n\t{\n\t\t*StrPtr = '\\0';\n\t\tStrPtr --;\n\t}\n\t\n\treturn;\n}\n\nstatic void RemoveQuotationMarks(char* String)\n{\n\tUINT32 StrLen;\n\tchar* EndQMark;\n\t\n\tif (String[0x00] != QMARK_CHR)\n\t\treturn;\n\t\n\tStrLen = strlen(String);\n\tmemmove(String, String + 0x01, StrLen);\t// Remove first char\n\tEndQMark = strrchr(String, QMARK_CHR);\n\tif (EndQMark != NULL)\n\t\t*EndQMark = 0x00;\t// Remove last Quot.-Mark\n\t\n\treturn;\n}\n\nchar* GetLastDirSeparator(const char* FilePath)\n{\n\tchar* SepPos1;\n\tchar* SepPos2;\n\t\n\tSepPos1 = strrchr(FilePath, '/');\n\tSepPos2 = strrchr(FilePath, '\\\\');\n\tif (SepPos1 < SepPos2)\n\t\treturn SepPos2;\n\telse\n\t\treturn SepPos1;\n}\n\nstatic bool IsAbsolutePath(const char* FilePath)\n{\n#ifdef WIN32\n\tif (FilePath[0] == '\\0')\n\t\treturn false;\t// empty string\n\tif (FilePath[1] == ':')\n\t\treturn true;\t// Device Path: C:\\path\n\tif (! strncmp(FilePath, \"\\\\\\\\\", 2))\n\t\treturn true;\t// Network Path: \\\\computername\\path\n#else\n\tif (FilePath[0] == '/')\n\t\treturn true;\t// absolute UNIX path\n#endif\n\treturn false;\n}\n\nstatic char* GetFileExtension(const char* FilePath)\n{\n\tchar* DirSepPos;\n\tchar* ExtDotPos;\n\t\n\tDirSepPos = GetLastDirSeparator(FilePath);\n\tif (DirSepPos == NULL)\n\t\tDirSepPos = (char*)FilePath;\n\tExtDotPos = strrchr(DirSepPos, '.');\n\tif (ExtDotPos == NULL)\n\t\treturn NULL;\n\telse\n\t\treturn ExtDotPos + 1;\n}\n\nstatic void StandardizeDirSeparators(char* FilePath)\n{\n\tchar* CurChr;\n\t\n\tCurChr = FilePath;\n\twhile(*CurChr != '\\0')\n\t{\n\t\tif (*CurChr == '\\\\' || *CurChr == '/')\n\t\t\t*CurChr = DIR_CHR;\n\t\tCurChr ++;\n\t}\n\t\n\treturn;\n}\n\n#ifdef WIN32\nstatic void WinNT_Check(void)\n{\n\tOSVERSIONINFO VerInf;\n\t\n\tVerInf.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\n\tGetVersionEx(&VerInf);\n\t//WINNT_MODE = (VerInf.dwPlatformId == VER_PLATFORM_WIN32_NT);\n\t\n\t/* Following Systems need larger Audio Buffers:\n\t\t- Windows 95 (500+ ms)\n\t\t- Windows Vista (200+ ms)\n\tTested Systems:\n\t\t- Windows 95B\n\t\t- Windows 98 SE\n\t\t- Windows 2000\n\t\t- Windows XP (32-bit)\n\t\t- Windows Vista (32-bit)\n\t\t- Windows 7 (64-bit)\n\t*/\n\t\n\tNEED_LARGE_AUDIOBUFS = 0;\n\tif (VerInf.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)\n\t{\n\t\tif (VerInf.dwMajorVersion == 4 && VerInf.dwMinorVersion == 0)\n\t\t\tNEED_LARGE_AUDIOBUFS = 50;\t// Windows 95\n\t}\n\telse if (VerInf.dwPlatformId == VER_PLATFORM_WIN32_NT)\n\t{\n\t\tif (VerInf.dwMajorVersion == 6 && VerInf.dwMinorVersion == 0)\n\t\t\tNEED_LARGE_AUDIOBUFS = 20;\t// Windows Vista\n\t}\n\t\n\treturn;\n}\n#endif\n\nstatic char* GetAppFileName(void)\n{\n\tchar* AppPath;\n\t\n\tAppPath = calloc(MAX_PATH, sizeof(char));\n#ifdef WIN32\n\tGetModuleFileName(NULL, AppPath, MAX_PATH - 1);\n#else\n\treadlink(\"/proc/self/exe\", AppPath, MAX_PATH - 1);\n#endif\n\t\n\treturn AppPath;\n}\n\nstatic void cls(void)\n{\n#ifdef WIN32\n\t// CLS-Function from the MSDN Help\n\tHANDLE hConsole;\n\tCOORD coordScreen = {0, 0};\n\tBOOL bSuccess;\n\tDWORD cCharsWritten;\n\tCONSOLE_SCREEN_BUFFER_INFO csbi;\n\tDWORD dwConSize;\n\t\n\thConsole = GetStdHandle(STD_OUTPUT_HANDLE);\n\t\n\t// get the number of character cells in the current buffer\n\tbSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);\n\t\n\t// fill the entire screen with blanks\n\tdwConSize = csbi.dwSize.X * csbi.dwSize.Y;\n\tbSuccess = FillConsoleOutputCharacter(hConsole, (TCHAR)' ', dwConSize, coordScreen,\n\t\t\t\t\t\t\t\t\t\t\t&cCharsWritten);\n\t\n\t// get the current text attribute\n\t//bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);\n\t\n\t// now set the buffer's attributes accordingly\n\t//bSuccess = FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen,\n\t//\t\t\t\t\t\t\t\t\t\t&cCharsWritten);\n\t\n\t// put the cursor at (0, 0)\n\tbSuccess = SetConsoleCursorPosition(hConsole, coordScreen);\n#else\n\tint retVal;\n\t\n\tretVal = system(\"clear\");\n#endif\n\t\n\treturn;\n}\n\n#ifndef WIN32\n\nstatic void changemode(bool dir)\n{\n\tstatic struct termios newterm;\n\t\n\tif (termmode == dir)\n\t\treturn;\n\t\n\tif (dir)\n\t{\n\t\tnewterm = oldterm;\n\t\tnewterm.c_lflag &= ~(ICANON | ECHO);\n\t\ttcsetattr(STDIN_FILENO, TCSANOW, &newterm);\n\t}\n\telse\n\t{\n\t\ttcsetattr(STDIN_FILENO, TCSANOW, &oldterm);\n\t}\n\ttermmode = dir;\n\t\n\treturn;\n}\n\nstatic int _kbhit(void)\n{\n\tstruct timeval tv;\n\tfd_set rdfs;\n\tint kbret;\n\tbool needchg;\n\t\n\tneedchg = (! termmode);\n\tif (needchg)\n\t\tchangemode(true);\n\ttv.tv_sec = 0;\n\ttv.tv_usec = 0;\n\t\n\tFD_ZERO(&rdfs);\n\tFD_SET(STDIN_FILENO, &rdfs);\n\t\n\tselect(STDIN_FILENO + 1, &rdfs, NULL, NULL, &tv);\n\tkbret = FD_ISSET(STDIN_FILENO, &rdfs);\n\tif (needchg)\n\t\tchangemode(false);\n\t\n\treturn kbret;\n}\n\nstatic int _getch(void)\n{\n\tint ch;\n\tbool needchg;\n\t\n\tneedchg = (! termmode);\n\tif (needchg)\n\t\tchangemode(true);\n\tch = getchar();\n\tif (needchg)\n\t\tchangemode(false);\n\t\n\treturn ch;\n}\n#endif\n\nstatic INT8 stricmp_u(const char *string1, const char *string2)\n{\n\t// my own stricmp, because VC++6 doesn't find _stricmp when compiling without\n\t// standard libraries\n\tconst char* StrPnt1;\n\tconst char* StrPnt2;\n\tchar StrChr1;\n\tchar StrChr2;\n\t\n\tStrPnt1 = string1;\n\tStrPnt2 = string2;\n\twhile(true)\n\t{\n\t\tStrChr1 = toupper(*StrPnt1);\n\t\tStrChr2 = toupper(*StrPnt2);\n\t\t\n\t\tif (StrChr1 < StrChr2)\n\t\t\treturn -1;\n\t\telse if (StrChr1 > StrChr2)\n\t\t\treturn +1;\n\t\tif (StrChr1 == 0x00)\n\t\t\treturn 0;\n\t\t\n\t\tStrPnt1 ++;\n\t\tStrPnt2 ++;\n\t}\n\t\n\treturn 0;\n}\n\nstatic INT8 strnicmp_u(const char *string1, const char *string2, size_t count)\n{\n\t// my own strnicmp, because GCC doesn't seem to have _strnicmp\n\tconst char* StrPnt1;\n\tconst char* StrPnt2;\n\tchar StrChr1;\n\tchar StrChr2;\n\tsize_t CurChr;\n\t\n\tStrPnt1 = string1;\n\tStrPnt2 = string2;\n\tCurChr = 0x00;\n\twhile(CurChr < count)\n\t{\n\t\tStrChr1 = toupper(*StrPnt1);\n\t\tStrChr2 = toupper(*StrPnt2);\n\t\t\n\t\tif (StrChr1 < StrChr2)\n\t\t\treturn -1;\n\t\telse if (StrChr1 > StrChr2)\n\t\t\treturn +1;\n\t\tif (StrChr1 == 0x00)\n\t\t\treturn 0;\n\t\t\n\t\tStrPnt1 ++;\n\t\tStrPnt2 ++;\n\t\tCurChr ++;\n\t}\n\t\n\treturn 0;\n}\n\nstatic void ReadOptions(const char* AppName)\n{\n\tconst UINT8 CHN_COUNT[CHIP_COUNT] =\n\t{\t0x04, 0x09, 0x06, 0x08, 0x10, 0x08, 0x03, 0x00,\n\t\t0x00, 0x09, 0x09, 0x09, 0x12, 0x00, 0x0C, 0x08,\n\t\t0x08, 0x00, 0x03, 0x04, 0x05, 0x1C, 0x00, 0x00,\n\t\t0x04, 0x05, 0x08, 0x08, 0x18, 0x04, 0x04, 0x10,\n\t\t0x20, 0x04, 0x06, 0x06, 0x20, 0x20, 0x10, 0x20,\n\t\t0x04\n\t};\n\tconst UINT8 CHN_MASK_CNT[CHIP_COUNT] =\n\t{\t0x04, 0x0E, 0x07, 0x08, 0x10, 0x08, 0x03, 0x06,\n\t\t0x06, 0x0E, 0x0E, 0x0E, 0x17, 0x18, 0x0C, 0x08,\n\t\t0x08, 0x00, 0x03, 0x04, 0x05, 0x1C, 0x00, 0x00,\n\t\t0x04, 0x05, 0x08, 0x08, 0x18, 0x04, 0x04, 0x10,\n\t\t0x20, 0x04, 0x06, 0x06, 0x20, 0x20, 0x10, 0x20,\n\t\t0x04\n\t};\n\tconst char* FNList[3];\n\tchar* FileName;\n\tFILE* hFile;\n\tchar TempStr[0x40];\n\tUINT32 StrLen;\n\tUINT32 TempLng;\n\tchar* LStr;\n\tchar* RStr;\n\tUINT8 IniSection;\n\tUINT8 CurChip;\n\tCHIP_OPTS* TempCOpt;\n\tCHIP_OPTS* TempCOpt2;\n\tUINT8 CurChn;\n\tchar* TempPnt;\n\tbool TempFlag;\n\t\n\t// most defaults are set by VGMPlay_Init()\n\tFadeTimeN = FadeTime;\n\tFadeTimePL = 2000;\n\tPauseTimeJ = PauseTime;\n\tPauseTimeL = 0;\n\tShow95Cmds = 0x00;\n\tLogToWave = 0x00;\n\tOutputDevID = 0;\n\tForceAudioBuf = 0x00;\n\tPreferJapTag = false;\n\t\n\tif (AppName == NULL)\n\t{\n\t\tprinterr(\"Argument \\\"Application-Path\\\" is NULL!\\nSkip loading INI.\\n\");\n\t\treturn;\n\t}\n\t\n\t// AppName: \"C:\\VGMPlay\\VGMPlay.exe\"\n\tRStr = strrchr(AppName, DIR_CHR);\n\tif (RStr != NULL)\n\t\tRStr ++;\n\telse\n\t\tRStr = (char*)AppName;\n\tFileName = (char*)malloc(strlen(RStr) + 0x05);\t// \".ini\" + 00\n\tstrcpy(FileName, RStr);\n\t// FileName: \"VGMPlay.exe\"\n\t\n\tRStr = GetFileExtension(FileName);\n\tif (RStr == NULL)\n\t{\n\t\tRStr = FileName + strlen(FileName);\n\t\t*RStr = '.';\n\t\tRStr ++;\n\t}\n\tstrcpy(RStr, \"ini\");\n\t// FileName: \"VGMPlay.ini\" or \"vgmplay.ini\"\n\t\n\t// on Linux platforms, it searches for \"vgmplay.ini\" first and\n\t// file names are case sensitive\n\tFNList[0] = FileName;\n\tFNList[1] = \"VGMPlay.ini\";\n\tFNList[2] = NULL;\n\tLStr = FileName;\n\tFileName = FindFile_List(FNList);\n\tfree(LStr);\n\tif (FileName == NULL)\n\t{\n\t\tprinterr(\"Failed to load INI.\\n\");\n\t\treturn;\n\t}\n\thFile = fopen(FileName, \"rt\");\n\tfree(FileName);\n\tif (hFile == NULL)\n\t{\n\t\tprinterr(\"Failed to load INI.\\n\");\n\t\treturn;\n\t}\n\t\n\tIniSection = 0x00;\n\twhile(! feof(hFile))\n\t{\n\t\tLStr = fgets(TempStr, 0x40, hFile);\n\t\tif (LStr == NULL)\n\t\t\tbreak;\n\t\tif (TempStr[0x00] == ';')\t// Comment line\n\t\t\tcontinue;\n\t\t\n\t\tStrLen = strlen(TempStr) - 0x01;\n\t\t//if (TempStr[StrLen] == '\\n')\n\t\t//\tTempStr[StrLen] = '\\0';\n\t\twhile(TempStr[StrLen] < 0x20)\n\t\t{\n\t\t\tTempStr[StrLen] = '\\0';\n\t\t\tif (! StrLen)\n\t\t\t\tbreak;\n\t\t\tStrLen --;\n\t\t}\n\t\tif (! StrLen)\n\t\t\tcontinue;\n\t\tStrLen ++;\n\t\t\n\t\tLStr = &TempStr[0x00];\n\t\twhile(*LStr == ' ')\n\t\t\tLStr ++;\n\t\tif (LStr[0x00] == ';')\t// Comment line\n\t\t\tcontinue;\n\t\t\n\t\tif (LStr[0x00] == '[')\n\t\t\tRStr = strchr(TempStr, ']');\n\t\telse\n\t\t\tRStr = strchr(TempStr, '=');\n\t\tif (RStr == NULL)\n\t\t\tcontinue;\n\t\t\n\t\tif (LStr[0x00] == '[')\n\t\t{\n\t\t\t// Line pattern: [Group]\n\t\t\tLStr ++;\n\t\t\tRStr = strchr(TempStr, ']');\n\t\t\tif (RStr != NULL)\n\t\t\t\tRStr[0x00] = '\\0';\n\t\t\t\n\t\t\tif (! stricmp_u(LStr, \"General\"))\n\t\t\t{\n\t\t\t\tIniSection = 0x00;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tIniSection = 0xFF;\n\t\t\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++)\n\t\t\t\t{\n\t\t\t\t\tif (! stricmp_u(LStr, GetChipName(CurChip)))\n\t\t\t\t\t{\n\t\t\t\t\t\tIniSection = 0x80 | CurChip;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (IniSection == 0xFF)\n\t\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Line pattern: Option = Value\n\t\t\tTempLng = RStr - TempStr;\n\t\t\tTempStr[TempLng] = '\\0';\n\t\t\t\n\t\t\t// Prepare Strings (trim the spaces)\n\t\t\tRStr = &TempStr[TempLng - 0x01];\n\t\t\twhile(*RStr == ' ')\n\t\t\t\t*(RStr --) = '\\0';\n\t\t\t\n\t\t\tRStr = &TempStr[StrLen - 0x01];\n\t\t\twhile(*RStr == ' ')\n\t\t\t\t*(RStr --) = '\\0';\n\t\t\tRStr = &TempStr[TempLng + 0x01];\n\t\t\twhile(*RStr == ' ')\n\t\t\t\tRStr ++;\n\t\t\t\n\t\t\tswitch(IniSection)\n\t\t\t{\n\t\t\tcase 0x00:\t// General Sction\n\t\t\t\tif (! stricmp_u(LStr, \"SampleRate\"))\n\t\t\t\t{\n\t\t\t\t\tSampleRate = strtoul(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"PlaybackRate\"))\n\t\t\t\t{\n\t\t\t\t\tVGMPbRate = strtoul(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"DoubleSSGVol\"))\n\t\t\t\t{\n\t\t\t\t\tDoubleSSGVol = GetBoolFromStr(RStr);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"PreferJapTag\"))\n\t\t\t\t{\n\t\t\t\t\tPreferJapTag = GetBoolFromStr(RStr);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"FadeTime\"))\n\t\t\t\t{\n\t\t\t\t\tFadeTimeN = strtoul(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"FadeTimePL\"))\n\t\t\t\t{\n\t\t\t\t\tFadeTimePL = strtoul(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"JinglePause\"))\n\t\t\t\t{\n\t\t\t\t\tPauseTimeJ = strtoul(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"HardStopOld\"))\n\t\t\t\t{\n\t\t\t\t\tHardStopOldVGMs = (UINT8)strtoul(RStr, &TempPnt, 0);\n\t\t\t\t\tif (TempPnt == RStr)\n\t\t\t\t\t\tHardStopOldVGMs = GetBoolFromStr(RStr) ? 0x01 : 0x00;\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"FadeRAWLogs\"))\n\t\t\t\t{\n\t\t\t\t\tFadeRAWLog = GetBoolFromStr(RStr);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"Volume\"))\n\t\t\t\t{\n\t\t\t\t\tVolumeLevel = (float)strtod(RStr, NULL);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"LogSound\"))\n\t\t\t\t{\n\t\t\t\t\t//LogToWave = GetBoolFromStr(RStr);\n\t\t\t\t\tLogToWave = (UINT8)strtoul(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"MaxLoops\"))\n\t\t\t\t{\n\t\t\t\t\tVGMMaxLoop = strtoul(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"MaxLoopsCMF\"))\n\t\t\t\t{\n\t\t\t\t\tCMFMaxLoop = strtoul(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"ResamplingMode\"))\n\t\t\t\t{\n\t\t\t\t\tResampleMode = (UINT8)strtol(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"ChipSmplMode\"))\n\t\t\t\t{\n\t\t\t\t\tCHIP_SAMPLING_MODE = (UINT8)strtol(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"ChipSmplRate\"))\n\t\t\t\t{\n\t\t\t\t\tCHIP_SAMPLE_RATE = strtol(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"OutputDevice\"))\n\t\t\t\t{\n\t\t\t\t\tOutputDevID = (UINT8)strtol(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"AudioBuffers\"))\n\t\t\t\t{\n\t\t\t\t\tForceAudioBuf = (UINT16)strtol(RStr, NULL, 0);\n\t\t\t\t\tif (ForceAudioBuf < 0x04)\n\t\t\t\t\t\tForceAudioBuf = 0x00;\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"SurroundSound\"))\n\t\t\t\t{\n\t\t\t\t\tSurroundSound = GetBoolFromStr(RStr);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"EmulatePause\"))\n\t\t\t\t{\n\t\t\t\t\tPauseEmulate = GetBoolFromStr(RStr);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"ShowStreamCmds\"))\n\t\t\t\t{\n\t\t\t\t\tShow95Cmds = (UINT8)strtol(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"FMPort\"))\n\t\t\t\t{\n\t\t\t\t\tFMPort = (UINT16)strtoul(RStr, NULL, 16);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"FMForce\"))\n\t\t\t\t{\n\t\t\t\t\tFMForce = GetBoolFromStr(RStr);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"FMVolume\"))\n\t\t\t\t{\n\t\t\t\t\tFMVol = (float)strtod(RStr, NULL);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"FMOPL2Pan\"))\n\t\t\t\t{\n\t\t\t\t\tFMOPL2Pan = GetBoolFromStr(RStr);\n\t\t\t\t}\n\t\t\t\t/*else if (! stricmp_u(LStr, \"AccurateFM\"))\n\t\t\t\t{\n\t\t\t\t\tFMAccurate = GetBoolFromStr(RStr);\n\t\t\t\t}*/\n\t\t\t\telse if (! stricmp_u(LStr, \"FMSoftStop\"))\n\t\t\t\t{\n\t\t\t\t\tFMBreakFade = GetBoolFromStr(RStr);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0x80:\t// SN76496\n\t\t\tcase 0x81:\t// YM2413\n\t\t\tcase 0x82:\t// YM2612\n\t\t\tcase 0x83:\t// YM2151\n\t\t\tcase 0x84:\t// SegaPCM\n\t\t\tcase 0x85:\t// RF5C68\n\t\t\tcase 0x86:\t// YM2203\n\t\t\tcase 0x87:\t// YM2608\n\t\t\tcase 0x88:\t// YM2610\n\t\t\tcase 0x89:\t// YM3812\n\t\t\tcase 0x8A:\t// YM3526\n\t\t\tcase 0x8B:\t// Y8950\n\t\t\tcase 0x8C:\t// YMF262\n\t\t\tcase 0x8D:\t// YMF278B\n\t\t\tcase 0x8E:\t// YMF271\n\t\t\tcase 0x8F:\t// YMZ280B\n\t\t\tcase 0x90:\t// RF5C164\n\t\t\tcase 0x91:\t// PWM\n\t\t\tcase 0x92:\t// AY8910\n\t\t\tcase 0x93:\t// GameBoy\n\t\t\tcase 0x94:\t// NES\n\t\t\tcase 0x95:\t// MultiPCM\n\t\t\tcase 0x96:\t// UPD7759\n\t\t\tcase 0x97:\t// OKIM6258\n\t\t\tcase 0x98:\t// OKIM6295\n\t\t\tcase 0x99:\t// K051649\n\t\t\tcase 0x9A:\t// K054539\n\t\t\tcase 0x9B:\t// HuC6280\n\t\t\tcase 0x9C:\t// C140\n\t\t\tcase 0x9D:\t// K053260\n\t\t\tcase 0x9E:\t// Pokey\n\t\t\tcase 0x9F:\t// QSound\n\t\t\tcase 0xA0:\t// SCSP\n\t\t\tcase 0xA1:\t// WonderSwan\n\t\t\tcase 0xA2:\t// VSU\n\t\t\tcase 0xA3:\t// SAA1099\n\t\t\tcase 0xA4:\t// ES5503\n\t\t\tcase 0xA5:\t// ES5506\n\t\t\tcase 0xA6:\t// X1_010\n\t\t\tcase 0xA7:\t// C352\n\t\t\tcase 0xA8:\t// GA20\n\t\t\t\tCurChip = IniSection & 0x7F;\n\t\t\t\tTempCOpt = (CHIP_OPTS*)&ChipOpts[0x00] + CurChip;\n\t\t\t\t\n\t\t\t\tif (! stricmp_u(LStr, \"Disabled\"))\n\t\t\t\t{\n\t\t\t\t\tTempCOpt->Disabled = GetBoolFromStr(RStr);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"EmulatorType\"))\n\t\t\t\t{\n\t\t\t\t\tTempCOpt->EmuCore = (UINT8)strtol(RStr, NULL, 0);\n\t\t\t\t}\n\t\t\t\telse if (! stricmp_u(LStr, \"MuteMask\"))\n\t\t\t\t{\n\t\t\t\t\tif (! CHN_COUNT[CurChip])\n\t\t\t\t\t\tbreak;\t// must use MuteMaskFM and MuteMask???\n\t\t\t\t\tTempCOpt->ChnMute1 = strtoul(RStr, NULL, 0);\n\t\t\t\t\tif (CHN_MASK_CNT[CurChip] < 0x20)\n\t\t\t\t\t\tTempCOpt->ChnMute1 &= (1 << CHN_MASK_CNT[CurChip]) - 1;\n\t\t\t\t}\n\t\t\t\telse if (! strnicmp_u(LStr, \"MuteCh\", 0x06))\n\t\t\t\t{\n\t\t\t\t\tif (! CHN_COUNT[CurChip])\n\t\t\t\t\t\tbreak;\t// must use MuteFM and Mute???\n\t\t\t\t\tCurChn = (UINT8)strtol(LStr + 0x06, &TempPnt, 0);\n\t\t\t\t\tif (TempPnt == NULL || *TempPnt)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tif (CurChn >= CHN_COUNT[CurChip])\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\tTempCOpt->ChnMute1 &= ~(0x01 << CurChn);\n\t\t\t\t\tTempCOpt->ChnMute1 |= TempFlag << CurChn;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tswitch(CurChip)\n\t\t\t\t\t{\n\t\t\t\t\t//case 0x00:\t// SN76496\n\t\t\t\t\tcase 0x02:\t// YM2612\n\t\t\t\t\t\tif (! stricmp_u(LStr, \"MuteDAC\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCurChn = 0x06;\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->ChnMute1 &= ~(0x01 << CurChn);\n\t\t\t\t\t\t\tTempCOpt->ChnMute1 |= TempFlag << CurChn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"DACHighpass\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x01 << 0);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempFlag << 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"SSG-EG\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x01 << 1);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempFlag << 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"PseudoStereo\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x01 << 2);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempFlag << 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"NukedType\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempLng = (UINT32)strtoul(RStr, NULL, 0) & 0x03;\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x03 << 3);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempLng << 3;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t//case 0x03:\t// YM2151\n\t\t\t\t\t//case 0x04:\t// SegaPCM\n\t\t\t\t\t//case 0x05:\t// RF5C68\n\t\t\t\t\tcase 0x06:\t// YM2203\n\t\t\t\t\t\tif (! stricmp_u(LStr, \"DisableAY\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x01 << 0);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempFlag << 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x07:\t// YM2608\n\t\t\t\t\tcase 0x08:\t// YM2610\n\t\t\t\t\t\tif (! stricmp_u(LStr, \"DisableAY\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x01 << 0);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempFlag << 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"MuteMask_FM\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempCOpt->ChnMute1 = strtoul(RStr, NULL, 0);\n\t\t\t\t\t\t\tTempCOpt->ChnMute1 &= (1 << CHN_MASK_CNT[CurChip]) - 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"MuteMask_PCM\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempCOpt->ChnMute2 = strtoul(RStr, NULL, 0);\n\t\t\t\t\t\t\tTempCOpt->ChnMute2 &= (1 << (CHN_MASK_CNT[CurChip] + 1)) - 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! strnicmp_u(LStr, \"MuteFMCh\", 0x08))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCurChn = (UINT8)strtol(LStr + 0x08, &TempPnt, 0);\n\t\t\t\t\t\t\tif (TempPnt == NULL || *TempPnt)\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tif (CurChn >= CHN_MASK_CNT[CurChip])\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->ChnMute1 &= ~(0x01 << CurChn);\n\t\t\t\t\t\t\tTempCOpt->ChnMute1 |= TempFlag << CurChn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! strnicmp_u(LStr, \"MutePCMCh\", 0x09))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCurChn = (UINT8)strtol(LStr + 0x09, &TempPnt, 0);\n\t\t\t\t\t\t\tif (TempPnt == NULL || *TempPnt)\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tif (CurChn >= CHN_MASK_CNT[CurChip])\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->ChnMute2 &= ~(0x01 << CurChn);\n\t\t\t\t\t\t\tTempCOpt->ChnMute2 |= TempFlag << CurChn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"MuteDT\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCurChn = 0x06;\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->ChnMute2 &= ~(0x01 << CurChn);\n\t\t\t\t\t\t\tTempCOpt->ChnMute2 |= TempFlag << CurChn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x01:\t// YM2413\n\t\t\t\t\tcase 0x09:\t// YM3812\n\t\t\t\t\tcase 0x0A:\t// YM3526\n\t\t\t\t\tcase 0x0B:\t// Y8950\n\t\t\t\t\tcase 0x0C:\t// YMF262\n\t\t\t\t\t\tCurChn = 0xFF;\n\t\t\t\t\t\tif (! stricmp_u(LStr, \"MuteBD\"))\n\t\t\t\t\t\t\tCurChn = 0x00;\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"MuteSD\"))\n\t\t\t\t\t\t\tCurChn = 0x01;\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"MuteTOM\"))\n\t\t\t\t\t\t\tCurChn = 0x02;\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"MuteTC\"))\n\t\t\t\t\t\t\tCurChn = 0x03;\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"MuteHH\"))\n\t\t\t\t\t\t\tCurChn = 0x04;\n\t\t\t\t\t\telse if (CurChip == 0x0B && ! stricmp_u(LStr, \"MuteDT\"))\n\t\t\t\t\t\t\tCurChn = 0x05;\n\t\t\t\t\t\tif (CurChn != 0xFF)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (CurChip < 0x0C)\n\t\t\t\t\t\t\t\tCurChn += 9;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tCurChn += 18;\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->ChnMute1 &= ~(0x01 << CurChn);\n\t\t\t\t\t\t\tTempCOpt->ChnMute1 |= TempFlag << CurChn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x0D:\t// YMF278B\n\t\t\t\t\t\tif (! stricmp_u(LStr, \"MuteMask_FM\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempCOpt->ChnMute1 = strtoul(RStr, NULL, 0);\n\t\t\t\t\t\t\tTempCOpt->ChnMute1 &= (1 << CHN_MASK_CNT[CurChip - 0x01]) - 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"MuteMask_WT\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempCOpt->ChnMute2 = strtoul(RStr, NULL, 0);\n\t\t\t\t\t\t\tTempCOpt->ChnMute2 &= (1 << CHN_MASK_CNT[CurChip]) - 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! strnicmp_u(LStr, \"MuteFMCh\", 0x08))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCurChn = (UINT8)strtol(LStr + 0x08, &TempPnt, 0);\n\t\t\t\t\t\t\tif (TempPnt == NULL || *TempPnt)\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tif (CurChn >= CHN_COUNT[CurChip - 0x01])\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->ChnMute1 &= ~(0x01 << CurChn);\n\t\t\t\t\t\t\tTempCOpt->ChnMute1 |= TempFlag << CurChn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! strnicmp_u(LStr, \"MuteFM\", 0x06))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCurChn = 0xFF;\n\t\t\t\t\t\t\tif (! stricmp_u(LStr + 6, \"BD\"))\n\t\t\t\t\t\t\t\tCurChn = 0x00;\n\t\t\t\t\t\t\telse if (! stricmp_u(LStr + 6, \"SD\"))\n\t\t\t\t\t\t\t\tCurChn = 0x01;\n\t\t\t\t\t\t\telse if (! stricmp_u(LStr + 6, \"TOM\"))\n\t\t\t\t\t\t\t\tCurChn = 0x02;\n\t\t\t\t\t\t\telse if (! stricmp_u(LStr + 6, \"TC\"))\n\t\t\t\t\t\t\t\tCurChn = 0x03;\n\t\t\t\t\t\t\telse if (! stricmp_u(LStr + 6, \"HH\"))\n\t\t\t\t\t\t\t\tCurChn = 0x04;\n\t\t\t\t\t\t\tif (CurChn != 0xFF)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tCurChn += 18;\n\t\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\t\tTempCOpt->ChnMute1 &= ~(0x01 << CurChn);\n\t\t\t\t\t\t\t\tTempCOpt->ChnMute1 |= TempFlag << CurChn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! strnicmp_u(LStr, \"MuteWTCh\", 0x08))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCurChn = (UINT8)strtol(LStr + 0x08, &TempPnt, 0);\n\t\t\t\t\t\t\tif (TempPnt == NULL || *TempPnt)\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tif (CurChn >= CHN_MASK_CNT[CurChip])\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->ChnMute2 &= ~(0x01 << CurChn);\n\t\t\t\t\t\t\tTempCOpt->ChnMute2 |= TempFlag << CurChn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t//case 0x0E:\t// YMF271\n\t\t\t\t\t//case 0x0F:\t// YMZ280B\n\t\t\t\t\t\t/*if (! stricmp_u(LStr, \"DisableFix\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDISABLE_YMZ_FIX = GetBoolFromStr(RStr);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;*/\n\t\t\t\t\t//case 0x10:\t// RF5C164\n\t\t\t\t\t//case 0x11:\t// PWM\n\t\t\t\t\t//case 0x12:\t// AY8910\n\t\t\t\t\tcase 0x13:\t// GameBoy\n\t\t\t\t\t\tif (! stricmp_u(LStr, \"BoostWaveChn\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x01 << 0);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempFlag << 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x14:\t// NES\n\t\t\t\t\t\tif (! stricmp_u(LStr, \"SharedOpts\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// 2 bits\n\t\t\t\t\t\t\tTempLng = (UINT32)strtol(RStr, NULL, 0) & 0x03;\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x03 << 0) & 0x7FFF;\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempLng << 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"APUOpts\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// 2 bits\n\t\t\t\t\t\t\tTempLng = (UINT32)strtol(RStr, NULL, 0) & 0x03;\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x03 << 2) & 0x7FFF;\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempLng << 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"DMCOpts\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// 8 bits (6 bits used)\n\t\t\t\t\t\t\tTempLng = (UINT32)strtol(RStr, NULL, 0) & 0xFF;\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0xFF << 4) & 0x7FFF;\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempLng << 4;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (! stricmp_u(LStr, \"FDSOpts\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// 1 bit\n\t\t\t\t\t\t\tTempLng = (UINT32)strtol(RStr, NULL, 0) & 0x01;\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x01 << 12) & 0x7FFF;\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempLng << 12;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x17:\t// OKIM6258\n\t\t\t\t\t\tif (! stricmp_u(LStr, \"Enable10Bit\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x01 << 0);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempFlag << 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x20:\t// SCSP\n\t\t\t\t\t\tif (! stricmp_u(LStr, \"BypassDSP\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x01 << 0);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempFlag << 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x27:\t// C352\n\t\t\t\t\t\tif (! stricmp_u(LStr, \"DisableRear\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempFlag = GetBoolFromStr(RStr);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags &= ~(0x01 << 0);\n\t\t\t\t\t\t\tTempCOpt->SpecialFlags |= TempFlag << 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xFF:\t// Dummy Section\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tTempCOpt = (CHIP_OPTS*)&ChipOpts[0x00];\n\tTempCOpt2 = (CHIP_OPTS*)&ChipOpts[0x01];\n\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, TempCOpt ++, TempCOpt2 ++)\n\t{\n\t\tTempCOpt2->Disabled = TempCOpt->Disabled;\n\t\tTempCOpt2->EmuCore = TempCOpt->EmuCore;\n\t\tTempCOpt2->SpecialFlags = TempCOpt->SpecialFlags;\n\t\tTempCOpt2->ChnMute1 = TempCOpt->ChnMute1;\n\t\tTempCOpt2->ChnMute2 = TempCOpt->ChnMute2;\n\t\tTempCOpt2->ChnMute3 = TempCOpt->ChnMute3;\n\t}\n\t\n\tfclose(hFile);\n\t\n#ifdef WIN32\n\tWinNT_Check();\n#endif\n\tif (CHIP_SAMPLE_RATE <= 0)\n\t\tCHIP_SAMPLE_RATE = SampleRate;\n\t\n\treturn;\n}\n\nstatic bool GetBoolFromStr(const char* TextStr)\n{\n\tif (! stricmp_u(TextStr, \"True\"))\n\t\treturn true;\n\telse if (! stricmp_u(TextStr, \"False\"))\n\t\treturn false;\n\telse\n\t\treturn strtol(TextStr, NULL, 0) ? true : false;\n}\n\n#if defined(XMAS_EXTRA) || defined(WS_DEMO)\nstatic bool XMas_Extra(char* FileName, bool Mode)\n{\n\tchar* FileTitle;\n\tconst UINT8* XMasData;\n\tUINT32 XMasSize;\n\tFILE* hFile;\n\t\n\tif (! Mode)\n\t{\t// Prepare Mode\n\t\tFileTitle = NULL;\n\t\tXMasData = NULL;\n#ifdef XMAS_EXTRA\n\t\tif (! stricmp_u(FileName, \"WEWISH\")\n\t\t{\n\t\t\tFileTitle = \"WEWISH.CMF\";\n\t\t\tXMasSize = sizeof(WEWISH_CMF);\n\t\t\tXMasData = WEWISH_CMF;\n\t\t}\n\t\telse if (! stricmp_u(FileName, \"tim7\")\n\t\t{\n\t\t\tFileTitle = \"lem_tim7.vgz\";\n\t\t\tXMasSize = sizeof(TIM7_VGZ);\n\t\t\tXMasData = TIM7_VGZ;\n\t\t}\n\t\telse if (! stricmp_u(FileName, \"jingleb\")\n\t\t{\n\t\t\tFileTitle = \"lxmas_jb.dro\";\n\t\t\tXMasSize = sizeof(JB_DRO);\n\t\t\tXMasData = JB_DRO;\n\t\t}\n\t\telse if (! stricmp_u(FileName, \"rudolph\")\n\t\t{\n\t\t\tFileTitle = \"rudolph.dro\";\n\t\t\tXMasSize = sizeof(RODOLPH_DRO);\n\t\t\tXMasData = RODOLPH_DRO;\n\t\t}\n\t\telse if (! stricmp_u(FileName, \"clyde\"))\n\t\t{\n\t\t\tFileTitle = \"clyde1_1.dro\";\n\t\t\tXMasSize = sizeof(clyde1_1_dro);\n\t\t\tXMasData = clyde1_1_dro;\n\t\t}\n#elif defined(WS_DEMO)\n\t\tif (! stricmp_u(FileName, \"wswan\"))\n\t\t{\n\t\t\tFileTitle = \"SWJ-SQRC01_1C.vgz\";\n\t\t\tXMasSize = sizeof(FF1ws_1C);\n\t\t\tXMasData = FF1ws_1C;\n\t\t}\n#endif\n\t\t\n\t\tif (XMasData)\n\t\t{\n#ifdef WIN32\n\t\t\tGetEnvironmentVariable(\"Temp\", FileName, MAX_PATH);\n#else\n\t\t\tstrcpy(FileName, \"/tmp\");\n#endif\n\t\t\tstrcat(FileName, DIR_STR);\n\t\t\tif (FileTitle == NULL)\n\t\t\t\tFileTitle = \"XMas.dat\";\n\t\t\tstrcat(FileName, FileTitle);\n\t\t\t\n\t\t\thFile = fopen(FileName, \"wb\");\n\t\t\tif (hFile == NULL)\n\t\t\t{\n\t\t\t\tFileName[0x00] = '\\0';\n\t\t\t\tprinterr(\"Critical XMas-Error!\\n\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tfwrite(XMasData, 0x01, XMasSize, hFile);\n\t\t\tfclose(hFile);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tFileName = NULL;\n\t\t\treturn false;\n\t\t}\n\t}\n\telse\n\t{\t// Unprepare Mode\n\t\tif (! remove(FileName))\n\t\t\treturn false;\n\t\t// btw: it's intentional that the user can grab the file from the temp-folder\n\t}\n\t\n\treturn true;\n}\n#endif\n\n#ifndef WIN32\nstatic void ConvertCP1252toUTF8(char** DstStr, const char* SrcStr)\n{\n\tconst UINT16 CONV_TBL[0x20] =\n\t{\t0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,\t\t// 80-87\n\t\t0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,\t\t// 88-8F\n\t\t0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,\t\t// 90-97\n\t\t0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178};\t// 98-9F\n\tUINT32 StrLen;\n\tUINT16 UnicodeChr;\n\tchar* DstPtr;\n\tconst unsigned char* SrcPtr;\n\t\n\tSrcPtr = (const unsigned char*)SrcStr;\n\tStrLen = 0x00;\n\twhile(*SrcPtr != '\\0')\n\t{\n\t\tif (*SrcPtr < 0x80 || *SrcPtr >= 0xA0)\n\t\t\tUnicodeChr = *SrcPtr;\n\t\telse\n\t\t\tUnicodeChr = CONV_TBL[*SrcPtr - 0x80];\n\t\tif (UnicodeChr < 0x0080)\n\t\t\tStrLen ++;\n\t\telse if (UnicodeChr < 0x0800)\n\t\t\tStrLen += 2;\n\t\telse\n\t\t\tStrLen += 3;\n\t\tSrcPtr ++;\n\t}\n\t\n\t*DstStr = (char*)malloc((StrLen + 0x01) * sizeof(char));\n\tSrcPtr = (const unsigned char*)SrcStr;\n\tDstPtr = *DstStr;\n\twhile(*SrcPtr != '\\0')\n\t{\n\t\tif (*SrcPtr < 0x80 || *SrcPtr >= 0xA0)\n\t\t\tUnicodeChr = (unsigned char)*SrcPtr;\n\t\telse\n\t\t\tUnicodeChr = CONV_TBL[*SrcPtr - 0x80];\n\t\tif (UnicodeChr < 0x0080)\n\t\t{\n\t\t\t*DstPtr = UnicodeChr & 0xFF;\n\t\t\tDstPtr ++;\n\t\t}\n\t\telse if (UnicodeChr < 0x0800)\n\t\t{\n\t\t\tDstPtr[0x00] = 0xC0 | ((UnicodeChr >> 6) & 0x1F);\n\t\t\tDstPtr[0x01] = 0x80 | ((UnicodeChr >> 0) & 0x3F);\n\t\t\tDstPtr += 0x02;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDstPtr[0x00] = 0xE0 | ((UnicodeChr >> 12) & 0x0F);\n\t\t\tDstPtr[0x01] = 0x80 | ((UnicodeChr >>  6) & 0x3F);\n\t\t\tDstPtr[0x02] = 0x80 | ((UnicodeChr >>  0) & 0x3F);\n\t\t\tDstPtr += 0x03;\n\t\t}\n\t\tSrcPtr ++;\n\t}\n\t*DstPtr = '\\0';\n\t\n\treturn;\n}\n#endif\n\nstatic bool OpenPlayListFile(const char* FileName)\n{\n\tconst char M3UV2_HEAD[] = \"#EXTM3U\";\n\tconst char M3UV2_META[] = \"#EXTINF:\";\n\tconst UINT8 UTF8_SIG[] = {0xEF, 0xBB, 0xBF};\n\tUINT32 METASTR_LEN;\n\tsize_t RetVal;\n\t\n\tFILE* hFile;\n\tUINT32 LineNo;\n\tbool IsV2Fmt;\n\tUINT32 PLAlloc;\n\tchar TempStr[0x1000];\t// 4096 chars should be enough\n\tchar* RetStr;\n\tbool IsUTF8;\n\t\n\thFile = fopen(FileName, \"rt\");\n\tif (hFile == NULL)\n\t\treturn false;\n\t\n\tRetVal = fread(TempStr, 0x01, 0x03, hFile);\n\tif (RetVal >= 0x03)\n\t\tIsUTF8 = ! memcmp(TempStr, UTF8_SIG, 0x03);\n\telse\n\t\tIsUTF8 = false;\n\t\n\trewind(hFile);\n\t\n\tPLAlloc = 0x0100;\n\tPLFileCount = 0x00;\n\tLineNo = 0x00;\n\tIsV2Fmt = false;\n\tMETASTR_LEN = strlen(M3UV2_META);\n\tPlayListFile = (char**)malloc(PLAlloc * sizeof(char*));\n\twhile(! feof(hFile))\n\t{\n\t\tRetStr = fgets(TempStr, 0x1000, hFile);\n\t\tif (RetStr == NULL)\n\t\t\tbreak;\n\t\t//RetStr = strchr(TempStr, 0x0D);\n\t\t//if (RetStr)\n\t\t//\t*RetStr = 0x00;\t// remove NewLine-Character\n\t\tRetStr = TempStr + strlen(TempStr) - 0x01;\n\t\twhile(RetStr >= TempStr && *RetStr < 0x20)\n\t\t{\n\t\t\t*RetStr = '\\0';\t// remove NewLine-Characters\n\t\t\tRetStr --;\n\t\t}\n\t\tif (! strlen(TempStr))\n\t\t\tcontinue;\n\t\t\n\t\tif (! LineNo)\n\t\t{\n\t\t\tif (! strcmp(TempStr, M3UV2_HEAD))\n\t\t\t{\n\t\t\t\tIsV2Fmt = true;\n\t\t\t\tLineNo ++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (IsV2Fmt)\n\t\t{\n\t\t\tif (! strncmp(TempStr, M3UV2_META, METASTR_LEN))\n\t\t\t{\n\t\t\t\t// Ignore Metadata of m3u Version 2\n\t\t\t\tLineNo ++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (PLFileCount >= PLAlloc)\n\t\t{\n\t\t\tPLAlloc += 0x0100;\n\t\t\tPlayListFile = (char**)realloc(PlayListFile, PLAlloc * sizeof(char*));\n\t\t}\n\t\t\n\t\t// TODO:\n\t\t//\t- supprt UTF-8 m3us under Windows\n\t\t//\t- force IsUTF8 via Commandline\n#ifdef WIN32\n\t\t// Windows uses the 1252 Codepage by default\n\t\tPlayListFile[PLFileCount] = (char*)malloc((strlen(TempStr) + 0x01) * sizeof(char));\n\t\tstrcpy(PlayListFile[PLFileCount], TempStr);\n#else\n\t\tif (! IsUTF8)\n\t\t{\n\t\t\t// Most recent Linux versions use UTF-8, so I need to convert all strings.\n\t\t\tConvertCP1252toUTF8(&PlayListFile[PLFileCount], TempStr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tPlayListFile[PLFileCount] = (char*)malloc((strlen(TempStr) + 0x01) * sizeof(char));\n\t\t\tstrcpy(PlayListFile[PLFileCount], TempStr);\n\t\t}\n#endif\n\t\tStandardizeDirSeparators(PlayListFile[PLFileCount]);\n\t\tPLFileCount ++;\n\t\tLineNo ++;\n\t}\n\t\n\tfclose(hFile);\n\t\n\tRetStr = GetLastDirSeparator(FileName);\n\tif (RetStr != NULL)\n\t{\n\t\tRetStr ++;\n\t\tstrncpy(PLFileBase, FileName, RetStr - FileName);\n\t\tPLFileBase[RetStr - FileName] = '\\0';\n\t\tStandardizeDirSeparators(PLFileBase);\n\t}\n\telse\n\t{\n\t\tstrcpy(PLFileBase, \"\");\n\t}\n\t\n\treturn true;\n}\n\nstatic bool OpenMusicFile(const char* FileName)\n{\n\tif (OpenVGMFile(FileName))\n\t\treturn true;\n\telse if (OpenOtherFile(FileName))\n\t\treturn true;\n\t\n\treturn false;\n}\n\nstatic void wprintc(const wchar_t* format, ...)\n{\n\tva_list arg_list;\n\tint RetVal;\n\tUINT32 BufSize;\n\twchar_t* printbuf;\n#ifdef WIN32\n\tUINT32 StrLen;\n\tchar* oembuf;\n\tDWORD CPMode;\n#endif\n\t\n\tBufSize = 0x00;\n\tprintbuf = NULL;\n\tdo\n\t{\n\t\tBufSize += 0x100;\n\t\tprintbuf = (wchar_t*)realloc(printbuf, BufSize * sizeof(wchar_t));\n\t\t\n\t\t// Note: On Linux every vprintf call needs its own set of va_start/va_end commands.\n\t\t//       Under Windows (with VC6) one only one block for all calls works, too.\n\t\tva_start(arg_list, format);\n\t\tRetVal = _vsnwprintf(printbuf, BufSize - 0x01, format, arg_list);\n\t\tva_end(arg_list);\n\t} while(RetVal == -1 && BufSize < 0x1000);\n#ifdef WIN32\n\tStrLen = wcslen(printbuf);\n\t\n\t// This is the only way to print Unicode stuff to the Windows console.\n\t// No, wprintf doesn't work.\n\tRetVal = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), printbuf, StrLen, &CPMode, NULL);\n\tif (! RetVal)\t// call failed (e.g. with ERROR_CALL_NOT_IMPLEMENTED on Win95)\n\t{\n\t\t// fallback to printf with OEM codepage\n\t\toembuf = (char*)malloc(BufSize);\n\t\t/*if (GetConsoleOutputCP() == GetOEMCP())\n\t\t\tCPMode = CP_OEMCP;\n\t\telse\n\t\t\tCPMode = CP_ACP;*/\n\t\tCPMode = GetConsoleOutputCP();\n\t\tWideCharToMultiByte(CPMode, 0x00, printbuf, StrLen + 1, oembuf, BufSize, NULL, NULL);\n\t\t\n\t\tprintf(\"%s\", oembuf);\n\t\tfree(oembuf);\n\t}\n#else\n\t// on Linux, it's easy\n\tprintf(\"%ls\", printbuf);\n#endif\n\t\n\tfree(printbuf);\n\t\n\treturn;\n}\n\nstatic void PrintChipStr(UINT8 ChipID, UINT8 SubType, UINT32 Clock)\n{\n\tif (! Clock)\n\t\treturn;\n\t\n\tif (ChipID == 0x00 && (Clock & 0x80000000))\n\t\tClock &= ~0x40000000;\n\tif (Clock & 0x80000000)\n\t{\n\t\tClock &= ~0x80000000;\n\t\tChipID |= 0x80;\n\t}\n\t\n\tif (Clock & 0x40000000)\n\t\tprintf(\"2x\");\n\tprintf(\"%s, \", GetAccurateChipName(ChipID, SubType));\n\t\n\treturn;\n}\n\nconst wchar_t* GetTagStrEJ(const wchar_t* EngTag, const wchar_t* JapTag)\n{\n\tconst wchar_t* RetTag;\n\t\n\tif (EngTag == NULL || ! wcslen(EngTag))\n\t{\n\t\tRetTag = JapTag;\n\t}\n\telse if (JapTag == NULL || ! wcslen(JapTag))\n\t{\n\t\tRetTag = EngTag;\n\t}\n\telse\n\t{\n\t\tif (! PreferJapTag)\n\t\t\tRetTag = EngTag;\n\t\telse\n\t\t\tRetTag = JapTag;\n\t}\n\t\n\tif (RetTag == NULL)\n\t\treturn L\"\";\n\telse\n\t\treturn RetTag;\n}\n\nstatic void ShowVGMTag(void)\n{\n\tconst wchar_t* TitleTag;\n\tconst wchar_t* GameTag;\n\tconst wchar_t* AuthorTag;\n\tconst wchar_t* SystemTag;\n\tUINT8 CurChip;\n\tUINT32 ChpClk;\n\tUINT8 ChpType;\n\tINT16 VolMod;\n#ifdef SET_CONSOLE_TITLE\n\twchar_t TitleStr[0x80];\n\tUINT32 StrLen;\n#endif\n\t\n\tTitleTag = GetTagStrEJ(VGMTag.strTrackNameE, VGMTag.strTrackNameJ);\n\tGameTag = GetTagStrEJ(VGMTag.strGameNameE, VGMTag.strGameNameJ);\n\tAuthorTag = GetTagStrEJ(VGMTag.strAuthorNameE, VGMTag.strAuthorNameJ);\n\tSystemTag = GetTagStrEJ(VGMTag.strSystemNameE, VGMTag.strSystemNameJ);\n\t\n#ifdef SET_CONSOLE_TITLE\n\t// --- Show \"Song (Game) - VGM Player\" as Console Title ---\n\tif (! wcslen(TitleTag))\n\t{\n\t\tchar* TempPtr1;\n\t\tchar* TempPtr2;\n\t\t\n\t\tTempPtr1 = strrchr(VgmFileName, '\\\\');\n\t\tTempPtr2 = strrchr(VgmFileName, '/');\n\t\tif (TempPtr1 < TempPtr2)\n\t\t\tTempPtr1 = TempPtr2;\n\t\tif (TempPtr1 == NULL)\n\t\t\tTempPtr1 = VgmFileName;\n\t\telse\n\t\t\tTempPtr1 ++;\n\t\t//strncpy(TitleStr, TempPtr1, 0x70);\n\t\tmbstowcs(TitleStr, TempPtr1, 0x7F);\n\t\tTitleStr[0x70] = '\\0';\n\t}\n\telse\n\t{\n#if (defined(_MSC_VER) && _MSC_VER < 1400) || defined(OLD_SWPRINTF)\n\t\tswprintf(TitleStr, L\"%.*ls\", 0x70, TitleTag);\n#else\n\t\tswprintf(TitleStr, 0x80, L\"%.*ls\", 0x70, TitleTag);\n#endif\n\t}\n\tStrLen = wcslen(TitleStr);\n\t\n\tif (wcslen(GameTag) && StrLen < 0x6C)\n\t{\n#if (defined(_MSC_VER) && _MSC_VER < 1400) || defined(OLD_SWPRINTF)\n\t\tswprintf(TitleStr + StrLen, L\" (%.*ls)\", 0x70 - 3 - StrLen, GameTag);\n#else\n\t\tswprintf(TitleStr + StrLen, 0x80 - StrLen, L\" (%.*ls)\", 0x70 - 3 - StrLen, GameTag);\n#endif\n\t\tStrLen = wcslen(TitleStr);\n\t}\n\t\n\twcscat(TitleStr, L\" - \" APP_NAME_L);\n#ifdef WIN32\n\tSetConsoleTitleW(TitleStr);\t\t\t// Set Windows Console Title\n#else\n\tprintf(\"\\x1B]0;%ls\\x07\", TitleStr);\t// Set xterm/rxvt Terminal Title\n#endif\n#endif\n\t\n\t// --- Display Tag Data ---\n\tif (VGMHead.bytVolumeModifier <= VOLUME_MODIF_WRAP)\n\t\tVolMod = VGMHead.bytVolumeModifier;\n\telse if (VGMHead.bytVolumeModifier == (VOLUME_MODIF_WRAP + 0x01))\n\t\tVolMod = VOLUME_MODIF_WRAP - 0x100;\n\telse\n\t\tVolMod = VGMHead.bytVolumeModifier - 0x100;\n\t\n\twprintc(L\"Track Title:\\t%ls\\n\", TitleTag);\n\twprintc(L\"Game Name:\\t%ls\\n\", GameTag);\n\twprintc(L\"System:\\t\\t%ls\\n\", SystemTag);\n\twprintc(L\"Composer:\\t%ls\\n\", AuthorTag);\n\twprintc(L\"Release:\\t%ls\\n\", VGMTag.strReleaseDate);\n\tprintf(\"Version:\\t%X.%02X\\t\", VGMHead.lngVersion >> 8, VGMHead.lngVersion & 0xFF);\n\tprintf(\"  Gain:%5.2f\\t\", pow(2.0, VolMod / (double)0x20));\n\tprintf(\"Loop: \");\n\tif (VGMHead.lngLoopOffset)\n\t{\n\t\tUINT32 PbRateMul;\n\t\tUINT32 PbRateDiv;\n\t\tUINT32 PbSamples;\n\t\t\n\t\t// calculate samples for correct display with changed playback rate\n\t\tif (! VGMPbRate || ! VGMHead.lngRate)\n\t\t{\n\t\t\tPbRateMul = 1;\n\t\t\tPbRateDiv = 1;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tPbRateMul = VGMHead.lngRate;\n\t\t\tPbRateDiv = VGMPbRate;\n\t\t}\n\t\tPbSamples = (UINT32)((UINT64)VGMHead.lngLoopSamples * PbRateMul / PbRateDiv);\n\t\t\n\t\tprintf(\"Yes (\");\n\t\tPrintMinSec(PbSamples, VGMSampleRate);\n\t\tprintf(\")\\n\");\n\t}\n\telse\n\t{\n\t\tprintf(\"No\\n\");\n\t}\n\twprintc(L\"VGM by:\\t\\t%ls\\n\", VGMTag.strCreator);\n\twprintc(L\"Notes:\\t\\t%ls\\n\", VGMTag.strNotes);\n\tprintf(\"\\n\");\n\t\n\tprintf(\"Used chips:\\t\");\n\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++)\n\t{\n\t\tChpClk = GetChipClock(&VGMHead, CurChip, &ChpType);\n\t\tif (ChpClk && GetChipClock(&VGMHead, 0x80 | CurChip, NULL))\n\t\t\tChpClk |= 0x40000000;\n\t\tPrintChipStr(CurChip, ChpType, ChpClk);\n\t}\n\tprintf(\"\\b\\b \\n\");\n\tprintf(\"\\n\");\n\t\n\treturn;\n}\n\nstatic void MMKey_Event(UINT8 event)\n{\n\tlastMMEvent = event;\n\n\treturn;\n}\n\n#define LOG_SAMPLES\t(SampleRate / 5)\nstatic void PlayVGM_UI(void)\n{\n\tINT32 VGMPbSmplCount;\n\tINT32 PlaySmpl;\n\tUINT8 KeyCode;\n\tUINT32 VGMPlaySt;\n\tUINT32 VGMPlayEnd;\n\tchar WavFileName[MAX_PATH];\n\tchar* TempStr;\n\tWAVE_16BS* TempBuf;\n\tUINT8 RetVal;\n\tUINT32 TempLng;\n\tbool PosPrint;\n\tbool LastUninit;\n\tbool QuitPlay;\n\tUINT32 PlayTimeEnd;\n\t\n\tprintf(\"Initializing ...\\r\");\n\t\n\tPlayVGM();\n\tDBus_EmitSignal(SIGNAL_SEEK | SIGNAL_METADATA | SIGNAL_PLAYSTATUS | SIGNAL_CONTROLS);\n\t/*switch(LogToWave)\n\t{\n\tcase 0x00:\n\t\tbreak;\n\tcase 0x01:\n\t\t// Currently there's no record for Hardware FM\n\t\tPlayingMode = 0x00;\t// Impossible to log at full speed AND use FMPort\n\t\tbreak;\n\tcase 0x02:\n\t\tif (PlayingMode == 0x01)\n\t\t\tLogToWave = 0x00;\t// Output and log sound (FM isn't logged)\n\t\tbreak;\n\t}*/\n\tswitch(PlayingMode)\n\t{\n\tcase 0x00:\n\t\tAUDIOBUFFERU = 10;\n\t\tbreak;\n\tcase 0x01:\n\t\tAUDIOBUFFERU = 0;\t// no AudioBuffers needed\n\t\tbreak;\n\tcase 0x02:\n\t\tAUDIOBUFFERU = 5;\t// try to sync Hardware/Software Emulator as well as possible\n\t\tbreak;\n\t}\n\tif (AUDIOBUFFERU < NEED_LARGE_AUDIOBUFS)\n\t\tAUDIOBUFFERU = NEED_LARGE_AUDIOBUFS;\n\tif (ForceAudioBuf && AUDIOBUFFERU)\n\t\tAUDIOBUFFERU = ForceAudioBuf;\n\t\n\tswitch(FileMode)\n\t{\n\tcase 0x00:\t// VGM\n\t\t// RAW Log: no loop, no Creator, System Name set\n\t\tIsRAWLog = (! VGMHead.lngLoopOffset && ! wcslen(VGMTag.strCreator) &&\n\t\t\t\t\t(wcslen(VGMTag.strSystemNameE) || wcslen(VGMTag.strSystemNameJ)));\n\t\tbreak;\n\tcase 0x01:\t// CMF\n\t\tIsRAWLog = false;\n\t\tbreak;\n\tcase 0x02:\t// DRO\n\t\tIsRAWLog = true;\n\t\tbreak;\n\t}\n\tif (! VGMHead.lngTotalSamples)\n\t\tIsRAWLog = false;\n\t\n#ifndef WIN32\n\tchangemode(true);\n#endif\n\t\n\tswitch(PlayingMode)\n\t{\n\tcase 0x00:\n\tcase 0x02:\n\t\tif (LogToWave)\n\t\t{\n\t\t\tstrcpy(WavFileName, VgmFileName);\n\t\t\tTempStr = GetFileExtension(WavFileName);\n\t\t\tif (TempStr == NULL)\n\t\t\t\tTempStr = WavFileName + strlen(WavFileName);\n\t\t\telse\n\t\t\t\tTempStr --;\n\t\t\tstrcpy(TempStr, \".wav\");\n\t\t\t\n\t\t\tstrcpy(SoundLogFile, WavFileName);\n\t\t}\n\t\t//FullBufFill = ! LogToWave;\n\t\t\n\t\tswitch(LogToWave)\n\t\t{\n\t\tcase 0x00:\n\t\tcase 0x02:\n\t\t\tSoundLogging(LogToWave ? true : false);\n\t\t\tif (FirstInit || ! StreamStarted)\n\t\t\t{\n\t\t\t\t// support smooth transistions between songs\n\t\t\t\tRetVal = StartStream(OutputDevID);\n\t\t\t\tif (RetVal)\n\t\t\t\t{\n\t\t\t\t\tprintf(\"Error openning Sound Device!\\n\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tStreamStarted = true;\n\t\t\t}\n\t\t\tPauseStream(PausePlay);\n\t\t\tbreak;\n\t\tcase 0x01:\n\t\t\tTempBuf = (WAVE_16BS*)malloc(SAMPLESIZE * LOG_SAMPLES);\n\t\t\tif (TempBuf == NULL)\n\t\t\t{\n\t\t\t\tprintf(\"Allocation Error!\\n\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tStartStream(0xFF);\n\t\t\tRetVal = SaveFile(0x00000000, NULL);\n\t\t\tif (RetVal)\n\t\t\t{\n\t\t\t\tprintf(\"Can't open %s!\\n\", SoundLogFile);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase 0x01:\n\t\t// PlayVGM() does it all\n\t\t//FullBufFill = true;\n\t\tbreak;\n\t}\n\tFirstInit = false;\n\t\n\tVGMPlaySt = VGMPos;\n\tif (VGMHead.lngGD3Offset)\n\t\tVGMPlayEnd = VGMHead.lngGD3Offset;\n\telse\n\t\tVGMPlayEnd = VGMHead.lngEOFOffset;\n\tVGMPlayEnd -= VGMPlaySt;\n\tif (! FileMode)\n\t\tVGMPlayEnd --;\t// EOF Command doesn't count\n\tPosPrint = true;\n\t\n\tPlayTimeEnd = 0;\n\tQuitPlay = false;\n\twhile(! QuitPlay)\n\t{\n\t\tDBus_ReadWriteDispatch();\n\t\tif(sigint)\n\t\t{\n\t\t\tQuitPlay = true;\n\t\t\tNextPLCmd = 0xFF;\n\t\t}\n\t\t\n\t\tif (! PausePlay || PosPrint)\n\t\t{\n\t\t\tPosPrint = false;\n\t\t\t\n\t\t\tVGMPbSmplCount = SampleVGM2Playback(VGMHead.lngTotalSamples);\n\t\t\tPlaySmpl = VGMPos - VGMPlaySt;\n\n#ifdef WIN32\n\t\t\tprintf(\"Playing %01.2f%%\\t\", 100.0 * PlaySmpl / VGMPlayEnd);\n#else\n\t\t\t// \\t doesn't display correctly under Linux\n\t\t\t// but \\b causes flickering under Windows\n\t\t\tprintf(\"Playing %01.2f%%   \\b\\b\\b\\t\", 100.0 * PlaySmpl / VGMPlayEnd);\n#endif\n\t\t\tif (LogToWave != 0x01)\n\t\t\t{\n\t\t\t\tPlaySmpl = (BlocksSent - BlocksPlayed) * SMPL_P_BUFFER;\n\t\t\t\tPlaySmpl = VGMSmplPlayed - PlaySmpl;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tPlaySmpl = VGMSmplPlayed;\n\t\t\t}\n\t\t\tif (! VGMCurLoop)\n\t\t\t{\n\t\t\t\tif (PlaySmpl < 0)\n\t\t\t\t\tPlaySmpl = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//printf(\"%i\", VGMSmplPos);\n\t\t\t\twhile(PlaySmpl < SampleVGM2Playback(VGMHead.lngTotalSamples -\n\t\t\t\t\tVGMHead.lngLoopSamples))\n\t\t\t\t\tPlaySmpl += SampleVGM2Playback(VGMHead.lngLoopSamples);\n\t\t\t}\n\t\t\t//if (PlaySmpl > VGMPbSmplCount)\n\t\t\t//\tPlaySmpl = VGMPbSmplCount;\n\t\t\tPrintMinSec(PlaySmpl, SampleRate);\n\t\t\tprintf(\" / \");\n\t\t\tPrintMinSec(VGMPbSmplCount, SampleRate);\n\t\t\tprintf(\" seconds\");\n\t\t\tif (Show95Cmds && Last95Max != 0xFFFF)\n\t\t\t{\n\t\t\t\tUINT16 drumID = 1 + Last95Drum;\t// 0-based -> 1-based, 0xFFFF = 0\n\t\t\t\tif (Show95Cmds == 0x01)\n\t\t\t\t\tprintf(\"  %02hX / %02hX\", drumID , Last95Max);\n\t\t\t\telse if (Show95Cmds == 0x02)\n\t\t\t\t\tprintf(\"  %02hX / %02hX at %5u Hz\", drumID, Last95Max, Last95Freq);\n\t\t\t\telse if (Show95Cmds == 0x03)\n\t\t\t\t\tprintf(\"  %02hX / %02hX at %4.1f KHz\", drumID, Last95Max,\n\t\t\t\t\t\t\tLast95Freq / 1000.0);\n\t\t\t}\n\t\t\t//printf(\"  %u / %u\", multipcm_get_channels(0, NULL), 28);\n\t\t\tprintf(\"\\r\");\n#ifndef WIN32\n\t\t\tfflush(stdout);\n#endif\n\t\t\t\n\t\t\tif (LogToWave == 0x01 && ! PausePlay)\n\t\t\t{\n\t\t\t\tTempLng = FillBuffer(TempBuf, LOG_SAMPLES);\n\t\t\t\tif (TempLng)\n\t\t\t\t\tSaveFile(TempLng, TempBuf);\n\t\t\t\tif (EndPlay)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n#ifdef WIN32\n\t\t\t\tSleep(50);\n#endif\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n#ifdef WIN32\n\t\t\tSleep(1);\n#endif\n\t\t}\n#ifndef WIN32\n\t\tif (! PausePlay && PlayingMode != 0x01)\n\t\t\tWaveOutLinuxCallBack();\n\t\telse\n\t\t\tSleep(50);\n#endif\n\t\t\n\t\tif (EndPlay)\n\t\t{\n\t\t\tif (! PlayTimeEnd)\n\t\t\t{\n\t\t\t\tPlayTimeEnd = PlayingTime;\n\t\t\t\t// quitting now terminates the program, so I need some special\n\t\t\t\t// checks to make sure that the rest of the audio buffer is played\n\t\t\t\tif (! PLFileCount || CurPLFile >= PLFileCount - 0x01)\n\t\t\t\t{\n\t\t\t\t\tif (FileMode == 0x01)\n\t\t\t\t\t\tPlayTimeEnd += SampleRate << 1;\t// Add 2 secs\n\t\t\t\t\tPlayTimeEnd += AUDIOBUFFERU * SMPL_P_BUFFER;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (PlayingTime >= PlayTimeEnd)\n\t\t\t\tQuitPlay = true;\n\t\t}\n\t\tif (_kbhit() || lastMMEvent)\n \t\t{\n\t\t\tif (lastMMEvent)\n\t\t\t{\n\t\t\t\tif (lastMMEvent == MMKEY_PLAY)\n\t\t\t\t\tKeyCode = ' ';\n\t\t\t\telse if (lastMMEvent == MMKEY_PREV)\n\t\t\t\t\tKeyCode = 'B';\n\t\t\t\telse if (lastMMEvent == MMKEY_NEXT)\n\t\t\t\t\tKeyCode = 'N';\n\t\t\t\tlastMMEvent = 0x00;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tKeyCode = _getch();\n\t\t\t}\n\t\t\tif (KeyCode < 0x80)\n\t\t\t\tKeyCode = toupper(KeyCode);\n\t\t\tswitch(KeyCode)\n\t\t\t{\n#ifndef WIN32\n\t\t\tcase 0x1B:\t// Special Key\n\t\t\t\tKeyCode = _getch();\n\t\t\t\tif (KeyCode == 0x1B || KeyCode == 0x00)\n\t\t\t\t{\n\t\t\t\t\t// ESC Key pressed\n\t\t\t\t\tQuitPlay = true;\n\t\t\t\t\tNextPLCmd = 0xFF;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tswitch(KeyCode)\n\t\t\t\t{\n\t\t\t\tcase 0x5B:\n\t\t\t\t\t// Cursor-Key Table\n\t\t\t\t\t//\tKey\t\tKeyCode\n\t\t\t\t\t//\tUp\t\t41\n\t\t\t\t\t//\tDown\t42\n\t\t\t\t\t//\tLeft\t44\n\t\t\t\t\t//\tRight\t43\n\t\t\t\t\t// Cursor only: CursorKey\n\t\t\t\t\t// Ctrl: 0x31 + 0x3B + 0x35 + CursorKey\n\t\t\t\t\t// Alt: 0x31 + 0x3B + 0x33 + CursorKey\n\t\t\t\t\t\n\t\t\t\t\t// Page-Keys: PageKey + 0x7E\n\t\t\t\t\t//\tPageUp\t\t35\n\t\t\t\t\t//\tPageDown\t36\n\t\t\t\t\tKeyCode = _getch();\t// Get 2nd Key\n\t\t\t\t\t// Convert Cursor Key Code from Linux to Windows\n\t\t\t\t\tswitch(KeyCode)\n\t\t\t\t\t{\n\t\t\t\t\tcase 0x31:\t// Ctrl or Alt key\n\t\t\t\t\t\tKeyCode = _getch();\n\t\t\t\t\t\tif (KeyCode == 0x3B)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tKeyCode = _getch();\n\t\t\t\t\t\t\tif (KeyCode == 0x35)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tKeyCode = _getch();\n\t\t\t\t\t\t\t\tswitch(KeyCode)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase 0x41:\n\t\t\t\t\t\t\t\t\tKeyCode = 0x8D;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x42:\n\t\t\t\t\t\t\t\t\tKeyCode = 0x91;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x43:\n\t\t\t\t\t\t\t\t\tKeyCode = 0x74;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x44:\n\t\t\t\t\t\t\t\t\tKeyCode = 0x73;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tKeyCode = 0x00;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ((KeyCode & 0xF0) == 0x30)\n\t\t\t\t\t\t\tKeyCode = 0x00;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x35:\n\t\t\t\t\t\tKeyCode = 0x49;\n\t\t\t\t\t\t_getch();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x36:\n\t\t\t\t\t\tKeyCode = 0x51;\n\t\t\t\t\t\t_getch();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x41:\n\t\t\t\t\t\tKeyCode = 0x48;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x42:\n\t\t\t\t\t\tKeyCode = 0x50;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x43:\n\t\t\t\t\t\tKeyCode = 0x4D;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x44:\n\t\t\t\t\t\tKeyCode = 0x4B;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tKeyCode = 0x00;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// At this point I have Windows-style keys.\n#else\t//#ifdef WIN32\n\t\t\tcase 0xE0:\t// Special Key\n\t\t\t\t// Cursor-Key Table\n\t\t\t\t// Shift + Cursor results in the usual value for the Cursor Key\n\t\t\t\t// Alt + Cursor results in 0x00 + (0x50 + CursorKey) (0x00 instead of 0xE0)\n\t\t\t\t//\tKey\t\tNone\tCtrl\n\t\t\t\t//\tUp\t\t48\t\t8D\n\t\t\t\t//\tDown\t50\t\t91\n\t\t\t\t//\tLeft\t4B\t\t73\n\t\t\t\t//\tRight\t4D\t\t74\n\t\t\t\tKeyCode = _getch();\t// Get 2nd Key\n#endif\n\t\t\t\tswitch(KeyCode)\n\t\t\t\t{\n\t\t\t\tcase 0x4B:\t// Cursor Left\n\t\t\t\t\tPlaySmpl = -5;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x4D:\t// Cursor Right\n\t\t\t\t\tPlaySmpl = 5;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x73:\t// Ctrl + Cursor Left\n\t\t\t\t\tPlaySmpl = -60;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x74:\t// Ctrl + Cursor Right\n\t\t\t\t\tPlaySmpl = 60;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x49:\t// Page Up\n\t\t\t\t\tif (PLFileCount && /*! NextPLCmd &&*/ CurPLFile)\n\t\t\t\t\t{\n\t\t\t\t\t\tNextPLCmd = 0x01;\n\t\t\t\t\t\tQuitPlay = true;\n\t\t\t\t\t}\n\t\t\t\t\tPlaySmpl = 0;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x51:\t// Page Down\n\t\t\t\t\tif (PLFileCount && /*! NextPLCmd &&*/ CurPLFile < PLFileCount - 0x01)\n\t\t\t\t\t{\n\t\t\t\t\t\tNextPLCmd = 0x00;\n\t\t\t\t\t\tQuitPlay = true;\n\t\t\t\t\t}\n\t\t\t\t\tPlaySmpl = 0;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tPlaySmpl = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (PlaySmpl)\n\t\t\t\t{\n\t\t\t\t\tSeekVGM(true, PlaySmpl * SampleRate);\n\t\t\t\t\tPosPrint = true;\n\t\t\t\t\tDBus_EmitSignal(SIGNAL_SEEK);\n\t\t\t\t}\n\t\t\t\tbreak;\n#ifdef WIN32\n\t\t\tcase 0x1B:\t// ESC\n#endif\n\t\t\tcase 'Q':\n\t\t\t\tQuitPlay = true;\n\t\t\t\tNextPLCmd = 0xFF;\n\t\t\t\tbreak;\n\t\t\tcase ' ':\n\t\t\t\tPauseVGM(! PausePlay);\n\t\t\t\tPosPrint = true;\n\t\t\t\tDBus_EmitSignal(SIGNAL_PLAYSTATUS); // Emit status change signal\n\t\t\t\tbreak;\n\t\t\tcase 'F':\t// Fading\n\t\t\t\tFadeTime = FadeTimeN;\n\t\t\t\tFadePlay = true;\n\t\t\t\tbreak;\n\t\t\tcase 'R':\t// Restart\n\t\t\t\tDBus_EmitSignal(SIGNAL_SEEK);\n\t\t\t\tRestartVGM();\n\t\t\t\tPosPrint = true;\n\t\t\t\tbreak;\n\t\t\tcase 'B':\t// Previous file (Back)\n\t\t\t\tif (PLFileCount && /*! NextPLCmd &&*/ CurPLFile)\n\t\t\t\t{\n\t\t\t\t\tNextPLCmd = 0x01;\n\t\t\t\t\tQuitPlay = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'N':\t// Next file\n\t\t\t\tif (PLFileCount && /*! NextPLCmd &&*/ CurPLFile < PLFileCount - 0x01)\n\t\t\t\t{\n\t\t\t\t\tNextPLCmd = 0x00;\n\t\t\t\t\tQuitPlay = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\t/*if (! PauseThread && FadePlay && (! FadeTime || MasterVol == 0.0f))\n\t\t{\n\t\t\tQuitPlay = true;\n\t\t}*/\n\t\tif (FadeRAWLog && IsRAWLog && ! PausePlay && ! FadePlay && FadeTimeN)\n\t\t{\n\t\t\tPlaySmpl = (INT32)VGMHead.lngTotalSamples -\n\t\t\t\t\t\tFadeTimeN * VGMSampleRate / 1500;\n\t\t\tif (VGMSmplPos >= PlaySmpl)\n\t\t\t{\n\t\t\t\tFadeTime = FadeTimeN;\n\t\t\t\tFadePlay = true;\t// (FadeTime / 1500) ends at 33%\n\t\t\t}\n\t\t}\n\t}\n\tThreadNoWait = false;\n\t\n\t// Last Uninit: ESC pressed, no playlist, last file in playlist\n\tLastUninit = (NextPLCmd & 0x80) || ! PLFileCount ||\n\t\t\t\t(NextPLCmd == 0x00 && CurPLFile >= PLFileCount - 0x01);\n\tswitch(PlayingMode)\n\t{\n\tcase 0x00:\n\t\tswitch(LogToWave)\n\t\t{\n\t\tcase 0x00:\n\t\tcase 0x02:\n\t\t\tif (LastUninit)\n\t\t\t{\n\t\t\t\tStopStream();\n\t\t\t\tStreamStarted = false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (ThreadPauseEnable)\n\t\t\t\t{\n\t\t\t\t\tThreadPauseConfrm = false;\n\t\t\t\t\tPauseThread = true;\n\t\t\t\t\twhile(! ThreadPauseConfrm)\n\t\t\t\t\t\tSleep(1);\t// Wait until the Thread is finished\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tPauseThread = true;\n\t\t\t\t}\n\t\t\t\tif (LogToWave)\n\t\t\t\t\tSaveFile(0xFFFFFFFF, NULL);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 0x01:\n\t\t\tSaveFile(0xFFFFFFFF, NULL);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase 0x01:\n\t\tif (StreamStarted)\n\t\t{\n\t\t\tStopStream();\n\t\t\tStreamStarted = false;\n\t\t}\n\t\tbreak;\n\tcase 0x02:\n\t\tif (LastUninit)\n\t\t{\n\t\t\tStopStream();\n\t\t\tStreamStarted = false;\n#ifdef MIXER_MUTING\n#ifdef WIN32\n\t\t\tmixerClose(hmixer);\n#else\n\t\t\tclose(hmixer);\n#endif\n#endif\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (ThreadPauseEnable)\n\t\t\t{\n\t\t\t\tThreadPauseConfrm = false;\n\t\t\t\tPauseThread = true;\n\t\t\t\twhile(! ThreadPauseConfrm)\n\t\t\t\t\tSleep(1);\t// Wait until the Thread is finished\n\t\t\t\tPauseStream(true);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tPauseThread = true;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t}\n#ifndef WIN32\n\tchangemode(false);\n#endif\n\t\n\tStopVGM();\n\t\n\tprintf(\"\\nPlaying finished.\\n\");\n\t\n\treturn;\n}\n\nINLINE INT8 sign(double Value)\n{\n\tif (Value > 0.0)\n\t\treturn 1;\n\telse if (Value < 0.0)\n\t\treturn -1;\n\telse\n\t\treturn 0;\n}\n\nINLINE long int Round(double Value)\n{\n\t// Alternative:\t(fabs(Value) + 0.5) * sign(Value);\n\treturn (long int)(Value + 0.5 * sign(Value));\n}\n\nINLINE double RoundSpecial(double Value, double RoundTo)\n{\n\treturn (long int)(Value / RoundTo + 0.5 * sign(Value)) * RoundTo;\n}\n\nstatic void PrintMinSec(UINT32 SamplePos, UINT32 SmplRate)\n{\n\tfloat TimeSec;\n\tUINT16 TimeMin;\n\tUINT16 TimeHours;\n\t\n\tTimeSec = (float)RoundSpecial(SamplePos / (double)SmplRate, 0.01);\n\t//TimeSec = SamplePos / (float)SmplRate;\n\tTimeMin = (UINT16)TimeSec / 60;\n\tTimeSec -= TimeMin * 60;\n\tif (! PrintMSHours)\n\t{\n\t\tprintf(\"%02hu:%05.2f\", TimeMin, TimeSec);\n\t}\n\telse\n\t{\n\t\tTimeHours = TimeMin / 60;\n\t\tTimeMin %= 60;\n\t\tprintf(\"%hu:%02hu:%05.2f\", TimeHours, TimeMin, TimeSec);\n\t}\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/VGMPlay_AddFmts.c",
    "content": "// VGMPlay_AddFmts.c: C Source File for playback of additional non-VGM formats\n#define _GNU_SOURCE\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <wchar.h>\n#include \"stdbool.h\"\n#include <math.h>\n\n#ifdef WIN32\n//#include <windows.h>\nvoid __stdcall Sleep(unsigned int dwMilliseconds);\n#else\n#include <unistd.h>\n#define\tSleep(msec)\t\tusleep(msec * 1000)\n#endif\n\n#include <zlib.h>\n\n#include \"chips/mamedef.h\"\n\n#include \"VGMPlay.h\"\n\n#include \"ChipMapper.h\"\n\n// Structures for DRO and CMF files\ntypedef struct _cmf_file_header\n{\n\tUINT32 fccCMF;\n\tUINT16 shtVersion;\n\tUINT16 shtOffsetInsData;\n\tUINT16 shtOffsetMusData;\n\tUINT16 shtTickspQuarter;\n\tUINT16 shtTickspSecond;\n\tUINT16 shtOffsetTitle;\n\tUINT16 shtOffsetAuthor;\n\tUINT16 shtOffsetComments;\n\tUINT8 bytChnUsed[0x10];\n\tUINT16 shtInstrumentCount;\n\tUINT16 shtTempo;\n} CMF_HEADER;\ntypedef struct _cmf_instrument_table\n{\n\tUINT8 Character[0x02];\n\tUINT8 ScaleLevel[0x02];\n\tUINT8 AttackDelay[0x02];\n\tUINT8 SustnRelease[0x02];\n\tUINT8 WaveSelect[0x02];\n\tUINT8 FeedbConnect;\n\tUINT8 Reserved[0x5];\n} CMF_INSTRUMENT;\n\ntypedef struct _dro_file_header\n{\n\tchar cSignature[0x08];\n\tUINT16 iVersionMajor;\n\tUINT16 iVersionMinor;\n} DRO_HEADER;\ntypedef struct _dro_version_header_1\n{\n\tUINT32 iLengthMS;\n\tUINT32 iLengthBytes;\n\tUINT32 iHardwareType;\n} DRO_VER_HEADER_1;\ntypedef struct _dro_version_header_2\n{\n\tUINT32 iLengthPairs;\n\tUINT32 iLengthMS;\n\tUINT8 iHardwareType;\n\tUINT8 iFormat;\n\tUINT8 iCompression;\n\tUINT8 iShortDelayCode;\n\tUINT8 iLongDelayCode;\n\tUINT8 iCodemapLength;\n} DRO_VER_HEADER_2;\n\n#define FCC_CMF\t\t0x464D5443\t// 'CTMF'\n#define FCC_DRO1\t0x41524244\t// 'DBRA'\n#define FCC_DRO2\t0x4C504F57\t// 'WOPL'\n\nextern UINT32 GetGZFileLength(const char* FileName);\n//bool OpenOtherFile(const char* FileName)\n\nINLINE UINT16 ReadLE16(const UINT8* Data);\nINLINE UINT32 ReadLE32(const UINT8* Data);\nINLINE int gzgetLE32(gzFile hFile, UINT32* RetValue);\n\nstatic UINT32 GetMIDIDelay(UINT32* DelayLen);\nstatic UINT16 MIDINote2FNum(UINT8 Note, INT8 Pitch);\nstatic void SendMIDIVolume(UINT8 ChipID, UINT8 Channel, UINT8 Command,\n\t\t\t\t\t\t   UINT8 ChnIns, UINT8 Volume);\n//void InterpretOther(UINT32 SampleCount);\n\nINLINE INT32 SampleVGM2Playback(INT32 SampleVal);\nINLINE INT32 SamplePlayback2VGM(INT32 SampleVal);\n\n\nextern UINT32 SampleRate;\t// Note: also used by some sound cores to determinate the chip sample rate\n\nextern UINT8 FileMode;\nextern VGM_HEADER VGMHead;\nextern UINT32 VGMDataLen;\nextern UINT8* VGMData;\nextern GD3_TAG VGMTag;\n\nCMF_HEADER CMFHead;\nUINT16 CMFInsCount;\nCMF_INSTRUMENT* CMFIns;\n\nDRO_HEADER DROHead;\nDRO_VER_HEADER_2 DROInf;\nUINT8* DROCodemap;\n\n\nextern UINT32 VGMPos;\nextern INT32 VGMSmplPos;\nextern INT32 VGMSmplPlayed;\nextern INT32 VGMSampleRate;\nextern UINT32 BlocksSent;\nextern UINT32 BlocksPlayed;\nextern bool VGMEnd;\nextern bool EndPlay;\nextern bool PausePlay;\nextern bool FadePlay;\nextern bool ForceVGMExec;\n\nextern UINT32 VGMMaxLoop;\nUINT32 CMFMaxLoop;\nextern UINT32 VGMMaxLoopM;\nextern UINT32 VGMCurLoop;\n\nextern UINT32 FadeTime;\nextern UINT32 VGMMaxLoop;\nextern bool ErrorHappened;\n\nextern UINT8 CmdList[0x100];\n\nbool OpenOtherFile(const char* FileName)\n{\n\tgzFile hFile;\n\tUINT32 FileSize;\n\tUINT32 fccHeader;\n\tUINT32 CurPos;\n\tUINT32 TempLng;\n\tUINT16 FileVer;\n\tconst char* TempStr;\n\tDRO_VER_HEADER_1 DRO_V1;\n\t\n\tFileSize = GetGZFileLength(FileName);\n\t\n\tFileMode = 0x00;\n\thFile = gzopen(FileName, \"rb\");\n\tif (hFile == NULL)\n\t\treturn false;\n\t\n\tgzseek(hFile, 0x00, SEEK_SET);\n\tgzgetLE32(hFile, &fccHeader);\n\tswitch(fccHeader)\n\t{\n\tcase FCC_VGM:\n\t\tFileMode = 0xFF;\t// should already be opened\n\t\tbreak;\n\tcase FCC_CMF:\n\t\tFileMode = 0x01;\n\t\tbreak;\n\tcase FCC_DRO1:\n\t\tgzgetLE32(hFile, &fccHeader);\n\t\tif (fccHeader == FCC_DRO2)\n\t\t\tFileMode = 0x02;\n\t\telse\n\t\t\tFileMode = 0xFF;\n\t\tbreak;\n\tdefault:\n\t\tFileMode = 0xFF;\n\t\tbreak;\n\t}\n\tif (FileMode == 0xFF)\n\t\tgoto OpenErr;\n\t\n\tVGMTag.strTrackNameE = L\"\";\n\tVGMTag.strTrackNameJ = L\"\";\n\tVGMTag.strGameNameE = L\"\";\n\tVGMTag.strGameNameJ = L\"\";\n\tVGMTag.strSystemNameE = L\"\";\n\tVGMTag.strSystemNameJ = L\"\";\n\tVGMTag.strAuthorNameE = L\"\";\n\tVGMTag.strAuthorNameJ = L\"\";\n\tVGMTag.strReleaseDate = L\"\";\n\tVGMTag.strCreator = L\"\";\n\tVGMTag.strNotes = L\"\";\n\t\n\tswitch(FileMode)\n\t{\n\tcase 0x00:\t// VGM File\n\t\tbreak;\n\tcase 0x01:\t// CMF File\n\tcase 0x02:\t// DosBox RAW OPL\n\t\tVGMTag.strGameNameE = (wchar_t*)malloc(0x10 * sizeof(wchar_t*));\n\t\twcscpy(VGMTag.strGameNameE, L\"    Player\");\n\t\tVGMTag.strSystemNameE = L\"PC / MS-DOS\";\n\t\tbreak;\n\t}\n\t\n\tVGMDataLen = FileSize;\n\t\n\tswitch(FileMode)\n\t{\n\tcase 0x00:\t// VGM File\n\t\t// already done by OpenVGMFile\n\t\tbreak;\n\tcase 0x01:\t// CMF File\n\t\t// Read Data\n\t\tVGMData = (UINT8*)malloc(VGMDataLen);\n\t\tif (VGMData == NULL)\n\t\t\tgoto OpenErr;\n\t\tgzseek(hFile, 0x00, SEEK_SET);\n\t\tgzread(hFile, VGMData, VGMDataLen);\n\t\t\n#ifdef VGM_LITTLE_ENDIAN\n\t\tmemcpy(&CMFHead, &VGMData[0x00], sizeof(CMF_HEADER));\n#else\n\t\tCMFHead.fccCMF = ReadLE32(&VGMData[0x00]);\n\t\tCMFHead.shtVersion = ReadLE16(&VGMData[0x04]);\n\t\tCMFHead.shtOffsetInsData = ReadLE16(&VGMData[0x06]);\n\t\tCMFHead.shtOffsetMusData = ReadLE16(&VGMData[0x08]);\n\t\tCMFHead.shtTickspQuarter = ReadLE16(&VGMData[0x0A]);\n\t\tCMFHead.shtTickspSecond = ReadLE16(&VGMData[0x0C]);\n\t\tCMFHead.shtOffsetTitle = ReadLE16(&VGMData[0x0E]);\n\t\tCMFHead.shtOffsetAuthor = ReadLE16(&VGMData[0x10]);\n\t\tCMFHead.shtOffsetComments = ReadLE16(&VGMData[0x12]);\n\t\tmemcpy(CMFHead.bytChnUsed, &VGMData[0x14], 0x10);\n\t\tCMFHead.shtInstrumentCount = ReadLE16(&VGMData[0x24]);\n\t\tCMFHead.shtTempo = ReadLE16(&VGMData[0x26]);\n#endif\n\t\t\n\t\tif (CMFHead.shtVersion == 0x0100)\n\t\t{\n\t\t\tCMFHead.shtInstrumentCount &= 0x00FF;\n\t\t\tCMFHead.shtTempo = (UINT16)(60.0 *\n\t\t\t\t\t\t\t\tCMFHead.shtTickspQuarter / CMFHead.shtTickspSecond + 0.5);\n\t\t}\n\t\t\n\t\tif (CMFHead.shtOffsetTitle)\n\t\t{\n\t\t\tTempStr = (char*)&VGMData[CMFHead.shtOffsetTitle];\n\t\t\tTempLng = strlen(TempStr) + 0x01;\n\t\t\tVGMTag.strTrackNameE = (wchar_t*)malloc(TempLng * sizeof(wchar_t));\n\t\t\tmbstowcs(VGMTag.strTrackNameE, TempStr, TempLng);\n\t\t}\n\t\tVGMTag.strGameNameE[0x00] = 'C';\n\t\tVGMTag.strGameNameE[0x01] = 'M';\n\t\tVGMTag.strGameNameE[0x02] = 'F';\n\t\tif (CMFHead.shtOffsetAuthor)\n\t\t{\n\t\t\tTempStr = (char*)&VGMData[CMFHead.shtOffsetAuthor];\n\t\t\tTempLng = strlen(TempStr) + 0x01;\n\t\t\tVGMTag.strAuthorNameE = (wchar_t*)malloc(TempLng * sizeof(wchar_t));\n\t\t\tmbstowcs(VGMTag.strAuthorNameE, TempStr, TempLng);\n\t\t}\n\t\tif (CMFHead.shtOffsetComments)\n\t\t{\n\t\t\tTempStr = (char*)&VGMData[CMFHead.shtOffsetComments];\n\t\t\tTempLng = strlen(TempStr) + 0x01;\n\t\t\tVGMTag.strNotes = (wchar_t*)malloc(TempLng * sizeof(wchar_t));\n\t\t\tmbstowcs(VGMTag.strNotes, TempStr, TempLng);\n\t\t}\n\t\t\n\t\tCMFInsCount = CMFHead.shtInstrumentCount;\n\t\tTempLng = CMFInsCount * sizeof(CMF_INSTRUMENT);\n\t\tCMFIns = (CMF_INSTRUMENT*)malloc(TempLng);\n\t\tmemcpy(CMFIns, &VGMData[CMFHead.shtOffsetInsData], TempLng);\n\t\t\n\t\tmemset(&VGMHead, 0x00, sizeof(VGM_HEADER));\n\t\tVGMHead.lngEOFOffset = VGMDataLen;\n\t\tVGMHead.lngVersion = CMFHead.shtVersion;\n\t\tVGMHead.lngDataOffset = CMFHead.shtOffsetMusData;\n\t\tVGMSampleRate = CMFHead.shtTickspSecond;\n\t\tVGMHead.lngTotalSamples = 0;\n\t\tVGMHead.lngHzYM3812 = 3579545 | 0x40000000;\n\t\t\n\t\tbreak;\n\tcase 0x02:\t// DosBox RAW OPL\n\t\t// Read Data\n\t\tVGMData = (UINT8*)malloc(VGMDataLen);\n\t\tif (VGMData == NULL)\n\t\t\tgoto OpenErr;\n\t\tgzseek(hFile, 0x00, SEEK_SET);\n\t\tVGMDataLen = gzread(hFile, VGMData, VGMDataLen);\n\t\t\n\t\tVGMTag.strGameNameE[0x00] = 'D';\n\t\tVGMTag.strGameNameE[0x01] = 'R';\n\t\tVGMTag.strGameNameE[0x02] = 'O';\n\t\t\n\t\tmemset(&VGMHead, 0x00, sizeof(VGM_HEADER));\n\t\tCurPos = 0x00;\n#ifdef VGM_LITTLE_ENDIAN\n\t\tmemcpy(&DROHead, &VGMData[CurPos], sizeof(DRO_HEADER));\n#else\n\t\tmemcpy(DROHead.cSignature,\t\t\t&VGMData[CurPos + 0x00], 0x08);\n\t\tDROHead.iVersionMajor = ReadLE16(\t&VGMData[CurPos + 0x08]);\n\t\tDROHead.iVersionMinor = ReadLE16(\t&VGMData[CurPos + 0x0A]);\n#endif\n\t\tCurPos += sizeof(DRO_HEADER);\n\t\t\n\t\tmemcpy(&TempLng, &VGMData[0x08], sizeof(UINT32));\n\t\tif (TempLng & 0xFF00FF00)\n\t\t{\n\t\t\t// DosBox Version 0.61\n\t\t\t// this version didn't contain Version Bytes\n\t\t\tCurPos = 0x08;\n\t\t\tDROHead.iVersionMajor = 0x00;\n\t\t\tDROHead.iVersionMinor = 0x00;\n\t\t}\n\t\telse if (! (TempLng & 0x0000FFFF))\n\t\t{\n\t\t\t// DosBox Version 0.63\n\t\t\t// the order of the Version Bytes is swapped in this version\n\t\t\tFileVer = DROHead.iVersionMinor;\n\t\t\tif (FileVer == 0x01)\n\t\t\t{\n\t\t\t\tDROHead.iVersionMinor = DROHead.iVersionMajor;\n\t\t\t\tDROHead.iVersionMajor = FileVer;\n\t\t\t}\n\t\t}\n\t\tVGMHead.lngEOFOffset = VGMDataLen;\n\t\tVGMHead.lngVersion = (DROHead.iVersionMajor << 8) |\n\t\t\t\t\t\t\t((DROHead.iVersionMinor & 0xFF) << 0);\n\t\tVGMSampleRate = 1000;\n\t\t\n\t\tif (DROHead.iVersionMajor > 2)\n\t\t\tDROHead.iVersionMajor = 2;\n\t\tswitch(DROHead.iVersionMajor)\n\t\t{\n\t\tcase 0:\t// Version 0 (DosBox Version 0.61)\n\t\tcase 1:\t// Version 1 (DosBox Version 0.63)\n\t\t\tswitch(DROHead.iVersionMajor)\n\t\t\t{\n\t\t\tcase 0:\t// Version 0\n\t\t\t\tDRO_V1.iLengthMS = ReadLE32(&VGMData[CurPos + 0x00]);\n\t\t\t\tDRO_V1.iLengthBytes = ReadLE32(&VGMData[CurPos + 0x04]);\n\t\t\t\tDRO_V1.iHardwareType = VGMData[CurPos + 0x08];\n\t\t\t\tCurPos += 0x09;\n\t\t\t\tbreak;\n\t\t\tcase 1:\t// Version 1\n\t\t\t\tDRO_V1.iLengthMS = ReadLE32(&VGMData[CurPos + 0x00]);\n\t\t\t\tDRO_V1.iLengthBytes = ReadLE32(&VGMData[CurPos + 0x04]);\n\t\t\t\tDRO_V1.iHardwareType = ReadLE32(&VGMData[CurPos + 0x08]);\n\t\t\t\tCurPos += 0x0C;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tDROInf.iLengthPairs = DRO_V1.iLengthBytes >> 1;\n\t\t\tDROInf.iLengthMS = DRO_V1.iLengthMS;\n\t\t\tswitch(DRO_V1.iHardwareType)\n\t\t\t{\n\t\t\tcase 0x01:\t// Single OPL3\n\t\t\t\tDROInf.iHardwareType = 0x02;\n\t\t\t\tbreak;\n\t\t\tcase 0x02:\t// Dual OPL2\n\t\t\t\tDROInf.iHardwareType = 0x01;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tDROInf.iHardwareType = (UINT8)DRO_V1.iHardwareType;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tDROInf.iFormat = 0x00;\n\t\t\tDROInf.iCompression = 0x00;\n\t\t\tDROInf.iShortDelayCode = 0x00;\n\t\t\tDROInf.iLongDelayCode = 0x01;\n\t\t\tDROInf.iCodemapLength = 0x00;\n\t\t\t\n\t\t\tbreak;\n\t\tcase 2:\t// Version 2 (DosBox Version 0.73)\n\t\t\t// sizeof(DRO_VER_HEADER_2) returns 0x10, but the exact size is 0x0E\n\t\t\t//memcpy(&DROInf, &VGMData[CurPos], 0x0E);\n\t\t\tDROInf.iLengthPairs =\tReadLE32(\t&VGMData[CurPos + 0x00]);\n\t\t\tDROInf.iLengthMS =\t\tReadLE32(\t&VGMData[CurPos + 0x04]);\n\t\t\tDROInf.iHardwareType =\t\t\t\t VGMData[CurPos + 0x08];\n\t\t\tDROInf.iFormat =\t\t\t\t\t VGMData[CurPos + 0x09];\n\t\t\tDROInf.iCompression =\t\t\t\t VGMData[CurPos + 0x0A];\n\t\t\tDROInf.iShortDelayCode =\t\t\t VGMData[CurPos + 0x0B];\n\t\t\tDROInf.iLongDelayCode =\t\t\t\t VGMData[CurPos + 0x0C];\n\t\t\tDROInf.iCodemapLength =\t\t\t\t VGMData[CurPos + 0x0D];\n\t\t\tCurPos += 0x0E;\n\t\t\t\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tif (DROInf.iCodemapLength)\n\t\t{\n\t\t\tDROCodemap = (UINT8*)malloc(DROInf.iCodemapLength * sizeof(UINT8));\n\t\t\tmemcpy(DROCodemap, &VGMData[CurPos], DROInf.iCodemapLength);\n\t\t\tCurPos += DROInf.iCodemapLength;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDROCodemap = NULL;\n\t\t}\n\t\t\n\t\tVGMHead.lngDataOffset = CurPos;\n\t\tVGMHead.lngTotalSamples = DROInf.iLengthMS;\n\t\tswitch(DROInf.iHardwareType)\n\t\t{\n\t\tcase 0x00:\t// Single OPL2 Chip\n\t\t\tVGMHead.lngHzYM3812 = 3579545;\n\t\t\tbreak;\n\t\tcase 0x01:\t// Dual OPL2 Chip\n\t\t\tVGMHead.lngHzYM3812 = 3579545 | 0xC0000000;\n\t\t\tbreak;\n\t\tcase 0x02:\t// Single OPL3 Chip\n\t\t\tVGMHead.lngHzYMF262 = 14318180;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tVGMHead.lngHzYM3812 = 3579545 | 0x40000000;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tbreak;\n\t}\n\t\n\tgzclose(hFile);\n\treturn true;\n\nOpenErr:\n\n\tgzclose(hFile);\n\treturn false;\n}\n\nINLINE UINT16 ReadLE16(const UINT8* Data)\n{\n\t// read 16-Bit Word (Little Endian/Intel Byte Order)\n#ifdef VGM_LITTLE_ENDIAN\n\treturn *(UINT16*)Data;\n#else\n\treturn\t(Data[0x01] << 8) | (Data[0x00] << 0);\n#endif\n}\n\nINLINE UINT32 ReadLE32(const UINT8* Data)\n{\n\t// read 32-Bit Word (Little Endian/Intel Byte Order)\n#ifdef VGM_LITTLE_ENDIAN\n\treturn *(UINT32*)Data;\n#else\n\treturn\t(Data[0x03] << 24) | (Data[0x02] << 16) |\n\t\t\t(Data[0x01] <<  8) | (Data[0x00] <<  0);\n#endif\n}\n\nINLINE int gzgetLE32(gzFile hFile, UINT32* RetValue)\n{\n#ifdef VGM_LITTLE_ENDIAN\n\treturn gzread(hFile, RetValue, 0x04);\n#else\n\tint RetVal;\n\tUINT8 Data[0x04];\n\t\n\tRetVal = gzread(hFile, Data, 0x04);\n\t*RetValue =\t(Data[0x03] << 24) | (Data[0x02] << 16) |\n\t\t\t\t(Data[0x01] <<  8) | (Data[0x00] <<  0);\n\treturn RetVal;\n#endif\n}\n\nstatic UINT32 GetMIDIDelay(UINT32* DelayLen)\n{\n\tUINT32 CurPos;\n\tUINT32 DelayVal;\n\t\n\tCurPos = VGMPos;\n\tDelayVal = 0x00;\n\tdo\n\t{\n\t\tDelayVal = (DelayVal << 7) | (VGMData[CurPos] & 0x7F);\n\t} while(VGMData[CurPos ++] & 0x80);\n\t\n\tif (DelayLen != NULL)\n\t\t*DelayLen = CurPos - VGMPos;\n\treturn DelayVal;\n}\n\nstatic UINT16 MIDINote2FNum(UINT8 Note, INT8 Pitch)\n{\n\tconst double CHIP_RATE = 3579545.0 / 72.0;\t// ~49716\n\tdouble FreqVal;\n\tINT8 BlockVal;\n\tUINT16 KeyVal;\n\t\n\tFreqVal = 440.0 * pow(2, (Note - 69 + Pitch / 256.0) / 12.0);\n\tBlockVal = (Note / 12) - 1;\n\tif (BlockVal < 0x00)\n\t\tBlockVal = 0x00;\n\telse if (BlockVal > 0x07)\n\t\tBlockVal = 0x07;\n\tKeyVal = (UINT16)(FreqVal * pow(2, 20 - BlockVal) / CHIP_RATE + 0.5);\n\t\n\treturn (BlockVal << 10) | KeyVal;\t// << (8+2)\n}\n\nstatic void SendMIDIVolume(UINT8 ChipID, UINT8 Channel, UINT8 Command,\n\t\t\t\t\t\t   UINT8 ChnIns, UINT8 Volume)\n{\n\tbool RhythmOn;\n\tUINT8 TempByt;\n\t//UINT16 TempSht;\n\tUINT32 TempLng;\n\tUINT8 OpBase;\t// Operator Base\n\tCMF_INSTRUMENT* TempIns;\n\tUINT8 OpMask;\n\tINT8 OpVol;\n\tINT8 NoteVol;\n\t\n\tRhythmOn = (Channel >> 7) & 0x01;\n\tChannel &= 0x7F;\n\t\n\t// Refresh Total Level (Volume)\n\tTempIns = CMFIns + ChnIns;\n\tOpBase = (Channel / 0x03) * 0x08 + (Channel % 0x03);\n\t\n\tif (! RhythmOn)\n\t{\n\t\tTempLng = 0x01;\n\t\tOpMask = 0x03;\n\t}\n\telse\n\t{\n\t\t//TempLng = 0x01;\n\t\tswitch(Command & 0x0F)\n\t\t{\n\t\tcase 0x0B:\t// Bass Drum\n\t\t\tOpMask = 0x00;\n\t\t\tbreak;\n\t\tcase 0x0F:\t// Hi Hat\n\t\t\tOpMask = 0x00;\n\t\t\tbreak;\n\t\tcase 0x0C:\t// Snare Drum\n\t\t\tOpMask = 0x01;\n\t\t\tbreak;\n\t\tcase 0x0D:\t// Tom Tom\n\t\t\tOpMask = 0x00;\n\t\t\tbreak;\n\t\tcase 0x0E:\t// Cymbal\n\t\t\tOpMask = 0x01;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tOpMask = 0x00;\n\t\t\tbreak;\n\t\t}\n\t\tTempLng = OpMask;\n\t\tOpMask *= 0x03;\n\t}\n\t\n\t// Verified with PLAY.EXE\n\tOpVol = (Volume + 0x04) >> 3;\n\tOpVol = 0x10 - (OpVol << 1);\n\tif (OpVol < 0x00)\n\t\tOpVol >>= 1;\n\tNoteVol = (TempIns->ScaleLevel[TempLng] & 0x3F) + OpVol;\n\tif (NoteVol < 0x00)\n\t\tNoteVol = 0x00;\n\t\n\tTempByt = NoteVol | (TempIns->ScaleLevel[TempLng] & 0xC0);\n\tchip_reg_write(0x09, ChipID, 0x00, 0x40 | (OpBase + OpMask), TempByt);\n\t\n\treturn;\n}\n\nvoid InterpretOther(UINT32 SampleCount)\n{\n\tstatic UINT8 LastCmd = 0x90;\n\tstatic UINT8 DrumReg[0x02] = {0x00, 0x00};\n\tstatic UINT8 ChnIns[0x10];\n\tstatic UINT8 ChnNote[0x20];\n\tstatic INT8 ChnPitch[0x10];\n\tINT32 SmplPlayed;\n\tUINT8 Command;\n\tUINT8 Channel;\n\tUINT8 TempByt;\n\tUINT16 TempSht;\n\tUINT32 TempLng;\n\tUINT32 DataLen;\n\tstatic UINT8 CurChip = 0x00;\n\tUINT8 OpBase;\t// Operator Base\n\tCMF_INSTRUMENT* TempIns;\n\tbool RhythmOn;\n\tbool NoteOn;\n\tUINT8 OpMask;\n\t\n\tif (VGMEnd)\n\t\treturn;\n\tif (PausePlay && ! ForceVGMExec)\n\t\treturn;\n\t\n\tswitch(FileMode)\n\t{\n\tcase 0x01:\t// CMF File Mode\n\t\tif (! SampleCount)\n\t\t{\n\t\t\tmemset(ChnIns, 0xFF, 0x10);\n\t\t\tmemset(ChnNote, 0xFF, 0x20);\n\t\t\tmemset(ChnPitch, 0x00, 0x10);\n\t\t\t\n\t\t\tTempLng = VGMPos;\n\t\t\tSmplPlayed = VGMSmplPos;\n\t\t\tVGMPos = VGMHead.lngDataOffset;\n\t\t\tRhythmOn = false;\n\t\t\twhile(! RhythmOn)\n\t\t\t{\n\t\t\t\tVGMSmplPos += GetMIDIDelay(&DataLen);\n\t\t\t\tVGMPos += DataLen;\n\t\t\t\t\n\t\t\t\tCommand = VGMData[VGMPos];\n\t\t\t\tif (Command & 0x80)\n\t\t\t\t\tVGMPos ++;\n\t\t\t\telse\n\t\t\t\t\tCommand = LastCmd;\n\t\t\t\tChannel = Command & 0x0F;\n\t\t\t\t\n\t\t\t\tswitch(Command & 0xF0)\n\t\t\t\t{\n\t\t\t\tcase 0xF0:\t// End Of File\n\t\t\t\t\tswitch(Command)\n\t\t\t\t\t{\n\t\t\t\t\tcase 0xFF:\n\t\t\t\t\t\tswitch(VGMData[VGMPos + 0x00])\n\t\t\t\t\t\t{\n\t\t\t\t\t\tcase 0x2F:\n\t\t\t\t\t\t\tVGMHead.lngTotalSamples = VGMSmplPos;\n\t\t\t\t\t\t\tVGMHead.lngLoopSamples = VGMHead.lngTotalSamples;\n\t\t\t\t\t\t\tRhythmOn = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tVGMPos += 0x01;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x80:\n\t\t\t\tcase 0x90:\n\t\t\t\tcase 0xA0:\n\t\t\t\tcase 0xB0:\n\t\t\t\tcase 0xE0:\n\t\t\t\t\tVGMPos += 0x02;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0xC0:\n\t\t\t\tcase 0xD0:\n\t\t\t\t\tVGMPos += 0x01;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (Command < 0xF0)\n\t\t\t\t\tLastCmd = Command;\n\t\t\t}\n\t\t\t\n\t\t\tVGMPos = TempLng;\n\t\t\tVGMSmplPos = SmplPlayed;\n\t\t}\n\t\t\n\t\tSmplPlayed = SamplePlayback2VGM(VGMSmplPlayed + SampleCount);\n\t\twhile(true)\n\t\t{\n\t\t\tTempLng = GetMIDIDelay(&DataLen);\n\t\t\tif (VGMSmplPos + (INT32)TempLng > SmplPlayed)\n\t\t\t\tbreak;\n\t\t\tVGMSmplPos += TempLng;\n\t\t\tVGMPos += DataLen;\n\t\t\t\n\t\t\tCommand = VGMData[VGMPos];\n\t\t\tif (Command & 0x80)\n\t\t\t\tVGMPos ++;\n\t\t\telse\n\t\t\t\tCommand = LastCmd;\n\t\t\tChannel = Command & 0x0F;\n\t\t\t\n\t\t\tif (DrumReg[0x00] & 0x20)\n\t\t\t{\n\t\t\t\tif (Channel < 0x0B)\n\t\t\t\t{\n\t\t\t\t\tCurChip = Channel / 0x06;\n\t\t\t\t\tChannel = Channel % 0x06;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tChannel -= 0x0B;\n\t\t\t\t\tCurChip = Channel / 0x03;\n\t\t\t\t\tChannel = Channel % 0x03;\n\t\t\t\t\tif (CurChip == 0x01 && Channel == 0x00)\n\t\t\t\t\t\tChannel = 0x02;\n\t\t\t\t\tChannel += 0x06;\n\t\t\t\t\t// Map all drums to one chip\n\t\t\t\t\tCurChip = 0x00;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tCurChip = Channel / 0x09;\n\t\t\t\tChannel = Channel % 0x09;\n\t\t\t}\n\t\t\tCurChip = 0x00;\n\t\t\t\n\t\t\tRhythmOn = (Channel >= 0x06) && (DrumReg[CurChip] & 0x20);\n\t\t\tswitch(Command & 0xF0)\n\t\t\t{\n\t\t\tcase 0xF0:\t// End Of File\n\t\t\t\tswitch(Command)\n\t\t\t\t{\n\t\t\t\tcase 0xFF:\n\t\t\t\t\tswitch(VGMData[VGMPos + 0x00])\n\t\t\t\t\t{\n\t\t\t\t\tcase 0x2F:\n\t\t\t\t\t\tif (CMFMaxLoop != 0x01)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tVGMPos = VGMHead.lngDataOffset;\n\t\t\t\t\t\t\tVGMSmplPos -= VGMHead.lngLoopSamples;\n\t\t\t\t\t\t\tVGMSmplPlayed -= SampleVGM2Playback(VGMHead.lngLoopSamples);\n\t\t\t\t\t\t\tSmplPlayed = SamplePlayback2VGM(VGMSmplPlayed + SampleCount);\n\t\t\t\t\t\t\tVGMCurLoop ++;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (CMFMaxLoop && VGMCurLoop >= CMFMaxLoop)\n\t\t\t\t\t\t\t\tFadePlay = true;\n\t\t\t\t\t\t\tif (FadePlay && ! FadeTime)\n\t\t\t\t\t\t\t\tVGMEnd = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tVGMEnd = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tVGMPos += 0x01;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0x80:\n\t\t\tcase 0x90:\n\t\t\t\tTempSht = MIDINote2FNum(VGMData[VGMPos + 0x00], ChnPitch[Channel]);\n\t\t\t\tif ((Command & 0xF0) == 0x80)\n\t\t\t\t\tNoteOn = false;\n\t\t\t\telse\n\t\t\t\t\tNoteOn = VGMData[VGMPos + 0x01] ? true : false;\n\t\t\t\t\n\t\t\t\tif (! RhythmOn)\t// Set \"Key On\"\n\t\t\t\t\tTempSht |= (UINT8)NoteOn << 13;\t// << (8+5)\n\t\t\t\t\n\t\t\t\tif (NoteOn)\n\t\t\t\t{\n\t\t\t\t\tfor (CurChip = 0x00; CurChip < 0x02; CurChip ++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (ChnNote[(CurChip << 4) | Channel] == 0xFF)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tChnNote[(CurChip << 4) | Channel] = VGMData[VGMPos + 0x00];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (CurChip >= 0x02)\n\t\t\t\t\t{\n\t\t\t\t\t\tCurChip = 0x00;\n\t\t\t\t\t\tChnNote[(CurChip << 4) | Channel] = VGMData[VGMPos + 0x00];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfor (CurChip = 0x00; CurChip < 0x02; CurChip ++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (ChnNote[(CurChip << 4) | Channel] != 0xFF)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tChnNote[(CurChip << 4) | Channel] = 0xFF;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (CurChip >= 0x02)\n\t\t\t\t\tCurChip = 0xFF;\n\t\t\t\t\n\t\t\t\tif (CurChip != 0xFF)\n\t\t\t\t{\n\t\t\t\t\tif (NoteOn)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (! RhythmOn)\n\t\t\t\t\t\t\tSendMIDIVolume(CurChip, Channel | (RhythmOn << 7), Command,\n\t\t\t\t\t\t\t\t\t\t\tChnIns[Command & 0x0F], VGMData[VGMPos + 0x01]);\n\t\t\t\t\t}\n\t\t\t\t\tif (NoteOn || ! RhythmOn)\n\t\t\t\t\t{\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00, 0xA0 | Channel, TempSht & 0xFF);\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00, 0xB0 | Channel, TempSht >> 8);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (RhythmOn)\n\t\t\t\t\t{\n\t\t\t\t\t\tTempByt = 0x0F - (Command & 0x0F);\n\t\t\t\t\t\tDrumReg[CurChip] &= ~(0x01 << TempByt);\n\t\t\t\t\t\tif (NoteOn)\n\t\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00, 0xBD, DrumReg[CurChip]);\n\t\t\t\t\t\tDrumReg[CurChip] |= (UINT8)NoteOn << TempByt;\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00, 0xBD, DrumReg[CurChip]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x02;\n\t\t\t\tbreak;\n\t\t\tcase 0xB0:\n\t\t\t\tNoteOn = false;\n\t\t\t\tswitch(VGMData[VGMPos + 0x00])\n\t\t\t\t{\n\t\t\t\tcase 0x66:\t// Marker\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x67:\t// Rhythm Mode\n\t\t\t\t\tif (! VGMData[VGMPos + 0x01])\n\t\t\t\t\t{\t// Set Rhythm Mode off\n\t\t\t\t\t\tDrumReg[0x00] = 0xC0;\n\t\t\t\t\t\tDrumReg[0x01] = 0xC0;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\t// Set Rhythm Mode on\n\t\t\t\t\t\tDrumReg[0x00] = 0xE0;\n\t\t\t\t\t\tDrumReg[0x01] = 0xE0;\n\t\t\t\t\t}\n\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00, 0xBD, DrumReg[0x00]);\n\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00, 0xBD, DrumReg[0x01]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x68:\t// Pitch Upward\n\t\t\t\t\tChnPitch[Channel] = +VGMData[VGMPos + 0x01];\n\t\t\t\t\tNoteOn = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x69:\t// Pitch Downward\n\t\t\t\t\tChnPitch[Channel] = -VGMData[VGMPos + 0x01];\n\t\t\t\t\tNoteOn = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (NoteOn)\n\t\t\t\t{\n\t\t\t\t\tfor (CurChip = 0x00; CurChip < 0x02; CurChip ++)\n\t\t\t\t\t{\n\t\t\t\t\t\tTempByt = ChnNote[(CurChip << 4) | Channel];\n\t\t\t\t\t\tif (! RhythmOn && TempByt != 0xFF)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTempSht = MIDINote2FNum(TempByt, ChnPitch[Channel]);\n\t\t\t\t\t\t\tTempSht |= 0x01 << 13;\t// << (8+5)\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00, 0xA0 | Channel, TempSht & 0xFF);\n\t\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00, 0xB0 | Channel, TempSht >> 8);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x02;\n\t\t\t\tbreak;\n\t\t\tcase 0xC0:\n\t\t\t\tTempByt = VGMData[VGMPos + 0x00];\n\t\t\t\tif (TempByt >= CMFInsCount)\n\t\t\t\t{\n\t\t\t\t\t//VGMPos += 0x01;\n\t\t\t\t\t//break;\n\t\t\t\t\tTempByt %= CMFInsCount;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tTempIns = CMFIns + TempByt;\n\t\t\t\tChnIns[Command & 0x0F] = TempByt;\n\t\t\t\t\n\t\t\t\tOpBase = (Channel / 0x03) * 0x08 + (Channel % 0x03);\n\t\t\t\tif (! RhythmOn)\n\t\t\t\t{\n\t\t\t\t\tOpMask = 0x03;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tswitch(Command & 0x0F)\n\t\t\t\t\t{\n\t\t\t\t\tcase 0x0B:\t// Bass Drum\n\t\t\t\t\t\tOpMask = 0x03;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x0F:\t// Hi Hat\n\t\t\t\t\t\tOpMask = 0x01;\n\t\t\t\t\t\t//Channel = 0x01;\t// PLAY.EXE really does this sometimes\n\t\t\t\t\t\t//OpBase = 0x01;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x0C:\t// Snare Drum\n\t\t\t\t\t\tOpMask = 0x02;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x0D:\t// Tom Tom\n\t\t\t\t\t\tOpMask = 0x01;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x0E:\t// Cymbal\n\t\t\t\t\t\tOpMask = 0x02;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tOpMask = 0x03;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tfor (CurChip = 0x00; CurChip < 0x02; CurChip ++)\n\t\t\t\t{\n\t\t\t\t\tTempByt = 0x00;\n\t\t\t\t\tif (OpMask & 0x01)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Write Operator 1\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00,\n\t\t\t\t\t\t\t\t\t\t0x20 | (OpBase + 0x00), TempIns->Character[TempByt]);\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00,\n\t\t\t\t\t\t\t\t\t\t0x40 | (OpBase + 0x00), TempIns->ScaleLevel[TempByt]);\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00,\n\t\t\t\t\t\t\t\t\t\t0x60 | (OpBase + 0x00), TempIns->AttackDelay[TempByt]);\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00,\n\t\t\t\t\t\t\t\t\t\t0x80 | (OpBase + 0x00), TempIns->SustnRelease[TempByt]);\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00,\n\t\t\t\t\t\t\t\t\t\t0xE0 | (OpBase + 0x00), TempIns->WaveSelect[TempByt]);\n\t\t\t\t\t\tTempByt ++;\n\t\t\t\t\t}\n\t\t\t\t\tif (OpMask & 0x02)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Write Operator 2\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00,\n\t\t\t\t\t\t\t\t\t\t0x20 | (OpBase + 0x03), TempIns->Character[TempByt]);\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00,\n\t\t\t\t\t\t\t\t\t\t0x40 | (OpBase + 0x03), TempIns->ScaleLevel[TempByt]);\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00,\n\t\t\t\t\t\t\t\t\t\t0x60 | (OpBase + 0x03), TempIns->AttackDelay[TempByt]);\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00,\n\t\t\t\t\t\t\t\t\t\t0x80 | (OpBase + 0x03), TempIns->SustnRelease[TempByt]);\n\t\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00,\n\t\t\t\t\t\t\t\t\t\t0xE0 | (OpBase + 0x03), TempIns->WaveSelect[TempByt]);\n\t\t\t\t\t\tTempByt ++;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00, 0xC0 | Channel, TempIns->FeedbConnect);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tVGMPos += 0x01;\n\t\t\t\tbreak;\n\t\t\tcase 0xA0:\n\t\t\tcase 0xE0:\n\t\t\t\tVGMPos += 0x02;\n\t\t\t\tbreak;\n\t\t\tcase 0xD0:\n\t\t\t\tVGMPos += 0x01;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (Command < 0xF0)\n\t\t\t\tLastCmd = Command;\n\t\t\t\n\t\t\tif (VGMEnd)\n\t\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase 0x02:\t// DosBox RAW OPL File Mode\n\t\tNoteOn = false;\n\t\tif (! SampleCount)\n\t\t{\n\t\t\t// was done during Init (Emulation Core / Chip Mapper for real FM),\n\t\t\t// but Chip Mapper's init-routine now works different\n\t\t\tswitch(DROInf.iHardwareType)\n\t\t\t{\n\t\t\tcase 0x00:\t// OPL 2\n\t\t\t\tfor (TempByt = 0xFF; TempByt >= 0x20; TempByt --)\n\t\t\t\t\tchip_reg_write(0x09, 0x00, 0x00, TempByt, 0x00);\n\t\t\t\tchip_reg_write(0x09, 0x00, 0x00, 0x08, 0x00);\n\t\t\t\tchip_reg_write(0x09, 0x00, 0x00, 0x01, 0x00);\n\t\t\t\tbreak;\n\t\t\tcase 0x01:\t// Dual OPL 2\n\t\t\t\tfor (TempByt = 0xFF; TempByt >= 0x20; TempByt --)\n\t\t\t\t\tchip_reg_write(0x09, 0x00, 0x00, TempByt, 0x00);\n\t\t\t\tchip_reg_write(0x09, 0x00, 0x00, 0x08, 0x00);\n\t\t\t\tchip_reg_write(0x09, 0x00, 0x00, 0x01, 0x00);\n\t\t\t\t//Sleep(1);\n\t\t\t\tfor (TempByt = 0xFF; TempByt >= 0x20; TempByt --)\n\t\t\t\t\tchip_reg_write(0x09, 0x01, 0x00, TempByt, 0x00);\n\t\t\t\tchip_reg_write(0x09, 0x01, 0x00, 0x08, 0x00);\n\t\t\t\tchip_reg_write(0x09, 0x01, 0x00, 0x01, 0x00);\n\t\t\t\tbreak;\n\t\t\tcase 0x02:\t// OPL 3\n\t\t\t\tfor (TempByt = 0xFF; TempByt >= 0x20; TempByt --)\n\t\t\t\t\tchip_reg_write(0x0C, 0x00, 0x00, TempByt, 0x00);\n\t\t\t\tchip_reg_write(0x0C, 0x00, 0x00, 0x08, 0x00);\n\t\t\t\tchip_reg_write(0x0C, 0x00, 0x00, 0x01, 0x00);\n\t\t\t\t//Sleep(1);\n\t\t\t\tfor (TempByt = 0xFF; TempByt >= 0x20; TempByt --)\n\t\t\t\t\tchip_reg_write(0x0C, 0x00, 0x01, TempByt, 0x00);\n\t\t\t\t//chip_reg_write(0x0C, 0x00, 0x01, 0x05, 0x00);\n\t\t\t\tchip_reg_write(0x0C, 0x00, 0x01, 0x04, 0x00);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tfor (TempByt = 0xFF; TempByt >= 0x20; TempByt --)\n\t\t\t\t\tchip_reg_write(0x09, 0x00, 0x00, TempByt, 0x00);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tSleep(1);\n\t\t\tNoteOn = true && (DROHead.iVersionMajor < 2);\n\t\t\tOpBase = 0x00;\n\t\t}\n\t\t\n\t\tSmplPlayed = SamplePlayback2VGM(VGMSmplPlayed + SampleCount);\n\t\twhile(VGMSmplPos <= SmplPlayed)\n\t\t{\n\t\t\tCommand = VGMData[VGMPos + 0x00];\n\t\t\t\n\t\t\tif (Command == DROInf.iShortDelayCode)\n\t\t\t\tCommand = 0x00;\n\t\t\telse if (Command == DROInf.iLongDelayCode)\n\t\t\t\tCommand = 0x01;\n\t\t\telse\n\t\t\t{\n\t\t\t\tswitch(DROHead.iVersionMajor)\n\t\t\t\t{\n\t\t\t\tcase 0:\n\t\t\t\tcase 1:\n\t\t\t\t\tif (Command <= 0x01)\n\t\t\t\t\t\tCommand = 0xFF;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tCommand = 0xFF;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// DRO v0/v1 only: \"Delay-Command\" fix\n\t\t\tif (NoteOn)\t// \"Delay\"-Command during init-phase?\n\t\t\t{\n\t\t\t\tif (Command < OpBase)\t// out of operator range?\n\t\t\t\t{\n\t\t\t\t\tNoteOn = false;\t// it's a delay\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tOpBase = Command;\t// it's a command\n\t\t\t\t\tCommand = 0xFF;\n\t\t\t\t}\n\t\t\t}\nDRO_CommandSwitch:\n\t\t\tswitch(Command)\n\t\t\t{\n\t\t\tcase 0x00:\t// 1-Byte Delay\n\t\t\t\tVGMSmplPos += 0x01 + VGMData[VGMPos + 0x01];\n\t\t\t\tVGMPos += 0x02;\n\t\t\t\tbreak;\n\t\t\tcase 0x01:\t// 2-Byte Delay\n\t\t\t\tswitch(DROHead.iVersionMajor)\n\t\t\t\t{\n\t\t\t\tcase 0:\n\t\t\t\tcase 1:\n\t\t\t\t\tmemcpy(&TempSht, &VGMData[VGMPos + 0x01], 0x02);\n\t\t\t\t\tif ((TempSht & 0xFF00) == 0xBD00)\n\t\t\t\t\t{\n\t\t\t\t\t\tCommand = 0xFF;\n\t\t\t\t\t\tgoto DRO_CommandSwitch;\n\t\t\t\t\t}\n\t\t\t\t\tVGMSmplPos += 0x01 + TempSht;\n\t\t\t\t\tVGMPos += 0x03;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tVGMSmplPos += (0x01 + VGMData[VGMPos + 0x01]) << 8;\n\t\t\t\t\tVGMPos += 0x02;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0x02:\t// Use 1st OPL Chip\n\t\t\tcase 0x03:\t// Use 2nd OPL Chip\n\t\t\t\tCurChip = Command & 0x01;\n\t\t\t\tif (CurChip > 0x00 && DROInf.iHardwareType == 0x00)\n\t\t\t\t{\n\t\t\t\t\t//CurChip = 0x00;\n\t\t\t\t\tif (! CmdList[0x02])\n\t\t\t\t\t{\n\t\t\t\t\t\tprintf(\"More chips used than defined in header!\\n\");\n\t\t\t\t\t\tCmdList[0x02] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x01;\n\t\t\t\tbreak;\n\t\t\tcase 0x04:\t// Escape\n\t\t\t\tVGMPos += 0x01;\n\t\t\t\t// No break (execute following Register)\n\t\t\tdefault:\n\t\t\t\tCommand = VGMData[VGMPos + 0x00];\n\t\t\t\tif (DROCodemap)\n\t\t\t\t{\n\t\t\t\t\tCurChip = (Command & 0x80) ? 0x01 : 0x00;\n\t\t\t\t\tCommand &= 0x7F;\n\t\t\t\t\tif (Command < DROInf.iCodemapLength)\n\t\t\t\t\t\tCommand = DROCodemap[Command];\n\t\t\t\t\telse\n\t\t\t\t\t\tCommand = Command;\n\t\t\t\t\tswitch(DROInf.iHardwareType)\n\t\t\t\t\t{\n\t\t\t\t\tcase 0x00:\n\t\t\t\t\t\tif (CurChip)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (! CmdList[0x02])\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tprintf(\"More chips used than defined in header!\\n\");\n\t\t\t\t\t\t\t\tCmdList[0x02] = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t//CurChip = 0x00;\n\t\t\t\t\t\t\t//Command = 0x00;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x01:\n\t\t\t\t\tcase 0x02:\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tswitch(DROInf.iHardwareType)\n\t\t\t\t{\n\t\t\t\tcase 0x00:\t// OPL 2\n\t\t\t\t\tif (CurChip > 0x00)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tchip_reg_write(0x09, 0x00, 0x00, Command, VGMData[VGMPos + 0x01]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x01:\n\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00, Command, VGMData[VGMPos + 0x01]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x02:\t// OPL 3\n\t\t\t\t\tchip_reg_write(0x0C, 0x00, CurChip, Command, VGMData[VGMPos + 0x01]);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tchip_reg_write(0x09, CurChip, 0x00, Command, VGMData[VGMPos + 0x01]);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tVGMPos += 0x02;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tif (VGMPos >= VGMDataLen)\n\t\t\t{\n\t\t\t\tif (VGMHead.lngTotalSamples != (UINT32)VGMSmplPos)\n\t\t\t\t{\n\t\t\t\t\tprintf(\"Warning! Header Samples: %u\\t Counted Samples: %u\\n\",\n\t\t\t\t\t\t\tVGMHead.lngTotalSamples, VGMSmplPos);\n\t\t\t\t\tVGMHead.lngTotalSamples = VGMSmplPos;\n\t\t\t\t\tErrorHappened = true;\n\t\t\t\t}\n\t\t\t\tVGMEnd = true;\n\t\t\t}\n\t\t\tif (VGMEnd)\n\t\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\nINLINE INT32 SampleVGM2Playback(INT32 SampleVal)\n{\n\treturn (INT32)((INT64)SampleVal * SampleRate / VGMSampleRate);\n}\n\nINLINE INT32 SamplePlayback2VGM(INT32 SampleVal)\n{\n\treturn (INT32)((INT64)SampleVal * VGMSampleRate / SampleRate);\n}\n"
  },
  {
    "path": "VGMPlay/VGMPlay_Intf.h",
    "content": "// VGMPlay_Intf.h: VGMPlay Interface Header File\n//\n\n//#define NO_WCHAR_FILENAMES\n#ifndef WIN32\n// Linux uses UTF-8 Unicode and has no special wide-character file routines.\n#define NO_WCHAR_FILENAMES\n#endif\n\ntypedef struct waveform_16bit_stereo\n{\n\tINT16 Left;\n\tINT16 Right;\n} WAVE_16BS;\n\ntypedef struct waveform_32bit_stereo\n{\n\tINT32 Left;\n\tINT32 Right;\n} WAVE_32BS;\n\n\nvoid VGMPlay_Init(void);\nvoid VGMPlay_Init2(void);\nvoid VGMPlay_Deinit(void);\nchar* FindFile(const char* FileName);\nchar* FindFile_List(const char** FileNameList);\n\nUINT32 GetGZFileLength(const char* FileName);\nbool OpenVGMFile(const char* FileName);\nvoid CloseVGMFile(void);\n\nvoid FreeGD3Tag(GD3_TAG* TagData);\nUINT32 GetVGMFileInfo(const char* FileName, VGM_HEADER* RetVGMHead, GD3_TAG* RetGD3Tag);\nUINT32 CalcSampleMSec(UINT64 Value, UINT8 Mode);\nUINT32 CalcSampleMSecExt(UINT64 Value, UINT8 Mode, VGM_HEADER* FileHead);\nconst char* GetChipName(UINT8 ChipID);\nconst char* GetAccurateChipName(UINT8 ChipID, UINT8 SubType);\nUINT32 GetChipClock(VGM_HEADER* FileHead, UINT8 ChipID, UINT8* RetSubType);\n\n#ifndef NO_WCHAR_FILENAMES\nUINT32 GetGZFileLengthW(const wchar_t* FileName);\nbool OpenVGMFileW(const wchar_t* FileName);\nUINT32 GetVGMFileInfoW(const wchar_t* FileName, VGM_HEADER* RetVGMHead, GD3_TAG* RetGD3Tag);\n#endif\n\nINT32 SampleVGM2Playback(INT32 SampleVal);\nINT32 SamplePlayback2VGM(INT32 SampleVal);\n\nvoid PlayVGM(void);\nvoid StopVGM(void);\nvoid RestartVGM(void);\nvoid PauseVGM(bool Pause);\nvoid SeekVGM(bool Relative, INT32 PlayBkSamples);\nvoid RefreshMuting(void);\nvoid RefreshPanning(void);\nvoid RefreshPlaybackOptions(void);\n\nUINT32 FillBuffer(WAVE_16BS* Buffer, UINT32 BufferSize);\n"
  },
  {
    "path": "VGMPlay/VGMPlay_Updates.txt",
    "content": "Update list since 0.4.0u3 (03.12.2012)\n- replaced some larger swich statements with function pointers (small speed up)\n- fixed Stereo flag in SN76496 OPL mapper\n- optimized playback routine (huge speed up, >20% for single-chip VGMs)\n- writing to a second chip if only the first one is defined doesn't cause crashes anymore\n- shortened the Chip Reset, Chip Mute and Chip Panning routines\n- added OKIM6295, OKIM6258 and UPD7759 to DAC Stream Control\n- slight improvements on OPL Hardware Playback\n- fixed bug where [VGMPlay Linux] was unable to show Unicode characters\n- added multiple paths for VGMPlay.ini and OPL4 ROM\n- [VGMPlay Linux] is now checking for \"vgmplay.ini\" as well as \"VGMPlay.ini\"\n- cleaned the code a bit\n- [VGMPlay] now frees its memory properly when quitting\n\n17.04.2013 and later:\n- improved skipping code for OPL hardware (to hopefully reduce noise after seeking)\n- made Makefile print short information instead of full gcc command lines\n- added possibility to override volume (+gain) of VGMs when using OPL hardware\n- [VGMPlay] made it use stderr for error messages\n- added optional debug output for DAC stream control (current data block, frequency)\n- fixed a bug with data blocks being re-read when restarting playback (wasted memory)\n- [VGMPlay] fixed bug when alternating between OPL hardware playback and emulation without restarting VGMPlay (e.g. via playlist with OPL and non-OPL VGMs)\n- fixed crash where the NES ROM could be written to invalid offsets\n- added alternative AY8910 core (EMU2149)\n- added NES DPCM address overflow behaviour, added alternative DPCM range (based on NSFPlay)\n- [VGMPlay] prevented it from writing too quickly to the OPL chip on fast computers\n\n15.06.2013 and later:\n- [VGMPlay] console title now changes to \"Song (Game) - VGM Player\" while playing\n- [VGMPlay] made it fall back to Japanese tags if English ones are empty\n- [VGMPlay] made Console title use Unicode (yes, that works - not like the in-Console text)\n- [in_vgm] made ANSI GetFileInfo function fall back to Japanese tags if English ones are not present\n- [in_vgm] fixed Unicode -> ANSI filename conversion bug (caused Unicode Tag function to fail with some non-ANSI filenames)\n- [in_vgm] fixed File Info Dialog falling back to tags of the other language (it isn't supposed to do that)\n- [VGMPlay] some Codepage fixes for Windows version, hopefully it now behaves correctly in all cases.\n  The Linux version should now be able to print non-ANSI Unicode characters in tags.\n- [VGMPlay Windows] now writes Unicode to the console (via WinAPI), so with the non-raster-fonts Japanese characters should work now. (although I only saw square boxes in WinXP, copying and pasting into Notepad worked at least)\n- [in_vgm] Fixed bug where \"Chip Rate\" == 0 didn't work and would get reset to 44100 when loading the plugin.\n- fixed bug where YM2612 Database Block caused DAC Stream Control to malfunction or crash (The MAME devs were right - realloc IS evil.)\n- [VGMPlay Linux] added support for libao\n\n09.09.2013 and later:\n- added WonderSwan support\n- added better SN-PSG name display\n- made it work on Big Endian machines (Thanks to nextvolume for sending me a patch that helped to find the critical spots)\n- cleaned code that loads VGMs a bit\n- shortened the Chip Stop routine\n- applied MAME fixes to YM2413/YMF262 (thread safe now), K051649 (added test register, changed sound generation code a bit), K054539 (replaced sound generation code, might improve reverb), YMZ280B (minor stuff), YMF271 (FM code replaced, sounds different now!)\n- added NES APU database block type\n- added NES APU to 0x68 command (RAM write from database) and fixed its dual chip support\n- ported NES APU/DMC emulator from NSFPlay 2.2\n- ported NES FDS emulator from NSFPlay 2.3\n- fixed MAME NES emulator reset\n- fixed MAME NES (and maybe others?) unmuting all channels when restarting a song or seeking back\n- added EMU2149 to YM2203, YM2608 and YM2610, fixes wrong AY-PSG tones in some VGMs (bug is still present with MAME's AY core)\n- [VGMPlay] modified makefile to make it easier to compile VGMPlay using MSYS/MinGW\n- [in_vgm] fixed crash when trying to mute channels after opening Winamp, but before any song was played\n- [in_vgm] added options from VGMPlay.ini to in_vgm.ini\n- [in_vgm] fixed track length display bug after changing the playback rate\n- [VGMPlay Linux] fixed warnings that are printed from ym2612.c\n- added VRC7 mode for YM2413 (reducing features and using separate instrument set)\n- [in_vgm] made OK button of File Dialog return another error code to Winamp to prevent a playlist bug\n\nUpdates since 0.4.0u4 (02.11.2013)\n- added code for muting channels to K053260 (looks like I forgot that one) and K054539 (lost when applying MAME fixes)\n- made K054539 use a proper clock (with a fallback for older VGMs)\n- added a small hack that allows mid-song sample rate changes for the OKIM6258 chip (I'll make a proper implementation for 0.41)\n- [VGMPlay] fixed absolute paths in m3u files\n- [VGMPlay] fixed path handling, makes paths that contain / and \\ work in both Windows and Unix, fixes m3u Windows paths under Unix\n- fixed pitch of YM2608 ADPCM Tom Tom and Rim Shot (reported by MaliceX)\n- fixed YM2612 Timer A (there are still tiny rounding errors though), this fixed the CSM mode\n- fixed probable YM2612 bug (CSM mode was able to prevent KeyOn/Off commands on channels other than FM3)\n- fixed noise calculation in MAME's AY8910 (applied latest MAME update)\n- fixed a few crashes related to corrupted VGM headers with invalid offsets and insane clock values (though not all)\n- [VGMPlay] MuteWTCh# now works in VGMPlay.ini\n- fixed clicks in YMF278B core (introduced when porting it from openMSX)\n- [VGMPlay] fixed length display when VGMs play slower/faster after using the PlaybackRate option\n- fixed bug where VGZs with additional 00s at the end won't play (because VGMPlay will read an unpacked size of 0 bytes)\n- changed Endianess of SCSP RAM data to Big Endian (as it should be)\n- applied MAME QSound fixes (key on register, chip initialization)\n- removed last A from AY-3-8910A and variants\n- added an option to force OKIM6258 into 12-bit mode (makes it louder sometimes, but an internal 12-bit calculation seems to be more correct)\n- VGMs using the OKIM6258 or OKIM6295 are now half as loud (affects global volume only, not chip-relative volume)\n- [VGMPlay] fixed crash that happened on Linux when trying to display a large Notes tag (thanks to vampi-the-frog for the report)\n- OKIM6258 lowers its output signal faster if there's no incoming data (reduces clicks)\n\nUpdates since 0.4.0u5 (13.04.2014)\n- fixed panning in AdLibEmu with 4-op instruments (it used the bits from Channel+0 instead of Channel+3)\n- fixed panning in AdLibEmu for rhythm channels\n- [VGMPlay] fixed YM2608/YM2610 DeltaT-channel not being muteable via MuteMask_PCM\n- [VGMPlay] fixed muting of YM278B's FM drums\n- applied MAME YM2612 Timer fix (said to fix SFX in Streets of Rage 2, see MAME Testers 05049)\n- fixed C140 sub chip type and C140/System 21 banking (using current MAME code)\n- added code to handle \"real\" C140 clock\n- [VGMPlay] fixed \"make install\" (the share/vgmplay/ folder was created without \"execute\" rights for users)\n- improved OKIM6258 data cache (should reduce clicks a bit)\n- YMF278B: fixed OPL3 register writes and OPL3 chip clock\n- applied MAME K053260 DPCM decoding fix\n- applied MAME OPLx Key Scale Level fix\n- added 40h-byte-FIFO to UPD7759 chip when in Slave mode, based on how Sega Pico games work\n- fixed T6W28 muting (Noise channel muting was controlled by chip #2, affected in_vgm only)\n  Thanks to the developers of foo_input_vgm for noticing this bug.\n- added NMK112 banking to OKIM6295 emulation\n- added callback function for chip sample rate change\n  -> replaces OKIM6258 hack\n  -> fixes OPN SSG with MAME AY emulation\n  -> makes OKIM6295 clock changes work\n- added routines for wide-character file names (only used by in_vgm for now)\n- fixed RAM write range check for RF5C68 and RF5C164\n- made OKIM6258 FIFO queue larger, added RemoveDCOfs option\n- [VGMPlay] fixed tag display under Windows 95\n- fixed YM2151 internal sample clipping (works like YM2612 now, can reduce distortion)\n- fixed SegaPCM volume register bitmask [thanks ctr for finding the bug]\n- fix potential crash in MultiPCM chip when playing invalid instruments\n- fixed buggy frequency writes in K051649 by backporting some MAME changes\n- added VSU, SAA1099 support\n- fixed high beep in NSFPlay NES core with triangle at frequency 0 and OPT_TRI_NULL option\n- [VGMPlay] fixed YM2612 DAC not being muteable via MuteMask\n- added ES5503, ES5506, Seta X1-010, Namco C352, Irem GA20 support\n- [VGMPlay] fixed Loop Length (is now adjusted for changed playback rates)\n\nUpdates since 0.4.0u6 (30.05.2015)\n- fixed SAA1099 muting (muting channel 1 or 4 prevented the envelope generator from running, thus muting 0-2 or 3-5 respectively)\n- made SAA1099 output bipolar\n- [VGMPlay] fix compiling under Linux (broken since Wide-Charcter file name support)\n- fixed ES5503 sample rate (divider was off by one)\n- applied fix from VOGONS that makes the SAA1099 core actually use the chip clock\n- fixed YMF278B's FM part being emulated at wrong sample rate\n- fixed Irem GA20 channel muting\n- fixed playing non-NMK banked OKIM6295 VGMs after NMK-banked ones\n- fixed SN76489 PSG muting (muting didn't work if the frequency was set to 0 to play PCM)\n- [misc] added vgm2wav (thanks libertyernie)\n- improved DAC Stream Control for HuC6280\n- [VGMPlay] added warning for zlib seeking bug\n- [VGMPlay + in_vgm] fixed bugs with .ini file reading\n- fixed YMF278B sample looping\n- repalced C352 sound core with new one written by superctr\n- added option to disable rarely used C352 rear channels\n- [in_vgm] added option to disable caching of VGM info (tags/etc.)\n- added option to enforce silence at the end of <1.50 VGMs\n- fixed memory leak when seeking back in songs that use the YM2610 (thanks to GTheGuardian for reporting)\n- fixed bug with X1-010 PCM loops\n\nUpdates since 0.4.0u7 (04.05.2016)\n- fixed looping samples in YMF278B (was broken since 0.4.0u7)\n- fixed OKIM6258 ADPCM algorithm (thanks, XM6 source code)\n- \"fixed\" some Project2612 VGMs (worked around incorrect register order in the initialization block of Kega Fusion logs)\n- [VGMPlay] fixed YM2608/YM2610 \"MutePCMCh\" option not working\n- fixed bug with YM2612 \"PseudoStereo\" option\n- fixed YMF278B FM<->Wavetable volume balance, added code to emulate the \"FM mix\" register\n- fixed YM2151 to use 10 bits per channel instead of 9 (improves Toms in Sharp X1 Space Harrier), thanks MovieMovies1\n- improved GameBoy emulation by porting current MAME core (ported from libvgm)\n- improved C352 emulation by porting ctr's updates from libvgm\n\nUpdates since 0.4.0u8 (16.04.2017)\n- [in_vgm] fixed a crash and incorrect track times (thanks to NewRisingSun for the bug report)\n- fixed mid-sample frequency changes in DAC Stream Control (thanks NewRisingSun)\n- fixed SAA1099 sample rate and noise volume (thanks NewRisingSun)\n- [in_vgm] fixed being unable to mute 2nd MultiPCM chip (thanks to Alianger for the bug report)\n- added Nuked OPN2 core (YM2612 emulation) (thanks Nuke.YKT)\n- improved C352 emulation (thanks ctr)\n- added command for AY8910 panning (thanks NewRisingSun)\n- fixed YMF278B FM<->Wavetable volume balance again (thanks to ctr for a test VGM and thanks to l_oliveira for the hardware recording)\n- added (very basic) YMF278B RAM block support\n- slightly improved YMF271 emulation, thanks to GTheGuardian and kirishima\n- added new and accurate QSound sound core (thanks ctr)\n- slightly improved YMF278B emulation\n- swapped YM2612 emulator type IDs 1 and 2, so that Nuked OPN2 is selectable in in_vgm\n- [VGMPlay] added \"OutputDevice\" configuration option (thanks ctr for the \"-DeviceId\" commandline option)\n- fixed SN76496 variant being incorrectly called NCR7496 instead of NCR8496\n- [in_vgm] made \"Tag fallback\" option work (finally, after 5 years!)\n- [in_vgm] made \"disable file information cache\" option selectable via configuration\n- [in_vgm] fix VGM information dialog using cached data even if file was changed\n\nUpdates since 0.4.0u9 (24.12.2018)\n- improved VRC7 preset instruments (thanks Nuke.YKT)\n- [VGMPlay Linux] added support for DBus MPRIS and XDG integration (thanks Tasos Sahanidis)\n- [VGMPlay Windows] added support for Media Keys\n- added NukedOPLL (thanks Nuke.YKT)\n- updated EMU2413 core (thanks Mitsutaka Okazaki)\n- added NukedOPM (thanks Nuke.YKT)\n"
  },
  {
    "path": "VGMPlay/XMasFiles/SWJ-SQRC01_1C.h",
    "content": "// SWJ-SQRC01_1C.vgz\nUINT8 FF1ws_1C[0x1908] =\n{\t0x1F, 0x8B, 0x08, 0x00, 0xD4, 0x7A, 0x2F, 0x52, 0x02, 0x00, 0xD4, 0x98, 0x57, 0xCC, 0x0E, 0x51,\n\t0x10, 0x86, 0xC7, 0xFA, 0x7D, 0x7A, 0x0D, 0x42, 0x5C, 0x10, 0x12, 0x2E, 0x08, 0xA2, 0x25, 0x7A,\n\t0xFB, 0x95, 0x04, 0x21, 0xD1, 0xE2, 0x42, 0x39, 0x21, 0x24, 0x12, 0xD1, 0xAD, 0x16, 0xBD, 0xF7,\n\t0xDE, 0x7B, 0xEF, 0xBD, 0x1B, 0xDC, 0x6D, 0x24, 0x88, 0x1E, 0xA2, 0x04, 0x97, 0x6E, 0x48, 0x5C,\n\t0x48, 0x44, 0x94, 0x67, 0x8F, 0xC3, 0xE2, 0x60, 0xD5, 0xE0, 0x4B, 0x26, 0xF1, 0xAD, 0x9D, 0x77,\n\t0xDE, 0x77, 0x66, 0xCE, 0x9C, 0xF9, 0xFE, 0x2E, 0xFD, 0x06, 0x94, 0xEB, 0xDA, 0x4B, 0x64, 0x70,\n\t0x0E, 0xF9, 0xF0, 0x69, 0xDA, 0x53, 0xE4, 0x71, 0xC9, 0x72, 0x72, 0xB5, 0x80, 0x48, 0xA5, 0x1E,\n\t0x65, 0xE4, 0xF3, 0xCF, 0x1A, 0xF9, 0x87, 0x3E, 0x0F, 0xAB, 0x7E, 0xF2, 0x75, 0x90, 0xE6, 0x11,\n\t0xCD, 0x27, 0x9A, 0x5F, 0x54, 0x44, 0x73, 0x88, 0x06, 0xA2, 0x39, 0x45, 0xB3, 0x44, 0x73, 0x89,\n\t0x66, 0x44, 0x73, 0xF3, 0x46, 0x01, 0xD1, 0x82, 0xA2, 0x79, 0x45, 0x8B, 0x34, 0xD1, 0xE2, 0xA2,\n\t0x45, 0x33, 0x83, 0xB4, 0x50, 0x29, 0x2D, 0x1C, 0x98, 0xD6, 0x41, 0x24, 0x13, 0xDE, 0x44, 0x32,\n\t0x11, 0x9B, 0x84, 0x4D, 0xC6, 0xA6, 0x60, 0x53, 0xB1, 0x69, 0xD8, 0x74, 0x6C, 0x86, 0x44, 0x32,\n\t0x13, 0x9B, 0x85, 0xCD, 0xC6, 0xE6, 0x60, 0x73, 0xB1, 0x79, 0xD8, 0x7C, 0x19, 0x1A, 0xC9, 0x02,\n\t0x5E, 0x5A, 0x88, 0x2D, 0xC2, 0x16, 0x63, 0x4B, 0xB0, 0xA5, 0xD8, 0x32, 0x6C, 0x39, 0xB6, 0x82,\n\t0x17, 0x57, 0x62, 0xAB, 0xB0, 0xD5, 0xD8, 0x1A, 0x6C, 0x2D, 0xB6, 0x0E, 0x5B, 0x2F, 0xC3, 0x22,\n\t0xD9, 0xF0, 0x2A, 0x92, 0x8D, 0xCB, 0x22, 0xD9, 0x54, 0x3D, 0x92, 0xCD, 0x2F, 0x23, 0xD9, 0x32,\n\t0x35, 0x92, 0xAD, 0xCD, 0x22, 0xD9, 0x56, 0x2C, 0x92, 0xED, 0x2D, 0x22, 0xD9, 0xD1, 0x27, 0x92,\n\t0x9D, 0xE5, 0x23, 0xD9, 0x55, 0x3B, 0x92, 0xDD, 0xFB, 0x22, 0xD9, 0xC3, 0xFB, 0x7B, 0x4F, 0x44,\n\t0xB2, 0x6F, 0x78, 0x24, 0xFB, 0x6B, 0x8C, 0x00, 0xA0, 0x39, 0x00, 0xE5, 0x01, 0x78, 0x03, 0xC0,\n\t0x13, 0x00, 0xEA, 0x00, 0xB0, 0x06, 0x80, 0x0C, 0x00, 0x97, 0x01, 0x78, 0x03, 0x00, 0xB6, 0x0B,\n\t0xDB, 0x1D, 0x00, 0xD0, 0x0F, 0x80, 0x0D, 0x00, 0x08, 0x00, 0xC5, 0x06, 0x6B, 0x56, 0x69, 0xCD,\n\t0x95, 0x7B, 0x70, 0x24, 0x07, 0x00, 0x3E, 0x08, 0x91, 0x43, 0x10, 0x39, 0x0C, 0x91, 0x23, 0x10,\n\t0x39, 0x0A, 0x91, 0x63, 0x10, 0x39, 0x0E, 0x91, 0x13, 0x10, 0x39, 0x49, 0x9C, 0x53, 0x10, 0x39,\n\t0x0D, 0x11, 0xE5, 0xFD, 0x33, 0x10, 0x39, 0x0B, 0x91, 0x73, 0x35, 0x86, 0x03, 0xD0, 0x1C, 0x80,\n\t0xF2, 0x00, 0xBC, 0x01, 0xE0, 0x09, 0x00, 0x75, 0x00, 0x58, 0x03, 0x40, 0x06, 0x80, 0xCB, 0x00,\n\t0xBC, 0x01, 0x00, 0x3B, 0x85, 0x9D, 0x86, 0x88, 0xF6, 0x03, 0x60, 0x03, 0x00, 0x02, 0x00, 0x44,\n\t0x32, 0xBD, 0x35, 0x77, 0xD6, 0x20, 0x2D, 0xD2, 0xD6, 0x54, 0x0D, 0x34, 0x6F, 0xCD, 0xA1, 0x9A,\n\t0x0F, 0xCB, 0x5F, 0xD3, 0xDC, 0xC8, 0x68, 0xBE, 0xEC, 0x21, 0x9A, 0x3F, 0xDB, 0xCC, 0xCC, 0xD2,\n\t0xBC, 0xD9, 0xA6, 0x6C, 0x5E, 0xCD, 0xDB, 0xD9, 0xDC, 0xE5, 0x69, 0x27, 0xFE, 0xBF, 0x85, 0xB9,\n\t0x96, 0x51, 0x69, 0xA8, 0x39, 0x72, 0x8F, 0xD4, 0xE0, 0xB9, 0xE6, 0xCC, 0x0A, 0xB5, 0x48, 0x7B,\n\t0x53, 0x23, 0xD0, 0x3C, 0xD9, 0x43, 0x41, 0x31, 0xF3, 0x63, 0x1F, 0xB0, 0xFA, 0x80, 0xD0, 0xD2,\n\t0x34, 0xE2, 0x79, 0x67, 0x73, 0x2B, 0xA3, 0x79, 0xFA, 0x0E, 0x8D, 0x51, 0x96, 0x67, 0x69, 0xFE,\n\t0xF2, 0xA6, 0x21, 0x4F, 0xC3, 0x21, 0x9A, 0xB7, 0xAF, 0x39, 0x50, 0x50, 0xA5, 0xC6, 0x08, 0x0D,\n\t0xCE, 0xDB, 0x67, 0x44, 0x05, 0x61, 0x81, 0x8D, 0x9A, 0x6D, 0x3D, 0x6F, 0xC7, 0x9E, 0x43, 0x62,\n\t0xCF, 0x0E, 0x41, 0xCC, 0x6D, 0x4A, 0x16, 0x9E, 0x43, 0x63, 0xCF, 0xFD, 0x78, 0x36, 0xC4, 0xF3,\n\t0x39, 0x9E, 0x2E, 0xF6, 0x50, 0x18, 0x9A, 0xD9, 0x2E, 0x7E, 0xB6, 0x69, 0xFA, 0x69, 0xEC, 0x21,\n\t0xE8, 0x33, 0x57, 0x33, 0xCE, 0x9F, 0x6F, 0xE5, 0x63, 0xF4, 0x7C, 0x45, 0xCD, 0xCD, 0x0C, 0x1C,\n\t0x46, 0xC2, 0x81, 0x67, 0x12, 0x6A, 0xA6, 0xB2, 0xA9, 0x86, 0x67, 0x11, 0xA2, 0xE6, 0x30, 0x0F,\n\t0x32, 0x71, 0x1E, 0x2E, 0xE1, 0x55, 0x8E, 0xEF, 0x81, 0x39, 0x5E, 0xF0, 0x7D, 0x06, 0x3A, 0x86,\n\t0x1A, 0xB4, 0xD1, 0x9C, 0xB9, 0x4C, 0xBD, 0x4F, 0xA5, 0x8F, 0xF8, 0x92, 0xEC, 0xC5, 0x59, 0x04,\n\t0xB2, 0x84, 0x12, 0xF2, 0xDD, 0x21, 0x3F, 0x04, 0xF2, 0x9F, 0x78, 0xC7, 0x14, 0x1C, 0xF1, 0x44,\n\t0x3A, 0x04, 0x49, 0xD7, 0x7B, 0xBF, 0x81, 0xF8, 0x9D, 0xFA, 0xDC, 0xCF, 0xB4, 0xF8, 0xCC, 0xE7,\n\t0x86, 0x13, 0x4A, 0x8A, 0xE3, 0x58, 0xC8, 0x1B, 0x32, 0x5A, 0x33, 0xCF, 0x34, 0x77, 0xCE, 0x77,\n\t0xEA, 0x86, 0xA2, 0x0E, 0xAA, 0xD6, 0x1D, 0x85, 0x25, 0xF2, 0xBE, 0x57, 0xB8, 0x22, 0x0B, 0x85,\n\t0xD4, 0x1C, 0x19, 0xE8, 0x24, 0x5C, 0x18, 0x87, 0xAB, 0xEF, 0x55, 0xC7, 0x0F, 0x97, 0x48, 0xEB,\n\t0x0B, 0xC5, 0xE5, 0x3E, 0x45, 0x97, 0x14, 0x5F, 0xD6, 0xC1, 0x82, 0x2E, 0x0E, 0x14, 0x8F, 0x98,\n\t0xEA, 0xEF, 0xB3, 0x1F, 0xC6, 0xFC, 0xE6, 0x59, 0x7E, 0x25, 0x3F, 0xF0, 0x5B, 0x6E, 0xF9, 0x95,\n\t0xB3, 0xFC, 0xA8, 0xA6, 0x84, 0x48, 0xBB, 0x93, 0x14, 0xC1, 0x8F, 0x35, 0xD4, 0xF1, 0xFB, 0xA8,\n\t0xE3, 0xC6, 0xC3, 0xEF, 0x05, 0xFC, 0x7E, 0x44, 0xD3, 0x34, 0x7C, 0x4A, 0x6A, 0xCE, 0x0C, 0x6E,\n\t0xDF, 0x1B, 0xEA, 0xA0, 0x0B, 0x75, 0x7F, 0xA4, 0x66, 0x9D, 0xD2, 0x5C, 0xB9, 0x46, 0x68, 0x26,\n\t0x5B, 0x73, 0x07, 0xA6, 0x8A, 0x13, 0x98, 0x1C, 0xB9, 0x19, 0xAE, 0xF6, 0x58, 0x22, 0xD6, 0xB6,\n\t0x6C, 0x27, 0xB3, 0x24, 0x16, 0x4C, 0x4F, 0x80, 0x18, 0x1F, 0x2B, 0x0E, 0xE2, 0xFB, 0xD2, 0xAC,\n\t0x07, 0x7B, 0x0C, 0xA5, 0x49, 0xE7, 0x93, 0xC8, 0x58, 0x89, 0x4F, 0x9F, 0x71, 0x9A, 0x59, 0xC6,\n\t0xA1, 0xC7, 0xCF, 0xB1, 0x28, 0x9F, 0xB0, 0x18, 0x01, 0x03, 0x34, 0xC6, 0x18, 0xED, 0x03, 0xBA,\n\t0x96, 0x21, 0xE0, 0x12, 0xE2, 0x5A, 0xA3, 0x41, 0xE0, 0xF0, 0xEC, 0x48, 0x90, 0xA1, 0x31, 0x9B,\n\t0x2B, 0xB0, 0x99, 0x3B, 0x12, 0x36, 0x23, 0x34, 0xAB, 0x86, 0xE6, 0xCA, 0x98, 0x5A, 0x8E, 0x54,\n\t0x0E, 0x4B, 0x19, 0x62, 0x08, 0x41, 0x82, 0x03, 0xCD, 0x26, 0x94, 0xA5, 0x47, 0x3D, 0xDB, 0x04,\n\t0x24, 0xC1, 0x06, 0x09, 0x47, 0x24, 0x67, 0x32, 0xF6, 0x10, 0xD3, 0x2D, 0x78, 0x37, 0xA4, 0xDE,\n\t0xB5, 0xC4, 0x08, 0x97, 0x2D, 0xD7, 0xB2, 0xE8, 0x72, 0x87, 0xBC, 0x9C, 0x59, 0xFD, 0x59, 0xD3,\n\t0xAE, 0x0C, 0x51, 0xE9, 0x37, 0x85, 0x23, 0x00, 0x19, 0x08, 0xF8, 0xF9, 0xE9, 0x9F, 0x1F, 0xB2,\n\t0xBC, 0xE5, 0x32, 0xEB, 0x55, 0x3A, 0xFB, 0x9B, 0xE7, 0x72, 0x17, 0x3E, 0x5B, 0x4D, 0xA3, 0xEF,\n\t0x6E, 0xAA, 0x93, 0x05, 0xDF, 0xE5, 0xAB, 0x24, 0x6D, 0x51, 0x99, 0x9E, 0x70, 0x87, 0x72, 0xC8,\n\t0xD7, 0x54, 0xFA, 0xC7, 0xF3, 0x3A, 0x4A, 0xB7, 0xA2, 0x74, 0xA1, 0x55, 0x1A, 0xDA, 0xA8, 0x73,\n\t0x9C, 0xAE, 0x6C, 0xFE, 0x45, 0xE4, 0x11, 0x68, 0x25, 0xB9, 0x70, 0x8A, 0xA3, 0xDB, 0x67, 0x35,\n\t0x4D, 0xDB, 0x00, 0xB6, 0x7C, 0xE7, 0x3D, 0x18, 0xA3, 0xD2, 0xF9, 0xCE, 0x75, 0x95, 0x4E, 0x7C,\n\t0xFB, 0xBC, 0xF3, 0x05, 0xCF, 0xF9, 0x52, 0x2E, 0xFC, 0xAC, 0x2A, 0x7A, 0x46, 0xF6, 0xA3, 0xF9,\n\t0x24, 0x08, 0x56, 0x93, 0x1F, 0x3D, 0xD6, 0xE0, 0x7B, 0x93, 0x61, 0xBC, 0xC7, 0x12, 0x1B, 0xF5,\n\t0x2F, 0x38, 0x17, 0xA1, 0x1B, 0x4C, 0x55, 0x9C, 0xCA, 0x1C, 0xF6, 0x5C, 0x24, 0x87, 0x7F, 0x1A,\n\t0xBE, 0x45, 0x5C, 0xE3, 0x64, 0x07, 0xC9, 0x10, 0x68, 0x86, 0x8E, 0x13, 0x74, 0xDD, 0x7D, 0xF4,\n\t0x7B, 0x1A, 0xC2, 0x38, 0x43, 0x53, 0x2C, 0x8B, 0x05, 0x5F, 0x67, 0x31, 0x44, 0xE5, 0x30, 0x1A,\n\t0x2E, 0xD8, 0xAB, 0xA3, 0xEE, 0x8F, 0xE9, 0xB0, 0xAD, 0xDD, 0xD4, 0x69, 0xB9, 0x8F, 0x96, 0x3B,\n\t0x08, 0x39, 0xF2, 0x53, 0x2A, 0x56, 0xA2, 0x82, 0x7E, 0xF5, 0xE3, 0xDB, 0xDB, 0x64, 0xAA, 0xC7,\n\t0xC1, 0x57, 0x71, 0x22, 0x9E, 0x33, 0x56, 0xC5, 0xD7, 0x7A, 0xC1, 0xE5, 0x61, 0xC8, 0x57, 0x55,\n\t0x8C, 0x50, 0xB9, 0x34, 0x92, 0xED, 0xEA, 0x09, 0xDB, 0xD5, 0x7D, 0xB6, 0xAB, 0x8B, 0x6C, 0x57,\n\t0xA7, 0xD9, 0xAE, 0x76, 0xB1, 0x5D, 0xAD, 0x64, 0xBB, 0x9A, 0xC1, 0x76, 0x15, 0xB2, 0x5D, 0xF5,\n\t0x65, 0xBB, 0xEA, 0xCC, 0x76, 0x95, 0xCD, 0x76, 0x55, 0x93, 0xED, 0xAA, 0x3C, 0xDB, 0x55, 0xD1,\n\t0xC1, 0x94, 0x73, 0x94, 0x3D, 0xFC, 0xB9, 0x47, 0xB3, 0x9A, 0x5C, 0x60, 0x35, 0xB9, 0xC7, 0x6A,\n\t0xF2, 0x9A, 0xD5, 0xE4, 0x0D, 0xAB, 0x09, 0x76, 0xF4, 0x29, 0xAB, 0xC9, 0x25, 0x56, 0x13, 0x65,\n\t0x35, 0xA9, 0xC5, 0x6A, 0x52, 0x81, 0xD5, 0x24, 0x07, 0xAB, 0x89, 0x44, 0xA2, 0xD8, 0x99, 0x22,\n\t0xAC, 0x26, 0x35, 0x58, 0x4D, 0x9A, 0xB3, 0x9A, 0x9C, 0x8F, 0x4F, 0x7D, 0x59, 0xA7, 0x64, 0x25,\n\t0x1C, 0xB1, 0xFC, 0x2B, 0x4D, 0x13, 0x18, 0xCF, 0xA0, 0xB2, 0x33, 0x98, 0x42, 0x68, 0x0B, 0x35,\n\t0xDF, 0x0C, 0x9B, 0xCB, 0x90, 0x3C, 0x85, 0x6E, 0x6A, 0xB5, 0x8B, 0x55, 0xF1, 0x4E, 0x5F, 0x37,\n\t0x19, 0xDF, 0xCD, 0xD1, 0x10, 0xFF, 0xCE, 0x64, 0x12, 0xDD, 0xAE, 0x3B, 0xB2, 0xE9, 0x0E, 0x54,\n\t0xBB, 0xC5, 0x81, 0x9E, 0xA1, 0x52, 0x31, 0x16, 0x4F, 0x82, 0x85, 0xE0, 0x95, 0x37, 0x75, 0xF0,\n\t0x97, 0xA1, 0xC4, 0xC7, 0xBF, 0xB3, 0xC9, 0x76, 0xB1, 0x8B, 0x32, 0x3B, 0xDE, 0x45, 0x14, 0xD3,\n\t0xC2, 0x55, 0x93, 0x88, 0xAC, 0xB7, 0x44, 0xFA, 0xB0, 0xFE, 0xC4, 0xD9, 0x77, 0xB3, 0xD5, 0x34,\n\t0x0F, 0x58, 0x7A, 0xC9, 0xEA, 0x24, 0xB2, 0x3A, 0x99, 0xAC, 0x4E, 0x21, 0xAB, 0x53, 0xC9, 0xEA,\n\t0x34, 0xB2, 0x3A, 0x9D, 0xAC, 0xCE, 0x08, 0x59, 0x7A, 0xC9, 0xEA, 0x2C, 0xB2, 0x3A, 0x9B, 0xAC,\n\t0xCE, 0x21, 0xAB, 0x73, 0xC9, 0xEA, 0x3C, 0xB2, 0x2A, 0x0B, 0x35, 0x47, 0x66, 0xC8, 0x3B, 0x56,\n\t0x77, 0x58, 0x37, 0xAC, 0xF0, 0xC0, 0x91, 0x2A, 0x0A, 0x01, 0x48, 0xD9, 0xA0, 0xA1, 0x3D, 0x94,\n\t0x39, 0x48, 0x89, 0xF8, 0x84, 0x28, 0x3D, 0x64, 0xE2, 0x27, 0x72, 0x47, 0x73, 0xE4, 0x72, 0x78,\n\t0x5B, 0xED, 0x75, 0xF6, 0x1E, 0xCF, 0xB4, 0x4E, 0xB0, 0xC0, 0x05, 0xCB, 0xB4, 0x49, 0x70, 0xDC,\n\t0x38, 0x9B, 0xFF, 0x01, 0x67, 0xEB, 0xA7, 0xBC, 0x12, 0x1C, 0x24, 0x0B, 0xC9, 0x94, 0xC1, 0xF1,\n\t0x5E, 0xD8, 0xD8, 0x62, 0x2E, 0x70, 0xFC, 0x52, 0x30, 0x2D, 0x37, 0x20, 0xE8, 0xE7, 0xA0, 0x0F,\n\t0xDC, 0xEC, 0x30, 0x0D, 0x86, 0x38, 0x6E, 0xA9, 0x38, 0x89, 0xC6, 0x3E, 0x09, 0xB7, 0x85, 0x10,\n\t0xFB, 0x3A, 0x48, 0x5B, 0x0B, 0xD2, 0xEA, 0x8B, 0x20, 0x0B, 0xBF, 0xA8, 0x8E, 0x97, 0x3D, 0x90,\n\t0xEF, 0xCF, 0xF6, 0xCF, 0xE1, 0xF8, 0xD9, 0xFE, 0xF1, 0xAA, 0xF9, 0x7C, 0x2E, 0xFC, 0x4A, 0xF5,\n\t0x2F, 0xC0, 0xC7, 0x56, 0xCA, 0xE3, 0x93, 0x52, 0xA9, 0xB4, 0xFC, 0xFC, 0x64, 0xC5, 0xB7, 0xFE,\n\t0x07, 0x15, 0x77, 0x19, 0xFE, 0x7B, 0x15, 0xEF, 0xE3, 0xF1, 0xF9, 0x81, 0xB3, 0xD9, 0x27, 0xA9,\n\t0xF8, 0xC2, 0x9F, 0x3E, 0x98, 0x7E, 0x86, 0x87, 0xFC, 0xB9, 0x9E, 0xF1, 0xCB, 0xED, 0x67, 0xF8,\n\t0x37, 0x57, 0xFC, 0x42, 0x6A, 0xC5, 0x53, 0xCE, 0xD4, 0xEF, 0xAA, 0xF8, 0xD0, 0x24, 0x3F, 0xA3,\n\t0x35, 0xEB, 0xBC, 0xE6, 0xCA, 0xD2, 0x02, 0x32, 0x8A, 0xF5, 0x84, 0x3D, 0x8B, 0x3F, 0xC7, 0xF0,\n\t0xAB, 0xFF, 0xB2, 0xA9, 0xF8, 0xD1, 0xC4, 0x0E, 0x99, 0xD8, 0xBB, 0x58, 0x03, 0x88, 0xC3, 0xC5,\n\t0x66, 0x71, 0xB8, 0xE8, 0xF8, 0xFE, 0x9E, 0x39, 0xCB, 0x20, 0x6B, 0x5F, 0x12, 0xD5, 0x5E, 0x7F,\n\t0x33, 0xDD, 0xCF, 0x16, 0x16, 0x0A, 0x1B, 0xBD, 0xED, 0xE7, 0x27, 0xB1, 0x9E, 0x2D, 0x8D, 0x0B,\n\t0x81, 0x7B, 0x92, 0x56, 0x0F, 0x34, 0x91, 0xC2, 0xBB, 0x0E, 0xD0, 0xEB, 0x99, 0xF1, 0x83, 0x34,\n\t0xF3, 0x48, 0x73, 0xE7, 0x46, 0x02, 0x7B, 0x56, 0x82, 0x5D, 0xCE, 0xEE, 0x59, 0x76, 0x3B, 0x70,\n\t0xC4, 0xBE, 0xD1, 0x02, 0xBC, 0x5F, 0x04, 0xFC, 0xD4, 0x03, 0x3B, 0xE4, 0x8B, 0x9C, 0xC3, 0xCF,\n\t0x39, 0xCF, 0xF7, 0x38, 0x7B, 0xAD, 0xC5, 0xEF, 0xAD, 0xBE, 0x31, 0xE5, 0xAA, 0x1F, 0x43, 0x7B,\n\t0x77, 0x77, 0x0A, 0x74, 0xCA, 0x79, 0x4E, 0x52, 0x9C, 0x74, 0xCA, 0xD7, 0x52, 0x9C, 0xD4, 0xCC,\n\t0xBF, 0x2F, 0xD9, 0x63, 0x97, 0xB3, 0x93, 0x8F, 0x7C, 0xD7, 0x2B, 0x83, 0x6C, 0xA6, 0x3F, 0x6B,\n\t0x94, 0xD3, 0x1F, 0x1A, 0x25, 0xDB, 0x35, 0x0A, 0x99, 0x77, 0x01, 0x53, 0x1B, 0x25, 0xA9, 0xEB,\n\t0xC7, 0xF7, 0x47, 0xA3, 0x8F, 0x8B, 0x89, 0x7B, 0xCA, 0x3C, 0x48, 0x2B, 0x62, 0xA8, 0x59, 0x6D,\n\t0x50, 0xE0, 0xB7, 0x8A, 0x5D, 0x04, 0xA1, 0x6D, 0x5B, 0x65, 0x78, 0x4C, 0x6D, 0xD6, 0x8F, 0xB5,\n\t0xA3, 0x3F, 0x35, 0x52, 0x98, 0xFF, 0x40, 0xFB, 0x5D, 0x78, 0xC7, 0xBC, 0x7C, 0x48, 0xBB, 0x7C,\n\t0x9A, 0xF8, 0x0F, 0x0B, 0xAC, 0xE5, 0x6D, 0x3A, 0x04, 0xEF, 0x35, 0x84, 0xF6, 0xB4, 0x36, 0xFC,\n\t0xB4, 0x7B, 0xEC, 0xF2, 0xDA, 0xD4, 0x46, 0x6C, 0xEF, 0xCA, 0xE3, 0x74, 0x80, 0x21, 0x66, 0x46,\n\t0xEA, 0xC4, 0x21, 0x1E, 0x5A, 0x5A, 0xA4, 0xDC, 0x57, 0xA9, 0x55, 0x18, 0xF9, 0x6E, 0xF2, 0x84,\n\t0x1F, 0xB5, 0x52, 0xE5, 0x3F, 0xD2, 0x4A, 0x5B, 0x3F, 0xBA, 0x9B, 0x9C, 0x88, 0x1F, 0x98, 0x39,\n\t0x29, 0xBD, 0x39, 0x7E, 0xF0, 0x57, 0x66, 0x8E, 0xD7, 0x48, 0x3F, 0xDD, 0xAE, 0x70, 0x4E, 0x9F,\n\t0x93, 0x2D, 0xBC, 0x46, 0xFA, 0xBE, 0x99, 0xF3, 0x27, 0x7B, 0xC8, 0x9F, 0x47, 0xBF, 0x3E, 0x3E,\n\t0xFD, 0x79, 0xF4, 0x96, 0x57, 0xAB, 0xC7, 0x69, 0x23, 0x0C, 0xA2, 0x52, 0xA2, 0xF4, 0x7B, 0x04,\n\t0x8B, 0x2A, 0x0A, 0x22, 0x48, 0xA6, 0x4B, 0x88, 0x44, 0xA4, 0xB5, 0x82, 0x65, 0x8A, 0x48, 0xC8,\n\t0x27, 0x88, 0xB4, 0x6D, 0xD0, 0x6E, 0xC2, 0x1A, 0x28, 0x68, 0x28, 0x42, 0x41, 0x91, 0x32, 0x07,\n\t0xC8, 0x2D, 0x72, 0x03, 0xCE, 0x92, 0x26, 0x27, 0xC8, 0x78, 0x3C, 0x9F, 0x9F, 0x9F, 0x9F, 0xF9,\n\t0x3E, 0x81, 0xA3, 0x34, 0xC8, 0x08, 0xF6, 0x9B, 0xBF, 0x37, 0x6F, 0xDE, 0x37, 0xEB, 0x3F, 0xBF,\n\t0x5E, 0x3C, 0x0F, 0x3E, 0x9A, 0x47, 0xB4, 0x47, 0x11, 0xFD, 0x33, 0x3A, 0xD2, 0x46, 0x40, 0x53,\n\t0x17, 0xC7, 0x6F, 0xAB, 0xF5, 0x0D, 0x08, 0x45, 0x23, 0x7C, 0xB2, 0x46, 0x98, 0x49, 0x07, 0xB8,\n\t0xF7, 0x47, 0xF0, 0xFE, 0x91, 0x53, 0xF7, 0x4E, 0x8B, 0x8F, 0x39, 0xD9, 0xE4, 0xE7, 0xA4, 0x95,\n\t0x35, 0x4A, 0xCC, 0xA8, 0xED, 0xCD, 0x85, 0xAF, 0xF3, 0xE7, 0xDE, 0xCC, 0x0D, 0xF6, 0xBE, 0x17,\n\t0x4C, 0x08, 0x6E, 0xE7, 0x4F, 0xDC, 0xE6, 0xA8, 0xCB, 0x26, 0x47, 0x67, 0x07, 0x7C, 0x41, 0xB5,\n\t0x60, 0x9E, 0xE2, 0xF5, 0x0B, 0xF8, 0x07, 0x8A, 0x97, 0x80, 0x7E, 0xB5, 0x08, 0xE0, 0x6C, 0xB3,\n\t0x27, 0x53, 0xF2, 0x44, 0x88, 0xEC, 0x2A, 0x62, 0x40, 0xB2, 0x5B, 0x8E, 0xFD, 0xA3, 0xC7, 0x6E,\n\t0x9F, 0x99, 0xDA, 0xCE, 0xD3, 0x73, 0x6F, 0x3D, 0xD9, 0x14, 0x7B, 0x67, 0x4F, 0x04, 0xEC, 0xC7,\n\t0xCB, 0x17, 0x59, 0x67, 0x4F, 0x7D, 0x93, 0x75, 0x66, 0xAF, 0x1C, 0xEC, 0x15, 0x8A, 0x63, 0x84,\n\t0xC8, 0xB2, 0x9D, 0xBB, 0x80, 0xEC, 0xBD, 0x8C, 0x95, 0x90, 0x60, 0x3D, 0x96, 0xB4, 0xCD, 0x25,\n\t0xF0, 0xEE, 0xAB, 0x46, 0xF4, 0x97, 0xFF, 0x5E, 0x77, 0x81, 0x9A, 0x58, 0x7D, 0x44, 0xFA, 0x7C,\n\t0xAD, 0x67, 0x96, 0x23, 0x7D, 0x3D, 0x5D, 0x9D, 0x7A, 0x26, 0x4F, 0x3F, 0xA7, 0x31, 0x70, 0x24,\n\t0xF8, 0xDB, 0x79, 0x6C, 0x03, 0x4B, 0xA9, 0xCE, 0x91, 0x49, 0xE7, 0x8F, 0xED, 0xFC, 0xCF, 0x0C,\n\t0x4D, 0x54, 0xF6, 0x95, 0x3F, 0x1E, 0xD8, 0x6C, 0xE7, 0xE4, 0xF4, 0x7E, 0x89, 0xCD, 0xDA, 0x3F,\n\t0x83, 0x9C, 0xA6, 0x09, 0x9F, 0x5E, 0x39, 0x10, 0x93, 0xA7, 0x21, 0x0C, 0x57, 0x44, 0x4E, 0x20,\n\t0x58, 0x33, 0x8A, 0x19, 0xB4, 0xEF, 0x6B, 0xA5, 0x72, 0x07, 0x9A, 0x39, 0xEE, 0xBE, 0xDE, 0x0F,\n\t0x67, 0xBE, 0x32, 0x0C, 0x23, 0x36, 0xFF, 0x67, 0xE6, 0x70, 0x1C, 0x54, 0xE2, 0xEF, 0xE1, 0xCA,\n\t0xE6, 0xC3, 0x3C, 0x20, 0x06, 0x8D, 0x55, 0x1E, 0x0E, 0xF3, 0x5D, 0x7A, 0x07, 0x12, 0xF2, 0x3A,\n\t0xD8, 0xDF, 0xE2, 0x58, 0x8B, 0x28, 0x16, 0xBD, 0xA8, 0x30, 0xCB, 0x3B, 0xF0, 0xC3, 0x1E, 0x41,\n\t0x8C, 0x6B, 0x10, 0x20, 0x6B, 0x53, 0x1D, 0x46, 0x6E, 0xFC, 0x28, 0x8C, 0xC7, 0x90, 0x80, 0x03,\n\t0x97, 0x3A, 0x28, 0xDE, 0xB9, 0x23, 0x93, 0xA5, 0x23, 0xD7, 0x2B, 0x50, 0xE8, 0x17, 0x90, 0x9F,\n\t0x91, 0x3E, 0x80, 0x33, 0x3B, 0x9B, 0xB8, 0x1D, 0x0E, 0x59, 0x4E, 0x28, 0x07, 0xE7, 0xC9, 0x5C,\n\t0x3D, 0x8F, 0xDB, 0xE1, 0xE0, 0x95, 0x24, 0xF3, 0x3D, 0xCB, 0x93, 0x89, 0xA7, 0x02, 0x76, 0xA1,\n\t0x4B, 0x32, 0x76, 0x4F, 0x50, 0x81, 0x36, 0x67, 0x7D, 0x2A, 0xD6, 0x1B, 0x5E, 0x99, 0xC0, 0xE4,\n\t0x40, 0xCA, 0xEC, 0xC1, 0xB5, 0x5C, 0x60, 0x1C, 0x5D, 0xC5, 0xD1, 0x28, 0xF0, 0xE9, 0x1A, 0x11,\n\t0xCF, 0x68, 0x00, 0x10, 0xDE, 0x1D, 0x1D, 0x5C, 0xE0, 0x2E, 0x15, 0xB8, 0xE6, 0xD8, 0xD0, 0x6C,\n\t0xDE, 0xF9, 0xF5, 0x45, 0x74, 0x47, 0x90, 0x30, 0x0A, 0x0C, 0x47, 0x8E, 0xB9, 0xD7, 0x83, 0xC9,\n\t0xD8, 0x8B, 0x81, 0xCE, 0x01, 0x34, 0x32, 0x2A, 0x9B, 0xDA, 0xA5, 0x77, 0x3B, 0x84, 0xF0, 0x0A,\n\t0x08, 0x0F, 0x8E, 0x19, 0x92, 0xFC, 0x77, 0x60, 0xC5, 0x5B, 0x28, 0xED, 0xA4, 0x69, 0x87, 0x3A,\n\t0x82, 0xC7, 0x9A, 0x8E, 0xF5, 0x88, 0xBF, 0xAE, 0x45, 0xF5, 0x82, 0x21, 0xEB, 0x67, 0x72, 0x7F,\n\t0xF3, 0xB3, 0xCA, 0xBA, 0x66, 0xF3, 0x78, 0x3E, 0x88, 0xF3, 0x06, 0xD2, 0x7A, 0xCE, 0xEA, 0x69,\n\t0xEC, 0xA9, 0x22, 0xB3, 0xCF, 0x42, 0x7A, 0xA8, 0x00, 0x94, 0x25, 0x18, 0x56, 0x53, 0x30, 0xD1,\n\t0x14, 0x40, 0xD1, 0x68, 0x0A, 0x10, 0x80, 0x79, 0x6E, 0xD9, 0x15, 0x4C, 0x09, 0x71, 0xD7, 0x30,\n\t0x40, 0xC4, 0xAD, 0x38, 0xBA, 0x0D, 0x36, 0x85, 0x94, 0xCC, 0xB0, 0x69, 0xF9, 0x9A, 0x76, 0x9A,\n\t0xD7, 0x8F, 0x35, 0xF1, 0xBF, 0x22, 0x91, 0x13, 0x34, 0xE2, 0x04, 0x9D, 0xA7, 0x7C, 0x83, 0x6B,\n\t0x0D, 0x01, 0x92, 0xA4, 0x04, 0x15, 0xBE, 0x16, 0xDA, 0xCF, 0xEC, 0x25, 0x0A, 0x20, 0x0E, 0xD1,\n\t0xA8, 0x50, 0xE9, 0x33, 0x50, 0x31, 0x4B, 0x8F, 0x96, 0xF0, 0xCD, 0xBA, 0xF4, 0xAD, 0x99, 0x96,\n\t0x82, 0x8C, 0xE0, 0xBC, 0x42, 0xA5, 0x12, 0xA8, 0x90, 0x2A, 0xE4, 0x7D, 0xC2, 0xF0, 0x99, 0x12,\n\t0xAD, 0x0E, 0xDF, 0xA2, 0x70, 0xE7, 0xC6, 0x57, 0x71, 0xF1, 0x3A, 0xCC, 0x0C, 0x80, 0xCF, 0x85,\n\t0xE7, 0x97, 0x79, 0x71, 0xE1, 0x19, 0x68, 0x59, 0x60, 0x1C, 0x74, 0x49, 0x02, 0x27, 0x2D, 0xB5,\n\t0xD3, 0x01, 0x6A, 0xC2, 0x3C, 0x33, 0xE1, 0xBD, 0x8D, 0x68, 0x3B, 0x74, 0x6F, 0x58, 0x03, 0x5B,\n\t0xA0, 0x84, 0xB8, 0xBA, 0x4D, 0x0C, 0x78, 0xE3, 0x0A, 0x2B, 0xA1, 0xEE, 0x1B, 0xF9, 0x70, 0xCC,\n\t0x0A, 0x6E, 0x8D, 0xF3, 0x46, 0x50, 0x70, 0xAC, 0x12, 0x55, 0xC1, 0xB5, 0x7A, 0xFE, 0x18, 0x31,\n\t0x0A, 0x7B, 0xED, 0x82, 0x61, 0x95, 0xC1, 0x16, 0x99, 0x5D, 0x8A, 0x87, 0xDB, 0xC4, 0x62, 0xC1,\n\t0xF4, 0x0A, 0xCC, 0x2A, 0x24, 0x03, 0x21, 0x49, 0x44, 0x5C, 0xB4, 0x42, 0xF1, 0xFE, 0x77, 0x52,\n\t0x86, 0x10, 0x2C, 0xA8, 0x7E, 0x63, 0x72, 0x57, 0xC6, 0x51, 0x1C, 0x82, 0xBA, 0xDC, 0x03, 0xD5,\n\t0xD0, 0x27, 0xD9, 0x2A, 0xDB, 0x61, 0xC5, 0x0A, 0x43, 0xC1, 0xF5, 0x2B, 0x48, 0xDF, 0x23, 0x8C,\n\t0x95, 0xD1, 0x0E, 0x05, 0x5F, 0x46, 0xFC, 0x34, 0x83, 0xF8, 0xC2, 0x8C, 0x2F, 0x63, 0xDD, 0x33,\n\t0xC2, 0x38, 0xE7, 0x9B, 0x4A, 0xB5, 0x96, 0x85, 0x66, 0x6D, 0xC9, 0x77, 0xC1, 0xA2, 0x91, 0x5B,\n\t0x6C, 0xCB, 0x4B, 0x12, 0x4C, 0x4B, 0xD0, 0xE8, 0x32, 0x6C, 0xCA, 0xE8, 0x9E, 0x24, 0xD1, 0xC9,\n\t0x1D, 0xA9, 0xC2, 0x1D, 0x89, 0xEA, 0x7B, 0xBF, 0x50, 0xA6, 0x3B, 0xA8, 0xAF, 0xA8, 0x53, 0xEF,\n\t0x32, 0xD4, 0x17, 0x03, 0x40, 0xEB, 0x8B, 0x7E, 0xAB, 0x3B, 0xAD, 0xAF, 0x43, 0xB8, 0xF3, 0xC0,\n\t0xC9, 0x97, 0x21, 0xAF, 0xBF, 0xA2, 0xBE, 0xEC, 0xC7, 0xA0, 0xD5, 0xDB, 0xA8, 0xD6, 0x77, 0xB2,\n\t0x29, 0xC9, 0x0F, 0x64, 0x61, 0xAC, 0xFA, 0x1C, 0x2A, 0x8E, 0x97, 0x63, 0xC8, 0x6F, 0x58, 0x6A,\n\t0x10, 0xB1, 0xB3, 0x5D, 0xDF, 0xAA, 0x30, 0x80, 0xBA, 0xF8, 0xBE, 0xF5, 0x45, 0x0D, 0xD9, 0x01,\n\t0x17, 0xEE, 0x93, 0x92, 0x3B, 0x02, 0xF3, 0x5E, 0x68, 0x07, 0x9A, 0xEF, 0xF9, 0xEA, 0xB4, 0xAB,\n\t0x8C, 0x78, 0x43, 0x5C, 0x7C, 0xBD, 0xAA, 0xEF, 0x0E, 0x49, 0xE2, 0x8E, 0x68, 0x5C, 0x17, 0x24,\n\t0x6E, 0x51, 0xDF, 0x6D, 0x21, 0x37, 0xA0, 0x4F, 0x21, 0x37, 0xA8, 0xC6, 0x4A, 0x94, 0xDB, 0x2F,\n\t0x1B, 0xF8, 0x92, 0xF5, 0x13, 0xCA, 0x8F, 0xDE, 0x64, 0xF4, 0xBC, 0x7C, 0xCB, 0x03, 0x98, 0x60,\n\t0x25, 0xC3, 0x18, 0x1E, 0x10, 0x53, 0xF4, 0xC2, 0x14, 0x89, 0x13, 0x79, 0x1A, 0x48, 0x9F, 0x8C,\n\t0x64, 0x12, 0x28, 0x07, 0xA2, 0xFE, 0xF7, 0x22, 0x12, 0x3D, 0xC4, 0x27, 0xCD, 0x82, 0x11, 0xA3,\n\t0x31, 0xBE, 0x71, 0x0B, 0x34, 0x3E, 0x3C, 0x0B, 0x7E, 0x3C, 0x48, 0x8B, 0x10, 0x1F, 0x25, 0x5A,\n\t0xCC, 0x10, 0xFE, 0x5D, 0x1C, 0xFF, 0x7B, 0xB3, 0x94, 0xDC, 0xFD, 0x5F, 0xFB, 0x31, 0x95, 0x98,\n\t0x42, 0x88, 0x25, 0x62, 0x46, 0xA1, 0x8B, 0xA4, 0x5C, 0x31, 0x29, 0xA3, 0xED, 0xFF, 0xF6, 0x72,\n\t0x25, 0xAF, 0x3F, 0x45, 0x51, 0xFC, 0x9A, 0x43, 0x8A, 0x94, 0x4C, 0xE5, 0x87, 0x42, 0x64, 0x9E,\n\t0xE7, 0x79, 0x26, 0x22, 0xAC, 0x2C, 0x9E, 0x29, 0x4A, 0x86, 0x2F, 0xBE, 0xCF, 0xAC, 0x64, 0xA1,\n\t0x64, 0x8A, 0x05, 0x52, 0x94, 0x58, 0xA0, 0xA4, 0x64, 0xCA, 0x7F, 0x80, 0x28, 0x0B, 0x0B, 0x2C,\n\t0x14, 0x76, 0xB2, 0xA6, 0x0C, 0x9F, 0xF7, 0xB9, 0xC3, 0xE7, 0xDD, 0x77, 0xCD, 0x13, 0x7D, 0xF9,\n\t0x0E, 0xF7, 0x9E, 0xF9, 0x9E, 0x73, 0xEE, 0xBD, 0xE7, 0xBC, 0xAD, 0xF7, 0x1A, 0xAF, 0xB9, 0xD7,\n\t0xA4, 0x45, 0x8E, 0x1C, 0x20, 0xE4, 0x98, 0x3A, 0x46, 0x53, 0x52, 0x0D, 0xAA, 0x95, 0x50, 0x93,\n\t0x24, 0xFA, 0x36, 0x0A, 0x77, 0x09, 0x08, 0x33, 0x10, 0x3A, 0xF8, 0xA4, 0xDE, 0x73, 0x14, 0x19,\n\t0x5A, 0x0F, 0xCA, 0x77, 0x90, 0x0C, 0xC7, 0x42, 0x06, 0xDE, 0x8F, 0x9E, 0xE4, 0xD8, 0xD7, 0xCD,\n\t0x0B, 0x5C, 0x23, 0x98, 0xAB, 0xF9, 0xF8, 0x3E, 0xB3, 0x84, 0xA7, 0x63, 0x4B, 0x90, 0x9A, 0x7B,\n\t0xD8, 0x6D, 0x6D, 0x31, 0x15, 0x3C, 0x28, 0x62, 0x1B, 0x8A, 0xD3, 0x7A, 0x69, 0x67, 0x51, 0xF3,\n\t0x98, 0x0E, 0x96, 0x30, 0xB1, 0x48, 0xBA, 0x65, 0x5E, 0x48, 0x7F, 0xE5, 0x4A, 0x99, 0xF3, 0x30,\n\t0xE7, 0xDC, 0x65, 0xCA, 0x6B, 0x4A, 0x57, 0x17, 0x4B, 0x74, 0x2A, 0x05, 0x50, 0xA1, 0xB4, 0x3C,\n\t0x5B, 0xFC, 0x95, 0xFD, 0x4E, 0x97, 0x96, 0xDE, 0x43, 0x0E, 0x45, 0x75, 0x2C, 0x15, 0x8A, 0x59,\n\t0xDD, 0x5A, 0xFA, 0xDA, 0xAE, 0x76, 0xD9, 0x71, 0x90, 0x8A, 0x84, 0xA8, 0xF1, 0x47, 0xD8, 0x5A,\n\t0xBA, 0x6D, 0xEC, 0xF7, 0x75, 0x21, 0x07, 0x83, 0x6B, 0x47, 0x7D, 0x71, 0x39, 0x31, 0x58, 0xE4,\n\t0xDE, 0xAC, 0x40, 0xBF, 0x0F, 0x20, 0xFC, 0x85, 0x16, 0xB3, 0x84, 0xEE, 0x00, 0x34, 0xE1, 0xEA,\n\t0xBE, 0xA1, 0x10, 0x5C, 0xB8, 0x41, 0xE8, 0x61, 0x13, 0x6E, 0x88, 0xAC, 0x13, 0x35, 0xCD, 0x43,\n\t0xAA, 0xCA, 0x65, 0xE6, 0xB4, 0xE8, 0x32, 0x73, 0x46, 0xE3, 0x02, 0xD3, 0x14, 0xF9, 0x7E, 0xD1,\n\t0xC0, 0xCF, 0xE0, 0x29, 0xC6, 0x5F, 0xF3, 0xF8, 0xBB, 0x12, 0x3F, 0x64, 0x80, 0x4A, 0x35, 0xE1,\n\t0x07, 0x5F, 0x56, 0x65, 0xFE, 0x32, 0x32, 0xEC, 0x9A, 0x4B, 0x2B, 0x8D, 0xE9, 0x91, 0x76, 0xCD,\n\t0xDE, 0xC0, 0x73, 0xA9, 0x82, 0x7E, 0x46, 0xC6, 0x0D, 0x31, 0x28, 0x16, 0x44, 0xA2, 0xA0, 0x3D,\n\t0x90, 0x14, 0xAA, 0xA4, 0x8B, 0x23, 0x67, 0x49, 0x49, 0x1C, 0x43, 0x72, 0xEB, 0x02, 0xB6, 0x69,\n\t0x7F, 0xA5, 0xE3, 0xDC, 0x58, 0x27, 0xE9, 0xD2, 0x3F, 0x18, 0x45, 0x12, 0xF0, 0xC6, 0xF5, 0x99,\n\t0xEF, 0x8C, 0xF5, 0x33, 0x4D, 0x31, 0x07, 0x0C, 0x40, 0x03, 0x76, 0x54, 0x0E, 0xC8, 0xB6, 0x5A,\n\t0x58, 0x7E, 0xAB, 0x04, 0xCB, 0x7E, 0xCE, 0x83, 0x1F, 0x23, 0x2C, 0x18, 0xB4, 0x87, 0x02, 0x2C,\n\t0x4D, 0x57, 0xF2, 0x88, 0x71, 0x30, 0x1D, 0xB3, 0x65, 0x32, 0xD7, 0xE2, 0x11, 0xAD, 0xA4, 0x45,\n\t0x90, 0xF7, 0x85, 0x44, 0x66, 0x68, 0x88, 0x38, 0xD4, 0xA4, 0x5D, 0x58, 0xF2, 0xA5, 0xD0, 0x95,\n\t0xA2, 0x1D, 0xD6, 0xA7, 0xFC, 0xBF, 0x08, 0xA7, 0x53, 0x92, 0xB7, 0x17, 0x7B, 0xD9, 0x51, 0x81,\n\t0x8D, 0x5C, 0x34, 0x58, 0xDB, 0xE1, 0x85, 0x2D, 0x87, 0x37, 0xA8, 0x98, 0x53, 0x57, 0x39, 0x65,\n\t0x39, 0xBB, 0x59, 0x93, 0xC6, 0x14, 0x93, 0xEF, 0x28, 0x2C, 0x61, 0x8C, 0x17, 0x51, 0x6A, 0x0D,\n\t0x64, 0xCC, 0x63, 0xDC, 0x07, 0x8C, 0x2B, 0xFD, 0x68, 0x3A, 0xC2, 0xDC, 0x96, 0x9F, 0x83, 0x4A,\n\t0xF9, 0x6E, 0x04, 0x85, 0x20, 0xF4, 0xA1, 0x12, 0xBA, 0xC4, 0xC2, 0x22, 0x50, 0x57, 0xEA, 0x5E,\n\t0x07, 0x0F, 0x95, 0xDD, 0xB8, 0xAC, 0xB8, 0xE2, 0x29, 0xC3, 0x7E, 0xF5, 0xA0, 0x4B, 0x9C, 0x28,\n\t0x3D, 0x79, 0x4B, 0x9B, 0x2E, 0x31, 0xB1, 0x7A, 0xDE, 0xBC, 0xA0, 0xED, 0x09, 0xBD, 0x25, 0xC7,\n\t0x62, 0x04, 0x1B, 0x3D, 0x38, 0xEE, 0x4D, 0xF3, 0xB0, 0x5C, 0xE5, 0x2F, 0x6B, 0x7E, 0xA5, 0x98,\n\t0x2C, 0x6B, 0x0D, 0xCA, 0x39, 0xB6, 0x2D, 0x1D, 0x52, 0x0F, 0xF0, 0x07, 0x59, 0x81, 0xDE, 0xC5,\n\t0x58, 0xF2, 0xD9, 0x84, 0x28, 0xE1, 0x7D, 0xDC, 0x9C, 0x87, 0x51, 0x91, 0xB3, 0x5C, 0x83, 0xDA,\n\t0xE1, 0x70, 0xF4, 0xC4, 0x83, 0xAA, 0x73, 0x4D, 0xED, 0x3A, 0x45, 0x42, 0xE8, 0xB4, 0x03, 0x98,\n\t0xD2, 0x8C, 0x72, 0xB5, 0x79, 0xEE, 0xEA, 0x4B, 0x11, 0x1E, 0xDF, 0xDB, 0xC8, 0x4E, 0x0F, 0x4E,\n\t0xF3, 0xA4, 0x5B, 0x5C, 0xE3, 0xEE, 0x17, 0xC9, 0x93, 0xBC, 0x39, 0x5D, 0xD3, 0x90, 0x7D, 0xD1,\n\t0x79, 0xDA, 0x5F, 0x91, 0xE9, 0xB3, 0xE6, 0x8C, 0x0B, 0x7F, 0x55, 0xA6, 0x74, 0x63, 0xFF, 0x47,\n\t0xA0, 0x32, 0xEF, 0xE9, 0xDF, 0x12, 0xA8, 0xDB, 0x44, 0x9C, 0xAC, 0x08, 0x74, 0x48, 0xDD, 0x3A,\n\t0xB7, 0x9F, 0x95, 0x29, 0x48, 0x22, 0x07, 0x7F, 0x2E, 0x53, 0x45, 0x74, 0xBB, 0x6F, 0x11, 0x1E,\n\t0x45, 0xF4, 0xFA, 0x37, 0x22, 0x3A, 0xC3, 0x93, 0x82, 0x7A, 0x2A, 0x5A, 0x12, 0x26, 0xD1, 0x4E,\n\t0x0E, 0xA2, 0x3D, 0xDF, 0x54, 0xF1, 0x7D, 0xEC, 0x3F, 0x97, 0xAE, 0x22, 0x3A, 0xCF, 0x4D, 0x7E,\n\t0xEC, 0x0C, 0x82, 0xC9, 0x2A, 0xAA, 0x83, 0x22, 0x1A, 0x8A, 0xE3, 0xC0, 0x89, 0x44, 0x51, 0x15,\n\t0x78, 0x10, 0xC6, 0xBE, 0x17, 0x51, 0xE3, 0x88, 0x2E, 0x97, 0x1A, 0x1F, 0xA1, 0xC9, 0xAD, 0x12,\n\t0x7F, 0xEE, 0x55, 0x31, 0xD4, 0xBB, 0xCC, 0x38, 0xCF, 0xD9, 0xA2, 0x00, 0x0B, 0x7E, 0x15, 0x5C,\n\t0x49, 0xD1, 0x8F, 0x73, 0x8C, 0x7D, 0x39, 0xB2, 0xC9, 0xEF, 0xA5, 0x92, 0x8A, 0x52, 0x5A, 0xCC,\n\t0xE9, 0xD2, 0xA1, 0xE1, 0x1D, 0x8A, 0x74, 0x1C, 0x1B, 0xDE, 0x5C, 0x19, 0x1E, 0xB4, 0x23, 0xC3,\n\t0x1B, 0x1E, 0x52, 0x49, 0xC9, 0x7E, 0xE6, 0x8F, 0x52, 0xC9, 0x1C, 0x0B, 0x3A, 0xDA, 0xF5, 0xD2,\n\t0xEA, 0xD2, 0xE5, 0xE0, 0xD2, 0x49, 0xED, 0x72, 0x2F, 0x34, 0x8D, 0x4B, 0x0A, 0xB4, 0xAF, 0x05,\n\t0x89, 0x0B, 0x94, 0x52, 0x6A, 0x5F, 0x4B, 0x51, 0x13, 0xED, 0xFF, 0x4A, 0x26, 0x25, 0xE0, 0xC8,\n\t0xF4, 0xC8, 0x52, 0x6A, 0x7A, 0x3F, 0x50, 0xF4, 0x61, 0x99, 0x9E, 0x8B, 0x2C, 0xDB, 0x93, 0x64,\n\t0xB2, 0x5F, 0x92, 0x4C, 0xD2, 0x9B, 0x8A, 0x0E, 0x60, 0x91, 0xF9, 0x7B, 0xAF, 0x72, 0x52, 0xF8,\n\t0xB1, 0x6C, 0x7F, 0x2E, 0x99, 0x9C, 0x95, 0x26, 0x93, 0xA9, 0xCD, 0xA7, 0x09, 0x25, 0x44, 0xF8,\n\t0x0B, 0x36, 0xFF, 0x93, 0xC9, 0x24, 0xC8, 0xC1, 0xAB, 0x7A, 0x52, 0x3F, 0xE8, 0x5B, 0x89, 0x64,\n\t0xA4, 0x8F, 0x24, 0x8D, 0xC4, 0xAF, 0xED, 0x94, 0xEA, 0x57, 0xD2, 0xBF, 0xC5, 0x61, 0x8C, 0x51,\n\t0x3E, 0x06, 0x42, 0xA3, 0x14, 0x72, 0xDB, 0x9F, 0xB6, 0x35, 0x6F, 0x86, 0x78, 0xC3, 0x41, 0x43,\n\t0x8F, 0x6A, 0x1E, 0x5A, 0x10, 0x58, 0x48, 0xD4, 0xE4, 0x39, 0xCC, 0x60, 0x1B, 0x52, 0xAC, 0x1D,\n\t0xD4, 0x81, 0x1F, 0xFF, 0xDD, 0x7C, 0x94, 0xB3, 0x6B, 0x2E, 0x9D, 0x63, 0x37, 0xE3, 0x1A, 0x61,\n\t0xAA, 0xE4, 0xA5, 0x07, 0xFD, 0xF8, 0xA0, 0xF4, 0x5C, 0x59, 0xA9, 0x90, 0x49, 0x0A, 0x15, 0xF0,\n\t0xB4, 0xD3, 0x7D, 0x4E, 0xCD, 0x62, 0x24, 0x05, 0xBD, 0xA6, 0xB0, 0x27, 0x29, 0xB0, 0x5A, 0xC9,\n\t0xD0, 0xA3, 0x6C, 0x55, 0xE4, 0x45, 0x16, 0xE5, 0xC0, 0x6C, 0xF1, 0xC2, 0x67, 0xD2, 0x15, 0xBA,\n\t0x7D, 0x38, 0xFB, 0x9B, 0x49, 0xAA, 0x08, 0xA0, 0x1C, 0xEA, 0x90, 0xA4, 0x66, 0x45, 0xC9, 0x6A,\n\t0x15, 0xCB, 0xE1, 0x42, 0x16, 0x62, 0xAC, 0xAA, 0xA1, 0x5A, 0x01, 0x77, 0xB6, 0x4B, 0x59, 0xF7,\n\t0x25, 0x29, 0xAB, 0x9B, 0x95, 0x6E, 0xEE, 0xD9, 0x8B, 0xE4, 0xF1, 0xE0, 0x73, 0xE3, 0xC3, 0x4C,\n\t0x60, 0x78, 0x02, 0x16, 0x3B, 0x0A, 0xC0, 0x9F, 0x8F, 0xDF, 0x4F, 0x67, 0x13, 0x9D, 0x04, 0x7A,\n\t0x28, 0x6E, 0x52, 0xB8, 0xD3, 0xB0, 0xA8, 0xAD, 0x2A, 0xD8, 0xD7, 0xC8, 0x8A, 0xAA, 0x7D, 0x5B,\n\t0xE5, 0x28, 0x06, 0xBA, 0xC4, 0xBF, 0x41, 0x3B, 0x4E, 0xA6, 0x55, 0xC0, 0x5B, 0x40, 0xE4, 0xBF,\n\t0xA0, 0xC9, 0x1E, 0x16, 0x99, 0xB7, 0x50, 0xA7, 0x36, 0x17, 0xBC, 0xAE, 0xAF, 0x8E, 0x42, 0xF7,\n\t0xE0, 0xC7, 0xBA, 0x2A, 0xE6, 0x63, 0xEB, 0x88, 0xC1, 0x72, 0xA5, 0x4C, 0x76, 0x93, 0x3A, 0xA1,\n\t0x6C, 0xAA, 0xC8, 0x97, 0xEC, 0x24, 0x6D, 0x5F, 0xBE, 0x8A, 0xA1, 0x17, 0x46, 0x7E, 0xDC, 0x2B,\n\t0x59, 0x0E, 0x20, 0x17, 0x8A, 0xF6, 0xF1, 0xC5, 0xC4, 0xF8, 0x6F, 0xA0, 0x1C, 0xA2, 0x64, 0x27,\n\t0xDD, 0x36, 0xA6, 0x68, 0x5D, 0xD6, 0x29, 0xF3, 0xA8, 0xCB, 0x34, 0x66, 0x6A, 0x74, 0xCE, 0x52,\n\t0x1A, 0xCE, 0x70, 0x39, 0xB5, 0x63, 0xE9, 0x98, 0x87, 0xED, 0x3A, 0x66, 0x31, 0x47, 0xB0, 0x65,\n\t0xFB, 0x55, 0xC3, 0xAF, 0xA7, 0x46, 0x4F, 0x86, 0xF0, 0x6E, 0x28, 0x98, 0x8C, 0x31, 0x26, 0x86,\n\t0x9F, 0x2D, 0x4E, 0x8D, 0xBE, 0x2C, 0x10, 0x50, 0x21, 0xDE, 0x30, 0x82, 0x27, 0x71, 0x76, 0x6A,\n\t0xFE, 0x2D, 0xA5, 0xC5, 0xEC, 0xE5, 0x29, 0x7B, 0x89, 0xE5, 0xC4, 0x4B, 0x3B, 0x39, 0xB9, 0xCD,\n\t0x13, 0xE7, 0xFC, 0x3D, 0xCD, 0xD5, 0x1C, 0x93, 0xD9, 0x84, 0xA0, 0xB6, 0x03, 0xDF, 0xC5, 0xCD,\n\t0x7C, 0x08, 0xFE, 0xF1, 0x4C, 0x36, 0x92, 0x02, 0xFD, 0xB1, 0x31, 0x72, 0x5D, 0xFF, 0xD8, 0x12,\n\t0xB7, 0xA2, 0x5E, 0xF0, 0x3E, 0xEA, 0x05, 0x9F, 0xA3, 0x5C, 0xF0, 0x13, 0xCA, 0x04, 0xDF, 0xA1,\n\t0x4C, 0xF0, 0x21, 0xCA, 0x04, 0xEF, 0xA1, 0x4C, 0x70, 0x18, 0xCA, 0x04, 0x7B, 0xA2, 0x4C, 0xB0,\n\t0x11, 0xCA, 0x03, 0xDB, 0xA2, 0x3C, 0x70, 0x08, 0xCA, 0x03, 0xA7, 0xA2, 0x3C, 0xF0, 0x44, 0xFE,\n\t0xBD, 0x56, 0xCC, 0x4D, 0xDF, 0xEB, 0xC5, 0xDC, 0x74, 0xAF, 0xF1, 0x46, 0x88, 0xF0, 0xD5, 0xBD,\n\t0x66, 0x8D, 0xB7, 0xA3, 0x17, 0x13, 0xE1, 0xE3, 0xFA, 0x67, 0x3E, 0x26, 0x42, 0xBD, 0x98, 0x78,\n\t0xDD, 0xC4, 0xEB, 0x16, 0x5E, 0xB7, 0x0D, 0x7A, 0x31, 0xF1, 0xBA, 0x6B, 0x4A, 0xBD, 0x98, 0xC6,\n\t0x3D, 0x26, 0xC2, 0xE0, 0x7E, 0x63, 0xDE, 0xBD, 0x16, 0xCD, 0x37, 0x15, 0xCD, 0x7C, 0x7D, 0x98,\n\t0x02, 0x79, 0x33, 0x7B, 0xD0, 0xDC, 0x56, 0x7C, 0xC1, 0xC3, 0x29, 0xBF, 0x43, 0x44, 0xC8, 0xAD,\n\t0xD7, 0x41, 0x0E, 0xE7, 0x8A, 0x78, 0xDC, 0xD6, 0xE2, 0x20, 0x12, 0xA5, 0xA2, 0x87, 0xF3, 0xA1,\n\t0xEB, 0x4C, 0xCF, 0xED, 0x66, 0x8D, 0xB1, 0xFD, 0x72, 0x76, 0x1A, 0xD9, 0x19, 0x17, 0x00, 0x20,\n\t0x63, 0x1C, 0xA0, 0xA2, 0x67, 0x1A, 0xB0, 0xAE, 0xB4, 0x01, 0x3E, 0xCE, 0x7E, 0xCE, 0xD9, 0x93,\n\t0x0A, 0x5C, 0x90, 0x35, 0x60, 0xF2, 0x9B, 0xCB, 0x80, 0x02, 0x12, 0x41, 0x03, 0x66, 0xBA, 0x6C,\n\t0x11, 0x59, 0x20, 0xE6, 0x3F, 0xE5, 0xFC, 0x4B, 0x6D, 0x54, 0xAB, 0x76, 0x90, 0x30, 0x4F, 0xEB,\n\t0xE4, 0x95, 0x14, 0x18, 0x52, 0x3E, 0x8D, 0x5E, 0xFF, 0xB2, 0xCA, 0x99, 0xCC, 0x39, 0x58, 0xC3,\n\t0x72, 0x6C, 0xC9, 0x76, 0xE1, 0xB2, 0xF9, 0x97, 0x78, 0xB6, 0x9D, 0xD5, 0x29, 0xCF, 0x2E, 0x75,\n\t0x8A, 0x79, 0x9E, 0xF7, 0x0D, 0x9E, 0x4D, 0x89, 0xE7, 0x47, 0xCC, 0xA5, 0xC9, 0xAD, 0xC3, 0x0B,\n\t0x5A, 0x41, 0x97, 0x78, 0x5E, 0xE2, 0x78, 0x7E, 0x82, 0x91, 0xD3, 0x30, 0x93, 0x19, 0x50, 0x2B,\n\t0xF6, 0xA0, 0x63, 0x93, 0x2C, 0xCE, 0x57, 0xB6, 0xA6, 0x7C, 0x88, 0xFD, 0x2C, 0xB0, 0x5F, 0xCC,\n\t0x46, 0x35, 0x76, 0x57, 0x8A, 0x18, 0x21, 0xBE, 0xFC, 0xBC, 0x1C, 0x8F, 0x4B, 0xC0, 0x6C, 0x2B,\n\t0x57, 0x4A, 0xE8, 0x34, 0xA8, 0xF3, 0xB4, 0xBF, 0xBF, 0xD7, 0xA2, 0x99, 0x36, 0x70, 0x60, 0x41,\n\t0x00, 0xC0, 0x26, 0x26, 0x1F, 0xF9, 0xAE, 0x21, 0x48, 0x0D, 0xDD, 0x98, 0xAE, 0x89, 0xB4, 0x71,\n\t0x54, 0x02, 0x02, 0x16, 0x9B, 0xEA, 0x17, 0x43, 0x09, 0x77, 0x60, 0x83, 0xD2, 0x03, 0xE5, 0x99,\n\t0xE8, 0xA1, 0x9E, 0xDA, 0x1E, 0xF5, 0x20, 0xFE, 0xA1, 0x3F, 0xD9, 0x9E, 0xD0, 0x9D, 0xA6, 0x24,\n\t0x80, 0x94, 0x52, 0x90, 0xED, 0x5C, 0x2D, 0x6C, 0x4F, 0xB3, 0xCB, 0xB2, 0xC9, 0x9E, 0x51, 0x1B,\n\t0xA7, 0x30, 0xF3, 0x4E, 0x36, 0x49, 0xB6, 0x07, 0xCD, 0x4A, 0x8F, 0xD7, 0x28, 0xBB, 0x67, 0x9C,\n\t0xFB, 0x18, 0x9A, 0x31, 0x78, 0xEF, 0xF1, 0xBD, 0x48, 0x04, 0x67, 0x4F, 0xB1, 0x4F, 0x7C, 0x57,\n\t0x70, 0xA4, 0x43, 0x57, 0x34, 0x4C, 0xF6, 0xF1, 0x2E, 0x70, 0x22, 0xEB, 0xBD, 0x06, 0xEB, 0x3D,\n\t0xB1, 0xA3, 0xA0, 0x6E, 0x38, 0xAF, 0x7B, 0x62, 0xA9, 0xF1, 0x1C, 0x9D, 0xFD, 0xE7, 0x0C, 0x4C,\n\t0x80, 0xD4, 0x95, 0x96, 0x6B, 0xD5, 0x60, 0xC4, 0x33, 0xB7, 0x47, 0x3A, 0x64, 0xA3, 0x7C, 0x99,\n\t0x21, 0x05, 0x5B, 0x64, 0xDE, 0xB1, 0x78, 0x67, 0xC1, 0xD1, 0x68, 0xDE, 0x75, 0xC8, 0x26, 0x29,\n\t0x0B, 0x42, 0x20, 0x5F, 0xCE, 0x32, 0x0F, 0x86, 0x03, 0x08, 0xC2, 0x05, 0x46, 0x99, 0x85, 0x30,\n\t0xC2, 0x24, 0x90, 0x0E, 0x68, 0xAD, 0xA0, 0xBB, 0x82, 0x3D, 0xEE, 0xE7, 0x10, 0xCD, 0x3F, 0x32,\n\t0xE0, 0x0D, 0x2D, 0xF4, 0x58, 0x8B, 0x2C, 0x62, 0x47, 0xC0, 0xB7, 0x25, 0x78, 0x89, 0x12, 0xCE,\n\t0x97, 0xCD, 0xEF, 0x35, 0x5D, 0x8C, 0x06, 0x75, 0x88, 0x1E, 0xCC, 0xFA, 0x13, 0x46, 0x09, 0x96,\n\t0x62, 0x01, 0x58, 0x97, 0x12, 0xD1, 0x8A, 0x99, 0xD8, 0x2D, 0x71, 0xE2, 0xC5, 0x8E, 0xAA, 0xF1,\n\t0x78, 0xE7, 0x59, 0xF1, 0xD4, 0x86, 0x4E, 0x08, 0xBF, 0x56, 0xBC, 0xFE, 0x5E, 0x9E, 0xC2, 0xE4,\n\t0xF2, 0x74, 0x42, 0x5E, 0x42, 0x68, 0x64, 0xB3, 0xEE, 0x85, 0x3D, 0xB4, 0x16, 0x6F, 0x47, 0x96,\n\t0xEF, 0xBD, 0xD7, 0xB4, 0x57, 0x41, 0xD6, 0x28, 0x4C, 0x68, 0xE2, 0x40, 0x1D, 0x44, 0x18, 0xF7,\n\t0x77, 0x65, 0xC0, 0x45, 0xAD, 0xBB, 0xE8, 0x03, 0x5B, 0xF2, 0xA5, 0x8F, 0x8D, 0x42, 0x95, 0x5E,\n\t0x8F, 0x9D, 0x20, 0x10, 0xE0, 0xE3, 0x47, 0x2C, 0xA9, 0x20, 0x7D, 0x53, 0x54, 0x91, 0x1E, 0x57,\n\t0xA2, 0xEF, 0xDB, 0x1E, 0x6D, 0x53, 0x77, 0x86, 0x7C, 0xA9, 0xE8, 0x12, 0xEC, 0xFD, 0xE3, 0x6A,\n\t0xE9, 0xE4, 0x16, 0x5E, 0x15, 0xD3, 0x4A, 0x9D, 0xD3, 0x7B, 0xF4, 0xCB, 0xDC, 0xAC, 0xB8, 0xB3,\n\t0x2A, 0x32, 0xDE, 0xC0, 0x03, 0x83, 0xC6, 0x16, 0x56, 0xD6, 0xE0, 0x4C, 0xB2, 0x51, 0x61, 0x06,\n\t0x4C, 0x4A, 0x2F, 0x66, 0x53, 0x43, 0x15, 0x28, 0xDD, 0xB6, 0x7F, 0xB4, 0x06, 0x1F, 0x77, 0x02,\n\t0xC7, 0xD9, 0x94, 0x07, 0xED, 0xBF, 0x5D, 0x1B, 0x74, 0xF0, 0x6B, 0x35, 0x9B, 0xFB, 0xB6, 0xE9,\n\t0xDC, 0x80, 0xB0, 0x9B, 0xF8, 0x3B, 0x7E, 0xB8, 0x02, 0x7F, 0x6A, 0xD0, 0x38, 0xB7, 0x8F, 0xEC,\n\t0x08, 0xE7, 0x05, 0xC4, 0xDB, 0x28, 0x5C, 0xE5, 0xBD, 0x68, 0x1E, 0x84, 0x8A, 0x8B, 0x1A, 0x4F,\n\t0x97, 0x11, 0x5D, 0x30, 0x78, 0x77, 0x8A, 0x69, 0xCE, 0x65, 0x33, 0x7F, 0x5C, 0x3D, 0xA4, 0x6B,\n\t0xE9, 0x9F, 0xAA, 0x1E, 0x3A, 0x51, 0x2B, 0x38, 0xA9, 0xBB, 0x13, 0x1E, 0x09, 0x3C, 0xDD, 0xF7,\n\t0x91, 0x74, 0xAF, 0x04, 0xB2, 0x48, 0x9F, 0xA1, 0x1B, 0xEF, 0x46, 0xBA, 0xA5, 0xB5, 0x87, 0xF6,\n\t0x1C, 0x99, 0x3B, 0xA5, 0x90, 0x54, 0xCC, 0x0A, 0x73, 0xF9, 0x2F, 0x44, 0x13, 0xC6, 0x1F, 0xDE,\n\t0xB7, 0x83, 0x64, 0xFC, 0x72, 0xD1, 0x8E, 0x6A, 0x33, 0xA6, 0xFE, 0x4C, 0xD1, 0x8E, 0xF8, 0x0E,\n\t0xC7, 0x52, 0xD4, 0x9C, 0xCB, 0xC4, 0xE7, 0x8A, 0xC9, 0x32, 0xA1, 0xB4, 0xB7, 0x50, 0x97, 0x82,\n\t0x51, 0x60, 0xD0, 0x55, 0x43, 0x30, 0x89, 0x94, 0xE6, 0xD2, 0xAD, 0x32, 0x98, 0xA4, 0xB0, 0x3C,\n\t0x4D, 0x80, 0xE8, 0x61, 0x9C, 0x00, 0xD3, 0xB4, 0x22, 0xB2, 0x9E, 0x96, 0xF3, 0xFC, 0x52, 0xB9,\n\t0xD6, 0xB8, 0x5F, 0x2C, 0xE7, 0x39, 0xB7, 0xC5, 0x9A, 0xB1, 0x4E, 0x9F, 0xFE, 0xA6, 0x09, 0x90,\n\t0xBB, 0xED, 0x51, 0x53, 0xC7, 0x6F, 0x56, 0x20, 0xF0, 0x8A, 0x7B, 0x4D, 0x3D, 0xDC, 0x18, 0xA9,\n\t0x0A, 0xC1, 0x6E, 0xD2, 0x92, 0x8A, 0xB4, 0x25, 0xE5, 0x92, 0x0B, 0xB1, 0x28, 0x2A, 0xB6, 0x68,\n\t0xB5, 0x46, 0x9B, 0x86, 0x1D, 0x15, 0x1E, 0xC9, 0xC5, 0xE2, 0xEA, 0xB5, 0x60, 0x2D, 0x70, 0xAA,\n\t0x1B, 0x2A, 0x19, 0xEF, 0xAF, 0x96, 0x1D, 0x34, 0x7C, 0xBF, 0xEC, 0x80, 0xCB, 0x57, 0x86, 0x7B,\n\t0x39, 0x31, 0xDC, 0xB6, 0x91, 0xE1, 0x42, 0x5C, 0xDE, 0xE0, 0xA8, 0x20, 0xAA, 0x85, 0x30, 0xA8,\n\t0x12, 0xEF, 0x2A, 0xE9, 0x34, 0x8C, 0x7D, 0x52, 0x93, 0x63, 0x63, 0x7F, 0x6B, 0x6E, 0x19, 0x29,\n\t0xD0, 0x5F, 0xAA, 0xC3, 0x55, 0x61, 0x95, 0x1A, 0x61, 0xD4, 0x86, 0x06, 0x13, 0xA2, 0x8B, 0x91,\n\t0x99, 0xD3, 0x57, 0xD2, 0xC2, 0xA2, 0xE3, 0x7D, 0x86, 0x33, 0xAE, 0x0D, 0xE8, 0xF9, 0xA8, 0x7C,\n\t0xA5, 0xAB, 0xAE, 0x95, 0xAF, 0xDC, 0x14, 0x9C, 0x25, 0x25, 0x69, 0x4A, 0x05, 0xDA, 0x0D, 0x91,\n\t0xB3, 0xFC, 0x9B, 0xC5, 0xAE, 0xA9, 0xB3, 0x4C, 0xAD, 0x28, 0x56, 0x72, 0xBA, 0x52, 0x54, 0xE3,\n\t0xC6, 0x08, 0x20, 0x5F, 0x22, 0x67, 0x39, 0x2F, 0x71, 0x96, 0x52, 0xA5, 0xFC, 0x46, 0xEA, 0x2C,\n\t0xA5, 0x2D, 0xD9, 0xDB, 0xCF, 0x16, 0x11, 0xCB, 0xDE, 0x54, 0xB7, 0x14, 0xF3, 0x9D, 0x06, 0x64,\n\t0x5D, 0x20, 0xC7, 0x4C, 0x92, 0xDC, 0xD4, 0x15, 0xA4, 0xCE, 0x72, 0xD2, 0xD7, 0x9D, 0x65, 0x2A,\n\t0x2C, 0x40, 0x4C, 0xDD, 0x49, 0xBA, 0xD6, 0x7E, 0x5C, 0x5A, 0x27, 0xDE, 0x7F, 0x5C, 0x5E, 0xA7,\n\t0xB3, 0x3D, 0x49, 0xE1, 0x5C, 0xE4, 0x4A, 0xFE, 0xD8, 0x08, 0x6A, 0x89, 0x8C, 0x14, 0x0C, 0x52,\n\t0xF6, 0x7E, 0xBA, 0xB6, 0x93, 0xDE, 0xD2, 0x07, 0x84, 0xD1, 0x5F, 0xBB, 0x5F, 0x4F, 0x02, 0xC2,\n\t0x92, 0x5A, 0xEC, 0x2D, 0xEB, 0x96, 0xC5, 0x88, 0x43, 0xEE, 0x97, 0xBE, 0xC9, 0x61, 0x5C, 0x1D,\n\t0xA1, 0xD3, 0x9C, 0xC8, 0xD0, 0xED, 0xE5, 0xFB, 0x7B, 0xF4, 0x86, 0x62, 0x0B, 0x32, 0x6F, 0xBB,\n\t0xCD, 0x96, 0xB3, 0xC1, 0x8C, 0x51, 0x3F, 0xDD, 0xCF, 0xA1, 0xFE, 0x13, 0xFA, 0x30, 0xF9, 0x97,\n\t0x1A, 0x36, 0xBE, 0xEE, 0x3C, 0x02, 0xF9, 0xB2, 0xF7, 0xAA, 0xED, 0x38, 0xC7, 0xB0, 0x90, 0x89,\n\t0x0F, 0x99, 0xA4, 0x2B, 0xE9, 0x5E, 0x7C, 0x6E, 0xFC, 0x3E, 0x14, 0x76, 0x13, 0xBC, 0xDA, 0x30,\n\t0xBE, 0xF9, 0x64, 0x10, 0x96, 0x0F, 0xCE, 0x2B, 0x2E, 0x64, 0x37, 0xDB, 0x24, 0x5F, 0xE5, 0xE6,\n\t0xA2, 0xDC, 0x27, 0x91, 0x35, 0xBF, 0xF2, 0xD2, 0xC6, 0x1F, 0xD5, 0x86, 0xEF, 0x52, 0x7F, 0xEA,\n\t0x9D, 0x7D, 0xEE, 0x48, 0xC5, 0xF6, 0x27, 0x84, 0xAD, 0x9D, 0xEA, 0x2B, 0x73, 0x05, 0x0E, 0xC7,\n\t0xBC, 0x72, 0xD4, 0x35, 0x21, 0x47, 0xA5, 0xB0, 0x69, 0x5E, 0x43, 0xEB, 0xB4, 0x1A, 0x5F, 0x29,\n\t0xBF, 0x03, 0x12, 0x42, 0xFC, 0x04, 0xEC, 0xFA, 0x57, 0xE1, 0x42, 0x89, 0xF4, 0x2E, 0x31, 0x5C,\n\t0x40, 0xF3, 0x41, 0xA8, 0x9D, 0x2B, 0x39, 0x59, 0x02, 0xE7, 0x6B, 0xCF, 0x5B, 0x69, 0x2E, 0xD8,\n\t0x23, 0xF3, 0x14, 0xF8, 0x60, 0xEE, 0x77, 0x28, 0xE3, 0xFD, 0xF5, 0x87, 0x05, 0x1F, 0x5A, 0xE4,\n\t0x4C, 0xB9, 0x45, 0x2E, 0x5B, 0xC4, 0xCD, 0x10, 0x57, 0x21, 0xC6, 0xA9, 0x2D, 0x6E, 0x71, 0xB1,\n\t0x6B, 0xE6, 0xF7, 0x10, 0x37, 0x4F, 0x6A, 0xA9, 0xA9, 0x09, 0x05, 0x8A, 0x52, 0x0D, 0xB9, 0x71,\n\t0x0F, 0x1C, 0xFC, 0xC9, 0xF6, 0xB8, 0xB4, 0x3B, 0xCC, 0x3D, 0xAC, 0x4E, 0x3D, 0xD2, 0x5B, 0xFD,\n\t0x73, 0x51, 0x20, 0xA7, 0xC1, 0x05, 0x36, 0xC0, 0x08, 0x07, 0x78, 0x9C, 0xD3, 0x2E, 0x75, 0x75,\n\t0x78, 0x6F, 0xA1, 0xDC, 0xA9, 0x43, 0x87, 0x7B, 0xA1, 0x42, 0xE8, 0x0F, 0x73, 0xC3, 0xD1, 0xFF,\n\t0xE4, 0x2A, 0x8C, 0x9A, 0x44, 0x80, 0xB9, 0x9E, 0x79, 0x52, 0x26, 0x68, 0x2F, 0x00, 0xED, 0x05,\n\t0x44, 0xDB, 0x01, 0x01, 0x59, 0xD0, 0x1A, 0x1C, 0xB4, 0x63, 0x36, 0xE0, 0x07, 0x8A, 0x04, 0x49,\n\t0x2D, 0x80, 0xC0, 0x28, 0xBA, 0xC0, 0x53, 0xAF, 0xC2, 0x5E, 0x87, 0x78, 0x60, 0x98, 0xF6, 0x1D,\n\t0x40, 0xFC, 0x57, 0x20, 0x7A, 0xD9, 0xA3, 0xF5, 0x5E, 0x3C, 0xEA, 0xF6, 0x10, 0xB8, 0x5E, 0x27,\n\t0x55, 0xA1, 0x6C, 0x11, 0x73, 0x98, 0x2D, 0xCD, 0x8A, 0xB9, 0x1A, 0x98, 0x83, 0xC0, 0x0B, 0xFE,\n\t0x20, 0xEC, 0x08, 0x5E, 0x43, 0x0A, 0x4F, 0xF9, 0x8C, 0xD8, 0x8B, 0x60, 0x8D, 0x07, 0x6D, 0x39,\n\t0x76, 0xDF, 0x81, 0xB6, 0x5A, 0x44, 0x5B, 0xAE, 0x58, 0x25, 0x05, 0x46, 0x41, 0xB5, 0x1E, 0x02,\n\t0xF1, 0x16, 0xFB, 0x0C, 0xD5, 0x8D, 0x82, 0x03, 0xEC, 0x3F, 0x6F, 0x00, 0x17, 0x5D, 0x29, 0x1A,\n\t0x3C, 0xDB, 0x0D, 0xEC, 0x96, 0xF9, 0xB0, 0x0E, 0xB7, 0x57, 0xEE, 0x6B, 0x99, 0x94, 0x2F, 0x77,\n\t0x37, 0x1B, 0x7A, 0xDE, 0x82, 0xCF, 0x63, 0xD3, 0x76, 0x5A, 0x1C, 0xD9, 0x28, 0xFB, 0x25, 0x1C,\n\t0x6F, 0xD7, 0x79, 0xDA, 0x56, 0x6B, 0xE1, 0xC8, 0xBE, 0x39, 0xFF, 0xA2, 0x0F, 0xDF, 0x9C, 0xDB,\n\t0xA4, 0x6A, 0x47, 0xF8, 0xB5, 0x31, 0xD7, 0x0D, 0x71, 0x61, 0x96, 0x2C, 0x7F, 0xAE, 0xCF, 0xBF,\n\t0x30, 0x5E, 0x17, 0x58, 0x80, 0x58, 0x1E, 0xB5, 0xC5, 0xED, 0xB9, 0xF5, 0xBB, 0xA0, 0x08, 0x8B,\n\t0xE6, 0x2A, 0x73, 0x39, 0x18, 0xED, 0x75, 0xBC, 0xD7, 0xF8, 0x71, 0x03, 0x2A, 0x10, 0x84, 0x2E,\n\t0xE3, 0xD1, 0x15, 0x91, 0xA4, 0x05, 0xE6, 0x84, 0x43, 0x56, 0x28, 0x58, 0xCE, 0xBF, 0xB8, 0x25,\n\t0x88, 0x84, 0x19, 0x4D, 0xC5, 0xF6, 0xB6, 0x78, 0x91, 0x10, 0x17, 0x67, 0x1D, 0xE4, 0x45, 0x47,\n\t0xEE, 0x4E, 0x57, 0x24, 0x92, 0x63, 0x62, 0x2B, 0x0E, 0x9B, 0x07, 0xA3, 0xB3, 0x91, 0x71, 0x24,\n\t0x2E, 0x2A, 0x0B, 0x75, 0x84, 0x2D, 0x70, 0x8C, 0x49, 0xD7, 0xB9, 0x25, 0x6C, 0x67, 0xDC, 0xF3,\n\t0xB4, 0x26, 0xF4, 0x14, 0xAE, 0xB1, 0x89, 0x6A, 0x40, 0x1C, 0x15, 0xC5, 0x12, 0x2F, 0x9F, 0x73,\n\t0x2C, 0x3B, 0xA3, 0xAB, 0x95, 0x40, 0x87, 0x06, 0x81, 0x0E, 0x15, 0x5E, 0xBA, 0xF2, 0x4D, 0x85,\n\t0x44, 0x07, 0x25, 0x86, 0x42, 0xA9, 0xAA, 0x00, 0xA0, 0xCC, 0x75, 0x61, 0x3C, 0xBB, 0xC5, 0x38,\n\t0x09, 0x60, 0x7E, 0x37, 0xDE, 0x33, 0x4C, 0x44, 0x6D, 0xB7, 0x70, 0xB3, 0xA6, 0xB9, 0x32, 0x12,\n\t0x3E, 0x70, 0x98, 0x90, 0xAB, 0xC6, 0xB2, 0x6F, 0x8F, 0x7D, 0xDE, 0x23, 0x42, 0x7A, 0x88, 0x89,\n\t0xB9, 0x0D, 0xFD, 0xC1, 0xEB, 0x0F, 0x55, 0x3B, 0x03, 0x65, 0xD3, 0xA3, 0xD2, 0xFB, 0xDE, 0xAE,\n\t0xD2, 0x75, 0x6D, 0xCA, 0x4D, 0x0D, 0xF8, 0xD7, 0x2B, 0xFF, 0x09, 0xCF, 0x97, 0xD6, 0xB6, 0xF6,\n\t0xCA, 0x5D, 0x85, 0x77, 0x26, 0xEB, 0xDC, 0xA9, 0xD8, 0x1E, 0xB5, 0xEF, 0x84, 0x07, 0x60, 0xE6,\n\t0x08, 0x0E, 0xB9, 0x7D, 0x8E, 0x25, 0xB8, 0x94, 0x7A, 0xD7, 0xB8, 0xBC, 0x38, 0x69, 0xC6, 0x27,\n\t0xC2, 0xA8, 0x5D, 0x99, 0x76, 0xA4, 0x56, 0xE5, 0x69, 0x69, 0x30, 0xAA, 0xAB, 0x59, 0x4F, 0x0E,\n\t0xE3, 0x27, 0x30, 0x88, 0xE5, 0x1F, 0x61, 0xC8, 0x55, 0xB0, 0x8E, 0x1F, 0x5D, 0x3F, 0x7D, 0x39,\n\t0x79, 0x91, 0xD4, 0x92, 0xC4, 0xA5, 0x9D, 0x4B, 0x5C, 0xE6, 0xFC, 0xF6, 0x63, 0x2B, 0x37, 0x25,\n\t0x4F, 0x40, 0xC9, 0xC6, 0xFC, 0xB5, 0xC7, 0x4C, 0xAE, 0x99, 0xB9, 0x6A, 0x68, 0x83, 0x69, 0x64,\n\t0xCC, 0x07, 0x63, 0xCC, 0x3C, 0x93, 0x99, 0x2D, 0x66, 0xAB, 0x69, 0x30, 0x53, 0xF0, 0x6E, 0x2B,\n\t0xFE, 0xAE, 0x37, 0xAB, 0x4D, 0xF1, 0x67, 0x86, 0x59, 0x67, 0x36, 0x98, 0x0C, 0x9F, 0x1B, 0xF0,\n\t0x3E, 0xC3, 0xFB, 0xAD, 0x1C, 0xBB, 0x83, 0xBF, 0x2E, 0x33, 0x1B, 0xF1, 0xCD, 0x2A, 0x8C, 0xAD,\n\t0x99, 0xC5, 0x26, 0xE7, 0xEF, 0x0D, 0x66, 0x2A, 0xBE, 0x5D, 0x8F, 0x57, 0xCD, 0xF8, 0x3F, 0x43,\n\t0xCC, 0x20, 0xFE, 0xED, 0x6F, 0x06, 0xE3, 0x7D, 0x7F, 0xBC, 0x1B, 0x8D, 0x6F, 0x97, 0x16, 0x70,\n\t0x89, 0x69, 0x07, 0x31, 0xAF, 0xE6, 0x27, 0x63, 0x16, 0x63, 0xEE, 0x36, 0xC2, 0x6D, 0x30, 0xB3,\n\t0xCD, 0x34, 0x33, 0x06, 0xFF, 0x0F, 0x06, 0xD4, 0x56, 0x66, 0x26, 0xC6, 0x6C, 0x28, 0xB0, 0x91,\n\t0xCA, 0xD5, 0x1C, 0xB1, 0x82, 0xB3, 0x97, 0x61, 0xD6, 0x22, 0xD3, 0x10, 0xCD, 0x5D, 0x08, 0x68,\n\t0x99, 0xD9, 0xC1, 0xF1, 0x0D, 0x8E, 0x86, 0x11, 0xC4, 0x3E, 0x9C, 0xFF, 0x0E, 0x01, 0xAE, 0x2F,\n\t0x11, 0x23, 0x48, 0xC8, 0x5B, 0x60, 0x00, 0x00};\n"
  },
  {
    "path": "VGMPlay/XMasFiles/XMasBonus.h",
    "content": "// WEWISH.CMF - We Wish You A Merry Christmas\nconst unsigned char WEWISH_CMF[0x2245] =\n{\t0x43, 0x54, 0x4D, 0x46, 0x01, 0x01, 0x28, 0x00, 0xE8, 0x00, 0x28, 0x00, 0x60, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\n\t0x01, 0x00, 0x01, 0x01, 0x0C, 0x00, 0x90, 0x00, 0x31, 0xA1, 0x1C, 0x80, 0x41, 0x92, 0x01, 0x3B,\n\t0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xB1, 0xD2, 0x80, 0x81, 0xF1, 0x03, 0x05,\n\t0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x4F, 0x00, 0xF1, 0xD2, 0x53, 0x74,\n\t0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x4E, 0x00, 0xDA, 0xF9, 0x25, 0x15,\n\t0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x12, 0x4F, 0x00, 0xF2, 0xF2, 0x60, 0x72,\n\t0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x8A, 0x40, 0xF1, 0xF1, 0x11, 0xB3,\n\t0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0xA8, 0xD6, 0x4C, 0x4F,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xF8, 0xD6, 0xB5, 0x4F,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF7, 0xD6, 0xB5, 0x4F,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xF5, 0xD6, 0xB5, 0x4F,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xDE, 0x00, 0x00, 0xF7, 0x10, 0xB5, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB2, 0x03, 0x5D, 0xDA, 0x02, 0x18, 0x01,\n\t0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x67, 0x01, 0x00, 0x69, 0x00, 0x00,\n\t0xC0, 0x00, 0x00, 0xB1, 0x69, 0x00, 0x00, 0xC1, 0x02, 0x00, 0xB2, 0x69, 0x00, 0x00, 0xC2, 0x03,\n\t0x00, 0xB3, 0x69, 0x00, 0x00, 0xC3, 0x05, 0x00, 0xB4, 0x69, 0x00, 0x00, 0xC4, 0x05, 0x00, 0xB5,\n\t0x69, 0x00, 0x00, 0xC5, 0x02, 0x00, 0xBB, 0x69, 0x00, 0x00, 0xCB, 0x06, 0x00, 0xBC, 0x69, 0x00,\n\t0x00, 0xCC, 0x07, 0x00, 0xBE, 0x69, 0x00, 0x00, 0xCE, 0x09, 0x00, 0xBF, 0x69, 0x00, 0x00, 0xCF,\n\t0x0A, 0x55, 0x90, 0x3F, 0x78, 0x00, 0x92, 0x3F, 0x6B, 0x2A, 0x90, 0x3F, 0x00, 0x00, 0x92, 0x3F,\n\t0x00, 0x00, 0x90, 0x44, 0x78, 0x00, 0x92, 0x44, 0x6B, 0x00, 0x95, 0x2C, 0x74, 0x00, 0x9B, 0x24,\n\t0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x93, 0x3C,\n\t0x6B, 0x00, 0x94, 0x38, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x28, 0x00, 0x0B, 0x90, 0x44, 0x00,\n\t0x00, 0x92, 0x44, 0x00, 0x00, 0x93, 0x3C, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x90, 0x44, 0x78,\n\t0x00, 0x92, 0x44, 0x6B, 0x00, 0x93, 0x3C, 0x6B, 0x00, 0x94, 0x33, 0x6B, 0x00, 0x9C, 0x26, 0x6B,\n\t0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x90, 0x44, 0x00,\n\t0x00, 0x92, 0x44, 0x00, 0x00, 0x90, 0x46, 0x78, 0x00, 0x92, 0x46, 0x6B, 0x00, 0x9B, 0x24, 0x6B,\n\t0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x93, 0x3C, 0x00,\n\t0x00, 0x94, 0x33, 0x00, 0x00, 0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x90, 0x44, 0x78,\n\t0x00, 0x92, 0x44, 0x6B, 0x00, 0x93, 0x3C, 0x6B, 0x00, 0x94, 0x38, 0x6B, 0x00, 0x9C, 0x26, 0x6B,\n\t0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x90, 0x44, 0x00,\n\t0x00, 0x92, 0x44, 0x00, 0x00, 0x90, 0x43, 0x78, 0x00, 0x92, 0x43, 0x6B, 0x00, 0x9B, 0x24, 0x6B,\n\t0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x95, 0x2C, 0x00,\n\t0x00, 0x93, 0x3C, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x90, 0x43, 0x00, 0x00, 0x92, 0x43, 0x00,\n\t0x00, 0x90, 0x41, 0x78, 0x00, 0x92, 0x41, 0x6B, 0x00, 0x95, 0x31, 0x74, 0x00, 0x9B, 0x24, 0x6B,\n\t0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x9C, 0x26, 0x6B,\n\t0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x90, 0x41, 0x00,\n\t0x00, 0x92, 0x41, 0x00, 0x00, 0x90, 0x41, 0x78, 0x00, 0x92, 0x41, 0x6B, 0x00, 0x93, 0x3D, 0x6B,\n\t0x00, 0x94, 0x38, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00,\n\t0x00, 0x9F, 0x28, 0x00, 0x0A, 0x28, 0x58, 0x0B, 0x90, 0x41, 0x00, 0x00, 0x92, 0x41, 0x00, 0x00,\n\t0x9F, 0x28, 0x00, 0x0B, 0x95, 0x31, 0x00, 0x00, 0x93, 0x3D, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00,\n\t0x90, 0x41, 0x78, 0x00, 0x92, 0x41, 0x6B, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x94, 0x39, 0x6B, 0x00,\n\t0x95, 0x30, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A,\n\t0x9B, 0x24, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x28, 0x58, 0x0B, 0x28,\n\t0x00, 0x0A, 0x90, 0x41, 0x00, 0x00, 0x92, 0x41, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x39,\n\t0x00, 0x00, 0x95, 0x30, 0x00, 0x00, 0x90, 0x46, 0x78, 0x00, 0x92, 0x46, 0x6B, 0x00, 0x95, 0x2E,\n\t0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28,\n\t0x00, 0x0B, 0x93, 0x3E, 0x6B, 0x00, 0x94, 0x3A, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x28, 0x00,\n\t0x0B, 0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x93, 0x3E, 0x00, 0x00, 0x94, 0x3A, 0x00,\n\t0x00, 0x90, 0x46, 0x78, 0x00, 0x92, 0x46, 0x6B, 0x00, 0x93, 0x3E, 0x6B, 0x00, 0x94, 0x35, 0x6B,\n\t0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00,\n\t0x0A, 0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x90, 0x48, 0x78, 0x00, 0x92, 0x48, 0x6B,\n\t0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00,\n\t0x0B, 0x93, 0x3E, 0x00, 0x00, 0x94, 0x35, 0x00, 0x00, 0x90, 0x48, 0x00, 0x00, 0x92, 0x48, 0x00,\n\t0x00, 0x90, 0x46, 0x78, 0x00, 0x92, 0x46, 0x6B, 0x00, 0x93, 0x3E, 0x6B, 0x00, 0x94, 0x3A, 0x6B,\n\t0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00,\n\t0x0B, 0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x90, 0x44, 0x78, 0x00, 0x92, 0x44, 0x6B,\n\t0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00,\n\t0x0A, 0x95, 0x2E, 0x00, 0x00, 0x93, 0x3E, 0x00, 0x00, 0x94, 0x3A, 0x00, 0x00, 0x90, 0x44, 0x00,\n\t0x00, 0x92, 0x44, 0x00, 0x00, 0x90, 0x43, 0x78, 0x00, 0x92, 0x43, 0x6B, 0x00, 0x95, 0x33, 0x74,\n\t0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00,\n\t0x0B, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00,\n\t0x0B, 0x90, 0x43, 0x00, 0x00, 0x92, 0x43, 0x00, 0x00, 0x90, 0x3F, 0x78, 0x00, 0x92, 0x3F, 0x6B,\n\t0x00, 0x93, 0x3F, 0x6B, 0x00, 0x94, 0x37, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58,\n\t0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x28, 0x58, 0x0B, 0x90, 0x3F, 0x00, 0x00,\n\t0x92, 0x3F, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x95, 0x33, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00,\n\t0x94, 0x37, 0x00, 0x00, 0x90, 0x3F, 0x78, 0x00, 0x92, 0x3F, 0x6B, 0x00, 0x93, 0x3F, 0x6B, 0x00,\n\t0x94, 0x37, 0x6B, 0x00, 0x95, 0x31, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00,\n\t0x9F, 0x28, 0x58, 0x0A, 0x9B, 0x24, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B,\n\t0x28, 0x58, 0x0B, 0x28, 0x00, 0x0A, 0x90, 0x3F, 0x00, 0x00, 0x92, 0x3F, 0x00, 0x00, 0x93, 0x3F,\n\t0x00, 0x00, 0x94, 0x37, 0x00, 0x00, 0x95, 0x31, 0x00, 0x00, 0x90, 0x48, 0x78, 0x00, 0x92, 0x48,\n\t0x6B, 0x00, 0x95, 0x30, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24,\n\t0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x93, 0x40, 0x6B, 0x00, 0x94, 0x37, 0x6B, 0x00, 0x9F, 0x28,\n\t0x58, 0x0A, 0x28, 0x00, 0x0B, 0x90, 0x48, 0x00, 0x00, 0x92, 0x48, 0x00, 0x00, 0x93, 0x40, 0x00,\n\t0x00, 0x94, 0x37, 0x00, 0x00, 0x90, 0x48, 0x78, 0x00, 0x92, 0x48, 0x6B, 0x00, 0x93, 0x40, 0x6B,\n\t0x00, 0x94, 0x37, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00,\n\t0x00, 0x9F, 0x28, 0x00, 0x0A, 0x90, 0x48, 0x00, 0x00, 0x92, 0x48, 0x00, 0x00, 0x90, 0x49, 0x78,\n\t0x00, 0x92, 0x49, 0x6B, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00,\n\t0x00, 0x9F, 0x28, 0x00, 0x0B, 0x93, 0x40, 0x00, 0x00, 0x94, 0x37, 0x00, 0x00, 0x90, 0x49, 0x00,\n\t0x00, 0x92, 0x49, 0x00, 0x00, 0x90, 0x48, 0x78, 0x00, 0x92, 0x48, 0x6B, 0x00, 0x93, 0x40, 0x6B,\n\t0x00, 0x94, 0x3C, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9C, 0x26, 0x00,\n\t0x00, 0x9F, 0x28, 0x00, 0x0B, 0x90, 0x48, 0x00, 0x00, 0x92, 0x48, 0x00, 0x00, 0x90, 0x46, 0x78,\n\t0x00, 0x92, 0x46, 0x6B, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00,\n\t0x00, 0x9F, 0x28, 0x00, 0x0A, 0x95, 0x30, 0x00, 0x00, 0x93, 0x40, 0x00, 0x00, 0x94, 0x3C, 0x00,\n\t0x00, 0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x90, 0x44, 0x78, 0x00, 0x92, 0x44, 0x6B,\n\t0x00, 0x95, 0x35, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00,\n\t0x00, 0x9F, 0x28, 0x00, 0x0B, 0x93, 0x41, 0x6B, 0x00, 0x94, 0x3C, 0x6B, 0x00, 0x9C, 0x26, 0x6B,\n\t0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x90, 0x44, 0x00,\n\t0x00, 0x92, 0x44, 0x00, 0x00, 0x95, 0x35, 0x00, 0x00, 0x93, 0x41, 0x00, 0x00, 0x94, 0x3C, 0x00,\n\t0x00, 0x90, 0x41, 0x78, 0x00, 0x92, 0x41, 0x6B, 0x00, 0x93, 0x3D, 0x6B, 0x00, 0x94, 0x3A, 0x6B,\n\t0x00, 0x95, 0x2E, 0x74, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00,\n\t0x00, 0x9F, 0x28, 0x00, 0x0A, 0x28, 0x58, 0x0B, 0x90, 0x41, 0x00, 0x00, 0x92, 0x41, 0x00, 0x00,\n\t0x9F, 0x28, 0x00, 0x0B, 0x93, 0x3D, 0x00, 0x00, 0x94, 0x3A, 0x00, 0x00, 0x95, 0x2E, 0x00, 0x00,\n\t0x90, 0x3F, 0x78, 0x00, 0x92, 0x3F, 0x6B, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x94, 0x38, 0x6B, 0x00,\n\t0x95, 0x30, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A,\n\t0x9B, 0x24, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x90, 0x3F, 0x00, 0x00,\n\t0x92, 0x3F, 0x00, 0x00, 0x90, 0x3F, 0x78, 0x00, 0x92, 0x3F, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B,\n\t0x28, 0x00, 0x0A, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x95, 0x30, 0x00, 0x00, 0x90,\n\t0x3F, 0x00, 0x00, 0x92, 0x3F, 0x00, 0x00, 0x90, 0x41, 0x78, 0x00, 0x92, 0x41, 0x6B, 0x00, 0x95,\n\t0x31, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F,\n\t0x28, 0x00, 0x0B, 0x93, 0x3D, 0x6B, 0x00, 0x94, 0x38, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x90,\n\t0x41, 0x00, 0x00, 0x92, 0x41, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x95, 0x31, 0x00, 0x00, 0x93,\n\t0x3D, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x90, 0x46, 0x78, 0x00, 0x92, 0x46, 0x6B, 0x00, 0x93,\n\t0x41, 0x6B, 0x00, 0x94, 0x3D, 0x6B, 0x00, 0x95, 0x2E, 0x74, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F,\n\t0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x9B, 0x24, 0x6B, 0x00, 0x9F,\n\t0x28, 0x58, 0x0B, 0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x9B, 0x24, 0x00, 0x00, 0x9F,\n\t0x28, 0x00, 0x0B, 0x93, 0x41, 0x00, 0x00, 0x94, 0x3D, 0x00, 0x00, 0x95, 0x2E, 0x00, 0x00, 0x90,\n\t0x43, 0x78, 0x00, 0x92, 0x43, 0x6B, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x94, 0x3D, 0x6B, 0x00, 0x95,\n\t0x33, 0x74, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F,\n\t0x28, 0x00, 0x0C, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0C, 0x90, 0x43, 0x00, 0x00, 0x92,\n\t0x43, 0x00, 0x00, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0C, 0x93, 0x3F, 0x00, 0x00, 0x94,\n\t0x3D, 0x00, 0x00, 0x95, 0x33, 0x00, 0x00, 0x90, 0x44, 0x78, 0x00, 0x92, 0x44, 0x6B, 0x00, 0x93,\n\t0x3F, 0x6B, 0x00, 0x94, 0x3C, 0x6B, 0x00, 0x95, 0x2C, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F,\n\t0x28, 0x58, 0x0C, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0C, 0x9C, 0x26, 0x6B, 0x00, 0x9F,\n\t0x28, 0x58, 0x0C, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x9C, 0x26, 0x58, 0x00, 0x9F,\n\t0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x9C, 0x26, 0x5F, 0x00, 0x9F,\n\t0x28, 0x58, 0x0B, 0x90, 0x44, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x94,\n\t0x3C, 0x00, 0x00, 0x95, 0x2C, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x90,\n\t0x4B, 0x78, 0x00, 0xC1, 0x00, 0x00, 0x91, 0x43, 0x72, 0x00, 0xC2, 0x04, 0x00, 0x92, 0x3F, 0x65,\n\t0x00, 0x93, 0x3D, 0x72, 0x00, 0x94, 0x3A, 0x72, 0x00, 0x95, 0x27, 0x78, 0x00, 0x9B, 0x24, 0x6B,\n\t0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9B, 0x24, 0x00, 0x00, 0x9C, 0x26, 0x00,\n\t0x00, 0x9F, 0x28, 0x00, 0x0B, 0x90, 0x4B, 0x00, 0x00, 0x91, 0x43, 0x00, 0x00, 0x90, 0x4D, 0x78,\n\t0x00, 0x91, 0x44, 0x72, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x90, 0x4D, 0x00,\n\t0x00, 0x91, 0x44, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x00, 0x90, 0x4F, 0x78,\n\t0x00, 0x91, 0x46, 0x72, 0x0A, 0x92, 0x3F, 0x00, 0x00, 0x93, 0x3D, 0x00, 0x00, 0x94, 0x3A, 0x00,\n\t0x00, 0x95, 0x27, 0x00, 0x00, 0x90, 0x4F, 0x00, 0x00, 0x91, 0x46, 0x00, 0x00, 0x90, 0x50, 0x78,\n\t0x00, 0x91, 0x48, 0x72, 0x00, 0x92, 0x44, 0x65, 0x00, 0x95, 0x20, 0x78, 0x00, 0x9B, 0x24, 0x6B,\n\t0x00, 0x9E, 0x29, 0x4C, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x93, 0x3C, 0x72,\n\t0x00, 0x94, 0x38, 0x72, 0x00, 0x9E, 0x29, 0x4C, 0x0A, 0x29, 0x00, 0x0B, 0x90, 0x50, 0x00, 0x00,\n\t0x91, 0x48, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00, 0x93, 0x3C, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00,\n\t0x90, 0x50, 0x78, 0x00, 0x91, 0x48, 0x72, 0x00, 0x92, 0x44, 0x65, 0x00, 0x93, 0x3C, 0x72, 0x00,\n\t0x94, 0x33, 0x72, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B, 0x9C, 0x26, 0x00, 0x00,\n\t0x9E, 0x29, 0x00, 0x0A, 0x90, 0x50, 0x00, 0x00, 0x91, 0x48, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00,\n\t0x90, 0x52, 0x78, 0x00, 0x91, 0x49, 0x72, 0x00, 0x92, 0x46, 0x65, 0x00, 0x9B, 0x24, 0x6B, 0x00,\n\t0x9E, 0x29, 0x4C, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x93, 0x3C, 0x00, 0x00,\n\t0x94, 0x33, 0x00, 0x00, 0x90, 0x52, 0x00, 0x00, 0x91, 0x49, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00,\n\t0x90, 0x50, 0x78, 0x00, 0x91, 0x48, 0x72, 0x00, 0x92, 0x44, 0x65, 0x00, 0x93, 0x3C, 0x72, 0x00,\n\t0x94, 0x38, 0x72, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0A, 0x9C, 0x26, 0x00, 0x00,\n\t0x9E, 0x29, 0x00, 0x0B, 0x90, 0x50, 0x00, 0x00, 0x91, 0x48, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00,\n\t0x90, 0x4F, 0x78, 0x00, 0x91, 0x46, 0x72, 0x00, 0x92, 0x43, 0x65, 0x00, 0x9B, 0x24, 0x6B, 0x00,\n\t0x9E, 0x29, 0x4C, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0A, 0x95, 0x20, 0x00, 0x00,\n\t0x93, 0x3C, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x90, 0x4F, 0x00, 0x00, 0x91, 0x46, 0x00, 0x00,\n\t0x92, 0x43, 0x00, 0x00, 0x90, 0x4D, 0x78, 0x00, 0x91, 0x44, 0x72, 0x00, 0x92, 0x41, 0x65, 0x00,\n\t0x95, 0x25, 0x78, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B, 0x9B, 0x24, 0x00, 0x00,\n\t0x9E, 0x29, 0x00, 0x0B, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0A, 0x9C, 0x26, 0x00, 0x00,\n\t0x9E, 0x29, 0x00, 0x0B, 0x90, 0x4D, 0x00, 0x00, 0x91, 0x44, 0x00, 0x00, 0x92, 0x41, 0x00, 0x00,\n\t0x90, 0x4D, 0x78, 0x00, 0x91, 0x44, 0x72, 0x00, 0x92, 0x41, 0x65, 0x00, 0x93, 0x3D, 0x72, 0x00,\n\t0x94, 0x38, 0x72, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B, 0x9C, 0x26, 0x00, 0x00,\n\t0x9E, 0x29, 0x00, 0x0A, 0x29, 0x4C, 0x0B, 0x90, 0x4D, 0x00, 0x00, 0x91, 0x44, 0x00, 0x00, 0x92,\n\t0x41, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x95, 0x25, 0x00, 0x00, 0x93, 0x3D, 0x00, 0x00, 0x94,\n\t0x38, 0x00, 0x00, 0x90, 0x4D, 0x78, 0x00, 0x91, 0x45, 0x72, 0x00, 0x92, 0x41, 0x65, 0x00, 0x93,\n\t0x3F, 0x72, 0x00, 0x94, 0x39, 0x72, 0x00, 0x95, 0x24, 0x78, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9C,\n\t0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0A, 0x9B, 0x24, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9E,\n\t0x29, 0x00, 0x0B, 0x29, 0x4C, 0x0B, 0x29, 0x00, 0x0A, 0x90, 0x4D, 0x00, 0x00, 0x91, 0x45, 0x00,\n\t0x00, 0x92, 0x41, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x39, 0x00, 0x00, 0x95, 0x24, 0x00,\n\t0x00, 0x90, 0x52, 0x78, 0x00, 0x91, 0x4A, 0x72, 0x00, 0x92, 0x46, 0x65, 0x00, 0x95, 0x22, 0x78,\n\t0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00,\n\t0x0B, 0x93, 0x3E, 0x72, 0x00, 0x94, 0x3A, 0x72, 0x00, 0x9E, 0x29, 0x4C, 0x0A, 0x29, 0x00, 0x0B,\n\t0x90, 0x52, 0x00, 0x00, 0x91, 0x4A, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x93, 0x3E, 0x00, 0x00,\n\t0x94, 0x3A, 0x00, 0x00, 0x90, 0x52, 0x78, 0x00, 0x91, 0x4A, 0x72, 0x00, 0x92, 0x46, 0x65, 0x00,\n\t0x93, 0x3E, 0x72, 0x00, 0x94, 0x35, 0x72, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B,\n\t0x9C, 0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0A, 0x90, 0x52, 0x00, 0x00, 0x91, 0x4A, 0x00, 0x00,\n\t0x92, 0x46, 0x00, 0x00, 0x90, 0x54, 0x78, 0x00, 0x91, 0x4B, 0x72, 0x00, 0x92, 0x48, 0x65, 0x00,\n\t0x9B, 0x24, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B,\n\t0x93, 0x3E, 0x00, 0x00, 0x94, 0x35, 0x00, 0x00, 0x90, 0x54, 0x00, 0x00, 0x91, 0x4B, 0x00, 0x00,\n\t0x92, 0x48, 0x00, 0x00, 0x90, 0x52, 0x78, 0x00, 0x91, 0x4A, 0x72, 0x00, 0x92, 0x46, 0x65, 0x00,\n\t0x93, 0x3E, 0x72, 0x00, 0x94, 0x3A, 0x72, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0A,\n\t0x9C, 0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x90, 0x52, 0x00, 0x00, 0x91, 0x4A, 0x00, 0x00,\n\t0x92, 0x46, 0x00, 0x00, 0x90, 0x50, 0x78, 0x00, 0x91, 0x48, 0x72, 0x00, 0x92, 0x44, 0x65, 0x00,\n\t0x9B, 0x24, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0A,\n\t0x95, 0x22, 0x00, 0x00, 0x93, 0x3E, 0x00, 0x00, 0x94, 0x3A, 0x00, 0x00, 0x90, 0x50, 0x00, 0x00,\n\t0x91, 0x48, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00, 0x90, 0x4F, 0x78, 0x00, 0x91, 0x46, 0x72, 0x00,\n\t0x92, 0x43, 0x65, 0x00, 0x95, 0x27, 0x78, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B,\n\t0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0A,\n\t0x9C, 0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x90, 0x4F, 0x00, 0x00, 0x91, 0x46, 0x00, 0x00,\n\t0x92, 0x43, 0x00, 0x00, 0x90, 0x4B, 0x78, 0x00, 0x91, 0x43, 0x72, 0x00, 0x92, 0x3F, 0x65, 0x00,\n\t0x93, 0x3F, 0x72, 0x00, 0x94, 0x37, 0x72, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B,\n\t0x9C, 0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0A, 0x29, 0x4C, 0x0B, 0x90, 0x4B, 0x00, 0x00, 0x91,\n\t0x43, 0x00, 0x00, 0x92, 0x3F, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x95, 0x27, 0x00, 0x00, 0x93,\n\t0x3F, 0x00, 0x00, 0x94, 0x37, 0x00, 0x00, 0x90, 0x4B, 0x78, 0x00, 0x91, 0x43, 0x72, 0x00, 0x92,\n\t0x3F, 0x65, 0x00, 0x93, 0x3F, 0x72, 0x00, 0x94, 0x37, 0x72, 0x00, 0x95, 0x25, 0x78, 0x00, 0x9B,\n\t0x24, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0A, 0x9B, 0x24, 0x00, 0x00, 0x9C,\n\t0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x29, 0x4C, 0x0B, 0x29, 0x00, 0x0A, 0x90, 0x4B, 0x00,\n\t0x00, 0x91, 0x43, 0x00, 0x00, 0x92, 0x3F, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x37, 0x00,\n\t0x00, 0x95, 0x25, 0x00, 0x00, 0x90, 0x54, 0x78, 0x00, 0x91, 0x4C, 0x72, 0x00, 0x92, 0x48, 0x65,\n\t0x00, 0x95, 0x24, 0x78, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B, 0x9B, 0x24, 0x00,\n\t0x00, 0x9E, 0x29, 0x00, 0x0B, 0x93, 0x40, 0x72, 0x00, 0x94, 0x37, 0x72, 0x00, 0x9E, 0x29, 0x4C,\n\t0x0A, 0x29, 0x00, 0x0B, 0x90, 0x54, 0x00, 0x00, 0x91, 0x4C, 0x00, 0x00, 0x92, 0x48, 0x00, 0x00,\n\t0x93, 0x40, 0x00, 0x00, 0x94, 0x37, 0x00, 0x00, 0x90, 0x54, 0x78, 0x00, 0x91, 0x4C, 0x72, 0x00,\n\t0x92, 0x48, 0x65, 0x00, 0x93, 0x40, 0x72, 0x00, 0x94, 0x37, 0x72, 0x00, 0x9C, 0x26, 0x6B, 0x00,\n\t0x9E, 0x29, 0x4C, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0A, 0x90, 0x54, 0x00, 0x00,\n\t0x91, 0x4C, 0x00, 0x00, 0x92, 0x48, 0x00, 0x00, 0x90, 0x55, 0x78, 0x00, 0x91, 0x4D, 0x72, 0x00,\n\t0x92, 0x49, 0x65, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B, 0x9B, 0x24, 0x00, 0x00,\n\t0x9E, 0x29, 0x00, 0x0B, 0x93, 0x40, 0x00, 0x00, 0x94, 0x37, 0x00, 0x00, 0x90, 0x55, 0x00, 0x00,\n\t0x91, 0x4D, 0x00, 0x00, 0x92, 0x49, 0x00, 0x00, 0x90, 0x54, 0x78, 0x00, 0x91, 0x4C, 0x72, 0x00,\n\t0x92, 0x48, 0x65, 0x00, 0x93, 0x40, 0x72, 0x00, 0x94, 0x3C, 0x72, 0x00, 0x9C, 0x26, 0x6B, 0x00,\n\t0x9E, 0x29, 0x4C, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x90, 0x54, 0x00, 0x00,\n\t0x91, 0x4C, 0x00, 0x00, 0x92, 0x48, 0x00, 0x00, 0x90, 0x52, 0x78, 0x00, 0x91, 0x49, 0x72, 0x00,\n\t0x92, 0x46, 0x65, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B, 0x9B, 0x24, 0x00, 0x00,\n\t0x9E, 0x29, 0x00, 0x0A, 0x95, 0x24, 0x00, 0x00, 0x93, 0x40, 0x00, 0x00, 0x94, 0x3C, 0x00, 0x00,\n\t0x90, 0x52, 0x00, 0x00, 0x91, 0x49, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x90, 0x50, 0x78, 0x00,\n\t0x91, 0x48, 0x72, 0x00, 0x92, 0x44, 0x65, 0x00, 0x95, 0x29, 0x78, 0x00, 0x9B, 0x24, 0x6B, 0x00,\n\t0x9E, 0x29, 0x4C, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x93, 0x41, 0x72, 0x00,\n\t0x94, 0x3C, 0x72, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0A, 0x9C, 0x26, 0x00, 0x00,\n\t0x9E, 0x29, 0x00, 0x0B, 0x90, 0x50, 0x00, 0x00, 0x91, 0x48, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00,\n\t0x95, 0x29, 0x00, 0x00, 0x93, 0x41, 0x00, 0x00, 0x94, 0x3C, 0x00, 0x00, 0x90, 0x4D, 0x78, 0x00,\n\t0x91, 0x49, 0x72, 0x00, 0x92, 0x41, 0x65, 0x00, 0x93, 0x3D, 0x72, 0x00, 0x94, 0x3A, 0x72, 0x00,\n\t0x95, 0x22, 0x78, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0B, 0x9C, 0x26, 0x00, 0x00,\n\t0x9E, 0x29, 0x00, 0x0A, 0x29, 0x4C, 0x0B, 0x90, 0x4D, 0x00, 0x00, 0x91, 0x49, 0x00, 0x00, 0x92,\n\t0x41, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x93, 0x3D, 0x00, 0x00, 0x94, 0x3A, 0x00, 0x00, 0x95,\n\t0x22, 0x00, 0x00, 0x90, 0x4B, 0x78, 0x00, 0x91, 0x48, 0x72, 0x00, 0x92, 0x3F, 0x65, 0x00, 0x93,\n\t0x3F, 0x72, 0x00, 0x94, 0x38, 0x72, 0x00, 0x95, 0x24, 0x78, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9C,\n\t0x26, 0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x0A, 0x9B, 0x24, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9E,\n\t0x29, 0x00, 0x0B, 0x90, 0x4B, 0x00, 0x00, 0x91, 0x48, 0x00, 0x00, 0x92, 0x3F, 0x00, 0x00, 0x90,\n\t0x4B, 0x78, 0x00, 0x91, 0x48, 0x72, 0x00, 0x92, 0x3F, 0x65, 0x00, 0x9E, 0x29, 0x4C, 0x0B, 0x29,\n\t0x00, 0x0A, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x95, 0x24, 0x00, 0x00, 0x90, 0x4B,\n\t0x00, 0x00, 0x91, 0x48, 0x00, 0x00, 0x92, 0x3F, 0x00, 0x00, 0x90, 0x4D, 0x78, 0x00, 0x91, 0x44,\n\t0x72, 0x00, 0x92, 0x41, 0x65, 0x00, 0x95, 0x25, 0x78, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9E, 0x29,\n\t0x4C, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x93, 0x3D, 0x72, 0x00, 0x94, 0x38,\n\t0x72, 0x00, 0x9E, 0x29, 0x4C, 0x0A, 0x90, 0x4D, 0x00, 0x00, 0x91, 0x44, 0x00, 0x00, 0x92, 0x41,\n\t0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x95, 0x25, 0x00, 0x00, 0x93, 0x3D, 0x00, 0x00, 0x94, 0x38,\n\t0x00, 0x00, 0x90, 0x52, 0x78, 0x00, 0x91, 0x49, 0x72, 0x00, 0x92, 0x46, 0x65, 0x00, 0x93, 0x41,\n\t0x72, 0x00, 0x94, 0x3D, 0x72, 0x00, 0x95, 0x22, 0x78, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29,\n\t0x4C, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0A, 0x9B, 0x24, 0x6B, 0x00, 0x9E, 0x29,\n\t0x4C, 0x0B, 0x90, 0x52, 0x00, 0x00, 0x91, 0x49, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x9B, 0x24,\n\t0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x93, 0x41, 0x00, 0x00, 0x94, 0x3D, 0x00, 0x00, 0x95, 0x22,\n\t0x00, 0x00, 0x90, 0x4F, 0x78, 0x00, 0x91, 0x46, 0x72, 0x00, 0x92, 0x43, 0x65, 0x00, 0x93, 0x3F,\n\t0x72, 0x00, 0x94, 0x3D, 0x72, 0x00, 0x95, 0x27, 0x78, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29,\n\t0x4C, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0C, 0x9B, 0x24, 0x6B, 0x00, 0x9E, 0x29,\n\t0x4C, 0x0C, 0x90, 0x4F, 0x00, 0x00, 0x91, 0x46, 0x00, 0x00, 0x92, 0x43, 0x00, 0x00, 0x9B, 0x24,\n\t0x00, 0x00, 0x9E, 0x29, 0x00, 0x0C, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x3D, 0x00, 0x00, 0x95, 0x27,\n\t0x00, 0x00, 0x90, 0x50, 0x78, 0x00, 0x91, 0x48, 0x72, 0x00, 0x92, 0x44, 0x65, 0x00, 0x93, 0x3F,\n\t0x72, 0x00, 0x94, 0x3C, 0x72, 0x00, 0x95, 0x20, 0x78, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9E, 0x29,\n\t0x4C, 0x0C, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0C, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29,\n\t0x4C, 0x0C, 0x9C, 0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x9C, 0x26, 0x6B, 0x00, 0x9E, 0x29,\n\t0x4C, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0A, 0x29, 0x4C, 0x0B, 0x90, 0x50, 0x00,\n\t0x00, 0x91, 0x48, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x3C, 0x00,\n\t0x00, 0x95, 0x20, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0xC0, 0x01, 0x00, 0x90, 0x3F, 0x65, 0x00,\n\t0xC2, 0x03, 0x00, 0x92, 0x3F, 0x72, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9E,\n\t0x29, 0x4C, 0x0A, 0x9B, 0x24, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x29,\n\t0x4C, 0x0B, 0x29, 0x00, 0x0A, 0x90, 0x3F, 0x00, 0x00, 0x92, 0x3F, 0x00, 0x00, 0x90, 0x44, 0x65,\n\t0x00, 0x92, 0x44, 0x72, 0x00, 0x94, 0x3C, 0x6B, 0x00, 0x95, 0x2C, 0x6E, 0x00, 0x9B, 0x24, 0x65,\n\t0x00, 0x9E, 0x29, 0x45, 0x00, 0xCF, 0x0B, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B,\n\t0x94, 0x3C, 0x00, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0A, 0x28, 0x00, 0x0B, 0x90,\n\t0x44, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x90, 0x44, 0x65, 0x00, 0x92,\n\t0x44, 0x72, 0x00, 0x94, 0x3C, 0x6B, 0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x9C,\n\t0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x94, 0x3C, 0x00, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F,\n\t0x28, 0x5F, 0x0B, 0x28, 0x00, 0x0B, 0x90, 0x44, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00, 0x93, 0x3F,\n\t0x00, 0x00, 0x90, 0x44, 0x65, 0x00, 0x92, 0x44, 0x72, 0x00, 0x94, 0x3C, 0x6B, 0x00, 0x9C, 0x26,\n\t0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x94, 0x3C,\n\t0x00, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x28, 0x00, 0x0A, 0x95, 0x2C, 0x00,\n\t0x00, 0x90, 0x44, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x90, 0x43, 0x65,\n\t0x00, 0x92, 0x43, 0x72, 0x00, 0x94, 0x3A, 0x6B, 0x00, 0x95, 0x2E, 0x6E, 0x00, 0x9B, 0x24, 0x65,\n\t0x00, 0x9E, 0x29, 0x45, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x94, 0x3A, 0x00,\n\t0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0A, 0x28, 0x00, 0x0B, 0x93, 0x3F, 0x00, 0x00,\n\t0x94, 0x3A, 0x6B, 0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x9C, 0x26, 0x00, 0x00,\n\t0x9F, 0x28, 0x00, 0x0A, 0x94, 0x3A, 0x00, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0B,\n\t0x28, 0x00, 0x0B, 0x90, 0x43, 0x00, 0x00, 0x92, 0x43, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x90,\n\t0x43, 0x65, 0x00, 0x92, 0x43, 0x72, 0x00, 0x94, 0x3A, 0x6B, 0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F,\n\t0x28, 0x5F, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x94, 0x3A, 0x00, 0x00, 0x93,\n\t0x3F, 0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x28, 0x00, 0x0A, 0x95, 0x2E, 0x00, 0x00, 0x90, 0x43,\n\t0x00, 0x00, 0x92, 0x43, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x90, 0x44, 0x65, 0x00, 0x92, 0x44,\n\t0x72, 0x00, 0x94, 0x3A, 0x6B, 0x00, 0x95, 0x2E, 0x6E, 0x00, 0x9B, 0x24, 0x65, 0x00, 0x9E, 0x29,\n\t0x45, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x94, 0x3A, 0x00, 0x00, 0x93, 0x3E,\n\t0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0A, 0x28, 0x00, 0x0B, 0x90, 0x44, 0x00, 0x00, 0x92, 0x44, 0x00,\n\t0x00, 0x93, 0x3E, 0x00, 0x00, 0x90, 0x43, 0x65, 0x00, 0x92, 0x43, 0x72, 0x00, 0x94, 0x3A, 0x6B,\n\t0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00,\n\t0x0A, 0x94, 0x3A, 0x00, 0x00, 0x93, 0x3E, 0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x28, 0x00, 0x0B,\n\t0x90, 0x43, 0x00, 0x00, 0x92, 0x43, 0x00, 0x00, 0x93, 0x3E, 0x00, 0x00, 0x90, 0x41, 0x65, 0x00,\n\t0x92, 0x41, 0x72, 0x00, 0x94, 0x38, 0x6B, 0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0A,\n\t0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x94, 0x38, 0x00, 0x00, 0x93, 0x3E, 0x6B, 0x00,\n\t0x9F, 0x28, 0x5F, 0x0B, 0x28, 0x00, 0x0A, 0x95, 0x2E, 0x00, 0x00, 0x90, 0x41, 0x00, 0x00, 0x92,\n\t0x41, 0x00, 0x00, 0x93, 0x3E, 0x00, 0x00, 0x90, 0x3F, 0x65, 0x00, 0x92, 0x3F, 0x72, 0x00, 0x94,\n\t0x37, 0x6B, 0x00, 0x95, 0x27, 0x6E, 0x00, 0x9B, 0x24, 0x65, 0x00, 0x9E, 0x29, 0x45, 0x0B, 0x9B,\n\t0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x94, 0x37, 0x00, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F,\n\t0x28, 0x5F, 0x0A, 0x28, 0x00, 0x0B, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x37, 0x6B, 0x00, 0x9C, 0x26,\n\t0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x94, 0x37,\n\t0x00, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x90, 0x3F, 0x00, 0x00, 0x92, 0x3F,\n\t0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x93, 0x3F, 0x00, 0x00, 0x90, 0x46, 0x65, 0x00, 0x92, 0x46,\n\t0x72, 0x00, 0x94, 0x37, 0x6B, 0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0A, 0x9C, 0x26,\n\t0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x94, 0x37, 0x00, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F, 0x28,\n\t0x5F, 0x0B, 0x28, 0x00, 0x0A, 0x95, 0x27, 0x00, 0x00, 0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00,\n\t0x00, 0x93, 0x3F, 0x00, 0x00, 0x90, 0x48, 0x65, 0x00, 0x92, 0x48, 0x72, 0x00, 0x94, 0x38, 0x6B,\n\t0x00, 0x95, 0x2C, 0x6E, 0x00, 0x9B, 0x24, 0x65, 0x00, 0x9E, 0x29, 0x45, 0x0B, 0x9B, 0x24, 0x00,\n\t0x00, 0x9E, 0x29, 0x00, 0x0B, 0x94, 0x38, 0x00, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F, 0x28, 0x5F,\n\t0x0A, 0x28, 0x00, 0x0B, 0x90, 0x48, 0x00, 0x00, 0x92, 0x48, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00,\n\t0x90, 0x46, 0x65, 0x00, 0x92, 0x46, 0x72, 0x00, 0x94, 0x3A, 0x6B, 0x00, 0x9C, 0x26, 0x65, 0x00,\n\t0x9F, 0x28, 0x5F, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x94, 0x3A, 0x00, 0x00,\n\t0x93, 0x3D, 0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x28, 0x00, 0x0B, 0x90, 0x46, 0x00, 0x00, 0x92,\n\t0x46, 0x00, 0x00, 0x93, 0x3D, 0x00, 0x00, 0x90, 0x44, 0x65, 0x00, 0x92, 0x44, 0x72, 0x00, 0x94,\n\t0x3C, 0x6B, 0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F,\n\t0x28, 0x00, 0x0B, 0x94, 0x3C, 0x00, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x28,\n\t0x00, 0x0A, 0x95, 0x2C, 0x00, 0x00, 0x90, 0x44, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00, 0x93, 0x3F,\n\t0x00, 0x00, 0x90, 0x4B, 0x65, 0x00, 0x92, 0x4B, 0x72, 0x00, 0x94, 0x38, 0x6B, 0x00, 0x95, 0x30,\n\t0x6E, 0x00, 0x9B, 0x24, 0x65, 0x00, 0x9E, 0x29, 0x45, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29,\n\t0x00, 0x0B, 0x94, 0x38, 0x00, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0A, 0x28, 0x00,\n\t0x0B, 0x90, 0x4B, 0x00, 0x00, 0x92, 0x4B, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x90, 0x3F, 0x65,\n\t0x00, 0x92, 0x3F, 0x72, 0x00, 0x94, 0x38, 0x6B, 0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F,\n\t0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x94, 0x38, 0x00, 0x00, 0x93, 0x3F, 0x6B,\n\t0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x28, 0x00, 0x0B, 0x90, 0x3F, 0x00, 0x00, 0x92, 0x3F, 0x00, 0x00,\n\t0x93, 0x3F, 0x00, 0x00, 0x90, 0x3F, 0x65, 0x00, 0x92, 0x3F, 0x72, 0x00, 0x94, 0x38, 0x6B, 0x00,\n\t0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B,\n\t0x90, 0x3F, 0x00, 0x00, 0x92, 0x3F, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x90, 0x3F, 0x65, 0x00,\n\t0x92, 0x3F, 0x72, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x28, 0x00, 0x0A, 0x95,\n\t0x30, 0x00, 0x00, 0x90, 0x3F, 0x00, 0x00, 0x92, 0x3F, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x90,\n\t0x41, 0x65, 0x00, 0x92, 0x41, 0x72, 0x00, 0x94, 0x38, 0x6B, 0x00, 0x95, 0x31, 0x6E, 0x00, 0x9B,\n\t0x24, 0x65, 0x00, 0x9E, 0x29, 0x45, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0B, 0x94,\n\t0x38, 0x00, 0x00, 0x93, 0x3D, 0x6B, 0x00, 0x9F, 0x28, 0x5F, 0x0A, 0x90, 0x41, 0x00, 0x00, 0x92,\n\t0x41, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x93, 0x3D, 0x00, 0x00, 0x90, 0x46, 0x65, 0x00, 0x92,\n\t0x46, 0x72, 0x00, 0x94, 0x3D, 0x6B, 0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x9C,\n\t0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x94, 0x3D, 0x00, 0x00, 0x93, 0x41, 0x6B, 0x00, 0x9F,\n\t0x28, 0x5F, 0x0B, 0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x95,\n\t0x31, 0x00, 0x00, 0x93, 0x41, 0x00, 0x00, 0x90, 0x43, 0x65, 0x00, 0x92, 0x43, 0x72, 0x00, 0x94,\n\t0x3D, 0x6B, 0x00, 0x95, 0x33, 0x6E, 0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0A, 0x9C,\n\t0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x94, 0x3D, 0x00, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9F,\n\t0x28, 0x5F, 0x0C, 0x90, 0x43, 0x00, 0x00, 0x92, 0x43, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0C, 0x95,\n\t0x33, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x90, 0x44, 0x65, 0x00, 0x92, 0x44, 0x72, 0x00, 0x94,\n\t0x3C, 0x6B, 0x00, 0x95, 0x2C, 0x6E, 0x00, 0x9B, 0x24, 0x65, 0x00, 0x9E, 0x29, 0x45, 0x0C, 0x9B,\n\t0x24, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x0C, 0x94, 0x3C, 0x00, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x9C,\n\t0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0C, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0C, 0x93,\n\t0x3F, 0x00, 0x00, 0x94, 0x38, 0x6B, 0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F, 0x0C, 0x9C,\n\t0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0C, 0x94, 0x38, 0x00, 0x00, 0x93, 0x3D, 0x6B, 0x00, 0x9C,\n\t0x26, 0x5F, 0x00, 0x9F, 0x28, 0x5F, 0x0B, 0x90, 0x44, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00, 0x95,\n\t0x2C, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x93, 0x3D, 0x00, 0x00, 0xC0,\n\t0x00, 0x00, 0x90, 0x3F, 0x78, 0x00, 0xC2, 0x03, 0x00, 0x92, 0x3F, 0x6B, 0x00, 0x93, 0x3A, 0x6B,\n\t0x00, 0x94, 0x37, 0x6B, 0x00, 0x95, 0x33, 0x74, 0x00, 0x9C, 0x26, 0x65, 0x00, 0x9F, 0x28, 0x5F,\n\t0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x00, 0x9C, 0x26, 0x68, 0x0B, 0x26, 0x00, 0x00,\n\t0x26, 0x6A, 0x00, 0x9F, 0x28, 0x5F, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x00, 0x9C,\n\t0x26, 0x6D, 0x0B, 0x90, 0x3F, 0x00, 0x00, 0x92, 0x3F, 0x00, 0x00, 0x93, 0x3A, 0x00, 0x00, 0x94,\n\t0x37, 0x00, 0x00, 0x95, 0x33, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x90, 0x44, 0x78, 0x00, 0xC1,\n\t0x02, 0x00, 0x92, 0x44, 0x6B, 0x00, 0x95, 0x2C, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9C, 0x26,\n\t0x6B, 0x00, 0x9E, 0x29, 0x4C, 0x00, 0xCF, 0x0A, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00,\n\t0x00, 0x9C, 0x26, 0x00, 0x00, 0x9E, 0x29, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x93, 0x3C, 0x6B,\n\t0x00, 0x94, 0x38, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x28, 0x00, 0x0B, 0x90, 0x44, 0x00, 0x00,\n\t0x92, 0x44, 0x00, 0x00, 0x93, 0x3C, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x90, 0x44, 0x78, 0x00,\n\t0x92, 0x44, 0x6B, 0x00, 0x93, 0x3C, 0x6B, 0x00, 0x94, 0x33, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00,\n\t0x9F, 0x28, 0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x90, 0x44, 0x00, 0x00,\n\t0x92, 0x44, 0x00, 0x00, 0x90, 0x46, 0x78, 0x00, 0x92, 0x46, 0x6B, 0x00, 0x9B, 0x24, 0x6B, 0x00,\n\t0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x93, 0x3C, 0x00, 0x00,\n\t0x94, 0x33, 0x00, 0x00, 0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x90, 0x44, 0x78, 0x00,\n\t0x92, 0x44, 0x6B, 0x00, 0x93, 0x3C, 0x6B, 0x00, 0x94, 0x38, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00,\n\t0x9F, 0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x90, 0x44, 0x00, 0x00,\n\t0x92, 0x44, 0x00, 0x00, 0x90, 0x43, 0x78, 0x00, 0x92, 0x43, 0x6B, 0x00, 0x9B, 0x24, 0x6B, 0x00,\n\t0x9F, 0x28, 0x58, 0x0A, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x95, 0x2C, 0x00, 0x00,\n\t0x93, 0x3C, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x90, 0x43, 0x00, 0x00, 0x92, 0x43, 0x00, 0x00,\n\t0x90, 0x41, 0x78, 0x00, 0x92, 0x41, 0x6B, 0x00, 0x95, 0x31, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00,\n\t0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x9C, 0x26, 0x6B, 0x00,\n\t0x9F, 0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x90, 0x41, 0x00, 0x00,\n\t0x92, 0x41, 0x00, 0x00, 0x90, 0x41, 0x78, 0x00, 0x92, 0x41, 0x6B, 0x00, 0x93, 0x3D, 0x6B, 0x00,\n\t0x94, 0x38, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00,\n\t0x9F, 0x28, 0x00, 0x0B, 0x28, 0x58, 0x0B, 0x90, 0x41, 0x00, 0x00, 0x92, 0x41, 0x00, 0x00, 0x9F,\n\t0x28, 0x00, 0x0A, 0x95, 0x31, 0x00, 0x00, 0x93, 0x3D, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x90,\n\t0x41, 0x78, 0x00, 0x92, 0x41, 0x6B, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x94, 0x39, 0x6B, 0x00, 0x95,\n\t0x30, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B,\n\t0x24, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x28, 0x58, 0x0A, 0x28, 0x00,\n\t0x0B, 0x90, 0x41, 0x00, 0x00, 0x92, 0x41, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x39, 0x00,\n\t0x00, 0x95, 0x30, 0x00, 0x00, 0x90, 0x46, 0x78, 0x00, 0x92, 0x46, 0x6B, 0x00, 0x95, 0x2E, 0x74,\n\t0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00,\n\t0x0A, 0x93, 0x3E, 0x6B, 0x00, 0x94, 0x3A, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x28, 0x00, 0x0B,\n\t0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x93, 0x3E, 0x00, 0x00, 0x94, 0x3A, 0x00, 0x00,\n\t0x90, 0x46, 0x78, 0x00, 0x92, 0x46, 0x6B, 0x00, 0x93, 0x3E, 0x6B, 0x00, 0x94, 0x35, 0x6B, 0x00,\n\t0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B,\n\t0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x90, 0x48, 0x78, 0x00, 0x92, 0x48, 0x6B, 0x00,\n\t0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A,\n\t0x93, 0x3E, 0x00, 0x00, 0x94, 0x35, 0x00, 0x00, 0x90, 0x48, 0x00, 0x00, 0x92, 0x48, 0x00, 0x00,\n\t0x90, 0x46, 0x78, 0x00, 0x92, 0x46, 0x6B, 0x00, 0x93, 0x3E, 0x6B, 0x00, 0x94, 0x3A, 0x6B, 0x00,\n\t0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B,\n\t0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x90, 0x44, 0x78, 0x00, 0x92, 0x44, 0x6B, 0x00,\n\t0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B,\n\t0x95, 0x2E, 0x00, 0x00, 0x93, 0x3E, 0x00, 0x00, 0x94, 0x3A, 0x00, 0x00, 0x90, 0x44, 0x00, 0x00,\n\t0x92, 0x44, 0x00, 0x00, 0x90, 0x43, 0x78, 0x00, 0x92, 0x43, 0x6B, 0x00, 0x95, 0x33, 0x74, 0x00,\n\t0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A,\n\t0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B,\n\t0x90, 0x43, 0x00, 0x00, 0x92, 0x43, 0x00, 0x00, 0x90, 0x3F, 0x78, 0x00, 0x92, 0x3F, 0x6B, 0x00,\n\t0x93, 0x3F, 0x6B, 0x00, 0x94, 0x37, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A,\n\t0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x28, 0x58, 0x0B, 0x90, 0x3F, 0x00, 0x00, 0x92,\n\t0x3F, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x95, 0x33, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x94,\n\t0x37, 0x00, 0x00, 0x90, 0x3F, 0x78, 0x00, 0x92, 0x3F, 0x6B, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x94,\n\t0x37, 0x6B, 0x00, 0x95, 0x31, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F,\n\t0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x28,\n\t0x58, 0x0A, 0x28, 0x00, 0x0B, 0x90, 0x3F, 0x00, 0x00, 0x92, 0x3F, 0x00, 0x00, 0x93, 0x3F, 0x00,\n\t0x00, 0x94, 0x37, 0x00, 0x00, 0x95, 0x31, 0x00, 0x00, 0x90, 0x48, 0x78, 0x00, 0x92, 0x48, 0x6B,\n\t0x00, 0x95, 0x30, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00,\n\t0x00, 0x9F, 0x28, 0x00, 0x0A, 0x93, 0x40, 0x6B, 0x00, 0x94, 0x37, 0x6B, 0x00, 0x9F, 0x28, 0x58,\n\t0x0B, 0x28, 0x00, 0x0B, 0x90, 0x48, 0x00, 0x00, 0x92, 0x48, 0x00, 0x00, 0x93, 0x40, 0x00, 0x00,\n\t0x94, 0x37, 0x00, 0x00, 0x90, 0x48, 0x78, 0x00, 0x92, 0x48, 0x6B, 0x00, 0x93, 0x40, 0x6B, 0x00,\n\t0x94, 0x37, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00,\n\t0x9F, 0x28, 0x00, 0x0B, 0x90, 0x48, 0x00, 0x00, 0x92, 0x48, 0x00, 0x00, 0x90, 0x49, 0x78, 0x00,\n\t0x92, 0x49, 0x6B, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00,\n\t0x9F, 0x28, 0x00, 0x0A, 0x93, 0x40, 0x00, 0x00, 0x94, 0x37, 0x00, 0x00, 0x90, 0x49, 0x00, 0x00,\n\t0x92, 0x49, 0x00, 0x00, 0x90, 0x48, 0x78, 0x00, 0x92, 0x48, 0x6B, 0x00, 0x93, 0x40, 0x6B, 0x00,\n\t0x94, 0x3C, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00, 0x00,\n\t0x9F, 0x28, 0x00, 0x0B, 0x90, 0x48, 0x00, 0x00, 0x92, 0x48, 0x00, 0x00, 0x90, 0x46, 0x78, 0x00,\n\t0x92, 0x46, 0x6B, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9B, 0x24, 0x00, 0x00,\n\t0x9F, 0x28, 0x00, 0x0B, 0x95, 0x30, 0x00, 0x00, 0x93, 0x40, 0x00, 0x00, 0x94, 0x3C, 0x00, 0x00,\n\t0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x90, 0x44, 0x78, 0x00, 0x92, 0x44, 0x6B, 0x00,\n\t0x95, 0x35, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00,\n\t0x9F, 0x28, 0x00, 0x0A, 0x93, 0x41, 0x6B, 0x00, 0x94, 0x3C, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00,\n\t0x9F, 0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x90, 0x44, 0x00, 0x00,\n\t0x92, 0x44, 0x00, 0x00, 0x95, 0x35, 0x00, 0x00, 0x93, 0x41, 0x00, 0x00, 0x94, 0x3C, 0x00, 0x00,\n\t0x90, 0x41, 0x78, 0x00, 0x92, 0x41, 0x6B, 0x00, 0x93, 0x3D, 0x6B, 0x00, 0x94, 0x3A, 0x6B, 0x00,\n\t0x95, 0x2E, 0x74, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00,\n\t0x9F, 0x28, 0x00, 0x0B, 0x28, 0x58, 0x0B, 0x90, 0x41, 0x00, 0x00, 0x92, 0x41, 0x00, 0x00, 0x9F,\n\t0x28, 0x00, 0x0A, 0x93, 0x3D, 0x00, 0x00, 0x94, 0x3A, 0x00, 0x00, 0x95, 0x2E, 0x00, 0x00, 0x90,\n\t0x3F, 0x78, 0x00, 0x92, 0x3F, 0x6B, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x94, 0x38, 0x6B, 0x00, 0x95,\n\t0x30, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B,\n\t0x24, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x90, 0x3F, 0x00, 0x00, 0x92,\n\t0x3F, 0x00, 0x00, 0x90, 0x3F, 0x78, 0x00, 0x92, 0x3F, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0A, 0x28,\n\t0x00, 0x0B, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x95, 0x30, 0x00, 0x00, 0x90, 0x3F,\n\t0x00, 0x00, 0x92, 0x3F, 0x00, 0x00, 0x90, 0x41, 0x78, 0x00, 0x92, 0x41, 0x6B, 0x00, 0x95, 0x31,\n\t0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28,\n\t0x00, 0x0A, 0x93, 0x3D, 0x6B, 0x00, 0x94, 0x38, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x90, 0x41,\n\t0x00, 0x00, 0x92, 0x41, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x95, 0x31, 0x00, 0x00, 0x93, 0x3D,\n\t0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x90, 0x46, 0x78, 0x00, 0x92, 0x46, 0x6B, 0x00, 0x93, 0x41,\n\t0x6B, 0x00, 0x94, 0x3D, 0x6B, 0x00, 0x95, 0x2E, 0x74, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28,\n\t0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28,\n\t0x58, 0x0B, 0x90, 0x46, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28,\n\t0x00, 0x0A, 0x93, 0x41, 0x00, 0x00, 0x94, 0x3D, 0x00, 0x00, 0x95, 0x2E, 0x00, 0x00, 0x90, 0x43,\n\t0x78, 0x00, 0x92, 0x43, 0x6B, 0x00, 0x93, 0x3F, 0x6B, 0x00, 0x94, 0x3D, 0x6B, 0x00, 0x95, 0x33,\n\t0x74, 0x00, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0B, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28,\n\t0x00, 0x0C, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28, 0x58, 0x0C, 0x90, 0x43, 0x00, 0x00, 0x92, 0x43,\n\t0x00, 0x00, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0C, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x3D,\n\t0x00, 0x00, 0x95, 0x33, 0x00, 0x00, 0x90, 0x44, 0x78, 0x00, 0x92, 0x44, 0x6B, 0x00, 0x93, 0x3F,\n\t0x6B, 0x00, 0x94, 0x3C, 0x6B, 0x00, 0x95, 0x2C, 0x74, 0x00, 0x9B, 0x24, 0x6B, 0x00, 0x9F, 0x28,\n\t0x58, 0x0C, 0x9B, 0x24, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0C, 0x9C, 0x26, 0x6B, 0x00, 0x9F, 0x28,\n\t0x58, 0x0C, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x9C, 0x26, 0x58, 0x00, 0x9F, 0x28,\n\t0x58, 0x0A, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0B, 0x9C, 0x26, 0x5F, 0x00, 0x9F, 0x28,\n\t0x58, 0x0B, 0x90, 0x44, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x3C,\n\t0x00, 0x00, 0x95, 0x2C, 0x00, 0x00, 0x9C, 0x26, 0x00, 0x00, 0x9F, 0x28, 0x00, 0x0A, 0x90, 0x4E,\n\t0x78, 0x00, 0xC1, 0x00, 0x00, 0x91, 0x46, 0x72, 0x00, 0xC2, 0x04, 0x00, 0x92, 0x42, 0x65, 0x00,\n\t0x93, 0x40, 0x72, 0x00, 0x94, 0x3A, 0x72, 0x00, 0x95, 0x2A, 0x7B, 0x00, 0x9B, 0x27, 0x6B, 0x00,\n\t0x9C, 0x29, 0x65, 0x00, 0x9F, 0x2B, 0x58, 0x0B, 0x9B, 0x27, 0x00, 0x00, 0x9C, 0x29, 0x00, 0x00,\n\t0x9F, 0x2B, 0x00, 0x0B, 0x90, 0x4E, 0x00, 0x00, 0x91, 0x46, 0x00, 0x00, 0x90, 0x50, 0x78, 0x00,\n\t0x91, 0x47, 0x72, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9F, 0x2B, 0x58, 0x0A, 0x90, 0x50, 0x00, 0x00,\n\t0x91, 0x47, 0x00, 0x00, 0x9C, 0x29, 0x00, 0x00, 0x9F, 0x2B, 0x00, 0x00, 0x90, 0x52, 0x78, 0x00,\n\t0x91, 0x49, 0x72, 0x00, 0x9C, 0x29, 0x6B, 0x0B, 0x92, 0x42, 0x00, 0x00, 0x93, 0x40, 0x00, 0x00,\n\t0x94, 0x3A, 0x00, 0x00, 0x95, 0x2A, 0x00, 0x00, 0x90, 0x52, 0x00, 0x00, 0x91, 0x49, 0x00, 0x00,\n\t0x9C, 0x29, 0x00, 0x00, 0x90, 0x53, 0x78, 0x00, 0x91, 0x4B, 0x72, 0x00, 0x92, 0x47, 0x65, 0x00,\n\t0x95, 0x23, 0x7B, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B,\n\t0x9B, 0x27, 0x00, 0x00, 0x9C, 0x29, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0A, 0x93, 0x3F, 0x72, 0x00,\n\t0x94, 0x3B, 0x72, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x2C, 0x00, 0x0B, 0x90, 0x53, 0x00, 0x00, 0x91,\n\t0x4B, 0x00, 0x00, 0x92, 0x47, 0x00, 0x00, 0x93, 0x3F, 0x00, 0x00, 0x94, 0x3B, 0x00, 0x00, 0x90,\n\t0x53, 0x78, 0x00, 0x91, 0x4B, 0x72, 0x00, 0x92, 0x47, 0x65, 0x00, 0x93, 0x3F, 0x72, 0x00, 0x94,\n\t0x36, 0x72, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0A, 0x9C, 0x29, 0x00, 0x00, 0x9E,\n\t0x2C, 0x00, 0x0B, 0x90, 0x53, 0x00, 0x00, 0x91, 0x4B, 0x00, 0x00, 0x92, 0x47, 0x00, 0x00, 0x90,\n\t0x55, 0x78, 0x00, 0x91, 0x4C, 0x72, 0x00, 0x92, 0x49, 0x65, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9E,\n\t0x2C, 0x4C, 0x0B, 0x9B, 0x27, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0A, 0x93, 0x3F, 0x00, 0x00, 0x94,\n\t0x36, 0x00, 0x00, 0x90, 0x55, 0x00, 0x00, 0x91, 0x4C, 0x00, 0x00, 0x92, 0x49, 0x00, 0x00, 0x90,\n\t0x53, 0x78, 0x00, 0x91, 0x4B, 0x72, 0x00, 0x92, 0x47, 0x65, 0x00, 0x93, 0x3F, 0x72, 0x00, 0x94,\n\t0x3B, 0x72, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9C, 0x29, 0x00, 0x00, 0x9E,\n\t0x2C, 0x00, 0x0B, 0x90, 0x53, 0x00, 0x00, 0x91, 0x4B, 0x00, 0x00, 0x92, 0x47, 0x00, 0x00, 0x90,\n\t0x52, 0x78, 0x00, 0x91, 0x49, 0x72, 0x00, 0x92, 0x46, 0x65, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9E,\n\t0x2C, 0x4C, 0x0A, 0x9B, 0x27, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0B, 0x95, 0x23, 0x00, 0x00, 0x93,\n\t0x3F, 0x00, 0x00, 0x94, 0x3B, 0x00, 0x00, 0x90, 0x52, 0x00, 0x00, 0x91, 0x49, 0x00, 0x00, 0x92,\n\t0x46, 0x00, 0x00, 0x90, 0x50, 0x78, 0x00, 0x91, 0x47, 0x72, 0x00, 0x92, 0x44, 0x65, 0x00, 0x95,\n\t0x28, 0x7B, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9B, 0x27, 0x00, 0x00, 0x9E,\n\t0x2C, 0x00, 0x0A, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9C, 0x29, 0x00, 0x00, 0x9E,\n\t0x2C, 0x00, 0x0B, 0x90, 0x50, 0x00, 0x00, 0x91, 0x47, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00, 0x90,\n\t0x50, 0x78, 0x00, 0x91, 0x47, 0x72, 0x00, 0x92, 0x44, 0x65, 0x00, 0x93, 0x40, 0x72, 0x00, 0x94,\n\t0x3B, 0x72, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0A, 0x9C, 0x29, 0x00, 0x00, 0x9E,\n\t0x2C, 0x00, 0x0B, 0x2C, 0x4C, 0x0B, 0x90, 0x50, 0x00, 0x00, 0x91, 0x47, 0x00, 0x00, 0x92, 0x44,\n\t0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0A, 0x95, 0x28, 0x00, 0x00, 0x93, 0x40, 0x00, 0x00, 0x94, 0x3B,\n\t0x00, 0x00, 0x90, 0x50, 0x78, 0x00, 0x91, 0x48, 0x72, 0x00, 0x92, 0x44, 0x65, 0x00, 0x93, 0x42,\n\t0x72, 0x00, 0x94, 0x3C, 0x72, 0x00, 0x95, 0x27, 0x7B, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9C, 0x29,\n\t0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9B, 0x27, 0x00, 0x00, 0x9C, 0x29, 0x00, 0x00, 0x9E, 0x2C,\n\t0x00, 0x0B, 0x2C, 0x4C, 0x0A, 0x2C, 0x00, 0x0B, 0x90, 0x50, 0x00, 0x00, 0x91, 0x48, 0x00, 0x00,\n\t0x92, 0x44, 0x00, 0x00, 0x93, 0x42, 0x00, 0x00, 0x94, 0x3C, 0x00, 0x00, 0x95, 0x27, 0x00, 0x00,\n\t0x90, 0x55, 0x78, 0x00, 0x91, 0x4D, 0x72, 0x00, 0x92, 0x49, 0x65, 0x00, 0x95, 0x25, 0x7B, 0x00,\n\t0x9B, 0x27, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9B, 0x27, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0A,\n\t0x93, 0x41, 0x72, 0x00, 0x94, 0x3D, 0x72, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x2C, 0x00, 0x0B, 0x90,\n\t0x55, 0x00, 0x00, 0x91, 0x4D, 0x00, 0x00, 0x92, 0x49, 0x00, 0x00, 0x93, 0x41, 0x00, 0x00, 0x94,\n\t0x3D, 0x00, 0x00, 0x90, 0x55, 0x78, 0x00, 0x91, 0x4D, 0x72, 0x00, 0x92, 0x49, 0x65, 0x00, 0x93,\n\t0x41, 0x72, 0x00, 0x94, 0x38, 0x72, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0A, 0x9C,\n\t0x29, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0B, 0x90, 0x55, 0x00, 0x00, 0x91, 0x4D, 0x00, 0x00, 0x92,\n\t0x49, 0x00, 0x00, 0x90, 0x57, 0x78, 0x00, 0x91, 0x4E, 0x72, 0x00, 0x92, 0x4B, 0x65, 0x00, 0x9B,\n\t0x27, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9B, 0x27, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0A, 0x93,\n\t0x41, 0x00, 0x00, 0x94, 0x38, 0x00, 0x00, 0x90, 0x57, 0x00, 0x00, 0x91, 0x4E, 0x00, 0x00, 0x92,\n\t0x4B, 0x00, 0x00, 0x90, 0x55, 0x78, 0x00, 0x91, 0x4D, 0x72, 0x00, 0x92, 0x49, 0x65, 0x00, 0x93,\n\t0x41, 0x72, 0x00, 0x94, 0x3D, 0x72, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9C,\n\t0x29, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0B, 0x90, 0x55, 0x00, 0x00, 0x91, 0x4D, 0x00, 0x00, 0x92,\n\t0x49, 0x00, 0x00, 0x90, 0x53, 0x78, 0x00, 0x91, 0x4B, 0x72, 0x00, 0x92, 0x47, 0x65, 0x00, 0x9B,\n\t0x27, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0A, 0x9B, 0x27, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0B, 0x95,\n\t0x25, 0x00, 0x00, 0x93, 0x41, 0x00, 0x00, 0x94, 0x3D, 0x00, 0x00, 0x90, 0x53, 0x00, 0x00, 0x91,\n\t0x4B, 0x00, 0x00, 0x92, 0x47, 0x00, 0x00, 0x90, 0x52, 0x78, 0x00, 0x91, 0x49, 0x72, 0x00, 0x92,\n\t0x46, 0x65, 0x00, 0x95, 0x2A, 0x7B, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9B,\n\t0x27, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0A, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9C,\n\t0x29, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0B, 0x90, 0x52, 0x00, 0x00, 0x91, 0x49, 0x00, 0x00, 0x92,\n\t0x46, 0x00, 0x00, 0x90, 0x4E, 0x78, 0x00, 0x91, 0x46, 0x72, 0x00, 0x92, 0x42, 0x65, 0x00, 0x93,\n\t0x42, 0x72, 0x00, 0x94, 0x3A, 0x72, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0A, 0x9C,\n\t0x29, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0B, 0x2C, 0x4C, 0x0B, 0x90, 0x4E, 0x00, 0x00, 0x91, 0x46,\n\t0x00, 0x00, 0x92, 0x42, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0A, 0x95, 0x2A, 0x00, 0x00, 0x93, 0x42,\n\t0x00, 0x00, 0x94, 0x3A, 0x00, 0x00, 0x90, 0x4E, 0x78, 0x00, 0x91, 0x46, 0x72, 0x00, 0x92, 0x42,\n\t0x65, 0x00, 0x93, 0x42, 0x72, 0x00, 0x94, 0x3A, 0x72, 0x00, 0x95, 0x28, 0x7B, 0x00, 0x9B, 0x27,\n\t0x6B, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9B, 0x27, 0x00, 0x00, 0x9C, 0x29,\n\t0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0B, 0x2C, 0x4C, 0x0A, 0x2C, 0x00, 0x0B, 0x90, 0x4E, 0x00, 0x00,\n\t0x91, 0x46, 0x00, 0x00, 0x92, 0x42, 0x00, 0x00, 0x93, 0x42, 0x00, 0x00, 0x94, 0x3A, 0x00, 0x00,\n\t0x95, 0x28, 0x00, 0x00, 0x90, 0x57, 0x78, 0x00, 0x91, 0x4F, 0x72, 0x00, 0x92, 0x4B, 0x65, 0x00,\n\t0x95, 0x27, 0x7B, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9B, 0x27, 0x00, 0x00,\n\t0x9E, 0x2C, 0x00, 0x0A, 0x93, 0x43, 0x72, 0x00, 0x94, 0x3A, 0x72, 0x00, 0x9E, 0x2C, 0x4C, 0x0B,\n\t0x2C, 0x00, 0x0B, 0x90, 0x57, 0x00, 0x00, 0x91, 0x4F, 0x00, 0x00, 0x92, 0x4B, 0x00, 0x00, 0x93,\n\t0x43, 0x00, 0x00, 0x94, 0x3A, 0x00, 0x00, 0x90, 0x57, 0x78, 0x00, 0x91, 0x4F, 0x72, 0x00, 0x92,\n\t0x4B, 0x65, 0x00, 0x93, 0x43, 0x72, 0x00, 0x94, 0x3A, 0x72, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E,\n\t0x2C, 0x4C, 0x0A, 0x9C, 0x29, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0B, 0x90, 0x57, 0x00, 0x00, 0x91,\n\t0x4F, 0x00, 0x00, 0x92, 0x4B, 0x00, 0x00, 0x90, 0x58, 0x78, 0x00, 0x91, 0x50, 0x72, 0x00, 0x92,\n\t0x4C, 0x65, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9B, 0x27, 0x00, 0x00, 0x9E,\n\t0x2C, 0x00, 0x0A, 0x93, 0x43, 0x00, 0x00, 0x94, 0x3A, 0x00, 0x00, 0x90, 0x58, 0x00, 0x00, 0x91,\n\t0x50, 0x00, 0x00, 0x92, 0x4C, 0x00, 0x00, 0x90, 0x57, 0x78, 0x00, 0x91, 0x4F, 0x72, 0x00, 0x92,\n\t0x4B, 0x65, 0x00, 0x93, 0x43, 0x72, 0x00, 0x94, 0x3F, 0x72, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E,\n\t0x2C, 0x4C, 0x0B, 0x9C, 0x29, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0B, 0x90, 0x57, 0x00, 0x00, 0x91,\n\t0x4F, 0x00, 0x00, 0x92, 0x4B, 0x00, 0x00, 0x90, 0x55, 0x78, 0x00, 0x91, 0x4C, 0x72, 0x00, 0x92,\n\t0x49, 0x65, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0A, 0x9B, 0x27, 0x00, 0x00, 0x9E,\n\t0x2C, 0x00, 0x0B, 0x95, 0x27, 0x00, 0x00, 0x93, 0x43, 0x00, 0x00, 0x94, 0x3F, 0x00, 0x00, 0x90,\n\t0x55, 0x00, 0x00, 0x91, 0x4C, 0x00, 0x00, 0x92, 0x49, 0x00, 0x00, 0x90, 0x53, 0x78, 0x00, 0x91,\n\t0x4B, 0x72, 0x00, 0x92, 0x47, 0x65, 0x00, 0x95, 0x2C, 0x7B, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9E,\n\t0x2C, 0x4C, 0x0B, 0x9B, 0x27, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0A, 0x93, 0x44, 0x72, 0x00, 0x94,\n\t0x3F, 0x72, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9C, 0x29, 0x00, 0x00, 0x9E,\n\t0x2C, 0x00, 0x0B, 0x90, 0x53, 0x00, 0x00, 0x91, 0x4B, 0x00, 0x00, 0x92, 0x47, 0x00, 0x00, 0x95,\n\t0x2C, 0x00, 0x00, 0x93, 0x44, 0x00, 0x00, 0x94, 0x3F, 0x00, 0x00, 0x90, 0x50, 0x78, 0x00, 0x91,\n\t0x4C, 0x72, 0x00, 0x92, 0x44, 0x65, 0x00, 0x93, 0x40, 0x72, 0x00, 0x94, 0x3D, 0x72, 0x00, 0x95,\n\t0x25, 0x7B, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0A, 0x9C, 0x29, 0x00, 0x00, 0x9E,\n\t0x2C, 0x00, 0x0B, 0x2C, 0x4C, 0x0B, 0x90, 0x50, 0x00, 0x00, 0x91, 0x4C, 0x00, 0x00, 0x92, 0x44,\n\t0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0A, 0x93, 0x40, 0x00, 0x00, 0x94, 0x3D, 0x00, 0x00, 0x95, 0x25,\n\t0x00, 0x00, 0x90, 0x4E, 0x78, 0x00, 0x91, 0x4B, 0x72, 0x00, 0x92, 0x42, 0x65, 0x00, 0x93, 0x42,\n\t0x72, 0x00, 0x94, 0x3B, 0x72, 0x00, 0x95, 0x27, 0x7B, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9C, 0x29,\n\t0x6B, 0x00, 0x9E, 0x2C, 0x4C, 0x0B, 0x9B, 0x27, 0x00, 0x00, 0x9C, 0x29, 0x00, 0x00, 0x9E, 0x2C,\n\t0x00, 0x0B, 0x90, 0x4E, 0x00, 0x00, 0x91, 0x4B, 0x00, 0x00, 0x92, 0x42, 0x00, 0x00, 0x90, 0x4E,\n\t0x78, 0x00, 0x91, 0x4B, 0x72, 0x00, 0x92, 0x42, 0x65, 0x00, 0x9E, 0x2C, 0x4C, 0x0A, 0x2C, 0x00,\n\t0x0B, 0x93, 0x42, 0x00, 0x00, 0x94, 0x3B, 0x00, 0x00, 0x95, 0x27, 0x00, 0x00, 0x90, 0x4E, 0x00,\n\t0x00, 0x91, 0x4B, 0x00, 0x00, 0x92, 0x42, 0x00, 0x00, 0x90, 0x50, 0x78, 0x00, 0x91, 0x47, 0x72,\n\t0x00, 0x92, 0x44, 0x65, 0x00, 0x95, 0x28, 0x7B, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9E, 0x2C, 0x4C,\n\t0x0C, 0x9B, 0x27, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0C, 0x93, 0x40, 0x72, 0x00, 0x94, 0x3B, 0x72,\n\t0x00, 0x9E, 0x2C, 0x4C, 0x0C, 0x90, 0x50, 0x00, 0x00, 0x91, 0x47, 0x00, 0x00, 0x92, 0x44, 0x00,\n\t0x00, 0x9E, 0x2C, 0x00, 0x0C, 0x95, 0x28, 0x00, 0x00, 0x93, 0x40, 0x00, 0x00, 0x94, 0x3B, 0x00,\n\t0x00, 0x90, 0x55, 0x78, 0x00, 0x91, 0x4C, 0x72, 0x00, 0x92, 0x49, 0x65, 0x00, 0x93, 0x44, 0x72,\n\t0x00, 0x94, 0x40, 0x72, 0x00, 0x95, 0x25, 0x7B, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C,\n\t0x0C, 0x9C, 0x29, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0C, 0x9B, 0x27, 0x6B, 0x00, 0x9E, 0x2C, 0x4C,\n\t0x0C, 0x90, 0x55, 0x00, 0x00, 0x91, 0x4C, 0x00, 0x00, 0x92, 0x49, 0x00, 0x00, 0x9B, 0x27, 0x00,\n\t0x00, 0x9E, 0x2C, 0x00, 0x0C, 0x93, 0x44, 0x00, 0x00, 0x94, 0x40, 0x00, 0x00, 0x95, 0x25, 0x00,\n\t0x00, 0x90, 0x52, 0x78, 0x00, 0x91, 0x49, 0x72, 0x00, 0x92, 0x46, 0x65, 0x00, 0x93, 0x42, 0x72,\n\t0x00, 0x94, 0x40, 0x72, 0x00, 0x95, 0x2A, 0x7B, 0x00, 0x9C, 0x29, 0x6B, 0x00, 0x9E, 0x2C, 0x4C,\n\t0x0C, 0x9C, 0x29, 0x00, 0x00, 0x9E, 0x2C, 0x00, 0x0E, 0x9B, 0x27, 0x6B, 0x00, 0x9E, 0x2C, 0x4C,\n\t0x0E, 0x90, 0x52, 0x00, 0x00, 0x91, 0x49, 0x00, 0x00, 0x92, 0x46, 0x00, 0x00, 0x9B, 0x27, 0x00,\n\t0x00, 0x9E, 0x2C, 0x00, 0x0E, 0x93, 0x42, 0x00, 0x00, 0x94, 0x40, 0x00, 0x00, 0x95, 0x2A, 0x00,\n\t0x00, 0x90, 0x53, 0x78, 0x00, 0x91, 0x4B, 0x72, 0x00, 0x92, 0x47, 0x65, 0x00, 0x93, 0x42, 0x72,\n\t0x00, 0x94, 0x3F, 0x72, 0x00, 0x95, 0x23, 0x7B, 0x00, 0x9B, 0x27, 0x6B, 0x00, 0x9C, 0x29, 0x6B,\n\t0x00, 0x9E, 0x2C, 0x4C, 0x00, 0x9F, 0x2B, 0x58, 0x0E, 0x9B, 0x27, 0x00, 0x00, 0x9C, 0x29, 0x00,\n\t0x00, 0x9E, 0x2C, 0x00, 0x00, 0x9F, 0x2B, 0x00, 0x52, 0x90, 0x53, 0x00, 0x00, 0x91, 0x4B, 0x00,\n\t0x00, 0x92, 0x47, 0x00, 0x00, 0x93, 0x42, 0x00, 0x00, 0x94, 0x3F, 0x00, 0x00, 0x95, 0x23, 0x00,\n\t0x00, 0xFF, 0x2F, 0x00, 0xFF};\n\n// lemmings_012_tim7.vgz - Lemmings: Ronda Alla Turca\nconst unsigned char TIM7_VGZ[0x065B] =\n{\t0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xED, 0x5B, 0xCD, 0x6F, 0x1B, 0x45,\n\t0x14, 0x7F, 0x6B, 0x77, 0x9D, 0x28, 0x87, 0xBA, 0xB2, 0x95, 0x9E, 0xDD, 0x18, 0x28, 0x0A, 0xD0,\n\t0xAC, 0x93, 0x12, 0x04, 0xA7, 0x36, 0x31, 0x02, 0x09, 0xAA, 0xF2, 0x51, 0x15, 0xE9, 0x69, 0x57,\n\t0xAA, 0x93, 0xB8, 0xAE, 0x45, 0xD2, 0x4A, 0xFD, 0xE0, 0xEB, 0x54, 0x28, 0x48, 0x48, 0xAC, 0x4F,\n\t0x9C, 0x7C, 0x41, 0xA4, 0xFD, 0x07, 0x9C, 0xCD, 0x25, 0x7B, 0x40, 0x6A, 0x81, 0x7B, 0xFE, 0x00,\n\t0x5F, 0x5A, 0x08, 0x12, 0x11, 0x17, 0x2E, 0xDC, 0x79, 0x33, 0xDE, 0xD9, 0xEC, 0xDA, 0xEB, 0xCD,\n\t0x8E, 0xD7, 0x9B, 0x38, 0x81, 0xB5, 0x62, 0xAF, 0x67, 0xF6, 0xCD, 0xBE, 0xDF, 0x7B, 0x33, 0xBF,\n\t0xDF, 0xCE, 0xB3, 0x72, 0xB5, 0xB6, 0x56, 0x58, 0x78, 0x15, 0xE0, 0x7D, 0x05, 0xDC, 0xE3, 0xD7,\n\t0x39, 0x80, 0xBF, 0xBF, 0x9F, 0x86, 0x35, 0xE8, 0x7C, 0x76, 0x1F, 0xEF, 0x42, 0xFF, 0xA3, 0xF9,\n\t0xC3, 0x3C, 0xC8, 0x1C, 0xA8, 0x14, 0xF0, 0xA7, 0xC7, 0x38, 0x0E, 0x78, 0x6D, 0x07, 0x97, 0xFF,\n\t0xC1, 0xFB, 0x19, 0x7C, 0x30, 0x86, 0x4F, 0x53, 0xF8, 0x3B, 0xE0, 0xE3, 0x2C, 0x16, 0x00, 0x8B,\n\t0x19, 0xBC, 0x00, 0xB8, 0x08, 0xD8, 0x3A, 0x89, 0x3F, 0xD6, 0xB0, 0x35, 0x85, 0x95, 0x5D, 0x5C,\n\t0xD9, 0xC5, 0x2F, 0x55, 0xFC, 0x5A, 0xC5, 0x67, 0x29, 0xDC, 0x49, 0xE1, 0x13, 0x05, 0xCF, 0x28,\n\t0xF8, 0x9C, 0x82, 0x17, 0x01, 0xCB, 0x80, 0x1B, 0x59, 0x5C, 0x6F, 0xE3, 0xC6, 0x39, 0x5C, 0xDA,\n\t0xC5, 0xEA, 0x2E, 0x7E, 0xA5, 0xE2, 0x37, 0x2A, 0xFE, 0x96, 0xC2, 0x3F, 0x52, 0xF8, 0xB3, 0x82,\n\t0x53, 0x0A, 0x3E, 0xAF, 0xE0, 0x02, 0xE0, 0x9B, 0x80, 0x56, 0x1A, 0x1F, 0xB6, 0xD1, 0x9A, 0xC5,\n\t0xCD, 0x4C, 0xC5, 0x98, 0xC4, 0x8D, 0x93, 0xB8, 0x6E, 0x31, 0x43, 0x2B, 0x87, 0x0F, 0x2D, 0x6A,\n\t0xAF, 0x68, 0x93, 0xD8, 0x4A, 0x39, 0xF7, 0x65, 0xBD, 0x35, 0xD1, 0x5B, 0x63, 0xBD, 0x7A, 0x90,\n\t0x49, 0x69, 0x12, 0xAF, 0xED, 0xE2, 0xF2, 0x2E, 0xDE, 0x57, 0xF1, 0x41, 0x0A, 0x9F, 0x2A, 0x1C,\n\t0x4B, 0x06, 0x0B, 0x0A, 0x16, 0x15, 0xBC, 0x30, 0x8E, 0x8B, 0xE3, 0x62, 0xCC, 0x17, 0xC4, 0x98,\n\t0xB3, 0xDC, 0x9C, 0x79, 0x52, 0xD9, 0x9A, 0xC6, 0x56, 0xA6, 0xD3, 0x5B, 0x69, 0x4C, 0x47, 0x08,\n\t0x4B, 0x46, 0xB8, 0x97, 0xC3, 0xF5, 0xF3, 0xB8, 0x31, 0xC3, 0x87, 0x3A, 0x8F, 0xD6, 0x1C, 0x73,\n\t0xDE, 0x0D, 0x85, 0x95, 0x77, 0xC6, 0x37, 0x64, 0xDD, 0xF3, 0xA3, 0x73, 0x20, 0xB7, 0x45, 0x63,\n\t0xDB, 0x81, 0x2C, 0x7C, 0xF6, 0x23, 0x6A, 0x32, 0x37, 0xCC, 0x38, 0x88, 0xB6, 0x39, 0x22, 0x72,\n\t0x7E, 0x9B, 0x0D, 0xA5, 0x77, 0x10, 0x35, 0x45, 0x23, 0x1F, 0x3F, 0x2A, 0xA2, 0x26, 0xB6, 0x8A,\n\t0xDC, 0xBC, 0x2A, 0xCC, 0xAB, 0x9E, 0x28, 0xF9, 0xC7, 0xA4, 0x1B, 0xB5, 0xD2, 0x02, 0x51, 0x96,\n\t0x07, 0x61, 0x96, 0xF7, 0x52, 0x10, 0xE6, 0x19, 0x5E, 0xE6, 0x5B, 0x07, 0xE6, 0x69, 0x3E, 0x19,\n\t0xE6, 0xB9, 0x89, 0x1B, 0x04, 0xEA, 0x2D, 0x8B, 0xDE, 0x32, 0xEB, 0x35, 0x82, 0x4C, 0xE8, 0xD6,\n\t0x72, 0xD1, 0xB0, 0x84, 0xB9, 0xE5, 0xDC, 0xB1, 0x77, 0x4C, 0xB9, 0xE9, 0xD7, 0xE3, 0xA7, 0xDE,\n\t0xC7, 0x4F, 0x1F, 0xB4, 0xB6, 0xE8, 0x6D, 0xB3, 0x5E, 0x3B, 0x4E, 0x7E, 0x7D, 0x37, 0x62, 0xCB,\n\t0x90, 0x66, 0x8B, 0x9C, 0xFF, 0x7E, 0x67, 0x28, 0xCE, 0xDD, 0x6E, 0x53, 0xDE, 0xCF, 0xF2, 0x2B,\n\t0x3B, 0x29, 0x16, 0xD1, 0x23, 0x57, 0x5B, 0x63, 0xA2, 0x37, 0xDB, 0x0D, 0x39, 0x12, 0x90, 0x31,\n\t0x0F, 0x90, 0xA2, 0x30, 0x2F, 0x32, 0xF3, 0xAD, 0x88, 0x28, 0x2C, 0x81, 0xA2, 0x27, 0x89, 0xDD,\n\t0xF3, 0x6A, 0x20, 0x14, 0x66, 0x3C, 0x14, 0x8D, 0xE9, 0xC8, 0x2B, 0xEB, 0x6C, 0x00, 0x8A, 0xEE,\n\t0x5C, 0x8C, 0xF5, 0x45, 0x61, 0x8F, 0x02, 0x0A, 0x37, 0x17, 0xEE, 0x2A, 0x53, 0x45, 0x84, 0xBD,\n\t0xF1, 0x77, 0x07, 0x77, 0xC9, 0xCD, 0xF1, 0x5C, 0x6E, 0xCE, 0xEC, 0xAF, 0x62, 0xB9, 0xC8, 0x2A,\n\t0x96, 0xDF, 0x47, 0xC5, 0xF4, 0x50, 0x15, 0xD3, 0x82, 0x4C, 0x8C, 0x78, 0x2A, 0x66, 0x0E, 0x4F,\n\t0xC5, 0xF4, 0x20, 0x15, 0x2B, 0x25, 0xA0, 0x62, 0x5A, 0xA8, 0x8A, 0xD9, 0xC3, 0x53, 0x31, 0x6D,\n\t0x34, 0x54, 0xCC, 0x88, 0x42, 0xF5, 0x11, 0xD4, 0xA1, 0x94, 0x80, 0x8A, 0x19, 0xF1, 0x54, 0x4C,\n\t0x8B, 0x22, 0xD0, 0x7E, 0xE1, 0x68, 0x1C, 0x4D, 0x15, 0xB3, 0x93, 0x54, 0x31, 0xF3, 0x58, 0xA8,\n\t0x98, 0x1D, 0x4F, 0xC5, 0xB4, 0x49, 0xDF, 0xB4, 0x0C, 0x51, 0xB1, 0xC6, 0x91, 0x55, 0xB1, 0xAD,\n\t0x44, 0x55, 0x8C, 0xC7, 0x21, 0x92, 0x8A, 0x65, 0xC8, 0x19, 0xB6, 0x7C, 0x24, 0x1E, 0x3C, 0x8A,\n\t0x1E, 0xB0, 0x79, 0x47, 0x32, 0x18, 0xD8, 0xB4, 0x67, 0x71, 0x65, 0x70, 0x63, 0x6E, 0x8F, 0x15,\n\t0x3D, 0xDA, 0x84, 0x1B, 0xF9, 0xEE, 0x5E, 0xB9, 0xB5, 0x9F, 0xE7, 0x6A, 0xD5, 0x31, 0x57, 0x05,\n\t0x9B, 0xB9, 0x63, 0x9E, 0x96, 0xE4, 0x76, 0xD7, 0x25, 0x3F, 0x1C, 0x1F, 0x9B, 0x39, 0x51, 0xEA,\n\t0x61, 0x33, 0x97, 0xF9, 0xB9, 0xA6, 0x0F, 0xCA, 0x66, 0x92, 0x91, 0xCF, 0x7A, 0x54, 0x52, 0x78,\n\t0xD5, 0x9B, 0x0E, 0x6D, 0x32, 0x2C, 0x1D, 0x76, 0x92, 0xE9, 0xD0, 0x82, 0xD2, 0xA1, 0xC7, 0x4B,\n\t0x47, 0x49, 0x2A, 0x1D, 0x56, 0x9C, 0x74, 0xB0, 0xB5, 0x10, 0x75, 0x2B, 0x91, 0x11, 0x19, 0x51,\n\t0x45, 0x46, 0x6A, 0xCE, 0x93, 0xD2, 0x9E, 0x3E, 0x7A, 0x1F, 0x08, 0x29, 0x23, 0xAA, 0x9F, 0xB7,\n\t0x45, 0x12, 0x1D, 0x6F, 0xBB, 0x7A, 0x05, 0x52, 0x73, 0x7A, 0x20, 0xB9, 0x17, 0xD1, 0x33, 0x82,\n\t0xA2, 0xA7, 0x45, 0xCC, 0x88, 0xEA, 0x97, 0xFB, 0xFC, 0xDE, 0xC3, 0x2A, 0x6B, 0xF4, 0x03, 0x77,\n\t0x74, 0xD3, 0x35, 0xD9, 0x16, 0x4F, 0x95, 0x65, 0x4F, 0x46, 0x58, 0x2F, 0x8F, 0xF0, 0xD0, 0x17,\n\t0x48, 0x9F, 0x74, 0x68, 0x41, 0xE9, 0x30, 0x42, 0xD3, 0x61, 0x86, 0xA6, 0xA3, 0x31, 0x7A, 0xE9,\n\t0xD0, 0x83, 0xD2, 0x61, 0x84, 0xA6, 0xC3, 0x83, 0x51, 0x0E, 0xD1, 0x30, 0x8B, 0x81, 0xB9, 0xBD,\n\t0x6D, 0x54, 0xBF, 0xCA, 0x9E, 0x6C, 0x31, 0x50, 0x8B, 0xB7, 0x8D, 0xF2, 0xF2, 0x86, 0x3D, 0x7A,\n\t0xC5, 0x40, 0x2D, 0x68, 0x1B, 0xA5, 0x87, 0x6E, 0xA3, 0x1A, 0x09, 0x17, 0x03, 0xB5, 0x78, 0xDB,\n\t0x28, 0xE3, 0x40, 0x8A, 0x81, 0x5A, 0xBF, 0x2D, 0xCF, 0xB0, 0xB7, 0x51, 0x5A, 0xBC, 0x6D, 0x94,\n\t0x21, 0x5F, 0x0C, 0x8C, 0x35, 0x63, 0x87, 0xBD, 0x8D, 0x3A, 0x62, 0x65, 0xB4, 0x3E, 0xDB, 0x28,\n\t0xBD, 0x6B, 0x03, 0x72, 0x34, 0x8B, 0x81, 0x5E, 0x14, 0xA5, 0xD0, 0x6D, 0x94, 0x19, 0x8A, 0xC2,\n\t0xFE, 0xBF, 0x18, 0x18, 0xB9, 0x18, 0x38, 0x2C, 0x15, 0xD3, 0x87, 0xA7, 0x62, 0xC7, 0xA3, 0x18,\n\t0x18, 0x8B, 0xE5, 0x22, 0x14, 0x03, 0xF5, 0x78, 0x2A, 0x56, 0x3A, 0x5E, 0xC5, 0xC0, 0x24, 0x54,\n\t0x2C, 0x7A, 0x31, 0xD0, 0x8C, 0xAD, 0x62, 0x8D, 0xD1, 0xF8, 0x49, 0x6B, 0xEB, 0x50, 0x55, 0x4C,\n\t0x8B, 0xAC, 0x62, 0x66, 0x92, 0x25, 0xCD, 0x21, 0xAA, 0x98, 0x11, 0x43, 0xC5, 0x1A, 0x87, 0xAA,\n\t0x62, 0x66, 0xA8, 0x8A, 0x79, 0x66, 0x91, 0x9C, 0xDA, 0x8E, 0x66, 0x31, 0xD0, 0x0C, 0x2D, 0x06,\n\t0x36, 0x0E, 0xBC, 0x18, 0xA8, 0xC5, 0xAB, 0x3E, 0x19, 0x07, 0x58, 0x0C, 0x34, 0xE3, 0x15, 0x03,\n\t0x0D, 0xF9, 0x62, 0x60, 0x78, 0x3A, 0xEC, 0x63, 0x57, 0x0C, 0x34, 0x25, 0x8B, 0x81, 0x31, 0xAB,\n\t0x4F, 0xBA, 0x7C, 0xF5, 0x29, 0xD1, 0x62, 0x60, 0xBF, 0xE8, 0x0D, 0xBD, 0xFA, 0x54, 0x8A, 0x5C,\n\t0x7D, 0xB2, 0xFF, 0xC3, 0xC5, 0x40, 0x3D, 0x28, 0x1D, 0xA5, 0x04, 0xD2, 0xA1, 0x47, 0xAE, 0xCD,\n\t0xCA, 0x21, 0xCA, 0xB2, 0x41, 0x24, 0x25, 0xC3, 0x27, 0x10, 0x95, 0x3A, 0xAE, 0xD4, 0xB9, 0x84,\n\t0x9D, 0xC0, 0x67, 0x69, 0xDC, 0x49, 0xE3, 0x93, 0x09, 0x3C, 0x03, 0x5C, 0xC2, 0x4E, 0x61, 0x79,\n\t0x7C, 0x8F, 0xE5, 0x22, 0x95, 0x13, 0x89, 0x61, 0x66, 0xF0, 0x46, 0x1D, 0x3F, 0xAE, 0xE3, 0xB7,\n\t0x2A, 0x7E, 0x77, 0x02, 0xFF, 0x4C, 0xE3, 0x5F, 0x69, 0xFC, 0x65, 0x02, 0x5F, 0x04, 0x7C, 0x49,\n\t0xC1, 0xB7, 0x4F, 0xE1, 0x3B, 0xE3, 0xE4, 0x30, 0x3E, 0x6A, 0xE2, 0x26, 0x27, 0x4C, 0x2B, 0xCB,\n\t0x73, 0x31, 0xE3, 0x7B, 0xF6, 0x66, 0x8D, 0x19, 0xD6, 0xA8, 0x7B, 0x2E, 0x90, 0xAA, 0x17, 0x31,\n\t0x2B, 0xE6, 0x8C, 0x7C, 0x45, 0xA5, 0x33, 0x19, 0x1C, 0x73, 0xDC, 0xCC, 0x3B, 0xAE, 0x96, 0x3C,\n\t0x9E, 0xE8, 0x41, 0xAE, 0x6A, 0x7E, 0x57, 0x7D, 0x17, 0x70, 0x4F, 0x64, 0x95, 0x48, 0x6C, 0x5A,\n\t0xE5, 0x1F, 0xA7, 0x39, 0x04, 0xD7, 0x73, 0x7B, 0x40, 0xFA, 0x8D, 0x7B, 0xDF, 0x2E, 0x15, 0x1E,\n\t0x4C, 0x02, 0x9C, 0xF0, 0x76, 0x50, 0x88, 0x5D, 0xBC, 0x57, 0x59, 0xE4, 0x96, 0x6A, 0x53, 0xAC,\n\t0x3B, 0x95, 0x57, 0x0C, 0xC8, 0x55, 0x0B, 0x37, 0x39, 0x2F, 0x05, 0x2E, 0x55, 0x71, 0x25, 0x9F,\n\t0xA8, 0x1E, 0x12, 0x93, 0xF0, 0xDF, 0x23, 0x2B, 0xD1, 0x5D, 0x75, 0x14, 0x9C, 0x3B, 0x13, 0x4C,\n\t0xE9, 0x5E, 0x6A, 0xED, 0x60, 0xC9, 0xE1, 0xA3, 0x0C, 0x0B, 0xBB, 0x1E, 0x82, 0x65, 0x30, 0xCE,\n\t0xE4, 0x41, 0x73, 0x63, 0x35, 0x98, 0x04, 0xB8, 0xEE, 0x39, 0xE4, 0xA3, 0x7A, 0x66, 0x85, 0x3A,\n\t0x50, 0x9D, 0x44, 0x15, 0xAC, 0xEB, 0xA6, 0x32, 0xE3, 0xCC, 0x76, 0x89, 0x38, 0x3B, 0x94, 0x25,\n\t0x16, 0xAF, 0xDA, 0x15, 0xB4, 0x58, 0x1E, 0x32, 0x66, 0xCE, 0x4B, 0x3D, 0x52, 0xFA, 0x7E, 0xC7,\n\t0xDF, 0x9F, 0x99, 0x73, 0x09, 0x30, 0x73, 0x3E, 0x80, 0x99, 0xA3, 0xD0, 0xDD, 0x21, 0x32, 0xB3,\n\t0x94, 0x88, 0x94, 0x82, 0x98, 0x59, 0x8A, 0x15, 0xED, 0xE1, 0x31, 0x73, 0x63, 0x04, 0x98, 0xD9,\n\t0x8E, 0xCD, 0xCC, 0x8D, 0x24, 0x99, 0x59, 0x9F, 0x0C, 0xFE, 0x81, 0x7B, 0x88, 0xCC, 0x6C, 0x0F,\n\t0xC4, 0xCC, 0x5E, 0xC9, 0x30, 0xA2, 0x31, 0xB3, 0x76, 0x74, 0x98, 0xD9, 0x4E, 0x80, 0x99, 0x1B,\n\t0x03, 0x31, 0xB3, 0xEE, 0x61, 0x66, 0xAD, 0x2F, 0x33, 0x5F, 0x7F, 0x6B, 0x65, 0xAE, 0x00, 0x0A,\n\t0xC0, 0x12, 0xFD, 0x5D, 0x81, 0x3A, 0xAC, 0x41, 0x01, 0x5E, 0x83, 0x37, 0xE8, 0xFD, 0x03, 0xB8,\n\t0x05, 0x37, 0x61, 0x05, 0x2A, 0x74, 0x7E, 0x11, 0x56, 0xE9, 0xC5, 0xCE, 0xAE, 0xC0, 0x3D, 0xB8,\n\t0x0D, 0xCB, 0x74, 0xDE, 0xF9, 0x0F, 0x9F, 0x2A, 0x59, 0xAC, 0x91, 0xDD, 0x4D, 0xA8, 0xC1, 0x1D,\n\t0xDE, 0xF6, 0x1E, 0x2C, 0xD2, 0x75, 0x33, 0xF4, 0x77, 0x09, 0x3E, 0x84, 0x57, 0xA0, 0x0C, 0x97,\n\t0xE9, 0x93, 0x1D, 0x97, 0x68, 0xC4, 0x2F, 0xC8, 0xF2, 0x36, 0xDC, 0xE5, 0xDF, 0x4B, 0xF0, 0x3A,\n\t0xBD, 0x4A, 0x74, 0x76, 0x95, 0x5A, 0xD9, 0x1D, 0xAA, 0xF0, 0x39, 0xD9, 0x2D, 0xD0, 0x27, 0xFB,\n\t0x06, 0x34, 0x12, 0xF3, 0xE1, 0x13, 0xFA, 0xCE, 0x6C, 0xAA, 0xE4, 0x4D, 0x01, 0xAE, 0xD3, 0xF9,\n\t0x2D, 0xEE, 0x27, 0xF3, 0xA7, 0x4C, 0x7E, 0x5E, 0xE6, 0xAD, 0x75, 0x6E, 0xFF, 0x32, 0x9D, 0xAF,\n\t0x52, 0x7F, 0x8D, 0x5E, 0x9D, 0xEB, 0x3F, 0xA5, 0x9E, 0xBB, 0x70, 0x83, 0x5F, 0x7B, 0x8B, 0x7C,\n\t0x5C, 0xA0, 0xF7, 0xCF, 0xE0, 0x1C, 0x4C, 0xD0, 0x6B, 0x81, 0xC6, 0xB8, 0xE3, 0x5C, 0xC7, 0xEE,\n\t0x54, 0x80, 0xA9, 0x7D, 0x71, 0x4F, 0xD1, 0xB7, 0x25, 0xEE, 0xE7, 0x47, 0x74, 0xE5, 0x2A, 0xDD,\n\t0xB9, 0x46, 0xAD, 0x0C, 0x3F, 0xBB, 0x7E, 0x8D, 0xCE, 0x57, 0x68, 0xC4, 0x7B, 0x34, 0x6E, 0xA1,\n\t0x07, 0xF1, 0xBF, 0x46, 0x65, 0x12, 0x63, 0x46, 0x35, 0x00, 0x00};\n\n// lem_xmas_001_jb.dro - Xmas Lemmings: Jingle Bells\nconst unsigned char JB_DRO[0x3100] =\n{\t0x44, 0x42, 0x52, 0x41, 0x57, 0x4F, 0x50, 0x4C, 0x02, 0x00, 0x00, 0x00, 0x36, 0x18, 0x00, 0x00,\n\t0xC3, 0xAB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x7B, 0x7A, 0x01, 0x04, 0x05, 0x08, 0xBD, 0x20,\n\t0x40, 0x60, 0x80, 0xE0, 0x21, 0x41, 0x61, 0x81, 0xE1, 0x22, 0x42, 0x62, 0x82, 0xE2, 0x23, 0x43,\n\t0x63, 0x83, 0xE3, 0x24, 0x44, 0x64, 0x84, 0xE4, 0x25, 0x45, 0x65, 0x85, 0xE5, 0x28, 0x48, 0x68,\n\t0x88, 0xE8, 0x29, 0x49, 0x69, 0x89, 0xE9, 0x2A, 0x4A, 0x6A, 0x8A, 0xEA, 0x2B, 0x4B, 0x6B, 0x8B,\n\t0xEB, 0x2C, 0x4C, 0x6C, 0x8C, 0xEC, 0x2D, 0x4D, 0x6D, 0x8D, 0xED, 0x30, 0x50, 0x70, 0x90, 0xF0,\n\t0x31, 0x51, 0x71, 0x91, 0xF1, 0x32, 0x52, 0x72, 0x92, 0xF2, 0x33, 0x53, 0x73, 0x93, 0xF3, 0x34,\n\t0x54, 0x74, 0x94, 0xF4, 0x35, 0x55, 0x75, 0x95, 0xF5, 0xA0, 0xB0, 0xC0, 0xA1, 0xB1, 0xC1, 0xA2,\n\t0xB2, 0xC2, 0xA3, 0xB3, 0xC3, 0xA4, 0xB4, 0xC4, 0xA5, 0xB5, 0xC5, 0xA6, 0xB6, 0xC6, 0xA7, 0xB7,\n\t0xC7, 0xA8, 0xB8, 0xC8, 0x4B, 0x02, 0x5A, 0x03, 0x4D, 0x99, 0x5C, 0x59, 0x4E, 0x06, 0x5D, 0x07,\n\t0x77, 0x23, 0x79, 0x0B, 0x4F, 0x01, 0x5E, 0x02, 0x78, 0x32, 0x77, 0x44, 0x7A, 0x0C, 0x77, 0x67,\n\t0x7A, 0x0C, 0x77, 0x8B, 0x7A, 0x0D, 0x77, 0xB2, 0x7A, 0x0D, 0x77, 0xDB, 0x7A, 0x0D, 0x78, 0x12,\n\t0x7A, 0xA3, 0x77, 0x65, 0x7A, 0x00, 0x78, 0x2F, 0x7A, 0x0C, 0x77, 0x99, 0x7A, 0x0D, 0x77, 0xCF,\n\t0x7A, 0x0D, 0x77, 0x05, 0x78, 0x32, 0x7A, 0x0C, 0x77, 0x23, 0x7A, 0x0D, 0x77, 0x44, 0x7A, 0x0D,\n\t0x78, 0x12, 0x77, 0xCF, 0x78, 0x2F, 0x7A, 0x0D, 0x77, 0x99, 0x7A, 0x0C, 0x77, 0x65, 0x7A, 0x0D,\n\t0x77, 0x34, 0x7A, 0x0D, 0x77, 0x06, 0x7A, 0x0C, 0x77, 0xDB, 0x7A, 0x00, 0x78, 0x2E, 0x7A, 0x1A,\n\t0x77, 0xB2, 0x7A, 0x0D, 0x77, 0x8B, 0x7A, 0x0C, 0x77, 0x67, 0x7A, 0x0D, 0x77, 0x44, 0x7A, 0x0D,\n\t0x77, 0x23, 0x7A, 0x0D, 0x78, 0x0E, 0x7B, 0x02, 0x7A, 0x7B, 0x5C, 0x89, 0x4E, 0x36, 0x5D, 0x47,\n\t0x4F, 0x03, 0x5E, 0x00, 0x79, 0x00, 0x4B, 0x22, 0x5A, 0x21, 0x7A, 0x00, 0x77, 0xB2, 0x78, 0x22,\n\t0x7A, 0x6C, 0x77, 0xDB, 0x7A, 0x0D, 0x77, 0x06, 0x78, 0x23, 0x7A, 0x0C, 0x77, 0x34, 0x7A, 0x0D,\n\t0x77, 0x65, 0x7A, 0x0D, 0x77, 0x99, 0x7A, 0x0D, 0x77, 0xCF, 0x7A, 0x0C, 0x77, 0x05, 0x78, 0x26,\n\t0x7A, 0x1B, 0x77, 0x23, 0x7A, 0x0D, 0x77, 0x44, 0x7A, 0x0C, 0x77, 0x67, 0x7A, 0x0D, 0x77, 0x8B,\n\t0x7A, 0x0D, 0x77, 0xB2, 0x7A, 0x0C, 0x77, 0xDB, 0x7A, 0x0D, 0x77, 0x06, 0x78, 0x27, 0x7A, 0x0D,\n\t0x78, 0x07, 0x7B, 0x03, 0x7A, 0x13, 0x00, 0x20, 0x04, 0xC0, 0x07, 0xF2, 0x16, 0xF2, 0x08, 0xF2,\n\t0x17, 0xF2, 0x61, 0x08, 0x05, 0x27, 0x14, 0x32, 0x7A, 0x00, 0x06, 0x4F, 0x15, 0x08, 0x5F, 0x65,\n\t0x60, 0x33, 0x0C, 0x53, 0x1B, 0xAA, 0x0D, 0x5A, 0x1C, 0x1A, 0x64, 0x0C, 0x0A, 0x21, 0x19, 0x21,\n\t0x0B, 0x97, 0x1A, 0x80, 0x11, 0x53, 0x20, 0xAA, 0x12, 0x5A, 0x21, 0x1A, 0x67, 0x0C, 0x7A, 0x00,\n\t0x0F, 0x21, 0x1E, 0x21, 0x10, 0x97, 0x1F, 0x80, 0x25, 0x53, 0x34, 0xAA, 0x26, 0x5A, 0x35, 0x1A,\n\t0x6A, 0x0C, 0x23, 0x21, 0x32, 0x21, 0x24, 0x97, 0x33, 0x80, 0x68, 0xB2, 0x69, 0x2A, 0x2A, 0xE2,\n\t0x39, 0xE3, 0x2B, 0xF3, 0x7A, 0x00, 0x3A, 0xF3, 0x2C, 0x02, 0x6D, 0x0E, 0x28, 0x26, 0x37, 0x32,\n\t0x29, 0x42, 0x38, 0x0E, 0x6B, 0xB2, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x45, 0x60, 0x13, 0x60, 0x33,\n\t0x62, 0x05, 0x63, 0x2E, 0x65, 0xB2, 0x66, 0x2E, 0x69, 0x0A, 0x7A, 0x00, 0x68, 0x65, 0x69, 0x2F,\n\t0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0x6C, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x7A, 0xDB,\n\t0x60, 0x13, 0x60, 0x33, 0x63, 0x2E, 0x66, 0x2E, 0x69, 0x2F, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49,\n\t0x60, 0x33, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x68, 0xB2, 0x69, 0x2A, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13, 0x60, 0x33, 0x7A, 0x00, 0x63, 0x2E, 0x66, 0x2E, 0x69, 0x0A,\n\t0x68, 0x65, 0x69, 0x2F, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0x6C, 0x63, 0x0E, 0x66, 0x0E,\n\t0x69, 0x0F, 0x7A, 0xDB, 0x60, 0x13, 0x60, 0x33, 0x63, 0x2E, 0x66, 0x2E, 0x69, 0x2F, 0x7A, 0x00,\n\t0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x6C, 0x16, 0x7A, 0x00,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x33, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x68, 0xB2,\n\t0x69, 0x2A, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x60, 0x13, 0x5F, 0x05, 0x60, 0x36,\n\t0x63, 0x2E, 0x66, 0x2E, 0x69, 0x0A, 0x68, 0x65, 0x69, 0x2F, 0x38, 0x16, 0x7A, 0x00, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xD9, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x7A, 0x6D, 0x60, 0x16, 0x5F, 0xB2,\n\t0x60, 0x32, 0x68, 0xB2, 0x69, 0x2A, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x63, 0x2E, 0x66, 0x2E, 0x69, 0x0A, 0x68, 0x65, 0x69, 0x2F, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x60, 0x12, 0x5F, 0x06, 0x60, 0x33, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x65, 0x60, 0x33,\n\t0x63, 0x0E, 0x62, 0xB2, 0x63, 0x2A, 0x66, 0x0E, 0x69, 0x0F, 0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x63, 0x0A, 0x63, 0x2E, 0x65, 0x05, 0x66, 0x2E, 0x69, 0x2F, 0x7A, 0x00,\n\t0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0x6C, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x7A, 0xDA,\n\t0x63, 0x2E, 0x66, 0x2E, 0x7A, 0x00, 0x69, 0x2F, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13, 0x5F, 0x99, 0x60, 0x33,\n\t0x7A, 0x00, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x68, 0x99, 0x69, 0x2B, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13, 0x60, 0x33, 0x62, 0x44, 0x63, 0x2E, 0x65, 0xB2, 0x66, 0x2E,\n\t0x69, 0x0B, 0x69, 0x2F, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x0E,\n\t0x66, 0x0E, 0x69, 0x0F, 0x7A, 0xA3, 0x60, 0x13, 0x7A, 0x00, 0x60, 0x33, 0x69, 0x2B, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xDA, 0x69, 0x0B, 0x7A, 0x6D, 0x60, 0x13, 0x63, 0x2E, 0x66, 0x2E,\n\t0x69, 0x2F, 0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x33, 0x7A, 0x36, 0x63, 0x0E,\n\t0x66, 0x0E, 0x7A, 0x6D, 0x60, 0x13, 0x60, 0x33, 0x62, 0x65, 0x63, 0x2B, 0x69, 0x0F, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13, 0x5F, 0x65, 0x60, 0x33, 0x63, 0x0B, 0x62, 0xB2,\n\t0x63, 0x2E, 0x65, 0x05, 0x66, 0x2E, 0x7A, 0x00, 0x68, 0x65, 0x69, 0x2F, 0x38, 0x16, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33,\n\t0x69, 0x2B, 0x38, 0x0E, 0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13,\n\t0x60, 0x33, 0x62, 0x05, 0x63, 0x2E, 0x7A, 0x00, 0x65, 0xB2, 0x66, 0x2E, 0x69, 0x0B, 0x69, 0x2F,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x13, 0x60, 0x33, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F,\n\t0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x68, 0x06, 0x69, 0x2B, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x60, 0x13, 0x5F, 0x06, 0x60, 0x33, 0x7A, 0x00, 0x62, 0xCF, 0x63, 0x2B, 0x65, 0x44,\n\t0x66, 0x2E, 0x69, 0x0B, 0x69, 0x2F, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xDA, 0x63, 0x0B,\n\t0x66, 0x0E, 0x69, 0x0F, 0x7A, 0x6D, 0x60, 0x13, 0x60, 0x33, 0x69, 0x2B, 0x7A, 0x00, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x5F, 0x65, 0x7A, 0x00, 0x60, 0x33,\n\t0x63, 0x2B, 0x66, 0x2E, 0x69, 0x0B, 0x69, 0x2F, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xDA, 0x63, 0x0B,\n\t0x66, 0x0E, 0x69, 0x0F, 0x7A, 0x6D, 0x60, 0x13, 0x5F, 0x06, 0x60, 0x33, 0x68, 0x05, 0x69, 0x2A,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x60, 0x13, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x5F, 0x05, 0x60, 0x36, 0x62, 0x05, 0x63, 0x2E, 0x65, 0x8B, 0x66, 0x2E,\n\t0x7A, 0x00, 0x69, 0x0A, 0x68, 0x06, 0x69, 0x2F, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x16, 0x5F, 0x65, 0x60, 0x33,\n\t0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x68, 0xB2, 0x7A, 0x00, 0x69, 0x2A, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13, 0x60, 0x33, 0x63, 0x2E, 0x65, 0xB2, 0x66, 0x2E, 0x69, 0x0A,\n\t0x68, 0x65, 0x69, 0x2F, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0x6C, 0x63, 0x0E,\n\t0x66, 0x0E, 0x69, 0x0F, 0x7A, 0xDA, 0x60, 0x13, 0x60, 0x33, 0x7A, 0x00, 0x63, 0x2E, 0x66, 0x2E,\n\t0x69, 0x2F, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x60, 0x33, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x68, 0xB2,\n\t0x69, 0x2A, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13, 0x60, 0x33, 0x63, 0x2E,\n\t0x66, 0x2E, 0x69, 0x0A, 0x68, 0x65, 0x69, 0x2F, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0x6C, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x7A, 0xDB, 0x60, 0x13, 0x60, 0x33, 0x63, 0x2E,\n\t0x66, 0x2E, 0x69, 0x2F, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47,\n\t0x60, 0x13, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x60, 0x33, 0x63, 0x0E, 0x66, 0x0E,\n\t0x69, 0x0F, 0x68, 0xB2, 0x69, 0x2A, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13,\n\t0x5F, 0x05, 0x60, 0x36, 0x63, 0x2E, 0x7A, 0x00, 0x66, 0x2E, 0x69, 0x0A, 0x68, 0x65, 0x69, 0x2F,\n\t0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xDA, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x7A, 0x6D,\n\t0x60, 0x16, 0x5F, 0xB2, 0x60, 0x32, 0x68, 0xB2, 0x69, 0x2A, 0x38, 0x0E, 0x6C, 0x16, 0x7A, 0x00,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x2E, 0x7A, 0x00, 0x66, 0x2E, 0x69, 0x0A, 0x68, 0x65,\n\t0x69, 0x2F, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x12, 0x5F, 0x06, 0x60, 0x33, 0x7A, 0xA4,\n\t0x60, 0x13, 0x5F, 0x65, 0x60, 0x33, 0x63, 0x0E, 0x62, 0xB2, 0x63, 0x2A, 0x66, 0x0E, 0x69, 0x0F,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x63, 0x0A, 0x63, 0x2E, 0x7A, 0x00, 0x65, 0x05,\n\t0x66, 0x2E, 0x69, 0x2F, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0x6C, 0x63, 0x0E, 0x66, 0x0E,\n\t0x69, 0x0F, 0x7A, 0xDB, 0x63, 0x2E, 0x66, 0x2E, 0x69, 0x2F, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13,\n\t0x5F, 0x99, 0x60, 0x33, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x68, 0x99, 0x69, 0x2B, 0x6C, 0x16,\n\t0x7A, 0x00, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13, 0x60, 0x33, 0x62, 0x44, 0x63, 0x2E,\n\t0x65, 0xB2, 0x66, 0x2E, 0x69, 0x0B, 0x69, 0x2F, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA2, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x69, 0x2B,\n\t0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xDA, 0x69, 0x0B, 0x7A, 0x6D, 0x60, 0x13,\n\t0x63, 0x2E, 0x66, 0x2E, 0x69, 0x2F, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA4, 0x60, 0x33, 0x7A, 0x35,\n\t0x63, 0x0E, 0x66, 0x0E, 0x7A, 0x6D, 0x60, 0x13, 0x60, 0x33, 0x62, 0x65, 0x63, 0x2B, 0x7A, 0x00,\n\t0x69, 0x0F, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13, 0x5F, 0x65, 0x60, 0x33,\n\t0x63, 0x0B, 0x62, 0xB2, 0x63, 0x2E, 0x65, 0x05, 0x66, 0x2E, 0x68, 0x65, 0x69, 0x2F, 0x7A, 0x00,\n\t0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x7A, 0xA3,\n\t0x60, 0x13, 0x60, 0x33, 0x7A, 0x00, 0x69, 0x2B, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x60, 0x13, 0x60, 0x33, 0x62, 0x05, 0x63, 0x2E, 0x65, 0xB2, 0x66, 0x2E, 0x69, 0x0B,\n\t0x69, 0x2F, 0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x13, 0x5F, 0x99, 0x60, 0x33,\n\t0x63, 0x0E, 0x66, 0x0E, 0x69, 0x0F, 0x7A, 0xA3, 0x60, 0x13, 0x7A, 0x00, 0x5F, 0x05, 0x60, 0x36,\n\t0x63, 0x2A, 0x65, 0x05, 0x66, 0x2E, 0x68, 0x05, 0x69, 0x32, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x63, 0x0A, 0x66, 0x0E, 0x69, 0x12, 0x7A, 0xA4, 0x60, 0x16, 0x60, 0x36, 0x63, 0x2A, 0x66, 0x2E,\n\t0x69, 0x32, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x0A, 0x66, 0x0E,\n\t0x69, 0x12, 0x7A, 0xA4, 0x60, 0x16, 0x5F, 0x99, 0x60, 0x33, 0x62, 0x99, 0x63, 0x27, 0x65, 0x99,\n\t0x66, 0x2B, 0x68, 0x99, 0x69, 0x2F, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2,\n\t0x63, 0x07, 0x66, 0x0B, 0x69, 0x0F, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x06, 0x60, 0x33, 0x62, 0x06,\n\t0x63, 0x27, 0x65, 0x06, 0x66, 0x2B, 0x7A, 0x00, 0x68, 0x06, 0x69, 0x2F, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x07, 0x66, 0x0B, 0x69, 0x0F, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0xB2, 0x60, 0x32,\n\t0x62, 0xB2, 0x63, 0x26, 0x65, 0xB2, 0x66, 0x2A, 0x68, 0xB2, 0x69, 0x2E, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x49, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x63, 0x06,\n\t0x66, 0x0A, 0x69, 0x0E, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x07, 0x55, 0x16, 0x43, 0x08, 0x75, 0x17, 0x65, 0x09, 0x01,\n\t0x18, 0x01, 0x61, 0x0B, 0x05, 0x22, 0x14, 0x22, 0x06, 0x00, 0x15, 0x00, 0x60, 0x12, 0x5F, 0x05,\n\t0x60, 0x2A, 0x7A, 0x00, 0x0C, 0x52, 0x1B, 0x32, 0x0D, 0x18, 0x1C, 0x18, 0x64, 0x09, 0x0A, 0x64,\n\t0x19, 0x24, 0x0B, 0x0A, 0x1A, 0x0A, 0x62, 0x05, 0x63, 0x2A, 0x11, 0x52, 0x20, 0x32, 0x12, 0x18,\n\t0x21, 0x18, 0x67, 0x09, 0x0F, 0x64, 0x1E, 0x24, 0x7A, 0x00, 0x10, 0x0A, 0x1F, 0x0A, 0x66, 0x2A,\n\t0x25, 0x52, 0x34, 0x32, 0x26, 0x18, 0x35, 0x18, 0x6A, 0x09, 0x23, 0x64, 0x32, 0x24, 0x24, 0x0A,\n\t0x33, 0x0A, 0x68, 0x65, 0x69, 0x2B, 0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x45,\n\t0x60, 0x0A, 0x5F, 0x65, 0x7A, 0x00, 0x60, 0x2B, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x60, 0x0B, 0x5F, 0xB2, 0x60, 0x2A, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x60, 0x0A, 0x5F, 0x05, 0x60, 0x2A, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49,\n\t0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x60, 0x0A, 0x7A, 0xA4, 0x5F, 0x65, 0x60, 0x27, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA4,\n\t0x60, 0x07, 0x5F, 0x99, 0x60, 0x27, 0x7A, 0xA3, 0x60, 0x07, 0x5F, 0x05, 0x60, 0x2A, 0x6C, 0x16,\n\t0x7A, 0x00, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x0A, 0x5F, 0x65, 0x60, 0x2B, 0x38, 0x16,\n\t0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B,\n\t0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x0B, 0x5F, 0xB2,\n\t0x60, 0x2A, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x60, 0x0A, 0x5F, 0x44, 0x60, 0x2A,\n\t0x63, 0x0A, 0x62, 0x44, 0x63, 0x2A, 0x66, 0x0A, 0x66, 0x2A, 0x69, 0x0B, 0x68, 0x99, 0x69, 0x2B,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x0A, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x60, 0x2A, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x60, 0x0A, 0x5F, 0x99, 0x60, 0x2B, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x60, 0x0B, 0x5F, 0x65, 0x60, 0x2B, 0x38, 0x0E, 0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x47, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x60, 0x0B, 0x5F, 0x8B, 0x60, 0x2A, 0x63, 0x0A, 0x62, 0x8B, 0x63, 0x2A,\n\t0x66, 0x0A, 0x65, 0x06, 0x66, 0x2B, 0x69, 0x0B, 0x68, 0x05, 0x69, 0x2E, 0x6C, 0x16, 0x7A, 0x00,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x38, 0x0E, 0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x60, 0x0A, 0x5F, 0x05, 0x60, 0x2E, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA4,\n\t0x60, 0x0E, 0x7A, 0xA4, 0x60, 0x2E, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x60, 0x0E, 0x5F, 0x99, 0x60, 0x2B, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x60, 0x0B, 0x5F, 0x65, 0x60, 0x2B, 0x63, 0x0A, 0x7A, 0x00, 0x62, 0xB2, 0x63, 0x2A, 0x66, 0x0B,\n\t0x65, 0x65, 0x66, 0x2B, 0x69, 0x0E, 0x69, 0x2E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x60, 0x0B, 0x5F, 0x05,\n\t0x60, 0x2A, 0x63, 0x0A, 0x62, 0x05, 0x63, 0x2A, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x69, 0x0E,\n\t0x68, 0x65, 0x69, 0x2B, 0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x0A,\n\t0x5F, 0x65, 0x60, 0x2B, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x60, 0x0B, 0x5F, 0xB2, 0x60, 0x2A, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x60, 0x0A,\n\t0x5F, 0x05, 0x60, 0x2A, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x38, 0x16, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x0A, 0x60, 0x2A, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49, 0x60, 0x0A, 0x5F, 0x65, 0x60, 0x2B, 0x38, 0x16, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x7A, 0x00, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x0B, 0x5F, 0xB2, 0x60, 0x2A, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x0A, 0x5F, 0x44, 0x60, 0x2A, 0x63, 0x0A, 0x62, 0x44,\n\t0x63, 0x2A, 0x66, 0x0A, 0x7A, 0x00, 0x66, 0x2A, 0x69, 0x0B, 0x68, 0x99, 0x69, 0x2B, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x49,\n\t0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x60, 0x0A, 0x60, 0x2A, 0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x60, 0x0A, 0x5F, 0x99, 0x60, 0x2B, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x60, 0x0B, 0x5F, 0x65, 0x60, 0x2B, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA4, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x7A, 0xA4,\n\t0x60, 0x0B, 0x5F, 0x05, 0x60, 0x2E, 0x63, 0x0A, 0x62, 0x8B, 0x63, 0x2A, 0x66, 0x0A, 0x65, 0x06,\n\t0x66, 0x2B, 0x69, 0x0B, 0x68, 0x05, 0x69, 0x2E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x60, 0x0E, 0x60, 0x2E, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x60, 0x0E, 0x60, 0x2E, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA4, 0x60, 0x0E, 0x60, 0x2E, 0x63, 0x0A, 0x62, 0x05, 0x63, 0x2E, 0x25, 0xF2,\n\t0x34, 0xF2, 0x26, 0xF2, 0x35, 0xF2, 0x7A, 0x00, 0x6A, 0x08, 0x23, 0x27, 0x32, 0x32, 0x24, 0x4F,\n\t0x33, 0x08, 0x69, 0x0E, 0x69, 0x36, 0x7A, 0xA3, 0x60, 0x0E, 0x5F, 0x44, 0x60, 0x2E, 0x63, 0x0E,\n\t0x62, 0x44, 0x63, 0x2E, 0x66, 0x0B, 0x69, 0x16, 0x68, 0x44, 0x69, 0x36, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x60, 0x0E, 0x5F, 0x05, 0x60, 0x2E, 0x7A, 0x00, 0x63, 0x0E, 0x62, 0x05,\n\t0x63, 0x2E, 0x69, 0x16, 0x68, 0x05, 0x69, 0x36, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x60, 0x0E, 0x5F, 0x99, 0x60, 0x2B, 0x63, 0x0E, 0x62, 0x99, 0x63, 0x2B, 0x69, 0x16,\n\t0x68, 0x99, 0x69, 0x33, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47,\n\t0x60, 0x0B, 0x7A, 0x00, 0x5F, 0x06, 0x60, 0x2B, 0x63, 0x0B, 0x62, 0x06, 0x63, 0x2B, 0x69, 0x13,\n\t0x68, 0x06, 0x69, 0x33, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x0B, 0x5F, 0xB2,\n\t0x60, 0x2A, 0x63, 0x0B, 0x62, 0xB2, 0x63, 0x2A, 0x69, 0x13, 0x68, 0xB2, 0x69, 0x32, 0x6C, 0x16,\n\t0x7A, 0x00, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x63, 0x0A, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x60, 0x0A, 0x69, 0x12, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x07, 0xF2, 0x16, 0xF2,\n\t0x08, 0xF2, 0x17, 0xF2, 0x09, 0x00, 0x18, 0x00, 0x61, 0x08, 0x7A, 0x00, 0x05, 0x27, 0x14, 0x32,\n\t0x06, 0x4F, 0x15, 0x08, 0x5F, 0x65, 0x60, 0x33, 0x0C, 0xE9, 0x1B, 0xE9, 0x0D, 0x05, 0x1C, 0x04,\n\t0x0E, 0x01, 0x64, 0x06, 0x0A, 0x01, 0x19, 0x01, 0x0B, 0x08, 0x1A, 0x08, 0x63, 0x26, 0x7A, 0x00,\n\t0x1F, 0x16, 0x65, 0xB2, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x23, 0x00, 0x32, 0x00, 0x24, 0x00, 0x33, 0x04, 0x7A, 0x00, 0x68, 0x65, 0x69, 0x23,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA1, 0x63, 0x06, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x26,\n\t0x66, 0x0E, 0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x7A, 0x00, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x06, 0x7A, 0xA3, 0x60, 0x13, 0x60, 0x33, 0x7A, 0x00,\n\t0x63, 0x26, 0x66, 0x0E, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08,\n\t0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00,\n\t0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x63, 0x06, 0x62, 0x05,\n\t0x63, 0x26, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07,\n\t0x27, 0x02, 0x6A, 0x0F, 0x7A, 0x00, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x06, 0x62, 0xB2, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x33,\n\t0x63, 0x06, 0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x06, 0x66, 0x0E, 0x65, 0x05,\n\t0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x06, 0x63, 0x26, 0x66, 0x0E,\n\t0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x7A, 0x00, 0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4,\n\t0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x06, 0x62, 0x05,\n\t0x63, 0x26, 0x7A, 0xA4, 0x60, 0x33, 0x63, 0x06, 0x62, 0xB2, 0x63, 0x26, 0x66, 0x0A, 0x66, 0x2E,\n\t0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x7A, 0x00,\n\t0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x06,\n\t0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x05, 0x60, 0x36, 0x63, 0x26, 0x66, 0x0E, 0x7A, 0x00, 0x65, 0x05,\n\t0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06,\n\t0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA2, 0x63, 0x06, 0x7A, 0xA4, 0x60, 0x16, 0x5F, 0xB2, 0x60, 0x32, 0x63, 0x26, 0x66, 0x0E,\n\t0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x7A, 0x00, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x06, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4,\n\t0x7A, 0x00, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x12, 0x5F, 0x06,\n\t0x60, 0x33, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x65, 0x60, 0x33, 0x63, 0x06, 0x62, 0x99,\n\t0x63, 0x27, 0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x7A, 0x00, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x07, 0x62, 0x65, 0x7A, 0x00, 0x63, 0x27, 0x66, 0x0E,\n\t0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x07, 0x62, 0x06, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x65,\n\t0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x7A, 0x00,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x63, 0x07, 0x62, 0xB2, 0x63, 0x26, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47,\n\t0x60, 0x13, 0x5F, 0x99, 0x60, 0x33, 0x63, 0x06, 0x62, 0x99, 0x63, 0x27, 0x66, 0x0A, 0x66, 0x2E,\n\t0x25, 0xE8, 0x7A, 0x00, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00,\n\t0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x07,\n\t0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x44, 0x66, 0x2E, 0x25, 0xE4,\n\t0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x7A, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07,\n\t0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x99, 0x7A, 0x00, 0x66, 0x2B,\n\t0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04,\n\t0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x47, 0x60, 0x13, 0x63, 0x07, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5,\n\t0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44,\n\t0x7A, 0x00, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x33, 0x62, 0xB2, 0x63, 0x26,\n\t0x7A, 0xA3, 0x60, 0x13, 0x60, 0x33, 0x63, 0x06, 0x62, 0x99, 0x7A, 0x00, 0x63, 0x27, 0x66, 0x0A,\n\t0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00,\n\t0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x07,\n\t0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x65, 0x60, 0x33, 0x62, 0x65, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x44,\n\t0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x07, 0x7A, 0xA3, 0x60, 0x13, 0x60, 0x33, 0x7A, 0x00, 0x63, 0x27, 0x66, 0x0E,\n\t0x65, 0x99, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x60, 0x33, 0x63, 0x07, 0x66, 0x0B, 0x65, 0xB2,\n\t0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x60, 0x13, 0x60, 0x33, 0x63, 0x27, 0x7A, 0xA3, 0x60, 0x13, 0x7A, 0x00, 0x60, 0x33, 0x63, 0x07,\n\t0x63, 0x27, 0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x06, 0x60, 0x33, 0x62, 0x06,\n\t0x63, 0x27, 0x66, 0x0E, 0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x7A, 0x00, 0x26, 0x06,\n\t0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22,\n\t0x38, 0x16, 0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13,\n\t0x60, 0x33, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07,\n\t0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x7A, 0x00, 0x68, 0x65,\n\t0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13,\n\t0x5F, 0x65, 0x60, 0x33, 0x62, 0x65, 0x63, 0x27, 0x66, 0x0B, 0x65, 0xB2, 0x7A, 0x00, 0x66, 0x2A,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x13, 0x5F, 0x06,\n\t0x60, 0x33, 0x63, 0x07, 0x62, 0x06, 0x63, 0x27, 0x7A, 0xA4, 0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8,\n\t0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02,\n\t0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13,\n\t0x63, 0x07, 0x62, 0xB2, 0x63, 0x26, 0x25, 0xE4, 0x34, 0xF5, 0x7A, 0x00, 0x26, 0x06, 0x35, 0x07,\n\t0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16,\n\t0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x06, 0x7A, 0xA4, 0x5F, 0x05, 0x60, 0x36,\n\t0x62, 0x06, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x06, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07,\n\t0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x7A, 0x00, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65,\n\t0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x07, 0x62, 0x05,\n\t0x63, 0x2A, 0x7A, 0x00, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x60, 0x16, 0x5F, 0x65, 0x60, 0x33, 0x63, 0x0A, 0x62, 0xB2, 0x63, 0x26, 0x66, 0x0B,\n\t0x65, 0xB2, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x7A, 0x00,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x06, 0x7A, 0xA3, 0x60, 0x13, 0x7A, 0x00, 0x60, 0x33, 0x63, 0x26, 0x66, 0x0E,\n\t0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x06, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x26, 0x66, 0x0E,\n\t0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x7A, 0x00, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E, 0x7A, 0x00,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x63, 0x06, 0x62, 0x05, 0x63, 0x26,\n\t0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x7A, 0x00,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x06, 0x62, 0xB2, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x33, 0x63, 0x06,\n\t0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x7A, 0x00, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x06, 0x66, 0x0E, 0x65, 0x05,\n\t0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06,\n\t0x33, 0x00, 0x69, 0x03, 0x7A, 0x00, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x26, 0x7A, 0xA3, 0x60, 0x13, 0x60, 0x33, 0x63, 0x06, 0x63, 0x26, 0x66, 0x0E,\n\t0x7A, 0x00, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x7A, 0x00, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x06,\n\t0x62, 0x05, 0x63, 0x26, 0x7A, 0xA3, 0x60, 0x33, 0x63, 0x06, 0x7A, 0x00, 0x62, 0xB2, 0x63, 0x26,\n\t0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x63, 0x06, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x05, 0x60, 0x36, 0x63, 0x26, 0x66, 0x0E, 0x65, 0x05,\n\t0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x06, 0x7A, 0xA3, 0x60, 0x16, 0x5F, 0xB2, 0x7A, 0x00, 0x60, 0x32, 0x63, 0x26,\n\t0x66, 0x0E, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x06, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x7A, 0x00, 0x32, 0x06,\n\t0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x12,\n\t0x5F, 0x06, 0x60, 0x33, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x65, 0x60, 0x33, 0x63, 0x06,\n\t0x62, 0x99, 0x63, 0x27, 0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08,\n\t0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x7A, 0x00, 0x69, 0x23,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x07, 0x62, 0x65, 0x63, 0x27, 0x66, 0x0E,\n\t0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x7A, 0x00, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16,\n\t0x7A, 0x00, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x07, 0x62, 0x06, 0x63, 0x27, 0x66, 0x0E,\n\t0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x07, 0x62, 0xB2, 0x63, 0x26, 0x66, 0x0B, 0x65, 0xB2,\n\t0x66, 0x2A, 0x25, 0xE4, 0x7A, 0x00, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x60, 0x13, 0x5F, 0x99, 0x60, 0x33, 0x63, 0x06, 0x62, 0x99, 0x63, 0x27, 0x66, 0x0A,\n\t0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00,\n\t0x7A, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x63, 0x07, 0x7A, 0xA3, 0x60, 0x13, 0x60, 0x33, 0x7A, 0x00, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x44,\n\t0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06,\n\t0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x99,\n\t0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x7A, 0x00,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x63, 0x07, 0x7A, 0x00, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x33, 0x62, 0xB2,\n\t0x63, 0x26, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x06, 0x62, 0x99, 0x63, 0x27, 0x66, 0x0A,\n\t0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x7A, 0x00, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x65, 0x60, 0x33, 0x62, 0x65, 0x63, 0x27, 0x66, 0x0E,\n\t0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x27, 0x66, 0x0E,\n\t0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x7A, 0x00, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x60, 0x33, 0x63, 0x07, 0x63, 0x27,\n\t0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x7A, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x60, 0x13, 0x5F, 0x99, 0x60, 0x33, 0x7A, 0x00, 0x63, 0x07, 0x62, 0x99,\n\t0x63, 0x27, 0x7A, 0xA3, 0x60, 0x13, 0x5F, 0x05, 0x60, 0x36, 0x63, 0x07, 0x62, 0x05, 0x63, 0x2A,\n\t0x66, 0x0A, 0x65, 0x06, 0x7A, 0x00, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08,\n\t0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x16, 0x60, 0x36, 0x63, 0x0A, 0x63, 0x2E, 0x66, 0x0B,\n\t0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x7A, 0x00, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x16, 0x5F, 0x99, 0x60, 0x33, 0x63, 0x0E, 0x62, 0x99,\n\t0x63, 0x27, 0x7A, 0x00, 0x66, 0x0A, 0x65, 0x8B, 0x66, 0x2A, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07,\n\t0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23,\n\t0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x5F, 0x06,\n\t0x60, 0x33, 0x63, 0x07, 0x62, 0x06, 0x63, 0x2B, 0x66, 0x0A, 0x65, 0x44, 0x66, 0x2A, 0x25, 0xE4,\n\t0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x7A, 0x00, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13,\n\t0x5F, 0xB2, 0x60, 0x32, 0x7A, 0x00, 0x63, 0x0B, 0x62, 0xB2, 0x63, 0x26, 0x66, 0x0A, 0x65, 0x05,\n\t0x66, 0x2A, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00,\n\t0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x7A, 0x00, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x47, 0x66, 0x0A, 0x7A, 0x00, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x06, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06,\n\t0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x7A, 0x00, 0x69, 0x03, 0x68, 0x44,\n\t0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x07, 0x55, 0x16, 0x43, 0x08, 0x75,\n\t0x17, 0x65, 0x09, 0x01, 0x18, 0x01, 0x61, 0x0B, 0x05, 0x22, 0x14, 0x22, 0x06, 0x00, 0x15, 0x00,\n\t0x60, 0x12, 0x5F, 0x05, 0x60, 0x2A, 0x63, 0x26, 0x7A, 0x00, 0x1F, 0x0A, 0x66, 0x2A, 0x25, 0xE8,\n\t0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02,\n\t0x68, 0x65, 0x7A, 0x00, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA1, 0x63, 0x06, 0x7A, 0xA4,\n\t0x60, 0x0A, 0x5F, 0x65, 0x60, 0x2B, 0x63, 0x26, 0x66, 0x0A, 0x65, 0x65, 0x7A, 0x00, 0x66, 0x2B,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2,\n\t0x63, 0x06, 0x7A, 0xA4, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x63, 0x26, 0x66, 0x0B, 0x65, 0x06,\n\t0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00,\n\t0x7A, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x47, 0x60, 0x0B, 0x5F, 0xB2, 0x60, 0x2A, 0x63, 0x06, 0x66, 0x0B, 0x65, 0xB2,\n\t0x7A, 0x00, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x63, 0x26, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x7A, 0x00,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0xA3, 0x60, 0x0A, 0x5F, 0x05,\n\t0x60, 0x2A, 0x63, 0x06, 0x66, 0x0A, 0x65, 0x05, 0x66, 0x2A, 0x69, 0x03, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA4, 0x63, 0x26, 0x69, 0x23, 0x7A, 0xA3, 0x63, 0x06, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06,\n\t0x7A, 0x00, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44,\n\t0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x26, 0x69, 0x02,\n\t0x7A, 0xA4, 0x63, 0x06, 0x63, 0x26, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x7A, 0x00, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x0A, 0x66, 0x0A, 0x69, 0x03, 0x7A, 0xA4, 0x5F, 0x65, 0x60, 0x27,\n\t0x63, 0x06, 0x65, 0x65, 0x66, 0x27, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x60, 0x07, 0x5F, 0x99, 0x60, 0x27, 0x66, 0x07, 0x65, 0x99, 0x66, 0x27, 0x69, 0x02, 0x7A, 0x00,\n\t0x69, 0x22, 0x7A, 0xA3, 0x60, 0x07, 0x5F, 0x05, 0x60, 0x2A, 0x63, 0x26, 0x66, 0x07, 0x65, 0x05,\n\t0x66, 0x2A, 0x25, 0xE8, 0x34, 0xE9, 0x7A, 0x00, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x63, 0x06, 0x7A, 0xA4, 0x60, 0x0A, 0x5F, 0x65, 0x60, 0x2B, 0x63, 0x26, 0x66, 0x0A, 0x65, 0x65,\n\t0x66, 0x2B, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06,\n\t0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA2, 0x63, 0x06, 0x7A, 0xA4, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x63, 0x26, 0x66, 0x0B,\n\t0x65, 0x06, 0x66, 0x2B, 0x7A, 0x00, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x0B, 0x5F, 0xB2, 0x60, 0x2A, 0x63, 0x06,\n\t0x63, 0x26, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07,\n\t0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x7A, 0x00, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x06, 0x62, 0x99, 0x7A, 0x00, 0x63, 0x27, 0x25, 0xE8,\n\t0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02,\n\t0x68, 0x65, 0x69, 0x23, 0x7A, 0xA3, 0x60, 0x0A, 0x5F, 0x44, 0x60, 0x2A, 0x63, 0x07, 0x66, 0x0A,\n\t0x65, 0x44, 0x66, 0x2A, 0x7A, 0x00, 0x69, 0x03, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x27,\n\t0x69, 0x23, 0x7A, 0xA4, 0x63, 0x07, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x27, 0x69, 0x02, 0x7A, 0xA3, 0x63, 0x07, 0x63, 0x27,\n\t0x25, 0xE8, 0x7A, 0x00, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00,\n\t0x33, 0x04, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2,\n\t0x69, 0x03, 0x7A, 0xA4, 0x60, 0x0A, 0x66, 0x0A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07,\n\t0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x7A, 0x00, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x07, 0x69, 0x02, 0x69, 0x22, 0x7A, 0xA4, 0x60, 0x2A, 0x63, 0x27,\n\t0x66, 0x2A, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00,\n\t0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7A, 0xA2,\n\t0x63, 0x07, 0x7A, 0xA4, 0x60, 0x0A, 0x5F, 0x99, 0x60, 0x2B, 0x63, 0x27, 0x66, 0x0A, 0x65, 0x99,\n\t0x66, 0x2B, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x7A, 0x00, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x7A, 0x00,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x0B, 0x5F, 0x65, 0x60, 0x2B, 0x63, 0x27,\n\t0x66, 0x0B, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x7A, 0x00, 0x69, 0x23, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x63, 0x07,\n\t0x66, 0x0B, 0x65, 0x06, 0x66, 0x2B, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x7A, 0x00, 0x35, 0x07,\n\t0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA3, 0x62, 0x05, 0x63, 0x2A, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08,\n\t0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x7A, 0x00, 0x68, 0x65, 0x69, 0x23,\n\t0x7A, 0xA3, 0x60, 0x0B, 0x5F, 0x8B, 0x60, 0x2A, 0x63, 0x0A, 0x66, 0x0B, 0x65, 0x8B, 0x66, 0x2A,\n\t0x69, 0x03, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA4, 0x63, 0x2A, 0x69, 0x23, 0x7A, 0xA3, 0x63, 0x0A,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00, 0x6A, 0x0F, 0x32, 0x06,\n\t0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x63, 0x2A, 0x69, 0x02, 0x7A, 0xA4, 0x63, 0x0A, 0x63, 0x2A, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07,\n\t0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00,\n\t0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x69, 0x03, 0x7A, 0xA3, 0x25, 0xE4, 0x34, 0xF5,\n\t0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x68, 0x44,\n\t0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x0A, 0x69, 0x02, 0x69, 0x22, 0x7A, 0xA4,\n\t0x60, 0x0A, 0x5F, 0x05, 0x60, 0x2E, 0x63, 0x2A, 0x66, 0x0A, 0x65, 0x05, 0x66, 0x2E, 0x25, 0xE8,\n\t0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x7A, 0x00, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04,\n\t0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x0E, 0x63, 0x0A,\n\t0x66, 0x0E, 0x7A, 0xA3, 0x60, 0x2E, 0x7A, 0x00, 0x63, 0x2A, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5,\n\t0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44,\n\t0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x0A, 0x7A, 0xA4,\n\t0x60, 0x0E, 0x5F, 0x99, 0x60, 0x2B, 0x63, 0x2A, 0x66, 0x0E, 0x65, 0x99, 0x66, 0x2B, 0x25, 0xE8,\n\t0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x7A, 0x00, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04,\n\t0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x47, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x63, 0x0A, 0x66, 0x0B, 0x65, 0x06, 0x66, 0x2B,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7A, 0xA2, 0x62, 0xB2,\n\t0x63, 0x26, 0x25, 0xE8, 0x34, 0xE9, 0x7A, 0x00, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0xA3, 0x60, 0x0B, 0x5F, 0x65,\n\t0x60, 0x2B, 0x63, 0x06, 0x66, 0x0B, 0x65, 0x65, 0x66, 0x2B, 0x69, 0x03, 0x6C, 0x16, 0x7A, 0x00,\n\t0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x26, 0x69, 0x23, 0x7A, 0xA4, 0x63, 0x06, 0x25, 0xE4, 0x34, 0xF5,\n\t0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44,\n\t0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x26, 0x7A, 0x00,\n\t0x69, 0x02, 0x7A, 0xA3, 0x63, 0x06, 0x63, 0x26, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08,\n\t0x27, 0x01, 0x7A, 0x00, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x69, 0x03, 0x7A, 0xA4, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06,\n\t0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x06, 0x7A, 0x00, 0x69, 0x02, 0x69, 0x22, 0x7A, 0xA3, 0x60, 0x0B,\n\t0x5F, 0x05, 0x60, 0x2A, 0x63, 0x26, 0x7A, 0x00, 0x66, 0x0B, 0x65, 0x05, 0x66, 0x2A, 0x25, 0xE8,\n\t0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02,\n\t0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x06, 0x7A, 0xA4,\n\t0x60, 0x0A, 0x5F, 0x65, 0x60, 0x2B, 0x63, 0x26, 0x66, 0x0A, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE4,\n\t0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x7A, 0x00, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x06,\n\t0x7A, 0xA3, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x7A, 0x00, 0x63, 0x26, 0x66, 0x0B, 0x65, 0x06,\n\t0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00,\n\t0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x47, 0x60, 0x0B, 0x5F, 0xB2, 0x60, 0x2A, 0x63, 0x06, 0x66, 0x0B, 0x65, 0xB2,\n\t0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x63, 0x26, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00,\n\t0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0xA3, 0x60, 0x0A, 0x7A, 0x00, 0x5F, 0x05,\n\t0x60, 0x2A, 0x63, 0x06, 0x66, 0x0A, 0x65, 0x05, 0x66, 0x2A, 0x69, 0x03, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x26, 0x69, 0x23, 0x7A, 0xA4, 0x63, 0x06, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06,\n\t0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x7A, 0x00, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44,\n\t0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x26, 0x69, 0x02, 0x7A, 0xA4,\n\t0x63, 0x06, 0x63, 0x26, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA2, 0x69, 0x03, 0x7A, 0xA4, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x7A, 0x00, 0x33, 0x00, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x06, 0x69, 0x02, 0x69, 0x22, 0x7A, 0xA4, 0x60, 0x0A, 0x60, 0x2A, 0x63, 0x26,\n\t0x66, 0x0A, 0x66, 0x2A, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x7A, 0x00, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA2, 0x63, 0x06, 0x7A, 0xA4, 0x60, 0x0A, 0x5F, 0x65, 0x60, 0x2B, 0x63, 0x26, 0x7A, 0x00,\n\t0x66, 0x0A, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x06, 0x7A, 0xA4, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B,\n\t0x63, 0x26, 0x66, 0x0B, 0x65, 0x06, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08,\n\t0x27, 0x01, 0x6A, 0x06, 0x7A, 0x00, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23,\n\t0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x0B, 0x5F, 0xB2, 0x60, 0x2A,\n\t0x63, 0x06, 0x7A, 0x00, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06,\n\t0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x62, 0x99, 0x63, 0x27, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07,\n\t0x35, 0x08, 0x27, 0x01, 0x7A, 0x00, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65,\n\t0x69, 0x23, 0x7A, 0xA3, 0x60, 0x0A, 0x5F, 0x44, 0x60, 0x2A, 0x63, 0x07, 0x66, 0x0A, 0x65, 0x44,\n\t0x66, 0x2A, 0x69, 0x03, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA4, 0x63, 0x27, 0x69, 0x23, 0x7A, 0xA3,\n\t0x63, 0x07, 0x7A, 0x00, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x27, 0x69, 0x02, 0x7A, 0xA4, 0x63, 0x07, 0x63, 0x27, 0x25, 0xE8,\n\t0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x7A, 0x00, 0x33, 0x04,\n\t0x68, 0x65, 0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x69, 0x03, 0x7A, 0xA4,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x07, 0x69, 0x02, 0x69, 0x22,\n\t0x7A, 0xA4, 0x60, 0x0A, 0x60, 0x2A, 0x63, 0x27, 0x66, 0x0A, 0x66, 0x2A, 0x25, 0xE8, 0x7A, 0x00,\n\t0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02,\n\t0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x0A,\n\t0x5F, 0x99, 0x60, 0x2B, 0x63, 0x27, 0x66, 0x0A, 0x65, 0x99, 0x66, 0x2B, 0x25, 0xE4, 0x34, 0xF5,\n\t0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x7A, 0x00, 0x33, 0x00, 0x69, 0x03,\n\t0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4,\n\t0x60, 0x0B, 0x5F, 0x65, 0x60, 0x2B, 0x63, 0x27, 0x66, 0x0B, 0x7A, 0x00, 0x65, 0x65, 0x66, 0x2B,\n\t0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04,\n\t0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x47, 0x63, 0x07, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x62, 0x05, 0x63, 0x2A, 0x66, 0x0B, 0x65, 0x06,\n\t0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00,\n\t0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x7A, 0x00, 0x69, 0x23, 0x7A, 0xA2, 0x60, 0x0B, 0x5F, 0x05,\n\t0x60, 0x2E, 0x63, 0x0A, 0x66, 0x0B, 0x7A, 0x00, 0x65, 0x05, 0x66, 0x2E, 0x69, 0x03, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x2A, 0x69, 0x23, 0x7A, 0xA4, 0x60, 0x0E, 0x60, 0x2E, 0x63, 0x0A,\n\t0x66, 0x0E, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x7A, 0x00, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x2A, 0x69, 0x02, 0x7A, 0xA3, 0x60, 0x0E, 0x7A, 0x00, 0x60, 0x2E,\n\t0x63, 0x0A, 0x63, 0x2A, 0x66, 0x0E, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08,\n\t0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x69, 0x03, 0x7A, 0xA4, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06,\n\t0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x7A, 0x00, 0x68, 0x44, 0x69, 0x22,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x0E, 0x60, 0x2E, 0x63, 0x0A, 0x66, 0x0E, 0x66, 0x2E,\n\t0x69, 0x02, 0x7A, 0xA4, 0x60, 0x0E, 0x5F, 0x44, 0x60, 0x2E, 0x62, 0x44, 0x63, 0x2A, 0x66, 0x0E,\n\t0x65, 0x44, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x47, 0x60, 0x0E, 0x5F, 0x05, 0x60, 0x2E, 0x63, 0x0A, 0x62, 0x05, 0x63, 0x2A, 0x66, 0x0E,\n\t0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x7A, 0x00, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x0E, 0x5F, 0x99, 0x60, 0x2B, 0x63, 0x0A,\n\t0x62, 0x99, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x99, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07,\n\t0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x7A, 0x00, 0x69, 0x02, 0x68, 0x65,\n\t0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x0B, 0x5F, 0x06,\n\t0x60, 0x2B, 0x63, 0x07, 0x62, 0x06, 0x63, 0x27, 0x66, 0x0B, 0x65, 0x06, 0x7A, 0x00, 0x66, 0x2B,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x69, 0x02, 0x7A, 0xA4,\n\t0x60, 0x0B, 0x5F, 0xB2, 0x60, 0x2A, 0x63, 0x07, 0x62, 0xB2, 0x63, 0x26, 0x66, 0x0B, 0x65, 0xB2,\n\t0x66, 0x2A, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00,\n\t0x7A, 0x00, 0x33, 0x04, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00, 0x6A, 0x0F, 0x32, 0x06,\n\t0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x69, 0x02, 0x69, 0x22, 0x7A, 0xA4, 0x63, 0x06, 0x69, 0x02, 0x38, 0x0E, 0x6C, 0x16, 0x7A, 0x00,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x0A, 0x66, 0x0A, 0x7A, 0x00, 0x69, 0x22, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0x6C, 0x69, 0x02, 0x69, 0x22, 0x7A, 0x6D, 0x69, 0x02, 0x69, 0x22, 0x7A, 0x6D,\n\t0x07, 0xF2, 0x16, 0xF2, 0x08, 0xF2, 0x17, 0xF2, 0x09, 0x00, 0x18, 0x00, 0x61, 0x08, 0x05, 0x27,\n\t0x14, 0x32, 0x06, 0x4F, 0x15, 0x08, 0x5F, 0x65, 0x7A, 0x00, 0x60, 0x33, 0x63, 0x26, 0x7A, 0x00,\n\t0x1F, 0x16, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA1, 0x63, 0x06, 0x7A, 0xA3, 0x60, 0x13, 0x7A, 0x00, 0x60, 0x33, 0x63, 0x26, 0x66, 0x0E,\n\t0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x06, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x26, 0x66, 0x0E,\n\t0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x7A, 0x00, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E, 0x7A, 0x00,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x63, 0x06, 0x62, 0x05, 0x63, 0x26,\n\t0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x06, 0x62, 0xB2, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x33, 0x63, 0x06,\n\t0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x7A, 0x00, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x06, 0x66, 0x0E, 0x65, 0x05,\n\t0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06,\n\t0x33, 0x00, 0x7A, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x26, 0x7A, 0xA3, 0x60, 0x13, 0x60, 0x33, 0x63, 0x06, 0x63, 0x26, 0x7A, 0x00,\n\t0x66, 0x0E, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x7A, 0x00, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x06,\n\t0x62, 0x05, 0x63, 0x26, 0x7A, 0xA3, 0x60, 0x33, 0x63, 0x06, 0x7A, 0x00, 0x62, 0xB2, 0x63, 0x26,\n\t0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x63, 0x06, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x05, 0x60, 0x36, 0x63, 0x26, 0x66, 0x0E, 0x65, 0x05,\n\t0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x7A, 0x00,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x06, 0x7A, 0xA3, 0x60, 0x16, 0x7A, 0x00, 0x5F, 0xB2, 0x60, 0x32,\n\t0x63, 0x26, 0x66, 0x0E, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08,\n\t0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00,\n\t0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x06, 0x66, 0x0B, 0x65, 0xB2,\n\t0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x7A, 0x00,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x60, 0x12, 0x5F, 0x06, 0x60, 0x33, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x65, 0x60, 0x33,\n\t0x63, 0x06, 0x62, 0x99, 0x63, 0x27, 0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07,\n\t0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x7A, 0x00, 0x68, 0x65,\n\t0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x07, 0x62, 0x65, 0x63, 0x27,\n\t0x66, 0x0E, 0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x7A, 0x00, 0x35, 0x07,\n\t0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16,\n\t0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x07, 0x62, 0x06, 0x63, 0x27,\n\t0x66, 0x0E, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x7A, 0x00, 0x69, 0x23, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x07, 0x62, 0xB2, 0x63, 0x26, 0x66, 0x0B,\n\t0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x7A, 0x00, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13, 0x5F, 0x99, 0x60, 0x33, 0x63, 0x06, 0x62, 0x99, 0x63, 0x27,\n\t0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x7A, 0x00, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x07, 0x7A, 0xA3, 0x60, 0x13, 0x60, 0x33, 0x7A, 0x00, 0x63, 0x27, 0x66, 0x0E,\n\t0x65, 0x44, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x27, 0x66, 0x0E,\n\t0x65, 0x99, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x7A, 0x00,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x63, 0x07, 0x7A, 0x00, 0x66, 0x0B, 0x65, 0xB2,\n\t0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06,\n\t0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x33,\n\t0x62, 0xB2, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x06, 0x62, 0x99, 0x63, 0x27,\n\t0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x7A, 0x00, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x65, 0x60, 0x33, 0x62, 0x65, 0x63, 0x27,\n\t0x66, 0x0E, 0x65, 0x44, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x7A, 0x00, 0x69, 0x22, 0x38, 0x16,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x27,\n\t0x66, 0x0E, 0x65, 0x99, 0x66, 0x2B, 0x7A, 0x00, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08,\n\t0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00,\n\t0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x60, 0x33, 0x63, 0x07,\n\t0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x7A, 0x00, 0x69, 0x22, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x60, 0x13, 0x7A, 0x00, 0x60, 0x33, 0x63, 0x27, 0x7A, 0xA3, 0x60, 0x13,\n\t0x60, 0x33, 0x63, 0x07, 0x63, 0x27, 0x66, 0x0A, 0x7A, 0x00, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9,\n\t0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65,\n\t0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x06,\n\t0x60, 0x33, 0x62, 0x06, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5,\n\t0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x7A, 0x00, 0x33, 0x00, 0x69, 0x03,\n\t0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x07, 0x7A, 0xA3,\n\t0x60, 0x13, 0x60, 0x33, 0x7A, 0x00, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8,\n\t0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02,\n\t0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07,\n\t0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x65, 0x60, 0x33, 0x62, 0x65, 0x63, 0x27, 0x66, 0x0B, 0x65, 0xB2,\n\t0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x60, 0x13, 0x5F, 0x06, 0x60, 0x33, 0x63, 0x07, 0x62, 0x06, 0x63, 0x27, 0x7A, 0xA3, 0x66, 0x0A,\n\t0x66, 0x2E, 0x7A, 0x00, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x60, 0x13, 0x63, 0x07, 0x62, 0xB2, 0x63, 0x26, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06,\n\t0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x7A, 0x00, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44,\n\t0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x06, 0x7A, 0xA4, 0x5F, 0x05,\n\t0x60, 0x36, 0x62, 0x06, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x06, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9,\n\t0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65,\n\t0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x07,\n\t0x62, 0x05, 0x63, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x7A, 0x00, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x48, 0x60, 0x16, 0x5F, 0x65, 0x60, 0x33, 0x63, 0x0A, 0x62, 0xB2, 0x63, 0x26,\n\t0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x7A, 0x00, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x06, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x26, 0x66, 0x0E,\n\t0x65, 0x05, 0x7A, 0x00, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x06, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x26,\n\t0x66, 0x0E, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x7A, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x63, 0x06, 0x62, 0x05, 0x63, 0x26,\n\t0x66, 0x0B, 0x7A, 0x00, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07,\n\t0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x06, 0x62, 0xB2, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x33, 0x63, 0x06,\n\t0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x7A, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x26, 0x7A, 0xA3, 0x60, 0x13, 0x60, 0x33, 0x7A, 0x00, 0x63, 0x06, 0x66, 0x0E,\n\t0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x06, 0x63, 0x26,\n\t0x66, 0x0E, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x7A, 0x00, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x7A, 0x00, 0x66, 0x0B, 0x65, 0xB2,\n\t0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06,\n\t0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x63, 0x06,\n\t0x62, 0x05, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x33, 0x63, 0x06, 0x62, 0xB2, 0x63, 0x26, 0x66, 0x0A,\n\t0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x7A, 0x00, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x63, 0x06, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x05, 0x60, 0x36, 0x63, 0x26, 0x66, 0x0E, 0x65, 0x05,\n\t0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06,\n\t0x33, 0x00, 0x69, 0x03, 0x7A, 0x00, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA2, 0x63, 0x06, 0x7A, 0xA4, 0x60, 0x16, 0x5F, 0xB2, 0x60, 0x32, 0x63, 0x26, 0x66, 0x0E,\n\t0x65, 0x65, 0x7A, 0x00, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x06, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x60, 0x12,\n\t0x7A, 0x00, 0x5F, 0x06, 0x60, 0x33, 0x63, 0x26, 0x7A, 0xA3, 0x60, 0x13, 0x5F, 0x65, 0x60, 0x33,\n\t0x63, 0x06, 0x62, 0x99, 0x63, 0x27, 0x7A, 0x00, 0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9,\n\t0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65,\n\t0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x63, 0x07, 0x62, 0x65, 0x63, 0x27,\n\t0x66, 0x0E, 0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x7A, 0x00, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x07, 0x62, 0x06, 0x63, 0x27, 0x66, 0x0E,\n\t0x7A, 0x00, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x63, 0x07, 0x62, 0xB2, 0x63, 0x26, 0x66, 0x0B,\n\t0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F,\n\t0x7A, 0x00, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x7A, 0x00, 0x5F, 0x99, 0x60, 0x33, 0x63, 0x06, 0x62, 0x99,\n\t0x63, 0x27, 0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x7A, 0x00,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x27, 0x66, 0x0E,\n\t0x65, 0x44, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x7A, 0x00, 0x35, 0x07, 0x27, 0x02,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16,\n\t0x7A, 0x00, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x27,\n\t0x66, 0x0E, 0x65, 0x99, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x7A, 0x00, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x63, 0x07, 0x66, 0x0B, 0x65, 0xB2,\n\t0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x7A, 0x00, 0x27, 0x02, 0x6A, 0x0F,\n\t0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x60, 0x33, 0x62, 0xB2, 0x63, 0x26, 0x7A, 0xA4, 0x60, 0x13, 0x60, 0x33, 0x63, 0x06, 0x62, 0x99,\n\t0x63, 0x27, 0x66, 0x0A, 0x66, 0x2E, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x32, 0x00, 0x7A, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x65, 0x60, 0x33, 0x62, 0x65,\n\t0x63, 0x27, 0x66, 0x0E, 0x7A, 0x00, 0x65, 0x05, 0x66, 0x2E, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06,\n\t0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22,\n\t0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA2, 0x63, 0x07, 0x7A, 0xA4, 0x60, 0x13,\n\t0x60, 0x33, 0x63, 0x27, 0x66, 0x0E, 0x65, 0x65, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07,\n\t0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x7A, 0x00, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65,\n\t0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x13, 0x60, 0x33,\n\t0x63, 0x07, 0x7A, 0x00, 0x63, 0x27, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5,\n\t0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44,\n\t0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3, 0x60, 0x13, 0x5F, 0x99, 0x60, 0x33, 0x63, 0x07,\n\t0x62, 0x99, 0x63, 0x27, 0x7A, 0xA4, 0x60, 0x13, 0x5F, 0x05, 0x60, 0x36, 0x63, 0x07, 0x62, 0x05,\n\t0x63, 0x2A, 0x66, 0x0A, 0x65, 0x06, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08,\n\t0x27, 0x01, 0x7A, 0x00, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x16, 0x7A, 0x00, 0x60, 0x36, 0x63, 0x0A,\n\t0x63, 0x2E, 0x66, 0x0B, 0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07,\n\t0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00,\n\t0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x16, 0x5F, 0x99, 0x60, 0x33,\n\t0x63, 0x0E, 0x62, 0x99, 0x63, 0x27, 0x66, 0x0A, 0x65, 0x8B, 0x66, 0x2A, 0x25, 0xE8, 0x34, 0xE9,\n\t0x26, 0x07, 0x7A, 0x00, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02,\n\t0x68, 0x65, 0x69, 0x23, 0x38, 0x0E, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x60, 0x13,\n\t0x5F, 0x06, 0x60, 0x33, 0x63, 0x07, 0x62, 0x06, 0x63, 0x2B, 0x66, 0x0A, 0x65, 0x44, 0x66, 0x2A,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00,\n\t0x69, 0x03, 0x68, 0x44, 0x7A, 0x00, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47,\n\t0x60, 0x13, 0x5F, 0xB2, 0x60, 0x32, 0x63, 0x0B, 0x62, 0xB2, 0x63, 0x26, 0x66, 0x0A, 0x65, 0x05,\n\t0x66, 0x2A, 0x25, 0xE8, 0x7A, 0x00, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00,\n\t0x7A, 0x48, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06,\n\t0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x7A, 0x00, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7B, 0x00, 0x7A, 0x47, 0x66, 0x0A, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01,\n\t0x6A, 0x06, 0x7A, 0x00, 0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x38, 0x0E,\n\t0x6C, 0x16, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x48, 0x63, 0x06, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06,\n\t0x35, 0x07, 0x27, 0x02, 0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22,\n\t0x6C, 0x16, 0x7A, 0x00, 0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x07, 0x55, 0x16, 0x43, 0x08, 0x75,\n\t0x17, 0x65, 0x09, 0x01, 0x7A, 0x00, 0x18, 0x01, 0x61, 0x0B, 0x05, 0x22, 0x14, 0x22, 0x06, 0x00,\n\t0x15, 0x00, 0x60, 0x12, 0x5F, 0x05, 0x60, 0x2A, 0x63, 0x26, 0x1F, 0x0A, 0x7A, 0x00, 0x66, 0x2A,\n\t0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06, 0x32, 0x00, 0x33, 0x04,\n\t0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA1, 0x63, 0x06,\n\t0x7A, 0xA4, 0x60, 0x0A, 0x5F, 0x65, 0x60, 0x2B, 0x63, 0x26, 0x66, 0x0A, 0x65, 0x65, 0x66, 0x2B,\n\t0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00, 0x6A, 0x0F, 0x32, 0x06,\n\t0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x38, 0x16, 0x6C, 0x16, 0x6C, 0x36, 0x7A, 0xA3,\n\t0x63, 0x06, 0x7A, 0xA3, 0x60, 0x0B, 0x5F, 0x06, 0x60, 0x2B, 0x7A, 0x00, 0x63, 0x26, 0x66, 0x0B,\n\t0x65, 0x06, 0x66, 0x2B, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0x00, 0x38, 0x0E, 0x6C, 0x16,\n\t0x6C, 0x36, 0x7B, 0x00, 0x7A, 0x47, 0x60, 0x0B, 0x5F, 0xB2, 0x60, 0x2A, 0x63, 0x06, 0x66, 0x0B,\n\t0x65, 0xB2, 0x66, 0x2A, 0x25, 0xE4, 0x34, 0xF5, 0x26, 0x06, 0x35, 0x07, 0x27, 0x02, 0x7A, 0x00,\n\t0x6A, 0x0F, 0x32, 0x06, 0x33, 0x00, 0x69, 0x03, 0x68, 0x44, 0x69, 0x22, 0x6C, 0x16, 0x6C, 0x36,\n\t0x7A, 0xA3, 0x63, 0x26, 0x25, 0xE8, 0x34, 0xE9, 0x26, 0x07, 0x35, 0x08, 0x27, 0x01, 0x6A, 0x06,\n\t0x32, 0x00, 0x33, 0x04, 0x69, 0x02, 0x68, 0x65, 0x69, 0x23, 0x7A, 0xA4, 0x60, 0x0A, 0x5F, 0x05,\n\t0x60, 0x2A, 0x63, 0x06, 0x66, 0x0A, 0x65, 0x05, 0x66, 0x2A, 0x69, 0x03, 0x6C, 0x16, 0x6C, 0x36};\n\n// rudolph.dro - Rudolph, the red-nosed Reindeer (Recording of RUDOLPH.CMF)\nconst unsigned char RODOLPH_DRO[0x1451] =\n{\t0x44, 0x42, 0x52, 0x41, 0x57, 0x4F, 0x50, 0x4C, 0xE2, 0x36, 0x01, 0x00, 0x40, 0x14, 0x00, 0x00,\n\t0x00, 0x00, 0x08, 0x01, 0x20, 0x02, 0x08, 0x04, 0x08, 0x0B, 0x08, 0x0D, 0x08, 0x0F, 0x08, 0x16,\n\t0x08, 0x18, 0x08, 0x1A, 0x08, 0x20, 0x01, 0x21, 0x01, 0x22, 0x01, 0x23, 0x11, 0x24, 0x11, 0x25,\n\t0x11, 0x28, 0x01, 0x29, 0x01, 0x2A, 0x01, 0x2B, 0x11, 0x2C, 0x11, 0x2D, 0x11, 0x30, 0x01, 0x31,\n\t0x01, 0x32, 0x01, 0x33, 0x11, 0x34, 0x11, 0x35, 0x11, 0x40, 0x4F, 0x41, 0x4F, 0x42, 0x4F, 0x48,\n\t0x4F, 0x49, 0x4F, 0x4A, 0x4F, 0x50, 0x4F, 0x51, 0x4F, 0x52, 0x4F, 0x60, 0xF1, 0x61, 0xF1, 0x62,\n\t0xF1, 0x63, 0xD2, 0x64, 0xF2, 0x65, 0xF2, 0x68, 0xF1, 0x69, 0xF1, 0x6A, 0xF1, 0x6B, 0xF2, 0x6C,\n\t0xF2, 0x6D, 0xF2, 0x70, 0xF1, 0x71, 0xF1, 0x72, 0xF1, 0x73, 0xF2, 0x74, 0xF2, 0x75, 0xF2, 0x80,\n\t0x53, 0x81, 0x53, 0x82, 0x53, 0x83, 0x74, 0x84, 0x74, 0x85, 0x74, 0x88, 0x53, 0x89, 0x53, 0x8A,\n\t0x53, 0x8B, 0x74, 0x8C, 0x74, 0x8D, 0x74, 0x90, 0x53, 0x91, 0x53, 0x92, 0x53, 0x93, 0x74, 0x94,\n\t0x74, 0x95, 0x74, 0xA0, 0x02, 0xA1, 0x81, 0xA2, 0x87, 0xBD, 0xE0, 0xB0, 0x36, 0x21, 0x01, 0x24,\n\t0x11, 0x41, 0x4F, 0x61, 0xF1, 0x64, 0xD2, 0x81, 0x53, 0x84, 0x74, 0xE1, 0x00, 0x00, 0x05, 0xE4,\n\t0x00, 0xC1, 0x00, 0x44, 0x00, 0xA1, 0x81, 0xB1, 0x35, 0x22, 0x01, 0x25, 0x11, 0x42, 0x4F, 0x00,\n\t0x05, 0x62, 0xF1, 0x65, 0xD2, 0x82, 0x53, 0x85, 0x74, 0xE2, 0x00, 0xE5, 0x00, 0xC2, 0x00, 0x45,\n\t0x00, 0xA2, 0x87, 0x00, 0x05, 0xB2, 0x32, 0x00, 0xCB, 0xA0, 0x02, 0xB0, 0x16, 0x43, 0x00, 0xA0,\n\t0x41, 0xB0, 0x36, 0x00, 0xDA, 0xA0, 0x41, 0xB0, 0x16, 0x43, 0x00, 0xA0, 0x02, 0xB0, 0x36, 0x01,\n\t0xBF, 0x01, 0xA1, 0x81, 0xB1, 0x15, 0xA2, 0x87, 0xB2, 0x12, 0xA0, 0x02, 0xB0, 0x16, 0x43, 0x00,\n\t0xA0, 0xCA, 0xB0, 0x35, 0x00, 0x05, 0x44, 0x00, 0xA1, 0x57, 0xB1, 0x35, 0x45, 0x00, 0xA2, 0x41,\n\t0xB2, 0x32, 0x00, 0xD3, 0xA0, 0xCA, 0xB0, 0x15, 0x43, 0x00, 0xA0, 0x02, 0xB0, 0x36, 0x00, 0xDA,\n\t0xA0, 0x02, 0xB0, 0x16, 0x43, 0x00, 0xA0, 0xCA, 0xB0, 0x35, 0x01, 0xBF, 0x01, 0xA1, 0x57, 0xB1,\n\t0x15, 0xA2, 0x41, 0xB2, 0x12, 0xA0, 0xCA, 0xB0, 0x15, 0x43, 0x00, 0xA0, 0xB0, 0x00, 0x05, 0xB0,\n\t0x35, 0x44, 0x00, 0xA1, 0x87, 0xB1, 0x32, 0x45, 0x00, 0xA2, 0x02, 0xB2, 0x32, 0x00, 0xD4, 0xA0,\n\t0xB0, 0xB0, 0x15, 0x43, 0x00, 0xA0, 0xCA, 0xB0, 0x35, 0x00, 0xE4, 0xA0, 0xCA, 0xB0, 0x15, 0x43,\n\t0x00, 0xA0, 0xB0, 0xB0, 0x35, 0x01, 0xB4, 0x01, 0xA1, 0x87, 0xB1, 0x12, 0xA2, 0x02, 0xB2, 0x12,\n\t0xA0, 0xB0, 0xB0, 0x15, 0x43, 0x00, 0xA0, 0x81, 0x00, 0x05, 0xB0, 0x35, 0x44, 0x00, 0xA1, 0x41,\n\t0xB1, 0x32, 0x45, 0x00, 0xA2, 0xCA, 0xB2, 0x31, 0x01, 0x79, 0x03, 0xA0, 0x81, 0xB0, 0x15, 0xA1,\n\t0x41, 0xB1, 0x12, 0xA2, 0xCA, 0xB2, 0x11, 0x43, 0x00, 0xA0, 0x57, 0x00, 0x05, 0xB0, 0x35, 0x44,\n\t0x00, 0xA1, 0x02, 0xB1, 0x32, 0x45, 0x00, 0xA2, 0xB0, 0xB2, 0x31, 0x00, 0xD4, 0xA0, 0x57, 0xB0,\n\t0x15, 0x43, 0x00, 0xA0, 0x81, 0xB0, 0x35, 0x00, 0xD9, 0xA0, 0x81, 0xB0, 0x15, 0x43, 0x00, 0xA0,\n\t0x57, 0xB0, 0x35, 0x01, 0xBF, 0x01, 0xA1, 0x02, 0xB1, 0x12, 0xA2, 0xB0, 0xB2, 0x11, 0xA0, 0x57,\n\t0xB0, 0x15, 0x43, 0x00, 0xA0, 0x87, 0x00, 0x05, 0xB0, 0x32, 0x44, 0x00, 0xA1, 0xE5, 0xB1, 0x31,\n\t0x45, 0x00, 0xA2, 0x98, 0xB2, 0x31, 0x00, 0xD4, 0xA0, 0x87, 0xB0, 0x12, 0x43, 0x00, 0xA0, 0x57,\n\t0xB0, 0x35, 0x00, 0xE4, 0xA0, 0x57, 0xB0, 0x15, 0x43, 0x00, 0xA0, 0x87, 0xB0, 0x32, 0x01, 0xB5,\n\t0x01, 0xA1, 0xE5, 0xB1, 0x11, 0xA2, 0x98, 0xB2, 0x11, 0xA0, 0x87, 0xB0, 0x12, 0x43, 0x00, 0xA0,\n\t0x41, 0xB0, 0x32, 0x00, 0x05, 0x44, 0x00, 0xA1, 0xCA, 0xB1, 0x31, 0x45, 0x00, 0xA2, 0x81, 0xB2,\n\t0x31, 0x01, 0xB9, 0x01, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x00, 0xA0, 0x81, 0xB0, 0x35, 0x01, 0xBE,\n\t0x01, 0xA1, 0xCA, 0xB1, 0x11, 0xA2, 0x81, 0xB2, 0x11, 0xA0, 0x81, 0xB0, 0x15, 0x43, 0x00, 0xA0,\n\t0x02, 0x00, 0x05, 0xB0, 0x32, 0x44, 0x00, 0xA1, 0xCA, 0xB1, 0x31, 0x45, 0x00, 0xA2, 0x87, 0xB2,\n\t0x2E, 0x01, 0xAF, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0xA1, 0xCA, 0xB1, 0x11, 0xA2, 0x87, 0xB2, 0x0E,\n\t0x20, 0x32, 0x23, 0x61, 0x00, 0x05, 0x40, 0x9A, 0x60, 0x51, 0x63, 0xA2, 0x80, 0x1B, 0x83, 0x3B,\n\t0xE0, 0x00, 0xE3, 0x00, 0xC0, 0x00, 0x43, 0x80, 0x00, 0x05, 0xA0, 0x41, 0xB0, 0x32, 0x00, 0xD8,\n\t0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x87, 0xB0, 0x32, 0x00, 0xDA, 0xA0, 0x87, 0xB0, 0x12,\n\t0x43, 0x80, 0xA0, 0x57, 0xB0, 0x35, 0x21, 0x31, 0x24, 0x61, 0x41, 0x1C, 0x61, 0x41, 0x00, 0x05,\n\t0x64, 0x92, 0x81, 0x0B, 0x84, 0x3B, 0xE1, 0x00, 0xE4, 0x00, 0xC1, 0x00, 0x44, 0x80, 0xA1, 0xB0,\n\t0x00, 0x05, 0xB1, 0x31, 0x22, 0x31, 0x25, 0x61, 0x42, 0x1C, 0x62, 0x41, 0x65, 0x92, 0x82, 0x0B,\n\t0x85, 0x3B, 0xE2, 0x00, 0x00, 0x05, 0xE5, 0x00, 0xC2, 0x00, 0x45, 0x80, 0xA2, 0x41, 0xB2, 0x2E,\n\t0x28, 0x01, 0x2B, 0x11, 0x48, 0x4F, 0x00, 0x05, 0x68, 0xF1, 0x6B, 0xD2, 0x88, 0x53, 0x8B, 0x74,\n\t0xE8, 0x00, 0xEB, 0x00, 0xC3, 0x00, 0x4B, 0x00, 0xA3, 0xCA, 0x00, 0x05, 0xB3, 0x2D, 0x00, 0xC6,\n\t0xA0, 0x57, 0xB0, 0x15, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x01, 0xBF, 0x01, 0xA0, 0x41, 0xB0,\n\t0x12, 0x43, 0x80, 0xA0, 0xCA, 0xB0, 0x31, 0x00, 0xDA, 0xA1, 0xB0, 0xB1, 0x11, 0xA2, 0x41, 0xB2,\n\t0x0E, 0xA3, 0xCA, 0xB3, 0x0D, 0xA0, 0xCA, 0xB0, 0x11, 0x43, 0x80, 0x00, 0x05, 0xA0, 0x87, 0xB0,\n\t0x32, 0x44, 0x80, 0xA1, 0x81, 0xB1, 0x31, 0x45, 0x80, 0xA2, 0x02, 0xB2, 0x2E, 0x00, 0x05, 0x4B,\n\t0x00, 0xA3, 0xB0, 0xB3, 0x2D, 0x00, 0xD8, 0xA0, 0x87, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x02, 0xB0,\n\t0x32, 0x01, 0xB4, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0xB0, 0xB0, 0x31, 0x00, 0xE4,\n\t0xA1, 0x81, 0xB1, 0x11, 0xA2, 0x02, 0xB2, 0x0E, 0xA3, 0xB0, 0xB3, 0x0D, 0xA0, 0xB0, 0xB0, 0x11,\n\t0x00, 0x05, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x31, 0x45, 0x80,\n\t0xA2, 0xCA, 0x00, 0x05, 0xB2, 0x2D, 0x4B, 0x00, 0xA3, 0x81, 0xB3, 0x2D, 0x00, 0xCE, 0xA0, 0x41,\n\t0xB0, 0x12, 0x43, 0x80, 0xA0, 0xCA, 0xB0, 0x31, 0x01, 0xBF, 0x01, 0xA0, 0xCA, 0xB0, 0x11, 0x43,\n\t0x80, 0xA0, 0x81, 0xB0, 0x31, 0x00, 0xDA, 0xA1, 0x57, 0xB1, 0x11, 0xA2, 0xCA, 0xB2, 0x0D, 0xA3,\n\t0x81, 0xB3, 0x0D, 0xA0, 0x81, 0xB0, 0x11, 0x43, 0x80, 0x00, 0x05, 0xA0, 0x41, 0xB0, 0x32, 0x44,\n\t0x80, 0xA1, 0x87, 0xB1, 0x2E, 0x45, 0x80, 0xA2, 0xB0, 0xB2, 0x2D, 0x00, 0x05, 0x4B, 0x00, 0xA3,\n\t0x57, 0xB3, 0x2D, 0x00, 0xCD, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x01,\n\t0x9A, 0x02, 0xA1, 0x87, 0xB1, 0x0E, 0xA2, 0xB0, 0xB2, 0x0D, 0xA3, 0x57, 0xB3, 0x0D, 0xA0, 0x02,\n\t0xB0, 0x12, 0x00, 0x05, 0x43, 0x80, 0xA0, 0x57, 0xB0, 0x35, 0x44, 0x80, 0xA1, 0xB0, 0xB1, 0x31,\n\t0x45, 0x80, 0xA2, 0x41, 0xB2, 0x2E, 0x00, 0x05, 0x4B, 0x00, 0xA3, 0xCA, 0xB3, 0x2D, 0x00, 0xD8,\n\t0xA0, 0x57, 0xB0, 0x15, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x01, 0xB5, 0x01, 0xA0, 0x41, 0xB0,\n\t0x12, 0x43, 0x80, 0xA0, 0xCA, 0xB0, 0x31, 0x00, 0xE4, 0xA1, 0xB0, 0xB1, 0x11, 0xA2, 0x41, 0xB2,\n\t0x0E, 0xA3, 0xCA, 0xB3, 0x0D, 0xA0, 0xCA, 0xB0, 0x11, 0x43, 0x80, 0x00, 0x05, 0xA0, 0x87, 0xB0,\n\t0x32, 0x44, 0x80, 0xA1, 0x81, 0xB1, 0x31, 0x45, 0x80, 0xA2, 0x02, 0xB2, 0x2E, 0x00, 0x05, 0x4B,\n\t0x00, 0xA3, 0xB0, 0xB3, 0x2D, 0x00, 0xCE, 0xA0, 0x87, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x02, 0xB0,\n\t0x32, 0x01, 0xBE, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0xB0, 0xB0, 0x31, 0x00, 0xDA,\n\t0xA1, 0x81, 0xB1, 0x11, 0xA2, 0x02, 0xB2, 0x0E, 0xA3, 0xB0, 0xB3, 0x0D, 0xA0, 0xB0, 0xB0, 0x11,\n\t0x00, 0x05, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x31, 0x45, 0x80,\n\t0xA2, 0xCA, 0xB2, 0x2D, 0x00, 0x05, 0x4B, 0x00, 0xA3, 0x81, 0xB3, 0x2D, 0x00, 0xCE, 0xA0, 0x41,\n\t0xB0, 0x12, 0x43, 0x80, 0xA0, 0xCA, 0xB0, 0x31, 0x01, 0xBF, 0x01, 0xA0, 0xCA, 0xB0, 0x11, 0x43,\n\t0x80, 0xA0, 0x81, 0xB0, 0x31, 0x00, 0xDA, 0xA1, 0x57, 0xB1, 0x11, 0xA2, 0xCA, 0xB2, 0x0D, 0xA3,\n\t0x81, 0xB3, 0x0D, 0xA0, 0x81, 0xB0, 0x11, 0x43, 0x80, 0x00, 0x05, 0xA0, 0x41, 0xB0, 0x32, 0x44,\n\t0x80, 0xA1, 0x87, 0xB1, 0x2E, 0x45, 0x80, 0xA2, 0xB0, 0xB2, 0x2D, 0x00, 0x05, 0x4B, 0x00, 0xA3,\n\t0x57, 0xB3, 0x2D, 0x00, 0xD8, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x01,\n\t0x99, 0x02, 0xA1, 0x87, 0xB1, 0x0E, 0xA2, 0xB0, 0xB2, 0x0D, 0xA3, 0x57, 0xB3, 0x0D, 0xA0, 0x02,\n\t0xB0, 0x12, 0x00, 0x05, 0x43, 0x80, 0xA0, 0xB0, 0xB0, 0x31, 0x29, 0xB2, 0x2C, 0xB1, 0x49, 0xCD,\n\t0x69, 0x91, 0x6C, 0x91, 0x00, 0x05, 0x89, 0x2A, 0x8C, 0x2A, 0xE9, 0x00, 0xEC, 0x00, 0xC4, 0x00,\n\t0x4C, 0x80, 0xA4, 0xB0, 0xB4, 0x31, 0x44, 0x80, 0x00, 0x05, 0xA1, 0x41, 0xB1, 0x2E, 0x45, 0x80,\n\t0xA2, 0x57, 0xB2, 0x2D, 0x01, 0xAD, 0x01, 0xA0, 0xB0, 0xB0, 0x11, 0xA4, 0xB0, 0xB4, 0x11, 0x43,\n\t0x80, 0xA0, 0xB0, 0xB0, 0x31, 0x4C, 0x80, 0x00, 0x05, 0xA4, 0xB0, 0xB4, 0x31, 0x01, 0xB9, 0x01,\n\t0xA1, 0x41, 0xB1, 0x0E, 0xA2, 0x57, 0xB2, 0x0D, 0xA0, 0xB0, 0xB0, 0x11, 0xA4, 0xB0, 0xB4, 0x11,\n\t0x00, 0x05, 0x43, 0x80, 0xA0, 0xB0, 0xB0, 0x31, 0x4C, 0x80, 0xA4, 0x81, 0xB4, 0x31, 0x44, 0x80,\n\t0xA1, 0x20, 0xB1, 0x2E, 0x00, 0x05, 0x45, 0x80, 0xA2, 0x87, 0xB2, 0x2A, 0x01, 0xB3, 0x01, 0xA0,\n\t0xB0, 0xB0, 0x11, 0xA4, 0x81, 0xB4, 0x11, 0x43, 0x80, 0xA0, 0xB0, 0xB0, 0x31, 0x4C, 0x80, 0x00,\n\t0x05, 0xA4, 0x81, 0xB4, 0x31, 0x01, 0xAE, 0x01, 0xA1, 0x20, 0xB1, 0x0E, 0xA2, 0x87, 0xB2, 0x0A,\n\t0xA0, 0xB0, 0xB0, 0x11, 0xA4, 0x81, 0xB4, 0x11, 0x00, 0x05, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32,\n\t0x4C, 0x80, 0xA4, 0xB0, 0xB4, 0x31, 0x2A, 0xB2, 0x2D, 0xB1, 0x00, 0x05, 0x4A, 0xCD, 0x6A, 0x91,\n\t0x6D, 0x91, 0x8A, 0x2A, 0x8D, 0x2A, 0xEA, 0x00, 0xED, 0x00, 0xC5, 0x00, 0x4D, 0x80, 0x00, 0x05,\n\t0xA5, 0x57, 0xB5, 0x31, 0x44, 0x80, 0xA1, 0x41, 0xB1, 0x2A, 0x01, 0xB8, 0x01, 0xA1, 0x41, 0xB1,\n\t0x0A, 0x44, 0x80, 0xA1, 0xB0, 0xB1, 0x2D, 0x01, 0xBF, 0x01, 0xA1, 0xB0, 0xB1, 0x0D, 0x44, 0x80,\n\t0xA1, 0x41, 0xB1, 0x2E, 0x01, 0xB4, 0x01, 0xA0, 0x41, 0xB0, 0x12, 0xA4, 0xB0, 0xB4, 0x11, 0xA5,\n\t0x57, 0xB5, 0x11, 0xA1, 0x41, 0xB1, 0x0E, 0x00, 0x05, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x00,\n\t0xDE, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x87, 0xB0, 0x32, 0x00, 0xDA, 0xA0, 0x87, 0xB0,\n\t0x12, 0x43, 0x80, 0xA0, 0x57, 0xB0, 0x35, 0x4C, 0x80, 0xA4, 0xE5, 0xB4, 0x31, 0x00, 0x05, 0x4D,\n\t0x80, 0xA5, 0xB0, 0xB5, 0x31, 0x44, 0x80, 0xA1, 0x41, 0xB1, 0x2A, 0x01, 0xB9, 0x01, 0xA0, 0x57,\n\t0xB0, 0x15, 0x43, 0x80, 0xA0, 0x57, 0xB0, 0x35, 0x01, 0xB4, 0x01, 0xA4, 0xE5, 0xB4, 0x11, 0xA5,\n\t0xB0, 0xB5, 0x11, 0xA1, 0x41, 0xB1, 0x0A, 0xA0, 0x57, 0xB0, 0x15, 0x00, 0x05, 0x43, 0x80, 0xA0,\n\t0x57, 0xB0, 0x35, 0x4C, 0x80, 0xA4, 0xE5, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0xB0, 0x00, 0x05, 0xB5,\n\t0x31, 0x44, 0x80, 0xA1, 0x81, 0xB1, 0x2D, 0x00, 0xD8, 0xA0, 0x57, 0xB0, 0x15, 0xA4, 0xE5, 0xB4,\n\t0x11, 0xA5, 0xB0, 0xB5, 0x11, 0x43, 0x80, 0xA0, 0x87, 0x00, 0x05, 0xB0, 0x32, 0x4C, 0x80, 0xA4,\n\t0xE5, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x81, 0xB5, 0x31, 0x01, 0xAF, 0x01, 0xA0, 0x87, 0xB0, 0x12,\n\t0xA4, 0xE5, 0xB4, 0x11, 0xA5, 0x81, 0xB5, 0x11, 0x43, 0x80, 0xA0, 0x41, 0x00, 0x05, 0xB0, 0x32,\n\t0x4C, 0x80, 0xA4, 0xE5, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x57, 0xB5, 0x31, 0x00, 0xDE, 0xA1, 0x81,\n\t0xB1, 0x0D, 0xA0, 0x41, 0xB0, 0x12, 0xA4, 0xE5, 0xB4, 0x11, 0xA5, 0x57, 0xB5, 0x11, 0x00, 0x05,\n\t0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x4C, 0x80, 0xA4, 0xCA, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x57,\n\t0xB5, 0x31, 0x00, 0x05, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xA8, 0x01, 0xA5, 0x57, 0xB5,\n\t0x11, 0x4D, 0x80, 0xA5, 0x41, 0xB5, 0x2E, 0x01, 0xBF, 0x01, 0xA1, 0x02, 0xB1, 0x0A, 0xA5, 0x41,\n\t0xB5, 0x0E, 0x4D, 0x80, 0xA5, 0x87, 0xB5, 0x2E, 0x44, 0x80, 0x00, 0x05, 0xA1, 0x02, 0xB1, 0x2A,\n\t0x45, 0x80, 0xA2, 0xCA, 0xB2, 0x2D, 0x01, 0x6F, 0x03, 0xA0, 0x02, 0xB0, 0x12, 0xA4, 0xCA, 0xB4,\n\t0x11, 0xA5, 0x87, 0xB5, 0x0E, 0xA1, 0x02, 0xB1, 0x0A, 0xA2, 0xCA, 0x00, 0x05, 0xB2, 0x0D, 0x43,\n\t0x80, 0xA0, 0x02, 0xB0, 0x32, 0x4C, 0x80, 0xA4, 0xB0, 0xB4, 0x31, 0x44, 0x80, 0x00, 0x05, 0xA1,\n\t0x57, 0xB1, 0x2D, 0x00, 0xD8, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x00,\n\t0xDA, 0xA4, 0xB0, 0xB4, 0x11, 0xA1, 0x57, 0xB1, 0x0D, 0x00, 0xD9, 0xA0, 0x41, 0xB0, 0x12, 0x43,\n\t0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0xE4, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0xB0, 0xB0,\n\t0x31, 0x4C, 0x80, 0xA4, 0x57, 0xB4, 0x31, 0x00, 0x05, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01,\n\t0xAF, 0x01, 0xA0, 0xB0, 0xB0, 0x11, 0xA4, 0x57, 0xB4, 0x11, 0xA1, 0x02, 0xB1, 0x0A, 0x43, 0x80,\n\t0xA0, 0x57, 0x00, 0x05, 0xB0, 0x35, 0x01, 0xB9, 0x01, 0xA0, 0x57, 0xB0, 0x15, 0x43, 0x80, 0xA0,\n\t0x41, 0xB0, 0x32, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x2D, 0x01, 0xBF, 0x01, 0xA0, 0x41, 0xB0, 0x12,\n\t0xA1, 0x57, 0xB1, 0x0D, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x4C, 0x80, 0xA4, 0xB0, 0x00, 0x05,\n\t0xB4, 0x31, 0x01, 0xAE, 0x01, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xBF, 0x01, 0xA4, 0xB0,\n\t0xB4, 0x11, 0xA1, 0x02, 0xB1, 0x0A, 0x4C, 0x80, 0xA4, 0xB0, 0xB4, 0x31, 0x01, 0xBF, 0x01, 0xA0,\n\t0x02, 0xB0, 0x12, 0xA4, 0xB0, 0xB4, 0x11, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x4C, 0x80, 0x00,\n\t0x05, 0xA4, 0xB0, 0xB4, 0x31, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x2D, 0x00, 0xD4, 0xA0, 0x02, 0xB0,\n\t0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x00, 0xD9, 0xA1, 0x57, 0xB1, 0x0D, 0xA0, 0x41, 0xB0,\n\t0x12, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0xE5, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0,\n\t0x41, 0xB0, 0x32, 0x00, 0xD9, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x44,\n\t0x80, 0xA1, 0x57, 0xB1, 0x31, 0x00, 0x05, 0x45, 0x80, 0xA2, 0xB0, 0xB2, 0x2D, 0x01, 0xB9, 0x01,\n\t0xA4, 0xB0, 0xB4, 0x11, 0xA0, 0x02, 0xB0, 0x12, 0xA2, 0xB0, 0xB2, 0x0D, 0x43, 0x80, 0xA0, 0x57,\n\t0x00, 0x05, 0xB0, 0x35, 0x4C, 0x80, 0xA4, 0xE5, 0xB4, 0x31, 0x45, 0x80, 0xA2, 0x98, 0xB2, 0x2D,\n\t0x01, 0xAF, 0x01, 0xA1, 0x57, 0xB1, 0x11, 0xA0, 0x57, 0xB0, 0x15, 0xA4, 0xE5, 0xB4, 0x11, 0xA2,\n\t0x98, 0xB2, 0x0D, 0x43, 0x80, 0x00, 0x05, 0xA0, 0x87, 0xB0, 0x32, 0x44, 0x80, 0xA1, 0x81, 0xB1,\n\t0x2D, 0x01, 0xB9, 0x01, 0xA1, 0x81, 0xB1, 0x0D, 0x4C, 0x80, 0xA4, 0x02, 0xB4, 0x32, 0x4D, 0x80,\n\t0xA5, 0xCA, 0xB5, 0x31, 0x01, 0xBE, 0x01, 0xA4, 0x02, 0xB4, 0x12, 0xA5, 0xCA, 0xB5, 0x11, 0x44,\n\t0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xB5, 0x01, 0xA1, 0x02, 0xB1, 0x0A, 0x4C, 0x80, 0xA4, 0x02,\n\t0xB4, 0x32, 0x4D, 0x80, 0xA5, 0xCA, 0xB5, 0x31, 0x01, 0xBF, 0x01, 0xA0, 0x87, 0xB0, 0x12, 0xA4,\n\t0x02, 0xB4, 0x12, 0xA5, 0xCA, 0xB5, 0x11, 0x43, 0x80, 0xA0, 0xCA, 0xB0, 0x31, 0x00, 0x05, 0x4C,\n\t0x80, 0xA4, 0x57, 0xB4, 0x31, 0x44, 0x80, 0xA1, 0x81, 0xB1, 0x2D, 0x00, 0xD3, 0xA0, 0xCA, 0xB0,\n\t0x11, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0xE5, 0xA4, 0x57, 0xB4, 0x11, 0xA1, 0x81, 0xB1,\n\t0x0D, 0x00, 0xD9, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0xCA, 0xB0, 0x31, 0x00, 0xDA, 0xA0,\n\t0xCA, 0xB0, 0x11, 0x43, 0x80, 0xA0, 0x81, 0xB0, 0x31, 0x4C, 0x80, 0xA4, 0x87, 0xB4, 0x2E, 0x00,\n\t0x05, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xB9, 0x01, 0xA0, 0x81, 0xB0, 0x11, 0xA4, 0x87,\n\t0xB4, 0x0E, 0xA1, 0x02, 0xB1, 0x0A, 0x43, 0x80, 0xA0, 0x87, 0x00, 0x05, 0xB0, 0x32, 0x01, 0xB9,\n\t0x01, 0xA0, 0x87, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x44, 0x80, 0xA1, 0x81, 0xB1,\n\t0x2D, 0x01, 0xB4, 0x01, 0xA0, 0x41, 0xB0, 0x12, 0xA1, 0x81, 0xB1, 0x0D, 0x43, 0x80, 0xA0, 0x02,\n\t0xB0, 0x32, 0x4C, 0x80, 0x00, 0x05, 0xA4, 0xCA, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x87, 0xB5, 0x2E,\n\t0x01, 0xB9, 0x01, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xBF, 0x01, 0xA1, 0x02, 0xB1, 0x0A,\n\t0x01, 0xB5, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0xA4, 0xCA, 0xB4, 0x11, 0xA5, 0x87, 0xB5, 0x0E, 0x43,\n\t0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0x05, 0x4C, 0x80, 0xA4, 0xCA, 0xB4, 0x31, 0x4D, 0x80, 0xA5,\n\t0x57, 0xB5, 0x31, 0x44, 0x80, 0xA1, 0x81, 0x00, 0x05, 0xB1, 0x2D, 0x00, 0xD8, 0xA0, 0x02, 0xB0,\n\t0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x00, 0xD9, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0,\n\t0x02, 0xB0, 0x32, 0x00, 0xDA, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x00,\n\t0xE4, 0xA4, 0xCA, 0xB4, 0x11, 0xA5, 0x57, 0xB5, 0x11, 0xA1, 0x81, 0xB1, 0x0D, 0xA0, 0x41, 0xB0,\n\t0x12, 0x00, 0x05, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x4C, 0x80, 0xA4, 0x98, 0xB4, 0x31, 0x4D,\n\t0x80, 0xA5, 0x87, 0x00, 0x05, 0xB5, 0x2E, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xA9, 0x01,\n\t0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x01, 0xBF, 0x01, 0xA4, 0x98, 0xB4,\n\t0x11, 0xA5, 0x87, 0xB5, 0x0E, 0xA1, 0x02, 0xB1, 0x0A, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0x00,\n\t0x05, 0xA0, 0xB0, 0xB0, 0x31, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x2D, 0x01, 0xB9, 0x01, 0xA1, 0x57,\n\t0xB1, 0x0D, 0x4C, 0x80, 0xA4, 0x57, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x41, 0xB5, 0x2E, 0x01, 0xB4,\n\t0x01, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xBF, 0x01, 0xA4, 0x57, 0xB4, 0x11, 0xA5, 0x41,\n\t0xB5, 0x0E, 0xA1, 0x02, 0xB1, 0x0A, 0x4C, 0x80, 0xA4, 0x57, 0x00, 0x05, 0xB4, 0x31, 0x4D, 0x80,\n\t0xA5, 0x41, 0xB5, 0x2E, 0x01, 0xB9, 0x01, 0xA0, 0xB0, 0xB0, 0x11, 0xA4, 0x57, 0xB4, 0x11, 0xA5,\n\t0x41, 0xB5, 0x0E, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0x05, 0x4C, 0x80, 0xA4, 0xB0, 0xB4,\n\t0x31, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x2D, 0x00, 0xD3, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0,\n\t0x41, 0xB0, 0x32, 0x00, 0xDA, 0xA4, 0xB0, 0xB4, 0x11, 0xA1, 0x57, 0xB1, 0x0D, 0x00, 0xE4, 0xA0,\n\t0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0xDA, 0xA0, 0x02, 0xB0, 0x12, 0x43,\n\t0x80, 0xA0, 0xB0, 0xB0, 0x31, 0x4C, 0x80, 0xA4, 0x57, 0xB4, 0x31, 0x00, 0x05, 0x44, 0x80, 0xA1,\n\t0x02, 0xB1, 0x2A, 0x01, 0xB9, 0x01, 0xA0, 0xB0, 0xB0, 0x11, 0xA4, 0x57, 0xB4, 0x11, 0xA1, 0x02,\n\t0xB1, 0x0A, 0x43, 0x80, 0xA0, 0x57, 0x00, 0x05, 0xB0, 0x35, 0x01, 0xAE, 0x01, 0xA0, 0x57, 0xB0,\n\t0x15, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x2D, 0x01, 0xBF, 0x01,\n\t0xA0, 0x41, 0xB0, 0x12, 0xA1, 0x57, 0xB1, 0x0D, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x4C, 0x80,\n\t0x00, 0x05, 0xA4, 0xB0, 0xB4, 0x31, 0x01, 0xB9, 0x01, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01,\n\t0xB5, 0x01, 0xA4, 0xB0, 0xB4, 0x11, 0xA1, 0x02, 0xB1, 0x0A, 0x4C, 0x80, 0xA4, 0xB0, 0xB4, 0x31,\n\t0x01, 0xBF, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0xA4, 0xB0, 0xB4, 0x11, 0x43, 0x80, 0xA0, 0x02, 0xB0,\n\t0x32, 0x4C, 0x80, 0xA4, 0xB0, 0x00, 0x05, 0xB4, 0x31, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x2D, 0x00,\n\t0xD3, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x00, 0xE4, 0xA1, 0x57, 0xB1,\n\t0x0D, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0xDA, 0xA0, 0x02, 0xB0,\n\t0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x00, 0xDA, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0,\n\t0x02, 0xB0, 0x32, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x31, 0x00, 0x05, 0x45, 0x80, 0xA2, 0xB0, 0xB2,\n\t0x2D, 0x01, 0xB9, 0x01, 0xA4, 0xB0, 0xB4, 0x11, 0xA0, 0x02, 0xB0, 0x12, 0xA2, 0xB0, 0xB2, 0x0D,\n\t0x43, 0x80, 0xA0, 0x57, 0xB0, 0x35, 0x00, 0x05, 0x4C, 0x80, 0xA4, 0xE5, 0xB4, 0x31, 0x45, 0x80,\n\t0xA2, 0x98, 0xB2, 0x2D, 0x01, 0xB9, 0x01, 0xA1, 0x57, 0xB1, 0x11, 0xA0, 0x57, 0xB0, 0x15, 0xA4,\n\t0xE5, 0xB4, 0x11, 0xA2, 0x98, 0xB2, 0x0D, 0x43, 0x80, 0x00, 0x05, 0xA0, 0x87, 0xB0, 0x32, 0x44,\n\t0x80, 0xA1, 0x81, 0xB1, 0x2D, 0x01, 0xAE, 0x01, 0xA1, 0x81, 0xB1, 0x0D, 0x4C, 0x80, 0xA4, 0x02,\n\t0xB4, 0x32, 0x4D, 0x80, 0xA5, 0xCA, 0xB5, 0x31, 0x01, 0xBF, 0x01, 0xA4, 0x02, 0xB4, 0x12, 0xA5,\n\t0xCA, 0xB5, 0x11, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xBF, 0x01, 0xA1, 0x02, 0xB1, 0x0A,\n\t0x4C, 0x80, 0xA4, 0x02, 0xB4, 0x32, 0x4D, 0x80, 0xA5, 0xCA, 0xB5, 0x31, 0x01, 0xB4, 0x01, 0xA0,\n\t0x87, 0xB0, 0x12, 0xA4, 0x02, 0xB4, 0x12, 0xA5, 0xCA, 0xB5, 0x11, 0x43, 0x80, 0xA0, 0xCA, 0x00,\n\t0x05, 0xB0, 0x31, 0x4C, 0x80, 0xA4, 0x57, 0xB4, 0x31, 0x44, 0x80, 0xA1, 0x81, 0xB1, 0x2D, 0x00,\n\t0xDF, 0xA0, 0xCA, 0xB0, 0x11, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0xD9, 0xA4, 0x57, 0xB4,\n\t0x11, 0xA1, 0x81, 0xB1, 0x0D, 0x00, 0xDA, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0xCA, 0xB0,\n\t0x31, 0x00, 0xE4, 0xA0, 0xCA, 0xB0, 0x11, 0x43, 0x80, 0xA0, 0x81, 0xB0, 0x31, 0x4C, 0x80, 0xA4,\n\t0x87, 0xB4, 0x2E, 0x00, 0x05, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xAF, 0x01, 0xA0, 0x81,\n\t0xB0, 0x11, 0xA4, 0x87, 0xB4, 0x0E, 0xA1, 0x02, 0xB1, 0x0A, 0x43, 0x80, 0xA0, 0x87, 0xB0, 0x32,\n\t0x01, 0xBE, 0x01, 0xA0, 0x87, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x44, 0x80, 0xA1,\n\t0x81, 0xB1, 0x2D, 0x01, 0xBF, 0x01, 0xA0, 0x41, 0xB0, 0x12, 0xA1, 0x81, 0xB1, 0x0D, 0x43, 0x80,\n\t0xA0, 0x02, 0xB0, 0x32, 0x4C, 0x80, 0x00, 0x05, 0xA4, 0xCA, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x87,\n\t0xB5, 0x2E, 0x01, 0xAF, 0x01, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xBF, 0x01, 0xA1, 0x02,\n\t0xB1, 0x0A, 0x01, 0xBF, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0xA4, 0xCA, 0xB4, 0x11, 0xA5, 0x87, 0xB5,\n\t0x0E, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0x05, 0x4C, 0x80, 0xA4, 0xCA, 0xB4, 0x31, 0x4D,\n\t0x80, 0xA5, 0x57, 0xB5, 0x31, 0x44, 0x80, 0xA1, 0x81, 0x00, 0x05, 0xB1, 0x2D, 0x00, 0xCD, 0xA0,\n\t0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x00, 0xDA, 0xA0, 0x41, 0xB0, 0x12, 0x43,\n\t0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0xE4, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0,\n\t0x32, 0x00, 0xDA, 0xA4, 0xCA, 0xB4, 0x11, 0xA5, 0x57, 0xB5, 0x11, 0xA1, 0x81, 0xB1, 0x0D, 0xA0,\n\t0x41, 0xB0, 0x12, 0x00, 0x05, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x4C, 0x80, 0xA4, 0xCA, 0xB4,\n\t0x31, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xB9, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0xA4, 0xCA,\n\t0xB4, 0x11, 0xA1, 0x02, 0xB1, 0x0A, 0x43, 0x80, 0xA0, 0x81, 0xB0, 0x35, 0x01, 0xB4, 0x01, 0xA0,\n\t0x81, 0xB0, 0x15, 0x43, 0x80, 0xA0, 0x57, 0xB0, 0x35, 0x01, 0xBF, 0x01, 0x4C, 0x80, 0xA4, 0xB0,\n\t0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x87, 0xB5, 0x2E, 0x44, 0x80, 0xA1, 0x57, 0x00, 0x05, 0xB1, 0x2D,\n\t0x01, 0xB9, 0x01, 0xA4, 0xB0, 0xB4, 0x11, 0xA5, 0x87, 0xB5, 0x0E, 0xA1, 0x57, 0xB1, 0x0D, 0x4C,\n\t0x80, 0xA4, 0xCA, 0x00, 0x05, 0xB4, 0x31, 0x44, 0x80, 0xA1, 0x81, 0xB1, 0x2D, 0x01, 0xAF, 0x01,\n\t0xA4, 0xCA, 0xB4, 0x11, 0xA1, 0x81, 0xB1, 0x0D, 0x4C, 0x80, 0xA4, 0x02, 0xB4, 0x32, 0x44, 0x80,\n\t0xA1, 0xB0, 0x00, 0x05, 0xB1, 0x2D, 0x01, 0xB8, 0x01, 0xA0, 0x57, 0xB0, 0x15, 0xA4, 0x02, 0xB4,\n\t0x12, 0xA1, 0xB0, 0xB1, 0x0D, 0x43, 0x80, 0xA0, 0x41, 0x00, 0x05, 0xB0, 0x32, 0x4C, 0x80, 0xA4,\n\t0x02, 0xB4, 0x32, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x31, 0x45, 0x80, 0x00, 0x05, 0xA2, 0xCA, 0xB2,\n\t0x2D, 0x01, 0xB3, 0x01, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x01, 0xB5,\n\t0x01, 0xA4, 0x02, 0xB4, 0x12, 0xA1, 0x57, 0xB1, 0x11, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0,\n\t0x57, 0xB0, 0x35, 0x00, 0x05, 0x4C, 0x80, 0xA4, 0xCA, 0xB4, 0x31, 0x44, 0x80, 0xA1, 0x81, 0xB1,\n\t0x31, 0x01, 0xB9, 0x01, 0xA0, 0x57, 0xB0, 0x15, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x01, 0xBF,\n\t0x01, 0xA2, 0xCA, 0xB2, 0x0D, 0xA4, 0xCA, 0xB4, 0x11, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0,\n\t0x02, 0xB0, 0x32, 0x00, 0x05, 0x45, 0x80, 0xA2, 0xB0, 0xB2, 0x2D, 0x01, 0xAE, 0x01, 0xA0, 0x02,\n\t0xB0, 0x12, 0x43, 0x80, 0xA0, 0xB0, 0xB0, 0x31, 0x01, 0xBF, 0x01, 0xA1, 0x81, 0xB1, 0x11, 0xA0,\n\t0xB0, 0xB0, 0x11, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x44, 0x80, 0xA1, 0x6B, 0x00, 0x05, 0xB1,\n\t0x31, 0x01, 0x93, 0x02, 0x4C, 0x80, 0xA4, 0xB0, 0xB4, 0x31, 0x00, 0xDA, 0xA2, 0xB0, 0xB2, 0x0D,\n\t0xA0, 0x02, 0xB0, 0x12, 0xA1, 0x6B, 0xB1, 0x11, 0xA4, 0xB0, 0xB4, 0x11, 0x00, 0x05, 0x43, 0x80,\n\t0xA0, 0xCA, 0xB0, 0x31, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x31, 0x45, 0x80, 0xA2, 0x81, 0xB2, 0x2D,\n\t0x01, 0xB9, 0x01, 0xA0, 0xCA, 0xB0, 0x11, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x01, 0xBF, 0x01,\n\t0xA1, 0x57, 0xB1, 0x11, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x44, 0x80,\n\t0x00, 0x05, 0xA1, 0x87, 0xB1, 0x2E, 0x01, 0xAE, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0,\n\t0xCA, 0xB0, 0x31, 0x01, 0xBF, 0x01, 0xA2, 0x81, 0xB2, 0x0D, 0xA1, 0x87, 0xB1, 0x0E, 0xA0, 0xCA,\n\t0xB0, 0x11, 0x43, 0x80, 0xA0, 0xB0, 0x00, 0x05, 0xB0, 0x31, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2E,\n\t0x45, 0x80, 0xA2, 0x57, 0xB2, 0x2D, 0x00, 0xD4, 0xA1, 0x02, 0xB1, 0x0E, 0x44, 0x80, 0xA1, 0x41,\n\t0xB1, 0x2E, 0x00, 0xE4, 0xA1, 0x41, 0xB1, 0x0E, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2E, 0x01, 0xB5,\n\t0x01, 0xA1, 0x02, 0xB1, 0x0E, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2E, 0x01, 0xBF, 0x01, 0xA2, 0x57,\n\t0xB2, 0x0D, 0xA1, 0x02, 0xB1, 0x0E, 0x44, 0x80, 0xA1, 0x63, 0xB1, 0x2E, 0x45, 0x80, 0xA2, 0x6B,\n\t0x00, 0x05, 0xB2, 0x2D, 0x01, 0xB8, 0x01, 0xA0, 0xB0, 0xB0, 0x11, 0xA1, 0x63, 0xB1, 0x0E, 0xA2,\n\t0x6B, 0xB2, 0x0D, 0x43, 0x80, 0xA0, 0x81, 0x00, 0x05, 0xB0, 0x31, 0x44, 0x80, 0xA1, 0x87, 0xB1,\n\t0x2E, 0x45, 0x80, 0xA2, 0x02, 0xB2, 0x2E, 0x01, 0xAF, 0x01, 0xA0, 0x81, 0xB0, 0x11, 0x43, 0x80,\n\t0xA0, 0xB0, 0xB0, 0x31, 0x01, 0xBF, 0x01, 0xA0, 0xB0, 0xB0, 0x11, 0x43, 0x80, 0xA0, 0x02, 0xB0,\n\t0x32, 0x01, 0xBF, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x01, 0xB4,\n\t0x01, 0xA1, 0x87, 0xB1, 0x0E, 0xA2, 0x02, 0xB2, 0x0E, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0,\n\t0x87, 0x00, 0x05, 0xB0, 0x32, 0x4C, 0x80, 0xA4, 0xB0, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x81, 0xB5,\n\t0x31, 0x44, 0x80, 0xA1, 0x02, 0x00, 0x05, 0xB1, 0x2E, 0x01, 0xB3, 0x01, 0xA0, 0x87, 0xB0, 0x12,\n\t0xA4, 0xB0, 0xB4, 0x11, 0xA5, 0x81, 0xB5, 0x11, 0xA1, 0x02, 0xB1, 0x0E, 0x00, 0x05, 0x43, 0x80,\n\t0xA0, 0x87, 0xB0, 0x32, 0x4C, 0x80, 0xA4, 0xB0, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x81, 0xB5, 0x31,\n\t0x00, 0x05, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2E, 0x01, 0xB3, 0x01, 0xA0, 0x87, 0xB0, 0x12, 0xA4,\n\t0xB0, 0xB4, 0x11, 0xA5, 0x81, 0xB5, 0x11, 0xA1, 0x02, 0xB1, 0x0E, 0x00, 0x05, 0x43, 0x80, 0xA0,\n\t0x87, 0xB0, 0x32, 0x4C, 0x80, 0xA4, 0xCA, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x81, 0xB5, 0x31, 0x00,\n\t0x05, 0x44, 0x80, 0xA1, 0x20, 0xB1, 0x2E, 0x01, 0xA8, 0x01, 0xA1, 0x20, 0xB1, 0x0E, 0x44, 0x80,\n\t0xA1, 0xB0, 0xB1, 0x2D, 0x01, 0xBF, 0x01, 0xA0, 0x87, 0xB0, 0x12, 0xA4, 0xCA, 0xB4, 0x11, 0xA5,\n\t0x81, 0xB5, 0x11, 0xA1, 0xB0, 0xB1, 0x0D, 0x00, 0x05, 0x43, 0x80, 0xA0, 0x57, 0xB0, 0x35, 0x4C,\n\t0x80, 0xA4, 0x02, 0xB4, 0x32, 0x4D, 0x80, 0xA5, 0xB0, 0x00, 0x05, 0xB5, 0x31, 0x44, 0x80, 0xA1,\n\t0x41, 0xB1, 0x2E, 0x01, 0xB3, 0x01, 0xA0, 0x57, 0xB0, 0x15, 0xA4, 0x02, 0xB4, 0x12, 0xA5, 0xB0,\n\t0xB5, 0x11, 0xA1, 0x41, 0xB1, 0x0E, 0x00, 0x05, 0x43, 0x80, 0xA0, 0x57, 0xB0, 0x35, 0x4C, 0x80,\n\t0xA4, 0x02, 0xB4, 0x32, 0x4D, 0x80, 0xA5, 0xB0, 0xB5, 0x31, 0x01, 0xAF, 0x01, 0xA0, 0x57, 0xB0,\n\t0x15, 0xA4, 0x02, 0xB4, 0x12, 0xA5, 0xB0, 0xB5, 0x11, 0x43, 0x80, 0xA0, 0x87, 0xB0, 0x32, 0x00,\n\t0x05, 0x4C, 0x80, 0xA4, 0xE5, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x81, 0xB5, 0x31, 0x44, 0x80, 0xA1,\n\t0x81, 0x00, 0x05, 0xB1, 0x2D, 0x01, 0xB2, 0x01, 0xA0, 0x87, 0xB0, 0x12, 0xA4, 0xE5, 0xB4, 0x11,\n\t0xA5, 0x81, 0xB5, 0x11, 0x43, 0x80, 0xA0, 0x41, 0x00, 0x05, 0xB0, 0x32, 0x4C, 0x80, 0xA4, 0xE5,\n\t0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x57, 0xB5, 0x31, 0x01, 0xB9, 0x01, 0xA1, 0x81, 0xB1, 0x0D, 0xA0,\n\t0x41, 0xB0, 0x12, 0xA4, 0xE5, 0xB4, 0x11, 0xA5, 0x57, 0xB5, 0x11, 0x00, 0x05, 0x43, 0x80, 0xA0,\n\t0x02, 0xB0, 0x32, 0x4C, 0x80, 0xA4, 0x57, 0xB4, 0x31, 0x44, 0x80, 0xA1, 0xCA, 0x00, 0x05, 0xB1,\n\t0x2D, 0x45, 0x80, 0xA2, 0x81, 0xB2, 0x2D, 0x01, 0xA9, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0xA4, 0x57,\n\t0xB4, 0x11, 0xA1, 0xCA, 0xB1, 0x0D, 0xA2, 0x81, 0xB2, 0x0D, 0x43, 0x80, 0x00, 0x05, 0xA0, 0xCA,\n\t0xB0, 0x31, 0x00, 0xDE, 0xA0, 0xCA, 0xB0, 0x11, 0x43, 0x80, 0xA0, 0x81, 0xB0, 0x31, 0x4C, 0x80,\n\t0xA4, 0x87, 0xB4, 0x2E, 0x00, 0x05, 0x44, 0x80, 0xA1, 0xCA, 0xB1, 0x2D, 0x45, 0x80, 0xA2, 0x02,\n\t0xB2, 0x2A, 0x01, 0x94, 0x02, 0xA0, 0x81, 0xB0, 0x11, 0xA4, 0x87, 0xB4, 0x0E, 0xA1, 0xCA, 0xB1,\n\t0x0D, 0xA2, 0x02, 0xB2, 0x0A, 0x44, 0x80, 0x00, 0x05, 0xA1, 0x02, 0xB1, 0x2E, 0x01, 0xAE, 0x01,\n\t0xA1, 0x02, 0xB1, 0x0E, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x4C, 0x80, 0xA4, 0xB0, 0xB4, 0x31,\n\t0x00, 0x05, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x2D, 0x00, 0xDE, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80,\n\t0xA0, 0x41, 0xB0, 0x32, 0x00, 0xDA, 0xA4, 0xB0, 0xB4, 0x11, 0xA1, 0x57, 0xB1, 0x0D, 0x00, 0xDA,\n\t0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0xE4, 0xA0, 0x02, 0xB0, 0x12,\n\t0x43, 0x80, 0xA0, 0xB0, 0xB0, 0x31, 0x4C, 0x80, 0xA4, 0x57, 0xB4, 0x31, 0x44, 0x80, 0x00, 0x05,\n\t0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xAE, 0x01, 0xA0, 0xB0, 0xB0, 0x11, 0xA4, 0x57, 0xB4, 0x11, 0xA1,\n\t0x02, 0xB1, 0x0A, 0x43, 0x80, 0xA0, 0x57, 0x00, 0x05, 0xB0, 0x35, 0x01, 0xB9, 0x01, 0xA0, 0x57,\n\t0xB0, 0x15, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x2D, 0x01, 0xBF,\n\t0x01, 0xA0, 0x41, 0xB0, 0x12, 0xA1, 0x57, 0xB1, 0x0D, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x4C,\n\t0x80, 0x00, 0x05, 0xA4, 0xB0, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x81, 0xB5, 0x31, 0x01, 0xAE, 0x01,\n\t0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xBF, 0x01, 0xA4, 0xB0, 0xB4, 0x11, 0xA1, 0x02, 0xB1,\n\t0x0A, 0x4C, 0x80, 0xA4, 0xB0, 0xB4, 0x31, 0x01, 0xBF, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0xA5, 0x81,\n\t0xB5, 0x11, 0xA4, 0xB0, 0xB4, 0x11, 0x43, 0x80, 0xA0, 0x02, 0x00, 0x05, 0xB0, 0x32, 0x4C, 0x80,\n\t0xA4, 0xB0, 0xB4, 0x31, 0x44, 0x80, 0xA1, 0x57, 0xB1, 0x2D, 0x00, 0xD4, 0xA0, 0x02, 0xB0, 0x12,\n\t0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x00, 0xDA, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x02,\n\t0xB0, 0x32, 0x00, 0xE4, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x00, 0xDA,\n\t0xA1, 0x57, 0xB1, 0x0D, 0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x44, 0x80,\n\t0xA1, 0x57, 0x00, 0x05, 0xB1, 0x31, 0x45, 0x80, 0xA2, 0xB0, 0xB2, 0x2D, 0x01, 0xB8, 0x01, 0xA4,\n\t0xB0, 0xB4, 0x11, 0xA0, 0x02, 0xB0, 0x12, 0xA2, 0xB0, 0xB2, 0x0D, 0x43, 0x80, 0xA0, 0x57, 0x00,\n\t0x05, 0xB0, 0x35, 0x4C, 0x80, 0xA4, 0xE5, 0xB4, 0x31, 0x45, 0x80, 0xA2, 0x98, 0xB2, 0x2D, 0x01,\n\t0xAF, 0x01, 0xA1, 0x57, 0xB1, 0x11, 0xA0, 0x57, 0xB0, 0x15, 0xA4, 0xE5, 0xB4, 0x11, 0xA2, 0x98,\n\t0xB2, 0x0D, 0x00, 0x05, 0x43, 0x80, 0xA0, 0x87, 0xB0, 0x32, 0x44, 0x80, 0xA1, 0x81, 0xB1, 0x2D,\n\t0x01, 0xB9, 0x01, 0xA1, 0x81, 0xB1, 0x0D, 0x4C, 0x80, 0xA4, 0x02, 0xB4, 0x32, 0x4D, 0x80, 0xA5,\n\t0x87, 0xB5, 0x2E, 0x01, 0xBF, 0x01, 0xA4, 0x02, 0xB4, 0x12, 0xA5, 0x87, 0xB5, 0x0E, 0x44, 0x80,\n\t0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xB4, 0x01, 0xA1, 0x02, 0xB1, 0x0A, 0x4C, 0x80, 0xA4, 0x02, 0xB4,\n\t0x32, 0x4D, 0x80, 0xA5, 0x87, 0xB5, 0x2E, 0x01, 0xBF, 0x01, 0xA0, 0x87, 0xB0, 0x12, 0xA4, 0x02,\n\t0xB4, 0x12, 0xA5, 0x87, 0xB5, 0x0E, 0x43, 0x80, 0xA0, 0xCA, 0x00, 0x05, 0xB0, 0x31, 0x4C, 0x80,\n\t0xA4, 0x57, 0xB4, 0x31, 0x44, 0x80, 0xA1, 0x81, 0xB1, 0x2D, 0x00, 0xD4, 0xA0, 0xCA, 0xB0, 0x11,\n\t0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0xE4, 0xA4, 0x57, 0xB4, 0x11, 0xA1, 0x81, 0xB1, 0x0D,\n\t0x00, 0xDA, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0xCA, 0xB0, 0x31, 0x00, 0xD9, 0xA0, 0xCA,\n\t0xB0, 0x11, 0x43, 0x80, 0xA0, 0x81, 0xB0, 0x31, 0x4C, 0x80, 0xA4, 0x87, 0xB4, 0x2E, 0x00, 0x05,\n\t0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xB9, 0x01, 0xA0, 0x81, 0xB0, 0x11, 0xA4, 0x87, 0xB4,\n\t0x0E, 0xA1, 0x02, 0xB1, 0x0A, 0x43, 0x80, 0xA0, 0x87, 0x00, 0x05, 0xB0, 0x32, 0x01, 0xB9, 0x01,\n\t0xA0, 0x87, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x44, 0x80, 0xA1, 0x81, 0xB1, 0x2D,\n\t0x01, 0xB5, 0x01, 0xA0, 0x41, 0xB0, 0x12, 0xA1, 0x81, 0xB1, 0x0D, 0x43, 0x80, 0xA0, 0x02, 0xB0,\n\t0x32, 0x4C, 0x80, 0xA4, 0xCA, 0x00, 0x05, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x87, 0xB5, 0x2E, 0x01,\n\t0xB9, 0x01, 0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0xBE, 0x01, 0xA4, 0xCA, 0xB4, 0x11, 0xA5,\n\t0x87, 0xB5, 0x0E, 0xA1, 0x02, 0xB1, 0x0A, 0x4C, 0x80, 0xA4, 0xCA, 0x00, 0x05, 0xB4, 0x31, 0x4D,\n\t0x80, 0xA5, 0x87, 0xB5, 0x2E, 0x01, 0xAF, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0xA4, 0xCA, 0xB4, 0x11,\n\t0xA5, 0x87, 0xB5, 0x0E, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x00, 0x05, 0x4C, 0x80, 0xA4, 0xCA,\n\t0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x57, 0xB5, 0x31, 0x44, 0x80, 0xA1, 0x81, 0x00, 0x05, 0xB1, 0x2D,\n\t0x01, 0xB3, 0x01, 0xA0, 0x02, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x01, 0xBF, 0x01,\n\t0xA0, 0x41, 0xB0, 0x12, 0x43, 0x80, 0xA0, 0x02, 0xB0, 0x32, 0x01, 0xB4, 0x01, 0xA0, 0x02, 0xB0,\n\t0x12, 0x43, 0x80, 0xA0, 0x41, 0xB0, 0x32, 0x01, 0xBF, 0x01, 0xA4, 0xCA, 0xB4, 0x11, 0xA5, 0x57,\n\t0xB5, 0x11, 0xA1, 0x81, 0xB1, 0x0D, 0xA0, 0x41, 0xB0, 0x12, 0x00, 0x05, 0x43, 0x80, 0xA0, 0x02,\n\t0xB0, 0x32, 0x4C, 0x80, 0xA4, 0xCA, 0xB4, 0x31, 0x4D, 0x80, 0xA5, 0x87, 0xB5, 0x2E, 0x00, 0x05,\n\t0x44, 0x80, 0xA1, 0x02, 0xB1, 0x2A, 0x01, 0x68, 0x03, 0xA0, 0x02, 0xB0, 0x12, 0xA4, 0xCA, 0xB4,\n\t0x11, 0xA5, 0x87, 0xB5, 0x0E, 0x43, 0x80, 0xA0, 0x81, 0x00, 0x05, 0xB0, 0x35, 0x4C, 0x80, 0xA4,\n\t0x87, 0xB4, 0x32, 0x4D, 0x80, 0xA5, 0xCA, 0xB5, 0x31, 0x01, 0x79, 0x03, 0xA1, 0x02, 0xB1, 0x0A,\n\t0xA0, 0x81, 0xB0, 0x15, 0xA4, 0x87, 0xB4, 0x12, 0xA5, 0xCA, 0xB5, 0x11, 0x00, 0x05, 0x43, 0x80,\n\t0xA0, 0x57, 0xB0, 0x35, 0x4C, 0x80, 0xA4, 0x41, 0xB4, 0x32, 0x01, 0x2E, 0x05, 0xA0, 0x57, 0xB0,\n\t0x15, 0xA4, 0x41, 0xB4, 0x12, 0x85, 0x13, 0x84, 0x13, 0x83, 0x13, 0x82, 0x13, 0x00, 0x05, 0x81,\n\t0x13, 0x80, 0x13, 0xBD, 0xE0, 0x90, 0xFF, 0x91, 0xFF, 0x92, 0xFF, 0x93, 0xFF, 0x94, 0xFF, 0x95,\n\t0xFF};\n\n// clyde1_1.dro - Clyde's Adventure: Castle 1-3\nconst unsigned char clyde1_1_dro[0x1DF3] =\n{\t0x44, 0x42, 0x52, 0x41, 0x57, 0x4F, 0x50, 0x4C, 0x00, 0x00, 0x01, 0x00, 0xBC, 0xB7, 0x01, 0x00,\n\t0xDB, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x40, 0x4F, 0xC0, 0x06,\n\t0x60, 0xF1, 0x80, 0x51, 0x20, 0x01, 0xE0, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x41, 0x4F, 0xC1, 0x06,\n\t0x61, 0xF1, 0x81, 0x51, 0x21, 0x01, 0xE1, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x42, 0x4F, 0xC2, 0x06,\n\t0x62, 0xF1, 0x82, 0x51, 0x22, 0x01, 0xE2, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x43, 0x00, 0x63, 0xF1,\n\t0x83, 0x71, 0x23, 0x11, 0xE3, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x44, 0x00, 0x64, 0xF1, 0x84, 0x71,\n\t0x24, 0x11, 0xE4, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x45, 0x00, 0x65, 0xF1, 0x85, 0x71, 0x25, 0x11,\n\t0xE5, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x48, 0x4F, 0xC3, 0x06, 0x68, 0xF1, 0x88, 0x51, 0x28, 0x01,\n\t0xE8, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x49, 0x4F, 0xC4, 0x06, 0x69, 0xF1, 0x89, 0x51, 0x29, 0x01,\n\t0xE9, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x4A, 0x4F, 0xC5, 0x06, 0x6A, 0xF1, 0x8A, 0x51, 0x2A, 0x01,\n\t0xEA, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x4B, 0x00, 0x6B, 0xF1, 0x8B, 0x71, 0x2B, 0x11, 0xEB, 0x00,\n\t0xBD, 0x00, 0x08, 0x00, 0x4C, 0x00, 0x6C, 0xF1, 0x8C, 0x71, 0x2C, 0x11, 0xEC, 0x00, 0x10, 0x05,\n\t0xBD, 0x00, 0x08, 0x00, 0x4D, 0x00, 0x6D, 0xF1, 0x8D, 0x71, 0x2D, 0x11, 0xED, 0x00, 0xBD, 0x00,\n\t0x08, 0x00, 0x50, 0x4F, 0xC6, 0x06, 0x70, 0xF1, 0x90, 0x51, 0x30, 0x01, 0xF0, 0x00, 0xBD, 0x00,\n\t0x08, 0x00, 0x51, 0x4F, 0xC7, 0x06, 0x71, 0xF1, 0x91, 0x51, 0x31, 0x01, 0xF1, 0x00, 0xBD, 0x00,\n\t0x08, 0x00, 0x52, 0x4F, 0xC8, 0x06, 0x72, 0xF1, 0x92, 0x51, 0x32, 0x01, 0xF2, 0x00, 0xBD, 0x00,\n\t0x08, 0x00, 0x53, 0x00, 0x73, 0xF1, 0x93, 0x71, 0x33, 0x11, 0xF3, 0x00, 0xBD, 0x00, 0x08, 0x00,\n\t0x54, 0x00, 0x74, 0xF1, 0x94, 0x71, 0x34, 0x11, 0xF4, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x55, 0x00,\n\t0x75, 0xF1, 0x95, 0x71, 0x35, 0x11, 0xF5, 0x00, 0xBD, 0x00, 0xBD, 0x00, 0x08, 0x00, 0xA0, 0x00,\n\t0xB0, 0x00, 0xA1, 0x00, 0xB1, 0x00, 0xA2, 0x00, 0xB2, 0x00, 0xA3, 0x00, 0xB3, 0x00, 0xA4, 0x00,\n\t0xB4, 0x00, 0xA5, 0x00, 0xB5, 0x00, 0xA6, 0x00, 0xB6, 0x00, 0xA7, 0x00, 0xB7, 0x00, 0xA8, 0x00,\n\t0xB8, 0x00, 0xE0, 0x00, 0xE1, 0x00, 0xE2, 0x00, 0xE3, 0x00, 0xE4, 0x00, 0xE5, 0x00, 0xE8, 0x00,\n\t0xE9, 0x00, 0xEA, 0x00, 0xEB, 0x00, 0xEC, 0x00, 0xED, 0x00, 0xF0, 0x00, 0xF1, 0x00, 0xF2, 0x00,\n\t0xF3, 0x00, 0xF4, 0x00, 0xF5, 0x00, 0x04, 0x01, 0x20, 0x10, 0x31, 0xBD, 0x00, 0x08, 0x00, 0x40,\n\t0x4F, 0xC0, 0x06, 0x60, 0xF1, 0x80, 0x51, 0x20, 0x01, 0xE0, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x41,\n\t0x4F, 0xC1, 0x06, 0x61, 0xF1, 0x81, 0x51, 0x21, 0x01, 0xE1, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x42,\n\t0x4F, 0xC2, 0x06, 0x62, 0xF1, 0x82, 0x51, 0x22, 0x01, 0xE2, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x43,\n\t0x00, 0x63, 0xF1, 0x83, 0x71, 0x23, 0x11, 0xE3, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x44, 0x00, 0x64,\n\t0xF1, 0x84, 0x71, 0x24, 0x11, 0xE4, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x45, 0x00, 0x65, 0xF1, 0x85,\n\t0x71, 0x25, 0x11, 0xE5, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x48, 0x4F, 0xC3, 0x06, 0x68, 0xF1, 0x88,\n\t0x51, 0x28, 0x01, 0xE8, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x49, 0x4F, 0xC4, 0x06, 0x69, 0xF1, 0x89,\n\t0x51, 0x29, 0x01, 0xE9, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x4A, 0x4F, 0xC5, 0x06, 0x6A, 0xF1, 0x8A,\n\t0x51, 0x2A, 0x01, 0xEA, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x4B, 0x00, 0x6B, 0xF1, 0x8B, 0x71, 0x2B,\n\t0x11, 0x10, 0x05, 0xEB, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x4C, 0x00, 0x6C, 0xF1, 0x8C, 0x71, 0x2C,\n\t0x11, 0xEC, 0x00, 0xBD, 0x00, 0x08, 0x00, 0x4D, 0x00, 0x6D, 0xF1, 0x8D, 0x71, 0x2D, 0x11, 0xED,\n\t0x00, 0xBD, 0x00, 0x08, 0x00, 0x50, 0x4F, 0xC6, 0x06, 0x70, 0xF1, 0x90, 0x51, 0x30, 0x01, 0xF0,\n\t0x00, 0xBD, 0x00, 0x08, 0x00, 0x51, 0x4F, 0xC7, 0x06, 0x71, 0xF1, 0x91, 0x51, 0x31, 0x01, 0xF1,\n\t0x00, 0xBD, 0x00, 0x08, 0x00, 0x52, 0x4F, 0xC8, 0x06, 0x72, 0xF1, 0x92, 0x51, 0x32, 0x01, 0xF2,\n\t0x00, 0xBD, 0x00, 0x08, 0x00, 0x53, 0x00, 0x73, 0xF1, 0x93, 0x71, 0x33, 0x11, 0xF3, 0x00, 0xBD,\n\t0x00, 0x08, 0x00, 0x54, 0x00, 0x74, 0xF1, 0x94, 0x71, 0x34, 0x11, 0xF4, 0x00, 0xBD, 0x00, 0x08,\n\t0x00, 0x55, 0x00, 0x75, 0xF1, 0x95, 0x71, 0x35, 0x11, 0xF5, 0x00, 0xBD, 0x00, 0xBD, 0x00, 0x08,\n\t0x00, 0xA0, 0x00, 0xB0, 0x00, 0xA1, 0x00, 0xB1, 0x00, 0xA2, 0x00, 0xB2, 0x00, 0xA3, 0x00, 0xB3,\n\t0x00, 0xA4, 0x00, 0xB4, 0x00, 0xA5, 0x00, 0xB5, 0x00, 0xA6, 0x00, 0xB6, 0x00, 0xA7, 0x00, 0xB7,\n\t0x00, 0xA8, 0x00, 0xB8, 0x00, 0xE0, 0x00, 0xE1, 0x00, 0xE2, 0x00, 0xE3, 0x00, 0xE4, 0x00, 0xE5,\n\t0x00, 0xE8, 0x00, 0xE9, 0x00, 0xEA, 0x00, 0x10, 0x05, 0xEB, 0x00, 0xEC, 0x00, 0xED, 0x00, 0xF0,\n\t0x00, 0xF1, 0x00, 0xF2, 0x00, 0xF3, 0x00, 0xF4, 0x00, 0xF5, 0x00, 0x04, 0x01, 0x20, 0xA6, 0x00,\n\t0xB6, 0x00, 0xA7, 0x00, 0xB7, 0x00, 0xA8, 0x00, 0xB8, 0x00, 0xA8, 0x57, 0xB8, 0x09, 0xA7, 0x03,\n\t0xB7, 0x0A, 0xBD, 0x20, 0x08, 0x00, 0x40, 0x4F, 0xC0, 0x06, 0x60, 0xF1, 0x80, 0x51, 0x20, 0x01,\n\t0xE0, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x41, 0x4F, 0xC1, 0x06, 0x61, 0xF1, 0x81, 0x51, 0x21, 0x01,\n\t0xE1, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x42, 0x4F, 0xC2, 0x06, 0x62, 0xF1, 0x82, 0x51, 0x22, 0x01,\n\t0xE2, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x43, 0x00, 0x63, 0xF1, 0x83, 0x71, 0x23, 0x11, 0xE3, 0x00,\n\t0xBD, 0x20, 0x08, 0x00, 0x44, 0x00, 0x64, 0xF1, 0x84, 0x71, 0x24, 0x11, 0xE4, 0x00, 0xBD, 0x20,\n\t0x08, 0x00, 0x45, 0x00, 0x65, 0xF1, 0x85, 0x71, 0x25, 0x11, 0xE5, 0x00, 0xBD, 0x20, 0x08, 0x00,\n\t0x48, 0x4F, 0xC3, 0x06, 0x68, 0xF1, 0x88, 0x51, 0x28, 0x01, 0xE8, 0x00, 0xBD, 0x20, 0x08, 0x00,\n\t0x49, 0x4F, 0xC4, 0x06, 0x69, 0xF1, 0x89, 0x51, 0x29, 0x01, 0xE9, 0x00, 0xBD, 0x20, 0x08, 0x00,\n\t0x4A, 0x4F, 0xC5, 0x06, 0x6A, 0xF1, 0x8A, 0x51, 0x10, 0x05, 0x2A, 0x01, 0xEA, 0x00, 0xBD, 0x20,\n\t0x08, 0x00, 0x4B, 0x00, 0x6B, 0xF1, 0x8B, 0x71, 0x2B, 0x11, 0xEB, 0x00, 0xBD, 0x20, 0x08, 0x00,\n\t0x4C, 0x00, 0x6C, 0xF1, 0x8C, 0x71, 0x2C, 0x11, 0xEC, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x4D, 0x00,\n\t0x6D, 0xF1, 0x8D, 0x71, 0x2D, 0x11, 0xED, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x50, 0x4F, 0xC6, 0x06,\n\t0x70, 0xF1, 0x90, 0x51, 0x30, 0x01, 0xF0, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x51, 0x4F, 0xC7, 0x06,\n\t0x71, 0xF1, 0x91, 0x51, 0x31, 0x01, 0xF1, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x52, 0x4F, 0xC8, 0x06,\n\t0x72, 0xF1, 0x92, 0x51, 0x32, 0x01, 0xF2, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x53, 0x00, 0x73, 0xF1,\n\t0x93, 0x71, 0x33, 0x11, 0xF3, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x54, 0x00, 0x74, 0xF1, 0x94, 0x71,\n\t0x34, 0x11, 0xF4, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x55, 0x00, 0x75, 0xF1, 0x95, 0x71, 0x35, 0x11,\n\t0xF5, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x50, 0x0B, 0xC6, 0x00, 0x70, 0xA8, 0x90, 0x4C, 0x30, 0x00,\n\t0xF0, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x53, 0x00, 0x10, 0x05, 0x73, 0xD6, 0x93, 0x4F, 0x33, 0x00,\n\t0xF3, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x54, 0x00, 0x74, 0xF8, 0x94, 0xB5, 0x34, 0x0C, 0xF4, 0x00,\n\t0xBD, 0x20, 0x08, 0x00, 0x52, 0x00, 0xC8, 0x01, 0x72, 0xF7, 0x92, 0xB5, 0x32, 0x04, 0xF2, 0x00,\n\t0xBD, 0x20, 0x08, 0x00, 0x55, 0x00, 0x75, 0xF5, 0x95, 0xB5, 0x35, 0x01, 0xF5, 0x00, 0xBD, 0x20,\n\t0x08, 0x00, 0x51, 0x00, 0xC7, 0x01, 0x71, 0xF7, 0x91, 0xB5, 0x31, 0x01, 0xF1, 0x00, 0xBD, 0x20,\n\t0xBD, 0x20, 0x08, 0x00, 0x41, 0x00, 0xC1, 0x00, 0x61, 0x70, 0x81, 0x04, 0x21, 0x00, 0xE1, 0x01,\n\t0xBD, 0x20, 0x08, 0x00, 0x44, 0x00, 0x64, 0x70, 0x84, 0x04, 0x24, 0x03, 0xE4, 0x00, 0xBD, 0x20,\n\t0x08, 0x00, 0x42, 0x00, 0xC2, 0x01, 0x62, 0x80, 0x82, 0x06, 0x22, 0x0F, 0xE2, 0x00, 0xBD, 0x20,\n\t0x08, 0x00, 0x45, 0x00, 0x65, 0x80, 0x85, 0x06, 0x25, 0x0F, 0xE5, 0x00, 0xBD, 0x20, 0x08, 0x00,\n\t0x48, 0x00, 0xC3, 0x06, 0x68, 0x10, 0x88, 0x02, 0x28, 0x10, 0xE8, 0x00, 0xBD, 0x20, 0x08, 0x00,\n\t0x4B, 0x00, 0x6B, 0x40, 0x8B, 0x02, 0x2B, 0x01, 0xEB, 0x00, 0x4C, 0x0B, 0x53, 0x0B, 0x54, 0x0B,\n\t0x01, 0x01, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x49, 0x00, 0xC4, 0x00, 0x69, 0xA0, 0x89, 0x04, 0x29,\n\t0x00, 0xE9, 0x00, 0xBD, 0x20, 0x08, 0x00, 0x4C, 0x0B, 0x6C, 0xA0, 0x8C, 0x04, 0x2C, 0x00, 0xEC,\n\t0x00, 0x00, 0x54, 0xBD, 0x20, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x30, 0xA4, 0x57, 0xB4, 0x01, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x57, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x57, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xCB, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4, 0xCB, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0xB1, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0xCB, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4, 0xCB, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4,\n\t0x81, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0x8A, 0xB4, 0x2E, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x8A, 0xB4, 0x0E, 0xA4, 0x8A, 0xB4,\n\t0x2E, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x8A, 0xB4, 0x0E, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x57, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x57, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xCB, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4, 0xCB, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0xB1, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x57, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0x6D, 0xBD, 0x38, 0x08, 0x00, 0x49, 0x00, 0xC4, 0x01, 0x69, 0xD0, 0x89, 0x04, 0x29,\n\t0x01, 0xE9, 0x00, 0xBD, 0x38, 0x08, 0x00, 0x4C, 0x0B, 0x6C, 0xD0, 0x8C, 0x04, 0x2C, 0x02, 0xEC,\n\t0x00, 0x00, 0x6D, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x57, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x57, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xCB, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4, 0xCB, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0xB1, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0xCB, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4, 0xCB, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4,\n\t0x81, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0x8A, 0xB4, 0x2E, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x8A, 0xB4, 0x0E, 0xA4, 0x8A, 0xB4,\n\t0x2E, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x8A, 0xB4, 0x0E, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x57, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x57, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xCB, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4, 0xCB, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0xB1, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x57, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0x6D, 0xBD, 0x38, 0x08, 0x00, 0x49, 0x07, 0xC4, 0x05, 0x69, 0x80, 0x89, 0x04, 0x29,\n\t0x01, 0xE9, 0x01, 0xBD, 0x38, 0x08, 0x00, 0x4C, 0x0B, 0x6C, 0x60, 0x8C, 0x02, 0x2C, 0x01, 0xEC,\n\t0x00, 0x00, 0x6D, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x57, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x57, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xCB, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4, 0xCB, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0xB1, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0xCB, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4, 0xCB, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4,\n\t0x81, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0x8A, 0xB4, 0x2E, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x8A, 0xB4, 0x0E, 0xA4, 0x8A, 0xB4,\n\t0x2E, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x8A, 0xB4, 0x0E, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x57, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x57, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xCB, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4, 0xCB, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0xB1, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x57, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0x6D, 0xBD, 0x38, 0x08, 0x00, 0x49, 0x00, 0xC4, 0x00, 0x69, 0xA0, 0x89, 0x04, 0x29,\n\t0x00, 0xE9, 0x00, 0xBD, 0x38, 0x08, 0x00, 0x4C, 0x0B, 0x6C, 0xA0, 0x8C, 0x04, 0x2C, 0x00, 0xEC,\n\t0x00, 0x00, 0x6D, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x57, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x57, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xCB, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4, 0xCB, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0xB1, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0xCB, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4, 0xCB, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4,\n\t0x81, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0x8A, 0xB4, 0x2E, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x8A, 0xB4, 0x0E, 0xA4, 0x8A, 0xB4,\n\t0x2E, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x8A, 0xB4, 0x0E, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x03, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x43, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4,\n\t0x43, 0xB4, 0x32, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x43, 0xB4, 0x12, 0xA4, 0x03, 0xB4,\n\t0x32, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x03, 0xB4, 0x12, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x57, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x57, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6,\n\t0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4, 0x81, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x81, 0xB4, 0x11, 0xA4,\n\t0xCB, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4, 0xCB, 0xB4,\n\t0x31, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xCB, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDB, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0xB1, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31, 0x00, 0xDA, 0xBD, 0x30, 0xBD, 0x38, 0xA4, 0xB1, 0xB4, 0x11, 0xA4, 0x57, 0xB4,\n\t0x31, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDA, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDA, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0xDB, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0x00, 0xDB, 0xBD, 0x30, 0xBD,\n\t0x38, 0x00, 0x6C, 0xBD, 0x38, 0x08, 0x00, 0x49, 0x00, 0xC4, 0x01, 0x69, 0xD0, 0x89, 0x04, 0x29,\n\t0x01, 0xE9, 0x00, 0xBD, 0x38, 0x08, 0x00, 0x4C, 0x0B, 0x6C, 0xD0, 0x8C, 0x04, 0x2C, 0x02, 0xEC,\n\t0x00, 0x00, 0x6D, 0xBD, 0x28, 0xA6, 0x57, 0xB6, 0x05, 0xBD, 0x38, 0xA4, 0x57, 0xB4, 0x11, 0xA4,\n\t0xB1, 0xB4, 0x31};\n"
  },
  {
    "path": "VGMPlay/chips/2151intf.c",
    "content": "/***************************************************************************\n\n  2151intf.c\n\n  Support interface YM2151(OPM)\n\n***************************************************************************/\n\n#include \"mamedef.h\"\n#include <stdlib.h>\n#include <stddef.h>\t// for NULL\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#include \"fm.h\"\n#include \"2151intf.h\"\n#include \"ym2151.h\"\n#include \"opm.h\"\n\n#define EC_MAME\t\t0x00\n#ifdef ENABLE_ALL_CORES\n#define EC_NUKED\t0x01\n#endif\n\ntypedef struct _ym2151_state ym2151_state;\nstruct _ym2151_state\n{\n\t//sound_stream *\t\t\tstream;\n\t//emu_timer *\t\t\t\ttimer[2];\n\tvoid *\t\t\t\t\tchip;\n\tUINT8\t\t\t\t\tlastreg;\n\t//const ym2151_interface *intf;\n};\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nstatic UINT8 EMU_CORE = 0x00;\n#define MAX_CHIPS\t0x02\nstatic ym2151_state YM2151Data[MAX_CHIPS];\n\n\n/*INLINE ym2151_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_YM2151);\n\treturn (ym2151_state *)device->token;\n}*/\n\n//static STREAM_UPDATE( ym2151_update )\nvoid ym2151_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ym2151_state *info = (ym2151_state *)param;\n\tym2151_state *info = &YM2151Data[ChipID];\n\n\tswitch (EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tym2151_update_one(info->chip, outputs, samples);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_NUKED:\n\t\tOPM_GenerateStream(info->chip, outputs, samples);\n\t\tbreak;\n#endif\n\t}\n\t//YM2151UpdateOne(0x00, outputs, samples);\n}\n\n\n//static STATE_POSTLOAD( ym2151intf_postload )\n/*static void ym2151intf_postload(UINT8 ChipID)\n{\n\t//ym2151_state *info = (ym2151_state *)param;\n\tym2151_state *info = &YM2151Data[ChipID];\n\tym2151_postload(info->chip);\n}*/\n\n\n//static DEVICE_START( ym2151 )\nint device_start_ym2151(UINT8 ChipID, int clock)\n{\n\t//static const ym2151_interface dummy = { 0 };\n\t\n\t//ym2151_state *info = get_safe_token(device);\n\tym2151_state *info;\n\tint rate;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &YM2151Data[ChipID];\n\trate = clock/64;\n\tif ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\t//info->intf = device->static_config ? (const ym2151_interface *)device->static_config : &dummy;\n\t//info->intf = &dummy;\n\n\t/* stream setup */\n\t//info->stream = stream_create(device,0,2,rate,info,ym2151_update);\n\n\tswitch (EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tinfo->chip = ym2151_init(clock, rate);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_NUKED:\n\t\tinfo->chip = malloc(sizeof(opm_t));\n\t\tOPM_Reset(info->chip, rate, clock);\n\t\tbreak;\n#endif\n\t}\n\t//assert_always(info->chip != NULL, \"Error creating YM2151 chip\");\n\n\t//state_save_register_postload(device->machine, ym2151intf_postload, info);\n\n\t//ym2151_set_irq_handler(info->chip,info->intf->irqhandler);\n\t//ym2151_set_port_write_handler(info->chip,info->intf->portwritehandler);\n\t\n\treturn rate;\n}\n\n\n//static DEVICE_STOP( ym2151 )\nvoid device_stop_ym2151(UINT8 ChipID)\n{\n\t//ym2151_state *info = get_safe_token(device);\n\tym2151_state *info = &YM2151Data[ChipID];\n\tswitch (EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tym2151_shutdown(info->chip);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_NUKED:\n\t\tfree(info->chip);\n\t\tbreak;\n#endif\n\t}\n\t//YM2151Shutdown();\n}\n\n//static DEVICE_RESET( ym2151 )\nvoid device_reset_ym2151(UINT8 ChipID)\n{\n\t//ym2151_state *info = get_safe_token(device);\n\tym2151_state *info = &YM2151Data[ChipID];\n\tswitch (EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tym2151_reset_chip(info->chip);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_NUKED:\n\t\tOPM_Reset(info->chip, 0, 0);\n\t\tbreak;\n#endif\n\t}\n\t//YM2151ResetChip(0x00);\n}\n\n\n//READ8_DEVICE_HANDLER( ym2151_r )\nUINT8 ym2151_r(UINT8 ChipID, offs_t offset)\n{\n\t//ym2151_state *token = get_safe_token(device);\n\tym2151_state *token = &YM2151Data[ChipID];\n\n\tswitch (EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tif (offset & 1)\n\t\t{\n\t\t\t//stream_update(token->stream);\n\t\t\treturn ym2151_read_status(token->chip);\n\t\t\t//return YM2151ReadStatus(0x00);\n\t\t}\n\t\telse\n\t\t\treturn 0xff;\t/* confirmed on a real YM2151 */\n\t}\n\treturn 0x00;\n}\n\n//WRITE8_DEVICE_HANDLER( ym2151_w )\nvoid ym2151_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//ym2151_state *token = get_safe_token(device);\n\tym2151_state *token = &YM2151Data[ChipID];\n\tswitch (EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tif (offset & 1)\n\t\t{\n\t\t\t//stream_update(token->stream);\n\t\t\tym2151_write_reg(token->chip, token->lastreg, data);\n\t\t\t//YM2151WriteReg(0x00, token->lastreg, data);\n\t\t}\n\t\telse\n\t\t\ttoken->lastreg = data;\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_NUKED:\n\t\tOPM_WriteBuffered(token->chip, offset, data);\n\t\tbreak;\n#endif\n\t}\n}\n\n\n/*READ8_DEVICE_HANDLER( ym2151_status_port_r ) { return ym2151_r(device, 1); }\n\nWRITE8_DEVICE_HANDLER( ym2151_register_port_w ) { ym2151_w(device, 0, data); }\nWRITE8_DEVICE_HANDLER( ym2151_data_port_w ) { ym2151_w(device, 1, data); }*/\nUINT8 ym2151_status_port_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2151_r(ChipID, 1);\n}\n\nvoid ym2151_register_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2151_w(ChipID, 0, data);\n}\nvoid ym2151_data_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2151_w(ChipID, 1, data);\n}\n\n\nvoid ym2151_set_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tEMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;\n#else\n\tEMU_CORE = EC_MAME;\n#endif\n\n\treturn;\n}\n\n\nvoid ym2151_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tym2151_state *info = &YM2151Data[ChipID];\n\tswitch (EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tym2151_set_mutemask(info->chip, MuteMask);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_NUKED:\n\t\tOPM_SetMute(info->chip, MuteMask);\n\t\tbreak;\n#endif\n\t}\n}\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( ym2151 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ym2151_state);\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ym2151 );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( ym2151 );\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( ym2151 );\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YM2151\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Yamaha FM\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/2151intf.h",
    "content": "#pragma once\n\n/*typedef struct _ym2151_interface ym2151_interface;\nstruct _ym2151_interface\n{\n\t//void (*irqhandler)(const device_config *device, int irq);\n\tvoid (*irqhandler)(int irq);\n\twrite8_device_func portwritehandler;\n};*/\n\n/*READ8_DEVICE_HANDLER( ym2151_r );\nWRITE8_DEVICE_HANDLER( ym2151_w );\n\nREAD8_DEVICE_HANDLER( ym2151_status_port_r );\nWRITE8_DEVICE_HANDLER( ym2151_register_port_w );\nWRITE8_DEVICE_HANDLER( ym2151_data_port_w );\n\nDEVICE_GET_INFO( ym2151 );\n#define SOUND_YM2151 DEVICE_GET_INFO_NAME( ym2151 )*/\nvoid ym2151_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_ym2151(UINT8 ChipID, int clock);\nvoid device_stop_ym2151(UINT8 ChipID);\nvoid device_reset_ym2151(UINT8 ChipID);\n\nUINT8 ym2151_r(UINT8 ChipID, offs_t offset);\nvoid ym2151_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nUINT8 ym2151_status_port_r(UINT8 ChipID, offs_t offset);\nvoid ym2151_register_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2151_data_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid ym2151_set_emu_core(UINT8 Emulator);\nvoid ym2151_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/chips/2203intf.c",
    "content": "#include <math.h>\n#include <stdlib.h>\t// for free\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#include \"2203intf.h\"\n#include \"fm.h\"\n\n\n#ifdef ENABLE_ALL_CORES\n#define EC_MAME\t\t0x01\t// AY8910 core from MAME\n#endif\n#define EC_EMU2149\t0x00\n\ntypedef struct _ym2203_state ym2203_state;\nstruct _ym2203_state\n{\n\t//sound_stream *\tstream;\n\t//emu_timer *\t\ttimer[2];\n\tvoid *\t\t\tchip;\n\tvoid *\t\t\tpsg;\n\tym2203_interface intf;\n\t//const device_config *device;\n};\n\n#define CHTYPE_YM2203\t0x20\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nstatic UINT8 AY_EMU_CORE = 0x00;\nextern UINT32 SampleRate;\n\n#define MAX_CHIPS\t0x10\nstatic ym2203_state YM2203Data[MAX_CHIPS];\n\n/*INLINE ym2203_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_YM2203);\n\treturn (ym2203_state *)device->token;\n}*/\n\n\nstatic void psg_set_clock(void *param, int clock)\n{\n\tym2203_state *info = (ym2203_state *)param;\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_set_clock_ym(info->psg, clock);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_set_clock((PSG*)info->psg, clock);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstatic void psg_write(void *param, int address, int data)\n{\n\tym2203_state *info = (ym2203_state *)param;\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_write_ym(info->psg, address, data);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_writeIO((PSG*)info->psg, address, data);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstatic int psg_read(void *param)\n{\n\tym2203_state *info = (ym2203_state *)param;\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\treturn ay8910_read_ym(info->psg);\n#endif\n\t\tcase EC_EMU2149:\n\t\t\treturn PSG_readIO((PSG*)info->psg);\n\t\t}\n\t}\n\treturn 0x00;\n}\n\nstatic void psg_reset(void *param)\n{\n\tym2203_state *info = (ym2203_state *)param;\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_reset_ym(info->psg);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_reset((PSG*)info->psg);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstatic const ssg_callbacks psgintf =\n{\n\tpsg_set_clock,\n\tpsg_write,\n\tpsg_read,\n\tpsg_reset\n};\n\n/* IRQ Handler */\n/*static void IRQHandler(void *param,int irq)\n{\n\tym2203_state *info = (ym2203_state *)param;\n\tif (info->intf.handler != NULL)\n\t\t//(*info->intf->handler)(info->device, irq);\n\t\t(*info->intf.handler)(irq);\n}*/\n\n/* Timer overflow callback from timer.c */\n/*static TIMER_CALLBACK( timer_callback_2203_0 )\n{\n\tym2203_state *info = (ym2203_state *)ptr;\n\tym2203_timer_over(info->chip,0);\n}\n\nstatic TIMER_CALLBACK( timer_callback_2203_1 )\n{\n\tym2203_state *info = (ym2203_state *)ptr;\n\tym2203_timer_over(info->chip,1);\n}*/\n\n/* update request from fm.c */\nvoid ym2203_update_request(void *param)\n{\n\tym2203_state *info = (ym2203_state *)param;\n\t//stream_update(info->stream);\n\t\n\tym2203_update_one(info->chip, DUMMYBUF, 0);\n\t// We really don't need this.\n\t/*if (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_update_one(info->psg, DUMMYBUF, 0);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_calc_stereo((PSG*)info->psg, DUMMYBUF, 0);\n\t\t\tbreak;\n\t\t}\n\t}*/\n}\n\n\n/*static void timer_handler(void *param,int c,int count,int clock)\n{\n\tym2203_state *info = (ym2203_state *)param;\n\tif( count == 0 )\n\t{\t// Reset FM Timer\n\t\t//timer_enable(info->timer[c], 0);\n\t}\n\telse\n\t{\t// Start FM Timer\n\t\t//attotime period = attotime_mul(ATTOTIME_IN_HZ(clock), count);\n\t\t//if (!timer_enable(info->timer[c], 1))\n\t\t//\ttimer_adjust_oneshot(info->timer[c], period, 0);\n\t}\n}*/\n\n//static STREAM_UPDATE( ym2203_stream_update )\nvoid ym2203_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ym2203_state *info = (ym2203_state *)param;\n\tym2203_state *info = &YM2203Data[ChipID];\n\tym2203_update_one(info->chip, outputs, samples);\n}\n\nvoid ym2203_stream_update_ay(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ym2203_state *info = (ym2203_state *)param;\n\tym2203_state *info = &YM2203Data[ChipID];\n\t\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_update_one(info->psg, outputs, samples);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_calc_stereo((PSG*)info->psg, outputs, samples);\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\tmemset(outputs[0], 0x00, samples * sizeof(stream_sample_t));\n\t\tmemset(outputs[1], 0x00, samples * sizeof(stream_sample_t));\n\t}\n}\n\n\n//static STATE_POSTLOAD( ym2203_intf_postload )\n/*static void ym2203_intf_postload(UINT8 ChipID)\n{\n\t//ym2203_state *info = (ym2203_state *)param;\n\tym2203_state *info = &YM2203Data[ChipID];\n\tym2203_postload(info->chip);\n}*/\n\n\n//static DEVICE_START( ym2203 )\nint device_start_ym2203(UINT8 ChipID, int clock, UINT8 AYDisable, UINT8 AYFlags, int* AYrate)\n{\n\tstatic const ym2203_interface generic_2203 =\n\t{\n\t\t{\n\t\t\tAY8910_LEGACY_OUTPUT,\n\t\t\tAY8910_DEFAULT_LOADS\n\t\t\t//DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL\n\t\t},\n\t\tNULL\n\t};\n\t//const ym2203_interface *intf = device->static_config ? (const ym2203_interface *)device->static_config : &generic_2203;\n\tym2203_interface* intf;\n\t//ym2203_state *info = get_safe_token(device);\n\tym2203_state *info;\n\tint rate;\n\tint ay_clock;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &YM2203Data[ChipID];\n\trate = clock/72; /* ??? */\n\tif ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\n\tinfo->intf = generic_2203;\n\tintf = &info->intf;\n\tif (AYFlags)\n\t\tintf->ay8910_intf.flags = AYFlags;\n\t//info->device = device;\n\t//info->psg = ay8910_start_ym(NULL, SOUND_YM2203, device, device->clock, &intf->ay8910_intf);\n\tif (! AYDisable)\n\t{\n\t\tay_clock = clock / 2;\n\t\t*AYrate = ay_clock / 8;\n\t\tif ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||\n\t\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\t\t*AYrate = CHIP_SAMPLE_RATE;\n\t\t\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\t// fits in the most common cases\n\t\t\t// TODO: remove after being able to change the resampler's sampling rate\n\t\t\tinfo->psg = ay8910_start_ym(NULL, CHTYPE_YM2203, ay_clock, &intf->ay8910_intf);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tinfo->psg = PSG_new(ay_clock, *AYrate);\n\t\t\tif (info->psg == NULL)\n\t\t\t\treturn 0;\n\t\t\tPSG_setVolumeMode((PSG*)info->psg, 1);\t// YM2149 volume mode\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\tinfo->psg = NULL;\n\t\t*AYrate = 0;\n\t}\n\t//assert_always(info->psg != NULL, \"Error creating YM2203/AY8910 chip\");\n\n\t/* Timer Handler set */\n\t//info->timer[0] = timer_alloc(device->machine, timer_callback_2203_0, info);\n\t//info->timer[1] = timer_alloc(device->machine, timer_callback_2203_1, info);\n\n\t/* stream system initialize */\n\t//info->stream = stream_create(device,0,1,rate,info,ym2203_stream_update);\n\n\t/* Initialize FM emurator */\n\t//info->chip = ym2203_init(info,clock,rate,timer_handler,IRQHandler,&psgintf);\n\tinfo->chip = ym2203_init(info,clock,rate,NULL,NULL,&psgintf);\n\t//assert_always(info->chip != NULL, \"Error creating YM2203 chip\");\n\n\t//state_save_register_postload(device->machine, ym2203_intf_postload, info);\n\t\n\treturn rate;\n}\n\n//static DEVICE_STOP( ym2203 )\nvoid device_stop_ym2203(UINT8 ChipID)\n{\n\t//ym2203_state *info = get_safe_token(device);\n\tym2203_state *info = &YM2203Data[ChipID];\n\tym2203_shutdown(info->chip);\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_stop_ym(info->psg);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_delete((PSG*)info->psg);\n\t\t\tbreak;\n\t\t}\n\t\tinfo->psg = NULL;\n\t}\n}\n\n//static DEVICE_RESET( ym2203 )\nvoid device_reset_ym2203(UINT8 ChipID)\n{\n\t//ym2203_state *info = get_safe_token(device);\n\tym2203_state *info = &YM2203Data[ChipID];\n\tym2203_reset_chip(info->chip);\t// also resets the AY clock\n\t//psg_reset(info);\t// already done as a callback in ym2203_reset_chip\n}\n\n\n\n//READ8_DEVICE_HANDLER( ym2203_r )\nUINT8 ym2203_r(UINT8 ChipID, offs_t offset)\n{\n\t//ym2203_state *info = get_safe_token(device);\n\tym2203_state *info = &YM2203Data[ChipID];\n\treturn ym2203_read(info->chip, offset & 1);\n}\n\n//WRITE8_DEVICE_HANDLER( ym2203_w )\nvoid ym2203_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//ym2203_state *info = get_safe_token(device);\n\tym2203_state *info = &YM2203Data[ChipID];\n\tym2203_write(info->chip, offset & 1, data);\n}\n\n\n//READ8_DEVICE_HANDLER( ym2203_status_port_r )\nUINT8 ym2203_status_port_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2203_r(ChipID, 0);\n}\n//READ8_DEVICE_HANDLER( ym2203_read_port_r )\nUINT8 ym2203_read_port_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2203_r(ChipID, 1);\n}\n//WRITE8_DEVICE_HANDLER( ym2203_control_port_w )\nvoid ym2203_control_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2203_w(ChipID, 0, data);\n}\n//WRITE8_DEVICE_HANDLER( ym2203_write_port_w )\nvoid ym2203_write_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2203_w(ChipID, 1, data);\n}\n\n\nvoid ym2203_set_ay_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tAY_EMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;\n#else\n\tAY_EMU_CORE = EC_EMU2149;\n#endif\n\t\n\treturn;\n}\n\nvoid ym2203_set_mute_mask(UINT8 ChipID, UINT32 MuteMaskFM, UINT32 MuteMaskAY)\n{\n\tym2203_state *info = &YM2203Data[ChipID];\n\tym2203_set_mutemask(info->chip, MuteMaskFM);\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_set_mute_mask_ym(info->psg, MuteMaskAY);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_setMask((PSG*)info->psg, MuteMaskAY);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid ym2203_set_stereo_mask_ay(UINT8 ChipID, UINT32 StereoMaskAY)\n{\n\tym2203_state *info = &YM2203Data[ChipID];\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_set_stereo_mask_ym(info->psg, StereoMaskAY);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_setStereoMask((PSG*)info->psg, StereoMaskAY);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid ym2203_set_srchg_cb(UINT8 ChipID, SRATE_CALLBACK CallbackFunc, void* DataPtr, void* AYDataPtr)\n{\n\tym2203_state *info = &YM2203Data[ChipID];\n\t\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_set_srchg_cb_ym(info->psg, CallbackFunc, AYDataPtr);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\treturn;\n}\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( ym2203 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ym2203_state);\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ym2203 );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( ym2203 );\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( ym2203 );\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YM2203\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Yamaha FM\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/2203intf.h",
    "content": "#pragma once\n\n#include \"ay8910.h\"\n#include \"emu2149.h\"\n\nvoid ym2203_update_request(void *param);\n\ntypedef struct _ym2203_interface ym2203_interface;\nstruct _ym2203_interface\n{\n\tay8910_interface ay8910_intf;\n\t//void (*handler)(const device_config *device, int irq);\n\tvoid (*handler)(int irq);\n};\n\n/*READ8_DEVICE_HANDLER( ym2203_r );\nWRITE8_DEVICE_HANDLER( ym2203_w );\n\nREAD8_DEVICE_HANDLER( ym2203_status_port_r );\nREAD8_DEVICE_HANDLER( ym2203_read_port_r );\nWRITE8_DEVICE_HANDLER( ym2203_control_port_w );\nWRITE8_DEVICE_HANDLER( ym2203_write_port_w );\n\nDEVICE_GET_INFO( ym2203 );\n#define SOUND_YM2203 DEVICE_GET_INFO_NAME( ym2203 )*/\n\nvoid ym2203_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nvoid ym2203_stream_update_ay(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_ym2203(UINT8 ChipID, int clock, UINT8 AYDisable, UINT8 AYFlags, int* AYrate);\nvoid device_stop_ym2203(UINT8 ChipID);\nvoid device_reset_ym2203(UINT8 ChipID);\n\nUINT8 ym2203_r(UINT8 ChipID, offs_t offset);\nvoid ym2203_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nUINT8 ym2203_status_port_r(UINT8 ChipID, offs_t offset);\nUINT8 ym2203_read_port_r(UINT8 ChipID, offs_t offset);\nvoid ym2203_control_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2203_write_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid ym2203_set_ay_emu_core(UINT8 Emulator);\nvoid ym2203_set_mute_mask(UINT8 ChipID, UINT32 MuteMaskFM, UINT32 MuteMaskAY);\nvoid ym2203_set_stereo_mask_ay(UINT8 ChipID, UINT32 StereoMaskAY);\nvoid ym2203_set_srchg_cb(UINT8 ChipID, SRATE_CALLBACK CallbackFunc, void* DataPtr, void* AYDataPtr);\n"
  },
  {
    "path": "VGMPlay/chips/2413intf.c",
    "content": "/****************************************************************\n\n    MAME / MESS functions\n\n****************************************************************/\n\n#include \"mamedef.h\"\n#include <stdlib.h>\n#include <stddef.h>\t// for NULL\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#ifdef ENABLE_ALL_CORES\n#include \"ym2413.h\"\n#include \"opll.h\"\n#endif\n#include \"emu2413.h\"\n#include \"2413intf.h\"\n\n#ifdef ENABLE_ALL_CORES\n#define EC_NUKED\t0x02\t// Nuked OPLL\n#define EC_MAME\t\t0x01\t// YM2413 core from MAME\n#endif\n#define EC_EMU2413\t0x00\t// EMU2413 core from in_vgm, value 0 because it's better than MAME\n\n/* for stream system */\ntypedef struct _ym2413_state ym2413_state;\nstruct _ym2413_state\n{\n\t//sound_stream *\tstream;\n\tvoid *\t\t\tchip;\n\tUINT8\t\t\tMode;\n};\n\nstatic unsigned char vrc7_inst[(16 + 3) * 8] =\n{\n#include \"vrc7tone.h\"\n};\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nstatic UINT8 EMU_CORE = 0x00;\n\n#define MAX_CHIPS\t0x02\nstatic ym2413_state YM2413Data[MAX_CHIPS];\n\n/*INLINE ym2413_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_YM2413);\n\treturn (ym2413_state *)device->token;\n}*/\n\n#ifdef UNUSED_FUNCTION\nvoid YM2413DAC_update(int chip,stream_sample_t **inputs, stream_sample_t **_buffer,int length)\n{\n    INT16 *buffer = _buffer[0];\n    static int out = 0;\n\n    if ( ym2413[chip].reg[0x0F] & 0x01 )\n    {\n        out = ((ym2413[chip].reg[0x10] & 0xF0) << 7);\n    }\n    while (length--) *(buffer++) = out;\n}\n#endif\n\nstatic void _emu2413_calc_stereo(OPLL *opll, INT32 **out, int samples)\n{\n\tINT32 *bufL = out[0];\n\tINT32 *bufR = out[1];\n\tINT32 buffers[2];\n\tint i;\n\n\tfor (i = 0; i < samples; i++)\n\t{\n\t\tOPLL_calcStereo(opll, buffers);\n\t\tbufL[i] = buffers[0];\n\t\tbufR[i] = buffers[1];\n\t}\n}\n\nstatic void _emu2413_set_mute_mask(OPLL *opll, UINT32 MuteMask)\n{\n\tunsigned char CurChn;\n\tUINT32 ChnMsk;\n\n\tfor (CurChn = 0; CurChn < 14; CurChn++)\n\t{\n\t\tif (CurChn < 9)\n\t\t{\n\t\t\tChnMsk = OPLL_MASK_CH(CurChn);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tswitch (CurChn)\n\t\t\t{\n\t\t\tcase 9:\n\t\t\t\tChnMsk = OPLL_MASK_BD;\n\t\t\t\tbreak;\n\t\t\tcase 10:\n\t\t\t\tChnMsk = OPLL_MASK_SD;\n\t\t\t\tbreak;\n\t\t\tcase 11:\n\t\t\t\tChnMsk = OPLL_MASK_TOM;\n\t\t\t\tbreak;\n\t\t\tcase 12:\n\t\t\t\tChnMsk = OPLL_MASK_CYM;\n\t\t\t\tbreak;\n\t\t\tcase 13:\n\t\t\t\tChnMsk = OPLL_MASK_HH;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tChnMsk = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif ((MuteMask >> CurChn) & 0x01)\n\t\t\topll->mask |= ChnMsk;\n\t\telse\n\t\t\topll->mask &= ~ChnMsk;\n\t}\n\n\treturn;\n}\n\n//static STREAM_UPDATE( ym2413_stream_update )\nvoid ym2413_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tym2413_state *info = &YM2413Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tym2413_update_one(info->chip, outputs, samples);\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tOPLL_GenerateStream(info->chip, outputs, samples);\n\t\tbreak;\n#endif\n\tcase EC_EMU2413:\n\t\t_emu2413_calc_stereo(info->chip, outputs, samples);\n\t\tbreak;\n\t}\n}\n\nstatic void _stream_update(void *param, int interval)\n{\n\tym2413_state *info = (ym2413_state *)param;\n\t/*stream_update(info->stream);*/\n\t\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tym2413_update_one(info->chip, DUMMYBUF, 0);\n\t\tbreak;\n\tcase EC_NUKED:\n\t\t// OPLL_GenerateStream(info->chip, DUMMYBUF, 0);\n\t\tbreak;\n#endif\n\tcase EC_EMU2413:\n\t\t_emu2413_calc_stereo(info->chip, DUMMYBUF, 0);\n\t\tbreak;\n\t}\n}\n\n//static DEVICE_START( ym2413 )\nint device_start_ym2413(UINT8 ChipID, int clock)\n{\n\t//ym2413_state *info = get_safe_token(device);\n\tym2413_state *info;\n\tint type;\n\tint rate;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &YM2413Data[ChipID];\n\tinfo->Mode = (clock & 0x80000000) >> 31;\n\tclock &= 0x7FFFFFFF;\n\t\n\trate = clock/72;\n\tif ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\t/* emulator create */\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tinfo->chip = ym2413_init(clock, rate);\n\t\tif (info->chip == NULL)\n\t\t\treturn 0;\n\t\t//assert_always(info->chip != NULL, \"Error creating YM2413 chip\");\n\t\tym2413_set_chip_mode(info->chip, info->Mode);\n\n\t\t/* stream system initialize */\n\t\t//info->stream = stream_create(device,0,2,rate,info,ym2413_stream_update);\n\n\t\tym2413_set_update_handler(info->chip, _stream_update, info);\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tinfo->chip = malloc(sizeof(opll_t));\n\t\t//if(chiptype)\n\t\t//\tOPN2_SetChipType(ym3438_type_discrete);\n\t\ttype = info->Mode ? opll_type_ds1001 : opll_type_ym2413;\n\t\tOPLL_Reset(info->chip, type, rate, clock);\n\t\tbreak;\n#endif\n\tcase EC_EMU2413:\n\t\tinfo->chip = OPLL_new(clock, rate);\n\t\tif (info->chip == NULL)\n\t\t\treturn 0;\n\t\t\n\t\tOPLL_setChipMode(info->chip, info->Mode);\n\t\tif (info->Mode)\n\t\t\tOPLL_setPatch(info->chip, vrc7_inst);\n\t\tbreak;\n\t}\n\t// Note: VRC7 instruments are set in device_reset if necessary.\n\n\n\n/*#if 0\n\tint i, tst;\n\tchar name[40];\n\n\tnum = intf->num;\n\n\ttst = YM3812_sh_start (msound);\n\tif (tst)\n\t\treturn 1;\n\n\tfor (i=0;i<num;i++)\n\t{\n\t\tym2413_reset (i);\n\n\t\tym2413[i].DAC_stream = stream_create(device, 0, 1, device->clock/72, i, YM2413DAC_update);\n\n\t\tif (ym2413[i].DAC_stream == -1)\n\t\t\treturn 1;\n\t}\n\treturn 0;\n#endif*/\n\treturn rate;\n}\n\n//static DEVICE_STOP( ym2413 )\nvoid device_stop_ym2413(UINT8 ChipID)\n{\n\t//ym2413_state *info = get_safe_token(device);\n\tym2413_state *info = &YM2413Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tym2413_shutdown(info->chip);\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tfree(info->chip);\n\t\tbreak;\n#endif\n\tcase EC_EMU2413:\n\t\tOPLL_delete(info->chip);\n\t\tbreak;\n\t}\n}\n\n//static DEVICE_RESET( ym2413 )\nvoid device_reset_ym2413(UINT8 ChipID)\n{\n\t//ym2413_state *info = get_safe_token(device);\n\tym2413_state *info = &YM2413Data[ChipID];\n\tint type;\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tym2413_reset_chip(info->chip);\n\t\tif (info->Mode)\n\t\t\tym2413_override_patches(info->chip, vrc7_inst);\n\t\tbreak;\n\tcase EC_NUKED:\n\t\ttype = info->Mode ? opll_type_ds1001 : opll_type_ym2413;\n\t\tOPLL_Reset(info->chip, type, 0, 0);\n\t\tbreak;\n#endif\n\tcase EC_EMU2413:\n\t\tOPLL_reset(info->chip);\n\t\t// EMU2413 doesn't reset the patch data in OPLL_reset\n\t\t//if (info->Mode)\n\t\t//\tOPLL_setPatch(info->chip, vrc7_inst);\n\t\tbreak;\n\t}\n}\n\n\n//WRITE8_DEVICE_HANDLER( ym2413_w )\nvoid ym2413_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//ym2413_state *info = get_safe_token(device);\n\tym2413_state *info = &YM2413Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tym2413_write(info->chip, offset & 1, data);\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tOPLL_WriteBuffered(info->chip, offset, data);\n\t\tbreak;\n#endif\n\tcase EC_EMU2413:\n\t\tOPLL_writeIO(info->chip, offset & 1, data);\n\t\tbreak;\n\t}\n}\n\n//WRITE8_DEVICE_HANDLER( ym2413_register_port_w )\nvoid ym2413_register_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2413_w(ChipID, 0, data);\n}\n//WRITE8_DEVICE_HANDLER( ym2413_data_port_w )\nvoid ym2413_data_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2413_w(ChipID, 1, data);\n}\n\n\nvoid ym2413_set_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tEMU_CORE = (Emulator < 0x03) ? Emulator : 0x00;\n#else\n\tEMU_CORE = EC_EMU2413;\n#endif\n\t\n\treturn;\n}\n\nvoid ym2413_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tym2413_state *info = &YM2413Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tym2413_set_mutemask(info->chip, MuteMask);\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tOPLL_SetMute(info->chip, MuteMask);\n\t\tbreak;\n#endif\n\tcase EC_EMU2413:\n\t\t_emu2413_set_mute_mask(info->chip, MuteMask);\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\nvoid ym2413_set_panning(UINT8 ChipID, INT16* PanVals)\n{\n\tym2413_state *info = &YM2413Data[ChipID];\n\tUINT8 CurChn;\n\tUINT8 EmuChn;\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tbreak;\n#endif\n\tcase EC_EMU2413:\n\t\tfor (CurChn = 0x00; CurChn < 0x0E; CurChn ++)\n\t\t{\n\t\t\t// input:  0..8, BD, SD, TOM, CYM, HH\n\t\t\t// output: 0..8, BD, HH, SD, TOM, CYM\n\t\t\tif (CurChn < 10)\n\t\t\t\tEmuChn = CurChn;\n\t\t\telse if (CurChn < 13)\n\t\t\t\tEmuChn = CurChn + 1;\n\t\t\telse\n\t\t\t\tEmuChn = 10;\n\t\t\tOPLL_setPanEx(info->chip, EmuChn, PanVals[CurChn]);\n\t\t}\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( ym2413 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ym2413_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ym2413 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( ym2413 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( ym2413 );\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YM2413\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Yamaha FM\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/2413intf.h",
    "content": "#pragma once\n\n/*WRITE8_DEVICE_HANDLER( ym2413_w );\n\nWRITE8_DEVICE_HANDLER( ym2413_register_port_w );\nWRITE8_DEVICE_HANDLER( ym2413_data_port_w );\n\nDEVICE_GET_INFO( ym2413 );\n#define SOUND_YM2413 DEVICE_GET_INFO_NAME( ym2413 )*/\n\nvoid ym2413_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_ym2413(UINT8 ChipID, int clock);\nvoid device_stop_ym2413(UINT8 ChipID);\nvoid device_reset_ym2413(UINT8 ChipID);\n\nvoid ym2413_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2413_register_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2413_data_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid ym2413_set_emu_core(UINT8 Emulator);\nvoid ym2413_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\nvoid ym2413_set_panning(UINT8 ChipID, INT16* PanVals);\n"
  },
  {
    "path": "VGMPlay/chips/2608intf.c",
    "content": "/***************************************************************************\n\n  2608intf.c\n\n  The YM2608 emulator supports up to 2 chips.\n  Each chip has the following connections:\n  - Status Read / Control Write A\n  - Port Read / Data Write A\n  - Control Write B\n  - Data Write B\n\n***************************************************************************/\n\n#include <stdlib.h>\t// for free\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#include \"2608intf.h\"\n//#include \"fm.h\"\n\n\n#ifdef ENABLE_ALL_CORES\n#define EC_MAME\t\t0x01\t// AY8910 core from MAME\n#endif\n#define EC_EMU2149\t0x00\n\ntypedef struct _ym2608_state ym2608_state;\nstruct _ym2608_state\n{\n\t//sound_stream *\tstream;\n\t//emu_timer *\ttimer[2];\n\tvoid *\t\t\tchip;\n\tvoid *\t\t\tpsg;\n\tym2608_interface intf;\n\t//const device_config *device;\n};\n\n#define CHTYPE_YM2608\t0x21\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nstatic UINT8 AY_EMU_CORE = 0x00;\nextern UINT32 SampleRate;\n\n#define MAX_CHIPS\t0x02\nstatic ym2608_state YM2608Data[MAX_CHIPS];\n\n/*INLINE ym2608_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_YM2608);\n\treturn (ym2608_state *)device->token;\n}*/\n\n\n\nstatic void psg_set_clock(void *param, int clock)\n{\n\tym2608_state *info = (ym2608_state *)param;\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_set_clock_ym(info->psg, clock);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_set_clock((PSG*)info->psg, clock);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstatic void psg_write(void *param, int address, int data)\n{\n\tym2608_state *info = (ym2608_state *)param;\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_write_ym(info->psg, address, data);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_writeIO((PSG*)info->psg, address, data);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstatic int psg_read(void *param)\n{\n\tym2608_state *info = (ym2608_state *)param;\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\treturn ay8910_read_ym(info->psg);\n#endif\n\t\tcase EC_EMU2149:\n\t\t\treturn PSG_readIO((PSG*)info->psg);\n\t\t}\n\t}\n\treturn 0x00;\n}\n\nstatic void psg_reset(void *param)\n{\n\tym2608_state *info = (ym2608_state *)param;\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_reset_ym(info->psg);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_reset((PSG*)info->psg);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstatic const ssg_callbacks psgintf =\n{\n\tpsg_set_clock,\n\tpsg_write,\n\tpsg_read,\n\tpsg_reset\n};\n\n\n/* IRQ Handler */\n/*static void IRQHandler(void *param,int irq)\n{\n\tym2608_state *info = (ym2608_state *)param;\n\t//if(info->intf->handler) info->intf->handler(info->device, irq);\n\tif(info->intf.handler) info->intf.handler(irq);\n}*/\n\n/* Timer overflow callback from timer.c */\n/*static TIMER_CALLBACK( timer_callback_2608_0 )\n{\n\tym2608_state *info = (ym2608_state *)ptr;\n\tym2608_timer_over(info->chip,0);\n}\n\nstatic TIMER_CALLBACK( timer_callback_2608_1 )\n{\n\tym2608_state *info = (ym2608_state *)ptr;\n\tym2608_timer_over(info->chip,1);\n}*/\n\n/*static void timer_handler(void *param,int c,int count,int clock)\n{\n\tym2608_state *info = (ym2608_state *)param;\n\tif( count == 0 )\n\t{\t// Reset FM Timer\n\t\t//timer_enable(info->timer[c], 0);\n\t}\n\telse\n\t{\t// Start FM Timer\n\t\t//attotime period = attotime_mul(ATTOTIME_IN_HZ(clock), count);\n\t\t//if (!timer_enable(info->timer[c], 1))\n\t\t//\ttimer_adjust_oneshot(info->timer[c], period, 0);\n\t}\n}*/\n\n/* update request from fm.c */\nvoid ym2608_update_request(void *param)\n{\n\tym2608_state *info = (ym2608_state *)param;\n\t//stream_update(info->stream);\n\t\n\tym2608_update_one(info->chip, DUMMYBUF, 0);\n\t// Not necessary.\n\t//if (info->psg != NULL)\n\t//\tay8910_update_one(info->psg, DUMMYBUF, 0);\n}\n\n//static STREAM_UPDATE( ym2608_stream_update )\nvoid ym2608_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ym2608_state *info = (ym2608_state *)param;\n\tym2608_state *info = &YM2608Data[ChipID];\n\tym2608_update_one(info->chip, outputs, samples);\n}\n\nvoid ym2608_stream_update_ay(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ym2608_state *info = (ym2608_state *)param;\n\tym2608_state *info = &YM2608Data[ChipID];\n\t\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_update_one(info->psg, outputs, samples);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_calc_stereo((PSG*)info->psg, outputs, samples);\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\tmemset(outputs[0], 0x00, samples * sizeof(stream_sample_t));\n\t\tmemset(outputs[1], 0x00, samples * sizeof(stream_sample_t));\n\t}\n}\n\n\n//static STATE_POSTLOAD( ym2608_intf_postload )\n/*static void ym2608_intf_postload(UINT8 ChipID)\n{\n\t//ym2608_state *info = (ym2608_state *)param;\n\tym2608_state *info = &YM2608Data[ChipID];\n\tym2608_postload(info->chip);\n}*/\n\n\n//static DEVICE_START( ym2608 )\nint device_start_ym2608(UINT8 ChipID, int clock, UINT8 AYDisable, UINT8 AYFlags, int* AYrate)\n{\n\tstatic const ym2608_interface generic_2608 =\n\t{\n\t\t{\n\t\t\tAY8910_LEGACY_OUTPUT | AY8910_SINGLE_OUTPUT,\n\t\t\tAY8910_DEFAULT_LOADS\n\t\t\t//DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL\n\t\t},\n\t\tNULL\n\t};\n\t//const ym2608_interface *intf = device->static_config ? (const ym2608_interface *)device->static_config : &generic_2608;\n\tym2608_interface *intf;\n\tint rate;\n\tint ay_clock;\n\t//void *pcmbufa;\n\t//int  pcmsizea;\n\n\t//ym2608_state *info = get_safe_token(device);\n\tym2608_state *info;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &YM2608Data[ChipID];\n\trate = clock/72;\n\tif ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\tinfo->intf = generic_2608;\n\tintf = &info->intf;\n\tif (AYFlags)\n\t\tintf->ay8910_intf.flags = AYFlags;\n\t//info->device = device;\n\n\t/* FIXME: Force to use single output */\n\t//info->psg = ay8910_start_ym(NULL, SOUND_YM2608, clock, &intf->ay8910_intf);\n\tif (! AYDisable)\n\t{\n\t\tay_clock = clock / 4;\n\t\t*AYrate = ay_clock / 8;\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tinfo->psg = ay8910_start_ym(NULL, CHTYPE_YM2608, ay_clock, &intf->ay8910_intf);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tinfo->psg = PSG_new(ay_clock, *AYrate);\n\t\t\tif (info->psg == NULL)\n\t\t\t\treturn 0;\n\t\t\tPSG_setVolumeMode((PSG*)info->psg, 1);\t// YM2149 volume mode\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\tinfo->psg = NULL;\n\t\t*AYrate = 0;\n\t}\n\t//assert_always(info->psg != NULL, \"Error creating YM2608/AY8910 chip\");\n\n\t/* Timer Handler set */\n\t//info->timer[0] = timer_alloc(device->machine, timer_callback_2608_0, info);\n\t//info->timer[1] = timer_alloc(device->machine, timer_callback_2608_1, info);\n\n\t/* stream system initialize */\n\t//info->stream = stream_create(device,0,2,rate,info,ym2608_stream_update);\n\t/* setup adpcm buffers */\n\t//pcmbufa  = device->region;\n\t//pcmsizea = device->regionbytes;\n\n\t/* initialize YM2608 */\n\t//info->chip = ym2608_init(info,device,device->clock,rate,\n\t//\t           pcmbufa,pcmsizea,\n\t//\t           timer_handler,IRQHandler,&psgintf);\n\tinfo->chip = ym2608_init(info, clock, rate, NULL, NULL, &psgintf);\n\t//assert_always(info->chip != NULL, \"Error creating YM2608 chip\");\n\n\t//state_save_register_postload(device->machine, ym2608_intf_postload, info);\n\t\n\treturn rate;\n}\n\n//static DEVICE_STOP( ym2608 )\nvoid device_stop_ym2608(UINT8 ChipID)\n{\n\t//ym2608_state *info = get_safe_token(device);\n\tym2608_state *info = &YM2608Data[ChipID];\n\tym2608_shutdown(info->chip);\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_stop_ym(info->psg);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_delete((PSG*)info->psg);\n\t\t\tbreak;\n\t\t}\n\t\tinfo->psg = NULL;\n\t}\n}\n\n//static DEVICE_RESET( ym2608 )\nvoid device_reset_ym2608(UINT8 ChipID)\n{\n\t//ym2608_state *info = get_safe_token(device);\n\tym2608_state *info = &YM2608Data[ChipID];\n\tym2608_reset_chip(info->chip);\t// also resets the AY clock\n\t//psg_reset(info);\t// already done as a callback in ym2608_reset_chip\n}\n\n\n//READ8_DEVICE_HANDLER( ym2608_r )\nUINT8 ym2608_r(UINT8 ChipID, offs_t offset)\n{\n\t//ym2608_state *info = get_safe_token(device);\n\tym2608_state *info = &YM2608Data[ChipID];\n\treturn ym2608_read(info->chip, offset & 3);\n}\n\n//WRITE8_DEVICE_HANDLER( ym2608_w )\nvoid ym2608_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//ym2608_state *info = get_safe_token(device);\n\tym2608_state *info = &YM2608Data[ChipID];\n\tym2608_write(info->chip, offset & 3, data);\n}\n\n//READ8_DEVICE_HANDLER( ym2608_read_port_r )\nUINT8 ym2608_read_port_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2608_r(ChipID, 1);\n}\n//READ8_DEVICE_HANDLER( ym2608_status_port_a_r )\nUINT8 ym2608_status_port_a_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2608_r(ChipID, 0);\n}\n//READ8_DEVICE_HANDLER( ym2608_status_port_b_r )\nUINT8 ym2608_status_port_b_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2608_r(ChipID, 2);\n}\n\n//WRITE8_DEVICE_HANDLER( ym2608_control_port_a_w )\nvoid ym2608_control_port_a_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2608_w(ChipID, 0, data);\n}\n//WRITE8_DEVICE_HANDLER( ym2608_control_port_b_w )\nvoid ym2608_control_port_b_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2608_w(ChipID, 2, data);\n}\n//WRITE8_DEVICE_HANDLER( ym2608_data_port_a_w )\nvoid ym2608_data_port_a_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2608_w(ChipID, 1, data);\n}\n//WRITE8_DEVICE_HANDLER( ym2608_data_port_b_w )\nvoid ym2608_data_port_b_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2608_w(ChipID, 3, data);\n}\n\n\nvoid ym2608_set_ay_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tAY_EMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;\n#else\n\tAY_EMU_CORE = EC_EMU2149;\n#endif\n\t\n\treturn;\n}\n\nvoid ym2608_write_data_pcmrom(UINT8 ChipID, UINT8 rom_id, offs_t ROMSize, offs_t DataStart,\n\t\t\t\t\t\t\t  offs_t DataLength, const UINT8* ROMData)\n{\n\tym2608_state* info = &YM2608Data[ChipID];\n\tym2608_write_pcmrom(info->chip, rom_id, ROMSize, DataStart, DataLength, ROMData);\n}\n\nvoid ym2608_set_mute_mask(UINT8 ChipID, UINT32 MuteMaskFM, UINT32 MuteMaskAY)\n{\n\tym2608_state* info = &YM2608Data[ChipID];\n\tym2608_set_mutemask(info->chip, MuteMaskFM);\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_set_mute_mask_ym(info->psg, MuteMaskAY);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_setMask((PSG*)info->psg, MuteMaskAY);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid ym2608_set_srchg_cb(UINT8 ChipID, SRATE_CALLBACK CallbackFunc, void* DataPtr, void* AYDataPtr)\n{\n\tym2608_state* info = &YM2608Data[ChipID];\n\t\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_set_srchg_cb_ym(info->psg, CallbackFunc, AYDataPtr);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\treturn;\n}\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( ym2608 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ym2608_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ym2608 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( ym2608 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( ym2608 );\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YM2608\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Yamaha FM\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/2608intf.h",
    "content": "#pragma once\n\n#include \"fm.h\"\n#include \"ay8910.h\"\n#include \"emu2149.h\"\n\nvoid ym2608_update_request(void *param);\n\ntypedef struct _ym2608_interface ym2608_interface;\nstruct _ym2608_interface\n{\n\tay8910_interface ay8910_intf;\n\t//void ( *handler )( const device_config *device, int irq );\t/* IRQ handler for the YM2608 */\n\tvoid ( *handler )( int irq );\t/* IRQ handler for the YM2608 */\n};\n\n/*READ8_DEVICE_HANDLER( ym2608_r );\nWRITE8_DEVICE_HANDLER( ym2608_w );\n\nREAD8_DEVICE_HANDLER( ym2608_read_port_r );\nREAD8_DEVICE_HANDLER( ym2608_status_port_a_r );\nREAD8_DEVICE_HANDLER( ym2608_status_port_b_r );\n\nWRITE8_DEVICE_HANDLER( ym2608_control_port_a_w );\nWRITE8_DEVICE_HANDLER( ym2608_control_port_b_w );\nWRITE8_DEVICE_HANDLER( ym2608_data_port_a_w );\nWRITE8_DEVICE_HANDLER( ym2608_data_port_b_w );\n\nDEVICE_GET_INFO( ym2608 );\n#define SOUND_YM2608 DEVICE_GET_INFO_NAME( ym2608 )*/\n\nvoid ym2608_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nvoid ym2608_stream_update_ay(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_ym2608(UINT8 ChipID, int clock, UINT8 AYDisable, UINT8 AYFlags, int* AYrate);\nvoid device_stop_ym2608(UINT8 ChipID);\nvoid device_reset_ym2608(UINT8 ChipID);\n\nUINT8 ym2608_r(UINT8 ChipID, offs_t offset);\nvoid ym2608_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nUINT8 ym2608_read_port_r(UINT8 ChipID, offs_t offset);\nUINT8 ym2608_status_port_a_r(UINT8 ChipID, offs_t offset);\nUINT8 ym2608_status_port_b_r(UINT8 ChipID, offs_t offset);\n\nvoid ym2608_control_port_a_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2608_control_port_b_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2608_data_port_a_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2608_data_port_b_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid ym2608_set_ay_emu_core(UINT8 Emulator);\nvoid ym2608_write_data_pcmrom(UINT8 ChipID, UINT8 rom_id, offs_t ROMSize, offs_t DataStart,\n\t\t\t\t\t\t\t  offs_t DataLength, const UINT8* ROMData);\nvoid ym2608_set_mute_mask(UINT8 ChipID, UINT32 MuteMaskFM, UINT32 MuteMaskAY);\nvoid ym2608_set_srchg_cb(UINT8 ChipID, SRATE_CALLBACK CallbackFunc, void* DataPtr, void* AYDataPtr);\n"
  },
  {
    "path": "VGMPlay/chips/2610intf.c",
    "content": "/***************************************************************************\n\n  2610intf.c\n\n  The YM2610 emulator supports up to 2 chips.\n  Each chip has the following connections:\n  - Status Read / Control Write A\n  - Port Read / Data Write A\n  - Control Write B\n  - Data Write B\n\n***************************************************************************/\n\n#include <stdlib.h>\t// for free\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#include \"2610intf.h\"\n#include \"fm.h\"\n\n\n#ifdef ENABLE_ALL_CORES\n#define EC_MAME\t\t0x01\t// AY8910 core from MAME\n#endif\n#define EC_EMU2149\t0x00\n\ntypedef struct _ym2610_state ym2610_state;\nstruct _ym2610_state\n{\n\t//sound_stream *\tstream;\n\t//emu_timer *\t\ttimer[2];\n\tvoid *\t\t\tchip;\n\tvoid *\t\t\tpsg;\n\t//const ym2610_interface *intf;\n\t//const device_config *device;\n};\n\n#define CHTYPE_YM2610\t0x22\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nstatic UINT8 AY_EMU_CORE = 0x00;\nextern UINT32 SampleRate;\n\n#define MAX_CHIPS\t0x02\n\nstatic ym2610_state YM2610Data[MAX_CHIPS];\n\n/*INLINE ym2610_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_YM2610 || sound_get_type(device) == SOUND_YM2610B);\n\treturn (ym2610_state *)device->token;\n}*/\n\n\nstatic void psg_set_clock(void *param, int clock)\n{\n\tym2610_state *info = (ym2610_state *)param;\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_set_clock_ym(info->psg, clock);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_set_clock((PSG*)info->psg, clock);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstatic void psg_write(void *param, int address, int data)\n{\n\tym2610_state *info = (ym2610_state *)param;\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_write_ym(info->psg, address, data);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_writeIO((PSG*)info->psg, address, data);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstatic int psg_read(void *param)\n{\n\tym2610_state *info = (ym2610_state *)param;\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\treturn ay8910_read_ym(info->psg);\n#endif\n\t\tcase EC_EMU2149:\n\t\t\treturn PSG_readIO((PSG*)info->psg);\n\t\t}\n\t}\n\treturn 0x00;\n}\n\nstatic void psg_reset(void *param)\n{\n\tym2610_state *info = (ym2610_state *)param;\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_reset_ym(info->psg);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_reset((PSG*)info->psg);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstatic const ssg_callbacks psgintf =\n{\n\tpsg_set_clock,\n\tpsg_write,\n\tpsg_read,\n\tpsg_reset\n};\n\n/*------------------------- TM2610 -------------------------------*/\n/* IRQ Handler */\n/*static void IRQHandler(void *param,int irq)\n{\n\tym2610_state *info = (ym2610_state *)param;\n\t//if(info->intf->handler) info->intf->handler(info->device, irq);\n\t//if(info->intf->handler) info->intf->handler(irq);\n}*/\n\n/* Timer overflow callback from timer.c */\n/*static TIMER_CALLBACK( timer_callback_0 )\n{\n\tym2610_state *info = (ym2610_state *)ptr;\n\tym2610_timer_over(info->chip,0);\n}\n\nstatic TIMER_CALLBACK( timer_callback_1 )\n{\n\tym2610_state *info = (ym2610_state *)ptr;\n\tym2610_timer_over(info->chip,1);\n}*/\n\n/*static void timer_handler(void *param,int c,int count,int clock)\n{\n\tym2610_state *info = (ym2610_state *)param;\n\tif( count == 0 )\n\t{\t// Reset FM Timer\n\t\t//timer_enable(info->timer[c], 0);\n\t}\n\telse\n\t{\t// Start FM Timer\n\t\t//attotime period = attotime_mul(ATTOTIME_IN_HZ(clock), count);\n\n\t\t//if (!timer_enable(info->timer[c], 1))\n\t\t//\ttimer_adjust_oneshot(info->timer[c], period, 0);\n\t}\n}*/\n\n/* update request from fm.c */\nvoid ym2610_update_request(void *param)\n{\n\tym2610_state *info = (ym2610_state *)param;\n\t//stream_update(info->stream);\n\t\n\tym2610b_update_one(info->chip, DUMMYBUF, 0);\n\t// Not necessary.\n\t//if (info->psg != NULL)\n\t//\tay8910_update_one(info->psg, DUMMYBUF, 0);\n}\n\n\n//static STREAM_UPDATE( ym2610_stream_update )\nvoid ym2610_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ym2610_state *info = (ym2610_state *)param;\n\tym2610_state *info = &YM2610Data[ChipID];\n\tym2610_update_one(info->chip, outputs, samples);\n}\n\n//static STREAM_UPDATE( ym2610b_stream_update )\nvoid ym2610b_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ym2610_state *info = (ym2610_state *)param;\n\tym2610_state *info = &YM2610Data[ChipID];\n\tym2610b_update_one(info->chip, outputs, samples);\n}\n\nvoid ym2610_stream_update_ay(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ym2610_state *info = (ym2610_state *)param;\n\tym2610_state *info = &YM2610Data[ChipID];\n\t\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_update_one(info->psg, outputs, samples);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_calc_stereo((PSG*)info->psg, outputs, samples);\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\tmemset(outputs[0], 0x00, samples * sizeof(stream_sample_t));\n\t\tmemset(outputs[1], 0x00, samples * sizeof(stream_sample_t));\n\t}\n}\n\n\n//static STATE_POSTLOAD( ym2610_intf_postload )\n/*static void ym2610_intf_postload(UINT8 ChipID)\n{\n\t//ym2610_state *info = (ym2610_state *)param;\n\tym2610_state *info = &YM2610Data[ChipID];\n\tym2610_postload(info->chip);\n}*/\n\n\n//static DEVICE_START( ym2610 )\nint device_start_ym2610(UINT8 ChipID, int clock, UINT8 AYDisable, int* AYrate)\n{\n\t// clock bit 31:\t0 - YM2610\n\t//\t\t\t\t\t1 - YM2610B\n\t\n\t//static const ym2610_interface generic_2610 = { 0 };\n\tstatic const ay8910_interface generic_ay8910 =\n\t{\n\t\tAY8910_LEGACY_OUTPUT | AY8910_SINGLE_OUTPUT,\n\t\tAY8910_DEFAULT_LOADS\n\t\t//DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL\n\t};\n\t//const ym2610_interface *intf = device->static_config ? (const ym2610_interface *)device->static_config : &generic_2610;\n\t//const ym2610_interface *intf = &generic_2610;\n\tint rate;\n\tint ay_clock;\n\t//void *pcmbufa,*pcmbufb;\n\t//int  pcmsizea,pcmsizeb;\n\t//ym2610_state *info = get_safe_token(device);\n\tym2610_state *info;\n\t//astring *name = astring_alloc();\n\t//sound_type type = sound_get_type(device);\n\tunsigned char ChipType;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &YM2610Data[ChipID];\n\tChipType = (clock & 0x80000000) ? 0x01 : 0x00;\n\tclock &= 0x7FFFFFFF;\n\trate = clock/72;\n\tif ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\t//info->intf = intf;\n\t//info->device = device;\n\t//info->psg = ay8910_start_ym(NULL, sound_get_type(device), device, device->clock, &generic_ay8910);\n\tif (! AYDisable)\n\t{\n\t\tay_clock = clock / 4;\n\t\t*AYrate = ay_clock / 8;\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tinfo->psg = ay8910_start_ym(NULL, CHTYPE_YM2610 + ChipType, ay_clock, &generic_ay8910);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tinfo->psg = PSG_new(ay_clock, *AYrate);\n\t\t\tif (info->psg == NULL)\n\t\t\t\treturn 0;\n\t\t\tPSG_setVolumeMode((PSG*)info->psg, 1);\t// YM2149 volume mode\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\tinfo->psg = NULL;\n\t\t*AYrate = 0;\n\t}\n\t//assert_always(info->psg != NULL, \"Error creating YM2610/AY8910 chip\");\n\n\t/* Timer Handler set */\n\t//info->timer[0] = timer_alloc(device->machine, timer_callback_0, info);\n\t//info->timer[1] = timer_alloc(device->machine, timer_callback_1, info);\n\n\t/* stream system initialize */\n\t//info->stream = stream_create(device,0,2,rate,info,(type == SOUND_YM2610) ? ym2610_stream_update : ym2610b_stream_update);\n\t/* setup adpcm buffers */\n\t//pcmbufa  = device->region;\n\t//pcmsizea = device->regionbytes;\n\t//astring_printf(name, \"%s.deltat\", device->tag);\n\t//pcmbufb  = (void *)(memory_region(device->machine, astring_c(name)));\n\t//pcmsizeb = memory_region_length(device->machine, astring_c(name));\n\t//astring_free(name);\n\t/*if (pcmbufb == NULL || pcmsizeb == 0)\n\t{\n\t\tpcmbufb = pcmbufa;\n\t\tpcmsizeb = pcmsizea;\n\t}*/\n\n\t/**** initialize YM2610 ****/\n\t//info->chip = ym2610_init(info,device,device->clock,rate,\n\t//\t           pcmbufa,pcmsizea,pcmbufb,pcmsizeb,\n\t//\t           timer_handler,IRQHandler,&psgintf);\n\tinfo->chip = ym2610_init(info, clock & 0x7FFFFFFF, rate, NULL, NULL, &psgintf);\n\t//assert_always(info->chip != NULL, \"Error creating YM2610 chip\");\n\n\t//state_save_register_postload(device->machine, ym2610_intf_postload, info);\n\t\n\treturn rate;\n}\n\n//static DEVICE_STOP( ym2610 )\nvoid device_stop_ym2610(UINT8 ChipID)\n{\n\t//ym2610_state *info = get_safe_token(device);\n\tym2610_state* info = &YM2610Data[ChipID];\n\tym2610_shutdown(info->chip);\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_stop_ym(info->psg);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_delete((PSG*)info->psg);\n\t\t\tbreak;\n\t\t}\n\t\tinfo->psg = NULL;\n\t}\n}\n\n//static DEVICE_RESET( ym2610 )\nvoid device_reset_ym2610(UINT8 ChipID)\n{\n\t//ym2610_state *info = get_safe_token(device);\n\tym2610_state* info = &YM2610Data[ChipID];\n\tym2610_reset_chip(info->chip);\t// also resets the AY clock\n\t//psg_reset(info);\t// already done as a callback in ym2610_reset_chip\n}\n\n\n//READ8_DEVICE_HANDLER( ym2610_r )\nUINT8 ym2610_r(UINT8 ChipID, offs_t offset)\n{\n\t//ym2610_state *info = get_safe_token(device);\n\tym2610_state* info = &YM2610Data[ChipID];\n\treturn ym2610_read(info->chip, offset & 3);\n}\n\n//WRITE8_DEVICE_HANDLER( ym2610_w )\nvoid ym2610_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//ym2610_state *info = get_safe_token(device);\n\tym2610_state* info = &YM2610Data[ChipID];\n\tym2610_write(info->chip, offset & 3, data);\n}\n\n\n//READ8_DEVICE_HANDLER( ym2610_status_port_a_r )\nUINT8 ym2610_status_port_a_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2610_r(ChipID, 0);\n}\n//READ8_DEVICE_HANDLER( ym2610_status_port_b_r )\nUINT8 ym2610_status_port_b_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2610_r(ChipID, 2);\n}\n//READ8_DEVICE_HANDLER( ym2610_read_port_r )\nUINT8 ym2610_read_port_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2610_r(ChipID, 1);\n}\n\n//WRITE8_DEVICE_HANDLER( ym2610_control_port_a_w )\nvoid ym2610_control_port_a_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2610_w(ChipID, 0, data);\n}\n//WRITE8_DEVICE_HANDLER( ym2610_control_port_b_w )\nvoid ym2610_control_port_b_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2610_w(ChipID, 2, data);\n}\n//WRITE8_DEVICE_HANDLER( ym2610_data_port_a_w )\nvoid ym2610_data_port_a_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2610_w(ChipID, 1, data);\n}\n//WRITE8_DEVICE_HANDLER( ym2610_data_port_b_w )\nvoid ym2610_data_port_b_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2610_w(ChipID, 3, data);\n}\n\n\nvoid ym2610_set_ay_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tAY_EMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;\n#else\n\tAY_EMU_CORE = EC_EMU2149;\n#endif\n\t\n\treturn;\n}\n\nvoid ym2610_write_data_pcmrom(UINT8 ChipID, UINT8 rom_id, offs_t ROMSize, offs_t DataStart,\n\t\t\t\t\t\t\t  offs_t DataLength, const UINT8* ROMData)\n{\n\tym2610_state* info = &YM2610Data[ChipID];\n\tym2610_write_pcmrom(info->chip, rom_id, ROMSize, DataStart, DataLength, ROMData);\n}\n\nvoid ym2610_set_mute_mask(UINT8 ChipID, UINT32 MuteMaskFM, UINT32 MuteMaskAY)\n{\n\tym2610_state* info = &YM2610Data[ChipID];\n\tym2610_set_mutemask(info->chip, MuteMaskFM);\n\tif (info->psg != NULL)\n\t{\n\t\tswitch(AY_EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tay8910_set_mute_mask_ym(info->psg, MuteMaskAY);\n\t\t\tbreak;\n#endif\n\t\tcase EC_EMU2149:\n\t\t\tPSG_setMask((PSG*)info->psg, MuteMaskAY);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( ym2610 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ym2610_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ym2610 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( ym2610 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( ym2610 );\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YM2610\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Yamaha FM\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n\n/*DEVICE_GET_INFO( ym2610b )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YM2610B\");\t\t\t\t\tbreak;\n\n\t\tdefault:\t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(ym2610);\t\t\t\tbreak;\n\t}\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/2610intf.h",
    "content": "#pragma once\n\n#include \"fm.h\"\n#include \"ay8910.h\"\n#include \"emu2149.h\"\n\n\nvoid ym2610_update_request(void *param);\n\n/*typedef struct _ym2610_interface ym2610_interface;\nstruct _ym2610_interface\n{\n\t//void ( *handler )( const device_config *device, int irq );\t// IRQ handler for the YM2610\n\tvoid ( *handler )( int irq );\t// IRQ handler for the YM2610\n};*/\n\n/*READ8_DEVICE_HANDLER( ym2610_r );\nWRITE8_DEVICE_HANDLER( ym2610_w );\n\nREAD8_DEVICE_HANDLER( ym2610_status_port_a_r );\nREAD8_DEVICE_HANDLER( ym2610_status_port_b_r );\nREAD8_DEVICE_HANDLER( ym2610_read_port_r );\n\nWRITE8_DEVICE_HANDLER( ym2610_control_port_a_w );\nWRITE8_DEVICE_HANDLER( ym2610_control_port_b_w );\nWRITE8_DEVICE_HANDLER( ym2610_data_port_a_w );\nWRITE8_DEVICE_HANDLER( ym2610_data_port_b_w );\n\n\nDEVICE_GET_INFO( ym2610 );\nDEVICE_GET_INFO( ym2610b );\n\n#define SOUND_YM2610 DEVICE_GET_INFO_NAME( ym2610 )\n#define SOUND_YM2610B DEVICE_GET_INFO_NAME( ym2610b )*/\n\nvoid ym2610_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nvoid ym2610b_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nvoid ym2610_stream_update_ay(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_ym2610(UINT8 ChipID, int clock, UINT8 AYDisable, int* AYrate);\nvoid device_stop_ym2610(UINT8 ChipID);\nvoid device_reset_ym2610(UINT8 ChipID);\n\nUINT8 ym2610_r(UINT8 ChipID, offs_t offset);\nvoid ym2610_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nUINT8 ym2610_status_port_a_r(UINT8 ChipID, offs_t offset);\nUINT8 ym2610_status_port_b_r(UINT8 ChipID, offs_t offset);\nUINT8 ym2610_read_port_r(UINT8 ChipID, offs_t offset);\n\nvoid ym2610_control_port_a_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2610_control_port_b_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2610_data_port_a_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2610_data_port_b_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid ym2610_set_ay_emu_core(UINT8 Emulator);\nvoid ym2610_write_data_pcmrom(UINT8 ChipID, UINT8 rom_id, offs_t ROMSize, offs_t DataStart,\n\t\t\t\t\t\t\t  offs_t DataLength, const UINT8* ROMData);\nvoid ym2610_set_mute_mask(UINT8 ChipID, UINT32 MuteMaskFM, UINT32 MuteMaskAY);\n\n"
  },
  {
    "path": "VGMPlay/chips/2612intf.c",
    "content": "/***************************************************************************\n\n  2612intf.c\n\n  The YM2612 emulator supports up to 2 chips.\n  Each chip has the following connections:\n  - Status Read / Control Write A\n  - Port Read / Data Write A\n  - Control Write B\n  - Data Write B\n\n***************************************************************************/\n\n#include <stdlib.h>\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n//#include \"sound/fm.h\"\n//#include \"sound/2612intf.h\"\n#include \"fm.h\"\n#include \"2612intf.h\"\n#ifdef ENABLE_ALL_CORES\n#include \"ym2612.h\"\n#include \"ym3438.h\"\n#endif\n\n\n#define EC_MAME\t\t0x00\t// YM2612 core from MAME (now fixed, so it isn't worse than Gens anymore)\n#ifdef ENABLE_ALL_CORES\n#define EC_GENS\t\t0x02\t// Gens YM2612 core from in_vgm\n#define EC_NUKED\t0x01\t// Nuked YM3438/YM2612 core\n#endif\n\ntypedef struct _ym2612_state ym2612_state;\nstruct _ym2612_state\n{\n\t//sound_stream *\tstream;\n\t//emu_timer *\t\ttimer[2];\n\tvoid *\t\t\tchip;\n\t//const ym2612_interface *intf;\n\t//const device_config *device;\n};\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nstatic UINT8 EMU_CORE = 0x00;\n\n#define MAX_CHIPS\t0x02\nstatic ym2612_state YM2612Data[MAX_CHIPS];\nstatic int* GensBuf[0x02] = {NULL, NULL};\nstatic UINT8 ChipFlags = 0x00;\n\n/*INLINE ym2612_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_YM2612 || sound_get_type(device) == SOUND_YM3438);\n\treturn (ym2612_state *)device->token;\n}*/\n\n/*------------------------- TM2612 -------------------------------*/\n/* IRQ Handler */\n/*static void IRQHandler(void *param,int irq)\n{\n\tym2612_state *info = (ym2612_state *)param;\n\t//if(info->intf->handler) info->intf->handler(info->device, irq);\n\t//if(info->intf->handler) info->intf->handler(irq);\n}*/\n\n/* Timer overflow callback from timer.c */\n//static TIMER_CALLBACK( timer_callback_2612_0 )\n/*void timer_callback_2612_0(void *ptr, int param)\n{\n\tym2612_state *info = (ym2612_state *)ptr;\n\tym2612_timer_over(info->chip,0);\n}\n\n//static TIMER_CALLBACK( timer_callback_2612_1 )\nvoid timer_callback_2612_1(void *ptr, int param)\n{\n\tym2612_state *info = (ym2612_state *)ptr;\n\tym2612_timer_over(info->chip,1);\n}*/\n\n/*static void timer_handler(void *param,int c,int count,int clock)\n{\n\tym2612_state *info = (ym2612_state *)param;\n\tif( count == 0 )\n\t{\t// Reset FM Timer\n\t\t//timer_enable(info->timer[c], 0);\n\t}\n\telse\n\t{\t// Start FM Timer\n\t\t//attotime period = attotime_mul(ATTOTIME_IN_HZ(clock), count);\n\t\t//if (!timer_enable(info->timer[c], 1))\n\t\t//\ttimer_adjust_oneshot(info->timer[c], period, 0);\n\t}\n}*/\n\n/* update request from fm.c */\nvoid ym2612_update_request(void *param)\n{\n\tym2612_state *info = (ym2612_state *)param;\n\t//stream_update(info->stream);\n\t\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tym2612_update_one(info->chip, DUMMYBUF, 0);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_GENS:\n\t\tYM2612_Update(info->chip, DUMMYBUF, 0);\n\t\tYM2612_DacAndTimers_Update(info->chip, DUMMYBUF, 0);\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tbreak;\n#endif\n\t}\n}\n\n/***********************************************************/\n/*    YM2612                                               */\n/***********************************************************/\n\n//static STREAM_UPDATE( ym2612_stream_update )\nvoid ym2612_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ym2612_state *info = (ym2612_state *)param;\n\tym2612_state *info = &YM2612Data[ChipID];\n#ifdef ENABLE_ALL_CORES\n\tint i;\n#endif\n\t\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tym2612_update_one(info->chip, outputs, samples);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_GENS:\n\t\tYM2612_ClearBuffer(GensBuf, samples);\n\t\tYM2612_Update(info->chip, GensBuf, samples);\n\t\tYM2612_DacAndTimers_Update(info->chip, GensBuf, samples);\n\t\tfor (i = 0x00; i < samples; i ++)\n\t\t{\n\t\t\toutputs[0x00][i] = (stream_sample_t)GensBuf[0x00][i];\n\t\t\toutputs[0x01][i] = (stream_sample_t)GensBuf[0x01][i];\n\t\t}\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tOPN2_GenerateStream(info->chip, outputs, samples);\n\t\tbreak;\n#endif\n\t}\n}\n\n\n//static STATE_POSTLOAD( ym2612_intf_postload )\n/*static void ym2612_intf_postload(UINT8 ChipID)\n{\n\t//ym2612_state *info = (ym2612_state *)param;\n\tym2612_state *info = &YM2612Data[ChipID];\n\tym2612_postload(info->chip);\n}*/\n\n\n//static DEVICE_START( ym2612 )\nint device_start_ym2612(UINT8 ChipID, int clock)\n{\n\t//static const ym2612_interface dummy = { 0 };\n\t//ym2612_state *info = get_safe_token(device);\n\tym2612_state *info;\n\tint rate;\n\tint chiptype;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchiptype = clock&0x80000000;\n\tclock&=0x3fffffff;\n\t\n\tinfo = &YM2612Data[ChipID];\n\trate = clock/72;\n\tif (! (EMU_CORE == EC_MAME && (ChipFlags & 0x04)))\t// if not (\"double rate\" required)\n\t\trate /= 2;\n\tif ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\t//info->intf = device->static_config ? (const ym2612_interface *)device->static_config : &dummy;\n\t//info->intf = &dummy;\n\t//info->device = device;\n\n\t/* FM init */\n\t/* Timer Handler set */\n\t//info->timer[0] = timer_alloc(device->machine, timer_callback_2612_0, info);\n\t//info->timer[1] = timer_alloc(device->machine, timer_callback_2612_1, info);\n\n\t/* stream system initialize */\n\t//info->stream = stream_create(device,0,2,rate,info,ym2612_stream_update);\n\n\t/**** initialize YM2612 ****/\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\t//info->chip = ym2612_init(info,clock,rate,timer_handler,IRQHandler);\n\t\tinfo->chip = ym2612_init(info, clock, rate, NULL, NULL);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_GENS:\n\t\tif (GensBuf[0x00] == NULL)\n\t\t{\n\t\t\tGensBuf[0x00] = malloc(sizeof(int) * 0x100);\n\t\t\tGensBuf[0x01] = GensBuf[0x00] + 0x80;\n\t\t}\n\t\tinfo->chip = YM2612_Init(clock, rate, 0x00);\n\t\tYM2612_SetMute(info->chip, 0x80);\t// Disable SSG-EG\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tinfo->chip = malloc(sizeof(ym3438_t));\n\t\tif(chiptype)\n\t\t\tOPN2_SetChipType(ym3438_type_discrete);\n\t\tOPN2_Reset(info->chip, rate, clock);\n#endif\n\t}\n\t//assert_always(info->chip != NULL, \"Error creating YM2612 chip\");\n\t//ym2612_postload(info->chip);\n\n\t//state_save_register_postload(device->machine, ym2612_intf_postload, info);\n\t//ym2612_intf_postload();\n\treturn rate;\n}\n\n\n//static DEVICE_STOP( ym2612 )\nvoid device_stop_ym2612(UINT8 ChipID)\n{\n\t//ym2612_state *info = get_safe_token(device);\n\tym2612_state *info = &YM2612Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tym2612_shutdown(info->chip);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_GENS:\n\t\tYM2612_End(info->chip);\n\t\tif (GensBuf[0x00] != NULL)\n\t\t{\n\t\t\tfree(GensBuf[0x00]);\n\t\t\tGensBuf[0x00] = NULL;\n\t\t\tGensBuf[0x01] = NULL;\n\t\t}\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tfree(info->chip);\n\t\tbreak;\n#endif\n\t}\n}\n\n//static DEVICE_RESET( ym2612 )\nvoid device_reset_ym2612(UINT8 ChipID)\n{\n\t//ym2612_state *info = get_safe_token(device);\n\tym2612_state *info = &YM2612Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tym2612_reset_chip(info->chip);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_GENS:\n\t\tYM2612_Reset(info->chip);\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tOPN2_Reset(info->chip, 0, 0);\n\t\tbreak;\n#endif\n\t}\n}\n\n\n//READ8_DEVICE_HANDLER( ym2612_r )\nUINT8 ym2612_r(UINT8 ChipID, offs_t offset)\n{\n\t//ym2612_state *info = get_safe_token(device);\n\tym2612_state *info = &YM2612Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\treturn ym2612_read(info->chip, offset & 3);\n#ifdef ENABLE_ALL_CORES\n\tcase EC_GENS:\n\t\treturn YM2612_Read(info->chip);\n\tcase EC_NUKED:\n\t\treturn OPN2_Read(info->chip, offset);\n#endif\n\tdefault:\n\t\treturn 0x00;\n\t}\n}\n\n//WRITE8_DEVICE_HANDLER( ym2612_w )\nvoid ym2612_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//ym2612_state *info = get_safe_token(device);\n\tym2612_state *info = &YM2612Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tym2612_write(info->chip, offset & 3, data);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_GENS:\n\t\tYM2612_Write(info->chip, (unsigned char)(offset & 0x03), data);\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tOPN2_WriteBuffered(info->chip, offset, data);\n\t\tbreak;\n#endif\n\t}\n}\n\n\n/*READ8_DEVICE_HANDLER( ym2612_status_port_a_r ) { return ym2612_r(device, 0); }\nREAD8_DEVICE_HANDLER( ym2612_status_port_b_r ) { return ym2612_r(device, 2); }\nREAD8_DEVICE_HANDLER( ym2612_data_port_a_r ) { return ym2612_r(device, 1); }\nREAD8_DEVICE_HANDLER( ym2612_data_port_b_r ) { return ym2612_r(device, 3); }\n\nWRITE8_DEVICE_HANDLER( ym2612_control_port_a_w ) { ym2612_w(device, 0, data); }\nWRITE8_DEVICE_HANDLER( ym2612_control_port_b_w ) { ym2612_w(device, 2, data); }\nWRITE8_DEVICE_HANDLER( ym2612_data_port_a_w ) { ym2612_w(device, 1, data); }\nWRITE8_DEVICE_HANDLER( ym2612_data_port_b_w ) { ym2612_w(device, 3, data); }*/\nUINT8 ym2612_status_port_a_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2612_r(ChipID, 0);\n}\nUINT8 ym2612_status_port_b_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2612_r(ChipID, 2);\n}\nUINT8 ym2612_data_port_a_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2612_r(ChipID, 1);\n}\nUINT8 ym2612_data_port_b_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym2612_r(ChipID, 3);\n}\n\nvoid ym2612_control_port_a_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2612_w(ChipID, 0, data);\n}\nvoid ym2612_control_port_b_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2612_w(ChipID, 2, data);\n}\nvoid ym2612_data_port_a_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2612_w(ChipID, 1, data);\n}\nvoid ym2612_data_port_b_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym2612_w(ChipID, 3, data);\n}\n\n\nvoid ym2612_set_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tEMU_CORE = (Emulator < 0x03) ? Emulator : 0x00;\n#else\n\tEMU_CORE = EC_MAME;\n#endif\n\t\n\treturn;\n}\n\nvoid ym2612_set_options(UINT8 Flags)\n{\n\tChipFlags = Flags;\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tym2612_setoptions(Flags);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_GENS:\n\t\tYM2612_SetOptions(Flags);\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tOPN2_SetOptions(Flags);\n\t\tbreak;\n#endif\n\t}\n\t\n\treturn;\n}\n\nvoid ym2612_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tym2612_state *info = &YM2612Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tym2612_set_mutemask(info->chip, MuteMask);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_GENS:\n\t\tYM2612_SetMute(info->chip, (int)MuteMask);\n\t\tbreak;\n\tcase EC_NUKED:\n\t\tOPN2_SetMute(info->chip, MuteMask);\n\t\tbreak;\n#endif\n\t}\n\t\n\treturn;\n}\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( ym2612 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ym2612_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ym2612 );\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( ym2612 );\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( ym2612 );\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YM2612\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Yamaha FM\");\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}\n\n\nDEVICE_GET_INFO( ym3438 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YM3438\");\t\t\t\t\t\t\tbreak;\n\n\t\tdefault:\t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(ym2612);\t\t\t\t\t\tbreak;\n\t}\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/2612intf.h",
    "content": "#pragma once\n\nvoid ym2612_update_request(void *param);\n\n/*typedef struct _ym2612_interface ym2612_interface;\nstruct _ym2612_interface\n{\n\t//void (*handler)(const device_config *device, int irq);\n\tvoid (*handler)(int irq);\n};*/\n\n/*READ8_DEVICE_HANDLER( ym2612_r );\nWRITE8_DEVICE_HANDLER( ym2612_w );\n\nREAD8_DEVICE_HANDLER( ym2612_status_port_a_r );\nREAD8_DEVICE_HANDLER( ym2612_status_port_b_r );\nREAD8_DEVICE_HANDLER( ym2612_data_port_a_r );\nREAD8_DEVICE_HANDLER( ym2612_data_port_b_r );\n\nWRITE8_DEVICE_HANDLER( ym2612_control_port_a_w );\nWRITE8_DEVICE_HANDLER( ym2612_control_port_b_w );\nWRITE8_DEVICE_HANDLER( ym2612_data_port_a_w );\nWRITE8_DEVICE_HANDLER( ym2612_data_port_b_w );\n\n\nDEVICE_GET_INFO( ym2612 );\n#define SOUND_YM2612 DEVICE_GET_INFO_NAME( ym2612 )*/\nvoid ym2612_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_ym2612(UINT8 ChipID, int clock);\nvoid device_stop_ym2612(UINT8 ChipID);\nvoid device_reset_ym2612(UINT8 ChipID);\n\nUINT8 ym2612_r(UINT8 ChipID, offs_t offset);\nvoid ym2612_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nUINT8 ym2612_status_port_a_r(UINT8 ChipID, offs_t offset);\nUINT8 ym2612_status_port_b_r(UINT8 ChipID, offs_t offset);\nUINT8 ym2612_data_port_a_r(UINT8 ChipID, offs_t offset);\nUINT8 ym2612_data_port_b_r(UINT8 ChipID, offs_t offset);\n\nvoid ym2612_control_port_a_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2612_control_port_b_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2612_data_port_a_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym2612_data_port_b_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid ym2612_set_emu_core(UINT8 Emulator);\nvoid ym2612_set_options(UINT8 Flags);\nvoid ym2612_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n\n/*typedef struct _ym3438_interface ym3438_interface;\nstruct _ym3438_interface\n{\n\t//void (*handler)(const device_config *device, int irq);\n\tvoid (*handler)(int irq);\n};\n\n\n#define ym3438_r\t\t\t\tym2612_r\n#define ym3438_w\t\t\t\tym2612_w\n\n#define ym3438_status_port_a_r\tym2612_status_port_a_r\n#define ym3438_status_port_b_r\tym2612_status_port_b_r\n#define ym3438_data_port_a_r\tym2612_data_port_a_r\n#define ym3438_data_port_b_r\tym2612_data_port_b_r\n\n#define ym3438_control_port_a_w\tym2612_control_port_a_w\n#define ym3438_control_port_b_w\tym2612_control_port_b_w\n#define ym3438_data_port_a_w\tym2612_data_port_a_w\n#define ym3438_data_port_b_w\tym2612_data_port_b_w*/\n\n\n//DEVICE_GET_INFO( ym3438 );\n//#define SOUND_YM3438 DEVICE_GET_INFO_NAME( ym3438 )\n"
  },
  {
    "path": "VGMPlay/chips/262intf.c",
    "content": "/***************************************************************************\n\n  262intf.c\n\n  MAME interface for YMF262 (OPL3) emulator\n\n***************************************************************************/\n#include \"mamedef.h\"\n//#include \"attotime.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#include \"262intf.h\"\n#ifdef ENABLE_ALL_CORES\n#include \"ymf262.h\"\n#endif\n\n#define OPLTYPE_IS_OPL3\n#include \"adlibemu.h\"\n\n\n#define EC_DBOPL\t0x00\t// DosBox OPL (AdLibEmu)\n#ifdef ENABLE_ALL_CORES\n#define EC_MAME\t\t0x01\t// YMF262 core from MAME\n#endif\n\ntypedef struct _ymf262_state ymf262_state;\nstruct _ymf262_state\n{\n\t//sound_stream *\tstream;\n\t//emu_timer *\t\ttimer[2];\n\tvoid *\t\t\tchip;\n\t//const ymf262_interface *intf;\n\t//const device_config *device;\n};\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nstatic UINT8 EMU_CORE = 0x00;\n\n#define MAX_CHIPS\t0x02\nstatic ymf262_state YMF262Data[MAX_CHIPS];\n\n/*INLINE ymf262_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_YMF262);\n\treturn (ymf262_state *)device->token;\n}*/\n\n\n\n\nstatic void IRQHandler_262(void *param,int irq)\n{\n\tymf262_state *info = (ymf262_state *)param;\n\t//if (info->intf->handler) (info->intf->handler)(info->device, irq);\n}\n\n/*static TIMER_CALLBACK( timer_callback_262_0 )\n{\n\tymf262_state *info = (ymf262_state *)ptr;\n\tymf262_timer_over(info->chip, 0);\n}\n\nstatic TIMER_CALLBACK( timer_callback_262_1 )\n{\n\tymf262_state *info = (ymf262_state *)ptr;\n\tymf262_timer_over(info->chip, 1);\n}*/\n\n//static void timer_handler_262(void *param,int timer, attotime period)\nstatic void timer_handler_262(void *param,int timer, int period)\n{\n\tymf262_state *info = (ymf262_state *)param;\n\tif( period == 0 )\n\t{\t/* Reset FM Timer */\n\t\t//timer_enable(info->timer[timer], 0);\n\t}\n\telse\n\t{\t/* Start FM Timer */\n\t\t//timer_adjust_oneshot(info->timer[timer], period, 0);\n\t}\n}\n\n//static STREAM_UPDATE( ymf262_stream_update )\nvoid ymf262_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ymf262_state *info = (ymf262_state *)param;\n\tymf262_state *info = &YMF262Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tymf262_update_one(info->chip, outputs, samples);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tadlib_OPL3_getsample(info->chip, outputs, samples);\n\t\tbreak;\n\t}\n}\n\nstatic void _stream_update(void *param/*, int interval*/)\n{\n\tymf262_state *info = (ymf262_state *)param;\n\t//stream_update(info->stream);\n\t\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tymf262_update_one(info->chip, DUMMYBUF, 0);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tadlib_OPL3_getsample(info->chip, DUMMYBUF, 0);\n\t\tbreak;\n\t}\n}\n\n\n//static DEVICE_START( ymf262 )\nint device_start_ymf262(UINT8 ChipID, int clock)\n{\n\t//static const ymf262_interface dummy = { 0 };\n\t//ymf262_state *info = get_safe_token(device);\n\tymf262_state *info;\n\tint rate;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &YMF262Data[ChipID];\n\trate = clock/288;\n\tif ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\n\t//info->intf = device->static_config ? (const ymf262_interface *)device->static_config : &dummy;\n\t//info->intf = &dummy;\n\t//info->device = device;\n\n\t/* stream system initialize */\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tinfo->chip = ymf262_init(clock,rate);\n\t\t//assert_always(info->chip != NULL, \"Error creating YMF262 chip\");\n\n\t\t//info->stream = stream_create(device,0,4,rate,info,ymf262_stream_update);\n\n\t\t/* YMF262 setup */\n\t\tymf262_set_timer_handler (info->chip, timer_handler_262, info);\n\t\tymf262_set_irq_handler   (info->chip, IRQHandler_262, info);\n\t\tymf262_set_update_handler(info->chip, _stream_update, info);\n\n\t\t//info->timer[0] = timer_alloc(device->machine, timer_callback_262_0, info);\n\t\t//info->timer[1] = timer_alloc(device->machine, timer_callback_262_1, info);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tinfo->chip = adlib_OPL3_init(clock, rate, _stream_update, info);\n\t\tbreak;\n\t}\n\t\n\treturn rate;\n}\n\n//static DEVICE_STOP( ymf262 )\nvoid device_stop_ymf262(UINT8 ChipID)\n{\n\t//ymf262_state *info = get_safe_token(device);\n\tymf262_state *info = &YMF262Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tymf262_shutdown(info->chip);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tadlib_OPL3_stop(info->chip);\n\t\tbreak;\n\t}\n}\n\n/* reset */\n//static DEVICE_RESET( ymf262 )\nvoid device_reset_ymf262(UINT8 ChipID)\n{\n\t//ymf262_state *info = get_safe_token(device);\n\tymf262_state *info = &YMF262Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tymf262_reset_chip(info->chip);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tadlib_OPL3_reset(info->chip);\n\t\tbreak;\n\t}\n}\n\n\n//READ8_DEVICE_HANDLER( ymf262_r )\nUINT8 ymf262_r(UINT8 ChipID, offs_t offset)\n{\n\t//ymf262_state *info = get_safe_token(device);\n\tymf262_state *info = &YMF262Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\treturn ymf262_read(info->chip, offset & 3);\n#endif\n\tcase EC_DBOPL:\n\t\treturn adlib_OPL3_reg_read(info->chip, offset & 0x03);\n\tdefault:\n\t\treturn 0x00;\n\t}\n}\n\n//WRITE8_DEVICE_HANDLER( ymf262_w )\nvoid ymf262_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//ymf262_state *info = get_safe_token(device);\n\tymf262_state *info = &YMF262Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tymf262_write(info->chip, offset & 3, data);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tadlib_OPL3_writeIO(info->chip, offset & 3, data);\n\t\tbreak;\n\t}\n}\n\n//READ8_DEVICE_HANDLER ( ymf262_status_r )\nUINT8 ymf262_status_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ymf262_r(ChipID, 0);\n}\n//WRITE8_DEVICE_HANDLER( ymf262_register_a_w )\nvoid ymf262_register_a_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tymf262_w(ChipID, 0, data);\n}\n//WRITE8_DEVICE_HANDLER( ymf262_register_b_w )\nvoid ymf262_register_b_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tymf262_w(ChipID, 2, data);\n}\n//WRITE8_DEVICE_HANDLER( ymf262_data_a_w )\nvoid ymf262_data_a_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tymf262_w(ChipID, 1, data);\n}\n//WRITE8_DEVICE_HANDLER( ymf262_data_b_w )\nvoid ymf262_data_b_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tymf262_w(ChipID, 3, data);\n}\n\n\nvoid ymf262_set_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tEMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;\n#else\n\tEMU_CORE = EC_DBOPL;\n#endif\n\t\n\treturn;\n}\n\nvoid ymf262_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tymf262_state *info = &YMF262Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tymf262_set_mutemask(info->chip, MuteMask);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tadlib_OPL3_set_mute_mask(info->chip, MuteMask);\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( ymf262 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ymf262_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ymf262 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( ymf262 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( ymf262 );\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YMF262\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Yamaha FM\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n\n"
  },
  {
    "path": "VGMPlay/chips/262intf.h",
    "content": "#pragma once\n\n\n/*typedef struct _ymf262_interface ymf262_interface;\nstruct _ymf262_interface\n{\n\t//void (*handler)(const device_config *device, int irq);\n\tvoid (*handler)(int irq);\n};*/\n\n\n/*READ8_DEVICE_HANDLER( ymf262_r );\nWRITE8_DEVICE_HANDLER( ymf262_w );\n\nREAD8_DEVICE_HANDLER ( ymf262_status_r );\nWRITE8_DEVICE_HANDLER( ymf262_register_a_w );\nWRITE8_DEVICE_HANDLER( ymf262_register_b_w );\nWRITE8_DEVICE_HANDLER( ymf262_data_a_w );\nWRITE8_DEVICE_HANDLER( ymf262_data_b_w );\n\n\nDEVICE_GET_INFO( ymf262 );\n#define SOUND_YMF262 DEVICE_GET_INFO_NAME( ymf262 )*/\n\nvoid ymf262_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_ymf262(UINT8 ChipID, int clock);\nvoid device_stop_ymf262(UINT8 ChipID);\nvoid device_reset_ymf262(UINT8 ChipID);\n\nUINT8 ymf262_r(UINT8 ChipID, offs_t offset);\nvoid ymf262_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nUINT8 ymf262_status_r(UINT8 ChipID, offs_t offset);\nvoid ymf262_register_a_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ymf262_register_b_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ymf262_data_a_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ymf262_data_b_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid ymf262_set_emu_core(UINT8 Emulator);\nvoid ymf262_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n"
  },
  {
    "path": "VGMPlay/chips/3526intf.c",
    "content": "/******************************************************************************\n* FILE\n*   Yamaha 3812 emulator interface - MAME VERSION\n*\n* CREATED BY\n*   Ernesto Corvi\n*\n* UPDATE LOG\n*   JB  28-04-2002  Fixed simultaneous usage of all three different chip types.\n*                       Used real sample rate when resample filter is active.\n*       AAT 12-28-2001  Protected Y8950 from accessing unmapped port and keyboard handlers.\n*   CHS 1999-01-09  Fixes new ym3812 emulation interface.\n*   CHS 1998-10-23  Mame streaming sound chip update\n*   EC  1998        Created Interface\n*\n* NOTES\n*\n******************************************************************************/\n#include \"mamedef.h\"\n//#include \"attotime.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n//#include \"cpuintrf.h\"\n#include \"3526intf.h\"\n#include \"fmopl.h\"\n\ntypedef struct _ym3526_state ym3526_state;\nstruct _ym3526_state\n{\n\t//sound_stream *\tstream;\n\t//emu_timer *\t\ttimer[2];\n\tvoid *\t\t\tchip;\n\t//const ym3526_interface *intf;\n\t//const device_config *device;\n};\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\n#define MAX_CHIPS\t0x02\nstatic ym3526_state YM3526Data[MAX_CHIPS];\n\n/*INLINE ym3526_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_YM3526);\n\treturn (ym3526_state *)device->token;\n}*/\n\n\n/* IRQ Handler */\nstatic void IRQHandler(void *param,int irq)\n{\n\tym3526_state *info = (ym3526_state *)param;\n\t//if (info->intf->handler) (info->intf->handler)(info->device, irq ? ASSERT_LINE : CLEAR_LINE);\n\t//if (info->intf->handler) (info->intf->handler)(irq ? ASSERT_LINE : CLEAR_LINE);\n}\n/* Timer overflow callback from timer.c */\n/*static TIMER_CALLBACK( timer_callback_0 )\n{\n\tym3526_state *info = (ym3526_state *)ptr;\n\tym3526_timer_over(info->chip,0);\n}\nstatic TIMER_CALLBACK( timer_callback_1 )\n{\n\tym3526_state *info = (ym3526_state *)ptr;\n\tym3526_timer_over(info->chip,1);\n}*/\n/* TimerHandler from fm.c */\n//static void TimerHandler(void *param,int c,attotime period)\nstatic void TimerHandler(void *param,int c,int period)\n{\n\tym3526_state *info = (ym3526_state *)param;\n\t//if( attotime_compare(period, attotime_zero) == 0 )\n\tif( period == 0 )\n\t{\t/* Reset FM Timer */\n\t\t//timer_enable(info->timer[c], 0);\n\t}\n\telse\n\t{\t/* Start FM Timer */\n\t\t//timer_adjust_oneshot(info->timer[c], period, 0);\n\t}\n}\n\n\n//static STREAM_UPDATE( ym3526_stream_update )\nvoid ym3526_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ym3526_state *info = (ym3526_state *)param;\n\tym3526_state *info = &YM3526Data[ChipID];\n\tym3526_update_one(info->chip, outputs, samples);\n}\n\nstatic void _stream_update(void *param/*, int interval*/)\n{\n\tym3526_state *info = (ym3526_state *)param;\n\t//stream_update(info->stream);\n\t\n\tym3526_update_one(info->chip, DUMMYBUF, 0);\n}\n\n\n//static DEVICE_START( ym3526 )\nint device_start_ym3526(UINT8 ChipID, int clock)\n{\n\t//static const ym3526_interface dummy = { 0 };\n\t//ym3526_state *info = get_safe_token(device);\n\tym3526_state *info;\n\tint rate;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &YM3526Data[ChipID];\n\trate = clock/72;\n\tif ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\t//info->intf = device->static_config ? (const ym3526_interface *)device->static_config : &dummy;\n\t//info->intf = &dummy;\n\t//info->device = device;\n\n\t/* stream system initialize */\n\tinfo->chip = ym3526_init(clock,rate);\n\t//assert_always(info->chip != NULL, \"Error creating YM3526 chip\");\n\n\t//info->stream = stream_create(device,0,1,rate,info,ym3526_stream_update);\n\t/* YM3526 setup */\n\tym3526_set_timer_handler (info->chip, TimerHandler, info);\n\tym3526_set_irq_handler   (info->chip, IRQHandler, info);\n\tym3526_set_update_handler(info->chip, _stream_update, info);\n\n\t//info->timer[0] = timer_alloc(device->machine, timer_callback_0, info);\n\t//info->timer[1] = timer_alloc(device->machine, timer_callback_1, info);\n\t\n\treturn rate;\n}\n\n//static DEVICE_STOP( ym3526 )\nvoid device_stop_ym3526(UINT8 ChipID)\n{\n\t//ym3526_state *info = get_safe_token(device);\n\tym3526_state *info = &YM3526Data[ChipID];\n\tym3526_shutdown(info->chip);\n}\n\n//static DEVICE_RESET( ym3526 )\nvoid device_reset_ym3526(UINT8 ChipID)\n{\n\t//ym3526_state *info = get_safe_token(device);\n\tym3526_state *info = &YM3526Data[ChipID];\n\tym3526_reset_chip(info->chip);\n}\n\n\n//READ8_DEVICE_HANDLER( ym3526_r )\nUINT8 ym3526_r(UINT8 ChipID, offs_t offset)\n{\n\t//ym3526_state *info = get_safe_token(device);\n\tym3526_state *info = &YM3526Data[ChipID];\n\treturn ym3526_read(info->chip, offset & 1);\n}\n\n//WRITE8_DEVICE_HANDLER( ym3526_w )\nvoid ym3526_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//ym3526_state *info = get_safe_token(device);\n\tym3526_state *info = &YM3526Data[ChipID];\n\tym3526_write(info->chip, offset & 1, data);\n}\n\n//READ8_DEVICE_HANDLER( ym3526_status_port_r )\nUINT8 ym3526_status_port_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym3526_r(ChipID, 0);\n}\n//READ8_DEVICE_HANDLER( ym3526_read_port_r )\nUINT8 ym3526_read_port_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym3526_r(ChipID, 1);\n}\n//WRITE8_DEVICE_HANDLER( ym3526_control_port_w )\nvoid ym3526_control_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym3526_w(ChipID, 0, data);\n}\n//WRITE8_DEVICE_HANDLER( ym3526_write_port_w )\nvoid ym3526_write_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym3526_w(ChipID, 1, data);\n}\n\n\nvoid ym3526_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tym3526_state *info = &YM3526Data[ChipID];\n\topl_set_mute_mask(info->chip, MuteMask);\n}\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( ym3526 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ym3526_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ym3526 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( ym3526 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( ym3526 );\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YM3526\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Yamaha FM\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/3526intf.h",
    "content": "#pragma once\n\n/*typedef struct _ym3526_interface ym3526_interface;\nstruct _ym3526_interface\n{\n\t//void (*handler)(const device_config *device, int linestate);\n\tvoid (*handler)(int linestate);\n};*/\n\n/*READ8_DEVICE_HANDLER( ym3526_r );\nWRITE8_DEVICE_HANDLER( ym3526_w );\n\nREAD8_DEVICE_HANDLER( ym3526_status_port_r );\nREAD8_DEVICE_HANDLER( ym3526_read_port_r );\nWRITE8_DEVICE_HANDLER( ym3526_control_port_w );\nWRITE8_DEVICE_HANDLER( ym3526_write_port_w );\n\nDEVICE_GET_INFO( ym3526 );\n#define SOUND_YM3526 DEVICE_GET_INFO_NAME( ym3526 )*/\nvoid ym3526_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_ym3526(UINT8 ChipID, int clock);\nvoid device_stop_ym3526(UINT8 ChipID);\nvoid device_reset_ym3526(UINT8 ChipID);\n\nUINT8 ym3526_r(UINT8 ChipID, offs_t offset);\nvoid ym3526_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nUINT8 ym3526_status_port_r(UINT8 ChipID, offs_t offset);\nUINT8 ym3526_read_port_r(UINT8 ChipID, offs_t offset);\nvoid ym3526_control_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym3526_write_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid ym3526_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/chips/3812intf.c",
    "content": "/******************************************************************************\n* FILE\n*   Yamaha 3812 emulator interface - MAME VERSION\n*\n* CREATED BY\n*   Ernesto Corvi\n*\n* UPDATE LOG\n*   JB  28-04-2002  Fixed simultaneous usage of all three different chip types.\n*                       Used real sample rate when resample filter is active.\n*       AAT 12-28-2001  Protected Y8950 from accessing unmapped port and keyboard handlers.\n*   CHS 1999-01-09  Fixes new ym3812 emulation interface.\n*   CHS 1998-10-23  Mame streaming sound chip update\n*   EC  1998        Created Interface\n*\n* NOTES\n*\n******************************************************************************/\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n//#include \"attotime.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n//#include \"cpuintrf.h\"\n#include \"3812intf.h\"\n#ifdef ENABLE_ALL_CORES\n#include \"fmopl.h\"\n#endif\n\n#define OPLTYPE_IS_OPL2\n#include \"adlibemu.h\"\n\n\n#define EC_DBOPL\t0x00\t// DosBox OPL (AdLibEmu)\n#ifdef ENABLE_ALL_CORES\n#define EC_MAME\t\t0x01\t// YM3826 core from MAME\n#endif\n\ntypedef struct _ym3812_state ym3812_state;\nstruct _ym3812_state\n{\n\t//sound_stream *\tstream;\n\t//emu_timer *\t\ttimer[2];\n\tvoid *\t\t\tchip;\n\t//const ym3812_interface *intf;\n\t//const device_config *device;\n};\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nstatic UINT8 EMU_CORE = 0x00;\n\n#define MAX_CHIPS\t0x02\nstatic ym3812_state YM3812Data[MAX_CHIPS];\n\n/*INLINE ym3812_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_YM3812);\n\treturn (ym3812_state *)device->token;\n}*/\n\n\n\nstatic void IRQHandler(void *param,int irq)\n{\n\tym3812_state *info = (ym3812_state *)param;\n\t//if (info->intf->handler) (info->intf->handler)(info->device, irq ? ASSERT_LINE : CLEAR_LINE);\n\t//if (info->intf->handler) (info->intf->handler)(irq ? ASSERT_LINE : CLEAR_LINE);\n}\n/*static TIMER_CALLBACK( timer_callback_0 )\n{\n\tym3812_state *info = (ym3812_state *)ptr;\n\tym3812_timer_over(info->chip,0);\n}\n\nstatic TIMER_CALLBACK( timer_callback_1 )\n{\n\tym3812_state *info = (ym3812_state *)ptr;\n\tym3812_timer_over(info->chip,1);\n}*/\n\n//static void TimerHandler(void *param,int c,attotime period)\nstatic void TimerHandler(void *param,int c,int period)\n{\n\tym3812_state *info = (ym3812_state *)param;\n\t//if( attotime_compare(period, attotime_zero) == 0 )\n\tif( period == 0 )\n\t{\t/* Reset FM Timer */\n\t\t//timer_enable(info->timer[c], 0);\n\t}\n\telse\n\t{\t/* Start FM Timer */\n\t\t//timer_adjust_oneshot(info->timer[c], period, 0);\n\t}\n}\n\n\n//static STREAM_UPDATE( ym3812_stream_update )\nvoid ym3812_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ym3812_state *info = (ym3812_state *)param;\n\tym3812_state *info = &YM3812Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tym3812_update_one(info->chip, outputs, samples);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tadlib_OPL2_getsample(info->chip, outputs, samples);\n\t\tbreak;\n\t}\n}\n\nstatic void _stream_update(void * param/*, int interval*/)\n{\n\tym3812_state *info = (ym3812_state *)param;\n\t//stream_update(info->stream);\n\t\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tym3812_update_one(info->chip, DUMMYBUF, 0);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tadlib_OPL2_getsample(info->chip, DUMMYBUF, 0);\n\t\tbreak;\n\t}\n}\n\n\n//static DEVICE_START( ym3812 )\nint device_start_ym3812(UINT8 ChipID, int clock)\n{\n\t//static const ym3812_interface dummy = { 0 };\n\t//ym3812_state *info = get_safe_token(device);\n\tym3812_state *info;\n\tint rate;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &YM3812Data[ChipID];\n\trate = (clock & 0x7FFFFFFF)/72;\n\tif ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\t//info->intf = device->static_config ? (const ym3812_interface *)device->static_config : &dummy;\n\t//info->intf = &dummy;\n\t//info->device = device;\n\n\t/* stream system initialize */\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tinfo->chip = ym3812_init(clock & 0x7FFFFFFF,rate);\n\t\t//assert_always(info->chip != NULL, \"Error creating YM3812 chip\");\n\n\t\t//info->stream = stream_create(device,0,1,rate,info,ym3812_stream_update);\n\n\t\t/* YM3812 setup */\n\t\tym3812_set_timer_handler (info->chip, TimerHandler, info);\n\t\tym3812_set_irq_handler   (info->chip, IRQHandler, info);\n\t\tym3812_set_update_handler(info->chip, _stream_update, info);\n\n\t\t//info->timer[0] = timer_alloc(device->machine, timer_callback_0, info);\n\t\t//info->timer[1] = timer_alloc(device->machine, timer_callback_1, info);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tinfo->chip = adlib_OPL2_init(clock & 0x7FFFFFFF, rate, _stream_update, info);\n\t\tbreak;\n\t}\n\t\n\treturn rate;\n}\n\n//static DEVICE_STOP( ym3812 )\nvoid device_stop_ym3812(UINT8 ChipID)\n{\n\t//ym3812_state *info = get_safe_token(device);\n\tym3812_state *info = &YM3812Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tym3812_shutdown(info->chip);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tadlib_OPL2_stop(info->chip);\n\t\tbreak;\n\t}\n}\n\n//static DEVICE_RESET( ym3812 )\nvoid device_reset_ym3812(UINT8 ChipID)\n{\n\t//ym3812_state *info = get_safe_token(device);\n\tym3812_state *info = &YM3812Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tym3812_reset_chip(info->chip);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tadlib_OPL2_reset(info->chip);\n\t\tbreak;\n\t}\n}\n\n\n//READ8_DEVICE_HANDLER( ym3812_r )\nUINT8 ym3812_r(UINT8 ChipID, offs_t offset)\n{\n\t//ym3812_state *info = get_safe_token(device);\n\tym3812_state *info = &YM3812Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\treturn ym3812_read(info->chip, offset & 1);\n#endif\n\tcase EC_DBOPL:\n\t\treturn adlib_OPL2_reg_read(info->chip, offset & 0x01);\n\tdefault:\n\t\treturn 0x00;\n\t}\n}\n\n//WRITE8_DEVICE_HANDLER( ym3812_w )\nvoid ym3812_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//ym3812_state *info = get_safe_token(device);\n\tym3812_state *info = &YM3812Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tym3812_write(info->chip, offset & 1, data);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tadlib_OPL2_writeIO(info->chip, offset & 1, data);\n\t\tbreak;\n\t}\n}\n\n//READ8_DEVICE_HANDLER( ym3812_status_port_r )\nUINT8 ym3812_status_port_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym3812_r(ChipID, 0);\n}\n//READ8_DEVICE_HANDLER( ym3812_read_port_r )\nUINT8 ym3812_read_port_r(UINT8 ChipID, offs_t offset)\n{\n\treturn ym3812_r(ChipID, 1);\n}\n//WRITE8_DEVICE_HANDLER( ym3812_control_port_w )\nvoid ym3812_control_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym3812_w(ChipID, 0, data);\n}\n//WRITE8_DEVICE_HANDLER( ym3812_write_port_w )\nvoid ym3812_write_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tym3812_w(ChipID, 1, data);\n}\n\n\nvoid ym3812_set_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tEMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;\n#else\n\tEMU_CORE = EC_DBOPL;\n#endif\n\t\n\treturn;\n}\n\nvoid ym3812_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tym3812_state *info = &YM3812Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\topl_set_mute_mask(info->chip, MuteMask);\n\t\tbreak;\n#endif\n\tcase EC_DBOPL:\n\t\tadlib_OPL2_set_mute_mask(info->chip, MuteMask);\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( ym3812 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ym3812_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ym3812 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( ym3812 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( ym3812 );\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YM3812\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Yamaha FM\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/3812intf.h",
    "content": "#pragma once\n\n/*typedef struct _ym3812_interface ym3812_interface;\nstruct _ym3812_interface\n{\n\t//void (*handler)(const device_config *device, int linestate);\n\tvoid (*handler)(int linestate);\n};*/\n\n/*READ8_DEVICE_HANDLER( ym3812_r );\nWRITE8_DEVICE_HANDLER( ym3812_w );\n\nREAD8_DEVICE_HANDLER( ym3812_status_port_r );\nREAD8_DEVICE_HANDLER( ym3812_read_port_r );\nWRITE8_DEVICE_HANDLER( ym3812_control_port_w );\nWRITE8_DEVICE_HANDLER( ym3812_write_port_w );\n\nDEVICE_GET_INFO( ym3812 );\n#define SOUND_YM3812 DEVICE_GET_INFO_NAME( ym3812 )*/\n\nvoid ym3812_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_ym3812(UINT8 ChipID, int clock);\nvoid device_stop_ym3812(UINT8 ChipID);\nvoid device_reset_ym3812(UINT8 ChipID);\n\nUINT8 ym3812_r(UINT8 ChipID, offs_t offset);\nvoid ym3812_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nUINT8 ym3812_status_port_r(UINT8 ChipID, offs_t offset);\nUINT8 ym3812_read_port_r(UINT8 ChipID, offs_t offset);\nvoid ym3812_control_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ym3812_write_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid ym3812_set_emu_core(UINT8 Emulator);\nvoid ym3812_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/chips/8950intf.c",
    "content": "/******************************************************************************\n* FILE\n*   Yamaha 3812 emulator interface - MAME VERSION\n*\n* CREATED BY\n*   Ernesto Corvi\n*\n* UPDATE LOG\n*   JB  28-04-2002  Fixed simultaneous usage of all three different chip types.\n*                       Used real sample rate when resample filter is active.\n*       AAT 12-28-2001  Protected Y8950 from accessing unmapped port and keyboard handlers.\n*   CHS 1999-01-09  Fixes new ym3812 emulation interface.\n*   CHS 1998-10-23  Mame streaming sound chip update\n*   EC  1998        Created Interface\n*\n* NOTES\n*\n******************************************************************************/\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n//#include \"attotime.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n//#include \"cpuintrf.h\"\n#include \"8950intf.h\"\n//#include \"fm.h\"\n#include \"fmopl.h\"\n\n\ntypedef struct _y8950_state y8950_state;\nstruct _y8950_state\n{\n\t//sound_stream *\tstream;\n\t//emu_timer *\t\ttimer[2];\n\tvoid *\t\t\tchip;\n\t//const y8950_interface *intf;\n\t//const device_config *device;\n};\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\n#define MAX_CHIPS\t0x02\nstatic y8950_state Y8950Data[MAX_CHIPS];\n\n/*INLINE y8950_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_Y8950);\n\treturn (y8950_state *)device->token;\n}*/\n\n\nstatic void IRQHandler(void *param,int irq)\n{\n\ty8950_state *info = (y8950_state *)param;\n\t//if (info->intf->handler) (info->intf->handler)(info->device, irq ? ASSERT_LINE : CLEAR_LINE);\n\t//if (info->intf->handler) (info->intf->handler)(irq ? ASSERT_LINE : CLEAR_LINE);\n}\n/*static TIMER_CALLBACK( timer_callback_0 )\n{\n\ty8950_state *info = (y8950_state *)ptr;\n\ty8950_timer_over(info->chip,0);\n}\nstatic TIMER_CALLBACK( timer_callback_1 )\n{\n\ty8950_state *info = (y8950_state *)ptr;\n\ty8950_timer_over(info->chip,1);\n}*/\n//static void TimerHandler(void *param,int c,attotime period)\nstatic void TimerHandler(void *param,int c,int period)\n{\n\ty8950_state *info = (y8950_state *)param;\n\t//if( attotime_compare(period, attotime_zero) == 0 )\n\tif( period == 0 )\n\t{\t/* Reset FM Timer */\n\t\t//timer_enable(info->timer[c], 0);\n\t}\n\telse\n\t{\t/* Start FM Timer */\n\t\t//timer_adjust_oneshot(info->timer[c], period, 0);\n\t}\n}\n\n\nstatic unsigned char Y8950PortHandler_r(void *param)\n{\n\ty8950_state *info = (y8950_state *)param;\n\t/*if (info->intf->portread)\n\t\treturn info->intf->portread(0);*/\n\treturn 0;\n}\n\nstatic void Y8950PortHandler_w(void *param,unsigned char data)\n{\n\ty8950_state *info = (y8950_state *)param;\n\t/*if (info->intf->portwrite)\n\t\tinfo->intf->portwrite(0,data);*/\n}\n\nstatic unsigned char Y8950KeyboardHandler_r(void *param)\n{\n\ty8950_state *info = (y8950_state *)param;\n\t/*if (info->intf->keyboardread)\n\t\treturn info->intf->keyboardread(0);*/\n\treturn 0;\n}\n\nstatic void Y8950KeyboardHandler_w(void *param,unsigned char data)\n{\n\ty8950_state *info = (y8950_state *)param;\n\t/*if (info->intf->keyboardwrite)\n\t\tinfo->intf->keyboardwrite(0,data);*/\n}\n\n//static STREAM_UPDATE( y8950_stream_update )\nvoid y8950_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//y8950_state *info = (y8950_state *)param;\n\ty8950_state *info = &Y8950Data[ChipID];\n\ty8950_update_one(info->chip, outputs, samples);\n}\n\nstatic void _stream_update(void *param/*, int interval*/)\n{\n\ty8950_state *info = (y8950_state *)param;\n\t//stream_update(info->stream);\n\t\n\ty8950_update_one(info->chip, DUMMYBUF, 0);\n}\n\n\n//static DEVICE_START( y8950 )\nint device_start_y8950(UINT8 ChipID, int clock)\n{\n\t//static const y8950_interface dummy = { 0 };\n\t//y8950_state *info = get_safe_token(device);\n\ty8950_state *info;\n\tint rate;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &Y8950Data[ChipID];\n\trate = clock/72;\n\tif ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\t//info->intf = device->static_config ? (const y8950_interface *)device->static_config : &dummy;\n\t//info->intf = &dummy;\n\t//info->device = device;\n\n\t/* stream system initialize */\n\tinfo->chip = y8950_init(clock,rate);\n\t//assert_always(info->chip != NULL, \"Error creating Y8950 chip\");\n\n\t/* ADPCM ROM data */\n\t//y8950_set_delta_t_memory(info->chip, device->region, device->regionbytes);\n\ty8950_set_delta_t_memory(info->chip, NULL, 0x00);\n\n\t//info->stream = stream_create(device,0,1,rate,info,y8950_stream_update);\n\n\t/* port and keyboard handler */\n\ty8950_set_port_handler(info->chip, Y8950PortHandler_w, Y8950PortHandler_r, info);\n\ty8950_set_keyboard_handler(info->chip, Y8950KeyboardHandler_w, Y8950KeyboardHandler_r, info);\n\n\t/* Y8950 setup */\n\ty8950_set_timer_handler (info->chip, TimerHandler, info);\n\ty8950_set_irq_handler   (info->chip, IRQHandler, info);\n\ty8950_set_update_handler(info->chip, _stream_update, info);\n\n\t//info->timer[0] = timer_alloc(device->machine, timer_callback_0, info);\n\t//info->timer[1] = timer_alloc(device->machine, timer_callback_1, info);\n\t\n\treturn rate;\n}\n\n//static DEVICE_STOP( y8950 )\nvoid device_stop_y8950(UINT8 ChipID)\n{\n\t//y8950_state *info = get_safe_token(device);\n\ty8950_state *info = &Y8950Data[ChipID];\n\ty8950_shutdown(info->chip);\n}\n\n//static DEVICE_RESET( y8950 )\nvoid device_reset_y8950(UINT8 ChipID)\n{\n\t//y8950_state *info = get_safe_token(device);\n\ty8950_state *info = &Y8950Data[ChipID];\n\ty8950_reset_chip(info->chip);\n}\n\n\n//READ8_DEVICE_HANDLER( y8950_r )\nUINT8 y8950_r(UINT8 ChipID, offs_t offset)\n{\n\t//y8950_state *info = get_safe_token(device);\n\ty8950_state *info = &Y8950Data[ChipID];\n\treturn y8950_read(info->chip, offset & 1);\n}\n\n//WRITE8_DEVICE_HANDLER( y8950_w )\nvoid y8950_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//y8950_state *info = get_safe_token(device);\n\ty8950_state *info = &Y8950Data[ChipID];\n\ty8950_write(info->chip, offset & 1, data);\n}\n\n//READ8_DEVICE_HANDLER( y8950_status_port_r )\nUINT8 y8950_status_port_r(UINT8 ChipID, offs_t offset)\n{\n\treturn y8950_r(ChipID, 0);\n}\n//READ8_DEVICE_HANDLER( y8950_read_port_r )\nUINT8 y8950_read_port_r(UINT8 ChipID, offs_t offset)\n{\n\treturn y8950_r(ChipID, 1);\n}\n//WRITE8_DEVICE_HANDLER( y8950_control_port_w )\nvoid y8950_control_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\ty8950_w(ChipID, 0, data);\n}\n//WRITE8_DEVICE_HANDLER( y8950_write_port_w )\nvoid y8950_write_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\ty8950_w(ChipID, 1, data);\n}\n\n\nvoid y8950_write_data_pcmrom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart,\n\t\t\t\t\t\t\t  offs_t DataLength, const UINT8* ROMData)\n{\n\ty8950_state* info = &Y8950Data[ChipID];\n\t\n\ty8950_write_pcmrom(info->chip, ROMSize, DataStart, DataLength, ROMData);\n\t\n\treturn;\n}\n\nvoid y8950_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\ty8950_state *info = &Y8950Data[ChipID];\n\topl_set_mute_mask(info->chip, MuteMask);\n}\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( y8950 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(y8950_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( y8950 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( y8950 );\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( y8950 );\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"Y8950\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Yamaha FM\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/8950intf.h",
    "content": "#pragma once\n\n/*typedef struct _y8950_interface y8950_interface;\nstruct _y8950_interface\n{\n\t//void (*handler)(const device_config *device, int linestate);\n\tvoid (*handler)(int linestate);\n\n\tread8_device_func keyboardread;\n\twrite8_device_func keyboardwrite;\n\tread8_device_func portread;\n\twrite8_device_func portwrite;\n};*/\n\n/*READ8_DEVICE_HANDLER( y8950_r );\nWRITE8_DEVICE_HANDLER( y8950_w );\n\nREAD8_DEVICE_HANDLER( y8950_status_port_r );\nREAD8_DEVICE_HANDLER( y8950_read_port_r );\nWRITE8_DEVICE_HANDLER( y8950_control_port_w );\nWRITE8_DEVICE_HANDLER( y8950_write_port_w );\n\nDEVICE_GET_INFO( y8950 );\n#define SOUND_Y8950 DEVICE_GET_INFO_NAME( y8950 )*/\nvoid y8950_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_y8950(UINT8 ChipID, int clock);\nvoid device_stop_y8950(UINT8 ChipID);\nvoid device_reset_y8950(UINT8 ChipID);\n\nUINT8 y8950_r(UINT8 ChipID, offs_t offset);\nvoid y8950_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nUINT8 y8950_status_port_r(UINT8 ChipID, offs_t offset);\nUINT8 y8950_read_port_r(UINT8 ChipID, offs_t offset);\nvoid y8950_control_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid y8950_write_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid y8950_write_data_pcmrom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart,\n\t\t\t\t\t\t\t  offs_t DataLength, const UINT8* ROMData);\nvoid y8950_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/chips/ChipIncl.h",
    "content": "// includes all chip-headers\n\n#include \"sn764intf.h\"\n#include \"2413intf.h\"\n#include \"2612intf.h\"\n#include \"2151intf.h\"\n#include \"segapcm.h\"\n#include \"rf5c68.h\"\n#include \"2203intf.h\"\n#include \"2608intf.h\"\n#include \"2610intf.h\"\n#include \"3812intf.h\"\n#include \"3526intf.h\"\n#include \"8950intf.h\"\n#include \"262intf.h\"\n#include \"ymz280b.h\"\n#include \"ymf271.h\"\n#include \"ymf278b.h\"\n#include \"scd_pcm.h\"\n#include \"pwm.h\"\n#include \"ay_intf.h\"\n#include \"dac_control.h\"\n#include \"gb.h\"\n#include \"nes_intf.h\"\n#include \"multipcm.h\"\n#include \"upd7759.h\"\n#include \"okim6258.h\"\n#include \"okim6295.h\"\n#include \"k051649.h\"\n#include \"k054539.h\"\n#include \"c6280intf.h\"\n#include \"c140.h\"\n#include \"k053260.h\"\n#include \"pokey.h\"\n#include \"qsound_intf.h\"\n#include \"scsp.h\"\n#include \"ws_audio.h\"\n#include \"vsu.h\"\n#include \"saa1099.h\"\n#include \"es5503.h\"\n#include \"es5506.h\"\n#include \"x1_010.h\"\n#include \"c352.h\"\n#include \"iremga20.h\"\n"
  },
  {
    "path": "VGMPlay/chips/Ootake_PSG.c",
    "content": "/******************************************************************************\nOotake\n・キューの参照処理をシンプルにした。テンポの安定性および音質の向上。\n・オーバーサンプリングしないようにした。（筆者の主観もあるが、PSGの場合、響きの\n  美しさが損なわれてしまうケースが多いため。速度的にもアップ）\n・ノイズの音質・音量を実機並みに調整した。v0.72\n・ノイズの周波数に0x1Fが書き込まれたときは、0x1Eと同じ周波数で音量を半分にして\n  鳴らすようにした。v0.68\n・現状は再生サンプルレートは44.1KHz固定とした。(CD-DA再生時の速度アップのため)\n・DDA音の発声が終了したときにいきなり波形を0にせず、フェードアウトさせるように\n  し、ノイズを軽減した。v0.57\n・DDAモード(サンプリング発声)のときの波形データのノイズが多く含まれている部分\n  をカットしして、音質を上げた。音量も調節した。v0.59\n・ノイズ音の音質・音量を調整して、実機の雰囲気に近づけた。v0.68\n・waveIndexの初期化とDDAモード時の動作を見直して実機の動作に近づけた。v0.63\n・waveIndexの初期化時にwaveテーブルも初期化するようにした。ファイヤープロレス\n  リング、Ｆ１トリプルバトルなどの音が実機に近づいた。v0.65\n・waveの波形の正負を実機同様にした。v0.74\n・waveの最小値が-14になるようにし音質を整えた。v0.74\n・クリティカルセクションは必要ない(書き込みが同時に行われるわけではない)ような\n  ので、省略し高速化した。v1.09\n・キュー処理(ApuQueue.c)をここに統合して高速化した。v1.10\n・低音領域のボリュームを上げて実機並みの聞こえやすさに近づけた。v1.46\n・LFO処理のの実装。\"はにいいんざすかい\"のOPや、フラッシュハイダースの効果音が\n  実機の音に近づいた。v1.59\n\nCopyright(C)2006-2012 Kitao Nakamura.\n\t改造版・後継版を公開なさるときは必ずソースコードを添付してください。\n\tその際に事後でかまいませんので、ひとことお知らせいただけると幸いです。\n\t商的な利用は禁じます。\n\tあとは「GNU General Public License(一般公衆利用許諾契約書)」に準じます。\n\n*******************************************************************************\n\t[PSG.c]\n\t\tＰＳＧを実装します。\n\n\tImplements the PSG.\n\n\tCopyright (C) 2004 Ki\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n******************************************************************************/\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <math.h>\n#include \"mamedef.h\"\n#include \"Ootake_PSG.h\"\n//#include \"MainBoard.h\" //Kitao追加\n//#include \"App.h\" //Kitao追加\n//#include \"PRINTF.h\" //Kitao追加\n//#define PRINTF\tprintf\n\n\n#define N_CHANNEL\t\t\t6\n\n//#define SAMPLE_RATE\t\t\t44100.0 //Kitao更新。現状は速度優先でサンプルレートを44100固定とした。\n#define OVERSAMPLE_RATE\t\t1.0 //Kitao更新。PSGはオーバーサンプリングすると響きの美しさが損なわれてしまうのでオーバーサンプリングしないようにした。速度的にもアップ。\n#define PSG_DECLINE\t\t\t(21.8500*6.0) //21.8500。Kitao追加。PSG音量の減少値。*6.0は各チャンネル足したぶんを割る意味。大きいほど音は減る。CDDAが100%のときにちょうど良いぐらいの音量に合わせよう。v2.19,v2.37,v2.39,v2.62更新\n#define VOL_TABLE_DECLINE\t-1.05809999010 //-1.05809999010で雀探物語２OK。Kitao追加。音量テーブルの減少値。マイナスが大きいほど小さい音が聞こえづらくなる。マイナスが小さすぎると平面的な音になる。v2.19,v2.37,v2.39,v2.40,v2.62,v2.65更新\n\t\t\t\t\t\t\t\t\t       //  ※PSG_DECLINEの値を変更した場合、減退率のベスト値も変更する必要がある。雀探物語２(マイナスが小さいとPSGが目立ちすぎてADPCMが聴きづらい)，大魔界村(マイナスが大きいと音篭り),ソルジャーブレイドで、PSG_DECLINE=(14.4701*6.0)で減退率-1.0498779900db前後が飛び抜けていい響き(うちの環境で主観)。\n\t\t\t\t\t\t\t\t\t\t   //\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  モトローダー(マイナスやや大き目がいい),１９４１(マイナス小さめがいい)なども微妙な値変更で大きく変わる。\n#define NOISE_TABLE_VALUE\t-18 : -1 //キレと聴きやすさで-18:-1をベストとした。最大値が大きい(+に近い)と重い音に。２つの値が離れていると重い音に。フォーメーションサッカー，大魔界村のエンディングのドラムなどで調整。v1.46,v2.40,v2.62更新\n\t\t\t\t\t\t\t\t\t //  ※VOL_TABLE_DECLINEによってこの値の最適値も変化する。\n#define SAMPLE_FADE_DECLINE\t 0.305998999951 //0.30599899951。Kitao追加。サンプリング音の消音時の音の減退量。ソルジャーブレイド,将棋初心者無用の音声で調整。基本的にこの値が小さいほうがノイズが減る(逆のケースもある)。v2.40\n\t\t\t\t\t\t\t\t\t\t\t//\t\t\t\t\t\t\tサンプリングドラムの音色が決まるので大事な値。値が大きすぎるとファイナルソルジャーやソルジャーブレイド,モトローダーなどでドラムがしょぼくなる。\n\n//#define RESMPL_RATE\t\tPSG_FRQ / OVERSAMPLE_RATE / SAMPLE_RATE\t// the lack of () is intentional\n\n\n/*-----------------------------------------------------------------------------\n\t[DEV NOTE]\n\n\tMAL\t\t\t--- 0 - 15 (15 で -0[dB], １減るごとに -3.0 [dB])\n\tAL\t\t\t--- 0 - 31 (31 で -0[dB], １減るごとに -1.5 [dB])\n\tLAL/RAL\t\t--- 0 - 15 (15 で -0[dB], １減るごとに -3.0 [dB])\n\n\t次のように解釈しなおす。\n\n\tMAL*2\t\t--- 0 - 30 (30 で -0[dB], １減るごとに -1.5 [dB])\n\tAL\t\t\t--- 0 - 31 (31 で -0[dB], １減るごとに -1.5 [dB])\n\tLAL/RAL*2\t--- 0 - 30 (30 で -0[dB], １減るごとに -1.5 [dB])\n\n\n\tdB = 20 * log10(OUT/IN)\n\n\tdB / 20 = log10(OUT/IN)\n\n\tOUT/IN = 10^(dB/20)\n\n\tIN(最大出力) を 1.0 とすると、\n\n\tOUT = 10^(dB/20)\n\n\t\t\t\t\t-91 <= -(MAL*2 + AL + LAL(RAL)*2) <= 0\n\n\tだから、最も小さい音は、\n\n\t\t-91 * 1.5 [dB] = -136.5 [dB] = 10^(-136.5/20) ~= 1.496236e-7 [倍]\n\n\tとなる。\n\n\t  1e-7 オーダーの値は、固定小数点で表現しようとすると、小数部だけで\n\t24 ビット以上必要で、なおかつ１６ビットの音声を扱うためには +16ビット\n\tだから 24+16 = 40ビット以上必要になる。よって、32 ビットの処理系で\n\tＰＣＥの音声を固定小数点で表現するのはつらい。そこで、波形の計算は\n\tfloat で行なうことにする。\n\n\t  float から出力形式に変換するのはＡＰＵの仕事とする。\n\n\t[2004.4.28] やっぱり Sint32 で実装することにした(微小な値は無視する)。\n\n\t  ＣＰＵとＰＳＧは同じＩＣにパッケージしてあるのだが、\n\t実際にはＰＳＧはＣＰＵの１／２のクロックで動作すると考えて良いようだ。\n\tよって、ＰＳＧの動作周波数 Fpsg は、\n\n\t\tFpsg = 21.47727 [MHz] / 3 / 2 = 3.579545 [MHz]\n\n\tとなる。\n\n\tたとえば３２サンプルを１周期とする波形が再生されるとき、\n\tこの周波数の周期でサンプルを１つずつ拾い出すと、\n\n\t\tM = 3579545 / 32 = 111860.78125 [Hz]\n\n\tというマジックナンバーが得られる（ファミコンと同じ）。\n\tただし、再生周波数が固定では曲の演奏ができないので、\n\tFRQ なる周波数パラメータを用いて再生周波数を変化させる。\n\tFRQ はＰＳＧのレジスタに書き込まれる１２ビット長のパラメータで、\n\t↑で得られたマジックナンバーの「割る数」になっている。\n\n\t上の３２サンプルを１周期とする波形が再生されるとき、\n\tこの波形の周波数 F は、FRQ を用いて、\n\t\n\t\tF = M / FRQ [Hz]  (FRQ != 0)\n\t\n\tとなる。\n\n\t  ＰＣの再生サンプリング周波数が Fpc [Hz] だとすると、\n\t１周期３２サンプルの波形の再生周波数 F2 は  F2 = Fpc / 32 [Hz]。\n\tよって、ＰＣの１サンプルに対して、ＰＣＥの１サンプルを拾い出す\n\tカウンタの進み幅 I は\n\n\t\tI = F / F2 = 32 * F / Fpc = Fpsg / FRQ / Fpc [単位なし]\n\n\tとなる。\n\n\t[NOISE CHANNEL]\n\n\t  擬似ノイズの生成にはＭ系列(maximum length sequence)が用いられる。\n\tＭ系列のビット長は未調査につき不明。\n\tここでは仮に１５ビットとして実装を行なう。\n\t出力は１ビットで、D0 がゼロのときは負の値、１のときは正の値とする。\n\n\tＰＣの１サンプルに対して、ＰＣＥの１サンプルを拾い出す\n\tカウンタの進み幅 I は、\n\n\t\tI = Fpsg / 64 / FRQ / Fpc  (FRQ != 0)\n\n\tとなる。\n\n\t[再生クオリティ向上について] 2004.6.22\n\n\t  エミュレータでは、ＰＳＧのレジスタにデータが書き込まれるまで、\n\t次に発声すべき音がわからない。レジスタにデータが書き込まれたときに、\n\tサウンドバッファを更新したいのだけど、あいにく現在の実装では、\n\tサウンドバッファの更新は別スレッドで行なわれていて、\n\tエミュレーションスレッドから任意の時間に更新することができない。\n\n\t  これまでの再生では、サウンドバッファの更新時のレジスタ設定のみが\n\t有効だったが、これだと例えばサウンドバッファ更新の合間に一瞬だけ\n\t出力された音などが無視されてしまう。これは特にＤＤＡモードやノイズが\n\tリズムパートとして使用される上で問題になる。\n\n\t  レジスタに書き込まれた値をきちんと音声出力に反映させるには、\n\t過去に書き込まれたレジスタの値(いつ、どのレジスタに、何が書き込まれたか)\n\tを保存しておいて、サウンドバッファ更新時にこれを参照する方法が\n\t考えられる。どのくらい過去までレジスタの値を保存しておくかは、\n\tサウンドバッファの長さにもよると思われるが、とりあえずは試行錯誤で\n\t決めることにする。\n\n\t  ＰＳＧレジスタへの書き込み動作はエミュレーションスレッドで\n\t行なわれ、サウンドバッファ更新はその専用スレッドで行なわれる。\n\tこれだと、エミュレーションスレッドがレジスタのキューに書き込みを\n\t行なっている最中に、サウンドバッファ更新スレッドがキューから\n\t読み出しを行なってしまい、アクセスが衝突する。この問題を解決するには、\n\n\t\t１．サウンドバッファの更新を別スレッドで行なわない\n\t\t２．キューのアクセス部分を排他処理にする\n\n\tの２とおりが考えられる。とりあえず２の方法をとることにする。\n---------------------------------------------------------------------------*/\n\n\ntypedef struct\n{\n\tUint32\t\tfrq;\n\tBOOL\t\tbOn;\n\tBOOL\t\tbDDA;\n\tUint32\t\tvolume;\n\tUint32\t\tvolumeL;\n\tUint32\t\tvolumeR;\n\tSint32\t\toutVolumeL;\n\tSint32\t\toutVolumeR;\n\tSint32\t\twave[32];\n\tUint32\t\twaveIndex;\n\tSint32\t\tddaSample;\n\tUint32\t\tphase;\n\tUint32\t\tdeltaPhase;\n\tBOOL\t\tbNoiseOn;\n\tUint32\t\tnoiseFrq;\n\tUint32\t\tdeltaNoisePhase;\n} PSG;\n\ntypedef struct\n{\n\tdouble SAMPLE_RATE;\n\tdouble PSG_FRQ;\n\tdouble RESMPL_RATE;\n\n\tPSG\t\t\tPsg[8];\t\t\t\t// 6, 7 is unused\n\tSint32\t\tDdaFadeOutL[8]; //Kitao追加\n\tSint32\t\tDdaFadeOutR[8]; //Kitao追加\n\tUint32\t\tChannel;\t\t\t\t// 0 - 5;\n\tUint32\t\tMainVolumeL;\t\t\t// 0 - 15\n\tUint32\t\tMainVolumeR;\t\t\t// 0 - 15\n\tUint32\t\tLfoFrq;\n\tBOOL\t\tbLfoOn; //v1.59から非使用。過去verのステートロードのために残してある。\n\tUint32\t\tLfoCtrl;\n\tUint32\t\tLfoShift; //v1.59から非使用。過去verのステートロードのために残してある。\n\tSint32\t\tPsgVolumeEffect;\t// = 0;//Kitao追加\n\tdouble\t\tVolume;\t// = 0;//Kitao追加\n\tdouble\t\tVOL;\t// = 0.0;//Kitao追加。v1.08\n//\tBOOL\t\t_bPsgMute[8] = {FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE};//Kitao追加。v1.29\n\tBOOL\t\tbPsgMute[8];\n\n\tUint8\t\tPort[16];\t\t\t\t// for debug purpose \n\n\tBOOL\t\tbWaveCrash; //Kitao追加。DDA再生中にWaveデータが書き換えられたらTRUE\n\tBOOL\t\tbHoneyInTheSky; //はにいいんざすかいパッチ用。v2.60\n} huc6280_state;\n\nstatic Sint32\t\t_VolumeTable[92];\nstatic Sint32\t\t_NoiseTable[32768];\n\n//static BOOL\t\t_bPsgInit = FALSE;\nstatic BOOL\t\t\t_bTblInit = FALSE;\n\n//Kitao更新。v1.10。キュー処理をここに統合して高速化。\n/*\n\tＡＰＵ専用キューの仕様\n\n\tレジスタに書き込みが行なわれるごとに、\n\tキューにその内容を追加する。\n\n\tサウンドバッファ更新時に経過時間をみて、\n\t過去に書き込まれたレジスタ内容を\n\t書き込まれた順にキューから取り出し、\n\tＰＳＧレジスタを更新する。\n\t（なおＰＳＧレジスタは全て write only とみなす)\n\t  ↑要確認\n\n\tキューに追加するときには write index を用い、\n\t取り出すときには read index を用いる。\n\n\t// 追加\n\tqueue[write index++] = written data\n\n\t// 取り出し\n\tdata = queue[read index++]\n\n\tキューから値を取り出したときに read index が\n\twrite index と一致したときは queue underflow。\n\t→とりあえずなにもしない。\n\n\tキューに値を追加したときに write index が\n\tread index と一致したときは queue overflow。\n\t→とりあえずリセットすることにする。\n*/\n\n/*#define APUQUEUE_SIZE\t65536*2\t\t\t\t// must be power of 2  v1.61更新。65536だとＡ列車３をオーバークロックしてプレイしたときに足りなかった。\n\ntypedef struct\t\t//Kitao更新。clockは非使用とした。v1.61からステートセーブのサイズを減らすために変数上からもカット。\n{\n\tUint8\t\t\treg;\t\t\t\t\t// 0-15\n\tUint8\t\t\tdata;\t\t\t\t\t// written data\n} ApuQueue;\ntypedef struct\t\t//v1.60以前のステートロードのため残してある。\n{\n\tUint32\t\t\tclock;\t\t\t\t\t// cpu cycles elapsed since previous write  Kitao更新。clockは現在非使用。\n\tUint8\t\t\treg;\t\t\t\t\t// 0-15\n\tUint8\t\t\tdata;\t\t\t\t\t// written data\n} OldApuQueue;\n\nstatic ApuQueue\t\t\t\t_Queue[APUQUEUE_SIZE];\nstatic Uint32\t\t\t\t_QueueWriteIndex;\nstatic Uint32\t\t\t\t_QueueReadIndex;*/\n\n\n//ボリュームテーブルの作成\n//Kitao更新。低音量の音が実機より聞こえづらいので、減退率をVOL_TABLE_DECLINE[db](試行錯誤したベスト値)とし、ノーマライズ処理をするようにした。v1.46\n//\t\t\t おそらく、実機もアンプを通って出力される際にノーマライズ処理されている。\nstatic void\ncreate_volume_table()\n{\n\tint\t\ti;\n\tdouble\tv;\n\n\t_VolumeTable[0] = 0; //Kitao追加\n\tfor (i = 1; i <= 91; i++)\n\t{\n\t\tv = 91 - i;\n\t\t_VolumeTable[i] = (Sint32)(32768.0 * pow(10.0, v * VOL_TABLE_DECLINE / 20.0)); //VOL_TABLE_DECLINE。小さくしすぎると音が平面的な傾向に。ソルジャーブレイドで調整。v1.46。\n\t}\n}\n\n\n//ノイズテーブルの作成\nstatic void\ncreate_noise_table()\n{\n\tSint32\ti;\n\tUint32\tbit0;\n\tUint32\tbit1;\n\tUint32\tbit14;\n\tUint32\treg = 0x100;\n\n\tfor (i = 0; i < 32768; i++)\n\t{\n\t\tbit0 = reg & 1;\n\t\tbit1 = (reg & 2) >> 1;\n\t\tbit14 = (bit0 ^ bit1);\n\t\treg >>= 1;\n\t\treg |= (bit14 << 14);\n\t\t_NoiseTable[i] = (bit0) ? NOISE_TABLE_VALUE; //Kitao更新。ノイズのボリュームと音質を調整した。\n\t}\n}\n\n\n/*-----------------------------------------------------------------------------\n\t[write_reg]\n\t\tＰＳＧポートの書き込みに対する動作を記述します。\n-----------------------------------------------------------------------------*/\n//static inline void\nINLINE void\nwrite_reg(\n\thuc6280_state* info,\n\tUint8\t\treg,\n\tUint8\t\tdata)\n{\n\tUint32\ti;\n\tUint32\tfrq;//Kitao追加\n\tPSG*\tPSGChn;\n\n\tinfo->Port[reg & 15] = data;\n\n\tswitch (reg & 15)\n\t{\n\t\tcase 0:\t// register select\n\t\t\tinfo->Channel = data & 7;\n\t\t\tbreak;\n\n\t\tcase 1:\t// main volume\n\t\t\tinfo->MainVolumeL = (data >> 4) & 0x0F;\n\t\t\tinfo->MainVolumeR = data & 0x0F;\n\n\t\t\t/* LMAL, RMAL は全チャネルの音量に影響する */\n\t\t\tfor (i = 0; i < N_CHANNEL; i++)\n\t\t\t{\n\t\t\t\tPSGChn = &info->Psg[i];\n\t\t\t\tPSGChn->outVolumeL = _VolumeTable[PSGChn->volume + (info->MainVolumeL + PSGChn->volumeL) * 2];\n\t\t\t\tPSGChn->outVolumeR = _VolumeTable[PSGChn->volume + (info->MainVolumeR + PSGChn->volumeR) * 2];\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 2:\t// frequency low\n\t\t\tPSGChn = &info->Psg[info->Channel];\n\t\t\tPSGChn->frq &= ~0xFF;\n\t\t\tPSGChn->frq |= data;\n\t\t\t//Kitao更新。update_frequencyは、速度アップのためサブルーチンにせず直接実行するようにした。\n\t\t\tfrq = (PSGChn->frq - 1) & 0xFFF;\n\t\t\tif (frq)\n\t\t\t\tPSGChn->deltaPhase = (Uint32)((double)(65536.0 * 256.0 * 8.0 * info->RESMPL_RATE) / (double)frq +0.5); //Kitao更新。速度アップのためfrq以外は定数計算にした。精度向上のため、先に値の小さいOVERSAMPLE_RATEのほうで割るようにした。+0.5は四捨五入で精度アップ。プチノイズ軽減のため。\n\t\t\telse\n\t\t\t\tPSGChn->deltaPhase = 0;\n\t\t\tbreak;\n\n\t\tcase 3:\t// frequency high\n\t\t\tPSGChn = &info->Psg[info->Channel];\n\t\t\tPSGChn->frq &= ~0xF00;\n\t\t\tPSGChn->frq |= (data & 0x0F) << 8;\n\t\t\t//Kitao更新。update_frequencyは、速度アップのためサブルーチンにせず直接実行するようにした。\n\t\t\tfrq = (PSGChn->frq - 1) & 0xFFF;\n\t\t\tif (frq)\n\t\t\t\tPSGChn->deltaPhase = (Uint32)((double)(65536.0 * 256.0 * 8.0 * info->RESMPL_RATE) / (double)frq +0.5); //Kitao更新。速度アップのためfrq以外は定数計算にした。精度向上のため、先に値の小さいOVERSAMPLE_RATEのほうで割るようにした。+0.5は四捨五入で精度アップ。プチノイズ軽減のため。\n\t\t\telse\n\t\t\t\tPSGChn->deltaPhase = 0;\n\t\t\tbreak;\n\n\t\tcase 4:\t// ON, DDA, AL\n\t\t\tPSGChn = &info->Psg[info->Channel];\n\t\t\tif (info->bHoneyInTheSky) //はにいいんざすかいのポーズ時に、微妙なボリューム調整タイミングの問題でプチノイズが載ってしまうので、現状はパッチ処理で対応。v2.60更新\n\t\t\t{\n\t\t\t\tif ((PSGChn->bOn)&&(data == 0)) //発声中にdataが0の場合、LRボリュームも0にリセット。はにいいんざすかいのポーズ時のノイズが解消。(data & 0x1F)だけが0のときにリセットすると、サイレントデバッガーズ等でNG。発声してない時にリセットするとアトミックロボでNG。ｖ2.55\n\t\t\t\t{\n\t\t\t\t\t//PRINTF(\"test %X %X %X %X\",info->Channel,PSGChn->bOn,info->MainVolumeL,info->MainVolumeR);\n\t\t\t\t\tif ((info->MainVolumeL & 1) == 0) //メインボリュームのbit0が0のときだけ処理(はにいいんざすかいでイレギュラーな0xE。他のゲームは0xF。※ヘビーユニットも0xEだった)。これがないとミズバク大冒険で音が出ない。実機の仕組みと同じかどうかは未確認。v2.53追加\n\t\t\t\t\t\tPSGChn->volumeL = 0;\n\t\t\t\t\tif ((info->MainVolumeR & 1) == 0) //右チャンネルも同様とする\n\t\t\t\t\t\tPSGChn->volumeR = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tPSGChn->bOn = ((data & 0x80) != 0);\n\t\t\tif ((PSGChn->bDDA)&&((data & 0x40)==0)) //DDAからWAVEへ切り替わるとき or DDAから消音するとき\n\t\t\t{\n\t\t\t\t//Kitao追加。DDAはいきなり消音すると目立つノイズが載るのでフェードアウトする。\n\t\t\t\tinfo->DdaFadeOutL[info->Channel] = (Sint32)((double)(PSGChn->ddaSample * PSGChn->outVolumeL) *\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t((1 + (1 >> 3) + (1 >> 4) + (1 >> 5) + (1 >> 7) + (1 >> 12) + (1 >> 14) + (1 >> 15)) * SAMPLE_FADE_DECLINE)); //元の音量。v2.65更新\n\t\t\t\tinfo->DdaFadeOutR[info->Channel] = (Sint32)((double)(PSGChn->ddaSample * PSGChn->outVolumeR) *\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t((1 + (1 >> 3) + (1 >> 4) + (1 >> 5) + (1 >> 7) + (1 >> 12) + (1 >> 14) + (1 >> 15)) * SAMPLE_FADE_DECLINE));\n\n\t\t\t}\n\t\t\tPSGChn->bDDA = ((data & 0x40) != 0);\n\t\t\t\n\t\t\t//Kitao追加。dataのbit7,6が01のときにWaveインデックスをリセットする。\n\t\t\t//DDAモード時にWaveデータを書き込んでいた場合はここでWaveデータを修復（初期化）する。ファイヤープロレスリング。\n\t\t\tif ((data & 0xC0) == 0x40)\n\t\t\t{\n\t\t\t\tPSGChn->waveIndex = 0;\n\t\t\t\tif (info->bWaveCrash)\n\t\t\t\t{\n\t\t\t\t\tfor (i=0; i<32; i++)\n\t\t\t\t\t\tPSGChn->wave[i] = -14; //Waveデータを最小値で初期化\n\t\t\t\t\tinfo->bWaveCrash = FALSE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tPSGChn->volume = data & 0x1F;\n\t\t\tPSGChn->outVolumeL = _VolumeTable[PSGChn->volume + (info->MainVolumeL + PSGChn->volumeL) * 2];\n\t\t\tPSGChn->outVolumeR = _VolumeTable[PSGChn->volume + (info->MainVolumeR + PSGChn->volumeR) * 2];\n\t\t\tbreak;\n\n\t\tcase 5:\t// LAL, RAL\n\t\t\tPSGChn = &info->Psg[info->Channel];\n\t\t\tPSGChn->volumeL = (data >> 4) & 0xF;\n\t\t\tPSGChn->volumeR = data & 0xF;\n\t\t\tPSGChn->outVolumeL = _VolumeTable[PSGChn->volume + (info->MainVolumeL + PSGChn->volumeL) * 2];\n\t\t\tPSGChn->outVolumeR = _VolumeTable[PSGChn->volume + (info->MainVolumeR + PSGChn->volumeR) * 2];\n\t\t\tbreak;\n\n\t\tcase 6:\t// wave data  //Kitao更新。DDAモードのときもWaveデータを更新するようにした。v0.63。ファイヤープロレスリング\n\t\t\tPSGChn = &info->Psg[info->Channel];\n\t\t\tdata &= 0x1F;\n\t\t\tinfo->bWaveCrash = FALSE; //Kitao追加\n\t\t\tif (!PSGChn->bOn) //Kitao追加。音を鳴らしていないときだけWaveデータを更新する。v0.65。F1トリプルバトルのエンジン音。\n\t\t\t{\n\t\t\t\tPSGChn->wave[PSGChn->waveIndex++] = 17 - data; //17。Kitao更新。一番心地よく響く値に。ミズバク大冒険，モトローダー，ドラゴンスピリット等で調整。\n\t\t\t\tPSGChn->waveIndex &= 0x1F;\n\t\t\t}\n\t\t\tif (PSGChn->bDDA)\n\t\t\t{\n\t\t\t\t//Kitao更新。ノイズ軽減のため6より下側の値はカットするようにした。v0.59\n\t\t\t\tif (data < 6) //サイバーナイトで6に決定\n\t\t\t\t\tdata = 6; //ノイズが多いので小さな値はカット\n\t\t\t\tPSGChn->ddaSample = 11 - data; //サイバーナイトで11に決定。ドラムの音色が最適。v0.74\n\t\t\t\n\t\t\t\tif (!PSGChn->bOn) //DDAモード時にWaveデータを書き換えた場合\n\t\t\t\t\tinfo->bWaveCrash = TRUE;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 7:\t// noise on, noise frq\n\t\t\tif (info->Channel >= 4)\n\t\t\t{\n\t\t\t\tPSGChn = &info->Psg[info->Channel];\n\t\t\t\tPSGChn->bNoiseOn = ((data & 0x80) != 0);\n\t\t\t\tPSGChn->noiseFrq = 0x1F - (data & 0x1F);\n\t\t\t\tif (PSGChn->noiseFrq == 0)\n\t\t\t\t\tPSGChn->deltaNoisePhase = (Uint32)((double)(2048.0 * info->RESMPL_RATE) +0.5); //Kitao更新\n\t\t\t\telse\n\t\t\t\t\tPSGChn->deltaNoisePhase = (Uint32)((double)(2048.0 * info->RESMPL_RATE) / (double)PSGChn->noiseFrq +0.5); //Kitao更新\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 8:\t// LFO frequency\n\t\t\tinfo->LfoFrq = data;\n\t\t\t//Kitaoテスト用\n\t\t\t//PRINTF(\"LFO Frq = %X\",info->LfoFrq);\n\t\t\tbreak;\n\n\t\tcase 9:\t// LFO control  Kitao更新。シンプルに実装してみた。実機で同じ動作かは未確認。はにいいんざすかいの音が似るように実装。v1.59\n\t\t\tif (data & 0x80) //bit7を立てて呼ぶと恐らくリセット\n\t\t\t{\n\t\t\t\tinfo->Psg[1].phase = 0; //LfoFrqは初期化しない。はにいいんざすかい。\n\t\t\t\t//Kitaoテスト用\n\t\t\t\t//PRINTF(\"LFO control = %X\",data);\n\t\t\t}\n\t\t\tinfo->LfoCtrl = data & 7; //ドロップロックほらホラで5が使われる。v1.61更新\n\t\t\tif (info->LfoCtrl & 4)\n\t\t\t\tinfo->LfoCtrl = 0; //ドロップロックほらホラ。実機で聴いた感じはLFOオフと同じ音のようなのでbit2が立っていた(負の数扱い？)ら0と同じこととする。\n\t\t\t//Kitaoテスト用\n\t\t\t//PRINTF(\"LFO control = %X,  Frq =%X\",data,info->LfoFrq);\n\t\t\tbreak;\n\n\t\tdefault:\t// invalid write\n\t\t\tbreak;\n\t}\n\n\treturn;\n}\n\n\n//Kitao追加\nstatic void\nset_VOL(huc6280_state* info)\n{\n\t//Sint32\tv;\n\n\tif (info->PsgVolumeEffect == 0)\n\t\t//info->VOL = 0.0; //ミュート\n\t\tinfo->VOL = 1.0 / 128.0;\n\telse if (info->PsgVolumeEffect == 3)\n\t\tinfo->VOL = info->Volume / (double)(OVERSAMPLE_RATE * 4.0/3.0); // 3/4。v1.29追加\n\telse\n\t\tinfo->VOL = info->Volume / (double)(OVERSAMPLE_RATE * info->PsgVolumeEffect); //Kitao追加。_PsgVolumeEffect=ボリューム調節効果。\n\n\t/*if (!APP_GetCDGame()) //Huカードゲームのときだけ、ボリューム101～120を有効化。v2.62\n\t{\n\t\tv = APP_GetWindowsVolume();\n\t\tif (v > 100)\n\t\t\t_VOL *= ((double)(v-100) * 3.0 + 100.0) / 100.0; //101～120は通常の3.0倍の音量変化。3.0倍のVol120でソルジャーブレイド最適。ビックリマンワールドOK。3.1倍以上だと音が薄くなる＆音割れの心配もあり。\n\t}*/\n}\n\n/*-----------------------------------------------------------------------------\n\t[Mix]\n\t\tＰＳＧの出力をミックスします。\n-----------------------------------------------------------------------------*/\nvoid\nPSG_Mix(\n//\tSint16*\t\tpDst,\t\t// 出力先バッファ //Kitao更新。PSG専用バッファにしたためSint16に。\n\tvoid*\t\tchip,\n\tSint32**\tpDst,\n\tSint32\t\tnSample)\t// 書き出すサンプル数 \n{\n\thuc6280_state* info = (huc6280_state*)chip;\n\tPSG*\t\tPSGChn;\n\tSint32\t\ti;\n\tSint32\t\tj;\n\tSint32\t\tsample; //Kitao追加\n\tSint32\t\tlfo;\n\tSint32\t\tsampleAllL; //Kitao追加。6chぶんのサンプルを足していくためのバッファ。精度を維持するために必要。6chぶん合計が終わった後に、これをSint16に変換して書き込むようにした。\n\tSint32\t\tsampleAllR; //Kitao追加。上のＲチャンネル用\n\tSint32\t\tsmp; //Kitao追加。DDA音量,ノイズ音量計算用\n\tSint32*\t\tbufL = pDst[0];\n\tSint32*\t\tbufR = pDst[1];\n\n//\tif (!_bPsgInit)\n//\t\treturn;\n\n\tfor (j=0; j<nSample; j++)\n\t{\n\t\tsampleAllL = 0;\n\t\tsampleAllR = 0;\n\t\tfor (i=0; i<N_CHANNEL; i++)\n\t\t{\n\t\t\tPSGChn = &info->Psg[i];\n\t\t\t\n\t\t\tif ((PSGChn->bOn)&&((i != 1)||(info->LfoCtrl == 0))&&(!info->bPsgMute[i])) //Kitao更新\n\t\t\t{\n\t\t\t\tif (PSGChn->bDDA)\n\t\t\t\t{\n\t\t\t\t\tsmp = PSGChn->ddaSample * PSGChn->outVolumeL;\n\t\t\t\t\tsampleAllL += smp + (smp >> 3) + (smp >> 4) + (smp >> 5) + (smp >> 7) + (smp >> 12) + (smp >> 14) + (smp >> 15); //Kitao更新。サンプリング音の音量を実機並みに調整。v2.39,v2.40,v2.62,v2.65再調整した。\n\t\t\t\t\tsmp = PSGChn->ddaSample * PSGChn->outVolumeR;\n\t\t\t\t\tsampleAllR += smp + (smp >> 3) + (smp >> 4) + (smp >> 5) + (smp >> 7) + (smp >> 12) + (smp >> 14) + (smp >> 15); //Kitao更新。サンプリング音の音量を実機並みに調整。v2.39,v2.40,v2.62,v2.65再調整した。\n\t\t\t\t}\n\t\t\t\telse if (PSGChn->bNoiseOn)\n\t\t\t\t{\n\t\t\t\t\tsample = _NoiseTable[PSGChn->phase >> 17];\n\t\t\t\t\t\n\t\t\t\t\tif (PSGChn->noiseFrq == 0) //Kitao追加。noiseFrq=0(dataに0x1Fが書き込まれた)のときは音量が通常の半分とした。（ファイヤープロレスリング３、パックランド、桃太郎活劇、がんばれゴルフボーイズなど）\n\t\t\t\t\t{\n\t\t\t\t\t\tsmp = sample * PSGChn->outVolumeL;\n\t\t\t\t\t\tsampleAllL += (smp >> 1) + (smp >> 12) + (smp >> 14); //(1/2 + 1/4096 + (1/32768 + 1/32768))\n\t\t\t\t\t\tsmp = sample * PSGChn->outVolumeR;\n\t\t\t\t\t\tsampleAllR += (smp >> 1) + (smp >> 12) + (smp >> 14);\n\t\t\t\t\t}\n\t\t\t\t\telse //通常\n\t\t\t\t\t{\n\t\t\t\t\t\tsmp = sample * PSGChn->outVolumeL;\n\t\t\t\t\t\tsampleAllL += smp + (smp >> 11) + (smp >> 14) + (smp >> 15); //Kitao更新。ノイズの音量を実機並みに調整(1 + 1/2048 + 1/16384 + 1/32768)。この\"+1/32768\"で絶妙(主観。大魔界村,ソルジャーブレイドなど)になる。v2.62更新\n\t\t\t\t\t\tsmp = sample * PSGChn->outVolumeR;\n\t\t\t\t\t\tsampleAllR += smp + (smp >> 11) + (smp >> 14) + (smp >> 15); //Kitao更新。ノイズの音量を実機並みに調整\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tPSGChn->phase += PSGChn->deltaNoisePhase; //Kitao更新\n\t\t\t\t}\n\t\t\t\telse if (PSGChn->deltaPhase)\n\t\t\t\t{\n\t\t\t\t\t//Kitao更新。オーバーサンプリングしないようにした。\n\t\t\t\t\tsample = PSGChn->wave[PSGChn->phase >> 27];\n\t\t\t\t\tif (PSGChn->frq < 128)\n\t\t\t\t\t\tsample -= sample >> 2; //低周波域の音量を制限。ブラッドギアのスタート時などで実機と同様の音に。ソルジャーブレイドなども実機に近くなった。v2.03\n\n\t\t\t\t\tsampleAllL += sample * PSGChn->outVolumeL; //Kitao更新\n\t\t\t\t\tsampleAllR += sample * PSGChn->outVolumeR; //Kitao更新\n\t\t\t\t\t\n\t\t\t\t\t//Kitao更新。Lfoオンが有効になるようにし、Lfoの掛かり具合を実機に近づけた。v1.59\n\t\t\t\t\tif ((i==0)&&(info->LfoCtrl>0))\n\t\t\t\t\t{\n\t\t\t\t\t\t//_LfoCtrlが1のときに0回シフト(そのまま)で、はにいいんざすかいが実機の音に近い。\n\t\t\t\t\t\t//_LfoCtrlが3のときに4回シフトで、フラッシュハイダースが実機の音に近い。\n\t\t\t\t\t\tlfo = info->Psg[1].wave[info->Psg[1].phase >> 27] << ((info->LfoCtrl-1) << 1); //v1.60更新\n\t\t\t\t\t\tinfo->Psg[0].phase += (Uint32)((double)(65536.0 * 256.0 * 8.0 * info->RESMPL_RATE) / (double)(info->Psg[0].frq + lfo) +0.5);\n\t\t\t\t\t\tinfo->Psg[1].phase += (Uint32)((double)(65536.0 * 256.0 * 8.0 *info-> RESMPL_RATE) / (double)(info->Psg[1].frq * info->LfoFrq) +0.5); //v1.60更新\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tPSGChn->phase += PSGChn->deltaPhase;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//Kitao追加。DDA消音時はノイズ軽減のためフェードアウトで消音する。\n\t\t\t//\t\t\t ベラボーマン(「わしがばくだはかせじゃ」から数秒後)やパワーテニス(タイトル曲終了から数秒後。点数コール)，将棋初心者無用(音声)等で効果あり。\n\t\t\tif (info->DdaFadeOutL[i] > 0)\n\t\t\t\t--info->DdaFadeOutL[i];\n\t\t\telse if (info->DdaFadeOutL[i] < 0)\n\t\t\t\t++info->DdaFadeOutL[i];\n\t\t\tif (info->DdaFadeOutR[i] > 0)\n\t\t\t\t--info->DdaFadeOutR[i];\n\t\t\telse if (info->DdaFadeOutR[i] < 0)\n\t\t\t\t++info->DdaFadeOutR[i];\n\t\t\tsampleAllL += info->DdaFadeOutL[i];\n\t\t\tsampleAllR += info->DdaFadeOutR[i];\n\t\t}\n\t\t//Kitao更新。6ch合わさったところで、ボリューム調整してバッファに書き込む。\n\t\tsampleAllL = (Sint32)((double)sampleAllL * info->VOL);\n\t\t//if ((sampleAllL>32767)||(sampleAllL<-32768)) PRINTF(\"PSG Sachitta!\");//test用\n//\t\tif (sampleAllL> 32767) sampleAllL= 32767; //Volをアップしたのでサチレーションチェックが必要。v2.39\n//\t\tif (sampleAllL<-32768) sampleAllL=-32768; //  パックランドでUFO等にやられたときぐらいで、通常のゲームでは起こらない。音量の大きなビックリマンワールドもOK。パックランドも通常はOKでサチレーションしたときでもわずかなので音質的に大丈夫。\n\t\t\t\t\t\t\t\t\t\t\t\t  //  なので音質的には、PSGを２つのDirectXチャンネルに分けて鳴らすべき(処理は重くなる)だが、現状はパックランドでもサチレーション処理だけで音質的に問題なし(速度優先)とする。\n\t\tsampleAllR = (Sint32)((double)sampleAllR * info->VOL);\n\t\t//if ((sampleAllR>32767)||(sampleAllR<-32768)) PRINTF(\"PSG Satitta!\");//test用\n//\t\tif (sampleAllR> 32767) sampleAllR= 32767; //Volをアップしたのでサチレーションチェックが必要。v2.39\n//\t\tif (sampleAllR<-32768) sampleAllR=-32768; //\n\t\t*bufL++ = sampleAllL;\n\t\t*bufR++ = sampleAllR;\n\t\t\n\t\t//キューを参照しPSGレジスタを更新する。Kitao更新。高速化のためサブルーチンにせずここで処理。キューの参照はシンプルにした(テンポの安定性向上)。\n\t\t/*while (_QueueReadIndex != _QueueWriteIndex) //v1.10更新。キュー処理をここへ統合し高速化。\n\t\t{\n\t\t\twrite_reg(_Queue[_QueueReadIndex].reg, _Queue[_QueueReadIndex].data);\n\t\t\t_QueueReadIndex++; //Kitao更新\n\t\t\t_QueueReadIndex &= APUQUEUE_SIZE-1; //Kitao更新\n\t\t}*/\n\t}\n}\n\n\n//Kitao更新\nstatic void\npsg_reset(huc6280_state* info)\n{\n\tint\t\ti,j;\n\n\tmemset(info->Psg, 0, sizeof(info->Psg));\n\tmemset(info->DdaFadeOutL, 0, sizeof(info->DdaFadeOutL)); //Kitao追加\n\tmemset(info->DdaFadeOutR, 0, sizeof(info->DdaFadeOutR)); //Kitao追加\n\tinfo->MainVolumeL = 0;\n\tinfo->MainVolumeR = 0;\n\tinfo->LfoFrq = 0;\n\tinfo->LfoCtrl = 0;\n\tinfo->Channel = 0; //Kitao追加。v2.65\n\tinfo->bWaveCrash = FALSE; //Kitao追加\n\n\t//Kitao更新。v0.65．waveデータを初期化。\n\tfor (i=0; i<N_CHANNEL; i++)\n\t\tfor (j=0; j<32; j++)\n\t\t\tinfo->Psg[i].wave[j] = -14; //最小値で初期化。ファイプロ，フォーメーションサッカー'90，F1トリプルバトルで必要。\n\tfor (j=0; j<32; j++)\n\t\tinfo->Psg[3].wave[j] = 17; //ch3は最大値で初期化。F1トリプルバトル。v2.65\n\n\t//Kitao更新。v1.10。キュー処理をここに統合\n//\t_QueueWriteIndex = 0;\n//\t_QueueReadIndex  = 0;\n}\n\n\nstatic void PSG_SetVolume(huc6280_state* info);\n/*-----------------------------------------------------------------------------\n\t[Init]\n\t\tＰＳＧを初期化します。\n-----------------------------------------------------------------------------*/\n//Sint32\nvoid*\nPSG_Init(\n\tSint32\t\tclock,\n\tSint32\t\tsampleRate)\n{\n\thuc6280_state* info;\n\t\n\tinfo = (huc6280_state*)malloc(sizeof(huc6280_state));\n\tif (info == NULL)\n\t\treturn NULL;\n\t\n\tinfo->PSG_FRQ = clock & 0x7FFFFFFF;\n\tPSG_SetHoneyInTheSky(info, (clock >> 31) & 0x01);\n//\tPSG_SetHoneyInTheSky(0x01);\n\t\n\tinfo->PsgVolumeEffect = 0;\n\tinfo->Volume = 0;\n\tinfo->VOL = 0.0;\n\t\n\t//PSG_SetVolume(APP_GetPsgVolume());//Kitao追加\n\tPSG_SetVolume(info);\n\n\tpsg_reset(info);\n\n\tif (! _bTblInit)\n\t{\n\t\tcreate_volume_table();\n\t\tcreate_noise_table();\n\t\t_bTblInit = TRUE;\n\t}\n\n\t//PSG_SetSampleRate(sampleRate);\n\tinfo->SAMPLE_RATE = sampleRate;\n\tinfo->RESMPL_RATE = info->PSG_FRQ / OVERSAMPLE_RATE / info->SAMPLE_RATE;\n\n//\t_bPsgInit = TRUE;\n\n\treturn info;\n}\n\n\n/*-----------------------------------------------------------------------------\n\t[SetSampleRate]\n-----------------------------------------------------------------------------*/\n/*void\nPSG_SetSampleRate(\n\tUint32\t\tsampleRate)\n{\n\t//_SampleRate = sampleRate;\n}*/\n\n\n/*-----------------------------------------------------------------------------\n\t[Deinit]\n\t\tＰＳＧを破棄します。\n-----------------------------------------------------------------------------*/\nvoid\nPSG_Deinit(void* chip)\n{\n\thuc6280_state* info = (huc6280_state*)chip;\n\t\n\t/*memset(info->Psg, 0, sizeof(_Psg));\n\tmemset(info->DdaFadeOutL, 0, sizeof(_DdaFadeOutL)); //Kitao追加\n\tmemset(info->DdaFadeOutR, 0, sizeof(_DdaFadeOutR)); //Kitao追加\n\tinfo->MainVolumeL = 0;\n\tinfo->MainVolumeR = 0;\n\tinfo->LfoFrq = 0;\n\tinfo->LfoCtrl = 0;\n\tinfo->bWaveCrash = FALSE; //Kitao追加\n//\t_bPsgInit = FALSE;*/\n\t\n\tfree(info);\n}\n\n\n/*-----------------------------------------------------------------------------\n\t[Read]\n\t\tＰＳＧポートの読み出しに対する動作を記述します。\n-----------------------------------------------------------------------------*/\nUint8\nPSG_Read(\n\tvoid*\tchip,\n\tUint32\tregNum)\n{\n\thuc6280_state* info = (huc6280_state*)chip;\n\t\n\tif (regNum == 0)\n\t\treturn (Uint8)info->Channel;\n\n\treturn info->Port[regNum & 15];\n}\n\n\n/*-----------------------------------------------------------------------------\n\t[Write]\n\t\tＰＳＧポートの書き込みに対する動作を記述します。\n-----------------------------------------------------------------------------*/\nvoid\nPSG_Write(\n\tvoid*\t\tchip,\n\tUint32\t\tregNum,\n\tUint8\t\tdata)\n{\n\thuc6280_state* info = (huc6280_state*)chip;\n\t\n\t//v1.10更新。キュー処理をここに統合して高速化。\n\t//Kitao更新。clockは考慮せずにシンプルにして高速化した。\n/*\tif (((_QueueWriteIndex + 1) & (APUQUEUE_SIZE-1)) == _QueueReadIndex)\n\t{\n\t\tPRINTF(\"PSG Queue Over!\"); // キューが満タン\n\t\treturn;\n\t}\n\t_Queue[_QueueWriteIndex].reg   = (Uint8)(regNum & 15);\n\t_Queue[_QueueWriteIndex].data  = data;\n\t_QueueWriteIndex++; //Kitao更新\n\t_QueueWriteIndex &= APUQUEUE_SIZE-1; //Kitao更新\n*/\n\twrite_reg(chip, regNum, data);\n}\n\n\n/*Sint32\nPSG_AdvanceClock(\n\tSint32\t\tclock)\n{\n\treturn 0;\n}*/\n\n\n//Kitao追加。PSGのボリュームも個別に設定可能にした。\n/*static void\nPSG_SetVolume(\n\tUint32\tvolume)\t\t// 0 - 65535*/\nstatic void PSG_SetVolume(huc6280_state* info)\n{\n\t/*if (volume < 0)\tvolume = 0;\n\tif (volume > 65535)\tvolume = 65535;*/\n\n\t//_Volume = (double)volume / 65535.0 / PSG_DECLINE;\n\tinfo->Volume = 1.0 / PSG_DECLINE;\n\tset_VOL(info);\n}\n\n//Kitao追加。ボリュームミュート、ハーフなどをできるようにした。\n/*static void\nPSG_SetVolumeEffect(\n\tUint32\tvolumeEffect)\n{\n\t_PsgVolumeEffect = (Sint32)volumeEffect; //※数値が大きいほどボリュームは小さくなる\n\tset_VOL();\n}*/\n\n\n//Kitao追加\nvoid\nPSG_ResetVolumeReg(void* chip)\n{\n\thuc6280_state* info = (huc6280_state*)chip;\n\tint\ti;\n\n\tinfo->MainVolumeL = 0;\n\tinfo->MainVolumeR = 0;\n\tfor (i = 0; i < N_CHANNEL; i++)\n\t{\n\t\tinfo->Psg[i].volume = 0;\n\t\tinfo->Psg[i].outVolumeL = 0;\n\t\tinfo->Psg[i].outVolumeR = 0;\n\t\tinfo->DdaFadeOutL[i] = 0;\n\t\tinfo->DdaFadeOutR[i] = 0;\n\t}\n}\n\n\n//Kitao追加\nvoid\nPSG_SetMutePsgChannel(\n\tvoid*\tchip,\n\tSint32\tnum,\n\tBOOL\tbMute)\n{\n\thuc6280_state* info = (huc6280_state*)chip;\n\t\n\tinfo->bPsgMute[num] = bMute;\n\tif (bMute)\n\t{\n\t\tinfo->DdaFadeOutL[num] = 0;\n\t\tinfo->DdaFadeOutR[num] = 0;\n\t}\n}\n\nvoid PSG_SetMuteMask(void* chip, Uint32 MuteMask)\n{\n\tUint8 CurChn;\n\t\n\tfor (CurChn = 0x00; CurChn < N_CHANNEL; CurChn ++)\n\t\tPSG_SetMutePsgChannel(chip, CurChn, (MuteMask >> CurChn) & 0x01);\n\t\n\treturn;\n}\n\n//Kitao追加\nBOOL\nPSG_GetMutePsgChannel(\n\tvoid*\tchip,\n\tSint32\tnum)\n{\n\thuc6280_state* info = (huc6280_state*)chip;\n\t\n\treturn info->bPsgMute[num];\n}\n\n//Kitao追加。v2.60\nvoid\nPSG_SetHoneyInTheSky(\n\tvoid*\tchip,\n\tBOOL\tbHoneyInTheSky)\n{\n\thuc6280_state* info = (huc6280_state*)chip;\n\t\n\tinfo->bHoneyInTheSky = bHoneyInTheSky;\n}\n\n\n/*// save variable\n#define SAVE_V(V)\tif (fwrite(&V, sizeof(V), 1, p) != 1)\treturn FALSE\n#define LOAD_V(V)\tif (fread(&V, sizeof(V), 1, p) != 1)\treturn FALSE\n// save array\n#define SAVE_A(A)\tif (fwrite(A, sizeof(A), 1, p) != 1)\treturn FALSE\n#define LOAD_A(A)\tif (fread(A, sizeof(A), 1, p) != 1)\t\treturn FALSE*/\n/*-----------------------------------------------------------------------------\n\t[SaveState]\n\t\t状態をファイルに保存します。 \n-----------------------------------------------------------------------------*/\n/*BOOL\nPSG_SaveState(\n\tFILE*\t\tp)\n{\n\tBOOL\tbFlashHiders = FALSE; //Kitao更新。現在非使用。旧バージョンのステートセーブとの互換のため\n\n\tif (p == NULL)\n\t\treturn FALSE;\n\n\tSAVE_A(_Psg);\n\n\tSAVE_V(_Channel);\n\tSAVE_V(_MainVolumeL);\n\tSAVE_V(_MainVolumeR);\n\tSAVE_V(_LfoFrq);\n\tSAVE_V(_bLfoOn); //v1.59から非使用に。\n\tSAVE_V(_LfoCtrl);\n\tSAVE_V(_LfoShift); //v1.59から非使用に。\n\tSAVE_V(_bWaveCrash); //Kitao追加。v0.65\n\n\tSAVE_V(bFlashHiders); //Kitao追加。v0.62\n\n\t//v1.10追加。キュー処理をここへ統合。\n\tSAVE_A(_Queue); //v1.61からサイズが２倍になった。\n\tSAVE_V(_QueueWriteIndex);\n\tSAVE_V(_QueueReadIndex);\n\n\treturn TRUE;\n}*/\n\n\n/*-----------------------------------------------------------------------------\n\t[LoadState]\n\t\t状態をファイルから読み込みます。 \n-----------------------------------------------------------------------------*/\n/*BOOL\nPSG_LoadState(\n\tFILE*\t\tp)\n{\n\tUint32\t\t\ti;\n\tdouble\t\t\tclockCounter; //Kitao更新。現在非使用。旧バージョンのステートセーブとの互換のため\n\tBOOL\t\t\tbInit; //Kitao更新。現在非使用。旧バージョンのステートセーブとの互換のため\n\tSint32\t\t\ttotalClockAdvanced; //Kitao更新。現在非使用。旧バージョンのステートセーブとの互換のため\n\tBOOL\t\t\tbFlashHiders; //Kitao更新。現在非使用。旧バージョンのステートセーブとの互換のため\n\tOldApuQueue\t\toldQueue[65536]; //v1.60以前のステートを読み込み用。\n\t\n\n\tif (p == NULL)\n\t\treturn FALSE;\n\n\tLOAD_A(_Psg);\n\n\tLOAD_V(_Channel);\n\tLOAD_V(_MainVolumeL);\n\tLOAD_V(_MainVolumeR);\n\tLOAD_V(_LfoFrq);\n\tLOAD_V(_bLfoOn); //v1.59から非使用に。\n\tLOAD_V(_LfoCtrl);\n\tif (MAINBOARD_GetStateVersion() >= 3) //Kitao追加。v0.57以降のセーブファイルなら\n\t\tLOAD_V(_LfoShift); //v1.59から非使用に。\n\tif (MAINBOARD_GetStateVersion() >= 9) //Kitao追加。v0.65以降のセーブファイルなら\n\t{\n\t\tLOAD_V(_bWaveCrash);\n\t}\n\telse\n\t\t_bWaveCrash = FALSE;\n\n\tif (MAINBOARD_GetStateVersion() >= 7) //Kitao追加。v0.62以降のセーブファイルなら\n\t\tLOAD_V(bFlashHiders);\n\n\t//v1.10追加。キュー処理をここへ統合。v1.61更新\n\tif (MAINBOARD_GetStateVersion() >= 34) //v1.61beta以降のセーブファイルなら\n\t{\n\t\tLOAD_A(_Queue); //v1.61からサイズが２倍＆clock部分を削除した。\n\t\tLOAD_V(_QueueWriteIndex);\n\t\tLOAD_V(_QueueReadIndex);\n\t}\n\telse //v1.60以前のキュー(旧)バージョンのステートの場合、新バージョンの方に合うように変換。\n\t{\n\t\tLOAD_A(oldQueue);\n\t\tLOAD_V(_QueueWriteIndex);\n\t\tLOAD_V(_QueueReadIndex);\n\t\tif (_QueueWriteIndex >= _QueueReadIndex)\n\t\t{\n\t\t\tfor (i=_QueueReadIndex; i<=_QueueWriteIndex; i++)\n\t\t\t{\n\t\t\t\t_Queue[i].reg  = oldQueue[i].reg;\n\t\t\t\t_Queue[i].data = oldQueue[i].data;\n\t\t\t}\n\t\t}\n\t\telse //Writeの位置がReadの位置よりも前（65536地点をまたいでデータが存在しているとき）の場合\n\t\t{\n\t\t\tfor (i=_QueueReadIndex; i<=65535; i++)\n\t\t\t{\n\t\t\t\t_Queue[i].reg  = oldQueue[i].reg;\n\t\t\t\t_Queue[i].data = oldQueue[i].data;\n\t\t\t}\n\t\t\tfor (i=0; i<=_QueueWriteIndex; i++)\n\t\t\t{\n\t\t\t\t_Queue[65536+i].reg  = oldQueue[i].reg;\n\t\t\t\t_Queue[65536+i].data = oldQueue[i].data;\n\t\t\t}\n\t\t\t_QueueWriteIndex += 65536;\n\t\t}\n\t}\n\tif (MAINBOARD_GetStateVersion() < 26) //Kitao追加。v1.11より前のセーブファイルなら\n\t{\n\t\tLOAD_V(clockCounter); //現在非使用。v0.95\n\t\tLOAD_V(bInit); //現在非使用。v1.10\n\t\tLOAD_V(totalClockAdvanced); //現在非使用。v0.95\n\t}\n\n\treturn TRUE;\n}\n\n#undef SAVE_V\n#undef SAVE_A\n#undef LOAD_V\n#undef LOAD_A*/\n\n"
  },
  {
    "path": "VGMPlay/chips/Ootake_PSG.h",
    "content": "/*-----------------------------------------------------------------------------\n\t[PSG.h]\n\t\tＰＳＧを記述するのに必要な定義および関数のプロトタイプ宣言を行ないます．\n\n\tCopyright (C) 2004 Ki\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n**---------------------------------------------------------------------------*/\n//#include <stdio.h>\n//#include \"TypeDefs.h\"\n\ntypedef UINT8\tUint8;\ntypedef INT16\tSint16;\ntypedef INT32\tSint32;\ntypedef UINT32\tUint32;\ntypedef UINT8\tBOOL;\n#define TRUE\t1\n#define\tFALSE\t0\n\n//#define PSG_FRQ\t\t3579545.0\n\n\n/*-----------------------------------------------------------------------------\n** 関数のプロトタイプ宣言を行ないます．\n**---------------------------------------------------------------------------*/\n//Sint32\nvoid*\nPSG_Init(\n\tSint32\t\tclock,\n\tSint32\t\tsampleRate);\n\nvoid\nPSG_Deinit(void* chip);\n\nvoid\nPSG_Mix(\n//\tSint16*\t\tpDst,\t\t\t\t// 出力先バッファ \n\tvoid*\t\tchip,\n\tSint32**\tpDst,\n\tSint32\t\tnSample);\t\t\t// 書き出すサンプル数 \n\n/*void\nPSG_SetSampleRate(\n\tUint32\t\tsampleRate);\n\nvoid\nPSGDEBUG_ShowRegs();*/\n\nUint8\nPSG_Read(void* chip, Uint32 regNum);\n\nvoid\nPSG_Write(\n\tvoid*\t\tchip,\n\tUint32\t\tregNum,\n\tUint8\t\tdata);\n\n/*Sint32\nPSG_AdvanceClock(Sint32 clock);\n\nBOOL\nPSG_SaveState(\n\tFILE*\t\tp);\n\nBOOL\nPSG_LoadState(\n\tFILE*\t\tp);*/\n\n//Kitao追加。PSGのボリュームも個別に設定可能にした。\n/*void\nPSG_SetVolume(\n\tUint32\t\tvolume);\t\t// 0 - 65535\n\n//Kitao追加。ボリュームミュート、ハーフなどをできるようにした。\nvoid\nPSG_SetVolumeEffect(\n\tUint32 volumeEffect);*/\n\n//Kitao追加\nvoid\nPSG_ResetVolumeReg(void* chip);\n\n//Kitao追加\nvoid\nPSG_SetMutePsgChannel(\n\tvoid*\tchip,\n\tSint32\tnum,\n\tBOOL\tbMute);\n\nvoid PSG_SetMuteMask(void* chip, Uint32 MuteMask);\n\n//Kitao追加\nBOOL\nPSG_GetMutePsgChannel(\n\tvoid*\tchip,\n\tSint32\tnum);\n\n//Kitao追加。v2.60\nvoid\nPSG_SetHoneyInTheSky(\n\tvoid*\tchip,\n\tBOOL\tbHoneyInTheSky);\n"
  },
  {
    "path": "VGMPlay/chips/adlibemu.h",
    "content": "#if defined(OPLTYPE_IS_OPL2)\n#define ADLIBEMU(name)\t\t\tadlib_OPL2_##name\n#elif defined(OPLTYPE_IS_OPL3)\n#define ADLIBEMU(name)\t\t\tadlib_OPL3_##name\n#endif\n\ntypedef void (*ADL_UPDATEHANDLER)(void *param);\n\nvoid* ADLIBEMU(init)(UINT32 clock, UINT32 samplerate,\n\t\t\t\t\t ADL_UPDATEHANDLER UpdateHandler, void* param);\nvoid ADLIBEMU(stop)(void *chip);\nvoid ADLIBEMU(reset)(void *chip);\n\nvoid ADLIBEMU(writeIO)(void *chip, UINT32 addr, UINT8 val);\nvoid ADLIBEMU(getsample)(void *chip, INT32 ** sndptr, INT32 numsamples);\n\nUINT32 ADLIBEMU(reg_read)(void *chip, UINT32 port);\nvoid ADLIBEMU(write_index)(void *chip, UINT32 port, UINT8 val);\n\nvoid ADLIBEMU(set_mute_mask)(void *chip, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/chips/adlibemu_opl2.c",
    "content": "#include \"mamedef.h\"\n\n#define OPLTYPE_IS_OPL2\n#include \"adlibemu.h\"\n#include \"opl.c\"\n"
  },
  {
    "path": "VGMPlay/chips/adlibemu_opl3.c",
    "content": "#include \"mamedef.h\"\n\n#define OPLTYPE_IS_OPL3\n#include \"adlibemu.h\"\n#include \"opl.c\"\n"
  },
  {
    "path": "VGMPlay/chips/ay8910.c",
    "content": "/***************************************************************************\n\n  ay8910.c\n\n  Emulation of the AY-3-8910 / YM2149 sound chip.\n\n  Based on various code snippets by Ville Hallik, Michael Cuddy,\n  Tatsuyuki Satoh, Fabrice Frances, Nicola Salmoria.\n\n  Mostly rewritten by couriersud in 2008\n\n  Public documentation:\n\n  - http://privatfrickler.de/blick-auf-den-chip-soundchip-general-instruments-ay-3-8910/\n    Die pictures of the AY8910\n\n  - US Patent 4933980\n\n  Games using ADSR: gyruss\n\n  A list with more games using ADSR can be found here:\n        http://mametesters.org/view.php?id=3043\n\n  TODO:\n  * The AY8930 has an extended mode which is currently\n    not emulated.\n  * The YMZ284 only has one 1 output channel (mixed chan A,B,C).\n    This should be forced.\n  * YM2610 & YM2608 will need a separate flag in their config structures\n    to distinguish between legacy and discrete mode.\n\n  The rewrite also introduces a generic model for the DAC. This model is\n  not perfect, but allows channel mixing based on a parametrized approach.\n  This model also allows to factor in different loads on individual channels.\n  If a better model is developped in the future or better measurements are\n  available, the driver should be easy to change. The model is described\n  later.\n\n  In order to not break hundreds of existing drivers by default the flag\n  AY8910_LEGACY_OUTPUT is used by drivers not changed to take into account the\n  new model. All outputs are normalized to the old output range (i.e. 0 .. 7ffff).\n  In the case of channel mixing, output range is 0...3 * 7fff.\n\n  The main difference between the AY-3-8910 and the YM2149 is, that the\n  AY-3-8910 datasheet mentions, that fixed volume level 0, which is set by\n  registers 8 to 10 is \"channel off\". The YM2149 mentions, that the generated\n  signal has a 2V DC component. This is confirmed by measurements. The approach\n  taken here is to assume the 2V DC offset for all outputs for the YM2149.\n  For the AY-3-8910, an offset is used if envelope is active for a channel.\n  This is backed by oscilloscope pictures from the datasheet. If a fixed volume\n  is set, i.e. envelope is disabled, the output voltage is set to 0V. Recordings\n  I found on the web for gyruss indicate, that the AY-3-8910 offset should\n  be around 0.2V. This will also make sound levels more compatible with\n  user observations for scramble.\n\n  The Model:\n                     5V     5V\n                      |      |\n                      /      |\n  Volume Level x >---|       Z\n                      >      Z Pullup Resistor RU\n                       |     Z\n                       Z     |\n                    Rx Z     |\n                       Z     |\n                       |     |\n                       '-----+-------->  >---+----> Output signal\n                             |               |\n                             Z               Z\n               Pulldown RD   Z               Z Load RL\n                             Z               Z\n                             |               |\n                            GND             GND\n\nEach Volume level x will select a different resistor Rx. Measurements from fpgaarcade.com\nwhere used to calibrate channel mixing for the YM2149. This was done using\na least square approach using a fixed RL of 1K Ohm.\n\nFor the AY measurements cited in e.g. openmsx as \"Hacker Kay\" for a single\nchannel were taken. These were normalized to 0 ... 65535 and consequently\nadapted to an offset of 0.2V and a VPP of 1.3V. These measurements are in\nline e.g. with the formula used by pcmenc for the volume: vol(i) = exp(i/2-7.5).\n\nThe following is documentation from the code moved here and amended to reflect\nthe changes done:\n\nCareful studies of the chip output prove that the chip counts up from 0\nuntil the counter becomes greater or equal to the period. This is an\nimportant difference when the program is rapidly changing the period to\nmodulate the sound. This is worthwhile noting, since the datasheets\nsay, that the chip counts down.\nAlso, note that period = 0 is the same as period = 1. This is mentioned\nin the YM2203 data sheets. However, this does NOT apply to the Envelope\nperiod. In that case, period = 0 is half as period = 1.\n\nEnvelope shapes:\n    C AtAlH\n    0 0 x x  \\___\n    0 1 x x  /___\n    1 0 0 0  \\\\\\\\\n    1 0 0 1  \\___\n    1 0 1 0  \\/\\/\n    1 0 1 1  \\```\n    1 1 0 0  ////\n    1 1 0 1  /```\n    1 1 1 0  /\\/\\\n    1 1 1 1  /___\n\nThe envelope counter on the AY-3-8910 has 16 steps. On the YM2149 it\nhas twice the steps, happening twice as fast.\n\n***************************************************************************/\n\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n//#include \"cpuintrf.h\"\n//#include \"cpuexec.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stdio.h>\n#include \"ay8910.h\"\n\n/*************************************\n *\n *  Defines\n *\n *************************************/\n\n#define ENABLE_REGISTER_TEST\t\t(0)\t\t/* Enable preprogrammed registers */\n\n//#define MAX_OUTPUT 0x7fff\n#define MAX_OUTPUT 0x4000\n#define NUM_CHANNELS 3\n\n/* register id's */\n#define AY_AFINE\t(0)\n#define AY_ACOARSE\t(1)\n#define AY_BFINE\t(2)\n#define AY_BCOARSE\t(3)\n#define AY_CFINE\t(4)\n#define AY_CCOARSE\t(5)\n#define AY_NOISEPER\t(6)\n#define AY_ENABLE\t(7)\n#define AY_AVOL\t\t(8)\n#define AY_BVOL\t\t(9)\n#define AY_CVOL\t\t(10)\n#define AY_EFINE\t(11)\n#define AY_ECOARSE\t(12)\n#define AY_ESHAPE\t(13)\n\n#define AY_PORTA\t(14)\n#define AY_PORTB\t(15)\n\n#define NOISE_ENABLEQ(_psg, _chan)\t(((_psg)->regs[AY_ENABLE] >> (3 + _chan)) & 1)\n#define TONE_ENABLEQ(_psg, _chan)\t(((_psg)->regs[AY_ENABLE] >> (_chan)) & 1)\n#define TONE_PERIOD(_psg, _chan)\t( (_psg)->regs[(_chan) << 1] | (((_psg)->regs[((_chan) << 1) | 1] & 0x0f) << 8) )\n#define NOISE_PERIOD(_psg)\t\t\t( (_psg)->regs[AY_NOISEPER] & 0x1f)\n#define TONE_VOLUME(_psg, _chan)\t( (_psg)->regs[AY_AVOL + (_chan)] & 0x0f)\n//#define TONE_ENVELOPE(_psg, _chan)\t(((_psg)->regs[AY_AVOL + (_chan)] >> 4) & (((_psg)->device->type() == AY8914) ? 3 : 1))\n#define TONE_ENVELOPE(_psg, _chan)\t(((_psg)->regs[AY_AVOL + (_chan)] >> 4) & (((_psg)->chip_type == CHTYPE_AY8914) ? 3 : 1))\n#define ENVELOPE_PERIOD(_psg)\t\t(((_psg)->regs[AY_EFINE] | ((_psg)->regs[AY_ECOARSE]<<8)))\n#define NOISE_OUTPUT(_psg)\t\t\t((_psg)->rng & 1)\n\n#define CHTYPE_AY8910\t0x00\n#define CHTYPE_AY8912\t0x01\n#define CHTYPE_AY8913\t0x02\n#define CHTYPE_AY8930\t0x03\n#define CHTYPE_AY8914\t0x04\n#define CHTYPE_YM2149\t0x10\n#define CHTYPE_YM3439\t0x11\n#define CHTYPE_YMZ284\t0x12\n#define CHTYPE_YMZ294\t0x13\n#define CHTYPE_YM2203\t0x20\n#define CHTYPE_YM2608\t0x21\n#define CHTYPE_YM2610\t0x22\n#define CHTYPE_YM2610B\t0x23\n\n/*************************************\n *\n *  Type definitions\n *\n *************************************/\n\ntypedef struct _ay_ym_param ay_ym_param;\nstruct _ay_ym_param\n{\n\tdouble r_up;\n\tdouble r_down;\n\tint    res_count;\n\tdouble res[32];\n};\n\ntypedef struct _ay8910_context ay8910_context;\nstruct _ay8910_context\n{\n\t//const device_config *device;\n\tint streams;\n\tint ready;\n\t//sound_stream *channel;\n\tconst ay8910_interface *intf;\n\tINT32 register_latch;\n\tUINT8 regs[16];\n\tINT32 last_enable;\n\tINT32 count[NUM_CHANNELS];\n\tUINT8 output[NUM_CHANNELS];\n\tUINT8 prescale_noise;\n\tINT32 count_noise;\n\tINT32 count_env;\n\tINT8 env_step;\n\tUINT32 env_volume;\n\tUINT8 hold,alternate,attack,holding;\n\tINT32 rng;\n\tUINT8 env_step_mask;\n\t/* init parameters ... */\n\tint step;\n\tint zero_is_off;\n\tUINT8 vol_enabled[NUM_CHANNELS];\n\tconst ay_ym_param *par;\n\tconst ay_ym_param *par_env;\n\tINT32 vol_table[NUM_CHANNELS][16];\n\tINT32 env_table[NUM_CHANNELS][32];\n\tINT32 vol3d_table[8*32*32*32];\n\t//devcb_resolved_read8 portAread;\n\t//devcb_resolved_read8 portBread;\n\t//devcb_resolved_write8 portAwrite;\n\t//devcb_resolved_write8 portBwrite;\n\tUINT8 StereoMask[NUM_CHANNELS];\n\tUINT32 MuteMsk[NUM_CHANNELS];\n\tUINT8 chip_type;\n\tUINT8 IsDisabled;\n\t\n\tSRATE_CALLBACK SmpRateFunc;\n\tvoid* SmpRateData;\n};\n\n//#define MAX_CHIPS\t0x02\n//static ay8910_context AY8910Data[MAX_CHIPS];\n\n#define MAX_UPDATE_LEN\t0x10\t// in samples\nstatic stream_sample_t AYBuf[NUM_CHANNELS][MAX_UPDATE_LEN];\n\n\n/*INLINE ay8910_context *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_AY8910 ||\n\t\t   sound_get_type(device) == SOUND_AY8912 ||\n\t\t   sound_get_type(device) == SOUND_AY8913 ||\n\t\t   sound_get_type(device) == SOUND_AY8930 ||\n\t\t   sound_get_type(device) == SOUND_YM2149 ||\n\t\t   sound_get_type(device) == SOUND_YM3439 ||\n\t\t   sound_get_type(device) == SOUND_YMZ284 ||\n\t\t   sound_get_type(device) == SOUND_YMZ294);\n\treturn (ay8910_context *)device->token;\n}*/\n\n\n/*************************************\n *\n *  Static\n *\n *************************************/\n\nstatic const ay_ym_param ym2149_param =\n{\n\t630, 801,\n\t16,\n\t{ 73770, 37586, 27458, 21451, 15864, 12371, 8922,  6796,\n\t   4763,  3521,  2403,  1737,  1123,   762,  438,   251 },\n};\n\nstatic const ay_ym_param ym2149_param_env =\n{\n\t630, 801,\n\t32,\n\t{ 103350, 73770, 52657, 37586, 32125, 27458, 24269, 21451,\n\t   18447, 15864, 14009, 12371, 10506,  8922,  7787,  6796,\n\t    5689,  4763,  4095,  3521,  2909,  2403,  2043,  1737,\n\t    1397,  1123,   925,   762,   578,   438,   332,   251 },\n};\n\n#if 0\n/* RL = 1000, Hacker Kay normalized, 2.1V to 3.2V */\nstatic const ay_ym_param ay8910_param =\n{\n\t664, 913,\n\t16,\n\t{ 85785, 34227, 26986, 20398, 14886, 10588,  7810,  4856,\n\t   4120,  2512,  1737,  1335,  1005,   747,   586,    451 },\n};\n\n/*\n * RL = 3000, Hacker Kay normalized pattern, 1.5V to 2.8V\n * These values correspond with guesses based on Gyruss schematics\n * They work well with scramble as well.\n */\nstatic const ay_ym_param ay8910_param =\n{\n\t930, 454,\n\t16,\n\t{ 85066, 34179, 27027, 20603, 15046, 10724, 7922, 4935,\n\t   4189,  2557,  1772,  1363,  1028,  766,   602,  464 },\n};\n\n/*\n * RL = 1000, Hacker Kay normalized pattern, 0.75V to 2.05V\n * These values correspond with guesses based on Gyruss schematics\n * They work well with scramble as well.\n */\nstatic const ay_ym_param ay8910_param =\n{\n\t1371, 313,\n\t16,\n\t{ 93399, 33289, 25808, 19285, 13940, 9846,  7237,  4493,\n\t   3814,  2337,  1629,  1263,   962,  727,   580,   458 },\n};\n\n/*\n * RL = 1000, Hacker Kay normalized pattern, 0.2V to 1.5V\n */\nstatic const ay_ym_param ay8910_param =\n{\n\t5806, 300,\n\t16,\n\t{ 118996, 42698, 33105, 24770, 17925, 12678,  9331,  5807,\n        4936,  3038,  2129,  1658,  1271,   969,   781,   623 }\n};\n#endif\n\n/*\n * RL = 2000, Based on Matthew Westcott's measurements from Dec 2001.\n * -------------------------------------------------------------------\n *\n * http://groups.google.com/group/comp.sys.sinclair/browse_thread/thread/fb3091da4c4caf26/d5959a800cda0b5e?lnk=gst&q=Matthew+Westcott#d5959a800cda0b5e\n * After what Russell mentioned a couple of weeks back about the lack of\n * publicised measurements of AY chip volumes - I've finally got round to\n * making these readings, and I'm placing them in the public domain - so\n * anyone's welcome to use them in emulators or anything else.\n\n * To make the readings, I set up the chip to produce a constant voltage on\n * channel C (setting bits 2 and 5 of register 6), and varied the amplitude\n * (the low 4 bits of register 10). The voltages were measured between the\n * channel C output (pin 1) and ground (pin 6).\n *\n * Level  Voltage\n *  0     1.147\n *  1     1.162\n *  2     1.169\n *  3     1.178\n *  4     1.192\n *  5     1.213\n *  6     1.238\n *  7     1.299\n *  8     1.336\n *  9     1.457\n * 10     1.573\n * 11     1.707\n * 12     1.882\n * 13     2.06\n * 14     2.32\n * 15     2.58\n * -------------------------------------------------------------------\n *\n * The ZX spectrum output circuit was modelled in SwitcherCAD and\n * the resistor values below create the voltage levels above.\n * RD was measured on a real chip to be 8m Ohm, RU was 0.8m Ohm.\n */\n\nstatic const ay_ym_param ay8910_param =\n{\n\t800000, 8000000,\n\t16,\n\t{ 15950, 15350, 15090, 14760, 14275, 13620, 12890, 11370,\n      10600,  8590,  7190,  5985,  4820,  3945,  3017,  2345 }\n};\n\n/*************************************\n *\n *  Inline\n *\n *************************************/\n\nINLINE void build_3D_table(double rl, const ay_ym_param *par, const ay_ym_param *par_env, int normalize, double factor, int zero_is_off, INT32 *tab)\n{\n\tint j, j1, j2, j3, e, indx;\n\tdouble rt, rw, n;\n\tdouble min = 10.0,  max = 0.0;\n\tdouble *temp;\n\tdouble spdup;\n\n\ttemp = (double *)malloc(8*32*32*32*sizeof(*temp));\n\n\tfor (e=0; e < 8; e++)\n\t\tfor (j1=0; j1 < 32; j1++)\n\t\t\tfor (j2=0; j2 < 32; j2++)\n\t\t\t\tfor (j3=0; j3 < 32; j3++)\n\t\t\t\t{\n\t\t\t\t\tif (zero_is_off)\n\t\t\t\t\t{\n\t\t\t\t\t\tn  = (j1 != 0 || (e & 0x01)) ? 1 : 0;\n\t\t\t\t\t\tn += (j2 != 0 || (e & 0x02)) ? 1 : 0;\n\t\t\t\t\t\tn += (j3 != 0 || (e & 0x04)) ? 1 : 0;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tn = 3.0;\n\n\t\t\t\t\trt = n / par->r_up + 3.0 / par->r_down + 1.0 / rl;\n\t\t\t\t\trw = n / par->r_up;\n\n\t\t\t\t\t/*rw += 1.0 / ( (e & 0x01) ? par_env->res[j1] : par->res[j1]);\n\t\t\t\t\trt += 1.0 / ( (e & 0x01) ? par_env->res[j1] : par->res[j1]);\n\t\t\t\t\trw += 1.0 / ( (e & 0x02) ? par_env->res[j2] : par->res[j2]);\n\t\t\t\t\trt += 1.0 / ( (e & 0x02) ? par_env->res[j2] : par->res[j2]);\n\t\t\t\t\trw += 1.0 / ( (e & 0x04) ? par_env->res[j3] : par->res[j3]);\n\t\t\t\t\trt += 1.0 / ( (e & 0x04) ? par_env->res[j3] : par->res[j3]);*/\n\t\t\t\t\t/* this should speed up the initialsation a bit (it calculates 262144 values) */\n\t\t\t\t\tspdup  = 1.0 / ( (e & 0x01) ? par_env->res[j1] : par->res[j1]);\n\t\t\t\t\tspdup += 1.0 / ( (e & 0x02) ? par_env->res[j2] : par->res[j2]);\n\t\t\t\t\tspdup += 1.0 / ( (e & 0x04) ? par_env->res[j3] : par->res[j3]);\n\t\t\t\t\tif (spdup > 1.0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Bugfix for spdup being 1.#INF\n\t\t\t\t\t\tindx = (e << 15) | (j3<<10) | (j2<<5) | j1;\n\t\t\t\t\t\ttemp[indx] = 0.0;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\trw += spdup;\n\t\t\t\t\trt += spdup;\n\n\t\t\t\t\tindx = (e << 15) | (j3<<10) | (j2<<5) | j1;\n\t\t\t\t\ttemp[indx] = rw / rt;\n\t\t\t\t\tif (temp[indx] < min)\n\t\t\t\t\t\tmin = temp[indx];\n\t\t\t\t\tif (temp[indx] > max)\n\t\t\t\t\t\tmax = temp[indx];\n\t\t\t\t}\n\n\tif (normalize)\n\t{\n\t\tfor (j=0; j < 32*32*32*8; j++)\n\t\t\t//tab[j] = MAX_OUTPUT * (((temp[j] - min)/(max-min))) * factor;\n\t\t\ttab[j] = MAX_OUTPUT * (((temp[j] - min)/(max-min)) * 0.5) * factor;\n\t}\n\telse\n\t{\n\t\tfor (j=0; j < 32*32*32*8; j++)\n\t\t\ttab[j] = MAX_OUTPUT * temp[j];\n\t}\n\n\t/* for (e=0;e<16;e++) printf(\"%d %d\\n\",e<<10, tab[e<<10]); */\n\n\tfree(temp);\n}\n\nINLINE void build_single_table(double rl, const ay_ym_param *par, int normalize, INT32 *tab, int zero_is_off)\n{\n\tint j;\n\tdouble rt, rw = 0;\n\tdouble temp[32], min=10.0, max=0.0;\n\n\tfor (j=0; j < par->res_count; j++)\n\t{\n\t\trt = 1.0 / par->r_down + 1.0 / rl;\n\n\t\trw = 1.0 / par->res[j];\n\t\trt += 1.0 / par->res[j];\n\n\t\tif (!(zero_is_off && j == 0))\n\t\t{\n\t\t\trw += 1.0 / par->r_up;\n\t\t\trt += 1.0 / par->r_up;\n\t\t}\n\n\t\ttemp[j] = rw / rt;\n\t\tif (temp[j] < min)\n\t\t\tmin = temp[j];\n\t\tif (temp[j] > max)\n\t\t\tmax = temp[j];\n\t}\n\tif (normalize)\n\t{\n\t\tfor (j=0; j < par->res_count; j++)\n\t\t\t/* The following line generates values that cause clicks when starting/pausing/stopping\n\t\t\t\tbecause there're off (the center is at zero, not the base).\n\t\t\t\tThat's quite bad for a player.\n\t\t\ttab[j] = MAX_OUTPUT * (((temp[j] - min)/(max-min)) - 0.25) * 0.5;\n\t\t\t*/\n\t\t\ttab[j] = MAX_OUTPUT * ((temp[j] - min)/(max-min)) / NUM_CHANNELS;\n\t}\n\telse\n\t{\n\t\tfor (j=0; j < par->res_count; j++)\n\t\t\ttab[j] = MAX_OUTPUT * temp[j] / NUM_CHANNELS;\n\t}\n\n}\n\nINLINE UINT16 mix_3D(ay8910_context *psg)\n{\n\tint indx = 0, chan;\n\n\tfor (chan = 0; chan < NUM_CHANNELS; chan++)\n\t\tif (TONE_ENVELOPE(psg, chan) != 0)\n\t\t{\n\t\t\t//if (psg->device->type() == AY8914) // AY8914 Has a two bit tone_envelope field\n\t\t\tif (psg->chip_type == CHTYPE_AY8914) // AY8914 Has a two bit tone_envelope field\n\t\t\t{\n\t\t\t\tindx |= (1 << (chan+15)) | ( psg->vol_enabled[chan] ? ((psg->env_volume >> (3-TONE_ENVELOPE(psg, chan))) << (chan*5)) : 0);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tindx |= (1 << (chan+15)) | ( psg->vol_enabled[chan] ? psg->env_volume << (chan*5) : 0);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tindx |= (psg->vol_enabled[chan] ? TONE_VOLUME(psg, chan) << (chan*5) : 0);\n\t\t}\n\treturn psg->vol3d_table[indx];\n}\n\n/*************************************\n *\n * Static functions\n *\n *************************************/\n\nstatic void ay8910_write_reg(ay8910_context *psg, int r, int v)\n{\n\t//if (r >= 11 && r <= 13 ) printf(\"%d %x %02x\\n\", PSG->index, r, v);\n\tpsg->regs[r] = v;\n\n\tswitch( r )\n\t{\n\t\tcase AY_AFINE:\n\t\tcase AY_ACOARSE:\n\t\tcase AY_BFINE:\n\t\tcase AY_BCOARSE:\n\t\tcase AY_CFINE:\n\t\tcase AY_CCOARSE:\n\t\tcase AY_NOISEPER:\n\t\tcase AY_AVOL:\n\t\tcase AY_BVOL:\n\t\tcase AY_CVOL:\n\t\tcase AY_EFINE:\n\t\t\t/* No action required */\n\t\t\tbreak;\n\t\tcase AY_ECOARSE:\n\t\t\t#ifdef MAME_DEBUG\n\t\t\tif ( (v & 0x0f) > 0)\n\t\t\t\tpopmessage(\"Write to ECoarse register detected - please inform www.mametesters.org\");\n\t\t\t#endif\n\t\t\t/* No action required */\n\t\t\tbreak;\n\t\tcase AY_ENABLE:\n\t\t\t/*if ((psg->last_enable == -1) ||\n\t\t\t    ((psg->last_enable & 0x40) != (psg->regs[AY_ENABLE] & 0x40)))\n\t\t\t{\n\t\t\t\t// write out 0xff if port set to input\n\t\t\t\tdevcb_call_write8(&psg->portAwrite, 0, (psg->regs[AY_ENABLE] & 0x40) ? psg->regs[AY_PORTA] : 0xff);\n\t\t\t}\n\n\t\t\tif ((psg->last_enable == -1) ||\n\t\t\t    ((psg->last_enable & 0x80) != (psg->regs[AY_ENABLE] & 0x80)))\n\t\t\t{\n\t\t\t\t// write out 0xff if port set to input\n\t\t\t\tdevcb_call_write8(&psg->portBwrite, 0, (psg->regs[AY_ENABLE] & 0x80) ? psg->regs[AY_PORTB] : 0xff);\n\t\t\t}*/\n\t\t\tif (~v & 0x3F)\t// one of the channels gets enabled -> Enable emulation\n\t\t\t\tpsg->IsDisabled = 0x00;\n\n\t\t\tpsg->last_enable = psg->regs[AY_ENABLE];\n\t\t\tbreak;\n\t\tcase AY_ESHAPE:\n\t\t\t#ifdef MAME_DEBUG\n\t\t\tif ( (v & 0x0f) > 0)\n\t\t\t\tpopmessage(\"Write to EShape register detected - please inform www.mametesters.org\");\n\t\t\t#endif\n\t\t\tpsg->attack = (psg->regs[AY_ESHAPE] & 0x04) ? psg->env_step_mask : 0x00;\n\t\t\tif ((psg->regs[AY_ESHAPE] & 0x08) == 0)\n\t\t\t{\n\t\t\t\t/* if Continue = 0, map the shape to the equivalent one which has Continue = 1 */\n\t\t\t\tpsg->hold = 1;\n\t\t\t\tpsg->alternate = psg->attack;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpsg->hold = psg->regs[AY_ESHAPE] & 0x01;\n\t\t\t\tpsg->alternate = psg->regs[AY_ESHAPE] & 0x02;\n\t\t\t}\n\t\t\tpsg->env_step = psg->env_step_mask;\n\t\t\tpsg->holding = 0;\n\t\t\tpsg->env_volume = (psg->env_step ^ psg->attack);\n\t\t\tbreak;\n\t\tcase AY_PORTA:\n\t\t\t/*if (psg->regs[AY_ENABLE] & 0x40)\n\t\t\t{\n\t\t\t\tif (psg->portAwrite.write)\n\t\t\t\t\tdevcb_call_write8(&psg->portAwrite, 0, psg->regs[AY_PORTA]);\n\t\t\t\telse\n\t\t\t\t\tlogerror(\"warning - write %02x to 8910 '%s' Port A\\n\",psg->regs[AY_PORTA],psg->device->tag);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlogerror(\"warning: write to 8910 '%s' Port A set as input - ignored\\n\",psg->device->tag);\n\t\t\t}*/\n\t\t\tbreak;\n\t\tcase AY_PORTB:\n\t\t\t/*if (psg->regs[AY_ENABLE] & 0x80)\n\t\t\t{\n\t\t\t\tif (psg->portBwrite.write)\n\t\t\t\t\tdevcb_call_write8(&psg->portBwrite, 0, psg->regs[AY_PORTB]);\n\t\t\t\telse\n\t\t\t\t\tlogerror(\"warning - write %02x to 8910 '%s' Port B\\n\",psg->regs[AY_PORTB],psg->device->tag);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlogerror(\"warning: write to 8910 '%s' Port B set as input - ignored\\n\",psg->device->tag);\n\t\t\t}*/\n\t\t\tbreak;\n\t}\n}\n\n//static STREAM_UPDATE( ay8910_update )\n/*void ay8910_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tay8910_context *psg = &AY8910Data[ChipID];\n\t\n\tmemset(outputs[0], 0x00, samples * sizeof(stream_sample_t));\n\tmemset(outputs[1], 0x00, samples * sizeof(stream_sample_t));\n\tay8910_update_one(psg, outputs, samples);\n\t\n\treturn;\n}*/\n\nvoid ay8910_update_one(void *param, stream_sample_t **outputs, int samples)\n{\n\tay8910_context *psg = (ay8910_context *)param;\n\tstream_sample_t *buf[NUM_CHANNELS];\n\tint chan;\n\tint cursmpl;\n\tint buf_smpls;\n\tstream_sample_t *bufL = outputs[0];\n\tstream_sample_t *bufR = outputs[1];\n\t//stream_sample_t bufSmpl;\n\t\n\tmemset(outputs[0], 0x00, samples * sizeof(stream_sample_t));\n\tmemset(outputs[1], 0x00, samples * sizeof(stream_sample_t));\n\t\n\t// Speed hack for OPN chips (YM2203, YM26xx), that have an often unused AY8910\n\tif (psg->IsDisabled)\n\t\treturn;\n\t\n\tbuf_smpls = samples;\n\t//buf[0] = outputs[0];\n\tbuf[0] = AYBuf[0];\n\tbuf[1] = NULL;\n\tbuf[2] = NULL;\n\t//if (psg->streams == NUM_CHANNELS)\n\t//{\n\t\t//buf[1] = outputs[1];\n\t\t//buf[2] = outputs[2];\n\t\tbuf[1] = AYBuf[1];\n\t\tbuf[2] = AYBuf[2];\n\t//}\n\n\t/* hack to prevent us from hanging when starting filtered outputs */\n\t//if (!psg->ready)\n\t//{\n\t\tfor (chan = 0; chan < NUM_CHANNELS; chan++)\n\t\t\tif (buf[chan] != NULL)\n\t\t\t\tmemset(buf[chan], 0, samples * sizeof(*buf[chan]));\n\t//}\n\n\t/* The 8910 has three outputs, each output is the mix of one of the three */\n\t/* tone generators and of the (single) noise generator. The two are mixed */\n\t/* BEFORE going into the DAC. The formula to mix each channel is: */\n\t/* (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable). */\n\t/* Note that this means that if both tone and noise are disabled, the output */\n\t/* is 1, not 0, and can be modulated changing the volume. */\n\n\tif (buf_smpls > MAX_UPDATE_LEN)\n\t\tbuf_smpls = MAX_UPDATE_LEN;\n\t/* buffering loop */\n\twhile (buf_smpls)\n\t{\n\t\tfor (chan = 0; chan < NUM_CHANNELS; chan++)\n\t\t{\n\t\t\tpsg->count[chan]++;\n\t\t\tif (psg->count[chan] >= TONE_PERIOD(psg, chan))\n\t\t\t{\n\t\t\t\tpsg->output[chan] ^= 1;\n\t\t\t\tpsg->count[chan] = 0;\n\t\t\t}\n\t\t}\n\n\t\tpsg->count_noise++;\n\t\tif (psg->count_noise >= NOISE_PERIOD(psg))\n\t\t{\n\t\t\t/* toggle the prescaler output. Noise is no different to\n\t\t\t * channels.\n\t\t\t */\n\t\t\tpsg->count_noise = 0;\n\t\t\tpsg->prescale_noise ^= 1;\n\n\t\t\tif ( psg->prescale_noise)\n\t\t\t{\n\t\t\t\t/* The Random Number Generator of the 8910 is a 17-bit shift */\n\t\t\t\t/* register. The input to the shift register is bit0 XOR bit3 */\n\t\t\t\t/* (bit0 is the output). This was verified on AY-3-8910 and YM2149 chips. */\n\n\t\t\t\tpsg->rng ^= (((psg->rng & 1) ^ ((psg->rng >> 3) & 1)) << 17);\n\t\t\t\tpsg->rng >>= 1;\n\t\t\t}\n\t\t}\n\n\t\tfor (chan = 0; chan < NUM_CHANNELS; chan++)\n\t\t{\n\t\t\tpsg->vol_enabled[chan] = (psg->output[chan] | TONE_ENABLEQ(psg, chan)) & (NOISE_OUTPUT(psg) | NOISE_ENABLEQ(psg, chan));\n\t\t}\n\n\t\t/* update envelope */\n\t\tif (psg->holding == 0)\n\t\t{\n\t\t\tpsg->count_env++;\n\t\t\tif (psg->count_env >= ENVELOPE_PERIOD(psg) * psg->step )\n\t\t\t{\n\t\t\t\tpsg->count_env = 0;\n\t\t\t\tpsg->env_step--;\n\n\t\t\t\t/* check envelope current position */\n\t\t\t\tif (psg->env_step < 0)\n\t\t\t\t{\n\t\t\t\t\tif (psg->hold)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (psg->alternate)\n\t\t\t\t\t\t\tpsg->attack ^= psg->env_step_mask;\n\t\t\t\t\t\tpsg->holding = 1;\n\t\t\t\t\t\tpsg->env_step = 0;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t/* if CountEnv has looped an odd number of times (usually 1), */\n\t\t\t\t\t\t/* invert the output. */\n\t\t\t\t\t\tif (psg->alternate && (psg->env_step & (psg->env_step_mask + 1)))\n \t\t\t\t\t\t\tpsg->attack ^= psg->env_step_mask;\n\n\t\t\t\t\t\tpsg->env_step &= psg->env_step_mask;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\t\tpsg->env_volume = (psg->env_step ^ psg->attack);\n\n\t\t//if (psg->streams == NUM_CHANNELS)\n\t\t//{\n\t\t\tfor (chan = 0; chan < NUM_CHANNELS; chan++)\n\t\t\t\tif (TONE_ENVELOPE(psg, chan) != 0)\n\t\t\t\t{\n\t\t\t\t\t/* Envolope has no \"off\" state */\n\t\t\t\t\t//if (psg->device->type() == AY8914) // AY8914 Has a two bit tone_envelope field\n\t\t\t\t\tif (psg->chip_type == CHTYPE_AY8914) // AY8914 Has a two bit tone_envelope field\n\t\t\t\t\t{\n\t\t\t\t\t\t*(buf[chan]++) = psg->env_table[chan][psg->vol_enabled[chan] ? psg->env_volume >> (3-TONE_ENVELOPE(psg,chan)) : 0];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t*(buf[chan]++) = psg->env_table[chan][psg->vol_enabled[chan] ? psg->env_volume : 0];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t*(buf[chan]++) = psg->vol_table[chan][psg->vol_enabled[chan] ? TONE_VOLUME(psg, chan) : 0];\n\t\t\t\t}\n\t\t/*}\n\t\telse\n\t\t{\n\t\t\t*(buf[0]++) = mix_3D(psg);\n#if 0\n\t\t\t*(buf[0]) = (  vol_enabled[0] * psg->vol_table[psg->Vol[0]]\n\t\t\t             + vol_enabled[1] * psg->vol_table[psg->Vol[1]]\n\t\t\t             + vol_enabled[2] * psg->vol_table[psg->Vol[2]]) / psg->step;\n#endif\n\t\t}*/\n\t\tbuf_smpls--;\n\t\t\n\t}\n\t\n\tbuf_smpls = samples;\n\tif (buf_smpls > MAX_UPDATE_LEN)\n\t\tbuf_smpls = MAX_UPDATE_LEN;\n\tfor (cursmpl = 0; cursmpl < buf_smpls; cursmpl ++)\n\t{\n\t\t/*bufSmpl = AYBuf[0][cursmpl] & psg->MuteMsk[0];\n\t\tif (psg->streams == NUM_CHANNELS)\n\t\t{\n\t\t\tbufSmpl += AYBuf[1][cursmpl] & psg->MuteMsk[1];\n\t\t\tbufSmpl += AYBuf[2][cursmpl] & psg->MuteMsk[2];\n\t\t}\n\t\tbufL[cursmpl] += bufSmpl;\n\t\tbufR[cursmpl] += bufSmpl;*/\n\t\tfor (chan = 0; chan < NUM_CHANNELS; chan ++)\n\t\t{\n\t\t\tif (psg->MuteMsk[chan])\n\t\t\t{\n\t\t\t\tif (psg->StereoMask[chan] & 0x01)\n\t\t\t\t\tbufL[cursmpl] += AYBuf[chan][cursmpl];\n\t\t\t\tif (psg->StereoMask[chan] & 0x02)\n\t\t\t\t\tbufR[cursmpl] += AYBuf[chan][cursmpl];\n\t\t\t}\n\t\t}\n\t}\n}\n\nstatic void build_mixer_table(ay8910_context *psg)\n{\n\tint\tnormalize = 0;\n\tint\tchan;\n\n\tif ((psg->intf->flags & AY8910_LEGACY_OUTPUT) != 0)\n\t{\n#ifdef _DEBUG\n\t\t//logerror(\"AY-3-8910/YM2149 using legacy output levels!\\n\");\n#endif\n\t\t//normalize = 1;\n\t}\n\tnormalize = 1;\n\n\t/* skip unnecessary things to speed up the AY8910 init\n\t\t1-channel AY uses the 3D table, 3-channel AY uses envelope and volume\n\t\tbut building the 3D table still takes too long */\n\t//if (psg->streams == NUM_CHANNELS)\n\t{\n\t\tfor (chan=0; chan < NUM_CHANNELS; chan++)\n\t\t{\n\t\t\tbuild_single_table(psg->intf->res_load[chan], psg->par, normalize, psg->vol_table[chan], psg->zero_is_off);\n\t\t\tbuild_single_table(psg->intf->res_load[chan], psg->par_env, normalize, psg->env_table[chan], 0);\n\t\t}\n\t}\n\t//else\n\t//{\n\t//\t/*\n\t//\t * The previous implementation added all three channels up instead of averaging them.\n\t//\t * The factor of 3 will force the same levels if normalizing is used.\n\t//\t */\n\t//\tbuild_3D_table(psg->intf->res_load[0], psg->par, psg->par_env, normalize, 3, psg->zero_is_off, psg->vol3d_table);\n\t//}\n}\n\n/*static void ay8910_statesave(ay8910_context *psg, const device_config *device)\n{\n\tstate_save_register_device_item(device, 0, psg->register_latch);\n\tstate_save_register_device_item_array(device, 0, psg->regs);\n\tstate_save_register_device_item(device, 0, psg->last_enable);\n\n\tstate_save_register_device_item_array(device, 0, psg->count);\n\tstate_save_register_device_item(device, 0, psg->count_noise);\n\tstate_save_register_device_item(device, 0, psg->count_env);\n\n\tstate_save_register_device_item(device, 0, psg->env_volume);\n\n\tstate_save_register_device_item_array(device, 0, psg->output);\n\tstate_save_register_device_item(device, 0, psg->output_noise);\n\n\tstate_save_register_device_item(device, 0, psg->env_step);\n\tstate_save_register_device_item(device, 0, psg->hold);\n\tstate_save_register_device_item(device, 0, psg->alternate);\n\tstate_save_register_device_item(device, 0, psg->attack);\n\tstate_save_register_device_item(device, 0, psg->holding);\n\tstate_save_register_device_item(device, 0, psg->rng);\n}*/\n\n/*************************************\n *\n * Public functions\n *\n *   used by e.g. YM2203, YM2210 ...\n *\n *************************************/\n\n//void *ay8910_start_ym(void *infoptr, sound_type chip_type, const device_config *device, int clock, const ay8910_interface *intf)\nvoid *ay8910_start_ym(void *infoptr, unsigned char chip_type, int clock, const ay8910_interface *intf)\n{\n\tay8910_context *info = (ay8910_context *)infoptr;\n\tint master_clock = clock;\n\tUINT8 CurChn;\n\n\tif (info == NULL)\n\t{\n\t\t//info = auto_alloc_clear(device->machine, ay8910_context);\n\t\tinfo = (ay8910_context*)malloc(sizeof(ay8910_context));\n\t\tmemset(info, 0x00, sizeof(ay8910_context));\n\t}\n\n\t//info->device = device;\n\tinfo->intf = intf;\n\tinfo->SmpRateFunc = NULL;\n\t//devcb_resolve_read8(&info->portAread, &intf->portAread, device);\n\t//devcb_resolve_read8(&info->portBread, &intf->portBread, device);\n\t//devcb_resolve_write8(&info->portAwrite, &intf->portAwrite, device);\n\t//devcb_resolve_write8(&info->portBwrite, &intf->portBwrite, device);\n\tif ((info->intf->flags & AY8910_SINGLE_OUTPUT) != 0)\n\t{\n#ifdef _DEBUG\n\t\t//logerror(\"AY-3-8910/YM2149 using single output!\\n\");\n#endif\n\t\t//info->streams = 1;\n\t\tinfo->streams = 3;\t// set to 3 to greatly speed up loading times\n\t}\n\telse\t\n\t\tinfo->streams = 3;\n\n\tinfo->chip_type = chip_type;\n\t//if (chip_type == CHTYPE_AY8910 || chip_type == CHTYPE_AY8914 || chip_type == CHTYPE_AY8930)\n\tif ((chip_type & 0xF0) == 0x00)\t// CHTYPE_AY89xx variants\n\t{\n\t\tinfo->step = 2;\n\t\tinfo->par = &ay8910_param;\n\t\tinfo->par_env = &ay8910_param;\n\t\tinfo->zero_is_off = 0;\t\t/* FIXME: Remove after verification that off=vol(0) */\n\t\tinfo->env_step_mask = 0x0F;\n\t}\n\telse //if ((chip_type & 0xF0) == 0x10)\t// CHTYPE_YMxxxx variants (also YM2203/2608/2610)\n\t{\n\t\tinfo->step = 1;\n\t\tinfo->par = &ym2149_param;\n\t\tinfo->par_env = &ym2149_param_env;\n\t\tinfo->zero_is_off = 0;\n\t\tinfo->env_step_mask = 0x1F;\n\n\t\t/* YM2149 master clock divider? */\n\t\tif (info->intf->flags & YM2149_PIN26_LOW)\n\t\t\tmaster_clock /= 2;\n\t}\n\tif (intf->flags & AY8910_ZX_STEREO)\n\t{\n\t\t// ABC Stereo\n\t\tinfo->StereoMask[0] = 0x01;\n\t\tinfo->StereoMask[1] = 0x03;\n\t\tinfo->StereoMask[2] = 0x02;\n\t}\n\telse\n\t{\n\t\tinfo->StereoMask[0] = 0x03;\n\t\tinfo->StereoMask[1] = 0x03;\n\t\tinfo->StereoMask[2] = 0x03;\n\t}\n\n\tbuild_mixer_table(info);\n\n\t/* The envelope is pacing twice as fast for the YM2149 as for the AY-3-8910,    */\n\t/* This handled by the step parameter. Consequently we use a divider of 8 here. */\n\t//info->channel = stream_create(device, 0, info->streams, device->clock / 8, info, ay8910_update);\n\n\tay8910_set_clock_ym(info,clock);\n\t//ay8910_statesave(info, device);\n\n\tfor (CurChn = 0; CurChn < NUM_CHANNELS; CurChn ++)\n\t\tinfo->MuteMsk[CurChn] = 0;\n\t\n\treturn info;\n}\n\nvoid ay8910_stop_ym(void *chip)\n{\n\tfree(chip);\n}\n\nvoid ay8910_reset_ym(void *chip)\n{\n\tay8910_context *psg = (ay8910_context *)chip;\n\tint i;\n\n\tpsg->register_latch = 0;\n\tpsg->rng = 1;\n\tpsg->output[0] = 0;\n\tpsg->output[1] = 0;\n\tpsg->output[2] = 0;\n\tpsg->count[0] = 0;\n\tpsg->count[1] = 0;\n\tpsg->count[2] = 0;\n\tpsg->count_noise = 0;\n\tpsg->count_env = 0;\n\tpsg->prescale_noise = 0;\n\tpsg->last_enable = -1;\t/* force a write */\n\tfor (i = 0;i < AY_PORTA;i++)\n\t\tay8910_write_reg(psg,i,0);\n\tpsg->ready = 1;\n#if ENABLE_REGISTER_TEST\n\tay8910_write_reg(psg, AY_AFINE, 0);\n\tay8910_write_reg(psg, AY_ACOARSE, 1);\n\tay8910_write_reg(psg, AY_BFINE, 0);\n\tay8910_write_reg(psg, AY_BCOARSE, 2);\n\tay8910_write_reg(psg, AY_CFINE, 0);\n\tay8910_write_reg(psg, AY_CCOARSE, 4);\n\t//#define AY_NOISEPER   (6)\n\tay8910_write_reg(psg, AY_ENABLE, ~7);\n\tay8910_write_reg(psg, AY_AVOL, 10);\n\tay8910_write_reg(psg, AY_BVOL, 10);\n\tay8910_write_reg(psg, AY_CVOL, 10);\n\t//#define AY_EFINE  (11)\n\t//#define AY_ECOARSE    (12)\n\t//#define AY_ESHAPE (13)\n#endif\n\tif (psg->chip_type & 0x20)\n\t\tpsg->IsDisabled = 0x01;\n}\n\n/*void ay8910_set_volume(UINT8 ChipID,int channel,int volume)\n{\n\t//ay8910_context *psg = get_safe_token(device);\n\tint ch;\n\n\tfor (ch = 0; ch < psg->streams; ch++)\n\t\tif (channel == ch || psg->streams == 1 || channel == ALL_8910_CHANNELS)\n\t\t\tstream_set_output_gain(psg->channel, ch, volume / 100.0);\n}*/\n\nvoid ay8910_set_clock_ym(void *chip, int clock)\n{\n\tay8910_context *psg = (ay8910_context *)chip;\n\t\n\tif ((psg->chip_type & 0xF0) == 0x10 && (psg->intf->flags & YM2149_PIN26_LOW))\n\t\tclock /= 2;\n\t\n\t//stream_set_sample_rate(psg->channel, clock / 8 );\n\tif (psg->SmpRateFunc != NULL)\n\t\tpsg->SmpRateFunc(psg->SmpRateData, clock / 8);\n\t\n\treturn;\n}\n\nvoid ay8910_write_ym(void *chip, int addr, int data)\n{\n\tay8910_context *psg = (ay8910_context *)chip;\n\n\tif (addr & 1)\n\t{\t/* Data port */\n\t\tint r = psg->register_latch;\n\n\t\tif (r > 15) return;\n\t\tif (r == AY_ESHAPE || psg->regs[r] != data)\n\t\t{\n\t\t\t/* update the output buffer before changing the register */\n\t\t\t//stream_update(psg->channel);\n\t\t}\n\n\t\tay8910_write_reg(psg,r,data);\n\t}\n\telse\n\t{\t/* Register port */\n\t\tpsg->register_latch = data & 0x0f;\n\t}\n}\n\nint ay8910_read_ym(void *chip)\n{\n\tay8910_context *psg = (ay8910_context *)chip;\n\tint r = psg->register_latch;\n\n\tif (r > 15) return 0;\n\n\t/* There are no state dependent register in the AY8910! */\n\t/* stream_update(psg->channel); */\n\n\tswitch (r)\n\t{\n\tcase AY_PORTA:\n\t\t//if ((psg->regs[AY_ENABLE] & 0x40) != 0)\n\t\t//\tlogerror(\"warning: read from 8910 '%s' Port A set as output\\n\",psg->device->tag);\n\t\t/*\n           even if the port is set as output, we still need to return the external\n           data. Some games, like kidniki, need this to work.\n         */\n\t\t/*if (psg->portAread.read)\n\t\t\tpsg->regs[AY_PORTA] = devcb_call_read8(&psg->portAread, 0);\n\t\telse\n\t\t\tlogerror(\"%s: warning - read 8910 '%s' Port A\\n\",cpuexec_describe_context(psg->device->machine),psg->device->tag);*/\n\t\tbreak;\n\tcase AY_PORTB:\n\t\t//if ((psg->regs[AY_ENABLE] & 0x80) != 0)\n\t\t//\tlogerror(\"warning: read from 8910 '%s' Port B set as output\\n\",psg->device->tag);\n\t\t/*if (psg->portBread.read)\n\t\t\tpsg->regs[AY_PORTB] = devcb_call_read8(&psg->portBread, 0);\n\t\telse\n\t\t\tlogerror(\"%s: warning - read 8910 '%s' Port B\\n\",cpuexec_describe_context(psg->device->machine),psg->device->tag);*/\n\t\tbreak;\n\t}\n\n\t/* Depending on chip type, unused bits in registers may or may not be accessible.\n\tUntested chips are assumed to regard them as 'ram'\n\tTested and confirmed on hardware:\n\t- AY-3-8910: inaccessible bits (see masks below) read back as 0\n\t- YM2149: no anomaly\n\t*/\n\tif (! (psg->chip_type & 0x10)) {\n\t\tconst UINT8 mask[0x10]={\n\t\t\t0xff,0x0f,0xff,0x0f,0xff,0x0f,0x1f,0xff,0x1f,0x1f,0x1f,0xff,0xff,0x0f,0xff,0xff\n\t\t};\n\n\t\treturn psg->regs[r] & mask[r];\n\t}\n\telse return psg->regs[r];\n}\n\n/*************************************\n *\n * Sound Interface\n *\n *************************************/\n\n//static DEVICE_START( ay8910 )\n/*int device_start_ay8910(UINT8 ChipID, int clock, unsigned char chip_type, unsigned char Flags)\n{\n\tstatic const ay8910_interface generic_ay8910 =\n\t{\n\t\tAY8910_LEGACY_OUTPUT,\n\t\tAY8910_DEFAULT_LOADS\n\t};\n\t//const ay8910_interface *intf = (device->static_config ? (const ay8910_interface *)device->static_config : &generic_ay8910);\n\tay8910_interface intf = generic_ay8910;\n\tay8910_context *psg;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tpsg = &AY8910Data[ChipID];\n\tintf.flags = Flags;\n\tay8910_start_ym(psg, chip_type, clock, &intf);\n\t\n\treturn clock / 8;\n}*/\nint ay8910_start(void **chip, int clock, UINT8 chip_type, UINT8 Flags)\n{\n\tstatic const ay8910_interface generic_ay8910 =\n\t{\n\t\tAY8910_LEGACY_OUTPUT,\n\t\tAY8910_DEFAULT_LOADS\n\t};\n\tay8910_interface intf = generic_ay8910;\n\tay8910_context *psg = (ay8910_context*)chip;\n\t\n\tpsg = (ay8910_context*)malloc(sizeof(ay8910_context));\n\tif(psg == NULL)\n\t\treturn 0;\n\tmemset(psg, 0x00, sizeof(ay8910_context));\n\t*chip = psg;\n\t\n\tintf.flags = Flags;\n\tay8910_start_ym(psg, chip_type, clock, &intf);\n\t\n\tif (Flags & YM2149_PIN26_LOW)\n\t\treturn clock / 16;\n\telse\n\t\treturn clock / 8;\n}\n\n/*static DEVICE_START( ym2149 )\n{\n\tstatic const ay8910_interface generic_ay8910 =\n\t{\n\t\tAY8910_LEGACY_OUTPUT,\n\t\tAY8910_DEFAULT_LOADS,\n\t\tDEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL\n\t};\n\tconst ay8910_interface *intf = (device->static_config ? (const ay8910_interface *)device->static_config : &generic_ay8910);\n\tay8910_start_ym(get_safe_token(device), SOUND_YM2149, device, device->clock, intf);\n}*/\n\n//static DEVICE_STOP( ay8910 )\n/*void device_stop_ay8910(UINT8 ChipID)\n{\n\tay8910_context *psg = &AY8910Data[ChipID];\n\tay8910_stop_ym(psg);\n}\n\n//static DEVICE_RESET( ay8910 )\nvoid device_reset_ay8910(UINT8 ChipID)\n{\n\tay8910_context *psg = &AY8910Data[ChipID];\n\tay8910_reset_ym(psg);\n}*/\n\n/*DEVICE_GET_INFO( ay8910 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ay8910_context);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ay8910 );\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( ay8910 );\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( ay8910 );\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"AY-3-8910A\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"PSG\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}\n\nDEVICE_GET_INFO( ay8912 )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ay8910 );\t\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"AY-3-8912A\");\t\t\t\t\tbreak;\n\t\tdefault: \t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(ay8910);\t\t\t\t\t\tbreak;\n\t}\n}\n\nDEVICE_GET_INFO( ay8913 )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ay8910 );\t\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"AY-3-8913A\");\t\t\t\t\tbreak;\n\t\tdefault: \t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(ay8910);\t\t\t\t\t\tbreak;\n\t}\n}\n\nDEVICE_GET_INFO( ay8930 )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ay8910 );\t\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"AY8930\");\t\t\t\t\t\tbreak;\n\t\tdefault: \t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(ay8910);\t\t\t\t\t\tbreak;\n\t}\n}\n\nDEVICE_GET_INFO( ym2149 )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ym2149 );\t\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YM2149\");\t\t\t\t\t\tbreak;\n\t\tdefault: \t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(ay8910);\t\t\t\t\t\tbreak;\n\t}\n}\n\nDEVICE_GET_INFO( ym3439 )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ym2149 );\t\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YM3439\");\t\t\t\t\t\tbreak;\n\t\tdefault: \t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(ay8910);\t\t\t\t\t\tbreak;\n\t}\n}\n\nDEVICE_GET_INFO( ymz284 )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ym2149 );\t\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YMZ284\");\t\t\t\t\t\tbreak;\n\t\tdefault: \t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(ay8910);\t\t\t\t\t\tbreak;\n\t}\n}\n\nDEVICE_GET_INFO( ymz294 )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ym2149 );\t\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YMZ294\");\t\t\t\t\t\tbreak;\n\t\tdefault: \t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(ay8910);\t\t\t\t\t\tbreak;\n\t}\n}*/\n\n/*************************************\n *\n * Read/Write Handlers\n *\n *************************************/\n\n//READ8_DEVICE_HANDLER( ay8910_r )\n/*UINT8 ay8910_r(UINT8 ChipID, offs_t offset)\n{\n\tay8910_context *psg = &AY8910Data[ChipID];\n\treturn ay8910_read_ym(psg);\n}\n\n//WRITE8_DEVICE_HANDLER( ay8910_data_address_w )\nvoid ay8910_data_address_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tay8910_context *psg = &AY8910Data[ChipID];\n\t// note that directly connecting BC1 to A0 puts data on 0 and address on 1\n\tay8910_write_ym(psg, ~offset & 1, data);\n}\n\n//WRITE8_DEVICE_HANDLER( ay8910_address_data_w )\nvoid ay8910_address_data_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tay8910_context *psg = &AY8910Data[ChipID];\n\tay8910_write_ym(psg, offset & 1, data);\n}\n\n//WRITE8_DEVICE_HANDLER( ay8910_address_w )\nvoid ay8910_address_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n#if ENABLE_REGISTER_TEST\n\treturn;\n#endif\n\tay8910_data_address_w(ChipID, 1, data);\n}\n\n//WRITE8_DEVICE_HANDLER( ay8910_data_w )\nvoid ay8910_data_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n#if ENABLE_REGISTER_TEST\n\treturn;\n#endif\n\tay8910_data_address_w(ChipID, 0, data);\n}*/\n\n\nvoid ay8910_set_mute_mask_ym(void *chip, UINT32 MuteMask)\n{\n\tay8910_context *psg = (ay8910_context *)chip;\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < NUM_CHANNELS; CurChn ++)\n\t\tpsg->MuteMsk[CurChn] = (MuteMask & (1 << CurChn)) ? 0 : ~0;\n\t\n\treturn;\n}\n\nvoid ay8910_set_stereo_mask_ym(void *chip, UINT32 StereoMask)\n{\n\tay8910_context *psg = (ay8910_context *)chip;\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < NUM_CHANNELS; CurChn ++) {\n\t\tpsg->StereoMask[CurChn] = StereoMask &3;\n\t\tStereoMask >>= 2;\n\t}\t\n\treturn;\n}\n\n/*void ay8910_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tay8910_context *psg = &AY8910Data[ChipID];\n\tay8910_set_mute_mask_ym(psg, MuteMask);\n}*/\n\nvoid ay8910_set_srchg_cb_ym(void *chip, SRATE_CALLBACK CallbackFunc, void* DataPtr)\n{\n\tay8910_context *info = (ay8910_context *)chip;\n\t\n\t// set Sample Rate Change Callback routine\n\tinfo->SmpRateFunc = CallbackFunc;\n\tinfo->SmpRateData = DataPtr;\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/ay8910.h",
    "content": "#pragma once\n\n//#include \"devcb.h\"\n#define DEVCB_TYPE_NULL\t\t\t\t(0)\n#define DEVCB_NULL\t\t\t\t\t\t\t{ DEVCB_TYPE_NULL }\n\n/*\nAY-3-8910A: 2 I/O ports\nAY-3-8912A: 1 I/O port\nAY-3-8913A: 0 I/O port\nAY8930: upper compatible with 8910.\nIn extended mode, it has higher resolution and duty ratio setting\nYM2149: higher resolution\nYM3439: same as 2149\nYMZ284: 0 I/O port, different clock divider\nYMZ294: 0 I/O port\n*/\n\n#define ALL_8910_CHANNELS -1\n\n/* Internal resistance at Volume level 7. */\n\n#define AY8910_INTERNAL_RESISTANCE\t(356)\n#define YM2149_INTERNAL_RESISTANCE\t(353)\n\n/*\n * Default values for resistor loads.\n * The macro should be used in AY8910interface if\n * the real values are unknown.\n */\n#define AY8910_DEFAULT_LOADS\t\t{1000, 1000, 1000}\n\n/*\n * The following is used by all drivers not reviewed yet.\n * This will like the old behaviour, output between\n * 0 and 7FFF\n */\n#define AY8910_LEGACY_OUTPUT\t\t(1)\n\n/*\n * Specifing the next define will simulate the special\n * cross channel mixing if outputs are tied together.\n * The driver will only provide one stream in this case.\n */\n#define AY8910_SINGLE_OUTPUT\t\t(2)\n\n/*\n * The follwoing define is the default behaviour.\n * Output level 0 is 0V and 7ffff corresponds to 5V.\n * Use this to specify that a discrete mixing stage\n * follows.\n */\n#define AY8910_DISCRETE_OUTPUT\t\t(4)\n\n/*\n * The follwoing define causes the driver to output\n * raw volume levels, i.e. 0 .. 15 and 0..31.\n * This is intended to be used in a subsequent\n * mixing modul (i.e. mpatrol ties 6 channels from\n * AY-3-8910 together). Do not use it now.\n */\n/* TODO: implement mixing module */\n#define AY8910_RAW_OUTPUT\t\t\t(8)\n\n#define AY8910_ZX_STEREO\t\t\t0x80\n/*\n* This define specifies the initial state of YM2149\n* pin 26 (SEL pin). By default it is set to high,\n* compatible with AY8910.\n*/\n/* TODO: make it controllable while it's running (used by any hw???) */\n#define YM2149_PIN26_HIGH           (0x00) /* or N/C */\n#define YM2149_PIN26_LOW            (0x10)\n\ntypedef struct _ay8910_interface ay8910_interface;\nstruct _ay8910_interface\n{\n\tint\t\t\t\t\tflags;\t\t\t/* Flags */\n\tint\t\t\t\t\tres_load[3]; \t/* Load on channel in ohms */\n\t//devcb_read8\t\t\tportAread;\n\t//devcb_read8\t\t\tportBread;\n\t//devcb_write8\t\tportAwrite;\n\t//devcb_write8\t\tportBwrite;\n};\n\n\n//void ay8910_set_volume(UINT8 ChipID,int channel,int volume);\n\n/*READ8_DEVICE_HANDLER( ay8910_r );\nWITE8_DEVICE_HANDLER( ay8910_address_w );\nWRITE8_DEVICE_HANDLER( ay8910_data_w );*/\n/*UINT8 ay8910_r(UINT8 ChipID, offs_t offset);\nvoid ay8910_address_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ay8910_data_w(UINT8 ChipID, offs_t offset, UINT8 data);*/\n\n/* use this when BC1 == A0; here, BC1=0 selects 'data' and BC1=1 selects 'latch address' */\n//WRITE8_DEVICE_HANDLER( ay8910_data_address_w );\n//void ay8910_data_address_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\n/* use this when BC1 == !A0; here, BC1=0 selects 'latch address' and BC1=1 selects 'data' */\n//WRITE8_DEVICE_HANDLER( ay8910_address_data_w );\n//void ay8910_address_data_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\n\n/*********** An interface for SSG of YM2203 ***********/\n\n//void *ay8910_start_ym(void *infoptr, sound_type chip_type, const device_config *device, int clock, const ay8910_interface *intf);\nvoid *ay8910_start_ym(void *infoptr, unsigned char chip_type, int clock, const ay8910_interface *intf);\n\nvoid ay8910_stop_ym(void *chip);\nvoid ay8910_reset_ym(void *chip);\nvoid ay8910_set_clock_ym(void *chip, int clock);\nvoid ay8910_write_ym(void *chip, int addr, int data);\nint ay8910_read_ym(void *chip);\n\n//void ay8910_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nvoid ay8910_update_one(void *param, stream_sample_t **outputs, int samples);\nint ay8910_start(void **chip, int clock, UINT8 chip_type, UINT8 Flags);\n/*int device_start_ay8910(UINT8 ChipID, int clock, unsigned char chip_type, unsigned char Flags);\nvoid device_stop_ay8910(UINT8 ChipID);\nvoid device_reset_ay8910(UINT8 ChipID);*/\n\nvoid ay8910_set_mute_mask_ym(void *chip, UINT32 MuteMask);\nvoid ay8910_set_stereo_mask_ym(void *chip, UINT32 StereoMask);\n//void ay8910_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\nvoid ay8910_set_srchg_cb_ym(void *chip, SRATE_CALLBACK CallbackFunc, void* DataPtr);\n\n/*DEVICE_GET_INFO( ay8910 );\nDEVICE_GET_INFO( ay8912 );\nDEVICE_GET_INFO( ay8913 );\nDEVICE_GET_INFO( ay8930 );\nDEVICE_GET_INFO( ym2149 );\nDEVICE_GET_INFO( ym3439 );\nDEVICE_GET_INFO( ymz284 );\nDEVICE_GET_INFO( ymz294 );\n\n#define SOUND_AY8910 DEVICE_GET_INFO_NAME( ay8910 )\n#define SOUND_AY8912 DEVICE_GET_INFO_NAME( ay8912 )\n#define SOUND_AY8913 DEVICE_GET_INFO_NAME( ay8913 )\n#define SOUND_AY8930 DEVICE_GET_INFO_NAME( ay8930 )\n#define SOUND_YM2149 DEVICE_GET_INFO_NAME( ym2149 )\n#define SOUND_YM3439 DEVICE_GET_INFO_NAME( ym3439 )\n#define SOUND_YMZ284 DEVICE_GET_INFO_NAME( ymz284 )\n#define SOUND_YMZ294 DEVICE_GET_INFO_NAME( ymz294 )*/\n"
  },
  {
    "path": "VGMPlay/chips/ay8910_opl.c",
    "content": "#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n#include \"math.h\"\n\nvoid OPL_RegMapper(UINT16 Reg, UINT8 Data);\n\n#define NUM_CHANNELS 3\n\n/* register id's */\n#define AY_AFINE\t(0)\n#define AY_ACOARSE\t(1)\n#define AY_BFINE\t(2)\n#define AY_BCOARSE\t(3)\n#define AY_CFINE\t(4)\n#define AY_CCOARSE\t(5)\n#define AY_NOISEPER\t(6)\n#define AY_ENABLE\t(7)\n#define AY_AVOL\t\t(8)\n#define AY_BVOL\t\t(9)\n#define AY_CVOL\t\t(10)\n#define AY_EFINE\t(11)\n#define AY_ECOARSE\t(12)\n#define AY_ESHAPE\t(13)\n\n#define AY_PORTA\t(14)\n#define AY_PORTB\t(15)\n\n#define NOISE_ENABLEQ(_psg, _chan)\t(((_psg)->regs[AY_ENABLE] >> (3 + _chan)) & 1)\n#define TONE_ENABLEQ(_psg, _chan)\t(((_psg)->regs[AY_ENABLE] >> (_chan)) & 1)\n#define TONE_PERIOD(_psg, _chan)\t( (_psg)->regs[(_chan) << 1] | (((_psg)->regs[((_chan) << 1) | 1] & 0x0f) << 8) )\n#define NOISE_PERIOD(_psg)\t\t\t( (_psg)->regs[AY_NOISEPER] & 0x1f)\n#define TONE_VOLUME(_psg, _chan)\t( (_psg)->regs[AY_AVOL + (_chan)] & 0x0f)\n//#define TONE_ENVELOPE(_psg, _chan)\t(((_psg)->regs[AY_AVOL + (_chan)] >> 4) & (((_psg)->device->type() == AY8914) ? 3 : 1))\n#define TONE_ENVELOPE(_psg, _chan)\t(((_psg)->regs[AY_AVOL + (_chan)] >> 4) & (((_psg)->chip_type == CHTYPE_AY8914) ? 3 : 1))\n#define ENVELOPE_PERIOD(_psg)\t\t(((_psg)->regs[AY_EFINE] | ((_psg)->regs[AY_ECOARSE]<<8)))\n\n\ntypedef struct _ay_ym_param ay_ym_param;\nstruct _ay_ym_param\n{\n\tdouble r_up;\n\tdouble r_down;\n\tint    res_count;\n\tdouble res[32];\n};\n\ntypedef struct _ay8910_context_opl ay8910_context_opl;\nstruct _ay8910_context_opl\n{\n\tUINT32 clock;\n\tUINT8 regs[0x10];\n\t//INT32 count[NUM_CHANNELS];\n\t//UINT8 output[NUM_CHANNELS];\n\t//UINT8 output_noise;\n\t//INT32 count_noise;\n\t//INT32 count_env;\n\t//INT8 env_step;\n\t//UINT32 env_volume;\n\t//UINT8 hold,alternate,attack,holding;\n\t//INT32 rng;\n\t//UINT8 env_step_mask;\n\t/* init parameters ... */\n\t//int step;\n\t//int zero_is_off;\n\t//UINT8 vol_enabled[NUM_CHANNELS];\n\tconst ay_ym_param *par;\n\tconst ay_ym_param *par_env;\n\tINT32 vol_table[16];\n\tUINT8 Vol2OPL[16];\n\t//INT32 env_table[32];\n\t//INT32 vol3d_table[8*32*32*32];\n\t//devcb_resolved_read8 portAread;\n\t//devcb_resolved_read8 portBread;\n\t//devcb_resolved_write8 portAwrite;\n\t//devcb_resolved_write8 portBwrite;\n\t//UINT32 MuteMsk[NUM_CHANNELS];\n\t\n\tUINT8 chip_type;\n\t\n\tUINT8 LastVol[3];\n\tUINT16 LastFreq[4];\n\tUINT16 OPLFreq[4];\n\tUINT8 OPLVol[3];\n\tUINT8 Enabled;\n};\n\n\nstatic const UINT8 REG_LIST[0x0B] =\n\t{0x20, 0x40, 0x60, 0x80, 0xE0, 0x23, 0x43, 0x63, 0x83, 0xE3, 0xC0};\n// writing Reg 83 Data #6 makes a smooth fading, if you break playing\n// actually the release time could be everything - it wouldn't change anything\nstatic const UINT8 SQUARE_FM_INS_OPL[0x0B] =\n\t{0x02, 0x18, 0xFF, 0x00, 0x02, 0x01, 0x00, 0xF0, 0xF6, 0x00, 0x00};\t// OPL2/OPL3\nstatic const UINT8 SQUARE_FM_INS_OPL3[0x0B] =\n\t{0x01, 0x3F, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xF0, 0xF6, 0x06, 0x01};\t// OPL3 only\n// OPL3 has a SquareWave Waveform (OPL2 has only SineWaves)\n//static const UINT8 NOISE_FM_INS[0x0A] =\n//\t{0x0F, 0x00, 0xF0, 0xFF, 0x00, 0x01, 0x00, 0xF0, 0xF6, 0x00};\n\n/* Volume Table (4-bit AY8910 -> 6-bit OPL Conversion)\n\tAY8910\t\tOPL\n\tIdx\tVol\t\tIdx\tVol\n\t??\t??\t\t??\t??\n*/\n/*static const UINT8 VOL_OPL[0x10] =\n\t{0x3F, 0x38, 0x34, 0x20, 0x2C, 0x28, 0x24, 0x20,\n\t 0x1C, 0x18, 0x14, 0x10, 0x0C, 0x08, 0x04, 0x00};*/\n\n\nextern UINT8 OPL_MODE;\n#define MAX_CHIPS\t0x02\nstatic ay8910_context_opl AY8910Data[MAX_CHIPS];\n\nstatic const ay_ym_param ym2149_param =\n{\n\t630, 801,\n\t16,\n\t{ 73770, 37586, 27458, 21451, 15864, 12371, 8922,  6796,\n\t   4763,  3521,  2403,  1737,  1123,   762,  438,   251 },\n};\n\nstatic const ay_ym_param ym2149_param_env =\n{\n\t630, 801,\n\t32,\n\t{ 103350, 73770, 52657, 37586, 32125, 27458, 24269, 21451,\n\t   18447, 15864, 14009, 12371, 10506,  8922,  7787,  6796,\n\t    5689,  4763,  4095,  3521,  2909,  2403,  2043,  1737,\n\t    1397,  1123,   925,   762,   578,   438,   332,   251 },\n};\n\nstatic const ay_ym_param ay8910_param =\n{\n\t800000, 8000000,\n\t16,\n\t{ 15950, 15350, 15090, 14760, 14275, 13620, 12890, 11370,\n\t  10600,  8590,  7190,  5985,  4820,  3945,  3017,  2345 }\n};\n\nstatic void SendVolume(ay8910_context_opl* chip, UINT8 Channel)\n{\n\tUINT8 Volume;\n\t\n\t//if (Channel >= 0x04)\n\t//\tChannel &= 0x03;\n\t\n\tVolume = TONE_VOLUME(chip, Channel);\n\tif (Volume == chip->LastVol[Channel])\n\t\treturn;\n\telse\n\t\tchip->LastVol[Channel] = Volume;\n\t\n\tif (! (Volume & 0x10))\n\t{\n\t\tchip->OPLVol[Channel] = chip->Vol2OPL[Volume];\n\t}\n\telse\n\t{\n\t\t// TODO: Handle hardware envelope shapes correctly\n\t\tchip->OPLVol[Channel] = 0x00;\n\t}\n\t\n\tif (chip->Enabled & (1 << Channel))\n\t\tOPL_RegMapper(0x43 + Channel, 0x00 | 0x3F);\n\telse\t// 0 - enable\n\t\tOPL_RegMapper(0x43 + Channel, 0x00 | chip->OPLVol[Channel]);\n\t\n\treturn;\n}\n\nstatic void SendFrequency(ay8910_context_opl* chip, UINT8 Channel)\n{\n\tconst double OPL_CHIP_RATE = 3579545.0 / 72.0;\n\t\n\tUINT16 Period;\n\tdouble FreqVal;\n\tINT16 FNum;\n\tINT8 BlockVal;\n\t\n\t//Channel &= 0x03;\n\tPeriod = TONE_PERIOD(chip, Channel);\n\tif (Period == chip->LastFreq[Channel])\n\t\treturn;\n\telse\n\t\tchip->LastFreq[Channel] = Period;\n\t\n\tif (Period)\n\t\tFreqVal = (chip->clock / 16.0) / Period;\n\telse\n\t\tFreqVal = 0.0;\n\tif (FreqVal > OPL_CHIP_RATE)\n\t\tFreqVal = 0.0;\n\t\n\tBlockVal = (UINT8)(0x05 + (log(FreqVal) - log(440.0)) / log(2.0));\n\tif (BlockVal < 0x00)\n\t{\n\t\tBlockVal = 0x00;\n\t\tFNum = 0x000;\n\t}\n\telse if (BlockVal > 0x07)\n\t{\n\t\tBlockVal = 0x07;\n\t\tFNum = 0x3FF;\n\t}\n\telse\n\t{\n\t\tFNum = (UINT16)(FreqVal * (1 << (20 - BlockVal)) / OPL_CHIP_RATE + 0.5);\n\t\tif (FNum < 0x000)\n\t\t\tFNum = 0x000;\n\t\telse if (FNum > 0x3FF)\n\t\t\tFNum = 0x3FF;\n\t}\n\t\n\tchip->OPLFreq[Channel] = (BlockVal << 10) | (FNum << 0);\n\t\n\tOPL_RegMapper(0xA0 | Channel, chip->OPLFreq[Channel] & 0x00FF);\n\t/*if (chip->Enabled & (1 << Channel))\n\t\tOPL_RegMapper(0xB0 | Channel, 0x00 | (chip->OPLFreq[Channel] >> 8));\n\telse\t// 0 - enable*/\n\t\tOPL_RegMapper(0xB0 | Channel, 0x20 | (chip->OPLFreq[Channel] >> 8));\n\t\n\treturn;\n}\n\nvoid ay8910_write_opl(UINT8 ChipID, UINT8 r, UINT8 v)\n{\n\tay8910_context_opl* chip = &AY8910Data[ChipID];\n\tUINT8 CurChn;\n\tUINT8 EnDiff;\n\t\n\tchip->regs[r] = v;\n\n\tswitch(r)\n\t{\n\tcase AY_AFINE:\n\tcase AY_ACOARSE:\n\tcase AY_BFINE:\n\tcase AY_BCOARSE:\n\tcase AY_CFINE:\n\tcase AY_CCOARSE:\n\t\tSendFrequency(chip, r >> 1);\n\t\tbreak;\n\tcase AY_NOISEPER:\n\t\tbreak;\n\tcase AY_AVOL:\n\tcase AY_BVOL:\n\tcase AY_CVOL:\n\t\tSendVolume(chip, r - AY_AVOL);\n\t\tbreak;\n\tcase AY_EFINE:\n\tcase AY_ECOARSE:\n\t\tbreak;\n\tcase AY_ENABLE:\n\t\tEnDiff = chip->Enabled ^ v;\n\t\tfor (CurChn = 0x00; CurChn < 0x03; CurChn ++)\n\t\t{\n\t\t\tif (EnDiff & (1 << CurChn))\n\t\t\t{\n\t\t\t\t// using the Key On bit sounds horrible, if it's disabled and enabled a lot\n\t\t\t\t// (see Final Fantasy MSX: Chaos Temple\n\t\t\t\t/*if (v & (1 << CurChn))\n\t\t\t\t\tOPL_RegMapper(0xB0 | CurChn, 0x00 | (chip->OPLFreq[CurChn] >> 8));\n\t\t\t\telse\t// 0 - enable\n\t\t\t\t\tOPL_RegMapper(0xB0 | CurChn, 0x20 | (chip->OPLFreq[CurChn] >> 8));*/\n\t\t\t\tif (v & (1 << CurChn))\n\t\t\t\t\tOPL_RegMapper(0x43 + CurChn, 0x00 | 0x3F);\n\t\t\t\telse\t// 0 - enable\n\t\t\t\t\tOPL_RegMapper(0x43 + CurChn, 0x00 | chip->OPLVol[CurChn]);\n\t\t\t}\n\t\t}\n\t\tchip->Enabled = v;\n\t\tbreak;\n\tcase AY_ESHAPE:\n\t\tbreak;\n\tcase AY_PORTA:\n\tcase AY_PORTB:\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\nINLINE void build_single_table(double rl, const ay_ym_param *par, INT32 *tab, UINT8* OPLtab)\n{\n\tint j;\n\tdouble rt, rw = 0;\n\tdouble temp[32], min=10.0, max=0.0;\n\t\n\tfor (j=0; j < par->res_count; j++)\n\t{\n\t\trt = 1.0 / par->r_down + 1.0 / rl;\n\t\t\n\t\trw = 1.0 / par->res[j];\n\t\trt += 1.0 / par->res[j];\n\t\t\n\t\trw += 1.0 / par->r_up;\n\t\trt += 1.0 / par->r_up;\n\t\t\n\t\ttemp[j] = rw / rt;\n\t\tif (temp[j] < min)\n\t\t\tmin = temp[j];\n\t\tif (temp[j] > max)\n\t\t\tmax = temp[j];\n\t}\n\tfor (j = 0; j < par->res_count; j ++)\n\t{\n\t\ttab[j] = (INT32)(0x10000 * temp[j]);\n\t\trt = (temp[j] - min) / (max - min);\n\t\trt = -8.0 * log(temp[j]) / log(2.0);\n\t\tOPLtab[j] = (UINT8)rt;\n\t}\n\t\n\treturn;\n}\n\nstatic void ay8910_start_opl(int clock, ay8910_context_opl* chip, UINT8 chip_type)\n{\n\tconst UINT8* SQUARE_FM_INS;\n\tUINT8 i;\n\tUINT8 reg;\n\t\n\tchip->clock = clock;\n\tchip->chip_type = chip_type;\n\tif ((chip_type & 0xF0) == 0x00)\t// CHTYPE_AY89xx variants\n\t{\n\t//\tchip->step = 2;\n\t\tchip->par = &ay8910_param;\n\t\tchip->par_env = &ay8910_param;\n\t\t//chip->zero_is_off = 0;\n\t//\tchip->env_step_mask = 0x0F;\n\t}\n\telse //if ((chip_type & 0xF0) == 0x10)\t// CHTYPE_YMxxxx variants (also YM2203/2608/2610)\n\t{\n\t//\tchip->step = 1;\n\t\tchip->par = &ym2149_param;\n\t\tchip->par_env = &ym2149_param_env;\n\t\t//chip->zero_is_off = 0;\n\t//\tchip->env_step_mask = 0x1F;\n\t\t\n\t\t/*// YM2149 master clock divider?\n\t\tif (info->intf->flags & YM2149_PIN26_LOW)\n\t\t\tmaster_clock /= 2;*/\n\t}\n\t\n\tfor (i = 0; i < 3; i ++)\n\t{\n\t\tbuild_single_table(1000, chip->par, chip->vol_table, chip->Vol2OPL);\n\t\t//build_single_table(1000, chip->par_env, psg->env_table, NULL);\n\t}\n\t\n\tfor (i = 0x00; i < 0x10; i ++)\n\t\tchip->regs[i] = 0x00;\n\t\n\tif (OPL_MODE == 0x03)\n\t\tSQUARE_FM_INS = SQUARE_FM_INS_OPL3;\n\telse\n\t\tSQUARE_FM_INS = SQUARE_FM_INS_OPL;\n\t// Init Instruments\n\tfor (i = 0; i < 3; i++)\n\t{\n\t\tfor (reg = 0x00; reg < 0x0A; reg ++)\n\t\t\tOPL_RegMapper(REG_LIST[reg] + i, SQUARE_FM_INS[reg]);\n\t\tOPL_RegMapper(REG_LIST[0x0A] + i, 0x30 | SQUARE_FM_INS[0x0A]);\n\t}\n\t\n\tchip->Enabled = 0xFF;\n\tfor (i = 0; i < 3; i ++)\n\t{\n\t\tchip->LastVol[i] = 0xFF;\n\t\tchip->LastFreq[i] = 0xFFFF;\n\t\tchip->OPLFreq[i] = 0x0000;\n\t\tSendVolume(chip, i);\n\t\t//SendFrequency(chip, i);\n\t\tOPL_RegMapper(0xB0 | i, 0x00);\n\t}\n\t\n\treturn;\n}\n\n\nvoid start_ay8910_opl(UINT8 ChipID, int clock, UINT8 chip_type)\n{\n\tay8910_context_opl* chip;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn;\n\t\n\tchip = &AY8910Data[ChipID];\n\tay8910_start_opl(clock & 0x7FFFFFFF, chip, chip_type);\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/ay_intf.c",
    "content": "/****************************************************************\n\n    MAME / MESS functions\n\n****************************************************************/\n\n#include <stdlib.h>\t// for free\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#include \"ay8910.h\"\t\t// must be always included (for YM2149_PIN26_LOW)\n#include \"emu2149.h\"\n#include \"ay_intf.h\"\n\n\n#ifdef ENABLE_ALL_CORES\n#define EC_MAME\t\t0x01\t// AY8910 core from MAME\n#endif\n#define EC_EMU2149\t0x00\t// EMU2149 from NSFPlay\n\n\n/* for stream system */\ntypedef struct _ayxx_state ayxx_state;\nstruct _ayxx_state\n{\n\tvoid *chip;\n};\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nstatic UINT8 EMU_CORE = 0x00;\n\nextern UINT32 SampleRate;\n#define MAX_CHIPS\t0x02\nstatic ayxx_state AYxxData[MAX_CHIPS];\n\nvoid ayxx_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tayxx_state *info = &AYxxData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tay8910_update_one(info->chip, outputs, samples);\n\t\tbreak;\n#endif\n\tcase EC_EMU2149:\n\t\tPSG_calc_stereo((PSG*)info->chip, outputs, samples);\n\t\tbreak;\n\t}\n}\n\nint device_start_ayxx(UINT8 ChipID, int clock, UINT8 chip_type, UINT8 Flags)\n{\n\tayxx_state *info;\n\tint rate;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &AYxxData[ChipID];\n\tif (Flags & YM2149_PIN26_LOW)\n\t\trate = clock / 16;\n\telse\n\t\trate = clock / 8;\n\tif (((CHIP_SAMPLING_MODE & 0x01) && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\t\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\trate = ay8910_start(&info->chip, clock, chip_type, Flags);\n\t\tbreak;\n#endif\n\tcase EC_EMU2149:\n\t\tif (Flags & YM2149_PIN26_LOW)\n\t\t\tclock /= 2;\n\t\tinfo->chip = PSG_new(clock, rate);\n\t\tif (info->chip == NULL)\n\t\t\treturn 0;\n\t\tPSG_setVolumeMode((PSG*)info->chip, (chip_type & 0x10) ? 1 : 2);\n\t\tPSG_setFlags((PSG*)info->chip, Flags & ~YM2149_PIN26_LOW);\n\t\tbreak;\n\t}\n \n\treturn rate;\n}\n\nvoid device_stop_ayxx(UINT8 ChipID)\n{\n\tayxx_state *info = &AYxxData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tay8910_stop_ym(info->chip);\n\t\tbreak;\n#endif\n\tcase EC_EMU2149:\n\t\tPSG_delete((PSG*)info->chip);\n\t\tbreak;\n\t}\n\tinfo->chip = NULL;\n}\n\nvoid device_reset_ayxx(UINT8 ChipID)\n{\n\tayxx_state *info = &AYxxData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tay8910_reset_ym(info->chip);\n\t\tbreak;\n#endif\n\tcase EC_EMU2149:\n\t\tPSG_reset((PSG*)info->chip);\n\t\tbreak;\n\t}\n}\n\n\nvoid ayxx_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tayxx_state *info = &AYxxData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tay8910_write_ym(info->chip, offset, data);\n\t\tbreak;\n#endif\n\tcase EC_EMU2149:\n\t\tPSG_writeIO((PSG*)info->chip, offset, data);\n\t\tbreak;\n\t}\n}\n\nvoid ayxx_set_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tEMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;\n#else\n\tEMU_CORE = EC_EMU2149;\n#endif\n\t\n\treturn;\n}\n\nvoid ayxx_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tayxx_state *info = &AYxxData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tay8910_set_mute_mask_ym(info->chip, MuteMask);\n\t\tbreak;\n#endif\n\tcase EC_EMU2149:\n\t\tPSG_setMask((PSG*)info->chip, MuteMask);\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\nvoid ayxx_set_stereo_mask(UINT8 ChipID, UINT32 StereoMask)\n{\n\tayxx_state *info = &AYxxData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tay8910_set_stereo_mask_ym(info->chip, StereoMask);\n\t\tbreak;\n#endif\n\tcase EC_EMU2149:\n\t\tPSG_setStereoMask((PSG*)info->chip, StereoMask);\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/ay_intf.h",
    "content": "#pragma once\n\nvoid ayxx_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_ayxx(UINT8 ChipID, int clock, UINT8 chip_type, UINT8 Flags);\nvoid device_stop_ayxx(UINT8 ChipID);\nvoid device_reset_ayxx(UINT8 ChipID);\n\nvoid ayxx_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid ayxx_set_emu_core(UINT8 Emulator);\nvoid ayxx_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\nvoid ayxx_set_stereo_mask(UINT8 ChipID, UINT32 StereoMask);\n"
  },
  {
    "path": "VGMPlay/chips/c140.c",
    "content": "/*\nC140.c\n\nSimulator based on AMUSE sources.\nThe C140 sound chip is used by Namco System 2 and System 21\nThe 219 ASIC (which incorporates a modified C140) is used by Namco NA-1 and NA-2\nThis chip controls 24 channels (C140) or 16 (219) of PCM.\n16 bytes are associated with each channel.\nChannels can be 8 bit signed PCM, or 12 bit signed PCM.\n\nTimer behavior is not yet handled.\n\nUnmapped registers:\n    0x1f8:timer interval?   (Nx0.1 ms)\n    0x1fa:irq ack? timer restart?\n    0x1fe:timer switch?(0:off 1:on)\n\n--------------\n\n    ASIC \"219\" notes\n\n    On the 219 ASIC used on NA-1 and NA-2, the high registers have the following\n    meaning instead:\n    0x1f7: bank for voices 0-3\n    0x1f1: bank for voices 4-7\n    0x1f3: bank for voices 8-11\n    0x1f5: bank for voices 12-15\n\n    Some games (bkrtmaq, xday2) write to 0x1fd for voices 12-15 instead.  Probably the bank registers\n    mirror at 1f8, in which case 1ff is also 0-3, 1f9 is also 4-7, 1fb is also 8-11, and 1fd is also 12-15.\n\n    Each bank is 0x20000 (128k), and the voice addresses on the 219 are all multiplied by 2.\n    Additionally, the 219's base pitch is the same as the C352's (42667).  But these changes\n    are IMO not sufficient to make this a separate file - all the other registers are\n    fully compatible.\n\n    Finally, the 219 only has 16 voices.\n*/\n/*\n    2000.06.26  CAB     fixed compressed pcm playback\n    2002.07.20  R.Belmont   added support for multiple banking types\n    2006.01.08  R.Belmont   added support for NA-1/2 \"219\" derivative\n*/\n\n\n//#include \"emu.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n#include \"c140.h\"\n\n#define MAX_VOICE 24\n\nstruct voice_registers\n{\n\tUINT8 volume_right;\n\tUINT8 volume_left;\n\tUINT8 frequency_msb;\n\tUINT8 frequency_lsb;\n\tUINT8 bank;\n\tUINT8 mode;\n\tUINT8 start_msb;\n\tUINT8 start_lsb;\n\tUINT8 end_msb;\n\tUINT8 end_lsb;\n\tUINT8 loop_msb;\n\tUINT8 loop_lsb;\n\tUINT8 reserved[4];\n};\n\ntypedef struct\n{\n\tlong\tptoffset;\n\tlong\tpos;\n\tlong\tkey;\n\t//--work\n\tlong\tlastdt;\n\tlong\tprevdt;\n\tlong\tdltdt;\n\t//--reg\n\tlong\trvol;\n\tlong\tlvol;\n\tlong\tfrequency;\n\tlong\tbank;\n\tlong\tmode;\n\n\tlong\tsample_start;\n\tlong\tsample_end;\n\tlong\tsample_loop;\n\tUINT8\tMuted;\n} VOICE;\n\ntypedef struct _c140_state c140_state;\nstruct _c140_state\n{\n\tint sample_rate;\n\t//sound_stream *stream;\n\tint banking_type;\n\t/* internal buffers */\n\tINT16 *mixer_buffer_left;\n\tINT16 *mixer_buffer_right;\n\n\tint baserate;\n\tUINT32 pRomSize;\n\tvoid *pRom;\n\tUINT8 REG[0x200];\n\n\tINT16 pcmtbl[8];\t\t//2000.06.26 CAB\n\n\tVOICE voi[MAX_VOICE];\n};\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\n\n#define MAX_CHIPS\t0x02\nstatic c140_state C140Data[MAX_CHIPS];\n\n/*INLINE c140_state *get_safe_token(device_t *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == C140);\n\treturn (c140_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n\nstatic void init_voice( VOICE *v )\n{\n\tv->key=0;\n\tv->ptoffset=0;\n\tv->rvol=0;\n\tv->lvol=0;\n\tv->frequency=0;\n\tv->bank=0;\n\tv->mode=0;\n\tv->sample_start=0;\n\tv->sample_end=0;\n\tv->sample_loop=0;\n}\n//READ8_DEVICE_HANDLER( c140_r )\nUINT8 c140_r(UINT8 ChipID, offs_t offset)\n{\n\t//c140_state *info = get_safe_token(device);\n\tc140_state *info = &C140Data[ChipID];\n\toffset&=0x1ff;\n\treturn info->REG[offset];\n}\n\n/*\n   find_sample: compute the actual address of a sample given it's\n   address and banking registers, as well as the board type.\n\n   I suspect in \"real life\" this works like the Sega MultiPCM where the banking\n   is done by a small PAL or GAL external to the sound chip, which can be switched\n   per-game or at least per-PCB revision as addressing range needs grow.\n */\nstatic long find_sample(c140_state *info, long adrs, long bank, int voice)\n{\n\tlong newadr = 0;\n\n\tstatic const INT16 asic219banks[4] = { 0x1f7, 0x1f1, 0x1f3, 0x1f5 };\n\n\tadrs=(bank<<16)+adrs;\n\n\tswitch (info->banking_type)\n\t{\n\t\tcase C140_TYPE_SYSTEM2:\n\t\t\t// System 2 banking\n\t\t\tnewadr = ((adrs&0x200000)>>2)|(adrs&0x7ffff);\n\t\t\tbreak;\n\n\t\tcase C140_TYPE_SYSTEM21:\n\t\t\t// System 21 banking.\n\t\t\t// similar to System 2's.\n\t\t\tnewadr = ((adrs&0x300000)>>1)+(adrs&0x7ffff);\n\t\t\tbreak;\n\n\t\t/*case C140_TYPE_SYSTEM21_A:\n\t\t\t// System 21 type A (simple) banking.\n\t\t\t// similar to System 2's.\n\t\t\tnewadr = ((adrs&0x300000)>>1)+(adrs&0x7ffff);\n\t\t\tbreak;\n\n\t\tcase C140_TYPE_SYSTEM21_B:\n\t\t\t// System 21 type B (chip select) banking\n\n\t\t\t// get base address of sample inside the bank\n\t\t\tnewadr = ((adrs&0x100000)>>2) + (adrs&0x3ffff);\n\n\t\t\t// now add the starting bank offsets based on the 2\n\t\t\t// chip select bits.\n\t\t\t// 0x40000 picks individual 512k ROMs\n\t\t\tif (adrs & 0x40000)\n\t\t\t{\n\t\t\t\tnewadr += 0x80000;\n\t\t\t}\n\n\t\t\t// and 0x200000 which group of chips...\n\t\t\tif (adrs & 0x200000)\n\t\t\t{\n\t\t\t\tnewadr += 0x100000;\n\t\t\t}\n\t\t\tbreak;*/\n\n\t\tcase C140_TYPE_ASIC219:\n\t\t\t// ASIC219's banking is fairly simple\n\t\t\tnewadr = ((info->REG[asic219banks[voice/4]]&0x3) * 0x20000) + adrs;\n\t\t\tbreak;\n\t}\n\n\treturn (newadr);\n}\n//WRITE8_DEVICE_HANDLER( c140_w )\nvoid c140_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//c140_state *info = get_safe_token(device);\n\tc140_state *info = &C140Data[ChipID];\n\t//info->stream->update();\n\n\toffset&=0x1ff;\n\n\t// mirror the bank registers on the 219, fixes bkrtmaq (and probably xday2 based on notes in the HLE)\n\tif ((offset >= 0x1f8) && (info->banking_type == C140_TYPE_ASIC219))\n\t{\n\t\toffset -= 8;\n\t}\n\n\tinfo->REG[offset]=data;\n\tif( offset<0x180 )\n\t{\n\t\tVOICE *v = &info->voi[offset>>4];\n\n\t\tif( (offset&0xf)==0x5 )\n\t\t{\n\t\t\tif( data&0x80 )\n\t\t\t{\n\t\t\t\tconst struct voice_registers *vreg = (struct voice_registers *) &info->REG[offset&0x1f0];\n\t\t\t\tv->key=1;\n\t\t\t\tv->ptoffset=0;\n\t\t\t\tv->pos=0;\n\t\t\t\tv->lastdt=0;\n\t\t\t\tv->prevdt=0;\n\t\t\t\tv->dltdt=0;\n\t\t\t\tv->bank = vreg->bank;\n\t\t\t\tv->mode = data;\n\n\t\t\t\t// on the 219 asic, addresses are in words\n\t\t\t\tif (info->banking_type == C140_TYPE_ASIC219)\n\t\t\t\t{\n\t\t\t\t\tv->sample_loop = (vreg->loop_msb*256 + vreg->loop_lsb)*2;\n\t\t\t\t\tv->sample_start = (vreg->start_msb*256 + vreg->start_lsb)*2;\n\t\t\t\t\tv->sample_end = (vreg->end_msb*256 + vreg->end_lsb)*2;\n\n\t\t\t\t\t#if 0\n\t\t\t\t\tlogerror(\"219: play v %d mode %02x start %x loop %x end %x\\n\",\n\t\t\t\t\t\toffset>>4, v->mode,\n\t\t\t\t\t\tfind_sample(info, v->sample_start, v->bank, offset>>4),\n\t\t\t\t\t\tfind_sample(info, v->sample_loop, v->bank, offset>>4),\n\t\t\t\t\t\tfind_sample(info, v->sample_end, v->bank, offset>>4));\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tv->sample_loop = vreg->loop_msb*256 + vreg->loop_lsb;\n\t\t\t\t\tv->sample_start = vreg->start_msb*256 + vreg->start_lsb;\n\t\t\t\t\tv->sample_end = vreg->end_msb*256 + vreg->end_lsb;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tv->key=0;\n\t\t\t}\n\t\t}\n\t}\n}\n\n//void c140_set_base(device_t *device, void *base)\nvoid c140_set_base(UINT8 ChipID, void *base)\n{\n\t//c140_state *info = get_safe_token(device);\n\tc140_state *info = &C140Data[ChipID];\n\tinfo->pRom = base;\n}\n\n/*INLINE int limit(INT32 in)\n{\n\tif(in>0x7fff)\t\treturn 0x7fff;\n\telse if(in<-0x8000)\treturn -0x8000;\n\treturn in;\n}*/\n\n//static STREAM_UPDATE( update_stereo )\nvoid c140_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//c140_state *info = (c140_state *)param;\n\tc140_state *info = &C140Data[ChipID];\n\tint\t\ti,j;\n\n\tINT32\trvol,lvol;\n\tINT32\tdt;\n\tINT32\tsdt;\n\tINT32\tst,ed,sz;\n\n\tINT8\t*pSampleData;\n\tINT32\tfrequency,delta,offset,pos;\n\tINT32\tcnt, voicecnt;\n\tINT32\tlastdt,prevdt,dltdt;\n\tfloat\tpbase=(float)info->baserate*2.0f / (float)info->sample_rate;\n\n\tINT16\t*lmix, *rmix;\n\n\tif(samples>info->sample_rate) samples=info->sample_rate;\n\n\t/* zap the contents of the mixer buffer */\n\tmemset(info->mixer_buffer_left, 0, samples * sizeof(INT16));\n\tmemset(info->mixer_buffer_right, 0, samples * sizeof(INT16));\n\tif (info->pRom == NULL)\n\t\treturn;\n\n\t/* get the number of voices to update */\n\tvoicecnt = (info->banking_type == C140_TYPE_ASIC219) ? 16 : 24;\n\n\t//--- audio update\n\tfor( i=0;i<voicecnt;i++ )\n\t{\n\t\tVOICE *v = &info->voi[i];\n\t\tconst struct voice_registers *vreg = (struct voice_registers *)&info->REG[i*16];\n\n\t\tif( v->key && ! v->Muted)\n\t\t{\n\t\t\tfrequency= vreg->frequency_msb*256 + vreg->frequency_lsb;\n\n\t\t\t/* Abort voice if no frequency value set */\n\t\t\tif(frequency==0) continue;\n\n\t\t\t/* Delta =  frequency * ((8MHz/374)*2 / sample rate) */\n\t\t\tdelta=(long)((float)frequency * pbase);\n\n\t\t\t/* Calculate left/right channel volumes */\n\t\t\tlvol=(vreg->volume_left*32)/MAX_VOICE; //32ch -> 24ch\n\t\t\trvol=(vreg->volume_right*32)/MAX_VOICE;\n\n\t\t\t/* Set mixer outputs base pointers */\n\t\t\tlmix = info->mixer_buffer_left;\n\t\t\trmix = info->mixer_buffer_right;\n\n\t\t\t/* Retrieve sample start/end and calculate size */\n\t\t\tst=v->sample_start;\n\t\t\ted=v->sample_end;\n\t\t\tsz=ed-st;\n\n\t\t\t/* Retrieve base pointer to the sample data */\n\t\t\t//pSampleData=(signed char*)((FPTR)info->pRom + find_sample(info, st, v->bank, i));\n\t\t\tpSampleData = (INT8*)info->pRom + find_sample(info, st, v->bank, i);\n\n\t\t\t/* Fetch back previous data pointers */\n\t\t\toffset=v->ptoffset;\n\t\t\tpos=v->pos;\n\t\t\tlastdt=v->lastdt;\n\t\t\tprevdt=v->prevdt;\n\t\t\tdltdt=v->dltdt;\n\n\t\t\t/* Switch on data type - compressed PCM is only for C140 */\n\t\t\tif ((v->mode&8) && (info->banking_type != C140_TYPE_ASIC219))\n\t\t\t{\n\t\t\t\t//compressed PCM (maybe correct...)\n\t\t\t\t/* Loop for enough to fill sample buffer as requested */\n\t\t\t\tfor(j=0;j<samples;j++)\n\t\t\t\t{\n\t\t\t\t\toffset += delta;\n\t\t\t\t\tcnt = (offset>>16)&0x7fff;\n\t\t\t\t\toffset &= 0xffff;\n\t\t\t\t\tpos+=cnt;\n\t\t\t\t\t//for(;cnt>0;cnt--)\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Check for the end of the sample */\n\t\t\t\t\t\tif(pos >= sz)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t/* Check if its a looping sample, either stop or loop */\n\t\t\t\t\t\t\tif(v->mode&0x10)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tpos = (v->sample_loop - st);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tv->key=0;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/* Read the chosen sample byte */\n\t\t\t\t\t\tdt=pSampleData[pos];\n\n\t\t\t\t\t\t/* decompress to 13bit range */\t\t//2000.06.26 CAB\n\t\t\t\t\t\tsdt=dt>>3;\t\t\t\t//signed\n\t\t\t\t\t\tif(sdt<0)\tsdt = (sdt<<(dt&7)) - info->pcmtbl[dt&7];\n\t\t\t\t\t\telse\t\tsdt = (sdt<<(dt&7)) + info->pcmtbl[dt&7];\n\n\t\t\t\t\t\tprevdt=lastdt;\n\t\t\t\t\t\tlastdt=sdt;\n\t\t\t\t\t\tdltdt=(lastdt - prevdt);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Caclulate the sample value */\n\t\t\t\t\tdt=((dltdt*offset)>>16)+prevdt;\n\n\t\t\t\t\t/* Write the data to the sample buffers */\n\t\t\t\t\t*lmix++ +=(dt*lvol)>>(5+5);\n\t\t\t\t\t*rmix++ +=(dt*rvol)>>(5+5);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* linear 8bit signed PCM */\n\t\t\t\tfor(j=0;j<samples;j++)\n\t\t\t\t{\n\t\t\t\t\toffset += delta;\n\t\t\t\t\tcnt = (offset>>16)&0x7fff;\n\t\t\t\t\toffset &= 0xffff;\n\t\t\t\t\tpos += cnt;\n\t\t\t\t\t/* Check for the end of the sample */\n\t\t\t\t\tif(pos >= sz)\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Check if its a looping sample, either stop or loop */\n\t\t\t\t\t\tif( v->mode&0x10 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpos = (v->sample_loop - st);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tv->key=0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif( cnt )\n\t\t\t\t\t{\n\t\t\t\t\t\tprevdt=lastdt;\n\n\t\t\t\t\t\tif (info->banking_type == C140_TYPE_ASIC219)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//lastdt = pSampleData[BYTE_XOR_BE(pos)];\n\t\t\t\t\t\t\tlastdt = pSampleData[pos ^ 0x01];\n\n\t\t\t\t\t\t\t// Sign + magnitude format\n\t\t\t\t\t\t\tif ((v->mode & 0x01) && (lastdt & 0x80))\n\t\t\t\t\t\t\t\tlastdt = -(lastdt & 0x7f);\n\n\t\t\t\t\t\t\t// Sign flip\n\t\t\t\t\t\t\tif (v->mode & 0x40)\n\t\t\t\t\t\t\t\tlastdt = -lastdt;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlastdt=pSampleData[pos];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdltdt = (lastdt - prevdt);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Caclulate the sample value */\n\t\t\t\t\tdt=((dltdt*offset)>>16)+prevdt;\n\n\t\t\t\t\t/* Write the data to the sample buffers */\n\t\t\t\t\t*lmix++ +=(dt*lvol)>>5;\n\t\t\t\t\t*rmix++ +=(dt*rvol)>>5;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Save positional data for next callback */\n\t\t\tv->ptoffset=offset;\n\t\t\tv->pos=pos;\n\t\t\tv->lastdt=lastdt;\n\t\t\tv->prevdt=prevdt;\n\t\t\tv->dltdt=dltdt;\n\t\t}\n\t}\n\n\t/* render to MAME's stream buffer */\n\tlmix = info->mixer_buffer_left;\n\trmix = info->mixer_buffer_right;\n\t{\n\t\tstream_sample_t *dest1 = outputs[0];\n\t\tstream_sample_t *dest2 = outputs[1];\n\t\tfor (i = 0; i < samples; i++)\n\t\t{\n\t\t\t//*dest1++ = limit(8*(*lmix++));\n\t\t\t//*dest2++ = limit(8*(*rmix++));\n\t\t\t*dest1++ = 8 * (*lmix ++);\n\t\t\t*dest2++ = 8 * (*rmix ++);\n\t\t}\n\t}\n}\n\n//static DEVICE_START( c140 )\nint device_start_c140(UINT8 ChipID, int clock, int banking_type)\n{\n\t//const c140_interface *intf = (const c140_interface *)device->static_config();\n\t//c140_state *info = get_safe_token(device);\n\tc140_state *info;\n\tint i;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &C140Data[ChipID];\n\t\n\t//info->sample_rate=info->baserate=device->clock();\n\tif (clock < 1000000)\n\t\tinfo->baserate = clock;\n\telse\n\t\tinfo->baserate = clock / 384;\t// based on MAME's notes on Namco System II\n\tinfo->sample_rate = info->baserate;\n\tif (((CHIP_SAMPLING_MODE & 0x01) && info->sample_rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\tinfo->sample_rate = CHIP_SAMPLE_RATE;\n\tif (info->sample_rate >= 0x1000000)\t// limit to 16 MHz sample rate (32 MB buffer)\n\t\treturn 0;\n\n\t//info->banking_type = intf->banking_type;\n\tinfo->banking_type = banking_type;\n\n\t//info->stream = device->machine().sound().stream_alloc(*device,0,2,info->sample_rate,info,update_stereo);\n\n\t//info->pRom=*device->region();\n\tinfo->pRomSize = 0x00;\n\tinfo->pRom = NULL;\n\n\t/* make decompress pcm table */\t\t//2000.06.26 CAB\n\t{\n\t\tINT32 segbase=0;\n\t\tfor(i=0;i<8;i++)\n\t\t{\n\t\t\tinfo->pcmtbl[i]=segbase;\t//segment base value\n\t\t\tsegbase += 16<<i;\n\t\t}\n\t}\n\n\t// done at device_reset\n\t/*memset(info->REG,0,sizeof(info->REG));\n\t{\n\t\tint i;\n\t\tfor(i=0;i<MAX_VOICE;i++) init_voice( &info->voi[i] );\n\t}*/\n\n\t/* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */\n\t//info->mixer_buffer_left = auto_alloc_array(device->machine(), INT16, 2 * info->sample_rate);\n\tinfo->mixer_buffer_left = (INT16*)malloc(sizeof(INT16) * 2 * info->sample_rate);\n\tinfo->mixer_buffer_right = info->mixer_buffer_left + info->sample_rate;\n\t\n\tfor (i = 0; i < MAX_VOICE; i ++)\n\t\tinfo->voi[i].Muted = 0x00;\n\t\n\treturn info->sample_rate;\n}\n\nvoid device_stop_c140(UINT8 ChipID)\n{\n\tc140_state *info = &C140Data[ChipID];\n\t\n\tfree(info->pRom);\tinfo->pRom = NULL;\n\tfree(info->mixer_buffer_left);\n\t\n\treturn;\n}\n\nvoid device_reset_c140(UINT8 ChipID)\n{\n\tc140_state *info = &C140Data[ChipID];\n\tint i;\n\t\n\tmemset(info->REG, 0, sizeof(info->REG));\n\t\n\tfor(i = 0; i < MAX_VOICE; i ++)\n\t\tinit_voice( &info->voi[i] );\n\t\n\treturn;\n}\n\nvoid c140_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\tconst UINT8* ROMData)\n{\n\tc140_state *info = &C140Data[ChipID];\n\t\n\tif (info->pRomSize != ROMSize)\n\t{\n\t\tinfo->pRom = (UINT8*)realloc(info->pRom, ROMSize);\n\t\tinfo->pRomSize = ROMSize;\n\t\tmemset(info->pRom, 0xFF, ROMSize);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy((INT8*)info->pRom + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\n\nvoid c140_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tc140_state *info = &C140Data[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < MAX_VOICE; CurChn ++)\n\t\tinfo->voi[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( c140 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers --- //\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(c140_state);\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions --- //\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( c140 );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// nothing //\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// nothing //\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings --- //\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"C140\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Namco PCM\");\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}\n\n\nDEFINE_LEGACY_SOUND_DEVICE(C140, c140);*/\n"
  },
  {
    "path": "VGMPlay/chips/c140.h",
    "content": "/* C140.h */\n\n#pragma once\n\nvoid c140_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_c140(UINT8 ChipID, int clock, int banking_type);\nvoid device_stop_c140(UINT8 ChipID);\nvoid device_reset_c140(UINT8 ChipID);\n\n//READ8_DEVICE_HANDLER( c140_r );\n//WRITE8_DEVICE_HANDLER( c140_w );\nUINT8 c140_r(UINT8 ChipID, offs_t offset);\nvoid c140_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\n//void c140_set_base(device_t *device, void *base);\nvoid c140_set_base(UINT8 ChipID, void *base);\n\nenum\n{\n\tC140_TYPE_SYSTEM2,\n\tC140_TYPE_SYSTEM21,\n\tC140_TYPE_ASIC219\n};\n\n/*typedef struct _c140_interface c140_interface;\nstruct _c140_interface {\n    int banking_type;\n};*/\n\n\nvoid c140_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\tconst UINT8* ROMData);\n\nvoid c140_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n//DECLARE_LEGACY_SOUND_DEVICE(C140, c140);\n"
  },
  {
    "path": "VGMPlay/chips/c352.c",
    "content": "// license:BSD-3-Clause\n// copyright-holders:R. Belmont, superctr\n/*\n    c352.c - Namco C352 custom PCM chip emulation\n    v2.0\n    By R. Belmont\n    Rewritten and improved by superctr\n    Additional code by cync and the hoot development team\n\n    Thanks to Cap of VivaNonno for info and The_Author for preliminary reverse-engineering\n\n    Chip specs:\n    32 voices\n    Supports 8-bit linear and 8-bit muLaw samples\n    Output: digital, 16 bit, 4 channels\n    Output sample rate is the input clock / (288 * 2).\n */\n\n//#include \"emu.h\"\n//#include \"streams.h\"\n#include <math.h>\n#include <stdlib.h>\n#include <string.h> // for memset\n#include <stddef.h> // for NULL\n#include \"mamedef.h\"\n#include \"c352.h\"\n\n#define C352_VOICES 32\nenum {\n    C352_FLG_BUSY       = 0x8000,   // channel is busy\n    C352_FLG_KEYON      = 0x4000,   // Keyon\n    C352_FLG_KEYOFF     = 0x2000,   // Keyoff\n    C352_FLG_LOOPTRG    = 0x1000,   // Loop Trigger\n    C352_FLG_LOOPHIST   = 0x0800,   // Loop History\n    C352_FLG_FM         = 0x0400,   // Frequency Modulation\n    C352_FLG_PHASERL    = 0x0200,   // Rear Left invert phase 180 degrees\n    C352_FLG_PHASEFL    = 0x0100,   // Front Left invert phase 180 degrees\n    C352_FLG_PHASEFR    = 0x0080,   // invert phase 180 degrees (e.g. flip sign of sample)\n    C352_FLG_LDIR       = 0x0040,   // loop direction\n    C352_FLG_LINK       = 0x0020,   // \"long-format\" sample (can't loop, not sure what else it means)\n    C352_FLG_NOISE      = 0x0010,   // play noise instead of sample\n    C352_FLG_MULAW      = 0x0008,   // sample is mulaw instead of linear 8-bit PCM\n    C352_FLG_FILTER     = 0x0004,   // don't apply filter\n    C352_FLG_REVLOOP    = 0x0003,   // loop backwards\n    C352_FLG_LOOP       = 0x0002,   // loop forward\n    C352_FLG_REVERSE    = 0x0001    // play sample backwards\n};\n\ntypedef struct {\n\n    UINT32 pos;\n    UINT32 counter;\n\n    INT16 sample;\n    INT16 last_sample;\n\n    UINT16 vol_f;\n    UINT16 vol_r;\n    UINT8 curr_vol[4];\n    UINT16 freq;\n    UINT16 flags;\n\n    UINT16 wave_bank;\n    UINT16 wave_start;\n    UINT16 wave_end;\n    UINT16 wave_loop;\n\n    UINT8 mute;\n\n} C352_Voice;\n\ntypedef struct {\n\n    UINT32 sample_rate_base;\n    UINT16 divider;\n\n    C352_Voice v[C352_VOICES];\n\n    UINT16 random;\n    UINT16 control; // control flags, purpose unknown.\n\n    UINT8* wave;\n    UINT32 wavesize;\n    UINT32 wave_mask;\n\n    UINT8 muteRear;     // flag from VGM header\n    //UINT8 optMuteRear;  // option\n    \n    UINT16 mulaw_table[256];\n\n} C352;\n\n\n#define MAX_CHIPS   0x02\nstatic C352 C352Data[MAX_CHIPS];\n\nstatic UINT8 MuteAllRear = 0x00;\n\n\nstatic void C352_fetch_sample(C352 *c, C352_Voice *v)\n{\n    v->last_sample = v->sample;\n    \n    if(v->flags & C352_FLG_NOISE)\n    {\n        c->random = (c->random>>1) ^ ((-(c->random&1)) & 0xfff6);\n        v->sample = c->random;\n    }\n    else\n    {\n        INT8 s;\n        UINT16 pos;\n\n        s = (INT8)c->wave[v->pos & c->wave_mask];\n\n        v->sample = s<<8;\n        if(v->flags & C352_FLG_MULAW)\n        {\n            v->sample = c->mulaw_table[s&0xff];\n        }\n        \n        pos = v->pos&0xffff;\n        \n        if((v->flags & C352_FLG_LOOP) && v->flags & C352_FLG_REVERSE)\n        {\n            // backwards>forwards\n            if((v->flags & C352_FLG_LDIR) && pos == v->wave_loop)\n                v->flags &= ~C352_FLG_LDIR;\n            // forwards>backwards\n            else if(!(v->flags & C352_FLG_LDIR) && pos == v->wave_end)\n                v->flags |= C352_FLG_LDIR;\n            \n            v->pos += (v->flags&C352_FLG_LDIR) ? -1 : 1;\n        }\n        else if(pos == v->wave_end)\n        {\n            if((v->flags & C352_FLG_LINK) && (v->flags & C352_FLG_LOOP))\n            {\n                v->pos = (v->wave_start<<16) | v->wave_loop;\n                v->flags |= C352_FLG_LOOPHIST;\n            }\n            else if(v->flags & C352_FLG_LOOP)\n            {\n                v->pos = (v->pos&0xff0000) | v->wave_loop;\n                v->flags |= C352_FLG_LOOPHIST;\n            }\n            else\n            {\n                v->flags |= C352_FLG_KEYOFF;\n                v->flags &= ~C352_FLG_BUSY;\n                v->sample=0;\n            }\n        }\n        else\n        {\n            v->pos += (v->flags&C352_FLG_REVERSE) ? -1 : 1;\n        }\n    }\n}\n\nstatic void c352_ramp_volume(C352_Voice* v,int ch,UINT8 val)\n{\n    INT16 vol_delta = v->curr_vol[ch] - val;\n    if(vol_delta != 0)\n        v->curr_vol[ch] += (vol_delta>0) ? -1 : 1;\n}\n\nvoid c352_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n    C352 *c = &C352Data[ChipID];\n    int i, j;\n    INT16 s;\n    INT32 next_counter;\n    C352_Voice* v;\n\n    stream_sample_t out[4];\n\n    memset(outputs[0], 0, samples * sizeof(stream_sample_t));\n    memset(outputs[1], 0, samples * sizeof(stream_sample_t));\n\n    for(i=0;i<samples;i++)\n    {\n        out[0]=out[1]=out[2]=out[3]=0;\n\n        for(j=0;j<C352_VOICES;j++)\n        {\n\n            v = &c->v[j];\n            s = 0;\n\n            if(v->flags & C352_FLG_BUSY)\n            {\n                next_counter = v->counter+v->freq;\n\n                if(next_counter & 0x10000)\n                {\n                    C352_fetch_sample(c,v);\n                }\n\n                if((next_counter^v->counter) & 0x18000)\n                {\n                    c352_ramp_volume(v,0,v->vol_f>>8);\n                    c352_ramp_volume(v,1,v->vol_f&0xff);\n                    c352_ramp_volume(v,2,v->vol_r>>8);\n                    c352_ramp_volume(v,3,v->vol_r&0xff);\n                }\n\n                v->counter = next_counter&0xffff;\n\n                s = v->sample;\n\n                // Interpolate samples\n                if((v->flags & C352_FLG_FILTER) == 0)\n                    s = v->last_sample + (v->counter*(v->sample-v->last_sample)>>16);\n            }\n\n            if(!c->v[j].mute)\n            {\n                // Left\n                out[0] += (((v->flags & C352_FLG_PHASEFL) ? -s : s) * v->curr_vol[0])>>8;\n                out[2] += (((v->flags & C352_FLG_PHASERL) ? -s : s) * v->curr_vol[2])>>8;\n\n                // Right\n                out[1] += (((v->flags & C352_FLG_PHASEFR) ? -s : s) * v->curr_vol[1])>>8;\n                out[3] += (((v->flags & C352_FLG_PHASEFR) ? -s : s) * v->curr_vol[3])>>8;\n            }\n        }\n\n        outputs[0][i] += out[0];\n        outputs[1][i] += out[1];\n        if (!c->muteRear && !MuteAllRear)\n        {\n            outputs[0][i] += out[2];\n            outputs[1][i] += out[3];\n        }\n    }\n}\n\nint device_start_c352(UINT8 ChipID, int clock, int clkdiv)\n{\n    C352 *c;\n    int i,j;\n\n    if (ChipID >= MAX_CHIPS)\n        return 0;\n\n    c = &C352Data[ChipID];\n\n    c->wave = NULL;\n    c->wavesize = 0x00;\n\n    c->divider = clkdiv ? clkdiv : 288;\n    c->sample_rate_base = (clock&0x7FFFFFFF) / c->divider;\n    c->muteRear = (clock&0x80000000)>>31;\n\n    memset(c->v,0,sizeof(C352_Voice)*C352_VOICES);\n\n    c352_set_mute_mask(ChipID, 0x00000000);\n    \n    j=0;\n    for(i=0;i<128;i++)\n    {\n        c->mulaw_table[i] = j<<5;\n        if(i < 16)\n            j += 1;\n        else if(i < 24)\n            j += 2;\n        else if(i < 48)\n            j += 4;\n        else if(i < 100)\n            j += 8;\n        else\n            j += 16;\n    }\n    for(i=128;i<256;i++)\n        c->mulaw_table[i] = (~c->mulaw_table[i-128])&0xffe0;\n\n    return c->sample_rate_base;\n}\n\nvoid device_stop_c352(UINT8 ChipID)\n{\n    C352 *c = &C352Data[ChipID];\n    \n    free(c->wave);\n    c->wave = NULL;\n    \n    return;\n}\n\nvoid device_reset_c352(UINT8 ChipID)\n{\n    C352 *c = &C352Data[ChipID];\n    UINT32 muteMask;\n    \n    muteMask = c352_get_mute_mask(ChipID);\n    \n    // clear all channels states\n    memset(c->v,0,sizeof(C352_Voice)*C352_VOICES);\n    \n    // init noise generator\n    c->random = 0x1234;\n    c->control = 0;\n    \n    c352_set_mute_mask(ChipID, muteMask);\n    \n    return;\n}\n\nstatic UINT16 C352RegMap[8] = {\n    offsetof(C352_Voice,vol_f) / sizeof(UINT16),\n    offsetof(C352_Voice,vol_r) / sizeof(UINT16),\n    offsetof(C352_Voice,freq) / sizeof(UINT16),\n    offsetof(C352_Voice,flags) / sizeof(UINT16),\n    offsetof(C352_Voice,wave_bank) / sizeof(UINT16),\n    offsetof(C352_Voice,wave_start) / sizeof(UINT16),\n    offsetof(C352_Voice,wave_end) / sizeof(UINT16),\n    offsetof(C352_Voice,wave_loop) / sizeof(UINT16),\n};\n\nUINT16 c352_r(UINT8 ChipID, offs_t address)\n{\n    C352 *c = &C352Data[ChipID];\n\n    if(address < 0x100)\n        return *((UINT16*)&c->v[address/8]+C352RegMap[address%8]);\n    else if(address == 0x200)\n        return c->control;\n    else\n        return 0;\n}\n\nvoid c352_w(UINT8 ChipID, offs_t address, UINT16 val)\n{\n    C352 *c = &C352Data[ChipID];\n    \n    int i;\n    \n    if(address < 0x100) // Channel registers, see map above.\n    {\n        *((UINT16*)&c->v[address/8]+C352RegMap[address%8]) = val;\n    }\n    else if(address == 0x200)\n    {\n        c->control = val;\n        //logerror(\"C352 control register write: %04x\\n\",val);\n    }\n    else if(address == 0x202) // execute keyons/keyoffs\n    {\n        for(i=0;i<C352_VOICES;i++)\n        {\n            if((c->v[i].flags & C352_FLG_KEYON))\n            {\n                c->v[i].pos = (c->v[i].wave_bank<<16) | c->v[i].wave_start;\n\n                c->v[i].sample = 0;\n                c->v[i].last_sample = 0;\n                c->v[i].counter = 0xffff;\n\n                c->v[i].flags |= C352_FLG_BUSY;\n                c->v[i].flags &= ~(C352_FLG_KEYON|C352_FLG_LOOPHIST);\n\n                c->v[i].curr_vol[0] = c->v[i].curr_vol[1] = 0;\n                c->v[i].curr_vol[2] = c->v[i].curr_vol[3] = 0;\n            }\n            else if(c->v[i].flags & C352_FLG_KEYOFF)\n            {\n                c->v[i].flags &= ~(C352_FLG_BUSY|C352_FLG_KEYOFF);\n                c->v[i].counter = 0xffff;\n            }\n        }\n    }\n}\n\n\nvoid c352_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n                    const UINT8* ROMData)\n{\n    C352 *c = &C352Data[ChipID];\n    \n    if (c->wavesize != ROMSize)\n    {\n        c->wave = (UINT8*)realloc(c->wave, ROMSize);\n        c->wavesize = ROMSize;\n        for (c->wave_mask = 1; c->wave_mask < c->wavesize; c->wave_mask <<= 1)\n            ;\n        c->wave_mask --;\n        memset(c->wave, 0xFF, ROMSize);\n    }\n    if (DataStart > ROMSize)\n        return;\n    if (DataStart + DataLength > ROMSize)\n        DataLength = ROMSize - DataStart;\n    \n    memcpy(c->wave + DataStart, ROMData, DataLength);\n    \n    return;\n}\n\nvoid c352_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n    C352 *c = &C352Data[ChipID];\n    UINT8 CurChn;\n    \n    for (CurChn = 0; CurChn < C352_VOICES; CurChn ++)\n        c->v[CurChn].mute = (MuteMask >> CurChn) & 0x01;\n    \n    return;\n}\n\nUINT32 c352_get_mute_mask(UINT8 ChipID)\n{\n    C352 *c = &C352Data[ChipID];\n    UINT32 muteMask;\n    UINT8 CurChn;\n    \n    muteMask = 0x00000000;\n    for (CurChn = 0; CurChn < C352_VOICES; CurChn ++)\n        muteMask |= (c->v[CurChn].mute << CurChn);\n    \n    return muteMask;\n}\n\nvoid c352_set_options(UINT8 Flags)\n{\n    MuteAllRear = (Flags & 0x01) >> 0;\n    \n    return;\n}\n"
  },
  {
    "path": "VGMPlay/chips/c352.h",
    "content": "#pragma once\n\n#ifndef __C352_H__\n#define __C352_H__\n\nvoid c352_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_c352(UINT8 ChipID, int clock, int clkdiv);\nvoid device_stop_c352(UINT8 ChipID);\nvoid device_reset_c352(UINT8 ChipID);\n\nUINT16 c352_r(UINT8 ChipID, offs_t offset);\nvoid c352_w(UINT8 ChipID, offs_t offset, UINT16 data);\n\nvoid c352_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\tconst UINT8* ROMData);\n\nvoid c352_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\nUINT32 c352_get_mute_mask(UINT8 ChipID);\nvoid c352_set_options(UINT8 Flags);\n\n#endif /* __C352_H__ */\n"
  },
  {
    "path": "VGMPlay/chips/c6280.c",
    "content": "/*\n    HuC6280 sound chip emulator\n    by Charles MacDonald\n    E-mail: cgfm2@hotmail.com\n    WWW: http://cgfm2.emuviews.com\n\n    Thanks to:\n\n    - Paul Clifford for his PSG documentation.\n    - Richard Bannister for the TGEmu-specific sound updating code.\n    - http://www.uspto.gov for the PSG patents.\n    - All contributors to the tghack-list.\n\n    Changes:\n\n    (03/30/2003)\n    - Removed TGEmu specific code and added support functions for MAME.\n    - Modified setup code to handle multiple chips with different clock and\n      volume settings.\n\n    Missing features / things to do:\n\n    - Add LFO support. But do any games actually use it?\n\n    - Add shared index for waveform playback and sample writes. Almost every\n      game will reset the index prior to playback so this isn't an issue.\n\n    - While the noise emulation is complete, the data for the pseudo-random\n      bitstream is calculated by machine.rand() and is not a representation of what\n      the actual hardware does.\n\n    For some background on Hudson Soft's C62 chipset:\n\n    - http://www.hudsonsoft.net/ww/about/about.html\n    - http://www.hudson.co.jp/corp/eng/coinfo/history.html\n\n    Legal information:\n\n    Copyright Charles MacDonald\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n*/\n\n//#include \"emu.h\"\n#include <stdlib.h>\t// for rand\n#include <string.h>\t// for memset\n#include <math.h>\t// for pow\n#include \"mamedef.h\"\n#include \"c6280.h\"\n\ntypedef struct {\n    UINT16 frequency;\n    UINT8 control;\n    UINT8 balance;\n    UINT8 waveform[32];\n    UINT8 index;\n    INT16 dda;\n    UINT8 noise_control;\n    UINT32 noise_counter;\n    UINT32 counter;\n\tUINT8 Muted;\n} t_channel;\n\ntypedef struct {\n\t//sound_stream *stream;\n\t//device_t *device;\n\t//device_t *cpudevice;\n    UINT8 select;\n    UINT8 balance;\n    UINT8 lfo_frequency;\n    UINT8 lfo_control;\n    t_channel channel[8];\t// is 8, because: p->select = data & 0x07;\n    INT16 volume_table[32];\n    UINT32 noise_freq_tab[32];\n    UINT32 wave_freq_tab[4096];\n} c6280_t;\n\n/*INLINE c6280_t *get_safe_token(device_t *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == C6280);\n\treturn (c6280_t *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n\n/* only needed for io_buffer */\n//#include \"cpu/h6280/h6280.h\"\n\n\nstatic void c6280_init(/*device_t *device,*/ c6280_t *p, double clk, double rate)\n{\n\t//const c6280_interface *intf = (const c6280_interface *)device->static_config();\n    int i;\n    double step;\n\n    /* Loudest volume level for table */\n    //double level = 65535.0 / 6.0 / 32.0;\n\tdouble level = 65536.0 / 6.0 / 32.0;\n\n    /* Clear context */\n    memset(p, 0, sizeof(c6280_t));\n\n    //p->device = device;\n    //p->cpudevice = device->machine().device(intf->cpu);\n    //if (p->cpudevice == NULL)\n    //\tfatalerror(\"c6280_init: no CPU found with tag of '%s'\\n\", device->tag());\n\n    /* Make waveform frequency table */\n    for(i = 0; i < 4096; i += 1)\n    {\n        step = ((clk / rate) * 4096) / (i+1);\n        p->wave_freq_tab[(1 + i) & 0xFFF] = (UINT32)step;\n    }\n\n    /* Make noise frequency table */\n    for(i = 0; i < 32; i += 1)\n    {\n        step = ((clk / rate) * 32) / (i+1);\n        p->noise_freq_tab[i] = (UINT32)step;\n    }\n\n    /* Make volume table */\n    /* PSG has 48dB volume range spread over 32 steps */\n    step = 48.0 / 32.0;\n    for(i = 0; i < 31; i++)\n    {\n        p->volume_table[i] = (UINT16)level;\n        level /= pow(10.0, step / 20.0);\n    }\n    p->volume_table[31] = 0;\n}\n\n\nstatic void c6280_write(c6280_t *p, int offset, int data)\n{\n    t_channel *q = &p->channel[p->select];\n\n    /* Update stream */\n    //p->stream->update();\n\n    switch(offset & 0x0F)\n    {\n        case 0x00: /* Channel select */\n            p->select = data & 0x07;\n            break;\n\n        case 0x01: /* Global balance */\n            p->balance  = data;\n            break;\n\n        case 0x02: /* Channel frequency (LSB) */\n            q->frequency = (q->frequency & 0x0F00) | data;\n            q->frequency &= 0x0FFF;\n            break;\n\n        case 0x03: /* Channel frequency (MSB) */\n            q->frequency = (q->frequency & 0x00FF) | (data << 8);\n            q->frequency &= 0x0FFF;\n            break;\n\n        case 0x04: /* Channel control (key-on, DDA mode, volume) */\n\n            /* 1-to-0 transition of DDA bit resets waveform index */\n            if((q->control & 0x40) && ((data & 0x40) == 0))\n            {\n                q->index = 0;\n            }\n            q->control = data;\n            break;\n\n        case 0x05: /* Channel balance */\n            q->balance = data;\n            break;\n\n        case 0x06: /* Channel waveform data */\n\n            switch(q->control & 0xC0)\n            {\n                case 0x00:\n                    q->waveform[q->index & 0x1F] = data & 0x1F;\n                    q->index = (q->index + 1) & 0x1F;\n                    break;\n\n                case 0x40:\n                    break;\n\n                case 0x80:\n                    q->waveform[q->index & 0x1F] = data & 0x1F;\n                    q->index = (q->index + 1) & 0x1F;\n                    break;\n\n                case 0xC0:\n                    q->dda = data & 0x1F;\n                    break;\n            }\n\n            break;\n\n        case 0x07: /* Noise control (enable, frequency) */\n            q->noise_control = data;\n            break;\n\n        case 0x08: /* LFO frequency */\n            p->lfo_frequency = data;\n            break;\n\n        case 0x09: /* LFO control (enable, mode) */\n            p->lfo_control = data;\n            break;\n\n        default:\n            break;\n    }\n}\n\n\n//static STREAM_UPDATE( c6280_update )\nvoid c6280m_update(void* param, stream_sample_t **outputs, int samples)\n{\n    static const int scale_tab[] = {\n        0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,\n        0x10, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F\n    };\n    int ch;\n    int i;\n    c6280_t *p = (c6280_t *)param;\n\n    int lmal = (p->balance >> 4) & 0x0F;\n    int rmal = (p->balance >> 0) & 0x0F;\n    int vll, vlr;\n\n    lmal = scale_tab[lmal];\n    rmal = scale_tab[rmal];\n\n    /* Clear buffer */\n    for(i = 0; i < samples; i++)\n    {\n        outputs[0][i] = 0;\n        outputs[1][i] = 0;\n    }\n\n    for(ch = 0; ch < 6; ch++)\n    {\n        /* Only look at enabled channels */\n        if((p->channel[ch].control & 0x80) && ! p->channel[ch].Muted)\n        {\n            int lal = (p->channel[ch].balance >> 4) & 0x0F;\n            int ral = (p->channel[ch].balance >> 0) & 0x0F;\n            int al  = p->channel[ch].control & 0x1F;\n\n            lal = scale_tab[lal];\n            ral = scale_tab[ral];\n\n            /* Calculate volume just as the patent says */\n            vll = (0x1F - lal) + (0x1F - al) + (0x1F - lmal);\n            if(vll > 0x1F) vll = 0x1F;\n\n            vlr = (0x1F - ral) + (0x1F - al) + (0x1F - rmal);\n            if(vlr > 0x1F) vlr = 0x1F;\n\n            vll = p->volume_table[vll];\n            vlr = p->volume_table[vlr];\n\n            /* Check channel mode */\n            if((ch >= 4) && (p->channel[ch].noise_control & 0x80))\n            {\n                /* Noise mode */\n                UINT32 step = p->noise_freq_tab[(p->channel[ch].noise_control & 0x1F) ^ 0x1F];\n                for(i = 0; i < samples; i += 1)\n                {\n                    static int data = 0;\n                    p->channel[ch].noise_counter += step;\n                    if(p->channel[ch].noise_counter >= 0x800)\n                    {\n                        //data = (p->device->machine().rand() & 1) ? 0x1F : 0;\n\t\t\t\t\t\tdata = (rand() & 1) ? 0x1F : 0;\n                    }\n                    p->channel[ch].noise_counter &= 0x7FF;\n                    outputs[0][i] += (INT16)(vll * (data - 16));\n                    outputs[1][i] += (INT16)(vlr * (data - 16));\n                }\n            }\n            else\n            if(p->channel[ch].control & 0x40)\n            {\n                /* DDA mode */\n                for(i = 0; i < samples; i++)\n                {\n                    outputs[0][i] += (INT16)(vll * (p->channel[ch].dda - 16));\n                    outputs[1][i] += (INT16)(vlr * (p->channel[ch].dda - 16));\n                }\n            }\n            else\n            {\n                /* Waveform mode */\n                UINT32 step = p->wave_freq_tab[p->channel[ch].frequency];\n                for(i = 0; i < samples; i += 1)\n                {\n                    int offset;\n                    INT16 data;\n                    offset = (p->channel[ch].counter >> 12) & 0x1F;\n                    p->channel[ch].counter += step;\n                    p->channel[ch].counter &= 0x1FFFF;\n                    data = p->channel[ch].waveform[offset];\n                    outputs[0][i] += (INT16)(vll * (data - 16));\n                    outputs[1][i] += (INT16)(vlr * (data - 16));\n                }\n            }\n        }\n    }\n}\n\n\n/*--------------------------------------------------------------------------*/\n/* MAME specific code                                                       */\n/*--------------------------------------------------------------------------*/\n\n//static DEVICE_START( c6280 )\nvoid* device_start_c6280m(int clock, int rate)\n{\n    //int rate = device->clock()/16;\n    //c6280_t *info = get_safe_token(device);\n\tc6280_t *info;\n\tUINT8 CurChn;\n\n\tinfo = (c6280_t*)malloc(sizeof(c6280_t));\n\tif (info == NULL)\n\t\treturn 0;\n\tmemset(info, 0x00, sizeof(c6280_t));\n\t\n    /* Initialize PSG emulator */\n    //c6280_init(device, info, device->clock(), rate);\n\tc6280_init(info, clock & 0x7FFFFFFF, rate);\n\n    /* Create stereo stream */\n    //info->stream = device->machine().sound().stream_alloc(*device, 0, 2, rate, info, c6280_update);\n\t\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t\tinfo->channel[CurChn].Muted = 0x00;\n\t\n\treturn info;\n}\n\nvoid device_stop_c6280m(void* chip)\n{\n\tc6280_t *info = (c6280_t *)chip;\n\t\n\tfree(info);\n\t\n\treturn;\n}\n\nvoid device_reset_c6280m(void* chip)\n{\n\tc6280_t *info = (c6280_t *)chip;\n\tUINT8 CurChn;\n\tt_channel* TempChn;\n\t\n\tinfo->select = 0x00;\n\tinfo->balance = 0x00;\n\tinfo->lfo_frequency = 0x00;\n\tinfo->lfo_control = 0x00;\n\t\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t{\n\t\tTempChn = &info->channel[CurChn];\n\t\t\n\t\tTempChn->frequency = 0x00;\n\t\tTempChn->control = 0x00;\n\t\tTempChn->balance = 0x00;\n\t\tmemset(TempChn->waveform, 0x00, 0x20);\n\t\tTempChn->index = 0x00;\n\t\tTempChn->dda = 0x00;\n\t\tTempChn->noise_control = 0x00;\n\t\tTempChn->noise_counter = 0x00;\n\t\tTempChn->counter = 0x00;\n\t}\n\t\n\treturn;\n}\n\n//READ8_DEVICE_HANDLER( c6280_r )\nUINT8 c6280m_r(void* chip, offs_t offset)\n{\n    //c6280_t *info = get_safe_token(device);\n\tc6280_t *info = (c6280_t *)chip;\n\t//return h6280io_get_buffer(info->cpudevice);\n\tif (offset == 0)\n\t\treturn info->select;\n\treturn 0;\n}\n\n//WRITE8_DEVICE_HANDLER( c6280_w )\nvoid c6280m_w(void* chip, offs_t offset, UINT8 data)\n{\n    //c6280_t *info = get_safe_token(device);\n\tc6280_t *info = (c6280_t *)chip;\n\t//h6280io_set_buffer(info->cpudevice, data);\n\tc6280_write(info, offset, data);\n}\n\n\nvoid c6280m_set_mute_mask(void* chip, UINT32 MuteMask)\n{\n\tc6280_t *info = (c6280_t *)chip;\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t\tinfo->channel[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( c6280 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(c6280_t);\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( c6280 );\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// nothing //\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// nothing //\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"HuC6280\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"????\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}\n\n\nDEFINE_LEGACY_SOUND_DEVICE(C6280, c6280);*/\n"
  },
  {
    "path": "VGMPlay/chips/c6280.h",
    "content": "#pragma once\n\n//#include \"devlegcy.h\"\n\ntypedef struct _c6280_interface c6280_interface;\nstruct _c6280_interface\n{\n\tconst char *\tcpu;\n};\n\n/* Function prototypes */\n//WRITE8_DEVICE_HANDLER( c6280_w );\n//READ8_DEVICE_HANDLER( c6280_r );\nvoid c6280m_w(void* chip, offs_t offset, UINT8 data);\nUINT8 c6280m_r(void* chip, offs_t offset);\n\nvoid c6280m_update(void* param, stream_sample_t **outputs, int samples);\nvoid* device_start_c6280m(int clock, int rate);\nvoid device_stop_c6280m(void* chip);\nvoid device_reset_c6280m(void* chip);\n\nvoid c6280m_set_mute_mask(void* chip, UINT32 MuteMask);\n\n//DECLARE_LEGACY_SOUND_DEVICE(C6280, c6280);\n"
  },
  {
    "path": "VGMPlay/chips/c6280intf.c",
    "content": "#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n#ifdef ENABLE_ALL_CORES\n#include \"c6280.h\"\n#endif\n#include \"Ootake_PSG.h\"\n\n#ifdef ENABLE_ALL_CORES\n#define EC_MAME\t\t0x01\n#endif\n#define EC_OOTAKE\t0x00\n\ntypedef struct _c6280_state\n{\n\tvoid* chip;\n} c6280_state;\n\nextern UINT32 SampleRate;\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nstatic UINT8 EMU_CORE = 0x00;\n\n#define MAX_CHIPS\t0x02\nstatic c6280_state C6280Data[MAX_CHIPS];\n\nvoid c6280_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tc6280_state* info = &C6280Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tc6280m_update(info->chip, outputs, samples);\n\t\tbreak;\n#endif\n\tcase EC_OOTAKE:\n\t\tPSG_Mix(info->chip, outputs, samples);\n\t\tbreak;\n\t}\n}\n\nint device_start_c6280(UINT8 ChipID, int clock)\n{\n\tc6280_state* info;\n\tint rate = 0;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &C6280Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\trate = (clock & 0x7FFFFFFF)/16;\n\t\tif (((CHIP_SAMPLING_MODE & 0x01) && rate < CHIP_SAMPLE_RATE) ||\n\t\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\t\trate = CHIP_SAMPLE_RATE;\n\t\t\n\t\tinfo->chip = device_start_c6280m(clock, rate);\n\t\tif (info->chip == NULL)\n\t\t\treturn 0;\n\t\tbreak;\n#endif\n\tcase EC_OOTAKE:\n\t\trate = SampleRate;\n\t\tinfo->chip = PSG_Init(clock, rate);\n\t\tif (info->chip == NULL)\n\t\t\treturn 0;\n\t\tbreak;\n\t}\n \n\treturn rate;\n}\n\nvoid device_stop_c6280(UINT8 ChipID)\n{\n\tc6280_state* info = &C6280Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tdevice_stop_c6280m(info->chip);\n\t\tbreak;\n#endif\n\tcase EC_OOTAKE:\n\t\tPSG_Deinit(info->chip);\n\t\tbreak;\n\t}\n\tinfo->chip = NULL;\n\t\n\treturn;\n}\n\nvoid device_reset_c6280(UINT8 ChipID)\n{\n\tc6280_state* info = &C6280Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tdevice_reset_c6280m(info->chip);\n\t\tbreak;\n#endif\n\tcase EC_OOTAKE:\n\t\tPSG_ResetVolumeReg(info->chip);\n\t\tbreak;\n\t}\n\treturn;\n}\n\nUINT8 c6280_r(UINT8 ChipID, offs_t offset)\n{\n\tc6280_state* info = &C6280Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\treturn c6280m_r(info->chip, offset);\n#endif\n\tcase EC_OOTAKE:\n\t\treturn PSG_Read(info->chip, offset);\n\tdefault:\n\t\treturn 0x00;\n\t}\n}\n\nvoid c6280_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tc6280_state* info = &C6280Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tc6280m_w(info->chip, offset, data);\n\t\tbreak;\n#endif\n\tcase EC_OOTAKE:\n\t\tPSG_Write(info->chip, offset, data);\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\n\nvoid c6280_set_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tEMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;\n#else\n\tEMU_CORE = EC_OOTAKE;\n#endif\n\t\n\treturn;\n}\n\nvoid c6280_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tc6280_state* info = &C6280Data[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tc6280m_set_mute_mask(info->chip, MuteMask);\n\t\tbreak;\n#endif\n\tcase EC_OOTAKE:\n\t\tPSG_SetMuteMask(info->chip, MuteMask);\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/c6280intf.h",
    "content": "#pragma once\n\nvoid c6280_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 c6280_r(UINT8 ChipID, offs_t offset);\n\nvoid c6280_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_c6280(UINT8 ChipID, int clock);\nvoid device_stop_c6280(UINT8 ChipID);\nvoid device_reset_c6280(UINT8 ChipID);\n\nvoid c6280_set_emu_core(UINT8 Emulator);\nvoid c6280_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/chips/dac_control.c",
    "content": "// TODO: SCSP and (especially) WonderSwan\n /************************\n  *  DAC Stream Control  *\n  ***********************/\n// (Custom Driver to handle PCM Streams of YM2612 DAC and PWM.)\n//\n// Written on 3 February 2011 by Valley Bell\n// Last Update: 29 September 2017\n//\n// Only for usage in non-commercial, VGM file related software.\n\n/* How it basically works:\n\n1. send command X with data Y at frequency F to chip C\n2. do that until you receive a STOP command, or until you sent N commands\n\n*/\n\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n#include \"dac_control.h\"\n#include \"c6280intf.h\"\n\n//#include \"../ChipMapper.h\"\nvoid chip_reg_write(UINT8 ChipType, UINT8 ChipID, UINT8 Port, UINT8 Offset, UINT8 Data);\n\nextern UINT32 SampleRate;\n#define DAC_SMPL_RATE\tSampleRate\n\ntypedef struct _dac_control\n{\n\t// Commands sent to dest-chip\n\tUINT8 DstChipType;\n\tUINT8 DstChipID;\n\tUINT16 DstCommand;\n\tUINT8 CmdSize;\n\t\n\tUINT32 Frequency;\t// Frequency (Hz) at which the commands are sent\n\tUINT32 DataLen;\t\t// to protect from reading beyond End Of Data\n\tconst UINT8* Data;\n\tUINT32 DataStart;\t// Position where to start\n\tUINT8 StepSize;\t\t// usually 1, set to 2 for L/R interleaved data\n\tUINT8 StepBase;\t\t// usually 0, set to 0/1 for L/R interleaved data\n\tUINT32 CmdsToSend;\n\t\n\t// Running Bits:\t0 (01) - is playing\n\t//\t\t\t\t\t2 (04) - loop sample (simple loop from start to end)\n\t//\t\t\t\t\t4 (10) - already sent this command\n\t//\t\t\t\t\t7 (80) - disabled\n\tUINT8 Running;\n\tUINT8 Reverse;\n\tUINT32 Step;\t\t// Position in Player SampleRate\n\tUINT32 Pos;\t\t\t// Position in Data SampleRate\n\tUINT32 RemainCmds;\n\tUINT32 RealPos;\t\t// true Position in Data (== Pos, if Reverse is off)\n\tUINT8 DataStep;\t\t// always StepSize * CmdSize\n} dac_control;\n\n#define MAX_CHIPS\t0xFF\nstatic dac_control DACData[MAX_CHIPS];\n\nINLINE void daccontrol_SendCommand(dac_control *chip)\n{\n\tUINT8 Port;\n\tUINT8 Command;\n\tUINT8 Data;\n\tconst UINT8* ChipData;\n\t\n\tif (chip->Running & 0x10)\t// command already sent\n\t\treturn;\n\tif (chip->DataStart + chip->RealPos >= chip->DataLen)\n\t\treturn;\n\t\n\t//if (! chip->Reverse)\n\t\tChipData = chip->Data + (chip->DataStart + chip->RealPos);\n\t//else\n\t//\tChipData = chip->Data + (chip->DataStart + chip->CmdsToSend - 1 - chip->Pos);\n\tswitch(chip->DstChipType)\n\t{\n\t// Support for the important chips\n\tcase 0x02:\t// YM2612 (16-bit Register (actually 9 Bit), 8-bit Data)\n\t\tPort = (chip->DstCommand & 0xFF00) >> 8;\n\t\tCommand = (chip->DstCommand & 0x00FF) >> 0;\n\t\tData = ChipData[0x00];\n\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, Port, Command, Data);\n\t\tbreak;\n\tcase 0x11:\t// PWM (4-bit Register, 12-bit Data)\n\t\tPort = (chip->DstCommand & 0x000F) >> 0;\n\t\tCommand = ChipData[0x01] & 0x0F;\n\t\tData = ChipData[0x00];\n\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, Port, Command, Data);\n\t\tbreak;\n\t// Support for other chips (mainly for completeness)\n\tcase 0x00:\t// SN76496 (4-bit Register, 4-bit/10-bit Data)\n\t\tCommand = (chip->DstCommand & 0x00F0) >> 0;\n\t\tData = ChipData[0x00] & 0x0F;\n\t\tif (Command & 0x10)\n\t\t{\n\t\t\t// Volume Change (4-Bit value)\n\t\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, 0x00, 0x00, Command | Data);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Frequency Write (10-Bit value)\n\t\t\tPort = ((ChipData[0x01] & 0x03) << 4) | ((ChipData[0x00] & 0xF0) >> 4);\n\t\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, 0x00, 0x00, Command | Data);\n\t\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, 0x00, 0x00, Port);\n\t\t}\n\t\tbreak;\n\tcase 0x18:\t// OKIM6295 - TODO: verify\n\t\tCommand = (chip->DstCommand & 0x00FF) >> 0;\n\t\tData = ChipData[0x00];\n\t\t\n\t\tif (! Command)\n\t\t{\n\t\t\tPort = (chip->DstCommand & 0x0F00) >> 8;\n\t\t\tif (Data & 0x80)\n\t\t\t{\n\t\t\t\t// Sample Start\n\t\t\t\t// write sample ID\n\t\t\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, 0x00, Command, Data);\n\t\t\t\t// write channel(s) that should play the sample\n\t\t\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, 0x00, Command, Port << 4);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Sample Stop\n\t\t\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, 0x00, Command, Port << 3);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, 0x00, Command, Data);\n\t\t}\n\t\tbreak;\n\t\t// Generic support: 8-bit Register, 8-bit Data\n\tcase 0x01:\t// YM2413\n\tcase 0x03:\t// YM2151\n\tcase 0x06:\t// YM2203\n\tcase 0x09:\t// YM3812\n\tcase 0x0A:\t// YM3526\n\tcase 0x0B:\t// Y8950\n\tcase 0x0F:\t// YMZ280B\n\tcase 0x12:\t// AY8910\n\tcase 0x13:\t// GameBoy DMG\n\tcase 0x14:\t// NES APU\n//\tcase 0x15:\t// MultiPCM\n\tcase 0x16:\t// UPD7759\n\tcase 0x17:\t// OKIM6258\n\tcase 0x1D:\t// K053260 - TODO: Verify\n\tcase 0x1E:\t// Pokey - TODO: Verify\n\t\tCommand = (chip->DstCommand & 0x00FF) >> 0;\n\t\tData = ChipData[0x00];\n\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, 0x00, Command, Data);\n\t\tbreak;\n\t\t// Generic support: 16-bit Register, 8-bit Data\n\tcase 0x07:\t// YM2608\n\tcase 0x08:\t// YM2610/B\n\tcase 0x0C:\t// YMF262\n\tcase 0x0D:\t// YMF278B\n\tcase 0x0E:\t// YMF271\n\tcase 0x19:\t// K051649 - TODO: Verify\n\tcase 0x1A:\t// K054539 - TODO: Verify\n\tcase 0x1C:\t// C140 - TODO: Verify\n\t\tPort = (chip->DstCommand & 0xFF00) >> 8;\n\t\tCommand = (chip->DstCommand & 0x00FF) >> 0;\n\t\tData = ChipData[0x00];\n\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, Port, Command, Data);\n\t\tbreak;\n\t\t// Generic support: 8-bit Register with Channel Select, 8-bit Data\n\tcase 0x05:\t// RF5C68\n\tcase 0x10:\t// RF5C164\n\tcase 0x1B:\t// HuC6280\n\t\tPort = (chip->DstCommand & 0xFF00) >> 8;\n\t\tCommand = (chip->DstCommand & 0x00FF) >> 0;\n\t\tData = ChipData[0x00];\n\t\t\n\t\tif (Port == 0xFF)\n\t\t{\n\t\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, 0x00, Command & 0x0F, Data);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tUINT8 prevChn;\n\t\t\t\n\t\t\tprevChn = Port;\t// by default don't restore channel\n\t\t\t// get current channel for supported chips\n\t\t\tif (chip->DstChipType == 0x05)\n\t\t\t\t;\t// TODO\n\t\t\telse if (chip->DstChipType == 0x05)\n\t\t\t\t;\t// TODO\n\t\t\telse if (chip->DstChipType == 0x1B)\n\t\t\t\tprevChn = c6280_r(chip->DstChipID, 0x00);\n\t\t\t\n\t\t\t// Send Channel Select\n\t\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, 0x00, Command >> 4, Port);\n\t\t\t// Send Data\n\t\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, 0x00, Command & 0x0F, Data);\n\t\t\t// restore old channel\n\t\t\tif (prevChn != Port)\n\t\t\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, 0x00, Command >> 4, prevChn);\n\t\t}\n\t\tbreak;\n\t\t// Generic support: 8-bit Register, 16-bit Data\n\tcase 0x1F:\t// QSound\n\t\tCommand = (chip->DstCommand & 0x00FF) >> 0;\n\t\tchip_reg_write(chip->DstChipType, chip->DstChipID, ChipData[0x00], ChipData[0x01], Command);\n\t\tbreak;\n\t}\n\tchip->Running |= 0x10;\n\t\n\treturn;\n}\n\nINLINE UINT32 muldiv64round(UINT32 Multiplicand, UINT32 Multiplier, UINT32 Divisor)\n{\n\t// Yes, I'm correctly rounding the values.\n\treturn (UINT32)(((UINT64)Multiplicand * Multiplier + Divisor / 2) / Divisor);\n}\n\nvoid daccontrol_update(UINT8 ChipID, UINT32 samples)\n{\n\tdac_control *chip = &DACData[ChipID];\n\tUINT32 NewPos;\n\tINT16 RealDataStp;\n\t\n\tif (chip->Running & 0x80)\t// disabled\n\t\treturn;\n\tif (! (chip->Running & 0x01))\t// stopped\n\t\treturn;\n\t\n\tif (! chip->Reverse)\n\t\tRealDataStp = chip->DataStep;\n\telse\n\t\tRealDataStp = -chip->DataStep;\n\t\n\tif (samples > 0x20)\n\t{\n\t\t// very effective Speed Hack for fast seeking\n\t\tNewPos = chip->Step + (samples - 0x10);\n\t\tNewPos = muldiv64round(NewPos * chip->DataStep, chip->Frequency, DAC_SMPL_RATE);\n\t\twhile(chip->RemainCmds && chip->Pos < NewPos)\n\t\t{\n\t\t\tchip->Pos += chip->DataStep;\n\t\t\tchip->RealPos += RealDataStp;\n\t\t\tchip->RemainCmds --;\n\t\t}\n\t}\n\t\n\tchip->Step += samples;\n\t// Formula: Step * Freq / SampleRate\n\tNewPos = muldiv64round(chip->Step * chip->DataStep, chip->Frequency, DAC_SMPL_RATE);\n\tdaccontrol_SendCommand(chip);\n\t\n\twhile(chip->RemainCmds && chip->Pos < NewPos)\n\t{\n\t\tdaccontrol_SendCommand(chip);\n\t\tchip->Pos += chip->DataStep;\n\t\tchip->RealPos += RealDataStp;\n\t\tchip->Running &= ~0x10;\n\t\tchip->RemainCmds --;\n\t}\n\t\n\tif (! chip->RemainCmds && (chip->Running & 0x04))\n\t{\n\t\t// loop back to start\n\t\tchip->RemainCmds = chip->CmdsToSend;\n\t\tchip->Step = 0x00;\n\t\tchip->Pos = 0x00;\n\t\tif (! chip->Reverse)\n\t\t\tchip->RealPos = 0x00;\n\t\telse\n\t\t\tchip->RealPos = (chip->CmdsToSend - 0x01) * chip->DataStep;\n\t}\n\t\n\tif (! chip->RemainCmds)\n\t\tchip->Running &= ~0x01;\t// stop\n\t\n\treturn;\n}\n\nUINT8 device_start_daccontrol(UINT8 ChipID)\n{\n\tdac_control *chip;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &DACData[ChipID];\n\t\n\tchip->DstChipType = 0xFF;\n\tchip->DstChipID = 0x00;\n\tchip->DstCommand = 0x0000;\n\t\n\tchip->Running = 0xFF;\t// disable all actions (except setup_chip)\n\t\n\treturn 1;\n}\n\nvoid device_stop_daccontrol(UINT8 ChipID)\n{\n\tdac_control *chip = &DACData[ChipID];\n\t\n\tchip->Running = 0xFF;\n\t\n\treturn;\n}\n\nvoid device_reset_daccontrol(UINT8 ChipID)\n{\n\tdac_control *chip = &DACData[ChipID];\n\t\n\tchip->DstChipType = 0x00;\n\tchip->DstChipID = 0x00;\n\tchip->DstCommand = 0x00;\n\tchip->CmdSize = 0x00;\n\t\n\tchip->Frequency = 0;\n\tchip->DataLen = 0x00;\n\tchip->Data = NULL;\n\tchip->DataStart = 0x00;\n\tchip->StepSize = 0x00;\n\tchip->StepBase = 0x00;\n\t\n\tchip->Running = 0x00;\n\tchip->Reverse = 0x00;\n\tchip->Step = 0x00;\n\tchip->Pos = 0x00;\n\tchip->RealPos = 0x00;\n\tchip->RemainCmds = 0x00;\n\tchip->DataStep = 0x00;\n\t\n\treturn;\n}\n\nvoid daccontrol_setup_chip(UINT8 ChipID, UINT8 ChType, UINT8 ChNum, UINT16 Command)\n{\n\tdac_control *chip = &DACData[ChipID];\n\t\n\tchip->DstChipType = ChType;\t// TypeID (e.g. 0x02 for YM2612)\n\tchip->DstChipID = ChNum;\t// chip number (to send commands to 1st or 2nd chip)\n\tchip->DstCommand = Command;\t// Port and Command (would be 0x02A for YM2612)\n\t\n\tswitch(chip->DstChipType)\n\t{\n\tcase 0x00:\t// SN76496\n\t\tif (chip->DstCommand & 0x0010)\n\t\t\tchip->CmdSize = 0x01;\t// Volume Write\n\t\telse\n\t\t\tchip->CmdSize = 0x02;\t// Frequency Write\n\t\tbreak;\n\tcase 0x02:\t// YM2612\n\t\tchip->CmdSize = 0x01;\n\t\tbreak;\n\tcase 0x11:\t// PWM\n\tcase 0x1F:\t// QSound\n\t\tchip->CmdSize = 0x02;\n\t\tbreak;\n\tdefault:\n\t\tchip->CmdSize = 0x01;\n\t\tbreak;\n\t}\n\tchip->DataStep = chip->CmdSize * chip->StepSize;\n\t\n\treturn;\n}\n\nvoid daccontrol_set_data(UINT8 ChipID, UINT8* Data, UINT32 DataLen, UINT8 StepSize, UINT8 StepBase)\n{\n\tdac_control *chip = &DACData[ChipID];\n\t\n\tif (chip->Running & 0x80)\n\t\treturn;\n\t\n\tif (DataLen && Data != NULL)\n\t{\n\t\tchip->DataLen = DataLen;\n\t\tchip->Data = Data;\n\t}\n\telse\n\t{\n\t\tchip->DataLen = 0x00;\n\t\tchip->Data = NULL;\n\t}\n\tchip->StepSize = StepSize ? StepSize : 1;\n\tchip->StepBase = StepBase;\n\tchip->DataStep = chip->CmdSize * chip->StepSize;\n\t\n\treturn;\n}\n\nvoid daccontrol_refresh_data(UINT8 ChipID, UINT8* Data, UINT32 DataLen)\n{\n\t// Should be called to fix the data pointer. (e.g. after a realloc)\n\tdac_control *chip = &DACData[ChipID];\n\t\n\tif (chip->Running & 0x80)\n\t\treturn;\n\t\n\tif (DataLen && Data != NULL)\n\t{\n\t\tchip->DataLen = DataLen;\n\t\tchip->Data = Data;\n\t}\n\telse\n\t{\n\t\tchip->DataLen = 0x00;\n\t\tchip->Data = NULL;\n\t}\n\t\n\treturn;\n}\n\nvoid daccontrol_set_frequency(UINT8 ChipID, UINT32 Frequency)\n{\n\tdac_control *chip = &DACData[ChipID];\n\t\n\tif (chip->Running & 0x80)\n\t\treturn;\n\t\n\tif (Frequency)\n\t\tchip->Step = chip->Step * chip->Frequency / Frequency;\n\tchip->Frequency = Frequency;\n\t\n\treturn;\n}\n\nvoid daccontrol_start(UINT8 ChipID, UINT32 DataPos, UINT8 LenMode, UINT32 Length)\n{\n\tdac_control *chip = &DACData[ChipID];\n\tUINT16 CmdStepBase;\n\t\n\tif (chip->Running & 0x80)\n\t\treturn;\n\t\n\tCmdStepBase = chip->CmdSize * chip->StepBase;\n\tif (DataPos != 0xFFFFFFFF)\t// skip setting DataStart, if Pos == -1\n\t{\n\t\tchip->DataStart = DataPos + CmdStepBase;\n\t\tif (chip->DataStart > chip->DataLen)\t// catch bad value and force silence\n\t\t\tchip->DataStart = chip->DataLen;\n\t}\n\t\n\tswitch(LenMode & 0x0F)\n\t{\n\tcase DCTRL_LMODE_IGNORE:\t// Length is already set - ignore\n\t\tbreak;\n\tcase DCTRL_LMODE_CMDS:\t\t// Length = number of commands\n\t\tchip->CmdsToSend = Length;\n\t\tbreak;\n\tcase DCTRL_LMODE_MSEC:\t\t// Length = time in msec\n\t\tchip->CmdsToSend = 1000 * Length / chip->Frequency;\n\t\tbreak;\n\tcase DCTRL_LMODE_TOEND:\t\t// play unti stop-command is received (or data-end is reached)\n\t\tchip->CmdsToSend = (chip->DataLen - (chip->DataStart - CmdStepBase)) / chip->DataStep;\n\t\tbreak;\n\tcase DCTRL_LMODE_BYTES:\t\t// raw byte count\n\t\tchip->CmdsToSend = Length / chip->DataStep;\n\t\tbreak;\n\tdefault:\n\t\tchip->CmdsToSend = 0x00;\n\t\tbreak;\n\t}\n\tchip->Reverse = (LenMode & 0x10) >> 4;\n\t\n\tchip->RemainCmds = chip->CmdsToSend;\n\tchip->Step = 0x00;\n\tchip->Pos = 0x00;\n\tif (! chip->Reverse)\n\t\tchip->RealPos = 0x00;\n\telse\n\t\tchip->RealPos = (chip->CmdsToSend - 0x01) * chip->DataStep;\n\t\n\tchip->Running &= ~0x04;\n\tchip->Running |= (LenMode & 0x80) ? 0x04 : 0x00;\t// set loop mode\n\t\n\tchip->Running |= 0x01;\t// start\n\tchip->Running &= ~0x10;\t// command isn't yet sent\n\t\n\treturn;\n}\n\nvoid daccontrol_stop(UINT8 ChipID)\n{\n\tdac_control *chip = &DACData[ChipID];\n\t\n\tif (chip->Running & 0x80)\n\t\treturn;\n\t\n\tchip->Running &= ~0x01;\t// stop\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/dac_control.h",
    "content": "void daccontrol_update(UINT8 ChipID, UINT32 samples);\nUINT8 device_start_daccontrol(UINT8 ChipID);\nvoid device_stop_daccontrol(UINT8 ChipID);\nvoid device_reset_daccontrol(UINT8 ChipID);\nvoid daccontrol_setup_chip(UINT8 ChipID, UINT8 ChType, UINT8 ChNum, UINT16 Command);\nvoid daccontrol_set_data(UINT8 ChipID, UINT8* Data, UINT32 DataLen, UINT8 StepSize, UINT8 StepBase);\nvoid daccontrol_refresh_data(UINT8 ChipID, UINT8* Data, UINT32 DataLen);\nvoid daccontrol_set_frequency(UINT8 ChipID, UINT32 Frequency);\nvoid daccontrol_start(UINT8 ChipID, UINT32 DataPos, UINT8 LenMode, UINT32 Length);\nvoid daccontrol_stop(UINT8 ChipID);\n\n#define DCTRL_LMODE_IGNORE\t0x00\n#define DCTRL_LMODE_CMDS\t0x01\n#define DCTRL_LMODE_MSEC\t0x02\n#define DCTRL_LMODE_TOEND\t0x03\n#define DCTRL_LMODE_BYTES\t0x0F\n"
  },
  {
    "path": "VGMPlay/chips/emu2149.c",
    "content": "/****************************************************************************\n\n  emu2149.c -- YM2149/AY-3-8910 emulator by Mitsutaka Okazaki 2001\n\n  2001 04-28 : Version 1.00beta -- 1st Beta Release.\n  2001 08-14 : Version 1.10\n  2001 10-03 : Version 1.11     -- Added PSG_set_quality().\n  2002 03-02 : Version 1.12     -- Removed PSG_init & PSG_close.\n  2002 10-13 : Version 1.14     -- Fixed the envelope unit.\n  2003 09-19 : Version 1.15     -- Added PSG_setMask and PSG_toggleMask\n  2004 01-11 : Version 1.16     -- Fixed an envelope problem where the envelope \n                                   frequency register is written before key-on.\n  \n  References: \n    psg.vhd        -- 2000 written by Kazuhiro Tsujikawa.\n    s_fme7.c       -- 1999,2000 written by Mamiya (NEZplug).\n    ay8910.c       -- 1998-2001 Author unknown (MAME).\n    MSX-Datapack   -- 1991 ASCII Corp.\n    AY-3-8910 data sheet\n    \n*****************************************************************************/\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"emu2149.h\"\n\nstatic e_uint32 voltbl[2][32] = {\n  {0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09,\n   0x0B, 0x0D, 0x0F, 0x12,\n   0x16, 0x1A, 0x1F, 0x25, 0x2D, 0x35, 0x3F, 0x4C, 0x5A, 0x6A, 0x7F, 0x97,\n   0xB4, 0xD6, 0xEB, 0xFF},\n  {0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x05, 0x05, 0x07, 0x07,\n   0x0B, 0x0B, 0x0F, 0x0F,\n   0x16, 0x16, 0x1F, 0x1F, 0x2D, 0x2D, 0x3F, 0x3F, 0x5A, 0x5A, 0x7F, 0x7F,\n   0xB4, 0xB4, 0xFF, 0xFF}\n};\n\n#define GETA_BITS 24\n\nstatic void\ninternal_refresh (PSG * psg)\n{\n  if (psg->quality)\n  {\n    psg->base_incr = 1 << GETA_BITS;\n    psg->realstep = (e_uint32) ((1 << 31) / psg->rate);\n    psg->psgstep = (e_uint32) ((1 << 31) / (psg->clk / 8));\n    psg->psgtime = 0;\n  }\n  else\n  {\n    psg->base_incr =\n      (e_uint32) ((double) psg->clk * (1 << GETA_BITS) / (8.0 * psg->rate));\n  }\n}\n\nEMU2149_API void\nPSG_set_clock(PSG * psg, e_uint32 c)\n{\n  psg->clk = c;\n  internal_refresh(psg);\n}\n\nEMU2149_API void\nPSG_set_rate (PSG * psg, e_uint32 r)\n{\n  psg->rate = r ? r : 44100;\n  internal_refresh (psg);\n}\n\nEMU2149_API void\nPSG_set_quality (PSG * psg, e_uint32 q)\n{\n  psg->quality = q;\n  internal_refresh (psg);\n}\n\nEMU2149_API PSG *\nPSG_new (e_uint32 c, e_uint32 r)\n{\n  PSG *psg;\n\n  psg = (PSG *) malloc (sizeof (PSG));\n  if (psg == NULL)\n    return NULL;\n  memset(psg, 0x00, sizeof(PSG));\n\n  PSG_setVolumeMode (psg, EMU2149_VOL_DEFAULT);\n  psg->clk = c;\n  psg->rate = r ? r : 44100;\n  PSG_set_quality (psg, 0);\n  psg->stereo_mask[0] = 0x03;\n  psg->stereo_mask[1] = 0x03;\n  psg->stereo_mask[2] = 0x03;\n\n  return psg;\n}\n\nEMU2149_API void\nPSG_setFlags (PSG * psg, e_uint8 flags)\n{\n\tif (flags & EMU2149_ZX_STEREO)\n\t{\n\t\t// ABC Stereo\n\t\tpsg->stereo_mask[0] = 0x01;\n\t\tpsg->stereo_mask[1] = 0x03;\n\t\tpsg->stereo_mask[2] = 0x02;\n\t}\n\telse\n\t{\n\t\tpsg->stereo_mask[0] = 0x03;\n\t\tpsg->stereo_mask[1] = 0x03;\n\t\tpsg->stereo_mask[2] = 0x03;\n\t}\n\t\n\treturn;\n}\n\nEMU2149_API void\nPSG_setVolumeMode (PSG * psg, int type)\n{\n  switch (type)\n  {\n  case 1:\n    psg->voltbl = voltbl[EMU2149_VOL_YM2149];\n    break;\n  case 2:\n    psg->voltbl = voltbl[EMU2149_VOL_AY_3_8910];\n    break;\n  default:\n    psg->voltbl = voltbl[EMU2149_VOL_DEFAULT];\n    break;\n  }\n}\n\nEMU2149_API e_uint32\nPSG_setMask (PSG *psg, e_uint32 mask)\n{\n  e_uint32 ret = 0;\n  if(psg)\n  {\n    ret = psg->mask;\n    psg->mask = mask;\n  }  \n  return ret;\n}\n\nEMU2149_API void\nPSG_setStereoMask (PSG *psg, e_uint32 mask)\n{\n  e_uint32 ret = 0;\n  if(psg)\n  {\n    psg->stereo_mask[0] = (mask >>0) &3;\n    psg->stereo_mask[1] = (mask >>2) &3;\n    psg->stereo_mask[2] = (mask >>4) &3;\n  }  \n}\n\nEMU2149_API e_uint32\nPSG_toggleMask (PSG *psg, e_uint32 mask)\n{\n  e_uint32 ret = 0;\n  if(psg)\n  {\n    ret = psg->mask;\n    psg->mask ^= mask;\n  }\n  return ret;\n}\n\nEMU2149_API void\nPSG_reset (PSG * psg)\n{\n  int i;\n\n  psg->base_count = 0;\n\n  for (i = 0; i < 3; i++)\n  {\n    psg->cout[i] = 0;\n    psg->count[i] = 0x1000;\n    psg->freq[i] = 0;\n    psg->edge[i] = 0;\n    psg->volume[i] = 0;\n  }\n\n  psg->mask = 0;\n\n  for (i = 0; i < 16; i++)\n    psg->reg[i] = 0;\n  psg->adr = 0;\n\n  psg->noise_seed = 0xffff;\n  psg->noise_count = 0x40;\n  psg->noise_freq = 0;\n\n  psg->env_volume = 0;\n  psg->env_ptr = 0;\n  psg->env_freq = 0;\n  psg->env_count = 0;\n  psg->env_pause = 1;\n\n  psg->out = 0;\n}\n\nEMU2149_API void\nPSG_delete (PSG * psg)\n{\n  free (psg);\n}\n\nEMU2149_API e_uint8\nPSG_readIO (PSG * psg)\n{\n  return (e_uint8) (psg->reg[psg->adr]);\n}\n\nEMU2149_API e_uint8\nPSG_readReg (PSG * psg, e_uint32 reg)\n{\n  return (e_uint8) (psg->reg[reg & 0x1f]);\n\n}\n\nEMU2149_API void\nPSG_writeIO (PSG * psg, e_uint32 adr, e_uint32 val)\n{\n  if (adr & 1)\n    PSG_writeReg (psg, psg->adr, val);\n  else\n    psg->adr = val & 0x1f;\n}\n\nINLINE static e_int16\ncalc (PSG * psg)\n{\n\n  int i, noise;\n  e_uint32 incr;\n  e_int32 mix = 0;\n\n  psg->base_count += psg->base_incr;\n  incr = (psg->base_count >> GETA_BITS);\n  psg->base_count &= (1 << GETA_BITS) - 1;\n\n  /* Envelope */\n  psg->env_count += incr;\n  while (psg->env_count>=0x10000 && psg->env_freq!=0)\n  {\n    if (!psg->env_pause)\n    {\n      if(psg->env_face)\n        psg->env_ptr = (psg->env_ptr + 1) & 0x3f ; \n      else\n        psg->env_ptr = (psg->env_ptr + 0x3f) & 0x3f;\n    }\n\n    if (psg->env_ptr & 0x20) /* if carry or borrow */\n    {\n      if (psg->env_continue)\n      {\n        if (psg->env_alternate^psg->env_hold) psg->env_face ^= 1;\n        if (psg->env_hold) psg->env_pause = 1;\n        psg->env_ptr = psg->env_face?0:0x1f;       \n      }\n      else\n      {\n        psg->env_pause = 1;\n        psg->env_ptr = 0;\n      }\n    }\n\n    psg->env_count -= psg->env_freq;\n  }\n\n  /* Noise */\n  psg->noise_count += incr;\n  if (psg->noise_count & 0x40)\n  {\n    if (psg->noise_seed & 1)\n      psg->noise_seed ^= 0x24000;\n    psg->noise_seed >>= 1;\n    psg->noise_count -= psg->noise_freq;\n  }\n  noise = psg->noise_seed & 1;\n\n  /* Tone */\n  for (i = 0; i < 3; i++)\n  {\n    psg->count[i] += incr;\n    if (psg->count[i] & 0x1000)\n    {\n      if (psg->freq[i] > 1)\n      {\n        psg->edge[i] = !psg->edge[i];\n        psg->count[i] -= psg->freq[i];\n      }\n      else\n      {\n        psg->edge[i] = 1;\n      }\n    }\n\n    psg->cout[i] = 0; // BS maintaining cout for stereo mix\n\n    if (psg->mask&PSG_MASK_CH(i))\n      continue;\n\n    if ((psg->tmask[i] || psg->edge[i]) && (psg->nmask[i] || noise))\n    {\n      if (!(psg->volume[i] & 32))\n        psg->cout[i] = psg->voltbl[psg->volume[i] & 31];\n      else\n        psg->cout[i] = psg->voltbl[psg->env_ptr];\n\n      mix += psg->cout[i];\n    }\n  }\n\n  return (e_int16) mix;\n}\n\nEMU2149_API e_int16\nPSG_calc (PSG * psg)\n{\n  if (!psg->quality)\n    return (e_int16) (calc (psg) << 4);\n\n  /* Simple rate converter */\n  while (psg->realstep > psg->psgtime)\n  {\n    psg->psgtime += psg->psgstep;\n    psg->out += calc (psg);\n    psg->out >>= 1;\n  }\n\n  psg->psgtime = psg->psgtime - psg->realstep;\n\n  return (e_int16) (psg->out << 4);\n}\n\nINLINE static void\ncalc_stereo (PSG * psg, e_int32 out[2])\n{\n  int i, noise;\n  e_uint32 incr;\n  e_int32 l = 0, r = 0;\n\n  psg->base_count += psg->base_incr;\n  incr = (psg->base_count >> GETA_BITS);\n  psg->base_count &= (1 << GETA_BITS) - 1;\n\n  /* Envelope */\n  psg->env_count += incr;\n  while (psg->env_count>=0x10000 && psg->env_freq!=0)\n  {\n    if (!psg->env_pause)\n    {\n      if(psg->env_face)\n        psg->env_ptr = (psg->env_ptr + 1) & 0x3f ; \n      else\n        psg->env_ptr = (psg->env_ptr + 0x3f) & 0x3f;\n    }\n\n    if (psg->env_ptr & 0x20) /* if carry or borrow */\n    {\n      if (psg->env_continue)\n      {\n        if (psg->env_alternate^psg->env_hold) psg->env_face ^= 1;\n        if (psg->env_hold) psg->env_pause = 1;\n        psg->env_ptr = psg->env_face?0:0x1f;       \n      }\n      else\n      {\n        psg->env_pause = 1;\n        psg->env_ptr = 0;\n      }\n    }\n\n    psg->env_count -= psg->env_freq;\n  }\n\n  /* Noise */\n  psg->noise_count += incr;\n  if (psg->noise_count & 0x40)\n  {\n    if (psg->noise_seed & 1)\n      psg->noise_seed ^= 0x24000;\n    psg->noise_seed >>= 1;\n    psg->noise_count -= psg->noise_freq;\n  }\n  noise = psg->noise_seed & 1;\n\n  /* Tone */\n  for (i = 0; i < 3; i++)\n  {\n    psg->count[i] += incr;\n    if (psg->count[i] & 0x1000)\n    {\n      if (psg->freq[i] > 1)\n      {\n        psg->edge[i] = !psg->edge[i];\n        psg->count[i] -= psg->freq[i];\n      }\n      else\n      {\n        psg->edge[i] = 1;\n      }\n    }\n\n    psg->cout[i] = 0; // BS maintaining cout for stereo mix\n\n    if (psg->mask&PSG_MASK_CH(i))\n      continue;\n\n    if ((psg->tmask[i] || psg->edge[i]) && (psg->nmask[i] || noise))\n    {\n      if (!(psg->volume[i] & 32))\n        psg->cout[i] = psg->voltbl[psg->volume[i] & 31];\n      else\n        psg->cout[i] = psg->voltbl[psg->env_ptr];\n\n      if (psg->stereo_mask[i] & 0x01)\n        l += psg->cout[i];\n      if (psg->stereo_mask[i] & 0x02)\n        r += psg->cout[i];\n    }\n  }\n\n  out[0] = l << 5;\n  out[1] = r << 5;\n\n  return;\n}\n\nEMU2149_API void\nPSG_calc_stereo (PSG * psg, e_int32 **out, e_int32 samples)\n{\n  e_int32 *bufMO = out[0];\n  e_int32 *bufRO = out[1];\n  e_int32 buffers[2];\n\n  int i;\n\n  for (i = 0; i < samples; i ++)\n  {\n    if (!psg->quality)\n    {\n      calc_stereo (psg, buffers);\n      bufMO[i] = buffers[0];\n      bufRO[i] = buffers[1];\n    }\n    else\n    {\n      while (psg->realstep > psg->psgtime)\n      { \n        psg->psgtime += psg->psgstep;\n        psg->sprev[0] = psg->snext[0];\n        psg->sprev[1] = psg->snext[1];\n        calc_stereo (psg, psg->snext);\n      }\n\n      psg->psgtime -= psg->realstep;\n      bufMO[i] = (e_int32) (((double) psg->snext[0] * (psg->psgstep - psg->psgtime)\n                           + (double) psg->sprev[0] * psg->psgtime) / psg->psgstep);\n      bufRO[i] = (e_int32) (((double) psg->snext[1] * (psg->psgstep - psg->psgtime)\n                           + (double) psg->sprev[1] * psg->psgtime) / psg->psgstep);\n    }\n  }\n}\n\nEMU2149_API void\nPSG_writeReg (PSG * psg, e_uint32 reg, e_uint32 val)\n{\n  int c;\n\n  if (reg > 15) return;\n\n  psg->reg[reg] = (e_uint8) (val & 0xff);\n  switch (reg)\n  {\n  case 0:\n  case 2:\n  case 4:\n  case 1:\n  case 3:\n  case 5:\n    c = reg >> 1;\n    psg->freq[c] = ((psg->reg[c * 2 + 1] & 15) << 8) + psg->reg[c * 2];\n    break;\n\n  case 6:\n    psg->noise_freq = (val == 0) ? 1 : ((val & 31) << 1);\n    break;\n\n  case 7:\n    psg->tmask[0] = (val & 1);\n    psg->tmask[1] = (val & 2);\n    psg->tmask[2] = (val & 4);\n    psg->nmask[0] = (val & 8);\n    psg->nmask[1] = (val & 16);\n    psg->nmask[2] = (val & 32);\n    break;\n\n  case 8:\n  case 9:\n  case 10:\n    psg->volume[reg - 8] = val << 1;\n\n    break;\n\n  case 11:\n  case 12:\n    psg->env_freq = (psg->reg[12] << 8) + psg->reg[11];\n    break;\n\n  case 13:\n    psg->env_continue = (val >> 3) & 1;\n    psg->env_attack = (val >> 2) & 1;\n    psg->env_alternate = (val >> 1) & 1;\n    psg->env_hold = val & 1;\n    psg->env_face = psg->env_attack;\n    psg->env_pause = 0;\n    psg->env_count = 0x10000 - psg->env_freq;\n    psg->env_ptr = psg->env_face?0:0x1f;\n    break;\n\n  case 14:\n  case 15:\n  default:\n    break;\n  }\n\n  return;\n}\n"
  },
  {
    "path": "VGMPlay/chips/emu2149.h",
    "content": "/* emu2149.h */\n#ifndef _EMU2149_H_\n#define _EMU2149_H_\n#include \"emutypes.h\"\n\n/*#ifdef EMU2149_DLL_EXPORTS\n#define EMU2149_API __declspec(dllexport)\n#elif  EMU2149_DLL_IMPORTS\n#define EMU2149_API __declspec(dllimport)\n#else*/\n#define EMU2149_API\n//#endif\n\n#define EMU2149_VOL_DEFAULT 1\n#define EMU2149_VOL_YM2149 0\n#define EMU2149_VOL_AY_3_8910 1\n\n#define EMU2149_ZX_STEREO\t\t\t0x80\n\n#define PSG_MASK_CH(x) (1<<(x))\n\n/*#ifdef __cplusplus\nextern \"C\"\n{\n#endif*/\n\n  typedef struct __PSG\n  {\n\n    /* Volume Table */\n    e_uint32 *voltbl;\n\n    e_uint8 reg[0x20];\n    e_int32 out;\n    e_int32 cout[3];\n\n    e_uint32 clk, rate, base_incr, quality;\n\n    e_uint32 count[3];\n    e_uint32 volume[3];\n    e_uint32 freq[3];\n    e_uint32 edge[3];\n    e_uint32 tmask[3];\n    e_uint32 nmask[3];\n    e_uint32 mask;\n    e_uint32 stereo_mask[3];\n\n    e_uint32 base_count;\n\n    e_uint32 env_volume;\n    e_uint32 env_ptr;\n    e_uint32 env_face;\n\n    e_uint32 env_continue;\n    e_uint32 env_attack;\n    e_uint32 env_alternate;\n    e_uint32 env_hold;\n    e_uint32 env_pause;\n    e_uint32 env_reset;\n\n    e_uint32 env_freq;\n    e_uint32 env_count;\n\n    e_uint32 noise_seed;\n    e_uint32 noise_count;\n    e_uint32 noise_freq;\n\n    /* rate converter */\n    e_uint32 realstep;\n    e_uint32 psgtime;\n    e_uint32 psgstep;\n    e_int32 prev, next;\n    e_int32 sprev[2], snext[2];\n\n    /* I/O Ctrl */\n    e_uint32 adr;\n\n  }\n  PSG;\n\n  EMU2149_API void PSG_set_quality (PSG * psg, e_uint32 q);\n  EMU2149_API void PSG_set_clock(PSG * psg, e_uint32 c);\n  EMU2149_API void PSG_set_rate (PSG * psg, e_uint32 r);\n  EMU2149_API PSG *PSG_new (e_uint32 clk, e_uint32 rate);\n  EMU2149_API void PSG_reset (PSG *);\n  EMU2149_API void PSG_delete (PSG *);\n  EMU2149_API void PSG_writeReg (PSG *, e_uint32 reg, e_uint32 val);\n  EMU2149_API void PSG_writeIO (PSG * psg, e_uint32 adr, e_uint32 val);\n  EMU2149_API e_uint8 PSG_readReg (PSG * psg, e_uint32 reg);\n  EMU2149_API e_uint8 PSG_readIO (PSG * psg);\n  EMU2149_API e_int16 PSG_calc (PSG *);\n  EMU2149_API void PSG_calc_stereo (PSG * psg, e_int32 **out, e_int32 samples);\n  EMU2149_API void PSG_setFlags (PSG * psg, e_uint8 flags);\n  EMU2149_API void PSG_setVolumeMode (PSG * psg, int type);\n  EMU2149_API e_uint32 PSG_setMask (PSG *, e_uint32 mask);\n  EMU2149_API e_uint32 PSG_toggleMask (PSG *, e_uint32 mask);\n  EMU2149_API void PSG_setStereoMask (PSG *psg, e_uint32 mask);\n    \n/*#ifdef __cplusplus\n}\n#endif*/\n\n#endif\n"
  },
  {
    "path": "VGMPlay/chips/emu2413.c",
    "content": "/**\n * emu2413 v1.5.2\n * https://github.com/digital-sound-antiques/emu2413\n * Copyright (C) 2020 Mitsutaka Okazaki\n *\n * This source refers to the following documents. The author would like to thank all the authors who have\n * contributed to the writing of them.\n * - [YM2413 notes](http://www.smspower.org/Development/YM2413) by andete\n * - ymf262.c by Jarek Burczynski\n * - [VRC7 presets](https://siliconpr0n.org/archive/doku.php?id=vendor:yamaha:opl2#opll_vrc7_patch_format) by Nuke.YKT\n * - YMF281B presets by Chabin\n */\n#include \"emu2413.h\"\n#include <math.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"panning.h\" // Maxim\n\n#ifndef INLINE\n#if defined(_MSC_VER)\n#define INLINE __inline\n#elif defined(__GNUC__)\n#define INLINE __inline__\n#else\n#define INLINE inline\n#endif\n#endif\n\n#define _PI_ 3.14159265358979323846264338327950288\n\n#define OPLL_TONE_NUM 3\n/* clang-format off */\nstatic uint8_t default_inst[OPLL_TONE_NUM][(16 + 3) * 8] = {{\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0: Original\n0x71,0x61,0x1e,0x17,0xd0,0x78,0x00,0x17, // 1: Violin\n0x13,0x41,0x1a,0x0d,0xd8,0xf7,0x23,0x13, // 2: Guitar\n0x13,0x01,0x99,0x00,0xf2,0xc4,0x21,0x23, // 3: Piano\n0x11,0x61,0x0e,0x07,0x8d,0x64,0x70,0x27, // 4: Flute\n0x32,0x21,0x1e,0x06,0xe1,0x76,0x01,0x28, // 5: Clarinet\n0x31,0x22,0x16,0x05,0xe0,0x71,0x00,0x18, // 6: Oboe\n0x21,0x61,0x1d,0x07,0x82,0x81,0x11,0x07, // 7: Trumpet\n0x33,0x21,0x2d,0x13,0xb0,0x70,0x00,0x07, // 8: Organ\n0x61,0x61,0x1b,0x06,0x64,0x65,0x10,0x17, // 9: Horn\n0x41,0x61,0x0b,0x18,0x85,0xf0,0x81,0x07, // A: Synthesizer\n0x33,0x01,0x83,0x11,0xea,0xef,0x10,0x04, // B: Harpsichord\n0x17,0xc1,0x24,0x07,0xf8,0xf8,0x22,0x12, // C: Vibraphone\n0x61,0x50,0x0c,0x05,0xd2,0xf5,0x40,0x42, // D: Synthsizer Bass\n0x01,0x01,0x55,0x03,0xe9,0x90,0x03,0x02, // E: Acoustic Bass\n0x41,0x41,0x89,0x03,0xf1,0xe4,0xc0,0x13, // F: Electric Guitar\n0x01,0x01,0x18,0x0f,0xdf,0xf8,0x6a,0x6d, // R: Bass Drum (from VRC7)\n0x01,0x01,0x00,0x00,0xc8,0xd8,0xa7,0x68, // R: High-Hat(M) / Snare Drum(C) (from VRC7)\n0x05,0x01,0x00,0x00,0xf8,0xaa,0x59,0x55, // R: Tom-tom(M) / Top Cymbal(C) (from VRC7)\n},{\n/* VRC7 presets from Nuke.YKT */\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x03,0x21,0x05,0x06,0xe8,0x81,0x42,0x27,\n0x13,0x41,0x14,0x0d,0xd8,0xf6,0x23,0x12,\n0x11,0x11,0x08,0x08,0xfa,0xb2,0x20,0x12,\n0x31,0x61,0x0c,0x07,0xa8,0x64,0x61,0x27,\n0x32,0x21,0x1e,0x06,0xe1,0x76,0x01,0x28,\n0x02,0x01,0x06,0x00,0xa3,0xe2,0xf4,0xf4,\n0x21,0x61,0x1d,0x07,0x82,0x81,0x11,0x07,\n0x23,0x21,0x22,0x17,0xa2,0x72,0x01,0x17,\n0x35,0x11,0x25,0x00,0x40,0x73,0x72,0x01,\n0xb5,0x01,0x0f,0x0F,0xa8,0xa5,0x51,0x02,\n0x17,0xc1,0x24,0x07,0xf8,0xf8,0x22,0x12,\n0x71,0x23,0x11,0x06,0x65,0x74,0x18,0x16,\n0x01,0x02,0xd3,0x05,0xc9,0x95,0x03,0x02,\n0x61,0x63,0x0c,0x00,0x94,0xC0,0x33,0xf6,\n0x21,0x72,0x0d,0x00,0xc1,0xd5,0x56,0x06,\n0x01,0x01,0x18,0x0f,0xdf,0xf8,0x6a,0x6d,\n0x01,0x01,0x00,0x00,0xc8,0xd8,0xa7,0x68,\n0x05,0x01,0x00,0x00,0xf8,0xaa,0x59,0x55,\n},{\n/* YMF281B presets by Chabin */\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x62,0x21,0x1a,0x07,0xf0,0x6f,0x00,0x16,\n0x00,0x10,0x44,0x02,0xf6,0xf4,0x54,0x23,\n0x03,0x01,0x97,0x04,0xf3,0xf3,0x13,0xf3,\n0x01,0x61,0x0a,0x0f,0xfa,0x64,0x70,0x17,\n0x22,0x21,0x1e,0x06,0xf0,0x76,0x00,0x28,\n0x00,0x61,0x8a,0x0e,0xc0,0x61,0x00,0x07,\n0x21,0x61,0x1b,0x07,0x84,0x80,0x17,0x17,\n0x37,0x32,0xc9,0x01,0x66,0x64,0x40,0x28,\n0x01,0x21,0x06,0x03,0xa5,0x71,0x51,0x07,\n0x06,0x11,0x5e,0x07,0xf3,0xf2,0xf6,0x11,\n0x00,0x20,0x18,0x06,0xf5,0xf3,0x20,0x26,\n0x97,0x41,0x20,0x07,0xff,0xf4,0x22,0x22,\n0x65,0x61,0x15,0x00,0xf7,0xf3,0x16,0xf4,\n0x01,0x31,0x0e,0x07,0xfa,0xf3,0xff,0xff,\n0x48,0x61,0x09,0x07,0xf1,0x94,0xf0,0xf5,\n0x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,\n0x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7,\n0x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55,\n}};\n/* clang-format on */\n\n/* phase increment counter */\n#define DP_BITS 19\n#define DP_WIDTH (1 << DP_BITS)\n#define DP_BASE_BITS (DP_BITS - PG_BITS)\n\n/* dynamic range of envelope output */\n#define EG_STEP 0.375\n#define EG_BITS 7\n#define EG_MUTE ((1 << EG_BITS) - 1)\n#define EG_MAX (EG_MUTE - 3)\n\n/* dynamic range of total level */\n#define TL_STEP 0.75\n#define TL_BITS 6\n\n/* dynamic range of sustine level */\n#define SL_STEP 3.0\n#define SL_BITS 4\n\n/* damper speed before key-on. key-scale affects. */\n#define DAMPER_RATE 12\n\n#define TL2EG(d) ((d) << 1)\n\n/* sine table */\n#define PG_BITS 10 /* 2^10 = 1024 length sine table */\n#define PG_WIDTH (1 << PG_BITS)\n\n/* clang-format off */\n/* exp_table[x] = round((exp2((double)x / 256.0) - 1) * 1024) */\nstatic uint16_t exp_table[256] = {\n0,    3,    6,    8,    11,   14,   17,   20,   22,   25,   28,   31,   34,   37,   40,   42,\n45,   48,   51,   54,   57,   60,   63,   66,   69,   72,   75,   78,   81,   84,   87,   90,\n93,   96,   99,   102,  105,  108,  111,  114,  117,  120,  123,  126,  130,  133,  136,  139,\n142,  145,  148,  152,  155,  158,  161,  164,  168,  171,  174,  177,  181,  184,  187,  190,\n194,  197,  200,  204,  207,  210,  214,  217,  220,  224,  227,  231,  234,  237,  241,  244,\n248,  251,  255,  258,  262,  265,  268,  272,  276,  279,  283,  286,  290,  293,  297,  300,\n304,  308,  311,  315,  318,  322,  326,  329,  333,  337,  340,  344,  348,  352,  355,  359,\n363,  367,  370,  374,  378,  382,  385,  389,  393,  397,  401,  405,  409,  412,  416,  420,\n424,  428,  432,  436,  440,  444,  448,  452,  456,  460,  464,  468,  472,  476,  480,  484,\n488,  492,  496,  501,  505,  509,  513,  517,  521,  526,  530,  534,  538,  542,  547,  551,\n555,  560,  564,  568,  572,  577,  581,  585,  590,  594,  599,  603,  607,  612,  616,  621,\n625,  630,  634,  639,  643,  648,  652,  657,  661,  666,  670,  675,  680,  684,  689,  693,\n698,  703,  708,  712,  717,  722,  726,  731,  736,  741,  745,  750,  755,  760,  765,  770,\n774,  779,  784,  789,  794,  799,  804,  809,  814,  819,  824,  829,  834,  839,  844,  849,\n854,  859,  864,  869,  874,  880,  885,  890,  895,  900,  906,  911,  916,  921,  927,  932,\n937,  942,  948,  953,  959,  964,  969,  975,  980,  986,  991,  996, 1002, 1007, 1013, 1018\n};\n/* fullsin_table[x] = round(-log2(sin((x + 0.5) * PI / (PG_WIDTH / 4) / 2)) * 256) */\nstatic uint16_t fullsin_table[PG_WIDTH] = {\n2137, 1731, 1543, 1419, 1326, 1252, 1190, 1137, 1091, 1050, 1013, 979,  949,  920,  894,  869, \n846,  825,  804,  785,  767,  749,  732,  717,  701,  687,  672,  659,  646,  633,  621,  609, \n598,  587,  576,  566,  556,  546,  536,  527,  518,  509,  501,  492,  484,  476,  468,  461,\n453,  446,  439,  432,  425,  418,  411,  405,  399,  392,  386,  380,  375,  369,  363,  358,  \n352,  347,  341,  336,  331,  326,  321,  316,  311,  307,  302,  297,  293,  289,  284,  280,\n276,  271,  267,  263,  259,  255,  251,  248,  244,  240,  236,  233,  229,  226,  222,  219, \n215,  212,  209,  205,  202,  199,  196,  193,  190,  187,  184,  181,  178,  175,  172,  169, \n167,  164,  161,  159,  156,  153,  151,  148,  146,  143,  141,  138,  136,  134,  131,  129,  \n127,  125,  122,  120,  118,  116,  114,  112,  110,  108,  106,  104,  102,  100,  98,   96,   \n94,   92,   91,   89,   87,   85,   83,   82,   80,   78,   77,   75,   74,   72,   70,   69,\n67,   66,   64,   63,   62,   60,   59,   57,   56,   55,   53,   52,   51,   49,   48,   47,  \n46,   45,   43,   42,   41,   40,   39,   38,   37,   36,   35,   34,   33,   32,   31,   30,  \n29,   28,   27,   26,   25,   24,   23,   23,   22,   21,   20,   20,   19,   18,   17,   17,   \n16,   15,   15,   14,   13,   13,   12,   12,   11,   10,   10,   9,    9,    8,    8,    7,    \n7,    7,    6,    6,    5,    5,    5,    4,    4,    4,    3,    3,    3,    2,    2,    2,\n2,    1,    1,    1,    1,    1,    1,    1,    0,    0,    0,    0,    0,    0,    0,    0,\n};\n/* clang-format on */\n\nstatic uint16_t halfsin_table[PG_WIDTH];\nstatic uint16_t *wave_table_map[2] = {fullsin_table, halfsin_table};\n\n/* pitch modulator */\n/* offset to fnum, rough approximation of 14 cents depth. */\nstatic int8_t pm_table[8][8] = {\n    {0, 0, 0, 0, 0, 0, 0, 0},    // fnum = 000xxxxxx\n    {0, 0, 1, 0, 0, 0, -1, 0},   // fnum = 001xxxxxx\n    {0, 1, 2, 1, 0, -1, -2, -1}, // fnum = 010xxxxxx\n    {0, 1, 3, 1, 0, -1, -3, -1}, // fnum = 011xxxxxx\n    {0, 2, 4, 2, 0, -2, -4, -2}, // fnum = 100xxxxxx\n    {0, 2, 5, 2, 0, -2, -5, -2}, // fnum = 101xxxxxx\n    {0, 3, 6, 3, 0, -3, -6, -3}, // fnum = 110xxxxxx\n    {0, 3, 7, 3, 0, -3, -7, -3}, // fnum = 111xxxxxx\n};\n\n/* amplitude lfo table */\n/* The following envelop pattern is verified on real YM2413. */\n/* each element repeates 64 cycles */\nstatic uint8_t am_table[210] = {0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  //\n                                2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,  //\n                                4,  4,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,  5,  5,  5,  5,  //\n                                6,  6,  6,  6,  6,  6,  6,  6,  7,  7,  7,  7,  7,  7,  7,  7,  //\n                                8,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  //\n                                10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, //\n                                12, 12, 12, 12, 12, 12, 12, 12,                                 //\n                                13, 13, 13,                                                     //\n                                12, 12, 12, 12, 12, 12, 12, 12,                                 //\n                                11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, //\n                                9,  9,  9,  9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,  8,  8,  //\n                                7,  7,  7,  7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  6,  6,  //\n                                5,  5,  5,  5,  5,  5,  5,  5,  4,  4,  4,  4,  4,  4,  4,  4,  //\n                                3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,  //\n                                1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0};\n\n/* envelope decay increment step table */\n/* based on andete's research */\nstatic uint8_t eg_step_tables[4][8] = {\n    {0, 1, 0, 1, 0, 1, 0, 1},\n    {0, 1, 0, 1, 1, 1, 0, 1},\n    {0, 1, 1, 1, 0, 1, 1, 1},\n    {0, 1, 1, 1, 1, 1, 1, 1},\n};\n\nenum __OPLL_EG_STATE { ATTACK, DECAY, SUSTAIN, RELEASE, DAMP, UNKNOWN };\n\nstatic uint32_t ml_table[16] = {1,     1 * 2, 2 * 2,  3 * 2,  4 * 2,  5 * 2,  6 * 2,  7 * 2,\n                                8 * 2, 9 * 2, 10 * 2, 10 * 2, 12 * 2, 12 * 2, 15 * 2, 15 * 2};\n\n#define dB2(x) ((x)*2)\nstatic double kl_table[16] = {dB2(0.000),  dB2(9.000),  dB2(12.000), dB2(13.875), dB2(15.000), dB2(16.125),\n                              dB2(16.875), dB2(17.625), dB2(18.000), dB2(18.750), dB2(19.125), dB2(19.500),\n                              dB2(19.875), dB2(20.250), dB2(20.625), dB2(21.000)};\n\nstatic uint32_t tll_table[8 * 16][1 << TL_BITS][4];\nstatic int32_t rks_table[8 * 2][2];\n\nstatic OPLL_PATCH null_patch = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\nstatic OPLL_PATCH default_patch[OPLL_TONE_NUM][(16 + 3) * 2];\n\n#define min(i, j) (((i) < (j)) ? (i) : (j))\n#define max(i, j) (((i) > (j)) ? (i) : (j))\n\n/***************************************************\n\n           Internal Sample Rate Converter\n\n****************************************************/\n/* Note: to disable internal rate converter, set clock/72 to output sampling rate. */\n\n/*\n * LW is truncate length of sinc(x) calculation.\n * Lower LW is faster, higher LW results better quality.\n * LW must be a non-zero positive even number, no upper limit.\n * LW=16 or greater is recommended when upsampling.\n * LW=8 is practically okay for downsampling.\n */\n#define LW 16\n\n/* resolution of sinc(x) table. sinc(x) where 0.0<=x<1.0 corresponds to sinc_table[0...SINC_RESO-1] */\n#define SINC_RESO 256\n#define SINC_AMP_BITS 12\n\n// double hamming(double x) { return 0.54 - 0.46 * cos(2 * PI * x); }\nstatic double blackman(double x) { return 0.42 - 0.5 * cos(2 * _PI_ * x) + 0.08 * cos(4 * _PI_ * x); }\nstatic double sinc(double x) { return (x == 0.0 ? 1.0 : sin(_PI_ * x) / (_PI_ * x)); }\nstatic double windowed_sinc(double x) { return blackman(0.5 + 0.5 * x / (LW / 2)) * sinc(x); }\n\n/* f_inp: input frequency. f_out: output frequencey, ch: number of channels */\nOPLL_RateConv *OPLL_RateConv_new(double f_inp, double f_out, int ch) {\n  OPLL_RateConv *conv = malloc(sizeof(OPLL_RateConv));\n  int i;\n\n  conv->ch = ch;\n  conv->f_ratio = f_inp / f_out;\n  conv->buf = malloc(sizeof(void *) * ch);\n  for (i = 0; i < ch; i++) {\n    conv->buf[i] = malloc(sizeof(conv->buf[0][0]) * LW);\n  }\n\n  /* create sinc_table for positive 0 <= x < LW/2 */\n  conv->sinc_table = malloc(sizeof(conv->sinc_table[0]) * SINC_RESO * LW / 2);\n  for (i = 0; i < SINC_RESO * LW / 2; i++) {\n    const double x = (double)i / SINC_RESO;\n    if (f_out < f_inp) {\n      /* for downsampling */\n      conv->sinc_table[i] = (int16_t)((1 << SINC_AMP_BITS) * windowed_sinc(x / conv->f_ratio) / conv->f_ratio);\n    } else {\n      /* for upsampling */\n      conv->sinc_table[i] = (int16_t)((1 << SINC_AMP_BITS) * windowed_sinc(x));\n    }\n  }\n\n  return conv;\n}\n\nstatic INLINE int16_t lookup_sinc_table(int16_t *table, double x) {\n  int16_t index = (int16_t)(x * SINC_RESO);\n  if (index < 0)\n    index = -index;\n  return table[min(SINC_RESO * LW / 2 - 1, index)];\n}\n\nvoid OPLL_RateConv_reset(OPLL_RateConv *conv) {\n  int i;\n  conv->timer = 0;\n  for (i = 0; i < conv->ch; i++) {\n    memset(conv->buf[i], 0, sizeof(conv->buf[i][0]) * LW);\n  }\n}\n\n/* put original data to this converter at f_inp. */\nvoid OPLL_RateConv_putData(OPLL_RateConv *conv, int ch, int16_t data) {\n  int16_t *buf = conv->buf[ch];\n  int i;\n  for (i = 0; i < LW - 1; i++) {\n    buf[i] = buf[i + 1];\n  }\n  buf[LW - 1] = data;\n}\n\n/* get resampled data from this converter at f_out. */\n/* this function must be called f_out / f_inp times per one putData call. */\nint16_t OPLL_RateConv_getData(OPLL_RateConv *conv, int ch) {\n  int16_t *buf = conv->buf[ch];\n  int32_t sum = 0;\n  int k;\n  double dn;\n  conv->timer += conv->f_ratio;\n  dn = conv->timer - floor(conv->timer);\n  conv->timer = dn;\n\n  for (k = 0; k < LW; k++) {\n    double x = ((double)k - (LW / 2 - 1)) - dn;\n    sum += buf[k] * lookup_sinc_table(conv->sinc_table, x);\n  }\n  return sum >> SINC_AMP_BITS;\n}\n\nvoid OPLL_RateConv_delete(OPLL_RateConv *conv) {\n  int i;\n  for (i = 0; i < conv->ch; i++) {\n    free(conv->buf[i]);\n  }\n  free(conv->buf);\n  free(conv->sinc_table);\n  free(conv);\n}\n\n/***************************************************\n\n                  Create tables\n\n****************************************************/\n\nstatic void makeSinTable(void) {\n  int x;\n\n  for (x = 0; x < PG_WIDTH / 4; x++) {\n    fullsin_table[PG_WIDTH / 4 + x] = fullsin_table[PG_WIDTH / 4 - x - 1];\n  }\n\n  for (x = 0; x < PG_WIDTH / 2; x++) {\n    fullsin_table[PG_WIDTH / 2 + x] = 0x8000 | fullsin_table[x];\n  }\n\n  for (x = 0; x < PG_WIDTH / 2; x++)\n    halfsin_table[x] = fullsin_table[x];\n\n  for (x = PG_WIDTH / 2; x < PG_WIDTH; x++)\n    halfsin_table[x] = 0xfff;\n}\n\nstatic void makeTllTable(void) {\n\n  int32_t tmp;\n  int32_t fnum, block, TL, KL;\n\n  for (fnum = 0; fnum < 16; fnum++) {\n    for (block = 0; block < 8; block++) {\n      for (TL = 0; TL < 64; TL++) {\n        for (KL = 0; KL < 4; KL++) {\n          if (KL == 0) {\n            tll_table[(block << 4) | fnum][TL][KL] = TL2EG(TL);\n          } else {\n            tmp = (int32_t)(kl_table[fnum] - dB2(3.000) * (7 - block));\n            if (tmp <= 0)\n              tll_table[(block << 4) | fnum][TL][KL] = TL2EG(TL);\n            else\n              tll_table[(block << 4) | fnum][TL][KL] = (uint32_t)((tmp >> (3 - KL)) / EG_STEP) + TL2EG(TL);\n          }\n        }\n      }\n    }\n  }\n}\n\nstatic void makeRksTable(void) {\n  int fnum8, block;\n  for (fnum8 = 0; fnum8 < 2; fnum8++)\n    for (block = 0; block < 8; block++) {\n      rks_table[(block << 1) | fnum8][1] = (block << 1) + fnum8;\n      rks_table[(block << 1) | fnum8][0] = block >> 1;\n    }\n}\n\nstatic void makeDefaultPatch() {\n  int i, j;\n  for (i = 0; i < OPLL_TONE_NUM; i++)\n    for (j = 0; j < 19; j++)\n      OPLL_getDefaultPatch(i, j, &default_patch[i][j * 2]);\n}\n\nstatic uint8_t table_initialized = 0;\n\nstatic void initializeTables() {\n  makeTllTable();\n  makeRksTable();\n  makeSinTable();\n  makeDefaultPatch();\n  table_initialized = 1;\n}\n\n/*********************************************************\n\n                      Synthesizing\n\n*********************************************************/\n#define SLOT_BD1 12\n#define SLOT_BD2 13\n#define SLOT_HH 14\n#define SLOT_SD 15\n#define SLOT_TOM 16\n#define SLOT_CYM 17\n\n/* utility macros */\n#define MOD(o, x) (&(o)->slot[(x) << 1])\n#define CAR(o, x) (&(o)->slot[((x) << 1) | 1])\n#define BIT(s, b) (((s) >> (b)) & 1)\n\n#if OPLL_DEBUG\nstatic void _debug_print_patch(OPLL_SLOT *slot) {\n  OPLL_PATCH *p = slot->patch;\n  printf(\"[slot#%d am:%d pm:%d eg:%d kr:%d ml:%d kl:%d tl:%d ws:%d fb:%d A:%d D:%d S:%d R:%d]\\n\", slot->number, //\n         p->AM, p->PM, p->EG, p->KR, p->ML,                                                                     //\n         p->KL, p->TL, p->WS, p->FB,                                                                            //\n         p->AR, p->DR, p->SL, p->RR);\n}\n\nstatic char *_debug_eg_state_name(OPLL_SLOT *slot) {\n  switch (slot->eg_state) {\n  case ATTACK:\n    return \"attack\";\n  case DECAY:\n    return \"decay\";\n  case SUSTAIN:\n    return \"sustain\";\n  case RELEASE:\n    return \"release\";\n  case DAMP:\n    return \"damp\";\n  default:\n    return \"unknown\";\n  }\n}\n\nstatic INLINE void _debug_print_slot_info(OPLL_SLOT *slot) {\n  char *name = _debug_eg_state_name(slot);\n  printf(\"[slot#%d state:%s fnum:%03x rate:%d-%d]\\n\", slot->number, name, slot->blk_fnum, slot->eg_rate_h,\n         slot->eg_rate_l);\n  _debug_print_patch(slot);\n  fflush(stdout);\n}\n#endif\n\nstatic INLINE int get_parameter_rate(OPLL_SLOT *slot) {\n\n  if ((slot->type & 1) == 0 && slot->key_flag == 0) {\n    return 0;\n  }\n\n  switch (slot->eg_state) {\n  case ATTACK:\n    return slot->patch->AR;\n  case DECAY:\n    return slot->patch->DR;\n  case SUSTAIN:\n    return slot->patch->EG ? 0 : slot->patch->RR;\n  case RELEASE:\n    if (slot->sus_flag) {\n      return 5;\n    } else if (slot->patch->EG) {\n      return slot->patch->RR;\n    } else {\n      return 7;\n    }\n  case DAMP:\n    return DAMPER_RATE;\n  default:\n    return 0;\n  }\n}\n\nenum SLOT_UPDATE_FLAG {\n  UPDATE_WS = 1,\n  UPDATE_TLL = 2,\n  UPDATE_RKS = 4,\n  UPDATE_EG = 8,\n  UPDATE_ALL = 255,\n};\n\nstatic INLINE void request_update(OPLL_SLOT *slot, int flag) { slot->update_requests |= flag; }\n\nstatic void commit_slot_update(OPLL_SLOT *slot) {\n\n#if OPLL_DEBUG\n  if (slot->last_eg_state != slot->eg_state) {\n    _debug_print_slot_info(slot);\n    slot->last_eg_state = slot->eg_state;\n  }\n#endif\n\n  if (slot->update_requests & UPDATE_WS) {\n    slot->wave_table = wave_table_map[slot->patch->WS];\n  }\n\n  if (slot->update_requests & UPDATE_TLL) {\n    if ((slot->type & 1) == 0) {\n      slot->tll = tll_table[slot->blk_fnum >> 5][slot->patch->TL][slot->patch->KL];\n    } else {\n      slot->tll = tll_table[slot->blk_fnum >> 5][slot->volume][slot->patch->KL];\n    }\n  }\n\n  if (slot->update_requests & UPDATE_RKS) {\n    slot->rks = rks_table[slot->blk_fnum >> 8][slot->patch->KR];\n  }\n\n  if (slot->update_requests & (UPDATE_RKS | UPDATE_EG)) {\n    int p_rate = get_parameter_rate(slot);\n\n    if (p_rate == 0) {\n      slot->eg_shift = 0;\n      slot->eg_rate_h = 0;\n      slot->eg_rate_l = 0;\n      return;\n    }\n\n    slot->eg_rate_h = min(15, p_rate + (slot->rks >> 2));\n    slot->eg_rate_l = slot->rks & 3;\n    if (slot->eg_state == ATTACK) {\n      slot->eg_shift = (0 < slot->eg_rate_h && slot->eg_rate_h < 12) ? (13 - slot->eg_rate_h) : 0;\n    } else {\n      slot->eg_shift = (slot->eg_rate_h < 13) ? (13 - slot->eg_rate_h) : 0;\n    }\n  }\n\n  slot->update_requests = 0;\n}\n\nstatic void reset_slot(OPLL_SLOT *slot, int number) {\n  slot->number = number;\n  slot->type = number % 2;\n  slot->pg_keep = 0;\n  slot->wave_table = wave_table_map[0];\n  slot->pg_phase = 0;\n  slot->output[0] = 0;\n  slot->output[1] = 0;\n  slot->eg_state = RELEASE;\n  slot->eg_shift = 0;\n  slot->rks = 0;\n  slot->tll = 0;\n  slot->key_flag = 0;\n  slot->sus_flag = 0;\n  slot->blk_fnum = 0;\n  slot->blk = 0;\n  slot->fnum = 0;\n  slot->volume = 0;\n  slot->pg_out = 0;\n  slot->eg_out = EG_MUTE;\n  slot->patch = &null_patch;\n}\n\nstatic INLINE void slotOn(OPLL *opll, int i) {\n  OPLL_SLOT *slot = &opll->slot[i];\n  slot->key_flag = 1;\n  slot->eg_state = DAMP;\n  request_update(slot, UPDATE_EG);\n}\n\nstatic INLINE void slotOff(OPLL *opll, int i) {\n  OPLL_SLOT *slot = &opll->slot[i];\n  slot->key_flag = 0;\n  if (slot->type & 1) {\n    slot->eg_state = RELEASE;\n    request_update(slot, UPDATE_EG);\n  }\n}\n\nstatic INLINE void update_key_status(OPLL *opll) {\n  const uint8_t r14 = opll->reg[0x0e];\n  const uint8_t rhythm_mode = BIT(r14, 5);\n  uint32_t new_slot_key_status = 0;\n  uint32_t updated_status;\n  int ch;\n\n  for (ch = 0; ch < 9; ch++)\n    if (opll->reg[0x20 + ch] & 0x10)\n      new_slot_key_status |= 3 << (ch * 2);\n\n  if (rhythm_mode) {\n    if (r14 & 0x10)\n      new_slot_key_status |= 3 << SLOT_BD1;\n\n    if (r14 & 0x01)\n      new_slot_key_status |= 1 << SLOT_HH;\n\n    if (r14 & 0x08)\n      new_slot_key_status |= 1 << SLOT_SD;\n\n    if (r14 & 0x04)\n      new_slot_key_status |= 1 << SLOT_TOM;\n\n    if (r14 & 0x02)\n      new_slot_key_status |= 1 << SLOT_CYM;\n  }\n\n  updated_status = opll->slot_key_status ^ new_slot_key_status;\n\n  if (updated_status) {\n    int i;\n    for (i = 0; i < 18; i++)\n      if (BIT(updated_status, i)) {\n        if (BIT(new_slot_key_status, i)) {\n          slotOn(opll, i);\n        } else {\n          slotOff(opll, i);\n        }\n      }\n  }\n\n  opll->slot_key_status = new_slot_key_status;\n}\n\nstatic INLINE void set_patch(OPLL *opll, int32_t ch, int32_t num) {\n  opll->patch_number[ch] = num;\n  MOD(opll, ch)->patch = &opll->patch[num * 2 + 0];\n  CAR(opll, ch)->patch = &opll->patch[num * 2 + 1];\n  request_update(MOD(opll, ch), UPDATE_ALL);\n  request_update(CAR(opll, ch), UPDATE_ALL);\n}\n\nstatic INLINE void set_sus_flag(OPLL *opll, int ch, int flag) {\n  CAR(opll, ch)->sus_flag = flag;\n  request_update(CAR(opll, ch), UPDATE_EG);\n  if (MOD(opll, ch)->type & 1) {\n    MOD(opll, ch)->sus_flag = flag;\n    request_update(MOD(opll, ch), UPDATE_EG);\n  }\n}\n\n/* set volume ( volume : 6bit, register value << 2 ) */\nstatic INLINE void set_volume(OPLL *opll, int ch, int volume) {\n  CAR(opll, ch)->volume = volume;\n  request_update(CAR(opll, ch), UPDATE_TLL);\n}\n\nstatic INLINE void set_slot_volume(OPLL_SLOT *slot, int volume) {\n  slot->volume = volume;\n  request_update(slot, UPDATE_TLL);\n}\n\n/* set f-Nnmber ( fnum : 9bit ) */\nstatic INLINE void set_fnumber(OPLL *opll, int ch, int fnum) {\n  OPLL_SLOT *car = CAR(opll, ch);\n  OPLL_SLOT *mod = MOD(opll, ch);\n  car->fnum = fnum;\n  car->blk_fnum = (car->blk_fnum & 0xe00) | (fnum & 0x1ff);\n  mod->fnum = fnum;\n  mod->blk_fnum = (mod->blk_fnum & 0xe00) | (fnum & 0x1ff);\n  request_update(car, UPDATE_EG | UPDATE_RKS | UPDATE_TLL);\n  request_update(mod, UPDATE_EG | UPDATE_RKS | UPDATE_TLL);\n}\n\n/* set block data (blk : 3bit ) */\nstatic INLINE void set_block(OPLL *opll, int ch, int blk) {\n  OPLL_SLOT *car = CAR(opll, ch);\n  OPLL_SLOT *mod = MOD(opll, ch);\n  car->blk = blk;\n  car->blk_fnum = ((blk & 7) << 9) | (car->blk_fnum & 0x1ff);\n  mod->blk = blk;\n  mod->blk_fnum = ((blk & 7) << 9) | (mod->blk_fnum & 0x1ff);\n  request_update(car, UPDATE_EG | UPDATE_RKS | UPDATE_TLL);\n  request_update(mod, UPDATE_EG | UPDATE_RKS | UPDATE_TLL);\n}\n\nstatic INLINE void update_rhythm_mode(OPLL *opll) {\n  const uint8_t new_rhythm_mode = (opll->reg[0x0e] >> 5) & 1;\n\n  if (opll->rhythm_mode != new_rhythm_mode) {\n\n    if (new_rhythm_mode) {\n      opll->slot[SLOT_HH].type = 3;\n      opll->slot[SLOT_HH].pg_keep = 1;\n      opll->slot[SLOT_SD].type = 3;\n      opll->slot[SLOT_TOM].type = 3;\n      opll->slot[SLOT_CYM].type = 3;\n      opll->slot[SLOT_CYM].pg_keep = 1;\n      set_patch(opll, 6, 16);\n      set_patch(opll, 7, 17);\n      set_patch(opll, 8, 18);\n      set_slot_volume(&opll->slot[SLOT_HH], ((opll->reg[0x37] >> 4) & 15) << 2);\n      set_slot_volume(&opll->slot[SLOT_TOM], ((opll->reg[0x38] >> 4) & 15) << 2);\n    } else {\n      opll->slot[SLOT_HH].type = 0;\n      opll->slot[SLOT_HH].pg_keep = 0;\n      opll->slot[SLOT_SD].type = 1;\n      opll->slot[SLOT_TOM].type = 0;\n      opll->slot[SLOT_CYM].type = 1;\n      opll->slot[SLOT_CYM].pg_keep = 0;\n      set_patch(opll, 6, opll->reg[0x36] >> 4);\n      set_patch(opll, 7, opll->reg[0x37] >> 4);\n      set_patch(opll, 8, opll->reg[0x38] >> 4);\n    }\n  }\n\n  opll->rhythm_mode = new_rhythm_mode;\n}\n\nstatic void update_ampm(OPLL *opll) {\n  if (opll->test_flag & 2) {\n    opll->pm_phase = 0;\n    opll->am_phase = 0;\n  } else {\n    opll->pm_phase += (opll->test_flag & 8) ? 1024 : 1;\n    opll->am_phase += (opll->test_flag & 8) ? 64 : 1;\n  }\n  opll->lfo_am = am_table[(opll->am_phase >> 6) % sizeof(am_table)];\n}\n\nstatic void update_noise(OPLL *opll, int cycle) {\n  int i;\n  for (i = 0; i < cycle; i++) {\n    if (opll->noise & 1) {\n      opll->noise ^= 0x800200;\n    }\n    opll->noise >>= 1;\n  }\n}\n\nstatic void update_short_noise(OPLL *opll) {\n  const uint32_t pg_hh = opll->slot[SLOT_HH].pg_out;\n  const uint32_t pg_cym = opll->slot[SLOT_CYM].pg_out;\n\n  const uint8_t h_bit2 = BIT(pg_hh, PG_BITS - 8);\n  const uint8_t h_bit7 = BIT(pg_hh, PG_BITS - 3);\n  const uint8_t h_bit3 = BIT(pg_hh, PG_BITS - 7);\n\n  const uint8_t c_bit3 = BIT(pg_cym, PG_BITS - 7);\n  const uint8_t c_bit5 = BIT(pg_cym, PG_BITS - 5);\n\n  opll->short_noise = (h_bit2 ^ h_bit7) | (h_bit3 ^ c_bit5) | (c_bit3 ^ c_bit5);\n}\n\nstatic INLINE void calc_phase(OPLL_SLOT *slot, int32_t pm_phase, uint8_t reset) {\n  const int8_t pm = slot->patch->PM ? pm_table[(slot->fnum >> 6) & 7][(pm_phase >> 10) & 7] : 0;\n  if (reset) {\n    slot->pg_phase = 0;\n  }\n  slot->pg_phase += (((slot->fnum & 0x1ff) * 2 + pm) * ml_table[slot->patch->ML]) << slot->blk >> 2;\n  slot->pg_phase &= (DP_WIDTH - 1);\n  slot->pg_out = slot->pg_phase >> DP_BASE_BITS;\n}\n\nstatic INLINE uint8_t lookup_attack_step(OPLL_SLOT *slot, uint32_t counter) {\n  int index;\n\n  switch (slot->eg_rate_h) {\n  case 12:\n    index = (counter & 0xc) >> 1;\n    return 4 - eg_step_tables[slot->eg_rate_l][index];\n  case 13:\n    index = (counter & 0xc) >> 1;\n    return 3 - eg_step_tables[slot->eg_rate_l][index];\n  case 14:\n    index = (counter & 0xc) >> 1;\n    return 2 - eg_step_tables[slot->eg_rate_l][index];\n  case 0:\n  case 15:\n    return 0;\n  default:\n    index = counter >> slot->eg_shift;\n    return eg_step_tables[slot->eg_rate_l][index & 7] ? 4 : 0;\n  }\n}\n\nstatic INLINE uint8_t lookup_decay_step(OPLL_SLOT *slot, uint32_t counter) {\n  int index;\n\n  switch (slot->eg_rate_h) {\n  case 0:\n    return 0;\n  case 13:\n    index = ((counter & 0xc) >> 1) | (counter & 1);\n    return eg_step_tables[slot->eg_rate_l][index];\n  case 14:\n    index = ((counter & 0xc) >> 1);\n    return eg_step_tables[slot->eg_rate_l][index] + 1;\n  case 15:\n    return 2;\n  default:\n    index = counter >> slot->eg_shift;\n    return eg_step_tables[slot->eg_rate_l][index & 7];\n  }\n}\n\nstatic INLINE void start_envelope(OPLL_SLOT *slot) {\n  if (min(15, slot->patch->AR + (slot->rks >> 2)) == 15) {\n    slot->eg_state = DECAY;\n    slot->eg_out = 0;\n  } else {\n    slot->eg_state = ATTACK;\n    slot->eg_out = EG_MUTE;\n  }\n  request_update(slot, UPDATE_EG);\n}\n\nstatic INLINE void calc_envelope(OPLL_SLOT *slot, OPLL_SLOT *buddy, uint16_t eg_counter, uint8_t test) {\n\n  uint32_t mask = (1 << slot->eg_shift) - 1;\n  uint8_t s;\n\n  if (slot->eg_state == ATTACK) {\n    if (0 < slot->eg_out && 0 < slot->eg_rate_h && (eg_counter & mask & ~3) == 0) {\n      s = lookup_attack_step(slot, eg_counter);\n      if (0 < s) {\n        slot->eg_out = max(0, ((int)slot->eg_out - (slot->eg_out >> s) - 1));\n      }\n    }\n  } else {\n    if (slot->eg_rate_h > 0 && (eg_counter & mask) == 0) {\n      slot->eg_out = min(EG_MUTE, slot->eg_out + lookup_decay_step(slot, eg_counter));\n    }\n  }\n\n  switch (slot->eg_state) {\n  case DAMP:\n    if (slot->eg_out >= EG_MUTE) {\n      start_envelope(slot);\n      if (slot->type & 1) {\n        if (!slot->pg_keep) {\n          slot->pg_phase = 0;\n        }\n        if (buddy && !buddy->pg_keep) {\n          buddy->pg_phase = 0;\n        }\n      }\n    }\n    break;\n\n  case ATTACK:\n    if (slot->eg_out == 0) {\n      slot->eg_state = DECAY;\n      request_update(slot, UPDATE_EG);\n    }\n    break;\n\n  case DECAY:\n    if ((slot->eg_out >> 3) == slot->patch->SL) {\n      slot->eg_state = SUSTAIN;\n      request_update(slot, UPDATE_EG);\n    }\n    break;\n\n  case SUSTAIN:\n  case RELEASE:\n  default:\n    break;\n  }\n\n  if (test) {\n    slot->eg_out = 0;\n  }\n}\n\nstatic void update_slots(OPLL *opll) {\n  int i;\n  opll->eg_counter++;\n\n  for (i = 0; i < 18; i++) {\n    OPLL_SLOT *slot = &opll->slot[i];\n    OPLL_SLOT *buddy = NULL;\n    if (slot->type == 0) {\n      buddy = &opll->slot[i + 1];\n    }\n    if (slot->type == 1) {\n      buddy = &opll->slot[i - 1];\n    }\n    if (slot->update_requests) {\n      commit_slot_update(slot);\n    }\n    calc_envelope(slot, buddy, opll->eg_counter, opll->test_flag & 1);\n    calc_phase(slot, opll->pm_phase, opll->test_flag & 4);\n  }\n}\n\n/* output: -4095...4095 */\nstatic INLINE int16_t lookup_exp_table(uint16_t i) {\n  /* from andete's expressoin */\n  int16_t t = (exp_table[(i & 0xff) ^ 0xff] + 1024);\n  int16_t res = t >> ((i & 0x7f00) >> 8);\n  return ((i & 0x8000) ? ~res : res) << 1;\n}\n\nstatic INLINE int16_t to_linear(uint16_t h, OPLL_SLOT *slot, int16_t am) {\n  uint16_t att;\n  if (slot->eg_out >= EG_MAX)\n    return 0;\n\n  att = min(EG_MAX, (slot->eg_out + slot->tll + am)) << 4;\n  return lookup_exp_table(h + att);\n}\n\nstatic INLINE int16_t calc_slot_car(OPLL *opll, int ch, int16_t fm) {\n  OPLL_SLOT *slot = CAR(opll, ch);\n\n  uint8_t am = slot->patch->AM ? opll->lfo_am : 0;\n\n  slot->output[1] = slot->output[0];\n  slot->output[0] = to_linear(slot->wave_table[(slot->pg_out + 2 * (fm >> 1)) & (PG_WIDTH - 1)], slot, am);\n\n  return slot->output[0];\n}\n\nstatic INLINE int16_t calc_slot_mod(OPLL *opll, int ch) {\n  OPLL_SLOT *slot = MOD(opll, ch);\n\n  int16_t fm = slot->patch->FB > 0 ? (slot->output[1] + slot->output[0]) >> (9 - slot->patch->FB) : 0;\n  uint8_t am = slot->patch->AM ? opll->lfo_am : 0;\n\n  slot->output[1] = slot->output[0];\n  slot->output[0] = to_linear(slot->wave_table[(slot->pg_out + fm) & (PG_WIDTH - 1)], slot, am);\n\n  return slot->output[0];\n}\n\nstatic INLINE int16_t calc_slot_tom(OPLL *opll) {\n  OPLL_SLOT *slot = MOD(opll, 8);\n\n  return to_linear(slot->wave_table[slot->pg_out], slot, 0);\n}\n\n/* Specify phase offset directly based on 10-bit (1024-length) sine table */\n#define _PD(phase) ((PG_BITS < 10) ? (phase >> (10 - PG_BITS)) : (phase << (PG_BITS - 10)))\n\nstatic INLINE int16_t calc_slot_snare(OPLL *opll) {\n  OPLL_SLOT *slot = CAR(opll, 7);\n\n  uint32_t phase;\n\n  if (BIT(slot->pg_out, PG_BITS - 2))\n    phase = (opll->noise & 1) ? _PD(0x300) : _PD(0x200);\n  else\n    phase = (opll->noise & 1) ? _PD(0x0) : _PD(0x100);\n\n  return to_linear(slot->wave_table[phase], slot, 0);\n}\n\nstatic INLINE int16_t calc_slot_cym(OPLL *opll) {\n  OPLL_SLOT *slot = CAR(opll, 8);\n\n  uint32_t phase = opll->short_noise ? _PD(0x300) : _PD(0x100);\n\n  return to_linear(slot->wave_table[phase], slot, 0);\n}\n\nstatic INLINE int16_t calc_slot_hat(OPLL *opll) {\n  OPLL_SLOT *slot = MOD(opll, 7);\n\n  uint32_t phase;\n\n  if (opll->short_noise)\n    phase = (opll->noise & 1) ? _PD(0x2d0) : _PD(0x234);\n  else\n    phase = (opll->noise & 1) ? _PD(0x34) : _PD(0xd0);\n\n  return to_linear(slot->wave_table[phase], slot, 0);\n}\n\n#define _MO(x) (-(x) >> 1)\n#define _RO(x) (x)\n\nstatic void update_output(OPLL *opll) {\n  int16_t *out;\n  int i;\n\n  update_ampm(opll);\n  update_short_noise(opll);\n  update_slots(opll);\n\n  out = opll->ch_out;\n\n  /* CH1-6 */\n  for (i = 0; i < 6; i++) {\n    if (!(opll->mask & OPLL_MASK_CH(i))) {\n      out[i] = _MO(calc_slot_car(opll, i, calc_slot_mod(opll, i)));\n    }\n  }\n\n  /* CH7 */\n  if (!opll->rhythm_mode) {\n    if (!(opll->mask & OPLL_MASK_CH(6))) {\n      out[6] = _MO(calc_slot_car(opll, 6, calc_slot_mod(opll, 6)));\n    }\n  } else {\n    if (!(opll->mask & OPLL_MASK_BD)) {\n      out[9] = _RO(calc_slot_car(opll, 6, calc_slot_mod(opll, 6)));\n    }\n  }\n  update_noise(opll, 14);\n\n  /* CH8 */\n  if (!opll->rhythm_mode) {\n    if (!(opll->mask & OPLL_MASK_CH(7))) {\n      out[7] = _MO(calc_slot_car(opll, 7, calc_slot_mod(opll, 7)));\n    }\n  } else {\n    if (!(opll->mask & OPLL_MASK_HH)) {\n      out[10] = _RO(calc_slot_hat(opll));\n    }\n    if (!(opll->mask & OPLL_MASK_SD)) {\n      out[11] = _RO(calc_slot_snare(opll));\n    }\n  }\n  update_noise(opll, 2);\n\n  /* CH9 */\n  if (!opll->rhythm_mode) {\n    if (!(opll->mask & OPLL_MASK_CH(8))) {\n      out[8] = _MO(calc_slot_car(opll, 8, calc_slot_mod(opll, 8)));\n    }\n  } else {\n    if (!(opll->mask & OPLL_MASK_TOM)) {\n      out[12] = _RO(calc_slot_tom(opll));\n    }\n    if (!(opll->mask & OPLL_MASK_CYM)) {\n      out[13] = _RO(calc_slot_cym(opll));\n    }\n  }\n  update_noise(opll, 2);\n}\n\nINLINE static void mix_output(OPLL *opll) {\n  int16_t out = 0;\n  int i;\n  for (i = 0; i < 14; i++) {\n    out += opll->ch_out[i];\n  }\n  if (opll->conv) {\n    OPLL_RateConv_putData(opll->conv, 0, out);\n  } else {\n    opll->mix_out[0] = out;\n  }\n}\n\nINLINE static void mix_output_stereo(OPLL *opll) {\n  int16_t *out = opll->mix_out;\n  int i;\n  out[0] = out[1] = 0;\n  for (i = 0; i < 14; i++) {\n    /* Maxim/Valley Bell: added stereo control (multiply each side by a float in opll->pan[ch][side]) */\n    if (opll->pan[i] & 2)\n      out[0] += (int16_t)(opll->ch_out[i] * opll->pan_fine[i][0]);\n    if (opll->pan[i] & 1)\n      out[1] += (int16_t)(opll->ch_out[i] * opll->pan_fine[i][1]);\n  }\n  if (opll->conv) {\n    OPLL_RateConv_putData(opll->conv, 0, out[0]);\n    OPLL_RateConv_putData(opll->conv, 1, out[1]);\n  }\n}\n\n/***********************************************************\n\n                   External Interfaces\n\n***********************************************************/\n\nOPLL *OPLL_new(uint32_t clk, uint32_t rate) {\n  OPLL *opll;\n  int i;\n\n  if (!table_initialized) {\n    initializeTables();\n  }\n\n  opll = (OPLL *)calloc(sizeof(OPLL), 1);\n  if (opll == NULL)\n    return NULL;\n\n  for (i = 0; i < 19 * 2; i++)\n    memcpy(&opll->patch[i], &null_patch, sizeof(OPLL_PATCH));\n\n  opll->clk = clk;\n  opll->rate = rate;\n  opll->mask = 0;\n  opll->conv = NULL;\n  opll->mix_out[0] = 0;\n  opll->mix_out[1] = 0;\n\n  OPLL_reset(opll);\n  OPLL_setChipType(opll, 0);\n  OPLL_resetPatch(opll, 0);\n  return opll;\n}\n\nvoid OPLL_delete(OPLL *opll) {\n  if (opll->conv) {\n    OPLL_RateConv_delete(opll->conv);\n    opll->conv = NULL;\n  }\n  free(opll);\n}\n\nstatic void reset_rate_conversion_params(OPLL *opll) {\n  const double f_out = opll->rate;\n  const double f_inp = opll->clk / 72;\n\n  opll->out_time = 0;\n  opll->out_step = ((uint32_t)f_inp) << 8;\n  opll->inp_step = ((uint32_t)f_out) << 8;\n\n  if (opll->conv) {\n    OPLL_RateConv_delete(opll->conv);\n    opll->conv = NULL;\n  }\n\n  if (floor(f_inp) != f_out && floor(f_inp + 0.5) != f_out) {\n    opll->conv = OPLL_RateConv_new(f_inp, f_out, 2);\n  }\n\n  if (opll->conv) {\n    OPLL_RateConv_reset(opll->conv);\n  }\n}\n\nvoid OPLL_reset(OPLL *opll) {\n  int i;\n\n  if (!opll)\n    return;\n\n  opll->adr = 0;\n\n  opll->pm_phase = 0;\n  opll->am_phase = 0;\n\n  opll->noise = 0x1;\n  opll->mask = 0;\n\n  opll->rhythm_mode = 0;\n  opll->slot_key_status = 0;\n  opll->eg_counter = 0;\n\n  reset_rate_conversion_params(opll);\n\n  for (i = 0; i < 18; i++)\n    reset_slot(&opll->slot[i], i);\n\n  for (i = 0; i < 9; i++) {\n    set_patch(opll, i, 0);\n  }\n\n  for (i = 0; i < 0x40; i++)\n    OPLL_writeReg(opll, i, 0);\n\n  for (i = 0; i < 15; i++) {\n    opll->pan[i] = 3;\n    centre_panning(opll->pan_fine[i]);\n  }\n\n  for (i = 0; i < 14; i++) {\n    opll->ch_out[i] = 0;\n  }\n}\n\nvoid OPLL_forceRefresh(OPLL *opll) {\n  int i;\n\n  if (opll == NULL)\n    return;\n\n  for (i = 0; i < 9; i++) {\n    set_patch(opll, i, opll->patch_number[i]);\n  }\n\n  for (i = 0; i < 18; i++) {\n    request_update(&opll->slot[i], UPDATE_ALL);\n  }\n}\n\nvoid OPLL_setRate(OPLL *opll, uint32_t rate) {\n  opll->rate = rate;\n  reset_rate_conversion_params(opll);\n}\n\nvoid OPLL_setQuality(OPLL *opll, uint8_t q) {}\n\nvoid OPLL_setChipType(OPLL *opll, uint8_t type) { opll->chip_type = type; }\n\nvoid OPLL_writeReg(OPLL *opll, uint32_t reg, uint8_t data) {\n  int ch, i;\n\n  if (reg >= 0x40)\n    return;\n\n  /* mirror registers */\n  if ((0x19 <= reg && reg <= 0x1f) || (0x29 <= reg && reg <= 0x2f) || (0x39 <= reg && reg <= 0x3f)) {\n    reg -= 9;\n  }\n\n  opll->reg[reg] = (uint8_t)data;\n\n  switch (reg) {\n  case 0x00:\n    opll->patch[0].AM = (data >> 7) & 1;\n    opll->patch[0].PM = (data >> 6) & 1;\n    opll->patch[0].EG = (data >> 5) & 1;\n    opll->patch[0].KR = (data >> 4) & 1;\n    opll->patch[0].ML = (data)&15;\n    for (i = 0; i < 9; i++) {\n      if (opll->patch_number[i] == 0) {\n        request_update(MOD(opll, i), UPDATE_RKS | UPDATE_EG);\n      }\n    }\n    break;\n\n  case 0x01:\n    opll->patch[1].AM = (data >> 7) & 1;\n    opll->patch[1].PM = (data >> 6) & 1;\n    opll->patch[1].EG = (data >> 5) & 1;\n    opll->patch[1].KR = (data >> 4) & 1;\n    opll->patch[1].ML = (data)&15;\n    for (i = 0; i < 9; i++) {\n      if (opll->patch_number[i] == 0) {\n        request_update(CAR(opll, i), UPDATE_RKS | UPDATE_EG);\n      }\n    }\n    break;\n\n  case 0x02:\n    opll->patch[0].KL = (data >> 6) & 3;\n    opll->patch[0].TL = (data)&63;\n    for (i = 0; i < 9; i++) {\n      if (opll->patch_number[i] == 0) {\n        request_update(MOD(opll, i), UPDATE_TLL);\n      }\n    }\n    break;\n\n  case 0x03:\n    opll->patch[1].KL = (data >> 6) & 3;\n    opll->patch[1].WS = (data >> 4) & 1;\n    opll->patch[0].WS = (data >> 3) & 1;\n    opll->patch[0].FB = (data)&7;\n    for (i = 0; i < 9; i++) {\n      if (opll->patch_number[i] == 0) {\n        request_update(MOD(opll, i), UPDATE_WS);\n        request_update(CAR(opll, i), UPDATE_WS | UPDATE_TLL);\n      }\n    }\n    break;\n\n  case 0x04:\n    opll->patch[0].AR = (data >> 4) & 15;\n    opll->patch[0].DR = (data)&15;\n    for (i = 0; i < 9; i++) {\n      if (opll->patch_number[i] == 0) {\n        request_update(MOD(opll, i), UPDATE_EG);\n      }\n    }\n    break;\n\n  case 0x05:\n    opll->patch[1].AR = (data >> 4) & 15;\n    opll->patch[1].DR = (data)&15;\n    for (i = 0; i < 9; i++) {\n      if (opll->patch_number[i] == 0) {\n        request_update(CAR(opll, i), UPDATE_EG);\n      }\n    }\n    break;\n\n  case 0x06:\n    opll->patch[0].SL = (data >> 4) & 15;\n    opll->patch[0].RR = (data)&15;\n    for (i = 0; i < 9; i++) {\n      if (opll->patch_number[i] == 0) {\n        request_update(MOD(opll, i), UPDATE_EG);\n      }\n    }\n    break;\n\n  case 0x07:\n    opll->patch[1].SL = (data >> 4) & 15;\n    opll->patch[1].RR = (data)&15;\n    for (i = 0; i < 9; i++) {\n      if (opll->patch_number[i] == 0) {\n        request_update(CAR(opll, i), UPDATE_EG);\n      }\n    }\n    break;\n\n  case 0x0e:\n    if (opll->chip_type == 1)\n      break;\n    update_rhythm_mode(opll);\n    update_key_status(opll);\n    break;\n\n  case 0x0f:\n    opll->test_flag = data;\n    break;\n\n  case 0x10:\n  case 0x11:\n  case 0x12:\n  case 0x13:\n  case 0x14:\n  case 0x15:\n  case 0x16:\n  case 0x17:\n  case 0x18:\n    ch = reg - 0x10;\n    set_fnumber(opll, ch, data + ((opll->reg[0x20 + ch] & 1) << 8));\n    break;\n\n  case 0x20:\n  case 0x21:\n  case 0x22:\n  case 0x23:\n  case 0x24:\n  case 0x25:\n  case 0x26:\n  case 0x27:\n  case 0x28:\n    ch = reg - 0x20;\n    set_fnumber(opll, ch, ((data & 1) << 8) + opll->reg[0x10 + ch]);\n    set_block(opll, ch, (data >> 1) & 7);\n    set_sus_flag(opll, ch, (data >> 5) & 1);\n    update_key_status(opll);\n    break;\n\n  case 0x30:\n  case 0x31:\n  case 0x32:\n  case 0x33:\n  case 0x34:\n  case 0x35:\n  case 0x36:\n  case 0x37:\n  case 0x38:\n    if ((opll->reg[0x0e] & 32) && (reg >= 0x36)) {\n      switch (reg) {\n      case 0x37:\n        set_slot_volume(MOD(opll, 7), ((data >> 4) & 15) << 2);\n        break;\n      case 0x38:\n        set_slot_volume(MOD(opll, 8), ((data >> 4) & 15) << 2);\n        break;\n      default:\n        break;\n      }\n    } else {\n      set_patch(opll, reg - 0x30, (data >> 4) & 15);\n    }\n    set_volume(opll, reg - 0x30, (data & 15) << 2);\n    break;\n\n  default:\n    break;\n  }\n}\n\nvoid OPLL_writeIO(OPLL *opll, uint32_t adr, uint8_t val) {\n  if (adr & 1)\n    OPLL_writeReg(opll, opll->adr, val);\n  else\n    opll->adr = val;\n}\n\nvoid OPLL_setPan(OPLL *opll, uint32_t ch, uint8_t pan) { opll->pan[ch & 15] = pan; }\n\nvoid OPLL_setPanEx(OPLL *opll, uint32_t ch, int16_t pan) {\n  calc_panning(opll->pan_fine[ch & 15], pan); // Maxim/Valley Bell\n}\n\nvoid OPLL_setPanFine(OPLL *opll, uint32_t ch, float pan[2]) {\n  opll->pan_fine[ch & 15][0] = pan[0];\n  opll->pan_fine[ch & 15][1] = pan[1];\n}\n\nvoid OPLL_dumpToPatch(const uint8_t *dump, OPLL_PATCH *patch) {\n  patch[0].AM = (dump[0] >> 7) & 1;\n  patch[1].AM = (dump[1] >> 7) & 1;\n  patch[0].PM = (dump[0] >> 6) & 1;\n  patch[1].PM = (dump[1] >> 6) & 1;\n  patch[0].EG = (dump[0] >> 5) & 1;\n  patch[1].EG = (dump[1] >> 5) & 1;\n  patch[0].KR = (dump[0] >> 4) & 1;\n  patch[1].KR = (dump[1] >> 4) & 1;\n  patch[0].ML = (dump[0]) & 15;\n  patch[1].ML = (dump[1]) & 15;\n  patch[0].KL = (dump[2] >> 6) & 3;\n  patch[1].KL = (dump[3] >> 6) & 3;\n  patch[0].TL = (dump[2]) & 63;\n  patch[1].TL = 0;\n  patch[0].FB = (dump[3]) & 7;\n  patch[1].FB = 0;\n  patch[0].WS = (dump[3] >> 3) & 1;\n  patch[1].WS = (dump[3] >> 4) & 1;\n  patch[0].AR = (dump[4] >> 4) & 15;\n  patch[1].AR = (dump[5] >> 4) & 15;\n  patch[0].DR = (dump[4]) & 15;\n  patch[1].DR = (dump[5]) & 15;\n  patch[0].SL = (dump[6] >> 4) & 15;\n  patch[1].SL = (dump[7] >> 4) & 15;\n  patch[0].RR = (dump[6]) & 15;\n  patch[1].RR = (dump[7]) & 15;\n}\n\nvoid OPLL_getDefaultPatch(int32_t type, int32_t num, OPLL_PATCH *patch) {\n  OPLL_dump2patch(default_inst[type] + num * 8, patch);\n}\n\nvoid OPLL_setPatch(OPLL *opll, const uint8_t *dump) {\n  OPLL_PATCH patch[2];\n  int i;\n  for (i = 0; i < 19; i++) {\n    OPLL_dump2patch(dump + i * 8, patch);\n    memcpy(&opll->patch[i * 2 + 0], &patch[0], sizeof(OPLL_PATCH));\n    memcpy(&opll->patch[i * 2 + 1], &patch[1], sizeof(OPLL_PATCH));\n  }\n}\n\nvoid OPLL_patchToDump(const OPLL_PATCH *patch, uint8_t *dump) {\n  dump[0] = (uint8_t)((patch[0].AM << 7) + (patch[0].PM << 6) + (patch[0].EG << 5) + (patch[0].KR << 4) + patch[0].ML);\n  dump[1] = (uint8_t)((patch[1].AM << 7) + (patch[1].PM << 6) + (patch[1].EG << 5) + (patch[1].KR << 4) + patch[1].ML);\n  dump[2] = (uint8_t)((patch[0].KL << 6) + patch[0].TL);\n  dump[3] = (uint8_t)((patch[1].KL << 6) + (patch[1].WS << 4) + (patch[0].WS << 3) + patch[0].FB);\n  dump[4] = (uint8_t)((patch[0].AR << 4) + patch[0].DR);\n  dump[5] = (uint8_t)((patch[1].AR << 4) + patch[1].DR);\n  dump[6] = (uint8_t)((patch[0].SL << 4) + patch[0].RR);\n  dump[7] = (uint8_t)((patch[1].SL << 4) + patch[1].RR);\n}\n\nvoid OPLL_copyPatch(OPLL *opll, int32_t num, OPLL_PATCH *patch) {\n  memcpy(&opll->patch[num], patch, sizeof(OPLL_PATCH));\n}\n\nvoid OPLL_resetPatch(OPLL *opll, uint8_t type) {\n  int i;\n  for (i = 0; i < 19 * 2; i++)\n    OPLL_copyPatch(opll, i, &default_patch[type % OPLL_TONE_NUM][i]);\n}\n\nint16_t OPLL_calc(OPLL *opll) {\n  while (opll->out_step > opll->out_time) {\n    opll->out_time += opll->inp_step;\n    update_output(opll);\n    mix_output(opll);\n  }\n  opll->out_time -= opll->out_step;\n  if (opll->conv) {\n    opll->mix_out[0] = OPLL_RateConv_getData(opll->conv, 0);\n  }\n  return opll->mix_out[0];\n}\n\nvoid OPLL_calcStereo(OPLL *opll, int32_t out[2]) {\n  while (opll->out_step > opll->out_time) {\n    opll->out_time += opll->inp_step;\n    update_output(opll);\n    mix_output_stereo(opll);\n  }\n  opll->out_time -= opll->out_step;\n  if (opll->conv) {\n    out[0] = OPLL_RateConv_getData(opll->conv, 0);\n    out[1] = OPLL_RateConv_getData(opll->conv, 1);\n  } else {\n    out[0] = opll->mix_out[0];\n    out[1] = opll->mix_out[1];\n  }\n}\n\nuint32_t OPLL_setMask(OPLL *opll, uint32_t mask) {\n  uint32_t ret;\n\n  if (opll) {\n    ret = opll->mask;\n    opll->mask = mask;\n    return ret;\n  } else\n    return 0;\n}\n\nuint32_t OPLL_toggleMask(OPLL *opll, uint32_t mask) {\n  uint32_t ret;\n\n  if (opll) {\n    ret = opll->mask;\n    opll->mask ^= mask;\n    return ret;\n  } else\n    return 0;\n}\n"
  },
  {
    "path": "VGMPlay/chips/emu2413.h",
    "content": "#ifndef _EMU2413_H_\n#define _EMU2413_H_\n\n#include \"emutypes.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define OPLL_DEBUG 0\n\nenum OPLL_TONE_ENUM { OPLL_2413_TONE = 0, OPLL_VRC7_TONE = 1, OPLL_281B_TONE = 2 };\n\n/* voice data */\ntypedef struct __OPLL_PATCH {\n  uint32_t TL, FB, EG, ML, AR, DR, SL, RR, KR, KL, AM, PM, WS;\n} OPLL_PATCH;\n\n/* slot */\ntypedef struct __OPLL_SLOT {\n  uint8_t number;\n\n  /* type flags:\n   * 000000SM\n   *       |+-- M: 0:modulator 1:carrier\n   *       +--- S: 0:normal 1:single slot mode (sd, tom, hh or cym)\n   */\n  uint8_t type;\n\n  OPLL_PATCH *patch; /* voice parameter */\n\n  /* slot output */\n  int32_t output[2]; /* output value, latest and previous. */\n\n  /* phase generator (pg) */\n  uint16_t *wave_table; /* wave table */\n  uint32_t pg_phase;    /* pg phase */\n  uint32_t pg_out;      /* pg output, as index of wave table */\n  uint8_t pg_keep;      /* if 1, pg_phase is preserved when key-on */\n  uint16_t blk_fnum;    /* (block << 9) | f-number */\n  uint16_t fnum;        /* f-number (9 bits) */\n  uint8_t blk;          /* block (3 bits) */\n\n  /* envelope generator (eg) */\n  uint8_t eg_state;  /* current state */\n  int32_t volume;    /* current volume */\n  uint8_t key_flag;  /* key-on flag 1:on 0:off */\n  uint8_t sus_flag;  /* key-sus option 1:on 0:off */\n  uint16_t tll;      /* total level + key scale level*/\n  uint8_t rks;       /* key scale offset (rks) for eg speed */\n  uint8_t eg_rate_h; /* eg speed rate high 4bits */\n  uint8_t eg_rate_l; /* eg speed rate low 2bits */\n  uint32_t eg_shift; /* shift for eg global counter, controls envelope speed */\n  uint32_t eg_out;   /* eg output */\n\n  uint32_t update_requests; /* flags to debounce update */\n\n#if OPLL_DEBUG\n  uint8_t last_eg_state;\n#endif\n} OPLL_SLOT;\n\n/* mask */\n#define OPLL_MASK_CH(x) (1 << (x))\n#define OPLL_MASK_HH (1 << (9))\n#define OPLL_MASK_CYM (1 << (10))\n#define OPLL_MASK_TOM (1 << (11))\n#define OPLL_MASK_SD (1 << (12))\n#define OPLL_MASK_BD (1 << (13))\n#define OPLL_MASK_RHYTHM (OPLL_MASK_HH | OPLL_MASK_CYM | OPLL_MASK_TOM | OPLL_MASK_SD | OPLL_MASK_BD)\n\n/* rate conveter */\ntypedef struct __OPLL_RateConv {\n  int ch;\n  double timer;\n  double f_ratio;\n  int16_t *sinc_table;\n  int16_t **buf;\n} OPLL_RateConv;\n\nOPLL_RateConv *OPLL_RateConv_new(double f_inp, double f_out, int ch);\nvoid OPLL_RateConv_reset(OPLL_RateConv *conv);\nvoid OPLL_RateConv_putData(OPLL_RateConv *conv, int ch, int16_t data);\nint16_t OPLL_RateConv_getData(OPLL_RateConv *conv, int ch);\nvoid OPLL_RateConv_delete(OPLL_RateConv *conv);\n\ntypedef struct __OPLL {\n  uint32_t clk;\n  uint32_t rate;\n\n  uint8_t chip_type;\n\n  uint32_t adr;\n\n  uint32_t inp_step;\n  uint32_t out_step;\n  uint32_t out_time;\n\n  uint8_t reg[0x40];\n  uint8_t test_flag;\n  uint32_t slot_key_status;\n  uint8_t rhythm_mode;\n\n  uint32_t eg_counter;\n\n  uint32_t pm_phase;\n  int32_t am_phase;\n\n  uint8_t lfo_am;\n\n  uint32_t noise;\n  uint8_t short_noise;\n\n  int32_t patch_number[9];\n  OPLL_SLOT slot[18];\n  OPLL_PATCH patch[19 * 2];\n\n  uint8_t pan[16];\n  float pan_fine[16][2];\n\n  uint32_t mask;\n\n  /* channel output */\n  /* 0..8:tone 9:bd 10:hh 11:sd 12:tom 13:cym */\n  int16_t ch_out[14];\n\n  int16_t mix_out[2];\n\n  OPLL_RateConv *conv;\n} OPLL;\n\nOPLL *OPLL_new(uint32_t clk, uint32_t rate);\nvoid OPLL_delete(OPLL *);\n\nvoid OPLL_reset(OPLL *);\nvoid OPLL_resetPatch(OPLL *, uint8_t);\n\n/**\n * Set output wave sampling rate.\n * @param rate sampling rate. If clock / 72 (typically 49716 or 49715 at 3.58MHz) is set, the internal rate converter is\n * disabled.\n */\nvoid OPLL_setRate(OPLL *opll, uint32_t rate);\n\n/**\n * Set internal calcuration quality. Currently no effects, just for compatibility.\n * >= v1.0.0 always synthesizes internal output at clock/72 Hz.\n */\nvoid OPLL_setQuality(OPLL *opll, uint8_t q);\n\n/**\n * Set pan pot (extra function - not YM2413 chip feature)\n * @param ch 0..8:tone 9:bd 10:hh 11:sd 12:tom 13:cym 14,15:reserved\n * @param pan 0:mute 1:right 2:left 3:center\n * ```\n * pan: 76543210\n *            |+- bit 1: enable Left output\n *            +-- bit 0: enable Right output\n * ```\n */\nvoid OPLL_setPan(OPLL *opll, uint32_t ch, uint8_t pan);\n\n/**\n * Set fine-grained panning\n * @param ch 0..8:tone 9:bd 10:hh 11:sd 12:tom 13:cym 14,15:reserved\n * @param pan output strength of left/right channel.\n *            pan[0]: left, pan[1]: right. pan[0]=pan[1]=1.0f for center.\n */\nvoid OPLL_setPanFine(OPLL *opll, uint32_t ch, float pan[2]);\n\n/**\n * Set chip type. If vrc7 is selected, r#14 is ignored.\n * This method not change the current ROM patch set.\n * To change ROM patch set, use OPLL_resetPatch.\n * @param type 0:YM2413 1:VRC7\n */\nvoid OPLL_setChipType(OPLL *opll, uint8_t type);\n\nvoid OPLL_writeIO(OPLL *opll, uint32_t reg, uint8_t val);\nvoid OPLL_writeReg(OPLL *opll, uint32_t reg, uint8_t val);\n\n/**\n * Calculate one sample\n */\nint16_t OPLL_calc(OPLL *opll);\n\n/**\n * Calulate stereo sample\n */\nvoid OPLL_calcStereo(OPLL *opll, int32_t out[2]);\n\nvoid OPLL_setPatch(OPLL *, const uint8_t *dump);\nvoid OPLL_copyPatch(OPLL *, int32_t, OPLL_PATCH *);\n\n/**\n * Force to refresh.\n * External program should call this function after updating patch parameters.\n */\nvoid OPLL_forceRefresh(OPLL *);\n\nvoid OPLL_dumpToPatch(const uint8_t *dump, OPLL_PATCH *patch);\nvoid OPLL_patchToDump(const OPLL_PATCH *patch, uint8_t *dump);\nvoid OPLL_getDefaultPatch(int32_t type, int32_t num, OPLL_PATCH *);\n\n/**\n *  Set channel mask\n *  @param mask mask flag: OPLL_MASK_* can be used.\n *  - bit 0..8: mask for ch 1 to 9 (OPLL_MASK_CH(i))\n *  - bit 9: mask for Hi-Hat (OPLL_MASK_HH)\n *  - bit 10: mask for Top-Cym (OPLL_MASK_CYM)\n *  - bit 11: mask for Tom (OPLL_MASK_TOM)\n *  - bit 12: mask for Snare Drum (OPLL_MASK_SD)\n *  - bit 13: mask for Bass Drum (OPLL_MASK_BD)\n */\nuint32_t OPLL_setMask(OPLL *, uint32_t mask);\n\n/**\n * Toggler channel mask flag\n */\nuint32_t OPLL_toggleMask(OPLL *, uint32_t mask);\n\n/* for compatibility */\n#define OPLL_set_rate OPLL_setRate\n#define OPLL_set_quality OPLL_setQuality\n#define OPLL_set_pan OPLL_setPan\n#define OPLL_set_pan_fine OPLL_setPanFine\n#define OPLL_calc_stereo OPLL_calcStereo\n#define OPLL_reset_patch OPLL_resetPatch\n#define OPLL_dump2patch OPLL_dumpToPatch\n#define OPLL_patch2dump OPLL_patchToDump\n#define OPLL_setChipMode OPLL_setChipType\n\n/* for vgmplay */\nvoid OPLL_setPanEx(OPLL *opll, uint32_t ch, int16_t pan);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "VGMPlay/chips/emu2413_NESpatches.txt",
    "content": "http://forums.nesdev.com/viewtopic.php?f=6&t=9141\n"
  },
  {
    "path": "VGMPlay/chips/emutypes.h",
    "content": "#ifndef _EMUTYPES_H_\n#define _EMUTYPES_H_\n\n#ifndef INLINE\n\n#if defined(_MSC_VER)\n//#define INLINE __forceinline\n#define INLINE __inline\n#elif defined(__GNUC__)\n#define INLINE __inline__\n#elif defined(_MWERKS_)\n#define INLINE inline\n#else\n#define INLINE\n#endif\n\n#endif\n\ntypedef unsigned int e_uint;\ntypedef signed int e_int;\n\ntypedef unsigned char e_uint8 ;\ntypedef signed char e_int8 ;\n\ntypedef unsigned short e_uint16 ;\ntypedef signed short e_int16 ;\n\ntypedef unsigned int e_uint32 ;\ntypedef signed int e_int32 ;\n\n\n#if !defined(__int8_t_defined) && !defined(_STDINT)\n#define __int8_t_defined\t// for GCC\n#define _STDINT\t// for MSVC\n\ntypedef e_uint8 uint8_t;\ntypedef e_int8 int8_t;\ntypedef e_uint16 uint16_t;\ntypedef e_int16 int16_t;\ntypedef e_uint32 uint32_t;\ntypedef e_int32 int32_t;\n#ifdef _MSC_VER\ntypedef unsigned __int64\t\t\t\t\tuint64_t;\ntypedef signed __int64\t\t\t\t\t\tint64_t;\n#else\n#include <stdint.h>\n#endif\n\n#endif\n\n\n#endif\n"
  },
  {
    "path": "VGMPlay/chips/es5503.c",
    "content": "/*\n\n  ES5503 - Ensoniq ES5503 \"DOC\" emulator v2.1.1\n  By R. Belmont.\n\n  Copyright R. Belmont.\n\n  This software is dual-licensed: it may be used in MAME and properly licensed\n  MAME derivatives under the terms of the MAME license.  For use outside of\n  MAME and properly licensed derivatives, it is available under the\n  terms of the GNU Lesser General Public License (LGPL), version 2.1.\n  You may read the LGPL at http://www.gnu.org/licenses/lgpl.html\n\n  History: the ES5503 was the next design after the famous C64 \"SID\" by Bob Yannes.\n  It powered the legendary Mirage sampler (the first affordable pro sampler) as well\n  as the ESQ-1 synth/sequencer.  The ES5505 (used in Taito's F3 System) and 5506\n  (used in the \"Soundscape\" series of ISA PC sound cards) followed on a fundamentally\n  similar architecture.\n\n  Bugs: On the real silicon, oscillators 30 and 31 have random volume fluctuations and are\n  unusable for playback.  We don't attempt to emulate that. :-)\n\n  Additionally, in \"swap\" mode, there's one cycle when the switch takes place where the\n  oscillator's output is 0x80 (centerline) regardless of the sample data.  This can\n  cause audible clicks and a general degradation of audio quality if the correct sample\n  data at that point isn't 0x80 or very near it.\n\n  Changes:\n  0.2 (RB) - improved behavior for volumes > 127, fixes missing notes in Nucleus & missing voices in Thexder\n  0.3 (RB) - fixed extraneous clicking, improved timing behavior for e.g. Music Construction Set & Music Studio\n  0.4 (RB) - major fixes to IRQ semantics and end-of-sample handling.\n  0.5 (RB) - more flexible wave memory hookup (incl. banking) and save state support.\n  1.0 (RB) - properly respects the input clock\n  2.0 (RB) - C++ conversion, more accurate oscillator IRQ timing\n  2.1 (RB) - Corrected phase when looping; synthLAB, Arkanoid, and Arkanoid II no longer go out of tune\n  2.1.1 (RB) - Fixed issue introduced in 2.0 where IRQs were delayed\n*/\n\n//#include \"emu.h\"\n//#include \"streams.h\"\n#include <stdlib.h>\n#include <string.h>\n#include \"mamedef.h\"\n#include \"es5503.h\"\n\ntypedef struct\n{\n\tUINT16 freq;\n\tUINT16 wtsize;\n\tUINT8  control;\n\tUINT8  vol;\n\tUINT8  data;\n\tUINT32 wavetblpointer;\n\tUINT8  wavetblsize;\n\tUINT8  resolution;\n\n\tUINT32 accumulator;\n\tUINT8  irqpend;\n\t\n\tUINT8  Muted;\n} ES5503Osc;\n\ntypedef struct\n{\n\tES5503Osc oscillators[32];\n\n\tUINT32 dramsize;\n\tUINT8 *docram;\n\n\t//sound_stream * stream;\n\n\t//void (*irq_callback)(running_device *, int);\t// IRQ callback\n\n\t//read8_device_func adc_read;\t\t// callback for the 5503's built-in analog to digital converter\n\n\tINT8  oscsenabled;\t\t// # of oscillators enabled\n\tint   rege0;\t\t\t// contents of register 0xe0\n\n\tUINT8 channel_strobe;\n\n\tUINT32 clock;\n\tint output_channels;\n\tint outchn_mask;\n\tUINT32 output_rate;\n\t//running_device *device;\n\t\n\tSRATE_CALLBACK SmpRateFunc;\n\tvoid* SmpRateData;\n} ES5503Chip;\n\n#define MAX_CHIPS\t0x02\nstatic ES5503Chip ES5503Data[MAX_CHIPS];\n\n/*INLINE ES5503Chip *get_safe_token(running_device *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == ES5503);\n\treturn (ES5503Chip *)downcast<legacy_device_base *>(device)->token();\n}*/\n\nstatic const UINT16 wavesizes[8] = { 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 };\nstatic const UINT32 wavemasks[8] = { 0x1ff00, 0x1fe00, 0x1fc00, 0x1f800, 0x1f000, 0x1e000, 0x1c000, 0x18000 };\nstatic const UINT32 accmasks[8]  = { 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff };\nstatic const int    resshifts[8] = { 9, 10, 11, 12, 13, 14, 15, 16 };\n\nenum\n{\n\tMODE_FREE = 0,\n\tMODE_ONESHOT = 1,\n\tMODE_SYNCAM = 2,\n\tMODE_SWAP = 3\n};\n\n// halt_osc: handle halting an oscillator\n// chip = chip ptr\n// onum = oscillator #\n// type = 1 for 0 found in sample data, 0 for hit end of table size\nstatic void es5503_halt_osc(ES5503Chip *chip, int onum, int type, UINT32 *accumulator, int resshift)\n{\n\tES5503Osc *pOsc = &chip->oscillators[onum];\n\tES5503Osc *pPartner = &chip->oscillators[onum^1];\n\tint mode = (pOsc->control>>1) & 3;\n\tint omode = (pPartner->control>>1) & 3;\n\n\t// if 0 found in sample data or mode is not free-run, halt this oscillator\n\tif ((mode != MODE_FREE) || (type != 0))\n\t{\n\t\tpOsc->control |= 1;\n\t}\n\telse    // preserve the relative phase of the oscillator when looping\n\t{\n\t\tUINT16 wtsize = pOsc->wtsize - 1;\n\t\tUINT32 altram = (*accumulator) >> resshift;\n\n\t\tif (altram > wtsize)\n\t\t{\n\t\t\taltram -= wtsize;\n\t\t}\n\t\telse\n\t\t{\n\t\t\taltram = 0;\n\t\t}\n\n\t\t*accumulator = altram << resshift;\n\t}\n\n\t// if swap mode, start the partner\n\t// Note: The swap mode fix breaks Silpheed and other games.\n\tif ((mode == MODE_SWAP) /*|| (omode == MODE_SWAP)*/)\n\t{\n\t\tpPartner->control &= ~1;\t// clear the halt bit\n\t\tpPartner->accumulator = 0;  // and make sure it starts from the top (does this also need phase preservation?)\n\t}\n\n\t// IRQ enabled for this voice?\n\tif (pOsc->control & 0x08)\n\t{\n\t\tpOsc->irqpend = 1;\n\n\t\t/*if (chip->irq_callback)\n\t\t{\n\t\t\tchip->irq_callback(chip->device, 1);\n\t\t}*/\n\t}\n}\n\n//static STREAM_UPDATE( es5503_pcm_update )\nvoid es5503_pcm_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t// Note: The advantage of NOT using this buffer is not only less RAM usage,\n\t//       but also a huge speedup. This is, because the array is not marked\n\t//       as 'static' and thus re-allocated for every single call.\n\t//INT32 mix[48000*2];\n\t//INT32 *mixp;\n\tint osc, snum;\n\tUINT32 ramptr;\n\t//ES5503Chip *chip = (ES5503Chip *)param;\n\tES5503Chip *chip = &ES5503Data[ChipID];\n\tint chnsStereo, chan;\n\n\tmemset(outputs[0], 0x00, samples * sizeof(stream_sample_t));\n\tmemset(outputs[1], 0x00, samples * sizeof(stream_sample_t));\n\t//memset(mix, 0, sizeof(mix));\n\n\tchnsStereo = chip->output_channels & ~1;\n\tfor (osc = 0; osc < chip->oscsenabled; osc++)\n\t{\n\t\tES5503Osc *pOsc = &chip->oscillators[osc];\n\n\t\tif (!(pOsc->control & 1) && ! pOsc->Muted)\n\t\t{\n\t\t\tUINT32 wtptr = pOsc->wavetblpointer & wavemasks[pOsc->wavetblsize], altram;\n\t\t\tUINT32 acc = pOsc->accumulator;\n\t\t\tUINT16 wtsize = pOsc->wtsize - 1;\n\t\t\t//UINT8 ctrl = pOsc->control;\n\t\t\tUINT16 freq = pOsc->freq;\n\t\t\tINT16 vol = pOsc->vol;\n\t\t\t//INT8 data = -128;\n\t\t\tUINT8 chnMask = (pOsc->control >> 4) & 0x0F;\n\t\t\tint resshift = resshifts[pOsc->resolution] - pOsc->wavetblsize;\n\t\t\tUINT32 sizemask = accmasks[pOsc->wavetblsize];\n\t\t\tINT32 outData;\n\t\t\t//mixp = &mix[0] + chan;\n\n\t\t\tchnMask &= chip->outchn_mask;\n\t\t\tfor (snum = 0; snum < samples; snum++)\n\t\t\t{\n\t\t\t\taltram = acc >> resshift;\n\t\t\t\tramptr = altram & sizemask;\n\n\t\t\t\tacc += freq;\n\n\t\t\t\t// channel strobe is always valid when reading; this allows potentially banking per voice\n\t\t\t\t//chip->channel_strobe = (pOsc->control>>4) & 0xf;\n\t\t\t\t//data = (INT32)chip->docram[ramptr + wtptr] ^ 0x80;\n\t\t\t\tpOsc->data = chip->docram[ramptr + wtptr];\n\n\t\t\t\tif (pOsc->data == 0x00)\n\t\t\t\t{\n\t\t\t\t\tes5503_halt_osc(chip, osc, 1, &acc, resshift);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\toutData = (pOsc->data - 0x80) * vol;\n\t\t\t\t\t//*mixp += outData;\n\t\t\t\t\t//mixp += output_channels;\n\t\t\t\t\t\n\t\t\t\t\t// send groups of 2 channels to L or R\n\t\t\t\t\tfor (chan = 0; chan < chnsStereo; chan ++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (chan == chnMask)\n\t\t\t\t\t\t\toutputs[chan & 1][snum] += outData;\n\t\t\t\t\t}\n\t\t\t\t\toutData = (outData * 181) >> 8;\t// outData *= sqrt(2)\n\t\t\t\t\t// send remaining channels to L+R\n\t\t\t\t\tfor (; chan < chip->output_channels; chan ++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (chan == chnMask)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toutputs[0][snum] += outData;\n\t\t\t\t\t\t\toutputs[1][snum] += outData;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (altram >= wtsize)\n\t\t\t\t\t{\n\t\t\t\t\t\tes5503_halt_osc(chip, osc, 0, &acc, resshift);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if oscillator halted, we've got no more samples to generate\n\t\t\t\tif (pOsc->control & 1)\n\t\t\t\t{\n\t\t\t\t\t//pOsc->control |= 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//pOsc->control = ctrl;\n\t\t\tpOsc->accumulator = acc;\n\t\t\t//pOsc->data = data ^ 0x80;\n\t\t}\n\t}\n\n/*\tmixp = &mix[0];\n\tfor (i = 0; i < samples; i++)\n\t\tfor (int chan = 0; chan < output_channels; chan++)\n\t\t\toutputs[chan][i] = (*mixp++)>>1;*/\n}\n\n\n//static DEVICE_START( es5503 )\nint device_start_es5503(UINT8 ChipID, int clock, int channels)\n{\n\t//const es5503_interface *intf;\n\tint osc;\n\t//ES5503Chip *chip = get_safe_token(device);\n\tES5503Chip *chip;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &ES5503Data[ChipID];\n\t\n\t//intf = (const es5503_interface *)device->baseconfig().static_config();\n\n\t//chip->irq_callback = intf->irq_callback;\n\t//chip->adc_read = intf->adc_read;\n\t//chip->docram = intf->wave_memory;\n\tchip->dramsize = 0x20000;\t// 128 KB\n\tchip->docram = (UINT8*)malloc(chip->dramsize);\n\t//chip->clock = device->clock();\n\t//chip->device = device;\n\tchip->clock = clock;\n\n\tchip->output_channels = channels;\n\tchip->outchn_mask = 1;\n\twhile(chip->outchn_mask < chip->output_channels)\n\t\tchip->outchn_mask <<= 1;\n\tchip->outchn_mask --;\n\tchip->rege0 = 0xff;\n\n\t/*for (osc = 0; osc < 32; osc++)\n\t{\n\t\tstate_save_register_device_item(device, osc, chip->oscillators[osc].freq);\n\t\tstate_save_register_device_item(device, osc, chip->oscillators[osc].wtsize);\n\t\tstate_save_register_device_item(device, osc, chip->oscillators[osc].control);\n\t\tstate_save_register_device_item(device, osc, chip->oscillators[osc].vol);\n\t\tstate_save_register_device_item(device, osc, chip->oscillators[osc].data);\n\t\tstate_save_register_device_item(device, osc, chip->oscillators[osc].wavetblpointer);\n\t\tstate_save_register_device_item(device, osc, chip->oscillators[osc].wavetblsize);\n\t\tstate_save_register_device_item(device, osc, chip->oscillators[osc].resolution);\n\t\tstate_save_register_device_item(device, osc, chip->oscillators[osc].accumulator);\n\t\tstate_save_register_device_item(device, osc, chip->oscillators[osc].irqpend);\n\t}*/\n\n\t//chip->output_rate = (device->clock()/8)/34;\t// (input clock / 8) / # of oscs. enabled + 2\n\t//chip->stream = stream_create(device, 0, 2, chip->output_rate, chip, es5503_pcm_update);\n\tchip->output_rate = (chip->clock/8)/34;\t// (input clock / 8) / # of oscs. enabled + 2\n\t\n\tfor (osc = 0; osc < 32; osc ++)\n\t\tchip->oscillators[osc].Muted = 0x00;\n\t\n\treturn chip->output_rate;\n}\n\nvoid device_stop_es5503(UINT8 ChipID)\n{\n\tES5503Chip *chip = &ES5503Data[ChipID];\n\t\n\tfree(chip->docram);\tchip->docram = NULL;\n\t\n\treturn;\n}\n\nvoid device_reset_es5503(UINT8 ChipID)\n{\n\tES5503Chip *chip = &ES5503Data[ChipID];\n\tint osc;\n\tES5503Osc* tempOsc;\n\t\n\tfor (osc = 0; osc < 32; osc++)\n\t{\n\t\ttempOsc = &chip->oscillators[osc];\n\t\ttempOsc->freq = 0;\n\t\ttempOsc->wtsize = 0;\n\t\ttempOsc->control = 0;\n\t\ttempOsc->vol = 0;\n\t\ttempOsc->data = 0x80;\n\t\ttempOsc->wavetblpointer = 0;\n\t\ttempOsc->wavetblsize = 0;\n\t\ttempOsc->resolution = 0;\n\t\ttempOsc->accumulator = 0;\n\t\ttempOsc->irqpend = 0;\n\t}\n\t\n\tchip->oscsenabled = 1;\n\t\n\tchip->channel_strobe = 0;\n\tmemset(chip->docram, 0x00, chip->dramsize);\n\t\n\tchip->output_rate = (chip->clock/8)/(2+chip->oscsenabled);\t// (input clock / 8) / # of oscs. enabled + 2\n\tif (chip->SmpRateFunc != NULL)\n\t\tchip->SmpRateFunc(chip->SmpRateData, chip->output_rate);\n\t\n\treturn;\n}\n\n\n//READ8_DEVICE_HANDLER( es5503_r )\nUINT8 es5503_r(UINT8 ChipID, offs_t offset)\n{\n\tUINT8 retval;\n\tint i;\n\t//ES5503Chip *chip = get_safe_token(device);\n\tES5503Chip *chip = &ES5503Data[ChipID];\n\n\t//stream_update(chip->stream);\n\n\tif (offset < 0xe0)\n\t{\n\t\tint osc = offset & 0x1f;\n\n\t\tswitch(offset & 0xe0)\n\t\t{\n\t\t\tcase 0:\t\t// freq lo\n\t\t\t\treturn (chip->oscillators[osc].freq & 0xff);\n\n\t\t\tcase 0x20:  \t// freq hi\n\t\t\t\treturn (chip->oscillators[osc].freq >> 8);\n\n\t\t\tcase 0x40:\t// volume\n\t\t\t\treturn chip->oscillators[osc].vol;\n\n\t\t\tcase 0x60:\t// data\n\t\t\t\treturn chip->oscillators[osc].data;\n\n\t\t\tcase 0x80:\t// wavetable pointer\n\t\t\t\treturn (chip->oscillators[osc].wavetblpointer>>8) & 0xff;\n\n\t\t\tcase 0xa0:\t// oscillator control\n\t\t\t\treturn chip->oscillators[osc].control;\n\n\t\t\tcase 0xc0:\t// bank select / wavetable size / resolution\n\t\t\t\tretval = 0;\n\t\t\t\tif (chip->oscillators[osc].wavetblpointer & 0x10000)\n\t\t\t\t{\n\t\t\t\t\tretval |= 0x40;\n\t\t\t\t}\n\n\t\t\t\tretval |= (chip->oscillators[osc].wavetblsize<<3);\n\t\t\t\tretval |= chip->oscillators[osc].resolution;\n\t\t\t\treturn retval;\n\t\t}\n\t}\n\telse\t // global registers\n\t{\n\t\tswitch (offset)\n\t\t{\n\t\t\tcase 0xe0:\t// interrupt status\n\t\t\t\tretval = chip->rege0;\n\n\t\t\t\t//m_irq_func(0);\n\n\t\t\t\t// scan all oscillators\n\t\t\t\tfor (i = 0; i < chip->oscsenabled; i++)\n\t\t\t\t{\n\t\t\t\t\tif (chip->oscillators[i].irqpend)\n\t\t\t\t\t{\n\t\t\t\t\t\t// signal this oscillator has an interrupt\n\t\t\t\t\t\tretval = i<<1;\n\n\t\t\t\t\t\tchip->rege0 = retval | 0x80;\n\n\t\t\t\t\t\t// and clear its flag\n\t\t\t\t\t\tchip->oscillators[i].irqpend = 0;\n\n\t\t\t\t\t\t/*if (chip->irq_callback)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tchip->irq_callback(chip->device, 0);\n\t\t\t\t\t\t}*/\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if any oscillators still need to be serviced, assert IRQ again immediately\n\t\t\t\t/*for (i = 0; i < chip->oscsenabled; i++)\n\t\t\t\t{\n\t\t\t\t\tif (chip->oscillators[i].irqpend)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (chip->irq_callback)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tchip->irq_callback(chip->device, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}*/\n\n\t\t\t\treturn retval;\n\n\t\t\tcase 0xe1:\t// oscillator enable\n\t\t\t\treturn (chip->oscsenabled-1)<<1;\n\n\t\t\tcase 0xe2:\t// A/D converter\n\t\t\t\t/*if (chip->adc_read)\n\t\t\t\t{\n\t\t\t\t\treturn chip->adc_read(chip->device, 0);\n\t\t\t\t}*/\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\n//WRITE8_DEVICE_HANDLER( es5503_w )\nvoid es5503_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//ES5503Chip *chip = get_safe_token(device);\n\tES5503Chip *chip = &ES5503Data[ChipID];\n\n\t//stream_update(chip->stream);\n\n\tif (offset < 0xe0)\n\t{\n\t\tint osc = offset & 0x1f;\n\n\t\tswitch(offset & 0xe0)\n\t\t{\n\t\t\tcase 0:\t\t// freq lo\n\t\t\t\tchip->oscillators[osc].freq &= 0xff00;\n\t\t\t\tchip->oscillators[osc].freq |= data;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x20:  \t// freq hi\n\t\t\t\tchip->oscillators[osc].freq &= 0x00ff;\n\t\t\t\tchip->oscillators[osc].freq |= (data<<8);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x40:\t// volume\n\t\t\t\tchip->oscillators[osc].vol = data;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x60:\t// data - ignore writes\n\t\t\t\tbreak;\n\n\t\t\tcase 0x80:\t// wavetable pointer\n\t\t\t\tchip->oscillators[osc].wavetblpointer = (data<<8);\n\t\t\t\tbreak;\n\n\t\t\tcase 0xa0:\t// oscillator control\n\t\t\t\t// if a fresh key-on, reset the ccumulator\n\t\t\t\tif ((chip->oscillators[osc].control & 1) && (!(data&1)))\n\t\t\t\t{\n\t\t\t\t\tchip->oscillators[osc].accumulator = 0;\n\t\t\t\t}\n\n\t\t\t\tchip->oscillators[osc].control = data;\n\t\t\t\tbreak;\n\n\t\t\tcase 0xc0:\t// bank select / wavetable size / resolution\n\t\t\t\tif (data & 0x40)\t// bank select - not used on the Apple IIgs\n\t\t\t\t{\n\t\t\t\t\tchip->oscillators[osc].wavetblpointer |= 0x10000;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tchip->oscillators[osc].wavetblpointer &= 0xffff;\n\t\t\t\t}\n\n\t\t\t\tchip->oscillators[osc].wavetblsize = ((data>>3) & 7);\n\t\t\t\tchip->oscillators[osc].wtsize = wavesizes[chip->oscillators[osc].wavetblsize];\n\t\t\t\tchip->oscillators[osc].resolution = (data & 7);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\telse\t // global registers\n\t{\n\t\tswitch (offset)\n\t\t{\n\t\t\tcase 0xe0:\t// interrupt status\n\t\t\t\tbreak;\n\n\t\t\tcase 0xe1:\t// oscillator enable\n\t\t\t\tchip->oscsenabled = 1 + ((data>>1) & 0x1f);\n\n\t\t\t\tchip->output_rate = (chip->clock/8)/(2+chip->oscsenabled);\n\t\t\t\t//stream_set_sample_rate(chip->stream, chip->output_rate);\n\t\t\t\tif (chip->SmpRateFunc != NULL)\n\t\t\t\t\tchip->SmpRateFunc(chip->SmpRateData, chip->output_rate);\n\t\t\t\tbreak;\n\n\t\t\tcase 0xe2:\t// A/D converter\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/*void es5503_set_base(running_device *device, UINT8 *wavemem)\n{\n\tES5503Chip *chip = get_safe_token(device);\n\n\tchip->docram = wavemem;\n}*/\n\nvoid es5503_write_ram(UINT8 ChipID, offs_t DataStart, offs_t DataLength, const UINT8* RAMData)\n{\n\tES5503Chip *chip = &ES5503Data[ChipID];\n\t\n\tif (DataStart >= chip->dramsize)\n\t\treturn;\n\tif (DataStart + DataLength > chip->dramsize)\n\t\tDataLength = chip->dramsize - DataStart;\n\t\n\tmemcpy(chip->docram + DataStart, RAMData, DataLength);\n\t\n\treturn;\n}\n\nvoid es5503_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tES5503Chip *chip = &ES5503Data[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 32; CurChn ++)\n\t\tchip->oscillators[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\nvoid es5503_set_srchg_cb(UINT8 ChipID, SRATE_CALLBACK CallbackFunc, void* DataPtr)\n{\n\tES5503Chip *chip = &ES5503Data[ChipID];\n\t\n\t// set Sample Rate Change Callback routine\n\tchip->SmpRateFunc = CallbackFunc;\n\tchip->SmpRateData = DataPtr;\n\t\n\treturn;\n}\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( es5503 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ES5503Chip);\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions --- //\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( es5503 );\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing //\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// Nothing //\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"ES5503\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Ensoniq ES550x\");\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright R. Belmont\");\t\tbreak;\n\t}\n}\n\n\nDEFINE_LEGACY_SOUND_DEVICE(ES5503, es5503);*/\n"
  },
  {
    "path": "VGMPlay/chips/es5503.h",
    "content": "#pragma once\n\n#ifndef __ES5503_H__\n#define __ES5503_H__\n\n///#include \"devlegcy.h\"\n\n/*typedef struct _es5503_interface es5503_interface;\nstruct _es5503_interface\n{\n\tvoid (*irq_callback)(running_device *device, int state);\n\tread8_device_func adc_read;\n\tUINT8 *wave_memory;\n};*/\n\n//READ8_DEVICE_HANDLER( es5503_r );\n//WRITE8_DEVICE_HANDLER( es5503_w );\nvoid es5503_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 es5503_r(UINT8 ChipID, offs_t offset);\n\nvoid es5503_pcm_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_es5503(UINT8 ChipID, int clock, int channels);\nvoid device_stop_es5503(UINT8 ChipID);\nvoid device_reset_es5503(UINT8 ChipID);\n//void es5503_set_base(running_device *device, UINT8 *wavemem);\n\nvoid es5503_write_ram(UINT8 ChipID, offs_t DataStart, offs_t DataLength, const UINT8* RAMData);\n\nvoid es5503_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\nvoid es5503_set_srchg_cb(UINT8 ChipID, SRATE_CALLBACK CallbackFunc, void* DataPtr);\n\n//DECLARE_LEGACY_SOUND_DEVICE(ES5503, es5503);\n\n#endif /* __ES5503_H__ */\n"
  },
  {
    "path": "VGMPlay/chips/es5506.c",
    "content": "/**********************************************************************************************\n\n     Ensoniq ES5505/6 driver\n     by Aaron Giles\n\nEnsoniq OTIS - ES5505                                            Ensoniq OTTO - ES5506\n\n  OTIS is a VLSI device designed in a 2 micron double metal        OTTO is a VLSI device designed in a 1.5 micron double metal\n   CMOS process. The device is the next generation of audio         CMOS process. The device is the next generation of audio\n   technology from ENSONIQ. This new chip achieves a new            technology from ENSONIQ. All calculations in the device are\n   level of audio fidelity performance. These improvements          made with at least 18-bit accuracy.\n   are achieved through the use of frequency interpolation\n   and on board real time digital filters. All calculations       The major features of OTTO are:\n   in the device are made with at least 16 bit accuracy.           - 68 pin PLCC package\n                                                                   - On chip real time digital filters\n The major features of OTIS are:                                   - Frequency interpolation\n  - 48 Pin dual in line package                                    - 32 independent voices\n  - On chip real time digital filters                              - Loop start and stop posistions for each voice\n  - Frequency interpolation                                        - Bidirectional and reverse looping\n  - 32 independent voices (up from 25 in DOCII)                    - 68000 compatibility for asynchronous bus communication\n  - Loop start and stop positions for each voice                   - separate host and sound memory interface\n  - Bidirectional and reverse looping                              - 6 channel stereo serial communication port\n  - 68000 compatibility for asynchronous bus communication         - Programmable clocks for defining serial protocol\n  - On board pulse width modulation D to A                         - Internal volume multiplication and stereo panning\n  - 4 channel stereo serial communication port                     - A to D input for pots and wheels\n  - Internal volume multiplication and stereo panning              - Hardware support for envelopes\n  - A to D input for pots and wheels                               - Support for dual OTTO systems\n  - Up to 10MHz operation                                          - Optional compressed data format for sample data\n                                                                   - Up to 16MHz operation\n              ______    ______\n            _|o     \\__/      |_\n A17/D13 - |_|1             48|_| - VSS                                                           A A A A A A\n            _|                |_                                                                  2 1 1 1 1 1 A\n A18/D14 - |_|2             47|_| - A16/D12                                                       0 9 8 7 6 5 1\n            _|                |_                                                                  / / / / / / 4\n A19/D15 - |_|3             46|_| - A15/D11                                   H H H H H H H V V H D D D D D D /\n            _|                |_                                              D D D D D D D S D D 1 1 1 1 1 1 D\n      BS - |_|4             45|_| - A14/D10                                   0 1 2 3 4 5 6 S D 7 5 4 3 2 1 0 9\n            _|                |_                                             ------------------------------------+\n  PWZERO - |_|5             44|_| - A13/D9                                  / 9 8 7 6 5 4 3 2 1 6 6 6 6 6 6 6 6  |\n            _|                |_                                           /                    8 7 6 5 4 3 2 1  |\n    SER0 - |_|6             43|_| - A12/D8                                |                                      |\n            _|       E        |_                                      SER0|10                                  60|A13/D8\n    SER1 - |_|7      N      42|_| - A11/D7                            SER1|11                                  59|A12/D7\n            _|       S        |_                                      SER2|12                                  58|A11/D6\n    SER2 - |_|8      O      41|_| - A10/D6                            SER3|13              ENSONIQ             57|A10/D5\n            _|       N        |_                                      SER4|14                                  56|A9/D4\n    SER3 - |_|9      I      40|_| - A9/D5                             SER5|15                                  55|A8/D3\n            _|       Q        |_                                      WCLK|16                                  54|A7/D2\n SERWCLK - |_|10            39|_| - A8/D4                            LRCLK|17               ES5506             53|A6/D1\n            _|                |_                                      BCLK|18                                  52|A5/D0\n   SERLR - |_|11            38|_| - A7/D3                             RESB|19                                  51|A4\n            _|                |_                                       HA5|20                                  50|A3\n SERBCLK - |_|12     E      37|_| - A6/D2                              HA4|21                OTTO              49|A2\n            _|       S        |_                                       HA3|22                                  48|A1\n     RLO - |_|13     5      36|_| - A5/D1                              HA2|23                                  47|A0\n            _|       5        |_                                       HA1|24                                  46|BS1\n     RHI - |_|14     0      35|_| - A4/D0                              HA0|25                                  45|BS0\n            _|       5        |_                                    POT_IN|26                                  44|DTACKB\n     LLO - |_|15            34|_| - CLKIN                                 |   2 2 2 3 3 3 3 3 3 3 3 3 3 4 4 4 4  |\n            _|                |_                                          |   7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3  |\n     LHI - |_|16            33|_| - CAS                                   +--------------------------------------+\n            _|                |_                                              B E E B E B B D S B B B E K B W W\n     POT - |_|17     O      32|_| - AMUX                                      S B L N L S S D S S X S   L Q / /\n            _|       T        |_                                              E E R E H M C V V A U A   C R R R\n   DTACK - |_|18     I      31|_| - RAS                                       R R D H           R M C     I M\n            _|       S        |_                                              _ D                 A\n     R/W - |_|19            30|_| - E                                         T\n            _|                |_                                              O\n      MS - |_|20            29|_| - IRQ                                       P\n            _|                |_\n      CS - |_|21            28|_| - A3\n            _|                |_\n     RES - |_|22            27|_| - A2\n            _|                |_\n     VSS - |_|23            26|_| - A1\n            _|                |_\n     VDD - |_|24            25|_| - A0\n             |________________|\n\n***********************************************************************************************/\n\n//#include \"emu.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include \"mamedef.h\"\n#include \"es5506.h\"\n\n\n\n/**********************************************************************************************\n\n     CONSTANTS\n\n***********************************************************************************************/\n\n#define LOG_COMMANDS\t\t\t0\n#define RAINE_CHECK\t\t\t\t0\n#define MAKE_WAVS\t\t\t\t0\n\n#if MAKE_WAVS\n#include \"wavwrite.h\"\n#endif\n\n#define ACCESSING_BITS_0_7\t(  byteOfs)\n#define ACCESSING_BITS_8_15\t(! byteOfs)\n\n\n#define MAX_SAMPLE_CHUNK\t\t10000\n#define ULAW_MAXBITS\t\t\t8\n\n#define CONTROL_BS1\t\t\t\t0x8000\n#define CONTROL_BS0\t\t\t\t0x4000\n#define CONTROL_CMPD\t\t\t0x2000\n#define CONTROL_CA2\t\t\t\t0x1000\n#define CONTROL_CA1\t\t\t\t0x0800\n#define CONTROL_CA0\t\t\t\t0x0400\n#define CONTROL_LP4\t\t\t\t0x0200\n#define CONTROL_LP3\t\t\t\t0x0100\n#define CONTROL_IRQ\t\t\t\t0x0080\n#define CONTROL_DIR\t\t\t\t0x0040\n#define CONTROL_IRQE\t\t\t0x0020\n#define CONTROL_BLE\t\t\t\t0x0010\n#define CONTROL_LPE\t\t\t\t0x0008\n#define CONTROL_LEI\t\t\t\t0x0004\n#define CONTROL_STOP1\t\t\t0x0002\n#define CONTROL_STOP0\t\t\t0x0001\n\n#define CONTROL_BSMASK\t\t\t(CONTROL_BS1 | CONTROL_BS0)\n#define CONTROL_CAMASK\t\t\t(CONTROL_CA2 | CONTROL_CA1 | CONTROL_CA0)\n#define CONTROL_LPMASK\t\t\t(CONTROL_LP4 | CONTROL_LP3)\n#define CONTROL_LOOPMASK\t\t(CONTROL_BLE | CONTROL_LPE)\n#define CONTROL_STOPMASK\t\t(CONTROL_STOP1 | CONTROL_STOP0)\n\n\n\n/**********************************************************************************************\n\n     INTERNAL DATA STRUCTURES\n\n***********************************************************************************************/\n\n/* struct describing a single playing voice */\ntypedef struct _es5506_voice es5506_voice;\nstruct _es5506_voice\n{\n\t/* external state */\n\tUINT32\t\tcontrol;\t\t\t\t/* control register */\n\tUINT32\t\tfreqcount;\t\t\t\t/* frequency count register */\n\tUINT32\t\tstart;\t\t\t\t\t/* start register */\n\tUINT32\t\tlvol;\t\t\t\t\t/* left volume register */\n\tUINT32\t\tend;\t\t\t\t\t/* end register */\n\tUINT32\t\tlvramp;\t\t\t\t\t/* left volume ramp register */\n\tUINT32\t\taccum;\t\t\t\t\t/* accumulator register */\n\tUINT32\t\trvol;\t\t\t\t\t/* right volume register */\n\tUINT32\t\trvramp;\t\t\t\t\t/* right volume ramp register */\n\tUINT32\t\tecount;\t\t\t\t\t/* envelope count register */\n\tUINT32\t\tk2;\t\t\t\t\t\t/* k2 register */\n\tUINT32\t\tk2ramp;\t\t\t\t\t/* k2 ramp register */\n\tUINT32\t\tk1;\t\t\t\t\t\t/* k1 register */\n\tUINT32\t\tk1ramp;\t\t\t\t\t/* k1 ramp register */\n\tINT32\t\to4n1;\t\t\t\t\t/* filter storage O4(n-1) */\n\tINT32\t\to3n1;\t\t\t\t\t/* filter storage O3(n-1) */\n\tINT32\t\to3n2;\t\t\t\t\t/* filter storage O3(n-2) */\n\tINT32\t\to2n1;\t\t\t\t\t/* filter storage O2(n-1) */\n\tINT32\t\to2n2;\t\t\t\t\t/* filter storage O2(n-2) */\n\tINT32\t\to1n1;\t\t\t\t\t/* filter storage O1(n-1) */\n\tUINT32\t\texbank;\t\t\t\t\t/* external address bank */\n\n\t/* internal state */\n\tUINT8\t\tindex;\t\t\t\t\t/* index of this voice */\n\tUINT8\t\tfiltcount;\t\t\t\t/* filter count */\n\tUINT8       Muted;\n\tUINT32\t\taccum_mask;\n};\n\ntypedef struct _es5506_state es5506_state;\nstruct _es5506_state\n{\n\t//sound_stream *stream;\t\t\t\t/* which stream are we using */\n\tint\t\t\tsample_rate;\t\t\t/* current sample rate */\n\tUINT32\t\tregion_size[4];\n\tUINT16 *\tregion_base[4];\t\t\t/* pointer to the base of the region */\n\tUINT32\t\twrite_latch;\t\t\t/* currently accumulated data for write */\n\tUINT32\t\tread_latch;\t\t\t\t/* currently accumulated data for read */\n\tUINT32\t\tmaster_clock;\t\t\t/* master clock frequency */\n\t//void\t\t(*irq_callback)(device_t *, int);\t/* IRQ callback */\n\t//UINT16\t\t(*port_read)(void);\t\t/* input port read */\n\n\tUINT8\t\tcurrent_page;\t\t\t/* current register page */\n\tUINT8\t\tactive_voices;\t\t\t/* number of active voices */\n\tUINT8\t\tmode;\t\t\t\t\t/* MODE register */\n\tUINT8\t\twst;\t\t\t\t\t/* W_ST register */\n\tUINT8\t\twend;\t\t\t\t\t/* W_END register */\n\tUINT8\t\tlrend;\t\t\t\t\t/* LR_END register */\n\tUINT8\t\tirqv;\t\t\t\t\t/* IRQV register */\n\n\tes5506_voice voice[32];\t\t\t\t/* the 32 voices */\n\n\tINT32 *\t\tscratch;\n\n\tINT16 *\t\tulaw_lookup;\n\tUINT16 *\tvolume_lookup;\n\t//device_t *device;\n\n#if MAKE_WAVS\n\tvoid *\t\twavraw;\t\t\t\t\t/* raw waveform */\n#endif\n\tint channels;\t\t\t\t\t\t/* number of output channels: 1 .. 6 */\n\tUINT8       sndtype;\t\t\t\t/* 0 - ES5505, 1 - ES5506 */\n\t\n\tSRATE_CALLBACK SmpRateFunc;\n\tvoid* SmpRateData;\n};\n\n\n#define MAX_CHIPS\t0x02\nstatic es5506_state ES5506Data[MAX_CHIPS];\n\n/*INLINE es5506_state *get_safe_token(device_t *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == ES5505 || device->type() == ES5506);\n\treturn (es5506_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n\n\n/**********************************************************************************************\n\n     GLOBAL VARIABLES\n\n***********************************************************************************************/\n\n//static FILE *eslog;\n\n\n\n/**********************************************************************************************\n\n     update_irq_state -- update the IRQ state\n\n***********************************************************************************************/\n\nstatic void update_irq_state(es5506_state *chip)\n{\n\t/* ES5505/6 irq line has been set high - inform the host */\n\t//if (chip->irq_callback)\n\t//\t(*chip->irq_callback)(chip->device, 1); /* IRQB set high */\n}\n\nstatic void update_internal_irq_state(es5506_state *chip)\n{\n\t/*  Host (cpu) has just read the voice interrupt vector (voice IRQ ack).\n\n        Reset the voice vector to show the IRQB line is low (top bit set).\n        If we have any stacked interrupts (other voices waiting to be\n        processed - with their IRQ bit set) then they will be moved into\n        the vector next time the voice is processed.  In emulation\n        terms they get updated next time generate_samples() is called.\n    */\n\n\tchip->irqv=0x80;\n\n\t//if (chip->irq_callback)\n\t//\t(*chip->irq_callback)(chip->device, 0); /* IRQB set low */\n}\n\n/**********************************************************************************************\n\n     compute_tables -- compute static tables\n\n***********************************************************************************************/\n\nstatic void compute_tables(es5506_state *chip)\n{\n\tint i;\n\n\t/* allocate ulaw lookup table */\n\t//chip->ulaw_lookup = auto_alloc_array(chip->device->machine(), INT16, 1 << ULAW_MAXBITS);\n\tchip->ulaw_lookup = (INT16*)malloc((1 << ULAW_MAXBITS) * sizeof(INT16));\n\n\t/* generate ulaw lookup table */\n\tfor (i = 0; i < (1 << ULAW_MAXBITS); i++)\n\t{\n\t\tUINT16 rawval = (i << (16 - ULAW_MAXBITS)) | (1 << (15 - ULAW_MAXBITS));\n\t\tUINT8 exponent = rawval >> 13;\n\t\tUINT32 mantissa = (rawval << 3) & 0xffff;\n\n\t\tif (exponent == 0)\n\t\t\tchip->ulaw_lookup[i] = (INT16)mantissa >> 7;\n\t\telse\n\t\t{\n\t\t\tmantissa = (mantissa >> 1) | (~mantissa & 0x8000);\n\t\t\tchip->ulaw_lookup[i] = (INT16)mantissa >> (7 - exponent);\n\t\t}\n\t}\n\n\t/* allocate volume lookup table */\n\t//chip->volume_lookup = auto_alloc_array(chip->device->machine(), UINT16, 4096);\n\tchip->volume_lookup = (UINT16*)malloc(4096 * sizeof(UINT16));\n\n\t/* generate volume lookup table */\n\tfor (i = 0; i < 4096; i++)\n\t{\n\t\tUINT8 exponent = i >> 8;\n\t\tUINT32 mantissa = (i & 0xff) | 0x100;\n\n\t\tchip->volume_lookup[i] = (mantissa << 11) >> (20 - exponent);\n\t}\n}\n\n\n\n/**********************************************************************************************\n\n     interpolate -- interpolate between two samples\n\n***********************************************************************************************/\n\n#define interpolate(sample1, sample2, accum)\t\t\t\t\t\t\t\t\\\n\t\t(sample1 * (INT32)(0x800 - (accum & 0x7ff)) +\t\t\t\t\t\t\\\n\t\t sample2 * (INT32)(accum & 0x7ff)) >> 11;\n\n\n\n/**********************************************************************************************\n\n     apply_filters -- apply the 4-pole digital filter to the sample\n\n***********************************************************************************************/\n\n#define apply_filters(voice, sample)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\ndo\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* pole 1 is always low-pass using K1 */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tsample = ((INT32)(voice->k1 >> 2) * (sample - voice->o1n1) / 16384) + voice->o1n1;\t\t\t\\\n\tvoice->o1n1 = sample;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* pole 2 is always low-pass using K1 */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tsample = ((INT32)(voice->k1 >> 2) * (sample - voice->o2n1) / 16384) + voice->o2n1;\t\t\t\\\n\tvoice->o2n2 = voice->o2n1;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tvoice->o2n1 = sample;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* remaining poles depend on the current filter setting */\t\t\t\t\t\t\t\t\t\\\n\tswitch (voice->control & CONTROL_LPMASK)\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tcase 0:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* pole 3 is high-pass using K2 */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tsample = sample - voice->o2n2 + ((INT32)(voice->k2 >> 2) * voice->o3n1) / 32768 + voice->o3n1 / 2; \\\n\t\t\tvoice->o3n2 = voice->o3n1;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tvoice->o3n1 = sample;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* pole 4 is high-pass using K2 */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tsample = sample - voice->o3n2 + ((INT32)(voice->k2 >> 2) * voice->o4n1) / 32768 + voice->o4n1 / 2; \\\n\t\t\tvoice->o4n1 = sample;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tcase CONTROL_LP3:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* pole 3 is low-pass using K1 */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tsample = ((INT32)(voice->k1 >> 2) * (sample - voice->o3n1) / 16384) + voice->o3n1;\t\\\n\t\t\tvoice->o3n2 = voice->o3n1;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tvoice->o3n1 = sample;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* pole 4 is high-pass using K2 */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tsample = sample - voice->o3n2 + ((INT32)(voice->k2 >> 2) * voice->o4n1) / 32768 + voice->o4n1 / 2; \\\n\t\t\tvoice->o4n1 = sample;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tcase CONTROL_LP4:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* pole 3 is low-pass using K2 */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tsample = ((INT32)(voice->k2 >> 2) * (sample - voice->o3n1) / 16384) + voice->o3n1;\t\\\n\t\t\tvoice->o3n2 = voice->o3n1;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tvoice->o3n1 = sample;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* pole 4 is low-pass using K2 */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tsample = ((INT32)(voice->k2 >> 2) * (sample - voice->o4n1) / 16384) + voice->o4n1;\t\\\n\t\t\tvoice->o4n1 = sample;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tcase CONTROL_LP4 | CONTROL_LP3:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* pole 3 is low-pass using K1 */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tsample = ((INT32)(voice->k1 >> 2) * (sample - voice->o3n1) / 16384) + voice->o3n1;\t\\\n\t\t\tvoice->o3n2 = voice->o3n1;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tvoice->o3n1 = sample;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* pole 4 is low-pass using K2 */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tsample = ((INT32)(voice->k2 >> 2) * (sample - voice->o4n1) / 16384) + voice->o4n1;\t\\\n\t\t\tvoice->o4n1 = sample;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\n\n\n/**********************************************************************************************\n\n     update_envelopes -- update the envelopes\n\n***********************************************************************************************/\n\n#define update_envelopes(voice, samples)\t\t\t\t\t\t\t\t\t\t\t\\\ndo\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tint count = (samples > 1 && samples > voice->ecount) ? voice->ecount : samples;\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* decrement the envelope counter */\t\t\t\t\t\t\t\t\t\t\t\\\n\tvoice->ecount -= count;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* ramp left volume */\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif (voice->lvramp)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tvoice->lvol += (INT8)voice->lvramp * count;\t\t\t\t\t\t\t\t\t\\\n\t\tif ((INT32)voice->lvol < 0) voice->lvol = 0;\t\t\t\t\t\t\t\t\\\n\t\telse if (voice->lvol > 0xffff) voice->lvol = 0xffff;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* ramp right volume */\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif (voice->rvramp)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tvoice->rvol += (INT8)voice->rvramp * count;\t\t\t\t\t\t\t\t\t\\\n\t\tif ((INT32)voice->rvol < 0) voice->rvol = 0;\t\t\t\t\t\t\t\t\\\n\t\telse if (voice->rvol > 0xffff) voice->rvol = 0xffff;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* ramp k1 filter constant */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif (voice->k1ramp && ((INT32)voice->k1ramp >= 0 || !(voice->filtcount & 7)))\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tvoice->k1 += (INT8)voice->k1ramp * count;\t\t\t\t\t\t\t\t\t\\\n\t\tif ((INT32)voice->k1 < 0) voice->k1 = 0;\t\t\t\t\t\t\t\t\t\\\n\t\telse if (voice->k1 > 0xffff) voice->k1 = 0xffff;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* ramp k2 filter constant */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif (voice->k2ramp && ((INT32)voice->k2ramp >= 0 || !(voice->filtcount & 7)))\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tvoice->k2 += (INT8)voice->k2ramp * count;\t\t\t\t\t\t\t\t\t\\\n\t\tif ((INT32)voice->k2 < 0) voice->k2 = 0;\t\t\t\t\t\t\t\t\t\\\n\t\telse if (voice->k2 > 0xffff) voice->k2 = 0xffff;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* update the filter constant counter */\t\t\t\t\t\t\t\t\t\t\\\n\tvoice->filtcount += count;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\n\n\n/**********************************************************************************************\n\n     check_for_end_forward\n     check_for_end_reverse -- check for loop end and loop appropriately\n\n***********************************************************************************************/\n\n#define check_for_end_forward(voice, accum)\t\t\t\t\t\t\t\t\t\t\t\\\ndo\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* are we past the end? */\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif (accum > voice->end && !(voice->control & CONTROL_LEI))\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t/* generate interrupt if required */\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (voice->control&CONTROL_IRQE)\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tvoice->control |= CONTROL_IRQ;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t/* handle the different types of looping */\t\t\t\t\t\t\t\t\t\\\n\t\tswitch (voice->control & CONTROL_LOOPMASK)\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* non-looping */\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tcase 0:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tvoice->control |= CONTROL_STOP0;\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tgoto alldone;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* uni-directional looping */\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tcase CONTROL_LPE:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\taccum = (voice->start + (accum - voice->end)) & voice->accum_mask;\t\\\n\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* trans-wave looping */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tcase CONTROL_BLE:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\taccum = (voice->start + (accum - voice->end)) & voice->accum_mask;\t\\\n\t\t\t\tvoice->control = (voice->control & ~CONTROL_LOOPMASK) | CONTROL_LEI;\\\n\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* bi-directional looping */\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tcase CONTROL_LPE | CONTROL_BLE:\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\taccum = (voice->end - (accum - voice->end)) & voice->accum_mask;\t\\\n\t\t\t\tvoice->control ^= CONTROL_DIR;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tgoto reverse;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\n\n#define check_for_end_reverse(voice, accum)\t\t\t\t\t\t\t\t\t\t\t\\\ndo\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* are we past the end? */\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif (accum < voice->start && !(voice->control & CONTROL_LEI))\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t/* generate interrupt if required */\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (voice->control&CONTROL_IRQE)\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tvoice->control |= CONTROL_IRQ;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t/* handle the different types of looping */\t\t\t\t\t\t\t\t\t\\\n\t\tswitch (voice->control & CONTROL_LOOPMASK)\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* non-looping */\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tcase 0:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tvoice->control |= CONTROL_STOP0;\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tgoto alldone;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* uni-directional looping */\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tcase CONTROL_LPE:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\taccum = (voice->end - (voice->start - accum)) & voice->accum_mask;\t\\\n\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* trans-wave looping */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tcase CONTROL_BLE:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\taccum = (voice->end - (voice->start - accum)) & voice->accum_mask;\t\\\n\t\t\t\tvoice->control = (voice->control & ~CONTROL_LOOPMASK) | CONTROL_LEI;\\\n\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* bi-directional looping */\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tcase CONTROL_LPE | CONTROL_BLE:\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\taccum = (voice->start + (voice->start - accum)) & voice->accum_mask;\\\n\t\t\t\tvoice->control ^= CONTROL_DIR;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tgoto reverse;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\n\n\n/**********************************************************************************************\n\n     generate_dummy -- generate nothing, just apply envelopes\n\n***********************************************************************************************/\n\nstatic void generate_dummy(es5506_state *chip, es5506_voice *voice, UINT16 *base, INT32 *lbuffer, INT32 *rbuffer, int samples)\n{\n\tUINT32 freqcount = voice->freqcount;\n\tUINT32 accum = voice->accum & voice->accum_mask;\n\n\t/* outer loop, in case we switch directions */\n\twhile (samples > 0 && !(voice->control & CONTROL_STOPMASK))\n\t{\nreverse:\n\t\t/* two cases: first case is forward direction */\n\t\tif (!(voice->control & CONTROL_DIR))\n\t\t{\n\t\t\t/* loop while we still have samples to generate */\n\t\t\twhile (samples--)\n\t\t\t{\n\t\t\t\t/* fetch two samples */\n\t\t\t\taccum = (accum + freqcount) & voice->accum_mask;\n\n\t\t\t\t/* update filters/volumes */\n\t\t\t\tif (voice->ecount != 0)\n\t\t\t\t\tupdate_envelopes(voice, 1);\n\n\t\t\t\t/* check for loop end */\n\t\t\t\tcheck_for_end_forward(voice, accum);\n\t\t\t}\n\t\t}\n\n\t\t/* two cases: second case is backward direction */\n\t\telse\n\t\t{\n\t\t\t/* loop while we still have samples to generate */\n\t\t\twhile (samples--)\n\t\t\t{\n\t\t\t\t/* fetch two samples */\n\t\t\t\taccum = (accum - freqcount) & voice->accum_mask;\n\n\t\t\t\t/* update filters/volumes */\n\t\t\t\tif (voice->ecount != 0)\n\t\t\t\t\tupdate_envelopes(voice, 1);\n\n\t\t\t\t/* check for loop end */\n\t\t\t\tcheck_for_end_reverse(voice, accum);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* if we stopped, process any additional envelope */\nalldone:\n\tvoice->accum = accum;\n\tif (samples > 0)\n\t\tupdate_envelopes(voice, samples);\n}\n\n\n\n/**********************************************************************************************\n\n     generate_ulaw -- general u-law decoding routine\n\n***********************************************************************************************/\n\nstatic void generate_ulaw(es5506_state *chip, es5506_voice *voice, UINT16 *base, INT32 *lbuffer, INT32 *rbuffer, int samples)\n{\n\tUINT32 freqcount = voice->freqcount;\n\tUINT32 accum = voice->accum & voice->accum_mask;\n\tINT32 lvol = chip->volume_lookup[voice->lvol >> 4];\n\tINT32 rvol = chip->volume_lookup[voice->rvol >> 4];\n\n\t/* pre-add the bank offset */\n\tbase += voice->exbank;\n\n\t/* outer loop, in case we switch directions */\n\twhile (samples > 0 && !(voice->control & CONTROL_STOPMASK))\n\t{\nreverse:\n\t\t/* two cases: first case is forward direction */\n\t\tif (!(voice->control & CONTROL_DIR))\n\t\t{\n\t\t\t/* loop while we still have samples to generate */\n\t\t\twhile (samples--)\n\t\t\t{\n\t\t\t\t/* fetch two samples */\n#ifdef VGM_BIG_ENDIAN\n\t#warning \"ES5506 sound emulation not Endian-Safe!\"\n#endif\n\t\t\t\tINT32 val1 = base[accum >> 11];\n\t\t\t\tINT32 val2 = base[((accum + (1 << 11)) & voice->accum_mask) >> 11];\n\n\t\t\t\t/* decompress u-law */\n\t\t\t\tval1 = chip->ulaw_lookup[val1 >> (16 - ULAW_MAXBITS)];\n\t\t\t\tval2 = chip->ulaw_lookup[val2 >> (16 - ULAW_MAXBITS)];\n\n\t\t\t\t/* interpolate */\n\t\t\t\tval1 = interpolate(val1, val2, accum);\n\t\t\t\taccum = (accum + freqcount) & voice->accum_mask;\n\n\t\t\t\t/* apply filters */\n\t\t\t\tapply_filters(voice, val1);\n\n\t\t\t\t/* update filters/volumes */\n\t\t\t\tif (voice->ecount != 0)\n\t\t\t\t{\n\t\t\t\t\tupdate_envelopes(voice, 1);\n\t\t\t\t\tlvol = chip->volume_lookup[voice->lvol >> 4];\n\t\t\t\t\trvol = chip->volume_lookup[voice->rvol >> 4];\n\t\t\t\t}\n\n\t\t\t\t/* apply volumes and add */\n\t\t\t\t*lbuffer++ += (val1 * lvol) >> 11;\n\t\t\t\t*rbuffer++ += (val1 * rvol) >> 11;\n\n\t\t\t\t/* check for loop end */\n\t\t\t\tcheck_for_end_forward(voice, accum);\n\t\t\t}\n\t\t}\n\n\t\t/* two cases: second case is backward direction */\n\t\telse\n\t\t{\n\t\t\t/* loop while we still have samples to generate */\n\t\t\twhile (samples--)\n\t\t\t{\n\t\t\t\t/* fetch two samples */\n#ifdef VGM_BIG_ENDIAN\n\t#warning \"ES5506 sound emulation not Endian-Safe!\"\n#endif\n\t\t\t\tINT32 val1 = base[accum >> 11];\n\t\t\t\tINT32 val2 = base[((accum + (1 << 11)) & voice->accum_mask) >> 11];\n\n\t\t\t\t/* decompress u-law */\n\t\t\t\tval1 = chip->ulaw_lookup[val1 >> (16 - ULAW_MAXBITS)];\n\t\t\t\tval2 = chip->ulaw_lookup[val2 >> (16 - ULAW_MAXBITS)];\n\n\t\t\t\t/* interpolate */\n\t\t\t\tval1 = interpolate(val1, val2, accum);\n\t\t\t\taccum = (accum - freqcount) & voice->accum_mask;\n\n\t\t\t\t/* apply filters */\n\t\t\t\tapply_filters(voice, val1);\n\n\t\t\t\t/* update filters/volumes */\n\t\t\t\tif (voice->ecount != 0)\n\t\t\t\t{\n\t\t\t\t\tupdate_envelopes(voice, 1);\n\t\t\t\t\tlvol = chip->volume_lookup[voice->lvol >> 4];\n\t\t\t\t\trvol = chip->volume_lookup[voice->rvol >> 4];\n\t\t\t\t}\n\n\t\t\t\t/* apply volumes and add */\n\t\t\t\t*lbuffer++ += (val1 * lvol) >> 11;\n\t\t\t\t*rbuffer++ += (val1 * rvol) >> 11;\n\n\t\t\t\t/* check for loop end */\n\t\t\t\tcheck_for_end_reverse(voice, accum);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* if we stopped, process any additional envelope */\nalldone:\n\tvoice->accum = accum;\n\tif (samples > 0)\n\t\tupdate_envelopes(voice, samples);\n}\n\n\n\n/**********************************************************************************************\n\n     generate_pcm -- general PCM decoding routine\n\n***********************************************************************************************/\n\nstatic void generate_pcm(es5506_state *chip, es5506_voice *voice, UINT16 *base, INT32 *lbuffer, INT32 *rbuffer, int samples)\n{\n\tUINT32 freqcount = voice->freqcount;\n\tUINT32 accum = voice->accum & voice->accum_mask;\n\tINT32 lvol = chip->volume_lookup[voice->lvol >> 4];\n\tINT32 rvol = chip->volume_lookup[voice->rvol >> 4];\n\n\t/* pre-add the bank offset */\n\tbase += voice->exbank;\n\n\t/* outer loop, in case we switch directions */\n\twhile (samples > 0 && !(voice->control & CONTROL_STOPMASK))\n\t{\nreverse:\n\t\t/* two cases: first case is forward direction */\n\t\tif (!(voice->control & CONTROL_DIR))\n\t\t{\n\t\t\t/* loop while we still have samples to generate */\n\t\t\twhile (samples--)\n\t\t\t{\n\t\t\t\t/* fetch two samples */\n#ifdef VGM_BIG_ENDIAN\n\t#warning \"ES5506 sound emulation not Endian-Safe!\"\n#endif\n\t\t\t\tINT32 val1 = (INT16)base[accum >> 11];\n\t\t\t\tINT32 val2 = (INT16)base[((accum + (1 << 11)) & voice->accum_mask) >> 11];\n\n\t\t\t\t/* interpolate */\n\t\t\t\tval1 = interpolate(val1, val2, accum);\n\t\t\t\taccum = (accum + freqcount) & voice->accum_mask;\n\n\t\t\t\t/* apply filters */\n\t\t\t\tapply_filters(voice, val1);\n\n\t\t\t\t/* update filters/volumes */\n\t\t\t\tif (voice->ecount != 0)\n\t\t\t\t{\n\t\t\t\t\tupdate_envelopes(voice, 1);\n\t\t\t\t\tlvol = chip->volume_lookup[voice->lvol >> 4];\n\t\t\t\t\trvol = chip->volume_lookup[voice->rvol >> 4];\n\t\t\t\t}\n\n\t\t\t\t/* apply volumes and add */\n\t\t\t\t*lbuffer++ += (val1 * lvol) >> 11;\n\t\t\t\t*rbuffer++ += (val1 * rvol) >> 11;\n\n\t\t\t\t/* check for loop end */\n\t\t\t\tcheck_for_end_forward(voice, accum);\n\t\t\t}\n\t\t}\n\n\t\t/* two cases: second case is backward direction */\n\t\telse\n\t\t{\n\t\t\t/* loop while we still have samples to generate */\n\t\t\twhile (samples--)\n\t\t\t{\n\t\t\t\t/* fetch two samples */\n#ifdef VGM_BIG_ENDIAN\n\t#warning \"ES5506 sound emulation not Endian-Safe!\"\n#endif\n\t\t\t\tINT32 val1 = (INT16)base[accum >> 11];\n\t\t\t\tINT32 val2 = (INT16)base[((accum + (1 << 11)) & voice->accum_mask) >> 11];\n\n\t\t\t\t/* interpolate */\n\t\t\t\tval1 = interpolate(val1, val2, accum);\n\t\t\t\taccum = (accum - freqcount) & voice->accum_mask;\n\n\t\t\t\t/* apply filters */\n\t\t\t\tapply_filters(voice, val1);\n\n\t\t\t\t/* update filters/volumes */\n\t\t\t\tif (voice->ecount != 0)\n\t\t\t\t{\n\t\t\t\t\tupdate_envelopes(voice, 1);\n\t\t\t\t\tlvol = chip->volume_lookup[voice->lvol >> 4];\n\t\t\t\t\trvol = chip->volume_lookup[voice->rvol >> 4];\n\t\t\t\t}\n\n\t\t\t\t/* apply volumes and add */\n\t\t\t\t*lbuffer++ += (val1 * lvol) >> 11;\n\t\t\t\t*rbuffer++ += (val1 * rvol) >> 11;\n\n\t\t\t\t/* check for loop end */\n\t\t\t\tcheck_for_end_reverse(voice, accum);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* if we stopped, process any additional envelope */\nalldone:\n\tvoice->accum = accum;\n\tif (samples > 0)\n\t\tupdate_envelopes(voice, samples);\n}\n\n\n\n/**********************************************************************************************\n\n     generate_samples -- tell each voice to generate samples\n\n***********************************************************************************************/\n\nstatic void generate_samples(es5506_state *chip, INT32 **outputs, int offset, int samples)\n{\n\tint v;\n\tint i;\n\tint voice_channel;\n\tint channel;\n\tint l;\n\tint r;\n\tINT32 *left;\n\tINT32 *right;\n\n\t/* skip if nothing to do */\n\tif (!samples)\n\t\treturn;\n\n\t/* clear out the accumulator */\n\tfor (i = 0; i < chip->channels << 1; i++)\n\t{\n\t\tmemset(outputs[i] + offset, 0, sizeof(INT32) * samples);\n\t}\n\n\t/* loop over voices */\n\tfor (v = 0; v <= chip->active_voices; v++)\n\t{\n\t\tes5506_voice *voice = &chip->voice[v];\n\t\tUINT16 *base = chip->region_base[voice->control >> 14];\n\n\t\t/* special case: if end == start, stop the voice */\n\t\tif (voice->start == voice->end)\n\t\t\tvoice->control |= CONTROL_STOP0;\n\n\t\tvoice_channel = (voice->control & CONTROL_CAMASK) >> 10;\n\t\tchannel = voice_channel % chip->channels;\n\t\tl = channel << 1;\n\t\tr = l + 1;\n\t\tleft = outputs[l] + offset;\n\t\tright = outputs[r] + offset;\n\n\t\t/* generate from the appropriate source */\n\t\tif (!base)\n\t\t{\n\t\t\t//logerror(\"es5506: NULL region base %d\\n\",voice->control >> 14);\n\t\t\tgenerate_dummy(chip, voice, base, left, right, samples);\n\t\t}\n\t\telse if (voice->control & 0x2000)\n\t\t\tgenerate_ulaw(chip, voice, base, left, right, samples);\n\t\telse\n\t\t\tgenerate_pcm(chip, voice, base, left, right, samples);\n\n\t\t/* does this voice have it's IRQ bit raised? */\n\t\tif (voice->control&CONTROL_IRQ)\n\t\t{\n\t\t\tlogerror(\"es5506: IRQ raised on voice %d!!\\n\",v);\n\t\t\t/* only update voice vector if existing IRQ is acked by host */\n\t\t\tif (chip->irqv&0x80)\n\t\t\t{\n\t\t\t\t/* latch voice number into vector, and set high bit low */\n\t\t\t\tchip->irqv=v&0x7f;\n\n\t\t\t\t/* take down IRQ bit on voice */\n\t\t\t\tvoice->control&=~CONTROL_IRQ;\n\n\t\t\t\t/* inform host of irq */\n\t\t\t\tupdate_irq_state(chip);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n/**********************************************************************************************\n\n     es5506_update -- update the sound chip so that it is in sync with CPU execution\n\n***********************************************************************************************/\n\n//static STREAM_UPDATE( es5506_update )\nvoid es5506_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//es5506_state *chip = (es5506_state *)param;\n\tes5506_state *chip = &ES5506Data[ChipID];\n\tint offset;\n\n#if MAKE_WAVS\n\t/* start the logging once we have a sample rate */\n\tif (chip->sample_rate)\n\t{\n\t\tif (!chip->wavraw)\n\t\t\tchip->wavraw = wav_open(\"raw.wav\", chip->sample_rate, 2);\n\t}\n#endif\n\n\t/* loop until all samples are output */\n\toffset = 0;\n\twhile (samples)\n\t{\n\t\tint length = (samples > MAX_SAMPLE_CHUNK) ? MAX_SAMPLE_CHUNK : samples;\n\n\t\tgenerate_samples(chip, outputs, offset, length);\n\n\t\t/* account for these samples */\n\t\toffset += length;\n\t\tsamples -= length;\n\t}\n}\n\n\n/**********************************************************************************************\n\n     DEVICE_START( es5506 ) -- start emulation of the ES5506\n\n***********************************************************************************************/\n\n//static void es5506_start_common(device_t *device, const void *config, device_type sndtype)\nstatic void es5506_start_common(es5506_state *chip, int clock, UINT8 sndtype)\n{\n\t//const es5506_interface *intf = (const es5506_interface *)config;\n\t//es5506_state *chip = get_safe_token(device);\n//\tint j;\n//\tUINT32 accum_mask;\n\tint max_chns;\n\n\tchip->sndtype = sndtype;\n\t/* only override the number of channels if the value is in the valid range 1 .. 6 */\n\tmax_chns = chip->sndtype ? 6 : 4;\t// 6 for ES5506, 4 for ES5505\n\tif (chip->channels < 1 || chip->channels > max_chns)\n\t\tchip->channels = 1;\t/* 1 channel by default, for backward compatibility */\n\t\n\t/* debugging */\n\t//if (LOG_COMMANDS && !eslog)\n\t//\teslog = fopen(\"es.log\", \"w\");\n\n\t/* create the stream */\n//\tchip->stream = device->machine().sound().stream_alloc(*device, 0, 2, device->clock() / (16*32), chip, es5506_update);\n\n\t/* initialize the regions */\n//\tchip->region_base[0] = intf->region0 ? (UINT16 *)device->machine().region(intf->region0)->base() : NULL;\n//\tchip->region_base[1] = intf->region1 ? (UINT16 *)device->machine().region(intf->region1)->base() : NULL;\n//\tchip->region_base[2] = intf->region2 ? (UINT16 *)device->machine().region(intf->region2)->base() : NULL;\n//\tchip->region_base[3] = intf->region3 ? (UINT16 *)device->machine().region(intf->region3)->base() : NULL;\n\n\t/* initialize the rest of the structure */\n//\tchip->device = device;\n//\tchip->master_clock = device->clock();\n//\tchip->irq_callback = intf->irq_callback;\n\tchip->master_clock = clock;\n\tchip->irqv = 0x80;\n\n\tif (chip->sndtype)\n\t{\n\t\t/* KT-76 assumes all voices are active on an ES5506 without setting them! */\n\t\tchip->active_voices = 31;\n\t\tchip->sample_rate = chip->master_clock / (16 * (chip->active_voices + 1));\n\t\t//chip->stream->set_sample_rate(m_sample_rate);\n\t}\n\telse\n\t{\n\t\t// ES5505\n\t\tchip->sample_rate = chip->master_clock / (16*32);\n\t}\n\n\t/* compute the tables */\n\tcompute_tables(chip);\n\n\t/* init the voices */\n\t//accum_mask = (chip->sndtype == ES5506) ? 0xffffffff : 0x7fffffff;\n\t// now done in device_reset\n\n\t/* allocate memory */\n\t//chip->scratch = auto_alloc_array(device->machine(), INT32, 2 * MAX_SAMPLE_CHUNK);\n\tchip->scratch = (INT32*)malloc(2 * MAX_SAMPLE_CHUNK * sizeof(INT32));\n\n\t/* register save */\n\t/*device->save_item(NAME(chip->sample_rate));\n\tdevice->save_item(NAME(chip->write_latch));\n\tdevice->save_item(NAME(chip->read_latch));\n\n\tdevice->save_item(NAME(chip->current_page));\n\tdevice->save_item(NAME(chip->active_voices));\n\tdevice->save_item(NAME(chip->mode));\n\tdevice->save_item(NAME(chip->wst));\n\tdevice->save_item(NAME(chip->wend));\n\tdevice->save_item(NAME(chip->lrend));\n\tdevice->save_item(NAME(chip->irqv));\n\n\tdevice->save_pointer(NAME(chip->scratch), 2 * MAX_SAMPLE_CHUNK);\n\n\tfor (j = 0; j < 32; j++)\n\t{\n\t\tdevice->save_item(NAME(chip->voice[j].control), j);\n\t\tdevice->save_item(NAME(chip->voice[j].freqcount), j);\n\t\tdevice->save_item(NAME(chip->voice[j].start), j);\n\t\tdevice->save_item(NAME(chip->voice[j].lvol), j);\n\t\tdevice->save_item(NAME(chip->voice[j].end), j);\n\t\tdevice->save_item(NAME(chip->voice[j].lvramp), j);\n\t\tdevice->save_item(NAME(chip->voice[j].accum), j);\n\t\tdevice->save_item(NAME(chip->voice[j].rvol), j);\n\t\tdevice->save_item(NAME(chip->voice[j].rvramp), j);\n\t\tdevice->save_item(NAME(chip->voice[j].ecount), j);\n\t\tdevice->save_item(NAME(chip->voice[j].k2), j);\n\t\tdevice->save_item(NAME(chip->voice[j].k2ramp), j);\n\t\tdevice->save_item(NAME(chip->voice[j].k1), j);\n\t\tdevice->save_item(NAME(chip->voice[j].k1ramp), j);\n\t\tdevice->save_item(NAME(chip->voice[j].o4n1), j);\n\t\tdevice->save_item(NAME(chip->voice[j].o3n1), j);\n\t\tdevice->save_item(NAME(chip->voice[j].o3n2), j);\n\t\tdevice->save_item(NAME(chip->voice[j].o2n1), j);\n\t\tdevice->save_item(NAME(chip->voice[j].o2n2), j);\n\t\tdevice->save_item(NAME(chip->voice[j].o1n1), j);\n\t\tdevice->save_item(NAME(chip->voice[j].exbank), j);\n\t\tdevice->save_item(NAME(chip->voice[j].filtcount), j);\n\t}*/\n\n\t/* success */\n}\n\n\n//static DEVICE_START( es5506 )\nint device_start_es5506(UINT8 ChipID, int clock, int channels)\n{\n\tes5506_state* chip;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &ES5506Data[ChipID];\n\t\n\t//es5506_start_common(device, device->static_config(), ES5506);\n\t//chip->channels = channels;\n\tchip->channels = 1;\t// fixed to L+R for now\n\tes5506_start_common(chip, clock & 0x7FFFFFFF, clock >> 31);\n\treturn chip->master_clock / (16*32);\n}\n\n\n\n/**********************************************************************************************\n\n     DEVICE_STOP( es5506 ) -- stop emulation of the ES5506\n\n***********************************************************************************************/\n\n//static DEVICE_STOP( es5506 )\nvoid device_stop_es5506(UINT8 ChipID)\n{\n\tes5506_state *chip = &ES5506Data[ChipID];\n\t\n\tfree(chip->ulaw_lookup);\tchip->ulaw_lookup = NULL;\n\tfree(chip->volume_lookup);\tchip->volume_lookup = NULL;\n\tfree(chip->scratch);\t\tchip->scratch = NULL;\n\n\t/* debugging */\n\t/*if (LOG_COMMANDS && eslog)\n\t{\n\t\tfclose(eslog);\n\t\teslog = NULL;\n\t}*/\n\n#if MAKE_WAVS\n{\n\tint i;\n\n\tfor (i = 0; i < MAX_ES5506; i++)\n\t{\n\t\tif (es5506[i].wavraw)\n\t\t\twav_close(es5506[i].wavraw);\n\t}\n}\n#endif\n}\n\n\n//static DEVICE_RESET( es5506 )\nvoid device_reset_es5506(UINT8 ChipID)\n{\n\tes5506_state *chip = &ES5506Data[ChipID];\n\tint j;\n\tUINT32 accum_mask;\n\t\n\taccum_mask = chip->sndtype ? 0xffffffff : 0x7fffffff;\n\tfor (j = 0; j < 32; j++)\n\t{\n\t\tchip->voice[j].index = j;\n\t\tchip->voice[j].control = CONTROL_STOPMASK;\n\t\tchip->voice[j].lvol = 0xffff;\n\t\tchip->voice[j].rvol = 0xffff;\n\t\tchip->voice[j].exbank = 0;\n\t\tchip->voice[j].accum_mask = accum_mask;\n\t}\n}\n\n\n\n/**********************************************************************************************\n\n     es5506_reg_write -- handle a write to the selected ES5506 register\n\n***********************************************************************************************/\n\nINLINE void es5506_reg_write_low(es5506_state *chip, es5506_voice *voice, offs_t offset, UINT32 data)\n{\n\tswitch (offset)\n\t{\n\t\tcase 0x00/8:\t/* CR */\n\t\t\tvoice->control = data & 0xffff;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, control=%04x\\n\", chip->current_page & 0x1f, voice->control);\n\t\t\tbreak;\n\n\t\tcase 0x08/8:\t/* FC */\n\t\t\tvoice->freqcount = data & 0x1ffff;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, freq count=%08x\\n\", chip->current_page & 0x1f, voice->freqcount);\n\t\t\tbreak;\n\n\t\tcase 0x10/8:\t/* LVOL */\n\t\t\tvoice->lvol = data & 0xffff;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, left vol=%04x\\n\", chip->current_page & 0x1f, voice->lvol);\n\t\t\tbreak;\n\n\t\tcase 0x18/8:\t/* LVRAMP */\n\t\t\tvoice->lvramp = (data & 0xff00) >> 8;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, left vol ramp=%04x\\n\", chip->current_page & 0x1f, voice->lvramp);\n\t\t\tbreak;\n\n\t\tcase 0x20/8:\t/* RVOL */\n\t\t\tvoice->rvol = data & 0xffff;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, right vol=%04x\\n\", chip->current_page & 0x1f, voice->rvol);\n\t\t\tbreak;\n\n\t\tcase 0x28/8:\t/* RVRAMP */\n\t\t\tvoice->rvramp = (data & 0xff00) >> 8;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, right vol ramp=%04x\\n\", chip->current_page & 0x1f, voice->rvramp);\n\t\t\tbreak;\n\n\t\tcase 0x30/8:\t/* ECOUNT */\n\t\t\tvoice->ecount = data & 0x1ff;\n\t\t\tvoice->filtcount = 0;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, envelope count=%04x\\n\", chip->current_page & 0x1f, voice->ecount);\n\t\t\tbreak;\n\n\t\tcase 0x38/8:\t/* K2 */\n\t\t\tvoice->k2 = data & 0xffff;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, K2=%04x\\n\", chip->current_page & 0x1f, voice->k2);\n\t\t\tbreak;\n\n\t\tcase 0x40/8:\t/* K2RAMP */\n\t\t\tvoice->k2ramp = ((data & 0xff00) >> 8) | ((data & 0x0001) << 31);\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, K2 ramp=%04x\\n\", chip->current_page & 0x1f, voice->k2ramp);\n\t\t\tbreak;\n\n\t\tcase 0x48/8:\t/* K1 */\n\t\t\tvoice->k1 = data & 0xffff;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, K1=%04x\\n\", chip->current_page & 0x1f, voice->k1);\n\t\t\tbreak;\n\n\t\tcase 0x50/8:\t/* K1RAMP */\n\t\t\tvoice->k1ramp = ((data & 0xff00) >> 8) | ((data & 0x0001) << 31);\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, K1 ramp=%04x\\n\", chip->current_page & 0x1f, voice->k1ramp);\n\t\t\tbreak;\n\n\t\tcase 0x58/8:\t/* ACTV */\n\t\t{\n\t\t\tchip->active_voices = data & 0x1f;\n\t\t\tchip->sample_rate = chip->master_clock / (16 * (chip->active_voices + 1));\n\t\t\t//chip->stream->set_sample_rate(chip->sample_rate);\n\t\t\tif (chip->SmpRateFunc != NULL)\n\t\t\t\tchip->SmpRateFunc(chip->SmpRateData, chip->sample_rate);\n\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"active voices=%d, sample_rate=%d\\n\", chip->active_voices, chip->sample_rate);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 0x60/8:\t/* MODE */\n\t\t\tchip->mode = data & 0x1f;\n\t\t\tbreak;\n\n\t\tcase 0x68/8:\t/* PAR - read only */\n\t\tcase 0x70/8:\t/* IRQV - read only */\n\t\t\tbreak;\n\n\t\tcase 0x78/8:\t/* PAGE */\n\t\t\tchip->current_page = data & 0x7f;\n\t\t\tbreak;\n\t}\n}\n\n\nINLINE void es5506_reg_write_high(es5506_state *chip, es5506_voice *voice, offs_t offset, UINT32 data)\n{\n\tswitch (offset)\n\t{\n\t\tcase 0x00/8:\t/* CR */\n\t\t\tvoice->control = data & 0xffff;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, control=%04x\\n\", chip->current_page & 0x1f, voice->control);\n\t\t\tbreak;\n\n\t\tcase 0x08/8:\t/* START */\n\t\t\tvoice->start = data & 0xfffff800;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, loop start=%08x\\n\", chip->current_page & 0x1f, voice->start);\n\t\t\tbreak;\n\n\t\tcase 0x10/8:\t/* END */\n\t\t\tvoice->end = data & 0xffffff80;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, loop end=%08x\\n\", chip->current_page & 0x1f, voice->end);\n\t\t\tbreak;\n\n\t\tcase 0x18/8:\t/* ACCUM */\n\t\t\tvoice->accum = data;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, accum=%08x\\n\", chip->current_page & 0x1f, voice->accum);\n\t\t\tbreak;\n\n\t\tcase 0x20/8:\t/* O4(n-1) */\n\t\t\tvoice->o4n1 = (INT32)(data << 14) >> 14;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, O4(n-1)=%05x\\n\", chip->current_page & 0x1f, voice->o4n1 & 0x3ffff);\n\t\t\tbreak;\n\n\t\tcase 0x28/8:\t/* O3(n-1) */\n\t\t\tvoice->o3n1 = (INT32)(data << 14) >> 14;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, O3(n-1)=%05x\\n\", chip->current_page & 0x1f, voice->o3n1 & 0x3ffff);\n\t\t\tbreak;\n\n\t\tcase 0x30/8:\t/* O3(n-2) */\n\t\t\tvoice->o3n2 = (INT32)(data << 14) >> 14;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, O3(n-2)=%05x\\n\", chip->current_page & 0x1f, voice->o3n2 & 0x3ffff);\n\t\t\tbreak;\n\n\t\tcase 0x38/8:\t/* O2(n-1) */\n\t\t\tvoice->o2n1 = (INT32)(data << 14) >> 14;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, O2(n-1)=%05x\\n\", chip->current_page & 0x1f, voice->o2n1 & 0x3ffff);\n\t\t\tbreak;\n\n\t\tcase 0x40/8:\t/* O2(n-2) */\n\t\t\tvoice->o2n2 = (INT32)(data << 14) >> 14;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, O2(n-2)=%05x\\n\", chip->current_page & 0x1f, voice->o2n2 & 0x3ffff);\n\t\t\tbreak;\n\n\t\tcase 0x48/8:\t/* O1(n-1) */\n\t\t\tvoice->o1n1 = (INT32)(data << 14) >> 14;\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"voice %d, O1(n-1)=%05x\\n\", chip->current_page & 0x1f, voice->o1n1 & 0x3ffff);\n\t\t\tbreak;\n\n\t\tcase 0x50/8:\t/* W_ST */\n\t\t\tchip->wst = data & 0x7f;\n\t\t\tbreak;\n\n\t\tcase 0x58/8:\t/* W_END */\n\t\t\tchip->wend = data & 0x7f;\n\t\t\tbreak;\n\n\t\tcase 0x60/8:\t/* LR_END */\n\t\t\tchip->lrend = data & 0x7f;\n\t\t\tbreak;\n\n\t\tcase 0x68/8:\t/* PAR - read only */\n\t\tcase 0x70/8:\t/* IRQV - read only */\n\t\t\tbreak;\n\n\t\tcase 0x78/8:\t/* PAGE */\n\t\t\tchip->current_page = data & 0x7f;\n\t\t\tbreak;\n\t}\n}\n\nINLINE void es5506_reg_write_test(es5506_state *chip, es5506_voice *voice, offs_t offset, UINT32 data)\n{\n\tswitch (offset)\n\t{\n\t\tcase 0x00/8:\t/* CHANNEL 0 LEFT */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Channel 0 left test write %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x08/8:\t/* CHANNEL 0 RIGHT */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Channel 0 right test write %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x10/8:\t/* CHANNEL 1 LEFT */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Channel 1 left test write %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x18/8:\t/* CHANNEL 1 RIGHT */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Channel 1 right test write %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x20/8:\t/* CHANNEL 2 LEFT */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Channel 2 left test write %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x28/8:\t/* CHANNEL 2 RIGHT */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Channel 2 right test write %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x30/8:\t/* CHANNEL 3 LEFT */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Channel 3 left test write %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x38/8:\t/* CHANNEL 3 RIGHT */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Channel 3 right test write %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x40/8:\t/* CHANNEL 4 LEFT */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Channel 4 left test write %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x48/8:\t/* CHANNEL 4 RIGHT */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Channel 4 right test write %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x50/8:\t/* CHANNEL 5 LEFT */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Channel 5 left test write %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x58/8:\t/* CHANNEL 6 RIGHT */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Channel 5 right test write %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x60/8:\t/* EMPTY */\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"Test write EMPTY %08x\\n\", data);\n\t\t\tbreak;\n\n\t\tcase 0x68/8:\t/* PAR - read only */\n\t\tcase 0x70/8:\t/* IRQV - read only */\n\t\t\tbreak;\n\n\t\tcase 0x78/8:\t/* PAGE */\n\t\t\tchip->current_page = data & 0x7f;\n\t\t\tbreak;\n\t}\n}\n\n//WRITE8_DEVICE_HANDLER( es5506_w )\nstatic void es5506_w(es5506_state *chip, offs_t offset, UINT8 data)\n{\n\t//es5506_state *chip = get_safe_token(device);\n\tes5506_voice *voice = &chip->voice[chip->current_page & 0x1f];\n\tint shift = 8 * (offset & 3);\n\n\t/* accumulate the data */\n\tchip->write_latch = (chip->write_latch & ~(0xff000000 >> shift)) | (data << (24 - shift));\n\n\t/* wait for a write to complete */\n\tif (shift != 24)\n\t\treturn;\n\n\t/* force an update */\n\t//chip->stream->update();\n\n\t/* switch off the page and register */\n\tif (chip->current_page < 0x20)\n\t\tes5506_reg_write_low(chip, voice, offset / 4, chip->write_latch);\n\telse if (chip->current_page < 0x40)\n\t\tes5506_reg_write_high(chip, voice, offset / 4, chip->write_latch);\n\telse\n\t\tes5506_reg_write_test(chip, voice, offset / 4, chip->write_latch);\n\n\t/* clear the write latch when done */\n\tchip->write_latch = 0;\n}\n\n\n\n/**********************************************************************************************\n\n     es5506_reg_read -- read from the specified ES5506 register\n\n***********************************************************************************************/\n\nINLINE UINT32 es5506_reg_read_low(es5506_state *chip, es5506_voice *voice, offs_t offset)\n{\n\tUINT32 result = 0;\n\n\tswitch (offset)\n\t{\n\t\tcase 0x00/8:\t/* CR */\n\t\t\tresult = voice->control;\n\t\t\tbreak;\n\n\t\tcase 0x08/8:\t/* FC */\n\t\t\tresult = voice->freqcount;\n\t\t\tbreak;\n\n\t\tcase 0x10/8:\t/* LVOL */\n\t\t\tresult = voice->lvol;\n\t\t\tbreak;\n\n\t\tcase 0x18/8:\t/* LVRAMP */\n\t\t\tresult = voice->lvramp << 8;\n\t\t\tbreak;\n\n\t\tcase 0x20/8:\t/* RVOL */\n\t\t\tresult = voice->rvol;\n\t\t\tbreak;\n\n\t\tcase 0x28/8:\t/* RVRAMP */\n\t\t\tresult = voice->rvramp << 8;\n\t\t\tbreak;\n\n\t\tcase 0x30/8:\t/* ECOUNT */\n\t\t\tresult = voice->ecount;\n\t\t\tbreak;\n\n\t\tcase 0x38/8:\t/* K2 */\n\t\t\tresult = voice->k2;\n\t\t\tbreak;\n\n\t\tcase 0x40/8:\t/* K2RAMP */\n\t\t\tresult = (voice->k2ramp << 8) | (voice->k2ramp >> 31);\n\t\t\tbreak;\n\n\t\tcase 0x48/8:\t/* K1 */\n\t\t\tresult = voice->k1;\n\t\t\tbreak;\n\n\t\tcase 0x50/8:\t/* K1RAMP */\n\t\t\tresult = (voice->k1ramp << 8) | (voice->k1ramp >> 31);\n\t\t\tbreak;\n\n\t\tcase 0x58/8:\t/* ACTV */\n\t\t\tresult = chip->active_voices;\n\t\t\tbreak;\n\n\t\tcase 0x60/8:\t/* MODE */\n\t\t\tresult = chip->mode;\n\t\t\tbreak;\n\n\t\tcase 0x68/8:\t/* PAR */\n\t\t\t//if (chip->port_read)\n\t\t\t//\tresult = (*chip->port_read)();\n\t\t\tbreak;\n\n\t\tcase 0x70/8:\t/* IRQV */\n\t\t\tresult = chip->irqv;\n\t\t\tupdate_internal_irq_state(chip);\n\t\t\tbreak;\n\n\t\tcase 0x78/8:\t/* PAGE */\n\t\t\tresult = chip->current_page;\n\t\t\tbreak;\n\t}\n\treturn result;\n}\n\n\nINLINE UINT32 es5506_reg_read_high(es5506_state *chip, es5506_voice *voice, offs_t offset)\n{\n\tUINT32 result = 0;\n\n\tswitch (offset)\n\t{\n\t\tcase 0x00/8:\t/* CR */\n\t\t\tresult = voice->control;\n\t\t\tbreak;\n\n\t\tcase 0x08/8:\t/* START */\n\t\t\tresult = voice->start;\n\t\t\tbreak;\n\n\t\tcase 0x10/8:\t/* END */\n\t\t\tresult = voice->end;\n\t\t\tbreak;\n\n\t\tcase 0x18/8:\t/* ACCUM */\n\t\t\tresult = voice->accum;\n\t\t\tbreak;\n\n\t\tcase 0x20/8:\t/* O4(n-1) */\n\t\t\tresult = voice->o4n1 & 0x3ffff;\n\t\t\tbreak;\n\n\t\tcase 0x28/8:\t/* O3(n-1) */\n\t\t\tresult = voice->o3n1 & 0x3ffff;\n\t\t\tbreak;\n\n\t\tcase 0x30/8:\t/* O3(n-2) */\n\t\t\tresult = voice->o3n2 & 0x3ffff;\n\t\t\tbreak;\n\n\t\tcase 0x38/8:\t/* O2(n-1) */\n\t\t\tresult = voice->o2n1 & 0x3ffff;\n\t\t\tbreak;\n\n\t\tcase 0x40/8:\t/* O2(n-2) */\n\t\t\tresult = voice->o2n2 & 0x3ffff;\n\t\t\tbreak;\n\n\t\tcase 0x48/8:\t/* O1(n-1) */\n\t\t\tresult = voice->o1n1 & 0x3ffff;\n\t\t\tbreak;\n\n\t\tcase 0x50/8:\t/* W_ST */\n\t\t\tresult = chip->wst;\n\t\t\tbreak;\n\n\t\tcase 0x58/8:\t/* W_END */\n\t\t\tresult = chip->wend;\n\t\t\tbreak;\n\n\t\tcase 0x60/8:\t/* LR_END */\n\t\t\tresult = chip->lrend;\n\t\t\tbreak;\n\n\t\tcase 0x68/8:\t/* PAR */\n\t\t\t//if (chip->port_read)\n\t\t\t//\tresult = (*chip->port_read)();\n\t\t\tbreak;\n\n\t\tcase 0x70/8:\t/* IRQV */\n\t\t\tresult = chip->irqv;\n\t\t\tupdate_internal_irq_state(chip);\n\t\t\tbreak;\n\n\t\tcase 0x78/8:\t/* PAGE */\n\t\t\tresult = chip->current_page;\n\t\t\tbreak;\n\t}\n\treturn result;\n}\n\nINLINE UINT32 es5506_reg_read_test(es5506_state *chip, es5506_voice *voice, offs_t offset)\n{\n\tUINT32 result = 0;\n\n\tswitch (offset)\n\t{\n\t\tcase 0x68/8:\t/* PAR */\n\t\t\t//if (chip->port_read)\n\t\t\t//\tresult = (*chip->port_read)();\n\t\t\tbreak;\n\n\t\tcase 0x70/8:\t/* IRQV */\n\t\t\tresult = chip->irqv;\n\t\t\tbreak;\n\n\t\tcase 0x78/8:\t/* PAGE */\n\t\t\tresult = chip->current_page;\n\t\t\tbreak;\n\t}\n\treturn result;\n}\n\n//READ8_DEVICE_HANDLER( es5506_r )\nstatic UINT8 es5506_r(es5506_state *chip, offs_t offset)\n{\n\t//es5506_state *chip = get_safe_token(device);\n\tes5506_voice *voice = &chip->voice[chip->current_page & 0x1f];\n\tint shift = 8 * (offset & 3);\n\n\t/* only read on offset 0 */\n\tif (shift != 0)\n\t\treturn chip->read_latch >> (24 - shift);\n\n\t//if (LOG_COMMANDS && eslog)\n\t//\tfprintf(eslog, \"read from %02x/%02x -> \", chip->current_page, offset / 4 * 8);\n\n\t/* force an update */\n\t//chip->stream->update();\n\n\t/* switch off the page and register */\n\tif (chip->current_page < 0x20)\n\t\tchip->read_latch = es5506_reg_read_low(chip, voice, offset / 4);\n\telse if (chip->current_page < 0x40)\n\t\tchip->read_latch = es5506_reg_read_high(chip, voice, offset / 4);\n\telse\n\t\tchip->read_latch = es5506_reg_read_test(chip, voice, offset / 4);\n\n\t//if (LOG_COMMANDS && eslog)\n\t//\tfprintf(eslog, \"%08x\\n\", chip->read_latch);\n\n\t/* return the high byte */\n\treturn chip->read_latch >> 24;\n}\n\n\n\n//void es5506_voice_bank_w(device_t *device, int voice, int bank)\nvoid es5506_voice_bank_w(UINT8 ChipID, int voice, int bank)\n{\n\t//es5506_state *chip = get_safe_token(device);\n\tes5506_state *chip = &ES5506Data[ChipID];\n\tchip->voice[voice].exbank=bank;\n}\n\n\n/**********************************************************************************************\n\n     DEVICE_START( es5505 ) -- start emulation of the ES5505\n\n***********************************************************************************************/\n\n/*static DEVICE_START( es5505 )\n{\n\tconst es5505_interface *intf = (const es5505_interface *)device->static_config();\n\tes5506_interface es5506intf;\n\n\tmemset(&es5506intf, 0, sizeof(es5506intf));\n\n\tes5506intf.region0 = intf->region0;\n\tes5506intf.region1 = intf->region1;\n\tes5506intf.irq_callback = intf->irq_callback;\n\tes5506intf.read_port = intf->read_port;\n\n\tes5506_start_common(device, &es5506intf, ES5505);\n}*/\n\n\n\n/**********************************************************************************************\n\n     DEVICE_STOP( es5505 ) -- stop emulation of the ES5505\n\n***********************************************************************************************/\n\n/*static DEVICE_STOP( es5505 )\n{\n\tDEVICE_STOP_CALL( es5506 );\n}\n\n\nstatic DEVICE_RESET( es5505 )\n{\n\tDEVICE_RESET_CALL( es5506 );\n}*/\n\n\n\n/**********************************************************************************************\n\n     es5505_reg_write -- handle a write to the selected ES5505 register\n\n***********************************************************************************************/\n\nINLINE void es5505_reg_write_low(es5506_state *chip, es5506_voice *voice, offs_t offset, UINT16 data)\n{\n\t//running_machine &machine = chip->device->machine();\n\tUINT8 byteOfs;\n\n\tbyteOfs = offset & 0x01;\n\tif (! byteOfs)\n\t\tdata <<= 8;\n\tswitch (offset >> 1)\n\t{\n\t\tcase 0x00:\t/* CR */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t{\n#if RAINE_CHECK\n\t\t\t\tvoice->control &= ~(CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_DIR);\n#else\n\t\t\t\tvoice->control &= ~(CONTROL_STOPMASK | CONTROL_BS0 | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ);\n#endif\n\t\t\t\tvoice->control |= (data & (CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ)) |\n\t\t\t\t\t\t\t\t  ((data << 12) & CONTROL_BS0);\n\t\t\t}\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t{\n\t\t\t\tvoice->control &= ~(CONTROL_CA0 | CONTROL_CA1 | CONTROL_LPMASK);\n\t\t\t\tvoice->control |= ((data >> 2) & CONTROL_LPMASK) |\n\t\t\t\t\t\t\t\t  ((data << 2) & (CONTROL_CA0 | CONTROL_CA1));\n\t\t\t}\n\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, control=%04x (raw=%04x & %04x)\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->control, data, mem_mask ^ 0xffff);\n\t\t\tbreak;\n\n\t\tcase 0x01:\t/* FC */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->freqcount = (voice->freqcount & ~0x001fe) | ((data & 0x00ff) << 1);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->freqcount = (voice->freqcount & ~0x1fe00) | ((data & 0xff00) << 1);\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, freq count=%08x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->freqcount);\n\t\t\tbreak;\n\n\t\tcase 0x02:\t/* STRT (hi) */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->start = (voice->start & ~0x03fc0000) | ((data & 0x00ff) << 18);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->start = (voice->start & ~0x7c000000) | ((data & 0x1f00) << 18);\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, loop start=%08x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->start);\n\t\t\tbreak;\n\n\t\tcase 0x03:\t/* STRT (lo) */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->start = (voice->start & ~0x00000380) | ((data & 0x00e0) << 2);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->start = (voice->start & ~0x0003fc00) | ((data & 0xff00) << 2);\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, loop start=%08x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->start);\n\t\t\tbreak;\n\n\t\tcase 0x04:\t/* END (hi) */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->end = (voice->end & ~0x03fc0000) | ((data & 0x00ff) << 18);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->end = (voice->end & ~0x7c000000) | ((data & 0x1f00) << 18);\n#if RAINE_CHECK\n\t\t\tvoice->control |= CONTROL_STOP0;\n#endif\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, loop end=%08x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->end);\n\t\t\tbreak;\n\n\t\tcase 0x05:\t/* END (lo) */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->end = (voice->end & ~0x00000380) | ((data & 0x00e0) << 2);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->end = (voice->end & ~0x0003fc00) | ((data & 0xff00) << 2);\n#if RAINE_CHECK\n\t\t\tvoice->control |= CONTROL_STOP0;\n#endif\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, loop end=%08x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->end);\n\t\t\tbreak;\n\n\t\tcase 0x06:\t/* K2 */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->k2 = (voice->k2 & ~0x00f0) | (data & 0x00f0);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->k2 = (voice->k2 & ~0xff00) | (data & 0xff00);\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, K2=%04x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->k2);\n\t\t\tbreak;\n\n\t\tcase 0x07:\t/* K1 */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->k1 = (voice->k1 & ~0x00f0) | (data & 0x00f0);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->k1 = (voice->k1 & ~0xff00) | (data & 0xff00);\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, K1=%04x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->k1);\n\t\t\tbreak;\n\n\t\tcase 0x08:\t/* LVOL */\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->lvol = (voice->lvol & ~0xff00) | (data & 0xff00);\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, left vol=%04x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->lvol);\n\t\t\tbreak;\n\n\t\tcase 0x09:\t/* RVOL */\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->rvol = (voice->rvol & ~0xff00) | (data & 0xff00);\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, right vol=%04x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->rvol);\n\t\t\tbreak;\n\n\t\tcase 0x0a:\t/* ACC (hi) */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->accum = (voice->accum & ~0x03fc0000) | ((data & 0x00ff) << 18);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->accum = (voice->accum & ~0x7c000000) | ((data & 0x1f00) << 18);\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, accum=%08x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->accum);\n\t\t\tbreak;\n\n\t\tcase 0x0b:\t/* ACC (lo) */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->accum = (voice->accum & ~0x000003fc) | ((data & 0x00ff) << 2);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->accum = (voice->accum & ~0x0003fc00) | ((data & 0xff00) << 2);\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, accum=%08x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->accum);\n\t\t\tbreak;\n\n\t\tcase 0x0c:\t/* unused */\n\t\t\tbreak;\n\n\t\tcase 0x0d:\t/* ACT */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t{\n\t\t\t\tchip->active_voices = data & 0x1f;\n\t\t\t\tchip->sample_rate = chip->master_clock / (16 * (chip->active_voices + 1));\n\t\t\t\t//chip->stream->set_sample_rate(chip->sample_rate);\n\t\t\t\tif (chip->SmpRateFunc != NULL)\n\t\t\t\t\tchip->SmpRateFunc(chip->SmpRateData, chip->sample_rate);\n\n\t\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t\t//\tfprintf(eslog, \"active voices=%d, sample_rate=%d\\n\", chip->active_voices, chip->sample_rate);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0x0e:\t/* IRQV - read only */\n\t\t\tbreak;\n\n\t\tcase 0x0f:\t/* PAGE */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tchip->current_page = data & 0x7f;\n\t\t\tbreak;\n\t}\n}\n\n\nINLINE void es5505_reg_write_high(es5506_state *chip, es5506_voice *voice, offs_t offset, UINT16 data)\n{\n\t//running_machine &machine = chip->device->machine();\n\tUINT8 byteOfs;\n\n\tbyteOfs = offset & 0x01;\n\tif (! byteOfs)\n\t\tdata <<= 8;\n\tswitch (offset >> 1)\n\t{\n\t\tcase 0x00:\t/* CR */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t{\n\t\t\t\tvoice->control &= ~(CONTROL_STOPMASK | CONTROL_BS0 | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ);\n\t\t\t\tvoice->control |= (data & (CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ)) |\n\t\t\t\t\t\t\t\t  ((data << 12) & CONTROL_BS0);\n\t\t\t}\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t{\n\t\t\t\tvoice->control &= ~(CONTROL_CA0 | CONTROL_CA1 | CONTROL_LPMASK);\n\t\t\t\tvoice->control |= ((data >> 2) & CONTROL_LPMASK) |\n\t\t\t\t\t\t\t\t  ((data << 2) & (CONTROL_CA0 | CONTROL_CA1));\n\t\t\t}\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, control=%04x (raw=%04x & %04x)\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->control, data, mem_mask);\n\t\t\tbreak;\n\n\t\tcase 0x01:\t/* O4(n-1) */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->o4n1 = (voice->o4n1 & ~0x00ff) | (data & 0x00ff);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->o4n1 = (INT16)((voice->o4n1 & ~0xff00) | (data & 0xff00));\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, O4(n-1)=%05x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->o4n1 & 0x3ffff);\n\t\t\tbreak;\n\n\t\tcase 0x02:\t/* O3(n-1) */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->o3n1 = (voice->o3n1 & ~0x00ff) | (data & 0x00ff);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->o3n1 = (INT16)((voice->o3n1 & ~0xff00) | (data & 0xff00));\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, O3(n-1)=%05x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->o3n1 & 0x3ffff);\n\t\t\tbreak;\n\n\t\tcase 0x03:\t/* O3(n-2) */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->o3n2 = (voice->o3n2 & ~0x00ff) | (data & 0x00ff);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->o3n2 = (INT16)((voice->o3n2 & ~0xff00) | (data & 0xff00));\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, O3(n-2)=%05x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->o3n2 & 0x3ffff);\n\t\t\tbreak;\n\n\t\tcase 0x04:\t/* O2(n-1) */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->o2n1 = (voice->o2n1 & ~0x00ff) | (data & 0x00ff);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->o2n1 = (INT16)((voice->o2n1 & ~0xff00) | (data & 0xff00));\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, O2(n-1)=%05x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->o2n1 & 0x3ffff);\n\t\t\tbreak;\n\n\t\tcase 0x05:\t/* O2(n-2) */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->o2n2 = (voice->o2n2 & ~0x00ff) | (data & 0x00ff);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->o2n2 = (INT16)((voice->o2n2 & ~0xff00) | (data & 0xff00));\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, O2(n-2)=%05x\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->o2n2 & 0x3ffff);\n\t\t\tbreak;\n\n\t\tcase 0x06:\t/* O1(n-1) */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tvoice->o1n1 = (voice->o1n1 & ~0x00ff) | (data & 0x00ff);\n\t\t\tif (ACCESSING_BITS_8_15)\n\t\t\t\tvoice->o1n1 = (INT16)((voice->o1n1 & ~0xff00) | (data & 0xff00));\n\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t//\tfprintf(eslog, \"%s:voice %d, O1(n-1)=%05x (accum=%08x)\\n\", machine.describe_context(), chip->current_page & 0x1f, voice->o2n1 & 0x3ffff, voice->accum);\n\t\t\tbreak;\n\n\t\tcase 0x07:\n\t\tcase 0x08:\n\t\tcase 0x09:\n\t\tcase 0x0a:\n\t\tcase 0x0b:\n\t\tcase 0x0c:\t/* unused */\n\t\t\tbreak;\n\n\t\tcase 0x0d:\t/* ACT */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t{\n\t\t\t\tchip->active_voices = data & 0x1f;\n\t\t\t\tchip->sample_rate = chip->master_clock / (16 * (chip->active_voices + 1));\n\t\t\t\t//chip->stream->set_sample_rate(chip->sample_rate);\n\t\t\t\tif (chip->SmpRateFunc != NULL)\n\t\t\t\t\tchip->SmpRateFunc(chip->SmpRateData, chip->sample_rate);\n\n\t\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t\t//\tfprintf(eslog, \"active voices=%d, sample_rate=%d\\n\", chip->active_voices, chip->sample_rate);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0x0e:\t/* IRQV - read only */\n\t\t\tbreak;\n\n\t\tcase 0x0f:\t/* PAGE */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tchip->current_page = data & 0x7f;\n\t\t\tbreak;\n\t}\n}\n\n\nINLINE void es5505_reg_write_test(es5506_state *chip, es5506_voice *voice, offs_t offset, UINT16 data)\n{\n\tUINT8 byteOfs;\n\n\tbyteOfs = offset & 0x01;\n\tif (! byteOfs)\n\t\tdata <<= 8;\n\tswitch (offset >> 1)\n\t{\n\t\tcase 0x00:\t/* CH0L */\n\t\tcase 0x01:\t/* CH0R */\n\t\tcase 0x02:\t/* CH1L */\n\t\tcase 0x03:\t/* CH1R */\n\t\tcase 0x04:\t/* CH2L */\n\t\tcase 0x05:\t/* CH2R */\n\t\tcase 0x06:\t/* CH3L */\n\t\tcase 0x07:\t/* CH3R */\n\t\t\tbreak;\n\n\t\tcase 0x08:\t/* SERMODE */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tchip->mode = data & 0x07;\n\t\t\tbreak;\n\n\t\tcase 0x09:\t/* PAR */\n\t\t\tbreak;\n\n\t\tcase 0x0d:\t/* ACT */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t{\n\t\t\t\tchip->active_voices = data & 0x1f;\n\t\t\t\tchip->sample_rate = chip->master_clock / (16 * (chip->active_voices + 1));\n\t\t\t\t//chip->stream->set_sample_rate(chip->sample_rate);\n\t\t\t\tif (chip->SmpRateFunc != NULL)\n\t\t\t\t\tchip->SmpRateFunc(chip->SmpRateData, chip->sample_rate);\n\n\t\t\t\t//if (LOG_COMMANDS && eslog)\n\t\t\t\t//\tfprintf(eslog, \"active voices=%d, sample_rate=%d\\n\", chip->active_voices, chip->sample_rate);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0x0e:\t/* IRQV - read only */\n\t\t\tbreak;\n\n\t\tcase 0x0f:\t/* PAGE */\n\t\t\tif (ACCESSING_BITS_0_7)\n\t\t\t\tchip->current_page = data & 0x7f;\n\t\t\tbreak;\n\t}\n}\n\n\n//WRITE16_DEVICE_HANDLER( es5505_w )\nstatic void es5505_w(es5506_state *chip, offs_t offset, UINT8 data)\n{\n\t//es5506_state *chip = get_safe_token(device);\n\tes5506_voice *voice = &chip->voice[chip->current_page & 0x1f];\n\n//  logerror(\"%s:ES5505 write %02x/%02x = %04x & %04x\\n\", machine.describe_context(), chip->current_page, offset, data, mem_mask);\n\n\t/* force an update */\n\t//chip->stream->update();\n\n\t/* switch off the page and register */\n\tif (chip->current_page < 0x20)\n\t\tes5505_reg_write_low(chip, voice, offset, data);\n\telse if (chip->current_page < 0x40)\n\t\tes5505_reg_write_high(chip, voice, offset, data);\n\telse\n\t\tes5505_reg_write_test(chip, voice, offset, data);\n}\n\n\n\n/**********************************************************************************************\n\n     es5505_reg_read -- read from the specified ES5505 register\n\n***********************************************************************************************/\n\nINLINE UINT16 es5505_reg_read_low(es5506_state *chip, es5506_voice *voice, offs_t offset)\n{\n\tUINT16 result = 0;\n\n\tswitch (offset)\n\t{\n\t\tcase 0x00:\t/* CR */\n\t\t\tresult = (voice->control & (CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ)) |\n\t\t\t\t\t ((voice->control & CONTROL_BS0) >> 12) |\n\t\t\t\t\t ((voice->control & CONTROL_LPMASK) << 2) |\n\t\t\t\t\t ((voice->control & (CONTROL_CA0 | CONTROL_CA1)) >> 2) |\n\t\t\t\t\t 0xf000;\n\t\t\tbreak;\n\n\t\tcase 0x01:\t/* FC */\n\t\t\tresult = voice->freqcount >> 1;\n\t\t\tbreak;\n\n\t\tcase 0x02:\t/* STRT (hi) */\n\t\t\tresult = voice->start >> 18;\n\t\t\tbreak;\n\n\t\tcase 0x03:\t/* STRT (lo) */\n\t\t\tresult = voice->start >> 2;\n\t\t\tbreak;\n\n\t\tcase 0x04:\t/* END (hi) */\n\t\t\tresult = voice->end >> 18;\n\t\t\tbreak;\n\n\t\tcase 0x05:\t/* END (lo) */\n\t\t\tresult = voice->end >> 2;\n\t\t\tbreak;\n\n\t\tcase 0x06:\t/* K2 */\n\t\t\tresult = voice->k2;\n\t\t\tbreak;\n\n\t\tcase 0x07:\t/* K1 */\n\t\t\tresult = voice->k1;\n\t\t\tbreak;\n\n\t\tcase 0x08:\t/* LVOL */\n\t\t\tresult = voice->lvol;\n\t\t\tbreak;\n\n\t\tcase 0x09:\t/* RVOL */\n\t\t\tresult = voice->rvol;\n\t\t\tbreak;\n\n\t\tcase 0x0a:\t/* ACC (hi) */\n\t\t\tresult = voice->accum >> 18;\n\t\t\tbreak;\n\n\t\tcase 0x0b:\t/* ACC (lo) */\n\t\t\tresult = voice->accum >> 2;\n\t\t\tbreak;\n\n\t\tcase 0x0c:\t/* unused */\n\t\t\tbreak;\n\n\t\tcase 0x0d:\t/* ACT */\n\t\t\tresult = chip->active_voices;\n\t\t\tbreak;\n\n\t\tcase 0x0e:\t/* IRQV */\n\t\t\tresult = chip->irqv;\n\t\t\tupdate_internal_irq_state(chip);\n\t\t\tbreak;\n\n\t\tcase 0x0f:\t/* PAGE */\n\t\t\tresult = chip->current_page;\n\t\t\tbreak;\n\t}\n\treturn result;\n}\n\n\nINLINE UINT16 es5505_reg_read_high(es5506_state *chip, es5506_voice *voice, offs_t offset)\n{\n\tUINT16 result = 0;\n\n\tswitch (offset)\n\t{\n\t\tcase 0x00:\t/* CR */\n\t\t\tresult = (voice->control & (CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ)) |\n\t\t\t\t\t ((voice->control & CONTROL_BS0) >> 12) |\n\t\t\t\t\t ((voice->control & CONTROL_LPMASK) << 2) |\n\t\t\t\t\t ((voice->control & (CONTROL_CA0 | CONTROL_CA1)) >> 2) |\n\t\t\t\t\t 0xf000;\n\t\t\tbreak;\n\n\t\tcase 0x01:\t/* O4(n-1) */\n\t\t\tresult = voice->o4n1;\n\t\t\tbreak;\n\n\t\tcase 0x02:\t/* O3(n-1) */\n\t\t\tresult = voice->o3n1;\n\t\t\tbreak;\n\n\t\tcase 0x03:\t/* O3(n-2) */\n\t\t\tresult = voice->o3n2;\n\t\t\tbreak;\n\n\t\tcase 0x04:\t/* O2(n-1) */\n\t\t\tresult = voice->o2n1;\n\t\t\tbreak;\n\n\t\tcase 0x05:\t/* O2(n-2) */\n\t\t\tresult = voice->o2n2;\n\t\t\tbreak;\n\n\t\tcase 0x06:\t/* O1(n-1) */\n\t\t\t/* special case for the Taito F3 games: they set the accumulator on a stopped */\n\t\t\t/* voice and assume the filters continue to process the data. They then read */\n\t\t\t/* the O1(n-1) in order to extract raw data from the sound ROMs. Since we don't */\n\t\t\t/* want to waste time filtering stopped channels, we just look for a read from */\n\t\t\t/* this register on a stopped voice, and return the raw sample data at the */\n\t\t\t/* accumulator */\n\t\t\tif ((voice->control & CONTROL_STOPMASK) && chip->region_base[voice->control >> 14])\n\t\t\t{\n\t\t\t\tvoice->o1n1 = chip->region_base[voice->control >> 14][voice->exbank + (voice->accum >> 11)];\n\t\t\t\tlogerror(\"%02x %08x ==> %08x\\n\",voice->o1n1,voice->control >> 14,voice->exbank + (voice->accum >> 11));\n\t\t\t}\n\t\t\tresult = voice->o1n1;\n\t\t\tbreak;\n\n\t\tcase 0x07:\n\t\tcase 0x08:\n\t\tcase 0x09:\n\t\tcase 0x0a:\n\t\tcase 0x0b:\n\t\tcase 0x0c:\t/* unused */\n\t\t\tbreak;\n\n\t\tcase 0x0d:\t/* ACT */\n\t\t\tresult = chip->active_voices;\n\t\t\tbreak;\n\n\t\tcase 0x0e:\t/* IRQV */\n\t\t\tresult = chip->irqv;\n\t\t\tupdate_internal_irq_state(chip);\n\t\t\tbreak;\n\n\t\tcase 0x0f:\t/* PAGE */\n\t\t\tresult = chip->current_page;\n\t\t\tbreak;\n\t}\n\treturn result;\n}\n\n\nINLINE UINT16 es5505_reg_read_test(es5506_state *chip, es5506_voice *voice, offs_t offset)\n{\n\tUINT16 result = 0;\n\n\tswitch (offset)\n\t{\n\t\tcase 0x00:\t/* CH0L */\n\t\tcase 0x01:\t/* CH0R */\n\t\tcase 0x02:\t/* CH1L */\n\t\tcase 0x03:\t/* CH1R */\n\t\tcase 0x04:\t/* CH2L */\n\t\tcase 0x05:\t/* CH2R */\n\t\tcase 0x06:\t/* CH3L */\n\t\tcase 0x07:\t/* CH3R */\n\t\t\tbreak;\n\n\t\tcase 0x08:\t/* SERMODE */\n\t\t\tresult = chip->mode;\n\t\t\tbreak;\n\n\t\tcase 0x09:\t/* PAR */\n\t\t\t//if (chip->port_read)\n\t\t\t//\tresult = (*chip->port_read)();\n\t\t\tbreak;\n\n\t\tcase 0x0f:\t/* PAGE */\n\t\t\tresult = chip->current_page;\n\t\t\tbreak;\n\t}\n\treturn result;\n}\n\n\n//READ16_DEVICE_HANDLER( es5505_r )\nstatic UINT8 es5505_r(es5506_state *chip, offs_t offset)\n{\n\t//es5506_state *chip = get_safe_token(device);\n\tes5506_voice *voice = &chip->voice[chip->current_page & 0x1f];\n\tUINT16 result = 0;\n\n\t//if (LOG_COMMANDS && eslog)\n\t//\tfprintf(eslog, \"read from %02x/%02x -> \", chip->current_page, offset);\n\n\t/* force an update */\n\t//chip->stream->update();\n\n\t/* switch off the page and register */\n\tif (chip->current_page < 0x20)\n\t\tresult = es5505_reg_read_low(chip, voice, offset);\n\telse if (chip->current_page < 0x40)\n\t\tresult = es5505_reg_read_high(chip, voice, offset);\n\telse\n\t\tresult = es5505_reg_read_test(chip, voice, offset);\n\n\t//if (LOG_COMMANDS && eslog)\n\t//\tfprintf(eslog, \"%04x (accum=%08x)\\n\", result, voice->accum);\n\n\t/* return the high byte */\n\tif (offset & 0x01)\n\t\treturn (result & 0x00FF) >> 0;\n\telse\n\t\treturn (result & 0xFF00) >> 8;\n}\n\nUINT8 es550x_r(UINT8 ChipID, offs_t offset)\n{\n\tes5506_state *chip = &ES5506Data[ChipID];\n\t\n\tif (! chip->sndtype)\n\t\treturn es5505_r(chip, offset);\n\telse\n\t\treturn es5506_r(chip, offset);\n}\n\nvoid es550x_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tes5506_state *chip = &ES5506Data[ChipID];\n\t\n\tif (offset < 0x40)\n\t{\n\t\tif (! chip->sndtype)\n\t\t\tes5505_w(chip, offset, data);\n\t\telse\n\t\t\tes5506_w(chip, offset, data);\n\t}\n\telse\n\t{\n\t\tes5506_voice_bank_w(ChipID, offset & 0x1F, data << 20);\n\t}\n\treturn;\n}\n\nvoid es550x_w16(UINT8 ChipID, offs_t offset, UINT16 data)\n{\n\tes5506_state *chip = &ES5506Data[ChipID];\n\t\n\tif (offset < 0x40)\n\t{\n\t\tif (! chip->sndtype)\n\t\t{\n\t\t\tes5505_w(chip, offset | 0, (data & 0xFF00) >> 8);\n\t\t\tes5505_w(chip, offset | 1, (data & 0x00FF) >> 0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tes5506_w(chip, offset | 0, (data & 0xFF00) >> 8);\n\t\t\tes5506_w(chip, offset | 1, (data & 0x00FF) >> 0);\n\t\t}\n\t}\n\telse\n\t{\n\t\tes5506_voice_bank_w(ChipID, offset & 0x1F, data << 20);\n\t}\n\treturn;\n}\n\n\n\n/*void es5505_voice_bank_w(device_t *device, int voice, int bank)\n{\n\t//es5506_state *chip = get_safe_token(device);\n\tes5506_state *chip = &ES5506Data[ChipID];\n#if RAINE_CHECK\n\tchip->voice[voice].control = CONTROL_STOPMASK;\n#endif\n\tchip->voice[voice].exbank=bank;\n}*/\n\n/*void es5505_set_channel_volume(device_t *device, int channel, int volume)\n{\n\t//es5506_state *chip = get_safe_token(device);\n\tes5506_state *chip = &ES5506Data[ChipID];\n\n\tchip->stream->set_output_gain(channel,volume / 100.0);\n}*/\n\nvoid es5506_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData)\n{\n\tes5506_state *info = &ES5506Data[ChipID];\n\tUINT8 curRgn;\n\tUINT8 is8bROM;\n\tUINT32 curPos;\n\t\n\tcurRgn = (DataStart >> 28) & 0x03;\n\tis8bROM = (DataStart >> 31) & 0x01;\n\tDataStart &= 0x0FFFFFFF;\n\t\n\tif (is8bROM)\n\t{\n\t\t// multiply all values with 2 for boundary checks\n\t\tROMSize *= 2;\n\t\tDataStart *= 2;\n\t\tDataLength *= 2;\n\t}\n\tif (info->region_size[curRgn] != ROMSize)\n\t{\n\t\tinfo->region_base[curRgn] = (UINT16*)realloc(info->region_base[curRgn], ROMSize);\n\t\tinfo->region_size[curRgn] = ROMSize;\n\t\tmemset(info->region_base[curRgn], 0x00, ROMSize);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tif (! is8bROM)\n\t{\n\t\tmemcpy((UINT8*)info->region_base[curRgn] + DataStart, ROMData, DataLength);\n\t}\n\telse\n\t{\n\t\tDataLength /= 2;\n\t\tfor (curPos = 0x00; curPos < DataLength; curPos ++)\n\t\t\tinfo->region_base[curRgn][DataStart + curPos] = ROMData[curPos] << 8;\n\t}\n\t\n\treturn;\n}\n\nvoid es5506_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tes5506_state *chip = &ES5506Data[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 32; CurChn ++)\n\t\tchip->voice[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\nvoid es5506_set_srchg_cb(UINT8 ChipID, SRATE_CALLBACK CallbackFunc, void* DataPtr)\n{\n\tes5506_state *chip = &ES5506Data[ChipID];\n\t\n\t// set Sample Rate Change Callback routine\n\tchip->SmpRateFunc = CallbackFunc;\n\tchip->SmpRateData = DataPtr;\n\t\n\treturn;\n}\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( es5505 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(es5506_state);\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( es5505 );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( es5505 );\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( es5505 );\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"ES5505\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Ensoniq Wavetable\");\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( es5506 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(es5506_state);\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( es5506 );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( es5506 );\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( es5506 );\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"ES5506\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Ensoniq Wavetable\");\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}\n\n\nDEFINE_LEGACY_SOUND_DEVICE(ES5505, es5505);\nDEFINE_LEGACY_SOUND_DEVICE(ES5506, es5506);*/\n"
  },
  {
    "path": "VGMPlay/chips/es5506.h",
    "content": "/**********************************************************************************************\n *\n *   Ensoniq ES5505/6 driver\n *   by Aaron Giles\n *\n **********************************************************************************************/\n\n#pragma once\n\n#ifndef __ES5506_H__\n#define __ES5506_H__\n\n//#include \"devlegcy.h\"\n\n/*typedef struct _es5505_interface es5505_interface;\nstruct _es5505_interface\n{\n\tconst char * region0;\t\t\t\t\t\t// memory region where the sample ROM lives\n\tconst char * region1;\t\t\t\t\t\t// memory region where the sample ROM lives\n\tvoid (*irq_callback)(device_t *device, int state);\t// irq callback\n\tUINT16 (*read_port)(device_t *device);\t\t\t// input port read\n};*\n\nREAD16_DEVICE_HANDLER( es5505_r );\nWRITE16_DEVICE_HANDLER( es5505_w );\nvoid es5505_voice_bank_w(device_t *device, int voice, int bank);\nvoid es5505_set_channel_volume(device_t *device, int channel, int volume);\n\n//DECLARE_LEGACY_SOUND_DEVICE(ES5505, es5505);\n\n\ntypedef struct _es5506_interface es5506_interface;\nstruct _es5506_interface\n{\n\tconst char * region0;\t\t\t\t\t\t// memory region where the sample ROM lives\n\tconst char * region1;\t\t\t\t\t\t// memory region where the sample ROM lives\n\tconst char * region2;\t\t\t\t\t\t// memory region where the sample ROM lives\n\tconst char * region3;\t\t\t\t\t\t// memory region where the sample ROM lives\n\tvoid (*irq_callback)(device_t *device, int state);\t// irq callback\n\tUINT16 (*read_port)(device_t *device);\t\t\t// input port read\n};*/\n\n//READ8_DEVICE_HANDLER( es5506_r );\n//WRITE8_DEVICE_HANDLER( es5506_w );\nUINT8 es550x_r(UINT8 ChipID, offs_t offset);\nvoid es550x_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid es550x_w16(UINT8 ChipID, offs_t offset, UINT16 data);\n\nvoid es5506_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_es5506(UINT8 ChipID, int clock, int channels);\nvoid device_stop_es5506(UINT8 ChipID);\nvoid device_reset_es5506(UINT8 ChipID);\n//void es5506_set_base(running_device *device, UINT8 *wavemem);\n\nvoid es5506_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData);\n\nvoid es5506_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\nvoid es5506_set_srchg_cb(UINT8 ChipID, SRATE_CALLBACK CallbackFunc, void* DataPtr);\n\n//void es5506_voice_bank_w(device_t *device, int voice, int bank);\n\n//DECLARE_LEGACY_SOUND_DEVICE(ES5506, es5506);\n\n#endif /* __ES5506_H__ */\n"
  },
  {
    "path": "VGMPlay/chips/fm.c",
    "content": "#define YM2610B_WARNING\n\n/*\n**\n** File: fm.c -- software implementation of Yamaha FM sound generator\n**\n** Copyright Jarek Burczynski (bujar at mame dot net)\n** Copyright Tatsuyuki Satoh , MultiArcadeMachineEmulator development\n**\n** Version 1.4.2 (final beta)\n**\n*/\n\n/*\n** History:\n**\n** 2006-2008 Eke-Eke (Genesis Plus GX), MAME backport by R. Belmont.\n**  - implemented PG overflow, aka \"detune bug\" (Ariel, Comix Zone, Shaq Fu, Spiderman,...), credits to Nemesis\n**  - fixed SSG-EG support, credits to Nemesis and additional fixes from Alone Coder\n**  - modified EG rates and frequency, tested by Nemesis on real hardware\n**  - implemented LFO phase update for CH3 special mode (Warlock birds, Alladin bug sound)\n**  - fixed Attack Rate update (Batman & Robin intro)\n**  - fixed attenuation level at the start of Substain (Gynoug explosions)\n**  - fixed EG decay->substain transition to handle special cases, like SL=0 and Decay rate is very slow (Mega Turrican tracks 03,09...)\n**\n** 06-23-2007 Zsolt Vasvari:\n**  - changed the timing not to require the use of floating point calculations\n**\n** 03-08-2003 Jarek Burczynski:\n**  - fixed YM2608 initial values (after the reset)\n**  - fixed flag and irqmask handling (YM2608)\n**  - fixed BUFRDY flag handling (YM2608)\n**\n** 14-06-2003 Jarek Burczynski:\n**  - implemented all of the YM2608 status register flags\n**  - implemented support for external memory read/write via YM2608\n**  - implemented support for deltat memory limit register in YM2608 emulation\n**\n** 22-05-2003 Jarek Burczynski:\n**  - fixed LFO PM calculations (copy&paste bugfix)\n**\n** 08-05-2003 Jarek Burczynski:\n**  - fixed SSG support\n**\n** 22-04-2003 Jarek Burczynski:\n**  - implemented 100% correct LFO generator (verified on real YM2610 and YM2608)\n**\n** 15-04-2003 Jarek Burczynski:\n**  - added support for YM2608's register 0x110 - status mask\n**\n** 01-12-2002 Jarek Burczynski:\n**  - fixed register addressing in YM2608, YM2610, YM2610B chips. (verified on real YM2608)\n**    The addressing patch used for early Neo-Geo games can be removed now.\n**\n** 26-11-2002 Jarek Burczynski, Nicola Salmoria:\n**  - recreated YM2608 ADPCM ROM using data from real YM2608's output which leads to:\n**  - added emulation of YM2608 drums.\n**  - output of YM2608 is two times lower now - same as YM2610 (verified on real YM2608)\n**\n** 16-08-2002 Jarek Burczynski:\n**  - binary exact Envelope Generator (verified on real YM2203);\n**    identical to YM2151\n**  - corrected 'off by one' error in feedback calculations (when feedback is off)\n**  - corrected connection (algorithm) calculation (verified on real YM2203 and YM2610)\n**\n** 18-12-2001 Jarek Burczynski:\n**  - added SSG-EG support (verified on real YM2203)\n**\n** 12-08-2001 Jarek Burczynski:\n**  - corrected sin_tab and tl_tab data (verified on real chip)\n**  - corrected feedback calculations (verified on real chip)\n**  - corrected phase generator calculations (verified on real chip)\n**  - corrected envelope generator calculations (verified on real chip)\n**  - corrected FM volume level (YM2610 and YM2610B).\n**  - changed YMxxxUpdateOne() functions (YM2203, YM2608, YM2610, YM2610B, YM2612) :\n**    this was needed to calculate YM2610 FM channels output correctly.\n**    (Each FM channel is calculated as in other chips, but the output of the channel\n**    gets shifted right by one *before* sending to accumulator. That was impossible to do\n**    with previous implementation).\n**\n** 23-07-2001 Jarek Burczynski, Nicola Salmoria:\n**  - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip)\n**\n** 11-06-2001 Jarek Burczynski:\n**  - corrected end of sample bug in ADPCMA_calc_cha().\n**    Real YM2610 checks for equality between current and end addresses (only 20 LSB bits).\n**\n** 08-12-98 hiro-shi:\n** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA\n** move ROM limit check.(CALC_CH? -> 2610Write1/2)\n** test program (ADPCMB_TEST)\n** move ADPCM A/B end check.\n** ADPCMB repeat flag(no check)\n** change ADPCM volume rate (8->16) (32->48).\n**\n** 09-12-98 hiro-shi:\n** change ADPCM volume. (8->16, 48->64)\n** replace ym2610 ch0/3 (YM-2610B)\n** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff.\n** add ADPCM_SHIFT_MASK\n** change ADPCMA_DECODE_MIN/MAX.\n*/\n\n\n\n\n/************************************************************************/\n/*    comment of hiro-shi(Hiromitsu Shioya)                             */\n/*    YM2610(B) = OPN-B                                                 */\n/*    YM2610  : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch      */\n/*    YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch      */\n/************************************************************************/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdarg.h>\n#include <math.h>\n\n#include \"mamedef.h\"\n//#ifndef __RAINE__\n//#include \"sndintrf.h\"\t\t/* use M.A.M.E. */\n//#else\n//#include \"deftypes.h\"\t\t/* use RAINE */\n//#include \"support.h\"\t\t/* use RAINE */\n//#endif\n#include \"fm.h\"\n\n\n/* include external DELTA-T unit (when needed) */\n#if (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B)\n\t#include \"ymdeltat.h\"\n#endif\n\n/* shared function building option */\n#define BUILD_OPN (BUILD_YM2203||BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B)\n#define BUILD_OPN_PRESCALER (BUILD_YM2203||BUILD_YM2608)\n\n\n/* globals */\n#define TYPE_SSG    0x01    /* SSG support          */\n#define TYPE_LFOPAN 0x02    /* OPN type LFO and PAN */\n#define TYPE_6CH    0x04    /* FM 6CH / 3CH         */\n#define TYPE_DAC    0x08    /* YM2612's DAC device  */\n#define TYPE_ADPCM  0x10    /* two ADPCM units      */\n#define TYPE_2610   0x20    /* bogus flag to differentiate 2608 from 2610 */\n\n\n#define TYPE_YM2203 (TYPE_SSG)\n#define TYPE_YM2608 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM)\n#define TYPE_YM2610 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM |TYPE_2610)\n\n\n\n#define FREQ_SH\t\t\t16  /* 16.16 fixed point (frequency calculations) */\n#define EG_SH\t\t\t16  /* 16.16 fixed point (envelope generator timing) */\n#define LFO_SH\t\t\t24  /*  8.24 fixed point (LFO calculations)       */\n#define TIMER_SH\t\t16  /* 16.16 fixed point (timers calculations)    */\n\n#define FREQ_MASK\t\t((1<<FREQ_SH)-1)\n\n#define ENV_BITS\t\t10\n#define ENV_LEN\t\t\t(1<<ENV_BITS)\n#define ENV_STEP\t\t(128.0/ENV_LEN)\n\n#define MAX_ATT_INDEX\t(ENV_LEN-1) /* 1023 */\n#define MIN_ATT_INDEX\t(0)\t\t\t/* 0 */\n\n#define EG_ATT\t\t\t4\n#define EG_DEC\t\t\t3\n#define EG_SUS\t\t\t2\n#define EG_REL\t\t\t1\n#define EG_OFF\t\t\t0\n\n#define SIN_BITS\t\t10\n#define SIN_LEN\t\t\t(1<<SIN_BITS)\n#define SIN_MASK\t\t(SIN_LEN-1)\n\n#define TL_RES_LEN\t\t(256) /* 8 bits addressing (real chip) */\n\n\n#if (FM_SAMPLE_BITS==16)\n\t#define FINAL_SH\t(0)\n\t#define MAXOUT\t\t(+32767)\n\t#define MINOUT\t\t(-32768)\n#else\n\t#define FINAL_SH\t(8)\n\t#define MAXOUT\t\t(+127)\n\t#define MINOUT\t\t(-128)\n#endif\n\n\n/*  TL_TAB_LEN is calculated as:\n*   13 - sinus amplitude bits     (Y axis)\n*   2  - sinus sign bit           (Y axis)\n*   TL_RES_LEN - sinus resolution (X axis)\n*/\n#define TL_TAB_LEN (13*2*TL_RES_LEN)\nstatic signed int tl_tab[TL_TAB_LEN];\n\n#define ENV_QUIET\t\t(TL_TAB_LEN>>3)\n\n/* sin waveform table in 'decibel' scale */\nstatic unsigned int sin_tab[SIN_LEN];\n\n/* sustain level table (3dB per step) */\n/* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */\n/* 1,    2,    4,    8,    16,   32,   64   (value)*/\n/* 0.75, 1.5,  3,    6,    12,   24,   48   (dB)*/\n\n/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/\n#define SC(db) (UINT32) ( db * (4.0/ENV_STEP) )\nstatic const UINT32 sl_table[16]={\n SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),\n SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)\n};\n#undef SC\n\n\n#define RATE_STEPS (8)\nstatic const UINT8 eg_inc[19*RATE_STEPS]={\n\n/*cycle:0 1  2 3  4 5  6 7*/\n\n/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */\n/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */\n/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */\n/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */\n\n/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */\n/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */\n/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */\n/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */\n\n/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */\n/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */\n/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */\n/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */\n\n/*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */\n/*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */\n/*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */\n/*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */\n\n/*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */\n/*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */\n/*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */\n};\n\n\n#define O(a) (a*RATE_STEPS)\n\n/*note that there is no O(17) in this table - it's directly in the code */\nstatic const UINT8 eg_rate_select[32+64+32]={\t/* Envelope Generator rates (32 + 64 rates + 32 RKS) */\n/* 32 infinite time rates */\nO(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\nO(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\nO(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\nO(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\n\n/* rates 00-11 */\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\n\n/* rate 12 */\nO( 4),O( 5),O( 6),O( 7),\n\n/* rate 13 */\nO( 8),O( 9),O(10),O(11),\n\n/* rate 14 */\nO(12),O(13),O(14),O(15),\n\n/* rate 15 */\nO(16),O(16),O(16),O(16),\n\n/* 32 dummy rates (same as 15 3) */\nO(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\nO(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\nO(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\nO(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16)\n\n};\n\n#undef O\n\n/*rate  0,    1,    2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15*/\n/*shift 11,  10,  9,  8,  7,  6,  5,  4,  3,  2, 1,  0,  0,  0,  0,  0 */\n/*mask  2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3, 1,  0,  0,  0,  0,  0 */\n\n#define O(a) (a*1)\nstatic const UINT8 eg_rate_shift[32+64+32]={\t/* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */\n/* 32 infinite time rates */\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\n\n/* rates 00-11 */\nO(11),O(11),O(11),O(11),\nO(10),O(10),O(10),O(10),\nO( 9),O( 9),O( 9),O( 9),\nO( 8),O( 8),O( 8),O( 8),\nO( 7),O( 7),O( 7),O( 7),\nO( 6),O( 6),O( 6),O( 6),\nO( 5),O( 5),O( 5),O( 5),\nO( 4),O( 4),O( 4),O( 4),\nO( 3),O( 3),O( 3),O( 3),\nO( 2),O( 2),O( 2),O( 2),\nO( 1),O( 1),O( 1),O( 1),\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 12 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 13 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 14 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 15 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* 32 dummy rates (same as 15 3) */\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0)\n\n};\n#undef O\n\nstatic const UINT8 dt_tab[4 * 32]={\n/* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/\n/* FD=0 */\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n/* FD=1 */\n\t0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,\n\t2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,\n/* FD=2 */\n\t1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,\n\t5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,\n/* FD=3 */\n\t2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,\n\t8 , 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22\n};\n\n\n/* OPN key frequency number -> key code follow table */\n/* fnum higher 4bit -> keycode lower 2bit */\nstatic const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};\n\n\n/* 8 LFO speed parameters */\n/* each value represents number of samples that one LFO level will last for */\nstatic const UINT32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5};\n\n\n\n/*There are 4 different LFO AM depths available, they are:\n  0 dB, 1.4 dB, 5.9 dB, 11.8 dB\n  Here is how it is generated (in EG steps):\n\n  11.8 dB = 0, 2, 4, 6, 8, 10,12,14,16...126,126,124,122,120,118,....4,2,0\n   5.9 dB = 0, 1, 2, 3, 4, 5, 6, 7, 8....63, 63, 62, 61, 60, 59,.....2,1,0\n   1.4 dB = 0, 0, 0, 0, 1, 1, 1, 1, 2,...15, 15, 15, 15, 14, 14,.....0,0,0\n\n  (1.4 dB is losing precision as you can see)\n\n  It's implemented as generator from 0..126 with step 2 then a shift\n  right N times, where N is:\n    8 for 0 dB\n    3 for 1.4 dB\n    1 for 5.9 dB\n    0 for 11.8 dB\n*/\nstatic const UINT8 lfo_ams_depth_shift[4] = {8, 3, 1, 0};\n\n\n\n/*There are 8 different LFO PM depths available, they are:\n  0, 3.4, 6.7, 10, 14, 20, 40, 80 (cents)\n\n  Modulation level at each depth depends on F-NUMBER bits: 4,5,6,7,8,9,10\n  (bits 8,9,10 = FNUM MSB from OCT/FNUM register)\n\n  Here we store only first quarter (positive one) of full waveform.\n  Full table (lfo_pm_table) containing all 128 waveforms is build\n  at run (init) time.\n\n  One value in table below represents 4 (four) basic LFO steps\n  (1 PM step = 4 AM steps).\n\n  For example:\n   at LFO SPEED=0 (which is 108 samples per basic LFO step)\n   one value from \"lfo_pm_output\" table lasts for 432 consecutive\n   samples (4*108=432) and one full LFO waveform cycle lasts for 13824\n   samples (32*432=13824; 32 because we store only a quarter of whole\n            waveform in the table below)\n*/\nstatic const UINT8 lfo_pm_output[7*8][8]={ /* 7 bits meaningful (of F-NUMBER), 8 LFO output levels per one depth (out of 32), 8 LFO depths */\n/* FNUM BIT 4: 000 0001xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 2 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 3 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 4 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 5 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 6 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 7 */ {0,   0,   0,   0,   1,   1,   1,   1},\n\n/* FNUM BIT 5: 000 0010xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 2 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 3 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 4 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 5 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 6 */ {0,   0,   0,   0,   1,   1,   1,   1},\n/* DEPTH 7 */ {0,   0,   1,   1,   2,   2,   2,   3},\n\n/* FNUM BIT 6: 000 0100xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 2 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 3 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 4 */ {0,   0,   0,   0,   0,   0,   0,   1},\n/* DEPTH 5 */ {0,   0,   0,   0,   1,   1,   1,   1},\n/* DEPTH 6 */ {0,   0,   1,   1,   2,   2,   2,   3},\n/* DEPTH 7 */ {0,   0,   2,   3,   4,   4,   5,   6},\n\n/* FNUM BIT 7: 000 1000xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 2 */ {0,   0,   0,   0,   0,   0,   1,   1},\n/* DEPTH 3 */ {0,   0,   0,   0,   1,   1,   1,   1},\n/* DEPTH 4 */ {0,   0,   0,   1,   1,   1,   1,   2},\n/* DEPTH 5 */ {0,   0,   1,   1,   2,   2,   2,   3},\n/* DEPTH 6 */ {0,   0,   2,   3,   4,   4,   5,   6},\n/* DEPTH 7 */ {0,   0,   4,   6,   8,   8, 0xa, 0xc},\n\n/* FNUM BIT 8: 001 0000xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   1,   1,   1,   1},\n/* DEPTH 2 */ {0,   0,   0,   1,   1,   1,   2,   2},\n/* DEPTH 3 */ {0,   0,   1,   1,   2,   2,   3,   3},\n/* DEPTH 4 */ {0,   0,   1,   2,   2,   2,   3,   4},\n/* DEPTH 5 */ {0,   0,   2,   3,   4,   4,   5,   6},\n/* DEPTH 6 */ {0,   0,   4,   6,   8,   8, 0xa, 0xc},\n/* DEPTH 7 */ {0,   0,   8, 0xc,0x10,0x10,0x14,0x18},\n\n/* FNUM BIT 9: 010 0000xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   2,   2,   2,   2},\n/* DEPTH 2 */ {0,   0,   0,   2,   2,   2,   4,   4},\n/* DEPTH 3 */ {0,   0,   2,   2,   4,   4,   6,   6},\n/* DEPTH 4 */ {0,   0,   2,   4,   4,   4,   6,   8},\n/* DEPTH 5 */ {0,   0,   4,   6,   8,   8, 0xa, 0xc},\n/* DEPTH 6 */ {0,   0,   8, 0xc,0x10,0x10,0x14,0x18},\n/* DEPTH 7 */ {0,   0,0x10,0x18,0x20,0x20,0x28,0x30},\n\n/* FNUM BIT10: 100 0000xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   4,   4,   4,   4},\n/* DEPTH 2 */ {0,   0,   0,   4,   4,   4,   8,   8},\n/* DEPTH 3 */ {0,   0,   4,   4,   8,   8, 0xc, 0xc},\n/* DEPTH 4 */ {0,   0,   4,   8,   8,   8, 0xc,0x10},\n/* DEPTH 5 */ {0,   0,   8, 0xc,0x10,0x10,0x14,0x18},\n/* DEPTH 6 */ {0,   0,0x10,0x18,0x20,0x20,0x28,0x30},\n/* DEPTH 7 */ {0,   0,0x20,0x30,0x40,0x40,0x50,0x60},\n\n};\n\n/* all 128 LFO PM waveforms */\nstatic INT32 lfo_pm_table[128*8*32]; /* 128 combinations of 7 bits meaningful (of F-NUMBER), 8 LFO depths, 32 LFO output levels per one depth */\n\n\n\n\n\n/* register number to channel number , slot offset */\n#define OPN_CHAN(N) (N&3)\n#define OPN_SLOT(N) ((N>>2)&3)\n\n/* slot number */\n#define SLOT1 0\n#define SLOT2 2\n#define SLOT3 1\n#define SLOT4 3\n\n/* bit0 = Right enable , bit1 = Left enable */\n#define OUTD_RIGHT  1\n#define OUTD_LEFT   2\n#define OUTD_CENTER 3\n\n\n/* save output as raw 16-bit sample */\n/* #define SAVE_SAMPLE */\n\n#ifdef SAVE_SAMPLE\nstatic FILE *sample[1];\n\t#if 1\t/*save to MONO file */\n\t\t#define SAVE_ALL_CHANNELS \\\n\t\t{\tsigned int pom = lt; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t}\n\t#else\t/*save to STEREO file */\n\t\t#define SAVE_ALL_CHANNELS \\\n\t\t{\tsigned int pom = lt; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t\tpom = rt; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t}\n\t#endif\n#endif\n\n\n/* struct describing a single operator (SLOT) */\ntypedef struct\n{\n\tINT32\t*DT;\t\t/* detune          :dt_tab[DT] */\n\tUINT8\tKSR;\t\t/* key scale rate  :3-KSR */\n\tUINT32\tar;\t\t\t/* attack rate  */\n\tUINT32\td1r;\t\t/* decay rate   */\n\tUINT32\td2r;\t\t/* sustain rate */\n\tUINT32\trr;\t\t\t/* release rate */\n\tUINT8\tksr;\t\t/* key scale rate  :kcode>>(3-KSR) */\n\tUINT32\tmul;\t\t/* multiple        :ML_TABLE[ML] */\n\n\t/* Phase Generator */\n\tUINT32\tphase;\t\t/* phase counter */\n\tINT32\tIncr;\t\t/* phase step */\n\n\t/* Envelope Generator */\n\tUINT8\tstate;\t\t/* phase type */\n\tUINT32\ttl;\t\t\t/* total level: TL << 3 */\n\tINT32\tvolume;\t\t/* envelope counter */\n\tUINT32\tsl;\t\t\t/* sustain level:sl_table[SL] */\n\tUINT32\tvol_out;\t/* current output from EG circuit (without AM from LFO) */\n\n\tUINT8\teg_sh_ar;\t/*  (attack state) */\n\tUINT8\teg_sel_ar;\t/*  (attack state) */\n\tUINT8\teg_sh_d1r;\t/*  (decay state) */\n\tUINT8\teg_sel_d1r;\t/*  (decay state) */\n\tUINT8\teg_sh_d2r;\t/*  (sustain state) */\n\tUINT8\teg_sel_d2r;\t/*  (sustain state) */\n\tUINT8\teg_sh_rr;\t/*  (release state) */\n\tUINT8\teg_sel_rr;\t/*  (release state) */\n\n\tUINT8\tssg;\t\t/* SSG-EG waveform */\n\tUINT8\tssgn;\t\t/* SSG-EG negated output */\n\n\tUINT32\tkey;\t\t/* 0=last key was KEY OFF, 1=KEY ON */\n\n\t/* LFO */\n\tUINT32\tAMmask;\t\t/* AM enable flag */\n\n} FM_SLOT;\n\ntypedef struct\n{\n\tFM_SLOT\tSLOT[4];\t/* four SLOTs (operators) */\n\n\tUINT8\tALGO;\t\t/* algorithm */\n\tUINT8\tFB;\t\t\t/* feedback shift */\n\tINT32\top1_out[2];\t/* op1 output for feedback */\n\n\tINT32\t*connect1;\t/* SLOT1 output pointer */\n\tINT32\t*connect3;\t/* SLOT3 output pointer */\n\tINT32\t*connect2;\t/* SLOT2 output pointer */\n\tINT32\t*connect4;\t/* SLOT4 output pointer */\n\n\tINT32\t*mem_connect;/* where to put the delayed sample (MEM) */\n\tINT32\tmem_value;\t/* delayed sample (MEM) value */\n\n\tINT32\tpms;\t\t/* channel PMS */\n\tUINT8\tams;\t\t/* channel AMS */\n\n\tUINT32\tfc;\t\t\t/* fnum,blk:adjusted to sample rate */\n\tUINT8\tkcode;\t\t/* key code:                        */\n\tUINT32\tblock_fnum;\t/* current blk/fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */\n\tUINT8\tMuted;\n} FM_CH;\n\n\ntypedef struct\n{\n\t//const device_config *device;\n\tvoid *\t\tparam;\t\t\t\t/* this chip parameter  */\n\tint\t\t\tclock;\t\t\t\t/* master clock  (Hz)   */\n\tint\t\t\trate;\t\t\t\t/* sampling rate (Hz)   */\n\tdouble\t\tfreqbase;\t\t\t/* frequency base       */\n\tint\t\t\ttimer_prescaler;\t/* timer prescaler      */\n#if FM_BUSY_FLAG_SUPPORT\n\tTIME_TYPE\tbusy_expiry_time;\t/* expiry time of the busy status */\n#endif\n\tUINT8\t\taddress;\t\t\t/* address register     */\n\tUINT8\t\tirq;\t\t\t\t/* interrupt level      */\n\tUINT8\t\tirqmask;\t\t\t/* irq mask             */\n\tUINT8\t\tstatus;\t\t\t\t/* status flag          */\n\tUINT32\t\tmode;\t\t\t\t/* mode  CSM / 3SLOT    */\n\tUINT8\t\tprescaler_sel;\t\t/* prescaler selector   */\n\tUINT8\t\tfn_h;\t\t\t\t/* freq latch           */\n\tINT32\t\tTA;\t\t\t\t\t/* timer a              */\n\tINT32\t\tTAC;\t\t\t\t/* timer a counter      */\n\tUINT8\t\tTB;\t\t\t\t\t/* timer b              */\n\tINT32\t\tTBC;\t\t\t\t/* timer b counter      */\n\t/* local time tables */\n\tINT32\t\tdt_tab[8][32];\t\t/* DeTune table         */\n\t/* Extention Timer and IRQ handler */\n\tFM_TIMERHANDLER\ttimer_handler;\n\tFM_IRQHANDLER\tIRQ_Handler;\n\tconst ssg_callbacks *SSG;\n} FM_ST;\n\n\n\n/***********************************************************/\n/* OPN unit                                                */\n/***********************************************************/\n\n/* OPN 3slot struct */\ntypedef struct\n{\n\tUINT32  fc[3];\t\t\t/* fnum3,blk3: calculated */\n\tUINT8\tfn_h;\t\t\t/* freq3 latch */\n\tUINT8\tkcode[3];\t\t/* key code */\n\tUINT32\tblock_fnum[3];\t/* current fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */\n} FM_3SLOT;\n\n/* OPN/A/B common state */\ntypedef struct\n{\n\tUINT8\ttype;\t\t\t/* chip type */\n\tFM_ST\tST;\t\t\t\t/* general state */\n\tFM_3SLOT SL3;\t\t\t/* 3 slot mode state */\n\tFM_CH\t*P_CH;\t\t\t/* pointer of CH */\n\tunsigned int pan[6*2];\t/* fm channels output masks (0xffffffff = enable) */\n\n\tUINT32\teg_cnt;\t\t\t/* global envelope generator counter */\n\tUINT32\teg_timer;\t\t/* global envelope generator counter works at frequency = chipclock/64/3 */\n\tUINT32\teg_timer_add;\t/* step of eg_timer */\n\tUINT32\teg_timer_overflow;/* envelope generator timer overlfows every 3 samples (on real chip) */\n\n\n\t/* there are 2048 FNUMs that can be generated using FNUM/BLK registers\n        but LFO works with one more bit of a precision so we really need 4096 elements */\n\n\tUINT32\tfn_table[4096];\t/* fnumber->increment counter */\n\tUINT32 fn_max;    /* maximal phase increment (used for phase overflow) */\n\n\t/* LFO */\n\tUINT32\tLFO_AM;\t\t\t/* runtime LFO calculations helper */\n\tINT32\tLFO_PM;\t\t\t/* runtime LFO calculations helper */\n\n\tUINT32\tlfo_cnt;\n\tUINT32\tlfo_inc;\n\n\tUINT32\tlfo_freq[8];\t/* LFO FREQ table */\n\n\tINT32\tm2,c1,c2;\t\t/* Phase Modulation input for operators 2,3,4 */\n\tINT32\tmem;\t\t\t/* one sample delay memory */\n\n\tINT32\tout_fm[8];\t\t/* outputs of working channels */\n\n#if (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B)\n\tINT32\tout_adpcm[4];\t/* channel output NONE,LEFT,RIGHT or CENTER for YM2608/YM2610 ADPCM */\n\tINT32\tout_delta[4];\t/* channel output NONE,LEFT,RIGHT or CENTER for YM2608/YM2610 DELTAT*/\n#endif\n} FM_OPN;\n\n\n\n/* log output level */\n#define LOG_ERR  3      /* ERROR       */\n#define LOG_WAR  2      /* WARNING     */\n#define LOG_INF  1      /* INFORMATION */\n#define LOG_LEVEL LOG_INF\n\n#ifndef __RAINE__\n#define LOG(n,x) do { if( (n)>=LOG_LEVEL ) logerror x; } while (0)\n#endif\n\n/* limitter */\n#define Limit(val, max,min) { \\\n\tif ( val > max )      val = max; \\\n\telse if ( val < min ) val = min; \\\n}\n\n\n/* status set and IRQ handling */\nINLINE void FM_STATUS_SET(FM_ST *ST,int flag)\n{\n\t/* set status flag */\n\tST->status |= flag;\n\tif ( !(ST->irq) && (ST->status & ST->irqmask) )\n\t{\n\t\tST->irq = 1;\n\t\t/* callback user interrupt handler (IRQ is OFF to ON) */\n\t\tif(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->param,1);\n\t}\n}\n\n/* status reset and IRQ handling */\nINLINE void FM_STATUS_RESET(FM_ST *ST,int flag)\n{\n\t/* reset status flag */\n\tST->status &=~flag;\n\tif ( (ST->irq) && !(ST->status & ST->irqmask) )\n\t{\n\t\tST->irq = 0;\n\t\t/* callback user interrupt handler (IRQ is ON to OFF) */\n\t\tif(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->param,0);\n\t}\n}\n\n/* IRQ mask set */\nINLINE void FM_IRQMASK_SET(FM_ST *ST,int flag)\n{\n\tST->irqmask = flag;\n\t/* IRQ handling check */\n\tFM_STATUS_SET(ST,0);\n\tFM_STATUS_RESET(ST,0);\n}\n\n/* OPN Mode Register Write */\nINLINE void set_timers( FM_ST *ST, void *n, int v )\n{\n\t/* b7 = CSM MODE */\n\t/* b6 = 3 slot mode */\n\t/* b5 = reset b */\n\t/* b4 = reset a */\n\t/* b3 = timer enable b */\n\t/* b2 = timer enable a */\n\t/* b1 = load b */\n\t/* b0 = load a */\n\tST->mode = v;\n\n\t/* reset Timer b flag */\n\tif( v & 0x20 )\n\t\tFM_STATUS_RESET(ST,0x02);\n\t/* reset Timer a flag */\n\tif( v & 0x10 )\n\t\tFM_STATUS_RESET(ST,0x01);\n\t/* load b */\n\tif( v & 0x02 )\n\t{\n\t\tif( ST->TBC == 0 )\n\t\t{\n\t\t\tST->TBC = ( 256-ST->TB)<<4;\n\t\t\t/* External timer handler */\n\t\t\tif (ST->timer_handler) (ST->timer_handler)(n,1,ST->TBC * ST->timer_prescaler,ST->clock);\n\t\t}\n\t}\n\telse\n\t{\t/* stop timer b */\n\t\tif( ST->TBC != 0 )\n\t\t{\n\t\t\tST->TBC = 0;\n\t\t\tif (ST->timer_handler) (ST->timer_handler)(n,1,0,ST->clock);\n\t\t}\n\t}\n\t/* load a */\n\tif( v & 0x01 )\n\t{\n\t\tif( ST->TAC == 0 )\n\t\t{\n\t\t\tST->TAC = (1024-ST->TA);\n\t\t\t/* External timer handler */\n\t\t\tif (ST->timer_handler) (ST->timer_handler)(n,0,ST->TAC * ST->timer_prescaler,ST->clock);\n\t\t}\n\t}\n\telse\n\t{\t/* stop timer a */\n\t\tif( ST->TAC != 0 )\n\t\t{\n\t\t\tST->TAC = 0;\n\t\t\tif (ST->timer_handler) (ST->timer_handler)(n,0,0,ST->clock);\n\t\t}\n\t}\n}\n\n\n/* Timer A Overflow */\nINLINE void TimerAOver(FM_ST *ST)\n{\n\t/* set status (if enabled) */\n\tif(ST->mode & 0x04) FM_STATUS_SET(ST,0x01);\n\t/* clear or reload the counter */\n\tST->TAC = (1024-ST->TA);\n\tif (ST->timer_handler) (ST->timer_handler)(ST->param,0,ST->TAC * ST->timer_prescaler,ST->clock);\n}\n/* Timer B Overflow */\nINLINE void TimerBOver(FM_ST *ST)\n{\n\t/* set status (if enabled) */\n\tif(ST->mode & 0x08) FM_STATUS_SET(ST,0x02);\n\t/* clear or reload the counter */\n\tST->TBC = ( 256-ST->TB)<<4;\n\tif (ST->timer_handler) (ST->timer_handler)(ST->param,1,ST->TBC * ST->timer_prescaler,ST->clock);\n}\n\n\n#if FM_INTERNAL_TIMER\n/* ----- internal timer mode , update timer */\n\n/* ---------- calculate timer A ---------- */\n\t#define INTERNAL_TIMER_A(ST,CSM_CH)\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( (ST)->TAC &&  ((ST)->timer_handler==0) )\t\t\\\n\t\t\tif( ((ST)->TAC -= (int)((ST)->freqbase*4096)) <= 0 )\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tTimerAOver( ST );\t\t\t\t\t\t\\\n\t\t\t\t/* CSM mode total level latch and auto key on */\t\\\n\t\t\t\tif( (ST)->mode & 0x80 )\t\t\t\t\t\\\n\t\t\t\t\tCSMKeyControll( OPN->type, CSM_CH );\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\n/* ---------- calculate timer B ---------- */\n\t#define INTERNAL_TIMER_B(ST,step)\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( (ST)->TBC && ((ST)->timer_handler==0) )\t\t\t\t\\\n\t\t\tif( ((ST)->TBC -= (int)((ST)->freqbase*4096*step)) <= 0 )\t\\\n\t\t\t\tTimerBOver( ST );\t\t\t\t\t\t\t\\\n\t}\n#else /* FM_INTERNAL_TIMER */\n/* external timer mode */\n#define INTERNAL_TIMER_A(ST,CSM_CH)\n#define INTERNAL_TIMER_B(ST,step)\n#endif /* FM_INTERNAL_TIMER */\n\n\n\n#if FM_BUSY_FLAG_SUPPORT\n#define FM_BUSY_CLEAR(ST) ((ST)->busy_expiry_time = UNDEFINED_TIME)\nINLINE UINT8 FM_STATUS_FLAG(FM_ST *ST)\n{\n\tif( COMPARE_TIMES(ST->busy_expiry_time, UNDEFINED_TIME) != 0 )\n\t{\n\t\tif (COMPARE_TIMES(ST->busy_expiry_time, FM_GET_TIME_NOW(ST->device->machine)) > 0)\n\t\t\treturn ST->status | 0x80;\t/* with busy */\n\t\t/* expire */\n\t\tFM_BUSY_CLEAR(ST);\n\t}\n\treturn ST->status;\n}\nINLINE void FM_BUSY_SET(FM_ST *ST,int busyclock )\n{\n\tTIME_TYPE expiry_period = MULTIPLY_TIME_BY_INT(ATTOTIME_IN_HZ(ST->clock), busyclock * ST->timer_prescaler);\n\tST->busy_expiry_time = ADD_TIMES(FM_GET_TIME_NOW(ST->device->machine), expiry_period);\n}\n#else\n#define FM_STATUS_FLAG(ST) ((ST)->status)\n#define FM_BUSY_SET(ST,bclock) {}\n#define FM_BUSY_CLEAR(ST) {}\n#endif\n\n\n\n\nINLINE void FM_KEYON(UINT8 type, FM_CH *CH , int s )\n{\n\tFM_SLOT *SLOT = &CH->SLOT[s];\n\tif( !SLOT->key )\n\t{\n\t\tSLOT->key = 1;\n\t\tSLOT->phase = 0;\t\t/* restart Phase Generator */\n\t\tSLOT->ssgn = (SLOT->ssg & 0x04) >> 1;\n\t\tSLOT->state = EG_ATT;\n\t}\n}\n\nINLINE void FM_KEYOFF(FM_CH *CH , int s )\n{\n\tFM_SLOT *SLOT = &CH->SLOT[s];\n\tif( SLOT->key )\n\t{\n\t\tSLOT->key = 0;\n\t\tif (SLOT->state>EG_REL)\n\t\t\tSLOT->state = EG_REL;/* phase -> Release */\n\t}\n}\n\n/* set algorithm connection */\nstatic void setup_connection( FM_OPN *OPN, FM_CH *CH, int ch )\n{\n\tINT32 *carrier = &OPN->out_fm[ch];\n\n\tINT32 **om1 = &CH->connect1;\n\tINT32 **om2 = &CH->connect3;\n\tINT32 **oc1 = &CH->connect2;\n\n\tINT32 **memc = &CH->mem_connect;\n\n\tswitch( CH->ALGO )\n\t{\n\tcase 0:\n\t\t/* M1---C1---MEM---M2---C2---OUT */\n\t\t*om1 = &OPN->c1;\n\t\t*oc1 = &OPN->mem;\n\t\t*om2 = &OPN->c2;\n\t\t*memc= &OPN->m2;\n\t\tbreak;\n\tcase 1:\n\t\t/* M1------+-MEM---M2---C2---OUT */\n\t\t/*      C1-+                     */\n\t\t*om1 = &OPN->mem;\n\t\t*oc1 = &OPN->mem;\n\t\t*om2 = &OPN->c2;\n\t\t*memc= &OPN->m2;\n\t\tbreak;\n\tcase 2:\n\t\t/* M1-----------------+-C2---OUT */\n\t\t/*      C1---MEM---M2-+          */\n\t\t*om1 = &OPN->c2;\n\t\t*oc1 = &OPN->mem;\n\t\t*om2 = &OPN->c2;\n\t\t*memc= &OPN->m2;\n\t\tbreak;\n\tcase 3:\n\t\t/* M1---C1---MEM------+-C2---OUT */\n\t\t/*                 M2-+          */\n\t\t*om1 = &OPN->c1;\n\t\t*oc1 = &OPN->mem;\n\t\t*om2 = &OPN->c2;\n\t\t*memc= &OPN->c2;\n\t\tbreak;\n\tcase 4:\n\t\t/* M1---C1-+-OUT */\n\t\t/* M2---C2-+     */\n\t\t/* MEM: not used */\n\t\t*om1 = &OPN->c1;\n\t\t*oc1 = carrier;\n\t\t*om2 = &OPN->c2;\n\t\t*memc= &OPN->mem;\t/* store it anywhere where it will not be used */\n\t\tbreak;\n\tcase 5:\n\t\t/*    +----C1----+     */\n\t\t/* M1-+-MEM---M2-+-OUT */\n\t\t/*    +----C2----+     */\n\t\t*om1 = 0;\t/* special mark */\n\t\t*oc1 = carrier;\n\t\t*om2 = carrier;\n\t\t*memc= &OPN->m2;\n\t\tbreak;\n\tcase 6:\n\t\t/* M1---C1-+     */\n\t\t/*      M2-+-OUT */\n\t\t/*      C2-+     */\n\t\t/* MEM: not used */\n\t\t*om1 = &OPN->c1;\n\t\t*oc1 = carrier;\n\t\t*om2 = carrier;\n\t\t*memc= &OPN->mem;\t/* store it anywhere where it will not be used */\n\t\tbreak;\n\tcase 7:\n\t\t/* M1-+     */\n\t\t/* C1-+-OUT */\n\t\t/* M2-+     */\n\t\t/* C2-+     */\n\t\t/* MEM: not used*/\n\t\t*om1 = carrier;\n\t\t*oc1 = carrier;\n\t\t*om2 = carrier;\n\t\t*memc= &OPN->mem;\t/* store it anywhere where it will not be used */\n\t\tbreak;\n\t}\n\n\tCH->connect4 = carrier;\n}\n\n/* set detune & multiple */\nINLINE void set_det_mul(FM_ST *ST,FM_CH *CH,FM_SLOT *SLOT,int v)\n{\n\tSLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;\n\tSLOT->DT  = ST->dt_tab[(v>>4)&7];\n\tCH->SLOT[SLOT1].Incr=-1;\n}\n\n/* set total level */\nINLINE void set_tl(FM_CH *CH,FM_SLOT *SLOT , int v)\n{\n\tSLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */\n}\n\n/* set attack rate & key scale  */\nINLINE void set_ar_ksr(UINT8 type, FM_CH *CH,FM_SLOT *SLOT,int v)\n{\n\tUINT8 old_KSR = SLOT->KSR;\n\n\tSLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\n\n\tSLOT->KSR = 3-(v>>6);\n\tif (SLOT->KSR != old_KSR)\n\t{\n\t\tCH->SLOT[SLOT1].Incr=-1;\n\t}\n\n\t/* refresh Attack rate */\n\tif ((SLOT->ar + SLOT->ksr) < 32+62)\n\t{\n\t\tSLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar  + SLOT->ksr ];\n\t\tSLOT->eg_sel_ar = eg_rate_select[SLOT->ar  + SLOT->ksr ];\n\t}\n\telse\n\t{\n\t\tSLOT->eg_sh_ar  = 0;\n\t\tSLOT->eg_sel_ar = 17*RATE_STEPS;\n\t}\n}\n\n/* set decay rate */\nINLINE void set_dr(UINT8 type, FM_SLOT *SLOT,int v)\n{\n\tSLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\n\n\tSLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];\n\tSLOT->eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];\n}\n\n/* set sustain rate */\nINLINE void set_sr(UINT8 type, FM_SLOT *SLOT,int v)\n{\n\tSLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\n\n\tSLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];\n\tSLOT->eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];\n}\n\n/* set release rate */\nINLINE void set_sl_rr(UINT8 type, FM_SLOT *SLOT,int v)\n{\n\tSLOT->sl = sl_table[ v>>4 ];\n\n\tSLOT->rr  = 34 + ((v&0x0f)<<2);\n\n\tSLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr  + SLOT->ksr];\n\tSLOT->eg_sel_rr = eg_rate_select[SLOT->rr  + SLOT->ksr];\n}\n\n\n\nINLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)\n{\n\tUINT32 p;\n\n\tp = (env<<3) + sin_tab[ ( ((signed int)((phase & ~FREQ_MASK) + (pm<<15))) >> FREQ_SH ) & SIN_MASK ];\n\n\tif (p >= TL_TAB_LEN)\n\t\treturn 0;\n\treturn tl_tab[p];\n}\n\nINLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)\n{\n\tUINT32 p;\n\n\tp = (env<<3) + sin_tab[ ( ((signed int)((phase & ~FREQ_MASK) + pm      )) >> FREQ_SH ) & SIN_MASK ];\n\n\tif (p >= TL_TAB_LEN)\n\t\treturn 0;\n\treturn tl_tab[p];\n}\n\n/* advance LFO to next sample */\nINLINE void advance_lfo(FM_OPN *OPN)\n{\n\tUINT8 pos;\n\n\tif (OPN->lfo_inc)\t/* LFO enabled ? */\n\t{\n\t\tOPN->lfo_cnt += OPN->lfo_inc;\n\n\t\tpos = (OPN->lfo_cnt >> LFO_SH) & 127;\n\n\n\t\t/* update AM when LFO output changes */\n\n\t\t/* actually I can't optimize is this way without rewriting chan_calc()\n        to use chip->lfo_am instead of global lfo_am */\n\t\t{\n\n\t\t\t/* triangle */\n\t\t\t/* AM: 0 to 126 step +2, 126 to 0 step -2 */\n\t\t\tif (pos<64)\n\t\t\t\tOPN->LFO_AM = (pos&63) * 2;\n\t\t\telse\n\t\t\t\tOPN->LFO_AM = 126 - ((pos&63) * 2);\n\t\t}\n\n\t\t/* PM works with 4 times slower clock */\n\t\tpos >>= 2;\n\t\t/* update PM when LFO output changes */\n\t\t/*if (prev_pos != pos)*/ /* can't use global lfo_pm for this optimization, must be chip->lfo_pm instead*/\n\t\t{\n\t\t\tOPN->LFO_PM = pos;\n\t\t}\n\n\t}\n\telse\n\t{\n\t\tOPN->LFO_AM = 0;\n\t\tOPN->LFO_PM = 0;\n\t}\n}\n\n/* changed from INLINE to static here to work around gcc 4.2.1 codegen bug */\nstatic void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)\n{\n\tunsigned int out;\n\tunsigned int swap_flag = 0;\n\tunsigned int i;\n\n\n\ti = 4; /* four operators per channel */\n\tdo\n\t{\n\t\t/* reset SSG-EG swap flag */\n\t\tswap_flag = 0;\n\n\t\tswitch(SLOT->state)\n\t\t{\n\t\tcase EG_ATT:\t\t/* attack phase */\n\t\t\tif ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_ar)-1) ) )\n\t\t\t{\n\t\t\t\tSLOT->volume += (~SLOT->volume *\n                                  (eg_inc[SLOT->eg_sel_ar + ((OPN->eg_cnt>>SLOT->eg_sh_ar)&7)])\n                                ) >>4;\n\n\t\t\t\tif (SLOT->volume <= MIN_ATT_INDEX)\n\t\t\t\t{\n\t\t\t\t\tSLOT->volume = MIN_ATT_INDEX;\n\t\t\t\t\tSLOT->state = EG_DEC;\n\t\t\t\t}\n\t\t\t}\n\t\tbreak;\n\n\t\tcase EG_DEC:\t/* decay phase */\n\t\t\t{\n\t\t\t\tif (SLOT->ssg&0x08)\t/* SSG EG type envelope selected */\n\t\t\t\t{\n\t\t\t\t\tif ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d1r)-1) ) )\n\t\t\t\t\t{\n\t\t\t\t\t\tSLOT->volume += 4 * eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)];\n\n\t\t\t\t\t\tif ( SLOT->volume >= (INT32)(SLOT->sl) )\n\t\t\t\t\t\t\tSLOT->state = EG_SUS;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d1r)-1) ) )\n\t\t\t\t\t{\n\t\t\t\t\t\tSLOT->volume += eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)];\n\n\t\t\t\t\t\tif ( SLOT->volume >= (INT32)(SLOT->sl) )\n\t\t\t\t\t\t\tSLOT->state = EG_SUS;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tbreak;\n\n\t\tcase EG_SUS:\t/* sustain phase */\n\t\t\tif (SLOT->ssg&0x08)\t/* SSG EG type envelope selected */\n\t\t\t{\n\t\t\t\tif ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d2r)-1) ) )\n\t\t\t\t{\n\n\t\t\t\t\tSLOT->volume += 4 * eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)];\n\n\t\t\t\t\tif ( SLOT->volume >= ENV_QUIET )\n\t\t\t\t\t{\n\t\t\t\t\t\tSLOT->volume = MAX_ATT_INDEX;\n\n\t\t\t\t\t\tif (SLOT->ssg&0x01)\t/* bit 0 = hold */\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (SLOT->ssgn&1)\t/* have we swapped once ??? */\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t/* yes, so do nothing, just hold current level */\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tswap_flag = (SLOT->ssg&0x02) | 1 ; /* bit 1 = alternate */\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t/* same as KEY-ON operation */\n\n\t\t\t\t\t\t\t/* restart of the Phase Generator should be here */\n\t\t\t\t\t\t\tSLOT->phase = 0;\n\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t/* phase -> Attack */\n\t\t\t\t\t\t\t\tSLOT->volume = 511;\n\t\t\t\t\t\t\t\tSLOT->state = EG_ATT;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tswap_flag = (SLOT->ssg&0x02); /* bit 1 = alternate */\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d2r)-1) ) )\n\t\t\t\t{\n\t\t\t\t\tSLOT->volume += eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)];\n\n\t\t\t\t\tif ( SLOT->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t{\n\t\t\t\t\t\tSLOT->volume = MAX_ATT_INDEX;\n\t\t\t\t\t\t/* do not change SLOT->state (verified on real chip) */\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\t\tbreak;\n\n\t\tcase EG_REL:\t/* release phase */\n\t\t\t\tif ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_rr)-1) ) )\n\t\t\t\t{\n\t\t\t\t\t/* SSG-EG affects Release phase also (Nemesis) */\n\t\t\t\t\tSLOT->volume += eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)];\n\n\t\t\t\t\tif ( SLOT->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t{\n\t\t\t\t\t\tSLOT->volume = MAX_ATT_INDEX;\n\t\t\t\t\t\tSLOT->state = EG_OFF;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\tbreak;\n\n\t\t}\n\n\n\t\tout = ((UINT32)SLOT->volume);\n\n                /* negate output (changes come from alternate bit, init comes from attack bit) */\n\t\tif ((SLOT->ssg&0x08) && (SLOT->ssgn&2) && (SLOT->state > EG_REL))\n\t\t\tout ^= MAX_ATT_INDEX;\n\n\t\t/* we need to store the result here because we are going to change ssgn\n            in next instruction */\n\t\tSLOT->vol_out = out + SLOT->tl;\n\n                /* reverse SLOT inversion flag */\n\t\tSLOT->ssgn ^= swap_flag;\n\n\t\tSLOT++;\n\t\ti--;\n\t}while (i);\n\n}\n\n\n\n#define volume_calc(OP) ((OP)->vol_out + (AM & (OP)->AMmask))\n\nINLINE void update_phase_lfo_slot(FM_OPN *OPN, FM_SLOT *SLOT, INT32 pms, UINT32 block_fnum)\n{\n\tUINT32 fnum_lfo  = ((block_fnum & 0x7f0) >> 4) * 32 * 8;\n\tINT32  lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + pms + OPN->LFO_PM ];\n\n\tif (lfo_fn_table_index_offset)    /* LFO phase modulation active */\n\t{\n\t\tUINT8 blk;\n\t\tUINT32 fn;\n\t\tint kc, fc;\n\n\t\tblock_fnum = block_fnum*2 + lfo_fn_table_index_offset;\n\n\t\tblk = (block_fnum&0x7000) >> 12;\n\t\tfn  = block_fnum & 0xfff;\n\n\t\t/* keyscale code */\n\t\tkc = (blk<<2) | opn_fktable[fn >> 8];\n\n\t\t/* phase increment counter */\n\t\tfc = (OPN->fn_table[fn]>>(7-blk)) + SLOT->DT[kc];\n\n\t\t/* detects frequency overflow (credits to Nemesis) */\n\t\tif (fc < 0) fc += OPN->fn_max;\n\n\t\t/* update phase */\n\t\tSLOT->phase += (fc * SLOT->mul) >> 1;\n\t}\n\telse    /* LFO phase modulation  = zero */\n\t{\n\t\tSLOT->phase += SLOT->Incr;\n\t}\n}\n\nINLINE void update_phase_lfo_channel(FM_OPN *OPN, FM_CH *CH)\n{\n\tUINT32 block_fnum = CH->block_fnum;\n\n\tUINT32 fnum_lfo  = ((block_fnum & 0x7f0) >> 4) * 32 * 8;\n\tINT32  lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + CH->pms + OPN->LFO_PM ];\n\n\tif (lfo_fn_table_index_offset)    /* LFO phase modulation active */\n\t{\n\t        UINT8 blk;\n\t        UINT32 fn;\n\t\tint kc, fc, finc;\n\n\t\tblock_fnum = block_fnum*2 + lfo_fn_table_index_offset;\n\n\t        blk = (block_fnum&0x7000) >> 12;\n\t        fn  = block_fnum & 0xfff;\n\n\t\t/* keyscale code */\n\t        kc = (blk<<2) | opn_fktable[fn >> 8];\n\n\t        /* phase increment counter */\n\t\tfc = (OPN->fn_table[fn]>>(7-blk));\n\n\t\t/* detects frequency overflow (credits to Nemesis) */\n\t\tfinc = fc + CH->SLOT[SLOT1].DT[kc];\n\n\t\tif (finc < 0) finc += OPN->fn_max;\n\t\tCH->SLOT[SLOT1].phase += (finc*CH->SLOT[SLOT1].mul) >> 1;\n\n\t\tfinc = fc + CH->SLOT[SLOT2].DT[kc];\n\t\tif (finc < 0) finc += OPN->fn_max;\n\t\tCH->SLOT[SLOT2].phase += (finc*CH->SLOT[SLOT2].mul) >> 1;\n\n\t\tfinc = fc + CH->SLOT[SLOT3].DT[kc];\n\t\tif (finc < 0) finc += OPN->fn_max;\n\t\tCH->SLOT[SLOT3].phase += (finc*CH->SLOT[SLOT3].mul) >> 1;\n\n\t\tfinc = fc + CH->SLOT[SLOT4].DT[kc];\n\t\tif (finc < 0) finc += OPN->fn_max;\n\t\tCH->SLOT[SLOT4].phase += (finc*CH->SLOT[SLOT4].mul) >> 1;\n\t}\n\telse    /* LFO phase modulation  = zero */\n\t{\n\t        CH->SLOT[SLOT1].phase += CH->SLOT[SLOT1].Incr;\n\t        CH->SLOT[SLOT2].phase += CH->SLOT[SLOT2].Incr;\n\t        CH->SLOT[SLOT3].phase += CH->SLOT[SLOT3].Incr;\n\t        CH->SLOT[SLOT4].phase += CH->SLOT[SLOT4].Incr;\n\t}\n}\n\nINLINE void chan_calc(FM_OPN *OPN, FM_CH *CH, int chnum)\n{\n\tunsigned int eg_out;\n\n\tUINT32 AM = OPN->LFO_AM >> CH->ams;\n\n\tif (CH->Muted)\n\t\treturn;\n\n\n\tOPN->m2 = OPN->c1 = OPN->c2 = OPN->mem = 0;\n\n\t*CH->mem_connect = CH->mem_value;\t/* restore delayed sample (MEM) value to m2 or c2 */\n\n\teg_out = volume_calc(&CH->SLOT[SLOT1]);\n\t{\n\t\tINT32 out = CH->op1_out[0] + CH->op1_out[1];\n\t\tCH->op1_out[0] = CH->op1_out[1];\n\n\t\tif( !CH->connect1 )\n\t\t{\n\t\t\t/* algorithm 5  */\n\t\t\tOPN->mem = OPN->c1 = OPN->c2 = CH->op1_out[0];\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* other algorithms */\n\t\t\t*CH->connect1 += CH->op1_out[0];\n\t\t}\n\n\t\tCH->op1_out[1] = 0;\n\t\tif( eg_out < ENV_QUIET )\t/* SLOT 1 */\n\t\t{\n\t\t\tif (!CH->FB)\n\t\t\t\tout=0;\n\n\t\t\tCH->op1_out[1] = op_calc1(CH->SLOT[SLOT1].phase, eg_out, (out<<CH->FB) );\n\t\t}\n\t}\n\n\teg_out = volume_calc(&CH->SLOT[SLOT3]);\n\tif( eg_out < ENV_QUIET )\t\t/* SLOT 3 */\n\t\t*CH->connect3 += op_calc(CH->SLOT[SLOT3].phase, eg_out, OPN->m2);\n\n\teg_out = volume_calc(&CH->SLOT[SLOT2]);\n\tif( eg_out < ENV_QUIET )\t\t/* SLOT 2 */\n\t\t*CH->connect2 += op_calc(CH->SLOT[SLOT2].phase, eg_out, OPN->c1);\n\n\teg_out = volume_calc(&CH->SLOT[SLOT4]);\n\tif( eg_out < ENV_QUIET )\t\t/* SLOT 4 */\n\t\t*CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, OPN->c2);\n\n\n\t/* store current MEM */\n\tCH->mem_value = OPN->mem;\n\n\t/* update phase counters AFTER output calculations */\n\tif(CH->pms)\n\t{\n\t\t/* add support for 3 slot mode */\n\t\tif ((OPN->ST.mode & 0xC0) && (chnum == 2))\n\t\t{\n\t\t        update_phase_lfo_slot(OPN, &CH->SLOT[SLOT1], CH->pms, OPN->SL3.block_fnum[1]);\n\t\t        update_phase_lfo_slot(OPN, &CH->SLOT[SLOT2], CH->pms, OPN->SL3.block_fnum[2]);\n\t\t        update_phase_lfo_slot(OPN, &CH->SLOT[SLOT3], CH->pms, OPN->SL3.block_fnum[0]);\n\t\t        update_phase_lfo_slot(OPN, &CH->SLOT[SLOT4], CH->pms, CH->block_fnum);\n\t\t}\n\t\telse update_phase_lfo_channel(OPN, CH);\n\t}\n\telse\t/* no LFO phase modulation */\n\t{\n\t\tCH->SLOT[SLOT1].phase += CH->SLOT[SLOT1].Incr;\n\t\tCH->SLOT[SLOT2].phase += CH->SLOT[SLOT2].Incr;\n\t\tCH->SLOT[SLOT3].phase += CH->SLOT[SLOT3].Incr;\n\t\tCH->SLOT[SLOT4].phase += CH->SLOT[SLOT4].Incr;\n\t}\n}\n\n/* update phase increment and envelope generator */\nINLINE void refresh_fc_eg_slot(FM_OPN *OPN, FM_SLOT *SLOT , int fc , int kc )\n{\n\tint ksr = kc >> SLOT->KSR;\n\n\tfc += SLOT->DT[kc];\n\n\t/* detects frequency overflow (credits to Nemesis) */\n\tif (fc < 0) fc += OPN->fn_max;\n\n\t/* (frequency) phase increment counter */\n\tSLOT->Incr = (fc * SLOT->mul) >> 1;\n\n\tif( SLOT->ksr != ksr )\n\t{\n\t\tSLOT->ksr = ksr;\n\n\t\t/* calculate envelope generator rates */\n\t\tif ((SLOT->ar + SLOT->ksr) < 32+62)\n\t\t{\n\t\t\tSLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar  + SLOT->ksr ];\n\t\t\tSLOT->eg_sel_ar = eg_rate_select[SLOT->ar  + SLOT->ksr ];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSLOT->eg_sh_ar  = 0;\n\t\t\tSLOT->eg_sel_ar = 17*RATE_STEPS;\n\t\t}\n\n\t\tSLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];\n\t\tSLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];\n\t\tSLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr  + SLOT->ksr];\n\n\t\tSLOT->eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];\n\t\tSLOT->eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];\n\t\tSLOT->eg_sel_rr = eg_rate_select[SLOT->rr  + SLOT->ksr];\n\t}\n}\n\n/* update phase increment counters */\n/* Changed from INLINE to static to work around gcc 4.2.1 codegen bug */\nstatic void refresh_fc_eg_chan(FM_OPN *OPN, FM_CH *CH )\n{\n\tif( CH->SLOT[SLOT1].Incr==-1)\n\t{\n\t\tint fc = CH->fc;\n\t\tint kc = CH->kcode;\n\t\trefresh_fc_eg_slot(OPN, &CH->SLOT[SLOT1] , fc , kc );\n\t\trefresh_fc_eg_slot(OPN, &CH->SLOT[SLOT2] , fc , kc );\n\t\trefresh_fc_eg_slot(OPN, &CH->SLOT[SLOT3] , fc , kc );\n\t\trefresh_fc_eg_slot(OPN, &CH->SLOT[SLOT4] , fc , kc );\n\t}\n}\n\n/* initialize time tables */\nstatic void init_timetables( FM_ST *ST , const UINT8 *dttable )\n{\n\tint i,d;\n\tdouble rate;\n\n#if 0\n\tlogerror(\"FM.C: samplerate=%8i chip clock=%8i  freqbase=%f  \\n\",\n\t\t\t ST->rate, ST->clock, ST->freqbase );\n#endif\n\n\t/* DeTune table */\n\tfor (d = 0;d <= 3;d++)\n\t{\n\t\tfor (i = 0;i <= 31;i++)\n\t\t{\n\t\t\trate = ((double)dttable[d*32 + i]) * SIN_LEN  * ST->freqbase  * (1<<FREQ_SH) / ((double)(1<<20));\n\t\t\tST->dt_tab[d][i]   = (INT32) rate;\n\t\t\tST->dt_tab[d+4][i] = -ST->dt_tab[d][i];\n#if 0\n\t\t\tlogerror(\"FM.C: DT [%2i %2i] = %8x  \\n\", d, i, ST->dt_tab[d][i] );\n#endif\n\t\t}\n\t}\n\n}\n\n\nstatic void reset_channels( FM_ST *ST , FM_CH *CH , int num )\n{\n\tint c,s;\n\n\tST->mode   = 0;\t/* normal mode */\n\tST->TA     = 0;\n\tST->TAC    = 0;\n\tST->TB     = 0;\n\tST->TBC    = 0;\n\n\tfor( c = 0 ; c < num ; c++ )\n\t{\n\t\t//memset(&CH[c], 0x00, sizeof(FM_CH));\n\t\tCH[c].mem_value = 0;\n\t\tCH[c].op1_out[0] = 0;\n\t\tCH[c].op1_out[1] = 0;\n\t\tCH[c].fc = 0;\n\t\tfor(s = 0 ; s < 4 ; s++ )\n\t\t{\n\t\t\t//memset(&CH[c].SLOT[s], 0x00, sizeof(FM_SLOT));\n\t\t\tCH[c].SLOT[s].Incr = -1;\n\t\t\tCH[c].SLOT[s].key = 0;\n\t\t\tCH[c].SLOT[s].phase = 0;\n\t\t\tCH[c].SLOT[s].ssg = 0;\n\t\t\tCH[c].SLOT[s].ssgn = 0;\n\t\t\tCH[c].SLOT[s].state= EG_OFF;\n\t\t\tCH[c].SLOT[s].volume = MAX_ATT_INDEX;\n\t\t\tCH[c].SLOT[s].vol_out= MAX_ATT_INDEX;\n\t\t}\n\t}\n}\n\n/* initialize generic tables */\nstatic int init_tables(void)\n{\n\tsigned int i,x;\n\tsigned int n;\n\tdouble o,m;\n\n\tfor (x=0; x<TL_RES_LEN; x++)\n\t{\n\t\tm = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);\n\t\tm = floor(m);\n\n\t\t/* we never reach (1<<16) here due to the (x+1) */\n\t\t/* result fits within 16 bits at maximum */\n\n\t\tn = (int)m;\t\t/* 16 bits here */\n\t\tn >>= 4;\t\t/* 12 bits here */\n\t\tif (n&1)\t\t/* round to nearest */\n\t\t\tn = (n>>1)+1;\n\t\telse\n\t\t\tn = n>>1;\n\t\t\t\t\t\t/* 11 bits here (rounded) */\n\t\tn <<= 2;\t\t/* 13 bits here (as in real chip) */\n\t\ttl_tab[ x*2 + 0 ] = n;\n\t\ttl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];\n\n\t\tfor (i=1; i<13; i++)\n\t\t{\n\t\t\ttl_tab[ x*2+0 + i*2*TL_RES_LEN ] =  tl_tab[ x*2+0 ]>>i;\n\t\t\ttl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];\n\t\t}\n\t#if 0\n\t\t\tlogerror(\"tl %04i\", x);\n\t\t\tfor (i=0; i<13; i++)\n\t\t\t\tlogerror(\", [%02i] %4x\", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ]);\n\t\t\tlogerror(\"\\n\");\n\t#endif\n\t}\n\t/*logerror(\"FM.C: TL_TAB_LEN = %i elements (%i bytes)\\n\",TL_TAB_LEN, (int)sizeof(tl_tab));*/\n\n\n\tfor (i=0; i<SIN_LEN; i++)\n\t{\n\t\t/* non-standard sinus */\n\t\tm = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */\n\n\t\t/* we never reach zero here due to ((i*2)+1) */\n\n\t\tif (m>0.0)\n\t\t\to = 8*log(1.0/m)/log(2.0);\t/* convert to 'decibels' */\n\t\telse\n\t\t\to = 8*log(-1.0/m)/log(2.0);\t/* convert to 'decibels' */\n\n\t\to = o / (ENV_STEP/4);\n\n\t\tn = (int)(2.0*o);\n\t\tif (n&1)\t\t\t\t\t\t/* round to nearest */\n\t\t\tn = (n>>1)+1;\n\t\telse\n\t\t\tn = n>>1;\n\n\t\tsin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );\n\t\t/*logerror(\"FM.C: sin [%4i]= %4i (tl_tab value=%5i)\\n\", i, sin_tab[i],tl_tab[sin_tab[i]]);*/\n\t}\n\n\t/*logerror(\"FM.C: ENV_QUIET= %08x\\n\",ENV_QUIET );*/\n\n\n\t/* build LFO PM modulation table */\n\tfor(i = 0; i < 8; i++) /* 8 PM depths */\n\t{\n\t\tUINT8 fnum;\n\t\tfor (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */\n\t\t{\n\t\t\tUINT8 value;\n\t\t\tUINT8 step;\n\t\t\tUINT32 offset_depth = i;\n\t\t\tUINT32 offset_fnum_bit;\n\t\t\tUINT32 bit_tmp;\n\n\t\t\tfor (step=0; step<8; step++)\n\t\t\t{\n\t\t\t\tvalue = 0;\n\t\t\t\tfor (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */\n\t\t\t\t{\n\t\t\t\t\tif (fnum & (1<<bit_tmp)) /* only if bit \"bit_tmp\" is set */\n\t\t\t\t\t{\n\t\t\t\t\t\toffset_fnum_bit = bit_tmp * 8;\n\t\t\t\t\t\tvalue += lfo_pm_output[offset_fnum_bit + offset_depth][step];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlfo_pm_table[(fnum*32*8) + (i*32) + step   + 0] = value;\n\t\t\t\tlfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;\n\t\t\t\tlfo_pm_table[(fnum*32*8) + (i*32) + step   +16] = -value;\n\t\t\t\tlfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;\n\t\t\t}\n#if 0\n\t\t\tlogerror(\"LFO depth=%1x FNUM=%04x (<<4=%4x): \", i, fnum, fnum<<4);\n\t\t\tfor (step=0; step<16; step++) /* dump only positive part of waveforms */\n\t\t\t\tlogerror(\"%02x \", lfo_pm_table[(fnum*32*8) + (i*32) + step] );\n\t\t\tlogerror(\"\\n\");\n#endif\n\n\t\t}\n\t}\n\n\n\n#ifdef SAVE_SAMPLE\n\tsample[0]=fopen(\"sampsum.pcm\",\"wb\");\n#endif\n\n\treturn 1;\n\n}\n\n\n\nstatic void FMCloseTable( void )\n{\n#ifdef SAVE_SAMPLE\n\tfclose(sample[0]);\n#endif\n\treturn;\n}\n\n\n/* CSM Key Controll */\nINLINE void CSMKeyControll(UINT8 type, FM_CH *CH)\n{\n\t/* all key on then off (only for operators which were OFF!) */\n\tif (!CH->SLOT[SLOT1].key)\n\t{\n\t\tFM_KEYON(type, CH,SLOT1);\n\t\tFM_KEYOFF(CH, SLOT1);\n\t}\n\tif (!CH->SLOT[SLOT2].key)\n\t{\n\t\tFM_KEYON(type, CH,SLOT2);\n\t\tFM_KEYOFF(CH, SLOT2);\n\t}\n\tif (!CH->SLOT[SLOT3].key)\n\t{\n\t\tFM_KEYON(type, CH,SLOT3);\n\t\tFM_KEYOFF(CH, SLOT3);\n\t}\n\tif (!CH->SLOT[SLOT4].key)\n\t{\n\t\tFM_KEYON(type, CH,SLOT4);\n\t\tFM_KEYOFF(CH, SLOT4);\n\t}\n}\n\n#ifdef __STATE_H__\n/* FM channel save , internal state only */\nstatic void FMsave_state_channel(const device_config *device,FM_CH *CH,int num_ch)\n{\n\tint slot , ch;\n\n\tfor(ch=0;ch<num_ch;ch++,CH++)\n\t{\n\t\t/* channel */\n\t\tstate_save_register_device_item_array(device, ch, CH->op1_out);\n\t\tstate_save_register_device_item(device, ch, CH->fc);\n\t\t/* slots */\n\t\tfor(slot=0;slot<4;slot++)\n\t\t{\n\t\t\tFM_SLOT *SLOT = &CH->SLOT[slot];\n\t\t\tstate_save_register_device_item(device, ch * 4 + slot, SLOT->phase);\n\t\t\tstate_save_register_device_item(device, ch * 4 + slot, SLOT->state);\n\t\t\tstate_save_register_device_item(device, ch * 4 + slot, SLOT->volume);\n\t\t}\n\t}\n}\n\nstatic void FMsave_state_st(const device_config *device,FM_ST *ST)\n{\n#if FM_BUSY_FLAG_SUPPORT\n\tstate_save_register_device_item(device, 0, ST->busy_expiry_time.seconds );\n\tstate_save_register_device_item(device, 0, ST->busy_expiry_time.attoseconds );\n#endif\n\tstate_save_register_device_item(device, 0, ST->address );\n\tstate_save_register_device_item(device, 0, ST->irq     );\n\tstate_save_register_device_item(device, 0, ST->irqmask );\n\tstate_save_register_device_item(device, 0, ST->status  );\n\tstate_save_register_device_item(device, 0, ST->mode    );\n\tstate_save_register_device_item(device, 0, ST->prescaler_sel );\n\tstate_save_register_device_item(device, 0, ST->fn_h );\n\tstate_save_register_device_item(device, 0, ST->TA   );\n\tstate_save_register_device_item(device, 0, ST->TAC  );\n\tstate_save_register_device_item(device, 0, ST->TB  );\n\tstate_save_register_device_item(device, 0, ST->TBC  );\n}\n#endif /* _STATE_H */\n\n#if BUILD_OPN\n\n\n\n/* prescaler set (and make time tables) */\nstatic void OPNSetPres(FM_OPN *OPN, int pres, int timer_prescaler, int SSGpres)\n{\n\tint i;\n\n\t/* frequency base */\n\tOPN->ST.freqbase = (OPN->ST.rate) ? ((double)OPN->ST.clock / OPN->ST.rate) / pres : 0;\n\n#if 0\n\tOPN->ST.rate = (double)OPN->ST.clock / pres;\n\tOPN->ST.freqbase = 1.0;\n#endif\n\n\tOPN->eg_timer_add  = (1<<EG_SH)  *  OPN->ST.freqbase;\n\tOPN->eg_timer_overflow = ( 3 ) * (1<<EG_SH);\n\n\n\t/* Timer base time */\n\tOPN->ST.timer_prescaler = timer_prescaler;\n\n\t/* SSG part  prescaler set */\n\tif( SSGpres ) (*OPN->ST.SSG->set_clock)( OPN->ST.param, OPN->ST.clock * 2 / SSGpres );\n\n\t/* make time tables */\n\tinit_timetables( &OPN->ST, dt_tab );\n\n\t/* there are 2048 FNUMs that can be generated using FNUM/BLK registers\n        but LFO works with one more bit of a precision so we really need 4096 elements */\n\t/* calculate fnumber -> increment counter table */\n\tfor(i = 0; i < 4096; i++)\n\t{\n\t\t/* freq table for octave 7 */\n\t\t/* OPN phase increment counter = 20bit */\n\t\tOPN->fn_table[i] = (UINT32)( (double)i * 32 * OPN->ST.freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */\n#if 0\n\t\tlogerror(\"FM.C: fn_table[%4i] = %08x (dec=%8i)\\n\",\n\t\t\t\t i, OPN->fn_table[i]>>6,OPN->fn_table[i]>>6 );\n#endif\n\t}\n\n\t/* maximal frequency is required for Phase overflow calculation, register size is 17 bits (Nemesis) */\n\tOPN->fn_max = (UINT32)( (double)0x20000 * OPN->ST.freqbase * (1<<(FREQ_SH-10)) );\n\n\t/* LFO freq. table */\n\tfor(i = 0; i < 8; i++)\n\t{\n\t\t/* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of \"lfo_samples_per_step\" samples */\n\t\t/* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * \"lfo_samples_per_step\" samples  */\n\t\tOPN->lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<<LFO_SH) * OPN->ST.freqbase;\n#if 0\n\t\tlogerror(\"FM.C: lfo_freq[%i] = %08x (dec=%8i)\\n\",\n\t\t\t\t i, OPN->lfo_freq[i],OPN->lfo_freq[i] );\n#endif\n\t}\n}\n\n\n\n/* write a OPN mode register 0x20-0x2f */\nstatic void OPNWriteMode(FM_OPN *OPN, int r, int v)\n{\n\tUINT8 c;\n\tFM_CH *CH;\n\n\tswitch(r)\n\t{\n\tcase 0x21:\t/* Test */\n\t\tbreak;\n\tcase 0x22:\t/* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */\n\t\tif( OPN->type & TYPE_LFOPAN )\n\t\t{\n\t\t\tif (v&0x08) /* LFO enabled ? */\n\t\t\t{\n\t\t\t\tOPN->lfo_inc = OPN->lfo_freq[v&7];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tOPN->lfo_inc = 0;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase 0x24:\t/* timer A High 8*/\n\t\tOPN->ST.TA = (OPN->ST.TA & 0x03)|(((int)v)<<2);\n\t\tbreak;\n\tcase 0x25:\t/* timer A Low 2*/\n\t\tOPN->ST.TA = (OPN->ST.TA & 0x3fc)|(v&3);\n\t\tbreak;\n\tcase 0x26:\t/* timer B */\n\t\tOPN->ST.TB = v;\n\t\tbreak;\n\tcase 0x27:\t/* mode, timer control */\n\t\tset_timers( &(OPN->ST),OPN->ST.param,v );\n\t\tbreak;\n\tcase 0x28:\t/* key on / off */\n\t\tc = v & 0x03;\n\t\tif( c == 3 ) break;\n\t\tif( (v&0x04) && (OPN->type & TYPE_6CH) ) c+=3;\n\t\tCH = OPN->P_CH;\n\t\tCH = &CH[c];\n\t\tif(v&0x10) FM_KEYON(OPN->type,CH,SLOT1); else FM_KEYOFF(CH,SLOT1);\n\t\tif(v&0x20) FM_KEYON(OPN->type,CH,SLOT2); else FM_KEYOFF(CH,SLOT2);\n\t\tif(v&0x40) FM_KEYON(OPN->type,CH,SLOT3); else FM_KEYOFF(CH,SLOT3);\n\t\tif(v&0x80) FM_KEYON(OPN->type,CH,SLOT4); else FM_KEYOFF(CH,SLOT4);\n\t\tbreak;\n\t}\n}\n\n/* write a OPN register (0x30-0xff) */\nstatic void OPNWriteReg(FM_OPN *OPN, int r, int v)\n{\n\tFM_CH *CH;\n\tFM_SLOT *SLOT;\n\n\tUINT8 c = OPN_CHAN(r);\n\n\tif (c == 3) return; /* 0xX3,0xX7,0xXB,0xXF */\n\n\tif (r >= 0x100) c+=3;\n\n\tCH = OPN->P_CH;\n\tCH = &CH[c];\n\n\tSLOT = &(CH->SLOT[OPN_SLOT(r)]);\n\n\tswitch( r & 0xf0 )\n\t{\n\tcase 0x30:\t/* DET , MUL */\n\t\tset_det_mul(&OPN->ST,CH,SLOT,v);\n\t\tbreak;\n\n\tcase 0x40:\t/* TL */\n\t\tset_tl(CH,SLOT,v);\n\t\tbreak;\n\n\tcase 0x50:\t/* KS, AR */\n\t\tset_ar_ksr(OPN->type,CH,SLOT,v);\n\t\tbreak;\n\n\tcase 0x60:\t/* bit7 = AM ENABLE, DR */\n\t\tset_dr(OPN->type, SLOT,v);\n\n\t\tif(OPN->type & TYPE_LFOPAN) /* YM2608/2610/2610B/2612 */\n\t\t{\n\t\t\tSLOT->AMmask = (v&0x80) ? ~0 : 0;\n\t\t}\n\t\tbreak;\n\n\tcase 0x70:\t/*     SR */\n\t\tset_sr(OPN->type,SLOT,v);\n\t\tbreak;\n\n\tcase 0x80:\t/* SL, RR */\n\t\tset_sl_rr(OPN->type,SLOT,v);\n\t\tbreak;\n\n\tcase 0x90:\t/* SSG-EG */\n\t\tSLOT->ssg  =  v&0x0f;\n\t\tSLOT->ssgn = (v&0x04)>>1; /* bit 1 in ssgn = attack */\n\n\t\t/* SSG-EG envelope shapes :\n\n        E AtAlH\n        1 0 0 0  \\\\\\\\\n\n        1 0 0 1  \\___\n\n        1 0 1 0  \\/\\/\n                  ___\n        1 0 1 1  \\\n\n        1 1 0 0  ////\n                  ___\n        1 1 0 1  /\n\n        1 1 1 0  /\\/\\\n\n        1 1 1 1  /___\n\n\n        E = SSG-EG enable\n\n\n        The shapes are generated using Attack, Decay and Sustain phases.\n\n        Each single character in the diagrams above represents this whole\n        sequence:\n\n        - when KEY-ON = 1, normal Attack phase is generated (*without* any\n          difference when compared to normal mode),\n\n        - later, when envelope level reaches minimum level (max volume),\n          the EG switches to Decay phase (which works with bigger steps\n          when compared to normal mode - see below),\n\n        - later when envelope level passes the SL level,\n          the EG swithes to Sustain phase (which works with bigger steps\n          when compared to normal mode - see below),\n\n        - finally when envelope level reaches maximum level (min volume),\n          the EG switches to Attack phase again (depends on actual waveform).\n\n        Important is that when switch to Attack phase occurs, the phase counter\n        of that operator will be zeroed-out (as in normal KEY-ON) but not always.\n        (I havent found the rule for that - perhaps only when the output level is low)\n\n        The difference (when compared to normal Envelope Generator mode) is\n        that the resolution in Decay and Sustain phases is 4 times lower;\n        this results in only 256 steps instead of normal 1024.\n        In other words:\n        when SSG-EG is disabled, the step inside of the EG is one,\n        when SSG-EG is enabled, the step is four (in Decay and Sustain phases).\n\n        Times between the level changes are the same in both modes.\n\n\n        Important:\n        Decay 1 Level (so called SL) is compared to actual SSG-EG output, so\n        it is the same in both SSG and no-SSG modes, with this exception:\n\n        when the SSG-EG is enabled and is generating raising levels\n        (when the EG output is inverted) the SL will be found at wrong level !!!\n        For example, when SL=02:\n            0 -6 = -6dB in non-inverted EG output\n            96-6 = -90dB in inverted EG output\n        Which means that EG compares its level to SL as usual, and that the\n        output is simply inverted afterall.\n\n\n        The Yamaha's manuals say that AR should be set to 0x1f (max speed).\n        That is not necessary, but then EG will be generating Attack phase.\n\n        */\n\n\n\t\tbreak;\n\n\tcase 0xa0:\n\t\tswitch( OPN_SLOT(r) )\n\t\t{\n\t\tcase 0:\t\t/* 0xa0-0xa2 : FNUM1 */\n\t\t\t{\n\t\t\t\tUINT32 fn = (((UINT32)( (OPN->ST.fn_h)&7))<<8) + v;\n\t\t\t\tUINT8 blk = OPN->ST.fn_h>>3;\n\t\t\t\t/* keyscale code */\n\t\t\t\tCH->kcode = (blk<<2) | opn_fktable[fn >> 7];\n\t\t\t\t/* phase increment counter */\n\t\t\t\tCH->fc = OPN->fn_table[fn*2]>>(7-blk);\n\n\t\t\t\t/* store fnum in clear form for LFO PM calculations */\n\t\t\t\tCH->block_fnum = (blk<<11) | fn;\n\n\t\t\t\tCH->SLOT[SLOT1].Incr=-1;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 1:\t\t/* 0xa4-0xa6 : FNUM2,BLK */\n\t\t\tOPN->ST.fn_h = v&0x3f;\n\t\t\tbreak;\n\t\tcase 2:\t\t/* 0xa8-0xaa : 3CH FNUM1 */\n\t\t\tif(r < 0x100)\n\t\t\t{\n\t\t\t\tUINT32 fn = (((UINT32)(OPN->SL3.fn_h&7))<<8) + v;\n\t\t\t\tUINT8 blk = OPN->SL3.fn_h>>3;\n\t\t\t\t/* keyscale code */\n\t\t\t\tOPN->SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];\n\t\t\t\t/* phase increment counter */\n\t\t\t\tOPN->SL3.fc[c] = OPN->fn_table[fn*2]>>(7-blk);\n\t\t\t\tOPN->SL3.block_fnum[c] = (blk<<11) | fn;\n\t\t\t\t(OPN->P_CH)[2].SLOT[SLOT1].Incr=-1;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 3:\t\t/* 0xac-0xae : 3CH FNUM2,BLK */\n\t\t\tif(r < 0x100)\n\t\t\t\tOPN->SL3.fn_h = v&0x3f;\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\n\tcase 0xb0:\n\t\tswitch( OPN_SLOT(r) )\n\t\t{\n\t\tcase 0:\t\t/* 0xb0-0xb2 : FB,ALGO */\n\t\t\t{\n\t\t\t\tint feedback = (v>>3)&7;\n\t\t\t\tCH->ALGO = v&7;\n\t\t\t\tCH->FB   = feedback ? feedback+6 : 0;\n\t\t\t\tsetup_connection( OPN, CH, c );\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 1:\t\t/* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */\n\t\t\tif( OPN->type & TYPE_LFOPAN)\n\t\t\t{\n\t\t\t\t/* b0-2 PMS */\n\t\t\t\tCH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */\n\n\t\t\t\t/* b4-5 AMS */\n\t\t\t\tCH->ams = lfo_ams_depth_shift[(v>>4) & 0x03];\n\n\t\t\t\t/* PAN :  b7 = L, b6 = R */\n\t\t\t\tOPN->pan[ c*2   ] = (v & 0x80) ? ~0 : 0;\n\t\t\t\tOPN->pan[ c*2+1 ] = (v & 0x40) ? ~0 : 0;\n\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n}\n\n#endif /* BUILD_OPN */\n\n#if BUILD_OPN_PRESCALER\n/*\n  prescaler circuit (best guess to verified chip behaviour)\n\n               +--------------+  +-sel2-+\n               |              +--|in20  |\n         +---+ |  +-sel1-+       |      |\nM-CLK -+-|1/2|-+--|in10  | +---+ |   out|--INT_CLOCK\n       | +---+    |   out|-|1/3|-|in21  |\n       +----------|in11  | +---+ +------+\n                  +------+\n\nreg.2d : sel2 = in21 (select sel2)\nreg.2e : sel1 = in11 (select sel1)\nreg.2f : sel1 = in10 , sel2 = in20 (clear selector)\nreset  : sel1 = in11 , sel2 = in21 (clear both)\n\n*/\nstatic void OPNPrescaler_w(FM_OPN *OPN , int addr, int pre_divider)\n{\n\tstatic const int opn_pres[4] = { 2*12 , 2*12 , 6*12 , 3*12 };\n\tstatic const int ssg_pres[4] = { 1    ,    1 ,    4 ,    2 };\n\tint sel;\n\n\tswitch(addr)\n\t{\n\tcase 0:\t\t/* when reset */\n\t\tOPN->ST.prescaler_sel = 2;\n\t\tbreak;\n\tcase 1:\t\t/* when postload */\n\t\tbreak;\n\tcase 0x2d:\t/* divider sel : select 1/1 for 1/3line    */\n\t\tOPN->ST.prescaler_sel |= 0x02;\n\t\tbreak;\n\tcase 0x2e:\t/* divider sel , select 1/3line for output */\n\t\tOPN->ST.prescaler_sel |= 0x01;\n\t\tbreak;\n\tcase 0x2f:\t/* divider sel , clear both selector to 1/2,1/2 */\n\t\tOPN->ST.prescaler_sel = 0;\n\t\tbreak;\n\t}\n\tsel = OPN->ST.prescaler_sel & 3;\n\t/* update prescaler */\n\tOPNSetPres( OPN,\topn_pres[sel]*pre_divider,\n\t\t\t\t\t\topn_pres[sel]*pre_divider,\n\t\t\t\t\t\tssg_pres[sel]*pre_divider );\n}\n#endif /* BUILD_OPN_PRESCALER */\n\n#if BUILD_YM2203\n/*****************************************************************************/\n/*      YM2203 local section                                                 */\n/*****************************************************************************/\n\n/* here's the virtual YM2203(OPN) */\ntypedef struct\n{\n\tUINT8 REGS[256];\t\t/* registers         */\n\tFM_OPN OPN;\t\t\t\t/* OPN state         */\n\tFM_CH CH[3];\t\t\t/* channel state     */\n} YM2203;\n\n/* Generate samples for one of the YM2203s */\nvoid ym2203_update_one(void *chip, FMSAMPLE **buffer, int length)\n{\n\tYM2203 *F2203 = (YM2203 *)chip;\n\tFM_OPN *OPN =   &F2203->OPN;\n\tint i;\n\tFMSAMPLE *bufL = buffer[0];\n\tFMSAMPLE *bufR = buffer[1];\n\tFM_CH\t*cch[3];\n\n\tcch[0]   = &F2203->CH[0];\n\tcch[1]   = &F2203->CH[1];\n\tcch[2]   = &F2203->CH[2];\n\n\n\t/* refresh PG and EG */\n\trefresh_fc_eg_chan( OPN, cch[0] );\n\trefresh_fc_eg_chan( OPN, cch[1] );\n\tif( (F2203->OPN.ST.mode & 0xc0) )\n\t{\n\t\t/* 3SLOT MODE */\n\t\tif( cch[2]->SLOT[SLOT1].Incr==-1)\n\t\t{\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );\n\t\t}\n\t}\n\telse\n\t\trefresh_fc_eg_chan( OPN, cch[2] );\n\n\n\t/* YM2203 doesn't have LFO so we must keep these globals at 0 level */\n\tOPN->LFO_AM = 0;\n\tOPN->LFO_PM = 0;\n\n\t/* buffering */\n\tfor (i=0; i < length ; i++)\n\t{\n\t\t/* clear outputs */\n\t\tOPN->out_fm[0] = 0;\n\t\tOPN->out_fm[1] = 0;\n\t\tOPN->out_fm[2] = 0;\n\n\t\t/* advance envelope generator */\n\t\tOPN->eg_timer += OPN->eg_timer_add;\n\t\twhile (OPN->eg_timer >= OPN->eg_timer_overflow)\n\t\t{\n\t\t\tOPN->eg_timer -= OPN->eg_timer_overflow;\n\t\t\tOPN->eg_cnt++;\n\n\t\t\tadvance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]);\n\t\t}\n\n\t\t/* calculate FM */\n\t\tchan_calc(OPN, cch[0], 0 );\n\t\tchan_calc(OPN, cch[1], 1 );\n\t\tchan_calc(OPN, cch[2], 2 );\n\n\t\t/* buffering */\n\t\t{\n\t\t\tint lt;\n\n\t\t\tlt = OPN->out_fm[0] + OPN->out_fm[1] + OPN->out_fm[2];\n\n\t\t\tlt >>= FINAL_SH;\n\n\t\t\t//Limit( lt , MAXOUT, MINOUT );\n\n\t\t\t#ifdef SAVE_SAMPLE\n\t\t\t\tSAVE_ALL_CHANNELS\n\t\t\t#endif\n\n\t\t\t/* buffering */\n\t\t\tbufL[i] = lt;\n\t\t\tbufR[i] = lt;\n\t\t}\n\n\t\t/* timer A control */\n\t\tINTERNAL_TIMER_A( &F2203->OPN.ST , cch[2] )\n\t}\n\tINTERNAL_TIMER_B(&F2203->OPN.ST,length)\n}\n\n/* ---------- reset one of chip ---------- */\nvoid ym2203_reset_chip(void *chip)\n{\n\tint i;\n\tYM2203 *F2203 = (YM2203 *)chip;\n\tFM_OPN *OPN = &F2203->OPN;\n\n\t/* Reset Prescaler */\n\tOPNPrescaler_w(OPN, 0 , 1 );\n\t/* reset SSG section */\n\t(*OPN->ST.SSG->reset)(OPN->ST.param);\n\t/* status clear */\n\tFM_IRQMASK_SET(&OPN->ST,0x03);\n\tFM_BUSY_CLEAR(&OPN->ST);\n\tOPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */\n\n\tOPN->eg_timer = 0;\n\tOPN->eg_cnt   = 0;\n\n\tFM_STATUS_RESET(&OPN->ST, 0xff);\n\n\treset_channels( &OPN->ST , F2203->CH , 3 );\n\t/* reset OPerator paramater */\n\tfor(i = 0xb2 ; i >= 0x30 ; i-- ) OPNWriteReg(OPN,i,0);\n\tfor(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);\n}\n\n#ifdef __STATE_H__\nvoid ym2203_postload(void *chip)\n{\n\tif (chip)\n\t{\n\t\tYM2203 *F2203 = (YM2203 *)chip;\n\t\tint r;\n\n\t\t/* prescaler */\n\t\tOPNPrescaler_w(&F2203->OPN,1,1);\n\n\t\t/* SSG registers */\n\t\tfor(r=0;r<16;r++)\n\t\t{\n\t\t\t(*F2203->OPN.ST.SSG->write)(F2203->OPN.ST.param,0,r);\n\t\t\t(*F2203->OPN.ST.SSG->write)(F2203->OPN.ST.param,1,F2203->REGS[r]);\n\t\t}\n\n\t\t/* OPN registers */\n\t\t/* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */\n\t\tfor(r=0x30;r<0x9e;r++)\n\t\t\tif((r&3) != 3)\n\t\t\t\tOPNWriteReg(&F2203->OPN,r,F2203->REGS[r]);\n\t\t/* FB / CONNECT , L / R / AMS / PMS */\n\t\tfor(r=0xb0;r<0xb6;r++)\n\t\t\tif((r&3) != 3)\n\t\t\t\tOPNWriteReg(&F2203->OPN,r,F2203->REGS[r]);\n\n\t\t/* channels */\n\t\t/*FM_channel_postload(F2203->CH,3);*/\n\t}\n}\n\nstatic void YM2203_save_state(YM2203 *F2203, const device_config *device)\n{\n\tstate_save_register_device_item_array(device, 0, F2203->REGS);\n\tFMsave_state_st(device,&F2203->OPN.ST);\n\tFMsave_state_channel(device,F2203->CH,3);\n\t/* 3slots */\n\tstate_save_register_device_item_array (device, 0, F2203->OPN.SL3.fc);\n\tstate_save_register_device_item  (device, 0, F2203->OPN.SL3.fn_h);\n\tstate_save_register_device_item_array  (device, 0, F2203->OPN.SL3.kcode);\n}\n#endif /* _STATE_H */\n\n/* ----------  Initialize YM2203 emulator(s) ----------\n   'num' is the number of virtual YM2203s to allocate\n   'clock' is the chip clock in Hz\n   'rate' is sampling rate\n*/\n//void * ym2203_init(void *param, const device_config *device, int clock, int rate,\n//               FM_TIMERHANDLER timer_handler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg)\nvoid * ym2203_init(void *param, int clock, int rate,\n               FM_TIMERHANDLER timer_handler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg)\n{\n\tYM2203 *F2203;\n\n\t/* allocate ym2203 state space */\n\tif( (F2203 = (YM2203 *)malloc(sizeof(YM2203)))==NULL)\n\t\treturn NULL;\n\t/* clear */\n\tmemset(F2203,0,sizeof(YM2203));\n\n\tif( !init_tables() )\n\t{\n\t\tfree( F2203 );\n\t\treturn NULL;\n\t}\n\n\tF2203->OPN.ST.param = param;\n\tF2203->OPN.type = TYPE_YM2203;\n\tF2203->OPN.P_CH = F2203->CH;\n\t//F2203->OPN.ST.device = device;\n\tF2203->OPN.ST.clock = clock;\n\tF2203->OPN.ST.rate = rate;\n\n\tF2203->OPN.ST.timer_handler = timer_handler;\n\tF2203->OPN.ST.IRQ_Handler   = IRQHandler;\n\tF2203->OPN.ST.SSG           = ssg;\n\n#ifdef __STATE_H__\n\tYM2203_save_state(F2203, device);\n#endif\n\treturn F2203;\n}\n\n/* shut down emulator */\nvoid ym2203_shutdown(void *chip)\n{\n\tYM2203 *FM2203 = (YM2203 *)chip;\n\n\tFMCloseTable();\n\tfree(FM2203);\n}\n\n/* YM2203 I/O interface */\nint ym2203_write(void *chip,int a,UINT8 v)\n{\n\tYM2203 *F2203 = (YM2203 *)chip;\n\tFM_OPN *OPN = &F2203->OPN;\n\n\tif( !(a&1) )\n\t{\t/* address port */\n\t\tOPN->ST.address = (v &= 0xff);\n\n\t\t/* Write register to SSG emulator */\n\t\tif( v < 16 ) (*OPN->ST.SSG->write)(OPN->ST.param,0,v);\n\n\t\t/* prescaler select : 2d,2e,2f  */\n\t\tif( v >= 0x2d && v <= 0x2f )\n\t\t\tOPNPrescaler_w(OPN , v , 1);\n\t}\n\telse\n\t{\t/* data port */\n\t\tint addr = OPN->ST.address;\n\t\tF2203->REGS[addr] = v;\n\t\tswitch( addr & 0xf0 )\n\t\t{\n\t\tcase 0x00:\t/* 0x00-0x0f : SSG section */\n\t\t\t/* Write data to SSG emulator */\n\t\t\t(*OPN->ST.SSG->write)(OPN->ST.param,a,v);\n\t\t\tbreak;\n\t\tcase 0x20:\t/* 0x20-0x2f : Mode section */\n\t\t\tym2203_update_req(OPN->ST.param);\n\t\t\t/* write register */\n\t\t\tOPNWriteMode(OPN,addr,v);\n\t\t\tbreak;\n\t\tdefault:\t/* 0x30-0xff : OPN section */\n\t\t\tym2203_update_req(OPN->ST.param);\n\t\t\t/* write register */\n\t\t\tOPNWriteReg(OPN,addr,v);\n\t\t}\n\t\tFM_BUSY_SET(&OPN->ST,1);\n\t}\n\treturn OPN->ST.irq;\n}\n\nUINT8 ym2203_read(void *chip,int a)\n{\n\tYM2203 *F2203 = (YM2203 *)chip;\n\tint addr = F2203->OPN.ST.address;\n\tUINT8 ret = 0;\n\n\tif( !(a&1) )\n\t{\t/* status port */\n\t\tret = FM_STATUS_FLAG(&F2203->OPN.ST);\n\t}\n\telse\n\t{\t/* data port (only SSG) */\n\t\tif( addr < 16 ) ret = (*F2203->OPN.ST.SSG->read)(F2203->OPN.ST.param);\n\t}\n\treturn ret;\n}\n\nint ym2203_timer_over(void *chip,int c)\n{\n\tYM2203 *F2203 = (YM2203 *)chip;\n\n\tif( c )\n\t{\t/* Timer B */\n\t\tTimerBOver( &(F2203->OPN.ST) );\n\t}\n\telse\n\t{\t/* Timer A */\n\t\tym2203_update_req(F2203->OPN.ST.param);\n\t\t/* timer update */\n\t\tTimerAOver( &(F2203->OPN.ST) );\n\t\t/* CSM mode key,TL control */\n\t\tif( F2203->OPN.ST.mode & 0x80 )\n\t\t{\t/* CSM mode auto key on */\n\t\t\tCSMKeyControll( F2203->OPN.type, &(F2203->CH[2]) );\n\t\t}\n\t}\n\treturn F2203->OPN.ST.irq;\n}\n\nvoid ym2203_set_mutemask(void *chip, UINT32 MuteMask)\n{\n\tYM2203 *F2203 = (YM2203 *)chip;\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 3; CurChn ++)\n\t\tF2203->CH[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n#endif /* BUILD_YM2203 */\n\n\n\n#if (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B)\n\n/* ADPCM type A channel struct */\ntypedef struct\n{\n\tUINT8\t\tflag;\t\t\t/* port state               */\n\tUINT8\t\tflagMask;\t\t/* arrived flag mask        */\n\tUINT8\t\tnow_data;\t\t/* current ROM data         */\n\tUINT32\t\tnow_addr;\t\t/* current ROM address      */\n\tUINT32\t\tnow_step;\n\tUINT32\t\tstep;\n\tUINT32\t\tstart;\t\t\t/* sample data start address*/\n\tUINT32\t\tend;\t\t\t/* sample data end address  */\n\tUINT8\t\tIL;\t\t\t\t/* Instrument Level         */\n\tINT32\t\tadpcm_acc;\t\t/* accumulator              */\n\tINT32\t\tadpcm_step;\t\t/* step                     */\n\tINT32\t\tadpcm_out;\t\t/* (speedup) hiro-shi!!     */\n\tINT8\t\tvol_mul;\t\t/* volume in \"0.75dB\" steps */\n\tUINT8\t\tvol_shift;\t\t/* volume in \"-6dB\" steps   */\n\tINT32\t\t*pan;\t\t\t/* &out_adpcm[OPN_xxxx]     */\n\tUINT8\t\tMuted;\n} ADPCM_CH;\n\n/* here's the virtual YM2610 */\ntypedef struct\n{\n\tUINT8\t\tREGS[512];\t\t\t/* registers            */\n\tFM_OPN\t\tOPN;\t\t\t\t/* OPN state            */\n\tFM_CH\t\tCH[6];\t\t\t\t/* channel state        */\n\tUINT8\t\taddr_A1;\t\t\t/* address line A1      */\n\n\t/* ADPCM-A unit */\n\t//const UINT8\t*pcmbuf;\t\t\t/* pcm rom buffer       */\n\tUINT8\t\t*pcmbuf;\t\t\t/* pcm rom buffer       */\n\tUINT32\t\tpcm_size;\t\t\t/* size of pcm rom      */\n\tUINT8\t\tadpcmTL;\t\t\t/* adpcmA total level   */\n\tADPCM_CH\tadpcm[6];\t\t\t/* adpcm channels       */\n\tUINT32\t\tadpcmreg[0x30];\t\t/* registers            */\n\tUINT8\t\tadpcm_arrivedEndAddress;\n\tYM_DELTAT\tdeltaT;\t\t\t\t/* Delta-T ADPCM unit   */\n\tUINT8\t\tMuteDeltaT;\n\n    UINT8\t\tflagmask;\t\t\t/* YM2608 only */\n    UINT8\t\tirqmask;\t\t\t/* YM2608 only */\n} YM2610;\n\n/* here is the virtual YM2608 */\ntypedef YM2610 YM2608;\n\n\n/**** YM2610 ADPCM defines ****/\n#define ADPCM_SHIFT    (16)      /* frequency step rate   */\n#define ADPCMA_ADDRESS_SHIFT 8   /* adpcm A address shift */\n\n/* Algorithm and tables verified on real YM2608 and YM2610 */\n\n/* usual ADPCM table (16 * 1.1^N) */\nstatic const int steps[49] =\n{\n\t 16,  17,   19,   21,   23,   25,   28,\n\t 31,  34,   37,   41,   45,   50,   55,\n\t 60,  66,   73,   80,   88,   97,  107,\n\t118, 130,  143,  157,  173,  190,  209,\n\t230, 253,  279,  307,  337,  371,  408,\n\t449, 494,  544,  598,  658,  724,  796,\n\t876, 963, 1060, 1166, 1282, 1411, 1552\n};\n\n/* different from the usual ADPCM table */\nstatic const int step_inc[8] = { -1*16, -1*16, -1*16, -1*16, 2*16, 5*16, 7*16, 9*16 };\n\n/* speedup purposes only */\nstatic int jedi_table[ 49*16 ];\n\n\nstatic void Init_ADPCMATable(void)\n{\n\tint step, nib;\n\n\tfor (step = 0; step < 49; step++)\n\t{\n\t\t/* loop over all nibbles and compute the difference */\n\t\tfor (nib = 0; nib < 16; nib++)\n\t\t{\n\t\t\tint value = (2*(nib & 0x07) + 1) * steps[step] / 8;\n\t\t\tjedi_table[step*16 + nib] = (nib&0x08) ? -value : value;\n\t\t}\n\t}\n}\n\n/* ADPCM A (Non control type) : calculate one channel output */\nINLINE void ADPCMA_calc_chan( YM2610 *F2610, ADPCM_CH *ch )\n{\n\tUINT32 step;\n\tUINT8  data;\n\n\tif (ch->Muted)\n\t\treturn;\n\n\n\tch->now_step += ch->step;\n\tif ( ch->now_step >= (1<<ADPCM_SHIFT) )\n\t{\n\t\tstep = ch->now_step >> ADPCM_SHIFT;\n\t\tch->now_step &= (1<<ADPCM_SHIFT)-1;\n\t\tdo{\n\t\t\t/* end check */\n\t\t\t/* 11-06-2001 JB: corrected comparison. Was > instead of == */\n\t\t\t/* YM2610 checks lower 20 bits only, the 4 MSB bits are sample bank */\n\t\t\t/* Here we use 1<<21 to compensate for nibble calculations */\n\n\t\t\tif (   (ch->now_addr & ((1<<21)-1)) == ((ch->end<<1) & ((1<<21)-1))\t   )\n\t\t\t{\n\t\t\t\tch->flag = 0;\n\t\t\t\tF2610->adpcm_arrivedEndAddress |= ch->flagMask;\n\t\t\t\treturn;\n\t\t\t}\n#if 0\n\t\t\tif ( ch->now_addr > (F2610->pcmsizeA<<1) )\n\t\t\t{\n#ifdef _DEBUG\n\t\t\t\tLOG(LOG_WAR,(\"YM2610: Attempting to play past adpcm rom size!\\n\" ));\n#endif\n\t\t\t\treturn;\n\t\t\t}\n#endif\n\t\t\tif ( ch->now_addr&1 )\n\t\t\t\tdata = ch->now_data & 0x0f;\n\t\t\telse\n\t\t\t{\n\t\t\t\tch->now_data = *(F2610->pcmbuf+(ch->now_addr>>1));\n\t\t\t\tdata = (ch->now_data >> 4) & 0x0f;\n\t\t\t}\n\n\t\t\tch->now_addr++;\n\n\t\t\tch->adpcm_acc += jedi_table[ch->adpcm_step + data];\n\n\t\t\t/* extend 12-bit signed int */\n\t\t\tif (ch->adpcm_acc & ~0x7ff)\n\t\t\t\tch->adpcm_acc |= ~0xfff;\n\t\t\telse\n\t\t\t\tch->adpcm_acc &= 0xfff;\n\n\t\t\tch->adpcm_step += step_inc[data & 7];\n\t\t\tLimit( ch->adpcm_step, 48*16, 0*16 );\n\n\t\t}while(--step);\n\n\t\t/* calc pcm * volume data */\n\t\tch->adpcm_out = ((ch->adpcm_acc * ch->vol_mul) >> ch->vol_shift) & ~3;\t/* multiply, shift and mask out 2 LSB bits */\n\t}\n\n\t/* output for work of output channels (out_adpcm[OPNxxxx])*/\n\t*(ch->pan) += ch->adpcm_out;\n}\n\n/* ADPCM type A Write */\nstatic void FM_ADPCMAWrite(YM2610 *F2610,int r,int v)\n{\n\tADPCM_CH *adpcm = F2610->adpcm;\n\tUINT8 c = r&0x07;\n\n\tF2610->adpcmreg[r] = v&0xff; /* stock data */\n\tswitch( r )\n\t{\n\tcase 0x00: /* DM,--,C5,C4,C3,C2,C1,C0 */\n\t\tif( !(v&0x80) )\n\t\t{\n\t\t\t/* KEY ON */\n\t\t\tfor( c = 0; c < 6; c++ )\n\t\t\t{\n\t\t\t\tif( (v>>c)&1 )\n\t\t\t\t{\n\t\t\t\t\t/**** start adpcm ****/\n\t\t\t\t\t// The .step variable is already set and for the YM2608 it is different on channels 4 and 5.\n\t\t\t\t\t//adpcm[c].step      = (UINT32)((float)(1<<ADPCM_SHIFT)*((float)F2610->OPN.ST.freqbase)/3.0);\n\t\t\t\t\tadpcm[c].now_addr  = adpcm[c].start<<1;\n\t\t\t\t\tadpcm[c].now_step  = 0;\n\t\t\t\t\tadpcm[c].adpcm_acc = 0;\n\t\t\t\t\tadpcm[c].adpcm_step= 0;\n\t\t\t\t\tadpcm[c].adpcm_out = 0;\n\t\t\t\t\tadpcm[c].flag      = 1;\n\n\t\t\t\t\tif(F2610->pcmbuf==NULL)\n\t\t\t\t\t{\t\t\t\t\t/* Check ROM Mapped */\n#ifdef _DEBUG\n\t\t\t\t\t\tlogerror(\"YM2608-YM2610: ADPCM-A rom not mapped\\n\");\n#endif\n\t\t\t\t\t\tadpcm[c].flag = 0;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif(adpcm[c].end >= F2610->pcm_size)\n\t\t\t\t\t\t{\t/* Check End in Range */\n#ifdef _DEBUG\n\t\t\t\t\t\t\tlogerror(\"YM2610: ADPCM-A end out of range: $%08x\\n\",adpcm[c].end);\n#endif\n\t\t\t\t\t\t\t/*adpcm[c].end = F2610->pcm_size-1;*/ /* JB: DO NOT uncomment this, otherwise you will break the comparison in the ADPCM_CALC_CHA() */\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(adpcm[c].start >= F2610->pcm_size)\t/* Check Start in Range */\n\t\t\t\t\t\t{\n#ifdef _DEBUG\n\t\t\t\t\t\t\tlogerror(\"YM2608-YM2610: ADPCM-A start out of range: $%08x\\n\",adpcm[c].start);\n#endif\n\t\t\t\t\t\t\tadpcm[c].flag = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* KEY OFF */\n\t\t\tfor( c = 0; c < 6; c++ )\n\t\t\t\tif( (v>>c)&1 )\n\t\t\t\t\tadpcm[c].flag = 0;\n\t\t}\n\t\tbreak;\n\tcase 0x01:\t/* B0-5 = TL */\n\t\tF2610->adpcmTL = (v & 0x3f) ^ 0x3f;\n\t\tfor( c = 0; c < 6; c++ )\n\t\t{\n\t\t\tint volume = F2610->adpcmTL + adpcm[c].IL;\n\n\t\t\tif ( volume >= 63 )\t/* This is correct, 63 = quiet */\n\t\t\t{\n\t\t\t\tadpcm[c].vol_mul   = 0;\n\t\t\t\tadpcm[c].vol_shift = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tadpcm[c].vol_mul   = 15 - (volume & 7);\t\t/* so called 0.75 dB */\n\t\t\t\tadpcm[c].vol_shift =  1 + (volume >> 3);\t/* Yamaha engineers used the approximation: each -6 dB is close to divide by two (shift right) */\n\t\t\t}\n\n\t\t\t/* calc pcm * volume data */\n\t\t\tadpcm[c].adpcm_out = ((adpcm[c].adpcm_acc * adpcm[c].vol_mul) >> adpcm[c].vol_shift) & ~3;\t/* multiply, shift and mask out low 2 bits */\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tc = r&0x07;\n\t\tif( c >= 0x06 ) return;\n\t\tswitch( r&0x38 )\n\t\t{\n\t\tcase 0x08:\t/* B7=L,B6=R, B4-0=IL */\n\t\t{\n\t\t\tint volume;\n\n\t\t\tadpcm[c].IL = (v & 0x1f) ^ 0x1f;\n\n\t\t\tvolume = F2610->adpcmTL + adpcm[c].IL;\n\n\t\t\tif ( volume >= 63 )\t/* This is correct, 63 = quiet */\n\t\t\t{\n\t\t\t\tadpcm[c].vol_mul   = 0;\n\t\t\t\tadpcm[c].vol_shift = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tadpcm[c].vol_mul   = 15 - (volume & 7);\t\t/* so called 0.75 dB */\n\t\t\t\tadpcm[c].vol_shift =  1 + (volume >> 3);\t/* Yamaha engineers used the approximation: each -6 dB is close to divide by two (shift right) */\n\t\t\t}\n\n\t\t\tadpcm[c].pan    = &F2610->OPN.out_adpcm[(v>>6)&0x03];\n\n\t\t\t/* calc pcm * volume data */\n\t\t\tadpcm[c].adpcm_out = ((adpcm[c].adpcm_acc * adpcm[c].vol_mul) >> adpcm[c].vol_shift) & ~3;\t/* multiply, shift and mask out low 2 bits */\n\t\t}\n\t\t\tbreak;\n\t\tcase 0x10:\n\t\tcase 0x18:\n\t\t\tadpcm[c].start  = ( (F2610->adpcmreg[0x18 + c]*0x0100 | F2610->adpcmreg[0x10 + c]) << ADPCMA_ADDRESS_SHIFT);\n\t\t\tbreak;\n\t\tcase 0x20:\n\t\tcase 0x28:\n\t\t\tadpcm[c].end    = ( (F2610->adpcmreg[0x28 + c]*0x0100 | F2610->adpcmreg[0x20 + c]) << ADPCMA_ADDRESS_SHIFT);\n\t\t\tadpcm[c].end   += (1<<ADPCMA_ADDRESS_SHIFT) - 1;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n#ifdef __STATE_H__\n/* FM channel save , internal state only */\nstatic void FMsave_state_adpcma(const device_config *device,ADPCM_CH *adpcm)\n{\n\tint ch;\n\n\tfor(ch=0;ch<6;ch++,adpcm++)\n\t{\n\t\tstate_save_register_device_item(device, ch, adpcm->flag);\n\t\tstate_save_register_device_item(device, ch, adpcm->now_data);\n\t\tstate_save_register_device_item(device, ch, adpcm->now_addr);\n\t\tstate_save_register_device_item(device, ch, adpcm->now_step);\n\t\tstate_save_register_device_item(device, ch, adpcm->adpcm_acc);\n\t\tstate_save_register_device_item(device, ch, adpcm->adpcm_step);\n\t\tstate_save_register_device_item(device, ch, adpcm->adpcm_out);\n\t}\n}\n#endif /* _STATE_H */\n\n#endif /* (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B) */\n\n\n#if BUILD_YM2608\n/*****************************************************************************/\n/*      YM2608 local section                                                 */\n/*****************************************************************************/\n\n\n\nstatic const unsigned int YM2608_ADPCM_ROM_addr[2*6] = {\n0x0000, 0x01bf, /* bass drum  */\n0x01c0, 0x043f, /* snare drum */\n0x0440, 0x1b7f, /* top cymbal */\n0x1b80, 0x1cff, /* high hat */\n0x1d00, 0x1f7f, /* tom tom  */\n0x1f80, 0x1fff  /* rim shot */\n};\n\n\n/*\n    This data is derived from the chip's output - internal ROM can't be read.\n    It was verified, using real YM2608, that this ADPCM stream produces 100% correct output signal.\n*/\n\nstatic const unsigned char YM2608_ADPCM_ROM[0x2000] = {\n\n/* Source: 01BD.ROM */\n/* Length: 448 / 0x000001C0 */\n\n0x88,0x08,0x08,0x08,0x00,0x88,0x16,0x76,0x99,0xB8,0x22,0x3A,0x84,0x3C,0xB1,0x54,\n0x10,0xA9,0x98,0x32,0x80,0x33,0x9A,0xA7,0x4A,0xB4,0x58,0xBC,0x15,0x29,0x8A,0x97,\n0x9B,0x44,0xAC,0x80,0x12,0xDE,0x13,0x1B,0xC0,0x58,0xC8,0x11,0x0A,0xA2,0x1A,0xA0,\n0x00,0x98,0x0B,0x93,0x9E,0x92,0x0A,0x88,0xBE,0x14,0x1B,0x98,0x08,0xA1,0x4A,0xC1,\n0x30,0xD9,0x33,0x98,0x10,0x89,0x17,0x1A,0x82,0x29,0x37,0x0C,0x83,0x50,0x9A,0x24,\n0x1A,0x83,0x10,0x23,0x19,0xB3,0x72,0x8A,0x16,0x10,0x0A,0x93,0x70,0x99,0x23,0x99,\n0x02,0x20,0x91,0x18,0x02,0x41,0xAB,0x24,0x18,0x81,0x99,0x4A,0xE8,0x28,0x9A,0x99,\n0xA1,0x2F,0xA8,0x9D,0x90,0x08,0xCC,0xA3,0x1D,0xCA,0x82,0x0B,0xD8,0x08,0xB9,0x09,\n0xBC,0xB8,0x00,0xBE,0x90,0x1B,0xCA,0x00,0x9B,0x8A,0xA8,0x91,0x0F,0xB3,0x3D,0xB8,\n0x31,0x0B,0xA5,0x0A,0x11,0xA1,0x48,0x92,0x10,0x50,0x91,0x30,0x23,0x09,0x37,0x39,\n0xA2,0x72,0x89,0x92,0x30,0x83,0x1C,0x96,0x28,0xB9,0x24,0x8C,0xA1,0x31,0xAD,0xA9,\n0x13,0x9C,0xBA,0xA8,0x0B,0xBF,0xB8,0x9B,0xCA,0x88,0xDB,0xB8,0x19,0xFC,0x92,0x0A,\n0xBA,0x89,0xAB,0xB8,0xAB,0xD8,0x08,0xAD,0xBA,0x33,0x9D,0xAA,0x83,0x3A,0xC0,0x40,\n0xB9,0x15,0x39,0xA2,0x52,0x89,0x02,0x63,0x88,0x13,0x23,0x03,0x52,0x02,0x54,0x00,\n0x11,0x23,0x23,0x35,0x20,0x01,0x44,0x41,0x80,0x24,0x40,0xA9,0x45,0x19,0x81,0x12,\n0x81,0x02,0x11,0x21,0x19,0x02,0x61,0x8A,0x13,0x3A,0x10,0x12,0x23,0x8B,0x37,0x18,\n0x91,0x24,0x10,0x81,0x34,0x20,0x05,0x32,0x82,0x53,0x20,0x14,0x33,0x31,0x34,0x52,\n0x00,0x43,0x32,0x13,0x52,0x22,0x13,0x52,0x11,0x43,0x11,0x32,0x32,0x32,0x22,0x02,\n0x13,0x12,0x89,0x22,0x19,0x81,0x81,0x08,0xA8,0x08,0x8B,0x90,0x1B,0xBA,0x8A,0x9B,\n0xB9,0x89,0xCA,0xB9,0xAB,0xCA,0x9B,0xCA,0xB9,0xAB,0xDA,0x99,0xAC,0xBB,0x9B,0xAC,\n0xAA,0xBA,0xAC,0xAB,0x9A,0xAA,0xAA,0xBA,0xB8,0xA9,0xBA,0x99,0xA9,0x9A,0xA0,0x8A,\n0xA9,0x08,0x8A,0xA9,0x00,0x99,0x89,0x88,0x98,0x08,0x99,0x00,0x89,0x80,0x08,0x98,\n0x00,0x88,0x88,0x80,0x90,0x80,0x90,0x80,0x81,0x99,0x08,0x88,0x99,0x09,0x00,0x1A,\n0xA8,0x10,0x9A,0x88,0x08,0x0A,0x8A,0x89,0x99,0xA8,0x98,0xA9,0x99,0x99,0xA9,0x99,\n0xAA,0x8A,0xAA,0x9B,0x8A,0x9A,0xA9,0x9A,0xBA,0x99,0x9A,0xAA,0x99,0x89,0xA9,0x99,\n0x98,0x9A,0x98,0x88,0x09,0x89,0x09,0x08,0x08,0x09,0x18,0x18,0x00,0x12,0x00,0x11,\n0x11,0x11,0x12,0x12,0x21,0x21,0x22,0x22,0x22,0x22,0x22,0x22,0x32,0x31,0x32,0x31,\n0x32,0x32,0x21,0x31,0x21,0x32,0x21,0x12,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,\n\n/* Source: 02SD.ROM */\n/* Length: 640 / 0x00000280 */\n\n0x0A,0xDC,0x14,0x0B,0xBA,0xBC,0x01,0x0F,0xF5,0x2F,0x87,0x19,0xC9,0x24,0x1B,0xA1,\n0x31,0x99,0x90,0x32,0x32,0xFE,0x83,0x48,0xA8,0xA9,0x23,0x19,0xBC,0x91,0x02,0x41,\n0xDE,0x81,0x28,0xA8,0x0A,0xB1,0x72,0xDA,0x23,0xBC,0x04,0x19,0xB8,0x21,0x8A,0x03,\n0x29,0xBA,0x14,0x21,0x0B,0xC0,0x43,0x08,0x91,0x50,0x93,0x0F,0x86,0x1A,0x91,0x18,\n0x21,0xCB,0x27,0x0A,0xA1,0x42,0x8C,0xA9,0x21,0x10,0x08,0xAB,0x94,0x2A,0xDA,0x02,\n0x8B,0x91,0x09,0x98,0xAE,0x80,0xA9,0x02,0x0A,0xE9,0x21,0xBB,0x15,0x20,0xBE,0x92,\n0x42,0x09,0xA9,0x11,0x34,0x08,0x12,0x0A,0x27,0x29,0xA1,0x52,0x12,0x8E,0x92,0x28,\n0x92,0x2B,0xD1,0x23,0xBF,0x81,0x10,0x99,0xA8,0x0A,0xC4,0x3B,0xB9,0xB0,0x00,0x62,\n0xCF,0x92,0x29,0x92,0x2B,0xB1,0x1C,0xB2,0x72,0xAA,0x88,0x11,0x18,0x80,0x13,0x9E,\n0x03,0x18,0xB0,0x60,0xA1,0x28,0x88,0x08,0x04,0x10,0x8F,0x96,0x19,0x90,0x01,0x09,\n0xC8,0x50,0x91,0x8A,0x01,0xAB,0x03,0x50,0xBA,0x9D,0x93,0x68,0xBA,0x80,0x22,0xCB,\n0x41,0xBC,0x92,0x60,0xB9,0x1A,0x95,0x4A,0xC8,0x20,0x88,0x33,0xAC,0x92,0x38,0x83,\n0x09,0x80,0x16,0x09,0x29,0xD0,0x54,0x8C,0xA2,0x28,0x91,0x89,0x93,0x60,0xCD,0x85,\n0x1B,0xA1,0x49,0x90,0x8A,0x80,0x34,0x0C,0xC9,0x14,0x19,0x98,0xA0,0x40,0xA9,0x21,\n0xD9,0x34,0x0A,0xA9,0x10,0x23,0xCB,0x25,0xAA,0x25,0x9B,0x13,0xCD,0x16,0x09,0xA0,\n0x80,0x01,0x19,0x90,0x88,0x21,0xAC,0x33,0x8B,0xD8,0x27,0x3B,0xB8,0x81,0x31,0x80,\n0xAF,0x97,0x0A,0x82,0x0A,0xA0,0x21,0x89,0x8A,0xA2,0x32,0x8D,0xBB,0x87,0x19,0x21,\n0xC9,0xBC,0x45,0x09,0x90,0x09,0xA1,0x24,0x1A,0xD0,0x10,0x08,0x11,0xA9,0x21,0xE8,\n0x60,0xA9,0x14,0x0C,0xD1,0x32,0xAB,0x04,0x0C,0x81,0x90,0x29,0x83,0x9B,0x01,0x8F,\n0x97,0x0B,0x82,0x18,0x88,0xBA,0x06,0x39,0xC8,0x23,0xBC,0x04,0x09,0x92,0x08,0x1A,\n0xBB,0x74,0x8C,0x81,0x18,0x81,0x9D,0x83,0x41,0xCD,0x81,0x40,0x9A,0x90,0x10,0x12,\n0x9C,0xA1,0x68,0xD8,0x33,0x9C,0x91,0x01,0x12,0xBE,0x02,0x09,0x12,0x99,0x9A,0x36,\n0x0A,0xB0,0x30,0x88,0xA3,0x2D,0x12,0xBC,0x03,0x3A,0x11,0xBD,0x08,0xC8,0x62,0x80,\n0x8B,0xD8,0x23,0x38,0xF9,0x12,0x08,0x99,0x91,0x21,0x99,0x85,0x2F,0xB2,0x30,0x90,\n0x88,0xD9,0x53,0xAC,0x82,0x19,0x91,0x20,0xCC,0x96,0x29,0xC9,0x24,0x89,0x80,0x99,\n0x12,0x08,0x18,0x88,0x99,0x23,0xAB,0x73,0xCB,0x33,0x9F,0x04,0x2B,0xB1,0x08,0x03,\n0x1B,0xC9,0x21,0x32,0xFA,0x33,0xDB,0x02,0x33,0xAE,0xB9,0x54,0x8B,0xA1,0x20,0x89,\n0x90,0x11,0x88,0x09,0x98,0x23,0xBE,0x37,0x8D,0x81,0x20,0xAA,0x34,0xBB,0x13,0x18,\n0xB9,0x40,0xB1,0x18,0x83,0x8E,0xB2,0x72,0xBC,0x82,0x30,0xA9,0x9A,0x24,0x8B,0x27,\n0x0E,0x91,0x20,0x90,0x08,0xB0,0x32,0xB9,0x21,0xB0,0xAC,0x45,0x9A,0xA1,0x50,0xA9,\n0x80,0x0A,0x26,0x9B,0x11,0xBB,0x23,0x71,0xCB,0x12,0x10,0xB8,0x40,0xA9,0xA5,0x39,\n0xC0,0x30,0xB2,0x20,0xAA,0xBA,0x76,0x1C,0xC1,0x48,0x98,0x80,0x18,0x81,0xAA,0x23,\n0x9C,0xA2,0x32,0xAC,0x9A,0x43,0x9C,0x12,0xAD,0x82,0x72,0xBC,0x00,0x82,0x39,0xD1,\n0x3A,0xB8,0x35,0x9B,0x10,0x40,0xF9,0x22,0x0A,0xC0,0x51,0xB9,0x82,0x18,0x98,0xA3,\n0x79,0xD0,0x20,0x88,0x09,0x01,0x99,0x82,0x11,0x38,0xFC,0x33,0x09,0xC8,0x40,0xA9,\n0x11,0x29,0xAA,0x94,0x3A,0xC2,0x4A,0xC0,0x89,0x52,0xBC,0x11,0x08,0x09,0xB8,0x71,\n0xA9,0x08,0xA8,0x62,0x8D,0x92,0x10,0x00,0x9E,0x94,0x38,0xBA,0x13,0x88,0x90,0x4A,\n0xE2,0x30,0xBA,0x02,0x00,0x19,0xD9,0x62,0xBB,0x04,0x0B,0xA3,0x68,0xB9,0x21,0x88,\n0x9D,0x04,0x10,0x8C,0xC8,0x62,0x99,0xAA,0x24,0x1A,0x80,0x9A,0x14,0x9B,0x26,0x8C,\n0x92,0x30,0xB9,0x09,0xA3,0x71,0xBB,0x10,0x19,0x82,0x39,0xDB,0x02,0x44,0x9F,0x10,\n\n/* Source: 04TOP.ROM */\n/* Length: 5952 / 0x00001740 */\n\n0x07,0xFF,0x7C,0x3C,0x31,0xC6,0xC4,0xBB,0x7F,0x7F,0x7B,0x82,0x8A,0x4D,0x5F,0x7C,\n0x3E,0x44,0xD2,0xB3,0xA0,0x19,0x1B,0x6C,0x81,0x28,0xC4,0xA1,0x1C,0x4B,0x18,0x00,\n0x2A,0xA2,0x0A,0x7C,0x2A,0x00,0x01,0x89,0x98,0x48,0x8A,0x3C,0x28,0x2A,0x5B,0x3E,\n0x3A,0x1A,0x3B,0x3D,0x4B,0x3B,0x4A,0x08,0x2A,0x1A,0x2C,0x4A,0x3B,0x82,0x99,0x3C,\n0x5D,0x29,0x2B,0x39,0x0B,0x23,0xAB,0x1A,0x4C,0x79,0xA3,0x01,0xC1,0x2A,0x0A,0x38,\n0xA7,0xB9,0x12,0x1F,0x29,0x08,0x82,0xA1,0x08,0xA9,0x42,0xAA,0x95,0xB3,0x90,0x81,\n0x09,0xD4,0x1A,0x80,0x1B,0x07,0xB8,0x12,0x8E,0x49,0x81,0x92,0xD3,0x90,0xA1,0x2A,\n0x02,0xE1,0xA3,0x99,0x02,0xB3,0x94,0xB3,0xB0,0xF4,0x98,0x93,0x90,0x13,0xE1,0x81,\n0x99,0x38,0x91,0xA6,0xD3,0x99,0x94,0xC1,0x83,0xB1,0x92,0x98,0x49,0xC4,0xB2,0xA4,\n0xA3,0xD0,0x1A,0x30,0xBA,0x59,0x02,0xD4,0xA0,0xA4,0xA2,0x8A,0x01,0x00,0xB7,0xA8,\n0x18,0x2A,0x2B,0x1E,0x23,0xC8,0x1A,0x00,0x39,0xA0,0x18,0x92,0x4F,0x2D,0x5A,0x10,\n0x89,0x81,0x2A,0x8B,0x6A,0x02,0x09,0xB3,0x8D,0x48,0x1B,0x80,0x19,0x34,0xF8,0x29,\n0x0A,0x7B,0x2A,0x28,0x81,0x0C,0x02,0x1E,0x29,0x09,0x12,0xC2,0x94,0xE1,0x18,0x98,\n0x02,0xC4,0x89,0x91,0x1A,0x20,0xA9,0x02,0x1B,0x48,0x8E,0x20,0x88,0x2D,0x08,0x59,\n0x1B,0x02,0xA3,0xB1,0x8A,0x1E,0x58,0x80,0xC2,0xB6,0x88,0x91,0x88,0x11,0xA1,0xA3,\n0xE2,0x01,0xB0,0x19,0x11,0x09,0xF4,0x88,0x09,0x88,0x19,0x89,0x12,0xF1,0x2A,0x28,\n0x8C,0x25,0x99,0xA4,0x98,0x39,0xA1,0x00,0xD0,0x58,0xAA,0x59,0x01,0x0C,0x00,0x2B,\n0x00,0x08,0x89,0x6B,0x69,0x90,0x01,0x90,0x98,0x12,0xB3,0xF3,0xA0,0x89,0x02,0x3B,\n0x0C,0x50,0xA9,0x4E,0x6B,0x19,0x28,0x09,0xA2,0x08,0x2F,0x20,0x88,0x92,0x8A,0x11,\n0xC4,0x93,0xF1,0x18,0x88,0x11,0xF2,0x80,0x92,0xA8,0x02,0xA8,0xB7,0xB3,0xA3,0xA0,\n0x88,0x1A,0x40,0xE2,0x91,0x19,0x88,0x18,0x91,0x83,0xC1,0xB5,0x92,0xA9,0xC6,0x90,\n0x01,0xC2,0x81,0x98,0x03,0xF0,0x00,0x2C,0x2A,0x92,0x2C,0x83,0x1F,0x3A,0x29,0x00,\n0xB8,0x70,0xAB,0x69,0x18,0x89,0x10,0x0D,0x12,0x0B,0x88,0x4A,0x3A,0x9B,0x70,0xA8,\n0x28,0x2F,0x2A,0x3A,0x1B,0x85,0x88,0x8B,0x6A,0x29,0x00,0x91,0x91,0x1B,0x7C,0x29,\n0x01,0x88,0x90,0x19,0x2B,0x2B,0x00,0x39,0xA8,0x5E,0x21,0x89,0x91,0x09,0x3A,0x6F,\n0x2A,0x18,0x18,0x8B,0x50,0x89,0x2B,0x19,0x49,0x88,0x29,0xF5,0x89,0x08,0x09,0x12,\n0xAA,0x15,0xB0,0x82,0xAC,0x38,0x00,0x3F,0x81,0x10,0xB0,0x49,0xA2,0x81,0x3A,0xC8,\n0x87,0x90,0xC4,0xA3,0x99,0x19,0x83,0xE1,0x84,0xE2,0xA2,0x90,0x80,0x93,0xB5,0xC4,\n0xB3,0xA1,0x0A,0x18,0x92,0xC4,0xA0,0x93,0x0C,0x3A,0x18,0x01,0x1E,0x20,0xB1,0x82,\n0x8C,0x03,0xB5,0x2E,0x82,0x19,0xB2,0x1B,0x1B,0x6B,0x4C,0x19,0x12,0x8B,0x5A,0x11,\n0x0C,0x3A,0x2C,0x18,0x3D,0x08,0x2A,0x5C,0x18,0x00,0x88,0x3D,0x29,0x80,0x2A,0x09,\n0x00,0x7A,0x0A,0x10,0x0B,0x69,0x98,0x10,0x81,0x3F,0x00,0x18,0x19,0x91,0xB7,0x9A,\n0x28,0x8A,0x48,0x92,0xF3,0xA2,0x88,0x98,0x87,0xA1,0x88,0x80,0x81,0x95,0xD1,0xA3,\n0x1B,0x1C,0x39,0x10,0xA1,0x2A,0x0B,0x7A,0x4B,0x80,0x13,0xC1,0xD1,0x2B,0x2A,0x85,\n0xB2,0xA2,0x93,0xB2,0xD3,0x80,0xD1,0x18,0x08,0x08,0xB7,0x98,0x81,0x3F,0x01,0x88,\n0x01,0xE2,0x00,0x9A,0x59,0x08,0x10,0xC3,0x99,0x84,0xA9,0xA5,0x91,0x91,0x91,0x80,\n0xB5,0x94,0xC0,0x01,0x98,0x09,0x84,0xB0,0x80,0x7A,0x08,0x18,0x90,0xA8,0x6A,0x1C,\n0x39,0x2A,0xB7,0x98,0x19,0x10,0x2A,0xA1,0x10,0xBD,0x39,0x18,0x2D,0x39,0x3F,0x10,\n0x3F,0x01,0x09,0x19,0x0A,0x38,0x8C,0x40,0xB3,0xB4,0x93,0xAD,0x20,0x2B,0xD4,0x81,\n0xC3,0xB0,0x39,0xA0,0x23,0xD8,0x04,0xB1,0x9B,0xA7,0x1A,0x92,0x08,0xA5,0x88,0x81,\n0xE2,0x01,0xB8,0x01,0x81,0xC1,0xC7,0x90,0x92,0x80,0xA1,0x97,0xA0,0xA2,0x82,0xB8,\n0x18,0x00,0x9C,0x78,0x98,0x83,0x0B,0x0B,0x32,0x7D,0x19,0x10,0xA1,0x19,0x09,0x0A,\n0x78,0xA8,0x10,0x1B,0x29,0x29,0x1A,0x14,0x2F,0x88,0x4A,0x1B,0x10,0x10,0xAB,0x79,\n0x0D,0x49,0x18,0xA0,0x02,0x1F,0x19,0x3A,0x2B,0x11,0x8A,0x88,0x79,0x8A,0x20,0x49,\n0x9B,0x58,0x0B,0x28,0x18,0xA9,0x3A,0x7D,0x00,0x29,0x88,0x82,0x3D,0x1A,0x38,0xBA,\n0x15,0x09,0xAA,0x51,0x8B,0x83,0x3C,0x8A,0x58,0x1B,0xB5,0x01,0xBB,0x50,0x19,0x99,\n0x24,0xCA,0x21,0x1B,0xA2,0x87,0xA8,0xB1,0x68,0xA1,0xA6,0xA2,0xA8,0x29,0x8B,0x24,\n0xB4,0xE2,0x92,0x8A,0x00,0x19,0x93,0xB5,0xB4,0xB1,0x81,0xB1,0x03,0x9A,0x82,0xA7,\n0x90,0xD6,0xA0,0x80,0x1B,0x29,0x01,0xA4,0xE1,0x18,0x0A,0x2A,0x29,0x92,0xC7,0xA8,\n0x81,0x19,0x89,0x30,0x10,0xE0,0x30,0xB8,0x10,0x0C,0x1A,0x79,0x1B,0xA7,0x80,0xA0,\n0x00,0x0B,0x28,0x18,0xB1,0x85,0x1E,0x00,0x20,0xA9,0x18,0x18,0x1C,0x13,0xBC,0x15,\n0x99,0x2E,0x12,0x00,0xE1,0x00,0x0B,0x3B,0x21,0x90,0x06,0xC9,0x2A,0x49,0x0A,0x18,\n0x20,0xD1,0x3C,0x08,0x00,0x83,0xC9,0x41,0x8E,0x18,0x08,0x02,0xA0,0x09,0xA4,0x7B,\n0x90,0x19,0x2A,0x10,0x2A,0xA8,0x71,0xBA,0x10,0x4A,0x0E,0x22,0xB2,0xB2,0x1B,0x8C,\n0x78,0x1A,0xB5,0x93,0xA9,0x1B,0x49,0x19,0x29,0xA3,0xC6,0x88,0xAA,0x32,0x0D,0x1B,\n0x22,0x08,0xC2,0x18,0xB9,0x79,0x3F,0x01,0x10,0xA9,0x84,0x1C,0x09,0x21,0xB0,0xA7,\n0x0A,0x99,0x50,0x0C,0x81,0x28,0x8B,0x48,0x2E,0x00,0x08,0x99,0x38,0x5B,0x88,0x14,\n0xA9,0x08,0x11,0xAA,0x72,0xC1,0xB3,0x09,0x8A,0x05,0x91,0xF2,0x81,0xA1,0x09,0x02,\n0xF2,0x92,0x99,0x1A,0x49,0x80,0xC5,0x90,0x90,0x18,0x09,0x12,0xA1,0xF2,0x81,0x98,\n0xC6,0x91,0xA0,0x11,0xA0,0x94,0xB4,0xF2,0x81,0x8B,0x03,0x80,0xD2,0x93,0xA8,0x88,\n0x69,0xA0,0x03,0xB8,0x88,0x32,0xBC,0x97,0x80,0xB1,0x3B,0x1A,0xA6,0x00,0xD1,0x01,\n0x0B,0x3B,0x30,0x9B,0x31,0x3E,0x92,0x19,0x8A,0xD3,0x5C,0x1B,0x41,0xA0,0x93,0xA2,\n0xAF,0x39,0x4C,0x01,0x92,0xA8,0x81,0x3C,0x0D,0x78,0x98,0x00,0x19,0x0A,0x20,0x2D,\n0x29,0x3C,0x1B,0x48,0x88,0x99,0x7A,0x2D,0x29,0x2A,0x82,0x80,0xA8,0x49,0x3E,0x19,\n0x11,0x98,0x82,0x9A,0x3B,0x28,0x2F,0x20,0x4C,0x90,0x29,0x19,0x9A,0x7A,0x29,0x28,\n0x98,0x88,0x33,0xCD,0x11,0x3A,0xC1,0xA4,0xA0,0xC4,0x82,0xC8,0x50,0x98,0xB2,0x21,\n0xC0,0xB6,0x98,0x82,0x80,0x9C,0x23,0x00,0xF8,0x30,0xA8,0x1A,0x68,0xA8,0x86,0x9A,\n0x01,0x2A,0x0A,0x97,0x91,0xC1,0x18,0x89,0x02,0x83,0xE0,0x01,0x8B,0x29,0x30,0xE2,\n0x91,0x0B,0x18,0x3B,0x1C,0x11,0x28,0xAC,0x78,0x80,0x93,0x91,0xA9,0x49,0x8B,0x87,\n0x90,0x99,0x3D,0x5A,0x81,0x08,0xA1,0x11,0x2F,0x1A,0x21,0x9B,0x15,0xA2,0xB0,0x11,\n0xC0,0x91,0x5B,0x98,0x24,0xA2,0xF2,0x92,0x8B,0x6A,0x18,0x81,0xB5,0xB1,0x88,0x4C,\n0x00,0x00,0xA4,0xC1,0x2B,0x1A,0x59,0x0A,0x02,0x80,0x1E,0x02,0x08,0xB3,0x80,0x9A,\n0x23,0xB8,0xF2,0x84,0xAB,0x01,0x48,0x90,0xA7,0x90,0x0A,0x29,0x09,0x95,0x99,0xA0,\n0x59,0x2B,0x00,0x97,0xB0,0x29,0x89,0x2A,0x03,0xD0,0xB7,0x1B,0x81,0x00,0xA6,0xB1,\n0x90,0x09,0x48,0xC0,0x11,0x00,0x8A,0x00,0x5B,0x83,0x9A,0x18,0x2F,0x3C,0x18,0x11,\n0xA9,0x04,0x1A,0x4F,0x01,0x98,0x81,0x09,0x09,0x4A,0x18,0xB4,0xA2,0x0B,0x59,0x90,\n0x3B,0x49,0xBC,0x40,0x6A,0x88,0x3A,0x08,0x3E,0x3A,0x80,0x93,0xB0,0xE1,0x5A,0x00,\n0xA4,0xB3,0xE3,0x90,0x0D,0x38,0x09,0x82,0xC4,0xA1,0xB1,0x4C,0x18,0x10,0x91,0xB2,\n0x13,0xEA,0x34,0x99,0x88,0xA6,0x89,0x92,0x91,0xC1,0x20,0xB2,0xC2,0x86,0xD2,0xB3,\n0x80,0xB2,0x08,0x09,0x87,0x91,0xC0,0x11,0x89,0x90,0x28,0xB9,0x79,0x19,0xA4,0x82,\n0xD0,0x03,0x0C,0xA3,0xA5,0xB2,0xB2,0x1B,0x29,0x13,0xF1,0xB4,0x81,0x9D,0x38,0x00,\n0xC4,0xA1,0x89,0x59,0x1A,0x81,0xA4,0xA9,0x1C,0x6A,0x19,0x02,0xB1,0x1A,0x4A,0x0B,\n0x78,0x89,0x81,0x1C,0x2A,0x29,0x4A,0xA3,0x3E,0x1C,0x49,0x1A,0x08,0x21,0xAE,0x28,\n0x4B,0x19,0x20,0x8C,0x10,0x3A,0xAB,0x26,0x8B,0x18,0x59,0x99,0x13,0xA2,0xAB,0x79,\n0x2F,0x18,0x10,0xB2,0x80,0x1B,0x4D,0x5A,0x80,0x82,0x98,0x81,0x80,0x09,0xA5,0x90,\n0x91,0x03,0xC2,0xE2,0x81,0xA8,0x82,0x09,0xC6,0xA3,0xB1,0x08,0x5B,0x08,0x05,0xD1,\n0xA2,0x89,0x2A,0x28,0x91,0xA6,0x88,0xB0,0x49,0x80,0x09,0x08,0x88,0x07,0xB8,0x05,\n0x99,0x81,0x88,0x18,0xE2,0x00,0xC3,0x18,0x0D,0x10,0x30,0xD0,0x93,0x8A,0x09,0x10,\n0x2F,0x11,0x90,0xA1,0x20,0x9B,0xB1,0x73,0xC8,0x94,0x98,0x3B,0x01,0x0C,0x30,0x19,\n0xF8,0x12,0x90,0xBA,0x78,0x0A,0x11,0x98,0xA0,0x79,0x8A,0x30,0x2B,0xC2,0x11,0x0D,\n0x09,0x7A,0x00,0x82,0xB9,0x01,0x7A,0x89,0x21,0x09,0xA1,0x0A,0x7C,0x10,0x88,0xB5,\n0x88,0x0A,0x2B,0x69,0x1A,0x10,0xA0,0x5B,0x19,0x1A,0x10,0x19,0x1A,0x6C,0x20,0x90,\n0xA5,0x98,0x1B,0x0A,0x69,0x82,0xD1,0x18,0x09,0x19,0x2A,0x93,0xD4,0x9A,0x01,0x49,\n0xA2,0xA2,0x82,0xD8,0x22,0xAA,0x97,0xA9,0x2D,0x38,0x2A,0xB6,0x80,0x90,0x0A,0x3C,\n0x82,0x94,0xB8,0x21,0x0E,0x2A,0x22,0xB8,0x00,0x4F,0x2B,0x3A,0x81,0xA1,0x29,0x2C,\n0x6A,0x13,0xD1,0xA2,0x98,0x28,0x0C,0x01,0xD5,0x08,0xA9,0x31,0xB3,0xB0,0xA7,0xB0,\n0x29,0x1B,0x87,0xA2,0xA1,0xB2,0x4A,0x89,0x11,0xC3,0xF3,0x98,0x08,0x03,0xA0,0xA3,\n0xC5,0x90,0xB3,0xB5,0xB4,0xB8,0x02,0x91,0x91,0xD3,0xA4,0xC1,0x1B,0x82,0x28,0xA4,\n0xD1,0x94,0x8A,0x28,0x08,0x03,0xE0,0x80,0xD4,0x90,0x91,0xA1,0x3B,0x3D,0x02,0xE4,\n0xA1,0x92,0x89,0x1A,0x4B,0x95,0xB3,0x90,0x99,0x6A,0x0A,0x30,0xA1,0x93,0xA6,0xA9,\n0x85,0x8B,0x82,0x10,0xB1,0xA3,0x94,0xF8,0x38,0x9A,0x30,0x1A,0x8B,0xA7,0x89,0x01,\n0x5B,0x19,0x18,0x11,0xF0,0x18,0x1C,0x39,0x19,0x0C,0x12,0x1C,0x2A,0x7B,0x3A,0x88,\n0x2B,0x18,0x2B,0x5C,0x20,0x92,0x8D,0x38,0x8A,0x3A,0x5B,0x2E,0x3A,0x2B,0x10,0x12,\n0xBB,0x6A,0x4D,0x18,0x10,0xB1,0x81,0x2A,0x8B,0x79,0x80,0x01,0x0A,0x09,0x5B,0x2D,\n0x84,0x8A,0x08,0x02,0xA2,0x91,0x82,0xE8,0x50,0x9B,0x85,0xA3,0xB0,0xA3,0x1B,0x02,\n0x18,0xF3,0xA2,0x88,0xAB,0x53,0xD1,0xB4,0xA3,0x09,0x09,0x18,0xD4,0x08,0xB0,0x09,\n0x58,0xD1,0x82,0x89,0x81,0x1A,0x18,0x05,0xB9,0xC3,0x30,0xC0,0x95,0x80,0xC3,0x89,\n0x89,0x13,0x88,0xF2,0x93,0x0E,0x18,0x01,0x92,0xA5,0xB8,0x2A,0x39,0xAA,0x33,0x9A,\n0xB1,0x11,0xF5,0xA1,0xA1,0x0A,0x50,0xB8,0x03,0xC4,0xA0,0x4E,0x29,0x10,0x88,0xC2,\n0x1A,0x39,0x1D,0x28,0x98,0x94,0x0E,0x10,0x2A,0x3C,0x02,0x2D,0x1B,0x4B,0x3B,0x49,\n0x19,0xA9,0x48,0x2F,0x29,0x10,0x89,0x02,0x0C,0x10,0x09,0xB9,0x70,0x1B,0x8A,0x50,\n0xA8,0x2B,0x49,0x89,0x69,0x88,0x95,0x89,0x90,0x92,0x4C,0x19,0x82,0xC1,0x01,0x80,\n0xA0,0x2B,0x7A,0x81,0x10,0xC2,0xB7,0x98,0x88,0x19,0x2C,0x03,0xB1,0xA4,0xA1,0x0C,\n0x3B,0x78,0x88,0x85,0xB1,0xA0,0x1B,0x3A,0x4A,0x08,0x94,0x81,0xF1,0x80,0x00,0x0C,\n0x59,0x09,0x18,0x90,0xA6,0x92,0x8C,0x1A,0x79,0x92,0xA8,0x00,0x81,0x2E,0x2A,0x13,\n0xA2,0xB0,0xA5,0x88,0x88,0x89,0x11,0x19,0xA0,0xF3,0x82,0xB0,0x83,0x5F,0x2A,0x01,\n0xA1,0x94,0xB0,0x09,0x78,0x98,0xA3,0xA6,0xA0,0x91,0x80,0x93,0x98,0xC1,0x12,0x18,\n0xC9,0x17,0xA0,0xA0,0x1A,0x21,0x80,0x99,0xD4,0x30,0x9D,0x00,0x10,0x2F,0x08,0x1C,\n0x21,0x08,0xB4,0xC3,0x2B,0xA9,0x52,0xD2,0xA3,0xD1,0x09,0x10,0x8B,0x24,0x92,0xD1,\n0x80,0x19,0xA0,0x2C,0x12,0x49,0xAA,0xB6,0x95,0xB8,0x08,0x3A,0x2B,0x01,0xF3,0xB3,\n0x0B,0x09,0x79,0x18,0xA2,0xA4,0xA0,0x18,0x0C,0x20,0x08,0xA9,0x16,0x0C,0x00,0x1B,\n0x08,0x2B,0x7B,0x01,0x01,0xB9,0x59,0x19,0x8B,0x45,0xA8,0x80,0x0C,0x1A,0x41,0x1E,\n0x00,0x28,0xA8,0x5A,0x00,0xC1,0x49,0x99,0x21,0x1D,0x08,0x85,0x99,0x95,0x89,0x90,\n0x11,0x90,0xD1,0x28,0xB2,0xA7,0x99,0x81,0x02,0xAC,0x13,0x81,0xB2,0xA6,0xA9,0x28,\n0x1C,0xB1,0x33,0xD1,0xC1,0x58,0xA8,0x14,0xB0,0xB7,0x91,0xA0,0x82,0x89,0xC2,0x28,\n0xA1,0xB2,0x49,0xD2,0x94,0xC8,0x12,0x80,0x99,0x85,0x08,0xD3,0x09,0xA2,0xB3,0x1E,\n0x08,0x21,0xB9,0x23,0xB4,0xAB,0x41,0xAC,0x87,0x09,0xA2,0xC5,0x0B,0x2A,0x5A,0x91,\n0x20,0x9A,0x89,0x78,0x9B,0x31,0x89,0x80,0x29,0x0A,0xB7,0x3C,0x98,0x48,0x1D,0x00,\n0x01,0xB0,0x20,0x2F,0x29,0x4A,0x89,0x94,0x1C,0x88,0x28,0x2B,0x10,0x88,0x9A,0x71,\n0x9A,0x08,0x4A,0x2F,0x18,0x2B,0x18,0x02,0xA8,0x4B,0x7A,0x99,0x48,0x80,0xA8,0x20,\n0x1D,0x40,0xA8,0x10,0x08,0xA8,0xC5,0x88,0xC2,0x18,0x88,0x2A,0x12,0xF3,0x82,0xD8,\n0x20,0x0A,0x09,0xA6,0x98,0x04,0xB9,0x11,0x18,0xC3,0xE1,0x29,0xA1,0x11,0xC1,0x03,\n0xE2,0x9A,0x33,0xA9,0xB5,0x98,0x92,0xA1,0x02,0xF8,0x21,0xA8,0x10,0x02,0xC1,0xB7,\n0x1B,0x90,0x5B,0x3C,0x83,0x93,0xE0,0x19,0x1A,0x11,0x11,0xF1,0x92,0x89,0x19,0x2C,\n0x2C,0x41,0x99,0x92,0x90,0x3F,0x18,0x4B,0x00,0x08,0xD2,0x01,0xB2,0xAA,0x78,0x09,\n0x01,0x91,0xA2,0x98,0x2F,0x3A,0x2C,0x01,0x00,0x93,0xE0,0x28,0x2C,0x2B,0x01,0x12,\n0xE1,0x80,0xB3,0x3D,0x3A,0x0A,0x50,0x98,0xC2,0xA0,0x11,0xAA,0x30,0x87,0x90,0xC2,\n0x29,0x88,0x38,0xC8,0xB5,0x90,0xBA,0x70,0x1A,0x02,0x94,0xD0,0x80,0x1A,0x82,0xA6,\n0xB0,0x91,0x18,0xB3,0x00,0x13,0xF1,0xA2,0xC1,0x82,0xB0,0x00,0x15,0x0B,0xD3,0x02,\n0xA8,0x91,0x2B,0x1F,0x49,0x88,0xA6,0x80,0x88,0x08,0x1B,0xA5,0x80,0xB9,0x06,0x0B,\n0x90,0x21,0x9D,0x48,0x18,0xA0,0x15,0xC9,0x82,0x2B,0x1A,0x42,0x9A,0xC4,0x39,0xBC,\n0x69,0x00,0xA0,0x29,0x8C,0x39,0x59,0x08,0x09,0x49,0xA9,0x6B,0x81,0x00,0x98,0xB0,\n0x68,0x3D,0x81,0x88,0x18,0x19,0x1D,0x12,0x80,0xB2,0x3A,0x3F,0x85,0x92,0xD0,0x00,\n0x0A,0x19,0x12,0xF1,0x02,0x9B,0x19,0x40,0xB9,0x11,0x02,0xF2,0x1A,0x08,0x94,0x0A,\n0xC2,0x83,0x0B,0xB4,0xA4,0xC0,0x32,0xD8,0x86,0x98,0x90,0x95,0x89,0xA3,0x83,0xC2,\n0x92,0xE1,0x92,0x82,0xD9,0x03,0x08,0xA9,0x85,0x92,0xA2,0x80,0xE0,0x30,0x8B,0xB3,\n0x87,0x89,0x90,0x83,0xA0,0x08,0x92,0x93,0x3E,0xAB,0x43,0x89,0xE3,0x80,0x83,0x2F,\n0x00,0xA3,0x80,0xC9,0x22,0x3F,0x08,0x81,0x0B,0x33,0x9A,0xA3,0x7B,0x0C,0x29,0x4A,\n0x1B,0x21,0xAA,0x70,0x1B,0x0D,0x48,0x1A,0x81,0x88,0xB1,0x39,0x3F,0x08,0x58,0xA0,\n0x81,0x1A,0x1A,0x2B,0x6D,0x11,0x0A,0x91,0x01,0x1A,0x98,0x5A,0x0C,0x03,0xB1,0x84,\n0xA3,0xAD,0x58,0x2A,0xA1,0x84,0xB1,0xA0,0x5C,0x2B,0x13,0xA8,0x95,0x83,0xE8,0x10,\n0x81,0xB0,0x00,0xC2,0x96,0xA0,0x91,0x00,0x2C,0x90,0x30,0xF2,0x80,0xA8,0x39,0x21,\n0xC1,0x03,0xAC,0x39,0x7C,0x29,0x91,0x1A,0x00,0x19,0x2C,0x3A,0x93,0xB0,0x29,0x8F,\n0x28,0x02,0x93,0xF3,0xA9,0x01,0x03,0xE0,0x08,0x09,0x1D,0x58,0xA1,0x83,0xA9,0x6B,\n0x2A,0x3C,0x21,0x89,0xC2,0x2C,0x4B,0x8A,0x50,0x81,0x98,0xA8,0x32,0x0C,0x8E,0x24,\n0x0B,0x1A,0x81,0x92,0xA1,0x4F,0x18,0x3A,0x0A,0xB4,0x18,0x2E,0x39,0x82,0x19,0xD3,\n0xD0,0x28,0x1B,0x11,0x98,0x07,0xAA,0x28,0x00,0x88,0xB4,0x89,0x1B,0x1F,0x22,0x00,\n0xB3,0xC9,0x33,0xAB,0x2B,0xB5,0x48,0x98,0x98,0xA7,0x10,0xD2,0xC1,0x23,0xCA,0x93,\n0xC6,0x80,0xA1,0x88,0x02,0x89,0xE2,0x09,0x38,0xBA,0x40,0x89,0x21,0xD8,0x49,0x10,\n0x8D,0x02,0x90,0xC3,0x9A,0x24,0x89,0x08,0x84,0xA5,0x9C,0x10,0x11,0x9C,0x88,0x30,\n0x3C,0xA1,0x94,0x58,0x8C,0x0B,0x69,0x29,0x9A,0x81,0x12,0x2B,0x8B,0x79,0x94,0xB0,\n0xC1,0x84,0xC2,0x99,0x25,0x99,0x11,0xA2,0x93,0xE4,0x99,0x80,0x0A,0x00,0x10,0xB7,\n0xB0,0x31,0xBA,0x3C,0x21,0xB3,0xF1,0x18,0xA0,0x2A,0x20,0xA3,0x06,0xE8,0x28,0xA1,\n0xB4,0x08,0x0B,0x11,0x4B,0xB7,0x90,0xA5,0x98,0x3D,0x19,0x02,0xA1,0xC4,0xB2,0x19,\n0x28,0xC0,0xA5,0x92,0xB1,0xA3,0x0A,0x0A,0x08,0x2B,0x70,0xC4,0xB3,0x00,0xBC,0x4B,\n0x39,0x12,0xE3,0xA0,0x00,0x3F,0x18,0x29,0x94,0xD1,0x19,0x09,0x00,0xA1,0x83,0x99,\n0x9B,0x35,0x80,0xC4,0xB1,0x6A,0x1A,0x1C,0x29,0x38,0x0E,0x19,0x5A,0x1A,0x82,0x8A,\n0x59,0x2A,0x2E,0x20,0x88,0xA8,0x3A,0x38,0x3D,0x00,0xB3,0x29,0xAD,0x49,0x10,0x0C,\n0x01,0x01,0xA3,0x8F,0x85,0x09,0x1B,0x88,0x10,0xA3,0xD2,0x90,0x3C,0x5C,0x39,0x03,\n0xD1,0xA0,0x00,0x2A,0x0B,0x04,0xA7,0x90,0xA0,0x11,0x90,0x99,0x83,0xB4,0xB1,0xF1,\n0x84,0x88,0x90,0x18,0x18,0xD3,0xD2,0xB3,0xA0,0x1A,0x21,0xA7,0xB2,0xB3,0x92,0x9A,\n0x22,0xB9,0x28,0x38,0xBD,0x87,0x2A,0xB1,0x13,0x0D,0x0A,0x38,0xC9,0x24,0xC0,0x19,\n0x23,0x0F,0x01,0x88,0xC0,0x2A,0x82,0x18,0x28,0xF0,0x18,0x2A,0x29,0x4B,0x35,0xB8,\n0xA3,0x9D,0x18,0x1B,0x40,0x00,0x9A,0x5C,0x3A,0x09,0x2F,0x38,0x8A,0x3B,0x3B,0x11,\n0x5C,0x19,0x2B,0x4A,0x08,0x0A,0x3D,0x20,0x4F,0x3A,0x19,0x2A,0x18,0x4D,0x1B,0x3A,\n0x11,0x0D,0x3A,0x3C,0x4B,0x93,0x81,0xAA,0x6B,0x4A,0x18,0x00,0xC3,0xC3,0x9A,0x59,\n0x2A,0x1B,0xA7,0xA1,0x81,0x88,0x88,0x58,0xB2,0xB1,0x2B,0x83,0xD4,0x81,0x08,0x0F,\n0x00,0x20,0xC2,0xE2,0x80,0x08,0x1C,0x29,0x04,0xB1,0xA2,0x01,0x1C,0x91,0x00,0x0C,\n0x49,0xB0,0x43,0xF2,0x99,0x39,0x3F,0x00,0x81,0x94,0xC1,0x09,0x1A,0x69,0x90,0x80,\n0x94,0xAA,0x20,0x2A,0x91,0xB1,0x39,0x7A,0x38,0xD1,0x10,0x8A,0x8C,0x5A,0x01,0xB5,\n0x98,0x80,0x2A,0x0B,0x32,0x92,0xF1,0x81,0x9A,0x23,0x8A,0xA3,0xB7,0x09,0x03,0x08,\n0xD0,0x94,0x9A,0x09,0x01,0x93,0xB7,0xC2,0x8C,0x3A,0x83,0x99,0x05,0xA0,0x0B,0x29,\n0x93,0xE5,0x80,0x89,0x38,0x90,0x8A,0xD7,0xA1,0x19,0x1B,0x48,0x98,0x92,0xC3,0xA1,\n0x09,0x3F,0x02,0x0C,0x22,0xC3,0xB2,0xA1,0x01,0x9F,0x4A,0x01,0xA3,0xD3,0xB0,0x28,\n0x3F,0x29,0x20,0xA2,0xC2,0xB1,0x08,0x5A,0x98,0x13,0xD2,0xC1,0x01,0xB2,0x80,0x3D,\n0x03,0xC1,0x89,0x96,0x90,0x90,0x3A,0x1A,0x9A,0x32,0xB6,0xA2,0x8E,0x4A,0x28,0x8A,\n0x84,0xA2,0x8A,0x2D,0x49,0x09,0x88,0x18,0x30,0x9D,0x2C,0x23,0xB1,0x0C,0x92,0x2D,\n0x39,0x82,0xC4,0x2E,0x10,0x1A,0x10,0xB9,0x48,0x19,0x39,0xBA,0x34,0xDA,0x2D,0x48,\n0x1A,0xA6,0x98,0x83,0x9A,0x1D,0x38,0x04,0xD0,0x18,0x90,0x2C,0x11,0x93,0xD3,0x9A,\n0x11,0x08,0x82,0xF1,0x01,0xA0,0x2A,0x93,0xD3,0xB4,0xB8,0x82,0x2F,0x11,0xA3,0xB3,\n0xA8,0x3B,0x09,0x23,0x96,0xC8,0x3B,0x3F,0x93,0x82,0xA1,0x90,0x3F,0x28,0x81,0xD1,\n0x93,0x08,0x2D,0x18,0x91,0xB3,0xB5,0x98,0x2A,0x2B,0x84,0xB1,0x5B,0x8A,0x31,0x18,\n0x80,0x8B,0x7E,0x39,0x2B,0x02,0xC1,0x8B,0x6C,0x49,0x09,0x10,0xA1,0x08,0x01,0x0C,\n0x20,0xA1,0x09,0x4F,0x18,0x00,0x01,0xA0,0x5C,0x1B,0x5B,0x10,0x92,0x90,0x2B,0x5A,\n0x3D,0x18,0x91,0x19,0x98,0x2D,0x39,0x89,0x2D,0x3A,0x48,0x2C,0x11,0xB5,0x9A,0x19,\n0x5B,0x28,0x90,0x95,0x98,0x89,0x2B,0x40,0x08,0x90,0xF3,0x0A,0x08,0xA6,0x80,0x91,\n0xB2,0xA0,0x02,0xF2,0xA1,0xB7,0x89,0x81,0x82,0x91,0xB1,0x21,0xAB,0x32,0xE9,0x04,\n0xA2,0x8D,0x12,0x91,0xA3,0xA3,0xD2,0x8B,0x39,0xD1,0x84,0xE2,0x90,0x00,0x2B,0x29,\n0xA3,0xD4,0xA1,0x91,0x1D,0x5A,0x08,0x19,0x11,0x99,0x08,0x18,0x49,0x0F,0x18,0x10,\n0x82,0xF1,0x00,0x89,0x2F,0x3A,0x01,0xB3,0xC2,0x81,0x3F,0x29,0x08,0x10,0xA1,0xA1,\n0x3B,0x5D,0x19,0x28,0x0B,0x38,0x82,0x91,0x19,0xBD,0x3B,0x7A,0x80,0x12,0xB3,0xE0,\n0x0B,0x6A,0x01,0x88,0xA4,0x08,0x0B,0x08,0x59,0x80,0x80,0x1D,0x49,0x89,0x00,0x84,\n0x99,0x1A,0x2B,0x32,0xE3,0xB4,0xA9,0x3A,0x99,0x31,0xE3,0xAA,0x58,0x3B,0x88,0x95,\n0xC0,0x18,0x4A,0x09,0x30,0xF2,0xA3,0x1C,0x1B,0x49,0x00,0xD3,0xB2,0xA0,0x18,0x11,\n0x92,0xD3,0xB2,0x91,0x80,0xE7,0xA1,0x91,0x98,0x19,0x22,0xC2,0xD2,0x18,0x8D,0x3B,\n0x10,0xA5,0x91,0x98,0x02,0x3E,0x80,0x01,0x90,0xAA,0x13,0xF1,0x02,0xD1,0x08,0x19,\n0x49,0xB4,0x91,0xB4,0x99,0x2A,0x0C,0x32,0xC0,0x05,0x88,0x0B,0x80,0x2C,0x81,0x10,\n0x0B,0x51,0xA9,0x19,0x05,0xBF,0x28,0x20,0xE1,0x90,0x80,0x28,0x19,0x08,0x26,0xB1,\n0xA1,0x18,0x88,0x2A,0xF0,0x12,0x8A,0xB3,0x14,0x1B,0xD4,0xD8,0x10,0x08,0x8A,0x17,\n0xA0,0x98,0x2B,0x3A,0x29,0x48,0xA4,0x99,0x0E,0x4A,0x12,0x8B,0x31,0x8B,0x4E,0x1A,\n0x11,0xB5,0x89,0x91,0x29,0x89,0xC2,0x97,0x90,0x0A,0x19,0x11,0x91,0xC1,0xD5,0x08,\n0x89,0x20,0x91,0xB1,0x1A,0x2D,0x18,0x29,0xD2,0x3B,0x3E,0x3A,0x2A,0x90,0x82,0x1C,\n0x49,0x3B,0x93,0xB6,0xC8,0x4C,0x02,0x91,0x93,0xF2,0x88,0x2D,0x28,0x81,0x82,0xC1,\n0x89,0x2D,0x6B,0x19,0x82,0x80,0x18,0x8B,0x39,0x39,0xC8,0x3A,0x6A,0x0A,0x22,0xD2,\n0x09,0x2C,0x1A,0x68,0x92,0xE2,0x89,0x2A,0x2A,0x30,0xC2,0xA3,0xB4,0x1D,0x2A,0x09,\n0x93,0x18,0xF2,0x89,0x28,0xB3,0x01,0x8F,0x18,0x11,0xA1,0x93,0x90,0xD1,0x7A,0x20,\n0xC3,0xA2,0xA8,0x88,0x1D,0x28,0xA5,0xA2,0xA2,0x0B,0x29,0x2B,0x87,0xC1,0x80,0x0A,\n0x19,0x01,0x12,0xF1,0x10,0x80,0x0A,0x18,0x08,0x2F,0x4A,0x02,0x89,0x1B,0x29,0x5D,\n0x4C,0x08,0x82,0xA1,0x0A,0x3A,0x4B,0x29,0xC6,0xC3,0x09,0x09,0x88,0x39,0x98,0x82,\n0xA5,0x1A,0x30,0x11,0xBD,0x3F,0x12,0x8B,0x28,0xC3,0x88,0x3F,0x2B,0x3B,0x48,0xA1,\n0x80,0x8A,0x4D,0x39,0x01,0x93,0xA2,0xF1,0x19,0x19,0x0A,0x02,0xB2,0x8B,0x24,0xD2,\n0x4B,0x12,0xC8,0x2E,0x10,0xB5,0x89,0x01,0x09,0x1C,0x2A,0x03,0xD4,0x91,0x98,0x99,\n0x11,0x2B,0xE4,0x00,0x00,0x01,0xE0,0xA5,0x89,0x99,0x31,0x18,0xD0,0xB7,0x98,0x18,\n0x0A,0x10,0x94,0xC2,0x90,0x18,0x00,0x99,0x87,0xA0,0x90,0x2A,0x3C,0x02,0xB8,0xC1,\n0x79,0x1A,0x20,0x08,0xA1,0xD2,0x1C,0x29,0x03,0xD1,0x29,0x99,0x2C,0x50,0xB3,0xD1,\n0x08,0x09,0x3C,0x10,0x04,0xB2,0x0D,0x2B,0x59,0x80,0x90,0x01,0x0F,0x3A,0x18,0x01,\n0xA2,0x9B,0x5B,0x3D,0x81,0x03,0xD2,0x98,0x59,0x90,0x81,0x92,0xB4,0x8B,0x1B,0x40,\n0xB2,0xB5,0x08,0x4B,0x01,0x09,0xD1,0x91,0x8B,0x7A,0x10,0xB3,0xC3,0x99,0x49,0x1A,\n0x29,0xB5,0xA2,0xAB,0x40,0x81,0x19,0xB7,0xB0,0x20,0x2B,0xD4,0x88,0xA1,0x91,0x3C,\n0x82,0x37,0xD3,0xB1,0x8A,0x1B,0x30,0xB3,0xF4,0xA1,0x91,0x09,0x10,0x03,0xD0,0x83,\n0xA9,0x8F,0x10,0x01,0x90,0x18,0x80,0x20,0x2B,0xF1,0x28,0x99,0x2A,0x41,0xF0,0x12,\n0xAA,0x83,0x82,0xD1,0xC1,0x08,0x89,0x59,0x09,0x83,0x87,0xB0,0x2A,0x4D,0x18,0x09,\n0x19,0xB3,0x4B,0x3F,0x39,0x19,0x09,0x01,0x89,0x03,0x1F,0x00,0x1A,0x0B,0x10,0x68,\n0xA0,0x18,0x8C,0x6A,0x09,0x08,0x97,0xA1,0x81,0x1B,0x2B,0x4C,0x03,0xB4,0xA8,0x92,\n0x4B,0x3C,0xA1,0x81,0x95,0xA8,0x81,0x12,0xBB,0x92,0x45,0xB9,0x93,0xF4,0x88,0x0A,\n0x2D,0x28,0x00,0xA3,0xA3,0x8A,0x3F,0x48,0xB1,0x92,0xB4,0xA8,0x30,0x80,0xD3,0x80,\n0xD1,0x19,0x3B,0xC4,0x81,0xC1,0x29,0x0D,0x20,0x13,0xC8,0xB4,0x4C,0x09,0x00,0x82,\n0xC2,0x3B,0x0D,0x30,0x0B,0x12,0xF0,0x1B,0x20,0x0A,0xA6,0x80,0x0A,0x4A,0x4A,0x80,\n0x94,0xB1,0x2E,0x3B,0x1A,0x10,0x93,0x10,0x4C,0x3D,0x08,0x82,0xC9,0x19,0x6A,0x2B,\n0x38,0xD1,0x08,0x19,0x2A,0x5A,0x82,0xB1,0x8D,0x29,0x78,0x09,0x82,0x0A,0x2C,0x1B,\n0x19,0x41,0xB8,0x8C,0x79,0x2B,0x11,0x88,0x82,0x91,0xDC,0x28,0x11,0xB0,0x11,0x18,\n0xC9,0x62,0xA1,0x91,0x98,0x3B,0x3A,0xB0,0xF4,0x01,0xC0,0x29,0x39,0xF8,0x95,0x91,\n0x88,0x88,0x91,0x03,0xA1,0xE2,0x18,0x82,0xD1,0xA2,0xD1,0x80,0x19,0x20,0x83,0xB1,\n0xE3,0x80,0x91,0x4D,0x1A,0x03,0xB2,0x09,0x18,0xD1,0x19,0x09,0x92,0xA6,0xA0,0xB6,\n0xB2,0x8B,0x38,0x10,0x42,0xD3,0xD0,0xA8,0x20,0x2C,0x10,0x01,0xB1,0xB4,0xAB,0x5B,\n0x79,0x80,0x10,0x1A,0xA8,0x3D,0x18,0x20,0xB3,0x8F,0x18,0x01,0x00,0x09,0xF3,0x89,\n0x69,0x88,0x81,0x91,0x08,0xE1,0x1A,0x08,0x11,0x81,0x1E,0x29,0xA0,0x01,0x00,0x90,\n0x3E,0x7B,0x18,0x82,0xC3,0xA1,0x2A,0x2C,0x5B,0x81,0xA5,0x90,0x81,0x00,0x0B,0x1A,\n0x1C,0x2C,0x32,0xC0,0xF3,0x80,0x2D,0x2A,0x10,0x02,0xE4,0xC1,0x89,0x4A,0x09,0x01,\n0x03,0xD2,0x98,0x2A,0x39,0x8A,0x89,0x26,0xB1,0xB2,0x12,0xC0,0x0A,0x5A,0x18,0x98,\n0xF3,0x92,0x99,0x99,0x79,0x01,0xB5,0xA1,0x80,0x80,0x90,0x83,0xA0,0xE2,0x81,0x29,\n0x93,0x8A,0x0A,0x6A,0x1F,0x18,0x02,0xC8,0x01,0x19,0x3B,0x4A,0x98,0x17,0xA8,0x0D,\n0x38,0xA1,0x91,0x10,0xA2,0x2B,0x4C,0xA6,0x81,0xBA,0x21,0x4C,0x80,0x21,0xD1,0x92,\n0x2C,0x08,0x30,0x9F,0x93,0x2A,0x89,0x03,0x8B,0x87,0x0A,0x0D,0x12,0x98,0xA4,0x93,\n0xBB,0x59,0x18,0xA1,0x32,0xE9,0x84,0x08,0x8A,0x02,0xA1,0x91,0x4B,0xB4,0x20,0x88,\n0xF0,0x3A,0x1A,0x88,0x87,0xB1,0x92,0x0A,0x08,0x6B,0x83,0xC3,0x91,0xC0,0x2B,0x79,\n0x08,0x8A,0x84,0xA0,0x89,0x40,0x1B,0xA1,0x39,0x98,0x17,0xC2,0xA2,0x12,0xCD,0x20,\n0x89,0x92,0x25,0xB0,0x2D,0x3A,0x8B,0x58,0x2A,0xA0,0x4C,0x08,0x30,0xAE,0x82,0x59,\n0x89,0x1A,0x10,0xC2,0x18,0x2C,0x40,0x1E,0x01,0xA3,0x8A,0x81,0x2C,0x29,0x29,0xA9,\n0x13,0x51,0xAD,0x12,0x89,0x8F,0x18,0x2C,0x39,0x00,0xC1,0x10,0x3C,0x2A,0x41,0xC8,\n0xA2,0x91,0x0A,0x6C,0x10,0x12,0x88,0xE8,0x30,0x91,0x81,0xD8,0x01,0x1B,0x0D,0x07,\n0x00,0xA8,0x92,0x0A,0x28,0xD2,0xC3,0x02,0xAA,0x94,0x81,0xB4,0xB3,0x1A,0x0B,0x13,\n0xF9,0x16,0xA1,0x8A,0x59,0x19,0x02,0xC1,0x91,0x8B,0x3D,0x18,0x3B,0xA4,0x94,0x80,\n0x99,0x88,0x1C,0x79,0x0A,0x02,0x03,0xF8,0x90,0x39,0x5B,0x19,0x02,0xC3,0x90,0xBB,\n0x58,0x6A,0x09,0x02,0x89,0x91,0x88,0x1A,0x69,0x8A,0x19,0x15,0xA0,0xA2,0x00,0x9A,\n0x6B,0x49,0x88,0xA3,0x92,0xBB,0x6B,0x3D,0x38,0x01,0x98,0x91,0x3F,0x09,0x18,0x20,\n0x90,0x80,0xAC,0x70,0x91,0x9B,0x51,0x09,0x88,0x99,0x14,0x8B,0x98,0x83,0x79,0xA0,\n0x99,0x13,0x01,0x19,0xE0,0x83,0x0B,0xB0,0x0C,0x31,0x95,0xB5,0xC2,0x8A,0x39,0x20,\n0x80,0x39,0xF3,0xB1,0x10,0x88,0x5E,0x18,0x94,0xA1,0x88,0xA1,0x98,0x15,0xAA,0x39,\n0xD4,0x84,0xC0,0xA2,0xA2,0x0C,0x81,0x86,0xB5,0xA1,0xB1,0x14,0x1B,0xB1,0x02,0x92,\n0xC3,0xE0,0x88,0x11,0xAA,0x69,0x18,0x81,0xA3,0xB0,0x01,0xBF,0x2A,0x31,0x93,0xF1,\n0x00,0x89,0x18,0x19,0x11,0xD3,0xE0,0x10,0x18,0xB1,0x18,0x24,0x9A,0x2B,0xA4,0xC0,\n0xB0,0x31,0x6C,0x19,0xB4,0x12,0xA8,0xEA,0x58,0x10,0x8B,0x93,0x82,0x88,0x9A,0x41,\n0x10,0xC3,0xEA,0x41,0xA9,0x9C,0x34,0xA1,0x2A,0x79,0xA2,0x01,0xA8,0xB3,0x28,0xCC,\n0x41,0x9A,0xB3,0x4B,0xB3,0x27,0x8B,0x83,0x2B,0x2F,0x08,0x28,0xB2,0x80,0x2C,0x30,\n0x5E,0x09,0x12,0x9B,0x09,0x22,0x5B,0x19,0x8A,0x11,0x59,0x99,0xA4,0x32,0xCD,0x18,\n0x08,0x10,0x85,0xB3,0xB4,0x1E,0x88,0x28,0x8A,0x11,0x09,0xC0,0x79,0x80,0x91,0x3B,\n0x80,0x10,0x0F,0x01,0x80,0x91,0x19,0x3D,0x92,0x28,0xA8,0x37,0x9A,0x0A,0x3A,0x8A,\n0x45,0xA9,0xA4,0x00,0xAA,0x09,0x3D,0x59,0x20,0xE1,0x08,0x98,0x90,0x59,0x10,0x09,\n0xA3,0xC3,0x93,0x99,0x2B,0x69,0x11,0xD1,0xB1,0xA4,0x91,0x3C,0x89,0x83,0xF0,0x10,\n0x91,0xA1,0x89,0x59,0x05,0x99,0x93,0x94,0xC8,0x08,0x0A,0x09,0x17,0xB1,0x83,0xC1,\n0x91,0x40,0xA2,0xC2,0x98,0xC3,0xBA,0x28,0x23,0x0F,0x80,0x50,0xB8,0x19,0x10,0x96,\n0x98,0x8C,0x05,0x98,0x19,0x29,0x2B,0x3B,0x0A,0xE2,0x01,0x0F,0x3C,0x38,0x08,0x09,\n0x81,0x4A,0x6C,0x08,0x00,0x88,0x98,0x38,0x2C,0x5A,0x1B,0x20,0x1A,0x39,0xB0,0x09,\n0xCB,0x5B,0x49,0x09,0x71,0x00,0xC1,0x0E,0x08,0x38,0x0C,0x02,0x10,0x0E,0x10,0x8A,\n0x48,0x19,0x90,0x92,0x0D,0xA3,0x98,0x3B,0x79,0x19,0x01,0x10,0xE1,0x80,0x19,0x2B,\n0x10,0xF2,0x02,0xAB,0x84,0x9A,0x29,0xB4,0x80,0x92,0x03,0x88,0x95,0xD0,0x03,0x90,\n0xA0,0xC7,0xA1,0xB0,0xA2,0x02,0x18,0xB5,0xD4,0x01,0xC0,0x08,0xA2,0x93,0xA8,0xA0,\n0xC3,0x20,0xF3,0x90,0x00,0xD5,0x08,0x89,0xA5,0x80,0xA0,0x81,0x82,0xC2,0x09,0xD1,\n0x13,0xCB,0x03,0x84,0x91,0xE1,0x1B,0x12,0x08,0xAB,0x87,0x18,0xAB,0x58,0x89,0x28,\n0x81,0xC9,0x33,0xA9,0x80,0x2E,0x20,0x83,0xB9,0x20,0x3B,0x9E,0x7A,0x08,0x81,0x18,\n0x0B,0x88,0x79,0x80,0x8B,0x00,0x12,0x0E,0x89,0x51,0x1B,0x81,0xA0,0x3A,0x01,0xAF,\n0x11,0x28,0xBA,0x35,0x98,0x88,0x52,0xC0,0x83,0x2F,0xA9,0x11,0x0A,0x19,0x25,0xD0,\n0x30,0x9C,0x08,0x21,0x98,0x81,0x2A,0xF3,0x2A,0x80,0xB6,0x2B,0x08,0x93,0xE9,0x02,\n0x81,0x8C,0x21,0x00,0xA6,0xA9,0x94,0x01,0x8F,0x80,0x94,0x98,0x93,0xB4,0x00,0x08,\n0xC0,0x14,0x98,0xB3,0xB4,0xC1,0x09,0x18,0xA7,0x00,0xA3,0xC8,0x0A,0x3C,0x19,0x96,\n0x83,0xC1,0x99,0x19,0x4A,0x85,0x80,0xC1,0x91,0x99,0x90,0x2A,0x17,0x95,0x99,0x88,\n0x12,0xAE,0x39,0x08,0x92,0x84,0xB0,0xA8,0x79,0x09,0x19,0x01,0xB2,0xA3,0x8F,0x28,\n0x2B,0xA2,0x40,0x82,0xA0,0x4C,0xA9,0x39,0x8D,0x81,0x70,0x88,0xA0,0x1A,0x49,0x2D,\n0x1A,0x26,0xA8,0x98,0x08,0x29,0x0B,0x12,0x96,0xB1,0xB2,0x3A,0x13,0x9B,0x60,0xA0,\n0x88,0xB2,0x34,0xEA,0x1A,0x2A,0x79,0x98,0x10,0x04,0x8C,0x1C,0x81,0x04,0x8C,0x83,\n0x19,0x2F,0x81,0x93,0x98,0x10,0x08,0x30,0x2A,0xFA,0x05,0x08,0x2A,0x89,0x91,0xA3,\n0xFA,0x11,0x11,0x00,0x8C,0x04,0x8A,0x2A,0xB5,0x10,0xA9,0xC2,0x3D,0x1B,0x32,0x04,\n0x0A,0x1A,0x09,0x40,0x1F,0x92,0x1D,0x2A,0x91,0x10,0x30,0x2F,0x0B,0x68,0x99,0xA2,\n0x92,0x88,0x78,0xA9,0x20,0x28,0xE2,0x92,0x1A,0x99,0x4B,0x19,0x22,0xA1,0xE2,0x21,\n0x2F,0x98,0x29,0x18,0x91,0x08,0xB0,0x79,0x1A,0x82,0x3B,0xB1,0xA7,0x8A,0xB3,0x98,\n0x5B,0x23,0xCA,0x42,0x83,0xF0,0x90,0x18,0x98,0x08,0xB4,0x20,0xA3,0xC0,0x43,0xD8,\n0x80,0x81,0xA3,0x99,0xD9,0xA7,0x19,0x90,0x10,0x05,0xB1,0x8B,0x02,0xA4,0xBD,0x23,\n0x93,0x8A,0x99,0x4B,0x03,0xC1,0xF8,0x38,0x09,0x2B,0x14,0xD0,0x03,0x8A,0x2A,0x39,\n0xB9,0x97,0x90,0xAA,0x50,0x01,0x99,0x51,0xD1,0x09,0x1A,0xB5,0x00,0x8B,0x93,0x08,\n0x98,0x11,0xF9,0x85,0x2B,0x08,0x96,0x89,0x90,0x2A,0x12,0x4A,0xD8,0x85,0x2B,0x0E,\n0x10,0x00,0x01,0xB1,0x9B,0x69,0x1A,0x90,0x40,0xB8,0x01,0x08,0x0A,0x2C,0x09,0x14,\n0x4B,0xE2,0x82,0x88,0xB1,0x78,0x0A,0x01,0xC2,0x93,0x19,0xCE,0x20,0x3C,0x82,0xB4,\n0x1B,0x20,0x8C,0x3B,0x29,0xAB,0x86,0x23,0xD8,0x81,0x9A,0x5A,0x49,0xB0,0x16,0xA0,\n0xB0,0x28,0x1B,0x13,0x93,0xE4,0xA2,0xA9,0x08,0x5A,0xB3,0x12,0xC1,0xE1,0x10,0x88,\n0x01,0x0C,0x92,0x08,0x89,0xB7,0x88,0x81,0x10,0x9A,0x17,0xA0,0xB0,0x13,0x99,0xE0,\n0x39,0x31,0xD2,0xB2,0x80,0x0B,0x2D,0x49,0x80,0x01,0xB0,0x06,0x09,0x0C,0x3A,0x69,\n0xA0,0x08,0xB2,0xA1,0x69,0x2B,0x5A,0x81,0x92,0xBA,0x21,0xB1,0x7D,0x10,0x80,0x08,\n0x88,0x82,0x32,0x0D,0xB0,0x1A,0x1C,0x21,0x94,0xA9,0x58,0xB9,0x5A,0x4A,0xA0,0x13,\n0xA9,0x80,0x7C,0x00,0x20,0x8A,0x04,0x0C,0x00,0x82,0x2A,0xB2,0xAC,0x4B,0x69,0xA0,\n0xA6,0x81,0x9B,0x19,0x38,0x8B,0x17,0xB2,0x81,0x2A,0xBB,0x94,0x29,0xA2,0x15,0xBA,\n0x97,0xA3,0xB9,0x79,0x01,0xB2,0x02,0xF1,0x90,0x0A,0x29,0x11,0x88,0xE5,0xA0,0x81,\n0x19,0x91,0x90,0x28,0xB3,0x14,0xD0,0xB5,0x91,0x9A,0x29,0x0B,0x07,0xA2,0xB3,0x01,\n0x9D,0x28,0x41,0xD0,0x91,0x90,0x82,0x1A,0xA8,0x44,0x9A,0xA9,0x21,0xE3,0xA9,0x4B,\n0x19,0x78,0x89,0x83,0xA3,0xB9,0x5A,0x3D,0x80,0x82,0xA2,0xA0,0x6C,0x10,0x20,0x8B,\n0x93,0x8B,0x0E,0x33,0xA9,0xB1,0x68,0x8A,0x31,0xAC,0x94,0xB4,0x8B,0x32,0x0B,0xB4,\n0x81,0x91,0x1D,0x33,0xD9,0x31,0xE1,0x8B,0x3B,0x30,0x12,0x49,0xD2,0x8E,0x29,0x18,\n0x8A,0x92,0x02,0xAA,0x59,0x1C,0x32,0x88,0x01,0x23,0xFB,0x83,0x29,0xDA,0x59,0x01,\n0x81,0x92,0xE1,0x18,0x8A,0x1D,0x30,0x93,0xF1,0x00,0x01,0x0B,0x39,0x92,0x89,0xA0,\n0x11,0x5B,0xE0,0x82,0x09,0x13,0xAA,0xB4,0x16,0xD8,0x91,0x2A,0x29,0x84,0x1B,0xC5,\n0x98,0x98,0x31,0x98,0x99,0x17,0xA9,0x20,0x92,0xC3,0x18,0x9D,0x20,0x3D,0x89,0x94,\n0xA2,0x1C,0x5C,0x29,0x39,0xA0,0xB3,0x00,0x0C,0x4C,0x48,0x92,0x0A,0x91,0x85,0x9A,\n0x01,0x82,0x1F,0x10,0x99,0x15,0xC1,0xA0,0x39,0x1A,0x1D,0x85,0xB4,0x90,0x1A,0x2A,\n0x4B,0x01,0xB2,0x93,0xBE,0x12,0x83,0xC9,0x18,0x09,0x20,0x78,0xF1,0x08,0x19,0x88,\n0x3A,0x83,0xB3,0xA9,0x93,0x7A,0x0A,0x96,0x98,0x00,0xA8,0x3A,0x30,0x92,0xF2,0x9B,\n0x3D,0x38,0x92,0x92,0xC3,0xB8,0x6B,0x29,0x01,0x01,0xB2,0x2F,0x09,0x19,0x18,0x01,\n0x3B,0x7B,0x10,0xA1,0x90,0x39,0x0F,0x38,0x0A,0xB5,0xA4,0x89,0x8B,0x6A,0x2B,0x12,\n0xC8,0x90,0x40,0x2A,0x9E,0x22,0x88,0x18,0x09,0x3A,0xC3,0xE8,0x09,0x59,0x08,0x12,\n0x94,0xD0,0x1A,0x2C,0x38,0x00,0xA1,0x83,0xE8,0x08,0x3A,0x08,0x10,0x9E,0x83,0x1D,\n0x92,0x19,0x2C,0x39,0x3B,0x59,0x04,0xE1,0x80,0x08,0x8D,0x21,0x81,0xB2,0xB2,0x02,\n0x99,0x91,0xA4,0xD6,0x98,0x99,0x03,0x80,0x98,0xA7,0x91,0x09,0xA1,0xB2,0xB3,0xE1,\n0x12,0x92,0xB1,0x81,0x06,0x99,0x0A,0x23,0xC4,0xB1,0xF2,0x89,0x19,0x3A,0x94,0x82,\n0xE0,0x89,0x38,0x0B,0xA4,0xA5,0x80,0x80,0x8C,0x34,0xB9,0xA9,0x23,0x13,0xB9,0xC1,\n0xC7,0x1B,0x89,0x10,0x20,0x11,0xE3,0xA8,0x4B,0x0B,0x40,0x91,0x90,0x1B,0x5F,0x2A,\n0x18,0x82,0x91,0x0B,0x4A,0x28,0xCA,0x40,0x80,0x5B,0x2C,0x13,0xB0,0x8A,0xA9,0x5A,\n0x58,0x89,0x82,0x88,0x2E,0x3B,0x31,0xA1,0x9B,0x01,0x7A,0x2C,0x01,0x91,0x93,0x3F,\n0x88,0x39,0x10,0xF1,0x91,0x8B,0x48,0x0A,0x12,0xE3,0xA8,0x18,0x28,0x92,0x97,0x98,\n0x99,0x19,0xA1,0x11,0xB6,0x88,0x3B,0x10,0xD3,0xC3,0xA1,0x2A,0x8A,0x49,0x04,0xF1,\n0x91,0x02,0x8A,0x89,0x04,0xF1,0x98,0x80,0x18,0x12,0xE3,0x81,0x98,0x80,0x01,0xB3,\n0xF2,0x99,0x12,0x2A,0xB5,0xB3,0x92,0xAA,0x19,0x50,0xB2,0xC3,0x92,0xD0,0x2B,0x68,\n0x93,0x99,0xC0,0x2C,0x3E,0x80,0x20,0x08,0x93,0x0D,0x2A,0x31,0x8D,0x02,0x2B,0x91,\n0x08,0x0A,0x03,0x2C,0x3C,0x52,0xB9,0xA0,0x12,0xBF,0x3A,0x29,0x01,0x88,0xC0,0x6A,\n0x3C,0x0A,0x49,0x18,0x0B,0x39,0x2B,0x69,0x0A,0x84,0x2A,0x2A,0x1C,0x2A,0xC3,0x8C,\n0x19,0x50,0x09,0x91,0xA7,0x8D,0x18,0x1A,0x28,0x00,0xA0,0x94,0x10,0x1F,0x20,0x90,\n0x8A,0x12,0xD0,0x1A,0x5A,0x81,0x04,0xBC,0x23,0x10,0xE0,0x90,0x90,0x18,0x1A,0xA6,\n0x12,0xB1,0xD0,0x4A,0x08,0x82,0x92,0xB6,0x9A,0x0A,0x12,0x88,0xC3,0xC5,0x8A,0x89,\n0x20,0xB5,0x93,0x0B,0x18,0x00,0x09,0xF2,0x88,0x2A,0x4A,0x08,0x05,0xB2,0xA9,0x3B,\n0x5D,0x28,0xA4,0xB1,0x00,0x19,0x19,0x7A,0xA3,0xB3,0x0A,0x90,0xA1,0xC4,0x80,0xBA,\n0x50,0x13,0xC1,0xC2,0x9A,0x2A,0x7B,0x28,0x84,0xC1,0x09,0x3B,0x4E,0x20,0x91,0xA1,\n0x18,0xAB,0x79,0x10,0xB4,0x08,0x9A,0x11,0x2B,0xF0,0x93,0xAA,0x01,0x6A,0x01,0x93,\n0x80,0xB8,0x2A,0x5B,0x10,0x80,0x89,0x4A,0x5B,0x92,0x15,0xB2,0xA0,0x2F,0x19,0x93,\n0xB8,0x95,0x80,0x1C,0x21,0xA9,0x02,0x0B,0xA0,0x5A,0x18,0x98,0x39,0x1B,0x68,0x00,\n0x91,0x91,0x9C,0x39,0x3E,0x18,0x84,0xB3,0x9B,0x7A,0x08,0x18,0x0A,0xB5,0x91,0x0B,\n0x28,0x39,0x19,0x90,0x0A,0x50,0xAC,0x11,0x01,0xAB,0x88,0x52,0x1B,0x83,0xC4,0xA2,\n0x9A,0xAB,0x03,0x90,0x19,0x93,0x81,0x08,0x92,0x9A,0x68,0x98,0x19,0x39,0xC1,0x92,\n0x8A,0x38,0x4E,0x02,0xB1,0x90,0xC3,0x18,0x2B,0x04,0xC3,0xD2,0x91,0x90,0x81,0x89,\n0x13,0xF1,0x88,0x93,0xA2,0x00,0x91,0xC0,0x5B,0x21,0x99,0x93,0x06,0x9A,0x1B,0x48,\n0x99,0xB7,0x90,0x89,0x18,0x1B,0x11,0xA4,0xB2,0x81,0x9A,0x08,0x97,0x98,0x91,0x10,\n0xB8,0x06,0xA2,0xA0,0x29,0x2B,0x21,0xC2,0xD1,0x10,0x1A,0x4A,0x29,0xF1,0x98,0x29,\n0x1B,0x31,0x10,0xA0,0xA1,0x1D,0x5A,0x29,0xB2,0x82,0xA8,0x0F,0x28,0x21,0x09,0x91,\n0x82,0x4D,0x10,0xA3,0xB0,0x89,0x4C,0x39,0xA0,0xA4,0xA1,0x89,0x1E,0x28,0x29,0xA3,\n0xC3,0x2D,0x19,0x01,0x49,0x01,0x9B,0x0C,0x21,0xC2,0xA2,0x93,0x7C,0x2A,0x10,0x90,\n\n/* Source: 08HH.ROM */\n/* Length: 384 / 0x00000180 */\n\n0x75,0xF2,0xAB,0x7D,0x7E,0x5C,0x3B,0x4B,0x3C,0x4D,0x4A,0x02,0xB3,0xC5,0xE7,0xE3,\n0x92,0xB3,0xC4,0xB3,0xC3,0x8A,0x3B,0x5D,0x5C,0x3A,0x84,0xC2,0x91,0xA4,0xE7,0xF7,\n0xF7,0xF4,0xA1,0x1B,0x49,0xA5,0xB1,0x1E,0x7F,0x5A,0x00,0x89,0x39,0xB7,0xA8,0x3D,\n0x4A,0x84,0xE7,0xF7,0xE2,0x2D,0x4C,0x3A,0x4E,0x7D,0x04,0xB0,0x2D,0x4B,0x10,0x80,\n0xA3,0x99,0x10,0x0E,0x59,0x93,0xC4,0xB1,0x81,0xC4,0xA2,0xB2,0x88,0x08,0x3F,0x3B,\n0x28,0xA6,0xC3,0xA2,0xA2,0xC5,0xC1,0x3F,0x7E,0x39,0x81,0x93,0xC2,0xA3,0xE5,0xD2,\n0x80,0x93,0xB8,0x6D,0x49,0x82,0xD4,0xA1,0x90,0x01,0xA0,0x09,0x04,0xE3,0xB2,0x91,\n0xB7,0xB3,0xA8,0x2A,0x03,0xF3,0xA1,0x92,0xC5,0xC3,0xB2,0x0B,0x30,0xB3,0x8E,0x6D,\n0x4A,0x01,0xB4,0xB4,0xC4,0xC3,0x99,0x3B,0x12,0xE3,0xA1,0x88,0x82,0xB4,0x9A,0x5C,\n0x3A,0x18,0x93,0xC3,0xB3,0xB4,0xA8,0x19,0x04,0xF3,0xA8,0x3B,0x10,0xA2,0x88,0xA5,\n0xB2,0x0B,0x6D,0x4B,0x10,0x91,0x89,0x3C,0x18,0x18,0xA6,0xC4,0xC3,0x98,0x19,0x2B,\n0x20,0x91,0xA0,0x4E,0x28,0x93,0xB3,0xC2,0x92,0xA9,0x5A,0x96,0xC4,0xC2,0x09,0x01,\n0xC4,0xA1,0x92,0xC4,0xA1,0x89,0x10,0xA3,0xA1,0x90,0x1C,0x5A,0x01,0xC5,0xA1,0x92,\n0xD4,0xB3,0xC4,0xC4,0xC3,0xA1,0x88,0x1A,0x28,0x89,0x3C,0x3A,0x3D,0x29,0x00,0x93,\n0xB0,0x3D,0x28,0x80,0x91,0x82,0xE3,0x99,0x2A,0x11,0xD6,0xC3,0x99,0x29,0x82,0xC4,\n0xC3,0xA1,0x0A,0x3B,0x3D,0x3A,0x02,0xC3,0xA2,0x99,0x3B,0x2C,0x7C,0x28,0x81,0xA3,\n0xB2,0xA3,0xB1,0x08,0x1A,0x3C,0x18,0x2E,0x4C,0x39,0xA5,0xB3,0xB4,0xC2,0x88,0x08,\n0x19,0x0A,0x49,0xB7,0xB3,0xA2,0xA1,0x92,0xA1,0x93,0xB1,0x0C,0x7D,0x39,0x93,0xB3,\n0xB1,0x1A,0x19,0x5D,0x28,0xA6,0xC4,0xB2,0x90,0x09,0x2A,0x18,0x1B,0x5B,0x28,0x88,\n0x2C,0x29,0x82,0xA0,0x18,0x91,0x2D,0x29,0x2B,0x5C,0x4C,0x3B,0x4C,0x28,0x80,0x92,\n0x90,0x09,0x2B,0x28,0x1D,0x6B,0x11,0xC5,0xB2,0x0B,0x39,0x09,0x4D,0x28,0x88,0x00,\n0x1B,0x28,0x94,0xE3,0xA0,0x1A,0x28,0xB5,0xB4,0xB3,0xB2,0x93,0xE2,0x91,0x92,0xD4,\n0xA0,0x1B,0x4A,0x01,0xA1,0x88,0x2D,0x5C,0x3B,0x28,0x08,0x93,0xD4,0xB2,0x91,0xB4,\n0xA0,0x3E,0x3B,0x4B,0x3B,0x29,0x08,0x93,0x9B,0x7B,0x3A,0x19,0x00,0x80,0x80,0xA0,\n\n/* Source: 10TOM.ROM */\n/* Length: 640 / 0x00000280 */\n\n0x77,0x27,0x87,0x01,0x2D,0x4F,0xC3,0xC1,0x92,0x91,0x89,0x59,0x83,0x1A,0x32,0xC2,\n0x95,0xB1,0x81,0x88,0x81,0x4A,0x3D,0x11,0x9E,0x0B,0x88,0x0C,0x18,0x3B,0x11,0x11,\n0x91,0x00,0xA0,0xE2,0x0A,0x48,0x13,0x24,0x81,0x48,0x1B,0x39,0x1C,0x83,0x84,0xA1,\n0xD1,0x8E,0x8A,0x0B,0xC0,0x98,0x92,0xB8,0x39,0x90,0x10,0x92,0xF0,0xB5,0x88,0x32,\n0x49,0x51,0x21,0x03,0x82,0x10,0x8A,0x7A,0x09,0x00,0xA2,0xCA,0x1B,0xCC,0x1C,0xB9,\n0x8E,0x89,0x89,0xA1,0x89,0x92,0x29,0x11,0x60,0x40,0x14,0x22,0x32,0x78,0x40,0x01,\n0x02,0x90,0x81,0xAB,0x0B,0x00,0xAF,0x99,0xCC,0xAB,0xDA,0xA9,0x99,0x1B,0x30,0x14,\n0x92,0x22,0x19,0x68,0x32,0x14,0x26,0x13,0x23,0x23,0x20,0x12,0x9A,0xA8,0xB9,0xFA,\n0xAA,0xCA,0xCC,0x0C,0xA8,0xAE,0x88,0xB9,0x88,0xA0,0x02,0x21,0x50,0x43,0x03,0x81,\n0x2A,0x11,0x34,0x63,0x24,0x33,0x22,0x38,0x8B,0xEA,0xAE,0x99,0xA0,0x90,0x82,0x00,\n0x89,0xBF,0x8A,0xE8,0xA9,0x90,0x01,0x12,0x13,0x12,0x08,0xA9,0xAA,0xC9,0x22,0x63,\n0x63,0x12,0x44,0x00,0x10,0x88,0x9C,0x98,0xA1,0x85,0x03,0x32,0x36,0x80,0x89,0xDB,\n0xDB,0xBB,0xB9,0xBA,0x01,0x81,0x28,0x19,0xCB,0xFA,0xBC,0x09,0x13,0x37,0x34,0x34,\n0x23,0x31,0x20,0x10,0x00,0x00,0x28,0x38,0x10,0x88,0xEC,0x8D,0xCB,0xBC,0xCC,0xBB,\n0xBB,0xC9,0x99,0x00,0x00,0x33,0x11,0x22,0x81,0x07,0x41,0x54,0x34,0x34,0x22,0x31,\n0x00,0x88,0x9A,0x9B,0x98,0xAB,0x8E,0x9B,0xBD,0x9C,0xBC,0xBB,0xDA,0xAA,0xA9,0x99,\n0x18,0x38,0x60,0x20,0x31,0x13,0x13,0x51,0x14,0x31,0x53,0x33,0x35,0x22,0x01,0x8A,\n0x9C,0xA9,0xCA,0xC9,0xA8,0x00,0x10,0x81,0x9C,0x9E,0xAB,0xCC,0xAB,0xBA,0x98,0x30,\n0x52,0x03,0x81,0x08,0x9C,0xAC,0xAC,0x18,0x11,0x03,0x51,0x61,0x41,0x31,0x31,0x02,\n0x01,0x20,0x24,0x43,0x44,0x40,0x30,0x10,0xBC,0xBE,0xCB,0xDB,0xAB,0xBA,0x99,0x98,\n0x99,0xAA,0xBD,0xAA,0xC8,0x90,0x11,0x53,0x37,0x23,0x43,0x34,0x33,0x33,0x33,0x11,\n0x28,0x00,0x19,0xA9,0x9A,0xCB,0xCE,0xBB,0xEB,0xBC,0xBB,0xCA,0xBA,0xA8,0x88,0x11,\n0x12,0x21,0x20,0x22,0x26,0x26,0x23,0x23,0x43,0x24,0x22,0x32,0x20,0x31,0x81,0x9A,\n0xBC,0xBC,0xCB,0xBD,0x9A,0xA9,0x90,0x98,0xBA,0xCC,0xCB,0xBC,0x8B,0x88,0x22,0x35,\n0x23,0x12,0x99,0x8B,0xAA,0xAA,0x89,0x82,0x93,0x31,0x42,0x23,0x23,0x21,0x32,0x11,\n0x20,0x13,0x13,0x24,0x24,0x24,0x22,0x11,0x8A,0x9E,0xAC,0xAC,0xAA,0xBA,0xAA,0xAB,\n0xBD,0xBC,0xCB,0xCB,0xA9,0xA8,0x91,0x12,0x44,0x43,0x44,0x34,0x34,0x42,0x33,0x42,\n0x21,0x11,0x11,0x88,0x80,0xAA,0x0B,0xAC,0xCB,0xEC,0xAC,0xBA,0xCA,0xAB,0x9A,0x99,\n0x80,0x91,0x09,0x08,0x10,0x22,0x44,0x43,0x44,0x33,0x43,0x22,0x13,0x21,0x22,0x20,\n0x09,0x88,0xB9,0xC8,0xBB,0xAB,0xAB,0xA9,0xA9,0x9B,0x9B,0x99,0x90,0x90,0x00,0x81,\n0x00,0x08,0x09,0x8A,0x9A,0xAA,0xA9,0xA9,0x99,0x90,0x80,0x01,0x80,0x00,0x09,0x31,\n0x32,0x44,0x33,0x43,0x34,0x33,0x24,0x22,0x23,0x12,0x10,0x09,0x9B,0xAB,0xCA,0xCC,\n0xBB,0xCB,0xDA,0xCA,0xAB,0xCA,0xAB,0xA9,0xA8,0x92,0x12,0x43,0x53,0x35,0x23,0x33,\n0x43,0x43,0x52,0x22,0x22,0x21,0x01,0x09,0x89,0xA9,0xBB,0xBD,0xBC,0xCB,0xDA,0xAB,\n0xAB,0xAB,0xAA,0xA9,0x99,0xA8,0x09,0x01,0x11,0x34,0x25,0x23,0x33,0x51,0x22,0x31,\n0x12,0x20,0x21,0x12,0x10,0x80,0x99,0x9A,0x99,0x99,0x88,0x08,0x00,0x88,0xA9,0x99,\n0x99,0x80,0x80,0x10,0x01,0x00,0x9A,0xAA,0xBB,0xBA,0xBA,0xA9,0x99,0x99,0x89,0x99,\n0x99,0x00,0x01,0x33,0x35,0x24,0x23,0x34,0x23,0x33,0x34,0x33,0x43,0x32,0x21,0x88,\n0xAB,0xBD,0xBB,0xDB,0xAB,0xBA,0xBB,0xDA,0xBB,0xCB,0xBB,0xBC,0xA8,0x90,0x01,0x12,\n0x23,0x43,0x53,0x34,0x34,0x39,0x80,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,\n\n/* Source: 20RIM.ROM */\n/* Length: 128 / 0x00000080 */\n\n0x0F,0xFF,0x73,0x8E,0x71,0xCD,0x00,0x49,0x10,0x90,0x21,0x49,0xA0,0xDB,0x02,0x3A,\n0xE3,0x0A,0x50,0x98,0xC0,0x59,0xA2,0x99,0x09,0x22,0xA2,0x80,0x10,0xA8,0x5B,0xD2,\n0x88,0x21,0x09,0x96,0xA8,0x10,0x0A,0xE0,0x08,0x48,0x19,0xAB,0x52,0xA8,0x92,0x0C,\n0x03,0x19,0xE2,0x0A,0x12,0xC2,0x81,0x1E,0x01,0xD0,0x48,0x88,0x98,0x01,0x49,0x91,\n0xAA,0x2C,0x25,0x89,0x88,0xB5,0x81,0xA2,0x9A,0x12,0x9E,0x38,0x3B,0x81,0x9B,0x59,\n0x01,0x93,0xCA,0x4A,0x21,0xA0,0x3D,0x0A,0x39,0x3D,0x12,0xA8,0x3F,0x18,0x01,0x92,\n0x1C,0x00,0xB2,0x48,0xB9,0x94,0xA3,0x19,0x4F,0x19,0xB2,0x32,0x90,0xBA,0x01,0xE6,\n0x91,0x80,0xC1,0xA4,0x2A,0x08,0xA1,0xB1,0x25,0xD2,0x88,0x99,0x21,0x80,0x88,0x80,\n};\n\n\n\n/* flag enable control 0x110 */\nINLINE void YM2608IRQFlagWrite(FM_OPN *OPN, YM2608 *F2608, int v)\n{\n\tif( v & 0x80 )\n\t{\t/* Reset IRQ flag */\n\t\tFM_STATUS_RESET(&OPN->ST, 0xf7); /* don't touch BUFRDY flag otherwise we'd have to call ymdeltat module to set the flag back */\n\t}\n\telse\n\t{\t/* Set status flag mask */\n\t\tF2608->flagmask = (~(v&0x1f));\n\t\tFM_IRQMASK_SET(&OPN->ST, (F2608->irqmask & F2608->flagmask) );\n\t}\n}\n\n/* compatible mode & IRQ enable control 0x29 */\nINLINE void YM2608IRQMaskWrite(FM_OPN *OPN, YM2608 *F2608, int v)\n{\n\t/* SCH,xx,xxx,EN_ZERO,EN_BRDY,EN_EOS,EN_TB,EN_TA */\n\n\t/* extend 3ch. enable/disable */\n\tif(v&0x80)\n\t\tOPN->type |= TYPE_6CH;\t/* OPNA mode - 6 FM channels */\n\telse\n\t\tOPN->type &= ~TYPE_6CH;\t/* OPN mode - 3 FM channels */\n\n\t/* IRQ MASK store and set */\n\tF2608->irqmask = v&0x1f;\n\tFM_IRQMASK_SET(&OPN->ST, (F2608->irqmask & F2608->flagmask) );\n}\n\n/* Generate samples for one of the YM2608s */\nvoid ym2608_update_one(void *chip, FMSAMPLE **buffer, int length)\n{\n\tYM2608 *F2608 = (YM2608 *)chip;\n\tFM_OPN *OPN   = &F2608->OPN;\n\tYM_DELTAT *DELTAT = &F2608->deltaT;\n\tint i,j;\n\tFMSAMPLE  *bufL,*bufR;\n\tFM_CH\t*cch[6];\n\tINT32 *out_fm = OPN->out_fm;\n\n\t/* set bufer */\n\tbufL = buffer[0];\n\tbufR = buffer[1];\n\n\tcch[0]   = &F2608->CH[0];\n\tcch[1]   = &F2608->CH[1];\n\tcch[2]   = &F2608->CH[2];\n\tcch[3]   = &F2608->CH[3];\n\tcch[4]   = &F2608->CH[4];\n\tcch[5]   = &F2608->CH[5];\n\n\t/* refresh PG and EG */\n\trefresh_fc_eg_chan( OPN, cch[0] );\n\trefresh_fc_eg_chan( OPN, cch[1] );\n\tif( (OPN->ST.mode & 0xc0) )\n\t{\n\t\t/* 3SLOT MODE */\n\t\tif( cch[2]->SLOT[SLOT1].Incr==-1)\n\t\t{\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );\n\t\t}\n\t}\n\telse\n\t\trefresh_fc_eg_chan( OPN, cch[2] );\n\trefresh_fc_eg_chan( OPN, cch[3] );\n\trefresh_fc_eg_chan( OPN, cch[4] );\n\trefresh_fc_eg_chan( OPN, cch[5] );\n\n\n\t/* buffering */\n\tfor(i=0; i < length ; i++)\n\t{\n\n\t\tadvance_lfo(OPN);\n\n\t\t/* clear output acc. */\n\t\tOPN->out_adpcm[OUTD_LEFT] = OPN->out_adpcm[OUTD_RIGHT] = OPN->out_adpcm[OUTD_CENTER] = 0;\n\t\tOPN->out_delta[OUTD_LEFT] = OPN->out_delta[OUTD_RIGHT] = OPN->out_delta[OUTD_CENTER] = 0;\n\t\t/* clear outputs */\n\t\tout_fm[0] = 0;\n\t\tout_fm[1] = 0;\n\t\tout_fm[2] = 0;\n\t\tout_fm[3] = 0;\n\t\tout_fm[4] = 0;\n\t\tout_fm[5] = 0;\n\n\t\t/* calculate FM */\n\t\tchan_calc(OPN, cch[0], 0 );\n\t\tchan_calc(OPN, cch[1], 1 );\n\t\tchan_calc(OPN, cch[2], 2 );\n\t\tchan_calc(OPN, cch[3], 3 );\n\t\tchan_calc(OPN, cch[4], 4 );\n\t\tchan_calc(OPN, cch[5], 5 );\n\n\t\t/* deltaT ADPCM */\n\t\tif( DELTAT->portstate&0x80 && ! F2608->MuteDeltaT )\n\t\t\tYM_DELTAT_ADPCM_CALC(DELTAT);\n\n\t\t/* ADPCMA */\n\t\tfor( j = 0; j < 6; j++ )\n\t\t{\n\t\t\tif( F2608->adpcm[j].flag )\n\t\t\t\tADPCMA_calc_chan( F2608, &F2608->adpcm[j]);\n\t\t}\n\n\t\t/* advance envelope generator */\n\t\tOPN->eg_timer += OPN->eg_timer_add;\n\t\twhile (OPN->eg_timer >= OPN->eg_timer_overflow)\n\t\t{\n\t\t\tOPN->eg_timer -= OPN->eg_timer_overflow;\n\t\t\tOPN->eg_cnt++;\n\n\t\t\tadvance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[3]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[4]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[5]->SLOT[SLOT1]);\n\t\t}\n\n\t\t/* buffering */\n\t\t{\n\t\t\tint lt,rt;\n\n\t\t\t/*lt =  OPN->out_adpcm[OUTD_LEFT]  + OPN->out_adpcm[OUTD_CENTER];\n\t\t\trt =  OPN->out_adpcm[OUTD_RIGHT] + OPN->out_adpcm[OUTD_CENTER];\n\t\t\tlt += (OPN->out_delta[OUTD_LEFT]  + OPN->out_delta[OUTD_CENTER])>>9;\n\t\t\trt += (OPN->out_delta[OUTD_RIGHT] + OPN->out_delta[OUTD_CENTER])>>9;\n\t\t\tlt += ((out_fm[0]>>1) & OPN->pan[0]);\t// shift right verified on real YM2608\n\t\t\trt += ((out_fm[0]>>1) & OPN->pan[1]);\n\t\t\tlt += ((out_fm[1]>>1) & OPN->pan[2]);\n\t\t\trt += ((out_fm[1]>>1) & OPN->pan[3]);\n\t\t\tlt += ((out_fm[2]>>1) & OPN->pan[4]);\n\t\t\trt += ((out_fm[2]>>1) & OPN->pan[5]);\n\t\t\tlt += ((out_fm[3]>>1) & OPN->pan[6]);\n\t\t\trt += ((out_fm[3]>>1) & OPN->pan[7]);\n\t\t\tlt += ((out_fm[4]>>1) & OPN->pan[8]);\n\t\t\trt += ((out_fm[4]>>1) & OPN->pan[9]);\n\t\t\tlt += ((out_fm[5]>>1) & OPN->pan[10]);\n\t\t\trt += ((out_fm[5]>>1) & OPN->pan[11]);*/\n\t\t\t// this way it's louder (and more accurate)\n\t\t\tlt =  (OPN->out_adpcm[OUTD_LEFT]  + OPN->out_adpcm[OUTD_CENTER]) << 1;\n\t\t\trt =  (OPN->out_adpcm[OUTD_RIGHT] + OPN->out_adpcm[OUTD_CENTER]) << 1;\n\t\t\tlt += (OPN->out_delta[OUTD_LEFT]  + OPN->out_delta[OUTD_CENTER])>>8;\n\t\t\trt += (OPN->out_delta[OUTD_RIGHT] + OPN->out_delta[OUTD_CENTER])>>8;\n\t\t\tlt += (out_fm[0] & OPN->pan[0]);\n\t\t\trt += (out_fm[0] & OPN->pan[1]);\n\t\t\tlt += (out_fm[1] & OPN->pan[2]);\n\t\t\trt += (out_fm[1] & OPN->pan[3]);\n\t\t\tlt += (out_fm[2] & OPN->pan[4]);\n\t\t\trt += (out_fm[2] & OPN->pan[5]);\n\t\t\tlt += (out_fm[3] & OPN->pan[6]);\n\t\t\trt += (out_fm[3] & OPN->pan[7]);\n\t\t\tlt += (out_fm[4] & OPN->pan[8]);\n\t\t\trt += (out_fm[4] & OPN->pan[9]);\n\t\t\tlt += (out_fm[5] & OPN->pan[10]);\n\t\t\trt += (out_fm[5] & OPN->pan[11]);\n\n\t\t\tlt >>= FINAL_SH;\n\t\t\trt >>= FINAL_SH;\n\n\t\t\t//Limit( lt, MAXOUT, MINOUT );\n\t\t\t//Limit( rt, MAXOUT, MINOUT );\n\t\t\t/* buffering */\n\t\t\tbufL[i] = lt;\n\t\t\tbufR[i] = rt;\n\n\t\t\t#ifdef SAVE_SAMPLE\n\t\t\t\tSAVE_ALL_CHANNELS\n\t\t\t#endif\n\n\t\t}\n\n\t\t/* timer A control */\n\t\tINTERNAL_TIMER_A( &OPN->ST , cch[2] )\n\t}\n\tINTERNAL_TIMER_B(&OPN->ST,length)\n\n\n\t/* check IRQ for DELTA-T EOS */\n\tFM_STATUS_SET(&OPN->ST, 0);\n\n}\n\n#ifdef __STATE_H__\nvoid ym2608_postload(void *chip)\n{\n\tif (chip)\n\t{\n\t\tYM2608 *F2608 = (YM2608 *)chip;\n\t\tint r;\n\n\t\t/* prescaler */\n\t\tOPNPrescaler_w(&F2608->OPN,1,2);\n\t\tF2608->deltaT.freqbase = F2608->OPN.ST.freqbase;\n\t\t/* IRQ mask / mode */\n\t\tYM2608IRQMaskWrite(&F2608->OPN, F2608, F2608->REGS[0x29]);\n\t\t/* SSG registers */\n\t\tfor(r=0;r<16;r++)\n\t\t{\n\t\t\t(*F2608->OPN.ST.SSG->write)(F2608->OPN.ST.param,0,r);\n\t\t\t(*F2608->OPN.ST.SSG->write)(F2608->OPN.ST.param,1,F2608->REGS[r]);\n\t\t}\n\n\t\t/* OPN registers */\n\t\t/* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */\n\t\tfor(r=0x30;r<0x9e;r++)\n\t\t\tif((r&3) != 3)\n\t\t\t{\n\t\t\t\tOPNWriteReg(&F2608->OPN,r,F2608->REGS[r]);\n\t\t\t\tOPNWriteReg(&F2608->OPN,r|0x100,F2608->REGS[r|0x100]);\n\t\t\t}\n\t\t/* FB / CONNECT , L / R / AMS / PMS */\n\t\tfor(r=0xb0;r<0xb6;r++)\n\t\t\tif((r&3) != 3)\n\t\t\t{\n\t\t\t\tOPNWriteReg(&F2608->OPN,r,F2608->REGS[r]);\n\t\t\t\tOPNWriteReg(&F2608->OPN,r|0x100,F2608->REGS[r|0x100]);\n\t\t\t}\n\t\t/* FM channels */\n\t\t/*FM_channel_postload(F2608->CH,6);*/\n\t\t/* rhythm(ADPCMA) */\n\t\tFM_ADPCMAWrite(F2608,1,F2608->REGS[0x111]);\n\t\tfor( r=0x08 ; r<0x0c ; r++)\n\t\t\tFM_ADPCMAWrite(F2608,r,F2608->REGS[r+0x110]);\n\t\t/* Delta-T ADPCM unit */\n\t\tYM_DELTAT_postload(&F2608->deltaT , &F2608->REGS[0x100] );\n\t}\n}\n\nstatic void YM2608_save_state(YM2608 *F2608, const device_config *device)\n{\n\tstate_save_register_device_item_array(device, 0, F2608->REGS);\n\tFMsave_state_st(device,&F2608->OPN.ST);\n\tFMsave_state_channel(device,F2608->CH,6);\n\t/* 3slots */\n\tstate_save_register_device_item_array(device, 0, F2608->OPN.SL3.fc);\n\tstate_save_register_device_item(device, 0, F2608->OPN.SL3.fn_h);\n\tstate_save_register_device_item_array(device, 0, F2608->OPN.SL3.kcode);\n\t/* address register1 */\n\tstate_save_register_device_item(device, 0, F2608->addr_A1);\n\t/* rythm(ADPCMA) */\n\tFMsave_state_adpcma(device,F2608->adpcm);\n\t/* Delta-T ADPCM unit */\n\tYM_DELTAT_savestate(device,&F2608->deltaT);\n}\n#endif /* _STATE_H */\n\nstatic void YM2608_deltat_status_set(void *chip, UINT8 changebits)\n{\n\tYM2608 *F2608 = (YM2608 *)chip;\n\tFM_STATUS_SET(&(F2608->OPN.ST), changebits);\n}\nstatic void YM2608_deltat_status_reset(void *chip, UINT8 changebits)\n{\n\tYM2608 *F2608 = (YM2608 *)chip;\n\tFM_STATUS_RESET(&(F2608->OPN.ST), changebits);\n}\n/* YM2608(OPNA) */\n//void * ym2608_init(void *param, const device_config *device, int clock, int rate,\n//               void *pcmrom,int pcmsize,\n//               FM_TIMERHANDLER timer_handler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg)\nvoid * ym2608_init(void *param, int clock, int rate,\n               FM_TIMERHANDLER timer_handler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg)\n{\n\tYM2608 *F2608;\n\n\t/* allocate extend state space */\n\tif( (F2608 = (YM2608 *)malloc(sizeof(YM2608)))==NULL)\n\t\treturn NULL;\n\t/* clear */\n\tmemset(F2608,0,sizeof(YM2608));\n\t/* allocate total level table (128kb space) */\n\tif( !init_tables() )\n\t{\n\t\tfree( F2608 );\n\t\treturn NULL;\n\t}\n\n\tF2608->OPN.ST.param = param;\n\tF2608->OPN.type = TYPE_YM2608;\n\tF2608->OPN.P_CH = F2608->CH;\n\t//F2608->OPN.ST.device = device;\n\tF2608->OPN.ST.clock = clock;\n\tF2608->OPN.ST.rate = rate;\n\n\t/* External handlers */\n\tF2608->OPN.ST.timer_handler = timer_handler;\n\tF2608->OPN.ST.IRQ_Handler   = IRQHandler;\n\tF2608->OPN.ST.SSG           = ssg;\n\n\t/* DELTA-T */\n\t//F2608->deltaT.memory = (UINT8 *)pcmrom;\n\t//F2608->deltaT.memory_size = pcmsize;\n\tF2608->deltaT.memory = NULL;\n\tF2608->deltaT.memory_size = 0x00;\n\tF2608->deltaT.memory_mask = 0x00;\n\n\t/*F2608->deltaT.write_time = 20.0 / clock;*/\t/* a single byte write takes 20 cycles of main clock */\n\t/*F2608->deltaT.read_time  = 18.0 / clock;*/\t/* a single byte read takes 18 cycles of main clock */\n\n\tF2608->deltaT.status_set_handler = YM2608_deltat_status_set;\n\tF2608->deltaT.status_reset_handler = YM2608_deltat_status_reset;\n\tF2608->deltaT.status_change_which_chip = F2608;\n\tF2608->deltaT.status_change_EOS_bit = 0x04;\t/* status flag: set bit2 on End Of Sample */\n\tF2608->deltaT.status_change_BRDY_bit = 0x08;\t/* status flag: set bit3 on BRDY */\n\tF2608->deltaT.status_change_ZERO_bit = 0x10;\t/* status flag: set bit4 if silence continues for more than 290 miliseconds while recording the ADPCM */\n\n\t/* ADPCM Rhythm */\n\tF2608->pcmbuf   = (UINT8*)YM2608_ADPCM_ROM;\n\tF2608->pcm_size = 0x2000;\n\n\tInit_ADPCMATable();\n\n#ifdef __STATE_H__\n\tYM2608_save_state(F2608, device);\n#endif\n\treturn F2608;\n}\n\n/* shut down emulator */\nvoid ym2608_shutdown(void *chip)\n{\n\tYM2608 *F2608 = (YM2608 *)chip;\n\n\tfree(F2608->deltaT.memory);\tF2608->deltaT.memory = NULL;\n\n\tFMCloseTable();\n\tfree(F2608);\n}\n\n/* reset one of chips */\nvoid ym2608_reset_chip(void *chip)\n{\n\tint i;\n\tYM2608 *F2608 = (YM2608 *)chip;\n\tFM_OPN *OPN   = &F2608->OPN;\n\tYM_DELTAT *DELTAT = &F2608->deltaT;\n\n\t/* Reset Prescaler */\n\tOPNPrescaler_w(OPN , 0 , 2);\n\tF2608->deltaT.freqbase = OPN->ST.freqbase;\n\t/* reset SSG section */\n\t(*OPN->ST.SSG->reset)(OPN->ST.param);\n\n\t/* status clear */\n\tFM_BUSY_CLEAR(&OPN->ST);\n\n\t/* register 0x29 - default value after reset is:\n        enable only 3 FM channels and enable all the status flags */\n\tYM2608IRQMaskWrite(OPN, F2608, 0x1f );\t/* default value for D4-D0 is 1 */\n\n\t/* register 0x10, A1=1 - default value is 1 for D4, D3, D2, 0 for the rest */\n\tYM2608IRQFlagWrite(OPN, F2608, 0x1c );\t/* default: enable timer A and B, disable EOS, BRDY and ZERO */\n\n\tOPNWriteMode(OPN,0x27,0x30);\t/* mode 0 , timer reset */\n\n\tOPN->eg_timer = 0;\n\tOPN->eg_cnt   = 0;\n\n\tFM_STATUS_RESET(&OPN->ST, 0xff);\n\n\treset_channels( &OPN->ST , F2608->CH , 6 );\n\t/* reset OPerator paramater */\n\tfor(i = 0xb6 ; i >= 0xb4 ; i-- )\n\t{\n\t\tOPNWriteReg(OPN,i      ,0xc0);\n\t\tOPNWriteReg(OPN,i|0x100,0xc0);\n\t}\n\tfor(i = 0xb2 ; i >= 0x30 ; i-- )\n\t{\n\t\tOPNWriteReg(OPN,i      ,0);\n\t\tOPNWriteReg(OPN,i|0x100,0);\n\t}\n\tfor(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);\n\n\t/* ADPCM - percussion sounds */\n\tfor( i = 0; i < 6; i++ )\n\t{\n\t\tif (i<=3)\t/* channels 0,1,2,3 */\n\t\t\tF2608->adpcm[i].step      = (UINT32)((float)(1<<ADPCM_SHIFT)*((float)F2608->OPN.ST.freqbase)/3.0);\n\t\telse\t\t/* channels 4 and 5 work with slower clock */\n\t\t\tF2608->adpcm[i].step      = (UINT32)((float)(1<<ADPCM_SHIFT)*((float)F2608->OPN.ST.freqbase)/6.0);\n\n\t\tF2608->adpcm[i].start     = YM2608_ADPCM_ROM_addr[i*2];\n\t\tF2608->adpcm[i].end       = YM2608_ADPCM_ROM_addr[i*2+1];\n\n\t\tF2608->adpcm[i].now_addr  = 0;\n\t\tF2608->adpcm[i].now_step  = 0;\n\t\t/* F2608->adpcm[i].delta     = 21866; */\n\t\tF2608->adpcm[i].vol_mul   = 0;\n\t\tF2608->adpcm[i].pan       = &OPN->out_adpcm[OUTD_CENTER]; /* default center */\n\t\tF2608->adpcm[i].flagMask  = 0;\n\t\tF2608->adpcm[i].flag      = 0;\n\t\tF2608->adpcm[i].adpcm_acc = 0;\n\t\tF2608->adpcm[i].adpcm_step= 0;\n\t\tF2608->adpcm[i].adpcm_out = 0;\n\t}\n\tF2608->adpcmTL = 0x3f;\n\n\tF2608->adpcm_arrivedEndAddress = 0; /* not used */\n\n\t/* DELTA-T unit */\n\tDELTAT->freqbase = OPN->ST.freqbase;\n\tDELTAT->output_pointer = OPN->out_delta;\n\tDELTAT->portshift = 5;\t\t/* always 5bits shift */ /* ASG */\n\tDELTAT->output_range = 1<<23;\n\tYM_DELTAT_ADPCM_Reset(DELTAT,OUTD_CENTER,YM_DELTAT_EMULATION_MODE_NORMAL);\n}\n\n/* YM2608 write */\n/* n = number  */\n/* a = address */\n/* v = value   */\nint ym2608_write(void *chip, int a,UINT8 v)\n{\n\tYM2608 *F2608 = (YM2608 *)chip;\n\tFM_OPN *OPN   = &F2608->OPN;\n\tint addr;\n\n\tv &= 0xff;\t/*adjust to 8 bit bus */\n\n\n\tswitch(a&3)\n\t{\n\tcase 0:\t/* address port 0 */\n\t\tOPN->ST.address = v;\n\t\tF2608->addr_A1 = 0;\n\n\t\t/* Write register to SSG emulator */\n\t\tif( v < 16 ) (*OPN->ST.SSG->write)(OPN->ST.param,0,v);\n\t\t/* prescaler selecter : 2d,2e,2f  */\n\t\tif( v >= 0x2d && v <= 0x2f )\n\t\t{\n\t\t\tOPNPrescaler_w(OPN , v , 2);\n\t\t\t//TODO: set ADPCM[c].step\n\t\t\tF2608->deltaT.freqbase = OPN->ST.freqbase;\n\t\t}\n\t\tbreak;\n\n\tcase 1:\t/* data port 0    */\n\t\tif (F2608->addr_A1 != 0)\n\t\t\tbreak;\t/* verified on real YM2608 */\n\n\t\taddr = OPN->ST.address;\n\t\tF2608->REGS[addr] = v;\n\t\tswitch(addr & 0xf0)\n\t\t{\n\t\tcase 0x00:\t/* SSG section */\n\t\t\t/* Write data to SSG emulator */\n\t\t\t(*OPN->ST.SSG->write)(OPN->ST.param,a,v);\n\t\t\tbreak;\n\t\tcase 0x10:\t/* 0x10-0x1f : Rhythm section */\n\t\t\tym2608_update_req(OPN->ST.param);\n\t\t\tFM_ADPCMAWrite(F2608,addr-0x10,v);\n\t\t\tbreak;\n\t\tcase 0x20:\t/* Mode Register */\n\t\t\tswitch(addr)\n\t\t\t{\n\t\t\tcase 0x29:\t/* SCH,xx,xxx,EN_ZERO,EN_BRDY,EN_EOS,EN_TB,EN_TA */\n\t\t\t\tYM2608IRQMaskWrite(OPN, F2608, v);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tym2608_update_req(OPN->ST.param);\n\t\t\t\tOPNWriteMode(OPN,addr,v);\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\t/* OPN section */\n\t\t\tym2608_update_req(OPN->ST.param);\n\t\t\tOPNWriteReg(OPN,addr,v);\n\t\t}\n\t\tbreak;\n\n\tcase 2:\t/* address port 1 */\n\t\tOPN->ST.address = v;\n\t\tF2608->addr_A1 = 1;\n\t\tbreak;\n\n\tcase 3:\t/* data port 1    */\n\t\tif (F2608->addr_A1 != 1)\n\t\t\tbreak;\t/* verified on real YM2608 */\n\n\t\taddr = OPN->ST.address;\n\t\tF2608->REGS[addr | 0x100] = v;\n\t\tym2608_update_req(OPN->ST.param);\n\t\tswitch( addr & 0xf0 )\n\t\t{\n\t\tcase 0x00:\t/* DELTAT PORT */\n\t\t\tswitch( addr )\n\t\t\t{\n\t\t\tcase 0x0e:\t/* DAC data */\n#ifdef _DEBUG\n\t\t\t\tlogerror(\"YM2608: write to DAC data (unimplemented) value=%02x\\n\",v);\n#endif\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t/* 0x00-0x0d */\n\t\t\t\tYM_DELTAT_ADPCM_Write(&F2608->deltaT,addr,v);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 0x10:\t/* IRQ Flag control */\n\t\t\tif( addr == 0x10 )\n\t\t\t{\n\t\t\t\tYM2608IRQFlagWrite(OPN, F2608, v);\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tOPNWriteReg(OPN,addr | 0x100,v);\n\t\t}\n\t}\n\treturn OPN->ST.irq;\n}\n\nUINT8 ym2608_read(void *chip,int a)\n{\n\tYM2608 *F2608 = (YM2608 *)chip;\n\tint addr = F2608->OPN.ST.address;\n\tUINT8 ret = 0;\n\n\tswitch( a&3 )\n\t{\n\tcase 0:\t/* status 0 : YM2203 compatible */\n\t\t/* BUSY:x:x:x:x:x:FLAGB:FLAGA */\n\t\tret = FM_STATUS_FLAG(&F2608->OPN.ST) & 0x83;\n\t\tbreak;\n\n\tcase 1:\t/* status 0, ID  */\n\t\tif( addr < 16 ) ret = (*F2608->OPN.ST.SSG->read)(F2608->OPN.ST.param);\n\t\telse if(addr == 0xff) ret = 0x01; /* ID code */\n\t\tbreak;\n\n\tcase 2:\t/* status 1 : status 0 + ADPCM status */\n\t\t/* BUSY : x : PCMBUSY : ZERO : BRDY : EOS : FLAGB : FLAGA */\n\t\tret = (FM_STATUS_FLAG(&F2608->OPN.ST) & (F2608->flagmask|0x80)) | ((F2608->deltaT.PCM_BSY & 1)<<5) ;\n\t\tbreak;\n\n\tcase 3:\n\t\tif(addr == 0x08)\n\t\t{\n\t\t\tret = YM_DELTAT_ADPCM_Read(&F2608->deltaT);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(addr == 0x0f)\n\t\t\t{\n#ifdef _DEBUG\n\t\t\t\tlogerror(\"YM2608 A/D conversion is accessed but not implemented !\\n\");\n#endif\n\t\t\t\tret = 0x80; /* 2's complement PCM data - result from A/D conversion */\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t}\n\treturn ret;\n}\n\nint ym2608_timer_over(void *chip,int c)\n{\n\tYM2608 *F2608 = (YM2608 *)chip;\n\n    switch(c)\n\t{\n#if 0\n\tcase 2:\n\t\t{\t/* BUFRDY flag */\n\t\t\tYM_DELTAT_BRDY_callback( &F2608->deltaT );\n\t\t}\n\t\tbreak;\n#endif\n\tcase 1:\n\t\t{\t/* Timer B */\n\t\t\tTimerBOver( &(F2608->OPN.ST) );\n\t\t}\n\t\tbreak;\n\tcase 0:\n\t\t{\t/* Timer A */\n\t\t\tym2608_update_req(F2608->OPN.ST.param);\n\t\t\t/* timer update */\n\t\t\tTimerAOver( &(F2608->OPN.ST) );\n\t\t\t/* CSM mode key,TL controll */\n\t\t\tif( F2608->OPN.ST.mode & 0x80 )\n\t\t\t{\t/* CSM mode total level latch and auto key on */\n\t\t\t\tCSMKeyControll( F2608->OPN.type, &(F2608->CH[2]) );\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n    }\n\n\treturn F2608->OPN.ST.irq;\n}\n\nvoid ym2608_write_pcmrom(void *chip, UINT8 rom_id, offs_t ROMSize, offs_t DataStart,\n\t\t\t\t\t\t offs_t DataLength, const UINT8* ROMData)\n{\n\tYM2608 *F2608 = (YM2608 *)chip;\n\t\n\tswitch(rom_id)\n\t{\n\tcase 0x01:\t// ADPCM\n\t\t// unused, it's constant\n\t\tbreak;\n\tcase 0x02:\t// DELTA-T\n\t\tif (F2608->deltaT.memory_size != ROMSize)\n\t\t{\n\t\t\tF2608->deltaT.memory = (UINT8*)realloc(F2608->deltaT.memory, ROMSize);\n\t\t\tF2608->deltaT.memory_size = ROMSize;\n\t\t\tmemset(F2608->deltaT.memory, 0xFF, ROMSize);\n\t\t\tYM_DELTAT_calc_mem_mask(&F2608->deltaT);\n\t\t}\n\t\tif (DataStart > ROMSize)\n\t\t\treturn;\n\t\tif (DataStart + DataLength > ROMSize)\n\t\t\tDataLength = ROMSize - DataStart;\n\t\t\n\t\tmemcpy(F2608->deltaT.memory + DataStart, ROMData, DataLength);\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\nvoid ym2608_set_mutemask(void *chip, UINT32 MuteMask)\n{\n\tYM2608 *F2608 = (YM2608 *)chip;\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t\tF2608->CH[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t\tF2608->adpcm[CurChn].Muted = (MuteMask >> (CurChn + 6)) & 0x01;\n\tF2608->MuteDeltaT = (MuteMask >> 12) & 0x01;\n\t\n\treturn;\n}\n#endif /* BUILD_YM2608 */\n\n\n\n#if (BUILD_YM2610||BUILD_YM2610B)\n/* YM2610(OPNB) */\n\n/* Generate samples for one of the YM2610s */\nvoid ym2610_update_one(void *chip, FMSAMPLE **buffer, int length)\n{\n\tYM2610 *F2610 = (YM2610 *)chip;\n\tFM_OPN *OPN   = &F2610->OPN;\n\tYM_DELTAT *DELTAT = &F2610->deltaT;\n\tint i,j;\n\tFMSAMPLE  *bufL,*bufR;\n\tFM_CH\t*cch[4];\n\tINT32 *out_fm = OPN->out_fm;\n\n\t/* buffer setup */\n\tbufL = buffer[0];\n\tbufR = buffer[1];\n\n\tcch[0] = &F2610->CH[1];\n\tcch[1] = &F2610->CH[2];\n\tcch[2] = &F2610->CH[4];\n\tcch[3] = &F2610->CH[5];\n\n#ifdef YM2610B_WARNING\n#define FM_KEY_IS(SLOT) ((SLOT)->key)\n#define FM_MSG_YM2610B \"YM2610-%p.CH%d is playing,Check whether the type of the chip is YM2610B\\n\"\n\t/* Check YM2610B warning message */\n\tif( FM_KEY_IS(&F2610->CH[0].SLOT[3]) )\n\t{\n\t\tLOG(LOG_WAR,(FM_MSG_YM2610B,F2610->OPN.ST.param,0));\n\t\tFM_KEY_IS(&F2610->CH[0].SLOT[3]) = 0;\n\t}\n\tif( FM_KEY_IS(&F2610->CH[3].SLOT[3]) )\n\t{\n\t\tLOG(LOG_WAR,(FM_MSG_YM2610B,F2610->OPN.ST.param,3));\n\t\tFM_KEY_IS(&F2610->CH[3].SLOT[3]) = 0;\n\t}\n#endif\n\n\t/* refresh PG and EG */\n\trefresh_fc_eg_chan( OPN, cch[0] );\n\tif( (OPN->ST.mode & 0xc0) )\n\t{\n\t\t/* 3SLOT MODE */\n\t\tif( cch[1]->SLOT[SLOT1].Incr==-1)\n\t\t{\n\t\t\trefresh_fc_eg_slot(OPN, &cch[1]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[1]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[1]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[1]->SLOT[SLOT4] , cch[1]->fc , cch[1]->kcode );\n\t\t}\n\t}\n\telse\n\t\trefresh_fc_eg_chan( OPN, cch[1] );\n\trefresh_fc_eg_chan( OPN, cch[2] );\n\trefresh_fc_eg_chan( OPN, cch[3] );\n\n\t/* buffering */\n\tfor(i=0; i < length ; i++)\n\t{\n\n\t\tadvance_lfo(OPN);\n\n\t\t/* clear output acc. */\n\t\tOPN->out_adpcm[OUTD_LEFT] = OPN->out_adpcm[OUTD_RIGHT] = OPN->out_adpcm[OUTD_CENTER] = 0;\n\t\tOPN->out_delta[OUTD_LEFT] = OPN->out_delta[OUTD_RIGHT] = OPN->out_delta[OUTD_CENTER] = 0;\n\t\t/* clear outputs */\n\t\tout_fm[1] = 0;\n\t\tout_fm[2] = 0;\n\t\tout_fm[4] = 0;\n\t\tout_fm[5] = 0;\n\n\t\t/* advance envelope generator */\n\t\tOPN->eg_timer += OPN->eg_timer_add;\n\t\twhile (OPN->eg_timer >= OPN->eg_timer_overflow)\n\t\t{\n\t\t\tOPN->eg_timer -= OPN->eg_timer_overflow;\n\t\t\tOPN->eg_cnt++;\n\n\t\t\tadvance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[3]->SLOT[SLOT1]);\n\t\t}\n\n\t\t/* calculate FM */\n\t\tchan_calc(OPN, cch[0], 1 );\t/*remapped to 1*/\n\t\tchan_calc(OPN, cch[1], 2 );\t/*remapped to 2*/\n\t\tchan_calc(OPN, cch[2], 4 );\t/*remapped to 4*/\n\t\tchan_calc(OPN, cch[3], 5 );\t/*remapped to 5*/\n\n\t\t/* deltaT ADPCM */\n\t\tif( DELTAT->portstate&0x80 && ! F2610->MuteDeltaT )\n\t\t\tYM_DELTAT_ADPCM_CALC(DELTAT);\n\n\t\t/* ADPCMA */\n\t\tfor( j = 0; j < 6; j++ )\n\t\t{\n\t\t\tif( F2610->adpcm[j].flag )\n\t\t\t\tADPCMA_calc_chan( F2610, &F2610->adpcm[j]);\n\t\t}\n\n\t\t/* buffering */\n\t\t{\n\t\t\tint lt,rt;\n\n\t\t\t/*lt =  OPN->out_adpcm[OUTD_LEFT]  + OPN->out_adpcm[OUTD_CENTER];\n\t\t\trt =  OPN->out_adpcm[OUTD_RIGHT] + OPN->out_adpcm[OUTD_CENTER];\n\t\t\tlt += (OPN->out_delta[OUTD_LEFT]  + OPN->out_delta[OUTD_CENTER])>>9;\n\t\t\trt += (OPN->out_delta[OUTD_RIGHT] + OPN->out_delta[OUTD_CENTER])>>9;\n\n\n\t\t\tlt += ((out_fm[1]>>1) & OPN->pan[2]);\t// the shift right was verified on real chip\n\t\t\trt += ((out_fm[1]>>1) & OPN->pan[3]);\n\t\t\tlt += ((out_fm[2]>>1) & OPN->pan[4]);\n\t\t\trt += ((out_fm[2]>>1) & OPN->pan[5]);\n\n\t\t\tlt += ((out_fm[4]>>1) & OPN->pan[8]);\n\t\t\trt += ((out_fm[4]>>1) & OPN->pan[9]);\n\t\t\tlt += ((out_fm[5]>>1) & OPN->pan[10]);\n\t\t\trt += ((out_fm[5]>>1) & OPN->pan[11]);*/\n\n\t\t\tlt =  (OPN->out_adpcm[OUTD_LEFT]  + OPN->out_adpcm[OUTD_CENTER]) << 1;\n\t\t\trt =  (OPN->out_adpcm[OUTD_RIGHT] + OPN->out_adpcm[OUTD_CENTER]) << 1;\n\t\t\tlt += (OPN->out_delta[OUTD_LEFT]  + OPN->out_delta[OUTD_CENTER])>>8;\n\t\t\trt += (OPN->out_delta[OUTD_RIGHT] + OPN->out_delta[OUTD_CENTER])>>8;\n\n\n\t\t\tlt += (out_fm[1] & OPN->pan[2]);\n\t\t\trt += (out_fm[1] & OPN->pan[3]);\n\t\t\tlt += (out_fm[2] & OPN->pan[4]);\n\t\t\trt += (out_fm[2] & OPN->pan[5]);\n\n\t\t\tlt += (out_fm[4] & OPN->pan[8]);\n\t\t\trt += (out_fm[4] & OPN->pan[9]);\n\t\t\tlt += (out_fm[5] & OPN->pan[10]);\n\t\t\trt += (out_fm[5] & OPN->pan[11]);\n\n\n\t\t\tlt >>= FINAL_SH;\n\t\t\trt >>= FINAL_SH;\n\n\t\t\t//Limit( lt, MAXOUT, MINOUT );\n\t\t\t//Limit( rt, MAXOUT, MINOUT );\n\n\t\t\t#ifdef SAVE_SAMPLE\n\t\t\t\tSAVE_ALL_CHANNELS\n\t\t\t#endif\n\n\t\t\t/* buffering */\n\t\t\tbufL[i] = lt;\n\t\t\tbufR[i] = rt;\n\t\t}\n\n\t\t/* timer A control */\n\t\tINTERNAL_TIMER_A( &OPN->ST , cch[1] )\n\t}\n\tINTERNAL_TIMER_B(&OPN->ST,length)\n\n}\n\n#if BUILD_YM2610B\n/* Generate samples for one of the YM2610Bs */\nvoid ym2610b_update_one(void *chip, FMSAMPLE **buffer, int length)\n{\n\tYM2610 *F2610 = (YM2610 *)chip;\n\tFM_OPN *OPN   = &F2610->OPN;\n\tYM_DELTAT *DELTAT = &F2610->deltaT;\n\tint i,j;\n\tFMSAMPLE  *bufL,*bufR;\n\tFM_CH\t*cch[6];\n\tINT32 *out_fm = OPN->out_fm;\n\n\t/* buffer setup */\n\tbufL = buffer[0];\n\tbufR = buffer[1];\n\n\tcch[0] = &F2610->CH[0];\n\tcch[1] = &F2610->CH[1];\n\tcch[2] = &F2610->CH[2];\n\tcch[3] = &F2610->CH[3];\n\tcch[4] = &F2610->CH[4];\n\tcch[5] = &F2610->CH[5];\n\n\t/* refresh PG and EG */\n\trefresh_fc_eg_chan( OPN, cch[0] );\n\trefresh_fc_eg_chan( OPN, cch[1] );\n\tif( (OPN->ST.mode & 0xc0) )\n\t{\n\t\t/* 3SLOT MODE */\n\t\tif( cch[2]->SLOT[SLOT1].Incr==-1)\n\t\t{\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );\n\t\t}\n\t}\n\telse\n\t\trefresh_fc_eg_chan( OPN, cch[2] );\n\trefresh_fc_eg_chan( OPN, cch[3] );\n\trefresh_fc_eg_chan( OPN, cch[4] );\n\trefresh_fc_eg_chan( OPN, cch[5] );\n\n\t/* buffering */\n\tfor(i=0; i < length ; i++)\n\t{\n\n\t\tadvance_lfo(OPN);\n\n\t\t/* clear output acc. */\n\t\tOPN->out_adpcm[OUTD_LEFT] = OPN->out_adpcm[OUTD_RIGHT] = OPN->out_adpcm[OUTD_CENTER] = 0;\n\t\tOPN->out_delta[OUTD_LEFT] = OPN->out_delta[OUTD_RIGHT] = OPN->out_delta[OUTD_CENTER] = 0;\n\t\t/* clear outputs */\n\t\tout_fm[0] = 0;\n\t\tout_fm[1] = 0;\n\t\tout_fm[2] = 0;\n\t\tout_fm[3] = 0;\n\t\tout_fm[4] = 0;\n\t\tout_fm[5] = 0;\n\n\t\t/* advance envelope generator */\n\t\tOPN->eg_timer += OPN->eg_timer_add;\n\t\twhile (OPN->eg_timer >= OPN->eg_timer_overflow)\n\t\t{\n\t\t\tOPN->eg_timer -= OPN->eg_timer_overflow;\n\t\t\tOPN->eg_cnt++;\n\n\t\t\tadvance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[3]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[4]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[5]->SLOT[SLOT1]);\n\t\t}\n\n\t\t/* calculate FM */\n\t\tchan_calc(OPN, cch[0], 0 );\n\t\tchan_calc(OPN, cch[1], 1 );\n\t\tchan_calc(OPN, cch[2], 2 );\n\t\tchan_calc(OPN, cch[3], 3 );\n\t\tchan_calc(OPN, cch[4], 4 );\n\t\tchan_calc(OPN, cch[5], 5 );\n\n\t\t/* deltaT ADPCM */\n\t\tif( DELTAT->portstate&0x80 && ! F2610->MuteDeltaT )\n\t\t\tYM_DELTAT_ADPCM_CALC(DELTAT);\n\n\t\t/* ADPCMA */\n\t\tfor( j = 0; j < 6; j++ )\n\t\t{\n\t\t\tif( F2610->adpcm[j].flag )\n\t\t\t\tADPCMA_calc_chan( F2610, &F2610->adpcm[j]);\n\t\t}\n\n\t\t/* buffering */\n\t\t{\n\t\t\tint lt,rt;\n\n\t\t\t/*lt =  OPN->out_adpcm[OUTD_LEFT]  + OPN->out_adpcm[OUTD_CENTER];\n\t\t\trt =  OPN->out_adpcm[OUTD_RIGHT] + OPN->out_adpcm[OUTD_CENTER];\n\t\t\tlt += (OPN->out_delta[OUTD_LEFT]  + OPN->out_delta[OUTD_CENTER])>>9;\n\t\t\trt += (OPN->out_delta[OUTD_RIGHT] + OPN->out_delta[OUTD_CENTER])>>9;\n\n\t\t\tlt += ((out_fm[0]>>1) & OPN->pan[0]);\t// the shift right is verified on YM2610\n\t\t\trt += ((out_fm[0]>>1) & OPN->pan[1]);\n\t\t\tlt += ((out_fm[1]>>1) & OPN->pan[2]);\n\t\t\trt += ((out_fm[1]>>1) & OPN->pan[3]);\n\t\t\tlt += ((out_fm[2]>>1) & OPN->pan[4]);\n\t\t\trt += ((out_fm[2]>>1) & OPN->pan[5]);\n\t\t\tlt += ((out_fm[3]>>1) & OPN->pan[6]);\n\t\t\trt += ((out_fm[3]>>1) & OPN->pan[7]);\n\t\t\tlt += ((out_fm[4]>>1) & OPN->pan[8]);\n\t\t\trt += ((out_fm[4]>>1) & OPN->pan[9]);\n\t\t\tlt += ((out_fm[5]>>1) & OPN->pan[10]);\n\t\t\trt += ((out_fm[5]>>1) & OPN->pan[11]);*/\n\t\t\tlt =  (OPN->out_adpcm[OUTD_LEFT]  + OPN->out_adpcm[OUTD_CENTER]) << 1;\n\t\t\trt =  (OPN->out_adpcm[OUTD_RIGHT] + OPN->out_adpcm[OUTD_CENTER]) << 1;\n\t\t\tlt += (OPN->out_delta[OUTD_LEFT]  + OPN->out_delta[OUTD_CENTER])>>8;\n\t\t\trt += (OPN->out_delta[OUTD_RIGHT] + OPN->out_delta[OUTD_CENTER])>>8;\n\n\t\t\tlt += (out_fm[0] & OPN->pan[0]);\n\t\t\trt += (out_fm[0] & OPN->pan[1]);\n\t\t\tlt += (out_fm[1] & OPN->pan[2]);\n\t\t\trt += (out_fm[1] & OPN->pan[3]);\n\t\t\tlt += (out_fm[2] & OPN->pan[4]);\n\t\t\trt += (out_fm[2] & OPN->pan[5]);\n\t\t\tlt += (out_fm[3] & OPN->pan[6]);\n\t\t\trt += (out_fm[3] & OPN->pan[7]);\n\t\t\tlt += (out_fm[4] & OPN->pan[8]);\n\t\t\trt += (out_fm[4] & OPN->pan[9]);\n\t\t\tlt += (out_fm[5] & OPN->pan[10]);\n\t\t\trt += (out_fm[5] & OPN->pan[11]);\n\n\n\t\t\tlt >>= FINAL_SH;\n\t\t\trt >>= FINAL_SH;\n\n\t\t\t//Limit( lt, MAXOUT, MINOUT );\n\t\t\t//Limit( rt, MAXOUT, MINOUT );\n\n\t\t\t#ifdef SAVE_SAMPLE\n\t\t\t\tSAVE_ALL_CHANNELS\n\t\t\t#endif\n\n\t\t\t/* buffering */\n\t\t\tbufL[i] = lt;\n\t\t\tbufR[i] = rt;\n\t\t}\n\n\t\t/* timer A control */\n\t\tINTERNAL_TIMER_A( &OPN->ST , cch[2] )\n\t}\n\tINTERNAL_TIMER_B(&OPN->ST,length)\n\n}\n#endif /* BUILD_YM2610B */\n\n\n#ifdef __STATE_H__\nvoid ym2610_postload(void *chip)\n{\n\tif (chip)\n\t{\n\t\tYM2610 *F2610 = (YM2610 *)chip;\n\t\tint r;\n\n\t\t/* SSG registers */\n\t\tfor(r=0;r<16;r++)\n\t\t{\n\t\t\t(*F2610->OPN.ST.SSG->write)(F2610->OPN.ST.param,0,r);\n\t\t\t(*F2610->OPN.ST.SSG->write)(F2610->OPN.ST.param,1,F2610->REGS[r]);\n\t\t}\n\n\t\t/* OPN registers */\n\t\t/* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */\n\t\tfor(r=0x30;r<0x9e;r++)\n\t\t\tif((r&3) != 3)\n\t\t\t{\n\t\t\t\tOPNWriteReg(&F2610->OPN,r,F2610->REGS[r]);\n\t\t\t\tOPNWriteReg(&F2610->OPN,r|0x100,F2610->REGS[r|0x100]);\n\t\t\t}\n\t\t/* FB / CONNECT , L / R / AMS / PMS */\n\t\tfor(r=0xb0;r<0xb6;r++)\n\t\t\tif((r&3) != 3)\n\t\t\t{\n\t\t\t\tOPNWriteReg(&F2610->OPN,r,F2610->REGS[r]);\n\t\t\t\tOPNWriteReg(&F2610->OPN,r|0x100,F2610->REGS[r|0x100]);\n\t\t\t}\n\t\t/* FM channels */\n\t\t/*FM_channel_postload(F2610->CH,6);*/\n\n\t\t/* rhythm(ADPCMA) */\n\t\tFM_ADPCMAWrite(F2610,1,F2610->REGS[0x101]);\n\t\tfor( r=0 ; r<6 ; r++)\n\t\t{\n\t\t\tFM_ADPCMAWrite(F2610,r+0x08,F2610->REGS[r+0x108]);\n\t\t\tFM_ADPCMAWrite(F2610,r+0x10,F2610->REGS[r+0x110]);\n\t\t\tFM_ADPCMAWrite(F2610,r+0x18,F2610->REGS[r+0x118]);\n\t\t\tFM_ADPCMAWrite(F2610,r+0x20,F2610->REGS[r+0x120]);\n\t\t\tFM_ADPCMAWrite(F2610,r+0x28,F2610->REGS[r+0x128]);\n\t\t}\n\t\t/* Delta-T ADPCM unit */\n\t\tYM_DELTAT_postload(&F2610->deltaT , &F2610->REGS[0x010] );\n\t}\n}\n\nstatic void YM2610_save_state(YM2610 *F2610, const device_config *device)\n{\n\tstate_save_register_device_item_array(device, 0, F2610->REGS);\n\tFMsave_state_st(device,&F2610->OPN.ST);\n\tFMsave_state_channel(device,F2610->CH,6);\n\t/* 3slots */\n\tstate_save_register_device_item_array(device, 0, F2610->OPN.SL3.fc);\n\tstate_save_register_device_item(device, 0, F2610->OPN.SL3.fn_h);\n\tstate_save_register_device_item_array(device, 0, F2610->OPN.SL3.kcode);\n\t/* address register1 */\n\tstate_save_register_device_item(device, 0, F2610->addr_A1);\n\n\tstate_save_register_device_item(device, 0, F2610->adpcm_arrivedEndAddress);\n\t/* rythm(ADPCMA) */\n\tFMsave_state_adpcma(device,F2610->adpcm);\n\t/* Delta-T ADPCM unit */\n\tYM_DELTAT_savestate(device,&F2610->deltaT);\n}\n#endif /* _STATE_H */\n\nstatic void YM2610_deltat_status_set(void *chip, UINT8 changebits)\n{\n\tYM2610 *F2610 = (YM2610 *)chip;\n\tF2610->adpcm_arrivedEndAddress |= changebits;\n}\nstatic void YM2610_deltat_status_reset(void *chip, UINT8 changebits)\n{\n\tYM2610 *F2610 = (YM2610 *)chip;\n\tF2610->adpcm_arrivedEndAddress &= (~changebits);\n}\n\n//void *ym2610_init(void *param, const device_config *device, int clock, int rate,\n//               void *pcmroma,int pcmsizea,void *pcmromb,int pcmsizeb,\n//               FM_TIMERHANDLER timer_handler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg)\nvoid *ym2610_init(void *param, int clock, int rate,\n               FM_TIMERHANDLER timer_handler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg)\n{\n\tYM2610 *F2610;\n\n\t/* allocate extend state space */\n\tif( (F2610 = (YM2610 *)malloc(sizeof(YM2610)))==NULL)\n\t\treturn NULL;\n\t/* clear */\n\tmemset(F2610,0,sizeof(YM2610));\n\t/* allocate total level table (128kb space) */\n\tif( !init_tables() )\n\t{\n\t\tfree( F2610 );\n\t\treturn NULL;\n\t}\n\n\t/* FM */\n\tF2610->OPN.ST.param = param;\n\tF2610->OPN.type = TYPE_YM2610;\n\tF2610->OPN.P_CH = F2610->CH;\n\t//F2610->OPN.ST.device = device;\n\tF2610->OPN.ST.clock = clock;\n\tF2610->OPN.ST.rate = rate;\n\t/* Extend handler */\n\tF2610->OPN.ST.timer_handler = timer_handler;\n\tF2610->OPN.ST.IRQ_Handler   = IRQHandler;\n\tF2610->OPN.ST.SSG           = ssg;\n\t/* ADPCM */\n\t//F2610->pcmbuf   = (const UINT8 *)pcmroma;\n\t//F2610->pcm_size = pcmsizea;\n\tF2610->pcmbuf   = NULL;\n\tF2610->pcm_size = 0x00;\n\t/* DELTA-T */\n\t//F2610->deltaT.memory = (UINT8 *)pcmromb;\n\t//F2610->deltaT.memory_size = pcmsizeb;\n\tF2610->deltaT.memory = NULL;\n\tF2610->deltaT.memory_size = 0x00;\n\tF2610->deltaT.memory_mask = 0x00;\n\n\tF2610->deltaT.status_set_handler = YM2610_deltat_status_set;\n\tF2610->deltaT.status_reset_handler = YM2610_deltat_status_reset;\n\tF2610->deltaT.status_change_which_chip = F2610;\n\tF2610->deltaT.status_change_EOS_bit = 0x80;\t/* status flag: set bit7 on End Of Sample */\n\n\tInit_ADPCMATable();\n#ifdef __STATE_H__\n\tYM2610_save_state(F2610, device);\n#endif\n\treturn F2610;\n}\n\n/* shut down emulator */\nvoid ym2610_shutdown(void *chip)\n{\n\tYM2610 *F2610 = (YM2610 *)chip;\n\n\tfree(F2610->pcmbuf);\t\tF2610->pcmbuf = NULL;\n\tfree(F2610->deltaT.memory);\tF2610->deltaT.memory = NULL;\n\n\tFMCloseTable();\n\tfree(F2610);\n}\n\n/* reset one of chip */\nvoid ym2610_reset_chip(void *chip)\n{\n\tint i;\n\tYM2610 *F2610 = (YM2610 *)chip;\n\tFM_OPN *OPN   = &F2610->OPN;\n\tYM_DELTAT *DELTAT = &F2610->deltaT;\n\n\t/*astring name;\n\tdevice_t* dev = F2610->OPN.ST.device;*/\n\n\t/* setup PCM buffers again */\n\t/*name.printf(\"%s\",dev->tag());\n\tF2610->pcmbuf   = (const UINT8 *)dev->machine->region(name)->base();\n\tF2610->pcm_size = dev->machine->region(name)->bytes();\n\tname.printf(\"%s.deltat\",dev->tag());\n\tF2610->deltaT.memory = (UINT8 *)dev->machine->region(name)->base();\n\tif(F2610->deltaT.memory == NULL)\n\t{\n\t\tF2610->deltaT.memory = (UINT8*)F2610->pcmbuf;\n\t\tF2610->deltaT.memory_size = F2610->pcm_size;\n\t}\n\telse\n\t\tF2610->deltaT.memory_size = dev->machine->region(name)->bytes();*/\n\n\t/* Reset Prescaler */\n\tOPNSetPres( OPN, 6*24, 6*24, 4*2); /* OPN 1/6 , SSG 1/4 */\n\t/* reset SSG section */\n\t(*OPN->ST.SSG->reset)(OPN->ST.param);\n\t/* status clear */\n\tFM_IRQMASK_SET(&OPN->ST,0x03);\n\tFM_BUSY_CLEAR(&OPN->ST);\n\tOPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */\n\n\tOPN->eg_timer = 0;\n\tOPN->eg_cnt   = 0;\n\n\tFM_STATUS_RESET(&OPN->ST, 0xff);\n\n\treset_channels( &OPN->ST , F2610->CH , 6 );\n\t/* reset OPerator paramater */\n\tfor(i = 0xb6 ; i >= 0xb4 ; i-- )\n\t{\n\t\tOPNWriteReg(OPN,i      ,0xc0);\n\t\tOPNWriteReg(OPN,i|0x100,0xc0);\n\t}\n\tfor(i = 0xb2 ; i >= 0x30 ; i-- )\n\t{\n\t\tOPNWriteReg(OPN,i      ,0);\n\t\tOPNWriteReg(OPN,i|0x100,0);\n\t}\n\tfor(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);\n\t/**** ADPCM work initial ****/\n\tfor( i = 0; i < 6 ; i++ )\n\t{\n\t\tF2610->adpcm[i].step      = (UINT32)((float)(1<<ADPCM_SHIFT)*((float)F2610->OPN.ST.freqbase)/3.0);\n\t\tF2610->adpcm[i].now_addr  = 0;\n\t\tF2610->adpcm[i].now_step  = 0;\n\t\tF2610->adpcm[i].start     = 0;\n\t\tF2610->adpcm[i].end       = 0;\n\t\t/* F2610->adpcm[i].delta     = 21866; */\n\t\tF2610->adpcm[i].vol_mul   = 0;\n\t\tF2610->adpcm[i].pan       = &OPN->out_adpcm[OUTD_CENTER]; /* default center */\n\t\tF2610->adpcm[i].flagMask  = 1<<i;\n\t\tF2610->adpcm[i].flag      = 0;\n\t\tF2610->adpcm[i].adpcm_acc = 0;\n\t\tF2610->adpcm[i].adpcm_step= 0;\n\t\tF2610->adpcm[i].adpcm_out = 0;\n\t}\n\tF2610->adpcmTL = 0x3f;\n\n\tF2610->adpcm_arrivedEndAddress = 0;\n\n\t/* DELTA-T unit */\n\tDELTAT->freqbase = OPN->ST.freqbase;\n\tDELTAT->output_pointer = OPN->out_delta;\n\tDELTAT->portshift = 8;\t\t/* allways 8bits shift */\n\tDELTAT->output_range = 1<<23;\n\tYM_DELTAT_ADPCM_Reset(DELTAT,OUTD_CENTER,YM_DELTAT_EMULATION_MODE_YM2610);\n}\n\n/* YM2610 write */\n/* n = number  */\n/* a = address */\n/* v = value   */\nint ym2610_write(void *chip, int a, UINT8 v)\n{\n\tYM2610 *F2610 = (YM2610 *)chip;\n\tFM_OPN *OPN   = &F2610->OPN;\n\tint addr;\n\tint ch;\n\n\tv &= 0xff;\t/* adjust to 8 bit bus */\n\n\tswitch( a&3 )\n\t{\n\tcase 0:\t/* address port 0 */\n\t\tOPN->ST.address = v;\n\t\tF2610->addr_A1 = 0;\n\n\t\t/* Write register to SSG emulator */\n\t\tif( v < 16 ) (*OPN->ST.SSG->write)(OPN->ST.param,0,v);\n\t\tbreak;\n\n\tcase 1:\t/* data port 0    */\n\t\tif (F2610->addr_A1 != 0)\n\t\t\tbreak;\t/* verified on real YM2608 */\n\n\t\taddr = OPN->ST.address;\n\t\tF2610->REGS[addr] = v;\n\t\tswitch(addr & 0xf0)\n\t\t{\n\t\tcase 0x00:\t/* SSG section */\n\t\t\t/* Write data to SSG emulator */\n\t\t\t(*OPN->ST.SSG->write)(OPN->ST.param,a,v);\n\t\t\tbreak;\n\t\tcase 0x10: /* DeltaT ADPCM */\n\t\t\tym2610_update_req(OPN->ST.param);\n\n\t\t\tswitch(addr)\n\t\t\t{\n\t\t\tcase 0x10:\t/* control 1 */\n\t\t\tcase 0x11:\t/* control 2 */\n\t\t\tcase 0x12:\t/* start address L */\n\t\t\tcase 0x13:\t/* start address H */\n\t\t\tcase 0x14:\t/* stop address L */\n\t\t\tcase 0x15:\t/* stop address H */\n\n\t\t\tcase 0x19:\t/* delta-n L */\n\t\t\tcase 0x1a:\t/* delta-n H */\n\t\t\tcase 0x1b:\t/* volume */\n\t\t\t\t{\n\t\t\t\t\tYM_DELTAT_ADPCM_Write(&F2610->deltaT,addr-0x10,v);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 0x1c: /*  FLAG CONTROL : Extend Status Clear/Mask */\n\t\t\t\t{\n\t\t\t\t\tUINT8 statusmask = ~v;\n\t\t\t\t\t/* set arrived flag mask */\n\t\t\t\t\tfor(ch=0;ch<6;ch++)\n\t\t\t\t\t\tF2610->adpcm[ch].flagMask = statusmask&(1<<ch);\n\n\t\t\t\t\tF2610->deltaT.status_change_EOS_bit = statusmask & 0x80;\t/* status flag: set bit7 on End Of Sample */\n\n\t\t\t\t\t/* clear arrived flag */\n\t\t\t\t\tF2610->adpcm_arrivedEndAddress &= statusmask;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n#ifdef _DEBUG\n\t\t\t\tlogerror(\"YM2610: write to unknown deltat register %02x val=%02x\\n\",addr,v);\n#endif\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tbreak;\n\t\tcase 0x20:\t/* Mode Register */\n\t\t\tym2610_update_req(OPN->ST.param);\n\t\t\tOPNWriteMode(OPN,addr,v);\n\t\t\tbreak;\n\t\tdefault:\t/* OPN section */\n\t\t\tym2610_update_req(OPN->ST.param);\n\t\t\t/* write register */\n\t\t\tOPNWriteReg(OPN,addr,v);\n\t\t}\n\t\tbreak;\n\n\tcase 2:\t/* address port 1 */\n\t\tOPN->ST.address = v;\n\t\tF2610->addr_A1 = 1;\n\t\tbreak;\n\n\tcase 3:\t/* data port 1    */\n\t\tif (F2610->addr_A1 != 1)\n\t\t\tbreak;\t/* verified on real YM2608 */\n\n\t\tym2610_update_req(OPN->ST.param);\n\t\taddr = OPN->ST.address;\n\t\tF2610->REGS[addr | 0x100] = v;\n\t\tif( addr < 0x30 )\n\t\t\t/* 100-12f : ADPCM A section */\n\t\t\tFM_ADPCMAWrite(F2610,addr,v);\n\t\telse\n\t\t\tOPNWriteReg(OPN,addr | 0x100,v);\n\t}\n\treturn OPN->ST.irq;\n}\n\nUINT8 ym2610_read(void *chip,int a)\n{\n\tYM2610 *F2610 = (YM2610 *)chip;\n\tint addr = F2610->OPN.ST.address;\n\tUINT8 ret = 0;\n\n\tswitch( a&3)\n\t{\n\tcase 0:\t/* status 0 : YM2203 compatible */\n\t\tret = FM_STATUS_FLAG(&F2610->OPN.ST) & 0x83;\n\t\tbreak;\n\tcase 1:\t/* data 0 */\n\t\tif( addr < 16 ) ret = (*F2610->OPN.ST.SSG->read)(F2610->OPN.ST.param);\n\t\tif( addr == 0xff ) ret = 0x01;\n\t\tbreak;\n\tcase 2:\t/* status 1 : ADPCM status */\n\t\t/* ADPCM STATUS (arrived End Address) */\n\t\t/* B,--,A5,A4,A3,A2,A1,A0 */\n\t\t/* B     = ADPCM-B(DELTA-T) arrived end address */\n\t\t/* A0-A5 = ADPCM-A          arrived end address */\n\t\tret = F2610->adpcm_arrivedEndAddress;\n\t\tbreak;\n\tcase 3:\n\t\tret = 0;\n\t\tbreak;\n\t}\n\treturn ret;\n}\n\nint ym2610_timer_over(void *chip,int c)\n{\n\tYM2610 *F2610 = (YM2610 *)chip;\n\n\tif( c )\n\t{\t/* Timer B */\n\t\tTimerBOver( &(F2610->OPN.ST) );\n\t}\n\telse\n\t{\t/* Timer A */\n\t\tym2610_update_req(F2610->OPN.ST.param);\n\t\t/* timer update */\n\t\tTimerAOver( &(F2610->OPN.ST) );\n\t\t/* CSM mode key,TL controll */\n\t\tif( F2610->OPN.ST.mode & 0x80 )\n\t\t{\t/* CSM mode total level latch and auto key on */\n\t\t\tCSMKeyControll( F2610->OPN.type, &(F2610->CH[2]) );\n\t\t}\n\t}\n\treturn F2610->OPN.ST.irq;\n}\n\nvoid ym2610_write_pcmrom(void *chip, UINT8 rom_id, offs_t ROMSize, offs_t DataStart,\n\t\t\t\t\t\t offs_t DataLength, const UINT8* ROMData)\n{\n\tYM2610 *F2610 = (YM2610 *)chip;\n\t\n\tswitch(rom_id)\n\t{\n\tcase 0x01:\t// ADPCM\n\t\tif (F2610->pcm_size != ROMSize)\n\t\t{\n\t\t\tF2610->pcmbuf = (UINT8*)realloc(F2610->pcmbuf, ROMSize);\n\t\t\tF2610->pcm_size = ROMSize;\n\t\t\tmemset(F2610->pcmbuf, 0xFF, ROMSize);\n\t\t}\n\t\tif (DataStart > ROMSize)\n\t\t\treturn;\n\t\tif (DataStart + DataLength > ROMSize)\n\t\t\tDataLength = ROMSize - DataStart;\n\t\t\n\t\tmemcpy(F2610->pcmbuf + DataStart, ROMData, DataLength);\n\t\tbreak;\n\tcase 0x02:\t// DELTA-T\n\t\tif (F2610->deltaT.memory_size != ROMSize)\n\t\t{\n\t\t\tF2610->deltaT.memory = (UINT8*)realloc(F2610->deltaT.memory, ROMSize);\n\t\t\tF2610->deltaT.memory_size = ROMSize;\n\t\t\tmemset(F2610->deltaT.memory, 0xFF, ROMSize);\n\t\t\tYM_DELTAT_calc_mem_mask(&F2610->deltaT);\n\t\t}\n\t\tif (DataStart > ROMSize)\n\t\t\treturn;\n\t\tif (DataStart + DataLength > ROMSize)\n\t\t\tDataLength = ROMSize - DataStart;\n\t\t\n\t\tmemcpy(F2610->deltaT.memory + DataStart, ROMData, DataLength);\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\nvoid ym2610_set_mutemask(void *chip, UINT32 MuteMask)\n{\n\tYM2610 *F2610 = (YM2610 *)chip;\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t\tF2610->CH[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t\tF2610->adpcm[CurChn].Muted = (MuteMask >> (CurChn + 6)) & 0x01;\n\tF2610->MuteDeltaT = (MuteMask >> 12) & 0x01;\n\t\n\treturn;\n}\n#endif /* (BUILD_YM2610||BUILD_YM2610B) */\n"
  },
  {
    "path": "VGMPlay/chips/fm.h",
    "content": "/*\n  File: fm.h -- header file for software emulation for FM sound generator\n\n*/\n\n#pragma once\n\n/* --- select emulation chips --- */\n/*\n#define BUILD_YM2203  (HAS_YM2203)\t\t// build YM2203(OPN)   emulator\n#define BUILD_YM2608  (HAS_YM2608)\t\t// build YM2608(OPNA)  emulator\n#define BUILD_YM2610  (HAS_YM2610)\t\t// build YM2610(OPNB)  emulator\n#define BUILD_YM2610B (HAS_YM2610B)\t\t// build YM2610B(OPNB?)emulator\n#define BUILD_YM2612  (HAS_YM2612)\t\t// build YM2612(OPN2)  emulator\n#define BUILD_YM3438  (HAS_YM3438)\t\t// build YM3438(OPN) emulator\n*/\n#define BUILD_YM2203  1\n#define BUILD_YM2608  1\n#define BUILD_YM2610  1\n#define BUILD_YM2610B 1\n#define BUILD_YM2612  1\n#define BUILD_YM3438  1\n\n/* select bit size of output : 8 or 16 */\n#define FM_SAMPLE_BITS 16\n\n/* select timer system internal or external */\n#define FM_INTERNAL_TIMER 1\n\n/* --- speedup optimize --- */\n/* busy flag enulation , The definition of FM_GET_TIME_NOW() is necessary. */\n//#define FM_BUSY_FLAG_SUPPORT 1\n\n/* --- external SSG(YM2149/AY-3-8910)emulator interface port */\n/* used by YM2203,YM2608,and YM2610 */\ntypedef struct _ssg_callbacks ssg_callbacks;\nstruct _ssg_callbacks\n{\n\tvoid (*set_clock)(void *param, int clock);\n\tvoid (*write)(void *param, int address, int data);\n\tint (*read)(void *param);\n\tvoid (*reset)(void *param);\n};\n\n/* --- external callback funstions for realtime update --- */\n\n#if FM_BUSY_FLAG_SUPPORT\n#define TIME_TYPE\t\t\t\t\tattotime\n#define UNDEFINED_TIME\t\t\t\tattotime_zero\n#define FM_GET_TIME_NOW(machine)\t\t\ttimer_get_time(machine)\n#define ADD_TIMES(t1, t2)   \t\tattotime_add((t1), (t2))\n#define COMPARE_TIMES(t1, t2)\t\tattotime_compare((t1), (t2))\n#define MULTIPLY_TIME_BY_INT(t,i)\tattotime_mul(t, i)\n#endif\n\n#if BUILD_YM2203\n  /* in 2203intf.c */\n  void ym2203_update_request(void *param);\n  #define ym2203_update_req(chip) ym2203_update_request(chip)\n#endif /* BUILD_YM2203 */\n\n#if BUILD_YM2608\n  /* in 2608intf.c */\n  void ym2608_update_request(void *param);\n  #define ym2608_update_req(chip) ym2608_update_request(chip);\n#endif /* BUILD_YM2608 */\n\n#if (BUILD_YM2610||BUILD_YM2610B)\n  /* in 2610intf.c */\n  void ym2610_update_request(void *param);\n  #define ym2610_update_req(chip) ym2610_update_request(chip);\n#endif /* (BUILD_YM2610||BUILD_YM2610B) */\n\n#if (BUILD_YM2612||BUILD_YM3438)\n  /* in 2612intf.c */\n  void ym2612_update_request(void *param);\n  #define ym2612_update_req(chip) ym2612_update_request(chip);\n#endif /* (BUILD_YM2612||BUILD_YM3438) */\n\n/* compiler dependence */\n#if 0\n#ifndef OSD_CPU_H\n#define OSD_CPU_H\ntypedef unsigned char\tUINT8;   /* unsigned  8bit */\ntypedef unsigned short\tUINT16;  /* unsigned 16bit */\ntypedef unsigned int\tUINT32;  /* unsigned 32bit */\ntypedef signed char\t\tINT8;    /* signed  8bit   */\ntypedef signed short\tINT16;   /* signed 16bit   */\ntypedef signed int\t\tINT32;   /* signed 32bit   */\n#endif /* OSD_CPU_H */\n#endif\n\n\n\ntypedef stream_sample_t FMSAMPLE;\n/*\n#if (FM_SAMPLE_BITS==16)\ntypedef INT16 FMSAMPLE;\n#endif\n#if (FM_SAMPLE_BITS==8)\ntypedef unsigned char  FMSAMPLE;\n#endif\n*/\n\ntypedef void (*FM_TIMERHANDLER)(void *param,int c,int cnt,int clock);\ntypedef void (*FM_IRQHANDLER)(void *param,int irq);\n/* FM_TIMERHANDLER : Stop or Start timer         */\n/* int n          = chip number                  */\n/* int c          = Channel 0=TimerA,1=TimerB    */\n/* int count      = timer count (0=stop)         */\n/* doube stepTime = step time of one count (sec.)*/\n\n/* FM_IRQHHANDLER : IRQ level changing sense     */\n/* int n       = chip number                     */\n/* int irq     = IRQ level 0=OFF,1=ON            */\n\n#if BUILD_YM2203\n/* -------------------- YM2203(OPN) Interface -------------------- */\n\n/*\n** Initialize YM2203 emulator(s).\n**\n** 'num'           is the number of virtual YM2203's to allocate\n** 'baseclock'\n** 'rate'          is sampling rate\n** 'TimerHandler'  timer callback handler when timer start and clear\n** 'IRQHandler'    IRQ callback handler when changed IRQ level\n** return      0 = success\n*/\n//void * ym2203_init(void *param, const device_config *device, int baseclock, int rate,\n//               FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg);\nvoid * ym2203_init(void *param, int baseclock, int rate,\n               FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg);\n\n/*\n** shutdown the YM2203 emulators\n*/\nvoid ym2203_shutdown(void *chip);\n\n/*\n** reset all chip registers for YM2203 number 'num'\n*/\nvoid ym2203_reset_chip(void *chip);\n\n/*\n** update one of chip\n*/\nvoid ym2203_update_one(void *chip, FMSAMPLE **buffer, int length);\n\n/*\n** Write\n** return : InterruptLevel\n*/\nint ym2203_write(void *chip,int a,unsigned char v);\n\n/*\n** Read\n** return : InterruptLevel\n*/\nunsigned char ym2203_read(void *chip,int a);\n\n/*\n**  Timer OverFlow\n*/\nint ym2203_timer_over(void *chip, int c);\n\n/*\n**  State Save\n*/\nvoid ym2203_postload(void *chip);\n\nvoid ym2203_set_mutemask(void *chip, UINT32 MuteMask);\n#endif /* BUILD_YM2203 */\n\n#if BUILD_YM2608\n/* -------------------- YM2608(OPNA) Interface -------------------- */\n//void * ym2608_init(void *param, const device_config *device, int baseclock, int rate,\n//               void *pcmroma,int pcmsizea,\n//               FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg);\nvoid * ym2608_init(void *param, int baseclock, int rate,\n               FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg);\nvoid ym2608_shutdown(void *chip);\nvoid ym2608_reset_chip(void *chip);\nvoid ym2608_update_one(void *chip, FMSAMPLE **buffer, int length);\n\nint ym2608_write(void *chip, int a,unsigned char v);\nunsigned char ym2608_read(void *chip,int a);\nint ym2608_timer_over(void *chip, int c );\nvoid ym2608_postload(void *chip);\nvoid ym2608_write_pcmrom(void *chip, UINT8 rom_id, offs_t ROMSize, offs_t DataStart,\n\t\t\t\t\t\t offs_t DataLength, const UINT8* ROMData);\n\nvoid ym2608_set_mutemask(void *chip, UINT32 MuteMask);\n#endif /* BUILD_YM2608 */\n\n#if (BUILD_YM2610||BUILD_YM2610B)\n/* -------------------- YM2610(OPNB) Interface -------------------- */\n//void * ym2610_init(void *param, const device_config *device, int baseclock, int rate,\n//               void *pcmroma,int pcmasize,void *pcmromb,int pcmbsize,\n//               FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg);\nvoid * ym2610_init(void *param, int baseclock, int rate,\n               FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler, const ssg_callbacks *ssg);\nvoid ym2610_shutdown(void *chip);\nvoid ym2610_reset_chip(void *chip);\nvoid ym2610_update_one(void *chip, FMSAMPLE **buffer, int length);\n\n#if BUILD_YM2610B\nvoid ym2610b_update_one(void *chip, FMSAMPLE **buffer, int length);\n#endif /* BUILD_YM2610B */\n\nint ym2610_write(void *chip, int a,unsigned char v);\nunsigned char ym2610_read(void *chip,int a);\nint ym2610_timer_over(void *chip, int c );\nvoid ym2610_postload(void *chip);\nvoid ym2610_write_pcmrom(void *chip, UINT8 rom_id, offs_t ROMSize, offs_t DataStart,\n\t\t\t\t\t\t offs_t DataLength, const UINT8* ROMData);\n\nvoid ym2610_set_mutemask(void *chip, UINT32 MuteMask);\n#endif /* (BUILD_YM2610||BUILD_YM2610B) */\n\n#if (BUILD_YM2612||BUILD_YM3438)\n//void * ym2612_init(void *param, const device_config *device, int baseclock, int rate,\n//               FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler);\nvoid * ym2612_init(void *param, int baseclock, int rate,\n               FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler);\nvoid ym2612_shutdown(void *chip);\nvoid ym2612_reset_chip(void *chip);\nvoid ym2612_update_one(void *chip, FMSAMPLE **buffer, int length);\n\nint ym2612_write(void *chip, int a,unsigned char v);\nunsigned char ym2612_read(void *chip,int a);\nint ym2612_timer_over(void *chip, int c );\nvoid ym2612_postload(void *chip);\n\nvoid ym2612_set_mutemask(void *chip, UINT32 MuteMask);\nvoid ym2612_setoptions(UINT8 Flags);\n#endif /* (BUILD_YM2612||BUILD_YM3438) */\n\n"
  },
  {
    "path": "VGMPlay/chips/fm2612.c",
    "content": "/*\n**\n** File: fm2612.c -- software implementation of Yamaha YM2612 FM sound generator\n** Split from fm.c to keep 2612 fixes from infecting other OPN chips\n**\n** Copyright Jarek Burczynski (bujar at mame dot net)\n** Copyright Tatsuyuki Satoh , MultiArcadeMachineEmulator development\n**\n** Version 1.5.1 (Genesis Plus GX ym2612.c rev. 368)\n**\n*/\n\n/*\n** History:\n**\n** 2006~2012  Eke-Eke (Genesis Plus GX):\n** Huge thanks to Nemesis, lot of those fixes came from his tests on Sega Genesis hardware\n** More informations at http://gendev.spritesmind.net/forum/viewtopic.php?t=386\n**\n**  TODO:\n**\n**  - core documentation\n**  - BUSY flag support\n**\n**  CHANGELOG:\n**\n**  - fixed LFO implementation:\n**      .added support for CH3 special mode: fixes various sound effects (birds in Warlock, bug sound in Aladdin...)\n**      .inverted LFO AM waveform: fixes Spider-Man & Venom : Separation Anxiety (intro), California Games (surfing event)\n**      .improved LFO timing accuracy: now updated AFTER sample output, like EG/PG updates, and without any precision loss anymore.\n**  - improved internal timers emulation\n**  - adjusted lowest EG rates increment values\n**  - fixed Attack Rate not being updated in some specific cases (Batman & Robin intro)\n**  - fixed EG behavior when Attack Rate is maximal\n**  - fixed EG behavior when SL=0 (Mega Turrican tracks 03,09...) or/and Key ON occurs at minimal attenuation\n**  - implemented EG output immediate changes on register writes\n**  - fixed YM2612 initial values (after the reset): fixes missing intro in B.O.B\n**  - implemented Detune overflow (Ariel, Comix Zone, Shaq Fu, Spiderman & many other games using GEMS sound engine)\n**  - implemented accurate CSM mode emulation\n**  - implemented accurate SSG-EG emulation (Asterix, Beavis&Butthead, Bubba'n Stix & many other games)\n**  - implemented accurate address/data ports behavior\n**\n** 06-23-2007 Zsolt Vasvari:\n**  - changed the timing not to require the use of floating point calculations\n**\n** 03-08-2003 Jarek Burczynski:\n**  - fixed YM2608 initial values (after the reset)\n**  - fixed flag and irqmask handling (YM2608)\n**  - fixed BUFRDY flag handling (YM2608)\n**\n** 14-06-2003 Jarek Burczynski:\n**  - implemented all of the YM2608 status register flags\n**  - implemented support for external memory read/write via YM2608\n**  - implemented support for deltat memory limit register in YM2608 emulation\n**\n** 22-05-2003 Jarek Burczynski:\n**  - fixed LFO PM calculations (copy&paste bugfix)\n**\n** 08-05-2003 Jarek Burczynski:\n**  - fixed SSG support\n**\n** 22-04-2003 Jarek Burczynski:\n**  - implemented 100% correct LFO generator (verified on real YM2610 and YM2608)\n**\n** 15-04-2003 Jarek Burczynski:\n**  - added support for YM2608's register 0x110 - status mask\n**\n** 01-12-2002 Jarek Burczynski:\n**  - fixed register addressing in YM2608, YM2610, YM2610B chips. (verified on real YM2608)\n**    The addressing patch used for early Neo-Geo games can be removed now.\n**\n** 26-11-2002 Jarek Burczynski, Nicola Salmoria:\n**  - recreated YM2608 ADPCM ROM using data from real YM2608's output which leads to:\n**  - added emulation of YM2608 drums.\n**  - output of YM2608 is two times lower now - same as YM2610 (verified on real YM2608)\n**\n** 16-08-2002 Jarek Burczynski:\n**  - binary exact Envelope Generator (verified on real YM2203);\n**    identical to YM2151\n**  - corrected 'off by one' error in feedback calculations (when feedback is off)\n**  - corrected connection (algorithm) calculation (verified on real YM2203 and YM2610)\n**\n** 18-12-2001 Jarek Burczynski:\n**  - added SSG-EG support (verified on real YM2203)\n**\n** 12-08-2001 Jarek Burczynski:\n**  - corrected sin_tab and tl_tab data (verified on real chip)\n**  - corrected feedback calculations (verified on real chip)\n**  - corrected phase generator calculations (verified on real chip)\n**  - corrected envelope generator calculations (verified on real chip)\n**  - corrected FM volume level (YM2610 and YM2610B).\n**  - changed YMxxxUpdateOne() functions (YM2203, YM2608, YM2610, YM2610B, YM2612) :\n**    this was needed to calculate YM2610 FM channels output correctly.\n**    (Each FM channel is calculated as in other chips, but the output of the channel\n**    gets shifted right by one *before* sending to accumulator. That was impossible to do\n**    with previous implementation).\n**\n** 23-07-2001 Jarek Burczynski, Nicola Salmoria:\n**  - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip)\n**\n** 11-06-2001 Jarek Burczynski:\n**  - corrected end of sample bug in ADPCMA_calc_cha().\n**    Real YM2610 checks for equality between current and end addresses (only 20 LSB bits).\n**\n** 08-12-98 hiro-shi:\n** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA\n** move ROM limit check.(CALC_CH? -> 2610Write1/2)\n** test program (ADPCMB_TEST)\n** move ADPCM A/B end check.\n** ADPCMB repeat flag(no check)\n** change ADPCM volume rate (8->16) (32->48).\n**\n** 09-12-98 hiro-shi:\n** change ADPCM volume. (8->16, 48->64)\n** replace ym2610 ch0/3 (YM-2610B)\n** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff.\n** add ADPCM_SHIFT_MASK\n** change ADPCMA_DECODE_MIN/MAX.\n*/\n\n\n\n\n/************************************************************************/\n/*    comment of hiro-shi(Hiromitsu Shioya)                             */\n/*    YM2610(B) = OPN-B                                                 */\n/*    YM2610  : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch      */\n/*    YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch      */\n/************************************************************************/\n\n//#include \"emu.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include <math.h>\n#include \"mamedef.h\"\n#include \"fm.h\"\n\n/* shared function building option */\n#define BUILD_OPN (BUILD_YM2203||BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B||BUILD_YM2612||BUILD_YM3438)\n#define BUILD_OPN_PRESCALER (BUILD_YM2203||BUILD_YM2608)\n\n\n/* globals */\n#define TYPE_SSG    0x01    /* SSG support          */\n#define TYPE_LFOPAN 0x02    /* OPN type LFO and PAN */\n#define TYPE_6CH    0x04    /* FM 6CH / 3CH         */\n#define TYPE_DAC    0x08    /* YM2612's DAC device  */\n#define TYPE_ADPCM  0x10    /* two ADPCM units      */\n#define TYPE_2610   0x20    /* bogus flag to differentiate 2608 from 2610 */\n\n\n#define TYPE_YM2203 (TYPE_SSG)\n#define TYPE_YM2608 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM)\n#define TYPE_YM2610 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM |TYPE_2610)\n#define TYPE_YM2612 (TYPE_DAC |TYPE_LFOPAN |TYPE_6CH)\n\n\n/* globals */\n#define FREQ_SH\t\t\t16  /* 16.16 fixed point (frequency calculations) */\n#define EG_SH\t\t\t16  /* 16.16 fixed point (envelope generator timing) */\n#define LFO_SH\t\t\t24  /*  8.24 fixed point (LFO calculations)       */\n#define TIMER_SH\t\t16  /* 16.16 fixed point (timers calculations)    */\n\n#define FREQ_MASK\t\t((1<<FREQ_SH)-1)\n\n#define MAXOUT    (+32767)\n#define MINOUT    (-32768)\n\n/* envelope generator */\n#define ENV_BITS\t\t10\n#define ENV_LEN\t\t\t(1<<ENV_BITS)\n#define ENV_STEP\t\t(128.0/ENV_LEN)\n\n#define MAX_ATT_INDEX\t(ENV_LEN-1) /* 1023 */\n#define MIN_ATT_INDEX\t(0)\t\t\t/* 0 */\n\n#define EG_ATT\t\t\t4\n#define EG_DEC\t\t\t3\n#define EG_SUS\t\t\t2\n#define EG_REL\t\t\t1\n#define EG_OFF\t\t\t0\n\n/* operator unit */\n#define SIN_BITS\t\t10\n#define SIN_LEN\t\t\t(1<<SIN_BITS)\n#define SIN_MASK\t\t(SIN_LEN-1)\n\n#define TL_RES_LEN\t\t(256) /* 8 bits addressing (real chip) */\n\n/*  TL_TAB_LEN is calculated as:\n*   13 - sinus amplitude bits     (Y axis)\n*   2  - sinus sign bit           (Y axis)\n*   TL_RES_LEN - sinus resolution (X axis)\n*/\n#define TL_TAB_LEN (13*2*TL_RES_LEN)\nstatic signed int tl_tab[TL_TAB_LEN];\n\n#define ENV_QUIET\t\t(TL_TAB_LEN>>3)\n\n/* sin waveform table in 'decibel' scale */\nstatic unsigned int sin_tab[SIN_LEN];\n\n/* sustain level table (3dB per step) */\n/* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */\n/* 1,    2,    4,    8,    16,   32,   64   (value)*/\n/* 0.75, 1.5,  3,    6,    12,   24,   48   (dB)*/\n\n/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/\n/* attenuation value (10 bits) = (SL << 2) << 3 */\n#define SC(db) (UINT32) ( db * (4.0/ENV_STEP) )\nstatic const UINT32 sl_table[16]={\n SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),\n SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)\n};\n#undef SC\n\n\n#define RATE_STEPS (8)\nstatic const UINT8 eg_inc[19*RATE_STEPS]={\n\n/*cycle:0 1  2 3  4 5  6 7*/\n\n/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */\n/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */\n/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */\n/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */\n\n/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */\n/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */\n/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */\n/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */\n\n/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */\n/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */\n/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */\n/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */\n\n/*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */\n/*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */\n/*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */\n/*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */\n\n/*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */\n/*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */\n/*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */\n};\n\n\n#define O(a) (a*RATE_STEPS)\n\n/*note that there is no O(17) in this table - it's directly in the code */\nstatic const UINT8 eg_rate_select2612[32+64+32]={  /* Envelope Generator rates (32 + 64 rates + 32 RKS) */\n/* 32 infinite time rates (same as Rate 0) */\nO(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\nO(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\nO(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\nO(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\n\n/* rates 00-11 */\n/*\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\n*/\nO(18),O(18),O( 0),O( 0),\nO( 0),O( 0),O( 2),O( 2),   // Nemesis's tests\n\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\n\n/* rate 12 */\nO( 4),O( 5),O( 6),O( 7),\n\n/* rate 13 */\nO( 8),O( 9),O(10),O(11),\n\n/* rate 14 */\nO(12),O(13),O(14),O(15),\n\n/* rate 15 */\nO(16),O(16),O(16),O(16),\n\n/* 32 dummy rates (same as 15 3) */\nO(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\nO(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\nO(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\nO(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16)\n\n};\n#undef O\n\n/*rate  0,    1,    2,   3,   4,   5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15*/\n/*shift 11,   10,   9,   8,   7,   6,  5,  4,  3,  2, 1,  0,  0,  0,  0,  0 */\n/*mask  2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3, 1,  0,  0,  0,  0,  0 */\n\n#define O(a) (a*1)\nstatic const UINT8 eg_rate_shift[32+64+32]={  /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */\n/* 32 infinite time rates */\n/* O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), */\n\n/* fixed (should be the same as rate 0, even if it makes no difference since increment value is 0 for these rates) */\nO(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),\nO(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),\nO(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),\nO(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11),\n\n/* rates 00-11 */\nO(11),O(11),O(11),O(11),\nO(10),O(10),O(10),O(10),\nO( 9),O( 9),O( 9),O( 9),\nO( 8),O( 8),O( 8),O( 8),\nO( 7),O( 7),O( 7),O( 7),\nO( 6),O( 6),O( 6),O( 6),\nO( 5),O( 5),O( 5),O( 5),\nO( 4),O( 4),O( 4),O( 4),\nO( 3),O( 3),O( 3),O( 3),\nO( 2),O( 2),O( 2),O( 2),\nO( 1),O( 1),O( 1),O( 1),\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 12 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 13 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 14 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 15 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* 32 dummy rates (same as 15 3) */\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0)\n\n};\n#undef O\n\nstatic const UINT8 dt_tab[4 * 32]={\n/* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/\n/* FD=0 */\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n/* FD=1 */\n\t0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,\n\t2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,\n/* FD=2 */\n\t1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,\n\t5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,\n/* FD=3 */\n\t2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,\n\t8 , 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22\n};\n\n\n/* OPN key frequency number -> key code follow table */\n/* fnum higher 4bit -> keycode lower 2bit */\nstatic const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};\n\n\n/* 8 LFO speed parameters */\n/* each value represents number of samples that one LFO level will last for */\nstatic const UINT32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5};\n\n\n\n/*There are 4 different LFO AM depths available, they are:\n  0 dB, 1.4 dB, 5.9 dB, 11.8 dB\n  Here is how it is generated (in EG steps):\n\n  11.8 dB = 0, 2, 4, 6, 8, 10,12,14,16...126,126,124,122,120,118,....4,2,0\n   5.9 dB = 0, 1, 2, 3, 4, 5, 6, 7, 8....63, 63, 62, 61, 60, 59,.....2,1,0\n   1.4 dB = 0, 0, 0, 0, 1, 1, 1, 1, 2,...15, 15, 15, 15, 14, 14,.....0,0,0\n\n  (1.4 dB is losing precision as you can see)\n\n  It's implemented as generator from 0..126 with step 2 then a shift\n  right N times, where N is:\n    8 for 0 dB\n    3 for 1.4 dB\n    1 for 5.9 dB\n    0 for 11.8 dB\n*/\nstatic const UINT8 lfo_ams_depth_shift[4] = {8, 3, 1, 0};\n\n\n\n/*There are 8 different LFO PM depths available, they are:\n  0, 3.4, 6.7, 10, 14, 20, 40, 80 (cents)\n\n  Modulation level at each depth depends on F-NUMBER bits: 4,5,6,7,8,9,10\n  (bits 8,9,10 = FNUM MSB from OCT/FNUM register)\n\n  Here we store only first quarter (positive one) of full waveform.\n  Full table (lfo_pm_table) containing all 128 waveforms is build\n  at run (init) time.\n\n  One value in table below represents 4 (four) basic LFO steps\n  (1 PM step = 4 AM steps).\n\n  For example:\n   at LFO SPEED=0 (which is 108 samples per basic LFO step)\n   one value from \"lfo_pm_output\" table lasts for 432 consecutive\n   samples (4*108=432) and one full LFO waveform cycle lasts for 13824\n   samples (32*432=13824; 32 because we store only a quarter of whole\n            waveform in the table below)\n*/\nstatic const UINT8 lfo_pm_output[7*8][8]={ /* 7 bits meaningful (of F-NUMBER), 8 LFO output levels per one depth (out of 32), 8 LFO depths */\n/* FNUM BIT 4: 000 0001xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 2 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 3 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 4 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 5 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 6 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 7 */ {0,   0,   0,   0,   1,   1,   1,   1},\n\n/* FNUM BIT 5: 000 0010xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 2 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 3 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 4 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 5 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 6 */ {0,   0,   0,   0,   1,   1,   1,   1},\n/* DEPTH 7 */ {0,   0,   1,   1,   2,   2,   2,   3},\n\n/* FNUM BIT 6: 000 0100xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 2 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 3 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 4 */ {0,   0,   0,   0,   0,   0,   0,   1},\n/* DEPTH 5 */ {0,   0,   0,   0,   1,   1,   1,   1},\n/* DEPTH 6 */ {0,   0,   1,   1,   2,   2,   2,   3},\n/* DEPTH 7 */ {0,   0,   2,   3,   4,   4,   5,   6},\n\n/* FNUM BIT 7: 000 1000xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 2 */ {0,   0,   0,   0,   0,   0,   1,   1},\n/* DEPTH 3 */ {0,   0,   0,   0,   1,   1,   1,   1},\n/* DEPTH 4 */ {0,   0,   0,   1,   1,   1,   1,   2},\n/* DEPTH 5 */ {0,   0,   1,   1,   2,   2,   2,   3},\n/* DEPTH 6 */ {0,   0,   2,   3,   4,   4,   5,   6},\n/* DEPTH 7 */ {0,   0,   4,   6,   8,   8, 0xa, 0xc},\n\n/* FNUM BIT 8: 001 0000xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   1,   1,   1,   1},\n/* DEPTH 2 */ {0,   0,   0,   1,   1,   1,   2,   2},\n/* DEPTH 3 */ {0,   0,   1,   1,   2,   2,   3,   3},\n/* DEPTH 4 */ {0,   0,   1,   2,   2,   2,   3,   4},\n/* DEPTH 5 */ {0,   0,   2,   3,   4,   4,   5,   6},\n/* DEPTH 6 */ {0,   0,   4,   6,   8,   8, 0xa, 0xc},\n/* DEPTH 7 */ {0,   0,   8, 0xc,0x10,0x10,0x14,0x18},\n\n/* FNUM BIT 9: 010 0000xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   2,   2,   2,   2},\n/* DEPTH 2 */ {0,   0,   0,   2,   2,   2,   4,   4},\n/* DEPTH 3 */ {0,   0,   2,   2,   4,   4,   6,   6},\n/* DEPTH 4 */ {0,   0,   2,   4,   4,   4,   6,   8},\n/* DEPTH 5 */ {0,   0,   4,   6,   8,   8, 0xa, 0xc},\n/* DEPTH 6 */ {0,   0,   8, 0xc,0x10,0x10,0x14,0x18},\n/* DEPTH 7 */ {0,   0,0x10,0x18,0x20,0x20,0x28,0x30},\n\n/* FNUM BIT10: 100 0000xxxx */\n/* DEPTH 0 */ {0,   0,   0,   0,   0,   0,   0,   0},\n/* DEPTH 1 */ {0,   0,   0,   0,   4,   4,   4,   4},\n/* DEPTH 2 */ {0,   0,   0,   4,   4,   4,   8,   8},\n/* DEPTH 3 */ {0,   0,   4,   4,   8,   8, 0xc, 0xc},\n/* DEPTH 4 */ {0,   0,   4,   8,   8,   8, 0xc,0x10},\n/* DEPTH 5 */ {0,   0,   8, 0xc,0x10,0x10,0x14,0x18},\n/* DEPTH 6 */ {0,   0,0x10,0x18,0x20,0x20,0x28,0x30},\n/* DEPTH 7 */ {0,   0,0x20,0x30,0x40,0x40,0x50,0x60},\n\n};\n\n/* all 128 LFO PM waveforms */\nstatic INT32 lfo_pm_table[128*8*32]; /* 128 combinations of 7 bits meaningful (of F-NUMBER), 8 LFO depths, 32 LFO output levels per one depth */\n\n/* register number to channel number , slot offset */\n#define OPN_CHAN(N) (N&3)\n#define OPN_SLOT(N) ((N>>2)&3)\n\n/* slot number */\n#define SLOT1 0\n#define SLOT2 2\n#define SLOT3 1\n#define SLOT4 3\n\n/* bit0 = Right enable , bit1 = Left enable */\n#define OUTD_RIGHT  1\n#define OUTD_LEFT   2\n#define OUTD_CENTER 3\n\n\n/* save output as raw 16-bit sample */\n/* #define SAVE_SAMPLE */\n\n#ifdef SAVE_SAMPLE\nstatic FILE *sample[1];\n\t#if 1\t/*save to MONO file */\n\t\t#define SAVE_ALL_CHANNELS \\\n\t\t{\tsigned int pom = lt; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t}\n\t#else\t/*save to STEREO file */\n\t\t#define SAVE_ALL_CHANNELS \\\n\t\t{\tsigned int pom = lt; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t\tpom = rt; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t}\n\t#endif\n#endif\n\n\n/* struct describing a single operator (SLOT) */\ntypedef struct\n{\n\tINT32\t*DT;\t\t/* detune          :dt_tab[DT] */\n\tUINT8\tKSR;\t\t/* key scale rate  :3-KSR */\n\tUINT32\tar;\t\t\t/* attack rate  */\n\tUINT32\td1r;\t\t/* decay rate   */\n\tUINT32\td2r;\t\t/* sustain rate */\n\tUINT32\trr;\t\t\t/* release rate */\n\tUINT8\tksr;\t\t/* key scale rate  :kcode>>(3-KSR) */\n\tUINT32\tmul;\t\t/* multiple        :ML_TABLE[ML] */\n\n\t/* Phase Generator */\n\tUINT32\tphase;\t\t/* phase counter */\n\tINT32\tIncr;\t\t/* phase step */\n\n\t/* Envelope Generator */\n\tUINT8\tstate;\t\t/* phase type */\n\tUINT32\ttl;\t\t\t/* total level: TL << 3 */\n\tINT32\tvolume;\t\t/* envelope counter */\n\tUINT32\tsl;\t\t\t/* sustain level:sl_table[SL] */\n\tUINT32\tvol_out;\t/* current output from EG circuit (without AM from LFO) */\n\n\tUINT8\teg_sh_ar;\t/*  (attack state) */\n\tUINT8\teg_sel_ar;\t/*  (attack state) */\n\tUINT8\teg_sh_d1r;\t/*  (decay state) */\n\tUINT8\teg_sel_d1r;\t/*  (decay state) */\n\tUINT8\teg_sh_d2r;\t/*  (sustain state) */\n\tUINT8\teg_sel_d2r;\t/*  (sustain state) */\n\tUINT8\teg_sh_rr;\t/*  (release state) */\n\tUINT8\teg_sel_rr;\t/*  (release state) */\n\n\tUINT8\tssg;\t\t/* SSG-EG waveform */\n\tUINT8\tssgn;\t\t/* SSG-EG negated output */\n\n\tUINT8\tkey;\t\t/* 0=last key was KEY OFF, 1=KEY ON */\n\n\t/* LFO */\n\tUINT32\tAMmask;\t\t/* AM enable flag */\n\n} FM_SLOT;\n\ntypedef struct\n{\n\tFM_SLOT\tSLOT[4];\t/* four SLOTs (operators) */\n\n\tUINT8\tALGO;\t\t/* algorithm */\n\tUINT8\tFB;\t\t\t/* feedback shift */\n\tINT32\top1_out[2];\t/* op1 output for feedback */\n\n\tINT32\t*connect1;\t/* SLOT1 output pointer */\n\tINT32\t*connect3;\t/* SLOT3 output pointer */\n\tINT32\t*connect2;\t/* SLOT2 output pointer */\n\tINT32\t*connect4;\t/* SLOT4 output pointer */\n\n\tINT32\t*mem_connect;/* where to put the delayed sample (MEM) */\n\tINT32\tmem_value;\t/* delayed sample (MEM) value */\n\n\tINT32\tpms;\t\t/* channel PMS */\n\tUINT8\tams;\t\t/* channel AMS */\n\n\tUINT32\tfc;\t\t\t/* fnum,blk:adjusted to sample rate */\n\tUINT8\tkcode;\t\t/* key code:                        */\n\tUINT32\tblock_fnum;\t/* current blk/fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */\n\tUINT8\tMuted;\n} FM_CH;\n\n\ntypedef struct\n{\n\t//running_device *device;\n\tvoid *\t\tparam;\t\t\t\t/* this chip parameter  */\n\tdouble\t\tfreqbase;\t\t\t/* frequency base       */\n\tint\t\t\ttimer_prescaler;\t/* timer prescaler      */\n\tUINT8\t\tirq;\t\t\t\t/* interrupt level      */\n\tUINT8\t\tirqmask;\t\t\t/* irq mask             */\n#if FM_BUSY_FLAG_SUPPORT\n\tTIME_TYPE\tbusy_expiry_time;\t/* expiry time of the busy status */\n#endif\n\tUINT32\t\tclock;\t\t\t\t/* master clock  (Hz)   */\n\tUINT32\t\trate;\t\t\t\t/* sampling rate (Hz)   */\n\tUINT8\t\taddress;\t\t\t/* address register     */\n\tUINT8\t\tstatus;\t\t\t\t/* status flag          */\n\tUINT32\t\tmode;\t\t\t\t/* mode  CSM / 3SLOT    */\n\tUINT8\t\tfn_h;\t\t\t\t/* freq latch           */\n\tUINT8\t\tprescaler_sel;\t\t/* prescaler selector   */\n\tINT32\t\tTA;\t\t\t\t\t/* timer a              */\n\tINT32\t\tTAC;\t\t\t\t/* timer a counter      */\n\tUINT8\t\tTB;\t\t\t\t\t/* timer b              */\n\tINT32\t\tTBC;\t\t\t\t/* timer b counter      */\n\t/* local time tables */\n\tINT32\t\tdt_tab[8][32];\t\t/* DeTune table         */\n\t/* Extention Timer and IRQ handler */\n\tFM_TIMERHANDLER\ttimer_handler;\n\tFM_IRQHANDLER\tIRQ_Handler;\n\tconst ssg_callbacks *SSG;\n} FM_ST;\n\n\n\n/***********************************************************/\n/* OPN unit                                                */\n/***********************************************************/\n\n/* OPN 3slot struct */\ntypedef struct\n{\n\tUINT32  fc[3];\t\t\t/* fnum3,blk3: calculated */\n\tUINT8\tfn_h;\t\t\t/* freq3 latch */\n\tUINT8\tkcode[3];\t\t/* key code */\n\tUINT32\tblock_fnum[3];\t/* current fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */\n\tUINT8   key_csm;        /* CSM mode Key-ON flag */\n} FM_3SLOT;\n\n/* OPN/A/B common state */\ntypedef struct\n{\n\tUINT8\ttype;\t\t\t/* chip type */\n\tFM_ST\tST;\t\t\t\t/* general state */\n\tFM_3SLOT SL3;\t\t\t/* 3 slot mode state */\n\tFM_CH\t*P_CH;\t\t\t/* pointer of CH */\n\tunsigned int pan[6*2];\t/* fm channels output masks (0xffffffff = enable) */\n\n\tUINT32\teg_cnt;\t\t\t/* global envelope generator counter */\n\tUINT32\teg_timer;\t\t/* global envelope generator counter works at frequency = chipclock/144/3 */\n\tUINT32\teg_timer_add;\t/* step of eg_timer */\n\tUINT32\teg_timer_overflow;/* envelope generator timer overlfows every 3 samples (on real chip) */\n\n\n\t/* there are 2048 FNUMs that can be generated using FNUM/BLK registers\n       but LFO works with one more bit of a precision so we really need 4096 elements */\n\tUINT32  fn_table[4096]; /* fnumber->increment counter */\n\tUINT32 fn_max;    /* maximal phase increment (used for phase overflow) */\n\n\t/* LFO */\n\tUINT8   lfo_cnt;            /* current LFO phase (out of 128) */\n\tUINT32  lfo_timer;          /* current LFO phase runs at LFO frequency */\n\tUINT32  lfo_timer_add;      /* step of lfo_timer */\n\tUINT32  lfo_timer_overflow; /* LFO timer overflows every N samples (depends on LFO frequency) */\n\tUINT32  LFO_AM;             /* current LFO AM step */\n\tUINT32  LFO_PM;             /* current LFO PM step */\n\n\tINT32\tm2,c1,c2;\t\t/* Phase Modulation input for operators 2,3,4 */\n\tINT32\tmem;\t\t\t/* one sample delay memory */\n\tINT32\tout_fm[6];\t\t/* outputs of working channels */\n\n} FM_OPN;\n\n/* here's the virtual YM2612 */\ntypedef struct\n{\n\tUINT8\t\tREGS[512];\t\t\t/* registers            */\n\tFM_OPN\t\tOPN;\t\t\t\t/* OPN state            */\n\tFM_CH\t\tCH[6];\t\t\t\t/* channel state        */\n\tUINT8\t\taddr_A1;\t\t\t/* address line A1      */\n\n\t/* dac output (YM2612) */\n\t//int\t\t\tdacen;\n\tUINT8\t\tdacen;\n\tUINT8\t\tdac_test;\n\tINT32\t\tdacout;\n\tUINT8\t\tMuteDAC;\n\t\n\tUINT8\t\tWaveOutMode;\n\tINT32\t\tWaveL;\n\tINT32\t\tWaveR;\n} YM2612;\n\n/* log output level */\n#define LOG_ERR  3      /* ERROR       */\n#define LOG_WAR  2      /* WARNING     */\n#define LOG_INF  1      /* INFORMATION */\n#define LOG_LEVEL LOG_INF\n\n#ifndef __RAINE__\n#define LOG(n,x) do { if( (n)>=LOG_LEVEL ) logerror x; } while (0)\n#endif\n\n/* limitter */\n#define Limit(val, max,min) { \\\n\tif ( val > max )      val = max; \\\n\telse if ( val < min ) val = min; \\\n}\n\nextern UINT8 IsVGMInit;\nstatic UINT8 PseudoSt = 0x00;\n/*#include <stdio.h>\nstatic FILE* hFile;\nstatic UINT32 FileSample;*/\n\n/* status set and IRQ handling */\nINLINE void FM_STATUS_SET(FM_ST *ST,int flag)\n{\n\t/* set status flag */\n\tST->status |= flag;\n\tif ( !(ST->irq) && (ST->status & ST->irqmask) )\n\t{\n\t\tST->irq = 1;\n\t\t/* callback user interrupt handler (IRQ is OFF to ON) */\n\t\tif(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->param,1);\n\t}\n}\n\n/* status reset and IRQ handling */\nINLINE void FM_STATUS_RESET(FM_ST *ST,int flag)\n{\n\t/* reset status flag */\n\tST->status &=~flag;\n\tif ( (ST->irq) && !(ST->status & ST->irqmask) )\n\t{\n\t\tST->irq = 0;\n\t\t/* callback user interrupt handler (IRQ is ON to OFF) */\n\t\tif(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->param,0);\n\t}\n}\n\n/* IRQ mask set */\nINLINE void FM_IRQMASK_SET(FM_ST *ST,int flag)\n{\n\tST->irqmask = flag;\n\t/* IRQ handling check */\n\tFM_STATUS_SET(ST,0);\n\tFM_STATUS_RESET(ST,0);\n}\n\nINLINE void FM_KEYON(FM_OPN *OPN, FM_CH *CH , int s )\n{\n\tFM_SLOT *SLOT = &CH->SLOT[s];\n\n\t// Note by Valley Bell:\n\t//  I assume that the CSM mode shouldn't affect channels\n\t//  other than FM3, so I added a check for it here.\n\tif( !SLOT->key && (!OPN->SL3.key_csm || CH == &OPN->P_CH[3]))\n\t{\n\t\t/* restart Phase Generator */\n\t\tSLOT->phase = 0;\n\n\t\t/* reset SSG-EG inversion flag */\n\t\tSLOT->ssgn = 0;\n\n\t\tif ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/)\n\t\t{\n\t\t\tSLOT->state = (SLOT->volume <= MIN_ATT_INDEX) ? ((SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC) : EG_ATT;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* force attenuation level to 0 */\n\t\t \tSLOT->volume = MIN_ATT_INDEX;\n\n\t\t\t/* directly switch to Decay (or Sustain) */\n\t\t\tSLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;\n\t\t}\n\n\t\t/* recalculate EG output */\n\t\tif ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04)))\n\t\t\tSLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;\n\t\telse\n\t\t\tSLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n\t}\n\n\tSLOT->key = 1;\n}\n\nINLINE void FM_KEYOFF(FM_OPN *OPN, FM_CH *CH , int s )\n{\n\tFM_SLOT *SLOT = &CH->SLOT[s];\n\n\tif (SLOT->key && (!OPN->SL3.key_csm || CH == &OPN->P_CH[3]))\n\t{\n\t\tif (IsVGMInit)\t// workaround for VGMs trimmed with VGMTool\n\t\t{\n\t\t\tSLOT->state = EG_OFF;\n\t\t\tSLOT->volume = MAX_ATT_INDEX;\n\t\t\tSLOT->vol_out= MAX_ATT_INDEX;\n\t\t}\n\t\telse if (SLOT->state>EG_REL)\n\t\t{\n\t\t\tSLOT->state = EG_REL; /* phase -> Release */\n\n\t\t\t/* SSG-EG specific update */\n\t\t\tif (SLOT->ssg&0x08)\n\t\t\t{\n\t\t\t\t/* convert EG attenuation level */\n\t\t\t\tif (SLOT->ssgn ^ (SLOT->ssg&0x04))\n\t\t\t        \tSLOT->volume = (0x200 - SLOT->volume);\n\n\t\t\t\t/* force EG attenuation level */\n\t\t\t\tif (SLOT->volume >= 0x200)\n\t\t\t\t{\n\t\t\t\t\tSLOT->volume = MAX_ATT_INDEX;\n\t\t\t\t\tSLOT->state  = EG_OFF;\n\t\t\t\t}\n\n\t\t\t\t/* recalculate EG output */\n\t\t\t\tSLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n\t\t\t}\n\t\t}\n\t}\n\n\tSLOT->key = 0;\n}\n\nINLINE void FM_KEYON_CSM(FM_OPN *OPN, FM_CH *CH , int s )\n{\n\tFM_SLOT *SLOT = &CH->SLOT[s];\n\n\tif( !SLOT->key && !OPN->SL3.key_csm)\n\t{\n\t\t/* restart Phase Generator */\n\t\tSLOT->phase = 0;\n\n\t\t/* reset SSG-EG inversion flag */\n\t\tSLOT->ssgn = 0;\n\n\t\tif ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/)\n\t\t{\n\t\t\tSLOT->state = (SLOT->volume <= MIN_ATT_INDEX) ? ((SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC) : EG_ATT;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* force attenuation level to 0 */\n\t\t\tSLOT->volume = MIN_ATT_INDEX;\n\n\t\t\t/* directly switch to Decay (or Sustain) */\n\t\t\tSLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;\n\t\t}\n\n\t\t/* recalculate EG output */\n\t\tif ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04)))\n\t\t\tSLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;\n\t\telse\n\t\t\tSLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n\t}\n}\n\nINLINE void FM_KEYOFF_CSM(FM_CH *CH , int s )\n{\n\tFM_SLOT *SLOT = &CH->SLOT[s];\n\tif (!SLOT->key)\n\t{\n\t\tif (IsVGMInit)\n\t\t{\n\t\t\tSLOT->state = EG_OFF;\n\t\t\tSLOT->volume = MAX_ATT_INDEX;\n\t\t\tSLOT->vol_out= MAX_ATT_INDEX;\n\t\t}\n\t\telse if (SLOT->state>EG_REL)\n\t\t{\n\t\t\tSLOT->state = EG_REL; /* phase -> Release */\n\n\t\t\t/* SSG-EG specific update */\n\t\t\tif (SLOT->ssg&0x08)\n\t\t\t{\n\t\t\t\t/* convert EG attenuation level */\n\t\t\t\tif (SLOT->ssgn ^ (SLOT->ssg&0x04))\n\t\t\t\t\tSLOT->volume = (0x200 - SLOT->volume);\n\n\t\t\t\t/* force EG attenuation level */\n\t\t\t\tif (SLOT->volume >= 0x200)\n\t\t\t\t{\n\t\t\t\t\tSLOT->volume = MAX_ATT_INDEX;\n\t\t\t\t\tSLOT->state  = EG_OFF;\n\t\t\t\t}\n\n\t\t\t\t/* recalculate EG output */\n\t\t\t\tSLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/* OPN Mode Register Write */\nINLINE void set_timers( FM_OPN *OPN, FM_ST *ST, void *n, int v )\n{\n\t/* b7 = CSM MODE */\n\t/* b6 = 3 slot mode */\n\t/* b5 = reset b */\n\t/* b4 = reset a */\n\t/* b3 = timer enable b */\n\t/* b2 = timer enable a */\n\t/* b1 = load b */\n\t/* b0 = load a */\n\n\tif ((OPN->ST.mode ^ v) & 0xC0)\n\t{\n\t\t/* phase increment need to be recalculated */\n\t\tOPN->P_CH[2].SLOT[SLOT1].Incr=-1;\n\n\t\t/* CSM mode disabled and CSM key ON active*/\n\t\tif (((v & 0xC0) != 0x80) && OPN->SL3.key_csm)\n\t\t{\n\t\t\t/* CSM Mode Key OFF (verified by Nemesis on real hardware) */\n\t\t\tFM_KEYOFF_CSM(&OPN->P_CH[2],SLOT1);\n\t\t\tFM_KEYOFF_CSM(&OPN->P_CH[2],SLOT2);\n\t\t\tFM_KEYOFF_CSM(&OPN->P_CH[2],SLOT3);\n\t\t\tFM_KEYOFF_CSM(&OPN->P_CH[2],SLOT4);\n\t\t\tOPN->SL3.key_csm = 0;\n\t\t}\n\t}\n\n\t// reset Timer b flag\n\tif( v & 0x20 )\n\t\tFM_STATUS_RESET(ST,0x02);\n\t// reset Timer a flag\n\tif( v & 0x10 )\n\t\tFM_STATUS_RESET(ST,0x01);\n\t// load b\n\tif ((v&2) && !(ST->mode&2))\n\t{\n\t\tST->TBC = ( 256-ST->TB)<<4;\n\t\t/* External timer handler */\n\t\tif (ST->timer_handler) (ST->timer_handler)(n,1,ST->TBC * ST->timer_prescaler,ST->clock);\n\t}\n\t// load a\n\tif ((v&1) && !(ST->mode&1))\n\t{\n\t\tST->TAC = (1024-ST->TA);\n\t\t/* External timer handler */\n\t\tif (ST->timer_handler) (ST->timer_handler)(n,0,ST->TAC * ST->timer_prescaler,ST->clock);\n\t\tST->TAC *= 4096;\n\t}\n\n\tST->mode = v;\n}\n\n\n/* Timer A Overflow */\nINLINE void TimerAOver(FM_ST *ST)\n{\n\t/* set status (if enabled) */\n\tif(ST->mode & 0x04) FM_STATUS_SET(ST,0x01);\n\t/* clear or reload the counter */\n\tST->TAC = (1024-ST->TA);\n\tif (ST->timer_handler) (ST->timer_handler)(ST->param,0,ST->TAC * ST->timer_prescaler,ST->clock);\n\tST->TAC *= 4096;\n}\n/* Timer B Overflow */\nINLINE void TimerBOver(FM_ST *ST)\n{\n\t/* set status (if enabled) */\n\tif(ST->mode & 0x08) FM_STATUS_SET(ST,0x02);\n\t/* clear or reload the counter */\n\tST->TBC = ( 256-ST->TB)<<4;\n\tif (ST->timer_handler) (ST->timer_handler)(ST->param,1,ST->TBC * ST->timer_prescaler,ST->clock);\n}\n\n\n#if FM_INTERNAL_TIMER\n/* ----- internal timer mode , update timer */\n// Valley Bell: defines fixed\n\n/* ---------- calculate timer A ---------- */\n\t#define INTERNAL_TIMER_A(ST,CSM_CH)\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( (ST)->TAC &&  ((ST)->timer_handler==0) )\t\t\\\n\t\t\tif( ((ST)->TAC -= (int)((ST)->freqbase*4096)) <= 0 )\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tTimerAOver( ST );\t\t\t\t\t\t\\\n\t\t\t\t/* CSM mode total level latch and auto key on */\t\\\n\t\t\t\tif( (ST)->mode & 0x80 )\t\t\t\t\t\\\n\t\t\t\t\tCSMKeyControll( OPN, CSM_CH );\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\n/* ---------- calculate timer B ---------- */\n\t#define INTERNAL_TIMER_B(ST,step)\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( (ST)->TBC && ((ST)->timer_handler==0) )\t\t\t\t\\\n\t\t\tif( ((ST)->TBC -= (int)((ST)->freqbase*4096*step)) <= 0 )\t\\\n\t\t\t\tTimerBOver( ST );\t\t\t\t\t\t\t\\\n\t}\n#else /* FM_INTERNAL_TIMER */\n/* external timer mode */\n#define INTERNAL_TIMER_A(ST,CSM_CH)\n#define INTERNAL_TIMER_B(ST,step)\n#endif /* FM_INTERNAL_TIMER */\n\n\n\n#if FM_BUSY_FLAG_SUPPORT\n#define FM_BUSY_CLEAR(ST) ((ST)->busy_expiry_time = UNDEFINED_TIME)\nINLINE UINT8 FM_STATUS_FLAG(FM_ST *ST)\n{\n\tif( COMPARE_TIMES(ST->busy_expiry_time, UNDEFINED_TIME) != 0 )\n\t{\n\t\tif (COMPARE_TIMES(ST->busy_expiry_time, FM_GET_TIME_NOW(ST->device->machine)) > 0)\n\t\t\treturn ST->status | 0x80;\t/* with busy */\n\t\t/* expire */\n\t\tFM_BUSY_CLEAR(ST);\n\t}\n\treturn ST->status;\n}\nINLINE void FM_BUSY_SET(FM_ST *ST,int busyclock )\n{\n\tTIME_TYPE expiry_period = MULTIPLY_TIME_BY_INT(ATTOTIME_IN_HZ(ST->clock), busyclock * ST->timer_prescaler);\n\tST->busy_expiry_time = ADD_TIMES(FM_GET_TIME_NOW(ST->device->machine), expiry_period);\n}\n#else\n#define FM_STATUS_FLAG(ST) ((ST)->status)\n#define FM_BUSY_SET(ST,bclock) {}\n#define FM_BUSY_CLEAR(ST) {}\n#endif\n\n\n/* set algorithm connection */\nINLINE void setup_connection( FM_OPN *OPN, FM_CH *CH, int ch )\n{\n\tINT32 *carrier = &OPN->out_fm[ch];\n\n\tINT32 **om1 = &CH->connect1;\n\tINT32 **om2 = &CH->connect3;\n\tINT32 **oc1 = &CH->connect2;\n\n\tINT32 **memc = &CH->mem_connect;\n\n\tswitch( CH->ALGO )\n\t{\n\tcase 0:\n\t\t/* M1---C1---MEM---M2---C2---OUT */\n\t\t*om1 = &OPN->c1;\n\t\t*oc1 = &OPN->mem;\n\t\t*om2 = &OPN->c2;\n\t\t*memc= &OPN->m2;\n\t\tbreak;\n\tcase 1:\n\t\t/* M1------+-MEM---M2---C2---OUT */\n\t\t/*      C1-+                     */\n\t\t*om1 = &OPN->mem;\n\t\t*oc1 = &OPN->mem;\n\t\t*om2 = &OPN->c2;\n\t\t*memc= &OPN->m2;\n\t\tbreak;\n\tcase 2:\n\t\t/* M1-----------------+-C2---OUT */\n\t\t/*      C1---MEM---M2-+          */\n\t\t*om1 = &OPN->c2;\n\t\t*oc1 = &OPN->mem;\n\t\t*om2 = &OPN->c2;\n\t\t*memc= &OPN->m2;\n\t\tbreak;\n\tcase 3:\n\t\t/* M1---C1---MEM------+-C2---OUT */\n\t\t/*                 M2-+          */\n\t\t*om1 = &OPN->c1;\n\t\t*oc1 = &OPN->mem;\n\t\t*om2 = &OPN->c2;\n\t\t*memc= &OPN->c2;\n\t\tbreak;\n\tcase 4:\n\t\t/* M1---C1-+-OUT */\n\t\t/* M2---C2-+     */\n\t\t/* MEM: not used */\n\t\t*om1 = &OPN->c1;\n\t\t*oc1 = carrier;\n\t\t*om2 = &OPN->c2;\n\t\t*memc= &OPN->mem;\t/* store it anywhere where it will not be used */\n\t\tbreak;\n\tcase 5:\n\t\t/*    +----C1----+     */\n\t\t/* M1-+-MEM---M2-+-OUT */\n\t\t/*    +----C2----+     */\n\t\t*om1 = 0;\t/* special mark */\n\t\t*oc1 = carrier;\n\t\t*om2 = carrier;\n\t\t*memc= &OPN->m2;\n\t\tbreak;\n\tcase 6:\n\t\t/* M1---C1-+     */\n\t\t/*      M2-+-OUT */\n\t\t/*      C2-+     */\n\t\t/* MEM: not used */\n\t\t*om1 = &OPN->c1;\n\t\t*oc1 = carrier;\n\t\t*om2 = carrier;\n\t\t*memc= &OPN->mem;\t/* store it anywhere where it will not be used */\n\t\tbreak;\n\tcase 7:\n\t\t/* M1-+     */\n\t\t/* C1-+-OUT */\n\t\t/* M2-+     */\n\t\t/* C2-+     */\n\t\t/* MEM: not used*/\n\t\t*om1 = carrier;\n\t\t*oc1 = carrier;\n\t\t*om2 = carrier;\n\t\t*memc= &OPN->mem;\t/* store it anywhere where it will not be used */\n\t\tbreak;\n\t}\n\n\tCH->connect4 = carrier;\n}\n\n/* set detune & multiple */\nINLINE void set_det_mul(FM_ST *ST,FM_CH *CH,FM_SLOT *SLOT,int v)\n{\n\tSLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1;\n\tSLOT->DT  = ST->dt_tab[(v>>4)&7];\n\tCH->SLOT[SLOT1].Incr=-1;\n}\n\n/* set total level */\nINLINE void set_tl(FM_CH *CH,FM_SLOT *SLOT , int v)\n{\n\tSLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */\n\n\t/* recalculate EG output */\n\tif ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04)) && (SLOT->state > EG_REL))\n\t\tSLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;\n\telse\n\t\tSLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n}\n\n/* set attack rate & key scale  */\nINLINE void set_ar_ksr(UINT8 type, FM_CH *CH,FM_SLOT *SLOT,int v)\n{\n\tUINT8 old_KSR = SLOT->KSR;\n\n\tSLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\n\n\tSLOT->KSR = 3-(v>>6);\n\tif (SLOT->KSR != old_KSR)\n\t{\n\t\tCH->SLOT[SLOT1].Incr=-1;\n\t}\n\n\t/* Even if it seems unnecessary, in some odd case, KSR and KC are both modified   */\n\t/* and could result in SLOT->kc remaining unchanged.                              */\n\t/* In such case, AR values would not be recalculated despite SLOT->ar has changed */\n\t/* This fixes the introduction music of Batman & Robin    (Eke-Eke)               */\n\tif ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/)\n\t{\n\t\tSLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar  + SLOT->ksr ];\n\t\tSLOT->eg_sel_ar = eg_rate_select2612[SLOT->ar  + SLOT->ksr ];\n\t}\n\telse\n\t{\n\t\tSLOT->eg_sh_ar  = 0;\n\t\tSLOT->eg_sel_ar = 18*RATE_STEPS;\t/* verified by Nemesis on real hardware */\n\t}\n}\n\n/* set decay rate */\nINLINE void set_dr(UINT8 type, FM_SLOT *SLOT,int v)\n{\n\tSLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\n\n\tSLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];\n\tSLOT->eg_sel_d1r= eg_rate_select2612[SLOT->d1r + SLOT->ksr];\n}\n\n/* set sustain rate */\nINLINE void set_sr(UINT8 type, FM_SLOT *SLOT,int v)\n{\n\tSLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\n\n\tSLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];\n\tSLOT->eg_sel_d2r= eg_rate_select2612[SLOT->d2r + SLOT->ksr];\n}\n\n/* set release rate */\nINLINE void set_sl_rr(UINT8 type, FM_SLOT *SLOT,int v)\n{\n\tSLOT->sl = sl_table[ v>>4 ];\n\n\t/* check EG state changes */\n\tif ((SLOT->state == EG_DEC) && (SLOT->volume >= (INT32)(SLOT->sl)))\n\t\tSLOT->state = EG_SUS;\n\n\tSLOT->rr  = 34 + ((v&0x0f)<<2);\n\n\tSLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr  + SLOT->ksr];\n\tSLOT->eg_sel_rr = eg_rate_select2612[SLOT->rr  + SLOT->ksr];\n}\n\n/* advance LFO to next sample */\nINLINE void advance_lfo(FM_OPN *OPN)\n{\n\tif (OPN->lfo_timer_overflow)   /* LFO enabled ? */\n\t{\n\t\t/* increment LFO timer */\n\t\tOPN->lfo_timer +=  OPN->lfo_timer_add;\n\n\t\t/* when LFO is enabled, one level will last for 108, 77, 71, 67, 62, 44, 8 or 5 samples */\n\t\twhile (OPN->lfo_timer >= OPN->lfo_timer_overflow)\n\t\t{\n\t\t\tOPN->lfo_timer -= OPN->lfo_timer_overflow;\n\n\t\t\t/* There are 128 LFO steps */\n\t\t\tOPN->lfo_cnt = ( OPN->lfo_cnt + 1 ) & 127;\n\n\t\t\t// Valley Bell: Replaced old code (non-inverted triangle) with\n\t\t\t// the one from Genesis Plus GX 1.71.\n\t\t\t/* triangle (inverted) */\n\t\t\t/* AM: from 126 to 0 step -2, 0 to 126 step +2 */\n\t\t\tif (OPN->lfo_cnt<64)\n\t\t\t\tOPN->LFO_AM = (OPN->lfo_cnt ^ 63) << 1;\n\t\t\telse\n\t\t\t\tOPN->LFO_AM = (OPN->lfo_cnt & 63) << 1;\n\n\t\t\t/* PM works with 4 times slower clock */\n\t\t\tOPN->LFO_PM = OPN->lfo_cnt >> 2;\n\t\t}\n\t}\n}\n\nINLINE void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)\n{\n\t//unsigned int out;\n\tunsigned int i = 4; /* four operators per channel */\n\n\tdo\n\t{\n\t\tswitch(SLOT->state)\n\t\t{\n\t\t\tcase EG_ATT:    /* attack phase */\n\t\t\tif (!(OPN->eg_cnt & ((1<<SLOT->eg_sh_ar)-1)))\n\t\t\t{\n\t\t\t        /* update attenuation level */\n\t\t\t        SLOT->volume += (~SLOT->volume * (eg_inc[SLOT->eg_sel_ar + ((OPN->eg_cnt>>SLOT->eg_sh_ar)&7)]))>>4;\n\n\t\t\t        /* check phase transition*/\n\t\t\t        if (SLOT->volume <= MIN_ATT_INDEX)\n\t\t\t        {\n\t\t\t\t        SLOT->volume = MIN_ATT_INDEX;\n\t\t\t\t        SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC; /* special case where SL=0 */\n\t\t\t        }\n\n\t\t\t        /* recalculate EG output */\n\t\t\t        if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04)))  /* SSG-EG Output Inversion */\n\t\t\t\t\tSLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;\n\t\t\t        else\n\t\t\t\t        SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_DEC:  /* decay phase */\n\t\t\tif (!(OPN->eg_cnt & ((1<<SLOT->eg_sh_d1r)-1)))\n\t\t\t{\n\t\t\t        /* SSG EG type */\n\t\t\t        if (SLOT->ssg&0x08)\n\t\t\t        {\n\t\t\t\t        /* update attenuation level */\n\t\t\t\t        if (SLOT->volume < 0x200)\n\t\t\t\t\t{\n\t\t\t\t\t\tSLOT->volume += 4 * eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)];\n\n\t\t\t\t\t\t/* recalculate EG output */\n\t\t\t\t\t\tif (SLOT->ssgn ^ (SLOT->ssg&0x04))   /* SSG-EG Output Inversion */\n\t\t\t\t\t\t\tSLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tSLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n\t\t\t\t\t}\n\n\t\t\t        }\n\t\t\t        else\n\t\t\t        {\n\t\t\t\t\t/* update attenuation level */\n\t\t\t\t\tSLOT->volume += eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)];\n\n\t\t\t\t\t/* recalculate EG output */\n\t\t\t\t\tSLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n\t\t\t        }\n\n\t\t\t        /* check phase transition*/\n\t\t\t        if (SLOT->volume >= (INT32)(SLOT->sl))\n\t\t\t\t        SLOT->state = EG_SUS;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_SUS:  /* sustain phase */\n\t\t\tif (!(OPN->eg_cnt & ((1<<SLOT->eg_sh_d2r)-1)))\n\t\t\t{\n\t\t\t        /* SSG EG type */\n\t\t\t        if (SLOT->ssg&0x08)\n\t\t\t        {\n\t\t\t\t\t/* update attenuation level */\n\t\t\t\t\tif (SLOT->volume < 0x200)\n\t\t\t\t\t{\n\t\t\t\t\t\tSLOT->volume += 4 * eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)];\n\n\t\t\t\t\t\t/* recalculate EG output */\n\t\t\t\t\t\tif (SLOT->ssgn ^ (SLOT->ssg&0x04))   /* SSG-EG Output Inversion */\n\t\t\t\t\t\t\tSLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tSLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n\t\t\t\t\t}\n\t\t\t        }\n\t\t\t        else\n\t\t\t        {\n\t\t\t\t        /* update attenuation level */\n\t\t\t\t        SLOT->volume += eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)];\n\n\t\t\t\t        /* check phase transition*/\n\t\t\t\t        if ( SLOT->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t        SLOT->volume = MAX_ATT_INDEX;\n\t\t\t\t        /* do not change SLOT->state (verified on real chip) */\n\n\t\t\t\t        /* recalculate EG output */\n\t\t\t\t        SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n\t\t\t        }\n\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_REL:  /* release phase */\n\t\t\tif (!(OPN->eg_cnt & ((1<<SLOT->eg_sh_rr)-1)))\n\t\t\t{\n\t\t\t        /* SSG EG type */\n\t\t\t        if (SLOT->ssg&0x08)\n\t\t\t        {\n\t\t\t\t        /* update attenuation level */\n\t\t\t\t        if (SLOT->volume < 0x200)\n\t\t\t\t\t        SLOT->volume += 4 * eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)];\n\t\t\t\t\t/* check phase transition */\n\t\t\t\t\tif (SLOT->volume >= 0x200)\n\t\t\t\t\t{\n\t\t\t\t\t\tSLOT->volume = MAX_ATT_INDEX;\n\t\t\t\t\t\tSLOT->state = EG_OFF;\n\t\t\t\t\t}\n\t\t\t        }\n\t\t\t        else\n\t\t\t        {\n\t\t\t\t        /* update attenuation level */\n\t\t\t\t        SLOT->volume += eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)];\n\n\t\t\t\t        /* check phase transition*/\n\t\t\t\t        if (SLOT->volume >= MAX_ATT_INDEX)\n\t\t\t\t        {\n\t\t\t\t\t        SLOT->volume = MAX_ATT_INDEX;\n\t\t\t\t\t        SLOT->state = EG_OFF;\n\t\t\t\t        }\n\t\t\t        }\n\n\t\t\t        /* recalculate EG output */\n\t\t\t        SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t// Valley Bell: These few lines are missing in Genesis Plus GX' ym2612 core file.\n\t\t//              Disabling them fixes the SSG-EG.\n\t\t// Additional Note: Asterix and the Great Rescue: Level 1 sounds \"better\" with these lines,\n\t\t//\t\t\t\t\tbut less accurate.\n\t\t/*out = ((UINT32)SLOT->volume);\n\n\t\t// negate output (changes come from alternate bit, init comes from attack bit)\n\t\tif ((SLOT->ssg&0x08) && (SLOT->ssgn&2) && (SLOT->state > EG_REL))\n\t\t\tout ^= MAX_ATT_INDEX;\n\n\t\t// we need to store the result here because we are going to change ssgn\n\t\t//  in next instruction\n\t\tSLOT->vol_out = out + SLOT->tl;*/\n\n\t\tSLOT++;\n\t\ti--;\n\t}while (i);\n\n}\n\n/* SSG-EG update process */\n/* The behavior is based upon Nemesis tests on real hardware */\n/* This is actually executed before each samples */\nINLINE void update_ssg_eg_channel(FM_SLOT *SLOT)\n{\n\tunsigned int i = 4; /* four operators per channel */\n\n\tdo\n\t{\n\t\t/* detect SSG-EG transition */\n\t\t/* this is not required during release phase as the attenuation has been forced to MAX and output invert flag is not used */\n\t\t/* if an Attack Phase is programmed, inversion can occur on each sample */\n\t\tif ((SLOT->ssg & 0x08) && (SLOT->volume >= 0x200) && (SLOT->state > EG_REL))\n\t\t{\n\t\t\tif (SLOT->ssg & 0x01)  /* bit 0 = hold SSG-EG */\n\t\t\t{\n\t\t\t\t/* set inversion flag */\n\t\t\t        if (SLOT->ssg & 0x02)\n\t\t\t\t       SLOT->ssgn = 4;\n\n\t\t\t\t/* force attenuation level during decay phases */\n\t\t\t\tif ((SLOT->state != EG_ATT) && !(SLOT->ssgn ^ (SLOT->ssg & 0x04)))\n\t\t\t\t\tSLOT->volume  = MAX_ATT_INDEX;\n\t\t\t}\n\t\t\telse  /* loop SSG-EG */\n\t\t\t{\n\t\t\t\t/* toggle output inversion flag or reset Phase Generator */\n\t\t\t        if (SLOT->ssg & 0x02)\n\t\t\t        \tSLOT->ssgn ^= 4;\n\t\t\t        else\n\t\t\t        \tSLOT->phase = 0;\n\n\t\t\t\t/* same as Key ON */\n\t\t\t\tif (SLOT->state != EG_ATT)\n\t\t\t\t{\n\t\t\t\t\tif ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/)\n\t\t\t\t\t{\n\t\t\t\t\t\tSLOT->state = (SLOT->volume <= MIN_ATT_INDEX) ? ((SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC) : EG_ATT;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Attack Rate is maximal: directly switch to Decay or Substain */\n\t\t\t\t\t\tSLOT->volume = MIN_ATT_INDEX;\n\t\t\t\t\t\tSLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* recalculate EG output */\n\t\t\tif (SLOT->ssgn ^ (SLOT->ssg&0x04))\n\t\t\t\tSLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;\n\t\t\telse\n\t\t\t\tSLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n\t\t}\n\n\t\t/* next slot */\n\t\tSLOT++;\n\t\ti--;\n\t} while (i);\n}\n\n\nINLINE void update_phase_lfo_slot(FM_OPN *OPN, FM_SLOT *SLOT, INT32 pms, UINT32 block_fnum)\n{\n\tUINT32 fnum_lfo   = ((block_fnum & 0x7f0) >> 4) * 32 * 8;\n\tINT32  lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + pms + OPN->LFO_PM ];\n\n\tblock_fnum = block_fnum*2 + lfo_fn_table_index_offset;\n\n\tif (lfo_fn_table_index_offset)    /* LFO phase modulation active */\n\t{\n\t\tUINT8 blk = (block_fnum&0x7000) >> 12;\n\t\tUINT32 fn  = block_fnum & 0xfff;\n\n\t\t/* recalculate keyscale code */\n\t\t/*int kc = (blk<<2) | opn_fktable[fn >> 7];*/\n\t\t/* This really stupid bug caused a read outside of the\n\t\t   array [size 0x10] and returned invalid values.\n\t\t   This caused an annoying vibrato for some notes.\n\t\t   (Note: seems to be a copy-and-paste from OPNWriteReg -> case 0xA0)\n\t\t    Why are MAME cores always SOO buggy ?! */\n\t\t/* Oh, and before I forget: it's correct in fm.c */\n\t\tint kc = (blk<<2) | opn_fktable[fn >> 8];\n\t\t/* Thanks to Blargg - his patch that helped me to find this bug */\n\n\t\t/* recalculate (frequency) phase increment counter */\n\t\tint fc = (OPN->fn_table[fn]>>(7-blk)) + SLOT->DT[kc];\n\n\t\t/* (frequency) phase overflow (credits to Nemesis) */\n\t\tif (fc < 0) fc += OPN->fn_max;\n\n\t\t/* update phase */\n\t\tSLOT->phase += (fc * SLOT->mul) >> 1;\n\t}\n\telse    /* LFO phase modulation  = zero */\n\t{\n\t\tSLOT->phase += SLOT->Incr;\n\t}\n}\n\nINLINE void update_phase_lfo_channel(FM_OPN *OPN, FM_CH *CH)\n{\n\tUINT32 block_fnum = CH->block_fnum;\n\n\tUINT32 fnum_lfo  = ((block_fnum & 0x7f0) >> 4) * 32 * 8;\n\tINT32  lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + CH->pms + OPN->LFO_PM ];\n\n\tblock_fnum = block_fnum*2 + lfo_fn_table_index_offset;\n\n\tif (lfo_fn_table_index_offset)    /* LFO phase modulation active */\n\t{\n\t\tUINT8 blk = (block_fnum&0x7000) >> 12;\n\t\tUINT32 fn  = block_fnum & 0xfff;\n\n\t\t/* recalculate keyscale code */\n\t\t/*int kc = (blk<<2) | opn_fktable[fn >> 7];*/\n\t\t/* the same stupid bug as above */\n\t\tint kc = (blk<<2) | opn_fktable[fn >> 8];\n\n\t\t/* recalculate (frequency) phase increment counter */\n\t\tint fc = (OPN->fn_table[fn]>>(7-blk));\n\n\t\t/* (frequency) phase overflow (credits to Nemesis) */\n\t\tint finc = fc + CH->SLOT[SLOT1].DT[kc];\n\t\tif (finc < 0) finc += OPN->fn_max;\n\t\tCH->SLOT[SLOT1].phase += (finc*CH->SLOT[SLOT1].mul) >> 1;\n\n\t\tfinc = fc + CH->SLOT[SLOT2].DT[kc];\n\t\tif (finc < 0) finc += OPN->fn_max;\n\t\tCH->SLOT[SLOT2].phase += (finc*CH->SLOT[SLOT2].mul) >> 1;\n\n\t\tfinc = fc + CH->SLOT[SLOT3].DT[kc];\n\t\tif (finc < 0) finc += OPN->fn_max;\n\t\tCH->SLOT[SLOT3].phase += (finc*CH->SLOT[SLOT3].mul) >> 1;\n\n\t\tfinc = fc + CH->SLOT[SLOT4].DT[kc];\n\t\tif (finc < 0) finc += OPN->fn_max;\n\t\tCH->SLOT[SLOT4].phase += (finc*CH->SLOT[SLOT4].mul) >> 1;\n\t}\n\telse    /* LFO phase modulation  = zero */\n\t{\n\t        CH->SLOT[SLOT1].phase += CH->SLOT[SLOT1].Incr;\n\t        CH->SLOT[SLOT2].phase += CH->SLOT[SLOT2].Incr;\n\t        CH->SLOT[SLOT3].phase += CH->SLOT[SLOT3].Incr;\n\t        CH->SLOT[SLOT4].phase += CH->SLOT[SLOT4].Incr;\n\t}\n}\n\n/* update phase increment and envelope generator */\nINLINE void refresh_fc_eg_slot(FM_OPN *OPN, FM_SLOT *SLOT , int fc , int kc )\n{\n\tint ksr = kc >> SLOT->KSR;\n\n\tfc += SLOT->DT[kc];\n\n\t/* detects frequency overflow (credits to Nemesis) */\n\tif (fc < 0) fc += OPN->fn_max;\n\n\t/* (frequency) phase increment counter */\n\tSLOT->Incr = (fc * SLOT->mul) >> 1;\n\n\tif( SLOT->ksr != ksr )\n\t{\n\t\tSLOT->ksr = ksr;\n\n\t\t/* calculate envelope generator rates */\n\t\tif ((SLOT->ar + SLOT->ksr) < 32+62)\n\t\t{\n\t\t\tSLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar  + SLOT->ksr ];\n\t\t\tSLOT->eg_sel_ar = eg_rate_select2612[SLOT->ar  + SLOT->ksr ];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSLOT->eg_sh_ar  = 0;\n\t\t\tSLOT->eg_sel_ar = 18*RATE_STEPS; /* verified by Nemesis on real hardware (Attack phase is blocked) */\n\t\t}\n\n\t\tSLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];\n\t\tSLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];\n\t\tSLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr  + SLOT->ksr];\n\n\t\tSLOT->eg_sel_d1r= eg_rate_select2612[SLOT->d1r + SLOT->ksr];\n\t\tSLOT->eg_sel_d2r= eg_rate_select2612[SLOT->d2r + SLOT->ksr];\n\t\tSLOT->eg_sel_rr = eg_rate_select2612[SLOT->rr  + SLOT->ksr];\n\t}\n}\n\n/* update phase increment counters */\nINLINE void refresh_fc_eg_chan(FM_OPN *OPN, FM_CH *CH )\n{\n\tif( CH->SLOT[SLOT1].Incr==-1)\n\t{\n\t\tint fc = CH->fc;\n\t\tint kc = CH->kcode;\n\t\trefresh_fc_eg_slot(OPN, &CH->SLOT[SLOT1] , fc , kc );\n\t\trefresh_fc_eg_slot(OPN, &CH->SLOT[SLOT2] , fc , kc );\n\t\trefresh_fc_eg_slot(OPN, &CH->SLOT[SLOT3] , fc , kc );\n\t\trefresh_fc_eg_slot(OPN, &CH->SLOT[SLOT4] , fc , kc );\n\t}\n}\n\n#define volume_calc(OP) ((OP)->vol_out + (AM & (OP)->AMmask))\n\nINLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm)\n{\n  UINT32 p;\n\n  p = (env<<3) + sin_tab[ ( ((signed int)((phase & ~FREQ_MASK) + (pm<<15))) >> FREQ_SH ) & SIN_MASK ];\n\n  if (p >= TL_TAB_LEN)\n    return 0;\n  return tl_tab[p];\n}\n\nINLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)\n{\n  UINT32 p;\n\n  p = (env<<3) + sin_tab[ ( ((signed int)((phase & ~FREQ_MASK) + pm      )) >> FREQ_SH ) & SIN_MASK ];\n\n  if (p >= TL_TAB_LEN)\n    return 0;\n  return tl_tab[p];\n}\n\nINLINE void chan_calc(YM2612 *F2612, FM_OPN *OPN, FM_CH *CH)\n{\n  UINT32 AM = OPN->LFO_AM >> CH->ams;\n  unsigned int eg_out;\n\n  if (CH->Muted)\n    return;\n\n  OPN->m2 = OPN->c1 = OPN->c2 = OPN->mem = 0;\n\n  *CH->mem_connect = CH->mem_value;  /* restore delayed sample (MEM) value to m2 or c2 */\n\n  eg_out = volume_calc(&CH->SLOT[SLOT1]);\n  {\n    INT32 out = CH->op1_out[0] + CH->op1_out[1];\n    CH->op1_out[0] = CH->op1_out[1];\n\n    if( !CH->connect1 )\n    {\n      /* algorithm 5  */\n      OPN->mem = OPN->c1 = OPN->c2 = CH->op1_out[0];\n    }\n    else\n    {\n      /* other algorithms */\n      *CH->connect1 += CH->op1_out[0];\n    }\n\n\n    CH->op1_out[1] = 0;\n    if( eg_out < ENV_QUIET )  /* SLOT 1 */\n    {\n      if (!CH->FB)\n        out=0;\n\n      CH->op1_out[1] = op_calc1(CH->SLOT[SLOT1].phase, eg_out, (out<<CH->FB) );\n    }\n  }\n\n  eg_out = volume_calc(&CH->SLOT[SLOT3]);\n  if( eg_out < ENV_QUIET )    /* SLOT 3 */\n    *CH->connect3 += op_calc(CH->SLOT[SLOT3].phase, eg_out, OPN->m2);\n\n  eg_out = volume_calc(&CH->SLOT[SLOT2]);\n  if( eg_out < ENV_QUIET )    /* SLOT 2 */\n    *CH->connect2 += op_calc(CH->SLOT[SLOT2].phase, eg_out, OPN->c1);\n\n  eg_out = volume_calc(&CH->SLOT[SLOT4]);\n  if( eg_out < ENV_QUIET )    /* SLOT 4 */\n    *CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, OPN->c2);\n\n\n  /* store current MEM */\n  CH->mem_value = OPN->mem;\n\n  /* update phase counters AFTER output calculations */\n  if(CH->pms)\n  {\n    /* add support for 3 slot mode */\n    if ((OPN->ST.mode & 0xC0) && (CH == &F2612->CH[2]))\n    {\n      update_phase_lfo_slot(OPN, &CH->SLOT[SLOT1], CH->pms, OPN->SL3.block_fnum[1]);\n      update_phase_lfo_slot(OPN, &CH->SLOT[SLOT2], CH->pms, OPN->SL3.block_fnum[2]);\n      update_phase_lfo_slot(OPN, &CH->SLOT[SLOT3], CH->pms, OPN->SL3.block_fnum[0]);\n      update_phase_lfo_slot(OPN, &CH->SLOT[SLOT4], CH->pms, CH->block_fnum);\n    }\n    else update_phase_lfo_channel(OPN, CH);\n  }\n  else  /* no LFO phase modulation */\n  {\n    CH->SLOT[SLOT1].phase += CH->SLOT[SLOT1].Incr;\n    CH->SLOT[SLOT2].phase += CH->SLOT[SLOT2].Incr;\n    CH->SLOT[SLOT3].phase += CH->SLOT[SLOT3].Incr;\n    CH->SLOT[SLOT4].phase += CH->SLOT[SLOT4].Incr;\n  }\n}\n\nstatic void FMCloseTable( void )\n{\n#ifdef SAVE_SAMPLE\n\tfclose(sample[0]);\n#endif\n\treturn;\n}\n\n\n/* CSM Key Controll */\nINLINE void CSMKeyControll(FM_OPN *OPN, FM_CH *CH)\n{\n\t/* all key ON (verified by Nemesis on real hardware) */\n\tFM_KEYON_CSM(OPN,CH,SLOT1);\n\tFM_KEYON_CSM(OPN,CH,SLOT2);\n\tFM_KEYON_CSM(OPN,CH,SLOT3);\n\tFM_KEYON_CSM(OPN,CH,SLOT4);\n\tOPN->SL3.key_csm = 1;\n}\n\n#ifdef __STATE_H__\n/* FM channel save , internal state only */\nstatic void FMsave_state_channel(running_device *device,FM_CH *CH,int num_ch)\n{\n\tint slot , ch;\n\n\tfor(ch=0;ch<num_ch;ch++,CH++)\n\t{\n\t\t/* channel */\n\t\tstate_save_register_device_item_array(device, ch, CH->op1_out);\n\t\tstate_save_register_device_item(device, ch, CH->fc);\n\t\t/* slots */\n\t\tfor(slot=0;slot<4;slot++)\n\t\t{\n\t\t\tFM_SLOT *SLOT = &CH->SLOT[slot];\n\t\t\tstate_save_register_device_item(device, ch * 4 + slot, SLOT->phase);\n\t\t\tstate_save_register_device_item(device, ch * 4 + slot, SLOT->state);\n\t\t\tstate_save_register_device_item(device, ch * 4 + slot, SLOT->volume);\n\t\t}\n\t}\n}\n\nstatic void FMsave_state_st(running_device *device,FM_ST *ST)\n{\n#if FM_BUSY_FLAG_SUPPORT\n\tstate_save_register_device_item(device, 0, ST->busy_expiry_time.seconds );\n\tstate_save_register_device_item(device, 0, ST->busy_expiry_time.attoseconds );\n#endif\n\tstate_save_register_device_item(device, 0, ST->address );\n\tstate_save_register_device_item(device, 0, ST->irq     );\n\tstate_save_register_device_item(device, 0, ST->irqmask );\n\tstate_save_register_device_item(device, 0, ST->status  );\n\tstate_save_register_device_item(device, 0, ST->mode    );\n\tstate_save_register_device_item(device, 0, ST->prescaler_sel );\n\tstate_save_register_device_item(device, 0, ST->fn_h );\n\tstate_save_register_device_item(device, 0, ST->TA   );\n\tstate_save_register_device_item(device, 0, ST->TAC  );\n\tstate_save_register_device_item(device, 0, ST->TB  );\n\tstate_save_register_device_item(device, 0, ST->TBC  );\n}\n#endif /* _STATE_H */\n\n#if BUILD_OPN\n/* write a OPN mode register 0x20-0x2f */\nstatic void OPNWriteMode(FM_OPN *OPN, int r, int v)\n{\n\tUINT8 c;\n\tFM_CH *CH;\n\n\tswitch(r)\n\t{\n\tcase 0x21:\t/* Test */\n\t\tbreak;\n\tcase 0x22:\t/* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */\n\t\tif (v&8) /* LFO enabled ? */\n\t\t{\n\t\t\t/*if (!OPN->lfo_timer_overflow)\n\t\t\t{\n\t\t\t\t// restart LFO\n\t\t\t\tOPN->lfo_cnt   = 0;\n\t\t\t\tOPN->lfo_timer = 0;\n\t\t\t\tOPN->LFO_AM    = 0;\n\t\t\t\tOPN->LFO_PM    = 0;\n\t\t\t}*/\n\n\t\t\tOPN->lfo_timer_overflow = lfo_samples_per_step[v&7] << LFO_SH;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Valley Bell: Ported from Genesis Plus GX 1.71\n\t\t\t// hold LFO waveform in reset state\n\t\t\tOPN->lfo_timer_overflow = 0;\n\t\t\tOPN->lfo_timer = 0;\n\t\t\tOPN->lfo_cnt = 0;\n\t\t\t\n\t\t\t\n\t\t\tOPN->LFO_PM = 0;\n\t\t\tOPN->LFO_AM = 126;\n\t\t\t//OPN->lfo_timer_overflow = 0;\n\t\t}\n\t\tbreak;\n\tcase 0x24:\t/* timer A High 8*/\n\t\tOPN->ST.TA = (OPN->ST.TA & 0x03)|(((int)v)<<2);\n\t\tbreak;\n\tcase 0x25:\t/* timer A Low 2*/\n\t\tOPN->ST.TA = (OPN->ST.TA & 0x3fc)|(v&3);\n\t\tbreak;\n\tcase 0x26:\t/* timer B */\n\t\tOPN->ST.TB = v;\n\t\tbreak;\n\tcase 0x27:\t/* mode, timer control */\n\t\tset_timers( OPN, &(OPN->ST),OPN->ST.param,v );\n\t\tbreak;\n\tcase 0x28:\t/* key on / off */\n\t\tc = v & 0x03;\n\t\tif( c == 3 ) break;\n\t\tif( (v&0x04) && (OPN->type & TYPE_6CH) ) c+=3;\n\t\tCH = OPN->P_CH;\n\t\tCH = &CH[c];\n\t\tif(v&0x10) FM_KEYON(OPN,CH,SLOT1); else FM_KEYOFF(OPN,CH,SLOT1);\n\t\tif(v&0x20) FM_KEYON(OPN,CH,SLOT2); else FM_KEYOFF(OPN,CH,SLOT2);\n\t\tif(v&0x40) FM_KEYON(OPN,CH,SLOT3); else FM_KEYOFF(OPN,CH,SLOT3);\n\t\tif(v&0x80) FM_KEYON(OPN,CH,SLOT4); else FM_KEYOFF(OPN,CH,SLOT4);\n\t\tbreak;\n\t}\n}\n\n/* write a OPN register (0x30-0xff) */\nstatic void OPNWriteReg(FM_OPN *OPN, int r, int v)\n{\n\tFM_CH *CH;\n\tFM_SLOT *SLOT;\n\n\tUINT8 c = OPN_CHAN(r);\n\n\tif (c == 3) return; /* 0xX3,0xX7,0xXB,0xXF */\n\n\tif (r >= 0x100) c+=3;\n\n\tCH = OPN->P_CH;\n\tCH = &CH[c];\n\n\tSLOT = &(CH->SLOT[OPN_SLOT(r)]);\n\n\tswitch( r & 0xf0 ) {\n\tcase 0x30:\t/* DET , MUL */\n\t\tset_det_mul(&OPN->ST,CH,SLOT,v);\n\t\tbreak;\n\n\tcase 0x40:\t/* TL */\n\t\tset_tl(CH,SLOT,v);\n\t\tbreak;\n\n\tcase 0x50:\t/* KS, AR */\n\t\tset_ar_ksr(OPN->type,CH,SLOT,v);\n\t\tbreak;\n\n\tcase 0x60:\t/* bit7 = AM ENABLE, DR */\n\t\tset_dr(OPN->type, SLOT,v);\n\n\t\tif(OPN->type & TYPE_LFOPAN) /* YM2608/2610/2610B/2612 */\n\t\t{\n\t\t\tSLOT->AMmask = (v&0x80) ? ~0 : 0;\n\t\t}\n\t\tbreak;\n\n\tcase 0x70:\t/*     SR */\n\t\tset_sr(OPN->type,SLOT,v);\n\t\tbreak;\n\n\tcase 0x80:\t/* SL, RR */\n\t\tset_sl_rr(OPN->type,SLOT,v);\n\t\tbreak;\n\n\tcase 0x90:\t/* SSG-EG */\n\t\tSLOT->ssg  =  v&0x0f;\n\n\t      /* recalculate EG output */\n\t\tif (SLOT->state > EG_REL)\n\t\t{\n\t\t\tif ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04)))\n\t\t\t\tSLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl;\n\t\t\telse\n\t\t\t\tSLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;\n\t\t}\n\n\t\t/* SSG-EG envelope shapes :\n\n        E AtAlH\n        1 0 0 0  \\\\\\\\\n\n        1 0 0 1  \\___\n\n        1 0 1 0  \\/\\/\n                  ___\n        1 0 1 1  \\\n\n        1 1 0 0  ////\n                  ___\n        1 1 0 1  /\n\n        1 1 1 0  /\\/\\\n\n        1 1 1 1  /___\n\n\n        E = SSG-EG enable\n\n\n        The shapes are generated using Attack, Decay and Sustain phases.\n\n        Each single character in the diagrams above represents this whole\n        sequence:\n\n        - when KEY-ON = 1, normal Attack phase is generated (*without* any\n          difference when compared to normal mode),\n\n        - later, when envelope level reaches minimum level (max volume),\n          the EG switches to Decay phase (which works with bigger steps\n          when compared to normal mode - see below),\n\n        - later when envelope level passes the SL level,\n          the EG swithes to Sustain phase (which works with bigger steps\n          when compared to normal mode - see below),\n\n        - finally when envelope level reaches maximum level (min volume),\n          the EG switches to Attack phase again (depends on actual waveform).\n\n        Important is that when switch to Attack phase occurs, the phase counter\n        of that operator will be zeroed-out (as in normal KEY-ON) but not always.\n        (I havent found the rule for that - perhaps only when the output level is low)\n\n        The difference (when compared to normal Envelope Generator mode) is\n        that the resolution in Decay and Sustain phases is 4 times lower;\n        this results in only 256 steps instead of normal 1024.\n        In other words:\n        when SSG-EG is disabled, the step inside of the EG is one,\n        when SSG-EG is enabled, the step is four (in Decay and Sustain phases).\n\n        Times between the level changes are the same in both modes.\n\n\n        Important:\n        Decay 1 Level (so called SL) is compared to actual SSG-EG output, so\n        it is the same in both SSG and no-SSG modes, with this exception:\n\n        when the SSG-EG is enabled and is generating raising levels\n        (when the EG output is inverted) the SL will be found at wrong level !!!\n        For example, when SL=02:\n            0 -6 = -6dB in non-inverted EG output\n            96-6 = -90dB in inverted EG output\n        Which means that EG compares its level to SL as usual, and that the\n        output is simply inverted afterall.\n\n\n        The Yamaha's manuals say that AR should be set to 0x1f (max speed).\n        That is not necessary, but then EG will be generating Attack phase.\n\n        */\n\n\n\t\tbreak;\n\n\tcase 0xa0:\n\t\tswitch( OPN_SLOT(r) )\n\t\t{\n\t\tcase 0:\t\t/* 0xa0-0xa2 : FNUM1 */\n\t\t\tif (IsVGMInit)\n\t\t\t\tOPN->ST.fn_h = CH->block_fnum >> 8;\n\t\t\t{\n\t\t\t\tUINT32 fn = (((UINT32)( (OPN->ST.fn_h)&7))<<8) + v;\n\t\t\t\tUINT8 blk = OPN->ST.fn_h>>3;\n\t\t\t\t/* keyscale code */\n\t\t\t\tCH->kcode = (blk<<2) | opn_fktable[fn >> 7];\n\t\t\t\t/* phase increment counter */\n\t\t\t\tCH->fc = OPN->fn_table[fn*2]>>(7-blk);\n\n\t\t\t\t/* store fnum in clear form for LFO PM calculations */\n\t\t\t\tCH->block_fnum = (blk<<11) | fn;\n\n\t\t\t\tCH->SLOT[SLOT1].Incr=-1;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 1:\t\t/* 0xa4-0xa6 : FNUM2,BLK */\n\t\t\tOPN->ST.fn_h = v&0x3f;\n\t\t\tif (IsVGMInit)\t// workaround for stupid Kega Fusion init block\n\t\t\t\tCH->block_fnum = (OPN->ST.fn_h << 8) | (CH->block_fnum & 0xFF);\n\t\t\tbreak;\n\t\tcase 2:\t\t/* 0xa8-0xaa : 3CH FNUM1 */\n\t\t\tif (IsVGMInit)\n\t\t\t\tOPN->SL3.fn_h = OPN->SL3.block_fnum[c] >> 8;\n\t\t\tif(r < 0x100)\n\t\t\t{\n\t\t\t\tUINT32 fn = (((UINT32)(OPN->SL3.fn_h&7))<<8) + v;\n\t\t\t\tUINT8 blk = OPN->SL3.fn_h>>3;\n\t\t\t\t/* keyscale code */\n\t\t\t\tOPN->SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];\n\t\t\t\t/* phase increment counter */\n\t\t\t\tOPN->SL3.fc[c] = OPN->fn_table[fn*2]>>(7-blk);\n\t\t\t\tOPN->SL3.block_fnum[c] = (blk<<11) | fn;\n\t\t\t\t(OPN->P_CH)[2].SLOT[SLOT1].Incr=-1;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 3:\t\t/* 0xac-0xae : 3CH FNUM2,BLK */\n\t\t\tif(r < 0x100)\n\t\t\t{\n\t\t\t\tOPN->SL3.fn_h = v&0x3f;\n\t\t\t\tif (IsVGMInit)\n\t\t\t\t\tOPN->SL3.block_fnum[c] = (OPN->SL3.fn_h << 8) | (OPN->SL3.block_fnum[c] & 0xFF);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\n\tcase 0xb0:\n\t\tswitch( OPN_SLOT(r) )\n\t\t{\n\t\tcase 0:\t\t/* 0xb0-0xb2 : FB,ALGO */\n\t\t\t{\n\t\t\t\tint feedback = (v>>3)&7;\n\t\t\t\tCH->ALGO = v&7;\n\t\t\t\tCH->FB   = feedback ? feedback+6 : 0;\n\t\t\t\tsetup_connection( OPN, CH, c );\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 1:\t\t/* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */\n\t\t\tif( OPN->type & TYPE_LFOPAN)\n\t\t\t{\n\t\t\t\t/* b0-2 PMS */\n\t\t\t\tCH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */\n\n\t\t\t\t/* b4-5 AMS */\n\t\t\t\tCH->ams = lfo_ams_depth_shift[(v>>4) & 0x03];\n\n\t\t\t\t/* PAN :  b7 = L, b6 = R */\n\t\t\t\tOPN->pan[ c*2   ] = (v & 0x80) ? ~0 : 0;\n\t\t\t\tOPN->pan[ c*2+1 ] = (v & 0x40) ? ~0 : 0;\n\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n}\n\n/* initialize time tables */\nstatic void init_timetables(FM_OPN *OPN, double freqbase)\n{\n\tint i,d;\n\tdouble rate;\n\n\t/* DeTune table */\n\tfor (d = 0;d <= 3;d++)\n\t{\n\t\tfor (i = 0;i <= 31;i++)\n\t\t{\n\t\t\trate = ((double)dt_tab[d*32 + i]) * freqbase * (1<<(FREQ_SH-10)); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */\n\t\t\tOPN->ST.dt_tab[d][i]   = (INT32) rate;\n\t\t\tOPN->ST.dt_tab[d+4][i] = -OPN->ST.dt_tab[d][i];\n\t\t}\n\t}\n\n\t/* there are 2048 FNUMs that can be generated using FNUM/BLK registers\n    but LFO works with one more bit of a precision so we really need 4096 elements */\n\t/* calculate fnumber -> increment counter table */\n\tfor(i = 0; i < 4096; i++)\n\t{\n\t\t/* freq table for octave 7 */\n\t\t/* OPN phase increment counter = 20bit */\n\t\t/* the correct formula is : F-Number = (144 * fnote * 2^20 / M) / 2^(B-1) */\n\t\t/* where sample clock is  M/144 */\n\t\t/* this means the increment value for one clock sample is FNUM * 2^(B-1) = FNUM * 64 for octave 7 */\n\t\t/* we also need to handle the ratio between the chip frequency and the emulated frequency (can be 1.0)  */\n\t\tOPN->fn_table[i] = (UINT32)( (double)i * 32 * freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */\n\t}\n\n\t/* maximal frequency is required for Phase overflow calculation, register size is 17 bits (Nemesis) */\n\tOPN->fn_max = (UINT32)( (double)0x20000 * freqbase * (1<<(FREQ_SH-10)) );\n}\n\n/* prescaler set (and make time tables) */\nstatic void OPNSetPres(FM_OPN *OPN, int pres, int timer_prescaler, int SSGpres)\n{\n\t/* frequency base */\n\tOPN->ST.freqbase = (OPN->ST.rate) ? ((double)OPN->ST.clock / OPN->ST.rate) / pres : 0;\n\n\t/* EG is updated every 3 samples */\n\tOPN->eg_timer_add  = (UINT32)((1<<EG_SH) * OPN->ST.freqbase);\n\tOPN->eg_timer_overflow = ( 3 ) * (1<<EG_SH);\n\n\t/* LFO timer increment (every samples) */\n\tOPN->lfo_timer_add  = (UINT32)((1<<LFO_SH) * OPN->ST.freqbase);\n\n\t/* Timer base time */\n\tOPN->ST.timer_prescaler = timer_prescaler;\n\n\t/* SSG part  prescaler set */\n\tif( SSGpres ) (*OPN->ST.SSG->set_clock)( OPN->ST.param, OPN->ST.clock * 2 / SSGpres );\n\n\t/* make time tables */\n\tinit_timetables(OPN, OPN->ST.freqbase);\n}\n\nstatic void reset_channels( FM_ST *ST , FM_CH *CH , int num )\n{\n\tint c,s;\n\n\tfor( c = 0 ; c < num ; c++ )\n\t{\n\t\t//memset(&CH[c], 0x00, sizeof(FM_CH));\n\t\tCH[c].mem_value = 0;\n\t\tCH[c].op1_out[0] = 0;\n\t\tCH[c].op1_out[1] = 0;\n\t\tCH[c].fc = 0;\n\t\tfor(s = 0 ; s < 4 ; s++ )\n\t\t{\n\t\t\t//memset(&CH[c].SLOT[s], 0x00, sizeof(FM_SLOT));\n\t\t\tCH[c].SLOT[s].Incr = -1;\n\t\t\tCH[c].SLOT[s].key = 0;\n\t\t\tCH[c].SLOT[s].phase = 0;\n\t\t\tCH[c].SLOT[s].ssg = 0;\n\t\t\tCH[c].SLOT[s].ssgn = 0;\n\t\t\tCH[c].SLOT[s].state= EG_OFF;\n\t\t\tCH[c].SLOT[s].volume = MAX_ATT_INDEX;\n\t\t\tCH[c].SLOT[s].vol_out= MAX_ATT_INDEX;\n\t\t}\n\t}\n}\n\n/* initialize generic tables */\nstatic void init_tables(void)\n{\n\tsigned int i,x;\n\tsigned int n;\n\tdouble o,m;\n\n\t/* build Linear Power Table */\n\tfor (x=0; x<TL_RES_LEN; x++)\n\t{\n\t\tm = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);\n\t\tm = floor(m);\n\n\t\t/* we never reach (1<<16) here due to the (x+1) */\n\t\t/* result fits within 16 bits at maximum */\n\n\t\tn = (int)m;\t\t/* 16 bits here */\n\t\tn >>= 4;\t\t/* 12 bits here */\n\t\tif (n&1)\t\t/* round to nearest */\n\t\t\tn = (n>>1)+1;\n\t\telse\n\t\t\tn = n>>1;\n\t\t\t\t\t\t/* 11 bits here (rounded) */\n\t\tn <<= 2;\t\t/* 13 bits here (as in real chip) */\n\n\n\t\t/* 14 bits (with sign bit) */\n\t\ttl_tab[ x*2 + 0 ] = n;\n\t\ttl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];\n\n\t\t/* one entry in the 'Power' table use the following format, xxxxxyyyyyyyys with:            */\n\t\t/*        s = sign bit                                                                      */\n\t\t/* yyyyyyyy = 8-bits decimal part (0-TL_RES_LEN)                                            */\n\t\t/* xxxxx    = 5-bits integer 'shift' value (0-31) but, since Power table output is 13 bits, */\n\t\t/*            any value above 13 (included) would be discarded.                             */\n\t\tfor (i=1; i<13; i++)\n\t\t{\n\t\t\ttl_tab[ x*2+0 + i*2*TL_RES_LEN ] =  tl_tab[ x*2+0 ]>>i;\n\t\t\ttl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];\n\t\t}\n\t}\n\n\t/* build Logarithmic Sinus table */\n\tfor (i=0; i<SIN_LEN; i++)\n\t{\n\t\t/* non-standard sinus */\n\t\tm = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */\n\t\t/* we never reach zero here due to ((i*2)+1) */\n\n\t\tif (m>0.0)\n\t\t\to = 8*log(1.0/m)/log(2.0);\t/* convert to 'decibels' */\n\t\telse\n\t\t\to = 8*log(-1.0/m)/log(2.0);\t/* convert to 'decibels' */\n\n\t\to = o / (ENV_STEP/4);\n\n\t\tn = (int)(2.0*o);\n\t\tif (n&1)    \t\t/* round to nearest */\n\t\t\tn = (n>>1)+1;\n\t\telse\n\t\t\tn = n>>1;\n\n\t\t/* 13-bits (8.5) value is formatted for above 'Power' table */\n\t\tsin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );\n\t}\n\n\t/* build LFO PM modulation table */\n\tfor(i = 0; i < 8; i++) /* 8 PM depths */\n\t{\n\t\tUINT8 fnum;\n\t\tfor (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */\n\t\t{\n\t\t\tUINT8 value;\n\t\t\tUINT8 step;\n\t\t\tUINT32 offset_depth = i;\n\t\t\tUINT32 offset_fnum_bit;\n\t\t\tUINT32 bit_tmp;\n\n\t\t\tfor (step=0; step<8; step++)\n\t\t\t{\n\t\t\t\tvalue = 0;\n\t\t\t\tfor (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */\n\t\t\t\t{\n\t\t\t\t\tif (fnum & (1<<bit_tmp)) /* only if bit \"bit_tmp\" is set */\n\t\t\t\t\t{\n\t\t\t\t\t\toffset_fnum_bit = bit_tmp * 8;\n\t\t\t\t\t\tvalue += lfo_pm_output[offset_fnum_bit + offset_depth][step];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t/* 32 steps for LFO PM (sinus) */\n\t\t\t\tlfo_pm_table[(fnum*32*8) + (i*32) + step   + 0] = value;\n\t\t\t\tlfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+ 8] = value;\n\t\t\t\tlfo_pm_table[(fnum*32*8) + (i*32) + step   +16] = -value;\n\t\t\t\tlfo_pm_table[(fnum*32*8) + (i*32) +(step^7)+24] = -value;\n\t\t\t}\n\n\t\t}\n\t}\n\n#ifdef SAVE_SAMPLE\n\tsample[0]=fopen(\"sampsum.pcm\",\"wb\");\n#endif\n}\n\n#endif /* BUILD_OPN */\n\n#if (BUILD_YM2612||BUILD_YM3438)\n/*******************************************************************************/\n/*      YM2612 local section                                                   */\n/*******************************************************************************/\n\n/* Generate samples for one of the YM2612s */\nvoid ym2612_update_one(void *chip, FMSAMPLE **buffer, int length)\n{\n\tYM2612 *F2612 = (YM2612 *)chip;\n\tFM_OPN *OPN   = &F2612->OPN;\n\tINT32 *out_fm = OPN->out_fm;\n\tint i;\n\tFMSAMPLE  *bufL,*bufR;\n\tINT32 dacout;\n\tFM_CH\t*cch[6];\n\tint lt,rt;\n\n\t/* set bufer */\n\tbufL = buffer[0];\n\tbufR = buffer[1];\n\n\tcch[0]   = &F2612->CH[0];\n\tcch[1]   = &F2612->CH[1];\n\tcch[2]   = &F2612->CH[2];\n\tcch[3]   = &F2612->CH[3];\n\tcch[4]   = &F2612->CH[4];\n\tcch[5]   = &F2612->CH[5];\n\t\n\tif (! F2612->MuteDAC)\n\t\tdacout = F2612->dacout;\n\telse\n\t\tdacout = 0;\n\n\t/* refresh PG and EG */\n\trefresh_fc_eg_chan( OPN, cch[0] );\n\trefresh_fc_eg_chan( OPN, cch[1] );\n\tif( (OPN->ST.mode & 0xc0) )\n\t{\n\t\t/* 3SLOT MODE */\n\t\tif( cch[2]->SLOT[SLOT1].Incr==-1)\n\t\t{\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );\n\t\t\trefresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );\n\t\t}\n\t}else refresh_fc_eg_chan( OPN, cch[2] );\n\trefresh_fc_eg_chan( OPN, cch[3] );\n\trefresh_fc_eg_chan( OPN, cch[4] );\n\trefresh_fc_eg_chan( OPN, cch[5] );\n\tif (! length)\n\t{\n\t\tupdate_ssg_eg_channel(&cch[0]->SLOT[SLOT1]);\n\t\tupdate_ssg_eg_channel(&cch[1]->SLOT[SLOT1]);\n\t\tupdate_ssg_eg_channel(&cch[2]->SLOT[SLOT1]);\n\t\tupdate_ssg_eg_channel(&cch[3]->SLOT[SLOT1]);\n\t\tupdate_ssg_eg_channel(&cch[4]->SLOT[SLOT1]);\n\t\tupdate_ssg_eg_channel(&cch[5]->SLOT[SLOT1]);\n\t}\n\n\n\t/* buffering */\n\tfor(i=0; i < length ; i++)\n\t{\n\t\t/* clear outputs */\n\t\tout_fm[0] = 0;\n\t\tout_fm[1] = 0;\n\t\tout_fm[2] = 0;\n\t\tout_fm[3] = 0;\n\t\tout_fm[4] = 0;\n\t\tout_fm[5] = 0;\n\n\t\t/* update SSG-EG output */\n\t\tupdate_ssg_eg_channel(&cch[0]->SLOT[SLOT1]);\n\t\tupdate_ssg_eg_channel(&cch[1]->SLOT[SLOT1]);\n\t\tupdate_ssg_eg_channel(&cch[2]->SLOT[SLOT1]);\n\t\tupdate_ssg_eg_channel(&cch[3]->SLOT[SLOT1]);\n\t\tupdate_ssg_eg_channel(&cch[4]->SLOT[SLOT1]);\n\t\tupdate_ssg_eg_channel(&cch[5]->SLOT[SLOT1]);\n\n\t\t/* calculate FM */\n\t\tif (! F2612->dac_test)\n\t\t{\n\t\t\tchan_calc(F2612, OPN, cch[0]);\n\t\t\tchan_calc(F2612, OPN, cch[1]);\n\t\t\tchan_calc(F2612, OPN, cch[2]);\n\t\t\tchan_calc(F2612, OPN, cch[3]);\n\t\t\tchan_calc(F2612, OPN, cch[4]);\n\t\t\tif( F2612->dacen )\n\t\t\t\t*cch[5]->connect4 += dacout;\n\t\t\telse\n\t\t\t\tchan_calc(F2612, OPN, cch[5]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tout_fm[0] = out_fm[1] = dacout;\n\t\t\tout_fm[2] = out_fm[3] = dacout;\n\t\t\tout_fm[5] = dacout;\n\t\t}\n\n\t\t/* advance LFO */\n\t\tadvance_lfo(OPN);\n\n\t\t/* advance envelope generator */\n\t\tOPN->eg_timer += OPN->eg_timer_add;\n\t\twhile (OPN->eg_timer >= OPN->eg_timer_overflow)\n\t\t{\n\t\t\tOPN->eg_timer -= OPN->eg_timer_overflow;\n\t\t\tOPN->eg_cnt++;\n\n\t\t\tadvance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[3]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[4]->SLOT[SLOT1]);\n\t\t\tadvance_eg_channel(OPN, &cch[5]->SLOT[SLOT1]);\n\t\t}\n\n\t\t/*fprintf(hFile, \"%u\", FileSample, out_fm[0]);\n\t\tfor (lt = 0; lt < 6; lt ++)\n\t\t\tfprintf(hFile, \"\\t%d\", out_fm[lt]);\n\t\tfprintf(hFile, \"\\n\");\n\t\tFileSample ++;*/\n\t\t\n\t\tif (out_fm[0] > 8192) out_fm[0] = 8192;\n\t\telse if (out_fm[0] < -8192) out_fm[0] = -8192;\n\t\tif (out_fm[1] > 8192) out_fm[1] = 8192;\n\t\telse if (out_fm[1] < -8192) out_fm[1] = -8192;\n\t\tif (out_fm[2] > 8192) out_fm[2] = 8192;\n\t\telse if (out_fm[2] < -8192) out_fm[2] = -8192;\n\t\tif (out_fm[3] > 8192) out_fm[3] = 8192;\n\t\telse if (out_fm[3] < -8192) out_fm[3] = -8192;\n\t\tif (out_fm[4] > 8192) out_fm[4] = 8192;\n\t\telse if (out_fm[4] < -8192) out_fm[4] = -8192;\n\t\tif (out_fm[5] > 8192) out_fm[5] = 8192;\n\t\telse if (out_fm[5] < -8192) out_fm[5] = -8192;\n\n\t\t/* 6-channels mixing  */\n\t\tlt  = ((out_fm[0]>>0) & OPN->pan[0]);\n\t\trt  = ((out_fm[0]>>0) & OPN->pan[1]);\n\t\tlt += ((out_fm[1]>>0) & OPN->pan[2]);\n\t\trt += ((out_fm[1]>>0) & OPN->pan[3]);\n\t\tlt += ((out_fm[2]>>0) & OPN->pan[4]);\n\t\trt += ((out_fm[2]>>0) & OPN->pan[5]);\n\t\tlt += ((out_fm[3]>>0) & OPN->pan[6]);\n\t\trt += ((out_fm[3]>>0) & OPN->pan[7]);\n\t\tif (! F2612->dac_test)\n\t\t{\n\t\t\tlt += ((out_fm[4]>>0) & OPN->pan[8]);\n\t\t\trt += ((out_fm[4]>>0) & OPN->pan[9]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlt += dacout;\n\t\t\tlt += dacout;\n\t\t}\n\t\tlt += ((out_fm[5]>>0) & OPN->pan[10]);\n\t\trt += ((out_fm[5]>>0) & OPN->pan[11]);\n\n//      Limit( lt, MAXOUT, MINOUT );\n//      Limit( rt, MAXOUT, MINOUT );\n\n\t\t#ifdef SAVE_SAMPLE\n\t\t\tSAVE_ALL_CHANNELS\n\t\t#endif\n\n\t\t/* buffering */\n\t\tif (F2612->WaveOutMode & 0x01)\n\t\t\tF2612->WaveL = lt;\n\t\tif (F2612->WaveOutMode & 0x02)\n\t\t\tF2612->WaveR = rt;\n\t\tif (F2612->WaveOutMode ^ 0x03)\n\t\t\tF2612->WaveOutMode ^= 0x03;\n\t\tbufL[i] = F2612->WaveL;\n\t\tbufR[i] = F2612->WaveR;\n\n\t\t/* CSM mode: if CSM Key ON has occured, CSM Key OFF need to be sent       */\n\t\t/* only if Timer A does not overflow again (i.e CSM Key ON not set again) */\n\t\tOPN->SL3.key_csm <<= 1;\n\n\t\t/* timer A control */\n\t\t//INTERNAL_TIMER_A( &OPN->ST , cch[2] )\n\t\t{\n\t\t\tif( OPN->ST.TAC &&  (OPN->ST.timer_handler==0) )\n\t\t\t\tif( (OPN->ST.TAC -= (int)(OPN->ST.freqbase*4096)) <= 0 )\n\t\t\t\t{\n\t\t\t\t\tTimerAOver( &OPN->ST );\n\t\t\t\t\t// CSM mode total level latch and auto key on\n\t\t\t\t\tif( OPN->ST.mode & 0x80 )\n\t\t\t\t\t\tCSMKeyControll( OPN, cch[2] );\n\t\t\t\t}\n\t\t}\n\n\t\t/* CSM Mode Key ON still disabled */\n\t\tif (OPN->SL3.key_csm & 2)\n\t\t{\n\t\t\t/* CSM Mode Key OFF (verified by Nemesis on real hardware) */\n\t\t\tFM_KEYOFF_CSM(cch[2],SLOT1);\n\t\t\tFM_KEYOFF_CSM(cch[2],SLOT2);\n\t\t\tFM_KEYOFF_CSM(cch[2],SLOT3);\n\t\t\tFM_KEYOFF_CSM(cch[2],SLOT4);\n\t\t\tOPN->SL3.key_csm = 0;\n\t\t}\n\t}\n\n\t/* timer B control */\n//\tINTERNAL_TIMER_B(&OPN->ST,length)\n}\n\n#ifdef __STATE_H__\nvoid ym2612_postload(void *chip)\n{\n\tif (chip)\n\t{\n\t\tYM2612 *F2612 = (YM2612 *)chip;\n\t\tint r;\n\n\t\t/* DAC data & port */\n\t\tF2612->dacout = ((int)F2612->REGS[0x2a] - 0x80) << 6;\t/* level unknown */\n\t\tF2612->dacen  = F2612->REGS[0x2d] & 0x80;\n\t\t/* OPN registers */\n\t\t/* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */\n\t\tfor(r=0x30;r<0x9e;r++)\n\t\t\tif((r&3) != 3)\n\t\t\t{\n\t\t\t\tOPNWriteReg(&F2612->OPN,r,F2612->REGS[r]);\n\t\t\t\tOPNWriteReg(&F2612->OPN,r|0x100,F2612->REGS[r|0x100]);\n\t\t\t}\n\t\t/* FB / CONNECT , L / R / AMS / PMS */\n\t\tfor(r=0xb0;r<0xb6;r++)\n\t\t\tif((r&3) != 3)\n\t\t\t{\n\t\t\t\tOPNWriteReg(&F2612->OPN,r,F2612->REGS[r]);\n\t\t\t\tOPNWriteReg(&F2612->OPN,r|0x100,F2612->REGS[r|0x100]);\n\t\t\t}\n\t\t/* channels */\n\t\t/*FM_channel_postload(F2612->CH,6);*/\n\t}\n}\n\nstatic void YM2612_save_state(YM2612 *F2612, running_device *device)\n{\n\tstate_save_register_device_item_array(device, 0, F2612->REGS);\n\tFMsave_state_st(device,&F2612->OPN.ST);\n\tFMsave_state_channel(device,F2612->CH,6);\n\t/* 3slots */\n\tstate_save_register_device_item_array(device, 0, F2612->OPN.SL3.fc);\n\tstate_save_register_device_item(device, 0, F2612->OPN.SL3.fn_h);\n\tstate_save_register_device_item_array(device, 0, F2612->OPN.SL3.kcode);\n\t/* address register1 */\n\tstate_save_register_device_item(device, 0, F2612->addr_A1);\n}\n#endif /* _STATE_H */\n\n/* initialize YM2612 emulator(s) */\n//void * ym2612_init(void *param, running_device *device, int clock, int rate,\n//               FM_TIMERHANDLER timer_handler,FM_IRQHANDLER IRQHandler)\nvoid * ym2612_init(void *param, int clock, int rate,\n               FM_TIMERHANDLER timer_handler,FM_IRQHANDLER IRQHandler)\n{\n\tYM2612 *F2612;\n\n\t/* allocate extend state space */\n\t//F2612 = auto_alloc_clear(device->machine, YM2612);\n\tF2612 = (YM2612 *)malloc(sizeof(YM2612));\n\tif (F2612 == NULL)\n\t\treturn NULL;\n\tmemset(F2612, 0x00, sizeof(YM2612));\n\t/* allocate total level table (128kb space) */\n\tinit_tables();\n\n\tF2612->OPN.ST.param = param;\n\tF2612->OPN.type = TYPE_YM2612;\n\tF2612->OPN.P_CH = F2612->CH;\n\t//F2612->OPN.ST.device = device;\n\tF2612->OPN.ST.clock = clock;\n\tF2612->OPN.ST.rate = rate;\n\t/* F2612->OPN.ST.irq = 0; */\n\t/* F2612->OPN.ST.status = 0; */\n\t/* Extend handler */\n\tF2612->OPN.ST.timer_handler = timer_handler;\n\tF2612->OPN.ST.IRQ_Handler   = IRQHandler;\n\t\n\tif (PseudoSt)\n\t\tF2612->WaveOutMode = 0x01;\n\telse\n\t\tF2612->WaveOutMode = 0x03;\n\t/*hFile = fopen(\"YM2612.log\", \"wt\");\n\tfprintf(hFile, \"Clock: %d, Sample Rate: %d\\n\", clock, rate);\n\tfprintf(hFile, \"Sample\\tCh 0\\tCh 1\\tCh 2\\tCh 3\\tCh 4\\tCh 5\\n\");\n\tFileSample = 0;*/\n\n#ifdef __STATE_H__\n\tYM2612_save_state(F2612, device);\n#endif\n\treturn F2612;\n}\n\n/* shut down emulator */\nvoid ym2612_shutdown(void *chip)\n{\n\tYM2612 *F2612 = (YM2612 *)chip;\n\t//fclose(hFile);\n\n\tFMCloseTable();\n\t//auto_free(F2612->OPN.ST.device->machine, F2612);\n\tfree(F2612);\n}\n\n/* reset one of chip */\nvoid ym2612_reset_chip(void *chip)\n{\n\tint i;\n\tYM2612 *F2612 = (YM2612 *)chip;\n\tFM_OPN *OPN   = &F2612->OPN;\n\n\tOPNSetPres( OPN, 6*24, 6*24, 0);\n\t/* status clear */\n\tFM_IRQMASK_SET(&OPN->ST,0x03);\n\tFM_BUSY_CLEAR(&OPN->ST);\n\t//OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */\n\n\tOPN->eg_timer = 0;\n\tOPN->eg_cnt   = 0;\n\n\tOPN->lfo_timer = 0;\n\tOPN->lfo_cnt   = 0;\n\tOPN->LFO_AM    = 126;\n\tOPN->LFO_PM    = 0;\n\n\tOPN->ST.TAC    = 0;\n\tOPN->ST.TBC    = 0;\n\n\tOPN->SL3.key_csm = 0;\n\n\tOPN->ST.status = 0;\n\tOPN->ST.mode = 0;\n\n\tmemset(F2612->REGS, 0x00, sizeof(UINT8) * 512);\n\t\n\tOPNWriteMode(OPN,0x22,0x00);\n\t\n\tOPNWriteMode(OPN,0x27,0x30);\n\tOPNWriteMode(OPN,0x26,0x00);\n\tOPNWriteMode(OPN,0x25,0x00);\n\tOPNWriteMode(OPN,0x24,0x00);\n\n\treset_channels( &OPN->ST , &F2612->CH[0] , 6 );\n\n\tfor(i = 0xb6 ; i >= 0xb4 ; i-- )\n\t{\n\t\tOPNWriteReg(OPN,i      ,0xc0);\n\t\tOPNWriteReg(OPN,i|0x100,0xc0);\n\t}\n\tfor(i = 0xb2 ; i >= 0x30 ; i-- )\n\t{\n\t\tOPNWriteReg(OPN,i      ,0);\n\t\tOPNWriteReg(OPN,i|0x100,0);\n\t}\n\n\t/* DAC mode clear */\n\tF2612->dacen = 0;\n\tF2612->dac_test = 0;\n\tF2612->dacout = 0;\n\t\n\tif (F2612->WaveOutMode == 0x02)\n\t\tF2612->WaveOutMode >>= 1;\n}\n\n/* YM2612 write */\n/* n = number  */\n/* a = address */\n/* v = value   */\nint ym2612_write(void *chip, int a, UINT8 v)\n{\n\tYM2612 *F2612 = (YM2612 *)chip;\n\tint addr;\n\n\tv &= 0xff;\t/* adjust to 8 bit bus */\n\n\tswitch( a&3)\n\t{\n\tcase 0:\t/* address port 0 */\n\t\tF2612->OPN.ST.address = v;\n\t\tF2612->addr_A1 = 0;\n\t\tbreak;\n\n\tcase 1:\t/* data port 0    */\n\t\tif (F2612->addr_A1 != 0)\n\t\t\tbreak;\t/* verified on real YM2608 */\n\n\t\taddr = F2612->OPN.ST.address;\n\t\tF2612->REGS[addr] = v;\n\t\tswitch( addr & 0xf0 )\n\t\t{\n\t\tcase 0x20:\t/* 0x20-0x2f Mode */\n\t\t\tswitch( addr )\n\t\t\t{\n\t\t\tcase 0x2a:\t/* DAC data (YM2612) */\n\t\t\t\tym2612_update_req(F2612->OPN.ST.param);\n\t\t\t\tF2612->dacout = ((int)v - 0x80) << 6;\t/* level unknown */\n\t\t\t\tbreak;\n\t\t\tcase 0x2b:\t/* DAC Sel  (YM2612) */\n\t\t\t\t/* b7 = dac enable */\n\t\t\t\tF2612->dacen = v & 0x80;\n\t\t\t\tbreak;\n\t\t\tcase 0x2C:\t// undocumented: DAC Test Reg\n\t\t\t\t// b5 = volume enable\n\t\t\t\tF2612->dac_test = v & 0x20;\n\t\t\t\tbreak;\n\t\t\tdefault:\t/* OPN section */\n\t\t\t\tym2612_update_req(F2612->OPN.ST.param);\n\t\t\t\t/* write register */\n\t\t\t\tOPNWriteMode(&(F2612->OPN),addr,v);\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\t/* 0x30-0xff OPN section */\n\t\t\tym2612_update_req(F2612->OPN.ST.param);\n\t\t\t/* write register */\n\t\t\tOPNWriteReg(&(F2612->OPN),addr,v);\n\t\t}\n\t\tbreak;\n\n\tcase 2:\t/* address port 1 */\n\t\tF2612->OPN.ST.address = v;\n\t\tF2612->addr_A1 = 1;\n\t\tbreak;\n\n\tcase 3:\t/* data port 1    */\n\t\tif (F2612->addr_A1 != 1)\n\t\t\tbreak;\t/* verified on real YM2608 */\n\n\t\taddr = F2612->OPN.ST.address;\n\t\tF2612->REGS[addr | 0x100] = v;\n\t\tym2612_update_req(F2612->OPN.ST.param);\n\t\tOPNWriteReg(&(F2612->OPN),addr | 0x100,v);\n\t\tbreak;\n\t}\n\treturn F2612->OPN.ST.irq;\n}\n\nUINT8 ym2612_read(void *chip,int a)\n{\n\tYM2612 *F2612 = (YM2612 *)chip;\n\n\tswitch( a&3)\n\t{\n\tcase 0:\t/* status 0 */\n\t\treturn FM_STATUS_FLAG(&F2612->OPN.ST);\n\tcase 1:\n\tcase 2:\n\tcase 3:\n\t\t//LOG(LOG_WAR,(\"YM2612 #%p:A=%d read unmapped area\\n\",F2612->OPN.ST.param,a));\n\t\treturn FM_STATUS_FLAG(&F2612->OPN.ST);\n\t}\n\treturn 0;\n}\n\nint ym2612_timer_over(void *chip,int c)\n{\n\tYM2612 *F2612 = (YM2612 *)chip;\n\n\tif( c )\n\t{\t/* Timer B */\n\t\tTimerBOver( &(F2612->OPN.ST) );\n\t}\n\telse\n\t{\t/* Timer A */\n\t\tym2612_update_req(F2612->OPN.ST.param);\n\t\t/* timer update */\n\t\tTimerAOver( &(F2612->OPN.ST) );\n\t\t/* CSM mode key,TL controll */\n\t\tif ((F2612->OPN.ST.mode & 0xc0) == 0x80)\n\t\t{\t/* CSM mode total level latch and auto key on */\n\t\t\tCSMKeyControll( &F2612->OPN, &(F2612->CH[2]) );\n\t\t}\n\t}\n\treturn F2612->OPN.ST.irq;\n}\n\n\nvoid ym2612_set_mutemask(void *chip, UINT32 MuteMask)\n{\n\tYM2612 *F2612 = (YM2612 *)chip;\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t\tF2612->CH[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\tF2612->MuteDAC = (MuteMask >> 6) & 0x01;\n\t\n\treturn;\n}\n\nvoid ym2612_setoptions(UINT8 Flags)\n{\n\tPseudoSt = (Flags >> 2) & 0x01;\n\t\n\treturn;\n}\n#endif /* (BUILD_YM2612||BUILD_YM3238) */\n"
  },
  {
    "path": "VGMPlay/chips/fmopl.c",
    "content": "/*\n**\n** File: fmopl.c - software implementation of FM sound generator\n**                                            types OPL and OPL2\n**\n** Copyright Jarek Burczynski (bujar at mame dot net)\n** Copyright Tatsuyuki Satoh , MultiArcadeMachineEmulator development\n**\n** Version 0.72\n**\n\nRevision History:\n\n04-08-2003 Jarek Burczynski:\n - removed BFRDY hack. BFRDY is busy flag, and it should be 0 only when the chip\n   handles memory read/write or during the adpcm synthesis when the chip\n   requests another byte of ADPCM data.\n\n24-07-2003 Jarek Burczynski:\n - added a small hack for Y8950 status BFRDY flag (bit 3 should be set after\n   some (unknown) delay). Right now it's always set.\n\n14-06-2003 Jarek Burczynski:\n - implemented all of the status register flags in Y8950 emulation\n - renamed y8950_set_delta_t_memory() parameters from _rom_ to _mem_ since\n   they can be either RAM or ROM\n\n08-10-2002 Jarek Burczynski (thanks to Dox for the YM3526 chip)\n - corrected ym3526_read() to always set bit 2 and bit 1\n   to HIGH state - identical to ym3812_read (verified on real YM3526)\n\n04-28-2002 Jarek Burczynski:\n - binary exact Envelope Generator (verified on real YM3812);\n   compared to YM2151: the EG clock is equal to internal_clock,\n   rates are 2 times slower and volume resolution is one bit less\n - modified interface functions (they no longer return pointer -\n   that's internal to the emulator now):\n    - new wrapper functions for OPLCreate: ym3526_init(), ym3812_init() and y8950_init()\n - corrected 'off by one' error in feedback calculations (when feedback is off)\n - enabled waveform usage (credit goes to Vlad Romascanu and zazzal22)\n - speeded up noise generator calculations (Nicola Salmoria)\n\n03-24-2002 Jarek Burczynski (thanks to Dox for the YM3812 chip)\n Complete rewrite (all verified on real YM3812):\n - corrected sin_tab and tl_tab data\n - corrected operator output calculations\n - corrected waveform_select_enable register;\n   simply: ignore all writes to waveform_select register when\n   waveform_select_enable == 0 and do not change the waveform previously selected.\n - corrected KSR handling\n - corrected Envelope Generator: attack shape, Sustain mode and\n   Percussive/Non-percussive modes handling\n - Envelope Generator rates are two times slower now\n - LFO amplitude (tremolo) and phase modulation (vibrato)\n - rhythm sounds phase generation\n - white noise generator (big thanks to Olivier Galibert for mentioning Berlekamp-Massey algorithm)\n - corrected key on/off handling (the 'key' signal is ORed from three sources: FM, rhythm and CSM)\n - funky details (like ignoring output of operator 1 in BD rhythm sound when connect == 1)\n\n12-28-2001 Acho A. Tang\n - reflected Delta-T EOS status on Y8950 status port.\n - fixed subscription range of attack/decay tables\n\n\n    To do:\n        add delay before key off in CSM mode (see CSMKeyControll)\n        verify volume of the FM part on the Y8950\n*/\n\n#include <math.h>\n#include \"mamedef.h\"\n#ifdef _DEBUG\n#include <stdio.h>\n#endif\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n//#include \"sndintrf.h\"\n#include \"fmopl.h\"\n#if BUILD_Y8950\n#include \"ymdeltat.h\"\n#endif\n\n\n/* output final shift */\n#if (OPL_SAMPLE_BITS==16)\n\t#define FINAL_SH\t(0)\n\t#define MAXOUT\t\t(+32767)\n\t#define MINOUT\t\t(-32768)\n#else\n\t#define FINAL_SH\t(8)\n\t#define MAXOUT\t\t(+127)\n\t#define MINOUT\t\t(-128)\n#endif\n\n\n#define FREQ_SH\t\t\t16  /* 16.16 fixed point (frequency calculations) */\n#define EG_SH\t\t\t16  /* 16.16 fixed point (EG timing)              */\n#define LFO_SH\t\t\t24  /*  8.24 fixed point (LFO calculations)       */\n#define TIMER_SH\t\t16  /* 16.16 fixed point (timers calculations)    */\n\n#define FREQ_MASK\t\t((1<<FREQ_SH)-1)\n\n/* envelope output entries */\n#define ENV_BITS\t\t10\n#define ENV_LEN\t\t\t(1<<ENV_BITS)\n#define ENV_STEP\t\t(128.0/ENV_LEN)\n\n#define MAX_ATT_INDEX\t((1<<(ENV_BITS-1))-1) /*511*/\n#define MIN_ATT_INDEX\t(0)\n\n/* sinwave entries */\n#define SIN_BITS\t\t10\n#define SIN_LEN\t\t\t(1<<SIN_BITS)\n#define SIN_MASK\t\t(SIN_LEN-1)\n\n#define TL_RES_LEN\t\t(256)\t/* 8 bits addressing (real chip) */\n\n\n\n/* register number to channel number , slot offset */\n#define SLOT1 0\n#define SLOT2 1\n\n/* Envelope Generator phases */\n\n#define EG_ATT\t\t\t4\n#define EG_DEC\t\t\t3\n#define EG_SUS\t\t\t2\n#define EG_REL\t\t\t1\n#define EG_OFF\t\t\t0\n\n\n/* save output as raw 16-bit sample */\n\n/*#define SAVE_SAMPLE*/\n\n#ifdef SAVE_SAMPLE\nINLINE signed int acc_calc(signed int value)\n{\n\tif (value>=0)\n\t{\n\t\tif (value < 0x0200)\n\t\t\treturn (value & ~0);\n\t\tif (value < 0x0400)\n\t\t\treturn (value & ~1);\n\t\tif (value < 0x0800)\n\t\t\treturn (value & ~3);\n\t\tif (value < 0x1000)\n\t\t\treturn (value & ~7);\n\t\tif (value < 0x2000)\n\t\t\treturn (value & ~15);\n\t\tif (value < 0x4000)\n\t\t\treturn (value & ~31);\n\t\treturn (value & ~63);\n\t}\n\t/*else value < 0*/\n\tif (value > -0x0200)\n\t\treturn (~abs(value) & ~0);\n\tif (value > -0x0400)\n\t\treturn (~abs(value) & ~1);\n\tif (value > -0x0800)\n\t\treturn (~abs(value) & ~3);\n\tif (value > -0x1000)\n\t\treturn (~abs(value) & ~7);\n\tif (value > -0x2000)\n\t\treturn (~abs(value) & ~15);\n\tif (value > -0x4000)\n\t\treturn (~abs(value) & ~31);\n\treturn (~abs(value) & ~63);\n}\n\n\nstatic FILE *sample[1];\n\t#if 1\t/*save to MONO file */\n\t\t#define SAVE_ALL_CHANNELS \\\n\t\t{\tsigned int pom = acc_calc(lt); \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t}\n\t#else\t/*save to STEREO file */\n\t\t#define SAVE_ALL_CHANNELS \\\n\t\t{\tsigned int pom = lt; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t\tpom = rt; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t}\n\t#endif\n#endif\n\n//#define LOG_CYM_FILE 0\n//static FILE * cymfile = NULL;\n\n\n\n#define OPL_TYPE_WAVESEL   0x01  /* waveform select     */\n#define OPL_TYPE_ADPCM     0x02  /* DELTA-T ADPCM unit  */\n#define OPL_TYPE_KEYBOARD  0x04  /* keyboard interface  */\n#define OPL_TYPE_IO        0x08  /* I/O port            */\n\n/* ---------- Generic interface section ---------- */\n#define OPL_TYPE_YM3526 (0)\n#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)\n#define OPL_TYPE_Y8950  (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)\n\n\n\ntypedef struct\n{\n\tUINT32\tar;\t\t\t/* attack rate: AR<<2           */\n\tUINT32\tdr;\t\t\t/* decay rate:  DR<<2           */\n\tUINT32\trr;\t\t\t/* release rate:RR<<2           */\n\tUINT8\tKSR;\t\t/* key scale rate               */\n\tUINT8\tksl;\t\t/* keyscale level               */\n\tUINT8\tksr;\t\t/* key scale rate: kcode>>KSR   */\n\tUINT8\tmul;\t\t/* multiple: mul_tab[ML]        */\n\n\t/* Phase Generator */\n\tUINT32\tCnt;\t\t/* frequency counter            */\n\tUINT32\tIncr;\t\t/* frequency counter step       */\n\tUINT8   FB;\t\t\t/* feedback shift value         */\n\tINT32   *connect1;\t/* slot1 output pointer         */\n\tINT32   op1_out[2];\t/* slot1 output for feedback    */\n\tUINT8   CON;\t\t/* connection (algorithm) type  */\n\n\t/* Envelope Generator */\n\tUINT8\teg_type;\t/* percussive/non-percussive mode */\n\tUINT8\tstate;\t\t/* phase type                   */\n\tUINT32\tTL;\t\t\t/* total level: TL << 2         */\n\tINT32\tTLL;\t\t/* adjusted now TL              */\n\tINT32\tvolume;\t\t/* envelope counter             */\n\tUINT32\tsl;\t\t\t/* sustain level: sl_tab[SL]    */\n\tUINT8\teg_sh_ar;\t/* (attack state)               */\n\tUINT8\teg_sel_ar;\t/* (attack state)               */\n\tUINT8\teg_sh_dr;\t/* (decay state)                */\n\tUINT8\teg_sel_dr;\t/* (decay state)                */\n\tUINT8\teg_sh_rr;\t/* (release state)              */\n\tUINT8\teg_sel_rr;\t/* (release state)              */\n\tUINT32\tkey;\t\t/* 0 = KEY OFF, >0 = KEY ON     */\n\n\t/* LFO */\n\tUINT32\tAMmask;\t\t/* LFO Amplitude Modulation enable mask */\n\tUINT8\tvib;\t\t/* LFO Phase Modulation enable flag (active high)*/\n\n\t/* waveform select */\n\tUINT16\twavetable;\n} OPL_SLOT;\n\ntypedef struct\n{\n\tOPL_SLOT SLOT[2];\n\t/* phase generator state */\n\tUINT32  block_fnum;\t/* block+fnum                   */\n\tUINT32  fc;\t\t\t/* Freq. Increment base         */\n\tUINT32  ksl_base;\t/* KeyScaleLevel Base step      */\n\tUINT8   kcode;\t\t/* key code (for key scaling)   */\n\tUINT8   Muted;\n} OPL_CH;\n\n/* OPL state */\ntypedef struct fm_opl_f\n{\n\t/* FM channel slots */\n\tOPL_CH\tP_CH[9];\t\t\t\t/* OPL/OPL2 chips have 9 channels*/\n\tUINT8\tMuteSpc[6];\t\t\t\t/* Mute Special: 5 Rhythm + 1 DELTA-T Channel */\n\n\tUINT32\teg_cnt;\t\t\t\t\t/* global envelope generator counter    */\n\tUINT32\teg_timer;\t\t\t\t/* global envelope generator counter works at frequency = chipclock/72 */\n\tUINT32\teg_timer_add;\t\t\t/* step of eg_timer                     */\n\tUINT32\teg_timer_overflow;\t\t/* envelope generator timer overlfows every 1 sample (on real chip) */\n\n\tUINT8\trhythm;\t\t\t\t\t/* Rhythm mode                  */\n\n\tUINT32\tfn_tab[1024];\t\t\t/* fnumber->increment counter   */\n\n\t/* LFO */\n\tUINT32\tLFO_AM;\n\tINT32\tLFO_PM;\n\n\tUINT8\tlfo_am_depth;\n\tUINT8\tlfo_pm_depth_range;\n\tUINT32\tlfo_am_cnt;\n\tUINT32\tlfo_am_inc;\n\tUINT32\tlfo_pm_cnt;\n\tUINT32\tlfo_pm_inc;\n\n\tUINT32\tnoise_rng;\t\t\t\t/* 23 bit noise shift register  */\n\tUINT32\tnoise_p;\t\t\t\t/* current noise 'phase'        */\n\tUINT32\tnoise_f;\t\t\t\t/* current noise period         */\n\n\tUINT8\twavesel;\t\t\t\t/* waveform select enable flag  */\n\n\tUINT32\tT[2];\t\t\t\t\t/* timer counters               */\n\tUINT8\tst[2];\t\t\t\t\t/* timer enable                 */\n\n#if BUILD_Y8950\n\t/* Delta-T ADPCM unit (Y8950) */\n\n\tYM_DELTAT *deltat;\n\n\t/* Keyboard and I/O ports interface */\n\tUINT8\tportDirection;\n\tUINT8\tportLatch;\n\tOPL_PORTHANDLER_R porthandler_r;\n\tOPL_PORTHANDLER_W porthandler_w;\n\tvoid *\tport_param;\n\tOPL_PORTHANDLER_R keyboardhandler_r;\n\tOPL_PORTHANDLER_W keyboardhandler_w;\n\tvoid *\tkeyboard_param;\n#endif\n\n\t/* external event callback handlers */\n\tOPL_TIMERHANDLER  timer_handler;\t/* TIMER handler                */\n\tvoid *TimerParam;\t\t\t\t\t/* TIMER parameter              */\n\tOPL_IRQHANDLER    IRQHandler;\t/* IRQ handler                  */\n\tvoid *IRQParam;\t\t\t\t\t/* IRQ parameter                */\n\tOPL_UPDATEHANDLER UpdateHandler;/* stream update handler        */\n\tvoid *UpdateParam;\t\t\t\t/* stream update parameter      */\n\n\tUINT8 type;\t\t\t\t\t\t/* chip type                    */\n\tUINT8 address;\t\t\t\t\t/* address register             */\n\tUINT8 status;\t\t\t\t\t/* status flag                  */\n\tUINT8 statusmask;\t\t\t\t/* status mask                  */\n\tUINT8 mode;\t\t\t\t\t\t/* Reg.08 : CSM,notesel,etc.    */\n\n\tUINT32 clock;\t\t\t\t\t/* master clock  (Hz)           */\n\tUINT32 rate;\t\t\t\t\t/* sampling rate (Hz)           */\n\tdouble freqbase;\t\t\t\t/* frequency base               */\n\t//attotime TimerBase;\t\t\t/* Timer base time (==sampling time)*/\n\n\tsigned int phase_modulation;\t/* phase modulation input (SLOT 2) */\n\tsigned int output[1];\n#if BUILD_Y8950\n\tINT32 output_deltat[4];\t\t/* for Y8950 DELTA-T, chip is mono, that 4 here is just for safety */\n#endif\n} FM_OPL;\n\n\n\n/* mapping of register number (offset) to slot number used by the emulator */\nstatic const int slot_array[32]=\n{\n\t 0, 2, 4, 1, 3, 5,-1,-1,\n\t 6, 8,10, 7, 9,11,-1,-1,\n\t12,14,16,13,15,17,-1,-1,\n\t-1,-1,-1,-1,-1,-1,-1,-1\n};\n\n/* key scale level */\n/* table is 3dB/octave , DV converts this into 6dB/octave */\n/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */\n#define DV (0.1875/2.0)\nstatic const UINT32 ksl_tab[8*16]=\n{\n\t/* OCT 0 */\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t/* OCT 1 */\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,\n\t 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,\n\t/* OCT 2 */\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,\n\t 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,\n\t 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,\n\t/* OCT 3 */\n\t 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,\n\t 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,\n\t 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,\n\t 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,\n\t/* OCT 4 */\n\t 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,\n\t 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,\n\t 9.000/DV, 9.750/DV,10.125/DV,10.500/DV,\n\t10.875/DV,11.250/DV,11.625/DV,12.000/DV,\n\t/* OCT 5 */\n\t 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,\n\t 9.000/DV,10.125/DV,10.875/DV,11.625/DV,\n\t12.000/DV,12.750/DV,13.125/DV,13.500/DV,\n\t13.875/DV,14.250/DV,14.625/DV,15.000/DV,\n\t/* OCT 6 */\n\t 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,\n\t12.000/DV,13.125/DV,13.875/DV,14.625/DV,\n\t15.000/DV,15.750/DV,16.125/DV,16.500/DV,\n\t16.875/DV,17.250/DV,17.625/DV,18.000/DV,\n\t/* OCT 7 */\n\t 0.000/DV, 9.000/DV,12.000/DV,13.875/DV,\n\t15.000/DV,16.125/DV,16.875/DV,17.625/DV,\n\t18.000/DV,18.750/DV,19.125/DV,19.500/DV,\n\t19.875/DV,20.250/DV,20.625/DV,21.000/DV\n};\n#undef DV\n\n/* 0 / 3.0 / 1.5 / 6.0 dB/OCT */\nstatic const UINT32 ksl_shift[4] = { 31, 1, 2, 0 };\n\n\n/* sustain level table (3dB per step) */\n/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/\n#define SC(db) (UINT32) ( db * (2.0/ENV_STEP) )\nstatic const UINT32 sl_tab[16]={\n SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),\n SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)\n};\n#undef SC\n\n\n#define RATE_STEPS (8)\nstatic const unsigned char eg_inc[15*RATE_STEPS]={\n\n/*cycle:0 1  2 3  4 5  6 7*/\n\n/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */\n/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */\n/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */\n/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */\n\n/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */\n/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */\n/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */\n/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */\n\n/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */\n/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */\n/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */\n/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */\n\n/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */\n/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */\n/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */\n};\n\n\n#define O(a) (a*RATE_STEPS)\n\n/*note that there is no O(13) in this table - it's directly in the code */\nstatic const unsigned char eg_rate_select[16+64+16]={\t/* Envelope Generator rates (16 + 64 rates + 16 RKS) */\n/* 16 infinite time rates */\nO(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),\nO(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),\n\n/* rates 00-12 */\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\n\n/* rate 13 */\nO( 4),O( 5),O( 6),O( 7),\n\n/* rate 14 */\nO( 8),O( 9),O(10),O(11),\n\n/* rate 15 */\nO(12),O(12),O(12),O(12),\n\n/* 16 dummy rates (same as 15 3) */\nO(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),\nO(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),\n\n};\n#undef O\n\n/*rate  0,    1,    2,    3,   4,   5,   6,  7,  8,  9,  10, 11, 12, 13, 14, 15 */\n/*shift 12,   11,   10,   9,   8,   7,   6,  5,  4,  3,  2,  1,  0,  0,  0,  0  */\n/*mask  4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3,  1,  0,  0,  0,  0  */\n\n#define O(a) (a*1)\nstatic const unsigned char eg_rate_shift[16+64+16]={\t/* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */\n/* 16 infinite time rates */\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\n\n/* rates 00-12 */\nO(12),O(12),O(12),O(12),\nO(11),O(11),O(11),O(11),\nO(10),O(10),O(10),O(10),\nO( 9),O( 9),O( 9),O( 9),\nO( 8),O( 8),O( 8),O( 8),\nO( 7),O( 7),O( 7),O( 7),\nO( 6),O( 6),O( 6),O( 6),\nO( 5),O( 5),O( 5),O( 5),\nO( 4),O( 4),O( 4),O( 4),\nO( 3),O( 3),O( 3),O( 3),\nO( 2),O( 2),O( 2),O( 2),\nO( 1),O( 1),O( 1),O( 1),\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 13 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 14 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 15 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* 16 dummy rates (same as 15 3) */\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\n\n};\n#undef O\n\n\n/* multiple table */\n#define ML 2\nstatic const UINT8 mul_tab[16]= {\n/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */\n   0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,\n   8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML\n};\n#undef ML\n\n/*  TL_TAB_LEN is calculated as:\n*   12 - sinus amplitude bits     (Y axis)\n*   2  - sinus sign bit           (Y axis)\n*   TL_RES_LEN - sinus resolution (X axis)\n*/\n#define TL_TAB_LEN (12*2*TL_RES_LEN)\nstatic signed int tl_tab[TL_TAB_LEN];\n\n#define ENV_QUIET\t\t(TL_TAB_LEN>>4)\n\n/* sin waveform table in 'decibel' scale */\n/* four waveforms on OPL2 type chips */\nstatic unsigned int sin_tab[SIN_LEN * 4];\n\n\n/* LFO Amplitude Modulation table (verified on real YM3812)\n   27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples\n\n   Length: 210 elements.\n\n    Each of the elements has to be repeated\n    exactly 64 times (on 64 consecutive samples).\n    The whole table takes: 64 * 210 = 13440 samples.\n\n    When AM = 1 data is used directly\n    When AM = 0 data is divided by 4 before being used (losing precision is important)\n*/\n\n#define LFO_AM_TAB_ELEMENTS 210\n\nstatic const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = {\n0,0,0,0,0,0,0,\n1,1,1,1,\n2,2,2,2,\n3,3,3,3,\n4,4,4,4,\n5,5,5,5,\n6,6,6,6,\n7,7,7,7,\n8,8,8,8,\n9,9,9,9,\n10,10,10,10,\n11,11,11,11,\n12,12,12,12,\n13,13,13,13,\n14,14,14,14,\n15,15,15,15,\n16,16,16,16,\n17,17,17,17,\n18,18,18,18,\n19,19,19,19,\n20,20,20,20,\n21,21,21,21,\n22,22,22,22,\n23,23,23,23,\n24,24,24,24,\n25,25,25,25,\n26,26,26,\n25,25,25,25,\n24,24,24,24,\n23,23,23,23,\n22,22,22,22,\n21,21,21,21,\n20,20,20,20,\n19,19,19,19,\n18,18,18,18,\n17,17,17,17,\n16,16,16,16,\n15,15,15,15,\n14,14,14,14,\n13,13,13,13,\n12,12,12,12,\n11,11,11,11,\n10,10,10,10,\n9,9,9,9,\n8,8,8,8,\n7,7,7,7,\n6,6,6,6,\n5,5,5,5,\n4,4,4,4,\n3,3,3,3,\n2,2,2,2,\n1,1,1,1\n};\n\n/* LFO Phase Modulation table (verified on real YM3812) */\nstatic const INT8 lfo_pm_table[8*8*2] = {\n\n/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */\n0, 0, 0, 0, 0, 0, 0, 0,\t/*LFO PM depth = 0*/\n0, 0, 0, 0, 0, 0, 0, 0,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */\n0, 0, 0, 0, 0, 0, 0, 0,\t/*LFO PM depth = 0*/\n1, 0, 0, 0,-1, 0, 0, 0,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */\n1, 0, 0, 0,-1, 0, 0, 0,\t/*LFO PM depth = 0*/\n2, 1, 0,-1,-2,-1, 0, 1,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */\n1, 0, 0, 0,-1, 0, 0, 0,\t/*LFO PM depth = 0*/\n3, 1, 0,-1,-3,-1, 0, 1,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */\n2, 1, 0,-1,-2,-1, 0, 1,\t/*LFO PM depth = 0*/\n4, 2, 0,-2,-4,-2, 0, 2,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */\n2, 1, 0,-1,-2,-1, 0, 1,\t/*LFO PM depth = 0*/\n5, 2, 0,-2,-5,-2, 0, 2,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */\n3, 1, 0,-1,-3,-1, 0, 1,\t/*LFO PM depth = 0*/\n6, 3, 0,-3,-6,-3, 0, 3,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */\n3, 1, 0,-1,-3,-1, 0, 1,\t/*LFO PM depth = 0*/\n7, 3, 0,-3,-7,-3, 0, 3\t/*LFO PM depth = 1*/\n};\n\n\n/* lock level of common table */\nstatic int num_lock = 0;\n\n\n#define SLOT7_1 (&OPL->P_CH[7].SLOT[SLOT1])\n#define SLOT7_2 (&OPL->P_CH[7].SLOT[SLOT2])\n#define SLOT8_1 (&OPL->P_CH[8].SLOT[SLOT1])\n#define SLOT8_2 (&OPL->P_CH[8].SLOT[SLOT2])\n\n\n\n\n/*INLINE int limit( int val, int max, int min ) {\n\tif ( val > max )\n\t\tval = max;\n\telse if ( val < min )\n\t\tval = min;\n\n\treturn val;\n}*/\n\n\n/* status set and IRQ handling */\nINLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)\n{\n\t/* set status flag */\n\tOPL->status |= flag;\n\tif(!(OPL->status & 0x80))\n\t{\n\t\tif(OPL->status & OPL->statusmask)\n\t\t{\t/* IRQ on */\n\t\t\tOPL->status |= 0x80;\n\t\t\t/* callback user interrupt handler (IRQ is OFF to ON) */\n\t\t\tif(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);\n\t\t}\n\t}\n}\n\n/* status reset and IRQ handling */\nINLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)\n{\n\t/* reset status flag */\n\tOPL->status &=~flag;\n\tif((OPL->status & 0x80))\n\t{\n\t\tif (!(OPL->status & OPL->statusmask) )\n\t\t{\n\t\t\tOPL->status &= 0x7f;\n\t\t\t/* callback user interrupt handler (IRQ is ON to OFF) */\n\t\t\tif(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);\n\t\t}\n\t}\n}\n\n/* IRQ mask set */\nINLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)\n{\n\tOPL->statusmask = flag;\n\t/* IRQ handling check */\n\tOPL_STATUS_SET(OPL,0);\n\tOPL_STATUS_RESET(OPL,0);\n}\n\n\n/* advance LFO to next sample */\nINLINE void advance_lfo(FM_OPL *OPL)\n{\n\tUINT8 tmp;\n\n\t/* LFO */\n\tOPL->lfo_am_cnt += OPL->lfo_am_inc;\n\tif (OPL->lfo_am_cnt >= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH) )\t/* lfo_am_table is 210 elements long */\n\t\tOPL->lfo_am_cnt -= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH);\n\n\ttmp = lfo_am_table[ OPL->lfo_am_cnt >> LFO_SH ];\n\n\tif (OPL->lfo_am_depth)\n\t\tOPL->LFO_AM = tmp;\n\telse\n\t\tOPL->LFO_AM = tmp>>2;\n\n\tOPL->lfo_pm_cnt += OPL->lfo_pm_inc;\n\tOPL->LFO_PM = ((OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range;\n}\n\nINLINE void refresh_eg(FM_OPL* OPL)\n{\n\tOPL_CH *CH;\n\tOPL_SLOT *op;\n\tint i;\n\tint new_vol;\n\n\tfor (i=0; i<9*2; i++)\n\t{\n\t\tCH  = &OPL->P_CH[i/2];\n\t\top  = &CH->SLOT[i&1];\n\n\t\t// Envelope Generator\n\t\tswitch(op->state)\n\t\t{\n\t\tcase EG_ATT:\t\t// attack phase\n\t\t\tif ( !(OPL->eg_cnt & ((1<<op->eg_sh_ar)-1) ) )\n\t\t\t{\n\t\t\t\tnew_vol = op->volume + ((~op->volume *\n\t\t\t\t\t\t\t   (eg_inc[op->eg_sel_ar + ((OPL->eg_cnt>>op->eg_sh_ar)&7)])\n\t\t\t\t\t\t\t  ) >> 3);\n\t\t\t\tif (new_vol <= MIN_ATT_INDEX)\n\t\t\t\t{\n\t\t\t\t\top->volume = MIN_ATT_INDEX;\n\t\t\t\t\top->state = EG_DEC;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t/*case EG_DEC:\t// decay phase\n\t\t\tif ( !(OPL->eg_cnt & ((1<<op->eg_sh_dr)-1) ) )\n\t\t\t{\n\t\t\t\tnew_vol = op->volume + eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)];\n\n\t\t\t\tif ( new_vol >= op->sl )\n\t\t\t\t\top->state = EG_SUS;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase EG_SUS:\t// sustain phase\n\t\t\tif ( !op->eg_type)\tpercussive mode\n\t\t\t{\n\t\t\t\tnew_vol = op->volume + eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];\n\n\t\t\t\tif ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\n\t\t\t\t{\n\t\t\t\t\tif ( new_vol >= MAX_ATT_INDEX )\n\t\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase EG_REL:\t// release phase\n\t\t\tif ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\n\t\t\t{\n\t\t\t\tnew_vol = op->volume + eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];\n\t\t\t\tif ( new_vol >= MAX_ATT_INDEX )\n\t\t\t\t{\n\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t\top->state = EG_OFF;\n\t\t\t\t}\n\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;*/\n\t\t}\n\t}\n\t\n\treturn;\n}\n\n/* advance to next sample */\nINLINE void advance(FM_OPL *OPL)\n{\n\tOPL_CH *CH;\n\tOPL_SLOT *op;\n\tint i;\n\n\tOPL->eg_timer += OPL->eg_timer_add;\n\n\twhile (OPL->eg_timer >= OPL->eg_timer_overflow)\n\t{\n\t\tOPL->eg_timer -= OPL->eg_timer_overflow;\n\n\t\tOPL->eg_cnt++;\n\n\t\tfor (i=0; i<9*2; i++)\n\t\t{\n\t\t\tCH  = &OPL->P_CH[i/2];\n\t\t\top  = &CH->SLOT[i&1];\n\n\t\t\t/* Envelope Generator */\n\t\t\tswitch(op->state)\n\t\t\t{\n\t\t\tcase EG_ATT:\t\t/* attack phase */\n\t\t\t\tif ( !(OPL->eg_cnt & ((1<<op->eg_sh_ar)-1) ) )\n\t\t\t\t{\n\t\t\t\t\top->volume += (~op->volume *\n\t\t\t\t\t\t\t   (eg_inc[op->eg_sel_ar + ((OPL->eg_cnt>>op->eg_sh_ar)&7)])\n\t\t\t\t\t\t\t  ) >>3;\n\n\t\t\t\t\tif (op->volume <= MIN_ATT_INDEX)\n\t\t\t\t\t{\n\t\t\t\t\t\top->volume = MIN_ATT_INDEX;\n\t\t\t\t\t\top->state = EG_DEC;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_DEC:\t/* decay phase */\n\t\t\t\tif ( !(OPL->eg_cnt & ((1<<op->eg_sh_dr)-1) ) )\n\t\t\t\t{\n\t\t\t\t\top->volume += eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)];\n\n\t\t\t\t\tif ( op->volume >= op->sl )\n\t\t\t\t\t\top->state = EG_SUS;\n\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_SUS:\t/* sustain phase */\n\n\t\t\t\t/* this is important behaviour:\n                one can change percusive/non-percussive modes on the fly and\n                the chip will remain in sustain phase - verified on real YM3812 */\n\n\t\t\t\tif(op->eg_type)\t\t/* non-percussive mode */\n\t\t\t\t{\n\t\t\t\t\t\t\t\t\t/* do nothing */\n\t\t\t\t}\n\t\t\t\telse\t\t\t\t/* percussive mode */\n\t\t\t\t{\n\t\t\t\t\t/* during sustain phase chip adds Release Rate (in percussive mode) */\n\t\t\t\t\tif ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\n\t\t\t\t\t{\n\t\t\t\t\t\top->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];\n\n\t\t\t\t\t\tif ( op->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t\t}\n\t\t\t\t\t/* else do nothing in sustain phase */\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_REL:\t/* release phase */\n\t\t\t\tif ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\n\t\t\t\t{\n\t\t\t\t\top->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];\n\n\t\t\t\t\tif ( op->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t{\n\t\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t\t\top->state = EG_OFF;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (i=0; i<9*2; i++)\n\t{\n\t\tCH  = &OPL->P_CH[i/2];\n\t\top  = &CH->SLOT[i&1];\n\n\t\t/* Phase Generator */\n\t\tif(op->vib)\n\t\t{\n\t\t\tUINT8 block;\n\t\t\tunsigned int block_fnum = CH->block_fnum;\n\n\t\t\tunsigned int fnum_lfo   = (block_fnum&0x0380) >> 7;\n\n\t\t\tsigned int lfo_fn_table_index_offset = lfo_pm_table[OPL->LFO_PM + 16*fnum_lfo ];\n\n\t\t\tif (lfo_fn_table_index_offset)\t/* LFO phase modulation active */\n\t\t\t{\n\t\t\t\tblock_fnum += lfo_fn_table_index_offset;\n\t\t\t\tblock = (block_fnum&0x1c00) >> 10;\n\t\t\t\top->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul;\n\t\t\t}\n\t\t\telse\t/* LFO phase modulation  = zero */\n\t\t\t{\n\t\t\t\top->Cnt += op->Incr;\n\t\t\t}\n\t\t}\n\t\telse\t/* LFO phase modulation disabled for this operator */\n\t\t{\n\t\t\top->Cnt += op->Incr;\n\t\t}\n\t}\n\n\t/*  The Noise Generator of the YM3812 is 23-bit shift register.\n    *   Period is equal to 2^23-2 samples.\n    *   Register works at sampling frequency of the chip, so output\n    *   can change on every sample.\n    *\n    *   Output of the register and input to the bit 22 is:\n    *   bit0 XOR bit14 XOR bit15 XOR bit22\n    *\n    *   Simply use bit 22 as the noise output.\n    */\n\n\tOPL->noise_p += OPL->noise_f;\n\ti = OPL->noise_p >> FREQ_SH;\t\t/* number of events (shifts of the shift register) */\n\tOPL->noise_p &= FREQ_MASK;\n\twhile (i)\n\t{\n\t\t/*\n        UINT32 j;\n        j = ( (OPL->noise_rng) ^ (OPL->noise_rng>>14) ^ (OPL->noise_rng>>15) ^ (OPL->noise_rng>>22) ) & 1;\n        OPL->noise_rng = (j<<22) | (OPL->noise_rng>>1);\n        */\n\n\t\t/*\n            Instead of doing all the logic operations above, we\n            use a trick here (and use bit 0 as the noise output).\n            The difference is only that the noise bit changes one\n            step ahead. This doesn't matter since we don't know\n            what is real state of the noise_rng after the reset.\n        */\n\n\t\tif (OPL->noise_rng & 1) OPL->noise_rng ^= 0x800302;\n\t\tOPL->noise_rng >>= 1;\n\n\t\ti--;\n\t}\n}\n\n\nINLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)\n{\n\tUINT32 p;\n\n\tp = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ];\n\n\tif (p >= TL_TAB_LEN)\n\t\treturn 0;\n\treturn tl_tab[p];\n}\n\nINLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)\n{\n\tUINT32 p;\n\n\tp = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm      )) >> FREQ_SH ) & SIN_MASK) ];\n\n\tif (p >= TL_TAB_LEN)\n\t\treturn 0;\n\treturn tl_tab[p];\n}\n\n\n#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (OPL->LFO_AM & (OP)->AMmask))\n\n/* calculate output */\nINLINE void OPL_CALC_CH( FM_OPL *OPL, OPL_CH *CH )\n{\n\tOPL_SLOT *SLOT;\n\tunsigned int env;\n\tsigned int out;\n\n\tif (CH->Muted)\n\t\treturn;\n\n\tOPL->phase_modulation = 0;\n\n\t/* SLOT 1 */\n\tSLOT = &CH->SLOT[SLOT1];\n\tenv  = volume_calc(SLOT);\n\tout  = SLOT->op1_out[0] + SLOT->op1_out[1];\n\tSLOT->op1_out[0] = SLOT->op1_out[1];\n\t*SLOT->connect1 += SLOT->op1_out[0];\n\tSLOT->op1_out[1] = 0;\n\tif( env < ENV_QUIET )\n\t{\n\t\tif (!SLOT->FB)\n\t\t\tout = 0;\n\t\tSLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );\n\t}\n\n\t/* SLOT 2 */\n\tSLOT++;\n\tenv = volume_calc(SLOT);\n\tif( env < ENV_QUIET )\n\t\tOPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable);\n}\n\n/*\n    operators used in the rhythm sounds generation process:\n\n    Envelope Generator:\n\nchannel  operator  register number   Bass  High  Snare Tom  Top\n/ slot   number    TL ARDR SLRR Wave Drum  Hat   Drum  Tom  Cymbal\n 6 / 0   12        50  70   90   f0  +\n 6 / 1   15        53  73   93   f3  +\n 7 / 0   13        51  71   91   f1        +\n 7 / 1   16        54  74   94   f4              +\n 8 / 0   14        52  72   92   f2                    +\n 8 / 1   17        55  75   95   f5                          +\n\n    Phase Generator:\n\nchannel  operator  register number   Bass  High  Snare Tom  Top\n/ slot   number    MULTIPLE          Drum  Hat   Drum  Tom  Cymbal\n 6 / 0   12        30                +\n 6 / 1   15        33                +\n 7 / 0   13        31                      +     +           +\n 7 / 1   16        34                -----  n o t  u s e d -----\n 8 / 0   14        32                                  +\n 8 / 1   17        35                      +                 +\n\nchannel  operator  register number   Bass  High  Snare Tom  Top\nnumber   number    BLK/FNUM2 FNUM    Drum  Hat   Drum  Tom  Cymbal\n   6     12,15     B6        A6      +\n\n   7     13,16     B7        A7            +     +           +\n\n   8     14,17     B8        A8            +           +     +\n\n*/\n\n/* calculate rhythm */\n\nINLINE void OPL_CALC_RH( FM_OPL *OPL, OPL_CH *CH, unsigned int noise )\n{\n\tOPL_SLOT *SLOT;\n\tsigned int out;\n\tunsigned int env;\n\n\n\t/* Bass Drum (verified on real YM3812):\n      - depends on the channel 6 'connect' register:\n          when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out)\n          when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored\n      - output sample always is multiplied by 2\n    */\n\n\tOPL->phase_modulation = 0;\n\t/* SLOT 1 */\n\tSLOT = &CH[6].SLOT[SLOT1];\n\tenv = volume_calc(SLOT);\n\n\tout = SLOT->op1_out[0] + SLOT->op1_out[1];\n\tSLOT->op1_out[0] = SLOT->op1_out[1];\n\n\tif (!SLOT->CON)\n\t\tOPL->phase_modulation = SLOT->op1_out[0];\n\t/* else ignore output of operator 1 */\n\n\tSLOT->op1_out[1] = 0;\n\tif( env < ENV_QUIET )\n\t{\n\t\tif (!SLOT->FB)\n\t\t\tout = 0;\n\t\tSLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );\n\t}\n\n\t/* SLOT 2 */\n\tSLOT++;\n\tenv = volume_calc(SLOT);\n\tif( env < ENV_QUIET && ! OPL->MuteSpc[0] )\n\t\tOPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable) * 2;\n\n\n\t/* Phase generation is based on: */\n\t/* HH  (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) */\n\t/* SD  (16) channel 7->slot 1 */\n\t/* TOM (14) channel 8->slot 1 */\n\t/* TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */\n\n\t/* Envelope generation based on: */\n\t/* HH  channel 7->slot1 */\n\t/* SD  channel 7->slot2 */\n\t/* TOM channel 8->slot1 */\n\t/* TOP channel 8->slot2 */\n\n\n\t/* The following formulas can be well optimized.\n       I leave them in direct form for now (in case I've missed something).\n    */\n\n\t/* High Hat (verified on real YM3812) */\n\tenv = volume_calc(SLOT7_1);\n\tif( env < ENV_QUIET && ! OPL->MuteSpc[4] )\n\t{\n\n\t\t/* high hat phase generation:\n            phase = d0 or 234 (based on frequency only)\n            phase = 34 or 2d0 (based on noise)\n        */\n\n\t\t/* base frequency derived from operator 1 in channel 7 */\n\t\tunsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;\n\t\tunsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;\n\t\tunsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;\n\n\t\tunsigned char res1 = (bit2 ^ bit7) | bit3;\n\n\t\t/* when res1 = 0 phase = 0x000 | 0xd0; */\n\t\t/* when res1 = 1 phase = 0x200 | (0xd0>>2); */\n\t\tUINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;\n\n\t\t/* enable gate based on frequency of operator 2 in channel 8 */\n\t\tunsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;\n\t\tunsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;\n\n\t\tunsigned char res2 = (bit3e ^ bit5e);\n\n\t\t/* when res2 = 0 pass the phase from calculation above (res1); */\n\t\t/* when res2 = 1 phase = 0x200 | (0xd0>>2); */\n\t\tif (res2)\n\t\t\tphase = (0x200|(0xd0>>2));\n\n\n\t\t/* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */\n\t\t/* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */\n\t\tif (phase&0x200)\n\t\t{\n\t\t\tif (noise)\n\t\t\t\tphase = 0x200|0xd0;\n\t\t}\n\t\telse\n\t\t/* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */\n\t\t/* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */\n\t\t{\n\t\t\tif (noise)\n\t\t\t\tphase = 0xd0>>2;\n\t\t}\n\n\t\tOPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1->wavetable) * 2;\n\t}\n\n\t/* Snare Drum (verified on real YM3812) */\n\tenv = volume_calc(SLOT7_2);\n\tif( env < ENV_QUIET && ! OPL->MuteSpc[1] )\n\t{\n\t\t/* base frequency derived from operator 1 in channel 7 */\n\t\tunsigned char bit8 = ((SLOT7_1->Cnt>>FREQ_SH)>>8)&1;\n\n\t\t/* when bit8 = 0 phase = 0x100; */\n\t\t/* when bit8 = 1 phase = 0x200; */\n\t\tUINT32 phase = bit8 ? 0x200 : 0x100;\n\n\t\t/* Noise bit XOR'es phase by 0x100 */\n\t\t/* when noisebit = 0 pass the phase from calculation above */\n\t\t/* when noisebit = 1 phase ^= 0x100; */\n\t\t/* in other words: phase ^= (noisebit<<8); */\n\t\tif (noise)\n\t\t\tphase ^= 0x100;\n\n\t\tOPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2->wavetable) * 2;\n\t}\n\n\t/* Tom Tom (verified on real YM3812) */\n\tenv = volume_calc(SLOT8_1);\n\tif( env < ENV_QUIET && ! OPL->MuteSpc[2] )\n\t\tOPL->output[0] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2;\n\n\t/* Top Cymbal (verified on real YM3812) */\n\tenv = volume_calc(SLOT8_2);\n\tif( env < ENV_QUIET && ! OPL->MuteSpc[3] )\n\t{\n\t\t/* base frequency derived from operator 1 in channel 7 */\n\t\tunsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;\n\t\tunsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;\n\t\tunsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;\n\n\t\tunsigned char res1 = (bit2 ^ bit7) | bit3;\n\n\t\t/* when res1 = 0 phase = 0x000 | 0x100; */\n\t\t/* when res1 = 1 phase = 0x200 | 0x100; */\n\t\tUINT32 phase = res1 ? 0x300 : 0x100;\n\n\t\t/* enable gate based on frequency of operator 2 in channel 8 */\n\t\tunsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;\n\t\tunsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;\n\n\t\tunsigned char res2 = (bit3e ^ bit5e);\n\t\t/* when res2 = 0 pass the phase from calculation above (res1); */\n\t\t/* when res2 = 1 phase = 0x200 | 0x100; */\n\t\tif (res2)\n\t\t\tphase = 0x300;\n\n\t\tOPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2->wavetable) * 2;\n\t}\n}\n\n\n/* generic table initialize */\nstatic int init_tables(void)\n{\n\tsigned int i,x;\n\tsigned int n;\n\tdouble o,m;\n\n\n\tfor (x=0; x<TL_RES_LEN; x++)\n\t{\n\t\tm = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);\n\t\tm = floor(m);\n\n\t\t/* we never reach (1<<16) here due to the (x+1) */\n\t\t/* result fits within 16 bits at maximum */\n\n\t\tn = (int)m;\t\t/* 16 bits here */\n\t\tn >>= 4;\t\t/* 12 bits here */\n\t\tif (n&1)\t\t/* round to nearest */\n\t\t\tn = (n>>1)+1;\n\t\telse\n\t\t\tn = n>>1;\n\t\t\t\t\t\t/* 11 bits here (rounded) */\n\t\tn <<= 1;\t\t/* 12 bits here (as in real chip) */\n\t\ttl_tab[ x*2 + 0 ] = n;\n\t\ttl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];\n\n\t\tfor (i=1; i<12; i++)\n\t\t{\n\t\t\ttl_tab[ x*2+0 + i*2*TL_RES_LEN ] =  tl_tab[ x*2+0 ]>>i;\n\t\t\ttl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];\n\t\t}\n\t#if 0\n\t\t\tlogerror(\"tl %04i\", x*2);\n\t\t\tfor (i=0; i<12; i++)\n\t\t\t\tlogerror(\", [%02i] %5i\", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] );\n\t\t\tlogerror(\"\\n\");\n\t#endif\n\t}\n\t/*logerror(\"FMOPL.C: TL_TAB_LEN = %i elements (%i bytes)\\n\",TL_TAB_LEN, (int)sizeof(tl_tab));*/\n\n\n\tfor (i=0; i<SIN_LEN; i++)\n\t{\n\t\t/* non-standard sinus */\n\t\tm = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */\n\n\t\t/* we never reach zero here due to ((i*2)+1) */\n\n\t\tif (m>0.0)\n\t\t\to = 8*log(1.0/m)/log(2.0);\t/* convert to 'decibels' */\n\t\telse\n\t\t\to = 8*log(-1.0/m)/log(2.0);\t/* convert to 'decibels' */\n\n\t\to = o / (ENV_STEP/4);\n\n\t\tn = (int)(2.0*o);\n\t\tif (n&1)\t\t\t\t\t\t/* round to nearest */\n\t\t\tn = (n>>1)+1;\n\t\telse\n\t\t\tn = n>>1;\n\n\t\tsin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );\n\n\t\t/*logerror(\"FMOPL.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\\n\", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/\n\t}\n\n\tfor (i=0; i<SIN_LEN; i++)\n\t{\n\t\t/* waveform 1:  __      __     */\n\t\t/*             /  \\____/  \\____*/\n\t\t/* output only first half of the sinus waveform (positive one) */\n\n\t\tif (i & (1<<(SIN_BITS-1)) )\n\t\t\tsin_tab[1*SIN_LEN+i] = TL_TAB_LEN;\n\t\telse\n\t\t\tsin_tab[1*SIN_LEN+i] = sin_tab[i];\n\n\t\t/* waveform 2:  __  __  __  __ */\n\t\t/*             /  \\/  \\/  \\/  \\*/\n\t\t/* abs(sin) */\n\n\t\tsin_tab[2*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>1) ];\n\n\t\t/* waveform 3:  _   _   _   _  */\n\t\t/*             / |_/ |_/ |_/ |_*/\n\t\t/* abs(output only first quarter of the sinus waveform) */\n\n\t\tif (i & (1<<(SIN_BITS-2)) )\n\t\t\tsin_tab[3*SIN_LEN+i] = TL_TAB_LEN;\n\t\telse\n\t\t\tsin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)];\n\n\t\t/*logerror(\"FMOPL.C: sin1[%4i]= %4i (tl_tab value=%5i)\\n\", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] );\n        logerror(\"FMOPL.C: sin2[%4i]= %4i (tl_tab value=%5i)\\n\", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] );\n        logerror(\"FMOPL.C: sin3[%4i]= %4i (tl_tab value=%5i)\\n\", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] );*/\n\t}\n\t/*logerror(\"FMOPL.C: ENV_QUIET= %08x (dec*8=%i)\\n\", ENV_QUIET, ENV_QUIET*8 );*/\n\n\n#ifdef SAVE_SAMPLE\n\tsample[0]=fopen(\"sampsum.pcm\",\"wb\");\n#endif\n\n\treturn 1;\n}\n\nstatic void OPLCloseTable( void )\n{\n#ifdef SAVE_SAMPLE\n\tfclose(sample[0]);\n#endif\n}\n\n\n\nstatic void OPL_initalize(FM_OPL *OPL)\n{\n\tint i;\n\n\t/* frequency base */\n\tOPL->freqbase  = (OPL->rate) ? ((double)OPL->clock / 72.0) / OPL->rate  : 0;\n#if 0\n\tOPL->rate = (double)OPL->clock / 72.0;\n\tOPL->freqbase  = 1.0;\n#endif\n\n\t/*logerror(\"freqbase=%f\\n\", OPL->freqbase);*/\n\n\t/* Timer base time */\n\t//OPL->TimerBase = attotime_mul(ATTOTIME_IN_HZ(OPL->clock), 72);\n\n\t/* make fnumber -> increment counter table */\n\tfor( i=0 ; i < 1024 ; i++ )\n\t{\n\t\t/* opn phase increment counter = 20bit */\n\t\tOPL->fn_tab[i] = (UINT32)( (double)i * 64 * OPL->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */\n#if 0\n\t\tlogerror(\"FMOPL.C: fn_tab[%4i] = %08x (dec=%8i)\\n\",\n\t\t\t\t i, OPL->fn_tab[i]>>6, OPL->fn_tab[i]>>6 );\n#endif\n\t}\n\n#if 0\n\tfor( i=0 ; i < 16 ; i++ )\n\t{\n\t\tlogerror(\"FMOPL.C: sl_tab[%i] = %08x\\n\",\n\t\t\ti, sl_tab[i] );\n\t}\n\tfor( i=0 ; i < 8 ; i++ )\n\t{\n\t\tint j;\n\t\tlogerror(\"FMOPL.C: ksl_tab[oct=%2i] =\",i);\n\t\tfor (j=0; j<16; j++)\n\t\t{\n\t\t\tlogerror(\"%08x \", ksl_tab[i*16+j] );\n\t\t}\n\t\tlogerror(\"\\n\");\n\t}\n#endif\n\n\tfor(i = 0; i < 9; i ++)\n\t\tOPL->P_CH[i].Muted = 0x00;\n\tfor(i = 0; i < 6; i ++)\n\t\tOPL->MuteSpc[i] = 0x00;\n\n\n\t/* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */\n\t/* One entry from LFO_AM_TABLE lasts for 64 samples */\n\tOPL->lfo_am_inc = (1.0 / 64.0 ) * (1<<LFO_SH) * OPL->freqbase;\n\n\t/* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */\n\tOPL->lfo_pm_inc = (1.0 / 1024.0) * (1<<LFO_SH) * OPL->freqbase;\n\n\t/*logerror (\"OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\\n\", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/\n\n\t/* Noise generator: a step takes 1 sample */\n\tOPL->noise_f = (1.0 / 1.0) * (1<<FREQ_SH) * OPL->freqbase;\n\n\tOPL->eg_timer_add  = (1<<EG_SH)  * OPL->freqbase;\n\tOPL->eg_timer_overflow = ( 1 ) * (1<<EG_SH);\n\t/*logerror(\"OPLinit eg_timer_add=%8x eg_timer_overflow=%8x\\n\", OPL->eg_timer_add, OPL->eg_timer_overflow);*/\n\n}\n\nINLINE void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set)\n{\n\tif( !SLOT->key )\n\t{\n\t\t/* restart Phase Generator */\n\t\tSLOT->Cnt = 0;\n\t\t/* phase -> Attack */\n\t\tSLOT->state = EG_ATT;\n\t}\n\tSLOT->key |= key_set;\n}\n\nINLINE void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr)\n{\n\tif( SLOT->key )\n\t{\n\t\tSLOT->key &= key_clr;\n\n\t\tif( !SLOT->key )\n\t\t{\n\t\t\t/* phase -> Release */\n\t\t\tif (SLOT->state>EG_REL)\n\t\t\t\tSLOT->state = EG_REL;\n\t\t}\n\t}\n}\n\n/* update phase increment counter of operator (also update the EG rates if necessary) */\nINLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)\n{\n\tint ksr;\n\n\t/* (frequency) phase increment counter */\n\tSLOT->Incr = CH->fc * SLOT->mul;\n\tksr = CH->kcode >> SLOT->KSR;\n\n\tif( SLOT->ksr != ksr )\n\t{\n\t\tSLOT->ksr = ksr;\n\n\t\t/* calculate envelope generator rates */\n\t\tif ((SLOT->ar + SLOT->ksr) < 16+62)\n\t\t{\n\t\t\tSLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];\n\t\t\tSLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSLOT->eg_sh_ar  = 0;\n\t\t\tSLOT->eg_sel_ar = 13*RATE_STEPS;\n\t\t}\n\t\tSLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];\n\t\tSLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];\n\t\tSLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];\n\t\tSLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];\n\t}\n}\n\n/* set multi,am,vib,EG-TYP,KSR,mul */\nINLINE void set_mul(FM_OPL *OPL,int slot,int v)\n{\n\tOPL_CH   *CH   = &OPL->P_CH[slot/2];\n\tOPL_SLOT *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->mul     = mul_tab[v&0x0f];\n\tSLOT->KSR     = (v&0x10) ? 0 : 2;\n\tSLOT->eg_type = (v&0x20);\n\tSLOT->vib     = (v&0x40);\n\tSLOT->AMmask  = (v&0x80) ? ~0 : 0;\n\tCALC_FCSLOT(CH,SLOT);\n}\n\n/* set ksl & tl */\nINLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)\n{\n\tOPL_CH   *CH   = &OPL->P_CH[slot/2];\n\tOPL_SLOT *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->ksl = ksl_shift[v >> 6];\n\tSLOT->TL  = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */\n\n\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n}\n\n/* set attack rate & decay rate  */\nINLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)\n{\n\tOPL_CH   *CH   = &OPL->P_CH[slot/2];\n\tOPL_SLOT *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->ar = (v>>4)  ? 16 + ((v>>4)  <<2) : 0;\n\n\tif ((SLOT->ar + SLOT->ksr) < 16+62)\n\t{\n\t\tSLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];\n\t\tSLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];\n\t}\n\telse\n\t{\n\t\tSLOT->eg_sh_ar  = 0;\n\t\tSLOT->eg_sel_ar = 13*RATE_STEPS;\n\t}\n\n\tSLOT->dr    = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;\n\tSLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];\n\tSLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];\n}\n\n/* set sustain level & release rate */\nINLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)\n{\n\tOPL_CH   *CH   = &OPL->P_CH[slot/2];\n\tOPL_SLOT *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->sl  = sl_tab[ v>>4 ];\n\n\tSLOT->rr  = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;\n\tSLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];\n\tSLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];\n}\n\n\n/* write a value v to register r on OPL chip */\nstatic void OPLWriteReg(FM_OPL *OPL, int r, int v)\n{\n\tOPL_CH *CH;\n\tint slot;\n\tint block_fnum;\n\n\n\t/* adjust bus to 8 bits */\n\tr &= 0xff;\n\tv &= 0xff;\n\n\t/*if (LOG_CYM_FILE && (cymfile) && (r!=0) )\n\t{\n\t\tfputc( (unsigned char)r, cymfile );\n\t\tfputc( (unsigned char)v, cymfile );\n\t}*/\n\n\n\tswitch(r&0xe0)\n\t{\n\tcase 0x00:\t/* 00-1f:control */\n\t\tswitch(r&0x1f)\n\t\t{\n\t\tcase 0x01:\t/* waveform select enable */\n\t\t\tif(OPL->type&OPL_TYPE_WAVESEL)\n\t\t\t{\n\t\t\t\tOPL->wavesel = v&0x20;\n\t\t\t\t/* do not change the waveform previously selected */\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 0x02:\t/* Timer 1 */\n\t\t\tOPL->T[0] = (256-v)*4;\n\t\t\tbreak;\n\t\tcase 0x03:\t/* Timer 2 */\n\t\t\tOPL->T[1] = (256-v)*16;\n\t\t\tbreak;\n\t\tcase 0x04:\t/* IRQ clear / mask and Timer enable */\n\t\t\tif(v&0x80)\n\t\t\t{\t/* IRQ flag clear */\n\t\t\t\tOPL_STATUS_RESET(OPL,0x7f-0x08); /* don't reset BFRDY flag or we will have to call deltat module to set the flag */\n\t\t\t}\n\t\t\telse\n\t\t\t{\t/* set IRQ mask ,timer enable*/\n\t\t\t\tUINT8 st1 = v&1;\n\t\t\t\tUINT8 st2 = (v>>1)&1;\n\n\t\t\t\t/* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */\n\t\t\t\tOPL_STATUS_RESET(OPL, v & (0x78-0x08) );\n\t\t\t\tOPL_STATUSMASK_SET(OPL, (~v) & 0x78 );\n\n\t\t\t\t/* timer 2 */\n\t\t\t\tif(OPL->st[1] != st2)\n\t\t\t\t{\n\t\t\t\t\t//attotime period = st2 ? attotime_mul(OPL->TimerBase, OPL->T[1]) : attotime_zero;\n\t\t\t\t\tOPL->st[1] = st2;\n\t\t\t\t\t//if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,1,period);\n\t\t\t\t}\n\t\t\t\t/* timer 1 */\n\t\t\t\tif(OPL->st[0] != st1)\n\t\t\t\t{\n\t\t\t\t\t//attotime period = st1 ? attotime_mul(OPL->TimerBase, OPL->T[0]) : attotime_zero;\n\t\t\t\t\tOPL->st[0] = st1;\n\t\t\t\t\t//if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,0,period);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n#if BUILD_Y8950\n\t\tcase 0x06:\t\t/* Key Board OUT */\n\t\t\tif(OPL->type&OPL_TYPE_KEYBOARD)\n\t\t\t{\n\t\t\t\tif(OPL->keyboardhandler_w)\n\t\t\t\t\tOPL->keyboardhandler_w(OPL->keyboard_param,v);\n#ifdef _DEBUG\n\t\t\t\telse\n\t\t\t\t\tlogerror(\"Y8950: write unmapped KEYBOARD port\\n\");\n#endif\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 0x07:\t/* DELTA-T control 1 : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */\n\t\t\tif(OPL->type&OPL_TYPE_ADPCM)\n\t\t\t\tYM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);\n\t\t\tbreak;\n#endif\n\t\tcase 0x08:\t/* MODE,DELTA-T control 2 : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */\n\t\t\tOPL->mode = v;\n#if BUILD_Y8950\n\t\t\tif(OPL->type&OPL_TYPE_ADPCM)\n\t\t\t\tYM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v&0x0f); /* mask 4 LSBs in register 08 for DELTA-T unit */\n#endif\n\t\t\tbreak;\n\n#if BUILD_Y8950\n\t\tcase 0x09:\t\t/* START ADD */\n\t\tcase 0x0a:\n\t\tcase 0x0b:\t\t/* STOP ADD  */\n\t\tcase 0x0c:\n\t\tcase 0x0d:\t\t/* PRESCALE   */\n\t\tcase 0x0e:\n\t\tcase 0x0f:\t\t/* ADPCM data write */\n\t\tcase 0x10:\t\t/* DELTA-N    */\n\t\tcase 0x11:\t\t/* DELTA-N    */\n\t\tcase 0x12:\t\t/* ADPCM volume */\n\t\t\tif(OPL->type&OPL_TYPE_ADPCM)\n\t\t\t\tYM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);\n\t\t\tbreak;\n\n\t\tcase 0x15:\t\t/* DAC data high 8 bits (F7,F6...F2) */\n\t\tcase 0x16:\t\t/* DAC data low 2 bits (F1, F0 in bits 7,6) */\n\t\tcase 0x17:\t\t/* DAC data shift (S2,S1,S0 in bits 2,1,0) */\n#ifdef _DEBUG\n\t\t\tlogerror(\"FMOPL.C: DAC data register written, but not implemented reg=%02x val=%02x\\n\",r,v);\n#endif\n\t\t\tbreak;\n\n\t\tcase 0x18:\t\t/* I/O CTRL (Direction) */\n\t\t\tif(OPL->type&OPL_TYPE_IO)\n\t\t\t\tOPL->portDirection = v&0x0f;\n\t\t\tbreak;\n\t\tcase 0x19:\t\t/* I/O DATA */\n\t\t\tif(OPL->type&OPL_TYPE_IO)\n\t\t\t{\n\t\t\t\tOPL->portLatch = v;\n\t\t\t\tif(OPL->porthandler_w)\n\t\t\t\t\tOPL->porthandler_w(OPL->port_param,v&OPL->portDirection);\n\t\t\t}\n\t\t\tbreak;\n#endif\n\t\tdefault:\n#ifdef _DEBUG\n\t\t\tlogerror(\"FMOPL.C: write to unknown register: %02x\\n\",r);\n#endif\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase 0x20:\t/* am ON, vib ON, ksr, eg_type, mul */\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot < 0) return;\n\t\tset_mul(OPL,slot,v);\n\t\tbreak;\n\tcase 0x40:\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot < 0) return;\n\t\tset_ksl_tl(OPL,slot,v);\n\t\tbreak;\n\tcase 0x60:\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot < 0) return;\n\t\tset_ar_dr(OPL,slot,v);\n\t\tbreak;\n\tcase 0x80:\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot < 0) return;\n\t\tset_sl_rr(OPL,slot,v);\n\t\tbreak;\n\tcase 0xa0:\n\t\tif (r == 0xbd)\t\t\t/* am depth, vibrato depth, r,bd,sd,tom,tc,hh */\n\t\t{\n\t\t\tOPL->lfo_am_depth = v & 0x80;\n\t\t\tOPL->lfo_pm_depth_range = (v&0x40) ? 8 : 0;\n\n\t\t\tOPL->rhythm  = v&0x3f;\n\n\t\t\tif(OPL->rhythm&0x20)\n\t\t\t{\n\t\t\t\t/* BD key on/off */\n\t\t\t\tif(v&0x10)\n\t\t\t\t{\n\t\t\t\t\tFM_KEYON (&OPL->P_CH[6].SLOT[SLOT1], 2);\n\t\t\t\t\tFM_KEYON (&OPL->P_CH[6].SLOT[SLOT2], 2);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tFM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);\n\t\t\t\t\tFM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);\n\t\t\t\t}\n\t\t\t\t/* HH key on/off */\n\t\t\t\tif(v&0x01) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT1], 2);\n\t\t\t\telse       FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);\n\t\t\t\t/* SD key on/off */\n\t\t\t\tif(v&0x08) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT2], 2);\n\t\t\t\telse       FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);\n\t\t\t\t/* TOM key on/off */\n\t\t\t\tif(v&0x04) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT1], 2);\n\t\t\t\telse       FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);\n\t\t\t\t/* TOP-CY key on/off */\n\t\t\t\tif(v&0x02) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT2], 2);\n\t\t\t\telse       FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* BD key off */\n\t\t\t\tFM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);\n\t\t\t\tFM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);\n\t\t\t\t/* HH key off */\n\t\t\t\tFM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);\n\t\t\t\t/* SD key off */\n\t\t\t\tFM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);\n\t\t\t\t/* TOM key off */\n\t\t\t\tFM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);\n\t\t\t\t/* TOP-CY off */\n\t\t\t\tFM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t/* keyon,block,fnum */\n\t\tif( (r&0x0f) > 8) return;\n\t\tCH = &OPL->P_CH[r&0x0f];\n\t\tif(!(r&0x10))\n\t\t{\t/* a0-a8 */\n\t\t\tblock_fnum  = (CH->block_fnum&0x1f00) | v;\n\t\t}\n\t\telse\n\t\t{\t/* b0-b8 */\n\t\t\tblock_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);\n\n\t\t\tif(v&0x20)\n\t\t\t{\n\t\t\t\tFM_KEYON (&CH->SLOT[SLOT1], 1);\n\t\t\t\tFM_KEYON (&CH->SLOT[SLOT2], 1);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tFM_KEYOFF(&CH->SLOT[SLOT1],~1);\n\t\t\t\tFM_KEYOFF(&CH->SLOT[SLOT2],~1);\n\t\t\t}\n\t\t}\n\t\t/* update */\n\t\tif(CH->block_fnum != block_fnum)\n\t\t{\n\t\t\tUINT8 block  = block_fnum >> 10;\n\n\t\t\tCH->block_fnum = block_fnum;\n\n\t\t\tCH->ksl_base = ksl_tab[block_fnum>>6];\n\t\t\tCH->fc       = OPL->fn_tab[block_fnum&0x03ff] >> (7-block);\n\n\t\t\t/* BLK 2,1,0 bits -> bits 3,2,1 of kcode */\n\t\t\tCH->kcode    = (CH->block_fnum&0x1c00)>>9;\n\n\t\t\t /* the info below is actually opposite to what is stated in the Manuals (verifed on real YM3812) */\n\t\t\t/* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum  */\n\t\t\t/* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */\n\t\t\tif (OPL->mode&0x40)\n\t\t\t\tCH->kcode |= (CH->block_fnum&0x100)>>8;\t/* notesel == 1 */\n\t\t\telse\n\t\t\t\tCH->kcode |= (CH->block_fnum&0x200)>>9;\t/* notesel == 0 */\n\n\t\t\t/* refresh Total Level in both SLOTs of this channel */\n\t\t\tCH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);\n\t\t\tCH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);\n\n\t\t\t/* refresh frequency counter in both SLOTs of this channel */\n\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT1]);\n\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT2]);\n\t\t}\n\t\tbreak;\n\tcase 0xc0:\n\t\t/* FB,C */\n\t\tif( (r&0x0f) > 8) return;\n\t\tCH = &OPL->P_CH[r&0x0f];\n\t\tCH->SLOT[SLOT1].FB  = (v>>1)&7 ? ((v>>1)&7) + 7 : 0;\n\t\tCH->SLOT[SLOT1].CON = v&1;\n\t\tCH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &OPL->output[0] : &OPL->phase_modulation;\n\t\tbreak;\n\tcase 0xe0: /* waveform select */\n\t\t/* simply ignore write to the waveform select register if selecting not enabled in test register */\n\t\tif(OPL->wavesel)\n\t\t{\n\t\t\tslot = slot_array[r&0x1f];\n\t\t\tif(slot < 0) return;\n\t\t\tCH = &OPL->P_CH[slot/2];\n\n\t\t\tCH->SLOT[slot&1].wavetable = (v&0x03)*SIN_LEN;\n\t\t}\n\t\tbreak;\n\t}\n}\n\n/*static TIMER_CALLBACK( cymfile_callback )\n{\n\tif (cymfile)\n\t{\n\t\tfputc( (unsigned char)0, cymfile );\n\t}\n}*/\n\n/* lock/unlock for common table */\nstatic int OPL_LockTable(void)\n{\n\tnum_lock++;\n\tif(num_lock>1) return 0;\n\n\t/* first time */\n\n\t/* allocate total level table (128kb space) */\n\tif( !init_tables() )\n\t{\n\t\tnum_lock--;\n\t\treturn -1;\n\t}\n\n\t/*if (LOG_CYM_FILE)\n\t{\n\t\tcymfile = fopen(\"3812_.cym\",\"wb\");\n\t\tif (cymfile)\n\t\t\ttimer_pulse ( device->machine, ATTOTIME_IN_HZ(110), NULL, 0, cymfile_callback); //110 Hz pulse timer\n\t\telse\n\t\t\tlogerror(\"Could not create file 3812_.cym\\n\");\n\t}*/\n\n\treturn 0;\n}\n\nstatic void OPL_UnLockTable(void)\n{\n\tif(num_lock) num_lock--;\n\tif(num_lock) return;\n\n\t/* last time */\n\n\tOPLCloseTable();\n\n\t/*if (cymfile)\n\t\tfclose (cymfile);\n\tcymfile = NULL;*/\n}\n\nstatic void OPLResetChip(FM_OPL *OPL)\n{\n\tint c,s;\n\tint i;\n\n\tOPL->eg_timer = 0;\n\tOPL->eg_cnt   = 0;\n\n\tOPL->noise_rng = 1;\t/* noise shift register */\n\tOPL->mode   = 0;\t/* normal mode */\n\tOPL_STATUS_RESET(OPL,0x7f);\n\n\t/* reset with register write */\n\tOPLWriteReg(OPL,0x01,0); /* wavesel disable */\n\tOPLWriteReg(OPL,0x02,0); /* Timer1 */\n\tOPLWriteReg(OPL,0x03,0); /* Timer2 */\n\tOPLWriteReg(OPL,0x04,0); /* IRQ mask clear */\n\tfor(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);\n\n\t/* reset operator parameters */\n\tfor( c = 0 ; c < 9 ; c++ )\n\t{\n\t\tOPL_CH *CH = &OPL->P_CH[c];\n\t\tfor(s = 0 ; s < 2 ; s++ )\n\t\t{\n\t\t\t/* wave table */\n\t\t\tCH->SLOT[s].wavetable = 0;\n\t\t\tCH->SLOT[s].state     = EG_OFF;\n\t\t\tCH->SLOT[s].volume    = MAX_ATT_INDEX;\n\t\t}\n\t}\n#if BUILD_Y8950\n\tif(OPL->type&OPL_TYPE_ADPCM)\n\t{\n\t\tYM_DELTAT *DELTAT = OPL->deltat;\n\n\t\tDELTAT->freqbase = OPL->freqbase;\n\t\tDELTAT->output_pointer = &OPL->output_deltat[0];\n\t\tDELTAT->portshift = 5;\n\t\tDELTAT->output_range = 1<<23;\n\t\tYM_DELTAT_ADPCM_Reset(DELTAT,0,YM_DELTAT_EMULATION_MODE_NORMAL);\n\t}\n#endif\n}\n\n\n#if 0\n//static STATE_POSTLOAD( OPL_postload )\nstatic void OPL_postload(void* param)\n{\n\tFM_OPL *OPL = (FM_OPL *)param;\n\tint slot, ch;\n\n\tfor( ch=0 ; ch < 9 ; ch++ )\n\t{\n\t\tOPL_CH *CH = &OPL->P_CH[ch];\n\n\t\t/* Look up key scale level */\n\t\tUINT32 block_fnum = CH->block_fnum;\n\t\tCH->ksl_base = ksl_tab[block_fnum >> 6];\n\t\tCH->fc       = OPL->fn_tab[block_fnum & 0x03ff] >> (7 - (block_fnum >> 10));\n\n\t\tfor( slot=0 ; slot < 2 ; slot++ )\n\t\t{\n\t\t\tOPL_SLOT *SLOT = &CH->SLOT[slot];\n\n\t\t\t/* Calculate key scale rate */\n\t\t\tSLOT->ksr = CH->kcode >> SLOT->KSR;\n\n\t\t\t/* Calculate attack, decay and release rates */\n\t\t\tif ((SLOT->ar + SLOT->ksr) < 16+62)\n\t\t\t{\n\t\t\t\tSLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];\n\t\t\t\tSLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tSLOT->eg_sh_ar  = 0;\n\t\t\t\tSLOT->eg_sel_ar = 13*RATE_STEPS;\n\t\t\t}\n\t\t\tSLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];\n\t\t\tSLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];\n\t\t\tSLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];\n\t\t\tSLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];\n\n\t\t\t/* Calculate phase increment */\n\t\t\tSLOT->Incr = CH->fc * SLOT->mul;\n\n\t\t\t/* Total level */\n\t\t\tSLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);\n\n\t\t\t/* Connect output */\n\t\t\tSLOT->connect1 = SLOT->CON ? &OPL->output[0] : &OPL->phase_modulation;\n\t\t}\n\t}\n#if BUILD_Y8950\n\tif ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) )\n\t{\n\t\t// We really should call the postlod function for the YM_DELTAT, but it's hard without registers\n\t\t// (see the way the YM2610 does it)\n\t\t//YM_DELTAT_postload(OPL->deltat, REGS);\n\t}\n#endif\n}\n\n\nstatic void OPLsave_state_channel(OPL_CH *CH)\n{\n\tint slot, ch;\n\n\tfor( ch=0 ; ch < 9 ; ch++, CH++ )\n\t{\n\t\t// channel \n\t\tstate_save_register_device_item(device, ch, CH->block_fnum);\n\t\tstate_save_register_device_item(device, ch, CH->kcode);\n\t\t// slots \n\t\tfor( slot=0 ; slot < 2 ; slot++ )\n\t\t{\n\t\t\tOPL_SLOT *SLOT = &CH->SLOT[slot];\n\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->ar);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->dr);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->rr);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->KSR);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->ksl);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->mul);\n\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->Cnt);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->FB);\n\t\t\tstate_save_register_device_item_array(device, ch * 2 + slot, SLOT->op1_out);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->CON);\n\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->eg_type);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->state);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->TL);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->volume);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->sl);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->key);\n\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->AMmask);\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->vib);\n\n\t\t\tstate_save_register_device_item(device, ch * 2 + slot, SLOT->wavetable);\n\t\t}\n\t}\n}\n#endif\n\n\n/* Register savestate for a virtual YM3812/YM3526/Y8950 */\n\n/*static void OPL_save_state(FM_OPL *OPL)\n{\n\tOPLsave_state_channel(device, OPL->P_CH);\n\n\tstate_save_register_device_item(device, 0, OPL->eg_cnt);\n\tstate_save_register_device_item(device, 0, OPL->eg_timer);\n\n\tstate_save_register_device_item(device, 0, OPL->rhythm);\n\n\tstate_save_register_device_item(device, 0, OPL->lfo_am_depth);\n\tstate_save_register_device_item(device, 0, OPL->lfo_pm_depth_range);\n\tstate_save_register_device_item(device, 0, OPL->lfo_am_cnt);\n\tstate_save_register_device_item(device, 0, OPL->lfo_pm_cnt);\n\n\tstate_save_register_device_item(device, 0, OPL->noise_rng);\n\tstate_save_register_device_item(device, 0, OPL->noise_p);\n\n\tif( OPL->type & OPL_TYPE_WAVESEL )\n\t{\n\t\tstate_save_register_device_item(device, 0, OPL->wavesel);\n\t}\n\n\tstate_save_register_device_item_array(device, 0, OPL->T);\n\tstate_save_register_device_item_array(device, 0, OPL->st);\n\n#if BUILD_Y8950\n\tif ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) )\n\t{\n\t\tYM_DELTAT_savestate(device, OPL->deltat);\n\t}\n\n\tif ( OPL->type & OPL_TYPE_IO )\n\t{\n\t\tstate_save_register_device_item(device, 0, OPL->portDirection);\n\t\tstate_save_register_device_item(device, 0, OPL->portLatch);\n\t}\n#endif\n\n\tstate_save_register_device_item(device, 0, OPL->address);\n\tstate_save_register_device_item(device, 0, OPL->status);\n\tstate_save_register_device_item(device, 0, OPL->statusmask);\n\tstate_save_register_device_item(device, 0, OPL->mode);\n\n\tstate_save_register_postload(device->machine, OPL_postload, OPL);\n}*/\n\n\n/* Create one of virtual YM3812/YM3526/Y8950 */\n/* 'clock' is chip clock in Hz  */\n/* 'rate'  is sampling rate  */\nstatic FM_OPL *OPLCreate(UINT32 clock, UINT32 rate, int type)\n{\n\tchar *ptr;\n\tFM_OPL *OPL;\n\tint state_size;\n\n\tif (OPL_LockTable() == -1) return NULL;\n\n\t/* calculate OPL state size */\n\tstate_size  = sizeof(FM_OPL);\n\n#if BUILD_Y8950\n\tif (type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);\n#endif\n\n\t/* allocate memory block */\n\tptr = (char *)malloc(state_size);\n\n\tif (ptr==NULL)\n\t\treturn NULL;\n\n\t/* clear */\n\tmemset(ptr,0,state_size);\n\n\tOPL  = (FM_OPL *)ptr;\n\n\tptr += sizeof(FM_OPL);\n\n#if BUILD_Y8950\n\tif (type&OPL_TYPE_ADPCM)\n\t{\n\t\tOPL->deltat = (YM_DELTAT *)ptr;\n\t}\n\tptr += sizeof(YM_DELTAT);\n#endif\n\n\tOPL->type  = type;\n\tOPL->clock = clock;\n\tOPL->rate  = rate;\n\n\t/* init global tables */\n\tOPL_initalize(OPL);\n\n\treturn OPL;\n}\n\n/* Destroy one of virtual YM3812 */\nstatic void OPLDestroy(FM_OPL *OPL)\n{\n\tOPL_UnLockTable();\n\tfree(OPL);\n}\n\n/* Optional handlers */\n\nstatic void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER timer_handler,void *param)\n{\n\tOPL->timer_handler   = timer_handler;\n\tOPL->TimerParam = param;\n}\nstatic void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,void *param)\n{\n\tOPL->IRQHandler     = IRQHandler;\n\tOPL->IRQParam = param;\n}\nstatic void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,void *param)\n{\n\tOPL->UpdateHandler = UpdateHandler;\n\tOPL->UpdateParam = param;\n}\n\nstatic int OPLWrite(FM_OPL *OPL,int a,int v)\n{\n\tif( !(a&1) )\n\t{\t/* address port */\n\t\tOPL->address = v & 0xff;\n\t}\n\telse\n\t{\t/* data port */\n\t\tif(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam/*,0*/);\n\t\tOPLWriteReg(OPL,OPL->address,v);\n\t}\n\treturn OPL->status>>7;\n}\n\nstatic unsigned char OPLRead(FM_OPL *OPL,int a)\n{\n\tif( !(a&1) )\n\t{\n\t\t/* status port */\n\n\t\t#if BUILD_Y8950\n\n\t\tif(OPL->type&OPL_TYPE_ADPCM)\t/* Y8950 */\n\t\t{\n\t\t\treturn (OPL->status & (OPL->statusmask|0x80)) | (OPL->deltat->PCM_BSY&1);\n\t\t}\n\n\t\t#endif\n\n\t\t/* OPL and OPL2 */\n\t\treturn OPL->status & (OPL->statusmask|0x80);\n\t}\n\n#if BUILD_Y8950\n\t/* data port */\n\tswitch(OPL->address)\n\t{\n\tcase 0x05: /* KeyBoard IN */\n\t\tif(OPL->type&OPL_TYPE_KEYBOARD)\n\t\t{\n\t\t\tif(OPL->keyboardhandler_r)\n\t\t\t\treturn OPL->keyboardhandler_r(OPL->keyboard_param);\n#ifdef _DEBUG\n\t\t\telse\n\t\t\t\tlogerror(\"Y8950: read unmapped KEYBOARD port\\n\");\n#endif\n\t\t}\n\t\treturn 0;\n\n\tcase 0x0f: /* ADPCM-DATA  */\n\t\tif(OPL->type&OPL_TYPE_ADPCM)\n\t\t{\n\t\t\tUINT8 val;\n\n\t\t\tval = YM_DELTAT_ADPCM_Read(OPL->deltat);\n\t\t\t/*logerror(\"Y8950: read ADPCM value read=%02x\\n\",val);*/\n\t\t\treturn val;\n\t\t}\n\t\treturn 0;\n\n\tcase 0x19: /* I/O DATA    */\n\t\tif(OPL->type&OPL_TYPE_IO)\n\t\t{\n\t\t\tif(OPL->porthandler_r)\n\t\t\t\treturn OPL->porthandler_r(OPL->port_param);\n#ifdef _DEBUG\n\t\t\telse\n\t\t\t\tlogerror(\"Y8950:read unmapped I/O port\\n\");\n#endif\n\t\t}\n\t\treturn 0;\n\tcase 0x1a: /* PCM-DATA    */\n\t\tif(OPL->type&OPL_TYPE_ADPCM)\n\t\t{\n#ifdef _DEBUG\n\t\t\tlogerror(\"Y8950 A/D conversion is accessed but not implemented !\\n\");\n#endif\n\t\t\treturn 0x80; /* 2's complement PCM data - result from A/D conversion */\n\t\t}\n\t\treturn 0;\n\t}\n#endif\n\n\treturn 0xff;\n}\n\n/* CSM Key Controll */\nINLINE void CSMKeyControll(OPL_CH *CH)\n{\n\tFM_KEYON (&CH->SLOT[SLOT1], 4);\n\tFM_KEYON (&CH->SLOT[SLOT2], 4);\n\n\t/* The key off should happen exactly one sample later - not implemented correctly yet */\n\n\tFM_KEYOFF(&CH->SLOT[SLOT1], ~4);\n\tFM_KEYOFF(&CH->SLOT[SLOT2], ~4);\n}\n\n\nstatic int OPLTimerOver(FM_OPL *OPL,int c)\n{\n\tif( c )\n\t{\t/* Timer B */\n\t\tOPL_STATUS_SET(OPL,0x20);\n\t}\n\telse\n\t{\t/* Timer A */\n\t\tOPL_STATUS_SET(OPL,0x40);\n\t\t/* CSM mode key,TL controll */\n\t\tif( OPL->mode & 0x80 )\n\t\t{\t/* CSM mode total level latch and auto key on */\n\t\t\tint ch;\n\t\t\tif(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam/*,0*/);\n\t\t\tfor(ch=0; ch<9; ch++)\n\t\t\t\tCSMKeyControll( &OPL->P_CH[ch] );\n\t\t}\n\t}\n\t/* reload timer */\n\t//if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,c,attotime_mul(OPL->TimerBase, OPL->T[c]));\n\treturn OPL->status>>7;\n}\n\n\n#define MAX_OPL_CHIPS 2\n\n\n#if (BUILD_YM3812)\n\nvoid * ym3812_init(UINT32 clock, UINT32 rate)\n{\n\t/* emulator create */\n\tFM_OPL *YM3812 = OPLCreate(clock,rate,OPL_TYPE_YM3812);\n\tif (YM3812)\n\t{\n\t\t//OPL_save_state(YM3812);\n\t\tym3812_reset_chip(YM3812);\n\t}\n\treturn YM3812;\n}\n\nvoid ym3812_shutdown(void *chip)\n{\n\tFM_OPL *YM3812 = (FM_OPL *)chip;\n\t/* emulator shutdown */\n\tOPLDestroy(YM3812);\n}\nvoid ym3812_reset_chip(void *chip)\n{\n\tFM_OPL *YM3812 = (FM_OPL *)chip;\n\tOPLResetChip(YM3812);\n}\n\nint ym3812_write(void *chip, int a, int v)\n{\n\tFM_OPL *YM3812 = (FM_OPL *)chip;\n\treturn OPLWrite(YM3812, a, v);\n}\n\nunsigned char ym3812_read(void *chip, int a)\n{\n\tFM_OPL *YM3812 = (FM_OPL *)chip;\n\t/* YM3812 always returns bit2 and bit1 in HIGH state */\n\treturn OPLRead(YM3812, a) | 0x06 ;\n}\nint ym3812_timer_over(void *chip, int c)\n{\n\tFM_OPL *YM3812 = (FM_OPL *)chip;\n\treturn OPLTimerOver(YM3812, c);\n}\n\nvoid ym3812_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)\n{\n\tFM_OPL *YM3812 = (FM_OPL *)chip;\n\tOPLSetTimerHandler(YM3812, timer_handler, param);\n}\nvoid ym3812_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)\n{\n\tFM_OPL *YM3812 = (FM_OPL *)chip;\n\tOPLSetIRQHandler(YM3812, IRQHandler, param);\n}\nvoid ym3812_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)\n{\n\tFM_OPL *YM3812 = (FM_OPL *)chip;\n\tOPLSetUpdateHandler(YM3812, UpdateHandler, param);\n}\n\n\n/*\n** Generate samples for one of the YM3812's\n**\n** 'which' is the virtual YM3812 number\n** '*buffer' is the output buffer pointer\n** 'length' is the number of samples that should be generated\n*/\nvoid ym3812_update_one(void *chip, OPLSAMPLE **buffer, int length)\n{\n\tFM_OPL\t\t*OPL = (FM_OPL *)chip;\n\tUINT8\t\trhythm = OPL->rhythm&0x20;\n\tOPLSAMPLE\t*bufL = buffer[0];\n\tOPLSAMPLE\t*bufR = buffer[1];\n\tint i;\n\n\tif (! length)\n\t{\n\t\trefresh_eg(OPL);\n\t\treturn;\n\t}\n\t\n\tfor( i=0; i < length ; i++ )\n\t{\n\t\tint lt;\n\n\t\tOPL->output[0] = 0;\n\n\t\tadvance_lfo(OPL);\n\n\t\t/* FM part */\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[0]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[1]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[2]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[3]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[4]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[5]);\n\n\t\tif(!rhythm)\n\t\t{\n\t\t\tOPL_CALC_CH(OPL, &OPL->P_CH[6]);\n\t\t\tOPL_CALC_CH(OPL, &OPL->P_CH[7]);\n\t\t\tOPL_CALC_CH(OPL, &OPL->P_CH[8]);\n\t\t}\n\t\telse\t\t/* Rhythm part */\n\t\t{\n\t\t\tOPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );\n\t\t}\n\n\t\tlt = OPL->output[0];\n\n\t\tlt >>= FINAL_SH;\n\n\t\t/* limit check */\n\t\t//lt = limit( lt , MAXOUT, MINOUT );\n\n\t\t#ifdef SAVE_SAMPLE\n\t\tif (which==0)\n\t\t{\n\t\t\tSAVE_ALL_CHANNELS\n\t\t}\n\t\t#endif\n\n\t\t/* store to sound buffer */\n\t\tbufL[i] = lt;\n\t\tbufR[i] = lt;\n\n\t\tadvance(OPL);\n\t}\n\n}\n#endif /* BUILD_YM3812 */\n\n\n\n#if (BUILD_YM3526)\n\nvoid *ym3526_init(UINT32 clock, UINT32 rate)\n{\n\t/* emulator create */\n\tFM_OPL *YM3526 = OPLCreate(clock,rate,OPL_TYPE_YM3526);\n\tif (YM3526)\n\t{\n\t\t//OPL_save_state(YM3526);\n\t\tym3526_reset_chip(YM3526);\n\t}\n\treturn YM3526;\n}\n\nvoid ym3526_shutdown(void *chip)\n{\n\tFM_OPL *YM3526 = (FM_OPL *)chip;\n\t/* emulator shutdown */\n\tOPLDestroy(YM3526);\n}\nvoid ym3526_reset_chip(void *chip)\n{\n\tFM_OPL *YM3526 = (FM_OPL *)chip;\n\tOPLResetChip(YM3526);\n}\n\nint ym3526_write(void *chip, int a, int v)\n{\n\tFM_OPL *YM3526 = (FM_OPL *)chip;\n\treturn OPLWrite(YM3526, a, v);\n}\n\nunsigned char ym3526_read(void *chip, int a)\n{\n\tFM_OPL *YM3526 = (FM_OPL *)chip;\n\t/* YM3526 always returns bit2 and bit1 in HIGH state */\n\treturn OPLRead(YM3526, a) | 0x06 ;\n}\nint ym3526_timer_over(void *chip, int c)\n{\n\tFM_OPL *YM3526 = (FM_OPL *)chip;\n\treturn OPLTimerOver(YM3526, c);\n}\n\nvoid ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)\n{\n\tFM_OPL *YM3526 = (FM_OPL *)chip;\n\tOPLSetTimerHandler(YM3526, timer_handler, param);\n}\nvoid ym3526_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)\n{\n\tFM_OPL *YM3526 = (FM_OPL *)chip;\n\tOPLSetIRQHandler(YM3526, IRQHandler, param);\n}\nvoid ym3526_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)\n{\n\tFM_OPL *YM3526 = (FM_OPL *)chip;\n\tOPLSetUpdateHandler(YM3526, UpdateHandler, param);\n}\n\n\n/*\n** Generate samples for one of the YM3526's\n**\n** 'which' is the virtual YM3526 number\n** '*buffer' is the output buffer pointer\n** 'length' is the number of samples that should be generated\n*/\nvoid ym3526_update_one(void *chip, OPLSAMPLE **buffer, int length)\n{\n\tFM_OPL\t\t*OPL = (FM_OPL *)chip;\n\tUINT8\t\trhythm = OPL->rhythm&0x20;\n\tOPLSAMPLE\t*bufL = buffer[0];\n\tOPLSAMPLE\t*bufR = buffer[1];\n\tint i;\n\n\tfor( i=0; i < length ; i++ )\n\t{\n\t\tint lt;\n\n\t\tOPL->output[0] = 0;\n\n\t\tadvance_lfo(OPL);\n\n\t\t/* FM part */\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[0]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[1]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[2]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[3]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[4]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[5]);\n\n\t\tif(!rhythm)\n\t\t{\n\t\t\tOPL_CALC_CH(OPL, &OPL->P_CH[6]);\n\t\t\tOPL_CALC_CH(OPL, &OPL->P_CH[7]);\n\t\t\tOPL_CALC_CH(OPL, &OPL->P_CH[8]);\n\t\t}\n\t\telse\t\t/* Rhythm part */\n\t\t{\n\t\t\tOPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );\n\t\t}\n\n\t\tlt = OPL->output[0];\n\n\t\tlt >>= FINAL_SH;\n\n\t\t/* limit check */\n\t\t//lt = limit( lt , MAXOUT, MINOUT );\n\n\t\t#ifdef SAVE_SAMPLE\n\t\tif (which==0)\n\t\t{\n\t\t\tSAVE_ALL_CHANNELS\n\t\t}\n\t\t#endif\n\n\t\t/* store to sound buffer */\n\t\tbufL[i] = lt;\n\t\tbufR[i] = lt;\n\n\t\tadvance(OPL);\n\t}\n\n}\n#endif /* BUILD_YM3526 */\n\n\n\n\n#if BUILD_Y8950\n\nstatic void Y8950_deltat_status_set(void *chip, UINT8 changebits)\n{\n\tFM_OPL *Y8950 = (FM_OPL *)chip;\n\tOPL_STATUS_SET(Y8950, changebits);\n}\nstatic void Y8950_deltat_status_reset(void *chip, UINT8 changebits)\n{\n\tFM_OPL *Y8950 = (FM_OPL *)chip;\n\tOPL_STATUS_RESET(Y8950, changebits);\n}\n\nvoid *y8950_init(UINT32 clock, UINT32 rate)\n{\n\t/* emulator create */\n\tFM_OPL *Y8950 = OPLCreate(clock,rate,OPL_TYPE_Y8950);\n\tif (Y8950)\n\t{\n\t\tY8950->deltat->memory = NULL;\n\t\tY8950->deltat->memory_size = 0x00;\n\t\tY8950->deltat->memory_mask = 0x00;\n\n\t\tY8950->deltat->status_set_handler = Y8950_deltat_status_set;\n\t\tY8950->deltat->status_reset_handler = Y8950_deltat_status_reset;\n\t\tY8950->deltat->status_change_which_chip = Y8950;\n\t\tY8950->deltat->status_change_EOS_bit = 0x10;\t\t/* status flag: set bit4 on End Of Sample */\n\t\tY8950->deltat->status_change_BRDY_bit = 0x08;\t/* status flag: set bit3 on BRDY (End Of: ADPCM analysis/synthesis, memory reading/writing) */\n\n\t\t/*Y8950->deltat->write_time = 10.0 / clock;*/\t\t/* a single byte write takes 10 cycles of main clock */\n\t\t/*Y8950->deltat->read_time  = 8.0 / clock;*/\t\t/* a single byte read takes 8 cycles of main clock */\n\t\t/* reset */\n\t\t//OPL_save_state(Y8950);\n\t\ty8950_reset_chip(Y8950);\n\t}\n\n\treturn Y8950;\n}\n\nvoid y8950_shutdown(void *chip)\n{\n\tFM_OPL *Y8950 = (FM_OPL *)chip;\n\t\n\tfree(Y8950->deltat->memory);\tY8950->deltat->memory = NULL;\n\t\n\t/* emulator shutdown */\n\tOPLDestroy(Y8950);\n}\nvoid y8950_reset_chip(void *chip)\n{\n\tFM_OPL *Y8950 = (FM_OPL *)chip;\n\tOPLResetChip(Y8950);\n}\n\nint y8950_write(void *chip, int a, int v)\n{\n\tFM_OPL *Y8950 = (FM_OPL *)chip;\n\treturn OPLWrite(Y8950, a, v);\n}\n\nunsigned char y8950_read(void *chip, int a)\n{\n\tFM_OPL *Y8950 = (FM_OPL *)chip;\n\treturn OPLRead(Y8950, a);\n}\nint y8950_timer_over(void *chip, int c)\n{\n\tFM_OPL *Y8950 = (FM_OPL *)chip;\n\treturn OPLTimerOver(Y8950, c);\n}\n\nvoid y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)\n{\n\tFM_OPL *Y8950 = (FM_OPL *)chip;\n\tOPLSetTimerHandler(Y8950, timer_handler, param);\n}\nvoid y8950_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)\n{\n\tFM_OPL *Y8950 = (FM_OPL *)chip;\n\tOPLSetIRQHandler(Y8950, IRQHandler, param);\n}\nvoid y8950_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)\n{\n\tFM_OPL *Y8950 = (FM_OPL *)chip;\n\tOPLSetUpdateHandler(Y8950, UpdateHandler, param);\n}\n\nvoid y8950_set_delta_t_memory(void *chip, void * deltat_mem_ptr, int deltat_mem_size )\n{\n\tFM_OPL\t\t*OPL = (FM_OPL *)chip;\n\tOPL->deltat->memory = (UINT8 *)(deltat_mem_ptr);\n\tOPL->deltat->memory_size = deltat_mem_size;\n}\n\nvoid y8950_write_pcmrom(void *chip, offs_t ROMSize, offs_t DataStart,\n\t\t\t\t\t\t offs_t DataLength, const UINT8* ROMData)\n{\n\tFM_OPL *Y8950 = (FM_OPL *)chip;\n\t\n\tif (Y8950->deltat->memory_size != ROMSize)\n\t{\n\t\tY8950->deltat->memory = (UINT8*)realloc(Y8950->deltat->memory, ROMSize);\n\t\tY8950->deltat->memory_size = ROMSize;\n\t\tmemset(Y8950->deltat->memory, 0xFF, ROMSize);\n\t\tYM_DELTAT_calc_mem_mask(Y8950->deltat);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(Y8950->deltat->memory + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\n/*\n** Generate samples for one of the Y8950's\n**\n** 'which' is the virtual Y8950 number\n** '*buffer' is the output buffer pointer\n** 'length' is the number of samples that should be generated\n*/\nvoid y8950_update_one(void *chip, OPLSAMPLE **buffer, int length)\n{\n\tint i;\n\tFM_OPL\t\t*OPL = (FM_OPL *)chip;\n\tUINT8\t\trhythm  = OPL->rhythm&0x20;\n\tYM_DELTAT\t*DELTAT = OPL->deltat;\n\tOPLSAMPLE\t*bufL = buffer[0];\n\tOPLSAMPLE\t*bufR = buffer[1];\n\n\tfor( i=0; i < length ; i++ )\n\t{\n\t\tint lt;\n\n\t\tOPL->output[0] = 0;\n\t\tOPL->output_deltat[0] = 0;\n\n\t\tadvance_lfo(OPL);\n\n\t\t/* deltaT ADPCM */\n\t\tif( DELTAT->portstate&0x80 && ! OPL->MuteSpc[5] )\n\t\t\tYM_DELTAT_ADPCM_CALC(DELTAT);\n\n\t\t/* FM part */\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[0]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[1]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[2]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[3]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[4]);\n\t\tOPL_CALC_CH(OPL, &OPL->P_CH[5]);\n\n\t\tif(!rhythm)\n\t\t{\n\t\t\tOPL_CALC_CH(OPL, &OPL->P_CH[6]);\n\t\t\tOPL_CALC_CH(OPL, &OPL->P_CH[7]);\n\t\t\tOPL_CALC_CH(OPL, &OPL->P_CH[8]);\n\t\t}\n\t\telse\t\t/* Rhythm part */\n\t\t{\n\t\t\tOPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );\n\t\t}\n\n\t\tlt = OPL->output[0] + (OPL->output_deltat[0]>>11);\n\n\t\tlt >>= FINAL_SH;\n\n\t\t/* limit check */\n\t\t//lt = limit( lt , MAXOUT, MINOUT );\n\n\t\t#ifdef SAVE_SAMPLE\n\t\tif (which==0)\n\t\t{\n\t\t\tSAVE_ALL_CHANNELS\n\t\t}\n\t\t#endif\n\n\t\t/* store to sound buffer */\n\t\tbufL[i] = lt;\n\t\tbufR[i] = lt;\n\n\t\tadvance(OPL);\n\t}\n\n}\n\nvoid y8950_set_port_handler(void *chip,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,void * param)\n{\n\tFM_OPL\t\t*OPL = (FM_OPL *)chip;\n\tOPL->porthandler_w = PortHandler_w;\n\tOPL->porthandler_r = PortHandler_r;\n\tOPL->port_param = param;\n}\n\nvoid y8950_set_keyboard_handler(void *chip,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,void * param)\n{\n\tFM_OPL\t\t*OPL = (FM_OPL *)chip;\n\tOPL->keyboardhandler_w = KeyboardHandler_w;\n\tOPL->keyboardhandler_r = KeyboardHandler_r;\n\tOPL->keyboard_param = param;\n}\n\n#endif\n\nvoid opl_set_mute_mask(void *chip, UINT32 MuteMask)\n{\n\tFM_OPL *opl = (FM_OPL *)chip;\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 9; CurChn ++)\n\t\topl->P_CH[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t\topl->MuteSpc[CurChn] = (MuteMask >> (9 + CurChn)) & 0x01;\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/fmopl.h",
    "content": "#pragma once\n\n//#include \"attotime.h\"\n\n/* --- select emulation chips --- */\n//#define BUILD_YM3812 (HAS_YM3812)\n//#define BUILD_YM3526 (HAS_YM3526)\n//#define BUILD_Y8950  (HAS_Y8950)\n#define BUILD_YM3812 1\n#define BUILD_YM3526 1\n#ifndef NO_Y8950\n#define BUILD_Y8950  1\n#else\n#define BUILD_Y8950  0\n#endif\n\n/* select output bits size of output : 8 or 16 */\n#define OPL_SAMPLE_BITS 16\n\n/* compiler dependence */\n/*#ifndef __OSDCOMM_H__\n#define __OSDCOMM_H__\ntypedef unsigned char\tUINT8;   // unsigned  8bit\ntypedef unsigned short\tUINT16;  // unsigned 16bit\ntypedef unsigned int\tUINT32;  // unsigned 32bit\ntypedef signed char\t\tINT8;    // signed  8bit\ntypedef signed short\tINT16;   // signed 16bit\ntypedef signed int\t\tINT32;   // signed 32bit\n#endif*/ /* __OSDCOMM_H__ */\n\ntypedef stream_sample_t OPLSAMPLE;\n/*\n#if (OPL_SAMPLE_BITS==16)\ntypedef INT16 OPLSAMPLE;\n#endif\n#if (OPL_SAMPLE_BITS==8)\ntypedef INT8 OPLSAMPLE;\n#endif\n*/\n\n//typedef void (*OPL_TIMERHANDLER)(void *param,int timer,attotime period);\ntypedef void (*OPL_TIMERHANDLER)(void *param,int timer,int period);\ntypedef void (*OPL_IRQHANDLER)(void *param,int irq);\ntypedef void (*OPL_UPDATEHANDLER)(void *param/*,int min_interval_us*/);\ntypedef void (*OPL_PORTHANDLER_W)(void *param,unsigned char data);\ntypedef unsigned char (*OPL_PORTHANDLER_R)(void *param);\n\n\n#if BUILD_YM3812\n\nvoid *ym3812_init(UINT32 clock, UINT32 rate);\nvoid ym3812_shutdown(void *chip);\nvoid ym3812_reset_chip(void *chip);\nint  ym3812_write(void *chip, int a, int v);\nunsigned char ym3812_read(void *chip, int a);\nint  ym3812_timer_over(void *chip, int c);\nvoid ym3812_update_one(void *chip, OPLSAMPLE **buffer, int length);\n\nvoid ym3812_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);\nvoid ym3812_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);\nvoid ym3812_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);\n\n#endif /* BUILD_YM3812 */\n\n\n#if BUILD_YM3526\n\n/*\n** Initialize YM3526 emulator(s).\n**\n** 'num' is the number of virtual YM3526's to allocate\n** 'clock' is the chip clock in Hz\n** 'rate' is sampling rate\n*/\nvoid *ym3526_init(UINT32 clock, UINT32 rate);\n/* shutdown the YM3526 emulators*/\nvoid ym3526_shutdown(void *chip);\nvoid ym3526_reset_chip(void *chip);\nint  ym3526_write(void *chip, int a, int v);\nunsigned char ym3526_read(void *chip, int a);\nint  ym3526_timer_over(void *chip, int c);\n/*\n** Generate samples for one of the YM3526's\n**\n** 'which' is the virtual YM3526 number\n** '*buffer' is the output buffer pointer\n** 'length' is the number of samples that should be generated\n*/\nvoid ym3526_update_one(void *chip, OPLSAMPLE **buffer, int length);\n\nvoid ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);\nvoid ym3526_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);\nvoid ym3526_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);\n\n#endif /* BUILD_YM3526 */\n\n\n#if BUILD_Y8950\n\n/* Y8950 port handlers */\nvoid y8950_set_port_handler(void *chip, OPL_PORTHANDLER_W PortHandler_w, OPL_PORTHANDLER_R PortHandler_r, void *param);\nvoid y8950_set_keyboard_handler(void *chip, OPL_PORTHANDLER_W KeyboardHandler_w, OPL_PORTHANDLER_R KeyboardHandler_r, void *param);\nvoid y8950_set_delta_t_memory(void *chip, void * deltat_mem_ptr, int deltat_mem_size );\nvoid y8950_write_pcmrom(void *chip, offs_t ROMSize, offs_t DataStart,\n\t\t\t\t\t\t offs_t DataLength, const UINT8* ROMData);\n\nvoid * y8950_init(UINT32 clock, UINT32 rate);\nvoid y8950_shutdown(void *chip);\nvoid y8950_reset_chip(void *chip);\nint  y8950_write(void *chip, int a, int v);\nunsigned char y8950_read (void *chip, int a);\nint  y8950_timer_over(void *chip, int c);\nvoid y8950_update_one(void *chip, OPLSAMPLE **buffer, int length);\n\nvoid y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);\nvoid y8950_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);\nvoid y8950_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);\n\n#endif /* BUILD_Y8950 */\n\nvoid opl_set_mute_mask(void *chip, UINT32 MuteMask);\n\n"
  },
  {
    "path": "VGMPlay/chips/gb.c",
    "content": "// license:BSD-3-Clause\n// copyright-holders:Wilbert Pol, Anthony Kruize\n// thanks-to:Shay Green\n/**************************************************************************************\n* Game Boy sound emulation (c) Anthony Kruize (trandor@labyrinth.net.au)\n*\n* Anyways, sound on the Game Boy consists of 4 separate 'channels'\n*   Sound1 = Quadrangular waves with SWEEP and ENVELOPE functions  (NR10,11,12,13,14)\n*   Sound2 = Quadrangular waves with ENVELOPE functions (NR21,22,23,24)\n*   Sound3 = Wave patterns from WaveRAM (NR30,31,32,33,34)\n*   Sound4 = White noise with an envelope (NR41,42,43,44)\n*\n* Each sound channel has 2 modes, namely ON and OFF...  whoa\n*\n* These tend to be the two most important equations in\n* converting between Hertz and GB frequency registers:\n* (Sounds will have a 2.4% higher frequency on Super GB.)\n*       gb = 2048 - (131072 / Hz)\n*       Hz = 131072 / (2048 - gb)\n*\n* Changes:\n*\n*   10/2/2002       AK - Preliminary sound code.\n*   13/2/2002       AK - Added a hack for mode 4, other fixes.\n*   23/2/2002       AK - Use lookup tables, added sweep to mode 1. Re-wrote the square\n*                        wave generation.\n*   13/3/2002       AK - Added mode 3, better lookup tables, other adjustments.\n*   15/3/2002       AK - Mode 4 can now change frequencies.\n*   31/3/2002       AK - Accidently forgot to handle counter/consecutive for mode 1.\n*    3/4/2002       AK - Mode 1 sweep can still occur if shift is 0.  Don't let frequency\n*                        go past the maximum allowed value. Fixed Mode 3 length table.\n*                        Slight adjustment to Mode 4's period table generation.\n*    5/4/2002       AK - Mode 4 is done correctly, using a polynomial counter instead\n*                        of being a total hack.\n*    6/4/2002       AK - Slight tweak to mode 3's frequency calculation.\n*   13/4/2002       AK - Reset envelope value when sound is initialized.\n*   21/4/2002       AK - Backed out the mode 3 frequency calculation change.\n*                        Merged init functions into gameboy_sound_w().\n*   14/5/2002       AK - Removed magic numbers in the fixed point math.\n*   12/6/2002       AK - Merged SOUNDx structs into one SOUND struct.\n*  26/10/2002       AK - Finally fixed channel 3!\n* xx/4-5/2016       WP - Rewrote sound core. Most of the code is not optimized yet.\n\nTODO:\n- Implement different behavior of CGB-02.\n- Implement different behavior of CGB-05.\n- Perform more tests on real hardware to figure out when the frequency counters are\n  reloaded.\n- Perform more tests on real hardware to understand when changes to the noise divisor\n  and shift kick in.\n- Optimize the channel update methods.\n\n***************************************************************************************/\n\n#include \"mamedef.h\"\n#include <stdlib.h>\t// for rand\n#include <string.h>\t// for memset\n//#include \"emu.h\"\n#include \"gb.h\"\n//#include \"streams.h\"\n\n\ntypedef UINT8\tbool;\n#define false\t0x00\n#define true\t0x01\n\n\n#define RC_SHIFT\t16\n\ntypedef struct\n{\n\tUINT32 inc;\t// counter increment\n\tUINT32 val;\t// current value\n} RATIO_CNTR;\n\nINLINE void RC_SET_RATIO(RATIO_CNTR* rc, UINT32 mul, UINT32 div)\n{\n\trc->inc = (UINT32)((((UINT64)mul << RC_SHIFT) + div / 2) / div);\n}\n\n\n/***************************************************************************\n    CONSTANTS\n***************************************************************************/\n\n#define NR10 0x00\n#define NR11 0x01\n#define NR12 0x02\n#define NR13 0x03\n#define NR14 0x04\n// 0x05\n#define NR21 0x06\n#define NR22 0x07\n#define NR23 0x08\n#define NR24 0x09\n#define NR30 0x0A\n#define NR31 0x0B\n#define NR32 0x0C\n#define NR33 0x0D\n#define NR34 0x0E\n// 0x0F\n#define NR41 0x10\n#define NR42 0x11\n#define NR43 0x12\n#define NR44 0x13\n#define NR50 0x14\n#define NR51 0x15\n#define NR52 0x16\n// 0x17 - 0x1F\n#define AUD3W0 0x20\n#define AUD3W1 0x21\n#define AUD3W2 0x22\n#define AUD3W3 0x23\n#define AUD3W4 0x24\n#define AUD3W5 0x25\n#define AUD3W6 0x26\n#define AUD3W7 0x27\n#define AUD3W8 0x28\n#define AUD3W9 0x29\n#define AUD3WA 0x2A\n#define AUD3WB 0x2B\n#define AUD3WC 0x2C\n#define AUD3WD 0x2D\n#define AUD3WE 0x2E\n#define AUD3WF 0x2F\n\n#define FRAME_CYCLES 8192\n\n/* Represents wave duties of 12.5%, 25%, 50% and 75% */\nstatic const int wave_duty_table[4][8] =\n{\n\t{ -1, -1, -1, -1, -1, -1, -1,  1},\n\t{  1, -1, -1, -1, -1, -1, -1,  1},\n\t{  1, -1, -1, -1, -1,  1,  1,  1},\n\t{ -1,  1,  1,  1,  1,  1,  1, -1}\n};\n\n\n/***************************************************************************\n    TYPE DEFINITIONS\n***************************************************************************/\n\nstruct SOUND\n{\n\t/* Common */\n\tUINT8  reg[5];\n\tbool   on;\n\tUINT8  channel;\n\tUINT8  length;\n\tUINT8  length_mask;\n\tbool   length_counting;\n\tbool   length_enabled;\n\t/* Mode 1, 2, 3 */\n\tUINT32 cycles_left;\n\tINT8   duty;\n\t/* Mode 1, 2, 4 */\n\tbool   envelope_enabled;\n\tINT8   envelope_value;\n\tINT8   envelope_direction;\n\tUINT8  envelope_time;\n\tUINT8  envelope_count;\n\tINT8   signal;\n\t/* Mode 1 */\n\tUINT16 frequency;\n\tUINT16 frequency_counter;\n\tbool   sweep_enabled;\n\tbool   sweep_neg_mode_used;\n\tUINT8  sweep_shift;\n\tINT32  sweep_direction;\n\tUINT8  sweep_time;\n\tUINT8  sweep_count;\n\t/* Mode 3 */\n\tUINT8  level;\n\tUINT8  offset;\n\tUINT32 duty_count;\n\tINT8   current_sample;\n\tbool   sample_reading;\n\t/* Mode 4 */\n\tbool   noise_short;\n\tUINT16 noise_lfsr;\n\tUINT8  Muted;\n};\n\nstruct SOUNDC\n{\n\tUINT8 on;\n\tUINT8 vol_left;\n\tUINT8 vol_right;\n\tUINT8 mode1_left;\n\tUINT8 mode1_right;\n\tUINT8 mode2_left;\n\tUINT8 mode2_right;\n\tUINT8 mode3_left;\n\tUINT8 mode3_right;\n\tUINT8 mode4_left;\n\tUINT8 mode4_right;\n\tUINT32 cycles;\n\tbool wave_ram_locked;\n};\n\n\n#define GBMODE_DMG      0x00\n#define GBMODE_CGB04    0x01\ntypedef struct _gb_sound_t gb_sound_t;\nstruct _gb_sound_t\n{\n\tUINT32 rate;\n\n\tstruct SOUND  snd_1;\n\tstruct SOUND  snd_2;\n\tstruct SOUND  snd_3;\n\tstruct SOUND  snd_4;\n\tstruct SOUNDC snd_control;\n\n\tUINT8 snd_regs[0x30];\n\n\tRATIO_CNTR cycleCntr;\n\n\tUINT8 gbMode;\n\t//UINT8 BoostWaveChn;\n};\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nextern UINT32 SampleRate;\n#define MAX_CHIPS\t0x02\nstatic gb_sound_t GBSoundData[MAX_CHIPS];\n\nstatic UINT8 BoostWaveChn = 0x00;\n\n\nstatic void gb_corrupt_wave_ram(gb_sound_t *gb);\nstatic void gb_apu_power_off(gb_sound_t *gb);\nstatic void gb_tick_length(struct SOUND *snd);\nstatic INT32 gb_calculate_next_sweep(struct SOUND *snd);\nINLINE bool gb_dac_enabled(struct SOUND *snd);\nINLINE UINT32 gb_noise_period_cycles(gb_sound_t *gb);\n\n/***************************************************************************\n    IMPLEMENTATION\n***************************************************************************/\n\nUINT8 gb_wave_r(UINT8 ChipID, offs_t offset)\n{\n\tgb_sound_t *gb = &GBSoundData[ChipID];\n\n\t//gb_update_state(gb, 0);\n\n\tif (gb->snd_3.on)\n\t{\n\t\tif (gb->gbMode == GBMODE_DMG)\n\t\t\treturn gb->snd_3.sample_reading ? gb->snd_regs[AUD3W0 + (gb->snd_3.offset/2)] : 0xFF;\n\t\telse if (gb->gbMode == GBMODE_CGB04)\n\t\t\treturn gb->snd_regs[AUD3W0 + (gb->snd_3.offset/2)];\n\t}\n\n\treturn gb->snd_regs[AUD3W0 + offset];\n}\n\nvoid gb_wave_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tgb_sound_t *gb = &GBSoundData[ChipID];\n\n\t//gb_update_state(gb, 0);\n\n\tif (gb->snd_3.on)\n\t{\n\t\tif (gb->gbMode == GBMODE_DMG)\n\t\t{\n\t\t\tif (gb->snd_3.sample_reading)\n\t\t\t{\n\t\t\t\tgb->snd_regs[AUD3W0 + (gb->snd_3.offset/2)] = data;\n\t\t\t}\n\t\t}\n\t\telse if (gb->gbMode == GBMODE_CGB04)\n\t\t{\n\t\t\tgb->snd_regs[AUD3W0 + (gb->snd_3.offset/2)] = data;\n\t\t}\n\t}\n\telse\n\t{\n\t\tgb->snd_regs[AUD3W0 + offset] = data;\n\t}\n}\n\nUINT8 gb_sound_r(UINT8 ChipID, offs_t offset)\n{\n\tstatic const UINT8 read_mask[0x40] =\n\t{\n\t\t0x80,0x3F,0x00,0xFF,0xBF,0xFF,0x3F,0x00,0xFF,0xBF,0x7F,0xFF,0x9F,0xFF,0xBF,0xFF,\n\t\t0xFF,0x00,0x00,0xBF,0x00,0x00,0x70,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,\n\t\t0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n\t\t0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n\t};\n\tgb_sound_t *gb = &GBSoundData[ChipID];\n\n\t//gb_update_state(gb, 0);\n\n\tif (offset < AUD3W0)\n\t{\n\t\tif (gb->snd_control.on)\n\t\t{\n\t\t\tif (offset == NR52)\n\t\t\t{\n\t\t\t\treturn (gb->snd_regs[NR52]&0xf0) | (gb->snd_1.on ? 1 : 0) | (gb->snd_2.on ? 2 : 0) | (gb->snd_3.on ? 4 : 0) | (gb->snd_4.on ? 8 : 0) | 0x70;\n\t\t\t}\n\t\t\treturn gb->snd_regs[offset] | read_mask[offset & 0x3F];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn read_mask[offset & 0x3F];\n\t\t}\n\t}\n\telse if (offset <= AUD3WF)\n\t{\n\t\treturn gb_wave_r(ChipID, offset - AUD3W0);\n\t}\n\treturn 0xFF;\n}\n\nvoid gb_sound_w_internal(gb_sound_t *gb, UINT8 offset, UINT8 data)\n{\n\t/* Store the value */\n\tUINT8 old_data = gb->snd_regs[offset];\n\n\tif (gb->snd_control.on)\n\t{\n\t\tgb->snd_regs[offset] = data;\n\t}\n\n\tswitch (offset)\n\t{\n\t/*MODE 1 */\n\tcase NR10: /* Sweep (R/W) */\n\t\tgb->snd_1.reg[0] = data;\n\t\tgb->snd_1.sweep_shift = data & 0x7;\n\t\tgb->snd_1.sweep_direction = (data & 0x8) ? -1 : 1;\n\t\tgb->snd_1.sweep_time = (data & 0x70) >> 4;\n\t\tif ((old_data & 0x08) && !(data & 0x08) && gb->snd_1.sweep_neg_mode_used)\n\t\t{\n\t\t\tgb->snd_1.on = false;\n\t\t}\n\t\tbreak;\n\tcase NR11: /* Sound length/Wave pattern duty (R/W) */\n\t\tgb->snd_1.reg[1] = data;\n\t\tif (gb->snd_control.on)\n\t\t{\n\t\t\tgb->snd_1.duty = (data & 0xc0) >> 6;\n\t\t}\n\t\tgb->snd_1.length = data & 0x3f;\n\t\tgb->snd_1.length_counting = true;\n\t\tbreak;\n\tcase NR12: /* Envelope (R/W) */\n\t\tgb->snd_1.reg[2] = data;\n\t\tgb->snd_1.envelope_value = data >> 4;\n\t\tgb->snd_1.envelope_direction = (data & 0x8) ? 1 : -1;\n\t\tgb->snd_1.envelope_time = data & 0x07;\n\t\tif (!gb_dac_enabled(&gb->snd_1))\n\t\t{\n\t\t\tgb->snd_1.on = false;\n\t\t}\n\t\tbreak;\n\tcase NR13: /* Frequency lo (R/W) */\n\t\tgb->snd_1.reg[3] = data;\n\t\t// Only enabling the frequency line breaks blarggs's sound test #5\n\t\t// This condition may not be correct\n\t\tif (!gb->snd_1.sweep_enabled)\n\t\t{\n\t\t\tgb->snd_1.frequency = ((gb->snd_1.reg[4] & 0x7) << 8) | gb->snd_1.reg[3];\n\t\t}\n\t\tbreak;\n\tcase NR14: /* Frequency hi / Initialize (R/W) */\n\t\tgb->snd_1.reg[4] = data;\n\t\t{\n\t\t\tbool length_was_enabled = gb->snd_1.length_enabled;\n\n\t\t\tgb->snd_1.length_enabled = (data & 0x40) ? true : false;\n\t\t\tgb->snd_1.frequency = ((gb->snd_regs[NR14] & 0x7) << 8) | gb->snd_1.reg[3];\n\n\t\t\tif (!length_was_enabled && !(gb->snd_control.cycles & FRAME_CYCLES) && gb->snd_1.length_counting)\n\t\t\t{\n\t\t\t\tif (gb->snd_1.length_enabled)\n\t\t\t\t{\n\t\t\t\t\tgb_tick_length(&gb->snd_1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (data & 0x80)\n\t\t\t{\n\t\t\t\tgb->snd_1.on = true;\n\t\t\t\tgb->snd_1.envelope_enabled = true;\n\t\t\t\tgb->snd_1.envelope_value = gb->snd_1.reg[2] >> 4;\n\t\t\t\tgb->snd_1.envelope_count = gb->snd_1.envelope_time;\n\t\t\t\tgb->snd_1.sweep_count = gb->snd_1.sweep_time;\n\t\t\t\tgb->snd_1.sweep_neg_mode_used = false;\n\t\t\t\tgb->snd_1.signal = 0;\n\t\t\t\tgb->snd_1.length = gb->snd_1.reg[1] & 0x3f;\t// VGM log fix -Valley Bell\n\t\t\t\tgb->snd_1.length_counting = true;\n\t\t\t\tgb->snd_1.frequency = ((gb->snd_1.reg[4] & 0x7) << 8) | gb->snd_1.reg[3];\n\t\t\t\tgb->snd_1.frequency_counter = gb->snd_1.frequency;\n\t\t\t\tgb->snd_1.cycles_left = 0;\n\t\t\t\tgb->snd_1.duty_count = 0;\n\t\t\t\tgb->snd_1.sweep_enabled = (gb->snd_1.sweep_shift != 0) || (gb->snd_1.sweep_time != 0);\n\t\t\t\tif (!gb_dac_enabled(&gb->snd_1))\n\t\t\t\t{\n\t\t\t\t\tgb->snd_1.on = false;\n\t\t\t\t}\n\t\t\t\tif (gb->snd_1.sweep_shift > 0)\n\t\t\t\t{\n\t\t\t\t\tgb_calculate_next_sweep(&gb->snd_1);\n\t\t\t\t}\n\n\t\t\t\tif (gb->snd_1.length == 0 && gb->snd_1.length_enabled && !(gb->snd_control.cycles & FRAME_CYCLES))\n\t\t\t\t{\n\t\t\t\t\tgb_tick_length(&gb->snd_1);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// This condition may not be correct\n\t\t\t\tif (!gb->snd_1.sweep_enabled)\n\t\t\t\t{\n\t\t\t\t\tgb->snd_1.frequency = ((gb->snd_1.reg[4] & 0x7) << 8) | gb->snd_1.reg[3];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\t/*MODE 2 */\n\tcase NR21: /* Sound length/Wave pattern duty (R/W) */\n\t\tgb->snd_2.reg[1] = data;\n\t\tif (gb->snd_control.on)\n\t\t{\n\t\t\tgb->snd_2.duty = (data & 0xc0) >> 6;\n\t\t}\n\t\tgb->snd_2.length = data & 0x3f;\n\t\tgb->snd_2.length_counting = true;\n\t\tbreak;\n\tcase NR22: /* Envelope (R/W) */\n\t\tgb->snd_2.reg[2] = data;\n\t\tgb->snd_2.envelope_value = data >> 4;\n\t\tgb->snd_2.envelope_direction = (data & 0x8) ? 1 : -1;\n\t\tgb->snd_2.envelope_time = data & 0x07;\n\t\tif (!gb_dac_enabled(&gb->snd_2))\n\t\t{\n\t\t\tgb->snd_2.on = false;\n\t\t}\n\t\tbreak;\n\tcase NR23: /* Frequency lo (R/W) */\n\t\tgb->snd_2.reg[3] = data;\n\t\tgb->snd_2.frequency = ((gb->snd_2.reg[4] & 0x7) << 8) | gb->snd_2.reg[3];\n\t\tbreak;\n\tcase NR24: /* Frequency hi / Initialize (R/W) */\n\t\tgb->snd_2.reg[4] = data;\n\t\t{\n\t\t\tbool length_was_enabled = gb->snd_2.length_enabled;\n\n\t\t\tgb->snd_2.length_enabled = (data & 0x40) ? true : false;\n\n\t\t\tif (!length_was_enabled && !(gb->snd_control.cycles & FRAME_CYCLES) && gb->snd_2.length_counting)\n\t\t\t{\n\t\t\t\tif (gb->snd_2.length_enabled)\n\t\t\t\t{\n\t\t\t\t\tgb_tick_length(&gb->snd_2);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (data & 0x80)\n\t\t\t{\n\t\t\t\tgb->snd_2.on = true;\n\t\t\t\tgb->snd_2.envelope_enabled = true;\n\t\t\t\tgb->snd_2.envelope_value = gb->snd_2.reg[2] >> 4;\n\t\t\t\tgb->snd_2.envelope_count = gb->snd_2.envelope_time;\n\t\t\t\tgb->snd_2.frequency = ((gb->snd_2.reg[4] & 0x7) << 8) | gb->snd_2.reg[3];\n\t\t\t\tgb->snd_2.frequency_counter = gb->snd_2.frequency;\n\t\t\t\tgb->snd_2.cycles_left = 0;\n\t\t\t\tgb->snd_2.duty_count = 0;\n\t\t\t\tgb->snd_2.signal = 0;\n\t\t\t\tgb->snd_2.length = gb->snd_2.reg[1] & 0x3f;\t// VGM log fix -Valley Bell\n\t\t\t\tgb->snd_2.length_counting = true;\n\n\t\t\t\tif (!gb_dac_enabled(&gb->snd_2))\n\t\t\t\t{\n\t\t\t\t\tgb->snd_2.on = false;\n\t\t\t\t}\n\n\t\t\t\tif (gb->snd_2.length == 0 && gb->snd_2.length_enabled && !(gb->snd_control.cycles & FRAME_CYCLES))\n\t\t\t\t{\n\t\t\t\t\tgb_tick_length(&gb->snd_2);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tgb->snd_2.frequency = ((gb->snd_2.reg[4] & 0x7) << 8) | gb->snd_2.reg[3];\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\t/*MODE 3 */\n\tcase NR30: /* Sound On/Off (R/W) */\n\t\tgb->snd_3.reg[0] = data;\n\t\tif (!gb_dac_enabled(&gb->snd_3))\n\t\t{\n\t\t\tgb->snd_3.on = false;\n\t\t}\n\t\tbreak;\n\tcase NR31: /* Sound Length (R/W) */\n\t\tgb->snd_3.reg[1] = data;\n\t\tgb->snd_3.length = data;\n\t\tgb->snd_3.length_counting = true;\n\t\tbreak;\n\tcase NR32: /* Select Output Level */\n\t\tgb->snd_3.reg[2] = data;\n\t\tgb->snd_3.level = (data & 0x60) >> 5;\n\t\tbreak;\n\tcase NR33: /* Frequency lo (W) */\n\t\tgb->snd_3.reg[3] = data;\n\t\tgb->snd_3.frequency = ((gb->snd_3.reg[4] & 0x7) << 8) | gb->snd_3.reg[3];\n\t\tbreak;\n\tcase NR34: /* Frequency hi / Initialize (W) */\n\t\tgb->snd_3.reg[4] = data;\n\t\t{\n\t\t\tbool length_was_enabled = gb->snd_3.length_enabled;\n\n\t\t\tgb->snd_3.length_enabled = (data & 0x40) ? true : false;\n\n\t\t\tif (!length_was_enabled && !(gb->snd_control.cycles & FRAME_CYCLES) && gb->snd_3.length_counting)\n\t\t\t{\n\t\t\t\tif (gb->snd_3.length_enabled)\n\t\t\t\t{\n\t\t\t\t\tgb_tick_length(&gb->snd_3);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (data & 0x80)\n\t\t\t{\n\t\t\t\tif (gb->snd_3.on && gb->snd_3.frequency_counter == 0x7ff)\n\t\t\t\t{\n\t\t\t\t\tgb_corrupt_wave_ram(gb);\n\t\t\t\t}\n\t\t\t\tgb->snd_3.on = true;\n\t\t\t\tgb->snd_3.offset = 0;\n\t\t\t\tgb->snd_3.duty = 1;\n\t\t\t\tgb->snd_3.duty_count = 0;\n\t\t\t\tgb->snd_3.length = gb->snd_3.reg[1];\t// VGM log fix -Valley Bell\n\t\t\t\tgb->snd_3.length_counting = true;\n\t\t\t\tgb->snd_3.frequency = ((gb->snd_3.reg[4] & 0x7) << 8) | gb->snd_3.reg[3];\n\t\t\t\tgb->snd_3.frequency_counter = gb->snd_3.frequency;\n\t\t\t\t// There is a tiny bit of delay in starting up the wave channel(?)\n\t\t\t\t//\n\t\t\t\t// Results from older code where corruption of wave ram was triggered when sample_reading == true:\n\t\t\t\t// 4 breaks test 09 (read wram), fixes test 10 (write trigger), breaks test 12 (write wram)\n\t\t\t\t// 6 fixes test 09 (read wram), breaks test 10 (write trigger), fixes test 12 (write wram)\n\t\t\t\tgb->snd_3.cycles_left = 0 + 6;\n\t\t\t\tgb->snd_3.sample_reading = false;\n\n\t\t\t\tif (!gb_dac_enabled(&gb->snd_3))\n\t\t\t\t{\n\t\t\t\t\tgb->snd_3.on = false;\n\t\t\t\t}\n\n\t\t\t\tif (gb->snd_3.length == 0 && gb->snd_3.length_enabled && !(gb->snd_control.cycles & FRAME_CYCLES))\n\t\t\t\t{\n\t\t\t\t\tgb_tick_length(&gb->snd_3);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tgb->snd_3.frequency = ((gb->snd_3.reg[4] & 0x7) << 8) | gb->snd_3.reg[3];\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\t/*MODE 4 */\n\tcase NR41: /* Sound Length (R/W) */\n\t\tgb->snd_4.reg[1] = data;\n\t\tgb->snd_4.length = data & 0x3f;\n\t\tgb->snd_4.length_counting = true;\n\t\tbreak;\n\tcase NR42: /* Envelope (R/W) */\n\t\tgb->snd_4.reg[2] = data;\n\t\tgb->snd_4.envelope_value = data >> 4;\n\t\tgb->snd_4.envelope_direction = (data & 0x8) ? 1 : -1;\n\t\tgb->snd_4.envelope_time = data & 0x07;\n\t\tif (!gb_dac_enabled(&gb->snd_4))\n\t\t{\n\t\t\tgb->snd_4.on = false;\n\t\t}\n\t\tbreak;\n\tcase NR43: /* Polynomial Counter/Frequency */\n\t\tgb->snd_4.reg[3] = data;\n\t\tgb->snd_4.noise_short = (data & 0x8);\n\t\tbreak;\n\tcase NR44: /* Counter/Consecutive / Initialize (R/W)  */\n\t\tgb->snd_4.reg[4] = data;\n\t\t{\n\t\t\tbool length_was_enabled = gb->snd_4.length_enabled;\n\n\t\t\tgb->snd_4.length_enabled = (data & 0x40) ? true : false;\n\n\t\t\tif (!length_was_enabled && !(gb->snd_control.cycles & FRAME_CYCLES) && gb->snd_4.length_counting)\n\t\t\t{\n\t\t\t\tif (gb->snd_4.length_enabled)\n\t\t\t\t{\n\t\t\t\t\tgb_tick_length(&gb->snd_4);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (data & 0x80)\n\t\t\t{\n\t\t\t\tgb->snd_4.on = true;\n\t\t\t\tgb->snd_4.envelope_enabled = true;\n\t\t\t\tgb->snd_4.envelope_value = gb->snd_4.reg[2] >> 4;\n\t\t\t\tgb->snd_4.envelope_count = gb->snd_4.envelope_time;\n\t\t\t\tgb->snd_4.frequency_counter = 0;\n\t\t\t\tgb->snd_4.cycles_left = gb_noise_period_cycles(gb);\n\t\t\t\tgb->snd_4.signal = -1;\n\t\t\t\tgb->snd_4.noise_lfsr = 0x7fff;\n\t\t\t\tgb->snd_4.length = gb->snd_4.reg[1] & 0x3f;\t// VGM log fix -Valley Bell\n\t\t\t\tgb->snd_4.length_counting = true;\n\n\t\t\t\tif (!gb_dac_enabled(&gb->snd_4))\n\t\t\t\t{\n\t\t\t\t\tgb->snd_4.on = false;\n\t\t\t\t}\n\n\t\t\t\tif (gb->snd_4.length == 0 && gb->snd_4.length_enabled && !(gb->snd_control.cycles & FRAME_CYCLES))\n\t\t\t\t{\n\t\t\t\t\tgb_tick_length(&gb->snd_4);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\t/* CONTROL */\n\tcase NR50: /* Channel Control / On/Off / Volume (R/W)  */\n\t\tgb->snd_control.vol_left = data & 0x7;\n\t\tgb->snd_control.vol_right = (data & 0x70) >> 4;\n\t\tbreak;\n\tcase NR51: /* Selection of Sound Output Terminal */\n\t\tgb->snd_control.mode1_right = data & 0x1;\n\t\tgb->snd_control.mode1_left = (data & 0x10) >> 4;\n\t\tgb->snd_control.mode2_right = (data & 0x2) >> 1;\n\t\tgb->snd_control.mode2_left = (data & 0x20) >> 5;\n\t\tgb->snd_control.mode3_right = (data & 0x4) >> 2;\n\t\tgb->snd_control.mode3_left = (data & 0x40) >> 6;\n\t\tgb->snd_control.mode4_right = (data & 0x8) >> 3;\n\t\tgb->snd_control.mode4_left = (data & 0x80) >> 7;\n\t\tbreak;\n\tcase NR52: // Sound On/Off (R/W)\n\t\t// Only bit 7 is writable, writing to bits 0-3 does NOT enable or disable sound. They are read-only.\n\t\tif (!(data & 0x80))\n\t\t{\n\t\t\t// On DMG the length counters are not affected and not clocked\n\t\t\t// powering off should actually clear all registers\n\t\t\tgb_apu_power_off(gb);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (!gb->snd_control.on)\n\t\t\t{\n\t\t\t\t// When switching on, the next step should be 0.\n\t\t\t\tgb->snd_control.cycles |= 7 * FRAME_CYCLES;\n\t\t\t}\n\t\t}\n\t\tgb->snd_control.on = (data & 0x80) ? true : false;\n\t\tgb->snd_regs[NR52] = data & 0x80;\n\t\tbreak;\n\t}\n}\n\nvoid gb_sound_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tgb_sound_t *gb = &GBSoundData[ChipID];\n\n\t//gb_update_state(gb, 0);\n\n\tif (offset < AUD3W0)\n\t{\n\t\tif (gb->gbMode == GBMODE_DMG)\n\t\t{\n\t\t\t/* Only register NR52 is accessible if the sound controller is disabled */\n\t\t\tif( !gb->snd_control.on && offset != NR52 && offset != NR11 && offset != NR21 && offset != NR31 && offset != NR41)\n\t\t\t\treturn;\n\t\t}\n\t\telse if (gb->gbMode == GBMODE_CGB04)\n\t\t{\n\t\t\t/* Only register NR52 is accessible if the sound controller is disabled */\n\t\t\tif (!gb->snd_control.on && offset != NR52)\n\t\t\t\treturn;\n\t\t}\n\n\t\tgb_sound_w_internal(gb, offset, data);\n\t}\n\telse if (offset <= AUD3WF)\n\t{\n\t\tgb_wave_w(ChipID, offset - AUD3W0, data);\n\t}\n}\n\nstatic void gb_corrupt_wave_ram(gb_sound_t *gb)\n{\n\tif (gb->gbMode != GBMODE_DMG)\n\t\treturn;\n\n\tif (gb->snd_3.offset < 8)\n\t{\n\t\tgb->snd_regs[AUD3W0] = gb->snd_regs[AUD3W0 + (gb->snd_3.offset/2)];\n\t}\n\telse\n\t{\n\t\tint i;\n\t\tfor (i = 0; i < 4; i++)\n\t\t{\n\t\t\tgb->snd_regs[AUD3W0 + i] = gb->snd_regs[AUD3W0 + ((gb->snd_3.offset / 2) & ~0x03) + i];\n\t\t}\n\t}\n}\n\n\nstatic void gb_apu_power_off(gb_sound_t *gb)\n{\n\tint i;\n\n\tswitch(gb->gbMode)\n\t{\n\tcase GBMODE_DMG:\n\t\tgb_sound_w_internal(gb, NR10, 0x00);\n\t\tgb->snd_1.duty = 0;\n\t\tgb->snd_regs[NR11] = 0;\n\t\tgb_sound_w_internal(gb, NR12, 0x00);\n\t\tgb_sound_w_internal(gb, NR13, 0x00);\n\t\tgb_sound_w_internal(gb, NR14, 0x00);\n\t\tgb->snd_1.length_counting = false;\n\t\tgb->snd_1.sweep_neg_mode_used = false;\n\n\t\tgb->snd_regs[NR21] = 0;\n\t\tgb_sound_w_internal(gb, NR22, 0x00);\n\t\tgb_sound_w_internal(gb, NR23, 0x00);\n\t\tgb_sound_w_internal(gb, NR24, 0x00);\n\t\tgb->snd_2.length_counting = false;\n\n\t\tgb_sound_w_internal(gb, NR30, 0x00);\n\t\tgb_sound_w_internal(gb, NR32, 0x00);\n\t\tgb_sound_w_internal(gb, NR33, 0x00);\n\t\tgb_sound_w_internal(gb, NR34, 0x00);\n\t\tgb->snd_3.length_counting = false;\n\t\tgb->snd_3.current_sample = 0;\n\n\t\tgb->snd_regs[NR41] = 0;\n\t\tgb_sound_w_internal(gb, NR42, 0x00);\n\t\tgb_sound_w_internal(gb, NR43, 0x00);\n\t\tgb_sound_w_internal(gb, NR44, 0x00);\n\t\tgb->snd_4.length_counting = false;\n\t\tgb->snd_4.cycles_left = gb_noise_period_cycles(gb);\n\t\tbreak;\n\tcase GBMODE_CGB04:\n\t\tgb_sound_w_internal(gb, NR10, 0x00);\n\t\tgb->snd_1.duty = 0;\n\t\tgb_sound_w_internal(gb, NR11, 0x00);\n\t\tgb_sound_w_internal(gb, NR12, 0x00);\n\t\tgb_sound_w_internal(gb, NR13, 0x00);\n\t\tgb_sound_w_internal(gb, NR14, 0x00);\n\t\tgb->snd_1.length_counting = false;\n\t\tgb->snd_1.sweep_neg_mode_used = false;\n\n\t\tgb_sound_w_internal(gb, NR21, 0x00);\n\t\tgb_sound_w_internal(gb, NR22, 0x00);\n\t\tgb_sound_w_internal(gb, NR23, 0x00);\n\t\tgb_sound_w_internal(gb, NR24, 0x00);\n\t\tgb->snd_2.length_counting = false;\n\n\t\tgb_sound_w_internal(gb, NR30, 0x00);\n\t\tgb_sound_w_internal(gb, NR31, 0x00);\n\t\tgb_sound_w_internal(gb, NR32, 0x00);\n\t\tgb_sound_w_internal(gb, NR33, 0x00);\n\t\tgb_sound_w_internal(gb, NR34, 0x00);\n\t\tgb->snd_3.length_counting = false;\n\t\tgb->snd_3.current_sample = 0;\n\n\t\tgb_sound_w_internal(gb, NR41, 0x00);\n\t\tgb_sound_w_internal(gb, NR42, 0x00);\n\t\tgb_sound_w_internal(gb, NR43, 0x00);\n\t\tgb_sound_w_internal(gb, NR44, 0x00);\n\t\tgb->snd_4.length_counting = false;\n\t\tgb->snd_4.cycles_left = gb_noise_period_cycles(gb);\n\t\tbreak;\n\t}\n\n\tgb->snd_1.on = false;\n\tgb->snd_2.on = false;\n\tgb->snd_3.on = false;\n\tgb->snd_4.on = false;\n\n\tgb->snd_control.wave_ram_locked = false;\n\n\tfor (i = NR44 + 1; i < NR52; i++)\n\t{\n\t\tgb_sound_w_internal(gb, i, 0x00);\n\t}\n\n\treturn;\n}\n\n\nstatic void gb_tick_length(struct SOUND *snd)\n{\n\tif (snd->length_enabled)\n\t{\n\t\tsnd->length = (snd->length + 1) & snd->length_mask;\n\t\tif (snd->length == 0)\n\t\t{\n\t\t\tsnd->on = false;\n\t\t\tsnd->length_counting = false;\n\t\t}\n\t}\n}\n\n\nstatic INT32 gb_calculate_next_sweep(struct SOUND *snd)\n{\n\tINT32 new_frequency;\n\tsnd->sweep_neg_mode_used = (snd->sweep_direction < 0);\n\tnew_frequency = snd->frequency + snd->sweep_direction * (snd->frequency >> snd->sweep_shift);\n\n\tif (new_frequency > 0x7FF)\n\t{\n\t\tsnd->on = false;\n\t}\n\n\treturn new_frequency;\n}\n\n\nstatic void gb_apply_next_sweep(struct SOUND *snd)\n{\n\tINT32 new_frequency = gb_calculate_next_sweep(snd);\n\n\tif (snd->on && snd->sweep_shift > 0)\n\t{\n\t\tsnd->frequency = new_frequency;\n\t\tsnd->reg[3] = snd->frequency & 0xFF;\n\t}\n}\n\n\nstatic void gb_tick_sweep(struct SOUND *snd)\n{\n\tsnd->sweep_count = (snd->sweep_count - 1) & 0x07;\n\tif (snd->sweep_count == 0)\n\t{\n\t\tsnd->sweep_count = snd->sweep_time;\n\n\t\tif (snd->sweep_enabled && snd->sweep_time > 0)\n\t\t{\n\t\t\tgb_apply_next_sweep(snd);\n\t\t\tgb_calculate_next_sweep(snd);\n\t\t}\n\t}\n}\n\n\nstatic void gb_tick_envelope(struct SOUND *snd)\n{\n\tif (snd->envelope_enabled)\n\t{\n\t\tsnd->envelope_count = (snd->envelope_count - 1) & 0x07;\n\n\t\tif (snd->envelope_count == 0)\n\t\t{\n\t\t\tsnd->envelope_count = snd->envelope_time;\n\n\t\t\tif (snd->envelope_count)\n\t\t\t{\n\t\t\t\tINT8 new_envelope_value = snd->envelope_value + snd->envelope_direction;\n\n\t\t\t\tif (new_envelope_value >= 0 && new_envelope_value <= 15)\n\t\t\t\t{\n\t\t\t\t\tsnd->envelope_value = new_envelope_value;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsnd->envelope_enabled = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nINLINE bool gb_dac_enabled(struct SOUND *snd)\n{\n\treturn (snd->channel != 3) ? snd->reg[2] & 0xF8 : snd->reg[0] & 0x80;\n}\n\n\nstatic void gb_update_square_channel(struct SOUND *snd, UINT32 cycles)\n{\n\tif (snd->on)\n\t{\n\t\t// compensate for leftover cycles\n\t\tif (snd->cycles_left > 0)\n\t\t{\n\t\t\tcycles += snd->cycles_left;\n\t\t\tsnd->cycles_left = 0;\n\t\t}\n\n\t\twhile (cycles > 0)\n\t\t{\n\t\t\t// Emit sample(s)\n\t\t\tif (cycles < 4)\n\t\t\t{\n\t\t\t\tsnd->cycles_left = cycles;\n\t\t\t\tcycles = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcycles -= 4;\n\t\t\t\tsnd->frequency_counter = (snd->frequency_counter + 1) & 0x7FF;\n\t\t\t\tif (snd->frequency_counter == 0)\n\t\t\t\t{\n\t\t\t\t\tsnd->duty_count = (snd->duty_count + 1) & 0x07;\n\t\t\t\t\tsnd->signal = wave_duty_table[snd->duty][snd->duty_count];\n\n\t\t\t\t\t// Reload frequency counter\n\t\t\t\t\tsnd->frequency_counter = snd->frequency;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nstatic void gb_update_wave_channel(gb_sound_t *gb, struct SOUND *snd, UINT32 cycles)\n{\n\tif (snd->on)\n\t{\n\t\t// compensate for leftover cycles\n\t\tif (snd->cycles_left > 0)\n\t\t{\n\t\t\tcycles += snd->cycles_left;\n\t\t\tsnd->cycles_left = 0;\n\t\t}\n\n\t\twhile (cycles > 0)\n\t\t{\n\t\t\t// Emit current sample\n\n\t\t\t// cycles -= 2\n\t\t\tif (cycles < 2)\n\t\t\t{\n\t\t\t\tsnd->cycles_left = cycles;\n\t\t\t\tcycles = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcycles -= 2;\n\n\t\t\t\t// Calculate next state\n\t\t\t\tsnd->frequency_counter = (snd->frequency_counter + 1) & 0x7FF;\n\t\t\t\tsnd->sample_reading = false;\n\t\t\t\tif (gb->gbMode == GBMODE_DMG && snd->frequency_counter == 0x7ff)\n\t\t\t\t\tsnd->offset = (snd->offset + 1) & 0x1F;\n\t\t\t\tif (snd->frequency_counter == 0)\n\t\t\t\t{\n\t\t\t\t\t// Read next sample\n\t\t\t\t\tsnd->sample_reading = true;\n\t\t\t\t\tif (gb->gbMode == GBMODE_CGB04)\n\t\t\t\t\t\tsnd->offset = (snd->offset + 1) & 0x1F;\n\t\t\t\t\tsnd->current_sample = gb->snd_regs[AUD3W0 + (snd->offset/2)];\n\t\t\t\t\tif (!(snd->offset & 0x01))\n\t\t\t\t\t{\n\t\t\t\t\t\tsnd->current_sample >>= 4;\n\t\t\t\t\t}\n\t\t\t\t\tsnd->current_sample = (snd->current_sample & 0x0F) - 8;\n\t\t\t\t\tif (BoostWaveChn)\n\t\t\t\t\t\tsnd->current_sample <<= 1;\n\n\t\t\t\t\tsnd->signal = snd->level ? snd->current_sample / (1 << (snd->level - 1)) : 0;\n\n\t\t\t\t\t// Reload frequency counter\n\t\t\t\t\tsnd->frequency_counter = snd->frequency;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nstatic void gb_update_noise_channel(gb_sound_t *gb, struct SOUND *snd, UINT32 cycles)\n{\n\twhile (cycles > 0)\n\t{\n\t\tif (cycles < snd->cycles_left)\n\t\t{\n\t\t\tif (snd->on)\n\t\t\t{\n\t\t\t\t// generate samples\n\t\t\t}\n\n\t\t\tsnd->cycles_left -= cycles;\n\t\t\tcycles = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tUINT16 feedback;\n\n\t\t\tif (snd->on)\n\t\t\t{\n\t\t\t\t// generate samples\n\t\t\t}\n\n\t\t\tcycles -= snd->cycles_left;\n\t\t\tsnd->cycles_left = gb_noise_period_cycles(gb);\n\n\t\t\t/* Using a Polynomial Counter (aka Linear Feedback Shift Register)\n\t\t\t Mode 4 has a 15 bit counter so we need to shift the\n\t\t\t bits around accordingly */\n\t\t\tfeedback = ((snd->noise_lfsr >> 1) ^ snd->noise_lfsr) & 1;\n\t\t\tsnd->noise_lfsr = (snd->noise_lfsr >> 1) | (feedback << 14);\n\t\t\tif (snd->noise_short)\n\t\t\t{\n\t\t\t\tsnd->noise_lfsr = (snd->noise_lfsr & ~(1 << 6)) | (feedback << 6);\n\t\t\t}\n\t\t\tsnd->signal = (snd->noise_lfsr & 1) ? -1 : 1;\n\t\t}\n\t}\n}\n\n\nstatic void gb_update_state(gb_sound_t *gb, UINT32 cycles)\n{\n\tUINT32 old_cycles;\n\n\tif (!gb->snd_control.on)\n\t\treturn;\n\n\told_cycles = gb->snd_control.cycles;\n\tgb->snd_control.cycles += cycles;\n\n\tif ((old_cycles / FRAME_CYCLES) != (gb->snd_control.cycles / FRAME_CYCLES))\n\t{\n\t\t// Left over cycles in current frame\n\t\tUINT32 cycles_current_frame = FRAME_CYCLES - (old_cycles & (FRAME_CYCLES - 1));\n\n\t\tgb_update_square_channel(&gb->snd_1, cycles_current_frame);\n\t\tgb_update_square_channel(&gb->snd_2, cycles_current_frame);\n\t\tgb_update_wave_channel(gb, &gb->snd_3, cycles_current_frame);\n\t\tgb_update_noise_channel(gb, &gb->snd_4, cycles_current_frame);\n\n\t\tcycles -= cycles_current_frame;\n\n\t\t// Switch to next frame\n\t\tswitch ((gb->snd_control.cycles / FRAME_CYCLES) & 0x07)\n\t\t{\n\t\tcase 0:\n\t\t\t// length\n\t\t\tgb_tick_length(&gb->snd_1);\n\t\t\tgb_tick_length(&gb->snd_2);\n\t\t\tgb_tick_length(&gb->snd_3);\n\t\t\tgb_tick_length(&gb->snd_4);\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\t// sweep\n\t\t\tgb_tick_sweep(&gb->snd_1);\n\t\t\t// length\n\t\t\tgb_tick_length(&gb->snd_1);\n\t\t\tgb_tick_length(&gb->snd_2);\n\t\t\tgb_tick_length(&gb->snd_3);\n\t\t\tgb_tick_length(&gb->snd_4);\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\t// length\n\t\t\tgb_tick_length(&gb->snd_1);\n\t\t\tgb_tick_length(&gb->snd_2);\n\t\t\tgb_tick_length(&gb->snd_3);\n\t\t\tgb_tick_length(&gb->snd_4);\n\t\t\tbreak;\n\t\tcase 6:\n\t\t\t// sweep\n\t\t\tgb_tick_sweep(&gb->snd_1);\n\t\t\t// length\n\t\t\tgb_tick_length(&gb->snd_1);\n\t\t\tgb_tick_length(&gb->snd_2);\n\t\t\tgb_tick_length(&gb->snd_3);\n\t\t\tgb_tick_length(&gb->snd_4);\n\t\t\tbreak;\n\t\tcase 7:\n\t\t\t// update envelope\n\t\t\tgb_tick_envelope(&gb->snd_1);\n\t\t\tgb_tick_envelope(&gb->snd_2);\n\t\t\tgb_tick_envelope(&gb->snd_4);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tgb_update_square_channel(&gb->snd_1, cycles);\n\tgb_update_square_channel(&gb->snd_2, cycles);\n\tgb_update_wave_channel(gb, &gb->snd_3, cycles);\n\tgb_update_noise_channel(gb, &gb->snd_4, cycles);\n}\n\n\nINLINE UINT32 gb_noise_period_cycles(gb_sound_t *gb)\n{\n\tstatic const int divisor[8] = { 8, 16,32, 48, 64, 80, 96, 112 };\n\treturn divisor[gb->snd_4.reg[3] & 7] << (gb->snd_4.reg[3] >> 4);\n}\n\n\nvoid gameboy_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tgb_sound_t *gb = &GBSoundData[ChipID];\n\tstream_sample_t sample, left, right;\n\tint i;\n\tUINT32 cycles;\n\n\tfor (i = 0; i < samples; i++)\n\t{\n\t\tleft = right = 0;\n\n\t\tgb->cycleCntr.val += gb->cycleCntr.inc;\n\t\tcycles = (UINT32)(gb->cycleCntr.val >> RC_SHIFT);\n\t\tgb->cycleCntr.val &= ((1 << RC_SHIFT) - 1);\n\t\tgb_update_state(gb, cycles);\n\n\t\t/* Mode 1 - Wave with Envelope and Sweep */\n\t\tif (gb->snd_1.on && !gb->snd_1.Muted)\n\t\t{\n\t\t\tsample = gb->snd_1.signal * gb->snd_1.envelope_value;\n\n\t\t\tif (gb->snd_control.mode1_left)\n\t\t\t\tleft += sample;\n\t\t\tif (gb->snd_control.mode1_right)\n\t\t\t\tright += sample;\n\t\t}\n\n\t\t/* Mode 2 - Wave with Envelope */\n\t\tif (gb->snd_2.on && !gb->snd_2.Muted)\n\t\t{\n\t\t\tsample = gb->snd_2.signal * gb->snd_2.envelope_value;\n\t\t\tif (gb->snd_control.mode2_left)\n\t\t\t\tleft += sample;\n\t\t\tif (gb->snd_control.mode2_right)\n\t\t\t\tright += sample;\n\t\t}\n\n\t\t/* Mode 3 - Wave patterns from WaveRAM */\n\t\tif (gb->snd_3.on && !gb->snd_3.Muted)\n\t\t{\n\t\t\tsample = gb->snd_3.signal;\n\t\t\tif (gb->snd_control.mode3_left)\n\t\t\t\tleft += sample;\n\t\t\tif (gb->snd_control.mode3_right)\n\t\t\t\tright += sample;\n\t\t}\n\n\t\t/* Mode 4 - Noise with Envelope */\n\t\tif (gb->snd_4.on && !gb->snd_4.Muted)\n\t\t{\n\t\t\tsample = gb->snd_4.signal * gb->snd_4.envelope_value;\n\t\t\tif (gb->snd_control.mode4_left)\n\t\t\t\tleft += sample;\n\t\t\tif (gb->snd_control.mode4_right)\n\t\t\t\tright += sample;\n\t\t}\n\n\t\t/* Adjust for master volume */\n\t\tleft *= gb->snd_control.vol_left;\n\t\tright *= gb->snd_control.vol_right;\n\n\t\t/* pump up the volume */\n\t\tleft <<= 6;\n\t\tright <<= 6;\n\n\t\t/* Update the buffers */\n\t\toutputs[0][i] = left;\n\t\toutputs[1][i] = right;\n\t}\n\n\tgb->snd_regs[NR52] = (gb->snd_regs[NR52]&0xf0) | gb->snd_1.on | (gb->snd_2.on << 1) | (gb->snd_3.on << 2) | (gb->snd_4.on << 3);\n}\n\n\nint device_start_gameboy_sound(UINT8 ChipID, int clock)\n{\n\tgb_sound_t *gb;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tgb = &GBSoundData[ChipID];\n\tmemset(gb, 0x00, sizeof(gb_sound_t));\n\n\tgb->rate = (clock & 0x7FFFFFFF) / 64;\n\tif (((CHIP_SAMPLING_MODE & 0x01) && gb->rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\tgb->rate = CHIP_SAMPLE_RATE;\n\n\tgb->gbMode = (clock & 0x80000000) ? GBMODE_CGB04 : GBMODE_DMG;\n\tRC_SET_RATIO(&gb->cycleCntr, clock & 0x7FFFFFFF, gb->rate);\n\n\tgameboy_sound_set_mute_mask(ChipID, 0x00);\n\t//gb->BoostWaveChn = 0x00;\n\n\treturn gb->rate;\n}\n\nvoid device_stop_gameboy_sound(UINT8 ChipID)\n{\n\treturn;\n}\n\nvoid device_reset_gameboy_sound(UINT8 ChipID)\n{\n\tgb_sound_t *gb = &GBSoundData[ChipID];\n\tUINT32 muteMask;\n\n\tmuteMask = gameboy_sound_get_mute_mask(ChipID);\n\n\tgb->cycleCntr.val = 0;\n\n\tmemset(&gb->snd_1, 0, sizeof(gb->snd_1));\n\tmemset(&gb->snd_2, 0, sizeof(gb->snd_2));\n\tmemset(&gb->snd_3, 0, sizeof(gb->snd_3));\n\tmemset(&gb->snd_4, 0, sizeof(gb->snd_4));\n\n\tgameboy_sound_set_mute_mask(ChipID, muteMask);\n\n\tgb->snd_1.channel = 1;\n\tgb->snd_1.length_mask = 0x3F;\n\tgb->snd_2.channel = 2;\n\tgb->snd_2.length_mask = 0x3F;\n\tgb->snd_3.channel = 3;\n\tgb->snd_3.length_mask = 0xFF;\n\tgb->snd_4.channel = 4;\n\tgb->snd_4.length_mask = 0x3F;\n\n\tgb_sound_w_internal(gb, NR52, 0x00);\n\tswitch(gb->gbMode)\n\t{\n\tcase GBMODE_DMG:\n\t\tgb->snd_regs[AUD3W0] = 0xac;\n\t\tgb->snd_regs[AUD3W1] = 0xdd;\n\t\tgb->snd_regs[AUD3W2] = 0xda;\n\t\tgb->snd_regs[AUD3W3] = 0x48;\n\t\tgb->snd_regs[AUD3W4] = 0x36;\n\t\tgb->snd_regs[AUD3W5] = 0x02;\n\t\tgb->snd_regs[AUD3W6] = 0xcf;\n\t\tgb->snd_regs[AUD3W7] = 0x16;\n\t\tgb->snd_regs[AUD3W8] = 0x2c;\n\t\tgb->snd_regs[AUD3W9] = 0x04;\n\t\tgb->snd_regs[AUD3WA] = 0xe5;\n\t\tgb->snd_regs[AUD3WB] = 0x2c;\n\t\tgb->snd_regs[AUD3WC] = 0xac;\n\t\tgb->snd_regs[AUD3WD] = 0xdd;\n\t\tgb->snd_regs[AUD3WE] = 0xda;\n\t\tgb->snd_regs[AUD3WF] = 0x48;\n\t\tbreak;\n\tcase GBMODE_CGB04:\n\t\tgb->snd_regs[AUD3W0] = 0x00;\n\t\tgb->snd_regs[AUD3W1] = 0xFF;\n\t\tgb->snd_regs[AUD3W2] = 0x00;\n\t\tgb->snd_regs[AUD3W3] = 0xFF;\n\t\tgb->snd_regs[AUD3W4] = 0x00;\n\t\tgb->snd_regs[AUD3W5] = 0xFF;\n\t\tgb->snd_regs[AUD3W6] = 0x00;\n\t\tgb->snd_regs[AUD3W7] = 0xFF;\n\t\tgb->snd_regs[AUD3W8] = 0x00;\n\t\tgb->snd_regs[AUD3W9] = 0xFF;\n\t\tgb->snd_regs[AUD3WA] = 0x00;\n\t\tgb->snd_regs[AUD3WB] = 0xFF;\n\t\tgb->snd_regs[AUD3WC] = 0x00;\n\t\tgb->snd_regs[AUD3WD] = 0xFF;\n\t\tgb->snd_regs[AUD3WE] = 0x00;\n\t\tgb->snd_regs[AUD3WF] = 0xFF;\n\t\tbreak;\n\t}\n\n\treturn;\n}\n\nvoid gameboy_sound_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tgb_sound_t *gb = &GBSoundData[ChipID];\n\t\n\tgb->snd_1.Muted = (MuteMask >> 0) & 0x01;\n\tgb->snd_2.Muted = (MuteMask >> 1) & 0x01;\n\tgb->snd_3.Muted = (MuteMask >> 2) & 0x01;\n\tgb->snd_4.Muted = (MuteMask >> 3) & 0x01;\n\t\n\treturn;\n}\n\nUINT32 gameboy_sound_get_mute_mask(UINT8 ChipID)\n{\n\tgb_sound_t *gb = &GBSoundData[ChipID];\n\tUINT32 muteMask;\n\t\n\tmuteMask =\t(gb->snd_1.Muted << 0) |\n\t\t\t\t(gb->snd_2.Muted << 1) |\n\t\t\t\t(gb->snd_3.Muted << 2) |\n\t\t\t\t(gb->snd_4.Muted << 3);\n\t\n\treturn muteMask;\n}\n\nvoid gameboy_sound_set_options(UINT8 Flags)\n{\n\tBoostWaveChn = (Flags & 0x01) >> 0;\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/gb.h",
    "content": "\n/* Custom Sound Interface */\nUINT8 gb_wave_r(UINT8 ChipID, offs_t offset);\nvoid gb_wave_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 gb_sound_r(UINT8 ChipID, offs_t offset);\nvoid gb_sound_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid gameboy_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_gameboy_sound(UINT8 ChipID, int clock);\nvoid device_stop_gameboy_sound(UINT8 ChipID);\nvoid device_reset_gameboy_sound(UINT8 ChipID);\n\nvoid gameboy_sound_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\nUINT32 gameboy_sound_get_mute_mask(UINT8 ChipID);\nvoid gameboy_sound_set_options(UINT8 Flags);\n"
  },
  {
    "path": "VGMPlay/chips/iremga20.c",
    "content": "/*********************************************************\n\nIrem GA20 PCM Sound Chip\n\nIt's not currently known whether this chip is stereo.\n\n\nRevisions:\n\n04-15-2002 Acho A. Tang\n- rewrote channel mixing\n- added prelimenary volume and sample rate emulation\n\n05-30-2002 Acho A. Tang\n- applied hyperbolic gain control to volume and used\n  a musical-note style progression in sample rate\n  calculation(still very inaccurate)\n\n02-18-2004 R. Belmont\n- sample rate calculation reverse-engineered.\n  Thanks to Fujix, Yasuhiro Ogawa, the Guru, and Tormod\n  for real PCB samples that made this possible.\n\n02-03-2007 R. Belmont\n- Cleaned up faux x86 assembly.\n\n*********************************************************/\n\n//#include \"emu.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n#include \"iremga20.h\"\n\n#define MAX_VOL 256\n\nstruct IremGA20_channel_def\n{\n\tUINT32 rate;\n\t//UINT32 size;\n\tUINT32 start;\n\tUINT32 pos;\n\tUINT32 frac;\n\tUINT32 end;\n\tUINT32 volume;\n\tUINT32 pan;\n\t//UINT32 effect;\n\tUINT8 play;\n\tUINT8 Muted;\n};\n\ntypedef struct _ga20_state ga20_state;\nstruct _ga20_state\n{\n\tUINT8 *rom;\n\tUINT32 rom_size;\n\t//sound_stream * stream;\n\tUINT16 regs[0x40];\n\tstruct IremGA20_channel_def channel[4];\n};\n\n\n#define MAX_CHIPS\t0x02\nstatic ga20_state GA20Data[MAX_CHIPS];\n\n/*INLINE ga20_state *get_safe_token(device_t *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == IREMGA20);\n\treturn (ga20_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n\n//static STREAM_UPDATE( IremGA20_update )\nvoid IremGA20_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ga20_state *chip = (ga20_state *)param;\n\tga20_state *chip = &GA20Data[ChipID];\n\tUINT32 rate[4], pos[4], frac[4], end[4], vol[4], play[4];\n\tUINT8 *pSamples;\n\tstream_sample_t *outL, *outR;\n\tint i, sampleout;\n\n\t/* precache some values */\n\tfor (i=0; i < 4; i++)\n\t{\n\t\trate[i] = chip->channel[i].rate;\n\t\tpos[i] = chip->channel[i].pos;\n\t\tfrac[i] = chip->channel[i].frac;\n\t\tend[i] = chip->channel[i].end - 0x20;\n\t\tvol[i] = chip->channel[i].volume;\n\t\tplay[i] = (! chip->channel[i].Muted) ? chip->channel[i].play : 0;\n\t}\n\n\ti = samples;\n\tpSamples = chip->rom;\n\toutL = outputs[0];\n\toutR = outputs[1];\n\n\tfor (i = 0; i < samples; i++)\n\t{\n\t\tsampleout = 0;\n\n\t\t// update the 4 channels inline\n\t\tif (play[0])\n\t\t{\n\t\t\tsampleout += (pSamples[pos[0]] - 0x80) * vol[0];\n\t\t\tfrac[0] += rate[0];\n\t\t\tpos[0] += frac[0] >> 24;\n\t\t\tfrac[0] &= 0xffffff;\n\t\t\tplay[0] = (pos[0] < end[0]);\n\t\t}\n\t\tif (play[1])\n\t\t{\n\t\t\tsampleout += (pSamples[pos[1]] - 0x80) * vol[1];\n\t\t\tfrac[1] += rate[1];\n\t\t\tpos[1] += frac[1] >> 24;\n\t\t\tfrac[1] &= 0xffffff;\n\t\t\tplay[1] = (pos[1] < end[1]);\n\t\t}\n\t\tif (play[2])\n\t\t{\n\t\t\tsampleout += (pSamples[pos[2]] - 0x80) * vol[2];\n\t\t\tfrac[2] += rate[2];\n\t\t\tpos[2] += frac[2] >> 24;\n\t\t\tfrac[2] &= 0xffffff;\n\t\t\tplay[2] = (pos[2] < end[2]);\n\t\t}\n\t\tif (play[3])\n\t\t{\n\t\t\tsampleout += (pSamples[pos[3]] - 0x80) * vol[3];\n\t\t\tfrac[3] += rate[3];\n\t\t\tpos[3] += frac[3] >> 24;\n\t\t\tfrac[3] &= 0xffffff;\n\t\t\tplay[3] = (pos[3] < end[3]);\n\t\t}\n\n\t\tsampleout >>= 2;\n\t\toutL[i] = sampleout;\n\t\toutR[i] = sampleout;\n\t}\n\n\t/* update the regs now */\n\tfor (i=0; i < 4; i++)\n\t{\n\t\tchip->channel[i].pos = pos[i];\n\t\tchip->channel[i].frac = frac[i];\n\t\tif (! chip->channel[i].Muted)\n\t\t\tchip->channel[i].play = play[i];\n\t}\n}\n\n//WRITE8_DEVICE_HANDLER( irem_ga20_w )\nvoid irem_ga20_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//ga20_state *chip = get_safe_token(device);\n\tga20_state *chip = &GA20Data[ChipID];\n\tint channel;\n\n\t//logerror(\"GA20:  Offset %02x, data %04x\\n\",offset,data);\n\n\t//chip->stream->update();\n\n\tchannel = offset >> 3;\n\n\tchip->regs[offset] = data;\n\n\tswitch (offset & 0x7)\n\t{\n\t\tcase 0: /* start address low */\n\t\t\tchip->channel[channel].start = ((chip->channel[channel].start)&0xff000) | (data<<4);\n\t\t\tbreak;\n\n\t\tcase 1: /* start address high */\n\t\t\tchip->channel[channel].start = ((chip->channel[channel].start)&0x00ff0) | (data<<12);\n\t\t\tbreak;\n\n\t\tcase 2: /* end address low */\n\t\t\tchip->channel[channel].end = ((chip->channel[channel].end)&0xff000) | (data<<4);\n\t\t\tbreak;\n\n\t\tcase 3: /* end address high */\n\t\t\tchip->channel[channel].end = ((chip->channel[channel].end)&0x00ff0) | (data<<12);\n\t\t\tbreak;\n\n\t\tcase 4:\n\t\t\tchip->channel[channel].rate = 0x1000000 / (256 - data);\n\t\t\tbreak;\n\n\t\tcase 5: //AT: gain control\n\t\t\tchip->channel[channel].volume = (data * MAX_VOL) / (data + 10);\n\t\t\tbreak;\n\n\t\tcase 6: //AT: this is always written 2(enabling both channels?)\n\t\t\tchip->channel[channel].play = data;\n\t\t\tchip->channel[channel].pos = chip->channel[channel].start;\n\t\t\tchip->channel[channel].frac = 0;\n\t\t\tbreak;\n\t}\n}\n\n//READ8_DEVICE_HANDLER( irem_ga20_r )\nUINT8 irem_ga20_r(UINT8 ChipID, offs_t offset)\n{\n\t//ga20_state *chip = get_safe_token(device);\n\tga20_state *chip = &GA20Data[ChipID];\n\tint channel;\n\n\t//chip->stream->update();\n\n\tchannel = offset >> 3;\n\n\tswitch (offset & 0x7)\n\t{\n\t\tcase 7:\t// voice status.  bit 0 is 1 if active. (routine around 0xccc in rtypeleo)\n\t\t\treturn chip->channel[channel].play ? 1 : 0;\n\n\t\tdefault:\n\t\t\tlogerror(\"GA20: read unk. register %d, channel %d\\n\", offset & 0xf, channel);\n\t\t\tbreak;\n\t}\n\n\treturn 0;\n}\n\nstatic void iremga20_reset(ga20_state *chip)\n{\n\tint i;\n\n\tfor( i = 0; i < 4; i++ ) {\n\t\tchip->channel[i].rate = 0;\n\t\t//chip->channel[i].size = 0;\n\t\tchip->channel[i].start = 0;\n\t\tchip->channel[i].pos = 0;\n\t\tchip->channel[i].frac = 0;\n\t\tchip->channel[i].end = 0;\n\t\tchip->channel[i].volume = 0;\n\t\tchip->channel[i].pan = 0;\n\t\t//chip->channel[i].effect = 0;\n\t\tchip->channel[i].play = 0;\n\t}\n}\n\n\n//static DEVICE_RESET( iremga20 )\nvoid device_reset_iremga20(UINT8 ChipID)\n{\n\t//iremga20_reset(get_safe_token(device));\n\tga20_state *chip = &GA20Data[ChipID];\n\t\n\tiremga20_reset(chip);\n\tmemset(chip->regs, 0x00, 0x40 * sizeof(UINT16));\n}\n\n//static DEVICE_START( iremga20 )\nint device_start_iremga20(UINT8 ChipID, int clock)\n{\n\t//ga20_state *chip = get_safe_token(device);\n\tga20_state *chip;\n\tint i;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &GA20Data[ChipID];\n\n\t/* Initialize our chip structure */\n\t//chip->rom = *device->region();\n\t//chip->rom_size = device->region()->bytes();\n\tchip->rom = NULL;\n\tchip->rom_size = 0x00;\n\n\tiremga20_reset(chip);\n\n\tfor ( i = 0; i < 0x40; i++ )\n\t\tchip->regs[i] = 0;\n\n\t//chip->stream = device->machine().sound().stream_alloc( *device, 0, 2, device->clock()/4, chip, IremGA20_update );\n\n\t/*device->save_item(NAME(chip->regs));\n\tfor (i = 0; i < 4; i++)\n\t{\n\t\tdevice->save_item(NAME(chip->channel[i].rate), i);\n\t\tdevice->save_item(NAME(chip->channel[i].size), i);\n\t\tdevice->save_item(NAME(chip->channel[i].start), i);\n\t\tdevice->save_item(NAME(chip->channel[i].pos), i);\n\t\tdevice->save_item(NAME(chip->channel[i].end), i);\n\t\tdevice->save_item(NAME(chip->channel[i].volume), i);\n\t\tdevice->save_item(NAME(chip->channel[i].pan), i);\n\t\tdevice->save_item(NAME(chip->channel[i].effect), i);\n\t\tdevice->save_item(NAME(chip->channel[i].play), i);\n\t}*/\n\tfor (i = 0; i < 4; i ++)\n\t\tchip->channel[i].Muted = 0x00;\n\t\n\treturn clock / 4;\n}\n\nvoid device_stop_iremga20(UINT8 ChipID)\n{\n\tga20_state *chip = &GA20Data[ChipID];\n\t\n\tfree(chip->rom);\tchip->rom = NULL;\n\t\n\treturn;\n}\n\nvoid iremga20_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t\tconst UINT8* ROMData)\n{\n\tga20_state *chip = &GA20Data[ChipID];\n\t\n\tif (chip->rom_size != ROMSize)\n\t{\n\t\tchip->rom = (UINT8*)realloc(chip->rom, ROMSize);\n\t\tchip->rom_size = ROMSize;\n\t\tmemset(chip->rom, 0xFF, ROMSize);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(chip->rom + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\n\nvoid iremga20_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tga20_state *chip = &GA20Data[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 4; CurChn ++)\n\t\tchip->channel[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( iremga20 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ga20_state);\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( iremga20 );\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// nothing //\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( iremga20 );\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"Irem GA20\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Irem custom\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}\n\n\nDEFINE_LEGACY_SOUND_DEVICE(IREMGA20, iremga20);*/\n"
  },
  {
    "path": "VGMPlay/chips/iremga20.h",
    "content": "/*********************************************************\n\n    Irem GA20 PCM Sound Chip\n\n*********************************************************/\n#pragma once\n\n#ifndef __IREMGA20_H__\n#define __IREMGA20_H__\n\n//#include \"devlegcy.h\"\n\nvoid IremGA20_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_iremga20(UINT8 ChipID, int clock);\nvoid device_stop_iremga20(UINT8 ChipID);\nvoid device_reset_iremga20(UINT8 ChipID);\n\n//WRITE8_DEVICE_HANDLER( irem_ga20_w );\n//READ8_DEVICE_HANDLER( irem_ga20_r );\nUINT8 irem_ga20_r(UINT8 ChipID, offs_t offset);\nvoid irem_ga20_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid iremga20_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t\tconst UINT8* ROMData);\n\nvoid iremga20_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n//DECLARE_LEGACY_SOUND_DEVICE(IREMGA20, iremga20);\n\n#endif /* __IREMGA20_H__ */\n"
  },
  {
    "path": "VGMPlay/chips/k051649.c",
    "content": "/***************************************************************************\n\n    Konami 051649 - SCC1 sound as used in Haunted Castle, City Bomber\n\n    This file is pieced together by Bryan McPhail from a combination of\n    Namco Sound, Amuse by Cab, Haunted Castle schematics and whoever first\n    figured out SCC!\n\n    The 051649 is a 5 channel sound generator, each channel gets its\n    waveform from RAM (32 bytes per waveform, 8 bit signed data).\n\n    This sound chip is the same as the sound chip in some Konami\n    megaROM cartridges for the MSX. It is actually well researched\n    and documented:\n\n        http://bifi.msxnet.org/msxnet/tech/scc.html\n\n    Thanks to Sean Young (sean@mess.org) for some bugfixes.\n\n    K052539 is more or less equivalent to this chip except channel 5\n    does not share waveram with channel 4.\n\n***************************************************************************/\n\n#include \"mamedef.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n//#include \"emu.h\"\n//#include \"streams.h\"\n#include \"k051649.h\"\n\n#define FREQ_BITS\t16\n#define DEF_GAIN\t8\n\n/* this structure defines the parameters for a channel */\ntypedef struct\n{\n\tunsigned long counter;\n\tint frequency;\n\tint volume;\n\tint key;\n\tsigned char waveram[32];\t\t/* 19991207.CAB */\n\tUINT8 Muted;\n} k051649_sound_channel;\n\ntypedef struct _k051649_state k051649_state;\nstruct _k051649_state\n{\n\tk051649_sound_channel channel_list[5];\n\n\t/* global sound parameters */\n\t//sound_stream * stream;\n\tint mclock,rate;\n\n\t/* mixer tables and internal buffers */\n\tINT16 *mixer_table;\n\tINT16 *mixer_lookup;\n\tshort *mixer_buffer;\n\n\tint cur_reg;\n\tUINT8 test;\n};\n\n#define MAX_CHIPS\t0x02\nstatic k051649_state SCC1Data[MAX_CHIPS];\n\n/*INLINE k051649_state *get_safe_token(running_device *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == K051649);\n\treturn (k051649_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n/* build a table to divide by the number of voices */\nstatic void make_mixer_table(/*running_machine *machine,*/ k051649_state *info, int voices)\n{\n\tint count = voices * 256;\n\tint i;\n\n\t/* allocate memory */\n\t//info->mixer_table = auto_alloc_array(machine, INT16, 512 * voices);\n\tinfo->mixer_table = (INT16*)malloc(sizeof(INT16) * 2 * count);\n\n\t/* find the middle of the table */\n\tinfo->mixer_lookup = info->mixer_table + count;\n\n\t/* fill in the table - 16 bit case */\n\tfor (i = 0; i < count; i++)\n\t{\n\t\tint val = i * DEF_GAIN * 16 / voices;\n\t\t//if (val > 32767) val = 32767;\n\t\tif (val > 32768) val = 32768;\n\t\tinfo->mixer_lookup[ i] = val;\n\t\tinfo->mixer_lookup[-i] = -val;\n\t}\n}\n\n\n/* generate sound to the mix buffer */\n//static STREAM_UPDATE( k051649_update )\nvoid k051649_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//k051649_state *info = (k051649_state *)param;\n\tk051649_state *info = &SCC1Data[ChipID];\n\tk051649_sound_channel *voice=info->channel_list;\n\tstream_sample_t *buffer = outputs[0];\n\tstream_sample_t *buffer2 = outputs[1];\n\tshort *mix;\n\tint i,j;\n\n\t// zap the contents of the mixer buffer\n\tmemset(info->mixer_buffer, 0, samples * sizeof(short));\n\n\tfor (j=0; j<5; j++) {\n\t\t// channel is halted for freq < 9\n\t\tif (voice[j].frequency > 8 && ! voice[j].Muted)\n\t\t{\n\t\t\tconst signed char *w = voice[j].waveram;\t\t\t/* 19991207.CAB */\n\t\t\tint v=voice[j].volume * voice[j].key;\n\t\t\tint c=voice[j].counter;\n\t\t\t/* Amuse source:  Cab suggests this method gives greater resolution */\n\t\t\t/* Sean Young 20010417: the formula is really: f = clock/(16*(f+1))*/\n\t\t\tint step = (int)(((INT64)info->mclock * (1 << FREQ_BITS)) / (float)((voice[j].frequency + 1) * 16 * (info->rate / 32)) + 0.5);\n\n\t\t\tmix = info->mixer_buffer;\n\n\t\t\t// add our contribution\n\t\t\tfor (i = 0; i < samples; i++)\n\t\t\t{\n\t\t\t\tint offs;\n\n\t\t\t\tc += step;\n\t\t\t\toffs = (c >> FREQ_BITS) & 0x1f;\n\t\t\t\t*mix++ += (w[offs] * v)>>3;\n\t\t\t}\n\n\t\t\t// update the counter for this voice\n\t\t\tvoice[j].counter = c;\n\t\t}\n\t}\n\n\t// mix it down\n\tmix = info->mixer_buffer;\n\tfor (i = 0; i < samples; i++)\n\t\t*buffer++ = *buffer2++ = info->mixer_lookup[*mix++];\n}\n\n//static DEVICE_START( k051649 )\nint device_start_k051649(UINT8 ChipID, int clock)\n{\n\t//k051649_state *info = get_safe_token(device);\n\tk051649_state *info;\n\tUINT8 CurChn;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &SCC1Data[ChipID];\n\t/* get stream channels */\n\t//info->rate = device->clock()/16;\n\t//info->stream = stream_create(device, 0, 1, info->rate, info, k051649_update);\n\t//info->mclock = device->clock();\n\tinfo->mclock = clock & 0x7FFFFFFF;\n\tinfo->rate = info->mclock / 16;\n\n\t/* allocate a buffer to mix into - 1 second's worth should be more than enough */\n\t//info->mixer_buffer = auto_alloc_array(device->machine, short, 2 * info->rate);\n\tinfo->mixer_buffer = (short*)malloc(sizeof(short) * info->rate);\n\n\t/* build the mixer table */\n\t//make_mixer_table(device->machine, info, 5);\n\tmake_mixer_table(info, 5);\n\t\n\tfor (CurChn = 0; CurChn < 5; CurChn ++)\n\t\tinfo->channel_list[CurChn].Muted = 0x00;\n\t\n\treturn info->rate;\n}\n\nvoid device_stop_k051649(UINT8 ChipID)\n{\n\tk051649_state *info = &SCC1Data[ChipID];\n\t\n\tfree(info->mixer_buffer);\n\tfree(info->mixer_table);\n\t\n\treturn;\n}\n\n//static DEVICE_RESET( k051649 )\nvoid device_reset_k051649(UINT8 ChipID)\n{\n\t//k051649_state *info = get_safe_token(device);\n\tk051649_state *info = &SCC1Data[ChipID];\n\tk051649_sound_channel *voice = info->channel_list;\n\tint i;\n\n\t// reset all the voices\n\tfor (i = 0; i < 5; i++)\n\t{\n\t\tvoice[i].frequency = 0;\n\t\tvoice[i].volume = 0;\n\t\tvoice[i].counter = 0;\n\t\tvoice[i].key = 0;\n\t}\n\t\n\t// other parameters\n\tinfo->test = 0x00;\n\tinfo->cur_reg = 0x00;\n\t\n\treturn;\n}\n\n/********************************************************************************/\n\n//WRITE8_DEVICE_HANDLER( k051649_waveform_w )\nvoid k051649_waveform_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//k051649_state *info = get_safe_token(device);\n\tk051649_state *info = &SCC1Data[ChipID];\n\t\n\t// waveram is read-only?\n\tif (info->test & 0x40 || (info->test & 0x80 && offset >= 0x60))\n\t\treturn;\n\n\t//stream_update(info->stream);\n\t\n\tif (offset >= 0x60)\n\t{\n\t\t// channel 5 shares waveram with channel 4\n\t\tinfo->channel_list[3].waveram[offset&0x1f]=data;\n\t\tinfo->channel_list[4].waveram[offset&0x1f]=data;\n\t}\n\telse\n\t\tinfo->channel_list[offset>>5].waveram[offset&0x1f]=data;\n}\n\n//READ8_DEVICE_HANDLER ( k051649_waveform_r )\nUINT8 k051649_waveform_r(UINT8 ChipID, offs_t offset)\n{\n\t//k051649_state *info = get_safe_token(device);\n\tk051649_state *info = &SCC1Data[ChipID];\n\t\n\t// test-register bits 6/7 expose the internal counter\n\tif (info->test & 0xc0)\n\t{\n\t\t//stream_update(info->stream);\n\n\t\tif (offset >= 0x60)\n\t\t\toffset += (info->channel_list[3 + (info->test >> 6 & 1)].counter >> FREQ_BITS);\n\t\telse if (info->test & 0x40)\n\t\t\toffset += (info->channel_list[offset>>5].counter >> FREQ_BITS);\n\t}\n\treturn info->channel_list[offset>>5].waveram[offset&0x1f];\n}\n\n/* SY 20001114: Channel 5 doesn't share the waveform with channel 4 on this chip */\n//WRITE8_DEVICE_HANDLER( k052539_waveform_w )\nvoid k052539_waveform_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//k051649_state *info = get_safe_token(device);\n\tk051649_state *info = &SCC1Data[ChipID];\n\t\n\t// waveram is read-only?\n\tif (info->test & 0x40)\n\t\treturn;\n\n\t//stream_update(info->stream);\n\tinfo->channel_list[offset>>5].waveram[offset&0x1f]=data;\n}\n\n//READ8_DEVICE_HANDLER ( k052539_waveform_r )\nUINT8 k052539_waveform_r(UINT8 ChipID, offs_t offset)\n{\n\t//k051649_state *info = get_safe_token(device);\n\tk051649_state *info = &SCC1Data[ChipID];\n\t\n\t// test-register bit 6 exposes the internal counter\n\tif (info->test & 0x40)\n\t{\n\t\t//stream_update(info->stream);\n\t\toffset += (info->channel_list[offset>>5].counter >> FREQ_BITS);\n\t}\n\treturn info->channel_list[offset>>5].waveram[offset&0x1f];\n}\n\n//WRITE8_DEVICE_HANDLER( k051649_volume_w )\nvoid k051649_volume_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//k051649_state *info = get_safe_token(device);\n\tk051649_state *info = &SCC1Data[ChipID];\n\t//stream_update(info->stream);\n\tinfo->channel_list[offset&0x7].volume=data&0xf;\n}\n\n//WRITE8_DEVICE_HANDLER( k051649_frequency_w )\nvoid k051649_frequency_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//k051649_state *info = get_safe_token(device);\n\tk051649_state *info = &SCC1Data[ChipID];\n\tk051649_sound_channel* chn = &info->channel_list[offset >> 1];\n\n\t//stream_update(info->stream);\n\t\n\t// test-register bit 5 resets the internal counter\n\tif (info->test & 0x20)\n\t\tchn->counter = ~0;\n\telse if (chn->frequency < 9)\n\t\tchn->counter |= ((1 << FREQ_BITS) - 1);\n\n\t// update frequency\n\tif (offset & 1)\n\t\tchn->frequency = (chn->frequency & 0x0FF) | ((data << 8) & 0xF00);\n\telse\n\t\tchn->frequency = (chn->frequency & 0xF00) |  (data << 0);\n\tchn->counter &= 0xFFFF0000;\t// Valley Bell: Behaviour according to openMSX\n}\n\n//WRITE8_DEVICE_HANDLER( k051649_keyonoff_w )\nvoid k051649_keyonoff_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//k051649_state *info = get_safe_token(device);\n\tk051649_state *info = &SCC1Data[ChipID];\n\tint i;\n\t//stream_update(info->stream);\n\t\n\tfor (i = 0; i < 5; i++)\n\t{\n\t\tinfo->channel_list[i].key=data&1;\n\t\tdata >>= 1;\n\t}\n}\n\n//WRITE8_MEMBER( k051649_device::k051649_test_w )\nvoid k051649_test_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tk051649_state *info = &SCC1Data[ChipID];\n\tinfo->test = data;\n}\n\n\n//READ8_MEMBER ( k051649_device::k051649_test_r )\nUINT8 k051649_test_r(UINT8 ChipID, offs_t offset)\n{\n\t// reading the test register sets it to $ff!\n\tk051649_test_w(ChipID, offset, 0xff);\n\treturn 0xff;\n}\n\n\nvoid k051649_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tk051649_state *info = &SCC1Data[ChipID];\n\t\n\tswitch(offset & 1)\n\t{\n\tcase 0x00:\n\t\tinfo->cur_reg = data;\n\t\tbreak;\n\tcase 0x01:\n\t\tswitch(offset >> 1)\n\t\t{\n\t\tcase 0x00:\n\t\t\tk051649_waveform_w(ChipID, info->cur_reg, data);\n\t\t\tbreak;\n\t\tcase 0x01:\n\t\t\tk051649_frequency_w(ChipID, info->cur_reg, data);\n\t\t\tbreak;\n\t\tcase 0x02:\n\t\t\tk051649_volume_w(ChipID, info->cur_reg, data);\n\t\t\tbreak;\n\t\tcase 0x03:\n\t\t\tk051649_keyonoff_w(ChipID, info->cur_reg, data);\n\t\t\tbreak;\n\t\tcase 0x04:\n\t\t\tk052539_waveform_w(ChipID, info->cur_reg, data);\n\t\t\tbreak;\n\t\tcase 0x05:\n\t\t\tk051649_test_w(ChipID, info->cur_reg, data);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\n\nvoid k051649_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tk051649_state *info = &SCC1Data[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 5; CurChn ++)\n\t\tinfo->channel_list[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( k051649 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(k051649_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( k051649 );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// nothing //\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( k051649 );\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"K051649\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Konami custom\");\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n\n\n//DEFINE_LEGACY_SOUND_DEVICE(K051649, k051649);\n"
  },
  {
    "path": "VGMPlay/chips/k051649.h",
    "content": "#pragma once\n\n//#ifndef __K051649_H__\n//#define __K051649_H__\n\n//#include \"devlegcy.h\"\n\n/*WRITE8_DEVICE_HANDLER( k051649_waveform_w );\nREAD8_DEVICE_HANDLER( k051649_waveform_r );\nWRITE8_DEVICE_HANDLER( k051649_volume_w );\nWRITE8_DEVICE_HANDLER( k051649_frequency_w );\nWRITE8_DEVICE_HANDLER( k051649_keyonoff_w );\n\nWRITE8_DEVICE_HANDLER( k052539_waveform_w );\n\nDECLARE_LEGACY_SOUND_DEVICE(K051649, k051649);*/\n\nvoid k051649_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_k051649(UINT8 ChipID, int clock);\nvoid device_stop_k051649(UINT8 ChipID);\nvoid device_reset_k051649(UINT8 ChipID);\n\nvoid k051649_waveform_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 k051649_waveform_r(UINT8 ChipID, offs_t offset);\nvoid k051649_volume_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid k051649_frequency_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid k051649_keyonoff_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid k052539_waveform_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 k052539_waveform_r(UINT8 ChipID, offs_t offset);\n\nvoid k051649_test_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 k051649_test_r(UINT8 ChipID, offs_t offset);\n\nvoid k051649_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid k051649_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n//#endif /* __K051649_H__ */\n"
  },
  {
    "path": "VGMPlay/chips/k053260.c",
    "content": "/*********************************************************\n\n    Konami 053260 PCM Sound Chip\n\n*********************************************************/\n\n#include \"mamedef.h\"\n//#include \"emu.h\"\n#ifdef _DEBUG\n#include <stdio.h>\n#endif\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"k053260.h\"\n\n/* 2004-02-28: Fixed PPCM decoding. Games sound much better now.*/\n\n#define LOG 0\n\n#define BASE_SHIFT\t16\n\ntypedef struct _k053260_channel k053260_channel;\nstruct _k053260_channel\n{\n\tUINT32\t\trate;\n\tUINT32\t\tsize;\n\tUINT32\t\tstart;\n\tUINT32\t\tbank;\n\tUINT32\t\tvolume;\n\tint\t\t\tplay;\n\tUINT32\t\tpan;\n\tUINT32\t\tpos;\n\tint\t\t\tloop;\n\tint\t\t\tppcm; /* packed PCM ( 4 bit signed ) */\n\tint\t\t\tppcm_data;\n\tUINT8\t\tMuted;\n};\n\ntypedef struct _k053260_state k053260_state;\nstruct _k053260_state\n{\n\t//sound_stream *\t\t\t\tchannel;\n\tint\t\t\t\t\t\t\tmode;\n\tint\t\t\t\t\t\t\tregs[0x30];\n\tUINT8\t\t\t\t\t\t*rom;\n\t//int\t\t\t\t\t\t\trom_size;\n\tUINT32\t\t\t\t\t\t\trom_size;\n\tUINT32\t\t\t\t\t\t*delta_table;\n\tk053260_channel\t\t\t\tchannels[4];\n\t//const k053260_interface\t\t*intf;\n\t//device_t\t\t\t\t*device;\n};\n\n#define MAX_CHIPS\t0x02\nstatic k053260_state K053260Data[MAX_CHIPS];\n\n/*INLINE k053260_state *get_safe_token(device_t *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == K053260);\n\treturn (k053260_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n\nstatic void InitDeltaTable( k053260_state *ic, int rate, int clock )\n{\n\tint\t\ti;\n\tdouble\tbase = ( double )rate;\n\tdouble\tmax = (double)(clock); /* Hz */\n\tUINT32 val;\n\n\tfor( i = 0; i < 0x1000; i++ ) {\n\t\tdouble v = ( double )( 0x1000 - i );\n\t\tdouble target = (max) / v;\n\t\tdouble fixed = ( double )( 1 << BASE_SHIFT );\n\n\t\tif ( target && base ) {\n\t\t\ttarget = fixed / ( base / target );\n\t\t\tval = ( UINT32 )target;\n\t\t\tif ( val == 0 )\n\t\t\t\tval = 1;\n\t\t} else\n\t\t\tval = 1;\n\n\t\tic->delta_table[i] = val;\n\t}\n}\n\n//static DEVICE_RESET( k053260 )\nvoid device_reset_k053260(UINT8 ChipID)\n{\n\t//k053260_state *ic = get_safe_token(device);\n\tk053260_state *ic = &K053260Data[ChipID];\n\tint i;\n\n\tfor( i = 0; i < 4; i++ ) {\n\t\tic->channels[i].rate = 0;\n\t\tic->channels[i].size = 0;\n\t\tic->channels[i].start = 0;\n\t\tic->channels[i].bank = 0;\n\t\tic->channels[i].volume = 0;\n\t\tic->channels[i].play = 0;\n\t\tic->channels[i].pan = 0;\n\t\tic->channels[i].pos = 0;\n\t\tic->channels[i].loop = 0;\n\t\tic->channels[i].ppcm = 0;\n\t\tic->channels[i].ppcm_data = 0;\n\t}\n}\n\nINLINE int limit( int val, int max, int min )\n{\n\tif ( val > max )\n\t\tval = max;\n\telse if ( val < min )\n\t\tval = min;\n\n\treturn val;\n}\n\n//#define MAXOUT 0x7fff\n#define MAXOUT +0x8000\n#define MINOUT -0x8000\n\n//static STREAM_UPDATE( k053260_update )\nvoid k053260_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tstatic const INT8 dpcmcnv[] = { 0,1,2,4,8,16,32,64, -128, -64, -32, -16, -8, -4, -2, -1};\n\n\tint i, j, lvol[4], rvol[4], play[4], loop[4], ppcm[4];\n\tUINT8 *rom[4];\n\tUINT32 delta[4], end[4], pos[4];\n\tINT8 ppcm_data[4];\n\tint dataL, dataR;\n\tINT8 d;\n\t//k053260_state *ic = (k053260_state *)param;\n\tk053260_state *ic = &K053260Data[ChipID];\n\n\t/* precache some values */\n\tfor ( i = 0; i < 4; i++ ) {\n\t\tif (ic->channels[i].Muted)\n\t\t{\n\t\t\tplay[i] = 0;\n\t\t\tcontinue;\n\t\t}\n\t\trom[i]= &ic->rom[ic->channels[i].start + ( ic->channels[i].bank << 16 )];\n\t\tdelta[i] = ic->delta_table[ic->channels[i].rate];\n\t\tlvol[i] = ic->channels[i].volume * ic->channels[i].pan;\n\t\trvol[i] = ic->channels[i].volume * ( 8 - ic->channels[i].pan );\n\t\tend[i] = ic->channels[i].size;\n\t\tpos[i] = ic->channels[i].pos;\n\t\tplay[i] = ic->channels[i].play;\n\t\tloop[i] = ic->channels[i].loop;\n\t\tppcm[i] = ic->channels[i].ppcm;\n\t\tppcm_data[i] = ic->channels[i].ppcm_data;\n\t\tif ( ppcm[i] )\n\t\t\tdelta[i] /= 2;\n\t}\n\n\t\tfor ( j = 0; j < samples; j++ ) {\n\n\t\t\tdataL = dataR = 0;\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\t/* see if the voice is on */\n\t\t\t\tif ( play[i] ) {\n\t\t\t\t\t/* see if we're done */\n\t\t\t\t\tif ( ( pos[i] >> BASE_SHIFT ) >= end[i] ) {\n\n\t\t\t\t\t\tppcm_data[i] = 0;\n\t\t\t\t\t\tif ( loop[i] )\n\t\t\t\t\t\t\tpos[i] = 0;\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tplay[i] = 0;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( ppcm[i] ) { /* Packed PCM */\n\t\t\t\t\t\t/* we only update the signal if we're starting or a real sound sample has gone by */\n\t\t\t\t\t\t/* this is all due to the dynamic sample rate conversion */\n\t\t\t\t\t\tif ( pos[i] == 0 || ( ( pos[i] ^ ( pos[i] - delta[i] ) ) & 0x8000 ) == 0x8000 )\n\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint newdata;\n\t\t\t\t\t\t\tif ( pos[i] & 0x8000 ){\n\n\t\t\t\t\t\t\t\tnewdata = ((rom[i][pos[i] >> BASE_SHIFT]) >> 4) & 0x0f; /*high nybble*/\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse{\n\t\t\t\t\t\t\t\tnewdata = ( ( rom[i][pos[i] >> BASE_SHIFT] ) ) & 0x0f; /*low nybble*/\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/*ppcm_data[i] = (( ( ppcm_data[i] * 62 ) >> 6 ) + dpcmcnv[newdata]);\n\n\t\t\t\t\t\t\tif ( ppcm_data[i] > 127 )\n\t\t\t\t\t\t\t\tppcm_data[i] = 127;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tif ( ppcm_data[i] < -128 )\n\t\t\t\t\t\t\t\t\tppcm_data[i] = -128;*/\n\t\t\t\t\t\t\tppcm_data[i] += dpcmcnv[newdata];\n\t\t\t\t\t\t}\n\n\n\n\t\t\t\t\t\td = ppcm_data[i];\n\n\t\t\t\t\t\tpos[i] += delta[i];\n\t\t\t\t\t} else { /* PCM */\n\t\t\t\t\t\td = rom[i][pos[i] >> BASE_SHIFT];\n\n\t\t\t\t\t\tpos[i] += delta[i];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( ic->mode & 2 ) {\n\t\t\t\t\t\tdataL += ( d * lvol[i] ) >> 2;\n\t\t\t\t\t\tdataR += ( d * rvol[i] ) >> 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toutputs[1][j] = limit( dataL, MAXOUT, MINOUT );\n\t\t\toutputs[0][j] = limit( dataR, MAXOUT, MINOUT );\n\t\t}\n\n\t/* update the regs now */\n\tfor ( i = 0; i < 4; i++ ) {\n\t\tif (ic->channels[i].Muted)\n\t\t\tcontinue;\n\t\tic->channels[i].pos = pos[i];\n\t\tic->channels[i].play = play[i];\n\t\tic->channels[i].ppcm_data = ppcm_data[i];\n\t}\n}\n\n//static DEVICE_START( k053260 )\nint device_start_k053260(UINT8 ChipID, int clock)\n{\n\t//static const k053260_interface defintrf = { 0 };\n\t//k053260_state *ic = get_safe_token(device);\n\tk053260_state *ic;\n\t//int rate = device->clock() / 32;\n\tint rate = clock / 32;\n\tint i;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tic = &K053260Data[ChipID];\n\t\n\t/* Initialize our chip structure */\n\t//ic->device = device;\n\t//ic->intf = (device->static_config() != NULL) ? (const k053260_interface *)device->static_config() : &defintrf;\n\n\tic->mode = 0;\n\n\t//const memory_region *region = (ic->intf->rgnoverride != NULL) ? device->machine().region(ic->intf->rgnoverride) : device->region();\n\n\t//ic->rom = *region;\n\t//ic->rom_size = region->bytes();\n\tic->rom = NULL;\n\tic->rom_size = 0x00;\n\n\t// has to be done by the player after calling device_start\n\t//DEVICE_RESET_CALL(k053260);\n\n\tfor ( i = 0; i < 0x30; i++ )\n\t\tic->regs[i] = 0;\n\n\t//ic->delta_table = auto_alloc_array( device->machine(), UINT32, 0x1000 );\n\tic->delta_table = (UINT32*)malloc(0x1000 * sizeof(UINT32));\n\n\t//ic->channel = device->machine().sound().stream_alloc( *device, 0, 2, rate, ic, k053260_update );\n\n\t//InitDeltaTable( ic, rate, device->clock() );\n\tInitDeltaTable( ic, rate, clock );\n\n\t/* register with the save state system */\n\t/*device->save_item(NAME(ic->mode));\n\tdevice->save_item(NAME(ic->regs));\n\n\tfor ( i = 0; i < 4; i++ )\n\t{\n\t\tdevice->save_item(NAME(ic->channels[i].rate), i);\n\t\tdevice->save_item(NAME(ic->channels[i].size), i);\n\t\tdevice->save_item(NAME(ic->channels[i].start), i);\n\t\tdevice->save_item(NAME(ic->channels[i].bank), i);\n\t\tdevice->save_item(NAME(ic->channels[i].volume), i);\n\t\tdevice->save_item(NAME(ic->channels[i].play), i);\n\t\tdevice->save_item(NAME(ic->channels[i].pan), i);\n\t\tdevice->save_item(NAME(ic->channels[i].pos), i);\n\t\tdevice->save_item(NAME(ic->channels[i].loop), i);\n\t\tdevice->save_item(NAME(ic->channels[i].ppcm), i);\n\t\tdevice->save_item(NAME(ic->channels[i].ppcm_data), i);\n\t}*/\n\n\t/* setup SH1 timer if necessary */\n\t//if ( ic->intf->irq )\n\t//\tdevice->machine().scheduler().timer_pulse( attotime::from_hz(device->clock()) * 32, ic->intf->irq, \"ic->intf->irq\" );\n\t\n\tfor (i = 0; i < 4; i ++)\n\t\tic->channels[i].Muted = 0x00;\n\t\n\treturn rate;\n}\n\nvoid device_stop_k053260(UINT8 ChipID)\n{\n\tk053260_state *ic = &K053260Data[ChipID];\n\t\n\tfree(ic->delta_table);\n\tfree(ic->rom);\tic->rom = NULL;\n\t\n\treturn;\n}\n\nINLINE void check_bounds( k053260_state *ic, int channel )\n{\n\n\tint channel_start = ( ic->channels[channel].bank << 16 ) + ic->channels[channel].start;\n\tint channel_end = channel_start + ic->channels[channel].size - 1;\n\n\tif ( channel_start > ic->rom_size ) {\n\t\tlogerror(\"K53260: Attempting to start playing past the end of the ROM ( start = %06x, end = %06x ).\\n\", channel_start, channel_end );\n\n\t\tic->channels[channel].play = 0;\n\n\t\treturn;\n\t}\n\n\tif ( channel_end > ic->rom_size ) {\n\t\tlogerror(\"K53260: Attempting to play past the end of the ROM ( start = %06x, end = %06x ).\\n\", channel_start, channel_end );\n\n\t\tic->channels[channel].size = ic->rom_size - channel_start;\n\t}\n\tif (LOG) logerror(\"K053260: Sample Start = %06x, Sample End = %06x, Sample rate = %04x, PPCM = %s\\n\", channel_start, channel_end, ic->channels[channel].rate, ic->channels[channel].ppcm ? \"yes\" : \"no\" );\n}\n\n//WRITE8_DEVICE_HANDLER( k053260_w )\nvoid k053260_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tint i, t;\n\tint r = offset;\n\tint v = data;\n\n\t//k053260_state *ic = get_safe_token(device);\n\tk053260_state *ic = &K053260Data[ChipID];\n\n\tif ( r > 0x2f ) {\n\t\tlogerror(\"K053260: Writing past registers\\n\" );\n\t\treturn;\n\t}\n\n\t //ic->channel->update();\n\n\t/* before we update the regs, we need to check for a latched reg */\n\tif ( r == 0x28 ) {\n\t\tt = ic->regs[r] ^ v;\n\n\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\tif ( t & ( 1 << i ) ) {\n\t\t\t\tif ( v & ( 1 << i ) ) {\n\t\t\t\t\tic->channels[i].play = 1;\n\t\t\t\t\tic->channels[i].pos = 0;\n\t\t\t\t\tic->channels[i].ppcm_data = 0;\n\t\t\t\t\tcheck_bounds( ic, i );\n\t\t\t\t} else\n\t\t\t\t\tic->channels[i].play = 0;\n\t\t\t}\n\t\t}\n\n\t\tic->regs[r] = v;\n\t\treturn;\n\t}\n\n\t/* update regs */\n\tic->regs[r] = v;\n\n\t/* communication registers */\n\tif ( r < 8 )\n\t\treturn;\n\n\t/* channel setup */\n\tif ( r < 0x28 ) {\n\t\tint channel = ( r - 8 ) / 8;\n\n\t\tswitch ( ( r - 8 ) & 0x07 ) {\n\t\t\tcase 0: /* sample rate low */\n\t\t\t\tic->channels[channel].rate &= 0x0f00;\n\t\t\t\tic->channels[channel].rate |= v;\n\t\t\tbreak;\n\n\t\t\tcase 1: /* sample rate high */\n\t\t\t\tic->channels[channel].rate &= 0x00ff;\n\t\t\t\tic->channels[channel].rate |= ( v & 0x0f ) << 8;\n\t\t\tbreak;\n\n\t\t\tcase 2: /* size low */\n\t\t\t\tic->channels[channel].size &= 0xff00;\n\t\t\t\tic->channels[channel].size |= v;\n\t\t\tbreak;\n\n\t\t\tcase 3: /* size high */\n\t\t\t\tic->channels[channel].size &= 0x00ff;\n\t\t\t\tic->channels[channel].size |= v << 8;\n\t\t\tbreak;\n\n\t\t\tcase 4: /* start low */\n\t\t\t\tic->channels[channel].start &= 0xff00;\n\t\t\t\tic->channels[channel].start |= v;\n\t\t\tbreak;\n\n\t\t\tcase 5: /* start high */\n\t\t\t\tic->channels[channel].start &= 0x00ff;\n\t\t\t\tic->channels[channel].start |= v << 8;\n\t\t\tbreak;\n\n\t\t\tcase 6: /* bank */\n\t\t\t\tic->channels[channel].bank = v & 0xff;\n\t\t\tbreak;\n\n\t\t\tcase 7: /* volume is 7 bits. Convert to 8 bits now. */\n\t\t\t\tic->channels[channel].volume = ( ( v & 0x7f ) << 1 ) | ( v & 1 );\n\t\t\tbreak;\n\t\t}\n\n\t\treturn;\n\t}\n\n\tswitch( r ) {\n\t\tcase 0x2a: /* loop, ppcm */\n\t\t\tfor ( i = 0; i < 4; i++ )\n\t\t\t\tic->channels[i].loop = ( v & ( 1 << i ) ) != 0;\n\n\t\t\tfor ( i = 4; i < 8; i++ )\n\t\t\t\tic->channels[i-4].ppcm = ( v & ( 1 << i ) ) != 0;\n\t\tbreak;\n\n\t\tcase 0x2c: /* pan */\n\t\t\tic->channels[0].pan = v & 7;\n\t\t\tic->channels[1].pan = ( v >> 3 ) & 7;\n\t\tbreak;\n\n\t\tcase 0x2d: /* more pan */\n\t\t\tic->channels[2].pan = v & 7;\n\t\t\tic->channels[3].pan = ( v >> 3 ) & 7;\n\t\tbreak;\n\n\t\tcase 0x2f: /* control */\n\t\t\tic->mode = v & 7;\n\t\t\t/* bit 0 = read ROM */\n\t\t\t/* bit 1 = enable sound output */\n\t\t\t/* bit 2 = unknown */\n\t\tbreak;\n\t}\n}\n\n//READ8_DEVICE_HANDLER( k053260_r )\nUINT8 k053260_r(UINT8 ChipID, offs_t offset)\n{\n\t//k053260_state *ic = get_safe_token(device);\n\tk053260_state *ic = &K053260Data[ChipID];\n\n\tswitch ( offset ) {\n\t\tcase 0x29: /* channel status */\n\t\t\t{\n\t\t\t\tint i, status = 0;\n\n\t\t\t\tfor ( i = 0; i < 4; i++ )\n\t\t\t\t\tstatus |= ic->channels[i].play << i;\n\n\t\t\t\treturn status;\n\t\t\t}\n\t\tbreak;\n\n\t\tcase 0x2e: /* read ROM */\n\t\t\tif ( ic->mode & 1 )\n\t\t\t{\n\t\t\t\tUINT32 offs = ic->channels[0].start + ( ic->channels[0].pos >> BASE_SHIFT ) + ( ic->channels[0].bank << 16 );\n\n\t\t\t\tic->channels[0].pos += ( 1 << 16 );\n\n\t\t\t\tif ( offs > ic->rom_size ) {\n\t\t\t\t\t//logerror(\"%s: K53260: Attempting to read past ROM size in ROM Read Mode (offs = %06x, size = %06x).\\n\", device->machine().describe_context(),offs,ic->rom_size );\n\t\t\t\t\tlogerror(\"K53260: Attempting to read past ROM size in ROM Read Mode (offs = %06x, size = %06x).\\n\", offs,ic->rom_size );\n\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\treturn ic->rom[offs];\n\t\t\t}\n\t\tbreak;\n\t}\n\n\treturn ic->regs[offset];\n}\n\nvoid k053260_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData)\n{\n\tk053260_state *info = &K053260Data[ChipID];\n\t\n\tif (info->rom_size != ROMSize)\n\t{\n\t\tinfo->rom = (UINT8*)realloc(info->rom, ROMSize);\n\t\tinfo->rom_size = ROMSize;\n\t\tmemset(info->rom, 0xFF, ROMSize);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(info->rom + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\n\nvoid k053260_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tk053260_state *info = &K053260Data[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 4; CurChn ++)\n\t\tinfo->channels[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( k053260 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers --- //\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(k053260_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions --- //\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( k053260 );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// nothing //\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( k053260 );\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings --- //\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"K053260\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\t\tstrcpy(info->s, \"Konami custom\");\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}\n\n\nDEFINE_LEGACY_SOUND_DEVICE(K053260, k053260);*/\n"
  },
  {
    "path": "VGMPlay/chips/k053260.h",
    "content": "/*********************************************************\n\n    Konami 053260 PCM/ADPCM Sound Chip\n\n*********************************************************/\n\n#pragma once\n\n//#include \"devlegcy.h\"\n\n/*typedef struct _k053260_interface k053260_interface;\nstruct _k053260_interface {\n\tconst char *rgnoverride;\n\ttimer_expired_func irq;\t\t\t// called on SH1 complete cycle ( clock / 32 ) //\n};*/\n\n\nvoid k053260_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_k053260(UINT8 ChipID, int clock);\nvoid device_stop_k053260(UINT8 ChipID);\nvoid device_reset_k053260(UINT8 ChipID);\n\n//WRITE8_DEVICE_HANDLER( k053260_w );\n//READ8_DEVICE_HANDLER( k053260_r );\nvoid k053260_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 k053260_r(UINT8 ChipID, offs_t offset);\n\nvoid k053260_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData);\nvoid k053260_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n//DECLARE_LEGACY_SOUND_DEVICE(K053260, k053260);\n"
  },
  {
    "path": "VGMPlay/chips/k054539.c",
    "content": "/*********************************************************\n\n    Konami 054539 (TOP) PCM Sound Chip\n\n    A lot of information comes from Amuse.\n    Big thanks to them.\n\n*********************************************************/\n\n//#include \"emu.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include <math.h>\n#include \"mamedef.h\"\n#ifdef _DEBUG\n#include <stdio.h>\n#endif\n#include \"k054539.h\"\n\n#define VERBOSE 0\n#define LOG(x) do { if (VERBOSE) logerror x; } while (0)\n\n/* Registers:\n   00..ff: 20 bytes/channel, 8 channels\n     00..02: pitch (lsb, mid, msb)\n         03: volume (0=max, 0x40=-36dB)\n         04: reverb volume (idem)\n     05: pan (1-f right, 10 middle, 11-1f left)\n     06..07: reverb delay (0=max, current computation non-trusted)\n     08..0a: loop (lsb, mid, msb)\n     0c..0e: start (lsb, mid, msb) (and current position ?)\n\n   100.1ff: effects?\n     13f: pan of the analog input (1-1f)\n\n   200..20f: 2 bytes/channel, 8 channels\n     00: type (b2-3), reverse (b5)\n     01: loop (b0)\n\n   214: Key on (b0-7 = channel 0-7)\n   215: Key off          \"\"\n   225: ?\n   227: Timer frequency\n   228: ?\n   229: ?\n   22a: ?\n   22b: ?\n   22c: Channel active? (b0-7 = channel 0-7)\n   22d: Data read/write port\n   22e: ROM/RAM select (00..7f == ROM banks, 80 = Reverb RAM)\n   22f: Global control:\n\t\t.......x - Enable PCM\n\t\t......x. - Timer related?\n\t\t...x.... - Enable ROM/RAM readback from 0x22d\n\t\t..x..... - Timer output enable?\n\t\tx....... - Disable register RAM updates\n\n\tThe chip has an optional 0x8000 byte reverb buffer.\n\tThe reverb delay is actually an offset in this buffer.\n*/\n\ntypedef struct _k054539_channel k054539_channel;\nstruct _k054539_channel {\n\tUINT32 pos;\n\tUINT32 pfrac;\n\tINT32 val;\n\tINT32 pval;\n};\n\ntypedef struct _k054539_state k054539_state;\nstruct _k054539_state {\n\t//const k054539_interface *intf;\n\t//device_t *device;\n\tdouble voltab[256];\n\tdouble pantab[0xf];\n\n\tdouble k054539_gain[8];\n\tUINT8 k054539_posreg_latch[8][3];\n\tint k054539_flags;\n\n\tunsigned char regs[0x230];\n\tunsigned char *ram;\n\tint reverb_pos;\n\n\tINT32 cur_ptr;\n\tint cur_limit;\n\tunsigned char *cur_zone;\n\tunsigned char *rom;\n\tUINT32 rom_size;\n\tUINT32 rom_mask;\n\t//sound_stream * stream;\n\n\tk054539_channel channels[8];\n\tUINT8 Muted[8];\n\t\n\tint clock;\n};\n\n#define MAX_CHIPS\t0x02\nstatic k054539_state K054539Data[MAX_CHIPS];\n\n/*INLINE k054539_state *get_safe_token(device_t *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == K054539);\n\treturn (k054539_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n//*\n\n//void k054539_init_flags(device_t *device, int flags)\nvoid k054539_init_flags(UINT8 ChipID, int flags)\n{\n\t//k054539_state *info = get_safe_token(device);\n\tk054539_state *info = &K054539Data[ChipID];\n\tinfo->k054539_flags = flags;\n}\n\n//void k054539_set_gain(device_t *device, int channel, double gain)\nvoid k054539_set_gain(UINT8 ChipID, int channel, double gain)\n{\n\t//k054539_state *info = get_safe_token(device);\n\tk054539_state *info = &K054539Data[ChipID];\n\tif (gain >= 0) info->k054539_gain[channel] = gain;\n}\n//*\n\nstatic int k054539_regupdate(k054539_state *info)\n{\n\treturn !(info->regs[0x22f] & 0x80);\n}\n\nstatic void k054539_keyon(k054539_state *info, int channel)\n{\n\tif(k054539_regupdate(info))\n\t\tinfo->regs[0x22c] |= 1 << channel;\n}\n\nstatic void k054539_keyoff(k054539_state *info, int channel)\n{\n\tif(k054539_regupdate(info))\n\t\tinfo->regs[0x22c] &= ~(1 << channel);\n}\n\n//static STREAM_UPDATE( k054539_update )\nvoid k054539_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//k054539_state *info = (k054539_state *)param;\n\tk054539_state *info = &K054539Data[ChipID];\n#define VOL_CAP 1.80\n\n\tstatic const INT16 dpcm[16] = {\n\t\t0<<8, 1<<8, 4<<8, 9<<8, 16<<8, 25<<8, 36<<8, 49<<8,\n\t\t-64<<8, -49<<8, -36<<8, -25<<8, -16<<8, -9<<8, -4<<8, -1<<8\n\t};\n\n\tINT16 *rbase = (INT16 *)info->ram;\n\tunsigned char *rom;\n\tUINT32 rom_mask;\n\tint i, ch;\n\tdouble lval, rval;\n\tunsigned char *base1, *base2;\n\tk054539_channel *chan;\n\tint delta, vol, bval, pan;\n\tdouble cur_gain, lvol, rvol, rbvol;\n\tint rdelta;\n\tUINT32 cur_pos;\n\tint fdelta, pdelta;\n\tint cur_pfrac, cur_val, cur_pval;\n\n\tmemset(outputs[0], 0, samples*sizeof(*outputs[0]));\n\tmemset(outputs[1], 0, samples*sizeof(*outputs[1]));\n\n\tif(!(info->regs[0x22f] & 1))\n\t\treturn;\n\n\trom = info->rom;\n\trom_mask = info->rom_mask;\n\n\tfor(i = 0; i != samples; i++) {\n\t\tif(!(info->k054539_flags & K054539_DISABLE_REVERB))\n\t\t\tlval = rval = rbase[info->reverb_pos];\n\t\telse\n\t\t\tlval = rval = 0;\n\t\trbase[info->reverb_pos] = 0;\n\n\t\tfor(ch=0; ch<8; ch++)\n\t\t\tif(info->regs[0x22c] & (1<<ch) && ! info->Muted[ch]) {\n\t\t\t\tbase1 = info->regs + 0x20*ch;\n\t\t\t\tbase2 = info->regs + 0x200 + 0x2*ch;\n\t\t\t\tchan = info->channels + ch;\n\n\t\t\t\tdelta = base1[0x00] | (base1[0x01] << 8) | (base1[0x02] << 16);\n\n\t\t\t\tvol = base1[0x03];\n\n\t\t\t\tbval = vol + base1[0x04];\n\t\t\t\tif (bval > 255)\n\t\t\t\t\tbval = 255;\n\n\t\t\t\tpan = base1[0x05];\n\t\t\t\t// DJ Main: 81-87 right, 88 middle, 89-8f left\n\t\t\t\tif (pan >= 0x81 && pan <= 0x8f)\n\t\t\t\t\tpan -= 0x81;\n\t\t\t\telse if (pan >= 0x11 && pan <= 0x1f)\n\t\t\t\t\tpan -= 0x11;\n\t\t\t\telse\n\t\t\t\t\tpan = 0x18 - 0x11;\n\n\t\t\t\tcur_gain = info->k054539_gain[ch];\n\n\t\t\t\tlvol = info->voltab[vol] * info->pantab[pan] * cur_gain;\n\t\t\t\tif (lvol > VOL_CAP)\n\t\t\t\t\tlvol = VOL_CAP;\n\n\t\t\t\trvol = info->voltab[vol] * info->pantab[0xe - pan] * cur_gain;\n\t\t\t\tif (rvol > VOL_CAP)\n\t\t\t\t\trvol = VOL_CAP;\n\n\t\t\t\trbvol= info->voltab[bval] * cur_gain / 2;\n\t\t\t\tif (rbvol > VOL_CAP)\n\t\t\t\t\trbvol = VOL_CAP;\n\n\t\t\t\trdelta = (base1[6] | (base1[7] << 8)) >> 3;\n\t\t\t\trdelta = (rdelta + info->reverb_pos) & 0x3fff;\n\n\t\t\t\tcur_pos = base1[0x0c] | (base1[0x0d] << 8) | (base1[0x0e] << 16);\n\n\t\t\t\tif(base2[0] & 0x20) {\n\t\t\t\t\tdelta = -delta;\n\t\t\t\t\tfdelta = +0x10000;\n\t\t\t\t\tpdelta = -1;\n\t\t\t\t} else {\n\t\t\t\t\tfdelta = -0x10000;\n\t\t\t\t\tpdelta = +1;\n\t\t\t\t}\n\n\t\t\t\tif(cur_pos != chan->pos) {\n\t\t\t\t\tchan->pos = cur_pos;\n\t\t\t\t\tcur_pfrac = 0;\n\t\t\t\t\tcur_val = 0;\n\t\t\t\t\tcur_pval = 0;\n\t\t\t\t} else {\n\t\t\t\t\tcur_pfrac = chan->pfrac;\n\t\t\t\t\tcur_val = chan->val;\n\t\t\t\t\tcur_pval = chan->pval;\n\t\t\t\t}\n\n\t\t\t\tswitch(base2[0] & 0xc) {\n\t\t\t\tcase 0x0: { // 8bit pcm\n\t\t\t\t\tcur_pfrac += delta;\n\t\t\t\t\twhile(cur_pfrac & ~0xffff) {\n\t\t\t\t\t\tcur_pfrac += fdelta;\n\t\t\t\t\t\tcur_pos += pdelta;\n\n\t\t\t\t\t\tcur_pval = cur_val;\n\t\t\t\t\t\tcur_val = (INT16)(rom[cur_pos & rom_mask] << 8);\n\t\t\t\t\t\tif(cur_val == (INT16)0x8000 && (base2[1] & 1)) {\n\t\t\t\t\t\t\tcur_pos = base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16);\n\t\t\t\t\t\t\tcur_val = (INT16)(rom[cur_pos & rom_mask] << 8);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(cur_val == (INT16)0x8000) {\n\t\t\t\t\t\t\tk054539_keyoff(info, ch);\n\t\t\t\t\t\t\tcur_val = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase 0x4: { // 16bit pcm lsb first\n\t\t\t\t\tpdelta <<= 1;\n\n\t\t\t\t\tcur_pfrac += delta;\n\t\t\t\t\twhile(cur_pfrac & ~0xffff) {\n\t\t\t\t\t\tcur_pfrac += fdelta;\n\t\t\t\t\t\tcur_pos += pdelta;\n\n\t\t\t\t\t\tcur_pval = cur_val;\n\t\t\t\t\t\tcur_val = (INT16)(rom[cur_pos & rom_mask] | rom[(cur_pos+1) & rom_mask]<<8);\n\t\t\t\t\t\tif(cur_val == (INT16)0x8000 && (base2[1] & 1)) {\n\t\t\t\t\t\t\tcur_pos = base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16);\n\t\t\t\t\t\t\tcur_val = (INT16)(rom[cur_pos & rom_mask] | rom[(cur_pos+1) & rom_mask]<<8);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(cur_val == (INT16)0x8000) {\n\t\t\t\t\t\t\tk054539_keyoff(info, ch);\n\t\t\t\t\t\t\tcur_val = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase 0x8: { // 4bit dpcm\n\t\t\t\t\tcur_pos <<= 1;\n\t\t\t\t\tcur_pfrac <<= 1;\n\t\t\t\t\tif(cur_pfrac & 0x10000) {\n\t\t\t\t\t\tcur_pfrac &= 0xffff;\n\t\t\t\t\t\tcur_pos |= 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tcur_pfrac += delta;\n\t\t\t\t\twhile(cur_pfrac & ~0xffff) {\n\t\t\t\t\t\tcur_pfrac += fdelta;\n\t\t\t\t\t\tcur_pos += pdelta;\n\n\t\t\t\t\t\tcur_pval = cur_val;\n\t\t\t\t\t\tcur_val = rom[(cur_pos>>1) & rom_mask];\n\t\t\t\t\t\tif(cur_val == 0x88 && (base2[1] & 1)) {\n\t\t\t\t\t\t\tcur_pos = (base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) << 1;\n\t\t\t\t\t\t\tcur_val = rom[(cur_pos>>1) & rom_mask];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(cur_val == 0x88) {\n\t\t\t\t\t\t\tk054539_keyoff(info, ch);\n\t\t\t\t\t\t\tcur_val = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(cur_pos & 1)\n\t\t\t\t\t\t\tcur_val >>= 4;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcur_val &= 15;\n\t\t\t\t\t\tcur_val = cur_pval + dpcm[cur_val];\n\t\t\t\t\t\tif(cur_val < -32768)\n\t\t\t\t\t\t\tcur_val = -32768;\n\t\t\t\t\t\telse if(cur_val > 32767)\n\t\t\t\t\t\t\tcur_val = 32767;\n\t\t\t\t\t}\n\n\t\t\t\t\tcur_pfrac >>= 1;\n\t\t\t\t\tif(cur_pos & 1)\n\t\t\t\t\t\tcur_pfrac |= 0x8000;\n\t\t\t\t\tcur_pos >>= 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tLOG((\"Unknown sample type %x for channel %d\\n\", base2[0] & 0xc, ch));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tlval += cur_val * lvol;\n\t\t\t\trval += cur_val * rvol;\n\t\t\t\trbase[(rdelta + info->reverb_pos) & 0x1fff] += (INT16)(cur_val*rbvol);\n\n\t\t\t\tchan->pos = cur_pos;\n\t\t\t\tchan->pfrac = cur_pfrac;\n\t\t\t\tchan->pval = cur_pval;\n\t\t\t\tchan->val = cur_val;\n\n\t\t\t\tif(k054539_regupdate(info)) {\n\t\t\t\t\tbase1[0x0c] = cur_pos     & 0xff;\n\t\t\t\t\tbase1[0x0d] = cur_pos>> 8 & 0xff;\n\t\t\t\t\tbase1[0x0e] = cur_pos>>16 & 0xff;\n\t\t\t\t}\n\t\t\t}\n\t\tinfo->reverb_pos = (info->reverb_pos + 1) & 0x1fff;\n\t\toutputs[0][i] = (INT32)lval;\n\t\toutputs[1][i] = (INT32)rval;\n\t}\n}\n\n\n/*static TIMER_CALLBACK( k054539_irq )\n{\n\tk054539_state *info = (k054539_state *)ptr;\n\tif(info->regs[0x22f] & 0x20)\n\t\tinfo->intf->irq(info->device);\n}*/\n\n//static void k054539_init_chip(device_t *device, k054539_state *info)\nstatic int k054539_init_chip(k054539_state *info, int clock)\n{\n\t//int i;\n\n\tif (clock < 1000000)\t// if < 1 MHz, then it's the sample rate, not the clock\n\t\tclock *= 384;\t// (for backwards compatibility with old VGM logs)\n\tinfo->clock = clock;\n\t// most of these are done in device_reset\n//\tmemset(info->regs, 0, sizeof(info->regs));\n//\tmemset(info->k054539_posreg_latch, 0, sizeof(info->k054539_posreg_latch)); //*\n\tinfo->k054539_flags |= K054539_UPDATE_AT_KEYON; //* make it default until proven otherwise\n\n\tinfo->ram = (unsigned char*)malloc(0x4000);\n//\tinfo->reverb_pos = 0;\n//\tinfo->cur_ptr = 0;\n//\tmemset(info->ram, 0, 0x4000);\n\n\t/*const memory_region *region = (info->intf->rgnoverride != NULL) ? device->machine().region(info->intf->rgnoverride) : device->region();\n\tinfo->rom = *region;\n\tinfo->rom_size = region->bytes();\n\tinfo->rom_mask = 0xffffffffU;\n\tfor(i=0; i<32; i++)\n\t\tif((1U<<i) >= info->rom_size) {\n\t\t\tinfo->rom_mask = (1U<<i) - 1;\n\t\t\tbreak;\n\t\t}*/\n\tinfo->rom = NULL;\n\tinfo->rom_size = 0;\n\tinfo->rom_mask = 0x00;\n\n\t//if(info->intf->irq)\n\t\t// One or more of the registers must be the timer period\n\t\t// And anyway, this particular frequency is probably wrong\n\t\t// 480 hz is TRUSTED by gokuparo disco stage - the looping sample doesn't line up otherwise\n\t//\tdevice->machine().scheduler().timer_pulse(attotime::from_hz(480), FUNC(k054539_irq), 0, info);\n\n\t//info->stream = device->machine().sound().stream_alloc(*device, 0, 2, device->clock() / 384, info, k054539_update);\n\n\t//device->save_item(NAME(info->regs));\n\t//device->save_pointer(NAME(info->ram), 0x4000);\n\t//device->save_item(NAME(info->cur_ptr));\n\t\n\treturn info->clock / 384;\n}\n\n//WRITE8_DEVICE_HANDLER( k054539_w )\nvoid k054539_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//k054539_state *info = get_safe_token(device);\n\tk054539_state *info = &K054539Data[ChipID];\n\n#if 0\n\tint voice, reg;\n\n\t/* The K054539 has behavior like many other wavetable chips including\n       the Ensoniq 550x and Gravis GF-1: if a voice is active, writing\n       to it's current position is silently ignored.\n\n       Dadandaan depends on this or the vocals go wrong.\n       */\n\tif (offset < 8*0x20)\n\t{\n\t\tvoice = offset / 0x20;\n\t\treg = offset & ~0x20;\n\n\t\tif(info->regs[0x22c] & (1<<voice))\n\t\t{\n\t\t\tif (reg >= 0xc && reg <= 0xe)\n\t\t\t\treturn;\n\t\t}\n\t}\n#endif\n\n\tint latch, offs, ch, pan;\n\tUINT8 *regbase, *regptr, *posptr;\n\n\tregbase = info->regs;\n\tlatch = (info->k054539_flags & K054539_UPDATE_AT_KEYON) && (regbase[0x22f] & 1);\n\n\tif (latch && offset < 0x100)\n\t{\n\t\toffs = (offset & 0x1f) - 0xc;\n\t\tch = offset >> 5;\n\n\t\tif (offs >= 0 && offs <= 2)\n\t\t{\n\t\t\t// latch writes to the position index registers\n\t\t\tinfo->k054539_posreg_latch[ch][offs] = data;\n\t\t\treturn;\n\t\t}\n\t}\n\n\telse switch(offset)\n\t{\n\t\tcase 0x13f:\n\t\t\tpan = data >= 0x11 && data <= 0x1f ? data - 0x11 : 0x18 - 0x11;\n\t\t\t//if(info->intf->apan)\n\t\t\t//\tinfo->intf->apan(info->device, info->pantab[pan], info->pantab[0xe - pan]);\n\t\tbreak;\n\n\t\tcase 0x214:\n\t\t\tif (latch)\n\t\t\t{\n\t\t\t\tfor(ch=0; ch<8; ch++)\n\t\t\t\t{\n\t\t\t\t\tif(data & (1<<ch))\n\t\t\t\t\t{\n\t\t\t\t\t\tposptr = &info->k054539_posreg_latch[ch][0];\n\t\t\t\t\t\tregptr = regbase + (ch<<5) + 0xc;\n\n\t\t\t\t\t\t// update the chip at key-on\n\t\t\t\t\t\tregptr[0] = posptr[0];\n\t\t\t\t\t\tregptr[1] = posptr[1];\n\t\t\t\t\t\tregptr[2] = posptr[2];\n\n\t\t\t\t\t\tk054539_keyon(info, ch);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor(ch=0; ch<8; ch++)\n\t\t\t\t\tif(data & (1<<ch))\n\t\t\t\t\t\tk054539_keyon(info, ch);\n\t\t\t}\n\t\tbreak;\n\n\t\tcase 0x215:\n\t\t\tfor(ch=0; ch<8; ch++)\n\t\t\t\tif(data & (1<<ch))\n\t\t\t\t\tk054539_keyoff(info, ch);\n\t\tbreak;\n\n\t\t/*case 0x227:\n\t\t{\n\t\t\tattotime period = attotime::from_hz((float)(38 + data) * (clock()/384.0f/14400.0f)) / 2.0f;\n\n\t\t\tm_timer->adjust(period, 0, period);\n\n\t\t\tm_timer_state = 0;\n\t\t\tm_timer_handler(m_timer_state);\n\t\t}*/\n\t\tbreak;\n\n\t\tcase 0x22d:\n\t\t\tif(regbase[0x22e] == 0x80)\n\t\t\t\tinfo->cur_zone[info->cur_ptr] = data;\n\t\t\tinfo->cur_ptr++;\n\t\t\tif(info->cur_ptr == info->cur_limit)\n\t\t\t\tinfo->cur_ptr = 0;\n\t\tbreak;\n\n\t\tcase 0x22e:\n\t\t\tinfo->cur_zone =\n\t\t\t\tdata == 0x80 ? info->ram :\n\t\t\t\tinfo->rom + 0x20000*data;\n\t\t\tinfo->cur_limit = data == 0x80 ? 0x4000 : 0x20000;\n\t\t\tinfo->cur_ptr = 0;\n\t\tbreak;\n\t\t\n\t\t/*case 0x22f:\n\t\t\tif (!(data & 0x20)) // Disable timer output?\n\t\t\t{\n\t\t\t\tm_timer_state = 0;\n\t\t\t\tm_timer_handler(m_timer_state);\n\t\t\t}\n\t\tbreak;*/\n\n\t\tdefault:\n#if 0\n\t\t\tif(regbase[offset] != data) {\n\t\t\t\tif((offset & 0xff00) == 0) {\n\t\t\t\t\tchanoff = offset & 0x1f;\n\t\t\t\t\tif(chanoff < 4 || chanoff == 5 ||\n\t\t\t\t\t   (chanoff >=8 && chanoff <= 0xa) ||\n\t\t\t\t\t   (chanoff >= 0xc && chanoff <= 0xe))\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif(1 || ((offset >= 0x200) && (offset <= 0x210)))\n\t\t\t\t\tbreak;\n\t\t\t\tlogerror(\"K054539 %03x = %02x\\n\", offset, data);\n\t\t\t}\n#endif\n\t\tbreak;\n\t}\n\n\tregbase[offset] = data;\n}\n\nstatic void reset_zones(k054539_state *info)\n{\n\tint data = info->regs[0x22e];\n\tinfo->cur_zone = data == 0x80 ? info->ram : info->rom + 0x20000*data;\n\tinfo->cur_limit = data == 0x80 ? 0x4000 : 0x20000;\n}\n\n//READ8_DEVICE_HANDLER( k054539_r )\nUINT8 k054539_r(UINT8 ChipID, offs_t offset)\n{\n\t//k054539_state *info = get_safe_token(device);\n\tk054539_state *info = &K054539Data[ChipID];\n\tswitch(offset) {\n\tcase 0x22d:\n\t\tif(info->regs[0x22f] & 0x10) {\n\t\t\tUINT8 res = info->cur_zone[info->cur_ptr];\n\t\t\tinfo->cur_ptr++;\n\t\t\tif(info->cur_ptr == info->cur_limit)\n\t\t\t\tinfo->cur_ptr = 0;\n\t\t\treturn res;\n\t\t} else\n\t\t\treturn 0;\n\tcase 0x22c:\n\t\tbreak;\n\tdefault:\n\t\tLOG((\"K054539 read %03x\\n\", offset));\n\t\tbreak;\n\t}\n\treturn info->regs[offset];\n}\n\n//static DEVICE_START( k054539 )\nint device_start_k054539(UINT8 ChipID, int clock)\n{\n\t//static const k054539_interface defintrf = { 0 };\n\tint i;\n\t//k054539_state *info = get_safe_token(device);\n\tk054539_state *info;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &K054539Data[ChipID];\n\t//info->device = device;\n\n\tfor (i = 0; i < 8; i++)\n\t\tinfo->k054539_gain[i] = 1.0;\n\tinfo->k054539_flags = K054539_RESET_FLAGS;\n\n\t//info->intf = (device->static_config() != NULL) ? (const k054539_interface *)device->static_config() : &defintrf;\n\n\t/*\n        I've tried various equations on volume control but none worked consistently.\n        The upper four channels in most MW/GX games simply need a significant boost\n        to sound right. For example, the bass and smash sound volumes in Violent Storm\n        have roughly the same values and the voices in Tokimeki Puzzledama are given\n        values smaller than those of the hihats. Needless to say the two K054539 chips\n        in Mystic Warriors are completely out of balance. Rather than forcing a\n        \"one size fits all\" function to the voltab the current invert exponential\n        appraoch seems most appropriate.\n    */\n\t// Factor the 1/4 for the number of channels in the volume (1/8 is too harsh, 1/2 gives clipping)\n\t// vol=0 -> no attenuation, vol=0x40 -> -36dB\n\tfor(i=0; i<256; i++)\n\t\tinfo->voltab[i] = pow(10.0, (-36.0 * (double)i / (double)0x40) / 20.0) / 4.0;\n\n\t// Pan table for the left channel\n\t// Right channel is identical with inverted index\n\t// Formula is such that pan[i]**2+pan[0xe-i]**2 = 1 (constant output power)\n\t// and pan[0xe] = 1 (full panning)\n\tfor(i=0; i<0xf; i++)\n\t\tinfo->pantab[i] = sqrt((double)i) / sqrt((double)0xe);\n\n\t//k054539_init_chip(device, info);\n\n\t//device->machine().save().register_postload(save_prepost_delegate(FUNC(reset_zones), info));\n\t\n\tfor (i = 0; i < 8; i ++)\n\t\tinfo->Muted[i] = 0x00;\n\t\n\treturn k054539_init_chip(info, clock);\n}\n\nvoid device_stop_k054539(UINT8 ChipID)\n{\n\tk054539_state *info = &K054539Data[ChipID];\n\t\n\tfree(info->rom);\tinfo->rom = NULL;\n\tfree(info->ram);\tinfo->ram = NULL;\n\t\n\treturn;\n}\n\nvoid device_reset_k054539(UINT8 ChipID)\n{\n\tk054539_state *info = &K054539Data[ChipID];\n\t\n\tmemset(info->regs, 0, sizeof(info->regs));\n\tmemset(info->k054539_posreg_latch, 0, sizeof(info->k054539_posreg_latch));\n\t//info->k054539_flags |= K054539_UPDATE_AT_KEYON;\n\t\n\tinfo->reverb_pos = 0;\n\tinfo->cur_ptr = 0;\n\tmemset(info->ram, 0, 0x4000);\n\t\n\treturn;\n}\n\nvoid k054539_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData)\n{\n\tk054539_state *info = &K054539Data[ChipID];\n\t\n\tif (info->rom_size != ROMSize)\n\t{\n\t\tUINT8 i;\n\t\t\n\t\tinfo->rom = (UINT8*)realloc(info->rom, ROMSize);\n\t\tinfo->rom_size = ROMSize;\n\t\tmemset(info->rom, 0xFF, ROMSize);\n\t\t\n\t\tinfo->rom_mask = 0xFFFFFFFF;\n\t\tfor (i = 0; i < 32; i ++)\n\t\t{\n\t\t\tif ((1U << i) >= info->rom_size)\n\t\t\t{\n\t\t\t\tinfo->rom_mask = (1 << i) - 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(info->rom + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\n\nvoid k054539_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tk054539_state *info = &K054539Data[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 8; CurChn ++)\n\t\tinfo->Muted[CurChn] = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( k054539 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers --- //\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(k054539_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions --- //\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( k054539 );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// nothing //\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// nothing //\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings --- //\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"K054539\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Konami custom\");\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n\n\n//DEFINE_LEGACY_SOUND_DEVICE(K054539, k054539);\n"
  },
  {
    "path": "VGMPlay/chips/k054539.h",
    "content": "/*********************************************************\n\n    Konami 054539 PCM Sound Chip\n\n*********************************************************/\n\n#pragma once\n\n//#include \"devlegcy.h\"\n\n/*typedef struct _k054539_interface k054539_interface;\nstruct _k054539_interface\n{\n\tconst char *rgnoverride;\n\tvoid (*apan)(device_t *, double, double);\t// Callback for analog output mixing levels (0..1 for each channel)\n\tvoid (*irq)(device_t *);\n};*/\n\n\nvoid k054539_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_k054539(UINT8 ChipID, int clock);\nvoid device_stop_k054539(UINT8 ChipID);\nvoid device_reset_k054539(UINT8 ChipID);\n\n\n//WRITE8_DEVICE_HANDLER( k054539_w );\n//READ8_DEVICE_HANDLER( k054539_r );\nvoid k054539_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 k054539_r(UINT8 ChipID, offs_t offset);\n\n//* control flags, may be set at DRIVER_INIT().\n#define K054539_RESET_FLAGS     0\n#define K054539_REVERSE_STEREO  1\n#define K054539_DISABLE_REVERB  2\n#define K054539_UPDATE_AT_KEYON 4\n\n//void k054539_init_flags(device_t *device, int flags);\nvoid k054539_init_flags(UINT8 ChipID, int flags);\n\n/*\n    Note that the eight PCM channels of a K054539 do not have separate\n    volume controls. Considering the global attenuation equation may not\n    be entirely accurate, k054539_set_gain() provides means to control\n    channel gain. It can be called anywhere but preferrably from\n    DRIVER_INIT().\n\n    Parameters:\n        chip    : 0 / 1\n        channel : 0 - 7\n        gain    : 0.0=silent, 1.0=no gain, 2.0=twice as loud, etc.\n*/\n//void k054539_set_gain(device_t *device, int channel, double gain);\nvoid k054539_set_gain(UINT8 ChipID, int channel, double gain);\n\n\nvoid k054539_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData);\nvoid k054539_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n\n//DECLARE_LEGACY_SOUND_DEVICE(K054539, k054539);\n"
  },
  {
    "path": "VGMPlay/chips/mamedef.h",
    "content": "#ifndef __MAMEDEF_H__\n#define __MAMEDEF_H__\n\n// typedefs to use MAME's (U)INTxx types (copied from MAME\\src\\ods\\odscomm.h)\n/* 8-bit values */\ntypedef unsigned char\t\t\t\t\t\tUINT8;\ntypedef signed char \t\t\t\t\t\tINT8;\n\n/* 16-bit values */\ntypedef unsigned short\t\t\t\t\t\tUINT16;\ntypedef signed short\t\t\t\t\t\tINT16;\n\n/* 32-bit values */\n#ifndef _WINDOWS_H\ntypedef unsigned int\t\t\t\t\t\tUINT32;\ntypedef signed int\t\t\t\t\t\t\tINT32;\n#endif\n\n/* 64-bit values */\n#ifndef _WINDOWS_H\n#ifdef _MSC_VER\ntypedef signed __int64\t\t\t\t\t\tINT64;\ntypedef unsigned __int64\t\t\t\t\tUINT64;\n#else\n__extension__ typedef unsigned long long\tUINT64;\n__extension__ typedef signed long long\t\tINT64;\n#endif\n#endif\n\n/* offsets and addresses are 32-bit (for now...) */\ntypedef UINT32\toffs_t;\n\n/* stream_sample_t is used to represent a single sample in a sound stream */\ntypedef INT32 stream_sample_t;\n\n#if defined(VGM_BIG_ENDIAN)\n#define BYTE_XOR_BE(x)\t (x)\n#elif defined(VGM_LITTLE_ENDIAN)\n#define BYTE_XOR_BE(x)\t((x) ^ 0x01)\n#else\n// don't define BYTE_XOR_BE so that it throws an error when compiling\n#endif\n\n#if defined(_MSC_VER)\n//#define INLINE\tstatic __forceinline\n#define INLINE\tstatic __inline\n#elif defined(__GNUC__)\n#define INLINE\tstatic __inline__\n#else\n#define INLINE\tstatic inline\n#endif\n#ifndef M_PI\n#define M_PI\t3.14159265358979323846\n#endif\n\n#ifdef _DEBUG\n#define logerror\tprintf\n#else\n#define logerror\n#endif\n\nextern stream_sample_t* DUMMYBUF[];\n\ntypedef void (*SRATE_CALLBACK)(void*, UINT32);\n\n#endif\t// __MAMEDEF_H__\n"
  },
  {
    "path": "VGMPlay/chips/multipcm.c",
    "content": "/*\n * Sega System 32 Multi/Model 1/Model 2 custom PCM chip (315-5560) emulation.\n *\n * by Miguel Angel Horna (ElSemi) for Model 2 Emulator and MAME.\n * Information by R.Belmont and the YMF278B (OPL4) manual.\n *\n * voice registers:\n * 0: Pan\n * 1: Index of sample\n * 2: LSB of pitch (low 2 bits seem unused so)\n * 3: MSB of pitch (ooooppppppppppxx) (o=octave (4 bit signed), p=pitch (10 bits), x=unused?\n * 4: voice control: top bit = 1 for key on, 0 for key off\n * 5: bit 0: 0: interpolate volume changes, 1: direct set volume,\n      bits 1-7 = volume attenuate (0=max, 7f=min)\n * 6: LFO frequency + Phase LFO depth\n * 7: Amplitude LFO size\n *\n * The first sample ROM contains a variable length table with 12\n * bytes per instrument/sample. This is very similar to the YMF278B.\n *\n * The first 3 bytes are the offset into the file (big endian).\n * The next 2 are the loop start offset into the file (big endian)\n * The next 2 are the 2's complement of the total sample size (big endian)\n * The next byte is LFO freq + depth (copied to reg 6 ?)\n * The next 3 are envelope params (Attack, Decay1 and 2, sustain level, release, Key Rate Scaling)\n * The next byte is Amplitude LFO size (copied to reg 7 ?)\n *\n * TODO\n * - The YM278B manual states that the chip supports 512 instruments. The MultiPCM probably supports them\n * too but the high bit position is unknown (probably reg 2 low bit). Any game use more than 256?\n *\n */\n\n//#include \"emu.h\"\n//#include \"streams.h\"\n#include \"mamedef.h\"\n#include <math.h>\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"multipcm.h\"\n\n//????\n#define MULTIPCM_CLOCKDIV   \t(180.0)\n//#define SHOW_WARNINGS\nstatic UINT8 didWarn = 0x00;\n\nstruct _Sample\n{\n\tunsigned int Start;\n\tunsigned int Loop;\n\tunsigned int End;\n\tunsigned char AR,DR1,DR2,DL,RR;\n\tunsigned char KRS;\n\tunsigned char LFOVIB;\n\tunsigned char AM;\n};\n\ntypedef enum {ATTACK,DECAY1,DECAY2,RELEASE} _STATE;\nstruct _EG\n{\n\tint volume;\t//\n\t_STATE state;\n\tint step;\n\t//step vals\n\tint AR;\t\t//Attack\n\tint D1R;\t//Decay1\n\tint D2R;\t//Decay2\n\tint RR;\t\t//Release\n\tint DL;\t\t//Decay level\n};\n\nstruct _LFO\n{\n\tunsigned short phase;\n\tUINT32 phase_step;\n\tint *table;\n\tint *scale;\n};\n\n\nstruct _SLOT\n{\n\tunsigned char Num;\n\tunsigned char Regs[8];\n\tint Playing;\n\tstruct _Sample *Sample;\n\tunsigned int Base;\n\tunsigned int offset;\n\tunsigned int step;\n\tunsigned int Pan,TL;\n\tunsigned int DstTL;\n\tint TLStep;\n\tsigned int Prev;\n\tstruct _EG EG;\n\tstruct _LFO PLFO;\t//Phase lfo\n\tstruct _LFO ALFO;\t//AM lfo\n\t\n\tUINT8 Muted;\n};\n\ntypedef struct _MultiPCM MultiPCM;\nstruct _MultiPCM\n{\n\t//sound_stream * stream;\n\tstruct _Sample Samples[0x200];\t\t//Max 512 samples\n\tstruct _SLOT Slots[28];\n\tunsigned int CurSlot;\n\tunsigned int Address;\n\tunsigned int Bank;\n\tunsigned int BankR,BankL;\n\tfloat Rate;\n\tUINT32 ROMMask;\n\tUINT32 ROMSize;\n\tINT8 *ROM;\n\t//I include these in the chip because they depend on the chip clock\n\tunsigned int ARStep[0x40],DRStep[0x40];\t//Envelope step table\n\tunsigned int FNS_Table[0x400];\t\t//Frequency step table\n};\n\n\nstatic UINT8 IsInit = 0x00;\nstatic signed int LPANTABLE[0x800],RPANTABLE[0x800];\n\n#define FIX(v)\t((UINT32) ((float) (1<<SHIFT)*(v)))\n\nstatic const int val2chan[] =\n{\n\t0, 1, 2, 3, 4, 5, 6 , -1,\n\t7, 8, 9, 10,11,12,13, -1,\n\t14,15,16,17,18,19,20, -1,\n\t21,22,23,24,25,26,27, -1,\n};\n\n\n#define SHIFT\t\t12\n\n\n#define MULTIPCM_RATE\t44100.0\n\n\n#define MAX_CHIPS\t0x02\nstatic MultiPCM MultiPCMData[MAX_CHIPS];\n\n/*INLINE MultiPCM *get_safe_token(running_device *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == MULTIPCM);\n\treturn (MultiPCM *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n\n/*******************************\n        ENVELOPE SECTION\n*******************************/\n\n//Times are based on a 44100Hz timebase. It's adjusted to the actual sampling rate on startup\n\nstatic const double BaseTimes[64]={0,0,0,0,6222.95,4978.37,4148.66,3556.01,3111.47,2489.21,2074.33,1778.00,1555.74,1244.63,1037.19,889.02,\n777.87,622.31,518.59,444.54,388.93,311.16,259.32,222.27,194.47,155.60,129.66,111.16,97.23,77.82,64.85,55.60,\n48.62,38.91,32.43,27.80,24.31,19.46,16.24,13.92,12.15,9.75,8.12,6.98,6.08,4.90,4.08,3.49,\n3.04,2.49,2.13,1.90,1.72,1.41,1.18,1.04,0.91,0.73,0.59,0.50,0.45,0.45,0.45,0.45};\n#define AR2DR\t14.32833\nstatic signed int lin2expvol[0x400];\nstatic int TLSteps[2];\n\n#define EG_SHIFT\t16\n\nstatic int EG_Update(struct _SLOT *slot)\n{\n\tswitch(slot->EG.state)\n\t{\n\t\tcase ATTACK:\n\t\t\tslot->EG.volume+=slot->EG.AR;\n\t\t\tif(slot->EG.volume>=(0x3ff<<EG_SHIFT))\n\t\t\t{\n\t\t\t\tslot->EG.state=DECAY1;\n\t\t\t\tif(slot->EG.D1R>=(0x400<<EG_SHIFT)) //Skip DECAY1, go directly to DECAY2\n\t\t\t\t\tslot->EG.state=DECAY2;\n\t\t\t\tslot->EG.volume=0x3ff<<EG_SHIFT;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase DECAY1:\n\t\t\tslot->EG.volume-=slot->EG.D1R;\n\t\t\tif(slot->EG.volume<=0)\n\t\t\t\tslot->EG.volume=0;\n\t\t\tif(slot->EG.volume>>EG_SHIFT<=(slot->EG.DL<<(10-4)))\n\t\t\t\tslot->EG.state=DECAY2;\n\t\t\tbreak;\n\t\tcase DECAY2:\n\t\t\tslot->EG.volume-=slot->EG.D2R;\n\t\t\tif(slot->EG.volume<=0)\n\t\t\t\tslot->EG.volume=0;\n\t\t\tbreak;\n\t\tcase RELEASE:\n\t\t\tslot->EG.volume-=slot->EG.RR;\n\t\t\tif(slot->EG.volume<=0)\n\t\t\t{\n\t\t\t\tslot->EG.volume=0;\n\t\t\t\tslot->Playing=0;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn 1<<SHIFT;\n\t}\n\treturn lin2expvol[slot->EG.volume>>EG_SHIFT];\n}\n\nstatic unsigned int Get_RATE(unsigned int *Steps,unsigned int rate,unsigned int val)\n{\n\tint r=4*val+rate;\n\tif(val==0)\n\t\treturn Steps[0];\n\tif(val==0xf)\n\t\treturn Steps[0x3f];\n\tif(r>0x3f)\n\t\tr=0x3f;\n\treturn Steps[r];\n}\n\nstatic void EG_Calc(MultiPCM *ptChip,struct _SLOT *slot)\n{\n\tint octave=((slot->Regs[3]>>4)-1)&0xf;\n\tint rate;\n\tif(octave&8) octave=octave-16;\n\tif(slot->Sample->KRS!=0xf)\n\t\trate=(octave+slot->Sample->KRS)*2+((slot->Regs[3]>>3)&1);\n\telse\n\t\trate=0;\n\n\tslot->EG.AR=Get_RATE(ptChip->ARStep,rate,slot->Sample->AR);\n\tslot->EG.D1R=Get_RATE(ptChip->DRStep,rate,slot->Sample->DR1);\n\tslot->EG.D2R=Get_RATE(ptChip->DRStep,rate,slot->Sample->DR2);\n\tslot->EG.RR=Get_RATE(ptChip->DRStep,rate,slot->Sample->RR);\n\tslot->EG.DL=0xf-slot->Sample->DL;\n\n}\n\n/*****************************\n        LFO  SECTION\n*****************************/\n\n#define LFO_SHIFT\t8\n\n\n#define LFIX(v)\t((unsigned int) ((float) (1<<LFO_SHIFT)*(v)))\n\n//Convert DB to multiply amplitude\n#define DB(v)\tLFIX(pow(10.0,v/20.0))\n\n//Convert cents to step increment\n#define CENTS(v) LFIX(pow(2.0,v/1200.0))\n\nstatic int PLFO_TRI[256];\nstatic int ALFO_TRI[256];\n\nstatic const float LFOFreq[8]={0.168f,2.019f,3.196f,4.206f,5.215f,5.888f,6.224f,7.066f};\t//Hz;\nstatic const float PSCALE[8]={0.0f,3.378f,5.065f,6.750f,10.114f,20.170f,40.180f,79.307f};\t//cents\nstatic const float ASCALE[8]={0.0f,0.4f,0.8f,1.5f,3.0f,6.0f,12.0f,24.0f};\t\t\t\t\t//DB\nstatic int PSCALES[8][256];\nstatic int ASCALES[8][256];\n\nstatic void LFO_Init(void)\n{\n\tint i,s;\n\tfor(i=0;i<256;++i)\n\t{\n\t\tint a;\t//amplitude\n\t\tint p;\t//phase\n\n\t\t//Tri\n\t\tif(i<128)\n\t\t\ta=255-(i*2);\n\t\telse\n\t\t\ta=(i*2)-256;\n\t\tif(i<64)\n\t\t\tp=i*2;\n\t\telse if(i<128)\n\t\t\tp=255-i*2;\n\t\telse if(i<192)\n\t\t\tp=256-i*2;\n\t\telse\n\t\t\tp=i*2-511;\n\t\tALFO_TRI[i]=a;\n\t\tPLFO_TRI[i]=p;\n\t}\n\n\tfor(s=0;s<8;++s)\n\t{\n\t\tfloat limit=PSCALE[s];\n\t\tfor(i=-128;i<128;++i)\n\t\t{\n\t\t\tPSCALES[s][i+128]=CENTS(((limit*(float) i)/128.0));\n\t\t}\n\t\tlimit=-ASCALE[s];\n\t\tfor(i=0;i<256;++i)\n\t\t{\n\t\t\tASCALES[s][i]=DB(((limit*(float) i)/256.0));\n\t\t}\n\t}\n}\n\nINLINE signed int PLFO_Step(struct _LFO *LFO)\n{\n\tint p;\n\tLFO->phase+=LFO->phase_step;\n\tp=LFO->table[(LFO->phase>>LFO_SHIFT)&0xff];\n\tp=LFO->scale[p+128];\n\treturn p<<(SHIFT-LFO_SHIFT);\n}\n\nINLINE signed int ALFO_Step(struct _LFO *LFO)\n{\n\tint p;\n\tLFO->phase+=LFO->phase_step;\n\tp=LFO->table[(LFO->phase>>LFO_SHIFT)&0xff];\n\tp=LFO->scale[p];\n\treturn p<<(SHIFT-LFO_SHIFT);\n}\n\nstatic void LFO_ComputeStep(MultiPCM *ptChip,struct _LFO *LFO,UINT32 LFOF,UINT32 LFOS,int ALFO)\n{\n\tfloat step=(float) LFOFreq[LFOF]*256.0/(float) ptChip->Rate;\n\tLFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step);\n\tif(ALFO)\n\t{\n\t\tLFO->table=ALFO_TRI;\n\t\tLFO->scale=ASCALES[LFOS];\n\t}\n\telse\n\t{\n\t\tLFO->table=PLFO_TRI;\n\t\tLFO->scale=PSCALES[LFOS];\n\t}\n}\n\n\n\nstatic void WriteSlot(MultiPCM *ptChip,struct _SLOT *slot,int reg,unsigned char data)\n{\n\tslot->Regs[reg]=data;\n\n\tswitch(reg)\n\t{\n\t\tcase 0:\t//PANPOT\n\t\t\tslot->Pan=(data>>4)&0xf;\n\t\t\tbreak;\n\t\tcase 1:\t//Sample\n\t\t\t//according to YMF278 sample write causes some base params written to the regs (envelope+lfos)\n\t\t\t//the game should never change the sample while playing.\n\t\t\t{\n\t\t\t\tstruct _Sample *Sample=ptChip->Samples+slot->Regs[1]+((slot->Regs[2]&1)<<8);\n\t\t\t\tWriteSlot(ptChip,slot,6,Sample->LFOVIB);\n\t\t\t\tWriteSlot(ptChip,slot,7,Sample->AM);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 2:\t//Pitch\n\t\tcase 3:\n\t\t\t{\n\t\t\t\tunsigned int oct=((slot->Regs[3]>>4)-1)&0xf;\n\t\t\t\tunsigned int pitch=((slot->Regs[3]&0xf)<<6)|(slot->Regs[2]>>2);\n\t\t\t\tpitch=ptChip->FNS_Table[pitch];\n\t\t\t\tif(oct&0x8)\n\t\t\t\t\tpitch>>=(16-oct);\n\t\t\t\telse\n\t\t\t\t\tpitch<<=oct;\n\t\t\t\tslot->step=pitch/ptChip->Rate;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 4:\t\t//KeyOn/Off (and more?)\n\t\t\t{\n\t\t\t\tif(data&0x80)\t\t//KeyOn\n\t\t\t\t{\n\t\t\t\t\tUINT16 sampleID = slot->Regs[1]+((slot->Regs[2]&1)<<8);\n\t\t\t\t\tif (ptChip->Bank && sampleID >= 0x100)\n\t\t\t\t\t{\n#ifdef SHOW_WARNINGS\n\t\t\t\t\t\tif (! (didWarn & 0x02))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdidWarn |= 0x02;\n\t\t\t\t\t\t\tprintf(\"YMW Warning: SEGA Banking + playing sample with ID 0x100+\\n\");\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\tsampleID &= 0x0FF;\n\t\t\t\t\t}\n\t\t\t\t\tslot->Sample=ptChip->Samples+sampleID;\n\t\t\t\t\t//slot->Sample=ptChip->Samples+slot->Regs[1]+((slot->Regs[2]&1)<<8);\n\t\t\t\t\tslot->Playing=1;\n\t\t\t\t\tslot->Base=slot->Sample->Start;\n\t\t\t\t\tslot->offset=0;\n\t\t\t\t\tslot->Prev=0;\n\t\t\t\t\tslot->TL=slot->DstTL<<SHIFT;\n\n\t\t\t\t\tEG_Calc(ptChip,slot);\n\t\t\t\t\tslot->EG.state=ATTACK;\n\t\t\t\t\tslot->EG.volume=0;\n\n\t\t\t\t\tif(ptChip->Bank && slot->Base>=0x100000)\n\t\t\t\t\t{\n#ifdef SHOW_WARNINGS\n\t\t\t\t\t\tUINT8 otherBnk;\n\t\t\t\t\t\tif (slot->Pan & 8)\n\t\t\t\t\t\t\totherBnk = (ptChip->Bank != ptChip->BankL);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\totherBnk = (ptChip->Bank != ptChip->BankR);\n\t\t\t\t\t\tif (otherBnk)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (! (didWarn & 0x01))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdidWarn |= 0x01;\n\t\t\t\t\t\t\t\tprintf(\"YMW Warning: Playing sound on possibly unintended bank!\\n\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\tslot->Base=(slot->Base&0xfffff)|(ptChip->Bank);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(slot->Playing)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(slot->Sample->RR!=0xf)\n\t\t\t\t\t\t\tslot->EG.state=RELEASE;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tslot->Playing=0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 5:\t//TL+Interpolation\n\t\t\t{\n\t\t\t\tslot->DstTL=(data>>1)&0x7f;\n\t\t\t\tif(!(data&1))\t//Interpolate TL\n\t\t\t\t{\n\t\t\t\t\tif((slot->TL>>SHIFT)>slot->DstTL)\n\t\t\t\t\t\tslot->TLStep=TLSteps[0];\t\t//decrease\n\t\t\t\t\telse\n\t\t\t\t\t\tslot->TLStep=TLSteps[1];\t\t//increase\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tslot->TL=slot->DstTL<<SHIFT;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 6:\t//LFO freq+PLFO\n\t\t\t{\n\t\t\t\tif(data)\n\t\t\t\t{\n\t\t\t\t\tLFO_ComputeStep(ptChip,&(slot->PLFO),(slot->Regs[6]>>3)&7,slot->Regs[6]&7,0);\n\t\t\t\t\tLFO_ComputeStep(ptChip,&(slot->ALFO),(slot->Regs[6]>>3)&7,slot->Regs[7]&7,1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 7:\t//ALFO\n\t\t\t{\n\t\t\t\tif(data)\n\t\t\t\t{\n\t\t\t\t\tLFO_ComputeStep(ptChip,&(slot->PLFO),(slot->Regs[6]>>3)&7,slot->Regs[6]&7,0);\n\t\t\t\t\tLFO_ComputeStep(ptChip,&(slot->ALFO),(slot->Regs[6]>>3)&7,slot->Regs[7]&7,1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t}\n}\n\n//static STREAM_UPDATE( MultiPCM_update )\nvoid MultiPCM_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//MultiPCM *ptChip = (MultiPCM *)param;\n\tMultiPCM *ptChip = &MultiPCMData[ChipID];\n\tstream_sample_t  *datap[2];\n\tint i,sl;\n\n\tdatap[0] = outputs[0];\n\tdatap[1] = outputs[1];\n\n\tmemset(datap[0], 0, sizeof(*datap[0])*samples);\n\tmemset(datap[1], 0, sizeof(*datap[1])*samples);\n\n\n\tfor(i=0;i<samples;++i)\n\t{\n\t\tsigned int smpl=0;\n\t\tsigned int smpr=0;\n\t\tfor(sl=0;sl<28;++sl)\n\t\t{\n\t\t\tstruct _SLOT *slot=ptChip->Slots+sl;\n\t\t\tif(slot->Playing && ! slot->Muted)\n\t\t\t{\n\t\t\t\tunsigned int vol=(slot->TL>>SHIFT)|(slot->Pan<<7);\n\t\t\t\tunsigned int adr=slot->offset>>SHIFT;\n\t\t\t\tsigned int sample;\n\t\t\t\tunsigned int step=slot->step;\n\t\t\t\tsigned int csample=(signed short) (ptChip->ROM[(slot->Base+adr) & ptChip->ROMMask]<<8);\n\t\t\t\tsigned int fpart=slot->offset&((1<<SHIFT)-1);\n\t\t\t\tsample=(csample*fpart+slot->Prev*((1<<SHIFT)-fpart))>>SHIFT;\n\n\t\t\t\tif(slot->Regs[6]&7)\t//Vibrato enabled\n\t\t\t\t{\n\t\t\t\t\tstep=step*PLFO_Step(&(slot->PLFO));\n\t\t\t\t\tstep>>=SHIFT;\n\t\t\t\t}\n\n\t\t\t\tslot->offset+=step;\n\t\t\t\tif(slot->offset>=(slot->Sample->End<<SHIFT))\n\t\t\t\t{\n\t\t\t\t\tslot->offset=slot->Sample->Loop<<SHIFT;\n\t\t\t\t}\n\t\t\t\tif(adr^(slot->offset>>SHIFT))\n\t\t\t\t{\n\t\t\t\t\tslot->Prev=csample;\n\t\t\t\t}\n\n\t\t\t\tif((slot->TL>>SHIFT)!=slot->DstTL)\n\t\t\t\t\tslot->TL+=slot->TLStep;\n\n\t\t\t\tif(slot->Regs[7]&7)\t//Tremolo enabled\n\t\t\t\t{\n\t\t\t\t\tsample=sample*ALFO_Step(&(slot->ALFO));\n\t\t\t\t\tsample>>=SHIFT;\n\t\t\t\t}\n\n\t\t\t\tsample=(sample*EG_Update(slot))>>10;\n\n\t\t\t\tsmpl+=(LPANTABLE[vol]*sample)>>SHIFT;\n\t\t\t\tsmpr+=(RPANTABLE[vol]*sample)>>SHIFT;\n\t\t\t}\n\t\t}\n/*#define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x)\n\t\tdatap[0][i]=ICLIP16(smpl);\n\t\tdatap[1][i]=ICLIP16(smpr);*/\n\t\tdatap[0][i] = smpl;\n\t\tdatap[1][i] = smpr;\n\t}\n}\n\n//READ8_DEVICE_HANDLER( multipcm_r )\nUINT8 multipcm_r(UINT8 ChipID, offs_t offset)\n{\n//  MultiPCM *ptChip = get_safe_token(device);\n//\tMultiPCM *ptChip = &MultiPCMData[ChipID];\n\treturn 0;\n}\n\n//static DEVICE_START( multipcm )\nint device_start_multipcm(UINT8 ChipID, int clock)\n{\n\t//MultiPCM *ptChip = get_safe_token(device);\n\tMultiPCM *ptChip;\n\tint i;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tptChip = &MultiPCMData[ChipID];\n\t\n\t//ptChip->ROM=*device->region();\n\tptChip->ROMMask = 0x00;\n\tptChip->ROMSize = 0x00;\n\tptChip->ROM = NULL;\n\t//ptChip->Rate=(float) device->clock() / MULTIPCM_CLOCKDIV;\n\tptChip->Rate=(float) clock / MULTIPCM_CLOCKDIV;\n\n\t//ptChip->stream = stream_create(device, 0, 2, ptChip->Rate, ptChip, MultiPCM_update);\n\n\tif (! IsInit)\n\t{\n\t\t//Volume+pan table\n\t\tfor(i=0;i<0x800;++i)\n\t\t{\n\t\t\tfloat SegaDB=0;\n\t\t\tfloat TL;\n\t\t\tfloat LPAN,RPAN;\n\n\t\t\tunsigned char iTL=i&0x7f;\n\t\t\tunsigned char iPAN=(i>>7)&0xf;\n\n\t\t\tSegaDB=(float) iTL*(-24.0)/(float) 0x40;\n\n\t\t\tTL=pow(10.0,SegaDB/20.0);\n\n\n\t\t\tif(iPAN==0x8)\n\t\t\t{\n\t\t\t\tLPAN=RPAN=0.0;\n\t\t\t}\n\t\t\telse if(iPAN==0x0)\n\t\t\t{\n\t\t\t\tLPAN=RPAN=1.0;\n\t\t\t}\n\t\t\telse if(iPAN&0x8)\n\t\t\t{\n\t\t\t\tLPAN=1.0;\n\n\t\t\t\tiPAN=0x10-iPAN;\n\n\t\t\t\tSegaDB=(float) iPAN*(-12.0)/(float) 0x4;\n\n\t\t\t\tRPAN=pow(10.0,SegaDB/20.0);\n\n\t\t\t\tif((iPAN&0x7)==7)\n\t\t\t\t\tRPAN=0.0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tRPAN=1.0;\n\n\t\t\t\tSegaDB=(float) iPAN*(-12.0)/(float) 0x4;\n\n\t\t\t\tLPAN=pow(10.0,SegaDB/20.0);\n\t\t\t\tif((iPAN&0x7)==7)\n\t\t\t\t\tLPAN=0.0;\n\t\t\t}\n\n\t\t\tTL/=4.0;\n\n\t\t\tLPANTABLE[i]=FIX((LPAN*TL));\n\t\t\tRPANTABLE[i]=FIX((RPAN*TL));\n\t\t}\n\t\tIsInit = 0x01;\n\t}\n\n\t//Pitch steps\n\tfor(i=0;i<0x400;++i)\n\t{\n\t\tfloat fcent=ptChip->Rate*(1024.0+(float) i)/1024.0;\n\t\tptChip->FNS_Table[i]=(unsigned int ) ((float) (1<<SHIFT) *fcent);\n\t}\n\n\t//Envelope steps\n\tfor(i=0;i<0x40;++i)\n\t{\n\t\t//Times are based on 44100 clock, adjust to real chip clock\n\t\tptChip->ARStep[i]=(float) (0x400<<EG_SHIFT)/(BaseTimes[i]*44100.0/(1000.0));\n\t\tptChip->DRStep[i]=(float) (0x400<<EG_SHIFT)/(BaseTimes[i]*AR2DR*44100.0/(1000.0));\n\t}\n\tptChip->ARStep[0]=ptChip->ARStep[1]=ptChip->ARStep[2]=ptChip->ARStep[3]=0;\n\tptChip->ARStep[0x3f]=0x400<<EG_SHIFT;\n\tptChip->DRStep[0]=ptChip->DRStep[1]=ptChip->DRStep[2]=ptChip->DRStep[3]=0;\n\n\t//TL Interpolation steps\n\t//lower\n\tTLSteps[0]=-(float) (0x80<<SHIFT)/(78.2*44100.0/1000.0);\n\t//raise\n\tTLSteps[1]=(float) (0x80<<SHIFT)/(78.2*2*44100.0/1000.0);\n\n\t//build the linear->exponential ramps\n\tfor(i=0;i<0x400;++i)\n\t{\n\t\tfloat db=-(96.0-(96.0*(float) i/(float) 0x400));\n\t\tlin2expvol[i]=pow(10.0,db/20.0)*(float) (1<<SHIFT);\n\t}\n\n\n\t/*for(i=0;i<512;++i)\n\t{\n\t\tUINT8 *ptSample=(UINT8 *) ptChip->ROM+i*12;\n\t\tptChip->Samples[i].Start=(ptSample[0]<<16)|(ptSample[1]<<8)|(ptSample[2]<<0);\n\t\tptChip->Samples[i].Loop=(ptSample[3]<<8)|(ptSample[4]<<0);\n\t\tptChip->Samples[i].End=0xffff-((ptSample[5]<<8)|(ptSample[6]<<0));\n\t\tptChip->Samples[i].LFOVIB=ptSample[7];\n\t\tptChip->Samples[i].DR1=ptSample[8]&0xf;\n\t\tptChip->Samples[i].AR=(ptSample[8]>>4)&0xf;\n\t\tptChip->Samples[i].DR2=ptSample[9]&0xf;\n\t\tptChip->Samples[i].DL=(ptSample[9]>>4)&0xf;\n\t\tptChip->Samples[i].RR=ptSample[10]&0xf;\n\t\tptChip->Samples[i].KRS=(ptSample[10]>>4)&0xf;\n\t\tptChip->Samples[i].AM=ptSample[11];\n\t}*/\n\n\t/*state_save_register_device_item(device, 0, ptChip->CurSlot);\n\tstate_save_register_device_item(device, 0, ptChip->Address);\n\tstate_save_register_device_item(device, 0, ptChip->BankL);\n\tstate_save_register_device_item(device, 0, ptChip->BankR);*/\n\n\t// reset is done via DEVICE_RESET\n\t/*for(i=0;i<28;++i)\n\t{\n\t\tptChip->Slots[i].Num=i;\n\t\tptChip->Slots[i].Playing=0;\n\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].Num);\n\t\tstate_save_register_device_item_array(device, i, ptChip->Slots[i].Regs);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].Playing);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].Base);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].offset);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].step);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].Pan);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].TL);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].DstTL);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].TLStep);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].Prev);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].EG.volume);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].EG.state);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].EG.step);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].EG.AR);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].EG.D1R);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].EG.D2R);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].EG.RR);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].EG.DL);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].PLFO.phase);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].PLFO.phase_step);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].ALFO.phase);\n\t\tstate_save_register_device_item(device, i, ptChip->Slots[i].ALFO.phase_step);\n\t}*/\n\n\tLFO_Init();\n\t\n\tdidWarn = 0x00;\n\tmultipcm_set_bank(ChipID, 0x00, 0x00);\n\t\n\treturn (int)(ptChip->Rate + 0.5);\n}\n\n\nvoid device_stop_multipcm(UINT8 ChipID)\n{\n\tMultiPCM *ptChip = &MultiPCMData[ChipID];\n\t\n\tfree(ptChip->ROM);\tptChip->ROM = NULL;\n\t\n\treturn;\n}\n\nvoid device_reset_multipcm(UINT8 ChipID)\n{\n\tMultiPCM *ptChip = &MultiPCMData[ChipID];\n\tint i;\n\t\n\tfor(i=0;i<28;++i)\n\t{\n\t\tptChip->Slots[i].Num=i;\n\t\tptChip->Slots[i].Playing=0;\n\t}\n\t\n\treturn;\n}\n\n\n//WRITE8_DEVICE_HANDLER( multipcm_w )\nvoid multipcm_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//MultiPCM *ptChip = get_safe_token(device);\n\tMultiPCM *ptChip = &MultiPCMData[ChipID];\n\tswitch(offset)\n\t{\n\t\tcase 0:\t\t//Data write\n\t\t\tWriteSlot(ptChip,ptChip->Slots+ptChip->CurSlot,ptChip->Address,data);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tptChip->CurSlot=val2chan[data&0x1f];\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tptChip->Address=(data>7)?7:data;\n\t\t\tbreak;\n\t}\n\t/*ptChip->CurSlot = val2chan[(offset >> 3) & 0x1F];\n\tptChip->Address = offset & 0x07;\n\tWriteSlot(ptChip, ptChip->Slots + ptChip->CurSlot, ptChip->Address, data);*/\n}\n\n/* MAME/M1 access functions */\n\n//void multipcm_set_bank(running_device *device, UINT32 leftoffs, UINT32 rightoffs)\nvoid multipcm_set_bank(UINT8 ChipID, UINT32 leftoffs, UINT32 rightoffs)\n{\n\t//MultiPCM *ptChip = get_safe_token(device);\n\tMultiPCM *ptChip = &MultiPCMData[ChipID];\n\tptChip->BankL = leftoffs;\n\tptChip->BankR = rightoffs;\n\tptChip->Bank = ptChip->BankR ? ptChip->BankR : ptChip->BankL;\n}\n\nvoid multipcm_bank_write(UINT8 ChipID, UINT8 offset, UINT16 data)\n{\n\tMultiPCM *ptChip = &MultiPCMData[ChipID];\n\t\n\tif (offset & 0x01)\n\t\tptChip->BankL = data << 16;\n\tif (offset & 0x02)\n\t\tptChip->BankR = data << 16;\n\tptChip->Bank = ptChip->BankR ? ptChip->BankR : ptChip->BankL;\n#ifdef SHOW_WARNINGS\n\tif (ptChip->BankL != 0 && ptChip->BankR != 0 && ptChip->BankL != ptChip->BankR)\n\t\t//printf(\"Bank L/R mismatch: 0x%X != 0x%X\\n\", ptChip->BankL, ptChip->BankR);\n\t\tprintf(\"YMW Banks: 0x%X != 0x%X  \\n\", ptChip->BankL, ptChip->BankR);\n\telse\n\t\tprintf(\"YMW Banks: 0x%X / 0x%X  \\n\", ptChip->BankL, ptChip->BankR);\n#endif\n\t\n\treturn;\n}\n\nvoid multipcm_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t\tconst UINT8* ROMData)\n{\n\tMultiPCM *ptChip = &MultiPCMData[ChipID];\n\tUINT16 CurSmpl;\n\tstruct _Sample* TempSmpl;\n\tUINT8* ptSample;\n\t\n\tif (ptChip->ROMSize != ROMSize)\n\t{\n\t\tptChip->ROM = (INT8*)realloc(ptChip->ROM, ROMSize);\n\t\tptChip->ROMSize = ROMSize;\n\t\t\n\t\tfor (ptChip->ROMMask = 1; ptChip->ROMMask < ROMSize; ptChip->ROMMask <<= 1)\n\t\t\t;\n\t\tptChip->ROMMask --;\n\t\t\n\t\tmemset(ptChip->ROM, 0xFF, ROMSize);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(ptChip->ROM + DataStart, ROMData, DataLength);\n\t\n\tif (DataStart < 0x200 * 12)\n\t{\n\t\tfor (CurSmpl = 0; CurSmpl < 512; CurSmpl ++)\n\t\t{\n\t\t\tTempSmpl = &ptChip->Samples[CurSmpl];\n\t\t\tptSample = (UINT8*)ptChip->ROM + CurSmpl * 12;\n\t\t\t\n\t\t\tTempSmpl->Start = (ptSample[0]<<16)|(ptSample[1]<<8)|(ptSample[2]<<0);\n\t\t\tTempSmpl->Loop = (ptSample[3]<<8)|(ptSample[4]<<0);\n\t\t\tTempSmpl->End = 0xffff-((ptSample[5]<<8)|(ptSample[6]<<0));\n\t\t\tTempSmpl->LFOVIB = ptSample[7];\n\t\t\tTempSmpl->DR1 = ptSample[8]&0xf;\n\t\t\tTempSmpl->AR = (ptSample[8]>>4)&0xf;\n\t\t\tTempSmpl->DR2 = ptSample[9]&0xf;\n\t\t\tTempSmpl->DL = (ptSample[9]>>4)&0xf;\n\t\t\tTempSmpl->RR = ptSample[10]&0xf;\n\t\t\tTempSmpl->KRS = (ptSample[10]>>4)&0xf;\n\t\t\tTempSmpl->AM = ptSample[11];\n\t\t}\n\t}\n\t\n\treturn;\n}\n\n\nvoid multipcm_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tMultiPCM* ptChip = &MultiPCMData[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 28; CurChn ++)\n\t\tptChip->Slots[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n#if 0\t// for debugging only\nUINT8 multipcm_get_channels(UINT8 ChipID, UINT32* ChannelMask)\n{\n\tMultiPCM* ptChip = &MultiPCMData[ChipID];\n\tUINT8 CurChn;\n\tUINT8 UsedChns;\n\tUINT32 ChnMask;\n\t\n\tChnMask = 0x00000000;\n\tUsedChns = 0x00;\n\tfor (CurChn = 0; CurChn < 28; CurChn ++)\n\t{\n\t\tif (ptChip->Slots[CurChn].Playing)\n\t\t{\n\t\t\tChnMask |= (1 << CurChn);\n\t\t\tUsedChns ++;\n\t\t}\n\t}\n\tif (ChannelMask != NULL)\n\t\t*ChannelMask = ChnMask;\n\t\n\treturn UsedChns;\n}\n#endif\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( multipcm )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(MultiPCM);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( multipcm );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"Sega/Yamaha 315-5560\");\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Sega custom\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"2.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n\n\n//DEFINE_LEGACY_SOUND_DEVICE(MULTIPCM, multipcm);\n"
  },
  {
    "path": "VGMPlay/chips/multipcm.h",
    "content": "#pragma once\n\n//#include \"devlegcy.h\"\n\nvoid MultiPCM_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_multipcm(UINT8 ChipID, int clock);\nvoid device_stop_multipcm(UINT8 ChipID);\nvoid device_reset_multipcm(UINT8 ChipID);\n\n//WRITE8_DEVICE_HANDLER( multipcm_w );\n//READ8_DEVICE_HANDLER( multipcm_r );\nvoid multipcm_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 multipcm_r(UINT8 ChipID, offs_t offset);\n\nvoid multipcm_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t\tconst UINT8* ROMData);\n//void multipcm_set_bank(running_device *device, UINT32 leftoffs, UINT32 rightoffs);\nvoid multipcm_set_bank(UINT8 ChipID, UINT32 leftoffs, UINT32 rightoffs);\nvoid multipcm_bank_write(UINT8 ChipID, UINT8 offset, UINT16 data);\n\nvoid multipcm_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n//DECLARE_LEGACY_SOUND_DEVICE(MULTIPCM, multipcm);\n"
  },
  {
    "path": "VGMPlay/chips/nes_apu.c",
    "content": "/*****************************************************************************\n\n  MAME/MESS NES APU CORE\n\n  Based on the Nofrendo/Nosefart NES N2A03 sound emulation core written by\n  Matthew Conte (matt@conte.com) and redesigned for use in MAME/MESS by\n  Who Wants to Know? (wwtk@mail.com)\n\n  This core is written with the advise and consent of Matthew Conte and is\n  released under the GNU Public License.  This core is freely avaiable for\n  use in any freeware project, subject to the following terms:\n\n  Any modifications to this code must be duly noted in the source and\n  approved by Matthew Conte and myself prior to public submission.\n\n  timing notes:\n  master = 21477270\n  2A03 clock = master/12\n  sequencer = master/89490 or CPU/7457\n\n *****************************************************************************\n\n   NES_APU.C\n\n   Actual NES APU interface.\n\n   LAST MODIFIED 02/29/2004\n\n   - Based on Matthew Conte's Nofrendo/Nosefart core and redesigned to\n     use MAME system calls and to enable multiple APUs.  Sound at this\n     point should be just about 100% accurate, though I cannot tell for\n     certain as yet.\n\n     A queue interface is also available for additional speed.  However,\n     the implementation is not yet 100% (DPCM sounds are inaccurate),\n     so it is disabled by default.\n\n *****************************************************************************\n\n   BUGFIXES:\n\n   - Various bugs concerning the DPCM channel fixed. (Oliver Achten)\n   - Fixed $4015 read behaviour. (Oliver Achten)\n\n *****************************************************************************/\n\n#include \"mamedef.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n//#include \"emu.h\"\n//#include \"streams.h\"\n#include \"nes_apu.h\"\n//#include \"cpu/m6502/m6502.h\"\n\n#include \"nes_defs.h\"\n\n/* GLOBAL CONSTANTS */\n#define  SYNCS_MAX1     0x20\n#define  SYNCS_MAX2     0x80\n\n/* GLOBAL VARIABLES */\ntypedef struct _nesapu_state nesapu_state;\nstruct _nesapu_state\n{\n\tapu_t   APU;\t\t\t       /* Actual APUs */\n\tfloat   apu_incsize;           /* Adjustment increment */\n\tuint32  samps_per_sync;        /* Number of samples per vsync */\n\tuint32  buffer_size;           /* Actual buffer size in bytes */\n\tuint32  real_rate;             /* Actual playback rate */\n\tuint8   noise_lut[NOISE_LONG]; /* Noise sample lookup table */\n\tuint32  vbl_times[0x20];       /* VBL durations in samples */\n\tuint32  sync_times1[SYNCS_MAX1]; /* Samples per sync table */\n\tuint32  sync_times2[SYNCS_MAX2]; /* Samples per sync table */\n\t//sound_stream *stream;\n};\n\nstatic UINT8 DPCMBase0 = 0x01;\n\n//#define MAX_CHIPS\t0x02\n//static nesapu_state NESAPUData[MAX_CHIPS];\n\n/*INLINE nesapu_state *get_safe_token(running_device *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == NES);\n\treturn (nesapu_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n/* INTERNAL FUNCTIONS */\n\n/* INITIALIZE WAVE TIMES RELATIVE TO SAMPLE RATE */\nstatic void create_vbltimes(uint32 * table,const uint8 *vbl,unsigned int rate)\n{\n\tint i;\n\n\tfor (i = 0; i < 0x20; i++)\n\t\ttable[i] = vbl[i] * rate;\n}\n\n/* INITIALIZE SAMPLE TIMES IN TERMS OF VSYNCS */\nstatic void create_syncs(nesapu_state *info, unsigned long sps)\n{\n\tint i;\n\tunsigned long val = sps;\n\n\tfor (i = 0; i < SYNCS_MAX1; i++)\n\t{\n\t\tinfo->sync_times1[i] = val;\n\t\tval += sps;\n\t}\n\n\tval = 0;\n\tfor (i = 0; i < SYNCS_MAX2; i++)\n\t{\n\t\tinfo->sync_times2[i] = val;\n\t\tinfo->sync_times2[i] >>= 2;\n\t\tval += sps;\n\t}\n}\n\n/* INITIALIZE NOISE LOOKUP TABLE */\nstatic void create_noise(uint8 *buf, const int bits, int size)\n{\n\tint m = 0x0011;\n\tint xor_val, i;\n\n\tfor (i = 0; i < size; i++)\n\t{\n\t\txor_val = m & 1;\n\t\tm >>= 1;\n\t\txor_val ^= (m & 1);\n\t\tm |= xor_val << (bits - 1);\n\n\t\tbuf[i] = m;\n\t}\n}\n\n/* TODO: sound channels should *ALL* have DC volume decay */\n\n/* OUTPUT SQUARE WAVE SAMPLE (VALUES FROM -16 to +15) */\nstatic int8 apu_square(nesapu_state *info, square_t *chan)\n{\n\tint env_delay;\n\tint sweep_delay;\n\tint8 output;\n\tuint8 freq_index;\n\n\t/* reg0: 0-3=volume, 4=envelope, 5=hold, 6-7=duty cycle\n    ** reg1: 0-2=sweep shifts, 3=sweep inc/dec, 4-6=sweep length, 7=sweep on\n    ** reg2: 8 bits of freq\n    ** reg3: 0-2=high freq, 7-4=vbl length counter\n    */\n\n\tif (FALSE == chan->enabled || chan->Muted)\n\t\treturn 0;\n\n\t/* enveloping */\n\tenv_delay = info->sync_times1[chan->regs[0] & 0x0F];\n\n\t/* decay is at a rate of (env_regs + 1) / 240 secs */\n\tchan->env_phase -= 4;\n\twhile (chan->env_phase < 0)\n\t{\n\t\tchan->env_phase += env_delay;\n\t\tif (chan->regs[0] & 0x20)\n\t\t\tchan->env_vol = (chan->env_vol + 1) & 15;\n\t\telse if (chan->env_vol < 15)\n\t\t\tchan->env_vol++;\n\t}\n\n\t/* vbl length counter */\n\tif (chan->vbl_length > 0 && 0 == (chan->regs [0] & 0x20))\n\t\tchan->vbl_length--;\n\n\tif (0 == chan->vbl_length)\n\t\treturn 0;\n\n\t/* freqsweeps */\n\tif ((chan->regs[1] & 0x80) && (chan->regs[1] & 7))\n\t{\n\t\tsweep_delay = info->sync_times1[(chan->regs[1] >> 4) & 7];\n\t\tchan->sweep_phase -= 2;\n\t\twhile (chan->sweep_phase < 0)\n\t\t{\n\t\t\tchan->sweep_phase += sweep_delay;\n\t\t\tif (chan->regs[1] & 8)\n\t\t\t\tchan->freq -= chan->freq >> (chan->regs[1] & 7);\n\t\t\telse\n\t\t\t\tchan->freq += chan->freq >> (chan->regs[1] & 7);\n\t\t}\n\t}\n\n//\tif ((0 == (chan->regs[1] & 8) && (chan->freq >> 16) > freq_limit[chan->regs[1] & 7])\n//\t\t || (chan->freq >> 16) < 4)\n//\t\treturn 0;\n\t\n\t// Thanks to Delek for the fix\n\tif (chan->regs[1] & 0x80)\n\t\tfreq_index = chan->regs[1] & 7;\t//If sweeping is enabled, I choose it as normal.\n\telse\n\t\tfreq_index = 7;\t//If sweeping is disabled, I choose the lower limit.\n\t\n\tif ((0 == (chan->regs[1] & 8) && (chan->freq >> 16) > freq_limit[freq_index])\n\t\t || (chan->freq >> 16) < 4)\n\t\treturn 0;\n\n\tchan->phaseacc -= (float) info->apu_incsize; /* # of cycles per sample */\n\n\twhile (chan->phaseacc < 0)\n\t{\n\t\tchan->phaseacc += (chan->freq >> 16);\n\t\tchan->adder = (chan->adder + 1) & 0x0F;\n\t}\n\n\tif (chan->regs[0] & 0x10) /* fixed volume */\n\t\toutput = chan->regs[0] & 0x0F;\n\telse\n\t\toutput = 0x0F - chan->env_vol;\n\n\tif (chan->adder < (duty_lut[chan->regs[0] >> 6]))\n\t\toutput = -output;\n\n\treturn (int8) output;\n}\n\n/* OUTPUT TRIANGLE WAVE SAMPLE (VALUES FROM -16 to +15) */\nstatic int8 apu_triangle(nesapu_state *info, triangle_t *chan)\n{\n\tint freq;\n\tint8 output;\n\t/* reg0: 7=holdnote, 6-0=linear length counter\n    ** reg2: low 8 bits of frequency\n    ** reg3: 7-3=length counter, 2-0=high 3 bits of frequency\n    */\n\n\tif (FALSE == chan->enabled || chan->Muted)\n\t\treturn 0;\n\n\tif (FALSE == chan->counter_started && 0 == (chan->regs[0] & 0x80))\n\t{\n\t\tif (chan->write_latency)\n\t\t\tchan->write_latency--;\n\t\tif (0 == chan->write_latency)\n\t\t\tchan->counter_started = TRUE;\n\t}\n\n\tif (chan->counter_started)\n\t{\n\t\tif (chan->linear_length > 0)\n\t\t\tchan->linear_length--;\n\t\tif (chan->vbl_length && 0 == (chan->regs[0] & 0x80))\n\t\t\t\tchan->vbl_length--;\n\n\t\tif (0 == chan->vbl_length)\n\t\t\treturn 0;\n\t}\n\n\tif (0 == chan->linear_length)\n\t\treturn 0;\n\n\tfreq = (((chan->regs[3] & 7) << 8) + chan->regs[2]) + 1;\n\n\tif (freq < 4) /* inaudible */\n\t\treturn 0;\n\n\tchan->phaseacc -= (float) info->apu_incsize; /* # of cycles per sample */\n\twhile (chan->phaseacc < 0)\n\t{\n\t\tchan->phaseacc += freq;\n\t\tchan->adder = (chan->adder + 1) & 0x1F;\n\n\t\toutput = (chan->adder & 7) << 1;\n\t\tif (chan->adder & 8)\n\t\t\toutput = 0x10 - output;\n\t\tif (chan->adder & 0x10)\n\t\t\toutput = -output;\n\n\t\tchan->output_vol = output;\n\t}\n\n\treturn (int8) chan->output_vol;\n}\n\n/* OUTPUT NOISE WAVE SAMPLE (VALUES FROM -16 to +15) */\nstatic int8 apu_noise(nesapu_state *info, noise_t *chan)\n{\n\tint freq, env_delay;\n\tuint8 outvol;\n\tuint8 output;\n\n\t/* reg0: 0-3=volume, 4=envelope, 5=hold\n    ** reg2: 7=small(93 byte) sample,3-0=freq lookup\n    ** reg3: 7-4=vbl length counter\n    */\n\n\tif (FALSE == chan->enabled || chan->Muted)\n\t\treturn 0;\n\n\t/* enveloping */\n\tenv_delay = info->sync_times1[chan->regs[0] & 0x0F];\n\n\t/* decay is at a rate of (env_regs + 1) / 240 secs */\n\tchan->env_phase -= 4;\n\twhile (chan->env_phase < 0)\n\t{\n\t\tchan->env_phase += env_delay;\n\t\tif (chan->regs[0] & 0x20)\n\t\t\tchan->env_vol = (chan->env_vol + 1) & 15;\n\t\telse if (chan->env_vol < 15)\n\t\t\tchan->env_vol++;\n\t}\n\n\t/* length counter */\n\tif (0 == (chan->regs[0] & 0x20))\n\t{\n\t\tif (chan->vbl_length > 0)\n\t\t\tchan->vbl_length--;\n\t}\n\n\tif (0 == chan->vbl_length)\n\t\treturn 0;\n\n\tfreq = noise_freq[chan->regs[2] & 0x0F];\n\tchan->phaseacc -= (float) info->apu_incsize; /* # of cycles per sample */\n\twhile (chan->phaseacc < 0)\n\t{\n\t\tchan->phaseacc += freq;\n\n\t\tchan->cur_pos++;\n\t\tif (NOISE_SHORT == chan->cur_pos && (chan->regs[2] & 0x80))\n\t\t\tchan->cur_pos = 0;\n\t\telse if (NOISE_LONG == chan->cur_pos)\n\t\t\tchan->cur_pos = 0;\n\t}\n\n\tif (chan->regs[0] & 0x10) /* fixed volume */\n\t\toutvol = chan->regs[0] & 0x0F;\n\telse\n\t\toutvol = 0x0F - chan->env_vol;\n\n\toutput = info->noise_lut[chan->cur_pos];\n\tif (output > outvol)\n\t\toutput = outvol;\n\n\tif (info->noise_lut[chan->cur_pos] & 0x80) /* make it negative */\n\t\toutput = -output;\n\n\treturn (int8) output;\n}\n\n/* RESET DPCM PARAMETERS */\nINLINE void apu_dpcmreset(dpcm_t *chan)\n{\n\tchan->address = 0xC000 + (uint16) (chan->regs[2] << 6);\n\tchan->length = (uint16) (chan->regs[3] << 4) + 1;\n\tchan->bits_left = chan->length << 3;\n\tchan->irq_occurred = FALSE;\n\tchan->enabled = TRUE; /* Fixed * Proper DPCM channel ENABLE/DISABLE flag behaviour*/\n\t// Note: according to NSFPlay, it does NOT do that\n\tchan->vol = 0; /* Fixed * DPCM DAC resets itself when restarted */\n}\n\n/* OUTPUT DPCM WAVE SAMPLE (VALUES FROM -64 to +63) */\n/* TODO: centerline naughtiness */\nstatic int8 apu_dpcm(nesapu_state *info, dpcm_t *chan)\n{\n\tint freq, bit_pos;\n\n\t/* reg0: 7=irq gen, 6=looping, 3-0=pointer to clock table\n    ** reg1: output dc level, 7 bits unsigned\n    ** reg2: 8 bits of 64-byte aligned address offset : $C000 + (value * 64)\n    ** reg3: length, (value * 16) + 1\n    */\n\tif (chan->Muted)\n\t\treturn 0;\n\n\tif (chan->enabled)\n\t{\n\t\tfreq = dpcm_clocks[chan->regs[0] & 0x0F];\n\t\tchan->phaseacc -= (float) info->apu_incsize; /* # of cycles per sample */\n\n\t\twhile (chan->phaseacc < 0)\n\t\t{\n\t\t\tchan->phaseacc += freq;\n\n\t\t\tif (0 == chan->length)\n\t\t\t{\n\t\t\t\tchan->enabled = FALSE; /* Fixed * Proper DPCM channel ENABLE/DISABLE flag behaviour*/\n\t\t\t\tchan->vol=0; /* Fixed * DPCM DAC resets itself when restarted */\n\t\t\t\tif (chan->regs[0] & 0x40)\n\t\t\t\t\tapu_dpcmreset(chan);\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (chan->regs[0] & 0x80) /* IRQ Generator */\n\t\t\t\t\t{\n\t\t\t\t\t\tchan->irq_occurred = TRUE;\n\t\t\t\t\t\t//n2a03_irq(info->APU.dpcm.memory->cpu);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tchan->bits_left--;\n\t\t\tbit_pos = 7 - (chan->bits_left & 7);\n\t\t\tif (7 == bit_pos)\n\t\t\t{\n\t\t\t\t//chan->cur_byte = info->APU.dpcm.memory->read_byte(chan->address);\n\t\t\t\tchan->cur_byte = info->APU.dpcm.memory[chan->address];\n\t\t\t\tchan->address++;\n\t\t\t\t// On overflow, the address is set to 8000\n\t\t\t\tif (chan->address >= 0x10000)\n\t\t\t\t\tchan->address -= 0x8000;\n\t\t\t\tchan->length--;\n\t\t\t}\n\n\t\t\tif (chan->cur_byte & (1 << bit_pos))\n//              chan->regs[1]++;\n\t\t\t\tchan->vol+=2; /* FIXED * DPCM channel only uses the upper 6 bits of the DAC */\n\t\t\telse\n//              chan->regs[1]--;\n\t\t\t\tchan->vol-=2;\n\t\t}\n\t}\n\n\tif (! DPCMBase0)\n\t{\n\t\tif (chan->vol > 63)\n\t\t\tchan->vol = 63;\n\t\telse if (chan->vol < -64)\n\t\t\tchan->vol = -64;\n\t}\n\telse\n\t{\n\t\tif (chan->vol > 127)\n\t\t\tchan->vol = 127;\n\t\telse if (chan->vol < 0)\n\t\t\tchan->vol = 0;\n\t}\n\n\treturn (int8) (chan->vol);\n\t//return (int8) 0;\n}\n\n/* WRITE REGISTER VALUE */\nINLINE void apu_regwrite(nesapu_state *info,int address, uint8 value)\n{\n\tint chan = (address & 4) ? 1 : 0;\n\n\tswitch (address)\n\t{\n\t/* squares */\n\tcase APU_WRA0:\n\tcase APU_WRB0:\n\t\tinfo->APU.squ[chan].regs[0] = value;\n\t\tbreak;\n\n\tcase APU_WRA1:\n\tcase APU_WRB1:\n\t\tinfo->APU.squ[chan].regs[1] = value;\n\t\tbreak;\n\n\tcase APU_WRA2:\n\tcase APU_WRB2:\n\t\tinfo->APU.squ[chan].regs[2] = value;\n\t\tif (info->APU.squ[chan].enabled)\n\t\t\tinfo->APU.squ[chan].freq = ((((info->APU.squ[chan].regs[3] & 7) << 8) + value) + 1) << 16;\n\t\tbreak;\n\n\tcase APU_WRA3:\n\tcase APU_WRB3:\n\t\tinfo->APU.squ[chan].regs[3] = value;\n\n\t\tif (info->APU.squ[chan].enabled)\n\t\t{\n\t\t// TODO: Test, if it sounds better with or without it.\n\t\t//\tinfo->APU.squ[chan].adder = 0;\t// Thanks to Delek\n\t\t\tinfo->APU.squ[chan].vbl_length = info->vbl_times[value >> 3];\n\t\t\tinfo->APU.squ[chan].env_vol = 0;\n\t\t\tinfo->APU.squ[chan].freq = ((((value & 7) << 8) + info->APU.squ[chan].regs[2]) + 1) << 16;\n\t\t}\n\n\t\tbreak;\n\n\t/* triangle */\n\tcase APU_WRC0:\n\t\tinfo->APU.tri.regs[0] = value;\n\n\t\tif (info->APU.tri.enabled)\n\t\t{                                          /* ??? */\n\t\t\tif (FALSE == info->APU.tri.counter_started)\n\t\t\t\tinfo->APU.tri.linear_length = info->sync_times2[value & 0x7F];\n\t\t}\n\n\t\tbreak;\n\n\t//case 0x4009:\n\tcase APU_WRC1:\n\t\t/* unused */\n\t\tinfo->APU.tri.regs[1] = value;\n\t\tbreak;\n\n\tcase APU_WRC2:\n\t\tinfo->APU.tri.regs[2] = value;\n\t\tbreak;\n\n\tcase APU_WRC3:\n\t\tinfo->APU.tri.regs[3] = value;\n\n\t\t/* this is somewhat of a hack.  there is some latency on the Real\n        ** Thing between when trireg0 is written to and when the linear\n        ** length counter actually begins its countdown.  we want to prevent\n        ** the case where the program writes to the freq regs first, then\n        ** to reg 0, and the counter accidentally starts running because of\n        ** the sound queue's timestamp processing.\n        **\n        ** set to a few NES sample -- should be sufficient\n        **\n        **    3 * (1789772.727 / 44100) = ~122 cycles, just around one scanline\n        **\n        ** should be plenty of time for the 6502 code to do a couple of table\n        ** dereferences and load up the other triregs\n        */\n\n\t/* used to be 3, but now we run the clock faster, so base it on samples/sync */\n\t\tinfo->APU.tri.write_latency = (info->samps_per_sync + 239) / 240;\n\n\t\tif (info->APU.tri.enabled)\n\t\t{\n\t\t\tinfo->APU.tri.counter_started = FALSE;\n\t\t\tinfo->APU.tri.vbl_length = info->vbl_times[value >> 3];\n\t\t\tinfo->APU.tri.linear_length = info->sync_times2[info->APU.tri.regs[0] & 0x7F];\n\t\t}\n\n\t\tbreak;\n\n\t/* noise */\n\tcase APU_WRD0:\n\t\tinfo->APU.noi.regs[0] = value;\n\t\tbreak;\n\n\tcase 0x400D:\n\t\t/* unused */\n\t\tinfo->APU.noi.regs[1] = value;\n\t\tbreak;\n\n\tcase APU_WRD2:\n\t\tinfo->APU.noi.regs[2] = value;\n\t\tinfo->APU.noi.cur_pos = 0;\t// Thanks to Delek for this fix.\n\t\tbreak;\n\n\tcase APU_WRD3:\n\t\tinfo->APU.noi.regs[3] = value;\n\n\t\tif (info->APU.noi.enabled)\n\t\t{\n\t\t\tinfo->APU.noi.vbl_length = info->vbl_times[value >> 3];\n\t\t\tinfo->APU.noi.env_vol = 0; /* reset envelope */\n\t\t}\n\t\tbreak;\n\n\t/* DMC */\n\tcase APU_WRE0:\n\t\tinfo->APU.dpcm.regs[0] = value;\n\t\tif (0 == (value & 0x80))\n\t\t\tinfo->APU.dpcm.irq_occurred = FALSE;\n\t\tbreak;\n\n\tcase APU_WRE1: /* 7-bit DAC */\n\t\t//info->APU.dpcm.regs[1] = value - 0x40;\n\t\tinfo->APU.dpcm.regs[1] = value & 0x7F;\n\t\tif (! DPCMBase0)\n\t\t\tinfo->APU.dpcm.vol = (info->APU.dpcm.regs[1]-64);\n\t\telse\n\t\t\tinfo->APU.dpcm.vol = info->APU.dpcm.regs[1];\n\t\tbreak;\n\n\tcase APU_WRE2:\n\t\tinfo->APU.dpcm.regs[2] = value;\n\t\t//apu_dpcmreset(info->APU.dpcm);\n\t\tbreak;\n\n\tcase APU_WRE3:\n\t\tinfo->APU.dpcm.regs[3] = value;\n\t\tbreak;\n\n\tcase APU_IRQCTRL:\n\t\tif(value & 0x80)\n\t\t\tinfo->APU.step_mode = 5;\n\t\telse\n\t\t\tinfo->APU.step_mode = 4;\n\t\tbreak;\n\n\tcase APU_SMASK:\n\t\tif (value & 0x01)\n\t\t\tinfo->APU.squ[0].enabled = TRUE;\n\t\telse\n\t\t{\n\t\t\tinfo->APU.squ[0].enabled = FALSE;\n\t\t\tinfo->APU.squ[0].vbl_length = 0;\n\t\t}\n\n\t\tif (value & 0x02)\n\t\t\tinfo->APU.squ[1].enabled = TRUE;\n\t\telse\n\t\t{\n\t\t\tinfo->APU.squ[1].enabled = FALSE;\n\t\t\tinfo->APU.squ[1].vbl_length = 0;\n\t\t}\n\n\t\tif (value & 0x04)\n\t\t\tinfo->APU.tri.enabled = TRUE;\n\t\telse\n\t\t{\n\t\t\tinfo->APU.tri.enabled = FALSE;\n\t\t\tinfo->APU.tri.vbl_length = 0;\n\t\t\tinfo->APU.tri.linear_length = 0;\n\t\t\tinfo->APU.tri.counter_started = FALSE;\n\t\t\tinfo->APU.tri.write_latency = 0;\n\t\t}\n\n\t\tif (value & 0x08)\n\t\t\tinfo->APU.noi.enabled = TRUE;\n\t\telse\n\t\t{\n\t\t\tinfo->APU.noi.enabled = FALSE;\n\t\t\tinfo->APU.noi.vbl_length = 0;\n\t\t}\n\n\t\tif (value & 0x10)\n\t\t{\n\t\t\t/* only reset dpcm values if DMA is finished */\n\t\t\tif (FALSE == info->APU.dpcm.enabled)\n\t\t\t{\n\t\t\t\tinfo->APU.dpcm.enabled = TRUE;\n\t\t\t\tapu_dpcmreset(&info->APU.dpcm);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\tinfo->APU.dpcm.enabled = FALSE;\n\n\t\tinfo->APU.dpcm.irq_occurred = FALSE;\n\n\t\tbreak;\n\tdefault:\n#ifdef MAME_DEBUG\nlogerror(\"invalid apu write: $%02X at $%04X\\n\", value, address);\n#endif\n\t\tbreak;\n\t}\n}\n\n/* UPDATE SOUND BUFFER USING CURRENT DATA */\n//INLINE void apu_update(nesapu_state *info, stream_sample_t *buffer16, int samples)\nINLINE void apu_update(nesapu_state *info, stream_sample_t **buffer16, int samples)\n{\n\tint accum;\n\tstream_sample_t* bufL = buffer16[0];\n\tstream_sample_t* bufR = buffer16[1];\n\n\twhile (samples--)\n\t{\n\t\t/*accum = apu_square(info, &info->APU.squ[0]);\n\t\taccum += apu_square(info, &info->APU.squ[1]);\n\t\taccum += apu_triangle(info, &info->APU.tri);\n\t\taccum += apu_noise(info, &info->APU.noi);\n\t\taccum += apu_dpcm(info, &info->APU.dpcm);\n\n\t\t// 8-bit clamps\n\t\tif (accum > 127)\n\t\t\taccum = 127;\n\t\telse if (accum < -128)\n\t\t\taccum = -128;\n\n\t\t*(bufL++)=accum<<8;\n\t\t*(bufR++)=accum<<8;*/\n\n\t\t// These volumes should match NSFPlay's NES core better\n\t\taccum = apu_square(info, &info->APU.squ[0]) << 8;\t// << 8 * 1.0\n\t\taccum += apu_square(info, &info->APU.squ[1]) << 8;\t// << 8 * 1.0\n\t\taccum += apu_triangle(info, &info->APU.tri) * 0xC0;\t// << 8 * 0.75\n\t\taccum += apu_noise(info, &info->APU.noi) * 0xC0;\t// << 8 * 0.75\n\t\taccum += apu_dpcm(info, &info->APU.dpcm) * 0xC0;\t// << 8 * 0.75\n\n\t\t*(bufL++)=accum;\n\t\t*(bufR++)=accum;\n\t}\n}\n\n/* READ VALUES FROM REGISTERS */\nINLINE uint8 apu_read(nesapu_state *info,int address)\n{\n\tif (address == 0x15) /*FIXED* Address $4015 has different behaviour*/\n\t{\n\t\tint readval = 0;\n\t\tif (info->APU.squ[0].vbl_length > 0)\n\t\t\treadval |= 0x01;\n\n\t\tif (info->APU.squ[1].vbl_length > 0)\n\t\t\treadval |= 0x02;\n\n\t\tif (info->APU.tri.vbl_length > 0)\n\t\t\treadval |= 0x04;\n\n\t\tif (info->APU.noi.vbl_length > 0)\n\t\t\treadval |= 0x08;\n\n\t\tif (info->APU.dpcm.enabled == TRUE)\n\t\t\treadval |= 0x10;\n\n\t\tif (info->APU.dpcm.irq_occurred == TRUE)\n\t\t\treadval |= 0x80;\n\n\t\treturn readval;\n\t}\n\telse\n\t\treturn info->APU.regs[address];\n}\n\n/* WRITE VALUE TO TEMP REGISTRY AND QUEUE EVENT */\nINLINE void apu_write(nesapu_state *info,int address, uint8 value)\n{\n\tif (address >= 0x20)\n\t\treturn;\n\tinfo->APU.regs[address]=value;\n\t//stream_update(info->stream);\n\tapu_regwrite(info,address,value);\n}\n\n/* EXTERNAL INTERFACE FUNCTIONS */\n\n/* REGISTER READ/WRITE FUNCTIONS */\n//READ8_DEVICE_HANDLER( nes_psg_r )\nUINT8 nes_psg_r(void* chip, offs_t offset)\n{\n\t//return apu_read(get_safe_token(device),offset);\n\treturn apu_read((nesapu_state*)chip, offset);\n}\n//WRITE8_DEVICE_HANDLER( nes_psg_w )\nvoid nes_psg_w(void* chip, offs_t offset, UINT8 data)\n{\n\t//apu_write(get_safe_token(device),offset,data);\n\tapu_write((nesapu_state*)chip, offset, data);\n}\n\n/* UPDATE APU SYSTEM */\n//static STREAM_UPDATE( nes_psg_update_sound )\nvoid nes_psg_update_sound(void* chip, stream_sample_t **outputs, int samples)\n{\n\t//nesapu_state *info = (nesapu_state *)param;\n\tnesapu_state *info = (nesapu_state*)chip;\n\t//apu_update(info, outputs[0], samples);\n\tapu_update(info, outputs, samples);\n}\n\n\n/* INITIALIZE APU SYSTEM */\n#define SCREEN_HZ\t60\n//static DEVICE_START( nesapu )\nvoid* device_start_nesapu(int clock, int rate)\n{\n\t//const nes_interface *intf = (const nes_interface *)device->baseconfig().static_config();\n\t//nesapu_state *info = get_safe_token(device);\n\tnesapu_state *info;\n\t//int rate = clock / 4;\n\t//int i;\n\n//\tif (ChipID >= MAX_CHIPS)\n//\t\treturn 0;\n\t\n\tinfo = (nesapu_state*)malloc(sizeof(nesapu_state));\n\tif (info == NULL)\n\t\treturn NULL;\n\t\n\t/* Initialize global variables */\n\t//info->samps_per_sync = rate / ATTOSECONDS_TO_HZ(device->machine->primary_screen->frame_period().attoseconds);\n\tinfo->samps_per_sync = rate / SCREEN_HZ;\n\tinfo->buffer_size = info->samps_per_sync;\n\t//info->real_rate = info->samps_per_sync * ATTOSECONDS_TO_HZ(device->machine->primary_screen->frame_period().attoseconds);\n\tinfo->real_rate = info->samps_per_sync * SCREEN_HZ;\n\t//info->apu_incsize = (float) (device->clock() / (float) info->real_rate);\n\tinfo->apu_incsize = (float) (clock / (float) info->real_rate);\n\n\t/* Use initializer calls */\n\tcreate_noise(info->noise_lut, 13, NOISE_LONG);\n\tcreate_vbltimes(info->vbl_times,vbl_length,info->samps_per_sync);\n\tcreate_syncs(info, info->samps_per_sync);\n\n\t/* Adjust buffer size if 16 bits */\n\tinfo->buffer_size+=info->samps_per_sync;\n\n\t/* Initialize individual chips */\n\t//(info->APU.dpcm).memory = cputag_get_address_space(device->machine, intf->cpu_tag, ADDRESS_SPACE_PROGRAM);\n\t// no idea how to obtain this\n\tinfo->APU.dpcm.memory = NULL;\n\n\t//info->stream = stream_create(device, 0, 1, rate, info, nes_psg_update_sound);\n\n\t/* register for save */\n\t/*for (i = 0; i < 2; i++)\n\t{\n\t\tstate_save_register_device_item_array(device, i, info->APU.squ[i].regs);\n\t\tstate_save_register_device_item(device, i, info->APU.squ[i].vbl_length);\n\t\tstate_save_register_device_item(device, i, info->APU.squ[i].freq);\n\t\tstate_save_register_device_item(device, i, info->APU.squ[i].phaseacc);\n\t\tstate_save_register_device_item(device, i, info->APU.squ[i].output_vol);\n\t\tstate_save_register_device_item(device, i, info->APU.squ[i].env_phase);\n\t\tstate_save_register_device_item(device, i, info->APU.squ[i].sweep_phase);\n\t\tstate_save_register_device_item(device, i, info->APU.squ[i].adder);\n\t\tstate_save_register_device_item(device, i, info->APU.squ[i].env_vol);\n\t\tstate_save_register_device_item(device, i, info->APU.squ[i].enabled);\n\t}\n\n\tstate_save_register_device_item_array(device, 0, info->APU.tri.regs);\n\tstate_save_register_device_item(device, 0, info->APU.tri.linear_length);\n\tstate_save_register_device_item(device, 0, info->APU.tri.vbl_length);\n\tstate_save_register_device_item(device, 0, info->APU.tri.write_latency);\n\tstate_save_register_device_item(device, 0, info->APU.tri.phaseacc);\n\tstate_save_register_device_item(device, 0, info->APU.tri.output_vol);\n\tstate_save_register_device_item(device, 0, info->APU.tri.adder);\n\tstate_save_register_device_item(device, 0, info->APU.tri.counter_started);\n\tstate_save_register_device_item(device, 0, info->APU.tri.enabled);\n\n\tstate_save_register_device_item_array(device, 0, info->APU.noi.regs);\n\tstate_save_register_device_item(device, 0, info->APU.noi.cur_pos);\n\tstate_save_register_device_item(device, 0, info->APU.noi.vbl_length);\n\tstate_save_register_device_item(device, 0, info->APU.noi.phaseacc);\n\tstate_save_register_device_item(device, 0, info->APU.noi.output_vol);\n\tstate_save_register_device_item(device, 0, info->APU.noi.env_phase);\n\tstate_save_register_device_item(device, 0, info->APU.noi.env_vol);\n\tstate_save_register_device_item(device, 0, info->APU.noi.enabled);\n\n\tstate_save_register_device_item_array(device, 0, info->APU.dpcm.regs);\n\tstate_save_register_device_item(device, 0, info->APU.dpcm.address);\n\tstate_save_register_device_item(device, 0, info->APU.dpcm.length);\n\tstate_save_register_device_item(device, 0, info->APU.dpcm.bits_left);\n\tstate_save_register_device_item(device, 0, info->APU.dpcm.phaseacc);\n\tstate_save_register_device_item(device, 0, info->APU.dpcm.output_vol);\n\tstate_save_register_device_item(device, 0, info->APU.dpcm.cur_byte);\n\tstate_save_register_device_item(device, 0, info->APU.dpcm.enabled);\n\tstate_save_register_device_item(device, 0, info->APU.dpcm.irq_occurred);\n\tstate_save_register_device_item(device, 0, info->APU.dpcm.vol);\n\n\tstate_save_register_device_item_array(device, 0, info->APU.regs);\n\n#ifdef USE_QUEUE\n\tstate_save_register_device_item_array(device, 0, info->APU.queue);\n\tstate_save_register_device_item(device, 0, info->APU.head);\n\tstate_save_register_device_item(device, 0, info->APU.tail);\n#else\n\tstate_save_register_device_item(device, 0, info->APU.buf_pos);\n\tstate_save_register_device_item(device, 0, info->APU.step_mode);\n#endif\n\t*/\n\t\n\tinfo->APU.squ[0].Muted = 0x00;\n\tinfo->APU.squ[1].Muted = 0x00;\n\tinfo->APU.tri.Muted = 0x00;\n\tinfo->APU.noi.Muted = 0x00;\n\tinfo->APU.dpcm.Muted = 0x00;\n\t\n\treturn info;\n}\n\nvoid device_stop_nesapu(void* chip)\n{\n\tnesapu_state *info = (nesapu_state*)chip;\n\t\n\tinfo->APU.dpcm.memory = NULL;\n\t\n\treturn;\n}\n\nvoid device_reset_nesapu(void* chip)\n{\n\tnesapu_state *info = (nesapu_state*)chip;\n\tconst UINT8* MemPtr;\n\tUINT8 CurReg;\n\t\n\tMemPtr = info->APU.dpcm.memory;\n\tmemset(&info->APU, 0x00, sizeof(apu_t));\n\tinfo->APU.dpcm.memory = MemPtr;\n\tapu_dpcmreset(&info->APU.dpcm);\n\t\n\tfor (CurReg = 0x00; CurReg < 0x18; CurReg ++)\n\t\tapu_write(info, CurReg, 0x00);\n\t\n\tapu_write(info, 0x15, 0x00);\n\tapu_write(info, 0x15, 0x0F);\n\t\n\treturn;\n}\n\nvoid nesapu_set_rom(void* chip, const UINT8* ROMData)\n{\n\tnesapu_state *info = (nesapu_state*)chip;\n\tinfo->APU.dpcm.memory = ROMData;\n\t\n\treturn;\n}\n\nvoid nesapu_set_mute_mask(void* chip, UINT32 MuteMask)\n{\n\tnesapu_state *info = (nesapu_state*)chip;\n\t\n\tinfo->APU.squ[0].Muted = (MuteMask >> 0) & 0x01;\n\tinfo->APU.squ[1].Muted = (MuteMask >> 1) & 0x01;\n\tinfo->APU.tri.Muted = (MuteMask >> 2) & 0x01;\n\tinfo->APU.noi.Muted = (MuteMask >> 3) & 0x01;\n\tinfo->APU.dpcm.Muted = (MuteMask >> 4) & 0x01;\n\t\n\treturn;\n}\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( nesapu )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(nesapu_state);\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( nesapu );\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"N2A03\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Nintendo custom\");\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);      \t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\");  break;\n\t}\n}\n\n\nDEFINE_LEGACY_SOUND_DEVICE(NES, nesapu);*/\n"
  },
  {
    "path": "VGMPlay/chips/nes_apu.h",
    "content": "/*****************************************************************************\n\n  MAME/MESS NES APU CORE\n\n  Based on the Nofrendo/Nosefart NES N2A03 sound emulation core written by\n  Matthew Conte (matt@conte.com) and redesigned for use in MAME/MESS by\n  Who Wants to Know? (wwtk@mail.com)\n\n  This core is written with the advise and consent of Matthew Conte and is\n  released under the GNU Public License.  This core is freely avaiable for\n  use in any freeware project, subject to the following terms:\n\n  Any modifications to this code must be duly noted in the source and\n  approved by Matthew Conte and myself prior to public submission.\n\n *****************************************************************************\n\n   NES_APU.H\n\n   NES APU external interface.\n\n *****************************************************************************/\n\n#pragma once\n\n#ifndef __NES_APU_H__\n#define __NES_APU_H__\n\n//#include \"devlegcy.h\"\n\n\n/* AN EXPLANATION\n *\n * The NES APU is actually integrated into the Nintendo processor.\n * You must supply the same number of APUs as you do processors.\n * Also make sure to correspond the memory regions to those used in the\n * processor, as each is shared.\n */\n\n/*typedef struct _nes_interface nes_interface;\nstruct _nes_interface\n{\n\tconst char *cpu_tag;  // CPU tag\n};\n\nREAD8_DEVICE_HANDLER( nes_psg_r );\nWRITE8_DEVICE_HANDLER( nes_psg_w );\n\nDECLARE_LEGACY_SOUND_DEVICE(NES, nesapu);*/\n\nUINT8 nes_psg_r(void* chip, offs_t offset);\nvoid nes_psg_w(void* chip, offs_t offset, UINT8 data);\n\nvoid nes_psg_update_sound(void* chip, stream_sample_t **outputs, int samples);\nvoid* device_start_nesapu(int clock, int rate);\nvoid device_stop_nesapu(void* chip);\nvoid device_reset_nesapu(void* chip);\n\nvoid nesapu_set_rom(void* chip, const UINT8* ROMData);\n\nvoid nesapu_set_mute_mask(void* chip, UINT32 MuteMask);\n\n#endif /* __NES_APU_H__ */\n"
  },
  {
    "path": "VGMPlay/chips/nes_defs.h",
    "content": "/*****************************************************************************\n\n  MAME/MESS NES APU CORE\n\n  Based on the Nofrendo/Nosefart NES N2A03 sound emulation core written by\n  Matthew Conte (matt@conte.com) and redesigned for use in MAME/MESS by\n  Who Wants to Know? (wwtk@mail.com)\n\n  This core is written with the advise and consent of Matthew Conte and is\n  released under the GNU Public License.  This core is freely avaiable for\n  use in any freeware project, subject to the following terms:\n\n  Any modifications to this code must be duly noted in the source and\n  approved by Matthew Conte and myself prior to public submission.\n\n *****************************************************************************\n\n   NES_DEFS.H\n\n   NES APU internal type definitions and constants.\n\n *****************************************************************************/\n\n#pragma once\n\n#ifndef __NES_DEFS_H__\n#define __NES_DEFS_H__\n\n/* BOOLEAN CONSTANTS */\n#ifndef TRUE\n#define TRUE   1\n#define FALSE  0\n#endif\n\n/* REGULAR TYPE DEFINITIONS */\ntypedef INT8          int8;\ntypedef INT16         int16;\ntypedef INT32         int32;\ntypedef UINT8         uint8;\ntypedef UINT16        uint16;\ntypedef UINT32        uint32;\ntypedef UINT8         boolean;\n\n\n/* QUEUE TYPES */\n#ifdef USE_QUEUE\n\n#define QUEUE_SIZE 0x2000\n#define QUEUE_MAX  (QUEUE_SIZE-1)\n\ntypedef struct queue_s\n{\n\tint pos;\n\tunsigned char reg,val;\n} queue_t;\n\n#endif\n\n/* REGISTER DEFINITIONS */\n#define  APU_WRA0    0x00\n#define  APU_WRA1    0x01\n#define  APU_WRA2    0x02\n#define  APU_WRA3    0x03\n#define  APU_WRB0    0x04\n#define  APU_WRB1    0x05\n#define  APU_WRB2    0x06\n#define  APU_WRB3    0x07\n#define  APU_WRC0    0x08\n#define  APU_WRC1    0x09\n#define  APU_WRC2    0x0A\n#define  APU_WRC3    0x0B\n#define  APU_WRD0    0x0C\n#define  APU_WRD2    0x0E\n#define  APU_WRD3    0x0F\n#define  APU_WRE0    0x10\n#define  APU_WRE1    0x11\n#define  APU_WRE2    0x12\n#define  APU_WRE3    0x13\n#define  APU_SMASK   0x15\n#define  APU_IRQCTRL 0x17\n\n#define  NOISE_LONG     0x4000\n#define  NOISE_SHORT    93\n\n/* CHANNEL TYPE DEFINITIONS */\n\n/* Square Wave */\ntypedef struct square_s\n{\n\tuint8 regs[4];\n\tint vbl_length;\n\tint freq;\n\tfloat phaseacc;\n\tfloat output_vol;\n\tfloat env_phase;\n\tfloat sweep_phase;\n\tuint8 adder;\n\tuint8 env_vol;\n\tboolean enabled;\n\tboolean Muted;\n} square_t;\n\n/* Triangle Wave */\ntypedef struct triangle_s\n{\n\tuint8 regs[4]; /* regs[1] unused */\n\tint linear_length;\n\tint vbl_length;\n\tint write_latency;\n\tfloat phaseacc;\n\tfloat output_vol;\n\tuint8 adder;\n\tboolean counter_started;\n\tboolean enabled;\n\tboolean Muted;\n} triangle_t;\n\n/* Noise Wave */\ntypedef struct noise_s\n{\n\tuint8 regs[4]; /* regs[1] unused */\n\tint cur_pos;\n\tint vbl_length;\n\tfloat phaseacc;\n\tfloat output_vol;\n\tfloat env_phase;\n\tuint8 env_vol;\n\tboolean enabled;\n\tboolean Muted;\n} noise_t;\n\n/* DPCM Wave */\ntypedef struct dpcm_s\n{\n\tuint8 regs[4];\n\tuint32 address;\n\tuint32 length;\n\tint bits_left;\n\tfloat phaseacc;\n\tfloat output_vol;\n\tuint8 cur_byte;\n\tboolean enabled;\n\tboolean irq_occurred;\n\t//address_space *memory;\n\tconst uint8 *memory;\n\t//signed char vol;\n\tsigned short vol;\n\tboolean Muted;\n} dpcm_t;\n\n/* APU type */\ntypedef struct apu\n{\n\t/* Sound channels */\n\tsquare_t   squ[2];\n\ttriangle_t tri;\n\tnoise_t    noi;\n\tdpcm_t     dpcm;\n\n\t/* APU registers */\n\tunsigned char regs[0x20];\n\n\t/* Sound pointers */\n\tvoid *buffer;\n\n#ifdef USE_QUEUE\n\n\t/* Event queue */\n\tqueue_t queue[QUEUE_SIZE];\n\tint head, tail;\n\n#else\n\n\tint buf_pos;\n\n#endif\n\n\tint step_mode;\n} apu_t;\n\n/* CONSTANTS */\n\n/* vblank length table used for squares, triangle, noise */\nstatic const uint8 vbl_length[32] =\n{\n   5, 127, 10, 1, 19,  2, 40,  3, 80,  4, 30,  5, 7,  6, 13,  7,\n   6,   8, 12, 9, 24, 10, 48, 11, 96, 12, 36, 13, 8, 14, 16, 15\n};\n\n/* frequency limit of square channels */\nstatic const int freq_limit[8] =\n{\n   //0x3FF, 0x555, 0x666, 0x71C, 0x787, 0x7C1, 0x7E0, 0x7F0,\n   // Fixed, thanks to Delek\n   0x3FF, 0x555, 0x666, 0x71C, 0x787, 0x7C1, 0x7E0, 0x7F2,\n};\n\n/* table of noise frequencies */\nstatic const int noise_freq[16] =\n{\n   //4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 2046\n   // Fixed, thanks to Delek\n   4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068\n};\n\n/* dpcm transfer freqs */\nstatic const int dpcm_clocks[16] =\n{\n   428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106, 85, 72, 54\n};\n\n/* ratios of pos/neg pulse for square waves */\n/* 2/16 = 12.5%, 4/16 = 25%, 8/16 = 50%, 12/16 = 75% */\nstatic const int duty_lut[4] =\n{\n   2, 4, 8, 12\n};\n\n#endif /* __NES_DEFS_H__ */\n"
  },
  {
    "path": "VGMPlay/chips/nes_intf.c",
    "content": "/****************************************************************\n\n    MAME / MESS functions\n\n****************************************************************/\n\n#include \"mamedef.h\"\n#include <stdlib.h>\t// for free\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"../stdbool.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#include \"nes_apu.h\"\n#include \"np_nes_apu.h\"\n#include \"np_nes_dmc.h\"\n#include \"np_nes_fds.h\"\n#include \"nes_intf.h\"\n\n\n#ifdef ENABLE_ALL_CORES\n#define EC_MAME\t\t0x01\t// NES core from MAME\n#endif\n#define EC_NSFPLAY\t0x00\t// NES core from NSFPlay\n// Note: FDS core from NSFPlay is always used\n\n/* for stream system */\ntypedef struct _nes_state nes_state;\nstruct _nes_state\n{\n\tvoid* chip_apu;\n\tvoid* chip_dmc;\n\tvoid* chip_fds;\n\tUINT8* Memory;\n};\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nstatic UINT8 EMU_CORE = 0x00;\n\nextern UINT32 SampleRate;\n#define MAX_CHIPS\t0x02\nstatic nes_state NESAPUData[MAX_CHIPS];\nstatic UINT16 NesOptions = 0x8000;\n\nstatic void nes_set_chip_option(UINT8 ChipID);\n\nvoid nes_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tnes_state *info = &NESAPUData[ChipID];\n\tint CurSmpl;\n\tINT32 Buffer[4];\n\t\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tnes_psg_update_sound(info->chip_apu, outputs, samples);\n\t\tbreak;\n#endif\n\tcase EC_NSFPLAY:\n\t\tfor (CurSmpl = 0x00; CurSmpl < samples; CurSmpl ++)\n\t\t{\n\t\t\tNES_APU_np_Render(info->chip_apu, &Buffer[0]);\n\t\t\tNES_DMC_np_Render(info->chip_dmc, &Buffer[2]);\n\t\t\toutputs[0][CurSmpl] = Buffer[0] + Buffer[2];\n\t\t\toutputs[1][CurSmpl] = Buffer[1] + Buffer[3];\n\t\t}\n\t\tbreak;\n\t}\n\t\n\tif (info->chip_fds != NULL)\n\t{\n\t\tfor (CurSmpl = 0x00; CurSmpl < samples; CurSmpl ++)\n\t\t{\n\t\t\tNES_FDS_Render(info->chip_fds, &Buffer[0]);\n\t\t\toutputs[0][CurSmpl] += Buffer[0];\n\t\t\toutputs[1][CurSmpl] += Buffer[1];\n\t\t}\n\t}\n\t\n\treturn;\n}\n\nint device_start_nes(UINT8 ChipID, int clock)\n{\n\tnes_state *info;\n\tint rate;\n\tUINT8 EnableFDS;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tEnableFDS = (clock >> 31) & 0x01;\n\tclock &= 0x7FFFFFFF;\n\t\n\tinfo = &NESAPUData[ChipID];\n\trate = clock / 4;\n\tif (((CHIP_SAMPLING_MODE & 0x01) && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\t\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tinfo->chip_apu = device_start_nesapu(clock, rate);\n\t\tif (info->chip_apu == NULL)\n\t\t\treturn 0;\n\t\t\n\t\tinfo->chip_dmc = NULL;\n\t\tinfo->chip_fds = NULL;\n\t\t\n\t\tinfo->Memory = (UINT8*)malloc(0x8000);\n\t\tmemset(info->Memory, 0x00, 0x8000);\n\t\tnesapu_set_rom(info->chip_apu, info->Memory - 0x8000);\n\t\tbreak;\n#endif\n\tcase EC_NSFPLAY:\n\t\tinfo->chip_apu = NES_APU_np_Create(clock, rate);\n\t\tif (info->chip_apu == NULL)\n\t\t\treturn 0;\n\t\t\n\t\tinfo->chip_dmc = NES_DMC_np_Create(clock, rate);\n\t\tif (info->chip_dmc == NULL)\n\t\t{\n\t\t\tNES_APU_np_Destroy(info->chip_apu);\n\t\t\tinfo->chip_apu = NULL;\n\t\t\treturn 0;\n\t\t}\n\t\t\n\t\tNES_DMC_np_SetAPU(info->chip_dmc, info->chip_apu);\n\t\t\n\t\tinfo->Memory = (UINT8*)malloc(0x8000);\n\t\tmemset(info->Memory, 0x00, 0x8000);\n\t\tNES_DMC_np_SetMemory(info->chip_dmc, info->Memory - 0x8000);\n\t\tbreak;\n\t}\n\t\n\tif (EnableFDS)\n\t{\n\t\tinfo->chip_fds = NES_FDS_Create(clock, rate);\n\t\t// If it returns NULL, that's okay.\n\t}\n\telse\n\t{\n\t\tinfo->chip_fds = NULL;\n\t}\n\tnes_set_chip_option(ChipID);\n\t\n\treturn rate;\n}\n\nvoid device_stop_nes(UINT8 ChipID)\n{\n\tnes_state *info = &NESAPUData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tdevice_stop_nesapu(info->chip_apu);\n\t\tbreak;\n#endif\n\tcase EC_NSFPLAY:\n\t\tNES_APU_np_Destroy(info->chip_apu);\n\t\tNES_DMC_np_Destroy(info->chip_dmc);\n\t\tbreak;\n\t}\n\tif (info->chip_fds != NULL)\n\t\tNES_FDS_Destroy(info->chip_fds);\n\t\n\tif (info->Memory != NULL)\n\t{\n\t\tfree(info->Memory);\n\t\tinfo->Memory = NULL;\n\t}\n\tinfo->chip_apu = NULL;\n\tinfo->chip_dmc = NULL;\n\tinfo->chip_fds = NULL;\n\t\n\treturn;\n}\n\nvoid device_reset_nes(UINT8 ChipID)\n{\n\tnes_state *info = &NESAPUData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tdevice_reset_nesapu(info->chip_apu);\n\t\tbreak;\n#endif\n\tcase EC_NSFPLAY:\n\t\tNES_APU_np_Reset(info->chip_apu);\n\t\tNES_DMC_np_Reset(info->chip_dmc);\n\t\tbreak;\n\t}\n\tif (info->chip_fds != NULL)\n\t\tNES_FDS_Reset(info->chip_fds);\n}\n\n\nvoid nes_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tnes_state *info = &NESAPUData[ChipID];\n\t\n\tswitch(offset & 0xE0)\n\t{\n\tcase 0x00:\t// NES APU\n\t\tswitch(EMU_CORE)\n\t\t{\n#ifdef ENABLE_ALL_CORES\n\t\tcase EC_MAME:\n\t\t\tnes_psg_w(info->chip_apu, offset, data);\n\t\t\tbreak;\n#endif\n\t\tcase EC_NSFPLAY:\n\t\t\t// NES_APU handles the sqaure waves, NES_DMC the rest\n\t\t\tNES_APU_np_Write(info->chip_apu, 0x4000 | offset, data);\n\t\t\tNES_DMC_np_Write(info->chip_dmc, 0x4000 | offset, data);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase 0x20:\t// FDS register\n\t\tif (info->chip_fds == NULL)\n\t\t\tbreak;\n\t\tif (offset == 0x3F)\n\t\t\tNES_FDS_Write(info->chip_fds, 0x4023, data);\n\t\telse\n\t\t\tNES_FDS_Write(info->chip_fds, 0x4080 | (offset & 0x1F), data);\n\t\tbreak;\n\tcase 0x40:\t// FDS wave RAM\n\tcase 0x60:\n\t\tif (info->chip_fds == NULL)\n\t\t\tbreak;\n\t\tNES_FDS_Write(info->chip_fds, 0x4000 | offset, data);\n\t\tbreak;\n\t}\n}\n\nvoid nes_write_ram(UINT8 ChipID, offs_t DataStart, offs_t DataLength, const UINT8* RAMData)\n{\n\tnes_state* info = &NESAPUData[ChipID];\n\tUINT32 RemainBytes;\n\t\n\tif (DataStart >= 0x10000)\n\t\treturn;\n\t\n\tif (DataStart < 0x8000)\n\t{\n\t\tif (DataStart + DataLength <= 0x8000)\n\t\t\treturn;\n\t\t\n\t\tRemainBytes = 0x8000 - DataStart;\n\t\tDataStart = 0x8000;\n\t\tRAMData += RemainBytes;\n\t\tDataLength -= RemainBytes;\n\t}\n\t\n\tRemainBytes = 0x00;\n\tif (DataStart + DataLength > 0x10000)\n\t{\n\t\tRemainBytes = DataLength;\n\t\tDataLength = 0x10000 - DataStart;\n\t\tRemainBytes -= DataLength;\n\t}\n\tmemcpy(info->Memory + (DataStart - 0x8000), RAMData, DataLength);\n\tif (RemainBytes)\n\t{\n\t\tif (RemainBytes > 0x8000)\n\t\t\tRemainBytes = 0x8000;\n\t\tmemcpy(info->Memory, RAMData + DataLength, RemainBytes);\n\t}\n\t\n\treturn;\n}\n\n\nvoid nes_set_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tEMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;\n#else\n\tEMU_CORE = EC_NSFPLAY;\n#endif\n\t\n\treturn;\n}\n\nvoid nes_set_options(UINT16 Options)\n{\n\tNesOptions = Options;\n\t\n\treturn;\n}\n\nstatic void nes_set_chip_option(UINT8 ChipID)\n{\n\tnes_state *info = &NESAPUData[ChipID];\n\tUINT8 CurOpt;\n\t\n\tif (NesOptions & 0x8000)\n\t\treturn;\n\t\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\t// no options for MAME's NES core\n\t\tbreak;\n#endif\n\tcase EC_NSFPLAY:\n\t\t// shared APU/DMC options\n\t\tfor (CurOpt = 0; CurOpt < 2; CurOpt ++)\n\t\t{\n\t\t\tNES_APU_np_SetOption(info->chip_apu, CurOpt, (NesOptions >> CurOpt) & 0x01);\n\t\t\tNES_DMC_np_SetOption(info->chip_dmc, CurOpt, (NesOptions >> CurOpt) & 0x01);\n\t\t}\n\t\t// APU-only options\n\t\tfor (; CurOpt < 4; CurOpt ++)\n\t\t\tNES_APU_np_SetOption(info->chip_apu, CurOpt-2+2, (NesOptions >> CurOpt) & 0x01);\n\t\t// DMC-only options\n\t\tfor (; CurOpt < 10; CurOpt ++)\n\t\t\tNES_DMC_np_SetOption(info->chip_dmc, CurOpt-4+2, (NesOptions >> CurOpt) & 0x01);\n\t\tbreak;\n\t}\n\tif (info->chip_fds != NULL)\n\t{\n\t\t// FDS options\n\t\t// I skip the Cutoff frequency here, since it's not a boolean value.\n\t\tfor (CurOpt = 12; CurOpt < 14; CurOpt ++)\n\t\t\tNES_FDS_SetOption(info->chip_fds, CurOpt-12+1, (NesOptions >> CurOpt) & 0x01);\n\t}\n\t\n\treturn;\n}\n\nvoid nes_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tnes_state *info = &NESAPUData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tnesapu_set_mute_mask(info->chip_apu, MuteMask);\n\t\tbreak;\n#endif\n\tcase EC_NSFPLAY:\n\t\tNES_APU_np_SetMask(info->chip_apu, (MuteMask & 0x03) >> 0);\n\t\tNES_DMC_np_SetMask(info->chip_dmc, (MuteMask & 0x1C) >> 2);\n\t\tbreak;\n\t}\n\tif (info->chip_fds != NULL)\n\t\tNES_FDS_SetMask(info->chip_fds, (MuteMask & 0x20) >> 5);\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/nes_intf.h",
    "content": "#pragma once\n\nvoid nes_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_nes(UINT8 ChipID, int clock);\nvoid device_stop_nes(UINT8 ChipID);\nvoid device_reset_nes(UINT8 ChipID);\n\nvoid nes_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid nes_write_ram(UINT8 ChipID, offs_t DataStart, offs_t DataLength, const UINT8* RAMData);\n\nvoid nes_set_emu_core(UINT8 Emulator);\nvoid nes_set_options(UINT16 Options);\nvoid nes_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/chips/np_nes_apu.c",
    "content": "//\n// NES 2A03\n//\n// Ported from NSFPlay 2.2 to VGMPlay (including C++ -> C conversion)\n// by Valley Bell on 24 September 2013\n// Updated to NSFPlay 2.3 on 26 September 2013\n// (Note: Encoding is UTF-8)\n\n//#include <assert.h>\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n#include \"../stdbool.h\"\n#include \"np_nes_apu.h\"\n\n\n// Master Clock: 21477272 (NTSC)\n// APU Clock = Master Clock / 12\n#define DEFAULT_CLOCK\t1789772.0\t// not sure if this shouldn't be 1789772,667 instead\n#define DEFAULT_RATE\t44100\n\n\n/** Upper half of APU **/\nenum\n{\n\tOPT_UNMUTE_ON_RESET=0,\n\tOPT_NONLINEAR_MIXER,\n\tOPT_PHASE_REFRESH,\n\tOPT_DUTY_SWAP,\n\tOPT_END\n};\n\nenum\n{\n\tSQR0_MASK = 1,\n\tSQR1_MASK = 2,\n};\n\n// Note: For increased speed, I'll inline all of NSFPlay's Counter member functions.\n#define COUNTER_SHIFT\t24\n\ntypedef struct _Counter Counter;\nstruct _Counter\n{\n\tdouble ratio;\n\tUINT32 val, step;\n};\n#define COUNTER_setcycle(cntr, s)\t(cntr).step = (UINT32)((cntr).ratio / (s + 1))\n#define COUNTER_iup(cntr)\t\t\t(cntr).val += (cntr).step\n#define COUNTER_value(cntr)\t\t\t((cntr).val >> COUNTER_SHIFT)\n#define COUNTER_init(cntr, clk, rate)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t(cntr).ratio = (1 << COUNTER_SHIFT) * (1.0 * clk / rate);\t\\\n\t(cntr).step = (UINT32)((cntr).ratio + 0.5);\t\t\t\t\t\\\n\t(cntr).val = 0;\t\t\t\t\t\t\t\t\t\t\t\t\\\n}\n\n\ntypedef struct _NES_APU NES_APU;\nstruct _NES_APU\n{\n\tint option[OPT_END];\t\t// 各種オプション\n\tint mask;\n\tINT32 sm[2][2];\n\n\tUINT32 gclock;\n\tUINT8 reg[0x20];\n\tINT32 out[2];\n\tdouble rate, clock;\n\n\tINT32 square_table[32];\t\t// nonlinear mixer\n\n\tint scounter[2];\t\t\t// frequency divider\n\tint sphase[2];\t\t\t\t// phase counter\n\n\tint duty[2];\n\tint volume[2];\n\tint freq[2];\n\tint sfreq[2];\n\n\tbool sweep_enable[2];\n\tbool sweep_mode[2];\n\tbool sweep_write[2];\n\tint sweep_div_period[2];\n\tint sweep_div[2];\n\tint sweep_amount[2];\n\n\tbool envelope_disable[2];\n\tbool envelope_loop[2];\n\tbool envelope_write[2];\n\tint envelope_div_period[2];\n\tint envelope_div[2];\n\tint envelope_counter[2];\n\n\tint length_counter[2];\n\n\tbool enable[2];\n\n\tCounter tick_count;\n\tUINT32 tick_last;\n};\n\nstatic void sweep_sqr(NES_APU* apu, int ch);\t// calculates target sweep frequency\nstatic INT32 calc_sqr(NES_APU* apu, int ch, UINT32 clocks);\nstatic void Tick(NES_APU* apu, UINT32 clocks);\n\n\nstatic void sweep_sqr(NES_APU* apu, int i)\n{\n\tint shifted = apu->freq[i] >> apu->sweep_amount[i];\n\tif (i == 0 && apu->sweep_mode[i]) shifted += 1;\n\tapu->sfreq[i] = apu->freq[i] + (apu->sweep_mode[i] ? -shifted : shifted);\n\t//DEBUG_OUT(\"shifted[%d] = %d (%d >> %d)\\n\",i,shifted,apu->freq[i],apu->sweep_amount[i]);\n}\n\nvoid NES_APU_np_FrameSequence(void* chip, int s)\n{\n\tNES_APU* apu = (NES_APU*)chip;\n\tint i;\n\n\t//DEBUG_OUT(\"FrameSequence(%d)\\n\",s);\n\n\tif (s > 3) return; // no operation in step 4\n\n\t// 240hz clock\n\tfor (i=0; i < 2; ++i)\n\t{\n\t\tbool divider = false;\n\t\tif (apu->envelope_write[i])\n\t\t{\n\t\t\tapu->envelope_write[i] = false;\n\t\t\tapu->envelope_counter[i] = 15;\n\t\t\tapu->envelope_div[i] = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t++apu->envelope_div[i];\n\t\t\tif (apu->envelope_div[i] > apu->envelope_div_period[i])\n\t\t\t{\n\t\t\t\tdivider = true;\n\t\t\t\tapu->envelope_div[i] = 0;\n\t\t\t}\n\t\t}\n\t\tif (divider)\n\t\t{\n\t\t\tif (apu->envelope_loop[i] && apu->envelope_counter[i] == 0)\n\t\t\t\tapu->envelope_counter[i] = 15;\n\t\t\telse if (apu->envelope_counter[i] > 0)\n\t\t\t\t--apu->envelope_counter[i];\n\t\t}\n\t}\n\n\t// 120hz clock\n\tif ((s&1) == 0)\n\t  for (i=0; i < 2; ++i)\n\t  {\n\t\tif (!apu->envelope_loop[i] && (apu->length_counter[i] > 0))\n\t\t\t--apu->length_counter[i];\n\n\t\tif (apu->sweep_enable[i])\n\t\t{\n\t\t\t//DEBUG_OUT(\"Clock sweep: %d\\n\", i);\n\n\t\t\t--apu->sweep_div[i];\n\t\t\tif (apu->sweep_div[i] <= 0)\n\t\t\t{\n\t\t\t\tsweep_sqr(apu, i);\t// calculate new sweep target\n\n\t\t\t\t//DEBUG_OUT(\"sweep_div[%d] (0/%d)\\n\",i,apu->sweep_div_period[i]);\n\t\t\t\t//DEBUG_OUT(\"freq[%d]=%d > sfreq[%d]=%d\\n\",i,apu->freq[i],i,apu->sfreq[i]);\n\n\t\t\t\tif (apu->freq[i] >= 8 && apu->sfreq[i] < 0x800 && apu->sweep_amount[i] > 0) // update frequency if appropriate\n\t\t\t\t{\n\t\t\t\t\tapu->freq[i] = apu->sfreq[i] < 0 ? 0 : apu->sfreq[i];\n\t\t\t\t\tif (apu->scounter[i] > apu->freq[i]) apu->scounter[i] = apu->freq[i];\n\t\t\t\t}\n\t\t\t\tapu->sweep_div[i] = apu->sweep_div_period[i] + 1;\n\n\t\t\t\t//DEBUG_OUT(\"freq[%d]=%d\\n\",i,apu->freq[i]);\n\t\t\t}\n\n\t\t\tif (apu->sweep_write[i])\n\t\t\t{\n\t\t\t\tapu->sweep_div[i] = apu->sweep_div_period[i] + 1;\n\t\t\t\tapu->sweep_write[i] = false;\n\t\t\t}\n\t\t}\n\t  }\n\n}\n\nstatic INT32 calc_sqr(NES_APU* apu, int i, UINT32 clocks)\n{\n\tstatic const INT16 sqrtbl[4][16] = {\n\t\t{0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},\n\t\t{1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}\n\t};\n\tINT32 ret = 0;\n\n\tapu->scounter[i] += clocks;\n\twhile (apu->scounter[i] > apu->freq[i])\n\t{\n\t\tapu->sphase[i] = (apu->sphase[i] + 1) & 15;\n\t\tapu->scounter[i] -= (apu->freq[i] + 1);\n\t}\n\n\t//INT32 ret = 0;\n\tif (apu->length_counter[i] > 0 &&\n\t\tapu->freq[i] >= 8 &&\n\t\tapu->sfreq[i] < 0x800\n\t\t)\n\t{\n\t\tint v = apu->envelope_disable[i] ? apu->volume[i] : apu->envelope_counter[i];\n\t\tret = sqrtbl[apu->duty[i]][apu->sphase[i]] ? v : 0;\n\t}\n\t\n\treturn ret;\n}\n\nbool NES_APU_np_Read(void* chip, UINT32 adr, UINT32* val)\n{\n\tNES_APU* apu = (NES_APU*)chip;\n\n\tif (0x4000 <= adr && adr < 0x4008)\n\t{\n\t\t*val |= apu->reg[adr&0x7];\n\t\treturn true;\n\t}\n\telse if(adr==0x4015)\n\t{\n\t\t*val |= (apu->length_counter[1]?2:0)|(apu->length_counter[0]?1:0);\n\t\treturn true;\n\t}\n\telse\n\t\treturn false;\n}\n\nstatic void Tick(NES_APU* apu, UINT32 clocks)\n{\n\tapu->out[0] = calc_sqr(apu, 0, clocks);\n\tapu->out[1] = calc_sqr(apu, 1, clocks);\n}\n\n// 生成される波形の振幅は0-8191\nUINT32 NES_APU_np_Render(void* chip, INT32 b[2])\n{\n\tNES_APU* apu = (NES_APU*)chip;\n\tINT32 m[2];\n\n\tCOUNTER_iup(apu->tick_count);\n\tTick(apu, (COUNTER_value(apu->tick_count) - apu->tick_last) & 0xFF);\n\tapu->tick_last = COUNTER_value(apu->tick_count);\n\n\tapu->out[0] = (apu->mask & 1) ? 0 : apu->out[0];\n\tapu->out[1] = (apu->mask & 2) ? 0 : apu->out[1];\n\n\tif(apu->option[OPT_NONLINEAR_MIXER])\n\t{\n\t\tINT32 voltage;\n\t\tINT32 ref;\n\t\t\n\t\tvoltage = apu->square_table[apu->out[0] + apu->out[1]];\n\t\tm[0] = apu->out[0] << 6;\n\t\tm[1] = apu->out[1] << 6;\n\t\tref = m[0] + m[1];\n\t\tif (ref > 0)\n\t\t{\n\t\t\tm[0] = (m[0] * voltage) / ref;\n\t\t\tm[1] = (m[1] * voltage) / ref;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm[0] = voltage;\n\t\t\tm[1] = voltage;\n\t\t}\n\t}\n\telse\n\t{\n\t\tm[0] = apu->out[0] << 6;\n\t\tm[1] = apu->out[1] << 6;\n\t}\n\n\t// Shifting is (x-2) to match the volume of MAME's NES APU sound core\n\tb[0]  = m[0] * apu->sm[0][0];\n\tb[0] += m[1] * apu->sm[0][1];\n\tb[0] >>= 7-2;\t// was 7, but is now 8 for bipolar square\n\n\tb[1]  = m[0] * apu->sm[1][0];\n\tb[1] += m[1] * apu->sm[1][1];\n\tb[1] >>= 7-2;\t// see above\n\n\treturn 2;\n}\n\nvoid* NES_APU_np_Create(int clock, int rate)\n{\n\tNES_APU* apu;\n\tint i, c, t;\n\n\tapu = (NES_APU*)malloc(sizeof(NES_APU));\n\tif (apu == NULL)\n\t\treturn NULL;\n\tmemset(apu, 0x00, sizeof(NES_APU));\n\n\t//NES_APU_np_SetClock(apu, DEFAULT_CLOCK);\n\t//NES_APU_np_SetRate(apu, DEFAULT_RATE);\n\tNES_APU_np_SetClock(apu, clock);\n\tNES_APU_np_SetRate(apu, rate);\n\tapu->option[OPT_UNMUTE_ON_RESET] = true;\n\tapu->option[OPT_PHASE_REFRESH] = true;\n\tapu->option[OPT_NONLINEAR_MIXER] = true;\n\tapu->option[OPT_DUTY_SWAP] = false;\n\n\tapu->square_table[0] = 0;\n\tfor(i=1;i<32;i++) \n\t\tapu->square_table[i]=(INT32)((8192.0*95.88)/(8128.0/i+100));\n\n\tfor(c=0;c<2;++c)\n\t\tfor(t=0;t<2;++t)\n\t\t\tapu->sm[c][t] = 128;\n\n\treturn apu;\n}\n\nvoid NES_APU_np_Destroy(void* chip)\n{\n\tfree(chip);\n}\n\nvoid NES_APU_np_Reset(void* chip)\n{\n\tNES_APU* apu = (NES_APU*)chip;\n\tint i;\n\tapu->gclock = 0;\n\tapu->mask = 0;\n\n\tapu->scounter[0] = 0;\n\tapu->scounter[1] = 0;\n\tapu->sphase[0] = 0;\n\tapu->sphase[0] = 0;\n\n\tapu->sweep_div[0] = 1;\n\tapu->sweep_div[1] = 1;\n\tapu->envelope_div[0] = 0;\n\tapu->envelope_div[1] = 0;\n\tapu->length_counter[0] = 0;\n\tapu->length_counter[1] = 0;\n\tapu->envelope_counter[0] = 0;\n\tapu->envelope_counter[1] = 0;\n\n\tfor (i = 0x4000; i < 0x4008; i++)\n\t\tNES_APU_np_Write(apu, i, 0);\n\n\tNES_APU_np_Write(apu, 0x4015, 0);\n\tif (apu->option[OPT_UNMUTE_ON_RESET])\n\t\tNES_APU_np_Write(apu, 0x4015, 0x0f);\n\n\tfor (i = 0; i < 2; i++)\n\t\tapu->out[i] = 0;\n\n\tNES_APU_np_SetRate(apu, apu->rate);\n}\n\nvoid NES_APU_np_SetOption(void* chip, int id, int val)\n{\n\tNES_APU* apu = (NES_APU*)chip;\n\n\tif(id<OPT_END) apu->option[id] = val;\n}\n\nvoid NES_APU_np_SetClock(void* chip, double c)\n{\n\tNES_APU* apu = (NES_APU*)chip;\n\n\tapu->clock = c;\n}\n\nvoid NES_APU_np_SetRate(void* chip, double r)\n{\n\tNES_APU* apu = (NES_APU*)chip;\n\n\tapu->rate = r ? r : DEFAULT_RATE;\n\n\tCOUNTER_init(apu->tick_count, apu->clock, apu->rate);\n\tapu->tick_last = 0;\n}\n\nvoid NES_APU_np_SetMask(void* chip, int m)\n{\n\tNES_APU* apu = (NES_APU*)chip;\n\tapu->mask = m;\n}\n\nvoid NES_APU_np_SetStereoMix(void* chip, int trk, INT16 mixl, INT16 mixr)\n{\n\tNES_APU* apu = (NES_APU*)chip;\n\n\tif (trk < 0) return;\n\tif (trk > 1) return;\n\tapu->sm[0][trk] = mixl;\n\tapu->sm[1][trk] = mixr;\n}\n\nbool NES_APU_np_Write(void* chip, UINT32 adr, UINT32 val)\n{\n\tNES_APU* apu = (NES_APU*)chip;\n\tint ch;\n\n\tstatic const UINT8 length_table[32] = {\n\t\t0x0A, 0xFE,\n\t\t0x14, 0x02,\n\t\t0x28, 0x04,\n\t\t0x50, 0x06,\n\t\t0xA0, 0x08,\n\t\t0x3C, 0x0A,\n\t\t0x0E, 0x0C,\n\t\t0x1A, 0x0E,\n\t\t0x0C, 0x10,\n\t\t0x18, 0x12,\n\t\t0x30, 0x14,\n\t\t0x60, 0x16,\n\t\t0xC0, 0x18,\n\t\t0x48, 0x1A,\n\t\t0x10, 0x1C,\n\t\t0x20, 0x1E\n\t};\n\n\tif (0x4000 <= adr && adr < 0x4008)\n\t{\n\t\t//DEBUG_OUT(\"$%04X = %02X\\n\",adr,val);\n\n\t\tadr &= 0xf;\n\t\tch = adr >> 2;\n\t\tswitch (adr)\n\t\t{\n\t\tcase 0x0:\n\t\tcase 0x4:\n\t\t\tapu->volume[ch] = val & 15;\n\t\t\tapu->envelope_disable[ch] = (val >> 4) & 1;\n\t\t\tapu->envelope_loop[ch] = (val >> 5) & 1;\n\t\t\tapu->envelope_div_period[ch] = (val & 15);\n\t\t\tapu->duty[ch] = (val >> 6) & 3;\n\t\t\tif (apu->option[OPT_DUTY_SWAP])\n\t\t\t{\n\t\t\t\tif      (apu->duty[ch] == 1) apu->duty[ch] = 2;\n\t\t\t\telse if (apu->duty[ch] == 2) apu->duty[ch] = 1;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0x1:\n\t\tcase 0x5:\n\t\t\tapu->sweep_enable[ch] = (val >> 7) & 1;\n\t\t\tapu->sweep_div_period[ch] = (((val >> 4) & 7));\n\t\t\tapu->sweep_mode[ch] = (val >> 3) & 1;\n\t\t\tapu->sweep_amount[ch] = val & 7;\n\t\t\tapu->sweep_write[ch] = true;\n\t\t\tsweep_sqr(apu, ch);\n\t\t\tbreak;\n\n\t\tcase 0x2:\n\t\tcase 0x6:\n\t\t\tapu->freq[ch] = val | (apu->freq[ch] & 0x700) ;\n\t\t\tsweep_sqr(apu, ch);\n\t\t\tif (apu->scounter[ch] > apu->freq[ch]) apu->scounter[ch] = apu->freq[ch];\n\t\t\tbreak;\n\n\t\tcase 0x3: \n\t\tcase 0x7:\n\t\t\tapu->freq[ch] = (apu->freq[ch] & 0xFF) | ((val & 0x7) << 8) ;\n\n\t\t\tif (apu->option[OPT_PHASE_REFRESH])\n\t\t\t\tapu->sphase[ch] = 0;\n\t\t\tapu->envelope_write[ch] = true;\n\t\t\tif (apu->enable[ch])\n\t\t\t{\n\t\t\t\tapu->length_counter[ch] = length_table[(val >> 3) & 0x1f];\n\t\t\t}\n\t\t\tsweep_sqr(apu, ch);\n\t\t\tif (apu->scounter[ch] > apu->freq[ch]) apu->scounter[ch] = apu->freq[ch];\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn false;\n\t\t}\n\t\tapu->reg[adr] = val;\n\t\treturn true;\n\t}\n\telse if (adr == 0x4015)\n\t{\n\t\tapu->enable[0] = (val & 1) ? true : false;\n\t\tapu->enable[1] = (val & 2) ? true : false;\n\n\t\tif (!apu->enable[0])\n\t\t\tapu->length_counter[0] = 0;\n\t\tif (!apu->enable[1])\n\t\t\tapu->length_counter[1] = 0;\n\n\t\tapu->reg[adr-0x4000] = val;\n\t\treturn true;\n\t}\n\n\t// 4017 is handled in np_nes_dmc.c\n\t//else if (adr == 0x4017)\n\t//{\n\t//}\n\n\treturn false;\n}\n"
  },
  {
    "path": "VGMPlay/chips/np_nes_apu.h",
    "content": "void NES_APU_np_FrameSequence(void* chip, int s);\nvoid* NES_APU_np_Create(int clock, int rate);\nvoid NES_APU_np_Destroy(void* chip);\nvoid NES_APU_np_Reset(void* chip);\nbool NES_APU_np_Read(void* chip, UINT32 adr, UINT32* val);\nbool NES_APU_np_Write(void* chip, UINT32 adr, UINT32 val);\nUINT32 NES_APU_np_Render(void* chip, INT32 b[2]);\nvoid NES_APU_np_SetRate(void* chip, double rate);\nvoid NES_APU_np_SetClock(void* chip, double clock);\nvoid NES_APU_np_SetOption(void* chip, int id, int b);\nvoid NES_APU_np_SetMask(void* chip, int m);\nvoid NES_APU_np_SetStereoMix(void* chip, int trk, INT16 mixl, INT16 mixr);\n"
  },
  {
    "path": "VGMPlay/chips/np_nes_dmc.c",
    "content": "// Ported from NSFPlay to VGMPlay (including C++ -> C conversion)\n// by Valley Bell on 25 September 2013\n// Updated to NSFPlay 2.3 on 26 September 2013\n// (Note: Encoding is UTF-8)\n\n#include <stdlib.h>\t// for rand\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n#include \"../stdbool.h\"\n#include \"np_nes_apu.h\"\t// for NES_APU_np_FrameSequence\n#include \"np_nes_dmc.h\"\n\n\n// Master Clock: 21477272 (NTSC)\n// APU Clock = Master Clock / 12\n#define DEFAULT_CLOCK\t1789772.0\n#define DEFAULT_CLK_PAL\t1662607\n#define DEFAULT_RATE\t44100\n\n\n/** Bottom Half of APU **/\nenum\n{\n\tOPT_UNMUTE_ON_RESET=0,\n\tOPT_NONLINEAR_MIXER,\n\tOPT_ENABLE_4011,\n\tOPT_ENABLE_PNOISE,\n\tOPT_DPCM_ANTI_CLICK,\n\tOPT_RANDOMIZE_NOISE,\n\tOPT_TRI_MUTE,\n\tOPT_TRI_NULL,\n\tOPT_END\n};\n\n\n// Note: For increased speed, I'll inline all of NSFPlay's Counter member functions.\n#define COUNTER_SHIFT\t24\n\ntypedef struct _Counter Counter;\nstruct _Counter\n{\n\tdouble ratio;\n\tUINT32 val, step;\n};\n#define COUNTER_setcycle(cntr, s)\t(cntr).step = (UINT32)((cntr).ratio / (s + 1))\n#define COUNTER_iup(cntr)\t\t\t(cntr).val += (cntr).step\n#define COUNTER_value(cntr)\t\t\t((cntr).val >> COUNTER_SHIFT)\n#define COUNTER_init(cntr, clk, rate)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t(cntr).ratio = (1 << COUNTER_SHIFT) * (1.0 * clk / rate);\t\\\n\t(cntr).step = (UINT32)((cntr).ratio + 0.5);\t\t\t\t\t\\\n\t(cntr).val = 0;\t\t\t\t\t\t\t\t\t\t\t\t\\\n}\n\n\ntypedef struct _NES_DMC NES_DMC;\nstruct _NES_DMC\n{\n\t//const int GETA_BITS;\n\t//static const UINT32 freq_table[2][16];\n\t//static const UINT32 wavlen_table[2][16];\n\tUINT32 tnd_table[2][16][16][128];\n\n\tint option[OPT_END];\n\tint mask;\n\tINT32 sm[2][3];\n\tUINT8 reg[0x10];\n\tUINT32 len_reg;\n\tUINT32 adr_reg;\n\t//IDevice *memory;\n\tconst UINT8* memory;\n\tUINT32 out[3];\n\tUINT32 daddress;\n\tUINT32 length;\n\tUINT32 data;\n\tINT16 damp;\n\tint dac_lsb;\n\tbool dmc_pop;\n\tINT32 dmc_pop_offset;\n\tINT32 dmc_pop_follow;\n\tUINT32 clock;\n\tUINT32 rate;\n\tint pal;\n\tint mode;\n\tbool irq;\n\tbool active;\n\n\tUINT32 counter[3];\t// frequency dividers\n\tint tphase;\t\t\t// triangle phase\n\tUINT32 nfreq;\t\t// noise frequency\n\tUINT32 dfreq;\t\t// DPCM frequency\n\n\tUINT32 tri_freq;\n\tint linear_counter;\n\tint linear_counter_reload;\n\tbool linear_counter_halt;\n\tbool linear_counter_control;\n\n\tint noise_volume;\n\tUINT32 noise, noise_tap;\n\n\t// noise envelope\n\tbool envelope_loop;\n\tbool envelope_disable;\n\tbool envelope_write;\n\tint envelope_div_period;\n\tint envelope_div;\n\tint envelope_counter;\n\n\tbool enable[3];\n\tint length_counter[2];\t// 0=tri, 1=noise\n\n\t// frame sequencer\n\tvoid* apu;\t// apu is clocked by DMC's frame sequencer\n\tint frame_sequence_count;\t// current cycle count\n\tint frame_sequence_length;\t// CPU cycles per FrameSequence\n\tint frame_sequence_step;\t// current step of frame sequence\n\tint frame_sequence_steps;\t// 4/5 steps per frame\n\tbool frame_irq;\n\tbool frame_irq_enable;\n\n\tCounter tick_count;\n\tUINT32 tick_last;\n};\n\nINLINE UINT32 calc_tri(NES_DMC* dmc, UINT32 clocks);\nINLINE UINT32 calc_dmc(NES_DMC* dmc, UINT32 clocks);\nINLINE UINT32 calc_noise(NES_DMC* dmc, UINT32 clocks);\nstatic void FrameSequence(NES_DMC* dmc, int s);\nstatic void TickFrameSequence(NES_DMC* dmc, UINT32 clocks);\nstatic void Tick(NES_DMC* dmc, UINT32 clocks);\n\n#define GETA_BITS\t20\nstatic const UINT32 wavlen_table[2][16] = {\n{\t// NTSC\n\t4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068\n},\n{\t// PAL\n\t4, 8, 14, 30, 60, 88, 118, 148, 188, 236, 354, 472, 708,  944, 1890, 3778\n}};\n\nstatic const UINT32 freq_table[2][16] = {\n{\t// NTSC\n\t428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106,  84,  72,  54\n},\n{\t// PAL\n\t398, 354, 316, 298, 276, 236, 210, 198, 176, 148, 132, 118,  98,  78,  66,  50\n}};\n\nvoid* NES_DMC_np_Create(int clock, int rate)\n{\n\tNES_DMC* dmc;\n\tint c, t;\n\n\tdmc = (NES_DMC*)malloc(sizeof(NES_DMC));\n\tif (dmc == NULL)\n\t\treturn NULL;\n\tmemset(dmc, 0x00, sizeof(NES_DMC));\n\n\t//NES_DMC_np_SetClock(dmc, DEFAULT_CLOCK);\n\t//NES_DMC_np_SetRate(dmc, DEFAULT_RATE);\n\t//NES_DMC_np_SetPal(dmc, false);\n\tNES_DMC_np_SetClock(dmc, clock);\t// does SetPal, too\n\tNES_DMC_np_SetRate(dmc, rate);\n\tdmc->option[OPT_ENABLE_4011] = 1;\n\tdmc->option[OPT_ENABLE_PNOISE] = 1;\n\tdmc->option[OPT_UNMUTE_ON_RESET] = 1;\n\tdmc->option[OPT_DPCM_ANTI_CLICK] = 0;\n\tdmc->option[OPT_NONLINEAR_MIXER] = 1;\n\tdmc->option[OPT_RANDOMIZE_NOISE] = 1;\n\tdmc->option[OPT_TRI_MUTE] = 1;\n\tdmc->tnd_table[0][0][0][0] = 0;\n\tdmc->tnd_table[1][0][0][0] = 0;\n\n\tdmc->apu = NULL;\n\tdmc->frame_sequence_count = 0;\n\tdmc->frame_sequence_length = 7458;\n\tdmc->frame_sequence_steps = 4;\n\n\tfor(c=0;c<2;++c)\n\t\tfor(t=0;t<3;++t)\n\t\t\tdmc->sm[c][t] = 128;\n\n\treturn dmc;\n}\n\n\nvoid NES_DMC_np_Destroy(void* chip)\n{\n\tfree(chip);\n}\n\nint NES_DMC_np_GetDamp(void* chip)\n{\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\n\treturn (dmc->damp<<1)|dmc->dac_lsb;\n}\n\nvoid NES_DMC_np_SetMask(void* chip, int m)\n{\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\n\tdmc->mask = m;\n}\n\nvoid NES_DMC_np_SetStereoMix(void* chip, int trk, INT16 mixl, INT16 mixr)\n{\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\n\tif (trk < 0) return;\n\tif (trk > 2) return;\n\tdmc->sm[0][trk] = mixl;\n\tdmc->sm[1][trk] = mixr;\n}\n\nstatic void FrameSequence(NES_DMC* dmc, int s)\n{\n\t//DEBUG_OUT(\"FrameSequence: %d\\n\",s);\n\n\tif (s > 3) return;\t// no operation in step 4\n\n\tif (dmc->apu != NULL)\n\t{\n\t\tNES_APU_np_FrameSequence(dmc->apu, s);\n\t}\n\n\tif (s == 0 && (dmc->frame_sequence_steps == 4))\n\t{\n\t\tdmc->frame_irq = true;\n\t}\n\n\t// 240hz clock\n\t{\n\t\tbool divider = false;\n\t\t\n\t\t// triangle linear counter\n\t\tif (dmc->linear_counter_halt)\n\t\t{\n\t\t\tdmc->linear_counter = dmc->linear_counter_reload;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (dmc->linear_counter > 0) --dmc->linear_counter;\n\t\t}\n\t\tif (!dmc->linear_counter_control)\n\t\t{\n\t\t\tdmc->linear_counter_halt = false;\n\t\t}\n\n\t\t// noise envelope\n\t\t//bool divider = false;\n\t\tif (dmc->envelope_write)\n\t\t{\n\t\t\tdmc->envelope_write = false;\n\t\t\tdmc->envelope_counter = 15;\n\t\t\tdmc->envelope_div = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t++dmc->envelope_div;\n\t\t\tif (dmc->envelope_div > dmc->envelope_div_period)\n\t\t\t{\n\t\t\t\tdivider = true;\n\t\t\t\tdmc->envelope_div = 0;\n\t\t\t}\n\t\t}\n\t\tif (divider)\n\t\t{\n\t\t\tif (dmc->envelope_loop && dmc->envelope_counter == 0)\n\t\t\t\tdmc->envelope_counter = 15;\n\t\t\telse if (dmc->envelope_counter > 0)\n\t\t\t\t--dmc->envelope_counter;\t// TODO: Make this work.\n\t\t}\n\t}\n\n\t// 120hz clock\n\tif ((s&1) == 0)\n\t{\n\t\t// triangle length counter\n\t\tif (!dmc->linear_counter_control && (dmc->length_counter[0] > 0))\n\t\t\t--dmc->length_counter[0];\n\n\t\t// noise length counter\n\t\tif (!dmc->envelope_loop && (dmc->length_counter[1] > 0))\n\t\t\t--dmc->length_counter[1];\n\t}\n\n}\n\n// 三角波チャンネルの計算 戻り値は0-15\nUINT32 calc_tri(NES_DMC* dmc, UINT32 clocks)\n{\n\tstatic UINT32 tritbl[32] = \n\t{\n\t  0, 1, 2, 3, 4, 5, 6, 7,\n\t  8, 9,10,11,12,13,14,15,\n\t 15,14,13,12,11,10, 9, 8,\n\t  7, 6, 5, 4, 3, 2, 1, 0\n\t};\n\n\tif (dmc->linear_counter > 0 && dmc->length_counter[0] > 0\n\t\t&& (!dmc->option[OPT_TRI_MUTE] || dmc->tri_freq > 0))\n\t{\n\t\tdmc->counter[0] += clocks;\n\t\twhile (dmc->counter[0] > dmc->tri_freq)\n\t\t{\n\t\t\tdmc->tphase = (dmc->tphase + 1) & 31;\n\t\t\tdmc->counter[0] -= (dmc->tri_freq + 1);\n\t\t}\n\t}\n\t// Note: else-block added by VB\n\telse if (dmc->option[OPT_TRI_NULL])\n\t{\n\t\tif (dmc->tphase && dmc->tphase < 31)\n\t\t{\n\t\t\t// Finish the Triangle wave to prevent clicks.\n\t\t\tdmc->counter[0] += clocks;\n\t\t\twhile(dmc->counter[0] > dmc->tri_freq && dmc->tphase)\n\t\t\t{\n\t\t\t\tdmc->tphase = (dmc->tphase + 1) & 31;\n\t\t\t\tdmc->counter[0] -= (dmc->tri_freq + 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t//UINT32 ret = tritbl[tphase];\n\t//return ret;\n\treturn tritbl[dmc->tphase];\n}\n\n// ノイズチャンネルの計算 戻り値は0-127\n// 低サンプリングレートで合成するとエイリアスノイズが激しいので\n// ノイズだけはこの関数内で高クロック合成し、簡易なサンプリングレート\n// 変換を行っている。\nUINT32 calc_noise(NES_DMC* dmc, UINT32 clocks)\n{\n\tUINT32 env, last, count, accum, clocks_accum;\n\t\n\tenv = dmc->envelope_disable ? dmc->noise_volume : dmc->envelope_counter;\n\tif (dmc->length_counter[1] < 1) env = 0;\n\n\tlast = (dmc->noise & 0x4000) ? env : 0;\n\tif (clocks < 1) return last;\n\n\t// simple anti-aliasing (noise requires it, even when oversampling is off)\n\tcount = 0;\n\taccum = 0;\n\n\tdmc->counter[1] += clocks;\n//\tassert(dmc->nfreq > 0);\t// prevent infinite loop\n\tif (dmc->nfreq <= 0)\t// prevent infinite loop -VB\n\t\treturn last;\n\twhile (dmc->counter[1] >= dmc->nfreq)\n\t{\n\t\t// tick the noise generator\n\t\tUINT32 feedback = (dmc->noise&1) ^ ((dmc->noise&dmc->noise_tap)?1:0);\n\t\tdmc->noise = (dmc->noise>>1) | (feedback<<14);\n\n\t\t++count;\n\t\taccum += last;\n\t\tlast = (dmc->noise & 0x4000) ? env : 0;\n\n\t\tdmc->counter[1] -= dmc->nfreq;\n\t}\n\n\tif (count < 1) // no change over interval, don't anti-alias\n\t{\n\t\treturn last;\n\t}\n\n\tclocks_accum = clocks - dmc->counter[1];\n\t// count = number of samples in accum\n\t// counter[1] = number of clocks since last sample\n\n\taccum = (accum * clocks_accum) + (last * dmc->counter[1] * count);\n\t// note accum as an average is already premultiplied by count\n\n\treturn accum / (clocks * count);\n}\n\n// DMCチャンネルの計算 戻り値は0-127\nUINT32 calc_dmc(NES_DMC* dmc, UINT32 clocks)\n{\n\tdmc->counter[2] += clocks;\n//\tassert(dmc->dfreq > 0);\t// prevent infinite loop\n\tif (dmc->dfreq <= 0)\t// prevent infinite loop -VB\n\t\treturn (dmc->damp<<1) + dmc->dac_lsb;\n\twhile (dmc->counter[2] >= dmc->dfreq)\n\t{\n\t\tif ( dmc->data != 0x100 )\t// data = 0x100 は EMPTY を意味する。\n\t\t{\n\t\t\tif ((dmc->data & 1) && (dmc->damp < 63))\n\t\t\t\tdmc->damp++;\n\t\t\telse if (!(dmc->data & 1) && (0 < dmc->damp))\n\t\t\t\tdmc->damp--;\n\t\t\tdmc->data >>=1;\n\t\t}\n\n\t\tif ( dmc->data == 0x100 && dmc->active )\n\t\t{\n\t\t\t//dmc->memory->Read(dmc->daddress, dmc->data);\n\t\t\tdmc->data = dmc->memory[dmc->daddress];\n\t\t\tdmc->data |= (dmc->data&0xFF)|0x10000;\t// 8bitシフトで 0x100 になる\n\t\t\tif ( dmc->length > 0 ) \n\t\t\t{\n\t\t\t\tdmc->daddress = ((dmc->daddress+1)&0xFFFF)|0x8000 ;\n\t\t\t\tdmc->length --;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif ( dmc->length == 0 )\t// 最後のフェッチが終了したら(再生完了より前に)即座に終端処理\n\t\t{\n\t\t\tif (dmc->mode & 1)\n\t\t\t{\n\t\t\t\tdmc->daddress = ((dmc->adr_reg<<6)|0xC000);\n\t\t\t\tdmc->length = (dmc->len_reg<<4)+1;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdmc->irq = (dmc->mode==2&&dmc->active)?1:0;\t// 直前がactiveだったときはIRQ発行\n\t\t\t\tdmc->active = false;\n\t\t\t}\n\t\t}\n\n\t\tdmc->counter[2] -= dmc->dfreq;\n\t}\n\n\treturn (dmc->damp<<1) + dmc->dac_lsb;\n}\n\nstatic void TickFrameSequence(NES_DMC* dmc, UINT32 clocks)\n{\n\tdmc->frame_sequence_count += clocks;\n\twhile (dmc->frame_sequence_count > dmc->frame_sequence_length)\n\t{\n\t\tFrameSequence(dmc, dmc->frame_sequence_step);\n\t\tdmc->frame_sequence_count -= dmc->frame_sequence_length;\n\t\t++dmc->frame_sequence_step;\n\t\tif(dmc->frame_sequence_step >= dmc->frame_sequence_steps)\n\t\t\tdmc->frame_sequence_step = 0;\n\t}\n}\n\nstatic void Tick(NES_DMC* dmc, UINT32 clocks)\n{\n\tdmc->out[0] = calc_tri(dmc, clocks);\n\tdmc->out[1] = calc_noise(dmc, clocks);\n\tdmc->out[2] = calc_dmc(dmc, clocks);\n}\n\nUINT32 NES_DMC_np_Render(void* chip, INT32 b[2])\n{\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\tUINT32 clocks;\n\tINT32 m[3];\n\n\tCOUNTER_iup(dmc->tick_count);\t// increase counter (overflows after 255)\n\tclocks = (COUNTER_value(dmc->tick_count) - dmc->tick_last) & 0xFF;\n\tTickFrameSequence(dmc, clocks);\n\tTick(dmc, clocks);\n\tdmc->tick_last = COUNTER_value(dmc->tick_count);\n\n\tdmc->out[0] = (dmc->mask & 1) ? 0 : dmc->out[0];\n\tdmc->out[1] = (dmc->mask & 2) ? 0 : dmc->out[1];\n\tdmc->out[2] = (dmc->mask & 4) ? 0 : dmc->out[2];\n\n\tm[0] = dmc->tnd_table[0][dmc->out[0]][0][0];\n\tm[1] = dmc->tnd_table[0][0][dmc->out[1]][0];\n\tm[2] = dmc->tnd_table[0][0][0][dmc->out[2]];\n\n\tif (dmc->option[OPT_NONLINEAR_MIXER])\n\t{\n\t\tINT32 ref = m[0] + m[1] + m[2];\n\t\tINT32 voltage = dmc->tnd_table[1][dmc->out[0]][dmc->out[1]][dmc->out[2]];\n\t\tint i;\n\t\tif (ref)\n\t\t{\n\t\t\tfor (i=0; i < 3; ++i)\n\t\t\t\tm[i] = (m[i] * voltage) / ref;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (i=0; i < 3; ++i)\n\t\t\t\tm[i] = voltage;\n\t\t}\n\t}\n\n\t// anti-click nullifies any 4011 write but preserves nonlinearity\n\tif (dmc->option[OPT_DPCM_ANTI_CLICK])\n\t{\n\t\tif (dmc->dmc_pop) // $4011 will cause pop this frame\n\t\t{\n\t\t\t// adjust offset to counteract pop\n\t\t\tdmc->dmc_pop_offset += dmc->dmc_pop_follow - m[2];\n\t\t\tdmc->dmc_pop = false;\n\n\t\t\t// prevent overflow, keep headspace at edges\n\t\t\t//const INT32 OFFSET_MAX = (1 << 30) - (4 << 16);\n#define OFFSET_MAX\t((1 << 30) - (4 << 16))\n\t\t\tif (dmc->dmc_pop_offset >  OFFSET_MAX) dmc->dmc_pop_offset =  OFFSET_MAX;\n\t\t\tif (dmc->dmc_pop_offset < -OFFSET_MAX) dmc->dmc_pop_offset = -OFFSET_MAX;\n\t\t}\n\t\tdmc->dmc_pop_follow = m[2]; // remember previous position\n\n\t\tm[2] += dmc->dmc_pop_offset; // apply offset\n\n\t\t// TODO implement this in a better way\n\t\t// roll off offset (not ideal, but prevents overflow)\n\t\tif (dmc->dmc_pop_offset > 0) --dmc->dmc_pop_offset;\n\t\telse if (dmc->dmc_pop_offset < 0) ++dmc->dmc_pop_offset;\n\t}\n\n\tb[0]  = m[0] * dmc->sm[0][0];\n\tb[0] += m[1] * dmc->sm[0][1];\n\tb[0] +=-m[2] * dmc->sm[0][2];\n\tb[0] >>= 7-2;\n\n\tb[1]  = m[0] * dmc->sm[1][0];\n\tb[1] += m[1] * dmc->sm[1][1];\n\tb[1] +=-m[2] * dmc->sm[1][2];\n\tb[1] >>= 7-2;\n\n\treturn 2;\n}\n\n\nvoid NES_DMC_np_SetClock(void* chip, double c)\n{\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\n\tdmc->clock = (UINT32)(c);\n\t\n\tif (abs(dmc->clock - DEFAULT_CLK_PAL) <= 1000)\t// check for approximately DEFAULT_CLK_PAL\n\t\tNES_DMC_np_SetPal(dmc, true);\n\telse\n\t\tNES_DMC_np_SetPal(dmc, false);\n}\n\nvoid NES_DMC_np_SetRate(void* chip, double r)\n{\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\n\tdmc->rate = (UINT32)(r?r:DEFAULT_RATE);\n\n\tCOUNTER_init(dmc->tick_count, dmc->clock, dmc->rate);\n\tdmc->tick_last = 0;\n}\n\nvoid NES_DMC_np_SetPal(void* chip, bool is_pal)\n{\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\n\tdmc->pal = (is_pal ? 1 : 0);\n\t// set CPU cycles in frame_sequence\n\tdmc->frame_sequence_length = is_pal ? 8314 : 7458;\n}\n\nvoid NES_DMC_np_SetAPU(void* chip, void* apu_)\n{\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\n\tdmc->apu = apu_;\n}\n\n// Initializing TRI, NOISE, DPCM mixing table\nstatic void InitializeTNDTable(NES_DMC* dmc, double wt, double wn, double wd)\n{\n\t// volume adjusted by 0.75 based on empirical measurements\n\tconst double MASTER = 8192.0 * 0.75;\n\t// truthfully, the nonlinear curve does not appear to match well\n\t// with my tests, triangle in particular seems too quiet relatively.\n\t// do more testing of the APU/DMC DAC later\n\n\tint t, n, d;\n\n\t{\t// Linear Mixer\n\t\tfor(t=0; t<16 ; t++) {\n\t\t\tfor(n=0; n<16; n++) {\n\t\t\t\tfor(d=0; d<128; d++) {\n\t\t\t\t\t\tdmc->tnd_table[0][t][n][d] = (UINT32)(MASTER*(3.0*t+2.0*n+d)/208.0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t{\t// Non-Linear Mixer\n\t\tdmc->tnd_table[1][0][0][0] = 0;\n\t\tfor(t=0; t<16 ; t++) {\n\t\t\tfor(n=0; n<16; n++) {\n\t\t\t\tfor(d=0; d<128; d++) {\n\t\t\t\t\tif(t!=0||n!=0||d!=0)\n\t\t\t\t\t\tdmc->tnd_table[1][t][n][d] = (UINT32)((MASTER*159.79)/(100.0+1.0/((double)t/wt+(double)n/wn+(double)d/wd)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n}\n\nvoid NES_DMC_np_Reset(void* chip)\n{\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\tint i;\n\tdmc->mask = 0;\n\n\tInitializeTNDTable(dmc,8227,12241,22638);\n\n\tdmc->counter[0] = 0;\n\tdmc->counter[1] = 0;\n\tdmc->counter[2] = 0;\n\tdmc->tphase = 0;\n\tdmc->nfreq = wavlen_table[0][0];\n\tdmc->dfreq = freq_table[0][0];\n\n\tdmc->envelope_div = 0;\n\tdmc->length_counter[0] = 0;\n\tdmc->length_counter[1] = 0;\n\tdmc->linear_counter = 0;\n\tdmc->envelope_counter = 0;\n\n\tdmc->frame_irq = false;\n\tdmc->frame_irq_enable = false;\n\tdmc->frame_sequence_count = 0;\n\tdmc->frame_sequence_steps = 4;\n\tdmc->frame_sequence_step = 0;\n\n\tfor (i = 0; i < 0x10; i++)\n\t\tNES_DMC_np_Write(dmc, 0x4008 + i, 0);\n\n\tdmc->irq = false;\n\tNES_DMC_np_Write(dmc, 0x4015, 0x00);\n\tif (dmc->option[OPT_UNMUTE_ON_RESET])\n\t\tNES_DMC_np_Write(dmc, 0x4015, 0x0f);\n\n\tdmc->out[0] = dmc->out[1] = dmc->out[2] = 0;\n\tdmc->tri_freq = 0;\n\tdmc->damp = 0;\n\tdmc->dmc_pop = false;\n\tdmc->dmc_pop_offset = 0;\n\tdmc->dmc_pop_follow = 0;\n\tdmc->dac_lsb = 0;\n\tdmc->data = 0x100;\n\tdmc->adr_reg = 0;\n\tdmc->active = false;\n\tdmc->length = 0;\n\tdmc->len_reg = 0;\n\tdmc->daddress = 0;\n\tdmc->noise = 1;\n\tdmc->noise_tap = (1<<1);\n\tif (dmc->option[OPT_RANDOMIZE_NOISE])\n\t{\n\t\tdmc->noise |= rand();\n\t}\n\n\tNES_DMC_np_SetRate(dmc, dmc->rate);\n}\n\nvoid NES_DMC_np_SetMemory(void* chip, const UINT8* r)\n{\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\n\tdmc->memory = r;\n}\n\nvoid NES_DMC_np_SetOption(void* chip, int id, int val)\n{\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\n\tif(id<OPT_END)\n\t{\n\t\tdmc->option[id] = val;\n\t\tif(id==OPT_NONLINEAR_MIXER)\n\t\t\tInitializeTNDTable(dmc, 8227,12241,22638);\n\t}\n}\n\nbool NES_DMC_np_Write(void* chip, UINT32 adr, UINT32 val)\n{\n\tstatic const UINT8 length_table[32] = {\n\t\t0x0A, 0xFE,\n\t\t0x14, 0x02,\n\t\t0x28, 0x04,\n\t\t0x50, 0x06,\n\t\t0xA0, 0x08,\n\t\t0x3C, 0x0A,\n\t\t0x0E, 0x0C,\n\t\t0x1A, 0x0E,\n\t\t0x0C, 0x10,\n\t\t0x18, 0x12,\n\t\t0x30, 0x14,\n\t\t0x60, 0x16,\n\t\t0xC0, 0x18,\n\t\t0x48, 0x1A,\n\t\t0x10, 0x1C,\n\t\t0x20, 0x1E\n\t};\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\n\tif (adr == 0x4015)\n\t{\n\t\tdmc->enable[0] = (val & 4) ? true : false;\n\t\tdmc->enable[1] = (val & 8) ? true : false;\n\n\t\tif (!dmc->enable[0])\n\t\t{\n\t\t\tdmc->length_counter[0] = 0;\n\t\t}\n\t\tif (!dmc->enable[1])\n\t\t{\n\t\t\tdmc->length_counter[1] = 0;\n\t\t}\n\n\t\tif ((val & 16)&&!dmc->active)\n\t\t{\n\t\t\tdmc->enable[2] = dmc->active = true;\n\t\t\tdmc->daddress = (0xC000 | (dmc->adr_reg << 6));\n\t\t\tdmc->length = (dmc->len_reg << 4) + 1;\n\t\t\tdmc->irq = 0;\n\t\t}\n\t\telse if (!(val & 16))\n\t\t{\n\t\t\tdmc->enable[2] = dmc->active = false;\n\t\t}\n\n\t\tdmc->reg[adr-0x4008] = val;\n\t\treturn true;\n\t}\n\n\tif (adr == 0x4017)\n\t{\n\t\t//DEBUG_OUT(\"4017 = %02X\\n\", val);\n\t\tdmc->frame_irq_enable = ((val & 0x40) == 0x40);\n\t\tdmc->frame_irq = (dmc->frame_irq_enable ? dmc->frame_irq : 0);\n\t\tdmc->frame_sequence_count = 0;\n\t\tif (val & 0x80)\n\t\t{\n\t\t\tdmc->frame_sequence_steps = 5;\n\t\t\tdmc->frame_sequence_step = 0;\n\t\t\tFrameSequence(dmc, dmc->frame_sequence_step);\n\t\t\t++dmc->frame_sequence_step;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdmc->frame_sequence_steps = 4;\n\t\t\tdmc->frame_sequence_step = 1;\n\t\t}\n\t}\n\n\tif (adr<0x4008||0x4013<adr)\n\t\treturn false;\n\n\tdmc->reg[adr-0x4008] = val&0xff;\n\n\t//DEBUG_OUT(\"$%04X %02X\\n\", adr, val);\n\n\tswitch (adr)\n\t{\n\n\t// tri\n\n\tcase 0x4008:\n\t\tdmc->linear_counter_control = (val >> 7) & 1;\n\t\tdmc->linear_counter_reload = val & 0x7F;\n\t\tbreak;\n\n\tcase 0x4009:\n\t\tbreak;\n\n\tcase 0x400a:\n\t\tdmc->tri_freq = val | (dmc->tri_freq & 0x700) ;\n\t\tif (dmc->counter[0] > dmc->tri_freq) dmc->counter[0] = dmc->tri_freq;\n\t\tbreak;\n\n\tcase 0x400b:\n\t\tdmc->tri_freq = (dmc->tri_freq & 0xff) | ((val & 0x7) << 8) ;\n\t\tif (dmc->counter[0] > dmc->tri_freq) dmc->counter[0] = dmc->tri_freq;\n\t\tdmc->linear_counter_halt = true;\n\t\tif (dmc->enable[0])\n\t\t{\n\t\t\tdmc->length_counter[0] = length_table[(val >> 3) & 0x1f];\n\t\t}\n\t\tbreak;\n\n\t// noise\n\n\tcase 0x400c:\n\t\tdmc->noise_volume = val & 15;\n\t\tdmc->envelope_div_period = val & 15;\n\t\tdmc->envelope_disable = (val >> 4) & 1;\n\t\tdmc->envelope_loop = (val >> 5) & 1;\n\t\tbreak;\n\n\tcase 0x400d:\n\t\tbreak;\n\n\tcase 0x400e:\n\t\tif (dmc->option[OPT_ENABLE_PNOISE])\n\t\t\tdmc->noise_tap = (val & 0x80) ? (1<<6) : (1<<1);\n\t\telse\n\t\t\tdmc->noise_tap = (1<<1);\n\t\tdmc->nfreq = wavlen_table[dmc->pal][val&15];\n\t\tif (dmc->counter[1] > dmc->nfreq) dmc->counter[1] = dmc->nfreq;\n\t\tbreak;\n\n\tcase 0x400f:\n\t\tif (dmc->enable[1])\n\t\t{\n\t\t\tdmc->length_counter[1] = length_table[(val >> 3) & 0x1f];\n\t\t}\n\t\tdmc->envelope_write = true;\n\t\tbreak;\n\n\t// dmc\n\n\tcase 0x4010:\n\t\tdmc->mode = (val >> 6) & 3;\n\t\tdmc->dfreq = freq_table[dmc->pal][val&15];\n\t\tif (dmc->counter[2] > dmc->dfreq) dmc->counter[2] = dmc->dfreq;\n\t\tbreak;\n\n\tcase 0x4011:\n\t\tif (dmc->option[OPT_ENABLE_4011])\n\t\t{\n\t\t\tdmc->damp = (val >> 1) & 0x3f;\n\t\t\tdmc->dac_lsb = val & 1;\n\t\t\tdmc->dmc_pop = true;\n\t\t}\n\t\tbreak;\n\n\tcase 0x4012:\n\t\tdmc->adr_reg = val&0xff;\n\t\t// ここでdaddressは更新されない\n\t\tbreak;\n\n\tcase 0x4013:\n\t\tdmc->len_reg = val&0xff;\n\t\t// ここでlengthは更新されない\n\t\tbreak;\n\n\tdefault:\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nbool NES_DMC_np_Read(void* chip, UINT32 adr, UINT32* val)\n{\n\tNES_DMC* dmc = (NES_DMC*)chip;\n\n\tif (adr == 0x4015)\n\t{\n\t\t*val |= (dmc->irq?128:0)\n\t\t\t | (dmc->frame_irq ? 0x40 : 0)\n\t\t\t | (dmc->active?16:0)\n\t\t\t | (dmc->length_counter[1]?8:0)\n\t\t\t | (dmc->length_counter[0]?4:0)\n\t\t\t ;\n\n\t\tdmc->frame_irq = false;\n\t\treturn true;\n\t}\n\telse if (0x4008<=adr&&adr<=0x4014)\n\t{\n\t\t*val |= dmc->reg[adr-0x4008];\n\t\treturn true;\n\t}\n\telse\n\t\treturn false;\n}\n"
  },
  {
    "path": "VGMPlay/chips/np_nes_dmc.h",
    "content": "#ifndef _NP_NES_DMC_H_\n#define _NP_NES_DMC_H_\n\nvoid* NES_DMC_np_Create(int clock, int rate);\nvoid NES_DMC_np_Destroy(void *chip);\nvoid NES_DMC_np_Reset(void *chip);\nvoid NES_DMC_np_SetRate(void* chip, double rate);\nvoid NES_DMC_np_SetPal(void* chip, bool is_pal);\nvoid NES_DMC_np_SetAPU(void* chip, void* apu_);\nUINT32 NES_DMC_np_Render(void* chip, INT32 b[2]);\nvoid NES_DMC_np_SetMemory(void* chip, const UINT8* r);\nbool NES_DMC_np_Write(void* chip, UINT32 adr, UINT32 val);\nbool NES_DMC_np_Read(void* chip, UINT32 adr, UINT32* val);\nvoid NES_DMC_np_SetClock(void* chip, double rate);\nvoid NES_DMC_np_SetOption(void* chip, int id, int val);\nint NES_DMC_np_GetDamp(void* chip);\nvoid NES_DMC_np_SetMask(void* chip, int m);\nvoid NES_DMC_np_SetStereoMix(void* chip, int trk, INT16 mixl, INT16 mixr);\n\n#endif\t// _NP_NES_DMC_H_\n"
  },
  {
    "path": "VGMPlay/chips/np_nes_fds.c",
    "content": "// Ported from NSFPlay 2.3 to VGMPlay (including C++ -> C conversion)\n// by Valley Bell on 26 September 2013\n\n#include <stdlib.h>\t// for rand, malloc\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include <math.h>\t// for exp\n#include \"mamedef.h\"\n#include \"../stdbool.h\"\n#include \"np_nes_fds.h\"\n\n\n#define DEFAULT_CLOCK\t1789772.0\n#define DEFAULT_RATE\t44100\n\n\nenum\n{\n\tOPT_CUTOFF=0,\n\tOPT_4085_RESET,\n\tOPT_WRITE_PROTECT,\n\tOPT_END\n};\n\nenum\n{\n\tEMOD=0,\n\tEVOL=1\n};\n\n//const int RC_BITS = 12;\n#define RC_BITS\t\t12\n\nenum\n{\n\tTMOD=0,\n\tTWAV=1\n};\n\n\n// 8 bit approximation of master volume\n#define MASTER_VOL\t(2.4 * 1223.0)\t// max FDS vol vs max APU square (arbitrarily 1223)\n#define\tMAX_OUT\t\t(32.0 * 63.0)\t// value that should map to master vol\nstatic const INT32 MASTER[4] = {\n\t(INT32)((MASTER_VOL / MAX_OUT) * 256.0 * 2.0f / 2.0f),\n\t(INT32)((MASTER_VOL / MAX_OUT) * 256.0 * 2.0f / 3.0f),\n\t(INT32)((MASTER_VOL / MAX_OUT) * 256.0 * 2.0f / 4.0f),\n\t(INT32)((MASTER_VOL / MAX_OUT) * 256.0 * 2.0f / 5.0f) };\n\n\n// Although they were pretty much removed from any sound core in NSFPlay 2.3,\n// I find this counter structure very useful.\n#define COUNTER_SHIFT\t24\n\ntypedef struct _Counter Counter;\nstruct _Counter\n{\n\tdouble ratio;\n\tUINT32 val, step;\n};\n#define COUNTER_setcycle(cntr, s)\t(cntr).step = (UINT32)((cntr).ratio / (s + 1))\n#define COUNTER_iup(cntr)\t\t\t(cntr).val += (cntr).step\n#define COUNTER_value(cntr)\t\t\t((cntr).val >> COUNTER_SHIFT)\n#define COUNTER_init(cntr, clk, rate)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t(cntr).ratio = (1 << COUNTER_SHIFT) * (1.0 * clk / rate);\t\\\n\t(cntr).step = (UINT32)((cntr).ratio + 0.5);\t\t\t\t\t\\\n\t(cntr).val = 0;\t\t\t\t\t\t\t\t\t\t\t\t\\\n}\n\n\ntypedef struct _NES_FDS NES_FDS;\nstruct _NES_FDS\n{\n\tdouble rate, clock;\n\tint mask;\n\tINT32 sm[2];\t// stereo mix\n\tINT32 fout;\t\t// current output\n\tint option[OPT_END];\n\n\tbool master_io;\n\tUINT8 master_vol;\n\tUINT32 last_freq;\t// for trackinfo\n\tUINT32 last_vol;\t// for trackinfo\n\n\t// two wavetables\n\t//const enum { TMOD=0, TWAV=1 };\n\tINT32 wave[2][64];\n\tUINT32 freq[2];\n\tUINT32 phase[2];\n\tbool wav_write;\n\tbool wav_halt;\n\tbool env_halt;\n\tbool mod_halt;\n\tUINT32 mod_pos;\n\tUINT32 mod_write_pos;\n\n\t// two ramp envelopes\n\t//const enum { EMOD=0, EVOL=1 };\n\tbool env_mode[2];\n\tbool env_disable[2];\n\tUINT32 env_timer[2];\n\tUINT32 env_speed[2];\n\tUINT32 env_out[2];\n\tUINT32 master_env_speed;\n\n\t// 1-pole RC lowpass filter\n\tINT32 rc_accum;\n\tINT32 rc_k;\n\tINT32 rc_l;\n\n\tCounter tick_count;\n\tUINT32 tick_last;\n};\n\nvoid* NES_FDS_Create(int clock, int rate)\n{\n\tNES_FDS* fds;\n\n\tfds = (NES_FDS*)malloc(sizeof(NES_FDS));\n\tif (fds == NULL)\n\t\treturn NULL;\n\tmemset(fds, 0x00, sizeof(NES_FDS));\n\n\tfds->option[OPT_CUTOFF] = 2000;\n\tfds->option[OPT_4085_RESET] = 0;\n\tfds->option[OPT_WRITE_PROTECT] = 0;\t// not used here, see nsfplay.cpp\n\n\tfds->rc_k = 0;\n\tfds->rc_l = (1<<RC_BITS);\n\n\t//NES_FDS_SetClock(fds, DEFAULT_CLOCK);\n\t//NES_FDS_SetRate(fds, DEFAULT_RATE);\n\tNES_FDS_SetClock(fds, clock);\n\tNES_FDS_SetRate(fds, rate);\n\tfds->sm[0] = 128;\n\tfds->sm[1] = 128;\n\n\tNES_FDS_Reset(fds);\n\n\treturn fds;\n}\n\nvoid NES_FDS_Destroy(void* chip)\n{\n\tfree(chip);\n}\n\nvoid NES_FDS_SetMask(void* chip, int m)\n{\n\tNES_FDS* fds = (NES_FDS*)chip;\n\n\tfds->mask = m&1;\n}\n\nvoid NES_FDS_SetStereoMix(void* chip, int trk, INT16 mixl, INT16 mixr)\n{\n\tNES_FDS* fds = (NES_FDS*)chip;\n\n\tif (trk < 0) return;\n\tif (trk > 1) return;\n\tfds->sm[0] = mixl;\n\tfds->sm[1] = mixr;\n}\n\nvoid NES_FDS_SetClock(void* chip, double c)\n{\n\tNES_FDS* fds = (NES_FDS*)chip;\n\n\tfds->clock = c;\n}\n\nvoid NES_FDS_SetRate(void* chip, double r)\n{\n\tNES_FDS* fds = (NES_FDS*)chip;\n\tdouble cutoff, leak;\n\n\tfds->rate = r;\n\n\tCOUNTER_init(fds->tick_count, fds->clock, fds->rate);\n\tfds->tick_last = 0;\n\t\n\t// configure lowpass filter\n\tcutoff = (double)fds->option[OPT_CUTOFF];\n\tleak = 0.0;\n\tif (cutoff > 0)\n\t\tleak = exp(-2.0 * 3.14159 * cutoff / fds->rate);\n\tfds->rc_k = (INT32)(leak * (double)(1<<RC_BITS));\n\tfds->rc_l = (1<<RC_BITS) - fds->rc_k;\n}\n\nvoid NES_FDS_SetOption(void* chip, int id, int val)\n{\n\tNES_FDS* fds = (NES_FDS*)chip;\n\n\tif(id<OPT_END) fds->option[id] = val;\n\n\t// update cutoff immediately\n\tif (id == OPT_CUTOFF) NES_FDS_SetRate(fds, fds->rate);\n}\n\nvoid NES_FDS_Reset(void* chip)\n{\n\tNES_FDS* fds = (NES_FDS*)chip;\n\tint i;\n\n\tfds->master_io = true;\n\tfds->master_vol = 0;\n\tfds->last_freq = 0;\n\tfds->last_vol = 0;\n\n\tfds->rc_accum = 0;\n\n\tfor (i=0; i<2; ++i)\n\t{\n\t\tmemset(fds->wave[i], 0, sizeof(fds->wave[i]));\n\t\tfds->freq[i] = 0;\n\t\tfds->phase[i] = 0;\n\t}\n\tfds->wav_write = false;\n\tfds->wav_halt = true;\n\tfds->env_halt = true;\n\tfds->mod_halt = true;\n\tfds->mod_pos = 0;\n\tfds->mod_write_pos = 0;\n\n\tfor (i=0; i<2; ++i)\n\t{\n\t\tfds->env_mode[i] = false;\n\t\tfds->env_disable[i] = true;\n\t\tfds->env_timer[i] = 0;\n\t\tfds->env_speed[i] = 0;\n\t\tfds->env_out[i] = 0;\n\t}\n\tfds->master_env_speed = 0xFF;\n\n\t// NOTE: the FDS BIOS reset only does the following related to audio:\n\t//   $4023 = $00\n\t//   $4023 = $83 enables master_io\n\t//   $4080 = $80 output volume = 0, envelope disabled\n\t//   $408A = $FF master envelope speed set to slowest\n\tNES_FDS_Write(fds, 0x4023, 0x00);\n\tNES_FDS_Write(fds, 0x4023, 0x83);\n\tNES_FDS_Write(fds, 0x4080, 0x80);\n\tNES_FDS_Write(fds, 0x408A, 0xFF);\n\n\t// reset other stuff\n\tNES_FDS_Write(fds, 0x4082, 0x00);\t// wav freq 0\n\tNES_FDS_Write(fds, 0x4083, 0x80);\t// wav disable\n\tNES_FDS_Write(fds, 0x4084, 0x80);\t// mod strength 0\n\tNES_FDS_Write(fds, 0x4085, 0x00);\t// mod position 0\n\tNES_FDS_Write(fds, 0x4086, 0x00);\t// mod freq 0\n\tNES_FDS_Write(fds, 0x4087, 0x80);\t// mod disable\n\tNES_FDS_Write(fds, 0x4089, 0x00);\t// wav write disable, max global volume}\n}\n\nstatic void Tick(NES_FDS* fds, UINT32 clocks)\n{\n\tINT32 vol_out;\n\n\t// clock envelopes\n\tif (!fds->env_halt && !fds->wav_halt && (fds->master_env_speed != 0))\n\t{\n\t\tint i;\n\t\t\n\t\tfor (i=0; i<2; ++i)\n\t\t{\n\t\t\tif (!fds->env_disable[i])\n\t\t\t{\n\t\t\t\tUINT32 period;\n\t\t\t\t\n\t\t\t\tfds->env_timer[i] += clocks;\n\t\t\t\tperiod = ((fds->env_speed[i]+1) * fds->master_env_speed) << 3;\n\t\t\t\twhile (fds->env_timer[i] >= period)\n\t\t\t\t{\n\t\t\t\t\t// clock the envelope\n\t\t\t\t\tif (fds->env_mode[i])\n\t\t\t\t\t{\n\t\t\t\t\t\tif (fds->env_out[i] < 32) ++fds->env_out[i];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif (fds->env_out[i] > 0 ) --fds->env_out[i];\n\t\t\t\t\t}\n\t\t\t\t\tfds->env_timer[i] -= period;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// clock the mod table\n\tif (!fds->mod_halt)\n\t{\n\t\tUINT32 start_pos, end_pos, p;\n\n\t\t// advance phase, adjust for modulator\n\t\tstart_pos = fds->phase[TMOD] >> 16;\n\t\tfds->phase[TMOD] += (clocks * fds->freq[TMOD]);\n\t\tend_pos = fds->phase[TMOD] >> 16;\n\n\t\t// wrap the phase to the 64-step table (+ 16 bit accumulator)\n\t\tfds->phase[TMOD] = fds->phase[TMOD] & 0x3FFFFF;\n\n\t\t// execute all clocked steps\n\t\tfor (p = start_pos; p < end_pos; ++p)\n\t\t{\n\t\t\tINT32 wv = fds->wave[TMOD][p & 0x3F];\n\t\t\tif (wv == 4)\t// 4 resets mod position\n\t\t\t\tfds->mod_pos = 0;\n\t\t\telse\n\t\t\t{\n\t\t\t\tstatic const INT32 BIAS[8] = { 0, 1, 2, 4, 0, -4, -2, -1 };\n\t\t\t\tfds->mod_pos += BIAS[wv];\n\t\t\t\tfds->mod_pos &= 0x7F;\t// 7-bit clamp\n\t\t\t}\n\t\t}\n\t}\n\n\t// clock the wav table\n\tif (!fds->wav_halt)\n\t{\n\t\tINT32 mod, f;\n\n\t\t// complex mod calculation\n\t\tmod = 0;\n\t\tif (fds->env_out[EMOD] != 0)\t// skip if modulator off\n\t\t{\n\t\t\t// convert mod_pos to 7-bit signed\n\t\t\tINT32 pos = (fds->mod_pos < 64) ? fds->mod_pos : (fds->mod_pos-128);\n\n\t\t\t// multiply pos by gain,\n\t\t\t// shift off 4 bits but with odd \"rounding\" behaviour\n\t\t\tINT32 temp = pos * fds->env_out[EMOD];\n\t\t\tINT32 rem = temp & 0x0F;\n\t\t\ttemp >>= 4;\n\t\t\tif ((rem > 0) && ((temp & 0x80) == 0))\n\t\t\t{\n\t\t\t\tif (pos < 0) temp -= 1;\n\t\t\t\telse         temp += 2;\n\t\t\t}\n\n\t\t\t// wrap if range is exceeded\n\t\t\twhile (temp >= 192) temp -= 256;\n\t\t\twhile (temp <  -64) temp += 256;\n\n\t\t\t// multiply result by pitch,\n\t\t\t// shift off 6 bits, round to nearest\n\t\t\ttemp = fds->freq[TWAV] * temp;\n\t\t\trem = temp & 0x3F;\n\t\t\ttemp >>= 6;\n\t\t\tif (rem >= 32) temp += 1;\n\n\t\t\tmod = temp;\n\t\t}\n\n\t\t// advance wavetable position\n\t\tf = fds->freq[TWAV] + mod;\n\t\tfds->phase[TWAV] = fds->phase[TWAV] + (clocks * f);\n\t\tfds->phase[TWAV] = fds->phase[TWAV] & 0x3FFFFF;\t// wrap\n\n\t\t// store for trackinfo\n\t\tfds->last_freq = f;\n\t}\n\n\t// output volume caps at 32\n\tvol_out = fds->env_out[EVOL];\n\tif (vol_out > 32) vol_out = 32;\n\n\t// final output\n\tif (!fds->wav_write)\n\t\tfds->fout = fds->wave[TWAV][(fds->phase[TWAV]>>16)&0x3F] * vol_out;\n\n\t// NOTE: during wav_halt, the unit still outputs (at phase 0)\n\t// and volume can affect it if the first sample is nonzero.\n\t// haven't worked out 100% of the conditions for volume to\n\t// effect (vol envelope does not seem to run, but am unsure)\n\t// but this implementation is very close to correct\n\n\t// store for trackinfo\n\tfds->last_vol = vol_out;\n}\n\nUINT32 NES_FDS_Render(void* chip, INT32 b[2])\n{\n\tNES_FDS* fds = (NES_FDS*)chip;\n\n/*\t// 8 bit approximation of master volume\n\tstatic const double MASTER_VOL = 2.4 * 1223.0;\t// max FDS vol vs max APU square (arbitrarily 1223)\n\tstatic const double MAX_OUT = 32.0f * 63.0f;\t// value that should map to master vol\n\tstatic const INT32 MASTER[4] = {\n\t\t(INT32)((MASTER_VOL / MAX_OUT) * 256.0 * 2.0f / 2.0f),\n\t\t(INT32)((MASTER_VOL / MAX_OUT) * 256.0 * 2.0f / 3.0f),\n\t\t(INT32)((MASTER_VOL / MAX_OUT) * 256.0 * 2.0f / 4.0f),\n\t\t(INT32)((MASTER_VOL / MAX_OUT) * 256.0 * 2.0f / 5.0f) };*/\n\n\tUINT32 clocks;\n\tINT32 v, rc_out, m;\n\n\tCOUNTER_iup(fds->tick_count);\n\tclocks = (COUNTER_value(fds->tick_count) - fds->tick_last) & 0xFF;\n\tTick(fds, clocks);\n\tfds->tick_last = COUNTER_value(fds->tick_count);\n\n\tv = fds->fout * MASTER[fds->master_vol] >> 8;\n\n\t// lowpass RC filter\n\trc_out = ((fds->rc_accum * fds->rc_k) + (v * fds->rc_l)) >> RC_BITS;\n\tfds->rc_accum = rc_out;\n\tv = rc_out;\n\n\t// output mix\n\tm = fds->mask ? 0 : v;\n\tb[0] = (m * fds->sm[0]) >> (7-2);\n\tb[1] = (m * fds->sm[1]) >> (7-2);\n\treturn 2;\n}\n\nbool NES_FDS_Write(void* chip, UINT32 adr, UINT32 val)\n{\n\tNES_FDS* fds = (NES_FDS*)chip;\n\n\t// $4023 master I/O enable/disable\n\tif (adr == 0x4023)\n\t{\n\t\tfds->master_io = ((val & 2) != 0);\n\t\treturn true;\n\t}\n\n\tif (!fds->master_io)\n\t\treturn false;\n\tif (adr < 0x4040 || adr > 0x408A)\n\t\treturn false;\n\n\tif (adr < 0x4080)\t// $4040-407F wave table write\n\t{\n\t\tif (fds->wav_write)\n\t\t\tfds->wave[TWAV][adr - 0x4040] = val & 0x3F;\n\t\treturn true;\n\t}\n\n\tswitch (adr & 0x00FF)\n\t{\n\tcase 0x80:\t// $4080 volume envelope\n\t\tfds->env_disable[EVOL] = ((val & 0x80) != 0);\n\t\tfds->env_mode[EVOL] = ((val & 0x40) != 0);\n\t\tfds->env_timer[EVOL] = 0;\n\t\tfds->env_speed[EVOL] = val & 0x3F;\n\t\tif (fds->env_disable[EVOL])\n\t\t\tfds->env_out[EVOL] = fds->env_speed[EVOL];\n\t\treturn true;\n\tcase 0x81:\t// $4081 ---\n\t\treturn false;\n\tcase 0x82:\t// $4082 wave frequency low\n\t\tfds->freq[TWAV] = (fds->freq[TWAV] & 0xF00) | val;\n\t\treturn true;\n\tcase 0x83:\t// $4083 wave frequency high / enables\n\t\tfds->freq[TWAV] = (fds->freq[TWAV] & 0x0FF) | ((val & 0x0F) << 8);\n\t\tfds->wav_halt = ((val & 0x80) != 0);\n\t\tfds->env_halt = ((val & 0x40) != 0);\n\t\tif (fds->wav_halt)\n\t\t\tfds->phase[TWAV] = 0;\n\t\tif (fds->env_halt)\n\t\t{\n\t\t\tfds->env_timer[EMOD] = 0;\n\t\t\tfds->env_timer[EVOL] = 0;\n\t\t}\n\t\treturn true;\n\tcase 0x84:\t// $4084 mod envelope\n\t\tfds->env_disable[EMOD] = ((val & 0x80) != 0);\n\t\tfds->env_mode[EMOD] = ((val & 0x40) != 0);\n\t\tfds->env_timer[EMOD] = 0;\n\t\tfds->env_speed[EMOD] = val & 0x3F;\n\t\tif (fds->env_disable[EMOD])\n\t\t\tfds->env_out[EMOD] = fds->env_speed[EMOD];\n\t\treturn true;\n\tcase 0x85:\t// $4085 mod position\n\t\tfds->mod_pos = val & 0x7F;\n\t\t// not hardware accurate., but prevents detune due to cycle inaccuracies\n\t\t// (notably in Bio Miracle Bokutte Upa)\n\t\tif (fds->option[OPT_4085_RESET])\n\t\t\tfds->phase[TMOD] = fds->mod_write_pos << 16;\n\t\treturn true;\n\tcase 0x86:\t// $4086 mod frequency low\n\t\tfds->freq[TMOD] = (fds->freq[TMOD] & 0xF00) | val;\n\t\treturn true;\n\tcase 0x87:\t// $4087 mod frequency high / enable\n\t\tfds->freq[TMOD] = (fds->freq[TMOD] & 0x0FF) | ((val & 0x0F) << 8);\n\t\tfds->mod_halt = ((val & 0x80) != 0);\n\t\tif (fds->mod_halt)\n\t\t\tfds->phase[TMOD] = fds->phase[TMOD] & 0x3F0000;\t// reset accumulator phase\n\t\treturn true;\n\tcase 0x88:\t// $4088 mod table write\n\t\tif (fds->mod_halt)\n\t\t{\n\t\t\t// writes to current playback position (there is no direct way to set phase)\n\t\t\tfds->wave[TMOD][(fds->phase[TMOD] >> 16) & 0x3F] = val & 0x7F;\n\t\t\tfds->phase[TMOD] = (fds->phase[TMOD] + 0x010000) & 0x3FFFFF;\n\t\t\tfds->wave[TMOD][(fds->phase[TMOD] >> 16) & 0x3F] = val & 0x7F;\n\t\t\tfds->phase[TMOD] = (fds->phase[TMOD] + 0x010000) & 0x3FFFFF;\n\t\t\tfds->mod_write_pos = fds->phase[TMOD] >> 16;\t// used by OPT_4085_RESET\n\t\t}\n\t\treturn true;\n\tcase 0x89:\t// $4089 wave write enable, master volume\n\t\tfds->wav_write = ((val & 0x80) != 0);\n\t\tfds->master_vol = val & 0x03;\n\t\treturn true;\n\tcase 0x8A:\t// $408A envelope speed\n\t\tfds->master_env_speed = val;\n\t\t// haven't tested whether this register resets phase on hardware,\n\t\t// but this ensures my inplementation won't spam envelope clocks\n\t\t// if this value suddenly goes low.\n\t\tfds->env_timer[EMOD] = 0;\n\t\tfds->env_timer[EVOL] = 0;\n\t\treturn true;\n\tdefault:\n\t\treturn false;\n\t}\n\treturn false;\n}\n\nbool NES_FDS_Read(void* chip, UINT32 adr, UINT32* val)\n{\n\tNES_FDS* fds = (NES_FDS*)chip;\n\n\tif (adr >= 0x4040 && adr < 0x407F)\n\t{\n\t\t// TODO: if wav_write is not enabled, the\n\t\t// read address may not be reliable? need\n\t\t// to test this on hardware.\n\t\t*val = fds->wave[TWAV][adr - 0x4040];\n\t\treturn true;\n\t}\n\n\tif (adr == 0x4090)\t// $4090 read volume envelope\n\t{\n\t\t*val = fds->env_out[EVOL] | 0x40;\n\t\treturn true;\n\t}\n\n\tif (adr == 0x4092)\t// $4092 read mod envelope\n\t{\n\t\t*val = fds->env_out[EMOD] | 0x40;\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n"
  },
  {
    "path": "VGMPlay/chips/np_nes_fds.h",
    "content": "#ifndef _NP_NES_FDS_H_\n#define _NP_NES_FDS_H_\n\nvoid* NES_FDS_Create(int clock, int rate);\nvoid NES_FDS_Destroy(void* chip);\nvoid NES_FDS_Reset(void* chip);\nUINT32 NES_FDS_Render(void* chip, INT32 b[2]);\nbool NES_FDS_Write(void* chip, UINT32 adr, UINT32 val);\nbool NES_FDS_Read(void* chip, UINT32 adr, UINT32* val);\nvoid NES_FDS_SetRate(void* chip, double r);\nvoid NES_FDS_SetClock(void* chip, double c);\nvoid NES_FDS_SetOption(void* chip, int id, int val);\nvoid NES_FDS_SetMask(void* chip, int m);\nvoid NES_FDS_SetStereoMix(void* chip, int trk, INT16 mixl, INT16 mixr);\n\n#endif\t// _NP_NES_FDS_H_\n"
  },
  {
    "path": "VGMPlay/chips/okim6258.c",
    "content": "/**********************************************************************************************\n *\n *   OKI MSM6258 ADPCM\n *\n *   TODO:\n *   3-bit ADPCM support\n *   Recording?\n *\n **********************************************************************************************/\n\n\n//#include \"emu.h\"\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n#ifdef _DEBUG\n#include <stdio.h>\n#endif\n//#include \"streams.h\"\n#include <math.h>\n#include \"okim6258.h\"\n\n#define COMMAND_STOP\t\t(1 << 0)\n#define COMMAND_PLAY\t\t(1 << 1)\n#define\tCOMMAND_RECORD\t\t(1 << 2)\n\n#define STATUS_PLAYING\t\t(1 << 1)\n#define STATUS_RECORDING\t(1 << 2)\n\nstatic const int dividers[4] = { 1024, 768, 512, 512 };\n\n#define QUEUE_SIZE\t(1 << 1)\n#define QUEUE_MASK\t(QUEUE_SIZE - 1)\ntypedef struct _okim6258_state okim6258_state;\nstruct _okim6258_state\n{\n\tUINT8  status;\n\n\tUINT32 master_clock;\t/* master clock frequency */\n\tUINT32 divider;\t\t\t/* master clock divider */\n\tUINT8 adpcm_type;\t\t/* 3/4 bit ADPCM select */\n\tUINT8 data_in;\t\t\t/* ADPCM data-in register */\n\tUINT8 nibble_shift;\t\t/* nibble select */\n\t//sound_stream *stream;\t/* which stream are we playing on? */\n\n\tUINT8 output_bits;\n\tINT32 output_mask;\n\n\t// Valley Bell: Added a small queue to prevent race conditions.\n\tUINT8 data_buf[8];\n\tUINT8 data_in_last;\n\tUINT8 data_buf_pos;\n\t// Data Empty Values:\n\t//\t00 - data written, but not read yet\n\t//\t01 - read data, waiting for next write\n\t//\t02 - tried to read, but had no data\n\tUINT8 data_empty;\n\t// Valley Bell: Added pan\n\tUINT8 pan;\n\tINT32 last_smpl;\n\n\tINT32 signal;\n\tINT32 step;\n\t\n\tUINT8 clock_buffer[0x04];\n\tUINT32 initial_clock;\n\tUINT8 initial_div;\n\t\n\tSRATE_CALLBACK SmpRateFunc;\n\tvoid* SmpRateData;\n};\n\n/* step size index shift table */\nstatic const int index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };\n\n/* lookup table for the precomputed difference */\nstatic int diff_lookup[49*16];\n\n/* tables computed? */\nstatic int tables_computed = 0;\n\n#define MAX_CHIPS\t0x02\nstatic okim6258_state OKIM6258Data[MAX_CHIPS];\nstatic UINT8 Iternal10Bit = 0x00;\n\n/*INLINE okim6258_state *get_safe_token(running_device *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == OKIM6258);\n\treturn (okim6258_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n/**********************************************************************************************\n\n     compute_tables -- compute the difference tables\n\n***********************************************************************************************/\n\nstatic void compute_tables(void)\n{\n\t/* nibble to bit map */\n\tstatic const int nbl2bit[16][4] =\n\t{\n\t\t{ 1, 0, 0, 0}, { 1, 0, 0, 1}, { 1, 0, 1, 0}, { 1, 0, 1, 1},\n\t\t{ 1, 1, 0, 0}, { 1, 1, 0, 1}, { 1, 1, 1, 0}, { 1, 1, 1, 1},\n\t\t{-1, 0, 0, 0}, {-1, 0, 0, 1}, {-1, 0, 1, 0}, {-1, 0, 1, 1},\n\t\t{-1, 1, 0, 0}, {-1, 1, 0, 1}, {-1, 1, 1, 0}, {-1, 1, 1, 1}\n\t};\n\n\tint step, nib;\n\n\tif (tables_computed)\n\t\treturn;\n\t\n\t/* loop over all possible steps */\n\tfor (step = 0; step <= 48; step++)\n\t{\n\t\t/* compute the step value */\n\t\tint stepval = floor(16.0 * pow(11.0 / 10.0, (double)step));\n\n\t\t/* loop over all nibbles and compute the difference */\n\t\tfor (nib = 0; nib < 16; nib++)\n\t\t{\n\t\t\tdiff_lookup[step*16 + nib] = nbl2bit[nib][0] *\n\t\t\t\t(stepval   * nbl2bit[nib][1] +\n\t\t\t\t stepval/2 * nbl2bit[nib][2] +\n\t\t\t\t stepval/4 * nbl2bit[nib][3] +\n\t\t\t\t stepval/8);\n\t\t}\n\t}\n\n\ttables_computed = 1;\n}\n\n\nstatic INT16 clock_adpcm(okim6258_state *chip, UINT8 nibble)\n{\n\tINT32 max = chip->output_mask - 1;\n\tINT32 min = -chip->output_mask;\n\n\t// original MAME algorithm (causes a DC offset over time)\n\t//chip->signal += diff_lookup[chip->step * 16 + (nibble & 15)];\n\n\t// awesome algorithm ported from XM6 - it works PERFECTLY\n\tint sample = diff_lookup[chip->step * 16 + (nibble & 15)];\n\tchip->signal = ((sample << 8) + (chip->signal * 245)) >> 8;\n\n\t/* clamp to the maximum */\n\tif (chip->signal > max)\n\t\tchip->signal = max;\n\telse if (chip->signal < min)\n\t\tchip->signal = min;\n\n\t/* adjust the step size and clamp */\n\tchip->step += index_shift[nibble & 7];\n\tif (chip->step > 48)\n\t\tchip->step = 48;\n\telse if (chip->step < 0)\n\t\tchip->step = 0;\n\n\t/* return the signal scaled up to 32767 */\n\treturn chip->signal << 4;\n}\n\n/**********************************************************************************************\n\n     okim6258_update -- update the sound chip so that it is in sync with CPU execution\n\n***********************************************************************************************/\n\n//static STREAM_UPDATE( okim6258_update )\nvoid okim6258_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//okim6258_state *chip = (okim6258_state *)param;\n\tokim6258_state *chip = &OKIM6258Data[ChipID];\n\t//stream_sample_t *buffer = outputs[0];\n\tstream_sample_t *bufL = outputs[0];\n\tstream_sample_t *bufR = outputs[1];\n\n\t//memset(outputs[0], 0, samples * sizeof(*outputs[0]));\n\n\tif (chip->status & STATUS_PLAYING)\n\t{\n\t\tint nibble_shift = chip->nibble_shift;\n\n\t\twhile (samples)\n\t\t{\n\t\t\t/* Compute the new amplitude and update the current step */\n\t\t\t//int nibble = (chip->data_in >> nibble_shift) & 0xf;\n\t\t\tint nibble;\n\t\t\tINT16 sample;\n\t\t\t\n\t\t\tif (! nibble_shift)\n\t\t\t{\n\t\t\t\t// 1st nibble - get data\n\t\t\t\tif (! chip->data_empty)\n\t\t\t\t{\n\t\t\t\t\tchip->data_in = chip->data_buf[chip->data_buf_pos >> 4];\n\t\t\t\t\tchip->data_buf_pos += 0x10;\n\t\t\t\t\tchip->data_buf_pos &= 0x7F;\n\t\t\t\t\tif ((chip->data_buf_pos >> 4) == (chip->data_buf_pos & 0x0F))\n\t\t\t\t\t\tchip->data_empty ++;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t//chip->data_in = chip->data_in_last;\n\t\t\t\t\tif (chip->data_empty < 0x80)\n\t\t\t\t\t\tchip->data_empty ++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tnibble = (chip->data_in >> nibble_shift) & 0xf;\n\n\t\t\t/* Output to the buffer */\n\t\t\t//INT16 sample = clock_adpcm(chip, nibble);\n\t\t\tif (chip->data_empty < 0x02)\n\t\t\t{\n\t\t\t\tsample = clock_adpcm(chip, nibble);\n\t\t\t\tchip->last_smpl = sample;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Valley Bell: data_empty behaviour (loosely) ported from XM6\n\t\t\t\tif (chip->data_empty >= 0x02 + 0x01)\n\t\t\t\t{\n\t\t\t\t\tchip->data_empty -= 0x01;\n\t\t\t\t\t/*if (chip->signal < 0)\n\t\t\t\t\t\tchip->signal ++;\n\t\t\t\t\telse if (chip->signal > 0)\n\t\t\t\t\t\tchip->signal --;*/\n\t\t\t\t\tchip->signal = chip->signal * 15 / 16;\n\t\t\t\t\tchip->last_smpl = chip->signal << 4;\n\t\t\t\t}\n\t\t\t\tsample = chip->last_smpl;\n\t\t\t}\n\n\t\t\tnibble_shift ^= 4;\n\n\t\t\t//*buffer++ = sample;\n\t\t\t*bufL++ = (chip->pan & 0x02) ? 0x00 : sample;\n\t\t\t*bufR++ = (chip->pan & 0x01) ? 0x00 : sample;\n\t\t\tsamples--;\n\t\t}\n\n\t\t/* Update the parameters */\n\t\tchip->nibble_shift = nibble_shift;\n\t}\n\telse\n\t{\n\t\t/* Fill with 0 */\n\t\twhile (samples--)\n\t\t{\n\t\t\t//*buffer++ = 0;\n\t\t\t*bufL++ = 0;\n\t\t\t*bufR++ = 0;\n\t\t}\n\t}\n}\n\n\n\n/**********************************************************************************************\n\n     state save support for MAME\n\n***********************************************************************************************/\n\n/*static void okim6258_state_save_register(okim6258_state *info, running_device *device)\n{\n\tstate_save_register_device_item(device, 0, info->status);\n\tstate_save_register_device_item(device, 0, info->master_clock);\n\tstate_save_register_device_item(device, 0, info->divider);\n\tstate_save_register_device_item(device, 0, info->data_in);\n\tstate_save_register_device_item(device, 0, info->nibble_shift);\n\tstate_save_register_device_item(device, 0, info->signal);\n\tstate_save_register_device_item(device, 0, info->step);\n}*/\n\n\n/**********************************************************************************************\n\n     OKIM6258_start -- start emulation of an OKIM6258-compatible chip\n\n***********************************************************************************************/\n\nstatic int get_vclk(okim6258_state* info)\n{\n\tint clk_rnd;\n\t\n\tclk_rnd = info->master_clock;\n\tclk_rnd += info->divider / 2;\t // for better rounding - should help some of the streams\n\treturn clk_rnd / info->divider;\n}\n\n//static DEVICE_START( okim6258 )\nint device_start_okim6258(UINT8 ChipID, int clock, int divider, int adpcm_type, int output_12bits)\n{\n\t//const okim6258_interface *intf = (const okim6258_interface *)device->baseconfig().static_config();\n\t//okim6258_state *info = get_safe_token(device);\n\tokim6258_state *info;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &OKIM6258Data[ChipID];\n\t\n\tcompute_tables();\n\n\t//info->master_clock = device->clock();\n\tinfo->initial_clock = clock;\n\tinfo->initial_div = divider;\n\tinfo->master_clock = clock;\n\tinfo->adpcm_type = /*intf->*/adpcm_type;\n\tinfo->clock_buffer[0x00] = (clock & 0x000000FF) >>  0;\n\tinfo->clock_buffer[0x01] = (clock & 0x0000FF00) >>  8;\n\tinfo->clock_buffer[0x02] = (clock & 0x00FF0000) >> 16;\n\tinfo->clock_buffer[0x03] = (clock & 0xFF000000) >> 24;\n\tinfo->SmpRateFunc = NULL;\n\n\t/* D/A precision is 10-bits but 12-bit data can be output serially to an external DAC */\n\tinfo->output_bits = /*intf->*/output_12bits ? 12 : 10;\n\tif (Iternal10Bit)\n\t\tinfo->output_mask = (1 << (info->output_bits - 1));\n\telse\n\t\tinfo->output_mask = (1 << (12 - 1));\n\tinfo->divider = dividers[/*intf->*/divider];\n\n\t//info->stream = stream_create(device, 0, 1, device->clock()/info->divider, info, okim6258_update);\n\n\tinfo->signal = -2;\n\tinfo->step = 0;\n\n\t//okim6258_state_save_register(info, device);\n\t\n\treturn get_vclk(info);\n}\n\n\n/**********************************************************************************************\n\n     OKIM6258_stop -- stop emulation of an OKIM6258-compatible chip\n\n***********************************************************************************************/\n\nvoid device_stop_okim6258(UINT8 ChipID)\n{\n\tokim6258_state *info = &OKIM6258Data[ChipID];\n\t\n\treturn;\n}\n\n//static DEVICE_RESET( okim6258 )\nvoid device_reset_okim6258(UINT8 ChipID)\n{\n\t//okim6258_state *info = get_safe_token(device);\n\tokim6258_state *info = &OKIM6258Data[ChipID];\n\n\t//stream_update(info->stream);\n\t\n\tinfo->master_clock = info->initial_clock;\n\tinfo->clock_buffer[0x00] = (info->initial_clock & 0x000000FF) >>  0;\n\tinfo->clock_buffer[0x01] = (info->initial_clock & 0x0000FF00) >>  8;\n\tinfo->clock_buffer[0x02] = (info->initial_clock & 0x00FF0000) >> 16;\n\tinfo->clock_buffer[0x03] = (info->initial_clock & 0xFF000000) >> 24;\n\tinfo->divider = dividers[info->initial_div];\n\tif (info->SmpRateFunc != NULL)\n\t\tinfo->SmpRateFunc(info->SmpRateData, get_vclk(info));\n\t\n\t\n\tinfo->signal = -2;\n\tinfo->step = 0;\n\tinfo->status = 0;\n\n\t// Valley Bell: Added reset of the Data In register.\n\tinfo->data_in = 0x00;\n\tinfo->data_buf[0] = info->data_buf[1] = 0x00;\n\tinfo->data_buf_pos = 0x00;\n\tinfo->data_empty = 0xFF;\n\tinfo->pan = 0x00;\n}\n\n\n/**********************************************************************************************\n\n     okim6258_set_divider -- set the master clock divider\n\n***********************************************************************************************/\n\n//void okim6258_set_divider(running_device *device, int val)\nvoid okim6258_set_divider(UINT8 ChipID, int val)\n{\n\t//okim6258_state *info = get_safe_token(device);\n\tokim6258_state *info = &OKIM6258Data[ChipID];\n\tint divider = dividers[val];\n\n\tinfo->divider = dividers[val];\n\t//stream_set_sample_rate(info->stream, info->master_clock / divider);\n\tif (info->SmpRateFunc != NULL)\n\t\tinfo->SmpRateFunc(info->SmpRateData, get_vclk(info));\n}\n\n\n/**********************************************************************************************\n\n     okim6258_set_clock -- set the master clock\n\n***********************************************************************************************/\n\n//void okim6258_set_clock(running_device *device, int val)\nvoid okim6258_set_clock(UINT8 ChipID, int val)\n{\n\t//okim6258_state *info = get_safe_token(device);\n\tokim6258_state *info = &OKIM6258Data[ChipID];\n\n\tif (val)\n\t{\n\t\tinfo->master_clock = val;\n\t}\n\telse\n\t{\n\t\tinfo->master_clock =\t(info->clock_buffer[0x00] <<  0) |\n\t\t\t\t\t\t\t\t(info->clock_buffer[0x01] <<  8) |\n\t\t\t\t\t\t\t\t(info->clock_buffer[0x02] << 16) |\n\t\t\t\t\t\t\t\t(info->clock_buffer[0x03] << 24);\n\t}\n\t//stream_set_sample_rate(info->stream, info->master_clock / info->divider);\n\tif (info->SmpRateFunc != NULL)\n\t\tinfo->SmpRateFunc(info->SmpRateData, get_vclk(info));\n}\n\n\n/**********************************************************************************************\n\n     okim6258_get_vclk -- get the VCLK/sampling frequency\n\n***********************************************************************************************/\n\n//int okim6258_get_vclk(running_device *device)\nint okim6258_get_vclk(UINT8 ChipID)\n{\n\t//okim6258_state *info = get_safe_token(device);\n\tokim6258_state *info = &OKIM6258Data[ChipID];\n\n\treturn get_vclk(info);\n}\n\n\n/**********************************************************************************************\n\n     okim6258_status_r -- read the status port of an OKIM6258-compatible chip\n\n***********************************************************************************************/\n\n//READ8_DEVICE_HANDLER( okim6258_status_r )\n/*UINT8 okim6258_status_r(UINT8 ChipID, offs_t offset)\n{\n\t//okim6258_state *info = get_safe_token(device);\n\tokim6258_state *info = &OKIM6258Data[ChipID];\n\n\t//stream_update(info->stream);\n\n\treturn (info->status & STATUS_PLAYING) ? 0x00 : 0x80;\n}*/\n\n\n/**********************************************************************************************\n\n     okim6258_data_w -- write to the control port of an OKIM6258-compatible chip\n\n***********************************************************************************************/\n//WRITE8_DEVICE_HANDLER( okim6258_data_w )\nstatic void okim6258_data_w(UINT8 ChipID, /*offs_t offset, */UINT8 data)\n{\n\t//okim6258_state *info = get_safe_token(device);\n\tokim6258_state *info = &OKIM6258Data[ChipID];\n\n\t/* update the stream */\n\t//stream_update(info->stream);\n\n\t//info->data_in = data;\n\t//info->nibble_shift = 0;\n\t\n\tif (info->data_empty >= 0x02)\n\t\tinfo->data_buf_pos = 0x00;\n\tinfo->data_in_last = data;\n\tinfo->data_buf[info->data_buf_pos & 0x0F] = data;\n\tinfo->data_buf_pos += 0x01;\n\tinfo->data_buf_pos &= 0xF7;\n\tif ((info->data_buf_pos >> 4) == (info->data_buf_pos & 0x0F))\n\t{\n\t\tlogerror(\"Warning: FIFO full!\\n\");\n\t\tinfo->data_buf_pos = (info->data_buf_pos & 0xF0) | ((info->data_buf_pos-1) & 0x07);\n\t}\n\tinfo->data_empty = 0x00;\n}\n\n\n/**********************************************************************************************\n\n     okim6258_ctrl_w -- write to the control port of an OKIM6258-compatible chip\n\n***********************************************************************************************/\n\n//WRITE8_DEVICE_HANDLER( okim6258_ctrl_w )\nstatic void okim6258_ctrl_w(UINT8 ChipID, /*offs_t offset, */UINT8 data)\n{\n\t//okim6258_state *info = get_safe_token(device);\n\tokim6258_state *info = &OKIM6258Data[ChipID];\n\n\t//stream_update(info->stream);\n\n\tif (data & COMMAND_STOP)\n\t{\n\t\tinfo->status &= ~(STATUS_PLAYING | STATUS_RECORDING);\n\t\treturn;\n\t}\n\n\tif (data & COMMAND_PLAY)\n\t{\n\t\tif (!(info->status & STATUS_PLAYING))\n\t\t{\n\t\t\tinfo->status |= STATUS_PLAYING;\n\n\t\t\t/* Also reset the ADPCM parameters */\n\t\t\tinfo->signal = -2;\t// Note: XM6 lets this fade to 0 when nothing is going on\n\t\t\tinfo->step = 0;\n\t\t\tinfo->nibble_shift = 0;\n\t\t\t\n\t\t\tinfo->data_buf[0x00] = data;\n\t\t\tinfo->data_buf_pos = 0x01;\t// write pos 01, read pos 00\n\t\t\tinfo->data_empty = 0x00;\n\t\t}\n\t\tinfo->step = 0;\t// this line was verified with the source of XM6\n\t\tinfo->nibble_shift = 0;\n\t}\n\telse\n\t{\n\t\tinfo->status &= ~STATUS_PLAYING;\n\t}\n\n\tif (data & COMMAND_RECORD)\n\t{\n\t\tlogerror(\"M6258: Record enabled\\n\");\n\t\tinfo->status |= STATUS_RECORDING;\n\t}\n\telse\n\t{\n\t\tinfo->status &= ~STATUS_RECORDING;\n\t}\n}\n\nstatic void okim6258_set_clock_byte(UINT8 ChipID, UINT8 Byte, UINT8 val)\n{\n\tokim6258_state *info = &OKIM6258Data[ChipID];\n\t\n\tinfo->clock_buffer[Byte] = val;\n\t\n\treturn;\n}\n\nstatic void okim6258_pan_w(UINT8 ChipID, UINT8 data)\n{\n\tokim6258_state *info = &OKIM6258Data[ChipID];\n\n\tinfo->pan = data;\n\t\n\treturn;\n}\n\n\nvoid okim6258_write(UINT8 ChipID, UINT8 Port, UINT8 Data)\n{\n\tswitch(Port)\n\t{\n\tcase 0x00:\n\t\tokim6258_ctrl_w(ChipID, /*0x00, */Data);\n\t\tbreak;\n\tcase 0x01:\n\t\tokim6258_data_w(ChipID, /*0x00, */Data);\n\t\tbreak;\n\tcase 0x02:\n\t\tokim6258_pan_w(ChipID, Data);\n\t\tbreak;\n\tcase 0x08:\n\tcase 0x09:\n\tcase 0x0A:\n\t\tokim6258_set_clock_byte(ChipID, Port & 0x03, Data);\n\t\tbreak;\n\tcase 0x0B:\n\t\tokim6258_set_clock_byte(ChipID, Port & 0x03, Data);\n\t\tokim6258_set_clock(ChipID, 0);\n\t\tbreak;\n\tcase 0x0C:\n\t\tokim6258_set_divider(ChipID, Data);\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\n\nvoid okim6258_set_options(UINT16 Options)\n{\n\tIternal10Bit = (Options >> 0) & 0x01;\n\t\n\treturn;\n}\n\nvoid okim6258_set_srchg_cb(UINT8 ChipID, SRATE_CALLBACK CallbackFunc, void* DataPtr)\n{\n\tokim6258_state *info = &OKIM6258Data[ChipID];\n\t\n\t// set Sample Rate Change Callback routine\n\tinfo->SmpRateFunc = CallbackFunc;\n\tinfo->SmpRateData = DataPtr;\n\t\n\treturn;\n}\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( okim6258 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers --- //\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(okim6258_state);\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions --- //\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME(okim6258);\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// nothing //\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME(okim6258);\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings --- //\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"OKI6258\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"OKI ADPCM\");\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}\n\n\nDEFINE_LEGACY_SOUND_DEVICE(OKIM6258, okim6258);*/\n"
  },
  {
    "path": "VGMPlay/chips/okim6258.h",
    "content": "#pragma once\n\n//#include \"devlegcy.h\"\n\n/* an interface for the OKIM6258 and similar chips */\n\n/*typedef struct _okim6258_interface okim6258_interface;\nstruct _okim6258_interface\n{\n\tint divider;\n\tint adpcm_type;\n\tint output_12bits;\n};*/\n\n\n#define FOSC_DIV_BY_1024\t0\n#define FOSC_DIV_BY_768\t\t1\n#define FOSC_DIV_BY_512\t\t2\n\n#define TYPE_3BITS      \t0\n#define TYPE_4BITS\t\t\t1\n\n#define\tOUTPUT_10BITS\t\t0\n#define\tOUTPUT_12BITS\t\t1\n\nvoid okim6258_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_okim6258(UINT8 ChipID, int clock, int divider, int adpcm_type, int output_12bits);\nvoid device_stop_okim6258(UINT8 ChipID);\nvoid device_reset_okim6258(UINT8 ChipID);\n\n//void okim6258_set_divider(running_device *device, int val);\n//void okim6258_set_clock(running_device *device, int val);\n//int okim6258_get_vclk(running_device *device);\n\nvoid okim6258_set_divider(UINT8 ChipID, int val);\nvoid okim6258_set_clock(UINT8 ChipID, int val);\nint okim6258_get_vclk(UINT8 ChipID);\n\n//READ8_DEVICE_HANDLER( okim6258_status_r );\n//WRITE8_DEVICE_HANDLER( okim6258_data_w );\n//WRITE8_DEVICE_HANDLER( okim6258_ctrl_w );\n\n/*UINT8 okim6258_status_r(UINT8 ChipID, offs_t offset);\nvoid okim6258_data_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid okim6258_ctrl_w(UINT8 ChipID, offs_t offset, UINT8 data);*/\nvoid okim6258_write(UINT8 ChipID, UINT8 Port, UINT8 Data);\n\nvoid okim6258_set_options(UINT16 Options);\nvoid okim6258_set_srchg_cb(UINT8 ChipID, SRATE_CALLBACK CallbackFunc, void* DataPtr);\n\n//DECLARE_LEGACY_SOUND_DEVICE(OKIM6258, okim6258);\n"
  },
  {
    "path": "VGMPlay/chips/okim6295.c",
    "content": "/**********************************************************************************************\n *\n *   streaming ADPCM driver\n *   by Aaron Giles\n *\n *   Library to transcode from an ADPCM source to raw PCM.\n *   Written by Buffoni Mirko in 08/06/97\n *   References: various sources and documents.\n *\n *   HJB 08/31/98\n *   modified to use an automatically selected oversampling factor\n *   for the current sample rate\n *\n *   Mish 21/7/99\n *   Updated to allow multiple OKI chips with different sample rates\n *\n *   R. Belmont 31/10/2003\n *   Updated to allow a driver to use both MSM6295s and \"raw\" ADPCM voices (gcpinbal)\n *   Also added some error trapping for MAME_DEBUG builds\n *\n **********************************************************************************************/\n\n\n#include \"mamedef.h\"\n//#include \"emu.h\"\n//#include \"streams.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <math.h>\n#include \"okim6295.h\"\n\n#define FALSE\t0\n#define TRUE\t1\n\n//#define MAX_SAMPLE_CHUNK\t10000\n#define MAX_SAMPLE_CHUNK\t0x10\t// that's enough for VGMPlay's update rate\n\n\n/* struct describing a single playing ADPCM voice */\nstruct ADPCMVoice\n{\n\tUINT8 playing;\t\t\t/* 1 if we are actively playing */\n\n\tUINT32 base_offset;\t\t/* pointer to the base memory location */\n\tUINT32 sample;\t\t\t/* current sample number */\n\tUINT32 count;\t\t\t/* total samples to play */\n\n\tstruct adpcm_state adpcm;/* current ADPCM state */\n\tUINT32 volume;\t\t\t/* output volume */\n\tUINT8 Muted;\n};\n\ntypedef struct _okim6295_state okim6295_state;\nstruct _okim6295_state\n{\n\t#define OKIM6295_VOICES\t\t4\n\tstruct ADPCMVoice voice[OKIM6295_VOICES];\n\t//running_device *device;\n\tINT16 command;\n\t//UINT8 bank_installed;\n\tINT32 bank_offs;\n\tUINT8 pin7_state;\n\tUINT8 nmk_mode;\n\tUINT8 nmk_bank[4];\n\t//sound_stream *stream;\t/* which stream are we playing on? */\n\tUINT32 master_clock;\t/* master clock frequency */\n\tUINT32 initial_clock;\n\t\n\tUINT32\tROMSize;\n\tUINT8*\tROM;\n\t\n\tSRATE_CALLBACK SmpRateFunc;\n\tvoid* SmpRateData;\n};\n\n/* step size index shift table */\nstatic const int index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };\n\n/* lookup table for the precomputed difference */\nstatic int diff_lookup[49*16];\n\n/* volume lookup table. The manual lists only 9 steps, ~3dB per step. Given the dB values,\n   that seems to map to a 5-bit volume control. Any volume parameter beyond the 9th index\n   results in silent playback. */\nstatic const int volume_table[16] =\n{\n\t0x20,\t//   0 dB\n\t0x16,\t//  -3.2 dB\n\t0x10,\t//  -6.0 dB\n\t0x0b,\t//  -9.2 dB\n\t0x08,\t// -12.0 dB\n\t0x06,\t// -14.5 dB\n\t0x04,\t// -18.0 dB\n\t0x03,\t// -20.5 dB\n\t0x02,\t// -24.0 dB\n\t0x00,\n\t0x00,\n\t0x00,\n\t0x00,\n\t0x00,\n\t0x00,\n\t0x00,\n};\n\n/* tables computed? */\nstatic int tables_computed = 0;\n\n/* useful interfaces */\n//const okim6295_interface okim6295_interface_pin7high = { 1 };\n//const okim6295_interface okim6295_interface_pin7low = { 0 };\n\n/* default address map */\n/*static ADDRESS_MAP_START( okim6295, 0, 8 )\n\tAM_RANGE(0x00000, 0x3ffff) AM_ROM\nADDRESS_MAP_END*/\n\n\n#define MAX_CHIPS\t0x02\nstatic okim6295_state OKIM6295Data[MAX_CHIPS];\n\n/*INLINE okim6295_state *get_safe_token(running_device *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_OKIM6295);\n\treturn (okim6295_state *)device->token;\n}*/\n\n\n/**********************************************************************************************\n\n     compute_tables -- compute the difference tables\n\n***********************************************************************************************/\n\nstatic void compute_tables(void)\n{\n\t/* nibble to bit map */\n\tstatic const int nbl2bit[16][4] =\n\t{\n\t\t{ 1, 0, 0, 0}, { 1, 0, 0, 1}, { 1, 0, 1, 0}, { 1, 0, 1, 1},\n\t\t{ 1, 1, 0, 0}, { 1, 1, 0, 1}, { 1, 1, 1, 0}, { 1, 1, 1, 1},\n\t\t{-1, 0, 0, 0}, {-1, 0, 0, 1}, {-1, 0, 1, 0}, {-1, 0, 1, 1},\n\t\t{-1, 1, 0, 0}, {-1, 1, 0, 1}, {-1, 1, 1, 0}, {-1, 1, 1, 1}\n\t};\n\n\tint step, nib;\n\n\t/* loop over all possible steps */\n\tfor (step = 0; step <= 48; step++)\n\t{\n\t\t/* compute the step value */\n\t\tint stepval = (int)floor(16.0 * pow(11.0 / 10.0, (double)step));\n\n\t\t/* loop over all nibbles and compute the difference */\n\t\tfor (nib = 0; nib < 16; nib++)\n\t\t{\n\t\t\tdiff_lookup[step*16 + nib] = nbl2bit[nib][0] *\n\t\t\t\t(stepval   * nbl2bit[nib][1] +\n\t\t\t\t stepval/2 * nbl2bit[nib][2] +\n\t\t\t\t stepval/4 * nbl2bit[nib][3] +\n\t\t\t\t stepval/8);\n\t\t}\n\t}\n\n\ttables_computed = 1;\n}\n\n\n\n/**********************************************************************************************\n\n     reset_adpcm -- reset the ADPCM stream\n\n***********************************************************************************************/\n\nvoid reset_adpcm(struct adpcm_state *state)\n{\n\t/* make sure we have our tables */\n\tif (!tables_computed)\n\t\tcompute_tables();\n\n\t/* reset the signal/step */\n\tstate->signal = -2;\n\tstate->step = 0;\n}\n\n\n\n/**********************************************************************************************\n\n     clock_adpcm -- clock the next ADPCM byte\n\n***********************************************************************************************/\n\nINT16 clock_adpcm(struct adpcm_state *state, UINT8 nibble)\n{\n\tstate->signal += diff_lookup[state->step * 16 + (nibble & 15)];\n\n\t/* clamp to the maximum */\n\tif (state->signal > 2047)\n\t\tstate->signal = 2047;\n\telse if (state->signal < -2048)\n\t\tstate->signal = -2048;\n\n\t/* adjust the step size and clamp */\n\tstate->step += index_shift[nibble & 7];\n\tif (state->step > 48)\n\t\tstate->step = 48;\n\telse if (state->step < 0)\n\t\tstate->step = 0;\n\n\t/* return the signal */\n\treturn state->signal;\n}\n\n\n\n/**********************************************************************************************\n\n     generate_adpcm -- general ADPCM decoding routine\n\n***********************************************************************************************/\n\n#define NMK_BNKTBLBITS\t8\n#define NMK_BNKTBLSIZE\t(1 << NMK_BNKTBLBITS)\t// 0x100\n#define NMK_TABLESIZE\t(4 * NMK_BNKTBLSIZE)\t// 0x400\n#define NMK_TABLEMASK\t(NMK_TABLESIZE - 1)\t\t// 0x3FF\n\n#define NMK_BANKBITS\t16\n#define NMK_BANKSIZE\t(1 << NMK_BANKBITS)\t\t// 0x10000\n#define NMK_BANKMASK\t(NMK_BANKSIZE - 1)\t\t// 0xFFFF\n#define NMK_ROMBASE\t\t(4 * NMK_BANKSIZE)\t\t// 0x40000\n\nstatic UINT8 memory_raw_read_byte(okim6295_state *chip, offs_t offset)\n{\n\toffs_t CurOfs;\n\t\n\tif (! chip->nmk_mode)\n\t{\n\t\tCurOfs = chip->bank_offs | offset;\n\t}\n\telse\n\t{\n\t\tUINT8 BankID;\n\t\t\n\t\tif (offset < NMK_TABLESIZE && (chip->nmk_mode & 0x80))\n\t\t{\n\t\t\t// pages sample table\n\t\t\tBankID = offset >> NMK_BNKTBLBITS;\n\t\t\tCurOfs = offset & NMK_TABLEMASK;\t// 0x3FF, not 0xFF\n\t\t}\n\t\telse\n\t\t{\n\t\t\tBankID = offset >> NMK_BANKBITS;\n\t\t\tCurOfs = offset & NMK_BANKMASK;\n\t\t}\n\t\tCurOfs |= (chip->nmk_bank[BankID & 0x03] << NMK_BANKBITS);\n\t\t// I modified MAME to write a clean sample ROM.\n\t\t// (Usually it moves the data by NMK_ROMBASE.)\n\t\t//CurOfs += NMK_ROMBASE;\n\t}\n\tif (CurOfs < chip->ROMSize)\n\t\treturn chip->ROM[CurOfs];\n\telse\n\t\treturn 0x00;\n}\n\nstatic void generate_adpcm(okim6295_state *chip, struct ADPCMVoice *voice, INT16 *buffer, int samples)\n{\n\t/* if this voice is active */\n\tif (voice->playing)\n\t{\n\t\toffs_t base = voice->base_offset;\n\t\tint sample = voice->sample;\n\t\tint count = voice->count;\n\n\t\t/* loop while we still have samples to generate */\n\t\twhile (samples)\n\t\t{\n\t\t\t/* compute the new amplitude and update the current step */\n\t\t\t//int nibble = memory_raw_read_byte(chip->device->space(), base + sample / 2) >> (((sample & 1) << 2) ^ 4);\n\t\t\tUINT8 nibble = memory_raw_read_byte(chip, base + sample / 2) >> (((sample & 1) << 2) ^ 4);\n\n\t\t\t/* output to the buffer, scaling by the volume */\n\t\t\t/* signal in range -2048..2047, volume in range 2..32 => signal * volume / 2 in range -32768..32767 */\n\t\t\t*buffer++ = clock_adpcm(&voice->adpcm, nibble) * voice->volume / 2;\n\t\t\tsamples--;\n\n\t\t\t/* next! */\n\t\t\tif (++sample >= count)\n\t\t\t{\n\t\t\t\tvoice->playing = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/* update the parameters */\n\t\tvoice->sample = sample;\n\t}\n\n\t/* fill the rest with silence */\n\twhile (samples--)\n\t\t*buffer++ = 0;\n}\n\n\n\n/**********************************************************************************************\n *\n *  OKIM 6295 ADPCM chip:\n *\n *  Command bytes are sent:\n *\n *      1xxx xxxx = start of 2-byte command sequence, xxxxxxx is the sample number to trigger\n *      abcd vvvv = second half of command; one of the abcd bits is set to indicate which voice\n *                  the v bits seem to be volumed\n *\n *      0abc d000 = stop playing; one or more of the abcd bits is set to indicate which voice(s)\n *\n *  Status is read:\n *\n *      ???? abcd = one bit per voice, set to 0 if nothing is playing, or 1 if it is active\n *\n***********************************************************************************************/\n\n\n/**********************************************************************************************\n\n     okim6295_update -- update the sound chip so that it is in sync with CPU execution\n\n***********************************************************************************************/\n\n//static STREAM_UPDATE( okim6295_update )\nvoid okim6295_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//okim6295_state *chip = (okim6295_state *)param;\n\tokim6295_state *chip = &OKIM6295Data[ChipID];\n\tint i;\n\n\tmemset(outputs[0], 0, samples * sizeof(*outputs[0]));\n\n\tfor (i = 0; i < OKIM6295_VOICES; i++)\n\t{\n\t\tstruct ADPCMVoice *voice = &chip->voice[i];\n\t\tif (! voice->Muted)\n\t\t{\n\t\t\tstream_sample_t *buffer = outputs[0];\n\t\t\tINT16 sample_data[MAX_SAMPLE_CHUNK];\n\t\t\tint remaining = samples;\n\n\t\t\t/* loop while we have samples remaining */\n\t\t\twhile (remaining)\n\t\t\t{\n\t\t\t\tint samples = (remaining > MAX_SAMPLE_CHUNK) ? MAX_SAMPLE_CHUNK : remaining;\n\t\t\t\tint samp;\n\n\t\t\t\tgenerate_adpcm(chip, voice, sample_data, samples);\n\t\t\t\tfor (samp = 0; samp < samples; samp++)\n\t\t\t\t\t*buffer++ += sample_data[samp];\n\n\t\t\t\tremaining -= samples;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tmemcpy(outputs[1], outputs[0], samples * sizeof(*outputs[0]));\n}\n\n\n\n/**********************************************************************************************\n\n     state save support for MAME\n\n***********************************************************************************************/\n\n/*static void adpcm_state_save_register(struct ADPCMVoice *voice, running_device *device, int index)\n{\n\tstate_save_register_device_item(device, index, voice->playing);\n\tstate_save_register_device_item(device, index, voice->sample);\n\tstate_save_register_device_item(device, index, voice->count);\n\tstate_save_register_device_item(device, index, voice->adpcm.signal);\n\tstate_save_register_device_item(device, index, voice->adpcm.step);\n\tstate_save_register_device_item(device, index, voice->volume);\n\tstate_save_register_device_item(device, index, voice->base_offset);\n}\n\nstatic STATE_POSTLOAD( okim6295_postload )\n{\n\trunning_device *device = (running_device *)param;\n\tokim6295_state *info = get_safe_token(device);\n\tokim6295_set_bank_base(device, info->bank_offs);\n}\n\nstatic void okim6295_state_save_register(okim6295_state *info, running_device *device)\n{\n\tint j;\n\n\tstate_save_register_device_item(device, 0, info->command);\n\tstate_save_register_device_item(device, 0, info->bank_offs);\n\tfor (j = 0; j < OKIM6295_VOICES; j++)\n\t\tadpcm_state_save_register(&info->voice[j], device, j);\n\n\tstate_save_register_postload(device->machine, okim6295_postload, (void *)device);\n}*/\n\n\n\n/**********************************************************************************************\n\n     DEVICE_START( okim6295 ) -- start emulation of an OKIM6295-compatible chip\n\n***********************************************************************************************/\n\n//static DEVICE_START( okim6295 )\nint device_start_okim6295(UINT8 ChipID, int clock)\n{\n\t//const okim6295_interface *intf = (const okim6295_interface *)device->baseconfig().static_config;\n\t//okim6295_state *info = get_safe_token(device);\n\tokim6295_state *info;\n\t//int divisor = intf->pin7 ? 132 : 165;\n\tint divisor;\n\t//int voice;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &OKIM6295Data[ChipID];\n\t\n\tcompute_tables();\n\n\tinfo->command = -1;\n\t//info->bank_installed = FALSE;\n\tinfo->bank_offs = 0;\n\tinfo->nmk_mode = 0x00;\n\tmemset(info->nmk_bank, 0x00, 4 * sizeof(UINT8));\n\t//info->device = device;\n\n\t//info->master_clock = device->clock;\n\tinfo->initial_clock = clock;\n\tinfo->master_clock = clock & 0x7FFFFFFF;\n\tinfo->pin7_state = (clock & 0x80000000) >> 31;\n\tinfo->SmpRateFunc = NULL;\n\n\t/* generate the name and create the stream */\n\tdivisor = info->pin7_state ? 132 : 165;\n\t//info->stream = stream_create(device, 0, 1, device->clock/divisor, info, okim6295_update);\n\n\t// moved to device_reset\n\t/*// initialize the voices //\n\tfor (voice = 0; voice < OKIM6295_VOICES; voice++)\n\t{\n\t\t// initialize the rest of the structure //\n\t\tinfo->voice[voice].volume = 0;\n\t\treset_adpcm(&info->voice[voice].adpcm);\n\t}*/\n\n\t//okim6295_state_save_register(info, device);\n\t\n\treturn info->master_clock / divisor;\n}\n\n\n\nvoid device_stop_okim6295(UINT8 ChipID)\n{\n\tokim6295_state* chip = &OKIM6295Data[ChipID];\n\t\n\tfree(chip->ROM);\tchip->ROM = NULL;\n\tchip->ROMSize = 0x00;\n\t\n\treturn;\n}\n\n/**********************************************************************************************\n\n     DEVICE_RESET( okim6295 ) -- stop emulation of an OKIM6295-compatible chip\n\n***********************************************************************************************/\n\n//static DEVICE_RESET( okim6295 )\nvoid device_reset_okim6295(UINT8 ChipID)\n{\n\t//okim6295_state *info = get_safe_token(device);\n\tokim6295_state *info = &OKIM6295Data[ChipID];\n\tint voice;\n\n\t//stream_update(info->stream);\n\t\n\tinfo->command = -1;\n\tinfo->bank_offs = 0;\n\tinfo->nmk_mode = 0x00;\n\tmemset(info->nmk_bank, 0x00, 4 * sizeof(UINT8));\n\tinfo->master_clock = info->initial_clock & 0x7FFFFFFF;\n\tinfo->pin7_state = (info->initial_clock & 0x80000000) >> 31;\n\t\n\tfor (voice = 0; voice < OKIM6295_VOICES; voice++)\n\t{\n\t\tinfo->voice[voice].volume = 0;\n\t\treset_adpcm(&info->voice[voice].adpcm);\n\t\t\n\t\tinfo->voice[voice].playing = 0;\n\t}\n}\n\n\n\n/**********************************************************************************************\n\n     okim6295_set_bank_base -- set the base of the bank for a given voice on a given chip\n\n***********************************************************************************************/\n\n//void okim6295_set_bank_base(running_device *device, int base)\nvoid okim6295_set_bank_base(okim6295_state *info, int base)\n{\n\t//okim6295_state *info = get_safe_token(device);\n\t//stream_update(info->stream);\n\n\t// if we are setting a non-zero base, and we have no bank, allocate one\n\t/*if (!info->bank_installed && base != 0)\n\t{\n\t\t// override our memory map with a bank\n\t\t//memory_install_read_bank(device->space(), 0x00000, 0x3ffff, 0, 0, device->tag());\n\t\tinfo->bank_installed = TRUE;\n\t}\n\n\t// if we have a bank number, set the base pointer\n\tif (info->bank_installed)\n\t{\n\t\tinfo->bank_offs = base;\n\t\t//memory_set_bankptr(device->machine, device->tag(), device->region->base.u8 + base);\n\t}*/\n\tinfo->bank_offs = base;\n}\n\n\n\n/**********************************************************************************************\n\n     okim6295_set_pin7 -- adjust pin 7, which controls the internal clock division\n\n***********************************************************************************************/\n\nstatic void okim6295_clock_changed(okim6295_state *info)\n{\n\tint divisor;\n\tdivisor = info->pin7_state ? 132 : 165;\n\t//stream_set_sample_rate(info->stream, info->master_clock/divisor);\n\tif (info->SmpRateFunc != NULL)\n\t\tinfo->SmpRateFunc(info->SmpRateData, info->master_clock / divisor);\n}\n\n//void okim6295_set_pin7(running_device *device, int pin7)\nINLINE void okim6295_set_pin7(okim6295_state *info, int pin7)\n{\n\t//okim6295_state *info = get_safe_token(device);\n\n\tinfo->pin7_state = pin7;\n\tokim6295_clock_changed(info);\n}\n\n\n/**********************************************************************************************\n\n     okim6295_status_r -- read the status port of an OKIM6295-compatible chip\n\n***********************************************************************************************/\n\n//READ8_DEVICE_HANDLER( okim6295_r )\nUINT8 okim6295_r(UINT8 ChipID, offs_t offset)\n{\n\t//okim6295_state *info = get_safe_token(device);\n\tokim6295_state *info = &OKIM6295Data[ChipID];\n\tint i, result;\n\n\tresult = 0xf0;\t/* naname expects bits 4-7 to be 1 */\n\n\t/* set the bit to 1 if something is playing on a given channel */\n\t//stream_update(info->stream);\n\tfor (i = 0; i < OKIM6295_VOICES; i++)\n\t{\n\t\tstruct ADPCMVoice *voice = &info->voice[i];\n\n\t\t/* set the bit if it's playing */\n\t\tif (voice->playing)\n\t\t\tresult |= 1 << i;\n\t}\n\n\treturn result;\n}\n\n\n\n/**********************************************************************************************\n\n     okim6295_data_w -- write to the data port of an OKIM6295-compatible chip\n\n***********************************************************************************************/\n\n//WRITE8_DEVICE_HANDLER( okim6295_w )\nvoid okim6295_write_command(okim6295_state *info, UINT8 data)\n{\n\t//okim6295_state *info = get_safe_token(device);\n\n\t/* if a command is pending, process the second half */\n\tif (info->command != -1)\n\t{\n\t\tint temp = data >> 4, i, start, stop;\n\t\toffs_t base;\n\n\t\t/* the manual explicitly says that it's not possible to start multiple voices at the same time */\n\t\tif (temp != 0 && temp != 1 && temp != 2 && temp != 4 && temp != 8)\n\t\t\tfprintf(stderr, \"OKI6295 start %x contact MAMEDEV\\n\", temp);\n\n\t\t/* update the stream */\n\t\t//stream_update(info->stream);\n\n\t\t/* determine which voice(s) (voice is set by a 1 bit in the upper 4 bits of the second byte) */\n\t\tfor (i = 0; i < OKIM6295_VOICES; i++, temp >>= 1)\n\t\t{\n\t\t\tif (temp & 1)\n\t\t\t{\n\t\t\t\tstruct ADPCMVoice *voice = &info->voice[i];\n\n\t\t\t\t/* determine the start/stop positions */\n\t\t\t\tbase = info->command * 8;\n\n\t\t\t\t//start  = memory_raw_read_byte(device->space(), base + 0) << 16;\n\t\t\t\tstart  = memory_raw_read_byte(info, base + 0) << 16;\n\t\t\t\tstart |= memory_raw_read_byte(info, base + 1) << 8;\n\t\t\t\tstart |= memory_raw_read_byte(info, base + 2) << 0;\n\t\t\t\tstart &= 0x3ffff;\n\n\t\t\t\tstop  = memory_raw_read_byte(info, base + 3) << 16;\n\t\t\t\tstop |= memory_raw_read_byte(info, base + 4) << 8;\n\t\t\t\tstop |= memory_raw_read_byte(info, base + 5) << 0;\n\t\t\t\tstop &= 0x3ffff;\n\n\t\t\t\t/* set up the voice to play this sample */\n\t\t\t\tif (start < stop)\n\t\t\t\t{\n\t\t\t\t\tif (!voice->playing) /* fixes Got-cha and Steel Force */\n\t\t\t\t\t{\n\t\t\t\t\t\tvoice->playing = 1;\n\t\t\t\t\t\tvoice->base_offset = start;\n\t\t\t\t\t\tvoice->sample = 0;\n\t\t\t\t\t\tvoice->count = 2 * (stop - start + 1);\n\n\t\t\t\t\t\t/* also reset the ADPCM parameters */\n\t\t\t\t\t\treset_adpcm(&voice->adpcm);\n\t\t\t\t\t\tvoice->volume = volume_table[data & 0x0f];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//logerror(\"OKIM6295:'%s' requested to play sample %02x on non-stopped voice\\n\",device->tag(),info->command);\n\t\t\t\t\t\t// just displays warnings when seeking\n\t\t\t\t\t\t//logerror(\"OKIM6295: Voice %u requested to play sample %02x on non-stopped voice\\n\",i,info->command);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t/* invalid samples go here */\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t//logerror(\"OKIM6295:'%s' requested to play invalid sample %02x\\n\",device->tag(),info->command);\n\t\t\t\t\tlogerror(\"OKIM6295: Voice %u  requested to play invalid sample %02x\\n\",i,info->command);\n\t\t\t\t\tvoice->playing = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* reset the command */\n\t\tinfo->command = -1;\n\t}\n\n\t/* if this is the start of a command, remember the sample number for next time */\n\telse if (data & 0x80)\n\t{\n\t\tinfo->command = data & 0x7f;\n\t}\n\n\t/* otherwise, see if this is a silence command */\n\telse\n\t{\n\t\tint temp = data >> 3, i;\n\n\t\t/* update the stream, then turn it off */\n\t\t//stream_update(info->stream);\n\n\t\t/* determine which voice(s) (voice is set by a 1 bit in bits 3-6 of the command */\n\t\tfor (i = 0; i < OKIM6295_VOICES; i++, temp >>= 1)\n\t\t{\n\t\t\tif (temp & 1)\n\t\t\t{\n\t\t\t\tstruct ADPCMVoice *voice = &info->voice[i];\n\n\t\t\t\tvoice->playing = 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid okim6295_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tokim6295_state* chip = &OKIM6295Data[ChipID];\n\t\n\tswitch(offset)\n\t{\n\tcase 0x00:\n\t\tokim6295_write_command(chip, data);\n\t\tbreak;\n\tcase 0x08:\n\t\tchip->master_clock &= ~0x000000FF;\n\t\tchip->master_clock |= data <<  0;\n\t\tbreak;\n\tcase 0x09:\n\t\tchip->master_clock &= ~0x0000FF00;\n\t\tchip->master_clock |= data <<  8;\n\t\tbreak;\n\tcase 0x0A:\n\t\tchip->master_clock &= ~0x00FF0000;\n\t\tchip->master_clock |= data << 16;\n\t\tbreak;\n\tcase 0x0B:\n\t\t//if ((data >> 7) != chip->pin7_state)\n\t\t//\tfprintf(stderr, \"Pin 7 changed!\\n\");\n\t\tdata &= 0x7F;\t// fix a bug in MAME VGM logs\n\t\tchip->master_clock &= ~0xFF000000;\n\t\tchip->master_clock |= data << 24;\n\t\tokim6295_clock_changed(chip);\n\t\tbreak;\n\tcase 0x0C:\n\t\tokim6295_set_pin7(chip, data);\n\t\tbreak;\n\tcase 0x0E:\t// NMK112 bank switch enable\n\t\tchip->nmk_mode = data;\n\t\tbreak;\n\tcase 0x0F:\n\t\tokim6295_set_bank_base(chip, data << 18);\n\t\tbreak;\n\tcase 0x10:\n\tcase 0x11:\n\tcase 0x12:\n\tcase 0x13:\n\t\tchip->nmk_bank[offset & 0x03] = data;\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\nvoid okim6295_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t\tconst UINT8* ROMData)\n{\n\tokim6295_state *chip = &OKIM6295Data[ChipID];\n\t\n\tif (chip->ROMSize != ROMSize)\n\t{\n\t\tchip->ROM = (UINT8*)realloc(chip->ROM, ROMSize);\n\t\tchip->ROMSize = ROMSize;\n\t\t//fprintf(stderr, \"OKIM6295: New ROM Size: 0x%05X\\n\", ROMSize);\n\t\tmemset(chip->ROM, 0xFF, ROMSize);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(chip->ROM + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\n\nvoid okim6295_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tokim6295_state *chip = &OKIM6295Data[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < OKIM6295_VOICES; CurChn ++)\n\t\tchip->voice[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\nvoid okim6295_set_srchg_cb(UINT8 ChipID, SRATE_CALLBACK CallbackFunc, void* DataPtr)\n{\n\tokim6295_state *info = &OKIM6295Data[ChipID];\n\t\n\t// set Sample Rate Change Callback routine\n\tinfo->SmpRateFunc = CallbackFunc;\n\tinfo->SmpRateData = DataPtr;\n\t\n\treturn;\n}\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( okim6295 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers --- //\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\tinfo->i = sizeof(okim6295_state);\t\t\t\tbreak;\n\t\tcase DEVINFO_INT_DATABUS_WIDTH_0:\t\t\tinfo->i = 8;\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_INT_ADDRBUS_WIDTH_0:\t\t\tinfo->i = 18;\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_INT_ADDRBUS_SHIFT_0:\t\t\tinfo->i = 0;\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data --- //\n\t\tcase DEVINFO_PTR_DEFAULT_MEMORY_MAP_0:\t\tinfo->default_map8 = ADDRESS_MAP_NAME(okim6295);break;\n\n\t\t// --- the following bits of info are returned as pointers to functions --- //\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( okim6295 );\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( okim6295 );\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings --- //\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\tstrcpy(info->s, \"OKI6295\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"OKI ADPCM\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/okim6295.h",
    "content": "#pragma once\n\n/* an interface for the OKIM6295 and similar chips */\n\n/*\n  Note about the playback frequency: the external clock is internally divided,\n  depending on pin 7, by 132 (high) or 165 (low).\n*/\n/*typedef struct _okim6295_interface okim6295_interface;\nstruct _okim6295_interface\n{\n\tint pin7;\n};\n\nextern const okim6295_interface okim6295_interface_pin7high;\nextern const okim6295_interface okim6295_interface_pin7low;*/\n\n\n\n//void okim6295_set_bank_base(running_device *device, int base);\n//void okim6295_set_pin7(running_device *device, int pin7);\n\nvoid okim6295_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_okim6295(UINT8 ChipID, int clock);\nvoid device_stop_okim6295(UINT8 ChipID);\nvoid device_reset_okim6295(UINT8 ChipID);\n\n//READ8_DEVICE_HANDLER( okim6295_r );\n//WRITE8_DEVICE_HANDLER( okim6295_w );\nvoid okim6295_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid okim6295_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t\tconst UINT8* ROMData);\nvoid okim6295_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\nvoid okim6295_set_srchg_cb(UINT8 ChipID, SRATE_CALLBACK CallbackFunc, void* DataPtr);\n\n\n/*\n    To help the various custom ADPCM generators out there,\n    the following routines may be used.\n*/\nstruct adpcm_state\n{\n\tINT32\tsignal;\n\tINT32\tstep;\n};\nvoid reset_adpcm(struct adpcm_state *state);\nINT16 clock_adpcm(struct adpcm_state *state, UINT8 nibble);\n\n//DEVICE_GET_INFO( okim6295 );\n//#define SOUND_OKIM6295 DEVICE_GET_INFO_NAME( okim6295 )\n"
  },
  {
    "path": "VGMPlay/chips/opl.c",
    "content": "// IMPORTANT: This file is not meant to be compiled. It's included in adlibemu_opl?.c.\n\n/*\n *  Copyright (C) 2002-2010  The DOSBox Team\n *  OPL2/OPL3 emulation library\n *\n *  This library is free software; you can redistribute it and/or\n *  modify it under the terms of the GNU Lesser General Public\n *  License as published by the Free Software Foundation; either\n *  version 2.1 of the License, or (at your option) any later version.\n * \n *  This library is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n *  Lesser General Public License for more details.\n * \n *  You should have received a copy of the GNU Lesser General Public\n *  License along with this library; if not, write to the Free Software\n *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n\n/*\n * Originally based on ADLIBEMU.C, an AdLib/OPL2 emulation library by Ken Silverman\n * Copyright (C) 1998-2001 Ken Silverman\n * Ken Silverman's official web site: \"http://www.advsys.net/ken\"\n */\n\n\n#include <math.h>\n#include <stdlib.h> // rand\n#include <string.h>\t// for memset\n//#include \"dosbox.h\"\n#include \"../stdbool.h\"\n#include \"opl.h\"\n\n\n//static fltype recipsamp;\t// inverse of sampling rate\t\t// moved to OPL_DATA\nstatic Bit16s wavtable[WAVEPREC*3];\t// wave form table\n\n// vibrato/tremolo tables\nstatic Bit32s vib_table[VIBTAB_SIZE];\nstatic Bit32s trem_table[TREMTAB_SIZE*2];\n\nstatic Bit32s vibval_const[BLOCKBUF_SIZE];\nstatic Bit32s tremval_const[BLOCKBUF_SIZE];\n\n// vibrato value tables (used per-operator)\nstatic Bit32s vibval_var1[BLOCKBUF_SIZE];\nstatic Bit32s vibval_var2[BLOCKBUF_SIZE];\n//static Bit32s vibval_var3[BLOCKBUF_SIZE];\n//static Bit32s vibval_var4[BLOCKBUF_SIZE];\n\n// vibrato/trmolo value table pointers\n//static Bit32s *vibval1, *vibval2, *vibval3, *vibval4;\n//static Bit32s *tremval1, *tremval2, *tremval3, *tremval4;\n// moved to adlib_getsample\n\n\n// key scale level lookup table\nstatic const fltype kslmul[4] = {\n\t0.0, 0.5, 0.25, 1.0\t\t// -> 0, 3, 1.5, 6 dB/oct\n};\n\n// frequency multiplicator lookup table\nstatic const fltype frqmul_tab[16] = {\n\t0.5,1,2,3,4,5,6,7,8,9,10,10,12,12,15,15\n};\n// calculated frequency multiplication values (depend on sampling rate)\n//static fltype frqmul[16];\t// moved to OPL_DATA\n\n// key scale levels\nstatic Bit8u kslev[8][16];\n\n// map a channel number to the register offset of the modulator (=register base)\nstatic const Bit8u modulatorbase[9]\t= {\n\t0,1,2,\n\t8,9,10,\n\t16,17,18\n};\n\n// map a register base to a modulator operator number or operator number\n#if defined(OPLTYPE_IS_OPL3)\nstatic const Bit8u regbase2modop[44] = {\n\t0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8,\t\t\t\t\t// first set\n\t18,19,20,18,19,20,0,0,21,22,23,21,22,23,0,0,24,25,26,24,25,26\t// second set\n};\nstatic const Bit8u regbase2op[44] = {\n\t0,1,2,9,10,11,0,0,3,4,5,12,13,14,0,0,6,7,8,15,16,17,\t\t\t// first set\n\t18,19,20,27,28,29,0,0,21,22,23,30,31,32,0,0,24,25,26,33,34,35\t// second set\n};\n#else\nstatic const Bit8u regbase2modop[22] = {\n\t0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8\n};\nstatic const Bit8u regbase2op[22] = {\n\t0,1,2,9,10,11,0,0,3,4,5,12,13,14,0,0,6,7,8,15,16,17\n};\n#endif\n\n\n// start of the waveform\nstatic Bit32u waveform[8] = {\n\tWAVEPREC,\n\tWAVEPREC>>1,\n\tWAVEPREC,\n\t(WAVEPREC*3)>>2,\n\t0,\n\t0,\n\t(WAVEPREC*5)>>2,\n\tWAVEPREC<<1\n};\n\n// length of the waveform as mask\nstatic Bit32u wavemask[8] = {\n\tWAVEPREC-1,\n\tWAVEPREC-1,\n\t(WAVEPREC>>1)-1,\n\t(WAVEPREC>>1)-1,\n\tWAVEPREC-1,\n\t((WAVEPREC*3)>>2)-1,\n\tWAVEPREC>>1,\n\tWAVEPREC-1\n};\n\n// where the first entry resides\nstatic Bit32u wavestart[8] = {\n\t0,\n\tWAVEPREC>>1,\n\t0,\n\tWAVEPREC>>2,\n\t0,\n\t0,\n\t0,\n\tWAVEPREC>>3\n};\n\n// envelope generator function constants\nstatic fltype attackconst[4] = {\n\t(fltype)(1/2.82624),\n\t(fltype)(1/2.25280),\n\t(fltype)(1/1.88416),\n\t(fltype)(1/1.59744)\n};\nstatic fltype decrelconst[4] = {\n\t(fltype)(1/39.28064),\n\t(fltype)(1/31.41608),\n\t(fltype)(1/26.17344),\n\t(fltype)(1/22.44608)\n};\n\n\nINLINE void operator_advance(OPL_DATA* chip, op_type* op_pt, Bit32s vib) {\n\top_pt->wfpos = op_pt->tcount;\t\t\t\t\t\t// waveform position\n\t\n\t// advance waveform time\n\top_pt->tcount += op_pt->tinc;\n\top_pt->tcount += (Bit32s)(op_pt->tinc)*vib/FIXEDPT;\n\n\top_pt->generator_pos += chip->generator_add;\n}\n\nINLINE void operator_advance_drums(OPL_DATA* chip, op_type* op_pt1, Bit32s vib1, op_type* op_pt2, Bit32s vib2, op_type* op_pt3, Bit32s vib3)\n{\n\tBit32u c1 = op_pt1->tcount/FIXEDPT;\n\tBit32u c3 = op_pt3->tcount/FIXEDPT;\n\tBit32u phasebit = (((c1 & 0x88) ^ ((c1<<5) & 0x80)) | ((c3 ^ (c3<<2)) & 0x20)) ? 0x02 : 0x00;\n\n\tBit32u noisebit = rand()&1;\n\n\tBit32u snare_phase_bit = (((Bitu)((op_pt1->tcount/FIXEDPT) / 0x100))&1);\n\n\t//Hihat\n\tBit32u inttm = (phasebit<<8) | (0x34<<(phasebit ^ (noisebit<<1)));\n\top_pt1->wfpos = inttm*FIXEDPT;\t\t\t\t// waveform position\n\t// advance waveform time\n\top_pt1->tcount += op_pt1->tinc;\n\top_pt1->tcount += (Bit32s)(op_pt1->tinc)*vib1/FIXEDPT;\n\top_pt1->generator_pos += chip->generator_add;\n\n\t//Snare\n\tinttm = ((1+snare_phase_bit) ^ noisebit)<<8;\n\top_pt2->wfpos = inttm*FIXEDPT;\t\t\t\t// waveform position\n\t// advance waveform time\n\top_pt2->tcount += op_pt2->tinc;\n\top_pt2->tcount += (Bit32s)(op_pt2->tinc)*vib2/FIXEDPT;\n\top_pt2->generator_pos += chip->generator_add;\n\n\t//Cymbal\n\tinttm = (1+phasebit)<<8;\n\top_pt3->wfpos = inttm*FIXEDPT;\t\t\t\t// waveform position\n\t// advance waveform time\n\top_pt3->tcount += op_pt3->tinc;\n\top_pt3->tcount += (Bit32s)(op_pt3->tinc)*vib3/FIXEDPT;\n\top_pt3->generator_pos += chip->generator_add;\n}\n\n\n// output level is sustained, mode changes only when operator is turned off (->release)\n// or when the keep-sustained bit is turned off (->sustain_nokeep)\nINLINE void operator_output(op_type* op_pt, Bit32s modulator, Bit32s trem)\n{\n\tif (op_pt->op_state != OF_TYPE_OFF)\n\t{\n\t\tBit32u i;\n\t\top_pt->lastcval = op_pt->cval;\n\t\ti = (Bit32u)((op_pt->wfpos+modulator)/FIXEDPT);\n\n\t\t// wform: -16384 to 16383 (0x4000)\n\t\t// trem :  32768 to 65535 (0x10000)\n\t\t// step_amp: 0.0 to 1.0\n\t\t// vol  : 1/2^14 to 1/2^29 (/0x4000; /1../0x8000)\n\n\t\top_pt->cval = (Bit32s)(op_pt->step_amp*op_pt->vol*op_pt->cur_wform[i&op_pt->cur_wmask]*trem/16.0);\n\t}\n}\n\n\n// no action, operator is off\nstatic void operator_off(op_type* op_pt) {\n}\n\n// output level is sustained, mode changes only when operator is turned off (->release)\n// or when the keep-sustained bit is turned off (->sustain_nokeep)\nstatic void operator_sustain(op_type* op_pt)\n{\n\tBit32u num_steps_add = op_pt->generator_pos/FIXEDPT;\t// number of (standardized) samples\n\tBit32u ct;\n\tfor (ct=0; ct<num_steps_add; ct++)\n\t{\n\t\top_pt->cur_env_step++;\n\t}\n\top_pt->generator_pos -= num_steps_add*FIXEDPT;\n}\n\n// operator in release mode, if output level reaches zero the operator is turned off\nstatic void operator_release(op_type* op_pt)\n{\n\tBit32u num_steps_add;\n\tBit32u ct;\n\t\n\t// ??? boundary?\n\tif (op_pt->amp > 0.00000001)\n\t{\n\t\t// release phase\n\t\top_pt->amp *= op_pt->releasemul;\n\t}\n\n\tnum_steps_add = op_pt->generator_pos/FIXEDPT;\t// number of (standardized) samples\n\tfor (ct=0; ct<num_steps_add; ct++)\n\t{\n\t\top_pt->cur_env_step++;\t\t\t\t\t\t// sample counter\n\t\tif ((op_pt->cur_env_step & op_pt->env_step_r)==0)\n\t\t{\n\t\t\tif (op_pt->amp <= 0.00000001)\n\t\t\t{\n\t\t\t\t// release phase finished, turn off this operator\n\t\t\t\top_pt->amp = 0.0;\n\t\t\t\tif (op_pt->op_state == OF_TYPE_REL)\n\t\t\t\t{\n\t\t\t\t\top_pt->op_state = OF_TYPE_OFF;\n\t\t\t\t}\n\t\t\t}\n\t\t\top_pt->step_amp = op_pt->amp;\n\t\t}\n\t}\n\top_pt->generator_pos -= num_steps_add*FIXEDPT;\n}\n\n// operator in decay mode, if sustain level is reached the output level is either\n// kept (sustain level keep enabled) or the operator is switched into release mode\nstatic void operator_decay(op_type* op_pt)\n{\n\tBit32u num_steps_add;\n\tBit32u ct;\n\t\n\tif (op_pt->amp > op_pt->sustain_level)\n\t{\n\t\t// decay phase\n\t\top_pt->amp *= op_pt->decaymul;\n\t}\n\n\tnum_steps_add = op_pt->generator_pos/FIXEDPT;\t// number of (standardized) samples\n\tfor (ct=0; ct<num_steps_add; ct++)\n\t{\n\t\top_pt->cur_env_step++;\n\t\tif ((op_pt->cur_env_step & op_pt->env_step_d)==0)\n\t\t{\n\t\t\tif (op_pt->amp <= op_pt->sustain_level)\n\t\t\t{\n\t\t\t\t// decay phase finished, sustain level reached\n\t\t\t\tif (op_pt->sus_keep)\n\t\t\t\t{\n\t\t\t\t\t// keep sustain level (until turned off)\n\t\t\t\t\top_pt->op_state = OF_TYPE_SUS;\n\t\t\t\t\top_pt->amp = op_pt->sustain_level;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// next: release phase\n\t\t\t\t\top_pt->op_state = OF_TYPE_SUS_NOKEEP;\n\t\t\t\t}\n\t\t\t}\n\t\t\top_pt->step_amp = op_pt->amp;\n\t\t}\n\t}\n\top_pt->generator_pos -= num_steps_add*FIXEDPT;\n}\n\n// operator in attack mode, if full output level is reached,\n// the operator is switched into decay mode\nstatic void operator_attack(op_type* op_pt)\n{\n\tBit32u num_steps_add;\n\tBit32u ct;\n\t\n\top_pt->amp = ((op_pt->a3*op_pt->amp + op_pt->a2)*op_pt->amp + op_pt->a1)*op_pt->amp + op_pt->a0;\n\n\tnum_steps_add = op_pt->generator_pos/FIXEDPT;\t\t// number of (standardized) samples\n\tfor (ct=0; ct<num_steps_add; ct++)\n\t{\n\t\top_pt->cur_env_step++;\t// next sample\n\t\tif ((op_pt->cur_env_step & op_pt->env_step_a)==0)\n\t\t{\t\t// check if next step already reached\n\t\t\tif (op_pt->amp > 1.0)\n\t\t\t{\n\t\t\t\t// attack phase finished, next: decay\n\t\t\t\top_pt->op_state = OF_TYPE_DEC;\n\t\t\t\top_pt->amp = 1.0;\n\t\t\t\top_pt->step_amp = 1.0;\n\t\t\t}\n\t\t\top_pt->step_skip_pos_a <<= 1;\n\t\t\tif (op_pt->step_skip_pos_a==0) op_pt->step_skip_pos_a = 1;\n\t\t\tif (op_pt->step_skip_pos_a & op_pt->env_step_skip_a)\n\t\t\t{\t// check if required to skip next step\n\t\t\t\top_pt->step_amp = op_pt->amp;\n\t\t\t}\n\t\t}\n\t}\n\top_pt->generator_pos -= num_steps_add*FIXEDPT;\n}\n\nstatic void operator_eg_attack_check(op_type* op_pt)\n{\n\tif (((op_pt->cur_env_step + 1) & op_pt->env_step_a)==0)\n\t{\n\t\t// check if next step already reached\n\t\tif (op_pt->a0 >= 1.0)\n\t\t{\n\t\t\t// attack phase finished, next: decay\n\t\t\top_pt->op_state = OF_TYPE_DEC;\n\t\t\top_pt->amp = 1.0;\n\t\t\top_pt->step_amp = 1.0;\n\t\t}\n\t}\n}\n\n\ntypedef void (*optype_fptr)(op_type*);\n\nstatic optype_fptr opfuncs[6] = {\n\toperator_attack,\n\toperator_decay,\n\toperator_release,\n\toperator_sustain,\t// sustain phase (keeping level)\n\toperator_release,\t// sustain_nokeep phase (release-style)\n\toperator_off\n};\n\nstatic void change_attackrate(OPL_DATA* chip, Bitu regbase, op_type* op_pt)\n{\n\tBits attackrate = chip->adlibreg[ARC_ATTR_DECR+regbase]>>4;\n\tif (attackrate)\n\t{\n\t\tstatic Bit8u step_skip_mask[5] = {0xff, 0xfe, 0xee, 0xba, 0xaa}; \n\t\tBits step_skip;\n\t\tBits steps;\n\t\tBits step_num;\n\t\t\n\t\tfltype f = (fltype)(pow(FL2,(fltype)attackrate+(op_pt->toff>>2)-1)*attackconst[op_pt->toff&3]*chip->recipsamp);\n\t\t// attack rate coefficients\n\t\top_pt->a0 = (fltype)(0.0377*f);\n\t\top_pt->a1 = (fltype)(10.73*f+1);\n\t\top_pt->a2 = (fltype)(-17.57*f);\n\t\top_pt->a3 = (fltype)(7.42*f);\n\n\t\tstep_skip = attackrate*4 + op_pt->toff;\n\t\tsteps = step_skip >> 2;\n\t\top_pt->env_step_a = (1<<(steps<=12?12-steps:0))-1;\n\n\t\tstep_num = (step_skip<=48)?(4-(step_skip&3)):0;\n\t\top_pt->env_step_skip_a = step_skip_mask[step_num];\n\n#if defined(OPLTYPE_IS_OPL3)\n\t\tif (step_skip>=60)\n#else\n\t\tif (step_skip>=62)\n#endif\n\t\t{\n\t\t\top_pt->a0 = (fltype)(2.0);\t// something that triggers an immediate transition to amp:=1.0\n\t\t\top_pt->a1 = (fltype)(0.0);\n\t\t\top_pt->a2 = (fltype)(0.0);\n\t\t\top_pt->a3 = (fltype)(0.0);\n\t\t}\n\t}\n\telse\n\t{\n\t\t// attack disabled\n\t\top_pt->a0 = 0.0;\n\t\top_pt->a1 = 1.0;\n\t\top_pt->a2 = 0.0;\n\t\top_pt->a3 = 0.0;\n\t\top_pt->env_step_a = 0;\n\t\top_pt->env_step_skip_a = 0;\n\t}\n}\n\nstatic void change_decayrate(OPL_DATA* chip, Bitu regbase, op_type* op_pt)\n{\n\tBits decayrate = chip->adlibreg[ARC_ATTR_DECR+regbase]&15;\n\t// decaymul should be 1.0 when decayrate==0\n\tif (decayrate) {\n\t\tBits steps;\n\t\t\n\t\tfltype f = (fltype)(-7.4493*decrelconst[op_pt->toff&3]*chip->recipsamp);\n\t\top_pt->decaymul = (fltype)(pow(FL2,f*pow(FL2,(fltype)(decayrate+(op_pt->toff>>2)))));\n\t\tsteps = (decayrate*4 + op_pt->toff) >> 2;\n\t\top_pt->env_step_d = (1<<(steps<=12?12-steps:0))-1;\n\t}\n\telse\n\t{\n\t\top_pt->decaymul = 1.0;\n\t\top_pt->env_step_d = 0;\n\t}\n}\n\nstatic void change_releaserate(OPL_DATA* chip, Bitu regbase, op_type* op_pt)\n{\n\tBits releaserate = chip->adlibreg[ARC_SUSL_RELR+regbase]&15;\n\t// releasemul should be 1.0 when releaserate==0\n\tif (releaserate)\n\t{\n\t\tBits steps;\n\t\t\n\t\tfltype f = (fltype)(-7.4493*decrelconst[op_pt->toff&3]*chip->recipsamp);\n\t\top_pt->releasemul = (fltype)(pow(FL2,f*pow(FL2,(fltype)(releaserate+(op_pt->toff>>2)))));\n\t\tsteps = (releaserate*4 + op_pt->toff) >> 2;\n\t\top_pt->env_step_r = (1<<(steps<=12?12-steps:0))-1;\n\t}\n\telse\n\t{\n\t\top_pt->releasemul = 1.0;\n\t\top_pt->env_step_r = 0;\n\t}\n}\n\nstatic void change_sustainlevel(OPL_DATA* chip, Bitu regbase, op_type* op_pt)\n{\n\tBits sustainlevel = chip->adlibreg[ARC_SUSL_RELR+regbase]>>4;\n\t// sustainlevel should be 0.0 when sustainlevel==15 (max)\n\tif (sustainlevel<15)\n\t{\n\t\top_pt->sustain_level = (fltype)(pow(FL2,(fltype)sustainlevel * (-FL05)));\n\t}\n\telse\n\t{\n\t\top_pt->sustain_level = 0.0;\n\t}\n}\n\nstatic void change_waveform(OPL_DATA* chip, Bitu regbase, op_type* op_pt)\n{\n#if defined(OPLTYPE_IS_OPL3)\n\tif (regbase>=ARC_SECONDSET) regbase -= (ARC_SECONDSET-22);\t// second set starts at 22\n#endif\n\t// waveform selection\n\top_pt->cur_wmask = wavemask[chip->wave_sel[regbase]];\n\top_pt->cur_wform = &wavtable[waveform[chip->wave_sel[regbase]]];\n\t// (might need to be adapted to waveform type here...)\n}\n\nstatic void change_keepsustain(OPL_DATA* chip, Bitu regbase, op_type* op_pt)\n{\n\top_pt->sus_keep = (chip->adlibreg[ARC_TVS_KSR_MUL+regbase]&0x20)>0;\n\tif (op_pt->op_state==OF_TYPE_SUS)\n\t{\n\t\tif (!op_pt->sus_keep)\n\t\t\top_pt->op_state = OF_TYPE_SUS_NOKEEP;\n\t}\n\telse if (op_pt->op_state==OF_TYPE_SUS_NOKEEP)\n\t{\n\t\tif (op_pt->sus_keep)\n\t\t\top_pt->op_state = OF_TYPE_SUS;\n\t}\n}\n\n// enable/disable vibrato/tremolo LFO effects\nstatic void change_vibrato(OPL_DATA* chip, Bitu regbase, op_type* op_pt)\n{\n\top_pt->vibrato = (chip->adlibreg[ARC_TVS_KSR_MUL+regbase]&0x40)!=0;\n\top_pt->tremolo = (chip->adlibreg[ARC_TVS_KSR_MUL+regbase]&0x80)!=0;\n}\n\n// change amount of self-feedback\nstatic void change_feedback(OPL_DATA* chip, Bitu chanbase, op_type* op_pt)\n{\n\tBits feedback = chip->adlibreg[ARC_FEEDBACK+chanbase]&14;\n\tif (feedback)\n\t\top_pt->mfbi = (Bit32s)(pow(FL2,(fltype)((feedback>>1)+8)));\n\telse\n\t\top_pt->mfbi = 0;\n}\n\nstatic void change_frequency(OPL_DATA* chip, Bitu chanbase, Bitu regbase, op_type* op_pt)\n{\n\tBit32u frn;\n\tBit32u oct;\n\tBit32u note_sel;\n\tfltype vol_in;\n\t\n\t// frequency\n\tfrn = ((((Bit32u)chip->adlibreg[ARC_KON_BNUM+chanbase])&3)<<8) + (Bit32u)chip->adlibreg[ARC_FREQ_NUM+chanbase];\n\t// block number/octave\n\toct = ((((Bit32u)chip->adlibreg[ARC_KON_BNUM+chanbase])>>2)&7);\n\top_pt->freq_high = (Bit32s)((frn>>7)&7);\n\n\t// keysplit\n\tnote_sel = (chip->adlibreg[8]>>6)&1;\n\top_pt->toff = ((frn>>9)&(note_sel^1)) | ((frn>>8)&note_sel);\n\top_pt->toff += (oct<<1);\n\n\t// envelope scaling (KSR)\n\tif (!(chip->adlibreg[ARC_TVS_KSR_MUL+regbase]&0x10)) op_pt->toff >>= 2;\n\n\t// 20+a0+b0:\n\top_pt->tinc = (Bit32u)((((fltype)(frn<<oct))*chip->frqmul[chip->adlibreg[ARC_TVS_KSR_MUL+regbase]&15]));\n\t// 40+a0+b0:\n\tvol_in = (fltype)((fltype)(chip->adlibreg[ARC_KSL_OUTLEV+regbase]&63) +\n\t\t\t\t\t\t\tkslmul[chip->adlibreg[ARC_KSL_OUTLEV+regbase]>>6]*kslev[oct][frn>>6]);\n\top_pt->vol = (fltype)(pow(FL2,(fltype)(vol_in * -0.125 - 14)));\n\n\t// operator frequency changed, care about features that depend on it\n\tchange_attackrate(chip, regbase,op_pt);\n\tchange_decayrate(chip, regbase,op_pt);\n\tchange_releaserate(chip, regbase,op_pt);\n}\n\nstatic void enable_operator(OPL_DATA* chip, Bitu regbase, op_type* op_pt, Bit32u act_type)\n{\n\t// check if this is really an off-on transition\n\tif (op_pt->act_state == OP_ACT_OFF)\n\t{\n\t\tBits wselbase = regbase;\n\t\tif (wselbase>=ARC_SECONDSET)\n\t\t\twselbase -= (ARC_SECONDSET-22);\t// second set starts at 22\n\n\t\top_pt->tcount = wavestart[chip->wave_sel[wselbase]]*FIXEDPT;\n\n\t\t// start with attack mode\n\t\top_pt->op_state = OF_TYPE_ATT;\n\t\top_pt->act_state |= act_type;\n\t}\n}\n\nstatic void disable_operator(op_type* op_pt, Bit32u act_type)\n{\n\t// check if this is really an on-off transition\n\tif (op_pt->act_state != OP_ACT_OFF)\n\t{\n\t\top_pt->act_state &= (~act_type);\n\t\tif (op_pt->act_state == OP_ACT_OFF)\n\t\t{\n\t\t\tif (op_pt->op_state != OF_TYPE_OFF)\n\t\t\t\top_pt->op_state = OF_TYPE_REL;\n\t\t}\n\t}\n}\n\n//void adlib_init(Bit32u samplerate)\nvoid* ADLIBEMU(init)(UINT32 clock, UINT32 samplerate,\n\t\t\t\t\t ADL_UPDATEHANDLER UpdateHandler, void* param)\n{\n\tOPL_DATA* OPL;\n\t//op_type* op;\n\n\tBits i, j, oct;\n\t//Bit32s trem_table_int[TREMTAB_SIZE];\n\tstatic Bitu initfirstime = 0;\n\n\tOPL = (OPL_DATA*)malloc(sizeof(OPL_DATA));\n\tOPL->chip_clock = clock;\n\tOPL->int_samplerate = samplerate;\n\tOPL->UpdateHandler = UpdateHandler;\n\tOPL->UpdateParam = param;\n\n\tOPL->generator_add = (Bit32u)(INTFREQU*FIXEDPT/OPL->int_samplerate);\n\n\n\t/*memset(OPL->adlibreg,0,sizeof(OPL->adlibreg));\n\tmemset(OPL->op,0,sizeof(op_type)*MAXOPERATORS);\n\tmemset(OPL->wave_sel,0,sizeof(OPL->wave_sel));\n\n\tfor (i=0;i<MAXOPERATORS;i++)\n\t{\n\t\top = &OPL->op[i];\n\t\t\n\t\top->op_state = OF_TYPE_OFF;\n\t\top->act_state = OP_ACT_OFF;\n\t\top->amp = 0.0;\n\t\top->step_amp = 0.0;\n\t\top->vol = 0.0;\n\t\top->tcount = 0;\n\t\top->tinc = 0;\n\t\top->toff = 0;\n\t\top->cur_wmask = wavemask[0];\n\t\top->cur_wform = &wavtable[waveform[0]];\n\t\top->freq_high = 0;\n\n\t\top->generator_pos = 0;\n\t\top->cur_env_step = 0;\n\t\top->env_step_a = 0;\n\t\top->env_step_d = 0;\n\t\top->env_step_r = 0;\n\t\top->step_skip_pos_a = 0;\n\t\top->env_step_skip_a = 0;\n\n#if defined(OPLTYPE_IS_OPL3)\n\t\top->is_4op = false;\n\t\top->is_4op_attached = false;\n\t\top->left_pan = 1;\n\t\top->right_pan = 1;\n#endif\n\t}*/\n\n\tOPL->recipsamp = 1.0 / (fltype)OPL->int_samplerate;\n\tfor (i=15;i>=0;i--)\n\t{\n\t\tOPL->frqmul[i] = (fltype)(frqmul_tab[i]*INTFREQU/(fltype)WAVEPREC*(fltype)FIXEDPT*OPL->recipsamp);\n\t}\n\n\t//OPL->status = 0;\n\t//OPL->opl_index = 0;\n\n\n\tif (!initfirstime)\n\t{\n\t\t// create vibrato table\n\t\tvib_table[0] = 8;\n\t\tvib_table[1] = 4;\n\t\tvib_table[2] = 0;\n\t\tvib_table[3] = -4;\n\t\tfor (i=4; i<VIBTAB_SIZE; i++) vib_table[i] = vib_table[i-4]*-1;\n\t}\n\n\t// vibrato at ~6.1 ?? (opl3 docs say 6.1, opl4 docs say 6.0, y8950 docs say 6.4)\n\tOPL->vibtab_add = (Bit32u)(VIBTAB_SIZE*FIXEDPT_LFO/8192*INTFREQU/OPL->int_samplerate);\n\tOPL->vibtab_pos = 0;\n\n\tif (!initfirstime)\n\t{\n\t\tBit32s trem_table_int[TREMTAB_SIZE];\n\t\t\n\t\tfor (i=0; i<BLOCKBUF_SIZE; i++) vibval_const[i] = 0;\n\n\n\t\t// create tremolo table\n\t\tfor (i=0; i<14; i++)\ttrem_table_int[i] = i-13;\t\t// upwards (13 to 26 -> -0.5/6 to 0)\n\t\tfor (i=14; i<41; i++)\ttrem_table_int[i] = -i+14;\t\t// downwards (26 to 0 -> 0 to -1/6)\n\t\tfor (i=41; i<53; i++)\ttrem_table_int[i] = i-40-26;\t// upwards (1 to 12 -> -1/6 to -0.5/6)\n\n\t\tfor (i=0; i<TREMTAB_SIZE; i++)\n\t\t{\n\t\t\t// 0.0 .. -26/26*4.8/6 == [0.0 .. -0.8], 4/53 steps == [1 .. 0.57]\n\t\t\tfltype trem_val1=(fltype)(((fltype)trem_table_int[i])*4.8/26.0/6.0);\t\t\t\t// 4.8db\n\t\t\tfltype trem_val2=(fltype)((fltype)((Bit32s)(trem_table_int[i]/4))*1.2/6.0/6.0);\t\t// 1.2db (larger stepping)\n\n\t\t\ttrem_table[i] = (Bit32s)(pow(FL2,trem_val1)*FIXEDPT);\n\t\t\ttrem_table[TREMTAB_SIZE+i] = (Bit32s)(pow(FL2,trem_val2)*FIXEDPT);\n\t\t}\n\t}\n\n\t// tremolo at 3.7hz\n\tOPL->tremtab_add = (Bit32u)((fltype)TREMTAB_SIZE * TREM_FREQ * FIXEDPT_LFO / (fltype)OPL->int_samplerate);\n\tOPL->tremtab_pos = 0;\n\n\tif (!initfirstime)\n\t{\n\t\tinitfirstime = 1;\n\n\t\tfor (i=0; i<BLOCKBUF_SIZE; i++) tremval_const[i] = FIXEDPT;\n\n\n\t\t// create waveform tables\n\t\tfor (i=0;i<(WAVEPREC>>1);i++)\n\t\t{\n\t\t\twavtable[(i<<1)  +WAVEPREC]\t= (Bit16s)(16384*sin((fltype)((i<<1)  )*PI*2/WAVEPREC));\n\t\t\twavtable[(i<<1)+1+WAVEPREC]\t= (Bit16s)(16384*sin((fltype)((i<<1)+1)*PI*2/WAVEPREC));\n\t\t\twavtable[i]\t\t\t\t\t= wavtable[(i<<1)  +WAVEPREC];\n\t\t\t// alternative: (zero-less)\n/*\t\t\twavtable[(i<<1)  +WAVEPREC]\t= (Bit16s)(16384*sin((fltype)((i<<2)+1)*PI/WAVEPREC));\n\t\t\twavtable[(i<<1)+1+WAVEPREC]\t= (Bit16s)(16384*sin((fltype)((i<<2)+3)*PI/WAVEPREC));\n\t\t\twavtable[i]\t\t\t\t\t= wavtable[(i<<1)-1+WAVEPREC]; */\n\t\t}\n\t\tfor (i=0;i<(WAVEPREC>>3);i++)\n\t\t{\n\t\t\twavtable[i+(WAVEPREC<<1)]\t\t= wavtable[i+(WAVEPREC>>3)]-16384;\n\t\t\twavtable[i+((WAVEPREC*17)>>3)]\t= wavtable[i+(WAVEPREC>>2)]+16384;\n\t\t}\n\n\t\t// key scale level table verified ([table in book]*8/3)\n\t\tkslev[7][0] = 0;\tkslev[7][1] = 24;\tkslev[7][2] = 32;\tkslev[7][3] = 37;\n\t\tkslev[7][4] = 40;\tkslev[7][5] = 43;\tkslev[7][6] = 45;\tkslev[7][7] = 47;\n\t\tkslev[7][8] = 48;\n\t\tfor (i=9;i<16;i++) kslev[7][i] = (Bit8u)(i+41);\n\t\tfor (j=6;j>=0;j--)\n\t\t{\n\t\t\tfor (i=0;i<16;i++)\n\t\t\t{\n\t\t\t\toct = (Bits)kslev[j+1][i]-8;\n\t\t\t\tif (oct < 0) oct = 0;\n\t\t\t\tkslev[j][i] = (Bit8u)oct;\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn OPL;\n}\n\nvoid ADLIBEMU(stop)(void *chip)\n{\n\tfree(chip);\n\t\n\treturn;\n}\n\nvoid ADLIBEMU(reset)(void *chip)\n{\n\tOPL_DATA* OPL = (OPL_DATA*)chip;\n\tBits i;\n\top_type* op;\n\t\n\tmemset(OPL->adlibreg, 0x00, sizeof(OPL->adlibreg));\n\tmemset(OPL->op, 0x00, sizeof(op_type) * MAXOPERATORS);\n\tmemset(OPL->wave_sel, 0x00, sizeof(OPL->wave_sel));\n\t\n\tfor (i=0;i<MAXOPERATORS;i++)\n\t{\n\t\top = &OPL->op[i];\n\t\t\n\t\top->op_state = OF_TYPE_OFF;\n\t\top->act_state = OP_ACT_OFF;\n\t\top->amp = 0.0;\n\t\top->step_amp = 0.0;\n\t\top->vol = 0.0;\n\t\top->tcount = 0;\n\t\top->tinc = 0;\n\t\top->toff = 0;\n\t\top->cur_wmask = wavemask[0];\n\t\top->cur_wform = &wavtable[waveform[0]];\n\t\top->freq_high = 0;\n\n\t\top->generator_pos = 0;\n\t\top->cur_env_step = 0;\n\t\top->env_step_a = 0;\n\t\top->env_step_d = 0;\n\t\top->env_step_r = 0;\n\t\top->step_skip_pos_a = 0;\n\t\top->env_step_skip_a = 0;\n\n#if defined(OPLTYPE_IS_OPL3)\n\t\top->is_4op = false;\n\t\top->is_4op_attached = false;\n\t\top->left_pan = 1;\n\t\top->right_pan = 1;\n#endif\n\t}\n\t\n\tOPL->status = 0;\n\tOPL->opl_index = 0;\n\tOPL->opl_addr = 0;\n\t\n\treturn;\n}\n\n\n\nvoid ADLIBEMU(writeIO)(void *chip, UINT32 addr, UINT8 val)\n{\n\tOPL_DATA* OPL = (OPL_DATA*)chip;\n\t\n\tif (addr & 1)\n\t\tadlib_write(OPL, OPL->opl_addr, val);\n\telse\n#if defined(OPLTYPE_IS_OPL3)\n\t\tOPL->opl_addr = val | ((addr & 2) << 7);\n#else\n\t\tOPL->opl_addr = val;\n#endif\n}\n\nstatic void adlib_write(void *chip, Bitu idx, Bit8u val)\n{\n\tOPL_DATA* OPL = (OPL_DATA*)chip;\n\t\n\tBit32u second_set = idx&0x100;\n\tOPL->adlibreg[idx] = val;\n\n\tswitch (idx&0xf0)\n\t{\n\tcase ARC_CONTROL:\n\t\t// here we check for the second set registers, too:\n\t\tswitch (idx)\n\t\t{\n\t\tcase 0x02:\t// timer1 counter\n\t\tcase 0x03:\t// timer2 counter\n\t\t\tbreak;\n\t\tcase 0x04:\n\t\t\t// IRQ reset, timer mask/start\n\t\t\tif (val&0x80)\n\t\t\t{\n\t\t\t\t// clear IRQ bits in status register\n\t\t\t\tOPL->status &= ~0x60;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tOPL->status = 0;\n\t\t\t}\n\t\t\tbreak;\n#if defined(OPLTYPE_IS_OPL3)\n\t\tcase 0x04|ARC_SECONDSET:\n\t\t\t// 4op enable/disable switches for each possible channel\n\t\t\tOPL->op[0].is_4op = (val&1)>0;\n\t\t\tOPL->op[3].is_4op_attached = OPL->op[0].is_4op;\n\t\t\tOPL->op[1].is_4op = (val&2)>0;\n\t\t\tOPL->op[4].is_4op_attached = OPL->op[1].is_4op;\n\t\t\tOPL->op[2].is_4op = (val&4)>0;\n\t\t\tOPL->op[5].is_4op_attached = OPL->op[2].is_4op;\n\t\t\tOPL->op[18].is_4op = (val&8)>0;\n\t\t\tOPL->op[21].is_4op_attached = OPL->op[18].is_4op;\n\t\t\tOPL->op[19].is_4op = (val&16)>0;\n\t\t\tOPL->op[22].is_4op_attached = OPL->op[19].is_4op;\n\t\t\tOPL->op[20].is_4op = (val&32)>0;\n\t\t\tOPL->op[23].is_4op_attached = OPL->op[20].is_4op;\n\t\t\tbreak;\n\t\tcase 0x05|ARC_SECONDSET:\n\t\t\tbreak;\n#endif\n\t\tcase 0x08:\n\t\t\t// CSW, note select\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase ARC_TVS_KSR_MUL:\n\tcase ARC_TVS_KSR_MUL+0x10:\n\t\t{\n\t\t// tremolo/vibrato/sustain keeping enabled; key scale rate; frequency multiplication\n\t\tint num = idx&7;\n\t\tBitu base = (idx-ARC_TVS_KSR_MUL)&0xff;\n\t\tif ((num<6) && (base<22)) {\n\t\t\tBitu modop = regbase2modop[second_set?(base+22):base];\n\t\t\tBitu regbase = base+second_set;\n\t\t\tBitu chanbase = second_set?(modop-18+ARC_SECONDSET):modop;\n\n\t\t\t// change tremolo/vibrato and sustain keeping of this operator\n\t\t\top_type* op_ptr = &OPL->op[modop+((num<3) ? 0 : 9)];\n\t\t\tchange_keepsustain(chip, regbase,op_ptr);\n\t\t\tchange_vibrato(chip, regbase,op_ptr);\n\n\t\t\t// change frequency calculations of this operator as\n\t\t\t// key scale rate and frequency multiplicator can be changed\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\tif ((OPL->adlibreg[0x105]&1) && (OPL->op[modop].is_4op_attached))\n\t\t\t{\n\t\t\t\t// operator uses frequency of channel\n\t\t\t\tchange_frequency(chip, chanbase-3,regbase,op_ptr);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tchange_frequency(chip, chanbase,regbase,op_ptr);\n\t\t\t}\n#else\n\t\t\tchange_frequency(chip, chanbase,base,op_ptr);\n#endif\n\t\t}\n\t\t}\n\t\tbreak;\n\tcase ARC_KSL_OUTLEV:\n\tcase ARC_KSL_OUTLEV+0x10:\n\t\t{\n\t\t// key scale level; output rate\n\t\tint num = idx&7;\n\t\tBitu base = (idx-ARC_KSL_OUTLEV)&0xff;\n\t\tif ((num<6) && (base<22))\n\t\t{\n\t\t\tBitu modop = regbase2modop[second_set?(base+22):base];\n\t\t\tBitu chanbase = second_set?(modop-18+ARC_SECONDSET):modop;\n\n\t\t\t// change frequency calculations of this operator as\n\t\t\t// key scale level and output rate can be changed\n\t\t\top_type* op_ptr = &OPL->op[modop+((num<3) ? 0 : 9)];\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\tBitu regbase = base+second_set;\n\t\t\tif ((OPL->adlibreg[0x105]&1) && (OPL->op[modop].is_4op_attached))\n\t\t\t{\n\t\t\t\t// operator uses frequency of channel\n\t\t\t\tchange_frequency(chip, chanbase-3,regbase,op_ptr);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tchange_frequency(chip, chanbase,regbase,op_ptr);\n\t\t\t}\n#else\n\t\t\tchange_frequency(chip, chanbase,base,op_ptr);\n#endif\n\t\t}\n\t\t}\n\t\tbreak;\n\tcase ARC_ATTR_DECR:\n\tcase ARC_ATTR_DECR+0x10:\n\t\t{\n\t\t// attack/decay rates\n\t\tint num = idx&7;\n\t\tBitu base = (idx-ARC_ATTR_DECR)&0xff;\n\t\tif ((num<6) && (base<22))\n\t\t{\n\t\t\tBitu regbase = base+second_set;\n\n\t\t\t// change attack rate and decay rate of this operator\n\t\t\top_type* op_ptr = &OPL->op[regbase2op[second_set?(base+22):base]];\n\t\t\tchange_attackrate(chip, regbase,op_ptr);\n\t\t\tchange_decayrate(chip, regbase,op_ptr);\n\t\t}\n\t\t}\n\t\tbreak;\n\tcase ARC_SUSL_RELR:\n\tcase ARC_SUSL_RELR+0x10:\n\t\t{\n\t\t// sustain level; release rate\n\t\tint num = idx&7;\n\t\tBitu base = (idx-ARC_SUSL_RELR)&0xff;\n\t\tif ((num<6) && (base<22))\n\t\t{\n\t\t\tBitu regbase = base+second_set;\n\n\t\t\t// change sustain level and release rate of this operator\n\t\t\top_type* op_ptr = &OPL->op[regbase2op[second_set?(base+22):base]];\n\t\t\tchange_releaserate(chip, regbase,op_ptr);\n\t\t\tchange_sustainlevel(chip, regbase,op_ptr);\n\t\t}\n\t\t}\n\t\tbreak;\n\tcase ARC_FREQ_NUM:\n\t\t{\n\t\t// 0xa0-0xa8 low8 frequency\n\t\tBitu base = (idx-ARC_FREQ_NUM)&0xff;\n\t\tif (base<9)\n\t\t{\n\t\t\tBits opbase = second_set?(base+18):base;\n\t\t\tBits modbase;\n\t\t\tBitu chanbase;\n#if defined(OPLTYPE_IS_OPL3)\n\t\tif ((OPL->adlibreg[0x105]&1) && OPL->op[opbase].is_4op_attached) break;\n#endif\n\t\t\t// regbase of modulator:\n\t\t\tmodbase = modulatorbase[base]+second_set;\n\n\t\t\tchanbase = base+second_set;\n\n\t\t\tchange_frequency(chip, chanbase,modbase,&OPL->op[opbase]);\n\t\t\tchange_frequency(chip, chanbase,modbase+3,&OPL->op[opbase+9]);\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\t// for 4op channels all four operators are modified to the frequency of the channel\n\t\t\tif ((OPL->adlibreg[0x105]&1) && OPL->op[second_set?(base+18):base].is_4op)\n\t\t\t{\n\t\t\t\tchange_frequency(chip, chanbase,modbase+8,&OPL->op[opbase+3]);\n\t\t\t\tchange_frequency(chip, chanbase,modbase+3+8,&OPL->op[opbase+3+9]);\n\t\t\t}\n#endif\n\t\t}\n\t\t}\n\t\tbreak;\n\tcase ARC_KON_BNUM:\n\t\t{\n\t\tBitu base;\n\t\tif (OPL->UpdateHandler != NULL)\t// hack for DOSBox logs\n\t\t\tOPL->UpdateHandler(OPL->UpdateParam);\n\t\tif (idx == ARC_PERC_MODE)\n\t\t{\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\tif (second_set) return;\n#endif\n\n\t\t\tif ((val&0x30) == 0x30)\n\t\t\t{\t\t// BassDrum active\n\t\t\t\tenable_operator(chip, 16,&OPL->op[6],OP_ACT_PERC);\n\t\t\t\tchange_frequency(chip, 6,16,&OPL->op[6]);\n\t\t\t\tenable_operator(chip, 16+3,&OPL->op[6+9],OP_ACT_PERC);\n\t\t\t\tchange_frequency(chip, 6,16+3,&OPL->op[6+9]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdisable_operator(&OPL->op[6],OP_ACT_PERC);\n\t\t\t\tdisable_operator(&OPL->op[6+9],OP_ACT_PERC);\n\t\t\t}\n\t\t\tif ((val&0x28) == 0x28)\n\t\t\t{\t\t// Snare active\n\t\t\t\tenable_operator(chip, 17+3,&OPL->op[16],OP_ACT_PERC);\n\t\t\t\tchange_frequency(chip, 7,17+3,&OPL->op[16]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdisable_operator(&OPL->op[16],OP_ACT_PERC);\n\t\t\t}\n\t\t\tif ((val&0x24) == 0x24)\n\t\t\t{\t\t// TomTom active\n\t\t\t\tenable_operator(chip, 18,&OPL->op[8],OP_ACT_PERC);\n\t\t\t\tchange_frequency(chip, 8,18,&OPL->op[8]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdisable_operator(&OPL->op[8],OP_ACT_PERC);\n\t\t\t}\n\t\t\tif ((val&0x22) == 0x22)\n\t\t\t{\t\t// Cymbal active\n\t\t\t\tenable_operator(chip, 18+3,&OPL->op[8+9],OP_ACT_PERC);\n\t\t\t\tchange_frequency(chip, 8,18+3,&OPL->op[8+9]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdisable_operator(&OPL->op[8+9],OP_ACT_PERC);\n\t\t\t}\n\t\t\tif ((val&0x21) == 0x21)\n\t\t\t{\t\t// Hihat active\n\t\t\t\tenable_operator(chip, 17,&OPL->op[7],OP_ACT_PERC);\n\t\t\t\tchange_frequency(chip, 7,17,&OPL->op[7]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdisable_operator(&OPL->op[7],OP_ACT_PERC);\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\t\t// regular 0xb0-0xb8\n\t\tbase = (idx-ARC_KON_BNUM)&0xff;\n\t\tif (base<9)\n\t\t{\n\t\t\tBits opbase = second_set?(base+18):base;\n\t\t\t// regbase of modulator:\n\t\t\tBits modbase = modulatorbase[base]+second_set;\n\t\t\tBitu chanbase;\n\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\tif ((OPL->adlibreg[0x105]&1) && OPL->op[opbase].is_4op_attached) break;\n#endif\n\t\t\tif (val&32)\n\t\t\t{\n\t\t\t\t// operator switched on\n\t\t\t\tenable_operator(chip, modbase,&OPL->op[opbase],OP_ACT_NORMAL);\t\t// modulator (if 2op)\n\t\t\t\tenable_operator(chip, modbase+3,&OPL->op[opbase+9],OP_ACT_NORMAL);\t// carrier (if 2op)\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\t\t// for 4op channels all four operators are switched on\n\t\t\t\tif ((OPL->adlibreg[0x105]&1) && OPL->op[opbase].is_4op)\n\t\t\t\t{\n\t\t\t\t\t// turn on chan+3 operators as well\n\t\t\t\t\tenable_operator(chip, modbase+8,&OPL->op[opbase+3],OP_ACT_NORMAL);\n\t\t\t\t\tenable_operator(chip, modbase+3+8,&OPL->op[opbase+3+9],OP_ACT_NORMAL);\n\t\t\t\t}\n#endif\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// operator switched off\n\t\t\t\tdisable_operator(&OPL->op[opbase],OP_ACT_NORMAL);\n\t\t\t\tdisable_operator(&OPL->op[opbase+9],OP_ACT_NORMAL);\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\t\t// for 4op channels all four operators are switched off\n\t\t\t\tif ((OPL->adlibreg[0x105]&1) && OPL->op[opbase].is_4op)\n\t\t\t\t{\n\t\t\t\t\t// turn off chan+3 operators as well\n\t\t\t\t\tdisable_operator(&OPL->op[opbase+3],OP_ACT_NORMAL);\n\t\t\t\t\tdisable_operator(&OPL->op[opbase+3+9],OP_ACT_NORMAL);\n\t\t\t\t}\n#endif\n\t\t\t}\n\n\t\t\tchanbase = base+second_set;\n\n\t\t\t// change frequency calculations of modulator and carrier (2op) as\n\t\t\t// the frequency of the channel has changed\n\t\t\tchange_frequency(chip, chanbase,modbase,&OPL->op[opbase]);\n\t\t\tchange_frequency(chip, chanbase,modbase+3,&OPL->op[opbase+9]);\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\t// for 4op channels all four operators are modified to the frequency of the channel\n\t\t\tif ((OPL->adlibreg[0x105]&1) && OPL->op[second_set?(base+18):base].is_4op)\n\t\t\t{\n\t\t\t\t// change frequency calculations of chan+3 operators as well\n\t\t\t\tchange_frequency(chip, chanbase,modbase+8,&OPL->op[opbase+3]);\n\t\t\t\tchange_frequency(chip, chanbase,modbase+3+8,&OPL->op[opbase+3+9]);\n\t\t\t}\n#endif\n\t\t}\n\t\t}\n\t\tbreak;\n\tcase ARC_FEEDBACK:\n\t\t{\n\t\t// 0xc0-0xc8 feedback/modulation type (AM/FM)\n\t\tBitu base = (idx-ARC_FEEDBACK)&0xff;\n\t\tif (base<9)\n\t\t{\n\t\t\tBits opbase = second_set?(base+18):base;\n\t\t\tBitu chanbase = base+second_set;\n\t\t\tchange_feedback(chip, chanbase,&OPL->op[opbase]);\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\t// OPL3 panning\n\t\t\tOPL->op[opbase].left_pan = ((val&0x10)>>4);\n\t\t\tOPL->op[opbase].right_pan = ((val&0x20)>>5);\n\t\t\tOPL->op[opbase].left_pan += ((val&0x40)>>6);\n\t\t\tOPL->op[opbase].right_pan += ((val&0x80)>>7);\n#endif\n\t\t}\n\t\t}\n\t\tbreak;\n\tcase ARC_WAVE_SEL:\n\tcase ARC_WAVE_SEL+0x10:\n\t\t{\n\t\tint num = idx&7;\n\t\tBitu base = (idx-ARC_WAVE_SEL)&0xff;\n\t\tif ((num<6) && (base<22))\n\t\t{\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\tBits wselbase = second_set?(base+22):base;\t// for easier mapping onto wave_sel[]\n\t\t\top_type* op_ptr;\n\t\t\t// change waveform\n\t\t\tif (OPL->adlibreg[0x105]&1) OPL->wave_sel[wselbase] = val&7;\t// opl3 mode enabled, all waveforms accessible\n\t\t\telse OPL->wave_sel[wselbase] = val&3;\n\t\t\top_ptr = &OPL->op[regbase2modop[wselbase]+((num<3) ? 0 : 9)];\n\t\t\tchange_waveform(chip, wselbase,op_ptr);\n#else\n\t\t\tif (OPL->adlibreg[0x01]&0x20)\n\t\t\t{\n\t\t\t\top_type* op_ptr;\n\t\t\t\t\n\t\t\t\t// wave selection enabled, change waveform\n\t\t\t\tOPL->wave_sel[base] = val&3;\n\t\t\t\top_ptr = &OPL->op[regbase2modop[base]+((num<3) ? 0 : 9)];\n\t\t\t\tchange_waveform(chip, base,op_ptr);\n\t\t\t}\n#endif\n\t\t}\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n\nBitu ADLIBEMU(reg_read)(void *chip, UINT32 port)\n{\n\tOPL_DATA* OPL = (OPL_DATA*)chip;\n\t\n#if defined(OPLTYPE_IS_OPL3)\n\t// opl3-detection routines require ret&6 to be zero\n\tif ((port&1)==0)\n\t{\n\t\treturn OPL->status;\n\t}\n\treturn 0x00;\n#else\n\t// opl2-detection routines require ret&6 to be 6\n\tif ((port&1)==0)\n\t{\n\t\treturn OPL->status|6;\n\t}\n\treturn 0xff;\n#endif\n}\n\nvoid ADLIBEMU(write_index)(void *chip, UINT32 port, UINT8 val)\n{\n\tOPL_DATA* OPL = (OPL_DATA*)chip;\n\t\n\tOPL->opl_index = val;\n#if defined(OPLTYPE_IS_OPL3)\n\tif ((port&3)!=0)\n\t{\n\t\t// possibly second set\n\t\tif (((OPL->adlibreg[0x105]&1)!=0) || (OPL->opl_index==5)) OPL->opl_index |= ARC_SECONDSET;\n\t}\n#endif\n}\n\n/*static void OPL_INLINE clipit16(Bit32s ival, Bit16s* outval)\n{\n\tif (ival<32768)\n\t{\n\t\tif (ival>-32769)\n\t\t{\n\t\t\t*outval=(Bit16s)ival;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t*outval = -32768;\n\t\t}\n\t}\n\telse\n\t{\n\t\t*outval = 32767;\n\t}\n}*/\n\n\n\n// be careful with this\n// uses cptr and chanval, outputs into outbufl(/outbufr)\n// for opl3 check if opl3-mode is enabled (which uses stereo panning)\n// \n// Changes by Valley Bell:\n//\t- Changed to always output to both channels\n//\t- added parameter \"chn\" to fix panning for 4-op channels and the Rhythm Cymbal\n#undef CHANVAL_OUT\n#if defined(OPLTYPE_IS_OPL3)\n#define CHANVAL_OUT(chn)\t\t\t\t\t\t\t\t\\\n\tif (OPL->adlibreg[0x105]&1) {\t\t\t\t\t\t\\\n\t\toutbufl[i] += chanval*cptr[chn].left_pan;\t\t\\\n\t\toutbufr[i] += chanval*cptr[chn].right_pan;\t\\\n\t} else {\t\t\t\t\t\t\t\t\t\t\\\n\t\toutbufl[i] += chanval;\t\t\t\t\t\t\\\n\t\toutbufr[i] += chanval;\t\t\t\t\t\t\\\n\t}\n#else\n#define CHANVAL_OUT(chn)\t\t\t\t\t\t\t\t\\\n\toutbufl[i] += chanval;\t\t\t\t\t\t\t\\\n\toutbufr[i] += chanval;\n#endif\n\n//void adlib_getsample(Bit16s* sndptr, Bits numsamples)\nvoid ADLIBEMU(getsample)(void *chip, INT32** sndptr, INT32 numsamples)\n{\n\tOPL_DATA* OPL = (OPL_DATA*)chip;\n\t\n\tBits i, endsamples;\n\top_type* cptr;\n\n\t//Bit32s outbufl[BLOCKBUF_SIZE];\n#if defined(OPLTYPE_IS_OPL3)\n\t// second output buffer (right channel for opl3 stereo)\n\t//Bit32s outbufr[BLOCKBUF_SIZE];\n#endif\n\tBit32s* outbufl = sndptr[0];\n\tBit32s* outbufr = sndptr[1];\n\n\t// vibrato/tremolo lookup tables (global, to possibly be used by all operators)\n\tBit32s vib_lut[BLOCKBUF_SIZE];\n\tBit32s trem_lut[BLOCKBUF_SIZE];\n\n\tBits samples_to_process = numsamples;\n\n\tBits cursmp;\n\tBit32s vib_tshift;\n\tBitu max_channel = NUM_CHANNELS;\n\tBits cur_ch;\n\t\n\tBit32s *vibval1, *vibval2, *vibval3, *vibval4;\n\tBit32s *tremval1, *tremval2, *tremval3, *tremval4;\n\t\n#if defined(OPLTYPE_IS_OPL3)\n\tif ((OPL->adlibreg[0x105]&1)==0) max_channel = NUM_CHANNELS/2;\n#endif\n\t\n\tif (! samples_to_process)\n\t{\n\t\tfor (cur_ch = 0; cur_ch < max_channel; cur_ch ++)\n\t\t{\n\t\t\tif ((OPL->adlibreg[ARC_PERC_MODE] & 0x20) && (cur_ch >= 6 && cur_ch < 9))\n\t\t\t\tcontinue;\n\t\t\t\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\tif (cur_ch < 9)\n\t\t\t\tcptr = &OPL->op[cur_ch];\n\t\t\telse\n\t\t\t\tcptr = &OPL->op[cur_ch+9];\t// second set is operator18-operator35\n\t\t\tif (cptr->is_4op_attached)\n\t\t\t\tcontinue;\n#else\n\t\t\tcptr = &OPL->op[cur_ch];\n#endif\n\t\t\t\n\t\t\tif (cptr[0].op_state == OF_TYPE_ATT)\n\t\t\t\toperator_eg_attack_check(&cptr[0]);\n\t\t\tif (cptr[9].op_state == OF_TYPE_ATT)\n\t\t\t\toperator_eg_attack_check(&cptr[9]);\n\t\t}\n\t\t\n\t\treturn;\n\t}\n\t\n\tfor (cursmp=0; cursmp<samples_to_process; cursmp+=endsamples)\n\t{\n\t\tendsamples = samples_to_process-cursmp;\n\t\t//if (endsamples>BLOCKBUF_SIZE) endsamples = BLOCKBUF_SIZE;\n\n\t\tmemset(outbufl,0,endsamples*sizeof(Bit32s));\n//#if defined(OPLTYPE_IS_OPL3)\n//\t\t// clear second output buffer (opl3 stereo)\n//\t\t//if (adlibreg[0x105]&1)\n\t\t\tmemset(outbufr,0,endsamples*sizeof(Bit32s));\n//#endif\n\n\t\t// calculate vibrato/tremolo lookup tables\n\t\tvib_tshift = ((OPL->adlibreg[ARC_PERC_MODE]&0x40)==0) ? 1 : 0;\t// 14cents/7cents switching\n\t\tfor (i=0;i<endsamples;i++)\n\t\t{\n\t\t\t// cycle through vibrato table\n\t\t\tOPL->vibtab_pos += OPL->vibtab_add;\n\t\t\tif (OPL->vibtab_pos/FIXEDPT_LFO>=VIBTAB_SIZE)\n\t\t\t\tOPL->vibtab_pos-=VIBTAB_SIZE*FIXEDPT_LFO;\n\t\t\tvib_lut[i] = vib_table[OPL->vibtab_pos/FIXEDPT_LFO]>>vib_tshift;\t\t// 14cents (14/100 of a semitone) or 7cents\n\n\t\t\t// cycle through tremolo table\n\t\t\tOPL->tremtab_pos += OPL->tremtab_add;\n\t\t\tif (OPL->tremtab_pos/FIXEDPT_LFO>=TREMTAB_SIZE)\n\t\t\t\tOPL->tremtab_pos-=TREMTAB_SIZE*FIXEDPT_LFO;\n\t\t\tif (OPL->adlibreg[ARC_PERC_MODE]&0x80)\n\t\t\t\ttrem_lut[i] = trem_table[OPL->tremtab_pos/FIXEDPT_LFO];\n\t\t\telse\n\t\t\t\ttrem_lut[i] = trem_table[TREMTAB_SIZE+OPL->tremtab_pos/FIXEDPT_LFO];\n\t\t}\n\n\t\tif (OPL->adlibreg[ARC_PERC_MODE]&0x20)\n\t\t{\n\t\t\tif (! (OPL->MuteChn[NUM_CHANNELS + 0]))\n\t\t\t{\n\t\t\t//BassDrum\n\t\t\tcptr = &OPL->op[6];\n\t\t\tif (OPL->adlibreg[ARC_FEEDBACK+6]&1)\n\t\t\t{\n\t\t\t\t// additive synthesis\n\t\t\t\tif (cptr[9].op_state != OF_TYPE_OFF)\n\t\t\t\t{\n\t\t\t\t\tif (cptr[9].vibrato)\n\t\t\t\t\t{\n\t\t\t\t\t\tvibval1 = vibval_var1;\n\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\tvibval1[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tvibval1 = vibval_const;\n\t\t\t\t\tif (cptr[9].tremolo)\n\t\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\telse\n\t\t\t\t\t\ttremval1 = tremval_const;\n\n\t\t\t\t\t// calculate channel output\n\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\t\n\t\t\t\t\t\toperator_advance(OPL, &cptr[9],vibval1[i]);\n\t\t\t\t\t\topfuncs[cptr[9].op_state](&cptr[9]);\n\t\t\t\t\t\toperator_output(&cptr[9],0,tremval1[i]);\n\t\t\t\t\t\t\n\t\t\t\t\t\tchanval = cptr[9].cval*2;\n\t\t\t\t\t\tCHANVAL_OUT(0)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// frequency modulation\n\t\t\t\tif ((cptr[9].op_state != OF_TYPE_OFF) || (cptr[0].op_state != OF_TYPE_OFF))\n\t\t\t\t{\n\t\t\t\t\tif ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF))\n\t\t\t\t\t{\n\t\t\t\t\t\tvibval1 = vibval_var1;\n\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\tvibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tvibval1 = vibval_const;\n\t\t\t\t\tif ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF))\n\t\t\t\t\t{\n\t\t\t\t\t\tvibval2 = vibval_var2;\n\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\tvibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tvibval2 = vibval_const;\n\t\t\t\t\tif (cptr[0].tremolo)\n\t\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\telse\n\t\t\t\t\t\ttremval1 = tremval_const;\n\t\t\t\t\tif (cptr[9].tremolo)\n\t\t\t\t\t\ttremval2 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\telse\n\t\t\t\t\t\ttremval2 = tremval_const;\n\n\t\t\t\t\t// calculate channel output\n\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\t\n\t\t\t\t\t\toperator_advance(OPL, &cptr[0],vibval1[i]);\n\t\t\t\t\t\topfuncs[cptr[0].op_state](&cptr[0]);\n\t\t\t\t\t\toperator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);\n\n\t\t\t\t\t\toperator_advance(OPL, &cptr[9],vibval2[i]);\n\t\t\t\t\t\topfuncs[cptr[9].op_state](&cptr[9]);\n\t\t\t\t\t\toperator_output(&cptr[9],cptr[0].cval*FIXEDPT,tremval2[i]);\n\t\t\t\t\t\t\n\t\t\t\t\t\tchanval = cptr[9].cval*2;\n\t\t\t\t\t\tCHANVAL_OUT(0)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t}\t// end if (! Muted)\n\n\t\t\t//TomTom (j=8)\n\t\t\tif (! (OPL->MuteChn[NUM_CHANNELS + 2]) && OPL->op[8].op_state != OF_TYPE_OFF)\n\t\t\t{\n\t\t\t\tcptr = &OPL->op[8];\n\t\t\t\tif (cptr[0].vibrato)\n\t\t\t\t{\n\t\t\t\t\tvibval3 = vibval_var1;\n\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\tvibval3[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tvibval3 = vibval_const;\n\n\t\t\t\tif (cptr[0].tremolo)\n\t\t\t\t\ttremval3 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\telse\n\t\t\t\t\ttremval3 = tremval_const;\n\n\t\t\t\t// calculate channel output\n\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t{\n\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\n\t\t\t\t\toperator_advance(OPL, &cptr[0],vibval3[i]);\n\t\t\t\t\topfuncs[cptr[0].op_state](&cptr[0]);\t\t//TomTom\n\t\t\t\t\toperator_output(&cptr[0],0,tremval3[i]);\n\t\t\t\t\tchanval = cptr[0].cval*2;\n\t\t\t\t\tCHANVAL_OUT(0)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Snare/Hihat (j=7), Cymbal (j=8)\n\t\t\tif ((OPL->op[7].op_state != OF_TYPE_OFF) || (OPL->op[16].op_state != OF_TYPE_OFF) ||\n\t\t\t\t(OPL->op[17].op_state != OF_TYPE_OFF))\n\t\t\t{\n\t\t\t\tcptr = &OPL->op[7];\n\t\t\t\tif ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF))\n\t\t\t\t{\n\t\t\t\t\tvibval1 = vibval_var1;\n\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\tvibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tvibval1 = vibval_const;\n\t\t\t\tif ((cptr[9].vibrato) && (cptr[9].op_state == OF_TYPE_OFF))\n\t\t\t\t{\n\t\t\t\t\tvibval2 = vibval_var2;\n\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\tvibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tvibval2 = vibval_const;\n\n\t\t\t\tif (cptr[0].tremolo)\n\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\telse\n\t\t\t\t\ttremval1 = tremval_const;\n\t\t\t\tif (cptr[9].tremolo)\n\t\t\t\t\ttremval2 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\telse\n\t\t\t\t\ttremval2 = tremval_const;\n\n\t\t\t\tcptr = &OPL->op[8];\n\t\t\t\tif ((cptr[9].vibrato) && (cptr[9].op_state == OF_TYPE_OFF))\n\t\t\t\t{\n\t\t\t\t\tvibval4 = vibval_var2;\n\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\tvibval4[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tvibval4 = vibval_const;\n\n\t\t\t\tif (cptr[9].tremolo) tremval4 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\telse tremval4 = tremval_const;\n\n\t\t\t\t// calculate channel output\n\t\t\t\tcptr = &OPL->op[0];\t// set cptr to something useful (else it stays at op[8])\n\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t{\n\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\n\t\t\t\t\toperator_advance_drums(OPL, &OPL->op[7],vibval1[i],&OPL->op[7+9],vibval2[i],&OPL->op[8+9],vibval4[i]);\n\n\t\t\t\t\tif (! (OPL->MuteChn[NUM_CHANNELS + 4]))\n\t\t\t\t\t{\n\t\t\t\t\t\topfuncs[OPL->op[7].op_state](&OPL->op[7]);\t\t\t//Hihat\n\t\t\t\t\t\toperator_output(&OPL->op[7],0,tremval1[i]);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tOPL->op[7].cval = 0;\n\n\t\t\t\t\tif (! (OPL->MuteChn[NUM_CHANNELS + 1]))\n\t\t\t\t\t{\n\t\t\t\t\t\topfuncs[OPL->op[7+9].op_state](&OPL->op[7+9]);\t\t//Snare\n\t\t\t\t\t\toperator_output(&OPL->op[7+9],0,tremval2[i]);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tOPL->op[7+9].cval = 0;\n\n\t\t\t\t\tif (! (OPL->MuteChn[NUM_CHANNELS + 3]))\n\t\t\t\t\t{\n\t\t\t\t\t\topfuncs[OPL->op[8+9].op_state](&OPL->op[8+9]);\t\t//Cymbal\n\t\t\t\t\t\toperator_output(&OPL->op[8+9],0,tremval4[i]);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tOPL->op[8+9].cval = 0;\n\n\t\t\t\t\t//chanval = (OPL->op[7].cval + OPL->op[7+9].cval + OPL->op[8+9].cval)*2;\n\t\t\t\t\t//CHANVAL_OUT(0)\n\t\t\t\t\t// fix panning of the snare -Valley Bell\n\t\t\t\t\tchanval = (OPL->op[7].cval + OPL->op[7+9].cval)*2;\n\t\t\t\t\tCHANVAL_OUT(7)\n\t\t\t\t\tchanval = OPL->op[8+9].cval*2;\n\t\t\t\t\tCHANVAL_OUT(8)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (cur_ch=max_channel-1; cur_ch>=0; cur_ch--)\n\t\t{\n\t\t\tBitu k;\n\n\t\t\tif (OPL->MuteChn[cur_ch])\n\t\t\t\tcontinue;\n\n\t\t\t// skip drum/percussion operators\n\t\t\tif ((OPL->adlibreg[ARC_PERC_MODE]&0x20) && (cur_ch >= 6) && (cur_ch < 9)) continue;\n\n\t\t\tk = cur_ch;\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\tif (cur_ch < 9)\n\t\t\t{\n\t\t\t\tcptr = &OPL->op[cur_ch];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcptr = &OPL->op[cur_ch+9];\t// second set is operator18-operator35\n\t\t\t\tk += (-9+256);\t\t// second set uses registers 0x100 onwards\n\t\t\t}\n\t\t\t// check if this operator is part of a 4-op\n\t\t\t//if ((OPL->adlibreg[0x105]&1) && cptr->is_4op_attached) continue;\n\t\t\tif (cptr->is_4op_attached) continue;\t// this is more correct\n#else\n\t\t\tcptr = &OPL->op[cur_ch];\n#endif\n\n\t\t\t// check for FM/AM\n\t\t\tif (OPL->adlibreg[ARC_FEEDBACK+k]&1)\n\t\t\t{\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\t\t//if ((OPL->adlibreg[0x105]&1) && cptr->is_4op)\n\t\t\t\tif (cptr->is_4op)\t// this is more correct\n\t\t\t\t{\n\t\t\t\t\tif (OPL->adlibreg[ARC_FEEDBACK+k+3]&1)\n\t\t\t\t\t{\n\t\t\t\t\t\t// AM-AM-style synthesis (op1[fb] + (op2 * op3) + op4)\n\t\t\t\t\t\tif (cptr[0].op_state != OF_TYPE_OFF)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (cptr[0].vibrato)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvibval1 = vibval_var1;\n\t\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t\t\tvibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tvibval1 = vibval_const;\n\t\t\t\t\t\t\tif (cptr[0].tremolo)\n\t\t\t\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval1 = tremval_const;\n\n\t\t\t\t\t\t\t// calculate channel output\n\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[0],vibval1[i]);\n\t\t\t\t\t\t\t\topfuncs[cptr[0].op_state](&cptr[0]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);\n\n\t\t\t\t\t\t\t\tchanval = cptr[0].cval;\n\t\t\t\t\t\t\t\tCHANVAL_OUT(3)\t// Note: Op 1 of 4, so it needs to use the panning bits of Op 4 (Ch+3)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ((cptr[3].op_state != OF_TYPE_OFF) || (cptr[9].op_state != OF_TYPE_OFF))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvibval1 = vibval_var1;\n\t\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t\t\tvibval1[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tvibval1 = vibval_const;\n\t\t\t\t\t\t\tif (cptr[9].tremolo)\n\t\t\t\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval1 = tremval_const;\n\t\t\t\t\t\t\tif (cptr[3].tremolo)\n\t\t\t\t\t\t\t\ttremval2 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval2 = tremval_const;\n\n\t\t\t\t\t\t\t// calculate channel output\n\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[9],vibval1[i]);\n\t\t\t\t\t\t\t\topfuncs[cptr[9].op_state](&cptr[9]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[9],0,tremval1[i]);\n\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[3],0);\n\t\t\t\t\t\t\t\topfuncs[cptr[3].op_state](&cptr[3]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[3],cptr[9].cval*FIXEDPT,tremval2[i]);\n\n\t\t\t\t\t\t\t\tchanval = cptr[3].cval;\n\t\t\t\t\t\t\t\tCHANVAL_OUT(3)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (cptr[3+9].op_state != OF_TYPE_OFF)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (cptr[3+9].tremolo)\n\t\t\t\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval1 = tremval_const;\n\n\t\t\t\t\t\t\t// calculate channel output\n\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[3+9],0);\n\t\t\t\t\t\t\t\topfuncs[cptr[3+9].op_state](&cptr[3+9]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[3+9],0,tremval1[i]);\n\n\t\t\t\t\t\t\t\tchanval = cptr[3+9].cval;\n\t\t\t\t\t\t\t\tCHANVAL_OUT(3)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// AM-FM-style synthesis (op1[fb] + (op2 * op3 * op4))\n\t\t\t\t\t\tif (cptr[0].op_state != OF_TYPE_OFF)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (cptr[0].vibrato)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvibval1 = vibval_var1;\n\t\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t\t\tvibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tvibval1 = vibval_const;\n\t\t\t\t\t\t\tif (cptr[0].tremolo)\n\t\t\t\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval1 = tremval_const;\n\n\t\t\t\t\t\t\t// calculate channel output\n\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[0],vibval1[i]);\n\t\t\t\t\t\t\t\topfuncs[cptr[0].op_state](&cptr[0]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);\n\n\t\t\t\t\t\t\t\tchanval = cptr[0].cval;\n\t\t\t\t\t\t\t\tCHANVAL_OUT(3)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ((cptr[9].op_state != OF_TYPE_OFF) || (cptr[3].op_state != OF_TYPE_OFF) || (cptr[3+9].op_state != OF_TYPE_OFF))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) {\n\t\t\t\t\t\t\t\tvibval1 = vibval_var1;\n\t\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t\t\tvibval1[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tvibval1 = vibval_const;\n\t\t\t\t\t\t\tif (cptr[9].tremolo)\n\t\t\t\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval1 = tremval_const;\n\t\t\t\t\t\t\tif (cptr[3].tremolo)\n\t\t\t\t\t\t\t\ttremval2 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval2 = tremval_const;\n\t\t\t\t\t\t\tif (cptr[3+9].tremolo)\n\t\t\t\t\t\t\t\ttremval3 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval3 = tremval_const;\n\n\t\t\t\t\t\t\t// calculate channel output\n\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[9],vibval1[i]);\n\t\t\t\t\t\t\t\topfuncs[cptr[9].op_state](&cptr[9]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[9],0,tremval1[i]);\n\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[3],0);\n\t\t\t\t\t\t\t\topfuncs[cptr[3].op_state](&cptr[3]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[3],cptr[9].cval*FIXEDPT,tremval2[i]);\n\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[3+9],0);\n\t\t\t\t\t\t\t\topfuncs[cptr[3+9].op_state](&cptr[3+9]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[3+9],cptr[3].cval*FIXEDPT,tremval3[i]);\n\n\t\t\t\t\t\t\t\tchanval = cptr[3+9].cval;\n\t\t\t\t\t\t\t\tCHANVAL_OUT(3)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n#endif\n\t\t\t\t// 2op additive synthesis\n\t\t\t\tif ((cptr[9].op_state == OF_TYPE_OFF) && (cptr[0].op_state == OF_TYPE_OFF)) continue;\n\t\t\t\tif ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF))\n\t\t\t\t{\n\t\t\t\t\tvibval1 = vibval_var1;\n\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\tvibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tvibval1 = vibval_const;\n\t\t\t\tif ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF))\n\t\t\t\t{\n\t\t\t\t\tvibval2 = vibval_var2;\n\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\tvibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tvibval2 = vibval_const;\n\t\t\t\tif (cptr[0].tremolo)\n\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\telse\n\t\t\t\t\ttremval1 = tremval_const;\n\t\t\t\tif (cptr[9].tremolo)\n\t\t\t\t\ttremval2 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\telse\n\t\t\t\t\ttremval2 = tremval_const;\n\n\t\t\t\t// calculate channel output\n\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t{\n\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\n\t\t\t\t\t// carrier1\n\t\t\t\t\toperator_advance(OPL, &cptr[0],vibval1[i]);\n\t\t\t\t\topfuncs[cptr[0].op_state](&cptr[0]);\n\t\t\t\t\toperator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);\n\n\t\t\t\t\t// carrier2\n\t\t\t\t\toperator_advance(OPL, &cptr[9],vibval2[i]);\n\t\t\t\t\topfuncs[cptr[9].op_state](&cptr[9]);\n\t\t\t\t\toperator_output(&cptr[9],0,tremval2[i]);\n\n\t\t\t\t\tchanval = cptr[9].cval + cptr[0].cval;\n\t\t\t\t\tCHANVAL_OUT(0)\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n#if defined(OPLTYPE_IS_OPL3)\n\t\t\t\t//if ((OPL->adlibreg[0x105]&1) && cptr->is_4op)\n\t\t\t\tif (cptr->is_4op)\t// this is more correct\n\t\t\t\t{\n\t\t\t\t\tif (OPL->adlibreg[ARC_FEEDBACK+k+3]&1)\n\t\t\t\t\t{\n\t\t\t\t\t\t// FM-AM-style synthesis ((op1[fb] * op2) + (op3 * op4))\n\t\t\t\t\t\tif ((cptr[0].op_state != OF_TYPE_OFF) || (cptr[9].op_state != OF_TYPE_OFF))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvibval1 = vibval_var1;\n\t\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t\t\tvibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tvibval1 = vibval_const;\n\t\t\t\t\t\t\tif ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvibval2 = vibval_var2;\n\t\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t\t\tvibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tvibval2 = vibval_const;\n\t\t\t\t\t\t\tif (cptr[0].tremolo)\n\t\t\t\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval1 = tremval_const;\n\t\t\t\t\t\t\tif (cptr[9].tremolo)\n\t\t\t\t\t\t\t\ttremval2 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval2 = tremval_const;\n\n\t\t\t\t\t\t\t// calculate channel output\n\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[0],vibval1[i]);\n\t\t\t\t\t\t\t\topfuncs[cptr[0].op_state](&cptr[0]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);\n\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[9],vibval2[i]);\n\t\t\t\t\t\t\t\topfuncs[cptr[9].op_state](&cptr[9]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[9],cptr[0].cval*FIXEDPT,tremval2[i]);\n\n\t\t\t\t\t\t\t\tchanval = cptr[9].cval;\n\t\t\t\t\t\t\t\tCHANVAL_OUT(3)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ((cptr[3].op_state != OF_TYPE_OFF) || (cptr[3+9].op_state != OF_TYPE_OFF))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (cptr[3].tremolo)\n\t\t\t\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval1 = tremval_const;\n\t\t\t\t\t\t\tif (cptr[3+9].tremolo)\n\t\t\t\t\t\t\t\ttremval2 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval2 = tremval_const;\n\n\t\t\t\t\t\t\t// calculate channel output\n\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[3],0);\n\t\t\t\t\t\t\t\topfuncs[cptr[3].op_state](&cptr[3]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[3],0,tremval1[i]);\n\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[3+9],0);\n\t\t\t\t\t\t\t\topfuncs[cptr[3+9].op_state](&cptr[3+9]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[3+9],cptr[3].cval*FIXEDPT,tremval2[i]);\n\n\t\t\t\t\t\t\t\tchanval = cptr[3+9].cval;\n\t\t\t\t\t\t\t\tCHANVAL_OUT(3)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// FM-FM-style synthesis (op1[fb] * op2 * op3 * op4)\n\t\t\t\t\t\tif ((cptr[0].op_state != OF_TYPE_OFF) || (cptr[9].op_state != OF_TYPE_OFF) || \n\t\t\t\t\t\t\t(cptr[3].op_state != OF_TYPE_OFF) || (cptr[3+9].op_state != OF_TYPE_OFF))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvibval1 = vibval_var1;\n\t\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t\t\tvibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tvibval1 = vibval_const;\n\t\t\t\t\t\t\tif ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvibval2 = vibval_var2;\n\t\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t\t\tvibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tvibval2 = vibval_const;\n\t\t\t\t\t\t\tif (cptr[0].tremolo)\n\t\t\t\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval1 = tremval_const;\n\t\t\t\t\t\t\tif (cptr[9].tremolo)\n\t\t\t\t\t\t\t\ttremval2 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval2 = tremval_const;\n\t\t\t\t\t\t\tif (cptr[3].tremolo)\n\t\t\t\t\t\t\t\ttremval3 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval3 = tremval_const;\n\t\t\t\t\t\t\tif (cptr[3+9].tremolo)\n\t\t\t\t\t\t\t\ttremval4 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttremval4 = tremval_const;\n\n\t\t\t\t\t\t\t// calculate channel output\n\t\t\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[0],vibval1[i]);\n\t\t\t\t\t\t\t\topfuncs[cptr[0].op_state](&cptr[0]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);\n\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[9],vibval2[i]);\n\t\t\t\t\t\t\t\topfuncs[cptr[9].op_state](&cptr[9]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[9],cptr[0].cval*FIXEDPT,tremval2[i]);\n\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[3],0);\n\t\t\t\t\t\t\t\topfuncs[cptr[3].op_state](&cptr[3]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[3],cptr[9].cval*FIXEDPT,tremval3[i]);\n\n\t\t\t\t\t\t\t\toperator_advance(OPL, &cptr[3+9],0);\n\t\t\t\t\t\t\t\topfuncs[cptr[3+9].op_state](&cptr[3+9]);\n\t\t\t\t\t\t\t\toperator_output(&cptr[3+9],cptr[3].cval*FIXEDPT,tremval4[i]);\n\n\t\t\t\t\t\t\t\tchanval = cptr[3+9].cval;\n\t\t\t\t\t\t\t\tCHANVAL_OUT(3)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n#endif\n\t\t\t\t// 2op frequency modulation\n\t\t\t\tif ((cptr[9].op_state == OF_TYPE_OFF) && (cptr[0].op_state == OF_TYPE_OFF)) continue;\n\t\t\t\tif ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF))\n\t\t\t\t{\n\t\t\t\t\tvibval1 = vibval_var1;\n\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\tvibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tvibval1 = vibval_const;\n\t\t\t\tif ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF))\n\t\t\t\t{\n\t\t\t\t\tvibval2 = vibval_var2;\n\t\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t\t\tvibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tvibval2 = vibval_const;\n\t\t\t\tif (cptr[0].tremolo)\n\t\t\t\t\ttremval1 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\telse\n\t\t\t\t\ttremval1 = tremval_const;\n\t\t\t\tif (cptr[9].tremolo)\n\t\t\t\t\ttremval2 = trem_lut;\t// tremolo enabled, use table\n\t\t\t\telse\n\t\t\t\t\ttremval2 = tremval_const;\n\n\t\t\t\t// calculate channel output\n\t\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t\t{\n\t\t\t\t\tBit32s chanval;\n\t\t\t\t\t\n\t\t\t\t\t// modulator\n\t\t\t\t\toperator_advance(OPL, &cptr[0],vibval1[i]);\n\t\t\t\t\topfuncs[cptr[0].op_state](&cptr[0]);\n\t\t\t\t\toperator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);\n\n\t\t\t\t\t// carrier\n\t\t\t\t\toperator_advance(OPL, &cptr[9],vibval2[i]);\n\t\t\t\t\topfuncs[cptr[9].op_state](&cptr[9]);\n\t\t\t\t\toperator_output(&cptr[9],cptr[0].cval*FIXEDPT,tremval2[i]);\n\n\t\t\t\t\tchanval = cptr[9].cval;\n\t\t\t\t\tCHANVAL_OUT(0)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n/*#if defined(OPLTYPE_IS_OPL3)\n\t\tif (adlibreg[0x105]&1)\n\t\t{\n\t\t\t// convert to 16bit samples (stereo)\n\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t{\n\t\t\t\tclipit16(outbufl[i],sndptr++);\n\t\t\t\tclipit16(outbufr[i],sndptr++);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// convert to 16bit samples (mono)\n\t\t\tfor (i=0;i<endsamples;i++)\n\t\t\t{\n\t\t\t\tclipit16(outbufl[i],sndptr++);\n\t\t\t\tclipit16(outbufl[i],sndptr++);\n\t\t\t}\n\t\t}\n#else\n\t\t// convert to 16bit samples\n\t\tfor (i=0;i<endsamples;i++)\n\t\t\tclipit16(outbufl[i],sndptr++);\n#endif*/\n\n\t}\n}\n\nvoid ADLIBEMU(set_mute_mask)(void *chip, UINT32 MuteMask)\n{\n\tOPL_DATA* OPL = (OPL_DATA*)chip;\n\t\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < NUM_CHANNELS + 5; CurChn ++)\n\t\tOPL->MuteChn[CurChn] = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/opl.h",
    "content": "/*\n *  Copyright (C) 2002-2010  The DOSBox Team\n *  OPL2/OPL3 emulation library\n *\n *  This library is free software; you can redistribute it and/or\n *  modify it under the terms of the GNU Lesser General Public\n *  License as published by the Free Software Foundation; either\n *  version 2.1 of the License, or (at your option) any later version.\n * \n *  This library is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n *  Lesser General Public License for more details.\n * \n *  You should have received a copy of the GNU Lesser General Public\n *  License along with this library; if not, write to the Free Software\n *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n\n/*\n * Originally based on ADLIBEMU.C, an AdLib/OPL2 emulation library by Ken Silverman\n * Copyright (C) 1998-2001 Ken Silverman\n * Ken Silverman's official web site: \"http://www.advsys.net/ken\"\n */\n\n\n#define fltype double\n\n/*\n\tdefine Bits, Bitu, Bit32s, Bit32u, Bit16s, Bit16u, Bit8s, Bit8u here\n*/\n/*\n#include <stdint.h>\ntypedef uintptr_t\tBitu;\ntypedef intptr_t\tBits;\ntypedef uint32_t\tBit32u;\ntypedef int32_t\t\tBit32s;\ntypedef uint16_t\tBit16u;\ntypedef int16_t\t\tBit16s;\ntypedef uint8_t\t\tBit8u;\ntypedef int8_t\t\tBit8s;\n*/\n\ntypedef UINT32\t\tBitu;\ntypedef INT32\t\tBits;\ntypedef UINT32\t\tBit32u;\ntypedef INT32\t\tBit32s;\ntypedef UINT16\t\tBit16u;\ntypedef INT16\t\tBit16s;\ntypedef UINT8\t\tBit8u;\ntypedef INT8\t\tBit8s;\n\n/*\n\tdefine attribution that inlines/forces inlining of a function (optional)\n*/\n#define OPL_INLINE INLINE\n\n\n#undef NUM_CHANNELS\n#if defined(OPLTYPE_IS_OPL3)\n#define NUM_CHANNELS\t18\n#else\n#define NUM_CHANNELS\t9\n#endif\n\n#define MAXOPERATORS\t(NUM_CHANNELS*2)\n\n\n#define FL05\t((fltype)0.5)\n#define FL2\t\t((fltype)2.0)\n#define PI\t\t((fltype)3.1415926535897932384626433832795)\n\n\n#define FIXEDPT\t\t\t0x10000\t\t// fixed-point calculations using 16+16\n#define FIXEDPT_LFO\t\t0x1000000\t// fixed-point calculations using 8+24\n\n#define WAVEPREC\t\t1024\t\t// waveform precision (10 bits)\n\n//#define INTFREQU\t\t((fltype)(14318180.0 / 288.0))\t\t// clocking of the chip\n#if defined(OPLTYPE_IS_OPL3)\n#define INTFREQU\t\t((fltype)(OPL->chip_clock / 288.0))\t\t// clocking of the chip\n#else\n#define INTFREQU\t\t((fltype)(OPL->chip_clock / 72.0))\t\t// clocking of the chip\n#endif\n\n\n#define OF_TYPE_ATT\t\t\t0\n#define OF_TYPE_DEC\t\t\t1\n#define OF_TYPE_REL\t\t\t2\n#define OF_TYPE_SUS\t\t\t3\n#define OF_TYPE_SUS_NOKEEP\t4\n#define OF_TYPE_OFF\t\t\t5\n\n#define ARC_CONTROL\t\t\t0x00\n#define ARC_TVS_KSR_MUL\t\t0x20\n#define ARC_KSL_OUTLEV\t\t0x40\n#define ARC_ATTR_DECR\t\t0x60\n#define ARC_SUSL_RELR\t\t0x80\n#define ARC_FREQ_NUM\t\t0xa0\n#define ARC_KON_BNUM\t\t0xb0\n#define ARC_PERC_MODE\t\t0xbd\n#define ARC_FEEDBACK\t\t0xc0\n#define ARC_WAVE_SEL\t\t0xe0\n\n#define ARC_SECONDSET\t\t0x100\t// second operator set for OPL3\n\n\n#define OP_ACT_OFF\t\t\t0x00\n#define OP_ACT_NORMAL\t\t0x01\t// regular channel activated (bitmasked)\n#define OP_ACT_PERC\t\t\t0x02\t// percussion channel activated (bitmasked)\n\n#define BLOCKBUF_SIZE\t\t512\n\n\n// vibrato constants\n#define VIBTAB_SIZE\t\t\t8\n#define VIBFAC\t\t\t\t70/50000\t\t// no braces, integer mul/div\n\n// tremolo constants and table\n#define TREMTAB_SIZE\t\t53\n#define TREM_FREQ\t\t\t((fltype)(3.7))\t\t\t// tremolo at 3.7hz\n\n\n/* operator struct definition\n     For OPL2 all 9 channels consist of two operators each, carrier and modulator.\n     Channel x has operators x as modulator and operators (9+x) as carrier.\n     For OPL3 all 18 channels consist either of two operators (2op mode) or four\n     operators (4op mode) which is determined through register4 of the second\n     adlib register set.\n     Only the channels 0,1,2 (first set) and 9,10,11 (second set) can act as\n     4op channels. The two additional operators for a channel y come from the\n     2op channel y+3 so the operatorss y, (9+y), y+3, (9+y)+3 make up a 4op\n     channel.\n*/\ntypedef struct operator_struct {\n\tBit32s cval, lastcval;\t\t\t// current output/last output (used for feedback)\n\tBit32u tcount, wfpos, tinc;\t\t// time (position in waveform) and time increment\n\tfltype amp, step_amp;\t\t\t// and amplification (envelope)\n\tfltype vol;\t\t\t\t\t\t// volume\n\tfltype sustain_level;\t\t\t// sustain level\n\tBit32s mfbi;\t\t\t\t\t// feedback amount\n\tfltype a0, a1, a2, a3;\t\t\t// attack rate function coefficients\n\tfltype decaymul, releasemul;\t// decay/release rate functions\n\tBit32u op_state;\t\t\t\t// current state of operator (attack/decay/sustain/release/off)\n\tBit32u toff;\n\tBit32s freq_high;\t\t\t\t// highest three bits of the frequency, used for vibrato calculations\n\tBit16s* cur_wform;\t\t\t\t// start of selected waveform\n\tBit32u cur_wmask;\t\t\t\t// mask for selected waveform\n\tBit32u act_state;\t\t\t\t// activity state (regular, percussion)\n\tbool sus_keep;\t\t\t\t\t// keep sustain level when decay finished\n\tbool vibrato,tremolo;\t\t\t// vibrato/tremolo enable bits\n\t\n\t// variables used to provide non-continuous envelopes\n\tBit32u generator_pos;\t\t\t// for non-standard sample rates we need to determine how many samples have passed\n\tBits cur_env_step;\t\t\t\t// current (standardized) sample position\n\tBits env_step_a,env_step_d,env_step_r;\t// number of std samples of one step (for attack/decay/release mode)\n\tBit8u step_skip_pos_a;\t\t\t// position of 8-cyclic step skipping (always 2^x to check against mask)\n\tBits env_step_skip_a;\t\t\t// bitmask that determines if a step is skipped (respective bit is zero then)\n\n#if defined(OPLTYPE_IS_OPL3)\n\tbool is_4op,is_4op_attached;\t// base of a 4op channel/part of a 4op channel\n\tBit32s left_pan,right_pan;\t\t// opl3 stereo panning amount\n#endif\n} op_type;\n\ntypedef struct opl_chip\n{\n\t// per-chip variables\n\t//Bitu chip_num;\n\top_type op[MAXOPERATORS];\n\tBit8u MuteChn[NUM_CHANNELS + 5];\n\tBitu chip_clock;\n\t\n\tBits int_samplerate;\n\t\n\tBit8u status;\n\tBit32u opl_index;\n\tBits opl_addr;\n#if defined(OPLTYPE_IS_OPL3)\n\tBit8u adlibreg[512];\t// adlib register set (including second set)\n\tBit8u wave_sel[44];\t\t// waveform selection\n#else\n\tBit8u adlibreg[256];\t// adlib register set\n\tBit8u wave_sel[22];\t\t// waveform selection\n#endif\n\t\n\t\n\t// vibrato/tremolo increment/counter\n\tBit32u vibtab_pos;\n\tBit32u vibtab_add;\n\tBit32u tremtab_pos;\n\tBit32u tremtab_add;\n\t\n\tBit32u generator_add;\t// should be a chip parameter\n\t\n\tfltype recipsamp;\t// inverse of sampling rate\n\tfltype frqmul[16];\n\t\n\tADL_UPDATEHANDLER UpdateHandler;\t// stream update handler\n\tvoid* UpdateParam;\t\t\t\t\t// stream update parameter\n} OPL_DATA;\n\n\n// enable an operator\nstatic void enable_operator(OPL_DATA* chip, Bitu regbase, op_type* op_pt, Bit32u act_type);\n\n// functions to change parameters of an operator\nstatic void change_frequency(OPL_DATA* chip, Bitu chanbase, Bitu regbase, op_type* op_pt);\n\nstatic void change_attackrate(OPL_DATA* chip, Bitu regbase, op_type* op_pt);\nstatic void change_decayrate(OPL_DATA* chip, Bitu regbase, op_type* op_pt);\nstatic void change_releaserate(OPL_DATA* chip, Bitu regbase, op_type* op_pt);\nstatic void change_sustainlevel(OPL_DATA* chip, Bitu regbase, op_type* op_pt);\nstatic void change_waveform(OPL_DATA* chip, Bitu regbase, op_type* op_pt);\nstatic void change_keepsustain(OPL_DATA* chip, Bitu regbase, op_type* op_pt);\nstatic void change_vibrato(OPL_DATA* chip, Bitu regbase, op_type* op_pt);\nstatic void change_feedback(OPL_DATA* chip, Bitu chanbase, op_type* op_pt);\n\n// general functions\n/*void* adlib_init(Bitu clock, Bit32u samplerate);\nvoid adlib_writeIO(void *chip, Bitu addr, Bit8u val);\nvoid adlib_write(void *chip, Bitu idx, Bit8u val);\n//void adlib_getsample(Bit16s* sndptr, Bits numsamples);\nvoid adlib_getsample(void *chip, Bit32s** sndptr, Bits numsamples);\n\nBitu adlib_reg_read(void *chip, Bitu port);\nvoid adlib_write_index(void *chip, Bitu port, Bit8u val);*/\nstatic void adlib_write(void *chip, Bitu idx, Bit8u val);\n"
  },
  {
    "path": "VGMPlay/chips/opll.c",
    "content": "/*\n * Copyright (C) 2019 Nuke.YKT\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n *\n *  Yamaha YM2413 emulator\n *  Thanks:\n *      siliconpr0n.org(digshadow, John McMaster):\n *          VRC VII decap and die shot.\n *\n *  version: 1.0\n */\n\n#include <string.h>\n#include \"opll.h\"\n\nenum {\n    eg_num_attack = 0,\n    eg_num_decay = 1,\n    eg_num_sustain = 2,\n    eg_num_release = 3\n};\n\nenum {\n    rm_num_bd0 = 0,\n    rm_num_hh = 1,\n    rm_num_tom = 2,\n    rm_num_bd1 = 3,\n    rm_num_sd = 4,\n    rm_num_tc = 5\n};\n\n/* logsin table */\nstatic const uint16_t logsinrom[256] = {\n    0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471,\n    0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365,\n    0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd,\n    0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261,\n    0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f,\n    0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd,\n    0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195,\n    0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166,\n    0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c,\n    0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118,\n    0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8,\n    0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db,\n    0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1,\n    0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9,\n    0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094,\n    0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081,\n    0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070,\n    0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060,\n    0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052,\n    0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045,\n    0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039,\n    0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f,\n    0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026,\n    0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e,\n    0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017,\n    0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011,\n    0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c,\n    0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007,\n    0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004,\n    0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002,\n    0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001,\n    0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000\n};\n\n/* exp table */\nstatic const uint16_t exprom[256] = {\n    0x7fa, 0x7f5, 0x7ef, 0x7ea, 0x7e4, 0x7df, 0x7da, 0x7d4,\n    0x7cf, 0x7c9, 0x7c4, 0x7bf, 0x7b9, 0x7b4, 0x7ae, 0x7a9,\n    0x7a4, 0x79f, 0x799, 0x794, 0x78f, 0x78a, 0x784, 0x77f,\n    0x77a, 0x775, 0x770, 0x76a, 0x765, 0x760, 0x75b, 0x756,\n    0x751, 0x74c, 0x747, 0x742, 0x73d, 0x738, 0x733, 0x72e,\n    0x729, 0x724, 0x71f, 0x71a, 0x715, 0x710, 0x70b, 0x706,\n    0x702, 0x6fd, 0x6f8, 0x6f3, 0x6ee, 0x6e9, 0x6e5, 0x6e0,\n    0x6db, 0x6d6, 0x6d2, 0x6cd, 0x6c8, 0x6c4, 0x6bf, 0x6ba,\n    0x6b5, 0x6b1, 0x6ac, 0x6a8, 0x6a3, 0x69e, 0x69a, 0x695,\n    0x691, 0x68c, 0x688, 0x683, 0x67f, 0x67a, 0x676, 0x671,\n    0x66d, 0x668, 0x664, 0x65f, 0x65b, 0x657, 0x652, 0x64e,\n    0x649, 0x645, 0x641, 0x63c, 0x638, 0x634, 0x630, 0x62b,\n    0x627, 0x623, 0x61e, 0x61a, 0x616, 0x612, 0x60e, 0x609,\n    0x605, 0x601, 0x5fd, 0x5f9, 0x5f5, 0x5f0, 0x5ec, 0x5e8,\n    0x5e4, 0x5e0, 0x5dc, 0x5d8, 0x5d4, 0x5d0, 0x5cc, 0x5c8,\n    0x5c4, 0x5c0, 0x5bc, 0x5b8, 0x5b4, 0x5b0, 0x5ac, 0x5a8,\n    0x5a4, 0x5a0, 0x59c, 0x599, 0x595, 0x591, 0x58d, 0x589,\n    0x585, 0x581, 0x57e, 0x57a, 0x576, 0x572, 0x56f, 0x56b,\n    0x567, 0x563, 0x560, 0x55c, 0x558, 0x554, 0x551, 0x54d,\n    0x549, 0x546, 0x542, 0x53e, 0x53b, 0x537, 0x534, 0x530,\n    0x52c, 0x529, 0x525, 0x522, 0x51e, 0x51b, 0x517, 0x514,\n    0x510, 0x50c, 0x509, 0x506, 0x502, 0x4ff, 0x4fb, 0x4f8,\n    0x4f4, 0x4f1, 0x4ed, 0x4ea, 0x4e7, 0x4e3, 0x4e0, 0x4dc,\n    0x4d9, 0x4d6, 0x4d2, 0x4cf, 0x4cc, 0x4c8, 0x4c5, 0x4c2,\n    0x4be, 0x4bb, 0x4b8, 0x4b5, 0x4b1, 0x4ae, 0x4ab, 0x4a8,\n    0x4a4, 0x4a1, 0x49e, 0x49b, 0x498, 0x494, 0x491, 0x48e,\n    0x48b, 0x488, 0x485, 0x482, 0x47e, 0x47b, 0x478, 0x475,\n    0x472, 0x46f, 0x46c, 0x469, 0x466, 0x463, 0x460, 0x45d,\n    0x45a, 0x457, 0x454, 0x451, 0x44e, 0x44b, 0x448, 0x445,\n    0x442, 0x43f, 0x43c, 0x439, 0x436, 0x433, 0x430, 0x42d,\n    0x42a, 0x428, 0x425, 0x422, 0x41f, 0x41c, 0x419, 0x416,\n    0x414, 0x411, 0x40e, 0x40b, 0x408, 0x406, 0x403, 0x400\n};\n\nstatic const opll_patch_t patch_ds1001[opll_patch_max] = {\n    { 0x05, 0x00, 0x00, 0x06,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x03, 0x01 },{ 0x00, 0x00 },{ 0x0e, 0x08 },{ 0x08, 0x01 },{ 0x04, 0x02 },{ 0x02, 0x07 } },\n    { 0x14, 0x00, 0x01, 0x05,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x03, 0x01 },{ 0x00, 0x00 },{ 0x0d, 0x0f },{ 0x08, 0x06 },{ 0x02, 0x01 },{ 0x03, 0x02 } },\n    { 0x08, 0x00, 0x01, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x0f, 0x0b },{ 0x0a, 0x02 },{ 0x02, 0x01 },{ 0x00, 0x02 } },\n    { 0x0c, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x0a, 0x06 },{ 0x08, 0x04 },{ 0x06, 0x02 },{ 0x01, 0x07 } },\n    { 0x1e, 0x00, 0x00, 0x06,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x02, 0x01 },{ 0x00, 0x00 },{ 0x0e, 0x07 },{ 0x01, 0x06 },{ 0x00, 0x02 },{ 0x01, 0x08 } },\n    { 0x06, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x02, 0x01 },{ 0x00, 0x00 },{ 0x0a, 0x0e },{ 0x03, 0x02 },{ 0x0f, 0x0f },{ 0x04, 0x04 } },\n    { 0x1d, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x08, 0x08 },{ 0x02, 0x01 },{ 0x01, 0x00 },{ 0x01, 0x07 } },\n    { 0x22, 0x01, 0x00, 0x07,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x03, 0x01 },{ 0x00, 0x00 },{ 0x0a, 0x07 },{ 0x02, 0x02 },{ 0x00, 0x01 },{ 0x01, 0x07 } },\n    { 0x25, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x05, 0x01 },{ 0x00, 0x00 },{ 0x04, 0x07 },{ 0x00, 0x03 },{ 0x07, 0x00 },{ 0x02, 0x01 } },\n    { 0x0f, 0x00, 0x01, 0x07,{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x00 },{ 0x05, 0x01 },{ 0x00, 0x00 },{ 0x0a, 0x0a },{ 0x08, 0x05 },{ 0x05, 0x00 },{ 0x01, 0x02 } },\n    { 0x24, 0x00, 0x00, 0x07,{ 0x00, 0x01 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x07, 0x01 },{ 0x00, 0x00 },{ 0x0f, 0x0f },{ 0x08, 0x08 },{ 0x02, 0x01 },{ 0x02, 0x02 } },\n    { 0x11, 0x00, 0x00, 0x06,{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x01, 0x03 },{ 0x00, 0x00 },{ 0x06, 0x07 },{ 0x05, 0x04 },{ 0x01, 0x01 },{ 0x08, 0x06 } },\n    { 0x13, 0x00, 0x00, 0x05,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x02 },{ 0x03, 0x00 },{ 0x0c, 0x09 },{ 0x09, 0x05 },{ 0x00, 0x00 },{ 0x03, 0x02 } },\n    { 0x0c, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x03 },{ 0x00, 0x00 },{ 0x09, 0x0c },{ 0x04, 0x00 },{ 0x03, 0x0f },{ 0x03, 0x06 } },\n    { 0x0d, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x01 },{ 0x01, 0x02 },{ 0x00, 0x00 },{ 0x0c, 0x0d },{ 0x01, 0x05 },{ 0x05, 0x00 },{ 0x06, 0x06 } },\n\n    { 0x18, 0x00, 0x01, 0x07,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x0d, 0x00 },{ 0x0f, 0x00 },{ 0x06, 0x00 },{ 0x0a, 0x00 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x0c, 0x00 },{ 0x08, 0x00 },{ 0x0a, 0x00 },{ 0x07, 0x00 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x05, 0x00 },{ 0x00, 0x00 },{ 0x0f, 0x00 },{ 0x08, 0x00 },{ 0x05, 0x00 },{ 0x09, 0x00 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0f },{ 0x00, 0x08 },{ 0x00, 0x06 },{ 0x00, 0x0d } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0d },{ 0x00, 0x08 },{ 0x00, 0x06 },{ 0x00, 0x08 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0a },{ 0x00, 0x0a },{ 0x00, 0x05 },{ 0x00, 0x05 } }\n};\n\nstatic const opll_patch_t patch_ym2413[opll_patch_max] = {\n    { 0x1e, 0x01, 0x00, 0x07,{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x0d, 0x07 },{ 0x00, 0x08 },{ 0x00, 0x01 },{ 0x00, 0x07 } },\n    { 0x1a, 0x00, 0x01, 0x05,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x03, 0x01 },{ 0x00, 0x00 },{ 0x0d, 0x0f },{ 0x08, 0x07 },{ 0x02, 0x01 },{ 0x03, 0x03 } },\n    { 0x19, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x03, 0x01 },{ 0x02, 0x00 },{ 0x0f, 0x0c },{ 0x02, 0x04 },{ 0x01, 0x02 },{ 0x01, 0x03 } },\n    { 0x0e, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x0a, 0x06 },{ 0x08, 0x04 },{ 0x07, 0x02 },{ 0x00, 0x07 } },\n    { 0x1e, 0x00, 0x00, 0x06,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x02, 0x01 },{ 0x00, 0x00 },{ 0x0e, 0x07 },{ 0x00, 0x06 },{ 0x00, 0x02 },{ 0x00, 0x08 } },\n    { 0x16, 0x00, 0x00, 0x05,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x01, 0x02 },{ 0x00, 0x00 },{ 0x0e, 0x07 },{ 0x00, 0x01 },{ 0x00, 0x01 },{ 0x00, 0x08 } },\n    { 0x1d, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x08, 0x08 },{ 0x02, 0x01 },{ 0x01, 0x00 },{ 0x00, 0x07 } },\n    { 0x2d, 0x01, 0x00, 0x04,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x03, 0x01 },{ 0x00, 0x00 },{ 0x0a, 0x07 },{ 0x02, 0x02 },{ 0x00, 0x00 },{ 0x00, 0x07 } },\n    { 0x1b, 0x00, 0x00, 0x06,{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x06, 0x06 },{ 0x04, 0x05 },{ 0x01, 0x01 },{ 0x00, 0x07 } },\n    { 0x0b, 0x01, 0x01, 0x00,{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x08, 0x0f },{ 0x05, 0x07 },{ 0x07, 0x00 },{ 0x01, 0x07 } },\n    { 0x03, 0x01, 0x00, 0x01,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x03, 0x01 },{ 0x02, 0x00 },{ 0x0f, 0x0e },{ 0x0a, 0x04 },{ 0x01, 0x00 },{ 0x00, 0x04 } },\n    { 0x24, 0x00, 0x00, 0x07,{ 0x00, 0x01 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x07, 0x01 },{ 0x00, 0x00 },{ 0x0f, 0x0f },{ 0x08, 0x08 },{ 0x02, 0x01 },{ 0x02, 0x02 } },\n    { 0x0c, 0x00, 0x00, 0x05,{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x0c, 0x0f },{ 0x02, 0x05 },{ 0x02, 0x04 },{ 0x00, 0x02 } },\n    { 0x15, 0x00, 0x00, 0x03,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x0c, 0x09 },{ 0x09, 0x05 },{ 0x00, 0x00 },{ 0x03, 0x02 } },\n    { 0x09, 0x00, 0x00, 0x03,{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x02, 0x00 },{ 0x0f, 0x0e },{ 0x01, 0x04 },{ 0x04, 0x01 },{ 0x00, 0x03 } },\n\n    { 0x18, 0x00, 0x01, 0x07,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x0d, 0x00 },{ 0x0f, 0x00 },{ 0x06, 0x00 },{ 0x0a, 0x00 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x0c, 0x00 },{ 0x08, 0x00 },{ 0x0a, 0x00 },{ 0x07, 0x00 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x05, 0x00 },{ 0x00, 0x00 },{ 0x0f, 0x00 },{ 0x08, 0x00 },{ 0x05, 0x00 },{ 0x09, 0x00 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0f },{ 0x00, 0x08 },{ 0x00, 0x06 },{ 0x00, 0x0d } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0d },{ 0x00, 0x08 },{ 0x00, 0x04 },{ 0x00, 0x08 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0a },{ 0x00, 0x0a },{ 0x00, 0x05 },{ 0x00, 0x05 } }\n};\n\nstatic const opll_patch_t patch_ymf281[opll_patch_max] = {\n    { 0x1a, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x02, 0x01 },{ 0x00, 0x00 },{ 0x0f, 0x06 },{ 0x0f, 0x07 },{ 0x00, 0x01 },{ 0x00, 0x06 } },\n    { 0x05, 0x00, 0x00, 0x01,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x0f, 0x08 },{ 0x06, 0x03 },{ 0x08, 0x00 },{ 0x00, 0x03 } },\n    { 0x16, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x03, 0x01 },{ 0x02, 0x00 },{ 0x0f, 0x0d },{ 0x02, 0x03 },{ 0x01, 0x00 },{ 0x01, 0x03 } },\n    { 0x0b, 0x00, 0x01, 0x07,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x0a, 0x06 },{ 0x08, 0x04 },{ 0x07, 0x01 },{ 0x00, 0x07 } },\n    { 0x1e, 0x00, 0x00, 0x06,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x02, 0x01 },{ 0x00, 0x00 },{ 0x0e, 0x07 },{ 0x01, 0x06 },{ 0x00, 0x02 },{ 0x00, 0x08 } },\n    { 0x02, 0x00, 0x01, 0x06,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x02, 0x00 },{ 0x09, 0x06 },{ 0x0a, 0x01 },{ 0x02, 0x02 },{ 0x00, 0x07 } },\n    { 0x1b, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x08, 0x08 },{ 0x04, 0x03 },{ 0x01, 0x00 },{ 0x00, 0x07 } },\n    { 0x0a, 0x00, 0x00, 0x02,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x07, 0x02 },{ 0x03, 0x00 },{ 0x06, 0x06 },{ 0x06, 0x04 },{ 0x04, 0x02 },{ 0x00, 0x07 } },\n    { 0x07, 0x00, 0x00, 0x03,{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x0c, 0x07 },{ 0x05, 0x07 },{ 0x05, 0x00 },{ 0x01, 0x07 } },\n    { 0x1e, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x00 },{ 0x06, 0x01 },{ 0x01, 0x00 },{ 0x0f, 0x0f },{ 0x02, 0x03 },{ 0x0f, 0x0f },{ 0x00, 0x03 } },\n    { 0x18, 0x00, 0x00, 0x06,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x0f, 0x0e },{ 0x05, 0x03 },{ 0x02, 0x01 },{ 0x00, 0x03 } },\n    { 0x24, 0x00, 0x00, 0x07,{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x07, 0x01 },{ 0x00, 0x00 },{ 0x0f, 0x0f },{ 0x08, 0x08 },{ 0x02, 0x00 },{ 0x02, 0x03 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x05, 0x04 },{ 0x00, 0x00 },{ 0x0f, 0x0f },{ 0x0f, 0x03 },{ 0x07, 0x0f },{ 0x00, 0x05 } },\n    { 0x03, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x01 },{ 0x0f, 0x01 },{ 0x00, 0x00 },{ 0x0f, 0x0e },{ 0x0c, 0x03 },{ 0x03, 0x0f },{ 0x0f, 0x0c } },\n    { 0x00, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x0a, 0x01 },{ 0x00, 0x00 },{ 0x0b, 0x08 },{ 0x0f, 0x04 },{ 0x00, 0x0f },{ 0x00, 0x05 } },\n\n    { 0x18, 0x00, 0x01, 0x07,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x0d, 0x00 },{ 0x0f, 0x00 },{ 0x06, 0x00 },{ 0x0a, 0x00 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x0c, 0x00 },{ 0x08, 0x00 },{ 0x0a, 0x00 },{ 0x07, 0x00 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x05, 0x00 },{ 0x00, 0x00 },{ 0x0f, 0x00 },{ 0x08, 0x00 },{ 0x05, 0x00 },{ 0x09, 0x00 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0f },{ 0x00, 0x08 },{ 0x00, 0x06 },{ 0x00, 0x0d } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0d },{ 0x00, 0x08 },{ 0x00, 0x04 },{ 0x00, 0x08 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0a },{ 0x00, 0x0a },{ 0x00, 0x05 },{ 0x00, 0x05 } }\n};\n\nstatic const opll_patch_t patch_ym2423[opll_patch_max] = {\n    { 0x1b, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x09, 0x05 },{ 0x04, 0x04 },{ 0x01, 0x00 },{ 0x00, 0x05 } },\n    { 0x12, 0x00, 0x00, 0x04,{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x03, 0x01 },{ 0x01, 0x00 },{ 0x0f, 0x0f },{ 0x03, 0x02 },{ 0x0a, 0x0e },{ 0x00, 0x09 } },\n    { 0x11, 0x00, 0x00, 0x05,{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x02 },{ 0x0f, 0x0f },{ 0x02, 0x02 },{ 0x05, 0x07 },{ 0x00, 0x05 } },\n    { 0x28, 0x00, 0x00, 0x07,{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x03, 0x02 },{ 0x00, 0x00 },{ 0x0f, 0x0f },{ 0x03, 0x02 },{ 0x09, 0x0b },{ 0x00, 0x04 } },\n    { 0x17, 0x00, 0x00, 0x05,{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x02, 0x01 },{ 0x02, 0x00 },{ 0x05, 0x06 },{ 0x01, 0x0f },{ 0x07, 0x00 },{ 0x00, 0x09 } },\n    { 0x18, 0x00, 0x00, 0x06,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x03, 0x00 },{ 0x00, 0x00 },{ 0x0f, 0x0f },{ 0x07, 0x04 },{ 0x05, 0x08 },{ 0x00, 0x05 } },\n    { 0x1c, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x05, 0x07 },{ 0x01, 0x01 },{ 0x02, 0x02 },{ 0x00, 0x06 } },\n    { 0x1b, 0x00, 0x00, 0x07,{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x04 },{ 0x00, 0x00 },{ 0x07, 0x03 },{ 0x03, 0x0f },{ 0x00, 0x00 },{ 0x00, 0x06 } },\n    { 0x0d, 0x00, 0x00, 0x03,{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x04, 0x06 },{ 0x02, 0x0f },{ 0x02, 0x00 },{ 0x00, 0x06 } },\n    { 0x10, 0x00, 0x00, 0x05,{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x02 },{ 0x0f, 0x0f },{ 0x03, 0x03 },{ 0x02, 0x00 },{ 0x00, 0x04 } },\n    { 0x1b, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x0c, 0x09 },{ 0x05, 0x06 },{ 0x0f, 0x0f },{ 0x00, 0x06 } },\n    { 0x1b, 0x00, 0x00, 0x00,{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x09, 0x01 },{ 0x03, 0x00 },{ 0x0f, 0x0f },{ 0x05, 0x03 },{ 0x07, 0x0f },{ 0x00, 0x02 } },\n    { 0x11, 0x00, 0x00, 0x03,{ 0x00, 0x01 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x02 },{ 0x02, 0x00 },{ 0x09, 0x0b },{ 0x04, 0x01 },{ 0x0e, 0x0f },{ 0x00, 0x07 } },\n    { 0x17, 0x00, 0x00, 0x06,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x0d, 0x0e },{ 0x03, 0x01 },{ 0x0b, 0x0e },{ 0x00, 0x0b } },\n    { 0x0d, 0x00, 0x00, 0x05,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x06 },{ 0x00, 0x00 },{ 0x0f, 0x0f },{ 0x02, 0x04 },{ 0x02, 0x09 },{ 0x00, 0x09 } },\n\n    { 0x18, 0x00, 0x01, 0x07,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x0d, 0x00 },{ 0x0f, 0x00 },{ 0x06, 0x00 },{ 0x0a, 0x00 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x0c, 0x00 },{ 0x08, 0x00 },{ 0x0a, 0x00 },{ 0x07, 0x00 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x05, 0x00 },{ 0x00, 0x00 },{ 0x0f, 0x00 },{ 0x08, 0x00 },{ 0x05, 0x00 },{ 0x09, 0x00 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0f },{ 0x00, 0x08 },{ 0x00, 0x06 },{ 0x00, 0x0d } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0d },{ 0x00, 0x08 },{ 0x00, 0x04 },{ 0x00, 0x08 } },\n    { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0a },{ 0x00, 0x0a },{ 0x00, 0x05 },{ 0x00, 0x05 } }\n};\n\nstatic const uint32_t ch_offset[18] = {\n    1, 2, 0, 1, 2, 3, 4, 5, 3, 4, 5, 6, 7, 8, 6, 7, 8, 0\n};\n\nstatic const uint32_t pg_multi[16] = {\n    1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30\n};\n\nstatic const uint32_t eg_stephi[4][4] = {\n    { 0, 0, 0, 0 },\n    { 1, 0, 0, 0 },\n    { 1, 0, 1, 0 },\n    { 1, 1, 1, 0 }\n};\n\nstatic const uint32_t eg_ksltable[16] = {\n    0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64\n};\n\nvoid OPLL_DoIO(opll_t *chip) {\n    /* Write signal check */\n    chip->write_a_en = (chip->write_a & 0x03) == 0x01;\n    chip->write_d_en = (chip->write_d & 0x03) == 0x01;\n    chip->write_a <<= 1;\n    chip->write_d <<= 1;\n}\n\nvoid OPLL_DoModeWrite(opll_t *chip) {\n    uint8_t slot;\n    if ((chip->write_mode_address & 0x10) && chip->write_d_en) {\n        slot = chip->write_mode_address & 0x01;\n        switch (chip->write_mode_address & 0x0f) {\n        case 0x00:\n        case 0x01:\n            chip->patch.multi[slot] = chip->write_data & 0x0f;\n            chip->patch.ksr[slot] = (chip->write_data >> 4) & 0x01;\n            chip->patch.et[slot] = (chip->write_data >> 5) & 0x01;\n            chip->patch.vib[slot] = (chip->write_data >> 6) & 0x01;\n            chip->patch.am[slot] = (chip->write_data >> 7) & 0x01;\n            break;\n\n        case 0x02:\n            chip->patch.ksl[0] = (chip->write_data >> 6) & 0x03;\n            chip->patch.tl = chip->write_data & 0x3f;\n            break;\n\n        case 0x03:\n            chip->patch.ksl[1] = (chip->write_data >> 6) & 0x03;\n            chip->patch.dc = (chip->write_data >> 4) & 0x01;\n            chip->patch.dm = (chip->write_data >> 3) & 0x01;\n            chip->patch.fb = chip->write_data & 0x07;\n            break;\n\n        case 0x04:\n        case 0x05:\n            chip->patch.dr[slot] = chip->write_data & 0x0f;\n            chip->patch.ar[slot] = (chip->write_data >> 4) & 0x0f;\n            break;\n\n        case 0x06:\n        case 0x07:\n            chip->patch.rr[slot] = chip->write_data & 0x0f;\n            chip->patch.sl[slot] = (chip->write_data >> 4) & 0x0f;\n            break;\n\n        case 0x0e:\n            chip->rhythm = chip->write_data & 0x3f;\n            if (chip->chip_type == opll_type_ds1001) {\n                chip->rhythm |= 0x20;\n            }\n            chip->rm_enable = (chip->rm_enable & 0x7f) | ((chip->rhythm << 2) & 0x80);\n            break;\n\n        case 0x0f:\n            chip->testmode = chip->write_data & 0x0f;\n            break;\n        }\n    }\n}\n\nvoid OPLL_Reset(opll_t *chip, uint32_t chip_type, uint32_t rate, uint32_t clock) {\n    uint32_t i;\n    uint32_t rateratio;\n    rateratio = chip->rateratio;\n    memset(chip, 0, sizeof(opll_t));\n    chip->chip_type = chip_type;\n    if (chip_type == opll_type_ds1001) {\n        /* Rhythm mode is always on */\n        chip->rhythm = 0x20;\n        chip->rm_enable = (int8_t)0x80;\n    }\n    switch (chip_type) {\n    case opll_type_ds1001:\n        chip->patchrom = patch_ds1001;\n        break;\n    case opll_type_ymf281:\n    case opll_type_ymf281b:\n        chip->patchrom = patch_ymf281;\n        break;\n    case opll_type_ym2423:\n        chip->patchrom = patch_ym2423;\n        break;\n    case opll_type_ym2413:\n    case opll_type_ym2413b:\n    case opll_type_ym2420:\n    default:\n        chip->patchrom = patch_ym2413;\n        break;\n    }\n    for (i = 0; i < 18; i++) {\n        chip->eg_state[i] = eg_num_release;\n        chip->eg_level[i] = 0x7f;\n        chip->eg_out = 0x7f;\n    }\n    chip->rm_select = rm_num_tc + 1;\n\n    if (rate != 0)\n    {\n        chip->rateratio = (uint32_t)((((uint64_t)72 * rate) << RSM_FRAC) / clock);\n    }\n    else\n    {\n        chip->rateratio = rateratio;\n    }\n}\n\nvoid OPLL_DoRegWrite(opll_t *chip) {\n    uint32_t channel;\n\n    /* Address */\n    if (chip->write_a_en) {\n        if ((chip->write_data & 0xc0) == 0x00) {\n            /* FM Write */\n            chip->write_fm_address = 1;\n            chip->address = chip->write_data;\n        } else {\n            chip->write_fm_address = 0;\n        }\n    }\n    /* Data */\n    if (chip->write_fm_address && chip->write_d_en) {\n        chip->data = chip->write_data;\n    }\n\n    /* Update registers */\n    if (chip->write_fm_data && !chip->write_a_en) {\n        if ((chip->address & 0x0f) == chip->cycles && chip->cycles < 16) {\n            channel = chip->cycles % 9;\n            switch (chip->address & 0xf0) {\n            case 0x10:\n                if (chip->chip_type == opll_type_ym2420)\n                {\n                    chip->fnum[channel] = (chip->fnum[channel] & 0x0f) | ((chip->data & 0x1f) << 4);\n                    chip->block[channel] = (chip->data >> 5) & 0x07;\n                }\n                else\n                    chip->fnum[channel] = (chip->fnum[channel] & 0x100) | chip->data;\n                break;\n            case 0x20:\n                if (chip->chip_type == opll_type_ym2420)\n                    chip->fnum[channel] = (chip->fnum[channel] & 0x1f0) | (chip->data & 0x0f);\n                else\n                {\n                    chip->fnum[channel] = (chip->fnum[channel] & 0xff) | ((chip->data & 0x01) << 8);\n                    chip->block[channel] = (chip->data >> 1) & 0x07;\n                }\n                chip->kon[channel] = (chip->data >> 4) & 0x01;\n                chip->son[channel] = (chip->data >> 5) & 0x01;\n                break;\n            case 0x30:\n                chip->vol[channel] = chip->data & 0x0f;\n                chip->inst[channel] = (chip->data >> 4) & 0x0f;\n                break;\n            }\n        }\n    }\n\n\n    if (chip->write_a_en) {\n        chip->write_fm_data = 0;\n    }\n    if (chip->write_fm_address && chip->write_d_en) {\n        chip->write_fm_data = 1;\n    }\n    if (chip->write_a_en) {\n        if (((chip->write_data & 0xf0) == 0x00)) {\n            chip->write_mode_address = 0x10 | (chip->write_data & 0x0f);\n        } else {\n            chip->write_mode_address = 0x00;\n        }\n    }\n\n}\nvoid OPLL_PreparePatch1(opll_t *chip) {\n    uint8_t instr;\n    uint32_t mcsel = ((chip->cycles + 1) / 3) & 0x01;\n    uint32_t instr_index;\n    uint32_t ch = ch_offset[chip->cycles];\n    const opll_patch_t *patch;\n    instr = chip->inst[ch];\n    if (instr > 0) {\n        instr_index = opll_patch_1 + instr - 1;\n    }\n    if (chip->rm_select <= rm_num_tc) {\n        instr_index = opll_patch_drum_0 + chip->rm_select;\n    }\n    if (chip->rm_select <= rm_num_tc || instr > 0) {\n        patch = &chip->patchrom[instr_index];\n    } else {\n        patch = &chip->patch;\n    }\n    if (chip->rm_select == rm_num_hh || chip->rm_select == rm_num_tom) {\n        chip->c_tl = chip->inst[ch] << 2;\n    } else if (mcsel == 1) {\n        chip->c_tl = chip->vol[ch] << 2;\n    } else {\n        chip->c_tl = patch->tl;\n    }\n\n    chip->c_adrr[0] = patch->ar[mcsel];\n    chip->c_adrr[1] = patch->dr[mcsel];\n    chip->c_adrr[2] = patch->rr[mcsel];\n    chip->c_et = patch->et[mcsel];\n    chip->c_ksr = patch->ksr[mcsel];\n    chip->c_ksl = patch->ksl[mcsel];\n    chip->c_ksr_freq = (chip->block[ch] << 1) | (chip->fnum[ch] >> 8);\n    chip->c_ksl_freq = (chip->fnum[ch]>>5);\n    chip->c_ksl_block = (chip->block[ch]);\n}\n\nvoid OPLL_PreparePatch2(opll_t *chip) {\n    uint8_t instr;\n    uint32_t mcsel = ((chip->cycles + 1) / 3) & 0x01;\n    uint32_t instr_index;\n    const opll_patch_t *patch;\n    instr = chip->inst[ch_offset[chip->cycles]];\n    if (instr > 0) {\n        instr_index = opll_patch_1 + instr - 1;\n    }\n    if (chip->rm_select <= rm_num_tc) {\n        instr_index = opll_patch_drum_0 + chip->rm_select;\n    }\n    if (chip->rm_select <= rm_num_tc || instr > 0) {\n        patch = &chip->patchrom[instr_index];\n    } else {\n        patch = &chip->patch;\n    }\n\n    chip->c_fnum = chip->fnum[ch_offset[chip->cycles]];\n    chip->c_block = chip->block[ch_offset[chip->cycles]];\n\n    chip->c_multi = patch->multi[mcsel];\n    chip->c_sl = patch->sl[mcsel];\n    chip->c_fb = patch->fb;\n    chip->c_vib = patch->vib[mcsel];\n    chip->c_am = patch->am[mcsel];\n    chip->c_dc <<= 1;\n    chip->c_dm <<= 1;\n    chip->c_dc |= patch->dc;\n    chip->c_dm |= patch->dm;\n}\n\nvoid OPLL_PhaseGenerate(opll_t *chip) {\n    uint32_t ismod;\n    uint32_t phase;\n    uint8_t rm_bit;\n    uint16_t pg_out;\n\n    chip->pg_phase[(chip->cycles + 17) % 18] = chip->pg_phase_next + chip->pg_inc;\n\n    if ((chip->rm_enable & 0x40) && (chip->cycles == 13 || chip->cycles == 14)) {\n        ismod = 0;\n    } else {\n        ismod = ((chip->cycles + 3) / 3) & 1;\n    }\n    phase = chip->pg_phase[chip->cycles];\n    /* KeyOn event check */\n    if ((chip->testmode & 0x04)\n     || (ismod && (chip->eg_dokon & 0x8000)) || (!ismod && (chip->eg_dokon & 0x01))) {\n        chip->pg_phase_next = 0;\n    } else {\n        chip->pg_phase_next = phase;\n    }\n    /* Rhythm mode */\n    if (chip->cycles == 13) {\n        chip->rm_hh_bit2 = (phase >> (2 + 9)) & 1;\n        chip->rm_hh_bit3 = (phase >> (3 + 9)) & 1;\n        chip->rm_hh_bit7 = (phase >> (7 + 9)) & 1;\n        chip->rm_hh_bit8 = (phase >> (8 + 9)) & 1;\n    } else if (chip->cycles == 17 && (chip->rm_enable & 0x80)) {\n        chip->rm_tc_bit3 = (phase >> (3 + 9)) & 1;\n        chip->rm_tc_bit5 = (phase >> (5 + 9)) & 1;\n    }\n    if ((chip->rm_enable & 0x80)) {\n        switch (chip->cycles) {\n        case 13:\n            /* HH */\n            rm_bit = (chip->rm_hh_bit2 ^ chip->rm_hh_bit7)\n                   | (chip->rm_hh_bit3 ^ chip->rm_tc_bit5)\n                   | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5);\n            pg_out = rm_bit << 9;\n            if (rm_bit ^ (chip->rm_noise & 1)) {\n                pg_out |= 0xd0;\n            } else {\n                pg_out |= 0x34;\n            }\n            break;\n        case 16:\n            /* SD */\n            pg_out = (chip->rm_hh_bit8 << 9)\n                   | ((chip->rm_hh_bit8 ^ (chip->rm_noise & 1)) << 8);\n            break;\n        case 17:\n            /* TC */\n            rm_bit = (chip->rm_hh_bit2 ^ chip->rm_hh_bit7)\n                   | (chip->rm_hh_bit3 ^ chip->rm_tc_bit5)\n                   | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5);\n            pg_out = (rm_bit << 9) | 0x100;\n            break;\n        default:\n            pg_out = phase >> 9;\n        }\n    } else {\n        pg_out = phase >> 9;\n    }\n    chip->pg_out = pg_out;\n}\n\nvoid OPLL_PhaseCalcIncrement(opll_t *chip) {\n    uint32_t freq;\n    uint16_t block;\n    freq = chip->c_fnum << 1;\n    block = chip->c_block;\n    /* Apply vibrato */\n    if (chip->c_vib) {\n        switch (chip->lfo_vib_counter) {\n        case 0:\n        case 4:\n            break;\n        case 1:\n        case 3:\n            freq += freq >> 8;\n            break;\n        case 2:\n            freq += freq >> 7;\n            break;\n        case 5:\n        case 7:\n            freq -= freq >> 8;\n            break;\n        case 6:\n            freq -= freq >> 7;\n            break;\n        }\n    }\n    /* Apply block */\n    freq = (freq << block) >> 1;\n\n    chip->pg_inc = (freq * pg_multi[chip->c_multi]) >> 1;\n}\n\nvoid OPLL_EnvelopeKSLTL(opll_t *chip)\n{\n    int32_t ksl;\n\n    ksl = eg_ksltable[chip->c_ksl_freq]-((8-chip->c_ksl_block)<<3);\n    if (ksl < 0) {\n        ksl = 0;\n    }\n\n    ksl <<= 1;\n\n    if (chip->c_ksl) {\n        ksl = ksl >> (3-chip->c_ksl);\n    } else {\n        ksl = 0;\n    }\n\n    chip->eg_ksltl = ksl + (chip->c_tl<<1);\n}\n\nvoid OPLL_EnvelopeOutput(opll_t *chip)\n{\n    int32_t level = chip->eg_level[(chip->cycles+17)%18];\n\n    level += chip->eg_ksltl;\n\n    if (chip->c_am) {\n        level += chip->lfo_am_out;\n    }\n\n    if (level >= 128) {\n        level = 127;\n    }\n\n    if (chip->testmode & 0x01) {\n        level = 0;\n    }\n\n    chip->eg_out = level;\n}\n\nvoid OPLL_EnvelopeGenerate(opll_t *chip) {\n    uint8_t timer_inc;\n    uint8_t timer_bit;\n    uint8_t timer_low;\n    uint8_t rate;\n    uint8_t state_rate;\n    uint8_t ksr;\n    uint8_t sum;\n    uint8_t rate_hi;\n    uint8_t rate_lo;\n    int32_t level;\n    int32_t next_level;\n    uint8_t zero;\n    uint8_t state;\n    uint8_t next_state;\n    int32_t step;\n    int32_t sl;\n    uint32_t mcsel = ((chip->cycles + 1) / 3) & 0x01;\n\n\n    /* EG timer */\n    if ((chip->eg_counter_state & 3) != 3) {\n        timer_inc = 0;\n    } else if (chip->cycles == 0) {\n        timer_inc = 1;\n    } else {\n        timer_inc = chip->eg_timer_carry;\n    }\n    timer_low = chip->eg_timer & 3;\n    timer_bit = chip->eg_timer & 1;\n    timer_bit += timer_inc;\n    chip->eg_timer_carry = timer_bit >> 1;\n    chip->eg_timer = ((timer_bit & 1) << 17) | (chip->eg_timer >> 1);\n    if (chip->testmode & 0x08) {\n        chip->eg_timer &= 0x2ffff;\n        chip->eg_timer |= (chip->write_data << (16 - 2)) & 0x10000;\n    }\n    if (!chip->eg_timer_shift_stop && ((chip->eg_timer >> 16) & 1)) {\n        chip->eg_timer_shift = chip->cycles;\n    }\n    if (chip->cycles == 0 && (chip->eg_counter_state_prev & 1) == 1) {\n        chip->eg_timer_low_lock = timer_low;\n        chip->eg_timer_shift_lock = chip->eg_timer_shift;\n        if (chip->eg_timer_shift_lock > 13)\n            chip->eg_timer_shift_lock = 0;\n\n        chip->eg_timer_shift = 0;\n    }\n    chip->eg_timer_shift_stop |= (chip->eg_timer >> 16) & 1;\n    if (chip->cycles == 0) {\n        chip->eg_timer_shift_stop = 0;\n    }\n    chip->eg_counter_state_prev = chip->eg_counter_state;\n    if (chip->cycles == 17) {\n        chip->eg_counter_state++;\n    }\n\n    level = chip->eg_level[(chip->cycles+16)%18];\n    next_level = level;\n    zero = level == 0;\n    chip->eg_silent = level == 0x7f;\n\n    if (chip->eg_state[(chip->cycles+16)%18] != eg_num_attack && (chip->eg_off&2) && !(chip->eg_dokon&2)) {\n        next_level = 0x7f;\n    }\n\n    if (chip->eg_maxrate && (chip->eg_dokon&2)) {\n        next_level = 0x00;\n    }\n\n\n    state = chip->eg_state[(chip->cycles+16)%18];\n    next_state = eg_num_attack;\n\n    step = 0;\n    sl = chip->eg_sl;\n\n    switch (state) {\n    case eg_num_attack:\n        if (!chip->eg_maxrate && (chip->eg_kon & 2) && !zero) {\n            int32_t shift = chip->eg_rate_hi - 11 + chip->eg_inc_hi;\n            if (chip->eg_inc_lo) {\n                shift = 1;\n            }\n            if (shift > 0) {\n                if (shift > 4)\n                    shift = 4;\n                step = ~level >> (5 - shift);\n            }\n        }\n        if (zero) {\n            next_state = eg_num_decay;\n        } else {\n            next_state = eg_num_attack;\n        }\n        break;\n    case eg_num_decay:\n        if (!(chip->eg_off & 2) && !(chip->eg_dokon & 2) && (level >> 3) != sl)\n        {\n            uint8_t i0 = chip->eg_rate_hi == 15 || (chip->eg_rate_hi == 14 && chip->eg_inc_hi);\n            uint8_t i1 = (chip->eg_rate_hi == 14 && !chip->eg_inc_hi) || (chip->eg_rate_hi == 13 && chip->eg_inc_hi) ||\n                (chip->eg_rate_hi == 13 && !chip->eg_inc_hi && (chip->eg_counter_state_prev & 1))\n                || (chip->eg_rate_hi == 12 && chip->eg_inc_hi && (chip->eg_counter_state_prev & 1))\n                || (chip->eg_rate_hi == 12 && !chip->eg_inc_hi && ((chip->eg_counter_state_prev & 3) == 3))\n                || (chip->eg_inc_lo && ((chip->eg_counter_state_prev & 3) == 3));\n            step = (i0<<1) | i1;\n        }\n        if ((level >> 3) == sl) {\n            next_state = eg_num_sustain;\n        } else {\n            next_state = eg_num_decay;\n        }\n        break;\n    case eg_num_sustain:\n    case eg_num_release:\n        if (!(chip->eg_off & 2) && !(chip->eg_dokon & 2))\n        {\n            uint8_t i0 = chip->eg_rate_hi == 15 || (chip->eg_rate_hi == 14 && chip->eg_inc_hi);\n            uint8_t i1 = (chip->eg_rate_hi == 14 && !chip->eg_inc_hi) || (chip->eg_rate_hi == 13 && chip->eg_inc_hi) ||\n                (chip->eg_rate_hi == 13 && !chip->eg_inc_hi && (chip->eg_counter_state_prev & 1))\n                || (chip->eg_rate_hi == 12 && chip->eg_inc_hi && (chip->eg_counter_state_prev & 1))\n                || (chip->eg_rate_hi == 12 && !chip->eg_inc_hi && ((chip->eg_counter_state_prev & 3) == 3))\n                || (chip->eg_inc_lo && ((chip->eg_counter_state_prev & 3) == 3));\n            step = (i0<<1) | i1;\n        }\n        next_state = state;\n        break;\n    }\n\n    if (!(chip->eg_kon & 2)) {\n        next_state = eg_num_release;\n    }\n    if (chip->eg_dokon & 2) {\n        next_state = eg_num_attack;\n    }\n\n    chip->eg_level[(chip->cycles+16)%18] = next_level+step;\n    chip->eg_state[(chip->cycles+16)%18] = next_state;\n\n    rate_hi = chip->eg_rate >> 2;\n    rate_lo = chip->eg_rate & 3;\n    chip->eg_inc_hi = eg_stephi[rate_lo][chip->eg_timer_low_lock];\n    sum = (chip->eg_timer_shift_lock + rate_hi) & 0x0f;\n    chip->eg_inc_lo = 0;\n    if (rate_hi < 12 && !chip->eg_zerorate) {\n        switch (sum) {\n        case 12:\n            chip->eg_inc_lo = 1;\n            break;\n        case 13:\n            chip->eg_inc_lo = (rate_lo >> 1) & 1;\n            break;\n        case 14:\n            chip->eg_inc_lo = rate_lo & 1;\n            break;\n        }\n    }\n    chip->eg_maxrate = rate_hi == 0x0f;\n\n    chip->eg_rate_hi = rate_hi;\n\n    chip->eg_kon <<= 1;\n    chip->eg_kon |= chip->kon[ch_offset[chip->cycles]];\n    chip->eg_off <<= 1;\n    chip->eg_off |= (chip->eg_level[chip->cycles] >> 2) == 0x1f;\n    switch (chip->rm_select) {\n    case rm_num_bd0:\n    case rm_num_bd1:\n        chip->eg_kon |= (chip->rhythm >> 4) & 1;\n        break;\n    case rm_num_sd:\n        chip->eg_kon |= (chip->rhythm >> 3) & 1;\n        break;\n    case rm_num_tom:\n        chip->eg_kon |= (chip->rhythm >> 2) & 1;\n        break;\n    case rm_num_tc:\n        chip->eg_kon |= (chip->rhythm >> 1) & 1;\n        break;\n    case rm_num_hh:\n        chip->eg_kon |= chip->rhythm & 1;\n        break;\n    }\n\n    /* Calculate rate */\n    rate = 0;\n    chip->eg_dokon <<= 1;\n    state_rate = chip->eg_state[chip->cycles];\n    if (state_rate == eg_num_release && (chip->eg_kon&1) && (chip->eg_off&1)) {\n        state_rate = eg_num_attack;\n        chip->eg_dokon |= 1;\n    }\n    switch (state_rate) {\n    case eg_num_attack:\n        rate = chip->c_adrr[0];\n        break;\n    case eg_num_decay:\n        rate = chip->c_adrr[1];\n        break;\n    case eg_num_sustain:\n        if (!chip->c_et) {\n            rate = chip->c_adrr[2];\n        }\n        break;\n    case eg_num_release:\n        if (chip->son[ch_offset[chip->cycles]]) {\n            rate = 5;\n        } else {\n            rate = chip->c_adrr[2];\n        }\n        break;\n    }\n    if (!(chip->eg_kon&1) && !mcsel && chip->rm_select != rm_num_tom && chip->rm_select != rm_num_hh) {\n        rate = 0;\n    }\n    if ((chip->eg_kon&1) && chip->eg_state[chip->cycles] == eg_num_release && !(chip->eg_off&1)) {\n        rate = 12;\n    }\n    if (!(chip->eg_kon&1) && !chip->son[ch_offset[chip->cycles]] && mcsel == 1 && !chip->c_et) {\n        rate = 7;\n    }\n    chip->eg_zerorate = rate == 0;\n    ksr = chip->c_ksr_freq;\n    if (!chip->c_ksr)\n        ksr >>= 2;\n    chip->eg_rate = (rate << 2) + ksr;\n    if (chip->eg_rate & 0x40) {\n        chip->eg_rate = 0x3c | (ksr & 3);\n    }\n    chip->eg_sl = chip->c_sl;\n}\n\nvoid OPLL_Channel(opll_t *chip) {\n    int16_t sign;\n    int16_t ch_out = chip->ch_out;\n    uint8_t ismod = (chip->cycles / 3) & 1;\n    uint8_t mute_m = ismod || ((chip->rm_enable&0x40) && (chip->cycles+15)%18 >= 12);\n    uint8_t mute_r = 1;\n    if (chip->chip_type == opll_type_ds1001) {\n        chip->output_m = ch_out;\n        if (chip->output_m >= 0) {\n            chip->output_m++;\n        }\n        if (mute_m) {\n            chip->output_m = 0;\n        }\n        chip->output_r = 0;\n        return;\n    } else {\n        /* TODO: This might be incorrect */\n        if ((chip->rm_enable & 0x40)) {\n            switch (chip->cycles) {\n            case 16: /* HH */\n            case 17: /* TOM */\n            case 0: /* BD */\n            case 1: /* SD */\n            case 2: /* TC */\n            case 3: /* HH */\n            case 4: /* TOM */\n            case 5: /* BD */\n            case 9: /* TOM */\n            case 10: /* TOM */\n                mute_r = 0;\n                break;\n            }\n        }\n        if (chip->chip_type == opll_type_ym2413b || chip->chip_type == opll_type_ymf281b) {\n            if (mute_m)\n                chip->output_m = 0;\n            else\n                chip->output_m = ch_out;\n            if (mute_r)\n                chip->output_r = 0;\n            else\n                chip->output_r = ch_out;\n        } else {\n            sign = ch_out >> 8;\n            if (ch_out >= 0) {\n                ch_out++;\n                sign++;\n            }\n            if (mute_m)\n                chip->output_m = sign;\n            else\n                chip->output_m = ch_out;\n            if (mute_r)\n                chip->output_r = sign;\n            else\n                chip->output_r = ch_out;\n        }\n    }\n}\n\nvoid OPLL_Operator(opll_t *chip) {\n    uint8_t ismod1, ismod2, ismod3;\n    uint32_t op_mod;\n    uint16_t exp_shift;\n    int16_t output;\n    uint32_t level;\n    uint32_t phase;\n    int16_t routput;\n    if ((chip->rm_enable & 0x80) && (chip->cycles == 15 || chip->cycles == 16)) {\n        ismod1 = 0;\n    } else {\n        ismod1 = ((chip->cycles + 1) / 3) & 1;\n    }\n    if ((chip->rm_enable & 0x40) && (chip->cycles == 13 || chip->cycles == 14)) {\n        ismod2 = 0;\n    } else {\n        ismod2 = ((chip->cycles + 3) / 3) & 1;\n    }\n    if ((chip->rm_enable & 0x40) && (chip->cycles == 16 || chip->cycles == 17)) {\n        ismod3 = 0;\n    } else {\n        ismod3 = (chip->cycles / 3) & 1;\n    }\n\n    op_mod = 0;\n    \n    if (ismod3) {\n        op_mod |= chip->op_mod << 1;\n    }\n\n    if (ismod2 && chip->c_fb) {\n        op_mod |= chip->op_fbsum >> (7 - chip->c_fb);\n    }\n\n    exp_shift = chip->op_exp_s;\n    if (chip->eg_silent || ((chip->op_neg&2) && (ismod1 ? (chip->c_dm&4) : (chip->c_dc&4)))) {\n        exp_shift |= 12;\n    }\n\n    output = chip->op_exp_m>>exp_shift;\n    if (!chip->eg_silent && (chip->op_neg&2)) {\n        output = ~output;\n    }\n\n    level = chip->op_logsin+(chip->eg_out<<4);\n    if (level >= 4096) {\n        level = 4095;\n    }\n\n    chip->op_exp_m = exprom[level & 0xff];\n    chip->op_exp_s = level >> 8;\n\n    phase = (op_mod + chip->pg_out) & 0x3ff;\n    if (phase & 0x100) {\n        phase ^= 0xff;\n    }\n    chip->op_logsin = logsinrom[phase & 0xff];\n    chip->op_neg <<= 1;\n    chip->op_neg |= phase >> 9;\n    chip->op_fbsum = (chip->op_fb1[(chip->cycles + 3) % 9] + chip->op_fb2[(chip->cycles + 3) % 9]) >> 1;\n\n    if (ismod1) {\n        chip->op_fb2[chip->cycles%9] = chip->op_fb1[chip->cycles%9];\n        chip->op_fb1[chip->cycles%9] = output;\n    }\n    chip->op_mod = output&0x1ff;\n\n    if (chip->chip_type == opll_type_ds1001) {\n        routput = 0;\n    } else {\n        switch (chip->cycles) {\n        case 2:\n            routput = chip->ch_out_hh;\n            break;\n        case 3:\n            routput = chip->ch_out_tm;\n            break;\n        case 4:\n            routput = chip->ch_out_bd;\n            break;\n        case 8:\n            routput = chip->ch_out_sd;\n            break;\n        case 9:\n            routput = chip->ch_out_tc;\n            break;\n        default:\n            routput = 0; /* TODO: Not quite true */\n            break;\n        }\n        switch (chip->cycles) {\n        case 15:\n            chip->ch_out_hh = output>>3;\n            break;\n        case 16:\n            chip->ch_out_tm = output>>3;\n            break;\n        case 17:\n            chip->ch_out_bd = output>>3;\n            break;\n        case 0:\n            chip->ch_out_sd = output>>3;\n            break;\n        case 1:\n            chip->ch_out_tc = output>>3;\n            break;\n        default:\n            break;\n        }\n    }\n\n    chip->ch_out = ismod1 ? routput : (output>>3);\n}\n\nvoid OPLL_DoRhythm(opll_t *chip) {\n    uint8_t nbit;\n\n    /* Noise */\n    nbit = (chip->rm_noise ^ (chip->rm_noise >> 14)) & 0x01;\n    nbit |= (chip->rm_noise == 0x00) | ((chip->testmode >> 1) & 0x01);\n    chip->rm_noise = (nbit << 22) | (chip->rm_noise >> 1);\n}\n\nvoid OPLL_DoLFO(opll_t *chip) {\n    uint8_t vib_step;\n    uint8_t am_inc = 0;\n    uint8_t am_bit;\n    \n    /* Update counter */\n    if (chip->cycles == 17) {\n        vib_step = ((chip->lfo_counter & 0x3ff) + 1) >> 10;\n        chip->lfo_am_step = ((chip->lfo_counter & 0x3f) + 1) >> 6;\n        vib_step |= (chip->testmode >> 3) & 0x01;\n        chip->lfo_vib_counter += vib_step;\n        chip->lfo_vib_counter &= 0x07;\n        chip->lfo_counter++;\n    }\n    \n    /* LFO AM */\n    if ((chip->lfo_am_step || (chip->testmode & 0x08)) && chip->cycles < 9) {\n        am_inc = chip->lfo_am_dir | (chip->cycles == 0);\n    }\n\n    if (chip->cycles >= 9) {\n        chip->lfo_am_car = 0;\n    }\n\n    if (chip->cycles == 0) {\n        if (chip->lfo_am_dir && (chip->lfo_am_counter & 0x7f) == 0) {\n            chip->lfo_am_dir = 0;\n        } else if (!chip->lfo_am_dir && (chip->lfo_am_counter & 0x69) == 0x69) {\n            chip->lfo_am_dir = 1;\n        }\n    }\n\n    am_bit = chip->lfo_am_counter & 0x01;\n    am_bit += am_inc + chip->lfo_am_car;\n    chip->lfo_am_car = am_bit >> 1;\n    am_bit &= 0x01;\n    chip->lfo_am_counter = (am_bit << 8) | (chip->lfo_am_counter >> 1);\n\n\n    /* Reset LFO */\n    if (chip->testmode & 0x02) {\n        chip->lfo_vib_counter = 0;\n        chip->lfo_counter = 0;\n        chip->lfo_am_dir = 0;\n        chip->lfo_am_counter &= 0xff;\n    }\n}\n\n\nvoid OPLL_Clock(opll_t *chip, int32_t *buffer) {\n    buffer[0] = chip->output_m;\n    buffer[1] = chip->output_r;\n    if (chip->cycles == 0) {\n        chip->lfo_am_out = (chip->lfo_am_counter >> 3) & 0x0f;\n    }\n    chip->rm_enable >>= 1;\n    OPLL_DoModeWrite(chip);\n    chip->rm_select++;\n    if (chip->rm_select > rm_num_tc) {\n        chip->rm_select = rm_num_tc + 1;\n    }\n    if (chip->cycles == 11 && (chip->rm_enable & 0x80) == 0x80) {\n        chip->rm_select = rm_num_bd0;\n    }\n    OPLL_PreparePatch1(chip);\n\n    OPLL_Channel(chip);\n\n    OPLL_PhaseGenerate(chip);\n\n    OPLL_Operator(chip);\n\n    OPLL_PhaseCalcIncrement(chip);\n\n    OPLL_EnvelopeOutput(chip);\n    OPLL_EnvelopeKSLTL(chip);\n    OPLL_EnvelopeGenerate(chip);\n\n    OPLL_DoLFO(chip);\n    OPLL_DoRhythm(chip);\n    OPLL_PreparePatch2(chip);\n    OPLL_DoRegWrite(chip);\n    OPLL_DoIO(chip);\n    chip->cycles = (chip->cycles + 1) % 18;\n\n}\n\n\nvoid OPLL_Write(opll_t *chip, uint32_t port, uint8_t data) {\n    chip->write_data = data;\n    if (port & 1) {\n        /* Data */\n        chip->write_d |= 1;\n    } else {\n        /* Address */\n        chip->write_a |= 1;\n    }\n}\n\nvoid OPLL_WriteBuffered(opll_t* chip, uint32_t port, uint8_t data)\n{\n    uint64_t time1, time2;\n    int32_t buffer[2];\n    uint64_t skip;\n\n    if (chip->writebuf[chip->writebuf_last].port & 0x04)\n    {\n        OPLL_Write(chip, chip->writebuf[chip->writebuf_last].port & 0x03,\n            chip->writebuf[chip->writebuf_last].data);\n\n        chip->writebuf_cur = (chip->writebuf_last + 1) % OPLL_WRITEBUF_SIZE;\n        skip = chip->writebuf[chip->writebuf_last].time - chip->writebuf_samplecnt;\n        chip->writebuf_samplecnt = chip->writebuf[chip->writebuf_last].time;\n        while (skip--)\n        {\n            OPLL_Clock(chip, buffer);\n        }\n    }\n\n    chip->writebuf[chip->writebuf_last].port = (port & 0x03) | 0x04;\n    chip->writebuf[chip->writebuf_last].data = data;\n    time1 = chip->writebuf_lasttime + OPLL_WRITEBUF_DELAY;\n    time2 = chip->writebuf_samplecnt;\n\n    if (time1 < time2)\n    {\n        time1 = time2;\n    }\n\n    chip->writebuf[chip->writebuf_last].time = time1;\n    chip->writebuf_lasttime = time1;\n    chip->writebuf_last = (chip->writebuf_last + 1) % OPLL_WRITEBUF_SIZE;\n}\n\n#define OUTPUT_FACTOR 8\n\nvoid OPLL_GenerateResampled(opll_t *chip, int32_t *buf)\n{\n    uint32_t i;\n    int32_t buffer[2];\n    uint32_t mute_m, mute_r;\n    int32_t sum;\n\n    while (chip->samplecnt >= chip->rateratio)\n    {\n        chip->oldsamples[0] = chip->samples[0];\n        chip->oldsamples[1] = chip->samples[1];\n        chip->samples[0] = chip->samples[1] = 0;\n        for (i = 0; i < 18; i++)\n        {\n            switch (chip->cycles)\n            {\n            case 1:\n                mute_m = chip->mute[6];\n                mute_r = chip->mute[9];\n                break;\n            case 2:\n                mute_m = chip->mute[7];\n                mute_r = chip->mute[10];\n                break;\n            case 3:\n                mute_m = chip->mute[8];\n                mute_r = chip->mute[12];\n                break;\n            case 4:\n                mute_m = 0;\n                mute_r = chip->mute[13];\n                break;\n            case 5:\n                mute_m = 0;\n                mute_r = chip->mute[11];\n                break;\n            case 6:\n                mute_m = 0;\n                mute_r = chip->mute[9];\n                break;\n            case 7:\n                mute_m = chip->mute[0];\n                mute_r = 0;\n                break;\n            case 8:\n                mute_m = chip->mute[1];\n                mute_r = 0;\n                break;\n            case 9:\n                mute_m = chip->mute[2];\n                mute_r = 0;\n                break;\n            case 10:\n                mute_m = 0;\n                mute_r = chip->mute[10];\n                break;\n            case 11:\n                mute_m = 0;\n                mute_r = chip->mute[12];\n                break;\n            case 12:\n                mute_m = 0;\n                mute_r = 0;\n                break;\n            case 13:\n                mute_m = chip->mute[3];\n                mute_r = 0;\n                break;\n            case 14:\n                mute_m = chip->mute[4];\n                mute_r = 0;\n                break;\n            case 15:\n                mute_m = chip->mute[5];\n                mute_r = 0;\n                break;\n            case 16:\n                mute_m = 0;\n                mute_r = 0;\n                break;\n            case 17:\n                mute_m = 0;\n                mute_r = chip->mute[13];\n                break;\n            case 0:\n                mute_m = 0;\n                mute_r = chip->mute[11];\n                break;\n            default:\n                mute_m = 0;\n                mute_r = 0;\n                break;\n            }\n            OPLL_Clock(chip, buffer);\n            if (!mute_m)\n            {\n                chip->samples[0] += buffer[0];\n            }\n            if (!mute_r)\n            {\n                chip->samples[1] += buffer[1];\n            }\n\n            while (chip->writebuf[chip->writebuf_cur].time <= chip->writebuf_samplecnt)\n            {\n                if (!(chip->writebuf[chip->writebuf_cur].port & 0x04))\n                {\n                    break;\n                }\n                chip->writebuf[chip->writebuf_cur].port &= 0x03;\n                OPLL_Write(chip, chip->writebuf[chip->writebuf_cur].port,\n                    chip->writebuf[chip->writebuf_cur].data);\n                chip->writebuf_cur = (chip->writebuf_cur + 1) % OPLL_WRITEBUF_SIZE;\n            }\n            chip->writebuf_samplecnt++;\n        }\n        chip->samples[0] *= OUTPUT_FACTOR;\n        chip->samples[1] *= OUTPUT_FACTOR;\n        sum = chip->samples[0] + chip->samples[1];\n        chip->samples[1] = chip->samples[0] = sum;\n        chip->samplecnt -= chip->rateratio;\n    }\n    buf[0] = (int32_t)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt)\n        + chip->samples[0] * chip->samplecnt) / chip->rateratio);\n    buf[1] = (int32_t)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt)\n        + chip->samples[1] * chip->samplecnt) / chip->rateratio);\n    chip->samplecnt += 1 << RSM_FRAC;\n}\n\nvoid OPLL_GenerateStream(opll_t* chip, int32_t** sndptr, uint32_t numsamples)\n{\n    uint32_t i;\n    int32_t* smpl, * smpr;\n    int32_t buffer[2];\n    smpl = sndptr[0];\n    smpr = sndptr[1];\n\n    for (i = 0; i < numsamples; i++)\n    {\n        OPLL_GenerateResampled(chip, buffer);\n        *smpl++ = buffer[0];\n        *smpr++ = buffer[1];\n    }\n}\n\nvoid OPLL_SetMute(opll_t* chip, uint32_t mute)\n{\n    uint32_t i;\n    for (i = 0; i < 14; i++)\n    {\n        chip->mute[i] = (mute >> i) & 0x01;\n    }\n}\n"
  },
  {
    "path": "VGMPlay/chips/opll.h",
    "content": "/*\n * Copyright (C) 2019 Nuke.YKT\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n *\n *  Yamaha YM2413 emulator\n *  Thanks:\n *      siliconpr0n.org(digshadow, John McMaster):\n *          VRC VII decap and die shot.\n *\n *  version: 1.0\n */\n\n#ifndef OPLL_H\n#define OPLL_H\n\n#include \"emutypes.h\"\n\n#define RSM_FRAC 10\n#define OPLL_WRITEBUF_SIZE 2048\n#define OPLL_WRITEBUF_DELAY 20\n\nenum {\n    opll_type_ym2413 = 0x00,    /* Yamaha YM2413  */\n    opll_type_ds1001,           /* Konami VRC VII */\n    opll_type_ym2413b,          /* Yamaha YM2413B */\n    opll_type_ymf281,           /* Yamaha YMF281  */\n    opll_type_ymf281b,          /* Yamaha YMF281B */\n    opll_type_ym2420,           /* Yamaha YM2420  */\n    opll_type_ym2423,           /* Yamaha YM2423  */\n};\n\nenum {\n    opll_patch_1 = 0x00,\n    opll_patch_2,\n    opll_patch_3,\n    opll_patch_4,\n    opll_patch_5,\n    opll_patch_6,\n    opll_patch_7,\n    opll_patch_8,\n    opll_patch_9,\n    opll_patch_10,\n    opll_patch_11,\n    opll_patch_12,\n    opll_patch_13,\n    opll_patch_14,\n    opll_patch_15,\n    opll_patch_drum_0,\n    opll_patch_drum_1,\n    opll_patch_drum_2,\n    opll_patch_drum_3,\n    opll_patch_drum_4,\n    opll_patch_drum_5,\n    opll_patch_max\n};\n\ntypedef struct _opll_writebuf {\n    uint64_t time;\n    uint8_t port;\n    uint8_t data;\n} opll_writebuf;\n\ntypedef struct {\n    uint8_t tl;\n    uint8_t dc;\n    uint8_t dm;\n    uint8_t fb;\n    uint8_t am[2];\n    uint8_t vib[2];\n    uint8_t et[2];\n    uint8_t ksr[2];\n    uint8_t multi[2];\n    uint8_t ksl[2];\n    uint8_t ar[2];\n    uint8_t dr[2];\n    uint8_t sl[2];\n    uint8_t rr[2];\n} opll_patch_t;\n\ntypedef struct {\n    uint32_t chip_type;\n    uint32_t cycles;\n    uint32_t slot;\n    const opll_patch_t *patchrom;\n    /* IO */\n    uint8_t write_data;\n    uint8_t write_a;\n    uint8_t write_d;\n    uint8_t write_a_en;\n    uint8_t write_d_en;\n    uint8_t write_fm_address;\n    uint8_t write_fm_data;\n    uint8_t write_mode_address;\n    uint8_t address;\n    uint8_t data;\n    /* Envelope generator */\n    uint8_t eg_counter_state;\n    uint8_t eg_counter_state_prev;\n    uint32_t eg_timer;\n    uint8_t eg_timer_low_lock;\n    uint8_t eg_timer_carry;\n    uint8_t eg_timer_shift;\n    uint8_t eg_timer_shift_lock;\n    uint8_t eg_timer_shift_stop;\n    uint8_t eg_state[18];\n    uint8_t eg_level[18];\n    uint8_t eg_kon;\n    uint32_t eg_dokon;\n    uint8_t eg_off;\n    uint8_t eg_rate;\n    uint8_t eg_maxrate;\n    uint8_t eg_zerorate;\n    uint8_t eg_inc_lo;\n    uint8_t eg_inc_hi;\n    uint8_t eg_rate_hi;\n    uint16_t eg_sl;\n    uint16_t eg_ksltl;\n    uint8_t eg_out;\n    uint8_t eg_silent;\n    /* Phase generator */\n    uint16_t pg_fnum;\n    uint8_t pg_block;\n    uint16_t pg_out;\n    uint32_t pg_inc;\n    uint32_t pg_phase[18];\n    uint32_t pg_phase_next;\n    /* Operator */\n    int16_t op_fb1[9];\n    int16_t op_fb2[9];\n    int16_t op_fbsum;\n    int16_t op_mod;\n    uint8_t op_neg;\n    uint16_t op_logsin;\n    uint16_t op_exp_m;\n    uint16_t op_exp_s;\n    /* Channel */\n    int16_t ch_out;\n    int16_t ch_out_hh;\n    int16_t ch_out_tm;\n    int16_t ch_out_bd;\n    int16_t ch_out_sd;\n    int16_t ch_out_tc;\n    /* LFO */\n    uint16_t lfo_counter;\n    uint8_t lfo_vib_counter;\n    uint16_t lfo_am_counter;\n    uint8_t lfo_am_step;\n    uint8_t lfo_am_dir;\n    uint8_t lfo_am_car;\n    uint8_t lfo_am_out;\n    /* Register set */\n    uint16_t fnum[9];\n    uint8_t block[9];\n    uint8_t kon[9];\n    uint8_t son[9];\n    uint8_t vol[9];\n    uint8_t inst[9];\n    uint8_t rhythm;\n    uint8_t testmode;\n    opll_patch_t patch;\n    uint8_t c_instr;\n    uint8_t c_op;\n    uint8_t c_tl;\n    uint8_t c_dc;\n    uint8_t c_dm;\n    uint8_t c_fb;\n    uint8_t c_am;\n    uint8_t c_vib;\n    uint8_t c_et;\n    uint8_t c_ksr;\n    uint8_t c_ksr_freq;\n    uint8_t c_ksl_freq;\n    uint8_t c_ksl_block;\n    uint8_t c_multi;\n    uint8_t c_ksl;\n    uint8_t c_adrr[3];\n    uint8_t c_sl;\n    uint16_t c_fnum;\n    uint16_t c_block;\n    /* Rhythm mode */\n    int8_t rm_enable;\n    uint32_t rm_noise;\n    uint32_t rm_select;\n    uint8_t rm_hh_bit2;\n    uint8_t rm_hh_bit3;\n    uint8_t rm_hh_bit7;\n    uint8_t rm_hh_bit8;\n    uint8_t rm_tc_bit3;\n    uint8_t rm_tc_bit5;\n\n    int16_t output_m;\n    int16_t output_r;\n\n    uint32_t mute[14];\n    int32_t rateratio;\n    int32_t samplecnt;\n    int32_t oldsamples[2];\n    int32_t samples[2];\n\n    uint64_t writebuf_samplecnt;\n    uint32_t writebuf_cur;\n    uint32_t writebuf_last;\n    uint64_t writebuf_lasttime;\n    opll_writebuf writebuf[OPLL_WRITEBUF_SIZE];\n\n} opll_t;\n\nvoid OPLL_Reset(opll_t *chip, uint32_t chip_type, uint32_t rate, uint32_t clock);\nvoid OPLL_Clock(opll_t *chip, int32_t *buffer);\nvoid OPLL_Write(opll_t *chip, uint32_t port, uint8_t data);\n\nvoid OPLL_WriteBuffered(opll_t*chip, uint32_t port, uint8_t data);\nvoid OPLL_GenerateStream(opll_t*chip, int32_t **sndptr, uint32_t numsamples);\nvoid OPLL_SetMute(opll_t*chip, uint32_t mute);\n#endif"
  },
  {
    "path": "VGMPlay/chips/opm.c",
    "content": "/* Nuked OPM\n * Copyright (C) 2020 Nuke.YKT\n *\n * This file is part of Nuked OPM.\n *\n * Nuked OPM is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as\n * published by the Free Software Foundation, either version 2.1\n * of the License, or (at your option) any later version.\n *\n * Nuked OPM is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with Nuked OPM. If not, see <https://www.gnu.org/licenses/>.\n *\n *  Nuked OPM emulator.\n *  Thanks:\n *      siliconpr0n.org(digshadow, John McMaster):\n *          YM2151 and other FM chip decaps and die shots.\n *\n * version: 0.9 beta\n */\n#include <string.h>\n#include \"opm.h\"\n\nenum {\n    eg_num_attack = 0,\n    eg_num_decay = 1,\n    eg_num_sustain = 2,\n    eg_num_release = 3\n};\n\n/* logsin table */\nstatic const uint16_t logsinrom[256] = {\n    0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471,\n    0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365,\n    0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd,\n    0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261,\n    0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f,\n    0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd,\n    0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195,\n    0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166,\n    0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c,\n    0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118,\n    0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8,\n    0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db,\n    0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1,\n    0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9,\n    0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094,\n    0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081,\n    0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070,\n    0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060,\n    0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052,\n    0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045,\n    0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039,\n    0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f,\n    0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026,\n    0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e,\n    0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017,\n    0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011,\n    0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c,\n    0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007,\n    0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004,\n    0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002,\n    0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001,\n    0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000\n};\n\n/* exp table */\nstatic const uint16_t exprom[256] = {\n    0x7fa, 0x7f5, 0x7ef, 0x7ea, 0x7e4, 0x7df, 0x7da, 0x7d4,\n    0x7cf, 0x7c9, 0x7c4, 0x7bf, 0x7b9, 0x7b4, 0x7ae, 0x7a9,\n    0x7a4, 0x79f, 0x799, 0x794, 0x78f, 0x78a, 0x784, 0x77f,\n    0x77a, 0x775, 0x770, 0x76a, 0x765, 0x760, 0x75b, 0x756,\n    0x751, 0x74c, 0x747, 0x742, 0x73d, 0x738, 0x733, 0x72e,\n    0x729, 0x724, 0x71f, 0x71a, 0x715, 0x710, 0x70b, 0x706,\n    0x702, 0x6fd, 0x6f8, 0x6f3, 0x6ee, 0x6e9, 0x6e5, 0x6e0,\n    0x6db, 0x6d6, 0x6d2, 0x6cd, 0x6c8, 0x6c4, 0x6bf, 0x6ba,\n    0x6b5, 0x6b1, 0x6ac, 0x6a8, 0x6a3, 0x69e, 0x69a, 0x695,\n    0x691, 0x68c, 0x688, 0x683, 0x67f, 0x67a, 0x676, 0x671,\n    0x66d, 0x668, 0x664, 0x65f, 0x65b, 0x657, 0x652, 0x64e,\n    0x649, 0x645, 0x641, 0x63c, 0x638, 0x634, 0x630, 0x62b,\n    0x627, 0x623, 0x61e, 0x61a, 0x616, 0x612, 0x60e, 0x609,\n    0x605, 0x601, 0x5fd, 0x5f9, 0x5f5, 0x5f0, 0x5ec, 0x5e8,\n    0x5e4, 0x5e0, 0x5dc, 0x5d8, 0x5d4, 0x5d0, 0x5cc, 0x5c8,\n    0x5c4, 0x5c0, 0x5bc, 0x5b8, 0x5b4, 0x5b0, 0x5ac, 0x5a8,\n    0x5a4, 0x5a0, 0x59c, 0x599, 0x595, 0x591, 0x58d, 0x589,\n    0x585, 0x581, 0x57e, 0x57a, 0x576, 0x572, 0x56f, 0x56b,\n    0x567, 0x563, 0x560, 0x55c, 0x558, 0x554, 0x551, 0x54d,\n    0x549, 0x546, 0x542, 0x53e, 0x53b, 0x537, 0x534, 0x530,\n    0x52c, 0x529, 0x525, 0x522, 0x51e, 0x51b, 0x517, 0x514,\n    0x510, 0x50c, 0x509, 0x506, 0x502, 0x4ff, 0x4fb, 0x4f8,\n    0x4f4, 0x4f1, 0x4ed, 0x4ea, 0x4e7, 0x4e3, 0x4e0, 0x4dc,\n    0x4d9, 0x4d6, 0x4d2, 0x4cf, 0x4cc, 0x4c8, 0x4c5, 0x4c2,\n    0x4be, 0x4bb, 0x4b8, 0x4b5, 0x4b1, 0x4ae, 0x4ab, 0x4a8,\n    0x4a4, 0x4a1, 0x49e, 0x49b, 0x498, 0x494, 0x491, 0x48e,\n    0x48b, 0x488, 0x485, 0x482, 0x47e, 0x47b, 0x478, 0x475,\n    0x472, 0x46f, 0x46c, 0x469, 0x466, 0x463, 0x460, 0x45d,\n    0x45a, 0x457, 0x454, 0x451, 0x44e, 0x44b, 0x448, 0x445,\n    0x442, 0x43f, 0x43c, 0x439, 0x436, 0x433, 0x430, 0x42d,\n    0x42a, 0x428, 0x425, 0x422, 0x41f, 0x41c, 0x419, 0x416,\n    0x414, 0x411, 0x40e, 0x40b, 0x408, 0x406, 0x403, 0x400\n};\n\n/* Envelope generator */\nstatic const uint32_t eg_stephi[4][4] = {\n    { 0, 0, 0, 0 },\n    { 1, 0, 0, 0 },\n    { 1, 0, 1, 0 },\n    { 1, 1, 1, 0 }\n};\n\n/* Phase generator */\nstatic const uint32_t pg_detune[8] = { 16, 17, 19, 20, 22, 24, 27, 29 };\n\ntypedef struct {\n    int32_t basefreq;\n    int32_t approxtype;\n    int32_t slope;\n} freqtable_t;\n\nstatic const freqtable_t pg_freqtable[64] = {\n    1299, 1, 19,\n    1318, 1, 19,\n    1337, 1, 19,\n    1356, 1, 20,\n    1376, 1, 20,\n    1396, 1, 20,\n    1416, 1, 21,\n    1437, 1, 20,\n    1458, 1, 21,\n    1479, 1, 21,\n    1501, 1, 22,\n    1523, 1, 22,\n    0,    0, 16,\n    0,    0, 16,\n    0,    0, 16,\n    0,    0, 16,\n    1545, 1, 22,\n    1567, 1, 22,\n    1590, 1, 23,\n    1613, 1, 23,\n    1637, 1, 23,\n    1660, 1, 24,\n    1685, 1, 24,\n    1709, 1, 24,\n    1734, 1, 25,\n    1759, 1, 25,\n    1785, 1, 26,\n    1811, 1, 26,\n    0,    0, 16,\n    0,    0, 16,\n    0,    0, 16,\n    0,    0, 16,\n    1837, 1, 26,\n    1864, 1, 27,\n    1891, 1, 27,\n    1918, 1, 28,\n    1946, 1, 28,\n    1975, 1, 28,\n    2003, 1, 29,\n    2032, 1, 30,\n    2062, 1, 30,\n    2092, 1, 30,\n    2122, 1, 31,\n    2153, 1, 31,\n    0,    0, 16,\n    0,    0, 16,\n    0,    0, 16,\n    0,    0, 16,\n    2185, 1, 31,\n    2216, 0, 31,\n    2249, 0, 31,\n    2281, 0, 31,\n    2315, 0, 31,\n    2348, 0, 31,\n    2382, 0, 30,\n    2417, 0, 30,\n    2452, 0, 30,\n    2488, 0, 30,\n    2524, 0, 30,\n    2561, 0, 30,\n    0,    0, 16,\n    0,    0, 16,\n    0,    0, 16,\n    0,    0, 16\n};\n\n\n/* FM algorithm */\nstatic const uint32_t fm_algorithm[4][6][8] = {\n    {\n        { 1, 1, 1, 1, 1, 1, 1, 1 }, /* M1_0          */\n        { 1, 1, 1, 1, 1, 1, 1, 1 }, /* M1_1          */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* C1            */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */\n        { 0, 0, 0, 0, 0, 0, 0, 1 }  /* Out           */\n    },\n    {\n        { 0, 1, 0, 0, 0, 1, 0, 0 }, /* M1_0          */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* M1_1          */\n        { 1, 1, 1, 0, 0, 0, 0, 0 }, /* C1            */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */\n        { 0, 0, 0, 0, 0, 1, 1, 1 }  /* Out           */\n    },\n    {\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* M1_0          */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* M1_1          */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* C1            */\n        { 1, 0, 0, 1, 1, 1, 1, 0 }, /* Last operator */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */\n        { 0, 0, 0, 0, 1, 1, 1, 1 }  /* Out           */\n    },\n    {\n        { 0, 0, 1, 0, 0, 1, 0, 0 }, /* M1_0          */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* M1_1          */\n        { 0, 0, 0, 1, 0, 0, 0, 0 }, /* C1            */\n        { 1, 1, 0, 1, 1, 0, 0, 0 }, /* Last operator */\n        { 0, 0, 1, 0, 0, 0, 0, 0 }, /* Last operator */\n        { 1, 1, 1, 1, 1, 1, 1, 1 }  /* Out           */\n    }\n};\n\nstatic uint16_t lfo_counter2_table[] = {\n    0x0000, 0x4000, 0x6000, 0x7000,\n    0x7800, 0x7c00, 0x7e00, 0x7f00,\n    0x7f80, 0x7fc0, 0x7fe0, 0x7ff0,\n    0x7ff8, 0x7ffc, 0x7ffe, 0x7fff\n};\n\nstatic int32_t OPM_KCToFNum(int32_t kcode)\n{\n    int32_t kcode_h = (kcode >> 4) & 63;\n    int32_t kcode_l = kcode & 15;\n    int32_t i, slope, sum = 0;\n    if (pg_freqtable[kcode_h].approxtype)\n    {\n        for (i = 0; i < 4; i++)\n        {\n            if (kcode_l & (1 << i))\n            {\n                sum += (pg_freqtable[kcode_h].slope >> (3 - i));\n            }\n        }\n    }\n    else\n    {\n        slope = pg_freqtable[kcode_h].slope | 1;\n        if (kcode_l & 1)\n        {\n            sum += (slope >> 3) + 2;\n        }\n        if (kcode_l & 2)\n        {\n            sum += 8;\n        }\n        if (kcode_l & 4)\n        {\n            sum += slope >> 1;\n        }\n        if (kcode_l & 8)\n        {\n            sum += slope;\n            sum++;\n        }\n        if ((kcode_l & 12) == 12 && (pg_freqtable[kcode_h].slope & 1) == 0)\n        {\n            sum += 4;\n        }\n    }\n    return pg_freqtable[kcode_h].basefreq + (sum >> 1);\n}\n\nstatic int32_t OPM_LFOApplyPMS(int32_t lfo, int32_t pms)\n{\n    int32_t t, out;\n    int32_t top = (lfo >> 4) & 7;\n    if (pms != 7)\n    {\n        top >>= 1;\n    }\n    t = (top & 6) == 6 || ((top & 3) == 3 && pms >= 6);\n\n    out = top + ((top >> 2) & 1) + t;\n    out = out * 2 + ((lfo >> 4) & 1);\n\n    if (pms == 7)\n    {\n        out >>= 1;\n    }\n    out &= 15;\n    out = (lfo & 15) + out * 16;\n    switch (pms)\n    {\n    case 0:\n    default:\n        out = 0;\n        break;\n    case 1:\n        out = (out >> 5) & 3;\n        break;\n    case 2:\n        out = (out >> 4) & 7;\n        break;\n    case 3:\n        out = (out >> 3) & 15;\n        break;\n    case 4:\n        out = (out >> 2) & 31;\n        break;\n    case 5:\n        out = (out >> 1) & 63;\n        break;\n    case 6:\n        out = (out & 255) << 1;\n        break;\n    case 7:\n        out = (out & 255) << 2;\n        break;\n    }\n    return out;\n}\n\nstatic int32_t OPM_CalcKCode(int32_t kcf, int32_t lfo, int32_t lfo_sign, int32_t dt)\n{\n    int32_t t2, t3, b0, b1, b2, b3, w2, w3, w4, w6;\n    int32_t overflow1 = 0;\n    int32_t overflow2 = 0;\n    int32_t negoverflow = 0;\n    int32_t sum, cr;\n    if (!lfo_sign)\n    {\n        lfo = ~lfo;\n    }\n    sum = (kcf & 8191) + (lfo&8191) + (!lfo_sign);\n    cr = ((kcf & 255) + (lfo & 255) + (!lfo_sign)) >> 8;\n    if (sum & (1 << 13))\n    {\n        overflow1 = 1;\n    }\n    sum &= 8191;\n    if (lfo_sign && ((((sum >> 6) & 3) == 3) || cr))\n    {\n        sum += 64;\n    }\n    if (!lfo_sign && !cr)\n    {\n        sum += (-64)&8191;\n        negoverflow = 1;\n    }\n    if (sum & (1 << 13))\n    {\n        overflow2 = 1;\n    }\n    sum &= 8191;\n    if ((!lfo_sign && !overflow1) || (negoverflow && !overflow2))\n    {\n        sum = 0;\n    }\n    if (lfo_sign && (overflow1 || overflow2))\n    {\n        sum = 8127;\n    }\n        \n    t2 = sum & 63;\n    if (dt == 2)\n        t2 += 20;\n    if (dt == 2 || dt == 3)\n        t2 += 32;\n\n    b0 = (t2 >> 6) & 1;\n    b1 = dt == 2;\n    b2 = ((sum >> 6) & 1);\n    b3 = ((sum >> 7) & 1);\n\n\n    w2 = (b0 && b1 && b2);\n    w3 = (b0 && b3);\n    w4 = !w2 && !w3;\n    w6 = (b0 && !w2 && !w3) || (b3 && !b0 && b1);\n\n    t2 &= 63;\n\n    t3 = (sum >> 6) + w6 + b1 + (w2 || w3) * 2 + (dt == 3) * 4 + (dt != 0) * 8;\n    if (t3 & 128)\n    {\n        t2 = 63;\n        t3 = 126;\n    }\n    sum = t3 * 64 + t2;\n    return sum;\n}\n\nstatic void OPM_PhaseCalcFNumBlock(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 7) & 31;\n    uint32_t channel = slot & 7;\n    uint32_t kcf = (chip->ch_kc[channel] << 6) + chip->ch_kf[channel];\n    uint32_t lfo = chip->lfo_pmd ? chip->lfo_pm_lock : 0;\n    uint32_t pms = chip->ch_pms[channel];\n    uint32_t dt = chip->sl_dt2[slot];\n    int32_t lfo_pm = OPM_LFOApplyPMS(lfo & 127, pms);\n    uint32_t kcode = OPM_CalcKCode(kcf, lfo_pm, (lfo & 0x80) != 0 && pms != 0 ? 0 : 1, dt);\n    uint32_t fnum = OPM_KCToFNum(kcode);\n    uint32_t kcode_h = kcode >> 8;\n    chip->pg_fnum[slot] = fnum;\n    chip->pg_kcode[slot] = kcode_h;\n}\n\nstatic void OPM_PhaseCalcIncrement(opm_t *chip)\n{\n    uint32_t slot = chip->cycles;\n    uint32_t channel = slot & 7;\n    uint32_t dt = chip->sl_dt1[slot];\n    uint32_t dt_l = dt & 3;\n    uint32_t detune = 0;\n    uint32_t multi = chip->sl_mul[slot];\n    uint32_t kcode = chip->pg_kcode[slot];\n    uint32_t fnum = chip->pg_fnum[slot];\n    uint32_t block = kcode >> 2;\n    uint32_t basefreq = (fnum << block) >> 2;\n    uint32_t note, sum, sum_h, sum_l, inc;\n    /* Apply detune */\n    if (dt_l)\n    {\n        if (kcode > 0x1c)\n        {\n            kcode = 0x1c;\n        }\n        block = kcode >> 2;\n        note = kcode & 0x03;\n        sum = block + 9 + ((dt_l == 3) | (dt_l & 0x02));\n        sum_h = sum >> 1;\n        sum_l = sum & 0x01;\n        detune = pg_detune[(sum_l << 2) | note] >> (9 - sum_h);\n    }\n    if (dt & 0x04)\n    {\n        basefreq -= detune;\n    }\n    else\n    {\n        basefreq += detune;\n    }\n    basefreq &= 0x1ffff;\n    if (multi)\n    {\n        inc = basefreq * multi;\n    }\n    else\n    {\n        inc = basefreq >> 1;\n    }\n    inc &= 0xfffff;\n    chip->pg_inc[slot] = inc;\n}\n\nstatic void OPM_PhaseGenerate(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 27) & 31;\n    chip->pg_reset_latch[slot] = chip->pg_reset[slot];\n    slot = (chip->cycles + 25) & 31;\n    /* Mask increment */\n    if (chip->pg_reset_latch[slot])\n    {\n        chip->pg_inc[slot] = 0;\n    }\n    /* Phase step */\n    slot = (chip->cycles + 24) & 31;\n    if (chip->pg_reset_latch[slot] || chip->mode_test[3])\n    {\n        chip->pg_phase[slot] = 0;\n    }\n    chip->pg_phase[slot] += chip->pg_inc[slot];\n    chip->pg_phase[slot] &= 0xfffff;\n}\n\nstatic void OPM_PhaseDebug(opm_t *chip)\n{\n    chip->pg_serial >>= 1;\n    if (chip->cycles == 5)\n    {\n        chip->pg_serial |= (chip->pg_phase[29] & 0x3ff);\n    }\n}\n\nstatic void OPM_KeyOn1(opm_t *chip)\n{\n    uint32_t cycles = (chip->cycles + 1) & 31;\n    chip->kon_chanmatch = 0;\n    if (chip->mode_kon_channel + 24 == cycles)\n    {\n        chip->kon_chanmatch = 1;\n    }\n}\n\nstatic void OPM_KeyOn2(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 8) & 31;\n    if (chip->kon_chanmatch)\n    {\n        chip->mode_kon[(slot + 0) & 31] = chip->mode_kon_operator[0];\n        chip->mode_kon[(slot + 8) & 31] = chip->mode_kon_operator[2];\n        chip->mode_kon[(slot + 16) & 31] = chip->mode_kon_operator[1];\n        chip->mode_kon[(slot + 24) & 31] = chip->mode_kon_operator[3];\n    }\n}\n\nstatic void OPM_EnvelopePhase1(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 2) & 31;\n    uint32_t kon = chip->mode_kon[slot] | chip->kon_csm;\n    uint32_t konevent = !chip->kon[slot] && kon;\n    if (konevent)\n    {\n        chip->eg_state[slot] = eg_num_attack;\n    }\n\n    chip->kon2[slot] = chip->kon[slot];\n    chip->kon[slot] = kon;\n}\n\nstatic void OPM_EnvelopePhase2(opm_t *chip)\n{\n    uint32_t slot = chip->cycles;\n    uint32_t chan = slot & 7;\n    uint8_t rate = 0, ksv, zr, ams;\n    switch (chip->eg_state[slot])\n    {\n    case eg_num_attack:\n        rate = chip->sl_ar[slot];\n        break;\n    case eg_num_decay:\n        rate = chip->sl_d1r[slot];\n        break;\n    case eg_num_sustain:\n        rate = chip->sl_d2r[slot];\n        break;\n    case eg_num_release:\n        rate = chip->sl_rr[slot] * 2 + 1;\n        break;\n    default:\n        break;\n    }\n    if (chip->ic)\n    {\n        rate = 31;\n    }\n    \n    zr = rate == 0;\n\n    ksv = chip->pg_kcode[slot] >> (chip->sl_ks[slot] ^ 3);\n    if (chip->sl_ks[slot] == 0 && zr)\n    {\n        ksv &= ~3;\n    }\n    rate = rate * 2 + ksv;\n    if (rate & 64)\n    {\n        rate = 63;\n    }\n\n    chip->eg_tl[2] = chip->eg_tl[1];\n    chip->eg_tl[1] = chip->eg_tl[0];\n    chip->eg_tl[0] = chip->sl_tl[slot];\n    chip->eg_sl[1] = chip->eg_sl[0];\n    chip->eg_sl[0] = chip->sl_d1l[slot];\n    if (chip->sl_d1l[slot] == 15)\n    {\n        chip->eg_sl[0] = 31;\n    }\n    chip->eg_zr[1] = chip->eg_zr[0];\n    chip->eg_zr[0] = zr;\n    chip->eg_rate[1] = chip->eg_rate[0];\n    chip->eg_rate[0] = rate;\n    chip->eg_ratemax[1] = chip->eg_ratemax[0];\n    chip->eg_ratemax[0] = (rate >> 1) == 31;\n    ams = chip->sl_am_e[slot] ? chip->ch_ams[chan] : 0;\n    switch (ams)\n    {\n    default:\n    case 0:\n        chip->eg_am = 0;\n        break;\n    case 1:\n        chip->eg_am = chip->lfo_am_lock << 0;\n        break;\n    case 2:\n        chip->eg_am = chip->lfo_am_lock << 1;\n        break;\n    case 3:\n        chip->eg_am = chip->lfo_am_lock << 2;\n        break;\n    }\n}\n\nstatic void OPM_EnvelopePhase3(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 31) & 31;\n    chip->eg_shift = (chip->eg_timershift_lock + (chip->eg_rate[0] >> 2)) & 15;\n    chip->eg_inchi = eg_stephi[chip->eg_rate[0] & 3][chip->eg_timer_lock & 3];\n\n    chip->eg_outtemp[1] = chip->eg_outtemp[0];\n    chip->eg_outtemp[0] = chip->eg_level[slot] + chip->eg_am;\n    if (chip->eg_outtemp[0] & 1024)\n    {\n        chip->eg_outtemp[0] = 1023;\n    }\n}\n\nstatic void OPM_EnvelopePhase4(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 30) & 31;\n    uint8_t inc = 0;\n    uint8_t kon, eg_off, eg_zero, slreach;\n    if (chip->eg_clock & 2)\n    {\n        if (chip->eg_rate[1] >= 48)\n        {\n            inc = chip->eg_inchi + (chip->eg_rate[1] >> 2) - 11;\n            if (inc > 4)\n            {\n                inc = 4;\n            }\n        }\n        else if (!chip->eg_zr[1])\n        {\n            switch (chip->eg_shift)\n            {\n            case 12:\n                inc = chip->eg_rate[1] != 0;\n                break;\n            case 13:\n                inc = (chip->eg_rate[1] >> 1) & 1;\n                break;\n            case 14:\n                inc = chip->eg_rate[1] & 1;\n                break;\n            }\n        }\n    }\n    chip->eg_inc = inc;\n\n    kon = chip->kon[slot] && !chip->kon2[slot];\n    chip->pg_reset[slot] = kon;\n    chip->eg_instantattack = chip->eg_ratemax[1] && (kon || !chip->eg_ratemax[1]);\n\n    eg_off = (chip->eg_level[slot] & 0x3f0) == 0x3f0;\n    slreach = (chip->eg_level[slot] >> 5) == chip->eg_sl[1];\n    eg_zero = chip->eg_level[slot] == 0;\n\n    chip->eg_mute = eg_off && chip->eg_state[slot] != eg_num_attack && !kon;\n    chip->eg_inclinear = 0;\n    if (!kon && !eg_off)\n    {\n        switch (chip->eg_state[slot])\n        {\n        case eg_num_decay:\n            if (!slreach)\n                chip->eg_inclinear = 1;\n            break;\n        case eg_num_sustain:\n        case eg_num_release:\n            chip->eg_inclinear = 1;\n            break;\n        }\n    }\n    chip->eg_incattack = chip->eg_state[slot] == eg_num_attack && !chip->eg_ratemax[1] && chip->kon[slot] && !eg_zero;\n\n\n    // Update state\n    if (kon)\n    {\n        chip->eg_state[slot] = eg_num_attack;\n    }\n    else if (!chip->kon[slot])\n    {\n        chip->eg_state[slot] = eg_num_release;\n    }\n    else\n    {\n        switch (chip->eg_state[slot])\n        {\n        case eg_num_attack:\n            if (eg_zero)\n            {\n                chip->eg_state[slot] = eg_num_decay;\n            }\n            break;\n        case eg_num_decay:\n            if (eg_off)\n            {\n                chip->eg_state[slot] = eg_num_release;\n            }\n            else if (slreach)\n            {\n                chip->eg_state[slot] = eg_num_sustain;\n            }\n            break;\n        case eg_num_sustain:\n            if (eg_off)\n            {\n                chip->eg_state[slot] = eg_num_release;\n            }\n            break;\n        case eg_num_release:\n            break;\n        }\n    }\n\n    if (chip->ic)\n    {\n        chip->eg_state[slot] = eg_num_release;\n    }\n}\n\nstatic void OPM_EnvelopePhase5(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 29) & 31;\n    uint32_t level = chip->eg_level[slot];\n    uint32_t step = 0;\n    if (chip->eg_instantattack)\n    {\n        level = 0;\n    }\n    if (chip->eg_mute || chip->ic)\n    {\n        level = 0x3ff;\n    }\n    if (chip->eg_inc)\n    {\n        if (chip->eg_inclinear)\n        {\n            step |= 1 << (chip->eg_inc - 1);\n        }\n        if (chip->eg_incattack)\n        {\n            step |= ((~(int32_t)chip->eg_level[slot]) << chip->eg_inc) >> 5;\n        }\n    }\n    level += step;\n    chip->eg_level[slot] = (uint16_t)level;\n\n    chip->eg_out[0] = chip->eg_outtemp[1] + (chip->eg_tl[2] << 3);\n    if (chip->eg_out[0] & 1024)\n    {\n        chip->eg_out[0] = 1023;\n    }\n\n    if (chip->eg_test)\n    {\n        chip->eg_out[0] = 0;\n    }\n\n    chip->eg_test = chip->mode_test[5];\n}\n\nstatic void OPM_EnvelopePhase6(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 28) & 31;\n    chip->eg_serial_bit = (chip->eg_serial >> 9) & 1;\n    if (chip->cycles == 3)\n    {\n        chip->eg_serial = chip->eg_out[0] ^ 1023;\n    }\n    else\n    {\n        chip->eg_serial <<= 1;\n    }\n\n    chip->eg_out[1] = chip->eg_out[0];\n}\n\nstatic void OPM_EnvelopeClock(opm_t *chip)\n{\n    chip->eg_clock <<= 1;\n    if ((chip->eg_clockcnt & 2) != 0 || chip->mode_test[0])\n    {\n        chip->eg_clock |= 1;\n    }\n    if (chip->ic || (chip->cycles == 31 && (chip->eg_clockcnt & 2) != 0))\n    {\n        chip->eg_clockcnt = 0;\n    }\n    else if (chip->cycles == 31)\n    {\n        chip->eg_clockcnt++;\n    }\n}\n\nstatic void OPM_EnvelopeTimer(opm_t *chip)\n{\n    uint32_t cycle = (chip->cycles + 31) & 15;\n    uint32_t cycle2;\n    uint8_t inc = ((chip->cycles + 31) & 31) < 16 && (chip->eg_clock & 1) != 0 && (cycle == 0 || chip->eg_timercarry);\n    uint8_t timerbit = (chip->eg_timer >> cycle) & 1;\n    uint8_t sum = timerbit + inc;\n    uint8_t sum0 = (sum & 1) && !chip->ic;\n    chip->eg_timercarry = sum >> 1;\n    chip->eg_timer = (chip->eg_timer & (~(1 << cycle))) | (sum0 << cycle);\n\n    cycle2 = (chip->cycles + 30) & 15;\n\n    chip->eg_timer2 <<= 1;\n    if ((chip->eg_timer & (1 << cycle2)) != 0 && !chip->eg_timerbstop)\n    {\n        chip->eg_timer2 |= 1;\n    }\n\n    if (chip->eg_timer & (1 << cycle2))\n    {\n        chip->eg_timerbstop = 1;\n    }\n\n    if (cycle == 0 || chip->ic2)\n    {\n        chip->eg_timerbstop = 0;\n    }\n\n    if (chip->cycles == 1 && (chip->eg_clock & 1) != 0)\n    {\n        chip->eg_timershift_lock = 0;\n        if (chip->eg_timer2 & (8 + 32 + 128 + 512 + 2048 + 8192 + 32768))\n        {\n            chip->eg_timershift_lock |= 1;\n        }\n        if (chip->eg_timer2 & (4 + 32 + 64 + 512 + 1024 + 8192 + 16384))\n        {\n            chip->eg_timershift_lock |= 2;\n        }\n        if (chip->eg_timer2 & (4 + 8 + 16 + 512 + 1024 + 2048 + 4096))\n        {\n            chip->eg_timershift_lock |= 4;\n        }\n        if (chip->eg_timer2 & (4 + 8 + 16 + 32 + 64 + 128 + 256))\n        {\n            chip->eg_timershift_lock |= 8;\n        }\n        chip->eg_timer_lock = chip->eg_timer;\n    }\n}\n\nstatic void OPM_OperatorPhase1(opm_t *chip)\n{\n    uint32_t slot = chip->cycles;\n    int16_t mod = chip->op_mod[2];\n    chip->op_phase_in = chip->pg_phase[slot] >> 10;\n    if (chip->op_fbshift & 8)\n    {\n        if (chip->op_fb[1] == 0)\n        {\n            mod = 0;\n        }\n        else\n        {\n            mod = mod >> (9 - chip->op_fb[1]);\n        }\n    }\n    chip->op_mod_in = mod;\n}\n\nstatic void OPM_OperatorPhase2(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 31) & 31;\n    chip->op_phase = (chip->op_phase_in + chip->op_mod_in) & 1023;\n}\n\nstatic void OPM_OperatorPhase3(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 30) & 31;\n    uint16_t phase = chip->op_phase & 255;\n    if (chip->op_phase & 256)\n    {\n        phase ^= 255;\n    }\n    chip->op_logsin[0] = logsinrom[phase];\n    chip->op_sign <<= 1;\n    chip->op_sign |= (chip->op_phase >> 9) & 1;\n}\n\nstatic void OPM_OperatorPhase4(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 29) & 31;\n    chip->op_logsin[1] = chip->op_logsin[0];\n}\n\nstatic void OPM_OperatorPhase5(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 28) & 31;\n    chip->op_logsin[2] = chip->op_logsin[1];\n}\n\nstatic void OPM_OperatorPhase6(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 27) & 31;\n    chip->op_atten = chip->op_logsin[2] + (chip->eg_out[1] << 2);\n    if (chip->op_atten & 4096)\n    {\n        chip->op_atten = 4095;\n    }\n}\n\nstatic void OPM_OperatorPhase7(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 26) & 31;\n    chip->op_exp[0] = exprom[chip->op_atten & 255];\n    chip->op_pow[0] = chip->op_atten >> 8;\n}\n\nstatic void OPM_OperatorPhase8(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 25) & 31;\n    chip->op_exp[1] = chip->op_exp[0];\n    chip->op_pow[1] = chip->op_pow[0];\n}\n\nstatic void OPM_OperatorPhase9(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 24) & 31;\n    int16_t out = (chip->op_exp[1] << 2) >> (chip->op_pow[1]);\n    if (chip->op_sign & 32)\n    {\n        out = -out;\n    }\n    chip->op_out[0] = out;\n}\n\nstatic void OPM_OperatorPhase10(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 23) & 31;\n    chip->op_out[1] = chip->op_out[0];\n}\n\nstatic void OPM_OperatorPhase11(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 22) & 31;\n    chip->op_out[2] = chip->op_out[1];\n}\n\nstatic void OPM_OperatorPhase12(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 21) & 31;\n    chip->op_out[3] = chip->op_out[2];\n}\n\nstatic void OPM_OperatorPhase13(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 20) & 31;\n    chip->op_out[4] = chip->op_out[3];\n    chip->op_connect = chip->ch_connect[slot & 7];\n}\n\nstatic void OPM_OperatorPhase14(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 19) & 31;\n    uint32_t channel = slot & 7;\n    chip->op_mix = chip->op_out[5] = chip->op_out[4];\n    chip->op_fbupdate = (chip->op_counter == 0);\n    chip->op_c1update = (chip->op_counter == 2);\n    chip->op_fbshift <<= 1;\n    chip->op_fbshift |= (chip->op_counter == 2);\n\n    chip->op_modtable[0] = fm_algorithm[(chip->op_counter + 2) & 3][0][chip->op_connect];\n    chip->op_modtable[1] = fm_algorithm[(chip->op_counter + 2) & 3][1][chip->op_connect];\n    chip->op_modtable[2] = fm_algorithm[(chip->op_counter + 2) & 3][2][chip->op_connect];\n    chip->op_modtable[3] = fm_algorithm[(chip->op_counter + 2) & 3][3][chip->op_connect];\n    chip->op_modtable[4] = fm_algorithm[(chip->op_counter + 2) & 3][4][chip->op_connect];\n    chip->op_mixl = fm_algorithm[chip->op_counter][5][chip->op_connect] && (chip->ch_rl[channel] & 1) != 0;\n    chip->op_mixr = fm_algorithm[chip->op_counter][5][chip->op_connect] && (chip->ch_rl[channel] & 2) != 0;\n    if (chip->mute[channel])\n    {\n        chip->op_mixl = chip->op_mixr = 0;\n    }\n}\n\nstatic void OPM_OperatorPhase15(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 18) & 31;\n    int16_t mod, mod1 = 0, mod2 = 0;\n    if (chip->op_modtable[0])\n    {\n        mod2 |= chip->op_m1[slot & 7][0];\n    }\n    if (chip->op_modtable[1])\n    {\n        mod1 |= chip->op_m1[slot & 7][1];\n    }\n    if (chip->op_modtable[2])\n    {\n        mod1 |= chip->op_c1[slot & 7];\n    }\n    if (chip->op_modtable[3])\n    {\n        mod2 |= chip->op_out[5];\n    }\n    if (chip->op_modtable[4])\n    {\n        mod1 |= chip->op_out[5];\n    }\n    mod = (mod1 + mod2) >> 1;\n    chip->op_mod[0] = mod;\n    if (chip->op_fbupdate)\n    {\n        chip->op_m1[slot & 7][1] = chip->op_m1[slot & 7][0];\n        chip->op_m1[slot & 7][0] = chip->op_out[5];\n    }\n    if (chip->op_c1update)\n    {\n        chip->op_c1[slot & 7] = chip->op_out[5];\n    }\n}\n\nstatic void OPM_OperatorPhase16(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 17) & 31;\n    // hack\n    chip->op_mod[2] = chip->op_mod[1];\n    chip->op_fb[1] = chip->op_fb[0];\n\n    chip->op_mod[1] = chip->op_mod[0];\n    chip->op_fb[0] = chip->ch_fb[slot & 7];\n}\n\nstatic void OPM_OperatorCounter(opm_t *chip)\n{\n    if ((chip->cycles & 7) == 4)\n    {\n        chip->op_counter++;\n    }\n    if (chip->cycles == 12)\n    {\n        chip->op_counter = 0;\n    }\n}\n\nstatic void OPM_Mixer2(opm_t *chip)\n{\n    uint32_t cycles = (chip->cycles + 30) & 31;\n    uint8_t bit;\n    uint8_t top, ex;\n    if (cycles < 16)\n    {\n        bit = chip->mix_serial[0] & 1;\n    }\n    else\n    {\n        bit = chip->mix_serial[1] & 1;\n    }\n    if ((chip->cycles & 15) == 1)\n    {\n        chip->mix_sign_lock = bit ^ 1;\n        chip->mix_top_bits_lock = (chip->mix_bits >> 15) & 63;\n    }\n    chip->mix_bits >>= 1;\n    chip->mix_bits |= bit << 20;\n    if ((chip->cycles & 15) == 10)\n    {\n        top = chip->mix_top_bits_lock;\n        if (chip->mix_sign_lock)\n        {\n            top ^= 63;\n        }\n        if (top & 32)\n        {\n            ex = 7;\n        }\n        else if (top & 16)\n        {\n            ex = 6;\n        }\n        else if (top & 8)\n        {\n            ex = 5;\n        }\n        else if (top & 4)\n        {\n            ex = 4;\n        }\n        else if (top & 2)\n        {\n            ex = 3;\n        }\n        else if (top & 1)\n        {\n            ex = 2;\n        }\n        else\n        {\n            ex = 1;\n        }\n        chip->mix_sign_lock2 = chip->mix_sign_lock;\n        chip->mix_exp_lock = ex;\n    }\n    chip->mix_out_bit <<= 1;\n    switch ((chip->cycles + 1) & 15)\n    {\n    case 0:\n        chip->mix_out_bit |= chip->mix_sign_lock2 ^ 1;\n        break;\n    case 1:\n        chip->mix_out_bit |= (chip->mix_exp_lock >> 0) & 1;\n        break;\n    case 2:\n        chip->mix_out_bit |= (chip->mix_exp_lock >> 1) & 1;\n        break;\n    case 3:\n        chip->mix_out_bit |= (chip->mix_exp_lock >> 2) & 1;\n        break;\n    default:\n        if (chip->mix_exp_lock)\n        {\n            chip->mix_out_bit |= (chip->mix_bits >> (chip->mix_exp_lock - 1)) & 1;\n        }\n        break;\n    }\n}\n\nstatic void OPM_Output(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 27) & 31;\n    chip->smp_so = (chip->mix_out_bit & 4) != 0;\n    chip->smp_sh1 = (slot & 24) == 8 && !chip->ic;\n    chip->smp_sh2 = (slot & 24) == 24 && !chip->ic;\n}\n\nstatic void OPM_DAC(opm_t *chip)\n{\n    int32_t exp, mant;\n    if (chip->dac_osh1 && !chip->smp_sh1)\n    {\n        exp = (chip->dac_bits >> 10) & 7;\n        mant = (chip->dac_bits >> 0) & 1023;\n        mant -= 512;\n        chip->dac_output[1] = (mant << exp) >> 1;\n    }\n    if (chip->dac_osh2 && !chip->smp_sh2)\n    {\n        exp = (chip->dac_bits >> 10) & 7;\n        mant = (chip->dac_bits >> 0) & 1023;\n        mant -= 512;\n        chip->dac_output[0] = (mant << exp) >> 1;\n    }\n    chip->dac_bits >>= 1;\n    chip->dac_bits |= chip->smp_so << 12;\n    chip->dac_osh1 = chip->smp_sh1;\n    chip->dac_osh2 = chip->smp_sh2;\n}\n\nstatic void OPM_Mixer(opm_t *chip)\n{\n    uint32_t slot = (chip->cycles + 18) & 31;\n    uint32_t channel = (slot & 7);\n    // Right channel\n    chip->mix_serial[1] >>= 1;\n    if (chip->cycles == 13)\n    {\n        chip->mix_serial[1] |= (chip->mix[1] & 1023) << 4;\n    }\n    if (chip->cycles == 14)\n    {\n        chip->mix_serial[1] |= ((chip->mix2[1] >> 10) & 31) << 13;\n        chip->mix_serial[1] |= (((chip->mix2[1] >> 17) & 1) ^ 1) << 18;\n        chip->mix_clamp_low[1] = 0;\n        chip->mix_clamp_high[1] = 0;\n        switch ((chip->mix2[1]>>15) & 7)\n        {\n        case 0:\n        default:\n            break;\n        case 1:\n            chip->mix_clamp_high[1] = 1;\n            break;\n        case 2:\n            chip->mix_clamp_high[1] = 1;\n            break;\n        case 3:\n            chip->mix_clamp_high[1] = 1;\n            break;\n        case 4:\n            chip->mix_clamp_low[1] = 1;\n            break;\n        case 5:\n            chip->mix_clamp_low[1] = 1;\n            break;\n        case 6:\n            chip->mix_clamp_low[1] = 1;\n            break;\n        case 7:\n            break;\n        }\n    }\n    if (chip->mix_clamp_low[1])\n    {\n        chip->mix_serial[1] &= ~2;\n    }\n    if (chip->mix_clamp_high[1])\n    {\n        chip->mix_serial[1] |= 2;\n    }\n    // Left channel\n    chip->mix_serial[0] >>= 1;\n    if (chip->cycles == 29)\n    {\n        chip->mix_serial[0] |= (chip->mix[0] & 1023) << 4;\n    }\n    if (chip->cycles == 30)\n    {\n        chip->mix_serial[0] |= ((chip->mix2[0] >> 10) & 31) << 13;\n        chip->mix_serial[0] |= (((chip->mix2[0] >> 17) & 1) ^ 1) << 18;\n        chip->mix_clamp_low[0] = 0;\n        chip->mix_clamp_high[0] = 0;\n        switch ((chip->mix2[0]>>15) & 7)\n        {\n        case 0:\n        default:\n            break;\n        case 1:\n            chip->mix_clamp_high[0] = 1;\n            break;\n        case 2:\n            chip->mix_clamp_high[0] = 1;\n            break;\n        case 3:\n            chip->mix_clamp_high[0] = 1;\n            break;\n        case 4:\n            chip->mix_clamp_low[0] = 1;\n            break;\n        case 5:\n            chip->mix_clamp_low[0] = 1;\n            break;\n        case 6:\n            chip->mix_clamp_low[0] = 1;\n            break;\n        case 7:\n            break;\n        }\n    }\n    if (chip->mix_clamp_low[0])\n    {\n        chip->mix_serial[0] &= ~2;\n    }\n    if (chip->mix_clamp_high[0])\n    {\n        chip->mix_serial[0] |= 2;\n    }\n    chip->mix2[0] = chip->mix[0];\n    chip->mix2[1] = chip->mix[1];\n    if (chip->cycles == 13)\n    {\n        chip->mix[1] = 0;\n    }\n    if (chip->cycles == 29)\n    {\n        chip->mix[0] = 0;\n    }\n    chip->mix[0] += chip->op_mix * chip->op_mixl;\n    chip->mix[1] += chip->op_mix * chip->op_mixr;\n}\n\nstatic void OPM_Noise(opm_t *chip)\n{\n    uint8_t w1 = !chip->ic && !chip->noise_update;\n    uint8_t xr = ((chip->noise_lfsr >> 2) & 1) ^ chip->noise_temp;\n    uint8_t w2t = (chip->noise_lfsr & 0xffff) == 0xffff && chip->noise_temp == 0;\n    uint8_t w2 = !w2t && !xr;\n    uint8_t w3 = !chip->ic && !w1 && !w2;\n    uint8_t w4 = ((chip->noise_lfsr & 1) == 0 || !w1) && !w3;\n    if (!w1)\n    {\n        chip->noise_temp = (chip->noise_lfsr & 1) == 0;\n    }\n    chip->noise_lfsr >>= 1;\n    chip->noise_lfsr |= w4 << 15;\n}\n\nstatic void OPM_NoiseTimer(opm_t *chip)\n{\n    uint32_t timer = chip->noise_timer;\n\n    chip->noise_update = chip->noise_timer_of;\n\n    if ((chip->cycles & 15) == 15)\n    {\n        timer++;\n        timer &= 31;\n    }\n    if (chip->ic || (chip->noise_timer_of && ((chip->cycles & 15) == 15)))\n    {\n        timer = 0;\n    }\n\n    chip->noise_timer_of = chip->noise_timer == (chip->noise_freq ^ 31);\n    chip->noise_timer = timer;\n}\n\nstatic void OPM_DoTimerA(opm_t *chip)\n{\n    uint16_t value = chip->timer_a_val;\n    value += chip->timer_a_inc;\n    chip->timer_a_of = (value >> 10) & 1;\n    if (chip->timer_a_do_reset)\n    {\n        value = 0;\n    }\n    if (chip->timer_a_do_load)\n    {\n        value = chip->timer_a_reg;\n    }\n\n    chip->timer_a_val = value & 1023;\n}\n\nstatic void OPM_DoTimerA2(opm_t *chip)\n{\n    if (chip->cycles == 1)\n    {\n        chip->timer_a_load = chip->timer_loada;\n    }\n    chip->timer_a_inc = chip->mode_test[2] || (chip->timer_a_load && chip->cycles == 0);\n    chip->timer_a_do_load = chip->timer_a_of || (chip->timer_a_load && chip->timer_a_temp);\n    chip->timer_a_do_reset = chip->timer_a_temp;\n    chip->timer_a_temp = !chip->timer_a_load;\n    if (chip->timer_reseta || chip->ic)\n    {\n        chip->timer_a_status = 0;\n    }\n    else\n    {\n        chip->timer_a_status |= chip->timer_irqa && chip->timer_a_of;\n    }\n    chip->timer_reseta = 0;\n}\n\nstatic void OPM_DoTimerB(opm_t *chip)\n{\n    uint16_t value = chip->timer_b_val;\n    value += chip->timer_b_inc;\n    chip->timer_b_of = (value >> 8) & 1;\n    if (chip->timer_b_do_reset)\n    {\n        value = 0;\n    }\n    if (chip->timer_b_do_load)\n    {\n        value = chip->timer_b_reg;\n    }\n\n    chip->timer_b_val = value & 255;\n\n    if (chip->cycles == 0)\n    {\n        chip->timer_b_sub++;\n    }\n\n    chip->timer_b_sub_of = (chip->timer_b_sub >> 4) & 1;\n    chip->timer_b_sub &= 15;\n    if (chip->ic)\n    {\n        chip->timer_b_sub = 0;\n    }\n}\n\nstatic void OPM_DoTimerB2(opm_t *chip)\n{\n    chip->timer_b_inc = chip->mode_test[2] || (chip->timer_loadb && chip->timer_b_sub_of);\n    chip->timer_b_do_load = chip->timer_b_of || (chip->timer_loadb && chip->timer_b_temp);\n    chip->timer_b_do_reset = chip->timer_b_temp;\n    chip->timer_b_temp = !chip->timer_loadb;\n    if (chip->timer_resetb || chip->ic)\n    {\n        chip->timer_b_status = 0;\n    }\n    else\n    {\n        chip->timer_b_status |= chip->timer_irqb && chip->timer_b_of;\n    }\n    chip->timer_resetb = 0;\n}\n\nstatic void OPM_DoTimerIRQ(opm_t *chip)\n{\n    chip->timer_irq = chip->timer_a_status || chip->timer_b_status;\n}\n\nstatic void OPM_DoLFOMult(opm_t *chip)\n{\n    uint8_t ampm_sel = (chip->lfo_bit_counter & 8) != 0;\n    uint8_t dp = ampm_sel ? chip->lfo_pmd : chip->lfo_amd;\n    uint8_t bit = 0, b1, b2;\n    uint8_t sum;\n\n    chip->lfo_out2_b = chip->lfo_out2;\n\n    switch (chip->lfo_bit_counter & 7)\n    {\n    case 0:\n        bit = (dp & 64) != 0 && (chip->lfo_out1 & 64) == 0;\n        break;\n    case 1:\n        bit = (dp & 32) != 0 && (chip->lfo_out1 & 32) == 0;\n        break;\n    case 2:\n        bit = (dp & 16) != 0 && (chip->lfo_out1 & 16) == 0;\n        break;\n    case 3:\n        bit = (dp & 8) != 0 && (chip->lfo_out1 & 8) == 0;\n        break;\n    case 4:\n        bit = (dp & 4) != 0 && (chip->lfo_out1 & 4) == 0;\n        break;\n    case 5:\n        bit = (dp & 2) != 0 && (chip->lfo_out1 & 2) == 0;\n        break;\n    case 6:\n        bit = (dp & 1) != 0 && (chip->lfo_out1 & 1) == 0;\n        break;\n    }\n\n    b1 = (chip->lfo_out2 & 1) != 0;\n    if ((chip->lfo_bit_counter & 7) == 0)\n    {\n        b1 = 0;\n    }\n    b2 = chip->lfo_mult_carry;\n    if ((chip->cycles & 15) == 15)\n    {\n        b2 = 0;\n    }\n    sum = bit + b1 + b2;\n    chip->lfo_out2 >>= 1;\n    chip->lfo_out2 |= (sum & 1) << 15;\n    chip->lfo_mult_carry = sum >> 1;\n}\n\nstatic void OPM_DoLFO1(opm_t *chip)\n{\n    uint16_t counter2 = chip->lfo_counter2;\n    uint8_t of_old = chip->lfo_counter2_of;\n    uint8_t lfo_bit, noise, sum, carry, w[10];\n    uint8_t lfo_pm_sign;\n    uint8_t ampm_sel = (chip->lfo_bit_counter & 8) != 0;\n    counter2 += (chip->lfo_counter1_of1 & 2) != 0 || chip->mode_test[3];\n    chip->lfo_counter2_of = (counter2 >> 15) & 1;\n    if (chip->ic)\n    {\n        counter2 = 0;\n    }\n    if (chip->lfo_counter2_load)\n    {\n        counter2 = lfo_counter2_table[chip->lfo_freq_hi];\n    }\n    chip->lfo_counter2 = counter2 & 32767;\n    chip->lfo_counter2_load = chip->lfo_frq_update || of_old;\n    chip->lfo_frq_update = 0;\n    if ((chip->cycles & 15) == 12)\n    {\n        chip->lfo_counter1++;\n    }\n    chip->lfo_counter1_of1 <<= 1;\n    chip->lfo_counter1_of1 |= (chip->lfo_counter1 >> 4) & 1;\n    chip->lfo_counter1 &= 15;\n    if (chip->ic)\n    {\n        chip->lfo_counter1 = 0;\n    }\n\n    if ((chip->cycles & 15) == 5)\n    {\n        chip->lfo_counter2_of_lock2 = chip->lfo_counter2_of_lock;\n    }\n\n    chip->lfo_counter3 += chip->lfo_counter3_clock;\n    if (chip->ic)\n    {\n        chip->lfo_counter3 = 0;\n    }\n\n    chip->lfo_counter3_clock = (chip->cycles & 15) == 13 && chip->lfo_counter2_of_lock2;\n\n    if ((chip->cycles & 15) == 15)\n    {\n        chip->lfo_trig_sign = (chip->lfo_val & 0x80) != 0;\n        chip->lfo_saw_sign = (chip->lfo_val & 0x100) != 0;\n    }\n\n    lfo_pm_sign = chip->lfo_wave == 2 ? chip->lfo_trig_sign : chip->lfo_saw_sign;\n\n    w[5] = ampm_sel ? chip->lfo_saw_sign : (chip->lfo_wave != 2 || chip->lfo_trig_sign);\n\n    w[1] = !chip->lfo_clock || chip->lfo_wave == 3 || (chip->cycles & 15) != 15;\n    w[2] = chip->lfo_wave == 2 && !w[1];\n    w[4] = chip->lfo_clock_lock && chip->lfo_wave == 3;\n    w[3] = !chip->ic && !chip->mode_test[1] && !w[4] && (chip->lfo_val & 0x8000) != 0;\n\n    w[7] = ((chip->cycles + 1) & 15) < 8;\n\n    w[6] = w[5] ^ w[3];\n    \n    w[9] = ampm_sel ? ((chip->cycles & 15) == 6) : !chip->lfo_saw_sign;\n\n    w[8] = chip->lfo_wave == 1 ? w[9] : w[6];\n\n    w[8] &= w[7];\n\n    chip->lfo_out1 <<= 1;\n    chip->lfo_out1 |= !w[8];\n\n    carry = !w[1] || ((chip->cycles & 15) != 15 && chip->lfo_val_carry != 0 && chip->lfo_wave != 3);\n    sum = carry + w[2] + w[3];\n    noise = chip->lfo_clock_lock && (chip->noise_lfsr & 1) != 0;\n    lfo_bit = sum & 1;\n    lfo_bit |= (chip->lfo_wave == 3) && noise;\n    chip->lfo_val_carry = sum >> 1;\n    chip->lfo_val <<= 1;\n    chip->lfo_val |= lfo_bit;\n    \n\n    if ((chip->cycles & 15) == 15 && (chip->lfo_bit_counter & 7) == 7)\n    {\n        if (ampm_sel)\n        {\n            chip->lfo_pm_lock = (chip->lfo_out2_b >> 8) & 255;\n            chip->lfo_pm_lock ^= lfo_pm_sign << 7;\n        }\n        else\n        {\n            chip->lfo_am_lock = (chip->lfo_out2_b >> 8) & 255;\n        }\n    }\n\n    if ((chip->cycles & 15) == 14)\n    {\n        chip->lfo_bit_counter++;\n    }\n    if ((chip->cycles & 15) != 12 && chip->lfo_counter1_of2)\n    {\n        chip->lfo_bit_counter = 0;\n    }\n    chip->lfo_counter1_of2 = chip->lfo_counter1 == 2;\n}\n\nstatic void OPM_DoLFO2(opm_t *chip)\n{\n    uint8_t c3_step = 0;\n\n    chip->lfo_clock_test = chip->lfo_clock;\n    chip->lfo_clock = (chip->lfo_counter2_of || chip->lfo_test || chip->lfo_counter3_step);\n    if ((chip->cycles & 15) == 14)\n    {\n        chip->lfo_counter2_of_lock = chip->lfo_counter2_of;\n        chip->lfo_clock_lock = chip->lfo_clock;\n    }\n    chip->lfo_counter3_step = 0;\n    if (chip->lfo_counter3_clock)\n    {\n        if ((chip->lfo_counter3 & 1) == 0)\n        {\n            chip->lfo_counter3_step = (chip->lfo_freq_lo & 8) != 0;\n        }\n        else if ((chip->lfo_counter3 & 2) == 0)\n        {\n            chip->lfo_counter3_step = (chip->lfo_freq_lo & 4) != 0;\n        }\n        else if ((chip->lfo_counter3 & 4) == 0)\n        {\n            chip->lfo_counter3_step = (chip->lfo_freq_lo & 2) != 0;\n        }\n        else if ((chip->lfo_counter3 & 8) == 0)\n        {\n            chip->lfo_counter3_step = (chip->lfo_freq_lo & 1) != 0;\n        }\n    }\n    chip->lfo_test = chip->mode_test[2];\n}\n\nstatic void OPM_CSM(opm_t *chip)\n{\n    chip->kon_csm = chip->kon_csm_lock;\n    if (chip->cycles == 1)\n    {\n        chip->kon_csm_lock = chip->timer_a_do_load && chip->mode_csm;\n    }\n}\n\nstatic void OPM_NoiseChannel(opm_t *chip)\n{\n    chip->nc_active |= chip->eg_serial_bit & 1;\n    if (chip->cycles == 13)\n    {\n        chip->nc_active = 0;\n    }\n    chip->nc_out <<= 1;\n    chip->nc_out |= chip->nc_sign ^ chip->eg_serial_bit;\n    chip->nc_sign = !chip->nc_sign_lock;\n    if (chip->cycles == 12)\n    {\n        chip->nc_active_lock = chip->nc_active;\n        chip->nc_sign_lock2 = chip->nc_active_lock && !chip->nc_sign_lock;\n        chip->nc_sign_lock = (chip->noise_lfsr & 1);\n\n        if (chip->noise_en)\n        {\n            if (chip->nc_sign_lock2)\n            {\n                chip->op_mix = ((chip->nc_out & ~1) << 2) | -4089;\n            }\n            else\n            {\n                chip->op_mix = ((chip->nc_out & ~1) << 2);\n            }\n        }\n    }\n}\n\nstatic void OPM_DoIO(opm_t *chip)\n{\n    // Busy\n    chip->write_busy_cnt += chip->write_busy;\n    chip->write_busy = (!(chip->write_busy_cnt >> 5) && chip->write_busy && !chip->ic) | chip->write_d_en;\n    chip->write_busy_cnt &= 0x1f;\n    if (chip->ic)\n    {\n        chip->write_busy_cnt = 0;\n    }\n    // Write signal check\n    chip->write_a_en = chip->write_a;\n    chip->write_d_en = chip->write_d;\n    chip->write_a = 0;\n    chip->write_d = 0;\n}\n\nstatic void OPM_DoRegWrite(opm_t *chip)\n{\n    int32_t i;\n    uint32_t channel = chip->cycles & 7;\n    uint32_t slot = chip->cycles;\n\n    // Register write\n    if (chip->reg_data_ready)\n    {\n        // Channel\n        if ((chip->reg_address & 0xe7) == (0x20 | channel))\n        {\n            switch (chip->reg_address & 0x18)\n            {\n            case 0x00: // RL, FB, CONNECT\n                chip->ch_rl[channel] = chip->reg_data >> 6;\n                chip->ch_fb[channel] = (chip->reg_data >> 3) & 0x07;\n                chip->ch_connect[channel] = chip->reg_data & 0x07;\n                break;\n            case 0x08: // KC\n                chip->ch_kc[channel] = chip->reg_data & 0x7f;\n                break;\n            case 0x10: // KF\n                chip->ch_kf[channel] = chip->reg_data >> 2;\n                break;\n            case 0x18: // PMS, AMS\n                chip->ch_pms[channel] = (chip->reg_data >> 4) & 0x07;\n                chip->ch_ams[channel] = chip->reg_data & 0x03;\n                break;\n            default:\n                break;\n            }\n        }\n        // Slot\n        if ((chip->reg_address & 0x1f) == slot)\n        {\n            switch (chip->reg_address & 0xe0)\n            {\n            case 0x40: // DT1, MUL\n                chip->sl_dt1[slot] = (chip->reg_data >> 4) & 0x07;\n                chip->sl_mul[slot] = chip->reg_data & 0x0f;\n                break;\n            case 0x60: // TL\n                chip->sl_tl[slot] = chip->reg_data & 0x7f;\n                break;\n            case 0x80: // KS, AR\n                chip->sl_ks[slot] = chip->reg_data >> 6;\n                chip->sl_ar[slot] = chip->reg_data & 0x1f;\n                break;\n            case 0xa0: // AMS-EN, D1R\n                chip->sl_am_e[slot] = chip->reg_data >> 7;\n                chip->sl_d1r[slot] = chip->reg_data & 0x1f;\n                break;\n            case 0xc0: // DT2, D2R\n                chip->sl_dt2[slot] = chip->reg_data >> 6;\n                chip->sl_d2r[slot] = chip->reg_data & 0x1f;\n                break;\n            case 0xe0: // D1L, RR\n                chip->sl_d1l[slot] = chip->reg_data >> 4;\n                chip->sl_rr[slot] = chip->reg_data & 0x0f;\n                break;\n            default:\n                break;\n            }\n        }\n    }\n\n    // Mode write\n    if (chip->write_d_en)\n    {\n        switch (chip->mode_address)\n        {\n        case 0x01:\n            for (i = 0; i < 8; i++)\n            {\n                chip->mode_test[i] = (chip->write_data >> i) & 0x01;\n            }\n            break;\n        case 0x08:\n            for (i = 0; i < 4; i++)\n            {\n                chip->mode_kon_operator[i] = (chip->write_data >> (i + 3)) & 0x01;\n            }\n            chip->mode_kon_channel = chip->write_data & 0x07;\n            break;\n        case 0x0f:\n            chip->noise_en = chip->write_data >> 7;\n            chip->noise_freq = chip->write_data & 0x1f;\n            break;\n        case 0x10:\n            chip->timer_a_reg &= 0x03;\n            chip->timer_a_reg |= chip->write_data << 2;\n            break;\n        case 0x11:\n            chip->timer_a_reg &= 0x3fc;\n            chip->timer_a_reg |= chip->write_data & 0x03;\n            break;\n        case 0x12:\n            chip->timer_b_reg = chip->write_data;\n            break;\n        case 0x14:\n            chip->mode_csm = (chip->write_data >> 7) & 1;\n            chip->timer_irqb = (chip->write_data >> 3) & 1;\n            chip->timer_irqa = (chip->write_data >> 2) & 1;\n            chip->timer_resetb = (chip->write_data >> 3) & 1;\n            chip->timer_reseta = (chip->write_data >> 2) & 1;\n            chip->timer_loadb = (chip->write_data >> 1) & 1;\n            chip->timer_loada = (chip->write_data >> 0) & 1;\n            break;\n        case 0x18:\n            chip->lfo_freq_hi = chip->write_data >> 4;\n            chip->lfo_freq_lo = chip->write_data & 0x0f;\n            chip->lfo_frq_update = 1;\n            break;\n        case 0x19:\n            if (chip->write_data & 0x80)\n            {\n                chip->lfo_pmd = chip->write_data & 0x7f;\n            }\n            else\n            {\n                chip->lfo_amd = chip->write_data;\n            }\n            break;\n        case 0x1b:\n            chip->lfo_wave = chip->write_data & 0x03;\n            chip->io_ct1 = chip->write_data >> 7;\n            chip->io_ct2 = (chip->write_data >> 6) & 0x01;\n            break;\n        }\n    }\n\n    // Register data write\n    chip->reg_data_ready = chip->reg_data_ready && !chip->write_a_en;\n    if (chip->reg_address_ready && chip->write_d_en)\n    {\n        chip->reg_data = chip->write_data;\n        chip->reg_data_ready = 1;\n    }\n\n    // Register address write\n    chip->reg_address_ready = chip->reg_address_ready && !chip->write_a_en;\n    if (chip->write_a_en && (chip->write_data & 0xe0) != 0)\n    {\n        chip->reg_address = chip->write_data;\n        chip->reg_address_ready = 1;\n    }\n    if (chip->write_a_en)\n    {\n        chip->mode_address = chip->write_data;\n    }\n}\n\nstatic void OPM_DoIC(opm_t *chip)\n{\n    uint32_t channel = chip->cycles & 7;\n    uint32_t slot = chip->cycles;\n    if (chip->ic)\n    {\n        chip->ch_rl[channel] = 0;\n        chip->ch_fb[channel] = 0;\n        chip->ch_connect[channel] = 0;\n        chip->ch_kc[channel] = 0;\n        chip->ch_kf[channel] = 0;\n        chip->ch_pms[channel] = 0;\n        chip->ch_ams[channel] = 0;\n\n        chip->sl_dt1[slot] = 0;\n        chip->sl_mul[slot] = 0;\n        chip->sl_tl[slot] = 0;\n        chip->sl_ks[slot] = 0;\n        chip->sl_ar[slot] = 0;\n        chip->sl_am_e[slot] = 0;\n        chip->sl_d1r[slot] = 0;\n        chip->sl_dt2[slot] = 0;\n        chip->sl_d2r[slot] = 0;\n        chip->sl_d1l[slot] = 0;\n        chip->sl_rr[slot] = 0;\n\n        chip->timer_a_reg = 0;\n        chip->timer_b_reg = 0;\n        chip->timer_irqa = 0;\n        chip->timer_irqb = 0;\n        chip->timer_loada = 0;\n        chip->timer_loadb = 0;\n        chip->mode_csm = 0;\n\n        chip->mode_test[0] = 0;\n        chip->mode_test[1] = 0;\n        chip->mode_test[2] = 0;\n        chip->mode_test[3] = 0;\n        chip->mode_test[4] = 0;\n        chip->mode_test[5] = 0;\n        chip->mode_test[6] = 0;\n        chip->mode_test[7] = 0;\n        chip->noise_en = 0;\n        chip->noise_freq = 0;\n\n        chip->mode_kon_channel = 0;\n        chip->mode_kon_operator[0] = 0;\n        chip->mode_kon_operator[1] = 0;\n        chip->mode_kon_operator[2] = 0;\n        chip->mode_kon_operator[3] = 0;\n        chip->mode_kon[(slot + 8) & 31] = 0;\n\n        chip->lfo_pmd = 0;\n        chip->lfo_amd = 0;\n        chip->lfo_wave = 0;\n        chip->lfo_freq_hi = 0;\n        chip->lfo_freq_lo = 0;\n\n        chip->io_ct1 = 0;\n        chip->io_ct2 = 0;\n\n        chip->reg_address = 0;\n        chip->reg_data = 0;\n    }\n    chip->ic2 = chip->ic;\n}\n\nvoid OPM_Clock(opm_t *chip, int32_t *output, uint8_t *sh1, uint8_t *sh2, uint8_t *so)\n{\n    OPM_Mixer2(chip);\n    OPM_Mixer(chip);\n\n    OPM_OperatorPhase16(chip);\n    OPM_OperatorPhase15(chip);\n    OPM_OperatorPhase14(chip);\n    OPM_OperatorPhase13(chip);\n    OPM_OperatorPhase12(chip);\n    OPM_OperatorPhase11(chip);\n    OPM_OperatorPhase10(chip);\n    OPM_OperatorPhase9(chip);\n    OPM_OperatorPhase8(chip);\n    OPM_OperatorPhase7(chip);\n    OPM_OperatorPhase6(chip);\n    OPM_OperatorPhase5(chip);\n    OPM_OperatorPhase4(chip);\n    OPM_OperatorPhase3(chip);\n    OPM_OperatorPhase2(chip);\n    OPM_OperatorPhase1(chip);\n    OPM_OperatorCounter(chip);\n\n    OPM_EnvelopeTimer(chip);\n    OPM_EnvelopePhase6(chip);\n    OPM_EnvelopePhase5(chip);\n    OPM_EnvelopePhase4(chip);\n    OPM_EnvelopePhase3(chip);\n    OPM_EnvelopePhase2(chip);\n    OPM_EnvelopePhase1(chip);\n\n    OPM_PhaseDebug(chip);\n    OPM_PhaseGenerate(chip);\n    OPM_PhaseCalcIncrement(chip);\n    OPM_PhaseCalcFNumBlock(chip);\n\n    OPM_DoTimerIRQ(chip);\n    OPM_DoTimerA(chip);\n    OPM_DoTimerB(chip);\n    OPM_DoLFOMult(chip);\n    OPM_DoLFO1(chip);\n    OPM_Noise(chip);\n    OPM_KeyOn2(chip);\n    OPM_DoRegWrite(chip);\n    OPM_EnvelopeClock(chip);\n    OPM_NoiseTimer(chip);\n    OPM_KeyOn1(chip);\n    OPM_DoIO(chip);\n    OPM_DoTimerA2(chip);\n    OPM_DoTimerB2(chip);\n    OPM_DoLFO2(chip);\n    OPM_CSM(chip);\n    OPM_NoiseChannel(chip);\n    OPM_Output(chip);\n    OPM_DAC(chip);\n    OPM_DoIC(chip);\n    if (sh1)\n    {\n        *sh1 = chip->smp_sh1;\n    }\n    if (sh2)\n    {\n        *sh2 = chip->smp_sh2;\n    }\n    if (so)\n    {\n        *so = chip->smp_so;\n    }\n    if (output)\n    {\n        output[0] = chip->dac_output[0];\n        output[1] = chip->dac_output[1];\n    }\n    chip->cycles = (chip->cycles + 1) & 31;\n}\n\nvoid OPM_Write(opm_t *chip, uint32_t port, uint8_t data)\n{\n    chip->write_data = data;\n    if (chip->ic)\n    {\n        return;\n    }\n    if (port & 0x01)\n    {\n        chip->write_d = 1;\n    }\n    else\n    {\n        chip->write_a = 1;\n    }\n}\n\nuint8_t OPM_Read(opm_t *chip, uint32_t port)\n{\n    uint16_t testdata;\n    if (chip->mode_test[6])\n    {\n        testdata = chip->op_out[5] | ((chip->eg_serial_bit ^ 1) << 14) | ((chip->pg_serial & 1) << 15);\n        if (chip->mode_test[7])\n        {\n            return testdata & 255;\n        }\n        else\n        {\n            return testdata >> 8;\n        }\n    }\n    return (chip->write_busy << 7) | (chip->timer_b_status << 1) | chip->timer_a_status;\n}\n\nuint8_t OPM_ReadIRQ(opm_t *chip, uint32_t port)\n{\n    return chip->timer_irq;\n}\n\nuint8_t OPM_ReadCT1(opm_t *chip)\n{\n    return chip->io_ct1;\n}\n\nuint8_t OPM_ReadCT2(opm_t *chip)\n{\n    if(chip->mode_test[3])\n    {\n        return chip->lfo_clock_test;\n    }\n    return chip->io_ct2;\n}\n\nvoid OPM_SetIC(opm_t *chip, uint8_t ic)\n{\n    if (chip->ic != ic)\n    {\n        chip->ic = ic;\n        if (!ic)\n        {\n            chip->cycles = 0;\n        }\n    }\n}\n\n#if 0\nvoid OPM_Reset(opm_t *chip)\n{\n    uint32_t i;\n    memset(chip, 0, sizeof(opm_t));\n    OPM_SetIC(chip, 1);\n    for (i = 0; i < 32 * 64; i++)\n    {\n        OPM_Clock(chip, NULL, NULL, NULL, NULL);\n    }\n    OPM_SetIC(chip, 0);\n}\n#endif\n\n\nvoid OPM_WriteBuffered(opm_t *chip, uint32_t port, uint8_t data)\n{\n    uint64_t time1, time2;\n    int32_t buffer[2];\n    uint64_t skip;\n\n    if (chip->writebuf[chip->writebuf_last].port & 0x02)\n    {\n        OPM_Write(chip, chip->writebuf[chip->writebuf_last].port & 0x01,\n                   chip->writebuf[chip->writebuf_last].data);\n\n        chip->writebuf[chip->writebuf_last].port &= 0x01;\n        chip->writebuf_cur = (chip->writebuf_last + 1) % OPN_WRITEBUF_SIZE;\n        skip = chip->writebuf[chip->writebuf_last].time - chip->writebuf_samplecnt;\n        chip->writebuf_samplecnt = chip->writebuf[chip->writebuf_last].time;\n        while (skip--)\n        {\n            OPM_Clock(chip, buffer, NULL, NULL, NULL);\n        }\n    }\n\n    chip->writebuf[chip->writebuf_last].port = (port & 0x01) | 0x02;\n    chip->writebuf[chip->writebuf_last].data = data;\n    time1 = chip->writebuf_lasttime + OPN_WRITEBUF_DELAY;\n    time2 = chip->writebuf_samplecnt;\n\n    if (time1 < time2)\n    {\n        time1 = time2;\n    }\n\n    chip->writebuf[chip->writebuf_last].time = time1;\n    chip->writebuf_lasttime = time1;\n    chip->writebuf_last = (chip->writebuf_last + 1) % OPN_WRITEBUF_SIZE;\n}\n\nvoid OPM_GenerateResampled(opm_t *chip, int32_t *buf)\n{\n    uint32_t i;\n    int32_t buffer[2];\n    \n    while (chip->samplecnt >= chip->rateratio)\n    {\n        chip->oldsamples[0] = chip->samples[0];\n        chip->oldsamples[1] = chip->samples[1];\n        chip->samples[0] = chip->samples[1] = 0;\n        for (i = 0; i < 32; i++)\n        {\n            OPM_Clock(chip, buffer, NULL, NULL, NULL);\n            if (i == 0)\n            {\n                chip->samples[0] += buffer[0];\n                chip->samples[1] += buffer[1];\n            }\n\n            while (chip->writebuf[chip->writebuf_cur].time <= chip->writebuf_samplecnt)\n            {\n                if (!(chip->writebuf[chip->writebuf_cur].port & 0x02))\n                {\n                    break;\n                }\n                chip->writebuf[chip->writebuf_cur].port &= 0x01;\n                OPM_Write(chip, chip->writebuf[chip->writebuf_cur].port,\n                              chip->writebuf[chip->writebuf_cur].data);\n                chip->writebuf_cur = (chip->writebuf_cur + 1) % OPN_WRITEBUF_SIZE;\n            }\n            chip->writebuf_samplecnt++;\n        }\n        chip->samplecnt -= chip->rateratio;\n    }\n    buf[0] = (int32_t)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt)\n                     + chip->samples[0] * chip->samplecnt) / chip->rateratio);\n    buf[1] = (int32_t)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt)\n                     + chip->samples[1] * chip->samplecnt) / chip->rateratio);\n    chip->samplecnt += 1 << RSM_FRAC;\n}\n\nvoid OPM_GenerateStream(opm_t *chip, int32_t **sndptr, uint32_t numsamples)\n{\n    uint32_t i;\n    int32_t *smpl, *smpr;\n    int32_t buffer[2];\n    smpl = sndptr[0];\n    smpr = sndptr[1];\n\n    for (i = 0; i < numsamples; i++)\n    {\n        OPM_GenerateResampled(chip, buffer);\n        *smpl++ = buffer[0];\n        *smpr++ = buffer[1];\n    }\n}\n\nvoid OPM_Reset(opm_t* chip, uint32_t rate, uint32_t clock)\n{\n    uint32_t i, rateratio;\n    rateratio = chip->rateratio;\n    memset(chip, 0, sizeof(opm_t));\n    OPM_SetIC(chip, 1);\n    for (i = 0; i < 32 * 64; i++)\n    {\n        OPM_Clock(chip, NULL, NULL, NULL, NULL);\n    }\n    OPM_SetIC(chip, 0);\n    if (rate != 0)\n    {\n        chip->rateratio = (uint32_t)((((uint64_t)64 * rate) << RSM_FRAC) / clock);\n    }\n    else\n    {\n        chip->rateratio = rateratio;\n    }\n}\n\nvoid OPM_SetMute(opm_t *chip, uint32_t mute)\n{\n    uint32_t i;\n    for (i = 0; i < 8; i++)\n    {\n        chip->mute[i] = (mute >> i) & 0x01;\n    }\n}\n\n\n"
  },
  {
    "path": "VGMPlay/chips/opm.h",
    "content": "/* Nuked OPM\n * Copyright (C) 2020 Nuke.YKT\n *\n * This file is part of Nuked OPM.\n *\n * Nuked OPM is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as\n * published by the Free Software Foundation, either version 2.1\n * of the License, or (at your option) any later version.\n *\n * Nuked OPM is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with Nuked OPM. If not, see <https://www.gnu.org/licenses/>.\n *\n *  Nuked OPM emulator.\n *  Thanks:\n *      siliconpr0n.org(digshadow, John McMaster):\n *          YM2151 and other FM chip decaps and die shots.\n *\n * version: 0.9 beta\n */\n#ifndef _OPM_H_\n#define _OPM_H_\n\n#include \"emutypes.h\"\n\n#define RSM_FRAC 10\n#define OPN_WRITEBUF_SIZE 2048\n#define OPN_WRITEBUF_DELAY 36\n\ntypedef struct {\n    uint64_t time;\n    uint8_t port;\n    uint8_t data;\n} opm_writebuf;\n\ntypedef struct {\n    uint32_t cycles;\n    uint8_t ic;\n    uint8_t ic2;\n    // IO\n    uint8_t write_data;\n    uint8_t write_a;\n    uint8_t write_a_en;\n    uint8_t write_d;\n    uint8_t write_d_en;\n    uint8_t write_busy;\n    uint8_t write_busy_cnt;\n    uint8_t mode_address;\n    uint8_t io_ct1;\n    uint8_t io_ct2;\n\n    // LFO\n    uint8_t lfo_am_lock;\n    uint8_t lfo_pm_lock;\n    uint8_t lfo_counter1;\n    uint8_t lfo_counter1_of1;\n    uint8_t lfo_counter1_of2;\n    uint16_t lfo_counter2;\n    uint8_t lfo_counter2_load;\n    uint8_t lfo_counter2_of;\n    uint8_t lfo_counter2_of_lock;\n    uint8_t lfo_counter2_of_lock2;\n    uint8_t lfo_counter3_clock;\n    uint16_t lfo_counter3;\n    uint8_t lfo_counter3_step;\n    uint8_t lfo_frq_update;\n    uint8_t lfo_clock;\n    uint8_t lfo_clock_lock;\n    uint8_t lfo_clock_test;\n    uint8_t lfo_test;\n    uint32_t lfo_val;\n    uint8_t lfo_val_carry;\n    uint32_t lfo_out1;\n    uint32_t lfo_out2;\n    uint32_t lfo_out2_b;\n    uint8_t lfo_mult_carry;\n    uint8_t lfo_trig_sign;\n    uint8_t lfo_saw_sign;\n    uint8_t lfo_bit_counter;\n\n    // Env Gen\n    uint8_t eg_state[32];\n    uint16_t eg_level[32];\n    uint8_t eg_rate[2];\n    uint8_t eg_sl[2];\n    uint8_t eg_tl[3];\n    uint8_t eg_zr[2];\n    uint8_t eg_timershift_lock;\n    uint8_t eg_timer_lock;\n    uint8_t eg_inchi;\n    uint8_t eg_shift;\n    uint8_t eg_clock;\n    uint8_t eg_clockcnt;\n    uint8_t eg_clockquotinent;\n    uint8_t eg_inc;\n    uint8_t eg_ratemax[2];\n    uint8_t eg_instantattack;\n    uint8_t eg_inclinear;\n    uint8_t eg_incattack;\n    uint8_t eg_mute;\n    uint16_t eg_outtemp[2];\n    uint16_t eg_out[2];\n    uint8_t eg_am;\n    uint8_t eg_ams[2];\n    uint8_t eg_timercarry;\n    uint32_t eg_timer;\n    uint32_t eg_timer2;\n    uint8_t eg_timerbstop;\n    uint32_t eg_serial;\n    uint8_t eg_serial_bit;\n    uint8_t eg_test;\n    \n\n    // Phase Gen\n    uint16_t pg_fnum[32];\n    uint8_t pg_kcode[32];\n    uint32_t pg_inc[32];\n    uint32_t pg_phase[32];\n    uint8_t pg_reset[32];\n    uint8_t pg_reset_latch[32];\n    uint32_t pg_serial;\n\n    // Operator\n    uint16_t op_phase_in;\n    uint16_t op_mod_in;\n    uint16_t op_phase;\n    uint16_t op_logsin[3];\n    uint16_t op_atten;\n    uint16_t op_exp[2];\n    uint8_t op_pow[2];\n    uint32_t op_sign;\n    int16_t op_out[6];\n    uint32_t op_connect;\n    uint8_t op_counter;\n    uint8_t op_fbupdate;\n    uint8_t op_fbshift;\n    uint8_t op_c1update;\n    uint8_t op_modtable[5];\n    int16_t op_m1[8][2];\n    int16_t op_c1[8];\n    int16_t op_mod[3];\n    int16_t op_fb[2];\n    uint8_t op_mixl;\n    uint8_t op_mixr;\n\n    // Mixer\n\n    int32_t mix[2];\n    int32_t mix2[2];\n    int32_t mix_op;\n    uint32_t mix_serial[2];\n    uint32_t mix_bits;\n    uint32_t mix_top_bits_lock;\n    uint8_t mix_sign_lock;\n    uint8_t mix_sign_lock2;\n    uint8_t mix_exp_lock;\n    uint8_t mix_clamp_low[2];\n    uint8_t mix_clamp_high[2];\n    uint8_t mix_out_bit;\n\n    // Output\n    uint8_t smp_so;\n    uint8_t smp_sh1;\n    uint8_t smp_sh2;\n\n    // Noise\n    uint32_t noise_lfsr;\n    uint32_t noise_timer;\n    uint8_t noise_timer_of;\n    uint8_t noise_update;\n    uint8_t noise_temp;\n\n    // Register set\n    uint8_t mode_test[8];\n    uint8_t mode_kon_operator[4];\n    uint8_t mode_kon_channel;\n\n    uint8_t reg_address;\n    uint8_t reg_address_ready;\n    uint8_t reg_data;\n    uint8_t reg_data_ready;\n\n    uint8_t ch_rl[8];\n    uint8_t ch_fb[8];\n    uint8_t ch_connect[8];\n    uint8_t ch_kc[8];\n    uint8_t ch_kf[8];\n    uint8_t ch_pms[8];\n    uint8_t ch_ams[8];\n\n    uint8_t sl_dt1[32];\n    uint8_t sl_mul[32];\n    uint8_t sl_tl[32];\n    uint8_t sl_ks[32];\n    uint8_t sl_ar[32];\n    uint8_t sl_am_e[32];\n    uint8_t sl_d1r[32];\n    uint8_t sl_dt2[32];\n    uint8_t sl_d2r[32];\n    uint8_t sl_d1l[32];\n    uint8_t sl_rr[32];\n\n    uint8_t noise_en;\n    uint8_t noise_freq;\n\n\n    // Timer\n    uint16_t timer_a_reg;\n    uint8_t timer_b_reg;\n    uint8_t timer_a_temp;\n    uint8_t timer_a_do_reset, timer_a_do_load;\n    uint8_t timer_a_inc;\n    uint16_t timer_a_val;\n    uint8_t timer_a_of;\n    uint8_t timer_a_load;\n    uint8_t timer_a_status;\n\n    uint8_t timer_b_sub;\n    uint8_t timer_b_sub_of;\n    uint8_t timer_b_inc;\n    uint16_t timer_b_val;\n    uint8_t timer_b_of;\n    uint8_t timer_b_do_reset, timer_b_do_load;\n    uint8_t timer_b_temp;\n    uint8_t timer_b_status;\n    uint8_t timer_irq;\n\n    uint8_t lfo_freq_hi;\n    uint8_t lfo_freq_lo;\n    uint8_t lfo_pmd;\n    uint8_t lfo_amd;\n    uint8_t lfo_wave;\n\n    uint8_t timer_irqa, timer_irqb;\n    uint8_t timer_loada, timer_loadb;\n    uint8_t timer_reseta, timer_resetb;\n    uint8_t mode_csm;\n\n    uint8_t nc_active, nc_active_lock, nc_sign, nc_sign_lock, nc_sign_lock2;\n    uint8_t nc_bit;\n    uint16_t nc_out;\n    int16_t op_mix;\n\n    uint8_t kon_csm, kon_csm_lock;\n    uint8_t kon_do;\n    uint8_t kon_chanmatch;\n    uint8_t kon[32];\n    uint8_t kon2[32];\n    uint8_t mode_kon[32];\n\n    // DAC\n    uint8_t dac_osh1, dac_osh2;\n    uint16_t dac_bits;\n    int32_t dac_output[2];\n\n    uint32_t mute[8];\n    int32_t rateratio;\n    int32_t samplecnt;\n    int32_t oldsamples[2];\n    int32_t samples[2];\n\n    uint64_t writebuf_samplecnt;\n    uint32_t writebuf_cur;\n    uint32_t writebuf_last;\n    uint64_t writebuf_lasttime;\n    opm_writebuf writebuf[OPN_WRITEBUF_SIZE];\n} opm_t;\n\nvoid OPM_GenerateStream(opm_t *chip, int32_t **sndptr, uint32_t numsamples);\nvoid OPM_Reset(opm_t* chip, uint32_t rate, uint32_t clock);\nvoid OPM_WriteBuffered(opm_t* chip, uint32_t port, uint8_t data);\nvoid OPM_SetMute(opm_t *chip, uint32_t mute);\n#endif\n"
  },
  {
    "path": "VGMPlay/chips/panning.c",
    "content": "#include <stdlib.h>\n#include <math.h>\n#include \"panning.h\"\n\n#ifndef PI\n#define PI 3.14159265359\n#endif\n#ifndef SQRT2\n#define SQRT2 1.414213562\n#endif\n#define RANGE 512\n\n//-----------------------------------------------------------------\n// Set the panning values for the two stereo channels (L,R)\n// for a position -256..0..256 L..C..R\n//-----------------------------------------------------------------\nvoid calc_panning(float channels[2], int position)\n{\n\tif ( position > RANGE / 2 )\n\t\tposition = RANGE / 2;\n\telse if ( position < -RANGE / 2 )\n\t\tposition = -RANGE / 2;\n\tposition += RANGE / 2;\t// make -256..0..256 -> 0..256..512\n\t\n\t// Equal power law: equation is\n\t// right = sin( position / range * pi / 2) * sqrt( 2 )\n\t// left is equivalent to right with position = range - position\n\t// position is in the range 0 .. RANGE\n\t// RANGE / 2 = centre, result = 1.0f\n\tchannels[1] = (float)( sin( (double)position / RANGE * PI / 2 ) * SQRT2 );\n\tposition = RANGE - position;\n\tchannels[0] = (float)( sin( (double)position / RANGE * PI / 2 ) * SQRT2 );\n}\n\n//-----------------------------------------------------------------\n// Reset the panning values to the centre position\n//-----------------------------------------------------------------\nvoid centre_panning(float channels[2])\n{\n\tchannels[0] = channels[1] = 1.0f;\n}\n\n/*//-----------------------------------------------------------------\n// Generate a stereo position in the range 0..RANGE\n// with Gaussian distribution, mean RANGE/2, S.D. RANGE/5\n//-----------------------------------------------------------------\nint random_stereo()\n{\n\tint n = (int)(RANGE/2 + gauss_rand() * (RANGE * 0.2) );\n\tif ( n > RANGE ) n = RANGE;\n\tif ( n < 0 ) n = 0;\n\treturn n;\n}\n\n//-----------------------------------------------------------------\n// Generate a Gaussian random number with mean 0, variance 1\n// Copied from an ancient C newsgroup FAQ\n//-----------------------------------------------------------------\ndouble gauss_rand()\n{\n\tstatic double V1, V2, S;\n\tstatic int phase = 0;\n\tdouble X;\n\n\tif(phase == 0) {\n\t\tdo {\n\t\t\tdouble U1 = (double)rand() / RAND_MAX;\n\t\t\tdouble U2 = (double)rand() / RAND_MAX;\n\n\t\t\tV1 = 2 * U1 - 1;\n\t\t\tV2 = 2 * U2 - 1;\n\t\t\tS = V1 * V1 + V2 * V2;\n\t\t\t} while(S >= 1 || S == 0);\n\n\t\tX = V1 * sqrt(-2 * log(S) / S);\n\t} else\n\t\tX = V2 * sqrt(-2 * log(S) / S);\n\n\tphase = 1 - phase;\n\n\treturn X;\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/panning.h",
    "content": "/*\n\tpanning.h by Maxim in 2006\n\tImplements \"simple equal power\" panning using sine distribution\n\tI am not an expert on this stuff, but this is the best sounding of the methods I've tried\n*/\n\n#ifndef PANNING_H\n#define PANNING_H\n\nvoid calc_panning(float channels[2], int position);\nvoid centre_panning(float channels[2]);\n\n#endif"
  },
  {
    "path": "VGMPlay/chips/pokey.c",
    "content": "/*****************************************************************************\n *\n *  POKEY chip emulator 4.51\n *  Copyright Nicola Salmoria and the MAME Team\n *\n *  Based on original info found in Ron Fries' Pokey emulator,\n *  with additions by Brad Oliver, Eric Smith and Juergen Buchmueller,\n *  paddle (a/d conversion) details from the Atari 400/800 Hardware Manual.\n *  Polynome algorithms according to info supplied by Perry McFarlane.\n *\n *  This code is subject to the MAME license, which besides other\n *  things means it is distributed as is, no warranties whatsoever.\n *  For more details read mame.txt that comes with MAME.\n *\n *  4.51:\n *  - changed to use the attotime datatype\n *  4.5:\n *  - changed the 9/17 bit polynomial formulas such that the values\n *    required for the Tempest Pokey protection will be found.\n *    Tempest expects the upper 4 bits of the RNG to appear in the\n *    lower 4 bits after four cycles, so there has to be a shift\n *    of 1 per cycle (which was not the case before). Bits #6-#13 of the\n *    new RNG give this expected result now, bits #0-7 of the 9 bit poly.\n *  - reading the RNG returns the shift register contents ^ 0xff.\n *    That way resetting the Pokey with SKCTL (which resets the\n *    polynome shifters to 0) returns the expected 0xff value.\n *  4.4:\n *  - reversed sample values to make OFF channels produce a zero signal.\n *    actually de-reversed them; don't remember that I reversed them ;-/\n *  4.3:\n *  - for POT inputs returning zero, immediately assert the ALLPOT\n *    bit after POTGO is written, otherwise start trigger timer\n *    depending on SK_PADDLE mode, either 1-228 scanlines or 1-2\n *    scanlines, depending on the SK_PADDLE bit of SKCTL.\n *  4.2:\n *  - half volume for channels which are inaudible (this should be\n *    close to the real thing).\n *  4.1:\n *  - default gain increased to closely match the old code.\n *  - random numbers repeat rate depends on POLY9 flag too!\n *  - verified sound output with many, many Atari 800 games,\n *    including the SUPPRESS_INAUDIBLE optimizations.\n *  4.0:\n *  - rewritten from scratch.\n *  - 16bit stream interface.\n *  - serout ready/complete delayed interrupts.\n *  - reworked pot analog/digital conversion timing.\n *  - optional non-indexing pokey update functions.\n *\n *****************************************************************************/\n\n#include \"mamedef.h\"\n//#include \"emu.h\"\n#ifdef _DEBUG\n#include <stdio.h>\n#endif\n#include \"pokey.h\"\n\n/*\n * Defining this produces much more (about twice as much)\n * but also more efficient code. Ideally this should be set\n * for processors with big code cache and for healthy compilers :)\n */\n#ifndef BIG_SWITCH\n#ifndef HEAVY_MACRO_USAGE\n#define HEAVY_MACRO_USAGE   1\n#endif\n#else\n#define HEAVY_MACRO_USAGE\tBIG_SWITCH\n#endif\n\n#define SUPPRESS_INAUDIBLE\t1\n\n/* Four channels with a range of 0..32767 and volume 0..15 */\n//#define POKEY_DEFAULT_GAIN (32767/15/4)\n\n/*\n * But we raise the gain and risk clipping, the old Pokey did\n * this too. It defined POKEY_DEFAULT_GAIN 6 and this was\n * 6 * 15 * 4 = 360, 360/256 = 1.40625\n * I use 15/11 = 1.3636, so this is a little lower.\n */\n#define POKEY_DEFAULT_GAIN (32767/11/4)\n\n#define VERBOSE \t\t0\n#define VERBOSE_SOUND\t0\n#define VERBOSE_TIMER\t0\n#define VERBOSE_POLY\t0\n#define VERBOSE_RAND\t0\n\n#define LOG(x) do { if (VERBOSE) logerror x; } while (0)\n\n#define LOG_SOUND(x) do { if (VERBOSE_SOUND) logerror x; } while (0)\n\n#define LOG_TIMER(x) do { if (VERBOSE_TIMER) logerror x; } while (0)\n\n#define LOG_POLY(x) do { if (VERBOSE_POLY) logerror x; } while (0)\n\n#define LOG_RAND(x) do { if (VERBOSE_RAND) logerror x; } while (0)\n\n#define CHAN1\t0\n#define CHAN2\t1\n#define CHAN3\t2\n#define CHAN4\t3\n\n#define TIMER1\t0\n#define TIMER2\t1\n#define TIMER4\t2\n\n/* values to add to the divisors for the different modes */\n#define DIVADD_LOCLK\t\t1\n#define DIVADD_HICLK\t\t4\n#define DIVADD_HICLK_JOINED 7\n\n/* AUDCx */\n#define NOTPOLY5\t0x80\t/* selects POLY5 or direct CLOCK */\n#define POLY4\t\t0x40\t/* selects POLY4 or POLY17 */\n#define PURE\t\t0x20\t/* selects POLY4/17 or PURE tone */\n#define VOLUME_ONLY 0x10\t/* selects VOLUME OUTPUT ONLY */\n#define VOLUME_MASK 0x0f\t/* volume mask */\n\n/* AUDCTL */\n#define POLY9\t\t0x80\t/* selects POLY9 or POLY17 */\n#define CH1_HICLK\t0x40\t/* selects 1.78979 MHz for Ch 1 */\n#define CH3_HICLK\t0x20\t/* selects 1.78979 MHz for Ch 3 */\n#define CH12_JOINED 0x10\t/* clocks channel 1 w/channel 2 */\n#define CH34_JOINED 0x08\t/* clocks channel 3 w/channel 4 */\n#define CH1_FILTER\t0x04\t/* selects channel 1 high pass filter */\n#define CH2_FILTER\t0x02\t/* selects channel 2 high pass filter */\n#define CLK_15KHZ\t0x01\t/* selects 15.6999 kHz or 63.9211 kHz */\n\n/* IRQEN (D20E) */\n#define IRQ_BREAK\t0x80\t/* BREAK key pressed interrupt */\n#define IRQ_KEYBD\t0x40\t/* keyboard data ready interrupt */\n#define IRQ_SERIN\t0x20\t/* serial input data ready interrupt */\n#define IRQ_SEROR\t0x10\t/* serial output register ready interrupt */\n#define IRQ_SEROC\t0x08\t/* serial output complete interrupt */\n#define IRQ_TIMR4\t0x04\t/* timer channel #4 interrupt */\n#define IRQ_TIMR2\t0x02\t/* timer channel #2 interrupt */\n#define IRQ_TIMR1\t0x01\t/* timer channel #1 interrupt */\n\n/* SKSTAT (R/D20F) */\n#define SK_FRAME\t0x80\t/* serial framing error */\n#define SK_OVERRUN\t0x40\t/* serial overrun error */\n#define SK_KBERR\t0x20\t/* keyboard overrun error */\n#define SK_SERIN\t0x10\t/* serial input high */\n#define SK_SHIFT\t0x08\t/* shift key pressed */\n#define SK_KEYBD\t0x04\t/* keyboard key pressed */\n#define SK_SEROUT\t0x02\t/* serial output active */\n\n/* SKCTL (W/D20F) */\n#define SK_BREAK\t0x80\t/* serial out break signal */\n#define SK_BPS\t\t0x70\t/* bits per second */\n#define SK_FM\t\t0x08\t/* FM mode */\n#define SK_PADDLE\t0x04\t/* fast paddle a/d conversion */\n#define SK_RESET\t0x03\t/* reset serial/keyboard interface */\n\n#define DIV_64\t\t28\t\t /* divisor for 1.78979 MHz clock to 63.9211 kHz */\n#define DIV_15\t\t114 \t /* divisor for 1.78979 MHz clock to 15.6999 kHz */\n\ntypedef struct _pokey_state pokey_state;\nstruct _pokey_state\n{\n\tINT32 counter[4];\t\t/* channel counter */\n\tINT32 divisor[4];\t\t/* channel divisor (modulo value) */\n\tUINT32 volume[4];\t\t/* channel volume - derived */\n\tUINT8 output[4];\t\t/* channel output signal (1 active, 0 inactive) */\n\tUINT8 audible[4];\t\t/* channel plays an audible tone/effect */\n\tUINT8 Muted[4];\n\tUINT32 samplerate_24_8; /* sample rate in 24.8 format */\n\tUINT32 samplepos_fract; /* sample position fractional part */\n\tUINT32 samplepos_whole; /* sample position whole part */\n\tUINT32 polyadjust;\t\t/* polynome adjustment */\n\tUINT32 p4;              /* poly4 index */\n\tUINT32 p5;              /* poly5 index */\n\tUINT32 p9;              /* poly9 index */\n\tUINT32 p17;             /* poly17 index */\n\tUINT32 r9;\t\t\t\t/* rand9 index */\n\tUINT32 r17;             /* rand17 index */\n\tUINT32 clockmult;\t\t/* clock multiplier */\n\t//device_t *device;\n\t//sound_stream * channel; /* streams channel */\n\t//emu_timer *timer[3];\t/* timers for channel 1,2 and 4 events */\n\t//attotime timer_period[3];\t/* computed periods for these timers */\n\t//int timer_param[3];\t\t/* computed parameters for these timers */\n\t//emu_timer *rtimer;     /* timer for calculating the random offset */\n\t//emu_timer *ptimer[8];\t/* pot timers */\n\t//devcb_resolved_read8 pot_r[8];\n\t//devcb_resolved_read8 allpot_r;\n\t//devcb_resolved_read8 serin_r;\n\t//devcb_resolved_write8 serout_w;\n\t//void (*interrupt_cb)(device_t *device, int mask);\n\tUINT8 AUDF[4];          /* AUDFx (D200, D202, D204, D206) */\n\tUINT8 AUDC[4];\t\t\t/* AUDCx (D201, D203, D205, D207) */\n\tUINT8 POTx[8];\t\t\t/* POTx   (R/D200-D207) */\n\tUINT8 AUDCTL;\t\t\t/* AUDCTL (W/D208) */\n\tUINT8 ALLPOT;\t\t\t/* ALLPOT (R/D208) */\n\tUINT8 KBCODE;\t\t\t/* KBCODE (R/D209) */\n\tUINT8 RANDOM;\t\t\t/* RANDOM (R/D20A) */\n\tUINT8 SERIN;\t\t\t/* SERIN  (R/D20D) */\n\tUINT8 SEROUT;\t\t\t/* SEROUT (W/D20D) */\n\tUINT8 IRQST;\t\t\t/* IRQST  (R/D20E) */\n\tUINT8 IRQEN;\t\t\t/* IRQEN  (W/D20E) */\n\tUINT8 SKSTAT;\t\t\t/* SKSTAT (R/D20F) */\n\tUINT8 SKCTL;\t\t\t/* SKCTL  (W/D20F) */\n\t//pokey_interface intf;\n\t//attotime clock_period;\n\tdouble clock_period;\n\t//attotime ad_time_fast;\n\t//attotime ad_time_slow;\n\n\tUINT8 poly4[0x0f];\n\tUINT8 poly5[0x1f];\n\tUINT8 poly9[0x1ff];\n\tUINT8 poly17[0x1ffff];\n\n\tUINT8 rand9[0x1ff];\n\tUINT8 rand17[0x1ffff];\n};\n\n\n#define P4(chip)  chip->poly4[chip->p4]\n#define P5(chip)  chip->poly5[chip->p5]\n#define P9(chip)  chip->poly9[chip->p9]\n#define P17(chip) chip->poly17[chip->p17]\n\n//static TIMER_CALLBACK( pokey_timer_expire );\n//static TIMER_CALLBACK( pokey_pot_trigger );\n\n\n#define SAMPLE\t-1\n\n#define ADJUST_EVENT(chip)\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tchip->counter[CHAN1] -= event;\t\t\t\t\t\t\t\t\t\t\\\n\tchip->counter[CHAN2] -= event;\t\t\t\t\t\t\t\t\t\t\\\n\tchip->counter[CHAN3] -= event;\t\t\t\t\t\t\t\t\t\t\\\n\tchip->counter[CHAN4] -= event;\t\t\t\t\t\t\t\t\t\t\\\n\tchip->samplepos_whole -= event;\t\t\t\t\t\t\t\t\t\t\\\n\tchip->polyadjust += event\n\n#if SUPPRESS_INAUDIBLE\n\n#define PROCESS_CHANNEL(chip,ch)                                        \\\n\tint toggle = 0; \t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tADJUST_EVENT(chip); \t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* reset the channel counter */ \t\t\t\t\t\t\t\t\t\\\n\tif( chip->audible[ch] )\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tchip->counter[ch] = chip->divisor[ch];\t\t\t\t\t\t\t\\\n\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tchip->counter[ch] = 0x7fffffff;\t\t\t\t\t\t\t\t\t\\\n\tchip->p4 = (chip->p4+chip->polyadjust)%0x0000f;\t\t\t\t\t\t\\\n\tchip->p5 = (chip->p5+chip->polyadjust)%0x0001f;\t\t\t\t\t\t\\\n\tchip->p9 = (chip->p9+chip->polyadjust)%0x001ff;\t\t\t\t\t\t\\\n\tchip->p17 = (chip->p17+chip->polyadjust)%0x1ffff;\t\t\t\t\t\\\n\tchip->polyadjust = 0;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif( (chip->AUDC[ch] & NOTPOLY5) || P5(chip) )\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->AUDC[ch] & PURE )\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttoggle = 1; \t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->AUDC[ch] & POLY4 )\t\t\t\t\t\t\t\t\t\\\n\t\t\ttoggle = chip->output[ch] == !P4(chip);\t\t\t\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->AUDCTL & POLY9 )\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttoggle = chip->output[ch] == !P9(chip);\t\t\t\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttoggle = chip->output[ch] == !P17(chip);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif( toggle )\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->audible[ch] && ! chip->Muted[ch] )\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tif( chip->output[ch] )\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tsum -= chip->volume[ch];\t\t\t\t\t\t\t\t\\\n\t\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tsum += chip->volume[ch];\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tchip->output[ch] ^= 1;\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* is this a filtering channel (3/4) and is the filter active? */\t\\\n\tif( chip->AUDCTL & ((CH1_FILTER|CH2_FILTER) & (0x10 >> ch)) )\t\t\\\n    {                                                                   \\\n\t\tif( chip->output[ch-2] )\t\t\t\t\t\t\t\t\t\t\\\n        {                                                               \\\n\t\t\tchip->output[ch-2] = 0;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tif( chip->audible[ch] && ! chip->Muted[ch] )\t\t\t\t\\\n\t\t\t\tsum -= chip->volume[ch-2];\t\t\t\t\t\t\t\t\\\n        }                                                               \\\n    }                                                                   \\\n\n#else\n\n#define PROCESS_CHANNEL(chip,ch)                                        \\\n\tint toggle = 0; \t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tADJUST_EVENT(chip); \t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* reset the channel counter */ \t\t\t\t\t\t\t\t\t\\\n\tchip->counter[ch] = p[chip].divisor[ch];\t\t\t\t\t\t\t\\\n\tchip->p4 = (chip->p4+chip->polyadjust)%0x0000f;\t\t\t\t\t\t\\\n\tchip->p5 = (chip->p5+chip->polyadjust)%0x0001f;\t\t\t\t\t\t\\\n\tchip->p9 = (chip->p9+chip->polyadjust)%0x001ff;\t\t\t\t\t\t\\\n\tchip->p17 = (chip->p17+chip->polyadjust)%0x1ffff;\t\t\t\t\t\\\n\tchip->polyadjust = 0;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif( (chip->AUDC[ch] & NOTPOLY5) || P5(chip) )\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->AUDC[ch] & PURE )\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttoggle = 1; \t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->AUDC[ch] & POLY4 )\t\t\t\t\t\t\t\t\t\\\n\t\t\ttoggle = chip->output[ch] == !P4(chip);\t\t\t\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->AUDCTL & POLY9 )\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttoggle = chip->output[ch] == !P9(chip);\t\t\t\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttoggle = chip->output[ch] == !P17(chip);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif( toggle && ! chip->Muted[ch] )\t\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->output[ch] )\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tsum -= chip->volume[ch];\t\t\t\t\t\t\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tsum += chip->volume[ch];\t\t\t\t\t\t\t\t\t\\\n\t\tchip->output[ch] ^= 1;\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* is this a filtering channel (3/4) and is the filter active? */\t\\\n\tif( chip->AUDCTL & ((CH1_FILTER|CH2_FILTER) & (0x10 >> ch)) )\t\t\\\n    {                                                                   \\\n\t\tif( chip->output[ch-2] && ! chip->Muted[ch] )\t\t\t\t\t\\\n        {                                                               \\\n\t\t\tchip->output[ch-2] = 0;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tsum -= chip->volume[ch-2];\t\t\t\t\t\t\t\t\t\\\n        }                                                               \\\n    }                                                                   \\\n\n#endif\n\n#define PROCESS_SAMPLE(chip)                                            \\\n    ADJUST_EVENT(chip);                                                 \\\n    /* adjust the sample position */                                    \\\n\tchip->samplepos_whole++;\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* store sum of output signals into the buffer */\t\t\t\t\t\\\n/*\t*buffer++ = (sum > 0x7fff) ? 0x7fff : sum;\t*/\t\t\t\t\t\t\\\n\t*bufL++ = *bufR++ = sum;\t\t\t\t\t\t\t\t\t\t\t\\\n\tsamples--\n\n#if HEAVY_MACRO_USAGE\n\n/*\n * This version of PROCESS_POKEY repeats the search for the minimum\n * event value without using an index to the channel. That way the\n * PROCESS_CHANNEL macros can be called with fixed values and expand\n * to much more efficient code\n */\n\n#define PROCESS_POKEY(chip) \t\t\t\t\t\t\t\t\t\t\t\\\n\tUINT32 sum = 0; \t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif( chip->output[CHAN1] && ! chip->Muted[CHAN1] )\t\t\t\t\t\\\n\t\tsum += chip->volume[CHAN1];\t\t\t\t\t\t\t\t\t\t\\\n\tif( chip->output[CHAN2] && ! chip->Muted[CHAN2] )\t\t\t\t\t\\\n\t\tsum += chip->volume[CHAN2];\t\t\t\t\t\t\t\t\t\t\\\n\tif( chip->output[CHAN3] && ! chip->Muted[CHAN3] )\t\t\t\t\t\\\n\t\tsum += chip->volume[CHAN3];\t\t\t\t\t\t\t\t\t\t\\\n\tif( chip->output[CHAN4] && ! chip->Muted[CHAN4] )\t\t\t\t\t\\\n\t\tsum += chip->volume[CHAN4];\t\t\t\t\t\t\t\t\t\t\\\n    while( samples > 0 )                                                \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->counter[CHAN1] < chip->samplepos_whole )\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tif( chip->counter[CHAN2] <  chip->counter[CHAN1] )\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tif( chip->counter[CHAN3] <  chip->counter[CHAN2] )\t\t\\\n\t\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\tif( chip->counter[CHAN4] < chip->counter[CHAN3] )\t\\\n\t\t\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\tUINT32 event = chip->counter[CHAN4];\t\t\t\\\n                        PROCESS_CHANNEL(chip,CHAN4);                    \\\n\t\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\tUINT32 event = chip->counter[CHAN3];\t\t\t\\\n                        PROCESS_CHANNEL(chip,CHAN3);                    \\\n\t\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tif( chip->counter[CHAN4] < chip->counter[CHAN2] )\t\t\\\n\t\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\tUINT32 event = chip->counter[CHAN4];\t\t\t\t\\\n                    PROCESS_CHANNEL(chip,CHAN4);                        \\\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n                else                                                    \\\n\t\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\tUINT32 event = chip->counter[CHAN2];\t\t\t\t\\\n                    PROCESS_CHANNEL(chip,CHAN2);                        \\\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n            }                                                           \\\n\t\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tif( chip->counter[CHAN3] < chip->counter[CHAN1] )\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tif( chip->counter[CHAN4] < chip->counter[CHAN3] )\t\t\\\n\t\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\tUINT32 event = chip->counter[CHAN4];\t\t\t\t\\\n                    PROCESS_CHANNEL(chip,CHAN4);                        \\\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n                else                                                    \\\n\t\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\tUINT32 event = chip->counter[CHAN3];\t\t\t\t\\\n                    PROCESS_CHANNEL(chip,CHAN3);                        \\\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n            }                                                           \\\n\t\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tif( chip->counter[CHAN4] < chip->counter[CHAN1] )\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tUINT32 event = chip->counter[CHAN4];\t\t\t\t\t\\\n                PROCESS_CHANNEL(chip,CHAN4);                            \\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n            else                                                        \\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tUINT32 event = chip->counter[CHAN1];\t\t\t\t\t\\\n                PROCESS_CHANNEL(chip,CHAN1);                            \\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->counter[CHAN2] < chip->samplepos_whole )\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tif( chip->counter[CHAN3] < chip->counter[CHAN2] )\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tif( chip->counter[CHAN4] < chip->counter[CHAN3] )\t\t\\\n\t\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\tUINT32 event = chip->counter[CHAN4];\t\t\t\t\\\n                    PROCESS_CHANNEL(chip,CHAN4);                        \\\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\tUINT32 event = chip->counter[CHAN3];\t\t\t\t\\\n                    PROCESS_CHANNEL(chip,CHAN3);                        \\\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tif( chip->counter[CHAN4] < chip->counter[CHAN2] )\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tUINT32 event = chip->counter[CHAN4];\t\t\t\t\t\\\n                PROCESS_CHANNEL(chip,CHAN4);                            \\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tUINT32 event = chip->counter[CHAN2];\t\t\t\t\t\\\n                PROCESS_CHANNEL(chip,CHAN2);                            \\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->counter[CHAN3] < chip->samplepos_whole )\t\t\t\t\\\n        {                                                               \\\n\t\t\tif( chip->counter[CHAN4] < chip->counter[CHAN3] )\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tUINT32 event = chip->counter[CHAN4];\t\t\t\t\t\\\n                PROCESS_CHANNEL(chip,CHAN4);                            \\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tUINT32 event = chip->counter[CHAN3];\t\t\t\t\t\\\n                PROCESS_CHANNEL(chip,CHAN3);                            \\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->counter[CHAN4] < chip->samplepos_whole )\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tUINT32 event = chip->counter[CHAN4];\t\t\t\t\t\t\\\n            PROCESS_CHANNEL(chip,CHAN4);                                \\\n        }                                                               \\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tUINT32 event = chip->samplepos_whole;\t\t\t\t\t\t\\\n\t\t\tPROCESS_SAMPLE(chip);\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tchip->rtimer->adjust(attotime::never)*/\n\n#else   /* no HEAVY_MACRO_USAGE */\n/*\n * And this version of PROCESS_POKEY uses event and channel variables\n * so that the PROCESS_CHANNEL macro needs to index memory at runtime.\n */\n\n#define PROCESS_POKEY(chip)                                             \\\n\tUINT32 sum = 0; \t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif( chip->output[CHAN1] && ! chip->Muted[CHAN1] )\t\t\t\t\t\\\n\t\tsum += chip->volume[CHAN1];\t\t\t\t\t\t\t\t\t\t\\\n\tif( chip->output[CHAN2] && ! chip->Muted[CHAN2] )\t\t\t\t\t\\\n\t\tsum += chip->volume[CHAN2];\t\t\t\t\t\t\t\t\t\t\\\n\tif( chip->output[CHAN3] && ! chip->Muted[CHAN3] )\t\t\t\t\t\\\n\t\tsum += chip->volume[CHAN3];\t\t\t\t\t\t\t\t\t\t\\\n\tif( chip->output[CHAN4] && ! chip->Muted[CHAN4] )\t\t\t\t\t\\\n        sum += chip->volume[CHAN4];                                     \\\n\twhile( samples > 0 )                                                \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tUINT32 event = chip->samplepos_whole;\t\t\t\t\t\t\t\\\n\t\tUINT32 channel = SAMPLE;\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->counter[CHAN1] < event )\t\t\t\t\t\t\t\t\\\n        {                                                               \\\n\t\t\tevent = chip->counter[CHAN1];\t\t\t\t\t\t\t\t\\\n\t\t\tchannel = CHAN1;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif( chip->counter[CHAN2] < event )\t\t\t\t\t\t\t\t\\\n        {                                                               \\\n\t\t\tevent = chip->counter[CHAN2];\t\t\t\t\t\t\t\t\\\n\t\t\tchannel = CHAN2;\t\t\t\t\t\t\t\t\t\t\t\\\n        }                                                               \\\n\t\tif( chip->counter[CHAN3] < event )\t\t\t\t\t\t\t\t\\\n        {                                                               \\\n\t\t\tevent = chip->counter[CHAN3];\t\t\t\t\t\t\t\t\\\n\t\t\tchannel = CHAN3;\t\t\t\t\t\t\t\t\t\t\t\\\n        }                                                               \\\n\t\tif( chip->counter[CHAN4] < event )\t\t\t\t\t\t\t\t\\\n        {                                                               \\\n\t\t\tevent = chip->counter[CHAN4];\t\t\t\t\t\t\t\t\\\n\t\t\tchannel = CHAN4;\t\t\t\t\t\t\t\t\t\t\t\\\n        }                                                               \\\n        if( channel == SAMPLE )                                         \\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n            PROCESS_SAMPLE(chip);                                       \\\n        }                                                               \\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tPROCESS_CHANNEL(chip,channel);\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tchip->rtimer->adjust(attotime::never)*/\n\n#endif\n\n\n/*INLINE pokey_state *get_safe_token(device_t *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == POKEY);\n\treturn (pokey_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n\n#define MAX_CHIPS\t0x02\nstatic pokey_state PokeyData[MAX_CHIPS];\n\n//static STREAM_UPDATE( pokey_update )\nvoid pokey_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//pokey_state *chip = (pokey_state *)param;\n\tpokey_state *chip = &PokeyData[ChipID];\n\t//stream_sample_t *buffer = outputs[0];\n\tstream_sample_t *bufL = outputs[0];\n\tstream_sample_t *bufR = outputs[1];\n\tPROCESS_POKEY(chip);\n}\n\n\nstatic void poly_init(UINT8 *poly, int size, int left, int right, int add)\n{\n\tint mask = (1 << size) - 1;\n    int i, x = 0;\n\n\tLOG_POLY((\"poly %d\\n\", size));\n\tfor( i = 0; i < mask; i++ )\n\t{\n\t\t*poly++ = x & 1;\n\t\tLOG_POLY((\"%05x: %d\\n\", x, x&1));\n        /* calculate next bit */\n\t\tx = ((x << left) + (x >> right) + add) & mask;\n\t}\n}\n\nstatic void rand_init(UINT8 *rng, int size, int left, int right, int add)\n{\n    int mask = (1 << size) - 1;\n    int i, x = 0;\n\n\tLOG_RAND((\"rand %d\\n\", size));\n    for( i = 0; i < mask; i++ )\n\t{\n\t\tif (size == 17)\n\t\t\t*rng = x >> 6;\t/* use bits 6..13 */\n\t\telse\n\t\t\t*rng = x;\t\t/* use bits 0..7 */\n        LOG_RAND((\"%05x: %02x\\n\", x, *rng));\n        rng++;\n        /* calculate next bit */\n\t\tx = ((x << left) + (x >> right) + add) & mask;\n\t}\n}\n\n\n/*static void register_for_save(pokey_state *chip, device_t *device)\n{\n\tdevice->save_item(NAME(chip->counter));\n\tdevice->save_item(NAME(chip->divisor));\n\tdevice->save_item(NAME(chip->volume));\n\tdevice->save_item(NAME(chip->output));\n\tdevice->save_item(NAME(chip->audible));\n\tdevice->save_item(NAME(chip->samplepos_fract));\n\tdevice->save_item(NAME(chip->samplepos_whole));\n\tdevice->save_item(NAME(chip->polyadjust));\n\tdevice->save_item(NAME(chip->p4));\n\tdevice->save_item(NAME(chip->p5));\n\tdevice->save_item(NAME(chip->p9));\n\tdevice->save_item(NAME(chip->p17));\n\tdevice->save_item(NAME(chip->r9));\n\tdevice->save_item(NAME(chip->r17));\n\tdevice->save_item(NAME(chip->clockmult));\n\tdevice->save_item(NAME(chip->timer_period[0]));\n\tdevice->save_item(NAME(chip->timer_period[1]));\n\tdevice->save_item(NAME(chip->timer_period[2]));\n\tdevice->save_item(NAME(chip->timer_param));\n\tdevice->save_item(NAME(chip->AUDF));\n\tdevice->save_item(NAME(chip->AUDC));\n\tdevice->save_item(NAME(chip->POTx));\n\tdevice->save_item(NAME(chip->AUDCTL));\n\tdevice->save_item(NAME(chip->ALLPOT));\n\tdevice->save_item(NAME(chip->KBCODE));\n\tdevice->save_item(NAME(chip->RANDOM));\n\tdevice->save_item(NAME(chip->SERIN));\n\tdevice->save_item(NAME(chip->SEROUT));\n\tdevice->save_item(NAME(chip->IRQST));\n\tdevice->save_item(NAME(chip->IRQEN));\n\tdevice->save_item(NAME(chip->SKSTAT));\n\tdevice->save_item(NAME(chip->SKCTL));\n}*/\n\n\n//static DEVICE_START( pokey )\nint device_start_pokey(UINT8 ChipID, int clock)\n{\n\t//pokey_state *chip = get_safe_token(device);\n\tpokey_state *chip;\n\t//int sample_rate = device->clock();\n\tint sample_rate = clock;\n\t//int i;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &PokeyData[ChipID];\n\t\n\t//if (device->static_config())\n\t//\tmemcpy(&chip->intf, device->static_config(), sizeof(pokey_interface));\n\t//chip->device = device;\n\t//chip->clock_period = attotime::from_hz(device->clock());\n\tchip->clock_period = 1.0 / clock;\n\n\t/* calculate the A/D times\n     * In normal, slow mode (SKCTL bit SK_PADDLE is clear) the conversion\n     * takes N scanlines, where N is the paddle value. A single scanline\n     * takes approximately 64us to finish (1.78979MHz clock).\n     * In quick mode (SK_PADDLE set) the conversion is done very fast\n     * (takes two scanlines) but the result is not as accurate.\n     */\n\t//chip->ad_time_fast = (attotime::from_nsec(64000*2/228) * FREQ_17_EXACT) / device->clock();\n\t//chip->ad_time_slow = (attotime::from_nsec(64000      ) * FREQ_17_EXACT) / device->clock();\n\n\t/* initialize the poly counters */\n\tpoly_init(chip->poly4,   4, 3, 1, 0x00004);\n\tpoly_init(chip->poly5,   5, 3, 2, 0x00008);\n\tpoly_init(chip->poly9,   9, 8, 1, 0x00180);\n\tpoly_init(chip->poly17, 17,16, 1, 0x1c000);\n\n\t/* initialize the random arrays */\n\trand_init(chip->rand9,   9, 8, 1, 0x00180);\n\trand_init(chip->rand17, 17,16, 1, 0x1c000);\n\n\t//chip->samplerate_24_8 = (device->clock() << 8) / sample_rate;\n\tchip->samplerate_24_8 = (clock << 8) / sample_rate;\n\tchip->divisor[CHAN1] = 4;\n\tchip->divisor[CHAN2] = 4;\n\tchip->divisor[CHAN3] = 4;\n\tchip->divisor[CHAN4] = 4;\n\tchip->clockmult = DIV_64;\n\tchip->KBCODE = 0x09;\t\t /* Atari 800 'no key' */\n\tchip->SKCTL = SK_RESET;\t /* let the RNG run after reset */\n\t//chip->rtimer = device->machine().scheduler().timer_alloc(FUNC_NULL);\n\n\t//chip->timer[0] = device->machine().scheduler().timer_alloc(FUNC(pokey_timer_expire), chip);\n\t//chip->timer[1] = device->machine().scheduler().timer_alloc(FUNC(pokey_timer_expire), chip);\n\t//chip->timer[2] = device->machine().scheduler().timer_alloc(FUNC(pokey_timer_expire), chip);\n\n\t/*for (i=0; i<8; i++)\n\t{\n\t\tchip->ptimer[i] = device->machine().scheduler().timer_alloc(FUNC(pokey_pot_trigger), chip);\n\t\tchip->pot_r[i].resolve(chip->intf.pot_r[i], *device);\n\t}\n\tchip->allpot_r.resolve(chip->intf.allpot_r, *device);\n\tchip->serin_r.resolve(chip->intf.serin_r, *device);\n\tchip->serout_w.resolve(chip->intf.serout_w, *device);\n\tchip->interrupt_cb = chip->intf.interrupt_cb;*/\n\n\t//chip->channel = device->machine().sound().stream_alloc(*device, 0, 1, sample_rate, chip, pokey_update);\n\n\t//register_for_save(chip, device);\n\t\n\treturn sample_rate;\n}\n\nvoid device_stop_pokey(UINT8 ChipID)\n{\n\tpokey_state *chip = &PokeyData[ChipID];\n\t\n\treturn;\n}\n\nvoid device_reset_pokey(UINT8 ChipID)\n{\n\tpokey_state *chip = &PokeyData[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 4; CurChn ++)\n\t{\n\t\tchip->counter[CurChn] = 0;\n\t\tchip->divisor[CurChn] = 4;\n\t\tchip->volume[CurChn] = 0;\n\t\tchip->output[CurChn] = 0;\n\t\tchip->audible[CurChn] = 0;\n\t}\n\tchip->samplepos_fract = 0;\n\tchip->samplepos_whole = 0;\n\tchip->polyadjust = 0;\n\tchip->p4 = 0;\n\tchip->p5 = 0;\n\tchip->p9 = 0;\n\tchip->p17 = 0;\n\tchip->r9 = 0;\n\tchip->r17 = 0;\n\tchip->clockmult = DIV_64;\n\t\n\treturn;\n}\n\n/*static TIMER_CALLBACK( pokey_timer_expire )\n{\n\tpokey_state *p = (pokey_state *)ptr;\n\tint timers = param;\n\n\tLOG_TIMER((\"POKEY #%p timer %d with IRQEN $%02x\\n\", p, timers, p->IRQEN));\n\n    // check if some of the requested timer interrupts are enabled //\n\ttimers &= p->IRQEN;\n\n    if( timers )\n    {\n\t\t// set the enabled timer irq status bits //\n\t\tp->IRQST |= timers;\n        // call back an application supplied function to handle the interrupt //\n\t\tif( p->interrupt_cb )\n\t\t\t(*p->interrupt_cb)(p->device, timers);\n    }\n}*/\n\n/*static char *audc2str(int val)\n{\n\tstatic char buff[80];\n\tif( val & NOTPOLY5 )\n\t{\n\t\tif( val & PURE )\n\t\t\tstrcpy(buff,\"pure\");\n\t\telse\n\t\tif( val & POLY4 )\n\t\t\tstrcpy(buff,\"poly4\");\n\t\telse\n\t\t\tstrcpy(buff,\"poly9/17\");\n\t}\n\telse\n\t{\n\t\tif( val & PURE )\n\t\t\tstrcpy(buff,\"poly5\");\n\t\telse\n\t\tif( val & POLY4 )\n\t\t\tstrcpy(buff,\"poly4+poly5\");\n\t\telse\n\t\t\tstrcpy(buff,\"poly9/17+poly5\");\n    }\n\treturn buff;\n}\n\nstatic char *audctl2str(int val)\n{\n\tstatic char buff[80];\n\tif( val & POLY9 )\n\t\tstrcpy(buff,\"poly9\");\n\telse\n\t\tstrcpy(buff,\"poly17\");\n\tif( val & CH1_HICLK )\n\t\tstrcat(buff,\"+ch1hi\");\n\tif( val & CH3_HICLK )\n\t\tstrcat(buff,\"+ch3hi\");\n\tif( val & CH12_JOINED )\n\t\tstrcat(buff,\"+ch1/2\");\n\tif( val & CH34_JOINED )\n\t\tstrcat(buff,\"+ch3/4\");\n\tif( val & CH1_FILTER )\n\t\tstrcat(buff,\"+ch1filter\");\n\tif( val & CH2_FILTER )\n\t\tstrcat(buff,\"+ch2filter\");\n\tif( val & CLK_15KHZ )\n\t\tstrcat(buff,\"+clk15\");\n    return buff;\n}*/\n\n/*static TIMER_CALLBACK( pokey_serin_ready_cb )\n{\n\tpokey_state *p = (pokey_state *)ptr;\n    if( p->IRQEN & IRQ_SERIN )\n\t{\n\t\t// set the enabled timer irq status bits //\n\t\tp->IRQST |= IRQ_SERIN;\n\t\t// call back an application supplied function to handle the interrupt //\n\t\tif( p->interrupt_cb )\n\t\t\t(*p->interrupt_cb)(p->device, IRQ_SERIN);\n\t}\n}\n\nstatic TIMER_CALLBACK( pokey_serout_ready_cb )\n{\n\tpokey_state *p = (pokey_state *)ptr;\n    if( p->IRQEN & IRQ_SEROR )\n\t{\n\t\tp->IRQST |= IRQ_SEROR;\n\t\tif( p->interrupt_cb )\n\t\t\t(*p->interrupt_cb)(p->device, IRQ_SEROR);\n\t}\n}\n\nstatic TIMER_CALLBACK( pokey_serout_complete )\n{\n\tpokey_state *p = (pokey_state *)ptr;\n    if( p->IRQEN & IRQ_SEROC )\n\t{\n\t\tp->IRQST |= IRQ_SEROC;\n\t\tif( p->interrupt_cb )\n\t\t\t(*p->interrupt_cb)(p->device, IRQ_SEROC);\n\t}\n}\n\nstatic TIMER_CALLBACK( pokey_pot_trigger )\n{\n\tpokey_state *p = (pokey_state *)ptr;\n\tint pot = param;\n\tLOG((\"POKEY #%p POT%d triggers after %dus\\n\", p, pot, (int)(1000000 * p->ptimer[pot]->elapsed().as_double())));\n\tp->ALLPOT &= ~(1 << pot);\t// set the enabled timer irq status bits //\n}*/\n\n/*#define AD_TIME  ((p->SKCTL & SK_PADDLE) ? p->ad_time_fast : p->ad_time_slow)\n\nstatic void pokey_potgo(pokey_state *p)\n{\n    int pot;\n\n\tLOG((\"POKEY #%p pokey_potgo\\n\", p));\n\n    p->ALLPOT = 0xff;\n\n    for( pot = 0; pot < 8; pot++ )\n\t{\n\t\tp->POTx[pot] = 0xff;\n\t\tif( !p->pot_r[pot].isnull() )\n\t\t{\n\t\t\tint r = p->pot_r[pot](pot);\n\n\t\t\tLOG((\"POKEY %s pot_r(%d) returned $%02x\\n\", p->device->tag(), pot, r));\n\t\t\tif( r != -1 )\n\t\t\t{\n\t\t\t\tif (r > 228)\n                    r = 228;\n\n                // final value //\n                p->POTx[pot] = r;\n\t\t\t\tp->ptimer[pot]->adjust(AD_TIME * r, pot);\n\t\t\t}\n\t\t}\n\t}\n}*/\n\n//READ8_DEVICE_HANDLER( pokey_r )\nUINT8 pokey_r(UINT8 ChipID, offs_t offset)\n{\n\t//pokey_state *p = get_safe_token(device);\n\tpokey_state *p = &PokeyData[ChipID];\n\tint data = 0, pot;\n\tUINT32 adjust = 0;\n\n\tswitch (offset & 15)\n\t{\n\tcase POT0_C: case POT1_C: case POT2_C: case POT3_C:\n\tcase POT4_C: case POT5_C: case POT6_C: case POT7_C:\n\t\tpot = offset & 7;\n\t\t/*if( !p->pot_r[pot].isnull() )\n\t\t{\n\t\t\t//\n             * If the conversion is not yet finished (ptimer running),\n             * get the current value by the linear interpolation of\n             * the final value using the elapsed time.\n             //\n\t\t\tif( p->ALLPOT & (1 << pot) )\n\t\t\t{\n\t\t\t\t//data = p->ptimer[pot]->elapsed().attoseconds / AD_TIME.attoseconds;\n\t\t\t\tdata = p->POTx[pot];\n\t\t\t\tLOG((\"POKEY '%s' read POT%d (interpolated) $%02x\\n\", p->device->tag(), pot, data));\n            }\n\t\t\telse\n\t\t\t{\n\t\t\t\tdata = p->POTx[pot];\n\t\t\t\tLOG((\"POKEY '%s' read POT%d (final value)  $%02x\\n\", p->device->tag(), pot, data));\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\tlogerror(\"%s: warning - read '%s' POT%d\\n\", p->device->machine().describe_context(), p->device->tag(), pot);*/\n\t\tbreak;\n\n    case ALLPOT_C:\n\t\t/****************************************************************\n         * If the 2 least significant bits of SKCTL are 0, the ALLPOTs\n         * are disabled (SKRESET). Thanks to MikeJ for pointing this out.\n         ****************************************************************/\n\t\t/*if( (p->SKCTL & SK_RESET) == 0)\n\t\t{\n\t\t\tdata = 0;\n\t\t\tLOG((\"POKEY '%s' ALLPOT internal $%02x (reset)\\n\", p->device->tag(), data));\n\t\t}\n\t\telse if( !p->allpot_r.isnull() )\n\t\t{\n\t\t\tdata = p->allpot_r(offset);\n\t\t\tLOG((\"POKEY '%s' ALLPOT callback $%02x\\n\", p->device->tag(), data));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdata = p->ALLPOT;\n\t\t\tLOG((\"POKEY '%s' ALLPOT internal $%02x\\n\", p->device->tag(), data));\n\t\t}*/\n\t\tbreak;\n\n\tcase KBCODE_C:\n\t\tdata = p->KBCODE;\n\t\tbreak;\n\n\tcase RANDOM_C:\n\t\t/****************************************************************\n         * If the 2 least significant bits of SKCTL are 0, the random\n         * number generator is disabled (SKRESET). Thanks to Eric Smith\n         * for pointing out this critical bit of info! If the random\n         * number generator is enabled, get a new random number. Take\n         * the time gone since the last read into account and read the\n         * new value from an appropriate offset in the rand17 table.\n         ****************************************************************/\n\t\tif( p->SKCTL & SK_RESET )\n\t\t{\n\t\t\t//adjust = p->rtimer->elapsed().as_double() / p->clock_period.as_double();\n\t\t\tadjust = 0;\n\t\t\tp->r9 = (p->r9 + adjust) % 0x001ff;\n\t\t\tp->r17 = (p->r17 + adjust) % 0x1ffff;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tadjust = 1;\n\t\t\tp->r9 = 0;\n\t\t\tp->r17 = 0;\n            //LOG_RAND((\"POKEY '%s' rand17 frozen (SKCTL): $%02x\\n\", p->device->tag(), p->RANDOM));\n\t\t}\n\t\tif( p->AUDCTL & POLY9 )\n\t\t{\n\t\t\tp->RANDOM = p->rand9[p->r9];\n\t\t\t//LOG_RAND((\"POKEY '%s' adjust %u rand9[$%05x]: $%02x\\n\", p->device->tag(), adjust, p->r9, p->RANDOM));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tp->RANDOM = p->rand17[p->r17];\n\t\t\t//LOG_RAND((\"POKEY '%s' adjust %u rand17[$%05x]: $%02x\\n\", p->device->tag(), adjust, p->r17, p->RANDOM));\n\t\t}\n\t\t//if (adjust > 0)\n\t\t//\tp->rtimer->adjust(attotime::never);\n\t\tdata = p->RANDOM ^ 0xff;\n\t\tbreak;\n\n\tcase SERIN_C:\n\t\t//if( !p->serin_r.isnull() )\n\t\t//\tp->SERIN = p->serin_r(offset);\n\t\tdata = p->SERIN;\n\t\t//LOG((\"POKEY '%s' SERIN  $%02x\\n\", p->device->tag(), data));\n\t\tbreak;\n\n\tcase IRQST_C:\n\t\t/* IRQST is an active low input port; we keep it active high */\n\t\t/* internally to ease the (un-)masking of bits */\n\t\tdata = p->IRQST ^ 0xff;\n\t\t//LOG((\"POKEY '%s' IRQST  $%02x\\n\", p->device->tag(), data));\n\t\tbreak;\n\n\tcase SKSTAT_C:\n\t\t/* SKSTAT is also an active low input port */\n\t\tdata = p->SKSTAT ^ 0xff;\n\t\t//LOG((\"POKEY '%s' SKSTAT $%02x\\n\", p->device->tag(), data));\n\t\tbreak;\n\n\tdefault:\n\t\t//LOG((\"POKEY '%s' register $%02x\\n\", p->device->tag(), offset));\n        break;\n    }\n    return data;\n}\n\n/*READ8_HANDLER( quad_pokey_r )\n{\n\tstatic const char *const devname[4] = { \"pokey1\", \"pokey2\", \"pokey3\", \"pokey4\" };\n\tint pokey_num = (offset >> 3) & ~0x04;\n\tint control = (offset & 0x20) >> 2;\n\tint pokey_reg = (offset % 8) | control;\n\n\treturn pokey_r(space->machine().device(devname[pokey_num]), pokey_reg);\n}*/\n\n\n//WRITE8_DEVICE_HANDLER( pokey_w )\nvoid pokey_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//pokey_state *p = get_safe_token(device);\n\tpokey_state *p = &PokeyData[ChipID];\n\tint ch_mask = 0, new_val;\n\n\t//p->channel->update();\n\n    /* determine which address was changed */\n\tswitch (offset & 15)\n    {\n    case AUDF1_C:\n\t\tif( data == p->AUDF[CHAN1] )\n            return;\n\t\t//LOG_SOUND((\"POKEY '%s' AUDF1  $%02x\\n\", p->device->tag(), data));\n\t\tp->AUDF[CHAN1] = data;\n        ch_mask = 1 << CHAN1;\n\t\tif( p->AUDCTL & CH12_JOINED )\t\t/* if ch 1&2 tied together */\n            ch_mask |= 1 << CHAN2;    /* then also change on ch2 */\n        break;\n\n    case AUDC1_C:\n\t\tif( data == p->AUDC[CHAN1] )\n            return;\n\t\t//LOG_SOUND((\"POKEY '%s' AUDC1  $%02x (%s)\\n\", p->device->tag(), data, audc2str(data)));\n\t\tp->AUDC[CHAN1] = data;\n        ch_mask = 1 << CHAN1;\n        break;\n\n    case AUDF2_C:\n\t\tif( data == p->AUDF[CHAN2] )\n            return;\n\t\t//LOG_SOUND((\"POKEY '%s' AUDF2  $%02x\\n\", p->device->tag(), data));\n\t\tp->AUDF[CHAN2] = data;\n        ch_mask = 1 << CHAN2;\n        break;\n\n    case AUDC2_C:\n\t\tif( data == p->AUDC[CHAN2] )\n            return;\n\t\t//LOG_SOUND((\"POKEY '%s' AUDC2  $%02x (%s)\\n\", p->device->tag(), data, audc2str(data)));\n\t\tp->AUDC[CHAN2] = data;\n        ch_mask = 1 << CHAN2;\n        break;\n\n    case AUDF3_C:\n\t\tif( data == p->AUDF[CHAN3] )\n            return;\n\t\t//LOG_SOUND((\"POKEY '%s' AUDF3  $%02x\\n\", p->device->tag(), data));\n\t\tp->AUDF[CHAN3] = data;\n        ch_mask = 1 << CHAN3;\n\n\t\tif( p->AUDCTL & CH34_JOINED )\t/* if ch 3&4 tied together */\n            ch_mask |= 1 << CHAN4;  /* then also change on ch4 */\n        break;\n\n    case AUDC3_C:\n\t\tif( data == p->AUDC[CHAN3] )\n            return;\n\t\t//LOG_SOUND((\"POKEY '%s' AUDC3  $%02x (%s)\\n\", p->device->tag(), data, audc2str(data)));\n\t\tp->AUDC[CHAN3] = data;\n        ch_mask = 1 << CHAN3;\n        break;\n\n    case AUDF4_C:\n\t\tif( data == p->AUDF[CHAN4] )\n            return;\n\t\t//LOG_SOUND((\"POKEY '%s' AUDF4  $%02x\\n\", p->device->tag(), data));\n\t\tp->AUDF[CHAN4] = data;\n        ch_mask = 1 << CHAN4;\n        break;\n\n    case AUDC4_C:\n\t\tif( data == p->AUDC[CHAN4] )\n            return;\n\t\t//LOG_SOUND((\"POKEY '%s' AUDC4  $%02x (%s)\\n\", p->device->tag(), data, audc2str(data)));\n\t\tp->AUDC[CHAN4] = data;\n        ch_mask = 1 << CHAN4;\n        break;\n\n    case AUDCTL_C:\n\t\tif( data == p->AUDCTL )\n            return;\n\t\t//LOG_SOUND((\"POKEY '%s' AUDCTL $%02x (%s)\\n\", p->device->tag(), data, audctl2str(data)));\n\t\tp->AUDCTL = data;\n        ch_mask = 15;       /* all channels */\n        /* determine the base multiplier for the 'div by n' calculations */\n\t\tp->clockmult = (p->AUDCTL & CLK_15KHZ) ? DIV_15 : DIV_64;\n        break;\n\n    case STIMER_C:\n        /*// first remove any existing timers //\n\t\tLOG_TIMER((\"POKEY '%s' STIMER $%02x\\n\", p->device->tag(), data));\n\n\t\tp->timer[TIMER1]->adjust(attotime::never, p->timer_param[TIMER1]);\n\t\tp->timer[TIMER2]->adjust(attotime::never, p->timer_param[TIMER2]);\n\t\tp->timer[TIMER4]->adjust(attotime::never, p->timer_param[TIMER4]);\n\n        // reset all counters to zero (side effect) //\n\t\tp->polyadjust = 0;\n\t\tp->counter[CHAN1] = 0;\n\t\tp->counter[CHAN2] = 0;\n\t\tp->counter[CHAN3] = 0;\n\t\tp->counter[CHAN4] = 0;\n\n        // joined chan#1 and chan#2 ? //\n\t\tif( p->AUDCTL & CH12_JOINED )\n        {\n\t\t\tif( p->divisor[CHAN2] > 4 )\n\t\t\t{\n\t\t\t\tLOG_TIMER((\"POKEY '%s' timer1+2 after %d clocks\\n\", p->device->tag(), p->divisor[CHAN2]));\n\t\t\t\t// set timer #1 _and_ #2 event after timer_div clocks of joined CHAN1+CHAN2 //\n\t\t\t\tp->timer_period[TIMER2] = p->clock_period * p->divisor[CHAN2];\n\t\t\t\tp->timer_param[TIMER2] = IRQ_TIMR2|IRQ_TIMR1;\n\t\t\t\tp->timer[TIMER2]->adjust(p->timer_period[TIMER2], p->timer_param[TIMER2], p->timer_period[TIMER2]);\n\t\t\t}\n        }\n        else\n        {\n\t\t\tif( p->divisor[CHAN1] > 4 )\n\t\t\t{\n\t\t\t\tLOG_TIMER((\"POKEY '%s' timer1 after %d clocks\\n\", p->device->tag(), p->divisor[CHAN1]));\n\t\t\t\t// set timer #1 event after timer_div clocks of CHAN1 //\n\t\t\t\tp->timer_period[TIMER1] = p->clock_period * p->divisor[CHAN1];\n\t\t\t\tp->timer_param[TIMER1] = IRQ_TIMR1;\n\t\t\t\tp->timer[TIMER1]->adjust(p->timer_period[TIMER1], p->timer_param[TIMER1], p->timer_period[TIMER1]);\n\t\t\t}\n\n\t\t\tif( p->divisor[CHAN2] > 4 )\n\t\t\t{\n\t\t\t\tLOG_TIMER((\"POKEY '%s' timer2 after %d clocks\\n\", p->device->tag(), p->divisor[CHAN2]));\n\t\t\t\t// set timer #2 event after timer_div clocks of CHAN2 //\n\t\t\t\tp->timer_period[TIMER2] = p->clock_period * p->divisor[CHAN2];\n\t\t\t\tp->timer_param[TIMER2] = IRQ_TIMR2;\n\t\t\t\tp->timer[TIMER2]->adjust(p->timer_period[TIMER2], p->timer_param[TIMER2], p->timer_period[TIMER2]);\n\t\t\t}\n        }\n\n\t\t// Note: p[chip] does not have a timer #3 //\n\n\t\tif( p->AUDCTL & CH34_JOINED )\n        {\n            // not sure about this: if audc4 == 0000xxxx don't start timer 4 ? //\n\t\t\tif( p->AUDC[CHAN4] & 0xf0 )\n            {\n\t\t\t\tif( p->divisor[CHAN4] > 4 )\n\t\t\t\t{\n\t\t\t\t\tLOG_TIMER((\"POKEY '%s' timer4 after %d clocks\\n\", p->device->tag(), p->divisor[CHAN4]));\n\t\t\t\t\t// set timer #4 event after timer_div clocks of CHAN4 //\n\t\t\t\t\tp->timer_period[TIMER4] = p->clock_period * p->divisor[CHAN4];\n\t\t\t\t\tp->timer_param[TIMER4] = IRQ_TIMR4;\n\t\t\t\t\tp->timer[TIMER4]->adjust(p->timer_period[TIMER4], p->timer_param[TIMER4], p->timer_period[TIMER4]);\n\t\t\t\t}\n            }\n        }\n        else\n        {\n\t\t\tif( p->divisor[CHAN4] > 4 )\n\t\t\t{\n\t\t\t\tLOG_TIMER((\"POKEY '%s' timer4 after %d clocks\\n\", p->device->tag(), p->divisor[CHAN4]));\n\t\t\t\t// set timer #4 event after timer_div clocks of CHAN4 //\n\t\t\t\tp->timer_period[TIMER4] = p->clock_period * p->divisor[CHAN4];\n\t\t\t\tp->timer_param[TIMER4] = IRQ_TIMR4;\n\t\t\t\tp->timer[TIMER4]->adjust(p->timer_period[TIMER4], p->timer_param[TIMER4], p->timer_period[TIMER4]);\n\t\t\t}\n        }\n\n\t\tp->timer[TIMER1]->enable(p->IRQEN & IRQ_TIMR1);\n\t\tp->timer[TIMER2]->enable(p->IRQEN & IRQ_TIMR2);\n\t\tp->timer[TIMER4]->enable(p->IRQEN & IRQ_TIMR4);*/\n        break;\n\n    case SKREST_C:\n        /* reset SKSTAT */\n\t\t//LOG((\"POKEY '%s' SKREST $%02x\\n\", p->device->tag(), data));\n\t\tp->SKSTAT &= ~(SK_FRAME|SK_OVERRUN|SK_KBERR);\n        break;\n\n    case POTGO_C:\n\t\t//LOG((\"POKEY '%s' POTGO  $%02x\\n\", p->device->tag(), data));\n\t\t//pokey_potgo(p);\n        break;\n\n    case SEROUT_C:\n\t\t//LOG((\"POKEY '%s' SEROUT $%02x\\n\", p->device->tag(), data));\n\t\t//p->serout_w(offset, data);\n\t\t//p->SKSTAT |= SK_SEROUT;\n        /*\n         * These are arbitrary values, tested with some custom boot\n         * loaders from Ballblazer and Escape from Fractalus\n         * The real times are unknown\n         */\n        //device->machine().scheduler().timer_set(attotime::from_usec(200), FUNC(pokey_serout_ready_cb), 0, p);\n        /* 10 bits (assumption 1 start, 8 data and 1 stop bit) take how long? */\n        //device->machine().scheduler().timer_set(attotime::from_usec(2000), FUNC(pokey_serout_complete), 0, p);\n        break;\n\n    case IRQEN_C:\n\t\t//LOG((\"POKEY '%s' IRQEN  $%02x\\n\", p->device->tag(), data));\n\n        /* acknowledge one or more IRQST bits ? */\n\t\tif( p->IRQST & ~data )\n        {\n            /* reset IRQST bits that are masked now */\n\t\t\tp->IRQST &= data;\n        }\n        else\n        {\n\t\t\t/* enable/disable timers now to avoid unneeded\n               breaking of the CPU cores for masked timers */\n\t\t\t/*if( p->timer[TIMER1] && ((p->IRQEN^data) & IRQ_TIMR1) )\n\t\t\t\tp->timer[TIMER1]->enable(data & IRQ_TIMR1);\n\t\t\tif( p->timer[TIMER2] && ((p->IRQEN^data) & IRQ_TIMR2) )\n\t\t\t\tp->timer[TIMER2]->enable(data & IRQ_TIMR2);\n\t\t\tif( p->timer[TIMER4] && ((p->IRQEN^data) & IRQ_TIMR4) )\n\t\t\t\tp->timer[TIMER4]->enable(data & IRQ_TIMR4);*/\n        }\n\t\t/* store irq enable */\n\t\tp->IRQEN = data;\n        break;\n\n    case SKCTL_C:\n\t\tif( data == p->SKCTL )\n            return;\n\t\t//LOG((\"POKEY '%s' SKCTL  $%02x\\n\", p->device->tag(), data));\n\t\tp->SKCTL = data;\n        if( !(data & SK_RESET) )\n        {\n            pokey_w(ChipID, IRQEN_C,  0);\n            pokey_w(ChipID, SKREST_C, 0);\n        }\n        break;\n    }\n\n\t/************************************************************\n     * As defined in the manual, the exact counter values are\n     * different depending on the frequency and resolution:\n     *    64 kHz or 15 kHz - AUDF + 1\n     *    1.79 MHz, 8-bit  - AUDF + 4\n     *    1.79 MHz, 16-bit - AUDF[CHAN1]+256*AUDF[CHAN2] + 7\n     ************************************************************/\n\n    /* only reset the channels that have changed */\n\n    if( ch_mask & (1 << CHAN1) )\n    {\n        /* process channel 1 frequency */\n\t\tif( p->AUDCTL & CH1_HICLK )\n\t\t\tnew_val = p->AUDF[CHAN1] + DIVADD_HICLK;\n        else\n\t\t\tnew_val = (p->AUDF[CHAN1] + DIVADD_LOCLK) * p->clockmult;\n\n\t\t//LOG_SOUND((\"POKEY '%s' chan1 %d\\n\", p->device->tag(), new_val));\n\n\t\tp->volume[CHAN1] = (p->AUDC[CHAN1] & VOLUME_MASK) * POKEY_DEFAULT_GAIN;\n        p->divisor[CHAN1] = new_val;\n\t\tif( new_val < p->counter[CHAN1] )\n\t\t\tp->counter[CHAN1] = new_val;\n\t\t//if( p->interrupt_cb && p->timer[TIMER1] )\n\t\t//\tp->timer[TIMER1]->adjust(p->clock_period * new_val, p->timer_param[TIMER1], p->timer_period[TIMER1]);\n\t\tp->audible[CHAN1] = !(\n\t\t\t(p->AUDC[CHAN1] & VOLUME_ONLY) ||\n\t\t\t(p->AUDC[CHAN1] & VOLUME_MASK) == 0 ||\n\t\t\t((p->AUDC[CHAN1] & PURE) && new_val < (p->samplerate_24_8 >> 8)));\n\t\tif( !p->audible[CHAN1] )\n\t\t{\n\t\t\tp->output[CHAN1] = 1;\n\t\t\tp->counter[CHAN1] = 0x7fffffff;\n\t\t\t/* 50% duty cycle should result in half volume */\n            p->volume[CHAN1] >>= 1;\n        }\n    }\n\n    if( ch_mask & (1 << CHAN2) )\n    {\n        /* process channel 2 frequency */\n\t\tif( p->AUDCTL & CH12_JOINED )\n        {\n\t\t\tif( p->AUDCTL & CH1_HICLK )\n\t\t\t\tnew_val = p->AUDF[CHAN2] * 256 + p->AUDF[CHAN1] + DIVADD_HICLK_JOINED;\n            else\n\t\t\t\tnew_val = (p->AUDF[CHAN2] * 256 + p->AUDF[CHAN1] + DIVADD_LOCLK) * p->clockmult;\n\t\t\t//LOG_SOUND((\"POKEY '%s' chan1+2 %d\\n\", p->device->tag(), new_val));\n        }\n        else\n\t\t{\n\t\t\tnew_val = (p->AUDF[CHAN2] + DIVADD_LOCLK) * p->clockmult;\n\t\t\t//LOG_SOUND((\"POKEY '%s' chan2 %d\\n\", p->device->tag(), new_val));\n\t\t}\n\n\t\tp->volume[CHAN2] = (p->AUDC[CHAN2] & VOLUME_MASK) * POKEY_DEFAULT_GAIN;\n\t\tp->divisor[CHAN2] = new_val;\n\t\tif( new_val < p->counter[CHAN2] )\n\t\t\tp->counter[CHAN2] = new_val;\n\t\t//if( p->interrupt_cb && p->timer[TIMER2] )\n\t\t//\tp->timer[TIMER2]->adjust(p->clock_period * new_val, p->timer_param[TIMER2], p->timer_period[TIMER2]);\n\t\tp->audible[CHAN2] = !(\n\t\t\t(p->AUDC[CHAN2] & VOLUME_ONLY) ||\n\t\t\t(p->AUDC[CHAN2] & VOLUME_MASK) == 0 ||\n\t\t\t((p->AUDC[CHAN2] & PURE) && new_val < (p->samplerate_24_8 >> 8)));\n\t\tif( !p->audible[CHAN2] )\n\t\t{\n\t\t\tp->output[CHAN2] = 1;\n\t\t\tp->counter[CHAN2] = 0x7fffffff;\n\t\t\t/* 50% duty cycle should result in half volume */\n\t\t\tp->volume[CHAN2] >>= 1;\n        }\n    }\n\n    if( ch_mask & (1 << CHAN3) )\n    {\n        /* process channel 3 frequency */\n\t\tif( p->AUDCTL & CH3_HICLK )\n\t\t\tnew_val = p->AUDF[CHAN3] + DIVADD_HICLK;\n        else\n\t\t\tnew_val = (p->AUDF[CHAN3] + DIVADD_LOCLK) * p->clockmult;\n\n\t\t//LOG_SOUND((\"POKEY '%s' chan3 %d\\n\", p->device->tag(), new_val));\n\n\t\tp->volume[CHAN3] = (p->AUDC[CHAN3] & VOLUME_MASK) * POKEY_DEFAULT_GAIN;\n\t\tp->divisor[CHAN3] = new_val;\n\t\tif( new_val < p->counter[CHAN3] )\n\t\t\tp->counter[CHAN3] = new_val;\n\t\t/* channel 3 does not have a timer associated */\n\t\tp->audible[CHAN3] = !(\n\t\t\t(p->AUDC[CHAN3] & VOLUME_ONLY) ||\n\t\t\t(p->AUDC[CHAN3] & VOLUME_MASK) == 0 ||\n\t\t\t((p->AUDC[CHAN3] & PURE) && new_val < (p->samplerate_24_8 >> 8))) ||\n\t\t\t(p->AUDCTL & CH1_FILTER);\n\t\tif( !p->audible[CHAN3] )\n\t\t{\n\t\t\tp->output[CHAN3] = 1;\n\t\t\tp->counter[CHAN3] = 0x7fffffff;\n\t\t\t/* 50% duty cycle should result in half volume */\n\t\t\tp->volume[CHAN3] >>= 1;\n        }\n    }\n\n    if( ch_mask & (1 << CHAN4) )\n    {\n        /* process channel 4 frequency */\n\t\tif( p->AUDCTL & CH34_JOINED )\n        {\n\t\t\tif( p->AUDCTL & CH3_HICLK )\n\t\t\t\tnew_val = p->AUDF[CHAN4] * 256 + p->AUDF[CHAN3] + DIVADD_HICLK_JOINED;\n            else\n\t\t\t\tnew_val = (p->AUDF[CHAN4] * 256 + p->AUDF[CHAN3] + DIVADD_LOCLK) * p->clockmult;\n\t\t\t//LOG_SOUND((\"POKEY '%s' chan3+4 %d\\n\", p->device->tag(), new_val));\n        }\n        else\n\t\t{\n\t\t\tnew_val = (p->AUDF[CHAN4] + DIVADD_LOCLK) * p->clockmult;\n\t\t\t//LOG_SOUND((\"POKEY '%s' chan4 %d\\n\", p->device->tag(), new_val));\n\t\t}\n\n\t\tp->volume[CHAN4] = (p->AUDC[CHAN4] & VOLUME_MASK) * POKEY_DEFAULT_GAIN;\n\t\tp->divisor[CHAN4] = new_val;\n\t\tif( new_val < p->counter[CHAN4] )\n\t\t\tp->counter[CHAN4] = new_val;\n\t\t//if( p->interrupt_cb && p->timer[TIMER4] )\n\t\t//\tp->timer[TIMER4]->adjust(p->clock_period * new_val, p->timer_param[TIMER4], p->timer_period[TIMER4]);\n\t\tp->audible[CHAN4] = !(\n\t\t\t(p->AUDC[CHAN4] & VOLUME_ONLY) ||\n\t\t\t(p->AUDC[CHAN4] & VOLUME_MASK) == 0 ||\n\t\t\t((p->AUDC[CHAN4] & PURE) && new_val < (p->samplerate_24_8 >> 8))) ||\n\t\t\t(p->AUDCTL & CH2_FILTER);\n\t\tif( !p->audible[CHAN4] )\n\t\t{\n\t\t\tp->output[CHAN4] = 1;\n\t\t\tp->counter[CHAN4] = 0x7fffffff;\n\t\t\t/* 50% duty cycle should result in half volume */\n\t\t\tp->volume[CHAN4] >>= 1;\n        }\n    }\n}\n\n/*WRITE8_HANDLER( quad_pokey_w )\n{\n\tstatic const char *const devname[4] = { \"pokey1\", \"pokey2\", \"pokey3\", \"pokey4\" };\n    int pokey_num = (offset >> 3) & ~0x04;\n    int control = (offset & 0x20) >> 2;\n    int pokey_reg = (offset % 8) | control;\n\n    pokey_w(space->machine().device(devname[pokey_num]), pokey_reg, data);\n}\n\nvoid pokey_serin_ready(device_t *device, int after)\n{\n\tpokey_state *p = get_safe_token(device);\n\tdevice->machine().scheduler().timer_set(p->clock_period * after, FUNC(pokey_serin_ready_cb), 0, p);\n}\n\nvoid pokey_break_w(device_t *device, int shift)\n{\n\t//pokey_state *p = get_safe_token(device);\n\tif( shift )                     // shift code ? //\n\t\tp->SKSTAT |= SK_SHIFT;\n\telse\n\t\tp->SKSTAT &= ~SK_SHIFT;\n\t// check if the break IRQ is enabled //\n\tif( p->IRQEN & IRQ_BREAK )\n\t{\n\t\t// set break IRQ status and call back the interrupt handler //\n\t\tp->IRQST |= IRQ_BREAK;\n\t\tif( p->interrupt_cb )\n\t\t\t(*p->interrupt_cb)(device, IRQ_BREAK);\n\t}\n}\n\nvoid pokey_kbcode_w(device_t *device, int kbcode, int make)\n{\n\tpokey_state *p = get_safe_token(device);\n    // make code ? //\n\tif( make )\n\t{\n\t\tp->KBCODE = kbcode;\n\t\tp->SKSTAT |= SK_KEYBD;\n\t\tif( kbcode & 0x40 ) \t\t// shift code ? //\n\t\t\tp->SKSTAT |= SK_SHIFT;\n\t\telse\n\t\t\tp->SKSTAT &= ~SK_SHIFT;\n\n\t\tif( p->IRQEN & IRQ_KEYBD )\n\t\t{\n\t\t\t// last interrupt not acknowledged ? //\n\t\t\tif( p->IRQST & IRQ_KEYBD )\n\t\t\t\tp->SKSTAT |= SK_KBERR;\n\t\t\tp->IRQST |= IRQ_KEYBD;\n\t\t\tif( p->interrupt_cb )\n\t\t\t\t(*p->interrupt_cb)(device, IRQ_KEYBD);\n\t\t}\n\t}\n\telse\n\t{\n\t\tp->KBCODE = kbcode;\n\t\tp->SKSTAT &= ~SK_KEYBD;\n    }\n}*/\n\n\nvoid pokey_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tpokey_state *chip = &PokeyData[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 4; CurChn ++)\n\t\tchip->Muted[CurChn] = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( pokey )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers --- //\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(pokey_state);\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions --- //\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( pokey );\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing //\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// Nothing //\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings --- //\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"POKEY\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Atari custom\");\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"4.51\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}\n\n\nDEFINE_LEGACY_SOUND_DEVICE(POKEY, pokey);*/\n"
  },
  {
    "path": "VGMPlay/chips/pokey.h",
    "content": "/*****************************************************************************\n *\n *  POKEY chip emulator 4.3\n *  Copyright Nicola Salmoria and the MAME Team\n *\n *  Based on original info found in Ron Fries' Pokey emulator,\n *  with additions by Brad Oliver, Eric Smith and Juergen Buchmueller.\n *  paddle (a/d conversion) details from the Atari 400/800 Hardware Manual.\n *  Polynome algorithms according to info supplied by Perry McFarlane.\n *\n *  This code is subject to the MAME license, which besides other\n *  things means it is distributed as is, no warranties whatsoever.\n *  For more details read mame.txt that comes with MAME.\n *\n *****************************************************************************/\n\n#pragma once\n\n//#include \"devlegcy.h\"\n\n/* CONSTANT DEFINITIONS */\n\n/* POKEY WRITE LOGICALS */\n#define AUDF1_C     0x00\n#define AUDC1_C     0x01\n#define AUDF2_C     0x02\n#define AUDC2_C     0x03\n#define AUDF3_C     0x04\n#define AUDC3_C     0x05\n#define AUDF4_C     0x06\n#define AUDC4_C     0x07\n#define AUDCTL_C    0x08\n#define STIMER_C    0x09\n#define SKREST_C    0x0A\n#define POTGO_C     0x0B\n#define SEROUT_C    0x0D\n#define IRQEN_C     0x0E\n#define SKCTL_C     0x0F\n\n/* POKEY READ LOGICALS */\n#define POT0_C      0x00\n#define POT1_C      0x01\n#define POT2_C      0x02\n#define POT3_C      0x03\n#define POT4_C      0x04\n#define POT5_C      0x05\n#define POT6_C      0x06\n#define POT7_C      0x07\n#define ALLPOT_C    0x08\n#define KBCODE_C    0x09\n#define RANDOM_C    0x0A\n#define SERIN_C     0x0D\n#define IRQST_C     0x0E\n#define SKSTAT_C    0x0F\n\n/* exact 1.79 MHz clock freq (of the Atari 800 that is) */\n#define FREQ_17_EXACT   1789790\n\n\n/*****************************************************************************\n * pot0_r to pot7_r:\n *  Handlers for reading the pot values. Some Atari games use\n *  ALLPOT to return dipswitch settings and other things.\n * serin_r, serout_w, interrupt_cb:\n *  New function pointers for serial input/output and a interrupt callback.\n *****************************************************************************/\n\n/*typedef struct _pokey_interface pokey_interface;\nstruct _pokey_interface\n{\n\tdevcb_read8 pot_r[8];\n\tdevcb_read8 allpot_r;\n\tdevcb_read8 serin_r;\n\tdevcb_write8 serout_w;\n\tvoid (*interrupt_cb)(device_t *device, int mask);\n};*/\n\n\nvoid pokey_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_pokey(UINT8 ChipID, int clock);\nvoid device_stop_pokey(UINT8 ChipID);\nvoid device_reset_pokey(UINT8 ChipID);\n\n//READ8_DEVICE_HANDLER( pokey_r );\n//WRITE8_DEVICE_HANDLER( pokey_w );\nUINT8 pokey_r(UINT8 ChipID, offs_t offset);\nvoid pokey_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\n/* fix me: eventually this should be a single device with pokey subdevices */\n//READ8_HANDLER( quad_pokey_r );\n//WRITE8_HANDLER( quad_pokey_w );\n\n/*void pokey_serin_ready (device_t *device, int after);\nvoid pokey_break_w (device_t *device, int shift);\nvoid pokey_kbcode_w (device_t *device, int kbcode, int make);*/\n\nvoid pokey_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n//DECLARE_LEGACY_SOUND_DEVICE(POKEY, pokey);\n"
  },
  {
    "path": "VGMPlay/chips/pwm.c",
    "content": "/***************************************************************************\n * Gens: PWM audio emulator.                                               *\n *                                                                         *\n * Copyright (c) 1999-2002 by Stphane Dallongeville                       *\n * Copyright (c) 2003-2004 by Stphane Akhoun                              *\n * Copyright (c) 2008-2009 by David Korth                                  *\n *                                                                         *\n * This program is free software; you can redistribute it and/or modify it *\n * under the terms of the GNU General Public License as published by the   *\n * Free Software Foundation; either version 2 of the License, or (at your  *\n * option) any later version.                                              *\n *                                                                         *\n * This program is distributed in the hope that it will be useful, but     *\n * WITHOUT ANY WARRANTY; without even the implied warranty of              *\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *\n * GNU General Public License for more details.                            *\n *                                                                         *\n * You should have received a copy of the GNU General Public License along *\n * with this program; if not, write to the Free Software Foundation, Inc., *\n * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.           *\n ***************************************************************************/\n\n#include \"mamedef.h\"\n#include \"pwm.h\"\n\n#include <string.h>\n\n//#include \"gens_core/mem/mem_sh2.h\"\n//#include \"gens_core/cpu/sh2/sh2.h\"\n\n#define CHILLY_WILLY_SCALE\t1\n\n#if PWM_BUF_SIZE == 8\nunsigned char PWM_FULL_TAB[PWM_BUF_SIZE * PWM_BUF_SIZE] =\n{\n\t0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,\n\t0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,\n};\n#elif PWM_BUF_SIZE == 4\nunsigned char PWM_FULL_TAB[PWM_BUF_SIZE * PWM_BUF_SIZE] =\n{\n\t0x40, 0x00, 0x00, 0x80,\n\t0x80, 0x40, 0x00, 0x00,\n\t0x00, 0x80, 0x40, 0x00,\n\t0x00, 0x00, 0x80, 0x40,\n};\n#else\n#error PWM_BUF_SIZE must equal 4 or 8.\n#endif /* PWM_BUF_SIZE */\n\ntypedef struct _pwm_chip\n{\n\tunsigned short PWM_FIFO_R[8];\n\tunsigned short PWM_FIFO_L[8];\n\tunsigned int PWM_RP_R;\n\tunsigned int PWM_WP_R;\n\tunsigned int PWM_RP_L;\n\tunsigned int PWM_WP_L;\n\tunsigned int PWM_Cycles;\n\tunsigned int PWM_Cycle;\n\tunsigned int PWM_Cycle_Cnt;\n\tunsigned int PWM_Int;\n\tunsigned int PWM_Int_Cnt;\n\tunsigned int PWM_Mode;\n\t//unsigned int PWM_Enable;\n\tunsigned int PWM_Out_R;\n\tunsigned int PWM_Out_L;\n\n\tunsigned int PWM_Cycle_Tmp;\n\tunsigned int PWM_Cycles_Tmp;\n\tunsigned int PWM_Int_Tmp;\n\tunsigned int PWM_FIFO_L_Tmp;\n\tunsigned int PWM_FIFO_R_Tmp;\n\n#if CHILLY_WILLY_SCALE\n// TODO: Fix Chilly Willy's new scaling algorithm.\n\t/* PWM scaling variables. */\n\tint PWM_Offset;\n\tint PWM_Scale;\n\t//int PWM_Loudness;\n#endif\n\t\n\tint clock;\n} pwm_chip;\n#if CHILLY_WILLY_SCALE\n// TODO: Fix Chilly Willy's new scaling algorithm.\n#define PWM_Loudness\t0\n#endif\n\nvoid PWM_Init(pwm_chip* chip);\nvoid PWM_Recalc_Scale(pwm_chip* chip);\n\nvoid PWM_Set_Cycle(pwm_chip* chip, unsigned int cycle);\nvoid PWM_Set_Int(pwm_chip* chip, unsigned int int_time);\n\nvoid PWM_Update(pwm_chip* chip, int **buf, int length);\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\n#define MAX_CHIPS\t0x02\nstatic pwm_chip PWM_Chip[MAX_CHIPS];\n\n/**\n * PWM_Init(): Initialize the PWM audio emulator.\n */\nvoid PWM_Init(pwm_chip* chip)\n{\n\tchip->PWM_Mode = 0;\n\tchip->PWM_Out_R = 0;\n\tchip->PWM_Out_L = 0;\n\t\n\tmemset(chip->PWM_FIFO_R, 0x00, sizeof(chip->PWM_FIFO_R));\n\tmemset(chip->PWM_FIFO_L, 0x00, sizeof(chip->PWM_FIFO_L));\n\t\n\tchip->PWM_RP_R = 0;\n\tchip->PWM_WP_R = 0;\n\tchip->PWM_RP_L = 0;\n\tchip->PWM_WP_L = 0;\n\tchip->PWM_Cycle_Tmp = 0;\n\tchip->PWM_Int_Tmp = 0;\n\tchip->PWM_FIFO_L_Tmp = 0;\n\tchip->PWM_FIFO_R_Tmp = 0;\n\t\n\t//PWM_Loudness = 0;\n\tPWM_Set_Cycle(chip, 0);\n\tPWM_Set_Int(chip, 0);\n}\n\n\n#if CHILLY_WILLY_SCALE\n// TODO: Fix Chilly Willy's new scaling algorithm.\nvoid PWM_Recalc_Scale(pwm_chip* chip)\n{\n\tchip->PWM_Offset = (chip->PWM_Cycle / 2) + 1;\n\tchip->PWM_Scale = 0x7FFF00 / chip->PWM_Offset;\n}\n#endif\n\n\nvoid PWM_Set_Cycle(pwm_chip* chip, unsigned int cycle)\n{\n\tcycle--;\n\tchip->PWM_Cycle = (cycle & 0xFFF);\n\tchip->PWM_Cycle_Cnt = chip->PWM_Cycles;\n\t\n#if CHILLY_WILLY_SCALE\n\t// TODO: Fix Chilly Willy's new scaling algorithm.\n\tPWM_Recalc_Scale(chip);\n#endif\n}\n\n\nvoid PWM_Set_Int(pwm_chip* chip, unsigned int int_time)\n{\n\tint_time &= 0x0F;\n\tif (int_time)\n\t\tchip->PWM_Int = chip->PWM_Int_Cnt = int_time;\n\telse\n\t\tchip->PWM_Int = chip->PWM_Int_Cnt = 16;\n}\n\n\nvoid PWM_Clear_Timer(pwm_chip* chip)\n{\n\tchip->PWM_Cycle_Cnt = 0;\n}\n\n\n/**\n * PWM_SHIFT(): Shift PWM data.\n * @param src: Channel (L or R) with the source data.\n * @param dest Channel (L or R) for the destination.\n */\n#define PWM_SHIFT(src, dest)\t\t\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t/* Make sure the source FIFO isn't empty. */\t\t\t\t\t\t\t\\\n\tif (PWM_RP_##src != PWM_WP_##src)\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t/* Get destination channel output from the source channel FIFO. */\t\t\t\\\n\t\tPWM_Out_##dest = PWM_FIFO_##src[PWM_RP_##src];\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t/* Increment the source channel read pointer, resetting to 0 if it overflows. */\t\\\n\t\tPWM_RP_##src = (PWM_RP_##src + 1) & (PWM_BUF_SIZE - 1);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\\\n}\n\n\n/*static void PWM_Shift_Data(void)\n{\n\tswitch (PWM_Mode & 0x0F)\n\t{\n\t\tcase 0x01:\n\t\tcase 0x0D:\n\t\t\t// Rx_LL: Right -> Ignore, Left -> Left\n\t\t\tPWM_SHIFT(L, L);\n\t\t\tbreak;\n\t\t\n\t\tcase 0x02:\n\t\tcase 0x0E:\n\t\t\t// Rx_LR: Right -> Ignore, Left -> Right\n\t\t\tPWM_SHIFT(L, R);\n\t\t\tbreak;\n\t\t\n\t\tcase 0x04:\n\t\tcase 0x07:\n\t\t\t// RL_Lx: Right -> Left, Left -> Ignore\n\t\t\tPWM_SHIFT(R, L);\n\t\t\tbreak;\n\t\t\n\t\tcase 0x05:\n\t\tcase 0x09:\n\t\t\t// RR_LL: Right -> Right, Left -> Left\n\t\t\tPWM_SHIFT(L, L);\n\t\t\tPWM_SHIFT(R, R);\n\t\t\tbreak;\n\t\t\n\t\tcase 0x06:\n\t\tcase 0x0A:\n\t\t\t// RL_LR: Right -> Left, Left -> Right\n\t\t\tPWM_SHIFT(L, R);\n\t\t\tPWM_SHIFT(R, L);\n\t\t\tbreak;\n\t\t\n\t\tcase 0x08:\n\t\tcase 0x0B:\n\t\t\t// RR_Lx: Right -> Right, Left -> Ignore\n\t\t\tPWM_SHIFT(R, R);\n\t\t\tbreak;\n\t\t\n\t\tcase 0x00:\n\t\tcase 0x03:\n\t\tcase 0x0C:\n\t\tcase 0x0F:\n\t\tdefault:\n\t\t\t// Rx_Lx: Right -> Ignore, Left -> Ignore\n\t\t\tbreak;\n\t}\n}\n\n\nvoid PWM_Update_Timer(unsigned int cycle)\n{\n\t// Don't do anything if PWM is disabled in the Sound menu.\n\t\n\t// Don't do anything if PWM isn't active.\n\tif ((PWM_Mode & 0x0F) == 0x00)\n\t\treturn;\n\t\n\tif (PWM_Cycle == 0x00 || (PWM_Cycle_Cnt > cycle))\n\t\treturn;\n\t\n\tPWM_Shift_Data();\n\t\n\tPWM_Cycle_Cnt += PWM_Cycle;\n\t\n\tPWM_Int_Cnt--;\n\tif (PWM_Int_Cnt == 0)\n\t{\n\t\tPWM_Int_Cnt = PWM_Int;\n\t\t\n\t\tif (PWM_Mode & 0x0080)\n\t\t{\n\t\t\t// RPT => generate DREQ1 as well as INT\n\t\t\tSH2_DMA1_Request(&M_SH2, 1);\n\t\t\tSH2_DMA1_Request(&S_SH2, 1);\n\t\t}\n\t\t\n\t\tif (_32X_MINT & 1)\n\t\t\tSH2_Interrupt(&M_SH2, 6);\n\t\tif (_32X_SINT & 1)\n\t\t\tSH2_Interrupt(&S_SH2, 6);\n\t}\n}*/\n\n\nINLINE int PWM_Update_Scale(pwm_chip* chip, int PWM_In)\n{\n\tif (PWM_In == 0)\n\t\treturn 0;\n\t\n\t// TODO: Chilly Willy's new scaling algorithm breaks drx's Sonic 1 32X (with PWM drums).\n#ifdef CHILLY_WILLY_SCALE\n\t//return (((PWM_In & 0xFFF) - chip->PWM_Offset) * chip->PWM_Scale) >> (8 - PWM_Loudness);\n\t// Knuckles' Chaotix: Tachy Touch uses the values 0xF?? for negative values\n\t// This small modification fixes the terrible pops.\n\tPWM_In &= 0xFFF;\n\tif (PWM_In & 0x800)\n\t\tPWM_In |= ~0xFFF;\n\treturn ((PWM_In - chip->PWM_Offset) * chip->PWM_Scale) >> (8 - PWM_Loudness);\n#else\n\tconst int PWM_adjust = ((chip->PWM_Cycle >> 1) + 1);\n\tint PWM_Ret = ((chip->PWM_In & 0xFFF) - PWM_adjust);\n\t\n\t// Increase PWM volume so it's audible.\n\tPWM_Ret <<= (5+2);\n\t\n\t// Make sure the PWM isn't oversaturated.\n\tif (PWM_Ret > 32767)\n\t\tPWM_Ret = 32767;\n\telse if (PWM_Ret < -32768)\n\t\tPWM_Ret = -32768;\n\t\n\treturn PWM_Ret;\n#endif\n}\n\n\nvoid PWM_Update(pwm_chip* chip, int **buf, int length)\n{\n\tint tmpOutL;\n\tint tmpOutR;\n\tint i;\n\t\n\t//if (!PWM_Enable)\n\t//\treturn;\n\t\n\tif (chip->PWM_Out_L == 0 && chip->PWM_Out_R == 0)\n\t{\n\t\tmemset(buf[0], 0x00, length * sizeof(int));\n\t\tmemset(buf[1], 0x00, length * sizeof(int));\n\t\treturn;\n\t}\n\t\n\t// New PWM scaling algorithm provided by Chilly Willy on the Sonic Retro forums.\n\ttmpOutL = PWM_Update_Scale(chip, (int)chip->PWM_Out_L);\n\ttmpOutR = PWM_Update_Scale(chip, (int)chip->PWM_Out_R);\n\t\n\tfor (i = 0; i < length; i ++)\n\t{\n\t\tbuf[0][i] = tmpOutL;\n\t\tbuf[1][i] = tmpOutR;\n\t}\n}\n\n\nvoid pwm_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tpwm_chip *chip = &PWM_Chip[ChipID];\n\t\n\tPWM_Update(chip, outputs, samples);\n}\n\nint device_start_pwm(UINT8 ChipID, int clock)\n{\n\t/* allocate memory for the chip */\n\t//pwm_state *chip = get_safe_token(device);\n\tpwm_chip *chip;\n\tint rate;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &PWM_Chip[ChipID];\n\trate = 22020;\t// that's the rate the PWM is mostly used\n\tif (((CHIP_SAMPLING_MODE & 0x01) && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\tchip->clock = clock;\n\t\n\tPWM_Init(chip);\n\t/* allocate the stream */\n\t//chip->stream = stream_create(device, 0, 2, device->clock / 384, chip, rf5c68_update);\n\t\n\treturn rate;\n}\n\nvoid device_stop_pwm(UINT8 ChipID)\n{\n\t//pwm_chip *chip = &PWM_Chip[ChipID];\n\t//free(chip->ram);\n\t\n\treturn;\n}\n\nvoid device_reset_pwm(UINT8 ChipID)\n{\n\tpwm_chip *chip = &PWM_Chip[ChipID];\n\tPWM_Init(chip);\n}\n\nvoid pwm_chn_w(UINT8 ChipID, UINT8 Channel, UINT16 data)\n{\n\tpwm_chip *chip = &PWM_Chip[ChipID];\n\t\n\tif (chip->clock == 1)\n\t{\t// old-style commands\n\t\tswitch(Channel)\n\t\t{\n\t\tcase 0x00:\n\t\t\tchip->PWM_Out_L = data;\n\t\t\tbreak;\n\t\tcase 0x01:\n\t\t\tchip->PWM_Out_R = data;\n\t\t\tbreak;\n\t\tcase 0x02:\n\t\t\tPWM_Set_Cycle(chip, data);\n\t\t\tbreak;\n\t\tcase 0x03:\n\t\t\tchip->PWM_Out_L = data;\n\t\t\tchip->PWM_Out_R = data;\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\tswitch(Channel)\n\t\t{\n\t\tcase 0x00/2:\t// control register\n\t\t\tPWM_Set_Int(chip, data >> 8);\n\t\t\tbreak;\n\t\tcase 0x02/2:\t// cycle register\n\t\t\tPWM_Set_Cycle(chip, data);\n\t\t\tbreak;\n\t\tcase 0x04/2:\t// l ch\n\t\t\tchip->PWM_Out_L = data;\n\t\t\tbreak;\n\t\tcase 0x06/2:\t// r ch\n\t\t\tchip->PWM_Out_R = data;\n\t\t\tif (! chip->PWM_Mode)\n\t\t\t{\n\t\t\t\tif (chip->PWM_Out_L == chip->PWM_Out_R)\n\t\t\t\t{\n\t\t\t\t\t// fixes these terrible pops when\n\t\t\t\t\t// starting/stopping/pausing the song\n\t\t\t\t\tchip->PWM_Offset = data;\n\t\t\t\t\tchip->PWM_Mode = 0x01;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 0x08/2:\t// mono ch\n\t\t\tchip->PWM_Out_L = data;\n\t\t\tchip->PWM_Out_R = data;\n\t\t\tif (! chip->PWM_Mode)\n\t\t\t{\n\t\t\t\tchip->PWM_Offset = data;\n\t\t\t\tchip->PWM_Mode = 0x01;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/pwm.h",
    "content": "/***************************************************************************\n * Gens: PWM audio emulator.                                               *\n *                                                                         *\n * Copyright (c) 1999-2002 by Stphane Dallongeville                       *\n * Copyright (c) 2003-2004 by Stphane Akhoun                              *\n * Copyright (c) 2008 by David Korth                                       *\n *                                                                         *\n * This program is free software; you can redistribute it and/or modify it *\n * under the terms of the GNU General Public License as published by the   *\n * Free Software Foundation; either version 2 of the License, or (at your  *\n * option) any later version.                                              *\n *                                                                         *\n * This program is distributed in the hope that it will be useful, but     *\n * WITHOUT ANY WARRANTY; without even the implied warranty of              *\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *\n * GNU General Public License for more details.                            *\n *                                                                         *\n * You should have received a copy of the GNU General Public License along *\n * with this program; if not, write to the Free Software Foundation, Inc., *\n * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.           *\n ***************************************************************************/\n\n#define PWM_BUF_SIZE 4\n/*extern unsigned char PWM_FULL_TAB[PWM_BUF_SIZE * PWM_BUF_SIZE];\n\nextern unsigned short PWM_FIFO_R[8];\nextern unsigned short PWM_FIFO_L[8];\nextern unsigned int PWM_RP_R;\nextern unsigned int PWM_WP_R;\nextern unsigned int PWM_RP_L;\nextern unsigned int PWM_WP_L;\nextern unsigned int PWM_Cycles;\nextern unsigned int PWM_Cycle;\nextern unsigned int PWM_Cycle_Cnt;\nextern unsigned int PWM_Int;\nextern unsigned int PWM_Int_Cnt;\nextern unsigned int PWM_Mode;\nextern unsigned int PWM_Enable;\nextern unsigned int PWM_Out_R;\nextern unsigned int PWM_Out_L;*/\n\n//void PWM_Init(void);\n//void PWM_Recalc_Scale(void);\n\n/* Functions called by x86 asm. */\n//void PWM_Set_Cycle(unsigned int cycle);\n//void PWM_Set_Int(unsigned int int_time);\n\n/* Functions called by C/C++ code only. */\n//void PWM_Clear_Timer(void);\n//void PWM_Update_Timer(unsigned int cycle);\n//void PWM_Update(int **buf, int length);\n\n\nvoid pwm_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_pwm(UINT8 ChipID, int clock);\nvoid device_stop_pwm(UINT8 ChipID);\nvoid device_reset_pwm(UINT8 ChipID);\n\nvoid pwm_chn_w(UINT8 ChipID, UINT8 Channel, UINT16 data);\n"
  },
  {
    "path": "VGMPlay/chips/qsound_ctr.c",
    "content": "/*\n\n\tCapcom DL-1425 QSound emulator\n\t==============================\n\t\n\tby superctr (Ian Karlsson)\n\twith thanks to Valley Bell\n\n\t2018-05-12 - 2018-05-15\n\n*/\n\n//#include \"emu.h\"\n#include \"mamedef.h\"\n#ifdef _DEBUG\n#include <stdio.h>\n#endif\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include <math.h>\n#include \"qsound_ctr.h\"\n\n\n#define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))\n\nstruct qsound_voice {\n\tUINT16 bank;\n\tINT16 addr; // top word is the sample address\n\tUINT16 phase;\n\tUINT16 rate;\n\tINT16 loop_len;\n\tINT16 end_addr;\n\tINT16 volume;\n\tINT16 echo;\n};\n\nstruct qsound_adpcm {\n\tUINT16 start_addr;\n\tUINT16 end_addr;\n\tUINT16 bank;\n\tINT16 volume;\n\tUINT16 flag;\n\tINT16 cur_vol;\n\tINT16 step_size;\n\tUINT16 cur_addr;\n};\n\n// Q1 Filter\nstruct qsound_fir {\n\tint tap_count;\t// usually 95\n\tint delay_pos;\n\tINT16 table_pos;\n\tINT16 taps[95];\n\tINT16 delay_line[95];\n};\n\n// Delay line\nstruct qsound_delay {\n\tINT16 delay;\n\tINT16 volume;\n\tINT16 write_pos;\n\tINT16 read_pos;\n\tINT16 delay_line[51];\n};\n\nstruct qsound_echo {\n\tUINT16 end_pos;\n\t\n\tINT16 feedback;\n\tINT16 length;\n\tINT16 last_sample;\n\tINT16 delay_line[1024];\n\tINT16 delay_pos;\n};\n\nstruct qsound_chip {\n\n\tUINT8* romData;\n\tUINT32 romSize;\n\tUINT32 romMask;\n\tUINT32 muteMask;\n\t\n\t// ==================================================== //\n\n\tUINT16 data_latch;\n\tINT16 out[2];\n\n\tINT16 pan_tables[2][2][98];\n\n\tstruct qsound_voice voice[16];\n\tstruct qsound_adpcm adpcm[3];\n\n\tUINT16 voice_pan[16+3];\n\tINT16 voice_output[16+3];\n\n\tstruct qsound_echo echo;\n\n\tstruct qsound_fir filter[2];\n\tstruct qsound_fir alt_filter[2];\n\n\tstruct qsound_delay wet[2];\n\tstruct qsound_delay dry[2];\n\n\tUINT16 state;\n\tUINT16 next_state;\n\n\tUINT16 delay_update;\n\n\tint state_counter;\n\tUINT8 ready_flag;\n\n\tUINT16 *register_map[256];\n};\n\nstatic void init_pan_tables(struct qsound_chip *chip);\nstatic void init_register_map(struct qsound_chip *chip);\nstatic void update_sample(struct qsound_chip *chip);\n\nstatic void state_init(struct qsound_chip *chip);\nstatic void state_refresh_filter_1(struct qsound_chip *chip);\nstatic void state_refresh_filter_2(struct qsound_chip *chip);\nstatic void state_normal_update(struct qsound_chip *chip);\n\nINLINE INT16 get_sample(struct qsound_chip *chip, UINT16 bank,UINT16 address);\nINLINE const INT16* get_filter_table(struct qsound_chip *chip, UINT16 offset);\nINLINE INT16 pcm_update(struct qsound_chip *chip, int voice_no, INT32 *echo_out);\nINLINE void adpcm_update(struct qsound_chip *chip, int voice_no, int nibble);\nINLINE INT16 echo(struct qsound_echo *r,INT32 input);\nINLINE INT32 fir(struct qsound_fir *f, INT16 input);\nINLINE INT32 delay(struct qsound_delay *d, INT32 input);\nINLINE void delay_update(struct qsound_delay *d);\n\n// ****************************************************************************\n\n#define MAX_CHIPS\t0x02\nstatic struct qsound_chip QSoundData[MAX_CHIPS];\n\nint device_start_qsound_ctr(UINT8 ChipID, int clock)\n{\n\tstruct qsound_chip* chip = &QSoundData[ChipID];\n\t\n\tmemset(chip,0,sizeof(*chip));\n\t\n\tchip->romData = NULL;\n\tchip->romSize = 0x00;\n\tchip->romMask = 0x00;\n\t\n\tqsoundc_set_mute_mask(ChipID, 0x00000);\n\t\n\tinit_pan_tables(chip);\n\tinit_register_map(chip);\n\t\n\treturn clock / 2 / 1248;\n}\n\nvoid device_stop_qsound_ctr(UINT8 ChipID)\n{\n\tstruct qsound_chip* chip = &QSoundData[ChipID];\n\t\n\tfree(chip->romData);\n\t\n\treturn;\n}\n\nvoid device_reset_qsound_ctr(UINT8 ChipID)\n{\n\tstruct qsound_chip* chip = &QSoundData[ChipID];\n\t\n\tchip->ready_flag = 0;\n\tchip->out[0] = chip->out[1] = 0;\n\tchip->state = 0;\n\tchip->state_counter = 0;\n\t\n\treturn;\n}\n\nUINT8 qsoundc_r(UINT8 ChipID, offs_t offset)\n{\n\tstruct qsound_chip* chip = &QSoundData[ChipID];\n\t\n\treturn chip->ready_flag;\n}\n\nvoid qsoundc_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tstruct qsound_chip* chip = &QSoundData[ChipID];\n\t\n\tswitch (offset)\n\t{\n\t\tcase 0:\n\t\t\tchip->data_latch = (chip->data_latch & 0x00ff) | (data << 8);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tchip->data_latch = (chip->data_latch & 0xff00) | data;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tqsoundc_write_data(ChipID, data, chip->data_latch);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\nvoid qsoundc_write_data(UINT8 ChipID, UINT8 address, UINT16 data)\n{\n\tstruct qsound_chip* chip = &QSoundData[ChipID];\n\t\n\tUINT16 *destination = chip->register_map[address];\n\tif(destination)\n\t\t*destination = data;\n\tchip->ready_flag = 0;\n\n\treturn;\n}\n\nvoid qsoundc_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tstruct qsound_chip* chip = &QSoundData[ChipID];\n\tUINT32 curSmpl;\n\t\n\tmemset(outputs[0], 0, samples * sizeof(*outputs[0]));\n\tmemset(outputs[1], 0, samples * sizeof(*outputs[1]));\n\t\n\tfor (curSmpl = 0; curSmpl < samples; curSmpl ++)\n\t{\n\t\tupdate_sample(chip);\n\t\toutputs[0][curSmpl] = chip->out[0];\n\t\toutputs[1][curSmpl] = chip->out[1];\n\t}\n\t\n\treturn;\n}\n\nvoid qsoundc_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t  const UINT8* ROMData)\n{\n\tstruct qsound_chip* chip = &QSoundData[ChipID];\n\t\n\tif (chip->romSize != ROMSize)\n\t{\n\t\tchip->romData = (UINT8*)realloc(chip->romData, ROMSize);\n\t\tchip->romSize = ROMSize;\n\t\tmemset(chip->romData, 0xFF, ROMSize);\n\t\tchip->romMask = -1;\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(chip->romData + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\nvoid qsoundc_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tstruct qsound_chip* chip = &QSoundData[ChipID];\n\t\n\tchip->muteMask = MuteMask;\n\t\n\treturn;\n}\n\nvoid qsoundc_wait_busy(UINT8 ChipID)\n{\n\tstruct qsound_chip* chip = &QSoundData[ChipID];\n\t\n\twhile(chip->ready_flag == 0)\n\t{\n\t\tupdate_sample(chip);\n\t}\n}\n\n// ============================================================================\n\nstatic const INT16 qsound_dry_mix_table[33] = {\n\t-16384,-16384,-16384,-16384,-16384,-16384,-16384,-16384,\n\t-16384,-16384,-16384,-16384,-16384,-16384,-16384,-16384,\n\t-16384,-14746,-13107,-11633,-10486,-9175,-8520,-7209,\n\t-6226,-5226,-4588,-3768,-3277,-2703,-2130,-1802,\n\t0\n};\n\nstatic const INT16 qsound_wet_mix_table[33] = {\n\t0,-1638,-1966,-2458,-2949,-3441,-4096,-4669,\n\t-4915,-5120,-5489,-6144,-7537,-8831,-9339,-9830,\n\t-10240,-10322,-10486,-10568,-10650,-11796,-12288,-12288,\n\t-12534,-12648,-12780,-12829,-12943,-13107,-13418,-14090,\n\t-16384\n};\n\nstatic const INT16 qsound_linear_mix_table[33] = {\n\t-16379,-16338,-16257,-16135,-15973,-15772,-15531,-15251,\n\t-14934,-14580,-14189,-13763,-13303,-12810,-12284,-11729,\n\t-11729,-11144,-10531,-9893,-9229,-8543,-7836,-7109,\n\t-6364,-5604,-4829,-4043,-3246,-2442,-1631,-817,\n\t0\n};\n\nstatic const INT16 qsound_filter_data[5][95] = {\n\t{\t// d53 - 0\n\t\t0,0,0,6,44,-24,-53,-10,59,-40,-27,1,39,-27,56,127,174,36,-13,49,\n\t\t212,142,143,-73,-20,66,-108,-117,-399,-265,-392,-569,-473,-71,95,-319,-218,-230,331,638,\n\t\t449,477,-180,532,1107,750,9899,3828,-2418,1071,-176,191,-431,64,117,-150,-274,-97,-238,165,\n\t\t166,250,-19,4,37,204,186,-6,140,-77,-1,1,18,-10,-151,-149,-103,-9,55,23,\n\t\t-102,-97,-11,13,-48,-27,5,18,-61,-30,64,72,0,0,0,\n\t},\n\t{\t// db2 - 1 - default left filter\n\t\t0,0,0,85,24,-76,-123,-86,-29,-14,-20,-7,6,-28,-87,-89,-5,100,154,160,\n\t\t150,118,41,-48,-78,-23,59,83,-2,-176,-333,-344,-203,-66,-39,2,224,495,495,280,\n\t\t432,1340,2483,5377,1905,658,0,97,347,285,35,-95,-78,-82,-151,-192,-171,-149,-147,-113,\n\t\t-22,71,118,129,127,110,71,31,20,36,46,23,-27,-63,-53,-21,-19,-60,-92,-69,\n\t\t-12,25,29,30,40,41,29,30,46,39,-15,-74,0,0,0,\n\t},\n\t{\t// e11 - 2 - default right filter\n\t\t0,0,0,23,42,47,29,10,2,-14,-54,-92,-93,-70,-64,-77,-57,18,94,113,\n\t\t87,69,67,50,25,29,58,62,24,-39,-131,-256,-325,-234,-45,58,78,223,485,496,\n\t\t127,6,857,2283,2683,4928,1328,132,79,314,189,-80,-90,35,-21,-186,-195,-99,-136,-258,\n\t\t-189,82,257,185,53,41,84,68,38,63,77,14,-60,-71,-71,-120,-151,-84,14,29,\n\t\t-8,7,66,69,12,-3,54,92,52,-6,-15,-2,0,0,0,\n\t},\n\t{\t// e70 - 3\n\t\t0,0,0,2,-28,-37,-17,0,-9,-22,-3,35,52,39,20,7,-6,2,55,121,\n\t\t129,67,8,1,9,-6,-16,16,66,96,118,130,75,-47,-92,43,223,239,151,219,\n\t\t440,475,226,206,940,2100,2663,4980,865,49,-33,186,231,103,42,114,191,184,116,29,\n\t\t-47,-72,-21,60,96,68,31,32,63,87,76,39,7,14,55,85,67,18,-12,-3,\n\t\t21,34,29,6,-27,-49,-37,-2,16,0,-21,-16,0,0,0,\n\t},\n\t{\t// ecf - 4\n\t\t0,0,0,48,7,-22,-29,-10,24,54,59,29,-36,-117,-185,-213,-185,-99,13,90,\n\t\t83,24,-5,23,53,47,38,56,67,57,75,107,16,-242,-440,-355,-120,-33,-47,152,\n\t\t501,472,-57,-292,544,1937,2277,6145,1240,153,47,200,152,36,64,134,74,-82,-208,-266,\n\t\t-268,-188,-42,65,74,56,89,133,114,44,-3,-1,17,29,29,-2,-76,-156,-187,-151,\n\t\t-85,-31,-5,7,20,32,24,-5,-20,6,48,62,0,0,0,\n\t}\n};\n\nstatic const INT16 qsound_filter_data2[209] = {\n\t// f2e - following 95 values used for \"disable output\" filter\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,\n\t\n\t// f73 - following 45 values used for \"mode 2\" filter (overlaps with f2e)\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,\n\t-371,-196,-268,-512,-303,-315,-184,-76,276,-256,298,196,990,236,1114,-126,4377,6549,791,\n\t\n\t// fa0 - filtering disabled (for 95-taps) (use fa3 or fa4 for mode2 filters)\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,-16384,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n};\n\nstatic const INT16 adpcm_step_table[16] = {\n\t154, 154, 128, 102, 77, 58, 58, 58,\n\t58, 58, 58, 58, 77, 102, 128, 154\n};\n\n// DSP states\nenum {\n\tSTATE_INIT1\t\t= 0x288,\n\tSTATE_INIT2\t\t= 0x61a,\n\tSTATE_REFRESH1\t= 0x039,\n\tSTATE_REFRESH2\t= 0x04f,\n\tSTATE_NORMAL1\t= 0x314,\n\tSTATE_NORMAL2 \t= 0x6b2,\n};\n\nenum {\n\tPANTBL_LEFT\t\t= 0,\n\tPANTBL_RIGHT\t= 1,\n\tPANTBL_DRY\t\t= 0,\n\tPANTBL_WET\t\t= 1,\n};\n\nstatic void init_pan_tables(struct qsound_chip *chip)\n{\n\tint i;\n\tfor(i=0;i<33;i++)\n\t{\n\t\t// dry mixing levels\n\t\tchip->pan_tables[PANTBL_LEFT][PANTBL_DRY][i] = qsound_dry_mix_table[i]; \n\t\tchip->pan_tables[PANTBL_RIGHT][PANTBL_DRY][i] = qsound_dry_mix_table[32-i];\n\t\t// wet mixing levels\n\t\tchip->pan_tables[PANTBL_LEFT][PANTBL_WET][i] = qsound_wet_mix_table[i]; \n\t\tchip->pan_tables[PANTBL_RIGHT][PANTBL_WET][i] = qsound_wet_mix_table[32-i];\n\t\t// linear panning, only for dry component. wet component is muted.\n\t\tchip->pan_tables[PANTBL_LEFT][PANTBL_DRY][i+0x30] = qsound_linear_mix_table[i];\n\t\tchip->pan_tables[PANTBL_RIGHT][PANTBL_DRY][i+0x30] = qsound_linear_mix_table[32-i]; \n\t}\n}\n\nstatic void init_register_map(struct qsound_chip *chip)\n{\n\tint i;\n\t\n\t// unused registers\n\tfor(i=0;i<256;i++)\n\t\tchip->register_map[i] = NULL;\n\t\n\t// PCM registers\n\tfor(i=0;i<16;i++) // PCM voices\n\t{\n\t\tchip->register_map[(i<<3)+0] = (UINT16*)&chip->voice[(i+1)%16].bank; // Bank applies to the next channel\n\t\tchip->register_map[(i<<3)+1] = (UINT16*)&chip->voice[i].addr; // Current sample position and start position.\n\t\tchip->register_map[(i<<3)+2] = (UINT16*)&chip->voice[i].rate; // 4.12 fixed point decimal.\n\t\tchip->register_map[(i<<3)+3] = (UINT16*)&chip->voice[i].phase;\n\t\tchip->register_map[(i<<3)+4] = (UINT16*)&chip->voice[i].loop_len;\n\t\tchip->register_map[(i<<3)+5] = (UINT16*)&chip->voice[i].end_addr;\n\t\tchip->register_map[(i<<3)+6] = (UINT16*)&chip->voice[i].volume;\n\t\tchip->register_map[(i<<3)+7] = NULL;\t// unused\n\t\tchip->register_map[i+0x80] = (UINT16*)&chip->voice_pan[i];\n\t\tchip->register_map[i+0xba] = (UINT16*)&chip->voice[i].echo;\n\t}\n\t\n\t// ADPCM registers\n\tfor(i=0;i<3;i++) // ADPCM voices\n\t{\n\t\t// ADPCM sample rate is fixed to 8khz. (one channel is updated every third sample)\n\t\tchip->register_map[(i<<2)+0xca] = (UINT16*)&chip->adpcm[i].start_addr;\n\t\tchip->register_map[(i<<2)+0xcb] = (UINT16*)&chip->adpcm[i].end_addr;\n\t\tchip->register_map[(i<<2)+0xcc] = (UINT16*)&chip->adpcm[i].bank;\n\t\tchip->register_map[(i<<2)+0xcd] = (UINT16*)&chip->adpcm[i].volume;\n\t\tchip->register_map[i+0xd6] = (UINT16*)&chip->adpcm[i].flag; // non-zero to start ADPCM playback\n\t\tchip->register_map[i+0x90] = (UINT16*)&chip->voice_pan[16+i];\n\t}\n\t\n\t// QSound registers\n\tchip->register_map[0x93] = (UINT16*)&chip->echo.feedback;\n\tchip->register_map[0xd9] = (UINT16*)&chip->echo.end_pos;\n\tchip->register_map[0xe2] = (UINT16*)&chip->delay_update; // non-zero to update delays\n\tchip->register_map[0xe3] = (UINT16*)&chip->next_state;\n\tfor(i=0;i<2;i++)  // left, right\n\t{\n\t\t// Wet\n\t\tchip->register_map[(i<<1)+0xda] = (UINT16*)&chip->filter[i].table_pos;\n\t\tchip->register_map[(i<<1)+0xde] = (UINT16*)&chip->wet[i].delay;\n\t\tchip->register_map[(i<<1)+0xe4] = (UINT16*)&chip->wet[i].volume;\n\t\t// Dry\n\t\tchip->register_map[(i<<1)+0xdb] = (UINT16*)&chip->alt_filter[i].table_pos;\n\t\tchip->register_map[(i<<1)+0xdf] = (UINT16*)&chip->dry[i].delay;\n\t\tchip->register_map[(i<<1)+0xe5] = (UINT16*)&chip->dry[i].volume;\n\t}\n}\n\nINLINE INT16 get_sample(struct qsound_chip *chip, UINT16 bank,UINT16 address)\n{\n\tUINT32 rom_addr;\n\tUINT8 sample_data;\n\n\tif (! chip->romMask)\n\t\treturn 0;\t// no ROM loaded\n\tif (! (bank & 0x8000))\n\t\treturn 0;\t// ignore attempts to read from DSP program ROM\n\n\tbank &= 0x7FFF;\n\trom_addr = (bank << 16) | (address << 0);\n\t\n\tsample_data = chip->romData[rom_addr];\n\t\n\treturn (INT16)((sample_data << 8) | (sample_data << 0));\t// MAME currently expands the 8 bit ROM data to 16 bits this way.\n}\n\nINLINE const INT16* get_filter_table(struct qsound_chip *chip, UINT16 offset)\n{\n\tint index;\n\t\n\tif (offset >= 0xf2e && offset < 0xfff)\n\t\treturn &qsound_filter_data2[offset-0xf2e];\t// overlapping filter data\n\t\n\tindex = (offset-0xd53)/95;\n\tif(index >= 0 && index < 5)\n\t\treturn qsound_filter_data[index];\t// normal tables\n\t\n\treturn NULL;\t// no filter found.\n}\n\n/********************************************************************/\n\n// updates one DSP sample\nstatic void update_sample(struct qsound_chip *chip)\n{\n\tswitch(chip->state)\n\t{\n\t\tdefault:\n\t\tcase STATE_INIT1:\n\t\tcase STATE_INIT2:\n\t\t\tstate_init(chip);\n\t\t\treturn;\n\t\tcase STATE_REFRESH1:\n\t\t\tstate_refresh_filter_1(chip);\n\t\t\treturn;\n\t\tcase STATE_REFRESH2:\n\t\t\tstate_refresh_filter_2(chip);\n\t\t\treturn;\n\t\tcase STATE_NORMAL1:\n\t\tcase STATE_NORMAL2:\n\t\t\tstate_normal_update(chip);\n\t\t\treturn;\n\t}\n}\n\n// Initialization routine\nstatic void state_init(struct qsound_chip *chip)\n{\n\tint mode = (chip->state == STATE_INIT2) ? 1 : 0;\n\tint i;\n\t\n\t// we're busy for 4 samples, including the filter refresh.\n\tif(chip->state_counter >= 2)\n\t{\n\t\tchip->state_counter = 0;\n\t\tchip->state = chip->next_state;\n\t\treturn;\n\t}\n\telse if(chip->state_counter == 1)\n\t{\n\t\tchip->state_counter++;\n\t\treturn;\n\t}\n\t\n\tmemset(chip->voice, 0, sizeof(chip->voice));\n\tmemset(chip->adpcm, 0, sizeof(chip->adpcm));\n\tmemset(chip->filter, 0, sizeof(chip->filter));\n\tmemset(chip->alt_filter, 0, sizeof(chip->alt_filter));\n\tmemset(chip->wet, 0, sizeof(chip->wet));\n\tmemset(chip->dry, 0, sizeof(chip->dry));\n\tmemset(&chip->echo, 0, sizeof(chip->echo));\n\t\n\tfor(i=0;i<19;i++)\n\t{\n\t\tchip->voice_pan[i] = 0x120;\n\t\tchip->voice_output[i] = 0;\n\t}\n\n\tfor(i=0;i<16;i++)\n\t\tchip->voice[i].bank = 0x8000;\n\tfor(i=0;i<3;i++)\n\t\tchip->adpcm[i].bank = 0x8000;\n\t\n\tif(mode == 0)\n\t{\n\t\t// mode 1\n\t\tchip->wet[0].delay = 0;\n\t\tchip->dry[0].delay = 46;\n\t\tchip->wet[1].delay = 0;\n\t\tchip->dry[1].delay = 48;\n\t\tchip->filter[0].table_pos = 0xdb2;\n\t\tchip->filter[1].table_pos = 0xe11;\n\t\tchip->echo.end_pos = 0x554 + 6;\n\t\tchip->next_state = STATE_REFRESH1;\n\t}\n\telse\n\t{\n\t\t// mode 2\n\t\tchip->wet[0].delay = 1;\n\t\tchip->dry[0].delay = 0;\n\t\tchip->wet[1].delay = 0;\n\t\tchip->dry[1].delay = 0;\n\t\tchip->filter[0].table_pos = 0xf73;\n\t\tchip->filter[1].table_pos = 0xfa4;\n\t\tchip->alt_filter[0].table_pos = 0xf73;\n\t\tchip->alt_filter[1].table_pos = 0xfa4;\n\t\tchip->echo.end_pos = 0x53c + 6;\n\t\tchip->next_state = STATE_REFRESH2;\n\t}\n\n\tchip->wet[0].volume = 0x3fff;\n\tchip->dry[0].volume = 0x3fff;\n\tchip->wet[1].volume = 0x3fff;\n\tchip->dry[1].volume = 0x3fff;\n\t\n\tchip->delay_update = 1;\n\tchip->ready_flag = 0;\n\tchip->state_counter = 1;\n}\n\n// Updates filter parameters for mode 1\nstatic void state_refresh_filter_1(struct qsound_chip *chip)\n{\n\tconst INT16 *table;\n\tint ch;\n\t\n\tfor(ch=0; ch<2; ch++)\n\t{\n\t\tchip->filter[ch].delay_pos = 0;\n\t\tchip->filter[ch].tap_count = 95;\n\t\n\t\ttable = get_filter_table(chip,chip->filter[ch].table_pos);\n\t\tif (table != NULL)\n\t\t\tmemcpy(chip->filter[ch].taps, table, 95 * sizeof(INT16));\n\t}\n\t\n\tchip->state = chip->next_state = STATE_NORMAL1;\n}\n\n// Updates filter parameters for mode 2\nstatic void state_refresh_filter_2(struct qsound_chip *chip)\n{\n\tconst INT16 *table;\n\tint ch;\n\t\n\tfor(ch=0; ch<2; ch++)\n\t{\n\t\tchip->filter[ch].delay_pos = 0;\n\t\tchip->filter[ch].tap_count = 45;\n\t\n\t\ttable = get_filter_table(chip,chip->filter[ch].table_pos);\n\t\tif (table != NULL)\n\t\t\tmemcpy(chip->filter[ch].taps, table, 45 * sizeof(INT16));\n\t\t\n\t\tchip->alt_filter[ch].delay_pos = 0;\n\t\tchip->alt_filter[ch].tap_count = 44;\n\t\n\t\ttable = get_filter_table(chip,chip->alt_filter[ch].table_pos);\n\t\tif (table != NULL)\n\t\t\tmemcpy(chip->alt_filter[ch].taps, table, 44 * sizeof(INT16));\n\t}\n\t\n\tchip->state = chip->next_state = STATE_NORMAL2;\n}\n\n// Updates a PCM voice. There are 16 voices, each are updated every sample\n// with full rate and volume control.\nINLINE INT16 pcm_update(struct qsound_chip *chip, int voice_no, INT32 *echo_out)\n{\n\tstruct qsound_voice *v = &chip->voice[voice_no];\n\tINT32 new_phase;\n\tINT16 output;\n\t\n\tif (chip->muteMask & (1<<voice_no))\n\t\treturn 0;\n\t\n\t// Read sample from rom and apply volume\n\toutput = (v->volume * get_sample(chip, v->bank, v->addr))>>14;\n\t\n\t*echo_out += (output * v->echo)<<2;\n\t\n\t// Add delta to the phase and loop back if required\n\tnew_phase = v->rate + ((v->addr<<12) | (v->phase>>4));\n\t\n\tif((new_phase>>12) >= v->end_addr)\n\t\tnew_phase -= (v->loop_len<<12);\n\t\n\tnew_phase = CLAMP(new_phase, -0x8000000, 0x7FFFFFF);\n\tv->addr = new_phase>>12;\n\tv->phase = (new_phase<<4)&0xffff;\n\t\n\treturn output;\n}\n\n// Updates an ADPCM voice. There are 3 voices, one is updated every sample\n// (effectively making the ADPCM rate 1/3 of the master sample rate), and\n// volume is set when starting samples only.\n// The ADPCM algorithm is supposedly similar to Yamaha ADPCM. It also seems\n// like Capcom never used it, so this was not emulated in the earlier QSound\n// emulators.\nINLINE void adpcm_update(struct qsound_chip *chip, int voice_no, int nibble)\n{\n\tstruct qsound_adpcm *v = &chip->adpcm[voice_no];\n\n\tINT32 delta;\n\tINT8 step;\n\n\tif (chip->muteMask & (1<<(16+voice_no)))\n\t{\n\t\tchip->voice_output[16+voice_no] = 0;\n\t\treturn;\n\t}\n\n\tif(!nibble)\n\t{\n\t\t// Mute voice when it reaches the end address.\n\t\tif(v->cur_addr == v->end_addr)\n\t\t\tv->cur_vol = 0;\n\t\t\n\t\t// Playback start flag\n\t\tif(v->flag)\n\t\t{\n\t\t\tchip->voice_output[16+voice_no] = 0;\n\t\t\tv->flag = 0;\n\t\t\tv->step_size = 10;\n\t\t\tv->cur_vol = v->volume;\n\t\t\tv->cur_addr = v->start_addr;\n\t\t}\n\t\t\n\t\t// get top nibble\n\t\tstep = get_sample(chip, v->bank, v->cur_addr) >> 8;\n\t}\n\telse\n\t{\n\t\t// get bottom nibble\n\t\tstep = get_sample(chip, v->bank, v->cur_addr++) >> 4;\n\t}\n\n\t// shift with sign extend\n\tstep >>= 4;\n\t\n\t// delta = (0.5 + abs(v->step)) * v->step_size\n\tdelta = ((1+abs(step<<1)) * v->step_size)>>1;\n\tif(step <= 0)\n\t\tdelta = -delta;\n\tdelta += chip->voice_output[16+voice_no];\n\tdelta = CLAMP(delta,-32768,32767);\n\t\n\tchip->voice_output[16+voice_no] = (delta * v->cur_vol)>>16;\n\t\n\tv->step_size = (adpcm_step_table[8+step] * v->step_size) >> 6;\n\tv->step_size = CLAMP(v->step_size, 1, 2000);\n}\n\n// The echo effect is pretty simple. A moving average filter is used on\n// the output from the delay line to smooth samples over time. \nINLINE INT16 echo(struct qsound_echo *r,INT32 input)\n{\n\t// get average of last 2 samples from the delay line\n\tINT32 new_sample;\n\tINT32 old_sample = r->delay_line[r->delay_pos];\n\tINT32 last_sample = r->last_sample;\n\t\n\tr->last_sample = old_sample;\n\told_sample = (old_sample+last_sample) >> 1;\n\t\n\t// add current sample to the delay line\n\tnew_sample = input + ((old_sample * r->feedback)<<2);\n\tr->delay_line[r->delay_pos++] = new_sample>>16;\n\t\n\tif(r->delay_pos >= r->length)\n\t\tr->delay_pos = 0;\n\t\n\treturn old_sample;\n}\n\n// Process a sample update\nstatic void state_normal_update(struct qsound_chip *chip)\n{\n\tint v, ch;\n\tINT32 echo_input = 0;\n\tINT16 echo_output;\n\t\n\tchip->ready_flag = 0x80;\n\n\t// recalculate echo length\n\tif(chip->state == STATE_NORMAL2)\n\t\tchip->echo.length = chip->echo.end_pos - 0x53c;\n\telse\n\t\tchip->echo.length = chip->echo.end_pos - 0x554;\n\t\n\tchip->echo.length = CLAMP(chip->echo.length, 0, 1024);\n\t\n\t// update PCM voices\n\tfor(v=0; v<16; v++)\n\t\tchip->voice_output[v] = pcm_update(chip, v, &echo_input);\n\n\t// update ADPCM voices (one every third sample)\n\tadpcm_update(chip, chip->state_counter % 3, chip->state_counter / 3);\n\t\n\techo_output = echo(&chip->echo,echo_input);\n\t\n\t// now, we do the magic stuff\n\tfor(ch=0; ch<2; ch++)\n\t{\n\t\t// Echo is output on the unfiltered component of the left channel and\n\t\t// the filtered component of the right channel.\n\t\tINT32 wet = (ch == 1) ? echo_output<<14 : 0;\n\t\tINT32 dry = (ch == 0) ? echo_output<<14 : 0;\n\t\tINT32 output = 0;\n\t\t\n\t\tfor(v=0; v<19; v++)\n\t\t{\n\t\t\tUINT16 pan_index = chip->voice_pan[v]-0x110;\n\t\t\tif(pan_index > 97)\n\t\t\t\tpan_index = 97;\n\t\t\t\n\t\t\t// Apply different volume tables on the dry and wet inputs.\n\t\t\tdry -= (chip->voice_output[v] * chip->pan_tables[ch][PANTBL_DRY][pan_index]);\n\t\t\twet -= (chip->voice_output[v] * chip->pan_tables[ch][PANTBL_WET][pan_index]);\n\t\t}\n\n\t\t// Saturate accumulated voices\n\t\tdry = CLAMP(dry, -0x1fffffff, 0x1fffffff) << 2;\n\t\twet = CLAMP(wet, -0x1fffffff, 0x1fffffff) << 2;\n\t\t\n\t\t// Apply FIR filter on 'wet' input\n\t\twet = fir(&chip->filter[ch], wet >> 16);\n\t\t\n\t\t// in mode 2, we do this on the 'dry' input too\n\t\tif(chip->state == STATE_NORMAL2)\n\t\t\tdry = fir(&chip->alt_filter[ch], dry >> 16);\n\t\t\n\t\t// output goes through a delay line and attenuation\n\t\toutput = (delay(&chip->wet[ch], wet) + delay(&chip->dry[ch], dry));\n\t\t\n\t\t// DSP round function\n\t\toutput = ((output + 0x2000) & ~0x3fff) >> 14;\n\t\tchip->out[ch] = CLAMP(output, -0x7fff, 0x7fff);\n\t\t\n\t\tif(chip->delay_update)\n\t\t{\n\t\t\tdelay_update(&chip->wet[ch]);\n\t\t\tdelay_update(&chip->dry[ch]);\n\t\t}\n\t}\n\t\n\tchip->delay_update = 0;\n\t\n\t// after 6 samples, the next state is executed.\n\tchip->state_counter++;\n\tif(chip->state_counter > 5)\n\t{\n\t\tchip->state_counter = 0;\n\t\tchip->state = chip->next_state;\n\t}\n}\n\n// Apply the FIR filter used as the Q1 transfer function\nINLINE INT32 fir(struct qsound_fir *f, INT16 input)\n{\n\tINT32 output = 0, tap = 0;\n\t\n\tfor(; tap < (f->tap_count-1); tap++)\n\t{\n\t\toutput -= (f->taps[tap] * f->delay_line[f->delay_pos++])<<2;\n\t\t\n\t\tif(f->delay_pos >= f->tap_count-1)\n\t\t\tf->delay_pos = 0;\n\t}\n\t\n\toutput -= (f->taps[tap] * input)<<2;\n\t\n\tf->delay_line[f->delay_pos++] = input;\n\tif(f->delay_pos >= f->tap_count-1)\n\t\tf->delay_pos = 0;\n\t\n\treturn output;\n}\n\n// Apply delay line and component volume\nINLINE INT32 delay(struct qsound_delay *d, INT32 input)\n{\n\tINT32 output;\n\t\n\td->delay_line[d->write_pos++] = input>>16;\n\tif(d->write_pos >= 51)\n\t\td->write_pos = 0;\n\n\toutput = d->delay_line[d->read_pos++]*d->volume;\n\tif(d->read_pos >= 51)\n\t\td->read_pos = 0;\n\n\treturn output;\n}\n\n// Update the delay read position to match new delay length\nINLINE void delay_update(struct qsound_delay *d)\n{\n\tINT16 new_read_pos = (d->write_pos - d->delay) % 51;\n\tif(new_read_pos < 0)\n\t\tnew_read_pos += 51;\n\t\n\td->read_pos = new_read_pos;\n}\n"
  },
  {
    "path": "VGMPlay/chips/qsound_ctr.h",
    "content": "#pragma once\n\nvoid qsoundc_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_qsound_ctr(UINT8 ChipID, int clock);\nvoid device_stop_qsound_ctr(UINT8 ChipID);\nvoid device_reset_qsound_ctr(UINT8 ChipID);\n\nvoid qsoundc_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 qsoundc_r(UINT8 ChipID, offs_t offset);\nvoid qsoundc_write_data(UINT8 ChipID, UINT8 address, UINT16 data);\n\nvoid qsoundc_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData);\nvoid qsoundc_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\nvoid qsoundc_wait_busy(UINT8 ChipID);\n"
  },
  {
    "path": "VGMPlay/chips/qsound_intf.c",
    "content": "//#include \"emu.h\"\n#include \"mamedef.h\"\n#ifdef _DEBUG\n#include <stdio.h>\n#endif\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include <math.h>\n#include \"qsound_intf.h\"\n#include \"qsound_mame.h\"\n#include \"qsound_ctr.h\"\n\n#ifdef ENABLE_ALL_CORES\n#define EC_MAME\t\t0x01\t// QSound HLE core from MAME\n#endif\n#define EC_CTR\t\t0x00\t// superctr custom HLE\n\nstatic UINT8 EMU_CORE = 0x00;\n// fix broken optimization of old VGMs causing problems with the new core\nstatic UINT8 key_on_hack = 0x00;\nstatic UINT16 start_addr_cache[2][16];\nstatic UINT16 pitch_cache[2][16];\nstatic UINT16 data_latch[2];\n\nint device_start_qsound(UINT8 ChipID, int clock)\n{\n\tmemset(start_addr_cache[ChipID], 0, sizeof(UINT16)*16);\n\tmemset(pitch_cache[ChipID], 0, sizeof(UINT16)*16);\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\treturn device_start_qsoundm(ChipID, clock);\n#endif\n\tcase EC_CTR:\n\t\tif(clock < 10000000)\n\t\t{\n\t\t\tclock *= 15;\n\t\t\tkey_on_hack = 1;\n\t\t}\n\t\treturn device_start_qsound_ctr(ChipID, clock);\n\t}\n\treturn 0;\n}\n\nvoid device_stop_qsound(UINT8 ChipID)\n{\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tdevice_stop_qsoundm(ChipID); return;\n#endif\n\tcase EC_CTR:\n\t\tdevice_stop_qsound_ctr(ChipID); return;\n\t}\n}\n\nvoid device_reset_qsound(UINT8 ChipID)\n{\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tdevice_reset_qsoundm(ChipID); return;\n#endif\n\tcase EC_CTR:\n\t\tdevice_reset_qsound_ctr(ChipID);\n\t\t\n\t\t// need to wait until the chip is ready before we start writing to it ...\n\t\t// we do this by time travel.\n\t\tqsoundc_wait_busy(ChipID);\n\t\treturn;\n\t}\n}\n\nvoid qsound_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tqsoundm_w(ChipID, offset, data); return;\n#endif\n\tcase EC_CTR:\n\t\tif(key_on_hack)\n\t\t{\n\t\t\tint ch;\n\t\t\tswitch (offset)\n\t\t\t{\n\t\t\t\t// need to handle three cases, as vgm_cmp can remove writes to both phase and bank\n\t\t\t\t// registers, depending on version.\n\t\t\t\t// - start address was written before end/loop, but phase register is written\n\t\t\t\t// - as above, but phase is not written (we use bank as a backup then)\n\t\t\t\t// - voice parameters are written during a note (we can't rewrite the address then)\n\t\t\t\tcase 0:\n\t\t\t\t\tdata_latch[ChipID] = (data_latch[ChipID] & 0x00ff) | (data << 8);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tdata_latch[ChipID] = (data_latch[ChipID] & 0xff00) | data;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tif(data > 0x7f)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tch = data>>3;\n\t\t\t\t\t\n\t\t\t\t\tswitch(data & 7)\n\t\t\t\t\t{\n\t\t\t\t\t\tcase 1:\t// Start addr. write\n\t\t\t\t\t\t\tstart_addr_cache[ChipID][ch] = data_latch[ChipID];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2:\t// Pitch write\n\t\t\t\t\t\t\t// (old HLE assumed writing a non-zero value after a zero value was Key On)\n\t\t\t\t\t\t\tif(pitch_cache[ChipID][ch] == 0 && data_latch[ChipID] != 0)\n\t\t\t\t\t\t\t\tqsoundc_write_data(ChipID, (ch << 3) + 1, start_addr_cache[ChipID][ch]);\n\t\t\t\t\t\t\tpitch_cache[ChipID][ch] = data_latch[ChipID];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3: // Phase (old HLE also assumed this was Key On)\n\t\t\t\t\t\t\tqsoundc_write_data(ChipID, (ch << 3) + 1, start_addr_cache[ChipID][ch]);\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tqsoundc_w(ChipID, offset, data);\n\t\t\n\t\t// need to wait until the chip is ready before we start writing to it ...\n\t\t// we do this by time travel.\n\t\tif(offset == 2 && data == 0xe3)\n\t\t\tqsoundc_wait_busy(ChipID);\n\t\t\n\t\treturn;\n\t}\n}\n\nUINT8 qsound_r(UINT8 ChipID, offs_t offset)\n{\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\treturn qsoundm_r(ChipID, offset);\n#endif\n\tcase EC_CTR:\n\t\treturn qsoundc_r(ChipID, offset);\n\t}\n\treturn 0;\n}\n\nvoid qsound_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tqsoundm_update(ChipID, outputs, samples); return;\n#endif\n\tcase EC_CTR:\n\t\tqsoundc_update(ChipID, outputs, samples); return;\n\t}\n}\n\nvoid qsound_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t  const UINT8* ROMData)\n{\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tqsoundm_write_rom(ChipID, ROMSize, DataStart, DataLength, ROMData); return;\n#endif\n\tcase EC_CTR:\n\t\tqsoundc_write_rom(ChipID, ROMSize, DataStart, DataLength, ROMData); return;\n\t}\n}\n\nvoid qsound_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tswitch(EMU_CORE)\n\t{\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAME:\n\t\tqsoundm_set_mute_mask(ChipID, MuteMask); return;\n#endif\n\tcase EC_CTR:\n\t\tqsoundc_set_mute_mask(ChipID, MuteMask); return;\n\t}\n}\n\nvoid qsound_set_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tEMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;\n#else\n\tEMU_CORE = EC_CTR;\n#endif\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/qsound_intf.h",
    "content": "#pragma once\n\nvoid qsound_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_qsound(UINT8 ChipID, int clock);\nvoid device_stop_qsound(UINT8 ChipID);\nvoid device_reset_qsound(UINT8 ChipID);\n\nvoid qsound_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 qsound_r(UINT8 ChipID, offs_t offset);\n\nvoid qsound_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData);\nvoid qsound_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\nvoid qsound_set_emu_core(UINT8 Emulator);\n\n"
  },
  {
    "path": "VGMPlay/chips/qsound_mame.c",
    "content": "/***************************************************************************\n\n  Capcom System QSound(tm)\n  ========================\n\n  Driver by Paul Leaman (paul@vortexcomputing.demon.co.uk)\n        and Miguel Angel Horna (mahorna@teleline.es)\n\n  A 16 channel stereo sample player.\n\n  QSpace position is simulated by panning the sound in the stereo space.\n\n  Register\n  0  xxbb   xx = unknown bb = start high address\n  1  ssss   ssss = sample start address\n  2  pitch\n  3  unknown (always 0x8000)\n  4  loop offset from end address\n  5  end\n  6  master channel volume\n  7  not used\n  8  Balance (left=0x0110  centre=0x0120 right=0x0130)\n  9  unknown (most fixed samples use 0 for this register)\n\n  Many thanks to CAB (the author of Amuse), without whom this probably would\n  never have been finished.\n\n  If anybody has some information about this hardware, please send it to me\n  to mahorna@teleline.es or 432937@cepsz.unizar.es.\n  http://teleline.terra.es/personal/mahorna\n\n***************************************************************************/\n\n//#include \"emu.h\"\n#include \"mamedef.h\"\n#ifdef _DEBUG\n#include <stdio.h>\n#endif\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include <math.h>\n#include \"qsound_mame.h\"\n\n/*\nDebug defines\n*/\n#define LOG_WAVE\t0\n#define VERBOSE  0\n#define LOG(x) do { if (VERBOSE) logerror x; } while (0)\n\n/* 8 bit source ROM samples */\ntypedef INT8 QSOUND_SRC_SAMPLE;\n\n\n#define QSOUND_CLOCKDIV 166\t\t\t /* Clock divider */\n#define QSOUND_CHANNELS 16\ntypedef stream_sample_t QSOUND_SAMPLE;\n\nstruct QSOUND_CHANNEL\n{\n\tUINT32 bank;        // bank\n\tUINT32 address;     // start/cur address\n\tUINT16 loop;        // loop address\n\tUINT16 end;         // end address\n\tUINT32 freq;        // frequency\n\tUINT16 vol;         // master volume\n\n\t// work variables\n\tUINT8 enabled;      // key on / key off\n\tint lvol;           // left volume\n\tint rvol;           // right volume\n\tUINT32 step_ptr;    // current offset counter\n\t\n\tUINT8 Muted;\n};\n\ntypedef struct _qsound_state qsound_state;\nstruct _qsound_state\n{\n\t/* Private variables */\n\t//sound_stream * stream;\t\t\t\t/* Audio stream */\n\tstruct QSOUND_CHANNEL channel[QSOUND_CHANNELS];\n\t\n\tUINT16 data;\t\t\t/* register latch data */\n\tQSOUND_SRC_SAMPLE *sample_rom;\t/* Q sound sample ROM */\n\tUINT32 sample_rom_length;\n\n\tint pan_table[33];\t\t/* Pan volume table */\n\n\t//FILE *fpRawDataL;\n\t//FILE *fpRawDataR;\n};\n\n#define MAX_CHIPS\t0x02\nstatic qsound_state QSoundData[MAX_CHIPS];\n\n/*INLINE qsound_state *get_safe_token(device_t *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == QSOUND);\n\treturn (qsound_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n\n/* Function prototypes */\n//static STREAM_UPDATE( qsoundm_update );\nstatic void qsound_set_command(qsound_state *chip, UINT8 address, UINT16 data);\n\n//static DEVICE_START( qsound )\nint device_start_qsoundm(UINT8 ChipID, int clock)\n{\n\t//qsound_state *chip = get_safe_token(device);\n\tqsound_state *chip;\n\tint i;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &QSoundData[ChipID];\n\t\n\t//chip->sample_rom = (QSOUND_SRC_SAMPLE *)*device->region();\n\t//chip->sample_rom_length = device->region()->bytes();\n\tchip->sample_rom = NULL;\n\tchip->sample_rom_length = 0x00;\n\n\t/* Create pan table */\n\tfor (i=0; i<33; i++)\n\t\tchip->pan_table[i]=(int)((256/sqrt(32.0)) * sqrt((double)i));\n\t\n\t// init sound regs\n\tmemset(chip->channel, 0, sizeof(chip->channel));\n\n//\tLOG((\"Pan table\\n\"));\n//\tfor (i=0; i<33; i++)\n//\t\tLOG((\"%02x \", chip->pan_table[i]));\n\n\t/* Allocate stream */\n\t/*chip->stream = device->machine().sound().stream_alloc(\n\t\t*device, 0, 2,\n\t\tdevice->clock() / QSOUND_CLOCKDIV,\n\t\tchip,\n\t\tqsoundm_update );*/\n\n\t/*if (LOG_WAVE)\n\t{\n\t\tchip->fpRawDataR=fopen(\"qsoundr.raw\", \"w+b\");\n\t\tchip->fpRawDataL=fopen(\"qsoundl.raw\", \"w+b\");\n\t}*/\n\n\t/* state save */\n\t/*for (i=0; i<QSOUND_CHANNELS; i++)\n\t{\n\t\tdevice->save_item(NAME(chip->channel[i].bank), i);\n\t\tdevice->save_item(NAME(chip->channel[i].address), i);\n\t\tdevice->save_item(NAME(chip->channel[i].pitch), i);\n\t\tdevice->save_item(NAME(chip->channel[i].loop), i);\n\t\tdevice->save_item(NAME(chip->channel[i].end), i);\n\t\tdevice->save_item(NAME(chip->channel[i].vol), i);\n\t\tdevice->save_item(NAME(chip->channel[i].pan), i);\n\t\tdevice->save_item(NAME(chip->channel[i].key), i);\n\t\tdevice->save_item(NAME(chip->channel[i].lvol), i);\n\t\tdevice->save_item(NAME(chip->channel[i].rvol), i);\n\t\tdevice->save_item(NAME(chip->channel[i].lastdt), i);\n\t\tdevice->save_item(NAME(chip->channel[i].offset), i);\n\t}*/\n\t\n\tfor (i = 0; i < QSOUND_CHANNELS; i ++)\n\t\tchip->channel[i].Muted = 0x00;\n\t\n\treturn clock / QSOUND_CLOCKDIV;\n}\n\n//static DEVICE_STOP( qsound )\nvoid device_stop_qsoundm(UINT8 ChipID)\n{\n\t//qsound_state *chip = get_safe_token(device);\n\tqsound_state *chip = &QSoundData[ChipID];\n\t/*if (chip->fpRawDataR)\n\t{\n\t\tfclose(chip->fpRawDataR);\n\t}\n\tchip->fpRawDataR = NULL;\n\tif (chip->fpRawDataL)\n\t{\n\t\tfclose(chip->fpRawDataL);\n\t}\n\tchip->fpRawDataL = NULL;*/\n\tfree(chip->sample_rom);\tchip->sample_rom = NULL;\n}\n\nvoid device_reset_qsoundm(UINT8 ChipID)\n{\n\tqsound_state *chip = &QSoundData[ChipID];\n\tint adr;\n\t\n\t// init sound regs\n\tmemset(chip->channel, 0, sizeof(chip->channel));\n\n\tfor (adr = 0x7f; adr >= 0; adr--)\n\t\tqsound_set_command(chip, adr, 0);\n\tfor (adr = 0x80; adr < 0x90; adr++)\n\t\tqsound_set_command(chip, adr, 0x120);\n\n\treturn;\n}\n\n//WRITE8_DEVICE_HANDLER( qsoundm_w )\nvoid qsoundm_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//qsound_state *chip = get_safe_token(device);\n\tqsound_state *chip = &QSoundData[ChipID];\n\tswitch (offset)\n\t{\n\t\tcase 0:\n\t\t\tchip->data=(chip->data&0xff)|(data<<8);\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tchip->data=(chip->data&0xff00)|data;\n\t\t\tbreak;\n\n\t\tcase 2:\n\t\t\tqsound_set_command(chip, data, chip->data);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\t//logerror(\"%s: unexpected qsound write to offset %d == %02X\\n\", device->machine().describe_context(), offset, data);\n\t\t\tlogerror(\"QSound: unexpected qsound write to offset %d == %02X\\n\", offset, data);\n\t\t\tbreak;\n\t}\n}\n\n//READ8_DEVICE_HANDLER( qsoundm_r )\nUINT8 qsoundm_r(UINT8 ChipID, offs_t offset)\n{\n\t/* Port ready bit (0x80 if ready) */\n\treturn 0x80;\n}\n\nstatic void qsound_set_command(qsound_state *chip, UINT8 address, UINT16 data)\n{\n\tint ch = 0, reg = 0;\n\n\t// direct sound reg\n\tif (address < 0x80)\n\t{\n\t\tch = address >> 3;\n\t\treg = address & 0x07;\n\t}\n\t// >= 0x80 is probably for the dsp?\n\telse if (address < 0x90)\n\t{\n\t\tch = address & 0x0F;\n\t\treg = 8;\n\t}\n\telse if (address >= 0xba && address < 0xca)\n\t{\n\t\tch = address - 0xba;\n\t\treg=9;\n\t}\n\telse\n\t{\n\t\t/* Unknown registers */\n\t\tch = 99;\n\t\treg = 99;\n\t}\n\n\tswitch (reg)\n\t{\n\t\tcase 0:\n\t\t\t// bank, high bits unknown\n\t\t\tch = (ch + 1) & 0x0f;\t/* strange ... */\n\t\t\tchip->channel[ch].bank = (data & 0x7f) << 16;\t// Note: The most recent MAME doesn't do \"& 0x7F\"\n#ifdef _DEBUG\n\t\t\tif (data && !(data & 0x8000))\n\t\t\t\tfprintf(stderr, \"QSound Ch %u: Bank = %04x\\n\",ch,data);\n#endif\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\t// start/cur address\n\t\t\tchip->channel[ch].address = data;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\t// frequency\n\t\t\tchip->channel[ch].freq = data;\n\t\t\t// This was working with the old code, but breaks the songs with the new one.\n\t\t\t// And I'm pretty sure the hardware won't do this. -Valley Bell\n\t\t\t/*if (!data)\n\t\t\t{\n\t\t\t\t// key off\n\t\t\t\tchip->channel[ch].enabled = 0;\n\t\t\t}*/\n\t\t\tbreak;\n\t\tcase 3:\n#ifdef _DEBUG\n\t\t\tif (chip->channel[ch].enabled && data != 0x8000)\n\t\t\t\tfprintf(stderr, \"QSound Ch %u: KeyOn = %04x\\n\",ch,data);\n#endif\n\t\t\t// key on (does the value matter? it always writes 0x8000)\n\t\t\t//chip->channel[ch].enabled = 1;\n\t\t\tchip->channel[ch].enabled = (data & 0x8000) >> 15;\n\t\t\tchip->channel[ch].step_ptr = 0;\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\t// loop address\n\t\t\tchip->channel[ch].loop = data;\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\t// end address\n\t\t\tchip->channel[ch].end = data;\n\t\t\tbreak;\n\t\tcase 6:\n\t\t\t// master volume\n#ifdef _DEBUG\n\t\t\tif (! chip->channel[ch].enabled && data)\n\t\t\t\tfprintf(stderr, \"QSound update warning - please report!\\n\");\n#endif\n\t\t\tchip->channel[ch].vol = data;\n\t\t\tbreak;\n\t\tcase 7:\n\t\t\t// unused?\n#ifdef MAME_DEBUG\n\t\t\tpopmessage(\"UNUSED QSOUND REG 7=%04x\",data);\n#endif\n\t\t\tbreak;\n\t\tcase 8:\n\t\t\t{\n\t\t\t\t// panning (left=0x0110, centre=0x0120, right=0x0130)\n\t\t\t\t// looks like it doesn't write other values than that\n\t\t\t\tint pan = (data & 0x3f) - 0x10;\n\t\t\t\tif (pan > 0x20)\n\t\t\t\t\tpan = 0x20;\n\t\t\t\tif (pan < 0)\n\t\t\t\t\tpan = 0;\n\t\t\t\t\n\t\t\t\tchip->channel[ch].rvol=chip->pan_table[pan];\n\t\t\t\tchip->channel[ch].lvol=chip->pan_table[0x20 - pan];\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 9:\n\t\t\t// unknown\n/*\n#ifdef MAME_DEBUG\n            popmessage(\"QSOUND REG 9=%04x\",data);\n#endif\n*/\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t//logerror(\"%s: write_data %02x = %04x\\n\", machine().describe_context(), address, data);\n\t\t\tbreak;\n\t}\n\t//LOG((\"QSOUND WRITE %02x CH%02d-R%02d =%04x\\n\", address, ch, reg, data));\n}\n\n\n//static STREAM_UPDATE( qsoundm_update )\nvoid qsoundm_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//qsound_state *chip = (qsound_state *)param;\n\tqsound_state *chip = &QSoundData[ChipID];\n\tint i,j;\n\tUINT32 offset;\n\tUINT32 advance;\n\tINT8 sample;\n\tstruct QSOUND_CHANNEL *pC=&chip->channel[0];\n\n\tmemset( outputs[0], 0x00, samples * sizeof(*outputs[0]) );\n\tmemset( outputs[1], 0x00, samples * sizeof(*outputs[1]) );\n\tif (! chip->sample_rom_length)\n\t\treturn;\n\n\tfor (i=0; i<QSOUND_CHANNELS; i++, pC++)\n\t{\n\t\tif (pC->enabled && ! pC->Muted)\n\t\t{\n\t\t\tQSOUND_SAMPLE *pOutL=outputs[0];\n\t\t\tQSOUND_SAMPLE *pOutR=outputs[1];\n\t\t\t\n\t\t\tfor (j=samples-1; j>=0; j--)\n\t\t\t{\n\t\t\t\tadvance = (pC->step_ptr >> 12);\n\t\t\t\tpC->step_ptr &= 0xfff;\n\t\t\t\tpC->step_ptr += pC->freq;\n\t\t\t\t\n\t\t\t\tif (advance)\n\t\t\t\t{\n\t\t\t\t\tpC->address += advance;\n\t\t\t\t\tif (pC->freq && pC->address >= pC->end)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (pC->loop)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Reached the end, restart the loop\n\t\t\t\t\t\t\tpC->address -= pC->loop;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Make sure we don't overflow (what does the real chip do in this case?)\n\t\t\t\t\t\t\tif (pC->address >= pC->end)\n\t\t\t\t\t\t\t\tpC->address = pC->end - pC->loop;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tpC->address &= 0xffff;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Reached the end of a non-looped sample\n\t\t\t\t\t\t\t//pC->enabled = 0;\n\t\t\t\t\t\t\tpC->address --;\t// ensure that old ripped VGMs still work\n\t\t\t\t\t\t\tpC->step_ptr += 0x1000;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\toffset = (pC->bank | pC->address) % chip->sample_rom_length;\n\t\t\t\tsample = chip->sample_rom[offset];\n\t\t\t\t*pOutL++ += ((sample * pC->lvol * pC->vol) >> 14);\n\t\t\t\t*pOutR++ += ((sample * pC->rvol * pC->vol) >> 14);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*if (chip->fpRawDataL)\n\t\tfwrite(outputs[0], samples*sizeof(QSOUND_SAMPLE), 1, chip->fpRawDataL);\n\tif (chip->fpRawDataR)\n\t\tfwrite(outputs[1], samples*sizeof(QSOUND_SAMPLE), 1, chip->fpRawDataR);*/\n}\n\nvoid qsoundm_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t  const UINT8* ROMData)\n{\n\tqsound_state* info = &QSoundData[ChipID];\n\t\n\tif (info->sample_rom_length != ROMSize)\n\t{\n\t\tinfo->sample_rom = (QSOUND_SRC_SAMPLE*)realloc(info->sample_rom, ROMSize);\n\t\tinfo->sample_rom_length = ROMSize;\n\t\tmemset(info->sample_rom, 0xFF, ROMSize);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(info->sample_rom + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\n\nvoid qsoundm_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tqsound_state* info = &QSoundData[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < QSOUND_CHANNELS; CurChn ++)\n\t\tinfo->channel[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( qsound )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers --- //\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(qsound_state);\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions --- //\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( qsound );\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\tinfo->stop = DEVICE_STOP_NAME( qsound );\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// Nothing //\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings --- //\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"Q-Sound\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Capcom custom\");\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n\n/**************** end of file ****************/\n\n//DEFINE_LEGACY_SOUND_DEVICE(QSOUND, qsound);\n"
  },
  {
    "path": "VGMPlay/chips/qsound_mame.h",
    "content": "/*********************************************************\n\n    Capcom Q-Sound system\n\n*********************************************************/\n\n#pragma once\n\n//#include \"devlegcy.h\"\n\n#define QSOUND_CLOCK    4000000   /* default 4MHz clock */\n\nvoid qsoundm_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_qsoundm(UINT8 ChipID, int clock);\nvoid device_stop_qsoundm(UINT8 ChipID);\nvoid device_reset_qsoundm(UINT8 ChipID);\n\n\n//WRITE8_DEVICE_HANDLER( qsound_w );\n//READ8_DEVICE_HANDLER( qsound_r );\nvoid qsoundm_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 qsoundm_r(UINT8 ChipID, offs_t offset);\n\n\nvoid qsoundm_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData);\nvoid qsoundm_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n//DECLARE_LEGACY_SOUND_DEVICE(QSOUND, qsound);\n"
  },
  {
    "path": "VGMPlay/chips/rf5c68.c",
    "content": "/*********************************************************/\n/*    ricoh RF5C68(or clone) PCM controller              */\n/*********************************************************/\n\n#include \"mamedef.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#include \"rf5c68.h\"\n#include <math.h>\n\n\n#define  NUM_CHANNELS    (8)\n#define STEAM_STEP\t\t0x800\n\n\n\ntypedef struct _pcm_channel pcm_channel;\nstruct _pcm_channel\n{\n\tUINT8\t\tenable;\n\tUINT8\t\tenv;\n\tUINT8\t\tpan;\n\tUINT8\t\tstart;\n\tUINT32\t\taddr;\n\tUINT16\t\tstep;\n\tUINT16\t\tloopst;\n\tUINT8\t\tMuted;\n};\n\ntypedef struct _mem_stream mem_stream;\nstruct _mem_stream\n{\n\tUINT32 BaseAddr;\n\tUINT32 EndAddr;\n\tUINT32 CurAddr;\n\tUINT16 CurStep;\n\tconst UINT8* MemPnt;\n};\n\n\ntypedef struct _rf5c68_state rf5c68_state;\nstruct _rf5c68_state\n{\n\t//sound_stream *\t\tstream;\n\tpcm_channel\t\t\tchan[NUM_CHANNELS];\n\tUINT8\t\t\t\tcbank;\n\tUINT8\t\t\t\twbank;\n\tUINT8\t\t\t\tenable;\n\tUINT32\t\t\t\tdatasize;\n\tUINT8*\t\t\t\tdata;\n\t//void\t\t\t\t(*sample_callback)(running_device* device,int channel);\n\tmem_stream\t\t\tmemstrm;\n};\n\n\nstatic void rf5c68_mem_stream_flush(rf5c68_state *chip);\n\n#define MAX_CHIPS\t0x02\nstatic rf5c68_state RF5C68Data[MAX_CHIPS];\n\n/*INLINE rf5c68_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_RF5C68);\n\treturn (rf5c68_state *)device->token;\n}*/\n\n/************************************************/\n/*    RF5C68 stream update                      */\n/************************************************/\n\nstatic void memstream_sample_check(rf5c68_state *chip, UINT32 addr, UINT16 Speed)\n{\n\tmem_stream* ms = &chip->memstrm;\n\tUINT32 SmplSpd;\n\t\n\tSmplSpd = (Speed >= 0x0800) ? (Speed >> 11) : 1;\n\tif (addr >= ms->CurAddr)\n\t{\n\t\t// Is the stream too fast? (e.g. about to catch up the output)\n\t\tif (addr - ms->CurAddr <= SmplSpd * 5)\n\t\t{\n\t\t\t// Yes - delay the stream\n\t\t\tms->CurAddr -= SmplSpd * 4;\n\t\t\tif (ms->CurAddr < ms->BaseAddr)\n\t\t\t\tms->CurAddr = ms->BaseAddr;\n\t\t}\n\t}\n\telse\n\t{\n\t\t// Is the stream too slow? (e.g. the output is about to catch up the stream)\n\t\tif (ms->CurAddr - addr <= SmplSpd * 5)\n\t\t{\n\t\t\tif (ms->CurAddr + SmplSpd * 4 >= ms->EndAddr)\n\t\t\t{\n\t\t\t\trf5c68_mem_stream_flush(chip);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tmemcpy(chip->data + ms->CurAddr, ms->MemPnt + (ms->CurAddr - ms->BaseAddr), SmplSpd * 4);\n\t\t\t\tms->CurAddr += SmplSpd * 4;\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn;\n}\n\n//static STREAM_UPDATE( rf5c68_update )\nvoid rf5c68_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//rf5c68_state *chip = (rf5c68_state *)param;\n\trf5c68_state *chip = &RF5C68Data[ChipID];\n\tmem_stream* ms = &chip->memstrm;\n\tstream_sample_t *left = outputs[0];\n\tstream_sample_t *right = outputs[1];\n\tint i, j;\n\n\t/* start with clean buffers */\n\tmemset(left, 0, samples * sizeof(*left));\n\tmemset(right, 0, samples * sizeof(*right));\n\n\t/* bail if not enabled */\n\tif (!chip->enable)\n\t\treturn;\n\n\t/* loop over channels */\n\tfor (i = 0; i < NUM_CHANNELS; i++)\n\t{\n\t\tpcm_channel *chan = &chip->chan[i];\n\n\t\t/* if this channel is active, accumulate samples */\n\t\tif (chan->enable && ! chan->Muted)\n\t\t{\n\t\t\tint lv = (chan->pan & 0x0f) * chan->env;\n\t\t\tint rv = ((chan->pan >> 4) & 0x0f) * chan->env;\n\n\t\t\t/* loop over the sample buffer */\n\t\t\tfor (j = 0; j < samples; j++)\n\t\t\t{\n\t\t\t\tint sample;\n\n\t\t\t\t/* trigger sample callback */\n\t\t\t\t/*if(chip->sample_callback)\n\t\t\t\t{\n\t\t\t\t\tif(((chan->addr >> 11) & 0xfff) == 0xfff)\n\t\t\t\t\t\tchip->sample_callback(chip->device,((chan->addr >> 11)/0x2000));\n\t\t\t\t}*/\n\n\t\t\t\tmemstream_sample_check(chip, (chan->addr >> 11) & 0xFFFF, chan->step);\n\t\t\t\t/* fetch the sample and handle looping */\n\t\t\t\tsample = chip->data[(chan->addr >> 11) & 0xffff];\n\t\t\t\tif (sample == 0xff)\n\t\t\t\t{\n\t\t\t\t\tchan->addr = chan->loopst << 11;\n\t\t\t\t\tsample = chip->data[(chan->addr >> 11) & 0xffff];\n\n\t\t\t\t\t/* if we loop to a loop point, we're effectively dead */\n\t\t\t\t\tif (sample == 0xff)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tchan->addr += chan->step;\n\n\t\t\t\t/* add to the buffer */\n\t\t\t\tif (sample & 0x80)\n\t\t\t\t{\n\t\t\t\t\tsample &= 0x7f;\n\t\t\t\t\tleft[j] += (sample * lv) >> 5;\n\t\t\t\t\tright[j] += (sample * rv) >> 5;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tleft[j] -= (sample * lv) >> 5;\n\t\t\t\t\tright[j] -= (sample * rv) >> 5;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (samples && ms->CurAddr < ms->EndAddr)\n\t{\n\t\tms->CurStep += STEAM_STEP * samples;\n\t\tif (ms->CurStep >= 0x0800)\t// 1 << 11\n\t\t{\n\t\t\ti = ms->CurStep >> 11;\n\t\t\tms->CurStep &= 0x07FF;\n\t\t\t\n\t\t\tif (ms->CurAddr + i > ms->EndAddr)\n\t\t\t\ti = ms->EndAddr - ms->CurAddr;\n\t\t\t\n\t\t\tmemcpy(chip->data + ms->CurAddr, ms->MemPnt + (ms->CurAddr - ms->BaseAddr), i);\n\t\t\tms->CurAddr += i;\n\t\t}\n\t}\n\t\n\t// I think, this is completely useless\n\t/* now clamp and shift the result (output is only 10 bits) */\n\t/*for (j = 0; j < samples; j++)\n\t{\n\t\tstream_sample_t temp;\n\n\t\ttemp = left[j];\n\t\tif (temp > 32767) temp = 32767;\n\t\telse if (temp < -32768) temp = -32768;\n\t\tleft[j] = temp & ~0x3f;\n\n\t\ttemp = right[j];\n\t\tif (temp > 32767) temp = 32767;\n\t\telse if (temp < -32768) temp = -32768;\n\t\tright[j] = temp & ~0x3f;\n\t}*/\n}\n\n\n/************************************************/\n/*    RF5C68 start                              */\n/************************************************/\n\n//static DEVICE_START( rf5c68 )\nint device_start_rf5c68(UINT8 ChipID, int clock)\n{\n\t//const rf5c68_interface* intf = (const rf5c68_interface*)device->baseconfig().static_config();\n\t\n\t/* allocate memory for the chip */\n\t//rf5c68_state *chip = get_safe_token(device);\n\trf5c68_state *chip;\n\tint chn;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &RF5C68Data[ChipID];\n\t\n\tchip->datasize = 0x10000;\n\tchip->data = (UINT8*)malloc(chip->datasize);\n\t\n\t/* allocate the stream */\n\t//chip->stream = stream_create(device, 0, 2, device->clock / 384, chip, rf5c68_update);\n\n\t/* set up callback */\n\t/*if(intf != NULL)\n\t\tchip->sample_callback = intf->sample_end_callback;\n\telse\n\t\tchip->sample_callback = NULL;*/\n\tfor (chn = 0; chn < NUM_CHANNELS; chn ++)\n\t\tchip->chan[chn].Muted = 0x00;\n\t\n\treturn (clock & 0x7FFFFFFF) / 384;\n}\n\nvoid device_stop_rf5c68(UINT8 ChipID)\n{\n\trf5c68_state *chip = &RF5C68Data[ChipID];\n\tfree(chip->data);\tchip->data = NULL;\n\t\n\treturn;\n}\n\nvoid device_reset_rf5c68(UINT8 ChipID)\n{\n\trf5c68_state *chip = &RF5C68Data[ChipID];\n\tint i;\n\tpcm_channel* chan;\n\tmem_stream* ms = &chip->memstrm;\n\t\n\t// Clear the PCM memory.\n\tmemset(chip->data, 0x00, chip->datasize);\n\t\n\tchip->enable = 0;\n\tchip->cbank = 0;\n\tchip->wbank = 0;\n\t\n\t/* clear channel registers */\n\tfor (i = 0; i < NUM_CHANNELS; i ++)\n\t{\n\t\tchan = &chip->chan[i];\n\t\tchan->enable = 0;\n\t\tchan->env = 0;\n\t\tchan->pan = 0;\n\t\tchan->start = 0;\n\t\tchan->addr = 0;\n\t\tchan->step = 0;\n\t\tchan->loopst = 0;\n\t}\n\t\n\tms->BaseAddr = 0x0000;\n\tms->CurAddr = 0x0000;\n\tms->EndAddr = 0x0000;\n\tms->CurStep = 0x0000;\n\tms->MemPnt = NULL;\n}\n\n/************************************************/\n/*    RF5C68 write register                     */\n/************************************************/\n\n//WRITE8_DEVICE_HANDLER( rf5c68_w )\nvoid rf5c68_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//rf5c68_state *chip = get_safe_token(device);\n\trf5c68_state *chip = &RF5C68Data[ChipID];\n\tpcm_channel *chan = &chip->chan[chip->cbank];\n\tint i;\n\n\t/* force the stream to update first */\n\t//stream_update(chip->stream);\n\n\t/* switch off the address */\n\tswitch (offset)\n\t{\n\t\tcase 0x00:\t/* envelope */\n\t\t\tchan->env = data;\n\t\t\tbreak;\n\n\t\tcase 0x01:\t/* pan */\n\t\t\tchan->pan = data;\n\t\t\tbreak;\n\n\t\tcase 0x02:\t/* FDL */\n\t\t\tchan->step = (chan->step & 0xff00) | (data & 0x00ff);\n\t\t\tbreak;\n\n\t\tcase 0x03:\t/* FDH */\n\t\t\tchan->step = (chan->step & 0x00ff) | ((data << 8) & 0xff00);\n\t\t\tbreak;\n\n\t\tcase 0x04:\t/* LSL */\n\t\t\tchan->loopst = (chan->loopst & 0xff00) | (data & 0x00ff);\n\t\t\tbreak;\n\n\t\tcase 0x05:\t/* LSH */\n\t\t\tchan->loopst = (chan->loopst & 0x00ff) | ((data << 8) & 0xff00);\n\t\t\tbreak;\n\n\t\tcase 0x06:\t/* ST */\n\t\t\tchan->start = data;\n\t\t\tif (!chan->enable)\n\t\t\t\tchan->addr = chan->start << (8 + 11);\n\t\t\tbreak;\n\n\t\tcase 0x07:\t/* control reg */\n\t\t\tchip->enable = (data >> 7) & 1;\n\t\t\tif (data & 0x40)\n\t\t\t\tchip->cbank = data & 7;\n\t\t\telse\n\t\t\t\tchip->wbank = data & 15;\n\t\t\tbreak;\n\n\t\tcase 0x08:\t/* channel on/off reg */\n\t\t\tfor (i = 0; i < 8; i++)\n\t\t\t{\n\t\t\t\tchip->chan[i].enable = (~data >> i) & 1;\n\t\t\t\tif (!chip->chan[i].enable)\n\t\t\t\t\tchip->chan[i].addr = chip->chan[i].start << (8 + 11);\n\t\t\t}\n\t\t\tbreak;\n\t}\n}\n\n\n/************************************************/\n/*    RF5C68 read memory                        */\n/************************************************/\n\n//READ8_DEVICE_HANDLER( rf5c68_mem_r )\nUINT8 rf5c68_mem_r(UINT8 ChipID, offs_t offset)\n{\n\t//rf5c68_state *chip = get_safe_token(device);\n\trf5c68_state *chip = &RF5C68Data[ChipID];\n\treturn chip->data[chip->wbank * 0x1000 + offset];\n}\n\n\n/************************************************/\n/*    RF5C68 write memory                       */\n/************************************************/\n\n//WRITE8_DEVICE_HANDLER( rf5c68_mem_w )\nvoid rf5c68_mem_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//rf5c68_state *chip = get_safe_token(device);\n\trf5c68_state *chip = &RF5C68Data[ChipID];\n\trf5c68_mem_stream_flush(chip);\n\tchip->data[chip->wbank * 0x1000 | offset] = data;\n}\n\nstatic void rf5c68_mem_stream_flush(rf5c68_state *chip)\n{\n\tmem_stream* ms = &chip->memstrm;\n\t\n\tif (ms->CurAddr >= ms->EndAddr)\n\t\treturn;\n\t\n\tmemcpy(chip->data + ms->CurAddr, ms->MemPnt + (ms->CurAddr - ms->BaseAddr), ms->EndAddr - ms->CurAddr);\n\tms->CurAddr = ms->EndAddr;\n\t\n\treturn;\n}\n\nvoid rf5c68_write_ram(UINT8 ChipID, offs_t DataStart, offs_t DataLength, const UINT8* RAMData)\n{\n\trf5c68_state *chip = &RF5C68Data[ChipID];\n\tmem_stream* ms = &chip->memstrm;\n\tUINT16 BytCnt;\n\t\n\tDataStart |= chip->wbank * 0x1000;\n\tif (DataStart >= chip->datasize)\n\t\treturn;\n\tif (DataStart + DataLength > chip->datasize)\n\t\tDataLength = chip->datasize - DataStart;\n\t\n\t//memcpy(chip->data + DataStart, RAMData, DataLength);\n\t\n\trf5c68_mem_stream_flush(chip);\n\t\n\tms->BaseAddr = DataStart;\n\tms->CurAddr = ms->BaseAddr;\n\tms->EndAddr = ms->BaseAddr + DataLength;\n\tms->CurStep = 0x0000;\n\tms->MemPnt = RAMData;\n\t\n\t//BytCnt = (STEAM_STEP * 32) >> 11;\n\tBytCnt = 0x40;\t// SegaSonic Arcade: Run! Run! Run! needs such a high value\n\tif (ms->CurAddr + BytCnt > ms->EndAddr)\n\t\tBytCnt = ms->EndAddr - ms->CurAddr;\n\t\n\tmemcpy(chip->data + ms->CurAddr, ms->MemPnt + (ms->CurAddr - ms->BaseAddr), BytCnt);\n\tms->CurAddr += BytCnt;\n\t\n\treturn;\n}\n\n\nvoid rf5c68_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\trf5c68_state *chip = &RF5C68Data[ChipID];\n\tunsigned char CurChn;\n\t\n\tfor (CurChn = 0; CurChn < NUM_CHANNELS; CurChn ++)\n\t\tchip->chan[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( rf5c68 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(rf5c68_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( rf5c68 );\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"RF5C68\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Ricoh PCM\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n\n/**************** end of file ****************/\n"
  },
  {
    "path": "VGMPlay/chips/rf5c68.h",
    "content": "/*********************************************************/\n/*    ricoh RF5C68(or clone) PCM controller              */\n/*********************************************************/\n\n#pragma once\n\n/******************************************/\n/*WRITE8_DEVICE_HANDLER( rf5c68_w );\n\nREAD8_DEVICE_HANDLER( rf5c68_mem_r );\nWRITE8_DEVICE_HANDLER( rf5c68_mem_w );\n\nDEVICE_GET_INFO( rf5c68 );\n#define SOUND_RF5C68 DEVICE_GET_INFO_NAME( rf5c68 )*/\n\nvoid rf5c68_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_rf5c68(UINT8 ChipID, int clock);\nvoid device_stop_rf5c68(UINT8 ChipID);\nvoid device_reset_rf5c68(UINT8 ChipID);\n\nvoid rf5c68_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nUINT8 rf5c68_mem_r(UINT8 ChipID, offs_t offset);\nvoid rf5c68_mem_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid rf5c68_write_ram(UINT8 ChipID, offs_t DataStart, offs_t DataLength, const UINT8* RAMData);\n\nvoid rf5c68_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/chips/saa1099.c",
    "content": "/***************************************************************************\n\n    Philips SAA1099 Sound driver\n\n    By Juergen Buchmueller and Manuel Abadia\n\n    SAA1099 register layout:\n    ========================\n\n    offs | 7654 3210 | description\n    -----+-----------+---------------------------\n    0x00 | ---- xxxx | Amplitude channel 0 (left)\n    0x00 | xxxx ---- | Amplitude channel 0 (right)\n    0x01 | ---- xxxx | Amplitude channel 1 (left)\n    0x01 | xxxx ---- | Amplitude channel 1 (right)\n    0x02 | ---- xxxx | Amplitude channel 2 (left)\n    0x02 | xxxx ---- | Amplitude channel 2 (right)\n    0x03 | ---- xxxx | Amplitude channel 3 (left)\n    0x03 | xxxx ---- | Amplitude channel 3 (right)\n    0x04 | ---- xxxx | Amplitude channel 4 (left)\n    0x04 | xxxx ---- | Amplitude channel 4 (right)\n    0x05 | ---- xxxx | Amplitude channel 5 (left)\n    0x05 | xxxx ---- | Amplitude channel 5 (right)\n         |           |\n    0x08 | xxxx xxxx | Frequency channel 0\n    0x09 | xxxx xxxx | Frequency channel 1\n    0x0a | xxxx xxxx | Frequency channel 2\n    0x0b | xxxx xxxx | Frequency channel 3\n    0x0c | xxxx xxxx | Frequency channel 4\n    0x0d | xxxx xxxx | Frequency channel 5\n         |           |\n    0x10 | ---- -xxx | Channel 0 octave select\n    0x10 | -xxx ---- | Channel 1 octave select\n    0x11 | ---- -xxx | Channel 2 octave select\n    0x11 | -xxx ---- | Channel 3 octave select\n    0x12 | ---- -xxx | Channel 4 octave select\n    0x12 | -xxx ---- | Channel 5 octave select\n         |           |\n    0x14 | ---- ---x | Channel 0 frequency enable (0 = off, 1 = on)\n    0x14 | ---- --x- | Channel 1 frequency enable (0 = off, 1 = on)\n    0x14 | ---- -x-- | Channel 2 frequency enable (0 = off, 1 = on)\n    0x14 | ---- x--- | Channel 3 frequency enable (0 = off, 1 = on)\n    0x14 | ---x ---- | Channel 4 frequency enable (0 = off, 1 = on)\n    0x14 | --x- ---- | Channel 5 frequency enable (0 = off, 1 = on)\n         |           |\n    0x15 | ---- ---x | Channel 0 noise enable (0 = off, 1 = on)\n    0x15 | ---- --x- | Channel 1 noise enable (0 = off, 1 = on)\n    0x15 | ---- -x-- | Channel 2 noise enable (0 = off, 1 = on)\n    0x15 | ---- x--- | Channel 3 noise enable (0 = off, 1 = on)\n    0x15 | ---x ---- | Channel 4 noise enable (0 = off, 1 = on)\n    0x15 | --x- ---- | Channel 5 noise enable (0 = off, 1 = on)\n         |           |\n    0x16 | ---- --xx | Noise generator parameters 0\n    0x16 | --xx ---- | Noise generator parameters 1\n         |           |\n    0x18 | --xx xxxx | Envelope generator 0 parameters\n    0x18 | x--- ---- | Envelope generator 0 control enable (0 = off, 1 = on)\n    0x19 | --xx xxxx | Envelope generator 1 parameters\n    0x19 | x--- ---- | Envelope generator 1 control enable (0 = off, 1 = on)\n         |           |\n    0x1c | ---- ---x | All channels enable (0 = off, 1 = on)\n    0x1c | ---- --x- | Synch & Reset generators\n\n***************************************************************************/\n\n//#include \"emu.h\"\n#include \"mamedef.h\"\n#include <string.h>\t// for memset\n#include \"saa1099.h\"\n\n\n#define LEFT\t0x00\n#define RIGHT\t0x01\n\n/* this structure defines a channel */\nstruct saa1099_channel\n{\n\tint frequency;\t\t\t/* frequency (0x00..0xff) */\n\tint freq_enable;\t\t/* frequency enable */\n\tint noise_enable;\t\t/* noise enable */\n\tint octave; \t\t\t/* octave (0x00..0x07) */\n\tint amplitude[2];\t\t/* amplitude (0x00..0x0f) */\n\tint envelope[2];\t\t/* envelope (0x00..0x0f or 0x10 == off) */\n\n\t/* vars to simulate the square wave */\n\tdouble counter;\n\tdouble freq;\n\tint level;\n\tUINT8 Muted;\n};\n\n/* this structure defines a noise channel */\nstruct saa1099_noise\n{\n\t/* vars to simulate the noise generator output */\n\tdouble counter;\n\tdouble freq;\n\tint level;\t\t\t\t\t\t/* noise polynomal shifter */\n};\n\n/* this structure defines a SAA1099 chip */\ntypedef struct _saa1099_state saa1099_state;\nstruct _saa1099_state\n{\n\t//device_t *device;\n\t//sound_stream * stream;\t\t\t/* our stream */\n\tint noise_params[2];\t\t\t/* noise generators parameters */\n\tint env_enable[2];\t\t\t\t/* envelope generators enable */\n\tint env_reverse_right[2];\t\t/* envelope reversed for right channel */\n\tint env_mode[2];\t\t\t\t/* envelope generators mode */\n\tint env_bits[2];\t\t\t\t/* non zero = 3 bits resolution */\n\tint env_clock[2];\t\t\t\t/* envelope clock mode (non-zero external) */\n\tint env_step[2];\t\t\t\t/* current envelope step */\n\tint all_ch_enable;\t\t\t\t/* all channels enable */\n\tint sync_state;\t\t\t\t\t/* sync all channels */\n\tint selected_reg;\t\t\t\t/* selected register */\n\tstruct saa1099_channel channels[6];\t/* channels */\n\tstruct saa1099_noise noise[2];\t/* noise generators */\n\tdouble sample_rate;\n\tint master_clock;\n};\n\nstatic const int amplitude_lookup[16] = {\n\t 0*32767/16,  1*32767/16,  2*32767/16,  3*32767/16,\n\t 4*32767/16,  5*32767/16,  6*32767/16,  7*32767/16,\n\t 8*32767/16,  9*32767/16, 10*32767/16, 11*32767/16,\n\t12*32767/16, 13*32767/16, 14*32767/16, 15*32767/16\n};\n\nstatic const UINT8 envelope[8][64] = {\n\t/* zero amplitude */\n\t{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\n\t/* maximum amplitude */\n\t{15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,\n\t 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,\n\t 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,\n\t 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, },\n\t/* single decay */\n\t{15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,\n\t  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\n\t/* repetitive decay */\n\t{15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,\n\t 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,\n\t 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,\n\t 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },\n\t/* single triangular */\n\t{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,\n\t 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,\n\t  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\n\t/* repetitive triangular */\n\t{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,\n\t 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,\n\t  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,\n\t 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },\n\t/* single attack */\n\t{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,\n\t  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\n\t/* repetitive attack */\n\t{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,\n\t  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,\n\t  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,\n\t  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 }\n};\n\n\n#define MAX_CHIPS\t0x02\nstatic saa1099_state SAA1099Data[MAX_CHIPS];\n\n/*INLINE saa1099_state *get_safe_token(device_t *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == SAA1099);\n\treturn (saa1099_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n\nstatic void saa1099_envelope(saa1099_state *saa, int ch)\n{\n\tif (saa->env_enable[ch])\n\t{\n\t\tint step, mode, mask;\n\t\tmode = saa->env_mode[ch];\n\t\t/* step from 0..63 and then loop in steps 32..63 */\n\t\tstep = saa->env_step[ch] =\n\t\t\t((saa->env_step[ch] + 1) & 0x3f) | (saa->env_step[ch] & 0x20);\n\n\t\tmask = 15;\n\t\tif (saa->env_bits[ch])\n\t\t\tmask &= ~1; \t/* 3 bit resolution, mask LSB */\n\n\t\tsaa->channels[ch*3+0].envelope[ LEFT] =\n\t\tsaa->channels[ch*3+1].envelope[ LEFT] =\n\t\tsaa->channels[ch*3+2].envelope[ LEFT] = envelope[mode][step] & mask;\n\t\tif (saa->env_reverse_right[ch] & 0x01)\n\t\t{\n\t\t\tsaa->channels[ch*3+0].envelope[RIGHT] =\n\t\t\tsaa->channels[ch*3+1].envelope[RIGHT] =\n\t\t\tsaa->channels[ch*3+2].envelope[RIGHT] = (15 - envelope[mode][step]) & mask;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsaa->channels[ch*3+0].envelope[RIGHT] =\n\t\t\tsaa->channels[ch*3+1].envelope[RIGHT] =\n\t\t\tsaa->channels[ch*3+2].envelope[RIGHT] = envelope[mode][step] & mask;\n\t\t}\n\t}\n\telse\n\t{\n\t\t/* envelope mode off, set all envelope factors to 16 */\n\t\tsaa->channels[ch*3+0].envelope[ LEFT] =\n\t\tsaa->channels[ch*3+1].envelope[ LEFT] =\n\t\tsaa->channels[ch*3+2].envelope[ LEFT] =\n\t\tsaa->channels[ch*3+0].envelope[RIGHT] =\n\t\tsaa->channels[ch*3+1].envelope[RIGHT] =\n\t\tsaa->channels[ch*3+2].envelope[RIGHT] = 16;\n    }\n}\n\n\n//static STREAM_UPDATE( saa1099_update )\nvoid saa1099_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//saa1099_state *saa = (saa1099_state *)param;\n\tsaa1099_state *saa = &SAA1099Data[ChipID];\n\tint j, ch;\n\tint clk2div512;\n\n\t/* if the channels are disabled we're done */\n\tif (!saa->all_ch_enable)\n\t{\n\t\t/* init output data */\n\t\tmemset(outputs[LEFT],0,samples*sizeof(*outputs[LEFT]));\n\t\tmemset(outputs[RIGHT],0,samples*sizeof(*outputs[RIGHT]));\n\t\treturn;\n\t}\n\n\tfor (ch = 0; ch < 2; ch++)\n\t{\n\t\tswitch (saa->noise_params[ch])\n\t\t{\n\t\tcase 0: saa->noise[ch].freq = saa->master_clock/ 256.0 * 2; break;\n\t\tcase 1: saa->noise[ch].freq = saa->master_clock/ 512.0 * 2; break;\n\t\tcase 2: saa->noise[ch].freq = saa->master_clock/1024.0 * 2; break;\n\t\tcase 3: saa->noise[ch].freq = saa->channels[ch * 3].freq;   break;\n\t\t}\n\t}\n\n\t// clock fix thanks to http://www.vogons.org/viewtopic.php?p=344227#p344227\n\t//clk2div512 = 2 * saa->master_clock / 512;\n\tclk2div512 = (saa->master_clock + 128) / 256;\n\t\n\t/* fill all data needed */\n\tfor( j = 0; j < samples; j++ )\n\t{\n\t\tint output_l = 0, output_r = 0;\n\n\t\t/* for each channel */\n\t\tfor (ch = 0; ch < 6; ch++)\n\t\t{\n\t\t\tif (saa->channels[ch].freq == 0.0)\n\t\t\t\tsaa->channels[ch].freq = (double)(clk2div512 << saa->channels[ch].octave) /\n\t\t\t\t\t(511.0 - (double)saa->channels[ch].frequency);\n\n\t\t\t/* check the actual position in the square wave */\n\t\t\tsaa->channels[ch].counter -= saa->channels[ch].freq;\n\t\t\twhile (saa->channels[ch].counter < 0)\n\t\t\t{\n\t\t\t\t/* calculate new frequency now after the half wave is updated */\n\t\t\t\tsaa->channels[ch].freq = (double)(clk2div512 << saa->channels[ch].octave) /\n\t\t\t\t\t(511.0 - (double)saa->channels[ch].frequency);\n\n\t\t\t\tsaa->channels[ch].counter += saa->sample_rate;\n\t\t\t\tsaa->channels[ch].level ^= 1;\n\n\t\t\t\t/* eventually clock the envelope counters */\n\t\t\t\tif (ch == 1 && saa->env_clock[0] == 0)\n\t\t\t\t\tsaa1099_envelope(saa, 0);\n\t\t\t\tif (ch == 4 && saa->env_clock[1] == 0)\n\t\t\t\t\tsaa1099_envelope(saa, 1);\n\t\t\t}\n\n\t\t\tif (saa->channels[ch].Muted)\n\t\t\t\tcontinue;\t// placed here to ensure that envelopes are updated\n\t\t\t\n#if 0\n\t\t\t// if the noise is enabled\n\t\t\tif (saa->channels[ch].noise_enable)\n\t\t\t{\n\t\t\t\t// if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5)\n\t\t\t\tif (saa->noise[ch/3].level & 1)\n\t\t\t\t{\n\t\t\t\t\t// subtract to avoid overflows, also use only half amplitude\n\t\t\t\t\toutput_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16;\n\t\t\t\t\toutput_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// if the square wave is enabled\n\t\t\tif (saa->channels[ch].freq_enable)\n\t\t\t{\n\t\t\t\t// if the channel level is high\n\t\t\t\tif (saa->channels[ch].level & 1)\n\t\t\t\t{\n\t\t\t\t\toutput_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16;\n\t\t\t\t\toutput_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16;\n\t\t\t\t}\n\t\t\t}\n#else\n\t\t\t// Now with bipolar output. -Valley Bell\n\t\t\tif (saa->channels[ch].noise_enable)\n\t\t\t{\n\t\t\t\tif (saa->noise[ch/3].level & 1)\n\t\t\t\t{\n\t\t\t\t\toutput_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 32;\n\t\t\t\t\toutput_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 32;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\toutput_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 32;\n\t\t\t\t\toutput_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 32;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (saa->channels[ch].freq_enable)\n\t\t\t{\n\t\t\t\tif (saa->channels[ch].level & 1)\n\t\t\t\t{\n\t\t\t\t\toutput_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 32;\n\t\t\t\t\toutput_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 32;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\toutput_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 32;\n\t\t\t\t\toutput_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 32;\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t}\n\n\t\tfor (ch = 0; ch < 2; ch++)\n\t\t{\n\t\t\t/* check the actual position in noise generator */\n\t\t\tsaa->noise[ch].counter -= saa->noise[ch].freq;\n\t\t\twhile (saa->noise[ch].counter < 0)\n\t\t\t{\n\t\t\t\tsaa->noise[ch].counter += saa->sample_rate;\n\t\t\t\tif( ((saa->noise[ch].level & 0x4000) == 0) == ((saa->noise[ch].level & 0x0040) == 0) )\n\t\t\t\t\tsaa->noise[ch].level = (saa->noise[ch].level << 1) | 1;\n\t\t\t\telse\n\t\t\t\t\tsaa->noise[ch].level <<= 1;\n\t\t\t}\n\t\t}\n\t\t/* write sound data to the buffer */\n\t\toutputs[LEFT][j] = output_l / 6;\n\t\toutputs[RIGHT][j] = output_r / 6;\n\t}\n}\n\n\n\n//static DEVICE_START( saa1099 )\nint device_start_saa1099(UINT8 ChipID, int clock)\n{\n\t//saa1099_state *saa = get_safe_token(device);\n\tsaa1099_state *saa;\n\tUINT8 CurChn;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tsaa = &SAA1099Data[ChipID];\n\n\t/* copy global parameters */\n\t//saa->device = device;\n\t//saa->sample_rate = device->clock() / 256;\n\tsaa->master_clock = clock;\n\tsaa->sample_rate = clock / 128.0 * 8;\n\n\t/* for each chip allocate one stream */\n\t//saa->stream = device->machine().sound().stream_alloc(*device, 0, 2, saa->sample_rate, saa, saa1099_update);\n\t\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t\tsaa->channels[CurChn].Muted = 0x00;\n\t\n\treturn (int)(saa->sample_rate + 0.5);\n}\n\nvoid device_stop_saa1099(UINT8 ChipID)\n{\n\tsaa1099_state *saa = &SAA1099Data[ChipID];\n\t\n\treturn;\n}\n\nvoid device_reset_saa1099(UINT8 ChipID)\n{\n\tsaa1099_state *saa = &SAA1099Data[ChipID];\n\tstruct saa1099_channel *sachn;\n\tUINT8 CurChn;\n\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t{\n\t\tsachn = &saa->channels[CurChn];\n\t\tsachn->frequency = 0;\n\t\tsachn->octave = 0;\n\t\tsachn->amplitude[0] = 0;\n\t\tsachn->amplitude[1] = 0;\n\t\tsachn->envelope[0] = 0;\n\t\tsachn->envelope[1] = 0;\n\t\tsachn->freq_enable = 0;\n\t\tsachn->noise_enable = 0;\n\t\t\n\t\tsachn->counter = 0;\n\t\tsachn->freq = 0;\n\t\tsachn->level = 0;\n\t}\n\tfor (CurChn = 0; CurChn < 2; CurChn ++)\n\t{\n\t\tsaa->noise[CurChn].counter = 0;\n\t\tsaa->noise[CurChn].freq = 0;\n\t\tsaa->noise[CurChn].level = 0;\n\t\t\n\t\tsaa->noise_params[1] = 0x00;\n\t\tsaa->env_reverse_right[CurChn] = 0x00;\n\t\tsaa->env_mode[CurChn] = 0x00;\n\t\tsaa->env_bits[CurChn] = 0x00;\n\t\tsaa->env_clock[CurChn] = 0x00;\n\t\tsaa->env_enable[CurChn] = 0x00;\n\t\tsaa->env_step[CurChn] = 0;\n\t}\n\t\n\tsaa->all_ch_enable = 0x00;\n\tsaa->sync_state = 0x00;\n\t\n\treturn;\n}\n\n//WRITE8_DEVICE_HANDLER( saa1099_control_w )\nvoid saa1099_control_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//saa1099_state *saa = get_safe_token(device);\n\tsaa1099_state *saa = &SAA1099Data[ChipID];\n\n\tif ((data & 0xff) > 0x1c)\n\t{\n\t\t/* Error! */\n\t\t//logerror(\"%s: (SAA1099 '%s') Unknown register selected\\n\",device->machine().describe_context(), device->tag());\n\t\tlogerror(\"SAA1099: Unknown register selected\\n\");\n\t}\n\n\tsaa->selected_reg = data & 0x1f;\n\tif (saa->selected_reg == 0x18 || saa->selected_reg == 0x19)\n\t{\n\t\t/* clock the envelope channels */\n\t\tif (saa->env_clock[0])\n\t\t\tsaa1099_envelope(saa,0);\n\t\tif (saa->env_clock[1])\n\t\t\tsaa1099_envelope(saa,1);\n    }\n}\n\n\n//WRITE8_DEVICE_HANDLER( saa1099_data_w )\nvoid saa1099_data_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//saa1099_state *saa = get_safe_token(device);\n\tsaa1099_state *saa = &SAA1099Data[ChipID];\n\tint reg = saa->selected_reg;\n\tint ch;\n\n\t/* first update the stream to this point in time */\n\t//saa->stream->update();\n\n\tswitch (reg)\n\t{\n\t/* channel i amplitude */\n\tcase 0x00:\tcase 0x01:\tcase 0x02:\tcase 0x03:\tcase 0x04:\tcase 0x05:\n\t\tch = reg & 7;\n\t\tsaa->channels[ch].amplitude[LEFT] = amplitude_lookup[data & 0x0f];\n\t\tsaa->channels[ch].amplitude[RIGHT] = amplitude_lookup[(data >> 4) & 0x0f];\n\t\tbreak;\n\t/* channel i frequency */\n\tcase 0x08:\tcase 0x09:\tcase 0x0a:\tcase 0x0b:\tcase 0x0c:\tcase 0x0d:\n\t\tch = reg & 7;\n\t\tsaa->channels[ch].frequency = data & 0xff;\n\t\tbreak;\n\t/* channel i octave */\n\tcase 0x10:\tcase 0x11:\tcase 0x12:\n\t\tch = (reg - 0x10) << 1;\n\t\tsaa->channels[ch + 0].octave = data & 0x07;\n\t\tsaa->channels[ch + 1].octave = (data >> 4) & 0x07;\n\t\tbreak;\n\t/* channel i frequency enable */\n\tcase 0x14:\n\t\tsaa->channels[0].freq_enable = data & 0x01;\n\t\tsaa->channels[1].freq_enable = data & 0x02;\n\t\tsaa->channels[2].freq_enable = data & 0x04;\n\t\tsaa->channels[3].freq_enable = data & 0x08;\n\t\tsaa->channels[4].freq_enable = data & 0x10;\n\t\tsaa->channels[5].freq_enable = data & 0x20;\n\t\tbreak;\n\t/* channel i noise enable */\n\tcase 0x15:\n\t\tsaa->channels[0].noise_enable = data & 0x01;\n\t\tsaa->channels[1].noise_enable = data & 0x02;\n\t\tsaa->channels[2].noise_enable = data & 0x04;\n\t\tsaa->channels[3].noise_enable = data & 0x08;\n\t\tsaa->channels[4].noise_enable = data & 0x10;\n\t\tsaa->channels[5].noise_enable = data & 0x20;\n\t\tbreak;\n\t/* noise generators parameters */\n\tcase 0x16:\n\t\tsaa->noise_params[0] = data & 0x03;\n\t\tsaa->noise_params[1] = (data >> 4) & 0x03;\n\t\tbreak;\n\t/* envelope generators parameters */\n\tcase 0x18:\tcase 0x19:\n\t\tch = reg - 0x18;\n\t\tsaa->env_reverse_right[ch] = data & 0x01;\n\t\tsaa->env_mode[ch] = (data >> 1) & 0x07;\n\t\tsaa->env_bits[ch] = data & 0x10;\n\t\tsaa->env_clock[ch] = data & 0x20;\n\t\tsaa->env_enable[ch] = data & 0x80;\n\t\t/* reset the envelope */\n\t\tsaa->env_step[ch] = 0;\n\t\tbreak;\n\t/* channels enable & reset generators */\n\tcase 0x1c:\n\t\tsaa->all_ch_enable = data & 0x01;\n\t\tsaa->sync_state = data & 0x02;\n\t\tif (data & 0x02)\n\t\t{\n\t\t\tint i;\n\n\t\t\t/* Synch & Reset generators */\n\t\t\t//logerror(\"%s: (SAA1099 '%s') -reg 0x1c- Chip reset\\n\",device->machine().describe_context(), device->tag());\n\t\t\tlogerror(\"SAA1099: -reg 0x1c- Chip reset\\n\");\n\t\t\tfor (i = 0; i < 6; i++)\n\t\t\t{\n\t\t\t\tsaa->channels[i].level = 0;\n\t\t\t\tsaa->channels[i].counter = 0.0;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tdefault:\t/* Error! */\n\t\t//logerror(\"%s: (SAA1099 '%s') Unknown operation (reg:%02x, data:%02x)\\n\",device->machine().describe_context(), device->tag(), reg, data);\n\t\tlogerror(\"SAA1099: Unknown operation (reg:%02x, data:%02x)\\n\",reg, data);\n\t}\n}\n\n\nvoid saa1099_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tsaa1099_state *saa = &SAA1099Data[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t\tsaa->channels[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( saa1099 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(saa1099_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( saa1099 );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing //\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// Nothing //\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"SAA1099\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Philips\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}\n\n\nDEFINE_LEGACY_SOUND_DEVICE(SAA1099, saa1099);*/\n"
  },
  {
    "path": "VGMPlay/chips/saa1099.h",
    "content": "#pragma once\n\n#ifndef __SAA1099_H__\n#define __SAA1099_H__\n\n/**********************************************\n    Philips SAA1099 Sound driver\n**********************************************/\n\n//WRITE8_DEVICE_HANDLER( saa1099_control_w );\nvoid saa1099_control_w(UINT8 ChipID, offs_t offset, UINT8 data);\n//WRITE8_DEVICE_HANDLER( saa1099_data_w );\nvoid saa1099_data_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\n//DECLARE_LEGACY_SOUND_DEVICE(SAA1099, saa1099);\nvoid saa1099_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_saa1099(UINT8 ChipID, int clock);\nvoid device_stop_saa1099(UINT8 ChipID);\nvoid device_reset_saa1099(UINT8 ChipID);\n\nvoid saa1099_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n#endif /* __SAA1099_H__ */\n"
  },
  {
    "path": "VGMPlay/chips/scd_pcm.c",
    "content": "/***********************************************************/\n/*                                                         */\n/* PCM.C : PCM RF5C164 emulator                            */\n/*                                                         */\n/* This source is a part of Gens project                   */\n/* Written by Stphane Dallongeville (gens@consolemul.com) */\n/* Copyright (c) 2002 by Stphane Dallongeville            */\n/*                                                         */\n/***********************************************************/\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n\n#include \"mamedef.h\"\n#include \"scd_pcm.h\"\nint  PCM_Init(UINT8 ChipID, int Rate);\nvoid PCM_Set_Rate(UINT8 ChipID, int Rate);\nvoid PCM_Reset(UINT8 ChipID);\nvoid PCM_Write_Reg(UINT8 ChipID, unsigned int Reg, unsigned int Data);\nint  PCM_Update(UINT8 ChipID, int **buf, int Length);\n\n#define PCM_STEP_SHIFT 11\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\n#define MAX_CHIPS\t0x02\nstatic struct pcm_chip_ PCM_Chip[MAX_CHIPS];\n\n/*static unsigned char VolTabIsInit = 0x00;\nstatic int PCM_Volume_Tab[256 * 256];*/\n\n//unsigned char Ram_PCM[64 * 1024];\n//int PCM_Enable;\n\n\n/**\n * PCM_Init(): Initialize the PCM chip.\n * @param Rate Sample rate.\n * @return 0 if successful.\n */\nint PCM_Init(UINT8 ChipID, int Rate)\n{\n\tstruct pcm_chip_ *chip = &PCM_Chip[ChipID];\n\tint i/*, j, out*/;\n\t\n\t/*if (! VolTabIsInit)\n\t{\n\t\tfor (i = 0; i < 0x100; i++)\n\t\t{\n\t\t\tfor (j = 0; j < 0x100; j++)\n\t\t\t{\n\t\t\t\tif (i & 0x80)\n\t\t\t\t{\n\t\t\t\t\tout = -(i & 0x7F);\n\t\t\t\t\tout *= j;\n\t\t\t\t\tPCM_Volume_Tab[(j << 8) + i] = out;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tout = i * j;\n\t\t\t\t\tPCM_Volume_Tab[(j << 8) + i] = out;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tVolTabIsInit = 0x01;\n\t}*/\n\t\n\tchip->Smpl0Patch = 0;\n\tfor (i = 0; i < 8; i ++)\n\t\tchip->Channel[i].Muted = 0x00;\n\t\n\tchip->RAMSize = 64 * 1024;\n\tchip->RAM = (unsigned char*)malloc(chip->RAMSize);\n\tPCM_Reset(ChipID);\n\tPCM_Set_Rate(ChipID, Rate);\n\t\n\treturn 0;\n}\n\n\n/**\n * PCM_Reset(): Reset the PCM chip.\n */\nvoid PCM_Reset(UINT8 ChipID)\n{\n\tstruct pcm_chip_ *chip = &PCM_Chip[ChipID];\n\tint i;\n\tstruct pcm_chan_* chan;\n\t\n\t// Clear the PCM memory.\n\tmemset(chip->RAM, 0x00, chip->RAMSize);\n\t\n\tchip->Enable = 0;\n\tchip->Cur_Chan = 0;\n\tchip->Bank = 0;\n\t\n\t/* clear channel registers */\n\tfor (i = 0; i < 8; i++)\n\t{\n\t\tchan = &chip->Channel[i];\n\t\tchan->Enable = 0;\n\t\tchan->ENV = 0;\n\t\tchan->PAN = 0;\n\t\tchan->St_Addr = 0;\n\t\tchan->Addr = 0;\n\t\tchan->Loop_Addr = 0;\n\t\tchan->Step = 0;\n\t\tchan->Step_B = 0;\n\t\tchan->Data = 0;\n\t}\n}\n\n\n/**\n * PCM_Set_Rate(): Change the PCM sample rate.\n * @param Rate New sample rate.\n */\nvoid PCM_Set_Rate(UINT8 ChipID, int Rate)\n{\n\tstruct pcm_chip_ *chip = &PCM_Chip[ChipID];\n\tint i;\n\t\n\tif (Rate == 0)\n\t\treturn;\n\t\n\t//chip->Rate = (float) (32 * 1024) / (float) Rate;\n\tchip->Rate = (float) (31.8 * 1024) / (float) Rate;\n\t\n\tfor (i = 0; i < 8; i++)\n\t{\n\t\tchip->Channel[i].Step =\n\t\t\t(int) ((float) chip->Channel[i].Step_B * chip->Rate);\n\t}\n}\n\n\n/**\n * PCM_Write_Reg(): Write to a PCM register.\n * @param Reg Register ID.\n * @param Data Data to write.\n */\nvoid PCM_Write_Reg(UINT8 ChipID, unsigned int Reg, unsigned int Data)\n{\n\tstruct pcm_chip_ *chip = &PCM_Chip[ChipID];\n\tint i;\n\tstruct pcm_chan_* chan = &chip->Channel[chip->Cur_Chan];\n\t\n\tData &= 0xFF;\n\t\n\tswitch (Reg)\n\t{\n\t\tcase 0x00:\n\t\t\t/* evelope register */\n\t\t\tchan->ENV = Data;\n\t\t\tchan->MUL_L = (Data * (chan->PAN & 0x0F)) >> 5;\n\t\t\tchan->MUL_R = (Data * (chan->PAN >> 4)) >> 5;\n\t\tbreak;\n\t\t\n\t\tcase 0x01:\n\t\t\t/* pan register */\n\t\t\tchan->PAN = Data;\n\t\t\tchan->MUL_L = ((Data & 0x0F) * chan->ENV) >> 5;\n\t\t\tchan->MUL_R = ((Data >> 4) * chan->ENV) >> 5;\n\t\t\tbreak;\n\t\t\n\t\tcase 0x02:\n\t\t\t/* frequency step (LB) registers */\n\t\t\tchan->Step_B &= 0xFF00;\n\t\t\tchan->Step_B += Data;\n\t\t\tchan->Step = (int)((float)chan->Step_B * chip->Rate);\n\t\t\t\n\t\t\t//LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,\n\t\t\t//\t\"Step low = %.2X   Step calculated = %.8X\",\n\t\t\t//\tData, chan->Step);\n\t\t\tbreak;\n\t\t\n\t\tcase 0x03:\n\t\t\t/* frequency step (HB) registers */\n\t\t\tchan->Step_B &= 0x00FF;\n\t\t\tchan->Step_B += Data << 8;\n\t\t\tchan->Step = (int)((float)chan->Step_B * chip->Rate);\n\t\t\t\n\t\t\t//LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,\n\t\t\t//\t\"Step high = %.2X   Step calculated = %.8X\",\n\t\t\t//\tData, chan->Step);\n\t\t\tbreak;\n\t\t\n\t\tcase 0x04:\n\t\t\tchan->Loop_Addr &= 0xFF00;\n\t\t\tchan->Loop_Addr += Data;\t\t\t\n\t\t\t\n\t\t\t//LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,\n\t\t\t//\t\"Loop low = %.2X   Loop = %.8X\",\n\t\t\t//\tData, chan->Loop_Addr);\n\t\t\tbreak;\n\t\t\n\t\tcase 0x05:\n\t\t\t/* loop address registers */\n\t\t\tchan->Loop_Addr &= 0x00FF;\n\t\t\tchan->Loop_Addr += Data << 8;\n\t\t\t\n\t\t\t//LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,\n\t\t\t//\t\"Loop high = %.2X   Loop = %.8X\",\n\t\t\t//\tData, chan->Loop_Addr);\n\t\t\tbreak;\n\t\t\n\t\tcase 0x06:\n\t\t\t/* start address registers */\n\t\t\tchan->St_Addr = Data << (PCM_STEP_SHIFT + 8);\n\t\t\t//chan->Addr = chan->St_Addr;\n\t\t\t\n\t\t\t//LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,\n\t\t\t//\t\"Start addr = %.2X   New Addr = %.8X\",\n\t\t\t//\tData, chan->Addr);\n\t\t\tbreak;\n\t\t\n\t\tcase 0x07:\n\t\t\t/* control register */\n\t\t\t/* mod is H */\n\t\t\tif (Data & 0x40)\n\t\t\t{\n\t\t\t\t/* select channel */\n\t\t\t\tchip->Cur_Chan = Data & 0x07;\n\t\t\t}\n\t\t\t/* mod is L */\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* pcm ram bank select */\n\t\t\t\tchip->Bank = (Data & 0x0F) << 12;\n\t\t\t}\n\t\t\t\n\t\t\t/* sounding bit */\n\t\t\tif (Data & 0x80)\n\t\t\t\tchip->Enable = 0xFF;\t// Used as mask\n\t\t\telse\n\t\t\t\tchip->Enable = 0;\n\t\t\t\n\t\t\t//LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,\n\t\t\t//\t\"General Enable = %.2X\", Data);\n\t\t\tbreak;\n\t\t\n\t\tcase 0x08:\n\t\t\t/* sound on/off register */\n\t\t\tData ^= 0xFF;\n\t\t\t\n\t\t\t//LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,\n\t\t\t//\t\"Channel Enable = %.2X\", Data);\n\t\t\t\n\t\t\tfor (i = 0; i < 8; i++)\n\t\t\t{\n\t\t\t\tchan = &chip->Channel[i];\n\t\t\t\tif (!chan->Enable)\n\t\t\t\t\tchan->Addr = chan->St_Addr;\n\t\t\t}\n\t\t\t\n\t\t\tfor (i = 0; i < 8; i++)\n\t\t\t{\n\t\t\t\tchip->Channel[i].Enable = Data & (1 << i);\n\t\t\t}\n\t}\n}\n\n\n/**\n * PCM_Update(): Update the PCM buffer.\n * @param buf PCM buffer.\n * @param Length Buffer length.\n */\nint PCM_Update(UINT8 ChipID, int **buf, int Length)\n{\n\tstruct pcm_chip_ *chip = &PCM_Chip[ChipID];\n\tint i, j;\n\tint *bufL, *bufR;\t\t//, *volL, *volR;\n\tunsigned int Addr, k;\n\tstruct pcm_chan_ *CH;\n\t\n\tbufL = buf[0];\n\tbufR = buf[1];\n\t\n\t// clear buffers\n\tmemset(bufL, 0, Length * sizeof(int));\n\tmemset(bufR, 0, Length * sizeof(int));\n\n\t// if PCM disable, no sound\n\tif (!chip->Enable)\n\t\treturn 1;\n\t\n#if 0\n\t// faster for short update\n\tfor (j = 0; j < Length; j++)\n\t{\n\t\tfor (i = 0; i < 8; i++)\n\t\t{\n\t\t\tCH = &(chip->Channel[i]);\n\n\t\t\t// only loop when sounding and on\n\t\t\tif (CH->Enable && ! CH->Muted)\n\t\t\t{\n\t\t\t\tAddr = CH->Addr >> PCM_STEP_SHIFT;\n\n\t\t\t\tif (Addr & 0x10000)\n\t\t\t\t{\n\t\t\t\t\tfor(k = CH->Old_Addr; k < 0x10000; k++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (chip->RAM[k] == 0xFF)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCH->Old_Addr = Addr = CH->Loop_Addr;\n\t\t\t\t\t\t\tCH->Addr = Addr << PCM_STEP_SHIFT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Addr & 0x10000)\n\t\t\t\t\t{\n\t\t\t\t\t\t//CH->Addr -= CH->Step;\n\t\t\t\t\t\tCH->Enable = 0;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfor(k = CH->Old_Addr; k <= Addr; k++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (chip->RAM[k] == 0xFF)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCH->Old_Addr = Addr = CH->Loop_Addr;\n\t\t\t\t\t\t\tCH->Addr = Addr << PCM_STEP_SHIFT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// test for loop signal\n\t\t\t\tif (chip->RAM[Addr] == 0xFF)\n\t\t\t\t{\n\t\t\t\t\tAddr = CH->Loop_Addr;\n\t\t\t\t\tCH->Addr = Addr << PCM_STEP_SHIFT;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (chip->RAM[Addr] & 0x80)\n\t\t\t\t{\n\t\t\t\t\tCH->Data = chip->RAM[Addr] & 0x7F;\n\t\t\t\t\tbufL[j] -= CH->Data * CH->MUL_L;\n\t\t\t\t\tbufR[j] -= CH->Data * CH->MUL_R;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tCH->Data = chip->RAM[Addr];\n\t\t\t\t\tbufL[j] += CH->Data * CH->MUL_L;\n\t\t\t\t\tbufR[j] += CH->Data * CH->MUL_R;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// update address register\n\t\t\t\t//CH->Addr = (CH->Addr + CH->Step) & 0x7FFFFFF;\n\t\t\t\tCH->Addr += CH->Step;\n\t\t\t\tCH->Old_Addr = Addr + 1;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n#if 1\n\t// for long update\n\tfor (i = 0; i < 8; i++)\n\t{\n\t\tCH = &(chip->Channel[i]);\n\t\t\n\t\t// only loop when sounding and on\n\t\tif (CH->Enable && ! CH->Muted)\n\t\t{\n\t\t\tAddr = CH->Addr >> PCM_STEP_SHIFT;\n\t\t\t//volL = &(PCM_Volume_Tab[CH->MUL_L << 8]);\n\t\t\t//volR = &(PCM_Volume_Tab[CH->MUL_R << 8]);\n\t\t\t\n\t\t\tfor (j = 0; j < Length; j++)\n\t\t\t{\n\t\t\t\t// test for loop signal\n\t\t\t\tif (chip->RAM[Addr] == 0xFF)\n\t\t\t\t{\n\t\t\t\t\tCH->Addr = (Addr = CH->Loop_Addr) << PCM_STEP_SHIFT;\n\t\t\t\t\tif (chip->RAM[Addr] == 0xFF)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\telse\n\t\t\t\t\t\tj--;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (chip->RAM[Addr] & 0x80)\n\t\t\t\t\t{\n\t\t\t\t\t\tCH->Data = chip->RAM[Addr] & 0x7F;\n\t\t\t\t\t\tbufL[j] -= CH->Data * CH->MUL_L;\n\t\t\t\t\t\tbufR[j] -= CH->Data * CH->MUL_R;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tCH->Data = chip->RAM[Addr];\n\t\t\t\t\t\t// this improves the sound of Cosmic Fantasy Stories,\n\t\t\t\t\t\t// although it's definately false behaviour\n\t\t\t\t\t\tif (! CH->Data && chip->Smpl0Patch)\n\t\t\t\t\t\t\tCH->Data = -0x7F;\n\t\t\t\t\t\tbufL[j] += CH->Data * CH->MUL_L;\n\t\t\t\t\t\tbufR[j] += CH->Data * CH->MUL_R;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// update address register\n\t\t\t\t\tk = Addr + 1;\n\t\t\t\t\tCH->Addr = (CH->Addr + CH->Step) & 0x7FFFFFF;\n\t\t\t\t\tAddr = CH->Addr >> PCM_STEP_SHIFT;\n\t\t\t\t\t\n\t\t\t\t\tfor (; k < Addr; k++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (chip->RAM[k] == 0xFF)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCH->Addr = (Addr = CH->Loop_Addr) << PCM_STEP_SHIFT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (chip->RAM[Addr] == 0xFF)\n\t\t\t{\n\t\t\t\tCH->Addr = CH->Loop_Addr << PCM_STEP_SHIFT;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\t\n\treturn 0;\n}\n\n\nvoid rf5c164_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tstruct pcm_chip_ *chip = &PCM_Chip[ChipID];\n\t\n\tPCM_Update(ChipID, outputs, samples);\n}\n\nint device_start_rf5c164(UINT8 ChipID, int clock)\n{\n\t/* allocate memory for the chip */\n\t//rf5c164_state *chip = get_safe_token(device);\n\tstruct pcm_chip_ *chip;\n\tint rate;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &PCM_Chip[ChipID];\n\trate = (clock & 0x7FFFFFFF) / 384;\n\tif (((CHIP_SAMPLING_MODE & 0x01) && rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\trate = CHIP_SAMPLE_RATE;\n\t\n\tPCM_Init(ChipID, rate);\n\tchip->Smpl0Patch = (clock & 0x80000000) >> 31;\n\t\n\t/* allocate the stream */\n\t//chip->stream = stream_create(device, 0, 2, device->clock / 384, chip, rf5c68_update);\n\t\n\treturn rate;\n}\n\nvoid device_stop_rf5c164(UINT8 ChipID)\n{\n\tstruct pcm_chip_ *chip = &PCM_Chip[ChipID];\n\tfree(chip->RAM);\tchip->RAM = NULL;\n\t\n\treturn;\n}\n\nvoid device_reset_rf5c164(UINT8 ChipID)\n{\n\t//struct pcm_chip_ *chip = &PCM_Chip[ChipID];\n\tPCM_Reset(ChipID);\n}\n\nvoid rf5c164_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//struct pcm_chip_ *chip = &PCM_Chip[ChipID];\n\tPCM_Write_Reg(ChipID, offset, data);\n}\n\nvoid rf5c164_mem_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tstruct pcm_chip_ *chip = &PCM_Chip[ChipID];\n\tchip->RAM[chip->Bank | offset] = data;\n}\n\nvoid rf5c164_write_ram(UINT8 ChipID, offs_t DataStart, offs_t DataLength, const UINT8* RAMData)\n{\n\tstruct pcm_chip_ *chip = &PCM_Chip[ChipID];\n\t\n\tDataStart |= chip->Bank;\n\tif (DataStart >= chip->RAMSize)\n\t\treturn;\n\tif (DataStart + DataLength > chip->RAMSize)\n\t\tDataLength = chip->RAMSize - DataStart;\n\t\n\tmemcpy(chip->RAM + DataStart, RAMData, DataLength);\n\t\n\treturn;\n}\n\n\nvoid rf5c164_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tstruct pcm_chip_ *chip = &PCM_Chip[ChipID];\n\tunsigned char CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 8; CurChn ++)\n\t\tchip->Channel[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/scd_pcm.h",
    "content": "struct pcm_chip_\n{\n\tfloat Rate;\n\tint Smpl0Patch;\n\tint Enable;\n\tint Cur_Chan;\n\tint Bank;\n\n\tstruct pcm_chan_\n\t{\n\t\tunsigned int ENV;\t\t/* envelope register */\n\t\tunsigned int PAN;\t\t/* pan register */\n\t\tunsigned int MUL_L;\t\t/* envelope & pan product letf */\n\t\tunsigned int MUL_R;\t\t/* envelope & pan product right */\n\t\tunsigned int St_Addr;\t/* start address register */\n\t\tunsigned int Loop_Addr;\t/* loop address register */\n\t\tunsigned int Addr;\t\t/* current address register */\n\t\tunsigned int Step;\t\t/* frequency register */\n\t\tunsigned int Step_B;\t/* frequency register binaire */\n\t\tunsigned int Enable;\t/* channel on/off register */\n\t\tint Data;\t\t\t\t/* wave data */\n\t\tunsigned int Muted;\n\t} Channel[8];\n\t\n\tunsigned long int RAMSize;\n\tunsigned char* RAM;\n};\n\n//extern struct pcm_chip_ PCM_Chip;\n//extern unsigned char Ram_PCM[64 * 1024];\n//extern int PCM_Enable;\n\n//int  PCM_Init(int Rate);\n//void PCM_Set_Rate(int Rate);\n//void PCM_Reset(void);\n//void PCM_Write_Reg(unsigned int Reg, unsigned int Data);\n//int  PCM_Update(int **buf, int Length);\n\nvoid rf5c164_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_rf5c164(UINT8 ChipID, int clock);\nvoid device_stop_rf5c164(UINT8 ChipID);\nvoid device_reset_rf5c164(UINT8 ChipID);\nvoid rf5c164_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid rf5c164_mem_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid rf5c164_write_ram(UINT8 ChipID, offs_t DataStart, offs_t DataLength, const UINT8* RAMData);\n\nvoid rf5c164_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/chips/scsp.c",
    "content": "/*\n    Sega/Yamaha YMF292-F (SCSP = Saturn Custom Sound Processor) emulation\n    By ElSemi\n    MAME/M1 conversion and cleanup by R. Belmont\n    Additional code and bugfixes by kingshriek\n\n    This chip has 32 voices.  Each voice can play a sample or be part of\n    an FM construct.  Unlike traditional Yamaha FM chips, the base waveform\n    for the FM still comes from the wavetable RAM.\n\n    ChangeLog:\n    * November 25, 2003  (ES) Fixed buggy timers and envelope overflows.\n                         (RB) Improved sample rates other than 44100, multiple\n                             chips now works properly.\n    * December 02, 2003  (ES) Added DISDL register support, improves mix.\n    * April 28, 2004     (ES) Corrected envelope rates, added key-rate scaling,\n                             added ringbuffer support.\n    * January 8, 2005    (RB) Added ability to specify region offset for RAM.\n    * January 26, 2007   (ES) Added on-board DSP capability\n    * September 24, 2007 (RB+ES) Removed fake reverb.  Rewrote timers and IRQ handling.\n                             Fixed case where voice frequency is updated while looping.\n                             Enabled DSP again.\n    * December 16, 2007  (kingshriek) Many EG bug fixes, implemented effects mixer,\n                             implemented FM.\n    * January 5, 2008    (kingshriek+RB) Working, good-sounding FM, removed obsolete non-USEDSP code.\n    * April 22, 2009     (\"PluginNinja\") Improved slot monitor, misc cleanups\n    * June 6, 2011       (AS) Rewrote DMA from scratch, Darius 2 relies on it.\n*/\n\n//#include \"emu.h\"\n#include \"mamedef.h\"\n#include <math.h>\t// for pow() in scsplfo.c\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include \"scsp.h\"\n#include \"scspdsp.h\"\n\n\n#define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x)\n\n#define SHIFT\t12\n#define FIX(v)\t((UINT32) ((float) (1<<SHIFT)*(v)))\n\n\n#define EG_SHIFT\t16\n#define FM_DELAY    0    // delay in number of slots processed before samples are written to the FM ring buffer\n\t\t\t // driver code indicates should be 4, but sounds distorted then\n\n// include the LFO handling code\n#include \"scsplfo.c\"\n\n/*\n    SCSP features 32 programmable slots\n    that can generate FM and PCM (from ROM/RAM) sound\n*/\n\n//SLOT PARAMETERS\n#define KEYONEX(slot)\t\t((slot->udata.data[0x0]>>0x0)&0x1000)\n#define KEYONB(slot)\t\t((slot->udata.data[0x0]>>0x0)&0x0800)\n#define SBCTL(slot)\t\t((slot->udata.data[0x0]>>0x9)&0x0003)\n#define SSCTL(slot)\t\t((slot->udata.data[0x0]>>0x7)&0x0003)\n#define LPCTL(slot)\t\t((slot->udata.data[0x0]>>0x5)&0x0003)\n#define PCM8B(slot)\t\t((slot->udata.data[0x0]>>0x0)&0x0010)\n\n#define SA(slot)\t\t(((slot->udata.data[0x0]&0xF)<<16)|(slot->udata.data[0x1]))\n\n#define LSA(slot)\t\t(slot->udata.data[0x2])\n\n#define LEA(slot)\t\t(slot->udata.data[0x3])\n\n#define D2R(slot)\t\t((slot->udata.data[0x4]>>0xB)&0x001F)\n#define D1R(slot)\t\t((slot->udata.data[0x4]>>0x6)&0x001F)\n#define EGHOLD(slot)\t\t((slot->udata.data[0x4]>>0x0)&0x0020)\n#define AR(slot)\t\t((slot->udata.data[0x4]>>0x0)&0x001F)\n\n#define LPSLNK(slot)\t\t((slot->udata.data[0x5]>>0x0)&0x4000)\n#define KRS(slot)\t\t((slot->udata.data[0x5]>>0xA)&0x000F)\n#define DL(slot)\t\t((slot->udata.data[0x5]>>0x5)&0x001F)\n#define RR(slot)\t\t((slot->udata.data[0x5]>>0x0)&0x001F)\n\n#define STWINH(slot)\t\t((slot->udata.data[0x6]>>0x0)&0x0200)\n#define SDIR(slot)\t\t((slot->udata.data[0x6]>>0x0)&0x0100)\n#define TL(slot)\t\t((slot->udata.data[0x6]>>0x0)&0x00FF)\n\n#define MDL(slot)\t\t((slot->udata.data[0x7]>>0xC)&0x000F)\n#define MDXSL(slot)\t\t((slot->udata.data[0x7]>>0x6)&0x003F)\n#define MDYSL(slot)\t\t((slot->udata.data[0x7]>>0x0)&0x003F)\n\n#define OCT(slot)\t\t((slot->udata.data[0x8]>>0xB)&0x000F)\n#define FNS(slot)\t\t((slot->udata.data[0x8]>>0x0)&0x03FF)\n\n#define LFORE(slot)\t\t((slot->udata.data[0x9]>>0x0)&0x8000)\n#define LFOF(slot)\t\t((slot->udata.data[0x9]>>0xA)&0x001F)\n#define PLFOWS(slot)\t\t((slot->udata.data[0x9]>>0x8)&0x0003)\n#define PLFOS(slot)\t\t((slot->udata.data[0x9]>>0x5)&0x0007)\n#define ALFOWS(slot)\t\t((slot->udata.data[0x9]>>0x3)&0x0003)\n#define ALFOS(slot)\t\t((slot->udata.data[0x9]>>0x0)&0x0007)\n\n#define ISEL(slot)\t\t((slot->udata.data[0xA]>>0x3)&0x000F)\n#define IMXL(slot)\t\t((slot->udata.data[0xA]>>0x0)&0x0007)\n\n#define DISDL(slot)\t\t((slot->udata.data[0xB]>>0xD)&0x0007)\n#define DIPAN(slot)\t\t((slot->udata.data[0xB]>>0x8)&0x001F)\n#define EFSDL(slot)\t\t((slot->udata.data[0xB]>>0x5)&0x0007)\n#define EFPAN(slot)\t\t((slot->udata.data[0xB]>>0x0)&0x001F)\n\n//Envelope times in ms\nstatic const double ARTimes[64]={100000/*infinity*/,100000/*infinity*/,8100.0,6900.0,6000.0,4800.0,4000.0,3400.0,3000.0,2400.0,2000.0,1700.0,1500.0,\n\t\t\t\t\t1200.0,1000.0,860.0,760.0,600.0,500.0,430.0,380.0,300.0,250.0,220.0,190.0,150.0,130.0,110.0,95.0,\n\t\t\t\t\t76.0,63.0,55.0,47.0,38.0,31.0,27.0,24.0,19.0,15.0,13.0,12.0,9.4,7.9,6.8,6.0,4.7,3.8,3.4,3.0,2.4,\n\t\t\t\t\t2.0,1.8,1.6,1.3,1.1,0.93,0.85,0.65,0.53,0.44,0.40,0.35,0.0,0.0};\nstatic const double DRTimes[64]={100000/*infinity*/,100000/*infinity*/,118200.0,101300.0,88600.0,70900.0,59100.0,50700.0,44300.0,35500.0,29600.0,25300.0,22200.0,17700.0,\n\t\t\t\t\t14800.0,12700.0,11100.0,8900.0,7400.0,6300.0,5500.0,4400.0,3700.0,3200.0,2800.0,2200.0,1800.0,1600.0,1400.0,1100.0,\n\t\t\t\t\t920.0,790.0,690.0,550.0,460.0,390.0,340.0,270.0,230.0,200.0,170.0,140.0,110.0,98.0,85.0,68.0,57.0,49.0,43.0,34.0,\n\t\t\t\t\t28.0,25.0,22.0,18.0,14.0,12.0,11.0,8.5,7.1,6.1,5.4,4.3,3.6,3.1};\n\ntypedef enum {ATTACK,DECAY1,DECAY2,RELEASE} _STATE;\nstruct _EG\n{\n\tint volume;\t//\n\t_STATE state;\n\tint step;\n\t//step vals\n\tint AR;\t\t//Attack\n\tint D1R;\t//Decay1\n\tint D2R;\t//Decay2\n\tint RR;\t\t//Release\n\n\tint DL;\t\t//Decay level\n\tUINT8 EGHOLD;\n\tUINT8 LPLINK;\n};\n\nstruct _SLOT\n{\n\tunion\n\t{\n\t\tUINT16 data[0x10];\t//only 0x1a bytes used\n\t\tUINT8 datab[0x20];\n\t} udata;\n\tUINT8 Backwards;\t//the wave is playing backwards\n\tUINT8 active;\t//this slot is currently playing\n\tUINT8 Muted;\n\tUINT8 *base;\t\t//samples base address\n\tUINT32 cur_addr;\t//current play address (24.8)\n\tUINT32 nxt_addr;\t//next play address\n\tUINT32 step;\t\t//pitch step (24.8)\n\tstruct _EG EG;\t\t\t//Envelope\n\tstruct _LFO PLFO;\t\t//Phase LFO\n\tstruct _LFO ALFO;\t\t//Amplitude LFO\n\tint slot;\n\tsigned short Prev;\t//Previous sample (for interpolation)\n};\n\n\n#define MEM4B(scsp)\t\t((scsp->udata.data[0]>>0x0)&0x0200)\n#define DAC18B(scsp)\t\t((scsp->udata.data[0]>>0x0)&0x0100)\n#define MVOL(scsp)\t\t((scsp->udata.data[0]>>0x0)&0x000F)\n#define RBL(scsp)\t\t((scsp->udata.data[1]>>0x7)&0x0003)\n#define RBP(scsp)\t\t((scsp->udata.data[1]>>0x0)&0x003F)\n#define MOFULL(scsp)\t\t((scsp->udata.data[2]>>0x0)&0x1000)\n#define MOEMPTY(scsp)\t\t((scsp->udata.data[2]>>0x0)&0x0800)\n#define MIOVF(scsp)\t\t((scsp->udata.data[2]>>0x0)&0x0400)\n#define MIFULL(scsp)\t\t((scsp->udata.data[2]>>0x0)&0x0200)\n#define MIEMPTY(scsp)\t\t((scsp->udata.data[2]>>0x0)&0x0100)\n\n#define SCILV0(scsp)    \t((scsp->udata.data[0x24/2]>>0x0)&0xff)\n#define SCILV1(scsp)    \t((scsp->udata.data[0x26/2]>>0x0)&0xff)\n#define SCILV2(scsp)    \t((scsp->udata.data[0x28/2]>>0x0)&0xff)\n\n#define SCIEX0\t0\n#define SCIEX1\t1\n#define SCIEX2\t2\n#define SCIMID\t3\n#define SCIDMA\t4\n#define SCIIRQ\t5\n#define SCITMA\t6\n#define SCITMB\t7\n\n#define USEDSP\n\ntypedef struct _scsp_state scsp_state;\nstruct _scsp_state\n{\n\tunion\n\t{\n\t\tUINT16 data[0x30/2];\n\t\tUINT8 datab[0x30];\n\t} udata;\n\tstruct _SLOT Slots[32];\n\tsigned short RINGBUF[128];\n\tunsigned char BUFPTR;\n#if FM_DELAY\n\tsigned short DELAYBUF[FM_DELAY];\n\tunsigned char DELAYPTR;\n#endif\n\tunsigned char *SCSPRAM;\n\tUINT32 SCSPRAM_LENGTH;\n\t//char Master;\n\t//void (*Int68kCB)(device_t *device, int irq);\n\t//sound_stream * stream;\n\tint clock;\n\tint rate;\n\n\t//INT32 *buffertmpl,*buffertmpr;\n\n\t/*UINT32 IrqTimA;\n\tUINT32 IrqTimBC;\n\tUINT32 IrqMidi;*/\n\n\tUINT8 MidiOutW,MidiOutR;\n\tUINT8 MidiStack[32];\n\tUINT8 MidiW,MidiR;\n\n\tINT32 EG_TABLE[0x400];\n\n\tint LPANTABLE[0x10000];\n\tint RPANTABLE[0x10000];\n\n\tint TimPris[3];\n\tint TimCnt[3];\n\n\t// timers\n\t//emu_timer *timerA, *timerB, *timerC;\n\n\t// DMA stuff\n\tstruct\n\t{\n\t\tUINT32 dmea;\n\t\tUINT16 drga;\n\t\tUINT16 dtlg;\n\t\tUINT8 dgate;\n\t\tUINT8 ddir;\n\t} dma;\n\n\tUINT16 mcieb;\n\tUINT16 mcipd;\n\n\tint ARTABLE[64], DRTABLE[64];\n\n\tstruct _SCSPDSP DSP;\n\t//devcb_resolved_write_line main_irq;\n\n\t//device_t *device;\n};\n\n//static void SCSP_exec_dma(address_space *space, scsp_state *scsp);\t\t/*state DMA transfer function*/\n/* TODO */\n//#define dma_transfer_end  ((scsp_regs[0x24/2] & 0x10)>>4)|(((scsp_regs[0x26/2] & 0x10)>>4)<<1)|(((scsp_regs[0x28/2] & 0x10)>>4)<<2)\n\nstatic const float SDLT[8]={-1000000.0f,-36.0f,-30.0f,-24.0f,-18.0f,-12.0f,-6.0f,0.0f};\n\n//static stream_sample_t *bufferl;\n//static stream_sample_t *bufferr;\n\n//static int length;\n\n\nstatic signed short *RBUFDST;\t//this points to where the sample will be stored in the RingBuf\n\n\n#define MAX_CHIPS\t0x02\nstatic scsp_state SCSPData[MAX_CHIPS];\nstatic UINT8 BypassDSP = 0x01;\n\n/*INLINE scsp_state *get_safe_token(device_t *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == SCSP);\n\treturn (scsp_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n/*static unsigned char DecodeSCI(scsp_state *scsp,unsigned char irq)\n{\n\tunsigned char SCI=0;\n\tunsigned char v;\n\tv=(SCILV0((scsp))&(1<<irq))?1:0;\n\tSCI|=v;\n\tv=(SCILV1((scsp))&(1<<irq))?1:0;\n\tSCI|=v<<1;\n\tv=(SCILV2((scsp))&(1<<irq))?1:0;\n\tSCI|=v<<2;\n\treturn SCI;\n}\n\nstatic void CheckPendingIRQ(scsp_state *scsp)\n{\n\tUINT32 pend=scsp->udata.data[0x20/2];\n\tUINT32 en=scsp->udata.data[0x1e/2];\n\n\tif(scsp->MidiW!=scsp->MidiR)\n\t{\n\t\tscsp->udata.data[0x20/2] |= 8;\n\t\tpend |= 8;\n\t}\n\tif(!pend)\n\t\treturn;\n\tif(pend&0x40)\n\t\tif(en&0x40)\n\t\t{\n\t\t\tscsp->Int68kCB(scsp->device, scsp->IrqTimA);\n\t\t\treturn;\n\t\t}\n\tif(pend&0x80)\n\t\tif(en&0x80)\n\t\t{\n\t\t\tscsp->Int68kCB(scsp->device, scsp->IrqTimBC);\n\t\t\treturn;\n\t\t}\n\tif(pend&0x100)\n\t\tif(en&0x100)\n\t\t{\n\t\t\tscsp->Int68kCB(scsp->device, scsp->IrqTimBC);\n\t\t\treturn;\n\t\t}\n\tif(pend&8)\n\t\tif (en&8)\n\t\t{\n\t\t\tscsp->Int68kCB(scsp->device, scsp->IrqMidi);\n\t\t\tscsp->udata.data[0x20/2] &= ~8;\n\t\t\treturn;\n\t\t}\n\n\tscsp->Int68kCB(scsp->device, 0);\n}\n\nstatic void ResetInterrupts(scsp_state *scsp)\n{\n\tUINT32 reset = scsp->udata.data[0x22/2];\n\n\tif (reset & 0x40)\n\t{\n\t\tscsp->Int68kCB(scsp->device, -scsp->IrqTimA);\n\t}\n\tif (reset & 0x180)\n\t{\n\t\tscsp->Int68kCB(scsp->device, -scsp->IrqTimBC);\n\t}\n\tif (reset & 0x8)\n\t{\n\t\tscsp->Int68kCB(scsp->device, -scsp->IrqMidi);\n\t}\n\n\tCheckPendingIRQ(scsp);\n}\n\nstatic TIMER_CALLBACK( timerA_cb )\n{\n\tscsp_state *scsp = (scsp_state *)ptr;\n\n\tscsp->TimCnt[0] = 0xFFFF;\n\tscsp->udata.data[0x20/2]|=0x40;\n\tscsp->udata.data[0x18/2]&=0xff00;\n\tscsp->udata.data[0x18/2]|=scsp->TimCnt[0]>>8;\n\n\tCheckPendingIRQ(scsp);\n}\n\nstatic TIMER_CALLBACK( timerB_cb )\n{\n\tscsp_state *scsp = (scsp_state *)ptr;\n\n\tscsp->TimCnt[1] = 0xFFFF;\n\tscsp->udata.data[0x20/2]|=0x80;\n\tscsp->udata.data[0x1a/2]&=0xff00;\n\tscsp->udata.data[0x1a/2]|=scsp->TimCnt[1]>>8;\n\n\tCheckPendingIRQ(scsp);\n}\n\nstatic TIMER_CALLBACK( timerC_cb )\n{\n\tscsp_state *scsp = (scsp_state *)ptr;\n\n\tscsp->TimCnt[2] = 0xFFFF;\n\tscsp->udata.data[0x20/2]|=0x100;\n\tscsp->udata.data[0x1c/2]&=0xff00;\n\tscsp->udata.data[0x1c/2]|=scsp->TimCnt[2]>>8;\n\n\tCheckPendingIRQ(scsp);\n}*/\n\nstatic int Get_AR(scsp_state *scsp,int base,int R)\n{\n\tint Rate=base+(R<<1);\n\tif(Rate>63)\tRate=63;\n\tif(Rate<0) Rate=0;\n\treturn scsp->ARTABLE[Rate];\n}\n\nstatic int Get_DR(scsp_state *scsp,int base,int R)\n{\n\tint Rate=base+(R<<1);\n\tif(Rate>63)\tRate=63;\n\tif(Rate<0) Rate=0;\n\treturn scsp->DRTABLE[Rate];\n}\n\nstatic int Get_RR(scsp_state *scsp,int base,int R)\n{\n\tint Rate=base+(R<<1);\n\tif(Rate>63)\tRate=63;\n\tif(Rate<0) Rate=0;\n\treturn scsp->DRTABLE[Rate];\n}\n\nstatic void Compute_EG(scsp_state *scsp,struct _SLOT *slot)\n{\n\tint octave=(OCT(slot)^8)-8;\n\tint rate;\n\tif(KRS(slot)!=0xf)\n\t\trate=octave+2*KRS(slot)+((FNS(slot)>>9)&1);\n\telse\n\t\trate=0; //rate=((FNS(slot)>>9)&1);\n\n\tslot->EG.volume=0x17F<<EG_SHIFT;\n\tslot->EG.AR=Get_AR(scsp,rate,AR(slot));\n\tslot->EG.D1R=Get_DR(scsp,rate,D1R(slot));\n\tslot->EG.D2R=Get_DR(scsp,rate,D2R(slot));\n\tslot->EG.RR=Get_RR(scsp,rate,RR(slot));\n\tslot->EG.DL=0x1f-DL(slot);\n\tslot->EG.EGHOLD=EGHOLD(slot);\n}\n\nstatic void SCSP_StopSlot(struct _SLOT *slot,int keyoff);\n\nstatic int EG_Update(struct _SLOT *slot)\n{\n\tswitch(slot->EG.state)\n\t{\n\t\tcase ATTACK:\n\t\t\tslot->EG.volume+=slot->EG.AR;\n\t\t\tif(slot->EG.volume>=(0x3ff<<EG_SHIFT))\n\t\t\t{\n\t\t\t\tif (!LPSLNK(slot))\n\t\t\t\t{\n\t\t\t\t\tslot->EG.state=DECAY1;\n\t\t\t\t\tif(slot->EG.D1R>=(1024<<EG_SHIFT)) //Skip DECAY1, go directly to DECAY2\n\t\t\t\t\t\tslot->EG.state=DECAY2;\n\t\t\t\t}\n\t\t\t\tslot->EG.volume=0x3ff<<EG_SHIFT;\n\t\t\t}\n\t\t\tif(slot->EG.EGHOLD)\n\t\t\t\treturn 0x3ff<<(SHIFT-10);\n\t\t\tbreak;\n\t\tcase DECAY1:\n\t\t\tslot->EG.volume-=slot->EG.D1R;\n\t\t\tif(slot->EG.volume<=0)\n\t\t\t\tslot->EG.volume=0;\n\t\t\tif(slot->EG.volume>>(EG_SHIFT+5)<=slot->EG.DL)\n\t\t\t\tslot->EG.state=DECAY2;\n\t\t\tbreak;\n\t\tcase DECAY2:\n\t\t\tif(D2R(slot)==0)\n\t\t\t\treturn (slot->EG.volume>>EG_SHIFT)<<(SHIFT-10);\n\t\t\tslot->EG.volume-=slot->EG.D2R;\n\t\t\tif(slot->EG.volume<=0)\n\t\t\t\tslot->EG.volume=0;\n\n\t\t\tbreak;\n\t\tcase RELEASE:\n\t\t\tslot->EG.volume-=slot->EG.RR;\n\t\t\tif(slot->EG.volume<=0)\n\t\t\t{\n\t\t\t\tslot->EG.volume=0;\n\t\t\t\tSCSP_StopSlot(slot,0);\n\t\t\t\t//slot->EG.volume=0x17F<<EG_SHIFT;\n\t\t\t\t//slot->EG.state=ATTACK;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn 1<<SHIFT;\n\t}\n\treturn (slot->EG.volume>>EG_SHIFT)<<(SHIFT-10);\n}\n\nstatic UINT32 SCSP_Step(struct _SLOT *slot)\n{\n\tint octave=(OCT(slot)^8)-8+SHIFT-10;\n\tUINT32 Fn=FNS(slot)+(1 << 10);\n\tif (octave >= 0)\n\t{\n\t\tFn<<=octave;\n\t}\n\telse\n\t{\n\t\tFn>>=-octave;\n\t}\n\n\treturn Fn;\n}\n\n\nstatic void Compute_LFO(struct _SLOT *slot)\n{\n\tif(PLFOS(slot)!=0)\n\t\tLFO_ComputeStep(&(slot->PLFO),LFOF(slot),PLFOWS(slot),PLFOS(slot),0);\n\tif(ALFOS(slot)!=0)\n\t\tLFO_ComputeStep(&(slot->ALFO),LFOF(slot),ALFOWS(slot),ALFOS(slot),1);\n}\n\nstatic void SCSP_StartSlot(scsp_state *scsp, struct _SLOT *slot)\n{\n\tUINT32 start_offset;\n\n\tslot->active=1;\n\tstart_offset = PCM8B(slot) ? SA(slot) : SA(slot) & 0x7FFFE;\n\tslot->base=scsp->SCSPRAM + start_offset;\n\tslot->cur_addr=0;\n\tslot->nxt_addr=1<<SHIFT;\n\tslot->step=SCSP_Step(slot);\n\tCompute_EG(scsp,slot);\n\tslot->EG.state=ATTACK;\n\tslot->EG.volume=0x17F<<EG_SHIFT;\n\tslot->Prev=0;\n\tslot->Backwards=0;\n\n\tCompute_LFO(slot);\n\n//  printf(\"StartSlot[%p]: SA %x PCM8B %x LPCTL %x ALFOS %x STWINH %x TL %x EFSDL %x\\n\", slot, SA(slot), PCM8B(slot), LPCTL(slot), ALFOS(slot), STWINH(slot), TL(slot), EFSDL(slot));\n}\n\nstatic void SCSP_StopSlot(struct _SLOT *slot,int keyoff)\n{\n\tif(keyoff /*&& slot->EG.state!=RELEASE*/)\n\t{\n\t\tslot->EG.state=RELEASE;\n\t}\n\telse\n\t{\n\t\tslot->active=0;\n\t}\n\tslot->udata.data[0]&=~0x800;\n}\n\n#define log_base_2(n) (log((double)(n))/log(2.0))\n\n//static void SCSP_Init(device_t *device, scsp_state *scsp, const scsp_interface *intf)\nstatic void SCSP_Init(scsp_state *scsp, int clock)\n{\n\tint i;\n\n\tmemset(scsp,0,sizeof(*scsp));\n\n\tSCSPDSP_Init(&scsp->DSP);\n\n\t//scsp->device = device;\n\tscsp->clock = clock;\n\tscsp->rate = clock / 512;\n\t\n\t//scsp->IrqTimA = scsp->IrqTimBC = scsp->IrqMidi = 0;\n\tscsp->MidiR=scsp->MidiW=0;\n\tscsp->MidiOutR=scsp->MidiOutW=0;\n\n\t// get SCSP RAM\n\t/*if (strcmp(device->tag(), \"scsp\") == 0 || strcmp(device->tag(), \"scsp1\") == 0)\n\t{\n\t\tscsp->Master=1;\n\t}\n\telse\n\t{\n\t\tscsp->Master=0;\n\t}*/\n\n\t/*scsp->SCSPRAM = *device->region();\n\tif (scsp->SCSPRAM)\n\t{\n\t\tscsp->SCSPRAM_LENGTH = device->region()->bytes();\n\t\tscsp->DSP.SCSPRAM = (UINT16 *)scsp->SCSPRAM;\n\t\tscsp->DSP.SCSPRAM_LENGTH = scsp->SCSPRAM_LENGTH/2;\n\t\tscsp->SCSPRAM += intf->roffset;\n\t}*/\n\tscsp->SCSPRAM_LENGTH = 0x80000;\t// 512 KB\n\tscsp->SCSPRAM = (unsigned char*)malloc(scsp->SCSPRAM_LENGTH);\n\tscsp->DSP.SCSPRAM_LENGTH = scsp->SCSPRAM_LENGTH / 2;\n\tscsp->DSP.SCSPRAM = (UINT16*)scsp->SCSPRAM;\n\n\t/*scsp->timerA = device->machine().scheduler().timer_alloc(FUNC(timerA_cb), scsp);\n\tscsp->timerB = device->machine().scheduler().timer_alloc(FUNC(timerB_cb), scsp);\n\tscsp->timerC = device->machine().scheduler().timer_alloc(FUNC(timerC_cb), scsp);*/\n\n\tfor(i=0;i<0x400;++i)\n\t{\n\t\tfloat envDB=((float)(3*(i-0x3ff)))/32.0f;\n\t\tfloat scale=(float)(1<<SHIFT);\n\t\tscsp->EG_TABLE[i]=(INT32)(pow(10.0,envDB/20.0)*scale);\n\t}\n\n\tfor(i=0;i<0x10000;++i)\n\t{\n\t\tint iTL =(i>>0x0)&0xff;\n\t\tint iPAN=(i>>0x8)&0x1f;\n\t\tint iSDL=(i>>0xD)&0x07;\n\t\tfloat TL=1.0f;\n\t\tfloat SegaDB=0.0f;\n\t\tfloat fSDL=1.0f;\n\t\tfloat PAN=1.0f;\n\t\tfloat LPAN,RPAN;\n\n\t\tif(iTL&0x01) SegaDB-=0.4f;\n\t\tif(iTL&0x02) SegaDB-=0.8f;\n\t\tif(iTL&0x04) SegaDB-=1.5f;\n\t\tif(iTL&0x08) SegaDB-=3.0f;\n\t\tif(iTL&0x10) SegaDB-=6.0f;\n\t\tif(iTL&0x20) SegaDB-=12.0f;\n\t\tif(iTL&0x40) SegaDB-=24.0f;\n\t\tif(iTL&0x80) SegaDB-=48.0f;\n\n\t\tTL=pow(10.0,SegaDB/20.0);\n\n\t\tSegaDB=0;\n\t\tif(iPAN&0x1) SegaDB-=3.0f;\n\t\tif(iPAN&0x2) SegaDB-=6.0f;\n\t\tif(iPAN&0x4) SegaDB-=12.0f;\n\t\tif(iPAN&0x8) SegaDB-=24.0f;\n\n\t\tif((iPAN&0xf)==0xf) PAN=0.0;\n\t\telse PAN=pow(10.0,SegaDB/20.0);\n\n\t\tif(iPAN<0x10)\n\t\t{\n\t\t\tLPAN=PAN;\n\t\t\tRPAN=1.0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tRPAN=PAN;\n\t\t\tLPAN=1.0;\n\t\t}\n\n\t\tif(iSDL)\n\t\t\tfSDL=pow(10.0,(SDLT[iSDL])/20.0);\n\t\telse\n\t\t\tfSDL=0.0;\n\n\t\tscsp->LPANTABLE[i]=FIX((4.0*LPAN*TL*fSDL));\n\t\tscsp->RPANTABLE[i]=FIX((4.0*RPAN*TL*fSDL));\n\t}\n\n\tscsp->ARTABLE[0]=scsp->DRTABLE[0]=0;\t//Infinite time\n\tscsp->ARTABLE[1]=scsp->DRTABLE[1]=0;\t//Infinite time\n\tfor(i=2;i<64;++i)\n\t{\n\t\tdouble t,step,scale;\n\t\tt=ARTimes[i];\t//In ms\n\t\tif(t!=0.0)\n\t\t{\n\t\t\tstep=(1023*1000.0)/((float) 44100.0f*t);\n\t\t\tscale=(double) (1<<EG_SHIFT);\n\t\t\tscsp->ARTABLE[i]=(int) (step*scale);\n\t\t}\n\t\telse\n\t\t\tscsp->ARTABLE[i]=1024<<EG_SHIFT;\n\n\t\tt=DRTimes[i];\t//In ms\n\t\tstep=(1023*1000.0)/((float) 44100.0f*t);\n\t\tscale=(double) (1<<EG_SHIFT);\n\t\tscsp->DRTABLE[i]=(int) (step*scale);\n\t}\n\n\t// make sure all the slots are off\n\tfor(i=0;i<32;++i)\n\t{\n\t\tscsp->Slots[i].slot=i;\n\t\tscsp->Slots[i].active=0;\n\t\tscsp->Slots[i].base=NULL;\n\t\tscsp->Slots[i].EG.state=RELEASE;\n\t}\n\n\t//LFO_Init(device->machine());\n\tLFO_Init();\n\t//scsp->buffertmpl=auto_alloc_array_clear(device->machine(), signed int, 44100);\n\t//scsp->buffertmpr=auto_alloc_array_clear(device->machine(), signed int, 44100);\n\n\t// no \"pend\"\n\tscsp->udata.data[0x20/2] = 0;\n\tscsp->TimCnt[0] = 0xffff;\n\tscsp->TimCnt[1] = 0xffff;\n\tscsp->TimCnt[2] = 0xffff;\n}\n\nINLINE void SCSP_UpdateSlotReg(scsp_state *scsp,int s,int r)\n{\n\tstruct _SLOT *slot=scsp->Slots+s;\n\tint sl;\n\tswitch(r&0x3f)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\t\tif(KEYONEX(slot))\n\t\t\t{\n\t\t\t\tfor(sl=0;sl<32;++sl)\n\t\t\t\t{\n\t\t\t\t\tstruct _SLOT *s2=scsp->Slots+sl;\n\t\t\t\t\t{\n\t\t\t\t\t\tif(KEYONB(s2) && s2->EG.state==RELEASE/*&& !s2->active*/)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tSCSP_StartSlot(scsp, s2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(!KEYONB(s2) /*&& s2->active*/)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tSCSP_StopSlot(s2,1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tslot->udata.data[0]&=~0x1000;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 0x10:\n\t\tcase 0x11:\n\t\t\tslot->step=SCSP_Step(slot);\n\t\t\tbreak;\n\t\tcase 0xA:\n\t\tcase 0xB:\n\t\t\tslot->EG.RR=Get_RR(scsp,0,RR(slot));\n\t\t\tslot->EG.DL=0x1f-DL(slot);\n\t\t\tbreak;\n\t\tcase 0x12:\n\t\tcase 0x13:\n\t\t\tCompute_LFO(slot);\n\t\t\tbreak;\n\t}\n}\n\nINLINE void SCSP_UpdateReg(scsp_state *scsp, /*address_space &space,*/ int reg)\n{\n\tswitch(reg&0x3f)\n\t{\n\t\tcase 0x0:\n\t\t\t// TODO: Make this work in VGMPlay\n\t\t\t//scsp->stream->set_output_gain(0,MVOL(scsp) / 15.0);\n\t\t\t//scsp->stream->set_output_gain(1,MVOL(scsp) / 15.0);\n\t\t\tbreak;\n\t\tcase 0x2:\n\t\tcase 0x3:\n\t\t\t{\n\t\t\t\tunsigned int v=RBL(scsp);\n\t\t\t\tscsp->DSP.RBP=RBP(scsp);\n\t\t\t\tif(v==0)\n\t\t\t\t\tscsp->DSP.RBL=8*1024;\n\t\t\t\telse if(v==1)\n\t\t\t\t\tscsp->DSP.RBL=16*1024;\n\t\t\t\telse if(v==2)\n\t\t\t\t\tscsp->DSP.RBL=32*1024;\n\t\t\t\telse if(v==3)\n\t\t\t\t\tscsp->DSP.RBL=64*1024;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 0x6:\n\t\tcase 0x7:\n\t\t\t//scsp_midi_in(space->machine().device(\"scsp\"), 0, scsp->udata.data[0x6/2]&0xff, 0);\n\t\t\tbreak;\n\t\tcase 8:\n\t\tcase 9:\n\t\t\t/* Only MSLC could be written. */\n\t\t\tscsp->udata.data[0x8/2] &= 0x7800;\n\t\t\tbreak;\n\t\tcase 0x12:\n\t\tcase 0x13:\n\t\t\t//scsp->dma.dmea = (scsp->udata.data[0x12/2] & 0xfffe) | (scsp->dma.dmea & 0xf0000);\n\t\t\tbreak;\n\t\tcase 0x14:\n\t\tcase 0x15:\n\t\t\t//scsp->dma.dmea = ((scsp->udata.data[0x14/2] & 0xf000) << 4) | (scsp->dma.dmea & 0xfffe);\n\t\t\t//scsp->dma.drga = (scsp->udata.data[0x14/2] & 0x0ffe);\n\t\t\tbreak;\n\t\tcase 0x16:\n\t\tcase 0x17:\n\t\t\t//scsp->dma.dtlg = (scsp->udata.data[0x16/2] & 0x0ffe);\n\t\t\t//scsp->dma.ddir = (scsp->udata.data[0x16/2] & 0x2000) >> 13;\n\t\t\t//scsp->dma.dgate = (scsp->udata.data[0x16/2] & 0x4000) >> 14;\n\t\t\t//if(scsp->udata.data[0x16/2] & 0x1000) // dexe\n\t\t\t//\tSCSP_exec_dma(space, scsp);\n\t\t\tbreak;\n\t\tcase 0x18:\n\t\tcase 0x19:\n\t\t\t/*if(scsp->Master)\n\t\t\t{\n\t\t\t\tUINT32 time;\n\n\t\t\t\tscsp->TimPris[0]=1<<((scsp->udata.data[0x18/2]>>8)&0x7);\n\t\t\t\tscsp->TimCnt[0]=(scsp->udata.data[0x18/2]&0xff)<<8;\n\n\t\t\t\tif ((scsp->udata.data[0x18/2]&0xff) != 255)\n\t\t\t\t{\n\t\t\t\t\ttime = (44100 / scsp->TimPris[0]) / (255-(scsp->udata.data[0x18/2]&0xff));\n\t\t\t\t\tif (time)\n\t\t\t\t\t{\n\t\t\t\t\t\tscsp->timerA->adjust(attotime::from_hz(time));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}*/\n\t\t\tbreak;\n\t\tcase 0x1a:\n\t\tcase 0x1b:\n\t\t\t/*if(scsp->Master)\n\t\t\t{\n\t\t\t\tUINT32 time;\n\n\t\t\t\tscsp->TimPris[1]=1<<((scsp->udata.data[0x1A/2]>>8)&0x7);\n\t\t\t\tscsp->TimCnt[1]=(scsp->udata.data[0x1A/2]&0xff)<<8;\n\n\t\t\t\tif ((scsp->udata.data[0x1A/2]&0xff) != 255)\n\t\t\t\t{\n\t\t\t\t\ttime = (44100 / scsp->TimPris[1]) / (255-(scsp->udata.data[0x1A/2]&0xff));\n\t\t\t\t\tif (time)\n\t\t\t\t\t{\n\t\t\t\t\t\tscsp->timerB->adjust(attotime::from_hz(time));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}*/\n\t\t\tbreak;\n\t\tcase 0x1C:\n\t\tcase 0x1D:\n\t\t\t/*if(scsp->Master)\n\t\t\t{\n\t\t\t\tUINT32 time;\n\n\t\t\t\tscsp->TimPris[2]=1<<((scsp->udata.data[0x1C/2]>>8)&0x7);\n\t\t\t\tscsp->TimCnt[2]=(scsp->udata.data[0x1C/2]&0xff)<<8;\n\n\t\t\t\tif ((scsp->udata.data[0x1C/2]&0xff) != 255)\n\t\t\t\t{\n\t\t\t\t\ttime = (44100 / scsp->TimPris[2]) / (255-(scsp->udata.data[0x1C/2]&0xff));\n\t\t\t\t\tif (time)\n\t\t\t\t\t{\n\t\t\t\t\t\tscsp->timerC->adjust(attotime::from_hz(time));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}*/\n\t\t\tbreak;\n\t\tcase 0x1e: // SCIEB\n\t\tcase 0x1f:\n\t\t\t/*if(scsp->Master)\n\t\t\t{\n\t\t\t\tCheckPendingIRQ(scsp);\n\n\t\t\t\tif(scsp->udata.data[0x1e/2] & 0x610)\n\t\t\t\t\tpopmessage(\"SCSP SCIEB enabled %04x, contact MAMEdev\",scsp->udata.data[0x1e/2]);\n\t\t\t}*/\n\t\t\tbreak;\n\t\tcase 0x20: // SCIPD\n\t\tcase 0x21:\n\t\t\t/*if(scsp->Master)\n\t\t\t{\n\t\t\t\tif(scsp->udata.data[0x1e/2] & scsp->udata.data[0x20/2] & 0x20)\n\t\t\t\t\tpopmessage(\"SCSP SCIPD write %04x, contact MAMEdev\",scsp->udata.data[0x20/2]);\n\t\t\t}*/\n\t\t\tbreak;\n\t\tcase 0x22:\t//SCIRE\n\t\tcase 0x23:\n\n\t\t\t/*if(scsp->Master)\n\t\t\t{\n\t\t\t\tscsp->udata.data[0x20/2]&=~scsp->udata.data[0x22/2];\n\t\t\t\tResetInterrupts(scsp);\n\n\t\t\t\t// behavior from real hardware: if you SCIRE a timer that's expired,\n\t\t\t\t// it'll immediately pop up again in SCIPD.  ask Sakura Taisen on the Saturn...\n\t\t\t\tif (scsp->TimCnt[0] == 0xffff)\n\t\t\t\t{\n\t\t\t\t\tscsp->udata.data[0x20/2] |= 0x40;\n\t\t\t\t}\n\t\t\t\tif (scsp->TimCnt[1] == 0xffff)\n\t\t\t\t{\n\t\t\t\t\tscsp->udata.data[0x20/2] |= 0x80;\n\t\t\t\t}\n\t\t\t\tif (scsp->TimCnt[2] == 0xffff)\n\t\t\t\t{\n\t\t\t\t\tscsp->udata.data[0x20/2] |= 0x100;\n\t\t\t\t}\n\t\t\t}*/\n\t\t\tbreak;\n\t\tcase 0x24:\n\t\tcase 0x25:\n\t\tcase 0x26:\n\t\tcase 0x27:\n\t\tcase 0x28:\n\t\tcase 0x29:\n\t\t\t/*if(scsp->Master)\n\t\t\t{\n\t\t\t\tscsp->IrqTimA=DecodeSCI(scsp,SCITMA);\n\t\t\t\tscsp->IrqTimBC=DecodeSCI(scsp,SCITMB);\n\t\t\t\tscsp->IrqMidi=DecodeSCI(scsp,SCIMID);\n\t\t\t}*/\n\t\t\tbreak;\n\t\tcase 0x2a:\n\t\tcase 0x2b:\n\t\t\tscsp->mcieb = scsp->udata.data[0x2a/2];\n\n\t\t\t/*MainCheckPendingIRQ(scsp, 0);\n\t\t\tif(scsp->mcieb & ~0x60)\n\t\t\t\tpopmessage(\"SCSP MCIEB enabled %04x, contact MAMEdev\",scsp->mcieb);*/\n\t\t\tbreak;\n\t\tcase 0x2c:\n\t\tcase 0x2d:\n\t\t\t//if(scsp->udata.data[0x2c/2] & 0x20)\n\t\t\t//\tMainCheckPendingIRQ(scsp, 0x20);\n\t\t\tbreak;\n\t\tcase 0x2e:\n\t\tcase 0x2f:\n\t\t\tscsp->mcipd &= ~scsp->udata.data[0x2e/2];\n\t\t\t//MainCheckPendingIRQ(scsp, 0);\n\t\t\tbreak;\n\n\t}\n}\n\nstatic void SCSP_UpdateSlotRegR(scsp_state *scsp, int slot,int reg)\n{\n\n}\n\nstatic void SCSP_UpdateRegR(scsp_state *scsp, int reg)\n{\n\tswitch(reg&0x3f)\n\t{\n\t\tcase 4:\n\t\tcase 5:\n\t\t\t{\n\t\t\t\tunsigned short v=scsp->udata.data[0x5/2];\n\t\t\t\tv&=0xff00;\n\t\t\t\tv|=scsp->MidiStack[scsp->MidiR];\n\t\t\t\t/*scsp->Int68kCB(scsp->device, -scsp->IrqMidi);\t// cancel the IRQ\n\t\t\t\tlogerror(\"Read %x from SCSP MIDI\\n\", v);*/\n\t\t\t\tif(scsp->MidiR!=scsp->MidiW)\n\t\t\t\t{\n\t\t\t\t\t++scsp->MidiR;\n\t\t\t\t\tscsp->MidiR&=31;\n\t\t\t\t}\n\t\t\t\tscsp->udata.data[0x5/2]=v;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 8:\n\t\tcase 9:\n\t\t\t{\n\t\t\t\t// MSLC     |  CA   |SGC|EG\n\t\t\t\t// f e d c b a 9 8 7 6 5 4 3 2 1 0\n\t\t\t\tunsigned char MSLC=(scsp->udata.data[0x8/2]>>11)&0x1f;\n\t\t\t\tstruct _SLOT *slot=scsp->Slots + MSLC;\n\t\t\t\tunsigned int SGC = (slot->EG.state) & 3;\n\t\t\t\tunsigned int CA = (slot->cur_addr>>(SHIFT+12)) & 0xf;\n\t\t\t\tunsigned int EG = (0x1f - (slot->EG.volume>>(EG_SHIFT+5))) & 0x1f;\n\t\t\t\t/* note: according to the manual MSLC is write only, CA, SGC and EG read only.  */\n\t\t\t\tscsp->udata.data[0x8/2] =  /*(MSLC << 11) |*/ (CA << 7) | (SGC << 5) | EG;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0x18:\n\t\tcase 0x19:\n\t\t\tbreak;\n\n\t\tcase 0x1a:\n\t\tcase 0x1b:\n\t\t\tbreak;\n\n\t\tcase 0x1c:\n\t\tcase 0x1d:\n\t\t\tbreak;\n\n\t\tcase 0x2a:\n\t\tcase 0x2b:\n\t\t\tscsp->udata.data[0x2a/2] = scsp->mcieb;\n\t\t\tbreak;\n\n\t\tcase 0x2c:\n\t\tcase 0x2d:\n\t\t\tscsp->udata.data[0x2c/2] = scsp->mcipd;\n\t\t\tbreak;\n\t}\n}\n\nINLINE void SCSP_w16(scsp_state *scsp,unsigned int addr,unsigned short val)\n{\n\taddr&=0xffff;\n\tif(addr<0x400)\n\t{\n\t\tint slot=addr/0x20;\n\t\taddr&=0x1f;\n\t\t*((unsigned short *) (scsp->Slots[slot].udata.datab+(addr))) = val;\n\t\tSCSP_UpdateSlotReg(scsp,slot,addr&0x1f);\n\t}\n\telse if(addr<0x600)\n\t{\n\t\tif (addr < 0x430)\n\t\t{\n\t\t\t*((unsigned short *) (scsp->udata.datab+((addr&0x3f)))) = val;\n\t\t\tSCSP_UpdateReg(scsp, addr&0x3f);\n\t\t}\n\t}\n\telse if(addr<0x700)\n\t\tscsp->RINGBUF[(addr-0x600)/2]=val;\n\telse\n\t{\n\t\t//DSP\n\t\tif(addr<0x780)\t//COEF\n\t\t\t*((unsigned short *) (scsp->DSP.COEF+(addr-0x700)/2))=val;\n\t\telse if(addr<0x7c0)\n\t\t\t*((unsigned short *) (scsp->DSP.MADRS+(addr-0x780)/2))=val;\n\t\telse if(addr<0x800)\t// MADRS is mirrored twice\n\t\t\t*((unsigned short *) (scsp->DSP.MADRS+(addr-0x7c0)/2))=val;\n\t\telse if(addr<0xC00)\n\t\t{\n\t\t\t*((unsigned short *) (scsp->DSP.MPRO+(addr-0x800)/2))=val;\n\n\t\t\tif(addr==0xBF0)\n\t\t\t{\n\t\t\t\tSCSPDSP_Start(&scsp->DSP);\n\t\t\t}\n\t\t}\n\t}\n}\n\nINLINE unsigned short SCSP_r16(scsp_state *scsp, unsigned int addr)\n{\n\tunsigned short v=0;\n\taddr&=0xffff;\n\tif(addr<0x400)\n\t{\n\t\tint slot=addr/0x20;\n\t\taddr&=0x1f;\n\t\tSCSP_UpdateSlotRegR(scsp, slot,addr&0x1f);\n\t\tv=*((unsigned short *) (scsp->Slots[slot].udata.datab+(addr)));\n\t}\n\telse if(addr<0x600)\n\t{\n\t\tif (addr < 0x430)\n\t\t{\n\t\t\tSCSP_UpdateRegR(scsp, addr&0x3f);\n\t\t\tv= *((unsigned short *) (scsp->udata.datab+((addr&0x3f))));\n\t\t}\n\t}\n\telse if(addr<0x700)\n\t\tv=scsp->RINGBUF[(addr-0x600)/2];\n#if 1\t// disabled by default until I get the DSP to work correctly\n\t\t// can be enabled using separate option\n\telse\n\t{\n\t\t//DSP\n\t\tif(addr<0x780)  //COEF\n\t\t\tv= *((unsigned short *) (scsp->DSP.COEF+(addr-0x700)/2));\n\t\telse if(addr<0x7c0)\n\t\t\tv= *((unsigned short *) (scsp->DSP.MADRS+(addr-0x780)/2));\n\t\telse if(addr<0x800)\n\t\t\tv= *((unsigned short *) (scsp->DSP.MADRS+(addr-0x7c0)/2));\n\t\telse if(addr<0xC00)\n\t\t\tv= *((unsigned short *) (scsp->DSP.MPRO+(addr-0x800)/2));\n\t\telse if(addr<0xE00)\n\t\t{\n\t\t\tif(addr & 2)\n\t\t\t\tv= scsp->DSP.TEMP[(addr >> 2) & 0x7f] & 0xffff;\n\t\t\telse\n\t\t\t\tv= scsp->DSP.TEMP[(addr >> 2) & 0x7f] >> 16;\n\t\t}\n\t\telse if(addr<0xE80)\n\t\t{\n\t\t\tif(addr & 2)\n\t\t\t\tv= scsp->DSP.MEMS[(addr >> 2) & 0x1f] & 0xffff;\n\t\t\telse\n\t\t\t\tv= scsp->DSP.MEMS[(addr >> 2) & 0x1f] >> 16;\n\t\t}\n\t\telse if(addr<0xEC0)\n\t\t{\n\t\t\tif(addr & 2)\n\t\t\t\tv= scsp->DSP.MIXS[(addr >> 2) & 0xf] & 0xffff;\n\t\t\telse\n\t\t\t\tv= scsp->DSP.MIXS[(addr >> 2) & 0xf] >> 16;\n\t\t}\n\t\telse if(addr<0xEE0)\n\t\t\tv= *((unsigned short *) (scsp->DSP.EFREG+(addr-0xec0)/2));\n\t\telse\n\t\t{\n\t\t\t/*\n\t\t\tKyuutenkai reads from 0xee0/0xee2, it's tied with EXTS register(s) also used for CD-Rom Player equalizer.\n\t\t\tThis port is actually an external parallel port, directly connected from the CD Block device, hence code is a bit of an hack.\n\t\t\t*/\n\t\t\tlogerror(\"SCSP: Reading from EXTS register %08x\\n\",addr);\n\t\t\t//if(addr == 0xee0)\n\t\t\t//\tv = space.machine().device<cdda_device>(\"cdda\")->get_channel_volume(0);\n\t\t\t//if(addr == 0xee2)\n\t\t\t//\tv = space.machine().device<cdda_device>(\"cdda\")->get_channel_volume(1);\n\t\t\tv = 0xFFFF;\n\t\t}\n\t}\n#endif\n\treturn v;\n}\n\n\n#define REVSIGN(v) ((~v)+1)\n\nINLINE INT32 SCSP_UpdateSlot(scsp_state *scsp, struct _SLOT *slot)\n{\n\tINT32 sample;\n\tint step=slot->step;\n\tUINT32 addr1,addr2,addr_select;                                   // current and next sample addresses\n\tUINT32 *addr[2]      = {&addr1, &addr2};                          // used for linear interpolation\n\tUINT32 *slot_addr[2] = {&(slot->cur_addr), &(slot->nxt_addr)};    //\n\n\tif(SSCTL(slot)!=0)\t//no FM or noise yet\n\t\treturn 0;\n\n\tif(PLFOS(slot)!=0)\n\t{\n\t\tstep=step*PLFO_Step(&(slot->PLFO));\n\t\tstep>>=SHIFT;\n\t}\n\n\tif(PCM8B(slot))\n\t{\n\t\taddr1=slot->cur_addr>>SHIFT;\n\t\taddr2=slot->nxt_addr>>SHIFT;\n\t}\n\telse\n\t{\n\t\taddr1=(slot->cur_addr>>(SHIFT-1))&0x7fffe;\n\t\taddr2=(slot->nxt_addr>>(SHIFT-1))&0x7fffe;\n\t}\n\n\tif(MDL(slot)!=0 || MDXSL(slot)!=0 || MDYSL(slot)!=0)\n\t{\n\t\tINT32 smp=(scsp->RINGBUF[(scsp->BUFPTR+MDXSL(slot))&63]+scsp->RINGBUF[(scsp->BUFPTR+MDYSL(slot))&63])/2;\n\n\t\tsmp<<=0xA; // associate cycle with 1024\n\t\tsmp>>=0x1A-MDL(slot); // ex. for MDL=0xF, sample range corresponds to +/- 64 pi (32=2^5 cycles) so shift by 11 (16-5 == 0x1A-0xF)\n\t\tif(!PCM8B(slot)) smp<<=1;\n\n\t\taddr1+=smp; addr2+=smp;\n\t}\n\n#if 0\t// --- old code ---\n\t// Since the SCSP is for Big Endian platforms (and this is optimized for Little Endian),\n\t// this code expects the data in byte order 1 0 3 2 5 4 ....\n\tif(PCM8B(slot))\t//8 bit signed\n\t{\n\t\tINT8 *p1=(signed char *) (scsp->SCSPRAM+BYTE_XOR_BE(((SA(slot)+addr1))&0x7FFFF));\n\t\tINT8 *p2=(signed char *) (scsp->SCSPRAM+BYTE_XOR_BE(((SA(slot)+addr2))&0x7FFFF));\n\t\t//sample=(p[0])<<8;\n\t\tINT32 s;\n\t\tINT32 fpart=slot->cur_addr&((1<<SHIFT)-1);\n\t\ts=(int) (p1[0]<<8)*((1<<SHIFT)-fpart)+(int)(p2[0]<<8)*fpart;\n\t\tsample=(s>>SHIFT);\n\t}\n\telse\t//16 bit signed (endianness?)\n\t{\n#ifdef VGM_BIG_ENDIAN\n\t#warning \"SCSP sound emulation uses Endian-unsafe 16-Bit reads!\"\n#endif\n\t\tINT16 *p1=(signed short *) (scsp->SCSPRAM+((SA(slot)+addr1)&0x7FFFE));\n\t\tINT16 *p2=(signed short *) (scsp->SCSPRAM+((SA(slot)+addr2)&0x7FFFE));\n\t\tINT32 s;\n\t\tINT32 fpart=slot->cur_addr&((1<<SHIFT)-1);\n\t\ts=(int)(p1[0])*((1<<SHIFT)-fpart)+(int)(p2)*fpart;\n\t\tsample=(s>>SHIFT);\n\t}\n#else\t// --- new code ---\n#ifdef VGM_BIG_ENDIAN\n#define READ_BE16(ptr)\t(*(INT16*)ptr)\n#else\n#define READ_BE16(ptr)\t(((ptr)[0] << 8) | (ptr)[1])\n#endif\n\t// I prefer the byte order 0 1 2 3 4 5 ...\n\t// also, I won't use pointers here, since they only used [0] on them anyway.\n\tif(PCM8B(slot))\t//8 bit signed\n\t{\n\t\tINT16 p1=(INT8)scsp->SCSPRAM[(SA(slot)+addr1)&0x7FFFF]<<8;\n\t\tINT16 p2=(INT8)scsp->SCSPRAM[(SA(slot)+addr2)&0x7FFFF]<<8;\n\t\tINT32 fpart=slot->cur_addr&((1<<SHIFT)-1);\n\t\tINT32 s=(int)p1*((1<<SHIFT)-fpart)+(int)p2*fpart;\n\t\tsample=(s>>SHIFT);\n\t}\n\telse\t//16 bit signed\n\t{\n\t\tUINT8 *pp1 = &scsp->SCSPRAM[(SA(slot)+addr1)&0x7FFFE];\n\t\tUINT8 *pp2 = &scsp->SCSPRAM[(SA(slot)+addr2)&0x7FFFE];\n\t\tINT16 p1 = (INT16)READ_BE16(pp1);\n\t\tINT16 p2 = (INT16)READ_BE16(pp2);\n\t\tINT32 fpart=slot->cur_addr&((1<<SHIFT)-1);\n\t\tINT32 s=(int)p1*((1<<SHIFT)-fpart)+(int)p2*fpart;\n\t\tsample=(s>>SHIFT);\n\t}\n#endif\n\n\tif(SBCTL(slot)&0x1)\n\t\tsample ^= 0x7FFF;\n\tif(SBCTL(slot)&0x2)\n\t\tsample = (INT16)(sample^0x8000);\n\n\tif(slot->Backwards)\n\t\tslot->cur_addr-=step;\n\telse\n\t\tslot->cur_addr+=step;\n\tslot->nxt_addr=slot->cur_addr+(1<<SHIFT);\n\n\taddr1=slot->cur_addr>>SHIFT;\n\taddr2=slot->nxt_addr>>SHIFT;\n\n\tif(addr1>=LSA(slot) && !(slot->Backwards))\n\t{\n\t\tif(LPSLNK(slot) && slot->EG.state==ATTACK)\n\t\t\tslot->EG.state = DECAY1;\n\t}\n\n\tfor (addr_select=0;addr_select<2;addr_select++)\n\t{\n\t\tINT32 rem_addr;\n\t\tswitch(LPCTL(slot))\n\t\t{\n\t\tcase 0:\t//no loop\n\t\t\tif(*addr[addr_select]>=LSA(slot) && *addr[addr_select]>=LEA(slot))\n\t\t\t{\n\t\t\t\t//slot->active=0;\n\t\t\t\tSCSP_StopSlot(slot,0);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 1: //normal loop\n\t\t\tif(*addr[addr_select]>=LEA(slot))\n\t\t\t{\n\t\t\t\trem_addr = *slot_addr[addr_select] - (LEA(slot)<<SHIFT);\n\t\t\t\t*slot_addr[addr_select]=(LSA(slot)<<SHIFT) + rem_addr;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 2:\t//reverse loop\n\t\t\tif((*addr[addr_select]>=LSA(slot)) && !(slot->Backwards))\n\t\t\t{\n\t\t\t\trem_addr = *slot_addr[addr_select] - (LSA(slot)<<SHIFT);\n\t\t\t\t*slot_addr[addr_select]=(LEA(slot)<<SHIFT) - rem_addr;\n\t\t\t\tslot->Backwards=1;\n\t\t\t}\n\t\t\telse if((*addr[addr_select]<LSA(slot) || (*slot_addr[addr_select]&0x80000000)) && slot->Backwards)\n\t\t\t{\n\t\t\t\trem_addr = (LSA(slot)<<SHIFT) - *slot_addr[addr_select];\n\t\t\t\t*slot_addr[addr_select]=(LEA(slot)<<SHIFT) - rem_addr;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 3: //ping-pong\n\t\t\tif(*addr[addr_select]>=LEA(slot)) //reached end, reverse till start\n\t\t\t{\n\t\t\t\trem_addr = *slot_addr[addr_select] - (LEA(slot)<<SHIFT);\n\t\t\t\t*slot_addr[addr_select]=(LEA(slot)<<SHIFT) - rem_addr;\n\t\t\t\tslot->Backwards=1;\n\t\t\t}\n\t\t\telse if((*addr[addr_select]<LSA(slot) || (*slot_addr[addr_select]&0x80000000)) && slot->Backwards)//reached start or negative\n\t\t\t{\n\t\t\t\trem_addr = (LSA(slot)<<SHIFT) - *slot_addr[addr_select];\n\t\t\t\t*slot_addr[addr_select]=(LSA(slot)<<SHIFT) + rem_addr;\n\t\t\t\tslot->Backwards=0;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif(!SDIR(slot))\n\t{\n\t\tif(ALFOS(slot)!=0)\n\t\t{\n\t\t\tsample=sample*ALFO_Step(&(slot->ALFO));\n\t\t\tsample>>=SHIFT;\n\t\t}\n\n\t\tif(slot->EG.state==ATTACK)\n\t\t\tsample=(sample*EG_Update(slot))>>SHIFT;\n\t\telse\n\t\t\tsample=(sample*scsp->EG_TABLE[EG_Update(slot)>>(SHIFT-10)])>>SHIFT;\n\t}\n\n\tif(!STWINH(slot))\n\t{\n\t\tif(!SDIR(slot))\n\t\t{\n\t\t\tunsigned short Enc=((TL(slot))<<0x0)|(0x7<<0xd);\n\t\t\t*RBUFDST=(sample*scsp->LPANTABLE[Enc])>>(SHIFT+1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tunsigned short Enc=(0<<0x0)|(0x7<<0xd);\n\t\t\t*RBUFDST=(sample*scsp->LPANTABLE[Enc])>>(SHIFT+1);\n\t\t}\n\t}\n\n\treturn sample;\n}\n\nINLINE void SCSP_DoMasterSamples(scsp_state *scsp, stream_sample_t **outputs, int nsamples)\n{\n\tstream_sample_t *bufr,*bufl;\n\tint sl, s, i;\n\n\t//bufr=bufferr;\n\t//bufl=bufferl;\n\tbufl = outputs[0];\n\tbufr = outputs[1];\n\n\tfor(s=0;s<nsamples;++s)\n\t{\n\t\tINT32 smpl, smpr;\n\n\t\tsmpl = smpr = 0;\n\n\t\tfor(sl=0;sl<32;++sl)\n\t\t{\n#if FM_DELAY\n\t\t\tRBUFDST=scsp->DELAYBUF+scsp->DELAYPTR;\n#else\n\t\t\tRBUFDST=scsp->RINGBUF+scsp->BUFPTR;\n#endif\n\t\t\tif(scsp->Slots[sl].active && ! scsp->Slots[sl].Muted)\n\t\t\t{\n\t\t\t\tstruct _SLOT *slot=scsp->Slots+sl;\n\t\t\t\tunsigned short Enc;\n\t\t\t\tsigned int sample;\n\n\t\t\t\tsample=SCSP_UpdateSlot(scsp, slot);\n\n\t\t\t\tif (! BypassDSP)\n\t\t\t\t{\n\t\t\t\t\tEnc=((TL(slot))<<0x0)|((IMXL(slot))<<0xd);\n\t\t\t\t\tSCSPDSP_SetSample(&scsp->DSP,(sample*scsp->LPANTABLE[Enc])>>(SHIFT-2),ISEL(slot),IMXL(slot));\n\t\t\t\t}\n\t\t\t\tEnc=((TL(slot))<<0x0)|((DIPAN(slot))<<0x8)|((DISDL(slot))<<0xd);\n\t\t\t\t{\n\t\t\t\t\tsmpl+=(sample*scsp->LPANTABLE[Enc])>>SHIFT;\n\t\t\t\t\tsmpr+=(sample*scsp->RPANTABLE[Enc])>>SHIFT;\n\t\t\t\t}\n\t\t\t}\n\n#if FM_DELAY\n\t\t\tscsp->RINGBUF[(scsp->BUFPTR+64-(FM_DELAY-1))&63] = scsp->DELAYBUF[(scsp->DELAYPTR+FM_DELAY-(FM_DELAY-1))%FM_DELAY];\n#endif\n\t\t\t++scsp->BUFPTR;\n\t\t\tscsp->BUFPTR&=63;\n#if FM_DELAY\n\t\t\t++scsp->DELAYPTR;\n\t\t\tif(scsp->DELAYPTR>FM_DELAY-1) scsp->DELAYPTR=0;\n#endif\n\t\t}\n\n\t\tif (! BypassDSP)\n\t\t{\n\t\t\tSCSPDSP_Step(&scsp->DSP);\n\n\t\t\tfor(i=0;i<16;++i)\n\t\t\t{\n\t\t\t\tstruct _SLOT *slot=scsp->Slots+i;\n\t\t\t\tif(EFSDL(slot))\n\t\t\t\t{\n\t\t\t\t\tunsigned short Enc=((EFPAN(slot))<<0x8)|((EFSDL(slot))<<0xd);\n\t\t\t\t\tsmpl+=(scsp->DSP.EFREG[i]*scsp->LPANTABLE[Enc])>>SHIFT;\n\t\t\t\t\tsmpr+=(scsp->DSP.EFREG[i]*scsp->RPANTABLE[Enc])>>SHIFT;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//*bufl++ = ICLIP16(smpl>>2);\n\t\t//*bufr++ = ICLIP16(smpr>>2);\n\t\t*bufl++ = smpl;\n\t\t*bufr++ = smpr;\n\t}\n}\n\n/* TODO: this needs to be timer-ized */\n/*static void SCSP_exec_dma(address_space *space, scsp_state *scsp)\n{\n\tstatic UINT16 tmp_dma[3];\n\tint i;\n\n\tlogerror(\"SCSP: DMA transfer START\\n\"\n\t\t\t \"DMEA: %04x DRGA: %04x DTLG: %04x\\n\"\n\t\t\t \"DGATE: %d  DDIR: %d\\n\",scsp->dma.dmea,scsp->dma.drga,scsp->dma.dtlg,scsp->dma.dgate ? 1 : 0,scsp->dma.ddir ? 1 : 0);\n\n\t// Copy the dma values in a temp storage for resuming later\n    \t// (DMA *can't* overwrite its parameters)\n\tif(!(dma.ddir))\n\t{\n\t\tfor(i=0;i<3;i++)\n\t\t\ttmp_dma[i] = scsp->udata.data[(0x12+(i*2))/2];\n\t}\n\n\t// note: we don't use space.read_word / write_word because it can happen that SH-2 enables the DMA instead of m68k.\n\t// TODO: don't know if params auto-updates, I guess not ...\n\tif(dma.ddir)\n\t{\n\t\tif(dma.dgate)\n\t\t{\n\t\t\tpopmessage(\"Check: SCSP DMA DGATE enabled, contact MAME/MESSdev\");\n\t\t\tfor(i=0;i < scsp->dma.dtlg;i+=2)\n\t\t\t{\n\t\t\t\tscsp->SCSPRAM[scsp->dma.dmea] = 0;\n\t\t\t\tscsp->SCSPRAM[scsp->dma.dmea+1] = 0;\n\t\t\t\tscsp->dma.dmea+=2;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor(i=0;i < scsp->dma.dtlg;i+=2)\n\t\t\t{\n\t\t\t\tUINT16 tmp;\n\t\t\t\ttmp = SCSP_r16(scsp, space, scsp->dma.drga);\n\t\t\t\tscsp->SCSPRAM[scsp->dma.dmea] = tmp & 0xff;\n\t\t\t\tscsp->SCSPRAM[scsp->dma.dmea+1] = tmp>>8;\n\t\t\t\tscsp->dma.dmea+=2;\n\t\t\t\tscsp->dma.drga+=2;\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tif(dma.dgate)\n\t\t{\n\t\t\tpopmessage(\"Check: SCSP DMA DGATE enabled, contact MAME/MESSdev\");\n\t\t\tfor(i=0;i < scsp->dma.dtlg;i+=2)\n\t\t\t{\n\t\t\t\tSCSP_w16(scsp, space, scsp->dma.drga, 0);\n\t\t\t\tscsp->dma.drga+=2;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor(i=0;i < scsp->dma.dtlg;i+=2)\n\t\t\t{\n\t\t\t\tUINT16 tmp;\n\t\t\t\ttmp = scsp->SCSPRAM[scsp->dma.dmea];\n\t\t\t\ttmp|= scsp->SCSPRAM[scsp->dma.dmea+1]<<8;\n\t\t\t\tSCSP_w16(scsp, space, scsp->dma.drga, tmp);\n\t\t\t\tscsp->dma.dmea+=2;\n\t\t\t\tscsp->dma.drga+=2;\n\t\t\t}\n\t\t}\n\t}\n\n\t//Resume the values\n\tif(!(dma.ddir))\n\t{\n\t\tfor(i=0;i<3;i++)\n\t\t\tscsp->udata.data[(0x12+(i*2))/2] = tmp_dma[i];\n\t}\n\n\t// Job done\n\tscsp->udata.data[0x16/2] &= ~0x1000;\n\t// request a dma end irq (TODO: make it inside the interface)\n\tif(scsp->udata.data[0x1e/2] & 0x10)\n\t{\n\t\tpopmessage(\"SCSP DMA IRQ triggered, contact MAMEdev\");\n\t\tdevice_set_input_line(space->machine().device(\"audiocpu\"),DecodeSCI(scsp,SCIDMA),HOLD_LINE);\n\t}\n}*/\n\n#ifdef UNUSED_FUNCTION\nint SCSP_IRQCB(void *param)\n{\n\tCheckPendingIRQ(param);\n\treturn -1;\n}\n#endif\n\n//static STREAM_UPDATE( SCSP_Update )\nvoid SCSP_Update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//scsp_state *scsp = (scsp_state *)param;\n\tscsp_state *scsp = &SCSPData[ChipID];\n\t//bufferl = outputs[0];\n\t//bufferr = outputs[1];\n\t//length = samples;\n\tSCSP_DoMasterSamples(scsp, outputs, samples);\n}\n\n//static DEVICE_START( scsp )\nint device_start_scsp(UINT8 ChipID, int clock)\n{\n\t/*const scsp_interface *intf;\n\n\tscsp_state *scsp = get_safe_token(device);\n\n\tintf = (const scsp_interface *)device->static_config();*/\n\tscsp_state *scsp;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tscsp = &SCSPData[ChipID];\n\n\tif (clock < 1000000)\t// if < 1 MHz, then it's the sample rate, not the clock\n\t\tclock *= 512;\t// (for backwards compatibility with old VGM logs)\n\t\n\t// init the emulation\n\t//SCSP_Init(device, scsp, intf);\n\tSCSP_Init(scsp, clock);\n\n\t// set up the IRQ callbacks\n\t/*{\n\t\tscsp->Int68kCB = intf->irq_callback;\n\n\t\tscsp->stream = device->machine().sound().stream_alloc(*device, 0, 2, 44100, scsp, SCSP_Update);\n\t}\n\n\tscsp->main_irq.resolve(intf->main_irq, *device);*/\n\treturn scsp->rate;\t// 44100\n}\n\nvoid device_stop_scsp(UINT8 ChipID)\n{\n\tscsp_state *scsp = &SCSPData[ChipID];\n\t\n\tfree(scsp->SCSPRAM);\tscsp->SCSPRAM = NULL;\n\t\n\treturn;\n}\n\nvoid device_reset_scsp(UINT8 ChipID)\n{\n\tscsp_state *scsp = &SCSPData[ChipID];\n\tint i;\n\t\n\t// make sure all the slots are off\n\tfor(i=0;i<32;++i)\n\t{\n\t\tscsp->Slots[i].slot=i;\n\t\tscsp->Slots[i].active=0;\n\t\tscsp->Slots[i].base=NULL;\n\t\tscsp->Slots[i].EG.state=RELEASE;\n\t}\n\t\n\tSCSPDSP_Init(&scsp->DSP);\n\tscsp->DSP.SCSPRAM_LENGTH = scsp->SCSPRAM_LENGTH / 2;\n\tscsp->DSP.SCSPRAM = (UINT16*)scsp->SCSPRAM;\n\t\n\treturn;\n}\n\n\n/*void scsp_set_ram_base(device_t *device, void *base)\n{\n\tscsp_state *scsp = get_safe_token(device);\n\tif (scsp)\n\t{\n\t\tscsp->SCSPRAM = (unsigned char *)base;\n\t\tscsp->DSP.SCSPRAM = (UINT16 *)base;\n\t\tscsp->SCSPRAM_LENGTH = 0x80000;\n\t\tscsp->DSP.SCSPRAM_LENGTH = 0x80000/2;\n\t}\n}*/\n\n\n//READ16_DEVICE_HANDLER( scsp_r )\nUINT16 scsp_r(UINT8 ChipID, offs_t offset)\n{\n\t//scsp_state *scsp = get_safe_token(device);\n\tscsp_state *scsp = &SCSPData[ChipID];\n\n\t//scsp->stream->update();\n\n\treturn SCSP_r16(scsp, offset*2);\n}\n\n//WRITE16_DEVICE_HANDLER( scsp_w )\nvoid scsp_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//scsp_state *scsp = get_safe_token(device);\n\tscsp_state *scsp = &SCSPData[ChipID];\n\tUINT16 tmp;\n\n\t//scsp->stream->update();\n\n\ttmp = SCSP_r16(scsp, offset & 0xFFFE);\n\t//COMBINE_DATA(&tmp);\n\tif (offset & 1)\n\t\ttmp = (tmp & 0xFF00) | (data << 0);\n\telse\n\t\ttmp = (tmp & 0x00FF) | (data << 8);\n\tSCSP_w16(scsp,offset & 0xFFFE, tmp);\n}\n\n/*WRITE16_DEVICE_HANDLER( scsp_midi_in )\n{\n\tscsp_state *scsp = get_safe_token(device);\n\n//    printf(\"scsp_midi_in: %02x\\n\", data);\n\n\tscsp->MidiStack[scsp->MidiW++]=data;\n\tscsp->MidiW &= 31;\n\n\t//CheckPendingIRQ(scsp);\n}\n\nREAD16_DEVICE_HANDLER( scsp_midi_out_r )\n{\n\tscsp_state *scsp = get_safe_token(device);\n\tunsigned char val;\n\n\tval=scsp->MidiStack[scsp->MidiR++];\n\tscsp->MidiR&=31;\n\treturn val;\n}*/\n\n\n/*void scsp_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\tconst UINT8* ROMData)\n{\n\tscsp_state *scsp = &SCSPData[ChipID];\n\t\n\tif (scsp->SCSPRAM_LENGTH != ROMSize)\n\t{\n\t\tscsp->SCSPRAM = (unsigned char*)realloc(scsp->SCSPRAM, ROMSize);\n\t\tscsp->SCSPRAM_LENGTH = ROMSize;\n\t\tscsp->DSP.SCSPRAM = (UINT16*)scsp->SCSPRAM;\n\t\tscsp->DSP.SCSPRAM_LENGTH = scsp->SCSPRAM_LENGTH / 2;\n\t\tmemset(scsp->SCSPRAM, 0x00, ROMSize);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(scsp->SCSPRAM + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}*/\n\nvoid scsp_write_ram(UINT8 ChipID, offs_t DataStart, offs_t DataLength, const UINT8* RAMData)\n{\n\tscsp_state *scsp = &SCSPData[ChipID];\n\t\n\tif (DataStart >= scsp->SCSPRAM_LENGTH)\n\t\treturn;\n\tif (DataStart + DataLength > scsp->SCSPRAM_LENGTH)\n\t\tDataLength = scsp->SCSPRAM_LENGTH - DataStart;\n\t\n\tmemcpy(scsp->SCSPRAM + DataStart, RAMData, DataLength);\n\t\n\treturn;\n}\n\n\nvoid scsp_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tscsp_state *scsp = &SCSPData[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 32; CurChn ++)\n\t\tscsp->Slots[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\nvoid scsp_set_options(UINT8 Flags)\n{\n\tBypassDSP = (Flags & 0x01) >> 0;\n\t\n\treturn;\n}\n\nUINT8 scsp_get_channels(UINT32* ChannelMask)\n{\n\tscsp_state *scsp = &SCSPData[0];\n\tUINT8 CurChn;\n\tUINT8 UsedChns;\n\tUINT32 ChnMask;\n\t\n\tChnMask = 0x00000000;\n\tUsedChns = 0x00;\n\tfor (CurChn = 0; CurChn < 32; CurChn ++)\n\t{\n\t\tif (scsp->Slots[CurChn].active)\n\t\t{\n\t\t\tChnMask |= (1 << CurChn);\n\t\t\tUsedChns ++;\n\t\t}\n\t}\n\tif (ChannelMask != NULL)\n\t\t*ChannelMask = ChnMask;\n\t\n\treturn UsedChns;\n}\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( scsp )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(scsp_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( scsp );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing //\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// Nothing //\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"SCSP\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Sega/Yamaha custom\");\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"2.1.1\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n\n\n//DEFINE_LEGACY_SOUND_DEVICE(SCSP, scsp);\n"
  },
  {
    "path": "VGMPlay/chips/scsp.h",
    "content": "/*\n    SCSP (YMF292-F) header\n*/\n\n#pragma once\n\n#ifndef __SCSP_H__\n#define __SCSP_H__\n\n//#include \"devlegcy.h\"\n\n/*typedef struct _scsp_interface scsp_interface;\nstruct _scsp_interface\n{\n\tint roffset;\t\t\t\t// offset in the region \n\tvoid (*irq_callback)(device_t *device, int state);\t// irq callback\n\tdevcb_write_line   main_irq;\n};\n\nvoid scsp_set_ram_base(device_t *device, void *base);*/\n\n\nvoid SCSP_Update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_scsp(UINT8 ChipID, int clock);\nvoid device_stop_scsp(UINT8 ChipID);\nvoid device_reset_scsp(UINT8 ChipID);\n\n// SCSP register access\n/*READ16_DEVICE_HANDLER( scsp_r );\nWRITE16_DEVICE_HANDLER( scsp_w );*/\nvoid scsp_w(UINT8 ChipID, offs_t offset, UINT8 data);\n//UINT8 scsp_r(UINT8 ChipID, offs_t offset);\n\n// MIDI I/O access (used for comms on Model 2/3)\n/*WRITE16_DEVICE_HANDLER( scsp_midi_in );\nREAD16_DEVICE_HANDLER( scsp_midi_out_r );*/\n\n//void scsp_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n//\t\t\t\t\tconst UINT8* ROMData);\nvoid scsp_write_ram(UINT8 ChipID, offs_t DataStart, offs_t DataLength, const UINT8* RAMData);\nvoid scsp_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\nvoid scsp_set_options(UINT8 Flags);\n\n/*extern UINT32* stv_scu;\n\nDECLARE_LEGACY_SOUND_DEVICE(SCSP, scsp);*/\n\n#endif /* __SCSP_H__ */\n"
  },
  {
    "path": "VGMPlay/chips/scspdsp.c",
    "content": "//#include \"emu.h\"\n#include <string.h>\t// for memset\n#include \"mamedef.h\"\n#include \"scsp.h\"\n#include \"scspdsp.h\"\n\nstatic UINT16 PACK(INT32 val)\n{\n\tUINT32 temp;\n\tint sign,exponent,k;\n\n\tsign = (val >> 23) & 0x1;\n\ttemp = (val ^ (val << 1)) & 0xFFFFFF;\n\texponent = 0;\n\tfor (k=0; k<12; k++)\n\t{\n\t\tif (temp & 0x800000)\n\t\t\tbreak;\n\t\ttemp <<= 1;\n\t\texponent += 1;\n\t}\n\tif (exponent < 12)\n\t\tval = (val << exponent) & 0x3FFFFF;\n\telse\n\t\tval <<= 11;\n\tval >>= 11;\n\tval &= 0x7FF;\n\tval |= sign << 15;\n\tval |= exponent << 11;\n\n\treturn (UINT16)val;\n}\n\nstatic INT32 UNPACK(UINT16 val)\n{\n\tint sign,exponent,mantissa;\n\tINT32 uval;\n\n\tsign = (val >> 15) & 0x1;\n\texponent = (val >> 11) & 0xF;\n\tmantissa = val & 0x7FF;\n\tuval = mantissa << 11;\n\tif (exponent > 11)\n\t{\n\t\texponent = 11;\n\t\tuval |= sign << 22;\n\t}\n\telse\n\t\tuval |= (sign ^ 1) << 22;\n\tuval |= sign << 23;\n\tuval <<= 8;\n\tuval >>= 8;\n\tuval >>= exponent;\n\n\treturn uval;\n}\n\nvoid SCSPDSP_Init(struct _SCSPDSP *DSP)\n{\n\tmemset(DSP,0,sizeof(struct _SCSPDSP));\n\tDSP->RBL=0x8000;\n\tDSP->Stopped=1;\n}\n\nvoid SCSPDSP_Step(struct _SCSPDSP *DSP)\n{\n\tINT32 ACC=0;\t//26 bit\n\tINT32 SHIFTED=0;\t//24 bit\n\tINT32 X=0;\t//24 bit\n\tINT32 Y=0;\t//13 bit\n\tINT32 B=0;\t//26 bit\n\tINT32 INPUTS=0;\t//24 bit\n\tINT32 MEMVAL=0;\n\tINT32 FRC_REG=0;\t//13 bit\n\tINT32 Y_REG=0;\t\t//24 bit\n\tUINT32 ADDR=0;\n\tUINT32 ADRS_REG=0;\t//13 bit\n\tint step;\n\n\tif(DSP->Stopped)\n\t\treturn;\n\n\tmemset(DSP->EFREG,0,2*16);\n#if 0\n\tint dump=0;\n\tFILE *f=NULL;\n\tif(dump)\n\t\tf=fopen(\"dsp.txt\",\"wt\");\n#endif\n\tfor(step=0;step</*128*/DSP->LastStep;++step)\n\t{\n\t\tUINT16 *IPtr=DSP->MPRO+step*4;\n\n//      if(IPtr[0]==0 && IPtr[1]==0 && IPtr[2]==0 && IPtr[3]==0)\n//          break;\n\n\t\tUINT32 TRA=(IPtr[0]>>8)&0x7F;\n\t\tUINT32 TWT=(IPtr[0]>>7)&0x01;\n\t\tUINT32 TWA=(IPtr[0]>>0)&0x7F;\n\n\t\tUINT32 XSEL=(IPtr[1]>>15)&0x01;\n\t\tUINT32 YSEL=(IPtr[1]>>13)&0x03;\n\t\tUINT32 IRA=(IPtr[1]>>6)&0x3F;\n\t\tUINT32 IWT=(IPtr[1]>>5)&0x01;\n\t\tUINT32 IWA=(IPtr[1]>>0)&0x1F;\n\n\t\tUINT32 TABLE=(IPtr[2]>>15)&0x01;\n\t\tUINT32 MWT=(IPtr[2]>>14)&0x01;\n\t\tUINT32 MRD=(IPtr[2]>>13)&0x01;\n\t\tUINT32 EWT=(IPtr[2]>>12)&0x01;\n\t\tUINT32 EWA=(IPtr[2]>>8)&0x0F;\n\t\tUINT32 ADRL=(IPtr[2]>>7)&0x01;\n\t\tUINT32 FRCL=(IPtr[2]>>6)&0x01;\n\t\tUINT32 SHIFT=(IPtr[2]>>4)&0x03;\n\t\tUINT32 YRL=(IPtr[2]>>3)&0x01;\n\t\tUINT32 NEGB=(IPtr[2]>>2)&0x01;\n\t\tUINT32 ZERO=(IPtr[2]>>1)&0x01;\n\t\tUINT32 BSEL=(IPtr[2]>>0)&0x01;\n\n\t\tUINT32 NOFL=(IPtr[3]>>15)&1;\t\t//????\n\t\tUINT32 COEF=(IPtr[3]>>9)&0x3f;\n\n\t\tUINT32 MASA=(IPtr[3]>>2)&0x1f;\t//???\n\t\tUINT32 ADREB=(IPtr[3]>>1)&0x1;\n\t\tUINT32 NXADR=(IPtr[3]>>0)&0x1;\n\n\t\tINT64 v;\n\n\t\t//operations are done at 24 bit precision\n#if 0\n\t\tif(MASA)\n\t\t\tint a=1;\n\t\tif(NOFL)\n\t\t\tint a=1;\n\n//      int dump=0;\n\n\t\tif(f)\n\t\t{\n#define DUMP(v)\tfprintf(f,\" \" #v \": %04X\",v);\n\n\t\t\tfprintf(f,\"%d: \",step);\n\t\t\tDUMP(ACC);\n\t\t\tDUMP(SHIFTED);\n\t\t\tDUMP(X);\n\t\t\tDUMP(Y);\n\t\t\tDUMP(B);\n\t\t\tDUMP(INPUTS);\n\t\t\tDUMP(MEMVAL);\n\t\t\tDUMP(FRC_REG);\n\t\t\tDUMP(Y_REG);\n\t\t\tDUMP(ADDR);\n\t\t\tDUMP(ADRS_REG);\n\t\t\tfprintf(f,\"\\n\");\n\t\t}\n#endif\n\t\t//INPUTS RW\n// colmns97 hits this\n//      assert(IRA<0x32);\n\t\tif(IRA<=0x1f)\n\t\t\tINPUTS=DSP->MEMS[IRA];\n\t\telse if(IRA<=0x2F)\n\t\t\tINPUTS=DSP->MIXS[IRA-0x20]<<4;\t//MIXS is 20 bit\n\t\telse if(IRA<=0x31)\n\t\t\tINPUTS=0;\n\t\telse\n\t\t\treturn;\n\n\t\tINPUTS<<=8;\n\t\tINPUTS>>=8;\n\t\t//if(INPUTS&0x00800000)\n\t\t//  INPUTS|=0xFF000000;\n\n\t\tif(IWT)\n\t\t{\n\t\t\tDSP->MEMS[IWA]=MEMVAL;\t//MEMVAL was selected in previous MRD\n\t\t\tif(IRA==IWA)\n\t\t\t\tINPUTS=MEMVAL;\n\t\t}\n\n\t\t//Operand sel\n\t\t//B\n\t\tif(!ZERO)\n\t\t{\n\t\t\tif(BSEL)\n\t\t\t\tB=ACC;\n\t\t\telse\n\t\t\t{\n\t\t\t\tB=DSP->TEMP[(TRA+DSP->DEC)&0x7F];\n\t\t\t\tB<<=8;\n\t\t\t\tB>>=8;\n\t\t\t\t//if(B&0x00800000)\n\t\t\t\t//  B|=0xFF000000;  //Sign extend\n\t\t\t}\n\t\t\tif(NEGB)\n\t\t\t\tB=0-B;\n\t\t}\n\t\telse\n\t\t\tB=0;\n\n\t\t//X\n\t\tif(XSEL)\n\t\t\tX=INPUTS;\n\t\telse\n\t\t{\n\t\t\tX=DSP->TEMP[(TRA+DSP->DEC)&0x7F];\n\t\t\tX<<=8;\n\t\t\tX>>=8;\n\t\t\t//if(X&0x00800000)\n\t\t\t//  X|=0xFF000000;\n\t\t}\n\n\t\t//Y\n\t\tif(YSEL==0)\n\t\t\tY=FRC_REG;\n\t\telse if(YSEL==1)\n\t\t\tY=DSP->COEF[COEF]>>3;\t//COEF is 16 bits\n\t\telse if(YSEL==2)\n\t\t\tY=(Y_REG>>11)&0x1FFF;\n\t\telse if(YSEL==3)\n\t\t\tY=(Y_REG>>4)&0x0FFF;\n\n\t\tif(YRL)\n\t\t\tY_REG=INPUTS;\n\n\t\t//Shifter\n\t\tif(SHIFT==0)\n\t\t{\n\t\t\tSHIFTED=ACC;\n\t\t\tif(SHIFTED>0x007FFFFF)\n\t\t\t\tSHIFTED=0x007FFFFF;\n\t\t\tif(SHIFTED<(-0x00800000))\n\t\t\t\tSHIFTED=-0x00800000;\n\t\t}\n\t\telse if(SHIFT==1)\n\t\t{\n\t\t\tSHIFTED=ACC*2;\n\t\t\tif(SHIFTED>0x007FFFFF)\n\t\t\t\tSHIFTED=0x007FFFFF;\n\t\t\tif(SHIFTED<(-0x00800000))\n\t\t\t\tSHIFTED=-0x00800000;\n\t\t}\n\t\telse if(SHIFT==2)\n\t\t{\n\t\t\tSHIFTED=ACC*2;\n\t\t\tSHIFTED<<=8;\n\t\t\tSHIFTED>>=8;\n\t\t\t//SHIFTED&=0x00FFFFFF;\n\t\t\t//if(SHIFTED&0x00800000)\n\t\t\t//  SHIFTED|=0xFF000000;\n\t\t}\n\t\telse if(SHIFT==3)\n\t\t{\n\t\t\tSHIFTED=ACC;\n\t\t\tSHIFTED<<=8;\n\t\t\tSHIFTED>>=8;\n\t\t\t//SHIFTED&=0x00FFFFFF;\n\t\t\t//if(SHIFTED&0x00800000)\n\t\t\t//  SHIFTED|=0xFF000000;\n\t\t}\n\n\t\t//ACCUM\n\t\tY<<=19;\n\t\tY>>=19;\n\t\t//if(Y&0x1000)\n\t\t//  Y|=0xFFFFF000;\n\n\t\tv=(((INT64) X*(INT64) Y)>>12);\n\t\tACC=(int) v+B;\n\n\t\tif(TWT)\n\t\t\tDSP->TEMP[(TWA+DSP->DEC)&0x7F]=SHIFTED;\n\n\t\tif(FRCL)\n\t\t{\n\t\t\tif(SHIFT==3)\n\t\t\t\tFRC_REG=SHIFTED&0x0FFF;\n\t\t\telse\n\t\t\t\tFRC_REG=(SHIFTED>>11)&0x1FFF;\n\t\t}\n\n\t\tif(MRD || MWT)\n\t\t//if(0)\n\t\t{\n\t\t\tADDR=DSP->MADRS[MASA];\n\t\t\tif(!TABLE)\n\t\t\t\tADDR+=DSP->DEC;\n\t\t\tif(ADREB)\n\t\t\t\tADDR+=ADRS_REG&0x0FFF;\n\t\t\tif(NXADR)\n\t\t\t\tADDR++;\n\t\t\tif(!TABLE)\n\t\t\t\tADDR&=DSP->RBL-1;\n\t\t\telse\n\t\t\t\tADDR&=0xFFFF;\n\t\t\t//ADDR<<=1;\n\t\t\t//ADDR+=DSP->RBP<<13;\n\t\t\t//MEMVAL=DSP->SCSPRAM[ADDR>>1];\n\t\t\tADDR+=DSP->RBP<<12;\n\t\t\tif (ADDR > 0x7ffff) ADDR = 0;\n\t\t\tif(MRD && (step&1))\t//memory only allowed on odd? DoA inserts NOPs on even\n\t\t\t{\n\t\t\t\tif(NOFL)\n\t\t\t\t\tMEMVAL=DSP->SCSPRAM[ADDR]<<8;\n\t\t\t\telse\n\t\t\t\t\tMEMVAL=UNPACK(DSP->SCSPRAM[ADDR]);\n\t\t\t}\n\t\t\tif(MWT && (step&1))\n\t\t\t{\n\t\t\t\tif(NOFL)\n\t\t\t    \t\tDSP->SCSPRAM[ADDR]=SHIFTED>>8;\n\t\t\t\telse\n\t\t\t\t\tDSP->SCSPRAM[ADDR]=PACK(SHIFTED);\n\t\t\t}\n\t\t}\n\n\t\tif(ADRL)\n\t\t{\n\t\t\tif(SHIFT==3)\n\t\t\t\tADRS_REG=(SHIFTED>>12)&0xFFF;\n\t\t\telse\n\t\t\t\tADRS_REG=(INPUTS>>16);\n\t\t}\n\n\t\tif(EWT)\n\t\t\tDSP->EFREG[EWA]+=SHIFTED>>8;\n\n\t}\n\t--DSP->DEC;\n\tmemset(DSP->MIXS,0,4*16);\n//  if(f)\n//      fclose(f);\n}\n\nvoid SCSPDSP_SetSample(struct _SCSPDSP *DSP,INT32 sample,int SEL,int MXL)\n{\n\t//DSP->MIXS[SEL]+=sample<<(MXL+1)/*7*/;\n\tDSP->MIXS[SEL]+=sample;\n//  if(MXL)\n//      int a=1;\n}\n\nvoid SCSPDSP_Start(struct _SCSPDSP *DSP)\n{\n\tint i;\n\tDSP->Stopped=0;\n\tfor(i=127;i>=0;--i)\n\t{\n\t\tUINT16 *IPtr=DSP->MPRO+i*4;\n\n\t\tif(IPtr[0]!=0 || IPtr[1]!=0 || IPtr[2]!=0 || IPtr[3]!=0)\n\t\t\tbreak;\n\t}\n\tDSP->LastStep=i+1;\n\n}\n"
  },
  {
    "path": "VGMPlay/chips/scspdsp.h",
    "content": "#pragma once\n\n#ifndef __SCSPDSP_H__\n#define __SCSPDSP_H__\n\n//the DSP Context\nstruct _SCSPDSP\n{\n//Config\n\tUINT16 *SCSPRAM;\n\tUINT32 SCSPRAM_LENGTH;\n\tUINT32 RBP;\t//Ring buf pointer\n\tUINT32 RBL;\t//Delay ram (Ring buffer) size in words\n\n//context\n\n\tINT16 COEF[64];\t\t//16 bit signed\n\tUINT16 MADRS[32];\t//offsets (in words), 16 bit\n\tUINT16 MPRO[128*4];\t//128 steps 64 bit\n\tINT32 TEMP[128];\t//TEMP regs,24 bit signed\n\tINT32 MEMS[32];\t//MEMS regs,24 bit signed\n\tUINT32 DEC;\n\n//input\n\tINT32 MIXS[16];\t//MIXS, 24 bit signed\n\tINT16 EXTS[2];\t//External inputs (CDDA)    16 bit signed\n\n//output\n\tINT16 EFREG[16];\t//EFREG, 16 bit signed\n\n\tint Stopped;\n\tint LastStep;\n};\n\nvoid SCSPDSP_Init(struct _SCSPDSP *DSP);\nvoid SCSPDSP_SetSample(struct _SCSPDSP *DSP, INT32 sample, INT32 SEL, INT32 MXL);\nvoid SCSPDSP_Step(struct _SCSPDSP *DSP);\nvoid SCSPDSP_Start(struct _SCSPDSP *DSP);\n\n#endif /* __SCSPDSP_H__ */\n"
  },
  {
    "path": "VGMPlay/chips/scsplfo.c",
    "content": "/*\n    SCSP LFO handling\n\n    Part of the SCSP (YMF292-F) emulator package.\n    (not compiled directly, #included from scsp.c)\n\n    By ElSemi\n    MAME/M1 conversion and cleanup by R. Belmont\n*/\n\n#define LFO_SHIFT\t8\n\nstruct _LFO\n{\n    unsigned short phase;\n    UINT32 phase_step;\n    int *table;\n    int *scale;\n};\n\n#define LFIX(v)\t((unsigned int) ((float) (1<<LFO_SHIFT)*(v)))\n\n//Convert DB to multiply amplitude\n#define DB(v)\tLFIX(pow(10.0,v/20.0))\n\n//Convert cents to step increment\n#define CENTS(v) LFIX(pow(2.0,v/1200.0))\n\nstatic int PLFO_TRI[256],PLFO_SQR[256],PLFO_SAW[256],PLFO_NOI[256];\nstatic int ALFO_TRI[256],ALFO_SQR[256],ALFO_SAW[256],ALFO_NOI[256];\nstatic const float LFOFreq[32]=\n{\n\t0.17f,0.19f,0.23f,0.27f,0.34f,0.39f,0.45f,0.55f,0.68f,0.78f,0.92f,1.10f,1.39f,1.60f,1.87f,2.27f,\n\t2.87f,3.31f,3.92f,4.79f,6.15f,7.18f,8.60f,10.8f,14.4f,17.2f,21.5f,28.7f,43.1f,57.4f,86.1f,172.3f\n};\nstatic const float ASCALE[8]={0.0f,0.4f,0.8f,1.5f,3.0f,6.0f,12.0f,24.0f};\nstatic const float PSCALE[8]={0.0f,7.0f,13.5f,27.0f,55.0f,112.0f,230.0f,494.0f};\nstatic int PSCALES[8][256];\nstatic int ASCALES[8][256];\nstatic UINT8 IsInit;\n\nstatic void LFO_Init(/*running_machine &machine*/)\n{\n    int i,s;\n\tif (IsInit)\n\t\treturn;\n    for(i=0;i<256;++i)\n    {\n\t\tint a,p;\n//      float TL;\n\t\t//Saw\n\t\ta=255-i;\n\t\tif(i<128)\n\t\t\tp=i;\n\t\telse\n\t\t\tp=i-256;\n\t\tALFO_SAW[i]=a;\n\t\tPLFO_SAW[i]=p;\n\n\t\t//Square\n\t\tif(i<128)\n\t\t{\n\t\t\ta=255;\n\t\t\tp=127;\n\t\t}\n\t\telse\n\t\t{\n\t\t\ta=0;\n\t\t\tp=-128;\n\t\t}\n\t\tALFO_SQR[i]=a;\n\t\tPLFO_SQR[i]=p;\n\n\t\t//Tri\n\t\tif(i<128)\n\t\t\ta=255-(i*2);\n\t\telse\n\t\t\ta=(i*2)-256;\n\t\tif(i<64)\n\t\t\tp=i*2;\n\t\telse if(i<128)\n\t\t\tp=255-i*2;\n\t\telse if(i<192)\n\t\t\tp=256-i*2;\n\t\telse\n\t\t\tp=i*2-511;\n\t\tALFO_TRI[i]=a;\n\t\tPLFO_TRI[i]=p;\n\n\t\t//noise\n\t\t//a=lfo_noise[i];\n\t\t//a=machine.rand()&0xff;\n\t\ta=rand()&0xff;\n\t\tp=128-a;\n\t\tALFO_NOI[i]=a;\n\t\tPLFO_NOI[i]=p;\n    }\n\n\tfor(s=0;s<8;++s)\n\t{\n\t\tfloat limit=PSCALE[s];\n\t\tfor(i=-128;i<128;++i)\n\t\t{\n\t\t\tPSCALES[s][i+128]=CENTS(((limit*(float) i)/128.0));\n\t\t}\n\t\tlimit=-ASCALE[s];\n\t\tfor(i=0;i<256;++i)\n\t\t{\n\t\t\tASCALES[s][i]=DB(((limit*(float) i)/256.0));\n\t\t}\n\t}\n\tIsInit = 0x01;\n}\n\nINLINE signed int PLFO_Step(struct _LFO *LFO)\n{\n\tint p;\n    LFO->phase+=LFO->phase_step;\n#if LFO_SHIFT!=8\n    LFO->phase&=(1<<(LFO_SHIFT+8))-1;\n#endif\n    p=LFO->table[LFO->phase>>LFO_SHIFT];\n\tp=LFO->scale[p+128];\n\treturn p<<(SHIFT-LFO_SHIFT);\n}\n\nINLINE signed int ALFO_Step(struct _LFO *LFO)\n{\n\tint p;\n    LFO->phase+=LFO->phase_step;\n#if LFO_SHIFT!=8\n    LFO->phase&=(1<<(LFO_SHIFT+8))-1;\n#endif\n    p=LFO->table[LFO->phase>>LFO_SHIFT];\n\tp=LFO->scale[p];\n\treturn p<<(SHIFT-LFO_SHIFT);\n}\n\nstatic void LFO_ComputeStep(struct _LFO *LFO,UINT32 LFOF,UINT32 LFOWS,UINT32 LFOS,int ALFO)\n{\n    float step=(float) LFOFreq[LFOF]*256.0/(float)44100;\n    LFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step);\n    if(ALFO)\n    {\n\t\tswitch(LFOWS)\n\t\t{\n\t\t\tcase 0: LFO->table=ALFO_SAW; break;\n\t\t\tcase 1: LFO->table=ALFO_SQR; break;\n\t\t\tcase 2: LFO->table=ALFO_TRI; break;\n\t\t\tcase 3: LFO->table=ALFO_NOI; break;\n\t\t}\n\t\tLFO->scale=ASCALES[LFOS];\n\t}\n\telse\n\t{\n\t\tswitch(LFOWS)\n\t\t{\n\t\t    case 0: LFO->table=PLFO_SAW; break;\n\t\t    case 1: LFO->table=PLFO_SQR; break;\n\t\t\tcase 2: LFO->table=PLFO_TRI; break;\n\t\t    case 3: LFO->table=PLFO_NOI; break;\n\t\t}\n\t\tLFO->scale=PSCALES[LFOS];\n\t}\n}\n"
  },
  {
    "path": "VGMPlay/chips/segapcm.c",
    "content": "/*********************************************************/\n/*    SEGA 16ch 8bit PCM                                 */\n/*********************************************************/\n\n#include \"mamedef.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stdio.h>\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#include \"segapcm.h\"\n\n\ntypedef struct _segapcm_state segapcm_state;\nstruct _segapcm_state\n{\n\tUINT8  *ram;\n\tUINT8 low[16];\n\tUINT32 ROMSize;\n\tUINT8 *rom;\n#ifdef _DEBUG\n\tUINT8 *romusage;\n#endif\n\tint bankshift;\n\tint bankmask;\n\tint rgnmask;\n\tsega_pcm_interface intf;\n\tUINT8 Muted[16];\n\t//sound_stream * stream;\n};\n\n#define MAX_CHIPS\t0x02\nstatic segapcm_state SPCMData[MAX_CHIPS];\n\n#ifndef _DEBUG\n//UINT8 SegaPCM_NewCore = 0x00;\n#else\n//UINT8 SegaPCM_NewCore = 0x01;\nstatic void sega_pcm_fwrite_romusage(UINT8 ChipID);\n#endif\n\n/*INLINE segapcm_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_SEGAPCM);\n\treturn (segapcm_state *)device->token;\n}*/\n\n//static STREAM_UPDATE( SEGAPCM_update )\nvoid SEGAPCM_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//segapcm_state *spcm = (segapcm_state *)param;\n\tsegapcm_state *spcm = &SPCMData[ChipID];\n\tint rgnmask = spcm->rgnmask;\n\tint ch;\n\n\t/* clear the buffers */\n\tmemset(outputs[0], 0, samples*sizeof(stream_sample_t));\n\tmemset(outputs[1], 0, samples*sizeof(stream_sample_t));\n\n\t// reg      function\n\t// ------------------------------------------------\n\t// 0x00     ?\n\t// 0x01     ?\n\t// 0x02     volume left\n\t// 0x03     volume right\n\t// 0x04     loop address (08-15)\n\t// 0x05     loop address (16-23)\n\t// 0x06     end address\n\t// 0x07     address delta\n\t// 0x80     ?\n\t// 0x81     ?\n\t// 0x82     ?\n\t// 0x83     ?\n\t// 0x84     current address (08-15), 00-07 is internal?\n\t// 0x85     current address (16-23)\n\t// 0x86     bit 0: channel disable?\n\t//          bit 1: loop disable\n\t//          other bits: bank\n\t// 0x87     ?\n\n\t/* loop over channels */\n\tfor (ch = 0; ch < 16; ch++)\n\t{\n#if 0\n//if (! SegaPCM_NewCore)\n//{\n\t\t/* only process active channels */\n\t\tif (!(spcm->ram[0x86+8*ch] & 1) && ! spcm->Muted[ch])\n\t\t{\n\t\t\tUINT8 *base = spcm->ram+8*ch;\n\t\t\tUINT8 flags = base[0x86];\n\t\t\tconst UINT8 *rom = spcm->rom + ((flags & spcm->bankmask) << spcm->bankshift);\n#ifdef _DEBUG\n\t\t\tUINT8 *romusage = spcm->romusage + ((flags & spcm->bankmask) << spcm->bankshift);\n#endif\n\t\t\tUINT32 addr = (base[5] << 16) | (base[4] << 8) | spcm->low[ch];\n\t\t\tUINT16 loop = (base[0x85] << 8) | base[0x84];\n\t\t\tUINT8 end = base[6] + 1;\n\t\t\tUINT8 delta = base[7];\n\t\t\tUINT8 voll = base[2] & 0x7F;\n\t\t\tUINT8 volr = base[3] & 0x7F;\n\t\t\tint i;\n\n\t\t\t/* loop over samples on this channel */\n\t\t\tfor (i = 0; i < samples; i++)\n\t\t\t{\n\t\t\t\tINT8 v = 0;\n\n\t\t\t\t/* handle looping if we've hit the end */\n\t\t\t\tif ((addr >> 16) == end)\n\t\t\t\t{\n\t\t\t\t\tif (!(flags & 2))\n\t\t\t\t\t\taddr = loop << 8;\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tflags |= 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* fetch the sample */\n\t\t\t\tv = rom[(addr >> 8) & rgnmask] - 0x80;\n#ifdef _DEBUG\n\t\t\t\tif ((romusage[(addr >> 8) & rgnmask] & 0x03) == 0x02 && (voll || volr))\n\t\t\t\t\tfprintf(stderr, \"Access to empty ROM section! (0x%06lX)\\n\",\n\t\t\t\t\t\t\t((flags & spcm->bankmask) << spcm->bankshift) + (addr >> 8) & rgnmask);\n\t\t\t\tromusage[(addr >> 8) & rgnmask] |= 0x01;\n#endif\n\n\t\t\t\t/* apply panning and advance */\n\t\t\t\toutputs[0][i] += v * voll;\n\t\t\t\toutputs[1][i] += v * volr;\n\t\t\t\taddr += delta;\n\t\t\t}\n\n\t\t\t/* store back the updated address and info */\n\t\t\tbase[0x86] = flags;\n\t\t\tbase[4] = addr >> 8;\n\t\t\tbase[5] = addr >> 16;\n\t\t\tspcm->low[ch] = flags & 1 ? 0 : addr;\n\t\t}\n//}\n//else\n//{\n#else\n\t\tUINT8 *regs = spcm->ram+8*ch;\n\n\t\t/* only process active channels */\n\t\tif (!(regs[0x86] & 1) && ! spcm->Muted[ch])\n\t\t{\n\t\t\tconst UINT8 *rom = spcm->rom + ((regs[0x86] & spcm->bankmask) << spcm->bankshift);\n#ifdef _DEBUG\n\t\t\tUINT8 *romusage = spcm->romusage + ((regs[0x86] & spcm->bankmask) << spcm->bankshift);\n#endif\n\t\t\tUINT32 addr = (regs[0x85] << 16) | (regs[0x84] << 8) | spcm->low[ch];\n\t\t\tUINT32 loop = (regs[0x05] << 16) | (regs[0x04] << 8);\n\t\t\tUINT8 end = regs[6] + 1;\n\t\t\tint i;\n\n\t\t\t/* loop over samples on this channel */\n\t\t\tfor (i = 0; i < samples; i++)\n\t\t\t{\n\t\t\t\tINT8 v = 0;\n\n\t\t\t\t/* handle looping if we've hit the end */\n\t\t\t\tif ((addr >> 16) == end)\n\t\t\t\t{\n\t\t\t\t\tif (regs[0x86] & 2)\n\t\t\t\t\t{\n\t\t\t\t\t\tregs[0x86] |= 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\telse addr = loop;\n\t\t\t\t}\n\n\t\t\t\t/* fetch the sample */\n\t\t\t\tv = rom[(addr >> 8) & rgnmask] - 0x80;\n#ifdef _DEBUG\n\t\t\t\tif ((romusage[(addr >> 8) & rgnmask] & 0x03) == 0x02 && (regs[2] || regs[3]))\n\t\t\t\t\tfprintf(stderr, \"Access to empty ROM section! (0x%06lX)\\n\",\n\t\t\t\t\t\t\t((regs[0x86] & spcm->bankmask) << spcm->bankshift) + (addr >> 8) & rgnmask);\n\t\t\t\tromusage[(addr >> 8) & rgnmask] |= 0x01;\n#endif\n\n\t\t\t\t/* apply panning and advance */\n\t\t\t\t// fixed Bitmask for volume multiplication, thanks to ctr -Valley Bell\n\t\t\t\toutputs[0][i] += v * (regs[2] & 0x7F);\n\t\t\t\toutputs[1][i] += v * (regs[3] & 0x7F);\n\t\t\t\taddr = (addr + regs[7]) & 0xffffff;\n\t\t\t}\n\n\t\t\t/* store back the updated address */\n\t\t\tregs[0x84] = addr >> 8;\n\t\t\tregs[0x85] = addr >> 16;\n\t\t\tspcm->low[ch] = regs[0x86] & 1 ? 0 : addr;\n\t\t}\n//}\n#endif\n\t}\n}\n\n//static DEVICE_START( segapcm )\nint device_start_segapcm(UINT8 ChipID, int clock, int intf_bank)\n{\n\tconst UINT32 STD_ROM_SIZE = 0x80000;\n\t//const sega_pcm_interface *intf = (const sega_pcm_interface *)device->static_config;\n\tsega_pcm_interface *intf;\n\tint mask, rom_mask, len;\n\t//segapcm_state *spcm = get_safe_token(device);\n\tsegapcm_state *spcm;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tspcm = &SPCMData[ChipID];\n\tintf = &spcm->intf;\n\tintf->bank = intf_bank;\n\t\n\t//spcm->rom = (const UINT8 *)device->region;\n\t//spcm->ram = auto_alloc_array(device->machine, UINT8, 0x800);\n\tspcm->ROMSize = STD_ROM_SIZE;\n\tspcm->rom = malloc(STD_ROM_SIZE);\n#ifdef _DEBUG\n\tspcm->romusage = malloc(STD_ROM_SIZE);\n#endif\n\tspcm->ram = (UINT8*)malloc(0x800);\n\t\n#ifndef _DEBUG\n\t//memset(spcm->rom, 0xFF, STD_ROM_SIZE);\n\t// filling 0xFF would actually be more true to the hardware,\n\t// (unused ROMs have all FFs)\n\t// but 0x80 is the effective 'zero' byte\n\tmemset(spcm->rom, 0x80, STD_ROM_SIZE);\n#else\n\t// filling with FF makes it easier to find bugs in a .wav-log\n\tmemset(spcm->rom, 0xFF, STD_ROM_SIZE);\n\tmemset(spcm->romusage, 0x02, STD_ROM_SIZE);\n#endif\n\t//memset(spcm->ram, 0xff, 0x800);\t// RAM Clear is done at device_reset\n\n\tspcm->bankshift = (UINT8)(intf->bank);\n\tmask = intf->bank >> 16;\n\tif(!mask)\n\t\tmask = BANK_MASK7>>16;\n\n\tlen = STD_ROM_SIZE;\n\tspcm->rgnmask = len - 1;\n\tfor(rom_mask = 1; rom_mask < len; rom_mask *= 2);\n\trom_mask--;\n\n\tspcm->bankmask = mask & (rom_mask >> spcm->bankshift);\n\n\t//spcm->stream = stream_create(device, 0, 2, device->clock / 128, spcm, SEGAPCM_update);\n\n\t//state_save_register_device_item_array(device, 0, spcm->low);\n\t//state_save_register_device_item_pointer(device, 0, spcm->ram, 0x800);\n\t\n\tfor (mask = 0; mask < 16; mask ++)\n\t\tspcm->Muted[mask] = 0x00;\n\t\n\treturn clock / 128;\n}\n\n//static DEVICE_STOP( segapcm )\nvoid device_stop_segapcm(UINT8 ChipID)\n{\n\t//segapcm_state *spcm = get_safe_token(device);\n\tsegapcm_state *spcm = &SPCMData[ChipID];\n\tfree(spcm->rom);\tspcm->rom = NULL;\n#ifdef _DEBUG\n\t//sega_pcm_fwrite_romusage(ChipID);\n\tfree(spcm->romusage);\n#endif\n\tfree(spcm->ram);\n\t\n\treturn;\n}\n\n//static DEVICE_RESET( segapcm )\nvoid device_reset_segapcm(UINT8 ChipID)\n{\n\t//segapcm_state *spcm = get_safe_token(device);\n\tsegapcm_state *spcm = &SPCMData[ChipID];\n\t\n\tmemset(spcm->ram, 0xFF, 0x800);\n\t\n\treturn;\n}\n\n\n//WRITE8_DEVICE_HANDLER( sega_pcm_w )\nvoid sega_pcm_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//segapcm_state *spcm = get_safe_token(device);\n\tsegapcm_state *spcm = &SPCMData[ChipID];\n\t//stream_update(spcm->stream);\n\n\tspcm->ram[offset & 0x07ff] = data;\n}\n\n//READ8_DEVICE_HANDLER( sega_pcm_r )\nUINT8 sega_pcm_r(UINT8 ChipID, offs_t offset)\n{\n\t//segapcm_state *spcm = get_safe_token(device);\n\tsegapcm_state *spcm = &SPCMData[ChipID];\n\t//stream_update(spcm->stream);\n\treturn spcm->ram[offset & 0x07ff];\n}\n\nvoid sega_pcm_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t\tconst UINT8* ROMData)\n{\n\tsegapcm_state *spcm = &SPCMData[ChipID];\n\t\n\tif (spcm->ROMSize != ROMSize)\n\t{\n\t\tunsigned long int mask, rom_mask;\n\t\t\n\t\tspcm->rom = (UINT8*)realloc(spcm->rom, ROMSize);\n#ifdef _DEBUG\n\t\tspcm->romusage = (UINT8*)realloc(spcm->romusage, ROMSize);\n#endif\n\t\tspcm->ROMSize = ROMSize;\n\t\tmemset(spcm->rom, 0x80, ROMSize);\n#ifdef _DEBUG\n\t\tmemset(spcm->romusage, 0x02, ROMSize);\n#endif\n\t\t\n\t\t// recalculate bankmask\n\t\tmask = spcm->intf.bank >> 16;\n\t\tif (! mask)\n\t\t\tmask = BANK_MASK7 >> 16;\n\t\t\n\t\t//spcm->rgnmask = ROMSize - 1;\n\t\tfor (rom_mask = 1; rom_mask < ROMSize; rom_mask *= 2);\n\t\trom_mask --;\n\t\tspcm->rgnmask = rom_mask;\t// fix for ROMs with e.g 0x60000 bytes (stupid M1)\n\t\t\n\t\tspcm->bankmask = mask & (rom_mask >> spcm->bankshift);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(spcm->rom + DataStart, ROMData, DataLength);\n#ifdef _DEBUG\n\tmemset(spcm->romusage + DataStart, 0x00, DataLength);\n#endif\n\t\n\treturn;\n}\n\n\n#ifdef _DEBUG\nstatic void sega_pcm_fwrite_romusage(UINT8 ChipID)\n{\n\tsegapcm_state *spcm = &SPCMData[ChipID];\n\t\n\tFILE* hFile;\n\t\n\thFile = fopen(\"SPCM_ROMUsage.bin\", \"wb\");\n\tif (hFile == NULL)\n\t\treturn;\n\t\n\tfwrite(spcm->romusage, 0x01, spcm->ROMSize, hFile);\n\t\n\tfclose(hFile);\n\treturn;\n}\n#endif\n\nvoid segapcm_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tsegapcm_state *spcm = &SPCMData[ChipID];\n\tunsigned char CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 16; CurChn ++)\n\t\tspcm->Muted[CurChn] = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( segapcm )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(segapcm_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( segapcm );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"Sega PCM\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Sega custom\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/segapcm.h",
    "content": "/*********************************************************/\n/*    SEGA 8bit PCM                                      */\n/*********************************************************/\n\n#pragma once\n\n#define   BANK_256    (11)\n#define   BANK_512    (12)\n#define   BANK_12M    (13)\n#define   BANK_MASK7    (0x70<<16)\n#define   BANK_MASKF    (0xf0<<16)\n#define   BANK_MASKF8   (0xf8<<16)\n\ntypedef struct _sega_pcm_interface sega_pcm_interface;\nstruct _sega_pcm_interface\n{\n\tint  bank;\n};\n\n/*WRITE8_DEVICE_HANDLER( sega_pcm_w );\nREAD8_DEVICE_HANDLER( sega_pcm_r );\n\nDEVICE_GET_INFO( segapcm );\n#define SOUND_SEGAPCM DEVICE_GET_INFO_NAME( segapcm )*/\n\nvoid SEGAPCM_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_segapcm(UINT8 ChipID, int clock, int intf_bank);\nvoid device_stop_segapcm(UINT8 ChipID);\nvoid device_reset_segapcm(UINT8 ChipID);\n\nvoid sega_pcm_w(UINT8 ChipID, offs_t offset, UINT8 data);\nUINT8 sega_pcm_r(UINT8 ChipID, offs_t offset);\nvoid sega_pcm_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t\tconst UINT8* ROMData);\n\nvoid segapcm_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n"
  },
  {
    "path": "VGMPlay/chips/sn76489.c",
    "content": "/* \n\tSN76489 emulation\n\tby Maxim in 2001 and 2002\n\tconverted from my original Delphi implementation\n\n\tI'm a C newbie so I'm sure there are loads of stupid things\n\tin here which I'll come back to some day and redo\n\n\tIncludes:\n\t- Super-high quality tone channel \"oversampling\" by calculating fractional positions on transitions\n\t- Noise output pattern reverse engineered from actual SMS output\n\t- Volume levels taken from actual SMS output\n\n\t07/08/04  Charles MacDonald\n\tModified for use with SMS Plus:\n\t- Added support for multiple PSG chips.\n\t- Added reset/config/update routines.\n\t- Added context management routines.\n\t- Removed SN76489_GetValues().\n\t- Removed some unused variables.\n*/\n\n#include <stdlib.h> // malloc/free\n#include <float.h> // for FLT_MIN\n#include <string.h> // for memcpy\n#include \"mamedef.h\"\n#include \"sn76489.h\"\n#include \"panning.h\"\n\n#define NoiseInitialState 0x8000  /* Initial state of shift register */\n#define PSG_CUTOFF        0x6     /* Value below which PSG does not output */\n\nstatic const int PSGVolumeValues[16] = {\n/*\t// These values are taken from a real SMS2's output\n\t{892,892,892,760,623,497,404,323,257,198,159,123,96,75,60,0}, // I can't remember why 892... :P some scaling I did at some point\n\t// these values are true volumes for 2dB drops at each step (multiply previous by 10^-0.1)\n\t1516,1205,957,760,603,479,381,303,240,191,152,120,96,76,60,0*/\n// The MAME core uses 0x2000 as maximum volume (0x1000 for bipolar output)\n\t4096, 3254, 2584, 2053, 1631, 1295, 1029, 817, 649, 516, 410, 325, 258, 205, 163, 0\n};\n\n/*static SN76489_Context SN76489[MAX_SN76489];*/\nstatic SN76489_Context* LastChipInit = NULL;\n//static unsigned short int FNumLimit;\n\n\nSN76489_Context* SN76489_Init( int PSGClockValue, int SamplingRate)\n{\n\tint i;\n\tSN76489_Context* chip = (SN76489_Context*)malloc(sizeof(SN76489_Context));\n\tif(chip)\n\t{\n\t\tchip->dClock=(float)(PSGClockValue & 0x7FFFFFF)/16/SamplingRate;\n\t\t\n\t\tSN76489_SetMute(chip, MUTE_ALLON);\n\t\tSN76489_Config(chip, /*MUTE_ALLON,*/ FB_SEGAVDP, SRW_SEGAVDP, 1);\n\t\t\n\t\tfor( i = 0; i <= 3; i++ )\n\t\t\tcentre_panning(chip->panning[i]);\n\t\t//SN76489_Reset(chip);\n\t\t\n\t\tif ((PSGClockValue & 0x80000000) && LastChipInit != NULL)\n\t\t{\n\t\t\t// Activate special NeoGeoPocket Mode\n\t\t\tLastChipInit->NgpFlags = 0x80 | 0x00;\n\t\t\tchip->NgpFlags = 0x80 | 0x01;\n\t\t\tchip->NgpChip2 = LastChipInit;\n\t\t\tLastChipInit->NgpChip2 = chip;\n\t\t\tLastChipInit = NULL;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tchip->NgpFlags = 0x00;\n\t\t\tchip->NgpChip2 = NULL;\n\t\t\tLastChipInit = chip;\n\t\t}\n\t}\n\treturn chip;\n}\n\nvoid SN76489_Reset(SN76489_Context* chip)\n{\n\tint i;\n\n\tchip->PSGStereo = 0xFF;\n\n\tfor( i = 0; i <= 3; i++ )\n\t{\n\t\t/* Initialise PSG state */\n\t\tchip->Registers[2*i] = 1;\t\t /* tone freq=1 */\n\t\tchip->Registers[2*i+1] = 0xf;\t /* vol=off */\n\t\tchip->NoiseFreq = 0x10;\n\n\t\t/* Set counters to 0 */\n\t\tchip->ToneFreqVals[i] = 0;\n\n\t\t/* Set flip-flops to 1 */\n\t\tchip->ToneFreqPos[i] = 1;\n\n\t\t/* Set intermediate positions to do-not-use value */\n\t\tchip->IntermediatePos[i] = FLT_MIN;\n\n\t\t/* Set panning to centre */\n\t\t//centre_panning( chip->panning[i] );\n\t}\n\n\tchip->LatchedRegister = 0;\n\n\t/* Initialise noise generator */\n\tchip->NoiseShiftRegister = NoiseInitialState;\n\n\t/* Zero clock */\n\tchip->Clock = 0;\n}\n\nvoid SN76489_Shutdown(SN76489_Context* chip)\n{\n\tfree(chip);\n}\n\nvoid SN76489_Config(SN76489_Context* chip, /*int mute,*/ int feedback, int sr_width, int boost_noise)\n{\n\t//chip->Mute = mute;\n\tchip->WhiteNoiseFeedback = feedback;\n\tchip->SRWidth = sr_width;\n}\n\n/*\nvoid SN76489_SetContext(int which, uint8 *data)\n{\n\tmemcpy( &SN76489[which], data, sizeof(SN76489_Context) );\n}\n\nvoid SN76489_GetContext(int which, uint8 *data)\n{\n\tmemcpy( data, &SN76489[which], sizeof(SN76489_Context) );\n}\n\nuint8 *SN76489_GetContextPtr(int which)\n{\n\treturn (uint8 *)&SN76489[which];\n}\n\nint SN76489_GetContextSize(void)\n{\n\treturn sizeof(SN76489_Context);\n}\n*/\nvoid SN76489_Write(SN76489_Context* chip, int data)\n{\n\tif ( data & 0x80 )\n\t{\n\t\t/* Latch/data byte  %1 cc t dddd */\n\t\tchip->LatchedRegister = ( data >> 4 ) & 0x07;\n\t\tchip->Registers[chip->LatchedRegister] =\n\t\t\t( chip->Registers[chip->LatchedRegister] & 0x3f0 ) /* zero low 4 bits */\n\t\t\t| ( data & 0xf );                            /* and replace with data */\n\t} else {\n\t\t/* Data byte        %0 - dddddd */\n\t\tif ( !( chip->LatchedRegister % 2 ) && ( chip->LatchedRegister < 5 ) )\n\t\t\t/* Tone register */\n\t\t\tchip->Registers[chip->LatchedRegister] =\n\t\t\t\t( chip->Registers[chip->LatchedRegister] & 0x00f) /* zero high 6 bits */\n\t\t\t\t| ( ( data & 0x3f ) << 4 );                 /* and replace with data */\n\t\telse\n\t\t\t/* Other register */\n\t\t\tchip->Registers[chip->LatchedRegister]=data&0x0f; /* Replace with data */\n\t}\n\tswitch (chip->LatchedRegister) {\n\tcase 0:\n\tcase 2:\n\tcase 4: /* Tone channels */\n\t\tif ( chip->Registers[chip->LatchedRegister] == 0 )\n\t\t\tchip->Registers[chip->LatchedRegister] = 1; /* Zero frequency changed to 1 to avoid div/0 */\n\t\tbreak;\n\tcase 6: /* Noise */\n\t\tchip->NoiseShiftRegister = NoiseInitialState;        /* reset shift register */\n\t\tchip->NoiseFreq = 0x10 << ( chip->Registers[6] & 0x3 ); /* set noise signal generator frequency */\n\t\tbreak;\n\t}\n}\n\nvoid SN76489_GGStereoWrite(SN76489_Context* chip, int data)\n{\n\tchip->PSGStereo=data;\n}\n\n//void SN76489_Update(SN76489_Context* chip, INT16 **buffer, int length)\nvoid SN76489_Update(SN76489_Context* chip, INT32 **buffer, int length)\n{\n\tint i, j;\n\tint NGPMode;\n\tSN76489_Context* chip2;\n\tSN76489_Context* chip_t;\n\tSN76489_Context* chip_n;\n\n\tNGPMode = (chip->NgpFlags >> 7) & 0x01;\n\tif (! NGPMode)\n\t{\n\t\tchip2 = NULL;\n\t\tchip_t = chip_n = chip;\n\t}\n\telse\n\t{\n\t\tchip2 = (SN76489_Context*)chip->NgpChip2;\n\t\tif (! (chip->NgpFlags & 0x01))\n\t\t{\n\t\t\tchip_t = chip;\n\t\t\tchip_n = chip2;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tchip_t = chip2;\n\t\t\tchip_n = chip;\n\t\t}\n\t}\n\t\n\tfor( j = 0; j < length; j++ )\n\t{\n\t\t/* Tone channels */\n\t\tfor ( i = 0; i <= 2; ++i )\n\t\t\tif ( (chip_t->Mute >> i) & 1 )\n\t\t\t{\n\t\t\t\tif ( chip_t->IntermediatePos[i] != FLT_MIN )\n\t\t\t\t\t/* Intermediate position (antialiasing) */\n\t\t\t\t\tchip->Channels[i] = (short)( PSGVolumeValues[chip->Registers[2 * i + 1]] * chip_t->IntermediatePos[i] );\n\t\t\t\telse\n\t\t\t\t\t/* Flat (no antialiasing needed) */\n\t\t\t\t\tchip->Channels[i]= PSGVolumeValues[chip->Registers[2 * i + 1]] * chip_t->ToneFreqPos[i];\n\t\t\t}\n\t\t\telse\n\t\t\t\t/* Muted channel */\n\t\t\t\tchip->Channels[i] = 0;\n\n\t\t/* Noise channel */\n\t\tif ( (chip_t->Mute >> 3) & 1 )\n\t\t{\n\t\t\t//chip->Channels[3] = PSGVolumeValues[chip->Registers[7]] * ( chip_n->NoiseShiftRegister & 0x1 ) * 2; /* double noise volume */\n\t\t\t// Now the noise is bipolar, too. -Valley Bell\n\t\t\tchip->Channels[3] = PSGVolumeValues[chip->Registers[7]] * (( chip_n->NoiseShiftRegister & 0x1 ) * 2 - 1);\n\t\t\t// due to the way the white noise works here, it seems twice as loud as it should be\n\t\t\tif (chip->Registers[6] & 0x4 )\n\t\t\t\tchip->Channels[3] >>= 1;\n\t\t}\n\t\telse\n\t\t\tchip->Channels[i] = 0;\n\n\t\t// Build stereo result into buffer\n\t\tbuffer[0][j] = 0;\n\t\tbuffer[1][j] = 0;\n\t\tif (! chip->NgpFlags)\n\t\t{\n\t\t\t// For all 4 channels\n\t\t\tfor ( i = 0; i <= 3; ++i )\n\t\t\t{\n\t\t\t\tif ( ( ( chip->PSGStereo >> i ) & 0x11 ) == 0x11 )\n\t\t\t\t{\n\t\t\t\t\t// no GG stereo for this channel\n\t\t\t\t\tif ( chip->panning[i][0] == 1.0f )\n\t\t\t\t\t{\n\t\t\t\t\t\tbuffer[0][j] += chip->Channels[i]; // left\n\t\t\t\t\t\tbuffer[1][j] += chip->Channels[i]; // right\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tbuffer[0][j] += (INT32)( chip->panning[i][0] * chip->Channels[i] ); // left\n\t\t\t\t\t\tbuffer[1][j] += (INT32)( chip->panning[i][1] * chip->Channels[i] ); // right\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// GG stereo overrides panning\n\t\t\t\t\tbuffer[0][j] += ( chip->PSGStereo >> (i+4) & 0x1 ) * chip->Channels[i]; // left\n\t\t\t\t\tbuffer[1][j] += ( chip->PSGStereo >>  i    & 0x1 ) * chip->Channels[i]; // right\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (! (chip->NgpFlags & 0x01))\n\t\t\t{\n\t\t\t\t// For all 3 tone channels\n\t\t\t\tfor (i = 0; i < 3; i ++)\n\t\t\t\t{\n\t\t\t\t\tbuffer[0][j] += (chip->PSGStereo >> (i+4) & 0x1 ) * chip ->Channels[i]; // left\n\t\t\t\t\tbuffer[1][j] += (chip->PSGStereo >>  i    & 0x1 ) * chip2->Channels[i]; // right\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// noise channel\n\t\t\t\ti = 3;\n\t\t\t\tbuffer[0][j] += (chip->PSGStereo >> (i+4) & 0x1 ) * chip2->Channels[i]; // left\n\t\t\t\tbuffer[1][j] += (chip->PSGStereo >>  i    & 0x1 ) * chip ->Channels[i]; // right\n\t\t\t}\n\t\t}\n\n\t\t/* Increment clock by 1 sample length */\n\t\tchip->Clock += chip->dClock;\n\t\tchip->NumClocksForSample = (int)chip->Clock;  /* truncate */\n\t\tchip->Clock -= chip->NumClocksForSample;      /* remove integer part */\n\t\n\t\t/* Decrement tone channel counters */\n\t\tfor ( i = 0; i <= 2; ++i )\n\t\t\tchip->ToneFreqVals[i] -= chip->NumClocksForSample;\n\t \n\t\t/* Noise channel: match to tone2 or decrement its counter */\n\t\tif ( chip->NoiseFreq == 0x80 )\n\t\t\tchip->ToneFreqVals[3] = chip->ToneFreqVals[2];\n\t\telse\n\t\t\tchip->ToneFreqVals[3] -= chip->NumClocksForSample;\n\t\n\t\t/* Tone channels: */\n\t\tfor ( i = 0; i <= 2; ++i ) {\n\t\t\tif ( chip->ToneFreqVals[i] <= 0 ) {   /* If the counter gets below 0... */\n\t\t\t\tif (chip->Registers[i*2]>=PSG_CUTOFF) {\n\t\t\t\t\t/* For tone-generating values, calculate how much of the sample is + and how much is - */\n\t\t\t\t\t/* This is optimised into an even more confusing state than it was in the first place... */\n\t\t\t\t\tchip->IntermediatePos[i] = ( chip->NumClocksForSample - chip->Clock + 2 * chip->ToneFreqVals[i] ) * chip->ToneFreqPos[i] / ( chip->NumClocksForSample + chip->Clock );\n\t\t\t\t\t/* Flip the flip-flop */\n\t\t\t\t\tchip->ToneFreqPos[i] = -chip->ToneFreqPos[i];\n\t\t\t\t} else {\n\t\t\t\t\t/* stuck value */\n\t\t\t\t\tchip->ToneFreqPos[i] = 1;\n\t\t\t\t\tchip->IntermediatePos[i] = FLT_MIN;\n\t\t\t\t}\n\t\t\t\tchip->ToneFreqVals[i] += chip->Registers[i*2] * ( chip->NumClocksForSample / chip->Registers[i*2] + 1 );\n\t\t\t}\n\t\t\telse\n\t\t\t\t/* signal no antialiasing needed */\n\t\t\t\tchip->IntermediatePos[i] = FLT_MIN;\n\t\t}\n\t\n\t\t/* Noise channel */\n\t\tif ( chip->ToneFreqVals[3] <= 0 ) {\n\t\t\t/* If the counter gets below 0... */\n\t\t\t/* Flip the flip-flop */\n\t\t\tchip->ToneFreqPos[3] = -chip->ToneFreqPos[3];\n\t\t\tif (chip->NoiseFreq != 0x80)\n\t\t\t\t/* If not matching tone2, decrement counter */\n\t\t\t\tchip->ToneFreqVals[3] += chip->NoiseFreq * ( chip->NumClocksForSample / chip->NoiseFreq + 1 );\n\t\t\tif (chip->ToneFreqPos[3] == 1) {\n\t\t\t\t/* On the positive edge of the square wave (only once per cycle) */\n\t\t\t\tint Feedback;\n\t\t\t\tif ( chip->Registers[6] & 0x4 ) {\n\t\t\t\t\t/* White noise */\n\t\t\t\t\t/* Calculate parity of fed-back bits for feedback */\n\t\t\t\t\tswitch (chip->WhiteNoiseFeedback) {\n\t\t\t\t\t\t/* Do some optimised calculations for common (known) feedback values */\n\t\t\t\t\tcase 0x0003: /* SC-3000, BBC %00000011 */\n\t\t\t\t\tcase 0x0009: /* SMS, GG, MD  %00001001 */\n\t\t\t\t\t\t/* If two bits fed back, I can do Feedback=(nsr & fb) && (nsr & fb ^ fb) */\n\t\t\t\t\t\t/* since that's (one or more bits set) && (not all bits set) */\n\t\t\t\t\t\tFeedback = ( ( chip->NoiseShiftRegister & chip->WhiteNoiseFeedback )\n\t\t\t\t\t\t\t&& ( (chip->NoiseShiftRegister & chip->WhiteNoiseFeedback ) ^ chip->WhiteNoiseFeedback ) );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t/* Default handler for all other feedback values */\n\t\t\t\t\t\t/* XOR fold bits into the final bit */\n\t\t\t\t\t\tFeedback = chip->NoiseShiftRegister & chip->WhiteNoiseFeedback;\n\t\t\t\t\t\tFeedback ^= Feedback >> 8;\n\t\t\t\t\t\tFeedback ^= Feedback >> 4;\n\t\t\t\t\t\tFeedback ^= Feedback >> 2;\n\t\t\t\t\t\tFeedback ^= Feedback >> 1;\n\t\t\t\t\t\tFeedback &= 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else\t  /* Periodic noise */\n\t\t\t\t\tFeedback=chip->NoiseShiftRegister&1;\n\n\t\t\t\tchip->NoiseShiftRegister=(chip->NoiseShiftRegister>>1) | (Feedback << (chip->SRWidth-1));\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*void SN76489_UpdateOne(SN76489_Context* chip, int *l, int *r)\n{\n  INT16 tl,tr;\n  INT16 *buff[2] = { &tl, &tr };\n  SN76489_Update( chip, buff, 1 );\n  *l = tl;\n  *r = tr;\n}*/\n\n\n/*int  SN76489_GetMute(SN76489_Context* chip)\n{\n  return chip->Mute;\n}*/\n\nvoid SN76489_SetMute(SN76489_Context* chip, int val)\n{\n  chip->Mute=val;\n}\n\nvoid SN76489_SetPanning(SN76489_Context* chip, int ch0, int ch1, int ch2, int ch3)\n{\n\tcalc_panning( chip->panning[0], ch0 );\n\tcalc_panning( chip->panning[1], ch1 );\n\tcalc_panning( chip->panning[2], ch2 );\n\tcalc_panning( chip->panning[3], ch3 );\n}\n"
  },
  {
    "path": "VGMPlay/chips/sn76489.h",
    "content": "#ifndef _SN76489_H_\n#define _SN76489_H_\n\n// all these defines are defined in mamedef.h, but GCC's #ifdef doesn't seem to know typedefs\n/*#ifndef INT32\n#define INT32 signed long\n#endif\n#ifndef UINT16\n#define UINT16 unsigned short\n#endif\n#ifndef INT16\n#define INT16 signed short\n#endif\n#ifndef INT8\n#define INT8 signed char\n#endif*/\n#ifndef uint8\n#define uint8 signed char\n#endif\n\n\n/*#define MAX_SN76489     4*/\n\n/*\n    More testing is needed to find and confirm feedback patterns for\n    SN76489 variants and compatible chips.\n*/\nenum feedback_patterns {\n    FB_BBCMICRO =   0x8005, /* Texas Instruments TMS SN76489N (original) from BBC Micro computer */\n    FB_SC3000   =   0x0006, /* Texas Instruments TMS SN76489AN (rev. A) from SC-3000H computer */\n    FB_SEGAVDP  =   0x0009, /* SN76489 clone in Sega's VDP chips (315-5124, 315-5246, 315-5313, Game Gear) */\n};\n\nenum sr_widths {\n  SRW_SC3000BBCMICRO  = 15,\n  SRW_SEGAVDP = 16\n};\n\nenum volume_modes {\n    VOL_TRUNC   =   0,      /* Volume levels 13-15 are identical */\n    VOL_FULL    =   1,      /* Volume levels 13-15 are unique */\n};\n\nenum mute_values {\n    MUTE_ALLOFF =   0,      /* All channels muted */\n    MUTE_TONE1  =   1,      /* Tone 1 mute control */\n    MUTE_TONE2  =   2,      /* Tone 2 mute control */\n    MUTE_TONE3  =   4,      /* Tone 3 mute control */\n    MUTE_NOISE  =   8,      /* Noise mute control */\n    MUTE_ALLON  =   15,     /* All channels enabled */\n};\n\ntypedef struct\n{\n    int Mute; // per-channel muting\n    int BoostNoise; // double noise volume when non-zero\n    \n    /* Variables */\n    float Clock;\n    float dClock;\n    int PSGStereo;\n    int NumClocksForSample;\n    int WhiteNoiseFeedback;\n    int SRWidth;\n    \n    /* PSG registers: */\n    int Registers[8];        /* Tone, vol x4 */\n    int LatchedRegister;\n    int NoiseShiftRegister;\n    int NoiseFreq;            /* Noise channel signal generator frequency */\n    \n    /* Output calculation variables */\n    int ToneFreqVals[4];      /* Frequency register values (counters) */\n    int ToneFreqPos[4];        /* Frequency channel flip-flops */\n    int Channels[4];          /* Value of each channel, before stereo is applied */\n    float IntermediatePos[4];   /* intermediate values used at boundaries between + and - (does not need double accuracy)*/\n\n    float panning[4][2];            /* fake stereo */\n\n\tint NgpFlags;\t\t/* bit 7 - NGP Mode on/off, bit 0 - is 2nd NGP chip */\n\tvoid* NgpChip2;\n} SN76489_Context;\n\n/* Function prototypes */\nSN76489_Context* SN76489_Init(int PSGClockValue, int SamplingRate);\nvoid SN76489_Reset(SN76489_Context* chip);\nvoid SN76489_Shutdown(SN76489_Context* chip);\nvoid SN76489_Config(SN76489_Context* chip, /*int mute,*/ int feedback, int sw_width, int boost_noise);\n/*\nvoid SN76489_SetContext(SN76489_Context* chip, uint8 *data);\nvoid SN76489_GetContext(SN76489_Context* chip, uint8 *data);\nuint8 *SN76489_GetContextPtr(int chip);\nint SN76489_GetContextSize(void);*/\nvoid SN76489_Write(SN76489_Context* chip, int data);\nvoid SN76489_GGStereoWrite(SN76489_Context* chip, int data);\n//void SN76489_Update(SN76489_Context* chip, INT16 **buffer, int length);\nvoid SN76489_Update(SN76489_Context* chip, INT32 **buffer, int length);\n\n/* Non-standard getters and setters */\n//int  SN76489_GetMute(SN76489_Context* chip);\nvoid SN76489_SetMute(SN76489_Context* chip, int val);\n\nvoid SN76489_SetPanning(SN76489_Context* chip, int ch0, int ch1, int ch2, int ch3);\n\n/* and a non-standard data getter */\n//void SN76489_UpdateOne(SN76489_Context* chip, int *l, int *r);\n\n#endif /* _SN76489_H_ */\n"
  },
  {
    "path": "VGMPlay/chips/sn76496.c",
    "content": "/***************************************************************************\n\n  sn76496.c\n  by Nicola Salmoria\n  with contributions by others\n\n  Routines to emulate the:\n  Texas Instruments SN76489, SN76489A, SN76494/SN76496\n  ( Also known as, or at least compatible with, the TMS9919 and SN94624.)\n  and the Sega 'PSG' used on the Master System, Game Gear, and Megadrive/Genesis\n  This chip is known as the Programmable Sound Generator, or PSG, and is a 4\n  channel sound generator, with three squarewave channels and a noise/arbitrary\n  duty cycle channel.\n\n  Noise emulation for all verified chips should be accurate:\n\n  ** SN76489 uses a 15-bit shift register with taps on bits D and E, output on E,\n  XOR function.\n  It uses a 15-bit ring buffer for periodic noise/arbitrary duty cycle.\n  Its output is inverted.\n  ** SN94624 is the same as SN76489 but lacks the /8 divider on its clock input.\n  ** SN76489A uses a 15-bit shift register with taps on bits D and E, output on F,\n  XOR function.\n  It uses a 15-bit ring buffer for periodic noise/arbitrary duty cycle.\n  Its output is not inverted.\n  ** SN76494 is the same as SN76489A but lacks the /8 divider on its clock input.\n  ** SN76496 is identical in operation to the SN76489A, but the audio input is\n  documented.\n  All the TI-made PSG chips have an audio input line which is mixed with the 4 channels\n  of output. (It is undocumented and may not function properly on the sn76489, 76489a\n  and 76494; the sn76489a input is mentioned in datasheets for the tms5200)\n  All the TI-made PSG chips act as if the frequency was set to 0x400 if 0 is\n  written to the frequency register.\n  ** Sega Master System III/MD/Genesis PSG uses a 16-bit shift register with taps\n  on bits C and F, output on F\n  It uses a 16-bit ring buffer for periodic noise/arbitrary duty cycle.\n  (whether it uses an XOR or XNOR needs to be verified, assumed XOR)\n  (whether output is inverted or not needs to be verified, assumed to be inverted)\n  ** Sega Game Gear PSG is identical to the SMS3/MD/Genesis one except it has an\n  extra register for mapping which channels go to which speaker.\n  The register, connected to a z80 port, means:\n  for bits 7  6  5  4  3  2  1  0\n           L3 L2 L1 L0 R3 R2 R1 R0\n  Noise is an XOR function, and audio output is negated before being output.\n  All the Sega-made PSG chips act as if the frequency was set to 0 if 0 is written\n  to the frequency register.\n  ** NCR7496 (as used on the Tandy 1000) is similar to the SN76489 but with a\n  different noise LFSR patttern: taps on bits A and E, output on E\n  It uses a 15-bit ring buffer for periodic noise/arbitrary duty cycle.\n  (all this chip's info needs to be verified)\n\n  28/03/2005 : Sebastien Chevalier\n  Update th SN76496Write func, according to SN76489 doc found on SMSPower.\n   - On write with 0x80 set to 0, when LastRegister is other then TONE,\n   the function is similar than update with 0x80 set to 1\n\n  23/04/2007 : Lord Nightmare\n  Major update, implement all three different noise generation algorithms and a\n  set_variant call to discern among them.\n\n  28/04/2009 : Lord Nightmare\n  Add READY line readback; cleaned up struct a bit. Cleaned up comments.\n  Add more TODOs. Fixed some unsaved savestate related stuff.\n\n  04/11/2009 : Lord Nightmare\n  Changed the way that the invert works (it now selects between XOR and XNOR\n  for the taps), and added R->OldNoise to simulate the extra 0 that is always\n  output before the noise LFSR contents are after an LFSR reset.\n  This fixes SN76489/A to match chips. Added SN94624.\n\n  14/11/2009 : Lord Nightmare\n  Removed STEP mess, vastly simplifying the code. Made output bipolar rather\n  than always above the 0 line, but disabled that code due to pending issues.\n\n  16/11/2009 : Lord Nightmare\n  Fix screeching in regulus: When summing together four equal channels, the\n  size of the max amplitude per channel should be 1/4 of the max range, not\n  1/3. Added NCR7496.\n\n  18/11/2009 : Lord Nightmare\n  Modify Init functions to support negating the audio output. The gamegear\n  psg does this. Change gamegear and sega psgs to use XOR rather than XNOR\n  based on testing. Got rid of R->OldNoise and fixed taps accordingly.\n  Added stereo support for game gear.\n\n  15/01/2010 : Lord Nightmare\n  Fix an issue with SN76489 and SN76489A having the wrong periodic noise periods.\n  Note that properly emulating the noise cycle bit timing accurately may require\n  extensive rewriting.\n\n  24/01/2010: Lord Nightmare\n  Implement periodic noise as forcing one of the XNOR or XOR taps to 1 or 0 respectively.\n  Thanks to PlgDavid for providing samples which helped immensely here.\n  Added true clock divider emulation, so sn94624 and sn76494 run 8x faster than\n  the others, as in real life.\n\n  15/02/2010: Lord Nightmare & Michael Zapf (additional testing by PlgDavid)\n  Fix noise period when set to mirror channel 3 and channel 3 period is set to 0 (tested on hardware for noise, wave needs tests) - MZ\n  Fix phase of noise on sn94624 and sn76489; all chips use a standard XOR, the only inversion is the output itself - LN, Plgdavid\n  Thanks to PlgDavid and Michael Zapf for providing samples which helped immensely here.\n\n  23/02/2011: Lord Nightmare & Enik\n  Made it so the Sega PSG chips have a frequency of 0 if 0 is written to the\n  frequency register, while the others have 0x400 as before. Should fix a bug\n  or two on sega games, particularly Vigilante on Sega Master System. Verified\n  on SMS hardware.\n\n  TODO: * Implement the TMS9919 - any difference to sn94624?\n        * Implement the T6W28; has registers in a weird order, needs writes\n          to be 'sanitized' first. Also is stereo, similar to game gear.\n        * Test the NCR7496; Smspower says the whitenoise taps are A and E,\n          but this needs verification on real hardware.\n        * Factor out common code so that the SAA1099 can share some code.\n        * Convert to modern device\n***************************************************************************/\n\n/* Note: I patched the core to speed the emulation up (factor 8!!)\n\tMy Pentium2 233MHz was too slow for two SN76496 chips in release mode!\n\tNow a 2xSN76496 vgm takes about 45 % CPU. */\n\n#include \"mamedef.h\"\n#ifdef _DEBUG\n#include <stdio.h>\n#endif\n//#include \"emu.h\"\n//#include \"streams.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"sn76496.h\"\n\n\n//#define MAX_OUTPUT 0x7fff\n#define MAX_OUTPUT 0x8000\n#define NOISEMODE (R->Register[6]&4)?1:0\n\n\ntypedef struct _sn76496_state sn76496_state;\nstruct _sn76496_state\n{\n\t//sound_stream * Channel;\n\tINT32 VolTable[16];\t/* volume table (for 4-bit to db conversion)*/\n\tINT32 Register[8];\t/* registers */\n\tINT32 LastRegister;\t/* last register written */\n\tINT32 Volume[4];\t/* db volume of voice 0-2 and noise */\n\tUINT32 RNG;\t\t\t/* noise generator LFSR*/\n\tINT32 ClockDivider;\t/* clock divider */\n\tINT32 CurrentClock;\n\tINT32 FeedbackMask;\t/* mask for feedback */\n\tINT32 WhitenoiseTap1;\t/* mask for white noise tap 1 (higher one, usually bit 14) */\n\tINT32 WhitenoiseTap2;\t/* mask for white noise tap 2 (lower one, usually bit 13)*/\n\tINT32 Negate;\t\t/* output negate flag */\n\tINT32 Stereo;\t\t/* whether we're dealing with stereo or not */\n\tINT32 StereoMask;\t/* the stereo output mask */\n\tINT32 Period[4];\t/* Length of 1/2 of waveform */\n\tINT32 Count[4];\t\t/* Position within the waveform */\n\tINT32 Output[4];\t/* 1-bit output of each channel, pre-volume */\n\tINT32 CyclestoREADY;/* number of cycles until the READY line goes active */\n\tINT32 Freq0IsMax;\t/* flag for if frequency zero acts as if it is one more than max (0x3ff+1) or if it acts like 0 */\n\tUINT32 MuteMsk[4];\n\tUINT8 NgpFlags;\t\t/* bit 7 - NGP Mode on/off, bit 0 - is 2nd NGP chip */\n\tsn76496_state* NgpChip2;\t/* Pointer to other Chip */\n};\n\n\nstatic sn76496_state* LastChipInit = NULL;\nstatic unsigned short int FNumLimit;\n\n/*INLINE sn76496_state *get_safe_token(running_device *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == SN76496 ||\n\t\t   device->type() == SN76489 ||\n\t\t   device->type() == SN76489A ||\n\t\t   device->type() == SN76494 ||\n\t\t   device->type() == SN94624 ||\n\t\t   device->type() == NCR7496 ||\n\t\t   device->type() == GAMEGEAR ||\n\t\t   device->type() == SMSIII);\n\treturn (sn76496_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n//READ_LINE_DEVICE_HANDLER( sn76496_ready_r )\nUINT8 sn76496_ready_r(void *chip, offs_t offset)\n{\n\t//sn76496_state *R = get_safe_token(device);\n\tsn76496_state *R = (sn76496_state*)chip;\n\t//stream_update(R->Channel);\n\treturn (R->CyclestoREADY? 0 : 1);\n}\n\n//WRITE8_DEVICE_HANDLER( sn76496_stereo_w )\nvoid sn76496_stereo_w(void *chip, offs_t offset, UINT8 data)\n{\n\t//sn76496_state *R = get_safe_token(device);\n\tsn76496_state *R = (sn76496_state*)chip;\n\t//stream_update(R->Channel);\n\tif (R->Stereo) R->StereoMask = data;\n#ifdef _DEBUG\n\telse logerror(\"Call to stereo write with mono chip!\\n\");\n#endif\n}\n\n//WRITE8_DEVICE_HANDLER( sn76496_w )\nvoid sn76496_write_reg(void *chip, offs_t offset, UINT8 data)\n{\n\t//sn76496_state *R = get_safe_token(device);\n\tsn76496_state *R = (sn76496_state*)chip;\n\tint n, r, c;\n\n\n\t/* update the output buffer before changing the registers */\n\t//stream_update(R->Channel);\n\n\t/* set number of cycles until READY is active; this is always one\n           'sample', i.e. it equals the clock divider exactly; until the\n           clock divider is fully supported, we delay until one sample has\n           played. The fact that this below is '2' and not '1' is because\n           of a ?race condition? in the mess crvision driver, where after\n           any sample is played at all, no matter what, the cycles_to_ready\n           ends up never being not ready, unless this value is greater than\n           1. Once the full clock divider stuff is written, this should no\n           longer be an issue. */\n\tR->CyclestoREADY = 2;\n\n\tif (data & 0x80)\n\t{\n\t\tr = (data & 0x70) >> 4;\n\t\tR->LastRegister = r;\n\t\tR->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f);\n\t}\n\telse\n    {\n\t\tr = R->LastRegister;\n\t}\n\tc = r/2;\n\tswitch (r)\n\t{\n\t\tcase 0:\t/* tone 0 : frequency */\n\t\tcase 2:\t/* tone 1 : frequency */\n\t\tcase 4:\t/* tone 2 : frequency */\n\t\t    if ((data & 0x80) == 0) R->Register[r] = (R->Register[r] & 0x0f) | ((data & 0x3f) << 4);\n\t\t\tif ((R->Register[r] != 0) || (R->Freq0IsMax == 0)) R->Period[c] = R->Register[r];\n\t\t\telse R->Period[c] = 0x400;\n\t\t\tif (r == 4)\n\t\t\t{\n\t\t\t\t/* update noise shift frequency */\n\t\t\t\tif ((R->Register[6] & 0x03) == 0x03)\n\t\t\t\t\tR->Period[3] = 2 * R->Period[2];\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 1:\t/* tone 0 : volume */\n\t\tcase 3:\t/* tone 1 : volume */\n\t\tcase 5:\t/* tone 2 : volume */\n\t\tcase 7:\t/* noise  : volume */\n\t\t\tR->Volume[c] = R->VolTable[data & 0x0f];\n\t\t\tif ((data & 0x80) == 0) R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f);\n\t\t\t\n\t\t//\t// \"Every volume write resets the waveform to High level.\", TmEE, 2012-11-24 on SMSPower\n\t\t//\tR->Output[c] = 1;\n\t\t//\tR->Count[c] = R->Period[c];\n\t\t//\tdisabled for now - sounds awful\n\t\t\tbreak;\n\t\tcase 6:\t/* noise  : frequency, mode */\n\t\t\t{\n#ifdef _DEBUG\n\t\t\t\t//if ((data & 0x80) == 0) logerror(\"sn76489: write to reg 6 with bit 7 clear; data was %03x, new write is %02x! report this to LN!\\n\", R->Register[6], data);\n#endif\n\t\t\t\tif ((data & 0x80) == 0) R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f);\n\t\t\t\tn = R->Register[6];\n\t\t\t\t/* N/512,N/1024,N/2048,Tone #3 output */\n\t\t\t\tR->Period[3] = ((n&3) == 3) ? 2 * R->Period[2] : (1 << (5+(n&3)));\n\t\t\t\tR->RNG = R->FeedbackMask;\n\t\t\t}\n\t\t\tbreak;\n\t}\n}\n\n//static STREAM_UPDATE( SN76496Update )\nvoid SN76496Update(void *chip, stream_sample_t **outputs, int samples)\n{\n\tint i;\n\t//sn76496_state *R = (sn76496_state *)param;\n\tsn76496_state *R = (sn76496_state*)chip;\n\tsn76496_state *R2;\n\tstream_sample_t *lbuffer = outputs[0];\n\t//stream_sample_t *rbuffer = (R->Stereo)?outputs[1]:NULL;\n\tstream_sample_t *rbuffer = outputs[1];\n\tINT32 out = 0;\n\tINT32 out2 = 0;\n\tINT32 vol[4];\n\tUINT8 NGPMode;\n\tINT32 ggst[2];\n\n\tNGPMode = (R->NgpFlags >> 7) & 0x01;\n\tR2 = R->NgpChip2;\n\n\tif (! NGPMode)\n\t{\n\t\t// Speed Hack\n\t\tout = 0;\n\t\tfor (i = 0; i < 3; i ++)\n\t\t{\n\t\t\tif (R->Period[i] || R->Volume[i])\n\t\t\t{\n\t\t\t\tout = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (R->Volume[3])\n\t\t\tout = 1;\n\t\tif (! out)\n\t\t{\n\t\t\tmemset(lbuffer, 0x00, sizeof(stream_sample_t) * samples);\n\t\t\tmemset(rbuffer, 0x00, sizeof(stream_sample_t) * samples);\n\t\t\treturn;\n\t\t}\n\t}\n\t\n\tggst[0] = 0x01;\n\tggst[1] = 0x01;\n\twhile (samples > 0)\n\t{\n\t\t/* Speed Patch */\n\t\t/*// clock chip once\n\t\tif (R->CurrentClock > 0) // not ready for new divided clock\n\t\t{\n\t\t\tR->CurrentClock--;\n\t\t}\n\t\telse // ready for new divided clock, make a new sample\n\t\t{\n\t\t\tR->CurrentClock = R->ClockDivider-1;*/\n\t\t\t/* decrement Cycles to READY by one */\n\t\t\tif (R->CyclestoREADY >0) R->CyclestoREADY--;\n\n\t\t\t// handle channels 0,1,2\n\t\t\tfor (i = 0;i < 3;i++)\n\t\t\t{\n\t\t\t\tR->Count[i]--;\n\t\t\t\tif (R->Count[i] <= 0)\n\t\t\t\t{\n\t\t\t\t\tR->Output[i] ^= 1;\n\t\t\t\t\tR->Count[i] = R->Period[i];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// handle channel 3\n\t\t\tR->Count[3]--;\n\t\t\tif (R->Count[3] <= 0)\n\t\t\t{\n\t\t\t// if noisemode is 1, both taps are enabled\n\t\t\t// if noisemode is 0, the lower tap, whitenoisetap2, is held at 0\n\t\t\t\tif (((R->RNG & R->WhitenoiseTap1)?1:0) ^ ((((R->RNG & R->WhitenoiseTap2)?1:0))*(NOISEMODE)))\n\t\t\t\t{\n\t\t\t\t\tR->RNG >>= 1;\n\t\t\t\t\tR->RNG |= R->FeedbackMask;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tR->RNG >>= 1;\n\t\t\t\t}\n\t\t\t\tR->Output[3] = R->RNG & 1;\n\n\t\t\t\tR->Count[3] = R->Period[3];\n\t\t\t}\n\t\t//}\n\n\n\t\t/*if (R->Stereo)\n\t\t{\n\t\t\tout = (((R->StereoMask&0x10)&&R->Output[0])?R->Volume[0]:0)\n\t\t\t\t+ (((R->StereoMask&0x20)&&R->Output[1])?R->Volume[1]:0)\n\t\t\t\t+ (((R->StereoMask&0x40)&&R->Output[2])?R->Volume[2]:0)\n\t\t\t\t+ (((R->StereoMask&0x80)&&R->Output[3])?R->Volume[3]:0);\n\n\t\t\tout2 = (((R->StereoMask&0x1)&&R->Output[0])?R->Volume[0]:0)\n\t\t\t\t+ (((R->StereoMask&0x2)&&R->Output[1])?R->Volume[1]:0)\n\t\t\t\t+ (((R->StereoMask&0x4)&&R->Output[2])?R->Volume[2]:0)\n\t\t\t\t+ (((R->StereoMask&0x8)&&R->Output[3])?R->Volume[3]:0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tout = (R->Output[0]?R->Volume[0]:0)\n\t\t\t\t+(R->Output[1]?R->Volume[1]:0)\n\t\t\t\t+(R->Output[2]?R->Volume[2]:0)\n\t\t\t\t+(R->Output[3]?R->Volume[3]:0);\n\t\t}*/\n\n\t\t// --- CUSTOM CODE START --\n\t\tout = out2 = 0;\n\t\tif (! R->NgpFlags)\n\t\t{\n\t\t\tfor (i = 0; i < 4; i ++)\n\t\t\t{\n\t\t\t\t// --- Preparation Start ---\n\t\t\t\t// Bipolar output\n\t\t\t\tvol[i] = R->Output[i] ? +1 : -1;\n\t\t\t\t\n\t\t\t\t// Disable high frequencies (> SampleRate / 2) for tone channels\n\t\t\t\t// Freq. 0/1 isn't disabled becaus it would also disable PCM\n\t\t\t\tif (i != 3)\n\t\t\t\t{\n\t\t\t\t\tif (R->Period[i] <= FNumLimit && R->Period[i] > 1)\n\t\t\t\t\t\tvol[i] = 0;\n\t\t\t\t}\n\t\t\t\tvol[i] &= R->MuteMsk[i];\n\t\t\t\t// --- Preparation End ---\n\t\t\t\t\n\t\t\t\tif (R->Stereo)\n\t\t\t\t{\n\t\t\t\t\tggst[0] = (R->StereoMask & (0x10 << i)) ? 0x01 : 0x00;\n\t\t\t\t\tggst[1] = (R->StereoMask & (0x01 << i)) ? 0x01 : 0x00;\n\t\t\t\t}\n\t\t\t\tif (R->Period[i] > 1 || i == 3)\n\t\t\t\t{\n\t\t\t\t\tout += vol[i] * R->Volume[i] * ggst[0];\n\t\t\t\t\tout2 += vol[i] * R->Volume[i] * ggst[1];\n\t\t\t\t}\n\t\t\t\telse if (R->MuteMsk[i])\n\t\t\t\t{\n\t\t\t\t\t// Make Bipolar Output with PCM possible\n\t\t\t\t\t//out += (2 * R->Volume[i] - R->VolTable[5]) * ggst[0];\n\t\t\t\t\t//out2 += (2 * R->Volume[i] - R->VolTable[5]) * ggst[1];\n\t\t\t\t\tout += R->Volume[i] * ggst[0];\n\t\t\t\t\tout2 += R->Volume[i] * ggst[1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (! (R->NgpFlags & 0x01))\n\t\t\t{\n\t\t\t\t// Tone Channel 1-3\n\t\t\t\tif (R->Stereo)\n\t\t\t\t{\n\t\t\t\t\tggst[0] = (R->StereoMask & (0x10 << i)) ? 0x01 : 0x00;\n\t\t\t\t\tggst[1] = (R->StereoMask & (0x01 << i)) ? 0x01 : 0x00;\n\t\t\t\t}\n\t\t\t\tfor (i = 0; i < 3; i ++)\n\t\t\t\t{\n\t\t\t\t\t// --- Preparation Start ---\n\t\t\t\t\t// Bipolar output\n\t\t\t\t\tvol[i] = R->Output[i] ? +1 : -1;\n\t\t\t\t\t\n\t\t\t\t\t// Disable high frequencies (> SampleRate / 2) for tone channels\n\t\t\t\t\t// Freq. 0 isn't disabled becaus it would also disable PCM\n\t\t\t\t\tif (R->Period[i] <= FNumLimit && R->Period[i])\n\t\t\t\t\t\tvol[i] = 0;\n\t\t\t\t\tvol[i] &= R->MuteMsk[i];\n\t\t\t\t\t// --- Preparation End ---\n\t\t\t\t\t\n\t\t\t\t\t//out += vol[i] * R->Volume[i];\n\t\t\t\t\t//out2 += vol[i] * R2->Volume[i];\n\t\t\t\t\tif (R->Period[i])\n\t\t\t\t\t{\n\t\t\t\t\t\tout += vol[i] * R->Volume[i] * ggst[0];\n\t\t\t\t\t\tout2 += vol[i] * R2->Volume[i] * ggst[1];\n\t\t\t\t\t}\n\t\t\t\t\telse if (R->MuteMsk[i])\n\t\t\t\t\t{\n\t\t\t\t\t\t// Make Bipolar Output with PCM possible\n\t\t\t\t\t\tout += R->Volume[i] * ggst[0];\n\t\t\t\t\t\tout2 += R2->Volume[i] * ggst[1];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// --- Preparation Start ---\n\t\t\t\t// Bipolar output\n\t\t\t\tvol[i] = R->Output[i] ? +1 : -1;\n\t\t\t\t\n\t\t\t\t//vol[i] &= R->MuteMsk[i];\n\t\t\t\tvol[i] &= R2->MuteMsk[i];\t// use MuteMask from chip 0\n\t\t\t\t// --- Preparation End ---\n\t\t\t\t\n\t\t\t\t// Noise Channel\n\t\t\t\tif (R->Stereo)\n\t\t\t\t{\n\t\t\t\t\tggst[0] = (R->StereoMask & 0x80) ? 0x01 : 0x00;\n\t\t\t\t\tggst[1] = (R->StereoMask & 0x08) ? 0x01 : 0x00;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tggst[0] = 0x01;\n\t\t\t\t\tggst[1] = 0x01;\n\t\t\t\t}\n\t\t\t\t//out += vol[3] * R2->Volume[3];\n\t\t\t\t//out2 += vol[3] * R->Volume[3];\n\t\t\t\tout += vol[3] * R2->Volume[3] * ggst[0];\n\t\t\t\tout2 += vol[3] * R->Volume[3] * ggst[1];\n\t\t\t}\n\t\t}\n\t\t// --- CUSTOM CODE END --\n\t\t\n\t\tif(R->Negate) { out = -out; out2 = -out2; }\n\n\t\t*(lbuffer++) = out >> 1;\t// Output is Bipolar\n\t\t//if (R->Stereo) *(rbuffer++) = out2;\n\t\t*(rbuffer++) = out2 >> 1;\n\t\tsamples--;\n\t}\n}\n\n\n\nstatic void SN76496_set_gain(sn76496_state *R,int gain)\n{\n\tint i;\n\tdouble out;\n\n\n\tgain &= 0xff;\n\n\t/* increase max output basing on gain (0.2 dB per step) */\n\tout = MAX_OUTPUT / 4; // four channels, each gets 1/4 of the total range\n\twhile (gain-- > 0)\n\t\tout *= 1.023292992;\t/* = (10 ^ (0.2/20)) */\n\n\t/* build volume table (2dB per step) */\n\tfor (i = 0;i < 15;i++)\n\t{\n\t\t/* limit volume to avoid clipping */\n\t\tif (out > MAX_OUTPUT / 4) R->VolTable[i] = MAX_OUTPUT / 4;\n\t\t//else R->VolTable[i] = out;\n\t\telse R->VolTable[i] = (INT32)(out + 0.5);\t// I like rounding\n\n\t\tout /= 1.258925412;\t/* = 10 ^ (2/20) = 2dB */\n\t}\n\tR->VolTable[15] = 0;\n}\n\n\n\n//static int SN76496_init(running_device *device, sn76496_state *R, int stereo)\nstatic int SN76496_init(int clock, sn76496_state *R, int stereo)\n{\n\tint sample_rate = clock/2;\n\tint i;\n\n\t//R->Channel = stream_create(device,0,(stereo?2:1),sample_rate,R,SN76496Update);\n\n\tfor (i = 0;i < 4;i++) R->Volume[i] = 0;\n\n\tR->LastRegister = 0;\n\tfor (i = 0;i < 8;i+=2)\n\t{\n\t\tR->Register[i] = 0;\n\t\tR->Register[i + 1] = 0x0f;\t/* volume = 0 */\n\t}\n\n\tfor (i = 0;i < 4;i++)\n\t{\n\t\tR->Output[i] = R->Period[i] = R->Count[i] = 0;\n\t\tR->MuteMsk[i] = ~0x00;\n\t}\n\n\t/* Default is SN76489A */\n\tR->ClockDivider = 8;\n\tR->FeedbackMask = 0x10000;     /* mask for feedback */\n\tR->WhitenoiseTap1 = 0x04;   /* mask for white noise tap 1*/\n\tR->WhitenoiseTap2 = 0x08;   /* mask for white noise tap 2*/\n\tR->Negate = 0; /* channels are not negated */\n\tR->Stereo = stereo; /* depends on init */\n\tR->CyclestoREADY = 1; /* assume ready is not active immediately on init. is this correct?*/\n\tR->StereoMask = 0xFF; /* all channels enabled */\n\tR->Freq0IsMax = 1; /* frequency set to 0 results in freq = 0x400 rather than 0 */\n\n\tR->RNG = R->FeedbackMask;\n\tR->Output[3] = R->RNG & 1;\n\n\tR->NgpFlags = 0x00;\n\tR->NgpChip2 = NULL;\n\n\t//return 0;\n\treturn sample_rate;\n}\n\n\n//static void generic_start(running_device *device, int feedbackmask, int noisetap1, int noisetap2, int negate, int stereo, int clockdivider, int freq0)\nstatic int generic_start(sn76496_state *chip, int clock, int feedbackmask, int noisetap1, int noisetap2, int negate, int stereo, int clockdivider, int freq0)\n{\n\tint sample_rate;\n\t\n\t//sn76496_state *chip = get_safe_token(device);\n\t//sn76496_state *chip;\n\tsn76496_state *chip2;\n\t\n\t//if (SN76496_init(device,chip,stereo) != 0)\n\t//\tfatalerror(\"Error creating SN76496 chip\");\n\tsample_rate = SN76496_init(clock & 0x7FFFFFFF, chip, stereo);\n\tif ((clock & 0x80000000) && LastChipInit != NULL)\n\t{\n\t\t// Activate special NeoGeoPocket Mode\n\t\tchip2 = LastChipInit;\n\t\tchip2->NgpFlags = 0x80 | 0x00;\n\t\tchip->NgpFlags = 0x80 | 0x01;\n\t\tchip->NgpChip2 = chip2;\n\t\tchip2->NgpChip2 = chip;\n\t\tLastChipInit = NULL;\n\t}\n\telse\n\t{\n\t\tLastChipInit = chip;\n\t}\n\tSN76496_set_gain(chip, 0);\n\t\n\tchip->FeedbackMask = feedbackmask;\n\tchip->WhitenoiseTap1 = noisetap1;\n\tchip->WhitenoiseTap2 = noisetap2;\n\tchip->Negate = negate;\n\tchip->Stereo = stereo;\n\tif (clockdivider)\n\t\tchip->ClockDivider = clockdivider;\n\tchip->CurrentClock = clockdivider-1;\n\tchip->Freq0IsMax = freq0;\n\t\n\t/* Speed Patch*/\n\tsample_rate /= chip->ClockDivider;\n\t\n\t/*state_save_register_device_item_array(device, 0, chip->VolTable);\n\tstate_save_register_device_item_array(device, 0, chip->Register);\n\tstate_save_register_device_item(device, 0, chip->LastRegister);\n\tstate_save_register_device_item_array(device, 0, chip->Volume);\n\tstate_save_register_device_item(device, 0, chip->RNG);\n\tstate_save_register_device_item(device, 0, chip->ClockDivider);\n\tstate_save_register_device_item(device, 0, chip->CurrentClock);\n\tstate_save_register_device_item(device, 0, chip->FeedbackMask);\n\tstate_save_register_device_item(device, 0, chip->WhitenoiseTap1);\n\tstate_save_register_device_item(device, 0, chip->WhitenoiseTap2);\n\tstate_save_register_device_item(device, 0, chip->Negate);\n\tstate_save_register_device_item(device, 0, chip->Stereo);\n\tstate_save_register_device_item(device, 0, chip->StereoMask);\n\tstate_save_register_device_item_array(device, 0, chip->Period);\n\tstate_save_register_device_item_array(device, 0, chip->Count);\n\tstate_save_register_device_item_array(device, 0, chip->Output);\n\tstate_save_register_device_item(device, 0, chip->CyclestoREADY);*/\n\t\n\treturn sample_rate;\n}\n\nunsigned long int sn76496_start(void **chip, int clock, int shiftregwidth, int noisetaps,\n\t\t\t\t\t\t\t\tint negate, int stereo, int clockdivider, int freq0)\n{\n\tsn76496_state* sn_chip;\n\tint ntap[2];\n\tint curbit;\n\tint curtap;\n\t\n\tsn_chip = (sn76496_state*)malloc(sizeof(sn76496_state));\n\tif (sn_chip == NULL)\n\t\treturn 0;\n\tmemset(sn_chip, 0x00, sizeof(sn76496_state));\n\t*chip = sn_chip;\n\t\n\t// extract single noise tap bits\n\tcurtap = 0;\n\tfor (curbit = 0; curbit < 16; curbit ++)\n\t{\n\t\tif (noisetaps & (1 << curbit))\n\t\t{\n\t\t\tntap[curtap] = (1 << curbit);\n\t\t\tcurtap ++;\n\t\t\tif (curtap >= 2)\n\t\t\t\tbreak;\n\t\t}\n\t}\n\twhile(curtap < 2)\n\t{\n\t\tntap[curtap] = ntap[0];\n\t\tcurtap ++;\n\t}\n\t\n\treturn generic_start(sn_chip, clock, 1 << (shiftregwidth - 1), ntap[0], ntap[1],\n\t\t\t\t\t\tnegate, ! stereo, clockdivider ? 1 : 8, freq0);\n}\n\nvoid sn76496_shutdown(void *chip)\n{\n\tsn76496_state *R = (sn76496_state*)chip;\n\t\n\tfree(R);\n\treturn;\n}\n\nvoid sn76496_reset(void *chip)\n{\n\tsn76496_state *R;\n\tUINT8 i;\n\t\n\tR = (sn76496_state*)chip;\n\t\n\tfor (i = 0;i < 4;i++) R->Volume[i] = 0;\n\n\tR->LastRegister = 0;\n\tfor (i = 0;i < 8;i+=2)\n\t{\n\t\tR->Register[i] = 0;\n\t\tR->Register[i + 1] = 0x0f;\t/* volume = 0 */\n\t}\n\n\tfor (i = 0;i < 4;i++)\n\t{\n\t\tR->Output[i] = R->Period[i] = R->Count[i] = 0;\n\t}\n\n\tR->CyclestoREADY = 1;\n\tR->StereoMask = 0xFF; /* all channels enabled */\n\n\tR->RNG = R->FeedbackMask;\n\tR->Output[3] = R->RNG & 1;\n\t\n\treturn;\n}\n\nvoid sn76496_freq_limiter(int clock, int clockdiv, int sample_rate)\n{\n\tFNumLimit = (unsigned short int)((clock / (clockdiv ? 2.0 : 16.0)) / sample_rate);\n\t\n\treturn;\n}\n\nvoid sn76496_set_mutemask(void *chip, UINT32 MuteMask)\n{\n\tsn76496_state *R = (sn76496_state*)chip;\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 4; CurChn ++)\n\t\tR->MuteMsk[CurChn] = (MuteMask & (1 << CurChn)) ? 0 : ~0;\n\t\n\treturn;\n}\n\n// function parameters: device, feedback destination tap, feedback source taps,\n// normal(false)/invert(true), mono(false)/stereo(true), clock divider factor\n\n/*static DEVICE_START( sn76489 )\n{\n\tgeneric_start(device, 0x4000, 0x01, 0x02, TRUE, FALSE, 8, TRUE); // SN76489 not verified yet. todo: verify;\n}\n\nstatic DEVICE_START( sn76489a )\n{\n\tgeneric_start(device, 0x10000, 0x04, 0x08, FALSE, FALSE, 8, TRUE); // SN76489A: whitenoise verified, phase verified, periodic verified (by plgdavid)\n}\n\nstatic DEVICE_START( sn76494 )\n{\n\tgeneric_start(device, 0x10000, 0x04, 0x08, FALSE, FALSE, 1, TRUE); // SN76494 not verified, (according to datasheet: same as sn76489a but without the /8 divider)\n}\n\nstatic DEVICE_START( sn76496 )\n{\n\tgeneric_start(device, 0x10000, 0x04, 0x08, FALSE, FALSE, 8, TRUE); // SN76496: Whitenoise verified, phase verified, periodic verified (by Michael Zapf)\n}\n\nstatic DEVICE_START( sn94624 )\n{\n\tgeneric_start(device, 0x4000, 0x01, 0x02, TRUE, FALSE, 1, TRUE); // SN94624 whitenoise verified, phase verified, period verified; verified by PlgDavid\n}\n\nstatic DEVICE_START( ncr7496 )\n{\n\tgeneric_start(device, 0x8000, 0x02, 0x20, FALSE, FALSE, 8, TRUE); // NCR7496 not verified; info from smspower wiki\n}\n\nstatic DEVICE_START( gamegear )\n{\n\tgeneric_start(device, 0x8000, 0x01, 0x08, TRUE, TRUE, 8, FALSE); // Verified by Justin Kerk\n}\n\nstatic DEVICE_START( smsiii )\n{\n\tgeneric_start(device, 0x8000, 0x01, 0x08, TRUE, FALSE, 8, FALSE); // todo: verify; from smspower wiki, assumed to have same invert as gamegear\n}*/\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( sn76496 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(sn76496_state);\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( sn76496 );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"SN76496\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"TI PSG\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.1\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}\n\nDEVICE_GET_INFO( sn76489 )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( sn76489 );\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"SN76489\");\t\t\t\t\t\tbreak;\n\t\tdefault:\t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(sn76496);\t\t\t\t\t\tbreak;\n\t}\n}\n\nDEVICE_GET_INFO( sn76489a )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( sn76489a );\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"SN76489A\");\t\t\t\t\tbreak;\n\t\tdefault:\t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(sn76496);\t\t\t\t\t\tbreak;\n\t}\n}\n\nDEVICE_GET_INFO( sn76494 )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( sn76494 );\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"SN76494\");\t\t\t\t\t\tbreak;\n\t\tdefault:\t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(sn76496);\t\t\t\t\t\tbreak;\n\t}\n}\n\nDEVICE_GET_INFO( sn94624 )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( sn94624 );\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"SN94624\");\t\t\t\t\t\tbreak;\n\t\tdefault:\t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(sn76496);\t\t\t\t\t\tbreak;\n\t}\n}\n\nDEVICE_GET_INFO( ncr7496 )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ncr7496 );\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"NCR7496\");\t\t\t\t\t\tbreak;\n\t\tdefault:\t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(sn76496);\t\t\t\t\t\tbreak;\n\t}\n}\n\nDEVICE_GET_INFO( gamegear )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( gamegear );\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"Game Gear PSG\");\t\t\t\tbreak;\n\t\tdefault:\t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(sn76496);\t\t\t\t\t\tbreak;\n\t}\n}\n\nDEVICE_GET_INFO( smsiii )\n{\n\tswitch (state)\n\t{\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( smsiii );\t\t\tbreak;\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"SMSIII PSG\");\t\t\t\t\tbreak;\n\t\tdefault:\t\t\t\t\t\t\t\t\t\tDEVICE_GET_INFO_CALL(sn76496);\t\t\t\t\t\tbreak;\n\t}\n}*/\n\n\n/*DEFINE_LEGACY_SOUND_DEVICE(SN76496, sn76496);\nDEFINE_LEGACY_SOUND_DEVICE(SN76489, sn76489);\nDEFINE_LEGACY_SOUND_DEVICE(SN76489A, sn76489a);\nDEFINE_LEGACY_SOUND_DEVICE(SN76494, sn76494);\nDEFINE_LEGACY_SOUND_DEVICE(SN94624, sn94624);\nDEFINE_LEGACY_SOUND_DEVICE(NCR7496, ncr7496);\nDEFINE_LEGACY_SOUND_DEVICE(GAMEGEAR, gamegear);\nDEFINE_LEGACY_SOUND_DEVICE(SMSIII, smsiii);*/\n"
  },
  {
    "path": "VGMPlay/chips/sn76496.h",
    "content": "#pragma once\n\n/*READ8_DEVICE_HANDLER( sn76496_ready_r );\nWRITE8_DEVICE_HANDLER( sn76496_w );\nWRITE8_DEVICE_HANDLER( sn76496_stereo_w );\n\nDEVICE_GET_INFO( sn76496 );\nDEVICE_GET_INFO( sn76489 );\nDEVICE_GET_INFO( sn76489a );\nDEVICE_GET_INFO( sn76494 );\nDEVICE_GET_INFO( sn94624 );\nDEVICE_GET_INFO( ncr7496 );\nDEVICE_GET_INFO( gamegear );\nDEVICE_GET_INFO( smsiii );\n\n#define SOUND_SN76496 DEVICE_GET_INFO_NAME( sn76496 )\n#define SOUND_SN76489 DEVICE_GET_INFO_NAME( sn76489 )\n#define SOUND_SN76489A DEVICE_GET_INFO_NAME( sn76489a )\n#define SOUND_SN76494 DEVICE_GET_INFO_NAME( sn76494 )\n#define SOUND_SN94624 DEVICE_GET_INFO_NAME( sn94624 )\n#define SOUND_NCR7496 DEVICE_GET_INFO_NAME( ncr7496 )\n#define SOUND_GAMEGEAR DEVICE_GET_INFO_NAME( gamegear )\n#define SOUND_SMSIII DEVICE_GET_INFO_NAME( smsiii )*/\n\nUINT8 sn76496_ready_r(void *chip, offs_t offset);\nvoid sn76496_write_reg(void *chip, offs_t offset, UINT8 data);\nvoid sn76496_stereo_w(void *chip, offs_t offset, UINT8 data);\n\nvoid SN76496Update(void *chip, stream_sample_t **outputs, int samples);\nunsigned long int sn76496_start(void **chip, int clock, int shiftregwidth, int noisetaps,\n\t\t\t\t\t\t\t\tint negate, int stereo, int clockdivider, int freq0);\nvoid sn76496_shutdown(void *chip);\nvoid sn76496_reset(void *chip);\nvoid sn76496_freq_limiter(int clock, int clockdiv, int sample_rate);\nvoid sn76496_set_mutemask(void *chip, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/chips/sn76496_opl.c",
    "content": "#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n#include \"math.h\"\n\nvoid OPL_RegMapper(UINT16 Reg, UINT8 Data);\n\ntypedef struct _sn76496_state_opl sn76496_state_opl;\nstruct _sn76496_state_opl\n{\n\tint clock;\n\t//sound_stream * Channel;\n\t//INT32 VolTable[16];\t/* volume table (for 4-bit to db conversion)*/\n\tINT32 Register[8];\t/* registers */\n\tINT32 LastRegister;\t/* last register written */\n\t//INT32 Volume[4];\t/* db volume of voice 0-2 and noise */\n\tUINT8 Volume[4];\t/* native volume of voice 0-2 and noise */\n\t//UINT32 RNG;\t\t\t/* noise generator LFSR*/\n\t//INT32 FeedbackMask;\t/* mask for feedback */\n\t//INT32 WhitenoiseTaps;\t/* mask for white noise taps */\n\t//INT32 FeedbackInvert;\t/* feedback invert flag (xor vs xnor) */\n\t//INT32 Negate;\t\t/* output negate flag */\n\tINT32 Stereo;\t\t/* whether we're dealing with stereo or not */\n\tUINT8 StereoMask;\t/* the stereo output mask */\n\tINT32 Period[4];\t/* Length of 1/2 of waveform */\n\t//INT32 Count[4];\t\t/* Position within the waveform */\n\t//INT32 Output[4];\t/* 1-bit output of each channel, pre-volume */\n\t//INT32 CyclestoREADY;/* number of cycles until the READY line goes active */\n\tunsigned char NgpFlags;\t// bit 7 - NGP Mode on/off, bit 0 - is 2nd NGP chip\n\tsn76496_state_opl* NgpChip2;\t// Pointer to other Chip\n\t\n\tUINT8 LastVol[4];\n\tUINT8 RegC0_M[4];\n\tUINT8 RegC0_L[4];\n};\n\n#define NOISEMODE (R->Register[6]&4)?1:0\n\nconst unsigned char REG_LIST[0x0B] =\n\t{0x20, 0x40, 0x60, 0x80, 0xE0, 0x23, 0x43, 0x63, 0x83, 0xE3, 0xC0};\n// writing Reg 83 Data #6 makes a smooth fading, if you break playing\n// actually the release time could be everything - it wouldn't change anything\nconst unsigned char SQUARE_FM_INS_OPL[0x0B] =\n\t{0x02, 0x18, 0xFF, 0x00, 0x02, 0x01, 0x00, 0xF0, 0xF6, 0x00, 0x00};\t// OPL2/OPL3\nconst unsigned char SQUARE_FM_INS_OPL3[0x0B] =\n\t{0x01, 0x3F, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xF0, 0xF6, 0x06, 0x01};\t// OPL3 only\n// OPL3 has a SquareWave Waveform (OPL2 has only SineWaves)\nconst unsigned char NOISE_FM_INS[0x0A] =\n\t{0x0F, 0x00, 0xF0, 0xFF, 0x00, 0x01, 0x00, 0xF0, 0xF6, 0x00};\nconst unsigned char NOISE_FM_REG_C0[0x02] =\n\t{0x0B, 0x0E};\t// periodic, white\n//\t{0x01, 0x0E};\n\n/* Volume Table (4-bit SN76496 -> 6-bit OPL Conversion)\n\tSN76496\t\tOPL\n\tIdx\tVol\t\tIdx\tVol\n\t0\t100.0%\t00\t100.0%\n\t\t\t\t01\t 91.7%\n\t\t\t\t02\t 84.1%\n\t1\t 79.4%\t03\t 77.1%\n\t\t\t\t04\t 70.7%\n\t2\t 63.1%\t05\t 64.8%\n\t\t\t\t06\t 59.5%\n\t\t\t\t07\t 54.5%\n\t3\t 50.1%\t08\t 50.0%\n\t\t\t\t09\t 45.9%\n\t\t\t\t0A\t 42.0%\n\t4\t 39.8%\t0B\t 38.6%\n\t\t\t\t0C\t 35.4%\n\t5\t 31.6%\t0D\t 32.4%\n\t\t\t\t0E\t 29.7%\n\t\t\t\t0F\t 27.3%\n\t6\t 25.1%\t10\t 25.0%\n\t\t\t\t11\t 22.9%\n\t\t\t\t12\t 21.0%\n\t7\t 20.0%\t13\t 19.3%\n\t\t\t\t14\t 17.7%\n\t8\t 15.8%\t15\t 16.2%\n\t\t\t\t16\t 14.9%\n\t\t\t\t17\t 13.6%\n\t9\t 12.6%\t18\t 12.5%\n\t\t\t\t19\t 11.5%\n\t\t\t\t1A\t 10.5%\n\tA\t 10.0%\t1B\t  9.6%\n\t\t\t\t1C\t  8.8%\n\tB\t  7.9%\t1D\t  8.1%\n\t\t\t\t1E\t  7.4%\n\t\t\t\t1F\t  6.8%\n\tC\t  6.3%\t20\t  6.3%\n\t\t\t\t21\t  5.7%\n\t\t\t\t22\t  5.3%\n\tD\t  5.0%\t23\t  4.8%\n\t\t\t\t24\t  4.4%\n\tE\t  4.0%\t25\t  4.1%\n\t\t\t\t26\t  3.7%\n\t\t\t\t27\t  3.4%\n\t\t\t\t28\t  3.1%\n\t\t\t\t29\t  2.9%\n\t\t\t\t2A\t  2.6%\n\t\t\t\t2B\t  2.4%\n\t\t\t\t2C\t  2.2%\n\t\t\t\t2D\t  2.0%\n\t\t\t\t2E\t  1.9%\n\t\t\t\t2F\t  1.7%\n\t\t\t\t30\t  1.6%\n\t\t\t\t31\t  1.4%\n\t\t\t\t32\t  1.3%\n\t\t\t\t33\t  1.2%\n\t\t\t\t34\t  1.1%\n\t\t\t\t35\t  1.0%\n\t\t\t\t36\t  0.9%\n\t\t\t\t37\t  0.9%\n\t\t\t\t38\t  0.8%\n\t\t\t\t39\t  0.7%\n\t\t\t\t3A\t  0.7%\n\t\t\t\t3B\t  0.6%\n\t\t\t\t3C\t  0.6%\n\t\t\t\t3D\t  0.5%\n\t\t\t\t3E\t  0.5%\n\tF\t  0.0%\t3F\t  0.4%\n*/\nconst unsigned char VOL_OPL[0x10] =\n\t{0x00, 0x03, 0x05, 0x08, 0x0B, 0x0D, 0x10, 0x13,\n\t 0x15, 0x18, 0x1B, 0x1D, 0x20, 0x23, 0x25, 0x3F};\n\n\nextern unsigned char OPL_MODE;\n#define MAX_CHIPS\t0x02\nstatic sn76496_state_opl SN76496Data[MAX_CHIPS];\nstatic unsigned char LastChipInit;\n\nvoid sn76496_stereo_opl(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tsn76496_state_opl *R = &SN76496Data[ChipID];\n\tunsigned char i;\n\tunsigned char st_data;\n\t\n\tif (! R->Stereo)\n\t\treturn;\n\t\n\tR->StereoMask = data;\n\tfor (i = 0; i < 4; i ++)\n\t{\n\t\tst_data = 0x00;\n\t\tst_data |= (R->StereoMask & (0x10 << i)) ? 0x10 : 0x00;\t// Left Channel\n\t\tst_data |= (R->StereoMask & (0x01 << i)) ? 0x20 : 0x00;\t// Right Channel\n\t\tR->RegC0_M[i] = st_data;\n\t\tOPL_RegMapper(REG_LIST[0x0A] | i, R->RegC0_M[i] | R->RegC0_L[i]);\n\t}\n\t\n\treturn;\n}\n\nvoid sn76496_refresh_t6w28_opl(UINT8 ChipID)\n{\n\tsn76496_state_opl *R = &SN76496Data[ChipID];\n\tsn76496_state_opl *R2 = R->NgpChip2;\n\tunsigned char CurChn;\n\tunsigned char Channel;\n\t\n\tfor (CurChn = 0x00; CurChn < 0x08; CurChn ++)\n\t{\n\t\tChannel = CurChn & 0x03;\n\t\tif (! (CurChn & 0x04))\n\t\t{\n\t\t\t// Tone Chip: Left Channel\n\t\t\tR->RegC0_M[Channel] = 0x10;\n\t\t\tOPL_RegMapper(REG_LIST[0x0A] | CurChn, R->RegC0_M[Channel] | R->RegC0_L[Channel]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Noise Chip: Right Channel\n\t\t\tR2->RegC0_M[Channel] = 0x20;\n\t\t\tOPL_RegMapper(REG_LIST[0x0A] | CurChn, R2->RegC0_M[Channel] | R2->RegC0_L[Channel]);\n\t\t}\n\t}\n\t\n\treturn;\n}\n\nstatic void SendVolume(sn76496_state_opl* R, UINT8 Channel)\n{\n\tunsigned char ChnFnl;\n\tunsigned char ChnOp;\n\tunsigned char OPLVol;\n\t\n\tif (Channel >= 0x04)\n\t\tChannel &= 0x03;\n\t\n\tif (R->Volume[Channel] == R->LastVol[Channel])\n\t\treturn;\n\telse\n\t\tR->LastVol[Channel] = R->Volume[Channel];\n\t\n\tChnFnl = ((R->NgpFlags & 0x01) << 2) | Channel;\n\t\n\tChnOp = (ChnFnl / 0x03) * 0x08 + (ChnFnl % 0x03);\n\tOPLVol = VOL_OPL[R->Volume[Channel]];\n\tif (Channel == 0x03)\n\t{\n\t\tif (R->RegC0_L[Channel] & 0x01)\n\t\t\tOPL_RegMapper(0x40 | (ChnOp + 0x00), 0x00 | OPLVol);\n\t}\n\tOPL_RegMapper(0x40 | (ChnOp + 0x03), 0x00 | OPLVol);\n\t\n\treturn;\n}\n\nstatic void SendFrequency(sn76496_state_opl* R, UINT8 Channel)\n{\n\tconst double OPL_CHIP_RATE = 3579545.0 / 72.0;\n\t\n\tdouble FreqVal;\n\tsigned short int FNum;\n\tsigned char BlockVal;\n\tsn76496_state_opl* R2;\n\tunsigned char ChnB;\n\t\n\tChannel &= 0x03;\n\tif (R->NgpFlags & 0x80)\n\t{\n\t\tif ((R->NgpFlags & 0x01) ^ (Channel == 0x03))\n\t\t\treturn;\n\t\t\n\t\tR2 = R->NgpChip2;\n\t\tChnB = Channel | 0x04;\n\t}\n\t\n\tif (R->Period[Channel])\n\t\tFreqVal = (R->clock / 32.0) / R->Period[Channel];\n\telse\n\t\tFreqVal = 0.0;\n\tif (Channel == 0x03)\n\t{\n\t\tR->RegC0_L[Channel] = NOISE_FM_REG_C0[(R->Register[6] >> 2) & 0x01];\n\t\tOPL_RegMapper(REG_LIST[0x0A] | Channel, R->RegC0_M[Channel] | R->RegC0_L[Channel]);\n\t\tif (R->NgpFlags & 0x80)\n\t\t{\n\t\t\tOPL_RegMapper(REG_LIST[0x0A] | ChnB, R2->RegC0_M[Channel] | R->RegC0_L[Channel]);\n\t\t\tFNum = (ChnB / 0x03) * 0x08 + (ChnB % 0x03);\n\t\t}\n\t\t\n\t\tif (! (R->RegC0_L[Channel] & 0x01))\n\t\t{\n\t\t\t//FreqVal = 220.0;\n\t\t\tFreqVal /= 8.0;\t// too high frequencies sound weird\n\t\t\t// reset Modulator-Volume\n\t\t\tOPL_RegMapper(0x40 | 0x08, NOISE_FM_INS[0x01]);\n\t\t\tif (R->NgpFlags & 0x80)\n\t\t\t\tOPL_RegMapper(0x40 | FNum, NOISE_FM_INS[0x01]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// set Modulator-Volume (because of Additive Synthesis)\n\t\t\tOPL_RegMapper(0x40 | 0x08, 0x00 | VOL_OPL[R->Volume[Channel]]);\n\t\t\tif (R->NgpFlags & 0x80)\n\t\t\t\tOPL_RegMapper(0x40 | FNum, 0x00 | VOL_OPL[R2->Volume[Channel]]);\n\t\t}\n\t}\n\telse if (FreqVal > OPL_CHIP_RATE)\n\t{\n\t\tFreqVal = 0.0;\n\t}\n\t\n\tBlockVal = (unsigned char)(0x05 + (log(FreqVal) - log(440.0)) / log(2.0));\n\tif (BlockVal < 0x00)\n\t{\n\t\tBlockVal = 0x00;\n\t\tFNum = 0x000;\n\t}\n\telse if (BlockVal > 0x07)\n\t{\n\t\tBlockVal = 0x07;\n\t\tFNum = 0x3FF;\n\t}\n\telse\n\t{\n\t\tFNum = (unsigned short int)(FreqVal * (1 << (20 - BlockVal)) / OPL_CHIP_RATE + 0.5);\n\t\tif (FNum < 0x000)\n\t\t\tFNum = 0x000;\n\t\telse if (FNum > 0x3FF)\n\t\t\tFNum = 0x3FF;\n\t}\n\t\n\tif (Channel == 0x03)\t// stop Noise Note before restarting\n\t\tOPL_RegMapper(0xB0 | Channel, 0x00);\n\tOPL_RegMapper(0xA0 | Channel, FNum & 0x00FF);\n\tOPL_RegMapper(0xB0 | Channel, 0x20 | (BlockVal << 2) |( (FNum & 0x0300) >> 8));\n\tif (R->NgpFlags & 0x80)\n\t{\n\t\t// Send 2nd Channel Set\n\t\tif (Channel == 0x03)\n\t\t\tOPL_RegMapper(0xB0 | ChnB, 0x00);\n\t\tOPL_RegMapper(0xA0 | ChnB, FNum & 0x00FF);\n\t\tOPL_RegMapper(0xB0 | ChnB, 0x20 | (BlockVal << 2) |( (FNum & 0x0300) >> 8));\n\t}\n\t\n\treturn;\n}\n\nvoid sn76496_write_opl(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tsn76496_state_opl *R = &SN76496Data[ChipID];\n\tunsigned char n, r, c;\n\t\n\tif (data & 0x80)\n\t{\n\t\tr = (data & 0x70) >> 4;\n\t\tR->LastRegister = r;\n\t\tR->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f);\n\t}\n\telse\n    {\n\t\tr = R->LastRegister;\n\t}\n\tc = r/2;\n\tswitch (r)\n\t{\n\t\tcase 0:\t/* tone 0 : frequency */\n\t\tcase 2:\t/* tone 1 : frequency */\n\t\tcase 4:\t/* tone 2 : frequency */\n\t\t    if ((data & 0x80) == 0)\n\t\t\t\tR->Register[r] = (R->Register[r] & 0x0f) | ((data & 0x3f) << 4);\n\t\t\tR->Period[c] = R->Register[r];\n\t\t    if (data & 0x80)\n\t\t\t\tbreak;\t// only send after receiving a Data Command\n\t\t\tSendFrequency(R, c);\n\t\t\tif (r == 4)\n\t\t\t{\n\t\t\t\t/* update noise shift frequency */\n\t\t\t\tif ((R->Register[6] & 0x03) == 0x03)\n\t\t\t\t{\n\t\t\t\t\tR->Period[3] = 2 * R->Period[2];\n\t\t\t\t\tSendFrequency(R, 3);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 1:\t/* tone 0 : volume */\n\t\tcase 3:\t/* tone 1 : volume */\n\t\tcase 5:\t/* tone 2 : volume */\n\t\tcase 7:\t/* noise  : volume */\n\t\t\t//R->Volume[c] = R->VolTable[data & 0x0f];\n\t\t\tR->Volume[c] = data & 0x0F;\n\t\t\tSendVolume(R, c);\n\t\t\tif ((data & 0x80) == 0)\n\t\t\t{\n\t\t\t\tR->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f);\n\t\t\t\t// Register is set, but frequency is NOT refreshed\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 6:\t/* noise  : frequency, mode */\n\t\t    if ((data & 0x80) == 0)\n\t\t\t\tR->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f);\n\t\t\tn = R->Register[6];\n\t\t\t/* N/512,N/1024,N/2048,Tone #3 output */\n\t\t\tR->Period[3] = ((n&3) == 3) ? 2 * R->Period[2] : (1 << (5+(n&3)));\n\t\t\tSendFrequency(R, 3);\n\t\t\t    /* Reset noise shifter */\n\t\t\t//R->RNG = R->FeedbackMask;\n\t\t\t//R->Output[3] = R->RNG & 1;\n\t\t\tbreak;\n\t}\n}\n\nstatic void SN76496_init(int clock, sn76496_state_opl *R, int stereo)\n{\n\tconst unsigned char* SQUARE_FM_INS;\n\tunsigned char i;\n\tunsigned char reg;\n\n\tR->NgpFlags = 0x00;\n\tR->NgpChip2 = NULL;\n\tR->clock = clock;\n\t//for (i = 0;i < 4;i++)\n\t//\tR->Volume[i] = 0;\n\n\tR->LastRegister = 0;\n\tfor (i = 0;i < 8;i+=2)\n\t{\n\t\tR->Register[i] = 0;\n\t\tR->Register[i + 1] = 0x0f;\t/* volume = 0 */\n\t}\n\n\tif (OPL_MODE == 0x03)\n\t\tSQUARE_FM_INS = SQUARE_FM_INS_OPL3;\n\telse\n\t\tSQUARE_FM_INS = SQUARE_FM_INS_OPL;\n\t// Init Instruments\n\tfor (i = 0;i < 3;i++)\n\t{\n\t\tfor (reg = 0x00; reg < 0x0A; reg ++)\n\t\t{\n\t\t\tOPL_RegMapper(REG_LIST[reg] + i, SQUARE_FM_INS[reg]);\n\t\t}\n\t\tR->RegC0_L[i] = SQUARE_FM_INS[0x0A];\n\t\tR->RegC0_M[i] = 0x30;\n\t\tOPL_RegMapper(REG_LIST[0x0A] + i, R->RegC0_M[i] | R->RegC0_L[i]);\n\t}\n\tfor (reg = 0x00; reg < 0x0A; reg ++)\n\t{\n\t\tOPL_RegMapper(REG_LIST[reg] + 0x08, NOISE_FM_INS[reg]);\n\t}\n\tR->RegC0_L[3] = NOISE_FM_REG_C0[0x00];\n\tR->RegC0_M[3] = 0x30;\n\tOPL_RegMapper(REG_LIST[0x0A] + 0x03, R->RegC0_M[i] | R->RegC0_L[i]);\n\t\n\tfor (i = 0;i < 4;i++)\n\t{\n\t\tR->LastVol[i] = 0xFF;\n\t\tR->Volume[i] = R->Register[i * 2 + 1];\n\t\tR->Period[i] = 0;\n\t\tSendVolume(R, i);\n\t\tOPL_RegMapper(0xB0 | i, 0x00);\n\t\tSendFrequency(R, i);\n\t}\n\t\n\t/* Default is SN76489 non-A */\n\t//R->FeedbackMask = 0x4000;     /* mask for feedback */\n\t//R->WhitenoiseTaps = 0x03;   /* mask for white noise taps */\n\t//R->FeedbackInvert = 0; /* feedback invert flag */\n\t//R->CyclestoREADY = 1; /* assume ready is not active immediately on init. is this correct?*/\n\t//R->Negate = 0; /* channels are not negated */\n\tR->Stereo = stereo; /* depends on init */\n\tR->StereoMask = 0xFF; /* all channels enabled */\n\n\t//R->RNG = R->FeedbackMask;\n\t//R->Output[3] = R->RNG & 1;\n\n\treturn;\n}\n\n\nvoid start_sn76496_opl(UINT8 ChipID, int clock, int stereo)\n{\n\tsn76496_state_opl *chip;\n\tsn76496_state_opl *chip2;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn;\n\t\n\tchip = &SN76496Data[ChipID];\n\t//if (SN76496_init(device,chip,stereo) != 0)\n\t//\tfatalerror(\"Error creating SN76496 chip\");\n\tSN76496_init(clock & 0x7FFFFFFF, chip, stereo);\n\tif (clock & 0x80000000)\n\t{\n\t\t// Activate special NeoGeoPocket Mode\n\t\tchip2 = &SN76496Data[LastChipInit];\n\t\tchip2->NgpFlags = 0x80 | 0x00;\n\t\tchip->NgpFlags = 0x80 | 0x01;\n\t\tchip->NgpChip2 = chip2;\n\t\tchip2->NgpChip2 = chip;\n\t}\n\t\n\t//chip->FeedbackMask = feedbackmask;\n\t//chip->WhitenoiseTaps = noisetaps;\n\t//chip->FeedbackInvert = feedbackinvert;\n\t//chip->Negate = negate;\n\tchip->Stereo = ! stereo;\n\tsn76496_stereo_opl(ChipID, 0x00, chip->StereoMask);\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/sn764intf.c",
    "content": "/****************************************************************\n\n    MAME / MESS functions\n\n****************************************************************/\n\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#include \"sn76496.h\"\n#include \"sn76489.h\"\n#include \"sn764intf.h\"\n\n\n#define EC_MAME\t\t0x00\t// SN76496 core from MAME\n#ifdef ENABLE_ALL_CORES\n#define EC_MAXIM\t0x01\t// SN76489 core by Maxim (from in_vgm)\n#endif\n\n/* for stream system */\ntypedef struct _sn764xx_state sn764xx_state;\nstruct _sn764xx_state\n{\n\tvoid *chip;\n};\n\nstatic UINT8 EMU_CORE = 0x00;\n\nextern UINT32 SampleRate;\n#define MAX_CHIPS\t0x02\nstatic sn764xx_state SN764xxData[MAX_CHIPS];\n\nvoid sn764xx_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tsn764xx_state *info = &SN764xxData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tSN76496Update(info->chip, outputs, samples);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAXIM:\n\t\tSN76489_Update((SN76489_Context*)info->chip, outputs, samples);\n\t\tbreak;\n#endif\n\t}\n}\n\nint device_start_sn764xx(UINT8 ChipID, int clock, int shiftregwidth, int noisetaps,\n\t\t\t\t\t\t int negate, int stereo, int clockdivider, int freq0)\n{\n\tsn764xx_state *info;\n\tint rate = 0;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &SN764xxData[ChipID];\n\t/* emulator create */\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\trate = sn76496_start(&info->chip, clock, shiftregwidth, noisetaps,\n\t\t\t\t\t\t\tnegate, stereo, clockdivider, freq0);\n\t\tsn76496_freq_limiter(clock & 0x3FFFFFFF, clockdivider, SampleRate);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAXIM:\n\t\trate = SampleRate;\n\t\tinfo->chip = SN76489_Init(clock, rate);\n\t\tif (info->chip == NULL)\n\t\t\treturn 0;\n\t\tSN76489_Config((SN76489_Context*)info->chip, noisetaps, shiftregwidth, 0);\n\t\tbreak;\n#endif\n\t}\n \n\treturn rate;\n}\n\nvoid device_stop_sn764xx(UINT8 ChipID)\n{\n\tsn764xx_state *info = &SN764xxData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tsn76496_shutdown(info->chip);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAXIM:\n\t\tSN76489_Shutdown((SN76489_Context*)info->chip);\n\t\tbreak;\n#endif\n\t}\n}\n\nvoid device_reset_sn764xx(UINT8 ChipID)\n{\n\tsn764xx_state *info = &SN764xxData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tsn76496_reset(info->chip);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAXIM:\n\t\tSN76489_Reset((SN76489_Context*)info->chip);\n\t\tbreak;\n#endif\n\t}\n}\n\n\nvoid sn764xx_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tsn764xx_state *info = &SN764xxData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tswitch(offset)\n\t\t{\n\t\tcase 0x00:\n\t\t\tsn76496_write_reg(info->chip, offset & 1, data);\n\t\t\tbreak;\n\t\tcase 0x01:\n\t\t\tsn76496_stereo_w(info->chip, offset, data);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAXIM:\n\t\tswitch(offset)\n\t\t{\n\t\tcase 0x00:\n\t\t\tSN76489_Write((SN76489_Context*)info->chip, data);\n\t\t\tbreak;\n\t\tcase 0x01:\n\t\t\tSN76489_GGStereoWrite((SN76489_Context*)info->chip, data);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n#endif\n\t}\n}\n\nvoid sn764xx_set_emu_core(UINT8 Emulator)\n{\n#ifdef ENABLE_ALL_CORES\n\tEMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;\n#else\n\tEMU_CORE = EC_MAME;\n#endif\n\t\n\treturn;\n}\n\nvoid sn764xx_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tsn764xx_state *info = &SN764xxData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tsn76496_set_mutemask(info->chip, MuteMask);\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAXIM:\n\t\tSN76489_SetMute(info->chip, ~MuteMask & 0x0F);\n\t\tbreak;\n#endif\n\t}\n\t\n\treturn;\n}\n\nvoid sn764xx_set_panning(UINT8 ChipID, INT16* PanVals)\n{\n\tsn764xx_state *info = &SN764xxData[ChipID];\n\tswitch(EMU_CORE)\n\t{\n\tcase EC_MAME:\n\t\tbreak;\n#ifdef ENABLE_ALL_CORES\n\tcase EC_MAXIM:\n\t\tSN76489_SetPanning(info->chip, PanVals[0x00], PanVals[0x01], PanVals[0x02], PanVals[0x03]);\n\t\tbreak;\n#endif\n\t}\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/sn764intf.h",
    "content": "#pragma once\n\n/*WRITE8_DEVICE_HANDLER( ym2413_w );\n\nWRITE8_DEVICE_HANDLER( ym2413_register_port_w );\nWRITE8_DEVICE_HANDLER( ym2413_data_port_w );\n\nDEVICE_GET_INFO( ym2413 );\n#define SOUND_YM2413 DEVICE_GET_INFO_NAME( ym2413 )*/\n\nvoid sn764xx_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_sn764xx(UINT8 ChipID, int clock, int shiftregwidth, int noisetaps,\n\t\t\t\t\t\t int negate, int stereo, int clockdivider, int freq0);\nvoid device_stop_sn764xx(UINT8 ChipID);\nvoid device_reset_sn764xx(UINT8 ChipID);\n\nvoid sn764xx_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid sn764xx_set_emu_core(UINT8 Emulator);\nvoid sn764xx_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\nvoid sn764xx_set_panning(UINT8 ChipID, INT16* PanVals);\n"
  },
  {
    "path": "VGMPlay/chips/upd7759.c",
    "content": "/************************************************************\n\n    NEC UPD7759 ADPCM Speech Processor\n    by: Juergen Buchmueller, Mike Balfour, Howie Cohen,\n        Olivier Galibert, and Aaron Giles\n\n*************************************************************\n\n    Description:\n\n    The UPD7759 is a speech processing LSI that utilizes ADPCM to produce\n    speech or other sampled sounds.  It can directly address up to 1Mbit\n    (128k) of external data ROM, or the host CPU can control the speech\n    data transfer.  The UPD7759 is usually hooked up to a 640 kHz clock and\n    has one 8-bit input port, a start pin, a busy pin, and a clock output.\n\n    The chip is composed of 3 parts:\n    - a clock divider\n    - a rom-reading engine\n    - an adpcm engine\n    - a 4-to-9 bit adpcm converter\n\n    The clock divider takes the base 640KHz clock and divides it first\n    by a fixed divisor of 4 and then by a value between 9 and 32.  The\n    result gives a clock between 5KHz and 17.78KHz.  It's probably\n    possible, but not recommended and certainly out-of-spec, to push the\n    chip harder by reducing the divider.\n\n    The rom-reading engine reads one byte every two divided clock cycles.\n    The factor two comes from the fact that a byte has two nibbles, i.e.\n    two samples.\n\n    The apdcm engine takes bytes and interprets them as commands:\n\n        00000000                    sample end\n        00dddddd                    silence\n        01ffffff                    send the 256 following nibbles to the converter\n        10ffffff nnnnnnnn           send the n+1 following nibbles to the converter\n        11---rrr --ffffff nnnnnnnn  send the n+1 following nibbles to the converter, and repeat r+1 times\n\n    \"ffffff\" is sent to the clock divider to be the base clock for the\n    adpcm converter, i.e., it's the sampling rate.  If the number of\n    nibbles to send is odd the last nibble is ignored.  The commands\n    are always 8-bit aligned.\n\n    \"dddddd\" is the duration of the silence.  The base speed is unknown,\n    1ms sounds reasonably.  It does not seem linked to the adpcm clock\n    speed because there often is a silence before any 01 or 10 command.\n\n    The adpcm converter converts nibbles into 9-bit DAC values.  It has\n    an internal state of 4 bits that's used in conjunction with the\n    nibble to lookup which of the 256 possible steps is used.  Then\n    the state is changed according to the nibble value.  Essentially, the\n    higher the state, the bigger the steps are, and using big steps\n    increase the state.  Conversely, using small steps reduces the state.\n    This allows the engine to be a little more adaptative than a\n    classical ADPCM algorithm.\n\n    The UPD7759 can run in two modes, master (also known as standalone)\n    and slave.  The mode is selected through the \"md\" pin.  No known\n    game changes modes on the fly, and it's unsure if that's even\n    possible to do.\n\n\n    Master mode:\n\n    The output of the rom reader is directly connected to the adpcm\n    converter.  The controlling cpu only sends a sample number and the\n    7759 plays it.\n\n    The sample rom has a header at the beginning of the form\n\n        nn 5a a5 69 55\n\n    where nn is the number of the last sample.  This is then followed by\n    a vector of 2-bytes msb-first values, one per sample.  Multiplying\n    them by two gives the sample start offset in the rom.  A 0x00 marks\n    the end of each sample.\n\n    It seems that the UPD7759 reads at least part of the rom header at\n    startup.  Games doing rom banking are careful to reset the chip after\n    each change.\n\n\n    Slave mode:\n\n    The rom reader is completely disconnected.  The input port is\n    connected directly to the adpcm engine.  The first write to the input\n    port activates the engine (the value itself is ignored).  The engine\n    activates the clock output and waits for commands.  The clock speed\n    is unknown, but its probably a divider of 640KHz.  We use 40KHz here\n    because 80KHz crashes altbeast.  The chip probably has an internal\n    fifo to the converter and suspends the clock when the fifo is full.\n    The first command is always 0xFF.  A second 0xFF marks the end of the\n    sample and the engine stops.  OTOH, there is a 0x00 at the end too.\n    Go figure.\n\n*************************************************************/\n\n//#include \"emu.h\"\n//#include \"streams.h\"\n#ifdef _DEBUG\n#include <stdio.h>\n#endif\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"mamedef.h\"\n#include \"upd7759.h\"\n\n\n#define DEBUG_STATES\t(0)\n//#define DEBUG_METHOD\tmame_printf_debug\n#define DEBUG_METHOD\tlogerror\n\n\n\n/************************************************************\n\n    Constants\n\n*************************************************************/\n\n/* step value fractional bits */\n#define FRAC_BITS\t\t20\n#define FRAC_ONE\t\t(1 << FRAC_BITS)\n#define FRAC_MASK\t\t(FRAC_ONE - 1)\n\n/* chip states */\nenum\n{\n\tSTATE_IDLE,\n\tSTATE_DROP_DRQ,\n\tSTATE_START,\n\tSTATE_FIRST_REQ,\n\tSTATE_LAST_SAMPLE,\n\tSTATE_DUMMY1,\n\tSTATE_ADDR_MSB,\n\tSTATE_ADDR_LSB,\n\tSTATE_DUMMY2,\n\tSTATE_BLOCK_HEADER,\n\tSTATE_NIBBLE_COUNT,\n\tSTATE_NIBBLE_MSN,\n\tSTATE_NIBBLE_LSN\n};\n\n\n\n/************************************************************\n\n    Type definitions\n\n*************************************************************/\n\ntypedef struct _upd7759_state upd7759_state;\nstruct _upd7759_state\n{\n\t//running_device *device;\n\t//sound_stream *channel;\t\t\t\t\t/* stream channel for playback */\n\n\t/* internal clock to output sample rate mapping */\n\tUINT32\t\tpos;\t\t\t\t\t\t/* current output sample position */\n\tUINT32\t\tstep;\t\t\t\t\t\t/* step value per output sample */\n\t//attotime\tclock_period;\t\t\t\t/* clock period */\n\t//emu_timer *timer;\t\t\t\t\t\t/* timer */\n\n\t/* I/O lines */\n\tUINT8\t\tfifo_in;\t\t\t\t\t/* last data written to the sound chip */\n\tUINT8\t\treset;\t\t\t\t\t\t/* current state of the RESET line */\n\tUINT8\t\tstart;\t\t\t\t\t\t/* current state of the START line */\n\tUINT8\t\tdrq;\t\t\t\t\t\t/* current state of the DRQ line */\n\t//void (*drqcallback)(running_device *device, int param);\t\t\t/* drq callback */\n\t//void (*drqcallback)(int param);\t\t\t/* drq callback */\n\n\t/* internal state machine */\n\tINT8\t\tstate;\t\t\t\t\t\t/* current overall chip state */\n\tINT32\t\tclocks_left;\t\t\t\t/* number of clocks left in this state */\n\tUINT16\t\tnibbles_left;\t\t\t\t/* number of ADPCM nibbles left to process */\n\tUINT8\t\trepeat_count;\t\t\t\t/* number of repeats remaining in current repeat block */\n\tINT8\t\tpost_drq_state;\t\t\t\t/* state we will be in after the DRQ line is dropped */\n\tINT32\t\tpost_drq_clocks;\t\t\t/* clocks that will be left after the DRQ line is dropped */\n\tUINT8\t\treq_sample;\t\t\t\t\t/* requested sample number */\n\tUINT8\t\tlast_sample;\t\t\t\t/* last sample number available */\n\tUINT8\t\tblock_header;\t\t\t\t/* header byte */\n\tUINT8\t\tsample_rate;\t\t\t\t/* number of UPD clocks per ADPCM nibble */\n\tUINT8\t\tfirst_valid_header;\t\t\t/* did we get our first valid header yet? */\n\tUINT32\t\toffset;\t\t\t\t\t\t/* current ROM offset */\n\tUINT32\t\trepeat_offset;\t\t\t\t/* current ROM repeat offset */\n\n\t/* ADPCM processing */\n\tINT8\t\tadpcm_state;\t\t\t\t/* ADPCM state index */\n\tUINT8\t\tadpcm_data;\t\t\t\t\t/* current byte of ADPCM data */\n\tINT16\t\tsample;\t\t\t\t\t\t/* current sample value */\n\n\t/* ROM access */\n\tUINT32\t\tromsize;\n\tUINT8 *\t\trom;\t\t\t\t\t\t/* pointer to ROM data or NULL for slave mode */\n\tUINT8 *\t\trombase;\t\t\t\t\t/* pointer to ROM data or NULL for slave mode */\n\tUINT32\t\tromoffset;\t\t\t\t\t/* ROM offset to make save/restore easier */\n\tUINT8\t\tChipMode;\t\t\t\t\t// 0 - Master, 1 - Slave\n\t\n\t// Valley Bell: Added a FIFO buffer based on Sega Pico.\n\tUINT8 data_buf[0x40];\n\tUINT8 dbuf_pos_read;\n\tUINT8 dbuf_pos_write;\n};\n\n\n\n/************************************************************\n\n    Local variables\n\n*************************************************************/\n\nstatic const int upd7759_step[16][16] =\n{\n\t{ 0,  0,  1,  2,  3,   5,   7,  10,  0,   0,  -1,  -2,  -3,   -5,   -7,  -10 },\n\t{ 0,  1,  2,  3,  4,   6,   8,  13,  0,  -1,  -2,  -3,  -4,   -6,   -8,  -13 },\n\t{ 0,  1,  2,  4,  5,   7,  10,  15,  0,  -1,  -2,  -4,  -5,   -7,  -10,  -15 },\n\t{ 0,  1,  3,  4,  6,   9,  13,  19,  0,  -1,  -3,  -4,  -6,   -9,  -13,  -19 },\n\t{ 0,  2,  3,  5,  8,  11,  15,  23,  0,  -2,  -3,  -5,  -8,  -11,  -15,  -23 },\n\t{ 0,  2,  4,  7, 10,  14,  19,  29,  0,  -2,  -4,  -7, -10,  -14,  -19,  -29 },\n\t{ 0,  3,  5,  8, 12,  16,  22,  33,  0,  -3,  -5,  -8, -12,  -16,  -22,  -33 },\n\t{ 1,  4,  7, 10, 15,  20,  29,  43, -1,  -4,  -7, -10, -15,  -20,  -29,  -43 },\n\t{ 1,  4,  8, 13, 18,  25,  35,  53, -1,  -4,  -8, -13, -18,  -25,  -35,  -53 },\n\t{ 1,  6, 10, 16, 22,  31,  43,  64, -1,  -6, -10, -16, -22,  -31,  -43,  -64 },\n\t{ 2,  7, 12, 19, 27,  37,  51,  76, -2,  -7, -12, -19, -27,  -37,  -51,  -76 },\n\t{ 2,  9, 16, 24, 34,  46,  64,  96, -2,  -9, -16, -24, -34,  -46,  -64,  -96 },\n\t{ 3, 11, 19, 29, 41,  57,  79, 117, -3, -11, -19, -29, -41,  -57,  -79, -117 },\n\t{ 4, 13, 24, 36, 50,  69,  96, 143, -4, -13, -24, -36, -50,  -69,  -96, -143 },\n\t{ 4, 16, 29, 44, 62,  85, 118, 175, -4, -16, -29, -44, -62,  -85, -118, -175 },\n\t{ 6, 20, 36, 54, 76, 104, 144, 214, -6, -20, -36, -54, -76, -104, -144, -214 },\n};\n\nstatic const int upd7759_state_table[16] = { -1, -1, 0, 0, 1, 2, 2, 3, -1, -1, 0, 0, 1, 2, 2, 3 };\n\n\n\n/*INLINE upd7759_state *get_safe_token(running_device *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == UPD7759);\n\treturn (upd7759_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n\n#define MAX_CHIPS\t0x02\nstatic upd7759_state UPD7759Data[MAX_CHIPS];\n\n/************************************************************\n\n    ADPCM sample updater\n\n*************************************************************/\n\nINLINE void update_adpcm(upd7759_state *chip, int data)\n{\n\t/* update the sample and the state */\n\tchip->sample += upd7759_step[chip->adpcm_state][data];\n\tchip->adpcm_state += upd7759_state_table[data];\n\n\t/* clamp the state to 0..15 */\n\tif (chip->adpcm_state < 0)\n\t\tchip->adpcm_state = 0;\n\telse if (chip->adpcm_state > 15)\n\t\tchip->adpcm_state = 15;\n}\n\n\n\n/************************************************************\n\n    Master chip state machine\n\n*************************************************************/\n\nstatic void get_fifo_data(upd7759_state *chip)\n{\n\tif (chip->dbuf_pos_read == chip->dbuf_pos_write)\n\t{\n\t\tlogerror(\"Warning: UPD7759 reading empty FIFO!\\n\");\n\t\treturn;\n\t}\n\t\n\tchip->fifo_in = chip->data_buf[chip->dbuf_pos_read];\n\tchip->dbuf_pos_read ++;\n\tchip->dbuf_pos_read &= 0x3F;\n\t\n\treturn;\n}\n\nstatic void advance_state(upd7759_state *chip)\n{\n\tswitch (chip->state)\n\t{\n\t\t/* Idle state: we stick around here while there's nothing to do */\n\t\tcase STATE_IDLE:\n\t\t\tchip->clocks_left = 4;\n\t\t\tbreak;\n\n\t\t/* drop DRQ state: update to the intended state */\n\t\tcase STATE_DROP_DRQ:\n\t\t\tchip->drq = 0;\n\n\t\t\tif (chip->ChipMode)\n\t\t\t\tget_fifo_data(chip);\t// Slave Mode only\n\t\t\tchip->clocks_left = chip->post_drq_clocks;\n\t\t\tchip->state = chip->post_drq_state;\n\t\t\tbreak;\n\n\t\t/* Start state: we begin here as soon as a sample is triggered */\n\t\tcase STATE_START:\n\t\t\tchip->req_sample = chip->rom ? chip->fifo_in : 0x10;\n\t\t\tif (DEBUG_STATES) DEBUG_METHOD(\"UPD7759: req_sample = %02X\\n\", chip->req_sample);\n\n\t\t\t/* 35+ cycles after we get here, the /DRQ goes low\n             *     (first byte (number of samples in ROM) should be sent in response)\n             *\n             * (35 is the minimum number of cycles I found during heavy tests.\n             * Depending on the state the chip was in just before the /MD was set to 0 (reset, standby\n             * or just-finished-playing-previous-sample) this number can range from 35 up to ~24000).\n             * It also varies slightly from test to test, but not much - a few cycles at most.) */\n\t\t\tchip->clocks_left = 70;\t/* 35 - breaks cotton */\n\t\t\tchip->state = STATE_FIRST_REQ;\n\t\t\tbreak;\n\n\t\t/* First request state: issue a request for the first byte */\n\t\t/* The expected response will be the index of the last sample */\n\t\tcase STATE_FIRST_REQ:\n\t\t\tif (DEBUG_STATES) DEBUG_METHOD(\"UPD7759: first data request\\n\");\n\t\t\tchip->drq = 1;\n\n\t\t\t/* 44 cycles later, we will latch this value and request another byte */\n\t\t\tchip->clocks_left = 44;\n\t\t\tchip->state = STATE_LAST_SAMPLE;\n\t\t\tbreak;\n\n\t\t/* Last sample state: latch the last sample value and issue a request for the second byte */\n\t\t/* The second byte read will be just a dummy */\n\t\tcase STATE_LAST_SAMPLE:\n\t\t\tchip->last_sample = chip->rom ? chip->rom[0] : chip->fifo_in;\n\t\t\tif (DEBUG_STATES) DEBUG_METHOD(\"UPD7759: last_sample = %02X, requesting dummy 1\\n\", chip->last_sample);\n\t\t\tchip->drq = 1;\n\n\t\t\t/* 28 cycles later, we will latch this value and request another byte */\n\t\t\tchip->clocks_left = 28;\t/* 28 - breaks cotton */\n\t\t\tchip->state = (chip->req_sample > chip->last_sample) ? STATE_IDLE : STATE_DUMMY1;\n\t\t\tbreak;\n\n\t\t/* First dummy state: ignore any data here and issue a request for the third byte */\n\t\t/* The expected response will be the MSB of the sample address */\n\t\tcase STATE_DUMMY1:\n\t\t\tif (DEBUG_STATES) DEBUG_METHOD(\"UPD7759: dummy1, requesting offset_hi\\n\");\n\t\t\tchip->drq = 1;\n\n\t\t\t/* 32 cycles later, we will latch this value and request another byte */\n\t\t\tchip->clocks_left = 32;\n\t\t\tchip->state = STATE_ADDR_MSB;\n\t\t\tbreak;\n\n\t\t/* Address MSB state: latch the MSB of the sample address and issue a request for the fourth byte */\n\t\t/* The expected response will be the LSB of the sample address */\n\t\tcase STATE_ADDR_MSB:\n\t\t\tchip->offset = (chip->rom ? chip->rom[chip->req_sample * 2 + 5] : chip->fifo_in) << 9;\n\t\t\tif (DEBUG_STATES) DEBUG_METHOD(\"UPD7759: offset_hi = %02X, requesting offset_lo\\n\", chip->offset >> 9);\n\t\t\tchip->drq = 1;\n\n\t\t\t/* 44 cycles later, we will latch this value and request another byte */\n\t\t\tchip->clocks_left = 44;\n\t\t\tchip->state = STATE_ADDR_LSB;\n\t\t\tbreak;\n\n\t\t/* Address LSB state: latch the LSB of the sample address and issue a request for the fifth byte */\n\t\t/* The expected response will be just a dummy */\n\t\tcase STATE_ADDR_LSB:\n\t\t\tchip->offset |= (chip->rom ? chip->rom[chip->req_sample * 2 + 6] : chip->fifo_in) << 1;\n\t\t\tif (DEBUG_STATES) DEBUG_METHOD(\"UPD7759: offset_lo = %02X, requesting dummy 2\\n\", (chip->offset >> 1) & 0xff);\n\t\t\tchip->drq = 1;\n\n\t\t\t/* 36 cycles later, we will latch this value and request another byte */\n\t\t\tchip->clocks_left = 36;\n\t\t\tchip->state = STATE_DUMMY2;\n\t\t\tbreak;\n\n\t\t/* Second dummy state: ignore any data here and issue a request for the the sixth byte */\n\t\t/* The expected response will be the first block header */\n\t\tcase STATE_DUMMY2:\n\t\t\tchip->offset++;\n\t\t\tchip->first_valid_header = 0;\n\t\t\tif (DEBUG_STATES) DEBUG_METHOD(\"UPD7759: dummy2, requesting block header\\n\");\n\t\t\tchip->drq = 1;\n\n\t\t\t/* 36?? cycles later, we will latch this value and request another byte */\n\t\t\tchip->clocks_left = 36;\n\t\t\tchip->state = STATE_BLOCK_HEADER;\n\t\t\tbreak;\n\n\t\t/* Block header state: latch the header and issue a request for the first byte afterwards */\n\t\tcase STATE_BLOCK_HEADER:\n\n\t\t\t/* if we're in a repeat loop, reset the offset to the repeat point and decrement the count */\n\t\t\tif (chip->repeat_count)\n\t\t\t{\n\t\t\t\tchip->repeat_count--;\n\t\t\t\tchip->offset = chip->repeat_offset;\n\t\t\t}\n\t\t\tchip->block_header = chip->rom ? chip->rom[chip->offset++ & 0x1ffff] : chip->fifo_in;\n\t\t\tif (DEBUG_STATES) DEBUG_METHOD(\"UPD7759: header (@%05X) = %02X, requesting next byte\\n\", chip->offset, chip->block_header);\n\t\t\tchip->drq = 1;\n\n\t\t\t/* our next step depends on the top two bits */\n\t\t\tswitch (chip->block_header & 0xc0)\n\t\t\t{\n\t\t\t\tcase 0x00:\t/* silence */\n\t\t\t\t\tchip->clocks_left = 1024 * ((chip->block_header & 0x3f) + 1);\n\t\t\t\t\tchip->state = (chip->block_header == 0 && chip->first_valid_header) ? STATE_IDLE : STATE_BLOCK_HEADER;\n\t\t\t\t\tchip->sample = 0;\n\t\t\t\t\tchip->adpcm_state = 0;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 0x40:\t/* 256 nibbles */\n\t\t\t\t\tchip->sample_rate = (chip->block_header & 0x3f) + 1;\n\t\t\t\t\tchip->nibbles_left = 256;\n\t\t\t\t\tchip->clocks_left = 36;\t/* just a guess */\n\t\t\t\t\tchip->state = STATE_NIBBLE_MSN;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 0x80:\t/* n nibbles */\n\t\t\t\t\tchip->sample_rate = (chip->block_header & 0x3f) + 1;\n\t\t\t\t\tchip->clocks_left = 36;\t/* just a guess */\n\t\t\t\t\tchip->state = STATE_NIBBLE_COUNT;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 0xc0:\t/* repeat loop */\n\t\t\t\t\tchip->repeat_count = (chip->block_header & 7) + 1;\n\t\t\t\t\tchip->repeat_offset = chip->offset;\n\t\t\t\t\tchip->clocks_left = 36;\t/* just a guess */\n\t\t\t\t\tchip->state = STATE_BLOCK_HEADER;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* set a flag when we get the first non-zero header */\n\t\t\tif (chip->block_header != 0)\n\t\t\t\tchip->first_valid_header = 1;\n\t\t\tbreak;\n\n\t\t/* Nibble count state: latch the number of nibbles to play and request another byte */\n\t\t/* The expected response will be the first data byte */\n\t\tcase STATE_NIBBLE_COUNT:\n\t\t\tchip->nibbles_left = (chip->rom ? chip->rom[chip->offset++ & 0x1ffff] : chip->fifo_in) + 1;\n\t\t\tif (DEBUG_STATES) DEBUG_METHOD(\"UPD7759: nibble_count = %u, requesting next byte\\n\", (unsigned)chip->nibbles_left);\n\t\t\tchip->drq = 1;\n\n\t\t\t/* 36?? cycles later, we will latch this value and request another byte */\n\t\t\tchip->clocks_left = 36;\t/* just a guess */\n\t\t\tchip->state = STATE_NIBBLE_MSN;\n\t\t\tbreak;\n\n\t\t/* MSN state: latch the data for this pair of samples and request another byte */\n\t\t/* The expected response will be the next sample data or another header */\n\t\tcase STATE_NIBBLE_MSN:\n\t\t\tchip->adpcm_data = chip->rom ? chip->rom[chip->offset++ & 0x1ffff] : chip->fifo_in;\n\t\t\tupdate_adpcm(chip, chip->adpcm_data >> 4);\n\t\t\tchip->drq = 1;\n\n\t\t\t/* we stay in this state until the time for this sample is complete */\n\t\t\tchip->clocks_left = chip->sample_rate * 4;\n\t\t\tif (--chip->nibbles_left == 0)\n\t\t\t\tchip->state = STATE_BLOCK_HEADER;\n\t\t\telse\n\t\t\t\tchip->state = STATE_NIBBLE_LSN;\n\t\t\tbreak;\n\n\t\t/* LSN state: process the lower nibble */\n\t\tcase STATE_NIBBLE_LSN:\n\t\t\tupdate_adpcm(chip, chip->adpcm_data & 15);\n\n\t\t\t/* we stay in this state until the time for this sample is complete */\n\t\t\tchip->clocks_left = chip->sample_rate * 4;\n\t\t\tif (--chip->nibbles_left == 0)\n\t\t\t\tchip->state = STATE_BLOCK_HEADER;\n\t\t\telse\n\t\t\t\tchip->state = STATE_NIBBLE_MSN;\n\t\t\tbreak;\n\t}\n\n\t/* if there's a DRQ, fudge the state */\n\tif (chip->drq)\n\t{\n\t\tchip->post_drq_state = chip->state;\n\t\tchip->post_drq_clocks = chip->clocks_left - 21;\n\t\tchip->state = STATE_DROP_DRQ;\n\t\tchip->clocks_left = 21;\n\t}\n}\n\n\n\n/************************************************************\n\n    Stream callback\n\n*************************************************************/\n\n//static STREAM_UPDATE( upd7759_update )\nvoid upd7759_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//upd7759_state *chip = (upd7759_state *)param;\n\tupd7759_state *chip = &UPD7759Data[ChipID];\n\tINT32 clocks_left = chip->clocks_left;\n\tINT16 sample = chip->sample;\n\tUINT32 step = chip->step;\n\tUINT32 pos = chip->pos;\n\tstream_sample_t *buffer = outputs[0];\n\tstream_sample_t *buffer2 = outputs[1];\n\n\t/* loop until done */\n\tif (chip->state != STATE_IDLE)\n\t\twhile (samples != 0)\n\t\t{\n\t\t\t/* store the current sample */\n\t\t\t*buffer++ = sample << 7;\n\t\t\t*buffer2++ = sample << 7;\n\t\t\tsamples--;\n\n\t\t\t/* advance by the number of clocks/output sample */\n\t\t\tpos += step;\n\n\t\t\t/* handle clocks, but only in standalone mode */\n\t\t\tif (! chip->ChipMode)\n\t\t\t{\n\t\t\t\twhile (chip->rom && pos >= FRAC_ONE)\n\t\t\t\t{\n\t\t\t\t\tint clocks_this_time = pos >> FRAC_BITS;\n\t\t\t\t\tif (clocks_this_time > clocks_left)\n\t\t\t\t\t\tclocks_this_time = clocks_left;\n\n\t\t\t\t\t/* clock once */\n\t\t\t\t\tpos -= clocks_this_time * FRAC_ONE;\n\t\t\t\t\tclocks_left -= clocks_this_time;\n\n\t\t\t\t\t/* if we're out of clocks, time to handle the next state */\n\t\t\t\t\tif (clocks_left == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t/* advance one state; if we hit idle, bail */\n\t\t\t\t\t\tadvance_state(chip);\n\t\t\t\t\t\tif (chip->state == STATE_IDLE)\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/* reimport the variables that we cached */\n\t\t\t\t\t\tclocks_left = chip->clocks_left;\n\t\t\t\t\t\tsample = chip->sample;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tUINT8 CntFour;\n\t\t\t\t\n\t\t\t\tif (! clocks_left)\n\t\t\t\t{\n\t\t\t\t\tadvance_state(chip);\n\t\t\t\t\tclocks_left = chip->clocks_left;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// advance the state (4x because of Clock Divider /4)\n\t\t\t\tfor (CntFour = 0; CntFour < 4; CntFour ++)\n\t\t\t\t{\n\t\t\t\t\tclocks_left --;\n\t\t\t\t\tif (! clocks_left)\n\t\t\t\t\t{\n\t\t\t\t\t\tadvance_state(chip);\n\t\t\t\t\t\tclocks_left = chip->clocks_left;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* if we got out early, just zap the rest of the buffer */\n\tif (samples != 0)\n\t{\n\t\tmemset(buffer, 0, samples * sizeof(*buffer));\n\t\tmemset(buffer2, 0, samples * sizeof(*buffer2));\n\t}\n\n\t/* flush the state back */\n\tchip->clocks_left = clocks_left;\n\tchip->pos = pos;\n}\n\n\n\n/************************************************************\n\n    DRQ callback\n\n*************************************************************/\n\n/*static TIMER_CALLBACK( upd7759_slave_update )\n{\n\tupd7759_state *chip = (upd7759_state *)ptr;\n\tUINT8 olddrq = chip->drq;\n\n\t// update the stream\n\t//stream_update(chip->channel);\n\n\t// advance the state\n\tadvance_state(chip);\n\n\t// if the DRQ changed, update it\n\tlogerror(\"slave_update: DRQ %d->%d\\n\", olddrq, chip->drq);\n\tif (olddrq != chip->drq && chip->drqcallback)\n\t\t//(*chip->drqcallback)(chip->device, chip->drq);\n\t\t(*chip->drqcallback)(chip->drq);\n\n\t// set a timer to go off when that is done\n\t//if (chip->state != STATE_IDLE)\n\t//\ttimer_adjust_oneshot(chip->timer, attotime_mul(chip->clock_period, chip->clocks_left), 0);\n}*/\n\n\n/************************************************************\n\n    Sound startup\n\n*************************************************************/\n\nstatic void upd7759_reset(upd7759_state *chip)\n{\n\tchip->pos                = 0;\n\tchip->fifo_in            = 0;\n\tchip->drq                = 0;\n\tchip->state              = STATE_IDLE;\n\tchip->clocks_left        = 0;\n\tchip->nibbles_left       = 0;\n\tchip->repeat_count       = 0;\n\tchip->post_drq_state     = STATE_IDLE;\n\tchip->post_drq_clocks    = 0;\n\tchip->req_sample         = 0;\n\tchip->last_sample        = 0;\n\tchip->block_header       = 0;\n\tchip->sample_rate        = 0;\n\tchip->first_valid_header = 0;\n\tchip->offset             = 0;\n\tchip->repeat_offset      = 0;\n\tchip->adpcm_state        = 0;\n\tchip->adpcm_data         = 0;\n\tchip->sample             = 0;\n\n\t// Valley Bell: reset buffer\n\tchip->data_buf[0] = chip->data_buf[1] = 0x00;\n\tchip->dbuf_pos_read = 0x00;\n\tchip->dbuf_pos_write = 0x00;\n\n\t/* turn off any timer */\n\t//if (chip->timer)\n\t//\ttimer_adjust_oneshot(chip->timer, attotime_never, 0);\n\tif (chip->ChipMode)\n\t\tchip->clocks_left = -1;\n}\n\n\n//static DEVICE_RESET( upd7759 )\nvoid device_reset_upd7759(UINT8 ChipID)\n{\n\tupd7759_state *chip = &UPD7759Data[ChipID];\n\t//upd7759_reset(get_safe_token(device));\n\tupd7759_reset(chip);\n}\n\n\n//static STATE_POSTLOAD( upd7759_postload )\n/*static void upd7759_postload(void* param)\n{\n\tupd7759_state *chip = (upd7759_state *)param;\n\tchip->rom = chip->rombase + chip->romoffset;\n}*/\n\n\n/*static void register_for_save(upd7759_state *chip, running_device *device)\n{\n\tstate_save_register_device_item(device, 0, chip->pos);\n\tstate_save_register_device_item(device, 0, chip->step);\n\n\tstate_save_register_device_item(device, 0, chip->fifo_in);\n\tstate_save_register_device_item(device, 0, chip->reset);\n\tstate_save_register_device_item(device, 0, chip->start);\n\tstate_save_register_device_item(device, 0, chip->drq);\n\n\tstate_save_register_device_item(device, 0, chip->state);\n\tstate_save_register_device_item(device, 0, chip->clocks_left);\n\tstate_save_register_device_item(device, 0, chip->nibbles_left);\n\tstate_save_register_device_item(device, 0, chip->repeat_count);\n\tstate_save_register_device_item(device, 0, chip->post_drq_state);\n\tstate_save_register_device_item(device, 0, chip->post_drq_clocks);\n\tstate_save_register_device_item(device, 0, chip->req_sample);\n\tstate_save_register_device_item(device, 0, chip->last_sample);\n\tstate_save_register_device_item(device, 0, chip->block_header);\n\tstate_save_register_device_item(device, 0, chip->sample_rate);\n\tstate_save_register_device_item(device, 0, chip->first_valid_header);\n\tstate_save_register_device_item(device, 0, chip->offset);\n\tstate_save_register_device_item(device, 0, chip->repeat_offset);\n\n\tstate_save_register_device_item(device, 0, chip->adpcm_state);\n\tstate_save_register_device_item(device, 0, chip->adpcm_data);\n\tstate_save_register_device_item(device, 0, chip->sample);\n\n\tstate_save_register_device_item(device, 0, chip->romoffset);\n\tstate_save_register_postload(device->machine, upd7759_postload, chip);\n}*/\n\n\n//static DEVICE_START( upd7759 )\nint device_start_upd7759(UINT8 ChipID, int clock)\n{\n\tstatic const upd7759_interface defintrf = { 0 };\n\t//const upd7759_interface *intf = (device->baseconfig().static_config() != NULL) ? (const upd7759_interface *)device->baseconfig().static_config() : &defintrf;\n\tconst upd7759_interface *intf = &defintrf;\n\t//upd7759_state *chip = get_safe_token(device);\n\tupd7759_state *chip;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &UPD7759Data[ChipID];\n\t//chip->device = device;\n\tchip->ChipMode = (clock & 0x80000000) >> 31;\n\tclock &= 0x7FFFFFFF;\n\n\t/* allocate a stream channel */\n\t//chip->channel = stream_create(device, 0, 1, device->clock()/4, chip, upd7759_update);\n\n\t/* compute the stepping rate based on the chip's clock speed */\n\tchip->step = 4 * FRAC_ONE;\n\n\t/* compute the clock period */\n\t//chip->clock_period = ATTOTIME_IN_HZ(device->clock());\n\n\t/* set the intial state */\n\tchip->state = STATE_IDLE;\n\n\t/* compute the ROM base or allocate a timer */\n\t//chip->rom = chip->rombase = *device->region();\n\tchip->romsize = 0x00;\n\tchip->rom = chip->rombase = NULL;\n\t//if (chip->rom == NULL)\n\t//\tchip->timer = timer_alloc(device->machine, upd7759_slave_update, chip);\n\tchip->romoffset = 0x00;\n\n\t/* set the DRQ callback */\n\t//chip->drqcallback = intf->drqcallback;\n\n\t/* assume /RESET and /START are both high */\n\tchip->reset = 1;\n\tchip->start = 1;\n\n\t/* toggle the reset line to finish the reset */\n\tupd7759_reset(chip);\n\n\t//register_for_save(chip, device);\n\t\n\treturn clock / 4;\n}\n\nvoid device_stop_upd7759(UINT8 ChipID)\n{\n\tupd7759_state *chip = &UPD7759Data[ChipID];\n\t\n\tfree(chip->rombase);\tchip->rombase = NULL;\n\t\n\treturn;\n}\n\n\n\n/************************************************************\n\n    I/O handlers\n\n*************************************************************/\n\n//void upd7759_reset_w(running_device *device, UINT8 data)\nvoid upd7759_reset_w(UINT8 ChipID, UINT8 data)\n{\n\t/* update the reset value */\n\t//upd7759_state *chip = get_safe_token(device);\n\tupd7759_state *chip = &UPD7759Data[ChipID];\n\tUINT8 oldreset = chip->reset;\n\tchip->reset = (data != 0);\n\n\t/* update the stream first */\n\t//stream_update(chip->channel);\n\n\t/* on the falling edge, reset everything */\n\tif (oldreset && !chip->reset)\n\t\tupd7759_reset(chip);\n}\n\n//void upd7759_start_w(running_device *device, UINT8 data)\nvoid upd7759_start_w(UINT8 ChipID, UINT8 data)\n{\n\t/* update the start value */\n\t//upd7759_state *chip = get_safe_token(device);\n\tupd7759_state *chip = &UPD7759Data[ChipID];\n\tUINT8 oldstart = chip->start;\n\tchip->start = (data != 0);\n\n\tif (DEBUG_STATES) logerror(\"upd7759_start_w: %d->%d\\n\", oldstart, chip->start);\n\n\t/* update the stream first */\n\t//stream_update(chip->channel);\n\n\t/* on the rising edge, if we're idle, start going, but not if we're held in reset */\n\tif (chip->state == STATE_IDLE && !oldstart && chip->start && chip->reset)\n\t{\n\t\tchip->state = STATE_START;\n\n\t\t/* for slave mode, start the timer going */\n\t\t//if (chip->timer)\n\t\t//\ttimer_adjust_oneshot(chip->timer, attotime_zero, 0);\n\t\tchip->clocks_left = 0;\n\t}\n}\n\n\n//WRITE8_DEVICE_HANDLER( upd7759_port_w )\nvoid upd7759_port_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t/* update the FIFO value */\n\t//upd7759_state *chip = get_safe_token(device);\n\tupd7759_state *chip = &UPD7759Data[ChipID];\n\t\n\tif (! chip->ChipMode)\n\t{\n\t\tchip->fifo_in = data;\n\t}\n\telse\n\t{\n\t\t// Valley Bell: added FIFO buffer for Slave mode\n\t\tchip->data_buf[chip->dbuf_pos_write] = data;\n\t\tchip->dbuf_pos_write ++;\n\t\tchip->dbuf_pos_write &= 0x3F;\n\t}\n}\n\n\n//int upd7759_busy_r(running_device *device)\nint upd7759_busy_r(UINT8 ChipID)\n{\n\t/* return /BUSY */\n\t//upd7759_state *chip = get_safe_token(device);\n\tupd7759_state *chip = &UPD7759Data[ChipID];\n\treturn (chip->state == STATE_IDLE);\n}\n\n\n//void upd7759_set_bank_base(running_device *device, UINT32 base)\nvoid upd7759_set_bank_base(UINT8 ChipID, UINT32 base)\n{\n\t//upd7759_state *chip = get_safe_token(device);\n\tupd7759_state *chip = &UPD7759Data[ChipID];\n\tchip->rom = chip->rombase + base;\n\tchip->romoffset = base;\n}\n\nvoid upd7759_write(UINT8 ChipID, UINT8 Port, UINT8 Data)\n{\n\tswitch(Port)\n\t{\n\tcase 0x00:\n\t\tupd7759_reset_w(ChipID, Data);\n\t\tbreak;\n\tcase 0x01:\n\t\tupd7759_start_w(ChipID, Data);\n\t\tbreak;\n\tcase 0x02:\n\t\tupd7759_port_w(ChipID, 0x00, Data);\n\t\tbreak;\n\tcase 0x03:\n\t\tupd7759_set_bank_base(ChipID, Data * 0x20000);\n\t\tbreak;\n\t}\n\t\n\treturn;\n}\n\nvoid upd7759_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData)\n{\n\tupd7759_state *chip = &UPD7759Data[ChipID];\n\t\n\tif (chip->romsize != ROMSize)\n\t{\n\t\tchip->rombase = (UINT8*)realloc(chip->rombase, ROMSize);\n\t\tchip->romsize = ROMSize;\n\t\tmemset(chip->rombase, 0xFF, ROMSize);\n\t\t\n\t\tchip->rom = chip->rombase + chip->romoffset;\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(chip->rombase + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( upd7759 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(upd7759_state);\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( upd7759 );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( upd7759 );\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"UPD7759\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"NEC ADPCM\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n\n\n//DEFINE_LEGACY_SOUND_DEVICE(UPD7759, upd7759);\n"
  },
  {
    "path": "VGMPlay/chips/upd7759.h",
    "content": "#pragma once\n\n//#include \"devlegcy.h\"\n\n/* There are two modes for the uPD7759, selected through the !MD pin.\n   This is the mode select input.  High is stand alone, low is slave.\n   We're making the assumption that nobody switches modes through\n   software. */\n\n#define UPD7759_STANDARD_CLOCK\t\t640000\n\ntypedef struct _upd7759_interface upd7759_interface;\nstruct _upd7759_interface\n{\n\t//void (*drqcallback)(running_device *device, int param);\t/* drq callback (per chip, slave mode only) */\n\tvoid (*drqcallback)(int param);\t/* drq callback (per chip, slave mode only) */\n};\n\nvoid upd7759_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nvoid device_reset_upd7759(UINT8 ChipID);\nint device_start_upd7759(UINT8 ChipID, int clock);\nvoid device_stop_upd7759(UINT8 ChipID);\n\n//void upd7759_set_bank_base(running_device *device, offs_t base);\n\n//void upd7759_reset_w(running_device *device, UINT8 data);\n//void upd7759_start_w(running_device *device, UINT8 data);\n//int upd7759_busy_r(running_device *device);\n//WRITE8_DEVICE_HANDLER( upd7759_port_w );\n\nvoid upd7759_set_bank_base(UINT8 ChipID, offs_t base);\n\nvoid upd7759_reset_w(UINT8 ChipID, UINT8 data);\nvoid upd7759_start_w(UINT8 ChipID, UINT8 data);\nint upd7759_busy_r(UINT8 ChipID);\nvoid upd7759_port_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\nvoid upd7759_write(UINT8 ChipID, UINT8 Port, UINT8 Data);\nvoid upd7759_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData);\n\n//DECLARE_LEGACY_SOUND_DEVICE(UPD7759, upd7759);\n"
  },
  {
    "path": "VGMPlay/chips/vrc7tone.h",
    "content": "/* VRC7 VOICE */\n/* Dumped via VRC7 debug mode by Nuke.YKT */\n0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n0x03, 0x21, 0x05, 0x06, 0xE8, 0x81, 0x42, 0x27,\n0x13, 0x41, 0x14, 0x0D, 0xD8, 0xF6, 0x23, 0x12,\n0x11, 0x11, 0x08, 0x08, 0xFA, 0xB2, 0x20, 0x12,\n0x31, 0x61, 0x0C, 0x07, 0xA8, 0x64, 0x61, 0x27,\n0x32, 0x21, 0x1E, 0x06, 0xE1, 0x76, 0x01, 0x28,\n0x02, 0x01, 0x06, 0x00, 0xA3, 0xE2, 0xF4, 0xF4,\n0x21, 0x61, 0x1D, 0x07, 0x82, 0x81, 0x11, 0x07,\n0x23, 0x21, 0x22, 0x17, 0xA2, 0x72, 0x01, 0x17,\n0x35, 0x11, 0x25, 0x00, 0x40, 0x73, 0x72, 0x01,\n0xB5, 0x01, 0x0F, 0x0F, 0xA8, 0xA5, 0x51, 0x02,\n0x17, 0xC1, 0x24, 0x07, 0xF8, 0xF8, 0x22, 0x12,\n0x71, 0x23, 0x11, 0x06, 0x65, 0x74, 0x18, 0x16,\n0x01, 0x02, 0xD3, 0x05, 0xC9, 0x95, 0x03, 0x02,\n0x61, 0x63, 0x0C, 0x00, 0x94, 0xC0, 0x33, 0xF6,\n0x21, 0x72, 0x0D, 0x00, 0xC1, 0xD5, 0x56, 0x06,\n0x01, 0x01, 0x18, 0x0F, 0xDF, 0xF8, 0x6A, 0x6D,\n0x01, 0x01, 0x00, 0x00, 0xC8, 0xD8, 0xA7, 0x68,\n0x05, 0x01, 0x00, 0x00, 0xF8, 0xAA, 0x59, 0x55,\n"
  },
  {
    "path": "VGMPlay/chips/vsu.c",
    "content": "/* Mednafen - Multi-system Emulator\n\t*\n\t* This program is free software; you can redistribute it and/or modify\n\t* it under the terms of the GNU General Public License as published by\n\t* the Free Software Foundation; either version 2 of the License, or\n\t* (at your option) any later version.\n\t*\n\t* This program is distributed in the hope that it will be useful,\n\t* but WITHOUT ANY WARRANTY; without even the implied warranty of\n\t* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\t* GNU General Public License for more details.\n\t*\n\t* You should have received a copy of the GNU General Public License\n\t* along with this program; if not, write to the Free Software\n\t* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\t*/\n\n//#include \"vb.h\"\n#include <string.h>\t// for memset\n#include \"mamedef.h\"\n#include \"vsu.h\"\n\ntypedef struct\n{\n\tUINT8 IntlControl[6];\n\tUINT8 LeftLevel[6];\n\tUINT8 RightLevel[6];\n\tUINT16 Frequency[6];\n\tUINT16 EnvControl[6];\t// Channel 5/6 extra functionality tacked on too.\n\n\tUINT8 RAMAddress[6];\n\n\tUINT8 SweepControl;\n\n\tUINT8 WaveData[5][0x20];\n\n\tUINT8 ModData[0x20];\n\n\t//\n\t//\n\t//\n\tINT32 EffFreq[6];\n\tINT32 Envelope[6];\n\n\tINT32 WavePos[6];\n\tINT32 ModWavePos;\n\n\tINT32 LatcherClockDivider[6];\n\n\tINT32 FreqCounter[6];\n\tINT32 IntervalCounter[6];\n\tINT32 EnvelopeCounter[6];\n\tINT32 SweepModCounter;\n\n\tINT32 EffectsClockDivider[6];\n\tINT32 IntervalClockDivider[6];\n\tINT32 EnvelopeClockDivider[6];\n\tINT32 SweepModClockDivider;\n\n\tINT32 NoiseLatcherClockDivider;\n\tUINT32 NoiseLatcher;\n\n\tUINT32 lfsr;\n\n\t//INT32 last_output[6][2];\n\tINT32 last_ts;\n\n\t//Blip_Buffer *sbuf[2];\n\t//Blip_Synth<blip_good_quality, 1024> Synth;\n\tint clock;\n\tint smplrate;\n\tUINT8 Muted[6];\n\t// values for Timing Calculation\n\tint tm_smpl;\n\tint tm_clk;\n} vsu_state;\n\nstatic void VSU_Power(vsu_state* chip);\n//void VSU_Write(UINT8 ChipID, UINT32 A, UINT8 V);\n\nINLINE void VSU_CalcCurrentOutput(vsu_state* chip, int ch, int* left, int* right);\nstatic void VSU_Update(vsu_state* chip, INT32 timestamp, int* outleft, int* outright);\n\n\nstatic const int Tap_LUT[8] = { 15 - 1, 11 - 1, 14 - 1, 5 - 1, 9 - 1, 7 - 1, 10 - 1, 12 - 1 };\n\nextern UINT32 SampleRate;\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\n#define MAX_CHIPS\t0x02\nstatic vsu_state VSUData[MAX_CHIPS];\n\nstatic void VSU_Power(vsu_state* chip)\n{\n\tint ch;\n\t\n\tchip->SweepControl = 0;\n\tchip->SweepModCounter = 0;\n\tchip->SweepModClockDivider = 1;\n\n\tfor(ch = 0; ch < 6; ch++)\n\t{\n\t\tchip->IntlControl[ch] = 0;\n\t\tchip->LeftLevel[ch] = 0;\n\t\tchip->RightLevel[ch] = 0;\n\t\tchip->Frequency[ch] = 0;\n\t\tchip->EnvControl[ch] = 0;\n\t\tchip->RAMAddress[ch] = 0;\n\n\t\tchip->EffFreq[ch] = 0;\n\t\tchip->Envelope[ch] = 0;\n\t\tchip->WavePos[ch] = 0;\n\t\tchip->FreqCounter[ch] = 0;\n\t\tchip->IntervalCounter[ch] = 0;\n\t\tchip->EnvelopeCounter[ch] = 0;\n\n\t\tchip->EffectsClockDivider[ch] = 4800;\n\t\tchip->IntervalClockDivider[ch] = 4;\n\t\tchip->EnvelopeClockDivider[ch] = 4;\n\n\t\tchip->LatcherClockDivider[ch] = 120;\n\t}\n\n\n\tchip->NoiseLatcherClockDivider = 120;\n\tchip->NoiseLatcher = 0;\n\n\tmemset(chip->WaveData, 0, sizeof(chip->WaveData));\n\tmemset(chip->ModData, 0, sizeof(chip->ModData));\n\n\tchip->last_ts = 0;\n}\n\nvoid VSU_Write(UINT8 ChipID, UINT32 A, UINT8 V)\n{\n\tvsu_state* chip = &VSUData[ChipID];\n\t\n\tA <<= 2;\n\tA &= 0x7FF;\n\n\t//Update(timestamp);\n\n\t//printf(\"VSU Write: %d, %08x %02x\\n\", timestamp, A, V);\n\n\tif(A < 0x280)\n\t\tchip->WaveData[A >> 7][(A >> 2) & 0x1F] = V & 0x3F;\n\telse if(A < 0x400)\n\t{\n\t\t//if(A >= 0x300)\n\t\t// printf(\"Modulation mirror write? %08x %02x\\n\", A, V);\n\t\tchip->ModData[(A >> 2) & 0x1F] = V;\n\t}\n\telse if(A < 0x600)\n\t{\n\t\tint ch = (A >> 6) & 0xF;\n\n\t\t//if(ch < 6)\n\t\t//printf(\"Ch: %d, Reg: %d, Value: %02x\\n\", ch, (A >> 2) & 0xF, V);\n\t\n\t\tif(ch > 5)\n\t\t{\n\t\t\tif(A == 0x580 && (V & 1))\n\t\t\t{\n\t\t\t\tint i;\n\t\t\t\t//puts(\"STOP, HAMMER TIME\");\n\t\t\t\tfor(i = 0; i < 6; i++)\n\t\t\t\t\tchip->IntlControl[i] &= ~0x80;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\tswitch((A >> 2) & 0xF)\n\t\t\t{\n\t\t\tcase 0x0:\n\t\t\t\tchip->IntlControl[ch] = V & ~0x40;\n\n\t\t\t\tif(V & 0x80)\n\t\t\t\t{\n\t\t\t\t\tchip->EffFreq[ch] = chip->Frequency[ch];\n\t\t\t\t\tif(ch == 5)\n\t\t\t\t\t\tchip->FreqCounter[ch] = 10 * (2048 - chip->EffFreq[ch]);\n\t\t\t\t\telse\n\t\t\t\t\t\tchip->FreqCounter[ch] = 2048 - chip->EffFreq[ch];\n\t\t\t\t\tchip->IntervalCounter[ch] = (V & 0x1F) + 1;\n\t\t\t\t\tchip->EnvelopeCounter[ch] = (chip->EnvControl[ch] & 0x7) + 1;\n\n\t\t\t\t\tif(ch == 4)\n\t\t\t\t\t{\n\t\t\t\t\t\tchip->SweepModCounter = (chip->SweepControl >> 4) & 7;\n\t\t\t\t\t\tchip->SweepModClockDivider = (chip->SweepControl & 0x80) ? 8 : 1;\n\t\t\t\t\t\tchip->ModWavePos = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tchip->WavePos[ch] = 0;\n\n\t\t\t\t\tif(ch == 5)\n\t\t\t\t\t\tchip->lfsr = 1;\n\n\t\t\t\t\t//if(!(chip->IntlControl[ch] & 0x80))\n\t\t\t\t\t// chip->Envelope[ch] = (chip->EnvControl[ch] >> 4) & 0xF;\n\n\t\t\t\t\tchip->EffectsClockDivider[ch] = 4800;\n\t\t\t\t\tchip->IntervalClockDivider[ch] = 4;\n\t\t\t\t\tchip->EnvelopeClockDivider[ch] = 4;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 0x1:\n\t\t\t\tchip->LeftLevel[ch] = (V >> 4) & 0xF;\n\t\t\t\tchip->RightLevel[ch] = (V >> 0) & 0xF;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x2:\n\t\t\t\tchip->Frequency[ch] &= 0xFF00;\n\t\t\t\tchip->Frequency[ch] |= V << 0;\n\t\t\t\tchip->EffFreq[ch] &= 0xFF00;\n\t\t\t\tchip->EffFreq[ch] |= V << 0;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x3:\n\t\t\t\tchip->Frequency[ch] &= 0x00FF;\n\t\t\t\tchip->Frequency[ch] |= (V & 0x7) << 8;\n\t\t\t\tchip->EffFreq[ch] &= 0x00FF;\n\t\t\t\tchip->EffFreq[ch] |= (V & 0x7) << 8;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x4:\n\t\t\t\tchip->EnvControl[ch] &= 0xFF00;\n\t\t\t\tchip->EnvControl[ch] |= V << 0;\n\n\t\t\t\tchip->Envelope[ch] = (V >> 4) & 0xF;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x5:\n\t\t\t\tchip->EnvControl[ch] &= 0x00FF;\n\t\t\t\tif(ch == 4)\n\t\t\t\t\tchip->EnvControl[ch] |= (V & 0x73) << 8;\n\t\t\t\telse if(ch == 5)\n\t\t\t\t\tchip->EnvControl[ch] |= (V & 0x73) << 8;\n\t\t\t\telse\n\t\t\t\t\tchip->EnvControl[ch] |= (V & 0x03) << 8;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x6:\n\t\t\t\tchip->RAMAddress[ch] = V & 0xF;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x7:\n\t\t\t\tif(ch == 4)\n\t\t\t\t{\n\t\t\t\t\tchip->SweepControl = V;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t}\n}\n\nINLINE void VSU_CalcCurrentOutput(vsu_state* chip, int ch, int* left, int* right)\n{\n\tint WD;\n\tint l_ol, r_ol;\n\n\tif(!(chip->IntlControl[ch] & 0x80) || chip->Muted[ch])\n\t{\n\t\t*left = *right = 0;\n\t\treturn;\n\t}\n\n\tif(ch == 5)\n\t\tWD = chip->NoiseLatcher;\t//(NoiseLatcher << 6) - NoiseLatcher;\n\telse\n\t{\n\t\tif(chip->RAMAddress[ch] > 4)\n\t\t\tWD = 0x20;\t//0;\n\t\telse\n\t\t\tWD = chip->WaveData[chip->RAMAddress[ch]][chip->WavePos[ch]];\t// - 0x20;\n\t}\n\tl_ol = chip->Envelope[ch] * chip->LeftLevel[ch];\n\tif(l_ol)\n\t{\n\t\tl_ol >>= 3;\n\t\tl_ol += 1;\n\t}\n\n\tr_ol = chip->Envelope[ch] * chip->RightLevel[ch];\n\tif(r_ol)\n\t{\n\t\tr_ol >>= 3;\n\t\tr_ol += 1;\n\t}\n\n\tWD -= 0x20;\n\t(*left) += WD * l_ol;\n\t(*right) += WD * r_ol;\n\treturn;\n}\n\nstatic void VSU_Update(vsu_state* chip, INT32 timestamp, int* outleft, int* outright)\n{\n\t//int left, right;\n\tint ch;\n\n\t*outleft = 0;\n\t*outright = 0;\n\t\n\t//puts(\"VSU Start\");\n\tfor(ch = 0; ch < 6; ch++)\n\t{\n\t\tINT32 clocks = timestamp - chip->last_ts;\n\t\t//INT32 running_timestamp = chip->last_ts;\n\n\t\tif(!(chip->IntlControl[ch] & 0x80) || chip->Muted[ch])\n\t\t\tcontinue;\t// channel disabled - don't add anything to output\n\t\t\n\t\t//// Output sound here\n\t\t//VSU_CalcCurrentOutput(chip, ch, &left, &right);\n\t\t//Synth.offset_inline(running_timestamp, left - chip->last_output[ch][0], sbuf[0]);\n\t\t//Synth.offset_inline(running_timestamp, right - chip->last_output[ch][1], sbuf[1]);\n\t\t//chip->last_output[ch][0] = left;\n\t\t//chip->last_output[ch][1] = right;\n\n\t\t//if(!(chip->IntlControl[ch] & 0x80))\n\t\t//\tcontinue;\n\n\t\twhile(clocks > 0)\n\t\t{\n\t\t\tINT32 chunk_clocks = clocks;\n\n\t\t\tif(chunk_clocks > chip->EffectsClockDivider[ch])\n\t\t\t\tchunk_clocks = chip->EffectsClockDivider[ch];\n\n\t\t\tif(ch == 5)\n\t\t\t{\n\t\t\t\tif(chunk_clocks > chip->NoiseLatcherClockDivider)\n\t\t\t\t\tchunk_clocks = chip->NoiseLatcherClockDivider;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(chip->EffFreq[ch] >= 2040)\n\t\t\t\t{\n\t\t\t\t\tif(chunk_clocks > chip->LatcherClockDivider[ch])\n\t\t\t\t\t\tchunk_clocks = chip->LatcherClockDivider[ch];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(chunk_clocks > chip->FreqCounter[ch])\n\t\t\t\t\t\tchunk_clocks = chip->FreqCounter[ch];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(ch == 5 && chunk_clocks > chip->NoiseLatcherClockDivider)\n\t\t\t\tchunk_clocks = chip->NoiseLatcherClockDivider;\n\n\t\t\tchip->FreqCounter[ch] -= chunk_clocks;\n\t\t\twhile(chip->FreqCounter[ch] <= 0)\n\t\t\t{\n\t\t\t\tif(ch == 5)\n\t\t\t\t{\n\t\t\t\t\tint feedback = ((chip->lfsr >> 7) & 1) ^ ((chip->lfsr >> Tap_LUT[(chip->EnvControl[5] >> 12) & 0x7]) & 1);\n\t\t\t\t\tchip->lfsr = ((chip->lfsr << 1) & 0x7FFF) | feedback;\n\t\n\t\t\t\t\tchip->FreqCounter[ch] += 10 * (2048 - chip->EffFreq[ch]);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tchip->FreqCounter[ch] += 2048 - chip->EffFreq[ch];\n\t\t\t\t\tchip->WavePos[ch] = (chip->WavePos[ch] + 1) & 0x1F;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchip->LatcherClockDivider[ch] -= chunk_clocks;\n\t\t\twhile(chip->LatcherClockDivider[ch] <= 0)\n\t\t\t\tchip->LatcherClockDivider[ch] += 120;\n\n\t\t\tif(ch == 5)\n\t\t\t{\n\t\t\t\tchip->NoiseLatcherClockDivider -= chunk_clocks;\n\t\t\t\tif(!chip->NoiseLatcherClockDivider)\n\t\t\t\t{\n\t\t\t\t\tchip->NoiseLatcherClockDivider = 120;\n\t\t\t\t\tchip->NoiseLatcher = ((chip->lfsr & 1) << 6) - (chip->lfsr & 1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchip->EffectsClockDivider[ch] -= chunk_clocks;\n\t\t\twhile(chip->EffectsClockDivider[ch] <= 0)\n\t\t\t{\n\t\t\t\tchip->EffectsClockDivider[ch] += 4800;\n\n\t\t\t\tchip->IntervalClockDivider[ch]--;\n\t\t\t\twhile(chip->IntervalClockDivider[ch] <= 0)\n\t\t\t\t{\n\t\t\t\t\tchip->IntervalClockDivider[ch] += 4;\n\n\t\t\t\t\tif(chip->IntlControl[ch] & 0x20)\n\t\t\t\t\t{\n\t\t\t\t\t\tchip->IntervalCounter[ch]--;\n\t\t\t\t\t\tif(!chip->IntervalCounter[ch])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tchip->IntlControl[ch] &= ~0x80;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tchip->EnvelopeClockDivider[ch]--;\n\t\t\t\t\twhile(chip->EnvelopeClockDivider[ch] <= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tchip->EnvelopeClockDivider[ch] += 4;\n\n\t\t\t\t\t\tif(chip->EnvControl[ch] & 0x0100)\t\t\t// Enveloping enabled?\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tchip->EnvelopeCounter[ch]--;\n\t\t\t\t\t\t\tif(!chip->EnvelopeCounter[ch])\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tchip->EnvelopeCounter[ch] = (chip->EnvControl[ch] & 0x7) + 1;\n\n\t\t\t\t\t\t\t\tif(chip->EnvControl[ch] & 0x0008)\t// Grow\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif(chip->Envelope[ch] < 0xF || (chip->EnvControl[ch] & 0x200))\n\t\t\t\t\t\t\t\t\t\tchip->Envelope[ch] = (chip->Envelope[ch] + 1) & 0xF;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\t\t\t\t\t\t// Decay\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif(chip->Envelope[ch] > 0 || (chip->EnvControl[ch] & 0x200))\n\t\t\t\t\t\t\t\t\t\tchip->Envelope[ch] = (chip->Envelope[ch] - 1) & 0xF;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} // end while(chip->EnvelopeClockDivider[ch] <= 0)\n\t\t\t\t} // end while(chip->IntervalClockDivider[ch] <= 0)\n\n\t\t\t\tif(ch == 4)\n\t\t\t\t{\n\t\t\t\t\tchip->SweepModClockDivider--;\n\t\t\t\t\twhile(chip->SweepModClockDivider <= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tchip->SweepModClockDivider += (chip->SweepControl & 0x80) ? 8 : 1;\n\n\t\t\t\t\t\tif(((chip->SweepControl >> 4) & 0x7) && (chip->EnvControl[ch] & 0x4000))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(chip->SweepModCounter)\n\t\t\t\t\t\t\t\tchip->SweepModCounter--;\n\n\t\t\t\t\t\t\tif(!chip->SweepModCounter)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tchip->SweepModCounter = (chip->SweepControl >> 4) & 0x7;\n\n\t\t\t\t\t\t\t\tif(chip->EnvControl[ch] & 0x1000)\t// Modulation\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif(chip->ModWavePos < 32 || (chip->EnvControl[ch] & 0x2000))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tchip->ModWavePos &= 0x1F;\n\n\t\t\t\t\t\t\t\t\t\tchip->EffFreq[ch] = (chip->EffFreq[ch] + (INT8)chip->ModData[chip->ModWavePos]);\n\t\t\t\t\t\t\t\t\t\tif(chip->EffFreq[ch] < 0)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t//puts(\"Underflow\");\n\t\t\t\t\t\t\t\t\t\t\tchip->EffFreq[ch] = 0;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if(chip->EffFreq[ch] > 0x7FF)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t//puts(\"Overflow\");\n\t\t\t\t\t\t\t\t\t\t\tchip->EffFreq[ch] = 0x7FF;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tchip->ModWavePos++;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t//puts(\"Mod\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\t\t\t\t\t\t// Sweep\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tINT32 delta = chip->EffFreq[ch] >> (chip->SweepControl & 0x7);\n\t\t\t\t\t\t\t\t\tINT32 NewFreq = chip->EffFreq[ch] + ((chip->SweepControl & 0x8) ? delta : -delta);\n\n\t\t\t\t\t\t\t\t\t//printf(\"Sweep(%d): Old: %d, New: %d\\n\", ch, EffFreq[ch], NewFreq);\n\n\t\t\t\t\t\t\t\t\tif(NewFreq < 0)\n\t\t\t\t\t\t\t\t\t\tchip->EffFreq[ch] = 0;\n\t\t\t\t\t\t\t\t\telse if(NewFreq > 0x7FF)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t//chip->EffFreq[ch] = 0x7FF;\n\t\t\t\t\t\t\t\t\t\tchip->IntlControl[ch] &= ~0x80;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tchip->EffFreq[ch] = NewFreq;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} // end while(chip->SweepModClockDivider <= 0)\n\t\t\t\t} // end if(ch == 4)\n\t\t\t} // end while(chip->EffectsClockDivider[ch] <= 0)\n\t\t\tclocks -= chunk_clocks;\n\t\t\t//running_timestamp += chunk_clocks;\n\n\t\t\t// Output sound here too.\n\t\t\t//VSU_CalcCurrentOutput(chip, ch, &left, &right);\n\t\t\t//Synth.offset_inline(running_timestamp, left - chip->last_output[ch][0], sbuf[0]);\n\t\t\t//Synth.offset_inline(running_timestamp, right - chip->last_output[ch][1], sbuf[1]);\n\t\t\t//chip->last_output[ch][0] = left;\n\t\t\t//chip->last_output[ch][1] = right;\n\t\t}\n\n\t\tVSU_CalcCurrentOutput(chip, ch, outleft, outright);\n\t}\n\tchip->last_ts = timestamp;\n\t//puts(\"VSU End\");\n}\n\n/*void VSU_EndFrame(INT32 timestamp)\n{\n\tUpdate(chip, timestamp);\n\tchip->last_ts = 0;\n}*/\n\n/*int VSU_StateAction(StateMem *sm, int load, int data_only)\n{\n\tSFORMAT StateRegs[] =\n\t{\n\t\tSFARRAY(IntlControl, 6),\n\t\tSFARRAY(LeftLevel, 6),\n\t\tSFARRAY(RightLevel, 6),\n\n\t\tSFARRAY16(Frequency, 6),\n\t\tSFARRAY16(EnvControl, 6),\n\t\tSFARRAY(RAMAddress, 6),\n\t\tSFVAR(SweepControl),\n\n\t\tSFARRAY(&WaveData[0][0], 5 * 0x20),\n\t\tSFARRAY(ModData, 0x20),\n\n\t\tSFARRAY32(EffFreq, 6),\n\t\tSFARRAY32(Envelope, 6),\n\t\n\t\tSFARRAY32(WavePos, 6),\n\n\t\tSFVAR(ModWavePos),\n\n\t\tSFARRAY32(LatcherClockDivider, 6),\n\t\tSFARRAY32(FreqCounter, 6),\n\t\tSFARRAY32(IntervalCounter, 6),\n\t\tSFARRAY32(EnvelopeCounter, 6),\n\n\t\tSFVAR(SweepModCounter),\n\n\t\tSFARRAY32(EffectsClockDivider, 6),\n\t\tSFARRAY32(IntervalClockDivider, 6),\n\t\tSFARRAY32(EnvelopeClockDivider, 6),\n\n\t\tSFVAR(SweepModClockDivider),\n\n\t\tSFVAR(NoiseLatcherClockDivider),\n\t\tSFVAR(NoiseLatcher),\n\t\tSFVAR(lfsr),\n\t\tSFEND\n\t};\n\n\tint ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, \"VSU\");\n\n\n\tif(load)\n\t{\n\n\t}\n\n\treturn(ret);\n}*/\n\n\nvoid vsu_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tvsu_state* chip = &VSUData[ChipID];\n\tint curSmpl;\n\t\n\tfor (curSmpl = 0; curSmpl < samples; curSmpl ++)\n\t{\n\t\tchip->tm_smpl ++;\n\t\tchip->tm_clk = (int)((INT64)chip->tm_smpl * chip->clock / chip->smplrate);\n\t\t\n\t\tVSU_Update(chip, chip->tm_clk, &outputs[0][curSmpl], &outputs[1][curSmpl]);\n\t\tif (chip->last_ts >= chip->clock)\n\t\t{\n\t\t\tchip->last_ts -= chip->clock;\n\t\t\tchip->tm_clk -= chip->clock;\n\t\t\tchip->tm_smpl -= chip->smplrate;\n\t\t}\n\t\t\n\t\t// Volume per channel: 0x1F (envelope/volume) * 0x3F (unsigned sample) = 0x7A1 (~0x800)\n\t\t// I turned the samples into signed format (-0x20..0x1F), so the used range is +-0x400.\n\t\t// 16-bit values are up to 0x8000\n\t\t// 0x8000 / 0x400 / 6 = 5.33 (possible boost without clipping)\n\t\t// Because music usually doesn't use the maximum volume (SFX do), I boost by 2^3 = 8.\n\t\toutputs[0][curSmpl] <<= 3;\n\t\toutputs[1][curSmpl] <<= 3;\n\t}\n\treturn;\n}\n\nint device_start_vsu(UINT8 ChipID, int clock)\n{\n\tvsu_state* chip;\n\tUINT8 CurChn;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &VSUData[ChipID];\n\tchip->clock = clock;\n\tchip->smplrate = chip->clock / 120;\t// most effects run with a /120 divider\n\tif (((CHIP_SAMPLING_MODE & 0x01) && chip->smplrate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\tchip->smplrate = CHIP_SAMPLE_RATE;\n\t\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t\tchip->Muted[CurChn] = 0x00;\n\t\n\treturn chip->smplrate; \n}\n\nvoid device_stop_vsu(UINT8 ChipID)\n{\n\tvsu_state* chip = &VSUData[ChipID];\n}\n\nvoid device_reset_vsu(UINT8 ChipID)\n{\n\tvsu_state* chip = &VSUData[ChipID];\n\t\n\tVSU_Power(chip);\n\tchip->tm_smpl = 0;\n\tchip->tm_clk = 0;\n\t\n\treturn;\n}\n\n//void vsu_set_options(UINT16 Options);\n\nvoid vsu_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tvsu_state* chip = &VSUData[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 6; CurChn ++)\n\t\tchip->Muted[CurChn] = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/vsu.h",
    "content": "#ifndef __VB_VSU_H\n#define __VB_VSU_H\n\nvoid VSU_Write(UINT8 ChipID, UINT32 A, UINT8 V);\n\nvoid vsu_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\n\nint device_start_vsu(UINT8 ChipID, int clock);\nvoid device_stop_vsu(UINT8 ChipID);\nvoid device_reset_vsu(UINT8 ChipID);\n\n//void vsu_set_options(UINT16 Options);\nvoid vsu_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n#endif\t// __VB_VSU_H\n"
  },
  {
    "path": "VGMPlay/chips/ws_audio.c",
    "content": "\n#include <stdlib.h>\n#include <stddef.h>\t// for NULL\n#include <string.h>\t// for memset\n#include \"mamedef.h\"\n\ntypedef UINT8\tBYTE;\ntypedef UINT8\tbyte;\ntypedef UINT8\tuint8;\n\n//#include <windows.h>\n//#include \"types.h\"\n//#include \"./nec/necintrf.h\"\n//#include \"ws_memory.h\"\n#include \"ws_initialIo.h\"\n//#include \"ws_io.h\"\n#include \"ws_audio.h\"\n//#include \"wsr_player.h\"\n\n#define SNDP\tchip->ws_ioRam[0x80]\n#define SNDV\tchip->ws_ioRam[0x88]\n#define SNDSWP\tchip->ws_ioRam[0x8C]\n#define SWPSTP\tchip->ws_ioRam[0x8D]\n#define NSCTL\tchip->ws_ioRam[0x8E]\n#define WAVDTP\tchip->ws_ioRam[0x8F]\n#define SNDMOD\tchip->ws_ioRam[0x90]\n#define SNDOUT\tchip->ws_ioRam[0x91]\n#define PCSRL\tchip->ws_ioRam[0x92]\n#define PCSRH\tchip->ws_ioRam[0x93]\n#define DMASL\tchip->ws_ioRam[0x40]\n#define DMASH\tchip->ws_ioRam[0x41]\n#define DMASB\tchip->ws_ioRam[0x42]\n#define DMADB\tchip->ws_ioRam[0x43]\n#define DMADL\tchip->ws_ioRam[0x44]\n#define DMADH\tchip->ws_ioRam[0x45]\n#define DMACL\tchip->ws_ioRam[0x46]\n#define DMACH\tchip->ws_ioRam[0x47]\n#define DMACTL\tchip->ws_ioRam[0x48]\n#define SDMASL\tchip->ws_ioRam[0x4A]\n#define SDMASH\tchip->ws_ioRam[0x4B]\n#define SDMASB\tchip->ws_ioRam[0x4C]\n#define SDMACL\tchip->ws_ioRam[0x4E]\n#define SDMACH\tchip->ws_ioRam[0x4F]\n#define SDMACTL\tchip->ws_ioRam[0x52]\n\n//SoundDMA ̓]Ԋu\n// ۂ̐lȂ̂ŁA\\zł\n// TvOlĂ݂Ĉȉ̂悤ɂ\n// 12KHz = 1.00HBlank = 256cyclesԊu\n// 16KHz = 0.75HBlank = 192cyclesԊu\n// 20KHz = 0.60HBlank = 154cyclesԊu\n// 24KHz = 0.50HBlank = 128cyclesԊu\nconst int DMACycles[4] = { 256, 192, 154, 128 };\n\ntypedef struct\n{\n\tint wave;\n\tint lvol;\n\tint rvol;\n\tlong offset;\n\tlong delta;\n\tlong pos;\n\tUINT8 Muted;\n} WS_AUDIO;\n\ntypedef struct\n{\n\tWS_AUDIO ws_audio[4];\n\tint sweepDelta;\n\tint sweepOffset;\n\tint SweepTime;\n\tint SweepStep;\n\tint SweepCount;\n\tint SweepFreq;\n\tint NoiseType;\n\tint NoiseRng;\n\tint MainVolume;\n\tint PCMVolumeLeft;\n\tint PCMVolumeRight;\n\t//int WaveAdrs;\n\n\tUINT8\t ws_ioRam[0x100];\n\tUINT8\t*ws_internalRam;\n\t\n\tint clock;\n\tint smplrate;\n} wsa_state;\n\n#define DEFAULT_CLOCK\t3072000\n\n\nstatic void ws_audio_process(wsa_state* chip);\n\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\nextern UINT32 SampleRate;\n\n#define MAX_CHIPS\t0x02\nstatic wsa_state WSAData[MAX_CHIPS];\n\nint ws_audio_init(UINT8 ChipID, int clock)\n{\n\twsa_state* chip;\n\tUINT8 CurChn;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &WSAData[ChipID];\n\t\n\tchip->ws_internalRam = (UINT8*)malloc(0x4000);\t// actual size is 64 KB, but the audio chip can only access 16 KB\n\t\n\tchip->clock = clock;\n\tchip->smplrate = SampleRate;\n\tif (((CHIP_SAMPLING_MODE & 0x01) && chip->smplrate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\tchip->smplrate = CHIP_SAMPLE_RATE;\n\t\n\tfor (CurChn = 0; CurChn < 4; CurChn ++)\n\t\tchip->ws_audio[CurChn].Muted = 0x00;\n\t\n\treturn chip->smplrate; \n}\n\nvoid ws_audio_reset(UINT8 ChipID)\n{\n\twsa_state* chip = &WSAData[ChipID];\n\tint i;\n\t\n\tmemset(&chip->ws_audio, 0, sizeof(WS_AUDIO));\n\tchip->SweepTime = 0;\n\tchip->SweepStep = 0;\n\tchip->NoiseType = 0;\n\tchip->NoiseRng = 1;\n\tchip->MainVolume = 0x02;\t// 0x04\n\tchip->PCMVolumeLeft = 0;\n\tchip->PCMVolumeRight = 0;\n\t\n\tchip->sweepDelta = chip->clock * 256 / chip->smplrate;\n\tchip->sweepOffset = 0;\n\t\n\tfor (i=0x80;i<0xc9;i++)\n\t\tws_audio_port_write(ChipID, i, initialIoValue[i]);\n}\n\nvoid ws_audio_done(UINT8 ChipID)\n{\n\twsa_state* chip = &WSAData[ChipID];\n\t\n\tfree(chip->ws_internalRam);\n\tchip->ws_internalRam = NULL;\n\t\n\treturn;\n}\n\nvoid ws_audio_update(UINT8 ChipID, stream_sample_t** buffer, int length)\n{\n\twsa_state* chip = &WSAData[ChipID];\n\tstream_sample_t* bufL;\n\tstream_sample_t* bufR;\n\tint i, ch, cnt;\n\tlong w, l, r;\n\n\tbufL = buffer[0];\n\tbufR = buffer[1];\n\tfor (i=0; i<length; i++)\n\t{\n\t\tchip->sweepOffset += chip->sweepDelta;\n\t\twhile(chip->sweepOffset >= 0x10000)\n\t\t{\n\t\t\tchip->sweepOffset -= 0x10000;\n\t\t\tws_audio_process(chip);\n\t\t}\n\t\tl = r = 0;\n\n\t\tfor (ch=0; ch<4; ch++)\n\t\t{\n\t\t\tif (chip->ws_audio[ch].Muted)\n\t\t\t\tcontinue;\n\t\t\t\n\t\t\tif ((ch==1) && (SNDMOD&0x20))\n\t\t\t{\n\t\t\t\t// Voiceo\n\t\t\t\tw = chip->ws_ioRam[0x89];\n\t\t\t\tw -= 0x80;\n\t\t\t\tl += chip->PCMVolumeLeft  * w;\n\t\t\t\tr += chip->PCMVolumeRight * w;\n\t\t\t}\n\t\t\telse if (SNDMOD&(1<<ch))\n\t\t\t{\n\t\t\t\tif ((ch==3) && (SNDMOD&0x80))\n\t\t\t\t{\n\t\t\t\t\t//Noise\n\n\t\t\t\t\t//OSWAN̋[̏Ɠ̂\n#define BIT(n) (1<<n)\n\t\t\t\t\tconst unsigned long noise_mask[8] =\n\t\t\t\t\t{\n\t\t\t\t\t\tBIT(0)|BIT(1),\n\t\t\t\t\t\tBIT(0)|BIT(1)|BIT(4)|BIT(5),\n\t\t\t\t\t\tBIT(0)|BIT(1)|BIT(3)|BIT(4),\n\t\t\t\t\t\tBIT(0)|BIT(1)|BIT(4)|BIT(6),\n\t\t\t\t\t\tBIT(0)|BIT(2),\n\t\t\t\t\t\tBIT(0)|BIT(3),\n\t\t\t\t\t\tBIT(0)|BIT(4),\n\t\t\t\t\t\tBIT(0)|BIT(2)|BIT(3)|BIT(4)\n\t\t\t\t\t};\n\n\t\t\t\t\tconst unsigned long noise_bit[8] =\n\t\t\t\t\t{\n\t\t\t\t\t\tBIT(15),\n\t\t\t\t\t\tBIT(14),\n\t\t\t\t\t\tBIT(13),\n\t\t\t\t\t\tBIT(12),\n\t\t\t\t\t\tBIT(11),\n\t\t\t\t\t\tBIT(10),\n\t\t\t\t\t\tBIT(9),\n\t\t\t\t\t\tBIT(8)\n\t\t\t\t\t};\n\n\t\t\t\t\tint Masked, XorReg;\n\n\t\t\t\t\tchip->ws_audio[ch].offset += chip->ws_audio[ch].delta;\n\t\t\t\t\tcnt = chip->ws_audio[ch].offset>>16;\n\t\t\t\t\tchip->ws_audio[ch].offset &= 0xffff;\n\t\t\t\t\twhile (cnt > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tcnt--;\n\n\t\t\t\t\t\tchip->NoiseRng &= noise_bit[chip->NoiseType]-1;\n\t\t\t\t\t\tif (!chip->NoiseRng) chip->NoiseRng = noise_bit[chip->NoiseType]-1;\n\n\t\t\t\t\t\tMasked = chip->NoiseRng & noise_mask[chip->NoiseType];\n\t\t\t\t\t\tXorReg = 0;\n\t\t\t\t\t\twhile (Masked)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tXorReg ^= Masked&1;\n\t\t\t\t\t\t\tMasked >>= 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (XorReg)\n\t\t\t\t\t\t\tchip->NoiseRng |= noise_bit[chip->NoiseType];\n\t\t\t\t\t\tchip->NoiseRng >>= 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tPCSRL = (byte)(chip->NoiseRng&0xff);\n\t\t\t\t\tPCSRH = (byte)((chip->NoiseRng>>8)&0x7f);\n\n\t\t\t\t\tw = (chip->NoiseRng&1)? 0x7f:-0x80;\n\t\t\t\t\tl += chip->ws_audio[ch].lvol * w;\n\t\t\t\t\tr += chip->ws_audio[ch].rvol * w;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tchip->ws_audio[ch].offset += chip->ws_audio[ch].delta;\n\t\t\t\t\tcnt = chip->ws_audio[ch].offset>>16;\n\t\t\t\t\tchip->ws_audio[ch].offset &= 0xffff;\n\t\t\t\t\tchip->ws_audio[ch].pos += cnt;\n\t\t\t\t\tchip->ws_audio[ch].pos &= 0x1f;\n\t\t\t\t\tw = chip->ws_internalRam[(chip->ws_audio[ch].wave&0xFFF0) + (chip->ws_audio[ch].pos>>1)];\n\t\t\t\t\tif ((chip->ws_audio[ch].pos&1) == 0)\n\t\t\t\t\t\tw = (w<<4)&0xf0;\t//ʃju\n\t\t\t\t\telse\n\t\t\t\t\t\tw = w&0xf0;\t\t\t//ʃju\n\t\t\t\t\tw -= 0x80;\n\t\t\t\t\tl += chip->ws_audio[ch].lvol * w;\n\t\t\t\t\tr += chip->ws_audio[ch].rvol * w;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*l = l * chip->MainVolume;\n\t\tif (l > 0x7fff) l = 0x7fff;\n\t\telse if (l < -0x8000) l = -0x8000;\n\t\tr = r * chip->MainVolume;\n\t\tif (r > 0x7fff) r = 0x7fff;\n\t\telse if (r < -0x8000) r = -0x8000;\n\n\t\t*buffer++ = (short)l;\n\t\t*buffer++ = (short)r;*/\n\t\tbufL[i] = l * chip->MainVolume;\n\t\tbufR[i] = r * chip->MainVolume;\n\t}\n}\n\nvoid ws_audio_port_write(UINT8 ChipID, BYTE port, BYTE value)\n{\n\twsa_state* chip = &WSAData[ChipID];\n\tint i;\n\tlong freq;\n\n\t//Update_SampleData();\n\n\tchip->ws_ioRam[port]=value;\n\n\tswitch (port)\n\t{\n\t// 0x80-0x87̎gWX^ɂ\n\t// - bN}&tHe0x0f̋Ȃł́Ag=0xFFFF ̉sv\n\t// - fWfB[vWFNg0x0d̋Ȃ̃mCY g=0x07FF ŉo\n\t// ܂A0xFFFF ̎oȂĂƂ낤B\n\t//   łA0x07FF ̎oȂǁAmCYôB\n\tcase 0x80:\n\tcase 0x81:\ti=(((unsigned int)chip->ws_ioRam[0x81])<<8)+((unsigned int)chip->ws_ioRam[0x80]);\n\t\t\t\tif (i == 0xffff)\n\t\t\t\t\tfreq = 0;\n\t\t\t\telse\n\t\t\t\t\tfreq = chip->clock/(2048-(i&0x7ff));\n\t\t\t\tchip->ws_audio[0].delta = (long)((float)freq*(float)65536/(float)chip->smplrate);\n\t\t\t\tbreak;\n\tcase 0x82:\n\tcase 0x83:\ti=(((unsigned int)chip->ws_ioRam[0x83])<<8)+((unsigned int)chip->ws_ioRam[0x82]);\n\t\t\t\tif (i == 0xffff)\n\t\t\t\t\tfreq = 0;\n\t\t\t\telse\n\t\t\t\t\tfreq = chip->clock/(2048-(i&0x7ff));\n\t\t\t\tchip->ws_audio[1].delta = (long)((float)freq*(float)65536/(float)chip->smplrate);\n\t\t\t\tbreak;\n\tcase 0x84:\n\tcase 0x85:\ti=(((unsigned int)chip->ws_ioRam[0x85])<<8)+((unsigned int)chip->ws_ioRam[0x84]);\n\t\t\t\tchip->SweepFreq = i;\n\t\t\t\tif (i == 0xffff)\n\t\t\t\t\tfreq = 0;\n\t\t\t\telse\n\t\t\t\t\tfreq = chip->clock/(2048-(i&0x7ff));\n\t\t\t\tchip->ws_audio[2].delta = (long)((float)freq*(float)65536/(float)chip->smplrate);\n\t\t\t\tbreak;\n\tcase 0x86:\n\tcase 0x87:\ti=(((unsigned int)chip->ws_ioRam[0x87])<<8)+((unsigned int)chip->ws_ioRam[0x86]);\n\t\t\t\tif (i == 0xffff)\n\t\t\t\t\tfreq = 0;\n\t\t\t\telse\n\t\t\t\t\tfreq = chip->clock/(2048-(i&0x7ff));\n\t\t\t\tchip->ws_audio[3].delta = (long)((float)freq*(float)65536/(float)chip->smplrate);\n\t\t\t\tbreak;\n\tcase 0x88:\n\t\t\t\tchip->ws_audio[0].lvol = (value>>4)&0xf;\n\t\t\t\tchip->ws_audio[0].rvol = value&0xf;\n\t\t\t\tbreak;\n\tcase 0x89:\n\t\t\t\tchip->ws_audio[1].lvol = (value>>4)&0xf;\n\t\t\t\tchip->ws_audio[1].rvol = value&0xf;\n\t\t\t\tbreak;\n\tcase 0x8A:\n\t\t\t\tchip->ws_audio[2].lvol = (value>>4)&0xf;\n\t\t\t\tchip->ws_audio[2].rvol = value&0xf;\n\t\t\t\tbreak;\n\tcase 0x8B:\n\t\t\t\tchip->ws_audio[3].lvol = (value>>4)&0xf;\n\t\t\t\tchip->ws_audio[3].rvol = value&0xf;\n\t\t\t\tbreak;\n\tcase 0x8C:\n\t\t\t\tchip->SweepStep = (signed char)value;\n\t\t\t\tbreak;\n\tcase 0x8D:\n\t\t\t\t//Sweep̊Ԋu 1/375[s] = 2.666..[ms]\n\t\t\t\t//CPU ClockŌ 3072000/375 = 8192[cycles]\n\t\t\t\t//̐ݒlnƂƁA8192[cycles]*(n+1) ԊuSweep邱ƂɂȂ\n\t\t\t\t//\n\t\t\t\t// HBlank (256cycles) ̊ԊuŌƁA\n\t\t\t\t//@8192/256 = 32\n\t\t\t\t//Ȃ̂ŁA32[HBlank]*(n+1) ԊuƂȂ\n\t\t\t\tchip->SweepTime = (((unsigned int)value)+1)<<5;\n\t\t\t\tchip->SweepCount = chip->SweepTime;\n\t\t\t\tbreak;\n\tcase 0x8E:\n\t\t\t\tchip->NoiseType = value&7;\n\t\t\t\tif (value&8) chip->NoiseRng = 1;\t//mCYJE^[Zbg\n\t\t\t\tbreak;\n\tcase 0x8F:\n\t\t\t\t//WaveAdrs = (unsigned int)value<<6;\n\t\t\t\tchip->ws_audio[0].wave = (unsigned int)value<<6;\n\t\t\t\tchip->ws_audio[1].wave = chip->ws_audio[0].wave + 0x10;\n\t\t\t\tchip->ws_audio[2].wave = chip->ws_audio[1].wave + 0x10;\n\t\t\t\tchip->ws_audio[3].wave = chip->ws_audio[2].wave + 0x10;\n\t\t\t\tbreak;\n\tcase 0x90:\n\t\t\t\tbreak;\n\tcase 0x91:\n\t\t\t\t//ł̃{[́ASpeakerɑ΂Ă̒炵̂ŁA\n\t\t\t\t//wbhtHڑĂƔFΖ薳炵B\n\t\t\t\tchip->ws_ioRam[port] |= 0x80;\n\t\t\t\tbreak;\n\tcase 0x92:\n\tcase 0x93:\n\t\t\t\tbreak;\n\tcase 0x94:\n\t\t\t\tchip->PCMVolumeLeft  = (value&0xc)*2;\n\t\t\t\tchip->PCMVolumeRight = ((value<<2)&0xc)*2;\n\t\t\t\tbreak;\n\t/*case 0x52:\n\t\t\t\tif (value&0x80)\n\t\t\t\t\tws_timer_set(2, DMACycles[value&3]);\n\t\t\t\tbreak;*/\n\t}\n}\n\nBYTE ws_audio_port_read(UINT8 ChipID, BYTE port)\n{\n\twsa_state* chip = &WSAData[ChipID];\n\treturn (chip->ws_ioRam[port]);\n}\n\n// HBlankԊuŌĂ΂\n// Note: Must be called every 256 cycles (3072000 Hz clock), i.e. at 12000 Hz\nstatic void ws_audio_process(wsa_state* chip)\n{\n\tlong freq;\n\n\tif (chip->SweepStep && (SNDMOD&0x40))\n\t{\n\t\tif (chip->SweepCount < 0)\n\t\t{\n\t\t\tchip->SweepCount = chip->SweepTime;\n\t\t\tchip->SweepFreq += chip->SweepStep;\n\t\t\tchip->SweepFreq &= 0x7FF;\n\n\t\t\t//Update_SampleData();\n\n\t\t\tfreq = chip->clock/(2048-chip->SweepFreq);\n\t\t\tchip->ws_audio[2].delta = (long)((float)freq*(float)65536/(float)chip->smplrate);\n\t\t}\n\t\tchip->SweepCount--;\n\t}\n}\n\n/*void ws_audio_sounddma(void)\n{\n\tint i, j, b;\n\n\tif ((SDMACTL&0x88)==0x80)\n\t{\n\t\ti=(SDMACH<<8)|SDMACL;\n\t\tj=(SDMASB<<16)|(SDMASH<<8)|SDMASL;\n\t\tb=cpu_readmem20(j);\n\n\t\tUpdate_SampleData();\n\n\t\tws_ioRam[0x89]=b;\n\t\ti--;\n\t\tj++;\n\t\tif(i<32)\n\t\t{\n\t\t\ti=0;\n\t\t\tSDMACTL&=0x7F;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tws_timer_set(2, DMACycles[SDMACTL&3]);\n\t\t}\n\t\tSDMASB=(byte)((j>>16)&0xFF);\n\t\tSDMASH=(byte)((j>>8)&0xFF);\n\t\tSDMASL=(byte)(j&0xFF);\n\t\tSDMACH=(byte)((i>>8)&0xFF);\n\t\tSDMACL=(byte)(i&0xFF);\n\t}\n}*/\n\nvoid ws_write_ram(UINT8 ChipID, UINT16 offset, UINT8 value)\n{\n\twsa_state* chip = &WSAData[ChipID];\n\t\n\t// RAM - 16 KB (WS) / 64 KB (WSC) internal RAM\n\tif (offset >= 0x4000)\n\t\treturn;\t// We only allocated 16 KB.\n\t\n\tchip->ws_internalRam[offset] = value;\n\treturn;\n}\n\nvoid ws_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\twsa_state* chip = &WSAData[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 4; CurChn ++)\n\t\tchip->ws_audio[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/ws_audio.h",
    "content": "#ifndef __WS_AUDIO_H__\n#define __WS_AUDIO_H__\n\nint ws_audio_init(UINT8 ChipID, int clock);\nvoid ws_audio_reset(UINT8 ChipID);\nvoid ws_audio_done(UINT8 ChipID);\nvoid ws_audio_update(UINT8 ChipID, stream_sample_t** buffer, int length);\nvoid ws_audio_port_write(UINT8 ChipID, UINT8 port, UINT8 value);\nUINT8 ws_audio_port_read(UINT8 ChipID, UINT8 port);\n//void ws_audio_process(void);\n//void ws_audio_sounddma(void);\nvoid ws_write_ram(UINT8 ChipID, UINT16 offset, UINT8 value);\nvoid ws_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n//extern int WaveAdrs;\n\n#endif\n"
  },
  {
    "path": "VGMPlay/chips/ws_initialIo.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n// Initial I/O values\n////////////////////////////////////////////////////////////////////////////////\n//\n//\n//\n//\n//\n//\n//////////////////////////////////////////////////////////////////////////////\n\nuint8 initialIoValue[256]=\n{\n\t0x00,//0\n\t0x00,//1\n\t0x9d,//2\n\t0xbb,//3\n\t0x00,//4\n\t0x00,//5\n\t0x00,//6\n\t0x26,//7\n\t0xfe,//8\n\t0xde,//9\n\t0xf9,//a\n\t0xfb,//b\n\t0xdb,//c\n\t0xd7,//d\n\t0x7f,//e\n\t0xf5,//f\n\t0x00,//10\n\t0x00,//11\n\t0x00,//12\n\t0x00,//13\n\t0x01,//14\n\t0x00,//15\n\t0x9e,//16\n\t0x9b,//17\n\t0x00,//18\n\t0x00,//19\n\t0x00,//1a\n\t0x00,//1b\n\t0x99,//1c\n\t0xfd,//1d\n\t0xb7,//1e\n\t0xdf,//1f\n\t0x30,//20\n\t0x57,//21\n\t0x75,//22\n\t0x76,//23\n\t0x15,//24\n\t0x73,//25\n\t0x77,//26\n\t0x77,//27\n\t0x20,//28\n\t0x75,//29\n\t0x50,//2a\n\t0x36,//2b\n\t0x70,//2c\n\t0x67,//2d\n\t0x50,//2e\n\t0x77,//2f\n\t0x57,//30\n\t0x54,//31\n\t0x75,//32\n\t0x77,//33\n\t0x75,//34\n\t0x17,//35\n\t0x37,//36\n\t0x73,//37\n\t0x50,//38\n\t0x57,//39\n\t0x60,//3a\n\t0x77,//3b\n\t0x70,//3c\n\t0x77,//3d\n\t0x10,//3e\n\t0x73,//3f\n\t0x00,//40\n\t0x00,//41\n\t0x00,//42\n\t0x00,//43\n\t0x00,//44\n\t0x00,//45\n\t0x00,//46\n\t0x00,//47\n\t0x00,//48\n\t0x00,//49\n\t0x00,//4a\n\t0x00,//4b\n\t0x00,//4c\n\t0x00,//4d\n\t0x00,//4e\n\t0x00,//4f\n\t0x00,//50\n\t0x00,//51\n\t0x00,//52\n\t0x00,//53\n\t0x00,//54\n\t0x00,//55\n\t0x00,//56\n\t0x00,//57\n\t0x00,//58\n\t0x00,//59\n\t0x00,//5a\n\t0x00,//5b\n\t0x00,//5c\n\t0x00,//5d\n\t0x00,//5e\n\t0x00,//5f\n\t0x0a,//60\n\t0x00,//61\n\t0x00,//62\n\t0x00,//63\n\t0x00,//64\n\t0x00,//65\n\t0x00,//66\n\t0x00,//67\n\t0x00,//68\n\t0x00,//69\n\t0x00,//6a\n\t0x0f,//6b\n\t0x00,//6c\n\t0x00,//6d\n\t0x00,//6e\n\t0x00,//6f\n\t0x00,//70\n\t0x00,//71\n\t0x00,//72\n\t0x00,//73\n\t0x00,//74\n\t0x00,//75\n\t0x00,//76\n\t0x00,//77\n\t0x00,//78\n\t0x00,//79\n\t0x00,//7a\n\t0x00,//7b\n\t0x00,//7c\n\t0x00,//7d\n\t0x00,//7e\n\t0x00,//7f\n\t0xFF,//80\n\t0x07,//81\n\t0xFF,//82\n\t0x07,//83\n\t0xFF,//84\n\t0x07,//85\n\t0xFF,//86\n\t0x07,//87\n\t0x00,//88\n\t0x00,//89\n\t0x00,//8a\n\t0x00,//8b\n\t0x00,//8c\n\t0x1f,//8d 1d ?\n\t0x00,//8e\n\t0x00,//8f\n\t0x00,//90\n\t0x00,//91\n\t0x00,//92\n\t0x00,//93\n\t0x00,//94\n\t0x00,//95\n\t0x00,//96\n\t0x00,//97\n\t0x00,//98\n\t0x00,//99\n\t0x00,//9a\n\t0x00,//9b\n\t0x00,//9c\n\t0x00,//9d\n\t0x03,//9e\n\t0x00,//9f\n\t0x87-2,//a0\n\t0x00,//a1\n\t0x00,//a2\n\t0x00,//a3\n\t0x0,//a4 2b\n\t0x0,//a5 7f\n\t0x4f,//a6\n\t0xff,//a7 cf ?\n\t0x00,//a8\n\t0x00,//a9\n\t0x00,//aa\n\t0x00,//ab\n\t0x00,//ac\n\t0x00,//ad\n\t0x00,//ae\n\t0x00,//af\n\t0x00,//b0\n\t0xdb,//b1\n\t0x00,//b2\n\t0x00,//b3\n\t0x00,//b4\n\t0x40,//b5\n\t0x00,//b6\n\t0x00,//b7\n\t0x00,//b8\n\t0x00,//b9\n\t0x01,//ba\n\t0x00,//bb\n\t0x42,//bc\n\t0x00,//bd\n\t0x83,//be\n\t0x00,//bf\n\t0x2f,//c0\n\t0x3f,//c1\n\t0xff,//c2\n\t0xff,//c3\n\t0x00,//c4\n\t0x00,//c5\n\t0x00,//c6\n\t0x00,//c7\n\n\t0xd1,//c8?\n\t0xd1,//c9\n\t0xd1,//ca\n\t0xd1,//cb\n\t0xd1,//cc\n\t0xd1,//cd\n\t0xd1,//ce\n\t0xd1,//cf\n\t0xd1,//d0\n\t0xd1,//d1\n\t0xd1,//d2\n\t0xd1,//d3\n\t0xd1,//d4\n\t0xd1,//d5\n\t0xd1,//d6\n\t0xd1,//d7\n\t0xd1,//d8\n\t0xd1,//d9\n\t0xd1,//da\n\t0xd1,//db\n\t0xd1,//dc\n\t0xd1,//dd\n\t0xd1,//de\n\t0xd1,//df\n\t0xd1,//e0\n\t0xd1,//e1\n\t0xd1,//e2\n\t0xd1,//e3\n\t0xd1,//e4\n\t0xd1,//e5\n\t0xd1,//e6\n\t0xd1,//e7\n\t0xd1,//e8\n\t0xd1,//e9\n\t0xd1,//ea\n\t0xd1,//eb\n\t0xd1,//ec\n\t0xd1,//ed\n\t0xd1,//ee\n\t0xd1,//ef\n\t0xd1,//f0\n\t0xd1,//f1\n\t0xd1,//f2\n\t0xd1,//f3\n\t0xd1,//f4\n\t0xd1,//f5\n\t0xd1,//f6\n\t0xd1,//f7\n\t0xd1,//f8\n\t0xd1,//f9\n\t0xd1,//fa\n\t0xd1,//fb\n\t0xd1,//fc\n\t0xd1,//fd\n\t0xd1,//fe\n\t0xd1 //ff\n};\n"
  },
  {
    "path": "VGMPlay/chips/x1_010.c",
    "content": "/***************************************************************************\n\n                            -= Seta Hardware =-\n\n                    driver by   Luca Elia (l.elia@tin.it)\n\n                    rewrite by Manbow-J(manbowj@hamal.freemail.ne.jp)\n\n                    X1-010 Seta Custom Sound Chip (80 Pin PQFP)\n\n Custom programmed Mitsubishi M60016 Gate Array, 3608 gates, 148 Max I/O ports\n\n    The X1-010 is 16 Voices sound generator, each channel gets it's\n    waveform from RAM (128 bytes per waveform, 8 bit unsigned data)\n    or sampling PCM(8bit unsigned data).\n\nRegisters:\n    8 registers per channel (mapped to the lower bytes of 16 words on the 68K)\n\n    Reg:    Bits:       Meaning:\n\n    0       7654 3---\n            ---- -2--   PCM/Waveform repeat flag (0:Ones 1:Repeat) (*1)\n            ---- --1-   Sound out select (0:PCM 1:Waveform)\n            ---- ---0   Key on / off\n\n    1       7654 ----   PCM Volume 1 (L?)\n            ---- 3210   PCM Volume 2 (R?)\n                        Waveform No.\n\n    2                   PCM Frequency\n                        Waveform Pitch Lo\n\n    3                   Waveform Pitch Hi\n\n    4                   PCM Sample Start / 0x1000           [Start/End in bytes]\n                        Waveform Envelope Time\n\n    5                   PCM Sample End 0x100 - (Sample End / 0x1000)    [PCM ROM is Max 1MB?]\n                        Waveform Envelope No.\n    6                   Reserved\n    7                   Reserved\n\n    offset 0x0000 - 0x0fff  Wave form data\n    offset 0x1000 - 0x1fff  Envelope data\n\n    *1 : when 0 is specified, hardware interrupt is caused(allways return soon)\n\n***************************************************************************/\n\n//#include \"emu.h\"\n#include <stdlib.h>\n#include <stddef.h>\t// for NULL\n#include <string.h>\t// for memset\n#include \"mamedef.h\"\n#include \"x1_010.h\"\n\n\n#define VERBOSE_SOUND 0\n#define VERBOSE_REGISTER_WRITE 0\n#define VERBOSE_REGISTER_READ 0\n\n#define LOG_SOUND(x) do { if (VERBOSE_SOUND) logerror x; } while (0)\n#define LOG_REGISTER_WRITE(x) do { if (VERBOSE_REGISTER_WRITE) logerror x; } while (0)\n#define LOG_REGISTER_READ(x) do { if (VERBOSE_REGISTER_READ) logerror x; } while (0)\n\n#define SETA_NUM_CHANNELS 16\n\n//#define FREQ_BASE_BITS\t\t  8\t\t\t\t\t// Frequency fixed decimal shift bits\n#define FREQ_BASE_BITS\t\t  14\t\t\t\t\t// Frequency fixed decimal shift bits\n#define ENV_BASE_BITS\t\t 16\t\t\t\t\t// wave form envelope fixed decimal shift bits\n#define\tVOL_BASE\t(2*32*256/30)\t\t\t\t\t// Volume base\n\n/* this structure defines the parameters for a channel */\ntypedef struct {\n\tunsigned char\tstatus;\n\tunsigned char\tvolume;\t\t\t\t\t\t//        volume / wave form no.\n\tunsigned char\tfrequency;\t\t\t\t\t//     frequency / pitch lo\n\tunsigned char\tpitch_hi;\t\t\t\t\t//      reserved / pitch hi\n\tunsigned char\tstart;\t\t\t\t\t\t// start address / envelope time\n\tunsigned char\tend;\t\t\t\t\t\t//   end address / envelope no.\n\tunsigned char\treserve[2];\n} X1_010_CHANNEL;\n\ntypedef struct _x1_010_state x1_010_state;\nstruct _x1_010_state\n{\n\t/* Variables only used here */\n\tint\trate;\t\t\t\t\t\t\t\t// Output sampling rate (Hz)\n\t//sound_stream *\tstream;\t\t\t\t\t// Stream handle\n\t//int\taddress;\t\t\t\t\t\t\t// address eor data\n\t//const UINT8 *region;\t\t\t\t\t// region name\n\tUINT32 ROMSize;\n\tUINT8* rom;\n\tint\tsound_enable;\t\t\t\t\t\t// sound output enable/disable\n\tUINT8\treg[0x2000];\t\t\t\t// X1-010 Register & wave form area\n//\tUINT8\tHI_WORD_BUF[0x2000];\t\t\t// X1-010 16bit access ram check avoidance work\n\tUINT32\tsmp_offset[SETA_NUM_CHANNELS];\n\tUINT32\tenv_offset[SETA_NUM_CHANNELS];\n\n\tUINT32 base_clock;\n\t\n\tUINT8 Muted[SETA_NUM_CHANNELS];\n};\n\n/* mixer tables and internal buffers */\n//static short  *mixer_buffer = NULL;\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\n\n#define MAX_CHIPS\t0x02\nstatic x1_010_state X1010Data[MAX_CHIPS];\n\n/*INLINE x1_010_state *get_safe_token(device_t *device)\n{\n\tassert(device != NULL);\n\tassert(device->type() == X1_010);\n\treturn (x1_010_state *)downcast<legacy_device_base *>(device)->token();\n}*/\n\n\n/*--------------------------------------------------------------\n generate sound to the mix buffer\n--------------------------------------------------------------*/\n//static STREAM_UPDATE( seta_update )\nvoid seta_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//x1_010_state *info = (x1_010_state *)param;\n\tx1_010_state *info = &X1010Data[ChipID];\n\tX1_010_CHANNEL\t*reg;\n\tint\t\tch, i, volL, volR, freq, div;\n\tregister INT8\t*start, *end, data;\n\tregister UINT8\t*env;\n\tregister UINT32\tsmp_offs, smp_step, env_offs, env_step, delta;\n\n\t// mixer buffer zero clear\n\tmemset( outputs[0], 0, samples*sizeof(*outputs[0]) );\n\tmemset( outputs[1], 0, samples*sizeof(*outputs[1]) );\n\n//  if( info->sound_enable == 0 ) return;\n\n\tfor( ch = 0; ch < SETA_NUM_CHANNELS; ch++ ) {\n\t\treg = (X1_010_CHANNEL *)&(info->reg[ch*sizeof(X1_010_CHANNEL)]);\n\t\tif( (reg->status&1) != 0 && ! info->Muted[ch]) {\t\t// Key On\n\t\t\tstream_sample_t *bufL = outputs[0];\n\t\t\tstream_sample_t *bufR = outputs[1];\n\t\t\tdiv = (reg->status&0x80) ? 1 : 0;\n\t\t\tif( (reg->status&2) == 0 ) {\t\t\t\t\t\t// PCM sampling\n\t\t\t\tstart    = (INT8 *)(info->rom + reg->start*0x1000);\n\t\t\t\tend      = (INT8 *)(info->rom + (0x100-reg->end)*0x1000);\n\t\t\t\tvolL     = ((reg->volume>>4)&0xf)*VOL_BASE;\n\t\t\t\tvolR     = ((reg->volume>>0)&0xf)*VOL_BASE;\n\t\t\t\tsmp_offs = info->smp_offset[ch];\n\t\t\t\tfreq     = reg->frequency>>div;\n\t\t\t\t// Meta Fox does write the frequency register, but this is a hack to make it \"work\" with the current setup\n\t\t\t\t// This is broken for Arbalester (it writes 8), but that'll be fixed later.\n\t\t\t\tif( freq == 0 ) freq = 4;\n\t\t\t\tsmp_step = (UINT32)((float)info->base_clock/8192.0f\n\t\t\t\t\t\t\t*freq*(1<<FREQ_BASE_BITS)/(float)info->rate+0.5f);\n\t\t\t\tif( smp_offs == 0 ) {\n\t\t\t\t\tLOG_SOUND(( \"Play sample %p - %p, channel %X volume %d:%d freq %X step %X offset %X\\n\",\n\t\t\t\t\t\tstart, end, ch, volL, volR, freq, smp_step, smp_offs ));\n\t\t\t\t}\n\t\t\t\tfor( i = 0; i < samples; i++ ) {\n\t\t\t\t\tdelta = smp_offs>>FREQ_BASE_BITS;\n\t\t\t\t\t// sample ended?\n\t\t\t\t\tif( start+delta >= end ) {\n\t\t\t\t\t\treg->status &= ~0x01;\t\t\t\t\t// Key off\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdata = *(start+delta);\n\t\t\t\t\t*bufL++ += (data*volL/256);\n\t\t\t\t\t*bufR++ += (data*volR/256);\n\t\t\t\t\tsmp_offs += smp_step;\n\t\t\t\t}\n\t\t\t\tinfo->smp_offset[ch] = smp_offs;\n\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t// Wave form\n\t\t\t\tstart    = (INT8 *)&(info->reg[reg->volume*128+0x1000]);\n\t\t\t\tsmp_offs = info->smp_offset[ch];\n\t\t\t\tfreq     = ((reg->pitch_hi<<8)+reg->frequency)>>div;\n\t\t\t\tsmp_step = (UINT32)((float)info->base_clock/128.0/1024.0/4.0*freq*(1<<FREQ_BASE_BITS)/(float)info->rate+0.5f);\n\n\t\t\t\tenv      = (UINT8 *)&(info->reg[reg->end*128]);\n\t\t\t\tenv_offs = info->env_offset[ch];\n\t\t\t\tenv_step = (UINT32)((float)info->base_clock/128.0/1024.0/4.0*reg->start*(1<<ENV_BASE_BITS)/(float)info->rate+0.5f);\n\t\t\t\t/* Print some more debug info */\n\t\t\t\tif( smp_offs == 0 ) {\n\t\t\t\t\tLOG_SOUND(( \"Play waveform %X, channel %X volume %X freq %4X step %X offset %X\\n\",\n\t\t\t\t\t\treg->volume, ch, reg->end, freq, smp_step, smp_offs ));\n\t\t\t\t}\n\t\t\t\tfor( i = 0; i < samples; i++ ) {\n\t\t\t\t\tint vol;\n\t\t\t\t\tdelta = env_offs>>ENV_BASE_BITS;\n\t\t\t\t\t// Envelope one shot mode\n\t\t\t\t\tif( (reg->status&4) != 0 && delta >= 0x80 ) {\n\t\t\t\t\t\treg->status &= ~0x01;\t\t\t\t\t// Key off\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tvol = *(env+(delta&0x7f));\n\t\t\t\t\tvolL = ((vol>>4)&0xf)*VOL_BASE;\n\t\t\t\t\tvolR = ((vol>>0)&0xf)*VOL_BASE;\n\t\t\t\t\tdata  = *(start+((smp_offs>>FREQ_BASE_BITS)&0x7f));\n\t\t\t\t\t*bufL++ += (data*volL/256);\n\t\t\t\t\t*bufR++ += (data*volR/256);\n\t\t\t\t\tsmp_offs += smp_step;\n\t\t\t\t\tenv_offs += env_step;\n\t\t\t\t}\n\t\t\t\tinfo->smp_offset[ch] = smp_offs;\n\t\t\t\tinfo->env_offset[ch] = env_offs;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n//static DEVICE_START( x1_010 )\nint device_start_x1_010(UINT8 ChipID, int clock)\n{\n\tint i;\n\t//const x1_010_interface *intf = (const x1_010_interface *)device->static_config();\n\t//x1_010_state *info = get_safe_token(device);\n\tx1_010_state *info;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tinfo = &X1010Data[ChipID];\n\t\n\t//info->region\t\t= *device->region();\n\t//info->base_clock\t= device->clock();\n\t//info->rate\t\t\t= device->clock() / 1024;\n\t//info->address\t\t= intf->adr;\n\tinfo->ROMSize\t\t= 0x00;\n\tinfo->rom\t\t\t= NULL;\n\tinfo->base_clock\t= clock;\n\tinfo->rate\t\t\t= clock / 512;\n\tif (((CHIP_SAMPLING_MODE & 0x01) && info->rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\tinfo->rate = CHIP_SAMPLE_RATE;\n\n\tfor( i = 0; i < SETA_NUM_CHANNELS; i++ ) {\n\t\tinfo->smp_offset[i] = 0;\n\t\tinfo->env_offset[i] = 0;\n\t}\n\t/* Print some more debug info */\n\t//LOG_SOUND((\"masterclock = %d rate = %d\\n\", device->clock(), info->rate ));\n\n\t/* get stream channels */\n\t//info->stream = device->machine().sound().stream_alloc(*device,0,2,info->rate,info,seta_update);\n\treturn info->rate;\n}\n\nvoid device_stop_x1_010(UINT8 ChipID)\n{\n\tx1_010_state *info = &X1010Data[ChipID];\n\t\n\tfree(info->rom);\tinfo->rom = NULL;\n\t\n\treturn;\n}\n\nvoid device_reset_x1_010(UINT8 ChipID)\n{\n\tx1_010_state *info = &X1010Data[ChipID];\n\t\n\tmemset(info->reg, 0, 0x2000);\n\t//memset(info->HI_WORD_BUF, 0, 0x2000);\n\tmemset(info->smp_offset, 0, SETA_NUM_CHANNELS * sizeof(UINT32));\n\tmemset(info->env_offset, 0, SETA_NUM_CHANNELS * sizeof(UINT32));\n\t\n\treturn;\n}\n\n\n/*void seta_sound_enable_w(device_t *device, int data)\n{\n\tx1_010_state *info = get_safe_token(device);\n\tinfo->sound_enable = data;\n}*/\n\n\n\n/* Use these for 8 bit CPUs */\n\n\n//READ8_DEVICE_HANDLER( seta_sound_r )\nUINT8 seta_sound_r(UINT8 ChipID, offs_t offset)\n{\n\t//x1_010_state *info = get_safe_token(device);\n\tx1_010_state *info = &X1010Data[ChipID];\n\t//offset ^= info->address;\n\treturn info->reg[offset];\n}\n\n\n\n\n//WRITE8_DEVICE_HANDLER( seta_sound_w )\nvoid seta_sound_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//x1_010_state *info = get_safe_token(device);\n\tx1_010_state *info = &X1010Data[ChipID];\n\tint channel, reg;\n\t//offset ^= info->address;\n\n\tchannel\t= offset/sizeof(X1_010_CHANNEL);\n\treg\t\t= offset%sizeof(X1_010_CHANNEL);\n\n\tif( channel < SETA_NUM_CHANNELS && reg == 0\n\t && (info->reg[offset]&1) == 0 && (data&1) != 0 ) {\n\t\tinfo->smp_offset[channel] = 0;\n\t\tinfo->env_offset[channel] = 0;\n\t}\n\t//LOG_REGISTER_WRITE((\"%s: offset %6X : data %2X\\n\", device->machine().describe_context(), offset, data ));\n\tinfo->reg[offset] = data;\n}\n\nvoid x1_010_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t\tconst UINT8* ROMData)\n{\n\tx1_010_state *info = &X1010Data[ChipID];\n\t\n\tif (info->ROMSize != ROMSize)\n\t{\n\t\tinfo->rom = (UINT8*)realloc(info->rom, ROMSize);\n\t\tinfo->ROMSize = ROMSize;\n\t\tmemset(info->rom, 0xFF, ROMSize);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(info->rom + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\n\nvoid x1_010_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tx1_010_state *info = &X1010Data[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < SETA_NUM_CHANNELS; CurChn ++)\n\t\tinfo->Muted[CurChn] = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n\n\n\n/* Use these for 16 bit CPUs */\n\n/*READ16_DEVICE_HANDLER( seta_sound_word_r )\n{\n\t//x1_010_state *info = get_safe_token(device);\n\tx1_010_state *info = &X1010Data[ChipID];\n\tUINT16\tret;\n\n\tret = info->HI_WORD_BUF[offset]<<8;\n\tret += (seta_sound_r( device, offset )&0xff);\n\tLOG_REGISTER_READ(( \"%s: Read X1-010 Offset:%04X Data:%04X\\n\", device->machine().describe_context(), offset, ret ));\n\treturn ret;\n}\n\nWRITE16_DEVICE_HANDLER( seta_sound_word_w )\n{\n\t//x1_010_state *info = get_safe_token(device);\n\tx1_010_state *info = &X1010Data[ChipID];\n\tinfo->HI_WORD_BUF[offset] = (data>>8)&0xff;\n\tseta_sound_w( device, offset, data&0xff );\n\tLOG_REGISTER_WRITE(( \"%s: Write X1-010 Offset:%04X Data:%04X\\n\", device->machine().describe_context(), offset, data ));\n}*/\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( x1_010 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(x1_010_state); \t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( x1_010 );\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing //\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\t// Nothing //\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"X1-010\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Seta custom\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}\n\n\nDEFINE_LEGACY_SOUND_DEVICE(X1_010, x1_010);*/\n"
  },
  {
    "path": "VGMPlay/chips/x1_010.h",
    "content": "#pragma once\n\n#ifndef __X1_010_H__\n#define __X1_010_H__\n\n//#include \"devlegcy.h\"\n\n\n/*typedef struct _x1_010_interface x1_010_interface;\nstruct _x1_010_interface\n{\n\tint adr;\t// address\n};*/\n\n\nvoid seta_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_x1_010(UINT8 ChipID, int clock);\nvoid device_stop_x1_010(UINT8 ChipID);\nvoid device_reset_x1_010(UINT8 ChipID);\n\n//READ8_DEVICE_HANDLER ( seta_sound_r );\n//WRITE8_DEVICE_HANDLER( seta_sound_w );\nUINT8 seta_sound_r(UINT8 ChipID, offs_t offset);\nvoid seta_sound_w(UINT8 ChipID, offs_t offset, UINT8 data);\n\n//READ16_DEVICE_HANDLER ( seta_sound_word_r );\n//WRITE16_DEVICE_HANDLER( seta_sound_word_w );\n\n//void seta_sound_enable_w(device_t *device, int data);\n\nvoid x1_010_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t\tconst UINT8* ROMData);\n\nvoid x1_010_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n\n//DECLARE_LEGACY_SOUND_DEVICE(X1_010, x1_010);\n\n#endif /* __X1_010_H__ */\n"
  },
  {
    "path": "VGMPlay/chips/ym2151.c",
    "content": "/*****************************************************************************\n*\n*   Yamaha YM2151 driver (version 2.150 final beta)\n*\n******************************************************************************/\n\n#include <stdio.h>\n#include <math.h>\n\n#include \"mamedef.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#include \"ym2151.h\"\n\n\n/* undef this to not use MAME timer system */\n//#define USE_MAME_TIMERS\n\n/*#define FM_EMU*/\n#ifdef FM_EMU\n\t#ifdef USE_MAME_TIMERS\n\t\t#undef USE_MAME_TIMERS\n\t#endif\n#endif\n\n//static char LOG_CYM_FILE = 0x00;\n//static FILE * cymfile = NULL;\n\n\n/* struct describing a single operator */\ntypedef struct{\n\tUINT32\t\tphase;\t\t\t\t\t/* accumulated operator phase */\n\tUINT32\t\tfreq;\t\t\t\t\t/* operator frequency count */\n\tINT32\t\tdt1;\t\t\t\t\t/* current DT1 (detune 1 phase inc/decrement) value */\n\tUINT32\t\tmul;\t\t\t\t\t/* frequency count multiply */\n\tUINT32\t\tdt1_i;\t\t\t\t\t/* DT1 index * 32 */\n\tUINT32\t\tdt2;\t\t\t\t\t/* current DT2 (detune 2) value */\n\n\tsigned int *connect;\t\t\t\t/* operator output 'direction' */\n\n\t/* only M1 (operator 0) is filled with this data: */\n\tsigned int *mem_connect;\t\t\t/* where to put the delayed sample (MEM) */\n\tINT32\t\tmem_value;\t\t\t\t/* delayed sample (MEM) value */\n\n\t/* channel specific data; note: each operator number 0 contains channel specific data */\n\tUINT32\t\tfb_shift;\t\t\t\t/* feedback shift value for operators 0 in each channel */\n\tINT32\t\tfb_out_curr;\t\t\t/* operator feedback value (used only by operators 0) */\n\tINT32\t\tfb_out_prev;\t\t\t/* previous feedback value (used only by operators 0) */\n\tUINT32\t\tkc;\t\t\t\t\t\t/* channel KC (copied to all operators) */\n\tUINT32\t\tkc_i;\t\t\t\t\t/* just for speedup */\n\tUINT32\t\tpms;\t\t\t\t\t/* channel PMS */\n\tUINT32\t\tams;\t\t\t\t\t/* channel AMS */\n\t/* end of channel specific data */\n\n\tUINT32\t\tAMmask;\t\t\t\t\t/* LFO Amplitude Modulation enable mask */\n\tUINT32\t\tstate;\t\t\t\t\t/* Envelope state: 4-attack(AR) 3-decay(D1R) 2-sustain(D2R) 1-release(RR) 0-off */\n\tUINT8\t\teg_sh_ar;\t\t\t\t/*  (attack state) */\n\tUINT8\t\teg_sel_ar;\t\t\t\t/*  (attack state) */\n\tUINT32\t\ttl;\t\t\t\t\t\t/* Total attenuation Level */\n\tINT32\t\tvolume;\t\t\t\t\t/* current envelope attenuation level */\n\tUINT8\t\teg_sh_d1r;\t\t\t\t/*  (decay state) */\n\tUINT8\t\teg_sel_d1r;\t\t\t\t/*  (decay state) */\n\tUINT32\t\td1l;\t\t\t\t\t/* envelope switches to sustain state after reaching this level */\n\tUINT8\t\teg_sh_d2r;\t\t\t\t/*  (sustain state) */\n\tUINT8\t\teg_sel_d2r;\t\t\t\t/*  (sustain state) */\n\tUINT8\t\teg_sh_rr;\t\t\t\t/*  (release state) */\n\tUINT8\t\teg_sel_rr;\t\t\t\t/*  (release state) */\n\n\tUINT32\t\tkey;\t\t\t\t\t/* 0=last key was KEY OFF, 1=last key was KEY ON */\n\n\tUINT32\t\tks;\t\t\t\t\t\t/* key scale    */\n\tUINT32\t\tar;\t\t\t\t\t\t/* attack rate  */\n\tUINT32\t\td1r;\t\t\t\t\t/* decay rate   */\n\tUINT32\t\td2r;\t\t\t\t\t/* sustain rate */\n\tUINT32\t\trr;\t\t\t\t\t\t/* release rate */\n\n\tUINT32\t\treserved0;\t\t\t\t/**/\n\tUINT32\t\treserved1;\t\t\t\t/**/\n\n} YM2151Operator;\n\n\ntypedef struct\n{\n\tYM2151Operator\toper[32];\t\t\t/* the 32 operators */\n\n\tUINT32\t\tpan[16];\t\t\t\t/* channels output masks (0xffffffff = enable) */\n\tUINT8\t\tMuted[8];\t\t\t\t/* used for muting */\n\n\tUINT32\t\teg_cnt;\t\t\t\t\t/* global envelope generator counter */\n\tUINT32\t\teg_timer;\t\t\t\t/* global envelope generator counter works at frequency = chipclock/64/3 */\n\tUINT32\t\teg_timer_add;\t\t\t/* step of eg_timer */\n\tUINT32\t\teg_timer_overflow;\t\t/* envelope generator timer overlfows every 3 samples (on real chip) */\n\n\tUINT32\t\tlfo_phase;\t\t\t\t/* accumulated LFO phase (0 to 255) */\n\tUINT32\t\tlfo_timer;\t\t\t\t/* LFO timer                        */\n\tUINT32\t\tlfo_timer_add;\t\t\t/* step of lfo_timer                */\n\tUINT32\t\tlfo_overflow;\t\t\t/* LFO generates new output when lfo_timer reaches this value */\n\tUINT32\t\tlfo_counter;\t\t\t/* LFO phase increment counter      */\n\tUINT32\t\tlfo_counter_add;\t\t/* step of lfo_counter              */\n\tUINT8\t\tlfo_wsel;\t\t\t\t/* LFO waveform (0-saw, 1-square, 2-triangle, 3-random noise) */\n\tUINT8\t\tamd;\t\t\t\t\t/* LFO Amplitude Modulation Depth   */\n\tINT8\t\tpmd;\t\t\t\t\t/* LFO Phase Modulation Depth       */\n\tUINT32\t\tlfa;\t\t\t\t\t/* LFO current AM output            */\n\tINT32\t\tlfp;\t\t\t\t\t/* LFO current PM output            */\n\n\tUINT8\t\ttest;\t\t\t\t\t/* TEST register */\n\tUINT8\t\tct;\t\t\t\t\t\t/* output control pins (bit1-CT2, bit0-CT1) */\n\n\tUINT32\t\tnoise;\t\t\t\t\t/* noise enable/period register (bit 7 - noise enable, bits 4-0 - noise period */\n\tUINT32\t\tnoise_rng;\t\t\t\t/* 17 bit noise shift register */\n\tUINT32\t\tnoise_p;\t\t\t\t/* current noise 'phase'*/\n\tUINT32\t\tnoise_f;\t\t\t\t/* current noise period */\n\n\tUINT32\t\tcsm_req;\t\t\t\t/* CSM  KEY ON / KEY OFF sequence request */\n\n\tUINT32\t\tirq_enable;\t\t\t\t/* IRQ enable for timer B (bit 3) and timer A (bit 2); bit 7 - CSM mode (keyon to all slots, everytime timer A overflows) */\n\tUINT32\t\tstatus;\t\t\t\t\t/* chip status (BUSY, IRQ Flags) */\n\tUINT8\t\tconnect[8];\t\t\t\t/* channels connections */\n\n#ifdef USE_MAME_TIMERS\n/* ASG 980324 -- added for tracking timers */\n\temu_timer\t*timer_A;\n\temu_timer\t*timer_B;\n\tattotime\ttimer_A_time[1024];\t\t/* timer A times for MAME */\n\tattotime\ttimer_B_time[256];\t\t/* timer B times for MAME */\n\tint\t\t\tirqlinestate;\n#else\n\tUINT8\t\ttim_A;\t\t\t\t\t/* timer A enable (0-disabled) */\n\tUINT8\t\ttim_B;\t\t\t\t\t/* timer B enable (0-disabled) */\n\tINT32\t\ttim_A_val;\t\t\t\t/* current value of timer A */\n\tINT32\t\ttim_B_val;\t\t\t\t/* current value of timer B */\n\tUINT32\t\ttim_A_tab[1024];\t\t/* timer A deltas */\n\tUINT32\t\ttim_B_tab[256];\t\t\t/* timer B deltas */\n#endif\n\tUINT32\t\ttimer_A_index;\t\t\t/* timer A index */\n\tUINT32\t\ttimer_B_index;\t\t\t/* timer B index */\n\tUINT32\t\ttimer_A_index_old;\t\t/* timer A previous index */\n\tUINT32\t\ttimer_B_index_old;\t\t/* timer B previous index */\n\n\t/*  Frequency-deltas to get the closest frequency possible.\n    *   There are 11 octaves because of DT2 (max 950 cents over base frequency)\n    *   and LFO phase modulation (max 800 cents below AND over base frequency)\n    *   Summary:   octave  explanation\n    *              0       note code - LFO PM\n    *              1       note code\n    *              2       note code\n    *              3       note code\n    *              4       note code\n    *              5       note code\n    *              6       note code\n    *              7       note code\n    *              8       note code\n    *              9       note code + DT2 + LFO PM\n    *              10      note code + DT2 + LFO PM\n    */\n\tUINT32\t\tfreq[11*768];\t\t\t/* 11 octaves, 768 'cents' per octave */\n\n\t/*  Frequency deltas for DT1. These deltas alter operator frequency\n    *   after it has been taken from frequency-deltas table.\n    */\n\tINT32\t\tdt1_freq[8*32];\t\t\t/* 8 DT1 levels, 32 KC values */\n\n\tUINT32\t\tnoise_tab[32];\t\t\t/* 17bit Noise Generator periods */\n\n\t//void (*irqhandler)(const device_config *device, int irq);\t\t/* IRQ function handler */\n\t//write8_device_func porthandler;\t\t/* port write function handler */\n\n\t//const device_config *device;\n\tunsigned int clock;\t\t\t\t\t/* chip clock in Hz (passed from 2151intf.c) */\n\tunsigned int sampfreq;\t\t\t\t/* sampling frequency in Hz (passed from 2151intf.c) */\n} YM2151;\n\n\n#define FREQ_SH\t\t\t16  /* 16.16 fixed point (frequency calculations) */\n#define EG_SH\t\t\t16  /* 16.16 fixed point (envelope generator timing) */\n#define LFO_SH\t\t\t10  /* 22.10 fixed point (LFO calculations)       */\n#define TIMER_SH\t\t16  /* 16.16 fixed point (timers calculations)    */\n\n#define FREQ_MASK\t\t((1<<FREQ_SH)-1)\n\n#define ENV_BITS\t\t10\n#define ENV_LEN\t\t\t(1<<ENV_BITS)\n#define ENV_STEP\t\t(128.0/ENV_LEN)\n\n#define MAX_ATT_INDEX\t(ENV_LEN-1) /* 1023 */\n#define MIN_ATT_INDEX\t(0)\t\t\t/* 0 */\n\n#define EG_ATT\t\t\t4\n#define EG_DEC\t\t\t3\n#define EG_SUS\t\t\t2\n#define EG_REL\t\t\t1\n#define EG_OFF\t\t\t0\n\n#define SIN_BITS\t\t10\n#define SIN_LEN\t\t\t(1<<SIN_BITS)\n#define SIN_MASK\t\t(SIN_LEN-1)\n\n#define TL_RES_LEN\t\t(256) /* 8 bits addressing (real chip) */\n\n\n#if (SAMPLE_BITS==16)\n\t#define FINAL_SH\t(0)\n\t#define MAXOUT\t\t(+32767)\n\t#define MINOUT\t\t(-32768)\n#else\n\t#define FINAL_SH\t(8)\n\t#define MAXOUT\t\t(+127)\n\t#define MINOUT\t\t(-128)\n#endif\n\n\n/*  TL_TAB_LEN is calculated as:\n*   13 - sinus amplitude bits     (Y axis)\n*   2  - sinus sign bit           (Y axis)\n*   TL_RES_LEN - sinus resolution (X axis)\n*/\n#define TL_TAB_LEN (13*2*TL_RES_LEN)\nstatic signed int tl_tab[TL_TAB_LEN];\n\n#define ENV_QUIET\t\t(TL_TAB_LEN>>3)\n\n/* sin waveform table in 'decibel' scale */\nstatic unsigned int sin_tab[SIN_LEN];\n\n\n/* translate from D1L to volume index (16 D1L levels) */\nstatic UINT32 d1l_tab[16];\n\n\n#define RATE_STEPS (8)\nstatic const UINT8 eg_inc[19*RATE_STEPS]={\n\n/*cycle:0 1  2 3  4 5  6 7*/\n\n/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */\n/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */\n/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */\n/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */\n\n/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */\n/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */\n/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */\n/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */\n\n/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */\n/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */\n/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */\n/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */\n\n/*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */\n/*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */\n/*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */\n/*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */\n\n/*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */\n/*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */\n/*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */\n};\n\n\n#define O(a) (a*RATE_STEPS)\n\n/*note that there is no O(17) in this table - it's directly in the code */\nstatic const UINT8 eg_rate_select[32+64+32]={\t/* Envelope Generator rates (32 + 64 rates + 32 RKS) */\n/* 32 dummy (infinite time) rates */\nO(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\nO(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\nO(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\nO(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),\n\n/* rates 00-11 */\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\n\n/* rate 12 */\nO( 4),O( 5),O( 6),O( 7),\n\n/* rate 13 */\nO( 8),O( 9),O(10),O(11),\n\n/* rate 14 */\nO(12),O(13),O(14),O(15),\n\n/* rate 15 */\nO(16),O(16),O(16),O(16),\n\n/* 32 dummy rates (same as 15 3) */\nO(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\nO(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\nO(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),\nO(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16)\n\n};\n#undef O\n\n/*rate  0,    1,    2,   3,   4,   5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15*/\n/*shift 11,   10,   9,   8,   7,   6,  5,  4,  3,  2, 1,  0,  0,  0,  0,  0 */\n/*mask  2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3, 1,  0,  0,  0,  0,  0 */\n\n#define O(a) (a*1)\nstatic const UINT8 eg_rate_shift[32+64+32]={\t/* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */\n/* 32 infinite time rates */\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\n\n\n/* rates 00-11 */\nO(11),O(11),O(11),O(11),\nO(10),O(10),O(10),O(10),\nO( 9),O( 9),O( 9),O( 9),\nO( 8),O( 8),O( 8),O( 8),\nO( 7),O( 7),O( 7),O( 7),\nO( 6),O( 6),O( 6),O( 6),\nO( 5),O( 5),O( 5),O( 5),\nO( 4),O( 4),O( 4),O( 4),\nO( 3),O( 3),O( 3),O( 3),\nO( 2),O( 2),O( 2),O( 2),\nO( 1),O( 1),O( 1),O( 1),\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 12 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 13 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 14 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 15 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* 32 dummy rates (same as 15 3) */\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0)\n\n};\n#undef O\n\n/*  DT2 defines offset in cents from base note\n*\n*   This table defines offset in frequency-deltas table.\n*   User's Manual page 22\n*\n*   Values below were calculated using formula: value =  orig.val / 1.5625\n*\n*   DT2=0 DT2=1 DT2=2 DT2=3\n*   0     600   781   950\n*/\nstatic const UINT32 dt2_tab[4] = { 0, 384, 500, 608 };\n\n/*  DT1 defines offset in Hertz from base note\n*   This table is converted while initialization...\n*   Detune table shown in YM2151 User's Manual is wrong (verified on the real chip)\n*/\n\nstatic const UINT8 dt1_tab[4*32] = { /* 4*32 DT1 values */\n/* DT1=0 */\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\n/* DT1=1 */\n  0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,\n  2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,\n\n/* DT1=2 */\n  1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,\n  5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,\n\n/* DT1=3 */\n  2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,\n  8, 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22\n};\n\nstatic const UINT16 phaseinc_rom[768]={\n1299,1300,1301,1302,1303,1304,1305,1306,1308,1309,1310,1311,1313,1314,1315,1316,\n1318,1319,1320,1321,1322,1323,1324,1325,1327,1328,1329,1330,1332,1333,1334,1335,\n1337,1338,1339,1340,1341,1342,1343,1344,1346,1347,1348,1349,1351,1352,1353,1354,\n1356,1357,1358,1359,1361,1362,1363,1364,1366,1367,1368,1369,1371,1372,1373,1374,\n1376,1377,1378,1379,1381,1382,1383,1384,1386,1387,1388,1389,1391,1392,1393,1394,\n1396,1397,1398,1399,1401,1402,1403,1404,1406,1407,1408,1409,1411,1412,1413,1414,\n1416,1417,1418,1419,1421,1422,1423,1424,1426,1427,1429,1430,1431,1432,1434,1435,\n1437,1438,1439,1440,1442,1443,1444,1445,1447,1448,1449,1450,1452,1453,1454,1455,\n1458,1459,1460,1461,1463,1464,1465,1466,1468,1469,1471,1472,1473,1474,1476,1477,\n1479,1480,1481,1482,1484,1485,1486,1487,1489,1490,1492,1493,1494,1495,1497,1498,\n1501,1502,1503,1504,1506,1507,1509,1510,1512,1513,1514,1515,1517,1518,1520,1521,\n1523,1524,1525,1526,1528,1529,1531,1532,1534,1535,1536,1537,1539,1540,1542,1543,\n1545,1546,1547,1548,1550,1551,1553,1554,1556,1557,1558,1559,1561,1562,1564,1565,\n1567,1568,1569,1570,1572,1573,1575,1576,1578,1579,1580,1581,1583,1584,1586,1587,\n1590,1591,1592,1593,1595,1596,1598,1599,1601,1602,1604,1605,1607,1608,1609,1610,\n1613,1614,1615,1616,1618,1619,1621,1622,1624,1625,1627,1628,1630,1631,1632,1633,\n1637,1638,1639,1640,1642,1643,1645,1646,1648,1649,1651,1652,1654,1655,1656,1657,\n1660,1661,1663,1664,1666,1667,1669,1670,1672,1673,1675,1676,1678,1679,1681,1682,\n1685,1686,1688,1689,1691,1692,1694,1695,1697,1698,1700,1701,1703,1704,1706,1707,\n1709,1710,1712,1713,1715,1716,1718,1719,1721,1722,1724,1725,1727,1728,1730,1731,\n1734,1735,1737,1738,1740,1741,1743,1744,1746,1748,1749,1751,1752,1754,1755,1757,\n1759,1760,1762,1763,1765,1766,1768,1769,1771,1773,1774,1776,1777,1779,1780,1782,\n1785,1786,1788,1789,1791,1793,1794,1796,1798,1799,1801,1802,1804,1806,1807,1809,\n1811,1812,1814,1815,1817,1819,1820,1822,1824,1825,1827,1828,1830,1832,1833,1835,\n1837,1838,1840,1841,1843,1845,1846,1848,1850,1851,1853,1854,1856,1858,1859,1861,\n1864,1865,1867,1868,1870,1872,1873,1875,1877,1879,1880,1882,1884,1885,1887,1888,\n1891,1892,1894,1895,1897,1899,1900,1902,1904,1906,1907,1909,1911,1912,1914,1915,\n1918,1919,1921,1923,1925,1926,1928,1930,1932,1933,1935,1937,1939,1940,1942,1944,\n1946,1947,1949,1951,1953,1954,1956,1958,1960,1961,1963,1965,1967,1968,1970,1972,\n1975,1976,1978,1980,1982,1983,1985,1987,1989,1990,1992,1994,1996,1997,1999,2001,\n2003,2004,2006,2008,2010,2011,2013,2015,2017,2019,2021,2022,2024,2026,2028,2029,\n2032,2033,2035,2037,2039,2041,2043,2044,2047,2048,2050,2052,2054,2056,2058,2059,\n2062,2063,2065,2067,2069,2071,2073,2074,2077,2078,2080,2082,2084,2086,2088,2089,\n2092,2093,2095,2097,2099,2101,2103,2104,2107,2108,2110,2112,2114,2116,2118,2119,\n2122,2123,2125,2127,2129,2131,2133,2134,2137,2139,2141,2142,2145,2146,2148,2150,\n2153,2154,2156,2158,2160,2162,2164,2165,2168,2170,2172,2173,2176,2177,2179,2181,\n2185,2186,2188,2190,2192,2194,2196,2197,2200,2202,2204,2205,2208,2209,2211,2213,\n2216,2218,2220,2222,2223,2226,2227,2230,2232,2234,2236,2238,2239,2242,2243,2246,\n2249,2251,2253,2255,2256,2259,2260,2263,2265,2267,2269,2271,2272,2275,2276,2279,\n2281,2283,2285,2287,2288,2291,2292,2295,2297,2299,2301,2303,2304,2307,2308,2311,\n2315,2317,2319,2321,2322,2325,2326,2329,2331,2333,2335,2337,2338,2341,2342,2345,\n2348,2350,2352,2354,2355,2358,2359,2362,2364,2366,2368,2370,2371,2374,2375,2378,\n2382,2384,2386,2388,2389,2392,2393,2396,2398,2400,2402,2404,2407,2410,2411,2414,\n2417,2419,2421,2423,2424,2427,2428,2431,2433,2435,2437,2439,2442,2445,2446,2449,\n2452,2454,2456,2458,2459,2462,2463,2466,2468,2470,2472,2474,2477,2480,2481,2484,\n2488,2490,2492,2494,2495,2498,2499,2502,2504,2506,2508,2510,2513,2516,2517,2520,\n2524,2526,2528,2530,2531,2534,2535,2538,2540,2542,2544,2546,2549,2552,2553,2556,\n2561,2563,2565,2567,2568,2571,2572,2575,2577,2579,2581,2583,2586,2589,2590,2593\n};\n\n\n/*\n    Noise LFO waveform.\n\n    Here are just 256 samples out of much longer data.\n\n    It does NOT repeat every 256 samples on real chip and I wasnt able to find\n    the point where it repeats (even in strings as long as 131072 samples).\n\n    I only put it here because its better than nothing and perhaps\n    someone might be able to figure out the real algorithm.\n\n\n    Note that (due to the way the LFO output is calculated) it is quite\n    possible that two values: 0x80 and 0x00 might be wrong in this table.\n    To be exact:\n        some 0x80 could be 0x81 as well as some 0x00 could be 0x01.\n*/\n\nstatic const UINT8 lfo_noise_waveform[256] = {\n0xFF,0xEE,0xD3,0x80,0x58,0xDA,0x7F,0x94,0x9E,0xE3,0xFA,0x00,0x4D,0xFA,0xFF,0x6A,\n0x7A,0xDE,0x49,0xF6,0x00,0x33,0xBB,0x63,0x91,0x60,0x51,0xFF,0x00,0xD8,0x7F,0xDE,\n0xDC,0x73,0x21,0x85,0xB2,0x9C,0x5D,0x24,0xCD,0x91,0x9E,0x76,0x7F,0x20,0xFB,0xF3,\n0x00,0xA6,0x3E,0x42,0x27,0x69,0xAE,0x33,0x45,0x44,0x11,0x41,0x72,0x73,0xDF,0xA2,\n\n0x32,0xBD,0x7E,0xA8,0x13,0xEB,0xD3,0x15,0xDD,0xFB,0xC9,0x9D,0x61,0x2F,0xBE,0x9D,\n0x23,0x65,0x51,0x6A,0x84,0xF9,0xC9,0xD7,0x23,0xBF,0x65,0x19,0xDC,0x03,0xF3,0x24,\n0x33,0xB6,0x1E,0x57,0x5C,0xAC,0x25,0x89,0x4D,0xC5,0x9C,0x99,0x15,0x07,0xCF,0xBA,\n0xC5,0x9B,0x15,0x4D,0x8D,0x2A,0x1E,0x1F,0xEA,0x2B,0x2F,0x64,0xA9,0x50,0x3D,0xAB,\n\n0x50,0x77,0xE9,0xC0,0xAC,0x6D,0x3F,0xCA,0xCF,0x71,0x7D,0x80,0xA6,0xFD,0xFF,0xB5,\n0xBD,0x6F,0x24,0x7B,0x00,0x99,0x5D,0xB1,0x48,0xB0,0x28,0x7F,0x80,0xEC,0xBF,0x6F,\n0x6E,0x39,0x90,0x42,0xD9,0x4E,0x2E,0x12,0x66,0xC8,0xCF,0x3B,0x3F,0x10,0x7D,0x79,\n0x00,0xD3,0x1F,0x21,0x93,0x34,0xD7,0x19,0x22,0xA2,0x08,0x20,0xB9,0xB9,0xEF,0x51,\n\n0x99,0xDE,0xBF,0xD4,0x09,0x75,0xE9,0x8A,0xEE,0xFD,0xE4,0x4E,0x30,0x17,0xDF,0xCE,\n0x11,0xB2,0x28,0x35,0xC2,0x7C,0x64,0xEB,0x91,0x5F,0x32,0x0C,0x6E,0x00,0xF9,0x92,\n0x19,0xDB,0x8F,0xAB,0xAE,0xD6,0x12,0xC4,0x26,0x62,0xCE,0xCC,0x0A,0x03,0xE7,0xDD,\n0xE2,0x4D,0x8A,0xA6,0x46,0x95,0x0F,0x8F,0xF5,0x15,0x97,0x32,0xD4,0x28,0x1E,0x55\n};\n\n\n\n/* these variables stay here for speedup purposes only */\nstatic YM2151 * PSG;\nstatic signed int chanout[8];\nstatic signed int m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */\nstatic signed int mem;\t\t/* one sample delay memory */\n\n\n/* save output as raw 16-bit sample */\n// #define SAVE_SAMPLE\n// #define SAVE_SEPARATE_CHANNELS\n#if defined SAVE_SAMPLE || defined SAVE_SEPARATE_CHANNELS\n#include <stdio.h>\n\nstatic FILE *sample[9];\n#endif\n\n\n\n\nstatic void init_tables(void)\n{\n\tsigned int i,x,n;\n\tdouble o,m;\n\n\tfor (x=0; x<TL_RES_LEN; x++)\n\t{\n\t\tm = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);\n\t\tm = floor(m);\n\n\t\t/* we never reach (1<<16) here due to the (x+1) */\n\t\t/* result fits within 16 bits at maximum */\n\n\t\tn = (int)m;\t\t/* 16 bits here */\n\t\tn >>= 4;\t\t/* 12 bits here */\n\t\tif (n&1)\t\t/* round to closest */\n\t\t\tn = (n>>1)+1;\n\t\telse\n\t\t\tn = n>>1;\n\t\t\t\t\t\t/* 11 bits here (rounded) */\n\t\tn <<= 2;\t\t/* 13 bits here (as in real chip) */\n\t\ttl_tab[ x*2 + 0 ] = n;\n\t\ttl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];\n\n\t\tfor (i=1; i<13; i++)\n\t\t{\n\t\t\ttl_tab[ x*2+0 + i*2*TL_RES_LEN ] =  tl_tab[ x*2+0 ]>>i;\n\t\t\ttl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];\n\t\t}\n\t#if 0\n\t\tlogerror(\"tl %04i\", x*2);\n\t\tfor (i=0; i<13; i++)\n\t\t\tlogerror(\", [%02i] %4i\", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ]);\n\t\tlogerror(\"\\n\");\n\t#endif\n\t}\n\t/*logerror(\"TL_TAB_LEN = %i (%i bytes)\\n\",TL_TAB_LEN, (int)sizeof(tl_tab));*/\n\t/*logerror(\"ENV_QUIET= %i\\n\",ENV_QUIET );*/\n\n\n\tfor (i=0; i<SIN_LEN; i++)\n\t{\n\t\t/* non-standard sinus */\n\t\tm = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* verified on the real chip */\n\n\t\t/* we never reach zero here due to ((i*2)+1) */\n\n\t\tif (m>0.0)\n\t\t\to = 8*log(1.0/m)/log(2.0);\t/* convert to 'decibels' */\n\t\telse\n\t\t\to = 8*log(-1.0/m)/log(2.0);\t/* convert to 'decibels' */\n\n\t\to = o / (ENV_STEP/4);\n\n\t\tn = (int)(2.0*o);\n\t\tif (n&1)\t\t\t\t\t\t/* round to closest */\n\t\t\tn = (n>>1)+1;\n\t\telse\n\t\t\tn = n>>1;\n\n\t\tsin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );\n\t\t/*logerror(\"sin [0x%4x]= %4i (tl_tab value=%8x)\\n\", i, sin_tab[i],tl_tab[sin_tab[i]]);*/\n\t}\n\n\n\t/* calculate d1l_tab table */\n\tfor (i=0; i<16; i++)\n\t{\n\t\tm = (i!=15 ? i : i+16) * (4.0/ENV_STEP);   /* every 3 'dB' except for all bits = 1 = 45+48 'dB' */\n\t\td1l_tab[i] = m;\n\t\t/*logerror(\"d1l_tab[%02x]=%08x\\n\",i,d1l_tab[i] );*/\n\t}\n\n#ifdef SAVE_SAMPLE\n\tsample[8]=fopen(\"sampsum.pcm\",\"wb\");\n#endif\n#ifdef SAVE_SEPARATE_CHANNELS\n\tsample[0]=fopen(\"samp0.pcm\",\"wb\");\n\tsample[1]=fopen(\"samp1.pcm\",\"wb\");\n\tsample[2]=fopen(\"samp2.pcm\",\"wb\");\n\tsample[3]=fopen(\"samp3.pcm\",\"wb\");\n\tsample[4]=fopen(\"samp4.pcm\",\"wb\");\n\tsample[5]=fopen(\"samp5.pcm\",\"wb\");\n\tsample[6]=fopen(\"samp6.pcm\",\"wb\");\n\tsample[7]=fopen(\"samp7.pcm\",\"wb\");\n#endif\n}\n\n\nstatic void init_chip_tables(YM2151 *chip)\n{\n\tint i,j;\n\tdouble mult,phaseinc,Hz;\n\tdouble scaler;\n\t//attotime pom;\n\tdouble pom;\n\n\tscaler = ( (double)chip->clock / 64.0 ) / ( (double)chip->sampfreq );\n\t/*logerror(\"scaler    = %20.15f\\n\", scaler);*/\n\n\n\t/* this loop calculates Hertz values for notes from c-0 to b-7 */\n\t/* including 64 'cents' (100/64 that is 1.5625 of real cent) per note */\n\t/* i*100/64/1200 is equal to i/768 */\n\n\t/* real chip works with 10 bits fixed point values (10.10) */\n\tmult = (1<<(FREQ_SH-10)); /* -10 because phaseinc_rom table values are already in 10.10 format */\n\n\tfor (i=0; i<768; i++)\n\t{\n\t\t/* 3.4375 Hz is note A; C# is 4 semitones higher */\n\t\tHz = 1000;\n#if 0\n/* Hz is close, but not perfect */\n\t\t//Hz = scaler * 3.4375 * pow (2, (i + 4 * 64 ) / 768.0 );\n\t\t/* calculate phase increment */\n\t\tphaseinc = (Hz*SIN_LEN) / (double)chip->sampfreq;\n#endif\n\n\t\tphaseinc = phaseinc_rom[i];\t/* real chip phase increment */\n\t\tphaseinc *= scaler;\t\t\t/* adjust */\n\n\n\t\t/* octave 2 - reference octave */\n\t\tchip->freq[ 768+2*768+i ] = ((int)(phaseinc*mult)) & 0xffffffc0; /* adjust to X.10 fixed point */\n\t\t/* octave 0 and octave 1 */\n\t\tfor (j=0; j<2; j++)\n\t\t{\n\t\t\tchip->freq[768 + j*768 + i] = (chip->freq[ 768+2*768+i ] >> (2-j) ) & 0xffffffc0; /* adjust to X.10 fixed point */\n\t\t}\n\t\t/* octave 3 to 7 */\n\t\tfor (j=3; j<8; j++)\n\t\t{\n\t\t\tchip->freq[768 + j*768 + i] = chip->freq[ 768+2*768+i ] << (j-2);\n\t\t}\n\n\t#if 0\n\t\t\tpom = (double)chip->freq[ 768+2*768+i ] / ((double)(1<<FREQ_SH));\n\t\t\tpom = pom * (double)chip->sampfreq / (double)SIN_LEN;\n\t\t\tlogerror(\"1freq[%4i][%08x]= real %20.15f Hz  emul %20.15f Hz\\n\", i, chip->freq[ 768+2*768+i ], Hz, pom);\n\t#endif\n\t}\n\n\t/* octave -1 (all equal to: oct 0, _KC_00_, _KF_00_) */\n\tfor (i=0; i<768; i++)\n\t{\n\t\tchip->freq[ 0*768 + i ] = chip->freq[1*768+0];\n\t}\n\n\t/* octave 8 and 9 (all equal to: oct 7, _KC_14_, _KF_63_) */\n\tfor (j=8; j<10; j++)\n\t{\n\t\tfor (i=0; i<768; i++)\n\t\t{\n\t\t\tchip->freq[768+ j*768 + i ] = chip->freq[768 + 8*768 -1];\n\t\t}\n\t}\n\n#if 0\n\t\tfor (i=0; i<11*768; i++)\n\t\t{\n\t\t\tpom = (double)chip->freq[i] / ((double)(1<<FREQ_SH));\n\t\t\tpom = pom * (double)chip->sampfreq / (double)SIN_LEN;\n\t\t\tlogerror(\"freq[%4i][%08x]= emul %20.15f Hz\\n\", i, chip->freq[i], pom);\n\t\t}\n#endif\n\n\tmult = (1<<FREQ_SH);\n\tfor (j=0; j<4; j++)\n\t{\n\t\tfor (i=0; i<32; i++)\n\t\t{\n\t\t\tHz = ( (double)dt1_tab[j*32+i] * ((double)chip->clock/64.0) ) / (double)(1<<20);\n\n\t\t\t/*calculate phase increment*/\n\t\t\tphaseinc = (Hz*SIN_LEN) / (double)chip->sampfreq;\n\n\t\t\t/*positive and negative values*/\n\t\t\tchip->dt1_freq[ (j+0)*32 + i ] = phaseinc * mult;\n\t\t\tchip->dt1_freq[ (j+4)*32 + i ] = -chip->dt1_freq[ (j+0)*32 + i ];\n\n#if 0\n\t\t\t{\n\t\t\t\tint x = j*32 + i;\n\t\t\t\tpom = (double)chip->dt1_freq[x] / mult;\n\t\t\t\tpom = pom * (double)chip->sampfreq / (double)SIN_LEN;\n\t\t\t\tlogerror(\"DT1(%03i)[%02i %02i][%08x]= real %19.15f Hz  emul %19.15f Hz\\n\",\n\t\t\t\t\t\t x, j, i, chip->dt1_freq[x], Hz, pom);\n\t\t\t}\n#endif\n\t\t}\n\t}\n\n\n\t/* calculate timers' deltas */\n\t/* User's Manual pages 15,16  */\n\tmult = (1<<TIMER_SH);\n\tfor (i=0; i<1024; i++)\n\t{\n\t\t/* ASG 980324: changed to compute both tim_A_tab and timer_A_time */\n\t\t//pom= attotime_mul(ATTOTIME_IN_HZ(chip->clock), 64 * (1024 - i));\n\t\tpom = ((double)64 * (1024 - i) / chip->clock);\n\t\t#ifdef USE_MAME_TIMERS\n\t\t\tchip->timer_A_time[i] = pom;\n\t\t#else\n\t\t\t//chip->tim_A_tab[i] = attotime_to_double(pom) * (double)chip->sampfreq * mult;  /* number of samples that timer period takes (fixed point) */\n\t\t\tchip->tim_A_tab[i] = pom * (double)chip->sampfreq * mult;  /* number of samples that timer period takes (fixed point) */\n\t\t#endif\n\t}\n\tfor (i=0; i<256; i++)\n\t{\n\t\t/* ASG 980324: changed to compute both tim_B_tab and timer_B_time */\n\t\t//pom= attotime_mul(ATTOTIME_IN_HZ(chip->clock), 1024 * (256 - i));\n\t\tpom = ((double)1024 * (256 - i) / chip->clock);\n\t\t#ifdef USE_MAME_TIMERS\n\t\t\tchip->timer_B_time[i] = pom;\n\t\t#else\n\t\t\t//chip->tim_B_tab[i] = attotime_to_double(pom) * (double)chip->sampfreq * mult;  /* number of samples that timer period takes (fixed point) */\n\t\t\tchip->tim_B_tab[i] = pom * (double)chip->sampfreq * mult;  /* number of samples that timer period takes (fixed point) */\n\t\t#endif\n\t}\n\n\t/* calculate noise periods table */\n\tscaler = ( (double)chip->clock / 64.0 ) / ( (double)chip->sampfreq );\n\tfor (i=0; i<32; i++)\n\t{\n\t\tj = (i!=31 ? i : 30);\t\t\t\t/* rate 30 and 31 are the same */\n\t\tj = 32-j;\n\t\tj = (65536.0 / (double)(j*32.0));\t/* number of samples per one shift of the shift register */\n\t\t/*chip->noise_tab[i] = j * 64;*/\t/* number of chip clock cycles per one shift */\n\t\tchip->noise_tab[i] = j * 64 * scaler;\n\t\t/*logerror(\"noise_tab[%02x]=%08x\\n\", i, chip->noise_tab[i]);*/\n\t}\n}\n\n#define KEY_ON(op, key_set){\t\t\t\t\t\t\t\t\t\\\n\t\tif (!(op)->key)\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t(op)->phase = 0;\t\t\t/* clear phase */\t\t\\\n\t\t\t(op)->state = EG_ATT;\t\t/* KEY ON = attack */\t\\\n\t\t\t(op)->volume += (~(op)->volume *\t\t\t\t\t\\\n                           (eg_inc[(op)->eg_sel_ar + ((PSG->eg_cnt>>(op)->eg_sh_ar)&7)])\t\\\n                          ) >>4;\t\t\t\t\t\t\t\t\\\n\t\t\tif ((op)->volume <= MIN_ATT_INDEX)\t\t\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t(op)->volume = MIN_ATT_INDEX;\t\t\t\t\t\\\n\t\t\t\t(op)->state = EG_DEC;\t\t\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t(op)->key |= key_set;\t\t\t\t\t\t\t\t\t\\\n}\n\n#define KEY_OFF(op, key_clr){\t\t\t\t\t\t\t\t\t\\\n\t\tif ((op)->key)\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t(op)->key &= key_clr;\t\t\t\t\t\t\t\t\\\n\t\t\tif (!(op)->key)\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tif ((op)->state>EG_REL)\t\t\t\t\t\t\t\\\n\t\t\t\t\t(op)->state = EG_REL;/* KEY OFF = release */\\\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n}\n\nINLINE void envelope_KONKOFF(YM2151Operator * op, int v)\n{\n\tif (v&0x08)\t/* M1 */\n\t\tKEY_ON (op+0, 1)\n\telse\n\t\tKEY_OFF(op+0,~1)\n\n\tif (v&0x20)\t/* M2 */\n\t\tKEY_ON (op+1, 1)\n\telse\n\t\tKEY_OFF(op+1,~1)\n\n\tif (v&0x10)\t/* C1 */\n\t\tKEY_ON (op+2, 1)\n\telse\n\t\tKEY_OFF(op+2,~1)\n\n\tif (v&0x40)\t/* C2 */\n\t\tKEY_ON (op+3, 1)\n\telse\n\t\tKEY_OFF(op+3,~1)\n}\n\n\n#ifdef USE_MAME_TIMERS\n\n/*static TIMER_CALLBACK( irqAon_callback )\n{\n\tYM2151 *chip = (YM2151 *)ptr;\n\tint oldstate = chip->irqlinestate;\n\n\tchip->irqlinestate |= 1;\n\n\tif (oldstate == 0 && chip->irqhandler) (*chip->irqhandler)(chip->device, 1);\n}\n\nstatic TIMER_CALLBACK( irqBon_callback )\n{\n\tYM2151 *chip = (YM2151 *)ptr;\n\tint oldstate = chip->irqlinestate;\n\n\tchip->irqlinestate |= 2;\n\n\tif (oldstate == 0 && chip->irqhandler) (*chip->irqhandler)(chip->device, 1);\n}\n\nstatic TIMER_CALLBACK( irqAoff_callback )\n{\n\tYM2151 *chip = (YM2151 *)ptr;\n\tint oldstate = chip->irqlinestate;\n\n\tchip->irqlinestate &= ~1;\n\n\tif (oldstate == 1 && chip->irqhandler) (*chip->irqhandler)(chip->device, 0);\n}\n\nstatic TIMER_CALLBACK( irqBoff_callback )\n{\n\tYM2151 *chip = (YM2151 *)ptr;\n\tint oldstate = chip->irqlinestate;\n\n\tchip->irqlinestate &= ~2;\n\n\tif (oldstate == 2 && chip->irqhandler) (*chip->irqhandler)(chip->device, 0);\n}\n\nstatic TIMER_CALLBACK( timer_callback_a )\n{\n\tYM2151 *chip = (YM2151 *)ptr;\n\ttimer_adjust_oneshot(chip->timer_A, chip->timer_A_time[ chip->timer_A_index ], 0);\n\tchip->timer_A_index_old = chip->timer_A_index;\n\tif (chip->irq_enable & 0x04)\n\t{\n\t\tchip->status |= 1;\n\t\ttimer_set(machine, attotime_zero,chip,0,irqAon_callback);\n\t}\n\tif (chip->irq_enable & 0x80)\n\t\tchip->csm_req = 2;\t\t// request KEY ON / KEY OFF sequence\n}\nstatic TIMER_CALLBACK( timer_callback_b )\n{\n\tYM2151 *chip = (YM2151 *)ptr;\n\ttimer_adjust_oneshot(chip->timer_B, chip->timer_B_time[ chip->timer_B_index ], 0);\n\tchip->timer_B_index_old = chip->timer_B_index;\n\tif (chip->irq_enable & 0x08)\n\t{\n\t\tchip->status |= 2;\n\t\ttimer_set(machine, attotime_zero,chip,0,irqBon_callback);\n\t}\n}*/\n#if 0\nstatic TIMER_CALLBACK( timer_callback_chip_busy )\n{\n\tYM2151 *chip = (YM2151 *)ptr;\n\tchip->status &= 0x7f;\t/* reset busy flag */\n}\n#endif\n#endif\n\n\n\n\n\n\nINLINE void set_connect( YM2151Operator *om1, int cha, int v)\n{\n\tYM2151Operator *om2 = om1+1;\n\tYM2151Operator *oc1 = om1+2;\n\n\t/* set connect algorithm */\n\n\t/* MEM is simply one sample delay */\n\n\tswitch( v&7 )\n\t{\n\tcase 0:\n\t\t/* M1---C1---MEM---M2---C2---OUT */\n\t\tom1->connect = &c1;\n\t\toc1->connect = &mem;\n\t\tom2->connect = &c2;\n\t\tom1->mem_connect = &m2;\n\t\tbreak;\n\n\tcase 1:\n\t\t/* M1------+-MEM---M2---C2---OUT */\n\t\t/*      C1-+                     */\n\t\tom1->connect = &mem;\n\t\toc1->connect = &mem;\n\t\tom2->connect = &c2;\n\t\tom1->mem_connect = &m2;\n\t\tbreak;\n\n\tcase 2:\n\t\t/* M1-----------------+-C2---OUT */\n\t\t/*      C1---MEM---M2-+          */\n\t\tom1->connect = &c2;\n\t\toc1->connect = &mem;\n\t\tom2->connect = &c2;\n\t\tom1->mem_connect = &m2;\n\t\tbreak;\n\n\tcase 3:\n\t\t/* M1---C1---MEM------+-C2---OUT */\n\t\t/*                 M2-+          */\n\t\tom1->connect = &c1;\n\t\toc1->connect = &mem;\n\t\tom2->connect = &c2;\n\t\tom1->mem_connect = &c2;\n\t\tbreak;\n\n\tcase 4:\n\t\t/* M1---C1-+-OUT */\n\t\t/* M2---C2-+     */\n\t\t/* MEM: not used */\n\t\tom1->connect = &c1;\n\t\toc1->connect = &chanout[cha];\n\t\tom2->connect = &c2;\n\t\tom1->mem_connect = &mem;\t/* store it anywhere where it will not be used */\n\t\tbreak;\n\n\tcase 5:\n\t\t/*    +----C1----+     */\n\t\t/* M1-+-MEM---M2-+-OUT */\n\t\t/*    +----C2----+     */\n\t\tom1->connect = 0;\t/* special mark */\n\t\toc1->connect = &chanout[cha];\n\t\tom2->connect = &chanout[cha];\n\t\tom1->mem_connect = &m2;\n\t\tbreak;\n\n\tcase 6:\n\t\t/* M1---C1-+     */\n\t\t/*      M2-+-OUT */\n\t\t/*      C2-+     */\n\t\t/* MEM: not used */\n\t\tom1->connect = &c1;\n\t\toc1->connect = &chanout[cha];\n\t\tom2->connect = &chanout[cha];\n\t\tom1->mem_connect = &mem;\t/* store it anywhere where it will not be used */\n\t\tbreak;\n\n\tcase 7:\n\t\t/* M1-+     */\n\t\t/* C1-+-OUT */\n\t\t/* M2-+     */\n\t\t/* C2-+     */\n\t\t/* MEM: not used*/\n\t\tom1->connect = &chanout[cha];\n\t\toc1->connect = &chanout[cha];\n\t\tom2->connect = &chanout[cha];\n\t\tom1->mem_connect = &mem;\t/* store it anywhere where it will not be used */\n\t\tbreak;\n\t}\n}\n\n\nINLINE void refresh_EG(YM2151Operator * op)\n{\n\tUINT32 kc;\n\tUINT32 v;\n\n\tkc = op->kc;\n\n\t/* v = 32 + 2*RATE + RKS = max 126 */\n\n\tv = kc >> op->ks;\n\tif ((op->ar+v) < 32+62)\n\t{\n\t\top->eg_sh_ar  = eg_rate_shift [op->ar  + v ];\n\t\top->eg_sel_ar = eg_rate_select[op->ar  + v ];\n\t}\n\telse\n\t{\n\t\top->eg_sh_ar  = 0;\n\t\top->eg_sel_ar = 17*RATE_STEPS;\n\t}\n\top->eg_sh_d1r = eg_rate_shift [op->d1r + v];\n\top->eg_sel_d1r= eg_rate_select[op->d1r + v];\n\top->eg_sh_d2r = eg_rate_shift [op->d2r + v];\n\top->eg_sel_d2r= eg_rate_select[op->d2r + v];\n\top->eg_sh_rr  = eg_rate_shift [op->rr  + v];\n\top->eg_sel_rr = eg_rate_select[op->rr  + v];\n\n\n\top+=1;\n\n\tv = kc >> op->ks;\n\tif ((op->ar+v) < 32+62)\n\t{\n\t\top->eg_sh_ar  = eg_rate_shift [op->ar  + v ];\n\t\top->eg_sel_ar = eg_rate_select[op->ar  + v ];\n\t}\n\telse\n\t{\n\t\top->eg_sh_ar  = 0;\n\t\top->eg_sel_ar = 17*RATE_STEPS;\n\t}\n\top->eg_sh_d1r = eg_rate_shift [op->d1r + v];\n\top->eg_sel_d1r= eg_rate_select[op->d1r + v];\n\top->eg_sh_d2r = eg_rate_shift [op->d2r + v];\n\top->eg_sel_d2r= eg_rate_select[op->d2r + v];\n\top->eg_sh_rr  = eg_rate_shift [op->rr  + v];\n\top->eg_sel_rr = eg_rate_select[op->rr  + v];\n\n\top+=1;\n\n\tv = kc >> op->ks;\n\tif ((op->ar+v) < 32+62)\n\t{\n\t\top->eg_sh_ar  = eg_rate_shift [op->ar  + v ];\n\t\top->eg_sel_ar = eg_rate_select[op->ar  + v ];\n\t}\n\telse\n\t{\n\t\top->eg_sh_ar  = 0;\n\t\top->eg_sel_ar = 17*RATE_STEPS;\n\t}\n\top->eg_sh_d1r = eg_rate_shift [op->d1r + v];\n\top->eg_sel_d1r= eg_rate_select[op->d1r + v];\n\top->eg_sh_d2r = eg_rate_shift [op->d2r + v];\n\top->eg_sel_d2r= eg_rate_select[op->d2r + v];\n\top->eg_sh_rr  = eg_rate_shift [op->rr  + v];\n\top->eg_sel_rr = eg_rate_select[op->rr  + v];\n\n\top+=1;\n\n\tv = kc >> op->ks;\n\tif ((op->ar+v) < 32+62)\n\t{\n\t\top->eg_sh_ar  = eg_rate_shift [op->ar  + v ];\n\t\top->eg_sel_ar = eg_rate_select[op->ar  + v ];\n\t}\n\telse\n\t{\n\t\top->eg_sh_ar  = 0;\n\t\top->eg_sel_ar = 17*RATE_STEPS;\n\t}\n\top->eg_sh_d1r = eg_rate_shift [op->d1r + v];\n\top->eg_sel_d1r= eg_rate_select[op->d1r + v];\n\top->eg_sh_d2r = eg_rate_shift [op->d2r + v];\n\top->eg_sel_d2r= eg_rate_select[op->d2r + v];\n\top->eg_sh_rr  = eg_rate_shift [op->rr  + v];\n\top->eg_sel_rr = eg_rate_select[op->rr  + v];\n}\n\n\n/* write a register on YM2151 chip number 'n' */\nvoid ym2151_write_reg(void *_chip, int r, int v)\n{\n\tYM2151 *chip = (YM2151 *)_chip;\n\tYM2151Operator *op = &chip->oper[ (r&0x07)*4+((r&0x18)>>3) ];\n\n\t/* adjust bus to 8 bits */\n\tr &= 0xff;\n\tv &= 0xff;\n\n#if 0\n\t/* There is no info on what YM2151 really does when busy flag is set */\n\tif ( chip->status & 0x80 ) return;\n\ttimer_set ( attotime_mul(ATTOTIME_IN_HZ(chip->clock), 64), chip, 0, timer_callback_chip_busy);\n\tchip->status |= 0x80;\t/* set busy flag for 64 chip clock cycles */\n#endif\n\n\t/*if (LOG_CYM_FILE && (cymfile) && (r!=0) )\n\t{\n\t\tfputc( (unsigned char)r, cymfile );\n\t\tfputc( (unsigned char)v, cymfile );\n\t}*/\n\n\n\tswitch(r & 0xe0){\n\tcase 0x00:\n\t\tswitch(r){\n\t\tcase 0x01:\t/* LFO reset(bit 1), Test Register (other bits) */\n\t\t\tchip->test = v;\n\t\t\tif (v&2) chip->lfo_phase = 0;\n\t\t\tbreak;\n\n\t\tcase 0x08:\n\t\t\tPSG = chip; /* PSG is used in KEY_ON macro */\n\t\t\tenvelope_KONKOFF(&chip->oper[ (v&7)*4 ], v );\n\t\t\tbreak;\n\n\t\tcase 0x0f:\t/* noise mode enable, noise period */\n\t\t\tchip->noise = v;\n\t\t\tchip->noise_f = chip->noise_tab[ v & 0x1f ];\n\t\t\tbreak;\n\n\t\tcase 0x10:\t/* timer A hi */\n\t\t\tchip->timer_A_index = (chip->timer_A_index & 0x003) | (v<<2);\n\t\t\tbreak;\n\n\t\tcase 0x11:\t/* timer A low */\n\t\t\tchip->timer_A_index = (chip->timer_A_index & 0x3fc) | (v & 3);\n\t\t\tbreak;\n\n\t\tcase 0x12:\t/* timer B */\n\t\t\tchip->timer_B_index = v;\n\t\t\tbreak;\n\n\t\tcase 0x14:\t/* CSM, irq flag reset, irq enable, timer start/stop */\n\n\t\t\tchip->irq_enable = v;\t/* bit 3-timer B, bit 2-timer A, bit 7 - CSM */\n\n\t\t\tif (v&0x10)\t/* reset timer A irq flag */\n\t\t\t{\n#ifdef USE_MAME_TIMERS\n\t\t\t\tchip->status &= ~1;\n\t\t\t\ttimer_set(chip->device->machine, attotime_zero,chip,0,irqAoff_callback);\n#else\n\t\t\t\tint oldstate = chip->status & 3;\n\t\t\t\tchip->status &= ~1;\n\t\t\t\t//if ((oldstate==1) && (chip->irqhandler)) (*chip->irqhandler)(chip->device, 0);\n#endif\n\t\t\t}\n\n\t\t\tif (v&0x20)\t/* reset timer B irq flag */\n\t\t\t{\n#ifdef USE_MAME_TIMERS\n\t\t\t\tchip->status &= ~2;\n\t\t\t\ttimer_set(chip->device->machine, attotime_zero,chip,0,irqBoff_callback);\n#else\n\t\t\t\tint oldstate = chip->status & 3;\n\t\t\t\tchip->status &= ~2;\n\t\t\t\t//if ((oldstate==2) && (chip->irqhandler)) (*chip->irqhandler)(chip->device, 0);\n#endif\n\t\t\t}\n\n\t\t\tif (v&0x02){\t/* load and start timer B */\n\t\t\t\t#ifdef USE_MAME_TIMERS\n\t\t\t\t/* ASG 980324: added a real timer */\n\t\t\t\t/* start timer _only_ if it wasn't already started (it will reload time value next round) */\n\t\t\t\t\tif (!timer_enable(chip->timer_B, 1))\n\t\t\t\t\t{\n\t\t\t\t\t\ttimer_adjust_oneshot(chip->timer_B, chip->timer_B_time[ chip->timer_B_index ], 0);\n\t\t\t\t\t\tchip->timer_B_index_old = chip->timer_B_index;\n\t\t\t\t\t}\n\t\t\t\t#else\n\t\t\t\t\tif (!chip->tim_B)\n\t\t\t\t\t{\n\t\t\t\t\t\tchip->tim_B = 1;\n\t\t\t\t\t\tchip->tim_B_val = chip->tim_B_tab[ chip->timer_B_index ];\n\t\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}else{\t\t/* stop timer B */\n\t\t\t\t#ifdef USE_MAME_TIMERS\n\t\t\t\t/* ASG 980324: added a real timer */\n\t\t\t\t\ttimer_enable(chip->timer_B, 0);\n\t\t\t\t#else\n\t\t\t\t\tchip->tim_B = 0;\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tif (v&0x01){\t/* load and start timer A */\n\t\t\t\t#ifdef USE_MAME_TIMERS\n\t\t\t\t/* ASG 980324: added a real timer */\n\t\t\t\t/* start timer _only_ if it wasn't already started (it will reload time value next round) */\n\t\t\t\t\tif (!timer_enable(chip->timer_A, 1))\n\t\t\t\t\t{\n\t\t\t\t\t\ttimer_adjust_oneshot(chip->timer_A, chip->timer_A_time[ chip->timer_A_index ], 0);\n\t\t\t\t\t\tchip->timer_A_index_old = chip->timer_A_index;\n\t\t\t\t\t}\n\t\t\t\t#else\n\t\t\t\t\tif (!chip->tim_A)\n\t\t\t\t\t{\n\t\t\t\t\t\tchip->tim_A = 1;\n\t\t\t\t\t\tchip->tim_A_val = chip->tim_A_tab[ chip->timer_A_index ];\n\t\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}else{\t\t/* stop timer A */\n\t\t\t\t#ifdef USE_MAME_TIMERS\n\t\t\t\t/* ASG 980324: added a real timer */\n\t\t\t\t\ttimer_enable(chip->timer_A, 0);\n\t\t\t\t#else\n\t\t\t\t\tchip->tim_A = 0;\n\t\t\t\t#endif\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0x18:\t/* LFO frequency */\n\t\t\t{\n\t\t\t\tchip->lfo_overflow    = ( 1 << ((15-(v>>4))+3) ) * (1<<LFO_SH);\n\t\t\t\tchip->lfo_counter_add = 0x10 + (v & 0x0f);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0x19:\t/* PMD (bit 7==1) or AMD (bit 7==0) */\n\t\t\tif (v&0x80)\n\t\t\t\tchip->pmd = v & 0x7f;\n\t\t\telse\n\t\t\t\tchip->amd = v & 0x7f;\n\t\t\tbreak;\n\n\t\tcase 0x1b:\t/* CT2, CT1, LFO waveform */\n\t\t\tchip->ct = v >> 6;\n\t\t\tchip->lfo_wsel = v & 3;\n\t\t\t//if (chip->porthandler) (*chip->porthandler)(chip->device, 0 , chip->ct );\n\t\t\tbreak;\n\n\t\tdefault:\n#ifdef _DEBUG\n\t\t\t//logerror(\"YM2151 Write %02x to undocumented register #%02x\\n\",v,r);\n#endif\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\n\tcase 0x20:\n\t\top = &chip->oper[ (r&7) * 4 ];\n\t\tswitch(r & 0x18){\n\t\tcase 0x00:\t/* RL enable, Feedback, Connection */\n\t\t\top->fb_shift = ((v>>3)&7) ? ((v>>3)&7)+6:0;\n\t\t\tchip->pan[ (r&7)*2    ] = (v & 0x40) ? ~0 : 0;\n\t\t\tchip->pan[ (r&7)*2 +1 ] = (v & 0x80) ? ~0 : 0;\n\t\t\tchip->connect[r&7] = v&7;\n\t\t\tset_connect(op, r&7, v&7);\n\t\t\tbreak;\n\n\t\tcase 0x08:\t/* Key Code */\n\t\t\tv &= 0x7f;\n\t\t\tif (v != op->kc)\n\t\t\t{\n\t\t\t\tUINT32 kc, kc_channel;\n\n\t\t\t\tkc_channel = (v - (v>>2))*64;\n\t\t\t\tkc_channel += 768;\n\t\t\t\tkc_channel |= (op->kc_i & 63);\n\n\t\t\t\t(op+0)->kc = v;\n\t\t\t\t(op+0)->kc_i = kc_channel;\n\t\t\t\t(op+1)->kc = v;\n\t\t\t\t(op+1)->kc_i = kc_channel;\n\t\t\t\t(op+2)->kc = v;\n\t\t\t\t(op+2)->kc_i = kc_channel;\n\t\t\t\t(op+3)->kc = v;\n\t\t\t\t(op+3)->kc_i = kc_channel;\n\n\t\t\t\tkc = v>>2;\n\n\t\t\t\t(op+0)->dt1 = chip->dt1_freq[ (op+0)->dt1_i + kc ];\n\t\t\t\t(op+0)->freq = ( (chip->freq[ kc_channel + (op+0)->dt2 ] + (op+0)->dt1) * (op+0)->mul ) >> 1;\n\n\t\t\t\t(op+1)->dt1 = chip->dt1_freq[ (op+1)->dt1_i + kc ];\n\t\t\t\t(op+1)->freq = ( (chip->freq[ kc_channel + (op+1)->dt2 ] + (op+1)->dt1) * (op+1)->mul ) >> 1;\n\n\t\t\t\t(op+2)->dt1 = chip->dt1_freq[ (op+2)->dt1_i + kc ];\n\t\t\t\t(op+2)->freq = ( (chip->freq[ kc_channel + (op+2)->dt2 ] + (op+2)->dt1) * (op+2)->mul ) >> 1;\n\n\t\t\t\t(op+3)->dt1 = chip->dt1_freq[ (op+3)->dt1_i + kc ];\n\t\t\t\t(op+3)->freq = ( (chip->freq[ kc_channel + (op+3)->dt2 ] + (op+3)->dt1) * (op+3)->mul ) >> 1;\n\n\t\t\t\trefresh_EG( op );\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0x10:\t/* Key Fraction */\n\t\t\tv >>= 2;\n\t\t\tif (v !=  (op->kc_i & 63))\n\t\t\t{\n\t\t\t\tUINT32 kc_channel;\n\n\t\t\t\tkc_channel = v;\n\t\t\t\tkc_channel |= (op->kc_i & ~63);\n\n\t\t\t\t(op+0)->kc_i = kc_channel;\n\t\t\t\t(op+1)->kc_i = kc_channel;\n\t\t\t\t(op+2)->kc_i = kc_channel;\n\t\t\t\t(op+3)->kc_i = kc_channel;\n\n\t\t\t\t(op+0)->freq = ( (chip->freq[ kc_channel + (op+0)->dt2 ] + (op+0)->dt1) * (op+0)->mul ) >> 1;\n\t\t\t\t(op+1)->freq = ( (chip->freq[ kc_channel + (op+1)->dt2 ] + (op+1)->dt1) * (op+1)->mul ) >> 1;\n\t\t\t\t(op+2)->freq = ( (chip->freq[ kc_channel + (op+2)->dt2 ] + (op+2)->dt1) * (op+2)->mul ) >> 1;\n\t\t\t\t(op+3)->freq = ( (chip->freq[ kc_channel + (op+3)->dt2 ] + (op+3)->dt1) * (op+3)->mul ) >> 1;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0x18:\t/* PMS, AMS */\n\t\t\top->pms = (v>>4) & 7;\n\t\t\top->ams = (v & 3);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\n\tcase 0x40:\t\t/* DT1, MUL */\n\t\t{\n\t\t\tUINT32 olddt1_i = op->dt1_i;\n\t\t\tUINT32 oldmul = op->mul;\n\n\t\t\top->dt1_i = (v&0x70)<<1;\n\t\t\top->mul   = (v&0x0f) ? (v&0x0f)<<1: 1;\n\n\t\t\tif (olddt1_i != op->dt1_i)\n\t\t\t\top->dt1 = chip->dt1_freq[ op->dt1_i + (op->kc>>2) ];\n\n\t\t\tif ( (olddt1_i != op->dt1_i) || (oldmul != op->mul) )\n\t\t\t\top->freq = ( (chip->freq[ op->kc_i + op->dt2 ] + op->dt1) * op->mul ) >> 1;\n\t\t}\n\t\tbreak;\n\n\tcase 0x60:\t\t/* TL */\n\t\top->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */\n\t\tbreak;\n\n\tcase 0x80:\t\t/* KS, AR */\n\t\t{\n\t\t\tUINT32 oldks = op->ks;\n\t\t\tUINT32 oldar = op->ar;\n\n\t\t\top->ks = 5-(v>>6);\n\t\t\top->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\n\n\t\t\tif ( (op->ar != oldar) || (op->ks != oldks) )\n\t\t\t{\n\t\t\t\tif ((op->ar + (op->kc>>op->ks)) < 32+62)\n\t\t\t\t{\n\t\t\t\t\top->eg_sh_ar  = eg_rate_shift [op->ar  + (op->kc>>op->ks) ];\n\t\t\t\t\top->eg_sel_ar = eg_rate_select[op->ar  + (op->kc>>op->ks) ];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\top->eg_sh_ar  = 0;\n\t\t\t\t\top->eg_sel_ar = 17*RATE_STEPS;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (op->ks != oldks)\n\t\t\t{\n\t\t\t\top->eg_sh_d1r = eg_rate_shift [op->d1r + (op->kc>>op->ks) ];\n\t\t\t\top->eg_sel_d1r= eg_rate_select[op->d1r + (op->kc>>op->ks) ];\n\t\t\t\top->eg_sh_d2r = eg_rate_shift [op->d2r + (op->kc>>op->ks) ];\n\t\t\t\top->eg_sel_d2r= eg_rate_select[op->d2r + (op->kc>>op->ks) ];\n\t\t\t\top->eg_sh_rr  = eg_rate_shift [op->rr  + (op->kc>>op->ks) ];\n\t\t\t\top->eg_sel_rr = eg_rate_select[op->rr  + (op->kc>>op->ks) ];\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\tcase 0xa0:\t\t/* LFO AM enable, D1R */\n\t\top->AMmask = (v&0x80) ? ~0 : 0;\n\t\top->d1r    = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\n\t\top->eg_sh_d1r = eg_rate_shift [op->d1r + (op->kc>>op->ks) ];\n\t\top->eg_sel_d1r= eg_rate_select[op->d1r + (op->kc>>op->ks) ];\n\t\tbreak;\n\n\tcase 0xc0:\t\t/* DT2, D2R */\n\t\t{\n\t\t\tUINT32 olddt2 = op->dt2;\n\t\t\top->dt2 = dt2_tab[ v>>6 ];\n\t\t\tif (op->dt2 != olddt2)\n\t\t\t\top->freq = ( (chip->freq[ op->kc_i + op->dt2 ] + op->dt1) * op->mul ) >> 1;\n\t\t}\n\t\top->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;\n\t\top->eg_sh_d2r = eg_rate_shift [op->d2r + (op->kc>>op->ks) ];\n\t\top->eg_sel_d2r= eg_rate_select[op->d2r + (op->kc>>op->ks) ];\n\t\tbreak;\n\n\tcase 0xe0:\t\t/* D1L, RR */\n\t\top->d1l = d1l_tab[ v>>4 ];\n\t\top->rr  = 34 + ((v&0x0f)<<2);\n\t\top->eg_sh_rr  = eg_rate_shift [op->rr  + (op->kc>>op->ks) ];\n\t\top->eg_sel_rr = eg_rate_select[op->rr  + (op->kc>>op->ks) ];\n\t\tbreak;\n\t}\n}\n\n\n/*static TIMER_CALLBACK( cymfile_callback )\n{\n\tif (cymfile)\n\t\tfputc( (unsigned char)0, cymfile );\n}*/\n\n\nint ym2151_read_status( void *_chip )\n{\n\tYM2151 *chip = (YM2151 *)_chip;\n\treturn chip->status;\n}\n\n\n\n//#ifdef USE_MAME_TIMERS\n#if 1 // disabled for now due to crashing with winalloc.c (ERROR_NOT_ENOUGH_MEMORY)\n/*\n*   state save support for MAME\n*/\n//STATE_POSTLOAD( ym2151_postload )\n/*void ym2151_postload(void *param)\n{\n\tYM2151 *YM2151_chip = (YM2151 *)param;\n\tint j;\n\n\tfor (j=0; j<8; j++)\n\t\tset_connect(&YM2151_chip->oper[j*4], j, YM2151_chip->connect[j]);\n}\n\nstatic void ym2151_state_save_register( YM2151 *chip, const device_config *device )\n{\n\tint j;\n\n\t// save all 32 operators of chip #i\n\tfor (j=0; j<32; j++)\n\t{\n\t\tYM2151Operator *op;\n\n\t\top = &chip->oper[(j&7)*4+(j>>3)];\n\n\t\tstate_save_register_device_item(device, j, op->phase);\n\t\tstate_save_register_device_item(device, j, op->freq);\n\t\tstate_save_register_device_item(device, j, op->dt1);\n\t\tstate_save_register_device_item(device, j, op->mul);\n\t\tstate_save_register_device_item(device, j, op->dt1_i);\n\t\tstate_save_register_device_item(device, j, op->dt2);\n\t\t// operators connection is saved in chip data block\n\t\tstate_save_register_device_item(device, j, op->mem_value);\n\n\t\tstate_save_register_device_item(device, j, op->fb_shift);\n\t\tstate_save_register_device_item(device, j, op->fb_out_curr);\n\t\tstate_save_register_device_item(device, j, op->fb_out_prev);\n\t\tstate_save_register_device_item(device, j, op->kc);\n\t\tstate_save_register_device_item(device, j, op->kc_i);\n\t\tstate_save_register_device_item(device, j, op->pms);\n\t\tstate_save_register_device_item(device, j, op->ams);\n\t\tstate_save_register_device_item(device, j, op->AMmask);\n\n\t\tstate_save_register_device_item(device, j, op->state);\n\t\tstate_save_register_device_item(device, j, op->eg_sh_ar);\n\t\tstate_save_register_device_item(device, j, op->eg_sel_ar);\n\t\tstate_save_register_device_item(device, j, op->tl);\n\t\tstate_save_register_device_item(device, j, op->volume);\n\t\tstate_save_register_device_item(device, j, op->eg_sh_d1r);\n\t\tstate_save_register_device_item(device, j, op->eg_sel_d1r);\n\t\tstate_save_register_device_item(device, j, op->d1l);\n\t\tstate_save_register_device_item(device, j, op->eg_sh_d2r);\n\t\tstate_save_register_device_item(device, j, op->eg_sel_d2r);\n\t\tstate_save_register_device_item(device, j, op->eg_sh_rr);\n\t\tstate_save_register_device_item(device, j, op->eg_sel_rr);\n\n\t\tstate_save_register_device_item(device, j, op->key);\n\t\tstate_save_register_device_item(device, j, op->ks);\n\t\tstate_save_register_device_item(device, j, op->ar);\n\t\tstate_save_register_device_item(device, j, op->d1r);\n\t\tstate_save_register_device_item(device, j, op->d2r);\n\t\tstate_save_register_device_item(device, j, op->rr);\n\n\t\tstate_save_register_device_item(device, j, op->reserved0);\n\t\tstate_save_register_device_item(device, j, op->reserved1);\n\t}\n\n\tstate_save_register_device_item_array(device, 0, chip->pan);\n\n\tstate_save_register_device_item(device, 0, chip->eg_cnt);\n\tstate_save_register_device_item(device, 0, chip->eg_timer);\n\tstate_save_register_device_item(device, 0, chip->eg_timer_add);\n\tstate_save_register_device_item(device, 0, chip->eg_timer_overflow);\n\n\tstate_save_register_device_item(device, 0, chip->lfo_phase);\n\tstate_save_register_device_item(device, 0, chip->lfo_timer);\n\tstate_save_register_device_item(device, 0, chip->lfo_timer_add);\n\tstate_save_register_device_item(device, 0, chip->lfo_overflow);\n\tstate_save_register_device_item(device, 0, chip->lfo_counter);\n\tstate_save_register_device_item(device, 0, chip->lfo_counter_add);\n\tstate_save_register_device_item(device, 0, chip->lfo_wsel);\n\tstate_save_register_device_item(device, 0, chip->amd);\n\tstate_save_register_device_item(device, 0, chip->pmd);\n\tstate_save_register_device_item(device, 0, chip->lfa);\n\tstate_save_register_device_item(device, 0, chip->lfp);\n\n\tstate_save_register_device_item(device, 0, chip->test);\n\tstate_save_register_device_item(device, 0, chip->ct);\n\n\tstate_save_register_device_item(device, 0, chip->noise);\n\tstate_save_register_device_item(device, 0, chip->noise_rng);\n\tstate_save_register_device_item(device, 0, chip->noise_p);\n\tstate_save_register_device_item(device, 0, chip->noise_f);\n\n\tstate_save_register_device_item(device, 0, chip->csm_req);\n\tstate_save_register_device_item(device, 0, chip->irq_enable);\n\tstate_save_register_device_item(device, 0, chip->status);\n\n\tstate_save_register_device_item(device, 0, chip->timer_A_index);\n\tstate_save_register_device_item(device, 0, chip->timer_B_index);\n\tstate_save_register_device_item(device, 0, chip->timer_A_index_old);\n\tstate_save_register_device_item(device, 0, chip->timer_B_index_old);\n\n#ifdef USE_MAME_TIMERS\n\tstate_save_register_device_item(device, 0, chip->irqlinestate);\n#endif\n\n\tstate_save_register_device_item_array(device, 0, chip->connect);\n\n\tstate_save_register_postload(device->machine, ym2151_postload, chip);\n}*/\n#else\n/*STATE_POSTLOAD( ym2151_postload )\n{\n}\n\nstatic void ym2151_state_save_register( YM2151 *chip, const device_config *device )\n{\n}*/\n#endif\n\n\n/*\n*   Initialize YM2151 emulator(s).\n*\n*   'num' is the number of virtual YM2151's to allocate\n*   'clock' is the chip clock in Hz\n*   'rate' is sampling rate\n*/\nvoid * ym2151_init(int clock, int rate)\n{\n\tYM2151 *PSG;\n\tint chn;\n\n\tPSG = (YM2151 *)malloc(sizeof(YM2151));\n\tif (PSG == NULL)\n\t\treturn NULL;\n\n\tmemset(PSG, 0, sizeof(YM2151));\n\n\t//ym2151_state_save_register( PSG, device );\n\n\tinit_tables();\n\n\t//PSG->device = device;\n\tPSG->clock = clock;\n\t/*rate = clock/64;*/\n\tPSG->sampfreq = rate ? rate : 44100;\t/* avoid division by 0 in init_chip_tables() */\n\t//PSG->irqhandler = NULL;\t\t\t\t\t/* interrupt handler  */\n\t//PSG->porthandler = NULL;\t\t\t\t/* port write handler */\n\tinit_chip_tables( PSG );\n\n\tPSG->lfo_timer_add = (1<<LFO_SH) * (clock/64.0) / PSG->sampfreq;\n\n\tPSG->eg_timer_add  = (1<<EG_SH)  * (clock/64.0) / PSG->sampfreq;\n\tPSG->eg_timer_overflow = ( 3 ) * (1<<EG_SH);\n\t/*logerror(\"YM2151[init] eg_timer_add=%8x eg_timer_overflow=%8x\\n\", PSG->eg_timer_add, PSG->eg_timer_overflow);*/\n\n#ifdef USE_MAME_TIMERS\n/* this must be done _before_ a call to ym2151_reset_chip() */\n\tPSG->timer_A = timer_alloc(device->machine, timer_callback_a, PSG);\n\tPSG->timer_B = timer_alloc(device->machine, timer_callback_b, PSG);\n#else\n\tPSG->tim_A      = 0;\n\tPSG->tim_B      = 0;\n#endif\n\tfor (chn = 0; chn < 8; chn ++)\n\t\tPSG->Muted[chn] = 0x00;\n\t//ym2151_reset_chip(PSG);\n\t/*logerror(\"YM2151[init] clock=%i sampfreq=%i\\n\", PSG->clock, PSG->sampfreq);*/\n\n\t/*LOG_CYM_FILE = (options_get_int(mame_options(), OPTION_VGMWRITE) > 0x00);\n\tif (LOG_CYM_FILE)\n\t{\n\t\tcymfile = fopen(\"2151_.cym\",\"wb\");\n\t\tif (cymfile)\n\t\t\ttimer_pulse ( device->machine, ATTOTIME_IN_HZ(60), NULL, 0, cymfile_callback); //110 Hz pulse timer\n\t\telse\n\t\t\tlogerror(\"Could not create file 2151_.cym\\n\");\n\t}*/\n\n\treturn PSG;\n}\n\n\n\nvoid ym2151_shutdown(void *_chip)\n{\n\tYM2151 *chip = (YM2151 *)_chip;\n\n\tfree (chip);\n\n\t/*if (cymfile)\n\t\tfclose (cymfile);\n\tcymfile = NULL;*/\n\n#ifdef SAVE_SAMPLE\n\tfclose(sample[8]);\n#endif\n#ifdef SAVE_SEPARATE_CHANNELS\n\tfclose(sample[0]);\n\tfclose(sample[1]);\n\tfclose(sample[2]);\n\tfclose(sample[3]);\n\tfclose(sample[4]);\n\tfclose(sample[5]);\n\tfclose(sample[6]);\n\tfclose(sample[7]);\n#endif\n}\n\n\n\n/*\n*   Reset chip number 'n'.\n*/\nvoid ym2151_reset_chip(void *_chip)\n{\n\tint i;\n\tYM2151 *chip = (YM2151 *)_chip;\n\n\n\t/* initialize hardware registers */\n\tfor (i=0; i<32; i++)\n\t{\n\t\tmemset(&chip->oper[i],'\\0',sizeof(YM2151Operator));\n\t\tchip->oper[i].volume = MAX_ATT_INDEX;\n\t        chip->oper[i].kc_i = 768; /* min kc_i value */\n\t}\n\n\tchip->eg_timer = 0;\n\tchip->eg_cnt   = 0;\n\n\tchip->lfo_timer  = 0;\n\tchip->lfo_counter= 0;\n\tchip->lfo_phase  = 0;\n\tchip->lfo_wsel   = 0;\n\tchip->pmd = 0;\n\tchip->amd = 0;\n\tchip->lfa = 0;\n\tchip->lfp = 0;\n\n\tchip->test= 0;\n\n\tchip->irq_enable = 0;\n#ifdef USE_MAME_TIMERS\n\t/* ASG 980324 -- reset the timers before writing to the registers */\n\ttimer_enable(chip->timer_A, 0);\n\ttimer_enable(chip->timer_B, 0);\n#else\n\tchip->tim_A      = 0;\n\tchip->tim_B      = 0;\n\tchip->tim_A_val  = 0;\n\tchip->tim_B_val  = 0;\n#endif\n\tchip->timer_A_index = 0;\n\tchip->timer_B_index = 0;\n\tchip->timer_A_index_old = 0;\n\tchip->timer_B_index_old = 0;\n\n\tchip->noise     = 0;\n\tchip->noise_rng = 0;\n\tchip->noise_p   = 0;\n\tchip->noise_f   = chip->noise_tab[0];\n\n\tchip->csm_req\t= 0;\n\tchip->status    = 0;\n\n\tym2151_write_reg(chip, 0x1b, 0);\t/* only because of CT1, CT2 output pins */\n\tym2151_write_reg(chip, 0x18, 0);\t/* set LFO frequency */\n\tfor (i=0x20; i<0x100; i++)\t\t/* set the operators */\n\t{\n\t\tym2151_write_reg(chip, i, 0);\n\t}\n}\n\n\n\nINLINE signed int op_calc(YM2151Operator * OP, unsigned int env, signed int pm)\n{\n\tUINT32 p;\n\n\n\tp = (env<<3) + sin_tab[ ( ((signed int)((OP->phase & ~FREQ_MASK) + (pm<<15))) >> FREQ_SH ) & SIN_MASK ];\n\n\tif (p >= TL_TAB_LEN)\n\t\treturn 0;\n\n\treturn tl_tab[p];\n}\n\nINLINE signed int op_calc1(YM2151Operator * OP, unsigned int env, signed int pm)\n{\n\tUINT32 p;\n\tINT32  i;\n\n\n\ti = (OP->phase & ~FREQ_MASK) + pm;\n\n/*logerror(\"i=%08x (i>>16)&511=%8i phase=%i [pm=%08x] \",i, (i>>16)&511, OP->phase>>FREQ_SH, pm);*/\n\n\tp = (env<<3) + sin_tab[ (i>>FREQ_SH) & SIN_MASK];\n\n/*logerror(\"(p&255=%i p>>8=%i) out= %i\\n\", p&255,p>>8, tl_tab[p&255]>>(p>>8) );*/\n\n\tif (p >= TL_TAB_LEN)\n\t\treturn 0;\n\n\treturn tl_tab[p];\n}\n\n\n\n#define volume_calc(OP) ((OP)->tl + ((UINT32)(OP)->volume) + (AM & (OP)->AMmask))\n\nINLINE void chan_calc(unsigned int chan)\n{\n\tYM2151Operator *op;\n\tunsigned int env;\n\tUINT32 AM = 0;\n\n\tif (PSG->Muted[chan])\n\t\treturn;\n\t\n\tm2 = c1 = c2 = mem = 0;\n\top = &PSG->oper[chan*4];\t/* M1 */\n\n\t*op->mem_connect = op->mem_value;\t/* restore delayed sample (MEM) value to m2 or c2 */\n\n\tif (op->ams)\n\t\tAM = PSG->lfa << (op->ams-1);\n\tenv = volume_calc(op);\n\t{\n\t\tINT32 out = op->fb_out_prev + op->fb_out_curr;\n\t\top->fb_out_prev = op->fb_out_curr;\n\n\t\tif (!op->connect)\n\t\t\t/* algorithm 5 */\n\t\t\tmem = c1 = c2 = op->fb_out_prev;\n\t\telse\n\t\t\t/* other algorithms */\n\t\t\t*op->connect = op->fb_out_prev;\n\n\t\top->fb_out_curr = 0;\n\t\tif (env < ENV_QUIET)\n\t\t{\n\t\t\tif (!op->fb_shift)\n\t\t\t\tout=0;\n\t\t\top->fb_out_curr = op_calc1(op, env, (out<<op->fb_shift) );\n\t\t}\n\t}\n\n\tenv = volume_calc(op+1);\t/* M2 */\n\tif (env < ENV_QUIET)\n\t\t*(op+1)->connect += op_calc(op+1, env, m2);\n\n\tenv = volume_calc(op+2);\t/* C1 */\n\tif (env < ENV_QUIET)\n\t\t*(op+2)->connect += op_calc(op+2, env, c1);\n\n\tenv = volume_calc(op+3);\t/* C2 */\n\tif (env < ENV_QUIET)\n\t\tchanout[chan]    += op_calc(op+3, env, c2);\n\tif (chanout[chan] > +16384)\t\t\tchanout[chan] = +16384;\n\telse if (chanout[chan] < -16384)\tchanout[chan] = -16384;\n\n\t/* M1 */\n\top->mem_value = mem;\n}\nINLINE void chan7_calc(void)\n{\n\tYM2151Operator *op;\n\tunsigned int env;\n\tUINT32 AM = 0;\n\n\tif (PSG->Muted[7])\n\t\treturn;\n\t\n\tm2 = c1 = c2 = mem = 0;\n\top = &PSG->oper[7*4];\t\t/* M1 */\n\n\t*op->mem_connect = op->mem_value;\t/* restore delayed sample (MEM) value to m2 or c2 */\n\n\tif (op->ams)\n\t\tAM = PSG->lfa << (op->ams-1);\n\tenv = volume_calc(op);\n\t{\n\t\tINT32 out = op->fb_out_prev + op->fb_out_curr;\n\t\top->fb_out_prev = op->fb_out_curr;\n\n\t\tif (!op->connect)\n\t\t\t/* algorithm 5 */\n\t\t\tmem = c1 = c2 = op->fb_out_prev;\n\t\telse\n\t\t\t/* other algorithms */\n\t\t\t*op->connect = op->fb_out_prev;\n\n\t\top->fb_out_curr = 0;\n\t\tif (env < ENV_QUIET)\n\t\t{\n\t\t\tif (!op->fb_shift)\n\t\t\t\tout=0;\n\t\t\top->fb_out_curr = op_calc1(op, env, (out<<op->fb_shift) );\n\t\t}\n\t}\n\n\tenv = volume_calc(op+1);\t/* M2 */\n\tif (env < ENV_QUIET)\n\t\t*(op+1)->connect += op_calc(op+1, env, m2);\n\n\tenv = volume_calc(op+2);\t/* C1 */\n\tif (env < ENV_QUIET)\n\t\t*(op+2)->connect += op_calc(op+2, env, c1);\n\n\tenv = volume_calc(op+3);\t/* C2 */\n\tif (PSG->noise & 0x80)\n\t{\n\t\tINT32 noiseout;\n\n\t\tnoiseout = 0;\n\t\tif (env < 0x3ff)\n\t\t\tnoiseout = (env ^ 0x3ff) * 2;\t/* range of the YM2151 noise output is -2044 to 2040 */\n\t\tchanout[7] += ((PSG->noise_rng&0x10000) ? noiseout: -noiseout); /* bit 16 -> output */\n\t}\n\telse\n\t{\n\t\tif (env < ENV_QUIET)\n\t\t\tchanout[7] += op_calc(op+3, env, c2);\n\t}\n\tif (chanout[7] > +16384)\t\tchanout[7] = +16384;\n\telse if (chanout[7] < -16384)\tchanout[7] = -16384;\n\t/* M1 */\n\top->mem_value = mem;\n}\n\n\n\n\n\n\n/*\nThe 'rate' is calculated from following formula (example on decay rate):\n  rks = notecode after key scaling (a value from 0 to 31)\n  DR = value written to the chip register\n  rate = 2*DR + rks; (max rate = 2*31+31 = 93)\nFour MSBs of the 'rate' above are the 'main' rate (from 00 to 15)\nTwo LSBs of the 'rate' above are the value 'x' (the shape type).\n(eg. '11 2' means that 'rate' is 11*4+2=46)\n\nNOTE: A 'sample' in the description below is actually 3 output samples,\nthats because the Envelope Generator clock is equal to internal_clock/3.\n\nSingle '-' (minus) character in the diagrams below represents one sample\non the output; this is for rates 11 x (11 0, 11 1, 11 2 and 11 3)\n\nthese 'main' rates:\n00 x: single '-' = 2048 samples; (ie. level can change every 2048 samples)\n01 x: single '-' = 1024 samples;\n02 x: single '-' = 512 samples;\n03 x: single '-' = 256 samples;\n04 x: single '-' = 128 samples;\n05 x: single '-' = 64 samples;\n06 x: single '-' = 32 samples;\n07 x: single '-' = 16 samples;\n08 x: single '-' = 8 samples;\n09 x: single '-' = 4 samples;\n10 x: single '-' = 2 samples;\n11 x: single '-' = 1 sample; (ie. level can change every 1 sample)\n\nShapes for rates 11 x look like this:\nrate:       step:\n11 0        01234567\n\nlevel:\n0           --\n1             --\n2               --\n3                 --\n\nrate:       step:\n11 1        01234567\n\nlevel:\n0           --\n1             --\n2               -\n3                -\n4                 --\n\nrate:       step:\n11 2        01234567\n\nlevel:\n0           --\n1             -\n2              -\n3               --\n4                 -\n5                  -\n\nrate:       step:\n11 3        01234567\n\nlevel:\n0           --\n1             -\n2              -\n3               -\n4                -\n5                 -\n6                  -\n\n\nFor rates 12 x, 13 x, 14 x and 15 x output level changes on every\nsample - this means that the waveform looks like this: (but the level\nchanges by different values on different steps)\n12 3        01234567\n\n0           -\n2            -\n4             -\n8              -\n10              -\n12               -\n14                -\n18                 -\n20                  -\n\nNotes about the timing:\n----------------------\n\n1. Synchronism\n\nOutput level of each two (or more) voices running at the same 'main' rate\n(eg 11 0 and 11 1 in the diagram below) will always be changing in sync,\neven if there're started with some delay.\n\nNote that, in the diagram below, the decay phase in channel 0 starts at\nsample #2, while in channel 1 it starts at sample #6. Anyway, both channels\nwill always change their levels at exactly the same (following) samples.\n\n(S - start point of this channel, A-attack phase, D-decay phase):\n\nstep:\n01234567012345670123456\n\nchannel 0:\n  --\n |  --\n |    -\n |     -\n |      --\n |        --\n|           --\n|             -\n|              -\n|               --\nAADDDDDDDDDDDDDDDD\nS\n\n01234567012345670123456\nchannel 1:\n      -\n     | -\n     |  --\n     |    --\n     |      --\n     |        -\n    |          -\n    |           --\n    |             --\n    |               --\n    AADDDDDDDDDDDDDDDD\n    S\n01234567012345670123456\n\n\n2. Shifted (delayed) synchronism\n\nOutput of each two (or more) voices running at different 'main' rate\n(9 1, 10 1 and 11 1 in the diagrams below) will always be changing\nin 'delayed-sync' (even if there're started with some delay as in \"1.\")\n\nNote that the shapes are delayed by exactly one sample per one 'main' rate\nincrement. (Normally one would expect them to start at the same samples.)\n\nSee diagram below (* - start point of the shape).\n\ncycle:\n0123456701234567012345670123456701234567012345670123456701234567\n\nrate 09 1\n*-------\n        --------\n                ----\n                    ----\n                        --------\n                                *-------\n                                |       --------\n                                |               ----\n                                |                   ----\n                                |                       --------\nrate 10 1                       |\n--                              |\n  *---                          |\n      ----                      |\n          --                    |\n            --                  |\n              ----              |\n                  *---          |\n                  |   ----      |\n                  |       --    | | <- one step (two samples) delay between 9 1 and 10 1\n                  |         --  | |\n                  |           ----|\n                  |               *---\n                  |                   ----\n                  |                       --\n                  |                         --\n                  |                           ----\nrate 11 1         |\n-                 |\n --               |\n   *-             |\n     --           |\n       -          |\n        -         |\n         --       |\n           *-     |\n             --   |\n               -  || <- one step (one sample) delay between 10 1 and 11 1\n                - ||\n                 --|\n                   *-\n                     --\n                       -\n                        -\n                         --\n                           *-\n                             --\n                               -\n                                -\n                                 --\n*/\n\nINLINE void advance_eg(void)\n{\n\tYM2151Operator *op;\n\tunsigned int i;\n\n\n\n\tPSG->eg_timer += PSG->eg_timer_add;\n\n\twhile (PSG->eg_timer >= PSG->eg_timer_overflow)\n\t{\n\t\tPSG->eg_timer -= PSG->eg_timer_overflow;\n\n\t\tPSG->eg_cnt++;\n\n\t\t/* envelope generator */\n\t\top = &PSG->oper[0];\t/* CH 0 M1 */\n\t\ti = 32;\n\t\tdo\n\t\t{\n\t\t\tswitch(op->state)\n\t\t\t{\n\t\t\tcase EG_ATT:\t/* attack phase */\n\t\t\t\tif ( !(PSG->eg_cnt & ((1<<op->eg_sh_ar)-1) ) )\n\t\t\t\t{\n\t\t\t\t\top->volume += (~op->volume *\n                                   (eg_inc[op->eg_sel_ar + ((PSG->eg_cnt>>op->eg_sh_ar)&7)])\n                                  ) >>4;\n\n\t\t\t\t\tif (op->volume <= MIN_ATT_INDEX)\n\t\t\t\t\t{\n\t\t\t\t\t\top->volume = MIN_ATT_INDEX;\n\t\t\t\t\t\top->state = EG_DEC;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_DEC:\t/* decay phase */\n\t\t\t\tif ( !(PSG->eg_cnt & ((1<<op->eg_sh_d1r)-1) ) )\n\t\t\t\t{\n\t\t\t\t\top->volume += eg_inc[op->eg_sel_d1r + ((PSG->eg_cnt>>op->eg_sh_d1r)&7)];\n\n\t\t\t\t\tif ( op->volume >= op->d1l )\n\t\t\t\t\t\top->state = EG_SUS;\n\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_SUS:\t/* sustain phase */\n\t\t\t\tif ( !(PSG->eg_cnt & ((1<<op->eg_sh_d2r)-1) ) )\n\t\t\t\t{\n\t\t\t\t\top->volume += eg_inc[op->eg_sel_d2r + ((PSG->eg_cnt>>op->eg_sh_d2r)&7)];\n\n\t\t\t\t\tif ( op->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t{\n\t\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t\t\top->state = EG_OFF;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_REL:\t/* release phase */\n\t\t\t\tif ( !(PSG->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\n\t\t\t\t{\n\t\t\t\t\top->volume += eg_inc[op->eg_sel_rr + ((PSG->eg_cnt>>op->eg_sh_rr)&7)];\n\n\t\t\t\t\tif ( op->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t{\n\t\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t\t\top->state = EG_OFF;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\t\t\top++;\n\t\t\ti--;\n\t\t}while (i);\n\t}\n}\n\n\nINLINE void advance(void)\n{\n\tYM2151Operator *op;\n\tunsigned int i;\n\tint a,p;\n\n\t/* LFO */\n\tif (PSG->test&2)\n\t\tPSG->lfo_phase = 0;\n\telse\n\t{\n\t\tPSG->lfo_timer += PSG->lfo_timer_add;\n\t\tif (PSG->lfo_timer >= PSG->lfo_overflow)\n\t\t{\n\t\t\tPSG->lfo_timer   -= PSG->lfo_overflow;\n\t\t\tPSG->lfo_counter += PSG->lfo_counter_add;\n\t\t\tPSG->lfo_phase   += (PSG->lfo_counter>>4);\n\t\t\tPSG->lfo_phase   &= 255;\n\t\t\tPSG->lfo_counter &= 15;\n\t\t}\n\t}\n\n\ti = PSG->lfo_phase;\n\t/* calculate LFO AM and PM waveform value (all verified on real chip, except for noise algorithm which is impossible to analyse)*/\n\tswitch (PSG->lfo_wsel)\n\t{\n\tcase 0:\n\t\t/* saw */\n\t\t/* AM: 255 down to 0 */\n\t\t/* PM: 0 to 127, -127 to 0 (at PMD=127: LFP = 0 to 126, -126 to 0) */\n\t\ta = 255 - i;\n\t\tif (i<128)\n\t\t\tp = i;\n\t\telse\n\t\t\tp = i - 255;\n\t\tbreak;\n\tcase 1:\n\t\t/* square */\n\t\t/* AM: 255, 0 */\n\t\t/* PM: 128,-128 (LFP = exactly +PMD, -PMD) */\n\t\tif (i<128){\n\t\t\ta = 255;\n\t\t\tp = 128;\n\t\t}else{\n\t\t\ta = 0;\n\t\t\tp = -128;\n\t\t}\n\t\tbreak;\n\tcase 2:\n\t\t/* triangle */\n\t\t/* AM: 255 down to 1 step -2; 0 up to 254 step +2 */\n\t\t/* PM: 0 to 126 step +2, 127 to 1 step -2, 0 to -126 step -2, -127 to -1 step +2*/\n\t\tif (i<128)\n\t\t\ta = 255 - (i*2);\n\t\telse\n\t\t\ta = (i*2) - 256;\n\n\t\tif (i<64)\t\t\t\t\t\t/* i = 0..63 */\n\t\t\tp = i*2;\t\t\t\t\t/* 0 to 126 step +2 */\n\t\telse if (i<128)\t\t\t\t\t/* i = 64..127 */\n\t\t\t\tp = 255 - i*2;\t\t\t/* 127 to 1 step -2 */\n\t\t\telse if (i<192)\t\t\t\t/* i = 128..191 */\n\t\t\t\t\tp = 256 - i*2;\t\t/* 0 to -126 step -2*/\n\t\t\t\telse\t\t\t\t\t/* i = 192..255 */\n\t\t\t\t\tp = i*2 - 511;\t\t/*-127 to -1 step +2*/\n\t\tbreak;\n\tcase 3:\n\tdefault:\t/*keep the compiler happy*/\n\t\t/* random */\n\t\t/* the real algorithm is unknown !!!\n            We just use a snapshot of data from real chip */\n\n\t\t/* AM: range 0 to 255    */\n\t\t/* PM: range -128 to 127 */\n\n\t\ta = lfo_noise_waveform[i];\n\t\tp = a-128;\n\t\tbreak;\n\t}\n\tPSG->lfa = a * PSG->amd / 128;\n\tPSG->lfp = p * PSG->pmd / 128;\n\n\n\t/*  The Noise Generator of the YM2151 is 17-bit shift register.\n    *   Input to the bit16 is negated (bit0 XOR bit3) (EXNOR).\n    *   Output of the register is negated (bit0 XOR bit3).\n    *   Simply use bit16 as the noise output.\n    */\n\tPSG->noise_p += PSG->noise_f;\n\ti = (PSG->noise_p>>16);\t\t/* number of events (shifts of the shift register) */\n\tPSG->noise_p &= 0xffff;\n\twhile (i)\n\t{\n\t\tUINT32 j;\n\t\tj = ( (PSG->noise_rng ^ (PSG->noise_rng>>3) ) & 1) ^ 1;\n\t\tPSG->noise_rng = (j<<16) | (PSG->noise_rng>>1);\n\t\ti--;\n\t}\n\n\n\t/* phase generator */\n\top = &PSG->oper[0];\t/* CH 0 M1 */\n\ti = 8;\n\tdo\n\t{\n\t\tif (op->pms)\t/* only when phase modulation from LFO is enabled for this channel */\n\t\t{\n\t\t\tINT32 mod_ind = PSG->lfp;\t\t/* -128..+127 (8bits signed) */\n\t\t\tif (op->pms < 6)\n\t\t\t\tmod_ind >>= (6 - op->pms);\n\t\t\telse\n\t\t\t\tmod_ind <<= (op->pms - 5);\n\n\t\t\tif (mod_ind)\n\t\t\t{\n\t\t\t\tUINT32 kc_channel =\top->kc_i + mod_ind;\n\t\t\t\t(op+0)->phase += ( (PSG->freq[ kc_channel + (op+0)->dt2 ] + (op+0)->dt1) * (op+0)->mul ) >> 1;\n\t\t\t\t(op+1)->phase += ( (PSG->freq[ kc_channel + (op+1)->dt2 ] + (op+1)->dt1) * (op+1)->mul ) >> 1;\n\t\t\t\t(op+2)->phase += ( (PSG->freq[ kc_channel + (op+2)->dt2 ] + (op+2)->dt1) * (op+2)->mul ) >> 1;\n\t\t\t\t(op+3)->phase += ( (PSG->freq[ kc_channel + (op+3)->dt2 ] + (op+3)->dt1) * (op+3)->mul ) >> 1;\n\t\t\t}\n\t\t\telse\t\t/* phase modulation from LFO is equal to zero */\n\t\t\t{\n\t\t\t\t(op+0)->phase += (op+0)->freq;\n\t\t\t\t(op+1)->phase += (op+1)->freq;\n\t\t\t\t(op+2)->phase += (op+2)->freq;\n\t\t\t\t(op+3)->phase += (op+3)->freq;\n\t\t\t}\n\t\t}\n\t\telse\t\t\t/* phase modulation from LFO is disabled */\n\t\t{\n\t\t\t(op+0)->phase += (op+0)->freq;\n\t\t\t(op+1)->phase += (op+1)->freq;\n\t\t\t(op+2)->phase += (op+2)->freq;\n\t\t\t(op+3)->phase += (op+3)->freq;\n\t\t}\n\n\t\top+=4;\n\t\ti--;\n\t}while (i);\n\n\n\t/* CSM is calculated *after* the phase generator calculations (verified on real chip)\n    * CSM keyon line seems to be ORed with the KO line inside of the chip.\n    * The result is that it only works when KO (register 0x08) is off, ie. 0\n    *\n    * Interesting effect is that when timer A is set to 1023, the KEY ON happens\n    * on every sample, so there is no KEY OFF at all - the result is that\n    * the sound played is the same as after normal KEY ON.\n    */\n\n\tif (PSG->csm_req)\t\t\t/* CSM KEYON/KEYOFF seqeunce request */\n\t{\n\t\tif (PSG->csm_req==2)\t/* KEY ON */\n\t\t{\n\t\t\top = &PSG->oper[0];\t/* CH 0 M1 */\n\t\t\ti = 32;\n\t\t\tdo\n\t\t\t{\n\t\t\t\tKEY_ON(op, 2);\n\t\t\t\top++;\n\t\t\t\ti--;\n\t\t\t}while (i);\n\t\t\tPSG->csm_req = 1;\n\t\t}\n\t\telse\t\t\t\t\t/* KEY OFF */\n\t\t{\n\t\t\top = &PSG->oper[0];\t/* CH 0 M1 */\n\t\t\ti = 32;\n\t\t\tdo\n\t\t\t{\n\t\t\t\tKEY_OFF(op,~2);\n\t\t\t\top++;\n\t\t\t\ti--;\n\t\t\t}while (i);\n\t\t\tPSG->csm_req = 0;\n\t\t}\n\t}\n}\n\n#if 0\nINLINE signed int acc_calc(signed int value)\n{\n\tif (value>=0)\n\t{\n\t\tif (value < 0x0200)\n\t\t\treturn (value & ~0);\n\t\tif (value < 0x0400)\n\t\t\treturn (value & ~1);\n\t\tif (value < 0x0800)\n\t\t\treturn (value & ~3);\n\t\tif (value < 0x1000)\n\t\t\treturn (value & ~7);\n\t\tif (value < 0x2000)\n\t\t\treturn (value & ~15);\n\t\tif (value < 0x4000)\n\t\t\treturn (value & ~31);\n\t\treturn (value & ~63);\n\t}\n\t/*else value < 0*/\n\tif (value > -0x0200)\n\t\treturn (~abs(value) & ~0);\n\tif (value > -0x0400)\n\t\treturn (~abs(value) & ~1);\n\tif (value > -0x0800)\n\t\treturn (~abs(value) & ~3);\n\tif (value > -0x1000)\n\t\treturn (~abs(value) & ~7);\n\tif (value > -0x2000)\n\t\treturn (~abs(value) & ~15);\n\tif (value > -0x4000)\n\t\treturn (~abs(value) & ~31);\n\treturn (~abs(value) & ~63);\n}\n#endif\n\n/* first macro saves left and right channels to mono file */\n/* second macro saves left and right channels to stereo file */\n#if 0\t/*MONO*/\n\t#ifdef SAVE_SEPARATE_CHANNELS\n\t  #define SAVE_SINGLE_CHANNEL(j) \\\n\t  {\tsigned int pom= -(chanout[j] & PSG->pan[j*2]); \\\n\t\tif (pom > 32767) pom = 32767; else if (pom < -32768) pom = -32768; \\\n\t\tfputc((unsigned short)pom&0xff,sample[j]); \\\n\t\tfputc(((unsigned short)pom>>8)&0xff,sample[j]); \\\n\t  }\n\t#else\n\t  #define SAVE_SINGLE_CHANNEL(j)\n\t#endif\n#else\t/*STEREO*/\n\t#ifdef SAVE_SEPARATE_CHANNELS\n\t  #define SAVE_SINGLE_CHANNEL(j) \\\n\t  {\tsigned int pom = -(chanout[j] & PSG->pan[j*2]); \\\n\t\tif (pom > 32767) pom = 32767; else if (pom < -32768) pom = -32768; \\\n\t\tfputc((unsigned short)pom&0xff,sample[j]); \\\n\t\tfputc(((unsigned short)pom>>8)&0xff,sample[j]); \\\n\t\tpom = -(chanout[j] & PSG->pan[j*2+1]); \\\n\t\tif (pom > 32767) pom = 32767; else if (pom < -32768) pom = -32768; \\\n\t\tfputc((unsigned short)pom&0xff,sample[j]); \\\n\t\tfputc(((unsigned short)pom>>8)&0xff,sample[j]); \\\n\t  }\n\t#else\n\t  #define SAVE_SINGLE_CHANNEL(j)\n\t#endif\n#endif\n\n/* first macro saves left and right channels to mono file */\n/* second macro saves left and right channels to stereo file */\n#if 1\t/*MONO*/\n\t#ifdef SAVE_SAMPLE\n\t  #define SAVE_ALL_CHANNELS \\\n\t  {\tsigned int pom = outl; \\\n\t\t/*pom = acc_calc(pom);*/ \\\n\t\t/*fprintf(sample[8],\" %i\\n\",pom);*/ \\\n\t\tfputc((unsigned short)pom&0xff,sample[8]); \\\n\t\tfputc(((unsigned short)pom>>8)&0xff,sample[8]); \\\n\t  }\n\t#else\n\t  #define SAVE_ALL_CHANNELS\n\t#endif\n#else\t/*STEREO*/\n\t#ifdef SAVE_SAMPLE\n\t  #define SAVE_ALL_CHANNELS \\\n\t  {\tsigned int pom = outl; \\\n\t\tfputc((unsigned short)pom&0xff,sample[8]); \\\n\t\tfputc(((unsigned short)pom>>8)&0xff,sample[8]); \\\n\t\tpom = outr; \\\n\t\tfputc((unsigned short)pom&0xff,sample[8]); \\\n\t\tfputc(((unsigned short)pom>>8)&0xff,sample[8]); \\\n\t  }\n\t#else\n\t  #define SAVE_ALL_CHANNELS\n\t#endif\n#endif\n\n\n/*  Generate samples for one of the YM2151's\n*\n*   'num' is the number of virtual YM2151\n*   '**buffers' is table of pointers to the buffers: left and right\n*   'length' is the number of samples that should be generated\n*/\nvoid ym2151_update_one(void *chip, SAMP **buffers, int length)\n{\n\tint i, chn;\n\tsigned int outl,outr;\n\tSAMP *bufL, *bufR;\n\n\tbufL = buffers[0];\n\tbufR = buffers[1];\n\n\tPSG = (YM2151 *)chip;\n\n#ifdef USE_MAME_TIMERS\n\t\t/* ASG 980324 - handled by real timers now */\n#else\n\tif (PSG->tim_B)\n\t{\n\t\tPSG->tim_B_val -= ( length << TIMER_SH );\n\t\tif (PSG->tim_B_val<=0)\n\t\t{\n\t\t\tPSG->tim_B_val += PSG->tim_B_tab[ PSG->timer_B_index ];\n\t\t\tif ( PSG->irq_enable & 0x08 )\n\t\t\t{\n\t\t\t\tint oldstate = PSG->status & 3;\n\t\t\t\tPSG->status |= 2;\n\t\t\t\t//if ((!oldstate) && (PSG->irqhandler)) (*PSG->irqhandler)(chip->device, 1);\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n\tfor (i=0; i<length; i++)\n\t{\n\t\tadvance_eg();\n\n\t\tchanout[0] = 0;\n\t\tchanout[1] = 0;\n\t\tchanout[2] = 0;\n\t\tchanout[3] = 0;\n\t\tchanout[4] = 0;\n\t\tchanout[5] = 0;\n\t\tchanout[6] = 0;\n\t\tchanout[7] = 0;\n\n\t\tchan_calc(0);\n\t\tSAVE_SINGLE_CHANNEL(0)\n\t\tchan_calc(1);\n\t\tSAVE_SINGLE_CHANNEL(1)\n\t\tchan_calc(2);\n\t\tSAVE_SINGLE_CHANNEL(2)\n\t\tchan_calc(3);\n\t\tSAVE_SINGLE_CHANNEL(3)\n\t\tchan_calc(4);\n\t\tSAVE_SINGLE_CHANNEL(4)\n\t\tchan_calc(5);\n\t\tSAVE_SINGLE_CHANNEL(5)\n\t\tchan_calc(6);\n\t\tSAVE_SINGLE_CHANNEL(6)\n\t\tchan7_calc();\n\t\tSAVE_SINGLE_CHANNEL(7)\n\n\t\toutl = chanout[0] & PSG->pan[0];\n\t\toutr = chanout[0] & PSG->pan[1];\n\t\toutl += (chanout[1] & PSG->pan[2]);\n\t\toutr += (chanout[1] & PSG->pan[3]);\n\t\toutl += (chanout[2] & PSG->pan[4]);\n\t\toutr += (chanout[2] & PSG->pan[5]);\n\t\toutl += (chanout[3] & PSG->pan[6]);\n\t\toutr += (chanout[3] & PSG->pan[7]);\n\t\toutl += (chanout[4] & PSG->pan[8]);\n\t\toutr += (chanout[4] & PSG->pan[9]);\n\t\toutl += (chanout[5] & PSG->pan[10]);\n\t\toutr += (chanout[5] & PSG->pan[11]);\n\t\toutl += (chanout[6] & PSG->pan[12]);\n\t\toutr += (chanout[6] & PSG->pan[13]);\n\t\toutl += (chanout[7] & PSG->pan[14]);\n\t\toutr += (chanout[7] & PSG->pan[15]);\n\n\t\toutl >>= FINAL_SH;\n\t\toutr >>= FINAL_SH;\n\t\t//if (outl > MAXOUT) outl = MAXOUT;\n\t\t//\telse if (outl < MINOUT) outl = MINOUT;\n\t\t//if (outr > MAXOUT) outr = MAXOUT;\n\t\t//\telse if (outr < MINOUT) outr = MINOUT;\n\t\t((SAMP*)bufL)[i] = (SAMP)outl;\n\t\t((SAMP*)bufR)[i] = (SAMP)outr;\n\n\t\tSAVE_ALL_CHANNELS\n\n#ifdef USE_MAME_TIMERS\n\t\t/* ASG 980324 - handled by real timers now */\n#else\n\t\t/* calculate timer A */\n\t\tif (PSG->tim_A)\n\t\t{\n\t\t\tPSG->tim_A_val -= ( 1 << TIMER_SH );\n\t\t\tif (PSG->tim_A_val <= 0)\n\t\t\t{\n\t\t\t\tPSG->tim_A_val += PSG->tim_A_tab[ PSG->timer_A_index ];\n\t\t\t\tif (PSG->irq_enable & 0x04)\n\t\t\t\t{\n\t\t\t\t\tint oldstate = PSG->status & 3;\n\t\t\t\t\tPSG->status |= 1;\n\t\t\t\t\t//if ((!oldstate) && (PSG->irqhandler)) (*PSG->irqhandler)(chip->device, 1);\n\t\t\t\t}\n\t\t\t\tif (PSG->irq_enable & 0x80)\n\t\t\t\t\tPSG->csm_req = 2;\t/* request KEY ON / KEY OFF sequence */\n\t\t\t}\n\t\t}\n#endif\n\t\tadvance();\n\t}\n}\n\n/*void ym2151_set_irq_handler(void *chip, void(*handler)(int irq))\n{\n\tYM2151 *PSG = (YM2151 *)chip;\n\tPSG->irqhandler = handler;\n}\n\nvoid ym2151_set_port_write_handler(void *chip, write8_device_func handler)\n{\n\tYM2151 *PSG = (YM2151 *)chip;\n\tPSG->porthandler = handler;\n}*/\n\nvoid ym2151_set_mutemask(void *chip, UINT32 MuteMask)\n{\n\tYM2151 *PSG = (YM2151 *)chip;\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 8; CurChn ++)\n\t\tPSG->Muted[CurChn] = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n"
  },
  {
    "path": "VGMPlay/chips/ym2151.h",
    "content": "/*\n** File: ym2151.h - header file for software implementation of YM2151\n**                                            FM Operator Type-M(OPM)\n**\n** (c) 1997-2002 Jarek Burczynski (s0246@poczta.onet.pl, bujar@mame.net)\n** Some of the optimizing ideas by Tatsuyuki Satoh\n**\n** Version 2.150 final beta May, 11th 2002\n**\n**\n** I would like to thank following people for making this project possible:\n**\n** Beauty Planets - for making a lot of real YM2151 samples and providing\n** additional informations about the chip. Also for the time spent making\n** the samples and the speed of replying to my endless requests.\n**\n** Shigeharu Isoda - for general help, for taking time to scan his YM2151\n** Japanese Manual first of all, and answering MANY of my questions.\n**\n** Nao - for giving me some info about YM2151 and pointing me to Shigeharu.\n** Also for creating fmemu (which I still use to test the emulator).\n**\n** Aaron Giles and Chris Hardy - they made some samples of one of my favourite\n** arcade games so I could compare it to my emulator.\n**\n** Bryan McPhail and Tim (powerjaw) - for making some samples.\n**\n** Ishmair - for the datasheet and motivation.\n*/\n\n#pragma once\n\n\n/* 16- and 8-bit samples (signed) are supported*/\n#define SAMPLE_BITS 16\n\ntypedef stream_sample_t SAMP;\n/*\n#if (SAMPLE_BITS==16)\n    typedef INT16 SAMP;\n#endif\n#if (SAMPLE_BITS==8)\n    typedef signed char SAMP;\n#endif\n*/\n\n/*\n** Initialize YM2151 emulator(s).\n**\n** 'num' is the number of virtual YM2151's to allocate\n** 'clock' is the chip clock in Hz\n** 'rate' is sampling rate\n*/\nvoid *ym2151_init(int clock, int rate);\n\n/* shutdown the YM2151 emulators*/\nvoid ym2151_shutdown(void *chip);\n\n/* reset all chip registers for YM2151 number 'num'*/\nvoid ym2151_reset_chip(void *chip);\n\n/*\n** Generate samples for one of the YM2151's\n**\n** 'num' is the number of virtual YM2151\n** '**buffers' is table of pointers to the buffers: left and right\n** 'length' is the number of samples that should be generated\n*/\nvoid ym2151_update_one(void *chip, SAMP **buffers, int length);\n\n/* write 'v' to register 'r' on YM2151 chip number 'n'*/\nvoid ym2151_write_reg(void *chip, int r, int v);\n\n/* read status register on YM2151 chip number 'n'*/\nint ym2151_read_status(void *chip);\n\n/* set interrupt handler on YM2151 chip number 'n'*/\n//void ym2151_set_irq_handler(void *chip, void (*handler)(int irq));\n\n/* set port write handler on YM2151 chip number 'n'*/\n//void ym2151_set_port_write_handler(void *chip, write8_device_func handler);\n\n/* refresh chip when load state */\n//STATE_POSTLOAD( ym2151_postload );\nvoid ym2151_postload(void *param);\n\nvoid ym2151_set_mutemask(void *chip, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/chips/ym2413.c",
    "content": "/*\n**\n** File: ym2413.c - software implementation of YM2413\n**                  FM sound generator type OPLL\n**\n** Copyright Jarek Burczynski\n**\n** Version 1.0\n**\n\n   Features as listed in LSI-212413A2 data sheet:\n    1. FM Sound Generator for real sound creation.\n    2. Two Selectable modes: 9 simultaneous sounds or 6 melody sounds plus 5 rhythm sounds\n       (different tones can be used together in either case).\n    3. Built-in Instruments data (15 melody tones, 5 rhythm tones, \"CAPTAIN and TELETEXT applicalbe tones).\n    4. Built-in DA Converter.\n    5. Built-in Quartz Oscillator.\n    6. Built-in Vibrato Oscillator/AM Oscillator\n    7. TTL Compatible Input.\n    8. Si-Gate NMOS LSI\n    9. A single 5V power source.\n\nto do:\n\n- make sure of the sinus amplitude bits\n\n- make sure of the EG resolution bits (looks like the biggest\n  modulation index generated by the modulator is 123, 124 = no modulation)\n- find proper algorithm for attack phase of EG\n\n- tune up instruments ROM\n\n- support sample replay in test mode (it is NOT as simple as setting bit 0\n  in register 0x0f and using register 0x10 for sample data).\n  Which games use this feature ?\n\n\n*/\n\n#include <stdio.h>\n#include <math.h>\n#include \"mamedef.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n//#include \"sndintrf.h\"\n#include \"ym2413.h\"\n\n/* output final shift */\n#if (SAMPLE_BITS==16)\n\t#define FINAL_SH\t(0)\n\t#define MAXOUT\t\t(+32767)\n\t#define MINOUT\t\t(-32768)\n#else\n\t#define FINAL_SH\t(8)\n\t#define MAXOUT\t\t(+127)\n\t#define MINOUT\t\t(-128)\n#endif\n\n\n#define FREQ_SH\t\t\t16  /* 16.16 fixed point (frequency calculations) */\n#define EG_SH\t\t\t16  /* 16.16 fixed point (EG timing)              */\n#define LFO_SH\t\t\t24  /*  8.24 fixed point (LFO calculations)       */\n\n#define FREQ_MASK\t\t((1<<FREQ_SH)-1)\n\n/* envelope output entries */\n#define ENV_BITS\t\t10\n#define ENV_LEN\t\t\t(1<<ENV_BITS)\n#define ENV_STEP\t\t(128.0/ENV_LEN)\n\n#define MAX_ATT_INDEX\t((1<<(ENV_BITS-2))-1) /*255*/\n#define MIN_ATT_INDEX\t(0)\n\n/* sinwave entries */\n#define SIN_BITS\t\t10\n#define SIN_LEN\t\t\t(1<<SIN_BITS)\n#define SIN_MASK\t\t(SIN_LEN-1)\n\n#define TL_RES_LEN\t\t(256)\t/* 8 bits addressing (real chip) */\n\n\n\n/* register number to channel number , slot offset */\n#define SLOT1 0\n#define SLOT2 1\n\n/* Envelope Generator phases */\n\n#define EG_DMP\t\t\t5\n#define EG_ATT\t\t\t4\n#define EG_DEC\t\t\t3\n#define EG_SUS\t\t\t2\n#define EG_REL\t\t\t1\n#define EG_OFF\t\t\t0\n\n\n/* save output as raw 16-bit sample */\n\n//#define SAVE_SAMPLE\n\n#ifdef SAVE_SAMPLE\n#include <stdio.h>\n\nINLINE signed int acc_calc(signed int value)\n{\n\tif (value>=0)\n\t{\n\t\tif (value < 0x0200)\n\t\t\treturn (value & ~0);\n\t\tif (value < 0x0400)\n\t\t\treturn (value & ~1);\n\t\tif (value < 0x0800)\n\t\t\treturn (value & ~3);\n\t\tif (value < 0x1000)\n\t\t\treturn (value & ~7);\n\t\tif (value < 0x2000)\n\t\t\treturn (value & ~15);\n\t\tif (value < 0x4000)\n\t\t\treturn (value & ~31);\n\t\treturn (value & ~63);\n\t}\n\t/*else value < 0*/\n\tif (value > -0x0200)\n\t\treturn (~abs(value) & ~0);\n\tif (value > -0x0400)\n\t\treturn (~abs(value) & ~1);\n\tif (value > -0x0800)\n\t\treturn (~abs(value) & ~3);\n\tif (value > -0x1000)\n\t\treturn (~abs(value) & ~7);\n\tif (value > -0x2000)\n\t\treturn (~abs(value) & ~15);\n\tif (value > -0x4000)\n\t\treturn (~abs(value) & ~31);\n\treturn (~abs(value) & ~63);\n}\n\n\nstatic FILE *sample[1];\n\t#if 0\t/*save to MONO file */\n\t\t#define SAVE_ALL_CHANNELS \\\n\t\t{\tsigned int pom = acc_calc(mo); \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t}\n\t#else\t/*save to STEREO file */\n\t\t#define SAVE_ALL_CHANNELS \\\n\t\t{\tsigned int pom = mo; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t\tpom = ro; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t}\n\t\t#define SAVE_SEPARATE_CHANNEL(j) \\\n\t\t{\tsigned int pom = outchan; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t\tpom = chip->instvol_r[j]>>4; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t}\n\t#endif\n#endif\n\n//#define LOG_CYM_FILE 0\n//static FILE * cymfile = NULL;\n\n\n\n\ntypedef struct{\n\tUINT32\tar;\t\t\t/* attack rate: AR<<2           */\n\tUINT32\tdr;\t\t\t/* decay rate:  DR<<2           */\n\tUINT32\trr;\t\t\t/* release rate:RR<<2           */\n\tUINT8\tKSR;\t\t/* key scale rate               */\n\tUINT8\tksl;\t\t/* keyscale level               */\n\tUINT8\tksr;\t\t/* key scale rate: kcode>>KSR   */\n\tUINT8\tmul;\t\t/* multiple: mul_tab[ML]        */\n\n\t/* Phase Generator */\n\tUINT32\tphase;\t\t/* frequency counter            */\n\tUINT32\tfreq;\t\t/* frequency counter step       */\n\tUINT8   fb_shift;\t/* feedback shift value         */\n\tINT32   op1_out[2];\t/* slot1 output for feedback    */\n\n\t/* Envelope Generator */\n\tUINT8\teg_type;\t/* percussive/nonpercussive mode*/\n\tUINT8\tstate;\t\t/* phase type                   */\n\tUINT32\tTL;\t\t\t/* total level: TL << 2         */\n\tINT32\tTLL;\t\t/* adjusted now TL              */\n\tINT32\tvolume;\t\t/* envelope counter             */\n\tUINT32\tsl;\t\t\t/* sustain level: sl_tab[SL]    */\n\n\tUINT8\teg_sh_dp;\t/* (dump state)                 */\n\tUINT8\teg_sel_dp;\t/* (dump state)                 */\n\tUINT8\teg_sh_ar;\t/* (attack state)               */\n\tUINT8\teg_sel_ar;\t/* (attack state)               */\n\tUINT8\teg_sh_dr;\t/* (decay state)                */\n\tUINT8\teg_sel_dr;\t/* (decay state)                */\n\tUINT8\teg_sh_rr;\t/* (release state for non-perc.)*/\n\tUINT8\teg_sel_rr;\t/* (release state for non-perc.)*/\n\tUINT8\teg_sh_rs;\t/* (release state for perc.mode)*/\n\tUINT8\teg_sel_rs;\t/* (release state for perc.mode)*/\n\n\tUINT32\tkey;\t\t/* 0 = KEY OFF, >0 = KEY ON     */\n\n\t/* LFO */\n\tUINT32\tAMmask;\t\t/* LFO Amplitude Modulation enable mask */\n\tUINT8\tvib;\t\t/* LFO Phase Modulation enable flag (active high)*/\n\n\t/* waveform select */\n\tunsigned int wavetable;\n} OPLL_SLOT;\n\ntypedef struct{\n\tOPLL_SLOT SLOT[2];\n\t/* phase generator state */\n\tUINT32  block_fnum;\t/* block+fnum                   */\n\tUINT32  fc;\t\t\t/* Freq. freqement base         */\n\tUINT32  ksl_base;\t/* KeyScaleLevel Base step      */\n\tUINT8   kcode;\t\t/* key code (for key scaling)   */\n\tUINT8   sus;\t\t/* sus on/off (release speed in percussive mode)*/\n\tUINT8   Muted;\n} OPLL_CH;\n\n/* chip state */\ntypedef struct {\n\tOPLL_CH\tP_CH[9];\t\t\t\t/* OPLL chips have 9 channels*/\n\tUINT8\tinstvol_r[9];\t\t\t/* instrument/volume (or volume/volume in percussive mode)*/\n\tUINT8\tMuteSpc[5];\t\t\t\t/* Mute Special: 5 Rhythm */\n\n\tUINT32\teg_cnt;\t\t\t\t\t/* global envelope generator counter    */\n\tUINT32\teg_timer;\t\t\t\t/* global envelope generator counter works at frequency = chipclock/72 */\n\tUINT32\teg_timer_add;\t\t\t/* step of eg_timer                     */\n\tUINT32\teg_timer_overflow;\t\t/* envelope generator timer overlfows every 1 sample (on real chip) */\n\n\tUINT8\trhythm;\t\t\t\t\t/* Rhythm mode                  */\n\n\t/* LFO */\n\tUINT32\tLFO_AM;\n\tINT32\tLFO_PM;\n\tUINT32\tlfo_am_cnt;\n\tUINT32\tlfo_am_inc;\n\tUINT32\tlfo_pm_cnt;\n\tUINT32\tlfo_pm_inc;\n\n\tUINT32\tnoise_rng;\t\t\t\t/* 23 bit noise shift register  */\n\tUINT32\tnoise_p;\t\t\t\t/* current noise 'phase'        */\n\tUINT32\tnoise_f;\t\t\t\t/* current noise period         */\n\n\n/* instrument settings */\n/*\n    0-user instrument\n    1-15 - fixed instruments\n    16 -bass drum settings\n    17,18 - other percussion instruments\n*/\n\tUINT8 inst_tab[19][8];\n\n\t/* external event callback handlers */\n\tOPLL_UPDATEHANDLER UpdateHandler; /* stream update handler      */\n\tvoid * UpdateParam;\t\t\t\t/* stream update parameter      */\n\n\tUINT32\tfn_tab[1024];\t\t\t/* fnumber->increment counter   */\n\n\tUINT8 address;\t\t\t\t\t/* address register             */\n\tUINT8 status;\t\t\t\t\t/* status flag                  */\n\n\tUINT8 VRC7_Mode;\n\tint clock;\t\t\t\t\t\t/* master clock  (Hz)           */\n\tint rate;\t\t\t\t\t\t/* sampling rate (Hz)           */\n\tdouble freqbase;\t\t\t\t/* frequency base               */\n\n\tsigned int output[2];\n\tsigned int outchan;\n} YM2413;\n\n/* key scale level */\n/* table is 3dB/octave, DV converts this into 6dB/octave */\n/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */\n#define DV (0.1875/1.0)\nstatic const UINT32 ksl_tab[8*16]=\n{\n\t/* OCT 0 */\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t/* OCT 1 */\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,\n\t 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,\n\t/* OCT 2 */\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,\n\t 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,\n\t 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,\n\t/* OCT 3 */\n\t 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,\n\t 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,\n\t 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,\n\t 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,\n\t/* OCT 4 */\n\t 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,\n\t 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,\n\t 9.000/DV, 9.750/DV,10.125/DV,10.500/DV,\n\t10.875/DV,11.250/DV,11.625/DV,12.000/DV,\n\t/* OCT 5 */\n\t 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,\n\t 9.000/DV,10.125/DV,10.875/DV,11.625/DV,\n\t12.000/DV,12.750/DV,13.125/DV,13.500/DV,\n\t13.875/DV,14.250/DV,14.625/DV,15.000/DV,\n\t/* OCT 6 */\n\t 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,\n\t12.000/DV,13.125/DV,13.875/DV,14.625/DV,\n\t15.000/DV,15.750/DV,16.125/DV,16.500/DV,\n\t16.875/DV,17.250/DV,17.625/DV,18.000/DV,\n\t/* OCT 7 */\n\t 0.000/DV, 9.000/DV,12.000/DV,13.875/DV,\n\t15.000/DV,16.125/DV,16.875/DV,17.625/DV,\n\t18.000/DV,18.750/DV,19.125/DV,19.500/DV,\n\t19.875/DV,20.250/DV,20.625/DV,21.000/DV\n};\n#undef DV\n\n/* 0 / 1.5 / 3.0 / 6.0 dB/OCT, confirmed on a real YM2413 (the application manual is incorrect) */\nstatic const UINT32 ksl_shift[4] = { 31, 2, 1, 0 };\n\n\n/* sustain level table (3dB per step) */\n/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,45 (dB)*/\n#define SC(db) (UINT32) ( db * (1.0/ENV_STEP) )\nstatic const UINT32 sl_tab[16]={\n SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),\n SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(15)\n};\n#undef SC\n\n\n#define RATE_STEPS (8)\nstatic const unsigned char eg_inc[15*RATE_STEPS]={\n\n/*cycle:0 1  2 3  4 5  6 7*/\n\n/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */\n/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */\n/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */\n/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */\n\n/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */\n/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */\n/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */\n/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */\n\n/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */\n/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */\n/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */\n/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */\n\n/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */\n/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */\n/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */\n};\n\n\n#define O(a) (a*RATE_STEPS)\n\n/*note that there is no O(13) in this table - it's directly in the code */\nstatic const unsigned char eg_rate_select[16+64+16]={\t/* Envelope Generator rates (16 + 64 rates + 16 RKS) */\n/* 16 infinite time rates */\nO(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),\nO(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),\n\n/* rates 00-12 */\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\n\n/* rate 13 */\nO( 4),O( 5),O( 6),O( 7),\n\n/* rate 14 */\nO( 8),O( 9),O(10),O(11),\n\n/* rate 15 */\nO(12),O(12),O(12),O(12),\n\n/* 16 dummy rates (same as 15 3) */\nO(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),\nO(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),\n\n};\n#undef O\n\n/*rate  0,    1,    2,    3,    4,   5,   6,   7,  8,  9, 10, 11, 12, 13, 14, 15 */\n/*shift 13,   12,   11,   10,   9,   8,   7,   6,  5,  4,  3,  2,  1,  0,  0,  0 */\n/*mask  8191, 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3,  1,  0,  0,  0 */\n\n#define O(a) (a*1)\nstatic const unsigned char eg_rate_shift[16+64+16]={\t/* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */\n/* 16 infinite time rates */\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\n\n/* rates 00-12 */\nO(13),O(13),O(13),O(13),\nO(12),O(12),O(12),O(12),\nO(11),O(11),O(11),O(11),\nO(10),O(10),O(10),O(10),\nO( 9),O( 9),O( 9),O( 9),\nO( 8),O( 8),O( 8),O( 8),\nO( 7),O( 7),O( 7),O( 7),\nO( 6),O( 6),O( 6),O( 6),\nO( 5),O( 5),O( 5),O( 5),\nO( 4),O( 4),O( 4),O( 4),\nO( 3),O( 3),O( 3),O( 3),\nO( 2),O( 2),O( 2),O( 2),\nO( 1),O( 1),O( 1),O( 1),\n\n/* rate 13 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 14 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 15 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* 16 dummy rates (same as 15 3) */\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\n\n};\n#undef O\n\n\n/* multiple table */\n#define ML 2\nstatic const UINT8 mul_tab[16]= {\n/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */\n   0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,\n   8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML\n};\n#undef ML\n\n/*  TL_TAB_LEN is calculated as:\n*   11 - sinus amplitude bits     (Y axis)\n*   2  - sinus sign bit           (Y axis)\n*   TL_RES_LEN - sinus resolution (X axis)\n*/\n#define TL_TAB_LEN (11*2*TL_RES_LEN)\nstatic signed int tl_tab[TL_TAB_LEN];\n\n#define ENV_QUIET\t\t(TL_TAB_LEN>>5)\n\n/* sin waveform table in 'decibel' scale */\n/* two waveforms on OPLL type chips */\nstatic unsigned int sin_tab[SIN_LEN * 2];\n\n\n/* LFO Amplitude Modulation table (verified on real YM3812)\n   27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples\n\n   Length: 210 elements.\n\n    Each of the elements has to be repeated\n    exactly 64 times (on 64 consecutive samples).\n    The whole table takes: 64 * 210 = 13440 samples.\n\nWe use data>>1, until we find what it really is on real chip...\n\n*/\n\n#define LFO_AM_TAB_ELEMENTS 210\n\nstatic const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = {\n0,0,0,0,0,0,0,\n1,1,1,1,\n2,2,2,2,\n3,3,3,3,\n4,4,4,4,\n5,5,5,5,\n6,6,6,6,\n7,7,7,7,\n8,8,8,8,\n9,9,9,9,\n10,10,10,10,\n11,11,11,11,\n12,12,12,12,\n13,13,13,13,\n14,14,14,14,\n15,15,15,15,\n16,16,16,16,\n17,17,17,17,\n18,18,18,18,\n19,19,19,19,\n20,20,20,20,\n21,21,21,21,\n22,22,22,22,\n23,23,23,23,\n24,24,24,24,\n25,25,25,25,\n26,26,26,\n25,25,25,25,\n24,24,24,24,\n23,23,23,23,\n22,22,22,22,\n21,21,21,21,\n20,20,20,20,\n19,19,19,19,\n18,18,18,18,\n17,17,17,17,\n16,16,16,16,\n15,15,15,15,\n14,14,14,14,\n13,13,13,13,\n12,12,12,12,\n11,11,11,11,\n10,10,10,10,\n9,9,9,9,\n8,8,8,8,\n7,7,7,7,\n6,6,6,6,\n5,5,5,5,\n4,4,4,4,\n3,3,3,3,\n2,2,2,2,\n1,1,1,1\n};\n\n/* LFO Phase Modulation table (verified on real YM2413) */\nstatic const INT8 lfo_pm_table[8*8] = {\n\n/* FNUM2/FNUM = 0 00xxxxxx (0x0000) */\n0, 0, 0, 0, 0, 0, 0, 0,\n\n/* FNUM2/FNUM = 0 01xxxxxx (0x0040) */\n1, 0, 0, 0,-1, 0, 0, 0,\n\n/* FNUM2/FNUM = 0 10xxxxxx (0x0080) */\n2, 1, 0,-1,-2,-1, 0, 1,\n\n/* FNUM2/FNUM = 0 11xxxxxx (0x00C0) */\n3, 1, 0,-1,-3,-1, 0, 1,\n\n/* FNUM2/FNUM = 1 00xxxxxx (0x0100) */\n4, 2, 0,-2,-4,-2, 0, 2,\n\n/* FNUM2/FNUM = 1 01xxxxxx (0x0140) */\n5, 2, 0,-2,-5,-2, 0, 2,\n\n/* FNUM2/FNUM = 1 10xxxxxx (0x0180) */\n6, 3, 0,-3,-6,-3, 0, 3,\n\n/* FNUM2/FNUM = 1 11xxxxxx (0x01C0) */\n7, 3, 0,-3,-7,-3, 0, 3,\n};\n\n\n\n\n\n\n/* This is not 100% perfect yet but very close */\n/*\n - multi parameters are 100% correct (instruments and drums)\n - LFO PM and AM enable are 100% correct\n - waveform DC and DM select are 100% correct\n*/\n\nstatic const unsigned char table[19][8] = {\n/* MULT  MULT modTL DcDmFb AR/DR AR/DR SL/RR SL/RR */\n/*   0     1     2     3     4     5     6    7    */\n  {0x49, 0x4c, 0x4c, 0x12, 0x00, 0x00, 0x00, 0x00 },\t//0\n\n  {0x61, 0x61, 0x1e, 0x17, 0xf0, 0x78, 0x00, 0x17 },\t//1\n  {0x13, 0x41, 0x1e, 0x0d, 0xd7, 0xf7, 0x13, 0x13 },\t//2\n  {0x13, 0x01, 0x99, 0x04, 0xf2, 0xf4, 0x11, 0x23 },\t//3\n  {0x21, 0x61, 0x1b, 0x07, 0xaf, 0x64, 0x40, 0x27 },\t//4\n\n//{0x22, 0x21, 0x1e, 0x09, 0xf0, 0x76, 0x08, 0x28 },    //5\n  {0x22, 0x21, 0x1e, 0x06, 0xf0, 0x75, 0x08, 0x18 },\t//5\n\n//{0x31, 0x22, 0x16, 0x09, 0x90, 0x7f, 0x00, 0x08 },    //6\n  {0x31, 0x22, 0x16, 0x05, 0x90, 0x71, 0x00, 0x13 },\t//6\n\n  {0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x10, 0x17 },\t//7\n  {0x23, 0x21, 0x2d, 0x16, 0xc0, 0x70, 0x07, 0x07 },\t//8\n  {0x61, 0x61, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 },\t//9\n\n//{0x61, 0x61, 0x0c, 0x08, 0x85, 0xa0, 0x79, 0x07 },    //A\n  {0x61, 0x61, 0x0c, 0x18, 0x85, 0xf0, 0x70, 0x07 },\t//A\n\n  {0x23, 0x01, 0x07, 0x11, 0xf0, 0xa4, 0x00, 0x22 },\t//B\n  {0x97, 0xc1, 0x24, 0x07, 0xff, 0xf8, 0x22, 0x12 },\t//C\n\n//{0x61, 0x10, 0x0c, 0x08, 0xf2, 0xc4, 0x40, 0xc8 },    //D\n  {0x61, 0x10, 0x0c, 0x05, 0xf2, 0xf4, 0x40, 0x44 },\t//D\n\n  {0x01, 0x01, 0x55, 0x03, 0xf3, 0x92, 0xf3, 0xf3 },\t//E\n  {0x61, 0x41, 0x89, 0x03, 0xf1, 0xf4, 0xf0, 0x13 },\t//F\n\n/* drum instruments definitions */\n/* MULTI MULTI modTL  xxx  AR/DR AR/DR SL/RR SL/RR */\n/*   0     1     2     3     4     5     6    7    */\n  {0x01, 0x01, 0x16, 0x00, 0xfd, 0xf8, 0x2f, 0x6d },/* BD(multi verified, modTL verified, mod env - verified(close), carr. env verifed) */\n  {0x01, 0x01, 0x00, 0x00, 0xd8, 0xd8, 0xf9, 0xf8 },/* HH(multi verified), SD(multi not used) */\n  {0x05, 0x01, 0x00, 0x00, 0xf8, 0xba, 0x49, 0x55 },/* TOM(multi,env verified), TOP CYM(multi verified, env verified) */\n};\n\n/* lock level of common table */\nstatic int num_lock = 0;\n\n/* work table */\n#define SLOT7_1 (&chip->P_CH[7].SLOT[SLOT1])\n#define SLOT7_2 (&chip->P_CH[7].SLOT[SLOT2])\n#define SLOT8_1 (&chip->P_CH[8].SLOT[SLOT1])\n#define SLOT8_2 (&chip->P_CH[8].SLOT[SLOT2])\n\n\n/*INLINE int limit( int val, int max, int min ) {\n\tif ( val > max )\n\t\tval = max;\n\telse if ( val < min )\n\t\tval = min;\n\n\treturn val;\n}*/\n\n\n/* advance LFO to next sample */\nINLINE void advance_lfo(YM2413 *chip)\n{\n\t/* LFO */\n\tchip->lfo_am_cnt += chip->lfo_am_inc;\n\tif (chip->lfo_am_cnt >= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH) )\t/* lfo_am_table is 210 elements long */\n\t\tchip->lfo_am_cnt -= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH);\n\n\tchip->LFO_AM = lfo_am_table[ chip->lfo_am_cnt >> LFO_SH ] >> 1;\n\n\tchip->lfo_pm_cnt += chip->lfo_pm_inc;\n\tchip->LFO_PM = (chip->lfo_pm_cnt>>LFO_SH) & 7;\n}\n\n/* advance to next sample */\nINLINE void advance(YM2413 *chip)\n{\n\tOPLL_CH *CH;\n\tOPLL_SLOT *op;\n\tunsigned int i;\n\n\t/* Envelope Generator */\n\tchip->eg_timer += chip->eg_timer_add;\n\n\twhile (chip->eg_timer >= chip->eg_timer_overflow)\n\t{\n\t\tchip->eg_timer -= chip->eg_timer_overflow;\n\n\t\tchip->eg_cnt++;\n\n\t\tfor (i=0; i<9*2; i++)\n\t\t{\n\t\t\tCH  = &chip->P_CH[i/2];\n\n\t\t\top  = &CH->SLOT[i&1];\n\n\t\t\tswitch(op->state)\n\t\t\t{\n\n\t\t\tcase EG_DMP:\t\t/* dump phase */\n\t\t\t/*dump phase is performed by both operators in each channel*/\n\t\t\t/*when CARRIER envelope gets down to zero level,\n            **  phases in BOTH opearators are reset (at the same time ?)\n            */\n\t\t\t\tif ( !(chip->eg_cnt & ((1<<op->eg_sh_dp)-1) ) )\n\t\t\t\t{\n\t\t\t\t\top->volume += eg_inc[op->eg_sel_dp + ((chip->eg_cnt>>op->eg_sh_dp)&7)];\n\n\t\t\t\t\tif ( op->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t{\n\t\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t\t\top->state = EG_ATT;\n\t\t\t\t\t\t/* restart Phase Generator  */\n\t\t\t\t\t\top->phase = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_ATT:\t\t/* attack phase */\n\t\t\t\tif ( !(chip->eg_cnt & ((1<<op->eg_sh_ar)-1) ) )\n\t\t\t\t{\n\t\t\t\t\top->volume += (~op->volume *\n\t                        \t\t           (eg_inc[op->eg_sel_ar + ((chip->eg_cnt>>op->eg_sh_ar)&7)])\n        \t\t\t                          ) >>2;\n\n\t\t\t\t\tif (op->volume <= MIN_ATT_INDEX)\n\t\t\t\t\t{\n\t\t\t\t\t\top->volume = MIN_ATT_INDEX;\n\t\t\t\t\t\top->state = EG_DEC;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_DEC:\t/* decay phase */\n\t\t\t\tif ( !(chip->eg_cnt & ((1<<op->eg_sh_dr)-1) ) )\n\t\t\t\t{\n\t\t\t\t\top->volume += eg_inc[op->eg_sel_dr + ((chip->eg_cnt>>op->eg_sh_dr)&7)];\n\n\t\t\t\t\tif ( op->volume >= op->sl )\n\t\t\t\t\t\top->state = EG_SUS;\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_SUS:\t/* sustain phase */\n\t\t\t\t/* this is important behaviour:\n                one can change percusive/non-percussive modes on the fly and\n                the chip will remain in sustain phase - verified on real YM3812 */\n\n\t\t\t\tif(op->eg_type)\t\t/* non-percussive mode (sustained tone) */\n\t\t\t\t{\n\t\t\t\t\t\t\t\t\t/* do nothing */\n\t\t\t\t}\n\t\t\t\telse\t\t\t\t/* percussive mode */\n\t\t\t\t{\n\t\t\t\t\t/* during sustain phase chip adds Release Rate (in percussive mode) */\n\t\t\t\t\tif ( !(chip->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\n\t\t\t\t\t{\n\t\t\t\t\t\top->volume += eg_inc[op->eg_sel_rr + ((chip->eg_cnt>>op->eg_sh_rr)&7)];\n\n\t\t\t\t\t\tif ( op->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t\t}\n\t\t\t\t\t/* else do nothing in sustain phase */\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_REL:\t/* release phase */\n\t\t\t/* exclude modulators in melody channels from performing anything in this mode*/\n\t\t\t/* allowed are only carriers in melody mode and rhythm slots in rhythm mode */\n\n\t\t\t/*This table shows which operators and on what conditions are allowed to perform EG_REL:\n            (a) - always perform EG_REL\n            (n) - never perform EG_REL\n            (r) - perform EG_REL in Rhythm mode ONLY\n                0: 0 (n),  1 (a)\n                1: 2 (n),  3 (a)\n                2: 4 (n),  5 (a)\n                3: 6 (n),  7 (a)\n                4: 8 (n),  9 (a)\n                5: 10(n),  11(a)\n                6: 12(r),  13(a)\n                7: 14(r),  15(a)\n                8: 16(r),  17(a)\n            */\n\t\t\t\tif ( (i&1) || ((chip->rhythm&0x20) && (i>=12)) )/* exclude modulators */\n\t\t\t\t{\n\t\t\t\t\tif(op->eg_type)\t\t/* non-percussive mode (sustained tone) */\n\t\t\t\t\t/*this is correct: use RR when SUS = OFF*/\n\t\t\t\t\t/*and use RS when SUS = ON*/\n\t\t\t\t\t{\n\t\t\t\t\t\tif (CH->sus)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( !(chip->eg_cnt & ((1<<op->eg_sh_rs)-1) ) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\top->volume += eg_inc[op->eg_sel_rs + ((chip->eg_cnt>>op->eg_sh_rs)&7)];\n\t\t\t\t\t\t\t\tif ( op->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t\t\t\t\t\top->state = EG_OFF;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( !(chip->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\top->volume += eg_inc[op->eg_sel_rr + ((chip->eg_cnt>>op->eg_sh_rr)&7)];\n\t\t\t\t\t\t\t\tif ( op->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t\t\t\t\t\top->state = EG_OFF;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\t\t\t\t/* percussive mode */\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( !(chip->eg_cnt & ((1<<op->eg_sh_rs)-1) ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\top->volume += eg_inc[op->eg_sel_rs + ((chip->eg_cnt>>op->eg_sh_rs)&7)];\n\t\t\t\t\t\t\tif ( op->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t\t\t\t\top->state = EG_OFF;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (i=0; i<9*2; i++)\n\t{\n\t\tCH  = &chip->P_CH[i/2];\n\t\top  = &CH->SLOT[i&1];\n\n\t\t/* Phase Generator */\n\t\tif(op->vib)\n\t\t{\n\t\t\tUINT8 block;\n\n\t\t\tunsigned int fnum_lfo   = 8*((CH->block_fnum&0x01c0) >> 6);\n\t\t\tunsigned int block_fnum = CH->block_fnum * 2;\n\t\t\tsigned int lfo_fn_table_index_offset = lfo_pm_table[chip->LFO_PM + fnum_lfo ];\n\n\t\t\tif (lfo_fn_table_index_offset)\t/* LFO phase modulation active */\n\t\t\t{\n\t\t\t\tblock_fnum += lfo_fn_table_index_offset;\n\t\t\t\tblock = (block_fnum&0x1c00) >> 10;\n\t\t\t\top->phase += (chip->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul;\n\t\t\t}\n\t\t\telse\t/* LFO phase modulation  = zero */\n\t\t\t{\n\t\t\t\top->phase += op->freq;\n\t\t\t}\n\t\t}\n\t\telse\t/* LFO phase modulation disabled for this operator */\n\t\t{\n\t\t\top->phase += op->freq;\n\t\t}\n\t}\n\n\t/*  The Noise Generator of the YM3812 is 23-bit shift register.\n    *   Period is equal to 2^23-2 samples.\n    *   Register works at sampling frequency of the chip, so output\n    *   can change on every sample.\n    *\n    *   Output of the register and input to the bit 22 is:\n    *   bit0 XOR bit14 XOR bit15 XOR bit22\n    *\n    *   Simply use bit 22 as the noise output.\n    */\n\n\tchip->noise_p += chip->noise_f;\n\ti = chip->noise_p >> FREQ_SH;\t\t/* number of events (shifts of the shift register) */\n\tchip->noise_p &= FREQ_MASK;\n\twhile (i)\n\t{\n\t\t/*\n        UINT32 j;\n        j = ( (chip->noise_rng) ^ (chip->noise_rng>>14) ^ (chip->noise_rng>>15) ^ (chip->noise_rng>>22) ) & 1;\n        chip->noise_rng = (j<<22) | (chip->noise_rng>>1);\n        */\n\n\t\t/*\n            Instead of doing all the logic operations above, we\n            use a trick here (and use bit 0 as the noise output).\n            The difference is only that the noise bit changes one\n            step ahead. This doesn't matter since we don't know\n            what is real state of the noise_rng after the reset.\n        */\n\n\t\tif (chip->noise_rng & 1) chip->noise_rng ^= 0x800302;\n\t\tchip->noise_rng >>= 1;\n\n\t\ti--;\n\t}\n}\n\n\nINLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)\n{\n\tUINT32 p;\n\n\tp = (env<<5) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<17))) >> FREQ_SH ) & SIN_MASK) ];\n\n\tif (p >= TL_TAB_LEN)\n\t\treturn 0;\n\treturn tl_tab[p];\n}\n\nINLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)\n{\n\tUINT32 p;\n\tINT32  i;\n\n\ti = (phase & ~FREQ_MASK) + pm;\n\n/*logerror(\"i=%08x (i>>16)&511=%8i phase=%i [pm=%08x] \",i, (i>>16)&511, phase>>FREQ_SH, pm);*/\n\n\tp = (env<<5) + sin_tab[ wave_tab + ((i>>FREQ_SH) & SIN_MASK)];\n\n/*logerror(\"(p&255=%i p>>8=%i) out= %i\\n\", p&255,p>>8, tl_tab[p&255]>>(p>>8) );*/\n\n\tif (p >= TL_TAB_LEN)\n\t\treturn 0;\n\treturn tl_tab[p];\n}\n\n\n#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (chip->LFO_AM & (OP)->AMmask))\n\n/* calculate output */\nINLINE void chan_calc( YM2413*chip, OPLL_CH *CH )\n{\n\tOPLL_SLOT *SLOT;\n\tunsigned int env;\n\tsigned int out;\n\tsigned int phase_modulation;\t/* phase modulation input (SLOT 2) */\n\n\n\tif (CH->Muted)\n\t\treturn;\n\n  /* SLOT 1 */\n\tSLOT = &CH->SLOT[SLOT1];\n\tenv  = volume_calc(SLOT);\n\tout  = SLOT->op1_out[0] + SLOT->op1_out[1];\n\n\tSLOT->op1_out[0] = SLOT->op1_out[1];\n\tphase_modulation = SLOT->op1_out[0];\n\n\tSLOT->op1_out[1] = 0;\n\n\tif( env < ENV_QUIET )\n\t{\n\t\tif (!SLOT->fb_shift)\n\t\t\tout = 0;\n\t\tSLOT->op1_out[1] = op_calc1(SLOT->phase, env, (out<<SLOT->fb_shift), SLOT->wavetable );\n\t}\n\n\t/* SLOT 2 */\n\n\tchip->outchan=0;\n\n\tSLOT++;\n\tenv = volume_calc(SLOT);\n\tif( env < ENV_QUIET )\n\t{\n\t\tsigned int outp = op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable);\n\t\tchip->output[0] += outp;\n\t\tchip->outchan = outp;\n\t\t//chip->output[0] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable);\n\t}\n}\n\n/*\n    operators used in the rhythm sounds generation process:\n\n    Envelope Generator:\n\nchannel  operator  register number   Bass  High  Snare Tom  Top\n/ slot   number    TL ARDR SLRR Wave Drum  Hat   Drum  Tom  Cymbal\n 6 / 0   12        50  70   90   f0  +\n 6 / 1   15        53  73   93   f3  +\n 7 / 0   13        51  71   91   f1        +\n 7 / 1   16        54  74   94   f4              +\n 8 / 0   14        52  72   92   f2                    +\n 8 / 1   17        55  75   95   f5                          +\n\n    Phase Generator:\n\nchannel  operator  register number   Bass  High  Snare Tom  Top\n/ slot   number    MULTIPLE          Drum  Hat   Drum  Tom  Cymbal\n 6 / 0   12        30                +\n 6 / 1   15        33                +\n 7 / 0   13        31                      +     +           +\n 7 / 1   16        34                -----  n o t  u s e d -----\n 8 / 0   14        32                                  +\n 8 / 1   17        35                      +                 +\n\nchannel  operator  register number   Bass  High  Snare Tom  Top\nnumber   number    BLK/FNUM2 FNUM    Drum  Hat   Drum  Tom  Cymbal\n   6     12,15     B6        A6      +\n\n   7     13,16     B7        A7            +     +           +\n\n   8     14,17     B8        A8            +           +     +\n\n*/\n\n/* calculate rhythm */\n\nINLINE void rhythm_calc( YM2413 *chip, OPLL_CH *CH, unsigned int noise )\n{\n\tOPLL_SLOT *SLOT;\n\tsigned int out;\n\tunsigned int env;\n\tsigned int phase_modulation;\t/* phase modulation input (SLOT 2) */\n\n\n\t/* Bass Drum (verified on real YM3812):\n      - depends on the channel 6 'connect' register:\n          when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out)\n          when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored\n      - output sample always is multiplied by 2\n    */\n\n\n\t/* SLOT 1 */\n\tSLOT = &CH[6].SLOT[SLOT1];\n\tenv = volume_calc(SLOT);\n\n\tout = SLOT->op1_out[0] + SLOT->op1_out[1];\n\tSLOT->op1_out[0] = SLOT->op1_out[1];\n\n\tphase_modulation = SLOT->op1_out[0];\n\n\tSLOT->op1_out[1] = 0;\n\tif( env < ENV_QUIET )\n\t{\n\t\tif (!SLOT->fb_shift)\n\t\t\tout = 0;\n\t\tSLOT->op1_out[1] = op_calc1(SLOT->phase, env, (out<<SLOT->fb_shift), SLOT->wavetable );\n\t}\n\n\t/* SLOT 2 */\n\tSLOT++;\n\tenv = volume_calc(SLOT);\n\tif( env < ENV_QUIET && ! chip->MuteSpc[0] )\n\t\tchip->output[1] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable) * 2;\n\n\n\t/* Phase generation is based on: */\n\t// HH  (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases)\n\t// SD  (16) channel 7->slot 1\n\t// TOM (14) channel 8->slot 1\n\t// TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases)\n\n\t/* Envelope generation based on: */\n\t// HH  channel 7->slot1\n\t// SD  channel 7->slot2\n\t// TOM channel 8->slot1\n\t// TOP channel 8->slot2\n\n\n\t/* The following formulas can be well optimized.\n       I leave them in direct form for now (in case I've missed something).\n    */\n\n\t/* High Hat (verified on real YM3812) */\n\tenv = volume_calc(SLOT7_1);\n\tif( env < ENV_QUIET && ! chip->MuteSpc[4] )\n\t{\n\n\t\t/* high hat phase generation:\n            phase = d0 or 234 (based on frequency only)\n            phase = 34 or 2d0 (based on noise)\n        */\n\n\t\t/* base frequency derived from operator 1 in channel 7 */\n\t\tunsigned char bit7 = ((SLOT7_1->phase>>FREQ_SH)>>7)&1;\n\t\tunsigned char bit3 = ((SLOT7_1->phase>>FREQ_SH)>>3)&1;\n\t\tunsigned char bit2 = ((SLOT7_1->phase>>FREQ_SH)>>2)&1;\n\n\t\tunsigned char res1 = (bit2 ^ bit7) | bit3;\n\n\t\t/* when res1 = 0 phase = 0x000 | 0xd0; */\n\t\t/* when res1 = 1 phase = 0x200 | (0xd0>>2); */\n\t\tUINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;\n\n\t\t/* enable gate based on frequency of operator 2 in channel 8 */\n\t\tunsigned char bit5e= ((SLOT8_2->phase>>FREQ_SH)>>5)&1;\n\t\tunsigned char bit3e= ((SLOT8_2->phase>>FREQ_SH)>>3)&1;\n\n\t\tunsigned char res2 = (bit3e | bit5e);\n\n\t\t/* when res2 = 0 pass the phase from calculation above (res1); */\n\t\t/* when res2 = 1 phase = 0x200 | (0xd0>>2); */\n\t\tif (res2)\n\t\t\tphase = (0x200|(0xd0>>2));\n\n\n\t\t/* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */\n\t\t/* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */\n\t\tif (phase&0x200)\n\t\t{\n\t\t\tif (noise)\n\t\t\t\tphase = 0x200|0xd0;\n\t\t}\n\t\telse\n\t\t/* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */\n\t\t/* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */\n\t\t{\n\t\t\tif (noise)\n\t\t\t\tphase = 0xd0>>2;\n\t\t}\n\n\t\tchip->output[1] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1->wavetable) * 2;\n\t}\n\n\t/* Snare Drum (verified on real YM3812) */\n\tenv = volume_calc(SLOT7_2);\n\tif( env < ENV_QUIET && ! chip->MuteSpc[1] )\n\t{\n\t\t/* base frequency derived from operator 1 in channel 7 */\n\t\tunsigned char bit8 = ((SLOT7_1->phase>>FREQ_SH)>>8)&1;\n\n\t\t/* when bit8 = 0 phase = 0x100; */\n\t\t/* when bit8 = 1 phase = 0x200; */\n\t\tUINT32 phase = bit8 ? 0x200 : 0x100;\n\n\t\t/* Noise bit XOR'es phase by 0x100 */\n\t\t/* when noisebit = 0 pass the phase from calculation above */\n\t\t/* when noisebit = 1 phase ^= 0x100; */\n\t\t/* in other words: phase ^= (noisebit<<8); */\n\t\tif (noise)\n\t\t\tphase ^= 0x100;\n\n\t\tchip->output[1] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2->wavetable) * 2;\n\t}\n\n\t/* Tom Tom (verified on real YM3812) */\n\tenv = volume_calc(SLOT8_1);\n\tif( env < ENV_QUIET && ! chip->MuteSpc[2] )\n\t\tchip->output[1] += op_calc(SLOT8_1->phase, env, 0, SLOT8_1->wavetable) * 2;\n\n\t/* Top Cymbal (verified on real YM2413) */\n\tenv = volume_calc(SLOT8_2);\n\tif( env < ENV_QUIET && ! chip->MuteSpc[3] )\n\t{\n\t\t/* base frequency derived from operator 1 in channel 7 */\n\t\tunsigned char bit7 = ((SLOT7_1->phase>>FREQ_SH)>>7)&1;\n\t\tunsigned char bit3 = ((SLOT7_1->phase>>FREQ_SH)>>3)&1;\n\t\tunsigned char bit2 = ((SLOT7_1->phase>>FREQ_SH)>>2)&1;\n\n\t\tunsigned char res1 = (bit2 ^ bit7) | bit3;\n\n\t\t/* when res1 = 0 phase = 0x000 | 0x100; */\n\t\t/* when res1 = 1 phase = 0x200 | 0x100; */\n\t\tUINT32 phase = res1 ? 0x300 : 0x100;\n\n\t\t/* enable gate based on frequency of operator 2 in channel 8 */\n\t\tunsigned char bit5e= ((SLOT8_2->phase>>FREQ_SH)>>5)&1;\n\t\tunsigned char bit3e= ((SLOT8_2->phase>>FREQ_SH)>>3)&1;\n\n\t\tunsigned char res2 = (bit3e | bit5e);\n\t\t/* when res2 = 0 pass the phase from calculation above (res1); */\n\t\t/* when res2 = 1 phase = 0x200 | 0x100; */\n\t\tif (res2)\n\t\t\tphase = 0x300;\n\n\t\tchip->output[1] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2->wavetable) * 2;\n\t}\n\n}\n\n\n/* generic table initialize */\nstatic int init_tables(void)\n{\n\tsigned int i,x;\n\tsigned int n;\n\tdouble o,m;\n\n\n\tfor (x=0; x<TL_RES_LEN; x++)\n\t{\n\t\tm = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);\n\t\tm = floor(m);\n\n\t\t/* we never reach (1<<16) here due to the (x+1) */\n\t\t/* result fits within 16 bits at maximum */\n\n\t\tn = (int)m;\t\t/* 16 bits here */\n\t\tn >>= 4;\t\t/* 12 bits here */\n\t\tif (n&1)\t\t/* round to nearest */\n\t\t\tn = (n>>1)+1;\n\t\telse\n\t\t\tn = n>>1;\n\t\t\t\t\t\t/* 11 bits here (rounded) */\n\t\ttl_tab[ x*2 + 0 ] = n;\n\t\ttl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];\n\n\t\tfor (i=1; i<11; i++)\n\t\t{\n\t\t\ttl_tab[ x*2+0 + i*2*TL_RES_LEN ] =  tl_tab[ x*2+0 ]>>i;\n\t\t\ttl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];\n\t\t}\n\t//#if 0\n\t//\t\tlogerror(\"tl %04i\", x*2);\n\t//\t\tfor (i=0; i<11; i++)\n\t//\t\t\tlogerror(\", [%02i] %5i\", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] );\n\t//\t\tlogerror(\"\\n\");\n\t//#endif*/\n\t}\n\t/*logerror(\"ym2413.c: TL_TAB_LEN = %i elements (%i bytes)\\n\",TL_TAB_LEN, (int)sizeof(tl_tab));*/\n\n\n\tfor (i=0; i<SIN_LEN; i++)\n\t{\n\t\t/* non-standard sinus */\n\t\tm = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */\n\n\t\t/* we never reach zero here due to ((i*2)+1) */\n\n\t\tif (m>0.0)\n\t\t\to = 8*log(1.0/m)/log(2.0);\t/* convert to 'decibels' */\n\t\telse\n\t\t\to = 8*log(-1.0/m)/log(2.0);\t/* convert to 'decibels' */\n\n\t\to = o / (ENV_STEP/4);\n\n\t\tn = (int)(2.0*o);\n\t\tif (n&1)\t\t\t\t\t\t/* round to nearest */\n\t\t\tn = (n>>1)+1;\n\t\telse\n\t\t\tn = n>>1;\n\n\t\t/* waveform 0: standard sinus  */\n\t\tsin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );\n\n\t\t/*logerror(\"ym2413.c: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\\n\", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/\n\n\n\t\t/* waveform 1:  __      __     */\n\t\t/*             /  \\____/  \\____*/\n\t\t/* output only first half of the sinus waveform (positive one) */\n\t\tif (i & (1<<(SIN_BITS-1)) )\n\t\t\tsin_tab[1*SIN_LEN+i] = TL_TAB_LEN;\n\t\telse\n\t\t\tsin_tab[1*SIN_LEN+i] = sin_tab[i];\n\n\t\t/*logerror(\"ym2413.c: sin1[%4i]= %4i (tl_tab value=%5i)\\n\", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] );*/\n\t}\n/*#if 0\n\tlogerror(\"YM2413.C: ENV_QUIET= %08x (*32=%08x)\\n\", ENV_QUIET, ENV_QUIET*32 );\n\tfor (i=0; i<ENV_QUIET; i++)\n\t{\n\t\tlogerror(\"tl_tb[%4x(%4i)]=%8x\\n\", i<<5, i, tl_tab[i<<5] );\n\t}\n#endif*/\n#ifdef SAVE_SAMPLE\n\tsample[0]=fopen(\"sampsum.pcm\",\"wb\");\n#endif\n\n\treturn 1;\n}\n\nstatic void OPLCloseTable( void )\n{\n#ifdef SAVE_SAMPLE\n\tfclose(sample[0]);\n#endif\n}\n\n\n/*static void OPLL_init_save(YM2413 *chip, const device_config *device)\n{\n\tint chnum;\n\n\tstate_save_register_device_item_array(device, 0, chip->instvol_r);\n\tstate_save_register_device_item(device, 0, chip->eg_cnt);\n\tstate_save_register_device_item(device, 0, chip->eg_timer);\n\tstate_save_register_device_item(device, 0, chip->eg_timer_add);\n\tstate_save_register_device_item(device, 0, chip->eg_timer_overflow);\n\tstate_save_register_device_item(device, 0, chip->rhythm);\n\tstate_save_register_device_item(device, 0, chip->lfo_am_cnt);\n\tstate_save_register_device_item(device, 0, chip->lfo_am_inc);\n\tstate_save_register_device_item(device, 0, chip->lfo_pm_cnt);\n\tstate_save_register_device_item(device, 0, chip->lfo_pm_inc);\n\tstate_save_register_device_item(device, 0, chip->noise_rng);\n\tstate_save_register_device_item(device, 0, chip->noise_p);\n\tstate_save_register_device_item(device, 0, chip->noise_f);\n\tstate_save_register_device_item_2d_array(device, 0, chip->inst_tab);\n\tstate_save_register_device_item(device, 0, chip->address);\n\tstate_save_register_device_item(device, 0, chip->status);\n\n\tfor (chnum = 0; chnum < ARRAY_LENGTH(chip->P_CH); chnum++)\n\t{\n\t\tOPLL_CH *ch = &chip->P_CH[chnum];\n\t\tint slotnum;\n\n\t\tstate_save_register_device_item(device, chnum, ch->block_fnum);\n\t\tstate_save_register_device_item(device, chnum, ch->fc);\n\t\tstate_save_register_device_item(device, chnum, ch->ksl_base);\n\t\tstate_save_register_device_item(device, chnum, ch->kcode);\n\t\tstate_save_register_device_item(device, chnum, ch->sus);\n\n\t\tfor (slotnum = 0; slotnum < ARRAY_LENGTH(ch->SLOT); slotnum++)\n\t\t{\n\t\t\tOPLL_SLOT *sl = &ch->SLOT[slotnum];\n\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->ar);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->dr);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->rr);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->KSR);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->ksl);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->ksr);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->mul);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->phase);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->freq);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->fb_shift);\n\t\t\tstate_save_register_device_item_array(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->op1_out);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->eg_type);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->state);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->TL);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->TLL);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->volume);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->sl);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->eg_sh_dp);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->eg_sel_dp);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->eg_sh_ar);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->eg_sel_ar);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->eg_sh_dr);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->eg_sel_dr);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->eg_sh_rr);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->eg_sel_rr);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->eg_sh_rs);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->eg_sel_rs);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->key);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->AMmask);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->vib);\n\t\t\tstate_save_register_device_item(device, chnum * ARRAY_LENGTH(ch->SLOT) + slotnum, sl->wavetable);\n\t\t}\n\t}\n}*/\n\n\n//static void OPLL_initalize(YM2413 *chip, const device_config *device)\nstatic void OPLL_initalize(YM2413 *chip)\n{\n\tint i;\n\n\t//OPLL_init_save(chip, device);\n\n\t/* frequency base */\n\tchip->freqbase  = (chip->rate) ? ((double)chip->clock / 72.0) / chip->rate  : 0;\n/*#if 0\n\tchip->rate = (double)chip->clock / 72.0;\n\tchip->freqbase  = 1.0;\n\tlogerror(\"freqbase=%f\\n\", chip->freqbase);\n#endif*/\n\n\n\n\t/* make fnumber -> increment counter table */\n\tfor( i = 0 ; i < 1024; i++ )\n\t{\n\t\t/* OPLL (YM2413) phase increment counter = 18bit */\n\n\t\tchip->fn_tab[i] = (UINT32)( (double)i * 64 * chip->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */\n/*#if 0\n\t\tlogerror(\"ym2413.c: fn_tab[%4i] = %08x (dec=%8i)\\n\",\n\t\t\t\t i, chip->fn_tab[i]>>6, chip->fn_tab[i]>>6 );\n#endif*/\n\t}\n\n/*#if 0\n\tfor( i=0 ; i < 16 ; i++ )\n\t{\n\t\tlogerror(\"ym2413.c: sl_tab[%i] = %08x\\n\", i, sl_tab[i] );\n\t}\n\tfor( i=0 ; i < 8 ; i++ )\n\t{\n\t\tint j;\n\t\tlogerror(\"ym2413.c: ksl_tab[oct=%2i] =\",i);\n\t\tfor (j=0; j<16; j++)\n\t\t{\n\t\t\tlogerror(\"%08x \", ksl_tab[i*16+j] );\n\t\t}\n\t\tlogerror(\"\\n\");\n\t}\n#endif*/\n\n\tfor(i = 0; i < 9; i ++)\n\t\tchip->P_CH[i].Muted = 0x00;\n\tfor(i = 0; i < 5; i ++)\n\t\tchip->MuteSpc[i] = 0x00;\n\n\n\t/* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */\n\t/* One entry from LFO_AM_TABLE lasts for 64 samples */\n\tchip->lfo_am_inc = (1.0 / 64.0 ) * (1<<LFO_SH) * chip->freqbase;\n\n\t/* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */\n\tchip->lfo_pm_inc = (1.0 / 1024.0) * (1<<LFO_SH) * chip->freqbase;\n\n\t/*logerror (\"chip->lfo_am_inc = %8x ; chip->lfo_pm_inc = %8x\\n\", chip->lfo_am_inc, chip->lfo_pm_inc);*/\n\n\t/* Noise generator: a step takes 1 sample */\n\tchip->noise_f = (1.0 / 1.0) * (1<<FREQ_SH) * chip->freqbase;\n\t/*logerror(\"YM2413init noise_f=%8x\\n\", chip->noise_f);*/\n\n\tchip->eg_timer_add  = (1<<EG_SH)  * chip->freqbase;\n\tchip->eg_timer_overflow = ( 1 ) * (1<<EG_SH);\n\t/*logerror(\"YM2413init eg_timer_add=%8x eg_timer_overflow=%8x\\n\", chip->eg_timer_add, chip->eg_timer_overflow);*/\n}\n\nINLINE void KEY_ON(OPLL_SLOT *SLOT, UINT32 key_set)\n{\n\tif( !SLOT->key )\n\t{\n\t\t/* do NOT restart Phase Generator (verified on real YM2413)*/\n\t\t/* phase -> Dump */\n\t\tSLOT->state = EG_DMP;\n\t}\n\tSLOT->key |= key_set;\n}\n\nINLINE void KEY_OFF(OPLL_SLOT *SLOT, UINT32 key_clr)\n{\n\tif( SLOT->key )\n\t{\n\t\tSLOT->key &= key_clr;\n\n\t\tif( !SLOT->key )\n\t\t{\n\t\t\t/* phase -> Release */\n\t\t\tif (SLOT->state>EG_REL)\n\t\t\t\tSLOT->state = EG_REL;\n\t\t}\n\t}\n}\n\n/* update phase increment counter of operator (also update the EG rates if necessary) */\nINLINE void CALC_FCSLOT(OPLL_CH *CH,OPLL_SLOT *SLOT)\n{\n\tint ksr;\n\tUINT32 SLOT_rs;\n\tUINT32 SLOT_dp;\n\n\t/* (frequency) phase increment counter */\n\tSLOT->freq = CH->fc * SLOT->mul;\n\tksr = CH->kcode >> SLOT->KSR;\n\n\tif( SLOT->ksr != ksr )\n\t{\n\t\tSLOT->ksr = ksr;\n\n\t\t/* calculate envelope generator rates */\n\t\tif ((SLOT->ar + SLOT->ksr) < 16+62)\n\t\t{\n\t\t\tSLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];\n\t\t\tSLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSLOT->eg_sh_ar  = 0;\n\t\t\tSLOT->eg_sel_ar = 13*RATE_STEPS;\n\t\t}\n\t\tSLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];\n\t\tSLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];\n\t\tSLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];\n\t\tSLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];\n\n\t}\n\n\tif (CH->sus)\n\t\tSLOT_rs  = 16 + (5<<2);\n\telse\n\t\tSLOT_rs  = 16 + (7<<2);\n\n\tSLOT->eg_sh_rs  = eg_rate_shift [SLOT_rs + SLOT->ksr ];\n\tSLOT->eg_sel_rs = eg_rate_select[SLOT_rs + SLOT->ksr ];\n\n\tSLOT_dp  = 16 + (13<<2);\n\tSLOT->eg_sh_dp  = eg_rate_shift [SLOT_dp + SLOT->ksr ];\n\tSLOT->eg_sel_dp = eg_rate_select[SLOT_dp + SLOT->ksr ];\n}\n\n/* set multi,am,vib,EG-TYP,KSR,mul */\nINLINE void set_mul(YM2413 *chip,int slot,int v)\n{\n\tOPLL_CH   *CH   = &chip->P_CH[slot/2];\n\tOPLL_SLOT *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->mul     = mul_tab[v&0x0f];\n\tSLOT->KSR     = (v&0x10) ? 0 : 2;\n\tSLOT->eg_type = (v&0x20);\n\tSLOT->vib     = (v&0x40);\n\tSLOT->AMmask  = (v&0x80) ? ~0 : 0;\n\tCALC_FCSLOT(CH,SLOT);\n}\n\n/* set ksl, tl */\nINLINE void set_ksl_tl(YM2413 *chip,int chan,int v)\n{\n\tOPLL_CH   *CH   = &chip->P_CH[chan];\n/* modulator */\n\tOPLL_SLOT *SLOT = &CH->SLOT[SLOT1];\n\n\tSLOT->ksl = ksl_shift[v >> 6];\n\tSLOT->TL  = (v&0x3f)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */\n\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n}\n\n/* set ksl , waveforms, feedback */\nINLINE void set_ksl_wave_fb(YM2413 *chip,int chan,int v)\n{\n\tOPLL_CH   *CH   = &chip->P_CH[chan];\n/* modulator */\n\tOPLL_SLOT *SLOT = &CH->SLOT[SLOT1];\n\tSLOT->wavetable = ((v&0x08)>>3)*SIN_LEN;\n\tSLOT->fb_shift  = (v&7) ? (v&7) + 8 : 0;\n\n/*carrier*/\n\tSLOT = &CH->SLOT[SLOT2];\n\n\tSLOT->ksl = ksl_shift[v >> 6];\n\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n\n\tSLOT->wavetable = ((v&0x10)>>4)*SIN_LEN;\n}\n\n/* set attack rate & decay rate  */\nINLINE void set_ar_dr(YM2413 *chip,int slot,int v)\n{\n\tOPLL_CH   *CH   = &chip->P_CH[slot/2];\n\tOPLL_SLOT *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->ar = (v>>4)  ? 16 + ((v>>4)  <<2) : 0;\n\n\tif ((SLOT->ar + SLOT->ksr) < 16+62)\n\t{\n\t\tSLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];\n\t\tSLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];\n\t}\n\telse\n\t{\n\t\tSLOT->eg_sh_ar  = 0;\n\t\tSLOT->eg_sel_ar = 13*RATE_STEPS;\n\t}\n\n\tSLOT->dr    = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;\n\tSLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];\n\tSLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];\n}\n\n/* set sustain level & release rate */\nINLINE void set_sl_rr(YM2413 *chip,int slot,int v)\n{\n\tOPLL_CH   *CH   = &chip->P_CH[slot/2];\n\tOPLL_SLOT *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->sl  = sl_tab[ v>>4 ];\n\n\tSLOT->rr  = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;\n\tSLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];\n\tSLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];\n}\n\nstatic void load_instrument(YM2413 *chip, UINT32 chan, UINT32 slot, UINT8* inst )\n{\n\tset_mul\t\t\t(chip, slot,   inst[0]);\n\tset_mul\t\t\t(chip, slot+1, inst[1]);\n\tset_ksl_tl\t\t(chip, chan,   inst[2]);\n\tset_ksl_wave_fb\t(chip, chan,   inst[3]);\n\tset_ar_dr\t\t(chip, slot,   inst[4]);\n\tset_ar_dr\t\t(chip, slot+1, inst[5]);\n\tset_sl_rr\t\t(chip, slot,   inst[6]);\n\tset_sl_rr\t\t(chip, slot+1, inst[7]);\n}\nstatic void update_instrument_zero(YM2413 *chip, UINT8 r )\n{\n\tUINT8* inst = &chip->inst_tab[0][0]; /* point to user instrument */\n\tUINT32 chan;\n\tUINT32 chan_max;\n\n\tchan_max = 9;\n\tif (chip->rhythm & 0x20)\n\t\tchan_max=6;\n\n\tswitch(r)\n\t{\n\tcase 0:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_mul\t\t\t(chip, chan*2, inst[0]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 1:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_mul\t\t\t(chip, chan*2+1,inst[1]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 2:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_ksl_tl\t\t(chip, chan,   inst[2]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 3:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_ksl_wave_fb\t(chip, chan,   inst[3]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 4:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_ar_dr\t\t(chip, chan*2, inst[4]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 5:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_ar_dr\t\t(chip, chan*2+1,inst[5]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 6:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_sl_rr\t\t(chip, chan*2, inst[6]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 7:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_sl_rr\t\t(chip, chan*2+1,inst[7]);\n\t\t\t}\n\t\t}\n        break;\n    }\n}\n\n/* write a value v to register r on chip chip */\nstatic void OPLLWriteReg(YM2413 *chip, int r, int v)\n{\n\tOPLL_CH *CH;\n\tOPLL_SLOT *SLOT;\n\tUINT8 *inst;\n\tint chan;\n\tint slot;\n\n\t/* adjust bus to 8 bits */\n\tr &= 0xff;\n\tv &= 0xff;\n\n\n\t/*if (LOG_CYM_FILE && (cymfile) && (r!=8) )\n\t{\n\t\tfputc( (unsigned char)r, cymfile );\n\t\tfputc( (unsigned char)v, cymfile );\n\t}*/\n\n\n\tswitch(r&0xf0)\n\t{\n\tcase 0x00:\t/* 00-0f:control */\n\t{\n\t\tswitch(r&0x0f)\n\t\t{\n\t\tcase 0x00:\t/* AM/VIB/EGTYP/KSR/MULTI (modulator) */\n\t\tcase 0x01:\t/* AM/VIB/EGTYP/KSR/MULTI (carrier) */\n\t\tcase 0x02:\t/* Key Scale Level, Total Level (modulator) */\n\t\tcase 0x03:\t/* Key Scale Level, carrier waveform, modulator waveform, Feedback */\n\t\tcase 0x04:\t/* Attack, Decay (modulator) */\n\t\tcase 0x05:\t/* Attack, Decay (carrier) */\n\t\tcase 0x06:\t/* Sustain, Release (modulator) */\n\t\tcase 0x07:\t/* Sustain, Release (carrier) */\n\t\t\tchip->inst_tab[0][r & 0x07] = v;\n\t\t\tupdate_instrument_zero(chip,r&7);\n\t\tbreak;\n\n\t\tcase 0x0e:\t/* x, x, r,bd,sd,tom,tc,hh */\n\t\t{\n\t\t\tif (chip->VRC7_Mode)\n\t\t\t\tbreak;\n\t\t\tif(v&0x20)\n\t\t\t{\n\t\t\t\tif ((chip->rhythm&0x20)==0)\n\t\t\t\t/*rhythm off to on*/\n\t\t\t\t{\n\t\t\t\t\t//logerror(\"YM2413: Rhythm mode enable\\n\");\n\n\t/* Load instrument settings for channel seven(chan=6 since we're zero based). (Bass drum) */\n\t\t\t\t\tchan = 6;\n\t\t\t\t\tinst = &chip->inst_tab[16][0];\n\t\t\t\t\tslot = chan*2;\n\n\t\t\t\t\tload_instrument(chip, chan, slot, inst);\n\n\t/* Load instrument settings for channel eight. (High hat and snare drum) */\n\t\t\t\t\tchan = 7;\n\t\t\t\t\tinst = &chip->inst_tab[17][0];\n\t\t\t\t\tslot = chan*2;\n\n\t\t\t\t\tload_instrument(chip, chan, slot, inst);\n\n\t\t\t\t\tCH   = &chip->P_CH[chan];\n\t\t\t\t\tSLOT = &CH->SLOT[SLOT1]; /* modulator envelope is HH */\n\t\t\t\t\tSLOT->TL  = ((chip->instvol_r[chan]>>4)<<2)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */\n\t\t\t\t\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n\n\t/* Load instrument settings for channel nine. (Tom-tom and top cymbal) */\n\t\t\t\t\tchan = 8;\n\t\t\t\t\tinst = &chip->inst_tab[18][0];\n\t\t\t\t\tslot = chan*2;\n\n\t\t\t\t\tload_instrument(chip, chan, slot, inst);\n\n\t\t\t\t\tCH   = &chip->P_CH[chan];\n\t\t\t\t\tSLOT = &CH->SLOT[SLOT1]; /* modulator envelope is TOM */\n\t\t\t\t\tSLOT->TL  = ((chip->instvol_r[chan]>>4)<<2)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */\n\t\t\t\t\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n\t\t\t\t}\n\t\t\t\t/* BD key on/off */\n\t\t\t\tif(v&0x10)\n\t\t\t\t{\n\t\t\t\t\tKEY_ON (&chip->P_CH[6].SLOT[SLOT1], 2);\n\t\t\t\t\tKEY_ON (&chip->P_CH[6].SLOT[SLOT2], 2);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tKEY_OFF(&chip->P_CH[6].SLOT[SLOT1],~2);\n\t\t\t\t\tKEY_OFF(&chip->P_CH[6].SLOT[SLOT2],~2);\n\t\t\t\t}\n\t\t\t\t/* HH key on/off */\n\t\t\t\tif(v&0x01) KEY_ON (&chip->P_CH[7].SLOT[SLOT1], 2);\n\t\t\t\telse       KEY_OFF(&chip->P_CH[7].SLOT[SLOT1],~2);\n\t\t\t\t/* SD key on/off */\n\t\t\t\tif(v&0x08) KEY_ON (&chip->P_CH[7].SLOT[SLOT2], 2);\n\t\t\t\telse       KEY_OFF(&chip->P_CH[7].SLOT[SLOT2],~2);\n\t\t\t\t/* TOM key on/off */\n\t\t\t\tif(v&0x04) KEY_ON (&chip->P_CH[8].SLOT[SLOT1], 2);\n\t\t\t\telse       KEY_OFF(&chip->P_CH[8].SLOT[SLOT1],~2);\n\t\t\t\t/* TOP-CY key on/off */\n\t\t\t\tif(v&0x02) KEY_ON (&chip->P_CH[8].SLOT[SLOT2], 2);\n\t\t\t\telse       KEY_OFF(&chip->P_CH[8].SLOT[SLOT2],~2);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ((chip->rhythm&0x20)!=0)\n\t\t\t\t/*rhythm on to off*/\n\t\t\t\t{\n\t\t\t\t\t//logerror(\"YM2413: Rhythm mode disable\\n\");\n\t/* Load instrument settings for channel seven(chan=6 since we're zero based).*/\n\t\t\t\t\tchan = 6;\n\t\t\t\t\tinst = &chip->inst_tab[chip->instvol_r[chan]>>4][0];\n\t\t\t\t\tslot = chan*2;\n\n\t\t\t\t\tload_instrument(chip, chan, slot, inst);\n\n\t/* Load instrument settings for channel eight.*/\n\t\t\t\t\tchan = 7;\n\t\t\t\t\tinst = &chip->inst_tab[chip->instvol_r[chan]>>4][0];\n\t\t\t\t\tslot = chan*2;\n\n\t\t\t\t\tload_instrument(chip, chan, slot, inst);\n\n\t/* Load instrument settings for channel nine.*/\n\t\t\t\t\tchan = 8;\n\t\t\t\t\tinst = &chip->inst_tab[chip->instvol_r[chan]>>4][0];\n\t\t\t\t\tslot = chan*2;\n\n\t\t\t\t\tload_instrument(chip, chan, slot, inst);\n\t\t\t\t}\n\t\t\t\t/* BD key off */\n\t\t\t\tKEY_OFF(&chip->P_CH[6].SLOT[SLOT1],~2);\n\t\t\t\tKEY_OFF(&chip->P_CH[6].SLOT[SLOT2],~2);\n\t\t\t\t/* HH key off */\n\t\t\t\tKEY_OFF(&chip->P_CH[7].SLOT[SLOT1],~2);\n\t\t\t\t/* SD key off */\n\t\t\t\tKEY_OFF(&chip->P_CH[7].SLOT[SLOT2],~2);\n\t\t\t\t/* TOM key off */\n\t\t\t\tKEY_OFF(&chip->P_CH[8].SLOT[SLOT1],~2);\n\t\t\t\t/* TOP-CY off */\n\t\t\t\tKEY_OFF(&chip->P_CH[8].SLOT[SLOT2],~2);\n\t\t\t}\n\t\t\tchip->rhythm  = v&0x3f;\n\t\t}\n\t\tbreak;\n\t\t}\n\t}\n\tbreak;\n\n\tcase 0x10:\n\tcase 0x20:\n\t{\n\t\tint block_fnum;\n\n\t\tchan = r&0x0f;\n\n\t\tif (chan >= 9)\n\t\t\tchan -= 9;\t/* verified on real YM2413 */\n\t\tif (chip->VRC7_Mode && chan >= 6)\n\t\t\tbreak;\n\n\t\tCH = &chip->P_CH[chan];\n\n\t\tif(r&0x10)\n\t\t{\t/* 10-18: FNUM 0-7 */\n\t\t\tblock_fnum  = (CH->block_fnum&0x0f00) | v;\n\t\t}\n\t\telse\n\t\t{\t/* 20-28: suson, keyon, block, FNUM 8 */\n\t\t\tblock_fnum = ((v&0x0f)<<8) | (CH->block_fnum&0xff);\n\n\t\t\tif(v&0x10)\n\t\t\t{\n\t\t\t\tKEY_ON (&CH->SLOT[SLOT1], 1);\n\t\t\t\tKEY_ON (&CH->SLOT[SLOT2], 1);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tKEY_OFF(&CH->SLOT[SLOT1],~1);\n\t\t\t\tKEY_OFF(&CH->SLOT[SLOT2],~1);\n\t\t\t}\n\n\n\t\t\t//if (CH->sus!=(v&0x20))\n\t\t\t//\tlogerror(\"chan=%i sus=%2x\\n\",chan,v&0x20);\n\n\t\t\tCH->sus = v & 0x20;\n\t\t}\n\t\t/* update */\n\t\tif(CH->block_fnum != block_fnum)\n\t\t{\n\t\t\tUINT8 block;\n\n\t\t\tCH->block_fnum = block_fnum;\n\n\t\t\t/* BLK 2,1,0 bits -> bits 3,2,1 of kcode, FNUM MSB -> kcode LSB */\n\t\t\tCH->kcode    = (block_fnum&0x0f00)>>8;\n\n\t\t\tCH->ksl_base = ksl_tab[block_fnum>>5];\n\n\t\t\tblock_fnum   = block_fnum * 2;\n\t\t\tblock        = (block_fnum&0x1c00) >> 10;\n\t\t\tCH->fc       = chip->fn_tab[block_fnum&0x03ff] >> (7-block);\n\n\t\t\t/* refresh Total Level in both SLOTs of this channel */\n\t\t\tCH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);\n\t\t\tCH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);\n\n\t\t\t/* refresh frequency counter in both SLOTs of this channel */\n\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT1]);\n\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT2]);\n\t\t}\n\t}\n\tbreak;\n\n\tcase 0x30:\t/* inst 4 MSBs, VOL 4 LSBs */\n\t{\n\t\tUINT8 old_instvol;\n\n\t\tchan = r&0x0f;\n\n\t\tif (chan >= 9)\n\t\t\tchan -= 9;\t/* verified on real YM2413 */\n\t\tif (chip->VRC7_Mode && chan >= 6)\n\t\t\tbreak;\n\n\t\told_instvol = chip->instvol_r[chan];\n\t\tchip->instvol_r[chan] = v;\t/* store for later use */\n\n\t\tCH   = &chip->P_CH[chan];\n\t\tSLOT = &CH->SLOT[SLOT2]; /* carrier */\n\t\tSLOT->TL  = ((v&0x0f)<<2)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */\n\t\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n\n\n\t\t/*check whether we are in rhythm mode and handle instrument/volume register accordingly*/\n\t\tif ((chan>=6) && (chip->rhythm&0x20))\n\t\t{\n\t\t\t/* we're in rhythm mode*/\n\n\t\t\tif (chan>=7) /* only for channel 7 and 8 (channel 6 is handled in usual way)*/\n\t\t\t{\n\t\t\t\tSLOT = &CH->SLOT[SLOT1]; /* modulator envelope is HH(chan=7) or TOM(chan=8) */\n\t\t\t\tSLOT->TL  = ((chip->instvol_r[chan]>>4)<<2)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */\n\t\t\t\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ( (old_instvol&0xf0) == (v&0xf0) )\n\t\t\t\treturn;\n\n\t\t\tinst = &chip->inst_tab[chip->instvol_r[chan]>>4][0];\n\t\t\tslot = chan*2;\n\n\t\t\tload_instrument(chip, chan, slot, inst);\n\n\t\t/*#if 0\n\t\t\tlogerror(\"YM2413: chan#%02i inst=%02i:  (r=%2x, v=%2x)\\n\",chan,v>>4,r,v);\n\t\t\tlogerror(\"  0:%2x  1:%2x\\n\",inst[0],inst[1]);\tlogerror(\"  2:%2x  3:%2x\\n\",inst[2],inst[3]);\n\t\t\tlogerror(\"  4:%2x  5:%2x\\n\",inst[4],inst[5]);\tlogerror(\"  6:%2x  7:%2x\\n\",inst[6],inst[7]);\n\t\t#endif*/\n\t\t}\n\t}\n\tbreak;\n\n\tdefault:\n\tbreak;\n\t}\n}\n\n/*static TIMER_CALLBACK( cymfile_callback )\n{\n\tif (cymfile)\n\t{\n\t\tfputc( (unsigned char)8, cymfile );\n\t}\n}*/\n\n/* lock/unlock for common table */\n//static int OPLL_LockTable(const device_config *device)\nstatic int OPLL_LockTable(void)\n{\n\tnum_lock++;\n\tif(num_lock>1) return 0;\n\n\t/* first time */\n\n\t/* allocate total level table (128kb space) */\n\tif( !init_tables() )\n\t{\n\t\tnum_lock--;\n\t\treturn -1;\n\t}\n\n\t/*if (LOG_CYM_FILE)\n\t{\n\t\tcymfile = fopen(\"2413_.cym\",\"wb\");\n\t\tif (cymfile)\n\t\t\ttimer_pulse ( device->machine, ATTOTIME_IN_HZ(110), NULL, 0, cymfile_callback); //110 Hz pulse timer\n\t\telse\n\t\t\tlogerror(\"Could not create file 2413_.cym\\n\");\n\t}*/\n\n\treturn 0;\n}\n\nstatic void OPLL_UnLockTable(void)\n{\n\tif(num_lock) num_lock--;\n\tif(num_lock) return;\n\n\t/* last time */\n\n\tOPLCloseTable();\n\n\t/*if (cymfile)\n\t\tfclose (cymfile);\n\tcymfile = NULL;*/\n}\n\nstatic void OPLLResetChip(YM2413 *chip)\n{\n\tint c,s;\n\tint i;\n\n\tchip->eg_timer = 0;\n\tchip->eg_cnt   = 0;\n\n\tchip->noise_rng = 1;\t/* noise shift register */\n\n\n\t/* setup instruments table */\n\tfor (i=0; i<19; i++)\n\t{\n\t\tfor (c=0; c<8; c++)\n\t\t{\n\t\t\tchip->inst_tab[i][c] = table[i][c];\n\t\t}\n\t}\n\n\n\t/* reset with register write */\n\tOPLLWriteReg(chip,0x0f,0); /*test reg*/\n\tfor(i = 0x3f ; i >= 0x10 ; i-- ) OPLLWriteReg(chip,i,0x00);\n\n\t/* reset operator parameters */\n\tfor( c = 0 ; c < 9 ; c++ )\n\t{\n\t\tOPLL_CH *CH = &chip->P_CH[c];\n\t\tfor(s = 0 ; s < 2 ; s++ )\n\t\t{\n\t\t\t/* wave table */\n\t\t\tCH->SLOT[s].wavetable = 0;\n\t\t\tCH->SLOT[s].state     = EG_OFF;\n\t\t\tCH->SLOT[s].volume    = MAX_ATT_INDEX;\n\t\t}\n\t}\n}\n\n/* Create one of virtual YM2413 */\n/* 'clock' is chip clock in Hz  */\n/* 'rate'  is sampling rate  */\n//static YM2413 *OPLLCreate(const device_config *device, int clock, int rate)\nstatic YM2413 *OPLLCreate(int clock, int rate)\n{\n\tchar *ptr;\n\tYM2413 *chip;\n\tint state_size;\n\n\tif (OPLL_LockTable() == -1) return NULL;\n\n\t/* calculate chip state size */\n\tstate_size  = sizeof(YM2413);\n\n\t/* allocate memory block */\n\tptr = (char *)malloc(state_size);\n\n\tif (ptr==NULL)\n\t\treturn NULL;\n\n\t/* clear */\n\tmemset(ptr,0,state_size);\n\n\tchip  = (YM2413 *)ptr;\n\n\tchip->clock = clock;\n\tchip->rate  = rate;\n\n\t/* init global tables */\n\tOPLL_initalize(chip);\n\n\t/* reset chip */\n\tOPLLResetChip(chip);\n\treturn chip;\n}\n\n/* Destroy one of virtual YM3812 */\nstatic void OPLLDestroy(YM2413 *chip)\n{\n\tOPLL_UnLockTable();\n\tfree(chip);\n}\n\n/* Option handlers */\n\nstatic void OPLLSetUpdateHandler(YM2413 *chip,OPLL_UPDATEHANDLER UpdateHandler,void * param)\n{\n\tchip->UpdateHandler = UpdateHandler;\n\tchip->UpdateParam = param;\n}\n\n/* YM3812 I/O interface */\nstatic void OPLLWrite(YM2413 *chip,int a,int v)\n{\n\tif( !(a&1) )\n\t{\t/* address port */\n\t\tchip->address = v & 0xff;\n\t}\n\telse\n\t{\t/* data port */\n\t\tif(chip->UpdateHandler) chip->UpdateHandler(chip->UpdateParam,0);\n\t\tOPLLWriteReg(chip,chip->address,v);\n\t}\n}\n\nstatic unsigned char OPLLRead(YM2413 *chip,int a)\n{\n\tif( !(a&1) )\n\t{\n\t\t/* status port */\n\t\treturn chip->status;\n\t}\n\treturn 0xff;\n}\n\n\n\n\n\n//void * ym2413_init(const device_config *device, int clock, int rate)\nvoid * ym2413_init(int clock, int rate)\n{\n\t/* emulator create */\n\treturn OPLLCreate(clock, rate);\n}\n\nvoid ym2413_shutdown(void *chip)\n{\n\tYM2413 *OPLL = (YM2413 *)chip;\n\n\t/* emulator shutdown */\n\tOPLLDestroy(OPLL);\n}\n\nvoid ym2413_reset_chip(void *chip)\n{\n\tYM2413 *OPLL = (YM2413 *)chip;\n\tOPLLResetChip(OPLL);\n}\n\nvoid ym2413_write(void *chip, int a, int v)\n{\n\tYM2413 *OPLL = (YM2413 *)chip;\n\tOPLLWrite(OPLL, a, v);\n}\n\nunsigned char ym2413_read(void *chip, int a)\n{\n\tYM2413 *OPLL = (YM2413 *)chip;\n\treturn OPLLRead(OPLL, a) & 0x03 ;\n}\n\nvoid ym2413_set_update_handler(void *chip,OPLL_UPDATEHANDLER UpdateHandler,void *param)\n{\n\tYM2413 *OPLL = (YM2413 *)chip;\n\tOPLLSetUpdateHandler(OPLL, UpdateHandler, param);\n}\n\n\n/*\n** Generate samples for one of the YM2413's\n**\n** 'which' is the virtual YM2413 number\n** '*buffer' is the output buffer pointer\n** 'length' is the number of samples that should be generated\n*/\nvoid ym2413_update_one(void *_chip, SAMP **buffers, int length)\n{\n\tYM2413\t\t*chip  = (YM2413 *)_chip;\n\tUINT8\t\trhythm = chip->rhythm&0x20;\n\tSAMP\t\t*bufMO = buffers[0];\n\tSAMP\t\t*bufRO = buffers[1];\n\n\tint i;\n\n\tfor( i=0; i < length ; i++ )\n\t{\n\t\tint mo,ro;\n\n\t\tchip->output[0] = 0;\n\t\tchip->output[1] = 0;\n\n\t\tadvance_lfo(chip);\n\n\t\t/* FM part */\n\t\tchan_calc(chip, &chip->P_CH[0]);\n//SAVE_SEPARATE_CHANNEL(0);\n\t\tchan_calc(chip, &chip->P_CH[1]);\n\t\tchan_calc(chip, &chip->P_CH[2]);\n\t\tchan_calc(chip, &chip->P_CH[3]);\n\t\tchan_calc(chip, &chip->P_CH[4]);\n\t\tchan_calc(chip, &chip->P_CH[5]);\n\n\t\tif (! chip->VRC7_Mode)\n\t\t{\n\t\t\tif(!rhythm)\n\t\t\t{\n\t\t\t\tchan_calc(chip, &chip->P_CH[6]);\n\t\t\t\tchan_calc(chip, &chip->P_CH[7]);\n\t\t\t\tchan_calc(chip, &chip->P_CH[8]);\n\t\t\t}\n\t\t\telse\t\t/* Rhythm part */\n\t\t\t{\n\t\t\t\trhythm_calc(chip, &chip->P_CH[0], (chip->noise_rng>>0)&1 );\n\t\t\t}\n\t\t}\n\n\t\tmo = chip->output[0];\n\t\tro = chip->output[1];\n\n\t\tmo >>= FINAL_SH;\n\t\tro >>= FINAL_SH;\n\n\t\t/* limit check */\n\t\t//mo = limit( mo , MAXOUT, MINOUT );\n\t\t//ro = limit( ro , MAXOUT, MINOUT );\n\n\t\t#ifdef SAVE_SAMPLE\n\t\t//if (which==0)\n\t\t//{\n\t\t\tSAVE_ALL_CHANNELS\n\t\t//}\n\t\t#endif\n\n\t\t/* store to sound buffer */\n\t\tbufMO[i] = mo + ro;\n\t\tbufRO[i] = mo + ro;\n\n\t\tadvance(chip);\n\t}\n\n}\n\nvoid ym2413_set_mutemask(void* chip, UINT32 MuteMask)\n{\n\tYM2413* OPLL = (YM2413*)chip;\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 9; CurChn ++)\n\t\tOPLL->P_CH[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\tfor (CurChn = 0; CurChn < 5; CurChn ++)\n\t\tOPLL->MuteSpc[CurChn] = (MuteMask >> (9 + CurChn)) & 0x01;\n\t\n\treturn;\n}\n\nvoid ym2413_set_chip_mode(void* chip, UINT8 Mode)\n{\n\t// Enable/Disable VRC7 Mode (with only 6 instead of 9 channels and no rhythm part)\n\tYM2413* OPLL = (YM2413*)chip;\n\t\n\tOPLL->VRC7_Mode = Mode;\n\t\n\treturn;\n}\n\nvoid ym2413_override_patches(void* chip, const UINT8* PatchDump)\n{\n\tYM2413* OPLL = (YM2413*)chip;\n\tUINT8 CurIns;\n\tUINT8 CurReg;\n\t\n\tfor (CurIns = 0; CurIns < 19; CurIns ++)\n\t{\n\t\tfor (CurReg = 0; CurReg < 8; CurReg ++)\n\t\t{\n\t\t\tOPLL->inst_tab[CurIns][CurReg] = PatchDump[CurIns * 8 + CurReg];\n\t\t}\n\t}\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/ym2413.h",
    "content": "#pragma once\n\n/* select output bits size of output : 8 or 16 */\n#define SAMPLE_BITS 16\n\n/* compiler dependence */\n//#ifndef __OSDCOMM_H__\n//#define __OSDCOMM_H__\n/*typedef unsigned char\tUINT8;   // unsigned  8bit\ntypedef unsigned short\tUINT16;  // unsigned 16bit\ntypedef unsigned int\tUINT32;  // unsigned 32bit\ntypedef signed char\t\tINT8;    // signed  8bit\ntypedef signed short\tINT16;   // signed 16bit\ntypedef signed int\t\tINT32;   // signed 32bit   */\n//#endif\n\n//typedef INT32 stream_sample_t;\ntypedef stream_sample_t SAMP;\n/*\n#if (SAMPLE_BITS==16)\ntypedef INT16 SAMP;\n#endif\n#if (SAMPLE_BITS==8)\ntypedef INT8 SAMP;\n#endif\n*/\n\n\n\n//void *ym2413_init(const device_config *device, int clock, int rate);\nvoid *ym2413_init(int clock, int rate);\nvoid ym2413_shutdown(void *chip);\nvoid ym2413_reset_chip(void *chip);\nvoid ym2413_write(void *chip, int a, int v);\nunsigned char ym2413_read(void *chip, int a);\nvoid ym2413_update_one(void *chip, SAMP **buffers, int length);\n\ntypedef void (*OPLL_UPDATEHANDLER)(void *param,int min_interval_us);\n\nvoid ym2413_set_update_handler(void *chip, OPLL_UPDATEHANDLER UpdateHandler, void *param);\nvoid ym2413_set_mutemask(void* chip, UINT32 MuteMask);\nvoid ym2413_set_chip_mode(void* chip, UINT8 Mode);\nvoid ym2413_override_patches(void* chip, const UINT8* PatchDump);\n"
  },
  {
    "path": "VGMPlay/chips/ym2413_opl.c",
    "content": "#include \"mamedef.h\"\n\nvoid OPL_RegMapper(UINT16 Reg, UINT8 Data);\n\n/* register number to channel number , slot offset */\n#define SLOT1 0\n#define SLOT2 1\n\ntypedef struct{\n\tUINT32\tar;\t\t\t/* attack rate                  */\n\tUINT32\tdr;\t\t\t/* decay rate                   */\n\tUINT32\trr;\t\t\t/* release rate                 */\n\tUINT8\tKSR;\t\t/* key scale rate               */\n\tUINT8\tksl;\t\t/* keyscale level               */\n\tUINT8\tmul;\t\t/* multiple: mul_tab[ML]        */\n\n\t/* Phase Generator */\n\t//UINT32\tphase;\t\t/* frequency counter            */\n\t//UINT32\tfreq;\t\t/* frequency counter step       */\n\tUINT8   fb_shift;\t/* feedback shift value         */\n\t//INT32   op1_out[2];\t/* slot1 output for feedback    */\n\n\t/* Envelope Generator */\n\tUINT8\teg_type;\t/* percussive/nonpercussive mode*/\n\t//UINT8\tstate;\t\t/* phase type                   */\n\tUINT32\tTL;\t\t\t/* total level                  */\n\t//INT32\tvolume;\t\t/* envelope counter             */\n\tUINT32\tsl;\t\t\t/* sustain level: sl_tab[SL]    */\n\n\t//UINT32\tkey;\t\t/* 0 = KEY OFF, >0 = KEY ON     */\n\n\t/* LFO */\n\tUINT32\tAMmask;\t\t/* LFO Amplitude Modulation enable mask */\n\tUINT8\tvib;\t\t/* LFO Phase Modulation enable flag (active high)*/\n\n\t/* waveform select */\n\tunsigned int wavetable;\n} OPLL_SLOT_OPL;\n\ntypedef struct{\n\tOPLL_SLOT_OPL SLOT[2];\n\t/* phase generator state */\n\t//UINT32  block_fnum;\t/* block+fnum                   */\n\tUINT8   fnum_lsb;\n\tUINT8   fnum_lmsb;\n\tUINT8   fnum_msb;\n\tUINT8   block;\n\tUINT8   keyon;\n\tUINT8   sus;\t\t/* sus on/off (release speed in percussive mode)*/\n\tUINT8   fnumlsb_null;\n} OPLL_CH_OPL;\n\n/* chip state */\n typedef struct {\n\tOPLL_CH_OPL\tP_CH[9];\t\t\t\t/* OPLL chips have 9 channels*/\n\tUINT8\tinstvol_r[9];\t\t\t/* instrument/volume (or volume/volume in percussive mode)*/\n\tUINT8\trhythm;\t\t\t\t\t/* Rhythm mode                  */\n\n/* instrument settings */\n/*\n    0-user instrument\n    1-15 - fixed instruments\n    16 -bass drum settings\n    17,18 - other percussion instruments\n*/\n\tUINT8 inst_tab[19][8];\n\n\tUINT8 address;\t\t\t\t\t/* address register             */\n\tUINT8 status;\t\t\t\t\t/* status flag                  */\n} YM2413;\n\nstatic const unsigned char table[19][8] = {\n/* MULT  MULT modTL DcDmFb AR/DR AR/DR SL/RR SL/RR */\n/*   0     1     2     3     4     5     6    7    */\n  {0x49, 0x4c, 0x4c, 0x12, 0x00, 0x00, 0x00, 0x00 },\t//0\n\n  {0x61, 0x61, 0x1e, 0x17, 0xf0, 0x78, 0x00, 0x17 },\t//1\n  {0x13, 0x41, 0x1e, 0x0d, 0xd7, 0xf7, 0x13, 0x13 },\t//2\n  {0x13, 0x01, 0x99, 0x04, 0xf2, 0xf4, 0x11, 0x23 },\t//3\n  {0x21, 0x61, 0x1b, 0x07, 0xaf, 0x64, 0x40, 0x27 },\t//4\n\n//{0x22, 0x21, 0x1e, 0x09, 0xf0, 0x76, 0x08, 0x28 },    //5\n  {0x22, 0x21, 0x1e, 0x06, 0xf0, 0x75, 0x08, 0x18 },\t//5\n\n//{0x31, 0x22, 0x16, 0x09, 0x90, 0x7f, 0x00, 0x08 },    //6\n  {0x31, 0x22, 0x16, 0x05, 0x90, 0x71, 0x00, 0x13 },\t//6\n\n  {0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x10, 0x17 },\t//7\n  {0x23, 0x21, 0x2d, 0x16, 0xc0, 0x70, 0x07, 0x07 },\t//8\n  {0x61, 0x61, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 },\t//9\n\n//{0x61, 0x61, 0x0c, 0x08, 0x85, 0xa0, 0x79, 0x07 },    //A\n  {0x61, 0x61, 0x0c, 0x18, 0x85, 0xf0, 0x70, 0x07 },\t//A\n\n  {0x23, 0x01, 0x07, 0x11, 0xf0, 0xa4, 0x00, 0x22 },\t//B\n  {0x97, 0xc1, 0x24, 0x07, 0xff, 0xf8, 0x22, 0x12 },\t//C\n\n//{0x61, 0x10, 0x0c, 0x08, 0xf2, 0xc4, 0x40, 0xc8 },    //D\n  {0x61, 0x10, 0x0c, 0x05, 0xf2, 0xf4, 0x40, 0x44 },\t//D\n\n  {0x01, 0x01, 0x55, 0x03, 0xf3, 0x92, 0xf3, 0xf3 },\t//E\n  {0x61, 0x41, 0x89, 0x03, 0xf1, 0xf4, 0xf0, 0x13 },\t//F\n\n/* drum instruments definitions */\n/* MULTI MULTI modTL  xxx  AR/DR AR/DR SL/RR SL/RR */\n/*   0     1     2     3     4     5     6    7    */\n  {0x01, 0x01, 0x16, 0x00, 0xfd, 0xf8, 0x2f, 0x6d },/* BD(multi verified, modTL verified, mod env - verified(close), carr. env verifed) */\n  {0x01, 0x01, 0x00, 0x00, 0xd8, 0xd8, 0xf9, 0xf8 },/* HH(multi verified), SD(multi not used) */\n  {0x05, 0x01, 0x00, 0x00, 0xf8, 0xba, 0x49, 0x55 },/* TOM(multi,env verified), TOP CYM(multi verified, env verified) */\n};\n\nstatic const unsigned char SLOT2OPL[6 * 3] = \n{\t0x00, 0x03, 0x01, 0x04, 0x02, 0x05,\n\t0x08, 0x0B, 0x09, 0x0C, 0x0A, 0x0D,\n\t0x10, 0x13, 0x11, 0x14, 0x12, 0x15};\n\n\n#define MAX_CHIPS\t0x10\nstatic YM2413 YM2413Data[MAX_CHIPS];\n\n\n/* set multi,am,vib,EG-TYP,KSR,mul */\nINLINE void set_mul(YM2413 *chip,int slot,int v)\n{\n\tOPLL_CH_OPL   *CH   = &chip->P_CH[slot/2];\n\tOPLL_SLOT_OPL *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->mul     = v & 0x0F;\n\tSLOT->KSR     = v & 0x10;\n\tSLOT->eg_type = v & 0x20;\n\tSLOT->vib     = v & 0x40;\n\tSLOT->AMmask  = v & 0x80;\n\t\n\tOPL_RegMapper(0x20 | SLOT2OPL[slot], \n\t\t\t\t\tSLOT->AMmask | SLOT->vib | SLOT->eg_type | SLOT->KSR | SLOT->mul);\n}\n\n/* set ksl, tl */\nINLINE void set_ksl_tl(YM2413 *chip,int chan,int v)\n{\n\tOPLL_CH_OPL   *CH   = &chip->P_CH[chan];\n\tOPLL_SLOT_OPL *SLOT = &CH->SLOT[SLOT1];\n\t\n/* modulator */\n\t// OPLL KSL (0/1.5/3/6) -> OPL KSL (0/3/1.5/6)\n\tSLOT->ksl = ((v & 0x40) << 1) | ((v & 0x80) >> 1);\t// swap bits 6<->7\n\tSLOT->TL = v & 0x3F;\n\t\n\tOPL_RegMapper(0x40 | SLOT2OPL[chan * 2 + SLOT1], SLOT->ksl | SLOT->TL);\n}\n\n/* set ksl , waveforms, feedback */\nINLINE void set_ksl_wave_fb(YM2413 *chip,int chan,int v)\n{\n\tOPLL_CH_OPL   *CH   = &chip->P_CH[chan];\n\tOPLL_SLOT_OPL *SLOT;\n\t\n/* modulator */\n\tSLOT = &CH->SLOT[SLOT1];\n\tSLOT->wavetable = (v & 0x08) >> 3;\n\tSLOT->fb_shift  = (v & 0x07) << 1;\n\t\n\tOPL_RegMapper(0xE0 | SLOT2OPL[chan * 2 + SLOT1], SLOT->wavetable);\n\tOPL_RegMapper(0xC0 | chan, SLOT->fb_shift | 0x30);\n\t\n/*carrier*/\n\tSLOT = &CH->SLOT[SLOT2];\n\tSLOT->ksl = v & 0xC0;\n\tSLOT->wavetable = (v & 0x10) >> 4;\n\t\n\tOPL_RegMapper(0xE0 | SLOT2OPL[chan * 2 + SLOT2], SLOT->wavetable);\n\tOPL_RegMapper(0x40 | SLOT2OPL[chan * 2 + SLOT2], SLOT->ksl | SLOT->TL);\n}\n\n/* set attack rate & decay rate  */\nINLINE void set_ar_dr(YM2413 *chip,int slot,int v)\n{\n\tOPLL_CH_OPL   *CH   = &chip->P_CH[slot/2];\n\tOPLL_SLOT_OPL *SLOT = &CH->SLOT[slot&1];\n\t\n\tSLOT->ar = v & 0xF0;\n\tSLOT->dr = v & 0x0F;\n\t\n\tOPL_RegMapper(0x60 | SLOT2OPL[slot], SLOT->ar | SLOT->dr);\n}\n\n/* set sustain level & release rate */\nINLINE void set_sl_rr(YM2413 *chip,int slot,int v)\n{\n\tOPLL_CH_OPL   *CH   = &chip->P_CH[slot/2];\n\tOPLL_SLOT_OPL *SLOT = &CH->SLOT[slot&1];\n\t\n\tSLOT->sl  = v & 0xF0;\n\tSLOT->rr  = v & 0x0F;\n\t\n\tOPL_RegMapper(0x80 | SLOT2OPL[slot], SLOT->sl | SLOT->rr);\n}\n\nstatic void load_instrument(YM2413 *chip, UINT32 chan, UINT32 slot, UINT8* inst )\n{\n\tset_mul\t\t\t(chip, slot,   inst[0]);\n\tset_mul\t\t\t(chip, slot+1, inst[1]);\n\tset_ksl_tl\t\t(chip, chan,   inst[2]);\n\t//set_ksl_wave_fb\t(chip, chan,   inst[3]);\n\tset_ar_dr\t\t(chip, slot,   inst[4]);\n\tset_ar_dr\t\t(chip, slot+1, inst[5]);\n\tset_sl_rr\t\t(chip, slot,   inst[6]);\n\tset_sl_rr\t\t(chip, slot+1, inst[7]);\n\tset_ksl_wave_fb\t(chip, chan,   inst[3]);\t// called last to avoid a 'click'\n}\nstatic void update_instrument_zero(YM2413 *chip, UINT8 r )\n{\n\tUINT8* inst = &chip->inst_tab[0][0]; /* point to user instrument */\n\tUINT32 chan;\n\tUINT32 chan_max;\n\n\tchan_max = 9;\n\tif (chip->rhythm & 0x20)\n\t\tchan_max=6;\n\n\tswitch(r)\n\t{\n\tcase 0:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_mul\t\t\t(chip, chan*2, inst[0]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 1:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_mul\t\t\t(chip, chan*2+1,inst[1]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 2:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_ksl_tl\t\t(chip, chan,   inst[2]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 3:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_ksl_wave_fb\t(chip, chan,   inst[3]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 4:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_ar_dr\t\t(chip, chan*2, inst[4]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 5:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_ar_dr\t\t(chip, chan*2+1,inst[5]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 6:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_sl_rr\t\t(chip, chan*2, inst[6]);\n\t\t\t}\n\t\t}\n        break;\n\tcase 7:\n\t\tfor (chan=0; chan<chan_max; chan++)\n\t\t{\n\t\t\tif ((chip->instvol_r[chan]&0xf0)==0)\n\t\t\t{\n\t\t\t\tset_sl_rr\t\t(chip, chan*2+1,inst[7]);\n\t\t\t}\n\t\t}\n        break;\n    }\n}\n\n/* write a value v to register r on chip chip */\nstatic void OPLLWriteReg2OPL(YM2413 *chip, int r, int v)\n{\n\tOPLL_CH_OPL *CH;\n\tOPLL_SLOT_OPL *SLOT;\n\tUINT8 *inst;\n\tint chan;\n\tint slot;\n\tUINT8 fnln_old;\n\n\t/* adjust bus to 8 bits */\n\tr &= 0xff;\n\tv &= 0xff;\n\n\tswitch(r&0xf0)\n\t{\n\tcase 0x00:\t/* 00-0f:control */\n\t{\n\t\tswitch(r&0x0f)\n\t\t{\n\t\tcase 0x00:\t/* AM/VIB/EGTYP/KSR/MULTI (modulator) */\n\t\tcase 0x01:\t/* AM/VIB/EGTYP/KSR/MULTI (carrier) */\n\t\tcase 0x02:\t/* Key Scale Level, Total Level (modulator) */\n\t\tcase 0x03:\t/* Key Scale Level, carrier waveform, modulator waveform, Feedback */\n\t\tcase 0x04:\t/* Attack, Decay (modulator) */\n\t\tcase 0x05:\t/* Attack, Decay (carrier) */\n\t\tcase 0x06:\t/* Sustain, Release (modulator) */\n\t\tcase 0x07:\t/* Sustain, Release (carrier) */\n\t\t\tchip->inst_tab[0][r & 0x07] = v;\n\t\t\tupdate_instrument_zero(chip,r&7);\n\t\tbreak;\n\n\t\tcase 0x0e:\t/* x, x, r,bd,sd,tom,tc,hh */\n\t\t{\n\t\t\tif(v&0x20)\n\t\t\t{\n\t\t\t\tif ((chip->rhythm&0x20)==0)\n\t\t\t\t/*rhythm off to on*/\n\t\t\t\t{\n\t\t\t\t\t//logerror(\"YM2413: Rhythm mode enable\\n\");\n\n\t/* Load instrument settings for channel seven(chan=6 since we're zero based). (Bass drum) */\n\t\t\t\t\tchan = 6;\n\t\t\t\t\tinst = &chip->inst_tab[16][0];\n\t\t\t\t\tslot = chan*2;\n\n\t\t\t\t\tload_instrument(chip, chan, slot, inst);\n\n\t/* Load instrument settings for channel eight. (High hat and snare drum) */\n\t\t\t\t\tchan = 7;\n\t\t\t\t\tinst = &chip->inst_tab[17][0];\n\t\t\t\t\tslot = chan*2;\n\n\t\t\t\t\tload_instrument(chip, chan, slot, inst);\n\n\t\t\t\t\tCH   = &chip->P_CH[chan];\n\t\t\t\t\tSLOT = &CH->SLOT[SLOT1]; /* modulator envelope is HH */\n\t\t\t\t\tSLOT->TL  = (chip->instvol_r[chan] >> 4) << 2; /* 7 bits TL (bit 6 = always 0) */\n\t\t\t\t\tOPL_RegMapper(0x40 | SLOT2OPL[slot], SLOT->ksl | SLOT->TL);\n\n\t/* Load instrument settings for channel nine. (Tom-tom and top cymbal) */\n\t\t\t\t\tchan = 8;\n\t\t\t\t\tinst = &chip->inst_tab[18][0];\n\t\t\t\t\tslot = chan*2;\n\n\t\t\t\t\tload_instrument(chip, chan, slot, inst);\n\n\t\t\t\t\tCH   = &chip->P_CH[chan];\n\t\t\t\t\tSLOT = &CH->SLOT[SLOT1]; /* modulator envelope is TOM */\n\t\t\t\t\tSLOT->TL  = (chip->instvol_r[chan] >> 4) << 2; /* 7 bits TL (bit 6 = always 0) */\n\t\t\t\t\tOPL_RegMapper(0x40 | SLOT2OPL[slot], SLOT->ksl | SLOT->TL);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (chip->rhythm&0x20)\n\t\t\t\t/*rhythm on to off*/\n\t\t\t\t{\n\t\t\t\t\t//logerror(\"YM2413: Rhythm mode disable\\n\");\n\t/* Load instrument settings for channel seven(chan=6 since we're zero based).*/\n\t\t\t\t\tchan = 6;\n\t\t\t\t\tinst = &chip->inst_tab[chip->instvol_r[chan]>>4][0];\n\t\t\t\t\tslot = chan*2;\n\n\t\t\t\t\tload_instrument(chip, chan, slot, inst);\n\n\t/* Load instrument settings for channel eight.*/\n\t\t\t\t\tchan = 7;\n\t\t\t\t\tinst = &chip->inst_tab[chip->instvol_r[chan]>>4][0];\n\t\t\t\t\tslot = chan*2;\n\n\t\t\t\t\tload_instrument(chip, chan, slot, inst);\n\n\t/* Load instrument settings for channel nine.*/\n\t\t\t\t\tchan = 8;\n\t\t\t\t\tinst = &chip->inst_tab[chip->instvol_r[chan]>>4][0];\n\t\t\t\t\tslot = chan*2;\n\n\t\t\t\t\tload_instrument(chip, chan, slot, inst);\n\t\t\t\t}\n\t\t\t}\n\t\t\tchip->rhythm  = v&0x3f;\n\t\t\tOPL_RegMapper(0xBD, v & 0xFF);\n\t\t}\n\t\tbreak;\n\t\t}\n\t}\n\tbreak;\n\n\tcase 0x10:\n\tcase 0x20:\n\t{\n\t\tchan = r&0x0f;\n\n\t\tif (chan >= 9)\n\t\t\tchan -= 9;\t/* verified on real YM2413 */\n\n\t\tCH = &chip->P_CH[chan];\n\n\t\t// ((FM_OPL_Regs[0x10] & 0x00ff) | ((FM_OPL_Regs[0x20] & 0x01) << 8)) << 1;\n\t\tif(r&0x10)\n\t\t{\t/* 10-18: FNUM 0-7 */\n\t\t\tCH->fnum_lsb = (v & 0x7F) << 1;\n\t\t\tif (! CH->fnumlsb_null)\n\t\t\t\tOPL_RegMapper(0xA0 | chan, CH->fnum_lsb);\n\t\t\tif (CH->fnum_lmsb != ((v & 0x80) >> 7))\n\t\t\t{\n\t\t\t\tCH->fnum_lmsb = (v & 0x80) >> 7;\n\t\t\t\tOPL_RegMapper(0xB0 | chan, CH->fnum_lmsb | CH->fnum_msb |\n\t\t\t\t\t\t\t\tCH->block | CH->keyon | CH->sus);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\t/* 20-28: suson, keyon, block, FNUM 8 */\n\t\t\t//block_fnum = ((v&0x0f)<<8) | (CH->block_fnum&0xff);\n\t\t\tCH->fnum_msb = (v & 0x01) << 1;\n\t\t\tCH->block = (v & 0x0E) << 1;\n\t\t\tCH->keyon = (v & 0x10) << 1;\n\t\t\t\n\t\t\t// fixes a behaviour that causes a rumble because of Reg A0 being not 0\n\t\t\tfnln_old = CH->fnumlsb_null;\n\t\t\tCH->fnumlsb_null = (! CH->fnum_msb && ! CH->block);\n\t\t\tif (CH->fnumlsb_null != fnln_old)\n\t\t\t{\n\t\t\t\tOPL_RegMapper(0xA0 | chan, CH->fnumlsb_null ? 0x00 : CH->fnum_lsb);\n\t\t\t}\n\n\t\t\tCH->sus = (v & 0x20) << 1;\t// actually n/a on real OPL\n\t\t\t\n\t\t\tOPL_RegMapper(0xB0 | chan, CH->fnum_lmsb | CH->fnum_msb |\n\t\t\t\t\t\t\tCH->block | CH->keyon | CH->sus);\n\t\t}\n\t}\n\tbreak;\n\n\tcase 0x30:\t/* inst 4 MSBs, VOL 4 LSBs */\n\t{\n\t\tUINT8 old_instvol;\n\n\t\tchan = r&0x0f;\n\n\t\tif (chan >= 9)\n\t\t\tchan -= 9;\t/* verified on real YM2413 */\n\n\t\told_instvol = chip->instvol_r[chan];\n\t\tchip->instvol_r[chan] = v;\t/* store for later use */\n\n\t\tCH   = &chip->P_CH[chan];\n\t\tSLOT = &CH->SLOT[SLOT2]; /* carrier */\n\t\tSLOT->TL  = (chip->instvol_r[chan] & 0x0F) << 2;\n\t\t//SLOT->TL  = (chip->instvol_r[chan] & 0x0F) << 0;\n\t\tOPL_RegMapper(0x40 | SLOT2OPL[chan * 2 + SLOT2], SLOT->ksl | SLOT->TL);\n\n\t\t/*check wether we are in rhythm mode and handle instrument/volume register accordingly*/\n\t\tif ((chan>=6) && (chip->rhythm&0x20))\n\t\t{\n\t\t\t/* we're in rhythm mode*/\n\n\t\t\tif (chan>=7) /* only for channel 7 and 8 (channel 6 is handled in usual way)*/\n\t\t\t{\n\t\t\t\tSLOT = &CH->SLOT[SLOT1]; /* modulator envelope is HH(chan=7) or TOM(chan=8) */\n\t\t\t\tSLOT->TL  = (chip->instvol_r[chan] >> 4) << 2;\n\t\t\t\tOPL_RegMapper(0x40 | SLOT2OPL[chan * 2 + SLOT1], SLOT->ksl | SLOT->TL);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ( (old_instvol&0xf0) == (v&0xf0) )\n\t\t\t\treturn;\n\n\t\t\tinst = &chip->inst_tab[chip->instvol_r[chan]>>4][0];\n\t\t\tslot = chan*2;\n\n\t\t\tload_instrument(chip, chan, slot, inst);\n\n\t\t/*#if 0\n\t\t\tlogerror(\"YM2413: chan#%02i inst=%02i:  (r=%2x, v=%2x)\\n\",chan,v>>4,r,v);\n\t\t\tlogerror(\"  0:%2x  1:%2x\\n\",inst[0],inst[1]);\tlogerror(\"  2:%2x  3:%2x\\n\",inst[2],inst[3]);\n\t\t\tlogerror(\"  4:%2x  5:%2x\\n\",inst[4],inst[5]);\tlogerror(\"  6:%2x  7:%2x\\n\",inst[6],inst[7]);\n\t\t#endif*/\n\t\t}\n\t}\n\tbreak;\n\n\tdefault:\n\tbreak;\n\t}\n}\n\nstatic void OPLLWrite(YM2413 *chip,int a,int v)\n{\n\tif( !(a&1) )\n\t{\t/* address port */\n\t\tchip->address = v & 0xff;\n\t}\n\telse\n\t{\t/* data port */\n\t\tOPLLWriteReg2OPL(chip,chip->address,v);\n\t}\n}\n\nstatic void OPLLResetChip(YM2413 *chip)\n{\n\tint c,s;\n\tint i;\n\n\t// setup instruments table\n\tfor (i=0; i<19; i++)\n\t{\n\t\tfor (c=0; c<8; c++)\n\t\t{\n\t\t\tchip->inst_tab[i][c] = table[i][c];\n\t\t}\n\t}\n\n\n\t// reset with register write\n\tOPLLWriteReg2OPL(chip,0x0f,0); //test reg\n\tfor(i = 0x3f ; i >= 0x10 ; i-- )\n\t\tOPLLWriteReg2OPL(chip,i,0x00);\n\n\tchip->rhythm = 0;\n\tOPLLWriteReg2OPL(chip,0x0E,0x00);\n\t// reset operator parameters\n\tfor( c = 0 ; c < 9 ; c++ )\n\t{\n\t\tOPLL_CH_OPL *CH = &chip->P_CH[c];\n\t\t\n\t\tchip->instvol_r[c] = 0;\n\t\t\n\t\tCH->fnum_lsb = 0;\n\t\tCH->fnum_msb = 0;\n\t\tCH->block = 0;\n\t\tCH->keyon = 0;\n\t\tCH->sus = 0;\n\t\tCH->fnumlsb_null = 0;\n\t\tfor(s = 0 ; s < 2 ; s++ )\n\t\t{\n\t\t\tCH->SLOT[s].ar = 0;\n\t\t\tCH->SLOT[s].dr = 0;\n\t\t\tCH->SLOT[s].rr = 0;\n\t\t\tCH->SLOT[s].KSR = 0;\n\t\t\tCH->SLOT[s].ksl = 0;\n\t\t\tCH->SLOT[s].mul = 0;\n\t\t\t\n\t\t\tCH->SLOT[s].fb_shift = 0;\n\t\t\t\n\t\t\tCH->SLOT[s].eg_type = 0;\n\t\t\tCH->SLOT[s].TL = 0;\n\t\t\tCH->SLOT[s].sl = 0;\n\t\t\t\n\t\t\tCH->SLOT[s].AMmask = 0;\n\t\t\tCH->SLOT[s].vib = 0;\n\t\t\t\n\t\t\t// wave table\n\t\t\tCH->SLOT[s].wavetable = 0;\n\t\t}\n\t}\n}\n\nvoid start_ym2413_opl(UINT8 ChipID)\n{\n\tYM2413 *chip;\n\t\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn;\n\t\n\tchip = &YM2413Data[ChipID];\n\t\n\tOPLLResetChip(chip);\n\t\n\treturn;\n}\n\nvoid ym2413_w_opl(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\tYM2413 *chip = &YM2413Data[ChipID];\n\tOPLLWrite(chip, offset & 1, data);\n}\n"
  },
  {
    "path": "VGMPlay/chips/ym2413hd.c",
    "content": "/*-----------------------------------*/\n/* YM-2413 emulator using OPL        */\n/* (c) by Hiromitsu Shioya           */\n/* Modified by Omar Cornut           */\n/*-----------------------------------*/\n// added |0x30 to all Reg 0xC0 writes (else it doesn't sound on OPL3)\n\nvoid OPL_RegMapper(unsigned short int Reg, unsigned char Data);\n\n//#include \"shared.h\"\n#define MEKA_ERR_OK                     (0)\ntypedef unsigned char       byte;\ntypedef unsigned short      word;\ntypedef unsigned long       dword;\n\n#define UBYTE\tunsigned char\t// Unsigned byte (       $00 to $FF      )\n#define BYTE\tsigned char\t// Signed byte   (      -$80 to $7F      )\n#define UWORD\tunsigned short\t// Unsigned word (     $0000 to $FFFF    )\n#define ULONG\tunsigned int\t// Unsigned long ( $00000000 to $FFFFFFFF)\n#define CPTR\tunsigned int\t// 32-bit address pointer format\n\n#define FALSE\t0\n#define TRUE\t1\n\n#include \"ym2413hd.h\"\n \n#define Sound_OPL_Write\tOPL_RegMapper\n\n//-----------------------------------------------------------------------------\n// YM-2413 Instruments Table\n//-----------------------------------------------------------------------------\n// FIXME: Currently placed outside of the MEKA_OPL test, as it is being\n// used by the FM Editor.\n//-----------------------------------------------------------------------------\n\nstatic FM_OPL_Patch    FM_OPL_Patchs[YM2413_INSTRUMENTS] =\n{\n  /*KSL | MUL | AR  | SL  | EG  | DR  | RR  | TL  | KSR | WAVE| FB/CN  */\n  { 1, 0, 1, 1,15, 8, 9, 8, 0, 0, 1, 4,13,14,50,63, 0, 1, 0, 0, 4, 0,}, /*  0: User voice       */\n  { 0, 0, 1, 2,15,15,14,15, 1, 1, 0, 0, 8, 7,35,63, 1, 0, 0, 0, 7, 0,}, /*  1: Violin           */\n  { 1, 0, 3, 1,15, 7, 7, 9, 0, 1, 2, 4, 9,12,40,63, 0, 1, 0, 0, 5, 0,}, /*  2: Guitar           */\n  { 1, 0, 1, 1,15,13, 7, 7, 0, 0, 2, 2, 7,11,50,63, 0, 1, 0, 0, 4, 0,}, /*  3: Piano            */\n  { 1, 0, 4, 1,12,10,15,14, 1, 1, 0, 1, 8, 8,27,63, 0, 0, 0, 0, 5, 0,}, /*  4: Flute            */\n  { 1, 0, 4, 1,13,10,10,14, 1, 1, 2, 1, 7, 8,44,63, 0, 0, 0, 0, 3, 0,}, /*  5: Clarinet         */\n  { 2, 0, 1, 2,15,15,15,14, 1, 1, 1, 1, 4,14,58,63, 1, 0, 0, 0, 1, 0,}, /*  6: Oboe             */\n  { 0, 0, 1, 1,15,15,12, 9, 1, 1, 1, 1,14,11,40,63, 0, 0, 0, 0, 6, 0,}, /*  7: Trumpet          */\n  { 1, 0, 5, 1,15,15,15,15, 1, 1, 0, 0,15,13,32,63, 0, 0, 0, 0, 0, 0,}, /*  8: Organ            */\n  { 0, 0, 0, 1, 8,15, 7, 9, 1, 1, 5, 1, 9,13,43,63, 0, 0, 0, 0, 6, 0,}, /*  9: Tube             */\n  { 2, 0, 1, 1, 5, 6, 5,10, 1, 1, 3, 2,14,15,63,63, 1, 0, 1, 0, 2, 0,}, /* 10: Synthesizer      */\n  { 1, 0, 3, 1,13,10, 9,11, 0, 1, 4, 3, 4,14,48,63, 0, 0, 1, 0, 7, 0,}, /* 11: Harpsicode       */\n  { 2, 0,11, 1,15, 9,11,10, 1, 1, 6, 3,13,12,36,63, 0, 0, 0, 0, 7, 0,}, /* 12: Vibraphone       */\n  { 2, 0, 1, 3, 7,15,12,14, 1, 1, 7, 1, 7, 8,45,63, 0, 0, 0, 0, 7, 0,}, /* 13: Synth bass       */\n  { 0, 0, 1, 1,15,14,11,13, 1, 1, 3, 2, 6, 9,42,63, 0, 0, 0, 0, 3, 0,}, /* 14: Wood bass        */\n  { 0, 0, 1, 3,15,14,11,13, 1, 1, 3, 2, 6, 9,55,63, 0, 0, 0, 0, 3, 0,}, /* 15: Electric bass    */\n};\n\nstatic int     vcref[9] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };\nstatic int     vlref[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\nstatic word    fref[9];\n\n//-----------------------------------------------------------------------------\n\n//#ifdef MEKA_OPL\n\n//-----------------------------------------------------------------------------\n// Variables\n//-----------------------------------------------------------------------------\n\nstatic int                     FM_OPL_Initialized = FALSE;\n/*t_fm_unit_interface     FM_OPL_Interface =\n{\n  \"YM-2413 OPL Emulator\",\n  \"Hiromitsu Shioya & Omar Cornut\",\n  FM_OPL_Reset,\n  FM_OPL_Write,\n  FM_OPL_Mute,\n  FM_OPL_Resume,\n  FM_OPL_Regenerate\n};*/\n\n//-----------------------------------------------------------------------------\n// Delayed writes stuff\n//-----------------------------------------------------------------------------\n\n//#define DELAY_BUFFER_MAX        (60*3) /* max 3second */\n//#define DELAY_STOCK_MAX         (DELAY_BUFFER_MAX * 64)\n\n/*typedef struct delay_rec\n{\n  BYTE  reg;\n  BYTE  data;\n} DelayRec;*/\n\n/*unsigned int    fm_delay_size = 6;\nunsigned int    fm_write_d, fm_update_d;\nunsigned int    delay_point[DELAY_BUFFER_MAX];\nunsigned int    w_delay;\nDelayRec        delay_chip[DELAY_STOCK_MAX];*/\n\nstatic int     fmVol[YM2413_VOLUME_STEPS] =\n{\n#if 0\n  0x00, 0x01, 0x02, 0x03, 0x04, 0x06, 0x08, 0x0a,\n  0x0c, 0x10, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3f\n#else\n  0x00, 0x03, 0x06, 0x03, 0x09, 0x0c, 0x0f, 0x12,\n  0x15, 0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a\n#endif\n};\n\n//-----------------------------------------------------------------------------\n// FM_OPL_Init ()\n// Initialize emulation (FIXME: not really necessary this way ?)\n//-----------------------------------------------------------------------------\nint     FM_OPL_Init (void *userdata /* unused */)\n{\n  //ConsolePrintf (\"%s \", Msg_Get (MSG_Sound_Init_YM2413_OPL));\n\n  FM_OPL_Reset ();\n  FM_OPL_Initialized = TRUE;\n\n  //ConsolePrintf (\"%s\\n\", Msg_Get (MSG_Ok));\n  return (MEKA_ERR_OK);\n}\n\n//-----------------------------------------------------------------------------\n// FM_OPL_Close()\n// Close emulation (actually only mute)\n//-----------------------------------------------------------------------------\nvoid    FM_OPL_Close (void)\n{\n  if (FM_OPL_Initialized)\n     {\n     //FM_OPL_Mute ();\n     // FM_OPL_Reset ();\n     }\n}\n\n//-----------------------------------------------------------------------------\n// FM_OPL_Active()\n// Active this engine as being the current FM interface to use\n//-----------------------------------------------------------------------------\n/*void    FM_OPL_Active (void)\n{\n  FM_Set_Interface (&FM_OPL_Interface, FM_OPL_Regs);\n}*/\n\n//-----------------------------------------------------------------------------\n// FM_OPL_Reset()\n// Reset emulated YM-2413\n//-----------------------------------------------------------------------------\nvoid    FM_OPL_Reset (void)\n{\n  int    i;\n\n  // printf(\"...OPL addr= %x\\n\", Sound.OPL_Address);\n\n  // Clear all OPL registers\n  // already done by global Chip Mapper\n  /*for (i = 0; i < 255; i++)\n      Sound_OPL_Write (i, 0x00);\n  Sound_OPL_Write (0x01, 0x20);*/\n  // Sound_OPL_Write (0xBD, 0x28);\n\n  // Set all YM-2413 registers to zero\n  for (i = 0; i < YM2413_REGISTERS; i++)\n      FM_OPL_Regs[i] = 0x00;\n\n  // Initialize delayed update system\n  /*fm_write_d = fm_update_d = 0;\n  w_delay = 0;\n  for (i = 0; i < DELAY_BUFFER_MAX; i++)\n      delay_point[i] = 0;*/\n\n  // Initialize volume & voices\n  for (i = 0; i < 9; i++)\n      {\n      vcref[i] = 0xff;\n      vlref[i] = 0;\n      }\n\n  Sound_OPL_Write (0xbd, 0x00);\n  for (i = 0; i < 3; i++)\n      {\n      Sound_OPL_Write(0x20 + i, 0x01);    Sound_OPL_Write(0x23 + i, 0x01);\n      Sound_OPL_Write(0x40 + i, 0x3f);    Sound_OPL_Write(0x43 + i, 0x3f);\n      Sound_OPL_Write(0x60 + i, 0xf0);    Sound_OPL_Write(0x63 + i, 0xf0);\n      Sound_OPL_Write(0x80 + i, 0xff);    Sound_OPL_Write(0x83 + i, 0xff);\n      Sound_OPL_Write(0xc0 + i, 0x00 | 0x30);\n\n      Sound_OPL_Write(0x28 + i, 0x01);    Sound_OPL_Write(0x2b + i, 0x01);\n      Sound_OPL_Write(0x48 + i, 0x3f);    Sound_OPL_Write(0x4b + i, 0x3f);\n      Sound_OPL_Write(0x68 + i, 0xf0);    Sound_OPL_Write(0x6b + i, 0xf0);\n      Sound_OPL_Write(0x88 + i, 0xff);    Sound_OPL_Write(0x8b + i, 0xff);\n      Sound_OPL_Write(0xc3 + i, 0x00 | 0x30);\n\n      Sound_OPL_Write(0x30 + i, 0x21);    Sound_OPL_Write(0x33 + i, 0x21);\n      Sound_OPL_Write(0x50 + i, 0x3f);    Sound_OPL_Write(0x53 + i, 0x3f);\n      Sound_OPL_Write(0x70 + i, 0xf0);    Sound_OPL_Write(0x73 + i, 0xf0);\n      Sound_OPL_Write(0x90 + i, 0xf0);    Sound_OPL_Write(0x93 + i, 0xf0);\n      Sound_OPL_Write(0xc6 + i, 0x00 | 0x30);\n      }\n\n  // Sound_OPL_Write (0x01, 0x20);\n}\n\n//-----------------------------------------------------------------------------\n// FM_OPL_Mute()\n// Mute FM Sound by setting all OPL volumes to zero\n//-----------------------------------------------------------------------------\n/*void    FM_OPL_Mute (void)\n{\n  int    i;\n\n  // Msg (MSGT_DEBUG, __FUNCTION__);\n  for (i = 0; i < 9; i++)\n      {\n      // Clear bit 5 of all channels (makes voice silent)\n      Sound_OPL_Write (0xb0 + i, 0x00);\n      //\n      //int vl = vlref[i];\n      //FM_OPL_Set_Voice (i, 0xff, 0x3f); // All sounds off.\n      //vlref[i] = vl;\n      //\n      }\n}*/\n\n//-----------------------------------------------------------------------------\n// FM_OPL_Resume()\n// Resume FM Sound AFTER muting\n//-----------------------------------------------------------------------------\n/*void    FM_OPL_Resume (void)\n{\n  int    i, oldv;\n  int    n_channels;\n\n  // 6 or 9 channels -----------------------------------------------------------\n  n_channels = (FM_OPL_Rhythm_Mode ? 6 : 9);\n  for (i = 0; i < n_channels; i++)\n      {\n      oldv = vcref[i];\n      vcref[i] = 0xff;\n      FM_OPL_Set_Voice (i, oldv, vlref[i]);\n      Sound_OPL_Write (0xa0 + i, fref[i] & 0xff);\n      Sound_OPL_Write (0xb0 + i, ((fref[i] >> 8) & 0x1f) | ((FM_OPL_Regs[0x20 + i] & 0x10) << 1));\n      }\n  // 3 Rythmic channels (if enabled) -------------------------------------------\n  if (FM_OPL_Rhythm_Mode)\n     {\n     for (i = 6; i < 9; i++)\n         {\n         Sound_OPL_Write (0xa0 + i, fref[i] & 0xff);\n         Sound_OPL_Write (0xb0 + i, (fref[i] >> 8) & 0x1f);\n         }\n     Sound_OPL_Write (0x53, fmVol[FM_OPL_Regs[0x36] & 0x0f]);        // Bass drum\n     Sound_OPL_Write (0x51, fmVol[(FM_OPL_Regs[0x37] >> 4) & 0x0f]); // Hi-hat\n     Sound_OPL_Write (0x54, fmVol[FM_OPL_Regs[0x37] & 0x0f]);        // Snare\n     Sound_OPL_Write (0x52, fmVol[(FM_OPL_Regs[0x38] >> 4) & 0x0f]); // Tomtom\n     Sound_OPL_Write (0x55, fmVol[FM_OPL_Regs[0x38] & 0x0f]);        // Top Cymbal\n     }\n}*/\n\n//-----------------------------------------------------------------------------\n// FM_OPL_Regenerate()\n// Regenerate various data from YM-2413 registers\n// This is called after a state loading\n//-----------------------------------------------------------------------------\n/*void    FM_OPL_Regenerate (void)\n{\n  int    i;\n\n  // Initialize delayed update system\n  fm_write_d = fm_update_d = 0;\n  w_delay = 0;\n  for (i = 0; i < DELAY_BUFFER_MAX; i++)\n      delay_point[i] = 0;\n\n  // Rewrite all registers\n  for (i = 0; i < YM2413_REGISTERS; i++)\n     {\n     FM_OPL_Write (i, FM_OPL_Regs[i]);\n     }\n}*/\n\n/*******************************************************************/\n/*    FM voice set                                                 */\n/*    note : YM3812 register map                                   */\n/*                                                                 */\n/*   9 voices map                                                  */\n/*   | 0  | 1  | 2  | 3  | 4  | 5  | 6  | 7  | 8  |                */\n/*   ----------------------------------------------                */\n/*   | 00 | 01 | 02 | 08 | 09 | 0a | 10 | 11 | 12 |                */\n/*   | 03 | 04 | 05 | 0b | 0c | 0d | 13 | 14 | 15 |                */\n/*                                                                 */\n/*   6 voices & 5 rhythm map                                       */\n/*   | 0  | 1  | 2  | 3  | 4  | 5  || BD | HH | TOM| SD | CYM|     */\n/*   ---------------------------------------------------------     */\n/*   | 00 | 01 | 02 | 08 | 09 | 0a || 10 | 11 | 12 | 14 | 15 |     */\n/*   | 03 | 04 | 05 | 0b | 0c | 0d || 13 |    |    |    |    |     */\n/*                                                                 */\n/*   BD=Bass drum, HH=HiHat, TOM=Tomtom, SD=Snare drum             */\n/*   CYM=Cymbal                                                    */\n/*******************************************************************/\nvoid            FM_OPL_Set_Voice (int R, int V, int VL)\n{\n  int           R2;\n  FM_OPL_Patch *patch;\n\n  R2 = R;\n  R = (R % 3) + ((R / 3) * 0x08);\n  V &= 0xff;\n  patch = &FM_OPL_Patchs[vcref[R2]];\n  vlref[R2] = VL & 0x3f;\n  if (V != 0xff)\n     {\n     if ((V == 0) || (vcref[R2] != V))\n        {\n        vcref[R2] = V;\n        patch = &FM_OPL_Patchs[V];\n        Sound_OPL_Write(0x20 + R, (patch->MS <<5) | (patch->MEV<<4) | patch->MML);\n        Sound_OPL_Write(0x60 + R, (patch->MA <<4) | patch->MD);\n        Sound_OPL_Write(0x80 + R, (patch->MSL<<4) | patch->MR);\n        Sound_OPL_Write(0xe0 + R, patch->MW);\n        Sound_OPL_Write(0x23 + R, (patch->CS <<5) | (patch->CEV<<4) | patch->CML);\n        Sound_OPL_Write(0x63 + R, (patch->CA <<4) | patch->CD);\n        Sound_OPL_Write(0x83 + R, (patch->CSL<<4) | patch->CR);\n        Sound_OPL_Write(0xe3 + R, patch->CW);\n        Sound_OPL_Write(0xc0 + R2, (patch->FB<<1) | patch->CON | 0x30);\n        Sound_OPL_Write(0x40 + R, (0x3f - patch->MTL) | (patch->MKS<<6));\n        }\n     }\n  Sound_OPL_Write(0x43 + R, (patch->CKS << 6) | vlref[R2]);\n}\n\n/***********************************************/\n/* check use user-voice & set                  */\n/***********************************************/\nvoid    FM_OPL_Set_User_Voice (void)\n{\n  int   c, lpmax;\n\n  lpmax = (FM_OPL_Rhythm_Mode) ? 6 : 9;\n  for (c = 0; c < lpmax; c ++)\n      {\n      if (!vcref[c])\n         FM_OPL_Set_Voice (c, 0, vlref[c]);\n      // if( !vcref[c] )  vcref[c] = 0xff; /* set direct write */\n      }\n}\n\n//-----------------------------------------------------------------------------\n// FM_OPL_Update()\n// Update audio stream with the delayed writes\n// This is periodically (~1/60th second) called by the sound engine\n//-----------------------------------------------------------------------------\n/*void    FM_OPL_Update (void)\n{\n  unsigned int i;\n  unsigned int start, end, stock;\n\n  if (fm_delay_size)\n     {\n     i = fm_write_d - fm_update_d;\n     fm_write_d++;\n     if (i < fm_delay_size)\n        {\n        delay_point[(fm_write_d+1) % DELAY_BUFFER_MAX] = delay_point[fm_write_d];\n        return;\n        }\n     start = delay_point[fm_update_d % DELAY_BUFFER_MAX];\n     fm_update_d++;\n     end   = delay_point[fm_update_d % DELAY_BUFFER_MAX];\n     stock = fm_delay_size;\n     fm_delay_size = 0;\n     // Message( MESSAGE_DEBUG, \" now delay write %d %d (%d)[%d]\", start, end, end - start, fm_update_d );\n     // printf( \" now delay write %d %d (%d)[%d]\\n\", start, end, end - start, fm_update_d );\n     if (end >= start)\n        {\n        for (i = start; i < end; i++)\n            FM_OPL_Write (delay_chip[i % DELAY_STOCK_MAX].reg & 0x3f, delay_chip[i % DELAY_STOCK_MAX].data & 0xff);\n        }\n     #if 0\n     else\n        {\n        printf(\" ??? %d %d (%d)[%d]\\n\", start, end, end - start, fm_update_d);\n        }\n     #endif\n     fm_delay_size = stock;\n     fm_write_d  %= DELAY_BUFFER_MAX;\n     fm_update_d %= DELAY_BUFFER_MAX;\n     delay_point[(fm_write_d + 1) % DELAY_BUFFER_MAX] = delay_point[fm_write_d];\n     }\n}*/\n\n//-----------------------------------------------------------------------------\n// FM_OPL_Write()\n// Port write to the YM-2413\n//-----------------------------------------------------------------------------\nvoid    FM_OPL_Write (int R, int V)\n{\n  int   Freq, c;\n  int   F;\n  int   Previous_Register;\n  FM_OPL_Patch *patch = &FM_OPL_Patchs[0];\n\n  // FIXME: is the first test necessary ?\n  // Note: the second is necessary, when an FM_OPL_Update() is called by the\n  // sound engine, while the FM emulator has already been switched to another!\n  /*if (FM_OPL_Initialized == FALSE || Sound.FM_Emulator_Current != FM_EMULATOR_YM2413HD)\n     {\n     FM_OPL_Regs[R] = V;\n     return;\n     }\n\n  if (fm_delay_size)\n     {\n     delay_chip[w_delay].reg  = (BYTE)R;\n     delay_chip[w_delay].data = (BYTE)V;\n     w_delay = (w_delay + 1) % DELAY_STOCK_MAX;\n     delay_point[(fm_write_d+1) % DELAY_BUFFER_MAX] = w_delay;\n     // printf( \"%d = %d\\n\", fm_write_d+1, delay_point[(fm_write_d+1)%DELAY_BUFFER_MAX] );\n     return;\n     }*/\n\n  Previous_Register = FM_OPL_Regs[R];\n  FM_OPL_Regs[R] = V;\n\n  switch (R)\n     {\n     /**** user voice set ****/\n     case 0x00:\n       patch->MML = V&0x0f;    patch->MS  = (V>>5)&0x01;    patch->MEV = (V>>4)&0x01;\n       FM_OPL_Set_User_Voice ();\n       return;\n     case 0x01:\n       patch->CML = V&0x0f;    patch->CS  = (V>>5)&0x01;    patch->CEV = (V>>4)&0x01;\n       FM_OPL_Set_User_Voice ();\n       return;\n     case 0x02:\n       patch->MTL = 0x3f - (V&0x3f);    patch->MKS = (V>>6)&0x03;\n       FM_OPL_Set_User_Voice ();\n       return;\n     case 0x03:\n       patch->FB  = V&0x07;             patch->MW  = (V>>4)&0x01;\n       patch->CW  = (V>>3)&0x01;        patch->MKS = (V>>6)&0x03;\n       FM_OPL_Set_User_Voice ();\n       return;\n     case 0x04:\n       patch->MA = (V>>4)&0x0f;         patch->MD = V&0x0f;\n       FM_OPL_Set_User_Voice ();\n       return;\n     case 0x05:\n       patch->CA = (V>>4)&0x0f;         patch->CD = V&0x0f;\n       FM_OPL_Set_User_Voice ();\n       return;\n     case 0x06:\n       patch->MSL = (V>>4)&0x0f;        patch->MR  = V&0x0f;\n       FM_OPL_Set_User_Voice ();\n       return;\n     case 0x07:\n       patch->CSL = (V>>4)&0x0f;        patch->CR  = V&0x0f;\n       FM_OPL_Set_User_Voice ();\n       return;\n     case 0x0e:\n       /**** rhythm select ****/\n       if (FM_OPL_Rhythm_Mode)\n          {\n          // If it was previously desactived, setup OPL instruments\n          if ((Previous_Register & 0x20) == 0x00)\n             {\n             for (c = 0; c < 3; c++)\n                 {\n                 Sound_OPL_Write (0xf0 + c, 0x00);    Sound_OPL_Write (0xf3 + c, 0x00);\n                 Sound_OPL_Write (0xc6 + c, 0x00 | 0x30);\n                 }\n             Sound_OPL_Write (0x70, 0xf0);    Sound_OPL_Write (0x73, 0xf0);\n             Sound_OPL_Write (0x71, 0xf0);    Sound_OPL_Write (0x74, 0xf0);\n             Sound_OPL_Write (0x72, 0xf0);    Sound_OPL_Write (0x75, 0xf0);\n\n             Sound_OPL_Write (0x30, 0x00);    Sound_OPL_Write (0x33, 0x01); /* bass */\n             Sound_OPL_Write (0x31, 0x01);    Sound_OPL_Write (0x34, 0x01); /* hi-hat/snare */\n             Sound_OPL_Write (0x32, 0x01);    Sound_OPL_Write (0x35, 0x01); /* tom/cymbal */\n\n             if (!(FM_OPL_Regs[0x26] & 0x20))\n                {\n                Sound_OPL_Write (0x90, 0x07);    Sound_OPL_Write (0x93, 0x07);\n                }\n             else\n                {\n                Sound_OPL_Write (0x90, 0x04);    Sound_OPL_Write (0x93, 0x04);\n                }\n             if (!(FM_OPL_Regs[0x27] & 0x20))\n                {\n                Sound_OPL_Write (0x91, 0x07);    Sound_OPL_Write (0x94, 0x07);\n                }\n             else\n                {\n                Sound_OPL_Write (0x91, 0x04);    Sound_OPL_Write (0x94, 0x04);\n                }\n             if (!(FM_OPL_Regs[0x28] & 0x20))\n                {\n                Sound_OPL_Write (0x92, 0x06);    Sound_OPL_Write (0x95, 0x06);\n                }\n             else\n                {\n                Sound_OPL_Write (0x92, 0x04);    Sound_OPL_Write (0x95, 0x04);\n                }\n             Sound_OPL_Write (0x50, 0x0f);                                  Sound_OPL_Write (0x53, fmVol[FM_OPL_Regs[0x36]&0x0f] >> 1);\n             Sound_OPL_Write (0x51, fmVol[(FM_OPL_Regs[0x37]>>4)&0x0f]);    Sound_OPL_Write (0x54, fmVol[FM_OPL_Regs[0x37]&0x0f]);\n             Sound_OPL_Write (0x52, fmVol[(FM_OPL_Regs[0x38]>>4)&0x0f]);    Sound_OPL_Write (0x55, fmVol[FM_OPL_Regs[0x38]&0x0f]);\n\n             Sound_OPL_Write (0xa6, fref[6]&0xff);    Sound_OPL_Write (0xb6, (fref[6]>>8) & 0x1f);\n             Sound_OPL_Write (0xa7, fref[7]&0xff);    Sound_OPL_Write (0xb7, (fref[7]>>8) & 0x1f);\n             Sound_OPL_Write (0xa8, fref[8]&0xff);    Sound_OPL_Write (0xb8, (fref[8]>>8) & 0x1f);\n             }\n          }\n       Sound_OPL_Write (0xbd, V);\n       return;\n     }\n\n  if (R >= 0x10 && R <= 0x28)\n     {\n     /**** Freq. set ****/\n     F = R & 0x0f;\n     Freq = (((int)FM_OPL_Regs[0x10+F] & 0x00ff) | (((int)FM_OPL_Regs[0x20+F] & 0x01) << 8)) << 1;\n     c = (FM_OPL_Regs[0x20+F] >> 1) & 0x0007;\n     if (FM_OPL_Regs[0x20+F] & 0x10) fref[F] = Freq | (c << 10) | 0x2000;\n     else                            fref[F] = Freq | (c << 10);\n     Sound_OPL_Write (0xa0+F, fref[F] & 0xff);\n     Sound_OPL_Write (0xb0+F, (fref[F] >> 8) & 0xff);\n     return;\n     }\n\n  if (R >= 0x30 && R < 0x36)\n     {\n     /**** set voice&volume (ch0-ch5) ****/\n     FM_OPL_Set_Voice (R & 0x0f, (V >> 4) & 0x0f, fmVol[V & 0x0f]);\n     return;\n     }\n\n  if (R >= 0x36 && R <= 0x38)\n     {\n     /**** set voice & volume (ch6-8 or rhythm) ****/\n     if (!FM_OPL_Rhythm_Mode)\n        {\n        FM_OPL_Set_Voice (R & 0x0f, (V >> 4) & 0x0f, fmVol[V & 0x0f]);\n        return;\n        }\n     switch (R & 0x0f)\n       {\n       case 6:\n         Sound_OPL_Write (0x53, fmVol[V&0x0f]>>1);           /* bass drum */\n         break;\n       case 7:\n         Sound_OPL_Write (0x51, fmVol[(V>>4)&0x0f]);         /* hi-hat */\n         Sound_OPL_Write (0x54, fmVol[V&0x0f]);              /* snare  */\n         break;\n       case 8:\n         Sound_OPL_Write (0x52, fmVol[(V>>4)&0x0f]);         /* tomtom */\n         Sound_OPL_Write (0x55, fmVol[V&0x0f]);              /* top cymbal */\n         break;\n       }\n     }\n}\n\n//-----------------------------------------------------------------------------\n\n//#endif // MEKA_OPL\n\n"
  },
  {
    "path": "VGMPlay/chips/ym2413hd.h",
    "content": "/*-----------------------------------*/\n/* YM-2413 emulator using OPL        */\n/* (c) by Hiromitsu Shioya           */\n/* Modified by Omar Cornut           */\n/*-----------------------------------*/\n\n//#ifndef __YM2413HD_H__\n//#define __YM2413HD_H__\n#define YM2413_REGISTERS        (64)    // 64 registers area \n#define YM2413_INSTRUMENTS      (16)    // 16 instruments (0 is user defined)\n#define YM2413_VOLUME_STEPS     (16)    // 16 different volume steps\n#define YM2413_VOLUME_MASK      (0x0F)\n\n//-----------------------------------------------------------------------------\n// Instrument Data\n//-----------------------------------------------------------------------------\n// FIXME: Currently placed outside of the MEKA_OPL test, as it is being\n// used by the FM Editor.\n//-----------------------------------------------------------------------------\n\ntypedef struct\n{\n  unsigned char MKS, CKS;       /* KSL                   */\n  unsigned char MML, CML;       /* MULTIPLE              */\n  unsigned char MA,  CA;        /* ATTACK RATE           */\n  unsigned char MSL, CSL;       /* SUSTAIN LEVEL         */\n  unsigned char MS,  CS;        /* EG                    */\n  unsigned char MD,  CD;        /* DECAY RATE            */\n  unsigned char MR,  CR;        /* RELEASE RATE          */\n  unsigned char MTL, CTL;       /* TOTAL LEVEL           */\n  unsigned char MEV, CEV;       /* KSR                   */\n  unsigned char MW,  CW;        /* WAVE FORM             */\n  unsigned char FB,  CON;       /* FEEDBACK / Connection */\n} FM_OPL_Patch;\n\n//-----------------------------------------------------------------------------\n\n//#ifdef MEKA_OPL\n\n//-----------------------------------------------------------------------------\n\n// Registers\nbyte    FM_OPL_Regs [YM2413_REGISTERS];\n#define FM_OPL_Rhythm_Mode (FM_OPL_Regs [0x0E] & 0x20)\n\n// Functions\nint     FM_OPL_Init             (void *userdata);\nvoid    FM_OPL_Close            (void);\n//void    FM_OPL_Active           (void);\nvoid    FM_OPL_Update           (void);\nvoid    FM_OPL_Set_Voice        (int R, int V, int VL);\nvoid    FM_OPL_Set_User_Voice   (void);\n\n// Interface (see FMUNIT.C/.H)\nvoid    FM_OPL_Reset            (void);\nvoid    FM_OPL_Write            (int Register, int Value);\n//void    FM_OPL_Mute             (void);\n//void    FM_OPL_Resume           (void);\n//void    FM_OPL_Regenerate       (void);\n\n//-----------------------------------------------------------------------------\n\n/*#else\n\n// A fake set of registers is created as sound/fmunit.c reference it.\n// FIXME: This sucks.\nbyte    FM_OPL_Regs [YM2413_REGISTERS];\n\n#endif*/\n\n//#endif /* !__YM2413HD_H__ */\n\n"
  },
  {
    "path": "VGMPlay/chips/ym2612.c",
    "content": "/***********************************************************/\n/*                                                         */\n/* YM2612.C : YM2612 emulator                              */\n/*                                                         */\n/* Almost constantes are taken from the MAME core          */\n/*                                                         */\n/* This source is a part of Gens project                   */\n/* Written by Stphane Dallongeville (gens@consolemul.com) */\n/* Copyright (c) 2002 by Stphane Dallongeville            */\n/*                                                         */\n/***********************************************************/\n\n/***********************************************************/\n/*                                                         */\n/* Modified by Maxim, Blargg                               */\n/* - removed non-sound-related functionality               */\n/* - added high-pass PCM filter                            */\n/* - added per-channel muting control                      */\n/* - made it use a context struct to allow multiple        */\n/*   instances                                             */\n/*                                                         */\n/***********************************************************/\n\n#include <stdlib.h> // for malloc\n#include <stdio.h>\n#include <math.h>\n#include <string.h> // for memset()\n#include \"mamedef.h\"\t// for correct INLINE macro\n#include \"ym2612.h\"\n\n\n#ifdef __GNUC__\n#pragma GCC diagnostic ignored \"-Wparentheses\"\n#pragma GCC diagnostic ignored \"-Wpointer-sign\"\n#endif\n\n/********************************************\n *            Partie dfinition             *\n ********************************************/\n\n#define YM_DEBUG_LEVEL 0\n\n#ifndef PI\n#define PI 3.14159265358979323846\n#endif\n\n#define ATTACK    0\n#define DECAY     1\n#define SUBSTAIN  2\n#define RELEASE   3\n\n// SIN_LBITS <= 16\n// LFO_HBITS <= 16\n// (SIN_LBITS + SIN_HBITS) <= 26\n// (ENV_LBITS + ENV_HBITS) <= 28\n// (LFO_LBITS + LFO_HBITS) <= 28\n\n#define SIN_HBITS      12                // Sinus phase counter int part\n#define SIN_LBITS      (26 - SIN_HBITS)          // Sinus phase counter float part (best setting)\n\n#if(SIN_LBITS > 16)\n#define SIN_LBITS      16                // Can't be greater than 16 bits\n#endif\n\n#define ENV_HBITS      12                // Env phase counter int part\n#define ENV_LBITS      (28 - ENV_HBITS)          // Env phase counter float part (best setting)\n\n#define LFO_HBITS      10                // LFO phase counter int part\n#define LFO_LBITS      (28 - LFO_HBITS)          // LFO phase counter float part (best setting)\n\n#define SIN_LENGHT     (1 << SIN_HBITS)\n#define ENV_LENGHT     (1 << ENV_HBITS)\n#define LFO_LENGHT     (1 << LFO_HBITS)\n\n#define TL_LENGHT      (ENV_LENGHT * 3)          // Env + TL scaling + LFO\n\n#define SIN_MASK       (SIN_LENGHT - 1)\n#define ENV_MASK       (ENV_LENGHT - 1)\n#define LFO_MASK       (LFO_LENGHT - 1)\n\n#define ENV_STEP       (96.0 / ENV_LENGHT)        // ENV_MAX = 96 dB\n\n#define ENV_ATTACK     ((ENV_LENGHT * 0) << ENV_LBITS)\n#define ENV_DECAY      ((ENV_LENGHT * 1) << ENV_LBITS)\n#define ENV_END        ((ENV_LENGHT * 2) << ENV_LBITS)\n\n#define MAX_OUT_BITS   (SIN_HBITS + SIN_LBITS + 2)    // Modulation = -4 <--> +4\n#define MAX_OUT        ((1 << MAX_OUT_BITS) - 1)\n\n//Just for tests stuff...\n//\n//#define COEF_MOD       0.5\n//#define MAX_OUT        ((int) (((1 << MAX_OUT_BITS) - 1) * COEF_MOD))\n\n#define OUT_BITS       (OUTPUT_BITS - 2)\n#define OUT_SHIFT      (MAX_OUT_BITS - OUT_BITS)\n#define LIMIT_CH_OUT   ((int) (((1 << OUT_BITS) * 1.5) - 1))\n\n#define PG_CUT_OFF     ((int) (78.0 / ENV_STEP))\n#define ENV_CUT_OFF    ((int) (68.0 / ENV_STEP))\n\n#define AR_RATE        399128\n#define DR_RATE        5514396\n\n//#define AR_RATE        426136\t\t\t// good rate ?\n//#define DR_RATE        (AR_RATE * 12)\n\n#define LFO_FMS_LBITS  9  // FIXED (LFO_FMS_BASE gives somethink as 1)\n#define LFO_FMS_BASE   ((int) (0.05946309436 * 0.0338 * (double) (1 << LFO_FMS_LBITS)))\n\n#define S0             0  // Stupid typo of the YM2612\n#define S1             2\n#define S2             1\n#define S3             3\n\n\n/********************************************\n *            Partie variables              *\n ********************************************/\n\n\n//struct ym2612__ YM2612;\n\nint *SIN_TAB[SIN_LENGHT];          // SINUS TABLE (pointer on TL TABLE)\nint TL_TAB[TL_LENGHT * 2];          // TOTAL LEVEL TABLE (positif and minus)\nunsigned int ENV_TAB[2 * ENV_LENGHT + 8];  // ENV CURVE TABLE (attack & decay)\n\n//unsigned int ATTACK_TO_DECAY[ENV_LENGHT];  // Conversion from attack to decay phase\nunsigned int DECAY_TO_ATTACK[ENV_LENGHT];  // Conversion from decay to attack phase\n\nunsigned int FINC_TAB[2048];        // Frequency step table\n\nunsigned int AR_TAB[128];          // Attack rate table\nunsigned int DR_TAB[96];          // Decay rate table\nunsigned int DT_TAB[8][32];          // Detune table\nunsigned int SL_TAB[16];          // Substain level table\nunsigned int NULL_RATE[32];          // Table for NULL rate\n\nint LFO_ENV_TAB[LFO_LENGHT];        // LFO AMS TABLE (adjusted for 11.8 dB)\nint LFO_FREQ_TAB[LFO_LENGHT];        // LFO FMS TABLE\n\n// int INTER_TAB[MAX_UPDATE_LENGHT];      // Interpolation table\n\nint LFO_INC_TAB[8];              // LFO step table\n\nvoid (* const UPDATE_CHAN[8 * 8])(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght) =    // Update Channel functions pointer table\n{\n  Update_Chan_Algo0,\n  Update_Chan_Algo1,\n  Update_Chan_Algo2,\n  Update_Chan_Algo3,\n  Update_Chan_Algo4,\n  Update_Chan_Algo5,\n  Update_Chan_Algo6,\n  Update_Chan_Algo7,\n\n  Update_Chan_Algo0_LFO,\n  Update_Chan_Algo1_LFO,\n  Update_Chan_Algo2_LFO,\n  Update_Chan_Algo3_LFO,\n  Update_Chan_Algo4_LFO,\n  Update_Chan_Algo5_LFO,\n  Update_Chan_Algo6_LFO,\n  Update_Chan_Algo7_LFO,\n\n  Update_Chan_Algo0_Int,\n  Update_Chan_Algo1_Int,\n  Update_Chan_Algo2_Int,\n  Update_Chan_Algo3_Int,\n  Update_Chan_Algo4_Int,\n  Update_Chan_Algo5_Int,\n  Update_Chan_Algo6_Int,\n  Update_Chan_Algo7_Int,\n\n  Update_Chan_Algo0_LFO_Int,\n  Update_Chan_Algo1_LFO_Int,\n  Update_Chan_Algo2_LFO_Int,\n  Update_Chan_Algo3_LFO_Int,\n  Update_Chan_Algo4_LFO_Int,\n  Update_Chan_Algo5_LFO_Int,\n  Update_Chan_Algo6_LFO_Int,\n  Update_Chan_Algo7_LFO_Int\n};\n\nvoid (* const ENV_NEXT_EVENT[8])(slot_ *SL) =    // Next Enveloppe phase functions pointer table\n{\n  Env_Attack_Next,\n  Env_Decay_Next,\n  Env_Substain_Next,\n  Env_Release_Next,\n  Env_NULL_Next,\n  Env_NULL_Next,\n  Env_NULL_Next,\n  Env_NULL_Next\n};\n\nconst unsigned int DT_DEF_TAB[4 * 32] =\n{\n// FD = 0\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\n// FD = 1\n  0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,\n  2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,\n\n// FD = 2\n  1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,\n  5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 16, 16, 16, 16,\n\n// FD = 3\n  2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,\n  8 , 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 20, 22, 22, 22, 22\n};\n\nconst unsigned int FKEY_TAB[16] =\n{\n  0, 0, 0, 0,\n  0, 0, 0, 1,\n  2, 3, 3, 3,\n  3, 3, 3, 3\n};\n\nconst unsigned int LFO_AMS_TAB[4] =\n{\n  31, 4, 1, 0\n};\n\nconst unsigned int LFO_FMS_TAB[8] =\n{\n  LFO_FMS_BASE * 0, LFO_FMS_BASE * 1,\n  LFO_FMS_BASE * 2, LFO_FMS_BASE * 3,\n  LFO_FMS_BASE * 4, LFO_FMS_BASE * 6,\n  LFO_FMS_BASE * 12, LFO_FMS_BASE * 24\n};\n\nint int_cnt;                // Interpolation calculation\n\n\n#if YM_DEBUG_LEVEL > 0            // Debug\nFILE *debug_file = NULL;\n#endif\n\n\n/* Gens */\n\n//extern unsigned int Sound_Extrapol[312][2];\n//extern int Seg_L[882], Seg_R[882];\n//extern int VDP_Current_Line;\n//extern int GYM_Dumping;\n//extern int YM2612_Enable;\n//extern int DAC_Enable=1;\n\n//int Update_GYM_Dump(char v0, char v1, char v2);\n\nint YM2612_Enable;\nint YM2612_Improv;\n//int DAC_Enable = 1;\nint *YM_Buf[2];\nint YM_Len = 0;\nint YM2612_Enable_SSGEG = 1; // enable SSG-EG envelope (causes inacurate sound sometimes - rodrigo)\nint DAC_Highpass_Enable = 1; // sometimes it creates a terrible noise\n\n/* end */\n\n\n/***********************************************\n *           fonctions calcul param            *\n ***********************************************/\n\n\nINLINE void CALC_FINC_SL(slot_ *SL, int finc, int kc)\n{\n  int ksr;\n\n  SL->Finc = (finc + SL->DT[kc]) * SL->MUL;\n\n  ksr = kc >> SL->KSR_S;  // keycode attnuation\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"FINC = %d  SL->Finc = %d\\n\", finc, SL->Finc);\n#endif\n\n\tif (SL->KSR != ksr)\t\t// si le KSR a chang alors\n\t{\t\t\t\t\t\t// les diffrents taux pour l'enveloppe sont mis  jour\n    SL->KSR = ksr;\n\n    SL->EincA = SL->AR[ksr];\n    SL->EincD = SL->DR[ksr];\n    SL->EincS = SL->SR[ksr];\n    SL->EincR = SL->RR[ksr];\n\n    if(SL->Ecurp == ATTACK) SL->Einc = SL->EincA;\n    else if(SL->Ecurp == DECAY) SL->Einc = SL->EincD;\n    else if(SL->Ecnt < ENV_END)\n    {\n      if(SL->Ecurp == SUBSTAIN) SL->Einc = SL->EincS;\n      else if(SL->Ecurp == RELEASE) SL->Einc = SL->EincR;\n    }\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"KSR = %.4X  EincA = %.8X EincD = %.8X EincS = %.8X EincR = %.8X\\n\", ksr, SL->EincA, SL->EincD, SL->EincS, SL->EincR);\n#endif\n  }\n}\n\n\nINLINE void CALC_FINC_CH(channel_ *CH)\n{\n  int finc, kc;\n\n  finc = FINC_TAB[CH->FNUM[0]] >> (7 - CH->FOCT[0]);\n  kc = CH->KC[0];\n\n  CALC_FINC_SL(&CH->SLOT[0], finc, kc);\n  CALC_FINC_SL(&CH->SLOT[1], finc, kc);\n  CALC_FINC_SL(&CH->SLOT[2], finc, kc);\n  CALC_FINC_SL(&CH->SLOT[3], finc, kc);\n}\n\n\n\n/***********************************************\n *             fonctions setting               *\n ***********************************************/\n\n\nINLINE void KEY_ON(channel_ *CH, int nsl)\n{\n  slot_ *SL = &(CH->SLOT[nsl]);  // on recupre le bon pointeur de slot\n\n  if(SL->Ecurp == RELEASE)    // la touche est-elle relche ?\n  {\n    SL->Fcnt = 0;\n\n    // Fix Ecco 2 splash sound\n\n    SL->Ecnt = (DECAY_TO_ATTACK[ENV_TAB[SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK) & SL->ChgEnM;\n    SL->ChgEnM = 0xFFFFFFFF;\n\n//    SL->Ecnt = DECAY_TO_ATTACK[ENV_TAB[SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK;\n//    SL->Ecnt = 0;\n\n    SL->Einc = SL->EincA;\n    SL->Ecmp = ENV_DECAY;\n    SL->Ecurp = ATTACK;\n  }\n}\n\n\nINLINE void KEY_OFF(channel_ *CH, int nsl)\n{\n  slot_ *SL = &(CH->SLOT[nsl]);  // on recupre le bon pointeur de slot\n\n  if(SL->Ecurp != RELEASE)    // la touche est-elle appuye ?\n  {\n    if(SL->Ecnt < ENV_DECAY)  // attack phase ?\n    {\n      SL->Ecnt = (ENV_TAB[SL->Ecnt >> ENV_LBITS] << ENV_LBITS) + ENV_DECAY;\n    }\n\n    SL->Einc = SL->EincR;\n    SL->Ecmp = ENV_END;\n    SL->Ecurp = RELEASE;\n  }\n}\n\n\nINLINE void CSM_Key_Control(ym2612_ *YM2612)\n{\n  KEY_ON(&YM2612->CHANNEL[2], 0);\n  KEY_ON(&YM2612->CHANNEL[2], 1);\n  KEY_ON(&YM2612->CHANNEL[2], 2);\n  KEY_ON(&YM2612->CHANNEL[2], 3);\n}\n\n\nint SLOT_SET(ym2612_ *YM2612, int Adr, unsigned char data)\n{\n  channel_ *CH;\n  slot_ *SL;\n  int nch, nsl;\n\n  if((nch = Adr & 3) == 3) return 1;\n  nsl = (Adr >> 2) & 3;\n\n  if(Adr & 0x100) nch += 3;\n\n  CH = &(YM2612->CHANNEL[nch]);\n  SL = &(CH->SLOT[nsl]);\n\n  switch(Adr & 0xF0)\n  {\n    case 0x30:\n      if(SL->MUL = (data & 0x0F)) SL->MUL <<= 1;\n      else SL->MUL = 1;\n\n      SL->DT = DT_TAB[(data >> 4) & 7];\n\n      CH->SLOT[0].Finc = -1;\n\n#if YM_DEBUG_LEVEL > 1\n      fprintf(debug_file, \"CHANNEL[%d], SLOT[%d] DTMUL = %.2X\\n\", nch, nsl, data & 0x7F);\n#endif\n      break;\n\n    case 0x40:\n      SL->TL = data & 0x7F;\n\n      // SOR2 do a lot of TL adjustement and this fix R.Shinobi jump sound...\n      YM2612_Special_Update(YM2612);\n\n#if((ENV_HBITS - 7) < 0)\n      SL->TLL = SL->TL >> (7 - ENV_HBITS);\n#else\n      SL->TLL = SL->TL << (ENV_HBITS - 7);\n#endif\n\n#if YM_DEBUG_LEVEL > 1\n      fprintf(debug_file, \"CHANNEL[%d], SLOT[%d] TL = %.2X\\n\", nch, nsl, SL->TL);\n#endif\n      break;\n\n    case 0x50:\n      SL->KSR_S = 3 - (data >> 6);\n\n      CH->SLOT[0].Finc = -1;\n\n      if(data &= 0x1F) SL->AR = &AR_TAB[data << 1];\n      else SL->AR = &NULL_RATE[0];\n\n      SL->EincA = SL->AR[SL->KSR];\n      if(SL->Ecurp == ATTACK) SL->Einc = SL->EincA;\n\n#if YM_DEBUG_LEVEL > 1\n      fprintf(debug_file, \"CHANNEL[%d], SLOT[%d] AR = %.2X  EincA = %.6X\\n\", nch, nsl, data, SL->EincA);\n#endif\n      break;\n\n    case 0x60:\n      if(SL->AMSon = (data & 0x80)) SL->AMS = CH->AMS;\n      else SL->AMS = 31;\n\n      if(data &= 0x1F) SL->DR = &DR_TAB[data << 1];\n      else SL->DR = &NULL_RATE[0];\n\n      SL->EincD = SL->DR[SL->KSR];\n      if(SL->Ecurp == DECAY) SL->Einc = SL->EincD;\n\n#if YM_DEBUG_LEVEL > 1\n      fprintf(debug_file, \"CHANNEL[%d], SLOT[%d] AMS = %d  DR = %.2X  EincD = %.6X\\n\", nch, nsl, SL->AMSon, data, SL->EincD);\n#endif\n      break;\n\n    case 0x70:\n      if(data &= 0x1F) SL->SR = &DR_TAB[data << 1];\n      else SL->SR = &NULL_RATE[0];\n\n      SL->EincS = SL->SR[SL->KSR];\n      if((SL->Ecurp == SUBSTAIN) && (SL->Ecnt < ENV_END)) SL->Einc = SL->EincS;\n\n#if YM_DEBUG_LEVEL > 1\n      fprintf(debug_file, \"CHANNEL[%d], SLOT[%d] SR = %.2X  EincS = %.6X\\n\", nch, nsl, data, SL->EincS);\n#endif\n      break;\n\n    case 0x80:\n      SL->SLL = SL_TAB[data >> 4];\n\n      SL->RR = &DR_TAB[((data & 0xF) << 2) + 2];\n\n      SL->EincR = SL->RR[SL->KSR];\n      if((SL->Ecurp == RELEASE) && (SL->Ecnt < ENV_END)) SL->Einc = SL->EincR;\n\n#if YM_DEBUG_LEVEL > 1\n      fprintf(debug_file, \"CHANNEL[%d], SLOT[%d] SL = %.8X\\n\", nch, nsl, SL->SLL);\n      fprintf(debug_file, \"CHANNEL[%d], SLOT[%d] RR = %.2X  EincR = %.2X\\n\", nch, nsl, ((data & 0xF) << 1) | 2, SL->EincR);\n#endif\n      break;\n\n    case 0x90:\n      /* SSG-EG envelope shapes :\n      //\n      // E  At Al H\n      //\n      // 1  0  0  0  \\\\\\\\\n      //\n      // 1  0  0  1  \\___\n      //\n      // 1  0  1  0  \\/\\/\n      //              ___\n      // 1  0  1  1  \\\n      //\n      // 1  1  0  0  ////\n      //              ___\n      // 1  1  0  1  /\n      //\n      // 1  1  1  0  /\\/\\\n      //\n      // 1  1  1  1  /___\n      //\n      // E  = SSG-EG enable\n      // At = Start negate\n      // Al = Altern\n      // H  = Hold */\n      if(YM2612_Enable_SSGEG)\n      {\n        if(data & 0x08) SL->SEG = data & 0x0F;\n        else SL->SEG = 0;\n\n#if YM_DEBUG_LEVEL > 1\n        fprintf(debug_file, \"CHANNEL[%d], SLOT[%d] SSG-EG = %.2X\\n\", nch, nsl, data);\n#endif\n      }\n      break;\n  }\n\n  return 0;\n}\n\n\nint CHANNEL_SET(ym2612_ *YM2612, int Adr, unsigned char data)\n{\n  channel_ *CH;\n  int num;\n\n  if((num = Adr & 3) == 3) return 1;\n\n  switch(Adr & 0xFC)\n  {\n    case 0xA0:\n      if(Adr & 0x100) num += 3;\n      CH = &(YM2612->CHANNEL[num]);\n\n      YM2612_Special_Update(YM2612);\n\n      CH->FNUM[0] = (CH->FNUM[0] & 0x700) + data;\n      CH->KC[0] = (CH->FOCT[0] << 2) | FKEY_TAB[CH->FNUM[0] >> 7];\n\n      CH->SLOT[0].Finc = -1;\n\n#if YM_DEBUG_LEVEL > 1\n      fprintf(debug_file, \"CHANNEL[%d] part1 FNUM = %d  KC = %d\\n\", num, CH->FNUM[0], CH->KC[0]);\n#endif\n      break;\n\n    case 0xA4:\n      if(Adr & 0x100) num += 3;\n      CH = &(YM2612->CHANNEL[num]);\n\n      YM2612_Special_Update(YM2612);\n\n      CH->FNUM[0] = (CH->FNUM[0] & 0x0FF) + ((int) (data & 0x07) << 8);\n      CH->FOCT[0] = (data & 0x38) >> 3;\n      CH->KC[0] = (CH->FOCT[0] << 2) | FKEY_TAB[CH->FNUM[0] >> 7];\n\n      CH->SLOT[0].Finc = -1;\n\n#if YM_DEBUG_LEVEL > 1\n      fprintf(debug_file, \"CHANNEL[%d] part2 FNUM = %d  FOCT = %d  KC = %d\\n\", num, CH->FNUM[0], CH->FOCT[0], CH->KC[0]);\n#endif\n      break;\n\n    case 0xA8:\n      if(Adr < 0x100)\n      {\n        num++;\n\n        YM2612_Special_Update(YM2612);\n\n        YM2612->CHANNEL[2].FNUM[num] = (YM2612->CHANNEL[2].FNUM[num] & 0x700) + data;\n        YM2612->CHANNEL[2].KC[num] = (YM2612->CHANNEL[2].FOCT[num] << 2) | FKEY_TAB[YM2612->CHANNEL[2].FNUM[num] >> 7];\n\n        YM2612->CHANNEL[2].SLOT[0].Finc = -1;\n\n#if YM_DEBUG_LEVEL > 1\n        fprintf(debug_file, \"CHANNEL[2] part1 FNUM[%d] = %d  KC[%d] = %d\\n\", num, YM2612->CHANNEL[2].FNUM[num], num, YM2612->CHANNEL[2].KC[num]);\n#endif\n      }\n      break;\n\n    case 0xAC:\n      if(Adr < 0x100)\n      {\n        num++;\n\n        YM2612_Special_Update(YM2612);\n\n        YM2612->CHANNEL[2].FNUM[num] = (YM2612->CHANNEL[2].FNUM[num] & 0x0FF) + ((int) (data & 0x07) << 8);\n        YM2612->CHANNEL[2].FOCT[num] = (data & 0x38) >> 3;\n        YM2612->CHANNEL[2].KC[num] = (YM2612->CHANNEL[2].FOCT[num] << 2) | FKEY_TAB[YM2612->CHANNEL[2].FNUM[num] >> 7];\n\n        YM2612->CHANNEL[2].SLOT[0].Finc = -1;\n\n#if YM_DEBUG_LEVEL > 1\n        fprintf(debug_file, \"CHANNEL[2] part2 FNUM[%d] = %d  FOCT[%d] = %d  KC[%d] = %d\\n\", num, YM2612->CHANNEL[2].FNUM[num], num, YM2612->CHANNEL[2].FOCT[num], num, YM2612->CHANNEL[2].KC[num]);\n#endif\n      }\n      break;\n\n    case 0xB0:\n      if(Adr & 0x100) num += 3;\n      CH = &(YM2612->CHANNEL[num]);\n\n      if(CH->ALGO != (data & 7))\n      {\n        // Fix VectorMan 2 heli sound (level 1)\n        YM2612_Special_Update(YM2612);\n\n        CH->ALGO = data & 7;\n\n        CH->SLOT[0].ChgEnM = 0;\n        CH->SLOT[1].ChgEnM = 0;\n        CH->SLOT[2].ChgEnM = 0;\n        CH->SLOT[3].ChgEnM = 0;\n      }\n\n      CH->FB = 9 - ((data >> 3) & 7);                // Real thing ?\n\n//      if(CH->FB = ((data >> 3) & 7)) CH->FB = 9 - CH->FB;    // Thunder force 4 (music stage 8), Gynoug, Aladdin bug sound...\n//      else CH->FB = 31;\n\n#if YM_DEBUG_LEVEL > 1\n      fprintf(debug_file, \"CHANNEL[%d] ALGO = %d  FB = %d\\n\", num, CH->ALGO, CH->FB);\n#endif\n      break;\n\n    case 0xB4:\n      if(Adr & 0x100) num += 3;\n      CH = &(YM2612->CHANNEL[num]);\n\n      YM2612_Special_Update(YM2612);\n\n      if(data & 0x80) CH->LEFT = 0xFFFFFFFF;\n      else CH->LEFT = 0;\n\n      if(data & 0x40) CH->RIGHT = 0xFFFFFFFF;\n      else CH->RIGHT = 0;\n\n      CH->AMS = LFO_AMS_TAB[(data >> 4) & 3];\n      CH->FMS = LFO_FMS_TAB[data & 7];\n\n      if(CH->SLOT[0].AMSon) CH->SLOT[0].AMS = CH->AMS;\n      else CH->SLOT[0].AMS = 31;\n      if(CH->SLOT[1].AMSon) CH->SLOT[1].AMS = CH->AMS;\n      else CH->SLOT[1].AMS = 31;\n      if(CH->SLOT[2].AMSon) CH->SLOT[2].AMS = CH->AMS;\n      else CH->SLOT[2].AMS = 31;\n      if(CH->SLOT[3].AMSon) CH->SLOT[3].AMS = CH->AMS;\n      else CH->SLOT[3].AMS = 31;\n\n#if YM_DEBUG_LEVEL > 0\n      fprintf(debug_file, \"CHANNEL[%d] AMS = %d  FMS = %d\\n\", num, CH->AMS, CH->FMS);\n#endif\n      break;\n  }\n\n  return 0;\n}\n\n\nint YM_SET(ym2612_ *YM2612, int Adr, unsigned char data)\n{\n  channel_ *CH;\n  int nch;\n\n  switch(Adr)\n  {\n    case 0x22:\n      if(data & 8)\n      {\n        // Cool Spot music 1, LFO modified severals time which\n        // distord the sound, have to check that on a real genesis...\n\n        YM2612->LFOinc = LFO_INC_TAB[data & 7];\n\n#if YM_DEBUG_LEVEL > 0\n        fprintf(debug_file, \"\\nLFO Enable, LFOinc = %.8X   %d\\n\", YM2612->LFOinc, data & 7);\n#endif\n      }\n      else\n      {\n        YM2612->LFOinc = YM2612->LFOcnt = 0;\n\n#if YM_DEBUG_LEVEL > 0\n        fprintf(debug_file, \"\\nLFO Disable\\n\");\n#endif\n      }\n      break;\n\n    case 0x24:\n      YM2612->TimerA = (YM2612->TimerA & 0x003) | (((int) data) << 2);\n\n      if(YM2612->TimerAL != (1024 - YM2612->TimerA) << 12)\n      {\n        YM2612->TimerAcnt = YM2612->TimerAL = (1024 - YM2612->TimerA) << 12;\n\n#if YM_DEBUG_LEVEL > 1\n        fprintf(debug_file, \"Timer A Set = %.8X\\n\", YM2612->TimerAcnt);\n#endif\n      }\n      break;\n\n    case 0x25:\n      YM2612->TimerA = (YM2612->TimerA & 0x3fc) | (data & 3);\n\n      if(YM2612->TimerAL != (1024 - YM2612->TimerA) << 12)\n      {\n        YM2612->TimerAcnt = YM2612->TimerAL = (1024 - YM2612->TimerA) << 12;\n\n#if YM_DEBUG_LEVEL > 1\n        fprintf(debug_file, \"Timer A Set = %.8X\\n\", YM2612->TimerAcnt);\n#endif\n      }\n      break;\n\n    case 0x26:\n      YM2612->TimerB = data;\n\n      if(YM2612->TimerBL != (256 - YM2612->TimerB) << (4 + 12))\n      {\n        YM2612->TimerBcnt = YM2612->TimerBL = (256 - YM2612->TimerB) << (4 + 12);\n\n#if YM_DEBUG_LEVEL > 1\n        fprintf(debug_file, \"Timer B Set = %.8X\\n\", YM2612->TimerBcnt);\n#endif\n      }\n      break;\n\n    case 0x27:\n      // Paramtre divers\n      // b7 = CSM MODE\n      // b6 = 3 slot mode\n      // b5 = reset b\n      // b4 = reset a\n      // b3 = timer enable b\n      // b2 = timer enable a\n      // b1 = load b\n      // b0 = load a\n\n      if((data ^ YM2612->Mode) & 0x40)\n      {\n        // We changed the channel 2 mode, so recalculate phase step\n        // This fix the punch sound in Street of Rage 2\n\n        YM2612_Special_Update(YM2612);\n\n        YM2612->CHANNEL[2].SLOT[0].Finc = -1;    // recalculate phase step\n      }\n\n//      if((data & 2) && (YM2612->Status & 2)) YM2612->TimerBcnt = YM2612->TimerBL;\n//      if((data & 1) && (YM2612->Status & 1)) YM2612->TimerAcnt = YM2612->TimerAL;\n\n//      YM2612->Status &= (~data >> 4);          // Reset du Status au cas ou c'est demand?\n      YM2612->Status &= (~data >> 4) & (data >> 2);  // Reset Status\n\n      YM2612->Mode = data;\n\n#if YM_DEBUG_LEVEL > 0\n      fprintf(debug_file, \"Mode reg = %.2X\\n\", data);\n#endif\n      break;\n\n    case 0x28:\n      if((nch = data & 3) == 3) return 1;\n\n      if(data & 4) nch += 3;\n      CH = &(YM2612->CHANNEL[nch]);\n\n      YM2612_Special_Update(YM2612);\n\n      if(data & 0x10) KEY_ON(CH, S0);  // On appuie sur la touche pour le slot 1\n      else KEY_OFF(CH, S0);        // On relche la touche pour le slot 1\n      if(data & 0x20) KEY_ON(CH, S1);  // On appuie sur la touche pour le slot 3\n      else KEY_OFF(CH, S1);        // On relche la touche pour le slot 3\n      if(data & 0x40) KEY_ON(CH, S2);  // On appuie sur la touche pour le slot 2\n      else KEY_OFF(CH, S2);        // On relche la touche pour le slot 2\n      if(data & 0x80) KEY_ON(CH, S3);  // On appuie sur la touche pour le slot 4\n      else KEY_OFF(CH, S3);        // On relche la touche pour le slot 4\n\n#if YM_DEBUG_LEVEL > 0\n      fprintf(debug_file, \"CHANNEL[%d]  KEY %.1X\\n\", nch, ((data & 0xf0) >> 4));\n#endif\n      break;\n\n    case 0x2A:\n      YM2612->DACdata = ((int) data - 0x80) << DAC_SHIFT;  // donne du DAC\n      break;\n\n    case 0x2B:\n      if(YM2612->DAC ^ (data & 0x80)) YM2612_Special_Update(YM2612);\n\n      YM2612->DAC = data & 0x80;  // activation/dsactivation du DAC\n      break;\n  }\n\n  return 0;\n}\n\n\n\n/***********************************************\n *          fonctions de gnration            *\n ***********************************************/\n\n\nvoid Env_NULL_Next(slot_ *SL)\n{\n}\n\n\nvoid Env_Attack_Next(slot_ *SL)\n{\n  // Verified with Gynoug even in HQ (explode SFX)\n  SL->Ecnt = ENV_DECAY;\n\n  SL->Einc = SL->EincD;\n  SL->Ecmp = SL->SLL;\n  SL->Ecurp = DECAY;\n}\n\n\nvoid Env_Decay_Next(slot_ *SL)\n{\n  // Verified with Gynoug even in HQ (explode SFX)\n  SL->Ecnt = SL->SLL;\n\n  SL->Einc = SL->EincS;\n  SL->Ecmp = ENV_END;\n  SL->Ecurp = SUBSTAIN;\n}\n\n\nvoid Env_Substain_Next(slot_ *SL)\n{\n  if(YM2612_Enable_SSGEG)\n  {\n    if(SL->SEG & 8)  // SSG envelope type\n    {\n      if(SL->SEG & 1)\n      {\n        SL->Ecnt = ENV_END;\n        SL->Einc = 0;\n        SL->Ecmp = ENV_END + 1;\n      }\n      else\n      {\n        // re KEY ON\n\n        // SL->Fcnt = 0;\n        // SL->ChgEnM = 0xFFFFFFFF;\n\n        SL->Ecnt = 0;\n        SL->Einc = SL->EincA;\n        SL->Ecmp = ENV_DECAY;\n        SL->Ecurp = ATTACK;\n      }\n\n      SL->SEG ^= (SL->SEG & 2) << 1;\n    }\n    else\n    {\n      SL->Ecnt = ENV_END;\n      SL->Einc = 0;\n      SL->Ecmp = ENV_END + 1;\n    }\n  }\n  else\n  {\n    SL->Ecnt = ENV_END;\n    SL->Einc = 0;\n    SL->Ecmp = ENV_END + 1;\n  }\n}\n\n\nvoid Env_Release_Next(slot_ *SL)\n{\n  SL->Ecnt = ENV_END;\n  SL->Einc = 0;\n  SL->Ecmp = ENV_END + 1;\n}\n\n\n#define GET_CURRENT_PHASE  \\\nYM2612->in0 = CH->SLOT[S0].Fcnt;  \\\nYM2612->in1 = CH->SLOT[S1].Fcnt;  \\\nYM2612->in2 = CH->SLOT[S2].Fcnt;  \\\nYM2612->in3 = CH->SLOT[S3].Fcnt;\n\n\n#define UPDATE_PHASE          \\\nCH->SLOT[S0].Fcnt += CH->SLOT[S0].Finc;  \\\nCH->SLOT[S1].Fcnt += CH->SLOT[S1].Finc;  \\\nCH->SLOT[S2].Fcnt += CH->SLOT[S2].Finc;  \\\nCH->SLOT[S3].Fcnt += CH->SLOT[S3].Finc;\n\n\n#define UPDATE_PHASE_LFO                                    \\\nif(freq_LFO = (CH->FMS * YM2612->LFO_FREQ_UP[i]) >> (LFO_HBITS - 1))                  \\\n{                                                \\\n  CH->SLOT[S0].Fcnt += CH->SLOT[S0].Finc + ((CH->SLOT[S0].Finc * freq_LFO) >> LFO_FMS_LBITS);  \\\n  CH->SLOT[S1].Fcnt += CH->SLOT[S1].Finc + ((CH->SLOT[S1].Finc * freq_LFO) >> LFO_FMS_LBITS);  \\\n  CH->SLOT[S2].Fcnt += CH->SLOT[S2].Finc + ((CH->SLOT[S2].Finc * freq_LFO) >> LFO_FMS_LBITS);  \\\n  CH->SLOT[S3].Fcnt += CH->SLOT[S3].Finc + ((CH->SLOT[S3].Finc * freq_LFO) >> LFO_FMS_LBITS);  \\\n}                                                \\\nelse                                              \\\n{                                                \\\n  CH->SLOT[S0].Fcnt += CH->SLOT[S0].Finc;                            \\\n  CH->SLOT[S1].Fcnt += CH->SLOT[S1].Finc;                            \\\n  CH->SLOT[S2].Fcnt += CH->SLOT[S2].Finc;                            \\\n  CH->SLOT[S3].Fcnt += CH->SLOT[S3].Finc;                            \\\n}\n\n\n#define GET_CURRENT_ENV                                        \\\nif(CH->SLOT[S0].SEG & 4)                                      \\\n{                                                  \\\n  if((YM2612->en0 = ENV_TAB[(CH->SLOT[S0].Ecnt >> ENV_LBITS)] + CH->SLOT[S0].TLL) > ENV_MASK) YM2612->en0 = 0;  \\\n  else YM2612->en0 ^= ENV_MASK;                                      \\\n}                                                  \\\nelse YM2612->en0 = ENV_TAB[(CH->SLOT[S0].Ecnt >> ENV_LBITS)] + CH->SLOT[S0].TLL;              \\\nif(CH->SLOT[S1].SEG & 4)                                      \\\n{                                                  \\\n  if((YM2612->en1 = ENV_TAB[(CH->SLOT[S1].Ecnt >> ENV_LBITS)] + CH->SLOT[S1].TLL) > ENV_MASK) YM2612->en1 = 0;  \\\n  else YM2612->en1 ^= ENV_MASK;                                      \\\n}                                                  \\\nelse YM2612->en1 = ENV_TAB[(CH->SLOT[S1].Ecnt >> ENV_LBITS)] + CH->SLOT[S1].TLL;              \\\nif(CH->SLOT[S2].SEG & 4)                                      \\\n{                                                  \\\n  if((YM2612->en2 = ENV_TAB[(CH->SLOT[S2].Ecnt >> ENV_LBITS)] + CH->SLOT[S2].TLL) > ENV_MASK) YM2612->en2 = 0;  \\\n  else YM2612->en2 ^= ENV_MASK;                                      \\\n}                                                  \\\nelse YM2612->en2 = ENV_TAB[(CH->SLOT[S2].Ecnt >> ENV_LBITS)] + CH->SLOT[S2].TLL;              \\\nif(CH->SLOT[S3].SEG & 4)                                      \\\n{                                                  \\\n  if((YM2612->en3 = ENV_TAB[(CH->SLOT[S3].Ecnt >> ENV_LBITS)] + CH->SLOT[S3].TLL) > ENV_MASK) YM2612->en3 = 0;  \\\n  else YM2612->en3 ^= ENV_MASK;                                      \\\n}                                                  \\\nelse YM2612->en3 = ENV_TAB[(CH->SLOT[S3].Ecnt >> ENV_LBITS)] + CH->SLOT[S3].TLL;\n\n\n#define GET_CURRENT_ENV_LFO                                          \\\nenv_LFO = YM2612->LFO_ENV_UP[i];                                          \\\n                                                      \\\nif(CH->SLOT[S0].SEG & 4)                                          \\\n{                                                      \\\n  if((YM2612->en0 = ENV_TAB[(CH->SLOT[S0].Ecnt >> ENV_LBITS)] + CH->SLOT[S0].TLL) > ENV_MASK) YM2612->en0 = 0;      \\\n  else YM2612->en0 = (YM2612->en0 ^ ENV_MASK) + (env_LFO >> CH->SLOT[S0].AMS);                      \\\n}                                                      \\\nelse YM2612->en0 = ENV_TAB[(CH->SLOT[S0].Ecnt >> ENV_LBITS)] + CH->SLOT[S0].TLL + (env_LFO >> CH->SLOT[S0].AMS);  \\\nif(CH->SLOT[S1].SEG & 4)                                          \\\n{                                                      \\\n  if((YM2612->en1 = ENV_TAB[(CH->SLOT[S1].Ecnt >> ENV_LBITS)] + CH->SLOT[S1].TLL) > ENV_MASK) YM2612->en1 = 0;      \\\n  else YM2612->en1 = (YM2612->en1 ^ ENV_MASK) + (env_LFO >> CH->SLOT[S1].AMS);                      \\\n}                                                      \\\nelse YM2612->en1 = ENV_TAB[(CH->SLOT[S1].Ecnt >> ENV_LBITS)] + CH->SLOT[S1].TLL + (env_LFO >> CH->SLOT[S1].AMS);  \\\nif(CH->SLOT[S2].SEG & 4)                                          \\\n{                                                      \\\n  if((YM2612->en2 = ENV_TAB[(CH->SLOT[S2].Ecnt >> ENV_LBITS)] + CH->SLOT[S2].TLL) > ENV_MASK) YM2612->en2 = 0;      \\\n  else YM2612->en2 = (YM2612->en2 ^ ENV_MASK) + (env_LFO >> CH->SLOT[S2].AMS);                      \\\n}                                                      \\\nelse YM2612->en2 = ENV_TAB[(CH->SLOT[S2].Ecnt >> ENV_LBITS)] + CH->SLOT[S2].TLL + (env_LFO >> CH->SLOT[S2].AMS);  \\\nif(CH->SLOT[S3].SEG & 4)                                          \\\n{                                                      \\\n  if((YM2612->en3 = ENV_TAB[(CH->SLOT[S3].Ecnt >> ENV_LBITS)] + CH->SLOT[S3].TLL) > ENV_MASK) YM2612->en3 = 0;      \\\n  else YM2612->en3 = (YM2612->en3 ^ ENV_MASK) + (env_LFO >> CH->SLOT[S3].AMS);                      \\\n}                                                      \\\nelse YM2612->en3 = ENV_TAB[(CH->SLOT[S3].Ecnt >> ENV_LBITS)] + CH->SLOT[S3].TLL + (env_LFO >> CH->SLOT[S3].AMS);\n\n\n#define UPDATE_ENV                            \\\nif((CH->SLOT[S0].Ecnt += CH->SLOT[S0].Einc) >= CH->SLOT[S0].Ecmp)    \\\n  ENV_NEXT_EVENT[CH->SLOT[S0].Ecurp](&(CH->SLOT[S0]));        \\\nif((CH->SLOT[S1].Ecnt += CH->SLOT[S1].Einc) >= CH->SLOT[S1].Ecmp)    \\\n  ENV_NEXT_EVENT[CH->SLOT[S1].Ecurp](&(CH->SLOT[S1]));        \\\nif((CH->SLOT[S2].Ecnt += CH->SLOT[S2].Einc) >= CH->SLOT[S2].Ecmp)    \\\n  ENV_NEXT_EVENT[CH->SLOT[S2].Ecurp](&(CH->SLOT[S2]));        \\\nif((CH->SLOT[S3].Ecnt += CH->SLOT[S3].Einc) >= CH->SLOT[S3].Ecmp)    \\\n  ENV_NEXT_EVENT[CH->SLOT[S3].Ecurp](&(CH->SLOT[S3]));\n\n\n#define DO_LIMIT                        \\\nif(CH->OUTd > LIMIT_CH_OUT) CH->OUTd = LIMIT_CH_OUT;      \\\nelse if(CH->OUTd < -LIMIT_CH_OUT) CH->OUTd = -LIMIT_CH_OUT;\n\n\n#define DO_FEEDBACK0                      \\\nYM2612->in0 += CH->S0_OUT[0] >> CH->FB;                  \\\nCH->S0_OUT[0] = SIN_TAB[(YM2612->in0 >> SIN_LBITS) & SIN_MASK][YM2612->en0];\n\n\n#define DO_FEEDBACK                        \\\nYM2612->in0 += (CH->S0_OUT[0] + CH->S0_OUT[1]) >> CH->FB;        \\\nCH->S0_OUT[1] = CH->S0_OUT[0];                  \\\nCH->S0_OUT[0] = SIN_TAB[(YM2612->in0 >> SIN_LBITS) & SIN_MASK][YM2612->en0];\n\n\n#define DO_FEEDBACK2                            \\\nYM2612->in0 += (CH->S0_OUT[0] + (CH->S0_OUT[0] >> 2) + CH->S0_OUT[1]) >> CH->FB;  \\\nCH->S0_OUT[1] = CH->S0_OUT[0] >> 2;                      \\\nCH->S0_OUT[0] = SIN_TAB[(YM2612->in0 >> SIN_LBITS) & SIN_MASK][YM2612->en0];\n\n\n#define DO_FEEDBACK3                                  \\\nYM2612->in0 += (CH->S0_OUT[0] + CH->S0_OUT[1] + CH->S0_OUT[2] + CH->S0_OUT[3]) >> CH->FB;    \\\nCH->S0_OUT[3] = CH->S0_OUT[2] >> 1;                            \\\nCH->S0_OUT[2] = CH->S0_OUT[1] >> 1;                            \\\nCH->S0_OUT[1] = CH->S0_OUT[0] >> 1;                            \\\nCH->S0_OUT[0] = SIN_TAB[(YM2612->in0 >> SIN_LBITS) & SIN_MASK][YM2612->en0];\n\n\n#define DO_ALGO_0                              \\\nDO_FEEDBACK                                  \\\nYM2612->in1 += CH->S0_OUT[1];                            \\\nYM2612->in2 += SIN_TAB[(YM2612->in1 >> SIN_LBITS) & SIN_MASK][YM2612->en1];              \\\nYM2612->in3 += SIN_TAB[(YM2612->in2 >> SIN_LBITS) & SIN_MASK][YM2612->en2];              \\\nCH->OUTd = (SIN_TAB[(YM2612->in3 >> SIN_LBITS) & SIN_MASK][YM2612->en3]) >> OUT_SHIFT;\n\n#define DO_ALGO_1                              \\\nDO_FEEDBACK                                  \\\nYM2612->in2 += CH->S0_OUT[1] + SIN_TAB[(YM2612->in1 >> SIN_LBITS) & SIN_MASK][YM2612->en1];      \\\nYM2612->in3 += SIN_TAB[(YM2612->in2 >> SIN_LBITS) & SIN_MASK][YM2612->en2];              \\\nCH->OUTd = (SIN_TAB[(YM2612->in3 >> SIN_LBITS) & SIN_MASK][YM2612->en3]) >> OUT_SHIFT;\n\n#define DO_ALGO_2                              \\\nDO_FEEDBACK                                  \\\nYM2612->in2 += SIN_TAB[(YM2612->in1 >> SIN_LBITS) & SIN_MASK][YM2612->en1];              \\\nYM2612->in3 += CH->S0_OUT[1] + SIN_TAB[(YM2612->in2 >> SIN_LBITS) & SIN_MASK][YM2612->en2];      \\\nCH->OUTd = (SIN_TAB[(YM2612->in3 >> SIN_LBITS) & SIN_MASK][YM2612->en3]) >> OUT_SHIFT;\n\n#define DO_ALGO_3                              \\\nDO_FEEDBACK                                  \\\nYM2612->in1 += CH->S0_OUT[1];                            \\\nYM2612->in3 += SIN_TAB[(YM2612->in1 >> SIN_LBITS) & SIN_MASK][YM2612->en1] + SIN_TAB[(YM2612->in2 >> SIN_LBITS) & SIN_MASK][YM2612->en2];  \\\nCH->OUTd = (SIN_TAB[(YM2612->in3 >> SIN_LBITS) & SIN_MASK][YM2612->en3]) >> OUT_SHIFT;\n\n#define DO_ALGO_4                              \\\nDO_FEEDBACK                                  \\\nYM2612->in1 += CH->S0_OUT[1];                            \\\nYM2612->in3 += SIN_TAB[(YM2612->in2 >> SIN_LBITS) & SIN_MASK][YM2612->en2];              \\\nCH->OUTd = ((int) SIN_TAB[(YM2612->in3 >> SIN_LBITS) & SIN_MASK][YM2612->en3] + (int) SIN_TAB[(YM2612->in1 >> SIN_LBITS) & SIN_MASK][YM2612->en1]) >> OUT_SHIFT;  \\\nDO_LIMIT\n\n#define DO_ALGO_5                              \\\nDO_FEEDBACK                                  \\\nYM2612->in1 += CH->S0_OUT[1];                            \\\nYM2612->in2 += CH->S0_OUT[1];                            \\\nYM2612->in3 += CH->S0_OUT[1];                            \\\nCH->OUTd = ((int) SIN_TAB[(YM2612->in3 >> SIN_LBITS) & SIN_MASK][YM2612->en3] + (int) SIN_TAB[(YM2612->in1 >> SIN_LBITS) & SIN_MASK][YM2612->en1] + (int) SIN_TAB[(YM2612->in2 >> SIN_LBITS) & SIN_MASK][YM2612->en2]) >> OUT_SHIFT;  \\\nDO_LIMIT\n\n#define DO_ALGO_6                              \\\nDO_FEEDBACK                                  \\\nYM2612->in1 += CH->S0_OUT[1];                            \\\nCH->OUTd = ((int) SIN_TAB[(YM2612->in3 >> SIN_LBITS) & SIN_MASK][YM2612->en3] + (int) SIN_TAB[(YM2612->in1 >> SIN_LBITS) & SIN_MASK][YM2612->en1] + (int) SIN_TAB[(YM2612->in2 >> SIN_LBITS) & SIN_MASK][YM2612->en2]) >> OUT_SHIFT;  \\\nDO_LIMIT\n\n#define DO_ALGO_7                              \\\nDO_FEEDBACK                                  \\\nCH->OUTd = ((int) SIN_TAB[(YM2612->in3 >> SIN_LBITS) & SIN_MASK][YM2612->en3] + (int) SIN_TAB[(YM2612->in1 >> SIN_LBITS) & SIN_MASK][YM2612->en1] + (int) SIN_TAB[(YM2612->in2 >> SIN_LBITS) & SIN_MASK][YM2612->en2] + CH->S0_OUT[1]) >> OUT_SHIFT;  \\\nDO_LIMIT\n\n\n#define DO_OUTPUT            \\\nbuf[0][i] += CH->OUTd & CH->LEFT;    \\\nbuf[1][i] += CH->OUTd & CH->RIGHT;\n\n\n#define DO_OUTPUT_INT0              \\\nif((int_cnt += YM2612->Inter_Step) & 0x04000)  \\\n{                        \\\n  int_cnt &= 0x3FFF;              \\\n  buf[0][i] += CH->OUTd & CH->LEFT;      \\\n  buf[1][i] += CH->OUTd & CH->RIGHT;      \\\n}                        \\\nelse i--;\n\n\n#define DO_OUTPUT_INT1              \\\nCH->Old_OUTd = (CH->OUTd + CH->Old_OUTd) >> 1;  \\\nif((int_cnt += YM2612->Inter_Step) & 0x04000)  \\\n{                        \\\n  int_cnt &= 0x3FFF;              \\\n  buf[0][i] += CH->Old_OUTd & CH->LEFT;    \\\n  buf[1][i] += CH->Old_OUTd & CH->RIGHT;    \\\n}                        \\\nelse i--;\n\n\n#define DO_OUTPUT_INT2                \\\nif((int_cnt += YM2612->Inter_Step) & 0x04000)    \\\n{                          \\\n  int_cnt &= 0x3FFF;                \\\n  CH->Old_OUTd = (CH->OUTd + CH->Old_OUTd) >> 1;  \\\n  buf[0][i] += CH->Old_OUTd & CH->LEFT;      \\\n  buf[1][i] += CH->Old_OUTd & CH->RIGHT;      \\\n}                          \\\nelse i--;                      \\\nCH->Old_OUTd = CH->OUTd;\n\n\n#define DO_OUTPUT_INT              \\\nif((int_cnt += YM2612->Inter_Step) & 0x04000)  \\\n{                        \\\n  int_cnt &= 0x3FFF;              \\\n  CH->Old_OUTd = (((int_cnt ^ 0x3FFF) * CH->OUTd) + (int_cnt * CH->Old_OUTd)) >> 14;  \\\n  buf[0][i] += CH->Old_OUTd & CH->LEFT;    \\\n  buf[1][i] += CH->Old_OUTd & CH->RIGHT;    \\\n}                        \\\nelse i--;                    \\\nCH->Old_OUTd = CH->OUTd;\n\n\nvoid Update_Chan_Algo0(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 0 len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_0\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo1(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 1 len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_1\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo2(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 2 len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_2\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo3(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 3 len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_3\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo4(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if((CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 4 len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_4\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo5(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if((CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S2].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 5 len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_5\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo6(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if((CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S2].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 6 len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_6\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo7(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if((CH->SLOT[S0].Ecnt == ENV_END) && (CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S2].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 7 len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_7\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo0_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 0 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_0\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo1_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 1 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_1\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo2_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 2 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_2\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo3_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 3 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_3\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo4_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if((CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 4 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_4\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo5_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if((CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S2].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 5 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_5\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo6_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if((CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S2].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 6 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_6\n    DO_OUTPUT\n  }\n}\n\n\nvoid Update_Chan_Algo7_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if((CH->SLOT[S0].Ecnt == ENV_END) && (CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S2].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 7 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_7\n    DO_OUTPUT\n  }\n}\n\n\n/******************************************************\n *          Interpolated output                       *\n *****************************************************/\n\n\nvoid Update_Chan_Algo0_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 0 len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_0\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo1_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 1 len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_1\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo2_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 2 len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_2\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo3_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 3 len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_3\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo4_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if((CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 4 len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_4\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo5_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if((CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S2].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 5 len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_5\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo6_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if((CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S2].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 6 len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_6\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo7_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i;\n\n  if((CH->SLOT[S0].Ecnt == ENV_END) && (CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S2].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 7 len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE\n    GET_CURRENT_ENV\n    UPDATE_ENV\n    DO_ALGO_7\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo0_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 0 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_0\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo1_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 1 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_1\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo2_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 2 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_2\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo3_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if(CH->SLOT[S3].Ecnt == ENV_END) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 3 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_3\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo4_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if((CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 4 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_4\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo5_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if((CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S2].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 5 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_5\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo6_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if((CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S2].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 6 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_6\n    DO_OUTPUT_INT\n  }\n}\n\n\nvoid Update_Chan_Algo7_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght)\n{\n  int i, env_LFO, freq_LFO;\n\n  if((CH->SLOT[S0].Ecnt == ENV_END) && (CH->SLOT[S1].Ecnt == ENV_END) && (CH->SLOT[S2].Ecnt == ENV_END) && (CH->SLOT[S3].Ecnt == ENV_END)) return;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nAlgo 7 LFO len = %d\\n\\n\", lenght);\n#endif\n\n  int_cnt = YM2612->Inter_Cnt;\n\n  for(i = 0; i < lenght; i++)\n  {\n    GET_CURRENT_PHASE\n    UPDATE_PHASE_LFO\n    GET_CURRENT_ENV_LFO\n    UPDATE_ENV\n    DO_ALGO_7\n    DO_OUTPUT_INT\n  }\n}\n\n\n\n/***********************************************\n *            fonctions publiques              *\n ***********************************************/\n\n\n// Initialisation de l'mulateur YM2612\nym2612_ *YM2612_Init(int Clock, int Rate, int Interpolation)\n{\n\tym2612_ *YM2612;\n  int i, j;\n  double x;\n\n  if((Rate == 0) || (Clock == 0)) return NULL;\n\n\tYM2612 = (ym2612_ *)malloc(sizeof(ym2612_));\n  memset(YM2612, 0, sizeof(ym2612_));\n\n#if YM_DEBUG_LEVEL > 0\n  if(debug_file == NULL)\n  {\n    debug_file = fopen(\"ym2612.log\", \"w\");\n    fprintf(debug_file, \"YM2612 logging :\\n\\n\");\n  }\n#endif\n\n  YM2612->Clock = Clock;\n  YM2612->Rate = Rate;\n\n  // 144 = 12 * (prescale * 2) = 12 * 6 * 2\n  // prescale set to 6 by default\n\n  YM2612->Frequence = ((double) YM2612->Clock / (double) YM2612->Rate) / 144.0;\n  YM2612->TimerBase = (int) (YM2612->Frequence * 4096.0);\n\n  if((Interpolation) && (YM2612->Frequence > 1.0))\n  {\n    YM2612->Inter_Step = (unsigned int) ((1.0 / YM2612->Frequence) * (double) (0x4000));\n    YM2612->Inter_Cnt = 0;\n\n    // We recalculate rate and frequence after interpolation\n\n    YM2612->Rate = YM2612->Clock / 144;\n    YM2612->Frequence = 1.0;\n  }\n  else\n  {\n    YM2612->Inter_Step = 0x4000;\n    YM2612->Inter_Cnt = 0;\n  }\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"YM2612 frequence = %g rate = %d  interp step = %.8X\\n\\n\", YM2612->Frequence, YM2612->Rate, YM2612->Inter_Step);\n#endif\n\n  // Tableau TL :\n  // [0     -  4095] = +output  [4095  - ...] = +output overflow (fill with 0)\n  // [12288 - 16383] = -output  [16384 - ...] = -output overflow (fill with 0)\n\n  for(i = 0; i < TL_LENGHT; i++)\n  {\n    if(i >= PG_CUT_OFF)  // YM2612 cut off sound after 78 dB (14 bits output ?)\n    {\n      TL_TAB[TL_LENGHT + i] = TL_TAB[i] = 0;\n    }\n    else\n    {\n      x = MAX_OUT;                // Max output\n      x /= pow(10, (ENV_STEP * i) / 20);      // Decibel -> Voltage\n\n      TL_TAB[i] = (int) x;\n      TL_TAB[TL_LENGHT + i] = -TL_TAB[i];\n    }\n\n#if YM_DEBUG_LEVEL > 2\n    fprintf(debug_file, \"TL_TAB[%d] = %.8X    TL_TAB[%d] = %.8X\\n\", i, TL_TAB[i], TL_LENGHT + i, TL_TAB[TL_LENGHT + i]);\n#endif\n  }\n\n#if YM_DEBUG_LEVEL > 2\n  fprintf(debug_file, \"\\n\\n\\n\\n\");\n#endif\n\n  // Tableau SIN :\n  // SIN_TAB[x][y] = sin(x) * y;\n  // x = phase and y = volume\n\n  SIN_TAB[0] = SIN_TAB[SIN_LENGHT / 2] = &TL_TAB[(int)PG_CUT_OFF];\n\n  for(i = 1; i <= SIN_LENGHT / 4; i++)\n  {\n    x = sin(2.0 * PI * (double) (i) / (double) (SIN_LENGHT));  // Sinus\n    x = 20 * log10(1 / x);                    // convert to dB\n\n    j = (int) (x / ENV_STEP);            // Get TL range\n\n    if(j > PG_CUT_OFF) j = (int) PG_CUT_OFF;\n\n    SIN_TAB[i] = SIN_TAB[(SIN_LENGHT / 2) - i] = &TL_TAB[j];\n    SIN_TAB[(SIN_LENGHT / 2) + i] = SIN_TAB[SIN_LENGHT - i] = &TL_TAB[TL_LENGHT + j];\n\n#if YM_DEBUG_LEVEL > 2\n    fprintf(debug_file, \"SIN[%d][0] = %.8X    SIN[%d][0] = %.8X    SIN[%d][0] = %.8X    SIN[%d][0] = %.8X\\n\", i, SIN_TAB[i][0], (SIN_LENGHT / 2) - i, SIN_TAB[(SIN_LENGHT / 2) - i][0], (SIN_LENGHT / 2) + i, SIN_TAB[(SIN_LENGHT / 2) + i][0], SIN_LENGHT - i, SIN_TAB[SIN_LENGHT - i][0]);\n#endif\n  }\n\n#if YM_DEBUG_LEVEL > 2\n  fprintf(debug_file, \"\\n\\n\\n\\n\");\n#endif\n\n  // Tableau LFO (LFO wav) :\n\n  for(i = 0; i < LFO_LENGHT; i++)\n  {\n    x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGHT));  // Sinus\n    x += 1.0;\n    x /= 2.0;          // positive only\n    x *= 11.8 / ENV_STEP;    // ajusted to MAX enveloppe modulation\n\n    LFO_ENV_TAB[i] = (int) x;\n\n    x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGHT));  // Sinus\n    x *= (double) ((1 << (LFO_HBITS - 1)) - 1);\n\n    LFO_FREQ_TAB[i] = (int) x;\n\n#if YM_DEBUG_LEVEL > 2\n    fprintf(debug_file, \"LFO[%d] = %.8X\\n\", i, LFO_ENV_TAB[i]);\n#endif\n  }\n\n#if YM_DEBUG_LEVEL > 2\n  fprintf(debug_file, \"\\n\\n\\n\\n\");\n#endif\n\n  // Tableau Enveloppe :\n  // ENV_TAB[0] -> ENV_TAB[ENV_LENGHT - 1]        = attack curve\n  // ENV_TAB[ENV_LENGHT] -> ENV_TAB[2 * ENV_LENGHT - 1]  = decay curve\n\n  for(i = 0; i < ENV_LENGHT; i++)\n  {\n    // Attack curve (x^8 - music level 2 Vectorman 2)\n    x = pow(((double) ((ENV_LENGHT - 1) - i) / (double) (ENV_LENGHT)), 8);\n    x *= ENV_LENGHT;\n\n    ENV_TAB[i] = (int) x;\n\n    // Decay curve (just linear)\n    x = pow(((double) (i) / (double) (ENV_LENGHT)), 1);\n    x *= ENV_LENGHT;\n\n    ENV_TAB[ENV_LENGHT + i] = (int) x;\n\n#if YM_DEBUG_LEVEL > 2\n    fprintf(debug_file, \"ATTACK[%d] = %d   DECAY[%d] = %d\\n\", i, ENV_TAB[i], i, ENV_TAB[ENV_LENGHT + i]);\n#endif\n  }\n\n  ENV_TAB[ENV_END >> ENV_LBITS] = ENV_LENGHT - 1;    // for the stopped state\n\n  // Tableau pour la conversion Attack -> Decay and Decay -> Attack\n\n  for(i = 0, j = ENV_LENGHT - 1; i < ENV_LENGHT; i++)\n  {\n    while (j && (ENV_TAB[j] < (unsigned) i)) j--;\n\n    DECAY_TO_ATTACK[i] = j << ENV_LBITS;\n  }\n\n  // Tableau pour le Substain Level\n\n  for(i = 0; i < 15; i++)\n  {\n    x = i * 3;          // 3 and not 6 (Mickey Mania first music for test)\n    x /= ENV_STEP;\n\n    j = (int) x;\n    j <<= ENV_LBITS;\n\n    SL_TAB[i] = j + ENV_DECAY;\n  }\n\n  j = ENV_LENGHT - 1;        // special case : volume off\n  j <<= ENV_LBITS;\n  SL_TAB[15] = j + ENV_DECAY;\n\n  // Tableau Frequency Step\n\n  for(i = 0; i < 2048; i++)\n  {\n    x = (double) (i) * YM2612->Frequence;\n\n#if((SIN_LBITS + SIN_HBITS - (21 - 7)) < 0)\n    x /= (double) (1 << ((21 - 7) - SIN_LBITS - SIN_HBITS));\n#else\n    x *= (double) (1 << (SIN_LBITS + SIN_HBITS - (21 - 7)));\n#endif\n\n    x /= 2.0;  // because MUL = value * 2\n\n    FINC_TAB[i] = (unsigned int) x;\n  }\n\n  // Tableaux Attack & Decay Rate\n\n  for(i = 0; i < 4; i++)\n  {\n    AR_TAB[i] = 0;\n    DR_TAB[i] = 0;\n  }\n\n  for(i = 0; i < 60; i++)\n  {\n    x = YM2612->Frequence;\n\n    x *= 1.0 + ((i & 3) * 0.25);          // bits 0-1 : x1.00, x1.25, x1.50, x1.75\n    x *= (double) (1 << ((i >> 2)));        // bits 2-5 : shift bits (x2^0 - x2^15)\n    x *= (double) (ENV_LENGHT << ENV_LBITS);    // on ajuste pour le tableau ENV_TAB\n\n    AR_TAB[i + 4] = (unsigned int) (x / AR_RATE);\n    DR_TAB[i + 4] = (unsigned int) (x / DR_RATE);\n  }\n\n  for(i = 64; i < 96; i++)\n  {\n    AR_TAB[i] = AR_TAB[63];\n    DR_TAB[i] = DR_TAB[63];\n\n    NULL_RATE[i - 64] = 0;\n  }\n\n  // Tableau Detune\n\n  for(i = 0; i < 4; i++)\n  {\n    for (j = 0; j < 32; j++)\n    {\n#if((SIN_LBITS + SIN_HBITS - 21) < 0)\n      x = (double) DT_DEF_TAB[(i << 5) + j] * YM2612->Frequence / (double) (1 << (21 - SIN_LBITS - SIN_HBITS));\n#else\n      x = (double) DT_DEF_TAB[(i << 5) + j] * YM2612->Frequence * (double) (1 << (SIN_LBITS + SIN_HBITS - 21));\n#endif\n\n      DT_TAB[i + 0][j] = (int) x;\n      DT_TAB[i + 4][j] = (int) -x;\n    }\n  }\n\n  // Tableau LFO\n\n  j = (YM2612->Rate * YM2612->Inter_Step) / 0x4000;\n\n  LFO_INC_TAB[0] = (unsigned int) (3.98 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j);\n  LFO_INC_TAB[1] = (unsigned int) (5.56 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j);\n  LFO_INC_TAB[2] = (unsigned int) (6.02 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j);\n  LFO_INC_TAB[3] = (unsigned int) (6.37 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j);\n  LFO_INC_TAB[4] = (unsigned int) (6.88 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j);\n  LFO_INC_TAB[5] = (unsigned int) (9.63 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j);\n  LFO_INC_TAB[6] = (unsigned int) (48.1 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j);\n  LFO_INC_TAB[7] = (unsigned int) (72.2 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j);\n\n  YM2612_Reset(YM2612);\n\n  return YM2612;\n}\n\n\nint YM2612_End(ym2612_ *YM2612)\n{\n\tfree(YM2612);\n\n#if YM_DEBUG_LEVEL > 0\n  if(debug_file) fclose(debug_file);\n  debug_file = NULL;\n#endif\n\n  return 0;\n}\n\n\nint YM2612_Reset(ym2612_ *YM2612)\n{\n  int i, j;\n\n#if YM_DEBUG_LEVEL > 0\n  fprintf(debug_file, \"\\n\\nStarting reseting YM2612 ...\\n\\n\");\n#endif\n\n  YM2612->LFOcnt = 0;\n  YM2612->TimerA = 0;\n  YM2612->TimerAL = 0;\n  YM2612->TimerAcnt = 0;\n  YM2612->TimerB = 0;\n  YM2612->TimerBL = 0;\n  YM2612->TimerBcnt = 0;\n  YM2612->DAC = 0;\n  YM2612->DACdata = 0;\n\tYM2612->dac_highpass = 0;\n\n  YM2612->Status = 0;\n\n  YM2612->OPNAadr = 0;\n  YM2612->OPNBadr = 0;\n  YM2612->Inter_Cnt = 0;\n\n  for(i = 0; i < 6; i++)\n  {\n    YM2612->CHANNEL[i].Old_OUTd = 0;\n    YM2612->CHANNEL[i].OUTd = 0;\n    YM2612->CHANNEL[i].LEFT = 0xFFFFFFFF;\n    YM2612->CHANNEL[i].RIGHT = 0xFFFFFFFF;\n    YM2612->CHANNEL[i].ALGO = 0;;\n    YM2612->CHANNEL[i].FB = 31;\n    YM2612->CHANNEL[i].FMS = 0;\n    YM2612->CHANNEL[i].AMS = 0;\n\n    for(j = 0 ;j < 4 ; j++)\n    {\n      YM2612->CHANNEL[i].S0_OUT[j] = 0;\n      YM2612->CHANNEL[i].FNUM[j] = 0;\n      YM2612->CHANNEL[i].FOCT[j] = 0;\n      YM2612->CHANNEL[i].KC[j] = 0;\n\n      YM2612->CHANNEL[i].SLOT[j].Fcnt = 0;\n      YM2612->CHANNEL[i].SLOT[j].Finc = 0;\n      YM2612->CHANNEL[i].SLOT[j].Ecnt = ENV_END;    // Put it at the end of Decay phase...\n      YM2612->CHANNEL[i].SLOT[j].Einc = 0;\n      YM2612->CHANNEL[i].SLOT[j].Ecmp = 0;\n      YM2612->CHANNEL[i].SLOT[j].Ecurp = RELEASE;\n\n      YM2612->CHANNEL[i].SLOT[j].ChgEnM = 0;\n    }\n  }\n\n  for(i = 0; i < 0x100; i++)\n  {\n    YM2612->REG[0][i] = -1;\n    YM2612->REG[1][i] = -1;\n  }\n\n  for(i = 0xB6; i >= 0xB4; i--)\n  {\n    YM2612_Write(YM2612, 0, (unsigned char) i);\n    YM2612_Write(YM2612, 2, (unsigned char) i);\n    YM2612_Write(YM2612, 1, 0xC0);\n    YM2612_Write(YM2612, 3, 0xC0);\n  }\n\n  for(i = 0xB2; i >= 0x22; i--)\n  {\n    YM2612_Write(YM2612, 0, (unsigned char) i);\n    YM2612_Write(YM2612, 2, (unsigned char) i);\n    YM2612_Write(YM2612, 1, 0);\n    YM2612_Write(YM2612, 3, 0);\n  }\n\n  YM2612_Write(YM2612, 0, 0x2A);\n  YM2612_Write(YM2612, 1, 0x80);\n\n#if YM_DEBUG_LEVEL > 0\n  fprintf(debug_file, \"\\n\\nFinishing reseting YM2612 ...\\n\\n\");\n#endif\n\n  return 0;\n}\n\n\nint YM2612_Read(ym2612_ *YM2612)\n{\n/*  static int cnt = 0;\n\n  if(cnt++ == 50)\n  {\n    cnt = 0;\n    return YM2612->Status;\n  }\n  else return YM2612->Status | 0x80;\n*/\n  return YM2612->Status;\n}\n\n\nint YM2612_Write(ym2612_ *YM2612, unsigned char adr, unsigned char data)\n{\n  int d;\n\n  data &= 0xFF;\n  adr  &= 0x03;\n\n  switch(adr)\n  {\n    case 0:\n      YM2612->OPNAadr = data;\n      break;\n\n    case 1:\n      // Trivial optimisation\n      if(YM2612->OPNAadr == 0x2A)\n      {\n        YM2612->DACdata = ((int)data - 0x80) << DAC_SHIFT;\n        return 0;\n      }\n\n      d = YM2612->OPNAadr & 0xF0;\n\n      if(d >= 0x30)\n      {\n        if(YM2612->REG[0][YM2612->OPNAadr] == data) return 2;\n        YM2612->REG[0][YM2612->OPNAadr] = data;\n\n//\t\t\t\tif (GYM_Dumping) Update_GYM_Dump(1, YM2612->OPNAadr, data);\n\n        if(d < 0xA0)    // SLOT\n        {\n          SLOT_SET(YM2612, YM2612->OPNAadr, data);\n        }\n        else        // CHANNEL\n        {\n          CHANNEL_SET(YM2612, YM2612->OPNAadr, data);\n        }\n      }\n      else          // YM2612\n      {\n        YM2612->REG[0][YM2612->OPNAadr] = data;\n\n//\t\t\t\tif ((GYM_Dumping) && ((YM2612->OPNAadr == 0x22) || (YM2612->OPNAadr == 0x27) || (YM2612->OPNAadr == 0x28))) Update_GYM_Dump(1, YM2612->OPNAadr, data);\n\n        YM_SET(YM2612, YM2612->OPNAadr, data);\n      }\n      break;\n\n    case 2:\n      YM2612->OPNBadr = data;\n      break;\n\n    case 3:\n      d = YM2612->OPNBadr & 0xF0;\n\n      if(d >= 0x30)\n      {\n        if(YM2612->REG[1][YM2612->OPNBadr] == data) return 2;\n        YM2612->REG[1][YM2612->OPNBadr] = data;\n\n//\t\t\t\tif (GYM_Dumping) Update_GYM_Dump(2, YM2612->OPNBadr, data);\n\n        if(d < 0xA0)    // SLOT\n        {\n          SLOT_SET(YM2612, YM2612->OPNBadr + 0x100, data);\n        }\n        else        // CHANNEL\n        {\n          CHANNEL_SET(YM2612, YM2612->OPNBadr + 0x100, data);\n        }\n      }\n      else return 1;\n      break;\n  }\n\n  return 0;\n}\n\nint YM2612_GetMute(ym2612_ *YM2612)\n{\n  int i, result = 0;\n  for (i = 0; i < 6; ++i)\n  {\n    result |= YM2612->CHANNEL[i].Mute << i;\n  }\n  result |= YM2612->DAC_Mute << 6;\n\t//result &= !(YM2612_Enable_SSGEG);\n  return result;  \n}\n\nvoid YM2612_SetMute(ym2612_ *YM2612, int val)\n{\n  int i;\n  for (i = 0; i < 6; ++i)\n  {\n    YM2612->CHANNEL[i].Mute = (val >> i) & 1;\n  }\n  YM2612->DAC_Mute = (val >> 6) & 1;\n\t//YM2612_Enable_SSGEG = !(val & 1);\n}\n\nvoid YM2612_SetOptions(int Flags)\n{\n\tDAC_Highpass_Enable = (Flags >> 0) & 0x01;\n\tYM2612_Enable_SSGEG = (Flags >> 1) & 0x01;\n}\n\nvoid YM2612_ClearBuffer(int **buffer, int length)\n{\n\t// the MAME core does this before updating,\n\t// but the Gens core does this before mixing\n\tint *bufL, *bufR;\n\tint i;\n\t\n\tbufL = buffer[0];\n\tbufR = buffer[1];\n\t\n\tfor(i = 0; i < length; i++)\n\t{\n\t\tbufL[i] = 0x0000;\n\t\tbufR[i] = 0x0000;\n\t}\n}\n\nvoid YM2612_Update(ym2612_ *YM2612, int **buf, int length)\n{\n  int i, j, algo_type;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nStarting generating sound...\\n\\n\");\n#endif\n\n  // Mise ?jour des pas des compteurs-frquences s'ils ont t?modifis\n\n  if(YM2612->CHANNEL[0].SLOT[0].Finc == -1) CALC_FINC_CH(&YM2612->CHANNEL[0]);\n  if(YM2612->CHANNEL[1].SLOT[0].Finc == -1) CALC_FINC_CH(&YM2612->CHANNEL[1]);\n  if(YM2612->CHANNEL[2].SLOT[0].Finc == -1)\n  {\n    if(YM2612->Mode & 0x40)\n    {\n      CALC_FINC_SL(&(YM2612->CHANNEL[2].SLOT[S0]), FINC_TAB[YM2612->CHANNEL[2].FNUM[2]] >> (7 - YM2612->CHANNEL[2].FOCT[2]), YM2612->CHANNEL[2].KC[2]);\n      CALC_FINC_SL(&(YM2612->CHANNEL[2].SLOT[S1]), FINC_TAB[YM2612->CHANNEL[2].FNUM[3]] >> (7 - YM2612->CHANNEL[2].FOCT[3]), YM2612->CHANNEL[2].KC[3]);\n      CALC_FINC_SL(&(YM2612->CHANNEL[2].SLOT[S2]), FINC_TAB[YM2612->CHANNEL[2].FNUM[1]] >> (7 - YM2612->CHANNEL[2].FOCT[1]), YM2612->CHANNEL[2].KC[1]);\n      CALC_FINC_SL(&(YM2612->CHANNEL[2].SLOT[S3]), FINC_TAB[YM2612->CHANNEL[2].FNUM[0]] >> (7 - YM2612->CHANNEL[2].FOCT[0]), YM2612->CHANNEL[2].KC[0]);\n    }\n    else\n    {\n      CALC_FINC_CH(&YM2612->CHANNEL[2]);\n    }\n  }\n  if(YM2612->CHANNEL[3].SLOT[0].Finc == -1) CALC_FINC_CH(&YM2612->CHANNEL[3]);\n  if(YM2612->CHANNEL[4].SLOT[0].Finc == -1) CALC_FINC_CH(&YM2612->CHANNEL[4]);\n  if(YM2612->CHANNEL[5].SLOT[0].Finc == -1) CALC_FINC_CH(&YM2612->CHANNEL[5]);\n\n/*\n  CALC_FINC_CH(&YM2612->CHANNEL[0]);\n  CALC_FINC_CH(&YM2612->CHANNEL[1]);\n  if(YM2612->Mode & 0x40)\n  {\n    CALC_FINC_SL(&(YM2612->CHANNEL[2].SLOT[0]), FINC_TAB[YM2612->CHANNEL[2].FNUM[2]] >> (7 - YM2612->CHANNEL[2].FOCT[2]), YM2612->CHANNEL[2].KC[2]);\n    CALC_FINC_SL(&(YM2612->CHANNEL[2].SLOT[1]), FINC_TAB[YM2612->CHANNEL[2].FNUM[3]] >> (7 - YM2612->CHANNEL[2].FOCT[3]), YM2612->CHANNEL[2].KC[3]);\n    CALC_FINC_SL(&(YM2612->CHANNEL[2].SLOT[2]), FINC_TAB[YM2612->CHANNEL[2].FNUM[1]] >> (7 - YM2612->CHANNEL[2].FOCT[1]), YM2612->CHANNEL[2].KC[1]);\n    CALC_FINC_SL(&(YM2612->CHANNEL[2].SLOT[3]), FINC_TAB[YM2612->CHANNEL[2].FNUM[0]] >> (7 - YM2612->CHANNEL[2].FOCT[0]), YM2612->CHANNEL[2].KC[0]);\n  }\n  else\n  {\n    CALC_FINC_CH(&YM2612->CHANNEL[2]);\n  }\n  CALC_FINC_CH(&YM2612->CHANNEL[3]);\n  CALC_FINC_CH(&YM2612->CHANNEL[4]);\n  CALC_FINC_CH(&YM2612->CHANNEL[5]);\n*/\n\n  if(YM2612->Inter_Step & 0x04000) algo_type = 0;\n  else algo_type = 16;\n\n  if(YM2612->LFOinc)\n  {\n    // Precalcul LFO wav\n\n    for(i = 0; i < length; i++)\n    {\n      j = ((YM2612->LFOcnt += YM2612->LFOinc) >> LFO_LBITS) & LFO_MASK;\n\n      YM2612->LFO_ENV_UP[i] = LFO_ENV_TAB[j];\n      YM2612->LFO_FREQ_UP[i] = LFO_FREQ_TAB[j];\n\n#if YM_DEBUG_LEVEL > 3\n      fprintf(debug_file, \"LFO_ENV_UP[%d] = %d   LFO_FREQ_UP[%d] = %d\\n\", i, YM2612->LFO_ENV_UP[i], i, YM2612->LFO_FREQ_UP[i]);\n#endif\n    }\n\n    algo_type |= 8;\n  }\n\n\n  if (!YM2612->CHANNEL[0].Mute) UPDATE_CHAN[YM2612->CHANNEL[0].ALGO + algo_type](YM2612, &(YM2612->CHANNEL[0]), buf, length);\n\tif (!YM2612->CHANNEL[1].Mute) UPDATE_CHAN[YM2612->CHANNEL[1].ALGO + algo_type](YM2612, &(YM2612->CHANNEL[1]), buf, length);\n\tif (!YM2612->CHANNEL[2].Mute) UPDATE_CHAN[YM2612->CHANNEL[2].ALGO + algo_type](YM2612, &(YM2612->CHANNEL[2]), buf, length);\n\tif (!YM2612->CHANNEL[3].Mute) UPDATE_CHAN[YM2612->CHANNEL[3].ALGO + algo_type](YM2612, &(YM2612->CHANNEL[3]), buf, length);\n\tif (!YM2612->CHANNEL[4].Mute) UPDATE_CHAN[YM2612->CHANNEL[4].ALGO + algo_type](YM2612, &(YM2612->CHANNEL[4]), buf, length);\n\tif (!YM2612->CHANNEL[5].Mute \n\t\t&& !(YM2612->DAC))          UPDATE_CHAN[YM2612->CHANNEL[5].ALGO + algo_type](YM2612, &(YM2612->CHANNEL[5]), buf, length);\n\n  YM2612->Inter_Cnt = int_cnt;\n\n#if YM_DEBUG_LEVEL > 1\n  fprintf(debug_file, \"\\n\\nFinishing generating sound...\\n\\n\");\n#endif\n\n}\n\n\n/*int YM2612_Save(ym2612_ *YM2612, unsigned char SAVE[0x200])\n{\n  int i;\n\n  for(i = 0; i < 0x100; i++)\n  {\n    SAVE[0x000 + i] = YM2612->REG[0][i];\n    SAVE[0x100 + i] = YM2612->REG[1][i];\n  }\n\n  return 0;\n}\n\n\nint YM2612_Restore(ym2612_ *YM2612, unsigned char SAVE[0x200])\n{\n  int i;\n\n  YM2612_Reset(YM2612);\n\n  for(i = 0; i < 0x100; i++)\n  {\n    YM2612_Write(YM2612, 0, (unsigned char) i);\n    YM2612_Write(YM2612, 1, SAVE[0x000 + i]);\n    YM2612_Write(YM2612, 2, (unsigned char) i);\n    YM2612_Write(YM2612, 3, SAVE[0x100 + i]);\n  }\n\n  return 0;\n}*/\n\n/* Gens */\n\nenum { highpass_fract = 15 };\nenum { highpass_shift = 9 }; // higher values reduce highpass on DAC\nvoid YM2612_DacAndTimers_Update(ym2612_ *YM2612, int **buffer, int length)\n{\n  int *bufL, *bufR;\n  int i;\n\n  if(YM2612->DAC && YM2612->DACdata && ! YM2612->DAC_Mute)\n  {\n\n    bufL = buffer[0];\n    bufR = buffer[1];\n\n    for(i = 0; i < length; i++)\n    {\n\t\t\tlong dac = (YM2612->DACdata << highpass_fract) - YM2612->dac_highpass;\n\t\t\tif (DAC_Highpass_Enable)\t// else it's left at 0 and doesn't affect the sound\n\t\t\t\tYM2612->dac_highpass += dac >> highpass_shift;\n\t\t\tdac >>= highpass_fract;\n\t\t\tbufL[i] += dac & YM2612->CHANNEL[5].LEFT;\n\t\t\tbufR[i] += dac & YM2612->CHANNEL[5].RIGHT;\n    }\n  }\n\n  i = YM2612->TimerBase * length;\n\n  if(YM2612->Mode & 1)              // Timer A ON ?\n  {\n//    if((YM2612->TimerAcnt -= 14073) <= 0)    // 13879=NTSC (old: 14475=NTSC  14586=PAL)\n    if((YM2612->TimerAcnt -= i) <= 0)\n    {\n      YM2612->Status |= (YM2612->Mode & 0x04) >> 2;\n      YM2612->TimerAcnt += YM2612->TimerAL;\n\n#if YM_DEBUG_LEVEL > 0\n      fprintf(debug_file, \"Counter A overflow\\n\");\n#endif\n\n      if(YM2612->Mode & 0x80) CSM_Key_Control(YM2612);\n    }\n  }\n\n  if(YM2612->Mode & 2)              // Timer B ON ?\n  {\n//    if((YM2612->TimerBcnt -= 14073) <= 0)    // 13879=NTSC (old: 14475=NTSC  14586=PAL)\n    if((YM2612->TimerBcnt -= i) <= 0)\n    {\n      YM2612->Status |= (YM2612->Mode & 0x08) >> 2;\n      YM2612->TimerBcnt += YM2612->TimerBL;\n\n#if YM_DEBUG_LEVEL > 0\n      fprintf(debug_file, \"Counter B overflow\\n\");\n#endif\n    }\n  }\n}\n\n/* Gens */\n\nvoid YM2612_Special_Update(ym2612_ *YM2612)\n{\n/*\tif (YM_Len && YM2612_Enable)\n  {\n    YM2612_Update(YM_Buf, YM_Len);\n\n\t\tYM_Buf[0] = Seg_L + Sound_Extrapol[VDP_Current_Line + 1][0];\n\t\tYM_Buf[1] = Seg_R + Sound_Extrapol[VDP_Current_Line + 1][0];\n    YM_Len = 0;\n\t}*/\n}\n\n/* end */\n"
  },
  {
    "path": "VGMPlay/chips/ym2612.h",
    "content": "#ifndef _YM2612_H_\n#define _YM2612_H_\n\n// Change it if you need to do long update\n//#define\tMAX_UPDATE_LENGHT   4000\n#define\tMAX_UPDATE_LENGHT   0x100\n//#define\tMAX_UPDATE_LENGHT   1\t// for in_vgm\n\n// Gens always uses 16 bits sound (in 32 bits buffer) and do the convertion later if needed.\n#define OUTPUT_BITS         15\n// OUTPUT_BITS 15 is MAME's volume level\n#define DAC_SHIFT\t\t\t(OUTPUT_BITS - 9)\n// DAC_SHIFT makes sure that FM and DAC volume has the same volume\n\n// VC++ inline\n#ifndef INLINE\n#define INLINE              __inline\n#endif\n\ntypedef struct slot__ {\n\tint *DT;\t// paramtre detune\n\tint MUL;\t// paramtre \"multiple de frquence\"\n\tint TL;\t\t// Total Level = volume lorsque l'enveloppe est au plus haut\n\tint TLL;\t// Total Level ajusted\n\tint SLL;\t// Sustin Level (ajusted) = volume o l'enveloppe termine sa premire phase de rgression\n\tint KSR_S;\t// Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe\n\tint KSR;\t// Key Scale Rate = cette valeur est calcule par rapport  la frquence actuelle, elle va influer\n\t\t\t\t// sur les diffrents paramtres de l'enveloppe comme l'attaque, le decay ...  comme dans la ralit !\n\tint SEG;\t// Type enveloppe SSG\n\tint *AR;\t// Attack Rate (table pointeur) = Taux d'attaque (AR[KSR])\n\tint *DR;\t// Decay Rate (table pointeur) = Taux pour la rgression (DR[KSR])\n\tint *SR;\t// Sustin Rate (table pointeur) = Taux pour le maintien (SR[KSR])\n\tint *RR;\t// Release Rate (table pointeur) = Taux pour le relchement (RR[KSR])\n\tint Fcnt;\t// Frequency Count = compteur-frquence pour dterminer l'amplitude actuelle (SIN[Finc >> 16])\n\tint Finc;\t// frequency step = pas d'incrmentation du compteur-frquence\n\t\t\t\t// plus le pas est grand, plus la frquence est agu (ou haute)\n\tint Ecurp;\t// Envelope current phase = cette variable permet de savoir dans quelle phase\n\t\t\t\t// de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ...\n\t\t\t\t// en fonction de la valeur de cette variable, on va appeler une fonction permettant\n\t\t\t\t// de mettre  jour l'enveloppe courante.\n\tint Ecnt;\t// Envelope counter = le compteur-enveloppe permet de savoir o l'on se trouve dans l'enveloppe\n\tint Einc;\t// Envelope step courant\n\tint Ecmp;\t// Envelope counter limite pour la prochaine phase\n\tint EincA;\t// Envelope step for Attack = pas d'incrmentation du compteur durant la phase d'attaque\n\t\t\t\t// cette valeur est gal  AR[KSR]\n\tint EincD;\t// Envelope step for Decay = pas d'incrmentation du compteur durant la phase de regression\n\t\t\t\t// cette valeur est gal  DR[KSR]\n\tint EincS;\t// Envelope step for Sustain = pas d'incrmentation du compteur durant la phase de maintenue\n\t\t\t\t// cette valeur est gal  SR[KSR]\n\tint EincR;\t// Envelope step for Release = pas d'incrmentation du compteur durant la phase de relchement\n\t\t\t\t// cette valeur est gal  RR[KSR]\n\tint *OUTp;\t// pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot  l'entre\n\t\t\t\t// d'un autre ou carrement  la sortie de la voie\n\tint INd;\t// input data of the slot = donnes en entre du slot\n\tint ChgEnM;\t// Change envelop mask.\n\tint AMS;\t// AMS depth level of this SLOT = degr de modulation de l'amplitude par le LFO\n\tint AMSon;\t// AMS enable flag = drapeau d'activation de l'AMS\n} slot_;\n\ntypedef struct channel__ {\n\tint S0_OUT[4];\t\t\t// anciennes sorties slot 0 (pour le feed back)\n\tint Old_OUTd;\t\t\t// ancienne sortie de la voie (son brut)\n\tint OUTd;\t\t\t\t// sortie de la voie (son brut)\n\tint LEFT;\t\t\t\t// LEFT enable flag\n\tint RIGHT;\t\t\t\t// RIGHT enable flag\n\tint ALGO;\t\t\t\t// Algorythm = dtermine les connections entre les oprateurs\n\tint FB;\t\t\t\t\t// shift count of self feed back = degr de \"Feed-Back\" du SLOT 1 (il est son unique entre)\n\tint FMS;\t\t\t\t// Frquency Modulation Sensitivity of channel = degr de modulation de la frquence sur la voie par le LFO\n\tint AMS;\t\t\t\t// Amplitude Modulation Sensitivity of channel = degr de modulation de l'amplitude sur la voie par le LFO\n\tint FNUM[4];\t\t\t// hauteur frquence de la voie (+ 3 pour le mode spcial)\n\tint FOCT[4];\t\t\t// octave de la voie (+ 3 pour le mode spcial)\n\tint KC[4];\t\t\t\t// Key Code = valeur fonction de la frquence (voir KSR pour les slots, KSR = KC >> KSR_S)\n\tstruct slot__ SLOT[4];\t// four slot.operators = les 4 slots de la voie\n\tint FFlag;\t\t\t\t// Frequency step recalculation flag\n  int Mute;         // Maxim: channel mute flag\n} channel_;\n\ntypedef struct ym2612__ {\n\tint Clock;\t\t\t// Horloge YM2612\n\tint Rate;\t\t\t// Sample Rate (11025/22050/44100)\n\tint TimerBase;\t\t// TimerBase calculation\n\tint Status;\t\t\t// YM2612 Status (timer overflow)\n\tint OPNAadr;\t\t// addresse pour l'criture dans l'OPN A (propre  l'mulateur)\n\tint OPNBadr;\t\t// addresse pour l'criture dans l'OPN B (propre  l'mulateur)\n\tint LFOcnt;\t\t\t// LFO counter = compteur-frquence pour le LFO\n\tint LFOinc;\t\t\t// LFO step counter = pas d'incrmentation du compteur-frquence du LFO\n\t\t\t\t\t\t// plus le pas est grand, plus la frquence est grande\n\tint TimerA;\t\t\t// timerA limit = valeur jusqu' laquelle le timer A doit compter\n\tint TimerAL;\n\tint TimerAcnt;\t\t// timerA counter = valeur courante du Timer A\n\tint TimerB;\t\t\t// timerB limit = valeur jusqu' laquelle le timer B doit compter\n\tint TimerBL;\n\tint TimerBcnt;\t\t// timerB counter = valeur courante du Timer B\n\tint Mode;\t\t\t// Mode actuel des voie 3 et 6 (normal / spcial)\n\tint DAC;\t\t\t// DAC enabled flag\n\tint DACdata;\t\t// DAC data\n\tlong dac_highpass;\n\tdouble Frequence;\t// Frquence de base, se calcul par rapport  l'horlage et au sample rate\n\tunsigned int Inter_Cnt;\t\t\t// Interpolation Counter\n\tunsigned int Inter_Step;\t\t// Interpolation Step\n\tstruct channel__ CHANNEL[6];\t// Les 6 voies du YM2612\n\tint REG[2][0x100];\t// Sauvegardes des valeurs de tout les registres, c'est facultatif\n\t\t\t\t\t\t// cela nous rend le dbuggage plus facile\n\n\tint LFO_ENV_UP[MAX_UPDATE_LENGHT];      // Temporary calculated LFO AMS (adjusted for 11.8 dB) *\n\tint LFO_FREQ_UP[MAX_UPDATE_LENGHT];      // Temporary calculated LFO FMS *\n\n\tint in0, in1, in2, in3;            // current phase calculation *\n\tint en0, en1, en2, en3;            // current enveloppe calculation *\n\n\tint DAC_Mute;\n} ym2612_;\n\n/* Gens */\n\n//extern int YM2612_Enable;\n//extern int YM2612_Improv;\n//extern int DAC_Enable;\n//extern int *YM_Buf[2];\n//extern int YM_Len;\n\n/* end */\n\nym2612_ *YM2612_Init(int clock, int rate, int interpolation);\nint YM2612_End(ym2612_ *YM2612);\nint YM2612_Reset(ym2612_ *YM2612);\nint YM2612_Read(ym2612_ *YM2612);\nint YM2612_Write(ym2612_ *YM2612, unsigned char adr, unsigned char data);\nvoid YM2612_ClearBuffer(int **buffer, int length);\nvoid YM2612_Update(ym2612_ *YM2612, int **buf, int length);\n/*int YM2612_Save(ym2612_ *YM2612, unsigned char SAVE[0x200]);\nint YM2612_Restore(ym2612_ *YM2612, unsigned char SAVE[0x200]);*/\n\n/* Maxim: muting (bits 0-5 for channels 0-5) */\nint YM2612_GetMute(ym2612_ *YM2612);\nvoid YM2612_SetMute(ym2612_ *YM2612, int val);\nvoid YM2612_SetOptions(int Flags);\n\n/* Gens */\n\nvoid YM2612_DacAndTimers_Update(ym2612_ *YM2612, int **buffer, int length);\nvoid YM2612_Special_Update(ym2612_ *YM2612);\n\n/* end */\n\n// used for foward...\nvoid Update_Chan_Algo0(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo1(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo2(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo3(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo4(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo5(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo6(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo7(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\n\nvoid Update_Chan_Algo0_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo1_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo2_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo3_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo4_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo5_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo6_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo7_LFO(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\n\nvoid Update_Chan_Algo0_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo1_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo2_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo3_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo4_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo5_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo6_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo7_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\n\nvoid Update_Chan_Algo0_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo1_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo2_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo3_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo4_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo5_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo6_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\nvoid Update_Chan_Algo7_LFO_Int(ym2612_ *YM2612, channel_ *CH, int **buf, int lenght);\n\n// used for foward...\nvoid Env_Attack_Next(slot_ *SL);\nvoid Env_Decay_Next(slot_ *SL);\nvoid Env_Substain_Next(slot_ *SL);\nvoid Env_Release_Next(slot_ *SL);\nvoid Env_NULL_Next(slot_ *SL);\n\n#endif\n"
  },
  {
    "path": "VGMPlay/chips/ym3438.c",
    "content": "//\n// Copyright (C) 2017 Alexey Khokholov (Nuke.YKT)\n// \n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n//\n//\n//  Nuked OPN2(Yamaha YM3438) emulator.\n//  Thanks:\n//      Silicon Pr0n:\n//          Yamaha YM3438 decap and die shot(digshadow).\n//      OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):\n//          OPL2 ROMs.\n//\n// version: 1.0.7\n//\n\n#include <string.h>\n#include \"ym3438.h\"\n\n#define OUTPUT_FACTOR 11\n#define OUTPUT_FACTOR_F 12\n#define FILTER_CUTOFF 0.512331301282628 // 5894Hz  single pole IIR low pass\n#define FILTER_CUTOFF_I (1-FILTER_CUTOFF)\n\nenum {\n    eg_num_attack = 0,\n    eg_num_decay = 1,\n    eg_num_sustain = 2,\n    eg_num_release = 3\n};\n\n/* logsin table */\nstatic const Bit16u logsinrom[256] = {\n    0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471,\n    0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365,\n    0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd,\n    0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261,\n    0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f,\n    0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd,\n    0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195,\n    0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166,\n    0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c,\n    0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118,\n    0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8,\n    0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db,\n    0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1,\n    0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9,\n    0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094,\n    0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081,\n    0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070,\n    0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060,\n    0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052,\n    0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045,\n    0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039,\n    0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f,\n    0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026,\n    0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e,\n    0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017,\n    0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011,\n    0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c,\n    0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007,\n    0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004,\n    0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002,\n    0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001,\n    0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000\n};\n\n/* exp table */\nstatic const Bit16u exprom[256] = {\n    0x000, 0x003, 0x006, 0x008, 0x00b, 0x00e, 0x011, 0x014,\n    0x016, 0x019, 0x01c, 0x01f, 0x022, 0x025, 0x028, 0x02a,\n    0x02d, 0x030, 0x033, 0x036, 0x039, 0x03c, 0x03f, 0x042,\n    0x045, 0x048, 0x04b, 0x04e, 0x051, 0x054, 0x057, 0x05a,\n    0x05d, 0x060, 0x063, 0x066, 0x069, 0x06c, 0x06f, 0x072,\n    0x075, 0x078, 0x07b, 0x07e, 0x082, 0x085, 0x088, 0x08b,\n    0x08e, 0x091, 0x094, 0x098, 0x09b, 0x09e, 0x0a1, 0x0a4,\n    0x0a8, 0x0ab, 0x0ae, 0x0b1, 0x0b5, 0x0b8, 0x0bb, 0x0be,\n    0x0c2, 0x0c5, 0x0c8, 0x0cc, 0x0cf, 0x0d2, 0x0d6, 0x0d9,\n    0x0dc, 0x0e0, 0x0e3, 0x0e7, 0x0ea, 0x0ed, 0x0f1, 0x0f4,\n    0x0f8, 0x0fb, 0x0ff, 0x102, 0x106, 0x109, 0x10c, 0x110,\n    0x114, 0x117, 0x11b, 0x11e, 0x122, 0x125, 0x129, 0x12c,\n    0x130, 0x134, 0x137, 0x13b, 0x13e, 0x142, 0x146, 0x149,\n    0x14d, 0x151, 0x154, 0x158, 0x15c, 0x160, 0x163, 0x167,\n    0x16b, 0x16f, 0x172, 0x176, 0x17a, 0x17e, 0x181, 0x185,\n    0x189, 0x18d, 0x191, 0x195, 0x199, 0x19c, 0x1a0, 0x1a4,\n    0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc, 0x1c0, 0x1c4,\n    0x1c8, 0x1cc, 0x1d0, 0x1d4, 0x1d8, 0x1dc, 0x1e0, 0x1e4,\n    0x1e8, 0x1ec, 0x1f0, 0x1f5, 0x1f9, 0x1fd, 0x201, 0x205,\n    0x209, 0x20e, 0x212, 0x216, 0x21a, 0x21e, 0x223, 0x227,\n    0x22b, 0x230, 0x234, 0x238, 0x23c, 0x241, 0x245, 0x249,\n    0x24e, 0x252, 0x257, 0x25b, 0x25f, 0x264, 0x268, 0x26d,\n    0x271, 0x276, 0x27a, 0x27f, 0x283, 0x288, 0x28c, 0x291,\n    0x295, 0x29a, 0x29e, 0x2a3, 0x2a8, 0x2ac, 0x2b1, 0x2b5,\n    0x2ba, 0x2bf, 0x2c4, 0x2c8, 0x2cd, 0x2d2, 0x2d6, 0x2db,\n    0x2e0, 0x2e5, 0x2e9, 0x2ee, 0x2f3, 0x2f8, 0x2fd, 0x302,\n    0x306, 0x30b, 0x310, 0x315, 0x31a, 0x31f, 0x324, 0x329,\n    0x32e, 0x333, 0x338, 0x33d, 0x342, 0x347, 0x34c, 0x351,\n    0x356, 0x35b, 0x360, 0x365, 0x36a, 0x370, 0x375, 0x37a,\n    0x37f, 0x384, 0x38a, 0x38f, 0x394, 0x399, 0x39f, 0x3a4,\n    0x3a9, 0x3ae, 0x3b4, 0x3b9, 0x3bf, 0x3c4, 0x3c9, 0x3cf,\n    0x3d4, 0x3da, 0x3df, 0x3e4, 0x3ea, 0x3ef, 0x3f5, 0x3fa\n};\n\n/* Note table */\nstatic const Bit32u fn_note[16] = {\n    0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3\n};\n\n/* Envelope generator */\nstatic const Bit32u eg_stephi[4][4] = {\n    { 0, 0, 0, 0 },\n    { 1, 0, 0, 0 },\n    { 1, 0, 1, 0 },\n    { 1, 1, 1, 0 }\n};\n\nstatic const Bit8u eg_am_shift[4] = {\n    7, 3, 1, 0\n};\n\n/* Phase generator */\nstatic const Bit32u pg_detune[8] = { 16, 17, 19, 20, 22, 24, 27, 29 };\n\nstatic const Bit32u pg_lfo_sh1[8][8] = {\n    { 7, 7, 7, 7, 7, 7, 7, 7 },\n    { 7, 7, 7, 7, 7, 7, 7, 7 },\n    { 7, 7, 7, 7, 7, 7, 1, 1 },\n    { 7, 7, 7, 7, 1, 1, 1, 1 },\n    { 7, 7, 7, 1, 1, 1, 1, 0 },\n    { 7, 7, 1, 1, 0, 0, 0, 0 },\n    { 7, 7, 1, 1, 0, 0, 0, 0 },\n    { 7, 7, 1, 1, 0, 0, 0, 0 }\n};\n\nstatic const Bit32u pg_lfo_sh2[8][8] = {\n    { 7, 7, 7, 7, 7, 7, 7, 7 },\n    { 7, 7, 7, 7, 2, 2, 2, 2 },\n    { 7, 7, 7, 2, 2, 2, 7, 7 },\n    { 7, 7, 2, 2, 7, 7, 2, 2 },\n    { 7, 7, 2, 7, 7, 7, 2, 7 },\n    { 7, 7, 7, 2, 7, 7, 2, 1 },\n    { 7, 7, 7, 2, 7, 7, 2, 1 },\n    { 7, 7, 7, 2, 7, 7, 2, 1 }\n};\n\n/* Address decoder */\nstatic const Bit32u op_offset[12] = {\n    0x000, /* Ch1 OP1/OP2 */\n    0x001, /* Ch2 OP1/OP2 */\n    0x002, /* Ch3 OP1/OP2 */\n    0x100, /* Ch4 OP1/OP2 */\n    0x101, /* Ch5 OP1/OP2 */\n    0x102, /* Ch6 OP1/OP2 */\n    0x004, /* Ch1 OP3/OP4 */\n    0x005, /* Ch2 OP3/OP4 */\n    0x006, /* Ch3 OP3/OP4 */\n    0x104, /* Ch4 OP3/OP4 */\n    0x105, /* Ch5 OP3/OP4 */\n    0x106  /* Ch6 OP3/OP4 */\n};\n\nstatic const Bit32u ch_offset[6] = {\n    0x000, /* Ch1 */\n    0x001, /* Ch2 */\n    0x002, /* Ch3 */\n    0x100, /* Ch4 */\n    0x101, /* Ch5 */\n    0x102  /* Ch6 */\n};\n\n/* LFO */\nstatic const Bit32u lfo_cycles[8] = {\n    108, 77, 71, 67, 62, 44, 8, 5\n};\n\n/* FM algorithm */\nstatic const Bit32u fm_algorithm[4][6][8] = {\n    {\n        { 1, 1, 1, 1, 1, 1, 1, 1 }, /* OP1_0         */\n        { 1, 1, 1, 1, 1, 1, 1, 1 }, /* OP1_1         */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP2           */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */\n        { 0, 0, 0, 0, 0, 0, 0, 1 }  /* Out           */\n    },\n    {\n        { 0, 1, 0, 0, 0, 1, 0, 0 }, /* OP1_0         */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP1_1         */\n        { 1, 1, 1, 0, 0, 0, 0, 0 }, /* OP2           */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */\n        { 0, 0, 0, 0, 0, 1, 1, 1 }  /* Out           */\n    },\n    {\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP1_0         */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP1_1         */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP2           */\n        { 1, 0, 0, 1, 1, 1, 1, 0 }, /* Last operator */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */\n        { 0, 0, 0, 0, 1, 1, 1, 1 }  /* Out           */\n    },\n    {\n        { 0, 0, 1, 0, 0, 1, 0, 0 }, /* OP1_0         */\n        { 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP1_1         */\n        { 0, 0, 0, 1, 0, 0, 0, 0 }, /* OP2           */\n        { 1, 1, 0, 1, 1, 0, 0, 0 }, /* Last operator */\n        { 0, 0, 1, 0, 0, 0, 0, 0 }, /* Last operator */\n        { 1, 1, 1, 1, 1, 1, 1, 1 }  /* Out           */\n    }\n};\n\nstatic Bit32u chip_type = ym3438_type_discrete;\nstatic Bit32u use_filter = 0;\n\nvoid OPN2_DoIO(ym3438_t *chip)\n{\n    /* Write signal check */\n    chip->write_a_en = (chip->write_a & 0x03) == 0x01;\n    chip->write_d_en = (chip->write_d & 0x03) == 0x01;\n    chip->write_a <<= 1;\n    chip->write_d <<= 1;\n    /* Busy counter */\n    chip->busy = chip->write_busy;\n    chip->write_busy_cnt += chip->write_busy;\n    chip->write_busy = (chip->write_busy && !(chip->write_busy_cnt >> 5)) || chip->write_d_en;\n    chip->write_busy_cnt &= 0x1f;\n}\n\nvoid OPN2_DoRegWrite(ym3438_t *chip)\n{\n    Bit32u i;\n    Bit32u slot = chip->slot % 12;\n    Bit32u address;\n    Bit32u channel = chip->channel;\n    /* Update registers */\n    if (chip->write_fm_data)\n    {\n        /* Slot */\n        if (op_offset[slot] == (chip->address & 0x107))\n        {\n            if (chip->address & 0x08)\n            {\n                /* OP2, OP4 */\n                slot += 12;\n            }\n            address = chip->address & 0xf0;\n            switch (address)\n            {\n            case 0x30: /* DT, MULTI */\n                chip->multi[slot] = chip->data & 0x0f;\n                if (!chip->multi[slot])\n                {\n                    chip->multi[slot] = 1;\n                }\n                else\n                {\n                    chip->multi[slot] <<= 1;\n                }\n                chip->dt[slot] = (chip->data >> 4) & 0x07;\n                break;\n            case 0x40: /* TL */\n                chip->tl[slot] = chip->data & 0x7f;\n                break;\n            case 0x50: /* KS, AR */\n                chip->ar[slot] = chip->data & 0x1f;\n                chip->ks[slot] = (chip->data >> 6) & 0x03;\n                break;\n            case 0x60: /* AM, DR */\n                chip->dr[slot] = chip->data & 0x1f;\n                chip->am[slot] = (chip->data >> 7) & 0x01;\n                break;\n            case 0x70: /* SR */\n                chip->sr[slot] = chip->data & 0x1f;\n                break;\n            case 0x80: /* SL, RR */\n                chip->rr[slot] = chip->data & 0x0f;\n                chip->sl[slot] = (chip->data >> 4) & 0x0f;\n                chip->sl[slot] |= (chip->sl[slot] + 1) & 0x10;\n                break;\n            case 0x90: /* SSG-EG */\n                chip->ssg_eg[slot] = chip->data & 0x0f;\n                break;\n            default:\n                break;\n            }\n        }\n\n        /* Channel */\n        if (ch_offset[channel] == (chip->address & 0x103))\n        {\n            address = chip->address & 0xfc;\n            switch (address)\n            {\n            case 0xa0:\n                chip->fnum[channel] = (chip->data & 0xff) | ((chip->reg_a4 & 0x07) << 8);\n                chip->block[channel] = (chip->reg_a4 >> 3) & 0x07;\n                chip->kcode[channel] = (chip->block[channel] << 2) | fn_note[chip->fnum[channel] >> 7];\n                break;\n            case 0xa4:\n                chip->reg_a4 = chip->data & 0xff;\n                break;\n            case 0xa8:\n                chip->fnum_3ch[channel] = (chip->data & 0xff) | ((chip->reg_ac & 0x07) << 8);\n                chip->block_3ch[channel] = (chip->reg_ac >> 3) & 0x07;\n                chip->kcode_3ch[channel] = (chip->block_3ch[channel] << 2) | fn_note[chip->fnum_3ch[channel] >> 7];\n                break;\n            case 0xac:\n                chip->reg_ac = chip->data & 0xff;\n                break;\n            case 0xb0:\n                chip->connect[channel] = chip->data & 0x07;\n                chip->fb[channel] = (chip->data >> 3) & 0x07;\n                break;\n            case 0xb4:\n                chip->pms[channel] = chip->data & 0x07;\n                chip->ams[channel] = (chip->data >> 4) & 0x03;\n                chip->pan_l[channel] = (chip->data >> 7) & 0x01;\n                chip->pan_r[channel] = (chip->data >> 6) & 0x01;\n                break;\n            default:\n                break;\n            }\n        }\n    }\n\n    if (chip->write_a_en || chip->write_d_en)\n    {\n        /* Data */\n        if (chip->write_a_en)\n        {\n            chip->write_fm_data = 0;\n        }\n\n        if (chip->write_fm_address && chip->write_d_en)\n        {\n            chip->write_fm_data = 1;\n        }\n\n        /* Address */\n        if (chip->write_a_en)\n        {\n            if ((chip->write_data & 0xf0) != 0x00)\n            {\n                /* FM Write */\n                chip->address = chip->write_data;\n                chip->write_fm_address = 1;\n            }\n            else\n            {\n                /* SSG write */\n                chip->write_fm_address = 0;\n            }\n        }\n\n        /* FM Mode */\n        /* Data */\n        if (chip->write_d_en && (chip->write_data & 0x100) == 0)\n        {\n            switch (chip->address)\n            {\n            case 0x21: /* LSI test 1 */\n                for (i = 0; i < 8; i++)\n                {\n                    chip->mode_test_21[i] = (chip->write_data >> i) & 0x01;\n                }\n                break;\n            case 0x22: /* LFO control */\n                if ((chip->write_data >> 3) & 0x01)\n                {\n                    chip->lfo_en = 0x7f;\n                }\n                else\n                {\n                    chip->lfo_en = 0;\n                }\n                chip->lfo_freq = chip->write_data & 0x07;\n                break;\n            case 0x24: /* Timer A */\n                chip->timer_a_reg &= 0x03;\n                chip->timer_a_reg |= (chip->write_data & 0xff) << 2;\n                break;\n            case 0x25:\n                chip->timer_a_reg &= 0x3fc;\n                chip->timer_a_reg |= chip->write_data & 0x03;\n                break;\n            case 0x26: /* Timer B */\n                chip->timer_b_reg = chip->write_data & 0xff;\n                break;\n            case 0x27: /* CSM, Timer control */\n                chip->mode_ch3 = (chip->write_data & 0xc0) >> 6;\n                chip->mode_csm = chip->mode_ch3 == 2;\n                chip->timer_a_load = chip->write_data & 0x01;\n                chip->timer_a_enable = (chip->write_data >> 2) & 0x01;\n                chip->timer_a_reset = (chip->write_data >> 4) & 0x01;\n                chip->timer_b_load = (chip->write_data >> 1) & 0x01;\n                chip->timer_b_enable = (chip->write_data >> 3) & 0x01;\n                chip->timer_b_reset = (chip->write_data >> 5) & 0x01;\n                break;\n            case 0x28: /* Key on/off */\n                for (i = 0; i < 4; i++)\n                {\n                    chip->mode_kon_operator[i] = (chip->write_data >> (4 + i)) & 0x01;\n                }\n                if ((chip->write_data & 0x03) == 0x03)\n                {\n                    /* Invalid address */\n                    chip->mode_kon_channel = 0xff;\n                }\n                else\n                {\n                    chip->mode_kon_channel = (chip->write_data & 0x03) + ((chip->write_data >> 2) & 1) * 3;\n                }\n                break;\n            case 0x2a: /* DAC data */\n                chip->dacdata &= 0x01;\n                chip->dacdata |= (chip->write_data ^ 0x80) << 1;\n                break;\n            case 0x2b: /* DAC enable */\n                chip->dacen = chip->write_data >> 7;\n                break;\n            case 0x2c: /* LSI test 2 */\n                for (i = 0; i < 8; i++)\n                {\n                    chip->mode_test_2c[i] = (chip->write_data >> i) & 0x01;\n                }\n                chip->dacdata &= 0x1fe;\n                chip->dacdata |= chip->mode_test_2c[3];\n                chip->eg_custom_timer = !chip->mode_test_2c[7] && chip->mode_test_2c[6];\n                break;\n            default:\n                break;\n            }\n        }\n\n        /* Address */\n        if (chip->write_a_en)\n        {\n            chip->write_fm_mode_a = chip->write_data & 0xff;\n        }\n    }\n\n    if (chip->write_fm_data)\n    {\n        chip->data = chip->write_data & 0xff;\n    }\n}\n\nvoid OPN2_PhaseCalcIncrement(ym3438_t *chip)\n{\n    Bit32u fnum = chip->pg_fnum;\n    Bit32u fnum_h = fnum >> 4;\n    Bit32u fm;\n    Bit32u basefreq;\n    Bit8u lfo = chip->lfo_pm;\n    Bit8u lfo_l = lfo & 0x0f;\n    Bit8u pms = chip->pms[chip->channel];\n    Bit8u dt = chip->dt[chip->slot];\n    Bit8u dt_l = dt & 0x03;\n    Bit8u detune = 0;\n    Bit8u block, note;\n    Bit8u sum, sum_h, sum_l;\n    Bit8u kcode = chip->pg_kcode;\n\n    fnum <<= 1;\n    /* Apply LFO */\n    if (lfo_l & 0x08)\n    {\n        lfo_l ^= 0x0f;\n    }\n    fm = (fnum_h >> pg_lfo_sh1[pms][lfo_l]) + (fnum_h >> pg_lfo_sh2[pms][lfo_l]);\n    if (pms > 5)\n    {\n        fm <<= pms - 5;\n    }\n    fm >>= 2;\n    if (lfo & 0x10)\n    {\n        fnum -= fm;\n    }\n    else\n    {\n        fnum += fm;\n    }\n    fnum &= 0xfff;\n\n    basefreq = (fnum << chip->pg_block) >> 2;\n\n    /* Apply detune */\n    if (dt_l)\n    {\n        if (kcode > 0x1c)\n        {\n            kcode = 0x1c;\n        }\n        block = kcode >> 2;\n        note = kcode & 0x03;\n        sum = block + 9 + ((dt_l == 3) | (dt_l & 0x02));\n        sum_h = sum >> 1;\n        sum_l = sum & 0x01;\n        detune = pg_detune[(sum_l << 2) | note] >> (9 - sum_h);\n    }\n    if (dt & 0x04)\n    {\n        basefreq -= detune;\n    }\n    else\n    {\n        basefreq += detune;\n    }\n    basefreq &= 0x1ffff;\n    chip->pg_inc[chip->slot] = (basefreq * chip->multi[chip->slot]) >> 1;\n    chip->pg_inc[chip->slot] &= 0xfffff;\n}\n\nvoid OPN2_PhaseGenerate(ym3438_t *chip)\n{\n    Bit32u slot;\n    /* Mask increment */\n    slot = (chip->slot + 20) % 24;\n    if (chip->pg_reset[slot])\n    {\n        chip->pg_inc[slot] = 0;\n    }\n    /* Phase step */\n    slot = (chip->slot + 19) % 24;\n    chip->pg_phase[slot] += chip->pg_inc[slot];\n    chip->pg_phase[slot] &= 0xfffff;\n    if (chip->pg_reset[slot] || chip->mode_test_21[3])\n    {\n        chip->pg_phase[slot] = 0;\n    }\n}\n\nvoid OPN2_EnvelopeSSGEG(ym3438_t *chip)\n{\n    Bit32u slot = chip->slot;\n    Bit8u direction = 0;\n    chip->eg_ssg_pgrst_latch[slot] = 0;\n    chip->eg_ssg_repeat_latch[slot] = 0;\n    chip->eg_ssg_hold_up_latch[slot] = 0;\n    chip->eg_ssg_inv[slot] = 0;\n    if (chip->ssg_eg[slot] & 0x08)\n    {\n        direction = chip->eg_ssg_dir[slot];\n        if (chip->eg_level[slot] & 0x200)\n        {\n            /* Reset */\n            if ((chip->ssg_eg[slot] & 0x03) == 0x00)\n            {\n                chip->eg_ssg_pgrst_latch[slot] = 1;\n            }\n            /* Repeat */\n            if ((chip->ssg_eg[slot] & 0x01) == 0x00)\n            {\n                chip->eg_ssg_repeat_latch[slot] = 1;\n            }\n            /* Inverse */\n            if ((chip->ssg_eg[slot] & 0x03) == 0x02)\n            {\n                direction ^= 1;\n            }\n            if ((chip->ssg_eg[slot] & 0x03) == 0x03)\n            {\n                direction = 1;\n            }\n        }\n        /* Hold up */\n        if (chip->eg_kon_latch[slot]\n         && ((chip->ssg_eg[slot] & 0x07) == 0x05 || (chip->ssg_eg[slot] & 0x07) == 0x03))\n        {\n            chip->eg_ssg_hold_up_latch[slot] = 1;\n        }\n        direction &= chip->eg_kon[slot];\n        chip->eg_ssg_inv[slot] = (chip->eg_ssg_dir[slot] ^ ((chip->ssg_eg[slot] >> 2) & 0x01))\n                               & chip->eg_kon[slot];\n    }\n    chip->eg_ssg_dir[slot] = direction;\n    chip->eg_ssg_enable[slot] = (chip->ssg_eg[slot] >> 3) & 0x01;\n}\n\nvoid OPN2_EnvelopeADSR(ym3438_t *chip)\n{\n    Bit32u slot = (chip->slot + 22) % 24;\n\n    Bit8u nkon = chip->eg_kon_latch[slot];\n    Bit8u okon = chip->eg_kon[slot];\n    Bit8u kon_event;\n    Bit8u koff_event;\n    Bit8u eg_off;\n    Bit16s level;\n    Bit16s nextlevel = 0;\n    Bit16s ssg_level;\n    Bit8u nextstate = chip->eg_state[slot];\n    Bit16s inc = 0;\n    chip->eg_read[0] = chip->eg_read_inc;\n    chip->eg_read_inc = chip->eg_inc > 0;\n\n    /* Reset phase generator */\n    chip->pg_reset[slot] = (nkon && !okon) || chip->eg_ssg_pgrst_latch[slot];\n\n    /* KeyOn/Off */\n    kon_event = (nkon && !okon) || (okon && chip->eg_ssg_repeat_latch[slot]);\n    koff_event = okon && !nkon;\n\n    ssg_level = level = (Bit16s)chip->eg_level[slot];\n\n    if (chip->eg_ssg_inv[slot])\n    {\n        /* Inverse */\n        ssg_level = 512 - level;\n        ssg_level &= 0x3ff;\n    }\n    if (koff_event)\n    {\n        level = ssg_level;\n    }\n    if (chip->eg_ssg_enable[slot])\n    {\n        eg_off = level >> 9;\n    }\n    else\n    {\n        eg_off = (level & 0x3f0) == 0x3f0;\n    }\n    nextlevel = level;\n    if (kon_event)\n    {\n        nextstate = eg_num_attack;\n        /* Instant attack */\n        if (chip->eg_ratemax)\n        {\n            nextlevel = 0;\n        }\n        else if (chip->eg_state[slot] == eg_num_attack && level != 0 && chip->eg_inc && nkon)\n        {\n            inc = (~level << chip->eg_inc) >> 5;\n        }\n    }\n    else\n    {\n        switch (chip->eg_state[slot])\n        {\n        case eg_num_attack:\n            if (level == 0)\n            {\n                nextstate = eg_num_decay;\n            }\n            else if(chip->eg_inc && !chip->eg_ratemax && nkon)\n            {\n                inc = (~level << chip->eg_inc) >> 5;\n            }\n            break;\n        case eg_num_decay:\n            if ((level >> 5) == chip->eg_sl[1])\n            {\n                nextstate = eg_num_sustain;\n            }\n            else if (!eg_off && chip->eg_inc)\n            {\n                inc = 1 << (chip->eg_inc - 1);\n                if (chip->eg_ssg_enable[slot])\n                {\n                    inc <<= 2;\n                }\n            }\n            break;\n        case eg_num_sustain:\n        case eg_num_release:\n            if (!eg_off && chip->eg_inc)\n            {\n                inc = 1 << (chip->eg_inc - 1);\n                if (chip->eg_ssg_enable[slot])\n                {\n                    inc <<= 2;\n                }\n            }\n            break;\n        default:\n            break;\n        }\n        if (!nkon)\n        {\n            nextstate = eg_num_release;\n        }\n    }\n    if (chip->eg_kon_csm[slot])\n    {\n        nextlevel |= chip->eg_tl[1] << 3;\n    }\n\n    /* Envelope off */\n    if (!kon_event && !chip->eg_ssg_hold_up_latch[slot] && chip->eg_state[slot] != eg_num_attack && eg_off)\n    {\n        nextstate = eg_num_release;\n        nextlevel = 0x3ff;\n    }\n\n    nextlevel += inc;\n\n    chip->eg_kon[slot] = chip->eg_kon_latch[slot];\n    chip->eg_level[slot] = (Bit16u)nextlevel & 0x3ff;\n    chip->eg_state[slot] = nextstate;\n}\n\nvoid OPN2_EnvelopePrepare(ym3438_t *chip)\n{\n    Bit8u rate;\n    Bit8u sum;\n    Bit8u inc = 0;\n    Bit32u slot = chip->slot;\n    Bit8u rate_sel;\n\n    /* Prepare increment */\n    rate = (chip->eg_rate << 1) + chip->eg_ksv;\n\n    if (rate > 0x3f)\n    {\n        rate = 0x3f;\n    }\n\n    sum = ((rate >> 2) + chip->eg_shift_lock) & 0x0f;\n    if (chip->eg_rate != 0 && chip->eg_quotient == 2)\n    {\n        if (rate < 48)\n        {\n            switch (sum)\n            {\n            case 12:\n                inc = 1;\n                break;\n            case 13:\n                inc = (rate >> 1) & 0x01;\n                break;\n            case 14:\n                inc = rate & 0x01;\n                break;\n            default:\n                break;\n            }\n        }\n        else\n        {\n            inc = eg_stephi[rate & 0x03][chip->eg_timer_low_lock] + (rate >> 2) - 11;\n            if (inc > 4)\n            {\n                inc = 4;\n            }\n        }\n    }\n    chip->eg_inc = inc;\n    chip->eg_ratemax = (rate >> 1) == 0x1f;\n\n    /* Prepare rate & ksv */\n    rate_sel = chip->eg_state[slot];\n    if ((chip->eg_kon[slot] && chip->eg_ssg_repeat_latch[slot])\n     || (!chip->eg_kon[slot] && chip->eg_kon_latch[slot]))\n    {\n        rate_sel = eg_num_attack;\n    }\n    switch (rate_sel)\n    {\n    case eg_num_attack:\n        chip->eg_rate = chip->ar[slot];\n        break;\n    case eg_num_decay:\n        chip->eg_rate = chip->dr[slot];\n        break;\n    case eg_num_sustain:\n        chip->eg_rate = chip->sr[slot];\n        break;\n    case eg_num_release:\n        chip->eg_rate = (chip->rr[slot] << 1) | 0x01;\n        break;\n    default:\n        break;\n    }\n    chip->eg_ksv = chip->pg_kcode >> (chip->ks[slot] ^ 0x03);\n    if (chip->am[slot])\n    {\n        chip->eg_lfo_am = chip->lfo_am >> eg_am_shift[chip->ams[chip->channel]];\n    }\n    else\n    {\n        chip->eg_lfo_am = 0;\n    }\n    /* Delay TL & SL value */\n    chip->eg_tl[1] = chip->eg_tl[0];\n    chip->eg_tl[0] = chip->tl[slot];\n    chip->eg_sl[1] = chip->eg_sl[0];\n    chip->eg_sl[0] = chip->sl[slot];\n}\n\nvoid OPN2_EnvelopeGenerate(ym3438_t *chip)\n{\n    Bit32u slot = (chip->slot + 23) % 24;\n    Bit16u level;\n\n    level = chip->eg_level[slot];\n\n    if (chip->eg_ssg_inv[slot])\n    {\n        /* Inverse */\n        level = 512 - level;\n    }\n    if (chip->mode_test_21[5])\n    {\n        level = 0;\n    }\n    level &= 0x3ff;\n\n    /* Apply AM LFO */\n    level += chip->eg_lfo_am;\n\n    /* Apply TL */\n    if (!(chip->mode_csm && chip->channel == 2 + 1))\n    {\n        level += chip->eg_tl[0] << 3;\n    }\n    if (level > 0x3ff)\n    {\n        level = 0x3ff;\n    }\n    chip->eg_out[slot] = level;\n}\n\nvoid OPN2_UpdateLFO(ym3438_t *chip)\n{\n    if ((chip->lfo_quotient & lfo_cycles[chip->lfo_freq]) == lfo_cycles[chip->lfo_freq])\n    {\n        chip->lfo_quotient = 0;\n        chip->lfo_cnt++;\n    }\n    else\n    {\n        chip->lfo_quotient += chip->lfo_inc;\n    }\n    chip->lfo_cnt &= chip->lfo_en;\n}\n\nvoid OPN2_FMPrepare(ym3438_t *chip)\n{\n    Bit32u slot = (chip->slot + 6) % 24;\n    Bit32u channel = chip->channel;\n    Bit16s mod, mod1, mod2;\n    Bit32u op = slot / 6;\n    Bit8u connect = chip->connect[channel];\n    Bit32u prevslot = (chip->slot + 18) % 24;\n\n    /* Calculate modulation */\n    mod1 = mod2 = 0;\n\n    if (fm_algorithm[op][0][connect])\n    {\n        mod2 |= chip->fm_op1[channel][0];\n    }\n    if (fm_algorithm[op][1][connect])\n    {\n        mod1 |= chip->fm_op1[channel][1];\n    }\n    if (fm_algorithm[op][2][connect])\n    {\n        mod1 |= chip->fm_op2[channel];\n    }\n    if (fm_algorithm[op][3][connect])\n    {\n        mod2 |= chip->fm_out[prevslot];\n    }\n    if (fm_algorithm[op][4][connect])\n    {\n        mod1 |= chip->fm_out[prevslot];\n    }\n    mod = mod1 + mod2;\n    if (op == 0)\n    {\n        /* Feedback */\n        mod = mod >> (10 - chip->fb[channel]);\n        if (!chip->fb[channel])\n        {\n            mod = 0;\n        }\n    }\n    else\n    {\n        mod >>= 1;\n    }\n    chip->fm_mod[slot] = mod;\n\n    slot = (chip->slot + 18) % 24;\n    /* OP1 */\n    if (slot / 6 == 0)\n    {\n        chip->fm_op1[channel][1] = chip->fm_op1[channel][0];\n        chip->fm_op1[channel][0] = chip->fm_out[slot];\n    }\n    /* OP2 */\n    if (slot / 6 == 2)\n    {\n        chip->fm_op2[channel] = chip->fm_out[slot];\n    }\n}\n\nvoid OPN2_ChGenerate(ym3438_t *chip)\n{\n    Bit32u slot = (chip->slot + 18) % 24;\n    Bit32u channel = chip->channel;\n    Bit32u op = slot / 6;\n    Bit32u test_dac = chip->mode_test_2c[5];\n    Bit16s acc = chip->ch_acc[channel];\n    Bit16s add = test_dac;\n    Bit16s sum = 0;\n    if (op == 0 && !test_dac)\n    {\n        acc = 0;\n    }\n    if (fm_algorithm[op][5][chip->connect[channel]] && !test_dac)\n    {\n        add += chip->fm_out[slot] >> 5;\n    }\n    sum = acc + add;\n    /* Clamp */\n    if (sum > 255)\n    {\n        sum = 255;\n    }\n    else if(sum < -256)\n    {\n        sum = -256;\n    }\n\n    if (op == 0 || test_dac)\n    {\n        chip->ch_out[channel] = chip->ch_acc[channel];\n    }\n    chip->ch_acc[channel] = sum;\n}\n\nvoid OPN2_ChOutput(ym3438_t *chip)\n{\n    Bit32u cycles = chip->cycles;\n    Bit32u channel = chip->channel;\n    Bit32u test_dac = chip->mode_test_2c[5];\n    Bit16s out;\n    Bit16s sign;\n    Bit32u out_en;\n    chip->ch_read = chip->ch_lock;\n    if (chip->slot < 12)\n    {\n        /* Ch 4,5,6 */\n        channel++;\n    }\n    if ((cycles & 3) == 0)\n    {\n        if (!test_dac)\n        {\n            /* Lock value */\n            chip->ch_lock = chip->ch_out[channel];\n        }\n        chip->ch_lock_l = chip->pan_l[channel];\n        chip->ch_lock_r = chip->pan_r[channel];\n    }\n    /* Ch 6 */\n    if (((cycles >> 2) == 1 && chip->dacen) || test_dac)\n    {\n        out = (Bit16s)chip->dacdata;\n        out <<= 7;\n        out >>= 7;\n    }\n    else\n    {\n        out = chip->ch_lock;\n    }\n    chip->mol = 0;\n    chip->mor = 0;\n\n    if (chip_type == ym3438_type_ym2612)\n    {\n        out_en = ((cycles & 3) == 3) || test_dac;\n        /* YM2612 DAC emulation(not verified) */\n        sign = out >> 8;\n        if (out >= 0)\n        {\n            out++;\n            sign++;\n        }\n        if (chip->ch_lock_l && out_en)\n        {\n            chip->mol = out;\n        }\n        else\n        {\n            chip->mol = sign;\n        }\n        if (chip->ch_lock_r && out_en)\n        {\n            chip->mor = out;\n        }\n        else\n        {\n            chip->mor = sign;\n        }\n        /* Amplify signal */\n        chip->mol *= 3;\n        chip->mor *= 3;\n    }\n    else\n    {\n        out_en = ((cycles & 3) != 0) || test_dac;\n        /* Discrete YM3438 seems has the ladder effect too */\n        if (out >= 0 && chip_type == ym3438_type_discrete)\n        {\n            out++;\n        }\n        if (chip->ch_lock_l && out_en)\n        {\n            chip->mol = out;\n        }\n        if (chip->ch_lock_r && out_en)\n        {\n            chip->mor = out;\n        }\n    }\n}\n\nvoid OPN2_FMGenerate(ym3438_t *chip)\n{\n    Bit32u slot = (chip->slot + 19) % 24;\n    /* Calculate phase */\n    Bit16u phase = (chip->fm_mod[slot] + (chip->pg_phase[slot] >> 10)) & 0x3ff;\n    Bit16u quarter;\n    Bit16u level;\n    Bit16s output;\n    if (phase & 0x100)\n    {\n        quarter = (phase ^ 0xff) & 0xff;\n    }\n    else\n    {\n        quarter = phase & 0xff;\n    }\n    level = logsinrom[quarter];\n    /* Apply envelope */\n    level += chip->eg_out[slot] << 2;\n    /* Transform */\n    if (level > 0x1fff)\n    {\n        level = 0x1fff;\n    }\n    output = ((exprom[(level & 0xff) ^ 0xff] | 0x400) << 2) >> (level >> 8);\n    if (phase & 0x200)\n    {\n        output = ((~output) ^ (chip->mode_test_21[4] << 13)) + 1;\n    }\n    else\n    {\n        output = output ^ (chip->mode_test_21[4] << 13);\n    }\n    output <<= 2;\n    output >>= 2;\n    chip->fm_out[slot] = output;\n}\n\nvoid OPN2_DoTimerA(ym3438_t *chip)\n{\n    Bit16u time;\n    Bit8u load;\n    load = chip->timer_a_overflow;\n    if (chip->cycles == 2)\n    {\n        /* Lock load value */\n        load |= (!chip->timer_a_load_lock && chip->timer_a_load);\n        chip->timer_a_load_lock = chip->timer_a_load;\n        if (chip->mode_csm)\n        {\n            /* CSM KeyOn */\n            chip->mode_kon_csm = load;\n        }\n        else\n        {\n            chip->mode_kon_csm = 0;\n        }\n    }\n    /* Load counter */\n    if (chip->timer_a_load_latch)\n    {\n        time = chip->timer_a_reg;\n    }\n    else\n    {\n        time = chip->timer_a_cnt;\n    }\n    chip->timer_a_load_latch = load;\n    /* Increase counter */\n    if ((chip->cycles == 1 && chip->timer_a_load_lock) || chip->mode_test_21[2])\n    {\n        time++;\n    }\n    /* Set overflow flag */\n    if (chip->timer_a_reset)\n    {\n        chip->timer_a_reset = 0;\n        chip->timer_a_overflow_flag = 0;\n    }\n    else\n    {\n        chip->timer_a_overflow_flag |= chip->timer_a_overflow & chip->timer_a_enable;\n    }\n    chip->timer_a_overflow = (time >> 10);\n    chip->timer_a_cnt = time & 0x3ff;\n}\n\nvoid OPN2_DoTimerB(ym3438_t *chip)\n{\n    Bit16u time;\n    Bit8u load;\n    load = chip->timer_b_overflow;\n    if (chip->cycles == 2)\n    {\n        /* Lock load value */\n        load |= (!chip->timer_b_load_lock && chip->timer_b_load);\n        chip->timer_b_load_lock = chip->timer_b_load;\n    }\n    /* Load counter */\n    if (chip->timer_b_load_latch)\n    {\n        time = chip->timer_b_reg;\n    }\n    else\n    {\n        time = chip->timer_b_cnt;\n    }\n    chip->timer_b_load_latch = load;\n    /* Increase counter */\n    if (chip->cycles == 1)\n    {\n        chip->timer_b_subcnt++;\n    }\n    if ((chip->timer_b_subcnt == 0x10 && chip->timer_b_load_lock) || chip->mode_test_21[2])\n    {\n        time++;\n    }\n    chip->timer_b_subcnt &= 0x0f;\n    /* Set overflow flag */\n    if (chip->timer_b_reset)\n    {\n        chip->timer_b_reset = 0;\n        chip->timer_b_overflow_flag = 0;\n    }\n    else\n    {\n        chip->timer_b_overflow_flag |= chip->timer_b_overflow & chip->timer_b_enable;\n    }\n    chip->timer_b_overflow = (time >> 8);\n    chip->timer_b_cnt = time & 0xff;\n}\n\nvoid OPN2_KeyOn(ym3438_t*chip)\n{\n    /* Key On */\n    chip->eg_kon_latch[chip->slot] = chip->mode_kon[chip->slot];\n    chip->eg_kon_csm[chip->slot] = 0;\n    if (chip->channel == 2 && chip->mode_kon_csm)\n    {\n        /* CSM Key On */\n        chip->eg_kon_latch[chip->slot] = 1;\n        chip->eg_kon_csm[chip->slot] = 1;\n    }\n    if (chip->cycles == chip->mode_kon_channel)\n    {\n        /* OP1 */\n        chip->mode_kon[chip->channel] = chip->mode_kon_operator[0];\n        /* OP2 */\n        chip->mode_kon[chip->channel + 12] = chip->mode_kon_operator[1];\n        /* OP3 */\n        chip->mode_kon[chip->channel + 6] = chip->mode_kon_operator[2];\n        /* OP4 */\n        chip->mode_kon[chip->channel + 18] = chip->mode_kon_operator[3];\n    }\n}\n\nvoid OPN2_Reset(ym3438_t *chip, Bit32u rate, Bit32u clock)\n{\n    Bit32u i, rateratio;\n    rateratio = chip->rateratio;\n    memset(chip, 0, sizeof(ym3438_t));\n    for (i = 0; i < 24; i++)\n    {\n        chip->eg_out[i] = 0x3ff;\n        chip->eg_level[i] = 0x3ff;\n        chip->eg_state[i] = eg_num_release;\n        chip->multi[i] = 1;\n    }\n    for (i = 0; i < 6; i++)\n    {\n        chip->pan_l[i] = 1;\n        chip->pan_r[i] = 1;\n    }\n    if (rate != 0)\n    {\n        chip->rateratio = (Bit32u)((((Bit64u)144 * rate) << RSM_FRAC) / clock);\n    }\n    else\n    {\n        chip->rateratio = rateratio;\n    }\n}\n\nvoid OPN2_SetChipType(Bit32u type)\n{\n    use_filter = 0;\n    if(type == ym3438_type_ym2612)\n        use_filter = 1;\n    if(type == ym3438_type_ym2612_u)\n        type = ym3438_type_ym2612;\n    chip_type = type;\n}\n\nvoid OPN2_Clock(ym3438_t *chip, Bit32s *buffer)\n{\n    chip->lfo_inc = chip->mode_test_21[1];\n    chip->pg_read >>= 1;\n    chip->eg_read[1] >>= 1;\n    chip->eg_cycle++;\n    /* Lock envelope generator timer value */\n    if (chip->cycles == 1 && chip->eg_quotient == 2)\n    {\n        if (chip->eg_cycle_stop)\n        {\n            chip->eg_shift_lock = 0;\n        }\n        else\n        {\n            chip->eg_shift_lock = chip->eg_shift + 1;\n        }\n        chip->eg_timer_low_lock = chip->eg_timer & 0x03;\n    }\n    /* Cycle specific functions */\n    switch (chip->cycles)\n    {\n    case 0:\n        chip->lfo_pm = chip->lfo_cnt >> 2;\n        if (chip->lfo_cnt & 0x40)\n        {\n            chip->lfo_am = chip->lfo_cnt & 0x3f;\n        }\n        else\n        {\n            chip->lfo_am = chip->lfo_cnt ^ 0x3f;\n        }\n        chip->lfo_am <<= 1;\n        break;\n    case 1:\n        chip->eg_quotient++;\n        chip->eg_quotient %= 3;\n        chip->eg_cycle = 0;\n        chip->eg_cycle_stop = 1;\n        chip->eg_shift = 0;\n        chip->eg_timer_inc |= chip->eg_quotient >> 1;\n        chip->eg_timer = chip->eg_timer + chip->eg_timer_inc;\n        chip->eg_timer_inc = chip->eg_timer >> 12;\n        chip->eg_timer &= 0xfff;\n        break;\n    case 2:\n        chip->pg_read = chip->pg_phase[21] & 0x3ff;\n        chip->eg_read[1] = chip->eg_out[0];\n        break;\n    case 13:\n        chip->eg_cycle = 0;\n        chip->eg_cycle_stop = 1;\n        chip->eg_shift = 0;\n        chip->eg_timer = chip->eg_timer + chip->eg_timer_inc;\n        chip->eg_timer_inc = chip->eg_timer >> 12;\n        chip->eg_timer &= 0xfff;\n        break;\n    case 23:\n        chip->lfo_inc |= 1;\n        break;\n    }\n    chip->eg_timer &= ~(chip->mode_test_21[5] << chip->eg_cycle);\n    if (((chip->eg_timer >> chip->eg_cycle) | (chip->pin_test_in & chip->eg_custom_timer)) & chip->eg_cycle_stop)\n    {\n        chip->eg_shift = chip->eg_cycle;\n        chip->eg_cycle_stop = 0;\n    }\n\n    OPN2_DoIO(chip);\n\n    OPN2_DoTimerA(chip);\n    OPN2_DoTimerB(chip);\n    OPN2_KeyOn(chip);\n\n    OPN2_ChOutput(chip);\n    OPN2_ChGenerate(chip);\n\n    OPN2_FMPrepare(chip);\n    OPN2_FMGenerate(chip);\n\n    OPN2_PhaseGenerate(chip);\n    OPN2_PhaseCalcIncrement(chip);\n\n    OPN2_EnvelopeADSR(chip);\n    OPN2_EnvelopeGenerate(chip);\n    OPN2_EnvelopeSSGEG(chip);\n    OPN2_EnvelopePrepare(chip);\n\n    /* Prepare fnum & block */\n    if (chip->mode_ch3)\n    {\n        /* Channel 3 special mode */\n        switch (chip->slot)\n        {\n        case 1: /* OP1 */\n            chip->pg_fnum = chip->fnum_3ch[1];\n            chip->pg_block = chip->block_3ch[1];\n            chip->pg_kcode = chip->kcode_3ch[1];\n            break;\n        case 7: /* OP3 */\n            chip->pg_fnum = chip->fnum_3ch[0];\n            chip->pg_block = chip->block_3ch[0];\n            chip->pg_kcode = chip->kcode_3ch[0];\n            break;\n        case 13: /* OP2 */\n            chip->pg_fnum = chip->fnum_3ch[2];\n            chip->pg_block = chip->block_3ch[2];\n            chip->pg_kcode = chip->kcode_3ch[2];\n            break;\n        case 19: /* OP4 */\n        default:\n            chip->pg_fnum = chip->fnum[(chip->channel + 1) % 6];\n            chip->pg_block = chip->block[(chip->channel + 1) % 6];\n            chip->pg_kcode = chip->kcode[(chip->channel + 1) % 6];\n            break;\n        }\n    }\n    else\n    {\n        chip->pg_fnum = chip->fnum[(chip->channel + 1) % 6];\n        chip->pg_block = chip->block[(chip->channel + 1) % 6];\n        chip->pg_kcode = chip->kcode[(chip->channel + 1) % 6];\n    }\n\n    OPN2_UpdateLFO(chip);\n    OPN2_DoRegWrite(chip);\n    chip->cycles = (chip->cycles + 1) % 24;\n    chip->slot = chip->cycles;\n    chip->channel = chip->cycles % 6;\n\n    buffer[0] = chip->mol;\n    buffer[1] = chip->mor;\n}\n\nvoid OPN2_Write(ym3438_t *chip, Bit32u port, Bit8u data)\n{\n    port &= 3;\n    chip->write_data = ((port << 7) & 0x100) | data;\n    if (port & 1)\n    {\n        /* Data */\n        chip->write_d |= 1;\n    }\n    else\n    {\n        /* Address */\n        chip->write_a |= 1;\n    }\n}\n\nvoid OPN2_SetTestPin(ym3438_t *chip, Bit32u value)\n{\n    chip->pin_test_in = value & 1;\n}\n\nBit32u OPN2_ReadTestPin(ym3438_t *chip)\n{\n    if (!chip->mode_test_2c[7])\n    {\n        return 0;\n    }\n    return chip->cycles == 23;\n}\n\nBit32u OPN2_ReadIRQPin(ym3438_t *chip)\n{\n    return chip->timer_a_overflow_flag | chip->timer_b_overflow_flag;\n}\n\nBit8u OPN2_Read(ym3438_t *chip, Bit32u port)\n{\n    if ((port & 3) == 0 || chip_type == ym3438_type_asic)\n    {\n        if (chip->mode_test_21[6])\n        {\n            /* Read test data */\n            Bit16u testdata = ((chip->pg_read & 0x01) << 15)\n                            | ((chip->eg_read[chip->mode_test_21[0]] & 0x01) << 14);\n            if (chip->mode_test_2c[4])\n            {\n                testdata |= chip->ch_read & 0x1ff;\n            }\n            else\n            {\n                testdata |= chip->fm_out[(chip->slot + 18) % 24] & 0x3fff;\n            }\n            if (chip->mode_test_21[7])\n            {\n                return testdata & 0xff;\n            }\n            else\n            {\n                return testdata >> 8;\n            }\n        }\n        else\n        {\n            return (chip->busy << 7) | (chip->timer_b_overflow_flag << 1)\n                 | chip->timer_a_overflow_flag;\n        }\n    }\n    return 0;\n}\n\nvoid OPN2_WriteBuffered(ym3438_t *chip, Bit32u port, Bit8u data)\n{\n    Bit64u time1, time2;\n    Bit32s buffer[2];\n    Bit64u skip;\n\n    if (chip->writebuf[chip->writebuf_last].port & 0x04)\n    {\n        OPN2_Write(chip, chip->writebuf[chip->writebuf_last].port & 0X03,\n                   chip->writebuf[chip->writebuf_last].data);\n\n        chip->writebuf_cur = (chip->writebuf_last + 1) % OPN_WRITEBUF_SIZE;\n        skip = chip->writebuf[chip->writebuf_last].time - chip->writebuf_samplecnt;\n        chip->writebuf_samplecnt = chip->writebuf[chip->writebuf_last].time;\n        while (skip--)\n        {\n            OPN2_Clock(chip, buffer);\n        }\n    }\n\n    chip->writebuf[chip->writebuf_last].port = (port & 0x03) | 0x04;\n    chip->writebuf[chip->writebuf_last].data = data;\n    time1 = chip->writebuf_lasttime + OPN_WRITEBUF_DELAY;\n    time2 = chip->writebuf_samplecnt;\n\n    if (time1 < time2)\n    {\n        time1 = time2;\n    }\n\n    chip->writebuf[chip->writebuf_last].time = time1;\n    chip->writebuf_lasttime = time1;\n    chip->writebuf_last = (chip->writebuf_last + 1) % OPN_WRITEBUF_SIZE;\n}\n\nvoid OPN2_GenerateResampled(ym3438_t *chip, Bit32s *buf)\n{\n    Bit32u i;\n    Bit32s buffer[2];\n    Bit32u mute;\n    \n    while (chip->samplecnt >= chip->rateratio)\n    {\n        chip->oldsamples[0] = chip->samples[0];\n        chip->oldsamples[1] = chip->samples[1];\n        chip->samples[0] = chip->samples[1] = 0;\n        for (i = 0; i < 24; i++)\n        {\n            switch (chip->cycles >> 2)\n            {\n            case 0: // Ch 2\n                mute = chip->mute[1];\n                break;\n            case 1: // Ch 6, DAC\n                mute = chip->mute[5 + chip->dacen];\n                break;\n            case 2: // Ch 4\n                mute = chip->mute[3];\n                break;\n            case 3: // Ch 1\n                mute = chip->mute[0];\n                break;\n            case 4: // Ch 5\n                mute = chip->mute[4];\n                break;\n            case 5: // Ch 3\n                mute = chip->mute[2];\n                break;\n            default:\n                mute = 0;\n                break;\n            }\n            OPN2_Clock(chip, buffer);\n            if (!mute)\n            {\n                chip->samples[0] += buffer[0];\n                chip->samples[1] += buffer[1];\n            }\n\n            while (chip->writebuf[chip->writebuf_cur].time <= chip->writebuf_samplecnt)\n            {\n                if (!(chip->writebuf[chip->writebuf_cur].port & 0x04))\n                {\n                    break;\n                }\n                chip->writebuf[chip->writebuf_cur].port &= 0x03;\n                OPN2_Write(chip, chip->writebuf[chip->writebuf_cur].port,\n                              chip->writebuf[chip->writebuf_cur].data);\n                chip->writebuf_cur = (chip->writebuf_cur + 1) % OPN_WRITEBUF_SIZE;\n            }\n            chip->writebuf_samplecnt++;\n        }\n        if(!use_filter)\n        {\n            chip->samples[0] *= OUTPUT_FACTOR;\n            chip->samples[1] *= OUTPUT_FACTOR;\n        }\n        else\n        {\n            chip->samples[0] = chip->oldsamples[0] + FILTER_CUTOFF_I * (chip->samples[0]*OUTPUT_FACTOR_F - chip->oldsamples[0]);\n            chip->samples[1] = chip->oldsamples[1] + FILTER_CUTOFF_I * (chip->samples[1]*OUTPUT_FACTOR_F - chip->oldsamples[1]);\n        }\n        chip->samplecnt -= chip->rateratio;\n    }\n    buf[0] = (Bit32s)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt)\n                     + chip->samples[0] * chip->samplecnt) / chip->rateratio);\n    buf[1] = (Bit32s)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt)\n                     + chip->samples[1] * chip->samplecnt) / chip->rateratio);\n    chip->samplecnt += 1 << RSM_FRAC;\n}\n\nvoid OPN2_GenerateStream(ym3438_t *chip, Bit32s **sndptr, Bit32u numsamples)\n{\n    Bit32u i;\n    Bit32s *smpl, *smpr;\n    Bit32s buffer[2];\n    smpl = sndptr[0];\n    smpr = sndptr[1];\n\n    for (i = 0; i < numsamples; i++)\n    {\n        OPN2_GenerateResampled(chip, buffer);\n        *smpl++ = buffer[0];\n        *smpr++ = buffer[1];\n    }\n}\n\nvoid OPN2_SetOptions(Bit8u flags)\n{\n    switch ((flags >> 3) & 0x03)\n    {\n    case 0x00: // YM2612\n    default:\n        OPN2_SetChipType(ym3438_type_ym2612);\n        break;\n    case 0x01: // ASIC YM3438\n        OPN2_SetChipType(ym3438_type_asic);\n        break;\n    case 0x02: // Discrete YM3438\n        OPN2_SetChipType(ym3438_type_discrete);\n        break;\n    case 0x03: // YM2612 without filter emulation\n        OPN2_SetChipType(ym3438_type_ym2612_u);\n        break;\n    }\n}\n\nvoid OPN2_SetMute(ym3438_t *chip, Bit32u mute)\n{\n    Bit32u i;\n    for (i = 0; i < 7; i++)\n    {\n        chip->mute[i] = (mute >> i) & 0x01;\n    }\n}\n"
  },
  {
    "path": "VGMPlay/chips/ym3438.h",
    "content": "//\n// Copyright (C) 2017 Alexey Khokholov (Nuke.YKT)\n// \n// This program is free software; you can redistribute it and/or\n// modify it under the terms of the GNU General Public License\n// as published by the Free Software Foundation; either version 2\n// of the License, or (at your option) any later version.\n// \n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License\n// along with this program; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n//\n//\n//  Nuked OPN2(Yamaha YM3438) emulator.\n//  Thanks:\n//      Silicon Pr0n:\n//          Yamaha YM3438 decap and die shot(digshadow).\n//      OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):\n//          OPL2 ROMs.\n//\n// version: 1.0.7\n//\n\n#ifndef YM3438_H\n#define YM3438_H\n\n#define RSM_FRAC 10\n#define OPN_WRITEBUF_SIZE 2048\n#define OPN_WRITEBUF_DELAY 15\n\nenum {\n    ym3438_type_discrete = 0,   /* Discrete YM3438 (Teradrive)          */\n    ym3438_type_asic = 1,       /* ASIC YM3438 (MD1 VA7, MD2, MD3, etc) */\n    ym3438_type_ym2612 = 2,     /* YM2612 (MD1, MD2 VA2)                */\n    ym3438_type_ym2612_u = 3\t/* YM2612 without lowpass filter \t\t*/\n};\n\n#include \"mamedef.h\"\n\ntypedef UINT64          Bit64u;\ntypedef INT64           Bit64s;\ntypedef UINT32          Bit32u;\ntypedef INT32           Bit32s;\ntypedef UINT16          Bit16u;\ntypedef INT16           Bit16s;\ntypedef UINT8           Bit8u;\ntypedef INT8            Bit8s;\n\ntypedef struct _opn2_writebuf {\n    Bit64u time;\n    Bit8u port;\n    Bit8u data;\n} opn2_writebuf;\n\ntypedef struct\n{\n    Bit32u cycles;\n    Bit32u slot;\n    Bit32u channel;\n    Bit16s mol, mor;\n    /* IO */\n    Bit16u write_data;\n    Bit8u write_a;\n    Bit8u write_d;\n    Bit8u write_a_en;\n    Bit8u write_d_en;\n    Bit8u write_busy;\n    Bit8u write_busy_cnt;\n    Bit8u write_fm_address;\n    Bit8u write_fm_data;\n    Bit8u write_fm_mode_a;\n    Bit16u address;\n    Bit8u data;\n    Bit8u pin_test_in;\n    Bit8u pin_irq;\n    Bit8u busy;\n    /* LFO */\n    Bit8u lfo_en;\n    Bit8u lfo_freq;\n    Bit8u lfo_pm;\n    Bit8u lfo_am;\n    Bit8u lfo_cnt;\n    Bit8u lfo_inc;\n    Bit8u lfo_quotient;\n    /* Phase generator */\n    Bit16u pg_fnum;\n    Bit8u pg_block;\n    Bit8u pg_kcode;\n    Bit32u pg_inc[24];\n    Bit32u pg_phase[24];\n    Bit8u pg_reset[24];\n    Bit32u pg_read;\n    /* Envelope generator */\n    Bit8u eg_cycle;\n    Bit8u eg_cycle_stop;\n    Bit8u eg_shift;\n    Bit8u eg_shift_lock;\n    Bit8u eg_timer_low_lock;\n    Bit16u eg_timer;\n    Bit8u eg_timer_inc;\n    Bit16u eg_quotient;\n    Bit8u eg_custom_timer;\n    Bit8u eg_rate;\n    Bit8u eg_ksv;\n    Bit8u eg_inc;\n    Bit8u eg_ratemax;\n    Bit8u eg_sl[2];\n    Bit8u eg_lfo_am;\n    Bit8u eg_tl[2];\n    Bit8u eg_state[24];\n    Bit16u eg_level[24];\n    Bit16u eg_out[24];\n    Bit8u eg_kon[24];\n    Bit8u eg_kon_csm[24];\n    Bit8u eg_kon_latch[24];\n    Bit8u eg_csm_mode[24];\n    Bit8u eg_ssg_enable[24];\n    Bit8u eg_ssg_pgrst_latch[24];\n    Bit8u eg_ssg_repeat_latch[24];\n    Bit8u eg_ssg_hold_up_latch[24];\n    Bit8u eg_ssg_dir[24];\n    Bit8u eg_ssg_inv[24];\n    Bit32u eg_read[2];\n    Bit8u eg_read_inc;\n    /* FM */\n    Bit16s fm_op1[6][2];\n    Bit16s fm_op2[6];\n    Bit16s fm_out[24];\n    Bit16u fm_mod[24];\n    /* Channel */\n    Bit16s ch_acc[6];\n    Bit16s ch_out[6];\n    Bit16s ch_lock;\n    Bit8u ch_lock_l;\n    Bit8u ch_lock_r;\n    Bit16s ch_read;\n    /* Timer */\n    Bit16u timer_a_cnt;\n    Bit16u timer_a_reg;\n    Bit8u timer_a_load_lock;\n    Bit8u timer_a_load;\n    Bit8u timer_a_enable;\n    Bit8u timer_a_reset;\n    Bit8u timer_a_load_latch;\n    Bit8u timer_a_overflow_flag;\n    Bit8u timer_a_overflow;\n    \n    Bit16u timer_b_cnt;\n    Bit8u timer_b_subcnt;\n    Bit16u timer_b_reg;\n    Bit8u timer_b_load_lock;\n    Bit8u timer_b_load;\n    Bit8u timer_b_enable;\n    Bit8u timer_b_reset;\n    Bit8u timer_b_load_latch;\n    Bit8u timer_b_overflow_flag;\n    Bit8u timer_b_overflow;\n    \n    /* Register set */\n    Bit8u mode_test_21[8];\n    Bit8u mode_test_2c[8];\n    Bit8u mode_ch3;\n    Bit8u mode_kon_channel;\n    Bit8u mode_kon_operator[4];\n    Bit8u mode_kon[24];\n    Bit8u mode_csm;\n    Bit8u mode_kon_csm;\n    Bit8u dacen;\n    Bit16s dacdata;\n    \n    Bit8u ks[24];\n    Bit8u ar[24];\n    Bit8u sr[24];\n    Bit8u dt[24];\n    Bit8u multi[24];\n    Bit8u sl[24];\n    Bit8u rr[24];\n    Bit8u dr[24];\n    Bit8u am[24];\n    Bit8u tl[24];\n    Bit8u ssg_eg[24];\n    \n    Bit16u fnum[6];\n    Bit8u block[6];\n    Bit8u kcode[6];\n    Bit16u fnum_3ch[6];\n    Bit8u block_3ch[6];\n    Bit8u kcode_3ch[6];\n    Bit8u reg_a4;\n    Bit8u reg_ac;\n    Bit8u connect[6];\n    Bit8u fb[6];\n    Bit8u pan_l[6], pan_r[6];\n    Bit8u ams[6];\n    Bit8u pms[6];\n\n\tBit32u mute[7];\n\tBit32s rateratio;\n\tBit32s samplecnt;\n\tBit32s oldsamples[2];\n\tBit32s samples[2];\n\n    Bit64u writebuf_samplecnt;\n    Bit32u writebuf_cur;\n    Bit32u writebuf_last;\n    Bit64u writebuf_lasttime;\n    opn2_writebuf writebuf[OPN_WRITEBUF_SIZE];\n} ym3438_t;\n\nvoid OPN2_Reset(ym3438_t *chip, Bit32u rate, Bit32u clock);\nvoid OPN2_SetChipType(Bit32u type);\nvoid OPN2_Clock(ym3438_t *chip, Bit32s *buffer);\nvoid OPN2_Write(ym3438_t *chip, Bit32u port, Bit8u data);\nvoid OPN2_SetTestPin(ym3438_t *chip, Bit32u value);\nBit32u OPN2_ReadTestPin(ym3438_t *chip);\nBit32u OPN2_ReadIRQPin(ym3438_t *chip);\nBit8u OPN2_Read(ym3438_t *chip, Bit32u port);\nvoid OPN2_WriteBuffered(ym3438_t *chip, Bit32u port, Bit8u data);\nvoid OPN2_GenerateStream(ym3438_t *chip, Bit32s **sndptr, Bit32u numsamples);\nvoid OPN2_SetOptions(Bit8u flags);\nvoid OPN2_SetMute(ym3438_t *chip, Bit32u mute);\n#endif\n"
  },
  {
    "path": "VGMPlay/chips/ymdeltat.c",
    "content": "/*\n**\n** File: ymdeltat.c\n**\n** YAMAHA DELTA-T adpcm sound emulation subroutine\n** used by fmopl.c (Y8950) and fm.c (YM2608 and YM2610/B)\n**\n** Base program is YM2610 emulator by Hiromitsu Shioya.\n** Written by Tatsuyuki Satoh\n** Improvements by Jarek Burczynski (bujar at mame dot net)\n**\n**\n** History:\n**\n** 03-08-2003 Jarek Burczynski:\n**  - fixed BRDY flag implementation.\n**\n** 24-07-2003 Jarek Burczynski, Frits Hilderink:\n**  - fixed delault value for control2 in YM_DELTAT_ADPCM_Reset\n**\n** 22-07-2003 Jarek Burczynski, Frits Hilderink:\n**  - fixed external memory support\n**\n** 15-06-2003 Jarek Burczynski:\n**  - implemented CPU -> AUDIO ADPCM synthesis (via writes to the ADPCM data reg $08)\n**  - implemented support for the Limit address register\n**  - supported two bits from the control register 2 ($01): RAM TYPE (x1 bit/x8 bit), ROM/RAM\n**  - implemented external memory access (read/write) via the ADPCM data reg reads/writes\n**    Thanks go to Frits Hilderink for the example code.\n**\n** 14-06-2003 Jarek Burczynski:\n**  - various fixes to enable proper support for status register flags: BSRDY, PCM BSY, ZERO\n**  - modified EOS handling\n**\n** 05-04-2003 Jarek Burczynski:\n**  - implemented partial support for external/processor memory on sample replay\n**\n** 01-12-2002 Jarek Burczynski:\n**  - fixed first missing sound in gigandes thanks to previous fix (interpolator) by ElSemi\n**  - renamed/removed some YM_DELTAT struct fields\n**\n** 28-12-2001 Acho A. Tang\n**  - added EOS status report on ADPCM playback.\n**\n** 05-08-2001 Jarek Burczynski:\n**  - now_step is initialized with 0 at the start of play.\n**\n** 12-06-2001 Jarek Burczynski:\n**  - corrected end of sample bug in YM_DELTAT_ADPCM_CALC.\n**    Checked on real YM2610 chip - address register is 24 bits wide.\n**    Thanks go to Stefan Jokisch (stefan.jokisch@gmx.de) for tracking down the problem.\n**\n** TO DO:\n**      Check size of the address register on the other chips....\n**\n** Version 0.72\n**\n** sound chips that have this unit:\n** YM2608   OPNA\n** YM2610/B OPNB\n** Y8950    MSX AUDIO\n**\n*/\n\n#include \"mamedef.h\"\n#include <stdio.h>\n//#include \"sndintrf.h\"\n#include \"ymdeltat.h\"\n\n#define YM_DELTAT_DELTA_MAX (24576)\n#define YM_DELTAT_DELTA_MIN (127)\n#define YM_DELTAT_DELTA_DEF (127)\n\n#define YM_DELTAT_DECODE_RANGE 32768\n#define YM_DELTAT_DECODE_MIN (-(YM_DELTAT_DECODE_RANGE))\n#define YM_DELTAT_DECODE_MAX ((YM_DELTAT_DECODE_RANGE)-1)\n\n\n/* Forecast to next Forecast (rate = *8) */\n/* 1/8 , 3/8 , 5/8 , 7/8 , 9/8 , 11/8 , 13/8 , 15/8 */\nstatic const INT32 ym_deltat_decode_tableB1[16] = {\n  1,   3,   5,   7,   9,  11,  13,  15,\n  -1,  -3,  -5,  -7,  -9, -11, -13, -15,\n};\n/* delta to next delta (rate= *64) */\n/* 0.9 , 0.9 , 0.9 , 0.9 , 1.2 , 1.6 , 2.0 , 2.4 */\nstatic const INT32 ym_deltat_decode_tableB2[16] = {\n  57,  57,  57,  57, 77, 102, 128, 153,\n  57,  57,  57,  57, 77, 102, 128, 153\n};\n\n#if 0\nvoid YM_DELTAT_BRDY_callback(YM_DELTAT *DELTAT)\n{\n\tlogerror(\"BRDY_callback reached (flag set) !\\n\");\n\n\t/* set BRDY bit in status register */\n\tif(DELTAT->status_set_handler)\n\t\tif(DELTAT->status_change_BRDY_bit)\n\t\t\t(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);\n}\n#endif\n\nUINT8 YM_DELTAT_ADPCM_Read(YM_DELTAT *DELTAT)\n{\n\tUINT8 v = 0;\n\n\t/* external memory read */\n\tif ( (DELTAT->portstate & 0xe0)==0x20 )\n\t{\n\t\t/* two dummy reads */\n\t\tif (DELTAT->memread)\n\t\t{\n\t\t\tDELTAT->now_addr = DELTAT->start << 1;\n\t\t\tDELTAT->memread--;\n\t\t\treturn 0;\n\t\t}\n\n\n\t\tif ( DELTAT->now_addr != (DELTAT->end<<1) )\n\t\t{\n\t\t\tv = DELTAT->memory[DELTAT->now_addr>>1];\n\n\t\t\t/*logerror(\"YM Delta-T memory read  $%08x, v=$%02x\\n\", DELTAT->now_addr >> 1, v);*/\n\n\t\t\tDELTAT->now_addr+=2; /* two nibbles at a time */\n\n\t\t\t/* reset BRDY bit in status register, which means we are reading the memory now */\n\t\t\tif(DELTAT->status_reset_handler)\n\t\t\t\tif(DELTAT->status_change_BRDY_bit)\n\t\t\t\t\t(DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);\n\n\t/* setup a timer that will callback us in 10 master clock cycles for Y8950\n    * in the callback set the BRDY flag to 1 , which means we have another data ready.\n    * For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work.\n    */\n\t\t\t/* set BRDY bit in status register */\n\t\t\tif(DELTAT->status_set_handler)\n\t\t\t\tif(DELTAT->status_change_BRDY_bit)\n\t\t\t\t\t(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* set EOS bit in status register */\n\t\t\tif(DELTAT->status_set_handler)\n\t\t\t\tif(DELTAT->status_change_EOS_bit)\n\t\t\t\t\t(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit);\n\t\t}\n\t}\n\n\treturn v;\n}\n\n\n/* 0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */\nstatic const UINT8 dram_rightshift[4]={3,0,0,0};\n\n/* DELTA-T ADPCM write register */\nvoid YM_DELTAT_ADPCM_Write(YM_DELTAT *DELTAT,int r,int v)\n{\n\tif(r>=0x10) return;\n\tDELTAT->reg[r] = v; /* stock data */\n\n\tswitch( r )\n\t{\n\tcase 0x00:\n/*\nSTART:\n    Accessing *external* memory is started when START bit (D7) is set to \"1\", so\n    you must set all conditions needed for recording/playback before starting.\n    If you access *CPU-managed* memory, recording/playback starts after\n    read/write of ADPCM data register $08.\n\nREC:\n    0 = ADPCM synthesis (playback)\n    1 = ADPCM analysis (record)\n\nMEMDATA:\n    0 = processor (*CPU-managed*) memory (means: using register $08)\n    1 = external memory (using start/end/limit registers to access memory: RAM or ROM)\n\n\nSPOFF:\n    controls output pin that should disable the speaker while ADPCM analysis\n\nRESET and REPEAT only work with external memory.\n\n\nsome examples:\nvalue:   START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET   meaning:\n  C8     1      1    0       0       1      0 0 0       Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register\n  E8     1      1    1       0       1      0 0 0       Analysis (recording) from AUDIO to EXT.MEMORY,       sample rate in PRESCALER register\n  80     1      0    0       0       0      0 0 0       Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register\n  a0     1      0    1       0       0      0 0 0       Synthesis (playing) from EXT.MEMORY to AUDIO,        sample rate in DELTA-N register\n\n  60     0      1    1       0       0      0 0 0       External memory write via ADPCM data register $08\n  20     0      0    1       0       0      0 0 0       External memory read via ADPCM data register $08\n\n*/\n\t\t/* handle emulation mode */\n\t\tif(DELTAT->emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610)\n\t\t{\n\t\t\tv |= 0x20;\t\t/*  YM2610 always uses external memory and doesn't even have memory flag bit. */\n\t\t}\n\n\t\tDELTAT->portstate = v & (0x80|0x40|0x20|0x10|0x01); /* start, rec, memory mode, repeat flag copy, reset(bit0) */\n\n\t\tif( DELTAT->portstate&0x80 )/* START,REC,MEMDATA,REPEAT,SPOFF,--,--,RESET */\n\t\t{\n\t\t\t/* set PCM BUSY bit */\n\t\t\tDELTAT->PCM_BSY = 1;\n\n\t\t\t/* start ADPCM */\n\t\t\tDELTAT->now_step = 0;\n\t\t\tDELTAT->acc      = 0;\n\t\t\tDELTAT->prev_acc = 0;\n\t\t\tDELTAT->adpcml   = 0;\n\t\t\tDELTAT->adpcmd   = YM_DELTAT_DELTA_DEF;\n\t\t\tDELTAT->now_data = 0;\n\t\t\tif (DELTAT->start > DELTAT->end)\n\t\t\t\tlogerror(\"DeltaT-Warning: Start: %06X, End: %06X\\n\", DELTAT->start, DELTAT->end);\n\t\t}\n\n\t\tif( DELTAT->portstate&0x20 ) /* do we access external memory? */\n\t\t{\n\t\t\tDELTAT->now_addr = DELTAT->start << 1;\n\t\t\tDELTAT->memread = 2;\t/* two dummy reads needed before accesing external memory via register $08*/\n\n\t\t\t/* if yes, then let's check if ADPCM memory is mapped and big enough */\n\t\t\tif(DELTAT->memory == 0)\n\t\t\t{\n#ifdef _DEBUG\n\t\t\t\tlogerror(\"YM Delta-T ADPCM rom not mapped\\n\");\n#endif\n\t\t\t\tDELTAT->portstate = 0x00;\n\t\t\t\tDELTAT->PCM_BSY = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif( DELTAT->end >= DELTAT->memory_size )\t/* Check End in Range */\n\t\t\t\t{\n#ifdef _DEBUG\n\t\t\t\t\tlogerror(\"YM Delta-T ADPCM end out of range: $%08x\\n\", DELTAT->end);\n#endif\n\t\t\t\t\tDELTAT->end = DELTAT->memory_size - 1;\n\t\t\t\t}\n\t\t\t\tif( DELTAT->start >= DELTAT->memory_size )\t/* Check Start in Range */\n\t\t\t\t{\n#ifdef _DEBUG\n\t\t\t\t\tlogerror(\"YM Delta-T ADPCM start out of range: $%08x\\n\", DELTAT->start);\n#endif\n\t\t\t\t\tDELTAT->portstate = 0x00;\n\t\t\t\t\tDELTAT->PCM_BSY = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\t/* we access CPU memory (ADPCM data register $08) so we only reset now_addr here */\n\t\t{\n\t\t\tDELTAT->now_addr = 0;\n\t\t}\n\n\t\tif( DELTAT->portstate&0x01 )\n\t\t{\n\t\t\tDELTAT->portstate = 0x00;\n\n\t\t\t/* clear PCM BUSY bit (in status register) */\n\t\t\tDELTAT->PCM_BSY = 0;\n\n\t\t\t/* set BRDY flag */\n\t\t\tif(DELTAT->status_set_handler)\n\t\t\t\tif(DELTAT->status_change_BRDY_bit)\n\t\t\t\t\t(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);\n\t\t}\n\t\tbreak;\n\tcase 0x01:\t/* L,R,-,-,SAMPLE,DA/AD,RAMTYPE,ROM */\n\t\t/* handle emulation mode */\n\t\tif(DELTAT->emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610)\n\t\t{\n\t\t\tv |= 0x01;\t\t/*  YM2610 always uses ROM as an external memory and doesn't have ROM/RAM memory flag bit. */\n\t\t}\n\n\t\tDELTAT->pan = &DELTAT->output_pointer[(v>>6)&0x03];\n\t\tif ((DELTAT->control2 & 3) != (v & 3))\n\t\t{\n\t\t\t/*0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */\n\t\t\tif (DELTAT->DRAMportshift != dram_rightshift[v&3])\n\t\t\t{\n\t\t\t\tDELTAT->DRAMportshift = dram_rightshift[v&3];\n\n\t\t\t\t/* final shift value depends on chip type and memory type selected:\n                        8 for YM2610 (ROM only),\n                        5 for ROM for Y8950 and YM2608,\n                        5 for x8bit DRAMs for Y8950 and YM2608,\n                        2 for x1bit DRAMs for Y8950 and YM2608.\n                */\n\n\t\t\t\t/* refresh addresses */\n\t\t\t\tDELTAT->start  = (DELTAT->reg[0x3]*0x0100 | DELTAT->reg[0x2]) << (DELTAT->portshift - DELTAT->DRAMportshift);\n\t\t\t\tDELTAT->end    = (DELTAT->reg[0x5]*0x0100 | DELTAT->reg[0x4]) << (DELTAT->portshift - DELTAT->DRAMportshift);\n\t\t\t\tDELTAT->end   += (1 << (DELTAT->portshift-DELTAT->DRAMportshift) ) - 1;\n\t\t\t\tDELTAT->limit  = (DELTAT->reg[0xd]*0x0100 | DELTAT->reg[0xc]) << (DELTAT->portshift - DELTAT->DRAMportshift);\n\t\t\t}\n\t\t}\n\t\tDELTAT->control2 = v;\n\t\tbreak;\n\tcase 0x02:\t/* Start Address L */\n\tcase 0x03:\t/* Start Address H */\n\t\tDELTAT->start  = (DELTAT->reg[0x3]*0x0100 | DELTAT->reg[0x2]) << (DELTAT->portshift - DELTAT->DRAMportshift);\n\t\t/*logerror(\"DELTAT start: 02=%2x 03=%2x addr=%8x\\n\",DELTAT->reg[0x2], DELTAT->reg[0x3],DELTAT->start );*/\n\t\tbreak;\n\tcase 0x04:\t/* Stop Address L */\n\tcase 0x05:\t/* Stop Address H */\n\t\tDELTAT->end    = (DELTAT->reg[0x5]*0x0100 | DELTAT->reg[0x4]) << (DELTAT->portshift - DELTAT->DRAMportshift);\n\t\tDELTAT->end   += (1 << (DELTAT->portshift-DELTAT->DRAMportshift) ) - 1;\n\t\t/*logerror(\"DELTAT end  : 04=%2x 05=%2x addr=%8x\\n\",DELTAT->reg[0x4], DELTAT->reg[0x5],DELTAT->end   );*/\n\t\tbreak;\n\tcase 0x06:\t/* Prescale L (ADPCM and Record frq) */\n\tcase 0x07:\t/* Prescale H */\n\t\tbreak;\n\tcase 0x08:\t/* ADPCM data */\n\n/*\nsome examples:\nvalue:   START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET   meaning:\n  C8     1      1    0       0       1      0 0 0       Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register\n  E8     1      1    1       0       1      0 0 0       Analysis (recording) from AUDIO to EXT.MEMORY,       sample rate in PRESCALER register\n  80     1      0    0       0       0      0 0 0       Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register\n  a0     1      0    1       0       0      0 0 0       Synthesis (playing) from EXT.MEMORY to AUDIO,        sample rate in DELTA-N register\n\n  60     0      1    1       0       0      0 0 0       External memory write via ADPCM data register $08\n  20     0      0    1       0       0      0 0 0       External memory read via ADPCM data register $08\n\n*/\n\n\t\t/* external memory write */\n\t\tif ( (DELTAT->portstate & 0xe0)==0x60 )\n\t\t{\n\t\t\tif (DELTAT->memread)\n\t\t\t{\n\t\t\t\tDELTAT->now_addr = DELTAT->start << 1;\n\t\t\t\tDELTAT->memread = 0;\n\t\t\t}\n\n\t\t\t/*logerror(\"YM Delta-T memory write $%08x, v=$%02x\\n\", DELTAT->now_addr >> 1, v);*/\n\n\t\t\tif ( DELTAT->now_addr != (DELTAT->end<<1) )\n\t\t\t{\n\t\t\t\tDELTAT->memory[DELTAT->now_addr>>1] = v;\n\t\t\t\tDELTAT->now_addr+=2; /* two nibbles at a time */\n\n\t\t\t\t/* reset BRDY bit in status register, which means we are processing the write */\n\t\t\t\tif(DELTAT->status_reset_handler)\n\t\t\t\t\tif(DELTAT->status_change_BRDY_bit)\n\t\t\t\t\t\t(DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);\n\n\t/* setup a timer that will callback us in 10 master clock cycles for Y8950\n    * in the callback set the BRDY flag to 1 , which means we have written the data.\n    * For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work.\n    */\n\t\t\t\t/* set BRDY bit in status register */\n\t\t\t\tif(DELTAT->status_set_handler)\n\t\t\t\t\tif(DELTAT->status_change_BRDY_bit)\n\t\t\t\t\t\t(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);\n\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* set EOS bit in status register */\n\t\t\t\tif(DELTAT->status_set_handler)\n\t\t\t\t\tif(DELTAT->status_change_EOS_bit)\n\t\t\t\t\t\t(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t/* ADPCM synthesis from CPU */\n\t\tif ( (DELTAT->portstate & 0xe0)==0x80 )\n\t\t{\n\t\t\tDELTAT->CPU_data = v;\n\n\t\t\t/* Reset BRDY bit in status register, which means we are full of data */\n\t\t\tif(DELTAT->status_reset_handler)\n\t\t\t\tif(DELTAT->status_change_BRDY_bit)\n\t\t\t\t\t(DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);\n\t\t\treturn;\n\t\t}\n\n\t  break;\n\tcase 0x09:\t/* DELTA-N L (ADPCM Playback Prescaler) */\n\tcase 0x0a:\t/* DELTA-N H */\n\t\tDELTAT->delta  = (DELTAT->reg[0xa]*0x0100 | DELTAT->reg[0x9]);\n\t\tDELTAT->step     = (UINT32)( (double)(DELTAT->delta /* *(1<<(YM_DELTAT_SHIFT-16)) */ ) * (DELTAT->freqbase) );\n\t\t/*logerror(\"DELTAT deltan:09=%2x 0a=%2x\\n\",DELTAT->reg[0x9], DELTAT->reg[0xa]);*/\n\t\tbreak;\n\tcase 0x0b:\t/* Output level control (volume, linear) */\n\t\t{\n\t\t\tINT32 oldvol = DELTAT->volume;\n\t\t\tDELTAT->volume = (v&0xff) * (DELTAT->output_range/256) / YM_DELTAT_DECODE_RANGE;\n/*                              v     *     ((1<<16)>>8)        >>  15;\n*                       thus:   v     *     (1<<8)              >>  15;\n*                       thus: output_range must be (1 << (15+8)) at least\n*                               v     *     ((1<<23)>>8)        >>  15;\n*                               v     *     (1<<15)             >>  15;\n*/\n\t\t\t/*logerror(\"DELTAT vol = %2x\\n\",v&0xff);*/\n\t\t\tif( oldvol != 0 )\n\t\t\t{\n\t\t\t\tDELTAT->adpcml = (int)((double)DELTAT->adpcml / (double)oldvol * (double)DELTAT->volume);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase 0x0c:\t/* Limit Address L */\n\tcase 0x0d:\t/* Limit Address H */\n\t\tDELTAT->limit  = (DELTAT->reg[0xd]*0x0100 | DELTAT->reg[0xc]) << (DELTAT->portshift - DELTAT->DRAMportshift);\n\t\t/*logerror(\"DELTAT limit: 0c=%2x 0d=%2x addr=%8x\\n\",DELTAT->reg[0xc], DELTAT->reg[0xd],DELTAT->limit );*/\n\t\tbreak;\n\t}\n}\n\nvoid YM_DELTAT_ADPCM_Reset(YM_DELTAT *DELTAT,int pan,int emulation_mode)\n{\n\tDELTAT->now_addr  = 0;\n\tDELTAT->now_step  = 0;\n\tDELTAT->step      = 0;\n\tDELTAT->start     = 0;\n\tDELTAT->end       = 0;\n\tDELTAT->limit     = ~0; /* this way YM2610 and Y8950 (both of which don't have limit address reg) will still work */\n\tDELTAT->volume    = 0;\n\tDELTAT->pan       = &DELTAT->output_pointer[pan];\n\tDELTAT->acc       = 0;\n\tDELTAT->prev_acc  = 0;\n\tDELTAT->adpcmd    = 127;\n\tDELTAT->adpcml    = 0;\n\tDELTAT->emulation_mode = (UINT8)emulation_mode;\n\tDELTAT->portstate = (emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610) ? 0x20 : 0;\n\tDELTAT->control2  = (emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610) ? 0x01 : 0;\t/* default setting depends on the emulation mode. MSX demo called \"facdemo_4\" doesn't setup control2 register at all and still works */\n\tDELTAT->DRAMportshift = dram_rightshift[DELTAT->control2 & 3];\n\n\t/* The flag mask register disables the BRDY after the reset, however\n    ** as soon as the mask is enabled the flag needs to be set. */\n\n\t/* set BRDY bit in status register */\n\tif(DELTAT->status_set_handler)\n\t\tif(DELTAT->status_change_BRDY_bit)\n\t\t\t(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);\n}\n\n/*void YM_DELTAT_postload(YM_DELTAT *DELTAT,UINT8 *regs)\n{\n\tint r;\n\n\t// to keep adpcml\n\tDELTAT->volume = 0;\n\t// update\n\tfor(r=1;r<16;r++)\n\t\tYM_DELTAT_ADPCM_Write(DELTAT,r,regs[r]);\n\tDELTAT->reg[0] = regs[0];\n\n\t// current rom data\n\tif (DELTAT->memory)\n\t\tDELTAT->now_data = *(DELTAT->memory + (DELTAT->now_addr>>1) );\n\n}\n//void YM_DELTAT_savestate(const device_config *device,YM_DELTAT *DELTAT)\nvoid YM_DELTAT_savestate(YM_DELTAT *DELTAT)\n{\n#ifdef __STATE_H__\n\tstate_save_register_device_item(device, 0, DELTAT->portstate);\n\tstate_save_register_device_item(device, 0, DELTAT->now_addr);\n\tstate_save_register_device_item(device, 0, DELTAT->now_step);\n\tstate_save_register_device_item(device, 0, DELTAT->acc);\n\tstate_save_register_device_item(device, 0, DELTAT->prev_acc);\n\tstate_save_register_device_item(device, 0, DELTAT->adpcmd);\n\tstate_save_register_device_item(device, 0, DELTAT->adpcml);\n#endif\n}*/\n\n\n#define YM_DELTAT_Limit(val,max,min)\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n\tif ( val > max ) val = max;\t\t\t\\\n\telse if ( val < min ) val = min;\t\\\n}\n\nINLINE void YM_DELTAT_synthesis_from_external_memory(YM_DELTAT *DELTAT)\n{\n\tUINT32 step;\n\tint data;\n\n\tDELTAT->now_step += DELTAT->step;\n\tif ( DELTAT->now_step >= (1<<YM_DELTAT_SHIFT) )\n\t{\n\t\tstep = DELTAT->now_step >> YM_DELTAT_SHIFT;\n\t\tDELTAT->now_step &= (1<<YM_DELTAT_SHIFT)-1;\n\t\tdo{\n\n\t\t\tif ( DELTAT->now_addr == (DELTAT->limit<<1) )\n\t\t\t\tDELTAT->now_addr = 0;\n\n\t\t\tif ( DELTAT->now_addr == (DELTAT->end<<1) ) {\t/* 12-06-2001 JB: corrected comparison. Was > instead of == */\n\t\t\t\tif( DELTAT->portstate&0x10 ){\n\t\t\t\t\t/* repeat start */\n\t\t\t\t\tDELTAT->now_addr = DELTAT->start<<1;\n\t\t\t\t\tDELTAT->acc      = 0;\n\t\t\t\t\tDELTAT->adpcmd   = YM_DELTAT_DELTA_DEF;\n\t\t\t\t\tDELTAT->prev_acc = 0;\n\t\t\t\t}else{\n\t\t\t\t\t/* set EOS bit in status register */\n\t\t\t\t\tif(DELTAT->status_set_handler)\n\t\t\t\t\t\tif(DELTAT->status_change_EOS_bit)\n\t\t\t\t\t\t\t(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit);\n\n\t\t\t\t\t/* clear PCM BUSY bit (reflected in status register) */\n\t\t\t\t\tDELTAT->PCM_BSY = 0;\n\n\t\t\t\t\tDELTAT->portstate = 0;\n\t\t\t\t\tDELTAT->adpcml = 0;\n\t\t\t\t\tDELTAT->prev_acc = 0;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( DELTAT->now_addr&1 ) data = DELTAT->now_data & 0x0f;\n\t\t\telse\n\t\t\t{\n\t\t\t\tDELTAT->now_data = *(DELTAT->memory + (DELTAT->now_addr>>1));\n\t\t\t\tdata = DELTAT->now_data >> 4;\n\t\t\t}\n\n\t\t\tDELTAT->now_addr++;\n\t\t\t/* 12-06-2001 JB: */\n\t\t\t/* YM2610 address register is 24 bits wide.*/\n\t\t\t/* The \"+1\" is there because we use 1 bit more for nibble calculations.*/\n\t\t\t/* WARNING: */\n\t\t\t/* Side effect: we should take the size of the mapped ROM into account */\n\t\t\t//DELTAT->now_addr &= ( (1<<(24+1))-1);\n\t\t\tDELTAT->now_addr &= DELTAT->memory_mask;\n\t\t\t\n\n\t\t\t/* store accumulator value */\n\t\t\tDELTAT->prev_acc = DELTAT->acc;\n\n\t\t\t/* Forecast to next Forecast */\n\t\t\tDELTAT->acc += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8);\n\t\t\tYM_DELTAT_Limit(DELTAT->acc,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN);\n\n\t\t\t/* delta to next delta */\n\t\t\tDELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64;\n\t\t\tYM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN );\n\n\t\t\t/* ElSemi: Fix interpolator. */\n\t\t\t/*DELTAT->prev_acc = prev_acc + ((DELTAT->acc - prev_acc) / 2 );*/\n\n\t\t}while(--step);\n\n\t}\n\n\t/* ElSemi: Fix interpolator. */\n\tDELTAT->adpcml = DELTAT->prev_acc * (int)((1<<YM_DELTAT_SHIFT)-DELTAT->now_step);\n\tDELTAT->adpcml += (DELTAT->acc * (int)DELTAT->now_step);\n\tDELTAT->adpcml = (DELTAT->adpcml>>YM_DELTAT_SHIFT) * (int)DELTAT->volume;\n\n\t/* output for work of output channels (outd[OPNxxxx])*/\n\t*(DELTAT->pan) += DELTAT->adpcml;\n}\n\n\n\nINLINE void YM_DELTAT_synthesis_from_CPU_memory(YM_DELTAT *DELTAT)\n{\n\tUINT32 step;\n\tint data;\n\n\tDELTAT->now_step += DELTAT->step;\n\tif ( DELTAT->now_step >= (1<<YM_DELTAT_SHIFT) )\n\t{\n\t\tstep = DELTAT->now_step >> YM_DELTAT_SHIFT;\n\t\tDELTAT->now_step &= (1<<YM_DELTAT_SHIFT)-1;\n\t\tdo{\n\n\t\t\tif( DELTAT->now_addr&1 )\n\t\t\t{\n\t\t\t\tdata = DELTAT->now_data & 0x0f;\n\n\t\t\t\tDELTAT->now_data = DELTAT->CPU_data;\n\n\t\t\t\t/* after we used CPU_data, we set BRDY bit in status register,\n                * which means we are ready to accept another byte of data */\n\t\t\t\tif(DELTAT->status_set_handler)\n\t\t\t\t\tif(DELTAT->status_change_BRDY_bit)\n\t\t\t\t\t\t(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdata = DELTAT->now_data >> 4;\n\t\t\t}\n\n\t\t\tDELTAT->now_addr++;\n\n\t\t\t/* store accumulator value */\n\t\t\tDELTAT->prev_acc = DELTAT->acc;\n\n\t\t\t/* Forecast to next Forecast */\n\t\t\tDELTAT->acc += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8);\n\t\t\tYM_DELTAT_Limit(DELTAT->acc,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN);\n\n\t\t\t/* delta to next delta */\n\t\t\tDELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64;\n\t\t\tYM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN );\n\n\n\t\t}while(--step);\n\n\t}\n\n\t/* ElSemi: Fix interpolator. */\n\tDELTAT->adpcml = DELTAT->prev_acc * (int)((1<<YM_DELTAT_SHIFT)-DELTAT->now_step);\n\tDELTAT->adpcml += (DELTAT->acc * (int)DELTAT->now_step);\n\tDELTAT->adpcml = (DELTAT->adpcml>>YM_DELTAT_SHIFT) * (int)DELTAT->volume;\n\n\t/* output for work of output channels (outd[OPNxxxx])*/\n\t*(DELTAT->pan) += DELTAT->adpcml;\n}\n\n\n\n/* ADPCM B (Delta-T control type) */\nvoid YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT)\n{\n\n/*\nsome examples:\nvalue:   START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET   meaning:\n  80     1      0    0       0       0      0 0 0       Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register\n  a0     1      0    1       0       0      0 0 0       Synthesis (playing) from EXT.MEMORY to AUDIO,        sample rate in DELTA-N register\n  C8     1      1    0       0       1      0 0 0       Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register\n  E8     1      1    1       0       1      0 0 0       Analysis (recording) from AUDIO to EXT.MEMORY,       sample rate in PRESCALER register\n\n  60     0      1    1       0       0      0 0 0       External memory write via ADPCM data register $08\n  20     0      0    1       0       0      0 0 0       External memory read via ADPCM data register $08\n\n*/\n\n\tif ( (DELTAT->portstate & 0xe0)==0xa0 )\n\t{\n\t\tYM_DELTAT_synthesis_from_external_memory(DELTAT);\n\t\treturn;\n\t}\n\n\tif ( (DELTAT->portstate & 0xe0)==0x80 )\n\t{\n\t\t/* ADPCM synthesis from CPU-managed memory (from reg $08) */\n\t\tYM_DELTAT_synthesis_from_CPU_memory(DELTAT);\t/* change output based on data in ADPCM data reg ($08) */\n\t\treturn;\n\t}\n\n//todo: ADPCM analysis\n//  if ( (DELTAT->portstate & 0xe0)==0xc0 )\n//  if ( (DELTAT->portstate & 0xe0)==0xe0 )\n\n\treturn;\n}\n\nvoid YM_DELTAT_calc_mem_mask(YM_DELTAT* DELTAT)\n{\n\tUINT32 MaskSize;\n\t\n\tMaskSize = 0x01;\n\twhile(MaskSize < DELTAT->memory_size)\n\t\tMaskSize <<= 1;\n\t\n\tDELTAT->memory_mask = (MaskSize << 1) - 1;\t// it's Mask<<1 because of the nibbles\n\t\n\treturn;\n}"
  },
  {
    "path": "VGMPlay/chips/ymdeltat.h",
    "content": "#pragma once\n\n#define YM_DELTAT_SHIFT    (16)\n\n#define YM_DELTAT_EMULATION_MODE_NORMAL\t0\n#define YM_DELTAT_EMULATION_MODE_YM2610\t1\n\n\ntypedef void (*STATUS_CHANGE_HANDLER)(void *chip, UINT8 status_bits);\n\n\n/* DELTA-T (adpcm type B) struct */\ntypedef struct deltat_adpcm_state {     /* AT: rearranged and tigntened structure */\n\tUINT8\t*memory;\n\tINT32\t*output_pointer;/* pointer of output pointers   */\n\tINT32\t*pan;\t\t\t/* pan : &output_pointer[pan]   */\n\tdouble\tfreqbase;\n#if 0\n\tdouble\twrite_time;\t\t/* Y8950: 10 cycles of main clock; YM2608: 20 cycles of main clock */\n\tdouble\tread_time;\t\t/* Y8950: 8 cycles of main clock;  YM2608: 18 cycles of main clock */\n#endif\n\tUINT32\tmemory_size;\n\tUINT32\tmemory_mask;\n\tint\t\toutput_range;\n\tUINT32\tnow_addr;\t\t/* current address      */\n\tUINT32\tnow_step;\t\t/* currect step         */\n\tUINT32\tstep;\t\t\t/* step                 */\n\tUINT32\tstart;\t\t\t/* start address        */\n\tUINT32\tlimit;\t\t\t/* limit address        */\n\tUINT32\tend;\t\t\t/* end address          */\n\tUINT32\tdelta;\t\t\t/* delta scale          */\n\tINT32\tvolume;\t\t\t/* current volume       */\n\tINT32\tacc;\t\t\t/* shift Measurement value*/\n\tINT32\tadpcmd;\t\t\t/* next Forecast        */\n\tINT32\tadpcml;\t\t\t/* current value        */\n\tINT32\tprev_acc;\t\t/* leveling value       */\n\tUINT8\tnow_data;\t\t/* current rom data     */\n\tUINT8\tCPU_data;\t\t/* current data from reg 08 */\n\tUINT8\tportstate;\t\t/* port status          */\n\tUINT8\tcontrol2;\t\t/* control reg: SAMPLE, DA/AD, RAM TYPE (x8bit / x1bit), ROM/RAM */\n\tUINT8\tportshift;\t\t/* address bits shift-left:\n                            ** 8 for YM2610,\n                            ** 5 for Y8950 and YM2608 */\n\n\tUINT8\tDRAMportshift;\t/* address bits shift-right:\n                            ** 0 for ROM and x8bit DRAMs,\n                            ** 3 for x1 DRAMs */\n\n\tUINT8\tmemread;\t\t/* needed for reading/writing external memory */\n\n\t/* handlers and parameters for the status flags support */\n\tSTATUS_CHANGE_HANDLER\tstatus_set_handler;\n\tSTATUS_CHANGE_HANDLER\tstatus_reset_handler;\n\n\t/* note that different chips have these flags on different\n    ** bits of the status register\n    */\n\tvoid *\tstatus_change_which_chip;\t/* this chip id */\n\tUINT8\tstatus_change_EOS_bit;\t\t/* 1 on End Of Sample (record/playback/cycle time of AD/DA converting has passed)*/\n\tUINT8\tstatus_change_BRDY_bit;\t\t/* 1 after recording 2 datas (2x4bits) or after reading/writing 1 data */\n\tUINT8\tstatus_change_ZERO_bit;\t\t/* 1 if silence lasts for more than 290 miliseconds on ADPCM recording */\n\n\t/* neither Y8950 nor YM2608 can generate IRQ when PCMBSY bit changes, so instead of above,\n    ** the statusflag gets ORed with PCM_BSY (below) (on each read of statusflag of Y8950 and YM2608)\n    */\n\tUINT8\tPCM_BSY;\t\t/* 1 when ADPCM is playing; Y8950/YM2608 only */\n\n\tUINT8\treg[16];\t\t/* adpcm registers      */\n\tUINT8\temulation_mode;\t/* which chip we're emulating */\n}YM_DELTAT;\n\n/*void YM_DELTAT_BRDY_callback(YM_DELTAT *DELTAT);*/\n\nUINT8 YM_DELTAT_ADPCM_Read(YM_DELTAT *DELTAT);\nvoid YM_DELTAT_ADPCM_Write(YM_DELTAT *DELTAT,int r,int v);\nvoid YM_DELTAT_ADPCM_Reset(YM_DELTAT *DELTAT,int pan,int emulation_mode);\nvoid YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT);\n\n/*void YM_DELTAT_postload(YM_DELTAT *DELTAT,UINT8 *regs);\n//void YM_DELTAT_savestate(const device_config *device,YM_DELTAT *DELTAT);\nvoid YM_DELTAT_savestate(YM_DELTAT *DELTAT);*/\n\nvoid YM_DELTAT_calc_mem_mask(YM_DELTAT* DELTAT);"
  },
  {
    "path": "VGMPlay/chips/ymf262.c",
    "content": "/*\n**\n** File: ymf262.c - software implementation of YMF262\n**                  FM sound generator type OPL3\n**\n** Copyright Jarek Burczynski\n**\n** Version 0.2\n**\n\nRevision History:\n\n03-03-2003: initial release\n - thanks to Olivier Galibert and Chris Hardy for YMF262 and YAC512 chips\n - thanks to Stiletto for the datasheets\n\n   Features as listed in 4MF262A6 data sheet:\n    1. Registers are compatible with YM3812 (OPL2) FM sound source.\n    2. Up to six sounds can be used as four-operator melody sounds for variety.\n    3. 18 simultaneous melody sounds, or 15 melody sounds with 5 rhythm sounds (with two operators).\n    4. 6 four-operator melody sounds and 6 two-operator melody sounds, or 6 four-operator melody\n       sounds, 3 two-operator melody sounds and 5 rhythm sounds (with four operators).\n    5. 8 selectable waveforms.\n    6. 4-channel sound output.\n    7. YMF262 compabile DAC (YAC512) is available.\n    8. LFO for vibrato and tremolo effedts.\n    9. 2 programable timers.\n   10. Shorter register access time compared with YM3812.\n   11. 5V single supply silicon gate CMOS process.\n   12. 24 Pin SOP Package (YMF262-M), 48 Pin SQFP Package (YMF262-S).\n\n\ndifferences between OPL2 and OPL3 not documented in Yamaha datahasheets:\n- sinus table is a little different: the negative part is off by one...\n\n- in order to enable selection of four different waveforms on OPL2\n  one must set bit 5 in register 0x01(test).\n  on OPL3 this bit is ignored and 4-waveform select works *always*.\n  (Don't confuse this with OPL3's 8-waveform select.)\n\n- Envelope Generator: all 15 x rates take zero time on OPL3\n  (on OPL2 15 0 and 15 1 rates take some time while 15 2 and 15 3 rates\n  take zero time)\n\n- channel calculations: output of operator 1 is in perfect sync with\n  output of operator 2 on OPL3; on OPL and OPL2 output of operator 1\n  is always delayed by one sample compared to output of operator 2\n\n\ndifferences between OPL2 and OPL3 shown in datasheets:\n- YMF262 does not support CSM mode\n\n\n*/\n\n#include <math.h>\n#include \"mamedef.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n//#include \"sndintrf.h\"\n#include \"ymf262.h\"\n\n\n/* output final shift */\n#if (OPL3_SAMPLE_BITS==16)\n\t#define FINAL_SH\t(0)\n\t#define MAXOUT\t\t(+32767)\n\t#define MINOUT\t\t(-32768)\n#else\n\t#define FINAL_SH\t(8)\n\t#define MAXOUT\t\t(+127)\n\t#define MINOUT\t\t(-128)\n#endif\n\n\n#define FREQ_SH\t\t\t16  /* 16.16 fixed point (frequency calculations) */\n#define EG_SH\t\t\t16  /* 16.16 fixed point (EG timing)              */\n#define LFO_SH\t\t\t24  /*  8.24 fixed point (LFO calculations)       */\n#define TIMER_SH\t\t16  /* 16.16 fixed point (timers calculations)    */\n\n#define FREQ_MASK\t\t((1<<FREQ_SH)-1)\n\n/* envelope output entries */\n#define ENV_BITS\t\t10\n#define ENV_LEN\t\t\t(1<<ENV_BITS)\n#define ENV_STEP\t\t(128.0/ENV_LEN)\n\n#define MAX_ATT_INDEX\t((1<<(ENV_BITS-1))-1) /*511*/\n#define MIN_ATT_INDEX\t(0)\n\n/* sinwave entries */\n#define SIN_BITS\t\t10\n#define SIN_LEN\t\t\t(1<<SIN_BITS)\n#define SIN_MASK\t\t(SIN_LEN-1)\n\n#define TL_RES_LEN\t\t(256)\t/* 8 bits addressing (real chip) */\n\n\n\n/* register number to channel number , slot offset */\n#define SLOT1 0\n#define SLOT2 1\n\n/* Envelope Generator phases */\n\n#define EG_ATT\t\t\t4\n#define EG_DEC\t\t\t3\n#define EG_SUS\t\t\t2\n#define EG_REL\t\t\t1\n#define EG_OFF\t\t\t0\n\n\n/* save output as raw 16-bit sample */\n\n/*#define SAVE_SAMPLE*/\n\n#ifdef SAVE_SAMPLE\nstatic FILE *sample[1];\n\t#if 1\t/*save to MONO file */\n\t\t#define SAVE_ALL_CHANNELS \\\n\t\t{\tsigned int pom = a; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t}\n\t#else\t/*save to STEREO file */\n\t\t#define SAVE_ALL_CHANNELS \\\n\t\t{\tsigned int pom = a; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t\tpom = b; \\\n\t\t\tfputc((unsigned short)pom&0xff,sample[0]); \\\n\t\t\tfputc(((unsigned short)pom>>8)&0xff,sample[0]); \\\n\t\t}\n\t#endif\n#endif\n\n//#define LOG_CYM_FILE 0\n//static FILE * cymfile = NULL;\n\n\n\n\n\n#define OPL3_TYPE_YMF262 (0)\t/* 36 operators, 8 waveforms */\n\n\ntypedef struct{\n\tUINT32\tar;\t\t\t/* attack rate: AR<<2           */\n\tUINT32\tdr;\t\t\t/* decay rate:  DR<<2           */\n\tUINT32\trr;\t\t\t/* release rate:RR<<2           */\n\tUINT8\tKSR;\t\t/* key scale rate               */\n\tUINT8\tksl;\t\t/* keyscale level               */\n\tUINT8\tksr;\t\t/* key scale rate: kcode>>KSR   */\n\tUINT8\tmul;\t\t/* multiple: mul_tab[ML]        */\n\n\t/* Phase Generator */\n\tUINT32\tCnt;\t\t/* frequency counter            */\n\tUINT32\tIncr;\t\t/* frequency counter step       */\n\tUINT8   FB;\t\t\t/* feedback shift value         */\n\tINT32   *connect;\t/* slot output pointer          */\n\tINT32   op1_out[2];\t/* slot1 output for feedback    */\n\tUINT8   CON;\t\t/* connection (algorithm) type  */\n\n\t/* Envelope Generator */\n\tUINT8\teg_type;\t/* percussive/non-percussive mode */\n\tUINT8\tstate;\t\t/* phase type                   */\n\tUINT32\tTL;\t\t\t/* total level: TL << 2         */\n\tINT32\tTLL;\t\t/* adjusted now TL              */\n\tINT32\tvolume;\t\t/* envelope counter             */\n\tUINT32\tsl;\t\t\t/* sustain level: sl_tab[SL]    */\n\n\tUINT32\teg_m_ar;\t/* (attack state)               */\n\tUINT8\teg_sh_ar;\t/* (attack state)               */\n\tUINT8\teg_sel_ar;\t/* (attack state)               */\n\tUINT32\teg_m_dr;\t/* (decay state)                */\n\tUINT8\teg_sh_dr;\t/* (decay state)                */\n\tUINT8\teg_sel_dr;\t/* (decay state)                */\n\tUINT32\teg_m_rr;\t/* (release state)              */\n\tUINT8\teg_sh_rr;\t/* (release state)              */\n\tUINT8\teg_sel_rr;\t/* (release state)              */\n\n\tUINT32\tkey;\t\t/* 0 = KEY OFF, >0 = KEY ON     */\n\n\t/* LFO */\n\tUINT32\tAMmask;\t\t/* LFO Amplitude Modulation enable mask */\n\tUINT8\tvib;\t\t/* LFO Phase Modulation enable flag (active high)*/\n\n\t/* waveform select */\n\tUINT8\twaveform_number;\n\tunsigned int wavetable;\n\n//unsigned char reserved[128-84];//speedup: pump up the struct size to power of 2\nunsigned char reserved[128-100];//speedup: pump up the struct size to power of 2\n\n} OPL3_SLOT;\n\ntypedef struct{\n\tOPL3_SLOT SLOT[2];\n\n\tUINT32\tblock_fnum;\t/* block+fnum                   */\n\tUINT32\tfc;\t\t\t/* Freq. Increment base         */\n\tUINT32\tksl_base;\t/* KeyScaleLevel Base step      */\n\tUINT8\tkcode;\t\t/* key code (for key scaling)   */\n\n\t/*\n       there are 12 2-operator channels which can be combined in pairs\n       to form six 4-operator channel, they are:\n        0 and 3,\n        1 and 4,\n        2 and 5,\n        9 and 12,\n        10 and 13,\n        11 and 14\n    */\n\tUINT8\textended;\t/* set to 1 if this channel forms up a 4op channel with another channel(only used by first of pair of channels, ie 0,1,2 and 9,10,11) */\n\tUINT8\tMuted;\n\nunsigned char reserved[512-272];//speedup:pump up the struct size to power of 2\n\n} OPL3_CH;\n\n/* OPL3 state */\ntypedef struct {\n\tOPL3_CH\tP_CH[18];\t\t\t\t/* OPL3 chips have 18 channels  */\n\n\tUINT32\tpan[18*4];\t\t\t\t/* channels output masks (0xffffffff = enable); 4 masks per one channel */\n\tUINT32\tpan_ctrl_value[18];\t\t/* output control values 1 per one channel (1 value contains 4 masks) */\n\tUINT8\tMuteSpc[5];\t\t\t\t/* for the 5 Rhythm Channels */\n\n\tsigned int chanout[18];\t\t\t/* 18 channels */\n\tsigned int phase_modulation;\t/* phase modulation input (SLOT 2) */\n\tsigned int phase_modulation2;\t/* phase modulation input (SLOT 3 in 4 operator channels) */\n\n\tUINT32\teg_cnt;\t\t\t\t\t/* global envelope generator counter    */\n\tUINT32\teg_timer;\t\t\t\t/* global envelope generator counter works at frequency = chipclock/288 (288=8*36) */\n\tUINT32\teg_timer_add;\t\t\t/* step of eg_timer                     */\n\tUINT32\teg_timer_overflow;\t\t/* envelope generator timer overlfows every 1 sample (on real chip) */\n\n\tUINT32\tfn_tab[1024];\t\t\t/* fnumber->increment counter   */\n\n\t/* LFO */\n\tUINT32\tLFO_AM;\n\tINT32\tLFO_PM;\n\tUINT8\tlfo_am_depth;\n\tUINT8\tlfo_pm_depth_range;\n\tUINT32\tlfo_am_cnt;\n\tUINT32\tlfo_am_inc;\n\tUINT32\tlfo_pm_cnt;\n\tUINT32\tlfo_pm_inc;\n\n\tUINT32\tnoise_rng;\t\t\t\t/* 23 bit noise shift register  */\n\tUINT32\tnoise_p;\t\t\t\t/* current noise 'phase'        */\n\tUINT32\tnoise_f;\t\t\t\t/* current noise period         */\n\n\tUINT8\tOPL3_mode;\t\t\t\t/* OPL3 extension enable flag   */\n\n\tUINT8\trhythm;\t\t\t\t\t/* Rhythm mode                  */\n\n\tint\t\tT[2];\t\t\t\t\t/* timer counters               */\n\tUINT8\tst[2];\t\t\t\t\t/* timer enable                 */\n\n\tUINT32\taddress;\t\t\t\t/* address register             */\n\tUINT8\tstatus;\t\t\t\t\t/* status flag                  */\n\tUINT8\tstatusmask;\t\t\t\t/* status mask                  */\n\n\tUINT8\tnts;\t\t\t\t\t/* NTS (note select)            */\n\n\t/* external event callback handlers */\n\tOPL3_TIMERHANDLER  timer_handler;/* TIMER handler                */\n\tvoid *TimerParam;\t\t\t\t\t/* TIMER parameter              */\n\tOPL3_IRQHANDLER    IRQHandler;\t/* IRQ handler                  */\n\tvoid *IRQParam;\t\t\t\t\t/* IRQ parameter                */\n\tOPL3_UPDATEHANDLER UpdateHandler;/* stream update handler       */\n\tvoid *UpdateParam;\t\t\t\t/* stream update parameter      */\n\n\tUINT8 type;\t\t\t\t\t\t/* chip type                    */\n\tint clock;\t\t\t\t\t\t/* master clock  (Hz)           */\n\tint rate;\t\t\t\t\t\t/* sampling rate (Hz)           */\n\tdouble freqbase;\t\t\t\t/* frequency base               */\n\t//attotime TimerBase;\t\t\t/* Timer base time (==sampling time)*/\n} OPL3;\n\n\n\n/* mapping of register number (offset) to slot number used by the emulator */\nstatic const int slot_array[32]=\n{\n\t 0, 2, 4, 1, 3, 5,-1,-1,\n\t 6, 8,10, 7, 9,11,-1,-1,\n\t12,14,16,13,15,17,-1,-1,\n\t-1,-1,-1,-1,-1,-1,-1,-1\n};\n\n/* key scale level */\n/* table is 3dB/octave , DV converts this into 6dB/octave */\n/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */\n#define DV (0.1875/2.0)\nstatic const UINT32 ksl_tab[8*16]=\n{\n\t/* OCT 0 */\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t/* OCT 1 */\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,\n\t 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,\n\t/* OCT 2 */\n\t 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,\n\t 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,\n\t 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,\n\t 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,\n\t/* OCT 3 */\n\t 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,\n\t 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,\n\t 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,\n\t 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,\n\t/* OCT 4 */\n\t 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,\n\t 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,\n\t 9.000/DV, 9.750/DV,10.125/DV,10.500/DV,\n\t10.875/DV,11.250/DV,11.625/DV,12.000/DV,\n\t/* OCT 5 */\n\t 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,\n\t 9.000/DV,10.125/DV,10.875/DV,11.625/DV,\n\t12.000/DV,12.750/DV,13.125/DV,13.500/DV,\n\t13.875/DV,14.250/DV,14.625/DV,15.000/DV,\n\t/* OCT 6 */\n\t 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,\n\t12.000/DV,13.125/DV,13.875/DV,14.625/DV,\n\t15.000/DV,15.750/DV,16.125/DV,16.500/DV,\n\t16.875/DV,17.250/DV,17.625/DV,18.000/DV,\n\t/* OCT 7 */\n\t 0.000/DV, 9.000/DV,12.000/DV,13.875/DV,\n\t15.000/DV,16.125/DV,16.875/DV,17.625/DV,\n\t18.000/DV,18.750/DV,19.125/DV,19.500/DV,\n\t19.875/DV,20.250/DV,20.625/DV,21.000/DV\n};\n#undef DV\n\n/* 0 / 3.0 / 1.5 / 6.0 dB/OCT */\nstatic const UINT32 ksl_shift[4] = { 31, 1, 2, 0 };\n\n\n/* sustain level table (3dB per step) */\n/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/\n#define SC(db) (UINT32) ( db * (2.0/ENV_STEP) )\nstatic const UINT32 sl_tab[16]={\n SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),\n SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)\n};\n#undef SC\n\n\n#define RATE_STEPS (8)\nstatic const unsigned char eg_inc[15*RATE_STEPS]={\n\n/*cycle:0 1  2 3  4 5  6 7*/\n\n/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */\n/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */\n/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */\n/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */\n\n/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */\n/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */\n/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */\n/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */\n\n/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */\n/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */\n/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */\n/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */\n\n/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 for decay */\n/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 for attack (zero time) */\n/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */\n};\n\n\n#define O(a) (a*RATE_STEPS)\n\n/* note that there is no O(13) in this table - it's directly in the code */\nstatic const unsigned char eg_rate_select[16+64+16]={\t/* Envelope Generator rates (16 + 64 rates + 16 RKS) */\n/* 16 infinite time rates */\nO(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),\nO(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),\n\n/* rates 00-12 */\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\nO( 0),O( 1),O( 2),O( 3),\n\n/* rate 13 */\nO( 4),O( 5),O( 6),O( 7),\n\n/* rate 14 */\nO( 8),O( 9),O(10),O(11),\n\n/* rate 15 */\nO(12),O(12),O(12),O(12),\n\n/* 16 dummy rates (same as 15 3) */\nO(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),\nO(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),\n\n};\n#undef O\n\n/*rate  0,    1,    2,    3,   4,   5,   6,  7,  8,  9,  10, 11, 12, 13, 14, 15 */\n/*shift 12,   11,   10,   9,   8,   7,   6,  5,  4,  3,  2,  1,  0,  0,  0,  0  */\n/*mask  4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3,  1,  0,  0,  0,  0  */\n\n#define O(a) (a*1)\nstatic const unsigned char eg_rate_shift[16+64+16]={\t/* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */\n/* 16 infinite time rates */\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\nO(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),\n\n/* rates 00-12 */\nO(12),O(12),O(12),O(12),\nO(11),O(11),O(11),O(11),\nO(10),O(10),O(10),O(10),\nO( 9),O( 9),O( 9),O( 9),\nO( 8),O( 8),O( 8),O( 8),\nO( 7),O( 7),O( 7),O( 7),\nO( 6),O( 6),O( 6),O( 6),\nO( 5),O( 5),O( 5),O( 5),\nO( 4),O( 4),O( 4),O( 4),\nO( 3),O( 3),O( 3),O( 3),\nO( 2),O( 2),O( 2),O( 2),\nO( 1),O( 1),O( 1),O( 1),\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 13 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 14 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* rate 15 */\nO( 0),O( 0),O( 0),O( 0),\n\n/* 16 dummy rates (same as 15 3) */\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\nO( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),\n\n};\n#undef O\n\n\n/* multiple table */\n#define ML 2\nstatic const UINT8 mul_tab[16]= {\n/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */\n   0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,\n   8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML\n};\n#undef ML\n\n/*  TL_TAB_LEN is calculated as:\n\n*   (12+1)=13 - sinus amplitude bits     (Y axis)\n*   additional 1: to compensate for calculations of negative part of waveform\n*   (if we don't add it then the greatest possible _negative_ value would be -2\n*   and we really need -1 for waveform #7)\n*   2  - sinus sign bit           (Y axis)\n*   TL_RES_LEN - sinus resolution (X axis)\n*/\n#define TL_TAB_LEN (13*2*TL_RES_LEN)\nstatic signed int tl_tab[TL_TAB_LEN];\n\n#define ENV_QUIET\t\t(TL_TAB_LEN>>4)\n\n/* sin waveform table in 'decibel' scale */\n/* there are eight waveforms on OPL3 chips */\nstatic unsigned int sin_tab[SIN_LEN * 8];\n\n\n/* LFO Amplitude Modulation table (verified on real YM3812)\n   27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples\n\n   Length: 210 elements.\n\n    Each of the elements has to be repeated\n    exactly 64 times (on 64 consecutive samples).\n    The whole table takes: 64 * 210 = 13440 samples.\n\n    When AM = 1 data is used directly\n    When AM = 0 data is divided by 4 before being used (losing precision is important)\n*/\n\n#define LFO_AM_TAB_ELEMENTS 210\n\nstatic const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = {\n0,0,0,0,0,0,0,\n1,1,1,1,\n2,2,2,2,\n3,3,3,3,\n4,4,4,4,\n5,5,5,5,\n6,6,6,6,\n7,7,7,7,\n8,8,8,8,\n9,9,9,9,\n10,10,10,10,\n11,11,11,11,\n12,12,12,12,\n13,13,13,13,\n14,14,14,14,\n15,15,15,15,\n16,16,16,16,\n17,17,17,17,\n18,18,18,18,\n19,19,19,19,\n20,20,20,20,\n21,21,21,21,\n22,22,22,22,\n23,23,23,23,\n24,24,24,24,\n25,25,25,25,\n26,26,26,\n25,25,25,25,\n24,24,24,24,\n23,23,23,23,\n22,22,22,22,\n21,21,21,21,\n20,20,20,20,\n19,19,19,19,\n18,18,18,18,\n17,17,17,17,\n16,16,16,16,\n15,15,15,15,\n14,14,14,14,\n13,13,13,13,\n12,12,12,12,\n11,11,11,11,\n10,10,10,10,\n9,9,9,9,\n8,8,8,8,\n7,7,7,7,\n6,6,6,6,\n5,5,5,5,\n4,4,4,4,\n3,3,3,3,\n2,2,2,2,\n1,1,1,1\n};\n\n/* LFO Phase Modulation table (verified on real YM3812) */\nstatic const INT8 lfo_pm_table[8*8*2] = {\n\n/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */\n0, 0, 0, 0, 0, 0, 0, 0,\t/*LFO PM depth = 0*/\n0, 0, 0, 0, 0, 0, 0, 0,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */\n0, 0, 0, 0, 0, 0, 0, 0,\t/*LFO PM depth = 0*/\n1, 0, 0, 0,-1, 0, 0, 0,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */\n1, 0, 0, 0,-1, 0, 0, 0,\t/*LFO PM depth = 0*/\n2, 1, 0,-1,-2,-1, 0, 1,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */\n1, 0, 0, 0,-1, 0, 0, 0,\t/*LFO PM depth = 0*/\n3, 1, 0,-1,-3,-1, 0, 1,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */\n2, 1, 0,-1,-2,-1, 0, 1,\t/*LFO PM depth = 0*/\n4, 2, 0,-2,-4,-2, 0, 2,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */\n2, 1, 0,-1,-2,-1, 0, 1,\t/*LFO PM depth = 0*/\n5, 2, 0,-2,-5,-2, 0, 2,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */\n3, 1, 0,-1,-3,-1, 0, 1,\t/*LFO PM depth = 0*/\n6, 3, 0,-3,-6,-3, 0, 3,\t/*LFO PM depth = 1*/\n\n/* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */\n3, 1, 0,-1,-3,-1, 0, 1,\t/*LFO PM depth = 0*/\n7, 3, 0,-3,-7,-3, 0, 3\t/*LFO PM depth = 1*/\n};\n\n\n/* lock level of common table */\nstatic int num_lock = 0;\n\n/* work table */\n#define SLOT7_1 (&chip->P_CH[7].SLOT[SLOT1])\n#define SLOT7_2 (&chip->P_CH[7].SLOT[SLOT2])\n#define SLOT8_1 (&chip->P_CH[8].SLOT[SLOT1])\n#define SLOT8_2 (&chip->P_CH[8].SLOT[SLOT2])\n\n\n\n/*INLINE int limit( int val, int max, int min ) {\n\tif ( val > max )\n\t\tval = max;\n\telse if ( val < min )\n\t\tval = min;\n\n\treturn val;\n}*/\n\n\n/* status set and IRQ handling */\nINLINE void OPL3_STATUS_SET(OPL3 *chip,int flag)\n{\n\t/* set status flag masking out disabled IRQs */\n\tchip->status |= (flag & chip->statusmask);\n\tif(!(chip->status & 0x80))\n\t{\n\t\tif(chip->status & 0x7f)\n\t\t{\t/* IRQ on */\n\t\t\tchip->status |= 0x80;\n\t\t\t/* callback user interrupt handler (IRQ is OFF to ON) */\n\t\t\tif(chip->IRQHandler) (chip->IRQHandler)(chip->IRQParam,1);\n\t\t}\n\t}\n}\n\n/* status reset and IRQ handling */\nINLINE void OPL3_STATUS_RESET(OPL3 *chip,int flag)\n{\n\t/* reset status flag */\n\tchip->status &= ~flag;\n\tif(chip->status & 0x80)\n\t{\n\t\tif (!(chip->status & 0x7f))\n\t\t{\n\t\t\tchip->status &= 0x7f;\n\t\t\t/* callback user interrupt handler (IRQ is ON to OFF) */\n\t\t\tif(chip->IRQHandler) (chip->IRQHandler)(chip->IRQParam,0);\n\t\t}\n\t}\n}\n\n/* IRQ mask set */\nINLINE void OPL3_STATUSMASK_SET(OPL3 *chip,int flag)\n{\n\tchip->statusmask = flag;\n\t/* IRQ handling check */\n\tOPL3_STATUS_SET(chip,0);\n\tOPL3_STATUS_RESET(chip,0);\n}\n\n\n/* advance LFO to next sample */\nINLINE void advance_lfo(OPL3 *chip)\n{\n\tUINT8 tmp;\n\n\t/* LFO */\n\tchip->lfo_am_cnt += chip->lfo_am_inc;\n\tif (chip->lfo_am_cnt >= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH) )\t/* lfo_am_table is 210 elements long */\n\t\tchip->lfo_am_cnt -= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH);\n\n\ttmp = lfo_am_table[ chip->lfo_am_cnt >> LFO_SH ];\n\n\tif (chip->lfo_am_depth)\n\t\tchip->LFO_AM = tmp;\n\telse\n\t\tchip->LFO_AM = tmp>>2;\n\n\tchip->lfo_pm_cnt += chip->lfo_pm_inc;\n\tchip->LFO_PM = ((chip->lfo_pm_cnt>>LFO_SH) & 7) | chip->lfo_pm_depth_range;\n}\n\n/* advance to next sample */\nINLINE void advance(OPL3 *chip)\n{\n\tOPL3_CH *CH;\n\tOPL3_SLOT *op;\n\tint i;\n\n\tchip->eg_timer += chip->eg_timer_add;\n\n\twhile (chip->eg_timer >= chip->eg_timer_overflow)\n\t{\n\t\tchip->eg_timer -= chip->eg_timer_overflow;\n\n\t\tchip->eg_cnt++;\n\n\t\tfor (i=0; i<9*2*2; i++)\n\t\t{\n\t\t\tCH  = &chip->P_CH[i/2];\n\t\t\top  = &CH->SLOT[i&1];\n#if 1\n\t\t\t/* Envelope Generator */\n\t\t\tswitch(op->state)\n\t\t\t{\n\t\t\tcase EG_ATT:\t/* attack phase */\n//              if ( !(chip->eg_cnt & ((1<<op->eg_sh_ar)-1) ) )\n\t\t\t\tif ( !(chip->eg_cnt & op->eg_m_ar) )\n\t\t\t\t{\n\t\t\t\t\top->volume += (~op->volume *\n\t\t\t\t\t\t\t   (eg_inc[op->eg_sel_ar + ((chip->eg_cnt>>op->eg_sh_ar)&7)])\n\t\t\t\t\t\t\t  ) >>3;\n\n\t\t\t\t\tif (op->volume <= MIN_ATT_INDEX)\n\t\t\t\t\t{\n\t\t\t\t\t\top->volume = MIN_ATT_INDEX;\n\t\t\t\t\t\top->state = EG_DEC;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_DEC:\t/* decay phase */\n//              if ( !(chip->eg_cnt & ((1<<op->eg_sh_dr)-1) ) )\n\t\t\t\tif ( !(chip->eg_cnt & op->eg_m_dr) )\n\t\t\t\t{\n\t\t\t\t\top->volume += eg_inc[op->eg_sel_dr + ((chip->eg_cnt>>op->eg_sh_dr)&7)];\n\n\t\t\t\t\tif ( op->volume >= op->sl )\n\t\t\t\t\t\top->state = EG_SUS;\n\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_SUS:\t/* sustain phase */\n\n\t\t\t\t/* this is important behaviour:\n                one can change percusive/non-percussive modes on the fly and\n                the chip will remain in sustain phase - verified on real YM3812 */\n\n\t\t\t\tif(op->eg_type)\t\t/* non-percussive mode */\n\t\t\t\t{\n\t\t\t\t\t\t\t\t\t/* do nothing */\n\t\t\t\t}\n\t\t\t\telse\t\t\t\t/* percussive mode */\n\t\t\t\t{\n\t\t\t\t\t/* during sustain phase chip adds Release Rate (in percussive mode) */\n//                  if ( !(chip->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\n\t\t\t\t\tif ( !(chip->eg_cnt & op->eg_m_rr) )\n\t\t\t\t\t{\n\t\t\t\t\t\top->volume += eg_inc[op->eg_sel_rr + ((chip->eg_cnt>>op->eg_sh_rr)&7)];\n\n\t\t\t\t\t\tif ( op->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t\t}\n\t\t\t\t\t/* else do nothing in sustain phase */\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase EG_REL:\t/* release phase */\n//              if ( !(chip->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )\n\t\t\t\tif ( !(chip->eg_cnt & op->eg_m_rr) )\n\t\t\t\t{\n\t\t\t\t\top->volume += eg_inc[op->eg_sel_rr + ((chip->eg_cnt>>op->eg_sh_rr)&7)];\n\n\t\t\t\t\tif ( op->volume >= MAX_ATT_INDEX )\n\t\t\t\t\t{\n\t\t\t\t\t\top->volume = MAX_ATT_INDEX;\n\t\t\t\t\t\top->state = EG_OFF;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\tbreak;\n\t\t\t}\n#endif\n\t\t}\n\t}\n\n\tfor (i=0; i<9*2*2; i++)\n\t{\n\t\tCH  = &chip->P_CH[i/2];\n\t\top  = &CH->SLOT[i&1];\n\n\t\t/* Phase Generator */\n\t\tif(op->vib)\n\t\t{\n\t\t\tUINT8 block;\n\t\t\tunsigned int block_fnum = CH->block_fnum;\n\n\t\t\tunsigned int fnum_lfo   = (block_fnum&0x0380) >> 7;\n\n\t\t\tsigned int lfo_fn_table_index_offset = lfo_pm_table[chip->LFO_PM + 16*fnum_lfo ];\n\n\t\t\tif (lfo_fn_table_index_offset)\t/* LFO phase modulation active */\n\t\t\t{\n\t\t\t\tblock_fnum += lfo_fn_table_index_offset;\n\t\t\t\tblock = (block_fnum&0x1c00) >> 10;\n\t\t\t\top->Cnt += (chip->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul;\n\t\t\t}\n\t\t\telse\t/* LFO phase modulation  = zero */\n\t\t\t{\n\t\t\t\top->Cnt += op->Incr;\n\t\t\t}\n\t\t}\n\t\telse\t/* LFO phase modulation disabled for this operator */\n\t\t{\n\t\t\top->Cnt += op->Incr;\n\t\t}\n\t}\n\n\t/*  The Noise Generator of the YM3812 is 23-bit shift register.\n    *   Period is equal to 2^23-2 samples.\n    *   Register works at sampling frequency of the chip, so output\n    *   can change on every sample.\n    *\n    *   Output of the register and input to the bit 22 is:\n    *   bit0 XOR bit14 XOR bit15 XOR bit22\n    *\n    *   Simply use bit 22 as the noise output.\n    */\n\n\tchip->noise_p += chip->noise_f;\n\ti = chip->noise_p >> FREQ_SH;\t\t/* number of events (shifts of the shift register) */\n\tchip->noise_p &= FREQ_MASK;\n\twhile (i)\n\t{\n\t\t/*\n        UINT32 j;\n        j = ( (chip->noise_rng) ^ (chip->noise_rng>>14) ^ (chip->noise_rng>>15) ^ (chip->noise_rng>>22) ) & 1;\n        chip->noise_rng = (j<<22) | (chip->noise_rng>>1);\n        */\n\n\t\t/*\n            Instead of doing all the logic operations above, we\n            use a trick here (and use bit 0 as the noise output).\n            The difference is only that the noise bit changes one\n            step ahead. This doesn't matter since we don't know\n            what is real state of the noise_rng after the reset.\n        */\n\n\t\tif (chip->noise_rng & 1) chip->noise_rng ^= 0x800302;\n\t\tchip->noise_rng >>= 1;\n\n\t\ti--;\n\t}\n}\n\n\nINLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)\n{\n\tUINT32 p;\n\n\tp = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ];\n\n\tif (p >= TL_TAB_LEN)\n\t\treturn 0;\n\treturn tl_tab[p];\n}\n\nINLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)\n{\n\tUINT32 p;\n\n\tp = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm))>>FREQ_SH) & SIN_MASK)];\n\n\tif (p >= TL_TAB_LEN)\n\t\treturn 0;\n\treturn tl_tab[p];\n}\n\n\n#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (chip->LFO_AM & (OP)->AMmask))\n\n/* calculate output of a standard 2 operator channel\n (or 1st part of a 4-op channel) */\nINLINE void chan_calc( OPL3 *chip, OPL3_CH *CH )\n{\n\tOPL3_SLOT *SLOT;\n\tunsigned int env;\n\tsigned int out;\n\n\tif (CH->Muted)\n\t\treturn;\n\n\tchip->phase_modulation = 0;\n\tchip->phase_modulation2= 0;\n\n\t/* SLOT 1 */\n\tSLOT = &CH->SLOT[SLOT1];\n\tenv  = volume_calc(SLOT);\n\tout  = SLOT->op1_out[0] + SLOT->op1_out[1];\n\tSLOT->op1_out[0] = SLOT->op1_out[1];\n\tSLOT->op1_out[1] = 0;\n\tif( env < ENV_QUIET )\n\t{\n\t\tif (!SLOT->FB)\n\t\t\tout = 0;\n\t\tSLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );\n\t}\n\t*SLOT->connect += SLOT->op1_out[1];\n//logerror(\"out0=%5i vol0=%4i \", SLOT->op1_out[1], env );\n\n\t/* SLOT 2 */\n\tSLOT++;\n\tenv = volume_calc(SLOT);\n\tif( env < ENV_QUIET )\n\t\t*SLOT->connect += op_calc(SLOT->Cnt, env, chip->phase_modulation, SLOT->wavetable);\n\n//logerror(\"out1=%5i vol1=%4i\\n\", op_calc(SLOT->Cnt, env, chip->phase_modulation, SLOT->wavetable), env );\n\n}\n\n/* calculate output of a 2nd part of 4-op channel */\nINLINE void chan_calc_ext( OPL3 *chip, OPL3_CH *CH )\n{\n\tOPL3_SLOT *SLOT;\n\tunsigned int env;\n\n\tif (CH->Muted)\n\t\treturn;\n\n\tchip->phase_modulation = 0;\n\n\t/* SLOT 1 */\n\tSLOT = &CH->SLOT[SLOT1];\n\tenv  = volume_calc(SLOT);\n\tif( env < ENV_QUIET )\n\t\t*SLOT->connect += op_calc(SLOT->Cnt, env, chip->phase_modulation2, SLOT->wavetable );\n\n\t/* SLOT 2 */\n\tSLOT++;\n\tenv = volume_calc(SLOT);\n\tif( env < ENV_QUIET )\n\t\t*SLOT->connect += op_calc(SLOT->Cnt, env, chip->phase_modulation, SLOT->wavetable);\n\n}\n\n/*\n    operators used in the rhythm sounds generation process:\n\n    Envelope Generator:\n\nchannel  operator  register number   Bass  High  Snare Tom  Top\n/ slot   number    TL ARDR SLRR Wave Drum  Hat   Drum  Tom  Cymbal\n 6 / 0   12        50  70   90   f0  +\n 6 / 1   15        53  73   93   f3  +\n 7 / 0   13        51  71   91   f1        +\n 7 / 1   16        54  74   94   f4              +\n 8 / 0   14        52  72   92   f2                    +\n 8 / 1   17        55  75   95   f5                          +\n\n    Phase Generator:\n\nchannel  operator  register number   Bass  High  Snare Tom  Top\n/ slot   number    MULTIPLE          Drum  Hat   Drum  Tom  Cymbal\n 6 / 0   12        30                +\n 6 / 1   15        33                +\n 7 / 0   13        31                      +     +           +\n 7 / 1   16        34                -----  n o t  u s e d -----\n 8 / 0   14        32                                  +\n 8 / 1   17        35                      +                 +\n\nchannel  operator  register number   Bass  High  Snare Tom  Top\nnumber   number    BLK/FNUM2 FNUM    Drum  Hat   Drum  Tom  Cymbal\n   6     12,15     B6        A6      +\n\n   7     13,16     B7        A7            +     +           +\n\n   8     14,17     B8        A8            +           +     +\n\n*/\n\n/* calculate rhythm */\n\nINLINE void chan_calc_rhythm( OPL3 *chip, OPL3_CH *CH, unsigned int noise )\n{\n\tOPL3_SLOT *SLOT;\n\tsigned int *chanout = chip->chanout;\n\tsigned int out;\n\tunsigned int env;\n\n\n\t/* Bass Drum (verified on real YM3812):\n      - depends on the channel 6 'connect' register:\n          when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out)\n          when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored\n      - output sample always is multiplied by 2\n    */\n\n\tchip->phase_modulation = 0;\n\n\t/* SLOT 1 */\n\tSLOT = &CH[6].SLOT[SLOT1];\n\tenv = volume_calc(SLOT);\n\n\tout = SLOT->op1_out[0] + SLOT->op1_out[1];\n\tSLOT->op1_out[0] = SLOT->op1_out[1];\n\n\tif (!SLOT->CON)\n\t\tchip->phase_modulation = SLOT->op1_out[0];\n\t//else ignore output of operator 1\n\n\tSLOT->op1_out[1] = 0;\n\tif( env < ENV_QUIET )\n\t{\n\t\tif (!SLOT->FB)\n\t\t\tout = 0;\n\t\tSLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );\n\t}\n\n\t/* SLOT 2 */\n\tSLOT++;\n\tenv = volume_calc(SLOT);\n\tif( env < ENV_QUIET && ! chip->MuteSpc[0] )\n\t\tchanout[6] += op_calc(SLOT->Cnt, env, chip->phase_modulation, SLOT->wavetable) * 2;\n\n\n\t/* Phase generation is based on: */\n\t// HH  (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases)\n\t// SD  (16) channel 7->slot 1\n\t// TOM (14) channel 8->slot 1\n\t// TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases)\n\n\t/* Envelope generation based on: */\n\t// HH  channel 7->slot1\n\t// SD  channel 7->slot2\n\t// TOM channel 8->slot1\n\t// TOP channel 8->slot2\n\n\n\t/* The following formulas can be well optimized.\n       I leave them in direct form for now (in case I've missed something).\n    */\n\n\t/* High Hat (verified on real YM3812) */\n\tenv = volume_calc(SLOT7_1);\n\tif( env < ENV_QUIET && ! chip->MuteSpc[4] )\n\t{\n\n\t\t/* high hat phase generation:\n            phase = d0 or 234 (based on frequency only)\n            phase = 34 or 2d0 (based on noise)\n        */\n\n\t\t/* base frequency derived from operator 1 in channel 7 */\n\t\tunsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;\n\t\tunsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;\n\t\tunsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;\n\n\t\tunsigned char res1 = (bit2 ^ bit7) | bit3;\n\n\t\t/* when res1 = 0 phase = 0x000 | 0xd0; */\n\t\t/* when res1 = 1 phase = 0x200 | (0xd0>>2); */\n\t\tUINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;\n\n\t\t/* enable gate based on frequency of operator 2 in channel 8 */\n\t\tunsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;\n\t\tunsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;\n\n\t\tunsigned char res2 = (bit3e ^ bit5e);\n\n\t\t/* when res2 = 0 pass the phase from calculation above (res1); */\n\t\t/* when res2 = 1 phase = 0x200 | (0xd0>>2); */\n\t\tif (res2)\n\t\t\tphase = (0x200|(0xd0>>2));\n\n\n\t\t/* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */\n\t\t/* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */\n\t\tif (phase&0x200)\n\t\t{\n\t\t\tif (noise)\n\t\t\t\tphase = 0x200|0xd0;\n\t\t}\n\t\telse\n\t\t/* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */\n\t\t/* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */\n\t\t{\n\t\t\tif (noise)\n\t\t\t\tphase = 0xd0>>2;\n\t\t}\n\n\t\tchanout[7] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1->wavetable) * 2;\n\t}\n\n\t/* Snare Drum (verified on real YM3812) */\n\tenv = volume_calc(SLOT7_2);\n\tif( env < ENV_QUIET && ! chip->MuteSpc[1] )\n\t{\n\t\t/* base frequency derived from operator 1 in channel 7 */\n\t\tunsigned char bit8 = ((SLOT7_1->Cnt>>FREQ_SH)>>8)&1;\n\n\t\t/* when bit8 = 0 phase = 0x100; */\n\t\t/* when bit8 = 1 phase = 0x200; */\n\t\tUINT32 phase = bit8 ? 0x200 : 0x100;\n\n\t\t/* Noise bit XOR'es phase by 0x100 */\n\t\t/* when noisebit = 0 pass the phase from calculation above */\n\t\t/* when noisebit = 1 phase ^= 0x100; */\n\t\t/* in other words: phase ^= (noisebit<<8); */\n\t\tif (noise)\n\t\t\tphase ^= 0x100;\n\n\t\tchanout[7] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2->wavetable) * 2;\n\t}\n\n\t/* Tom Tom (verified on real YM3812) */\n\tenv = volume_calc(SLOT8_1);\n\tif( env < ENV_QUIET && ! chip->MuteSpc[2] )\n\t\tchanout[8] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2;\n\n\t/* Top Cymbal (verified on real YM3812) */\n\tenv = volume_calc(SLOT8_2);\n\tif( env < ENV_QUIET && ! chip->MuteSpc[3] )\n\t{\n\t\t/* base frequency derived from operator 1 in channel 7 */\n\t\tunsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;\n\t\tunsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;\n\t\tunsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;\n\n\t\tunsigned char res1 = (bit2 ^ bit7) | bit3;\n\n\t\t/* when res1 = 0 phase = 0x000 | 0x100; */\n\t\t/* when res1 = 1 phase = 0x200 | 0x100; */\n\t\tUINT32 phase = res1 ? 0x300 : 0x100;\n\n\t\t/* enable gate based on frequency of operator 2 in channel 8 */\n\t\tunsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;\n\t\tunsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;\n\n\t\tunsigned char res2 = (bit3e ^ bit5e);\n\t\t/* when res2 = 0 pass the phase from calculation above (res1); */\n\t\t/* when res2 = 1 phase = 0x200 | 0x100; */\n\t\tif (res2)\n\t\t\tphase = 0x300;\n\n\t\tchanout[8] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2->wavetable) * 2;\n\t}\n\n}\n\n\n/* generic table initialize */\nstatic int init_tables(void)\n{\n\tsigned int i,x;\n\tsigned int n;\n\tdouble o,m;\n\n\n\tfor (x=0; x<TL_RES_LEN; x++)\n\t{\n\t\tm = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);\n\t\tm = floor(m);\n\n\t\t/* we never reach (1<<16) here due to the (x+1) */\n\t\t/* result fits within 16 bits at maximum */\n\n\t\tn = (int)m;\t\t/* 16 bits here */\n\t\tn >>= 4;\t\t/* 12 bits here */\n\t\tif (n&1)\t\t/* round to nearest */\n\t\t\tn = (n>>1)+1;\n\t\telse\n\t\t\tn = n>>1;\n\t\t\t\t\t\t/* 11 bits here (rounded) */\n\t\tn <<= 1;\t\t/* 12 bits here (as in real chip) */\n\t\ttl_tab[ x*2 + 0 ] = n;\n\t\ttl_tab[ x*2 + 1 ] = ~tl_tab[ x*2 + 0 ]; /* this *is* different from OPL2 (verified on real YMF262) */\n\n\t\tfor (i=1; i<13; i++)\n\t\t{\n\t\t\ttl_tab[ x*2+0 + i*2*TL_RES_LEN ] =  tl_tab[ x*2+0 ]>>i;\n\t\t\ttl_tab[ x*2+1 + i*2*TL_RES_LEN ] = ~tl_tab[ x*2+0 + i*2*TL_RES_LEN ];  /* this *is* different from OPL2 (verified on real YMF262) */\n\t\t}\n\t#if 0\n\t\t\tlogerror(\"tl %04i\", x*2);\n\t\t\tfor (i=0; i<13; i++)\n\t\t\t\tlogerror(\", [%02i] %5i\", i*2, tl_tab[ x*2 +0 + i*2*TL_RES_LEN ] ); /* positive */\n\t\t\tlogerror(\"\\n\");\n\n\t\t\tlogerror(\"tl %04i\", x*2);\n\t\t\tfor (i=0; i<13; i++)\n\t\t\t\tlogerror(\", [%02i] %5i\", i*2, tl_tab[ x*2 +1 + i*2*TL_RES_LEN ] ); /* negative */\n\t\t\tlogerror(\"\\n\");\n\t#endif\n\t}\n\n\tfor (i=0; i<SIN_LEN; i++)\n\t{\n\t\t/* non-standard sinus */\n\t\tm = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */\n\n\t\t/* we never reach zero here due to ((i*2)+1) */\n\n\t\tif (m>0.0)\n\t\t\to = 8*log(1.0/m)/log(2.0);\t/* convert to 'decibels' */\n\t\telse\n\t\t\to = 8*log(-1.0/m)/log(2.0);\t/* convert to 'decibels' */\n\n\t\to = o / (ENV_STEP/4);\n\n\t\tn = (int)(2.0*o);\n\t\tif (n&1)\t\t\t\t\t\t/* round to nearest */\n\t\t\tn = (n>>1)+1;\n\t\telse\n\t\t\tn = n>>1;\n\n\t\tsin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );\n\n\t\t/*logerror(\"YMF262.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\\n\", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/\n\t}\n\n\tfor (i=0; i<SIN_LEN; i++)\n\t{\n\t\t/* these 'pictures' represent _two_ cycles */\n\t\t/* waveform 1:  __      __     */\n\t\t/*             /  \\____/  \\____*/\n\t\t/* output only first half of the sinus waveform (positive one) */\n\n\t\tif (i & (1<<(SIN_BITS-1)) )\n\t\t\tsin_tab[1*SIN_LEN+i] = TL_TAB_LEN;\n\t\telse\n\t\t\tsin_tab[1*SIN_LEN+i] = sin_tab[i];\n\n\t\t/* waveform 2:  __  __  __  __ */\n\t\t/*             /  \\/  \\/  \\/  \\*/\n\t\t/* abs(sin) */\n\n\t\tsin_tab[2*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>1) ];\n\n\t\t/* waveform 3:  _   _   _   _  */\n\t\t/*             / |_/ |_/ |_/ |_*/\n\t\t/* abs(output only first quarter of the sinus waveform) */\n\n\t\tif (i & (1<<(SIN_BITS-2)) )\n\t\t\tsin_tab[3*SIN_LEN+i] = TL_TAB_LEN;\n\t\telse\n\t\t\tsin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)];\n\n\t\t/* waveform 4:                 */\n\t\t/*             /\\  ____/\\  ____*/\n\t\t/*               \\/      \\/    */\n\t\t/* output whole sinus waveform in half the cycle(step=2) and output 0 on the other half of cycle */\n\n\t\tif (i & (1<<(SIN_BITS-1)) )\n\t\t\tsin_tab[4*SIN_LEN+i] = TL_TAB_LEN;\n\t\telse\n\t\t\tsin_tab[4*SIN_LEN+i] = sin_tab[i*2];\n\n\t\t/* waveform 5:                 */\n\t\t/*             /\\/\\____/\\/\\____*/\n\t\t/*                             */\n\t\t/* output abs(whole sinus) waveform in half the cycle(step=2) and output 0 on the other half of cycle */\n\n\t\tif (i & (1<<(SIN_BITS-1)) )\n\t\t\tsin_tab[5*SIN_LEN+i] = TL_TAB_LEN;\n\t\telse\n\t\t\tsin_tab[5*SIN_LEN+i] = sin_tab[(i*2) & (SIN_MASK>>1) ];\n\n\t\t/* waveform 6: ____    ____    */\n\t\t/*                             */\n\t\t/*                 ____    ____*/\n\t\t/* output maximum in half the cycle and output minimum on the other half of cycle */\n\n\t\tif (i & (1<<(SIN_BITS-1)) )\n\t\t\tsin_tab[6*SIN_LEN+i] = 1;\t/* negative */\n\t\telse\n\t\t\tsin_tab[6*SIN_LEN+i] = 0;\t/* positive */\n\n\t\t/* waveform 7:                 */\n\t\t/*             |\\____  |\\____  */\n\t\t/*                   \\|      \\|*/\n\t\t/* output sawtooth waveform    */\n\n\t\tif (i & (1<<(SIN_BITS-1)) )\n\t\t\tx = ((SIN_LEN-1)-i)*16 + 1;\t/* negative: from 8177 to 1 */\n\t\telse\n\t\t\tx = i*16;\t/*positive: from 0 to 8176 */\n\n\t\tif (x > TL_TAB_LEN)\n\t\t\tx = TL_TAB_LEN;\t/* clip to the allowed range */\n\n\t\tsin_tab[7*SIN_LEN+i] = x;\n\n\t\t//logerror(\"YMF262.C: sin1[%4i]= %4i (tl_tab value=%5i)\\n\", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] );\n\t\t//logerror(\"YMF262.C: sin2[%4i]= %4i (tl_tab value=%5i)\\n\", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] );\n\t\t//logerror(\"YMF262.C: sin3[%4i]= %4i (tl_tab value=%5i)\\n\", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] );\n\t\t//logerror(\"YMF262.C: sin4[%4i]= %4i (tl_tab value=%5i)\\n\", i, sin_tab[4*SIN_LEN+i], tl_tab[sin_tab[4*SIN_LEN+i]] );\n\t\t//logerror(\"YMF262.C: sin5[%4i]= %4i (tl_tab value=%5i)\\n\", i, sin_tab[5*SIN_LEN+i], tl_tab[sin_tab[5*SIN_LEN+i]] );\n\t\t//logerror(\"YMF262.C: sin6[%4i]= %4i (tl_tab value=%5i)\\n\", i, sin_tab[6*SIN_LEN+i], tl_tab[sin_tab[6*SIN_LEN+i]] );\n\t\t//logerror(\"YMF262.C: sin7[%4i]= %4i (tl_tab value=%5i)\\n\", i, sin_tab[7*SIN_LEN+i], tl_tab[sin_tab[7*SIN_LEN+i]] );\n\t}\n\t/*logerror(\"YMF262.C: ENV_QUIET= %08x (dec*8=%i)\\n\", ENV_QUIET, ENV_QUIET*8 );*/\n\n#ifdef SAVE_SAMPLE\n\tsample[0]=fopen(\"sampsum.pcm\",\"wb\");\n#endif\n\n\treturn 1;\n}\n\nstatic void OPLCloseTable( void )\n{\n#ifdef SAVE_SAMPLE\n\tfclose(sample[0]);\n#endif\n}\n\n\n\nstatic void OPL3_initalize(OPL3 *chip)\n{\n\tint i;\n\n\t/* frequency base */\n\tchip->freqbase  = (chip->rate) ? ((double)chip->clock / (8.0*36)) / chip->rate  : 0;\n#if 0\n\tchip->rate = (double)chip->clock / (8.0*36);\n\tchip->freqbase  = 1.0;\n#endif\n\n\t/* logerror(\"YMF262: freqbase=%f\\n\", chip->freqbase); */\n\n\t/* Timer base time */\n\t//chip->TimerBase = attotime_mul(ATTOTIME_IN_HZ(chip->clock), 8*36);\n\n\t/* make fnumber -> increment counter table */\n\tfor( i=0 ; i < 1024 ; i++ )\n\t{\n\t\t/* opn phase increment counter = 20bit */\n\t\tchip->fn_tab[i] = (UINT32)( (double)i * 64 * chip->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */\n#if 0\n\t\tlogerror(\"YMF262.C: fn_tab[%4i] = %08x (dec=%8i)\\n\",\n\t\t\t\t i, chip->fn_tab[i]>>6, chip->fn_tab[i]>>6 );\n#endif\n\t}\n\n#if 0\n\tfor( i=0 ; i < 16 ; i++ )\n\t{\n\t\tlogerror(\"YMF262.C: sl_tab[%i] = %08x\\n\",\n\t\t\ti, sl_tab[i] );\n\t}\n\tfor( i=0 ; i < 8 ; i++ )\n\t{\n\t\tint j;\n\t\tlogerror(\"YMF262.C: ksl_tab[oct=%2i] =\",i);\n\t\tfor (j=0; j<16; j++)\n\t\t{\n\t\t\tlogerror(\"%08x \", ksl_tab[i*16+j] );\n\t\t}\n\t\tlogerror(\"\\n\");\n\t}\n#endif\n\n\n\t/* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */\n\t/* One entry from LFO_AM_TABLE lasts for 64 samples */\n\tchip->lfo_am_inc = (1.0 / 64.0 ) * (1<<LFO_SH) * chip->freqbase;\n\n\t/* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */\n\tchip->lfo_pm_inc = (1.0 / 1024.0) * (1<<LFO_SH) * chip->freqbase;\n\n\t/*logerror (\"chip->lfo_am_inc = %8x ; chip->lfo_pm_inc = %8x\\n\", chip->lfo_am_inc, chip->lfo_pm_inc);*/\n\n\t/* Noise generator: a step takes 1 sample */\n\tchip->noise_f = (1.0 / 1.0) * (1<<FREQ_SH) * chip->freqbase;\n\n\tchip->eg_timer_add  = (1<<EG_SH)  * chip->freqbase;\n\tchip->eg_timer_overflow = ( 1 ) * (1<<EG_SH);\n\t/*logerror(\"YMF262init eg_timer_add=%8x eg_timer_overflow=%8x\\n\", chip->eg_timer_add, chip->eg_timer_overflow);*/\n\n}\n\nINLINE void FM_KEYON(OPL3_SLOT *SLOT, UINT32 key_set)\n{\n\tif( !SLOT->key )\n\t{\n\t\t/* restart Phase Generator */\n\t\tSLOT->Cnt = 0;\n\t\t/* phase -> Attack */\n\t\tSLOT->state = EG_ATT;\n\t}\n\tSLOT->key |= key_set;\n}\n\nINLINE void FM_KEYOFF(OPL3_SLOT *SLOT, UINT32 key_clr)\n{\n\tif( SLOT->key )\n\t{\n\t\tSLOT->key &= key_clr;\n\n\t\tif( !SLOT->key )\n\t\t{\n\t\t\t/* phase -> Release */\n\t\t\tif (SLOT->state>EG_REL)\n\t\t\t\tSLOT->state = EG_REL;\n\t\t}\n\t}\n}\n\n/* update phase increment counter of operator (also update the EG rates if necessary) */\nINLINE void CALC_FCSLOT(OPL3_CH *CH,OPL3_SLOT *SLOT)\n{\n\tint ksr;\n\n\t/* (frequency) phase increment counter */\n\tSLOT->Incr = CH->fc * SLOT->mul;\n\tksr = CH->kcode >> SLOT->KSR;\n\n\tif( SLOT->ksr != ksr )\n\t{\n\t\tSLOT->ksr = ksr;\n\n\t\t/* calculate envelope generator rates */\n\t\tif ((SLOT->ar + SLOT->ksr) < 16+60)\n\t\t{\n\t\t\tSLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];\n\t\t\tSLOT->eg_m_ar   = (1<<SLOT->eg_sh_ar)-1;\n\t\t\tSLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSLOT->eg_sh_ar  = 0;\n\t\t\tSLOT->eg_m_ar   = (1<<SLOT->eg_sh_ar)-1;\n\t\t\tSLOT->eg_sel_ar = 13*RATE_STEPS;\n\t\t}\n\t\tSLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];\n\t\tSLOT->eg_m_dr   = (1<<SLOT->eg_sh_dr)-1;\n\t\tSLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];\n\t\tSLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];\n\t\tSLOT->eg_m_rr   = (1<<SLOT->eg_sh_rr)-1;\n\t\tSLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];\n\t}\n}\n\n/* set multi,am,vib,EG-TYP,KSR,mul */\nINLINE void set_mul(OPL3 *chip,int slot,int v)\n{\n\tOPL3_CH   *CH   = &chip->P_CH[slot/2];\n\tOPL3_SLOT *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->mul     = mul_tab[v&0x0f];\n\tSLOT->KSR     = (v&0x10) ? 0 : 2;\n\tSLOT->eg_type = (v&0x20);\n\tSLOT->vib     = (v&0x40);\n\tSLOT->AMmask  = (v&0x80) ? ~0 : 0;\n\n\tif (chip->OPL3_mode & 1)\n\t{\n\t\tint chan_no = slot/2;\n\n\t\t/* in OPL3 mode */\n\t\t//DO THIS:\n\t\t//if this is one of the slots of 1st channel forming up a 4-op channel\n\t\t//do normal operation\n\t\t//else normal 2 operator function\n\t\t//OR THIS:\n\t\t//if this is one of the slots of 2nd channel forming up a 4-op channel\n\t\t//update it using channel data of 1st channel of a pair\n\t\t//else normal 2 operator function\n\t\tswitch(chan_no)\n\t\t{\n\t\tcase 0: case 1: case 2:\n\t\tcase 9: case 10: case 11:\n\t\t\tif (CH->extended)\n\t\t\t{\n\t\t\t\t/* normal */\n\t\t\t\tCALC_FCSLOT(CH,SLOT);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* normal */\n\t\t\t\tCALC_FCSLOT(CH,SLOT);\n\t\t\t}\n\t\tbreak;\n\t\tcase 3: case 4: case 5:\n\t\tcase 12: case 13: case 14:\n\t\t\tif ((CH-3)->extended)\n\t\t\t{\n\t\t\t\t/* update this SLOT using frequency data for 1st channel of a pair */\n\t\t\t\tCALC_FCSLOT(CH-3,SLOT);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* normal */\n\t\t\t\tCALC_FCSLOT(CH,SLOT);\n\t\t\t}\n\t\tbreak;\n\t\tdefault:\n\t\t\t\t/* normal */\n\t\t\t\tCALC_FCSLOT(CH,SLOT);\n\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\t/* in OPL2 mode */\n\t\tCALC_FCSLOT(CH,SLOT);\n\t}\n}\n\n/* set ksl & tl */\nINLINE void set_ksl_tl(OPL3 *chip,int slot,int v)\n{\n\tOPL3_CH   *CH   = &chip->P_CH[slot/2];\n\tOPL3_SLOT *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->ksl = ksl_shift[v >> 6];\n\tSLOT->TL  = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */\n\n\tif (chip->OPL3_mode & 1)\n\t{\n\t\tint chan_no = slot/2;\n\n\t\t/* in OPL3 mode */\n\t\t//DO THIS:\n\t\t//if this is one of the slots of 1st channel forming up a 4-op channel\n\t\t//do normal operation\n\t\t//else normal 2 operator function\n\t\t//OR THIS:\n\t\t//if this is one of the slots of 2nd channel forming up a 4-op channel\n\t\t//update it using channel data of 1st channel of a pair\n\t\t//else normal 2 operator function\n\t\tswitch(chan_no)\n\t\t{\n\t\tcase 0: case 1: case 2:\n\t\tcase 9: case 10: case 11:\n\t\t\tif (CH->extended)\n\t\t\t{\n\t\t\t\t/* normal */\n\t\t\t\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* normal */\n\t\t\t\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n\t\t\t}\n\t\tbreak;\n\t\tcase 3: case 4: case 5:\n\t\tcase 12: case 13: case 14:\n\t\t\tif ((CH-3)->extended)\n\t\t\t{\n\t\t\t\t/* update this SLOT using frequency data for 1st channel of a pair */\n\t\t\t\tSLOT->TLL = SLOT->TL + ((CH-3)->ksl_base>>SLOT->ksl);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* normal */\n\t\t\t\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n\t\t\t}\n\t\tbreak;\n\t\tdefault:\n\t\t\t\t/* normal */\n\t\t\t\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\t/* in OPL2 mode */\n\t\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n\t}\n\n}\n\n/* set attack rate & decay rate  */\nINLINE void set_ar_dr(OPL3 *chip,int slot,int v)\n{\n\tOPL3_CH   *CH   = &chip->P_CH[slot/2];\n\tOPL3_SLOT *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->ar = (v>>4)  ? 16 + ((v>>4)  <<2) : 0;\n\n\tif ((SLOT->ar + SLOT->ksr) < 16+60) /* verified on real YMF262 - all 15 x rates take \"zero\" time */\n\t{\n\t\tSLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];\n\t\tSLOT->eg_m_ar   = (1<<SLOT->eg_sh_ar)-1;\n\t\tSLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];\n\t}\n\telse\n\t{\n\t\tSLOT->eg_sh_ar  = 0;\n\t\tSLOT->eg_m_ar   = (1<<SLOT->eg_sh_ar)-1;\n\t\tSLOT->eg_sel_ar = 13*RATE_STEPS;\n\t}\n\n\tSLOT->dr    = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;\n\tSLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];\n\tSLOT->eg_m_dr   = (1<<SLOT->eg_sh_dr)-1;\n\tSLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];\n}\n\n/* set sustain level & release rate */\nINLINE void set_sl_rr(OPL3 *chip,int slot,int v)\n{\n\tOPL3_CH   *CH   = &chip->P_CH[slot/2];\n\tOPL3_SLOT *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->sl  = sl_tab[ v>>4 ];\n\n\tSLOT->rr  = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;\n\tSLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];\n\tSLOT->eg_m_rr   = (1<<SLOT->eg_sh_rr)-1;\n\tSLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];\n}\n\n\nstatic void update_channels(OPL3 *chip, OPL3_CH *CH)\n{\n\t/* update channel passed as a parameter and a channel at CH+=3; */\n\tif (CH->extended)\n\t{\t/* we've just switched to combined 4 operator mode */\n\n\t}\n\telse\n\t{\t/* we've just switched to normal 2 operator mode */\n\n\t}\n\n}\n\n/* write a value v to register r on OPL chip */\nstatic void OPL3WriteReg(OPL3 *chip, int r, int v)\n{\n\tOPL3_CH *CH;\n\tsigned int *chanout = chip->chanout;\n\tunsigned int ch_offset = 0;\n\tint slot;\n\tint block_fnum;\n\n\n\n\t/*if (LOG_CYM_FILE && (cymfile) && ((r&255)!=0) && (r!=255) )\n\t{\n\t\tif (r>0xff)\n\t\t\tfputc( (unsigned char)0xff, cymfile );//mark writes to second register set\n\n\t\tfputc( (unsigned char)r&0xff, cymfile );\n\t\tfputc( (unsigned char)v, cymfile );\n\t}*/\n\n\tif(r&0x100)\n\t{\n\t\tswitch(r)\n\t\t{\n\t\tcase 0x101:\t/* test register */\n\t\t\treturn;\n\n\t\tcase 0x104:\t/* 6 channels enable */\n\t\t\t{\n\t\t\t\tUINT8 prev;\n\n\t\t\t\tCH = &chip->P_CH[0];\t/* channel 0 */\n\t\t\t\tprev = CH->extended;\n\t\t\t\tCH->extended = (v>>0) & 1;\n\t\t\t\tif(prev != CH->extended)\n\t\t\t\t\tupdate_channels(chip, CH);\n\t\t\t\tCH++;\t\t\t\t\t/* channel 1 */\n\t\t\t\tprev = CH->extended;\n\t\t\t\tCH->extended = (v>>1) & 1;\n\t\t\t\tif(prev != CH->extended)\n\t\t\t\t\tupdate_channels(chip, CH);\n\t\t\t\tCH++;\t\t\t\t\t/* channel 2 */\n\t\t\t\tprev = CH->extended;\n\t\t\t\tCH->extended = (v>>2) & 1;\n\t\t\t\tif(prev != CH->extended)\n\t\t\t\t\tupdate_channels(chip, CH);\n\n\n\t\t\t\tCH = &chip->P_CH[9];\t/* channel 9 */\n\t\t\t\tprev = CH->extended;\n\t\t\t\tCH->extended = (v>>3) & 1;\n\t\t\t\tif(prev != CH->extended)\n\t\t\t\t\tupdate_channels(chip, CH);\n\t\t\t\tCH++;\t\t\t\t\t/* channel 10 */\n\t\t\t\tprev = CH->extended;\n\t\t\t\tCH->extended = (v>>4) & 1;\n\t\t\t\tif(prev != CH->extended)\n\t\t\t\t\tupdate_channels(chip, CH);\n\t\t\t\tCH++;\t\t\t\t\t/* channel 11 */\n\t\t\t\tprev = CH->extended;\n\t\t\t\tCH->extended = (v>>5) & 1;\n\t\t\t\tif(prev != CH->extended)\n\t\t\t\t\tupdate_channels(chip, CH);\n\n\t\t\t}\n\t\t\treturn;\n\n\t\tcase 0x105:\t/* OPL3 extensions enable register */\n\n\t\t\tchip->OPL3_mode = v&0x01;\t/* OPL3 mode when bit0=1 otherwise it is OPL2 mode */\n\n\t\t\t/* following behaviour was tested on real YMF262,\n            switching OPL3/OPL2 modes on the fly:\n             - does not change the waveform previously selected (unless when ....)\n             - does not update CH.A, CH.B, CH.C and CH.D output selectors (registers c0-c8) (unless when ....)\n             - does not disable channels 9-17 on OPL3->OPL2 switch\n             - does not switch 4 operator channels back to 2 operator channels\n            */\n\n\t\t\treturn;\n\n\t\tdefault:\n#ifdef _DEBUG\n\t\t\tif (r < 0x120)\n\t\t\t\tlogerror(\"YMF262: write to unknown register (set#2): %03x value=%02x\\n\",r,v);\n#endif\n\t\tbreak;\n\t\t}\n\n\t\tch_offset = 9;\t/* register page #2 starts from channel 9 (counting from 0) */\n\t}\n\n\t/* adjust bus to 8 bits */\n\tr &= 0xff;\n\tv &= 0xff;\n\n\n\tswitch(r&0xe0)\n\t{\n\tcase 0x00:\t/* 00-1f:control */\n\t\tswitch(r&0x1f)\n\t\t{\n\t\tcase 0x01:\t/* test register */\n\t\tbreak;\n\t\tcase 0x02:\t/* Timer 1 */\n\t\t\tchip->T[0] = (256-v)*4;\n\t\tbreak;\n\t\tcase 0x03:\t/* Timer 2 */\n\t\t\tchip->T[1] = (256-v)*16;\n\t\tbreak;\n\t\tcase 0x04:\t/* IRQ clear / mask and Timer enable */\n\t\t\tif(v&0x80)\n\t\t\t{\t/* IRQ flags clear */\n\t\t\t\tOPL3_STATUS_RESET(chip,0x60);\n\t\t\t}\n\t\t\telse\n\t\t\t{\t/* set IRQ mask ,timer enable */\n\t\t\t\tUINT8 st1 = v & 1;\n\t\t\t\tUINT8 st2 = (v>>1) & 1;\n\n\t\t\t\t/* IRQRST,T1MSK,t2MSK,x,x,x,ST2,ST1 */\n\t\t\t\tOPL3_STATUS_RESET(chip, v & 0x60);\n\t\t\t\tOPL3_STATUSMASK_SET(chip, (~v) & 0x60 );\n\n\t\t\t\t/* timer 2 */\n\t\t\t\tif(chip->st[1] != st2)\n\t\t\t\t{\n\t\t\t\t\t//attotime period = st2 ? attotime_mul(chip->TimerBase, chip->T[1]) : attotime_zero;\n\t\t\t\t\tchip->st[1] = st2;\n\t\t\t\t\t//if (chip->timer_handler) (chip->timer_handler)(chip->TimerParam,1,period);\n\t\t\t\t}\n\t\t\t\t/* timer 1 */\n\t\t\t\tif(chip->st[0] != st1)\n\t\t\t\t{\n\t\t\t\t\t//attotime period = st1 ? attotime_mul(chip->TimerBase, chip->T[0]) : attotime_zero;\n\t\t\t\t\tchip->st[0] = st1;\n\t\t\t\t\t//if (chip->timer_handler) (chip->timer_handler)(chip->TimerParam,0,period);\n\t\t\t\t}\n\t\t\t}\n\t\tbreak;\n\t\tcase 0x08:\t/* x,NTS,x,x, x,x,x,x */\n\t\t\tchip->nts = v;\n\t\tbreak;\n\n\t\tdefault:\n#ifdef _DEBUG\n\t\t\tlogerror(\"YMF262: write to unknown register: %02x value=%02x\\n\",r,v);\n#endif\n\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase 0x20:\t/* am ON, vib ON, ksr, eg_type, mul */\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot < 0) return;\n\t\tset_mul(chip, slot + ch_offset*2, v);\n\tbreak;\n\tcase 0x40:\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot < 0) return;\n\t\tset_ksl_tl(chip, slot + ch_offset*2, v);\n\tbreak;\n\tcase 0x60:\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot < 0) return;\n\t\tset_ar_dr(chip, slot + ch_offset*2, v);\n\tbreak;\n\tcase 0x80:\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot < 0) return;\n\t\tset_sl_rr(chip, slot + ch_offset*2, v);\n\tbreak;\n\tcase 0xa0:\n\t\tif (r == 0xbd)\t\t\t/* am depth, vibrato depth, r,bd,sd,tom,tc,hh */\n\t\t{\n\t\t\tif (ch_offset != 0)\t/* 0xbd register is present in set #1 only */\n\t\t\t\treturn;\n\n\t\t\tchip->lfo_am_depth = v & 0x80;\n\t\t\tchip->lfo_pm_depth_range = (v&0x40) ? 8 : 0;\n\n\t\t\tchip->rhythm = v&0x3f;\n\n\t\t\tif(chip->rhythm&0x20)\n\t\t\t{\n\t\t\t\t/* BD key on/off */\n\t\t\t\tif(v&0x10)\n\t\t\t\t{\n\t\t\t\t\tFM_KEYON (&chip->P_CH[6].SLOT[SLOT1], 2);\n\t\t\t\t\tFM_KEYON (&chip->P_CH[6].SLOT[SLOT2], 2);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tFM_KEYOFF(&chip->P_CH[6].SLOT[SLOT1],~2);\n\t\t\t\t\tFM_KEYOFF(&chip->P_CH[6].SLOT[SLOT2],~2);\n\t\t\t\t}\n\t\t\t\t/* HH key on/off */\n\t\t\t\tif(v&0x01) FM_KEYON (&chip->P_CH[7].SLOT[SLOT1], 2);\n\t\t\t\telse       FM_KEYOFF(&chip->P_CH[7].SLOT[SLOT1],~2);\n\t\t\t\t/* SD key on/off */\n\t\t\t\tif(v&0x08) FM_KEYON (&chip->P_CH[7].SLOT[SLOT2], 2);\n\t\t\t\telse       FM_KEYOFF(&chip->P_CH[7].SLOT[SLOT2],~2);\n\t\t\t\t/* TOM key on/off */\n\t\t\t\tif(v&0x04) FM_KEYON (&chip->P_CH[8].SLOT[SLOT1], 2);\n\t\t\t\telse       FM_KEYOFF(&chip->P_CH[8].SLOT[SLOT1],~2);\n\t\t\t\t/* TOP-CY key on/off */\n\t\t\t\tif(v&0x02) FM_KEYON (&chip->P_CH[8].SLOT[SLOT2], 2);\n\t\t\t\telse       FM_KEYOFF(&chip->P_CH[8].SLOT[SLOT2],~2);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* BD key off */\n\t\t\t\tFM_KEYOFF(&chip->P_CH[6].SLOT[SLOT1],~2);\n\t\t\t\tFM_KEYOFF(&chip->P_CH[6].SLOT[SLOT2],~2);\n\t\t\t\t/* HH key off */\n\t\t\t\tFM_KEYOFF(&chip->P_CH[7].SLOT[SLOT1],~2);\n\t\t\t\t/* SD key off */\n\t\t\t\tFM_KEYOFF(&chip->P_CH[7].SLOT[SLOT2],~2);\n\t\t\t\t/* TOM key off */\n\t\t\t\tFM_KEYOFF(&chip->P_CH[8].SLOT[SLOT1],~2);\n\t\t\t\t/* TOP-CY off */\n\t\t\t\tFM_KEYOFF(&chip->P_CH[8].SLOT[SLOT2],~2);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t/* keyon,block,fnum */\n\t\tif( (r&0x0f) > 8) return;\n\t\tCH = &chip->P_CH[(r&0x0f) + ch_offset];\n\n\t\tif(!(r&0x10))\n\t\t{\t/* a0-a8 */\n\t\t\tblock_fnum  = (CH->block_fnum&0x1f00) | v;\n\t\t}\n\t\telse\n\t\t{\t/* b0-b8 */\n\t\t\tblock_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);\n\n\t\t\tif (chip->OPL3_mode & 1)\n\t\t\t{\n\t\t\t\tint chan_no = (r&0x0f) + ch_offset;\n\n\t\t\t\t/* in OPL3 mode */\n\t\t\t\t//DO THIS:\n\t\t\t\t//if this is 1st channel forming up a 4-op channel\n\t\t\t\t//ALSO keyon/off slots of 2nd channel forming up 4-op channel\n\t\t\t\t//else normal 2 operator function keyon/off\n\t\t\t\t//OR THIS:\n\t\t\t\t//if this is 2nd channel forming up 4-op channel just do nothing\n\t\t\t\t//else normal 2 operator function keyon/off\n\t\t\t\tswitch(chan_no)\n\t\t\t\t{\n\t\t\t\tcase 0: case 1: case 2:\n\t\t\t\tcase 9: case 10: case 11:\n\t\t\t\t\tif (CH->extended)\n\t\t\t\t\t{\n\t\t\t\t\t\t//if this is 1st channel forming up a 4-op channel\n\t\t\t\t\t\t//ALSO keyon/off slots of 2nd channel forming up 4-op channel\n\t\t\t\t\t\tif(v&0x20)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFM_KEYON (&CH->SLOT[SLOT1], 1);\n\t\t\t\t\t\t\tFM_KEYON (&CH->SLOT[SLOT2], 1);\n\t\t\t\t\t\t\tFM_KEYON (&(CH+3)->SLOT[SLOT1], 1);\n\t\t\t\t\t\t\tFM_KEYON (&(CH+3)->SLOT[SLOT2], 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFM_KEYOFF(&CH->SLOT[SLOT1],~1);\n\t\t\t\t\t\t\tFM_KEYOFF(&CH->SLOT[SLOT2],~1);\n\t\t\t\t\t\t\tFM_KEYOFF(&(CH+3)->SLOT[SLOT1],~1);\n\t\t\t\t\t\t\tFM_KEYOFF(&(CH+3)->SLOT[SLOT2],~1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//else normal 2 operator function keyon/off\n\t\t\t\t\t\tif(v&0x20)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFM_KEYON (&CH->SLOT[SLOT1], 1);\n\t\t\t\t\t\t\tFM_KEYON (&CH->SLOT[SLOT2], 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFM_KEYOFF(&CH->SLOT[SLOT1],~1);\n\t\t\t\t\t\t\tFM_KEYOFF(&CH->SLOT[SLOT2],~1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\tcase 3: case 4: case 5:\n\t\t\t\tcase 12: case 13: case 14:\n\t\t\t\t\tif ((CH-3)->extended)\n\t\t\t\t\t{\n\t\t\t\t\t\t//if this is 2nd channel forming up 4-op channel just do nothing\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//else normal 2 operator function keyon/off\n\t\t\t\t\t\tif(v&0x20)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFM_KEYON (&CH->SLOT[SLOT1], 1);\n\t\t\t\t\t\t\tFM_KEYON (&CH->SLOT[SLOT2], 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFM_KEYOFF(&CH->SLOT[SLOT1],~1);\n\t\t\t\t\t\t\tFM_KEYOFF(&CH->SLOT[SLOT2],~1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tif(v&0x20)\n\t\t\t\t\t{\n\t\t\t\t\t\tFM_KEYON (&CH->SLOT[SLOT1], 1);\n\t\t\t\t\t\tFM_KEYON (&CH->SLOT[SLOT2], 1);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tFM_KEYOFF(&CH->SLOT[SLOT1],~1);\n\t\t\t\t\t\tFM_KEYOFF(&CH->SLOT[SLOT2],~1);\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(v&0x20)\n\t\t\t\t{\n\t\t\t\t\tFM_KEYON (&CH->SLOT[SLOT1], 1);\n\t\t\t\t\tFM_KEYON (&CH->SLOT[SLOT2], 1);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tFM_KEYOFF(&CH->SLOT[SLOT1],~1);\n\t\t\t\t\tFM_KEYOFF(&CH->SLOT[SLOT2],~1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t/* update */\n\t\tif(CH->block_fnum != block_fnum)\n\t\t{\n\t\t\tUINT8 block  = block_fnum >> 10;\n\n\t\t\tCH->block_fnum = block_fnum;\n\n\t\t\tCH->ksl_base = ksl_tab[block_fnum>>6];\n\t\t\tCH->fc       = chip->fn_tab[block_fnum&0x03ff] >> (7-block);\n\n\t\t\t/* BLK 2,1,0 bits -> bits 3,2,1 of kcode */\n\t\t\tCH->kcode    = (CH->block_fnum&0x1c00)>>9;\n\n\t\t\t/* the info below is actually opposite to what is stated in the Manuals (verifed on real YMF262) */\n\t\t\t/* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum  */\n\t\t\t/* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */\n\t\t\tif (chip->nts&0x40)\n\t\t\t\tCH->kcode |= (CH->block_fnum&0x100)>>8;\t/* notesel == 1 */\n\t\t\telse\n\t\t\t\tCH->kcode |= (CH->block_fnum&0x200)>>9;\t/* notesel == 0 */\n\n\t\t\tif (chip->OPL3_mode & 1)\n\t\t\t{\n\t\t\t\tint chan_no = (r&0x0f) + ch_offset;\n\t\t\t\t/* in OPL3 mode */\n\t\t\t\t//DO THIS:\n\t\t\t\t//if this is 1st channel forming up a 4-op channel\n\t\t\t\t//ALSO update slots of 2nd channel forming up 4-op channel\n\t\t\t\t//else normal 2 operator function keyon/off\n\t\t\t\t//OR THIS:\n\t\t\t\t//if this is 2nd channel forming up 4-op channel just do nothing\n\t\t\t\t//else normal 2 operator function keyon/off\n\t\t\t\tswitch(chan_no)\n\t\t\t\t{\n\t\t\t\tcase 0: case 1: case 2:\n\t\t\t\tcase 9: case 10: case 11:\n\t\t\t\t\tif (CH->extended)\n\t\t\t\t\t{\n\t\t\t\t\t\t//if this is 1st channel forming up a 4-op channel\n\t\t\t\t\t\t//ALSO update slots of 2nd channel forming up 4-op channel\n\n\t\t\t\t\t\t/* refresh Total Level in FOUR SLOTs of this channel and channel+3 using data from THIS channel */\n\t\t\t\t\t\tCH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);\n\t\t\t\t\t\tCH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);\n\t\t\t\t\t\t(CH+3)->SLOT[SLOT1].TLL = (CH+3)->SLOT[SLOT1].TL + (CH->ksl_base>>(CH+3)->SLOT[SLOT1].ksl);\n\t\t\t\t\t\t(CH+3)->SLOT[SLOT2].TLL = (CH+3)->SLOT[SLOT2].TL + (CH->ksl_base>>(CH+3)->SLOT[SLOT2].ksl);\n\n\t\t\t\t\t\t/* refresh frequency counter in FOUR SLOTs of this channel and channel+3 using data from THIS channel */\n\t\t\t\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT1]);\n\t\t\t\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT2]);\n\t\t\t\t\t\tCALC_FCSLOT(CH,&(CH+3)->SLOT[SLOT1]);\n\t\t\t\t\t\tCALC_FCSLOT(CH,&(CH+3)->SLOT[SLOT2]);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//else normal 2 operator function\n\t\t\t\t\t\t/* refresh Total Level in both SLOTs of this channel */\n\t\t\t\t\t\tCH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);\n\t\t\t\t\t\tCH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);\n\n\t\t\t\t\t\t/* refresh frequency counter in both SLOTs of this channel */\n\t\t\t\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT1]);\n\t\t\t\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT2]);\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\tcase 3: case 4: case 5:\n\t\t\t\tcase 12: case 13: case 14:\n\t\t\t\t\tif ((CH-3)->extended)\n\t\t\t\t\t{\n\t\t\t\t\t\t//if this is 2nd channel forming up 4-op channel just do nothing\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//else normal 2 operator function\n\t\t\t\t\t\t/* refresh Total Level in both SLOTs of this channel */\n\t\t\t\t\t\tCH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);\n\t\t\t\t\t\tCH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);\n\n\t\t\t\t\t\t/* refresh frequency counter in both SLOTs of this channel */\n\t\t\t\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT1]);\n\t\t\t\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT2]);\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\t/* refresh Total Level in both SLOTs of this channel */\n\t\t\t\t\tCH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);\n\t\t\t\t\tCH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);\n\n\t\t\t\t\t/* refresh frequency counter in both SLOTs of this channel */\n\t\t\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT1]);\n\t\t\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT2]);\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* in OPL2 mode */\n\n\t\t\t\t/* refresh Total Level in both SLOTs of this channel */\n\t\t\t\tCH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);\n\t\t\t\tCH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);\n\n\t\t\t\t/* refresh frequency counter in both SLOTs of this channel */\n\t\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT1]);\n\t\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT2]);\n\t\t\t}\n\t\t}\n\tbreak;\n\n\tcase 0xc0:\n\t\t/* CH.D, CH.C, CH.B, CH.A, FB(3bits), C */\n\t\tif( (r&0xf) > 8) return;\n\n\t\tCH = &chip->P_CH[(r&0xf) + ch_offset];\n\n\t\tif( chip->OPL3_mode & 1 )\n\t\t{\n\t\t\tint base = ((r&0xf) + ch_offset) * 4;\n\n\t\t\t/* OPL3 mode */\n\t\t\tchip->pan[ base    ] = (v & 0x10) ? ~0 : 0;\t/* ch.A */\n\t\t\tchip->pan[ base +1 ] = (v & 0x20) ? ~0 : 0;\t/* ch.B */\n\t\t\tchip->pan[ base +2 ] = (v & 0x40) ? ~0 : 0;\t/* ch.C */\n\t\t\tchip->pan[ base +3 ] = (v & 0x80) ? ~0 : 0;\t/* ch.D */\n\t\t}\n\t\telse\n\t\t{\n\t\t\tint base = ((r&0xf) + ch_offset) * 4;\n\n\t\t\t/* OPL2 mode - always enabled */\n\t\t\tchip->pan[ base    ] = ~0;\t\t/* ch.A */\n\t\t\tchip->pan[ base +1 ] = ~0;\t\t/* ch.B */\n\t\t\tchip->pan[ base +2 ] = ~0;\t\t/* ch.C */\n\t\t\tchip->pan[ base +3 ] = ~0;\t\t/* ch.D */\n\t\t}\n\n\t\tchip->pan_ctrl_value[ (r&0xf) + ch_offset ] = v;\t/* store control value for OPL3/OPL2 mode switching on the fly */\n\n\t\tCH->SLOT[SLOT1].FB  = (v>>1)&7 ? ((v>>1)&7) + 7 : 0;\n\t\tCH->SLOT[SLOT1].CON = v&1;\n\n\t\tif( chip->OPL3_mode & 1 )\n\t\t{\n\t\t\tint chan_no = (r&0x0f) + ch_offset;\n\n\t\t\tswitch(chan_no)\n\t\t\t{\n\t\t\tcase 0: case 1: case 2:\n\t\t\tcase 9: case 10: case 11:\n\t\t\t\tif (CH->extended)\n\t\t\t\t{\n\t\t\t\t\tUINT8 conn = (CH->SLOT[SLOT1].CON<<1) | ((CH+3)->SLOT[SLOT1].CON<<0);\n\t\t\t\t\tswitch(conn)\n\t\t\t\t\t{\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\t/* 1 -> 2 -> 3 -> 4 - out */\n\n\t\t\t\t\t\tCH->SLOT[SLOT1].connect = &chip->phase_modulation;\n\t\t\t\t\t\tCH->SLOT[SLOT2].connect = &chip->phase_modulation2;\n\t\t\t\t\t\t(CH+3)->SLOT[SLOT1].connect = &chip->phase_modulation;\n\t\t\t\t\t\t(CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ];\n\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\t/* 1 -> 2 -\\\n                           3 -> 4 -+- out */\n\n\t\t\t\t\t\tCH->SLOT[SLOT1].connect = &chip->phase_modulation;\n\t\t\t\t\t\tCH->SLOT[SLOT2].connect = &chanout[ chan_no ];\n\t\t\t\t\t\t(CH+3)->SLOT[SLOT1].connect = &chip->phase_modulation;\n\t\t\t\t\t\t(CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ];\n\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\t/* 1 -----------\\\n                           2 -> 3 -> 4 -+- out */\n\n\t\t\t\t\t\tCH->SLOT[SLOT1].connect = &chanout[ chan_no ];\n\t\t\t\t\t\tCH->SLOT[SLOT2].connect = &chip->phase_modulation2;\n\t\t\t\t\t\t(CH+3)->SLOT[SLOT1].connect = &chip->phase_modulation;\n\t\t\t\t\t\t(CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ];\n\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\t/* 1 ------\\\n                           2 -> 3 -+- out\n                           4 ------/     */\n\t\t\t\t\t\tCH->SLOT[SLOT1].connect = &chanout[ chan_no ];\n\t\t\t\t\t\tCH->SLOT[SLOT2].connect = &chip->phase_modulation2;\n\t\t\t\t\t\t(CH+3)->SLOT[SLOT1].connect = &chanout[ chan_no + 3 ];\n\t\t\t\t\t\t(CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ];\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* 2 operators mode */\n\t\t\t\t\tCH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &chip->phase_modulation;\n\t\t\t\t\tCH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset];\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tcase 3: case 4: case 5:\n\t\t\tcase 12: case 13: case 14:\n\t\t\t\tif ((CH-3)->extended)\n\t\t\t\t{\n\t\t\t\t\tUINT8 conn = ((CH-3)->SLOT[SLOT1].CON<<1) | (CH->SLOT[SLOT1].CON<<0);\n\t\t\t\t\tswitch(conn)\n\t\t\t\t\t{\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\t/* 1 -> 2 -> 3 -> 4 - out */\n\n\t\t\t\t\t\t(CH-3)->SLOT[SLOT1].connect = &chip->phase_modulation;\n\t\t\t\t\t\t(CH-3)->SLOT[SLOT2].connect = &chip->phase_modulation2;\n\t\t\t\t\t\tCH->SLOT[SLOT1].connect = &chip->phase_modulation;\n\t\t\t\t\t\tCH->SLOT[SLOT2].connect = &chanout[ chan_no ];\n\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\t/* 1 -> 2 -\\\n                           3 -> 4 -+- out */\n\n\t\t\t\t\t\t(CH-3)->SLOT[SLOT1].connect = &chip->phase_modulation;\n\t\t\t\t\t\t(CH-3)->SLOT[SLOT2].connect = &chanout[ chan_no - 3 ];\n\t\t\t\t\t\tCH->SLOT[SLOT1].connect = &chip->phase_modulation;\n\t\t\t\t\t\tCH->SLOT[SLOT2].connect = &chanout[ chan_no ];\n\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\t/* 1 -----------\\\n                           2 -> 3 -> 4 -+- out */\n\n\t\t\t\t\t\t(CH-3)->SLOT[SLOT1].connect = &chanout[ chan_no - 3 ];\n\t\t\t\t\t\t(CH-3)->SLOT[SLOT2].connect = &chip->phase_modulation2;\n\t\t\t\t\t\tCH->SLOT[SLOT1].connect = &chip->phase_modulation;\n\t\t\t\t\t\tCH->SLOT[SLOT2].connect = &chanout[ chan_no ];\n\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\t/* 1 ------\\\n                           2 -> 3 -+- out\n                           4 ------/     */\n\t\t\t\t\t\t(CH-3)->SLOT[SLOT1].connect = &chanout[ chan_no - 3 ];\n\t\t\t\t\t\t(CH-3)->SLOT[SLOT2].connect = &chip->phase_modulation2;\n\t\t\t\t\t\tCH->SLOT[SLOT1].connect = &chanout[ chan_no ];\n\t\t\t\t\t\tCH->SLOT[SLOT2].connect = &chanout[ chan_no ];\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* 2 operators mode */\n\t\t\t\t\tCH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &chip->phase_modulation;\n\t\t\t\t\tCH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset];\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t\t/* 2 operators mode */\n\t\t\t\t\tCH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &chip->phase_modulation;\n\t\t\t\t\tCH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset];\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* OPL2 mode - always 2 operators mode */\n\t\t\tCH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &chip->phase_modulation;\n\t\t\tCH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset];\n\t\t}\n\tbreak;\n\n\tcase 0xe0: /* waveform select */\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot < 0) return;\n\n\t\tslot += ch_offset*2;\n\n\t\tCH = &chip->P_CH[slot/2];\n\n\n\t\t/* store 3-bit value written regardless of current OPL2 or OPL3 mode... (verified on real YMF262) */\n\t\tv &= 7;\n\t\tCH->SLOT[slot&1].waveform_number = v;\n\n\t\t/* ... but select only waveforms 0-3 in OPL2 mode */\n\t\tif( !(chip->OPL3_mode & 1) )\n\t\t{\n\t\t\tv &= 3; /* we're in OPL2 mode */\n\t\t}\n\t\tCH->SLOT[slot&1].wavetable = v * SIN_LEN;\n\tbreak;\n\t}\n}\n\n/*static TIMER_CALLBACK( cymfile_callback )\n{\n\tif (cymfile)\n\t{\n\t\tfputc( (unsigned char)0, cymfile );\n\t}\n}*/\n\n/* lock/unlock for common table */\nstatic int OPL3_LockTable()\n{\n\tnum_lock++;\n\tif(num_lock>1) return 0;\n\n\t/* first time */\n\n\tif( !init_tables() )\n\t{\n\t\tnum_lock--;\n\t\treturn -1;\n\t}\n\n\t/*if (LOG_CYM_FILE)\n\t{\n\t\tcymfile = fopen(\"ymf262_.cym\",\"wb\");\n\t\tif (cymfile)\n\t\t\ttimer_pulse ( device->machine, ATTOTIME_IN_HZ(110), NULL, 0, cymfile_callback); //110 Hz pulse timer\n\t\telse\n\t\t\tlogerror(\"Could not create ymf262_.cym file\\n\");\n\t}*/\n\n\treturn 0;\n}\n\nstatic void OPL3_UnLockTable(void)\n{\n\tif(num_lock) num_lock--;\n\tif(num_lock) return;\n\n\t/* last time */\n\n\tOPLCloseTable();\n\n\t/*if (LOG_CYM_FILE)\n\t\tfclose (cymfile);\n\tcymfile = NULL;*/\n}\n\nstatic void OPL3ResetChip(OPL3 *chip)\n{\n\tint c,s;\n\n\tchip->eg_timer = 0;\n\tchip->eg_cnt   = 0;\n\n\tchip->noise_rng = 1;\t/* noise shift register */\n\tchip->nts       = 0;\t/* note split */\n\tOPL3_STATUS_RESET(chip,0x60);\n\n\t/* reset with register write */\n\tOPL3WriteReg(chip,0x01,0); /* test register */\n\tOPL3WriteReg(chip,0x02,0); /* Timer1 */\n\tOPL3WriteReg(chip,0x03,0); /* Timer2 */\n\tOPL3WriteReg(chip,0x04,0); /* IRQ mask clear */\n\n\n//FIX IT  registers 101, 104 and 105\n\n\n//FIX IT (dont change CH.D, CH.C, CH.B and CH.A in C0-C8 registers)\n\tfor(c = 0xff ; c >= 0x20 ; c-- )\n\t\tOPL3WriteReg(chip,c,0);\n//FIX IT (dont change CH.D, CH.C, CH.B and CH.A in C0-C8 registers)\n\tfor(c = 0x1ff ; c >= 0x120 ; c-- )\n\t\tOPL3WriteReg(chip,c,0);\n\n\n\n\t/* reset operator parameters */\n\tfor( c = 0 ; c < 9*2 ; c++ )\n\t{\n\t\tOPL3_CH *CH = &chip->P_CH[c];\n\t\tfor(s = 0 ; s < 2 ; s++ )\n\t\t{\n\t\t\tCH->SLOT[s].state     = EG_OFF;\n\t\t\tCH->SLOT[s].volume    = MAX_ATT_INDEX;\n\t\t}\n\t}\n}\n\n/* Create one of virtual YMF262 */\n/* 'clock' is chip clock in Hz  */\n/* 'rate'  is sampling rate  */\nstatic OPL3 *OPL3Create(int clock, int rate, int type)\n{\n\tOPL3 *chip;\n\n\tif (OPL3_LockTable() == -1) return NULL;\n\n\t/* allocate memory block */\n\tchip = (OPL3 *)malloc(sizeof(OPL3));\n\n\tif (chip==NULL)\n\t\treturn NULL;\n\n\t/* clear */\n\tmemset(chip, 0, sizeof(OPL3));\n\n\tchip->type  = type;\n\tchip->clock = clock;\n\tchip->rate  = rate;\n\n\t/* init global tables */\n\tOPL3_initalize(chip);\n\n\t/* reset chip */\n\tOPL3ResetChip(chip);\n\treturn chip;\n}\n\n/* Destroy one of virtual YMF262 */\nstatic void OPL3Destroy(OPL3 *chip)\n{\n\tOPL3_UnLockTable();\n\tfree(chip);\n}\n\n\n/* Optional handlers */\n\nstatic void OPL3SetTimerHandler(OPL3 *chip,OPL3_TIMERHANDLER timer_handler,void *param)\n{\n\tchip->timer_handler   = timer_handler;\n\tchip->TimerParam = param;\n}\nstatic void OPL3SetIRQHandler(OPL3 *chip,OPL3_IRQHANDLER IRQHandler,void *param)\n{\n\tchip->IRQHandler     = IRQHandler;\n\tchip->IRQParam = param;\n}\nstatic void OPL3SetUpdateHandler(OPL3 *chip,OPL3_UPDATEHANDLER UpdateHandler,void *param)\n{\n\tchip->UpdateHandler = UpdateHandler;\n\tchip->UpdateParam = param;\n}\n\n/* YMF262 I/O interface */\nstatic int OPL3Write(OPL3 *chip, int a, int v)\n{\n\t/* data bus is 8 bits */\n\tv &= 0xff;\n\n\tswitch(a&3)\n\t{\n\tcase 0:\t/* address port 0 (register set #1) */\n\t\tchip->address = v;\n\tbreak;\n\n\tcase 1:\t/* data port - ignore A1 */\n\tcase 3:\t/* data port - ignore A1 */\n\t\tif(chip->UpdateHandler) chip->UpdateHandler(chip->UpdateParam/*,0*/);\n\t\tOPL3WriteReg(chip,chip->address,v);\n\tbreak;\n\n\tcase 2:\t/* address port 1 (register set #2) */\n\n\t\t/* verified on real YMF262:\n         in OPL3 mode:\n           address line A1 is stored during *address* write and ignored during *data* write.\n\n         in OPL2 mode:\n           register set#2 writes go to register set#1 (ignoring A1)\n           verified on registers from set#2: 0x01, 0x04, 0x20-0xef\n           The only exception is register 0x05.\n        */\n\t\tif( chip->OPL3_mode & 1 )\n\t\t{\n\t\t\t/* OPL3 mode */\n\t\t\t\tchip->address = v | 0x100;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* in OPL2 mode the only accessible in set #2 is register 0x05 */\n\t\t\tif( v==5 )\n\t\t\t\tchip->address = v | 0x100;\n\t\t\telse\n\t\t\t\tchip->address = v;\t/* verified range: 0x01, 0x04, 0x20-0xef(set #2 becomes set #1 in opl2 mode) */\n\t\t}\n\tbreak;\n\t}\n\n\treturn chip->status>>7;\n}\n\nstatic unsigned char OPL3Read(OPL3 *chip,int a)\n{\n\tif( a==0 )\n\t{\n\t\t/* status port */\n\t\treturn chip->status;\n\t}\n\n\treturn 0x00;\t/* verified on real YMF262 */\n}\n\n\n\nstatic int OPL3TimerOver(OPL3 *chip,int c)\n{\n\tif( c )\n\t{\t/* Timer B */\n\t\tOPL3_STATUS_SET(chip,0x20);\n\t}\n\telse\n\t{\t/* Timer A */\n\t\tOPL3_STATUS_SET(chip,0x40);\n\t}\n\t/* reload timer */\n\t//if (chip->timer_handler) (chip->timer_handler)(chip->TimerParam,c,attotime_mul(chip->TimerBase, chip->T[c]));\n\treturn chip->status>>7;\n}\n\n\n\n\nvoid * ymf262_init(int clock, int rate)\n{\n\treturn OPL3Create(clock,rate,OPL3_TYPE_YMF262);\n}\n\nvoid ymf262_shutdown(void *chip)\n{\n\tOPL3Destroy((OPL3 *)chip);\n}\nvoid ymf262_reset_chip(void *chip)\n{\n\tOPL3ResetChip((OPL3 *)chip);\n}\n\nint ymf262_write(void *chip, int a, int v)\n{\n\treturn OPL3Write((OPL3 *)chip, a, v);\n}\n\nunsigned char ymf262_read(void *chip, int a)\n{\n\t/* Note on status register: */\n\n\t/* YM3526(OPL) and YM3812(OPL2) return bit2 and bit1 in HIGH state */\n\n\t/* YMF262(OPL3) always returns bit2 and bit1 in LOW state */\n\t/* which can be used to identify the chip */\n\n\t/* YMF278(OPL4) returns bit2 in LOW and bit1 in HIGH state ??? info from manual - not verified */\n\n\treturn OPL3Read((OPL3 *)chip, a);\n}\nint ymf262_timer_over(void *chip, int c)\n{\n\treturn OPL3TimerOver((OPL3 *)chip, c);\n}\n\nvoid ymf262_set_timer_handler(void *chip, OPL3_TIMERHANDLER timer_handler, void *param)\n{\n\tOPL3SetTimerHandler((OPL3 *)chip, timer_handler, param);\n}\nvoid ymf262_set_irq_handler(void *chip,OPL3_IRQHANDLER IRQHandler,void *param)\n{\n\tOPL3SetIRQHandler((OPL3 *)chip, IRQHandler, param);\n}\nvoid ymf262_set_update_handler(void *chip,OPL3_UPDATEHANDLER UpdateHandler,void *param)\n{\n\tOPL3SetUpdateHandler((OPL3 *)chip, UpdateHandler, param);\n}\n\nvoid ymf262_set_mutemask(void *chip, UINT32 MuteMask)\n{\n\tOPL3 *opl3 = (OPL3 *)chip;\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 18; CurChn ++)\n\t\topl3->P_CH[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\tfor (CurChn = 0; CurChn < 5; CurChn ++)\n\t\topl3->MuteSpc[CurChn] = (MuteMask >> (CurChn + 18)) & 0x01;\n\t\n\treturn;\n}\n\n\n/*\n** Generate samples for one of the YMF262's\n**\n** 'which' is the virtual YMF262 number\n** '**buffers' is table of 4 pointers to the buffers: CH.A, CH.B, CH.C and CH.D\n** 'length' is the number of samples that should be generated\n*/\nvoid ymf262_update_one(void *_chip, OPL3SAMPLE **buffers, int length)\n{\n\tOPL3\t\t*chip  = (OPL3 *)_chip;\n\tUINT8\t\trhythm = chip->rhythm&0x20;\n\n\tOPL3SAMPLE\t*ch_a = buffers[0];\n\tOPL3SAMPLE\t*ch_b = buffers[1];\n\t//OPL3SAMPLE\t*ch_c = buffers[2];\n\t//OPL3SAMPLE\t*ch_d = buffers[3];\n\n\tint i;\n\tint chn;\n\n\tfor( i=0; i < length ; i++ )\n\t{\n\t\tint a,b,c,d;\n\n\n\t\tadvance_lfo(chip);\n\n\t\t/* clear channel outputs */\n\t\tmemset(chip->chanout, 0, sizeof(signed int) * 18);\n\n#if 1\n\t/* register set #1 */\n\t\tchan_calc(chip, &chip->P_CH[0]);\t\t\t/* extended 4op ch#0 part 1 or 2op ch#0 */\n\t\tif (chip->P_CH[0].extended)\n\t\t\tchan_calc_ext(chip, &chip->P_CH[3]);\t/* extended 4op ch#0 part 2 */\n\t\telse\n\t\t\tchan_calc(chip, &chip->P_CH[3]);\t\t/* standard 2op ch#3 */\n\n\n\t\tchan_calc(chip, &chip->P_CH[1]);\t\t\t/* extended 4op ch#1 part 1 or 2op ch#1 */\n\t\tif (chip->P_CH[1].extended)\n\t\t\tchan_calc_ext(chip, &chip->P_CH[4]);\t/* extended 4op ch#1 part 2 */\n\t\telse\n\t\t\tchan_calc(chip, &chip->P_CH[4]);\t\t/* standard 2op ch#4 */\n\n\n\t\tchan_calc(chip, &chip->P_CH[2]);\t\t\t/* extended 4op ch#2 part 1 or 2op ch#2 */\n\t\tif (chip->P_CH[2].extended)\n\t\t\tchan_calc_ext(chip, &chip->P_CH[5]);\t/* extended 4op ch#2 part 2 */\n\t\telse\n\t\t\tchan_calc(chip, &chip->P_CH[5]);\t\t/* standard 2op ch#5 */\n\n\n\t\tif(!rhythm)\n\t\t{\n\t\t\tchan_calc(chip, &chip->P_CH[6]);\n\t\t\tchan_calc(chip, &chip->P_CH[7]);\n\t\t\tchan_calc(chip, &chip->P_CH[8]);\n\t\t}\n\t\telse\t\t/* Rhythm part */\n\t\t{\n\t\t\tchan_calc_rhythm(chip, &chip->P_CH[0], (chip->noise_rng>>0)&1 );\n\t\t}\n\n\t/* register set #2 */\n\t\tchan_calc(chip, &chip->P_CH[ 9]);\n\t\tif (chip->P_CH[9].extended)\n\t\t\tchan_calc_ext(chip, &chip->P_CH[12]);\n\t\telse\n\t\t\tchan_calc(chip, &chip->P_CH[12]);\n\n\n\t\tchan_calc(chip, &chip->P_CH[10]);\n\t\tif (chip->P_CH[10].extended)\n\t\t\tchan_calc_ext(chip, &chip->P_CH[13]);\n\t\telse\n\t\t\tchan_calc(chip, &chip->P_CH[13]);\n\n\n\t\tchan_calc(chip, &chip->P_CH[11]);\n\t\tif (chip->P_CH[11].extended)\n\t\t\tchan_calc_ext(chip, &chip->P_CH[14]);\n\t\telse\n\t\t\tchan_calc(chip, &chip->P_CH[14]);\n\n\n        /* channels 15,16,17 are fixed 2-operator channels only */\n\t\tchan_calc(chip, &chip->P_CH[15]);\n\t\tchan_calc(chip, &chip->P_CH[16]);\n\t\tchan_calc(chip, &chip->P_CH[17]);\n#endif\n\n\t\t/* accumulator register set #1 */\n\t\ta =  chip->chanout[0] & chip->pan[0];\n\t\tb =  chip->chanout[0] & chip->pan[1];\n\t\tc =  chip->chanout[0] & chip->pan[2];\n\t\td =  chip->chanout[0] & chip->pan[3];\n#if 1\n\t\ta += chip->chanout[1] & chip->pan[4];\n\t\tb += chip->chanout[1] & chip->pan[5];\n\t\tc += chip->chanout[1] & chip->pan[6];\n\t\td += chip->chanout[1] & chip->pan[7];\n\t\ta += chip->chanout[2] & chip->pan[8];\n\t\tb += chip->chanout[2] & chip->pan[9];\n\t\tc += chip->chanout[2] & chip->pan[10];\n\t\td += chip->chanout[2] & chip->pan[11];\n\n\t\ta += chip->chanout[3] & chip->pan[12];\n\t\tb += chip->chanout[3] & chip->pan[13];\n\t\tc += chip->chanout[3] & chip->pan[14];\n\t\td += chip->chanout[3] & chip->pan[15];\n\t\ta += chip->chanout[4] & chip->pan[16];\n\t\tb += chip->chanout[4] & chip->pan[17];\n\t\tc += chip->chanout[4] & chip->pan[18];\n\t\td += chip->chanout[4] & chip->pan[19];\n\t\ta += chip->chanout[5] & chip->pan[20];\n\t\tb += chip->chanout[5] & chip->pan[21];\n\t\tc += chip->chanout[5] & chip->pan[22];\n\t\td += chip->chanout[5] & chip->pan[23];\n\n\t\ta += chip->chanout[6] & chip->pan[24];\n\t\tb += chip->chanout[6] & chip->pan[25];\n\t\tc += chip->chanout[6] & chip->pan[26];\n\t\td += chip->chanout[6] & chip->pan[27];\n\t\ta += chip->chanout[7] & chip->pan[28];\n\t\tb += chip->chanout[7] & chip->pan[29];\n\t\tc += chip->chanout[7] & chip->pan[30];\n\t\td += chip->chanout[7] & chip->pan[31];\n\t\ta += chip->chanout[8] & chip->pan[32];\n\t\tb += chip->chanout[8] & chip->pan[33];\n\t\tc += chip->chanout[8] & chip->pan[34];\n\t\td += chip->chanout[8] & chip->pan[35];\n\n\t\t/* accumulator register set #2 */\n\t\ta += chip->chanout[9] & chip->pan[36];\n\t\tb += chip->chanout[9] & chip->pan[37];\n\t\tc += chip->chanout[9] & chip->pan[38];\n\t\td += chip->chanout[9] & chip->pan[39];\n\t\ta += chip->chanout[10] & chip->pan[40];\n\t\tb += chip->chanout[10] & chip->pan[41];\n\t\tc += chip->chanout[10] & chip->pan[42];\n\t\td += chip->chanout[10] & chip->pan[43];\n\t\ta += chip->chanout[11] & chip->pan[44];\n\t\tb += chip->chanout[11] & chip->pan[45];\n\t\tc += chip->chanout[11] & chip->pan[46];\n\t\td += chip->chanout[11] & chip->pan[47];\n\n\t\ta += chip->chanout[12] & chip->pan[48];\n\t\tb += chip->chanout[12] & chip->pan[49];\n\t\tc += chip->chanout[12] & chip->pan[50];\n\t\td += chip->chanout[12] & chip->pan[51];\n\t\ta += chip->chanout[13] & chip->pan[52];\n\t\tb += chip->chanout[13] & chip->pan[53];\n\t\tc += chip->chanout[13] & chip->pan[54];\n\t\td += chip->chanout[13] & chip->pan[55];\n\t\ta += chip->chanout[14] & chip->pan[56];\n\t\tb += chip->chanout[14] & chip->pan[57];\n\t\tc += chip->chanout[14] & chip->pan[58];\n\t\td += chip->chanout[14] & chip->pan[59];\n\n\t\ta += chip->chanout[15] & chip->pan[60];\n\t\tb += chip->chanout[15] & chip->pan[61];\n\t\tc += chip->chanout[15] & chip->pan[62];\n\t\td += chip->chanout[15] & chip->pan[63];\n\t\ta += chip->chanout[16] & chip->pan[64];\n\t\tb += chip->chanout[16] & chip->pan[65];\n\t\tc += chip->chanout[16] & chip->pan[66];\n\t\td += chip->chanout[16] & chip->pan[67];\n\t\ta += chip->chanout[17] & chip->pan[68];\n\t\tb += chip->chanout[17] & chip->pan[69];\n\t\tc += chip->chanout[17] & chip->pan[70];\n\t\td += chip->chanout[17] & chip->pan[71];\n#endif\n\t\ta >>= FINAL_SH;\n\t\tb >>= FINAL_SH;\n\t\tc >>= FINAL_SH;\n\t\td >>= FINAL_SH;\n\n\t\t/* limit check */\n\t\t//a = limit( a , MAXOUT, MINOUT );\n\t\t//b = limit( b , MAXOUT, MINOUT );\n\t\t//c = limit( c , MAXOUT, MINOUT );\n\t\t//d = limit( d , MAXOUT, MINOUT );\n\n\t\t#ifdef SAVE_SAMPLE\n\t\tif (which==0)\n\t\t{\n\t\t\tSAVE_ALL_CHANNELS\n\t\t}\n\t\t#endif\n\n\t\t/* store to sound buffer */\n\t\tch_a[i] = a+c;\n\t\tch_b[i] = b+d;\n\t\t//ch_c[i] = c;\n\t\t//ch_d[i] = d;\n\n\t\tadvance(chip);\n\t}\n\n}\n\n"
  },
  {
    "path": "VGMPlay/chips/ymf262.h",
    "content": "#pragma once\n\n//#include \"attotime.h\"\n\n/* select number of output bits: 8 or 16 */\n#define OPL3_SAMPLE_BITS 16\n\n/* compiler dependence */\n//#ifndef __OSDCOMM_H__\n//#define __OSDCOMM_H__\n/*typedef unsigned char\tUINT8;   // unsigned  8bit\ntypedef unsigned short\tUINT16;  // unsigned 16bit\ntypedef unsigned int\tUINT32;  // unsigned 32bit\ntypedef signed char\t\tINT8;    // signed  8bit\ntypedef signed short\tINT16;   // signed 16bit\ntypedef signed int\t\tINT32;   // signed 32bit*/\n//#endif\n\ntypedef stream_sample_t OPL3SAMPLE;\n/*\n#if (OPL3_SAMPLE_BITS==16)\ntypedef INT16 OPL3SAMPLE;\n#endif\n#if (OPL3_SAMPLE_BITS==8)\ntypedef INT8 OPL3SAMPLE;\n#endif\n*/\n\n//typedef void (*OPL3_TIMERHANDLER)(void *param,int timer,attotime period);\ntypedef void (*OPL3_TIMERHANDLER)(void *param,int timer,int period);\ntypedef void (*OPL3_IRQHANDLER)(void *param,int irq);\ntypedef void (*OPL3_UPDATEHANDLER)(void *param/*,int min_interval_us*/);\n\n\nvoid *ymf262_init(int clock, int rate);\nvoid ymf262_shutdown(void *chip);\nvoid ymf262_reset_chip(void *chip);\nint  ymf262_write(void *chip, int a, int v);\nunsigned char ymf262_read(void *chip, int a);\nint  ymf262_timer_over(void *chip, int c);\nvoid ymf262_update_one(void *chip, OPL3SAMPLE **buffers, int length);\n\nvoid ymf262_set_timer_handler(void *chip, OPL3_TIMERHANDLER TimerHandler, void *param);\nvoid ymf262_set_irq_handler(void *chip, OPL3_IRQHANDLER IRQHandler, void *param);\nvoid ymf262_set_update_handler(void *chip, OPL3_UPDATEHANDLER UpdateHandler, void *param);\n\nvoid ymf262_set_emu_core(UINT8 Emulator);\nvoid ymf262_set_mutemask(void *chip, UINT32 MuteMask);\n\n"
  },
  {
    "path": "VGMPlay/chips/ymf271.c",
    "content": "/*\n    Yamaha YMF271-F \"OPX\" emulator v0.1\n    By R. Belmont.\n    Based in part on YMF278B emulator by R. Belmont and O. Galibert.\n    12June04 update by Toshiaki Nijiura\n    Copyright R. Belmont.\n\n    This software is dual-licensed: it may be used in MAME and properly licensed\n    MAME derivatives under the terms of the MAME license.  For use outside of\n    MAME and properly licensed derivatives, it is available under the\n    terms of the GNU Lesser General Public License (LGPL), version 2.1.\n    You may read the LGPL at http://www.gnu.org/licenses/lgpl.html\n\n    TODO:\n    - A/L bit (alternate loop)\n    - EN and EXT Out bits\n    - Src B and Src NOTE bits\n    - statusreg Busy and End bits\n    - timer register 0x11\n    - ch2/ch3 (4 speakers)\n    - PFM (FM using external PCM waveform)\n    - detune (should be same as on other Yamaha chips)\n    - Acc On bit (some sound effects in viprp1?). The documentation says\n      \"determines if slot output is accumulated(1), or output directly(0)\"\n    - Is memory handling 100% correct? At the moment, seibuspi.c is the only\n      hardware currently emulated that uses external handlers.\n*/\n\n#include <math.h>\n#include \"mamedef.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#ifdef _DEBUG\n#include <stdio.h>\n#endif\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"../stdbool.h\"\n#include \"ymf271.h\"\n\n//#define DEVCB_NULL\t\t\t\t\t\t\t{ DEVCB_TYPE_NULL }\n//#define DEVCB_NULL\t\t\t\t\t\t\tDEVCB_TYPE_NULL\n//#define DEVCB_TYPE_NULL\t\t\t\t(0)\n\n#define VERBOSE\t\t(1)\n\n#define STD_CLOCK\t(16934400)\n\n#define MAXOUT\t\t(+32767)\n#define MINOUT\t\t(-32768)\n\n#define SIN_BITS\t\t10\n#define SIN_LEN\t\t\t(1<<SIN_BITS)\n#define SIN_MASK\t\t(SIN_LEN-1)\n\n#define LFO_LENGTH\t\t256\n#define LFO_SHIFT\t\t8\n#define PLFO_MAX\t\t(+1.0)\n#define PLFO_MIN\t\t(-1.0)\n#define ALFO_MAX\t\t(+65536)\n#define ALFO_MIN\t\t(0)\n\n#define ENV_ATTACK\t\t0\n#define ENV_DECAY1\t\t1\n#define ENV_DECAY2\t\t2\n#define ENV_RELEASE\t\t3\n\n#define OP_INPUT_FEEDBACK   -1\n#define OP_INPUT_NONE       -2\n\n#define ENV_VOLUME_SHIFT\t16\n\n#define INF\t\t-1.0\n\nstatic const double ARTime[64] =\n{\n\tINF,\t\tINF,\t\tINF,\t\tINF,\t\t6188.12,\t4980.68,\t4144.76,\t3541.04,\n\t3094.06,\t2490.34,\t2072.38,\t1770.52,\t1547.03,\t1245.17,\t1036.19,\t885.26,\n\t773.51,\t\t622.59,\t\t518.10,\t\t441.63,\t\t386.76,\t\t311.29,\t\t259.05,\t\t221.32,\n\t193.38,\t\t155.65,\t\t129.52,\t\t110.66,\t\t96.69,\t\t77.82,\t\t64.76,\t\t55.33,\n\t48.34,\t\t38.91,\t\t32.38,\t\t27.66,\t\t24.17,\t\t19.46,\t\t16.19,\t\t13.83,\n\t12.09,\t\t9.73,\t\t8.10,\t\t6.92,\t\t6.04,\t\t4.86,\t\t4.05,\t\t3.46,\n\t3.02,\t\t2.47,\t\t2.14,\t\t1.88,\t\t1.70,\t\t1.38,\t\t1.16,\t\t1.02,\n\t0.88,\t\t0.70,\t\t0.57,\t\t0.48,\t\t0.43,\t\t0.43,\t\t0.43,\t\t0.07\n};\n\nstatic const double DCTime[64] =\n{\n\tINF,\t\tINF,\t\tINF,\t\tINF,\t\t93599.64,\t74837.91,\t62392.02,\t53475.56,\n\t46799.82,\t37418.96,\t31196.01,\t26737.78,\t23399.91,\t18709.48,\t15598.00,\t13368.89,\n\t11699.95,\t9354.74,\t7799.00,\t6684.44,\t5849.98,\t4677.37,\t3899.50,\t3342.22,\n\t2924.99,\t2338.68,\t1949.75,\t1671.11,\t1462.49,\t1169.34,\t974.88,\t\t835.56,\n\t731.25,\t\t584.67,\t\t487.44,\t\t417.78,\t\t365.62,\t\t292.34,\t\t243.72,\t\t208.89,\n\t182.81,\t\t146.17,\t\t121.86,\t\t104.44,\t\t91.41,\t\t73.08,\t\t60.93,\t\t52.22,\n\t45.69,\t\t36.55,\t\t33.85,\t\t26.09,\t\t22.83,\t\t18.28,\t\t15.22,\t\t13.03,\n\t11.41,\t\t9.12,\t\t7.60,\t\t6.51,\t\t5.69,\t\t5.69,\t\t5.69,\t\t5.69\n};\n\n/* Notes about the LFO Frequency Table below:\n\n    There are 2 known errors in the LFO table listed in the original manual.\n\n    Both 201 & 202 are listed as 3.74490.  202 has been computed/corrected to 3.91513\n    232 was listed as 13.35547 but has been replaced with the correct value of 14.35547.\n\n  Corrections are computed values based on formulas by Olivier Galibert & Nicola Salmoria listed below:\n\nLFO period seems easy to compute:\n\nOlivier Galibert's version                       Nicola Salmoria's version\n\nint lfo_period(int entry)             or         int calc_lfo_period(int entry)\n{                                                {\n  int ma, ex;                                      entry = 256 - entry;\n  entry = 256-entry;\n  ma = entry & 15;                                 if (entry < 16)\n                                                   {\n  ex = entry >> 4;                                    return (entry & 0x0f) << 7;\n  if(ex)                                           }\n    return (ma | 16) << (ex+6);                    else\n  else                                             {\n    return ma << 7;                                   int shift = 6 + (entry >> 4);\n}                                                     return (0x10 + (entry & 0x0f)) << shift;\n                                                   }\nlfo_freq = 44100 / lfo_period                    }\n\n*/\n\nstatic const double LFO_frequency_table[256] =\n{\n\t0.00066,\t0.00068,\t0.00070,\t0.00073,\t0.00075,\t0.00078,\t0.00081,\t0.00084,\n\t0.00088,\t0.00091,\t0.00096,\t0.00100,\t0.00105,\t0.00111,\t0.00117,\t0.00124,\n\t0.00131,\t0.00136,\t0.00140,\t0.00145,\t0.00150,\t0.00156,\t0.00162,\t0.00168,\n\t0.00175,\t0.00183,\t0.00191,\t0.00200,\t0.00210,\t0.00221,\t0.00234,\t0.00247,\n\t0.00263,\t0.00271,\t0.00280,\t0.00290,\t0.00300,\t0.00312,\t0.00324,\t0.00336,\n\t0.00350,\t0.00366,\t0.00382,\t0.00401,\t0.00421,\t0.00443,\t0.00467,\t0.00495,\n\t0.00526,\t0.00543,\t0.00561,\t0.00580,\t0.00601,\t0.00623,\t0.00647,\t0.00673,\n\t0.00701,\t0.00731,\t0.00765,\t0.00801,\t0.00841,\t0.00885,\t0.00935,\t0.00990,\n\t0.01051,\t0.01085,\t0.01122,\t0.01160,\t0.01202,\t0.01246,\t0.01294,\t0.01346,\n\t0.01402,\t0.01463,\t0.01529,\t0.01602,\t0.01682,\t0.01771,\t0.01869,\t0.01979,\n\t0.02103,\t0.02171,\t0.02243,\t0.02320,\t0.02403,\t0.02492,\t0.02588,\t0.02692,\n\t0.02804,\t0.02926,\t0.03059,\t0.03204,\t0.03365,\t0.03542,\t0.03738,\t0.03958,\n\t0.04206,\t0.04341,\t0.04486,\t0.04641,\t0.04807,\t0.04985,\t0.05176,\t0.05383,\n\t0.05608,\t0.05851,\t0.06117,\t0.06409,\t0.06729,\t0.07083,\t0.07477,\t0.07917,\n\t0.08411,\t0.08683,\t0.08972,\t0.09282,\t0.09613,\t0.09969,\t0.10353,\t0.10767,\n\t0.11215,\t0.11703,\t0.12235,\t0.12817,\t0.13458,\t0.14167,\t0.14954,\t0.15833,\n\t0.16823,\t0.17365,\t0.17944,\t0.18563,\t0.19226,\t0.19938,\t0.20705,\t0.21533,\n\t0.22430,\t0.23406,\t0.24470,\t0.25635,\t0.26917,\t0.28333,\t0.29907,\t0.31666,\n\t0.33646,\t0.34731,\t0.35889,\t0.37126,\t0.38452,\t0.39876,\t0.41410,\t0.43066,\n\t0.44861,\t0.46811,\t0.48939,\t0.51270,\t0.53833,\t0.56666,\t0.59814,\t0.63333,\n\t0.67291,\t0.69462,\t0.71777,\t0.74252,\t0.76904,\t0.79753,\t0.82820,\t0.86133,\n\t0.89722,\t0.93623,\t0.97878,\t1.02539,\t1.07666,\t1.13333,\t1.19629,\t1.26666,\n\t1.34583,\t1.38924,\t1.43555,\t1.48505,\t1.53809,\t1.59509,\t1.65640,\t1.72266,\n\t1.79443,\t1.87245,\t1.95756,\t2.05078,\t2.15332,\t2.26665,\t2.39258,\t2.53332,\n\t2.69165,\t2.77848,\t2.87109,\t2.97010,\t3.07617,\t3.19010,\t3.31280,\t3.44531,\n\t3.58887,\t3.74490,\t3.91513,\t4.10156,\t4.30664,\t4.53331,\t4.78516,\t5.06664,\n\t5.38330,\t5.55696,\t5.74219,\t5.94019,\t6.15234,\t6.38021,\t6.62560,\t6.89062,\n\t7.17773,\t7.48981,\t7.83026,\t8.20312,\t8.61328,\t9.06661,\t9.57031,\t10.13327,\n\t10.76660,\t11.11391,\t11.48438,\t11.88039,\t12.30469,\t12.76042,\t13.25120,\t13.78125,\n\t14.35547,\t14.97962,\t15.66051,\t16.40625,\t17.22656,\t18.13322,\t19.14062,\t20.26654,\n\t21.53320,\t22.96875,\t24.60938,\t26.50240,\t28.71094,\t31.32102,\t34.45312,\t38.28125,\n\t43.06641,\t49.21875,\t57.42188,\t68.90625,\t86.13281,\t114.84375,\t172.26562,\t344.53125\n};\n\nstatic const int RKS_Table[32][8] =\n{\n\t{  0,  0,  0,  0,  0,  2,  4,  8 },\n\t{  0,  0,  0,  0,  1,  3,  5,  9 },\n\t{  0,  0,  0,  1,  2,  4,  6, 10 },\n\t{  0,  0,  0,  1,  3,  5,  7, 11 },\n\t{  0,  0,  1,  2,  4,  6,  8, 12 },\n\t{  0,  0,  1,  2,  5,  7,  9, 13 },\n\t{  0,  0,  1,  3,  6,  8, 10, 14 },\n\t{  0,  0,  1,  3,  7,  9, 11, 15 },\n\t{  0,  1,  2,  4,  8, 10, 12, 16 },\n\t{  0,  1,  2,  4,  9, 11, 13, 17 },\n\t{  0,  1,  2,  5, 10, 12, 14, 18 },\n\t{  0,  1,  2,  5, 11, 13, 15, 19 },\n\t{  0,  1,  3,  6, 12, 14, 16, 20 },\n\t{  0,  1,  3,  6, 13, 15, 17, 21 },\n\t{  0,  1,  3,  7, 14, 16, 18, 22 },\n\t{  0,  1,  3,  7, 15, 17, 19, 23 },\n\t{  0,  2,  4,  8, 16, 18, 20, 24 },\n\t{  0,  2,  4,  8, 17, 19, 21, 25 },\n\t{  0,  2,  4,  9, 18, 20, 22, 26 },\n\t{  0,  2,  4,  9, 19, 21, 23, 27 },\n\t{  0,  2,  5, 10, 20, 22, 24, 28 },\n\t{  0,  2,  5, 10, 21, 23, 25, 29 },\n\t{  0,  2,  5, 11, 22, 24, 26, 30 },\n\t{  0,  2,  5, 11, 23, 25, 27, 31 },\n\t{  0,  3,  6, 12, 24, 26, 28, 31 },\n\t{  0,  3,  6, 12, 25, 27, 29, 31 },\n\t{  0,  3,  6, 13, 26, 28, 30, 31 },\n\t{  0,  3,  6, 13, 27, 29, 31, 31 },\n\t{  0,  3,  7, 14, 28, 30, 31, 31 },\n\t{  0,  3,  7, 14, 29, 31, 31, 31 },\n\t{  0,  3,  7, 15, 30, 31, 31, 31 },\n\t{  0,  3,  7, 15, 31, 31, 31, 31 },\n};\n\nstatic const double multiple_table[16] = { 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };\n\nstatic const double pow_table[16] = { 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 0.5, 1, 2, 4, 8, 16, 32, 64 };\n\nstatic const double fs_frequency[4] = { 1.0/1.0, 1.0/2.0, 1.0/4.0, 1.0/8.0 };\n\nstatic const double channel_attenuation_table[16] =\n{\n\t0.0, 2.5, 6.0, 8.5, 12.0, 14.5, 18.1, 20.6, 24.1, 26.6, 30.1, 32.6, 36.1, 96.1, 96.1, 96.1\n};\n\nstatic const int modulation_level[8] = { 16, 8, 4, 2, 1, 32, 64, 128 };\n\n// feedback_level * 16\nstatic const int feedback_level[8] = { 0, 1, 2, 4, 8, 16, 32, 64 };\n\n// slot mapping assists\nstatic const int fm_tab[16] = { 0, 1, 2, -1, 3, 4, 5, -1, 6, 7, 8, -1, 9, 10, 11, -1 };\nstatic const int pcm_tab[16] = { 0, 4, 8, -1, 12, 16, 20, -1, 24, 28, 32, -1, 36, 40, 44, -1 };\n\n\ntypedef struct\n{\n\tUINT8 ext_en;\n\tUINT8 ext_out;\n\tUINT8 lfoFreq;\n\tUINT8 lfowave;\n\tUINT8 pms, ams;\n\tUINT8 detune;\n\tUINT8 multiple;\n\tUINT8 tl;\n\tUINT8 keyscale;\n\tUINT8 ar;\n\tUINT8 decay1rate, decay2rate;\n\tUINT8 decay1lvl;\n\tUINT8 relrate;\n\tUINT8 block;\n\tUINT8 fns_hi;\n\tUINT32 fns;\n\tUINT8 feedback;\n\tUINT8 waveform;\n\tUINT8 accon;\n\tUINT8 algorithm;\n\tUINT8 ch0_level, ch1_level, ch2_level, ch3_level;\n\n\tUINT32 startaddr;\n\tUINT32 loopaddr;\n\tUINT32 endaddr;\n\tUINT8 altloop;\n\tUINT8 fs;\n\tUINT8 srcnote, srcb;\n\n\tUINT32 step;\n\tUINT64 stepptr;\n\n\tUINT8 active;\n\tUINT8 bits;\n\n\t// envelope generator\n\tINT32 volume;\n\tINT32 env_state;\n\tINT32 env_attack_step;\t\t// volume increase step in attack state\n\tINT32 env_decay1_step;\n\tINT32 env_decay2_step;\n\tINT32 env_release_step;\n\n\tINT64 feedback_modulation0;\n\tINT64 feedback_modulation1;\n\n\tINT32 lfo_phase, lfo_step;\n\tINT32 lfo_amplitude;\n\tdouble lfo_phasemod;\n} YMF271Slot;\n\ntypedef struct\n{\n\tUINT8 sync, pfm;\n\tUINT8 Muted;\n} YMF271Group;\n\ntypedef struct\n{\n\t// lookup tables\n\tINT16 *lut_waves[8];\n\tdouble *lut_plfo[4][8];\n\tint *lut_alfo[4];\n\tdouble lut_ar[64];\n\tdouble lut_dc[64];\n\tdouble lut_lfo[256];\n\tint lut_attenuation[16];\n\tint lut_total_level[128];\n\tint lut_env_volume[256];\n\n\tYMF271Slot slots[48];\n\tYMF271Group groups[12];\n\n\tUINT8 regs_main[0x10];\n\n\tUINT32 timerA, timerB;\n\tUINT32 timerAVal, timerBVal;\n\tUINT32 irqstate;\n\tUINT8  status;\n\tUINT8  enable;\n\n\tUINT32 ext_address;\n\tUINT8 ext_rw;\n\tUINT8 ext_readlatch;\n\n\tUINT8 *mem_base;\n\tUINT32 mem_size;\n\tUINT32 clock;\n\n\t//emu_timer *timA, *timB;\n\t//sound_stream * stream;\n\tINT32 *mix_buffer;\n\t//const device_config *device;\n\n\t//devcb_resolved_read8 ext_mem_read;\n\t//devcb_resolved_write8 ext_mem_write;\n\t//void (*irq_callback)(const device_config *, int);\n\t//void (*irq_callback)(int);\n} YMF271Chip;\n\n\n#define MAX_CHIPS\t0x10\nstatic YMF271Chip YMF271Data[MAX_CHIPS];\n\n/*INLINE YMF271Chip *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_YMF271);\n\treturn (YMF271Chip *)device->token;\n}*/\n\nstatic UINT8 ymf271_read_memory(YMF271Chip *chip, UINT32 offset);\n\n\nINLINE void calculate_step(YMF271Slot *slot)\n{\n\tdouble st;\n\n\tif (slot->waveform == 7)\n\t{\n\t\t// external waveform (PCM)\n\t\tst = (double)(2 * (slot->fns | 2048)) * pow_table[slot->block] * fs_frequency[slot->fs];\n\t\tst = st * multiple_table[slot->multiple];\n\n\t\t// LFO phase modulation\n\t\tst *= slot->lfo_phasemod;\n\n\t\tst /= (double)(524288/65536);\t\t// pre-multiply with 65536\n\n\t\tslot->step = (UINT32)st;\n\t}\n\telse\n\t{\n\t\t// internal waveform (FM)\n\t\tst = (double)(2 * slot->fns) * pow_table[slot->block];\n\t\tst = st * multiple_table[slot->multiple] * (double)(SIN_LEN);\n\n\t\t// LFO phase modulation\n\t\tst *= slot->lfo_phasemod;\n\n\t\tst /= (double)(536870912/65536);\t// pre-multiply with 65536\n\n\t\tslot->step = (UINT32)st;\n\t}\n}\n\nINLINE bool check_envelope_end(YMF271Slot *slot)\n{\n\tif (slot->volume <= 0)\n\t{\n\t\tslot->active = 0;\n\t\tslot->volume = 0;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nstatic void update_envelope(YMF271Slot *slot)\n{\n\tswitch (slot->env_state)\n\t{\n\t\tcase ENV_ATTACK:\n\t\t{\n\t\t\tslot->volume += slot->env_attack_step;\n\n\t\t\tif (slot->volume >= (255 << ENV_VOLUME_SHIFT))\n\t\t\t{\n\t\t\t\tslot->volume = (255 << ENV_VOLUME_SHIFT);\n\t\t\t\tslot->env_state = ENV_DECAY1;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase ENV_DECAY1:\n\t\t{\n\t\t\tint decay_level = 255 - (slot->decay1lvl << 4);\n\t\t\tslot->volume -= slot->env_decay1_step;\n\n\t\t\tif (!check_envelope_end(slot) && (slot->volume >> ENV_VOLUME_SHIFT) <= decay_level)\n\t\t\t{\n\t\t\t\tslot->env_state = ENV_DECAY2;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase ENV_DECAY2:\n\t\t{\n\t\t\tslot->volume -= slot->env_decay2_step;\n\t\t\tcheck_envelope_end(slot);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase ENV_RELEASE:\n\t\t{\n\t\t\tslot->volume -= slot->env_release_step;\n\t\t\tcheck_envelope_end(slot);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nINLINE int get_keyscaled_rate(int rate, int keycode, int keyscale)\n{\n\tint newrate = rate + RKS_Table[keycode][keyscale];\n\n\tif (newrate > 63)\n\t{\n\t\tnewrate = 63;\n\t}\n\tif (newrate < 0)\n\t{\n\t\tnewrate = 0;\n\t}\n\treturn newrate;\n}\n\nINLINE int get_internal_keycode(int block, int fns)\n{\n\tint n43;\n\tif (fns < 0x780)\n\t{\n\t\tn43 = 0;\n\t}\n\telse if (fns < 0x900)\n\t{\n\t\tn43 = 1;\n\t}\n\telse if (fns < 0xa80)\n\t{\n\t\tn43 = 2;\n\t}\n\telse\n\t{\n\t\tn43 = 3;\n\t}\n\n\treturn ((block & 7) * 4) + n43;\n}\n\nINLINE int get_external_keycode(int block, int fns)\n{\n\tint n43;\n\tif (fns < 0x100)\n\t{\n\t\tn43 = 0;\n\t}\n\telse if (fns < 0x300)\n\t{\n\t\tn43 = 1;\n\t}\n\telse if (fns < 0x500)\n\t{\n\t\tn43 = 2;\n\t}\n\telse\n\t{\n\t\tn43 = 3;\n\t}\n\n\treturn ((block & 7) * 4) + n43;\n}\n\nstatic void init_envelope(YMF271Chip *chip, YMF271Slot *slot)\n{\n\tint keycode, rate;\n\tint decay_level = 255 - (slot->decay1lvl << 4);\n\n\tif (slot->waveform != 7)\n\t{\n\t\tkeycode = get_internal_keycode(slot->block, slot->fns);\n\t}\n\telse\n\t{\n\t\tkeycode = get_external_keycode(slot->block, slot->fns & 0x7ff);\n\t\t/* keycode = (keycode + slot->srcb * 4 + slot->srcnote) / 2; */ // not sure\n\t}\n\n\t// init attack state\n\trate = get_keyscaled_rate(slot->ar * 2, keycode, slot->keyscale);\n\tslot->env_attack_step = (rate < 4) ? 0 : (int)(((double)(255-0) / chip->lut_ar[rate]) * 65536.0);\n\n\t// init decay1 state\n\trate = get_keyscaled_rate(slot->decay1rate * 2, keycode, slot->keyscale);\n\tslot->env_decay1_step = (rate < 4) ? 0 : (int)(((double)(255-decay_level) / chip->lut_dc[rate]) * 65536.0);\n\n\t// init decay2 state\n\trate = get_keyscaled_rate(slot->decay2rate * 2, keycode, slot->keyscale);\n\tslot->env_decay2_step = (rate < 4) ? 0 : (int)(((double)(255-0) / chip->lut_dc[rate]) * 65536.0);\n\n\t// init release state\n\t//rate = get_keyscaled_rate(slot->relrate * 4, keycode, slot->keyscale);\n\t// improved rate as tested by GTheGuardian and kirishima\n\trate = get_keyscaled_rate(slot->relrate * 1.75, keycode, slot->keyscale);\n\tslot->env_release_step = (rate < 4) ? 0 : (int)(((double)(255-0) / chip->lut_ar[rate]) * 65536.0);\n\n\tslot->volume = (255-160) << ENV_VOLUME_SHIFT;\t\t// -60db\n\tslot->env_state = ENV_ATTACK;\n}\n\nstatic void init_lfo(YMF271Chip *chip, YMF271Slot *slot)\n{\n\tslot->lfo_phase = 0;\n\tslot->lfo_amplitude = 0;\n\tslot->lfo_phasemod = 0;\n\n\tslot->lfo_step = (int)((((double)LFO_LENGTH * chip->lut_lfo[slot->lfoFreq]) / 44100.0) * 256.0);\n}\n\nINLINE void update_lfo(YMF271Chip *chip, YMF271Slot *slot)\n{\n\tslot->lfo_phase += slot->lfo_step;\n\n\tslot->lfo_amplitude = chip->lut_alfo[slot->lfowave][(slot->lfo_phase >> LFO_SHIFT) & (LFO_LENGTH-1)];\n\tslot->lfo_phasemod = chip->lut_plfo[slot->lfowave][slot->pms][(slot->lfo_phase >> LFO_SHIFT) & (LFO_LENGTH-1)];\n\n\tcalculate_step(slot);\n}\n\nINLINE int calculate_slot_volume(YMF271Chip *chip, YMF271Slot *slot)\n{\n\t// Note: Actually everyone of these stores only INT32 (16.16 fixed point),\n\t//       but the calculations need INT64.\n\tINT32 volume;\n\tINT64 env_volume;\n\tINT64 lfo_volume = 65536;\n\n\tswitch (slot->ams)\n\t{\n\t\tcase 0: lfo_volume = 65536; break;\t// 0dB\n\t\tcase 1: lfo_volume = 65536 - ((slot->lfo_amplitude * 33124) >> 16); break;\t// 5.90625dB\n\t\tcase 2: lfo_volume = 65536 - ((slot->lfo_amplitude * 16742) >> 16); break;\t// 11.8125dB\n\t\tcase 3: lfo_volume = 65536 - ((slot->lfo_amplitude * 4277) >> 16); break;\t// 23.625dB\n\t}\n\n\tenv_volume = (chip->lut_env_volume[255 - (slot->volume >> ENV_VOLUME_SHIFT)] * lfo_volume) >> 16;\n\n\tvolume = (env_volume * chip->lut_total_level[slot->tl]) >> 16;\n\n\treturn volume;\n}\n\nstatic void update_pcm(YMF271Chip *chip, int slotnum, INT32 *mixp, int length)\n{\n\tint i;\n\tINT64 final_volume;\n\tINT16 sample;\n\tINT64 ch0_vol, ch1_vol; //, ch2_vol, ch3_vol;\n\n\tYMF271Slot *slot = &chip->slots[slotnum];\n\n\tif (!slot->active)\n\t{\n\t\treturn;\n\t}\n\n#ifdef _DEBUG\n\tif (slot->waveform != 7)\n\t{\n\t\tlogerror(\"Waveform %d in update_pcm !!!\\n\", slot->waveform);\n\t}\n#endif\n\n\tfor (i = 0; i < length; i++)\n\t{\n\t\t// loop\n\t\tif ((slot->stepptr>>16) > slot->endaddr)\n\t\t{\n\t\t\tslot->stepptr = slot->stepptr - ((UINT64)slot->endaddr<<16) + ((UINT64)slot->loopaddr<<16);\n\t\t\tif ((slot->stepptr>>16) > slot->endaddr)\n\t\t\t{\n\t\t\t\t// overflow\n\t\t\t\tslot->stepptr &= 0xffff;\n\t\t\t\tslot->stepptr |= ((UINT64)slot->loopaddr<<16);\n\t\t\t\tif ((slot->stepptr>>16) > slot->endaddr)\n\t\t\t\t{\n\t\t\t\t\t// still overflow? (triggers in rdft2, rarely)\n\t\t\t\t\tslot->stepptr &= 0xffff;\n\t\t\t\t\tslot->stepptr |= ((UINT64)slot->endaddr<<16);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (slot->bits == 8)\n\t\t{\n\t\t\t// 8bit\n\t\t\tsample = ymf271_read_memory(chip, slot->startaddr + (slot->stepptr>>16))<<8;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// 12bit\n\t\t\tif (slot->stepptr & 0x10000)\n\t\t\t\tsample = ymf271_read_memory(chip, slot->startaddr + (slot->stepptr>>17)*3 + 2)<<8 | ((ymf271_read_memory(chip, slot->startaddr + (slot->stepptr>>17)*3 + 1) << 4) & 0xf0);\n\t\t\telse\n\t\t\t\tsample = ymf271_read_memory(chip, slot->startaddr + (slot->stepptr>>17)*3)<<8 | (ymf271_read_memory(chip, slot->startaddr + (slot->stepptr>>17)*3 + 1) & 0xf0);\n\t\t}\n\n\t\tupdate_envelope(slot);\n\t\tupdate_lfo(chip, slot);\n\n\t\tfinal_volume = calculate_slot_volume(chip, slot);\n\n\t\tch0_vol = (final_volume * chip->lut_attenuation[slot->ch0_level]) >> 16;\n\t\tch1_vol = (final_volume * chip->lut_attenuation[slot->ch1_level]) >> 16;\n//\t\tch2_vol = (final_volume * chip->lut_attenuation[slot->ch2_level]) >> 16;\n//\t\tch3_vol = (final_volume * chip->lut_attenuation[slot->ch3_level]) >> 16;\n\n\t\tif (ch0_vol > 65536) ch0_vol = 65536;\n\t\tif (ch1_vol > 65536) ch1_vol = 65536;\n\n\t\t*mixp++ += (sample * ch0_vol) >> 16;\n\t\t*mixp++ += (sample * ch1_vol) >> 16;\n\n\t\t// go to next step\n\t\tslot->stepptr += slot->step;\n\t}\n}\n\n// calculates the output of one FM operator\nstatic INT64 calculate_op(YMF271Chip *chip, int slotnum, INT64 inp)\n{\n\tYMF271Slot *slot = &chip->slots[slotnum];\n\tINT64 env, slot_output, slot_input = 0;\n\n\tupdate_envelope(slot);\n\tupdate_lfo(chip, slot);\n\tenv = calculate_slot_volume(chip, slot);\n\n\tif (inp == OP_INPUT_FEEDBACK)\n\t{\n\t\t// from own feedback\n\t\tslot_input = (slot->feedback_modulation0 + slot->feedback_modulation1) / 2;\n\t\tslot->feedback_modulation0 = slot->feedback_modulation1;\n\t}\n\telse if (inp != OP_INPUT_NONE)\n\t{\n\t\t// from previous slot output\n\t\tslot_input = ((inp << (SIN_BITS-2)) * modulation_level[slot->feedback]);\n\t}\n\n\tslot_output = chip->lut_waves[slot->waveform][((slot->stepptr + slot_input) >> 16) & SIN_MASK];\n\tslot_output = (slot_output * env) >> 16;\n\tslot->stepptr += slot->step;\n\n\treturn slot_output;\n}\n\nstatic void set_feedback(YMF271Chip *chip, int slotnum, INT64 inp)\n{\n\tYMF271Slot *slot = &chip->slots[slotnum];\n\tslot->feedback_modulation1 = (((inp << (SIN_BITS-2)) * feedback_level[slot->feedback]) / 16);\n}\n\n//static STREAM_UPDATE( ymf271_update )\nvoid ymf271_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\tint i, j;\n\tint op;\n\tINT32 *mixp;\n\t//YMF271Chip *chip = (YMF271Chip *)param;\n\tYMF271Chip *chip = &YMF271Data[ChipID];\n\n\tmemset(chip->mix_buffer, 0, sizeof(chip->mix_buffer[0])*samples*2);\n\n\tfor (j = 0; j < 12; j++)\n\t{\n\t\tYMF271Group *slot_group = &chip->groups[j];\n\t\tmixp = &chip->mix_buffer[0];\n\n\t\tif (slot_group->Muted)\n\t\t\tcontinue;\n\n#ifdef _DEBUG\n\t\tif (slot_group->pfm && slot_group->sync != 3)\n\t\t{\n\t\t\tlogerror(\"ymf271 Group %d: PFM, Sync = %d, Waveform Slot1 = %d, Slot2 = %d, Slot3 = %d, Slot4 = %d\\n\",\n\t\t\t\tj, slot_group->sync, chip->slots[j+0].waveform, chip->slots[j+12].waveform, chip->slots[j+24].waveform, chip->slots[j+36].waveform);\n\t\t}\n#endif\n\n\t\tswitch (slot_group->sync)\n\t\t{\n\t\t\t// 4 operator FM\n\t\t\tcase 0:\n\t\t\t{\n\t\t\t\tint slot1 = j + (0*12);\n\t\t\t\tint slot2 = j + (1*12);\n\t\t\t\tint slot3 = j + (2*12);\n\t\t\t\tint slot4 = j + (3*12);\n\t\t\t\t//mixp = chip->mix_buffer;\n\n\t\t\t\tif (chip->slots[slot1].active)\n\t\t\t\t{\n\t\t\t\t\tfor (i = 0; i < samples; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tINT64 output1 = 0, output2 = 0, output3 = 0, output4 = 0;\n\t\t\t\t\t\tINT64 phase_mod1 = 0, phase_mod2 = 0, phase_mod3 = 0;\n\t\t\t\t\t\tswitch (chip->slots[slot1].algorithm)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// <--------|\n\t\t\t\t\t\t\t// +--[S1]--|--+--[S3]--+--[S2]--+--[S4]-->\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\tphase_mod2 = calculate_op(chip, slot2, phase_mod3);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, phase_mod2);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t// <-----------------|\n\t\t\t\t\t\t\t// +--[S1]--+--[S3]--|--+--[S2]--+--[S4]-->\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod3);\n\t\t\t\t\t\t\t\tphase_mod2 = calculate_op(chip, slot2, phase_mod3);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, phase_mod2);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t// <--------|\n\t\t\t\t\t\t\t// +--[S1]--|\n\t\t\t\t\t\t\t//          |\n\t\t\t\t\t\t\t//  --[S3]--+--[S2]--+--[S4]-->\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\tphase_mod2 = calculate_op(chip, slot2, (phase_mod1 + phase_mod3) / 1);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, phase_mod2);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//          <--------|\n\t\t\t\t\t\t\t//          +--[S1]--|\n\t\t\t\t\t\t\t//                   |\n\t\t\t\t\t\t\t//  --[S3]--+--[S2]--+--[S4]-->\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\tphase_mod2 = calculate_op(chip, slot2, phase_mod3);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, (phase_mod1 + phase_mod2) / 1);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//              --[S2]--|\n\t\t\t\t\t\t\t// <--------|           |\n\t\t\t\t\t\t\t// +--[S1]--|--+--[S3]--+--[S4]-->\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\tphase_mod2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, (phase_mod3 + phase_mod2) / 1);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//           --[S2]-----|\n\t\t\t\t\t\t\t// <-----------------|  |\n\t\t\t\t\t\t\t// +--[S1]--+--[S3]--|--+--[S4]-->\n\t\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod3);\n\t\t\t\t\t\t\t\tphase_mod2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, (phase_mod3 + phase_mod2) / 1);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//  --[S2]-----+--[S4]--|\n\t\t\t\t\t\t\t//                      |\n\t\t\t\t\t\t\t// <--------|           |\n\t\t\t\t\t\t\t// +--[S1]--|--+--[S3]--+-->\n\t\t\t\t\t\t\tcase 6:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\toutput3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\tphase_mod2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, phase_mod2);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//  --[S2]--+--[S4]-----|\n\t\t\t\t\t\t\t//                      |\n\t\t\t\t\t\t\t// <-----------------|  |\n\t\t\t\t\t\t\t// +--[S1]--+--[S3]--|--+-->\n\t\t\t\t\t\t\tcase 7:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod3);\n\t\t\t\t\t\t\t\toutput3 = phase_mod3;\n\t\t\t\t\t\t\t\tphase_mod2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, phase_mod2);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//  --[S3]--+--[S2]--+--[S4]--|\n\t\t\t\t\t\t\t//                            |\n\t\t\t\t\t\t\t// <--------|                 |\n\t\t\t\t\t\t\t// +--[S1]--|-----------------+-->\n\t\t\t\t\t\t\tcase 8:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\toutput1 = phase_mod1;\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\tphase_mod2 = calculate_op(chip, slot2, phase_mod3);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, phase_mod2);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//          <--------|\n\t\t\t\t\t\t\t//          +--[S1]--|\n\t\t\t\t\t\t\t//                   |\n\t\t\t\t\t\t\t//  --[S3]--|        |\n\t\t\t\t\t\t\t//  --[S2]--+--[S4]--+-->\n\t\t\t\t\t\t\tcase 9:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\toutput1 = phase_mod1;\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\tphase_mod2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, (phase_mod3 + phase_mod2) / 1);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//              --[S4]--|\n\t\t\t\t\t\t\t//              --[S2]--|\n\t\t\t\t\t\t\t// <--------|           |\n\t\t\t\t\t\t\t// +--[S1]--|--+--[S3]--+-->\n\t\t\t\t\t\t\tcase 10:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\toutput3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//           --[S4]-----|\n\t\t\t\t\t\t\t//           --[S2]-----|\n\t\t\t\t\t\t\t// <-----------------|  |\n\t\t\t\t\t\t\t// +--[S1]--+--[S3]--|--+-->\n\t\t\t\t\t\t\tcase 11:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod3);\n\t\t\t\t\t\t\t\toutput3 = phase_mod3;\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//             |--+--[S4]--|\n\t\t\t\t\t\t\t// <--------|  |--+--[S3]--|\n\t\t\t\t\t\t\t// +--[S1]--|--|--+--[S2]--+-->\n\t\t\t\t\t\t\tcase 12:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\toutput3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, phase_mod1);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, phase_mod1);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//  --[S3]--+--[S2]--|\n\t\t\t\t\t\t\t//                   |\n\t\t\t\t\t\t\t//  --[S4]-----------|\n\t\t\t\t\t\t\t// <--------|        |\n\t\t\t\t\t\t\t// +--[S1]--|--------+-->\n\t\t\t\t\t\t\tcase 13:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\toutput1 = phase_mod1;\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, phase_mod3);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//  --[S2]-----+--[S4]--|\n\t\t\t\t\t\t\t//                      |\n\t\t\t\t\t\t\t// <--------|  +--[S3]--|\n\t\t\t\t\t\t\t// +--[S1]--|--|--------+-->\n\t\t\t\t\t\t\tcase 14:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\toutput1 = phase_mod1;\n\t\t\t\t\t\t\t\toutput3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\tphase_mod2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, phase_mod2);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//  --[S4]-----|\n\t\t\t\t\t\t\t//  --[S2]-----|\n\t\t\t\t\t\t\t//  --[S3]-----|\n\t\t\t\t\t\t\t// <--------|  |\n\t\t\t\t\t\t\t// +--[S1]--|--+-->\n\t\t\t\t\t\t\tcase 15:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\toutput1 = phase_mod1;\n\t\t\t\t\t\t\t\toutput3 = calculate_op(chip, slot3, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput4 = calculate_op(chip, slot4, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t*mixp++ += ((output1 * chip->lut_attenuation[chip->slots[slot1].ch0_level]) +\n\t\t\t\t\t\t\t\t\t(output2 * chip->lut_attenuation[chip->slots[slot2].ch0_level]) +\n\t\t\t\t\t\t\t\t\t(output3 * chip->lut_attenuation[chip->slots[slot3].ch0_level]) +\n\t\t\t\t\t\t\t\t\t(output4 * chip->lut_attenuation[chip->slots[slot4].ch0_level])) >> 16;\n\t\t\t\t\t\t*mixp++ += ((output1 * chip->lut_attenuation[chip->slots[slot1].ch1_level]) +\n\t\t\t\t\t\t\t\t\t(output2 * chip->lut_attenuation[chip->slots[slot2].ch1_level]) +\n\t\t\t\t\t\t\t\t\t(output3 * chip->lut_attenuation[chip->slots[slot3].ch1_level]) +\n\t\t\t\t\t\t\t\t\t(output4 * chip->lut_attenuation[chip->slots[slot4].ch1_level])) >> 16;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// 2x 2 operator FM\n\t\t\tcase 1:\n\t\t\t{\n\t\t\t\tfor (op = 0; op < 2; op++)\n\t\t\t\t{\n\t\t\t\t\tint slot1 = j + ((op + 0) * 12);\n\t\t\t\t\tint slot3 = j + ((op + 2) * 12);\n\n\t\t\t\t\tmixp = chip->mix_buffer;\n\t\t\t\t\tif (chip->slots[slot1].active)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (i = 0; i < samples; i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tINT64 output1 = 0, output3 = 0;\n\t\t\t\t\t\t\tINT64 phase_mod1, phase_mod3 = 0;\n\t\t\t\t\t\t\tswitch (chip->slots[slot1].algorithm & 3)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// <--------|\n\t\t\t\t\t\t\t\t// +--[S1]--|--+--[S3]-->\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\t\toutput3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t// <-----------------|\n\t\t\t\t\t\t\t\t// +--[S1]--+--[S3]--|-->\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod3);\n\t\t\t\t\t\t\t\t\toutput3 = phase_mod3;\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t//  --[S3]-----|\n\t\t\t\t\t\t\t\t// <--------|  |\n\t\t\t\t\t\t\t\t// +--[S1]--|--+-->\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\t\toutput1 = phase_mod1;\n\t\t\t\t\t\t\t\t\toutput3 = calculate_op(chip, slot3, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t\t// <--------|  +--[S3]--|\n\t\t\t\t\t\t\t\t// +--[S1]--|--|--------+-->\n\t\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\t\toutput1 = phase_mod1;\n\t\t\t\t\t\t\t\t\toutput3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t*mixp++ += ((output1 * chip->lut_attenuation[chip->slots[slot1].ch0_level]) +\n\t\t\t\t\t\t\t\t\t\t(output3 * chip->lut_attenuation[chip->slots[slot3].ch0_level])) >> 16;\n\t\t\t\t\t\t\t*mixp++ += ((output1 * chip->lut_attenuation[chip->slots[slot1].ch1_level]) +\n\t\t\t\t\t\t\t\t\t\t(output3 * chip->lut_attenuation[chip->slots[slot3].ch1_level])) >> 16;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// 3 operator FM + PCM\n\t\t\tcase 2:\n\t\t\t{\n\t\t\t\tint slot1 = j + (0*12);\n\t\t\t\tint slot2 = j + (1*12);\n\t\t\t\tint slot3 = j + (2*12);\n\t\t\t\t//mixp = chip->mix_buffer;\n\n\t\t\t\tif (chip->slots[slot1].active)\n\t\t\t\t{\n\t\t\t\t\tfor (i = 0; i < samples; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tINT64 output1 = 0, output2 = 0, output3 = 0;\n\t\t\t\t\t\tINT64 phase_mod1 = 0, phase_mod3 = 0;\n\t\t\t\t\t\tswitch (chip->slots[slot1].algorithm & 7)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// <--------|\n\t\t\t\t\t\t\t// +--[S1]--|--+--[S3]--+--[S2]-->\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, phase_mod3);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t// <-----------------|\n\t\t\t\t\t\t\t// +--[S1]--+--[S3]--|--+--[S2]-->\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod3);\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, phase_mod3);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//  --[S3]-----|\n\t\t\t\t\t\t\t// <--------|  |\n\t\t\t\t\t\t\t// +--[S1]--|--+--[S2]-->\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, (phase_mod1 + phase_mod3) / 1);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//  --[S3]--+--[S2]--|\n\t\t\t\t\t\t\t// <--------|        |\n\t\t\t\t\t\t\t// +--[S1]--|--------+-->\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\toutput1 = phase_mod1;\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, phase_mod3);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//              --[S2]--|\n\t\t\t\t\t\t\t// <--------|           |\n\t\t\t\t\t\t\t// +--[S1]--|--+--[S3]--+-->\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\toutput3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//              --[S2]--|\n\t\t\t\t\t\t\t// <-----------------|  |\n\t\t\t\t\t\t\t// +--[S1]--+--[S3]--|--+-->\n\t\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tphase_mod3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod3);\n\t\t\t\t\t\t\t\toutput3 = phase_mod3;\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//  --[S2]-----|\n\t\t\t\t\t\t\t//  --[S3]-----|\n\t\t\t\t\t\t\t// <--------|  |\n\t\t\t\t\t\t\t// +--[S1]--|--+-->\n\t\t\t\t\t\t\tcase 6:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\toutput1 = phase_mod1;\n\t\t\t\t\t\t\t\toutput3 = calculate_op(chip, slot3, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t//              --[S2]--|\n\t\t\t\t\t\t\t// <--------|  +--[S3]--|\n\t\t\t\t\t\t\t// +--[S1]--|--|--------+-->\n\t\t\t\t\t\t\tcase 7:\n\t\t\t\t\t\t\t\tphase_mod1 = calculate_op(chip, slot1, OP_INPUT_FEEDBACK);\n\t\t\t\t\t\t\t\tset_feedback(chip, slot1, phase_mod1);\n\t\t\t\t\t\t\t\toutput1 = phase_mod1;\n\t\t\t\t\t\t\t\toutput3 = calculate_op(chip, slot3, phase_mod1);\n\t\t\t\t\t\t\t\toutput2 = calculate_op(chip, slot2, OP_INPUT_NONE);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t*mixp++ += ((output1 * chip->lut_attenuation[chip->slots[slot1].ch0_level]) +\n\t\t\t\t\t\t\t\t\t(output2 * chip->lut_attenuation[chip->slots[slot2].ch0_level]) +\n\t\t\t\t\t\t\t\t\t(output3 * chip->lut_attenuation[chip->slots[slot3].ch0_level])) >> 16;\n\t\t\t\t\t\t*mixp++ += ((output1 * chip->lut_attenuation[chip->slots[slot1].ch1_level]) +\n\t\t\t\t\t\t\t\t\t(output2 * chip->lut_attenuation[chip->slots[slot2].ch1_level]) +\n\t\t\t\t\t\t\t\t\t(output3 * chip->lut_attenuation[chip->slots[slot3].ch1_level])) >> 16;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tmixp = chip->mix_buffer;\n\t\t\t\tupdate_pcm(chip, j + (3*12), mixp, samples);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// PCM\n\t\t\tcase 3:\n\t\t\t{\n\t\t\t\tupdate_pcm(chip, j + (0*12), mixp, samples);\n\t\t\t\tupdate_pcm(chip, j + (1*12), mixp, samples);\n\t\t\t\tupdate_pcm(chip, j + (2*12), mixp, samples);\n\t\t\t\tupdate_pcm(chip, j + (3*12), mixp, samples);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tmixp = chip->mix_buffer;\n\tfor (i = 0; i < samples; i++)\n\t{\n\t\toutputs[0][i] = (*mixp++)>>2;\n\t\toutputs[1][i] = (*mixp++)>>2;\n\t}\n}\n\nstatic void write_register(YMF271Chip *chip, int slotnum, int reg, UINT8 data)\n{\n\tYMF271Slot *slot = &chip->slots[slotnum];\n\n\tswitch (reg)\n\t{\n\t\tcase 0x0:\n\t\t\tslot->ext_en = (data & 0x80) ? 1 : 0;\n\t\t\tslot->ext_out = (data>>3)&0xf;\n\n\t\t\tif (data & 1)\n\t\t\t{\n\t\t\t\t// key on\n\t\t\t\tslot->step = 0;\n\t\t\t\tslot->stepptr = 0;\n\n\t\t\t\tslot->active = 1;\n\n\t\t\t\tcalculate_step(slot);\n\t\t\t\tinit_envelope(chip, slot);\n\t\t\t\tinit_lfo(chip, slot);\n\t\t\t\tslot->feedback_modulation0 = 0;\n\t\t\t\tslot->feedback_modulation1 = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (slot->active)\n\t\t\t\t{\n\t\t\t\t\tslot->env_state = ENV_RELEASE;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 0x1:\n\t\t\tslot->lfoFreq = data;\n\t\t\tbreak;\n\n\t\tcase 0x2:\n\t\t\tslot->lfowave = data & 3;\n\t\t\tslot->pms = (data >> 3) & 0x7;\n\t\t\tslot->ams = (data >> 6) & 0x3;\n\t\t\tbreak;\n\n\t\tcase 0x3:\n\t\t\tslot->multiple = data & 0xf;\n\t\t\tslot->detune = (data >> 4) & 0x7;\n\t\t\tbreak;\n\n\t\tcase 0x4:\n\t\t\tslot->tl = data & 0x7f;\n\t\t\tbreak;\n\n\t\tcase 0x5:\n\t\t\tslot->ar = data & 0x1f;\n\t\t\tslot->keyscale = (data >> 5) & 0x7;\n\t\t\tbreak;\n\n\t\tcase 0x6:\n\t\t\tslot->decay1rate = data & 0x1f;\n\t\t\tbreak;\n\n\t\tcase 0x7:\n\t\t\tslot->decay2rate = data & 0x1f;\n\t\t\tbreak;\n\n\t\tcase 0x8:\n\t\t\tslot->relrate = data & 0xf;\n\t\t\tslot->decay1lvl = (data >> 4) & 0xf;\n\t\t\tbreak;\n\n\t\tcase 0x9:\n\t\t\t// write frequency and block here\n\t\t\tslot->fns = (slot->fns_hi << 8 & 0x0f00) | data;\n\t\t\tslot->block = slot->fns_hi >> 4 & 0xf;\n\t\t\tbreak;\n\n\t\tcase 0xa:\n\t\t\tslot->fns_hi = data;\n\t\t\tbreak;\n\n\t\tcase 0xb:\n\t\t\tslot->waveform = data & 0x7;\n\t\t\tslot->feedback = (data >> 4) & 0x7;\n\t\t\tslot->accon = (data & 0x80) ? 1 : 0;\n\t\t\tbreak;\n\n\t\tcase 0xc:\n\t\t\tslot->algorithm = data & 0xf;\n\t\t\tbreak;\n\n\t\tcase 0xd:\n\t\t\tslot->ch0_level = data >> 4;\n\t\t\tslot->ch1_level = data & 0xf;\n\t\t\tbreak;\n\n\t\tcase 0xe:\n\t\t\tslot->ch2_level = data >> 4;\n\t\t\tslot->ch3_level = data & 0xf;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\nstatic void ymf271_write_fm(YMF271Chip *chip, int bank, UINT8 address, UINT8 data)\n{\n\tint groupnum = fm_tab[address & 0xf];\n\tint reg = (address >> 4) & 0xf;\n\tint sync_reg;\n\tint sync_mode;\n\n\tif (groupnum == -1)\n\t{\n\t\tlogerror(\"ymf271_write_fm invalid group %02X %02X\\n\", address, data);\n\t\treturn;\n\t}\n\n\t// check if the register is a synchronized register\n\tsync_reg = 0;\n\tswitch (reg)\n\t{\n\t\tcase 0:\n\t\tcase 9:\n\t\tcase 10:\n\t\tcase 12:\n\t\tcase 13:\n\t\tcase 14:\n\t\t\tsync_reg = 1;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t// check if the slot is key on slot for synchronizing\n\tsync_mode = 0;\n\tswitch (chip->groups[groupnum].sync)\n\t{\n\t\t// 4 slot mode\n\t\tcase 0:\n\t\t\tif (bank == 0)\n\t\t\t\tsync_mode = 1;\n\t\t\tbreak;\n\n\t\t// 2x 2 slot mode\n\t\tcase 1:\n\t\t\tif (bank == 0 || bank == 1)\n\t\t\t\tsync_mode = 1;\n\t\t\tbreak;\n\n\t\t// 3 slot + 1 slot mode\n\t\tcase 2:\n\t\t\tif (bank == 0)\n\t\t\t\tsync_mode = 1;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t// key-on slot & synced register\n\tif (sync_mode && sync_reg)\n\t{\n\t\tswitch (chip->groups[groupnum].sync)\n\t\t{\n\t\t\t// 4 slot mode\n\t\t\tcase 0:\n\t\t\t\twrite_register(chip, (12 * 0) + groupnum, reg, data);\n\t\t\t\twrite_register(chip, (12 * 1) + groupnum, reg, data);\n\t\t\t\twrite_register(chip, (12 * 2) + groupnum, reg, data);\n\t\t\t\twrite_register(chip, (12 * 3) + groupnum, reg, data);\n\t\t\t\tbreak;\n\n\t\t\t// 2x 2 slot mode\n\t\t\tcase 1:\n\t\t\t\tif (bank == 0)\n\t\t\t\t{\n\t\t\t\t\t// Slot 1 - Slot 3\n\t\t\t\t\twrite_register(chip, (12 * 0) + groupnum, reg, data);\n\t\t\t\t\twrite_register(chip, (12 * 2) + groupnum, reg, data);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Slot 2 - Slot 4\n\t\t\t\t\twrite_register(chip, (12 * 1) + groupnum, reg, data);\n\t\t\t\t\twrite_register(chip, (12 * 3) + groupnum, reg, data);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t// 3 slot + 1 slot mode (1 slot is handled normally)\n\t\t\tcase 2:\n\t\t\t\twrite_register(chip, (12 * 0) + groupnum, reg, data);\n\t\t\t\twrite_register(chip, (12 * 1) + groupnum, reg, data);\n\t\t\t\twrite_register(chip, (12 * 2) + groupnum, reg, data);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\t// write register normally\n\t\twrite_register(chip, (12 * bank) + groupnum, reg, data);\n\t}\n}\n\nstatic void ymf271_write_pcm(YMF271Chip *chip, UINT8 address, UINT8 data)\n{\n\tint slotnum = pcm_tab[address & 0xf];\n\tYMF271Slot *slot;\n\tif (slotnum == -1)\n\t{\n\t\tlogerror(\"ymf271_write_pcm invalid slot %02X %02X\\n\", address, data);\n\t\treturn;\n\t}\n\tslot = &chip->slots[slotnum];\n\n\tswitch ((address >> 4) & 0xf)\n\t{\n\t\tcase 0x0:\n\t\t\tslot->startaddr &= ~0xff;\n\t\t\tslot->startaddr |= data;\n\t\t\tbreak;\n\n\t\tcase 0x1:\n\t\t\tslot->startaddr &= ~0xff00;\n\t\t\tslot->startaddr |= data<<8;\n\t\t\tbreak;\n\n\t\tcase 0x2:\n\t\t\tslot->startaddr &= ~0xff0000;\n\t\t\tslot->startaddr |= (data & 0x7f)<<16;\n\t\t\tslot->altloop = (data & 0x80) ? 1 : 0;\n\t\t\t//if (slot->altloop)\n\t\t\t//\tpopmessage(\"ymf271 A/L, contact MAMEdev\");\n\t\t\tbreak;\n\n\t\tcase 0x3:\n\t\t\tslot->endaddr &= ~0xff;\n\t\t\tslot->endaddr |= data;\n\t\t\tbreak;\n\n\t\tcase 0x4:\n\t\t\tslot->endaddr &= ~0xff00;\n\t\t\tslot->endaddr |= data<<8;\n\t\t\tbreak;\n\n\t\tcase 0x5:\n\t\t\tslot->endaddr &= ~0xff0000;\n\t\t\tslot->endaddr |= (data & 0x7f)<<16;\n\t\t\tbreak;\n\n\t\tcase 0x6:\n\t\t\tslot->loopaddr &= ~0xff;\n\t\t\tslot->loopaddr |= data;\n\t\t\tbreak;\n\n\t\tcase 0x7:\n\t\t\tslot->loopaddr &= ~0xff00;\n\t\t\tslot->loopaddr |= data<<8;\n\t\t\tbreak;\n\n\t\tcase 0x8:\n\t\t\tslot->loopaddr &= ~0xff0000;\n\t\t\tslot->loopaddr |= (data & 0x7f)<<16;\n\t\t\tbreak;\n\n\t\tcase 0x9:\n\t\t\tslot->fs = data & 0x3;\n\t\t\tslot->bits = (data & 0x4) ? 12 : 8;\n\t\t\tslot->srcnote = (data >> 3) & 0x3;\n\t\t\tslot->srcb = (data >> 5) & 0x7;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n/*static TIMER_CALLBACK( ymf271_timer_a_tick )\n{\n\tYMF271Chip *chip = (YMF271Chip *)ptr;\n\n\tchip->status |= 1;\n\n\tif (chip->enable & 4)\n\t{\n\t\tchip->irqstate |= 1;\n\t\tif (chip->irq_callback) chip->irq_callback(chip->device, 1);\n\t}\n}\n\nstatic TIMER_CALLBACK( ymf271_timer_b_tick )\n{\n\tYMF271Chip *chip = (YMF271Chip *)ptr;\n\n\tchip->status |= 2;\n\n\tif (chip->enable & 8)\n\t{\n\t\tchip->irqstate |= 2;\n\t\tif (chip->irq_callback) chip->irq_callback(chip->device, 1);\n\t}\n}*/\n\nstatic UINT8 ymf271_read_memory(YMF271Chip *chip, UINT32 offset)\n{\n\t/*if (m_ext_read_handler.isnull())\n\t{\n\t\tif (offset < chip->mem_size)\n\t\t\treturn chip->mem_base[offset];\n\n\t\t// 8MB chip limit (shouldn't happen)\n\t\telse if (offset > 0x7fffff)\n\t\t\treturn chip->mem_base[offset & 0x7fffff];\n\n\t\telse\n\t\t\treturn 0;\n\t}\n\telse\n\t\treturn m_ext_read_handler(offset);*/\n\t\n\toffset &= 0x7FFFFF;\n\tif (offset < chip->mem_size)\n\t\treturn chip->mem_base[offset];\n\telse\n\t\treturn 0;\n}\n\nstatic void ymf271_write_timer(YMF271Chip *chip, UINT8 address, UINT8 data)\n{\n\tif ((address & 0xf0) == 0)\n\t{\n\t\tint groupnum = fm_tab[address & 0xf];\n\t\tYMF271Group *group;\n\t\tif (groupnum == -1)\n\t\t{\n\t\t\tlogerror(\"ymf271_write_timer invalid group %02X %02X\\n\", address, data);\n\t\t\treturn;\n\t\t}\n\t\tgroup = &chip->groups[groupnum];\n\n\t\tgroup->sync = data & 0x3;\n\t\tgroup->pfm = data >> 7;\n\t}\n\telse\n\t{\n\t\tswitch (address)\n\t\t{\n\t\t\tcase 0x10:\n\t\t\t\tchip->timerA = data;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x11:\n\t\t\t\t// According to Yamaha's documentation, this sets timer A upper 2 bits\n\t\t\t\t// (it says timer A is 10 bits). But, PCB audio recordings proves\n\t\t\t\t// otherwise: it doesn't affect timer A frequency. (see ms32.c tetrisp)\n\t\t\t\t// Does this register have another function regarding timer A/B?\n\t\t\t\tbreak;\n\n\t\t\tcase 0x12:\n\t\t\t\tchip->timerB = data;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x13:\n\t\t\t\t// timer A load\n\t\t\t\tif (~chip->enable & data & 1)\n\t\t\t\t{\n\t\t\t\t\t//attotime period = attotime::from_hz(chip->clock) * (384 * 4 * (256 - chip->timerA));\n\t\t\t\t\t//chip->timA->adjust((data & 1) ? period : attotime::never, 0);\n\t\t\t\t}\n\n\t\t\t\t// timer B load\n\t\t\t\tif (~chip->enable & data & 2)\n\t\t\t\t{\n\t\t\t\t\t//attotime period = attotime::from_hz(chip->clock) * (384 * 16 * (256 - chip->timerB));\n\t\t\t\t\t//chip->timB->adjust((data & 2) ? period : attotime::never, 0);\n\t\t\t\t}\n\n\t\t\t\t// timer A reset\n\t\t\t\tif (data & 0x10)\n\t\t\t\t{\n\t\t\t\t\tchip->irqstate &= ~1;\n\t\t\t\t\tchip->status &= ~1;\n\n\t\t\t\t\t//if (!chip->irq_handler.isnull() && ~chip->irqstate & 2)\n\t\t\t\t\t//\tchip->irq_handler(0);\n\t\t\t\t}\n\n\t\t\t\t// timer B reset\n\t\t\t\tif (data & 0x20)\n\t\t\t\t{\n\t\t\t\t\tchip->irqstate &= ~2;\n\t\t\t\t\tchip->status &= ~2;\n\n\t\t\t\t\t//if (!chip->irq_handler.isnull() && ~chip->irqstate & 1)\n\t\t\t\t\t//\tchip->irq_handler(0);\n\t\t\t\t}\n\n\t\t\t\tchip->enable = data;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x14:\n\t\t\t\tchip->ext_address &= ~0xff;\n\t\t\t\tchip->ext_address |= data;\n\t\t\t\tbreak;\n\t\t\tcase 0x15:\n\t\t\t\tchip->ext_address &= ~0xff00;\n\t\t\t\tchip->ext_address |= data << 8;\n\t\t\t\tbreak;\n\t\t\tcase 0x16:\n\t\t\t\tchip->ext_address &= ~0xff0000;\n\t\t\t\tchip->ext_address |= (data & 0x7f) << 16;\n\t\t\t\tchip->ext_rw = (data & 0x80) ? 1 : 0;\n\t\t\t\tbreak;\n\t\t\tcase 0x17:\n\t\t\t\tchip->ext_address = (chip->ext_address + 1) & 0x7fffff;\n\t\t\t\t//if (!chip->ext_rw && !chip->ext_write_handler.isnull())\n\t\t\t\t//\tchip->ext_write_handler(chip->ext_address, data);\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n//WRITE8_DEVICE_HANDLER( ymf271_w )\nvoid ymf271_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//YMF271Chip *chip = get_safe_token(device);\n\tYMF271Chip *chip = &YMF271Data[ChipID];\n\n\tchip->regs_main[offset & 0xf] = data;\n\n\tswitch (offset & 0xf)\n\t{\n\t\tcase 0x0:\n\t\tcase 0x2:\n\t\tcase 0x4:\n\t\tcase 0x6:\n\t\tcase 0x8:\n\t\tcase 0xc:\n\t\t\t// address regs\n\t\t\tbreak;\n\n\t\tcase 0x1:\n\t\t\tymf271_write_fm(chip, 0, chip->regs_main[0x0], data);\n\t\t\tbreak;\n\n\t\tcase 0x3:\n\t\t\tymf271_write_fm(chip, 1, chip->regs_main[0x2], data);\n\t\t\tbreak;\n\n\t\tcase 0x5:\n\t\t\tymf271_write_fm(chip, 2, chip->regs_main[0x4], data);\n\t\t\tbreak;\n\n\t\tcase 0x7:\n\t\t\tymf271_write_fm(chip, 3, chip->regs_main[0x6], data);\n\t\t\tbreak;\n\n\t\tcase 0x9:\n\t\t\tymf271_write_pcm(chip, chip->regs_main[0x8], data);\n\t\t\tbreak;\n\n\t\tcase 0xd:\n\t\t\tymf271_write_timer(chip, chip->regs_main[0xc], data);\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n//READ8_DEVICE_HANDLER( ymf271_r )\nUINT8 ymf271_r(UINT8 ChipID, offs_t offset)\n{\n\t//YMF271Chip *chip = get_safe_token(device);\n\tYMF271Chip *chip = &YMF271Data[ChipID];\n\n\tswitch (offset & 0xf)\n\t{\n\t\tcase 0x0:\n\t\t\treturn chip->status;\n\n\t\tcase 0x1:\n\t\t\t// statusreg 2\n\t\t\treturn 0;\n\n\t\tcase 0x2:\n\t\t{\n\t\t\tUINT8 ret;\n\t\t\tif (!chip->ext_rw)\n\t\t\t\treturn 0xff;\n\n\t\t\tret = chip->ext_readlatch;\n\t\t\tchip->ext_address = (chip->ext_address + 1) & 0x7fffff;\n\t\t\tchip->ext_readlatch = ymf271_read_memory(chip, chip->ext_address);\n\t\t\treturn ret;\n\t\t}\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn 0xff;\n}\n\nstatic void init_tables(YMF271Chip *chip)\n{\n\tint i,j;\n\tdouble clock_correction;\n\n\tfor (i = 0; i < 8; i++)\n\t\tchip->lut_waves[i] = (INT16*)malloc(sizeof(INT16) * SIN_LEN);\n\n\tfor (i = 0; i < 4*8; i++)\n\t\tchip->lut_plfo[i>>3][i&7] = (double*)malloc(sizeof(double) * LFO_LENGTH);\n\n\tfor (i = 0; i < 4; i++)\n\t\tchip->lut_alfo[i] = (int*)malloc(sizeof(int) * LFO_LENGTH);\n\t\n\tfor (i=0; i < SIN_LEN; i++)\n\t{\n\t\tdouble m = sin( ((i*2)+1) * M_PI / SIN_LEN );\n\t\tdouble m2 = sin( ((i*4)+1) * M_PI / SIN_LEN );\n\n\t\t// Waveform 0: sin(wt)    (0 <= wt <= 2PI)\n\t\tchip->lut_waves[0][i] = (INT16)(m * MAXOUT);\n\n\t\t// Waveform 1: sin?(wt)   (0 <= wt <= PI)     -sin?(wt)  (PI <= wt <= 2PI)\n\t\tchip->lut_waves[1][i] = (i < (SIN_LEN/2)) ? (INT16)((m * m) * MAXOUT) : (INT16)((m * m) * MINOUT);\n\n\t\t// Waveform 2: sin(wt)    (0 <= wt <= PI)     -sin(wt)   (PI <= wt <= 2PI)\n\t\tchip->lut_waves[2][i] = (i < (SIN_LEN/2)) ? (INT16)(m * MAXOUT) : (INT16)(-m * MAXOUT);\n\n\t\t// Waveform 3: sin(wt)    (0 <= wt <= PI)     0\n\t\tchip->lut_waves[3][i] = (i < (SIN_LEN/2)) ? (INT16)(m * MAXOUT) : 0;\n\n\t\t// Waveform 4: sin(2wt)   (0 <= wt <= PI)     0\n\t\tchip->lut_waves[4][i] = (i < (SIN_LEN/2)) ? (INT16)(m2 * MAXOUT) : 0;\n\n\t\t// Waveform 5: |sin(2wt)| (0 <= wt <= PI)     0\n\t\tchip->lut_waves[5][i] = (i < (SIN_LEN/2)) ? (INT16)(fabs(m2) * MAXOUT) : 0;\n\n\t\t// Waveform 6:     1      (0 <= wt <= 2PI)\n\t\tchip->lut_waves[6][i] = (INT16)(1 * MAXOUT);\n\n\t\tchip->lut_waves[7][i] = 0;\n\t}\n\n\tfor (i = 0; i < LFO_LENGTH; i++)\n\t{\n\t\tint tri_wave;\n\t\tdouble ftri_wave, fsaw_wave;\n\t\tdouble plfo[4];\n\n\t\t// LFO phase modulation\n\t\tplfo[0] = 0;\n\n\t\tfsaw_wave = ((i % (LFO_LENGTH/2)) * PLFO_MAX) / (double)((LFO_LENGTH/2)-1);\n\t\tplfo[1] = (i < (LFO_LENGTH/2)) ? fsaw_wave : fsaw_wave - PLFO_MAX;\n\n\t\tplfo[2] = (i < (LFO_LENGTH/2)) ? PLFO_MAX : PLFO_MIN;\n\n\t\tftri_wave = ((i % (LFO_LENGTH/4)) * PLFO_MAX) / (double)(LFO_LENGTH/4);\n\t\tswitch (i / (LFO_LENGTH/4))\n\t\t{\n\t\t\tcase 0: plfo[3] = ftri_wave; break;\n\t\t\tcase 1: plfo[3] = PLFO_MAX - ftri_wave; break;\n\t\t\tcase 2: plfo[3] = 0 - ftri_wave; break;\n\t\t\tcase 3: plfo[3] = 0 - (PLFO_MAX - ftri_wave); break;\n\t\t\tdefault: plfo[3] = 0; /*assert(0);*/ break;\n\t\t}\n\n\t\tfor (j = 0; j < 4; j++)\n\t\t{\n\t\t\tchip->lut_plfo[j][0][i] = pow(2.0, 0.0);\n\t\t\tchip->lut_plfo[j][1][i] = pow(2.0, (3.378 * plfo[j]) / 1200.0);\n\t\t\tchip->lut_plfo[j][2][i] = pow(2.0, (5.0646 * plfo[j]) / 1200.0);\n\t\t\tchip->lut_plfo[j][3][i] = pow(2.0, (6.7495 * plfo[j]) / 1200.0);\n\t\t\tchip->lut_plfo[j][4][i] = pow(2.0, (10.1143 * plfo[j]) / 1200.0);\n\t\t\tchip->lut_plfo[j][5][i] = pow(2.0, (20.1699 * plfo[j]) / 1200.0);\n\t\t\tchip->lut_plfo[j][6][i] = pow(2.0, (40.1076 * plfo[j]) / 1200.0);\n\t\t\tchip->lut_plfo[j][7][i] = pow(2.0, (79.307 * plfo[j]) / 1200.0);\n\t\t}\n\n\t\t// LFO amplitude modulation\n\t\tchip->lut_alfo[0][i] = 0;\n\n\t\tchip->lut_alfo[1][i] = ALFO_MAX - ((i * ALFO_MAX) / LFO_LENGTH);\n\n\t\tchip->lut_alfo[2][i] = (i < (LFO_LENGTH/2)) ? ALFO_MAX : ALFO_MIN;\n\n\t\ttri_wave = ((i % (LFO_LENGTH/2)) * ALFO_MAX) / (LFO_LENGTH/2);\n\t\tchip->lut_alfo[3][i] = (i < (LFO_LENGTH/2)) ? ALFO_MAX-tri_wave : tri_wave;\n\t}\n\t\n\tfor (i = 0; i < 256; i++)\n\t{\n\t\tchip->lut_env_volume[i] = (int)(65536.0 / pow(10.0, ((double)i / (256.0 / 96.0)) / 20.0));\n\t}\n\n\tfor (i = 0; i < 16; i++)\n\t{\n\t\tchip->lut_attenuation[i] = (int)(65536.0 / pow(10.0, channel_attenuation_table[i] / 20.0));\n\t}\n\tfor (i = 0; i < 128; i++)\n\t{\n\t\tdouble db = 0.75 * (double)i;\n\t\tchip->lut_total_level[i] = (int)(65536.0 / pow(10.0, db / 20.0));\n\t}\n\n\t// timing may use a non-standard XTAL\n\tclock_correction = (double)(STD_CLOCK) / (double)(chip->clock);\n\tfor (i = 0; i < 256; i++)\n\t{\n\t\tchip->lut_lfo[i] = LFO_frequency_table[i] * clock_correction;\n\t}\n\n\tfor (i = 0; i < 64; i++)\n\t{\n\t\t// attack/release rate in number of samples\n\t\tchip->lut_ar[i] = (ARTime[i] * clock_correction * 44100.0) / 1000.0;\n\t}\n\tfor (i = 0; i < 64; i++)\n\t{\n\t\t// decay rate in number of samples\n\t\tchip->lut_dc[i] = (DCTime[i] * clock_correction * 44100.0) / 1000.0;\n\t}\n}\n\n/*static void init_state(YMF271Chip *chip, const device_config *device)\n{\n\tint i;\n\n\tfor (i = 0; i < ARRAY_LENGTH(chip->slots); i++)\n\t{\n\t\tstate_save_register_device_item(device, i, chip->slots[i].ext_out);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].lfoFreq);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].pms);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].ams);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].detune);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].multiple);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].tl);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].keyscale);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].ar);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].decay1rate);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].decay2rate);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].decay1lvl);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].relrate);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].fns);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].block);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].feedback);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].waveform);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].accon);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].algorithm);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].ch0_level);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].ch1_level);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].ch2_level);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].ch3_level);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].startaddr);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].loopaddr);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].endaddr);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].fs);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].srcnote);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].srcb);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].step);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].stepptr);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].active);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].bits);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].volume);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].env_state);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].env_attack_step);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].env_decay1_step);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].env_decay2_step);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].env_release_step);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].feedback_modulation0);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].feedback_modulation1);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].lfo_phase);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].lfo_step);\n\t\tstate_save_register_device_item(device, i, chip->slots[i].lfo_amplitude);\n\t}\n\n\tfor (i = 0; i < sizeof(chip->groups) / sizeof(chip->groups[0]); i++)\n\t{\n\t\tstate_save_register_device_item(device, i, chip->groups[i].sync);\n\t\tstate_save_register_device_item(device, i, chip->groups[i].pfm);\n\t}\n\n\tstate_save_register_device_item(device, 0, chip->timerA);\n\tstate_save_register_device_item(device, 0, chip->timerB);\n\tstate_save_register_device_item(device, 0, chip->timerAVal);\n\tstate_save_register_device_item(device, 0, chip->timerBVal);\n\tstate_save_register_device_item(device, 0, chip->irqstate);\n\tstate_save_register_device_item(device, 0, chip->status);\n\tstate_save_register_device_item(device, 0, chip->enable);\n\tstate_save_register_device_item(device, 0, chip->reg0);\n\tstate_save_register_device_item(device, 0, chip->reg1);\n\tstate_save_register_device_item(device, 0, chip->reg2);\n\tstate_save_register_device_item(device, 0, chip->reg3);\n\tstate_save_register_device_item(device, 0, chip->pcmreg);\n\tstate_save_register_device_item(device, 0, chip->timerreg);\n\tstate_save_register_device_item(device, 0, chip->ext_address);\n\tstate_save_register_device_item(device, 0, chip->ext_read);\n}*/\n\n//static DEVICE_START( ymf271 )\nint device_start_ymf271(UINT8 ChipID, int clock)\n{\n\t//static const ymf271_interface defintrf = { DEVCB_NULL };\n\t//const ymf271_interface *intf;\n\tint i;\n\t//YMF271Chip *chip = get_safe_token(device);\n\tYMF271Chip *chip;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &YMF271Data[ChipID];\n\t//chip->device = device;\n\tchip->clock = clock;\n\n\t//intf = (device->static_config != NULL) ? (const ymf271_interface *)device->static_config : &defintrf;\n\n\tchip->mem_size = 0x00;\n\tchip->mem_base = NULL;\n\n\tinit_tables(chip);\n\t//init_state(chip);\n\t//chip->stream = stream_create(device, 0, 2, device->clock/384, chip, ymf271_update);\n\n\t//chip->mix_buffer = auto_alloc_array(machine, INT32, 44100*2);\n\tchip->mix_buffer = (INT32*)malloc(44100*2 * sizeof(INT32));\n\t\n\tfor (i = 0; i < 12; i ++)\n\t\tchip->groups[i].Muted = 0x00;\n\n\treturn clock/384;\n}\n\n//static DEVICE_STOP( ymf271 )\nvoid device_stop_ymf271(UINT8 ChipID)\n{\n\tint i;\n\tYMF271Chip *chip = &YMF271Data[ChipID];\n\t\n\tfree(chip->mem_base);\tchip->mem_base = NULL;\n\t\n\tfor (i=0; i < 8; i++)\n\t{\n\t\tfree(chip->lut_waves[i]);\n\t\tchip->lut_waves[i] = NULL;\n\t}\n\tfor (i = 0; i < 4*8; i++)\n\t{\n\t\tfree(chip->lut_plfo[i>>3][i&7]);\n\t\tchip->lut_plfo[i>>3][i&7] = NULL;\n\t}\n\n\tfor (i = 0; i < 4; i++)\n\t{\n\t\tfree(chip->lut_alfo[i]);\n\t\tchip->lut_alfo[i] = NULL;\n\t}\n\t\n\tfree(chip->mix_buffer);\n\tchip->mix_buffer = NULL;\n\t\n\treturn;\n}\n\n//static DEVICE_RESET( ymf271 )\nvoid device_reset_ymf271(UINT8 ChipID)\n{\n\tint i;\n\t//YMF271Chip *chip = get_safe_token(device);\n\tYMF271Chip *chip = &YMF271Data[ChipID];\n\n\tfor (i = 0; i < 48; i++)\n\t{\n\t\tchip->slots[i].active = 0;\n\t\tchip->slots[i].volume = 0;\n\t}\n\n\t// reset timers and IRQ\n\t//chip->timA->reset();\n\t//chip->timB->reset();\n\n\tchip->irqstate = 0;\n\tchip->status = 0;\n\tchip->enable = 0;\n\n\t//if (!chip->irq_handler.isnull())\n\t//\tchip->irq_handler(0);\n}\n\nvoid ymf271_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t  const UINT8* ROMData)\n{\n\tYMF271Chip *chip = &YMF271Data[ChipID];\n\t\n\tif (chip->mem_size != ROMSize)\n\t{\n\t\tchip->mem_base = (UINT8*)realloc(chip->mem_base, ROMSize);\n\t\tchip->mem_size = ROMSize;\n\t\tmemset(chip->mem_base, 0xFF, ROMSize);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(chip->mem_base + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\nvoid ymf271_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tYMF271Chip *chip = &YMF271Data[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 12; CurChn ++)\n\t\tchip->groups[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( ymf271 )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(YMF271Chip); \t\t\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ymf271 );\t\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->reset = DEVICE_RESET_NAME( ymf271 );\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YMF271\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Yamaha FM\");\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n"
  },
  {
    "path": "VGMPlay/chips/ymf271.h",
    "content": "#pragma once\n\n//#include \"devcb.h\"\n\n//typedef struct _ymf271_interface ymf271_interface;\n//struct _ymf271_interface\n//{\n//\t//devcb_read8 ext_read;\t\t/* external memory read */\n//\t//devcb_write8 ext_write;\t/* external memory write */\n//\t//void (*irq_callback)(const device_config *device, int state);\t/* irq callback */\n//\tvoid (*irq_callback)(int state);\t/* irq callback */\n//};\n\n/*READ8_DEVICE_HANDLER( ymf271_r );\nWRITE8_DEVICE_HANDLER( ymf271_w );\n\nDEVICE_GET_INFO( ymf271 );\n#define SOUND_YMF271 DEVICE_GET_INFO_NAME( ymf271 )*/\n\nvoid ymf271_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_ymf271(UINT8 ChipID, int clock);\nvoid device_stop_ymf271(UINT8 ChipID);\nvoid device_reset_ymf271(UINT8 ChipID);\n\nUINT8 ymf271_r(UINT8 ChipID, offs_t offset);\nvoid ymf271_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ymf271_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t  const UINT8* ROMData);\n\nvoid ymf271_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/chips/ymf278b.c",
    "content": "/*\n\n   YMF278B  FM + Wave table Synthesizer (OPL4)\n\n   Timer and PCM YMF278B.  The FM is shared with the ymf262.\n\n   This chip roughly splits the difference between the Sega 315-5560 MultiPCM\n   (Multi32, Model 1/2) and YMF 292-F SCSP (later Model 2, STV, Saturn, Model 3).\n\n   Features as listed in LSI-4MF2782 data sheet:\n    FM Synthesis (same as YMF262)\n     1. Sound generation mode\n         Two-operater mode\n          Generates eighteen voices or fifteen voices plus five rhythm sounds simultaneously\n         Four-operator mode\n          Generates six voices in four-operator mode plus six voices in two-operator mode simultaneously,\n          or generates six voices in four-operator mode plus three voices in two-operator mode plus five\n          rhythm sounds simultaneously\n     2. Eight selectable waveforms\n     3. Stereo output\n    Wave Table Synthesis\n     1. Generates twenty-four voices simultaneously\n     2. 44.1kHz sampling rate for output sound data\n     3. Selectable from 8-bit, 12-bit and 16-bit word lengths for wave data\n     4. Stereo output (16-stage panpot for each voice)\n    Wave Data\n     1. Accepts 32M bit external memory at maximum\n     2. Up to 512 wave tables\n     3. External ROM or SRAM can be connected. With SRAM connected, the CPU can download wave data\n     4. Outputs chip select signals for 1Mbit, 4Mbit, 8Mbit or 16Mbit memory\n     5. Can be directly connected to the Yamaha YRW801 (Wave data ROM)\n        Features of YRW801 as listed in LSI 4RW801A2\n          Built-in wave data of tones which comply with GM system Level 1\n           Melody tone ....... 128 tones\n           Percussion tone ...  47 tones\n          16Mbit capacity (2,097,152word x 8)\n\n   By R. Belmont and O. Galibert.\n\n   Copyright R. Belmont and O. Galibert.\n\n   This software is dual-licensed: it may be used in MAME and properly licensed\n   MAME derivatives under the terms of the MAME license.  For use outside of\n   MAME and properly licensed derivatives, it is available under the\n   terms of the GNU Lesser General Public License (LGPL), version 2.1.\n   You may read the LGPL at http://www.gnu.org/licenses/lgpl.html\n\n   Changelog:\n   Sep. 8, 2002 - fixed ymf278b_compute_rate when OCT is negative (RB)\n   Dec. 11, 2002 - added ability to set non-standard clock rates (RB)\n                   fixed envelope target for release (fixes missing\n           instruments in hotdebut).\n                   Thanks to Team Japump! for MP3s from a real PCB.\n           fixed crash if MAME is run with no sound.\n   June 4, 2003 -  Changed to dual-license with LGPL for use in OpenMSX.\n                   OpenMSX contributed a bugfix where looped samples were\n            not being addressed properly, causing pitch fluctuation.\n   August 15, 2010 - Backport to MAME-style C from OpenMSX\n*/\n\n#include <math.h>\n#include \"mamedef.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n//#include \"cpuintrf.h\"\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include <stdio.h>\n#include <string.h>\n#include \"ymf262.h\"\n#include \"ymf278b.h\"\n\ntypedef struct\n{\n\tUINT32 startaddr;\n\tUINT32 loopaddr;\n\tUINT32 endaddr;\n\tUINT32 step;\t/* fixed-point frequency step */\n\tUINT32 stepptr;\t/* fixed-point pointer into the sample */\n\tUINT16 pos;\n\tINT16 sample1, sample2;\n\n\tINT32 env_vol;\n\t\n\tINT32 lfo_cnt;\n\tINT32 lfo_step;\n\tINT32 lfo_max;\n\t\n\tINT16 wave;\t\t/* wavetable number */\n\tINT16 FN;\t\t/* f-number */\n\tINT8 OCT;\t\t/* octave */\n\tINT8 PRVB;\t\t/* pseudo-reverb */\n\tINT8 LD;\t\t/* level direct */\n\tINT8 TL;\t\t/* total level */\n\tINT8 pan;\t\t/* panpot */\n\tINT8 lfo;\t\t/* LFO */\n\tINT8 vib;\t\t/* vibrato */\n\tINT8 AM;\t\t/* AM level */\n\n\tINT8 AR;\n\tINT8 D1R;\n\tINT32 DL;\n\tINT8 D2R;\n\tINT8 RC;\t\t/* rate correction */\n\tINT8 RR;\n\n\tINT8 bits;\t\t/* width of the samples */\n\tINT8 active;\t\t/* slot keyed on */\n\t\n\tINT8 state;\n\tINT8 lfo_active;\n\t\n\tUINT8 Muted;\n} YMF278BSlot;\n\ntypedef struct\n{\n\tYMF278BSlot slots[24];\n\t\n\tUINT32 eg_cnt;\t/* Global envelope generator counter. */\n\t\n\tINT8 wavetblhdr;\n\tINT8 memmode;\n\tINT32 memadr;\n\n\tUINT8 exp;\n\n\tINT32 fm_l, fm_r;\n\tINT32 pcm_l, pcm_r;\n\n\t//UINT8 timer_a_count, timer_b_count, enable, current_irq;\n\t//emu_timer *timer_a, *timer_b;\n\t//int irq_line;\n\n\tUINT8 port_A, port_B, port_C;\n\t//void (*irq_callback)(const device_config *, int);\n\tvoid (*irq_callback)(int);\n\t//const device_config *device;\n\n\tUINT32 ROMSize;\n\tUINT8 *rom;\n\tUINT32 RAMSize;\n\tUINT8 *ram;\n\tint clock;\n\n\tINT32 volume[256*4];\t\t\t// precalculated attenuation values with some marging for enveloppe and pan levels\n\n\tUINT8 regs[256];\n\t\n\tvoid *fmchip;\n\tUINT8 FMEnabled;\t// that saves a whole lot of CPU\n\t//sound_stream * stream;\n} YMF278BChip;\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\n#define MAX_CHIPS\t0x10\nstatic YMF278BChip YMF278BData[MAX_CHIPS];\nstatic UINT32 ROMFileSize = 0x00;\nstatic UINT8* ROMFile = NULL;\n\nchar* FindFile(const char* FileName);\t// from VGMPlay_Intf.h/VGMPlay.c\n\n\n#define EG_SH\t16\t// 16.16 fixed point (EG timing)\n#define EG_TIMER_OVERFLOW\t(1 << EG_SH)\n\n// envelope output entries\n#define ENV_BITS\t11\t// -VB\n#define ENV_LEN\t\t(1 << ENV_BITS)\n#define ENV_STEP\t(128.0 / ENV_LEN)\n#define MAX_ATT_INDEX\t511\n#define MIN_ATT_INDEX\t0\n\n// Envelope Generator phases\n#define EG_ATT\t4\n#define EG_DEC\t3\n#define EG_SUS\t2\n#define EG_REL\t1\n#define EG_OFF\t0\n\n#define EG_REV\t5\t// pseudo reverb\n#define EG_DMP\t6\t// damp\n\n// Pan values, units are -3dB, i.e. 8.\nconst INT32 pan_left[16]  = {\n\t0, 8, 16, 24, 32, 40, 48, 256, 256,   0,  0,  0,  0,  0,  0, 0\n};\nconst INT32 pan_right[16] = {\n\t0, 0,  0,  0,  0,  0,  0,   0, 256, 256, 48, 40, 32, 24, 16, 8\n};\n\n// Mixing levels, units are -3dB, and add some marging to avoid clipping\nconst INT32 mix_level[8] = {\n\t8, 16, 24, 32, 40, 48, 56, 256+8\n};\n\n// decay level table (3dB per step)\n// 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)\n#define SC(db) (db * (2.0 / ENV_STEP))\nconst UINT32 dl_tab[16] = {\n SC( 0), SC( 1), SC( 2), SC(3 ), SC(4 ), SC(5 ), SC(6 ), SC( 7),\n SC( 8), SC( 9), SC(10), SC(11), SC(12), SC(13), SC(14), SC(31)\n};\n#undef SC\n\n#define RATE_STEPS\t8\nconst UINT8 eg_inc[15 * RATE_STEPS] = {\n//cycle:0  1   2  3   4  5   6  7\n\t0, 1,  0, 1,  0, 1,  0, 1, //  0  rates 00..12 0 (increment by 0 or 1)\n\t0, 1,  0, 1,  1, 1,  0, 1, //  1  rates 00..12 1\n\t0, 1,  1, 1,  0, 1,  1, 1, //  2  rates 00..12 2\n\t0, 1,  1, 1,  1, 1,  1, 1, //  3  rates 00..12 3\n\n\t1, 1,  1, 1,  1, 1,  1, 1, //  4  rate 13 0 (increment by 1)\n\t1, 1,  1, 2,  1, 1,  1, 2, //  5  rate 13 1\n\t1, 2,  1, 2,  1, 2,  1, 2, //  6  rate 13 2\n\t1, 2,  2, 2,  1, 2,  2, 2, //  7  rate 13 3\n\n\t2, 2,  2, 2,  2, 2,  2, 2, //  8  rate 14 0 (increment by 2)\n\t2, 2,  2, 4,  2, 2,  2, 4, //  9  rate 14 1\n\t2, 4,  2, 4,  2, 4,  2, 4, // 10  rate 14 2\n\t2, 4,  4, 4,  2, 4,  4, 4, // 11  rate 14 3\n\n\t4, 4,  4, 4,  4, 4,  4, 4, // 12  rates 15 0, 15 1, 15 2, 15 3 for decay\n\t8, 8,  8, 8,  8, 8,  8, 8, // 13  rates 15 0, 15 1, 15 2, 15 3 for attack (zero time)\n\t0, 0,  0, 0,  0, 0,  0, 0, // 14  infinity rates for attack and decay(s)\n};\n\n#define O(a) (a * RATE_STEPS)\nconst UINT8 eg_rate_select[64] = {\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 0),O( 1),O( 2),O( 3),\n\tO( 4),O( 5),O( 6),O( 7),\n\tO( 8),O( 9),O(10),O(11),\n\tO(12),O(12),O(12),O(12),\n};\n#undef O\n\n// rate  0,    1,    2,    3,   4,   5,   6,  7,  8,  9,  10, 11, 12, 13, 14, 15\n// shift 12,   11,   10,   9,   8,   7,   6,  5,  4,  3,  2,  1,  0,  0,  0,  0\n// mask  4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3,  1,  0,  0,  0,  0\n#define O(a) (a)\nconst UINT8 eg_rate_shift[64] = {\n\tO(12),O(12),O(12),O(12),\n\tO(11),O(11),O(11),O(11),\n\tO(10),O(10),O(10),O(10),\n\tO( 9),O( 9),O( 9),O( 9),\n\tO( 8),O( 8),O( 8),O( 8),\n\tO( 7),O( 7),O( 7),O( 7),\n\tO( 6),O( 6),O( 6),O( 6),\n\tO( 5),O( 5),O( 5),O( 5),\n\tO( 4),O( 4),O( 4),O( 4),\n\tO( 3),O( 3),O( 3),O( 3),\n\tO( 2),O( 2),O( 2),O( 2),\n\tO( 1),O( 1),O( 1),O( 1),\n\tO( 0),O( 0),O( 0),O( 0),\n\tO( 0),O( 0),O( 0),O( 0),\n\tO( 0),O( 0),O( 0),O( 0),\n\tO( 0),O( 0),O( 0),O( 0),\n};\n#undef O\n\n\n// number of steps to take in quarter of lfo frequency\n// TODO check if frequency matches real chip\n#define O(a) ((EG_TIMER_OVERFLOW / a) / 6)\nconst INT32 lfo_period[8] = {\n\tO(0.168), O(2.019), O(3.196), O(4.206),\n\tO(5.215), O(5.888), O(6.224), O(7.066)\n};\n#undef O\n\n\n#define O(a) (a * 65536)\nconst INT32 vib_depth[8] = {\n\tO(0),\t   O(3.378),  O(5.065),  O(6.750),\n\tO(10.114), O(20.170), O(40.106), O(79.307)\n};\n#undef O\n\n\n#define SC(db) (INT32)(db * (2.0 / ENV_STEP))\nconst INT32 am_depth[8] = {\n\tSC(0),\t   SC(1.781), SC(2.906), SC(3.656),\n\tSC(4.406), SC(5.906), SC(7.406), SC(11.91)\n};\n#undef SC\n\nvoid ymf278b_slot_reset(YMF278BSlot* slot)\n{\n\tslot->wave = slot->FN = slot->OCT = slot->PRVB = slot->LD = slot->TL = slot->pan =\n\t\tslot->lfo = slot->vib = slot->AM = 0;\n\tslot->AR = slot->D1R = slot->DL = slot->D2R = slot->RC = slot->RR = 0;\n\tslot->step = slot->stepptr = 0;\n\tslot->bits = slot->startaddr = slot->loopaddr = slot->endaddr = 0;\n\tslot->env_vol = MAX_ATT_INDEX;\n\n\tslot->lfo_active = 0;\n\tslot->lfo_cnt = slot->lfo_step = 0;\n\tslot->lfo_max = lfo_period[0];\n\n\tslot->state = EG_OFF;\n\tslot->active = 0;\n\n\t// not strictly needed, but avoid UMR on savestate\n\tslot->pos = slot->sample1 = slot->sample2 = 0;\n}\n\nINLINE int ymf278b_slot_compute_rate(YMF278BSlot* slot, int val)\n{\n\tint res;\n\tint oct;\n\t\n\tif (val == 0)\n\t\treturn 0;\n\telse if (val == 15)\n\t\treturn 63;\n\t\n\tif (slot->RC != 15)\n\t{\n\t\toct = slot->OCT;\n\t\t\n\t\tif (oct & 8)\n\t\t{\n\t\t\toct |= -8;\n\t\t}\n\t\tres = (oct + slot->RC);\n\t\tif (res < 0)\n\t\t\tres = 0;\n\t\telse if (res > 15)\n\t\t\tres = 15;\n\t\tres = res * 2 + ((slot->FN & 0x200) ? 1 : 0) + val * 4;\n\t}\n\telse\n\t{\n\t\tres = val * 4;\n\t}\n\t\n\tif (res < 0)\n\t\tres = 0;\n\telse if (res > 63)\n\t\tres = 63;\n\t\n\treturn res;\n}\n\nINLINE int ymf278b_slot_compute_vib(YMF278BSlot* slot)\n{\n\treturn (((slot->lfo_step << 8) / slot->lfo_max) * vib_depth[slot->vib]) >> 24;\n}\n\n\nINLINE int ymf278b_slot_compute_am(YMF278BSlot* slot)\n{\n\tif (slot->lfo_active && slot->AM)\n\t\treturn (((slot->lfo_step << 8) / slot->lfo_max) * am_depth[slot->AM]) >> 12;\n\telse\n\t\treturn 0;\n}\n\nINLINE void ymf278b_slot_set_lfo(YMF278BSlot* slot, int newlfo)\n{\n\tslot->lfo_step = (((slot->lfo_step << 8) / slot->lfo_max) * newlfo) >> 8;\n\tslot->lfo_cnt  = (((slot->lfo_cnt  << 8) / slot->lfo_max) * newlfo) >> 8;\n\n\tslot->lfo = newlfo;\n\tslot->lfo_max = lfo_period[slot->lfo];\n}\n\nINLINE void ymf278b_advance(YMF278BChip* chip)\n{\n\tYMF278BSlot* op;\n\tint i;\n\tUINT8 rate;\n\tUINT8 shift;\n\tUINT8 select;\n\t\n\tchip->eg_cnt ++;\n\tfor (i = 0; i < 24; i ++)\n\t{\n\t\top = &chip->slots[i];\n\n\t\tif (op->lfo_active)\n\t\t{\n\t\t\top->lfo_cnt ++;\n\t\t\tif (op->lfo_cnt < op->lfo_max)\n\t\t\t{\n\t\t\t\top->lfo_step ++;\n\t\t\t}\n\t\t\telse if (op->lfo_cnt < (op->lfo_max * 3))\n\t\t\t{\n\t\t\t\top->lfo_step --;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\top->lfo_step ++;\n\t\t\t\tif (op->lfo_cnt == (op->lfo_max * 4))\n\t\t\t\t\top->lfo_cnt = 0;\n\t\t\t}\n\t\t}\n\n\t\t// Envelope Generator\n\t\tswitch(op->state)\n\t\t{\n\t\tcase EG_ATT:\t// attack phase\n\t\t\trate = ymf278b_slot_compute_rate(op, op->AR);\n\t\t\tif (rate < 4)\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tshift = eg_rate_shift[rate];\n\t\t\tif (! (chip->eg_cnt & ((1 << shift) - 1)))\n\t\t\t{\n\t\t\t\tselect = eg_rate_select[rate];\n\t\t\t\top->env_vol += (~op->env_vol * eg_inc[select + ((chip->eg_cnt >> shift) & 7)]) >> 4;\t// -VB\n\t\t\t\tif (op->env_vol <= MIN_ATT_INDEX)\n\t\t\t\t{\n\t\t\t\t\top->env_vol = MIN_ATT_INDEX;\n\t\t\t\t\tif (op->DL)\n\t\t\t\t\t\top->state = EG_DEC;\n\t\t\t\t\telse\n\t\t\t\t\t\top->state = EG_SUS;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase EG_DEC:\t// decay phase\n\t\t\trate = ymf278b_slot_compute_rate(op, op->D1R);\n\t\t\tif (rate < 4)\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tshift = eg_rate_shift[rate];\n\t\t\tif (! (chip->eg_cnt & ((1 << shift) - 1)))\n\t\t\t{\n\t\t\t\tselect = eg_rate_select[rate];\n\t\t\t\top->env_vol += eg_inc[select + ((chip->eg_cnt >> shift) & 7)];\n\n\t\t\t\tif ((op->env_vol > dl_tab[6]) && op->PRVB)\n\t\t\t\t\top->state = EG_REV;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (op->env_vol >= op->DL)\n\t\t\t\t\t\top->state = EG_SUS;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase EG_SUS:\t// sustain phase\n\t\t\trate = ymf278b_slot_compute_rate(op, op->D2R);\n\t\t\tif (rate < 4)\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tshift = eg_rate_shift[rate];\n\t\t\tif (! (chip->eg_cnt & ((1 << shift) - 1)))\n\t\t\t{\n\t\t\t\tselect = eg_rate_select[rate];\n\t\t\t\top->env_vol += eg_inc[select + ((chip->eg_cnt >> shift) & 7)];\n\n\t\t\t\tif ((op->env_vol > dl_tab[6]) && op->PRVB)\n\t\t\t\t\top->state = EG_REV;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (op->env_vol >= MAX_ATT_INDEX)\n\t\t\t\t\t{\n\t\t\t\t\t\top->env_vol = MAX_ATT_INDEX;\n\t\t\t\t\t\top->active = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase EG_REL:\t// release phase\n\t\t\trate = ymf278b_slot_compute_rate(op, op->RR);\n\t\t\tif (rate < 4)\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tshift = eg_rate_shift[rate];\n\t\t\tif (! (chip->eg_cnt & ((1 << shift) - 1)))\n\t\t\t{\n\t\t\t\tselect = eg_rate_select[rate];\n\t\t\t\top->env_vol += eg_inc[select + ((chip->eg_cnt >> shift) & 7)];\n\n\t\t\t\tif ((op->env_vol > dl_tab[6]) && op->PRVB)\n\t\t\t\t\top->state = EG_REV;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (op->env_vol >= MAX_ATT_INDEX)\n\t\t\t\t\t{\n\t\t\t\t\t\top->env_vol = MAX_ATT_INDEX;\n\t\t\t\t\t\top->active = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase EG_REV:\t// pseudo reverb\n\t\t\t// TODO improve env_vol update\n\t\t\trate = ymf278b_slot_compute_rate(op, 5);\n\t\t\t//if (rate < 4)\n\t\t\t//\tbreak;\n\t\t\t\n\t\t\tshift = eg_rate_shift[rate];\n\t\t\tif (! (chip->eg_cnt & ((1 << shift) - 1)))\n\t\t\t{\n\t\t\t\tselect = eg_rate_select[rate];\n\t\t\t\top->env_vol += eg_inc[select + ((chip->eg_cnt >> shift) & 7)];\n\n\t\t\t\tif (op->env_vol >= MAX_ATT_INDEX)\n\t\t\t\t{\n\t\t\t\t\top->env_vol = MAX_ATT_INDEX;\n\t\t\t\t\top->active = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase EG_DMP:\t// damping\n\t\t\t// TODO improve env_vol update, damp is just fastest decay now\n\t\t\trate = 56;\n\t\t\tshift = eg_rate_shift[rate];\n\t\t\tif (! (chip->eg_cnt & ((1 << shift) - 1)))\n\t\t\t{\n\t\t\t\tselect = eg_rate_select[rate];\n\t\t\t\top->env_vol += eg_inc[select + ((chip->eg_cnt >> shift) & 7)];\n\n\t\t\t\tif (op->env_vol >= MAX_ATT_INDEX)\n\t\t\t\t{\n\t\t\t\t\top->env_vol = MAX_ATT_INDEX;\n\t\t\t\t\top->active = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase EG_OFF:\n\t\t\t// nothing\n\t\t\tbreak;\n\n\t\tdefault:\n#ifdef _DEBUG\n\t\t\t//logerror(...);\n#endif\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nINLINE UINT8 ymf278b_readMem(YMF278BChip* chip, offs_t address)\n{\n\tif (address < chip->ROMSize)\n\t\treturn chip->rom[address&0x3fffff];\n\telse if (address < chip->ROMSize + chip->RAMSize)\n\t\treturn chip->ram[address - (chip->ROMSize&0x3fffff)];\n\telse\n\t\treturn 255; // TODO check\n}\n\nINLINE UINT8* ymf278b_readMemAddr(YMF278BChip* chip, offs_t address)\n{\n\tif (address < chip->ROMSize)\n\t\treturn &chip->rom[address&0x3fffff];\n\telse if (address < chip->ROMSize + chip->RAMSize)\n\t\treturn &chip->ram[address - (chip->ROMSize&0x3fffff)];\n\telse\n\t\treturn NULL; // TODO check\n}\n\nINLINE void ymf278b_writeMem(YMF278BChip* chip, offs_t address, UINT8 value)\n{\n\tif (address < chip->ROMSize)\n\t\treturn; // can't write to ROM\n\telse if (address < chip->ROMSize + chip->RAMSize)\n\t\tchip->ram[address - chip->ROMSize] = value;\n\telse\n\t\treturn;\t// can't write to unmapped memory\n\t\n\treturn;\n}\n\nINLINE INT16 ymf278b_getSample(YMF278BChip* chip, YMF278BSlot* op)\n{\n\tINT16 sample;\n\tUINT32 addr;\n\tUINT8* addrp;\n\t\n\tswitch (op->bits)\n\t{\n\tcase 0:\n\t\t// 8 bit\n\t\tsample = ymf278b_readMem(chip, op->startaddr + op->pos) << 8;\n\t\tbreak;\n\tcase 1:\n\t\t// 12 bit\n\t\taddr = op->startaddr + ((op->pos / 2) * 3);\n\t\taddrp = ymf278b_readMemAddr(chip, addr);\n\t\tif (op->pos & 1)\n\t\t\tsample = (addrp[2] << 8) | ((addrp[1] << 4) & 0xF0);\n\t\telse\n\t\t\tsample = (addrp[0] << 8) | (addrp[1] & 0xF0);\n\t\tbreak;\n\tcase 2:\n\t\t// 16 bit\n\t\taddr = op->startaddr + (op->pos * 2);\n\t\taddrp = ymf278b_readMemAddr(chip, addr);\n\t\tsample = (addrp[0] << 8) | addrp[1];\n\t\tbreak;\n\tdefault:\n\t\t// TODO unspecified\n\t\tsample = 0;\n\t\tbreak;\n\t}\n\treturn sample;\n}\n\nint ymf278b_anyActive(YMF278BChip* chip)\n{\n\tint i;\n\t\n\tfor (i = 0; i < 24; i ++)\n\t{\n\t\tif (chip->slots[i].active)\n\t\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nvoid ymf278b_pcm_update(UINT8 ChipID, stream_sample_t** outputs, int samples)\n{\n\tYMF278BChip* chip = &YMF278BData[ChipID];\n\tint i;\n\tunsigned int j;\n\tINT32 vl;\n\tINT32 vr;\n\t\n\tif (chip->FMEnabled)\n\t{\n\t\t/* memset is done by ymf262_update */\n\t\tymf262_update_one(chip->fmchip, outputs, samples);\n\t\t// apply FM mixing level\n\t\tvl = mix_level[chip->fm_l] - 8;\tvl = chip->volume[vl];\n\t\tvr = mix_level[chip->fm_r] - 8;\tvr = chip->volume[vr];\n\t\t// make FM softer by 3 db\n\t\tvl = (vl * 0x16A) >> 8;\tvr = (vr * 0x16A) >> 8;\n\t\tfor (j = 0; j < samples; j ++)\n\t\t{\n\t\t\toutputs[0][j] = (outputs[0][j] * vl) >> 15;\n\t\t\toutputs[1][j] = (outputs[1][j] * vr) >> 15;\n\t\t}\n\t}\n\telse\n\t{\n\t\tmemset(outputs[0], 0x00, samples * sizeof(stream_sample_t));\n\t\tmemset(outputs[1], 0x00, samples * sizeof(stream_sample_t));\n\t}\n\t\n\tif (! ymf278b_anyActive(chip))\n\t{\n\t\t// TODO update internal state, even if muted\n\t\t// TODO also mute individual channels\n\t\treturn;\n\t}\n\n\tvl = mix_level[chip->pcm_l];\n\tvr = mix_level[chip->pcm_r];\n\tfor (j = 0; j < samples; j ++)\n\t{\n\t\tfor (i = 0; i < 24; i ++)\n\t\t{\n\t\t\tYMF278BSlot* sl;\n\t\t\tINT16 sample;\n\t\t\tint vol;\n\t\t\tint volLeft;\n\t\t\tint volRight;\n\t\t\t\n\t\t\tsl = &chip->slots[i];\n\t\t\tif (! sl->active || sl->Muted)\n\t\t\t{\n\t\t\t\t//outputs[0][j] += 0;\n\t\t\t\t//outputs[1][j] += 0;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tsample = (sl->sample1 * (0x10000 - sl->stepptr) +\n\t\t\t\t\t\tsl->sample2 * sl->stepptr) >> 16;\n\t\t\tvol = sl->TL + (sl->env_vol >> 2) + ymf278b_slot_compute_am(sl);\n\n\t\t\tvolLeft  = vol + pan_left [sl->pan] + vl;\n\t\t\tvolRight = vol + pan_right[sl->pan] + vr;\n\t\t\t// TODO prob doesn't happen in real chip\n\t\t\t//volLeft  = std::max(0, volLeft);\n\t\t\t//volRight = std::max(0, volRight);\n\t\t\tvolLeft &= 0x3FF;\t// catch negative Volume values in a hardware-like way\n\t\t\tvolRight &= 0x3FF;\t// (anything beyond 0x100 results in *0)\n\n\t\t\toutputs[0][j] += (sample * chip->volume[volLeft] ) >> 17;\n\t\t\toutputs[1][j] += (sample * chip->volume[volRight]) >> 17;\n\n\t\t\tif (sl->lfo_active && sl->vib)\n\t\t\t{\n\t\t\t\tint oct;\n\t\t\t\tunsigned int step;\n\t\t\t\t\n\t\t\t\toct = sl->OCT;\n\t\t\t\tif (oct & 8)\n\t\t\t\t\toct |= -8;\n\t\t\t\toct += 5;\n\t\t\t\tstep = (sl->FN | 1024) + ymf278b_slot_compute_vib(sl);\n\t\t\t\tif (oct >= 0)\n\t\t\t\t\tstep <<= oct;\n\t\t\t\telse\n\t\t\t\t\tstep >>= -oct;\n\t\t\t\tsl->stepptr += step;\n\t\t\t}\n\t\t\telse\n\t\t\t\tsl->stepptr += sl->step;\n\n\t\t\tif (sl->stepptr >= 0x10000)\n\t\t\t{\n\t\t\t\tsl->sample1 = sl->sample2;\n\t\t\t\t\n\t\t\t\tsl->sample2 = ymf278b_getSample(chip, sl);\n\t\t\t\tsl->pos += (sl->stepptr >> 16);\n\t\t\t\tsl->stepptr &= 0xFFFF;\n\t\t\t\tif (sl->pos > sl->endaddr)\n\t\t\t\t\tsl->pos = sl->pos - sl->endaddr + sl->loopaddr - 1;\n\t\t\t}\n\t\t}\n\t\tymf278b_advance(chip);\n\t}\n}\n\nINLINE void ymf278b_keyOnHelper(YMF278BChip* chip, YMF278BSlot* slot)\n{\n\tint oct;\n\tunsigned int step;\n\t\n\tslot->active = 1;\n\n\toct = slot->OCT;\n\tif (oct & 8)\n\t\toct |= -8;\n\toct += 5;\n\tstep = slot->FN | 1024;\n\tif (oct >= 0)\n\t\tstep <<= oct;\n\telse\n\t\tstep >>= -oct;\n\tslot->step = step;\n\tslot->state = EG_ATT;\n\tslot->stepptr = 0;\n\tslot->pos = 0;\n\tslot->sample1 = ymf278b_getSample(chip, slot);\n\tslot->pos = 1;\n\tslot->sample2 = ymf278b_getSample(chip, slot);\n}\n\nstatic void ymf278b_A_w(YMF278BChip *chip, UINT8 reg, UINT8 data)\n{\n\tswitch(reg)\n\t{\n\t\tcase 0x02:\n\t\t\t//chip->timer_a_count = data;\n\t\t\t//ymf278b_timer_a_reset(chip);\n\t\t\tbreak;\n\t\tcase 0x03:\n\t\t\t//chip->timer_b_count = data;\n\t\t\t//ymf278b_timer_b_reset(chip);\n\t\t\tbreak;\n\t\tcase 0x04:\n\t\t\t/*if(data & 0x80)\n\t\t\t\tchip->current_irq = 0;\n\t\t\telse\n\t\t\t{\n\t\t\t\tUINT8 old_enable = chip->enable;\n\t\t\t\tchip->enable = data;\n\t\t\t\tchip->current_irq &= ~data;\n\t\t\t\tif((old_enable ^ data) & 1)\n\t\t\t\t\tymf278b_timer_a_reset(chip);\n\t\t\t\tif((old_enable ^ data) & 2)\n\t\t\t\t\tymf278b_timer_b_reset(chip);\n\t\t\t}\n\t\t\tymf278b_irq_check(chip);*/\n\t\t\tbreak;\n\t\tdefault:\n//#ifdef _DEBUG\n//\t\t\tlogerror(\"YMF278B:  Port A write %02x, %02x\\n\", reg, data);\n//#endif\n\t\t\tymf262_write(chip->fmchip, 1, data);\n\t\t\tif ((reg & 0xF0) == 0xB0 && (data & 0x20))\t// Key On set\n\t\t\t\tchip->FMEnabled = 0x01;\n\t\t\telse if (reg == 0xBD && (data & 0x1F))\t// one of the Rhythm bits set\n\t\t\t\tchip->FMEnabled = 0x01;\n\t\t\tbreak;\n\t}\n}\n\nstatic void ymf278b_B_w(YMF278BChip *chip, UINT8 reg, UINT8 data)\n{\n\tswitch(reg)\n\t{\n\t\tcase 0x05:\t// OPL3/OPL4 Enable\n\t\t\t// Bit 1 enables OPL4 WaveTable Synth\n\t\t\tchip->exp = data;\n\t\t\tymf262_write(chip->fmchip, 3, data & ~0x02);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tymf262_write(chip->fmchip, 3, data);\n\t\t\tif ((reg & 0xF0) == 0xB0 && (data & 0x20))\n\t\t\t\tchip->FMEnabled = 0x01;\n\t\t\tbreak;\n\t}\n//#ifdef _DEBUG\n//\tlogerror(\"YMF278B:  Port B write %02x, %02x\\n\", reg, data);\n//#endif\n}\n\nvoid ymf278b_C_w(YMF278BChip* chip, UINT8 reg, UINT8 data)\n{\n\t// Handle slot registers specifically\n\tif (reg >= 0x08 && reg <= 0xF7)\n\t{\n\t\tint snum = (reg - 8) % 24;\n\t\tYMF278BSlot* slot = &chip->slots[snum];\n\t\tint base;\n\t\tUINT8* buf;\n\t\tint oct;\n\t\tunsigned int step;\n\t\t\n\t\tswitch((reg - 8) / 24)\n\t\t{\n\t\tcase 0:\n\t\t\t//loadTime = time + LOAD_DELAY;\n\n\t\t\tslot->wave = (slot->wave & 0x100) | data;\n\t\t\tbase = (slot->wave < 384 || ! chip->wavetblhdr) ?\n\t\t\t\t\t(slot->wave * 12) :\n\t\t\t\t\t(chip->wavetblhdr * 0x80000 + ((slot->wave - 384) * 12));\n\t\t\tbuf = ymf278b_readMemAddr(chip, base);\n\t\t\t\n\t\t\tslot->bits = (buf[0] & 0xC0) >> 6;\n\t\t\tymf278b_slot_set_lfo(slot, (buf[7] >> 3) & 7);\n\t\t\tslot->vib  = buf[7] & 7;\n\t\t\tslot->AR   = buf[8] >> 4;\n\t\t\tslot->D1R  = buf[8] & 0xF;\n\t\t\tslot->DL   = dl_tab[buf[9] >> 4];\n\t\t\tslot->D2R  = buf[9] & 0xF;\n\t\t\tslot->RC   = buf[10] >> 4;\n\t\t\tslot->RR   = buf[10] & 0xF;\n\t\t\tslot->AM   = buf[11] & 7;\n\t\t\tslot->startaddr = buf[2] | (buf[1] << 8) |\n\t\t\t\t\t\t\t\t((buf[0] & 0x3F) << 16);\n\t\t\tslot->loopaddr = buf[4] + (buf[3] << 8);\n\t\t\tslot->endaddr  = ((buf[6] + (buf[5] << 8)) ^ 0xFFFF);\n\t\t\t\n\t\t\tif (chip->regs[reg + 4] & 0x080)\n\t\t\t\tymf278b_keyOnHelper(chip, slot);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tslot->wave = (slot->wave & 0xFF) | ((data & 0x1) << 8);\n\t\t\tslot->FN = (slot->FN & 0x380) | (data >> 1);\n\t\t\t\n\t\t\toct = slot->OCT;\n\t\t\tif (oct & 8)\n\t\t\t\toct |= -8;\n\t\t\toct += 5;\n\t\t\tstep = slot->FN | 1024;\n\t\t\tif (oct >= 0)\n\t\t\t\tstep <<= oct;\n\t\t\telse\n\t\t\t\tstep >>= -oct;\n\t\t\tslot->step = step;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tslot->FN = (slot->FN & 0x07F) | ((data & 0x07) << 7);\n\t\t\tslot->PRVB = ((data & 0x08) >> 3);\n\t\t\tslot->OCT =  ((data & 0xF0) >> 4);\n\t\t\t\n\t\t\toct = slot->OCT;\n\t\t\tif (oct & 8)\n\t\t\t\toct |= -8;\n\t\t\toct += 5;\n\t\t\tstep = slot->FN | 1024;\n\t\t\tif (oct >= 0)\n\t\t\t\tstep <<= oct;\n\t\t\telse\n\t\t\t\tstep >>= -oct;\n\t\t\tslot->step = step;\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tslot->TL = data >> 1;\n\t\t\tslot->LD = data & 0x1;\n\n\t\t\t// TODO\n\t\t\tif (slot->LD) {\n\t\t\t\t// directly change volume\n\t\t\t} else {\n\t\t\t\t// interpolate volume\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tif (data & 0x10)\n\t\t\t{\n\t\t\t\t// output to DO1 pin:\n\t\t\t\t// this pin is not used in moonsound\n\t\t\t\t// we emulate this by muting the sound\n\t\t\t\tslot->pan = 8; // both left/right -inf dB\n\t\t\t}\n\t\t\telse\n\t\t\t\tslot->pan = data & 0x0F;\n\n\t\t\tif (data & 0x020)\n\t\t\t{\n\t\t\t\t// LFO reset\n\t\t\t\tslot->lfo_active = 0;\n\t\t\t\tslot->lfo_cnt = 0;\n\t\t\t\tslot->lfo_max = lfo_period[slot->vib];\n\t\t\t\tslot->lfo_step = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// LFO activate\n\t\t\t\tslot->lfo_active = 1;\n\t\t\t}\n\n\t\t\tswitch (data >> 6)\n\t\t\t{\n\t\t\tcase 0: // tone off, no damp\n\t\t\t\tif (slot->active && (slot->state != EG_REV))\n\t\t\t\t\tslot->state = EG_REL;\n\t\t\t\tbreak;\n\t\t\tcase 2: // tone on, no damp\n\t\t\t\tif (! (chip->regs[reg] & 0x080))\n\t\t\t\t\tymf278b_keyOnHelper(chip, slot);\n\t\t\t\tbreak;\n\t\t\tcase 1: // tone off, damp\n\t\t\tcase 3: // tone on,  damp\n\t\t\t\tslot->state = EG_DMP;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tslot->vib = data & 0x7;\n\t\t\tymf278b_slot_set_lfo(slot, (data >> 3) & 0x7);\n\t\t\tbreak;\n\t\tcase 6:\n\t\t\tslot->AR  = data >> 4;\n\t\t\tslot->D1R = data & 0xF;\n\t\t\tbreak;\n\t\tcase 7:\n\t\t\tslot->DL  = dl_tab[data >> 4];\n\t\t\tslot->D2R = data & 0xF;\n\t\t\tbreak;\n\t\tcase 8:\n\t\t\tslot->RC = data >> 4;\n\t\t\tslot->RR = data & 0xF;\n\t\t\tbreak;\n\t\tcase 9:\n\t\t\tslot->AM = data & 0x7;\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\t// All non-slot registers\n\t\tswitch (reg)\n\t\t{\n\t\tcase 0x00: // TEST\n\t\tcase 0x01:\n\t\t\tbreak;\n\n\t\tcase 0x02:\n\t\t\tchip->wavetblhdr = (data >> 2) & 0x7;\n\t\t\tchip->memmode = data & 1;\n\t\t\tbreak;\n\n\t\tcase 0x03:\n\t\t\tchip->memadr = (chip->memadr & 0x00FFFF) | (data << 16);\n\t\t\tbreak;\n\n\t\tcase 0x04:\n\t\t\tchip->memadr = (chip->memadr & 0xFF00FF) | (data << 8);\n\t\t\tbreak;\n\n\t\tcase 0x05:\n\t\t\tchip->memadr = (chip->memadr & 0xFFFF00) | data;\n\t\t\tbreak;\n\n\t\tcase 0x06:  // memory data\n\t\t\t//busyTime = time + MEM_WRITE_DELAY;\n\t\t\tymf278b_writeMem(chip, chip->memadr, data);\n\t\t\tchip->memadr = (chip->memadr + 1) & 0xFFFFFF;\n\t\t\tbreak;\n\n\t\tcase 0xF8:\n\t\t\t// TODO use these\n\t\t\tchip->fm_l = data & 0x7;\n\t\t\tchip->fm_r = (data >> 3) & 0x7;\n\t\t\tbreak;\n\n\t\tcase 0xF9:\n\t\t\tchip->pcm_l = data & 0x7;\n\t\t\tchip->pcm_r = (data >> 3) & 0x7;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tchip->regs[reg] = data;\n}\n\nUINT8 ymf278b_readReg(YMF278BChip* chip, UINT8 reg)\n{\n\t// no need to call updateStream(time)\n\tUINT8 result;\n\tswitch(reg)\n\t{\n\tcase 2: // 3 upper bits are device ID\n\t\tresult = (chip->regs[2] & 0x1F) | 0x20;\n\t\tbreak;\n\n\tcase 6: // Memory Data Register\n\t\t//busyTime = time + MEM_READ_DELAY;\n\t\tresult = ymf278b_readMem(chip, chip->memadr);\n\t\tchip->memadr = (chip->memadr + 1) & 0xFFFFFF;\n\t\tbreak;\n\n\tdefault:\n\t\tresult = chip->regs[reg];\n\t\tbreak;\n\t}\n\t\n\treturn result;\n}\n\nUINT8 ymf278b_peekReg(YMF278BChip* chip, UINT8 reg)\n{\n\tUINT8 result;\n\t\n\tswitch(reg)\n\t{\n\tcase 2: // 3 upper bits are device ID\n\t\tresult = (chip->regs[2] & 0x1F) | 0x20;\n\t\tbreak;\n\n\tcase 6: // Memory Data Register\n\t\tresult = ymf278b_readMem(chip, chip->memadr);\n\t\tbreak;\n\n\tdefault:\n\t\tresult = chip->regs[reg];\n\t\tbreak;\n\t}\n\treturn result;\n}\n\nUINT8 ymf278b_readStatus(YMF278BChip* chip)\n{\n\tUINT8 result = 0;\n\t//if (time < busyTime)\n\t//\tresult |= 0x01;\n\t//if (time < loadTime)\n\t//\tresult |= 0x02;\n\treturn result;\n}\n\n//WRITE8_DEVICE_HANDLER( ymf278b_w )\nvoid ymf278b_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//YMF278BChip *chip = get_safe_token(device);\n\tYMF278BChip *chip = &YMF278BData[ChipID];\n\n\tswitch (offset)\n\t{\n\t\tcase 0:\n\t\t\tchip->port_A = data;\n\t\t\tymf262_write(chip->fmchip, offset, data);\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tymf278b_A_w(chip, chip->port_A, data);\n\t\t\tbreak;\n\n\t\tcase 2:\n\t\t\tchip->port_B = data;\n\t\t\tymf262_write(chip->fmchip, offset, data);\n\t\t\tbreak;\n\n\t\tcase 3:\n\t\t\tymf278b_B_w(chip, chip->port_B, data);\n\t\t\tbreak;\n\n\t\tcase 4:\n\t\t\tchip->port_C = data;\n\t\t\tbreak;\n\n\t\tcase 5:\n\t\t\t// PCM regs are only accessible if NEW2 is set\n\t\t\tif (~chip->exp & 2)\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tymf278b_C_w(chip, chip->port_C, data);\n\t\t\tbreak;\n\n\t\tdefault:\n#ifdef _DEBUG\n\t\t\tlogerror(\"YMF278B: unexpected write at offset %X to ymf278b = %02X\\n\", offset, data);\n#endif\n\t\t\tbreak;\n\t}\n}\n\nvoid ymf278b_clearRam(YMF278BChip* chip)\n{\n\tmemset(chip->ram, 0, chip->RAMSize);\n}\n\nstatic void ymf278b_load_rom(YMF278BChip *chip)\n{\n\tconst char* ROM_FILENAME = \"yrw801.rom\";\n\tchar* FileName;\n\tFILE* hFile;\n\tsize_t RetVal;\n\t\n\tif (! ROMFileSize)\n\t{\n\t\tROMFileSize = 0x00200000;\n\t\tROMFile = (UINT8*)malloc(ROMFileSize);\n\t\tmemset(ROMFile, 0xFF, ROMFileSize);\n\t\t\n\t\tFileName = FindFile(ROM_FILENAME);\n\t\tif (FileName != NULL)\n\t\t{\n\t\t\thFile = fopen(FileName, \"rb\");\n\t\t\tfree(FileName);\n\t\t}\n\t\telse\n\t\t{\n\t\t\thFile = NULL;\n\t\t}\n\t\tif (hFile != NULL)\n\t\t{\n\t\t\tRetVal = fread(ROMFile, 0x01, ROMFileSize, hFile);\n\t\t\tfclose(hFile);\n\t\t\tif (RetVal != ROMFileSize)\n\t\t\t\tfprintf(stderr, \"Error while reading OPL4 Sample ROM (%s)!\\n\", ROM_FILENAME);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfprintf(stderr, \"Warning! OPL4 Sample ROM (%s) not found!\\n\", ROM_FILENAME);\n\t\t}\n\t}\n\t\n\tchip->ROMSize = ROMFileSize;\n\tchip->rom = (UINT8*)malloc(chip->ROMSize);\n\tmemcpy(chip->rom, ROMFile, chip->ROMSize);\n\t\n\treturn;\n}\n\nstatic int ymf278b_init(YMF278BChip *chip, int clock, void (*cb)(int))\n{\n\tint rate;\n\t\n\trate = clock / 768;\n\t//if (((CHIP_SAMPLING_MODE & 0x01) && rate < CHIP_SAMPLE_RATE) ||\n\t//\tCHIP_SAMPLING_MODE == 0x02)\n\t//\trate = CHIP_SAMPLE_RATE;\n\tchip->fmchip = ymf262_init(clock * 8 / 19, rate);\n\tchip->FMEnabled = 0x00;\n\t\n\tchip->rom = NULL;\n\tchip->irq_callback = cb;\n\t//chip->timer_a = timer_alloc(device->machine, ymf278b_timer_a_tick, chip);\n\t//chip->timer_b = timer_alloc(device->machine, ymf278b_timer_b_tick, chip);\n\tchip->clock = clock;\n\n\tymf278b_load_rom(chip);\n\tchip->RAMSize = 0x00080000;\n\tchip->ram = (UINT8*)malloc(chip->RAMSize);\n\tymf278b_clearRam(chip);\n\n\treturn rate;\n}\n\n//static DEVICE_START( ymf278b )\nint device_start_ymf278b(UINT8 ChipID, int clock)\n{\n\tstatic const ymf278b_interface defintrf = { 0 };\n\tconst ymf278b_interface *intf;\n\tint i;\n\tYMF278BChip *chip;\n\tint rate;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &YMF278BData[ChipID];\n\t\n\t//chip->device = device;\n\t//intf = (device->static_config != NULL) ? (const ymf278b_interface *)device->static_config : &defintrf;\n\tintf = &defintrf;\n\n\trate = ymf278b_init(chip, clock, intf->irq_callback);\n\t//chip->stream = stream_create(device, 0, 2, device->clock/768, chip, ymf278b_pcm_update);\n\n\tchip->memadr = 0; // avoid UMR\n\n\t// Volume table, 1 = -0.375dB, 8 = -3dB, 256 = -96dB\n\tfor (i = 0; i < 256; i ++)\n\t{\n\t\tint vol_mul = 0x20 - (i & 0x0F);\t// 0x10 values per 6 db\n\t\tint vol_shift = 5 + (i >> 4);\t\t// approximation: -6 dB == divide by two (shift right)\n\t\tchip->volume[i] = (0x8000 * vol_mul) >> vol_shift;\n\t}\n\tfor (i = 256; i < 256 * 4; i ++)\n\t\tchip->volume[i] = 0;\n\tfor (i = 0; i < 24; i ++)\n\t\tchip->slots[i].Muted = 0x00;;\n\n\treturn rate;\n}\n\n//static DEVICE_STOP( ymf278 )\nvoid device_stop_ymf278b(UINT8 ChipID)\n{\n\tYMF278BChip* chip = &YMF278BData[ChipID];\n\t\n\tymf262_shutdown(chip->fmchip);\n\tfree(chip->rom);\tchip->rom = NULL;\n\tfree(chip->ram);\tchip->ram = NULL;\n\t\n\treturn;\n}\n\nvoid device_reset_ymf278b(UINT8 ChipID)\n{\n\tYMF278BChip* chip = &YMF278BData[ChipID];\n\tint i;\n\t\n\tymf262_reset_chip(chip->fmchip);\n\tchip->FMEnabled = 0x00;\n\t\n\tchip->eg_cnt = 0;\n\n\tfor (i = 0; i < 24; i ++)\n\t\tymf278b_slot_reset(&chip->slots[i]);\n\tfor (i = 255; i >= 0; i --)\t// reverse order to avoid UMR\n\t\tymf278b_C_w(chip, i, 0);\n\t\n\tchip->wavetblhdr = chip->memmode = chip->memadr = 0;\n\tchip->fm_l = chip->fm_r = 3;\n\tchip->pcm_l = chip->pcm_r = 0;\n\t//busyTime = time;\n\t//loadTime = time;\n}\n\nvoid ymf278b_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t  const UINT8* ROMData)\n{\n\tYMF278BChip *chip = &YMF278BData[ChipID];\n\t\n\tif (chip->ROMSize != ROMSize)\n\t{\n\t\tchip->rom = (UINT8*)realloc(chip->rom, ROMSize);\n\t\tchip->ROMSize = ROMSize;\n\t\tmemset(chip->rom, 0xFF, ROMSize);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(chip->rom + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\nvoid ymf278b_write_ram(UINT8 ChipID, offs_t DataStart, offs_t DataLength, const UINT8* RAMData)\n{\n\tYMF278BChip *chip = &YMF278BData[ChipID];\n\t\n\tif (DataStart >= chip->RAMSize)\n\t\treturn;\n\tif (DataStart + DataLength > chip->RAMSize)\n\t\tDataLength = chip->RAMSize - DataStart;\n\t\n\tmemcpy(chip->ram + DataStart, RAMData, DataLength);\n\t\n\treturn;\n}\n\n\nvoid ymf278b_set_mute_mask(UINT8 ChipID, UINT32 MuteMaskFM, UINT32 MuteMaskWT)\n{\n\tYMF278BChip *chip = &YMF278BData[ChipID];\n\tUINT8 CurChn;\n\t\n\tymf262_set_mutemask(chip->fmchip, MuteMaskFM);\n\tfor (CurChn = 0; CurChn < 24; CurChn ++)\n\t\tchip->slots[CurChn].Muted = (MuteMaskWT >> CurChn) & 0x01;\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/chips/ymf278b.h",
    "content": "#pragma once\n\n#define YMF278B_STD_CLOCK (33868800)\t\t\t/* standard clock for OPL4 */\n\n\ntypedef struct _ymf278b_interface ymf278b_interface;\nstruct _ymf278b_interface\n{\n\t//void (*irq_callback)(const device_config *device, int state);\t/* irq callback */\n\tvoid (*irq_callback)(int state);\t/* irq callback */\n};\n\n/*READ8_DEVICE_HANDLER( ymf278b_r );\nWRITE8_DEVICE_HANDLER( ymf278b_w );\n\nDEVICE_GET_INFO( ymf278b );\n#define SOUND_YMF278B DEVICE_GET_INFO_NAME( ymf278b )*/\n\nvoid ymf278b_pcm_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_ymf278b(UINT8 ChipID, int clock);\nvoid device_stop_ymf278b(UINT8 ChipID);\nvoid device_reset_ymf278b(UINT8 ChipID);\n\nUINT8 ymf278b_r(UINT8 ChipID, offs_t offset);\nvoid ymf278b_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ymf278b_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData);\nvoid ymf278b_write_ram(UINT8 ChipID, offs_t DataStart, offs_t DataLength, const UINT8* RAMData);\n\nvoid ymf278b_set_mute_mask(UINT8 ChipID, UINT32 MuteMaskFM, UINT32 MuteMaskWT);\n\n"
  },
  {
    "path": "VGMPlay/chips/ymz280b.c",
    "content": "/*\n\n Yamaha YMZ280B driver\n  by Aaron Giles\n\n  YMZ280B 8-Channel PCMD8 PCM/ADPCM Decoder\n\n Features as listed in LSI-4MZ280B3 data sheet:\n  Voice data stored in external memory can be played back simultaneously for up to eight voices\n  Voice data format can be selected from 4-bit ADPCM, 8-bit PCM and 16-bit PCM\n  Control of voice data external memory\n   Up to 16M bytes of ROM or SRAM (x 8 bits, access time 150ms max) can be connected\n   Continuous access is possible\n   Loop playback between selective addresses is possible\n  Voice data playback frequency control\n   4-bit ADPCM ................ 0.172 to 44.1kHz in 256 steps\n   8-bit PCM, 16-bit PCM ...... 0.172 to 88.2kHz in 512 steps\n  256 steps total level and 16 steps panpot can be set\n  Voice signal is output in stereo 16-bit 2's complement MSB-first format\n\n  TODO:\n  - Is memory handling 100% correct? At the moment, Konami firebeat.c is the only\n    hardware currently emulated that uses external handlers.\n    It also happens to be the only one using 16-bit PCM.\n\n    Some other drivers (eg. bishi.c, bfm_sc4/5.c) also use ROM readback.\n\n*/\n\n\n#include <math.h>\n\n#include \"mamedef.h\"\n//#include \"sndintrf.h\"\n//#include \"streams.h\"\n#ifdef _DEBUG\n#include <stdio.h>\n#endif\n#include <stdlib.h>\n#include <string.h>\t// for memset\n#include <stddef.h>\t// for NULL\n#include \"ymz280b.h\"\n\nstatic void update_irq_state_timer_common(void *param, int voicenum);\n\n//unsigned char DISABLE_YMZ_FIX = 0x00;\n\n#define MAX_SAMPLE_CHUNK\t0x10000\n#define MAKE_WAVS\t\t\t0\n#define MAKE_WAVS_CH\t\t0\n\n#define FRAC_BITS\t\t\t14\n#define FRAC_ONE\t\t\t(1 << FRAC_BITS)\n#define FRAC_MASK\t\t\t(FRAC_ONE - 1)\n\n#define INTERNAL_BUFFER_SIZE\t(1 << 15)\n//#define INTERNAL_SAMPLE_RATE\t(chip->master_clock * 2.0)\n#define INTERNAL_SAMPLE_RATE\tchip->rate\n\n#if MAKE_WAVS\n#include \"wavwrite.h\"\n#endif\n#if MAKE_WAVS_CH\n#include <stdio.h>\nFILE* hWavFile[8];\nsigned short int* wavmem[8];\n#endif\n\n\n/* struct describing a single playing ADPCM voice */\nstruct YMZ280BVoice\n{\n\tUINT8 playing;\t\t\t/* 1 if we are actively playing */\n\n\tUINT8 keyon;\t\t\t/* 1 if the key is on */\n\tUINT8 looping;\t\t\t/* 1 if looping is enabled */\n\tUINT8 mode;\t\t\t\t/* current playback mode */\n\tUINT16 fnum;\t\t\t/* frequency */\n\tUINT8 level;\t\t\t/* output level */\n\tUINT8 pan;\t\t\t\t/* panning */\n\n\tUINT32 start;\t\t\t/* start address, in nibbles */\n\tUINT32 stop;\t\t\t/* stop address, in nibbles */\n\tUINT32 loop_start;\t\t/* loop start address, in nibbles */\n\tUINT32 loop_end;\t\t/* loop end address, in nibbles */\n\tUINT32 position;\t\t/* current position, in nibbles */\n\n\tINT32 signal;\t\t\t/* current ADPCM signal */\n\tINT32 step;\t\t\t\t/* current ADPCM step */\n\n\tINT32 loop_signal;\t\t/* signal at loop start */\n\tINT32 loop_step;\t\t/* step at loop start */\n\tUINT32 loop_count;\t\t/* number of loops so far */\n\n\tINT32 output_left;\t\t/* output volume (left) */\n\tINT32 output_right;\t\t/* output volume (right) */\n\tINT32 output_step;\t\t/* step value for frequency conversion */\n\tINT32 output_pos;\t\t/* current fractional position */\n\tINT16 last_sample;\t\t/* last sample output */\n\tINT16 curr_sample;\t\t/* current sample target */\n\tUINT8 irq_schedule;\t\t/* 1 if the IRQ state is updated by timer */\n\tUINT8 Muted;\t\t\t/* used for muting */\n};\n\ntypedef struct _ymz280b_state ymz280b_state;\nstruct _ymz280b_state\n{\n\t//sound_stream * stream;\t\t\t/* which stream are we using */\n\tUINT8 *region_base;\t\t\t\t/* pointer to the base of the region */\n\tUINT32 region_size;\n\tUINT8 current_register;\t\t\t/* currently accessible register */\n\tUINT8 status_register;\t\t\t/* current status register */\n\tUINT8 irq_state;\t\t\t\t/* current IRQ state */\n\tUINT8 irq_mask;\t\t\t\t\t/* current IRQ mask */\n\tUINT8 irq_enable;\t\t\t\t/* current IRQ enable */\n\tUINT8 keyon_enable;\t\t\t\t/* key on enable */\n\tUINT8 ext_mem_enable;\t\t\t/* external memory enable */\n\tUINT8 ext_readlatch;\t\t\t/* external memory prefetched data */\n\tUINT32 ext_mem_address_hi;\n\tUINT32 ext_mem_address_mid;\n\tUINT32 ext_mem_address;\t\t\t/* where the CPU can read the ROM */\n\t\n\tdouble master_clock;\t\t\t/* master clock frequency */\n\tdouble rate;\n\t//void (*irq_callback)(const device_config *, int);\t\t/* IRQ callback */\n\tvoid (*irq_callback)(int);\t\t/* IRQ callback */\n\tstruct YMZ280BVoice\tvoice[8];\t/* the 8 voices */\n\t//devcb_resolved_read8 ext_ram_read;\t\t/* external RAM read handler */\n\t//devcb_resolved_write8 ext_ram_write;\t/* external RAM write handler */\n\n#if MAKE_WAVS\n\tvoid *\t\twavresample;\t\t\t/* resampled waveform */\n#endif\n\n\tINT16 *scratch;\n\t//const device_config *device;\n};\n\nstatic void write_to_register(ymz280b_state *chip, int data);\n\n\n/* step size index shift table */\nstatic const int index_scale[8] = { 0x0e6, 0x0e6, 0x0e6, 0x0e6, 0x133, 0x199, 0x200, 0x266 };\n\n/* lookup table for the precomputed difference */\nstatic int diff_lookup[16];\nstatic unsigned char lookup_init = 0x00;\t/* lookup-table is initialized */\n\n/* timer callback */\n/*static TIMER_CALLBACK( update_irq_state_timer_0 );\nstatic TIMER_CALLBACK( update_irq_state_timer_1 );\nstatic TIMER_CALLBACK( update_irq_state_timer_2 );\nstatic TIMER_CALLBACK( update_irq_state_timer_3 );\nstatic TIMER_CALLBACK( update_irq_state_timer_4 );\nstatic TIMER_CALLBACK( update_irq_state_timer_5 );\nstatic TIMER_CALLBACK( update_irq_state_timer_6 );\nstatic TIMER_CALLBACK( update_irq_state_timer_7 );\n\nstatic const timer_fired_func update_irq_state_cb[] =\n{\n\tupdate_irq_state_timer_0,\n\tupdate_irq_state_timer_1,\n\tupdate_irq_state_timer_2,\n\tupdate_irq_state_timer_3,\n\tupdate_irq_state_timer_4,\n\tupdate_irq_state_timer_5,\n\tupdate_irq_state_timer_6,\n\tupdate_irq_state_timer_7\n};*/\n\n\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\n#define MAX_CHIPS\t0x10\nstatic ymz280b_state YMZ280BData[MAX_CHIPS];\n\n/*INLINE ymz280b_state *get_safe_token(const device_config *device)\n{\n\tassert(device != NULL);\n\tassert(device->token != NULL);\n\tassert(device->type == SOUND);\n\tassert(sound_get_type(device) == SOUND_YMZ280B);\n\treturn (ymz280b_state *)device->token;\n}*/\n\nINLINE void update_irq_state(ymz280b_state *chip)\n{\n\tint irq_bits = chip->status_register & chip->irq_mask;\n\n\t/* always off if the enable is off */\n\tif (!chip->irq_enable)\n\t\tirq_bits = 0;\n\n\t/* update the state if changed */\n\tif (irq_bits && !chip->irq_state)\n\t{\n\t\tchip->irq_state = 1;\n\t\tif (chip->irq_callback)\n\t\t\t//(*chip->irq_callback)(chip->device, 1);\n\t\t\t(*chip->irq_callback)(1);\n\t\t//else logerror(\"YMZ280B: IRQ generated, but no callback specified!\");\n\t}\n\telse if (!irq_bits && chip->irq_state)\n\t{\n\t\tchip->irq_state = 0;\n\t\tif (chip->irq_callback)\n\t\t\t//(*chip->irq_callback)(chip->device, 0);\n\t\t\t(*chip->irq_callback)(0);\n\t\t//else logerror(\"YMZ280B: IRQ generated, but no callback specified!\");\n\t}\n}\n\n\nINLINE void update_step(ymz280b_state *chip, struct YMZ280BVoice *voice)\n{\n\tdouble frequency;\n\n\t/* compute the frequency */\n\tif (voice->mode == 1)\n\t\tfrequency = chip->master_clock * (double)((voice->fnum & 0x0ff) + 1) * (1.0 / 256.0);\n\telse\n\t\tfrequency = chip->master_clock * (double)((voice->fnum & 0x1ff) + 1) * (1.0 / 256.0);\n\tvoice->output_step = (UINT32)(frequency * (double)FRAC_ONE / INTERNAL_SAMPLE_RATE);\n}\n\n\nINLINE void update_volumes(struct YMZ280BVoice *voice)\n{\n\tif (voice->pan == 8)\n\t{\n\t\tvoice->output_left = voice->level;\n\t\tvoice->output_right = voice->level;\n\t}\n\telse if (voice->pan < 8)\n\t{\n\t\tvoice->output_left = voice->level;\n\n\t\t/* pan 1 is hard-left, what's pan 0? for now assume same as pan 1 */\n\t\tvoice->output_right = (voice->pan == 0) ? 0 : voice->level * (voice->pan - 1) / 7;\n\t}\n\telse\n\t{\n\t\tvoice->output_left = voice->level * (15 - voice->pan) / 7;\n\t\tvoice->output_right = voice->level;\n\t}\n}\n\n\n//static STATE_POSTLOAD( YMZ280B_state_save_update_step )\n/*void YMZ280B_state_save_update_step(void *param)\n{\n\tymz280b_state *chip = (ymz280b_state *)param;\n\tint j;\n\tfor (j = 0; j < 8; j++)\n\t{\n\t\tstruct YMZ280BVoice *voice = &chip->voice[j];\n\t\tupdate_step(chip, voice);\n\t\tif(voice->irq_schedule)\n\t\t//\ttimer_set(machine, attotime_zero, chip, 0, update_irq_state_cb[j]);\n\t\t\tupdate_irq_state_timer_common(param, j);\n\t}\n}*/\n\n\nINLINE UINT8 ymz280b_read_memory(UINT8 *base, UINT32 size, UINT32 offset)\n{\n\toffset &= 0xFFFFFF;\n\tif (offset < size)\n\t\treturn base[offset];\n\n\t/* 16MB chip limit (shouldn't happen) */\n\t//else if (offset > 0xffffff)\n\t//\treturn base[offset & 0xffffff];\n\n\telse\n\t\treturn 0;\n}\n\n\nstatic void update_irq_state_timer_common(void *param, int voicenum)\n{\n\tymz280b_state *chip = (ymz280b_state *)param;\n\tstruct YMZ280BVoice *voice = &chip->voice[voicenum];\n\n\tif(!voice->irq_schedule) return;\n\n\tvoice->playing = 0;\n\tchip->status_register |= 1 << voicenum;\n\tupdate_irq_state(chip);\n\tvoice->irq_schedule = 0;\n}\n\n/*static TIMER_CALLBACK( update_irq_state_timer_0 ) { update_irq_state_timer_common(ptr, 0); }\nstatic TIMER_CALLBACK( update_irq_state_timer_1 ) { update_irq_state_timer_common(ptr, 1); }\nstatic TIMER_CALLBACK( update_irq_state_timer_2 ) { update_irq_state_timer_common(ptr, 2); }\nstatic TIMER_CALLBACK( update_irq_state_timer_3 ) { update_irq_state_timer_common(ptr, 3); }\nstatic TIMER_CALLBACK( update_irq_state_timer_4 ) { update_irq_state_timer_common(ptr, 4); }\nstatic TIMER_CALLBACK( update_irq_state_timer_5 ) { update_irq_state_timer_common(ptr, 5); }\nstatic TIMER_CALLBACK( update_irq_state_timer_6 ) { update_irq_state_timer_common(ptr, 6); }\nstatic TIMER_CALLBACK( update_irq_state_timer_7 ) { update_irq_state_timer_common(ptr, 7); }*/\n\n\n/**********************************************************************************************\n\n     compute_tables -- compute the difference tables\n\n***********************************************************************************************/\n\nstatic void compute_tables(void)\n{\n\tint nib;\n\n\tif (lookup_init)\n\t\treturn;\n\n\t/* loop over all nibbles and compute the difference */\n\tfor (nib = 0; nib < 16; nib++)\n\t{\n\t\tint value = (nib & 0x07) * 2 + 1;\n\t\tdiff_lookup[nib] = (nib & 0x08) ? -value : value;\n\t}\n\t\n\tlookup_init = 0x01;\n}\n\n\n\n/**********************************************************************************************\n\n     generate_adpcm -- general ADPCM decoding routine\n\n***********************************************************************************************/\n\nstatic int generate_adpcm(struct YMZ280BVoice *voice, UINT8 *base, UINT32 size, INT16 *buffer, int samples)\n{\n\tint position = voice->position;\n\tint signal = voice->signal;\n\tint step = voice->step;\n\tint val;\n\n\t/*if (! DISABLE_YMZ_FIX)\n\t{\n\t\tif (position >= voice->stop)\n\t\t{\n\t\t\tvoice->playing = 0;\n\t\t\treturn samples;\n\t\t}\n\t}*/\n\n\t/* two cases: first cases is non-looping */\n\tif (!voice->looping)\n\t{\n\t\t/* loop while we still have samples to generate */\n\t\twhile (samples)\n\t\t{\n\t\t\t/* compute the new amplitude and update the current step */\n\t\t\t//val = base[position / 2] >> ((~position & 1) << 2);\n\t\t\tval = ymz280b_read_memory(base, size, position / 2) >> ((~position & 1) << 2);\n\t\t\tsignal = (signal * 254) / 256;\n\t\t\tsignal += (step * diff_lookup[val & 15]) / 8;\n\n\t\t\t/* clamp to the maximum */\n\t\t\tif (signal > 32767)\n\t\t\t\tsignal = 32767;\n\t\t\telse if (signal < -32768)\n\t\t\t\tsignal = -32768;\n\n\t\t\t/* adjust the step size and clamp */\n\t\t\tstep = (step * index_scale[val & 7]) >> 8;\n\t\t\tif (step > 0x6000)\n\t\t\t\tstep = 0x6000;\n\t\t\telse if (step < 0x7f)\n\t\t\t\tstep = 0x7f;\n\n\t\t\t/* output to the buffer, scaling by the volume */\n\t\t\t*buffer++ = signal;\n\t\t\tsamples--;\n\n\t\t\t/* next! */\n\t\t\tposition++;\n\t\t\tif (position >= voice->stop)\n\t\t\t{\n\t\t\t\tif (!samples)\n\t\t\t\t\tsamples |= 0x10000;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* second case: looping */\n\telse\n\t{\n\t\t/* loop while we still have samples to generate */\n\t\twhile (samples)\n\t\t{\n\t\t\t/* compute the new amplitude and update the current step */\n\t\t\t//val = base[position / 2] >> ((~position & 1) << 2);\n\t\t\tval = ymz280b_read_memory(base, size, position / 2) >> ((~position & 1) << 2);\n\t\t\tsignal = (signal * 254) / 256;\n\t\t\tsignal += (step * diff_lookup[val & 15]) / 8;\n\n\t\t\t/* clamp to the maximum */\n\t\t\tif (signal > 32767)\n\t\t\t\tsignal = 32767;\n\t\t\telse if (signal < -32768)\n\t\t\t\tsignal = -32768;\n\n\t\t\t/* adjust the step size and clamp */\n\t\t\tstep = (step * index_scale[val & 7]) >> 8;\n\t\t\tif (step > 0x6000)\n\t\t\t\tstep = 0x6000;\n\t\t\telse if (step < 0x7f)\n\t\t\t\tstep = 0x7f;\n\n\t\t\t/* output to the buffer, scaling by the volume */\n\t\t\t*buffer++ = signal;\n\t\t\tsamples--;\n\n\t\t\t/* next! */\n\t\t\tposition++;\n\t\t\tif (position == voice->loop_start && voice->loop_count == 0)\n\t\t\t{\n\t\t\t\tvoice->loop_signal = signal;\n\t\t\t\tvoice->loop_step = step;\n\t\t\t}\n\t\t\tif (position >= voice->loop_end)\n\t\t\t{\n\t\t\t\tif (voice->keyon)\n\t\t\t\t{\n\t\t\t\t\tposition = voice->loop_start;\n\t\t\t\t\tsignal = voice->loop_signal;\n\t\t\t\t\tstep = voice->loop_step;\n\t\t\t\t\tvoice->loop_count++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (position >= voice->stop)\n\t\t\t{\n\t\t\t\tif (!samples)\n\t\t\t\t\tsamples |= 0x10000;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* update the parameters */\n\tvoice->position = position;\n\tvoice->signal = signal;\n\tvoice->step = step;\n\n\treturn samples;\n}\n\n\n\n/**********************************************************************************************\n\n     generate_pcm8 -- general 8-bit PCM decoding routine\n\n***********************************************************************************************/\n\nstatic int generate_pcm8(struct YMZ280BVoice *voice, UINT8 *base, UINT32 size, INT16 *buffer, int samples)\n{\n\tint position = voice->position;\n\tint val;\n\n\t/*if (! DISABLE_YMZ_FIX)\n\t{\n\t\tif (position >= voice->stop)\n\t\t{\n\t\t\tvoice->playing = 0;\n\t\t\treturn samples;\n\t\t}\n\t}*/\n\n\t/* two cases: first cases is non-looping */\n\tif (!voice->looping)\n\t{\n\t\t/* loop while we still have samples to generate */\n\t\twhile (samples)\n\t\t{\n\t\t\t/* fetch the current value */\n\t\t\t//val = base[position / 2];\n\t\t\tval = ymz280b_read_memory(base, size, position / 2);\n\n\t\t\t/* output to the buffer, scaling by the volume */\n\t\t\t*buffer++ = (INT8)val * 256;\n\t\t\tsamples--;\n\n\t\t\t/* next! */\n\t\t\tposition += 2;\n\t\t\tif (position >= voice->stop)\n\t\t\t{\n\t\t\t\tif (!samples)\n\t\t\t\t\tsamples |= 0x10000;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* second case: looping */\n\telse\n\t{\n\t\t/* loop while we still have samples to generate */\n\t\twhile (samples)\n\t\t{\n\t\t\t/* fetch the current value */\n\t\t\t//val = base[position / 2];\n\t\t\tval = ymz280b_read_memory(base, size, position / 2);\n\n\t\t\t/* output to the buffer, scaling by the volume */\n\t\t\t*buffer++ = (INT8)val * 256;\n\t\t\tsamples--;\n\n\t\t\t/* next! */\n\t\t\tposition += 2;\n\t\t\tif (position >= voice->loop_end)\n\t\t\t{\n\t\t\t\tif (voice->keyon)\n\t\t\t\t\tposition = voice->loop_start;\n\t\t\t}\n\t\t\tif (position >= voice->stop)\n\t\t\t{\n\t\t\t\tif (!samples)\n\t\t\t\t\tsamples |= 0x10000;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* update the parameters */\n\tvoice->position = position;\n\n\treturn samples;\n}\n\n\n\n/**********************************************************************************************\n\n     generate_pcm16 -- general 16-bit PCM decoding routine\n\n***********************************************************************************************/\n\nstatic int generate_pcm16(struct YMZ280BVoice *voice, UINT8 *base, UINT32 size, INT16 *buffer, int samples)\n{\n\tint position = voice->position;\n\tint val;\n\n\t/*if (! DISABLE_YMZ_FIX)\n\t{\n\t\tif (position >= voice->stop)\n\t\t{\n\t\t\tvoice->playing = 0;\n\t\t\treturn samples;\n\t\t}\n\t}*/\n\n\t/* is it even used in any MAME game? */\n\t//popmessage(\"YMZ280B 16-bit PCM contact MAMEDEV\");\n\n\t/* two cases: first cases is non-looping */\n\tif (!voice->looping)\n\t{\n\t\t/* loop while we still have samples to generate */\n\t\twhile (samples)\n\t\t{\n\t\t\t/* fetch the current value */\n\t\t\t// the manual says \"16-bit 2's complement MSB-first format\"\n\t\t\t//val = (INT16)((base[position / 2 + 0] << 8) + base[position / 2 + 1]);\n\t\t\tval = (INT16)((ymz280b_read_memory(base, size, position / 2 + 0) << 8) + ymz280b_read_memory(base, size, position / 2 + 1));\n\n\t\t\t/* output to the buffer, scaling by the volume */\n\t\t\t*buffer++ = val;\n\t\t\tsamples--;\n\n\t\t\t/* next! */\n\t\t\tposition += 4;\n\t\t\tif (position >= voice->stop)\n\t\t\t{\n\t\t\t\tif (!samples)\n\t\t\t\t\tsamples |= 0x10000;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* second case: looping */\n\telse\n\t{\n\t\t/* loop while we still have samples to generate */\n\t\twhile (samples)\n\t\t{\n\t\t\t/* fetch the current value */\n\t\t\t//val = (INT16)((base[position / 2 + 0] << 8) + base[position / 2 + 1]);\n\t\t\tval = (INT16)((ymz280b_read_memory(base, size, position / 2 + 0) << 8) + ymz280b_read_memory(base, size, position / 2 + 1));\n\n\t\t\t/* output to the buffer, scaling by the volume */\n\t\t\t*buffer++ = val;\n\t\t\tsamples--;\n\n\t\t\t/* next! */\n\t\t\tposition += 4;\n\t\t\tif (position >= voice->loop_end)\n\t\t\t{\n\t\t\t\tif (voice->keyon)\n\t\t\t\t\tposition = voice->loop_start;\n\t\t\t}\n\t\t\tif (position >= voice->stop)\n\t\t\t{\n\t\t\t\tif (!samples)\n\t\t\t\t\tsamples |= 0x10000;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* update the parameters */\n\tvoice->position = position;\n\n\treturn samples;\n}\n\n\n\n/**********************************************************************************************\n\n     ymz280b_update -- update the sound chip so that it is in sync with CPU execution\n\n***********************************************************************************************/\n\n//static STREAM_UPDATE( ymz280b_update )\nvoid ymz280b_update(UINT8 ChipID, stream_sample_t **outputs, int samples)\n{\n\t//ymz280b_state *chip = (ymz280b_state *)param;\n\tymz280b_state *chip = &YMZ280BData[ChipID];\n\tstream_sample_t *lacc = outputs[0];\n\tstream_sample_t *racc = outputs[1];\n\tint v;\n\n\t/* clear out the accumulator */\n\tmemset(lacc, 0, samples * sizeof(lacc[0]));\n\tmemset(racc, 0, samples * sizeof(racc[0]));\n\n\t/* loop over voices */\n\tfor (v = 0; v < 8; v++)\n\t{\n\t\tstruct YMZ280BVoice *voice = &chip->voice[v];\n\t\tINT16 prev = voice->last_sample;\n\t\tINT16 curr = voice->curr_sample;\n\t\tINT16 *curr_data = chip->scratch;\n\t\tINT32 *ldest = lacc;\n\t\tINT32 *rdest = racc;\n\t\tUINT32 new_samples, samples_left;\n\t\tUINT32 final_pos;\n\t\tint remaining = samples;\n\t\tint lvol = voice->output_left;\n\t\tint rvol = voice->output_right;\n#if MAKE_WAVS_CH\n\t\tsigned short int* wavlog;\n\n\t\tmemset(wavmem[v], 0x00, samples * 0x02);\n\t\twavlog = wavmem[v];\n#endif\n\t\t\n\t\t/* skip if muted */\n\t\tif (voice->Muted)\n\t\t\tcontinue;\n\n\t\t/* quick out if we're not playing and we're at 0 */\n\t\tif (!voice->playing && curr == 0 && prev == 0)\n\t\t{\n\t\t\t/* make sure next sound plays immediately */\n\t\t\tvoice->output_pos = FRAC_ONE;\n\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* finish off the current sample */\n\t\t/* interpolate */\n\t\twhile (remaining > 0 && voice->output_pos < FRAC_ONE)\n\t\t{\n\t\t\tint interp_sample = (((INT32)prev * (FRAC_ONE - voice->output_pos)) + ((INT32)curr * voice->output_pos)) >> FRAC_BITS;\n\t\t\t*ldest++ += interp_sample * lvol;\n\t\t\t*rdest++ += interp_sample * rvol;\n#if MAKE_WAVS_CH\n\t\t\t*(wavlog ++) = (signed short int)interp_sample;\n#endif\n\t\t\tvoice->output_pos += voice->output_step;\n\t\t\tremaining--;\n\t\t}\n\n\t\t/* if we're over, continue; otherwise, we're done */\n\t\tif (voice->output_pos >= FRAC_ONE)\n\t\t\tvoice->output_pos -= FRAC_ONE;\n\t\telse\n\t\t\tcontinue;\n\n\t\t/* compute how many new samples we need */\n\t\tfinal_pos = voice->output_pos + remaining * voice->output_step;\n\t\tnew_samples = (final_pos + FRAC_ONE) >> FRAC_BITS;\n\t\tif (new_samples > MAX_SAMPLE_CHUNK)\n\t\t\tnew_samples = MAX_SAMPLE_CHUNK;\n\t\tsamples_left = new_samples;\n\n\t\t/* generate them into our buffer */\n\t\tswitch (voice->playing << 7 | voice->mode)\n\t\t{\n\t\t\tcase 0x81:\tsamples_left = generate_adpcm(voice, chip->region_base, chip->region_size, chip->scratch, new_samples);\t\tbreak;\n\t\t\tcase 0x82:\tsamples_left = generate_pcm8(voice, chip->region_base, chip->region_size, chip->scratch, new_samples);\t\tbreak;\n\t\t\tcase 0x83:\tsamples_left = generate_pcm16(voice, chip->region_base, chip->region_size, chip->scratch, new_samples);\t\tbreak;\n\t\t\tdefault:\tsamples_left = 0; memset(chip->scratch, 0, new_samples * sizeof(chip->scratch[0]));\t\t\t\t\t\t\tbreak;\n\t\t}\n\n\t\t/* if there are leftovers, ramp back to 0 */\n\t\tif (samples_left)\n\t\t{\n\t\t\t/* note: samples_left bit 16 is set if the voice was finished at the same time the function ended */\n\t\t\tint base;\n\t\t\tint i, t;\n\t\t\t\n\t\t\tsamples_left &= 0xffff;\n\t\t\tbase = new_samples - samples_left;\n\t\t\tt = (base == 0) ? curr : chip->scratch[base - 1];\n\t\t\t\n\t\t\tfor (i = 0; i < samples_left; i++)\n\t\t\t{\n\t\t\t\tif (t < 0) t = -((-t * 15) >> 4);\n\t\t\t\telse if (t > 0) t = (t * 15) >> 4;\n\t\t\t\tchip->scratch[base + i] = t;\n\t\t\t}\n\n\t\t\t/* if we hit the end and IRQs are enabled, signal it */\n\t\t\tif (base != 0)\n\t\t\t{\n\t\t\t\tvoice->playing = 0;\n\n\t\t\t\t/* set update_irq_state_timer. IRQ is signaled on next CPU execution. */\n\t\t\t\t//timer_set(chip->device->machine, attotime_zero, chip, 0, update_irq_state_cb[v]);\n\t\t\t\tvoice->irq_schedule = 1;\n\t\t\t}\n\t\t}\n\n\t\t/* advance forward one sample */\n\t\tprev = curr;\n\t\tcurr = *curr_data++;\n\n\t\t/* then sample-rate convert with linear interpolation */\n\t\twhile (remaining > 0)\n\t\t{\n\t\t\t/* interpolate */\n\t\t\twhile (remaining > 0 && voice->output_pos < FRAC_ONE)\n\t\t\t{\n\t\t\t\tint interp_sample = (((INT32)prev * (FRAC_ONE - voice->output_pos)) + ((INT32)curr * voice->output_pos)) >> FRAC_BITS;\n\t\t\t\t*ldest++ += interp_sample * lvol;\n\t\t\t\t*rdest++ += interp_sample * rvol;\n#if MAKE_WAVS_CH\n\t\t\t\t*(wavlog ++) = (signed short int)interp_sample;\n#endif\n\t\t\t\tvoice->output_pos += voice->output_step;\n\t\t\t\tremaining--;\n\t\t\t}\n\n\t\t\t/* if we're over, grab the next samples */\n\t\t\tif (voice->output_pos >= FRAC_ONE)\n\t\t\t{\n\t\t\t\tvoice->output_pos -= FRAC_ONE;\n\t\t\t\tprev = curr;\n\t\t\t\tcurr = *curr_data++;\n\t\t\t}\n\t\t}\n\n\t\t/* remember the last samples */\n\t\tvoice->last_sample = prev;\n\t\tvoice->curr_sample = curr;\n\t}\n\n\tfor (v = 0; v < samples; v++)\n\t{\n\t\toutputs[0][v] /= 256;\n\t\toutputs[1][v] /= 256;\n\t}\n\t\n\tfor (v = 0; v < 8; v++)\n\t\tupdate_irq_state_timer_common(chip, v);\n\t\n#if MAKE_WAVS_CH\n\tfor (v = 0; v < 8; v++)\n\t{\n\t\tfwrite(wavmem[v], 0x02, samples, hWavFile[v]);\n\t}\n#endif\n}\n\n\n\n/**********************************************************************************************\n\n     DEVICE_START( ymz280b ) -- start emulation of the YMZ280B\n\n***********************************************************************************************/\n\n//static DEVICE_START( ymz280b )\nint device_start_ymz280b(UINT8 ChipID, int clock)\n{\n\tstatic const ymz280b_interface defintrf = { 0 };\n\t//const ymz280b_interface *intf = (device->static_config != NULL) ? (const ymz280b_interface *)device->static_config : &defintrf;\n\tconst ymz280b_interface *intf = &defintrf;\n\t//ymz280b_state *chip = get_safe_token(device);\n\tymz280b_state *chip;\n\tint chn;\n\n\tif (ChipID >= MAX_CHIPS)\n\t\treturn 0;\n\t\n\tchip = &YMZ280BData[ChipID];\n\t//chip->device = device;\n\t//devcb_resolve_read8(&chip->ext_ram_read, &intf->ext_read, device);\n\t//devcb_resolve_write8(&chip->ext_ram_write, &intf->ext_write, device);\n\n\t/* compute ADPCM tables */\n\tcompute_tables();\n\n\t/* initialize the rest of the structure */\n\tchip->master_clock = (double)clock / 384.0;\n\t\n\tchip->rate = chip->master_clock * 2.0;\n\t// disabled until the frequency calculation gets fixed\n\t/*if (((CHIP_SAMPLING_MODE & 0x01) && chip->rate < CHIP_SAMPLE_RATE) ||\n\t\tCHIP_SAMPLING_MODE == 0x02)\n\t\tchip->rate = (double)CHIP_SAMPLE_RATE;*/\n\t\n\t//chip->region_base = device->region;\n\tchip->region_size = 0x00;\n\tchip->region_base = NULL;\n\tchip->irq_callback = intf->irq_callback;\n\n\t/* create the stream */\n\t//chip->stream = stream_create(device, 0, 2, INTERNAL_SAMPLE_RATE, chip, ymz280b_update);\n\n\t/* allocate memory */\n\t//chip->scratch = auto_alloc_array(device->machine, INT16, MAX_SAMPLE_CHUNK);\n\tchip->scratch = malloc(MAX_SAMPLE_CHUNK * sizeof(INT16));\n\tmemset(chip->scratch, 0x00, MAX_SAMPLE_CHUNK * sizeof(INT16));\n\n\t/* state save */\n\t/*{\n\t\tint j;\n\t\tstate_save_register_device_item(device, 0, chip->current_register);\n\t\tstate_save_register_device_item(device, 0, chip->status_register);\n\t\tstate_save_register_device_item(device, 0, chip->irq_state);\n\t\tstate_save_register_device_item(device, 0, chip->irq_mask);\n\t\tstate_save_register_device_item(device, 0, chip->irq_enable);\n\t\tstate_save_register_device_item(device, 0, chip->keyon_enable);\n\t\tstate_save_register_device_item(device, 0, chip->rom_readback_addr);\n\t\tfor (j = 0; j < 8; j++)\n\t\t{\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].playing);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].keyon);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].looping);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].mode);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].fnum);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].level);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].pan);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].start);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].stop);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].loop_start);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].loop_end);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].position);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].signal);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].step);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].loop_signal);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].loop_step);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].loop_count);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].output_left);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].output_right);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].output_pos);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].last_sample);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].curr_sample);\n\t\t\tstate_save_register_device_item(device, j, chip->voice[j].irq_schedule);\n\t\t}\n\t}*/\n\t\n\tfor (chn = 0; chn < 8; chn ++)\n\t\tchip->voice[chn].Muted = 0x00;\n\n\t//state_save_register_postload(device->machine, YMZ280B_state_save_update_step, chip);\n\n#if MAKE_WAVS\n\tchip->wavresample = wav_open(\"resamp.wav\", INTERNAL_SAMPLE_RATE, 2);\n#endif\n#if MAKE_WAVS_CH\n\thWavFile[0] = fopen(\"logwav0.raw\", \"wb\");\n\thWavFile[1] = fopen(\"logwav1.raw\", \"wb\");\n\thWavFile[2] = fopen(\"logwav2.raw\", \"wb\");\n\thWavFile[3] = fopen(\"logwav3.raw\", \"wb\");\n\thWavFile[4] = fopen(\"logwav4.raw\", \"wb\");\n\thWavFile[5] = fopen(\"logwav5.raw\", \"wb\");\n\thWavFile[6] = fopen(\"logwav6.raw\", \"wb\");\n\thWavFile[7] = fopen(\"logwav7.raw\", \"wb\");\n\t{\n\t\tchar v;\n\t\tfor (v = 0; v < 8; v++)\n\t\t{\n\t\t\twavmem[v] = (signed short int*)malloc(0x10 * 0x02);\n\t\t}\n\t}\n#endif\n\t\n\treturn (int)INTERNAL_SAMPLE_RATE;\n}\n\n//static DEVICE_STOP( ymz280b )\nvoid device_stop_ymz280b(UINT8 ChipID)\n{\n\t//ymz280b_state *chip = get_safe_token(device);\n\tymz280b_state *chip = &YMZ280BData[ChipID];\n\tfree(chip->region_base);\tchip->region_base = NULL;\n\tfree(chip->scratch);\n\t\n#if MAKE_WAVS_CH\n\t{\n\t\tchar v;\n\t\tfor (v = 0; v < 8; v++)\n\t\t{\n\t\t\tfree(wavmem[v]);\n\t\t\tfclose(hWavFile[v]);\n\t\t}\n\t}\n#endif\n\treturn;\n}\n\n//static DEVICE_RESET( ymz280b )\nvoid device_reset_ymz280b(UINT8 ChipID)\n{\n\tymz280b_state *chip = &YMZ280BData[ChipID];\n\t/*struct YMZ280BVoice *voice;\n\tunsigned char curvoc;\n\t\n\tchip->current_register = 0x00;\n\tchip->status_register = 0x00;\n\tchip->irq_state = 0x00;\n\tchip->irq_mask = 0x00;\n\tchip->irq_enable = 0x00;\n\tchip->keyon_enable = 0x00;\n\tchip->ext_mem_address = 0x000000;\n\tfor (curvoc = 0; curvoc < 8; curvoc ++)\n\t{\n\t\tvoice = &chip->voice[curvoc];\n\t\t\n\t\tvoice->playing = 0;\n\t\t\t\n\t\tvoice->keyon = 0;\n\t\tvoice->looping = 0;\n\t\tvoice->mode = 0;\n\t\tvoice->fnum = 0;\n\t\tvoice->level = 0;\n\t\tvoice->pan = 8;\n\t\t\n\t\tvoice->start = 0x000000;\n\t\tvoice->stop = 0x000000;\n\t\tvoice->loop_start = 0x000000;\n\t\tvoice->loop_end = 0x000000;\n\t\tvoice->position = 0x000000;\n\t}*/\n\t\n\t// new code from MAME 0.143u4\n\tint i;\n\n\t/* initial clear registers */\n\tfor (i = 0xff; i >= 0; i--)\n\t{\n\t\tif (i == 0x83 || (i >= 88 && i <= 0xFD))\n\t\t\tcontinue;\t// avoid too many debug messages\n\t\tchip->current_register = i;\n\t\twrite_to_register(chip, 0);\n\t}\n\n\tchip->current_register = 0;\n\tchip->status_register = 0;\n\n\t/* clear other voice parameters */\n\tfor (i = 0; i < 8; i++)\n\t{\n\t\tstruct YMZ280BVoice *voice = &chip->voice[i];\n\n\t\tvoice->curr_sample = 0;\n\t\tvoice->last_sample = 0;\n\t\tvoice->output_pos = FRAC_ONE;\n\t\tvoice->playing = 0;\n\t}\n\t\n\treturn;\n}\n\n\n/**********************************************************************************************\n\n     write_to_register -- handle a write to the current register\n\n***********************************************************************************************/\n\nstatic void write_to_register(ymz280b_state *chip, int data)\n{\n\tstruct YMZ280BVoice *voice;\n\tint i;\n\t//UINT8 mode_new;\n\n\t/* force an update */\n\t//stream_update(chip->stream);\n\n\t/* lower registers follow a pattern */\n\tif (chip->current_register < 0x80)\n\t{\n\t\tvoice = &chip->voice[(chip->current_register >> 2) & 7];\n\n\t\tswitch (chip->current_register & 0xe3)\n\t\t{\n\t\t\tcase 0x00:\t\t/* pitch low 8 bits */\n\t\t\t\tvoice->fnum = (voice->fnum & 0x100) | (data & 0xff);\n\t\t\t\tupdate_step(chip, voice);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x01:\t\t/* pitch upper 1 bit, loop, key on, mode */\n\t\t\t\tvoice->fnum = (voice->fnum & 0xff) | ((data & 0x01) << 8);\n\t\t\t\tvoice->looping = (data & 0x10) >> 4;\n\t\t\t\t/*mode_new = (data & 0x60) >> 5;\n\t\t\t\tif (! DISABLE_YMZ_FIX)\n\t\t\t\t{\n\t\t\t\t\t// that fixes the scratch-bug\n\t\t\t\t\tif (voice->mode != mode_new)\n\t\t\t\t\t{\n\t\t\t\t\t\t// On-the-fly Mode-Change won't make sense,\n\t\t\t\t\t\t//\tso I'm doing: KeyOff + Mode Change -> Instant Stop.\n\t\t\t\t\t\t//\t(Deroon DeroDero uses this quite often)\n\t\t\t\t\t\t//\tThis is done by setting KeyOn to 0.\n\t\t\t\t\t\t//\tInstant Stop/Restarting is done below.\n\t\t\t\t\t\tvoice->keyon = 0;\n\t\t\t\t\t\tvoice->irq_schedule = 0;\n\t\t\t\t\t}\n\t\t\t\t\tif (! mode_new)\n\t\t\t\t\t\tdata &= 0x7F;\n\t\t\t\t}\n\t\t\t\tvoice->mode = mode_new;*/\n\t\t\t\tif ((data & 0x60) == 0) data &= 0x7f; /* ignore mode setting and set to same state as KON=0 */\n\t\t\t\telse voice->mode = (data & 0x60) >> 5;\n\t\t\t\t\n\t\t\t\tif (!voice->keyon && (data & 0x80) && chip->keyon_enable)\n\t\t\t\t{\n\t\t\t\t\tvoice->playing = 1;\n\t\t\t\t\tvoice->position = voice->start;\n\t\t\t\t\tvoice->signal = voice->loop_signal = 0;\n\t\t\t\t\tvoice->step = voice->loop_step = 0x7f;\n\t\t\t\t\tvoice->loop_count = 0;\n\n\t\t\t\t\t/* if update_irq_state_timer is set, cancel it. */\n\t\t\t\t\tvoice->irq_schedule = 0;\n\t\t\t\t}\n\t\t\t\t/*else if (voice->keyon && !(data & 0x80) && !voice->looping)\n\t\t\t\t{\n\t\t\t\t\tvoice->playing = 0;\n\n\t\t\t\t\t// if update_irq_state_timer is set, cancel it.\n\t\t\t\t\tvoice->irq_schedule = 0;\n\t\t\t\t}\n\t\t\t\telse if (! DISABLE_YMZ_FIX && ! voice->keyon && !(data & 0x80) && voice->playing)\n\t\t\t\t{\n\t\t\t\t\t// 2x KeyOff -> Instant Stop, too (see Deroon DeroDero: Round Start-Tune)\n\t\t\t\t\tvoice->playing = 0;\n\t\t\t\t\tvoice->irq_schedule = 0;\n\t\t\t\t}*/\n\t\t\t\t// new code from MAME 0.143u4\n\t\t\t\telse if (voice->keyon && !(data & 0x80))\n\t\t\t\t{\n\t\t\t\t\tvoice->playing = 0;\n\n\t\t\t\t\t// if update_irq_state_timer is set, cancel it.\n\t\t\t\t\tvoice->irq_schedule = 0;\n\t\t\t\t}\n\t\t\t\tvoice->keyon = (data & 0x80) >> 7;\n\t\t\t\tupdate_step(chip, voice);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x02:\t\t/* total level */\n\t\t\t\tvoice->level = data;\n\t\t\t\tupdate_volumes(voice);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x03:\t\t/* pan */\n\t\t\t\tvoice->pan = data & 0x0f;\n\t\t\t\tupdate_volumes(voice);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x20:\t\t/* start address high */\n\t\t\t\tvoice->start = (voice->start & (0x00ffff << 1)) | (data << 17);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x21:\t\t/* loop start address high */\n\t\t\t\tvoice->loop_start = (voice->loop_start & (0x00ffff << 1)) | (data << 17);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x22:\t\t/* loop end address high */\n\t\t\t\tvoice->loop_end = (voice->loop_end & (0x00ffff << 1)) | (data << 17);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x23:\t\t/* stop address high */\n\t\t\t\tvoice->stop = (voice->stop & (0x00ffff << 1)) | (data << 17);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x40:\t\t/* start address middle */\n\t\t\t\tvoice->start = (voice->start & (0xff00ff << 1)) | (data << 9);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x41:\t\t/* loop start address middle */\n\t\t\t\tvoice->loop_start = (voice->loop_start & (0xff00ff << 1)) | (data << 9);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x42:\t\t/* loop end address middle */\n\t\t\t\tvoice->loop_end = (voice->loop_end & (0xff00ff << 1)) | (data << 9);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x43:\t\t/* stop address middle */\n\t\t\t\tvoice->stop = (voice->stop & (0xff00ff << 1)) | (data << 9);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x60:\t\t/* start address low */\n\t\t\t\tvoice->start = (voice->start & (0xffff00 << 1)) | (data << 1);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x61:\t\t/* loop start address low */\n\t\t\t\tvoice->loop_start = (voice->loop_start & (0xffff00 << 1)) | (data << 1);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x62:\t\t/* loop end address low */\n\t\t\t\tvoice->loop_end = (voice->loop_end & (0xffff00 << 1)) | (data << 1);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x63:\t\t/* stop address low */\n\t\t\t\tvoice->stop = (voice->stop & (0xffff00 << 1)) | (data << 1);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n#ifdef _DEBUG\n\t\t\t\tlogerror(\"YMZ280B: unknown register write %02X = %02X\\n\", chip->current_register, data);\n#endif\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* upper registers are special */\n\telse\n\t{\n\t\tswitch (chip->current_register)\n\t\t{\n\t\t\t/* DSP related (not implemented yet) */\n\t\t\tcase 0x80: // d0-2: DSP Rch, d3: enable Rch (0: yes, 1: no), d4-6: DSP Lch, d7: enable Lch (0: yes, 1: no)\n\t\t\tcase 0x81: // d0: enable control of $82 (0: yes, 1: no)\n\t\t\tcase 0x82: // DSP data\n\t\t\t\tlogerror(\"YMZ280B: DSP register write %02X = %02X\\n\", chip->current_register, data);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x84:\t\t/* ROM readback / RAM write (high) */\n\t\t\t\tchip->ext_mem_address_hi = data << 16;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x85:\t\t/* ROM readback / RAM write (middle) */\n\t\t\t\tchip->ext_mem_address_mid = data << 8;\n\t\t\t\tbreak;\n\n\t\t\tcase 0x86:      /* ROM readback / RAM write (low) -> update latch */\n\t\t\t\tchip->ext_mem_address = chip->ext_mem_address_hi | chip->ext_mem_address_mid | data;\n\t\t\t\tif (chip->ext_mem_enable)\n\t\t\t\t\tchip->ext_readlatch = ymz280b_read_memory(chip->region_base, chip->region_size, chip->ext_mem_address);\n\t\t\t\tbreak;\n\n\t\t\tcase 0x87:\t\t/* RAM write */\n\t\t\t\tif (chip->ext_mem_enable)\n\t\t\t\t{\n\t\t\t\t\t/*if (!chip->ext_ram_write.isnull())\n\t\t\t\t\t\tchip->ext_ram_write(chip->ext_mem_address, data);\n\t\t\t\t\telse\n\t\t\t\t\t\tlogerror(\"YMZ280B attempted RAM write to %X\\n\", chip->ext_mem_address);*/\n\t\t\t\t\tchip->ext_mem_address = (chip->ext_mem_address + 1) & 0xffffff;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 0xfe:\t\t/* IRQ mask */\n\t\t\t\tchip->irq_mask = data;\n\t\t\t\tupdate_irq_state(chip);\n\t\t\t\tbreak;\n\n\t\t\tcase 0xff:\t\t/* IRQ enable, test, etc */\n\t\t\t\tchip->ext_mem_enable = (data & 0x40) >> 6;\n\t\t\t\tchip->irq_enable = (data & 0x10) >> 4;\n\t\t\t\tupdate_irq_state(chip);\n\n\t\t\t\tif (chip->keyon_enable && !(data & 0x80))\n\t\t\t\t{\n\t\t\t\t\tfor (i = 0; i < 8; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tchip->voice[i].playing = 0;\n\n\t\t\t\t\t\t/* if update_irq_state_timer is set, cancel it. */\n\t\t\t\t\t\tchip->voice[i].irq_schedule = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (!chip->keyon_enable && (data & 0x80))\n\t\t\t\t{\n\t\t\t\t\tfor (i = 0; i < 8; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (chip->voice[i].keyon && chip->voice[i].looping)\n\t\t\t\t\t\t\tchip->voice[i].playing = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tchip->keyon_enable = (data & 0x80) >> 7;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n#ifdef _DEBUG\n\t\t\t\tlogerror(\"YMZ280B: unknown register write %02X = %02X\\n\", chip->current_register, data);\n#endif\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n\n/**********************************************************************************************\n\n     compute_status -- determine the status bits\n\n***********************************************************************************************/\n\nstatic int compute_status(ymz280b_state *chip)\n{\n\tUINT8 result;\n\n\t/* force an update */\n\t//stream_update(chip->stream);\n\n\tresult = chip->status_register;\n\n\t/* clear the IRQ state */\n\tchip->status_register = 0;\n\tupdate_irq_state(chip);\n\n\treturn result;\n}\n\n\n\n/**********************************************************************************************\n\n     ymz280b_r/ymz280b_w -- handle external accesses\n\n***********************************************************************************************/\n\n//READ8_DEVICE_HANDLER( ymz280b_r )\nUINT8 ymz280b_r(UINT8 ChipID, offs_t offset)\n{\n\t//ymz280b_state *chip = get_safe_token(device);\n\tymz280b_state *chip = &YMZ280BData[ChipID];\n\n\tif ((offset & 1) == 0)\n\t{\n\t\tUINT8 ret;\n\t\t\n\t\tif (! chip->ext_mem_enable)\n\t\t\treturn 0xff;\n\n\t\t/* read from external memory */\n\t\tret = chip->ext_readlatch;\n\t\tret = ymz280b_read_memory(chip->region_base, chip->region_size, chip->ext_mem_address);\n\t\tchip->ext_mem_address = (chip->ext_mem_address + 1) & 0xffffff;\n\t\treturn ret;\n\t}\n\telse\n\t{\n\t\treturn compute_status(chip);\n\t}\n}\n\n\n//WRITE8_DEVICE_HANDLER( ymz280b_w )\nvoid ymz280b_w(UINT8 ChipID, offs_t offset, UINT8 data)\n{\n\t//ymz280b_state *chip = get_safe_token(device);\n\tymz280b_state *chip = &YMZ280BData[ChipID];\n\n\tif ((offset & 1) == 0)\n\t\tchip->current_register = data;\n\telse\n\t{\n\t\t/* force an update */\n\t\t//chip->stream->update();\n\n\t\twrite_to_register(chip, data);\n\t}\n}\n\nvoid ymz280b_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData)\n{\n\tymz280b_state *chip = &YMZ280BData[ChipID];\n\t\n\tif (chip->region_size != ROMSize)\n\t{\n\t\tchip->region_base = (UINT8*)realloc(chip->region_base, ROMSize);\n\t\tchip->region_size = ROMSize;\n\t\tmemset(chip->region_base, 0xFF, ROMSize);\n\t}\n\tif (DataStart > ROMSize)\n\t\treturn;\n\tif (DataStart + DataLength > ROMSize)\n\t\tDataLength = ROMSize - DataStart;\n\t\n\tmemcpy(chip->region_base + DataStart, ROMData, DataLength);\n\t\n\treturn;\n}\n\n\nvoid ymz280b_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)\n{\n\tymz280b_state *chip = &YMZ280BData[ChipID];\n\tUINT8 CurChn;\n\t\n\tfor (CurChn = 0; CurChn < 8; CurChn ++)\n\t\tchip->voice[CurChn].Muted = (MuteMask >> CurChn) & 0x01;\n\t\n\treturn;\n}\n\n\n\n/**************************************************************************\n * Generic get_info\n **************************************************************************/\n\n/*DEVICE_GET_INFO( ymz280b )\n{\n\tswitch (state)\n\t{\n\t\t// --- the following bits of info are returned as 64-bit signed integers ---\n\t\tcase DEVINFO_INT_TOKEN_BYTES:\t\t\t\t\tinfo->i = sizeof(ymz280b_state);\t\t\tbreak;\n\n\t\t// --- the following bits of info are returned as pointers to data or functions ---\n\t\tcase DEVINFO_FCT_START:\t\t\t\t\t\t\tinfo->start = DEVICE_START_NAME( ymz280b );\t\tbreak;\n\t\tcase DEVINFO_FCT_STOP:\t\t\t\t\t\t\t// Nothing\t\t\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_FCT_RESET:\t\t\t\t\t\t\tinfo->start = DEVICE_RESET_NAME( ymz280b );\t\tbreak;\n\n\t\t// --- the following bits of info are returned as NULL-terminated strings ---\n\t\tcase DEVINFO_STR_NAME:\t\t\t\t\t\t\tstrcpy(info->s, \"YMZ280B\");\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_FAMILY:\t\t\t\t\tstrcpy(info->s, \"Yamaha Wavetable\");\t\t\tbreak;\n\t\tcase DEVINFO_STR_VERSION:\t\t\t\t\tstrcpy(info->s, \"1.0\");\t\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_SOURCE_FILE:\t\t\t\t\t\tstrcpy(info->s, __FILE__);\t\t\t\t\t\tbreak;\n\t\tcase DEVINFO_STR_CREDITS:\t\t\t\t\tstrcpy(info->s, \"Copyright Nicola Salmoria and the MAME Team\"); break;\n\t}\n}*/\n\n"
  },
  {
    "path": "VGMPlay/chips/ymz280b.h",
    "content": "/**********************************************************************************************\n *\n *   Yamaha YMZ280B driver\n *   by Aaron Giles\n *\n **********************************************************************************************/\n\n#pragma once\n\n//#include \"devcb.h\"\n\ntypedef struct _ymz280b_interface ymz280b_interface;\nstruct _ymz280b_interface\n{\n\t//void (*irq_callback)(const device_config *device, int state);\t/* irq callback */\n\tvoid (*irq_callback)(int state);\t/* irq callback */\n\t//devcb_read8 ext_read;\t\t\t/* external RAM read */\n\t//devcb_write8 ext_write;\t\t/* external RAM write */\n};\n\n/*READ8_DEVICE_HANDLER ( ymz280b_r );\nWRITE8_DEVICE_HANDLER( ymz280b_w );\n\nDEVICE_GET_INFO( ymz280b );\n#define SOUND_YMZ280B DEVICE_GET_INFO_NAME( ymz280b )*/\n\nvoid ymz280b_update(UINT8 ChipID, stream_sample_t **outputs, int samples);\nint device_start_ymz280b(UINT8 ChipID, int clock);\nvoid device_stop_ymz280b(UINT8 ChipID);\nvoid device_reset_ymz280b(UINT8 ChipID);\n\nUINT8 ymz280b_r(UINT8 ChipID, offs_t offset);\nvoid ymz280b_w(UINT8 ChipID, offs_t offset, UINT8 data);\nvoid ymz280b_write_rom(UINT8 ChipID, offs_t ROMSize, offs_t DataStart, offs_t DataLength,\n\t\t\t\t\t   const UINT8* ROMData);\n\nvoid ymz280b_set_mute_mask(UINT8 ChipID, UINT32 MuteMask);\n"
  },
  {
    "path": "VGMPlay/dbus.c",
    "content": "/*\nDBus/MPRIS for VGMPlay.\nBy Tasos Sahanidis <vgmsrc@tasossah.com>\n\nrequired packages:\nlibdbus-1-dev\n\ncompiling:\nCFLAGS=$(pkg-config --cflags dbus-1)\nLDFLAGS=$(pkg-config --libs dbus-1)\n\nThey weren't lying when they said that using libdbus directly signs you up for some pain...\n*/\n\n#define _GNU_SOURCE\n#include <stdio.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include <dbus/dbus.h>\n#include \"chips/mamedef.h\"          // for UINT8\n#include \"mmkeys.h\"\n#include <inttypes.h>\n#include \"dbus.h\"\n#include \"stdbool.h\"\n#include \"VGMPlay.h\"                // For VGMFile.h and CHIP_COUNT\n#include <errno.h>\n#include <locale.h>\n#include <wchar.h>\n#include <limits.h>\n#include <glob.h>\n#include \"VGMPlay_Intf.h\"\n\n// DBus MPRIS Constants\n#define DBUS_MPRIS_PATH             \"/org/mpris/MediaPlayer2\"\n#define DBUS_MPRIS_MEDIAPLAYER2     \"org.mpris.MediaPlayer2\"\n#define DBUS_MPRIS_PLAYER           \"org.mpris.MediaPlayer2.Player\"\n#define DBUS_MPRIS_VGMPLAY          \"org.mpris.MediaPlayer2.vgmplay\"\n#define DBUS_PROPERTIES             \"org.freedesktop.DBus.Properties\"\n\n//#define DBUS_DEBUG\n\n#ifdef DBUS_DEBUG\n#define ART_EXISTS_PRINTF(x)    fprintf(stderr, \"\\nTrying %s\\n\", (x));\n#else\n#define ART_EXISTS_PRINTF(x)\n#endif\n\n#define ART_EXISTS(path)        ART_EXISTS_PRINTF(path) \\\n                                if(FileExists((path))) { \\\n                                    free(basepath); \\\n                                    return; \\\n                                }\n\nstatic mmkey_cbfunc evtCallback = NULL;\n\nextern INT32 VGMSmplPlayed;\nextern UINT32 SampleRate;\nextern GD3_TAG VGMTag;\nextern wchar_t* GetTagStrEJ(const wchar_t* EngTag, const wchar_t* JapTag);\nextern INT32 SampleVGM2Playback(INT32 SampleVal);\nextern VGM_HEADER VGMHead;\n\n// Playlist status\nextern UINT32 PLFileCount;\nextern UINT32 CurPLFile;\nextern UINT8 PLMode;\n\n// Playlist Vars\nextern char PLFileName[];\n\n// Playback Status\nextern UINT8 PlayingMode;\nextern bool PausePlay;\n\nDBusConnection* dbus_connection = NULL;\n\n// Seek Function\nextern void SeekVGM(bool Relative, INT32 PlayBkSamples);\n\n// Filename\nextern char VgmFileName[];\n\nextern char* GetLastDirSeparator(const char* FilePath);\n\n// Needed for loop detection\nstatic UINT32 OldLoopCount;\nextern UINT32 VGMCurLoop;\n\n// MPRIS Metadata Struct\ntypedef struct DBusMetadata_\n{\n    const void* title;\n    const char* dbusType;\n    const void* content;\n    int contentType;\n    size_t childLen;\n} DBusMetadata;\n\n// Cached art path\nstatic char* cached_artpath = NULL;\n// Effectively the allocation size of cached_artpath, including the terminator\nstatic size_t pathmax = 0;\n\n// Misc Helper Functions\n\nstatic inline void invalidateArtCache()\n{\n    *cached_artpath = '\\0';\n}\n\nstatic char* wcharToUTF8(wchar_t* GD3)\n{\n    size_t len = wcstombs(NULL, GD3, 0) + 1;\n    char* out = malloc(len);\n    wcstombs(out, GD3, len);\n    return out;\n}\n\nstatic char* urlencode(const char* str)\n{\n    size_t len = strlen(str);\n    // Don't try to encode blank strings\n    if(!len)\n        return calloc(1, sizeof(char));\n\n    // strlen(\"file://\") + max str size + \\0\n    char* newstring = malloc(7 + len * 3 + 1);\n    char* loop = newstring;\n    loop += sprintf(loop, \"%s\", \"file://\");\n    for(size_t i = 0; i < len; i++)\n    {\n        // http://www.blooberry.com/indexdot/html/topics/urlencoding.htm\n        unsigned char c = (unsigned char)str[i];\n        switch(c)\n        {\n            case 32:\n            case 36:\n            case 38:\n            case 43:\n            case 44:\n            case 58:\n            case 59:\n            case 61:\n            case 63:\n            case 64:\n                loop += sprintf(loop, \"%%%02X\", c);\n                break;\n            default:\n                if(c > 127)\n                    loop += sprintf(loop, \"%%%02X\", c);\n                else\n                   loop += sprintf(loop, \"%c\", str[i]);\n        }\n    }\n    return newstring;\n}\n\n// Return current position in μs\nstatic inline int64_t ReturnPosMsec(UINT32 SamplePos, UINT32 SmplRate)\n{\n    return (int64_t)((SamplePos / (double)SmplRate)*1000000.0);\n}\n\n// Return current position in samples\nstatic inline INT32 ReturnSamplePos(int64_t UsecPos, UINT32 SmplRate)\n{\n    return (UsecPos / 1000000.0)*(double)SmplRate;\n}\n\nstatic inline int FileExists(char* file)\n{\n    return access(file, F_OK) + 1;\n}\n\n// DBus Helper Functions\nstatic void DBusEmptyMethodResponse(DBusConnection* connection, DBusMessage* request)\n{\n    DBusMessage* reply = dbus_message_new_method_return(request);\n    dbus_message_append_args(reply, DBUS_TYPE_INVALID);\n    dbus_connection_send(connection, reply, NULL);\n    dbus_message_unref(reply);\n}\n\nstatic void DBusReplyToIntrospect(DBusConnection* connection, DBusMessage* request)\n{\n    const char* introspection_data =\n\"<!DOCTYPE node PUBLIC \\\"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\\\"\\n\"\n\"\\\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\\\">\\n\"\n\"<node>\\n\"\n\"  <interface name=\\\"org.freedesktop.DBus.Introspectable\\\">\\n\"\n\"    <method name=\\\"Introspect\\\">\\n\"\n\"      <arg name=\\\"data\\\" direction=\\\"out\\\" type=\\\"s\\\"/>\\n\"\n\"    </method>\\n\"\n\"  </interface>\\n\"\n\"  <interface name=\\\"org.freedesktop.DBus.Peer\\\">\\n\"\n\"    <method name=\\\"Ping\\\"/>\\n\"\n\"    <method name=\\\"GetMachineId\\\">\\n\"\n\"      <arg type=\\\"s\\\" name=\\\"machine_uuid\\\" direction=\\\"out\\\"/>\\n\"\n\"    </method>\\n\"\n\"  </interface>\\n\"\n\"  <interface name=\\\"org.freedesktop.DBus.Properties\\\">\\n\"\n\"    <method name=\\\"Get\\\">\\n\"\n\"      <arg direction=\\\"in\\\" type=\\\"s\\\"/>\\n\"\n\"      <arg direction=\\\"in\\\" type=\\\"s\\\"/>\\n\"\n\"      <arg direction=\\\"out\\\" type=\\\"v\\\"/>\\n\"\n\"    </method>\\n\"\n\"    <method name=\\\"Set\\\">\\n\"\n\"      <arg direction=\\\"in\\\" type=\\\"s\\\"/>\\n\"\n\"      <arg direction=\\\"in\\\" type=\\\"s\\\"/>\\n\"\n\"      <arg direction=\\\"in\\\" type=\\\"v\\\"/>\\n\"\n\"    </method>\\n\"\n\"    <method name=\\\"GetAll\\\">\\n\"\n\"      <arg direction=\\\"in\\\" type=\\\"s\\\"/>\\n\"\n\"      <arg direction=\\\"out\\\" type=\\\"a{sv}\\\"/>\\n\"\n\"    </method>\\n\"\n\"    <signal name=\\\"PropertiesChanged\\\">\\n\"\n\"      <arg type=\\\"s\\\"/>\\n\"\n\"      <arg type=\\\"a{sv}\\\"/>\\n\"\n\"      <arg type=\\\"as\\\"/>\\n\"\n\"    </signal>\\n\"\n\"  </interface>\\n\"\n\"  <interface name=\\\"org.mpris.MediaPlayer2\\\">\\n\"\n\"    <property name=\\\"Identity\\\" type=\\\"s\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"DesktopEntry\\\" type=\\\"s\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"SupportedMimeTypes\\\" type=\\\"as\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"SupportedUriSchemes\\\" type=\\\"as\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"HasTrackList\\\" type=\\\"b\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"CanQuit\\\" type=\\\"b\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"CanRaise\\\" type=\\\"b\\\" access=\\\"read\\\" />\\n\"\n\"    <method name=\\\"Quit\\\" />\\n\"\n\"    <method name=\\\"Raise\\\" />\\n\"\n\"  </interface>\\n\"\n\"  <interface name=\\\"org.mpris.MediaPlayer2.Player\\\">\\n\"\n\"    <property name=\\\"Metadata\\\" type=\\\"a{sv}\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"PlaybackStatus\\\" type=\\\"s\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"Volume\\\" type=\\\"d\\\" access=\\\"readwrite\\\" />\\n\"\n\"    <property name=\\\"Position\\\" type=\\\"x\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"Rate\\\" type=\\\"d\\\" access=\\\"readwrite\\\" />\\n\"\n\"    <property name=\\\"MinimumRate\\\" type=\\\"d\\\" access=\\\"readwrite\\\" />\\n\"\n\"    <property name=\\\"MaximumRate\\\" type=\\\"d\\\" access=\\\"readwrite\\\" />\\n\"\n\"    <property name=\\\"CanControl\\\" type=\\\"b\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"CanGoNext\\\" type=\\\"b\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"CanGoPrevious\\\" type=\\\"b\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"CanPlay\\\" type=\\\"b\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"CanPause\\\" type=\\\"b\\\" access=\\\"read\\\" />\\n\"\n\"    <property name=\\\"CanSeek\\\" type=\\\"b\\\" access=\\\"read\\\" />\\n\"\n\"    <method name=\\\"Previous\\\" />\\n\"\n\"    <method name=\\\"Next\\\" />\\n\"\n\"    <method name=\\\"Stop\\\" />\\n\"\n\"    <method name=\\\"Play\\\" />\\n\"\n\"    <method name=\\\"Pause\\\" />\\n\"\n\"    <method name=\\\"PlayPause\\\" />\\n\"\n\"    <method name=\\\"Seek\\\">\\n\"\n\"      <arg type=\\\"x\\\" direction=\\\"in\\\" />\\n\"\n\"    </method>\"\n\"    <method name=\\\"OpenUri\\\">\\n\"\n\"      <arg type=\\\"s\\\" direction=\\\"in\\\" />\\n\"\n\"    </method>\\n\"\n\"    <method name=\\\"SetPosition\\\">\\n\"\n\"      <arg type=\\\"o\\\" direction=\\\"in\\\" />\\n\"\n\"      <arg type=\\\"x\\\" direction=\\\"in\\\" />\\n\"\n\"    </method>\\n\"\n\"    <signal name=\\\"Seeked\\\">\\n\"\n\"      <arg type=\\\"x\\\" name=\\\"Position\\\"/>\\n\"\n\"    </signal>\\n\"\n\"  </interface>\\n\"\n\"</node>\\n\"\n;\n\n    DBusMessage* reply = dbus_message_new_method_return(request);\n    dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_data, DBUS_TYPE_INVALID);\n    dbus_connection_send(connection, reply, NULL);\n    dbus_message_unref(reply);\n}\n\nstatic void DBusReplyWithVariant(DBusMessageIter* args, int type, char* type_as_string, const void* response)\n{\n    DBusMessageIter subargs;\n    dbus_message_iter_open_container(args, DBUS_TYPE_VARIANT, type_as_string, &subargs);\n        dbus_message_iter_append_basic(&subargs, type, response);\n    dbus_message_iter_close_container(args, &subargs);\n}\n\nvoid DBusAppendCanGoNext(DBusMessageIter* args)\n{\n    dbus_bool_t response = FALSE;\n    if(PLMode == 0x01)\n        if(CurPLFile < PLFileCount - 1)\n            response = TRUE;\n    DBusReplyWithVariant(args, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &response);\n}\n\nvoid DBusAppendCanGoPrevious(DBusMessageIter* args)\n{\n    dbus_bool_t response = FALSE;\n    if(PLMode == 0x01)\n        if(CurPLFile > 0x00)\n            response = TRUE;\n    DBusReplyWithVariant(args, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &response);\n}\n\nstatic void DBusSendMetadataArray(DBusMessageIter* dict_root, DBusMetadata meta[], size_t dbus_meta_array_len)\n{\n    DBusMessageIter root_variant, dict, dict_entry, variant;\n\n    dbus_message_iter_open_container(dict_root, DBUS_TYPE_VARIANT, \"a{sv}\", &root_variant);\n        // Open Root Container\n        dbus_message_iter_open_container(&root_variant, DBUS_TYPE_ARRAY, \"{sv}\", &dict);\n            for(size_t i = 0; i < dbus_meta_array_len; i++)\n            {\n                // Ignore empty strings\n                if(meta[i].contentType == DBUS_TYPE_STRING)\n                    if(!strlen(*(char**)meta[i].content))\n                        continue;\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &meta[i].title);\n                    // Field Value\n                    dbus_message_iter_open_container(&dict_entry, DBUS_TYPE_VARIANT, meta[i].dbusType, &variant);\n\n                        if(meta[i].contentType == DBUS_TYPE_ARRAY)\n                        {\n                            DBusMessageIter array_root;\n\n                            dbus_message_iter_open_container(&variant, meta[i].contentType, meta[i].dbusType, &array_root);\n\n                                for(size_t len = 0; len < meta[i].childLen; len++)\n                                {\n                                    const DBusMetadata* content = meta[i].content;\n                                    dbus_message_iter_append_basic(&array_root, content[len].contentType, content[len].content);\n                                }\n\n                            dbus_message_iter_close_container(&variant, &array_root);\n                        }\n                        else\n                            dbus_message_iter_append_basic(&variant, meta[i].contentType, meta[i].content);\n\n                    dbus_message_iter_close_container(&dict_entry, &variant);\n\n                dbus_message_iter_close_container(&dict, &dict_entry);\n            }\n        // Close Root Container\n        dbus_message_iter_close_container(&root_variant, &dict);\n    dbus_message_iter_close_container(dict_root, &root_variant);\n}\n\nstatic inline char* getAbsBasePath()\n{\n    // Pick the appropriate pointer\n    const char* fileptr = VgmFileName;\n    if(PLMode == 0x01)\n        fileptr = PLFileName;\n\n    char* basepath = realpath(fileptr, NULL);\n    if(basepath) {\n        char* sep = GetLastDirSeparator(basepath);\n        // It's okay to + 1 because sep points to a character before the terminator\n        if(sep)\n            sep[1] = '\\0';\n#ifdef DBUS_DEBUG\n        fprintf(stderr, \"\\nBase Path %s\\n\", basepath);\n#endif\n    }\n    return basepath;\n}\n\nstatic inline void getArtPath(const char* utf8album, char* artpath, const size_t artpath_size)\n{\n    char* basepath = getAbsBasePath();\n    if(basepath == NULL || basepath[0] == '\\0') {\n        free(basepath);\n        return;\n    }\n\n    // Now that we have the base path, we start looking for art\n    // If we are reading a playlist, append everything after the separator to the path and replace its m3u extension with png\n    if(PLMode == 0x01)\n    {\n        // Using the GNU version of basename which doesn't modify the argument\n        char* plname = basename(PLFileName);\n        char* plname_ext = strrchr(plname, '.');\n\n        // Find out how many characters we need to print until the file extension\n        // We use int because that's what the precision specifier accepts\n        // The filename is really not going to be more than INT_MAX characters\n        int plname_len = (plname_ext == NULL ? (int)strlen(plname) : (int)(plname_ext - plname));\n\n        snprintf(artpath, artpath_size, \"%s%.*s.png\", basepath, plname_len, plname);\n\n        ART_EXISTS(artpath);\n    }\n\n    // If we get here, we're probably in single track mode, or the playlist is named differently\n    // check base path + album + .png\n    snprintf(artpath, artpath_size, \"%s%s.png\", basepath, utf8album);\n    ART_EXISTS(artpath);\n\n    // As a last resort, pick the first image glob can find in the base path\n    // Append the case insensitive extension to the base path\n    snprintf(artpath, artpath_size, \"%s*.[pP][nN][gG]\", basepath);\n\n#ifdef DBUS_DEBUG\n    fprintf(stderr, \"Using glob %s\\n\", artpath);\n#endif\n    glob_t result;\n    if(glob(artpath, GLOB_NOSORT, NULL, &result) == 0)\n    {\n        if(result.gl_pathc > 0)\n        {\n            snprintf(artpath, artpath_size, \"%s\", result.gl_pathv[0]);\n            globfree(&result);\n            ART_EXISTS(artpath);\n        }\n    }\n    globfree(&result);\n\n    // There's nothing else we can do. Return an empty string\n    *artpath = '\\0';\n    free(basepath);\n}\n\nstatic void DBusSendMetadata(DBusMessageIter* dict_root)\n{\n    // Send an empty array in a variant if nothing is playing\n    if(PlayingMode == 0xFF)\n    {\n        DBusSendMetadataArray(dict_root, NULL, 0);\n        return;\n    }\n\n    // Prepare metadata\n\n    // Album\n    wchar_t* album = GetTagStrEJ(VGMTag.strGameNameE, VGMTag.strGameNameJ);\n    char* utf8album = wcharToUTF8(album);\n\n    // Title\n    wchar_t* title =  GetTagStrEJ(VGMTag.strTrackNameE, VGMTag.strTrackNameJ);\n    char* utf8title = wcharToUTF8(title);\n\n    // Length\n    int64_t len64 = 0;\n    INT32 VGMPbSmplCount = SampleVGM2Playback(VGMHead.lngTotalSamples);\n    len64 = ReturnPosMsec(VGMPbSmplCount, SampleRate);\n\n    // Artist\n    wchar_t* artist = GetTagStrEJ(VGMTag.strAuthorNameE, VGMTag.strAuthorNameJ);\n    char* utf8artist = wcharToUTF8(artist);\n\n    // Track Number in playlist\n    int32_t tracknum = 0;\n    if(PLMode == 0x01)\n        tracknum = (int32_t)(CurPLFile + 0x01);\n\n    // Try to get the cover art url\n    if(cached_artpath[0] == '\\0')\n        getArtPath(utf8album, cached_artpath, pathmax);\n\n#ifdef DBUS_DEBUG\n    fprintf(stderr, \"\\nFinal art path %s\\n\", artpath);\n#endif\n\n    // URL encode the path to the png\n    char* arturlescaped = urlencode(cached_artpath);\n\n    // Game release date\n    wchar_t* release = VGMTag.strReleaseDate;\n    char* utf8release = wcharToUTF8(release);\n\n    // VGM File Creator\n    wchar_t* creator = VGMTag.strCreator;\n    char* utf8creator = wcharToUTF8(creator);\n\n    // Notes\n    wchar_t* notes = VGMTag.strNotes;\n    char* utf8notes = wcharToUTF8(notes);\n\n    // System\n    wchar_t* system = GetTagStrEJ(VGMTag.strSystemNameE, VGMTag.strSystemNameJ);\n    char* utf8system = wcharToUTF8(system);\n\n    // VGM File version\n    uint32_t version = VGMHead.lngVersion;\n\n    // Loop point\n    int64_t loop = ReturnPosMsec(VGMHead.lngLoopSamples, SampleRate);\n\n    if(!strlen(utf8artist))\n    {\n        utf8artist = realloc(utf8artist, strlen(utf8album) + 1);\n        strcpy(utf8artist, utf8album);\n    }\n\n    // Encapsulate some data in DBusMetadata Arrays\n    // Artist Array\n    DBusMetadata dbusartist[] =\n    {\n        { \"\", DBUS_TYPE_STRING_AS_STRING, &utf8artist, DBUS_TYPE_STRING, 0 },\n    };\n\n    // Genre Array\n    const char* genre = \"Video Game Music\";\n    DBusMetadata dbusgenre[] =\n    {\n        { \"\", DBUS_TYPE_STRING_AS_STRING, &genre, DBUS_TYPE_STRING, 0 },\n    };\n\n    DBusMetadata chips[CHIP_COUNT] = { 0 };\n    size_t chipslen = 0;\n    // Generate chips array\n    for(UINT8 CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++)\n    {\n        UINT8 ChpType;\n        UINT32 ChpClk = GetChipClock(&VGMHead, CurChip, &ChpType);\n\n        if(ChpClk && GetChipClock(&VGMHead, 0x80 | CurChip, NULL))\n            ChpClk |= 0x40000000;\n\n        if(ChpClk)\n        {\n            if(CurChip == 0x00 && (ChpClk & 0x80000000))\n                ChpClk &= ~0x40000000;\n            if(ChpClk & 0x80000000)\n            {\n                ChpClk &= ~0x80000000;\n                CurChip |= 0x80;\n            }\n            const char* chip = GetAccurateChipName(CurChip, ChpType);\n            char** charptr = malloc(sizeof(char*));\n            chips[chipslen].content = charptr;\n            *charptr = strdup(chip);\n            // Set the type\n            chips[chipslen].dbusType = DBUS_TYPE_STRING_AS_STRING;\n            chips[chipslen].contentType = DBUS_TYPE_STRING;\n\n            // Duplicate the chip if necessasry\n            if(ChpClk & 0x40000000)\n            {\n                chipslen++;\n                chips[chipslen].content = chips[chipslen - 1].content;\n                chips[chipslen].dbusType = DBUS_TYPE_STRING_AS_STRING;\n                chips[chipslen].contentType = DBUS_TYPE_STRING;\n            }\n            chipslen++;\n        }\n    }\n\n    // URL encoded Filename\n    char* abspath = realpath(VgmFileName, NULL);\n    if(abspath == NULL)\n        abspath = calloc(1, sizeof(char));\n\n    char* url = urlencode(abspath);\n    free(abspath);\n\n    // Stubs\n    const char* trackid = \"/org/mpris/MediaPlayer2/CurrentTrack\";\n    const char* lastused = \"2018-01-04T12:21:32Z\";\n    int32_t discnum = 1;\n    int32_t usecnt = 0;\n    double userrating = 0;\n\n    DBusMetadata meta[] =\n    {\n        { \"mpris:trackid\", DBUS_TYPE_STRING_AS_STRING, &trackid, DBUS_TYPE_STRING, 0 },\n        { \"xesam:url\", DBUS_TYPE_STRING_AS_STRING, &url, DBUS_TYPE_STRING, 0 },\n        { \"mpris:artUrl\", DBUS_TYPE_STRING_AS_STRING, &arturlescaped, DBUS_TYPE_STRING, 0 },\n        { \"xesam:lastused\", DBUS_TYPE_STRING_AS_STRING, &lastused, DBUS_TYPE_STRING, 0 },\n        { \"xesam:genre\", \"as\", &dbusgenre, DBUS_TYPE_ARRAY, 1 },\n        { \"xesam:album\", DBUS_TYPE_STRING_AS_STRING, &utf8album, DBUS_TYPE_STRING, 0 },\n        { \"xesam:title\", DBUS_TYPE_STRING_AS_STRING, &utf8title, DBUS_TYPE_STRING, 0 },\n        { \"mpris:length\", DBUS_TYPE_INT64_AS_STRING, &len64, DBUS_TYPE_INT64, 0 },\n        { \"xesam:artist\", \"as\", &dbusartist, DBUS_TYPE_ARRAY, 1 },\n        { \"xesam:composer\", \"as\", &dbusartist, DBUS_TYPE_ARRAY, 1 },\n        { \"xesam:trackNumber\", DBUS_TYPE_INT32_AS_STRING, &tracknum, DBUS_TYPE_INT32, 1 },\n        { \"xesam:discNumber\", DBUS_TYPE_INT32_AS_STRING, &discnum, DBUS_TYPE_INT32, 1 },\n        { \"xesam:useCount\", DBUS_TYPE_INT32_AS_STRING, &usecnt, DBUS_TYPE_INT32, 1 },\n        { \"xesam:userRating\", DBUS_TYPE_DOUBLE_AS_STRING, &userrating, DBUS_TYPE_DOUBLE, 1 },\n        // Extra non-xesam/mpris entries\n        { \"vgm:release\", DBUS_TYPE_STRING_AS_STRING, &utf8release, DBUS_TYPE_STRING, 0 },\n        { \"vgm:creator\", DBUS_TYPE_STRING_AS_STRING, &utf8creator, DBUS_TYPE_STRING, 0 },\n        { \"vgm:notes\", DBUS_TYPE_STRING_AS_STRING, &utf8notes, DBUS_TYPE_STRING, 0 },\n        { \"vgm:system\", DBUS_TYPE_STRING_AS_STRING, &utf8system, DBUS_TYPE_STRING, 0 },\n        { \"vgm:version\", DBUS_TYPE_UINT32_AS_STRING, &version, DBUS_TYPE_UINT32, 0 },\n        { \"vgm:loop\", DBUS_TYPE_INT64_AS_STRING, &loop, DBUS_TYPE_INT64, 0 },\n        { \"vgm:chips\", \"as\", &chips, DBUS_TYPE_ARRAY, chipslen },\n    };\n    DBusSendMetadataArray(dict_root, meta, sizeof(meta)/sizeof(*meta));\n\n    // Free everything\n    free(arturlescaped);\n    free(url);\n    free(utf8title);\n    free(utf8album);\n    free(utf8artist);\n    free(utf8release);\n    free(utf8creator);\n    free(utf8notes);\n    free(utf8system);\n    for(size_t i = 0; i < chipslen; i++)\n    {\n        // If the next pointer is the same as the current one, don't free it.\n        // We also discard const here since we know we manually allocated these above.\n        char** ptr = (char**)chips[i].content;\n        if(chips[i].content == chips[i+1].content)\n            continue;\n        char* ch = *ptr;\n        free(ptr);\n        free(ch);\n    }\n}\n\nstatic void DBusSendPlaybackStatus(DBusMessageIter* args)\n{\n    const char* response;\n\n    if(PlayingMode == 0xFF)\n        response = \"Stopped\";\n    else if(PausePlay)\n        response = \"Paused\";\n    else\n        response = \"Playing\";\n\n    DBusReplyWithVariant(args, DBUS_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING, &response);\n}\n\nvoid DBus_EmitSignal_Internal(DBusConnection* connection, UINT8 type)\n{\n#ifdef DBUS_DEBUG\n    fprintf(stderr, \"Emitting signal type 0x%x\\n\", type);\n#endif\n    if(connection == NULL)\n        return;\n\n    // Make sure we're connected to DBus\n    // Otherwise discard the event\n    if(!dbus_connection_get_is_connected(connection))\n        return;\n\n    DBusMessage* msg;\n    DBusMessageIter args;\n\n    if(type & SIGNAL_SEEK)\n    {\n        msg = dbus_message_new_signal(DBUS_MPRIS_PATH, DBUS_MPRIS_PLAYER, \"Seeked\");\n\n        dbus_message_iter_init_append(msg, &args);\n        int64_t response = ReturnPosMsec(VGMSmplPlayed, SampleRate);\n        dbus_message_iter_append_basic(&args, DBUS_TYPE_INT64, &response);\n\n        dbus_connection_send(connection, msg, NULL);\n\n        dbus_message_unref(msg);\n\n        // Despite Seeked() being a different signal\n        // we need to send the changed position property too\n        // so we shouldn't return just yet.\n    }\n\n    msg = dbus_message_new_signal(DBUS_MPRIS_PATH, DBUS_PROPERTIES, \"PropertiesChanged\");\n\n    dbus_message_iter_init_append(msg, &args);\n    // The interface in which the properties were changed must be sent first\n    // Thankfully the only properties changing are in the same interface\n    const char* player = DBUS_MPRIS_PLAYER;\n    dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &player);\n    // Wrap everything inside an a{sv}\n    DBusMessageIter dict, dict_entry;\n\n    dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, \"{sv}\", &dict);\n        if(type & SIGNAL_METADATA)\n        {\n            // It is possible for the art to change if the playlist contains tracks from multiple games\n            // since art can be found by the \"Game Name\".png field\n            // Invalidate it on track change, as it will be populated later on demand\n            invalidateArtCache();\n            dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                const char* title = \"Metadata\";\n                dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusSendMetadata(&dict_entry);\n            dbus_message_iter_close_container(&dict, &dict_entry);\n        }\n        if(type & SIGNAL_CONTROLS)\n        {\n            dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                const char* title = \"CanGoPrevious\";\n                dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                DBusAppendCanGoPrevious(&dict_entry);\n            dbus_message_iter_close_container(&dict, &dict_entry);\n            dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                title = \"CanGoNext\";\n                dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                DBusAppendCanGoNext(&dict_entry);\n            dbus_message_iter_close_container(&dict, &dict_entry);\n        }\n        if(type & SIGNAL_PLAYSTATUS)\n        {\n            dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                const char* playing = \"PlaybackStatus\";\n                dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &playing);\n                DBusSendPlaybackStatus(&dict_entry);\n\n            dbus_message_iter_close_container(&dict, &dict_entry);\n        }\n        if((type & SIGNAL_SEEK) || (type & SIGNAL_PLAYSTATUS))\n        {\n            dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                const char* playing = \"Position\";\n                dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &playing);\n                int64_t response = ReturnPosMsec(VGMSmplPlayed, SampleRate);\n                DBusReplyWithVariant(&dict_entry, DBUS_TYPE_INT64, DBUS_TYPE_INT64_AS_STRING, &response);\n            dbus_message_iter_close_container(&dict, &dict_entry);\n        }\n        if((type & SIGNAL_VOLUME))\n        {\n            dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                const char* playing = \"Volume\";\n                dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &playing);\n                const double response = 1.0;\n                DBusReplyWithVariant(&dict_entry, DBUS_TYPE_DOUBLE, DBUS_TYPE_DOUBLE_AS_STRING, &response);\n            dbus_message_iter_close_container(&dict, &dict_entry);\n        }\n    dbus_message_iter_close_container(&args, &dict);\n\n    // Send a blank array _with signature \"s\"_.\n    dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, \"s\", &dict);\n    dbus_message_iter_close_container(&args, &dict);\n\n    dbus_connection_send(connection, msg, NULL);\n    dbus_message_unref(msg);\n}\n\n\nvoid DBus_EmitSignal(UINT8 type)\n{\n    DBus_EmitSignal_Internal(dbus_connection, type);\n}\n\nstatic void DBusSendMimeTypes(DBusMessageIter* args)\n{\n    DBusMessageIter variant, subargs;\n    dbus_message_iter_open_container(args, DBUS_TYPE_VARIANT, \"as\", &variant);\n        dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &subargs);\n            char* response[] = {\"audio/x-vgm\", \"audio/x-vgz\"};\n            size_t i_len = sizeof(response) / sizeof(*response);\n            for(size_t i = 0; i < i_len; ++i)\n            {\n                dbus_message_iter_append_basic(&subargs, DBUS_TYPE_STRING, &response[i]);\n            }\n        dbus_message_iter_close_container(&variant, &subargs);\n    dbus_message_iter_close_container(args, &variant);\n}\n\nstatic void DBusSendUriSchemes(DBusMessageIter* args)\n{\n    DBusMessageIter variant, subargs;\n    dbus_message_iter_open_container(args, DBUS_TYPE_VARIANT, \"as\", &variant);\n        dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &subargs);\n            char* response[] = {\"file\"};\n            size_t i_len = sizeof(response) / sizeof(*response);\n            for(size_t i = 0; i < i_len; ++i)\n            {\n                dbus_message_iter_append_basic(&subargs, DBUS_TYPE_STRING, &response[i]);\n            }\n        dbus_message_iter_close_container(&variant, &subargs);\n    dbus_message_iter_close_container(args, &variant);\n}\n\nstatic void DBusSendEmptyMethodResponse(DBusConnection* connection, DBusMessage* message)\n{\n    DBusMessage* reply;\n    DBusMessageIter args;\n    reply = dbus_message_new_method_return(message);\n    dbus_message_iter_init_append(reply, &args);\n    dbus_connection_send(connection, reply, NULL);\n}\n\nstatic DBusHandlerResult DBusHandler(DBusConnection* connection, DBusMessage* message, void* user_data)\n{\n#ifdef DBUS_DEBUG\n    const char* interface_name = dbus_message_get_interface(message);\n    const char* member_name = dbus_message_get_member(message);\n    const char* path_name = dbus_message_get_path(message);\n    const char* sender = dbus_message_get_sender(message);\n\n    fprintf(stderr, \"Interface: %s; Member: %s; Path: %s; Sender: %s;\\n\", interface_name, member_name, path_name, sender);\n#endif\n    if(!dbus_message_has_path(message, DBUS_MPRIS_PATH))\n        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;\n\n    // Respond to Introspect\n    if(dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, \"Introspect\"))\n    {\n        DBusReplyToIntrospect(connection, message);\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    else if(dbus_message_is_method_call(message, DBUS_MPRIS_MEDIAPLAYER2, \"Raise\"))\n    {\n        printf(\"\\a\");\n        fflush(stdout);\n        DBusSendEmptyMethodResponse(connection, message);\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    // Respond to Get\n    else if(dbus_message_is_method_call(message, DBUS_INTERFACE_PROPERTIES, \"Get\"))\n    {\n        char* method_interface_arg = NULL;\n        char* method_property_arg  = NULL;\n        DBusMessage* reply;\n\n        if(!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &method_interface_arg, DBUS_TYPE_STRING, &method_property_arg, DBUS_TYPE_INVALID))\n            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;\n\n        //printf(\"Interface name: %s\\n\", method_interface_arg);\n        //init reply\n        reply = dbus_message_new_method_return(message);\n\n        //printf(\"Property name: %s\\n\", method_property_arg);\n\n        // Global Iterator\n        DBusMessageIter args;\n        dbus_message_iter_init_append(reply, &args);\n\n        if(!strcmp(method_interface_arg, DBUS_MPRIS_MEDIAPLAYER2))\n        {\n            if(!strcmp(method_property_arg, \"SupportedMimeTypes\"))\n            {\n                DBusSendMimeTypes(&args);\n            }\n            else if(!strcmp(method_property_arg, \"SupportedUriSchemes\"))\n            {\n                DBusSendUriSchemes(&args);\n            }\n            else if(!strcmp(method_property_arg, \"CanQuit\"))\n            {\n                const dbus_bool_t response = TRUE;\n                DBusReplyWithVariant(&args, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &response);\n            }\n            else if(!strcmp(method_property_arg, \"CanRaise\"))\n            {\n                const dbus_bool_t response = TRUE;\n                DBusReplyWithVariant(&args, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &response);\n            }\n            else if(!strcmp(method_property_arg, \"HasTrackList\"))\n            {\n                const dbus_bool_t response = FALSE;\n                DBusReplyWithVariant(&args, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &response);\n            }\n            else if(!strcmp(method_property_arg, \"DesktopEntry\"))\n            {\n                const char* response = \"vgmplay\";\n                DBusReplyWithVariant(&args, DBUS_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING, &response);\n            }\n            else if(!strcmp(method_property_arg, \"Identity\"))\n            {\n                const char* response = \"VGMPlay\";\n                DBusReplyWithVariant(&args, DBUS_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING, &response);\n            }\n            else\n                dbus_message_append_args(reply, DBUS_TYPE_INVALID);\n        }\n        else if(!strcmp(method_interface_arg, DBUS_MPRIS_PLAYER))\n        {\n            if(!strcmp(method_property_arg, \"CanPlay\"))\n            {\n                const dbus_bool_t response = TRUE;\n                DBusReplyWithVariant(&args, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &response);\n            }\n            else if(!strcmp(method_property_arg, \"CanPause\"))\n            {\n                const dbus_bool_t response = TRUE;\n                DBusReplyWithVariant(&args, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &response);\n            }\n            else if(!strcmp(method_property_arg, \"CanGoNext\"))\n            {\n                DBusAppendCanGoNext(&args);\n            }\n            else if(!strcmp(method_property_arg, \"CanGoPrevious\"))\n            {\n                DBusAppendCanGoPrevious(&args);\n            }\n            else if(!strcmp(method_property_arg, \"CanSeek\"))\n            {\n                const dbus_bool_t response = TRUE;\n                DBusReplyWithVariant(&args, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &response);\n            }\n            else if(!strcmp(method_property_arg, \"PlaybackStatus\"))\n            {\n                DBusSendPlaybackStatus(&args);\n            }\n            else if(!strcmp(method_property_arg, \"Position\"))\n            {\n                int64_t response = ReturnPosMsec(VGMSmplPlayed, SampleRate);\n                DBusReplyWithVariant(&args, DBUS_TYPE_INT64, DBUS_TYPE_INT64_AS_STRING, &response);\n            }\n            //Dummy volume\n            else if(!strcmp(method_property_arg, \"Volume\") || !strcmp(method_property_arg, \"MaximumRate\") || !strcmp(method_property_arg, \"MinimumRate\") || !strcmp(method_property_arg, \"Rate\"))\n            {\n                const double response = 1.0;\n                DBusReplyWithVariant(&args, DBUS_TYPE_DOUBLE, DBUS_TYPE_DOUBLE_AS_STRING, &response);\n\n            }\n            else if(!strcmp(method_property_arg, \"CanControl\"))\n            {\n                const dbus_bool_t response = TRUE;\n                DBusReplyWithVariant(&args, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &response);\n            }\n            else if(!strcmp(method_property_arg, \"Metadata\"))\n            {\n                DBusSendMetadata(&args);\n            }\n            else\n                dbus_message_append_args(reply, DBUS_TYPE_INVALID);\n        }\n        else\n        {\n#ifdef DBUS_DEBUG\n            fprintf(stderr, \"Unimplemented interface %s passed to Get()\\n\", method_interface_arg);\n#endif\n            dbus_message_unref(reply);\n            reply = dbus_message_new_error(message, \"org.freedesktop.DBus.Error.InvalidArgs\", \"No such interface\");\n        }\n\n        dbus_connection_send(connection, reply, NULL);\n        dbus_message_unref(reply);\n\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    // Respond to GetAll\n    else if(dbus_message_is_method_call(message, DBUS_INTERFACE_PROPERTIES, \"GetAll\"))\n    {\n        char* method_interface_arg = NULL;\n        DBusMessage* reply;\n\n        if(!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &method_interface_arg, DBUS_TYPE_INVALID))\n            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;\n\n        //init reply\n        reply = dbus_message_new_method_return(message);\n\n        //printf(\"Property name: %s\\n\", property_name);\n\n        // Global Iterator\n        DBusMessageIter args;\n        dbus_message_iter_init_append(reply, &args);\n\n        const dbus_bool_t dbustrue = TRUE;\n        const dbus_bool_t dbusfalse = FALSE;\n        const char* title;\n        const char* strresponse;\n\n        if(!strcmp(method_interface_arg, \"org.mpris.MediaPlayer2\"))\n        {\n            // a{sv}\n            DBusMessageIter dict, dict_entry;\n            dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, \"{sv}\", &dict);\n\n                // Open Dict\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"SupportedMimeTypes\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusSendMimeTypes(&dict_entry);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"SupportedUriSchemes\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusSendUriSchemes(&dict_entry);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"CanQuit\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &dbustrue);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"CanRaise\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &dbustrue);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"HasTrackList\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &dbusfalse);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"DesktopEntry\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    strresponse = \"vgmplay\";\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING, &strresponse);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"Identity\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    strresponse = \"VGMPlay\";\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING, &strresponse);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n            dbus_message_iter_close_container(&args, &dict);\n        }\n        else if(!strcmp(method_interface_arg, DBUS_MPRIS_PLAYER))\n        {\n            const double doubleresponse = 1.0;\n            // a{sv}\n            DBusMessageIter dict, dict_entry;\n            dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, \"{sv}\", &dict);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"CanControl\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &dbustrue);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"CanGoNext\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusAppendCanGoNext(&dict_entry);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"CanGoPrevious\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusAppendCanGoPrevious(&dict_entry);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"CanPause\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &dbustrue);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"CanPlay\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &dbustrue);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"CanSeek\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &dbustrue);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"Metadata\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                        DBusSendMetadata(&dict_entry);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"MaximumRate\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_DOUBLE, DBUS_TYPE_DOUBLE_AS_STRING, &doubleresponse);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"MinimumRate\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_DOUBLE, DBUS_TYPE_DOUBLE_AS_STRING, &doubleresponse);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"Rate\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_DOUBLE, DBUS_TYPE_DOUBLE_AS_STRING, &doubleresponse);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"Volume\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_DOUBLE, DBUS_TYPE_DOUBLE_AS_STRING, &doubleresponse);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"Position\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    int64_t position = ReturnPosMsec(VGMSmplPlayed, SampleRate);\n                    DBusReplyWithVariant(&dict_entry, DBUS_TYPE_INT64, DBUS_TYPE_INT64_AS_STRING, &position);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n                dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);\n                    // Field Title\n                    title = \"PlaybackStatus\";\n                    dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &title);\n                    DBusSendPlaybackStatus(&dict_entry);\n                dbus_message_iter_close_container(&dict, &dict_entry);\n\n            dbus_message_iter_close_container(&args, &dict);\n        }\n        else\n        {\n#ifdef DBUS_DEBUG\n            fprintf(stderr, \"Unimplemented interface %s passed to GetAll\\n\", method_interface_arg);\n#endif\n            dbus_message_unref(reply);\n            reply = dbus_message_new_error(message, \"org.freedesktop.DBus.Error.InvalidArgs\", \"No such interface\");\n        }\n\n        dbus_connection_send(connection, reply, NULL);\n        dbus_message_unref(reply);\n\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    //Respond to Seek\n    else if(dbus_message_is_method_call(message, DBUS_MPRIS_PLAYER, \"Seek\"))\n    {\n        int64_t offset = 0;\n\n        if(!dbus_message_get_args(message, NULL, DBUS_TYPE_INT64, &offset, DBUS_TYPE_INVALID))\n            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;\n\n#ifdef DBUS_DEBUG\n        fprintf(stderr, \"Seek called with %\"PRId64\"\\n\", offset);\n#endif\n        INT32 TargetSeekPos = ReturnSamplePos(offset, SampleRate);\n        SeekVGM(true, TargetSeekPos);\n\n        DBusEmptyMethodResponse(connection, message);\n\n        // Emit seeked signal\n        DBus_EmitSignal_Internal(connection, SIGNAL_SEEK);\n\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    //Respond to PlayPause\n    else if(dbus_message_is_method_call(message, DBUS_MPRIS_PLAYER, \"PlayPause\"))\n    {\n        DBusEmptyMethodResponse(connection, message);\n        evtCallback(MMKEY_PLAY);\n\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    //Respond to Play\n    else if(dbus_message_is_method_call(message, DBUS_MPRIS_PLAYER, \"Play\"))\n    {\n        DBusEmptyMethodResponse(connection, message);\n        if(PausePlay)\n            evtCallback(MMKEY_PLAY);\n\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    //Respond to Pause\n    else if(dbus_message_is_method_call(message, DBUS_MPRIS_PLAYER, \"Pause\"))\n    {\n        DBusEmptyMethodResponse(connection, message);\n        if(!PausePlay)\n            evtCallback(MMKEY_PLAY);\n\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    // Stop is currently a stub\n    else if(dbus_message_is_method_call(message, DBUS_MPRIS_PLAYER, \"Stop\"))\n    {\n        DBusEmptyMethodResponse(connection, message);\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    //Respond to Previous\n    else if(dbus_message_is_method_call(message, DBUS_MPRIS_PLAYER, \"Previous\"))\n    {\n        DBusEmptyMethodResponse(connection, message);\n        evtCallback(MMKEY_PREV);\n\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    //Respond to Next\n    else if(dbus_message_is_method_call(message, DBUS_MPRIS_PLAYER, \"Next\"))\n    {\n        DBusEmptyMethodResponse(connection, message);\n        evtCallback(MMKEY_NEXT);\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    else if(dbus_message_is_method_call(message, DBUS_MPRIS_PLAYER, \"SetPosition\"))\n    {\n        int64_t pos;\n        const char* path;\n        if(!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INT64, &pos, DBUS_TYPE_INVALID))\n            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;\n\n        INT32 seek_pos = ReturnSamplePos(pos, SampleRate);\n        SeekVGM(false, seek_pos);\n\n        DBusEmptyMethodResponse(connection, message);\n        DBus_EmitSignal_Internal(connection, SIGNAL_SEEK);\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    else if(dbus_message_is_method_call(message, DBUS_INTERFACE_PROPERTIES, \"Set\"))\n    {\n        // Dummy Set to send a signal to revert Volume change attempts\n        DBus_EmitSignal_Internal(connection, SIGNAL_VOLUME);\n        return DBUS_HANDLER_RESULT_HANDLED;\n    }\n    else\n    {\n#ifdef DBUS_DEBUG\n        fprintf(stderr, \"Method %s for interface %s not implemented\", member_name, interface_name);\n#endif\n        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;\n    }\n}\n\nUINT8 MultimediaKeyHook_Init(void)\n{\n    // Allocate memory for the art path cache\n    long pathmax_s = pathconf(\"/\", _PC_PATH_MAX);\n    if (pathmax_s <= 0)\n        pathmax = 4096;\n    else\n        pathmax = pathmax_s + 1;\n\n    cached_artpath = malloc(pathmax);\n    *cached_artpath = '\\0';\n\n    dbus_connection = dbus_bus_get(DBUS_BUS_SESSION, NULL);\n    if(!dbus_connection)\n        return 0x00;\n\n    // If we're not the owners, don't bother with anything else\n    if(dbus_bus_request_name(dbus_connection, DBUS_MPRIS_VGMPLAY, DBUS_NAME_FLAG_DO_NOT_QUEUE, NULL) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)\n    {\n        dbus_connection_unref(dbus_connection);\n        dbus_connection = NULL;\n        return 0x00;\n    }\n\n    DBusObjectPathVTable vtable =\n    {\n        .message_function = DBusHandler,\n        .unregister_function = NULL,\n    };\n\n    dbus_connection_try_register_object_path(dbus_connection, DBUS_MPRIS_PATH, &vtable, NULL, NULL);\n\n    return 0x00;\n}\n\nvoid MultimediaKeyHook_Deinit(void)\n{\n    if(dbus_connection != NULL)\n        dbus_connection_unref(dbus_connection);\n    free(cached_artpath);\n    cached_artpath = NULL;\n}\n\nvoid MultimediaKeyHook_SetCallback(mmkey_cbfunc callbackFunc)\n{\n    evtCallback = callbackFunc;\n}\n\nvoid DBus_ReadWriteDispatch(void)\n{\n    if(dbus_connection == NULL)\n        return;\n\n    // Detect loops and send the seeked signal when appropriate\n    if(OldLoopCount != VGMCurLoop)\n    {\n        OldLoopCount = VGMCurLoop;\n        DBus_EmitSignal_Internal(dbus_connection, SIGNAL_SEEK);\n    }\n\n    // Wait at most for 1ms\n    dbus_connection_read_write_dispatch(dbus_connection, 1);\n}\n"
  },
  {
    "path": "VGMPlay/dbus.h",
    "content": "#ifndef __DBUS_H__\n#define __DBUS_H__\n\n// Defines for the DBUS Signal handler\n#define SIGNAL_METADATA    0x01 // Metadata changed\n#define SIGNAL_PLAYSTATUS  0x02 // Playback Status Changed\n#define SIGNAL_SEEKSTATUS  0x04 // Seek Status Changed\n#define SIGNAL_SEEK        0x08 // Seeked\n#define SIGNAL_CONTROLS    0x10 // Playback controls need to be updated (CanGoNext/Previous)\n#define SIGNAL_VOLUME      0x20 // Volume needs to be updated\n#define SIGNAL_ALL         0xFF // All Signals\n\n#include \"chips/mamedef.h\"\n\nvoid DBus_ReadWriteDispatch(void);\nvoid DBus_EmitSignal(UINT8 type);\n\n#endif\t// __DBUS_H__\n"
  },
  {
    "path": "VGMPlay/dbus_stub.c",
    "content": "#include \"chips/mamedef.h\"\n\nvoid DBus_ReadWriteDispatch(void)\n{\n\n}\n\nvoid DBus_EmitSignal(UINT8 type)\n{\n\n}\n"
  },
  {
    "path": "VGMPlay/licenses/GPL.txt",
    "content": "\t\t    GNU GENERAL PUBLIC LICENSE\n\t\t       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\t\t\t    Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Library General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\f\n\t\t    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\f\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\f\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\f\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n\t\t\t    NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n\t\t     END OF TERMS AND CONDITIONS\n\f\n\t    How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year  name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Library General\nPublic License instead of this License.\n"
  },
  {
    "path": "VGMPlay/licenses/List.txt",
    "content": "MAME - mame_license.txt\nDosBox - GPL.txt\nopenMSX - GPL.txt\nGens/GS - GPL.txt\nNSFPlay - [Google Code lists Apache License 2.0]\nOotake - ?\nGens - Cardware\nMEKA - ?\nzlib - see zlib.h\nin_wsr - ?\nvbjin/mednafen - GNU GPLv2\nEMU2149/EMU2413 - MIT License\n"
  },
  {
    "path": "VGMPlay/licenses/mame_license.txt",
    "content": "Unless otherwise explicitly stated, all code in MAME is released under the\nfollowing license:\n\nCopyright Nicola Salmoria and the MAME team\nAll rights reserved.\n\nRedistribution and use of this code or any derivative works are permitted\nprovided that the following conditions are met:\n\n* Redistributions may not be sold, nor may they be used in a commercial\nproduct or activity.\n\n* Redistributions that are modified from the original source must include the\ncomplete source code, including the source code for all components used by a\nbinary built from the modified sources. However, as a special exception, the\nsource code distributed need not include anything that is normally distributed\n(in either source or binary form) with the major components (compiler, kernel,\nand so on) of the operating system on which the executable runs, unless that\ncomponent itself accompanies the executable.\n\n* Redistributions must reproduce the above copyright notice, this list of\nconditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\nINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "VGMPlay/mmkeys.h",
    "content": "#ifndef __MMKEYS_H__\n#define __MMKEYS_H__\n\ntypedef void (*mmkey_cbfunc)(UINT8 event);\n\n#define MMKEY_PLAY\t0x01\n#define MMKEY_PREV\t0x10\n#define MMKEY_NEXT\t0x11\n\nUINT8 MultimediaKeyHook_Init(void);\nvoid MultimediaKeyHook_Deinit(void);\nvoid MultimediaKeyHook_SetCallback(mmkey_cbfunc callbackFunc);\n\n#endif\t// __MMKEYS_H__\n"
  },
  {
    "path": "VGMPlay/mmkeys_Win.c",
    "content": "#include <Windows.h>\n#include <stdio.h>\n\n#include \"chips/mamedef.h\"\n#include \"mmkeys.h\"\n\n#ifndef VK_MEDIA_NEXT_TRACK\n// from WinUser.h\n#define VK_MEDIA_NEXT_TRACK    0xB0\n#define VK_MEDIA_PREV_TRACK    0xB1\n#define VK_MEDIA_STOP          0xB2\n#define VK_MEDIA_PLAY_PAUSE    0xB3\n#endif\n\nstatic DWORD idThread = 0;\nstatic HANDLE hThread = NULL;\nstatic HANDLE hEvent = NULL;\nstatic mmkey_cbfunc evtCallback = NULL;\n\nstatic DWORD WINAPI KeyMessageThread(void* args)\n{\n\tMSG msg;\n\tBOOL retValB;\n\t\n\t// enforce creation of message queue\n\tPeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);\n\t\n\tretValB = RegisterHotKey(NULL, MMKEY_PLAY, 0, VK_MEDIA_PLAY_PAUSE);\n\tretValB = RegisterHotKey(NULL, MMKEY_PREV, 0, VK_MEDIA_PREV_TRACK);\n\tretValB = RegisterHotKey(NULL, MMKEY_NEXT, 0, VK_MEDIA_NEXT_TRACK);\n\t\n\tSetEvent(hEvent);\n\t\n\twhile(retValB = GetMessage(&msg, NULL, 0, 0))\n\t{\n\t\tif (msg.message == WM_HOTKEY)\n\t\t{\n\t\t\tif (evtCallback != NULL)\n\t\t\t\tevtCallback((UINT8)msg.wParam);\n\t\t}\n\t}\n\t\n\tUnregisterHotKey(NULL, MMKEY_PLAY);\n\tUnregisterHotKey(NULL, MMKEY_PREV);\n\tUnregisterHotKey(NULL, MMKEY_NEXT);\n\t\n\treturn 0;\n}\n\nUINT8 MultimediaKeyHook_Init(void)\n{\n\tif (hThread != NULL)\n\t\treturn 0x01;\n\t\n\thEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\n\thThread = CreateThread(NULL, 0x00, &KeyMessageThread, NULL, 0x00, &idThread);\n\tif (hThread == NULL)\n\t\treturn 0xFF;\t\t// CreateThread failed\n\t\n\tWaitForSingleObject(hEvent, INFINITE);\n\t\n\treturn 0x00;\n}\n\nvoid MultimediaKeyHook_Deinit(void)\n{\n\tif (hThread == NULL)\n\t\treturn;\n\t\n\tPostThreadMessage(idThread, WM_QUIT, 0, 0);\n\tWaitForSingleObject(hThread, INFINITE);\n\t\n\tCloseHandle(hThread);\n\thThread = NULL;\n\t\n\treturn;\n}\n\nvoid MultimediaKeyHook_SetCallback(mmkey_cbfunc callbackFunc)\n{\n\tevtCallback = callbackFunc;\n\t\n\treturn;\n}\n"
  },
  {
    "path": "VGMPlay/mmkeys_stub.c",
    "content": "#include \"chips/mamedef.h\"\n#include \"mmkeys.h\"\n\nUINT8 MultimediaKeyHook_Init(void)\n{\n    return 0;\n}\n\nvoid MultimediaKeyHook_Deinit(void)\n{\n    \n}\n\nvoid MultimediaKeyHook_SetCallback(mmkey_cbfunc callbackFunc)\n{\n    \n}\n"
  },
  {
    "path": "VGMPlay/pt_ioctl.c",
    "content": "/******************************************************************************/\n/*                                                                            */\n/*                          IoExample for PortTalk V2.1                       */\n/*                        Version 2.1, 12th January 2002                      */\n/*                          http://www.beyondlogic.org                        */\n/*                                                                            */\n/* Copyright  2002 Craig Peacock. Craig.Peacock@beyondlogic.org              */\n/* Any publication or distribution of this code in source form is prohibited  */\n/* without prior written permission of the copyright holder. This source code */\n/* is provided \"as is\", without any guarantee made as to its suitability or   */\n/* fitness for any particular use. Permission is herby granted to modify or   */\n/* enhance this sample code to produce a derivative program which may only be */\n/* distributed in compiled object form only.                                  */\n/******************************************************************************/\n\n#include <stdio.h>\n#include <windows.h>\n#include <winioctl.h>\n#include \"PortTalk_IOCTL.h\"\n\nunsigned char OpenPortTalk(void);\nvoid ClosePortTalk(void);\n\nvoid outportb(unsigned short PortAddress, unsigned char byte);\nunsigned char inportb(unsigned short PortAddress);\n\nvoid InstallPortTalkDriver(void);\nunsigned char StartPortTalkDriver(void);\n\n#define    inp(PortAddress)         inportb(PortAddress)\n#define    outp(PortAddress, Value) outportb(PortAddress, Value)\n\nHANDLE PortTalk_Handle;        /* Handle for PortTalk Driver */\n\nvoid outportb(unsigned short PortAddress, unsigned char byte)\n{\n    unsigned int error;\n    DWORD BytesReturned;        \n    unsigned char Buffer[3];\n    unsigned short * pBuffer;\n    pBuffer = (unsigned short *)&Buffer[0];\n    *pBuffer = PortAddress;\n    Buffer[2] = byte;\n\n    error = DeviceIoControl(PortTalk_Handle,\n                            IOCTL_WRITE_PORT_UCHAR,\n                            &Buffer,\n                            3,\n                            NULL,\n                            0,\n                            &BytesReturned,\n                            NULL);\n\n    if (!error) printf(\"Error occured during outportb while talking to PortTalk driver %d\\n\",GetLastError());\n}\n\nunsigned char inportb(unsigned short PortAddress)\n{\n    unsigned int error;\n    DWORD BytesReturned;\n    unsigned char Buffer[3];\n    unsigned short * pBuffer;\n    pBuffer = (unsigned short *)&Buffer;\n    *pBuffer = PortAddress;\n\n    error = DeviceIoControl(PortTalk_Handle,\n                            IOCTL_READ_PORT_UCHAR,\n                            &Buffer,\n                            2,\n                            &Buffer,\n                            1,\n                            &BytesReturned,\n                            NULL);\n\n    if (!error) printf(\"Error occured during inportb while talking to PortTalk driver %d\\n\",GetLastError());\n    return(Buffer[0]);\n}\n\nunsigned char OpenPortTalk(void)\n{\n    /* Open PortTalk Driver. If we cannot open it, try installing and starting it */\n    PortTalk_Handle = CreateFile(\"\\\\\\\\.\\\\PortTalk\", \n                                 GENERIC_READ, \n                                 0, \n                                 NULL,\n                                 OPEN_EXISTING, \n                                 FILE_ATTRIBUTE_NORMAL, \n                                 NULL);\n\n    if(PortTalk_Handle == INVALID_HANDLE_VALUE) {\n            /* Start or Install PortTalk Driver */\n            StartPortTalkDriver();\n            /* Then try to open once more, before failing */\n            PortTalk_Handle = CreateFile(\"\\\\\\\\.\\\\PortTalk\", \n                                         GENERIC_READ, \n                                         0, \n                                         NULL,\n                                         OPEN_EXISTING, \n                                         FILE_ATTRIBUTE_NORMAL, \n                                         NULL);\n               \n            if(PortTalk_Handle == INVALID_HANDLE_VALUE) {\n                    printf(\"PortTalk: Couldn't access PortTalk Driver, Please ensure driver is loaded.\\n\\n\");\n                    return -1;\n            }\n    }\n\treturn 0;\n}\n\nvoid ClosePortTalk(void)\n{\n    CloseHandle(PortTalk_Handle);\n}\n\nunsigned char StartPortTalkDriver(void)\n{\n    SC_HANDLE  SchSCManager;\n    SC_HANDLE  schService;\n    BOOL       ret;\n    DWORD      err;\n\n    /* Open Handle to Service Control Manager */\n    SchSCManager = OpenSCManager (NULL,                        /* machine (NULL == local) */\n                                  NULL,                        /* database (NULL == default) */\n                                  SC_MANAGER_ALL_ACCESS);      /* access required */\n                         \n    if (SchSCManager == NULL)\n      if (GetLastError() == ERROR_ACCESS_DENIED) {\n         /* We do not have enough rights to open the SCM, therefore we must */\n         /* be a poor user with only user rights. */\n         printf(\"PortTalk: You do not have rights to access the Service Control Manager and\\n\");\n         printf(\"PortTalk: the PortTalk driver is not installed or started. Please ask \\n\");\n         printf(\"PortTalk: your administrator to install the driver on your behalf.\\n\");\n         return(0);\n         }\n\n    do {\n         /* Open a Handle to the PortTalk Service Database */\n         schService = OpenService(SchSCManager,         /* handle to service control manager database */\n                                  \"PortTalk\",           /* pointer to name of service to start */\n                                  SERVICE_ALL_ACCESS);  /* type of access to service */\n\n         if (schService == NULL)\n            switch (GetLastError()){\n                case ERROR_ACCESS_DENIED:\n                        printf(\"PortTalk: You do not have rights to the PortTalk service database\\n\");\n                        return(0);\n                case ERROR_INVALID_NAME:\n                        printf(\"PortTalk: The specified service name is invalid.\\n\");\n                        return(0);\n                case ERROR_SERVICE_DOES_NOT_EXIST:\n                        printf(\"PortTalk: The PortTalk driver does not exist. Installing driver.\\n\");\n                        printf(\"PortTalk: This can take up to 30 seconds on some machines . .\\n\");\n                        InstallPortTalkDriver();\n                        break;\n            }\n         } while (schService == NULL);\n\n    /* Start the PortTalk Driver. Errors will occur here if PortTalk.SYS file doesn't exist */\n    \n    ret = StartService (schService,    /* service identifier */\n                        0,             /* number of arguments */\n                        NULL);         /* pointer to arguments */\n                    \n    if (ret) printf(\"PortTalk: The PortTalk driver has been successfully started.\\n\");\n    else {\n        err = GetLastError();\n        if (err == ERROR_SERVICE_ALREADY_RUNNING)\n          printf(\"PortTalk: The PortTalk driver is already running.\\n\");\n        else {\n          printf(\"PortTalk: Unknown error while starting PortTalk driver service.\\n\");\n          printf(\"PortTalk: Does PortTalk.SYS exist in your \\\\System32\\\\Drivers Directory?\\n\");\n          return(0);\n        }\n    }\n\n    /* Close handle to Service Control Manager */\n    CloseServiceHandle (schService);\n    return(TRUE);\n}\n\nvoid InstallPortTalkDriver(void)\n{\n    SC_HANDLE  SchSCManager;\n    SC_HANDLE  schService;\n    DWORD      err;\n    CHAR         DriverFileName[80];\n\n    /* Get Current Directory. Assumes PortTalk.SYS driver is in this directory.    */\n    /* Doesn't detect if file exists, nor if file is on removable media - if this  */\n    /* is the case then when windows next boots, the driver will fail to load and  */\n    /* a error entry is made in the event viewer to reflect this */\n\n    /* Get System Directory. This should be something like c:\\windows\\system32 or  */\n    /* c:\\winnt\\system32 with a Maximum Character lenght of 20. As we have a       */\n    /* buffer of 80 bytes and a string of 24 bytes to append, we can go for a max  */\n    /* of 55 bytes */\n\n    if (!GetSystemDirectory(DriverFileName, 55))\n        {\n         printf(\"PortTalk: Failed to get System Directory. Is System Directory Path > 55 Characters?\\n\");\n         printf(\"PortTalk: Please manually copy driver to your system32/driver directory.\\n\");\n        }\n\n    /* Append our Driver Name */\n    lstrcat(DriverFileName,\"\\\\Drivers\\\\PortTalk.sys\");\n    printf(\"PortTalk: Copying driver to %s\\n\",DriverFileName);\n\n    /* Copy Driver to System32/drivers directory. This fails if the file doesn't exist. */\n\n    if (!CopyFile(\"PortTalk.sys\", DriverFileName, FALSE))\n        {\n         printf(\"PortTalk: Failed to copy driver to %s\\n\",DriverFileName);\n         printf(\"PortTalk: Please manually copy driver to your system32/driver directory.\\n\");\n        }\n\n    /* Open Handle to Service Control Manager */\n    SchSCManager = OpenSCManager (NULL,                   /* machine (NULL == local) */\n                                  NULL,                   /* database (NULL == default) */\n                                  SC_MANAGER_ALL_ACCESS); /* access required */\n\n    /* Create Service/Driver - This adds the appropriate registry keys in */\n    /* HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services - It doesn't  */\n    /* care if the driver exists, or if the path is correct.              */\n\n    schService = CreateService (SchSCManager,                      /* SCManager database */\n                                \"PortTalk\",                        /* name of service */\n                                \"PortTalk\",                        /* name to display */\n                                SERVICE_ALL_ACCESS,                /* desired access */\n                                SERVICE_KERNEL_DRIVER,             /* service type */\n                                SERVICE_DEMAND_START,              /* start type */\n                                SERVICE_ERROR_NORMAL,              /* error control type */\n                                \"System32\\\\Drivers\\\\PortTalk.sys\", /* service's binary */\n                                NULL,                              /* no load ordering group */\n                                NULL,                              /* no tag identifier */\n                                NULL,                              /* no dependencies */\n                                NULL,                              /* LocalSystem account */\n                                NULL                               /* no password */\n                                );\n\n    if (schService == NULL) {\n         err = GetLastError();\n         if (err == ERROR_SERVICE_EXISTS)\n               printf(\"PortTalk: Driver already exists. No action taken.\\n\");\n         else  printf(\"PortTalk: Unknown error while creating Service.\\n\");    \n    }\n    else printf(\"PortTalk: Driver successfully installed.\\n\");\n\n    /* Close Handle to Service Control Manager */\n    CloseServiceHandle (schService);\n}\n"
  },
  {
    "path": "VGMPlay/stdbool.h",
    "content": "// custom stdbool.h to for 1-byte bool types\n\n#ifndef _CSTM_STDBOOL_H_\n#define\t_CSTM_STDBOOL_H_\t\n\n#ifndef __cplusplus\t// C++ already has the bool-type\n\n#define\tfalse\t0x00\n#define\ttrue\t0x01\n\n// the MS VC++ 6 compiler uses a one-byte-type (unsigned char, to be exact), so I'll reproduce this here\ntypedef\tunsigned char\tbool;\n\n#endif // !__cplusplus\n\n#endif // !_CSTM_STDBOOL_H_\n"
  },
  {
    "path": "VGMPlay/vgm-player",
    "content": "#!/bin/sh\n\n# Launcher script to work around limitations in vgmplay:\n#   OSS only - detects oss wrapper and allows explicit selection\n#   Config must be in working dir - automatically cd/mktemps as needed\n#   Can't open release packs - plays from temporary directories\n#\n# Original script by ZekeSulastin\n# 7z support by Valley Bell\n\ntrap '[ -n \"$_tmpdir\" ] && rm -rf \"$_tmpdir\"; [ -w \"$_log_path/vgmplay.ini\" ] && rm \"$_log_path/vgmplay.ini\"' EXIT\ntrap '[ -n \"$_tmpdir\" ] && rm -rf \"$_tmpdir\"; [ -w \"$_log_path/vgmplay.ini\" ] && rm \"$_log_path/vgmplay.ini\"' HUP INT QUIT TERM SEGV\n\n_set_output=\n_output=\n_pulse_server=\n_log_path=\n_binary=\n_config=\n_pwd=\"$(pwd)\"\n_host=\"$(hostname)\"\n_ext=\n_unpack=false\n_tmpdir=\n_music_file=\n_m3u_stub=\nXDG_CONFIG_HOME=\"${XDG_CONFIG_HOME:-$HOME/.config}\"\nXDG_CONFIG_DIRS=\"${XDG_CONFIG_DIRS:-/etc/xdg}\"\n_padsp=\"$(command -v padsp 2>/dev/null)\"\n_aoss=\"$(command -v aoss 2>/dev/null)\"\n\n_help () {\ncat <<EOF\nUsage: vgm-player [options] filename\nUses vgmplay to play vgm, vgz, cmf, dro, m3u, and zip'd vgm packs.\n\nOptions:\n        --help              display this help and exit\n        --version           display vgmplay and vgm format versions and exit\n\n -a,    --alsa              force use of aoss (ALSA's OSS wrapper)\n -o,    --oss               force use of OSS (native OSS, OSSProxy)\n -p,    --pulse             force use of padsp (PulseAudio's OSS wrapper)\n -s <server>,\n        --pulse-server=<server>\n                            set alternate PulseAudio server (implies --padsp)\n -l,    --log               outputs to wav files in current directory\n        --log-path=<path>   outputs to wav files in <path> (implies --log)\n\n WARNING: If you plan to log using this script, use --log or --log-path!\n  Do NOT set logging on in a custom config, else the script logic will\n  remove your logs!\n\n        --binary=<binary>   use alternate vgmplay binary\n        --config=<config>   use alternate configuration file\n\nKeys (In-Player):\n Left/Right                 seek 5 seconds backward/forward\n Ctrl + Left/Right          seek 60 seconds backward/forward\n Space                      pause\n Escape (twice) or Q        quit program\n F                          fade out current track\n R                          restart current track\n PageUp or B                previous track in playlist\n PageDown or N              next track in playlist\nEOF\nexit 0\n}\n\n_to_stderr () {\n    echo -e \"$0: $2\" 1>&2\n    exit $1\n}\n\n_die () {\n    case $1 in\n        too_many_outputs )\n            _to_stderr 64 \"can only force one output type\" ;;\n        no_pulse_server )\n            _to_stderr 64 \"--pulse-server requires server parameter\" ;;\n        no_log_path )\n            _to_stderr 64 \"--log-to requires path parameter\" ;;\n        unknown_option )\n            _to_stderr 64 \"unrecognized option '$2'\\nTry 'vgm-player --help' for more information.\" ;;\n        no_aoss )\n            _to_stderr 69 \"alsa output forced but aoss not found\" ;;\n        no_oss )\n            _to_stderr 74 \"oss output forced but /dev/dsp unwritable or not present\" ;;\n        no_pulse )\n            _to_stderr 69 \"pulse output forced but padsp not found\" ;;\n        too_many_files )\n            _to_stderr 64 \"only one music file should be specified\" ;;\n        file_unreadable )\n            _to_stderr 66 \"unable to read specified input - does it exist?\" ;;\n        invalid_format )\n            _to_stderr 66 \"format unsupported\" ;;\n        invalid_binary )\n            _to_stderr 69 \"invalid binary specified\" ;;\n        no_binary )\n            _to_stderr 64 \"--binary requires binary parameter\" ;;\n        no_config )\n            _to_stderr 64 \"--config requires config parameter\" ;;\n        noread_config )\n            _to_stderr 69 \"specified config unreadable - does it exist?\" ;;\n        invalid_config )\n            _to_stderr 64 \"invalid config specified\" ;;\n        vgmplay_not_found )\n            _to_stderr 69 \"vgmplay binary not found\" ;;\n        no_unpacker )\n            _to_stderr 69 \"no suitable unpacker found\" ;;\n        tmpdir_fail )\n            _to_stderr 70 \"unable to create/use temporary working directory\" ;;\n        no_output )\n            _to_stderr 69 \"no usable otuput detected\" ;;\n        log_path_nowrite )\n            _to_stderr 73 \"log path unwriteable\" ;;\n        no_music_file )\n            _to_stderr 64 \"No music file specified.\" ;;\n        * )\n            _to_stderr 64 \"Unhandled script error: $1\" ;;\n    esac\n}\n\n_set_output () {\n    if [ -n \"$_set_output\" ] && [ \"$1\" != \"$_set_output\" ]; then\n        _die too_many_outputs\n    fi\n    _set_output=$1\n\n    case \"$_set_output\" in\n        alsa )\n            [ -x \"$_aoss\" ] || _die no_aoss ;;\n        oss )\n            [ -w /dev/dsp ] || _die no_oss ;;\n        pulse )\n            [ -n \"$_padsp\" ] || _die no_pulse ;;\n        * )\n            ;;\n    esac\n}\n\n# Set terminal title for xterm/rxvt\ncase $TERM in\n    xterm* | rxvt* )\n        printf '%b' '\\033]2;VGM Player\\007' ;;\n    * )\n        ;;\nesac\n\n# Parse command line options\n#   All single-letter options are exclusive\nwhile :; do\n    case $1 in\n        --help )\n            _help ;;\n        -v | --version )\n            echo \"VGMPlay 0.40.9 player script\"\n            exit 0 ;;\n        -a | --alsa )\n            _set_output alsa\n            shift ;;\n        -o | --oss )\n            _set_output oss\n            shift ;;\n        -p | --pulse )\n            _set_output pulse\n            shift ;;\n        --pulse-server=* )\n            _set_output pulse\n            _pulse_server=\"${1#*=}\"\n            [ -n \"$_pulse_server\" ] || _die no_pulse_server\n            shift ;;\n        -s* )\n            _set_output pulse\n            _pulse_server=\"${1#-s}\"\n            if [ -z \"$_pulse_server\" ]; then\n                _pulse_server=\"$2\"\n                shift\n            fi\n            [ -n \"$_pulse_server\" ] || _die no_pulse_server\n            shift ;;\n        -l | --log )\n            _set_output log\n            _log_path=\"$_pwd\"\n            shift ;;\n        --log-path=* )\n            _set_output log\n            _log_path=\"${1#*=}\"\n            [ -d \"$_log_path\" ] || _die no_log_path\n            shift ;;\n        --config=* )\n            _config=\"${1#*=}\"\n            [ -n \"$_config\" ] || _die no_binary\n            [ -r \"$_config\" ] || _die noread_config\n            file \"$_config\" | grep -q \"ASCII\" || _die invalid_config\n            shift ;;\n        --binary=* )\n            _binary=\"${1#*=}\"\n            [ -n \"$_binary\"] || _die no_binary\n            if [ ! -x \"$_binary\" ] || [ ! \"${binary##*/}\" = \"vgmplay\" ]; then\n                die _invalid_binary\n            fi\n            shift ;;\n        -* )\n            _die unknown_option \"$1\" ;;\n        -- )\n            shift ;;\n        \"\" )\n            _die no_music_file ;;\n        * )\n            [ -z \"$2\" ] || _die too_many_files\n            _ext=\"$(echo ${1##*.} | tr [:upper:] [:lower:])\"\n            case $_ext in\n                vgm | vgz | cmf | dro | m3u | zip | 7z | vgm7z )\n                    [ -r \"$1\" ] || _die file_unreadable\n                    _music_file=\"$1\";;\n                * )\n                    _die invalid_format\n            esac\n            case $_music_file in\n                ~* | /* )\n                    break ;;\n                * )\n                    _music_file=\"$_pwd/$_music_file\" ;;\n            esac\n            break ;;\n    esac\ndone\n\n# Does `vgmplay` exist if --binary not specified?\n#   Prefers vgmplay in working dir over any others\nif [ -n \"$_binary\" ]; then\n    break\nelif [ -x \"$_pwd/vgmplay\" ] && [ -f \"$_pwd/vgmplay\" ]; then\n    _binary=\"$_pwd/vgmplay\"\nelse\n    _binary=\"$(command -v vgmplay 2>/dev/null)\"\nfi\n[ -n \"$_binary\" ] || _die vgmplay_not_found\n\n# If a compressed pack, does a suitable unpacker exist?\ncase $_ext in\n    zip )\n        _unpack=true\n        command -v unzip 2>/dev/null || _die no_unpacker ;;\n    7z | vgm7z )\n        _unpack=true\n        command -v 7z 2>/dev/null || _die no_unpacker ;;\n    vgm | vgz | cmf | dro | m3u )\n        break ;;\n    * )\n        _die invalid_format ;;\nesac\n\n# Select config\nif [ -r \"$_config\" ]; then\n    break\nelse\n    for i in \"$_pwd\" \"$XDG_CONFIG_HOME/vgmplay\" \"$HOME/.config/vgmplay\" \"$XDG_CONFIG_DIRS/vgmplay\" \"$HOME/.local/share/vgmplay\" \"/etc/xdg/vgmplay\" \"/usr/local/share/vgmplay\" \"/usr/share/vgmplay\"; do\n        _config=\"$i/vgmplay.ini\"\n        [ -r \"$_config\" ] && break\n        _config=\"$i/VGMPlay.ini\"\n        [ -r \"$_config\" ] && break\n    done\nfi\n# vgmplay will function without a config, but will warn the user thus from inside the program\n\n# Make temporary working directory for vgmplay\n# Logdir availability checked here ...\n#   Uses $XDG_RUNTIME_DIR, $TMPDIR, /tmp\n#   Uses mktemp program for my sanity's sake\n#   Assumes user isn't going to try to log into a directory w/ a preexisting vgmplay.ini\n#       Seriously, if you're going to do that why would you use this helper to start with\nif [ -d \"$_log_path\" ]; then\n    command sed \"s/^LogSound.*/LogSound = 1/\" < \"$_config\" > \"$_log_path/vgmplay.ini\" || _die log_path_nowrite\nelif [ -n \"$XDG_RUNTIME_DIR\" ]; then\n    _tmpdir=\"$(command mktemp -d --tmpdir=\"$XDG_RUNTIME_DIR\")\" || _die tmpdir_fail\n    command cp \"$_config\" \"$_tmpdir/vgmplay.ini\" || _die tmpdir_fail\nelse #mktemp defaults to tmpdir then /tmp!\n    _tmpdir=\"$(command mktemp -d)\" || _die tmpdir_fail\n    command cp \"$_config\" \"$_tmpdir/vgmplay.ini\" || _die tmpdir_fail\nfi\n\n# Determine output to use if not forced\n# Also sets pulse-server if detected\n# PULSE_SERVER, oss, padsp, aoss, log set, error\nif [ -z \"$_set_output\" ]; then\n    if [ -n \"$PULSE_SERVER\" ] && [ -x \"$_padsp\" ]; then\n        _set_output=\"pulse-server\"\n    elif [ -w /dev/dsp ]; then\n        _set_output=\"oss\"\n    elif [ -x \"$_padsp\" ] && command pulseaudio --check ; then\n        _set_output=\"pulse\"\n    elif [ -x \"$_aoss\" ]; then\n        _set_output=\"alsa\"\n    elif [ -n \"$_log_path\" ]; then\n        _set_output=\"log\"\n    else\n        _die no_output\n    fi\nfi\n[ -n \"$_pulse_server\" ] && _set_output=pulse-server\n\nif [ \"$_unpack\" = true ]; then\n    if [ \"$_set_output\" = log ]; then\n        [ -d \"$_log_path\" ] && cd \"$_log_path\" || _die log_path_nowrite\n    else\n        [ -d \"$_tmpdir\" ] && cd \"$_tmpdir\" || _die tmpdir_failed\n    fi\n    if [ $_ext = \"zip\" ]; then\n        command unzip \"$_music_file\" > /dev/null\n    elif [ $_ext = \"7z\" ] || [ $_ext = \"vgm7z\" ]; then\n        command 7z x \"$_music_file\" > /dev/null\n    fi\n    # Notes:\n    #   - sed is used to remove the leading ./\n    #   - find is used to scan subfolders as well\n    _m3u_stub=$(command find . -iname '*.m3u' -print 2> /dev/null | head -n 1 | sed -e 's/^.\\///')\n    if [ -z \"$_m3u_stub\" ]; then\n        _m3u_stub=\"List.m3u\"\n        command find . -iname '*.vg[mz]' -print | sort | sed -e 's/^.\\///' > \"$_m3u_stub\" 2> /dev/null\n    fi\n    _music_file=\"$PWD/$_m3u_stub\"\nfi\n\n# Plays back song with specified everything\ncase $_set_output in\n    log )\n        (   cd \"$_log_path\"\n            \"$_binary\" \"$_music_file\"\n        )\n        command mv \"${_music_file%/*}/\"*.wav \"${_log_path}\"\n        [ -n \"$_music_stub\" ] && rm -rf \"$_log_path/$_music_stub\" ;;\n    pulse-server )\n        _pulse_server=\"${_pulse_server:-$PULSE_SERVER}\"\n        (   cd \"$_tmpdir\"\n            exec \"$_padsp\" -s \"$_pulse_server\" -n \"VGM Player\" -m \"OSS Emulation (from $_host)\" \"$_binary\" \"$_music_file\"\n        ) ;;\n    pulse )\n        (   cd \"$_tmpdir\"\n            exec \"$_padsp\" -n \"VGM Player\" -m \"OSS Emulation\" \"$_binary\" \"$_music_file\"\n        ) ;;\n    alsa )\n        (   cd \"$_tmpdir\"\n            exec \"$_aoss\" \"$_binary\" \"$_music_file\"\n        ) ;;\n    oss )\n        (   cd \"$_tmpdir\"\n            exec \"$_binary\" \"$_music_file\"\n        ) ;;\nesac\n#read waitvar\n# vim:ts=4:sw=4:et\n"
  },
  {
    "path": "VGMPlay/vgm2pcm.c",
    "content": "#define _GNU_SOURCE\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <wchar.h>\n\n#ifdef WIN32\n#include <windows.h>\n#else\n#include <limits.h>\n#define MAX_PATH PATH_MAX\n#include <unistd.h>\n#include <libgen.h>\n#endif\n\n#ifdef WIN32\n#define DIR_CHR     '\\\\'\n#define DIR_STR     \"\\\\\"\n#define QMARK_CHR   '\\\"'\n#else\n#define DIR_CHR     '/'\n#define DIR_STR     \"/\"\n#define QMARK_CHR   '\\''\n#endif\n\n#include \"chips/mamedef.h\"\n#include \"stdbool.h\"\n#include \"VGMPlay.h\"\n#include \"VGMPlay_Intf.h\"\n\n#define SAMPLESIZE sizeof(WAVE_16BS)\n\nUINT8 CmdList[0x100]; // used by VGMPlay.c and VGMPlay_AddFmts.c\nbool ErrorHappened;   // used by VGMPlay.c and VGMPlay_AddFmts.c\nextern VGM_HEADER VGMHead;\nextern UINT32 SampleRate;\nextern UINT32 VGMMaxLoopM;\nextern UINT32 FadeTime;\nextern bool EndPlay;\nextern char *AppPaths[8];\nstatic char AppPathBuffer[MAX_PATH * 2];\n\nstatic char* GetAppFileName(void)\n{\n\tchar* AppPath;\n\tint RetVal;\n\n\tAppPath = (char*)malloc(MAX_PATH * sizeof(char));\n#ifdef WIN32\n\tRetVal = GetModuleFileName(NULL, AppPath, MAX_PATH);\n\tif (! RetVal)\n\t\tAppPath[0] = '\\0';\n#else\n\tRetVal = readlink(\"/proc/self/exe\", AppPath, MAX_PATH);\n\tif (RetVal == -1)\n\t\tAppPath[0] = '\\0';\n#endif\n\n\treturn AppPath;\n}\n\nINLINE int fputBE16(UINT16 Value, FILE* hFile)\n{\n\tint RetVal;\n\tint ResVal;\n\n\tRetVal = fputc((Value & 0xFF00) >> 8, hFile);\n\tRetVal = fputc((Value & 0x00FF) >> 0, hFile);\n\tResVal = (RetVal != EOF) ? 0x02 : 0x00;\n\treturn ResVal;\n}\n\nint main(int argc, char *argv[]) {\n\tUINT8 result;\n\tWAVE_16BS *sampleBuffer;\n\tUINT32 bufferedLength;\n\tFILE *outputFile;\n\tchar *AppName;\n\tchar* AppPathPtr;\n\tconst char *StrPtr;\n\tUINT8 CurPath;\n\tUINT32 ChrPos;\n\n\tif (argc < 3) {\n\t\tfputs(\"usage: vgm2pcm vgm_file pcm_file\\n\", stderr);\n\t\treturn 1;\n\t}\n\n\tVGMPlay_Init();\n\t// Path 2: exe's directory\n\tAppPathPtr = AppPathBuffer;\n\tAppName = GetAppFileName(); // \"C:\\VGMPlay\\VGMPlay.exe\"\n\t// Note: GetAppFileName always returns native directory separators.\n\tStrPtr = strrchr(AppName, DIR_CHR);\n\tif (StrPtr != NULL)\n\t{\n\t\tChrPos = StrPtr + 1 - AppName;\n\t\tstrncpy(AppPathPtr, AppName, ChrPos);\n\t\tAppPathPtr[ChrPos] = 0x00;  // \"C:\\VGMPlay\\\"\n\t\tAppPaths[CurPath] = AppPathPtr;\n\t\tCurPath ++;\n\t\tAppPathPtr += ChrPos + 1;\n\t}\n\tVGMPlay_Init2();\n\n\tif (!OpenVGMFile(argv[1])) {\n\t\tfprintf(stderr, \"vgm2pcm: error: failed to open vgm_file (%s)\\n\", argv[1]);\n\t\treturn 1;\n\t}\n\n\tif(!strcmp(argv[2], \"-\")) {\n\t\toutputFile = stdout;\n\t} else {\n\t\toutputFile = fopen(argv[2], \"wb\");\n\t\tif (outputFile == NULL) {\n\t\t\tfprintf(stderr, \"vgm2pcm: error: failed to open pcm_file (%s)\\n\", argv[2]);\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\tPlayVGM();\n\n\tsampleBuffer = (WAVE_16BS*)malloc(SAMPLESIZE * SampleRate);\n\tif (sampleBuffer == NULL) {\n\t\tfprintf(stderr, \"vgm2pcm: error: failed to allocate %lu bytes of memory\\n\", SAMPLESIZE * SampleRate);\n\t\treturn 1;\n\t}\n\n\twhile (!EndPlay) {\n\t\tUINT32 bufferSize = SampleRate;\n\t\tbufferedLength = FillBuffer(sampleBuffer, bufferSize);\n\t\tif (bufferedLength) {\n\t\t\tUINT32 numberOfSamples;\n\t\t\tUINT32 currentSample;\n\t\t\tconst UINT16* sampleData;\n\n\t\t\tsampleData = (UINT16*)sampleBuffer;\n\t\t\tnumberOfSamples = SAMPLESIZE * bufferedLength / 0x02;\n\t\t\tfor (currentSample = 0x00; currentSample < numberOfSamples; currentSample++) {\n\t\t\t\tfputBE16(sampleData[currentSample], outputFile);\n\t\t\t}\n\t\t}\n\t}\n\n\tStopVGM();\n\n\tCloseVGMFile();\n\n\tVGMPlay_Deinit();\n\n\treturn 0;\n}\n"
  },
  {
    "path": "VGMPlay/vgm2wav.c",
    "content": "/*\n *  This file is part of VGMPlay <https://github.com/vgmrips/vgmplay>\n *\n *  (c)2015 libertyernie <maybeway36@gmail.com>\n *  Based on vgm2pcm.c:\n *    (c)2015 Francis Gagné <fragag1@gmail.com>\n *    (c)2015 Valley Bell\n *\n *  This program is free software; you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation; either version 2 of the License, or\n *  (at your option) any later version.\n *\n *  This program is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with this program; if not, write to the Free Software\n *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <wchar.h>\n\n#include <fcntl.h>\n\n#ifndef _MSC_VER\n// This turns command line options on (using getopt.h) unless you are using MSVC / Visual Studio, which doesn't have it.\n#define VGM2WAV_HAS_GETOPT\n#include <getopt.h>\n#endif\n\n#include \"chips/mamedef.h\"\n#include \"stdbool.h\"\n#include \"VGMPlay.h\"\n#include \"VGMPlay_Intf.h\"\n\n#define SAMPLESIZE sizeof(WAVE_16BS)\n\nUINT8 CmdList[0x100]; // used by VGMPlay.c and VGMPlay_AddFmts.c\nbool ErrorHappened;   // used by VGMPlay.c and VGMPlay_AddFmts.c\nextern VGM_HEADER VGMHead;\nextern UINT32 SampleRate;\nextern bool EndPlay;\n\nextern UINT32 VGMMaxLoop;\nextern UINT32 FadeTime;\n\nbool WriteSmplChunk;\n\nINLINE int fputLE16(UINT16 Value, FILE* hFile)\n{\n\tint RetVal;\n\tint ResVal;\n\n\tRetVal = fputc((Value & 0x00FF) >> 0, hFile);\n\tRetVal = fputc((Value & 0xFF00) >> 8, hFile);\n\tResVal = (RetVal != EOF) ? 0x02 : 0x00;\n\treturn ResVal;\n}\n\nINLINE int fputLE32(UINT32 Value, FILE* hFile)\n{\n\tint RetVal;\n\tint ResVal;\n\n\tRetVal = fputc((Value & 0x000000FF) >> 0, hFile);\n\tRetVal = fputc((Value & 0x0000FF00) >> 8, hFile);\n\tRetVal = fputc((Value & 0x00FF0000) >> 16, hFile);\n\tRetVal = fputc((Value & 0xFF000000) >> 24, hFile);\n\tResVal = (RetVal != EOF) ? 0x02 : 0x00;\n\treturn ResVal;\n}\n\nvoid usage(const char *name) {\n\tfprintf(stderr, \"usage: %s [options] vgm_file wav_file\\n\"\n\t\t\"wav_file can be - for standard output.\\n\", name);\n#ifdef VGM2WAV_HAS_GETOPT\n\tfputs(\"\\n\"\n\t\t\"Options:\\n\"\n\t\t\"--loop-count {number}\\n\"\n\t\t\"--fade-ms {number}\\n\"\n\t\t\"--no-smpl-chunk\\n\"\n\t\t\"\\n\", stderr);\n#else\n\tfputs(\"Options not supported in this build (compiled without getopt.)\\n\", stderr);\n#endif\n}\n\nint main(int argc, char *argv[]) {\n\tWAVE_16BS *sampleBuffer;\n\tUINT32 bufferedLength;\n\tFILE *outputFile;\n\n\tlong int wavRIFFLengthPos;\n\tlong int wavDataLengthPos;\n\tint sampleBytesWritten = 0;\n\n\t// Initialize VGMPlay before parsing arguments, so we can set VGMMaxLoop and FadeTime\n\tVGMPlay_Init();\n\tVGMPlay_Init2();\n\n\tVGMMaxLoop = 2;\n\tFadeTime = 5000;\n\tWriteSmplChunk = true;\n\n\tint c;\n\n\t// Parse command line arguments\n#ifdef VGM2WAV_HAS_GETOPT\n\tstatic struct option long_options[] = {\n\t\t{ \"loop-count\", required_argument, NULL, 'l' },\n\t\t{ \"fade-ms\", required_argument, NULL, 'f' },\n\t\t{ \"no-smpl-chunk\", no_argument, NULL, 'S' },\n\t\t{ \"help\", no_argument, NULL, '?' },\n\t\t{ NULL, 0, NULL, 0 }\n\t};\n\twhile ((c = getopt_long(argc, argv, \"\", long_options, NULL)) != -1) {\n\t\tswitch (c) {\n\t\tcase 'l':\n\t\t\tc = atoi(optarg);\n\t\t\tif (c <= 0) {\n\t\t\t\tfputs(\"Error: loop count must be at least 1.\\n\", stderr);\n\t\t\t\tusage(argv[0]);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tVGMMaxLoop = c;\n\t\t\t//fprintf(stderr, \"Setting max loops to %u\\n\", VGMMaxLoop);\n\t\t\tbreak;\n\t\tcase 'f':\n\t\t\tFadeTime = atoi(optarg);\n\t\t\t//fprintf(stderr, \"Setting fade-out time in milliseconds to %u\\n\", FadeTime);\n\t\t\tbreak;\n\t\tcase 'S':\n\t\t\tWriteSmplChunk = false;\n\t\t\tbreak;\n\t\tcase -1:\n\t\t\tbreak;\n\t\tcase '?':\n\t\t\tusage(argv[0]);\n\t\t\treturn 0;\n\t\tdefault:\n\t\t\tusage(argv[0]);\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\t// Pretend for the rest of the program that those options don't exist\n\targv[optind - 1] = argv[0];\n\targc -= optind - 1;\n\targv += optind - 1;\n#endif\n\tif (argc < 3) {\n\t\tusage(argv[0]);\n\t\treturn 1;\n\t}\n\n\tif (!OpenVGMFile(argv[1])) {\n\t\tfprintf(stderr, \"vgm2wav: error: failed to open vgm_file (%s)\\n\", argv[1]);\n\t\treturn 1;\n\t}\n\n\tif (argv[2][0] == '-' && argv[2][1] == '\\0') {\n#ifdef O_BINARY\n\t\tsetmode(fileno(stdout), O_BINARY);\n#endif\n\t\toutputFile = stdout;\n\t} else {\n\t\toutputFile = fopen(argv[2], \"wb\");\n\t\tif (outputFile == NULL) {\n\t\t\tfprintf(stderr, \"vgm2wav: error: failed to open wav_file (%s)\\n\", argv[2]);\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\tif (WriteSmplChunk && VGMHead.lngLoopSamples == 0) {\n\t\tWriteSmplChunk = false;\n\t}\n\n\tfwrite(\"RIFF\", 1, 4, outputFile);\n\n\twavRIFFLengthPos = ftell(outputFile);\n\tfputLE32(-1, outputFile);\n\n\tfwrite(\"WAVE\", 1, 4, outputFile);\n\n\tfwrite(\"fmt \", 1, 4, outputFile);\n\tfputLE32(16, outputFile);\n\tfputLE16(1, outputFile);\n\tfputLE16(2, outputFile);\n\tfputLE32(SampleRate, outputFile);\n\tfputLE32(SampleRate * 2 * 2, outputFile);\n\tfputLE16(2 * 2, outputFile);\n\tfputLE16(16, outputFile);\n\n\tif (WriteSmplChunk) {\n\t\tfwrite(\"smpl\", 1, 4, outputFile);\n\t\tfputLE32(60, outputFile);\n\t\tfputLE32(0, outputFile);\n\t\tfputLE32(0, outputFile);\n\t\tfputLE32(0, outputFile);\n\t\tfputLE32(0, outputFile);\n\t\tfputLE32(0, outputFile);\n\t\tfputLE32(0, outputFile);\n\t\tfputLE32(0, outputFile);\n\t\tfputLE32(1, outputFile);\n\t\tfputLE32(0, outputFile);\n\n\t\tfputLE32(0, outputFile);\n\t\tfputLE32(0, outputFile);\n\t\tfputLE32(VGMHead.lngTotalSamples - VGMHead.lngLoopSamples, outputFile);\n\t\tfputLE32(VGMHead.lngTotalSamples, outputFile);\n\t\tfputLE32(0, outputFile);\n\t\tfputLE32(0, outputFile);\n\t}\n\n\tfwrite(\"data\", 1, 4, outputFile);\n\n\twavDataLengthPos = ftell(outputFile);\n\tfputLE32(-1, outputFile);\n\n\tPlayVGM();\n\n\tsampleBuffer = (WAVE_16BS*)malloc(SAMPLESIZE * SampleRate);\n\tif (sampleBuffer == NULL) {\n\t\tfprintf(stderr, \"vgm2wav: error: failed to allocate %lu bytes of memory\\n\", SAMPLESIZE * SampleRate);\n\t\treturn 1;\n\t}\n\n\twhile (!EndPlay) {\n\t\tUINT32 bufferSize = SampleRate;\n\t\tbufferedLength = FillBuffer(sampleBuffer, bufferSize);\n\t\tif (bufferedLength) {\n\t\t\tUINT32 numberOfSamples;\n\t\t\tUINT32 currentSample;\n\t\t\tconst UINT16* sampleData;\n\n\t\t\tsampleData = (UINT16*)sampleBuffer;\n\t\t\tnumberOfSamples = SAMPLESIZE * bufferedLength / 0x02;\n\t\t\tfor (currentSample = 0x00; currentSample < numberOfSamples; currentSample++) {\n\t\t\t\tfputLE16(sampleData[currentSample], outputFile);\n\t\t\t\tsampleBytesWritten += 2;\n\t\t\t}\n\t\t}\n\t}\n\n\tfflush(outputFile);\n\tStopVGM();\n\n\tCloseVGMFile();\n\n\tVGMPlay_Deinit();\n\n\tif (wavRIFFLengthPos >= 0) {\n\t\tfseek(outputFile, wavRIFFLengthPos, SEEK_SET);\n\t\tif (WriteSmplChunk) {\n\t\t\tfputLE32(sampleBytesWritten + 28 + 68 + 8, outputFile);\n\t\t} else {\n\t\t\tfputLE32(sampleBytesWritten + 28 + 8, outputFile);\n\t\t}\n\t}\n\tif (wavDataLengthPos >= 0) {\n\t\tfseek(outputFile, wavDataLengthPos, SEEK_SET);\n\t\tfputLE32(sampleBytesWritten, outputFile);\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "VGMPlay/vgm2wav.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"vgm2pcm\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** NICHT BEARBEITEN **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=VGMPlay - Win32 Debug\r\n!MESSAGE Dies ist kein gltiges Makefile. Zum Erstellen dieses Projekts mit NMAKE\r\n!MESSAGE verwenden Sie den Befehl \"Makefile exportieren\" und fhren Sie den Befehl\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"VGMPlay.mak\".\r\n!MESSAGE \r\n!MESSAGE Sie knnen beim Ausfhren von NMAKE eine Konfiguration angeben\r\n!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"VGMPlay.mak\" CFG=\"VGMPlay - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Fr die Konfiguration stehen zur Auswahl:\r\n!MESSAGE \r\n!MESSAGE \"VGMPlay - Win32 Release\" (basierend auf  \"Win32 (x86) Console Application\")\r\n!MESSAGE \"VGMPlay - Win32 Debug\" (basierend auf  \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"Release\"\r\n# PROP BASE Intermediate_Dir \"Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"Release\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /Yu\"stdafx.h\" /FD /c\r\n# ADD CPP /nologo /MD /W3 /GX /Ox /Ot /Og /Oi /Ob2 /I \"zlib\" /D \"NDEBUG\" /D \"WIN32_LEAN_AND_MEAN\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"ENABLE_ALL_CORES\" /D \"CONSOLE_MODE\" /D \"ADDITIONAL_FORMATS\" /D \"SET_CONSOLE_TITLE\" /FD /c\r\n# SUBTRACT CPP /Oa /Ow /YX /Yc /Yu\r\n# ADD BASE RSC /l 0x407 /d \"NDEBUG\"\r\n# ADD RSC /l 0x407 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 msvcrt.lib kernel32.lib user32.lib advapi32.lib winmm.lib zdll.lib /nologo /subsystem:console /machine:I386 /libpath:\"zlib\"\r\n# Begin Special Build Tool\r\nSOURCE=\"$(InputPath)\"\r\nPostBuild_Cmds=..\\vgm2txt\\HiddenMsg.exe Release\\VGMPlay.exe\r\n# End Special Build Tool\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"Debug\"\r\n# PROP BASE Intermediate_Dir \"Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"Debug\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /Yu\"stdafx.h\" /FD /GZ /c\r\n# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I \"zlib\" /D \"_DEBUG\" /D \"WIN32_LEAN_AND_MEAN\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"ENABLE_ALL_CORES\" /D \"CONSOLE_MODE\" /D \"ADDITIONAL_FORMATS\" /D \"SET_CONSOLE_TITLE\" /FR /FD /GZ /c\r\n# SUBTRACT CPP /YX /Yc /Yu\r\n# ADD BASE RSC /l 0x407 /d \"_DEBUG\"\r\n# ADD RSC /l 0x407 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 msvcrtd.lib kernel32.lib user32.lib advapi32.lib winmm.lib zdll.lib /nologo /subsystem:console /debug /machine:I386 /libpath:\"zlib\"\r\n# SUBTRACT LINK32 /profile /map\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"VGMPlay - Win32 Release\"\r\n# Name \"VGMPlay - Win32 Debug\"\r\n# Begin Group \"Quellcodedateien\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\pt_ioctl.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Stream.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\VGMPlay.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\VGMPlay_AddFmts.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\vgm2wav.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header-Dateien\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\PortTalk_IOCTL.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Stream.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=\".\\XMasFiles\\SWJ-SQRC01_1C.h\"\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\VGMFile.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\VGMPlay.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\VGMPlay_Intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\XMasFiles\\XMasBonus.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Ressourcendateien\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# Begin Group \"SoundCore\"\r\n\r\n# PROP Default_Filter \"c;h;cpp\"\r\n# Begin Group \"FM OPL Chips\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2413intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2413intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2413tone.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\262intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\262intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\281btone.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\3526intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /W1 /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n# ADD CPP /W1\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\3526intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\3812intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /W1 /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n# ADD CPP /W1\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\3812intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\8950intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /W1 /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n# ADD CPP /W1\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\8950intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\adlibemu.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\adlibemu_opl2.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\adlibemu_opl3.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\emu2413.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\emu2413.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\emutypes.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\fmopl.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\fmopl.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\opl.c\r\n# PROP Exclude_From_Build 1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\opl.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\vrc7tone.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2413.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2413.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymf262.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymf262.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymf278b.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymf278b.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"FM OPN Chips\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2203intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2203intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2608intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2608intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2610intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2610intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2612intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2612intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\fm.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\fm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\fm2612.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2612.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2612.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym3438.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym3438.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"FM OPx Chips\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2151intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\2151intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scsp.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scsp.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scspdsp.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scspdsp.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scsplfo.c\r\n# PROP Exclude_From_Build 1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2151.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2151.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymf271.c\r\n# ADD CPP /W1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymf271.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"PCM Chips\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c140.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c140.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c352.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c352.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\es5503.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\es5503.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\es5506.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\es5506.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\iremga20.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\iremga20.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\k053260.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\k053260.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\k054539.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\k054539.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\multipcm.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\multipcm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\okim6258.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\okim6258.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\okim6295.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\okim6295.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\pwm.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\pwm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\qsound.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\qsound.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\rf5c68.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\rf5c68.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scd_pcm.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\scd_pcm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\segapcm.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\segapcm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\upd7759.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\upd7759.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\x1_010.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\x1_010.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymdeltat.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymdeltat.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymz280b.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /W1 /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n# ADD CPP /W1\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ymz280b.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"OPL Mapper\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ay8910_opl.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn76496_opl.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2413_opl.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /W1 /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2413hd.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /W1 /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ym2413hd.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"PSG Chips\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ay8910.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ay8910.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ay_intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ay_intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c6280.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c6280.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c6280intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\c6280intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\emu2149.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\emu2149.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\gb.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\gb.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\k051649.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\k051649.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\Ootake_PSG.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\Ootake_PSG.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\pokey.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\pokey.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\saa1099.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\saa1099.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn76489.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn76489.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn76496.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn76496.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn764intf.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\sn764intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\vsu.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\vsu.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ws_audio.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ws_audio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ws_initialIo.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"NES Chips\"\r\n\r\n# PROP Default_Filter \"c;h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\nes_apu.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\nes_apu.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\nes_defs.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\nes_intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\nes_intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\np_nes_apu.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\np_nes_apu.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\np_nes_dmc.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\np_nes_dmc.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\np_nes_fds.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\np_nes_fds.h\r\n# End Source File\r\n# End Group\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\ChipIncl.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\ChipMapper.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\ChipMapper.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\dac_control.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\dac_control.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\mamedef.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\panning.c\r\n\r\n!IF  \"$(CFG)\" == \"VGMPlay - Win32 Release\"\r\n\r\n# ADD CPP /Oa\r\n\r\n!ELSEIF  \"$(CFG)\" == \"VGMPlay - Win32 Debug\"\r\n\r\n!ENDIF \r\n\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\chips\\panning.h\r\n# End Source File\r\n# End Group\r\n# Begin Source File\r\n\r\nSOURCE=.\\ReadMe.txt\r\n# End Source File\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "VGMPlay/vgmplay.1",
    "content": ".TH vgmplay \"1\" \"November 10\" \"Valley Bell\" \"User Commands\"\n.nh\n.SH NAME\nvgmplay \\- the official and always up-to-date player for all VGM files\n.SH SYNOPSIS\n\\fBvgmplay\\fP file\n.SH KEYS\nCursor Left/Right - Seek 5 seconds backward/forward\n.PP\nCtrl + Cursor Left/Right - Seek 1 minute backward/forward\n.PP\nSpace - Pause\n.PP\nESC/Q - Quit the program\n.PP\nF - Fade out\n.PP\nR - Restart current Track\n.PP\nPageUp/B - Previous Track\n.PP\nPageDown/N - Next Track\n.SH SUPPORTED FILETYPES\nVideo Game Music Files (.vgm, .vgz)\n.PP\nCreative Music Files (.cmf)\n.PP\nDosBox RAW OPL Log Files (.dro)\n.PP\nPlaylist files (.m3u)\n.SH SUPPORTED CHIPS\n.PP\nSN76496 (2) (Sega PSG) and T6W28 (2) (NeoGeo Pocket custom)\n.PP\nYM2413 (1) (OPLL)\n.PP\nYM2612 (OPN2)\n.PP\nYM2151 (OPM)\n.PP\nSegaPCM\n.PP\nRF5C68\n.PP\nYM2203 (OPN)\n.PP\nYM2608 (OPNA)\n.PP\nYM2610/B (OPNB)\n.PP\nYM3812 (1) (OPL2)\n.PP\nYM3526 (1) (OPL)\n.PP\nY8950 (1) (MSX AUDIO)\n.PP\nYMF262 (1) (OP3)\n.PP\nYMF278B (3) (OPL4)\n.PP\nYMF271 (OPLX)\n.PP\nYMZ280B\n.PP\nRF5C164 (Sega MegaCD PCM)\n.PP\nPWM (from Sega 32x)\n.PP\nAY8910 (MSX PSG)\n.PP\nGameBoy DMG\n.PP\nNES APU (incl. FDS)\n.PP\nMultiPCM\n.PP\nUPD7759\n.PP\nOKI6258 (Sharp X68000 ADPCM)\n.PP\nOKI6295\n.PP\nK051649\n.PP\nK054539\n.PP\nHuC6280 (PC Engine)\n.PP\nC140\n.PP\nK053260\n.PP\nPokey (Atari)\n.PP\nQSound\n.PP\nSCSP (Saturn Custom Sound Processor, YMF292-F)\n.PP\n(1) This chip can be emulated via OPL Hardware (like Soundblaster sound cards).\n.PP\n(2) OPL hardware emulation is available, but software emulation is prefered. Hardware emulation is used if another chip activates HW emulation or FMForce is True.\n(3) You need a sample ROM, called yrw801.rom, to make playback work. Place it in the directory where vgmplay lies or in /usr/local/share/vgmplay/.\n.PP\nOPL hardware emulation can be enabled by setting the \"FMPort\"-entry in the ini-file.\nUnder Linux the program must be run as root to use hardware FM.\n.PP\nIt's possible to write Wave files by editing the \"LogSound\"-line in the ini-file.\nBatch conversions are possible by opening a playlist.\nFM hardware cannot be logged to Wave files.\n.SH CONFIGURATION\nvgmplay is configured in the file VGMPlay.ini, which should be located in $XDG_CONFIG_HOME/vgmplay (thus, by default ~/.config/vgmplay/VGMPlay.ini).  A sample configuration /usr/share/vgmplay/VGMPlay.ini is available for copying and general reference.\n.SH BUGS\nPauseEmulation is disabled under Linux if no FM Hardware is used.\n.PP\nYou have to double-tap ESC to quit the program.\n.PP\nSometimes MAME's sound cores tend to sound strange.\n.SH COMMENTS\nThe T6W28 doesn't use MAME's T6W28 core. Instead the SN76496 core is modified to emulate the T6W28 with 2 SN76496 chips.\nThe SN76496 OPL emulation is okay, but it's impossible to get the noise sound right.\n.PP\nEMU2413 Emulator was added, because sometimes the one of MAME sounds strange.\nThe Gens YM2612 core was added for the same reason before MAME's YM2612 core was fixed.\n.PP\n.SH AUTHORS\nThis program was written by Valley Bell.\n.PP\nAlmost all software emulators are from MAME (http://mamedev.org)\n.PP\nEMU2413 and Gens YM2612 were ported from Maxim's in_vgm\n.PP\nThe YMF278B core was ported from openMSX\n.PP\nzlib compression by Jean-loup Gailly and Mark Adler is used\n.PP\nAll custom OPL Mappers were written using MAME software emulators and the OPL2/3 programming guides by Jeffrey S. Lee and Vladimir Arnost\n.PP\none YM2413 OPL Mapper was ported from MEKA.\n.PP\nThe RF5C164 and PWM cores were ported from Gens/GS\n.PP\nThe MAME YM2612 core was fixed with the help of Blargg's MAME YM2612 fix and Genesis Plus GX' YM2612 core\n.PP\nAdLibEmu (OPL2 and OPL3 core) was ported from DOSBox\n.PP\nThe default HuC6280 core is from Ootake.\n.PP\nEMU2149, the alternative NES APU core and the NES FDS core were ported from rainwarrior's NSFPlay.\n"
  },
  {
    "path": "VGMPlay/vgmspec171.txt",
    "content": "VGM Spec v1.71 beta\n==============\nVGM (Video Game Music) is a sample-accurate sound logging format for the Sega\nMaster System, the Sega Game Gear and possibly many other machines (e.g. Sega\nGenesis).\n\nThe normal file extension is .vgm but files can also be GZip compressed into\n.vgz files. However, a VGM player should attempt to support compressed and\nuncompressed files with either extension. (ZLib's GZIO library makes this\ntrivial to implement.)\n\nThe format starts with a 256 byte header:\n\n      00  01  02  03   04  05  06  07   08  09  0A  0B  0C  0D  0E  0F\n0x00 [\"Vgm \" ident   ][EoF offset     ][Version        ][SN76489 clock  ]\n0x10 [YM2413 clock   ][GD3 offset     ][Total # samples][Loop offset    ]\n0x20 [Loop # samples ][Rate           ][SN FB ][SNW][SF][YM2612 clock   ]\n0x30 [YM2151 clock   ][VGM data offset][Sega PCM clock ][SPCM Interface ]\n0x40 [RF5C68 clock   ][YM2203 clock   ][YM2608 clock   ][YM2610/B clock ]\n0x50 [YM3812 clock   ][YM3526 clock   ][Y8950 clock    ][YMF262 clock   ]\n0x60 [YMF278B clock  ][YMF271 clock   ][YMZ280B clock  ][RF5C164 clock  ]\n0x70 [PWM clock      ][AY8910 clock   ][AYT][AY Flags  ][VM] *** [LB][LM]\n0x80 [GB DMG clock   ][NES APU clock  ][MultiPCM clock ][uPD7759 clock  ]\n0x90 [OKIM6258 clock ][OF][KF][CF] *** [OKIM6295 clock ][K051649 clock  ]\n0xA0 [K054539 clock  ][HuC6280 clock  ][C140 clock     ][K053260 clock  ]\n0xB0 [Pokey clock    ][QSound clock   ][SCSP clock     ][Extra Hdr ofs  ]\n0xC0 [WSwan clock    ][VSU clock      ][SAA1099 clock  ][ES5503 clock   ]\n0xD0 [ES5506 clock   ][EC][EC][CD] *** [X1-010 clock   ][C352 clock     ]\n0xE0 [GA20 clock     ] *** *** *** ***  *** *** *** ***  *** *** *** ***\n0xF0  *** *** *** ***  *** *** *** ***  *** *** *** ***  *** *** *** ***\n\n- Unused space (marked with *) is reserved for future expansion, and must be\n  zero.\n- All integer values are *unsigned* and written in \"Intel\" byte order (Little\n  Endian), so for example 0x12345678 is written as 0x78 0x56 0x34 0x12.\n- All pointer offsets are written as relative to the current position in the\n  file, so for example the GD3 offset at 0x14 in the header is the file\n  position of the GD3 tag minus 0x14.\n- All header sizes are valid for all versions from 1.50 on, as long as header\n  has at least 64 bytes. If the VGM data starts at an offset that is lower\n  than 0x100, all overlapping header bytes have to be handled as they were\n  zero.\n- VGMs run with a rate of 44100 Hz. The unit of time is called \"sample\".\n\n0x00: \"Vgm \" (0x56 0x67 0x6d 0x20) file identification (32 bits)\n0x04: Eof offset (32 bits)\n        Relative offset to end of file (i.e. file length - 4).\n        This is mainly used to find the next track when concatenating\n        player stubs and multiple files.\n0x08: Version number (32 bits)\n        Version number in BCD-Code. e.g. Version 1.71 is stored as 0x00000171.\n        This is used for backwards compatibility in players, and defines which\n        header values are valid.\n0x0C: SN76489 clock (32 bits)\n        Input clock rate in Hz for the SN76489 PSG chip. A typical value is\n        3579545. It should be 0 if there is no PSG chip used.\n        Note: Bit 31 (0x80000000) is used on combination with the dual-chip-bit\n        to indicate that this is a T6W28. (PSG variant used in NeoGeo Pocket)\n0x10: YM2413 clock (32 bits)\n        Input clock rate in Hz for the YM2413 chip. A typical value is 3579545.\n        It should be 0 if there is no YM2413 chip used.\n        If bit 31 is set it is a VRC7 (version 1.51+).\n0x14: GD3 offset (32 bits)\n        Relative offset to GD3 tag. 0 if no GD3 tag.\n        GD3 tags are descriptive tags similar in use to ID3 tags in MP3 files.\n        See the GD3 specification for more details. The GD3 tag is usually\n        stored immediately after the VGM data.\n0x18: Total # samples (32 bits)\n        Total of all wait values in the file.\n0x1C: Loop offset (32 bits)\n        Relative offset to loop point, or 0 if no loop.\n        For example, if the data for the one-off intro to a song was in bytes\n        0x0040-0x3FFF of the file, but the main looping section started at\n        0x4000, this would contain the value 0x4000-0x1C = 0x00003FE4.\n0x20: Loop # samples (32 bits)\n        Number of samples in one loop, or 0 if there is no loop.\n        Total of all wait values between the loop point and the end of\n        the file.\n[VGM 1.01 additions:]\n0x24: Rate (32 bits)\n        \"Rate\" of recording in Hz, used for rate scaling on playback. It is\n        typically 50 for PAL systems and 60 for NTSC systems. It should be set\n        to zero if rate scaling is not appropriate - for example, if the game\n        adjusts its music engine for the system's speed.\n        VGM 1.00 files will have a value of 0.\n[VGM 1.10 additions:]\n0x28: SN76489 feedback (16 bits)\n        The white noise feedback pattern for the SN76489 PSG. Known values are:\n        0x0009  Sega Master System 2/Game Gear/Mega Drive\n                (SN76489/SN76496 integrated into Sega VDP chip)\n        0x0003  Sega Computer 3000H, BBC Micro\n                (SN76489AN)\n        0x0006  SN76494, SN76496\n        For version 1.01 and earlier files, the feedback pattern should be\n        assumed to be 0x0009. If the PSG is not used then this may be omitted\n        (left at zero).\n0x2A: SN76489 shift register width (8 bits)\n        The noise feedback shift register width, in bits. Known values are:\n        16  Sega Master System 2/Game Gear/Mega Drive\n            (SN76489/SN76496 integrated into Sega VDP chip)\n        15  Sega Computer 3000H, BBC Micro\n            (SN76489AN)\n        For version 1.01 and earlier files, the shift register width should be\n        assumed to be 16. If the PSG is not used then this may be omitted (left\n        at zero).\n[VGM 1.51 additions:]\n0x2B: SN76489 Flags (8 bits)\n        Misc flags for the SN76489. Most of them don't make audible changes and\n        can be ignored, if the SN76489 emulator lacks the features.\n        bit 0   frequency 0 is 0x400\n        bit 1   output negate flag\n        bit 2   stereo on/off (on when bit clear)\n        bit 3   /8 Clock Divider on/off (on when bit clear)\n        bit 4   XNOR noise feedback (used by NCR8496)\n        bit 5-7 reserved (must be zero)\n        For version 1.51 and earlier files, all the flags should not be set.\n        If the PSG is not used then this may be omitted (left at zero).\n[VGM 1.10 additions:]\n0x2C: YM2612/YM3438 clock (32 bits)\n        Input clock rate in Hz for the YM2612 chip. A typical value is 7670454.\n        It should be 0 if there us no YM2612 chip used.\n        For version 1.01 and earlier files, the YM2413 clock rate should be\n        used for the clock rate of the YM2612.\n        If bit 31 is set it is a YM3438 (version 1.51+).\n0x30: YM2151/YM2164 clock (32 bits)\n        Input clock rate in Hz for the YM2151 chip. A typical value is 3579545.\n        It should be 0 if there us no YM2151 chip used.\n        For version 1.01 and earlier files, the YM2413 clock rate should be\n        used for the clock rate of the YM2151.\n        If bit 31 is set it is a YM2164 (version 1.51+).\n[VGM 1.50 additions:]\n0x34: VGM data offset (32 bits)\n        Relative offset to VGM data stream.\n        If the VGM data starts at absolute offset 0x40, this will contain \n        value 0x0000000C. For versions prior to 1.50, it should be 0 and the\n        VGM data must start at offset 0x40.\n[VGM 1.51 additions:]\n0x38: Sega PCM clock (32 bits)\n        Input clock rate in Hz for the Sega PCM chip. A typical value is\n        4000000. It should be 0 if there is no Sega PCM chip used.\n0x3C: Sega PCM interface register (32 bits)\n        The interface register for the Sega PCM chip. It should be 0 if there\n        is no Sega PCM chip used.\n0x40: RF5C68 clock (32 bits)\n        Input clock rate in Hz for the RF5C68 PCM chip. A typical value is\n        12500000. It should be 0 if there is no RF5C68 chip used.\n0x44: YM2203 clock (32 bits)\n        Input clock rate in Hz for the YM2203 chip. A typical value is 3000000.\n        It should be 0 if there is no YM2203 chip used.\n0x48: YM2608 clock (32 bits)\n        Input clock rate in Hz for the YM2608 chip. A typical value is 8000000.\n        It should be 0 if there is no YM2608 chip used.\n0x4C: YM2610/YM2610B clock (32 bits)\n        Input clock rate in Hz for the YM2610/B chip. A typical value is\n        8000000. It should be 0 if there is no YM2610/B chip used.\n        Note: Bit 31 is used to set whether it is a YM2610 or a YM2610B chip.\n        If bit 31 is set it is an YM2610B, if bit 31 is clear it is an YM2610.\n0x50: YM3812 clock (32 bits)\n        Input clock rate in Hz for the YM3812 chip. A typical value is 3579545.\n        It should be 0 if there is no YM3812 chip used.\n0x54: YM3526 clock (32 bits)\n        Input clock rate in Hz for the YM3526 chip. A typical value is 3579545.\n        It should be 0 if there is no YM3526 chip used.\n0x58: Y8950 clock (32 bits)\n        Input clock rate in Hz for the Y8950 chip. A typical value is 3579545.\n        It should be 0 if there is no Y8950 chip used.\n0x5C: YMF262 clock (32 bits)\n        Input clock rate in Hz for the YMF262 chip. A typical value is\n        14318180. It should be 0 if there is no YMF262 chip used.\n0x60: YMF278B clock (32 bits)\n        Input clock rate in Hz for the YMF278B chip. A typical value is\n        33868800. It should be 0 if there is no YMF278B chip used.\n0x64: YMF271 clock (32 bits)\n        Input clock rate in Hz for the YMF271 chip. A typical value is\n        16934400. It should be 0 if there is no YMF271 chip used.\n0x68: YMZ280B clock (32 bits)\n        Input clock rate in Hz for the YMZ280B chip. A typical value is\n        16934400. It should be 0 if there is no YMZ280B chip used.\n0x6C: RF5C164 clock (32 bits)\n        Input clock rate in Hz for the RF5C164 PCM chip. A typical value is\n        12500000. It should be 0 if there is no RF5C164 chip used.\n0x70: PWM clock (32 bits)\n        Input clock rate in Hz for the PWM chip. A typical value is\n        23011361. It should be 0 if there is no PWM chip used.\n0x74: AY8910 clock (32 bits)\n        Input clock rate in Hz for the AY8910 chip. A typical value is 1789773.\n        It should be 0 if there is no AY8910 chip used.\n0x78: AY8910 Chip Type (8 bits)\n        Defines the exact type of AY8910. The values are:\n        0x00 - AY8910\n        0x01 - AY8912\n        0x02 - AY8913\n        0x03 - AY8930\n        0x10 - YM2149\n        0x11 - YM3439\n        0x12 - YMZ284\n        0x13 - YMZ294\n        If the AY8910 is not used then this may be omitted (left at zero).\n0x79: AY8910 Flags (8 bits)\n        Misc flags for the AY8910. Default is 0x01.\n        For additional description see ay8910.h in MAME source code.\n        bit 0   Legacy Output\n        bit 1   Single Output\n        bit 2   Discrete Output\n        bit 3   RAW Output\n        bit 4   YM2149 Pin 26 (additional /2 clock divider)\n        bit 5-6 reserved (must be zero)\n        bit 7   Use ZX-Spectrum-like pan configuration (Left-Center-Right).\n        If the AY8910 is not used then this may be omitted (left at zero).\n0x7A: YM2203/AY8910 Flags (8 bits)\n        Misc flags for the AY8910. This one is specific for the AY8910 that's\n        connected with/part of the YM2203.\n0x7B: YM2608/AY8910 Flags (8 bits)\n        Misc flags for the AY8910. This one is specific for the AY8910 that's\n        connected with/part of the YM2608.\n[VGM 1.60 additions:]\n0x7C: Volume Modifier (8 bits)\n        Volume = 2 ^ (VolumeModifier / 0x20) where VolumeModifier is a number\n        from -63 to 192 (-63 = 0xC1, 0 = 0x00, 192 = 0xC0). Also the value -63\n        gets replaced with -64 in order to make factor of 0.25 possible.\n        Therefore the volume can reach levels between 0.25 and 64.\n        Default is 0, which is equal to a factor of 1.0 or 100%.\n        Note: Players should support the Volume Modifier in v1.50 files and\n        higher despite their late addition. This way MegaDrive VGMs can use\n        the Volume Modifier without breaking compatibility with old players.\n0x7D: reserved\n        Reserved byte for future use. It must be 0.\n0x7E: Loop Base (8 bits)\n        Modifies the number of loops that are played before the playback ends.\n        Set this value to eg. 1 to reduce the number of played loops by one.\n        This is useful, if the song is looped twice in the vgm, because there\n        are minor differences between the first and second loop and the song\n        repeats just the second loop.\n        The resulting number of loops that are played is calculated as\n        following: NumLoops = NumLoopsModified - LoopBase\n        Default is 0. Negative numbers are possible (80h...FFh = -128...-1)\n        Note: Players should support the Volume Modifier in v1.51 files.\n[VGM 1.51 additions:]\n0x7F: Loop Modifier (8 bits)\n        Modifies the number of loops that are played before the playback ends.\n        You may want to use this, e.g. if a tune has a very short, but non-\n        repetive loop (then set it to 0x20 double the loop number).\n        The resulting number of loops that are played is calculated as\n        following: NumLoops = ProgramNumLoops * LoopModifier / 0x10\n        Default is 0, which is equal to 0x10.\n[VGM 1.61 additions:]\n0x80: GameBoy DMG clock (32 bits)\n        Input clock rate in Hz for the GameBoy DMG chip, LR35902. A typical\n        value is 4194304. It should be 0 if there is no GB DMG chip used.\n0x84: NES APU clock (32 bits)\n        Input clock rate in Hz for the NES APU chip, N2A03. A typical value is\n        1789772. It should be 0 if there is no NES APU chip used.\n        Note: Bit 31 is used to enable the FDS sound addon. Set to enable,\n        clear to disable.\n0x88: MultiPCM clock (32 bits)\n        Input clock rate in Hz for the MultiPCM chip. A typical value is\n        8053975. It should be 0 if there is no MultiPCM chip used.\n0x8C: uPD7759 clock (32 bits)\n        Input clock rate in Hz for the uPD7759 chip. A typical value is 640000.\n        It should be 0 if there is no uPD7759 chip used. Set bit 31 (0x80000000)\n        to denote that the chip is in a Slave, clear bit 31 to denote that the\n        chip is in a Master configuration.\n0x90: OKIM6258 clock (32 bits)\n        Input clock rate in Hz for the OKIM6258 chip. A typical value is\n        4000000. It should be 0 if there is no OKIM6258 chip used.\n0x94: OKIM6258 Flags (8 bits)\n        Misc flags for the OKIM6258. Default is 0x00.\n        bit 0-1 Clock Divider (clock dividers are 1024, 768, 512, 512)\n        bit 2   3/4-bit ADPCM select (default is 4-bit, doesn't work currently)\n        bit 3   10/12-bit Output (default is 10-bit)\n        bit 4-7 reserved (must be zero)\n        If the OKIM6258 is not used then this may be omitted (left at zero).\n0x95: K054539 Flags (8 bits)\n        Misc flags for the K054539. Default is 0x01.\n        See also k054539.h in MAME source code.\n        bit 0   Reverse Stereo\n        bit 1   Disable Reverb\n        bit 2   Update at KeyOn\n        bit 3-7 reserved (must be zero)\n        If the K054539 is not used then this may be omitted (left at zero).\n0x96: C140 Chip Type (8 bits)\n        Defines the exact type of C140 and its banking method. The values are:\n        0x00 - C140, Namco System 2\n        0x01 - C140, Namco System 21\n        0x02 - 219 ASIC, Namco NA-1/2\n        If the C140 is not used then this may be omitted (left at zero).\n0x97: reserved\n        Reserved byte for future use. It must be 0.\n0x98: OKIM6295 clock (32 bits)\n        Input clock rate in Hz for the OKIM6295 chip. A typical value is\n        8000000. It should be 0 if there is no OKIM6295 chip used.\n        Set bit 31 (0x80000000) to denote the status of pin 7.\n0x9C: K051649/K052539 clock (32 bits)\n        Input clock rate in Hz for the K051649 chip. A typical value is\n        1789773. It should be 0 if there is no K051649 chip used.\n        If bit 31 is set it is a K052539.\n0xA0: K054539 clock (32 bits)\n        Input clock rate in Hz for the K054539 chip. A typical value is\n        18432000. It should be 0 if there is no K054539 chip used.\n0xA4: HuC6280 clock (32 bits)\n        Input clock rate in Hz for the HuC6280 chip. A typical value is\n        3579545. It should be 0 if there is no HuC6280 chip used.\n0xA8: C140 clock (32 bits)\n        Input clock rate in Hz for the C140 chip. A typical value is 8000000.\n        It should be 0 if there is no C140 chip used.\n0xAC: K053260 clock (32 bits)\n        Input clock rate in Hz for the K053260 chip. A typical value is \n        3579545. It should be 0 if there is no K053260 chip used.\n0xB0: Pokey clock (32 bits)\n        Input clock rate in Hz for the Pokey chip. A typical value is 1789772.\n        It should be 0 if there is no Pokey chip used.\n0xB4: QSound clock (32 bits)\n        Input clock rate in Hz for the QSound chip. A typical value is 4000000.\n        It should be 0 if there is no QSound chip used.\n[VGM 1.71 additions:]\n0xB8: SCSP clock (32 bits)\n        Input clock rate in Hz for the SCSP chip. A typical value is 22579200.\n        It should be 0 if there is no SCSP chip used.\n[VGM 1.70 additions:]\n0xBC: Extra Header Offset (32 bits)\n        Relative offset to the extra header or 0 if no extra header is present.\n[VGM 1.71 additions:]\n0xC0: WonderSwan clock (32 bits)\n        Input clock rate in Hz for the WonderSwan chip. A typical value is\n        3072000. It should be 0 if there is no WonderSwan chip used.\n0xC4: Virtual Boy VSU clock (32 bits)\n        Input clock rate in Hz for the VSU chip. A typical value is 5000000.\n        It should be 0 if there is no VSU chip used.\n0xC8: SAA1099 clock (32 bits)\n        Input clock rate in Hz for the SAA1099 chip. A typical value is\n        8000000. It should be 0 if there is no SAA1099 chip used.\n0xCC: ES5503 clock (32 bits)\n        Input clock rate in Hz for the ES5503 chip. A typical value is 7159090.\n        It should be 0 if there is no ES5503 chip used.\n0xD0: ES5505/ES5506 clock (32 bits)\n        Input clock rate in Hz for the ES5506 chip. A typical value is\n        16000000. It should be 0 if there is no ES5506 chip used.\n        Note: Bit 31 is used to set whether it is an ES5505 or an ES5506 chip.\n        If bit 31 is set it is an ES5506, if bit 31 is clear it is an ES5505.\n0xD4: ES5503 Channels (8 bits)\n        Defines the internal number of output channels for the ES5503.\n        Possible values are 1 to 8. A typical value is 2.\n        If the ES5503 is not used then this may be omitted (left at zero).\n0xD5: ES5505/6 Channels (8 bits)\n        Defines the internal number of output channels for the ES5506.\n        Possible values are 1 to 4 for the ES5505 and 1 to 8 for the ES5506.\n        A typical value is 1.\n        If the ES5506 is not used then this may be omitted (left at zero).\n0xD6: C352 Clock Divider (8 bits)\n        Defines the clock divider for the C352 chip, divided by 4 in order\n        to achieve a divider range of 0 to 1020. A typical value is 288.\n        If the C352 is not used then this may be omitted (left at zero).\n        Note: Bit 31 is used to disable the rear channels, which are often\n        not connected to speakers. Set to disable them, clear to enable.\n0xD7: reserved\n        Reserved byte for future use. It must be 0.\n0xD8: Seta X1-010 clock (32 bits)\n        Input clock rate in Hz for the X1-010 chip. A typical value is\n        16000000. It should be 0 if there is no X1-010 chip used.\n0xDC: Namco C352 clock (32 bits)\n        Input clock rate in Hz for the C352 chip. A typical value is 24192000.\n        It should be 0 if there is no C352 chip used.\n0xE0: Irem GA20 clock (32 bits)\n        Input clock rate in Hz for the GA20 chip. A typical value is 3579545.\n        It should be 0 if there is no GA20 chip used.\n0xE4: reserved\n        Reserved bytes for future use. They must be 0.\n\n\nStarting at the location specified by the VGM data offset (or, offset 0x40 for\nfile versions below 1.50) is found a sequence of commands containing data\nwritten to the chips or timing information. A command is one of:\n\n  0x00       : no-operation, no file should contain these, but players should just skip them\n  0x30 dd    : Used for dual chip support: see below\n  0x31 dd    : Set AY8910 stereo mask\n               Bit 0-1: Channel A mask (00=off, 01=left, 10=right, 11=center)\n               Bit 2-3: Channel B mask (00=off, 01=left, 10=right, 11=center)\n               Bit 4-5: Channel C mask (00=off, 01=left, 10=right, 11=center)\n               Bit 6: Chip type, 0=AY8910, 1=YM2203 SSG part\n               Bit 7: Chip number, 0 or 1\n  0x3F dd    : Used for dual chip support: see below\n  0x4F dd    : Game Gear PSG stereo, write dd to port 0x06\n  0x50 dd    : PSG (SN76489/SN76496) write value dd\n  0x51 aa dd : YM2413, write value dd to register aa\n  0x52 aa dd : YM2612 port 0, write value dd to register aa\n  0x53 aa dd : YM2612 port 1, write value dd to register aa\n  0x54 aa dd : YM2151, write value dd to register aa\n  0x55 aa dd : YM2203, write value dd to register aa\n  0x56 aa dd : YM2608 port 0, write value dd to register aa\n  0x57 aa dd : YM2608 port 1, write value dd to register aa\n  0x58 aa dd : YM2610 port 0, write value dd to register aa\n  0x59 aa dd : YM2610 port 1, write value dd to register aa\n  0x5A aa dd : YM3812, write value dd to register aa\n  0x5B aa dd : YM3526, write value dd to register aa\n  0x5C aa dd : Y8950, write value dd to register aa\n  0x5D aa dd : YMZ280B, write value dd to register aa\n  0x5E aa dd : YMF262 port 0, write value dd to register aa\n  0x5F aa dd : YMF262 port 1, write value dd to register aa\n  0x61 nn nn : Wait n samples, n can range from 0 to 65535 (approx 1.49\n               seconds). Longer pauses than this are represented by multiple\n               wait commands.\n  0x62       : wait 735 samples (60th of a second), a shortcut for\n               0x61 0xdf 0x02\n  0x63       : wait 882 samples (50th of a second), a shortcut for\n               0x61 0x72 0x03\n  0x66       : end of sound data\n  0x67 ...   : data block: see below\n  0x68 ...   : PCM RAM write: see below\n  0x7n       : wait n+1 samples, n can range from 0 to 15.\n  0x8n       : YM2612 port 0 address 2A write from the data bank, then wait \n               n samples; n can range from 0 to 15. Note that the wait is n,\n               NOT n+1. (Note: Written to first chip instance only.)\n  0x90-0x95  : DAC Stream Control Write: see below\n  0xA0 aa dd : AY8910, write value dd to register aa\n  0xA1-0xAF\n       aa dd : Used for dual chip support: see below\n  0xB0 aa dd : RF5C68, write value dd to register aa\n  0xB1 aa dd : RF5C164, write value dd to register aa\n  0xB2 ad dd : PWM, write value ddd to register a (d is MSB, dd is LSB)\n  0xB3 aa dd : GameBoy DMG, write value dd to register aa\n               Note: Register 00 equals GameBoy address FF10.\n  0xB4 aa dd : NES APU, write value dd to register aa\n               Note: Registers 00-1F equal NES address 4000-401F,\n                     registers 20-3E equal NES address 4080-409E,\n                     register 3F equals NES address 4023,\n                     registers 40-7F equal NES address 4040-407F.\n  0xB5 aa dd : MultiPCM, write value dd to register aa\n  0xB6 aa dd : uPD7759, write value dd to register aa\n  0xB7 aa dd : OKIM6258, write value dd to register aa\n  0xB8 aa dd : OKIM6295, write value dd to register aa\n  0xB9 aa dd : HuC6280, write value dd to register aa\n  0xBA aa dd : K053260, write value dd to register aa\n  0xBB aa dd : Pokey, write value dd to register aa\n  0xBC aa dd : WonderSwan, write value dd to register aa\n  0xBD aa dd : SAA1099, write value dd to register aa\n  0xBE aa dd : ES5506, write 8-bit value dd to register aa\n  0xBF aa dd : GA20, write value dd to register aa\n  0xC0 bbaa dd : Sega PCM, write value dd to memory offset aabb\n  0xC1 bbaa dd : RF5C68, write value dd to memory offset aabb\n  0xC2 bbaa dd : RF5C164, write value dd to memory offset aabb\n  0xC3 cc bbaa : MultiPCM, write set bank offset aabb to channel cc\n  0xC4 mmll rr : QSound, write value mmll to register rr\n                 (mm - data MSB, ll - data LSB)\n  0xC5 mmll dd : SCSP, write value dd to memory offset mmll\n                 (mm - offset MSB, ll - offset LSB)\n  0xC6 mmll dd : WonderSwan, write value dd to memory offset mmll\n                 (mm - offset MSB, ll - offset LSB)\n  0xC7 mmll dd : VSU, write value dd to register mmll\n                 (mm - MSB, ll - LSB)\n  0xC8 mmll dd : X1-010, write value dd to memory offset mmll\n                 (mm - offset MSB, ll - offset LSB)\n  0xD0 pp aa dd : YMF278B port pp, write value dd to register aa\n  0xD1 pp aa dd : YMF271 port pp, write value dd to register aa\n  0xD2 pp aa dd : SCC1 port pp, write value dd to register aa\n  0xD3 pp aa dd : K054539 write value dd to register ppaa\n  0xD4 pp aa dd : C140 write value dd to register ppaa\n  0xD5 pp aa dd : ES5503 write value dd to register ppaa\n  0xD6 aa ddee  : ES5506 write 16-bit value ddee to register aa\n  0xE0 dddddddd : seek to offset dddddddd (Intel byte order) in PCM data bank\n  0xE1 aabb ddee: C352 write 16-bit value ddee to register aabb\n\nSome ranges are reserved for future use, with different numbers of operands:\n\n  0x32..0x3E dd          : one operand, reserved for future use\n  0x40..0x4E dd dd       : two operands, reserved for future use\n                           Note: was one operand only til v1.60\n  0xC9..0xCF dd dd dd    : three operands, reserved for future use\n  0xD7..0xDF dd dd dd    : three operands, reserved for future use\n  0xE2..0xFF dd dd dd dd : four operands, reserved for future use\n\nOn encountering these, the correct number of bytes should be skipped.\n\nWhen encountering undefined commands, the processing the file should be stopped\ninstantly.\n\n\nData blocks\n-----------\nVGM command 0x67 specifies a data block. These are used to store large amounts\nof data, which can be used in parallel with the normal VGM data stream. The\ndata block format is:\n\n  0x67 0x66 tt ss ss ss ss (data)\n\nwhere:\n  0x67 = VGM command\n  0x66 = compatibility command to make older players stop parsing the stream\n  tt   = data type\n  ss ss ss ss (32 bits) = size of data, in bytes\n  (data) = data, of size previously specified\n\nData blocks of recorded streams, if present, should be at the very start of the\nVGM data. Multiple data blocks expand the data bank. (The start offset and\nlength of the block in the data bank should be saved for command 0x95.)\nBecause data blocks can happen anywhere in the stream, players must be able to\nparse data blocks anywhere in the stream. \n\nThe data block type specifies what type of data it contains. Currently defined\ntypes are:\n\n00..3F : data of recorded streams (uncompressed)\n40..7E : data of recorded streams (compressed)\n  data block format for compressed streams:\n    tt (8 bits) = compression type\n                    00 - n-Bit-Compression\n                    01 - DPCM-Compression\n    ss ss ss ss (32 bits) = size of uncompressed data (for memory allocation)\n                            It is assumed that each decompressed value uses\n                            ceil(bd/8) bytes.\n    (attr) = attribute bytes used by the decompression-algorithm\n    n-Bit-Compression:\n        bd (8 bits) = Bits decompressed\n        bc (8 bits) = Bits compressed\n        st (8 bits) = compression sub-type\n                        00 - copy (high bits aren't used)\n                        01 - shift left (low bits aren't used)\n                        02 - use table (data = index into decompression table,\n                                        see data block 7F)\n        aa aa (16 bits) = value that is added (ignored if table is used)\n        The data block is treated as a bitstream with bc bits per value. The\n        top bits in each byte are read first. The extracted bits of each value\n        are transformed into a value with at least bd bits using method st.\n        Finally, aaaa is added to get the resulting value.\n    DPCM-Compression: (uses a decompression table)\n        bd (8 bits) = Bits decompressed\n        bc (8 bits) = Bits compressed\n        st (8 bits) = [reserved for future use, must be 00]\n        aa aa (16 bits) = start value\n        The data is read as a bitstream (see n-Bit). The read value is used as\n        index into a delta-table (defined by data block 7F). The delta value\n        is added to the \"state\" value, which is also the result value.\n        The \"state\" value is initialized with aaaa at the beginning.\n    (data) = compressed data, of size (block size - 0x0A - attr size)\n7F     : Decompression Table\n    tt (8 bits) = compression type (see data block 40..7E)\n    st (8 bits) = compression sub-type (see data block 40..7E)\n    bd (8 bits) = Bits decompressed\n    bc (8 bits) = Bits compressed (only used for verifying against\n                  block 40..7E)\n    cc cc (16 bits) = number of following values (with each of size\n                      ceil(bd / 8))\n    (data) = table data, cccc values with a total size of (block size - 0x06)\n    Note: Multiple decompression tables are valid. The player should keep a\n          list of one table per tt and st combination. If there are multiple\n          tables of the same tt/st type, the new one overrides the old one and\n          all following compressed data blocks will use the new table.\n80..BF : ROM/RAM Image dumps (contain usually samples)\n  data block format for ROM dumps:\n    rr rr rr rr (32 bits) = size of the entire ROM\n    ss ss ss ss (32 bits) = start address of data\n    (data) = ROM data, of size (block size - 0x08)\n  The size of the VGM can be decreased a lot by saving only the used parts\n  of the ROM. This is done by saving multiple small ROM data blocks.\n  The start address is the ROM offset where the data will be written, the\n  ROM size is used to allocate space for the ROM (and some chips rely on it).\nC0..DF : RAM writes (for RAM with up to 64 KB)\n  data block format for direct RAM writes:\n    ss ss (16 bits) = start address of data (affected by a chip's banking\n                      registers)\n    (data) = RAM data, of size (block size - 0x02)\nE0..FF : RAM writes (for RAM with more than 64 KB)\n  data block format for direct RAM writes:\n    ss ss ss ss (32 bits) = start address of data (affected by a chip's banking\n                            registers)\n    (data) = RAM data, of size (block size - 0x04)\n\n00 = YM2612 PCM data for use with associated commands\n01 = RF5C68 PCM data for use with associated commands\n02 = RF5C164 PCM data for use with associated commands\n03 = PWM PCM data for use with associated commands\n04 = OKIM6258 ADPCM data for use with associated commands\n05 = HuC6280 PCM data for use with associated commands\n06 = SCSP PCM data for use with associated commands\n07 = NES APU DPCM data for use with associated commands\n40..7E = same as 00..3E, but compressed\n80 = Sega PCM ROM data\n81 = YM2608 DELTA-T ROM data\n82 = YM2610 ADPCM ROM data\n83 = YM2610 DELTA-T ROM data\n84 = YMF278B ROM data\n85 = YMF271 ROM data\n86 = YMZ280B ROM data\n87 = YMF278B RAM data\n88 = Y8950 DELTA-T ROM data\n89 = MultiPCM ROM data\n8A = uPD7759 ROM data\n8B = OKIM6295 ROM data\n8C = K054539 ROM data\n8D = C140 ROM data\n8E = K053260 ROM data\n8F = Q-Sound ROM data\n90 = ES5506 ROM data\n91 = X1-010 ROM data\n92 = C352 ROM data\n93 = GA20 ROM data\nC0 = RF5C68 RAM write\nC1 = RF5C164 RAM write\nC2 = NES APU RAM write\nE0 = SCSP RAM write\nE1 = ES5503 RAM write\n\nAll unknown types must be skipped by the player.\n\n\nPCM RAM writes\n--------------\nVGM command 0x68 specifies a PCM RAM write. These are used to write data from\ndata blocks to the RAM of a PCM chip. The data block format is:\n\n  0x68 0x66 cc oo oo oo dd dd dd ss ss ss\n\nwhere:\n  0x68 = VGM command\n  0x66 = compatibility command to make older players stop parsing the stream\n  cc   = chip type (see data block types 00..3F)\n  oo oo oo (24 bits) = read offset in data block\n  dd dd dd (24 bits) = write offset in chip's ram (affected by chip's\n                        registers)\n  ss ss ss (24 bits) = size of data, in bytes\n    Since size can't be zero, a size of 0 bytes means 0x0100 0000 bytes.\n\nAll unknown types must be skipped by the player.\n\n\nDAC Stream Control Write\n------------------------\nVGM commands 0x90 to 0x95 specify writes to the DAC Stream Control Driver.\nThese are used to stream data from data blocks to the chips via chip writes.\nTo use it you must:\n1. Setup the Stream (set chip type and command) - this activates the stream\n2. Set the Stream Data Bank\n3. Set the Stream Frequency\n4. Now you can start the stream, change its frequency, start it again, stop it,\n    etc ...\n\nThere are the following commands:\n\nNote: Stream ID 0xFF is reserved and ignored unless noted otherwise.\n\nSetup Stream Control:\n  0x90 ss tt pp cc\n      ss = Stream ID\n      tt = Chip Type (see clock-order in header, e.g. YM2612 = 0x02)\n            bit 7 is used to select the 2nd chip\n      pp cc = write command/register cc at port pp\n      Note: For chips that use Channel Select Registers (like the RF5C-family\n            and the HuC6280), the format is pp cd where pp is the channel\n            number, c is the channel register and d is the data register.\n            If you set pp to FF, the channel select write is skipped.\n\nSet Stream Data:\n  0x91 ss dd ll bb\n      ss = Stream ID\n      dd = Data Bank ID (see data block types 0x00..0x3f)\n      ll = Step Size (how many data is skipped after every write, usually 1)\n            Set to 2, if you're using an interleaved stream (e.g. for\n             left/right channel).\n      bb = Step Base (data offset added to the Start Offset when starting\n            stream playback, usually 0)\n            If you're using an interleaved stream, set it to 0 in one stream\n            and to 1 in the other one.\n      Note: Step Size/Step Step are given in command-data-size\n             (i.e. 1 for YM2612, 2 for PWM), not bytes\n\nSet Stream Frequency:\n  0x92 ss ff ff ff ff\n      ss = Stream ID\n      ff = Frequency (or Sample Rate, in Hz) at which the writes are done\n\nStart Stream:\n  0x93 ss aa aa aa aa mm ll ll ll ll\n      ss = Stream ID\n      aa = Data Start offset in data bank (byte offset in data bank)\n            Note: if set to -1, the Data Start offset is ignored\n      mm = Length Mode (how the Data Length is calculated)\n            00 - ignore (just change current data position)\n            01 - length = number of commands\n            02 - length in msec\n            03 - play until end of data\n            1? - (bit 4) Reverse Mode\n            8? - (bit 7) Loop (automatically restarts when finished)\n      ll = Data Length\n\nStop Stream:\n  0x94 ss\n      ss = Stream ID\n            Note: 0xFF stops all streams\n\nStart Stream (fast call):\n  0x95 ss bb bb ff\n      ss = Stream ID\n      bb = Block ID (number of the data block that is part of the data bank set\n            with command 0x91)\n      ff = Flags\n            bit 0 - Loop (see command 0x93, mm bit 7)\n            bit 4 - Reverse Mode (see command 0x93)\n\nGeneral Note to the DAC Stream Control:\nAlthough it may be quite hard to press already streamed data into these\ncommands, it makes it very easy to write vgm-creation tools that need to stream\nsomething. (like YM2612 DAC drums/voices/etc.)\nThe DAC Stream Control can use with almost all chips and is NOT limited to\nchips such as YM2612 and PWM.\n\n\nDual Chip Support\n-----------------\nThese chips support two instances of a chip in one vgm:\nPSG, YM2413, YM2612, YM2151, SegaPCM, YM2203, YM2608, YM2610, YM3812, YM3526,\nY8950, YMZ280B, YMF262, YMF278B, YMF271, AY8910, GameBoy DMG, NES APU,\nMultiPCM, uPD7759, OKIM6258, OKIM6295, K051649, K054539, HuC6280, C140,\nK053260, Pokey, SCSP, WonderSwan, VSU, SAA1099, ES5503, ES5506, X1-010, C352,\nGA20.\n\nDual chip support is activated by setting bit 30 (0x40000000) in the chip's\nclock value. (Note: The PSG needs this bit set for T6W28 mode.)\n\nNote: For the YM3812 only, setting bit 31 (0x80000000) in the chip's clock\nvalue hard-pans the first chip on the left and the second chip on the right.\nThis replicates the pan configuration of the Sound Blaster Pro 1 and Pro\nAudio Spectrum sound cards on the IBM PC.\n\n\nDual Chip Support #1:\nThe second chip instance is controlled via separate commands.\n\nThe second SN76489 PSG uses 0x30 (0x3F for GG Stereo).\nAll chips of the YM-family that use command 0x5n use 0xAn for the second chip.\nn is the last digit of the main command.\ne.g. 0x52 (1st chip) -> 0xA2 (2nd chip)\n\nDual Chip Support #2:\nAll other chips use bit 7 (0x80) of the first parameter byte to distinguish\nbetween the 1st and 2nd chip. (0x00-7F = Chip 1, 0x80-0xFF = chip 2)\n\nNote: The SegaPCM chip has the 2nd-chip-bit in the high byte of the address\nparameter. This is the second parameter byte.\n\nDual Chip Support #3:\nData block commands have bit 31 set for ROM/RAM dumps that go to the second\nchip.\n\n\nExtra Header\n------------\nWith VGM v1.70, there was an extra header added. This one has to be placed\nbetween the usual header and the actual VGM data.\n\nThis is the format of the extra header:\n\n      00  01  02  03   04  05  06  07   08  09  0A  0B  0C  0D  0E  0F\n0x00 [Header Size    ][ChpClock Offset][ChpVol Offset  ]\n\nHeader Size is the size of the extra header. It has to be 4 or larger,\ndepending in the needed offsets.\n\nThen there are two offsets that point to extra header data for:\n- additional Chip Clocks for second chips\n- user-defined chip volumes\n\n\nChip Clock Header\n-----------------\n1 byte   - Entry Count (chips with extra clocks)\n[5 bytes - List Entry 1]\n[5 bytes - List Entry 2]\n...\n\nEach list entry has the format:\n1 byte  - Chip ID (chip order follows the header)\n4 bytes - clock for second chip of the type above\n\n\nChip Volume Header\n------------------\n1 byte   - Entry Count (chips with user-defined volumes)\n[4 bytes - List Entry 1]\n[4 bytes - List Entry 2]\n...\n\nEach list entry has the format:\n1 byte  - Chip ID (chip order follows the header)\n          Note: If bit 7 is set, it's the volume for a paired chip.\n                (e.g. the AY-part of the YM2203)\n1 byte  - Flags\n          Note: If bit 0 is set, it's the volume for the second chip.\n2 bytes - volume for the chip\n          Note: If Bit 15 is 0, this is an absolute volume setting.\n                If Bit 15 is 1, it's relative and the chip volume gets\n                multiplied by ((Value & 0x7FFF) / 0x0100).\n\n\nHistory\n-------\n[1.00]\nInitial public release by Dave\n\n[1.01]\nRate value added by Maxim; 1.00 files are fully compatible\n\n[1.10]\nPSG white noise feedback and shift register width parameters added by Maxim,\nwith note on how to handle earlier version files.\nAdditional wait command added by Maxim with thanks to Steve Snake for the \nsuggestion.\n1.01 files are fully compatible but 1.01 players might have problems\nwith 1.10 files, hence the 0.1 version change.\n\n[1.50]\nVGM data offset added to header by Maxim.\nData block support added by blargg, to allow for better handling of YM2612 PCM\ndata.\nBoth of these changes have the potential to cause problems, but are really good\nchanges, so the version number has been increased all the way to 1.50.\n\n[1.51]\nSega PCM, RF5C68, YM2203, YM2608, YM2610/B, YM3812, YM3526, Y8950, YMF262,\nYMF278B, YMF271, YMZ280B, RF5C164, PWM and AY8910 chips and commands added.\n\nAdditional data block types RF5C68 RAM write, RF5C164 RAM write, Sega PCM ROM,\nYM2608 DELTA-T ROM, YM2610 ADPCM ROM, YM2610 DELTA-T ROM, YMF278B ROM,\nYMF271 ROM, YMF271 RAM, YMZ280B ROM and Y8950 DELTA-T ROM Data added.\n\nData Block Types splitted into 4 categories. (PCM Stream, compressed PCM\nStream, ROM/RAM Dump, RAM write)\n\nSN76489 Flags and Loop Modifier added.\n\nIt is the first time the header size exceeds 0x40 bytes.\n1.51 files are fully compatible to 1.50 players, but there may be problems with\nthe new commands.\n\nNote: Dual chip support was added too, but as a \"cheat\"-feature. The dual-chip\n-bits in the clock values are not compatible to 1.50, but the rest is.\n\nAll changes done by Valley Bell.\n\n[1.60]\nRF5C68, RF5C164 and PWM PCM blocks and compressed data blocks added.\n\nA whole bunch of new commands (PCM RAM write and DAC Stream Control) added.\n\nVolume Modifier and Loop Base added.\n\nThe new commands (especially 0x9?) may cause problems with older players.\n\nAll changes done by Valley Bell.\n\n[1.61]\nGameBoy DMG, NES APU, MultiPCM, uPD7759, OKIM6258, OKIM6295, K051649, K051649,\nHuC6280, C140, K053260, Pokey and Q-Sound chips added.\n(including necessary data blocks)\n\nChanged number of operands from 1 to 2 for reserved commands 0x40-0x4E.\nAlthough they're still unused, old players might handle future vgm versions\nwrongly.\n\nAll changes done by Valley Bell.\n\n[1.70]\nAdded extra header with seperate chip clocks for the second one of dual chips\nand chip volume adjustments.\n\nAll changes done by Valley Bell.\n\n[1.71]\nSCSP, WonderSwan, Virtual Boy VSU, SAA1099, ES5503, ES5506, Seta X1-010,\nNamco C352, Irem GA20 added. (including necessary ROM data blocks)\n[Valley Bell]\n\nData blocks (type 0x) for OKIM6258, HuC6280, SCSP and NES added.\nVGM v1.61 players should support the data block of their respective chips\ndespite their late addition. [Valley Bell]\n\nAdded bit 31 flags to change chip types for YM2612, YM2151 and K051649. These\nchanges should be considered backwards compatible with VGM 1.51. [grauw, ctr]\n\nAdded command 0x31 to set AY8910 stereo mask. [NewRisingSun]\n\nDocumented some chip flags that have been present since earlier versions of\nVGMPlay. [NewRisingSun]\n\nAdded \"XNOR noise feedback\" bit to SN76489 flags. The new flag should be\nsupported by VGM v1.51 players where possible. [Valley Bell]\n"
  },
  {
    "path": "VGMPlay/xdg/vgmplay-mime.xml",
    "content": "<?xml version=\"1.0\"?>\n<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>\n    <mime-type type=\"audio/x-vgm\">\n        <comment>VGM Audio File</comment>\n        <glob pattern=\"*.vgm\"/>\n    </mime-type>\n    <mime-type type=\"audio/x-vgz\">\n        <comment>Compressed VGM Audio File</comment>\n        <glob pattern=\"*.vgz\"/>\n    </mime-type>\n</mime-info>\n"
  },
  {
    "path": "VGMPlay/xdg/vgmplay.desktop.in",
    "content": "[Desktop Entry]\nName=VGMPlay\nGenericName=VGMPlay\nComment=VGM File Player\nExec=@BIN_PATH@vgmplay %f\nTerminal=true\nIcon=vgmplay\nType=Application\nStartupNotify=false\nVersion=1.0\nCategories=AudioVideo;\nMimeType=audio/x-vgm;audio/x-vgz;application/mpegurl;application/x-mpegurl;audio/mpegurl;audio/x-mpegurl;\nKeywords=Audio;Music;VGM;Player;Video Game Music;Sound Chip; OKI; SN; YM; OPL; PCM; AY;\n"
  },
  {
    "path": "VGMPlay/zlib/zconf.h",
    "content": "/* zconf.h -- configuration of the zlib compression library\n * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* @(#) $Id$ */\n\n#ifndef ZCONF_H\n#define ZCONF_H\n\n/*\n * If you *really* need a unique prefix for all types and library functions,\n * compile with -DZ_PREFIX. The \"standard\" zlib should be compiled without it.\n * Even better than compiling with -DZ_PREFIX would be to use configure to set\n * this permanently in zconf.h using \"./configure --zprefix\".\n */\n#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */\n#  define Z_PREFIX_SET\n\n/* all linked symbols and init macros */\n#  define _dist_code            z__dist_code\n#  define _length_code          z__length_code\n#  define _tr_align             z__tr_align\n#  define _tr_flush_bits        z__tr_flush_bits\n#  define _tr_flush_block       z__tr_flush_block\n#  define _tr_init              z__tr_init\n#  define _tr_stored_block      z__tr_stored_block\n#  define _tr_tally             z__tr_tally\n#  define adler32               z_adler32\n#  define adler32_combine       z_adler32_combine\n#  define adler32_combine64     z_adler32_combine64\n#  define adler32_z             z_adler32_z\n#  ifndef Z_SOLO\n#    define compress              z_compress\n#    define compress2             z_compress2\n#    define compressBound         z_compressBound\n#  endif\n#  define crc32                 z_crc32\n#  define crc32_combine         z_crc32_combine\n#  define crc32_combine64       z_crc32_combine64\n#  define crc32_z               z_crc32_z\n#  define deflate               z_deflate\n#  define deflateBound          z_deflateBound\n#  define deflateCopy           z_deflateCopy\n#  define deflateEnd            z_deflateEnd\n#  define deflateGetDictionary  z_deflateGetDictionary\n#  define deflateInit           z_deflateInit\n#  define deflateInit2          z_deflateInit2\n#  define deflateInit2_         z_deflateInit2_\n#  define deflateInit_          z_deflateInit_\n#  define deflateParams         z_deflateParams\n#  define deflatePending        z_deflatePending\n#  define deflatePrime          z_deflatePrime\n#  define deflateReset          z_deflateReset\n#  define deflateResetKeep      z_deflateResetKeep\n#  define deflateSetDictionary  z_deflateSetDictionary\n#  define deflateSetHeader      z_deflateSetHeader\n#  define deflateTune           z_deflateTune\n#  define deflate_copyright     z_deflate_copyright\n#  define get_crc_table         z_get_crc_table\n#  ifndef Z_SOLO\n#    define gz_error              z_gz_error\n#    define gz_intmax             z_gz_intmax\n#    define gz_strwinerror        z_gz_strwinerror\n#    define gzbuffer              z_gzbuffer\n#    define gzclearerr            z_gzclearerr\n#    define gzclose               z_gzclose\n#    define gzclose_r             z_gzclose_r\n#    define gzclose_w             z_gzclose_w\n#    define gzdirect              z_gzdirect\n#    define gzdopen               z_gzdopen\n#    define gzeof                 z_gzeof\n#    define gzerror               z_gzerror\n#    define gzflush               z_gzflush\n#    define gzfread               z_gzfread\n#    define gzfwrite              z_gzfwrite\n#    define gzgetc                z_gzgetc\n#    define gzgetc_               z_gzgetc_\n#    define gzgets                z_gzgets\n#    define gzoffset              z_gzoffset\n#    define gzoffset64            z_gzoffset64\n#    define gzopen                z_gzopen\n#    define gzopen64              z_gzopen64\n#    ifdef _WIN32\n#      define gzopen_w              z_gzopen_w\n#    endif\n#    define gzprintf              z_gzprintf\n#    define gzputc                z_gzputc\n#    define gzputs                z_gzputs\n#    define gzread                z_gzread\n#    define gzrewind              z_gzrewind\n#    define gzseek                z_gzseek\n#    define gzseek64              z_gzseek64\n#    define gzsetparams           z_gzsetparams\n#    define gztell                z_gztell\n#    define gztell64              z_gztell64\n#    define gzungetc              z_gzungetc\n#    define gzvprintf             z_gzvprintf\n#    define gzwrite               z_gzwrite\n#  endif\n#  define inflate               z_inflate\n#  define inflateBack           z_inflateBack\n#  define inflateBackEnd        z_inflateBackEnd\n#  define inflateBackInit       z_inflateBackInit\n#  define inflateBackInit_      z_inflateBackInit_\n#  define inflateCodesUsed      z_inflateCodesUsed\n#  define inflateCopy           z_inflateCopy\n#  define inflateEnd            z_inflateEnd\n#  define inflateGetDictionary  z_inflateGetDictionary\n#  define inflateGetHeader      z_inflateGetHeader\n#  define inflateInit           z_inflateInit\n#  define inflateInit2          z_inflateInit2\n#  define inflateInit2_         z_inflateInit2_\n#  define inflateInit_          z_inflateInit_\n#  define inflateMark           z_inflateMark\n#  define inflatePrime          z_inflatePrime\n#  define inflateReset          z_inflateReset\n#  define inflateReset2         z_inflateReset2\n#  define inflateResetKeep      z_inflateResetKeep\n#  define inflateSetDictionary  z_inflateSetDictionary\n#  define inflateSync           z_inflateSync\n#  define inflateSyncPoint      z_inflateSyncPoint\n#  define inflateUndermine      z_inflateUndermine\n#  define inflateValidate       z_inflateValidate\n#  define inflate_copyright     z_inflate_copyright\n#  define inflate_fast          z_inflate_fast\n#  define inflate_table         z_inflate_table\n#  ifndef Z_SOLO\n#    define uncompress            z_uncompress\n#    define uncompress2           z_uncompress2\n#  endif\n#  define zError                z_zError\n#  ifndef Z_SOLO\n#    define zcalloc               z_zcalloc\n#    define zcfree                z_zcfree\n#  endif\n#  define zlibCompileFlags      z_zlibCompileFlags\n#  define zlibVersion           z_zlibVersion\n\n/* all zlib typedefs in zlib.h and zconf.h */\n#  define Byte                  z_Byte\n#  define Bytef                 z_Bytef\n#  define alloc_func            z_alloc_func\n#  define charf                 z_charf\n#  define free_func             z_free_func\n#  ifndef Z_SOLO\n#    define gzFile                z_gzFile\n#  endif\n#  define gz_header             z_gz_header\n#  define gz_headerp            z_gz_headerp\n#  define in_func               z_in_func\n#  define intf                  z_intf\n#  define out_func              z_out_func\n#  define uInt                  z_uInt\n#  define uIntf                 z_uIntf\n#  define uLong                 z_uLong\n#  define uLongf                z_uLongf\n#  define voidp                 z_voidp\n#  define voidpc                z_voidpc\n#  define voidpf                z_voidpf\n\n/* all zlib structs in zlib.h and zconf.h */\n#  define gz_header_s           z_gz_header_s\n#  define internal_state        z_internal_state\n\n#endif\n\n#if defined(__MSDOS__) && !defined(MSDOS)\n#  define MSDOS\n#endif\n#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)\n#  define OS2\n#endif\n#if defined(_WINDOWS) && !defined(WINDOWS)\n#  define WINDOWS\n#endif\n#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)\n#  ifndef WIN32\n#    define WIN32\n#  endif\n#endif\n#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)\n#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)\n#    ifndef SYS16BIT\n#      define SYS16BIT\n#    endif\n#  endif\n#endif\n\n/*\n * Compile with -DMAXSEG_64K if the alloc function cannot allocate more\n * than 64k bytes at a time (needed on systems with 16-bit int).\n */\n#ifdef SYS16BIT\n#  define MAXSEG_64K\n#endif\n#ifdef MSDOS\n#  define UNALIGNED_OK\n#endif\n\n#ifdef __STDC_VERSION__\n#  ifndef STDC\n#    define STDC\n#  endif\n#  if __STDC_VERSION__ >= 199901L\n#    ifndef STDC99\n#      define STDC99\n#    endif\n#  endif\n#endif\n#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))\n#  define STDC\n#endif\n#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))\n#  define STDC\n#endif\n#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))\n#  define STDC\n#endif\n#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))\n#  define STDC\n#endif\n\n#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */\n#  define STDC\n#endif\n\n#ifndef STDC\n#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */\n#    define const       /* note: need a more gentle solution here */\n#  endif\n#endif\n\n#if defined(ZLIB_CONST) && !defined(z_const)\n#  define z_const const\n#else\n#  define z_const\n#endif\n\n#ifdef Z_SOLO\n   typedef unsigned long z_size_t;\n#else\n#  define z_longlong long long\n#  if defined(NO_SIZE_T)\n     typedef unsigned NO_SIZE_T z_size_t;\n#  elif defined(STDC)\n#    include <stddef.h>\n     typedef size_t z_size_t;\n#  else\n     typedef unsigned long z_size_t;\n#  endif\n#  undef z_longlong\n#endif\n\n/* Maximum value for memLevel in deflateInit2 */\n#ifndef MAX_MEM_LEVEL\n#  ifdef MAXSEG_64K\n#    define MAX_MEM_LEVEL 8\n#  else\n#    define MAX_MEM_LEVEL 9\n#  endif\n#endif\n\n/* Maximum value for windowBits in deflateInit2 and inflateInit2.\n * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files\n * created by gzip. (Files created by minigzip can still be extracted by\n * gzip.)\n */\n#ifndef MAX_WBITS\n#  define MAX_WBITS   15 /* 32K LZ77 window */\n#endif\n\n/* The memory requirements for deflate are (in bytes):\n            (1 << (windowBits+2)) +  (1 << (memLevel+9))\n that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)\n plus a few kilobytes for small objects. For example, if you want to reduce\n the default memory requirements from 256K to 128K, compile with\n     make CFLAGS=\"-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7\"\n Of course this will generally degrade compression (there's no free lunch).\n\n   The memory requirements for inflate are (in bytes) 1 << windowBits\n that is, 32K for windowBits=15 (default value) plus about 7 kilobytes\n for small objects.\n*/\n\n                        /* Type declarations */\n\n#ifndef OF /* function prototypes */\n#  ifdef STDC\n#    define OF(args)  args\n#  else\n#    define OF(args)  ()\n#  endif\n#endif\n\n#ifndef Z_ARG /* function prototypes for stdarg */\n#  if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#    define Z_ARG(args)  args\n#  else\n#    define Z_ARG(args)  ()\n#  endif\n#endif\n\n/* The following definitions for FAR are needed only for MSDOS mixed\n * model programming (small or medium model with some far allocations).\n * This was tested only with MSC; for other MSDOS compilers you may have\n * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,\n * just define FAR to be empty.\n */\n#ifdef SYS16BIT\n#  if defined(M_I86SM) || defined(M_I86MM)\n     /* MSC small or medium model */\n#    define SMALL_MEDIUM\n#    ifdef _MSC_VER\n#      define FAR _far\n#    else\n#      define FAR far\n#    endif\n#  endif\n#  if (defined(__SMALL__) || defined(__MEDIUM__))\n     /* Turbo C small or medium model */\n#    define SMALL_MEDIUM\n#    ifdef __BORLANDC__\n#      define FAR _far\n#    else\n#      define FAR far\n#    endif\n#  endif\n#endif\n\n#if defined(WINDOWS) || defined(WIN32)\n   /* If building or using zlib as a DLL, define ZLIB_DLL.\n    * This is not mandatory, but it offers a little performance increase.\n    */\n#  ifdef ZLIB_DLL\n#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))\n#      ifdef ZLIB_INTERNAL\n#        define ZEXTERN extern __declspec(dllexport)\n#      else\n#        define ZEXTERN extern __declspec(dllimport)\n#      endif\n#    endif\n#  endif  /* ZLIB_DLL */\n   /* If building or using zlib with the WINAPI/WINAPIV calling convention,\n    * define ZLIB_WINAPI.\n    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.\n    */\n#  ifdef ZLIB_WINAPI\n#    ifdef FAR\n#      undef FAR\n#    endif\n#    include <windows.h>\n     /* No need for _export, use ZLIB.DEF instead. */\n     /* For complete Windows compatibility, use WINAPI, not __stdcall. */\n#    define ZEXPORT WINAPI\n#    ifdef WIN32\n#      define ZEXPORTVA WINAPIV\n#    else\n#      define ZEXPORTVA FAR CDECL\n#    endif\n#  endif\n#endif\n\n#if defined (__BEOS__)\n#  ifdef ZLIB_DLL\n#    ifdef ZLIB_INTERNAL\n#      define ZEXPORT   __declspec(dllexport)\n#      define ZEXPORTVA __declspec(dllexport)\n#    else\n#      define ZEXPORT   __declspec(dllimport)\n#      define ZEXPORTVA __declspec(dllimport)\n#    endif\n#  endif\n#endif\n\n#ifndef ZEXTERN\n#  define ZEXTERN extern\n#endif\n#ifndef ZEXPORT\n#  define ZEXPORT\n#endif\n#ifndef ZEXPORTVA\n#  define ZEXPORTVA\n#endif\n\n#ifndef FAR\n#  define FAR\n#endif\n\n#if !defined(__MACTYPES__)\ntypedef unsigned char  Byte;  /* 8 bits */\n#endif\ntypedef unsigned int   uInt;  /* 16 bits or more */\ntypedef unsigned long  uLong; /* 32 bits or more */\n\n#ifdef SMALL_MEDIUM\n   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */\n#  define Bytef Byte FAR\n#else\n   typedef Byte  FAR Bytef;\n#endif\ntypedef char  FAR charf;\ntypedef int   FAR intf;\ntypedef uInt  FAR uIntf;\ntypedef uLong FAR uLongf;\n\n#ifdef STDC\n   typedef void const *voidpc;\n   typedef void FAR   *voidpf;\n   typedef void       *voidp;\n#else\n   typedef Byte const *voidpc;\n   typedef Byte FAR   *voidpf;\n   typedef Byte       *voidp;\n#endif\n\n#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)\n#  include <limits.h>\n#  if (UINT_MAX == 0xffffffffUL)\n#    define Z_U4 unsigned\n#  elif (ULONG_MAX == 0xffffffffUL)\n#    define Z_U4 unsigned long\n#  elif (USHRT_MAX == 0xffffffffUL)\n#    define Z_U4 unsigned short\n#  endif\n#endif\n\n#ifdef Z_U4\n   typedef Z_U4 z_crc_t;\n#else\n   typedef unsigned long z_crc_t;\n#endif\n\n#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */\n#  define Z_HAVE_UNISTD_H\n#endif\n\n#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */\n#  define Z_HAVE_STDARG_H\n#endif\n\n#ifdef STDC\n#  ifndef Z_SOLO\n#    include <sys/types.h>      /* for off_t */\n#  endif\n#endif\n\n#if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#  ifndef Z_SOLO\n#    include <stdarg.h>         /* for va_list */\n#  endif\n#endif\n\n#ifdef _WIN32\n#  ifndef Z_SOLO\n#    include <stddef.h>         /* for wchar_t */\n#  endif\n#endif\n\n/* a little trick to accommodate both \"#define _LARGEFILE64_SOURCE\" and\n * \"#define _LARGEFILE64_SOURCE 1\" as requesting 64-bit operations, (even\n * though the former does not conform to the LFS document), but considering\n * both \"#undef _LARGEFILE64_SOURCE\" and \"#define _LARGEFILE64_SOURCE 0\" as\n * equivalently requesting no 64-bit operations\n */\n#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1\n#  undef _LARGEFILE64_SOURCE\n#endif\n\n#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)\n#  define Z_HAVE_UNISTD_H\n#endif\n#ifndef Z_SOLO\n#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)\n#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */\n#    ifdef VMS\n#      include <unixio.h>       /* for off_t */\n#    endif\n#    ifndef z_off_t\n#      define z_off_t off_t\n#    endif\n#  endif\n#endif\n\n#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0\n#  define Z_LFS64\n#endif\n\n#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)\n#  define Z_LARGE64\n#endif\n\n#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)\n#  define Z_WANT64\n#endif\n\n#if !defined(SEEK_SET) && !defined(Z_SOLO)\n#  define SEEK_SET        0       /* Seek from beginning of file.  */\n#  define SEEK_CUR        1       /* Seek from current position.  */\n#  define SEEK_END        2       /* Set file pointer to EOF plus \"offset\" */\n#endif\n\n#ifndef z_off_t\n#  define z_off_t long\n#endif\n\n#if !defined(_WIN32) && defined(Z_LARGE64)\n#  define z_off64_t off64_t\n#else\n#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)\n#    define z_off64_t __int64\n#  else\n#    define z_off64_t z_off_t\n#  endif\n#endif\n\n/* MVS linker does not support external names larger than 8 bytes */\n#if defined(__MVS__)\n  #pragma map(deflateInit_,\"DEIN\")\n  #pragma map(deflateInit2_,\"DEIN2\")\n  #pragma map(deflateEnd,\"DEEND\")\n  #pragma map(deflateBound,\"DEBND\")\n  #pragma map(inflateInit_,\"ININ\")\n  #pragma map(inflateInit2_,\"ININ2\")\n  #pragma map(inflateEnd,\"INEND\")\n  #pragma map(inflateSync,\"INSY\")\n  #pragma map(inflateSetDictionary,\"INSEDI\")\n  #pragma map(compressBound,\"CMBND\")\n  #pragma map(inflate_table,\"INTABL\")\n  #pragma map(inflate_fast,\"INFA\")\n  #pragma map(inflate_copyright,\"INCOPY\")\n#endif\n\n#endif /* ZCONF_H */\n"
  },
  {
    "path": "VGMPlay/zlib/zlib.def",
    "content": "; zlib data compression library\nEXPORTS\n; basic functions\n    zlibVersion\n    deflate\n    deflateEnd\n    inflate\n    inflateEnd\n; advanced functions\n    deflateSetDictionary\n    deflateGetDictionary\n    deflateCopy\n    deflateReset\n    deflateParams\n    deflateTune\n    deflateBound\n    deflatePending\n    deflatePrime\n    deflateSetHeader\n    inflateSetDictionary\n    inflateGetDictionary\n    inflateSync\n    inflateCopy\n    inflateReset\n    inflateReset2\n    inflatePrime\n    inflateMark\n    inflateGetHeader\n    inflateBack\n    inflateBackEnd\n    zlibCompileFlags\n; utility functions\n    compress\n    compress2\n    compressBound\n    uncompress\n    uncompress2\n    gzopen\n    gzdopen\n    gzbuffer\n    gzsetparams\n    gzread\n    gzfread\n    gzwrite\n    gzfwrite\n    gzprintf\n    gzvprintf\n    gzputs\n    gzgets\n    gzputc\n    gzgetc\n    gzungetc\n    gzflush\n    gzseek\n    gzrewind\n    gztell\n    gzoffset\n    gzeof\n    gzdirect\n    gzclose\n    gzclose_r\n    gzclose_w\n    gzerror\n    gzclearerr\n; large file functions\n    gzopen64\n    gzseek64\n    gztell64\n    gzoffset64\n    adler32_combine64\n    crc32_combine64\n; checksum functions\n    adler32\n    adler32_z\n    crc32\n    crc32_z\n    adler32_combine\n    crc32_combine\n; various hacks, don't look :)\n    deflateInit_\n    deflateInit2_\n    inflateInit_\n    inflateInit2_\n    inflateBackInit_\n    gzgetc_\n    zError\n    inflateSyncPoint\n    get_crc_table\n    inflateUndermine\n    inflateValidate\n    inflateCodesUsed\n    inflateResetKeep\n    deflateResetKeep\n    gzopen_w\n"
  },
  {
    "path": "VGMPlay/zlib/zlib.h",
    "content": "/* zlib.h -- interface of the 'zlib' general purpose compression library\n  version 1.2.11, January 15th, 2017\n\n  Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the authors be held liable for any damages\n  arising from the use of this software.\n\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n\n  Jean-loup Gailly        Mark Adler\n  jloup@gzip.org          madler@alumni.caltech.edu\n\n\n  The data format used by the zlib library is described by RFCs (Request for\n  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950\n  (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).\n*/\n\n#ifndef ZLIB_H\n#define ZLIB_H\n\n#include \"zconf.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ZLIB_VERSION \"1.2.11\"\n#define ZLIB_VERNUM 0x12b0\n#define ZLIB_VER_MAJOR 1\n#define ZLIB_VER_MINOR 2\n#define ZLIB_VER_REVISION 11\n#define ZLIB_VER_SUBREVISION 0\n\n/*\n    The 'zlib' compression library provides in-memory compression and\n  decompression functions, including integrity checks of the uncompressed data.\n  This version of the library supports only one compression method (deflation)\n  but other algorithms will be added later and will have the same stream\n  interface.\n\n    Compression can be done in a single step if the buffers are large enough,\n  or can be done by repeated calls of the compression function.  In the latter\n  case, the application must provide more input and/or consume the output\n  (providing more output space) before each call.\n\n    The compressed data format used by default by the in-memory functions is\n  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped\n  around a deflate stream, which is itself documented in RFC 1951.\n\n    The library also supports reading and writing files in gzip (.gz) format\n  with an interface similar to that of stdio using the functions that start\n  with \"gz\".  The gzip format is different from the zlib format.  gzip is a\n  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.\n\n    This library can optionally read and write gzip and raw deflate streams in\n  memory as well.\n\n    The zlib format was designed to be compact and fast for use in memory\n  and on communications channels.  The gzip format was designed for single-\n  file compression on file systems, has a larger header than zlib to maintain\n  directory information, and uses a different, slower check method than zlib.\n\n    The library does not install any signal handler.  The decoder checks\n  the consistency of the compressed data, so the library should never crash\n  even in the case of corrupted input.\n*/\n\ntypedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));\ntypedef void   (*free_func)  OF((voidpf opaque, voidpf address));\n\nstruct internal_state;\n\ntypedef struct z_stream_s {\n    z_const Bytef *next_in;     /* next input byte */\n    uInt     avail_in;  /* number of bytes available at next_in */\n    uLong    total_in;  /* total number of input bytes read so far */\n\n    Bytef    *next_out; /* next output byte will go here */\n    uInt     avail_out; /* remaining free space at next_out */\n    uLong    total_out; /* total number of bytes output so far */\n\n    z_const char *msg;  /* last error message, NULL if no error */\n    struct internal_state FAR *state; /* not visible by applications */\n\n    alloc_func zalloc;  /* used to allocate the internal state */\n    free_func  zfree;   /* used to free the internal state */\n    voidpf     opaque;  /* private data object passed to zalloc and zfree */\n\n    int     data_type;  /* best guess about the data type: binary or text\n                           for deflate, or the decoding state for inflate */\n    uLong   adler;      /* Adler-32 or CRC-32 value of the uncompressed data */\n    uLong   reserved;   /* reserved for future use */\n} z_stream;\n\ntypedef z_stream FAR *z_streamp;\n\n/*\n     gzip header information passed to and from zlib routines.  See RFC 1952\n  for more details on the meanings of these fields.\n*/\ntypedef struct gz_header_s {\n    int     text;       /* true if compressed data believed to be text */\n    uLong   time;       /* modification time */\n    int     xflags;     /* extra flags (not used when writing a gzip file) */\n    int     os;         /* operating system */\n    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */\n    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */\n    uInt    extra_max;  /* space at extra (only when reading header) */\n    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */\n    uInt    name_max;   /* space at name (only when reading header) */\n    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */\n    uInt    comm_max;   /* space at comment (only when reading header) */\n    int     hcrc;       /* true if there was or will be a header crc */\n    int     done;       /* true when done reading gzip header (not used\n                           when writing a gzip file) */\n} gz_header;\n\ntypedef gz_header FAR *gz_headerp;\n\n/*\n     The application must update next_in and avail_in when avail_in has dropped\n   to zero.  It must update next_out and avail_out when avail_out has dropped\n   to zero.  The application must initialize zalloc, zfree and opaque before\n   calling the init function.  All other fields are set by the compression\n   library and must not be updated by the application.\n\n     The opaque value provided by the application will be passed as the first\n   parameter for calls of zalloc and zfree.  This can be useful for custom\n   memory management.  The compression library attaches no meaning to the\n   opaque value.\n\n     zalloc must return Z_NULL if there is not enough memory for the object.\n   If zlib is used in a multi-threaded application, zalloc and zfree must be\n   thread safe.  In that case, zlib is thread-safe.  When zalloc and zfree are\n   Z_NULL on entry to the initialization function, they are set to internal\n   routines that use the standard library functions malloc() and free().\n\n     On 16-bit systems, the functions zalloc and zfree must be able to allocate\n   exactly 65536 bytes, but will not be required to allocate more than this if\n   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers\n   returned by zalloc for objects of exactly 65536 bytes *must* have their\n   offset normalized to zero.  The default allocation function provided by this\n   library ensures this (see zutil.c).  To reduce memory requirements and avoid\n   any allocation of 64K objects, at the expense of compression ratio, compile\n   the library with -DMAX_WBITS=14 (see zconf.h).\n\n     The fields total_in and total_out can be used for statistics or progress\n   reports.  After compression, total_in holds the total size of the\n   uncompressed data and may be saved for use by the decompressor (particularly\n   if the decompressor wants to decompress everything in a single step).\n*/\n\n                        /* constants */\n\n#define Z_NO_FLUSH      0\n#define Z_PARTIAL_FLUSH 1\n#define Z_SYNC_FLUSH    2\n#define Z_FULL_FLUSH    3\n#define Z_FINISH        4\n#define Z_BLOCK         5\n#define Z_TREES         6\n/* Allowed flush values; see deflate() and inflate() below for details */\n\n#define Z_OK            0\n#define Z_STREAM_END    1\n#define Z_NEED_DICT     2\n#define Z_ERRNO        (-1)\n#define Z_STREAM_ERROR (-2)\n#define Z_DATA_ERROR   (-3)\n#define Z_MEM_ERROR    (-4)\n#define Z_BUF_ERROR    (-5)\n#define Z_VERSION_ERROR (-6)\n/* Return codes for the compression/decompression functions. Negative values\n * are errors, positive values are used for special but normal events.\n */\n\n#define Z_NO_COMPRESSION         0\n#define Z_BEST_SPEED             1\n#define Z_BEST_COMPRESSION       9\n#define Z_DEFAULT_COMPRESSION  (-1)\n/* compression levels */\n\n#define Z_FILTERED            1\n#define Z_HUFFMAN_ONLY        2\n#define Z_RLE                 3\n#define Z_FIXED               4\n#define Z_DEFAULT_STRATEGY    0\n/* compression strategy; see deflateInit2() below for details */\n\n#define Z_BINARY   0\n#define Z_TEXT     1\n#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */\n#define Z_UNKNOWN  2\n/* Possible values of the data_type field for deflate() */\n\n#define Z_DEFLATED   8\n/* The deflate compression method (the only one supported in this version) */\n\n#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */\n\n#define zlib_version zlibVersion()\n/* for compatibility with versions < 1.0.2 */\n\n\n                        /* basic functions */\n\nZEXTERN const char * ZEXPORT zlibVersion OF((void));\n/* The application can compare zlibVersion and ZLIB_VERSION for consistency.\n   If the first character differs, the library code actually used is not\n   compatible with the zlib.h header file used by the application.  This check\n   is automatically made by deflateInit and inflateInit.\n */\n\n/*\nZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));\n\n     Initializes the internal stream state for compression.  The fields\n   zalloc, zfree and opaque must be initialized before by the caller.  If\n   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default\n   allocation functions.\n\n     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:\n   1 gives best speed, 9 gives best compression, 0 gives no compression at all\n   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION\n   requests a default compromise between speed and compression (currently\n   equivalent to level 6).\n\n     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_STREAM_ERROR if level is not a valid compression level, or\n   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible\n   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null\n   if there is no error message.  deflateInit does not perform any compression:\n   this will be done by deflate().\n*/\n\n\nZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));\n/*\n    deflate compresses as much data as possible, and stops when the input\n  buffer becomes empty or the output buffer becomes full.  It may introduce\n  some output latency (reading input without producing any output) except when\n  forced to flush.\n\n    The detailed semantics are as follows.  deflate performs one or both of the\n  following actions:\n\n  - Compress more input starting at next_in and update next_in and avail_in\n    accordingly.  If not all input can be processed (because there is not\n    enough room in the output buffer), next_in and avail_in are updated and\n    processing will resume at this point for the next call of deflate().\n\n  - Generate more output starting at next_out and update next_out and avail_out\n    accordingly.  This action is forced if the parameter flush is non zero.\n    Forcing flush frequently degrades the compression ratio, so this parameter\n    should be set only when necessary.  Some output may be provided even if\n    flush is zero.\n\n    Before the call of deflate(), the application should ensure that at least\n  one of the actions is possible, by providing more input and/or consuming more\n  output, and updating avail_in or avail_out accordingly; avail_out should\n  never be zero before the call.  The application can consume the compressed\n  output when it wants, for example when the output buffer is full (avail_out\n  == 0), or after each call of deflate().  If deflate returns Z_OK and with\n  zero avail_out, it must be called again after making room in the output\n  buffer because there might be more output pending. See deflatePending(),\n  which can be used if desired to determine whether or not there is more ouput\n  in that case.\n\n    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to\n  decide how much data to accumulate before producing output, in order to\n  maximize compression.\n\n    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is\n  flushed to the output buffer and the output is aligned on a byte boundary, so\n  that the decompressor can get all input data available so far.  (In\n  particular avail_in is zero after the call if enough output space has been\n  provided before the call.) Flushing may degrade compression for some\n  compression algorithms and so it should be used only when necessary.  This\n  completes the current deflate block and follows it with an empty stored block\n  that is three bits plus filler bits to the next byte, followed by four bytes\n  (00 00 ff ff).\n\n    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the\n  output buffer, but the output is not aligned to a byte boundary.  All of the\n  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.\n  This completes the current deflate block and follows it with an empty fixed\n  codes block that is 10 bits long.  This assures that enough bytes are output\n  in order for the decompressor to finish the block before the empty fixed\n  codes block.\n\n    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as\n  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to\n  seven bits of the current block are held to be written as the next byte after\n  the next deflate block is completed.  In this case, the decompressor may not\n  be provided enough bits at this point in order to complete decompression of\n  the data provided so far to the compressor.  It may need to wait for the next\n  block to be emitted.  This is for advanced applications that need to control\n  the emission of deflate blocks.\n\n    If flush is set to Z_FULL_FLUSH, all output is flushed as with\n  Z_SYNC_FLUSH, and the compression state is reset so that decompression can\n  restart from this point if previous compressed data has been damaged or if\n  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade\n  compression.\n\n    If deflate returns with avail_out == 0, this function must be called again\n  with the same value of the flush parameter and more output space (updated\n  avail_out), until the flush is complete (deflate returns with non-zero\n  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that\n  avail_out is greater than six to avoid repeated flush markers due to\n  avail_out == 0 on return.\n\n    If the parameter flush is set to Z_FINISH, pending input is processed,\n  pending output is flushed and deflate returns with Z_STREAM_END if there was\n  enough output space.  If deflate returns with Z_OK or Z_BUF_ERROR, this\n  function must be called again with Z_FINISH and more output space (updated\n  avail_out) but no more input data, until it returns with Z_STREAM_END or an\n  error.  After deflate has returned Z_STREAM_END, the only possible operations\n  on the stream are deflateReset or deflateEnd.\n\n    Z_FINISH can be used in the first deflate call after deflateInit if all the\n  compression is to be done in a single step.  In order to complete in one\n  call, avail_out must be at least the value returned by deflateBound (see\n  below).  Then deflate is guaranteed to return Z_STREAM_END.  If not enough\n  output space is provided, deflate will not return Z_STREAM_END, and it must\n  be called again as described above.\n\n    deflate() sets strm->adler to the Adler-32 checksum of all input read\n  so far (that is, total_in bytes).  If a gzip stream is being generated, then\n  strm->adler will be the CRC-32 checksum of the input read so far.  (See\n  deflateInit2 below.)\n\n    deflate() may update strm->data_type if it can make a good guess about\n  the input data type (Z_BINARY or Z_TEXT).  If in doubt, the data is\n  considered binary.  This field is only for information purposes and does not\n  affect the compression algorithm in any manner.\n\n    deflate() returns Z_OK if some progress has been made (more input\n  processed or more output produced), Z_STREAM_END if all input has been\n  consumed and all output has been produced (only when flush is set to\n  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example\n  if next_in or next_out was Z_NULL or the state was inadvertently written over\n  by the application), or Z_BUF_ERROR if no progress is possible (for example\n  avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not fatal, and\n  deflate() can be called again with more input and more output space to\n  continue compressing.\n*/\n\n\nZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));\n/*\n     All dynamically allocated data structures for this stream are freed.\n   This function discards any unprocessed input and does not flush any pending\n   output.\n\n     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the\n   stream state was inconsistent, Z_DATA_ERROR if the stream was freed\n   prematurely (some input or output was discarded).  In the error case, msg\n   may be set but then points to a static string (which must not be\n   deallocated).\n*/\n\n\n/*\nZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));\n\n     Initializes the internal stream state for decompression.  The fields\n   next_in, avail_in, zalloc, zfree and opaque must be initialized before by\n   the caller.  In the current version of inflate, the provided input is not\n   read or consumed.  The allocation of a sliding window will be deferred to\n   the first call of inflate (if the decompression does not complete on the\n   first call).  If zalloc and zfree are set to Z_NULL, inflateInit updates\n   them to use default allocation functions.\n\n     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the\n   version assumed by the caller, or Z_STREAM_ERROR if the parameters are\n   invalid, such as a null pointer to the structure.  msg is set to null if\n   there is no error message.  inflateInit does not perform any decompression.\n   Actual decompression will be done by inflate().  So next_in, and avail_in,\n   next_out, and avail_out are unused and unchanged.  The current\n   implementation of inflateInit() does not process any header information --\n   that is deferred until inflate() is called.\n*/\n\n\nZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));\n/*\n    inflate decompresses as much data as possible, and stops when the input\n  buffer becomes empty or the output buffer becomes full.  It may introduce\n  some output latency (reading input without producing any output) except when\n  forced to flush.\n\n  The detailed semantics are as follows.  inflate performs one or both of the\n  following actions:\n\n  - Decompress more input starting at next_in and update next_in and avail_in\n    accordingly.  If not all input can be processed (because there is not\n    enough room in the output buffer), then next_in and avail_in are updated\n    accordingly, and processing will resume at this point for the next call of\n    inflate().\n\n  - Generate more output starting at next_out and update next_out and avail_out\n    accordingly.  inflate() provides as much output as possible, until there is\n    no more input data or no more space in the output buffer (see below about\n    the flush parameter).\n\n    Before the call of inflate(), the application should ensure that at least\n  one of the actions is possible, by providing more input and/or consuming more\n  output, and updating the next_* and avail_* values accordingly.  If the\n  caller of inflate() does not provide both available input and available\n  output space, it is possible that there will be no progress made.  The\n  application can consume the uncompressed output when it wants, for example\n  when the output buffer is full (avail_out == 0), or after each call of\n  inflate().  If inflate returns Z_OK and with zero avail_out, it must be\n  called again after making room in the output buffer because there might be\n  more output pending.\n\n    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,\n  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much\n  output as possible to the output buffer.  Z_BLOCK requests that inflate()\n  stop if and when it gets to the next deflate block boundary.  When decoding\n  the zlib or gzip format, this will cause inflate() to return immediately\n  after the header and before the first block.  When doing a raw inflate,\n  inflate() will go ahead and process the first block, and will return when it\n  gets to the end of that block, or when it runs out of data.\n\n    The Z_BLOCK option assists in appending to or combining deflate streams.\n  To assist in this, on return inflate() always sets strm->data_type to the\n  number of unused bits in the last byte taken from strm->next_in, plus 64 if\n  inflate() is currently decoding the last block in the deflate stream, plus\n  128 if inflate() returned immediately after decoding an end-of-block code or\n  decoding the complete header up to just before the first byte of the deflate\n  stream.  The end-of-block will not be indicated until all of the uncompressed\n  data from that block has been written to strm->next_out.  The number of\n  unused bits may in general be greater than seven, except when bit 7 of\n  data_type is set, in which case the number of unused bits will be less than\n  eight.  data_type is set as noted here every time inflate() returns for all\n  flush options, and so can be used to determine the amount of currently\n  consumed input in bits.\n\n    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the\n  end of each deflate block header is reached, before any actual data in that\n  block is decoded.  This allows the caller to determine the length of the\n  deflate block header for later use in random access within a deflate block.\n  256 is added to the value of strm->data_type when inflate() returns\n  immediately after reaching the end of the deflate block header.\n\n    inflate() should normally be called until it returns Z_STREAM_END or an\n  error.  However if all decompression is to be performed in a single step (a\n  single call of inflate), the parameter flush should be set to Z_FINISH.  In\n  this case all pending input is processed and all pending output is flushed;\n  avail_out must be large enough to hold all of the uncompressed data for the\n  operation to complete.  (The size of the uncompressed data may have been\n  saved by the compressor for this purpose.)  The use of Z_FINISH is not\n  required to perform an inflation in one step.  However it may be used to\n  inform inflate that a faster approach can be used for the single inflate()\n  call.  Z_FINISH also informs inflate to not maintain a sliding window if the\n  stream completes, which reduces inflate's memory footprint.  If the stream\n  does not complete, either because not all of the stream is provided or not\n  enough output space is provided, then a sliding window will be allocated and\n  inflate() can be called again to continue the operation as if Z_NO_FLUSH had\n  been used.\n\n     In this implementation, inflate() always flushes as much output as\n  possible to the output buffer, and always uses the faster approach on the\n  first call.  So the effects of the flush parameter in this implementation are\n  on the return value of inflate() as noted below, when inflate() returns early\n  when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of\n  memory for a sliding window when Z_FINISH is used.\n\n     If a preset dictionary is needed after this call (see inflateSetDictionary\n  below), inflate sets strm->adler to the Adler-32 checksum of the dictionary\n  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets\n  strm->adler to the Adler-32 checksum of all output produced so far (that is,\n  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described\n  below.  At the end of the stream, inflate() checks that its computed Adler-32\n  checksum is equal to that saved by the compressor and returns Z_STREAM_END\n  only if the checksum is correct.\n\n    inflate() can decompress and check either zlib-wrapped or gzip-wrapped\n  deflate data.  The header type is detected automatically, if requested when\n  initializing with inflateInit2().  Any information contained in the gzip\n  header is not retained unless inflateGetHeader() is used.  When processing\n  gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output\n  produced so far.  The CRC-32 is checked against the gzip trailer, as is the\n  uncompressed length, modulo 2^32.\n\n    inflate() returns Z_OK if some progress has been made (more input processed\n  or more output produced), Z_STREAM_END if the end of the compressed data has\n  been reached and all uncompressed output has been produced, Z_NEED_DICT if a\n  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was\n  corrupted (input stream not conforming to the zlib format or incorrect check\n  value, in which case strm->msg points to a string with a more specific\n  error), Z_STREAM_ERROR if the stream structure was inconsistent (for example\n  next_in or next_out was Z_NULL, or the state was inadvertently written over\n  by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR\n  if no progress was possible or if there was not enough room in the output\n  buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and\n  inflate() can be called again with more input and more output space to\n  continue decompressing.  If Z_DATA_ERROR is returned, the application may\n  then call inflateSync() to look for a good compression block if a partial\n  recovery of the data is to be attempted.\n*/\n\n\nZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));\n/*\n     All dynamically allocated data structures for this stream are freed.\n   This function discards any unprocessed input and does not flush any pending\n   output.\n\n     inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state\n   was inconsistent.\n*/\n\n\n                        /* Advanced functions */\n\n/*\n    The following functions are needed only in some special applications.\n*/\n\n/*\nZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,\n                                     int  level,\n                                     int  method,\n                                     int  windowBits,\n                                     int  memLevel,\n                                     int  strategy));\n\n     This is another version of deflateInit with more compression options.  The\n   fields next_in, zalloc, zfree and opaque must be initialized before by the\n   caller.\n\n     The method parameter is the compression method.  It must be Z_DEFLATED in\n   this version of the library.\n\n     The windowBits parameter is the base two logarithm of the window size\n   (the size of the history buffer).  It should be in the range 8..15 for this\n   version of the library.  Larger values of this parameter result in better\n   compression at the expense of memory usage.  The default value is 15 if\n   deflateInit is used instead.\n\n     For the current implementation of deflate(), a windowBits value of 8 (a\n   window size of 256 bytes) is not supported.  As a result, a request for 8\n   will result in 9 (a 512-byte window).  In that case, providing 8 to\n   inflateInit2() will result in an error when the zlib header with 9 is\n   checked against the initialization of inflate().  The remedy is to not use 8\n   with deflateInit2() with this initialization, or at least in that case use 9\n   with inflateInit2().\n\n     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits\n   determines the window size.  deflate() will then generate raw deflate data\n   with no zlib header or trailer, and will not compute a check value.\n\n     windowBits can also be greater than 15 for optional gzip encoding.  Add\n   16 to windowBits to write a simple gzip header and trailer around the\n   compressed data instead of a zlib wrapper.  The gzip header will have no\n   file name, no extra data, no comment, no modification time (set to zero), no\n   header crc, and the operating system will be set to the appropriate value,\n   if the operating system was determined at compile time.  If a gzip stream is\n   being written, strm->adler is a CRC-32 instead of an Adler-32.\n\n     For raw deflate or gzip encoding, a request for a 256-byte window is\n   rejected as invalid, since only the zlib header provides a means of\n   transmitting the window size to the decompressor.\n\n     The memLevel parameter specifies how much memory should be allocated\n   for the internal compression state.  memLevel=1 uses minimum memory but is\n   slow and reduces compression ratio; memLevel=9 uses maximum memory for\n   optimal speed.  The default value is 8.  See zconf.h for total memory usage\n   as a function of windowBits and memLevel.\n\n     The strategy parameter is used to tune the compression algorithm.  Use the\n   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a\n   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no\n   string match), or Z_RLE to limit match distances to one (run-length\n   encoding).  Filtered data consists mostly of small values with a somewhat\n   random distribution.  In this case, the compression algorithm is tuned to\n   compress them better.  The effect of Z_FILTERED is to force more Huffman\n   coding and less string matching; it is somewhat intermediate between\n   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as\n   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The\n   strategy parameter only affects the compression ratio but not the\n   correctness of the compressed output even if it is not set appropriately.\n   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler\n   decoder for special applications.\n\n     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid\n   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is\n   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is\n   set to null if there is no error message.  deflateInit2 does not perform any\n   compression: this will be done by deflate().\n*/\n\nZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,\n                                             const Bytef *dictionary,\n                                             uInt  dictLength));\n/*\n     Initializes the compression dictionary from the given byte sequence\n   without producing any compressed output.  When using the zlib format, this\n   function must be called immediately after deflateInit, deflateInit2 or\n   deflateReset, and before any call of deflate.  When doing raw deflate, this\n   function must be called either before any call of deflate, or immediately\n   after the completion of a deflate block, i.e. after all input has been\n   consumed and all output has been delivered when using any of the flush\n   options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH.  The\n   compressor and decompressor must use exactly the same dictionary (see\n   inflateSetDictionary).\n\n     The dictionary should consist of strings (byte sequences) that are likely\n   to be encountered later in the data to be compressed, with the most commonly\n   used strings preferably put towards the end of the dictionary.  Using a\n   dictionary is most useful when the data to be compressed is short and can be\n   predicted with good accuracy; the data can then be compressed better than\n   with the default empty dictionary.\n\n     Depending on the size of the compression data structures selected by\n   deflateInit or deflateInit2, a part of the dictionary may in effect be\n   discarded, for example if the dictionary is larger than the window size\n   provided in deflateInit or deflateInit2.  Thus the strings most likely to be\n   useful should be put at the end of the dictionary, not at the front.  In\n   addition, the current implementation of deflate will use at most the window\n   size minus 262 bytes of the provided dictionary.\n\n     Upon return of this function, strm->adler is set to the Adler-32 value\n   of the dictionary; the decompressor may later use this value to determine\n   which dictionary has been used by the compressor.  (The Adler-32 value\n   applies to the whole dictionary even if only a subset of the dictionary is\n   actually used by the compressor.) If a raw deflate was requested, then the\n   Adler-32 value is not computed and strm->adler is not set.\n\n     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a\n   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is\n   inconsistent (for example if deflate has already been called for this stream\n   or if not at a block boundary for raw deflate).  deflateSetDictionary does\n   not perform any compression: this will be done by deflate().\n*/\n\nZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,\n                                             Bytef *dictionary,\n                                             uInt  *dictLength));\n/*\n     Returns the sliding dictionary being maintained by deflate.  dictLength is\n   set to the number of bytes in the dictionary, and that many bytes are copied\n   to dictionary.  dictionary must have enough space, where 32768 bytes is\n   always enough.  If deflateGetDictionary() is called with dictionary equal to\n   Z_NULL, then only the dictionary length is returned, and nothing is copied.\n   Similary, if dictLength is Z_NULL, then it is not set.\n\n     deflateGetDictionary() may return a length less than the window size, even\n   when more than the window size in input has been provided. It may return up\n   to 258 bytes less in that case, due to how zlib's implementation of deflate\n   manages the sliding window and lookahead for matches, where matches can be\n   up to 258 bytes long. If the application needs the last window-size bytes of\n   input, then that would need to be saved by the application outside of zlib.\n\n     deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the\n   stream state is inconsistent.\n*/\n\nZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,\n                                    z_streamp source));\n/*\n     Sets the destination stream as a complete copy of the source stream.\n\n     This function can be useful when several compression strategies will be\n   tried, for example when there are several ways of pre-processing the input\n   data with a filter.  The streams that will be discarded should then be freed\n   by calling deflateEnd.  Note that deflateCopy duplicates the internal\n   compression state which can be quite large, so this strategy is slow and can\n   consume lots of memory.\n\n     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not\n   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent\n   (such as zalloc being Z_NULL).  msg is left unchanged in both source and\n   destination.\n*/\n\nZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));\n/*\n     This function is equivalent to deflateEnd followed by deflateInit, but\n   does not free and reallocate the internal compression state.  The stream\n   will leave the compression level and any other attributes that may have been\n   set unchanged.\n\n     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent (such as zalloc or state being Z_NULL).\n*/\n\nZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,\n                                      int level,\n                                      int strategy));\n/*\n     Dynamically update the compression level and compression strategy.  The\n   interpretation of level and strategy is as in deflateInit2().  This can be\n   used to switch between compression and straight copy of the input data, or\n   to switch to a different kind of input data requiring a different strategy.\n   If the compression approach (which is a function of the level) or the\n   strategy is changed, and if any input has been consumed in a previous\n   deflate() call, then the input available so far is compressed with the old\n   level and strategy using deflate(strm, Z_BLOCK).  There are three approaches\n   for the compression levels 0, 1..3, and 4..9 respectively.  The new level\n   and strategy will take effect at the next call of deflate().\n\n     If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does\n   not have enough output space to complete, then the parameter change will not\n   take effect.  In this case, deflateParams() can be called again with the\n   same parameters and more output space to try again.\n\n     In order to assure a change in the parameters on the first try, the\n   deflate stream should be flushed using deflate() with Z_BLOCK or other flush\n   request until strm.avail_out is not zero, before calling deflateParams().\n   Then no more input data should be provided before the deflateParams() call.\n   If this is done, the old level and strategy will be applied to the data\n   compressed before deflateParams(), and the new level and strategy will be\n   applied to the the data compressed after deflateParams().\n\n     deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream\n   state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if\n   there was not enough output space to complete the compression of the\n   available input data before a change in the strategy or approach.  Note that\n   in the case of a Z_BUF_ERROR, the parameters are not changed.  A return\n   value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be\n   retried with more output space.\n*/\n\nZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,\n                                    int good_length,\n                                    int max_lazy,\n                                    int nice_length,\n                                    int max_chain));\n/*\n     Fine tune deflate's internal compression parameters.  This should only be\n   used by someone who understands the algorithm used by zlib's deflate for\n   searching for the best matching string, and even then only by the most\n   fanatic optimizer trying to squeeze out the last compressed bit for their\n   specific input data.  Read the deflate.c source code for the meaning of the\n   max_lazy, good_length, nice_length, and max_chain parameters.\n\n     deflateTune() can be called after deflateInit() or deflateInit2(), and\n   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.\n */\n\nZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,\n                                       uLong sourceLen));\n/*\n     deflateBound() returns an upper bound on the compressed size after\n   deflation of sourceLen bytes.  It must be called after deflateInit() or\n   deflateInit2(), and after deflateSetHeader(), if used.  This would be used\n   to allocate an output buffer for deflation in a single pass, and so would be\n   called before deflate().  If that first deflate() call is provided the\n   sourceLen input bytes, an output buffer allocated to the size returned by\n   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed\n   to return Z_STREAM_END.  Note that it is possible for the compressed size to\n   be larger than the value returned by deflateBound() if flush options other\n   than Z_FINISH or Z_NO_FLUSH are used.\n*/\n\nZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,\n                                       unsigned *pending,\n                                       int *bits));\n/*\n     deflatePending() returns the number of bytes and bits of output that have\n   been generated, but not yet provided in the available output.  The bytes not\n   provided would be due to the available output space having being consumed.\n   The number of bits of output not provided are between 0 and 7, where they\n   await more bits to join them in order to fill out a full byte.  If pending\n   or bits are Z_NULL, then those values are not set.\n\n     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent.\n */\n\nZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,\n                                     int bits,\n                                     int value));\n/*\n     deflatePrime() inserts bits in the deflate output stream.  The intent\n   is that this function is used to start off the deflate output with the bits\n   leftover from a previous deflate stream when appending to it.  As such, this\n   function can only be used for raw deflate, and must be used before the first\n   deflate() call after a deflateInit2() or deflateReset().  bits must be less\n   than or equal to 16, and that many of the least significant bits of value\n   will be inserted in the output.\n\n     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough\n   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the\n   source stream state was inconsistent.\n*/\n\nZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,\n                                         gz_headerp head));\n/*\n     deflateSetHeader() provides gzip header information for when a gzip\n   stream is requested by deflateInit2().  deflateSetHeader() may be called\n   after deflateInit2() or deflateReset() and before the first call of\n   deflate().  The text, time, os, extra field, name, and comment information\n   in the provided gz_header structure are written to the gzip header (xflag is\n   ignored -- the extra flags are set according to the compression level).  The\n   caller must assure that, if not Z_NULL, name and comment are terminated with\n   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are\n   available there.  If hcrc is true, a gzip header crc is included.  Note that\n   the current versions of the command-line version of gzip (up through version\n   1.3.x) do not support header crc's, and will report that it is a \"multi-part\n   gzip file\" and give up.\n\n     If deflateSetHeader is not used, the default gzip header has text false,\n   the time set to zero, and os set to 255, with no extra, name, or comment\n   fields.  The gzip header is returned to the default state by deflateReset().\n\n     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent.\n*/\n\n/*\nZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,\n                                     int  windowBits));\n\n     This is another version of inflateInit with an extra parameter.  The\n   fields next_in, avail_in, zalloc, zfree and opaque must be initialized\n   before by the caller.\n\n     The windowBits parameter is the base two logarithm of the maximum window\n   size (the size of the history buffer).  It should be in the range 8..15 for\n   this version of the library.  The default value is 15 if inflateInit is used\n   instead.  windowBits must be greater than or equal to the windowBits value\n   provided to deflateInit2() while compressing, or it must be equal to 15 if\n   deflateInit2() was not used.  If a compressed stream with a larger window\n   size is given as input, inflate() will return with the error code\n   Z_DATA_ERROR instead of trying to allocate a larger window.\n\n     windowBits can also be zero to request that inflate use the window size in\n   the zlib header of the compressed stream.\n\n     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits\n   determines the window size.  inflate() will then process raw deflate data,\n   not looking for a zlib or gzip header, not generating a check value, and not\n   looking for any check values for comparison at the end of the stream.  This\n   is for use with other formats that use the deflate compressed data format\n   such as zip.  Those formats provide their own check values.  If a custom\n   format is developed using the raw deflate format for compressed data, it is\n   recommended that a check value such as an Adler-32 or a CRC-32 be applied to\n   the uncompressed data as is done in the zlib, gzip, and zip formats.  For\n   most applications, the zlib format should be used as is.  Note that comments\n   above on the use in deflateInit2() applies to the magnitude of windowBits.\n\n     windowBits can also be greater than 15 for optional gzip decoding.  Add\n   32 to windowBits to enable zlib and gzip decoding with automatic header\n   detection, or add 16 to decode only the gzip format (the zlib format will\n   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a\n   CRC-32 instead of an Adler-32.  Unlike the gunzip utility and gzread() (see\n   below), inflate() will not automatically decode concatenated gzip streams.\n   inflate() will return Z_STREAM_END at the end of the gzip stream.  The state\n   would need to be reset to continue decoding a subsequent gzip stream.\n\n     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the\n   version assumed by the caller, or Z_STREAM_ERROR if the parameters are\n   invalid, such as a null pointer to the structure.  msg is set to null if\n   there is no error message.  inflateInit2 does not perform any decompression\n   apart from possibly reading the zlib header if present: actual decompression\n   will be done by inflate().  (So next_in and avail_in may be modified, but\n   next_out and avail_out are unused and unchanged.) The current implementation\n   of inflateInit2() does not process any header information -- that is\n   deferred until inflate() is called.\n*/\n\nZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,\n                                             const Bytef *dictionary,\n                                             uInt  dictLength));\n/*\n     Initializes the decompression dictionary from the given uncompressed byte\n   sequence.  This function must be called immediately after a call of inflate,\n   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor\n   can be determined from the Adler-32 value returned by that call of inflate.\n   The compressor and decompressor must use exactly the same dictionary (see\n   deflateSetDictionary).  For raw inflate, this function can be called at any\n   time to set the dictionary.  If the provided dictionary is smaller than the\n   window and there is already data in the window, then the provided dictionary\n   will amend what's there.  The application must insure that the dictionary\n   that was used for compression is provided.\n\n     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a\n   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is\n   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the\n   expected one (incorrect Adler-32 value).  inflateSetDictionary does not\n   perform any decompression: this will be done by subsequent calls of\n   inflate().\n*/\n\nZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,\n                                             Bytef *dictionary,\n                                             uInt  *dictLength));\n/*\n     Returns the sliding dictionary being maintained by inflate.  dictLength is\n   set to the number of bytes in the dictionary, and that many bytes are copied\n   to dictionary.  dictionary must have enough space, where 32768 bytes is\n   always enough.  If inflateGetDictionary() is called with dictionary equal to\n   Z_NULL, then only the dictionary length is returned, and nothing is copied.\n   Similary, if dictLength is Z_NULL, then it is not set.\n\n     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the\n   stream state is inconsistent.\n*/\n\nZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));\n/*\n     Skips invalid compressed data until a possible full flush point (see above\n   for the description of deflate with Z_FULL_FLUSH) can be found, or until all\n   available input is skipped.  No output is provided.\n\n     inflateSync searches for a 00 00 FF FF pattern in the compressed data.\n   All full flush points have this pattern, but not all occurrences of this\n   pattern are full flush points.\n\n     inflateSync returns Z_OK if a possible full flush point has been found,\n   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point\n   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.\n   In the success case, the application may save the current current value of\n   total_in which indicates where valid compressed data was found.  In the\n   error case, the application may repeatedly call inflateSync, providing more\n   input each time, until success or end of the input data.\n*/\n\nZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,\n                                    z_streamp source));\n/*\n     Sets the destination stream as a complete copy of the source stream.\n\n     This function can be useful when randomly accessing a large stream.  The\n   first pass through the stream can periodically record the inflate state,\n   allowing restarting inflate at those points when randomly accessing the\n   stream.\n\n     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not\n   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent\n   (such as zalloc being Z_NULL).  msg is left unchanged in both source and\n   destination.\n*/\n\nZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));\n/*\n     This function is equivalent to inflateEnd followed by inflateInit,\n   but does not free and reallocate the internal decompression state.  The\n   stream will keep attributes that may have been set by inflateInit2.\n\n     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent (such as zalloc or state being Z_NULL).\n*/\n\nZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,\n                                      int windowBits));\n/*\n     This function is the same as inflateReset, but it also permits changing\n   the wrap and window size requests.  The windowBits parameter is interpreted\n   the same as it is for inflateInit2.  If the window size is changed, then the\n   memory allocated for the window is freed, and the window will be reallocated\n   by inflate() if needed.\n\n     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent (such as zalloc or state being Z_NULL), or if\n   the windowBits parameter is invalid.\n*/\n\nZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,\n                                     int bits,\n                                     int value));\n/*\n     This function inserts bits in the inflate input stream.  The intent is\n   that this function is used to start inflating at a bit position in the\n   middle of a byte.  The provided bits will be used before any bytes are used\n   from next_in.  This function should only be used with raw inflate, and\n   should be used before the first inflate() call after inflateInit2() or\n   inflateReset().  bits must be less than or equal to 16, and that many of the\n   least significant bits of value will be inserted in the input.\n\n     If bits is negative, then the input stream bit buffer is emptied.  Then\n   inflatePrime() can be called again to put bits in the buffer.  This is used\n   to clear out bits leftover after feeding inflate a block description prior\n   to feeding inflate codes.\n\n     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent.\n*/\n\nZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));\n/*\n     This function returns two values, one in the lower 16 bits of the return\n   value, and the other in the remaining upper bits, obtained by shifting the\n   return value down 16 bits.  If the upper value is -1 and the lower value is\n   zero, then inflate() is currently decoding information outside of a block.\n   If the upper value is -1 and the lower value is non-zero, then inflate is in\n   the middle of a stored block, with the lower value equaling the number of\n   bytes from the input remaining to copy.  If the upper value is not -1, then\n   it is the number of bits back from the current bit position in the input of\n   the code (literal or length/distance pair) currently being processed.  In\n   that case the lower value is the number of bytes already emitted for that\n   code.\n\n     A code is being processed if inflate is waiting for more input to complete\n   decoding of the code, or if it has completed decoding but is waiting for\n   more output space to write the literal or match data.\n\n     inflateMark() is used to mark locations in the input data for random\n   access, which may be at bit positions, and to note those cases where the\n   output of a code may span boundaries of random access blocks.  The current\n   location in the input stream can be determined from avail_in and data_type\n   as noted in the description for the Z_BLOCK flush parameter for inflate.\n\n     inflateMark returns the value noted above, or -65536 if the provided\n   source stream state was inconsistent.\n*/\n\nZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,\n                                         gz_headerp head));\n/*\n     inflateGetHeader() requests that gzip header information be stored in the\n   provided gz_header structure.  inflateGetHeader() may be called after\n   inflateInit2() or inflateReset(), and before the first call of inflate().\n   As inflate() processes the gzip stream, head->done is zero until the header\n   is completed, at which time head->done is set to one.  If a zlib stream is\n   being decoded, then head->done is set to -1 to indicate that there will be\n   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be\n   used to force inflate() to return immediately after header processing is\n   complete and before any actual data is decompressed.\n\n     The text, time, xflags, and os fields are filled in with the gzip header\n   contents.  hcrc is set to true if there is a header CRC.  (The header CRC\n   was valid if done is set to one.) If extra is not Z_NULL, then extra_max\n   contains the maximum number of bytes to write to extra.  Once done is true,\n   extra_len contains the actual extra field length, and extra contains the\n   extra field, or that field truncated if extra_max is less than extra_len.\n   If name is not Z_NULL, then up to name_max characters are written there,\n   terminated with a zero unless the length is greater than name_max.  If\n   comment is not Z_NULL, then up to comm_max characters are written there,\n   terminated with a zero unless the length is greater than comm_max.  When any\n   of extra, name, or comment are not Z_NULL and the respective field is not\n   present in the header, then that field is set to Z_NULL to signal its\n   absence.  This allows the use of deflateSetHeader() with the returned\n   structure to duplicate the header.  However if those fields are set to\n   allocated memory, then the application will need to save those pointers\n   elsewhere so that they can be eventually freed.\n\n     If inflateGetHeader is not used, then the header information is simply\n   discarded.  The header is always checked for validity, including the header\n   CRC if present.  inflateReset() will reset the process to discard the header\n   information.  The application would need to call inflateGetHeader() again to\n   retrieve the header from the next gzip stream.\n\n     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent.\n*/\n\n/*\nZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,\n                                        unsigned char FAR *window));\n\n     Initialize the internal stream state for decompression using inflateBack()\n   calls.  The fields zalloc, zfree and opaque in strm must be initialized\n   before the call.  If zalloc and zfree are Z_NULL, then the default library-\n   derived memory allocation routines are used.  windowBits is the base two\n   logarithm of the window size, in the range 8..15.  window is a caller\n   supplied buffer of that size.  Except for special applications where it is\n   assured that deflate was used with small window sizes, windowBits must be 15\n   and a 32K byte window must be supplied to be able to decompress general\n   deflate streams.\n\n     See inflateBack() for the usage of these routines.\n\n     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of\n   the parameters are invalid, Z_MEM_ERROR if the internal state could not be\n   allocated, or Z_VERSION_ERROR if the version of the library does not match\n   the version of the header file.\n*/\n\ntypedef unsigned (*in_func) OF((void FAR *,\n                                z_const unsigned char FAR * FAR *));\ntypedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));\n\nZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,\n                                    in_func in, void FAR *in_desc,\n                                    out_func out, void FAR *out_desc));\n/*\n     inflateBack() does a raw inflate with a single call using a call-back\n   interface for input and output.  This is potentially more efficient than\n   inflate() for file i/o applications, in that it avoids copying between the\n   output and the sliding window by simply making the window itself the output\n   buffer.  inflate() can be faster on modern CPUs when used with large\n   buffers.  inflateBack() trusts the application to not change the output\n   buffer passed by the output function, at least until inflateBack() returns.\n\n     inflateBackInit() must be called first to allocate the internal state\n   and to initialize the state with the user-provided window buffer.\n   inflateBack() may then be used multiple times to inflate a complete, raw\n   deflate stream with each call.  inflateBackEnd() is then called to free the\n   allocated state.\n\n     A raw deflate stream is one with no zlib or gzip header or trailer.\n   This routine would normally be used in a utility that reads zip or gzip\n   files and writes out uncompressed files.  The utility would decode the\n   header and process the trailer on its own, hence this routine expects only\n   the raw deflate stream to decompress.  This is different from the default\n   behavior of inflate(), which expects a zlib header and trailer around the\n   deflate stream.\n\n     inflateBack() uses two subroutines supplied by the caller that are then\n   called by inflateBack() for input and output.  inflateBack() calls those\n   routines until it reads a complete deflate stream and writes out all of the\n   uncompressed data, or until it encounters an error.  The function's\n   parameters and return types are defined above in the in_func and out_func\n   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the\n   number of bytes of provided input, and a pointer to that input in buf.  If\n   there is no input available, in() must return zero -- buf is ignored in that\n   case -- and inflateBack() will return a buffer error.  inflateBack() will\n   call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].\n   out() should return zero on success, or non-zero on failure.  If out()\n   returns non-zero, inflateBack() will return with an error.  Neither in() nor\n   out() are permitted to change the contents of the window provided to\n   inflateBackInit(), which is also the buffer that out() uses to write from.\n   The length written by out() will be at most the window size.  Any non-zero\n   amount of input may be provided by in().\n\n     For convenience, inflateBack() can be provided input on the first call by\n   setting strm->next_in and strm->avail_in.  If that input is exhausted, then\n   in() will be called.  Therefore strm->next_in must be initialized before\n   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called\n   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in\n   must also be initialized, and then if strm->avail_in is not zero, input will\n   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].\n\n     The in_desc and out_desc parameters of inflateBack() is passed as the\n   first parameter of in() and out() respectively when they are called.  These\n   descriptors can be optionally used to pass any information that the caller-\n   supplied in() and out() functions need to do their job.\n\n     On return, inflateBack() will set strm->next_in and strm->avail_in to\n   pass back any unused input that was provided by the last in() call.  The\n   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR\n   if in() or out() returned an error, Z_DATA_ERROR if there was a format error\n   in the deflate stream (in which case strm->msg is set to indicate the nature\n   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.\n   In the case of Z_BUF_ERROR, an input or output error can be distinguished\n   using strm->next_in which will be Z_NULL only if in() returned an error.  If\n   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning\n   non-zero.  (in() will always be called before out(), so strm->next_in is\n   assured to be defined if out() returns non-zero.)  Note that inflateBack()\n   cannot return Z_OK.\n*/\n\nZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));\n/*\n     All memory allocated by inflateBackInit() is freed.\n\n     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream\n   state was inconsistent.\n*/\n\nZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));\n/* Return flags indicating compile-time options.\n\n    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:\n     1.0: size of uInt\n     3.2: size of uLong\n     5.4: size of voidpf (pointer)\n     7.6: size of z_off_t\n\n    Compiler, assembler, and debug options:\n     8: ZLIB_DEBUG\n     9: ASMV or ASMINF -- use ASM code\n     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention\n     11: 0 (reserved)\n\n    One-time table building (smaller code, but not thread-safe if true):\n     12: BUILDFIXED -- build static block decoding tables when needed\n     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed\n     14,15: 0 (reserved)\n\n    Library content (indicates missing functionality):\n     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking\n                          deflate code when not needed)\n     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect\n                    and decode gzip streams (to avoid linking crc code)\n     18-19: 0 (reserved)\n\n    Operation variations (changes in library functionality):\n     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate\n     21: FASTEST -- deflate algorithm with only one, lowest compression level\n     22,23: 0 (reserved)\n\n    The sprintf variant used by gzprintf (zero is best):\n     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format\n     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!\n     26: 0 = returns value, 1 = void -- 1 means inferred string length returned\n\n    Remainder:\n     27-31: 0 (reserved)\n */\n\n#ifndef Z_SOLO\n\n                        /* utility functions */\n\n/*\n     The following utility functions are implemented on top of the basic\n   stream-oriented functions.  To simplify the interface, some default options\n   are assumed (compression level and memory usage, standard memory allocation\n   functions).  The source code of these utility functions can be modified if\n   you need special options.\n*/\n\nZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,\n                                 const Bytef *source, uLong sourceLen));\n/*\n     Compresses the source buffer into the destination buffer.  sourceLen is\n   the byte length of the source buffer.  Upon entry, destLen is the total size\n   of the destination buffer, which must be at least the value returned by\n   compressBound(sourceLen).  Upon exit, destLen is the actual size of the\n   compressed data.  compress() is equivalent to compress2() with a level\n   parameter of Z_DEFAULT_COMPRESSION.\n\n     compress returns Z_OK if success, Z_MEM_ERROR if there was not\n   enough memory, Z_BUF_ERROR if there was not enough room in the output\n   buffer.\n*/\n\nZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,\n                                  const Bytef *source, uLong sourceLen,\n                                  int level));\n/*\n     Compresses the source buffer into the destination buffer.  The level\n   parameter has the same meaning as in deflateInit.  sourceLen is the byte\n   length of the source buffer.  Upon entry, destLen is the total size of the\n   destination buffer, which must be at least the value returned by\n   compressBound(sourceLen).  Upon exit, destLen is the actual size of the\n   compressed data.\n\n     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_BUF_ERROR if there was not enough room in the output buffer,\n   Z_STREAM_ERROR if the level parameter is invalid.\n*/\n\nZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));\n/*\n     compressBound() returns an upper bound on the compressed size after\n   compress() or compress2() on sourceLen bytes.  It would be used before a\n   compress() or compress2() call to allocate the destination buffer.\n*/\n\nZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,\n                                   const Bytef *source, uLong sourceLen));\n/*\n     Decompresses the source buffer into the destination buffer.  sourceLen is\n   the byte length of the source buffer.  Upon entry, destLen is the total size\n   of the destination buffer, which must be large enough to hold the entire\n   uncompressed data.  (The size of the uncompressed data must have been saved\n   previously by the compressor and transmitted to the decompressor by some\n   mechanism outside the scope of this compression library.) Upon exit, destLen\n   is the actual size of the uncompressed data.\n\n     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not\n   enough memory, Z_BUF_ERROR if there was not enough room in the output\n   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In\n   the case where there is not enough room, uncompress() will fill the output\n   buffer with the uncompressed data up to that point.\n*/\n\nZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest,   uLongf *destLen,\n                                    const Bytef *source, uLong *sourceLen));\n/*\n     Same as uncompress, except that sourceLen is a pointer, where the\n   length of the source is *sourceLen.  On return, *sourceLen is the number of\n   source bytes consumed.\n*/\n\n                        /* gzip file access functions */\n\n/*\n     This library supports reading and writing files in gzip (.gz) format with\n   an interface similar to that of stdio, using the functions that start with\n   \"gz\".  The gzip format is different from the zlib format.  gzip is a gzip\n   wrapper, documented in RFC 1952, wrapped around a deflate stream.\n*/\n\ntypedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */\n\n/*\nZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));\n\n     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as\n   in fopen (\"rb\" or \"wb\") but can also include a compression level (\"wb9\") or\n   a strategy: 'f' for filtered data as in \"wb6f\", 'h' for Huffman-only\n   compression as in \"wb1h\", 'R' for run-length encoding as in \"wb1R\", or 'F'\n   for fixed code compression as in \"wb9F\".  (See the description of\n   deflateInit2 for more information about the strategy parameter.)  'T' will\n   request transparent writing or appending with no compression and not using\n   the gzip format.\n\n     \"a\" can be used instead of \"w\" to request that the gzip stream that will\n   be written be appended to the file.  \"+\" will result in an error, since\n   reading and writing to the same gzip file is not supported.  The addition of\n   \"x\" when writing will create the file exclusively, which fails if the file\n   already exists.  On systems that support it, the addition of \"e\" when\n   reading or writing will set the flag to close the file on an execve() call.\n\n     These functions, as well as gzip, will read and decode a sequence of gzip\n   streams in a file.  The append function of gzopen() can be used to create\n   such a file.  (Also see gzflush() for another way to do this.)  When\n   appending, gzopen does not test whether the file begins with a gzip stream,\n   nor does it look for the end of the gzip streams to begin appending.  gzopen\n   will simply append a gzip stream to the existing file.\n\n     gzopen can be used to read a file which is not in gzip format; in this\n   case gzread will directly read from the file without decompression.  When\n   reading, this will be detected automatically by looking for the magic two-\n   byte gzip header.\n\n     gzopen returns NULL if the file could not be opened, if there was\n   insufficient memory to allocate the gzFile state, or if an invalid mode was\n   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).\n   errno can be checked to determine if the reason gzopen failed was that the\n   file could not be opened.\n*/\n\nZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));\n/*\n     gzdopen associates a gzFile with the file descriptor fd.  File descriptors\n   are obtained from calls like open, dup, creat, pipe or fileno (if the file\n   has been previously opened with fopen).  The mode parameter is as in gzopen.\n\n     The next call of gzclose on the returned gzFile will also close the file\n   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor\n   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,\n   mode);.  The duplicated descriptor should be saved to avoid a leak, since\n   gzdopen does not close fd if it fails.  If you are using fileno() to get the\n   file descriptor from a FILE *, then you will have to use dup() to avoid\n   double-close()ing the file descriptor.  Both gzclose() and fclose() will\n   close the associated file descriptor, so they need to have different file\n   descriptors.\n\n     gzdopen returns NULL if there was insufficient memory to allocate the\n   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not\n   provided, or '+' was provided), or if fd is -1.  The file descriptor is not\n   used until the next gz* read, write, seek, or close operation, so gzdopen\n   will not detect if fd is invalid (unless fd is -1).\n*/\n\nZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));\n/*\n     Set the internal buffer size used by this library's functions.  The\n   default buffer size is 8192 bytes.  This function must be called after\n   gzopen() or gzdopen(), and before any other calls that read or write the\n   file.  The buffer memory allocation is always deferred to the first read or\n   write.  Three times that size in buffer space is allocated.  A larger buffer\n   size of, for example, 64K or 128K bytes will noticeably increase the speed\n   of decompression (reading).\n\n     The new buffer size also affects the maximum length for gzprintf().\n\n     gzbuffer() returns 0 on success, or -1 on failure, such as being called\n   too late.\n*/\n\nZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));\n/*\n     Dynamically update the compression level or strategy.  See the description\n   of deflateInit2 for the meaning of these parameters.  Previously provided\n   data is flushed before the parameter change.\n\n     gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not\n   opened for writing, Z_ERRNO if there is an error writing the flushed data,\n   or Z_MEM_ERROR if there is a memory allocation error.\n*/\n\nZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));\n/*\n     Reads the given number of uncompressed bytes from the compressed file.  If\n   the input file is not in gzip format, gzread copies the given number of\n   bytes into the buffer directly from the file.\n\n     After reaching the end of a gzip stream in the input, gzread will continue\n   to read, looking for another gzip stream.  Any number of gzip streams may be\n   concatenated in the input file, and will all be decompressed by gzread().\n   If something other than a gzip stream is encountered after a gzip stream,\n   that remaining trailing garbage is ignored (and no error is returned).\n\n     gzread can be used to read a gzip file that is being concurrently written.\n   Upon reaching the end of the input, gzread will return with the available\n   data.  If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then\n   gzclearerr can be used to clear the end of file indicator in order to permit\n   gzread to be tried again.  Z_OK indicates that a gzip stream was completed\n   on the last gzread.  Z_BUF_ERROR indicates that the input file ended in the\n   middle of a gzip stream.  Note that gzread does not return -1 in the event\n   of an incomplete gzip stream.  This error is deferred until gzclose(), which\n   will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip\n   stream.  Alternatively, gzerror can be used before gzclose to detect this\n   case.\n\n     gzread returns the number of uncompressed bytes actually read, less than\n   len for end of file, or -1 for error.  If len is too large to fit in an int,\n   then nothing is read, -1 is returned, and the error state is set to\n   Z_STREAM_ERROR.\n*/\n\nZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,\n                                     gzFile file));\n/*\n     Read up to nitems items of size size from file to buf, otherwise operating\n   as gzread() does.  This duplicates the interface of stdio's fread(), with\n   size_t request and return types.  If the library defines size_t, then\n   z_size_t is identical to size_t.  If not, then z_size_t is an unsigned\n   integer type that can contain a pointer.\n\n     gzfread() returns the number of full items read of size size, or zero if\n   the end of the file was reached and a full item could not be read, or if\n   there was an error.  gzerror() must be consulted if zero is returned in\n   order to determine if there was an error.  If the multiplication of size and\n   nitems overflows, i.e. the product does not fit in a z_size_t, then nothing\n   is read, zero is returned, and the error state is set to Z_STREAM_ERROR.\n\n     In the event that the end of file is reached and only a partial item is\n   available at the end, i.e. the remaining uncompressed data length is not a\n   multiple of size, then the final partial item is nevetheless read into buf\n   and the end-of-file flag is set.  The length of the partial item read is not\n   provided, but could be inferred from the result of gztell().  This behavior\n   is the same as the behavior of fread() implementations in common libraries,\n   but it prevents the direct use of gzfread() to read a concurrently written\n   file, reseting and retrying on end-of-file, when size is not 1.\n*/\n\nZEXTERN int ZEXPORT gzwrite OF((gzFile file,\n                                voidpc buf, unsigned len));\n/*\n     Writes the given number of uncompressed bytes into the compressed file.\n   gzwrite returns the number of uncompressed bytes written or 0 in case of\n   error.\n*/\n\nZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,\n                                      z_size_t nitems, gzFile file));\n/*\n     gzfwrite() writes nitems items of size size from buf to file, duplicating\n   the interface of stdio's fwrite(), with size_t request and return types.  If\n   the library defines size_t, then z_size_t is identical to size_t.  If not,\n   then z_size_t is an unsigned integer type that can contain a pointer.\n\n     gzfwrite() returns the number of full items written of size size, or zero\n   if there was an error.  If the multiplication of size and nitems overflows,\n   i.e. the product does not fit in a z_size_t, then nothing is written, zero\n   is returned, and the error state is set to Z_STREAM_ERROR.\n*/\n\nZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));\n/*\n     Converts, formats, and writes the arguments to the compressed file under\n   control of the format string, as in fprintf.  gzprintf returns the number of\n   uncompressed bytes actually written, or a negative zlib error code in case\n   of error.  The number of uncompressed bytes written is limited to 8191, or\n   one less than the buffer size given to gzbuffer().  The caller should assure\n   that this limit is not exceeded.  If it is exceeded, then gzprintf() will\n   return an error (0) with nothing written.  In this case, there may also be a\n   buffer overflow with unpredictable consequences, which is possible only if\n   zlib was compiled with the insecure functions sprintf() or vsprintf()\n   because the secure snprintf() or vsnprintf() functions were not available.\n   This can be determined using zlibCompileFlags().\n*/\n\nZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));\n/*\n     Writes the given null-terminated string to the compressed file, excluding\n   the terminating null character.\n\n     gzputs returns the number of characters written, or -1 in case of error.\n*/\n\nZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));\n/*\n     Reads bytes from the compressed file until len-1 characters are read, or a\n   newline character is read and transferred to buf, or an end-of-file\n   condition is encountered.  If any characters are read or if len == 1, the\n   string is terminated with a null character.  If no characters are read due\n   to an end-of-file or len < 1, then the buffer is left untouched.\n\n     gzgets returns buf which is a null-terminated string, or it returns NULL\n   for end-of-file or in case of error.  If there was an error, the contents at\n   buf are indeterminate.\n*/\n\nZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));\n/*\n     Writes c, converted to an unsigned char, into the compressed file.  gzputc\n   returns the value that was written, or -1 in case of error.\n*/\n\nZEXTERN int ZEXPORT gzgetc OF((gzFile file));\n/*\n     Reads one byte from the compressed file.  gzgetc returns this byte or -1\n   in case of end of file or error.  This is implemented as a macro for speed.\n   As such, it does not do all of the checking the other functions do.  I.e.\n   it does not check to see if file is NULL, nor whether the structure file\n   points to has been clobbered or not.\n*/\n\nZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));\n/*\n     Push one character back onto the stream to be read as the first character\n   on the next read.  At least one character of push-back is allowed.\n   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will\n   fail if c is -1, and may fail if a character has been pushed but not read\n   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the\n   output buffer size of pushed characters is allowed.  (See gzbuffer above.)\n   The pushed character will be discarded if the stream is repositioned with\n   gzseek() or gzrewind().\n*/\n\nZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));\n/*\n     Flushes all pending output into the compressed file.  The parameter flush\n   is as in the deflate() function.  The return value is the zlib error number\n   (see function gzerror below).  gzflush is only permitted when writing.\n\n     If the flush parameter is Z_FINISH, the remaining data is written and the\n   gzip stream is completed in the output.  If gzwrite() is called again, a new\n   gzip stream will be started in the output.  gzread() is able to read such\n   concatenated gzip streams.\n\n     gzflush should be called only when strictly necessary because it will\n   degrade compression if called too often.\n*/\n\n/*\nZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,\n                                   z_off_t offset, int whence));\n\n     Sets the starting position for the next gzread or gzwrite on the given\n   compressed file.  The offset represents a number of bytes in the\n   uncompressed data stream.  The whence parameter is defined as in lseek(2);\n   the value SEEK_END is not supported.\n\n     If the file is opened for reading, this function is emulated but can be\n   extremely slow.  If the file is opened for writing, only forward seeks are\n   supported; gzseek then compresses a sequence of zeroes up to the new\n   starting position.\n\n     gzseek returns the resulting offset location as measured in bytes from\n   the beginning of the uncompressed stream, or -1 in case of error, in\n   particular if the file is opened for writing and the new starting position\n   would be before the current position.\n*/\n\nZEXTERN int ZEXPORT    gzrewind OF((gzFile file));\n/*\n     Rewinds the given file. This function is supported only for reading.\n\n     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)\n*/\n\n/*\nZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));\n\n     Returns the starting position for the next gzread or gzwrite on the given\n   compressed file.  This position represents a number of bytes in the\n   uncompressed data stream, and is zero when starting, even if appending or\n   reading a gzip stream from the middle of a file using gzdopen().\n\n     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)\n*/\n\n/*\nZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));\n\n     Returns the current offset in the file being read or written.  This offset\n   includes the count of bytes that precede the gzip stream, for example when\n   appending or when using gzdopen() for reading.  When reading, the offset\n   does not include as yet unused buffered input.  This information can be used\n   for a progress indicator.  On error, gzoffset() returns -1.\n*/\n\nZEXTERN int ZEXPORT gzeof OF((gzFile file));\n/*\n     Returns true (1) if the end-of-file indicator has been set while reading,\n   false (0) otherwise.  Note that the end-of-file indicator is set only if the\n   read tried to go past the end of the input, but came up short.  Therefore,\n   just like feof(), gzeof() may return false even if there is no more data to\n   read, in the event that the last read request was for the exact number of\n   bytes remaining in the input file.  This will happen if the input file size\n   is an exact multiple of the buffer size.\n\n     If gzeof() returns true, then the read functions will return no more data,\n   unless the end-of-file indicator is reset by gzclearerr() and the input file\n   has grown since the previous end of file was detected.\n*/\n\nZEXTERN int ZEXPORT gzdirect OF((gzFile file));\n/*\n     Returns true (1) if file is being copied directly while reading, or false\n   (0) if file is a gzip stream being decompressed.\n\n     If the input file is empty, gzdirect() will return true, since the input\n   does not contain a gzip stream.\n\n     If gzdirect() is used immediately after gzopen() or gzdopen() it will\n   cause buffers to be allocated to allow reading the file to determine if it\n   is a gzip file.  Therefore if gzbuffer() is used, it should be called before\n   gzdirect().\n\n     When writing, gzdirect() returns true (1) if transparent writing was\n   requested (\"wT\" for the gzopen() mode), or false (0) otherwise.  (Note:\n   gzdirect() is not needed when writing.  Transparent writing must be\n   explicitly requested, so the application already knows the answer.  When\n   linking statically, using gzdirect() will include all of the zlib code for\n   gzip file reading and decompression, which may not be desired.)\n*/\n\nZEXTERN int ZEXPORT    gzclose OF((gzFile file));\n/*\n     Flushes all pending output if necessary, closes the compressed file and\n   deallocates the (de)compression state.  Note that once file is closed, you\n   cannot call gzerror with file, since its structures have been deallocated.\n   gzclose must not be called more than once on the same file, just as free\n   must not be called more than once on the same allocation.\n\n     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a\n   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the\n   last read ended in the middle of a gzip stream, or Z_OK on success.\n*/\n\nZEXTERN int ZEXPORT gzclose_r OF((gzFile file));\nZEXTERN int ZEXPORT gzclose_w OF((gzFile file));\n/*\n     Same as gzclose(), but gzclose_r() is only for use when reading, and\n   gzclose_w() is only for use when writing or appending.  The advantage to\n   using these instead of gzclose() is that they avoid linking in zlib\n   compression or decompression code that is not used when only reading or only\n   writing respectively.  If gzclose() is used, then both compression and\n   decompression code will be included the application when linking to a static\n   zlib library.\n*/\n\nZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));\n/*\n     Returns the error message for the last error which occurred on the given\n   compressed file.  errnum is set to zlib error number.  If an error occurred\n   in the file system and not in the compression library, errnum is set to\n   Z_ERRNO and the application may consult errno to get the exact error code.\n\n     The application must not modify the returned string.  Future calls to\n   this function may invalidate the previously returned string.  If file is\n   closed, then the string previously returned by gzerror will no longer be\n   available.\n\n     gzerror() should be used to distinguish errors from end-of-file for those\n   functions above that do not distinguish those cases in their return values.\n*/\n\nZEXTERN void ZEXPORT gzclearerr OF((gzFile file));\n/*\n     Clears the error and end-of-file flags for file.  This is analogous to the\n   clearerr() function in stdio.  This is useful for continuing to read a gzip\n   file that is being written concurrently.\n*/\n\n#endif /* !Z_SOLO */\n\n                        /* checksum functions */\n\n/*\n     These functions are not related to compression but are exported\n   anyway because they might be useful in applications using the compression\n   library.\n*/\n\nZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));\n/*\n     Update a running Adler-32 checksum with the bytes buf[0..len-1] and\n   return the updated checksum.  If buf is Z_NULL, this function returns the\n   required initial value for the checksum.\n\n     An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed\n   much faster.\n\n   Usage example:\n\n     uLong adler = adler32(0L, Z_NULL, 0);\n\n     while (read_buffer(buffer, length) != EOF) {\n       adler = adler32(adler, buffer, length);\n     }\n     if (adler != original_adler) error();\n*/\n\nZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf,\n                                    z_size_t len));\n/*\n     Same as adler32(), but with a size_t length.\n*/\n\n/*\nZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,\n                                          z_off_t len2));\n\n     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1\n   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for\n   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of\n   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note\n   that the z_off_t type (like off_t) is a signed integer.  If len2 is\n   negative, the result has no meaning or utility.\n*/\n\nZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));\n/*\n     Update a running CRC-32 with the bytes buf[0..len-1] and return the\n   updated CRC-32.  If buf is Z_NULL, this function returns the required\n   initial value for the crc.  Pre- and post-conditioning (one's complement) is\n   performed within this function so it shouldn't be done by the application.\n\n   Usage example:\n\n     uLong crc = crc32(0L, Z_NULL, 0);\n\n     while (read_buffer(buffer, length) != EOF) {\n       crc = crc32(crc, buffer, length);\n     }\n     if (crc != original_crc) error();\n*/\n\nZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf,\n                                  z_size_t len));\n/*\n     Same as crc32(), but with a size_t length.\n*/\n\n/*\nZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));\n\n     Combine two CRC-32 check values into one.  For two sequences of bytes,\n   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were\n   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32\n   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and\n   len2.\n*/\n\n\n                        /* various hacks, don't look :) */\n\n/* deflateInit and inflateInit are macros to allow checking the zlib version\n * and the compiler's view of z_stream:\n */\nZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,\n                                     const char *version, int stream_size));\nZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,\n                                     const char *version, int stream_size));\nZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,\n                                      int windowBits, int memLevel,\n                                      int strategy, const char *version,\n                                      int stream_size));\nZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,\n                                      const char *version, int stream_size));\nZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,\n                                         unsigned char FAR *window,\n                                         const char *version,\n                                         int stream_size));\n#ifdef Z_PREFIX_SET\n#  define z_deflateInit(strm, level) \\\n          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define z_inflateInit(strm) \\\n          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \\\n          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\\\n                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define z_inflateInit2(strm, windowBits) \\\n          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \\\n                        (int)sizeof(z_stream))\n#  define z_inflateBackInit(strm, windowBits, window) \\\n          inflateBackInit_((strm), (windowBits), (window), \\\n                           ZLIB_VERSION, (int)sizeof(z_stream))\n#else\n#  define deflateInit(strm, level) \\\n          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define inflateInit(strm) \\\n          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \\\n          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\\\n                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define inflateInit2(strm, windowBits) \\\n          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \\\n                        (int)sizeof(z_stream))\n#  define inflateBackInit(strm, windowBits, window) \\\n          inflateBackInit_((strm), (windowBits), (window), \\\n                           ZLIB_VERSION, (int)sizeof(z_stream))\n#endif\n\n#ifndef Z_SOLO\n\n/* gzgetc() macro and its supporting function and exposed data structure.  Note\n * that the real internal state is much larger than the exposed structure.\n * This abbreviated structure exposes just enough for the gzgetc() macro.  The\n * user should not mess with these exposed elements, since their names or\n * behavior could change in the future, perhaps even capriciously.  They can\n * only be used by the gzgetc() macro.  You have been warned.\n */\nstruct gzFile_s {\n    unsigned have;\n    unsigned char *next;\n    z_off64_t pos;\n};\nZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */\n#ifdef Z_PREFIX_SET\n#  undef z_gzgetc\n#  define z_gzgetc(g) \\\n          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))\n#else\n#  define gzgetc(g) \\\n          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))\n#endif\n\n/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or\n * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if\n * both are true, the application gets the *64 functions, and the regular\n * functions are changed to 64 bits) -- in case these are set on systems\n * without large file support, _LFS64_LARGEFILE must also be true\n */\n#ifdef Z_LARGE64\n   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));\n   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));\n   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));\n   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));\n   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));\n   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));\n#endif\n\n#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)\n#  ifdef Z_PREFIX_SET\n#    define z_gzopen z_gzopen64\n#    define z_gzseek z_gzseek64\n#    define z_gztell z_gztell64\n#    define z_gzoffset z_gzoffset64\n#    define z_adler32_combine z_adler32_combine64\n#    define z_crc32_combine z_crc32_combine64\n#  else\n#    define gzopen gzopen64\n#    define gzseek gzseek64\n#    define gztell gztell64\n#    define gzoffset gzoffset64\n#    define adler32_combine adler32_combine64\n#    define crc32_combine crc32_combine64\n#  endif\n#  ifndef Z_LARGE64\n     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));\n     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));\n     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));\n     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));\n     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));\n     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));\n#  endif\n#else\n   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));\n   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));\n   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));\n   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));\n   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));\n   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));\n#endif\n\n#else /* Z_SOLO */\n\n   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));\n   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));\n\n#endif /* !Z_SOLO */\n\n/* undocumented functions */\nZEXTERN const char   * ZEXPORT zError           OF((int));\nZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));\nZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));\nZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));\nZEXTERN int            ZEXPORT inflateValidate OF((z_streamp, int));\nZEXTERN unsigned long  ZEXPORT inflateCodesUsed OF ((z_streamp));\nZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));\nZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));\n#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO)\nZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,\n                                            const char *mode));\n#endif\n#if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#  ifndef Z_SOLO\nZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,\n                                                  const char *format,\n                                                  va_list va));\n#  endif\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ZLIB_H */\n"
  },
  {
    "path": "in_vgm/README.md",
    "content": "# in_vgm Build Instructions\n\nIn order to build in_vgm you need to download the source of VGMPlay and extract it to `..\\VGMPlay\\`.\nThen you can open `in_vgm.dsw` with MS Visual C++ to compile it.\n\nin_vgm was made with MS VC++ 6. It should compile with later versions of MS Visual C++ too, but it will ask you to convert the project first.\n\n## Debug Build Notes\nTo make testing easier, the `in_vgm.dll` gets copied to the `Winamp\\Plugins` folder after the Debug build finished.\nYou may want to edit the post-build-command so that it fits with your Winamp PlugIn-directory.\n"
  },
  {
    "path": "in_vgm/Winamp/DSP.H",
    "content": "#ifndef NULLSOFT_WINAMP_DSP_H\n#define NULLSOFT_WINAMP_DSP_H\n// DSP plugin interface\n\n// notes:\n// any window that remains in foreground should optimally pass unused\n// keystrokes to the parent (winamp's) window, so that the user\n// can still control it. As for storing configuration,\n// Configuration data should be stored in <dll directory>\\plugin.ini\n// (look at the vis plugin for configuration code)\n\ntypedef struct winampDSPModule {\n  char *description;\t\t// description\n  HWND hwndParent;\t\t\t// parent window (filled in by calling app)\n  HINSTANCE hDllInstance;\t// instance handle to this DLL (filled in by calling app)\n\n  void (*Config)(struct winampDSPModule *this_mod);  // configuration dialog (if needed)\n  int (*Init)(struct winampDSPModule *this_mod);     // 0 on success, creates window, etc (if needed)\n\n  // modify waveform samples: returns number of samples to actually write\n  // (typically numsamples, but no more than twice numsamples, and no less than half numsamples)\n  // numsamples should always be at least 128. should, but I'm not sure\n  int (*ModifySamples)(struct winampDSPModule *this_mod, short int *samples, int numsamples, int bps, int nch, int srate);\n\t\t\t\n  void (*Quit)(struct winampDSPModule *this_mod);    // called when unloading\n\n  void *userData; // user data, optional\n} winampDSPModule;\n\ntypedef struct {\n  int version;       // DSP_HDRVER\n  char *description; // description of library\n  winampDSPModule* (*getModule)(int);\t// module retrieval function\n  int (*sf)(int key); // DSP_HDRVER == 0x21\n} winampDSPHeader;\n\n// exported symbols\n#ifdef USE_DSP_HDR_HWND\ntypedef winampDSPHeader* (*winampDSPGetHeaderType)(HWND);\n#define DSP_HDRVER 0x22\n\n#else\n\ntypedef winampDSPHeader* (*winampDSPGetHeaderType)(HWND);\n// header version: 0x20 == 0.20 == winamp 2.0\n#define DSP_HDRVER 0x20\n#endif\n\n// return values from the winampUninstallPlugin(HINSTANCE hdll, HWND parent, int param)\n// which determine if we can uninstall the plugin immediately or on winamp restart\n#define DSP_PLUGIN_UNINSTALL_NOW    0x0\n#define DSP_PLUGIN_UNINSTALL_REBOOT 0x1\n//\n// uninstall support was added from 5.0+ and uninstall now support from 5.5+\n// it is down to you to ensure that if uninstall now is returned that it will not cause a crash\n// (ie don't use if you've been subclassing the main window)\n\n// Version note:\n//\n// Added passing of Winamp's main hwnd in the call to the exported winampDSPHeader()\n// which allows for primarily the use of localisation features with the bundled plugins.\n// If you want to use the new version then either you can edit you version of dsp.h or\n// you can add USE_DSP_HDR_HWND to your project's defined list or before use of dsp.h\n//\n#endif"
  },
  {
    "path": "in_vgm/Winamp/GEN.H",
    "content": "#ifndef NULLSOFT_WINAMP_GEN_H\n#define NULLSOFT_WINAMP_GEN_H\n\n#include <windows.h>\n\n#define GEN_INIT_SUCCESS 0\n\n// return values from the winampUninstallPlugin(HINSTANCE hdll, HWND parent, int param)\n// which determine if we can uninstall the plugin immediately or on winamp restart\n//\n// uninstall support was added from 5.0+ and uninstall now support from 5.5+\n// it is down to you to ensure that if uninstall now is returned that it will not cause a crash\n// (ie don't use if you've been subclassing the main window)\n#define GEN_PLUGIN_UNINSTALL_NOW    0x1\n#define GEN_PLUGIN_UNINSTALL_REBOOT 0x0\n\ntypedef struct {\n\tint version;\n\tchar *description;\n\tint (*init)();\n\tvoid (*config)();\n\tvoid (*quit)();\n\tHWND hwndParent;\n\tHINSTANCE hDllInstance;\n} winampGeneralPurposePlugin;\n\n#define GPPHDR_VER 0x10\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n//extern winampGeneralPurposePlugin *gen_plugins[256];\ntypedef winampGeneralPurposePlugin * (*winampGeneralPurposePluginGetter)();\n#ifdef __cplusplus\n}\n#endif\n\n#endif"
  },
  {
    "path": "in_vgm/Winamp/IN2.H",
    "content": "\n#ifndef NULLSOFT_WINAMP_IN2H\n#define NULLSOFT_WINAMP_IN2H\n#include \"out.h\"\n\n// note: exported symbol is now winampGetInModule2.\n\n#define IN_UNICODE 0x0F000000\n\n#ifdef UNICODE_INPUT_PLUGIN\n#define in_char wchar_t\n#define IN_VER (IN_UNICODE | 0x100)\n#else\n#define in_char char\n#define IN_VER 0x100\n#endif\n\n#define IN_MODULE_FLAG_USES_OUTPUT_PLUGIN 1\n// By default, Winamp assumes that your input plugin wants to use Winamp's EQ, and doesn't do replay gain\n// if you handle any of these yourself (EQ, Replay Gain adjustments), then set these flags accordingly\n#define IN_MODULE_FLAG_EQ 2 // set this if you do your own EQ\n#define IN_MODULE_FLAG_REPLAYGAIN 8 // set this if you adjusted volume for replay gain\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// for tracks with no replay gain metadata, you should clear this flag \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// UNLESS you handle \"non_replaygain\" gain adjustment yourself\n#define IN_MODULE_FLAG_REPLAYGAIN_PREAMP 16 // use this if you queried for the replay gain preamp parameter and used it \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// this parameter is new to 5.54\ntypedef struct \n{\n\tint version;\t\t\t\t// module type (IN_VER)\n\tchar *description;\t\t\t// description of module, with version string\n\n\tHWND hMainWindow;\t\t\t// winamp's main window (filled in by winamp)\n\tHINSTANCE hDllInstance;\t\t// DLL instance handle (Also filled in by winamp)\n\n\tchar *FileExtensions;\t\t// \"mp3\\0Layer 3 MPEG\\0mp2\\0Layer 2 MPEG\\0mpg\\0Layer 1 MPEG\\0\"\n\t\t\t\t\t\t\t\t// May be altered from Config, so the user can select what they want\n\t\n\tint is_seekable;\t\t\t// is this stream seekable? \n\tint UsesOutputPlug;\t\t\t// does this plug-in use the output plug-ins? (musn't ever change, ever :)\n\t\t\t\t\t\t\t\t\t\t\t\t\t// note that this has turned into a \"flags\" field\n\t\t\t\t\t\t\t\t\t\t\t\t\t// see IN_MODULE_FLAG_*\n\n\tvoid (*Config)(HWND hwndParent); // configuration dialog\n\tvoid (*About)(HWND hwndParent);  // about dialog\n\n\tvoid (*Init)();\t\t\t\t// called at program init\n\tvoid (*Quit)();\t\t\t\t// called at program quit\n\n#define GETFILEINFO_TITLE_LENGTH 2048 \n\tvoid (*GetFileInfo)(const in_char *file, in_char *title, int *length_in_ms); // if file == NULL, current playing is used\n\n#define INFOBOX_EDITED 0\n#define INFOBOX_UNCHANGED 1\n\tint (*InfoBox)(const in_char *file, HWND hwndParent);\n\t\n\tint (*IsOurFile)(const in_char *fn);\t// called before extension checks, to allow detection of mms://, etc\n\t// playback stuff\n\tint (*Play)(const in_char *fn);\t\t// return zero on success, -1 on file-not-found, some other value on other (stopping winamp) error\n\tvoid (*Pause)();\t\t\t// pause stream\n\tvoid (*UnPause)();\t\t\t// unpause stream\n\tint (*IsPaused)();\t\t\t// ispaused? return 1 if paused, 0 if not\n\tvoid (*Stop)();\t\t\t\t// stop (unload) stream\n\n\t// time stuff\n\tint (*GetLength)();\t\t\t// get length in ms\n\tint (*GetOutputTime)();\t\t// returns current output time in ms. (usually returns outMod->GetOutputTime()\n\tvoid (*SetOutputTime)(int time_in_ms);\t// seeks to point in stream (in ms). Usually you signal your thread to seek, which seeks and calls outMod->Flush()..\n\n\t// volume stuff\n\tvoid (*SetVolume)(int volume);\t// from 0 to 255.. usually just call outMod->SetVolume\n\tvoid (*SetPan)(int pan);\t// from -127 to 127.. usually just call outMod->SetPan\n\t\n\t// in-window builtin vis stuff\n\n\tvoid (*SAVSAInit)(int maxlatency_in_ms, int srate);\t\t// call once in Play(). maxlatency_in_ms should be the value returned from outMod->Open()\n\t// call after opening audio device with max latency in ms and samplerate\n\tvoid (*SAVSADeInit)();\t// call in Stop()\n\n\n\t// simple vis supplying mode\n\tvoid (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); \n\t\t\t\t\t\t\t\t\t\t\t// sets the spec data directly from PCM data\n\t\t\t\t\t\t\t\t\t\t\t// quick and easy way to get vis working :)\n\t\t\t\t\t\t\t\t\t\t\t// needs at least 576 samples :)\n\n\t// advanced vis supplying mode, only use if you're cool. Use SAAddPCMData for most stuff.\n\tint (*SAGetMode)();\t\t// gets csa (the current type (4=ws,2=osc,1=spec))\n\t\t\t\t\t\t\t// use when calling SAAdd()\n\tint (*SAAdd)(void *data, int timestamp, int csa); // sets the spec data, filled in by winamp\n\n\n\t// vis stuff (plug-in)\n\t// simple vis supplying mode\n\tvoid (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); // sets the vis data directly from PCM data\n\t\t\t\t\t\t\t\t\t\t\t// quick and easy way to get vis working :)\n\t\t\t\t\t\t\t\t\t\t\t// needs at least 576 samples :)\n\n\t// advanced vis supplying mode, only use if you're cool. Use VSAAddPCMData for most stuff.\n\tint (*VSAGetMode)(int *specNch, int *waveNch); // use to figure out what to give to VSAAdd\n\tint (*VSAAdd)(void *data, int timestamp); // filled in by winamp, called by plug-in\n\n\n\t// call this in Play() to tell the vis plug-ins the current output params. \n\tvoid (*VSASetInfo)(int srate, int nch); // <-- Correct (benski, dec 2005).. old declaration had the params backwards\n\n\n\t// dsp plug-in processing: \n\t// (filled in by winamp, calld by input plug)\n\n\t// returns 1 if active (which means that the number of samples returned by dsp_dosamples\n\t// could be greater than went in.. Use it to estimate if you'll have enough room in the\n\t// output buffer\n\tint (*dsp_isactive)(); \n\n\t// returns number of samples to output. This can be as much as twice numsamples. \n\t// be sure to allocate enough buffer for samples, then.\n\tint (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate);\n\n\n\t// eq stuff\n\tvoid (*EQSet)(int on, char data[10], int preamp); // 0-64 each, 31 is +0, 0 is +12, 63 is -12. Do nothing to ignore.\n\n\t// info setting (filled in by winamp)\n\tvoid (*SetInfo)(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :)\n\n\tOut_Module *outMod; // filled in by winamp, optionally used :)\n} In_Module;\n\n// return values from the winampUninstallPlugin(HINSTANCE hdll, HWND parent, int param)\n// which determine if we can uninstall the plugin immediately or on winamp restart\n//\n// uninstall support was added from 5.0+ and uninstall now support from 5.5+\n// it is down to you to ensure that if uninstall now is returned that it will not cause a crash\n// (ie don't use if you've been subclassing the main window)\n#define IN_PLUGIN_UNINSTALL_NOW    0x1\n#define IN_PLUGIN_UNINSTALL_REBOOT 0x0\n\n#endif"
  },
  {
    "path": "in_vgm/Winamp/OUT.H",
    "content": "#ifndef NULLSOFT_OUTH\n#define NULLSOFT_OUTH\n#include <windows.h>\n#include <stddef.h>\n// ids:\n// waveout: 32\n// gapless: 64\n// xfade: 63\n// disk: 33\n// dsound: 38\n// NULL: 65\n// mm2: 69\n\n#if (_MSC_VER <= 1200)\ntypedef int intptr_t;\n#endif\n\n#define OUT_VER 0x10\n\ntypedef struct \n{\n\tint version;\t\t\t\t// module version (OUT_VER)\n\tchar *description;\t\t\t// description of module, with version string\n\tintptr_t id;\t\t\t\t\t\t// module id. each input module gets its own. non-nullsoft modules should\n\t\t\t\t\t\t\t\t// be >= 65536. \n\n\tHWND hMainWindow;\t\t\t// winamp's main window (filled in by winamp)\n\tHINSTANCE hDllInstance;\t\t// DLL instance handle (filled in by winamp)\n\n\tvoid (*Config)(HWND hwndParent); // configuration dialog \n\tvoid (*About)(HWND hwndParent);  // about dialog\n\n\tvoid (*Init)();\t\t\t\t// called when loaded\n\tvoid (*Quit)();\t\t\t\t// called when unloaded\n\n\tint (*Open)(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms); \n\t\t\t\t\t// returns >=0 on success, <0 on failure\n\n\t\t\t\t\t// NOTENOTENOTE: bufferlenms and prebufferms are ignored in most if not all output plug-ins. \n\t\t\t\t\t//    ... so don't expect the max latency returned to be what you asked for.\n\t\t\t\t\t// returns max latency in ms (0 for diskwriters, etc)\n\t\t\t\t\t// bufferlenms and prebufferms must be in ms. 0 to use defaults. \n\t\t\t\t\t// prebufferms must be <= bufferlenms\n\t\t\t\t\t// pass bufferlenms==-666 to tell the output plugin that it's clock is going to be used to sync video\n\t\t\t\t\t//   out_ds turns off silence-eating when -666 is passed\n\n\tvoid (*Close)();\t// close the ol' output device.\n\n\tint (*Write)(char *buf, int len);\t\n\t\t\t\t\t// 0 on success. Len == bytes to write (<= 8192 always). buf is straight audio data. \n\t\t\t\t\t// 1 returns not able to write (yet). Non-blocking, always.\n\n\tint (*CanWrite)();\t// returns number of bytes possible to write at a given time. \n\t\t\t\t\t\t// Never will decrease unless you call Write (or Close, heh)\n\n\tint (*IsPlaying)(); // non0 if output is still going or if data in buffers waiting to be\n\t\t\t\t\t\t// written (i.e. closing while IsPlaying() returns 1 would truncate the song\n\n\tint (*Pause)(int pause); // returns previous pause state\n\n\tvoid (*SetVolume)(int volume); // volume is 0-255\n\tvoid (*SetPan)(int pan); // pan is -128 to 128\n\n\tvoid (*Flush)(int t);\t// flushes buffers and restarts output at time t (in ms) \n\t\t\t\t\t\t\t// (used for seeking)\n\n\tint (*GetOutputTime)(); // returns played time in MS\n\tint (*GetWrittenTime)(); // returns time written in MS (used for synching up vis stuff)\n\n} Out_Module;\n\n\n#endif"
  },
  {
    "path": "in_vgm/Winamp/ipc_pe.h",
    "content": "#ifndef __IPC_PE_H\n#define __IPC_PE_H\n\n#define IPC_PE_GETCURINDEX        100 // returns current idx\n#define IPC_PE_GETINDEXTOTAL      101 // returns number of items \n#define IPC_PE_GETINDEXINFO       102 // (copydata) lpData is of type callbackinfo, callback is called with copydata/fileinfo structure and msg IPC_PE_GETINDEXINFORESULT\n#define IPC_PE_GETINDEXINFORESULT 103 // callback message for IPC_PE_GETINDEXINFO\n#define IPC_PE_DELETEINDEX        104 // lParam = index\n#define IPC_PE_SWAPINDEX          105 // (lParam & 0xFFFF0000) >> 16 = from, (lParam & 0xFFFF) = to\n#define IPC_PE_INSERTFILENAME     106 // (copydata) lpData is of type fileinfo\n#define IPC_PE_GETDIRTY           107 // returns 1 if the playlist changed since the last IPC_PE_SETCLEAN\n#define IPC_PE_SETCLEAN\t          108 // resets the dirty flag until next modification\n#define IPC_PE_GETIDXFROMPOINT    109 // pass a point parm, return a playlist index\n#define IPC_PE_SAVEEND            110 // pass index to save from\n#define IPC_PE_RESTOREEND         111 // no parm\n#define IPC_PE_GETNEXTSELECTED    112 // same as IPC_PLAYLIST_GET_NEXT_SELECTED for the main window\n#define IPC_PE_GETSELECTEDCOUNT   113\n#define IPC_PE_INSERTFILENAMEW  114 // (copydata) lpData is of type fileinfoW\n#define IPC_PE_GETINDEXINFO_TITLE 115 // like IPC_PE_GETINDEXINFO, but writes the title to char file[MAX_PATH] instead of filename\n#define IPC_PE_GETINDEXINFORESULT_TITLE 116 // callback message for IPC_PE_GETINDEXINFO\ntypedef struct {\n\tchar file[MAX_PATH];\n\tint index;\n\t} fileinfo;\n\ntypedef struct {\n\twchar_t file[MAX_PATH];\n\tint index;\n\t} fileinfoW;\n\ntypedef struct {\n\tHWND callback;\n\tint index;\n\t} callbackinfo;\n\n// the following messages are in_process ONLY\n\n#define IPC_PE_GETINDEXTITLE      200 // lParam = pointer to fileinfo2 struct\n#define IPC_PE_GETINDEXTITLEW      201 // lParam = pointer to fileinfo2W struct\n#define IPC_PE_GETINDEXINFO_INPROC      202 // lParam = pointer to fileinfo struct\n#define IPC_PE_GETINDEXINFOW_INPROC      203 // lParam = pointer to fileinfoW struct\n\ntypedef struct {\n  int fileindex;\n  char filetitle[256];\n  char filelength[16];\n  } fileinfo2;\n\ntypedef struct\n{\n  int fileindex;\n  wchar_t filetitle[256];\n  wchar_t filelength[16];\n  } fileinfo2W;\n\n#endif"
  },
  {
    "path": "in_vgm/Winamp/wa_dlg.h",
    "content": "/*\n** Copyright (C) 2003-2008 Nullsoft, Inc.\n**\n** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held \n** liable for any damages arising from the use of this software. \n**\n** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to \n** alter it and redistribute it freely, subject to the following restrictions:\n**\n**   1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. \n**      If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n**\n**   2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n**\n**   3. This notice may not be removed or altered from any source distribution.\n**\n*/\n\n#ifndef _WA_DLG_H_\n#define _WA_DLG_H_\n\n#include \"wa_ipc.h\"\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n/*\n       1) gen.bmp has a generic window frame for plugins to use.\n          its format is similar to the minibrowser's.\n          In addition gen.bmp includes a font for the titlebar, in both\n          highlight and no-highlight modes. The font is variable width,\n          and it uses the first color before the letter A as the delimiter.\n          The no-highlight form of letter must be the same width as the\n          highlight form.\n       2) genex.bmp has button and scrollbar images, as well as some individual\n          pixels that describe the colors for the dialog. The button and\n          scrollbar images should be self explanatory (note that the buttons\n          have 4 pixel sized edges that are not stretched, and the center is\n          stretched), and the scrollbars do something similar.\n          The colors start at (48,0) and run every other pixel. The meaning\n          of each pixel is:\n            x=48: item background (background to edits, listviews etc)\n            x=50: item foreground (text color of edit/listview, etc)\n            x=52: window background (used to set the bg color for the dialog)\n            x=54: button text color\n            x=56: window text color\n            x=58: color of dividers and sunken borders\n            x=60: selection color for playlists\n            x=62: listview header background color\n            x=64: listview header text color\n            x=66: listview header frame top color\n            x=68: listview header frame middle color\n            x=70: listview header frame bottom color\n            x=72: listview header empty color\n            x=74: scrollbar foreground color\n            x=76: scrollbar background color\n            x=78: inverse scrollbar foreground color\n            x=80: inverse scrollbar background color\n            x=82: scrollbar dead area color\n            x=84: listview/treeview selection bar text color (active)\n            x=86: listview/treeview selection bar back color (active)\n            x=88: listview/treeview selection bar text color (inactive)\n            x=90: listview/treeview selection bar back color (inactive)\n\t\t\tx=92: alternate item background\n\t\t\tx=94: alternate item foreground\n*/\n\n#define DCW_SUNKENBORDER 0x00010000\n#define DCW_DIVIDER 0x00020000\n\nenum\n{\n  WADLG_ITEMBG,\n  WADLG_ITEMFG,\n  WADLG_WNDBG,\n  WADLG_BUTTONFG,\n  WADLG_WNDFG,\n  WADLG_HILITE,\n  WADLG_SELCOLOR,\n  WADLG_LISTHEADER_BGCOLOR,\n  WADLG_LISTHEADER_FONTCOLOR,\n  WADLG_LISTHEADER_FRAME_TOPCOLOR,\n  WADLG_LISTHEADER_FRAME_MIDDLECOLOR,\n  WADLG_LISTHEADER_FRAME_BOTTOMCOLOR,\n  WADLG_LISTHEADER_EMPTY_BGCOLOR,\n  WADLG_SCROLLBAR_FGCOLOR,\n  WADLG_SCROLLBAR_BGCOLOR,\n  WADLG_SCROLLBAR_INV_FGCOLOR,\n  WADLG_SCROLLBAR_INV_BGCOLOR,\n  WADLG_SCROLLBAR_DEADAREA_COLOR,\n  WADLG_SELBAR_FGCOLOR,\n  WADLG_SELBAR_BGCOLOR,\n  WADLG_INACT_SELBAR_FGCOLOR,\n  WADLG_INACT_SELBAR_BGCOLOR,\n  WADLG_ITEMBG2,\n  WADLG_ITEMFG2,\n  WADLG_NUM_COLORS\n};\n\ntypedef enum _WACURSOR  // used in IPC_GETSKINCURSORS\n{\n\tWACURSOR_VOLUME\t= 0,\t\t// volume & balane\n\tWACURSOR_POSITION = 1,\t\t// position\n\tWACURSOR_BTN_WINSHADE = 2,\t// winshade\n\tWACURSOR_BTN_MINIMIZE = 3,\t// minimize\n\tWACURSOR_BTN_CLOSE = 4,\t\t// close\n\tWACURSOR_MENU = \t5,\t\t\t// main menu\n\tWACURSOR_TITLEBAR = 6,\t\t// title bar\n\tWACURSOR_SONGNAME = 7,\t\t\n\tWACURSOR_NORMAL = 8,\n\tWACURSOR_WINSHADE_BTN_WINSHADE = 9,\n\tWACURSOR_WINSHADE_BTN_MINIMIZE = 10,\n\tWACURSOR_WINSHADE_POSITION = 11,\n\tWACURSOR_WINSHADE_BTN_CLOSE = 12,\n\tWACURSOR_WINSHADE_MENU = 13,\n\tWACURSOR_WINSHADE_NORMAL = 14,\n\tWACURSOR_PL_BTN_WINSHADE = 15,\n\tWACURSOR_PL_BTN_CLOSE = 16,\n\tWACURSOR_PL_TITLEBAR = 17,\n\tWACURSOR_PL_VSCROLL = 18,\n\tWACURSOR_PL_RESIZE = 19,\n\tWACURSOR_PL_NORMAL = 20,\n\tWACURSOR_PL_WINSHADE_BTN_WINSHADE = 21,\n\tWACURSOR_PL_WINSHADE_BTN_CLOSE = 22,\n\tWACURSOR_PL_WINSHADE_HSIZE = 23,\n\tWACURSOR_PL_WINSHADE_NORMAL = 24,\n\tWACURSOR_EQ_SLIDER = 25,\n\tWACURSOR_EQ_BTN_CLOSE = 26,\n\tWACURSOR_EQ_TITLEBAR = 27,\n\tWACURSOR_EQ_NORMAL = 28,\n} WACURSOR;\n\nvoid WADlg_init(HWND hwndWinamp); // call this on init, or on WM_DISPLAYCHANGE\nvoid WADlg_close();\nint WADlg_getColor(int idx);\nint WADlg_initted();\n\nLRESULT WADlg_handleDialogMsgs(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); //\nvoid WADlg_DrawChildWindowBorders(HWND hwndDlg, int *tab, int tabsize); // each entry in tab would be the id | DCW_*\n\nHBITMAP WADlg_getBitmap();\n\n/// define WA_DLG_IMPLEMENT in one of your source files before including this .h\n// if you are making a media library plugin, you dont need to do this, look at view_ex for \n// an example of how to get the function *'s via an IPC message.\n#ifdef __cplusplus\n}\n#endif\n\n#ifdef WA_DLG_IMPLEMENT\n\nstatic HBRUSH wadlg_lastbrush=0;\nstatic HBITMAP wadlg_bitmap=0; // load this manually\nstatic int wadlg_colors[WADLG_NUM_COLORS];\nstatic int wadlg_defcolors[WADLG_NUM_COLORS]=\n{\n\tRGB(0,0,0),\n\tRGB(0,255,0),\n\tRGB(36,36,60),\n\tRGB(57,56,66),\n\tRGB(255,255,255),\n\tRGB(132,148,165),  \n\tRGB(0,0,198),\n\tRGB(36*2,36*2,60*2),\n\tRGB(255,255,255),\n\tRGB(36*3,36*3,60*3),\n\tRGB(36,36,60),\n\tRGB(36*0.5,36*0.5,60*0.5),\n\tRGB(36,36,60),\n\tRGB(36*1,36*1,60*1),\n\tRGB(36*1,36*1,60*1),\n\tRGB(121,130,150),\n\tRGB(78,88,110),\n\tRGB(36*1,36*1,60*1),\n\tRGB(255,255,255),\n\tRGB(0,0,180),\n\tRGB(0,255,0),\n\tRGB(0,0,128),\n\tRGB(0,0,0),\n\tRGB(0,255,0),\n};\n\nint WADlg_initted()\n{\n\treturn !!wadlg_bitmap;\n}\n\nint WADlg_getColor(int idx)\n{\n\tif (idx < 0 || idx >= WADLG_NUM_COLORS) return 0;\n\treturn wadlg_colors[idx];\n}\n\nHBITMAP WADlg_getBitmap()\n{\n\treturn wadlg_bitmap;\n}\n\nvoid WADlg_init(HWND hwndWinamp) // call this on init, or on WM_DISPLAYCHANGE\n{\n\tif (wadlg_bitmap) DeleteObject(wadlg_bitmap);\n\twadlg_bitmap = (HBITMAP) SendMessage(hwndWinamp,WM_WA_IPC,0,IPC_GET_GENSKINBITMAP);\n\tif (wadlg_bitmap)\n\t{\n\t\tHDC tmpDC=CreateCompatibleDC(NULL);\n\t\tHGDIOBJ o=SelectObject(tmpDC,(HGDIOBJ)wadlg_bitmap);\n\t\tint defbgcol=GetPixel(tmpDC,111,0);\n\t\tfor (int x = 0; x < WADLG_NUM_COLORS; x ++)\n\t\t{\n\t\t\tint a=GetPixel(tmpDC,48+x*2,0);\n\t\t\tif (a == CLR_INVALID || a == RGB(0,198,255) || a == defbgcol) \n\t\t\t{\n\t\t\t\t//defaults for old skins\n\t\t\t\tif (x == WADLG_SELBAR_FGCOLOR || x == WADLG_INACT_SELBAR_FGCOLOR) a=wadlg_colors[WADLG_WNDFG];\n\t\t\t\telse if (x == WADLG_SELBAR_BGCOLOR || x == WADLG_INACT_SELBAR_BGCOLOR) \n\t\t\t\t{\n\t\t\t\t\ta=wadlg_colors[WADLG_SELCOLOR];\n\t\t\t\t\tif (x == WADLG_INACT_SELBAR_BGCOLOR)\n\t\t\t\t\ta=((a/2)&0x7F7F7F)+(((wadlg_colors[WADLG_WNDBG])/2)&0x7F7F7F);\n\t\t\t\t}\n\t\t\t\telse if (x == WADLG_ITEMBG2)\n\t\t\t\t{\n\t\t\t\t\ta=wadlg_colors[WADLG_ITEMBG];\n\t\t\t\t}\n\t\t\t\telse if (x == WADLG_ITEMFG2)\n\t\t\t\t{\n\t\t\t\t\ta=wadlg_colors[WADLG_ITEMFG];\n\t\t\t\t}\n\t\t\t\telse a=wadlg_defcolors[x];\n\t\t\t}\n\t\t\twadlg_colors[x]=a;\n\t\t}\n\n\t\tSelectObject(tmpDC,o);\n\t\tDeleteDC(tmpDC);\n\t}\n}\n\nvoid WADlg_close()\n{\n\tif (wadlg_bitmap) DeleteObject(wadlg_bitmap);\n\twadlg_bitmap=0;\n\tif (wadlg_lastbrush) DeleteObject(wadlg_lastbrush);\n\twadlg_lastbrush=0;\n}\n\nvoid WADlg_dotLine(HDC hdc, int left, int top, int len, int vert)\n{\n\tfor(int i=(top&1);i<len-1;i+=2)\n\t{\n\t    if(vert)\n\t\t{\n\t\t\tMoveToEx(hdc,left,top+i,NULL);\n\t\t\tLineTo(hdc,left,top+i+1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tMoveToEx(hdc,left+i,top,NULL);\n\t\t\tLineTo(hdc,left+i+1,top);\n\t\t}\n\t}\n}\n\nLRESULT WADlg_handleDialogMsgs(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)\n{\n\tif (uMsg == WM_DRAWITEM)\n\t{\n\t\tDRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam;\n\t\tif (di->CtlType == ODT_BUTTON) {\n\t\t\twchar_t wt[256];\n\t\t\tRECT r;\n\t\t\tGetDlgItemTextW(hwndDlg,(INT)wParam,wt,sizeof(wt)/sizeof(*wt));\n\n\t\t\tHDC hdc = CreateCompatibleDC(di->hDC);\n\t\t\tHBITMAP hbmpOld = (HBITMAP)SelectObject(hdc, wadlg_bitmap);\n\n\t\t\tr=di->rcItem;\n\t\t\tSetStretchBltMode(di->hDC,COLORONCOLOR);\n\n\t\t\tint yoffs = (di->itemState & ODS_SELECTED) ? 15 : 0;\n\n\t\t\tBitBlt(di->hDC,r.left,r.top,4,4,hdc,0,yoffs,SRCCOPY); // top left\n\t\t\tStretchBlt(di->hDC,r.left+4,r.top,r.right-r.left-4-4,4,hdc,4,yoffs,47-4-4,4,SRCCOPY); // top center\n\t\t\tBitBlt(di->hDC,r.right-4,r.top,4,4,hdc,47-4,yoffs,SRCCOPY); // top right\n\n\t\t\tStretchBlt(di->hDC,r.left,r.top+4,4,r.bottom-r.top-4-4,hdc,0,4+yoffs,4,15-4-4,SRCCOPY); // left edge\n\t\t\tStretchBlt(di->hDC,r.right-4,r.top+4,4,r.bottom-r.top-4-4,hdc,47-4,4+yoffs,4,15-4-4,SRCCOPY); // right edge\n\n\t\t\t// center\n\t\t\tStretchBlt(di->hDC,r.left+4,r.top+4,r.right-r.left-4-4,r.bottom-r.top-4-4,hdc,4,4+yoffs,47-4-4,15-4-4,SRCCOPY);\n\n\t\t\tBitBlt(di->hDC,r.left,r.bottom-4,4,4,hdc,0,15-4+yoffs,SRCCOPY); // bottom left\n\t\t\tStretchBlt(di->hDC,r.left+4,r.bottom-4,r.right-r.left-4-4,4,hdc,4,15-4+yoffs,47-4-4,4,SRCCOPY); // bottom center\n\t\t\tBitBlt(di->hDC,r.right-4,r.bottom-4,4,4,hdc,47-4,15-4+yoffs,SRCCOPY); // bottom right\n\n\t\t\t// draw text\n\t\t\tSetBkMode(di->hDC,TRANSPARENT);\n\n\t\t\t// this will do a different style for the button text depending on enabled state of the button\n\t\t\tCOLORREF colour = wadlg_colors[WADLG_BUTTONFG];\n\t\t\tif(!IsWindowEnabled(di->hwndItem)){\n\t\t\t\tCOLORREF fg = wadlg_colors[WADLG_WNDFG],\n\t\t\t\t\t\t bg = wadlg_colors[WADLG_WNDBG];\n\t\t\t\t\t\t colour = RGB((GetRValue(fg)+GetRValue(bg))/2,\n\t\t\t\t\t\t\t\t\t  (GetGValue(fg)+GetGValue(bg))/2,\n\t\t\t\t\t\t\t\t\t  (GetBValue(fg)+GetBValue(bg))/2);\n\t\t\t}\n\t\t\tSetTextColor(di->hDC,colour);\n\t\t\n\t\t\tif (di->itemState & ODS_SELECTED) {r.left+=2; r.top+=2;}\n\t\t\tDrawTextW(di->hDC,wt,-1,&r,DT_VCENTER|DT_SINGLELINE|DT_CENTER);\n\t  \n\t\t\tSelectObject(hdc, hbmpOld);\n\t\t\tDeleteDC(hdc);\n\n\t\t\tif(GetFocus()==di->hwndItem) {\n\t\t\t\tHPEN hpen, hpenOld;\n\t\t\t\thpen =CreatePen(PS_SOLID,0,RGB(0,0,0));\n\t\t\t\thpenOld = (HPEN)SelectObject(di->hDC, hpen);\n\t\t\t\tWADlg_dotLine(di->hDC,r.left+2,r.top+2,r.right-r.left-3,0);\n\t\t\t\tWADlg_dotLine(di->hDC,r.right-3,r.top+2,r.bottom-r.top-3,1);\n\t\t\t\tWADlg_dotLine(di->hDC,r.left+2,r.top+2,r.bottom-r.top-3,1);\n\t\t\t\tWADlg_dotLine(di->hDC,r.left+2,r.bottom-3,r.right-r.left-3,0);\n\t\t\t\tSelectObject(di->hDC, hpenOld);\n\t\t\t\tDeleteObject(hpen);\n\t\t\t}\n\t\t}\t\n\t}\n\n\tswitch(uMsg) \n\t{\n\t\tcase WM_CTLCOLORLISTBOX:\n\t\tcase WM_CTLCOLORDLG:\n\t\tcase WM_CTLCOLORBTN:\n\t\tcase WM_CTLCOLORSTATIC:\n\t\tcase WM_CTLCOLOREDIT:\n\t\t{\n\t\t\tint bgcolor=(uMsg == WM_CTLCOLOREDIT || uMsg == WM_CTLCOLORLISTBOX) ? wadlg_colors[WADLG_ITEMBG] : (uMsg == WM_CTLCOLORBTN ? wadlg_colors[WADLG_ITEMBG] : wadlg_colors[WADLG_WNDBG]);\n\t\t\tLOGBRUSH lb={BS_SOLID,GetNearestColor((HDC)wParam,bgcolor)};\n\t\t\tif (wadlg_lastbrush) DeleteObject(wadlg_lastbrush);\n\t\t\twadlg_lastbrush=CreateBrushIndirect(&lb);\n\t\t\tSetTextColor((HDC)wParam,uMsg == WM_CTLCOLORSTATIC ? wadlg_colors[WADLG_WNDFG] : wadlg_colors[WADLG_ITEMFG]);\n\t\t\tSetBkColor((HDC)wParam,lb.lbColor);\n\t\t\treturn (LRESULT)wadlg_lastbrush;\n\t\t}\n\t}\n\treturn 0;\n}\n\nstatic int RectInRect(RECT *rect1, RECT *rect2)\n{ \n  // this has a bias towards true\n\n  // this could probably be optimized a lot\n  return ((rect1->top >= rect2->top && rect1->top <= rect2->bottom) ||\n      (rect1->bottom >= rect2->top && rect1->bottom <= rect2->bottom) ||\n      (rect2->top >= rect1->top && rect2->top <= rect1->bottom) ||\n      (rect2->bottom >= rect1->top && rect2->bottom <= rect1->bottom)) // vertical intersect\n      &&\n      ((rect1->left >= rect2->left && rect1->left <= rect2->right) ||\n      (rect1->right >= rect2->left && rect1->right <= rect2->right) ||\n      (rect2->left >= rect1->left && rect2->left <= rect1->right) ||\n      (rect2->right >= rect1->left && rect2->right <= rect1->right)) // horiz intersect\n      ;\n}\n\nstatic void WADlg_removeFromRgn(HRGN hrgn, int left, int top, int right, int bottom)\n{\n\tHRGN rgn2=CreateRectRgn(left,top,right,bottom);\n\tCombineRgn(hrgn,hrgn,rgn2,RGN_DIFF);\n\tDeleteObject(rgn2);\n}\n\nvoid WADlg_DrawChildWindowBorders(HWND hwndDlg, int *tab, int tabsize)\n{\n\tPAINTSTRUCT ps;\n\tBeginPaint(hwndDlg,&ps);\n\tHRGN hrgn = (ps.fErase) ? CreateRectRgnIndirect(&ps.rcPaint) : NULL;\n\tHPEN pen = CreatePen(PS_SOLID, 0, wadlg_colors[WADLG_HILITE]);\n\tHGDIOBJ o = SelectObject(ps.hdc, pen);\n\n\twhile (tabsize--)\n\t{\n\t\tRECT r;\n\t\tint a = *tab++;\n\t\tGetWindowRect(GetDlgItem(hwndDlg, a & 0xffff),&r);\n\t\tMapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&r, 2);\n    \n\t\tif (RectInRect(&ps.rcPaint,&r)) \n\t\t{\n\t\t\tif ((a & 0xffff0000) == DCW_SUNKENBORDER)\n\t\t\t{\n\t\t\t\tMoveToEx(ps.hdc,r.left,r.bottom,NULL);\n\t\t\t\tLineTo(ps.hdc,r.right,r.bottom);\n\t\t\t\tLineTo(ps.hdc,r.right,r.top-1);\n\t\t\t\tif(hrgn)\n\t\t\t\t{\n\t\t\t\t\tWADlg_removeFromRgn(hrgn,r.left,r.bottom,r.right,r.bottom+1);\n\t\t\t\t\tWADlg_removeFromRgn(hrgn,r.right,r.top,r.right+1,r.bottom);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ((a & 0xffff0000) == DCW_DIVIDER)\n\t\t\t{\n\t\t\t\tif (r.right - r.left < r.bottom - r.top) // vertical\n\t\t\t\t{\n\t\t\t\t\tint left=(r.left+r.right)/2;\n\t\t\t\t\tMoveToEx(ps.hdc,left,r.top,NULL);\n\t\t\t\t\tLineTo(ps.hdc,left,r.bottom+1);\n\t\t\t\t\tif(hrgn) WADlg_removeFromRgn(hrgn,left,r.top,left+1,r.bottom);\n\t\t\t\t}\n\t\t\t\telse // horiz\n\t\t\t\t{\n\t\t\t\t\tint top=(r.top+r.bottom)/2;\n\t\t\t\t\tMoveToEx(ps.hdc,r.left,top,NULL);\n\t\t\t\t\tLineTo(ps.hdc,r.right+1,top);\n\t\t\t\t\tif(hrgn) WADlg_removeFromRgn(hrgn,r.left,top,r.right,top+1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tSelectObject(ps.hdc, o);\n\tDeleteObject(pen);\n\n\tif(hrgn) \n\t{\n\t\t//erase bkgnd while clipping out our own drawn stuff (for flickerless display)\n\t\tHBRUSH b = CreateSolidBrush(wadlg_colors[WADLG_WNDBG]);\n\t\tFillRgn(ps.hdc,hrgn,b);\n\t\tDeleteObject(b);\n\t    DeleteObject(hrgn);\n\t}\n\tEndPaint(hwndDlg,&ps);\n}\n#endif\n\n#endif//_WA_DLG_H_"
  },
  {
    "path": "in_vgm/Winamp/wa_ipc.h",
    "content": "/*\n** Copyright (C) 1997-2008 Nullsoft, Inc.\n**\n** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held \n** liable for any damages arising from the use of this software. \n**\n** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to \n** alter it and redistribute it freely, subject to the following restrictions:\n**\n**   1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. \n**      If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n**\n**   2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n**\n**   3. This notice may not be removed or altered from any source distribution.\n**\n*/\n\n#ifndef _WA_IPC_H_\n#define _WA_IPC_H_\n\n#include <windows.h>\n#include <stddef.h>\n#if (_MSC_VER <= 1200)\ntypedef int intptr_t;\n#endif\n/*\n** This is the modern replacement for the classic 'frontend.h'. Most of these \n** updates are designed for in-process use, i.e. from a plugin.\n**\n*/\n\n/* Most of the IPC_* messages involve sending the message in the form of:\n** result = SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*);\n** Where different then this is specified (typically with WM_COPYDATA variants)\n**\n** When you use SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*) and specify a IPC_*\n** which is not currently implemented/supported by the Winamp version being used then it\n** will return 1 for 'result'. This is a good way of helping to check if an api being\n** used which returns a function pointer, etc is even going to be valid.\n*/\n\n#define WM_WA_IPC WM_USER\n\n#define WINAMP_VERSION_MAJOR(winampVersion) ((winampVersion & 0x0000FF00) >> 12)\n#define WINAMP_VERSION_MINOR(winampVersion) (winampVersion & 0x000000FF)  // returns, i.e. 0x12 for 5.12 and 0x10 for 5.1... \n\n\n#define IPC_GETVERSION 0\n/* int version = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION);\n**\n** The version returned will be 0x20yx for Winamp 2.yx.\n** Versions previous to Winamp 2.0 typically (but not always) use 0x1zyx for 1.zx.\n** Just a bit weird but that's the way it goes.\n**\n** For Winamp 5.x it uses the format 0x50yx for Winamp 5.yx\n** e.g.   5.01 -> 0x5001\n**        5.09 -> 0x5009\n**        5.1  -> 0x5010\n**\n** Notes: For 5.02 this api will return the same value as for a 5.01 build.\n**        For 5.07 this api will return the same value as for a 5.06 build.\n*/\n\n\n#define IPC_GETVERSIONSTRING 1\n\n\n#define IPC_GETREGISTEREDVERSION 770\n/* (requires Winamp 5.0+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETREGISTEREDVERSION);\n**\n** This will open the Winamp Preferences and show the Winamp Pro page.\n*/\n\n\ntypedef struct {\n  const char *filename;\n  const char *title;\n  int length;\n} enqueueFileWithMetaStruct; // send this to a IPC_PLAYFILE in a non WM_COPYDATA, \n// and you get the nice desired result. if title is NULL, it is treated as a \"thing\",\n// otherwise it's assumed to be a file (for speed)\n\ntypedef struct {\n  const wchar_t *filename;\n  const wchar_t *title;\n  int length;\n} enqueueFileWithMetaStructW;\n\n#define IPC_PLAYFILE 100  // dont be fooled, this is really the same as enqueufile\n#define IPC_ENQUEUEFILE 100 \n#define IPC_PLAYFILEW 1100\n#define IPC_ENQUEUEFILEW 1100\n/* This is sent as a WM_COPYDATA with IPC_PLAYFILE as the dwData member and the string\n** of the file / playlist to be enqueued into the playlist editor as the lpData member.\n** This will just enqueue the file or files since you can use this to enqueue a playlist.\n** It will not clear the current playlist or change the playback state.\n**\n** COPYDATASTRUCT cds = {0};\n**   cds.dwData = IPC_ENQUEUEFILE;\n**   cds.lpData = (void*)\"c:\\\\test\\\\folder\\\\test.mp3\";\n**   cds.cbData = lstrlen((char*)cds.lpData)+1;  // include space for null char\n**   SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds);\n**\n**\n** With 2.9+ and all of the 5.x versions you can send this as a normal WM_WA_IPC\n** (non WM_COPYDATA) with an enqueueFileWithMetaStruct as the param.\n** If the title member is null then it is treated as a \"thing\" otherwise it will be\n** assumed to be a file (for speed).\n**\n** enqueueFileWithMetaStruct eFWMS = {0};\n**   eFWMS.filename = \"c:\\\\test\\\\folder\\\\test.mp3\";\n**   eFWMS.title = \"Whipping Good\";\n**   eFWMS.length = 300;  // this is the number of seconds for the track\n**   SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&eFWMS,IPC_ENQUEUEFILE);\n*/\n\n\n#define IPC_DELETE 101\n#define IPC_DELETE_INT 1101 \n/* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_DELETE);\n** Use this api to clear Winamp's internal playlist.\n** You should not need to use IPC_DELETE_INT since it is used internally by Winamp when\n** it is dealing with some lame Windows Explorer issues (hard to believe that!).\n*/\n\n\n#define IPC_STARTPLAY 102   \n#define IPC_STARTPLAY_INT 1102 \n/* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_STARTPLAY);\n** Sending this will start playback and is almost the same as hitting the play button.\n** The IPC_STARTPLAY_INT version is used internally and you should not need to use it\n** since it won't be any fun.\n*/\n\n\n#define IPC_CHDIR 103\n/* This is sent as a WM_COPYDATA type message with IPC_CHDIR as the dwData value and the\n** directory you want to change to as the lpData member.\n**\n** COPYDATASTRUCT cds = {0};\n**   cds.dwData = IPC_CHDIR;\n**   cds.lpData = (void*)\"c:\\\\download\";\n**   cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char\n**   SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds);\n**\n** The above example will make Winamp change to the directory 'C:\\download'.\n*/\n\n\n#define IPC_ISPLAYING 104\n/* int res = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING);\n** This is sent to retrieve the current playback state of Winamp.\n** If it returns 1, Winamp is playing.\n** If it returns 3, Winamp is paused.\n** If it returns 0, Winamp is not playing.\n*/\n\n\n#define IPC_GETOUTPUTTIME 105\n/* int res = SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETOUTPUTTIME);\n** This api can return two different sets of information about current playback status.\n**\n** If mode = 0 then it will return the position (in ms) of the currently playing track.\n** Will return -1 if Winamp is not playing.\n**\n** If mode = 1 then it will return the current track length (in seconds).\n** Will return -1 if there are no tracks (or possibly if Winamp cannot get the length).\n**\n** If mode = 2 then it will return the current track length (in milliseconds).\n** Will return -1 if there are no tracks (or possibly if Winamp cannot get the length).\n*/\n\n\n#define IPC_JUMPTOTIME 106\n/* (requires Winamp 1.60+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,ms,IPC_JUMPTOTIME);\n** This api sets the current position (in milliseconds) for the currently playing song.\n** The resulting playback position may only be an approximate time since some playback\n** formats do not provide exact seeking e.g. mp3\n** This returns -1 if Winamp is not playing, 1 on end of file, or 0 if it was successful.\n*/\n\n\n#define IPC_GETMODULENAME 109\n#define IPC_EX_ISRIGHTEXE 666\n/* usually shouldnt bother using these, but here goes:\n** send a WM_COPYDATA with IPC_GETMODULENAME, and an internal\n** flag gets set, which if you send a normal WM_WA_IPC message with\n** IPC_EX_ISRIGHTEXE, it returns whether or not that filename\n** matches. lame, I know.\n*/\n\n\n#define IPC_WRITEPLAYLIST 120\n/* (requires Winamp 1.666+)\n** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_WRITEPLAYLIST);\n**\n** IPC_WRITEPLAYLIST will write the current playlist to '<winampdir>\\\\Winamp.m3u' and\n** will also return the current playlist position (see IPC_GETLISTPOS).\n**\n** This is kinda obsoleted by some of the newer 2.x api items but it still is good for\n** use with a front-end program (instead of a plug-in) and you want to see what is in the\n** current playlist.\n**\n** This api will only save out extended file information in the #EXTINF entry if Winamp\n** has already read the data such as if the file was played of scrolled into view. If\n** Winamp has not read the data then you will only find the file with its filepath entry\n** (as is the base requirements for a m3u playlist).\n*/\n\n\n#define IPC_SETPLAYLISTPOS 121\n/* (requires Winamp 2.0+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,position,IPC_SETPLAYLISTPOS)\n** IPC_SETPLAYLISTPOS sets the playlist position to the specified 'position'.\n** It will not change playback status or anything else. It will just set the current\n** position in the playlist and will update the playlist view if necessary.\n**\n** If you use SendMessage(hwnd_winamp,WM_COMMAND,MAKEWPARAM(WINAMP_BUTTON2,0),0);\n** after using IPC_SETPLAYLISTPOS then Winamp will start playing the file at 'position'.\n*/\n\n\n#define IPC_SETVOLUME 122\n/* (requires Winamp 2.0+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,volume,IPC_SETVOLUME);\n** IPC_SETVOLUME sets the volume of Winamp (between the range of 0 to 255).\n**\n** If you pass 'volume' as -666 then the message will return the current volume.\n** int curvol = SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETVOLUME);\n*/\n\n\n#define IPC_GETVOLUME(hwnd_winamp) SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETVOLUME)\n/* (requires Winamp 2.0+)\n** int curvol = IPC_GETVOLUME(hwnd_winamp);\n** This will return the current volume of Winamp or \n*/\n\n\n#define IPC_SETPANNING 123\n/* (requires Winamp 2.0+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,panning,IPC_SETPANNING);\n** IPC_SETPANNING sets the panning of Winamp from 0 (left) to 255 (right).\n**\n** At least in 5.x+ this works from -127 (left) to 127 (right).\n**\n** If you pass 'panning' as -666 to this api then it will return the current panning.\n** int curpan = SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETPANNING);\n*/\n\n\n#define IPC_GETLISTLENGTH 124\n/* (requires Winamp 2.0+)\n** int length = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTLENGTH);\n** IPC_GETLISTLENGTH returns the length of the current playlist as the number of tracks.\n*/\n\n\n#define IPC_GETLISTPOS 125\n/* (requires Winamp 2.05+)\n** int pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS);\n** IPC_GETLISTPOS returns the current playlist position (which is shown in the playlist\n** editor as a differently coloured text entry e.g is yellow for the classic skin).\n**\n** This api is a lot like IPC_WRITEPLAYLIST but a lot faster since it does not have to\n** write out the whole of the current playlist first.\n*/\n\n\n#define IPC_GETINFO 126\n/* (requires Winamp 2.05+)\n** int inf=SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETINFO);\n** IPC_GETINFO returns info about the current playing song. The value\n** it returns depends on the value of 'mode'.\n** Mode      Meaning\n** ------------------\n** 0         Samplerate, in kilohertz (i.e. 44)\n** 1         Bitrate  (i.e. 128)\n** 2         Channels (i.e. 2)\n** 3 (5+)    Video LOWORD=w HIWORD=h\n** 4 (5+)    > 65536, string (video description)\n** 5 (5.25+) Samplerate, in hertz (i.e. 44100)\n*/\n\n\n#define IPC_GETEQDATA 127\n/* (requires Winamp 2.05+)\n** int data=SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA);\n** IPC_GETEQDATA queries the status of the EQ. \n** The value returned depends on what 'pos' is set to:\n** Value      Meaning\n** ------------------\n** 0-9        The 10 bands of EQ data. 0-63 (+20db - -20db)\n** 10         The preamp value. 0-63 (+20db - -20db)\n** 11         Enabled. zero if disabled, nonzero if enabled.\n** 12         Autoload. zero if disabled, nonzero if enabled.\n*/\n\n\n#define IPC_SETEQDATA 128\n/* (requires Winamp 2.05+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA);\n** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SETEQDATA);\n** IPC_SETEQDATA sets the value of the last position retrieved\n** by IPC_GETEQDATA. This is pretty lame, and we should provide\n** an extended version that lets you do a MAKELPARAM(pos,value).\n** someday...\n\n  new (2.92+): \n    if the high byte is set to 0xDB, then the third byte specifies\n    which band, and the bottom word specifies the value.\n*/\n\n\n#define IPC_ADDBOOKMARK 129\n#define IPC_ADDBOOKMARKW 131\n/* (requires Winamp 2.4+)\n** This is sent as a WM_COPYDATA using IPC_ADDBOOKMARK as the dwData value and the\n** directory you want to change to as the lpData member. This will add the specified\n** file / url to the Winamp bookmark list.\n**\n** COPYDATASTRUCT cds = {0};\n**   cds.dwData = IPC_ADDBOOKMARK;\n**   cds.lpData = (void*)\"http://www.blah.com/listen.pls\";\n**   cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char\n**   SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds);\n**\n**\n** In Winamp 5.0+ we use this as a normal WM_WA_IPC and the string is null separated as\n** the filename and then the title of the entry.\n**\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(char*)\"filename\\0title\\0\",IPC_ADDBOOKMARK);\n**\n** This will notify the library / bookmark editor that a bookmark was added.\n** Note that using this message in this context does not actually add the bookmark.\n** Do not use, it is essentially just a notification type message :)\n*/\n\n\n#define IPC_INSTALLPLUGIN 130\n/* This is not implemented (and is very unlikely to be done due to safety concerns).\n** If it was then you could do a WM_COPYDATA with a path to a .wpz and it would then\n** install the plugin for you.\n**\n** COPYDATASTRUCT cds = {0};\n**   cds.dwData = IPC_INSTALLPLUGIN;\n**   cds.lpData = (void*)\"c:\\\\path\\\\to\\\\file.wpz\";\n**   cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char\n**   SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds);\n*/\n\n\n#define IPC_RESTARTWINAMP 135\n/* (requires Winamp 2.2+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_RESTARTWINAMP);\n** IPC_RESTARTWINAMP will restart Winamp (isn't that obvious ? :) )\n** If this fails to make Winamp start after closing then there is a good chance one (or\n** more) of the currently installed plugins caused Winamp to crash on exit (either as a\n** silent crash or a full crash log report before it could call itself start again.\n*/\n\n\n#define IPC_ISFULLSTOP 400\n/* (requires winamp 2.7+ I think)\n** int ret=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISFULLSTOP);\n** This is useful for when you're an output plugin and you want to see if the stop/close\n** happening is a full stop or if you are just between tracks. This returns non zero if\n** it is a full stop or zero if it is just a new track.\n** benski> i think it's actually the other way around - \n**         !0 for EOF and 0 for user pressing stop\n*/\n\n\n#define IPC_INETAVAILABLE 242\n/* (requires Winamp 2.05+)\n** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INETAVAILABLE);\n** IPC_INETAVAILABLE will return 1 if an Internet connection is available for Winamp and\n** relates to the internet connection type setting on the main general preferences page\n** in the Winamp preferences.\n*/\n\n\n#define IPC_UPDTITLE 243\n/* (requires Winamp 2.2+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_UPDTITLE);\n** IPC_UPDTITLE will ask Winamp to update the information about the current title and\n** causes GetFileInfo(..) in the input plugin associated with the current playlist entry\n** to be called. This can be called such as when an input plugin is buffering a file so\n** that it can cause the buffer percentage to appear in the playlist.\n*/\n\n\n#define IPC_REFRESHPLCACHE 247\n/* (requires Winamp 2.2+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REFRESHPLCACHE);\n** IPC_REFRESHPLCACHE will flush the playlist cache buffer and you send this if you want\n** Winamp to go refetch the titles for all of the entries in the current playlist.\n**\n** 5.3+: pass a wchar_t * string in wParam, and it'll do a strnicmp() before clearing the cache\n*/\n\n\n#define IPC_GET_SHUFFLE 250\n/* (requires Winamp 2.4+)\n** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_SHUFFLE);\n** IPC_GET_SHUFFLE returns the status of the shuffle option.\n** If set then it will return 1 and if not set then it will return 0.\n*/\n\n\n#define IPC_GET_REPEAT 251\n/* (requires Winamp 2.4+)\n** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_REPEAT);\n** IPC_GET_REPEAT returns the status of the repeat option.\n** If set then it will return 1 and if not set then it will return 0.\n*/\n\n\n#define IPC_SET_SHUFFLE 252\n/* (requires Winamp 2.4+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_SHUFFLE);\n** IPC_SET_SHUFFLE sets the status of the shuffle option.\n** If 'value' is 1 then shuffle is turned on.\n** If 'value' is 0 then shuffle is turned off.\n*/\n\n\n#define IPC_SET_REPEAT 253\n/* (requires Winamp 2.4+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_REPEAT);\n** IPC_SET_REPEAT sets the status of the repeat option.\n** If 'value' is 1 then shuffle is turned on.\n** If 'value' is 0 then shuffle is turned off.\n*/\n\n\n#define IPC_ENABLEDISABLE_ALL_WINDOWS 259 // 0xdeadbeef to disable\n/* (requires Winamp 2.9+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,(enable?0:0xdeadbeef),IPC_ENABLEDISABLE_ALL_WINDOWS);\n** Sending this message with 0xdeadbeef as the param will disable all winamp windows and\n** any other values will enable all of the Winamp windows again. When disabled you won't\n** get any response on clicking or trying to do anything to the Winamp windows. If the\n** taskbar icon is shown then you may still have control ;)\n*/\n\n\n#define IPC_GETWND 260\n/* (requires Winamp 2.9+)\n** HWND h=SendMessage(hwnd_winamp,WM_WA_IPC,IPC_GETWND_xxx,IPC_GETWND);\n** returns the HWND of the window specified.\n*/\n  #define IPC_GETWND_EQ 0 // use one of these for the param\n  #define IPC_GETWND_PE 1\n  #define IPC_GETWND_MB 2\n  #define IPC_GETWND_VIDEO 3\n#define IPC_ISWNDVISIBLE 261 // same param as IPC_GETWND\n\n\n/************************************************************************\n***************** in-process only (WE LOVE PLUGINS)\n************************************************************************/\n\n#define IPC_SETSKINW 199\n#define IPC_SETSKIN 200\n/* (requires Winamp 2.04+, only usable from plug-ins (not external apps))\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)\"skinname\",IPC_SETSKIN);\n** IPC_SETSKIN sets the current skin to \"skinname\". Note that skinname \n** can be the name of a skin, a skin .zip file, with or without path. \n** If path isn't specified, the default search path is the winamp skins \n** directory.\n*/\n\n\n#define IPC_GETSKIN 201\n#define IPC_GETSKINW 1201\n/* (requires Winamp 2.04+, only usable from plug-ins (not external apps))\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)skinname_buffer,IPC_GETSKIN);\n** IPC_GETSKIN puts the directory where skin bitmaps can be found \n** into  skinname_buffer.\n** skinname_buffer must be MAX_PATH characters in length.\n** When using a .zip'd skin file, it'll return a temporary directory\n** where the ZIP was decompressed.\n*/\n\n\n#define IPC_EXECPLUG 202\n/* (requires Winamp 2.04+, only usable from plug-ins (not external apps))\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)\"vis_file.dll\",IPC_EXECPLUG);\n** IPC_EXECPLUG executes a visualization plug-in pointed to by WPARAM.\n** the format of this string can be:\n** \"vis_whatever.dll\"\n** \"vis_whatever.dll,0\" // (first mod, file in winamp plug-in dir)\n** \"C:\\\\dir\\\\vis_whatever.dll,1\" \n*/\n\n\n#define IPC_GETPLAYLISTFILE 211\n#define IPC_GETPLAYLISTFILEW 214\n/* (requires Winamp 2.04+, only usable from plug-ins (not external apps))\n** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTFILE);\n** IPC_GETPLAYLISTFILE gets the filename of the playlist entry [index].\n** returns a pointer to it. returns NULL on error.\n*/\n\n\n#define IPC_GETPLAYLISTTITLE 212\n#define IPC_GETPLAYLISTTITLEW 213\n/* (requires Winamp 2.04+, only usable from plug-ins (not external apps))\n** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTTITLE);\n**\n** IPC_GETPLAYLISTTITLE gets the title of the playlist entry [index].\n** returns a pointer to it. returns NULL on error.\n*/\n\n\n#define IPC_GETHTTPGETTER 240\n/* retrieves a function pointer to a HTTP retrieval function.\n** if this is unsupported, returns 1 or 0.\n** the function should be:\n** int (*httpRetrieveFile)(HWND hwnd, char *url, char *file, char *dlgtitle);\n** if you call this function, with a parent window, a URL, an output file, and a dialog title,\n** it will return 0 on successful download, 1 on error.\n*/\n\n\n#define IPC_GETHTTPGETTERW 1240\n/* int (*httpRetrieveFileW)(HWND hwnd, char *url, wchar_t *file, wchar_t *dlgtitle); */\n\n\n#define IPC_MBOPEN 241\n/* (requires Winamp 2.05+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_MBOPEN);\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)url,IPC_MBOPEN);\n** IPC_MBOPEN will open a new URL in the minibrowser. if url is NULL, it will open the Minibrowser window.\n*/\n\n\n#define IPC_CHANGECURRENTFILE 245\n/* (requires Winamp 2.05+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)file,IPC_CHANGECURRENTFILE);\n** IPC_CHANGECURRENTFILE will set the current playlist item.\n*/\n\n\n#define IPC_CHANGECURRENTFILEW 1245\n/* (requires Winamp 5.3+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)file,IPC_CHANGECURRENTFILEW);\n** IPC_CHANGECURRENTFILEW will set the current playlist item.\n*/\n\n\n#define IPC_GETMBURL 246\n/* (requires Winamp 2.2+)\n** char buffer[4096]; // Urls can be VERY long\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)buffer,IPC_GETMBURL);\n** IPC_GETMBURL will retrieve the current Minibrowser URL into buffer.\n** buffer must be at least 4096 bytes long.\n*/\n\n\n#define IPC_MBBLOCK 248\n/* (requires Winamp 2.4+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_MBBLOCK);\n**\n** IPC_MBBLOCK will block the Minibrowser from updates if value is set to 1\n*/\n\n\n#define IPC_MBOPENREAL 249\n/* (requires Winamp 2.4+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)url,IPC_MBOPENREAL);\n**\n** IPC_MBOPENREAL works the same as IPC_MBOPEN except that it will works even if \n** IPC_MBBLOCK has been set to 1\n*/\n\n\n#define IPC_ADJUST_OPTIONSMENUPOS 280\n/* (requires Winamp 2.9+)\n** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_OPTIONSMENUPOS);\n** moves where winamp expects the Options menu in the main menu. Useful if you wish to insert a\n** menu item above the options/skins/vis menus.\n*/\n\n\n#define IPC_GET_HMENU 281\n/* (requires Winamp 2.9+)\n** HMENU hMenu=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)0,IPC_GET_HMENU);\n** values for data:\n** 0 : main popup menu \n** 1 : main menubar file menu\n** 2 : main menubar options menu\n** 3 : main menubar windows menu\n** 4 : main menubar help menu\n** other values will return NULL.\n*/\n\n\n#define IPC_GET_EXTENDED_FILE_INFO 290 //pass a pointer to the following struct in wParam\n#define IPC_GET_EXTENDED_FILE_INFO_HOOKABLE 296\n/* (requires Winamp 2.9+)\n** to use, create an extendedFileInfoStruct, point the values filename and metadata to the\n** filename and metadata field you wish to query, and ret to a buffer, with retlen to the\n** length of that buffer, and then SendMessage(hwnd_winamp,WM_WA_IPC,&struct,IPC_GET_EXTENDED_FILE_INFO);\n** the results should be in the buffer pointed to by ret.\n** returns 1 if the decoder supports a getExtendedFileInfo method\n*/\ntypedef struct {\n  const char *filename;\n  const char *metadata;\n  char *ret;\n  size_t retlen;\n} extendedFileInfoStruct;\n\n\n#define IPC_GET_BASIC_FILE_INFO 291 //pass a pointer to the following struct in wParam\ntypedef struct {\n  const char *filename;\n\n  int quickCheck; // set to 0 to always get, 1 for quick, 2 for default (if 2, quickCheck will be set to 0 if quick wasnot used)\n\n  // filled in by winamp\n  int length;\n  char *title;\n  int titlelen;\n} basicFileInfoStruct;\n\n\n#define IPC_GET_BASIC_FILE_INFOW 1291 //pass a pointer to the following struct in wParam\ntypedef struct {\n  const wchar_t *filename;\n\n  int quickCheck; // set to 0 to always get, 1 for quick, 2 for default (if 2, quickCheck will be set to 0 if quick wasnot used)\n\n  // filled in by winamp\n  int length;\n  wchar_t *title;\n  int titlelen;\n} basicFileInfoStructW;\n\n\n#define IPC_GET_EXTLIST 292 //returns doublenull delimited. GlobalFree() it when done. if data is 0, returns raw extlist, if 1, returns something suitable for getopenfilename\n#define IPC_GET_EXTLISTW 1292 // wide char version of above\n\n\n#define IPC_INFOBOX 293\ntypedef struct {\n  HWND parent;\n  char *filename;\n} infoBoxParam;\n\n\n#define IPC_INFOBOXW 1293\ntypedef struct {\n  HWND parent;\n  const wchar_t *filename;\n} infoBoxParamW;\n\n\n#define IPC_SET_EXTENDED_FILE_INFO 294 //pass a pointer to the a extendedFileInfoStruct in wParam\n/* (requires Winamp 2.9+)\n** to use, create an extendedFileInfoStruct, point the values filename and metadata to the\n** filename and metadata field you wish to write in ret. (retlen is not used). and then \n** SendMessage(hwnd_winamp,WM_WA_IPC,&struct,IPC_SET_EXTENDED_FILE_INFO);\n** returns 1 if the metadata is supported\n** Call IPC_WRITE_EXTENDED_FILE_INFO once you're done setting all the metadata you want to update\n*/\n\n\n#define IPC_WRITE_EXTENDED_FILE_INFO 295 \n/* (requires Winamp 2.9+)\n** writes all the metadata set thru IPC_SET_EXTENDED_FILE_INFO to the file\n** returns 1 if the file has been successfully updated, 0 if error\n*/\n\n\n#define IPC_FORMAT_TITLE 297\ntypedef struct \n{\n  char *spec; // NULL=default winamp spec\n  void *p;\n\n  char *out;\n  int out_len;\n\n  char * (*TAGFUNC)(const char * tag, void * p); //return 0 if not found\n  void (*TAGFREEFUNC)(char * tag,void * p);\n} waFormatTitle;\n\n\n#define IPC_FORMAT_TITLE_EXTENDED 298 // similiar to IPC_FORMAT_TITLE, but falls back to Winamp's %tags% if your passed tag function doesn't handle it\ntypedef struct \n{\n  const wchar_t *filename;\n  int useExtendedInfo; // set to 1 if you want the Title Formatter to query the input plugins for any tags that your tag function fails on\n  const wchar_t *spec; // NULL=default winamp spec\n  void *p;\n\n  wchar_t *out;\n  int out_len;\n\n  wchar_t * (*TAGFUNC)(const wchar_t * tag, void * p); //return 0 if not found, -1 for empty tag\n  void (*TAGFREEFUNC)(wchar_t *tag, void *p);\n} waFormatTitleExtended;\n\n\n#define IPC_COPY_EXTENDED_FILE_INFO 299 \ntypedef struct\n{\n  const char *source;\n  const char *dest;\n} copyFileInfoStruct;\n\n\n#define IPC_COPY_EXTENDED_FILE_INFOW 1299 \ntypedef struct\n{\n  const wchar_t *source;\n  const wchar_t *dest;\n} copyFileInfoStructW;\n\n\ntypedef struct {\n  int (*inflateReset)(void *strm);\n  int (*inflateInit_)(void *strm,const char *version, int stream_size);\n  int (*inflate)(void *strm, int flush);\n  int (*inflateEnd)(void *strm);\n  unsigned long (*crc32)(unsigned long crc, const unsigned  char *buf, unsigned int len);\n} wa_inflate_struct;\n\n#define IPC_GETUNCOMPRESSINTERFACE 331\n/* returns a function pointer to uncompress().\n** int (*uncompress)(unsigned char *dest, unsigned long *destLen, const unsigned char *source, unsigned long sourceLen);\n** right out of zlib, useful for decompressing zlibbed data.\n** if you pass the parm of 0x10100000, it will return a wa_inflate_struct * to an inflate API.\n*/\n\n\ntypedef struct _prefsDlgRec {\n  HINSTANCE hInst;  // dll instance containing the dialog resource\n  int dlgID;        // resource identifier of the dialog\n  void *proc;       // window proceedure for handling the dialog defined as\n                    // LRESULT CALLBACK PrefsPage(HWND,UINT,WPARAM,LPARAM)\n\n  char *name;       // name shown for the prefs page in the treelist\n  intptr_t where;   // section in the treelist the prefs page is to be added to\n                    // 0 for General Preferences\n                    // 1 for Plugins\n                    // 2 for Skins\n                    // 3 for Bookmarks (no longer in the 5.0+ prefs)\n                    // 4 for Prefs     (the old 'Setup' section - no longer in 5.0+)\n\n  intptr_t _id;\n  struct _prefsDlgRec *next; // no longer implemented as a linked list, now used by Winamp for other means\n} prefsDlgRec;\n\ntypedef struct _prefsDlgRecW {\n  HINSTANCE hInst;  // dll instance containing the dialog resource\n  int dlgID;        // resource identifier of the dialog\n  void *proc;       // window proceedure for handling the dialog defined as\n                    // LRESULT CALLBACK PrefsPage(HWND,UINT,WPARAM,LPARAM)\n\n  wchar_t *name;    // name shown for the prefs page in the treelist\n  intptr_t where;   // section in the treelist the prefs page is to be added to\n                    // 0 for General Preferences\n                    // 1 for Plugins\n                    // 2 for Skins\n                    // 3 for Bookmarks (no longer in the 5.0+ prefs)\n                    // 4 for Prefs     (the old 'Setup' section - no longer in 5.0+)\n\n  intptr_t _id;\n  struct _prefsDlgRec *next; // no longer implemented as a linked list, now used by Winamp for other means\n} prefsDlgRecW;\n\n#define IPC_ADD_PREFS_DLG 332\n#define IPC_ADD_PREFS_DLGW 1332 \n#define IPC_REMOVE_PREFS_DLG 333\n/* (requires Winamp 2.9+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_ADD_PREFS_DLG);\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_REMOVE_PREFS_DLG);\n**\n** IPC_ADD_PREFS_DLG:\n** To use this you need to allocate a prefsDlgRec structure (either on the heap or with\n** some global data but NOT on the stack) and then initialise the members of the structure\n** (see the definition of the prefsDlgRec structure above).\n**\n**   hInst  -  dll instance of where the dialog resource is located.\n**   dlgID  -  id of the dialog resource.\n**   proc   -  dialog window procedure for the prefs dialog.\n**   name   -  name of the prefs page as shown in the preferences list.\n**   where  -  see above for the valid locations the page can be added.\n**\n** Then you do SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_ADD_PREFS_DLG);\n**\n** example:\n**\n** prefsDlgRec* prefsRec = 0;\n**   prefsRec = GlobalAlloc(GPTR,sizeof(prefsDlgRec));\n**   prefsRec->hInst = hInst;\n**   prefsRec->dlgID = IDD_PREFDIALOG;\n**   prefsRec->name = \"Pref Page\";\n**   prefsRec->where = 0;\n**   prefsRec->proc = PrefsPage;\n**   SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_ADD_PREFS_DLG);\n**\n**\n** IPC_REMOVE_PREFS_DLG:\n** To use you pass the address of the same prefsRec you used when adding the prefs page \n** though you shouldn't really ever have to do this but it's good to clean up after you\n** when you're plugin is being unloaded.\n**\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_REMOVE_PREFS_DLG);\n**\n** IPC_ADD_PREFS_DLGW\n** requires Winamp 5.53+\n*/\n\n\n#define IPC_OPENPREFSTOPAGE 380\n/* SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_OPENPREFSTOPAGE);\n**\n** There are two ways of opening a preferences page.\n**\n** The first is to pass an id of a builtin preferences page (see below for ids) or a\n** &prefsDlgRec of the preferences page to open and this is normally done if you are\n** opening a prefs page you added yourself.\n**\n** If the page id does not or the &prefsRec is not valid then the prefs dialog will be\n** opened to the first page available (usually the Winamp Pro page).\n**\n** (requires Winamp 5.04+)\n** Passing -1 for param will open the preferences dialog to the last page viewed.\n**\n** Note: v5.0 to 5.03 had a bug in this api\n**       \n** On the first call then the correct prefs page would be opened to but on the next call\n** the prefs dialog would be brought to the front but the page would not be changed to the\n** specified.\n** In 5.04+ it will change to the prefs page specified if the prefs dialog is already open.\n*/\n\n/* Builtin Preference page ids (valid for 5.0+)\n** (stored in the lParam member of the TVITEM structure from the tree item)\n**\n** These can be useful if you want to detect a specific prefs page and add things to it\n** yourself or something like that ;)\n**\n** Winamp Pro           20\n** General Preferences  0\n** File Types           1\n** Playlist             23\n** Titles               21\n** Playback             42 (added in 5.25)\n** Station Info         41 (added in 5.11 & removed in 5.5)\n** Video                24\n** Localization         25 (added in 5.5)\n** Skins                40\n** Classic Skins        22\n** Plugins              30\n** Input                31\n** Output               32\n** Visualisation        33\n** DSP/Effect           34\n** General Purpose      35\n**\n** Note:\n** Custom page ids begin from 60\n** The value of the normal custom pages (Global Hotkeys, Jump To File, etc) is not\n** guaranteed since it depends on the order in which the plugins are loaded which can\n** change on different systems.\n**\n** Global Hotkeys, Jump To File, Media Library (under General Preferences and child pages),\n** Media Library (under Plugins), Portables, CD Ripping and Modern Skins are custom pages\n** created by the plugins shipped with Winamp.\n*/\n\n\n#define IPC_GETINIFILE 334\n/* (requires Winamp 2.9+)\n** char *ini=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIFILE);\n** This returns a pointer to the full file path of winamp.ini.\n**\n** char ini_path[MAX_PATH] = {0};\n**\n** void GetIniFilePath(HWND hwnd){\n**   if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION) >= 0x2900){\n**     // this gets the string of the full ini file path\n**     lstrcpyn(ini_path,(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIFILE),sizeof(ini_path));\n**   }\n**   else{\n**   char* p = ini_path;\n**     p += GetModuleFileName(0,ini_path,sizeof(ini_path)) - 1;\n**     while(p && *p != '.'){p--;}\n**     lstrcpyn(p+1,\"ini\",sizeof(ini_path));\n**   }\n** }\n*/\n\n\n#define IPC_GETINIDIRECTORY 335\n/* (requires Winamp 2.9+)\n** char *dir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIDIRECTORY);\n** This returns a pointer to the directory where winamp.ini can be found and is\n** useful if you want store config files but you don't want to use winamp.ini.\n*/\n\n\n#define IPC_GETPLUGINDIRECTORY 336\n/* (requires Winamp 5.11+)\n** char *plugdir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETPLUGINDIRECTORY);\n** This returns a pointer to the directory where Winamp has its plugins stored and is\n** useful if you want store config files in plugins.ini in the plugins folder or for\n** accessing any local files in the plugins folder.\n*/\n\n\n#define IPC_GETM3UDIRECTORY 337\n/* (requires Winamp 5.11+)\n** char *m3udir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETM3UDIRECTORY);\n** This returns a pointer to the directory where winamp.m3u (and winamp.m3u8 if supported) is stored in.\n*/\n\n\n#define IPC_GETM3UDIRECTORYW 338\n/* (requires Winamp 5.3+)\n** wchar_t *m3udirW=(wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETM3UDIRECTORYW);\n** This returns a pointer to the directory where winamp.m3u (and winamp.m3u8 if supported) is stored in.\n*/\n\n\n#define IPC_SPAWNBUTTONPOPUP 361 // param =\n// 0 = eject\n// 1 = previous\n// 2 = next\n// 3 = pause\n// 4 = play\n// 5 = stop\n\n\n#define IPC_OPENURLBOX 360\n/* (requires Winamp 5.0+)\n** HGLOBAL hglobal = (HGLOBAL)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_OPENURLBOX);\n** You pass a hwnd for the dialog to be parented to (which modern skin support uses).\n** This will return a HGLOBAL that needs to be freed with GlobalFree() if this worked.\n*/\n\n\n#define IPC_OPENFILEBOX 362\n/* (requires Winamp 5.0+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_OPENFILEBOX);\n** You pass a hwnd for the dialog to be parented to (which modern skin support uses).\n*/\n\n\n#define IPC_OPENDIRBOX 363\n/* (requires Winamp 5.0+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_OPENDIRBOX);\n** You pass a hwnd for the dialog to be parented to (which modern skin support uses).\n*/\n\n\n#define IPC_SETDIALOGBOXPARENT 364\n/* (requires Winamp 5.0+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_SETDIALOGBOXPARENT);\n** Pass 'parent' as the window which will be used as the parent for a number of the built\n** in Winamp dialogs and is useful when you are taking over the whole of the UI so that\n** the dialogs will not appear at the bottom right of the screen since the main winamp\n** window is located at 3000x3000 by gen_ff when this is used.  Call this again with\n** parent = null to reset the parent back to the orginal Winamp window.\n*/\n\n#define IPC_GETDIALOGBOXPARENT 365\n/* (requires Winamp 5.51+)\n** HWND hwndParent = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)0, IPC_GETDIALOGBOXPARENT);\n** hwndParent can/must be passed to all modal dialogs (including MessageBox) thats uses winamp as a parent\n*/\n\n#define IPC_UPDATEDIALOGBOXPARENT 366\n/* (requires Winamp 5.53+)\n** if you previous called IPC_SETDIALOGBOXPARENT, call this every time your window resizes\n*/ \n\n#define IPC_DRO_MIN 401 // reserved for DrO\n#define IPC_SET_JTF_COMPARATOR 409\n/* pass me an int (__cdecl *)(const char *, const char *) in wParam */\n#define IPC_SET_JTF_COMPARATOR_W 410\n/* pass me an int (__cdecl *)(const wchar_t *, const wchar_t *) in wParam ... maybe someday :) */\n#define IPC_SET_JTF_DRAWTEXT 416\n\n#define IPC_DRO_MAX 499\n\n\n// pass 0 for a copy of the skin HBITMAP\n// pass 1 for name of font to use for playlist editor likeness\n// pass 2 for font charset\n// pass 3 for font size\n#define IPC_GET_GENSKINBITMAP 503\n\n\ntypedef struct\n{\n  HWND me; //hwnd of the window\n\n  #define EMBED_FLAGS_NORESIZE 0x1\n  // set this bit to keep window from being resizable\n\n  #define EMBED_FLAGS_NOTRANSPARENCY 0x2\n  // set this bit to make gen_ff turn transparency off for this window\n\n  #define EMBED_FLAGS_NOWINDOWMENU 0x4\n  // set this bit to prevent gen_ff from automatically adding your window to the right-click menu\n\n  #define EMBED_FLAGS_GUID 0x8\n  // (5.31+) call SET_EMBED_GUID(yourEmbedWindowStateStruct, GUID) to define a GUID for this window \n\n  #define SET_EMBED_GUID(windowState, windowGUID) { windowState->flags |= EMBED_FLAGS_GUID; *((GUID *)&windowState->extra_data[4])=windowGUID; }\n  #define GET_EMBED_GUID(windowState) (*((GUID *)&windowState->extra_data[4]))\n\n  int flags;  // see above\n\n  RECT r;\n  void *user_ptr;       // for application use\n  int extra_data[64];   // for internal winamp use\n} embedWindowState;\n\n#define IPC_GET_EMBEDIF 505\n/* (requires Winamp 2.9+)\n** HWND myframe = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&wa_wnd,IPC_GET_EMBEDIF);\n**\n** or\n**\n** HWND myframe = 0;\n** HWND (*embed)(embedWindowState *params)=0;\n**   *(void**)&embed = (void*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_EMBEDIF);\n**   myframe = embed(&wa_wnd);\n**\n** You pass an embedWindowState* and it will return a hwnd for the frame window or if you\n** pass wParam as null then it will return a HWND embedWindow(embedWindowState *);\n*/\n\n#define IPC_SKINWINDOW\t534\n\ntypedef struct __SKINWINDOWPARAM \n{\n\tHWND hwndToSkin;\n\tGUID windowGuid;\n} SKINWINDOWPARAM;\n\n\n\n#define IPC_EMBED_ENUM 532\ntypedef struct embedEnumStruct\n{\n  int (*enumProc)(embedWindowState *ws, struct embedEnumStruct *param); // return 1 to abort\n  int user_data; // or more :)\n} embedEnumStruct;\n  // pass \n\n\n#define IPC_EMBED_ISVALID 533\n/* (requires Winamp 2.9+)\n** int valid = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)embedhwnd,IPC_EMBED_ISVALID);\n** Pass a hwnd in the wParam to this to check if the hwnd is a valid embed window or not.\n*/\n\n\n#define IPC_CONVERTFILE 506\n/* (requires Winamp 2.92+)\n** Converts a given file to a different format (PCM, MP3, etc...)\n** To use, pass a pointer to a waFileConvertStruct struct\n** This struct can be either on the heap or some global\n** data, but NOT on the stack. At least, until the conversion is done.\n**\n** eg: SendMessage(hwnd_winamp,WM_WA_IPC,&myConvertStruct,IPC_CONVERTFILE);\n**\n** Return value:\n** 0: Can't start the conversion. Look at myConvertStruct->error for details.\n** 1: Conversion started. Status messages will be sent to the specified callbackhwnd.\n**    Be sure to call IPC_CONVERTFILE_END when your callback window receives the\n**    IPC_CB_CONVERT_DONE message.\n*/\ntypedef struct \n{\n  char *sourcefile;  // \"c:\\\\source.mp3\"\n  char *destfile;    // \"c:\\\\dest.pcm\"\n  intptr_t destformat[8]; // like 'PCM ',srate,nch,bps.\n  //hack alert! you can set destformat[6]=mmioFOURCC('I','N','I',' '); and destformat[7]=(int)my_ini_file; (where my_ini_file is a char*)\n  HWND callbackhwnd; // window that will receive the IPC_CB_CONVERT notification messages\n  \n  //filled in by winamp.exe\n  char *error;        //if IPC_CONVERTFILE returns 0, the reason will be here\n\n  int bytes_done;     //you can look at both of these values for speed statistics\n  int bytes_total;\n  int bytes_out;\n\n  int killswitch;     // don't set it manually, use IPC_CONVERTFILE_END\n  intptr_t extra_data[64]; // for internal winamp use\n} convertFileStruct;\n\n\n#define IPC_CONVERTFILEW 515\n// (requires Winamp 5.36+)\ntypedef struct \n{\n  wchar_t *sourcefile;  // \"c:\\\\source.mp3\"\n  wchar_t *destfile;    // \"c:\\\\dest.pcm\"\n  intptr_t destformat[8]; // like 'PCM ',srate,nch,bps.\n  //hack alert! you can set destformat[6]=mmioFOURCC('I','N','I',' '); and destformat[7]=(int)my_ini_file; (where my_ini_file is a char*)\n  HWND callbackhwnd; // window that will receive the IPC_CB_CONVERT notification messages\n  \n  //filled in by winamp.exe\n  wchar_t *error;        //if IPC_CONVERTFILE returns 0, the reason will be here\n\n  int bytes_done;     //you can look at both of these values for speed statistics\n  int bytes_total;\n  int bytes_out;\n\n  int killswitch;     // don't set it manually, use IPC_CONVERTFILE_END\n  intptr_t extra_data[64]; // for internal winamp use\n} convertFileStructW;\n\n\n#define IPC_CONVERTFILE_END 507\n/* (requires Winamp 2.92+)\n** Stop/ends a convert process started from IPC_CONVERTFILE\n** You need to call this when you receive the IPC_CB_CONVERTDONE message or when you\n** want to abort a conversion process\n**\n** eg: SendMessage(hwnd_winamp,WM_WA_IPC,&myConvertStruct,IPC_CONVERTFILE_END);\n**\n** No return value\n*/\n\n\n#define IPC_CONVERTFILEW_END 516\n// (requires Winamp 5.36+)\n\ntypedef struct {\n  HWND hwndParent;\n  int format;\n\n  //filled in by winamp.exe\n  HWND hwndConfig;\n  int extra_data[8];\n  //hack alert! you can set extra_data[6]=mmioFOURCC('I','N','I',' '); and extra_data[7]=(int)my_ini_file; (where my_ini_file is a char*)\n} convertConfigStruct;\n\n\n#define IPC_CONVERT_CONFIG 508\n#define IPC_CONVERT_CONFIG_END 509\n\ntypedef struct\n{\n  void (*enumProc)(intptr_t user_data, const char *desc, int fourcc);\n  intptr_t user_data;\n} converterEnumFmtStruct;\n#define IPC_CONVERT_CONFIG_ENUMFMTS 510\n/* (requires Winamp 2.92+)\n*/\n\ntypedef struct\n{\n  char cdletter;\n  char *playlist_file;\n  HWND callback_hwnd;\n\n  //filled in by winamp.exe\n  char *error;\n} burnCDStruct;\n#define IPC_BURN_CD 511\n/* (requires Winamp 5.0+)\n*/\n\ntypedef struct\n{\n  convertFileStruct *cfs;\n  int priority;\n} convertSetPriority;\n\n\n#define IPC_CONVERT_SET_PRIORITY 512\n\ntypedef struct\n{\n  convertFileStructW *cfs;\n  int priority;\n} convertSetPriorityW;\n\n\n#define IPC_CONVERT_SET_PRIORITYW 517\n// (requires Winamp 5.36+)\n\ntypedef struct\n{\n  unsigned int format; //fourcc value\n  char *item; // config item, eg \"bitrate\"\n  char *data; // buffer to recieve, or buffer that contains the data\n  int len; // length of the data buffer (only used when getting a config item)\n  char *configfile; // config file to read from\n} convertConfigItem;\n\n\n#define IPC_CONVERT_CONFIG_SET_ITEM 513 // returns TRUE if successful\n#define IPC_CONVERT_CONFIG_GET_ITEM 514 // returns TRUE if successful\n\n\ntypedef struct\n{\n  const char *filename;\n  char *title; // 2048 bytes\n  int length;\n  int force_useformatting; // can set this to 1 if you want to force a url to use title formatting shit\n} waHookTitleStruct;\n\n#define IPC_HOOK_TITLES 850\n/* (requires Winamp 5.0+)\n** If you hook this message and modify the information then make sure to return TRUE.\n** If you don't hook the message then make sure you pass it on through the subclass chain.\n**\n** LRESULT CALLBACK WinampWndProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)\n** {\n**   LRESULT ret = CallWindowProc((WNDPROC)WinampProc,hwnd,umsg,wParam,lParam);\n**\n**   if(message==WM_WA_IPC && lParam==IPC_HOOK_TITLES)\n**   {\n**     waHookTitleStruct *ht = (waHookTitleStruct *) wParam;\n**     // Doing ATF stuff with ht->title, whatever...\n**     return TRUE;\n**   }\n**   return ret;\n** }\n*/\n\ntypedef struct\n{\n  const wchar_t *filename;\n  wchar_t *title; // 2048 characters\n  int length;\n  int force_useformatting; // can set this to 1 if you want to force a url to use title formatting shit\n} waHookTitleStructW;\n#define IPC_HOOK_TITLESW 851\n/* (requires Winamp 5.3+)\n** See information on IPC_HOOK_TITLES for how to process this.\n*/\n\n\n#define IPC_GETSADATAFUNC 800 \n// 0: returns a char *export_sa_get() that returns 150 bytes of data\n// 1: returns a export_sa_setreq(int want);\n\n\n#define IPC_GETVUDATAFUNC 801 \n// 0: returns a int export_vu_get(int channel) that returns 0-255 (or -1 for bad channel)\n\n\n#define IPC_ISMAINWNDVISIBLE 900\n/* (requires Winamp 5.0+)\n** int visible=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISMAINWNDVISIBLE);\n** You send this to Winamp to query if the main window is visible or not such as by\n** unchecking the option in the main right-click menu. If the main window is visible then\n** this will return 1 otherwise it returns 0.\n*/\n\n\ntypedef struct\n{\n  int numElems;\n  int *elems;\n  HBITMAP bm; // set if you want to override\n} waSetPlColorsStruct;\n\n#define IPC_SETPLEDITCOLORS 920\n/* (requires Winamp 5.0+)\n** This is sent by gen_ff when a modern skin is being loaded to set the colour scheme for\n** the playlist editor. When sent numElems is usually 6 and matches with the 6 possible\n** colours which are provided be pledit.txt from the classic skins. The elems array is\n** defined as follows:\n**\n** elems = 0  =>  normal text\n** elems = 1  =>  current text\n** elems = 2  =>  normal background\n** elems = 3  =>  selected background\n** elems = 4  =>  minibroswer foreground\n** elems = 5  =>  minibroswer background\n**\n** if(uMsg == WM_WA_IPC && lParam == IPC_SETPLEDITCOLORS)\n** {\n**   waSetPlColorsStruct* colStr = (waSetPlColorsStruct*)wp;\n**   if(colStr)\n**   {\n**      // set or inspect the colours being used (basically for gen_ff's benefit)\n**   }\n** }\n*/\n\n\ntypedef struct\n{\n  HWND wnd;\n  int xpos; // in screen coordinates\n  int ypos;\n} waSpawnMenuParms;\n\n// waSpawnMenuParms2 is used by the menubar submenus\ntypedef struct\n{\n  HWND wnd;\n  int xpos; // in screen coordinates\n  int ypos;\n  int width;\n  int height;\n} waSpawnMenuParms2;\n\n// the following IPC use waSpawnMenuParms as parameter\n#define IPC_SPAWNEQPRESETMENU 933\n#define IPC_SPAWNFILEMENU 934 //menubar\n#define IPC_SPAWNOPTIONSMENU 935 //menubar\n#define IPC_SPAWNWINDOWSMENU 936 //menubar\n#define IPC_SPAWNHELPMENU 937 //menubar\n#define IPC_SPAWNPLAYMENU 938 //menubar\n#define IPC_SPAWNPEFILEMENU 939 //menubar\n#define IPC_SPAWNPEPLAYLISTMENU 940 //menubar\n#define IPC_SPAWNPESORTMENU 941 //menubar\n#define IPC_SPAWNPEHELPMENU 942 //menubar\n#define IPC_SPAWNMLFILEMENU 943 //menubar\n#define IPC_SPAWNMLVIEWMENU 944 //menubar\n#define IPC_SPAWNMLHELPMENU 945 //menubar\n#define IPC_SPAWNPELISTOFPLAYLISTS 946\n\n\n#define WM_WA_SYSTRAY WM_USER+1\n/* This is sent by the system tray when an event happens (you might want to simulate it).\n**\n** if(uMsg == WM_WA_SYSTRAY)\n** {\n**   switch(lParam)\n**   {\n**     // process the messages sent from the tray\n**   }\n** }\n*/\n\n\n#define WM_WA_MPEG_EOF WM_USER+2\n/* Input plugins send this when they are done playing back the current file to inform\n** Winamp or anyother installed plugins that the current\n**\n** if(uMsg == WM_WA_MPEG_EOF)\n** {\n**   // do what is needed here\n** }\n*/\n\n\n//// video stuff\n\n#define IPC_IS_PLAYING_VIDEO 501 // returns >1 if playing, 0 if not, 1 if old version (so who knows):)\n#define IPC_GET_IVIDEOOUTPUT 500 // see below for IVideoOutput interface\n#define VIDEO_MAKETYPE(A,B,C,D) ((A) | ((B)<<8) | ((C)<<16) | ((D)<<24))\n#define VIDUSER_SET_INFOSTRING 0x1000\n#define VIDUSER_GET_VIDEOHWND  0x1001\n#define VIDUSER_SET_VFLIP      0x1002\n#define VIDUSER_SET_TRACKSELINTERFACE 0x1003 // give your ITrackSelector interface as param2\n#define VIDUSER_OPENVIDEORENDERER 0x1004\n#define VIDUSER_CLOSEVIDEORENDERER 0x1005\n#define VIDUSER_GETPOPUPMENU 0x1006\n#define VIDUSER_SET_INFOSTRINGW 0x1007\n\ntypedef struct\n{\n  int w;\n  int h;\n  int vflip;\n  double aspectratio;\n  unsigned int fmt;\n} VideoOpenStruct;\n\n#ifndef NO_IVIDEO_DECLARE\n#ifdef __cplusplus\n\nclass VideoOutput;\nclass SubsItem;\n\n#ifndef _NSV_DEC_IF_H_\nstruct YV12_PLANE {\n  unsigned char* baseAddr;\n  long rowBytes;\n} ;\n\nstruct YV12_PLANES {\n  YV12_PLANE y;\n  YV12_PLANE u;\n  YV12_PLANE v;\n};\n#endif\n\nclass IVideoOutput\n{\n  public:\n    virtual ~IVideoOutput() { }\n    virtual int open(int w, int h, int vflip, double aspectratio, unsigned int fmt)=0;\n    virtual void setcallback(LRESULT (*msgcallback)(void *token, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam), void *token) { (void)token; (void)msgcallback; /* to eliminate warning C4100 */ }\n    virtual void close()=0;\n    virtual void draw(void *frame)=0;\n    virtual void drawSubtitle(SubsItem *item) {UNREFERENCED_PARAMETER(item);  }\n    virtual void showStatusMsg(const char *text) {UNREFERENCED_PARAMETER(text);  }\n    virtual int get_latency() { return 0; }\n    virtual void notifyBufferState(int bufferstate) { UNREFERENCED_PARAMETER(bufferstate); } /* 0-255*/\n\tvirtual INT_PTR extended(INT_PTR param1, INT_PTR param2, INT_PTR param3) { UNREFERENCED_PARAMETER(param1); UNREFERENCED_PARAMETER(param2); UNREFERENCED_PARAMETER(param3); return 0; } // Dispatchable, eat this!\n};\n\nclass ITrackSelector \n{\n  public:\n    virtual int getNumAudioTracks()=0;\n    virtual void enumAudioTrackName(int n, const char *buf, int size)=0;\n    virtual int getCurAudioTrack()=0;\n    virtual int getNumVideoTracks()=0;\n    virtual void enumVideoTrackName(int n, const char *buf, int size)=0;\n    virtual int getCurVideoTrack()=0;\n\n    virtual void setAudioTrack(int n)=0;\n    virtual void setVideoTrack(int n)=0;\n};\n\n#endif //cplusplus\n#endif//NO_IVIDEO_DECLARE\n\n// these messages are callbacks that you can grab by subclassing the winamp window\n\n// wParam = \n#define IPC_CB_WND_EQ 0 // use one of these for the param\n#define IPC_CB_WND_PE 1\n#define IPC_CB_WND_MB 2\n#define IPC_CB_WND_VIDEO 3\n#define IPC_CB_WND_MAIN 4\n\n#define IPC_CB_ONSHOWWND 600 \n#define IPC_CB_ONHIDEWND 601 \n\n#define IPC_CB_GETTOOLTIP 602\n\n#define IPC_CB_MISC 603\n    #define IPC_CB_MISC_TITLE 0  // start of playing/stop/pause\n    #define IPC_CB_MISC_VOLUME 1 // volume/pan\n    #define IPC_CB_MISC_STATUS 2 // start playing/stop/pause/ffwd/rwd\n    #define IPC_CB_MISC_EQ 3\n    #define IPC_CB_MISC_INFO 4\n    #define IPC_CB_MISC_VIDEOINFO 5\n    #define IPC_CB_MISC_TITLE_RATING 6 // (5.5+ for when the rating is changed via the songticker menu on current file)\n\n/* Example of using IPC_CB_MISC_STATUS to detect the start of track playback with 5.x\n**\n** if(lParam == IPC_CB_MISC && wParam == IPC_CB_MISC_STATUS)\n** {\n**   if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING) == 1 &&\n**      !SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETOUTPUTTIME))\n**   {\n**     char* file = (char*)SendMessage(hwnd_winamp,WM_WA_IPC,\n**                  SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS),IPC_GETPLAYLISTFILE);\n**     // only output if a valid file was found\n**     if(file)\n**     {\n**       MessageBox(hwnd_winamp,file,\"starting\",0);\n**       // or do something else that you need to do\n**     }\n**   }\n** }\n*/\n\n\n#define IPC_CB_CONVERT_STATUS 604 // param value goes from 0 to 100 (percent)\n#define IPC_CB_CONVERT_DONE   605\n\n\n#define IPC_ADJUST_FFWINDOWSMENUPOS 606\n/* (requires Winamp 2.9+)\n** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_FFWINDOWSMENUPOS);\n** This will move where Winamp expects the freeform windows in the menubar windows main\n** menu. This is useful if you wish to insert a menu item above extra freeform windows.\n*/\n\n\n#define IPC_ISDOUBLESIZE 608\n/* (requires Winamp 5.0+)\n** int dsize=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISDOUBLESIZE);\n** You send this to Winamp to query if the double size mode is enabled or not.\n** If it is on then this will return 1 otherwise it will return 0.\n*/\n\n\n#define IPC_ADJUST_FFOPTIONSMENUPOS 609\n/* (requires Winamp 2.9+)\n** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_FFOPTIONSMENUPOS);\n** moves where winamp expects the freeform preferences item in the menubar windows main\n** menu. This is useful if you wish to insert a menu item above the preferences item.\n**\n** Note: This setting was ignored by gen_ff until it was fixed in 5.1\n**       gen_ff would assume thatthe menu position was 11 in all cases and so when you\n**       had two plugins attempting to add entries into the main right click menu it\n**       would cause the 'colour themes' submenu to either be incorrectly duplicated or\n**       to just disappear.instead.\n*/\n\n\n#define IPC_GETTIMEDISPLAYMODE 610\n/* (requires Winamp 5.0+)\n** int mode=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETTIMEDISPLAYMODE);\n** This will return the status of the time display i.e. shows time elapsed or remaining.\n** This returns 0 if Winamp is displaying time elapsed or 1 for the time remaining.\n*/\n\n\n#define IPC_SETVISWND 611\n/* (requires Winamp 5.0+)\n** int viswnd=(HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)viswnd,IPC_SETVISWND);\n** This allows you to set a window to receive the following message commands (which are\n** used as part of the modern skin integration).\n** When you have finished or your visualisation is closed then send wParam as zero to\n** ensure that things are correctly tidied up.\n*/\n\n/* The following messages are received as the LOWORD(wParam) of the WM_COMMAND message.\n** See %SDK%\\winamp\\wa5vis.txt for more info about visualisation integration in Winamp.\n*/\n#define ID_VIS_NEXT                     40382\n#define ID_VIS_PREV                     40383\n#define ID_VIS_RANDOM                   40384\n#define ID_VIS_FS                       40389\n#define ID_VIS_CFG                      40390\n#define ID_VIS_MENU                     40391\n\n\n#define IPC_GETVISWND 612\n/* (requires Winamp 5.0+)\n** int viswnd=(HWND)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVISWND);\n** This returns a HWND to the visualisation command handler window if set by IPC_SETVISWND.\n*/\n\n\n#define IPC_ISVISRUNNING 613\n/* (requires Winamp 5.0+)\n** int visrunning=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISVISRUNNING);\n** This will return 1 if a visualisation is currently running and 0 if one is not running.\n*/\n\n\n#define IPC_CB_VISRANDOM 628 // param is status of random\n\n\n#define IPC_SETIDEALVIDEOSIZE 614\n/* (requires Winamp 5.0+)\n** This is sent by Winamp back to itself so it can be trapped and adjusted as needed with\n** the desired width in HIWORD(wParam) and the desired height in LOWORD(wParam).\n**\n** if(uMsg == WM_WA_IPC){\n**   if(lParam == IPC_SETIDEALVIDEOSIZE){\n**      wParam = MAKEWPARAM(height,width);\n**   }\n** }\n*/\n\n\n#define IPC_GETSTOPONVIDEOCLOSE 615\n/* (requires Winamp 5.0+)\n** int sovc=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETSTOPONVIDEOCLOSE);\n** This will return 1 if 'stop on video close' is enabled and 0 if it is disabled.\n*/\n\n\n#define IPC_SETSTOPONVIDEOCLOSE 616\n/* (requires Winamp 5.0+)\n** int sovc=SendMessage(hwnd_winamp,WM_WA_IPC,enabled,IPC_SETSTOPONVIDEOCLOSE);\n** Set enabled to 1 to enable and 0 to disable the 'stop on video close' option.\n*/\n\n\ntypedef struct {\n  HWND hwnd;\n  int uMsg;\n  WPARAM wParam;\n  LPARAM lParam;\n} transAccelStruct;\n\n#define IPC_TRANSLATEACCELERATOR 617\n/* (requires Winamp 5.0+)\n** (deprecated as of 5.53x+)\n*/\n\ntypedef struct {\n  int cmd;\n  int x;\n  int y;\n  int align;\n} windowCommand; // send this as param to an IPC_PLCMD, IPC_MBCMD, IPC_VIDCMD\n\n\n#define IPC_CB_ONTOGGLEAOT 618 \n\n\n#define IPC_GETPREFSWND 619\n/* (requires Winamp 5.0+)\n** HWND prefs = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETPREFSWND);\n** This will return a handle to the preferences dialog if it is open otherwise it will\n** return zero. A simple check with the OS api IsWindow(..) is a good test if it's valid.\n**\n** e.g.  this will open (or close if already open) the preferences dialog and show if we\n**       managed to get a valid \n** SendMessage(hwnd_winamp,WM_COMMAND,MAKEWPARAM(WINAMP_OPTIONS_PREFS,0),0);\n** MessageBox(hwnd_winamp,(IsWindow((HWND)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETPREFSWND))?\"Valid\":\"Not Open\"),0,MB_OK);\n*/\n\n\n#define IPC_SET_PE_WIDTHHEIGHT 620\n/* (requires Winamp 5.0+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&point,IPC_SET_PE_WIDTHHEIGHT);\n** You pass a pointer to a POINT structure which holds the width and height and Winamp\n** will set the playlist editor to that size (this is used by gen_ff on skin changes).\n** There does not appear to be any bounds limiting with this so it is possible to create\n** a zero size playlist editor window (which is a pretty silly thing to do).\n*/\n\n\n#define IPC_GETLANGUAGEPACKINSTANCE 621\n/* (requires Winamp 5.0+)\n** HINSTANCE hInst = (HINSTANCE)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLANGUAGEPACKINSTANCE);\n** This will return the HINSTANCE to the currently used language pack file for winamp.exe\n**\n** (5.5+)\n** If you pass 1 in wParam then you will have zero returned if a language pack is in use.\n** if(!SendMessage(hwnd_winamp,WM_WA_IPC,1,IPC_GETLANGUAGEPACKINSTANCE)){\n**   // winamp is currently using a language pack\n** }\n**\n** If you pass 2 in wParam then you will get the path to the language pack folder.\n** wchar_t* lngpackfolder = (wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,2,IPC_GETLANGUAGEPACKINSTANCE);\n**\n** If you pass 3 in wParam then you will get the path to the currently extracted language pack.\n** wchar_t* lngpack = (wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,3,IPC_GETLANGUAGEPACKINSTANCE);\n**\n** If you pass 4 in wParam then you will get the name of the currently used language pack.\n** wchar_t* lngname = (char*)SendMessage(hwnd_winamp,WM_WA_IPC,4,IPC_GETLANGUAGEPACKINSTANCE);\n*/\n#define LANG_IDENT_STR 0\n#define LANG_LANG_CODE 1\n#define LANG_COUNTRY_CODE 2\n/*\n** (5.51+)\n** If you pass 5 in LOWORD(wParam) then you will get the ident string/code string\n** (based on the param passed in the HIWORD(wParam) of the currently used language pack.\n** The string returned with LANG_IDENT_STR is used to represent the language that the\n** language pack is intended for following ISO naming conventions for consistancy.\n**\n** wchar_t* ident_str = (wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,MAKEWPARAM(5,LANG_XXX),IPC_GETLANGUAGEPACKINSTANCE);\n**\n** e.g.\n** For the default language it will return the following for the different LANG_XXX codes\n**    LANG_IDENT_STR ->     \"en-US\" (max buffer size of this is 9 wchar_t)\n**    LANG_LANG_CODE ->     \"en\"    (language code)\n**    LANG_COUNTRY_CODE ->  \"US\"    (country code)\n**\n** On pre 5.51 installs you can get LANG_IDENT_STR using the following method\n** (you'll have to custom process the string returned if you want the langugage or country but that's easy ;) )\n**\n** #define LANG_PACK_LANG_ID 65534 (if you don't have lang.h)\n** HINSTANCE hInst = (HINSTANCE)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLANGUAGEPACKINSTANCE);\n** TCHAR buffer[9] = {0};\n** LoadString(hInst,LANG_PACK_LANG_ID,buffer,sizeof(buffer));\n**\n**\n**\n** The following example shows how using the basic api will allow you to load the playlist\n** context menu resource from the currently loaded language pack or it will fallback to\n** the default winamp.exe instance.\n**\n** HINSTANCE lang = (HINSTANCE)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLANGUAGEPACKINSTANCE);\n** HMENU popup = GetSubMenu(GetSubMenu((LoadMenu(lang?lang:GetModuleHandle(0),MAKEINTRESOURCE(101))),2),5);\n**   // do processing as needed on the menu before displaying it\n**   TrackPopupMenuEx(orig,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,rc.left,rc.bottom,hwnd_owner,0);\n**   DestroyMenu(popup);\n**\n** If you need a specific menu handle then look at IPC_GET_HMENU for more information.\n*/\n\n\n#define IPC_CB_PEINFOTEXT 622 // data is a string, ie: \"04:21/45:02\"\n\n\n#define IPC_CB_OUTPUTCHANGED 623 // output plugin was changed in config\n\n\n#define IPC_GETOUTPUTPLUGIN 625\n/* (requires Winamp 5.0+)\n** char* outdll = (char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETOUTPUTPLUGIN);\n** This returns a string of the current output plugin's dll name.\n** e.g. if the directsound plugin was selected then this would return 'out_ds.dll'.\n*/\n\n\n#define IPC_SETDRAWBORDERS 626\n/* (requires Winamp 5.0+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,enabled,IPC_SETDRAWBORDERS);\n** Set enabled to 1 to enable and 0 to disable drawing of the playlist editor and winamp\n** gen class windows (used by gen_ff to allow it to draw its own window borders).\n*/\n\n\n#define IPC_DISABLESKINCURSORS 627\n/* (requires Winamp 5.0+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,enabled,IPC_DISABLESKINCURSORS);\n** Set enabled to 1 to enable and 0 to disable the use of skinned cursors.\n*/\n\n\n#define IPC_GETSKINCURSORS 628\n/* (requires Winamp 5.36+)\n** data = (WACURSOR)cursorId. (check wa_dlg.h for values)\n*/\n\n\n#define IPC_CB_RESETFONT 629\n\n\n#define IPC_IS_FULLSCREEN 630\n/* (requires Winamp 5.0+)\n** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_FULLSCREEN);\n** This will return 1 if the video or visualisation is in fullscreen mode or 0 otherwise.\n*/\n\n\n#define IPC_SET_VIS_FS_FLAG 631\n/* (requires Winamp 5.0+)\n** A vis should send this message with 1/as param to notify winamp that it has gone to or has come back from fullscreen mode\n*/\n\n\n#define IPC_SHOW_NOTIFICATION 632\n\n\n#define IPC_GETSKININFO 633\n#define IPC_GETSKININFOW 1633\n/* (requires Winamp 5.0+)\n** This is a notification message sent to the main Winamp window by itself whenever it\n** needs to get information to be shown about the current skin in the 'Current skin\n** information' box on the main Skins page in the Winamp preferences.\n**\n** When this notification is received and the current skin is one you are providing the\n** support for then you return a valid buffer for Winamp to be able to read from with\n** information about it such as the name of the skin file.\n**\n** if(uMsg == WM_WA_IPC && lParam == IPC_GETSKININFO){\n**   if(is_our_skin()){\n**      return is_our_skin_name();\n**   }\n** }\n*/\n\n\n#define IPC_GET_MANUALPLADVANCE 634\n/* (requires Winamp 5.03+)\n** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_MANUALPLADVANCE);\n** IPC_GET_MANUALPLADVANCE returns the status of the Manual Playlist Advance.\n** If enabled this will return 1 otherwise it will return 0.\n*/\n\n\n#define IPC_SET_MANUALPLADVANCE 635\n/* (requires Winamp 5.03+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_MANUALPLADVANCE);\n** IPC_SET_MANUALPLADVANCE sets the status of the Manual Playlist Advance option.\n** Set value = 1 to turn it on and value = 0 to turn it off.\n*/\n\n\n#define IPC_GET_NEXT_PLITEM 636\n/* (requires Winamp 5.04+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_EOF_GET_NEXT_PLITEM);\n**\n** Sent to Winamp's main window when an item has just finished playback or the next\n** button has been pressed and requesting the new playlist item number to go to.\n**\n** Subclass this message in your application to return the new item number.\n** Return -1 for normal Winamp operation (default) or the new item number in\n** the playlist to be played instead of the originally selected next track.\n**\n** This is primarily provided for the JTFE plugin (gen_jumpex.dll).\n*/\n\n\n#define IPC_GET_PREVIOUS_PLITEM 637\n/* (requires Winamp 5.04+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_EOF_GET_PREVIOUS_PLITEM);\n**\n** Sent to Winamp's main window when the previous button has been pressed and Winamp is\n** requesting the new playlist item number to go to.\n**\n** Return -1 for normal Winamp operation (default) or the new item number in\n** the playlist to be played instead of the originally selected previous track.\n**\n** This is primarily provided for the JTFE plugin (gen_jumpex.dll).\n*/\n\n\n#define IPC_IS_WNDSHADE 638\n/* (requires Winamp 5.04+)\n** int is_shaded=SendMessage(hwnd_winamp,WM_WA_IPC,wnd,IPC_IS_WNDSHADE);\n** Pass 'wnd' as an id as defined for IPC_GETWND or pass -1 to query the status of the\n** main window. This returns 1 if the window is in winshade mode and 0 if it is not.\n** Make sure you only test for this on a 5.04+ install otherwise you get a false result.\n** (See the notes about unhandled WM_WA_IPC messages).\n*/\n\n\n#define IPC_SETRATING 639 \n/* (requires Winamp 5.04+ with ML)\n** int rating=SendMessage(hwnd_winamp,WM_WA_IPC,rating,IPC_SETRATING);\n** This will allow you to set the 'rating' on the current playlist entry where 'rating'\n** is an integer value from 0 (no rating) to 5 (5 stars).\n**\n** The following example should correctly allow you to set the rating for any specified\n** playlist entry assuming of course that you're trying to get a valid playlist entry.\n**\n** void SetPlaylistItemRating(int item_to_set, int rating_to_set){\n** int cur_pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS);\n**   SendMessage(hwnd_winamp,WM_WA_IPC,item_to_set,IPC_SETPLAYLISTPOS);\n**   SendMessage(hwnd_winamp,WM_WA_IPC,rating_to_set,IPC_SETRATING);\n**   SendMessage(hwnd_winamp,WM_WA_IPC,cur_pos,IPC_SETPLAYLISTPOS);\n** }\n*/\n\n\n#define IPC_GETRATING 640 \n/* (requires Winamp 5.04+ with ML)\n** int rating=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETRATING);\n** This returns the current playlist entry's rating between 0 (no rating) to 5 (5 stars).\n**\n** The following example should correctly allow you to get the rating for any specified\n** playlist entry assuming of course that you're trying to get a valid playlist entry.\n**\n** int GetPlaylistItemRating(int item_to_get, int rating_to_set){\n** int cur_pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS), rating = 0;\n**   SendMessage(hwnd_winamp,WM_WA_IPC,item_to_get,IPC_SETPLAYLISTPOS);\n**   rating = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETRATING);\n**   SendMessage(hwnd_winamp,WM_WA_IPC,cur_pos,IPC_SETPLAYLISTPOS);\n**   return rating;\n** }\n*/\n\n\n#define IPC_GETNUMAUDIOTRACKS 641\n/* (requires Winamp 5.04+)\n** int n = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETNUMAUDIOTRACKS);\n** This will return the number of audio tracks available from the currently playing item.\n*/\n\n\n#define IPC_GETNUMVIDEOTRACKS 642\n/* (requires Winamp 5.04+)\n** int n = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETNUMVIDEOTRACKS);\n** This will return the number of video tracks available from the currently playing item.\n*/\n\n\n#define IPC_GETAUDIOTRACK 643\n/* (requires Winamp 5.04+)\n** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETAUDIOTRACK);\n** This will return the id of the current audio track for the currently playing item.\n*/\n\n\n#define IPC_GETVIDEOTRACK 644\n/* (requires Winamp 5.04+)\n** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVIDEOTRACK);\n** This will return the id of the current video track for the currently playing item.\n*/\n\n\n#define IPC_SETAUDIOTRACK 645\n/* (requires Winamp 5.04+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,track,IPC_SETAUDIOTRACK);\n** This allows you to switch to a new audio track (if supported) in the current playing file.\n*/\n\n\n#define IPC_SETVIDEOTRACK 646\n/* (requires Winamp 5.04+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,track,IPC_SETVIDEOTRACK);\n** This allows you to switch to a new video track (if supported) in the current playing file.\n*/\n\n\n#define IPC_PUSH_DISABLE_EXIT 647\n/* (requires Winamp 5.04+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_PUSH_DISABLE_EXIT);\n** This will let you disable or re-enable the UI exit functions (close button, context\n** menu, alt-f4). Remember to call IPC_POP_DISABLE_EXIT when you are done doing whatever\n** was required that needed to prevent exit otherwise you have to kill the Winamp process.\n*/\n\n\n#define IPC_POP_DISABLE_EXIT  648\n/* (requires Winamp 5.04+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_POP_DISABLE_EXIT);\n** See IPC_PUSH_DISABLE_EXIT\n*/\n\n\n#define IPC_IS_EXIT_ENABLED 649\n/* (requires Winamp 5.04+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_EXIT_ENABLED);\n** This will return 0 if the 'exit' option of Winamp's menu is disabled and 1 otherwise.\n*/\n\n\n#define IPC_IS_AOT 650\n/* (requires Winamp 5.04+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_AOT);\n** This will return the status of the always on top flag.\n** Note: This may not match the actual TOPMOST window flag while another fullscreen\n** application is focused if the user has the 'Disable always on top while fullscreen\n** applications are focused' option under the  General Preferences page is checked.\n*/\n\n\n#define IPC_USES_RECYCLEBIN 651\n/* (requires Winamp 5.09+)\n** int use_bin=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USES_RECYCLEBIN);\n** This will return 1 if the deleted file should be sent to the recycle bin or\n** 0 if deleted files should be deleted permanently (default action for < 5.09).\n**\n** Note: if you use this on pre 5.09 installs of Winamp then it will return 1 which is\n** not correct but is due to the way that SendMessage(..) handles un-processed messages.\n** Below is a quick case for checking if the returned value is correct.\n**\n** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USES_RECYCLEBIN) &&\n**    SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION)>=0x5009)\n** {\n**   // can safely follow the option to recycle the file\n** }\n** else\n*  {\n**   // need to do a permanent delete of the file\n** }\n*/\n\n\n#define IPC_FLUSHAUDITS 652\n/*\n** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_FLUSHAUDITS);\n** \n** Will flush any pending audits in the global audits queue\n**\n*/\n\n#define IPC_GETPLAYITEM_START 653\n#define IPC_GETPLAYITEM_END   654\n\n\n#define IPC_GETVIDEORESIZE 655\n#define IPC_SETVIDEORESIZE 656\n\n\n#define IPC_INITIAL_SHOW_STATE 657\n/* (requires Winamp 5.36+)\n** int show_state = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INITIAL_SHOW_STATE);\n** returns the processed value of nCmdShow when Winamp was started\n** (see MSDN documentation the values passed to WinMain(..) for what this should be)\n**\n** e.g.\n** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INITIAL_SHOW_STATE) == SW_SHOWMINIMIZED){\n**   // we are starting minimised so process as needed (keep our window hidden)\n** }\n**\n** Useful for seeing if winamp was run minimised on startup so you can act accordingly.\n** On pre-5.36 versions this will effectively return SW_NORMAL/SW_SHOWNORMAL due to the\n** handling of unknown apis returning 1 from Winamp.\n*/\n\n// >>>>>>>>>>> Next is 658\n\n#define IPC_PLCMD  1000 \n\n#define PLCMD_ADD  0\n#define PLCMD_REM  1\n#define PLCMD_SEL  2\n#define PLCMD_MISC 3\n#define PLCMD_LIST 4\n\n//#define IPC_MBCMD  1001 \n\n#define MBCMD_BACK    0\n#define MBCMD_FORWARD 1\n#define MBCMD_STOP    2\n#define MBCMD_RELOAD  3\n#define MBCMD_MISC  4\n\n#define IPC_VIDCMD 1002 \n\n#define VIDCMD_FULLSCREEN 0\n#define VIDCMD_1X         1\n#define VIDCMD_2X         2\n#define VIDCMD_LIB        3\n#define VIDPOPUP_MISC     4\n\n//#define IPC_MBURL       1003 //sets the URL\n//#define IPC_MBGETCURURL 1004 //copies the current URL into wParam (have a 4096 buffer ready)\n//#define IPC_MBGETDESC   1005 //copies the current URL description into wParam (have a 4096 buffer ready)\n//#define IPC_MBCHECKLOCFILE 1006 //checks that the link file is up to date (otherwise updates it). wParam=parent HWND\n//#define IPC_MBREFRESH   1007 //refreshes the \"now playing\" view in the library\n//#define IPC_MBGETDEFURL 1008 //copies the default URL into wParam (have a 4096 buffer ready)\n\n#define IPC_STATS_LIBRARY_ITEMCNT 1300 // updates library count status\n\n/*\n** IPC's in the message range 2000 - 3000 are reserved internally for freeform messages.\n** These messages are taken from ff_ipc.h which is part of the Modern skin integration.\n*/\n\n#define IPC_FF_FIRST 2000\n\n#define IPC_FF_COLOURTHEME_CHANGE IPC_FF_ONCOLORTHEMECHANGED\n#define IPC_FF_ONCOLORTHEMECHANGED IPC_FF_FIRST + 3\n/*\n** This is a notification message sent when the user changes the colour theme in a Modern\n** skin and can also be detected when the Modern skin is first loaded as the gen_ff plugin\n** applies relevant settings and styles (like the colour theme).\n**\n** The value of wParam is the name of the new color theme being switched to.\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(const char*)colour_theme_name,IPC_FF_ONCOLORTHEMECHANGED);\n**\n** (IPC_FF_COLOURTHEME_CHANGE is the name i (DrO) was using before getting a copy of\n** ff_ipc.h with the proper name in it).\n*/\n\n\n#define IPC_FF_ISMAINWND IPC_FF_FIRST + 4\n/*\n** int ismainwnd = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)test_wnd,IPC_FF_ISMAINWND);\n**\n** This allows you to determine if the window handle passed to it is a modern skin main\n** window or not. If it is a main window or any of its windowshade variants then it will\n** return 1.\n**\n** Because of the way modern skins are implemented, it is possible for this message to\n** return a positive test result for a number of window handles within the current Winamp\n** process. This appears to be because you can have a visible main window, a compact main\n** window and also a winshaded version.\n**\n** The following code example below is one way of seeing how this api works since it will\n** enumerate all windows related to Winamp at the time and allows you to process as\n** required when a detection happens.\n**\n**\n** EnumThreadWindows(GetCurrentThreadId(),enumWndProc,0);\n**\n** BOOL CALLBACK enumWndProc(HWND hwnd, LPARAM lParam){\n**\n**   if(SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)hwnd,IPC_FF_ISMAINWND)){\n**     // do processing in here \n**     // or continue the enum for other main windows (if they exist)\n**     // and just comment out the line below\n**     return 0;\n**   }\n**   return 1;\n** }\n*/\n\n\n#define IPC_FF_GETCONTENTWND IPC_FF_FIRST + 5\n/*\n** HWND wa2embed = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)test_wnd,IPC_FF_GETCONTENTWND);\n**\n** This will return the Winamp 2 window that is embedded in the window's container\n** i.e. if hwnd is the playlist editor windowshade hwnd then it will return the Winamp 2\n**      playlist editor hwnd.\n**\n** If no content is found such as the window has nothing embedded then this will return\n** the hwnd passed to it.\n*/\n\n\n#define IPC_FF_NOTIFYHOTKEY IPC_FF_FIRST + 6\n/*\n** This is a notification message sent when the user uses a global hotkey combination\n** which had been registered with the gen_hotkeys plugin.\n**\n** The value of wParam is the description of the hotkey as passed to gen_hotkeys.\n** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(const char*)hotkey_desc,IPC_FF_NOTIFYHOTKEY);\n*/\n\n#define IPC_FF_LAST  3000\n\n\n/*\n** General IPC messages in Winamp\n**\n** All notification messages appear in the lParam of the main window message proceedure.\n*/\n\n\n#define IPC_GETDROPTARGET 3001\n/* (requires Winamp 5.0+)\n** IDropTarget* IDrop = (IDropTarget*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETDROPTARGET);\n**\n** You call this to retrieve a copy of the IDropTarget interface which Winamp created for\n** handling external drag and drop operations on to it's Windows. This is only really\n** useful if you're providing an alternate interface and want your Windows to provide the\n** same drag and drop support as Winamp normally provides the user. Check out MSDN or\n** your prefered search facility for more information about the IDropTarget interface and\n** what's needed to handle it in your own instance.\n*/\n\n\n#define IPC_PLAYLIST_MODIFIED 3002 \n/* (requires Winamp 5.0+)\n** This is a notification message sent to the main Winamp window whenever the playlist is\n** modified in any way e.g. the addition/removal of a playlist entry.\n**\n** It is not a good idea to do large amounts of processing in this notification since it\n** will slow down Winamp as playlist entries are modified (especially when you're adding\n** in a large playlist).\n**\n** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYLIST_MODIFIED)\n** {\n**   // do what you need to do here\n** }\n*/\n\n\n#define IPC_PLAYING_FILE 3003 \n/* (requires Winamp 5.0+)\n** This is a notification message sent to the main Winamp window when playback begins for\n** a file. This passes the full filepath in the wParam of the message received.\n**\n** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYING_FILE)\n** {\n**   // do what you need to do here, e.g.\n**   process_file((char*)wParam);\n** }\n*/\n\n\n#define IPC_PLAYING_FILEW 13003 \n/* (requires Winamp 5.0+)\n** This is a notification message sent to the main Winamp window when playback begins for\n** a file. This passes the full filepath in the wParam of the message received.\n**\n** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYING_FILEW)\n** {\n**   // do what you need to do here, e.g.\n**   process_file((wchar_t*)wParam);\n** }\n*/\n\n\n#define IPC_FILE_TAG_MAY_HAVE_UPDATED 3004\n#define IPC_FILE_TAG_MAY_HAVE_UPDATEDW 3005\n/* (requires Winamp 5.0+)\n** This is a notification message sent to the main Winamp window when a file's tag\n** (e.g. id3) may have been updated. This appears to be sent when the InfoBox(..) function\n** of the associated input plugin returns a 1 (which is the file information dialog/editor\n** call normally).\n**\n** if(uMsg == WM_WA_IPC && lParam == IPC_FILE_TAG_MAY_HAVE_UPDATED)\n** {\n**   // do what you need to do here, e.g.\n**   update_info_on_file_update((char*)wParam);\n** }\n*/\n\n\n#define IPC_ALLOW_PLAYTRACKING 3007\n/* (requires Winamp 5.0+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,allow,IPC_ALLOW_PLAYTRACKING);\n** Send allow as nonzero to allow play tracking and zero to disable the mode.\n*/\n\n\n#define IPC_HOOK_OKTOQUIT 3010 \n/* (requires Winamp 5.0+)\n** This is a notification message sent to the main Winamp window asking if it's okay to\n** close or not. Return zero to prevent Winamp from closing or return anything non-zero\n** to allow Winamp to close.\n**\n** The best implementation of this option is to let the message pass through to the\n** original window proceedure since another plugin may want to have a say in the matter\n** with regards to Winamp closing.\n**\n** if(uMsg == WM_WA_IPC && lParam == IPC_HOOK_OKTOQUIT)\n** {\n**   // do what you need to do here, e.g.\n**   if(no_shut_down())\n**   {\n**     return 1;\n**   }\n** }\n*/\n\n\n#define IPC_WRITECONFIG 3011\n/* (requires Winamp 5.0+)\n** SendMessage(hwnd_winamp,WM_WA_IPC,write_type,IPC_WRITECONFIG);\n**\n** Send write_type as 2 to write all config settings and the current playlist.\n**\n** Send write_type as 1 to write the playlist and common settings.\n** This won't save the following ini settings::\n**\n**   defext, titlefmt, proxy, visplugin_name, dspplugin_name, check_ft_startup,\n**   visplugin_num, pe_fontsize, visplugin_priority, visplugin_autoexec, dspplugin_num,\n**   sticon, splash, taskbar, dropaotfs, ascb_new, ttips, riol, minst, whichicon,\n**   whichicon2, addtolist, snap, snaplen, parent, hilite, disvis, rofiob, shownumsinpl,\n**   keeponscreen, eqdsize, usecursors, fixtitles, priority, shuffle_morph_rate,\n**   useexttitles, bifont, inet_mode, ospb, embedwnd_freesize, no_visseh\n** (the above was valid for 5.1)\n**\n** Send write_type as 0 to write the common and less common settings and no playlist.\n*/\n\n\n#define IPC_UPDATE_URL 3012\n// pass the URL (char *) in lparam, will be free()'d on done. \n\n\n#define IPC_GET_RANDFUNC 3015 // returns a function to get a random number\n/* (requires Winamp 5.1+)\n** int (*randfunc)(void) = (int(*)(void))SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_GET_RANDFUNC);\n** if(randfunc && randfunc != 1){\n**   randfunc();\n** }\n**\n** This will return a positive 32-bit number (essentially 31-bit).\n** The check for a returned value of 1 is because that's the default return value from\n** SendMessage(..) when it is not handled so is good to check for it in this situation.\n*/\n\n\n#define IPC_METADATA_CHANGED 3017 \n/* (requires Winamp 5.1+)\n** int changed=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(char*)field,IPC_METADATA_CHANGED);\n** a plugin can SendMessage this to winamp if internal metadata has changes.\n** wParam should be a char * of what field changed\n**\n** Currently used for internal actions (and very few at that) the intent of this api is\n** to allow a plugin to call it when metadata has changed in the current playlist entry\n** e.g.a new id3v2 tag was found in a stream\n**\n** The wparam value can either be NULL or a pointer to an ansi string for the metadata\n** which has changed. This can be thought of as an advanced version of IPC_UPDTITLE and\n** could be used to allow for update of the current title when a specific tag changed.\n**\n** Not recommended to be used since there is not the complete handling implemented in\n** Winamp for it at the moment.\n*/\n\n\n#define IPC_SKIN_CHANGED 3018 \n/* (requires Winamp 5.1+)\n** This is a notification message sent to the main Winamp window by itself whenever\n** the skin in use is changed. There is no information sent by the wParam for this.\n**\n** if(message == WM_WA_IPC && lparam == IPC_SKIN_CHANGED)\n** {\n**   // do what you need to do to handle skin changes, e.g. call WADlg_init(hwnd_winamp);\n** }\n*/\n\n\n#define IPC_REGISTER_LOWORD_COMMAND 3019 \n/* (requires Winamp 5.1+)\n** WORD id = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REGISTER_LOWORD_COMMAND);\n** This will assign you a unique id for making your own commands such as for extra menu\n** entries. The starting value returned by this message will potentially change as and\n** when the main resource file of Winamp is updated with extra data so assumptions cannot\n** be made on what will be returned and plugin loading order will affect things as well.\n\n** 5.33+\n** If you want to reserve more than one id, you can pass the number of ids required in wParam\n*/\n\n\n#define IPC_GET_DISPATCH_OBJECT 3020  // gets winamp main IDispatch * (for embedded webpages)\n#define IPC_GET_UNIQUE_DISPATCH_ID 3021 // gives you a unique dispatch ID that won't conflict with anything in winamp's IDispatch *\n#define IPC_ADD_DISPATCH_OBJECT 3022 // add your own dispatch object into winamp's.  This lets embedded webpages access your functions\n// pass a pointer to DispatchInfo (see below).  Winamp makes a copy of all this data so you can safely delete it later\ntypedef struct \n{\n  wchar_t *name; // filled in by plugin, make sure it's a unicode string!! (i.e. L\"myObject\" instead of \"myObject).\n  struct IDispatch *dispatch; // filled in by plugin \n  DWORD id; // filled in by winamp on return\n} DispatchInfo;\n\n// see IPC_JSAPI2_GET_DISPATCH_OBJECT for version 2 of the Dispatchable scripting interface\n\n#define IPC_GET_PROXY_STRING 3023\n/* (requires Winamp 5.11+)\n** char* proxy_string=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_PROXY_STRING);\n** This will return the same string as is shown on the General Preferences page.\n*/\n\n\n#define IPC_USE_REGISTRY 3024 \n/* (requires Winamp 5.11+)\n** int reg_enabled=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USE_REGISTRY);\n** This will return 0 if you should leave your grubby hands off the registry (i.e. for\n** lockdown mode). This is useful if Winamp is run from a USB drive and you can't alter\n** system settings, etc.\n*/\n\n\n#define IPC_GET_API_SERVICE 3025 \n/* (requires Winamp 5.12+)\n** api_service* api_service = (api_service)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_API_SERVICE);\n** This api will return Winamp's api_service pointer (which is what Winamp3 used, heh).\n** If this api is not supported in the Winamp version that is being used at the time then\n** the returned value from this api will be 1 which is a good version check.\n**\n** As of 5.12 there is support for .w5s plugins which reside in %WinampDir%\\System and\n** are intended for common code that can be shared amongst other plugins e.g. jnetlib.w5s\n** which contains jnetlib in one instance instead of being duplicated multiple times in\n** all of the plugins which need internet access.\n**\n** Details on the .w5s specifications will come at some stage (possibly).\n*/\n\n\ntypedef struct {\n  const wchar_t *filename;\n  const wchar_t *metadata;\n  wchar_t *ret;\n  size_t retlen;\n} extendedFileInfoStructW;\n\n#define IPC_GET_EXTENDED_FILE_INFOW 3026 \n/* (requires Winamp 5.13+)\n** Pass a pointer to the above struct in wParam\n*/\n\n\n#define IPC_GET_EXTENDED_FILE_INFOW_HOOKABLE 3027\n#define IPC_SET_EXTENDED_FILE_INFOW 3028 \n/* (requires Winamp 5.13+)\n** Pass a pointer to the above struct in wParam\n*/\n\n\n#define IPC_PLAYLIST_GET_NEXT_SELECTED 3029\n/* (requires 5.2+)\n** int pl_item = SendMessage(hwnd_winamp,WM_WA_IPC,start,IPC_PLAYLIST_GET_NEXT_SELECTED);\n**\n** This works just like the ListView_GetNextItem(..) macro for ListView controls.\n** 'start' is the index of the playlist item that you want to begin the search after or\n** set this as -1 for the search to begin with the first item of the current playlist.\n**\n** This will return the index of the selected playlist according to the 'start' value or\n** it returns -1 if there is no selection or no more selected items according to 'start'.\n**\n** Quick example:\n**\n** int sel = -1;\n** // keep incrementing the start of the search so we get all of the selected entries\n** while((sel = SendMessage(hwnd_winamp,WM_WA_IPC,sel,IPC_PLAYLIST_GET_NEXT_SELECTED))!=-1){\n**   // show the playlist file entry of the selected item(s) if there were any\n**   MessageBox(hwnd_winamp,(char*)SendMessage(hwnd_winamp,WM_WA_IPC,sel,IPC_GETPLAYLISTFILE),0,0);\n** }\n*/\n\n\n#define IPC_PLAYLIST_GET_SELECTED_COUNT 3030\n/* (requires 5.2+)\n** int selcnt = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_PLAYLIST_GET_SELECTED_COUNT);\n** This will return the number of selected playlist entries.\n*/\n\n\n#define IPC_GET_PLAYING_FILENAME 3031\n// returns wchar_t * of the currently playing filename\n\n#define IPC_OPEN_URL 3032\n// send either ANSI or Unicode string (it'll figure it out, but it MUST start with \"h\"!, so don't send ftp:// or anything funny)\n// you can also send this one from another process via WM_COPYDATA (unicode only)\n\n\n#define IPC_USE_UXTHEME_FUNC 3033\n/* (requires Winamp 5.35+)\n** int ret = SendMessage(hwnd_winamp,WM_WA_IPC,param,IPC_USE_UXTHEME_FUNC);\n** param can be IPC_ISWINTHEMEPRESENT or IPC_ISAEROCOMPOSITIONACTIVE or a valid hwnd.\n**\n** If you pass a hwnd then it will apply EnableThemeDialogTexture(ETDT_ENABLETAB)\n** so your tabbed dialogs can use the correct theme (on supporting OSes ie XP+).\n**\n** Otherwise this will return a value based on the param passed (as defined below).\n** For compatability, the return value will be zero on success (as 1 is returned\n** for unsupported ipc calls on older Winamp versions)\n*/\n  #define IPC_ISWINTHEMEPRESENT 0\n/* This will return 0 if uxtheme.dll is present\n** int isthemethere = !SendMessage(hwnd_winamp,WM_WA_IPC,IPC_ISWINTHEMEPRESENT,IPC_USE_UXTHEME_FUNC);\n*/\n  #define IPC_ISAEROCOMPOSITIONACTIVE 1\n/* This will return 0 if aero composition is active\n** int isaero = !SendMessage(hwnd_winamp,WM_WA_IPC,IPC_ISAEROCOMPOSITIONACTIVE,IPC_USE_UXTHEME_FUNC);\n*/\n\n\n#define IPC_GET_PLAYING_TITLE 3034\n// returns wchar_t * of the current title\n\n\n#define IPC_CANPLAY 3035\n// pass const wchar_t *, returns an in_mod * or 0\n\n\ntypedef struct {\n  // fill these in...\n  size_t size; // init to sizeof(artFetchData)\n  HWND parent; // parent window of the dialogue\n\n  // fill as much of these in as you can, otherwise leave them 0\n  const wchar_t *artist;\n  const wchar_t *album;\n  int year, amgArtistId, amgAlbumId;\n\n  int showCancelAll; // if set to 1, this shows a \"Cancel All\" button on the dialogue\n\n  // winamp will fill these in if the call returns successfully:\n  void* imgData; // a buffer filled with compressed image data. free with WASABI_API_MEMMGR->sysFree()\n  int imgDataLen; // the size of the buffer\n  wchar_t type[10]; // eg: \"jpg\"\n  const wchar_t *gracenoteFileId; // if you know it\n} artFetchData;\n\n#define IPC_FETCH_ALBUMART 3036\n/* pass an artFetchData*. This will show a dialog guiding the use through choosing art, and return when it's finished\n** return values:\n** 1: error showing dialog\n** 0: success\n** -1: cancel was pressed\n** -2: cancel all was pressed\n*/\n\n#define IPC_JSAPI2_GET_DISPATCH_OBJECT 3037\n/* pass your service's unique ID, as a wchar_t * string, in wParam\n** Winamp will copy the string, so don't worry about keeping it around\n** An IDispatch * object will be returned (cast the return value from SendMessage)\n** This IDispatch can be used for scripting/automation/VB interaction\n** Pass to IE via IDocHostUIHandler::GetExternal and it will become window.external in javscript\n*/\n\n#define IPC_REGISTER_WINAMP_IPCMESSAGE 65536 \n/* (requires Winamp 5.0+)\n** DWORD id = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)name,IPC_REGISTER_WINAMP_IPCMESSAGE);\n** The value 'id' returned is > 65536 and is incremented on subsequent calls for unique\n** 'name' values passed to it. By using the same 'name' in different plugins will allow a\n** common runtime api to be provided for the currently running instance of Winamp\n** e.g.\n**   PostMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)my_param,registered_ipc);\n** Have a look at wa_hotkeys.h for an example on how this api is used in practice for a\n** custom WM_WA_IPC message.\n**\n** if(uMsg == WM_WA_IPC && lParam == id_from_register_winamp_ipcmessage){\n**   // do things\n** }\n*/\n\n#endif//_WA_IPC_H_"
  },
  {
    "path": "in_vgm/dlg_cfg.c",
    "content": "/*3456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456\n0000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999*/\n#include <windows.h>\n#include <commctrl.h>\n#include <stdio.h>\n#include <math.h>\n#include <assert.h>\n\n#include \"stdbool.h\"\n#include \"chips/mamedef.h\"\t// for (U)INTxx types\n\n#include \"VGMPlay.h\"\n#include \"VGMPlay_Intf.h\"\n#include \"in_vgm.h\"\n\n\n#define HIDE_VGM7Z\n\n#define TAB_ICON_WIDTH\t16\n#define TAB_ICON_TRANSP\t0xFF00FF\n\n\n// Dialogue box tabsheet handler\n#define NUM_CFG_TABS\t5\n#define CfgPlayback\t\thWndCfgTab[0]\n#define CfgTags\t\t\thWndCfgTab[1]\n#define Cfg7z\t\t\thWndCfgTab[2]\n#define CfgMuting\t\thWndCfgTab[3]\n#define CfgOptPan\t\thWndCfgTab[4]\n\n// sadly I can't use DLG_ITEM in another define\n//#define DLG_ITEM\t\t\t\t\t\tGetDlgItem(hWnd, DlgID)\n#define SLIDER_GETPOS(hWnd, DlgID)\t(UINT16) \\\n\t\t\t\t\t\t\t\t\t\tSendDlgItemMessage(hWnd, DlgID, TBM_GETPOS, 0, 0)\n#define SLIDER_SETPOS(hWnd, DlgID, Pos)\tSendDlgItemMessage(hWnd, DlgID, TBM_SETPOS, TRUE, Pos)\n#define CTRL_DISABLE(hWnd, DlgID)\t\tEnableWindow(GetDlgItem(hWnd, DlgID), FALSE)\n#define CTRL_ENABLE(hWnd, DlgID)\t\tEnableWindow(GetDlgItem(hWnd, DlgID), TRUE)\n#define CTRL_HIDE(hWnd, DlgID)\t\t\tShowWindow(GetDlgItem(hWnd, DlgID), SW_HIDE)\n#define CTRL_SHOW(hWnd, DlgID)\t\t\tShowWindow(GetDlgItem(hWnd, DlgID), SW_SHOW)\n#define CTRL_SET_ENABLE(hWnd, DlgID, Enable)\tEnableWindow(GetDlgItem(hWnd, DlgID), Enable)\n#define CTRL_IS_ENABLED(hWnd, DlgID, Enable)\tIsWindowEnabled(GetDlgItem(hWnd, DlgID))\n#define SETCHECKBOX(hWnd, DlgID, Check)\tSendDlgItemMessage(hWnd, DlgID, BM_SETCHECK, Check, 0)\n#define CREATE_CHILD(DlgID, DlgProc)\t\\\n\t\t\t\t\t\t\t\tCreateDialog(hPluginInst, (LPCTSTR)DlgID, hWndMain, DlgProc)\n#define COMBO_ADDSTR(hWnd, DlgID, String)\t\\\n\t\t\t\t\t\t\t\tSendDlgItemMessage(hWnd, DlgID, CB_ADDSTRING, 0, (LPARAM)String)\n#define COMBO_GETPOS(hWnd, DlgID)\t\tSendDlgItemMessage(hWnd, DlgID, CB_GETCURSEL, 0, 0)\n#define COMBO_SETPOS(hWnd, DlgID, Pos)\tSendDlgItemMessage(hWnd, DlgID, CB_SETCURSEL, Pos, 0)\n#define CHECK2BOOL(hWnd, DlgID)\t\t\t(IsDlgButtonChecked(hWnd, DlgID) == BST_CHECKED)\n\n\n// Function Prototypes from in_vgm.c\nvoid UpdatePlayback(void);\n\n\n// Function Prototypes from dlg_fileinfo.c\nvoid QueueInfoReload(void);\n\n\n// Function Prototypes\nvoid InitConfigDialog(HWND hWndMain);\nINLINE void AddTab(HWND tabCtrlWnd, int ImgIndex, char* TabTitle);\nstatic void EnableWinXPVisualStyles(HWND hWndMain);\nstatic void Slider_Setup(HWND hWndDlg, int DlgID, int Min, int Max, int BigStep, int TickFreq);\nstatic BOOL SetDlgItemFloat(HWND hDlg, int nIDDlgItem, double Value, int Precision);\nstatic int LoadConfigDialogInfo(HWND hWndDlg);\n\nBOOL CALLBACK ConfigDialogProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam);\nBOOL CALLBACK CfgDlgPlaybackProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam);\nBOOL CALLBACK CfgDlgTagsProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam);\nBOOL CALLBACK CfgDlgMutingProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam);\nBOOL CALLBACK CfgDlgOptPanProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam);\nBOOL CALLBACK CfgDlgChildProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam);\n\nstatic bool IsChipAvailable(UINT8 ChipID, UINT8 ChipSet);\nstatic void ShowMutingCheckBoxes(UINT8 ChipID, UINT8 ChipSet);\nstatic void SetMutingData(UINT32 CheckBox, bool MuteOn);\nstatic void ShowOptPanBoxes(UINT8 ChipID, UINT8 ChipSet);\nstatic void SetPanningData(UINT32 Slider, UINT16 Value, bool NoRefresh);\nvoid Dialogue_TrackChange(void);\n\n\nextern UINT32 VGMMaxLoop;\nextern UINT32 VGMPbRate;\nextern UINT32 FadeTime;\n\nextern float VolumeLevel;\nextern bool SurroundSound;\nextern bool FadeRAWLog;\n\nextern UINT8 ResampleMode;\nextern UINT8 CHIP_SAMPLING_MODE;\n\nextern CHIPS_OPTION ChipOpts[0x02];\n\nextern VGM_HEADER VGMHead;\nextern UINT8 PlayingMode;\n\n\nextern HANDLE hPluginInst;\n\nstatic HWND hWndCfgTab[NUM_CFG_TABS];\nstatic bool LoopTimeMode;\nstatic UINT8 MuteChipID = 0x00;\nstatic UINT8 MuteChipSet = 0x00;\nstatic CHIP_OPTS* MuteCOpts;\n\nvoid InitConfigDialog(HWND hWndMain)\n{\n\tHWND TabCtrlWnd;\n\tRECT TabDispRect;\n\tRECT TabRect;\n\tHIMAGELIST hImgList;\n\tunsigned int CurTab;\n\t\n\tTabCtrlWnd = GetDlgItem(hWndMain, TabCollection);\n\tInitCommonControls();\n\t\n\t// Load images for tabs\n\thImgList = ImageList_LoadImage(hPluginInst, (LPCSTR)TabIcons, TAB_ICON_WIDTH, 0,\n\t\t\t\t\t\t\t\t\tTAB_ICON_TRANSP, IMAGE_BITMAP, LR_CREATEDIBSECTION);\n\tTabCtrl_SetImageList(TabCtrlWnd, hImgList);\n\t\n\t// Add tabs\n\tAddTab(TabCtrlWnd, 0, \"Playback\");\n\tAddTab(TabCtrlWnd, 1, \"Tags\");\n#ifndef HIDE_VGM7Z\n\tAddTab(TabCtrlWnd, 2, \"VGM7z\");\n#endif\n\tAddTab(TabCtrlWnd, 3, \"Muting\");\n\tAddTab(TabCtrlWnd, 5, \"Other Opts\");\n\t\n\t// Get display rect\n\tGetWindowRect(TabCtrlWnd, &TabDispRect);\n\tGetWindowRect(hWndMain, &TabRect);\n\tOffsetRect(&TabDispRect, -TabRect.left - GetSystemMetrics(SM_CXDLGFRAME),\n\t\t\t\t\t\t\t-TabRect.top - GetSystemMetrics(SM_CYDLGFRAME) -\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGetSystemMetrics(SM_CYCAPTION));\n\tTabCtrl_AdjustRect(TabCtrlWnd, FALSE, &TabDispRect);\n\t\n\t// Create child windows\n\tCfgPlayback\t= CREATE_CHILD(DlgCfgPlayback,\tCfgDlgPlaybackProc);\n\tCfgTags\t\t= CREATE_CHILD(DlgCfgTags,\t\tCfgDlgTagsProc);\n\tCfg7z\t\t= CREATE_CHILD(DlgCfgVgm7z,\t\tCfgDlgChildProc);\n\tCfgMuting\t= CREATE_CHILD(DlgCfgMuting,\tCfgDlgMutingProc);\n\tCfgOptPan\t= CREATE_CHILD(DlgCfgOptPan,\tCfgDlgOptPanProc);\n\t\n\tEnableWinXPVisualStyles(hWndMain);\n\t\n\t// position tabs\n\tTabDispRect.right -= TabDispRect.left;\t// .right gets Tab Width\n\tTabDispRect.bottom -= TabDispRect.top;\t// .bottom gets Tab Height\n\tfor (CurTab = 0; CurTab < NUM_CFG_TABS; CurTab ++)\n\t{\n\t\tSetWindowPos(hWndCfgTab[CurTab], HWND_TOP, TabDispRect.left, TabDispRect.top,\n\t\t\t\t\tTabDispRect.right, TabDispRect.bottom, SWP_NOZORDER);\n\t}\n\t\n\t// show first tab, hide the others\n\tShowWindow(hWndCfgTab[0], SW_SHOW);\n\tfor (CurTab = 1; CurTab < NUM_CFG_TABS; CurTab ++)\n\t\tShowWindow(hWndCfgTab[CurTab], SW_HIDE);\n\t\n\treturn;\n}\n\nINLINE void AddTab(HWND tabCtrlWnd, int ImgIndex, char* TabTitle)\n{\n\tTC_ITEM newTab;\n\tint tabIndex;\n\t\n\ttabIndex = TabCtrl_GetItemCount(tabCtrlWnd);\n\tnewTab.mask = TCIF_TEXT;\n\tnewTab.mask |= (ImgIndex >= 0) ? TCIF_IMAGE : 0;\n\tnewTab.pszText = TabTitle;\n\tnewTab.iImage = ImgIndex;\n\tTabCtrl_InsertItem(tabCtrlWnd, tabIndex, &newTab);\n\t\n\treturn;\n}\n\nstatic void EnableWinXPVisualStyles(HWND hWndMain)\n{\n\tHINSTANCE dllinst;\n\tFARPROC EnThemeDlgTex;\n\tFARPROC ThemeDlgTexIsEn;\n\tunsigned int CurWnd;\n\t\n\tdllinst = LoadLibrary(\"uxtheme.dll\");\n\tif (dllinst == NULL)\n\t\treturn;\n\t\n\tEnThemeDlgTex = GetProcAddress(dllinst, \"EnableThemeDialogTexture\");\n\tThemeDlgTexIsEn = GetProcAddress(dllinst, \"IsThemeDialogTextureEnabled\");\n\tif (ThemeDlgTexIsEn == NULL || EnThemeDlgTex == NULL)\n\t\tgoto CancelXPStyles;\n\t\n\tif (ThemeDlgTexIsEn(hWndMain))\n\t{ \n#ifndef ETDT_ENABLETAB\n#define ETDT_ENABLETAB\t6\n#endif\n\t\t\n\t\t// draw pages with theme texture\n\t\tfor (CurWnd = 0; CurWnd < NUM_CFG_TABS; CurWnd ++)\n\t\t\tEnThemeDlgTex(hWndCfgTab[CurWnd], ETDT_ENABLETAB);\n\t}\n\t\nCancelXPStyles:\n\tFreeLibrary(dllinst);\n\t\n\treturn;\n}\n\n\nstatic void Slider_Setup(HWND hWndDlg, int DlgID, int Min, int Max, int BigStep, int TickFreq)\n{\n\tLONG RetVal;\n\t\n\tRetVal = SendDlgItemMessage(hWndDlg, DlgID, TBM_SETRANGE, 0, MAKELONG(Min, Max));\n\t// Note to TBM_SETTICFREQ:\n\t//  Needs Automatic Ticks enabled, draw a tick mark every x ticks.\n\tRetVal = SendDlgItemMessage(hWndDlg, DlgID, TBM_SETTICFREQ, TickFreq, 0);\n\tRetVal = SendDlgItemMessage(hWndDlg, DlgID, TBM_SETLINESIZE, 0, 1);\n\tRetVal = SendDlgItemMessage(hWndDlg, DlgID, TBM_SETPAGESIZE, 0, BigStep);\n\t\n\treturn;\n}\n\nstatic BOOL SetDlgItemFloat(HWND hDlg, int nIDDlgItem, double Value, int Precision)\n{\n\tchar TempStr[0x10];\n\t\n\tsprintf(TempStr, \"%.*f\", Precision, Value);\n\treturn SetDlgItemText(hDlg, nIDDlgItem, TempStr);\n}\n\nstatic int LoadConfigDialogInfo(HWND hWndDlg)\n{\n\tUINT8 CurChp;\n\tfloat dbVol;\n\tINT32 TempSLng;\n\tchar TempStr[0x18];\n\tconst char* TempPnt;\n\t\n\t// --- Main Dialog ---\n\tCheckDlgButton(hWndDlg, ImmediateUpdCheck,\n\t\t\t\t\tOptions.ImmediateUpdate ? BST_CHECKED : BST_UNCHECKED);\n\t\n\t// --- Playback Tab ---\n\tCOMBO_ADDSTR(CfgPlayback, ResmpModeList, \"HQ resampling\");\n\tCOMBO_ADDSTR(CfgPlayback, ResmpModeList, \"HQ up, LQ down\");\n\tCOMBO_ADDSTR(CfgPlayback, ResmpModeList, \"LQ resampling\");\n\tCOMBO_ADDSTR(CfgPlayback, ChipSmpModeList, \"native\");\n\tCOMBO_ADDSTR(CfgPlayback, ChipSmpModeList, \"highest (nat./cust.)\");\n\tCOMBO_ADDSTR(CfgPlayback, ChipSmpModeList, \"custom\");\n\tCOMBO_ADDSTR(CfgPlayback, ChipSmpModeList, \"highest, FM native\");\n\t\n\tLoopTimeMode = false;\n\tSetDlgItemInt(CfgPlayback, LoopText, VGMMaxLoop, FALSE);\n\tSetDlgItemInt(CfgPlayback, FadeText, FadeTime, FALSE );\n\tSetDlgItemInt(CfgPlayback, PauseNlText, Options.PauseNL, FALSE);\n\tSetDlgItemInt(CfgPlayback, PauseLpText, Options.PauseLp, FALSE);\n\t\n\t// Playback rate\n\tswitch(VGMPbRate)\n\t{\n\tcase 0:\n\t\tCheckRadioButton(CfgPlayback, RateRecRadio, RateOtherRadio, RateRecRadio);\n\t\tbreak;\n\tcase 60:\n\t\tCheckRadioButton(CfgPlayback, RateRecRadio, RateOtherRadio, Rate60HzRadio);\n\t\tbreak;\n\tcase 50:\n\t\tCheckRadioButton(CfgPlayback, RateRecRadio, RateOtherRadio, Rate50HzRadio);\n\t\tbreak;\n\tdefault:\n\t\tCheckRadioButton(CfgPlayback, RateRecRadio, RateOtherRadio, RateOtherRadio);\n\t\tbreak;\n\t}\n\tCTRL_SET_ENABLE(CfgPlayback, RateText, CHECK2BOOL(CfgPlayback, RateOtherRadio));\n\tCTRL_SET_ENABLE(CfgPlayback, RateLabel, CHECK2BOOL(CfgPlayback, RateOtherRadio));\n\tSetDlgItemInt(CfgPlayback, RateText, VGMPbRate, FALSE);\n\t\n\t// Slider from -12.0 db to +12.0 db, 0.1 db Steps (large Steps 2.0 db)\n\tSlider_Setup(CfgPlayback, VolumeSlider, 0, 240, 20, 10);\n\tdbVol = (float)(6.0 * log(VolumeLevel) / log(2.0));\n\tTempSLng = (INT32)(floor(dbVol * 10 + 0.5)) + 120;\n\tif (TempSLng < 0)\n\t\tTempSLng = 0;\n\telse if (TempSLng > 240)\n\t\tTempSLng = 240;\n\tSLIDER_SETPOS(CfgPlayback, VolumeSlider, TempSLng);\n\t\n\tsprintf(TempStr, \"%.3f (%+.1f db)\", VolumeLevel, dbVol);\n\tSetDlgItemText(CfgPlayback, VolumeText, TempStr);\n\t\n\tSetDlgItemInt(CfgPlayback, SmplPbRateText, Options.SampleRate, FALSE);\n\tCOMBO_SETPOS(CfgPlayback, ResmpModeList, ResampleMode);\n\tSetDlgItemInt(CfgPlayback, SmplChipRateText, Options.ChipRate, FALSE);\n\tCOMBO_SETPOS(CfgPlayback, ChipSmpModeList, CHIP_SAMPLING_MODE);\n\t\n\tCheckDlgButton(CfgPlayback, SurroundCheck, SurroundSound ? BST_CHECKED : BST_UNCHECKED);\n\t\n\t/*// Filter\n\tswitch(filter_type)\n\t{\n\tcase FILTER_NONE:\n\t\tCheckRadioButton(CfgPlayback, rbFilterNone, rbFilterWeighted, rbFilterNone);\n\t\tbreak;\n\tcase FILTER_LOWPASS:\n\t\tCheckRadioButton(CfgPlayback, rbFilterNone, rbFilterWeighted, rbFilterLowPass);\n\t\tbreak;\n\tcase FILTER_WEIGHTED:\n\t\tCheckRadioButton(CfgPlayback, rbFilterNone, rbFilterWeighted, rbFilterWeighted);\n\t\tbreak;\n\t}*/\n\t\n\t// --- Tags Tab ---\n\tSetDlgItemText(CfgTags, TitleFormatText, Options.TitleFormat);\n\t\n\tCheckDlgButton(CfgTags, PreferJapCheck, Options.JapTags);\n\tCheckDlgButton(CfgTags, FM2413Check, Options.AppendFM2413);\n\tCheckDlgButton(CfgTags, TrimWhitespcCheck, Options.TrimWhitespc);\n\tCheckDlgButton(CfgTags, StdSeparatorsCheck, Options.StdSeparators);\n\tCheckDlgButton(CfgTags, TagFallbackCheck, Options.TagFallback);\n\tCheckDlgButton(CfgTags, NoInfoCacheCheck, Options.NoInfoCache);\n\t//CheckDlgButton(CfgTags, cbTagsStandardiseDates, TagsStandardiseDates);\n\t\n\tSetDlgItemInt(CfgTags, MLTypeText, Options.MLFileType, FALSE);\n\t\n\t// --- Muting Tab and Options & Pan Tab ---\n\tfor (CurChp = 0x00; CurChp < CHIP_COUNT; CurChp ++)\n\t{\n\t\tTempPnt = GetAccurateChipName(CurChp, 0xFF);\n\t\tCOMBO_ADDSTR(CfgMuting, MutingChipList, TempPnt);\n\t\tCOMBO_ADDSTR(CfgOptPan, EmuOptChipList, TempPnt);\n\t}\n\tCOMBO_ADDSTR(CfgMuting, MutingChipNumList, \"Chip #1\");\n\tCOMBO_ADDSTR(CfgOptPan, EmuOptChipNumList, \"Chip #1\");\n\tCOMBO_ADDSTR(CfgMuting, MutingChipNumList, \"Chip #2\");\n\tCOMBO_ADDSTR(CfgOptPan, EmuOptChipNumList, \"Chip #2\");\n\t\n\tCOMBO_SETPOS(CfgMuting, MutingChipList, MuteChipID);\n\tCOMBO_SETPOS(CfgOptPan, EmuOptChipList, MuteChipID);\n\tCOMBO_SETPOS(CfgMuting, MutingChipNumList, MuteChipSet);\n\tCOMBO_SETPOS(CfgOptPan, EmuOptChipNumList, MuteChipSet);\n\t\n\tCheckDlgButton(CfgMuting, ResetMuteCheck, Options.ResetMuting);\n\t\n\tfor (TempSLng = PanChn1Slider; TempSLng <= PanChn15Slider; TempSLng ++)\n\t\tSlider_Setup(CfgOptPan, TempSLng, 0x00, 0x40, 0x08, 0x08);\n\t\n\treturn 0;\n}\n \n\n// Dialogue box callback function\nBOOL CALLBACK ConfigDialogProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam)\n{\n\tswitch(wMessage)\n\t{\n\tcase WM_INITDIALOG:\n\t\t// do nothing if this is a child window (tab page) callback, pass to the parent\n\t\tif (GetWindowLong(hWndDlg, GWL_STYLE) & WS_CHILD)\n\t\t\tassert(false);\n\t\t\t//return FALSE;\n\t\t\n\t\tInitConfigDialog(hWndDlg);\n\t\t\n\t\tSetWindowText(hWndDlg, INVGM_TITLE \" configuration\");\n\t\t\n\t\tLoadConfigDialogInfo(hWndDlg);\n\t\t\n\t\tSendMessage(hWndDlg, WM_HSCROLL, 0, 0); // trigger slider value change handlers\n\t\tSendMessage(CfgPlayback, WM_COMMAND, MAKEWPARAM(ResmpModeList, CBN_SELCHANGE), 0);\n\t\tSendMessage(CfgPlayback, WM_COMMAND, MAKEWPARAM(ChipSmpModeList, CBN_SELCHANGE), 0);\n\t\tSendMessage(CfgMuting, WM_COMMAND, MAKEWPARAM(MutingChipList, CBN_SELCHANGE), 0);\n\t\tSendMessage(CfgOptPan, WM_COMMAND, MAKEWPARAM(EmuOptChipList, CBN_SELCHANGE), 0);\n\t\t\n\t\tSetFocus(hWndDlg);\n\t\t\n\t\treturn TRUE;\n\tcase WM_COMMAND:\n\t\tswitch(LOWORD(wParam))\n\t\t{\n\t\tcase IDOK:\n\t\t\t{\n\t\t\t\tUINT8 CurTab;\n\t\t\t\t\n\t\t\t\tfor (CurTab = 0; CurTab < NUM_CFG_TABS; CurTab ++)\n\t\t\t\t\tSendMessage(hWndCfgTab[CurTab], WM_COMMAND, IDOK, lParam);\n\t\t\t}\n\t\t\tEndDialog(hWndDlg, 0);\n\t\t\treturn TRUE;\n\t\tcase IDCANCEL:\t// [X] button, Alt+F4, etc\n\t\t\t{\n\t\t\t\tUINT8 CurTab;\n\t\t\t\t\n\t\t\t\tfor (CurTab = 0; CurTab < NUM_CFG_TABS; CurTab ++)\n\t\t\t\t\tSendMessage(hWndCfgTab[CurTab], WM_COMMAND, IDCANCEL, lParam);\n\t\t\t}\n\t\t\t\n\t\t\tEndDialog(hWndDlg, 1);\n\t\t\treturn TRUE;\n\n/*\t\t// Stuff not in tabs --------------------------------------------------------\n\t\tcase btnReadMe: {\n\t\t\t\tchar FileName[MAX_PATH];\n\t\t\t\tchar *PChar;\n\t\t\t\tGetModuleFileName(hPluginInst,FileName,MAX_PATH);  // get *dll* path\n\t\t\t\tGetFullPathName(FileName,MAX_PATH,FileName,&PChar);  // make it fully qualified plus find the filename bit\n\t\t\t\tstrcpy(PChar,\"in_vgm.html\");\n\t\t\t\tif ((int)ShellExecute(mod.hMainWindow,NULL,FileName,NULL,NULL,SW_SHOWNORMAL)<=32)\n\t\t\t\t\tMessageBox(hWndDlg,\"Error opening in_vgm.html from plugin folder\",mod.description,MB_ICONERROR+MB_OK);\n\t\t\t}\n\t\t\tbreak;*/\n\t\tcase ImmediateUpdCheck:\n\t\t\tif (HIWORD(wParam) == BN_CLICKED)\n\t\t\t\tOptions.ImmediateUpdate = CHECK2BOOL(hWndDlg, ImmediateUpdCheck);\n\t\t\tbreak;\n\t\t}\n\t\tbreak; // end WM_COMMAND handling\n\n\tcase WM_NOTIFY:\n\t\tswitch(LOWORD(wParam))\n\t\t{\n\t\tcase TabCollection:\n\t\t{\n\t\t\tint CurTab;\n\t\t\t\n\t\t\tCurTab = TabCtrl_GetCurSel(GetDlgItem(hWndDlg, TabCollection));\n\t\t\tif (CurTab == -1)\n\t\t\t\tbreak;\n#ifdef HIDE_VGM7Z\n\t\t\tif (CurTab >= 2)\n\t\t\t\tCurTab ++;\t// skip hidden VGM7Z tab\n#endif\n\t\t\t\n\t\t\tswitch(((LPNMHDR)lParam)->code)\n\t\t\t{\n\t\t\tcase TCN_SELCHANGING:\t// hide current window\n\t\t\t\tShowWindow(hWndCfgTab[CurTab], SW_HIDE);\n\t\t\t\tEnableWindow(hWndCfgTab[CurTab], FALSE);\n\t\t\t\tbreak;\n\t\t\tcase TCN_SELCHANGE:\t\t// show current window\n\t\t\t\tif (hWndCfgTab[CurTab] == CfgMuting)\n\t\t\t\t{\n\t\t\t\t\tCOMBO_SETPOS(CfgMuting, MutingChipList, MuteChipID);\n\t\t\t\t\tCOMBO_SETPOS(CfgMuting, MutingChipNumList, MuteChipSet);\n\t\t\t\t\tShowMutingCheckBoxes(MuteChipID, MuteChipSet);\n\t\t\t\t}\n\t\t\t\telse if (hWndCfgTab[CurTab] == CfgOptPan)\n\t\t\t\t{\n\t\t\t\t\tCOMBO_SETPOS(CfgOptPan, EmuOptChipList, MuteChipID);\n\t\t\t\t\tCOMBO_SETPOS(CfgOptPan, EmuOptChipNumList, MuteChipSet);\n\t\t\t\t\tShowOptPanBoxes(MuteChipID, MuteChipSet);\n\t\t\t\t}\n\t\t\t\tEnableWindow(hWndCfgTab[CurTab], TRUE);\n\t\t\t\tShowWindow(hWndCfgTab[CurTab], SW_SHOW);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\t}\n\t\treturn TRUE;\n\t}\n\t\n\treturn FALSE;\t// message not processed\n}\n\nBOOL CALLBACK CfgDlgPlaybackProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam)\n{\n\tswitch(wMessage)\n\t{\n\tcase WM_INITDIALOG:\n\t\tbreak;\n\tcase WM_COMMAND:\n\t\tswitch(LOWORD(wParam))\n\t\t{\n\t\tcase IDOK:\n\t\t\tVGMMaxLoop = GetDlgItemInt(CfgPlayback, LoopText, NULL, FALSE);\n\t\t\tFadeTime = GetDlgItemInt(CfgPlayback, FadeText, NULL, FALSE);\n\t\t\tOptions.PauseNL = GetDlgItemInt(CfgPlayback, PauseNlText, NULL, FALSE);\n\t\t\tOptions.PauseLp = GetDlgItemInt(CfgPlayback, PauseLpText, NULL, FALSE);\n\t\t\t\n\t\t\tif (IsDlgButtonChecked(CfgPlayback, RateRecRadio))\n\t\t\t\tVGMPbRate = 0;\n\t\t\telse if (IsDlgButtonChecked(CfgPlayback, Rate60HzRadio))\n\t\t\t\tVGMPbRate = 60;\n\t\t\telse if (IsDlgButtonChecked(CfgPlayback, Rate50HzRadio))\n\t\t\t\tVGMPbRate = 50;\n\t\t\telse if (IsDlgButtonChecked(CfgPlayback, RateOtherRadio))\n\t\t\t\tVGMPbRate = GetDlgItemInt(CfgPlayback, RateText, NULL, FALSE);\n\t\t\t\n\t\t\tOptions.SampleRate = GetDlgItemInt(CfgPlayback, SmplPbRateText, NULL, FALSE);\n\t\t\tResampleMode = (UINT8)COMBO_GETPOS(CfgPlayback, ResmpModeList);\n\t\t\tOptions.ChipRate = GetDlgItemInt(CfgPlayback, SmplChipRateText, NULL, FALSE);\n\t\t\tCHIP_SAMPLING_MODE = (UINT8)COMBO_GETPOS(CfgPlayback, ChipSmpModeList);\n\t\t\t\n\t\t\tQueueInfoReload();\t// if the Playback Rate was changed, a refresh is needed\n\t\t\t\n\t\t\tEndDialog(hWndDlg, 0);\n\t\t\treturn TRUE;\n\t\tcase IDCANCEL:\n\t\t\tEndDialog(hWndDlg, 1);\n\t\t\treturn TRUE;\n\t\tcase RateRecRadio:\n\t\tcase Rate60HzRadio:\n\t\tcase Rate50HzRadio:\n\t\tcase RateOtherRadio:\n\t\t\t// Windows already does the CheckRadioButton by itself\n\t\t\t//CheckRadioButton(CfgPlayback, RateRecRadio, RateOtherRadio, LOWORD(wParam));\n\t\t\tif (LOWORD(wParam) == RateOtherRadio)\n\t\t\t{\n\t\t\t\tCTRL_ENABLE(CfgPlayback, RateText);\n\t\t\t\tCTRL_ENABLE(CfgPlayback, RateLabel);\n\t\t\t\t//SetFocus(GetDlgItem(CfgPlayback, RateText));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tCTRL_DISABLE(CfgPlayback, RateText);\n\t\t\t\tCTRL_DISABLE(CfgPlayback, RateLabel);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase ResmpModeList:\n\t\t\tbreak;\n\t\tcase ChipSmpModeList:\n\t\t\tif (HIWORD(wParam) == CBN_SELCHANGE)\n\t\t\t{\n\t\t\t\tBOOL CtrlEnable;\n\t\t\t\t\n\t\t\t\tCtrlEnable = (COMBO_GETPOS(CfgPlayback, ChipSmpModeList) > 0);\n\t\t\t\tCTRL_SET_ENABLE(CfgPlayback, SmplChipRateLabel, CtrlEnable);\n\t\t\t\tCTRL_SET_ENABLE(CfgPlayback, SmplChipRateText, CtrlEnable);\n\t\t\t\tCTRL_SET_ENABLE(CfgPlayback, SmplChipRateHzLabel, CtrlEnable);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase LoopText:\n\t\t\tif (HIWORD(wParam) == EN_CHANGE)\n\t\t\t{\n\t\t\t\t// for correct grammar: \"Play loop x time(s)\"\n\t\t\t\tBOOL Translated;\n\t\t\t\tbool NewLTMode;\n\t\t\t\t\n\t\t\t\tNewLTMode = (GetDlgItemInt(CfgPlayback, LoopText, &Translated, FALSE) == 1);\n\t\t\t\tif (Translated && NewLTMode != LoopTimeMode)\n\t\t\t\t{\n\t\t\t\t\tchar TimeStr[0x08];\n\t\t\t\t\t\n\t\t\t\t\tLoopTimeMode = NewLTMode;\n\t\t\t\t\tstrcpy(TimeStr, \"times\");\n\t\t\t\t\tif (LoopTimeMode)\n\t\t\t\t\t\tTimeStr[0x04] = '\\0';\n\t\t\t\t\tSetDlgItemText(CfgPlayback, LoopTimesLabel, TimeStr);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase SurroundCheck:\n\t\t\tSurroundSound = CHECK2BOOL(CfgPlayback, SurroundCheck);\n\t\t\t\n\t\t\tUpdatePlayback();\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase WM_HSCROLL:\n\t\tif (GetDlgCtrlID((HWND)lParam) == VolumeSlider)\n\t\t{\n\t\t\tfloat dbVol;\n\t\t\tUINT16 TempSht;\n\t\t\tchar TempStr[0x18];\n\t\t\t\n\t\t\tif (LOWORD(wParam) == TB_THUMBPOSITION || LOWORD(wParam) == TB_THUMBTRACK)\n\t\t\t\tTempSht = HIWORD(wParam);\n\t\t\telse\n\t\t\t\tTempSht = SLIDER_GETPOS(CfgPlayback, VolumeSlider);\n\t\t\tdbVol = (TempSht - 120) / 10.0f;\n\t\t\tVolumeLevel = (float)pow(2.0, dbVol / 6.0);\n\t\t\t\n\t\t\tsprintf(TempStr, \"%.3f (%+.1f db)\", VolumeLevel, dbVol);\n\t\t\tSetDlgItemText(CfgPlayback, VolumeText, TempStr);\n\t\t\t\n\t\t\tRefreshPlaybackOptions();\n\t\t\tif (LOWORD(wParam) != TB_THUMBTRACK)\t// prevent too many skips\n\t\t\t\tUpdatePlayback();\n\t\t}\n\t\tbreak;\n\tcase WM_NOTIFY:\n\t\tbreak;\n\t}\n\t\n\treturn FALSE;\n}\n\nBOOL CALLBACK CfgDlgTagsProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam)\n{\n\tswitch(wMessage)\n\t{\n\tcase WM_INITDIALOG:\n\t\tbreak;\n\tcase WM_COMMAND:\n\t\tswitch(LOWORD(wParam))\n\t\t{\n\t\tcase IDOK:\n\t\t\tGetDlgItemText(CfgTags, TitleFormatText, Options.TitleFormat, 0x7F);\n\t\t\t\n\t\t\t//TagsStandardiseDates = CHECK2BOOL(CfgTags, cbTagsStandardiseDates, );\n\t\t\t\n\t\t\tSetDlgItemInt(CfgTags, MLTypeText, Options.MLFileType, FALSE);\n\t\t\t\n\t\t\tEndDialog(hWndDlg, 0);\n\t\t\treturn TRUE;\n\t\tcase IDCANCEL:\n\t\t\tEndDialog(hWndDlg, 1);\n\t\t\treturn TRUE;\n\t\tcase PreferJapCheck:\n\t\t\tOptions.JapTags = CHECK2BOOL(CfgTags, PreferJapCheck);\n\t\t\tbreak;\n\t\tcase FM2413Check:\n\t\t\tOptions.AppendFM2413 = CHECK2BOOL(CfgTags, FM2413Check);\n\t\t\tbreak;\n\t\tcase TrimWhitespcCheck:\n\t\t\tOptions.TrimWhitespc = CHECK2BOOL(CfgTags, TrimWhitespcCheck);\n\t\t\tQueueInfoReload();\n\t\t\tbreak;\n\t\tcase StdSeparatorsCheck:\n\t\t\tOptions.StdSeparators = CHECK2BOOL(CfgTags, StdSeparatorsCheck);\n\t\t\tQueueInfoReload();\n\t\t\tbreak;\n\t\tcase TagFallbackCheck:\n\t\t\tOptions.TagFallback = CHECK2BOOL(CfgTags, TagFallbackCheck);\n\t\t\tbreak;\n\t\tcase NoInfoCacheCheck:\n\t\t\tOptions.NoInfoCache = CHECK2BOOL(CfgTags, NoInfoCacheCheck);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase WM_NOTIFY:\n\t\tbreak;\n\t}\n\t\n\treturn FALSE;\n}\n\nBOOL CALLBACK CfgDlgMutingProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam)\n{\n\tswitch(wMessage)\n\t{\n\tcase WM_INITDIALOG:\n\t\tbreak;\n\tcase WM_COMMAND:\n\t\tswitch(LOWORD(wParam))\n\t\t{\n\t\tcase IDOK:\n\t\t\tEndDialog(hWndDlg, 0);\n\t\t\treturn TRUE;\n\t\tcase IDCANCEL:\n\t\t\tEndDialog(hWndDlg, 1);\n\t\t\treturn TRUE;\n\t\tcase MutingChipList:\n\t\tcase MutingChipNumList:\n\t\t\tif (HIWORD(wParam) == CBN_SELCHANGE)\n\t\t\t{\n\t\t\t\tShowMutingCheckBoxes((UINT8)COMBO_GETPOS(CfgMuting, MutingChipList),\n\t\t\t\t\t\t\t\t\t(UINT8)COMBO_GETPOS(CfgMuting, MutingChipNumList));\n\t\t\t}\n\t\t\tbreak;\n\t\tcase ResetMuteCheck:\n\t\t\tif (HIWORD(wParam) == BN_CLICKED)\n\t\t\t\tOptions.ResetMuting = CHECK2BOOL(CfgMuting, ResetMuteCheck);\n\t\t\tbreak;\n\t\tcase MuteChipCheck:\n\t\t\tMuteCOpts->Disabled = CHECK2BOOL(CfgMuting, MuteChipCheck);\n\t\t\t\n\t\t\tUpdatePlayback();\n\t\t\tbreak;\n\t\t}\n\t\t// I'm NOT going to have 24 case-lines!\n\t\tif (LOWORD(wParam) >= MuteChn1Check && LOWORD(wParam) <= MuteChn24Check)\n\t\t{\n\t\t\tif (HIWORD(wParam) == BN_CLICKED)\n\t\t\t{\n\t\t\t\tSetMutingData(LOWORD(wParam) - MuteChn1Check,\n\t\t\t\t\t\t\t\t(bool)CHECK2BOOL(CfgMuting, LOWORD(wParam)));\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase WM_NOTIFY:\n\t\tbreak;\n\t}\n\t\n\treturn FALSE;\n}\n\nBOOL CALLBACK CfgDlgOptPanProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam)\n{\n\tswitch(wMessage)\n\t{\n\tcase WM_INITDIALOG:\n\t\tbreak;\n\tcase WM_COMMAND:\n\t\tswitch(LOWORD(wParam))\n\t\t{\n\t\tcase IDOK:\n\t\t\tEndDialog(hWndDlg, 0);\n\t\t\treturn TRUE;\n\t\tcase IDCANCEL:\n\t\t\tEndDialog(hWndDlg, 1);\n\t\t\treturn TRUE;\n\t\tcase EmuCoreRadio1:\n\t\tcase EmuCoreRadio2:\n\t\t{\n\t\t\tCHIP_OPTS* TempCOpts;\n\t\t\t\n\t\t\t// EmuCore is only available for Chip #1\n\t\t\tTempCOpts = (CHIP_OPTS*)&ChipOpts[0x00] + MuteChipID;\n\t\t\tif (LOWORD(wParam) == EmuCoreRadio1)\n\t\t\t{\n\t\t\t\tTempCOpts->EmuCore = 0x00;\n\t\t\t}\n\t\t\telse //if (LOWORD(wParam) == EmuCoreRadio2)\n\t\t\t{\n\t\t\t\tTempCOpts->EmuCore = 0x01;\n\t\t\t}\n\t\t\tRefreshPlaybackOptions();\n\t\t\tShowOptPanBoxes(MuteChipID, MuteChipSet);\n\t\t\tbreak;\n\t\t}\n\t\tcase EmuOptChipList:\n\t\tcase EmuOptChipNumList:\n\t\t\tif (HIWORD(wParam) == CBN_SELCHANGE)\n\t\t\t{\n\t\t\t\tShowOptPanBoxes((UINT8)COMBO_GETPOS(CfgOptPan, EmuOptChipList),\n\t\t\t\t\t\t\t\t(UINT8)COMBO_GETPOS(CfgOptPan, EmuOptChipNumList));\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase WM_HSCROLL:\n\t{\n\t\tint SliderID;\n\t\t\n\t\tSliderID = GetDlgCtrlID((HWND)lParam);\n\t\tif (SliderID >= PanChn1Slider && SliderID <= PanChn15Slider)\n\t\t{\n\t\t\tUINT16 TempSht;\n\t\t\tbool Dragging;\n\t\t\t\n\t\t\tDragging = (LOWORD(wParam) == TB_THUMBTRACK);\n\t\t\tif (Dragging || LOWORD(wParam) == TB_THUMBPOSITION)\n\t\t\t\tTempSht = HIWORD(wParam);\n\t\t\telse\n\t\t\t\tTempSht = SLIDER_GETPOS(CfgOptPan, SliderID);\n\t\t\t\n\t\t\tSetPanningData(SliderID - PanChn1Slider, TempSht, Dragging);\n\t\t}\n\t\tbreak;\n\t}\n\tcase WM_NOTIFY:\n\t\tbreak;\n\t}\n\t\n\treturn FALSE;\n}\n\nBOOL CALLBACK CfgDlgChildProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam)\n{\n\t// Generic Procedure for unused/unfinished tabs\n\tswitch(wMessage)\n\t{\n\tcase WM_INITDIALOG:\n\t\tbreak;\n\tcase WM_COMMAND:\n\t\tswitch(LOWORD(wParam))\n\t\t{\n\t\tcase IDOK:\n\t\t\tEndDialog(hWndDlg, 0);\n\t\t\treturn TRUE;\n\t\tcase IDCANCEL:\n\t\t\tEndDialog(hWndDlg, 1);\n\t\t\treturn TRUE;\n\t\t}\n\t\tbreak;\n\tcase WM_NOTIFY:\n\t\tbreak;\n\t}\n\t\n\treturn FALSE;\n}\n\n\nstatic bool IsChipAvailable(UINT8 ChipID, UINT8 ChipSet)\n{\n\tUINT32 Clock;\n\t\n\tif (PlayingMode == 0xFF)\n\t\treturn true;\n\t\n\tClock = GetChipClock(&VGMHead, (ChipSet << 7) | ChipID, NULL);\n\t\n\tif (! Clock)\n\t\treturn false;\n\telse\n\t\treturn true;\n}\n\nstatic void ShowMutingCheckBoxes(UINT8 ChipID, UINT8 ChipSet)\n{\n\tUINT8 ChnCount;\n\tUINT8 ChnCntS[0x04];\n\tconst char* SpcName[0x40];\t// Special Channel Names\n\tUINT8 CurChn;\n\tUINT8 SpcModes;\n\tbool EnableChk;\n\tbool Checked;\n\tUINT8 CurMode;\n\tUINT8 ChnBase;\n\tUINT8 FnlChn;\n\tchar TempName[0x18];\n\t\n\tfor (CurChn = 0x00; CurChn < 0x40; CurChn ++)\n\t\tSpcName[CurChn] = NULL;\n\t\n\tEnableChk = IsChipAvailable(ChipID, ChipSet);\n\tSpcModes = 0;\n\tswitch(ChipID)\n\t{\n\tcase 0x00:\t// SN76496\n\t\tChnCount = 4;\n\t\tSpcName[3] = \"&Noise\";\n\t\tbreak;\n\tcase 0x01:\t// YM2413\n\tcase 0x09:\t// YM3812\n\tcase 0x0A:\t// YM3526\n\tcase 0x0B:\t// Y8950\n\t\tChnCount = 14;\t// 9 + 5\n\t\tSpcName[ 9] = \"&Bass Drum\";\n\t\tSpcName[10] = \"S&nare Drum\";\n\t\tSpcName[11] = \"&Tom Tom\";\n\t\tSpcName[12] = \"C&ymbal\";\n\t\tSpcName[13] = \"&Hi-Hat\";\n\t\tif (ChipID == 0x0B)\n\t\t{\n\t\t\tChnCount = 15;\n\t\t\tSpcName[14] = \"&Delta-T\";\n\t\t}\n\t\tbreak;\n\tcase 0x02:\t// YM2612\n\t\tChnCount = 7;\t// 6 + DAC\n\t\tSpcName[6] = \"&DAC\";\n\t\tbreak;\n\tcase 0x03:\t// YM2151\n\t\tChnCount = 8;\n\t\tbreak;\n\tcase 0x04:\t// Sega PCM\n\t\tChnCount = 16;\n\t\tEnableChk &= ! ChipSet;\n\t\tbreak;\n\tcase 0x05:\t// RF5C68\n\tcase 0x10:\t// RF5C164\n\t\tChnCount = 8;\n\t\tEnableChk &= ! ChipSet;\n\t\tbreak;\n\tcase 0x06:\t// YM2203\n\t\tChnCount = 6;\t// 3 FM + 3 AY8910\n\t\tSpcModes = 3;\n\t\tChnCntS[0] = 3;\n\t\tSpcName[0] = \"FM Chn\";\n\t\tChnCntS[1] = 0;\n\t\tChnCntS[2] = 3;\n\t\tSpcName[2] = \"PSG Chn\";\n\t\tbreak;\n\tcase 0x07:\t// YM2608\n\tcase 0x08:\t// YM2610\n\t\tChnCount = 16;\t// 6 FM + 6 ADPCM + 1 DeltaT + 3 AY8910\n\t\tSpcModes = 3;\n\t\tChnCntS[0] = 6;\n\t\tSpcName[0] = \"FM Chn\";\n\t\tChnCntS[1] = 7;\n\t\tSpcName[1] = \"PCM Chn\";\n\t\tSpcName[14] = \"&Delta-T\";\n\t\tChnCntS[2] = 3;\n\t\tSpcName[2] = \"PSG Chn\";\n\t\tbreak;\n\tcase 0x0C:\t// YMF262\n\t\tChnCount = 23;\t// 18 + 5\n\t\tSpcName[18] = \"&Bass Drum\";\n\t\tSpcName[19] = \"S&nare Drum\";\n\t\tSpcName[20] = \"&Tom Tom\";\n\t\tSpcName[21] = \"C&ymbal\";\n\t\tSpcName[22] = \"&Hi-Hat\";\n\t\tbreak;\n\tcase 0x0D:\t// YMF278B\n\t\tChnCount = 24;\n\t\tbreak;\n\tcase 0x0E:\t// YMF271\n\t\tChnCount = 12;\n\t\tbreak;\n\tcase 0x0F:\t// YMZ280B\n\t\tChnCount = 8;\n\t\tbreak;\n\tcase 0x11:\t// PWM\n\t\tChnCount = 0;\n\t\tEnableChk &= ! ChipSet;\n\t\tbreak;\n\tcase 0x12:\t// AY8910\n\t\tChnCount = 3;\n\t\tbreak;\n\tcase 0x13:\t// GB DMG\n\t\tSpcName[0] = \"Square &1\";\n\t\tSpcName[1] = \"Square &2\";\n\t\tSpcName[2] = \"Progr. &Wave\";\n\t\tSpcName[3] = \"&Noise\";\n\t\tChnCount = 4;\n\t\tbreak;\n\tcase 0x14:\t// NES APU\n\t\tSpcName[0] = \"Square &1\";\n\t\tSpcName[1] = \"Square &2\";\n\t\tSpcName[2] = \"&Triangle\";\n\t\tSpcName[3] = \"&Noise\";\n\t\tSpcName[4] = \"&DPCM\";\n\t\tSpcName[5] = \"&FDS\";\n\t\tChnCount = 6;\n\t\tbreak;\n\tcase 0x15:\t// Multi PCM\n\t\tChnCount = 28;\n\t\tbreak;\n\tcase 0x16:\t// UPD7759\n\t\tChnCount = 0;\n\t\tbreak;\n\tcase 0x17:\t// OKIM6258\n\t\tChnCount = 0;\n\t\tbreak;\n\tcase 0x18:\t// OKIM6295\n\t\tChnCount = 4;\n\t\tbreak;\n\tcase 0x19:\t// K051649\n\t\tChnCount = 5;\n\t\tbreak;\n\tcase 0x1A:\t// K054539\n\t\tChnCount = 8;\n\t\tbreak;\n\tcase 0x1B:\t// HuC6280\n\t\tChnCount = 6;\n\t\tbreak;\n\tcase 0x1C:\t// C140\n\t\tChnCount = 24;\n\t\tbreak;\n\tcase 0x1D:\t// K053260\n\t\tChnCount = 4;\n\t\tbreak;\n\tcase 0x1E:\t// Pokey\n\t\tChnCount = 4;\n\t\tbreak;\n\tcase 0x1F:\t// Q-Sound\n\t\tChnCount = 16;\n\t\tEnableChk &= ! ChipSet;\n\t\tbreak;\n\tcase 0x20:\t// SCSP\n\t\tChnCount = 32;\n\t\tbreak;\n\tcase 0x21:\t// WonderSwan\n\t\tChnCount = 4;\n\t\tbreak;\n\tcase 0x22:\t// VSU\n\t\tChnCount = 6;\n\t\tbreak;\n\tcase 0x23:\t// SAA1099\n\t\tChnCount = 6;\n\t\tbreak;\n\tcase 0x24:\t// ES5503\n\t\tChnCount = 32;\n\t\tbreak;\n\tcase 0x25:\t// ES5506\n\t\tChnCount = 32;\n\t\tbreak;\n\tcase 0x26:\t// X1-010\n\t\tChnCount = 16;\n\t\tbreak;\n\tcase 0x27:\t// C352\n\t\tChnCount = 32;\n\t\tbreak;\n\tcase 0x28:\t// GA20\n\t\tChnCount = 4;\n\t\tbreak;\n\tdefault:\n\t\tChnCount = 0;\n\t\tEnableChk &= ! ChipSet;\n\t\tbreak;\n\t}\n\tMuteCOpts = (CHIP_OPTS*)&ChipOpts[ChipSet] + ChipID;\n\tif (ChnCount > 24)\n\t\tChnCount = 24;\t// currently only 24 checkboxes are supported\n\t\n\tSETCHECKBOX(CfgMuting, MuteChipCheck, MuteCOpts->Disabled);\n\tCTRL_SET_ENABLE(CfgMuting, MuteChipCheck, EnableChk);\n\tif (! SpcModes)\n\t{\n\t\tfor (CurChn = 0; CurChn < ChnCount; CurChn ++)\n\t\t{\n\t\t\tif (SpcName[CurChn] == NULL)\n\t\t\t{\n\t\t\t\tif (1 + CurChn < 10)\n\t\t\t\t\tsprintf(TempName, \"Channel &%u\", 1 + CurChn);\n\t\t\t\telse\n\t\t\t\t\tsprintf(TempName, \"Channel %u (&%c)\", 1 + CurChn, 'A' + (CurChn - 9));\n\t\t\t\tSetDlgItemText(CfgMuting, MuteChn1Check + CurChn, TempName);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tSetDlgItemText(CfgMuting, MuteChn1Check + CurChn, SpcName[CurChn]);\n\t\t\t}\n\t\t\t\n\t\t\tif (ChipID == 0x0D)\n\t\t\t\tChecked = (MuteCOpts->ChnMute2 >> CurChn) & 0x01;\n\t\t\telse\n\t\t\t\tChecked = (MuteCOpts->ChnMute1 >> CurChn) & 0x01;\n\t\t\tSETCHECKBOX(CfgMuting, MuteChn1Check + CurChn, Checked);\n\t\t\tCTRL_SET_ENABLE(CfgMuting, MuteChn1Check + CurChn, EnableChk);\n\t\t\tCTRL_SHOW(CfgMuting, MuteChn1Check + CurChn);\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor (CurMode = 0; CurMode < SpcModes; CurMode ++)\n\t\t{\n\t\t\tChnBase = CurMode * 8;\n\t\t\tif (SpcName[CurMode] == NULL)\n\t\t\t\tSpcName[CurMode] = \"Channel\";\n\t\t\t\n\t\t\tfor (CurChn = 0, FnlChn = ChnBase; CurChn < ChnCntS[CurMode]; CurChn ++, FnlChn ++)\n\t\t\t{\n\t\t\t\tif (FnlChn < SpcModes || SpcName[FnlChn] == NULL)\n\t\t\t\t{\n\t\t\t\t\tif (1 + CurChn < 10)\n\t\t\t\t\t\tsprintf(TempName, \"%s &%u\", SpcName[CurMode], 1 + CurChn);\n\t\t\t\t\telse\n\t\t\t\t\t\tsprintf(TempName, \"%s %u (&%c)\", SpcName[CurMode], 1 + CurChn,\n\t\t\t\t\t\t\t\t'A' + (CurChn - 9));\n\t\t\t\t\tSetDlgItemText(CfgMuting, MuteChn1Check + FnlChn, TempName);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tSetDlgItemText(CfgMuting, MuteChn1Check + FnlChn, SpcName[FnlChn]);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tswitch(CurMode)\n\t\t\t\t{\n\t\t\t\tcase 0:\n\t\t\t\t\tChecked = (MuteCOpts->ChnMute1 >> CurChn) & 0x01;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tChecked = (MuteCOpts->ChnMute2 >> CurChn) & 0x01;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tChecked = (MuteCOpts->ChnMute3 >> CurChn) & 0x01;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tSETCHECKBOX(CfgMuting, MuteChn1Check + FnlChn, Checked);\n\t\t\t\tCTRL_SET_ENABLE(CfgMuting, MuteChn1Check + FnlChn, EnableChk);\n\t\t\t\tCTRL_SHOW(CfgMuting, MuteChn1Check + FnlChn);\n\t\t\t}\n\t\t\tfor (; CurChn < 8; CurChn ++, FnlChn ++)\n\t\t\t{\n\t\t\t\tCTRL_HIDE(CfgMuting, MuteChn1Check + FnlChn);\n\t\t\t\tCTRL_DISABLE(CfgMuting, MuteChn1Check + FnlChn);\n\t\t\t\tSetDlgItemText(CfgMuting, MuteChn1Check + FnlChn, \"\");\n\t\t\t}\n\t\t}\n\t\tCurChn = FnlChn;\n\t}\n\tfor (; CurChn < 24; CurChn ++)\n\t{\n\t\t// I thought that disabling a window should prevent it from catching other\n\t\t// windows' keyboard shortcuts.\n\t\t// But NO, it seems that you have to make its text EMPTY to make it work!\n\t\tCTRL_HIDE(CfgMuting, MuteChn1Check + CurChn);\n\t\tCTRL_DISABLE(CfgMuting, MuteChn1Check + CurChn);\n\t\tSetDlgItemText(CfgMuting, MuteChn1Check + CurChn, \"\");\n\t}\n\t\n\tMuteChipID = ChipID;\n\tMuteChipSet = ChipSet;\n\t\n\treturn;\n}\n\nstatic void SetMutingData(UINT32 CheckBox, bool MuteOn)\n{\n\t//UINT8 ChnCount;\n\t//UINT8 ChnCntS[0x04];\n\tUINT8 CurChn;\n\tUINT8 SpcModes;\n\tUINT8 CurMode;\n\t\n\tSpcModes = 0;\n\tswitch(MuteChipID)\n\t{\n\tcase 0x06:\t// YM2203\n\t\t//ChnCount = 6;\t// 3 FM + 3 AY8910\n\t\tSpcModes = 2;\n\t\t//ChnCntS[0] = 3;\n\t\t//ChnCntS[1] = 3;\n\t\tbreak;\n\tcase 0x07:\t// YM2608\n\tcase 0x08:\t// YM2610\n\t\t//ChnCount = 16;\t// 6 FM + 6 ADPCM + 1 DeltaT + 3 AY8910\n\t\tSpcModes = 3;\n\t\t//ChnCntS[0] = 6;\n\t\t//ChnCntS[1] = 7;\n\t\t//ChnCntS[2] = 3;\n\t\tbreak;\n\t}\n\t\n\tif (! SpcModes)\n\t{\n\t\tCurMode = 0;\n\t\tif (MuteChipID == 0x0D)\n\t\t\tCurMode = 1;\n\t\tCurChn = CheckBox;\n\t}\n\telse\n\t{\n\t\tCurMode = CheckBox / 8;\n\t\tCurChn = CheckBox % 8;\n\t}\n\tswitch(CurMode)\n\t{\n\tcase 0:\n\t\tMuteCOpts->ChnMute1 &= ~(1 << CurChn);\n\t\tMuteCOpts->ChnMute1 |= (MuteOn << CurChn);\n\t\tbreak;\n\tcase 1:\n\t\tMuteCOpts->ChnMute2 &= ~(1 << CurChn);\n\t\tMuteCOpts->ChnMute2 |= (MuteOn << CurChn);\n\t\tbreak;\n\tcase 2:\n\t\tMuteCOpts->ChnMute3 &= ~(1 << CurChn);\n\t\tMuteCOpts->ChnMute3 |= (MuteOn << CurChn);\n\t\tbreak;\n\t}\n\t\n\tRefreshMuting();\n\tUpdatePlayback();\n\t\n\treturn;\n}\n\nstatic void ShowOptPanBoxes(UINT8 ChipID, UINT8 ChipSet)\n{\n\tUINT8 ChnCount;\n\tUINT8 CurChn;\n\tconst char* SpcName[0x20];\t// Special Channel Names\n\tconst char* CoreName[0x02];\t// Names for the Emulation Cores\n\tbool EnableChk;\n\tbool MultiCore;\n\tbool CanPan;\n\tINT16 PanPos;\n\tchar TempName[0x20];\n\tconst char* TempStr;\n\tCHIP_OPTS* TempCOpts;\t// for getting EmuCore only\n\t\n\tfor (CurChn = 0x00; CurChn < 0x20; CurChn ++)\n\t\tSpcName[CurChn] = NULL;\n\t\n\tCoreName[0x00] = \"MAME\";\n\tCoreName[0x01] = NULL;\n\t\n\t// ChipOpts[0x01] contains the EmuCore that's currently used\n\tTempCOpts = (CHIP_OPTS*)&ChipOpts[0x01] + ChipID;\n\tEnableChk = IsChipAvailable(ChipID, ChipSet);\n\tMultiCore = false;\n\tCanPan = false;\n\tChnCount = 0;\n\tswitch(ChipID)\n\t{\n\tcase 0x00:\t// SN76496\n\t\tMultiCore = true;\n\t\tCoreName[0x01] = \"Maxim\";\n\t\tCanPan = (TempCOpts->EmuCore == 0x01);\n\t\t\n\t\tChnCount = 4;\n\t\tSpcName[3] = \"&N\";\n\t\tbreak;\n\tcase 0x01:\t// YM2413\n\t\tMultiCore = true;\n\t\tCoreName[0x00] = \"EMU2413\";\n\t\tCoreName[0x01] = \"MAME\";\n\t\tCanPan = (TempCOpts->EmuCore == 0x00);\n\t\t\n\t\tChnCount = 14;\t// 9 + 5\n\t\tSpcName[ 9] = \"&BD\";\n\t\tSpcName[10] = \"S&D\";\n\t\tSpcName[11] = \"&TT\";\n\t\tSpcName[12] = \"C&Y\";\n\t\tSpcName[13] = \"&HH\";\n\t\tbreak;\n\tcase 0x02:\t// YM2612\n\t\tMultiCore = true;\n\t\tCoreName[0x01] = \"Nuked OPN2\";\n\t\t//CoreName[0x02] = \"Gens\";\n\t\tbreak;\n\tcase 0x06:\t// YM2203\n\tcase 0x07:\t// YM2608\n\tcase 0x08:\t// YM2610\n\t\tMultiCore = true;\n\t\tCoreName[0x00] = \"EMU2149\";\n\t\tCoreName[0x01] = \"MAME\";\n\t\tbreak;\n\t/*case 0x06:\t// YM2203\n\t\tChnCount = 6;\t// 3 FM + 3 AY8910\n\t\tSpcModes = 2;\n\t\tChnCntS[0] = 3;\n\t\tSpcName[0] = \"FM Chn\";\n\t\tChnCntS[1] = 3;\n\t\tSpcName[1] = \"PSG Chn\";\n\t\tbreak;*/\n\tcase 0x09:\t// YM3812\n\tcase 0x0C:\t// YMF262\n\t\tMultiCore = true;\n\t\tCoreName[0x00] = \"AdLibEmu\";\n\t\tCoreName[0x01] = \"MAME\";\n\t\tbreak;\n\tcase 0x0D:\t// YMF272B\n\t\tCoreName[0x00] = \"openMSX\";\n\t\tbreak;\n\tcase 0x10:\t// RF5C164\n\tcase 0x11:\t// PWM\n\t\tCoreName[0x00] = \"Gens\";\n\t\tbreak;\n\tcase 0x12:\t// AY8910\n\t\tMultiCore = true;\n\t\tCoreName[0x00] = \"EMU2149\";\n\t\tCoreName[0x01] = \"MAME\";\n\t\tbreak;\n\tcase 0x14:\t// NES APU\n\t\tMultiCore = true;\n\t\tCoreName[0x00] = \"NSFPlay\";\n\t\tCoreName[0x01] = \"MAME\";\n\t\tbreak;\n\tcase 0x1B:\t// HuC6280\n\t\tMultiCore = true;\n\t\tCoreName[0x00] = \"Ootake\";\n\t\tCoreName[0x01] = \"MAME\";\n\t\tbreak;\n\tcase 0x1F:\t// QSound\n\t\tMultiCore = true;\n\t\tCoreName[0x00] = \"superctr\";\n\t\tCoreName[0x01] = \"MAME\";\n\t\tbreak;\n\tcase 0x27:\t// C352\n\t\tCoreName[0x00] = \"superctr\";\n\t\tbreak;\n\tdefault:\n\t\tChnCount = 0;\n\t\tEnableChk = false;\n\t\tbreak;\n\t}\n\tTempCOpts = (CHIP_OPTS*)&ChipOpts[0x00] + ChipID;\n\tMuteCOpts = (CHIP_OPTS*)&ChipOpts[ChipSet] + ChipID;\n\tif (! MuteCOpts->ChnCnt)\n\t\tCanPan = false;\n\t\n\tif (ChnCount > 15)\n\t\tChnCount = 15;\t// there are only 15 sliders\n\t\n\tfor (CurChn = 0x00; CurChn < 0x02; CurChn ++)\n\t{\n\t\tCTRL_SET_ENABLE(CfgOptPan, EmuCoreRadio1 + CurChn, MultiCore && EnableChk);\n\t\t\n\t\tTempStr = (! CurChn) ? \"Default\" : \"Alternative\";\n\t\tif (CoreName[CurChn] == NULL)\n\t\t\tsprintf(TempName, \"%s Core\", TempStr);\n\t\telse\n\t\t\tsprintf(TempName, \"%s (%s)\", TempStr, CoreName[CurChn]);\n\t\tPanPos = strlen(TempName);\n\t\tSetDlgItemText(CfgOptPan, EmuCoreRadio1 + CurChn, TempName);\n\t}\n\t\n\tCheckRadioButton(CfgOptPan, EmuCoreRadio1, EmuCoreRadio2,\n\t\t\t\t\tEmuCoreRadio1 + TempCOpts->EmuCore);\n\t\n\tfor (CurChn = 0; CurChn < ChnCount; CurChn ++)\n\t{\n\t\tif (SpcName[CurChn] == NULL)\n\t\t{\n\t\t\tif (1 + CurChn < 10)\n\t\t\t\tsprintf(TempName, \"&%u\", 1 + CurChn);\n\t\t\telse\n\t\t\t\tsprintf(TempName, \"&%c\", 'A' + (CurChn - 9));\n\t\t\tSetDlgItemText(CfgOptPan, PanChn1Label + CurChn, TempName);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSetDlgItemText(CfgOptPan, PanChn1Label + CurChn, SpcName[CurChn]);\n\t\t}\n\t\tCTRL_SET_ENABLE(CfgOptPan, PanChn1Label + CurChn, EnableChk && CanPan);\n\t\t\n\t\tPanPos = MuteCOpts->Panning[CurChn] / 0x08 + 0x20;\n\t\tSLIDER_SETPOS(CfgOptPan, PanChn1Slider + CurChn, PanPos);\n\t\tCTRL_SET_ENABLE(CfgOptPan, PanChn1Slider + CurChn, EnableChk && CanPan);\n\t}\n\tPanPos = 0x20;\n\tfor (; CurChn < 15; CurChn ++)\n\t{\n\t\tif (1 + CurChn < 10)\n\t\t\tsprintf(TempName, \"&%u\", 1 + CurChn);\n\t\telse\n\t\t\tsprintf(TempName, \"&%c\", 'A' + (CurChn - 9));\n\t\tSetDlgItemText(CfgOptPan, PanChn1Label + CurChn, TempName);\n\t\t\n\t\tCTRL_DISABLE(CfgOptPan, PanChn1Label + CurChn);\n\t\tCTRL_DISABLE(CfgOptPan, PanChn1Slider + CurChn);\n\t\tSLIDER_SETPOS(CfgOptPan, PanChn1Slider + CurChn, PanPos);\n\t}\n\t\n\tMuteChipID = ChipID;\n\tMuteChipSet = ChipSet;\n\t\n\treturn;\n}\n\nstatic void SetPanningData(UINT32 Slider, UINT16 Value, bool NoRefresh)\n{\n\tif (Slider >= MuteCOpts->ChnCnt)\n\t\treturn;\n\t\n\tMuteCOpts->Panning[Slider] = (Value - 0x20) * 0x08;\n\t\n\tRefreshPanning();\n\tif (! NoRefresh)\n\t\tUpdatePlayback();\n\t\n\treturn;\n}\n\nvoid Dialogue_TrackChange(void)\n{\n\t// redraw Muting Boxes and Panning Sliders\n\tShowMutingCheckBoxes(MuteChipID, MuteChipSet);\n\tShowOptPanBoxes(MuteChipID, MuteChipSet);\n\t\n\treturn;\n}\n"
  },
  {
    "path": "in_vgm/dlg_fileinfo.c",
    "content": "/*3456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456\n0000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999*/\n#include <windows.h>\n#include <stdio.h>\n#include <string.h>\n#include <wchar.h>\n#include <math.h>\n\n#include \"Winamp/wa_ipc.h\"\n#include \"Winamp/in2.h\"\n\n#include \"stdbool.h\"\n#include \"chips/mamedef.h\"\n#include \"VGMPlay.h\"\n#include \"VGMPlay_Intf.h\"\n#include \"in_vgm.h\"\n\n#define DllExport\t__declspec(dllexport)\n#define SETCHECKBOX(hWnd, DlgID, Check)\tSendDlgItemMessage(hWnd, DlgID, BM_SETCHECK, Check, 0)\n\n\ntypedef struct fileinfo_data\n{\n\tUINT32 FileNameAlloc;\n\twchar_t* FileName;\n\tbool ForceReload;\n\t\n\tFILETIME FileTime;\n\tUINT32 FileSize;\n\tVGM_HEADER Head;\n\tGD3_TAG Tag;\n\t\n\tUINT32 TrackLen;\t// length without loops\n\tUINT32 TotalLen;\t// including loops\n\tUINT32 LoopLen;\n\tUINT32 DataSize;\n\tfloat BitRate;\n\tfloat VolGain;\n} FINF_DATA;\n\n\n// Function Prototypes from in_vgm.c\nvoid Config(HWND hWndParent);\n\n\n// Function Prototypes\nvoid SetInfoDlgFile(const char* FileName);\nvoid SetInfoDlgFileW(const wchar_t* FileName);\nUINT32 GetVGZFileSize(const char* FileName);\nUINT32 GetVGZFileSizeW(const wchar_t* FileName);\nstatic void CopyWStr(wchar_t** DstStr, const wchar_t* SrcStr);\nstatic void CopyTagData(GD3_TAG* DstTag, const GD3_TAG* SrcTag);\nstatic bool LoadInfoA(const char* FileName, FINF_DATA* FileInf);\nstatic bool LoadInfoW(const wchar_t* FileName, FINF_DATA* FileInf);\nstatic void FixNewLine(wchar_t** TextData);\nstatic void FixSeparators(wchar_t** TextData);\nstatic void TrimWhitespaces(wchar_t* TextData);\n\nstatic bool CheckFM2413Text(VGM_HEADER* FileHead);\nUINT32 FormatVGMTag(const UINT32 BufLen, in_char* Buffer, GD3_TAG* FileTag, VGM_HEADER* FileHead);\n\nstatic void AppendToStr(char* Buffer, const char* AppendStr, UINT8 Seperator);\nstatic void MakeChipStr(char* Buffer, UINT8 ChipID, UINT8 SubType, UINT32 Clock);\nstatic void PrintTime(char* Buffer, UINT32 MSecTime);\nstatic void GetChipUsageText(char* Buffer, VGM_HEADER* FileHead);\nvoid FormatVGMLength(char* Buffer, FINF_DATA* FileInf);\nvoid PrintTime(char* Buffer, UINT32 MSecTime);\n//int GetTrackNumber(const char *filename);\nbool LoadPlayingVGMInfo(const char* FileName);\nbool LoadPlayingVGMInfoW(const wchar_t* FileName);\nvoid QueueInfoReload(void);\n\nbool GetExtendedFileInfoW(const wchar_t* FileName, const char* MetaType, wchar_t* RetBuffer,\n\t\t\t\t\t\t  int RetBufLen);\nconst wchar_t* GetTagStringEngJap(const wchar_t* TextEng, const wchar_t* TextJap,\n\t\t\t\t\t\t\t\t\tbool LangMode);\nvoid DisplayTagString(HWND hWndDlg, int DlgItem, const wchar_t* TextEng,\n\t\t\t\t\t  const wchar_t* TextJap, bool LangMode);\nBOOL CALLBACK FileInfoDialogProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam);\nDllExport int winampGetExtendedFileInfoW(const wchar_t* wfilename, const char* metadata,\n\t\t\t\t\t\t\t\t\t\t wchar_t* ret, int retlen);\nDllExport int winampGetExtendedFileInfo(const char* filename, const char* metadata, char* ret,\n\t\t\t\t\t\t\t\t\t\tint retlen);\n\n\n#define METATAG_AUTHOR\t0x01\n#define METATAG_LENGTH\t0x02\n#define METATAG_TITLE\t0x03\n#define METATAG_ALBUM\t0x04\n#define METATAG_COMMENT\t0x05\n#define METATAG_YEAR\t0x06\n#define METATAG_GENRE\t0x07\n#define METATAG_UNKNOWN\t0xFF\n\n\nextern VGM_HEADER VGMHead;\nextern GD3_TAG VGMTag;\n\n\nextern UINT32 VGMMaxLoop;\nextern UINT32 FadeTime;\n\nstatic FINF_DATA VGMInfo;\nstatic FINF_DATA PlayVGMInfo;\nstatic const char* FileNameToLoad;\nstatic const wchar_t* FileNameToLoadW;\n\n\nvoid SetInfoDlgFile(const char* FileName)\n{\n\tFileNameToLoadW = NULL;\n\tFileNameToLoad = FileName;\n\t\n\treturn;\n}\n\nvoid SetInfoDlgFileW(const wchar_t* FileName)\n{\n\tFileNameToLoad = NULL;\n\tFileNameToLoadW = FileName;\n\t\n\treturn;\n}\n\nUINT32 GetVGZFileSize(const char* FileName)\n{\n\t// returns the size of a compressed VGZ file\n\t// or 0 it the file is uncompressed or not found\n\tFILE* hFile;\n\tUINT32 FileSize;\n\tUINT16 gzHead;\n\t\n\thFile = fopen(FileName, \"rb\");\n\tif (hFile == NULL)\n\t\treturn 0x00;\n\t\n\tfread(&gzHead, 0x02, 0x01, hFile);\n\tif (gzHead == 0x8B1F)\n\t{\n\t\t// .gz File\n\t\tfseek(hFile, 0x00, SEEK_END);\n\t\tFileSize = ftell(hFile);\n\t}\n\telse\n\t{\n\t\tFileSize = 0x00;\n\t}\n\t\n\tfclose(hFile);\n\t\n\treturn FileSize;\n}\n\nUINT32 GetVGZFileSizeW(const wchar_t* FileName)\n{\n\t// returns the size of a compressed VGZ file\n\t// or 0 it the file is uncompressed or not found\n\tFILE* hFile;\n\tUINT32 FileSize;\n\tUINT16 gzHead;\n\t\n\thFile = _wfopen(FileName, L\"rb\");\n\tif (hFile == NULL)\n\t\treturn 0x00;\n\t\n\tfread(&gzHead, 0x02, 0x01, hFile);\n\tif (gzHead == 0x8B1F)\n\t{\n\t\t// .gz File\n\t\tfseek(hFile, 0x00, SEEK_END);\n\t\tFileSize = ftell(hFile);\n\t}\n\telse\n\t{\n\t\tFileSize = 0x00;\n\t}\n\t\n\tfclose(hFile);\n\t\n\treturn FileSize;\n}\n\nstatic void CopyWStr(wchar_t** DstStr, const wchar_t* SrcStr)\n{\n\tsize_t StrLen;\n\t\n\tif (SrcStr == NULL)\n\t{\n\t\t*DstStr = NULL;\n\t\treturn;\n\t}\n\t\n\tStrLen = wcslen(SrcStr) + 0x01;\n\t*DstStr = (wchar_t*)malloc(StrLen * sizeof(wchar_t));\n\twcscpy(*DstStr, SrcStr);\n\t\n\treturn;\n}\n\nstatic void CopyTagData(GD3_TAG* DstTag, const GD3_TAG* SrcTag)\n{\n\tDstTag->fccGD3 = SrcTag->fccGD3;\n\tDstTag->lngVersion = SrcTag->lngVersion;\n\tDstTag->lngTagLength = SrcTag->lngTagLength;\n\tCopyWStr(&DstTag->strTrackNameE,\tSrcTag->strTrackNameE);\n\tCopyWStr(&DstTag->strTrackNameJ,\tSrcTag->strTrackNameJ);\n\tCopyWStr(&DstTag->strGameNameE,\t\tSrcTag->strGameNameE);\n\tCopyWStr(&DstTag->strGameNameJ,\t\tSrcTag->strGameNameJ);\n\tCopyWStr(&DstTag->strSystemNameE,\tSrcTag->strSystemNameE);\n\tCopyWStr(&DstTag->strSystemNameJ,\tSrcTag->strSystemNameJ);\n\tCopyWStr(&DstTag->strAuthorNameE,\tSrcTag->strAuthorNameE);\n\tCopyWStr(&DstTag->strAuthorNameJ,\tSrcTag->strAuthorNameJ);\n\tCopyWStr(&DstTag->strReleaseDate,\tSrcTag->strReleaseDate);\n\tCopyWStr(&DstTag->strCreator,\t\tSrcTag->strCreator);\n\tCopyWStr(&DstTag->strNotes,\t\t\tSrcTag->strNotes);\n\t\n\treturn;\n}\n\nstatic bool LoadInfoA(const char* FileName, FINF_DATA* FileInf)\n{\n\tsize_t FNSize;\n\twchar_t* FileNameW;\n\tbool RetVal;\n\t\n\tFNSize = mbstowcs(NULL, FileName, 0);\n\tif (FNSize == -1)\n\t\treturn false;\n\tFNSize ++;\n\t\n\tFileNameW = (wchar_t*)malloc(FNSize * sizeof(wchar_t));\n\tmbstowcs(FileNameW, FileName, FNSize);\n\t\n\tRetVal = LoadInfoW(FileNameW, FileInf);\n\t\n\tfree(FileNameW);\n\treturn RetVal;\n}\n\nstatic bool LoadInfoW(const wchar_t* FileName, FINF_DATA* FileInf)\n{\n\tHANDLE hFile;\n\tFILETIME fileWrtTime;\n\tVGM_HEADER* FH;\n\tUINT32 StrSize;\n\tINT32 TempSLng;\n\t\n\thFile = CreateFileW(FileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,\n\t\t\t\t\t\tNULL, OPEN_EXISTING, 0, NULL);\n\tif (hFile != INVALID_HANDLE_VALUE)\n\t{\n\t\tGetFileTime(hFile, NULL, NULL, &fileWrtTime);\n\t\tCloseHandle(hFile);\thFile = NULL;\n\t}\n\telse\n\t{\n\t\tfileWrtTime.dwLowDateTime = 0x00;\n\t\tfileWrtTime.dwHighDateTime = 0x00;\n\t}\n\t\n\tif (! FileInf->ForceReload && ! Options.NoInfoCache)\n\t{\n\t\tif (FileInf->FileName != NULL && ! _wcsicmp(FileInf->FileName, FileName))\n\t\t{\n\t\t\t// We just loaded that file.\n\t\t\tif (CompareFileTime(&fileWrtTime, &FileInf->FileTime) == 0)\n\t\t\t\treturn true;\t// The file wasn't changed, so don't reload.\n\t\t}\n\t}\n\tFileInf->ForceReload = false;\n\t\n\tStrSize = wcslen(FileName) + 1;\n\tif (FileInf->FileNameAlloc < StrSize)\n\t{\n\t\tFileInf->FileName = (wchar_t*)realloc(FileInf->FileName, StrSize * sizeof(wchar_t));\n\t\tFileInf->FileNameAlloc = StrSize;\n\t}\n\twcscpy(FileInf->FileName, FileName);\n\t\n\tFreeGD3Tag(&FileInf->Tag);\n\t\n\tif (FileInf != &PlayVGMInfo)\n\t{\n\t\tif (PlayVGMInfo.FileName != NULL && ! _wcsicmp(PlayVGMInfo.FileName, FileName))\n\t\t{\n\t\t\tif (PlayVGMInfo.ForceReload || Options.NoInfoCache)\n\t\t\t\tLoadInfoW(PlayVGMInfo.FileName, &PlayVGMInfo);\n\t\t\t\n\t\t\t// copy all info from PlayVGMInfo to current structure\n\t\t\t// (advanced caching) ;)\n\t\t\tFileInf->FileTime = PlayVGMInfo.FileTime;\n\t\t\tFileInf->FileSize = PlayVGMInfo.FileSize;\n\t\t\tFileInf->Head = PlayVGMInfo.Head;\n\t\t\tCopyTagData(&FileInf->Tag, &PlayVGMInfo.Tag);\n\t\t\tFileInf->TrackLen = PlayVGMInfo.TrackLen;\n\t\t\tFileInf->TotalLen = PlayVGMInfo.TotalLen;\n\t\t\tFileInf->LoopLen = PlayVGMInfo.LoopLen;\n\t\t\tFileInf->DataSize = PlayVGMInfo.DataSize;\n\t\t\tFileInf->BitRate = PlayVGMInfo.BitRate;\n\t\t\tFileInf->VolGain = PlayVGMInfo.VolGain;\n\t\t\t\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\tFileInf->FileSize = GetVGMFileInfoW(FileInf->FileName, &FileInf->Head, &FileInf->Tag);\n\t}\n\telse\n\t{\n\t\tFileInf->FileSize = VGMHead.lngEOFOffset;\n\t\tFileInf->Head = VGMHead;\n\t\tCopyTagData(&FileInf->Tag, &VGMTag);\n\t}\n\t\n\tif (! FileInf->FileSize)\n\t{\n\t\tFileInf->FileTime.dwLowDateTime = 0x00;\n\t\tFileInf->FileTime.dwHighDateTime = 0x00;\n\t\tFileInf->FileSize = 0x00;\n\t\tmemset(&FileInf->Head, 0x00, sizeof(VGM_HEADER));\n\t\tmemset(&FileInf->Tag, 0x00, sizeof(GD3_TAG));\n\t\t\n\t\tFileInf->TrackLen = 0x00;\n\t\tFileInf->TotalLen = 0x00;\n\t\tFileInf->LoopLen = 0x00;\n\t\tFileInf->DataSize = 0x00;\n\t\tFileInf->BitRate = 0.0f;\n\t\tFileInf->VolGain = 0.0f;\n\t\t\n\t\tFileInf->Tag.strNotes = (wchar_t*)malloc(16 * sizeof(wchar_t));\n\t\tif (GetGZFileLengthW(FileName) == 0xFFFFFFFF)\n\t\t\twcscpy(FileInf->Tag.strNotes, L\"File not found!\");\n\t\telse\n\t\t\twcscpy(FileInf->Tag.strNotes, L\"File invalid!\");\n\t\treturn false;\n\t}\n\tFileInf->FileTime = fileWrtTime;\n\t\n\tFH = &FileInf->Head;\n\tFileInf->TrackLen = CalcSampleMSecExt(FH->lngTotalSamples, 0x02, FH);\n\tFileInf->LoopLen = CalcSampleMSecExt(FH->lngLoopSamples, 0x02, FH);\n\tif (! FH->lngLoopSamples)\n\t{\n\t\tFileInf->TotalLen = CalcSampleMSecExt(FH->lngTotalSamples, 0x02, FH) +\n\t\t\t\t\t\t\tOptions.PauseNL;\n\t}\n\telse\n\t{\n\t\tif (! VGMMaxLoop)\t// infinite looping\n\t\t{\n\t\t\tFileInf->TotalLen = -1000;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tTempSLng = (VGMMaxLoop * FH->bytLoopModifier + 0x08) / 0x10 - FH->bytLoopBase;\n\t\t\tif (TempSLng < 0x01)\n\t\t\t\tTempSLng = 0x01;\n\t\t\tFileInf->TotalLen = CalcSampleMSecExt(FH->lngTotalSamples + (INT64)(TempSLng - 1) *\n\t\t\t\t\t\t\t\tFH->lngLoopSamples, 0x02, FH) + FadeTime + Options.PauseLp;\n\t\t}\n\t}\n\t\n\tStrSize = GetVGZFileSizeW(FileInf->FileName);\n\tif (! StrSize)\n\t{\n\t\tif (FH->lngGD3Offset)\n\t\t\tFileInf->DataSize = FH->lngGD3Offset - FH->lngDataOffset;\n\t\telse\n\t\t\tFileInf->DataSize = FH->lngEOFOffset - FH->lngDataOffset;\n\t}\n\telse\n\t{\n\t\tFileInf->FileSize = StrSize;\n\t\tFileInf->DataSize = StrSize;\n\t}\n\t\n\t// 1 Bytes = 8 Bits\n\t// 1 sec = 1000 ms\n\t// -> (bytes * 8) / (ms / 1000) = bytes * 8000 / ms\n\tFileInf->BitRate = (INT64)FileInf->DataSize * 8000 / (float)FileInf->TrackLen;\n\t\n\tif (FH->bytVolumeModifier <= VOLUME_MODIF_WRAP)\n\t\tTempSLng = FH->bytVolumeModifier;\n\telse if (FH->bytVolumeModifier == (VOLUME_MODIF_WRAP + 0x01))\n\t\tTempSLng = VOLUME_MODIF_WRAP - 0x100;\n\telse\n\t\tTempSLng = FH->bytVolumeModifier - 0x100;\n\tFileInf->VolGain = (float)pow(2.0, TempSLng / (double)0x20);\n\t\n\tif (Options.TrimWhitespc)\n\t{\n\t\tTrimWhitespaces(FileInf->Tag.strTrackNameE);\n\t\tTrimWhitespaces(FileInf->Tag.strTrackNameJ);\n\t\tTrimWhitespaces(FileInf->Tag.strGameNameE);\n\t\tTrimWhitespaces(FileInf->Tag.strGameNameJ);\n\t\tTrimWhitespaces(FileInf->Tag.strSystemNameE);\n\t\tTrimWhitespaces(FileInf->Tag.strSystemNameJ);\n\t\tTrimWhitespaces(FileInf->Tag.strAuthorNameE);\n\t\tTrimWhitespaces(FileInf->Tag.strAuthorNameJ);\n\t\tTrimWhitespaces(FileInf->Tag.strReleaseDate);\n\t\tTrimWhitespaces(FileInf->Tag.strCreator);\n\t\tTrimWhitespaces(FileInf->Tag.strNotes);\n\t}\n\tif (Options.StdSeparators)\n\t{\n\t\tFixSeparators(&FileInf->Tag.strAuthorNameE);\n\t\tFixSeparators(&FileInf->Tag.strAuthorNameJ);\n\t}\n\t\n\tif (! FileInf->Tag.lngVersion)\n\t{\n\t\tFileInf->Tag.strNotes = (wchar_t*)malloc(22 * sizeof(wchar_t));\n\t\twcscpy(FileInf->Tag.strNotes, L\"No GD3 Tag available.\");\n\t}\n\telse\n\t{\n\t\tFixNewLine(&FileInf->Tag.strNotes);\n\t}\n\t\n\treturn true;\n}\n\nstatic void FixNewLine(wchar_t** TextData)\n{\n\t// Note: Reallocates memory for final string\n\twchar_t* TempStr;\n\twchar_t* SrcStr;\n\twchar_t* DstStr;\n\tUINT32 StrSize;\n\t\n\tif (TextData == NULL || *TextData == NULL || ! wcslen(*TextData))\n\t\treturn;\n\t\n\t// fix Notes-Tag (CR -> CRLF)\n\tSrcStr = *TextData;\n\tStrSize = 0x00;\n\twhile(*SrcStr != L'\\0')\n\t{\n\t\tif (*SrcStr == L'\\n')\n\t\t\tStrSize ++;\t// count CR characters twice (for additional LF character)\n\t\tSrcStr ++;\n\t\tStrSize ++;\n\t}\n\tStrSize ++;\t// final \\0 character\n\tTempStr = (wchar_t*)malloc(StrSize * sizeof(wchar_t));\n\t\n\tSrcStr = *TextData;\n\tDstStr = TempStr;\n\twhile(*SrcStr != L'\\0')\n\t{\n\t\tif (*SrcStr == L'\\n')\n\t\t{\n\t\t\t*DstStr = L'\\r';\n\t\t\tDstStr ++;\n\t\t}\n\t\t*DstStr = *SrcStr;\n\t\tSrcStr ++;\n\t\tDstStr ++;\n\t}\n\t*DstStr = L'\\0';\n\tfree(*TextData);\n\t*TextData = TempStr;\n\t\n\treturn;\n}\n\n#define GOODSEP_CHR\t\tL','\n\nstatic void FixSeparators(wchar_t** TextData)\n{\n\t// Note: Reallocates memory for final string\n\tconst wchar_t BADSEPS[] =\n\t{\tL';', L'/', L'\\\\', L'&', L'\\xFF0C', L'\\xFF0F', L'\\xFF3C', 0x0000};\n\t\n\twchar_t* TempStr;\n\twchar_t* SrcStr;\n\twchar_t* DstStr;\n\tconst wchar_t* ChkStr;\n\tUINT32 StrSize;\n\tUINT32 SpcWrt;\n\tbool WroteSep;\n\t\n\tif (TextData == NULL || *TextData == NULL || ! wcslen(*TextData))\n\t\treturn;\n\t\n\t// fix Author-Tag (a;b;c -> a, b, c)\n\tSrcStr = *TextData;\n\tStrSize = 0x00;\n\tWroteSep = false;\n\twhile(*SrcStr != L'\\0')\n\t{\n\t\tif (WroteSep && ! (*(SrcStr + 1) == L' ' || *(SrcStr + 1) == 0x3000))\n\t\t\tStrSize ++;\t// need additional Space character\n\t\t\n\t\tChkStr = BADSEPS;\n\t\twhile(*ChkStr != 0x0000)\n\t\t{\n\t\t\tif (*SrcStr == *ChkStr)\n\t\t\t{\n\t\t\t\t// replace bad with good chars\n\t\t\t\t*SrcStr = GOODSEP_CHR;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tChkStr ++;\n\t\t}\n\t\tif (*SrcStr == GOODSEP_CHR)\n\t\t\tWroteSep = true;\n\t\tSrcStr ++;\n\t\tStrSize ++;\n\t}\n\tStrSize ++;\t// final \\0 character\n\tTempStr = (wchar_t*)malloc(StrSize * sizeof(wchar_t));\n\t\n\tSrcStr = *TextData;\n\tDstStr = TempStr;\n\tSpcWrt = 0;\n\tWroteSep = false;\n\twhile(*SrcStr != L'\\0')\n\t{\n\t\tif (*SrcStr == GOODSEP_CHR)\n\t\t{\n\t\t\tWroteSep = true;\n\t\t\t// trim spaces left of the seperator\n\t\t\tDstStr -= SpcWrt;\n\t\t\tSpcWrt = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (*SrcStr == L' ' || *SrcStr == 0x3000)\n\t\t\t\tSpcWrt ++;\n\t\t\telse\n\t\t\t\tSpcWrt = 0;\n\t\t\tif (WroteSep && ! SpcWrt)\n\t\t\t{\n\t\t\t\t// insert space after the seperator\n\t\t\t\t*DstStr = L' ';\n\t\t\t\tDstStr ++;\n\t\t\t\tSpcWrt ++;\n\t\t\t}\n\t\t\tWroteSep = false;\n\t\t}\n\t\t*DstStr = *SrcStr;\n\t\tSrcStr ++;\n\t\tDstStr ++;\n\t}\n\t*DstStr = L'\\0';\n\tfree(*TextData);\n\t*TextData = TempStr;\n\t\n\treturn;\n}\n\nstatic void TrimWhitespaces(wchar_t* TextData)\n{\n\t// Note: Writes to argument string\n\twchar_t* CurStr;\n\t\n\tif (TextData == NULL || ! wcslen(TextData))\n\t\treturn;\n\t\n\t// trim whitespace at end\n\tCurStr = TextData + wcslen(TextData);\n\tCurStr --;\n\twhile(iswspace(*CurStr))\n\t\tCurStr --;\n\tCurStr ++;\n\t*CurStr = L'\\0';\n\t\n\t// trim whitespace at start\n\tCurStr = TextData;\n\twhile(iswspace(*CurStr))\n\t\tCurStr ++;\n\twcscpy(TextData, CurStr);\n\t\n\treturn;\n}\n\n\nstatic bool CheckFM2413Text(VGM_HEADER* FileHead)\n{\n\tUINT8 CurChip;\n\tUINT32 Clocks;\n\t\n\tif (! Options.AppendFM2413 || FileHead == NULL || ! GetChipClock(FileHead, 0x01, NULL))\n\t\treturn false;\n\t\n\tClocks = 0x00;\n\tfor (CurChip = 0x02; CurChip < CHIP_COUNT; CurChip ++)\n\t\tClocks |= GetChipClock(FileHead, CurChip, NULL);\n\t\n\treturn (! Clocks);\n}\n\nUINT32 FormatVGMTag(const UINT32 BufLen, in_char* Buffer, GD3_TAG* FileTag, VGM_HEADER* FileHead)\n{\n\tconst in_char* BufEnd;\n\tin_char* CurBuf;\n\tconst char* FormatStr;\n\tconst wchar_t* TagStr;\n\tconst wchar_t* TagStrE;\n\tconst wchar_t* TagStrJ;\n\tbool TempFlag;\n\tbool AppendFM;\n\tsize_t CnvBytes;\n\t\n\tBufEnd = Buffer + BufLen - 1;\n\tCurBuf = Buffer;\n\tFormatStr = Options.TitleFormat;\n\t\n\twhile(CurBuf < BufEnd && *FormatStr != '\\0')\n\t{\n\t\tif (*FormatStr == '%')\n\t\t{\n\t\t\tFormatStr ++;\n\t\t\tTempFlag = false;\t// Is Unknown Char\n\t\t\tAppendFM = false;\n\t\t\tswitch(toupper(*FormatStr))\n\t\t\t{\n\t\t\tcase 'T':\t// Track Title\n\t\t\t\tTagStrE = FileTag->strTrackNameE;\n\t\t\t\tTagStrJ = FileTag->strTrackNameJ;\n\t\t\t\tbreak;\n\t\t\tcase 'A':\t// Author\n\t\t\t\tTagStrE = FileTag->strAuthorNameE;\n\t\t\t\tTagStrJ = FileTag->strAuthorNameJ;\n\t\t\t\tbreak;\n\t\t\tcase 'G':\t// Game Name\n\t\t\t\tTagStrE = FileTag->strGameNameE;\n\t\t\t\tTagStrJ = FileTag->strGameNameJ;\n\t\t\t\tAppendFM = CheckFM2413Text(FileHead);\n\t\t\t\tbreak;\n\t\t\tcase 'D':\t// Release Date\n\t\t\t\tTagStrE = FileTag->strReleaseDate;\n\t\t\t\tTagStrJ = NULL;\n\t\t\t\tbreak;\n\t\t\tcase 'S':\t// System Name\n\t\t\t\tTagStrE = FileTag->strSystemNameE;\n\t\t\t\tTagStrJ = FileTag->strSystemNameJ;\n\t\t\t\tbreak;\n\t\t\tcase 'C':\t// File Creator\n\t\t\t\tTagStrE = FileTag->strCreator;\n\t\t\t\tTagStrJ = NULL;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tTempFlag = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (TempFlag)\n\t\t\t{\n#ifndef UNICODE_INPUT_PLUGIN\n\t\t\t\t*CurBuf = *FormatStr;\n\t\t\t\tFormatStr ++;\tCurBuf ++;\n#else\n\t\t\t\tCnvBytes = MultiByteToWideChar(CP_THREAD_ACP, 0x00, FormatStr, 1, CurBuf,\n\t\t\t\t\t\t\t\t\t\t\t\tBufEnd - CurBuf);\n\t\t\t\tFormatStr ++;\tCurBuf += CnvBytes;\n#endif\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tFormatStr ++;\n\t\t\t\tif (toupper(*FormatStr) == 'J')\n\t\t\t\t{\n\t\t\t\t\tTempFlag = true;\n\t\t\t\t\tFormatStr ++;\n\t\t\t\t}\n\t\t\t\tTagStr = GetTagStringEngJap(TagStrE, TagStrJ, TempFlag);\n\t\t\t\tif (TagStr == NULL)\n\t\t\t\t\tTagStr = L\"\";\n#ifndef UNICODE_INPUT_PLUGIN\n\t\t\t\tCnvBytes = WideCharToMultiByte(CP_THREAD_ACP, 0x00, TagStr, -1, CurBuf,\n\t\t\t\t\t\t\t\t\t\t\t\tBufEnd - CurBuf, NULL, NULL);\n\t\t\t\tif (CnvBytes)\n\t\t\t\t\tCurBuf += CnvBytes - 1;\t// It counts the \\0 ternimator, too.\n\t\t\t\t\n\t\t\t\t// The problem with the ANSI C function is, that it simply stops\n\t\t\t\t// converting the string, instead of inserting '?', which would be nicer,\n\t\t\t\t// at least in this case.\n\t\t\t\t/*TagStr = GetTagStringEngJap(TagStrE, TagStrJ, TempFlag);\n\t\t\t\tCnvBytes = wcstombs(CurBuf, TagStr, BufEnd - CurBuf);\n\t\t\t\tif (CnvBytes == -1)\n\t\t\t\t{\n\t\t\t\t\tTagStr = GetTagStringEngJap(TagStrE, TagStrJ, ! TempFlag);\n\t\t\t\t\tCnvBytes = wcstombs(CurBuf, TagStr, BufEnd - CurBuf);\n\t\t\t\t}\n\t\t\t\tif (CnvBytes != -1)\n\t\t\t\t\tCurBuf += CnvBytes - 1;*/\n\t\t\t\t\n\t\t\t\tif (AppendFM && (BufEnd - CurBuf) >= 0x05+1)\n\t\t\t\t{\n\t\t\t\t\tstrcpy(CurBuf, \" (FM)\");\n\t\t\t\t\tCurBuf += 0x05;\n\t\t\t\t}\n#else\n\t\t\t\tCnvBytes = wcslen(TagStr);\n\t\t\t\tif (CnvBytes < BufEnd - CurBuf)\n\t\t\t\t{\n\t\t\t\t\twcscpy(CurBuf, TagStr);\n\t\t\t\t\tCurBuf += CnvBytes;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tCnvBytes = (BufEnd - CurBuf) - 1;\n\t\t\t\t\twcsncpy(CurBuf, TagStr, CnvBytes);\n\t\t\t\t\tCurBuf += CnvBytes;\n\t\t\t\t}\n\t\t\t\tif (AppendFM && (BufEnd - CurBuf) >= 0x05+1)\n\t\t\t\t{\n\t\t\t\t\twcscpy(CurBuf, L\" (FM)\");\n\t\t\t\t\tCurBuf += 0x05;\n\t\t\t\t}\n#endif\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n#ifndef UNICODE_INPUT_PLUGIN\n\t\t\t*CurBuf = *FormatStr;\n\t\t\tFormatStr ++;\tCurBuf ++;\n#else\n\t\t\tCnvBytes = MultiByteToWideChar(CP_THREAD_ACP, 0x00, FormatStr, 1, CurBuf,\n\t\t\t\t\t\t\t\t\t\t\tBufEnd - CurBuf);\n\t\t\tFormatStr ++;\tCurBuf += CnvBytes;\n#endif\n\t\t}\n\t}\n#ifndef UNICODE_INPUT_PLUGIN\n\t*CurBuf = '\\0';\n#else\n\t*CurBuf = L'\\0';\n#endif\n\t\n\treturn Buffer - CurBuf;\n}\n\n\nstatic void AppendToStr(char* Buffer, const char* AppendStr, UINT8 Seperator)\n{\n\t// Seperator Mask:\n\t//\t01 - Space\n\t//\t02 - Comma\n\tchar* BufPnt;\n\t\n\tif (AppendStr == NULL)\n\t\treturn;\n\t\n\tif (*Buffer == '\\0')\n\t{\n\t\tstrcpy(Buffer, AppendStr);\n\t}\n\telse\n\t{\n\t\tBufPnt = Buffer + strlen(Buffer);\n\t\tif (Seperator & 0x02)\n\t\t{\n\t\t\t*BufPnt = ',';\n\t\t\tBufPnt ++;\n\t\t}\n\t\tif (Seperator & 0x01)\n\t\t{\n\t\t\t*BufPnt = ' ';\n\t\t\tBufPnt ++;\n\t\t}\n\t\tstrcpy(BufPnt, AppendStr);\n\t}\n\t\n\treturn;\n}\n\nstatic void MakeChipStr(char* Buffer, UINT8 ChipID, UINT8 SubType, UINT32 Clock)\n{\n\tif (! Clock)\n\t\treturn;\n\t\n\tif (ChipID == 0x00 && (Clock & 0x80000000))\n\t\tClock &= ~0x40000000;\n\tif (Clock & 0x80000000)\n\t{\n\t\tClock &= ~0x80000000;\n\t\tChipID |= 0x80;\n\t}\n\t\n\tif (! (Clock & 0x40000000))\n\t{\n\t\tAppendToStr(Buffer, GetAccurateChipName(ChipID, SubType), 0x03);\n\t}\n\telse\n\t{\n\t\tAppendToStr(Buffer, \"2x\", 0x03);\n\t\tAppendToStr(Buffer, GetAccurateChipName(ChipID, SubType), 0x00);\n\t}\n\t\n\treturn;\n}\n\nstatic void GetChipUsageText(char* Buffer, VGM_HEADER* FileHead)\n{\n\tUINT8 CurChip;\n\tUINT32 ChpClk;\n\tUINT8 ChpType;\n\t\n\t*Buffer = '\\0';\n\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++)\n\t{\n\t\tChpClk = GetChipClock(FileHead, CurChip, &ChpType);\n\t\tif (ChpClk && GetChipClock(FileHead, 0x80 | CurChip, NULL))\n\t\t\tChpClk |= 0x40000000;\n\t\tMakeChipStr(Buffer, CurChip, ChpType, ChpClk);\n\t}\n\t\n\treturn;\n}\n\nstatic void PrintTime(char* Buffer, UINT32 MSecTime)\n{\n\tUINT16 MSecs;\n\tUINT16 Secs;\n\tUINT16 Mins;\n\tUINT16 Hours;\n\tUINT32 Days;\n\t\n\tMSecs = MSecTime % 1000;\n\tMSecTime /= 1000;\n\tSecs = MSecTime % 60;\n\tMSecTime /= 60;\n\tMins = MSecTime % 60;\n\tMSecTime /= 60;\n\tHours = MSecTime % 24;\n\tMSecTime /= 24;\n\tDays = MSecTime;\n\t\n\t// Maximum Output: 4 294 967 295 -> \"49d + 17:02:47.29\" (17 chars + \\0)\n\tif (Days)\n\t{\n\t\t// just for fun\n\t\t//\t\t\t\t 1d +  2 :  34 :  56 . 78\n\t\tsprintf(Buffer, \"%ud + %hu:%02hu:%02hu.%02hu\", Days, Hours, Mins, Secs, MSecs / 10);\n\t}\n\telse if (Hours)\n\t{\n\t\t// unlikely for single VGMs, but possible\n\t\t//\t\t\t\t  1 :  23 :  45 . 67\n\t\tsprintf(Buffer, \"%hu:%02hu:%02hu.%02hu\", Hours, Mins, Secs, MSecs / 10);\n\t}\n\telse if (Mins)\n\t{\n\t\t//\t\t\t\t  1 :  23 . 45\n\t\tsprintf(Buffer, \"%hu:%02hu.%02hu\", Mins, Secs, MSecs / 10);\n\t}\n\telse\n\t{\n\t\t//\t\t\t\t  1 . 23\n\t\tsprintf(Buffer, \"%hu.%02hu\", Secs, MSecs / 10);\n\t}\n\n\treturn;\n}\n\nvoid FormatVGMLength(char* Buffer, FINF_DATA* FileInf)\n{\n\tUINT32 IntroLen;\n\tchar TempBuf1[0x20];\n\tchar TempBuf2[0x20];\n\n\tPrintTime(Buffer, FileInf->TrackLen);\n\tif (! FileInf->LoopLen)\n\t{\n\t\tstrcat(Buffer, \" (no loop)\");\n\t}\n\telse\n\t{\n\t\tIntroLen = FileInf->TrackLen - FileInf->LoopLen;\n\t\tif (IntroLen < 500)\n\t\t{\n\t\t\t// no intro (or only a very small intro for song init)\n\t\t\tstrcat(Buffer, \" (looped)\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\tPrintTime(TempBuf1, IntroLen);\n\t\t\tPrintTime(TempBuf2, FileInf->LoopLen);\n\t\t\tsprintf(Buffer, \"%s (%s intro and %s loop)\", Buffer, TempBuf1, TempBuf2);\n\t\t}\n\t}\n\n\treturn;\n}\n\n//-----------------------------------------------------------------\n// Get the track number for a given filename\n// by trying to find its M3U playlist\n//-----------------------------------------------------------------\n/*int GetTrackNumber(const char *filename)\n{\n\treturn 0;\n\t\n\t// assumes a filename \"Streets of Rage II - Never Return Alive.vgz\"\n\t// will have a playlist \"Streets of Rage II.m3u\"\n\t// returns track number, or 0 for not found\n\tFILE *f;\n\tchar *playlist;\n\tchar *p;\n\tchar *fn;\n\tchar buff[1024]; // buffer for reading lines from file\n\tint number=0;\n\tint linenumber;\n\n\tplaylist=malloc(strlen(filename)+16); // plenty of space in all weird cases\n\n\tif(playlist) {\n\t\tp=strrchr(filename,'\\\\'); // p points to the last \\ in the filename\n\t\tif(p){\n\t\t\t// isolate filename\n\t\t\tfn=malloc(strlen(p));\n\t\t\tif(fn) {\n\t\t\t\tstrcpy(fn,p+1);\n\n\t\t\t\twhile(number==0) {\n\t\t\t\t\tp=strstr(p,\" - \"); // find first \" - \" after current position of p\n\t\t\t\t\tif(p) {\n\t\t\t\t\t\tstrncpy(playlist,filename,p-filename); // copy filename up until the \" - \"\n\t\t\t\t\t\tstrcpy(playlist+(p-filename),\".m3u\"); // terminate it with a \".m3u\\0\"\n\n\t\t\t\t\t\tf=fopen(playlist,\"r\"); // try to open file\n\t\t\t\t\t\tif(f) {\n\t\t\t\t\t\t\tlinenumber=1;\n\t\t\t\t\t\t\t// read through file, a line at a time\n\t\t\t\t\t\t\twhile(fgets(buff,1024,f) && (number==0)) {\t\t// fgets will read in all characters up to and including the line break\n\t\t\t\t\t\t\t\tif(strnicmp(buff,fn,strlen(fn))==0) {\n\t\t\t\t\t\t\t\t\t// found it!\n\t\t\t\t\t\t\t\t\tnumber=linenumber;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif((strlen(buff)>3)&&(buff[0]!='#')) linenumber++; // count lines that are (probably) valid but not #EXTINF lines\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tfclose(f);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tp++; // make it not find this \" - \" next iteration\n\t\t\t\t\t} else break;\n\t\t\t\t}\n\t\t\t\tfree(fn);\n\t\t\t}\n\t\t}\n\t\tfree(playlist);\n\t}\n\treturn number;\n}*/\n\nbool LoadPlayingVGMInfo(const char* FileName)\n{\n\tsize_t FNSize;\n\twchar_t* FileNameW;\n\tbool RetVal;\n\t\n\tif (FileName == NULL)\n\t{\n\t\tRetVal = LoadPlayingVGMInfoW(NULL);\n\t}\n\telse\n\t{\n\t\tFNSize = mbstowcs(NULL, FileName, 0);\n\t\tif (FNSize == -1)\n\t\t\treturn LoadPlayingVGMInfoW(NULL);\n\t\tFNSize ++;\n\t\t\n\t\tFileNameW = (wchar_t*)malloc(FNSize * sizeof(wchar_t));\n\t\tmbstowcs(FileNameW, FileName, FNSize);\n\t\t\n\t\tRetVal = LoadPlayingVGMInfoW(FileNameW);\n\t\t\n\t\tfree(FileNameW);\n\t}\n\t\n\treturn true;\n}\n\nbool LoadPlayingVGMInfoW(const wchar_t* FileName)\n{\n\tbool RetVal;\n\t\n\tif (FileName == NULL && PlayVGMInfo.FileName != NULL)\n\t{\n\t\tPlayVGMInfo.FileName[0x00] = L'\\0';\n\t\treturn true;\n\t}\n\t\n\t// load new file only if neccessary\n\tif (PlayVGMInfo.FileName == NULL || _wcsicmp(PlayVGMInfo.FileName, FileName))\n\t\tRetVal = LoadInfoW(FileName, &PlayVGMInfo);\n\telse\n\t\tRetVal = true;\n\t\n\tif (! PlayVGMInfo.FileSize)\n\t\treturn false;\n\t\n\treturn true;\n}\n\nvoid QueueInfoReload(void)\n{\n\tPlayVGMInfo.ForceReload = true;\n\tVGMInfo.ForceReload = true;\n\t\n\treturn;\n}\n\n\n// GetExtendedFileInfoW worker function\nbool GetExtendedFileInfoW(const wchar_t* FileName, const char* MetaType, wchar_t* RetBuffer,\n\t\t\t\t\t\t  int RetBufLen)\n{\n\t/* Metadata Tag List:\n\t\t\"track\", \"title\", \"artist\", \"album\", \"year\", \"comment\", \"genre\", \"length\",\n\t\t\"type\", \"family\", \"formatinformation\", \"gain\", \"bitrate\", \"vbr\", \"stereo\", ...\n\t*/\n\tint TagIdx;\n\tFINF_DATA* UseInfo;\n\tGD3_TAG* FileTag;\n\t\n\tif (RetBuffer == NULL || ! RetBufLen)\n\t\treturn false;\n\t\n\t// default to a blank string\n\t*RetBuffer = L'\\0';\n\t\n\t// General Meta Tags\n\tif (! stricmp(MetaType, \"type\"))\n\t{\n\t\t// Data Type (Audio/Video/...)\n\t\t_snwprintf(RetBuffer, RetBufLen, L\"%d\", Options.MLFileType);\n\t\treturn true;\n\t}\n\telse if (! stricmp(MetaType, \"family\"))\t// Winamp 5.5+ only\n\t{\n\t\tconst wchar_t* FileExt;\n\t\t\n\t\tFileExt = wcsrchr(FileName, L'.');\n\t\tif (FileExt != NULL)\n\t\t{\n\t\t\tFileExt ++;\n\t\t\tif (! wcsicmp(FileExt, L\"vgm\") || ! wcsicmp(FileExt, L\"vgz\"))\n\t\t\t{\n\t\t\t\twcsncpy(RetBuffer, L\"Video Game Music File\", RetBufLen);\n\t\t\t\treturn true;\n\t\t\t}\t\n\t\t}\n\t\treturn false;\n\t}\n\telse if (! stricmp(MetaType, \"track\"))\n\t{\n\t\treturn false;\n\t\t/*// Track Number\n\t\tint TrackNo;\n\t\t\n\t\tTrackNo = GetTrackNumber(FileName);\n\t\tif (TrackNo)\n\t\t{\n\t\t\t_snwprintf(RetBuffer, RetBufLen, L\"%d\", TrackNo);\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}*/\n\t}\n\t\n\tif (PlayVGMInfo.FileName != NULL && ! _wcsicmp(PlayVGMInfo.FileName, FileName))\n\t{\n\t\tUseInfo = &PlayVGMInfo;\n\t}\n\telse\n\t{\n\t\t// load new file only if neccessary\n\t\tif (VGMInfo.FileName == NULL || _wcsicmp(VGMInfo.FileName, FileName))\n\t\t{\n\t\t\tif (! LoadInfoW(FileName, &VGMInfo))\n\t\t\t\treturn false;\t// Loading failed\n\t\t}\n\t\tUseInfo = &VGMInfo;\n\t}\n\tif (! UseInfo->FileSize)\n\t\treturn false;\n\t\n\tif (! stricmp(MetaType, \"artist\"))\n\t\tTagIdx = METATAG_AUTHOR;\n\telse if (! stricmp(MetaType, \"length\"))\n\t\tTagIdx = METATAG_LENGTH;\n\telse if (! stricmp(MetaType, \"title\"))\n\t\tTagIdx = METATAG_TITLE;\n\telse if (! stricmp(MetaType, \"album\"))\n\t\tTagIdx = METATAG_ALBUM;\t// return Game Name\n\telse if (! stricmp(MetaType, \"comment\"))\n\t\tTagIdx = METATAG_COMMENT;\n\telse if (! stricmp(MetaType, \"year\") || ! stricmp(MetaType, \"date\"))\n\t\tTagIdx = METATAG_YEAR;\n\telse if (! stricmp(MetaType, \"genre\"))\n\t\tTagIdx = METATAG_GENRE;\t// return System (?)\n\telse\n\t{\n\t\tTagIdx = METATAG_UNKNOWN;\n#ifdef _DEBUG\n\t\t{\n\t\t\tchar DebugStr[0x80];\n\t\t\t\n\t\t\t// debug: get metadata types\n\t\t\tsprintf(DebugStr, \"GetExtendedFileInfo: Unknown metadata type: \\\"%s\\\"\\n\", MetaType);\n\t\t\tMessageBox(NULL, DebugStr, \"in_vgm Warning\", MB_ICONEXCLAMATION);\n\t\t}\n#endif\n\t}\n\t\t\n\tswitch(TagIdx)\n\t{\n\tcase METATAG_LENGTH:\n\t\t_snwprintf(RetBuffer, RetBufLen, L\"%d\", UseInfo->TotalLen);\n\t\tbreak;\n\t/*case METATAG_GENRE:\n\t\twcsncpy(RetBuffer, L\"Game\", RetBufLen);\n\t\tbreak;*/\n\tcase METATAG_TITLE:\n\tcase METATAG_ALBUM:\n\tcase METATAG_GENRE:\n\tcase METATAG_AUTHOR:\n\tcase METATAG_YEAR:\n\t//case METATAG_RIPPER:\n\tcase METATAG_COMMENT:\n\t\tFileTag = &UseInfo->Tag;\n\t\t\n\t\tif (TagIdx == METATAG_YEAR)\n\t\t{\n\t\t\twchar_t* lastslash;\n\t\t\t\n\t\t\tif (FileTag->strReleaseDate == NULL || ! wcslen(FileTag->strReleaseDate))\n\t\t\t\treturn false;\n\t\t\t\n\t\t\t// Note: Date formatting is almost unchanged from Maxim's old in_vgm 0.35\n\t\t\t// try to detect various date formats\n\t\t\t// Not yyyy/mm/dd:\n\t\t\t//    nn/nn/yy    n/n/yy    nn/n/yy    n/nn/yy\n\t\t\t//    nn/nn/yyyy  n/n/yyyy  nn/n/yyyy  n/nn/yyyy\n\t\t\t// Should be:\n\t\t\t//    yyyy\n\t\t\t//    yyyy/mm\n\t\t\t//    yyyy/mm/dd\n\t\t\tlastslash = wcsrchr(FileTag->strReleaseDate, L'/');\n\t\t\tif (lastslash != NULL)\n\t\t\t{\n\t\t\t\tlong year = wcstol(lastslash + 1, NULL, 10);\n\t\t\t\tif (year > 31) // looks like a year\n\t\t\t\t{\n\t\t\t\t\tif (year < 100) // 2-digit, yuck\n\t\t\t\t\t{\n\t\t\t\t\t\tyear += 1900;\n\t\t\t\t\t\tif (year < 1960)\n\t\t\t\t\t\t\t// not many sound chips around then, due to lack of transistors\n\t\t\t\t\t\t\tyear += 100;\n\t\t\t\t\t}\n\t\t\t\t\t_snwprintf(RetBuffer, RetBufLen, L\"%d\", year);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (*RetBuffer == L'\\0')\n\t\t\t{\n\t\t\t\t// else, try the first bit\n\t\t\t\twcsncpy(RetBuffer, FileTag->strReleaseDate, 4);\n\t\t\t\tRetBuffer[4] = L'\\0';\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst wchar_t* TagStr;\n\t\t\t\n\t\t\tswitch(TagIdx)\n\t\t\t{\n\t\t\tcase METATAG_TITLE:\n\t\t\t\tTagStr = GetTagStringEngJap(FileTag->strTrackNameE, FileTag->strTrackNameJ,\n\t\t\t\t\t\t\t\t\t\t\tOptions.JapTags);\n\t\t\t\tbreak;\n\t\t\tcase METATAG_ALBUM:\n\t\t\t\tTagStr = GetTagStringEngJap(FileTag->strGameNameE, FileTag->strGameNameJ,\n\t\t\t\t\t\t\t\t\t\t\tOptions.JapTags);\n\t\t\t\tbreak;\n\t\t\tcase METATAG_GENRE:\n\t\t\t\tTagStr = GetTagStringEngJap(FileTag->strSystemNameE, FileTag->strSystemNameJ,\n\t\t\t\t\t\t\t\t\t\t\tOptions.JapTags);\n\t\t\t\tbreak;\n\t\t\tcase METATAG_AUTHOR:\n\t\t\t\tTagStr = GetTagStringEngJap(FileTag->strAuthorNameE, FileTag->strAuthorNameJ,\n\t\t\t\t\t\t\t\t\t\t\tOptions.JapTags);\n\t\t\t\tbreak;\n\t\t\tcase METATAG_COMMENT:\n\t\t\t\tTagStr = FileTag->strNotes;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tTagStr = NULL;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tif (TagStr != NULL)\n\t\t\t\twcsncpy(RetBuffer, TagStr, RetBufLen);\n\t\t\t\n\t\t\tif (TagIdx == METATAG_ALBUM && CheckFM2413Text(&UseInfo->Head))\n\t\t\t\twcscat(RetBuffer, L\" (FM)\");\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t// do nothing\n\t\tbreak;\n\t}\n\t\n\t// empty buffer is a bad result\n\treturn (*RetBuffer != L'\\0') ? true : false;\n}\n\nconst wchar_t* GetTagStringEngJap(const wchar_t* TextEng, const wchar_t* TextJap,\n\t\t\t\t\t\t\t\t\tbool LangMode)\n{\n\tconst wchar_t* Text;\n\t\n\tif (TextEng == NULL || ! wcslen(TextEng))\n\t{\n\t\tText = TextJap;\n\t}\n\telse if (TextJap == NULL || ! wcslen(TextJap))\n\t{\n\t\tText = TextEng;\n\t}\n\telse\n\t{\n\t\tif (! LangMode)\n\t\t\tText = TextEng;\n\t\telse\n\t\t\tText = TextJap;\n\t}\n\t\n\tif (Text == NULL || ! wcslen(Text))\n\t\treturn NULL;\n\telse\n\t\treturn Text;\n}\n\nvoid DisplayTagString(HWND hWndDlg, int DlgItem, const wchar_t* TextEng,\n\t\t\t\t\t  const wchar_t* TextJap, bool LangMode)\n{\n\tconst wchar_t* Text;\n\tBOOL RetVal;\n\t\n\tif (Options.TagFallback)\n\t\tText = GetTagStringEngJap(TextEng, TextJap, LangMode);\n\telse\n\t\tText = LangMode ? TextJap : TextEng;\n\tif (Text == NULL)\n\t{\n\t\tRetVal = SetDlgItemTextA(hWndDlg, DlgItem, \"\");\n\t\treturn;\n\t}\n\t\n\tRetVal = SetDlgItemTextW(hWndDlg, DlgItem, Text);\n\tif (! RetVal)\n\t{\n\t\t// Unicode version failed, try ANSI version\n\t\tchar ANSIStr[0x400];\n\t\t\n\t\twcstombs(ANSIStr, Text, 0x400);\n\t\t/*RetVal = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, Text, -1, ANSIStr, 0x400,\n\t\t\t\t\t\t\t\t\tNULL, NULL);\n\t\tif (! RetVal)\n\t\t\treturn;\t// Unicode -> ANSI failed*/\n\t\tRetVal = SetDlgItemTextA(hWndDlg, DlgItem, ANSIStr);\n\t}\n\t\n\treturn;\n}\n\nBOOL CALLBACK FileInfoDialogProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam)\n{\n\tswitch(wMessage)\n\t{\n\tcase WM_INITDIALOG:\n\t{\n\t\tchar TempStr[0x100];\n\t\t//----------------------------------------------------------------\n\t\t// Initialise dialogue\n\t\t//----------------------------------------------------------------\n\t\t\n\t\t/*int i;\n\t\tchar tempstr[1024];\n\t\t\n\t\tif ( IsURL( FileInfo_Name ) ) {\n\t\t\t// Filename is a URL\n\t\t\tif (\n\t\t\t\tCurrentURLFilename && CurrentURL && (\n\t\t\t\t\t( strcmp( FileInfo_Name, CurrentURLFilename ) == 0) ||\n\t\t\t\t\t( strcmp( FileInfo_Name, CurrentURL\t\t\t\t ) == 0)\n\t\t\t\t)\n\t\t\t)\n\t\t\t{\n\t\t\t\t// If it's the current file, look at the temp file\n\t\t\t\t// but display the URL\n\t\t\t\tSetDlgItemText(hWndDlg, ebFilename, CurrentURL );\n\t\t\t\tFileInfo_Name = CurrentURLFilename;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// If it's not the current file, no info\n\t\t\t\tSetDlgItemText(hWndDlg, ebFilename, FileInfo_Name );\n\t\t\t\tSetDlgItemText(hWndDlg, ebNotes, \"Information unavailable for this URL\" );\n\t\t\t\tDISABLECONTROL(hWndDlg, BrwsrInfoButton );\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t} else {\n\t\t\t// Filename is not a URL\n\t\t\tSetDlgItemText(hWndDlg, ebFilename, FileInfo_Name );\n\t\t}*/\n\t\t\n\t\t// Load File Info\n\t\tif (FileNameToLoadW != NULL)\n\t\t\tLoadInfoW(FileNameToLoadW, &VGMInfo);\n\t\telse\n\t\t\tLoadInfoA(FileNameToLoad, &VGMInfo);\n\t\t\n\t\tSetDlgItemTextW(hWndDlg, VGMFileText, VGMInfo.FileName);\n\t\t\n\t\tif (VGMInfo.FileSize)\n\t\t{\n\t\t\tsprintf(TempStr, \"%X.%02X\", VGMInfo.Head.lngVersion >> 8,\n\t\t\t\t\t\t\t\t\t\tVGMInfo.Head.lngVersion & 0xFF);\n\t\t\tSetDlgItemText(hWndDlg, VGMVerText, TempStr);\n\t\t\t\n\t\t\tsprintf(TempStr, \"%.2f\", VGMInfo.VolGain);\n\t\t\tSetDlgItemText(hWndDlg, VGMGainText, TempStr);\n\t\t\t\n\t\t\tGetChipUsageText(TempStr, &VGMInfo.Head);\n\t\t\tSetDlgItemText(hWndDlg, ChipUseText, TempStr);\n\t\t\t\n\t\t\tsprintf(TempStr, \"%d bytes (%.2f kbps)\", VGMInfo.FileSize, VGMInfo.BitRate / 1000);\n\t\t\tSetDlgItemText(hWndDlg, VGMSizeText, TempStr);\n\t\t\t\n\t\t\tFormatVGMLength(TempStr, &VGMInfo);\n\t\t\tSetDlgItemText(hWndDlg, VGMLenText, TempStr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSetDlgItemText(hWndDlg, VGMVerText, \"\");\n\t\t\tSetDlgItemText(hWndDlg, VGMGainText, \"\");\n\t\t\tSetDlgItemText(hWndDlg, ChipUseText, \"\");\n\t\t\tSetDlgItemText(hWndDlg, VGMSizeText, \"\");\n\t\t\tSetDlgItemText(hWndDlg, VGMLenText, \"\");\n\t\t}\n\t\t\n\t\t// display language independent tags\n\t\tDisplayTagString(hWndDlg, GameDateText, VGMInfo.Tag.strReleaseDate, NULL, false);\n\t\tDisplayTagString(hWndDlg, VGMCrtText, VGMInfo.Tag.strCreator, NULL, false);\n\t\tDisplayTagString(hWndDlg, VGMNotesText, VGMInfo.Tag.strNotes, NULL, false);\n\t\t\n\t\t// trigger English or Japanese for other fields\n\t\tSETCHECKBOX(hWndDlg, LangEngCheck + Options.JapTags, TRUE);\n\t\tPostMessage(hWndDlg, WM_COMMAND, LangEngCheck + Options.JapTags, 0);\n\t\t\n\t\treturn TRUE;\n\t}\n\tcase WM_COMMAND:\n\t\tswitch(LOWORD(wParam))\n\t\t{\n\t\tcase IDOK:\n\t\t\t//Options.JapTags = IsDlgButtonChecked(hWndDlg, LangJapCheck);\n\t\t\t//EndDialog(hWndDlg, 0);\t// return 0 = OK\n\t\t\tEndDialog(hWndDlg, 1);\t// returning 0 can cause bugs with the playlist\n\t\t\treturn TRUE;\n\t\tcase IDCANCEL:\t// [X] button, ESC, Alt + F4\n\t\t\tEndDialog(hWndDlg, 1);\t// return 1 = Cancel, stops further dialogues being opened\n\t\t\treturn TRUE;\n\t\tcase ConfigPluginButton:\n\t\t\tConfig(hWndDlg);\n\t\t\tbreak;\n\t\tcase LangEngCheck:\n\t\tcase LangJapCheck:\n\t\t{\n\t\t\tbool JapMode;\n\t\t\t\n\t\t\tJapMode = (LOWORD(wParam) == LangJapCheck);\n\t\t\tDisplayTagString(hWndDlg, TrkTitleText, VGMInfo.Tag.strTrackNameE,\n\t\t\t\t\t\t\t\t\t\t\t\t\tVGMInfo.Tag.strTrackNameJ, JapMode);\n\t\t\tDisplayTagString(hWndDlg, TrkAuthorText, VGMInfo.Tag.strAuthorNameE,\n\t\t\t\t\t\t\t\t\t\t\t\t\tVGMInfo.Tag.strAuthorNameJ, JapMode);\n\t\t\tDisplayTagString(hWndDlg, GameNameText, VGMInfo.Tag.strGameNameE,\n\t\t\t\t\t\t\t\t\t\t\t\t\tVGMInfo.Tag.strGameNameJ, JapMode);\n\t\t\tDisplayTagString(hWndDlg, GameSysText, VGMInfo.Tag.strSystemNameE,\n\t\t\t\t\t\t\t\t\t\t\t\t\tVGMInfo.Tag.strSystemNameJ, JapMode);\n\t\t\tbreak;\n\t\t}\n\t\tcase BrwsrInfoButton:\n\t\t\t//InfoInBrowser(FileInfo_Name, UseMB, TRUE);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\t\n\treturn FALSE;\t// FALSE to signify message not processed\n}\n\n\n// ------------------------\n// Winamp Export Functions\n// ------------------------\nDllExport int winampGetExtendedFileInfoW(const wchar_t* wfilename, const char* metadata,\n\t\t\t\t\t\t\t\t\t\t wchar_t* ret, int retlen)\n{\n\t// called by Winamp 5.3 and higher\n\tbool RetVal;\n\t\n\tRetVal = GetExtendedFileInfoW(wfilename, metadata, ret, retlen);\n#if 0\n\t{\n\t\twchar_t MsgStr[MAX_PATH * 2];\n\t\tswprintf(MsgStr, L\"file: %s\\nMetadata: %hs\\nResult: %ls\", wfilename, metadata, ret);\n\t\tMessageBoxW(NULL, MsgStr, L\"GetExtFileInfoW\", MB_ICONINFORMATION | MB_OK);\n\t}\n#endif\n\t\n\treturn RetVal;\n}\n\nDllExport int winampGetExtendedFileInfo(const char* filename, const char* metadata,\n\t\t\t\t\t\t\t\t\t\tchar* ret, int retlen)\n{\n\t// called by Winamp versions until 5.24\n\tsize_t FNSize;\n\twchar_t* FileNameW;\n\twchar_t* wRetStr;\n\tbool RetVal;\n\t\n\tFNSize = mbstowcs(NULL, filename, 0);\n\tif (FNSize == -1)\n\t\treturn 0;\n\tFNSize ++;\n\t\n\tFileNameW = (wchar_t*)malloc(FNSize * sizeof(wchar_t));\n\tmbstowcs(FileNameW, filename, FNSize);\n\t\n\twRetStr = (wchar_t*)malloc(retlen * sizeof(wchar_t));\n\t\n\tRetVal = GetExtendedFileInfoW(FileNameW, metadata, wRetStr, retlen);\n\t\n\tif (RetVal)\n\t\t//WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, wret, -1, ret, retlen, NULL, NULL);\n\t\twcstombs(ret, wRetStr, retlen);\n\t\n\tfree(FileNameW);\n\tfree(wRetStr);\n#if 0\n\t{\n\t\tchar MsgStr[MAX_PATH * 2];\n\t\tsprintf(MsgStr, \"file: %s\\nMetadata: %s\\nResult: %s\", filename, metadata, ret);\n\t\tMessageBoxA(NULL, MsgStr, \"GetExtFileInfoA\", MB_ICONINFORMATION | MB_OK);\n\t}\n#endif\n\t\n\treturn RetVal;\n}\n"
  },
  {
    "path": "in_vgm/in_vgm.c",
    "content": "// Winamp VGM input plug-in\n// ------------------------\n// Programmed by Valley Bell, 2011-2017\n//\n// Made using the Example .RAW plug-in by Justin Frankel and\n// small parts (mainly dialogues) of the old in_vgm 0.35 by Maxim.\n\n/*3456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456\n0000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999*/\n\n// #defines used by the Visual C++ project file:\n//\tENABLE_ALL_CORES\n//\tDISABLE_HW_SUPPORT\n//\tUNICODE_INPUT_PLUGIN (Unicode build only)\n\n#include <windows.h>\n#include <stdio.h>\n#include <locale.h>\t// for setlocale\n#include \"Winamp/in2.h\"\n#include \"Winamp/wa_ipc.h\"\n\n#include <zlib.h>\t// for info in About message\n\n#include \"stdbool.h\"\n#include \"chips/mamedef.h\"\t// for (U)INTxx types\n#include \"VGMPlay.h\"\n#include \"VGMPlay_Intf.h\"\n\n#include \"in_vgm.h\"\n#include \"ini_func.h\"\n\n\n#ifndef WM_WA_MPEG_EOF\n// post this to the main window at end of file (after playback as stopped)\n#define WM_WA_MPEG_EOF\tWM_USER+2\n#endif\n\n\n// configuration.\n#define NUM_CHN\t\t2\n#define BIT_PER_SEC\t16\n#define SMPL_BYTES\t(NUM_CHN * (BIT_PER_SEC / 8))\n\n\n// Function Prototypes from dlg_cfg.c\nBOOL CALLBACK ConfigDialogProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam);\nvoid Dialogue_TrackChange(void);\n\n// Function Protorypes from dlg_fileinfo.c\nvoid SetInfoDlgFile(const char* FileName);\nvoid SetInfoDlgFileW(const wchar_t* FileName);\nUINT32 GetVGZFileSize(const char* FileName);\nUINT32 GetVGZFileSizeW(const wchar_t* FileName);\nwchar_t* GetTagStringEngJap(wchar_t* TextEng, wchar_t* TextJap, bool LangMode);\nUINT32 FormatVGMTag(const UINT32 BufLen, in_char* Buffer, GD3_TAG* FileTag, VGM_HEADER* FileHead);\nbool LoadPlayingVGMInfo(const char* FileName);\nbool LoadPlayingVGMInfoW(const wchar_t* FileName);\nBOOL CALLBACK FileInfoDialogProc(HWND hWndDlg, UINT wMessage, WPARAM wParam, LPARAM lParam);\n\n\n// Function Prototypes\nBOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved);\nvoid Config(HWND hWndParent);\nvoid About(HWND hWndParent);\nvoid Init(void);\nvoid FindIniFile(void);\nvoid LoadConfigurationFile(void);\nstatic void ReadIntoBitfield2(const char* Section, const char* Key, UINT16* Value,\n\t\t\t\t\t\t\t  UINT8 BitStart, UINT8 BitCount);\nvoid SaveConfigurationFile(void);\nstatic void WriteFromBitfield(const char* Section, const char* Key, UINT32 Value,\n\t\t\t\t\t\t\t  UINT8 BitStart, UINT8 BitCount);\nvoid Deinit(void);\nint IsOurFile(const in_char* fn);\n\nINLINE UINT32 MulDivRound(UINT64 Number, UINT64 Numerator, UINT64 Denominator);\nint Play(const in_char* FileName);\nvoid Pause(void);\nvoid Unpause(void);\nint IsPaused(void);\nvoid Stop(void);\n\nint GetFileLength(VGM_HEADER* FileHead);\nint GetLength(void);\n\nint GetOutputTime(void);\nvoid SetOutputTime(int time_in_ms);\nvoid SetVolume(int volume);\nvoid SetPan(int pan);\nvoid UpdatePlayback(void);\n\nint InfoDialog(const in_char* FileName, HWND hWnd);\nconst in_char* GetFileNameTitle(const in_char* FileName);\nvoid GetFileInfo(const in_char* filename, in_char* title, int* length_in_ms);\nvoid EQ_Set(int on, char data[10], int preamp);\n\nDWORD WINAPI DecodeThread(LPVOID b);\n\n\n#define PATH_SIZE\t(MAX_PATH * 2)\n\n// the output module\nstatic In_Module WmpMod;\n\n// currently playing file (used for getting info on the current file)\nstatic in_char CurFileName[PATH_SIZE];\n\nstatic int decode_pos;\t\t\t\t// current decoding position (depends on SampleRate)\nstatic int decode_pos_ms;\t\t\t// Used for correcting DSP plug-in pitch changes\nstatic volatile int seek_needed;\t// if != -1, it is the point that the decode \n\t\t\t\t\t\t\t\t\t// thread should seek to, in ms.\n\nstatic volatile bool killDecodeThread = 0;\t\t\t// the kill switch for the decode thread\nstatic HANDLE thread_handle = INVALID_HANDLE_VALUE;\t// the handle to the decode thread\nstatic volatile bool InStopFunc;\n\nchar IniFilePath[PATH_SIZE + 0x10];\t// 16 extra characters for \"in_vgm.ini\"\nPLGIN_OPTS Options;\n\n\n\nextern UINT32 SampleRate;\nextern UINT32 VGMMaxLoop;\nextern UINT32 VGMPbRate;\n\nextern UINT32 FadeTime;\nextern UINT32 PauseTime;\n\nextern float VolumeLevel;\nextern bool SurroundSound;\nextern UINT8 HardStopOldVGMs;\n//extern bool FadeRAWLog;\n\nextern bool DoubleSSGVol;\n\nextern UINT8 ResampleMode;\t// 00 - HQ both, 01 - LQ downsampling, 02 - LQ both\nextern UINT8 CHIP_SAMPLING_MODE;\nextern INT32 CHIP_SAMPLE_RATE;\n\nextern CHIPS_OPTION ChipOpts[0x02];\n\nextern char* AppPaths[8];\nstatic char AppPathBuffer[PATH_SIZE];\n\nextern VGM_HEADER VGMHead;\nextern GD3_TAG VGMTag;\n\nextern UINT32 VGMMaxLoopM;\nextern bool VGMEnd;\nextern bool PausePlay;\nextern bool EndPlay;\n\n\n\nHANDLE hPluginInst;\n\n\n// avoid CRT. Evil. Big. Bloated. Only uncomment this code if you are using \n// 'ignore default libraries' in VC++. Keeps DLL size way down.\n// /*\nBOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)\n{\n\thPluginInst = hInst;\t// save for InitConfigDialog\n\t\n\treturn TRUE;\n}\n// */\n\nvoid Config(HWND hWndParent)\n{\n\t// if we had a configuration box we'd want to write it here (using DialogBox, etc)\n\tDialogBox(WmpMod.hDllInstance, (LPTSTR)DlgConfigMain, hWndParent, &ConfigDialogProc);\n\t\n\treturn;\n}\n\nvoid About(HWND hWndParent)\n{\n\tconst char* MsgStr =\n\t\tINVGM_TITLE\n#ifdef UNICODE_INPUT_PLUGIN\n\t\t\" (Unicode build)\"\n#endif\n\t\t\"\\n\"\n\t\t\"by Valley Bell 2011-2016\\n\"\n\t\t\"\\n\"\n\t\t\"Build date: \" __DATE__ \" (\" INVGM_VERSION \")\\n\"\n\t\t\"\\n\"\n\t\t\"http://vgmrips.net/\\n\"\n\t\t\"\\n\"\n\t\t\"Current status:\\n\"\n\t\t\"VGM file support up to version \" VGM_VER_STR \"\\n\"\n\t\t\"Currently %u chips are emulated:\\n\"\t// CHIP_COUNT\n\t\t\"%s\\n\"\t// ChipList\n\t\t\"\\n\"\n\t\t\"Don\\'t be put off by the pre-1.0 version numbers.\\n\"\n\t\t\"This is a non-commercial project and as such it is permanently in beta.\\n\"\n\t\t\"\\n\"\n\t\t\"Using:\\n\"\n\t\t\"ZLib \" ZLIB_VERSION \" (http://www.zlib.org)\\n\"\n\t\t//\"LZMA SDK 4.40 (http://www.7-zip.org)\\n\"\t\t// currently unused\n\t\t\"\\n\"\n\t\t\"Thanks also go to:\\n\"\n\t\t\"Maxim for the first version of in_vgm, one SN76489 and\\n\"\n\t\t\"YM2413 core and some dialogues\\n\"\n\t\t\"MAME team for most sound cores\\n\"\n\t\t\"openMSX team for the YMF278B core\\n\"\n\t\t\"GerbilSoft for the RF5C164 and PWM cores from Gens/GS\\n\"\n\t\t\"DOSBox Team for AdLibEmu (OPL2/3 sound core)\\n\"\n\t\t\"The author of Ootake for the HuC6280 core\\n\"\n\t\t\"rainwarrior for NSFPlay and the EMU2149 and NES cores\\n\"\n\t\t\"superctr for the new C352 core\";\n\tchar* ChipList;\n\tconst char* ChipStr;\n\tchar* FinalMsg;\n\tchar* TempPnt;\n\tUINT8 CurChip;\n\t\n\t// generate Chip list\n\tChipList = (char*)malloc(CHIP_COUNT * 12);\n\tTempPnt = ChipList;\n\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++)\n\t{\n\t\tif (CurChip && ! (CurChip % 6))\n\t\t{\n\t\t\t// replace space with new-line every 6 chips\n\t\t\t*(TempPnt - 1) = '\\n';\n\t\t}\n\t\t\n\t\tChipStr = GetAccurateChipName(CurChip, 0xFF);\n\t\tstrcpy(TempPnt, ChipStr);\n\t\tTempPnt += strlen(TempPnt);\n\t\tstrcpy(TempPnt, \", \");\n\t\tTempPnt += 2;\n\t}\n\tTempPnt -= 2;\n\t*TempPnt = '\\0';\n\t\n\tFinalMsg = (char*)malloc(strlen(MsgStr) + 0x10 + strlen(ChipList));\n\tsprintf(FinalMsg, MsgStr, CHIP_COUNT, ChipList);\n\tfree(ChipList);\n\t\n\tMessageBox(hWndParent, FinalMsg, WmpMod.description, MB_ICONINFORMATION | MB_OK);\n\t\n\tfree(FinalMsg);\n\t\n\treturn;\n}\n\nvoid Init(void)\n{\n\tchar* FileTitle;\n\t\n\tsetlocale(LC_CTYPE, \"\");\n\t\n\t// any one-time initialization goes here (configuration reading, etc)\n\tVGMPlay_Init();\t// General Init\n\t\n\tGetModuleFileName(hPluginInst, AppPathBuffer, PATH_SIZE);\t// get path of in_vgm.dll\n\tGetFullPathName(AppPathBuffer, PATH_SIZE, AppPathBuffer, &FileTitle);  // find file title\n\t*FileTitle = '\\0';\n\t\n\t// Path 1: dll's directory\n\tAppPaths[0x00] = AppPathBuffer;\n\t// Path 2: working directory (\"\\0\")\n\tAppPaths[0x01] = AppPathBuffer + strlen(AppPathBuffer);\n\t\n\tLoadConfigurationFile();\n\t\n\tVGMPlay_Init2();\t// Post-Config-Load Init\n\t\n\treturn;\n}\n\nvoid FindIniFile(void)\n{\n\tconst char* WAIniDir;\n\t\n\t// get directory for Winamp INI files\n\tWAIniDir = (char *)SendMessage(WmpMod.hMainWindow, WM_WA_IPC, 0, IPC_GETINIDIRECTORY);\n\tif (WAIniDir == NULL)\n\t{\n\t\t// old Winamp\n\t\tstrcpy(IniFilePath, AppPathBuffer);\n\t}\n\telse\n\t{\n\t\t// Winamp 5.11+ (with user profiles)\n\t\tstrcpy(IniFilePath, WAIniDir);\n\t\tstrcat(IniFilePath,\"\\\\Plugins\");\n\t\t\n\t\t// make sure folder exists\n\t\tCreateDirectory(IniFilePath, NULL);\n\t\tstrcat(IniFilePath, \"\\\\\");\n\t}\n\tstrcat(IniFilePath, \"in_vgm.ini\");\n\t\n\treturn;\n}\n\nvoid LoadConfigurationFile(void)\n{\n\tUINT8 CurCSet;\n\tUINT8 CurChip;\n\tUINT8 CurChn;\n\tCHIP_OPTS* TempCOpt;\n\tchar TempStr[0x20];\n\tconst char* ChipName;\n\t\n\t// -- set default values --\n\t// VGMPlay_Init() already sets most default values\n\tOptions.ImmediateUpdate = false;\n\tOptions.NoInfoCache = false;\n\t\n\tOptions.SampleRate = 44100;\n\tOptions.PauseNL = PauseTime;\n\tOptions.PauseLp = PauseTime;\n\t\n\tstrcpy(Options.TitleFormat, \"%t (%g) - %a\");\n\tOptions.JapTags = false;\n\tOptions.AppendFM2413 = false;\n\tOptions.TrimWhitespc = true;\n\tOptions.StdSeparators = true;\n\tOptions.TagFallback = false;\n\tOptions.MLFileType = 0;\n\t\n\tOptions.Enable7z = false;\n\t\n\tOptions.ResetMuting = true;\n\tDoubleSSGVol = true;\n\t\n\tFindIniFile();\n\t\n\t// Read actual options\n\tReadIni_Boolean (\"General\",\t\t\"ImmdtUpdate\",\t&Options.ImmediateUpdate);\n\tReadIni_Boolean (\"General\",\t\t\"NoInfoCache\",\t&Options.NoInfoCache);\n\t\n\tReadIni_Integer\t(\"Playback\",\t\"SampleRate\",\t&Options.SampleRate);\n\tReadIni_Integer\t(\"Playback\",\t\"FadeTime\",\t\t&FadeTime);\n\tReadIni_Integer\t(\"Playback\",\t\"PauseNoLoop\",\t&Options.PauseNL);\n\tReadIni_Integer\t(\"Playback\",\t\"PauseLoop\",\t&Options.PauseLp);\n\tReadIni_IntByte\t(\"Playback\",\t\"HardStopOld\",\t&HardStopOldVGMs);\n\tReadIni_Float\t(\"Playback\",\t\"Volume\",\t\t&VolumeLevel);\n\tReadIni_Integer\t(\"Playback\",\t\"MaxLoops\",\t\t&VGMMaxLoop);\n\tReadIni_Integer\t(\"Playback\",\t\"PlaybackRate\",\t&VGMPbRate);\n\tReadIni_Boolean\t(\"Playback\",\t\"DoubleSSGVol\",\t&DoubleSSGVol);\n\tReadIni_IntByte\t(\"Playback\",\t\"ResamplMode\",\t&ResampleMode);\n\tReadIni_Integer\t(\"Playback\",\t\"ChipSmplRate\",\t&Options.ChipRate);\n\tReadIni_IntByte\t(\"Playback\",\t\"ChipSmplMode\",\t&CHIP_SAMPLING_MODE);\n\tReadIni_Boolean\t(\"Playback\",\t\"SurroundSnd\",\t&SurroundSound);\n\t\n\tReadIni_String\t(\"Tags\",\t\t\"TitleFormat\",\t Options.TitleFormat, 0x80);\n\tReadIni_Boolean\t(\"Tags\",\t\t\"UseJapTags\",\t&Options.JapTags);\n\tReadIni_Boolean\t(\"Tags\",\t\t\"AppendFM2413\",\t&Options.AppendFM2413);\n\tReadIni_Boolean\t(\"Tags\",\t\t\"TrimWhitespc\",\t&Options.TrimWhitespc);\n\tReadIni_Boolean\t(\"Tags\",\t\t\"SeparatorStd\",\t&Options.StdSeparators);\n\tReadIni_Boolean\t(\"Tags\",\t\t\"TagFallback\",\t&Options.TagFallback);\n\tReadIni_Integer\t(\"Tags\",\t\t\"MLFileType\",\t&Options.MLFileType);\n\t\n\t//ReadIni_Boolean\t(\"Vgm7z\",\t\t\"Enable\",\t\t&Options.Enable7z);\n\t\n\tReadIni_Boolean (\"Muting\",\t\t\"Reset\",\t\t&Options.ResetMuting);\n\t\n\tTempCOpt = (CHIP_OPTS*)&ChipOpts[0x00];\n\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, TempCOpt ++)\n\t{\n\t\tReadIni_IntByte(\"EmuCore\",\tGetChipName(CurChip),\t&TempCOpt->EmuCore);\n\t}\n\t\n\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t{\n\t\tTempCOpt = (CHIP_OPTS*)&ChipOpts[CurCSet];\n\t\t\n\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, TempCOpt ++)\n\t\t{\n\t\t\tChipName = GetChipName(CurChip);\n\t\t\t\n\t\t\tsprintf(TempStr, \"%s #%u All\", ChipName, CurCSet);\n\t\t\tReadIni_Boolean(\"Muting\",\tTempStr,\t&TempCOpt->Disabled);\n\t\t\t\n\t\t\tsprintf(TempStr, \"%s #%u\", ChipName, CurCSet);\n\t\t\tReadIni_Integer(\"Muting\",\tTempStr,\t&TempCOpt->ChnMute1);\n\t\t\tsprintf(TempStr, \"%s #%u_%u\", ChipName, CurCSet, 2);\n\t\t\tReadIni_Integer(\"Muting\",\tTempStr,\t&TempCOpt->ChnMute2);\n\t\t\tsprintf(TempStr, \"%s #%u_%u\", ChipName, CurCSet, 3);\n\t\t\tReadIni_Integer(\"Muting\",\tTempStr,\t&TempCOpt->ChnMute3);\n\t\t\t\n\t\t\tfor (CurChn = 0x00; CurChn < TempCOpt->ChnCnt; CurChn ++)\n\t\t\t{\n\t\t\t\tif (TempCOpt->ChnCnt > 10)\n\t\t\t\t\tsprintf(TempStr, \"%s #%u %02u\", ChipName, CurCSet, CurChn);\n\t\t\t\telse\n\t\t\t\t\tsprintf(TempStr, \"%s #%u %u\", ChipName, CurCSet, CurChn);\n\t\t\t\tReadIni_SIntSht(\"Panning\",\tTempStr,\t&TempCOpt->Panning[CurChn]);\n\t\t\t}\n\t\t\t\n\t\t}\n\t}\n\t\n\t// Additional options\n\t// YM2612\n\tChipName = GetChipName(0x02);\tTempCOpt = &ChipOpts[0x00].YM2612;\n\tsprintf(TempStr, \"%s Gens DACHighpass\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 0, 1);\n\t\n\tsprintf(TempStr, \"%s Gens SSG-EG\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 1, 1);\n\t\n\tsprintf(TempStr, \"%s PseudoStereo\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 2, 1);\n\t\n\tsprintf(TempStr, \"%s NukedType\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 3, 2);\n\t\n\t// YM2203\n\tChipName = GetChipName(0x06);\tTempCOpt = &ChipOpts[0x00].YM2203;\n\tsprintf(TempStr, \"%s Disable AY\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 0, 1);\n\t\n\t// YM2608\n\tChipName = GetChipName(0x07);\tTempCOpt = &ChipOpts[0x00].YM2608;\n\tsprintf(TempStr, \"%s Disable AY\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 0, 1);\n\t\n\t// YM2610\n\tChipName = GetChipName(0x08);\tTempCOpt = &ChipOpts[0x00].YM2610;\n\tsprintf(TempStr, \"%s Disable AY\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 0, 1);\n\t\n\t// GameBoy\n\tChipName = GetChipName(0x13);\tTempCOpt = &ChipOpts[0x00].GameBoy;\n\tsprintf(TempStr, \"%s Boost WaveCh\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 0, 1);\n\t\n\t// NES\n\tChipName = GetChipName(0x14);\tTempCOpt = &ChipOpts[0x00].NES;\n\tTempCOpt->SpecialFlags &= 0x7FFF;\n\tsprintf(TempStr, \"%s Shared Opts\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 0, 2);\n\t\n\tsprintf(TempStr, \"%s APU Opts\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 2, 2);\n\t\n\tsprintf(TempStr, \"%s DMC Opts\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 4, 8);\n\t\n\tsprintf(TempStr, \"%s FDS Opts\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 12, 1);\n\t\n\t// OKIM6258\n\tChipName = GetChipName(0x17);\tTempCOpt = &ChipOpts[0x00].OKIM6258;\n\tsprintf(TempStr, \"%s Internal 10bit\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 0, 1);\n\t\n\t// SCSP\n\tChipName = GetChipName(0x20);\tTempCOpt = &ChipOpts[0x00].SCSP;\n\tsprintf(TempStr, \"%s Bypass DSP\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 0, 1);\n\t\n\t// C352\n\tChipName = GetChipName(0x27);\tTempCOpt = &ChipOpts[0x00].C352;\n\tsprintf(TempStr, \"%s Disable Rear\", ChipName);\n\tReadIntoBitfield2(\"ChipOpts\", TempStr, &TempCOpt->SpecialFlags, 0, 1);\n\t\n\treturn;\n}\n\nstatic void ReadIntoBitfield2(const char* Section, const char* Key, UINT16* Value,\n\t\t\t\t\t\t\t  UINT8 BitStart, UINT8 BitCount)\n{\n\t// Bitfield Read routine (2-byte/16-bit data)\n\tUINT16 BitMask;\n\tUINT16 NewBits;\n\t\n\tif (! BitCount)\n\t\treturn;\n\t\n\tBitMask = (1 << BitCount) - 1;\n\t\n\tNewBits = (*Value >> BitStart) & BitMask;\t// read old bits, making them the default data\n\tReadIni_SIntSht(Section, Key, &NewBits);\t// read .ini\n\t\n\t*Value &= ~(BitMask << BitStart);\t\t\t// clear bit range\n\t*Value |= (NewBits & BitMask) << BitStart;\t// add new bits in\n\t\n\treturn;\n}\n\nvoid SaveConfigurationFile(void)\n{\n\tUINT8 CurCSet;\n\tUINT8 CurChip;\n\tUINT8 CurChn;\n\tCHIP_OPTS* TempCOpt;\n\tchar TempStr[0x20];\n\tconst char* ChipName;\n\t\n\tWriteIni_Boolean(\"General\",\t\t\"ImmdtUpdate\",\tOptions.ImmediateUpdate);\n\tWriteIni_Boolean(\"General\",\t\t\"NoInfoCache\",\tOptions.NoInfoCache);\n\t\n\tWriteIni_Integer(\"Playback\",\t\"SampleRate\",\tOptions.SampleRate);\n\tWriteIni_Integer(\"Playback\",\t\"FadeTime\",\t\tFadeTime);\n\tWriteIni_Integer(\"Playback\",\t\"PauseNoLoop\",\tOptions.PauseNL);\n\tWriteIni_Integer(\"Playback\",\t\"PauseLoop\",\tOptions.PauseLp);\n\tWriteIni_Integer(\"Playback\",\t\"HardStopOld\",\tHardStopOldVGMs);\n\tWriteIni_Float\t(\"Playback\",\t\"Volume\",\t\tVolumeLevel);\n\tWriteIni_Integer(\"Playback\",\t\"MaxLoops\",\t\tVGMMaxLoop);\n\tWriteIni_Integer(\"Playback\",\t\"PlaybackRate\",\tVGMPbRate);\n\tWriteIni_Boolean(\"Playback\",\t\"DoubleSSGVol\",\tDoubleSSGVol);\n\tWriteIni_Integer(\"Playback\",\t\"ResamplMode\",\tResampleMode);\n\tWriteIni_Integer(\"Playback\",\t\"ChipSmplRate\",\tOptions.ChipRate);\n\tWriteIni_Integer(\"Playback\",\t\"ChipSmplMode\",\tCHIP_SAMPLING_MODE);\n\tWriteIni_Boolean(\"Playback\",\t\"SurroundSnd\",\tSurroundSound);\n\t\n\tWriteIni_String\t(\"Tags\",\t\t\"TitleFormat\",\tOptions.TitleFormat);\n\tWriteIni_Boolean(\"Tags\",\t\t\"UseJapTags\",\tOptions.JapTags);\n\tWriteIni_Boolean(\"Tags\",\t\t\"AppendFM2413\",\tOptions.AppendFM2413);\n\tWriteIni_Boolean(\"Tags\",\t\t\"TrimWhitespc\",\tOptions.TrimWhitespc);\n\tWriteIni_Boolean(\"Tags\",\t\t\"SeparatorStd\",\tOptions.StdSeparators);\n\tWriteIni_Boolean(\"Tags\",\t\t\"TagFallback\",\tOptions.TagFallback);\n\tWriteIni_XInteger(\"Tags\",\t\t\"MLFileType\",\tOptions.MLFileType);\n\t\n\t//WriteIni_Boolean(\"Vgm7z\",\t\t\"Enable\",\t\tOptions.Enable7z);\n\t\n\tTempCOpt = (CHIP_OPTS*)&ChipOpts[0x00];\n\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, TempCOpt ++)\n\t{\n\t\tChipName = GetChipName(CurChip);\n\t\tWriteIni_Integer(\"EmuCore\",\tChipName,\t\tTempCOpt->EmuCore);\n\t}\n\t\t\t\n\tWriteIni_Boolean(\"Muting\",\t\t\"Reset\",\t\tOptions.ResetMuting);\n\t\n\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t{\n\t\tTempCOpt = (CHIP_OPTS*)&ChipOpts[CurCSet];\n\t\t\n\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, TempCOpt ++)\n\t\t{\n\t\t\tChipName = GetChipName(CurChip);\n\t\t\tsprintf(TempStr, \"%s #%u All\", ChipName, CurCSet, 1);\n\t\t\tWriteIni_Boolean(\"Muting\",\tTempStr,\tTempCOpt->Disabled);\n\t\t\t\n\t\t\tsprintf(TempStr, \"%s #%u\", ChipName, CurCSet, 1);\n\t\t\tWriteIni_XInteger(\"Muting\",\tTempStr,\tTempCOpt->ChnMute1);\n\t\t\tif (CurChip == 0x07 || CurChip == 0x08 || CurChip == 0x0D)\n\t\t\t{\n\t\t\t\t// YM2608 (ADPCM), YM2610 (ADPCM), YMF278B (WaveTable)\n\t\t\t\tsprintf(TempStr, \"%s #%u_%u\", ChipName, CurCSet, 2);\n\t\t\t\tWriteIni_XInteger(\"Muting\",\tTempStr,\tTempCOpt->ChnMute2);\n\t\t\t}\n\t\t\tif (CurChip == 0x06 || CurChip == 0x07 || CurChip == 0x08)\n\t\t\t{\n\t\t\t\t// YM2203, YM2608, YM2610 (all AY8910)\n\t\t\t\tsprintf(TempStr, \"%s #%u_%u\", ChipName, CurCSet, 3);\n\t\t\t\tWriteIni_XInteger(\"Muting\",\tTempStr,\tTempCOpt->ChnMute3);\n\t\t\t}\n\t\t\t\n\t\t\tfor (CurChn = 0x00; CurChn < TempCOpt->ChnCnt; CurChn ++)\n\t\t\t{\n\t\t\t\tif (TempCOpt->ChnCnt > 10)\n\t\t\t\t\tsprintf(TempStr, \"%s #%u %02u\", ChipName, CurCSet, CurChn);\n\t\t\t\telse\n\t\t\t\t\tsprintf(TempStr, \"%s #%u %u\", ChipName, CurCSet, CurChn);\n\t\t\t\tWriteIni_SInteger(\"Panning\",\tTempStr,\tTempCOpt->Panning[CurChn]);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t// Additional options\n\t// YM2612\n\tChipName = GetChipName(0x02);\tTempCOpt = &ChipOpts[0x00].YM2612;\n\tsprintf(TempStr, \"%s Gens DACHighpass\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 0, 1);\n\t\n\tsprintf(TempStr, \"%s Gens SSG-EG\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 1, 1);\n\t\n\tsprintf(TempStr, \"%s PseudoStereo\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 2, 1);\n\t\n\tsprintf(TempStr, \"%s NukedType\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 3, 2);\n\t\n\t// YM2203\n\tChipName = GetChipName(0x06);\tTempCOpt = &ChipOpts[0x00].YM2203;\n\tsprintf(TempStr, \"%s Disable AY\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 0, 1);\n\t\n\t// YM2608\n\tChipName = GetChipName(0x07);\tTempCOpt = &ChipOpts[0x00].YM2608;\n\tsprintf(TempStr, \"%s Disable AY\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 0, 1);\n\t\n\t// YM2610\n\tChipName = GetChipName(0x08);\tTempCOpt = &ChipOpts[0x00].YM2610;\n\tsprintf(TempStr, \"%s Disable AY\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 0, 1);\n\t\n\t// GameBoy\n\tChipName = GetChipName(0x13);\tTempCOpt = &ChipOpts[0x00].GameBoy;\n\tsprintf(TempStr, \"%s Boost WaveCh\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 0, 1);\n\t\n\t// NES\n\tChipName = GetChipName(0x14);\tTempCOpt = &ChipOpts[0x00].NES;\n\tsprintf(TempStr, \"%s Shared Opts\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 0, 2);\n\t\n\tsprintf(TempStr, \"%s APU Opts\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 2, 2);\n\t\n\tsprintf(TempStr, \"%s DMC Opts\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 4, 8);\n\t\n\tsprintf(TempStr, \"%s FDS Opts\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 12, 1);\n\t\n\t// OKIM6258\n\tChipName = GetChipName(0x17);\tTempCOpt = &ChipOpts[0x00].OKIM6258;\n\tsprintf(TempStr, \"%s Internal 10bit\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 0, 1);\n\t\n\t// SCSP\n\tChipName = GetChipName(0x20);\tTempCOpt = &ChipOpts[0x00].SCSP;\n\tsprintf(TempStr, \"%s Bypass DSP\", ChipName);\n\t//TempCOpt->SpecialFlags |= 0x01;\t// force SCSP DSP bypass upon next loading\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 0, 1);\n\t\n\t// C352\n\tChipName = GetChipName(0x27);\tTempCOpt = &ChipOpts[0x00].C352;\n\tsprintf(TempStr, \"%s Disable Rear\", ChipName);\n\tWriteFromBitfield(\"ChipOpts\", TempStr, TempCOpt->SpecialFlags, 0, 1);\n\t\n\treturn;\n}\n\nstatic void WriteFromBitfield(const char* Section, const char* Key, UINT32 Value,\n\t\t\t\t\t\t\t  UINT8 BitStart, UINT8 BitCount)\n{\n\tUINT32 BitMask;\n\tUINT32 WrtBits;\n\t\n\tif (! BitCount)\n\t\treturn;\n\t\n\tBitMask = (1 << BitCount) - 1;\n\t\n\tWrtBits = Value >> BitStart;\n\tWrtBits &= BitMask;\n\tWriteIni_XInteger(Section, Key, WrtBits);\n\t\n\treturn;\n}\n\nvoid Deinit(void)\n{\n\t// one-time deinit, such as memory freeing\n\tSaveConfigurationFile();\n\t\n\tVGMPlay_Deinit();\n\t\n\treturn;\n}\n\nint IsOurFile(const in_char* fn)\n{\n\t// used for detecting URL streams - currently unused.\n\t// return ! strncmp(fn,\"http://\",7); to detect HTTP streams, etc\n\treturn 0;\n} \n\n\nINLINE UINT32 MulDivRound(UINT64 Number, UINT64 Numerator, UINT64 Denominator)\n{\n\treturn (UINT32)((Number * Numerator + Denominator / 2) / Denominator);\n}\n\n// called when winamp wants to play a file\nint Play(const in_char* FileName)\n{\n\tUINT32 TempLng;\n\tint maxlatency;\n\tint thread_id;\n\t\n\tPausePlay = false;\n\tdecode_pos = 0;\n\tdecode_pos_ms = 0;\n\tseek_needed = -1;\n\tSampleRate = Options.SampleRate;\n\tCHIP_SAMPLE_RATE = Options.ChipRate ? Options.ChipRate : Options.SampleRate;\n\t\n\t// return -1 - jump to next file in playlist\n\t// return +1 - stop the playlist\n#ifndef UNICODE_INPUT_PLUGIN\n\tif (! OpenVGMFile(FileName))\n\t{\n\t\tif (GetGZFileLength(FileName) == 0xFFFFFFFF)\n\t\t\treturn -1;\t// file not found\n\t\telse\n\t\t\treturn +1;\t// file invalid\n\t}\n\t\n\tLoadPlayingVGMInfo(FileName);\n\tstrcpy(CurFileName, FileName);\n#else\n\tif (! OpenVGMFileW(FileName))\n\t{\n\t\tif (GetGZFileLengthW(FileName) == 0xFFFFFFFF)\n\t\t\treturn -1;\t// file not found\n\t\telse\n\t\t\treturn +1;\t// file invalid\n\t}\n\t\n\tLoadPlayingVGMInfoW(FileName);\n\twcscpy(CurFileName, FileName);\n#endif\n\t\n\t// -1 and -1 are to specify buffer and prebuffer lengths.\n\t// -1 means to use the default, which all input plug-ins should really do.\n\tmaxlatency = WmpMod.outMod->Open(SampleRate, NUM_CHN, BIT_PER_SEC, -1, -1);\n\tif (maxlatency < 0) // error opening device\n\t\treturn +1;\n\t\n\tif (! VGMHead.lngLoopOffset)\n\t\tPauseTime = Options.PauseNL;\n\telse\n\t\tPauseTime = Options.PauseLp;\n\t\n\tPlayVGM();\n\t\n#ifndef UNICODE_INPUT_PLUGIN\n\tTempLng = GetVGZFileSize(FileName);\n#else\n\tTempLng = GetVGZFileSizeW(FileName);\n#endif\n\tif (! TempLng)\n\t{\n\t\tif (VGMHead.lngGD3Offset)\n\t\t\tTempLng = VGMHead.lngGD3Offset - VGMHead.lngDataOffset;\n\t\telse\n\t\t\tTempLng = VGMHead.lngEOFOffset - VGMHead.lngDataOffset;\n\t}\n\t// Bit/Sec = (TrackBytes * 8) / TrackTime\n\t// kbps = Bytes * (8 * SampleRate) / (Samples * 1000)\n\tif (VGMHead.lngTotalSamples)\n\t\tTempLng = MulDivRound(TempLng, CalcSampleMSec(8000, 0x03),\n\t\t\t\t\t\t\t\t(UINT64)VGMHead.lngTotalSamples * 1000);\n\telse\n\t\tTempLng = 0;\n\tWmpMod.SetInfo(TempLng, (SampleRate + 500) / 1000, NUM_CHN, 1);\n\t\n\t// initialize visualization stuff\n\tWmpMod.SAVSAInit(maxlatency, SampleRate);\n\tWmpMod.VSASetInfo(SampleRate, NUM_CHN);\n\t\n\t// set the output plug-ins default volume.\n\t// volume is 0-255, -666 is a token for current volume.\n\tWmpMod.outMod->SetVolume(-666); \n\t\n\t// launch decode thread\n\tkillDecodeThread = 0;\n\tthread_handle = CreateThread(NULL, 0, &DecodeThread, NULL, 0, &thread_id);\n\t\n\tDialogue_TrackChange();\n\t\n\treturn 0; \n}\n\n// standard pause implementation\nvoid Pause(void)\n{\n\tPauseVGM(true);\n\tWmpMod.outMod->Pause(PausePlay);\n\t\n\treturn;\n}\n\nvoid Unpause(void)\n{\n\tPauseVGM(false);\n\tWmpMod.outMod->Pause(PausePlay);\n\t\n\treturn;\n}\n\nint IsPaused(void)\n{\n\treturn PausePlay;\n}\n\n// stop playing.\nvoid Stop(void)\n{\n\tif (InStopFunc)\n\t\treturn;\n\t\n\tInStopFunc = true;\n\t// TODO: add Mutex for this block.\n\t//\tStupid XMPlay seems to call Stop() twice in 2 seperate threads.\n\tif (thread_handle != INVALID_HANDLE_VALUE)\n\t{\n\t\tkillDecodeThread = 1;\n\t\tif (WaitForSingleObject(thread_handle, 10000) == WAIT_TIMEOUT)\n\t\t{\n\t\t\tMessageBox(WmpMod.hMainWindow, \"Error asking thread to die!\\n\",\n\t\t\t\t\t\t\"Error killing decode thread\", 0);\n\t\t\tTerminateThread(thread_handle,0);\n\t\t}\n\t\tCloseHandle(thread_handle);\n\t\tthread_handle = INVALID_HANDLE_VALUE;\n\t}\n\t\n\t// close output system\n\tWmpMod.outMod->Close();\n\t\n\t// deinitialize visualization\n\tWmpMod.SAVSADeInit();\n\t\n\tStopVGM();\n\t\n\tif (Options.ResetMuting)\n\t{\n\t\tUINT8 CurChip;\n\t\tUINT8 CurCSet;\n\t\tCHIP_OPTS* TempCOpt;\n\t\t\n\t\tfor (CurCSet = 0x00; CurCSet < 0x02; CurCSet ++)\n\t\t{\n\t\t\tTempCOpt = (CHIP_OPTS*)&ChipOpts[CurCSet];\n\t\t\tfor (CurChip = 0x00; CurChip < CHIP_COUNT; CurChip ++, TempCOpt ++)\n\t\t\t{\n\t\t\t\tTempCOpt->Disabled = false;\n\t\t\t\tTempCOpt->ChnMute1 = 0x00;\n\t\t\t\tTempCOpt->ChnMute2 = 0x00;\n\t\t\t\tTempCOpt->ChnMute3 = 0x00;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// that would just make the check boxes flash during track change\n\t\t// and Winamp's main window is locked when the configuration is open\n\t\t// so I do it only when muting is reset\n\t\tDialogue_TrackChange();\n\t}\n\t\n\tCloseVGMFile();\n\tLoadPlayingVGMInfo(NULL);\n\t\n\tInStopFunc = false;\n\treturn;\n}\n\n\nint GetFileLength(VGM_HEADER* FileHead)\n{\n\tUINT32 SmplCnt;\n\tUINT32 MSecCnt;\n\tINT32 LoopCnt;\n\t\n\tif (FileHead == &VGMHead)\n\t{\n\t\tLoopCnt = VGMMaxLoopM;\n\t}\n\telse\n\t{\n\t\tLoopCnt = (VGMMaxLoop * FileHead->bytLoopModifier + 0x08) / 0x10 - FileHead->bytLoopBase;\n\t\tif (LoopCnt < 0x01)\n\t\t\tLoopCnt = 0x01;\n\t}\n\t\n\tif (! LoopCnt && FileHead->lngLoopSamples)\n\t\treturn -1000;\n\t\n\t// Note: SmplCnt is ALWAYS 44.1 KHz, VGM's native sample rate\n\tSmplCnt = FileHead->lngTotalSamples + FileHead->lngLoopSamples * (LoopCnt - 0x01);\n\tif (FileHead == &VGMHead)\n\t\tMSecCnt = CalcSampleMSec(SmplCnt, 0x02);\n\telse\n\t\tMSecCnt = CalcSampleMSecExt(SmplCnt, 0x02, FileHead);\n\t\n\tif (FileHead->lngLoopSamples)\n\t\tMSecCnt += FadeTime + Options.PauseLp;\n\telse\n\t\tMSecCnt += Options.PauseNL;\n\t\n\treturn MSecCnt;\n}\n\nint GetLength(void)\t// return length of playing track\n{\n\treturn GetFileLength(&VGMHead);\n}\n\n\n// returns current output position, in ms.\n// you could just use return mod.outMod->GetOutputTime(),\n// but the dsp plug-ins that do tempo changing tend to make that wrong.\nint GetOutputTime(void)\n{\n\tif (seek_needed == -1) // seek is needed.\n\t\treturn decode_pos_ms + (WmpMod.outMod->GetOutputTime() -\n\t\t\t\t\t\t\t\tWmpMod.outMod->GetWrittenTime());\n\telse\n\t\treturn seek_needed;\n}\n\nvoid SetOutputTime(int time_in_ms)\t// for seeking\n{\n\t// Winamp seems send negative seeking values,\n\t// when GetLength returns -1000.\n\tif (time_in_ms >= 0)\n\t\tseek_needed = time_in_ms;\n\t\n\treturn;\n}\n\nvoid SetVolume(int volume)\n{\n\tWmpMod.outMod->SetVolume(volume);\n\t\n\treturn;\n}\n\nvoid SetPan(int pan)\n{\n\tWmpMod.outMod->SetPan(pan);\n\t\n\treturn;\n}\n\nvoid UpdatePlayback(void)\n{\n\tif (WmpMod.outMod == NULL || ! WmpMod.outMod->IsPlaying())\n\t\treturn;\n\t\n\tif (Options.ImmediateUpdate)\n\t{\n\t\t// add 30 ms - else it sounds like you seek back a little\n\t\tSetOutputTime(GetOutputTime() + 30);\n\t}\n\t\n\treturn;\n}\n\n\nint InfoDialog(const in_char* FileName, HWND hWnd)\n{\n\t//MessageBox(hWnd, \"No File Info. Yet.\", \"File Info\", MB_OK);\n#ifndef UNICODE_INPUT_PLUGIN\n\tSetInfoDlgFile(FileName);\n#else\n\tSetInfoDlgFileW(FileName);\n#endif\n\t\n\treturn DialogBox(WmpMod.hDllInstance, (LPTSTR)DlgFileInfo, hWnd, &FileInfoDialogProc);\n}\n\nconst in_char* GetFileNameTitle(const in_char* FileName)\n{\n\tconst in_char* TempPnt;\n\t\n#ifndef UNICODE_INPUT_PLUGIN\n\tTempPnt = FileName + strlen(FileName) - 0x01;\n\twhile(TempPnt >= FileName && *TempPnt != '\\\\')\n\t\tTempPnt --;\n#else\n\tTempPnt = FileName + wcslen(FileName) - 0x01;\n\twhile(TempPnt >= FileName && *TempPnt != L'\\\\')\n\t\tTempPnt --;\n#endif\n\t\n\treturn TempPnt + 0x01;\n}\n\n// This is an odd function. It is used to get the title and/or length of a track.\n// If filename is either NULL or of length 0, it means you should\n// return the info of LastFileName. Otherwise, return the information\n// for the file in filename.\nvoid GetFileInfo(const in_char* filename, in_char* title, int* length_in_ms)\n{\n\tUINT32 FileSize;\n\tVGM_HEADER FileHead;\n\tGD3_TAG FileTag;\n\tconst wchar_t* Tag_TrackName;\n\t\n#if 0\n\t{\n\t\tchar MsgStr[MAX_PATH * 2];\n\t\tsprintf(MsgStr, \"Calling GetFileInfo() with file:\\n%ls\", filename);\n\t\tMessageBoxA(WmpMod.hMainWindow, MsgStr, WmpMod.description, MB_ICONINFORMATION | MB_OK);\n\t}\n#endif\n\t\n\t// Note: If filename is be null OR of length zero, return info about the current file.\n\tif (filename == NULL || filename[0x00] == '\\0')\n\t{\n\t\t// called when the Play-Button is pressed\n\t\tif (length_in_ms != NULL)\n\t\t\t*length_in_ms = GetLength();\n\t\tif (title != NULL) // get non-path portion.of filename\n\t\t{\n\t\t\tif (! VGMTag.lngVersion)\n\t\t\t\tTag_TrackName = NULL;\n\t\t\telse\n\t\t\t\tTag_TrackName = GetTagStringEngJap(VGMTag.strTrackNameE, VGMTag.strTrackNameJ, false);\n\t\t\tif (Tag_TrackName != NULL)\n\t\t\t{\n\t\t\t\t//_snprintf(title, GETFILEINFO_TITLE_LENGTH, \"%ls (%ls)\",\n\t\t\t\t//\t\t\tVGMTag.strTrackNameE, VGMTag.strGameNameE);\n\t\t\t\tFormatVGMTag(GETFILEINFO_TITLE_LENGTH, title, &VGMTag, &VGMHead);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n#ifndef UNICODE_INPUT_PLUGIN\n\t\t\t\tstrncpy(title, GetFileNameTitle(CurFileName), GETFILEINFO_TITLE_LENGTH);\n#else\n\t\t\t\twcsncpy(title, GetFileNameTitle(CurFileName), GETFILEINFO_TITLE_LENGTH);\n#endif\n\t\t\t}\n\t\t}\n\t}\n\telse // some other file\n\t{\n#ifndef UNICODE_INPUT_PLUGIN\n\t\t//FileSize = GetVGMFileInfo(filename, (length_in_ms != NULL) ? &FileHead : NULL,\n\t\t//\t\t\t\t\t\t\t(title != NULL) ? &FileTag : NULL);\n\t\tFileSize = GetVGMFileInfo(filename, &FileHead, (title != NULL) ? &FileTag : NULL);\n#else\n\t\tFileSize = GetVGMFileInfoW(filename, &FileHead, (title != NULL) ? &FileTag : NULL);\n#endif\n\t\tif (length_in_ms != NULL)\n\t\t{\n\t\t\tif (FileSize)\n\t\t\t\t*length_in_ms = GetFileLength(&FileHead);\n\t\t\telse\n\t\t\t\t*length_in_ms = -1000;\t// File not found\n\t\t}\n\t\tif (title != NULL)\n\t\t{\n\t\t\tif (! FileSize || ! FileTag.lngVersion)\n\t\t\t\tTag_TrackName = NULL;\n\t\t\telse\n\t\t\t\tTag_TrackName = GetTagStringEngJap(FileTag.strTrackNameE, FileTag.strTrackNameJ, false);\n\t\t\tif (Tag_TrackName != NULL)\n\t\t\t{\n\t\t\t\t//_snprintf(title, GETFILEINFO_TITLE_LENGTH, \"%ls (%ls)\",\n\t\t\t\t//\t\t\tFileTag.strTrackNameE, FileTag.strGameNameE);\n\t\t\t\tFormatVGMTag(GETFILEINFO_TITLE_LENGTH, title, &FileTag, &FileHead);\n\t\t\t\tFreeGD3Tag(&FileTag);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n#ifndef UNICODE_INPUT_PLUGIN\n\t\t\t\tstrncpy(title, GetFileNameTitle(filename), GETFILEINFO_TITLE_LENGTH);\n#else\n\t\t\t\twcsncpy(title, GetFileNameTitle(filename), GETFILEINFO_TITLE_LENGTH);\n#endif\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn;\n}\n\nvoid EQ_Set(int on, char data[10], int preamp)\n{\n\t// unsupported\n\t\n\t// Format: each data byte is 0-63 (+20db <-> -20db) and preamp is the same. \n\treturn;\n}\n\n\n#define RENDER_SAMPLES\t576\t// visualizations look best with 576 samples\n#define BLOCK_SIZE\t\t(RENDER_SAMPLES * SMPL_BYTES)\n\nDWORD WINAPI DecodeThread(LPVOID b)\n{\n\tchar sample_buffer[BLOCK_SIZE * 2];\t// has to be twice as big as the blocksize\n\tUINT32 RetSamples;\n\t\n\tSetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);\n\t\n\twhile (! killDecodeThread) \n\t{ \n\t\tif (seek_needed != -1) // seek is needed.\n\t\t{\n\t\t\tdecode_pos = MulDivRound(seek_needed, SampleRate, 1000);\n\t\t\t//decode_pos_ms = MulDivRound(decode_pos, 1000, SampleRate);\n\t\t\tdecode_pos_ms = seek_needed;\n\t\t\t\n\t\t\tSeekVGM(false, decode_pos);\n\t\t\t\n\t\t\t// flush output device and set output to seek position\n\t\t\tWmpMod.outMod->Flush(decode_pos_ms);\n\t\t\tseek_needed = -1;\n\t\t}\n\t\t\n\t\tif (EndPlay /*|| VGMEnd*/)\n\t\t{\n\t\t\t// Playback finished\n\t\t\tWmpMod.outMod->CanWrite();\t\t// needed for some output drivers\n\t\t\t\n\t\t\tif (! WmpMod.outMod->IsPlaying())\n\t\t\t{\n\t\t\t\t// we're done playing, so tell Winamp and quit the thread.\n\t\t\t\tPostMessage(WmpMod.hMainWindow, WM_WA_MPEG_EOF, 0, 0);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tSleep(10);\t\t// give a little CPU time back to the system.\n\t\t}\n\t\telse if (WmpMod.outMod->CanWrite() >= (BLOCK_SIZE * (WmpMod.dsp_isactive() ? 2 : 1)))\n\t\t\t// CanWrite() returns the number of bytes you can write, so we check that\n\t\t\t// to the block size. the reason we multiply the block size by two if \n\t\t\t// mod.dsp_isactive() is that DSP plug-ins can change it by up to a \n\t\t\t// factor of two (for tempo adjustment).\n\t\t{\t\n\t\t\tRetSamples = FillBuffer((WAVE_16BS*)sample_buffer, RENDER_SAMPLES);\n\t\t\tif (RetSamples)\n\t\t\t{\n\t\t\t\t// send data to the visualization and dsp systems\n\t\t\t\tWmpMod.SAAddPCMData(sample_buffer, NUM_CHN, BIT_PER_SEC, decode_pos_ms);\n\t\t\t\tWmpMod.VSAAddPCMData(sample_buffer, NUM_CHN, BIT_PER_SEC, decode_pos_ms);\n\t\t\t\tif (WmpMod.dsp_isactive())\n\t\t\t\t\tRetSamples = WmpMod.dsp_dosamples((short*)sample_buffer, RetSamples,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tBIT_PER_SEC, NUM_CHN, SampleRate);\n\t\t\t\t\n\t\t\t\tWmpMod.outMod->Write(sample_buffer, RetSamples * SMPL_BYTES);\n\t\t\t\t\n\t\t\t\tdecode_pos += RetSamples;\n\t\t\t\tdecode_pos_ms = MulDivRound(decode_pos, 1000, SampleRate);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//done = true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSleep(20);\t// Wait a little, until we can write again.\n\t\t}\n\t}\n\t\n\treturn 0;\n}\n\n\n// module definition.\nIn_Module WmpMod =\n{\n\tIN_VER,\t// defined in IN2.H\n\tINVGM_TITLE_FULL\n\t// winamp runs on both alpha systems and x86 ones. :)\n#ifdef __alpha\n\t\" (AXP)\"\n//#else\n//\t\" (x86)\"\n#endif\n\t,\n\t0,\t// hMainWindow (filled in by winamp)\n\t0,\t// hDllInstance (filled in by winamp)\n\t// Format List: \"EXT\\0Description\\0EXT\\0Description\\0 ...\"\n\t\"vgm;vgz\\0VGM Audio Files (*.vgm; *.vgz)\\0\",\n\t//\"vgm;vgz\\0VGM Audio Files (*.vgm; *.vgz)\\0vgm7z\\0VGM7Z Archive (*.vgm7z)\\0\",\n\t1,\t// is_seekable\n\tIN_MODULE_FLAG_USES_OUTPUT_PLUGIN,\n\t&Config,\n\t&About,\n\t&Init,\n\t&Deinit,\n\t&GetFileInfo,\n\t&InfoDialog,\n\t&IsOurFile,\n\t&Play,\n\t&Pause,\n\t&Unpause,\n\t&IsPaused,\n\t&Stop,\n\t\n\t&GetLength,\n\t&GetOutputTime,\n\t&SetOutputTime,\n\t\n\t&SetVolume,\n\t&SetPan,\n\t\n\tNULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\t// visualization calls filled in by winamp\n\t\n\tNULL, NULL,\t// dsp calls filled in by winamp\n\t\n\t&EQ_Set,\n\t\n\tNULL,\t// setinfo call filled in by winamp\n\t\n\tNULL\t// out_mod filled in by winamp\n};\n\n// exported symbol. Returns output module.\n__declspec(dllexport) In_Module* winampGetInModule2(void)\n{\n\treturn &WmpMod;\n}\n"
  },
  {
    "path": "in_vgm/in_vgm.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"in_vgm\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** NICHT BEARBEITEN **\r\n\r\n# TARGTYPE \"Win32 (x86) Dynamic-Link Library\" 0x0102\r\n\r\nCFG=in_vgm - Win32 Debug\r\n!MESSAGE Dies ist kein gltiges Makefile. Zum Erstellen dieses Projekts mit NMAKE\r\n!MESSAGE verwenden Sie den Befehl \"Makefile exportieren\" und fhren Sie den Befehl\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"in_vgm.mak\".\r\n!MESSAGE \r\n!MESSAGE Sie knnen beim Ausfhren von NMAKE eine Konfiguration angeben\r\n!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"in_vgm.mak\" CFG=\"in_vgm - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Fr die Konfiguration stehen zur Auswahl:\r\n!MESSAGE \r\n!MESSAGE \"in_vgm - Win32 Release\" (basierend auf  \"Win32 (x86) Dynamic-Link Library\")\r\n!MESSAGE \"in_vgm - Win32 Debug\" (basierend auf  \"Win32 (x86) Dynamic-Link Library\")\r\n!MESSAGE \"in_vgm - Win32 Unicode Release\" (basierend auf  \"Win32 (x86) Dynamic-Link Library\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nMTL=midl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"in_vgm - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"Release\"\r\n# PROP BASE Intermediate_Dir \"Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"Release\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"IN_VGM_EXPORTS\" /YX /FD /c\r\n# ADD CPP /nologo /MD /W3 /GX /O2 /I \"../VGMPlay\" /I \"../VGMPlay/zlib\" /D \"NDEBUG\" /D \"WIN32\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"IN_VGM_EXPORTS\" /D \"VGM_LITTLE_ENDIAN\" /D \"ENABLE_ALL_CORES\" /D \"DISABLE_HW_SUPPORT\" /FD /c\r\n# SUBTRACT CPP /YX\r\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD BASE RSC /l 0x407 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386\r\n# ADD LINK32 zlib.lib kernel32.lib user32.lib comctl32.lib advapi32.lib /nologo /dll /machine:I386 /libpath:\"../VGMPlay/zlib\"\r\n\r\n!ELSEIF  \"$(CFG)\" == \"in_vgm - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"Debug\"\r\n# PROP BASE Intermediate_Dir \"Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"Debug\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"IN_VGM_EXPORTS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /MD /W3 /Gm /GX /ZI /Od /I \"../VGMPlay\" /I \"../VGMPlay/zlib\" /D \"_DEBUG\" /D \"WIN32\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"IN_VGM_EXPORTS\" /D \"VGM_LITTLE_ENDIAN\" /D \"ENABLE_ALL_CORES\" /D \"DISABLE_HW_SUPPORT\" /D \"UNICODE_INPUT_PLUGIN\" /FD /GZ /c\r\n# SUBTRACT CPP /YX\r\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n# ADD BASE RSC /l 0x407 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 zlib.lib kernel32.lib user32.lib comctl32.lib advapi32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:\"../VGMPlay/zlib\"\r\n# Begin Special Build Tool\r\nSOURCE=\"$(InputPath)\"\r\nPostBuild_Cmds=copy  Debug\\in_vgm.dll  D:\\Programme\\Winamp5_03a\\Plugins\\ \tcopy  Debug\\in_vgm.dll  xmplay36\\ \r\n# End Special Build Tool\r\n\r\n!ELSEIF  \"$(CFG)\" == \"in_vgm - Win32 Unicode Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"in_vgm___Win32_Unicode_Release\"\r\n# PROP BASE Intermediate_Dir \"in_vgm___Win32_Unicode_Release\"\r\n# PROP BASE Ignore_Export_Lib 0\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"ReleaseW\"\r\n# PROP Intermediate_Dir \"ReleaseW\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I \"../VGMPlay\" /I \"../VGMPlay/zlib\" /D \"NDEBUG\" /D \"WIN32\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"IN_VGM_EXPORTS\" /D \"VGM_LITTLE_ENDIAN\" /D \"ENABLE_ALL_CORES\" /D \"DISABLE_HW_SUPPORT\" /FD /c\r\n# SUBTRACT BASE CPP /YX\r\n# ADD CPP /nologo /MD /W3 /GX /O2 /I \"../VGMPlay\" /I \"../VGMPlay/zlib\" /D \"NDEBUG\" /D \"WIN32\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"IN_VGM_EXPORTS\" /D \"VGM_LITTLE_ENDIAN\" /D \"ENABLE_ALL_CORES\" /D \"DISABLE_HW_SUPPORT\" /D \"UNICODE_INPUT_PLUGIN\" /FD /c\r\n# SUBTRACT CPP /YX\r\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 zlib.lib kernel32.lib user32.lib comctl32.lib advapi32.lib /nologo /dll /machine:I386 /libpath:\"../VGMPlay/zlib\"\r\n# ADD LINK32 zlib.lib kernel32.lib user32.lib comctl32.lib advapi32.lib /nologo /dll /machine:I386 /out:\"ReleaseW/in_vgm_w.dll\" /libpath:\"../VGMPlay/zlib\"\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"in_vgm - Win32 Release\"\r\n# Name \"in_vgm - Win32 Debug\"\r\n# Name \"in_vgm - Win32 Unicode Release\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"c;def\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\dlg_cfg.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\dlg_fileinfo.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\in_vgm.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\ini_func.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\pt_ioctl.c\r\n# PROP Exclude_From_Build 1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\VGMPlay.c\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\in_vgm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\ini_func.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\PortTalk_IOCTL.h\r\n# PROP Exclude_From_Build 1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\stdbool.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\VGMFile.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\VGMPlay.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\VGMPlay_Intf.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\icon.ico\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\in_vgm.rc\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\images\\logo.bmp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\resource.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\images\\tabicons.bmp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Sound Core\"\r\n\r\n# PROP Default_Filter \"\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\2151intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\2151intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\2203intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\2203intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\2413intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\2413intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\2608intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\2608intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\2610intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\2610intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\2612intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\2612intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\262intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\262intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\3526intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\3526intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\3812intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\3812intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\8950intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\8950intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\adlibemu.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\adlibemu_opl2.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\adlibemu_opl3.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ay8910.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ay8910.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ay_intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ay_intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\c140.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\c140.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\c352.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\c352.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\c6280.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\c6280.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\c6280intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\c6280intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ChipIncl.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\ChipMapper.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\ChipMapper.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\dac_control.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\dac_control.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\emu2149.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\emu2149.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\emu2413.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\emu2413.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\emutypes.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\es5503.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\es5503.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\es5506.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\es5506.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\fm.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\fm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\fm2612.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\fmopl.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\fmopl.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\gb.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\gb.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\iremga20.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\iremga20.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\k051649.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\k051649.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\k053260.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\k053260.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\k054539.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\k054539.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\mamedef.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\multipcm.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\multipcm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\nes_apu.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\nes_apu.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\nes_defs.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\nes_intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\nes_intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\np_nes_apu.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\np_nes_apu.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\np_nes_dmc.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\np_nes_dmc.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\np_nes_fds.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\np_nes_fds.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\okim6258.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\okim6258.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\okim6295.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\okim6295.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\Ootake_PSG.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\Ootake_PSG.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\opl.c\r\n# PROP Exclude_From_Build 1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\opl.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\opll.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\opll.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\opm.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\opm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\panning.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\panning.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\pokey.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\pokey.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\pwm.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\pwm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\qsound_ctr.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\qsound_ctr.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\qsound_intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\qsound_intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\qsound_mame.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\qsound_mame.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\rf5c68.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\rf5c68.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\saa1099.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\saa1099.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\scd_pcm.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\scd_pcm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\scsp.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\scsp.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\scspdsp.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\scspdsp.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\scsplfo.c\r\n# PROP Exclude_From_Build 1\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\segapcm.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\segapcm.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\sn76489.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\sn76489.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\sn76496.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\sn76496.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\sn764intf.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\sn764intf.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\upd7759.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\upd7759.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\vrc7tone.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\vsu.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\vsu.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ws_audio.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ws_audio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ws_initialIo.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\x1_010.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\x1_010.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ym2151.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ym2151.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ym2413.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ym2413.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ym2612.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ym2612.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ym3438.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ym3438.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ymdeltat.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ymdeltat.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ymf262.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ymf262.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ymf271.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ymf271.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ymf278b.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ymf278b.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ymz280b.c\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\VGMPlay\\chips\\ymz280b.h\r\n# End Source File\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "in_vgm/in_vgm.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\r\n# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELSCHT WERDEN!\r\n\r\n###############################################################################\r\n\r\nProject: \"in_vgm\"=\".\\in_vgm.dsp\" - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nGlobal:\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<3>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\n"
  },
  {
    "path": "in_vgm/in_vgm.h",
    "content": "//#include \"../VGMPlay.h\"\n\n#if defined(APLHA)\n\n#define VER_EXTRA\t\" alpha\"\n#define VER_DATE\t\" (\"__DATE__\" \"__TIME__\")\"\n\n#elif defined(BETA)\n\n#define VER_EXTRA\t\" beta\"\n#define VER_DATE\t\" (\"__DATE__\" \"__TIME__\")\"\n\n#else\n\n#define VER_EXTRA\t\"\"\n#define VER_DATE\t\"\"\n\n#endif\n\n#define INVGM_VERSION\t\tVGMPLAY_VER_STR VER_EXTRA\n#define INVGM_TITLE\t\t\t\"VGM Input Plugin v\" INVGM_VERSION\n#define INVGM_TITLE_FULL\t\"VGM Input Plugin v\" INVGM_VERSION VER_DATE\n\ntypedef struct plugin_options\n{\n\tbool ImmediateUpdate;\n\tbool NoInfoCache;\n\t\n\tUINT32 SampleRate;\n\tUINT32 ChipRate;\n\tUINT32 PauseNL;\n\tUINT32 PauseLp;\n\t\n\tchar TitleFormat[0x80];\n\tbool JapTags;\n\tbool AppendFM2413;\n\tbool TrimWhitespc;\n\tbool StdSeparators;\n\tbool TagFallback;\n\tUINT32 MLFileType;\n\t\n\tbool Enable7z;\n\t\n\tbool ResetMuting;\n} PLGIN_OPTS;\n\nextern PLGIN_OPTS Options;\n\n#include \"resource.h\"\n"
  },
  {
    "path": "in_vgm/in_vgm.rc",
    "content": "//Microsoft Developer Studio generated resource script.\n//\n#include \"resource.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"afxres.h\"\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// Neutral resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)\n#ifdef _WIN32\nLANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL\n#pragma code_page(1252)\n#endif //_WIN32\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Icon\n//\n\n// Icon with lowest ID value placed first to ensure application icon\n// remains consistent on all systems.\nMainIcon                ICON    DISCARDABLE     \"icon.ico\"\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Bitmap\n//\n\nTabIcons                BITMAP  DISCARDABLE     \"images\\\\tabicons.bmp\"\nLogoBitmap              BITMAP  DISCARDABLE     \"images\\\\logo.bmp\"\n#endif    // Neutral resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n/////////////////////////////////////////////////////////////////////////////\n// Deutsch (Deutschland) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)\n#ifdef _WIN32\nLANGUAGE LANG_GERMAN, SUBLANG_GERMAN\n#pragma code_page(1252)\n#endif //_WIN32\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"#include \"\"afxres.h\"\"\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"\\r\\n\"\n    \"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n#endif    // Deutsch (Deutschland) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n/////////////////////////////////////////////////////////////////////////////\n// Englisch (USA) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\n#ifdef _WIN32\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\n#pragma code_page(1252)\n#endif //_WIN32\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Dialog\n//\n\nDlgCfgTags DIALOG DISCARDABLE  0, 0, 270, 166\nSTYLE DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | \n    WS_VISIBLE\nFONT 8, \"MS Shell Dlg\"\nBEGIN\n    GROUPBOX        \"Legacy title &formatting\",IDC_STATIC,5,5,100,155\n    EDITTEXT        TitleFormatText,10,18,86,12,ES_AUTOHSCROLL\n    LTEXT           \"%t\\n%a\\n%g\\n%d\\n%s\\n%c\",IDC_STATIC,10,35,15,51,NOT \n                    WS_GROUP\n    LTEXT           \"Track title*\\nTrack author*\\nGame name*\\nGame release date\\nSystem name*\\nFile creator\",\n                    IDC_STATIC,30,35,65,50,NOT WS_GROUP\n    LTEXT           \"* use %?j for Japanese text if available\",IDC_STATIC,10,\n                    85,85,20,NOT WS_GROUP\n    LTEXT           \"Default:  %t (%g) - %a\",IDC_STATIC,10,105,85,10,NOT \n                    WS_GROUP\n    LTEXT           \"Note: this has no effect when Advanced Title Formatting is enabled in Winamp.\",\n                    IDC_STATIC,10,120,85,37,NOT WS_GROUP\n    GROUPBOX        \"Data formatting\",IDC_STATIC,110,5,150,99\n    CONTROL         \"Prefer &Japanese text\",PreferJapCheck,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,115,15,140,15\n    CONTROL         \"Append \"\"(&FM)\"\" to YM2413 game titles\",FM2413Check,\n                    \"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,115,28,140,15\n    CONTROL         \"&Trim whitespace\",TrimWhitespcCheck,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,115,44,140,10\n    CONTROL         \"Standardise &separators (to ,)\",StdSeparatorsCheck,\n                    \"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,115,58,140,10\n    GROUPBOX        \"File type\",IDC_STATIC,110,110,150,50\n    LTEXT           \"Return file &type ID:\",IDC_STATIC,115,121,65,12,\n                    SS_CENTERIMAGE | NOT WS_GROUP\n    EDITTEXT        MLTypeText,180,121,74,12,ES_AUTOHSCROLL | ES_NUMBER\n    CTEXT           \"0 = audio, 1 = video\\nSee the documentation for the usage.\",\n                    IDC_STATIC,115,135,140,20,NOT WS_GROUP\n    CONTROL         \"Tag fallb&ack in File Info Dialog\",TagFallbackCheck,\n                    \"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,115,72,140,10\n    CONTROL         \"Don't &cache file information\",NoInfoCacheCheck,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,115,86,140,10\nEND\n\nDlgConfigMain DIALOG DISCARDABLE  0, 0, 286, 210\nSTYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | \n    WS_SYSMENU\nCAPTION \"VGM plugin configuration\"\nFONT 8, \"MS Shell Dlg\"\nBEGIN\n    CONTROL         \"Immediate &update\",ImmediateUpdCheck,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,6,195,83,10\n    PUSHBUTTON      \"Help\",HelpButton,108,193,52,14,WS_DISABLED\n    PUSHBUTTON      \"Cancel\",IDCANCEL,169,193,52,14\n    DEFPUSHBUTTON   \"OK\",IDOK,230,193,52,14\n    CONTROL         \"Tab1\",TabCollection,\"SysTabControl32\",TCS_MULTILINE | \n                    WS_TABSTOP,2,2,280,187\nEND\n\nDlgFileInfo DIALOG DISCARDABLE  0, 0, 379, 143\nSTYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | \n    WS_SYSMENU\nCAPTION \"VGM File & GD3 Tag Information\"\nFONT 8, \"MS Shell Dlg\"\nBEGIN\n    DEFPUSHBUTTON   \"OK\",IDOK,325,127,52,14\n    GROUPBOX        \"Track\",IDC_STATIC,2,0,173,40\n    LTEXT           \"&Title\",IDC_STATIC,7,10,32,12,SS_CENTERIMAGE | NOT \n                    WS_GROUP\n    EDITTEXT        TrkTitleText,40,10,130,12,ES_AUTOHSCROLL | ES_READONLY\n    LTEXT           \"&Author\",IDC_STATIC,7,23,32,12,SS_CENTERIMAGE | NOT \n                    WS_GROUP\n    EDITTEXT        TrkAuthorText,40,23,130,12,ES_AUTOHSCROLL | ES_READONLY\n    GROUPBOX        \"Game\",IDC_STATIC,2,40,173,52\n    LTEXT           \"Na&me\",IDC_STATIC,7,49,32,12,SS_CENTERIMAGE | NOT \n                    WS_GROUP\n    EDITTEXT        GameNameText,40,49,130,12,ES_AUTOHSCROLL | ES_READONLY\n    LTEXT           \"&System\",IDC_STATIC,7,62,32,12,SS_CENTERIMAGE | NOT \n                    WS_GROUP\n    EDITTEXT        GameSysText,40,62,130,12,ES_AUTOHSCROLL | ES_READONLY\n    LTEXT           \"&Date\",IDC_STATIC,7,75,32,12,SS_CENTERIMAGE | NOT \n                    WS_GROUP\n    EDITTEXT        GameDateText,40,75,130,12,ES_AUTOHSCROLL | ES_READONLY\n    GROUPBOX        \"VGM file\",IDC_STATIC,179,0,198,125\n    LTEXT           \"&Filename\",IDC_STATIC,185,10,39,12,SS_CENTERIMAGE | NOT \n                    WS_GROUP\n    EDITTEXT        VGMFileText,224,10,101,12,ES_AUTOHSCROLL | ES_READONLY\n    LTEXT           \"&Creator\",IDC_STATIC,185,23,39,12,SS_CENTERIMAGE\n    EDITTEXT        VGMCrtText,224,23,101,12,ES_AUTOHSCROLL | ES_READONLY\n    LTEXT           \"&Version\",IDC_STATIC,185,36,39,12,SS_CENTERIMAGE\n    EDITTEXT        VGMVerText,224,36,23,12,ES_AUTOHSCROLL | ES_READONLY\n    LTEXT           \"&Gain\",IDC_STATIC,259,36,31,12,SS_CENTERIMAGE\n    EDITTEXT        VGMGainText,290,36,35,12,ES_AUTOHSCROLL | ES_READONLY\n    LTEXT           \"Si&ze\",IDC_STATIC,185,49,39,12,SS_CENTERIMAGE\n    EDITTEXT        VGMSizeText,224,49,101,12,ES_AUTOHSCROLL | ES_READONLY\n    LTEXT           \"&Length\",IDC_STATIC,185,62,39,12,SS_CENTERIMAGE\n    EDITTEXT        VGMLenText,224,62,148,12,ES_AUTOHSCROLL | ES_READONLY\n    LTEXT           \"&Notes:\",IDC_STATIC,185,77,39,8\n    EDITTEXT        VGMNotesText,185,87,188,34,ES_MULTILINE | ES_READONLY | \n                    WS_VSCROLL\n    LTEXT           \"Chips &used:\",IDC_STATIC,329,10,39,12,SS_CENTERIMAGE | \n                    NOT WS_GROUP\n    EDITTEXT        ChipUseText,329,23,42,39,ES_MULTILINE | ES_READONLY | \n                    NOT WS_BORDER\n    GROUPBOX        \"Language\",IDC_STATIC,123,92,52,33\n    CONTROL         \"&English\",LangEngCheck,\"Button\",BS_AUTORADIOBUTTON | \n                    WS_TABSTOP,127,103,39,8\n    CONTROL         \"&Japanese\",LangJapCheck,\"Button\",BS_AUTORADIOBUTTON | \n                    WS_TABSTOP,127,113,43,8\n    PUSHBUTTON      \"View in &browser\",BrwsrInfoButton,123,127,80,14,\n                    WS_DISABLED\n    PUSHBUTTON      \"Configure &plugin...\",ConfigPluginButton,206,127,80,14\n    CONTROL         103,IDC_STATIC,\"Static\",SS_BITMAP | SS_REALSIZEIMAGE,2,\n                    95,119,46\nEND\n\nDlgCfgPlayback DIALOG DISCARDABLE  0, 0, 270, 166\nSTYLE DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | \n    WS_VISIBLE\nFONT 8, \"MS Shell Dlg\"\nBEGIN\n    GROUPBOX        \"Sample Rates\",IDC_STATIC,5,5,257,40\n    LTEXT           \"&Playback Rate\",IDC_STATIC,11,16,54,10,NOT WS_GROUP\n    EDITTEXT        SmplPbRateText,65,14,33,12,ES_RIGHT | ES_AUTOHSCROLL | \n                    ES_NUMBER\n    LTEXT           \"Hz\",IDC_STATIC,102,16,15,10,NOT WS_GROUP\n    LTEXT           \"Re&sampling Mode\",IDC_STATIC,117,16,59,10,NOT WS_GROUP\n    COMBOBOX        ResmpModeList,182,14,74,43,CBS_DROPDOWNLIST | WS_TABSTOP\n    LTEXT           \"C&hip Rate\",SmplChipRateLabel,11,30,54,10,NOT WS_GROUP\n    EDITTEXT        SmplChipRateText,65,29,33,12,ES_RIGHT | ES_AUTOHSCROLL | \n                    ES_NUMBER\n    LTEXT           \"Hz\",SmplChipRateHzLabel,102,31,15,10,NOT WS_GROUP\n    LTEXT           \"Chip Sample &Mode\",IDC_STATIC,117,31,59,10,NOT WS_GROUP\n    COMBOBOX        ChipSmpModeList,182,29,74,43,CBS_DROPDOWNLIST | \n                    WS_TABSTOP\n    CONTROL         \"\"\"S&urround\"\" Sound\",SurroundCheck,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,5,52,85,10\n    GROUPBOX        \"Loops\",IDC_STATIC,5,66,150,45\n    LTEXT           \"Play &loops\",IDC_STATIC,11,79,38,10,NOT WS_GROUP\n    EDITTEXT        LoopText,49,77,27,12,ES_RIGHT | ES_AUTOHSCROLL | \n                    ES_NUMBER\n    LTEXT           \"times\",LoopTimesLabel,81,79,22,10,NOT WS_GROUP\n    LTEXT           \"(0 = infinite)\",IDC_STATIC,107,79,38,10,NOT WS_GROUP\n    LTEXT           \"&Fade over\",IDC_STATIC,11,93,38,10,NOT WS_GROUP\n    EDITTEXT        FadeText,49,91,27,12,ES_RIGHT | ES_AUTOHSCROLL | \n                    ES_NUMBER\n    LTEXT           \"ms\",IDC_STATIC,81,93,22,10,NOT WS_GROUP\n    GROUPBOX        \"Pause between tracks\",IDC_STATIC,5,115,100,45\n    LTEXT           \"&Non-looping\",IDC_STATIC,11,127,38,10,NOT WS_GROUP\n    EDITTEXT        PauseNlText,54,126,27,12,ES_RIGHT | ES_AUTOHSCROLL | \n                    ES_NUMBER\n    LTEXT           \"ms\",IDC_STATIC,86,128,15,10,NOT WS_GROUP\n    LTEXT           \"Loop&ing\",IDC_STATIC,11,143,38,10,NOT WS_GROUP\n    EDITTEXT        PauseLpText,54,141,27,12,ES_RIGHT | ES_AUTOHSCROLL | \n                    ES_NUMBER\n    LTEXT           \"ms\",IDC_STATIC,86,143,15,10,NOT WS_GROUP\n    GROUPBOX        \"Playback rate\",IDC_STATIC,165,48,97,63\n    CONTROL         \"&Recorded rate\",RateRecRadio,\"Button\",\n                    BS_AUTORADIOBUTTON,171,59,65,10\n    CONTROL         \"&60 Hz\",Rate60HzRadio,\"Button\",BS_AUTORADIOBUTTON,171,\n                    71,36,10\n    CONTROL         \"&50 Hz\",Rate50HzRadio,\"Button\",BS_AUTORADIOBUTTON,171,\n                    83,36,10\n    CONTROL         \"&Other:\",RateOtherRadio,\"Button\",BS_AUTORADIOBUTTON | \n                    WS_TABSTOP,171,95,35,10\n    EDITTEXT        RateText,208,94,22,12,ES_RIGHT | ES_AUTOHSCROLL | \n                    ES_NUMBER\n    LTEXT           \"Hz\",RateLabel,235,96,17,10,NOT WS_GROUP\n    GROUPBOX        \"&Volume\",IDC_STATIC,115,115,147,45\n    CONTROL         \"Slider1\",VolumeSlider,\"msctls_trackbar32\",TBS_AUTOTICKS | \n                    WS_TABSTOP,117,126,143,15\n    EDITTEXT        VolumeText,156,146,65,12,ES_CENTER | ES_AUTOHSCROLL | \n                    ES_READONLY | ES_NUMBER | NOT WS_BORDER\nEND\n\nDlgCfgVgm7z DIALOG DISCARDABLE  0, 0, 270, 166\nSTYLE DS_SETFOREGROUND | DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_VISIBLE\nFONT 8, \"MS Shell Dlg\"\nBEGIN\n    LTEXT           \"vgm7z-files are currently not supported.\\n\\nBut this will change someday.\",\n                    IDC_STATIC,5,5,245,35\nEND\n\nDlgCfgMuting DIALOG DISCARDABLE  0, 0, 270, 166\nSTYLE DS_SETFOREGROUND | DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_VISIBLE\nFONT 8, \"MS Shell Dlg\"\nBEGIN\n    LTEXT           \"&Select Chip:\",IDC_STATIC,10,12,50,10\n    COMBOBOX        MutingChipList,60,10,60,80,CBS_DROPDOWNLIST | WS_VSCROLL | \n                    WS_TABSTOP\n    COMBOBOX        MutingChipNumList,130,10,60,80,CBS_DROPDOWNLIST | \n                    WS_TABSTOP\n    CONTROL         \"Channel &1\",MuteChn1Check,\"Button\",BS_AUTOCHECKBOX | \n                    WS_TABSTOP,20,30,65,10\n    CONTROL         \"Channel &2\",MuteChn2Check,\"Button\",BS_AUTOCHECKBOX | \n                    WS_TABSTOP,20,45,65,10\n    CONTROL         \"Channel &3\",MuteChn3Check,\"Button\",BS_AUTOCHECKBOX | \n                    WS_TABSTOP,20,60,65,10\n    CONTROL         \"Channel &4\",MuteChn4Check,\"Button\",BS_AUTOCHECKBOX | \n                    WS_TABSTOP,20,75,65,10\n    CONTROL         \"Channel &5\",MuteChn5Check,\"Button\",BS_AUTOCHECKBOX | \n                    WS_TABSTOP,20,90,65,10\n    CONTROL         \"Channel &6\",MuteChn6Check,\"Button\",BS_AUTOCHECKBOX | \n                    WS_TABSTOP,20,105,65,10\n    CONTROL         \"Channel &7\",MuteChn7Check,\"Button\",BS_AUTOCHECKBOX | \n                    WS_TABSTOP,20,120,65,10\n    CONTROL         \"Channel &8\",MuteChn8Check,\"Button\",BS_AUTOCHECKBOX | \n                    WS_TABSTOP,20,135,65,10\n    CONTROL         \"Channel &9\",MuteChn9Check,\"Button\",BS_AUTOCHECKBOX | \n                    WS_TABSTOP,100,30,65,10\n    CONTROL         \"Channel 10 (&A)\",MuteChn10Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,100,45,65,10\n    CONTROL         \"Channel 11 (&B)\",MuteChn11Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,100,60,65,10\n    CONTROL         \"Channel 12 (&C)\",MuteChn12Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,100,75,65,10\n    CONTROL         \"Channel 13 (&D)\",MuteChn13Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,100,90,65,10\n    CONTROL         \"Channel 14 (&E)\",MuteChn14Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,100,105,65,10\n    CONTROL         \"Channel 15 (&F)\",MuteChn15Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,100,120,65,10\n    CONTROL         \"Channel 16 (&G)\",MuteChn16Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,100,135,65,10\n    CONTROL         \"Channel 17 (&H)\",MuteChn17Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,180,30,65,10\n    CONTROL         \"Channel 18 (&I)\",MuteChn18Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,180,45,65,10\n    CONTROL         \"Channel 19 (&J)\",MuteChn19Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,180,60,65,10\n    CONTROL         \"Channel 20 (&K)\",MuteChn20Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,180,75,65,10\n    CONTROL         \"Channel 21 (&L)\",MuteChn21Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,180,90,65,10\n    CONTROL         \"Channel 22 (&M)\",MuteChn22Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,180,105,65,10\n    CONTROL         \"Channel 23 (&N)\",MuteChn23Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,180,120,65,10\n    CONTROL         \"Channel 24 (&O)\",MuteChn24Check,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,180,135,65,10\n    CONTROL         \"&Reset on track change\",ResetMuteCheck,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,10,155,115,10\n    CONTROL         \"Disable Chip (&X)\",MuteChipCheck,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,180,155,70,10\nEND\n\nDlgCfgOptPan DIALOG DISCARDABLE  0, 0, 270, 166\nSTYLE DS_SETFOREGROUND | DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_VISIBLE\nFONT 8, \"MS Shell Dlg\"\nBEGIN\n    LTEXT           \"&Select Chip:\",IDC_STATIC,10,12,50,10\n    COMBOBOX        EmuOptChipList,60,10,60,80,CBS_DROPDOWNLIST | WS_VSCROLL | \n                    WS_TABSTOP\n    COMBOBOX        EmuOptChipNumList,130,10,60,80,CBS_DROPDOWNLIST | \n                    WS_TABSTOP\n    GROUPBOX        \"E&mulation Core\",IDC_STATIC,10,30,245,30\n    CONTROL         \"Default Core\",EmuCoreRadio1,\"Button\",BS_AUTORADIOBUTTON,\n                    20,43,105,10\n    CONTROL         \"Alternative Core\",EmuCoreRadio2,\"Button\",\n                    BS_AUTORADIOBUTTON,135,43,110,10\n    GROUPBOX        \"Panning\",IDC_STATIC,10,65,245,95\n    LTEXT           \"&1\",PanChn1Label,20,80,10,8\n    CONTROL         \"Slider1\",PanChn1Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,30,80,60,10\n    LTEXT           \"&2\",PanChn2Label,20,95,10,8\n    CONTROL         \"Slider1\",PanChn2Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,30,95,60,10\n    LTEXT           \"&3\",PanChn3Label,20,110,10,8\n    CONTROL         \"Slider1\",PanChn3Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,30,110,60,10\n    LTEXT           \"&4\",PanChn4Label,20,125,10,8\n    CONTROL         \"Slider1\",PanChn4Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,30,125,60,10\n    LTEXT           \"&5\",PanChn5Label,20,140,10,8\n    CONTROL         \"Slider1\",PanChn5Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,30,140,60,10\n    LTEXT           \"&6\",PanChn6Label,95,80,10,8\n    CONTROL         \"Slider1\",PanChn6Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,105,80,60,10\n    LTEXT           \"&7\",PanChn7Label,95,95,10,8\n    CONTROL         \"Slider1\",PanChn7Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,105,95,60,10\n    LTEXT           \"&8\",PanChn8Label,95,110,10,8\n    CONTROL         \"Slider1\",PanChn8Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,105,110,60,10\n    LTEXT           \"&9\",PanChn9Label,95,125,10,8\n    CONTROL         \"Slider1\",PanChn9Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,105,125,60,10\n    LTEXT           \"&A\",PanChn10Label,95,140,10,8\n    CONTROL         \"Slider1\",PanChn10Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,105,140,60,10\n    LTEXT           \"&B\",PanChn11Label,175,80,10,8\n    CONTROL         \"Slider1\",PanChn11Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,185,80,60,10\n    LTEXT           \"&C\",PanChn12Label,175,95,10,8\n    CONTROL         \"Slider1\",PanChn12Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,185,95,60,10\n    LTEXT           \"&D\",PanChn13Label,175,110,10,8\n    CONTROL         \"Slider1\",PanChn13Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,185,110,60,10\n    LTEXT           \"&E\",PanChn14Label,175,125,10,8\n    CONTROL         \"Slider1\",PanChn14Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,185,125,60,10\n    LTEXT           \"&F\",PanChn15Label,175,140,10,8\n    CONTROL         \"Slider1\",PanChn15Slider,\"msctls_trackbar32\",\n                    TBS_AUTOTICKS | WS_TABSTOP,185,140,60,10\nEND\n\n#endif    // Englisch (USA) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n\n"
  },
  {
    "path": "in_vgm/ini_func.c",
    "content": "#include <stdio.h>\n#include <windows.h>\n\n#include \"stdbool.h\"\n#include \"chips/mamedef.h\"\t// for (U)INTxx types\n\nextern char IniFilePath[MAX_PATH];\n\nvoid ReadIni_Integer(const char* Section, const char* Key, UINT32* Value)\n{\n\t*Value = (INT32)GetPrivateProfileInt(Section, Key, *Value, IniFilePath);\n\t\n\treturn;\n}\n\nvoid ReadIni_SIntSht(const char* Section, const char* Key, INT16* Value)\n{\n\t*Value = (INT16)GetPrivateProfileInt(Section, Key, *Value, IniFilePath);\n\t\n\treturn;\n}\n\nvoid ReadIni_IntByte(const char* Section, const char* Key, UINT8* Value)\n{\n\t*Value = (UINT8)GetPrivateProfileInt(Section, Key, *Value, IniFilePath);\n\t\n\treturn;\n}\n\nvoid ReadIni_Boolean(const char* Section, const char* Key, bool* Value)\n{\n\tchar TempStr[0x10];\n\t\n\tGetPrivateProfileString(Section, Key, \"\", TempStr, 0x10, IniFilePath);\n\tif (! strcmp(TempStr, \"\"))\n\t\treturn;\n\t\n\tif (! stricmp(TempStr, \"True\"))\n\t\t*Value = true;\n\telse if (! stricmp(TempStr, \"False\"))\n\t\t*Value = false;\n\telse\n\t\t*Value = strtol(TempStr, NULL, 0) ? true : false;\n\t\n\treturn;\n}\n\nvoid ReadIni_String(const char* Section, const char* Key, char* String, UINT32 StrSize)\n{\n\tGetPrivateProfileString(Section, Key, String, String, StrSize, IniFilePath);\n\t\n\treturn;\n}\n\nvoid ReadIni_Float(const char* Section, const char* Key, float* Value)\n{\n\tchar TempStr[0x10];\n\t\n\tGetPrivateProfileString(Section, Key, \"\", TempStr, 0x10, IniFilePath);\n\tif (! strcmp(TempStr, \"\"))\n\t\treturn;\n\t\n\t*Value = (float)strtod(TempStr, NULL);\n\t\n\treturn;\n}\n\n\n\nvoid WriteIni_Integer(const char* Section, const char* Key, UINT32 Value)\n{\n\tchar TempStr[0x10];\n\t\n\tsprintf(TempStr, \"%u\", Value);\n\tWritePrivateProfileString(Section, Key, TempStr, IniFilePath);\n\t\n\treturn;\n}\n\nvoid WriteIni_SInteger(const char* Section, const char* Key, INT32 Value)\n{\n\tchar TempStr[0x10];\n\t\n\tsprintf(TempStr, \"%d\", Value);\n\tWritePrivateProfileString(Section, Key, TempStr, IniFilePath);\n\t\n\treturn;\n}\n\nvoid WriteIni_XInteger(const char* Section, const char* Key, UINT32 Value)\n{\n\tchar TempStr[0x10];\n\t\n\tsprintf(TempStr, \"0x%02X\", Value);\n\tWritePrivateProfileString(Section, Key, TempStr, IniFilePath);\n\t\n\treturn;\n}\n\nvoid WriteIni_Boolean(const char* Section, const char* Key, bool Value)\n{\n\tchar TempStr[0x10];\n\t\n\tif (Value)\n\t\tstrcpy(TempStr, \"True\");\n\telse\n\t\tstrcpy(TempStr, \"False\");\n\tWritePrivateProfileString(Section, Key, TempStr, IniFilePath);\n\t\n\treturn;\n}\n\nvoid WriteIni_String(const char* Section, const char* Key, char* String)\n{\n\tWritePrivateProfileString(Section, Key, String, IniFilePath);\n\t\n\treturn;\n}\n\nvoid WriteIni_Float(const char* Section, const char* Key, float Value)\n{\n\tchar TempStr[0x10];\n\t\n\tsprintf(TempStr, \"%f\", Value);\n\tWritePrivateProfileString(Section, Key, TempStr, IniFilePath);\n\t\n\treturn;\n}\n"
  },
  {
    "path": "in_vgm/ini_func.h",
    "content": "void ReadIni_Integer(const char* Section, const char* Key, UINT32* Value);\nvoid ReadIni_SIntSht(const char* Section, const char* Key, INT16* Value);\nvoid ReadIni_IntByte(const char* Section, const char* Key, UINT8* Value);\nvoid ReadIni_Boolean(const char* Section, const char* Key, bool* Value);\nvoid ReadIni_String(const char* Section, const char* Key, char* String, UINT32 StrSize);\nvoid ReadIni_Float(const char* Section, const char* Key, float* Value);\n\nvoid WriteIni_Integer(const char* Section, const char* Key, UINT32 Value);\nvoid WriteIni_SInteger(const char* Section, const char* Key, INT32 Value);\nvoid WriteIni_XInteger(const char* Section, const char* Key, UINT32 Value);\nvoid WriteIni_Boolean(const char* Section, const char* Key, bool Value);\nvoid WriteIni_String(const char* Section, const char* Key, char* String);\nvoid WriteIni_Float(const char* Section, const char* Key, float Value);\n"
  },
  {
    "path": "in_vgm/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\n// Microsoft Developer Studio generated include file.\n// Used by in_vgm.rc\n//\n#define MainIcon                        101\n#define TabIcons                        102\n#define LogoBitmap                      103\n#define DlgConfigMain                   201\n#define DlgFileInfo                     202\n#define DlgCfgPlayback                  203\n#define DlgCfgTags                      204\n#define DlgCfgVgm7z                     205\n#define DlgCfgMuting                    206\n#define DlgCfgOptPan                    207\n#define TabCollection                   1001\n#define ImmediateUpdCheck               1002\n#define HelpButton                      1003\n#define LoopText                        1101\n#define FadeText                        1102\n#define PauseNlText                     1103\n#define PauseLpText                     1104\n#define RateRecRadio                    1105\n#define Rate60HzRadio                   1106\n#define Rate50HzRadio                   1107\n#define RateOtherRadio                  1108\n#define RateText                        1109\n#define RateLabel                       1110\n#define VolumeSlider                    1111\n#define VolumeText                      1112\n#define SmplPbRateText                  1113\n#define ResmpModeList                   1114\n#define SmplChipRateText                1115\n#define ChipSmpModeList                 1116\n#define SurroundCheck                   1117\n#define SmplChipRateLabel               1118\n#define SmplChipRateHzLabel             1119\n#define LoopTimesLabel                  1120\n#define TitleFormatText                 1201\n#define PreferJapCheck                  1202\n#define FM2413Check                     1203\n#define TrimWhitespcCheck               1204\n#define StdSeparatorsCheck              1205\n#define MLTypeText                      1206\n#define TagFallbackCheck                1207\n#define NoInfoCacheCheck                1208\n#define MutingChipList                  1301\n#define MutingChipNumList               1302\n#define MuteChn1Check                   1303\n#define MuteChn2Check                   1304\n#define MuteChn3Check                   1305\n#define MuteChn4Check                   1306\n#define MuteChn5Check                   1307\n#define MuteChn6Check                   1308\n#define MuteChn7Check                   1309\n#define MuteChn8Check                   1310\n#define MuteChn9Check                   1311\n#define MuteChn10Check                  1312\n#define MuteChn11Check                  1313\n#define MuteChn12Check                  1314\n#define MuteChn13Check                  1315\n#define MuteChn14Check                  1316\n#define MuteChn15Check                  1317\n#define MuteChn16Check                  1318\n#define MuteChn17Check                  1319\n#define MuteChn18Check                  1320\n#define MuteChn19Check                  1321\n#define MuteChn20Check                  1322\n#define MuteChn21Check                  1323\n#define MuteChn22Check                  1324\n#define MuteChn23Check                  1325\n#define MuteChn24Check                  1326\n#define ResetMuteCheck                  1327\n#define MuteChipCheck                   1328\n#define TrkTitleText                    2001\n#define TrkAuthorText                   2002\n#define GameNameText                    2003\n#define GameSysText                     2004\n#define GameDateText                    2005\n#define VGMFileText                     2006\n#define VGMCrtText                      2007\n#define VGMVerText                      2008\n#define VGMGainText                     2009\n#define VGMSizeText                     2010\n#define VGMLenText                      2011\n#define VGMNotesText                    2012\n#define ChipUseText                     2013\n#define LangEngCheck                    2014\n#define LangJapCheck                    2015\n#define ConfigPluginButton              2016\n#define BrwsrInfoButton                 2017\n#define EmuOptChipList                  3001\n#define EmuOptChipNumList               3002\n#define EmuCoreRadio1                   3003\n#define EmuCoreRadio2                   3004\n#define PanChn1Label                    3005\n#define PanChn2Label                    3006\n#define PanChn3Label                    3007\n#define PanChn4Label                    3008\n#define PanChn5Label                    3009\n#define PanChn6Label                    3010\n#define PanChn7Label                    3011\n#define PanChn8Label                    3012\n#define PanChn9Label                    3013\n#define PanChn10Label                   3014\n#define PanChn11Label                   3015\n#define PanChn12Label                   3016\n#define PanChn13Label                   3017\n#define PanChn14Label                   3018\n#define PanChn15Label                   3019\n#define PanChn1Slider                   3020\n#define PanChn2Slider                   3021\n#define PanChn3Slider                   3022\n#define PanChn4Slider                   3023\n#define PanChn5Slider                   3024\n#define PanChn6Slider                   3025\n#define PanChn7Slider                   3026\n#define PanChn8Slider                   3027\n#define PanChn9Slider                   3028\n#define PanChn10Slider                  3029\n#define PanChn11Slider                  3030\n#define PanChn12Slider                  3031\n#define PanChn13Slider                  3032\n#define PanChn14Slider                  3033\n#define PanChn15Slider                  3034\n\n// Next default values for new objects\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        212\n#define _APS_NEXT_COMMAND_VALUE         40001\n#define _APS_NEXT_CONTROL_VALUE         3038\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  }
]